Split out CMAC and HMAC code into auxiliary functions

Split algorithm-specific code out of psa_mac_start. This makes the
function easier to read.

The behavior is mostly unchanged. In a few cases, errors before
setting a key trigger a context wipe where they didn't. This is a
marginal performance loss but only cases that are an error in caller
code.
This commit is contained in:
Gilles Peskine 2018-06-11 17:26:17 +02:00 committed by itayzafrir
parent 99bc649760
commit 7e454bc19f

View file

@ -925,6 +925,7 @@ static const mbedtls_cipher_info_t *mbedtls_cipher_info_from_psa(
alg &= ~PSA_ALG_BLOCK_CIPHER_PADDING_MASK;
}
switch( alg )
{
case PSA_ALG_STREAM_CIPHER:
mode = MBEDTLS_MODE_STREAM;
@ -1037,69 +1038,33 @@ psa_status_t psa_mac_abort( psa_mac_operation_t *operation )
return( PSA_SUCCESS );
}
psa_status_t psa_mac_start( psa_mac_operation_t *operation,
psa_key_slot_t key,
psa_algorithm_t alg )
static int psa_cmac_start( psa_mac_operation_t *operation,
size_t key_bits,
key_slot_t *slot,
const mbedtls_cipher_info_t *cipher_info )
{
int ret = 0;
psa_status_t status;
key_slot_t *slot;
psa_key_type_t key_type;
size_t key_bits;
size_t key_length;
uint8_t* key_ptr = NULL;
const mbedtls_cipher_info_t *cipher_info = NULL;
int ret;
operation->alg = 0;
operation->key_set = 0;
operation->iv_set = 0;
operation->iv_required = 1;
operation->has_input = 0;
operation->key_usage_sign = 0;
operation->key_usage_verify = 0;
status = psa_get_key_information( key, &key_type, &key_bits );
if( status != PSA_SUCCESS )
return( status );
slot = &global_data.key_slots[key];
if( slot->type == PSA_KEY_TYPE_NONE )
return( PSA_ERROR_EMPTY_SLOT );
key_ptr = slot->data.raw.data;
key_length = slot->data.raw.bytes;
if( ( slot->policy.usage & PSA_KEY_USAGE_SIGN ) != 0 )
operation->key_usage_sign = 1;
if( ( slot->policy.usage & PSA_KEY_USAGE_VERIFY ) != 0 )
operation->key_usage_verify = 1;
if( ! PSA_ALG_IS_HMAC( alg ) )
{
cipher_info = mbedtls_cipher_info_from_psa( alg, key_type, key_bits, NULL );
if( cipher_info == NULL )
return( PSA_ERROR_NOT_SUPPORTED );
operation->mac_size = cipher_info->block_size;
}
switch( alg )
{
#if defined(MBEDTLS_CMAC_C)
case PSA_ALG_CMAC:
operation->iv_required = 0;
mbedtls_cipher_init( &operation->ctx.cmac );
ret = mbedtls_cipher_setup( &operation->ctx.cmac, cipher_info );
if( ret != 0 )
break;
return( ret );
ret = mbedtls_cipher_cmac_starts( &operation->ctx.cmac,
slot->data.raw.data,
key_bits );
break;
#endif /* MBEDTLS_CMAC_C */
default:
#if defined(MBEDTLS_MD_C)
if( PSA_ALG_IS_HMAC( alg ) )
{
return( ret );
}
static int psa_hmac_start( psa_mac_operation_t *operation,
psa_key_type_t key_type,
size_t key_bits,
key_slot_t *slot,
psa_algorithm_t alg )
{
unsigned char sum[PSA_CRYPTO_MD_MAX_SIZE];
unsigned char ipad[PSA_CRYPTO_MD_BLOCK_SIZE];
unsigned char *opad;
@ -1109,6 +1074,9 @@ psa_status_t psa_mac_start( psa_mac_operation_t *operation,
PSA_HASH_BLOCK_SIZE( ( PSA_ALG_HMAC_HASH( alg ) ) );
unsigned int digest_size =
PSA_HASH_FINAL_SIZE( ( PSA_ALG_HMAC_HASH( alg ) ) );
uint8_t* key_ptr = slot->data.raw.data;
size_t key_length = slot->data.raw.bytes;
psa_status_t status;
if( ( block_size == 0 ) || ( digest_size == 0 ) )
return( PSA_ERROR_NOT_SUPPORTED );
@ -1122,18 +1090,18 @@ psa_status_t psa_mac_start( psa_mac_operation_t *operation,
status = psa_hash_start( &operation->ctx.hmac.hash_ctx,
PSA_ALG_HMAC_HASH( alg ) );
if( status != PSA_SUCCESS )
goto cleanup;
return( status );
if( key_bits / 8 > (size_t) block_size )
{
status = psa_hash_update( &operation->ctx.hmac.hash_ctx,
key_ptr, slot->data.raw.bytes);
if( status != PSA_SUCCESS )
goto cleanup;
return( status );
status = psa_hash_finish( &operation->ctx.hmac.hash_ctx,
sum, sum_size, &sum_size);
if( status != PSA_SUCCESS )
goto cleanup;
return( status );
key_length = sum_size;
key_ptr = sum;
@ -1153,30 +1121,87 @@ psa_status_t psa_mac_start( psa_mac_operation_t *operation,
status = psa_hash_start( &operation->ctx.hmac.hash_ctx,
PSA_ALG_HMAC_HASH( alg ) );
if( status != PSA_SUCCESS )
goto cleanup;
return( status );
status = psa_hash_update( &operation->ctx.hmac.hash_ctx, ipad,
block_size );
return( status );
}
psa_status_t psa_mac_start( psa_mac_operation_t *operation,
psa_key_slot_t key,
psa_algorithm_t alg )
{
psa_status_t status;
key_slot_t *slot;
psa_key_type_t key_type;
size_t key_bits;
const mbedtls_cipher_info_t *cipher_info;
operation->alg = 0;
operation->key_set = 0;
operation->iv_set = 0;
operation->iv_required = 1;
operation->has_input = 0;
operation->key_usage_sign = 0;
operation->key_usage_verify = 0;
status = psa_get_key_information( key, &key_type, &key_bits );
if( status != PSA_SUCCESS )
goto cleanup;
break;
return( status );
slot = &global_data.key_slots[key];
if( slot->type == PSA_KEY_TYPE_NONE )
return( PSA_ERROR_EMPTY_SLOT );
if( ( slot->policy.usage & PSA_KEY_USAGE_SIGN ) != 0 )
operation->key_usage_sign = 1;
if( ( slot->policy.usage & PSA_KEY_USAGE_VERIFY ) != 0 )
operation->key_usage_verify = 1;
if( ! PSA_ALG_IS_HMAC( alg ) )
{
cipher_info = mbedtls_cipher_info_from_psa( alg, key_type, key_bits, NULL );
if( cipher_info == NULL )
return( PSA_ERROR_NOT_SUPPORTED );
operation->mac_size = cipher_info->block_size;
}
switch( alg )
{
#if defined(MBEDTLS_CMAC_C)
case PSA_ALG_CMAC:
status = mbedtls_to_psa_error( psa_cmac_start( operation,
key_bits,
slot,
cipher_info ) );
break;
#endif /* MBEDTLS_CMAC_C */
default:
#if defined(MBEDTLS_MD_C)
if( PSA_ALG_IS_HMAC( alg ) )
status = psa_hmac_start( operation,
key_type, key_bits, slot,
alg );
else
#endif /* MBEDTLS_MD_C */
return( PSA_ERROR_NOT_SUPPORTED );
}
cleanup:
/* If we reach this point, then the algorithm-specific part of the
* context has at least been initialized, and may contain data that
* needs to be wiped on error. */
operation->alg = alg;
if( ret != 0 )
* context may contain data that needs to be wiped on error. */
if( status != PSA_SUCCESS )
{
psa_mac_abort(operation);
if ( ret != 0 )
status = mbedtls_to_psa_error(ret);
}
else
{
operation->alg = alg;
operation->key_set = 1;
}
return( status );
}
psa_status_t psa_mac_update( psa_mac_operation_t *operation,