295fc13ef3
The GCM interface now has separate functions to start the operation and to pass the associated data. This is in preparation for allowing the associated data to be passed in chunks with repeatated calls to mbedtls_gcm_update_ad(). Signed-off-by: Gilles Peskine <Gilles.Peskine@arm.com>
361 lines
13 KiB
Text
361 lines
13 KiB
Text
/* 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;
|
|
size_t olen;
|
|
|
|
/* 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 ) );
|
|
TEST_EQUAL( 0, mbedtls_gcm_update_ad( ctx, 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 );
|
|
olen = 0xdeadbeef;
|
|
TEST_EQUAL( 0, mbedtls_gcm_update( ctx, input->x, n1, output, n1, &olen ) );
|
|
TEST_EQUAL( n1, olen );
|
|
ASSERT_COMPARE( output, olen, expected_output->x, n1 );
|
|
mbedtls_free( output );
|
|
output = NULL;
|
|
|
|
ASSERT_ALLOC( output, n2 );
|
|
olen = 0xdeadbeef;
|
|
TEST_EQUAL( 0, mbedtls_gcm_update( ctx, input->x + n1, n2, output, n2, &olen ) );
|
|
TEST_EQUAL( n2, olen );
|
|
ASSERT_COMPARE( output, olen, expected_output->x + n1, n2 );
|
|
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 );
|
|
mbedtls_free( output );
|
|
output = NULL;
|
|
|
|
ok = 1;
|
|
exit:
|
|
mbedtls_free( output );
|
|
return( ok );
|
|
}
|
|
|
|
/* END_HEADER */
|
|
|
|
/* BEGIN_DEPENDENCIES
|
|
* depends_on:MBEDTLS_GCM_C
|
|
* END_DEPENDENCIES
|
|
*/
|
|
|
|
/* BEGIN_CASE */
|
|
void gcm_bad_parameters( int cipher_id, int direction,
|
|
data_t *key_str, data_t *src_str,
|
|
data_t *iv_str, data_t *add_str,
|
|
int tag_len_bits, int gcm_result )
|
|
{
|
|
unsigned char output[128];
|
|
unsigned char tag_output[16];
|
|
mbedtls_gcm_context ctx;
|
|
size_t tag_len = tag_len_bits / 8;
|
|
|
|
mbedtls_gcm_init( &ctx );
|
|
|
|
memset( output, 0x00, sizeof( output ) );
|
|
memset( tag_output, 0x00, sizeof( tag_output ) );
|
|
|
|
TEST_ASSERT( mbedtls_gcm_setkey( &ctx, cipher_id, key_str->x, key_str->len * 8 ) == 0 );
|
|
TEST_ASSERT( mbedtls_gcm_crypt_and_tag( &ctx, direction, src_str->len, iv_str->x, iv_str->len,
|
|
add_str->x, add_str->len, src_str->x, output, tag_len, tag_output ) == gcm_result );
|
|
|
|
exit:
|
|
mbedtls_gcm_free( &ctx );
|
|
}
|
|
/* END_CASE */
|
|
|
|
/* BEGIN_CASE */
|
|
void gcm_encrypt_and_tag( int cipher_id, data_t * key_str,
|
|
data_t * src_str, data_t * iv_str,
|
|
data_t * add_str, data_t * dst,
|
|
int tag_len_bits, data_t * tag,
|
|
int init_result )
|
|
{
|
|
unsigned char output[128];
|
|
unsigned char tag_output[16];
|
|
mbedtls_gcm_context ctx;
|
|
size_t tag_len = tag_len_bits / 8;
|
|
size_t n1;
|
|
|
|
mbedtls_gcm_init( &ctx );
|
|
|
|
memset(output, 0x00, 128);
|
|
memset(tag_output, 0x00, 16);
|
|
|
|
|
|
TEST_ASSERT( mbedtls_gcm_setkey( &ctx, cipher_id, key_str->x, key_str->len * 8 ) == init_result );
|
|
if( init_result == 0 )
|
|
{
|
|
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 );
|
|
|
|
ASSERT_COMPARE( output, src_str->len, dst->x, dst->len );
|
|
ASSERT_COMPARE( tag_output, tag_len, tag->x, tag->len );
|
|
|
|
for( n1 = 0; n1 <= src_str->len; n1 += 1 )
|
|
{
|
|
mbedtls_test_set_step( n1 );
|
|
if( !check_multipart( &ctx, MBEDTLS_GCM_ENCRYPT,
|
|
iv_str, add_str, src_str,
|
|
dst, tag,
|
|
n1 ) )
|
|
goto exit;
|
|
}
|
|
}
|
|
|
|
exit:
|
|
mbedtls_gcm_free( &ctx );
|
|
}
|
|
/* END_CASE */
|
|
|
|
/* BEGIN_CASE */
|
|
void gcm_decrypt_and_verify( int cipher_id, data_t * key_str,
|
|
data_t * src_str, data_t * iv_str,
|
|
data_t * add_str, int tag_len_bits,
|
|
data_t * tag_str, char * result,
|
|
data_t * pt_result, int init_result )
|
|
{
|
|
unsigned char output[128];
|
|
mbedtls_gcm_context ctx;
|
|
int ret;
|
|
size_t tag_len = tag_len_bits / 8;
|
|
size_t n1;
|
|
|
|
mbedtls_gcm_init( &ctx );
|
|
|
|
memset(output, 0x00, 128);
|
|
|
|
|
|
TEST_ASSERT( mbedtls_gcm_setkey( &ctx, cipher_id, key_str->x, key_str->len * 8 ) == init_result );
|
|
if( init_result == 0 )
|
|
{
|
|
ret = mbedtls_gcm_auth_decrypt( &ctx, src_str->len, iv_str->x, iv_str->len, add_str->x, add_str->len, tag_str->x, tag_len, src_str->x, output );
|
|
|
|
if( strcmp( "FAIL", result ) == 0 )
|
|
{
|
|
TEST_ASSERT( ret == MBEDTLS_ERR_GCM_AUTH_FAILED );
|
|
}
|
|
else
|
|
{
|
|
TEST_ASSERT( ret == 0 );
|
|
ASSERT_COMPARE( output, src_str->len, pt_result->x, pt_result->len );
|
|
|
|
for( n1 = 0; n1 <= src_str->len; n1 += 1 )
|
|
{
|
|
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;
|
|
}
|
|
}
|
|
}
|
|
|
|
exit:
|
|
mbedtls_gcm_free( &ctx );
|
|
}
|
|
/* END_CASE */
|
|
|
|
/* BEGIN_CASE depends_on:MBEDTLS_CHECK_PARAMS:!MBEDTLS_PARAM_FAILED_ALT */
|
|
void gcm_invalid_param( )
|
|
{
|
|
mbedtls_gcm_context ctx;
|
|
unsigned char valid_buffer[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06 };
|
|
mbedtls_cipher_id_t valid_cipher = MBEDTLS_CIPHER_ID_AES;
|
|
int valid_mode = MBEDTLS_GCM_ENCRYPT;
|
|
int valid_len = sizeof(valid_buffer);
|
|
int valid_bitlen = 128, invalid_bitlen = 1;
|
|
size_t olen;
|
|
|
|
mbedtls_gcm_init( &ctx );
|
|
|
|
/* mbedtls_gcm_init() */
|
|
TEST_INVALID_PARAM( mbedtls_gcm_init( NULL ) );
|
|
|
|
/* mbedtls_gcm_setkey */
|
|
TEST_INVALID_PARAM_RET(
|
|
MBEDTLS_ERR_GCM_BAD_INPUT,
|
|
mbedtls_gcm_setkey( NULL, valid_cipher, valid_buffer, valid_bitlen ) );
|
|
TEST_INVALID_PARAM_RET(
|
|
MBEDTLS_ERR_GCM_BAD_INPUT,
|
|
mbedtls_gcm_setkey( &ctx, valid_cipher, NULL, valid_bitlen ) );
|
|
TEST_INVALID_PARAM_RET(
|
|
MBEDTLS_ERR_GCM_BAD_INPUT,
|
|
mbedtls_gcm_setkey( &ctx, valid_cipher, valid_buffer, invalid_bitlen ) );
|
|
|
|
/* mbedtls_gcm_crypt_and_tag() */
|
|
TEST_INVALID_PARAM_RET(
|
|
MBEDTLS_ERR_GCM_BAD_INPUT,
|
|
mbedtls_gcm_crypt_and_tag( NULL, valid_mode, valid_len,
|
|
valid_buffer, valid_len,
|
|
valid_buffer, valid_len,
|
|
valid_buffer, valid_buffer,
|
|
valid_len, valid_buffer ) );
|
|
TEST_INVALID_PARAM_RET(
|
|
MBEDTLS_ERR_GCM_BAD_INPUT,
|
|
mbedtls_gcm_crypt_and_tag( &ctx, valid_mode, valid_len,
|
|
NULL, valid_len,
|
|
valid_buffer, valid_len,
|
|
valid_buffer, valid_buffer,
|
|
valid_len, valid_buffer ) );
|
|
TEST_INVALID_PARAM_RET(
|
|
MBEDTLS_ERR_GCM_BAD_INPUT,
|
|
mbedtls_gcm_crypt_and_tag( &ctx, valid_mode, valid_len,
|
|
valid_buffer, valid_len,
|
|
NULL, valid_len,
|
|
valid_buffer, valid_buffer,
|
|
valid_len, valid_buffer ) );
|
|
TEST_INVALID_PARAM_RET(
|
|
MBEDTLS_ERR_GCM_BAD_INPUT,
|
|
mbedtls_gcm_crypt_and_tag( &ctx, valid_mode, valid_len,
|
|
valid_buffer, valid_len,
|
|
valid_buffer, valid_len,
|
|
NULL, valid_buffer,
|
|
valid_len, valid_buffer ) );
|
|
TEST_INVALID_PARAM_RET(
|
|
MBEDTLS_ERR_GCM_BAD_INPUT,
|
|
mbedtls_gcm_crypt_and_tag( &ctx, valid_mode, valid_len,
|
|
valid_buffer, valid_len,
|
|
valid_buffer, valid_len,
|
|
valid_buffer, NULL,
|
|
valid_len, valid_buffer ) );
|
|
TEST_INVALID_PARAM_RET(
|
|
MBEDTLS_ERR_GCM_BAD_INPUT,
|
|
mbedtls_gcm_crypt_and_tag( &ctx, valid_mode, valid_len,
|
|
valid_buffer, valid_len,
|
|
valid_buffer, valid_len,
|
|
valid_buffer, valid_buffer,
|
|
valid_len, NULL ) );
|
|
|
|
/* mbedtls_gcm_auth_decrypt() */
|
|
TEST_INVALID_PARAM_RET(
|
|
MBEDTLS_ERR_GCM_BAD_INPUT,
|
|
mbedtls_gcm_auth_decrypt( NULL, valid_len,
|
|
valid_buffer, valid_len,
|
|
valid_buffer, valid_len,
|
|
valid_buffer, valid_len,
|
|
valid_buffer, valid_buffer) );
|
|
TEST_INVALID_PARAM_RET(
|
|
MBEDTLS_ERR_GCM_BAD_INPUT,
|
|
mbedtls_gcm_auth_decrypt( &ctx, valid_len,
|
|
NULL, valid_len,
|
|
valid_buffer, valid_len,
|
|
valid_buffer, valid_len,
|
|
valid_buffer, valid_buffer) );
|
|
TEST_INVALID_PARAM_RET(
|
|
MBEDTLS_ERR_GCM_BAD_INPUT,
|
|
mbedtls_gcm_auth_decrypt( &ctx, valid_len,
|
|
valid_buffer, valid_len,
|
|
NULL, valid_len,
|
|
valid_buffer, valid_len,
|
|
valid_buffer, valid_buffer) );
|
|
TEST_INVALID_PARAM_RET(
|
|
MBEDTLS_ERR_GCM_BAD_INPUT,
|
|
mbedtls_gcm_auth_decrypt( &ctx, valid_len,
|
|
valid_buffer, valid_len,
|
|
valid_buffer, valid_len,
|
|
NULL, valid_len,
|
|
valid_buffer, valid_buffer) );
|
|
TEST_INVALID_PARAM_RET(
|
|
MBEDTLS_ERR_GCM_BAD_INPUT,
|
|
mbedtls_gcm_auth_decrypt( &ctx, valid_len,
|
|
valid_buffer, valid_len,
|
|
valid_buffer, valid_len,
|
|
valid_buffer, valid_len,
|
|
NULL, valid_buffer) );
|
|
TEST_INVALID_PARAM_RET(
|
|
MBEDTLS_ERR_GCM_BAD_INPUT,
|
|
mbedtls_gcm_auth_decrypt( &ctx, valid_len,
|
|
valid_buffer, valid_len,
|
|
valid_buffer, valid_len,
|
|
valid_buffer, valid_len,
|
|
valid_buffer, NULL) );
|
|
|
|
/* mbedtls_gcm_starts() */
|
|
TEST_INVALID_PARAM_RET(
|
|
MBEDTLS_ERR_GCM_BAD_INPUT,
|
|
mbedtls_gcm_starts( NULL, valid_mode,
|
|
valid_buffer, valid_len ) );
|
|
|
|
TEST_INVALID_PARAM_RET(
|
|
MBEDTLS_ERR_GCM_BAD_INPUT,
|
|
mbedtls_gcm_starts( &ctx, valid_mode,
|
|
NULL, valid_len ) );
|
|
|
|
/* mbedtls_gcm_update_ad() */
|
|
TEST_INVALID_PARAM_RET(
|
|
MBEDTLS_ERR_GCM_BAD_INPUT,
|
|
mbedtls_gcm_update_ad( &ctx,
|
|
NULL, valid_len ) );
|
|
|
|
/* mbedtls_gcm_update() */
|
|
TEST_INVALID_PARAM_RET(
|
|
MBEDTLS_ERR_GCM_BAD_INPUT,
|
|
mbedtls_gcm_update( NULL, valid_buffer, valid_len,
|
|
valid_buffer, valid_len, &olen ) );
|
|
TEST_INVALID_PARAM_RET(
|
|
MBEDTLS_ERR_GCM_BAD_INPUT,
|
|
mbedtls_gcm_update( &ctx, NULL, valid_len,
|
|
valid_buffer, valid_len, &olen ) );
|
|
TEST_INVALID_PARAM_RET(
|
|
MBEDTLS_ERR_GCM_BAD_INPUT,
|
|
mbedtls_gcm_update( &ctx, valid_buffer, valid_len,
|
|
NULL, valid_len, &olen ) );
|
|
TEST_INVALID_PARAM_RET(
|
|
MBEDTLS_ERR_GCM_BAD_INPUT,
|
|
mbedtls_gcm_update( &ctx, valid_buffer, valid_len,
|
|
valid_buffer, valid_len, NULL ) );
|
|
|
|
/* mbedtls_gcm_finish() */
|
|
TEST_INVALID_PARAM_RET(
|
|
MBEDTLS_ERR_GCM_BAD_INPUT,
|
|
mbedtls_gcm_finish( NULL, NULL, 0, valid_buffer, valid_len ) );
|
|
TEST_INVALID_PARAM_RET(
|
|
MBEDTLS_ERR_GCM_BAD_INPUT,
|
|
mbedtls_gcm_finish( &ctx, NULL, 0, NULL, valid_len ) );
|
|
|
|
exit:
|
|
mbedtls_gcm_free( &ctx );
|
|
}
|
|
/* END_CASE */
|
|
|
|
/* BEGIN_CASE */
|
|
void gcm_valid_param( )
|
|
{
|
|
TEST_VALID_PARAM( mbedtls_gcm_free( NULL ) );
|
|
exit:
|
|
return;
|
|
}
|
|
/* END_CASE */
|
|
|
|
/* BEGIN_CASE depends_on:MBEDTLS_SELF_TEST */
|
|
void gcm_selftest( )
|
|
{
|
|
TEST_ASSERT( mbedtls_gcm_self_test( 1 ) == 0 );
|
|
}
|
|
/* END_CASE */
|