Merge pull request #4316 from gabor-mezei-arm/3258_implement_one-shot_MAC
Implement one-shot MAC
This commit is contained in:
commit
36ff66c4b4
3
ChangeLog.d/one-shot-mac.txt
Normal file
3
ChangeLog.d/one-shot-mac.txt
Normal file
@ -0,0 +1,3 @@
|
||||
Features
|
||||
* Implement psa_mac_compute() and psa_mac_verify() as defined in the
|
||||
PSA Cryptograpy API 1.0.0 specification.
|
@ -2220,6 +2220,46 @@ psa_status_t psa_mac_abort( psa_mac_operation_t *operation )
|
||||
return( status );
|
||||
}
|
||||
|
||||
static psa_status_t psa_mac_finalize_alg_and_key_validation(
|
||||
psa_algorithm_t alg,
|
||||
const psa_key_attributes_t *attributes,
|
||||
uint8_t *mac_size )
|
||||
{
|
||||
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
|
||||
psa_key_type_t key_type = psa_get_key_type( attributes );
|
||||
size_t key_bits = psa_get_key_bits( attributes );
|
||||
|
||||
if( ! PSA_ALG_IS_MAC( alg ) )
|
||||
return( PSA_ERROR_INVALID_ARGUMENT );
|
||||
|
||||
/* Validate the combination of key type and algorithm */
|
||||
status = psa_mac_key_can_do( alg, key_type );
|
||||
if( status != PSA_SUCCESS )
|
||||
return( status );
|
||||
|
||||
/* Get the output length for the algorithm and key combination */
|
||||
*mac_size = PSA_MAC_LENGTH( key_type, key_bits, alg );
|
||||
|
||||
if( *mac_size < 4 )
|
||||
{
|
||||
/* A very short MAC is too short for security since it can be
|
||||
* brute-forced. Ancient protocols with 32-bit MACs do exist,
|
||||
* so we make this our minimum, even though 32 bits is still
|
||||
* too small for security. */
|
||||
return( PSA_ERROR_NOT_SUPPORTED );
|
||||
}
|
||||
|
||||
if( *mac_size > PSA_MAC_LENGTH( key_type, key_bits,
|
||||
PSA_ALG_FULL_LENGTH_MAC( alg ) ) )
|
||||
{
|
||||
/* It's impossible to "truncate" to a larger length than the full length
|
||||
* of the algorithm. */
|
||||
return( PSA_ERROR_INVALID_ARGUMENT );
|
||||
}
|
||||
|
||||
return( PSA_SUCCESS );
|
||||
}
|
||||
|
||||
static psa_status_t psa_mac_setup( psa_mac_operation_t *operation,
|
||||
mbedtls_svc_key_id_t key,
|
||||
psa_algorithm_t alg,
|
||||
@ -2233,9 +2273,6 @@ static psa_status_t psa_mac_setup( psa_mac_operation_t *operation,
|
||||
if( operation->id != 0 )
|
||||
return( PSA_ERROR_BAD_STATE );
|
||||
|
||||
if( ! PSA_ALG_IS_MAC( alg ) )
|
||||
return( PSA_ERROR_INVALID_ARGUMENT );
|
||||
|
||||
status = psa_get_and_lock_key_slot_with_policy(
|
||||
key,
|
||||
&slot,
|
||||
@ -2248,39 +2285,12 @@ static psa_status_t psa_mac_setup( psa_mac_operation_t *operation,
|
||||
.core = slot->attr
|
||||
};
|
||||
|
||||
/* Validate the combination of key type and algorithm */
|
||||
status = psa_mac_key_can_do( alg, psa_get_key_type( &attributes ) );
|
||||
status = psa_mac_finalize_alg_and_key_validation( alg, &attributes,
|
||||
&operation->mac_size );
|
||||
if( status != PSA_SUCCESS )
|
||||
goto exit;
|
||||
|
||||
operation->is_sign = is_sign;
|
||||
|
||||
/* Get the output length for the algorithm and key combination */
|
||||
operation->mac_size = PSA_MAC_LENGTH(
|
||||
psa_get_key_type( &attributes ),
|
||||
psa_get_key_bits( &attributes ),
|
||||
alg );
|
||||
|
||||
if( operation->mac_size < 4 )
|
||||
{
|
||||
/* A very short MAC is too short for security since it can be
|
||||
* brute-forced. Ancient protocols with 32-bit MACs do exist,
|
||||
* so we make this our minimum, even though 32 bits is still
|
||||
* too small for security. */
|
||||
status = PSA_ERROR_NOT_SUPPORTED;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if( operation->mac_size > PSA_MAC_LENGTH( psa_get_key_type( &attributes ),
|
||||
psa_get_key_bits( &attributes ),
|
||||
PSA_ALG_FULL_LENGTH_MAC( alg ) ) )
|
||||
{
|
||||
/* It's impossible to "truncate" to a larger length than the full length
|
||||
* of the algorithm. */
|
||||
status = PSA_ERROR_INVALID_ARGUMENT;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* Dispatch the MAC setup call with validated input */
|
||||
if( is_sign )
|
||||
{
|
||||
@ -2373,24 +2383,22 @@ psa_status_t psa_mac_sign_finish( psa_mac_operation_t *operation,
|
||||
mac, operation->mac_size,
|
||||
mac_length );
|
||||
|
||||
if( status == PSA_SUCCESS )
|
||||
/* In case of success, set the potential excess room in the output buffer
|
||||
* to an invalid value, to avoid potentially leaking a longer MAC.
|
||||
* In case of error, set the output length and content to a safe default,
|
||||
* such that in case the caller misses an error check, the output would be
|
||||
* an unachievable MAC.
|
||||
*/
|
||||
if( status != PSA_SUCCESS )
|
||||
{
|
||||
/* Set the excess room in the output buffer to an invalid value, to
|
||||
* avoid potentially leaking a longer MAC. */
|
||||
if( mac_size > operation->mac_size )
|
||||
memset( &mac[operation->mac_size],
|
||||
'!',
|
||||
mac_size - operation->mac_size );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Set the output length and content to a safe default, such that in
|
||||
* case the caller misses an error check, the output would be an
|
||||
* unachievable MAC. */
|
||||
*mac_length = mac_size;
|
||||
memset( mac, '!', mac_size );
|
||||
operation->mac_size = 0;
|
||||
}
|
||||
|
||||
if( mac_size > operation->mac_size )
|
||||
memset( &mac[operation->mac_size], '!',
|
||||
mac_size - operation->mac_size );
|
||||
|
||||
abort_status = psa_mac_abort( operation );
|
||||
|
||||
return( status == PSA_SUCCESS ? abort_status : status );
|
||||
@ -2424,7 +2432,116 @@ cleanup:
|
||||
return( status == PSA_SUCCESS ? abort_status : status );
|
||||
}
|
||||
|
||||
static psa_status_t psa_mac_compute_internal( mbedtls_svc_key_id_t key,
|
||||
psa_algorithm_t alg,
|
||||
const uint8_t *input,
|
||||
size_t input_length,
|
||||
uint8_t *mac,
|
||||
size_t mac_size,
|
||||
size_t *mac_length,
|
||||
int is_sign )
|
||||
{
|
||||
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
|
||||
psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED;
|
||||
psa_key_slot_t *slot;
|
||||
uint8_t operation_mac_size = 0;
|
||||
|
||||
status = psa_get_and_lock_key_slot_with_policy(
|
||||
key, &slot,
|
||||
is_sign ? PSA_KEY_USAGE_SIGN_HASH : PSA_KEY_USAGE_VERIFY_HASH,
|
||||
alg );
|
||||
if( status != PSA_SUCCESS )
|
||||
goto exit;
|
||||
|
||||
psa_key_attributes_t attributes = {
|
||||
.core = slot->attr
|
||||
};
|
||||
|
||||
status = psa_mac_finalize_alg_and_key_validation( alg, &attributes,
|
||||
&operation_mac_size );
|
||||
if( status != PSA_SUCCESS )
|
||||
goto exit;
|
||||
|
||||
if( mac_size < operation_mac_size )
|
||||
{
|
||||
status = PSA_ERROR_BUFFER_TOO_SMALL;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
status = psa_driver_wrapper_mac_compute(
|
||||
&attributes,
|
||||
slot->key.data, slot->key.bytes,
|
||||
alg,
|
||||
input, input_length,
|
||||
mac, operation_mac_size, mac_length );
|
||||
|
||||
exit:
|
||||
/* In case of success, set the potential excess room in the output buffer
|
||||
* to an invalid value, to avoid potentially leaking a longer MAC.
|
||||
* In case of error, set the output length and content to a safe default,
|
||||
* such that in case the caller misses an error check, the output would be
|
||||
* an unachievable MAC.
|
||||
*/
|
||||
if( status != PSA_SUCCESS )
|
||||
{
|
||||
*mac_length = mac_size;
|
||||
operation_mac_size = 0;
|
||||
}
|
||||
if( mac_size > operation_mac_size )
|
||||
memset( &mac[operation_mac_size], '!', mac_size - operation_mac_size );
|
||||
|
||||
unlock_status = psa_unlock_key_slot( slot );
|
||||
|
||||
return( ( status == PSA_SUCCESS ) ? unlock_status : status );
|
||||
}
|
||||
|
||||
psa_status_t psa_mac_compute( mbedtls_svc_key_id_t key,
|
||||
psa_algorithm_t alg,
|
||||
const uint8_t *input,
|
||||
size_t input_length,
|
||||
uint8_t *mac,
|
||||
size_t mac_size,
|
||||
size_t *mac_length)
|
||||
{
|
||||
return( psa_mac_compute_internal( key, alg,
|
||||
input, input_length,
|
||||
mac, mac_size, mac_length, 1 ) );
|
||||
}
|
||||
|
||||
psa_status_t psa_mac_verify( mbedtls_svc_key_id_t key,
|
||||
psa_algorithm_t alg,
|
||||
const uint8_t *input,
|
||||
size_t input_length,
|
||||
const uint8_t *mac,
|
||||
size_t mac_length)
|
||||
{
|
||||
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
|
||||
uint8_t actual_mac[PSA_MAC_MAX_SIZE];
|
||||
size_t actual_mac_length;
|
||||
|
||||
status = psa_mac_compute_internal( key, alg,
|
||||
input, input_length,
|
||||
actual_mac, sizeof( actual_mac ),
|
||||
&actual_mac_length, 0 );
|
||||
if( status != PSA_SUCCESS )
|
||||
goto exit;
|
||||
|
||||
if( mac_length != actual_mac_length )
|
||||
{
|
||||
status = PSA_ERROR_INVALID_SIGNATURE;
|
||||
goto exit;
|
||||
}
|
||||
if( mbedtls_psa_safer_memcmp( mac, actual_mac, actual_mac_length ) != 0 )
|
||||
{
|
||||
status = PSA_ERROR_INVALID_SIGNATURE;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
exit:
|
||||
mbedtls_platform_zeroize( actual_mac, sizeof( actual_mac ) );
|
||||
|
||||
return ( status );
|
||||
}
|
||||
|
||||
/****************************************************************/
|
||||
/* Asymmetric cryptography */
|
||||
|
@ -355,30 +355,6 @@ static psa_status_t mac_setup( mbedtls_psa_mac_operation_t *operation,
|
||||
return( status );
|
||||
}
|
||||
|
||||
static psa_status_t mac_compute(
|
||||
const psa_key_attributes_t *attributes,
|
||||
const uint8_t *key_buffer,
|
||||
size_t key_buffer_size,
|
||||
psa_algorithm_t alg,
|
||||
const uint8_t *input,
|
||||
size_t input_length,
|
||||
uint8_t *mac,
|
||||
size_t mac_size,
|
||||
size_t *mac_length )
|
||||
{
|
||||
/* One-shot MAC has not been implemented in this PSA implementation yet. */
|
||||
(void) attributes;
|
||||
(void) key_buffer;
|
||||
(void) key_buffer_size;
|
||||
(void) alg;
|
||||
(void) input;
|
||||
(void) input_length;
|
||||
(void) mac;
|
||||
(void) mac_size;
|
||||
(void) mac_length;
|
||||
return( PSA_ERROR_NOT_SUPPORTED );
|
||||
}
|
||||
|
||||
static psa_status_t mac_update(
|
||||
mbedtls_psa_mac_operation_t *operation,
|
||||
const uint8_t *input,
|
||||
@ -493,6 +469,44 @@ cleanup:
|
||||
|
||||
return( status );
|
||||
}
|
||||
|
||||
static psa_status_t mac_compute(
|
||||
const psa_key_attributes_t *attributes,
|
||||
const uint8_t *key_buffer,
|
||||
size_t key_buffer_size,
|
||||
psa_algorithm_t alg,
|
||||
const uint8_t *input,
|
||||
size_t input_length,
|
||||
uint8_t *mac,
|
||||
size_t mac_size,
|
||||
size_t *mac_length )
|
||||
{
|
||||
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
|
||||
mbedtls_psa_mac_operation_t operation = MBEDTLS_PSA_MAC_OPERATION_INIT;
|
||||
|
||||
status = mac_setup( &operation,
|
||||
attributes, key_buffer, key_buffer_size,
|
||||
alg );
|
||||
if( status != PSA_SUCCESS )
|
||||
goto exit;
|
||||
|
||||
if( input_length > 0 )
|
||||
{
|
||||
status = mac_update( &operation, input, input_length );
|
||||
if( status != PSA_SUCCESS )
|
||||
goto exit;
|
||||
}
|
||||
|
||||
status = mac_finish_internal( &operation, mac, mac_size );
|
||||
if( status == PSA_SUCCESS )
|
||||
*mac_length = mac_size;
|
||||
|
||||
exit:
|
||||
mac_abort( &operation );
|
||||
|
||||
return( status );
|
||||
}
|
||||
|
||||
#endif /* BUILTIN_ALG_HMAC || BUILTIN_ALG_CMAC */
|
||||
|
||||
#if defined(MBEDTLS_PSA_BUILTIN_MAC)
|
||||
|
@ -1987,7 +1987,21 @@ void mac_sign( int key_type_arg,
|
||||
mbedtls_test_set_step( output_size );
|
||||
ASSERT_ALLOC( actual_mac, output_size );
|
||||
|
||||
/* Calculate the MAC. */
|
||||
/* Calculate the MAC, one-shot case. */
|
||||
TEST_EQUAL( psa_mac_compute( key, alg,
|
||||
input->x, input->len,
|
||||
actual_mac, output_size, &mac_length ),
|
||||
expected_status );
|
||||
if( expected_status == PSA_SUCCESS )
|
||||
{
|
||||
ASSERT_COMPARE( expected_mac->x, expected_mac->len,
|
||||
actual_mac, mac_length );
|
||||
}
|
||||
|
||||
if( output_size > 0 )
|
||||
memset( actual_mac, 0, output_size );
|
||||
|
||||
/* Calculate the MAC, multi-part case. */
|
||||
PSA_ASSERT( psa_mac_sign_setup( &operation, key, alg ) );
|
||||
PSA_ASSERT( psa_mac_update( &operation,
|
||||
input->x, input->len ) );
|
||||
@ -2039,7 +2053,11 @@ void mac_verify( int key_type_arg,
|
||||
PSA_ASSERT( psa_import_key( &attributes, key_data->x, key_data->len,
|
||||
&key ) );
|
||||
|
||||
/* Test the correct MAC. */
|
||||
/* Verify correct MAC, one-shot case. */
|
||||
PSA_ASSERT( psa_mac_verify( key, alg, input->x, input->len,
|
||||
expected_mac->x, expected_mac->len ) );
|
||||
|
||||
/* Verify correct MAC, multi-part case. */
|
||||
PSA_ASSERT( psa_mac_verify_setup( &operation, key, alg ) );
|
||||
PSA_ASSERT( psa_mac_update( &operation,
|
||||
input->x, input->len ) );
|
||||
@ -2047,7 +2065,14 @@ void mac_verify( int key_type_arg,
|
||||
expected_mac->x,
|
||||
expected_mac->len ) );
|
||||
|
||||
/* Test a MAC that's too short. */
|
||||
/* Test a MAC that's too short, one-shot case. */
|
||||
TEST_EQUAL( psa_mac_verify( key, alg,
|
||||
input->x, input->len,
|
||||
expected_mac->x,
|
||||
expected_mac->len - 1 ),
|
||||
PSA_ERROR_INVALID_SIGNATURE );
|
||||
|
||||
/* Test a MAC that's too short, multi-part case. */
|
||||
PSA_ASSERT( psa_mac_verify_setup( &operation, key, alg ) );
|
||||
PSA_ASSERT( psa_mac_update( &operation,
|
||||
input->x, input->len ) );
|
||||
@ -2056,9 +2081,15 @@ void mac_verify( int key_type_arg,
|
||||
expected_mac->len - 1 ),
|
||||
PSA_ERROR_INVALID_SIGNATURE );
|
||||
|
||||
/* Test a MAC that's too long. */
|
||||
/* Test a MAC that's too long, one-shot case. */
|
||||
ASSERT_ALLOC( perturbed_mac, expected_mac->len + 1 );
|
||||
memcpy( perturbed_mac, expected_mac->x, expected_mac->len );
|
||||
TEST_EQUAL( psa_mac_verify( key, alg,
|
||||
input->x, input->len,
|
||||
perturbed_mac, expected_mac->len + 1 ),
|
||||
PSA_ERROR_INVALID_SIGNATURE );
|
||||
|
||||
/* Test a MAC that's too long, multi-part case. */
|
||||
PSA_ASSERT( psa_mac_verify_setup( &operation, key, alg ) );
|
||||
PSA_ASSERT( psa_mac_update( &operation,
|
||||
input->x, input->len ) );
|
||||
@ -2072,6 +2103,12 @@ void mac_verify( int key_type_arg,
|
||||
{
|
||||
mbedtls_test_set_step( i );
|
||||
perturbed_mac[i] ^= 1;
|
||||
|
||||
TEST_EQUAL( psa_mac_verify( key, alg,
|
||||
input->x, input->len,
|
||||
perturbed_mac, expected_mac->len ),
|
||||
PSA_ERROR_INVALID_SIGNATURE );
|
||||
|
||||
PSA_ASSERT( psa_mac_verify_setup( &operation, key, alg ) );
|
||||
PSA_ASSERT( psa_mac_update( &operation,
|
||||
input->x, input->len ) );
|
||||
|
@ -1118,7 +1118,31 @@ void mac_sign( int key_type_arg,
|
||||
ASSERT_ALLOC( actual_mac, mac_buffer_size );
|
||||
mbedtls_test_driver_mac_hooks.forced_status = forced_status;
|
||||
|
||||
/* Calculate the MAC. */
|
||||
/*
|
||||
* Calculate the MAC, one-shot case.
|
||||
*/
|
||||
status = psa_mac_compute( key, alg,
|
||||
input->x, input->len,
|
||||
actual_mac, mac_buffer_size,
|
||||
&mac_length );
|
||||
|
||||
TEST_EQUAL( mbedtls_test_driver_mac_hooks.hits, 1 );
|
||||
if( forced_status == PSA_SUCCESS ||
|
||||
forced_status == PSA_ERROR_NOT_SUPPORTED )
|
||||
{
|
||||
PSA_ASSERT( status );
|
||||
}
|
||||
else
|
||||
TEST_EQUAL( forced_status, status );
|
||||
|
||||
if( mac_buffer_size > 0 )
|
||||
memset( actual_mac, 0, mac_buffer_size );
|
||||
mbedtls_test_driver_mac_hooks = mbedtls_test_driver_mac_hooks_init();
|
||||
mbedtls_test_driver_mac_hooks.forced_status = forced_status;
|
||||
|
||||
/*
|
||||
* Calculate the MAC, multipart case.
|
||||
*/
|
||||
status = psa_mac_sign_setup( &operation, key, alg );
|
||||
TEST_EQUAL( mbedtls_test_driver_mac_hooks.hits, 1 );
|
||||
|
||||
@ -1214,7 +1238,27 @@ void mac_verify( int key_type_arg,
|
||||
|
||||
mbedtls_test_driver_mac_hooks.forced_status = forced_status;
|
||||
|
||||
/* Test the correct MAC. */
|
||||
/*
|
||||
* Verify the MAC, one-shot case.
|
||||
*/
|
||||
status = psa_mac_verify( key, alg,
|
||||
input->x, input->len,
|
||||
expected_mac->x, expected_mac->len );
|
||||
TEST_EQUAL( mbedtls_test_driver_mac_hooks.hits, 1 );
|
||||
if( forced_status == PSA_SUCCESS ||
|
||||
forced_status == PSA_ERROR_NOT_SUPPORTED )
|
||||
{
|
||||
PSA_ASSERT( status );
|
||||
}
|
||||
else
|
||||
TEST_EQUAL( forced_status, status );
|
||||
|
||||
mbedtls_test_driver_mac_hooks = mbedtls_test_driver_mac_hooks_init();
|
||||
mbedtls_test_driver_mac_hooks.forced_status = forced_status;
|
||||
|
||||
/*
|
||||
* Verify the MAC, multi-part case.
|
||||
*/
|
||||
status = psa_mac_verify_setup( &operation, key, alg );
|
||||
TEST_EQUAL( mbedtls_test_driver_mac_hooks.hits, 1 );
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user