Isolate HMAC code into its own functions
Create internal functions for HMAC operations. This prepares for two things: separating crypto-sensitive code from argument decoding and validation, and using HMAC for other purposes than a MAC inside the library (e.g. HMAC_DRBG, HKDF). No intended observable behavior change in this commit.
This commit is contained in:
parent
94e44540ff
commit
01126fae7f
@ -1332,6 +1332,14 @@ static psa_status_t psa_mac_init( psa_mac_operation_t *operation,
|
|||||||
return( status );
|
return( status );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(MBEDTLS_MD_C)
|
||||||
|
static psa_status_t psa_hmac_abort_internal( psa_hmac_internal_data *hmac )
|
||||||
|
{
|
||||||
|
mbedtls_zeroize( hmac->opad, sizeof( hmac->opad ) );
|
||||||
|
return( psa_hash_abort( &hmac->hash_ctx ) );
|
||||||
|
}
|
||||||
|
#endif /* MBEDTLS_MD_C */
|
||||||
|
|
||||||
psa_status_t psa_mac_abort( psa_mac_operation_t *operation )
|
psa_status_t psa_mac_abort( psa_mac_operation_t *operation )
|
||||||
{
|
{
|
||||||
if( operation->alg == 0 )
|
if( operation->alg == 0 )
|
||||||
@ -1352,12 +1360,7 @@ psa_status_t psa_mac_abort( psa_mac_operation_t *operation )
|
|||||||
#if defined(MBEDTLS_MD_C)
|
#if defined(MBEDTLS_MD_C)
|
||||||
if( PSA_ALG_IS_HMAC( operation->alg ) )
|
if( PSA_ALG_IS_HMAC( operation->alg ) )
|
||||||
{
|
{
|
||||||
size_t block_size =
|
psa_hmac_abort_internal( &operation->ctx.hmac );
|
||||||
psa_get_hash_block_size( PSA_ALG_HMAC_HASH( operation->alg ) );
|
|
||||||
if( block_size == 0 )
|
|
||||||
goto bad_state;
|
|
||||||
psa_hash_abort( &operation->ctx.hmac.hash_ctx );
|
|
||||||
mbedtls_zeroize( operation->ctx.hmac.opad, block_size );
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
#endif /* MBEDTLS_MD_C */
|
#endif /* MBEDTLS_MD_C */
|
||||||
@ -1407,43 +1410,33 @@ static int psa_cmac_setup( psa_mac_operation_t *operation,
|
|||||||
#endif /* MBEDTLS_CMAC_C */
|
#endif /* MBEDTLS_CMAC_C */
|
||||||
|
|
||||||
#if defined(MBEDTLS_MD_C)
|
#if defined(MBEDTLS_MD_C)
|
||||||
static int psa_hmac_setup( psa_mac_operation_t *operation,
|
static psa_status_t psa_hmac_setup_internal( psa_hmac_internal_data *hmac,
|
||||||
psa_key_type_t key_type,
|
const uint8_t *key,
|
||||||
key_slot_t *slot,
|
size_t key_length,
|
||||||
psa_algorithm_t alg )
|
psa_algorithm_t hash_alg )
|
||||||
{
|
{
|
||||||
unsigned char ipad[PSA_HMAC_MAX_HASH_BLOCK_SIZE];
|
unsigned char ipad[PSA_HMAC_MAX_HASH_BLOCK_SIZE];
|
||||||
unsigned char *opad = operation->ctx.hmac.opad;
|
|
||||||
size_t i;
|
size_t i;
|
||||||
size_t block_size =
|
size_t block_size = psa_get_hash_block_size( hash_alg );
|
||||||
psa_get_hash_block_size( PSA_ALG_HMAC_HASH( alg ) );
|
|
||||||
unsigned int digest_size =
|
|
||||||
PSA_HASH_SIZE( PSA_ALG_HMAC_HASH( alg ) );
|
|
||||||
size_t key_length = slot->data.raw.bytes;
|
|
||||||
psa_status_t status;
|
psa_status_t status;
|
||||||
|
|
||||||
if( block_size == 0 || digest_size == 0 )
|
if( block_size == 0 )
|
||||||
return( PSA_ERROR_NOT_SUPPORTED );
|
return( PSA_ERROR_NOT_SUPPORTED );
|
||||||
|
|
||||||
if( key_type != PSA_KEY_TYPE_HMAC )
|
|
||||||
return( PSA_ERROR_INVALID_ARGUMENT );
|
|
||||||
|
|
||||||
operation->mac_size = digest_size;
|
|
||||||
|
|
||||||
/* The hash was started earlier in psa_mac_init. */
|
/* The hash was started earlier in psa_mac_init. */
|
||||||
if( key_length > block_size )
|
if( key_length > block_size )
|
||||||
{
|
{
|
||||||
status = psa_hash_update( &operation->ctx.hmac.hash_ctx,
|
status = psa_hash_update( &hmac->hash_ctx, key, key_length );
|
||||||
slot->data.raw.data, slot->data.raw.bytes );
|
|
||||||
if( status != PSA_SUCCESS )
|
if( status != PSA_SUCCESS )
|
||||||
return( status );
|
return( status );
|
||||||
status = psa_hash_finish( &operation->ctx.hmac.hash_ctx,
|
status = psa_hash_finish( &hmac->hash_ctx,
|
||||||
ipad, sizeof( ipad ), &key_length );
|
ipad, sizeof( ipad ), &key_length );
|
||||||
if( status != PSA_SUCCESS )
|
if( status != PSA_SUCCESS )
|
||||||
return( status );
|
return( status );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
memcpy( ipad, slot->data.raw.data, slot->data.raw.bytes );
|
memcpy( ipad, key, key_length );
|
||||||
|
|
||||||
/* ipad contains the key followed by garbage. Xor and fill with 0x36
|
/* ipad contains the key followed by garbage. Xor and fill with 0x36
|
||||||
* to create the ipad value. */
|
* to create the ipad value. */
|
||||||
@ -1454,22 +1447,17 @@ static int psa_hmac_setup( psa_mac_operation_t *operation,
|
|||||||
/* Copy the key material from ipad to opad, flipping the requisite bits,
|
/* Copy the key material from ipad to opad, flipping the requisite bits,
|
||||||
* and filling the rest of opad with the requisite constant. */
|
* and filling the rest of opad with the requisite constant. */
|
||||||
for( i = 0; i < key_length; i++ )
|
for( i = 0; i < key_length; i++ )
|
||||||
opad[i] = ipad[i] ^ 0x36 ^ 0x5C;
|
hmac->opad[i] = ipad[i] ^ 0x36 ^ 0x5C;
|
||||||
memset( opad + key_length, 0x5C, block_size - key_length );
|
memset( hmac->opad + key_length, 0x5C, block_size - key_length );
|
||||||
|
|
||||||
status = psa_hash_setup( &operation->ctx.hmac.hash_ctx,
|
status = psa_hash_setup( &hmac->hash_ctx, hash_alg );
|
||||||
PSA_ALG_HMAC_HASH( alg ) );
|
|
||||||
if( status != PSA_SUCCESS )
|
if( status != PSA_SUCCESS )
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
status = psa_hash_update( &operation->ctx.hmac.hash_ctx, ipad,
|
status = psa_hash_update( &hmac->hash_ctx, ipad, block_size );
|
||||||
block_size );
|
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
mbedtls_zeroize( ipad, key_length );
|
mbedtls_zeroize( ipad, key_length );
|
||||||
/* opad is in the context. It needs to stay in memory if this function
|
|
||||||
* succeeds, and it will be wiped by psa_mac_abort() called from
|
|
||||||
* psa_mac_setup in the error case. */
|
|
||||||
|
|
||||||
return( status );
|
return( status );
|
||||||
}
|
}
|
||||||
@ -1517,7 +1505,22 @@ static psa_status_t psa_mac_setup( psa_mac_operation_t *operation,
|
|||||||
#if defined(MBEDTLS_MD_C)
|
#if defined(MBEDTLS_MD_C)
|
||||||
if( PSA_ALG_IS_HMAC( alg ) )
|
if( PSA_ALG_IS_HMAC( alg ) )
|
||||||
{
|
{
|
||||||
status = psa_hmac_setup( operation, slot->type, slot, alg );
|
psa_algorithm_t hash_alg = PSA_ALG_HMAC_HASH( alg );
|
||||||
|
if( hash_alg == 0 )
|
||||||
|
{
|
||||||
|
status = PSA_ERROR_NOT_SUPPORTED;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
if( slot->type != PSA_KEY_TYPE_HMAC )
|
||||||
|
{
|
||||||
|
status = PSA_ERROR_INVALID_ARGUMENT;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
status = psa_hmac_setup_internal( &operation->ctx.hmac,
|
||||||
|
slot->data.raw.data,
|
||||||
|
slot->data.raw.bytes,
|
||||||
|
hash_alg );
|
||||||
|
operation->mac_size = PSA_HASH_SIZE( hash_alg );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
#endif /* MBEDTLS_MD_C */
|
#endif /* MBEDTLS_MD_C */
|
||||||
@ -1591,12 +1594,49 @@ cleanup:
|
|||||||
return( status );
|
return( status );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(MBEDTLS_MD_C)
|
||||||
|
static psa_status_t psa_hmac_finish_internal( psa_hmac_internal_data *hmac,
|
||||||
|
uint8_t *mac,
|
||||||
|
size_t mac_size )
|
||||||
|
{
|
||||||
|
unsigned char tmp[MBEDTLS_MD_MAX_SIZE];
|
||||||
|
psa_algorithm_t hash_alg = hmac->hash_ctx.alg;
|
||||||
|
size_t hash_size = 0;
|
||||||
|
size_t block_size = psa_get_hash_block_size( hash_alg );
|
||||||
|
psa_status_t status;
|
||||||
|
|
||||||
|
if( block_size == 0 )
|
||||||
|
return( PSA_ERROR_NOT_SUPPORTED );
|
||||||
|
|
||||||
|
status = psa_hash_finish( &hmac->hash_ctx, tmp, sizeof( tmp ), &hash_size );
|
||||||
|
if( status != PSA_SUCCESS )
|
||||||
|
return( status );
|
||||||
|
/* From here on, tmp needs to be wiped. */
|
||||||
|
|
||||||
|
status = psa_hash_setup( &hmac->hash_ctx, hash_alg );
|
||||||
|
if( status != PSA_SUCCESS )
|
||||||
|
goto exit;
|
||||||
|
|
||||||
|
status = psa_hash_update( &hmac->hash_ctx, hmac->opad, block_size );
|
||||||
|
if( status != PSA_SUCCESS )
|
||||||
|
goto exit;
|
||||||
|
|
||||||
|
status = psa_hash_update( &hmac->hash_ctx, tmp, hash_size );
|
||||||
|
if( status != PSA_SUCCESS )
|
||||||
|
goto exit;
|
||||||
|
|
||||||
|
status = psa_hash_finish( &hmac->hash_ctx, mac, mac_size, &hash_size );
|
||||||
|
|
||||||
|
exit:
|
||||||
|
mbedtls_zeroize( tmp, hash_size );
|
||||||
|
return( status );
|
||||||
|
}
|
||||||
|
#endif /* MBEDTLS_MD_C */
|
||||||
|
|
||||||
static psa_status_t psa_mac_finish_internal( psa_mac_operation_t *operation,
|
static psa_status_t psa_mac_finish_internal( psa_mac_operation_t *operation,
|
||||||
uint8_t *mac,
|
uint8_t *mac,
|
||||||
size_t mac_size )
|
size_t mac_size )
|
||||||
{
|
{
|
||||||
psa_status_t status;
|
|
||||||
|
|
||||||
if( ! operation->key_set )
|
if( ! operation->key_set )
|
||||||
return( PSA_ERROR_BAD_STATE );
|
return( PSA_ERROR_BAD_STATE );
|
||||||
if( operation->iv_required && ! operation->iv_set )
|
if( operation->iv_required && ! operation->iv_set )
|
||||||
@ -1616,41 +1656,8 @@ static psa_status_t psa_mac_finish_internal( psa_mac_operation_t *operation,
|
|||||||
#if defined(MBEDTLS_MD_C)
|
#if defined(MBEDTLS_MD_C)
|
||||||
if( PSA_ALG_IS_HMAC( operation->alg ) )
|
if( PSA_ALG_IS_HMAC( operation->alg ) )
|
||||||
{
|
{
|
||||||
unsigned char tmp[MBEDTLS_MD_MAX_SIZE];
|
return( psa_hmac_finish_internal( &operation->ctx.hmac,
|
||||||
unsigned char *opad = operation->ctx.hmac.opad;
|
mac, mac_size ) );
|
||||||
size_t hash_size = 0;
|
|
||||||
size_t block_size =
|
|
||||||
psa_get_hash_block_size( PSA_ALG_HMAC_HASH( operation->alg ) );
|
|
||||||
|
|
||||||
if( block_size == 0 )
|
|
||||||
return( PSA_ERROR_NOT_SUPPORTED );
|
|
||||||
|
|
||||||
status = psa_hash_finish( &operation->ctx.hmac.hash_ctx, tmp,
|
|
||||||
sizeof( tmp ), &hash_size );
|
|
||||||
if( status != PSA_SUCCESS )
|
|
||||||
return( status );
|
|
||||||
/* From here on, tmp needs to be wiped. */
|
|
||||||
|
|
||||||
status = psa_hash_setup( &operation->ctx.hmac.hash_ctx,
|
|
||||||
PSA_ALG_HMAC_HASH( operation->alg ) );
|
|
||||||
if( status != PSA_SUCCESS )
|
|
||||||
goto hmac_cleanup;
|
|
||||||
|
|
||||||
status = psa_hash_update( &operation->ctx.hmac.hash_ctx, opad,
|
|
||||||
block_size );
|
|
||||||
if( status != PSA_SUCCESS )
|
|
||||||
goto hmac_cleanup;
|
|
||||||
|
|
||||||
status = psa_hash_update( &operation->ctx.hmac.hash_ctx, tmp,
|
|
||||||
hash_size );
|
|
||||||
if( status != PSA_SUCCESS )
|
|
||||||
goto hmac_cleanup;
|
|
||||||
|
|
||||||
status = psa_hash_finish( &operation->ctx.hmac.hash_ctx, mac,
|
|
||||||
mac_size, &hash_size );
|
|
||||||
hmac_cleanup:
|
|
||||||
mbedtls_zeroize( tmp, hash_size );
|
|
||||||
return( status );
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
#endif /* MBEDTLS_MD_C */
|
#endif /* MBEDTLS_MD_C */
|
||||||
|
Loading…
Reference in New Issue
Block a user