diff --git a/include/psa/crypto.h b/include/psa/crypto.h index 957385916..98573c90f 100644 --- a/include/psa/crypto.h +++ b/include/psa/crypto.h @@ -1333,30 +1333,32 @@ psa_status_t psa_hash_abort(psa_hash_operation_t *operation); * as directed by the documentation of a specific implementation. */ typedef struct psa_mac_operation_s psa_mac_operation_t; -/** Start a multipart MAC operation. +/** Start a multipart MAC calculation operation. * - * The sequence of operations to calculate a MAC (message authentication code) - * is as follows: + * This function sets up the calculation of the MAC + * (message authentication code) of a byte string. + * To verify the MAC of a message against an + * expected value, use psa_mac_verify_setup() instead. + * + * The sequence of operations to calculate a MAC is as follows: * -# Allocate an operation object which will be passed to all the functions * listed here. - * -# Call psa_mac_start() to specify the algorithm and key. + * -# Call psa_mac_sign_setup() to specify the algorithm and key. * The key remains associated with the operation even if the content * of the key slot changes. * -# Call psa_mac_update() zero, one or more times, passing a fragment * of the message each time. The MAC that is calculated is the MAC * of the concatenation of these messages in order. - * -# To calculate the MAC, call psa_mac_sign_finish(). - * To compare the MAC with an expected value, call psa_mac_verify_finish(). + * -# At the end of the message, call psa_mac_sign_finish() to finish + * calculating the MAC value and retrieve it. * * The application may call psa_mac_abort() at any time after the operation - * has been initialized with psa_mac_start(). + * has been initialized with psa_mac_sign_setup(). * - * After a successful call to psa_mac_start(), the application must - * eventually terminate the operation. The following events terminate an - * operation: + * After a successful call to psa_mac_sign_setup(), the application must + * eventually terminate the operation through one of the following methods: * - A failed call to psa_mac_update(). - * - A call to psa_mac_sign_finish(), psa_mac_verify_finish() or - * psa_mac_abort(). + * - A call to psa_mac_sign_finish() or psa_mac_abort(). * * \param operation The operation object to use. * \param key Slot containing the key to use for the operation. @@ -1376,9 +1378,57 @@ typedef struct psa_mac_operation_s psa_mac_operation_t; * \retval PSA_ERROR_HARDWARE_FAILURE * \retval PSA_ERROR_TAMPERING_DETECTED */ -psa_status_t psa_mac_start(psa_mac_operation_t *operation, - psa_key_slot_t key, - psa_algorithm_t alg); +psa_status_t psa_mac_sign_setup(psa_mac_operation_t *operation, + psa_key_slot_t key, + psa_algorithm_t alg); + +/** Start a multipart MAC verification operation. + * + * This function sets up the verification of the MAC + * (message authentication code) of a byte string against an expected value. + * + * The sequence of operations to verify a MAC is as follows: + * -# Allocate an operation object which will be passed to all the functions + * listed here. + * -# Call psa_mac_verify_setup() to specify the algorithm and key. + * The key remains associated with the operation even if the content + * of the key slot changes. + * -# Call psa_mac_update() zero, one or more times, passing a fragment + * of the message each time. The MAC that is calculated is the MAC + * of the concatenation of these messages in order. + * -# At the end of the message, call psa_mac_verify_finish() to finish + * calculating the actual MAC of the message and verify it against + * the expected value. + * + * The application may call psa_mac_abort() at any time after the operation + * has been initialized with psa_mac_verify_setup(). + * + * After a successful call to psa_mac_verify_setup(), the application must + * eventually terminate the operation through one of the following methods: + * - A failed call to psa_mac_update(). + * - A call to psa_mac_verify_finish() or psa_mac_abort(). + * + * \param operation The operation object to use. + * \param key Slot containing the key to use for the operation. + * \param alg The MAC algorithm to compute (\c PSA_ALG_XXX value + * such that #PSA_ALG_IS_MAC(alg) is true). + * + * \retval PSA_SUCCESS + * Success. + * \retval PSA_ERROR_EMPTY_SLOT + * \retval PSA_ERROR_NOT_PERMITTED + * \retval PSA_ERROR_INVALID_ARGUMENT + * \c key is not compatible with \c alg. + * \retval PSA_ERROR_NOT_SUPPORTED + * \c alg is not supported or is not a MAC algorithm. + * \retval PSA_ERROR_INSUFFICIENT_MEMORY + * \retval PSA_ERROR_COMMUNICATION_FAILURE + * \retval PSA_ERROR_HARDWARE_FAILURE + * \retval PSA_ERROR_TAMPERING_DETECTED + */ +psa_status_t psa_mac_verify_setup(psa_mac_operation_t *operation, + psa_key_slot_t key, + psa_algorithm_t alg); psa_status_t psa_mac_update(psa_mac_operation_t *operation, const uint8_t *input, diff --git a/include/psa/crypto_struct.h b/include/psa/crypto_struct.h index b981f23c7..85c997485 100644 --- a/include/psa/crypto_struct.h +++ b/include/psa/crypto_struct.h @@ -102,8 +102,7 @@ struct psa_mac_operation_s int iv_required : 1; int iv_set : 1; int has_input : 1; - int key_usage_sign : 1; - int key_usage_verify : 1; + int is_sign : 1; uint8_t mac_size; union { diff --git a/library/psa_crypto.c b/library/psa_crypto.c index 4c42d61e0..61eef45ca 100644 --- a/library/psa_crypto.c +++ b/library/psa_crypto.c @@ -1296,8 +1296,7 @@ static psa_status_t psa_mac_init( psa_mac_operation_t *operation, operation->iv_set = 0; operation->iv_required = 0; operation->has_input = 0; - operation->key_usage_sign = 0; - operation->key_usage_verify = 0; + operation->is_sign = 0; #if defined(MBEDTLS_CMAC_C) if( alg == PSA_ALG_CMAC ) @@ -1367,14 +1366,13 @@ psa_status_t psa_mac_abort( psa_mac_operation_t *operation ) operation->iv_set = 0; operation->iv_required = 0; operation->has_input = 0; - operation->key_usage_sign = 0; - operation->key_usage_verify = 0; + operation->is_sign = 0; return( PSA_SUCCESS ); } #if defined(MBEDTLS_CMAC_C) -static int psa_cmac_start( psa_mac_operation_t *operation, +static int psa_cmac_setup( psa_mac_operation_t *operation, size_t key_bits, key_slot_t *slot, const mbedtls_cipher_info_t *cipher_info ) @@ -1395,7 +1393,7 @@ static int psa_cmac_start( psa_mac_operation_t *operation, #endif /* MBEDTLS_CMAC_C */ #if defined(MBEDTLS_MD_C) -static int psa_hmac_start( psa_mac_operation_t *operation, +static int psa_hmac_setup( psa_mac_operation_t *operation, psa_key_type_t key_type, key_slot_t *slot, psa_algorithm_t alg ) @@ -1457,39 +1455,34 @@ cleanup: 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_start in the error case. */ + * psa_mac_setup in the error case. */ return( status ); } #endif /* MBEDTLS_MD_C */ -psa_status_t psa_mac_start( psa_mac_operation_t *operation, - psa_key_slot_t key, - psa_algorithm_t alg ) +static psa_status_t psa_mac_setup( psa_mac_operation_t *operation, + psa_key_slot_t key, + psa_algorithm_t alg, + int is_sign ) { psa_status_t status; key_slot_t *slot; size_t key_bits; + psa_key_usage_t usage = + is_sign ? PSA_KEY_USAGE_SIGN : PSA_KEY_USAGE_VERIFY; const mbedtls_cipher_info_t *cipher_info = NULL; status = psa_mac_init( operation, alg ); if( status != PSA_SUCCESS ) return( status ); + if( is_sign ) + operation->is_sign = 1; - status = psa_get_key_from_slot( key, &slot, 0, alg ); + status = psa_get_key_from_slot( key, &slot, usage, alg ); if( status != PSA_SUCCESS ) return( status ); - /* Since this function is called identically for a sign or verify - * operation, we don't know yet whether the operation is permitted. - * Store the part of the key policy that we can't check in the - * operation structure. psa_mac_sign_finish() or psa_mac_verify_finish() - * will check that remaining part. */ - 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; - key_bits = psa_get_key_bits( slot ); if( ! PSA_ALG_IS_HMAC( alg ) ) @@ -1504,7 +1497,7 @@ psa_status_t psa_mac_start( psa_mac_operation_t *operation, { #if defined(MBEDTLS_CMAC_C) case PSA_ALG_CMAC: - status = mbedtls_to_psa_error( psa_cmac_start( operation, + status = mbedtls_to_psa_error( psa_cmac_setup( operation, key_bits, slot, cipher_info ) ); @@ -1513,7 +1506,7 @@ psa_status_t psa_mac_start( psa_mac_operation_t *operation, default: #if defined(MBEDTLS_MD_C) if( PSA_ALG_IS_HMAC( alg ) ) - status = psa_hmac_start( operation, slot->type, slot, alg ); + status = psa_hmac_setup( operation, slot->type, slot, alg ); else #endif /* MBEDTLS_MD_C */ return( PSA_ERROR_NOT_SUPPORTED ); @@ -1532,6 +1525,20 @@ psa_status_t psa_mac_start( psa_mac_operation_t *operation, return( status ); } +psa_status_t psa_mac_sign_setup( psa_mac_operation_t *operation, + psa_key_slot_t key, + psa_algorithm_t alg ) +{ + return( psa_mac_setup( operation, key, alg, 1 ) ); +} + +psa_status_t psa_mac_verify_setup( psa_mac_operation_t *operation, + psa_key_slot_t key, + psa_algorithm_t alg ) +{ + return( psa_mac_setup( operation, key, alg, 0 ) ); +} + psa_status_t psa_mac_update( psa_mac_operation_t *operation, const uint8_t *input, size_t input_length ) @@ -1676,8 +1683,11 @@ psa_status_t psa_mac_sign_finish( psa_mac_operation_t *operation, size_t mac_size, size_t *mac_length ) { - if( ! operation->key_usage_sign ) - return( PSA_ERROR_NOT_PERMITTED ); + if( ! operation->is_sign ) + { + psa_mac_abort( operation ); + return( PSA_ERROR_BAD_STATE ); + } return( psa_mac_finish_internal( operation, mac, mac_size, mac_length ) ); @@ -1691,8 +1701,11 @@ psa_status_t psa_mac_verify_finish( psa_mac_operation_t *operation, size_t actual_mac_length; psa_status_t status; - if( ! operation->key_usage_verify ) - return( PSA_ERROR_NOT_PERMITTED ); + if( operation->is_sign ) + { + psa_mac_abort( operation ); + return( PSA_ERROR_BAD_STATE ); + } status = psa_mac_finish_internal( operation, actual_mac, sizeof( actual_mac ), diff --git a/tests/suites/test_suite_psa_crypto.function b/tests/suites/test_suite_psa_crypto.function index fcab07bc3..3a03a76bf 100644 --- a/tests/suites/test_suite_psa_crypto.function +++ b/tests/suites/test_suite_psa_crypto.function @@ -138,7 +138,8 @@ static int exercise_mac_key( psa_key_slot_t key, if( usage & PSA_KEY_USAGE_SIGN ) { - TEST_ASSERT( psa_mac_start( &operation, key, alg ) == PSA_SUCCESS ); + TEST_ASSERT( psa_mac_sign_setup( &operation, + key, alg ) == PSA_SUCCESS ); TEST_ASSERT( psa_mac_update( &operation, input, sizeof( input ) ) == PSA_SUCCESS ); TEST_ASSERT( psa_mac_sign_finish( &operation, @@ -152,7 +153,8 @@ static int exercise_mac_key( psa_key_slot_t key, ( usage & PSA_KEY_USAGE_SIGN ? PSA_SUCCESS : PSA_ERROR_INVALID_SIGNATURE ); - TEST_ASSERT( psa_mac_start( &operation, key, alg ) == PSA_SUCCESS ); + TEST_ASSERT( psa_mac_verify_setup( &operation, + key, alg ) == PSA_SUCCESS ); TEST_ASSERT( psa_mac_update( &operation, input, sizeof( input ) ) == PSA_SUCCESS ); TEST_ASSERT( psa_mac_verify_finish( &operation, @@ -736,7 +738,6 @@ void mac_key_policy( int policy_usage, psa_mac_operation_t operation; psa_status_t status; unsigned char mac[PSA_MAC_MAX_SIZE]; - size_t output_length; TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS ); @@ -747,10 +748,7 @@ void mac_key_policy( int policy_usage, TEST_ASSERT( psa_import_key( key_slot, key_type, key_data->x, key_data->len ) == PSA_SUCCESS ); - status = psa_mac_start( &operation, key_slot, exercise_alg ); - if( status == PSA_SUCCESS ) - status = psa_mac_sign_finish( &operation, - mac, sizeof( mac ), &output_length ); + status = psa_mac_sign_setup( &operation, key_slot, exercise_alg ); if( policy_alg == exercise_alg && ( policy_usage & PSA_KEY_USAGE_SIGN ) != 0 ) TEST_ASSERT( status == PSA_SUCCESS ); @@ -759,12 +757,10 @@ void mac_key_policy( int policy_usage, psa_mac_abort( &operation ); memset( mac, 0, sizeof( mac ) ); - status = psa_mac_start( &operation, key_slot, exercise_alg ); - if( status == PSA_SUCCESS ) - status = psa_mac_verify_finish( &operation, mac, sizeof( mac ) ); + status = psa_mac_verify_setup( &operation, key_slot, exercise_alg ); if( policy_alg == exercise_alg && ( policy_usage & PSA_KEY_USAGE_VERIFY ) != 0 ) - TEST_ASSERT( status == PSA_ERROR_INVALID_SIGNATURE ); + TEST_ASSERT( status == PSA_SUCCESS ); else TEST_ASSERT( status == PSA_ERROR_NOT_PERMITTED ); @@ -1155,7 +1151,7 @@ void mac_setup( int key_type_arg, TEST_ASSERT( psa_import_key( key_slot, key_type, key->x, key->len ) == PSA_SUCCESS ); - status = psa_mac_start( &operation, key_slot, alg ); + status = psa_mac_sign_setup( &operation, key_slot, alg ); psa_mac_abort( &operation ); TEST_ASSERT( status == expected_status ); @@ -1196,7 +1192,8 @@ void mac_verify( int key_type_arg, TEST_ASSERT( psa_import_key( key_slot, key_type, key->x, key->len ) == PSA_SUCCESS ); - TEST_ASSERT( psa_mac_start( &operation, key_slot, alg ) == PSA_SUCCESS ); + TEST_ASSERT( psa_mac_verify_setup( &operation, + key_slot, alg ) == PSA_SUCCESS ); TEST_ASSERT( psa_destroy_key( key_slot ) == PSA_SUCCESS ); TEST_ASSERT( psa_mac_update( &operation, input->x, input->len ) == PSA_SUCCESS );