Test the multipart GCM interface

The existing GCM test suite only exercises the one-shot API. Also test
the multipart interface: systematically run it on the same test data,
with the input (plaintext or ciphertext) split in two parts.

Given the current limitations of the GCM API, the associated data is
always passed in a single shot to mbedtls_gcm_starts(), and the first
part of the input is a nonzero multiple of 16.

Signed-off-by: Gilles Peskine <Gilles.Peskine@arm.com>
This commit is contained in:
Gilles Peskine 2021-04-13 13:02:03 +02:00
parent fce7061a51
commit 36dd93e745

View file

@ -1,5 +1,57 @@
/* BEGIN_HEADER */
#include "mbedtls/gcm.h"
/* Use the multipart interface to process the encrypted data in two parts
* and check that the output matches the expected output.
* The context must have been set up with the key. */
static int check_multipart( mbedtls_gcm_context *ctx,
int mode,
const data_t *iv,
const data_t *add,
const data_t *input,
const data_t *expected_output,
const data_t *tag,
size_t n1 )
{
int ok = 0;
uint8_t *output = NULL;
size_t n2 = input->len - n1;
/* Sanity checks on the test data */
TEST_ASSERT( n1 <= input->len );
TEST_EQUAL( input->len, expected_output->len );
TEST_EQUAL( 0, mbedtls_gcm_starts( ctx, mode,
iv->x, iv->len,
add->x, add->len ) );
/* 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, n1 );
TEST_EQUAL( 0, mbedtls_gcm_update( ctx, n1, input->x, output ) );
ASSERT_COMPARE( output, n1, expected_output->x, n1 );
mbedtls_free( output );
output = NULL;
ASSERT_ALLOC( output, n2 );
TEST_EQUAL( 0, mbedtls_gcm_update( ctx, n2, input->x + n1, output ) );
ASSERT_COMPARE( output, n2, expected_output->x + n1, n2 );
mbedtls_free( output );
output = NULL;
ASSERT_ALLOC( output, tag->len );
TEST_EQUAL( 0, mbedtls_gcm_finish( ctx, output, tag->len ) );
ASSERT_COMPARE( output, tag->len, tag->x, tag->len );
mbedtls_free( output );
output = NULL;
ok = 1;
exit:
mbedtls_free( output );
return( ok );
}
/* END_HEADER */
/* BEGIN_DEPENDENCIES
@ -43,6 +95,7 @@ void gcm_encrypt_and_tag( int cipher_id, data_t * key_str,
unsigned char tag_output[16];
mbedtls_gcm_context ctx;
size_t tag_len = tag_len_bits / 8;
size_t n1;
mbedtls_gcm_init( &ctx );
@ -55,10 +108,18 @@ void gcm_encrypt_and_tag( int cipher_id, data_t * key_str,
{
TEST_ASSERT( mbedtls_gcm_crypt_and_tag( &ctx, MBEDTLS_GCM_ENCRYPT, src_str->len, iv_str->x, iv_str->len, add_str->x, add_str->len, src_str->x, output, tag_len, tag_output ) == 0 );
TEST_ASSERT( mbedtls_test_hexcmp( output, dst->x,
src_str->len, dst->len ) == 0 );
TEST_ASSERT( mbedtls_test_hexcmp( tag_output, tag->x,
tag_len, tag->len ) == 0 );
ASSERT_COMPARE( output, src_str->len, dst->x, dst->len );
ASSERT_COMPARE( tag_output, tag_len, tag->x, tag->len );
for( n1 = 16; n1 < src_str->len; n1 += 16 )
{
mbedtls_test_set_step( n1 );
if( !check_multipart( &ctx, MBEDTLS_GCM_ENCRYPT,
iv_str, add_str, src_str,
dst, tag,
n1 ) )
goto exit;
}
}
exit:
@ -77,6 +138,7 @@ void gcm_decrypt_and_verify( int cipher_id, data_t * key_str,
mbedtls_gcm_context ctx;
int ret;
size_t tag_len = tag_len_bits / 8;
size_t n1;
mbedtls_gcm_init( &ctx );
@ -95,10 +157,17 @@ void gcm_decrypt_and_verify( int cipher_id, data_t * key_str,
else
{
TEST_ASSERT( ret == 0 );
ASSERT_COMPARE( output, src_str->len, pt_result->x, pt_result->len );
TEST_ASSERT( mbedtls_test_hexcmp( output, pt_result->x,
src_str->len,
pt_result->len ) == 0 );
for( n1 = 16; n1 < src_str->len; n1 += 16 )
{
mbedtls_test_set_step( n1 );
if( !check_multipart( &ctx, MBEDTLS_GCM_DECRYPT,
iv_str, add_str, src_str,
pt_result, tag_str,
n1 ) )
goto exit;
}
}
}