PSA: Add support for HKDF-Extend and HKDF-Expand algs
Signed-off-by: Przemek Stekiel <przemyslaw.stekiel@mobica.com>
This commit is contained in:
parent
6b6ce3278e
commit
17520fe2c5
1 changed files with 89 additions and 55 deletions
|
@ -4295,7 +4295,8 @@ psa_status_t psa_key_derivation_abort( psa_key_derivation_operation_t *operation
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
#if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF)
|
#if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF)
|
||||||
if( PSA_ALG_IS_HKDF( kdf_alg ) )
|
if( PSA_ALG_IS_HKDF( kdf_alg ) || PSA_ALG_IS_HKDF_EXTRACT( kdf_alg ) ||
|
||||||
|
PSA_ALG_IS_HKDF_EXPAND( kdf_alg ) )
|
||||||
{
|
{
|
||||||
mbedtls_free( operation->ctx.hkdf.info );
|
mbedtls_free( operation->ctx.hkdf.info );
|
||||||
status = psa_mac_abort( &operation->ctx.hkdf.hmac );
|
status = psa_mac_abort( &operation->ctx.hkdf.hmac );
|
||||||
|
@ -4379,15 +4380,17 @@ psa_status_t psa_key_derivation_set_capacity( psa_key_derivation_operation_t *op
|
||||||
/* Read some bytes from an HKDF-based operation. This performs a chunk
|
/* Read some bytes from an HKDF-based operation. This performs a chunk
|
||||||
* of the expand phase of the HKDF algorithm. */
|
* of the expand phase of the HKDF algorithm. */
|
||||||
static psa_status_t psa_key_derivation_hkdf_read( psa_hkdf_key_derivation_t *hkdf,
|
static psa_status_t psa_key_derivation_hkdf_read( psa_hkdf_key_derivation_t *hkdf,
|
||||||
psa_algorithm_t hash_alg,
|
psa_algorithm_t kdf_alg,
|
||||||
uint8_t *output,
|
uint8_t *output,
|
||||||
size_t output_length )
|
size_t output_length )
|
||||||
{
|
{
|
||||||
|
psa_algorithm_t hash_alg = PSA_ALG_HKDF_GET_HASH( kdf_alg );
|
||||||
uint8_t hash_length = PSA_HASH_LENGTH( hash_alg );
|
uint8_t hash_length = PSA_HASH_LENGTH( hash_alg );
|
||||||
size_t hmac_output_length;
|
size_t hmac_output_length;
|
||||||
psa_status_t status;
|
psa_status_t status;
|
||||||
|
|
||||||
if( hkdf->state < HKDF_STATE_KEYED || ! hkdf->info_set )
|
if( hkdf->state < HKDF_STATE_KEYED ||
|
||||||
|
( ! hkdf->info_set && ! PSA_ALG_IS_HKDF_EXTRACT( kdf_alg ) ) )
|
||||||
return( PSA_ERROR_BAD_STATE );
|
return( PSA_ERROR_BAD_STATE );
|
||||||
hkdf->state = HKDF_STATE_OUTPUT;
|
hkdf->state = HKDF_STATE_OUTPUT;
|
||||||
|
|
||||||
|
@ -4411,40 +4414,49 @@ static psa_status_t psa_key_derivation_hkdf_read( psa_hkdf_key_derivation_t *hkd
|
||||||
if( hkdf->block_number == 0xff )
|
if( hkdf->block_number == 0xff )
|
||||||
return( PSA_ERROR_BAD_STATE );
|
return( PSA_ERROR_BAD_STATE );
|
||||||
|
|
||||||
|
|
||||||
|
if( PSA_ALG_IS_HKDF_EXTRACT( kdf_alg ) && hkdf->block_number == 0 )
|
||||||
|
{
|
||||||
|
memcpy( hkdf->output_block, hkdf->prk, hash_length );
|
||||||
|
}
|
||||||
|
|
||||||
/* We need a new block */
|
/* We need a new block */
|
||||||
++hkdf->block_number;
|
++hkdf->block_number;
|
||||||
hkdf->offset_in_block = 0;
|
hkdf->offset_in_block = 0;
|
||||||
|
|
||||||
status = psa_key_derivation_start_hmac( &hkdf->hmac,
|
if( ! PSA_ALG_IS_HKDF_EXTRACT( kdf_alg ) )
|
||||||
hash_alg,
|
|
||||||
hkdf->prk,
|
|
||||||
hash_length );
|
|
||||||
if( status != PSA_SUCCESS )
|
|
||||||
return( status );
|
|
||||||
|
|
||||||
if( hkdf->block_number != 1 )
|
|
||||||
{
|
{
|
||||||
|
status = psa_key_derivation_start_hmac( &hkdf->hmac,
|
||||||
|
hash_alg,
|
||||||
|
hkdf->prk,
|
||||||
|
hash_length );
|
||||||
|
if( status != PSA_SUCCESS )
|
||||||
|
return( status );
|
||||||
|
|
||||||
|
if( hkdf->block_number != 1 )
|
||||||
|
{
|
||||||
|
status = psa_mac_update( &hkdf->hmac,
|
||||||
|
hkdf->output_block,
|
||||||
|
hash_length );
|
||||||
|
if( status != PSA_SUCCESS )
|
||||||
|
return( status );
|
||||||
|
}
|
||||||
status = psa_mac_update( &hkdf->hmac,
|
status = psa_mac_update( &hkdf->hmac,
|
||||||
hkdf->output_block,
|
hkdf->info,
|
||||||
hash_length );
|
hkdf->info_length );
|
||||||
|
if( status != PSA_SUCCESS )
|
||||||
|
return( status );
|
||||||
|
status = psa_mac_update( &hkdf->hmac,
|
||||||
|
&hkdf->block_number, 1 );
|
||||||
|
if( status != PSA_SUCCESS )
|
||||||
|
return( status );
|
||||||
|
status = psa_mac_sign_finish( &hkdf->hmac,
|
||||||
|
hkdf->output_block,
|
||||||
|
sizeof( hkdf->output_block ),
|
||||||
|
&hmac_output_length );
|
||||||
if( status != PSA_SUCCESS )
|
if( status != PSA_SUCCESS )
|
||||||
return( status );
|
return( status );
|
||||||
}
|
}
|
||||||
status = psa_mac_update( &hkdf->hmac,
|
|
||||||
hkdf->info,
|
|
||||||
hkdf->info_length );
|
|
||||||
if( status != PSA_SUCCESS )
|
|
||||||
return( status );
|
|
||||||
status = psa_mac_update( &hkdf->hmac,
|
|
||||||
&hkdf->block_number, 1 );
|
|
||||||
if( status != PSA_SUCCESS )
|
|
||||||
return( status );
|
|
||||||
status = psa_mac_sign_finish( &hkdf->hmac,
|
|
||||||
hkdf->output_block,
|
|
||||||
sizeof( hkdf->output_block ),
|
|
||||||
&hmac_output_length );
|
|
||||||
if( status != PSA_SUCCESS )
|
|
||||||
return( status );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return( PSA_SUCCESS );
|
return( PSA_SUCCESS );
|
||||||
|
@ -4650,10 +4662,10 @@ psa_status_t psa_key_derivation_output_bytes(
|
||||||
operation->capacity -= output_length;
|
operation->capacity -= output_length;
|
||||||
|
|
||||||
#if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF)
|
#if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF)
|
||||||
if( PSA_ALG_IS_HKDF( kdf_alg ) )
|
if( PSA_ALG_IS_HKDF( kdf_alg ) || PSA_ALG_IS_HKDF_EXPAND( kdf_alg ) ||
|
||||||
|
PSA_ALG_IS_HKDF_EXTRACT( kdf_alg ) )
|
||||||
{
|
{
|
||||||
psa_algorithm_t hash_alg = PSA_ALG_HKDF_GET_HASH( kdf_alg );
|
status = psa_key_derivation_hkdf_read( &operation->ctx.hkdf, kdf_alg,
|
||||||
status = psa_key_derivation_hkdf_read( &operation->ctx.hkdf, hash_alg,
|
|
||||||
output, output_length );
|
output, output_length );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -5043,7 +5055,8 @@ psa_status_t psa_key_derivation_output_key( const psa_key_attributes_t *attribut
|
||||||
static int is_kdf_alg_supported( psa_algorithm_t kdf_alg )
|
static int is_kdf_alg_supported( psa_algorithm_t kdf_alg )
|
||||||
{
|
{
|
||||||
#if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF)
|
#if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF)
|
||||||
if( PSA_ALG_IS_HKDF( kdf_alg ) )
|
if( PSA_ALG_IS_HKDF( kdf_alg ) || PSA_ALG_IS_HKDF_EXTRACT( kdf_alg ) ||
|
||||||
|
PSA_ALG_IS_HKDF_EXPAND( kdf_alg ) )
|
||||||
return( 1 );
|
return( 1 );
|
||||||
#endif
|
#endif
|
||||||
#if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF)
|
#if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF)
|
||||||
|
@ -5097,8 +5110,10 @@ static psa_status_t psa_key_derivation_setup_kdf(
|
||||||
{
|
{
|
||||||
return( PSA_ERROR_NOT_SUPPORTED );
|
return( PSA_ERROR_NOT_SUPPORTED );
|
||||||
}
|
}
|
||||||
|
if( PSA_ALG_IS_HKDF_EXTRACT( kdf_alg ) )
|
||||||
operation->capacity = 255 * hash_size;
|
operation->capacity = hash_size;
|
||||||
|
else
|
||||||
|
operation->capacity = 255 * hash_size;
|
||||||
return( PSA_SUCCESS );
|
return( PSA_SUCCESS );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5154,15 +5169,18 @@ psa_status_t psa_key_derivation_setup( psa_key_derivation_operation_t *operation
|
||||||
|
|
||||||
#if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF)
|
#if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF)
|
||||||
static psa_status_t psa_hkdf_input( psa_hkdf_key_derivation_t *hkdf,
|
static psa_status_t psa_hkdf_input( psa_hkdf_key_derivation_t *hkdf,
|
||||||
psa_algorithm_t hash_alg,
|
psa_algorithm_t kdf_alg,
|
||||||
psa_key_derivation_step_t step,
|
psa_key_derivation_step_t step,
|
||||||
const uint8_t *data,
|
const uint8_t *data,
|
||||||
size_t data_length )
|
size_t data_length )
|
||||||
{
|
{
|
||||||
|
psa_algorithm_t hash_alg = PSA_ALG_HKDF_GET_HASH( kdf_alg );
|
||||||
psa_status_t status;
|
psa_status_t status;
|
||||||
switch( step )
|
switch( step )
|
||||||
{
|
{
|
||||||
case PSA_KEY_DERIVATION_INPUT_SALT:
|
case PSA_KEY_DERIVATION_INPUT_SALT:
|
||||||
|
if( PSA_ALG_IS_HKDF_EXPAND( kdf_alg ) )
|
||||||
|
return( PSA_ERROR_INVALID_ARGUMENT );
|
||||||
if( hkdf->state != HKDF_STATE_INIT )
|
if( hkdf->state != HKDF_STATE_INIT )
|
||||||
return( PSA_ERROR_BAD_STATE );
|
return( PSA_ERROR_BAD_STATE );
|
||||||
else
|
else
|
||||||
|
@ -5177,32 +5195,48 @@ static psa_status_t psa_hkdf_input( psa_hkdf_key_derivation_t *hkdf,
|
||||||
}
|
}
|
||||||
case PSA_KEY_DERIVATION_INPUT_SECRET:
|
case PSA_KEY_DERIVATION_INPUT_SECRET:
|
||||||
/* If no salt was provided, use an empty salt. */
|
/* If no salt was provided, use an empty salt. */
|
||||||
if( hkdf->state == HKDF_STATE_INIT )
|
if( PSA_ALG_IS_HKDF_EXPAND( kdf_alg ) )
|
||||||
{
|
{
|
||||||
status = psa_key_derivation_start_hmac( &hkdf->hmac,
|
if( hkdf->state != HKDF_STATE_INIT )
|
||||||
hash_alg,
|
return( PSA_ERROR_BAD_STATE );
|
||||||
NULL, 0 );
|
|
||||||
|
if( data_length > sizeof( hkdf->prk ) )
|
||||||
|
return( PSA_ERROR_INVALID_ARGUMENT );
|
||||||
|
|
||||||
|
memcpy( hkdf->prk, data, data_length );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if( hkdf->state == HKDF_STATE_INIT )
|
||||||
|
{
|
||||||
|
status = psa_key_derivation_start_hmac( &hkdf->hmac,
|
||||||
|
hash_alg,
|
||||||
|
NULL, 0 );
|
||||||
|
if( status != PSA_SUCCESS )
|
||||||
|
return( status );
|
||||||
|
hkdf->state = HKDF_STATE_STARTED;
|
||||||
|
}
|
||||||
|
if( hkdf->state != HKDF_STATE_STARTED )
|
||||||
|
return( PSA_ERROR_BAD_STATE );
|
||||||
|
status = psa_mac_update( &hkdf->hmac,
|
||||||
|
data, data_length );
|
||||||
|
if( status != PSA_SUCCESS )
|
||||||
|
return( status );
|
||||||
|
status = psa_mac_sign_finish( &hkdf->hmac,
|
||||||
|
hkdf->prk,
|
||||||
|
sizeof( hkdf->prk ),
|
||||||
|
&data_length );
|
||||||
if( status != PSA_SUCCESS )
|
if( status != PSA_SUCCESS )
|
||||||
return( status );
|
return( status );
|
||||||
hkdf->state = HKDF_STATE_STARTED;
|
|
||||||
}
|
}
|
||||||
if( hkdf->state != HKDF_STATE_STARTED )
|
|
||||||
return( PSA_ERROR_BAD_STATE );
|
|
||||||
status = psa_mac_update( &hkdf->hmac,
|
|
||||||
data, data_length );
|
|
||||||
if( status != PSA_SUCCESS )
|
|
||||||
return( status );
|
|
||||||
status = psa_mac_sign_finish( &hkdf->hmac,
|
|
||||||
hkdf->prk,
|
|
||||||
sizeof( hkdf->prk ),
|
|
||||||
&data_length );
|
|
||||||
if( status != PSA_SUCCESS )
|
|
||||||
return( status );
|
|
||||||
hkdf->offset_in_block = PSA_HASH_LENGTH( hash_alg );
|
hkdf->offset_in_block = PSA_HASH_LENGTH( hash_alg );
|
||||||
hkdf->block_number = 0;
|
hkdf->block_number = 0;
|
||||||
hkdf->state = HKDF_STATE_KEYED;
|
hkdf->state = HKDF_STATE_KEYED;
|
||||||
return( PSA_SUCCESS );
|
return( PSA_SUCCESS );
|
||||||
case PSA_KEY_DERIVATION_INPUT_INFO:
|
case PSA_KEY_DERIVATION_INPUT_INFO:
|
||||||
|
if( PSA_ALG_IS_HKDF_EXTRACT( kdf_alg ) )
|
||||||
|
return( PSA_ERROR_INVALID_ARGUMENT );
|
||||||
if( hkdf->state == HKDF_STATE_OUTPUT )
|
if( hkdf->state == HKDF_STATE_OUTPUT )
|
||||||
return( PSA_ERROR_BAD_STATE );
|
return( PSA_ERROR_BAD_STATE );
|
||||||
if( hkdf->info_set )
|
if( hkdf->info_set )
|
||||||
|
@ -5488,10 +5522,10 @@ static psa_status_t psa_key_derivation_input_internal(
|
||||||
goto exit;
|
goto exit;
|
||||||
|
|
||||||
#if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF)
|
#if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF)
|
||||||
if( PSA_ALG_IS_HKDF( kdf_alg ) )
|
if( PSA_ALG_IS_HKDF( kdf_alg ) || PSA_ALG_IS_HKDF_EXTRACT( kdf_alg ) ||
|
||||||
|
PSA_ALG_IS_HKDF_EXPAND( kdf_alg ) )
|
||||||
{
|
{
|
||||||
status = psa_hkdf_input( &operation->ctx.hkdf,
|
status = psa_hkdf_input( &operation->ctx.hkdf, kdf_alg,
|
||||||
PSA_ALG_HKDF_GET_HASH( kdf_alg ),
|
|
||||||
step, data, data_length );
|
step, data, data_length );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
Loading…
Reference in a new issue