Add customized test functions for GCM update and update_ad.
New functions are used to cover corner cases:
* authentication data is fed to gcm with 0, 1 or 2 calls to gcm_update
* ciphertext is fed to gcm with 0, 1 or 2 calls to gcm_update_ad
AES-GCM NIST test vectors downloaded at 16.06.2021 from:
csrc.nist.gov/groups/STM/cavp/documents/mac/gcmtestvectors.zip
Signed-off-by: Mateusz Starzyk <mateusz.starzyk@mobica.com>
diff --git a/tests/suites/test_suite_gcm.function b/tests/suites/test_suite_gcm.function
index fc01b40..86f7fb9 100644
--- a/tests/suites/test_suite_gcm.function
+++ b/tests/suites/test_suite_gcm.function
@@ -61,6 +61,77 @@
return( ok );
}
+static void check_cipher_with_empty_ad( mbedtls_gcm_context *ctx,
+ int mode,
+ const data_t *iv,
+ const data_t *input,
+ const data_t *expected_output,
+ const data_t *tag,
+ size_t ad_update_count)
+{
+ size_t n;
+ uint8_t *output = NULL;
+ size_t olen;
+
+ /* Sanity checks on the test data */
+ TEST_EQUAL( input->len, expected_output->len );
+
+ TEST_EQUAL( 0, mbedtls_gcm_starts( ctx, mode,
+ iv->x, iv->len ) );
+
+ for( n = 0; n < ad_update_count; n += 1 )
+ {
+ TEST_EQUAL( 0, mbedtls_gcm_update_ad( ctx, NULL, 0 ) );
+ }
+
+ /* Allocate a tight buffer for each update call. This way, if the function
+ * tries to write beyond the advertised required buffer size, this will
+ * count as an overflow for memory sanitizers and static checkers. */
+ ASSERT_ALLOC( output, input->len );
+ olen = 0xdeadbeef;
+ TEST_EQUAL( 0, mbedtls_gcm_update( ctx, input->x, input->len, output, input->len, &olen ) );
+ TEST_EQUAL( input->len, olen );
+ ASSERT_COMPARE( output, olen, expected_output->x, input->len );
+ mbedtls_free( output );
+ output = NULL;
+
+ ASSERT_ALLOC( output, tag->len );
+ TEST_EQUAL( 0, mbedtls_gcm_finish( ctx, NULL, 0, output, tag->len ) );
+ ASSERT_COMPARE( output, tag->len, tag->x, tag->len );
+
+exit:
+ mbedtls_free( output );
+}
+
+static void check_empty_cipher_with_ad( mbedtls_gcm_context *ctx,
+ int mode,
+ const data_t *iv,
+ const data_t *add,
+ const data_t *tag,
+ size_t cipher_update_count)
+{
+ size_t olen;
+ size_t n;
+ uint8_t* output_tag = NULL;
+
+ TEST_EQUAL( 0, mbedtls_gcm_starts( ctx, mode, iv->x, iv->len ) );
+ TEST_EQUAL( 0, mbedtls_gcm_update_ad( ctx, add->x, add->len ) );
+
+ for( n = 0; n < cipher_update_count; n += 1 )
+ {
+ olen = 0xdeadbeef;
+ TEST_EQUAL( 0, mbedtls_gcm_update( ctx, NULL, 0, NULL, 0, &olen ) );
+ TEST_EQUAL( 0, olen );
+ }
+
+ ASSERT_ALLOC( output_tag, tag->len );
+ TEST_EQUAL( 0, mbedtls_gcm_finish( ctx, NULL, 0, output_tag, tag->len ) );
+ ASSERT_COMPARE( output_tag, tag->len, tag->x, tag->len );
+
+exit:
+ mbedtls_free( output_tag );
+}
+
/* END_HEADER */
/* BEGIN_DEPENDENCIES
@@ -196,6 +267,110 @@
}
/* END_CASE */
+/* BEGIN_CASE */
+void gcm_decrypt_and_verify_empty_cipher( int cipher_id,
+ data_t * key_str,
+ data_t * iv_str,
+ data_t * add_str,
+ data_t * tag_str,
+ int cipher_update_calls,
+ int init_result )
+{
+ mbedtls_gcm_context ctx;
+
+ mbedtls_gcm_init( &ctx );
+
+ TEST_ASSERT( mbedtls_gcm_setkey( &ctx, cipher_id, key_str->x, key_str->len * 8 ) == init_result );
+ if( init_result == 0 )
+ {
+ check_empty_cipher_with_ad( &ctx, MBEDTLS_GCM_DECRYPT,
+ iv_str, add_str, tag_str,
+ cipher_update_calls );
+ }
+
+ mbedtls_gcm_free( &ctx );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void gcm_decrypt_and_verify_empty_ad( int cipher_id,
+ data_t * key_str,
+ data_t * iv_str,
+ data_t * src_str,
+ data_t * tag_str,
+ data_t * pt_result,
+ int ad_update_calls,
+ int init_result )
+{
+ mbedtls_gcm_context ctx;
+
+ mbedtls_gcm_init( &ctx );
+
+ TEST_ASSERT( mbedtls_gcm_setkey( &ctx, cipher_id, key_str->x, key_str->len * 8 ) == init_result );
+ if( init_result == 0 )
+ {
+ check_cipher_with_empty_ad( &ctx, MBEDTLS_GCM_DECRYPT,
+ iv_str, src_str, pt_result, tag_str,
+ ad_update_calls );
+ }
+
+ mbedtls_gcm_free( &ctx );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void gcm_encrypt_and_tag_empty_cipher( int cipher_id,
+ data_t * key_str,
+ data_t * iv_str,
+ data_t * add_str,
+ data_t * tag_str,
+ int cipher_update_calls,
+ int init_result )
+{
+ mbedtls_gcm_context ctx;
+
+ mbedtls_gcm_init( &ctx );
+
+ TEST_ASSERT( mbedtls_gcm_setkey( &ctx, cipher_id, key_str->x, key_str->len * 8 ) == init_result );
+ if( init_result == 0 )
+ {
+ check_empty_cipher_with_ad( &ctx, MBEDTLS_GCM_ENCRYPT,
+ iv_str, add_str, tag_str,
+ cipher_update_calls );
+ }
+
+exit:
+ mbedtls_gcm_free( &ctx );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void gcm_encrypt_and_tag_empty_ad( int cipher_id,
+ data_t * key_str,
+ data_t * iv_str,
+ data_t * src_str,
+ data_t * dst,
+ data_t * tag_str,
+ int ad_update_calls,
+ int init_result )
+{
+ mbedtls_gcm_context ctx;
+
+ mbedtls_gcm_init( &ctx );
+
+ TEST_ASSERT( mbedtls_gcm_setkey( &ctx, cipher_id, key_str->x, key_str->len * 8 ) == init_result );
+ if( init_result == 0 )
+ {
+ check_cipher_with_empty_ad( &ctx, MBEDTLS_GCM_ENCRYPT,
+ iv_str, src_str, dst, tag_str,
+ ad_update_calls );
+ }
+
+exit:
+ mbedtls_gcm_free( &ctx );
+}
+/* END_CASE */
+
/* BEGIN_CASE depends_on:NOT_DEFINED */
void gcm_invalid_param( )
{