diff --git a/include/psa/crypto_builtin_composites.h b/include/psa/crypto_builtin_composites.h index fd7f6f91a9..2fb0633ab4 100644 --- a/include/psa/crypto_builtin_composites.h +++ b/include/psa/crypto_builtin_composites.h @@ -53,6 +53,8 @@ typedef struct /** The HMAC part of the context. */ uint8_t opad[PSA_HMAC_MAX_HASH_BLOCK_SIZE]; } psa_hmac_internal_data; + +#define MBEDTLS_PSA_HMAC_OPERATION_INIT {0, {0}, {0}} #endif /* PSA_WANT_ALG_HMAC */ #include "mbedtls/cmac.h" diff --git a/library/psa_crypto.c b/library/psa_crypto.c index 3ca8c9d8f6..0ef73dff7a 100644 --- a/library/psa_crypto.c +++ b/library/psa_crypto.c @@ -3331,19 +3331,19 @@ static psa_status_t psa_key_derivation_hkdf_read( psa_hkdf_key_derivation_t *hkd return( status ); if( hkdf->block_number != 1 ) { - status = psa_hash_update( &hkdf->hmac.hash_ctx, - hkdf->output_block, - hash_length ); + status = psa_hmac_update_internal( &hkdf->hmac, + hkdf->output_block, + hash_length ); if( status != PSA_SUCCESS ) return( status ); } - status = psa_hash_update( &hkdf->hmac.hash_ctx, - hkdf->info, - hkdf->info_length ); + status = psa_hmac_update_internal( &hkdf->hmac, + hkdf->info, + hkdf->info_length ); if( status != PSA_SUCCESS ) return( status ); - status = psa_hash_update( &hkdf->hmac.hash_ctx, - &hkdf->block_number, 1 ); + status = psa_hmac_update_internal( &hkdf->hmac, + &hkdf->block_number, 1 ); if( status != PSA_SUCCESS ) return( status ); status = psa_hmac_finish_internal( &hkdf->hmac, @@ -3365,7 +3365,7 @@ static psa_status_t psa_key_derivation_tls12_prf_generate_next_block( { psa_algorithm_t hash_alg = PSA_ALG_HKDF_GET_HASH( alg ); uint8_t hash_length = PSA_HASH_LENGTH( hash_alg ); - psa_hash_operation_t backup = PSA_HASH_OPERATION_INIT; + psa_hmac_internal_data backup = MBEDTLS_PSA_HMAC_OPERATION_INIT; psa_status_t status, cleanup_status; /* We can't be wanting more output after block 0xff, otherwise @@ -3400,7 +3400,7 @@ static psa_status_t psa_key_derivation_tls12_prf_generate_next_block( /* Save the hash context before using it, to preserve the hash state with * only the inner padding in it. We need this, because inner padding depends * on the key (secret in the RFC's terminology). */ - status = psa_hash_clone( &tls12_prf->hmac.hash_ctx, &backup ); + status = psa_hmac_clone_internal( &tls12_prf->hmac, &backup ); if( status != PSA_SUCCESS ) goto cleanup; @@ -3410,20 +3410,22 @@ static psa_status_t psa_key_derivation_tls12_prf_generate_next_block( /* A(1) = HMAC_hash(secret, A(0)), where A(0) = seed. (The RFC overloads * the variable seed and in this instance means it in the context of the * P_hash function, where seed = label + seed.) */ - status = psa_hash_update( &tls12_prf->hmac.hash_ctx, - tls12_prf->label, tls12_prf->label_length ); + status = psa_hmac_update_internal( &tls12_prf->hmac, + tls12_prf->label, + tls12_prf->label_length ); if( status != PSA_SUCCESS ) goto cleanup; - status = psa_hash_update( &tls12_prf->hmac.hash_ctx, - tls12_prf->seed, tls12_prf->seed_length ); + status = psa_hmac_update_internal( &tls12_prf->hmac, + tls12_prf->seed, + tls12_prf->seed_length ); if( status != PSA_SUCCESS ) goto cleanup; } else { /* A(i) = HMAC_hash(secret, A(i-1)) */ - status = psa_hash_update( &tls12_prf->hmac.hash_ctx, - tls12_prf->Ai, hash_length ); + status = psa_hmac_update_internal( &tls12_prf->hmac, + tls12_prf->Ai, hash_length ); if( status != PSA_SUCCESS ) goto cleanup; } @@ -3432,35 +3434,35 @@ static psa_status_t psa_key_derivation_tls12_prf_generate_next_block( tls12_prf->Ai, hash_length ); if( status != PSA_SUCCESS ) goto cleanup; - status = psa_hash_clone( &backup, &tls12_prf->hmac.hash_ctx ); + status = psa_hmac_clone_internal( &backup, &tls12_prf->hmac ); if( status != PSA_SUCCESS ) goto cleanup; /* Calculate HMAC_hash(secret, A(i) + label + seed). */ - status = psa_hash_update( &tls12_prf->hmac.hash_ctx, - tls12_prf->Ai, hash_length ); + status = psa_hmac_update_internal( &tls12_prf->hmac, + tls12_prf->Ai, hash_length ); if( status != PSA_SUCCESS ) goto cleanup; - status = psa_hash_update( &tls12_prf->hmac.hash_ctx, - tls12_prf->label, tls12_prf->label_length ); + status = psa_hmac_update_internal( &tls12_prf->hmac, + tls12_prf->label, tls12_prf->label_length ); if( status != PSA_SUCCESS ) goto cleanup; - status = psa_hash_update( &tls12_prf->hmac.hash_ctx, - tls12_prf->seed, tls12_prf->seed_length ); + status = psa_hmac_update_internal( &tls12_prf->hmac, + tls12_prf->seed, tls12_prf->seed_length ); if( status != PSA_SUCCESS ) goto cleanup; status = psa_hmac_finish_internal( &tls12_prf->hmac, tls12_prf->output_block, hash_length ); if( status != PSA_SUCCESS ) goto cleanup; - status = psa_hash_clone( &backup, &tls12_prf->hmac.hash_ctx ); + status = psa_hmac_clone_internal( &backup, &tls12_prf->hmac ); if( status != PSA_SUCCESS ) goto cleanup; cleanup: - cleanup_status = psa_hash_abort( &backup ); + cleanup_status = psa_hmac_abort_internal( &backup ); if( status == PSA_SUCCESS && cleanup_status != PSA_SUCCESS ) status = cleanup_status; @@ -3806,8 +3808,8 @@ static psa_status_t psa_hkdf_input( psa_hkdf_key_derivation_t *hkdf, } if( hkdf->state != HKDF_STATE_STARTED ) return( PSA_ERROR_BAD_STATE ); - status = psa_hash_update( &hkdf->hmac.hash_ctx, - data, data_length ); + status = psa_hmac_update_internal( &hkdf->hmac, + data, data_length ); if( status != PSA_SUCCESS ) return( status ); status = psa_hmac_finish_internal( &hkdf->hmac, diff --git a/library/psa_crypto_mac.c b/library/psa_crypto_mac.c index 72386d873e..5a7bc2c86a 100644 --- a/library/psa_crypto_mac.c +++ b/library/psa_crypto_mac.c @@ -139,6 +139,13 @@ cleanup: return( status ); } +psa_status_t psa_hmac_update_internal( psa_hmac_internal_data *hmac, + const uint8_t *data, + size_t data_length ) +{ + return( psa_hash_update( &hmac->hash_ctx, data, data_length ) ); +} + psa_status_t psa_hmac_finish_internal( psa_hmac_internal_data *hmac, uint8_t *mac, size_t mac_size ) @@ -176,6 +183,22 @@ exit: mbedtls_platform_zeroize( tmp, hash_size ); return( status ); } + +psa_status_t psa_hmac_clone_internal( const psa_hmac_internal_data *source, + psa_hmac_internal_data *destination ) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + destination->alg = source->alg; + destination->hash_ctx = psa_hash_operation_init(); + status = psa_hash_clone( &source->hash_ctx, &destination->hash_ctx ); + memcpy( destination->opad, source->opad, sizeof( destination->opad ) ); + + if( status != PSA_SUCCESS ) + memset( destination, 0, sizeof( *destination ) ); + + return( status ); +} #endif /* MBEDTLS_PSA_BUILTIN_ALG_HMAC || PSA_CRYPTO_DRIVER_TEST */ /* Implement the PSA driver MAC interface on top of mbed TLS if either the diff --git a/library/psa_crypto_mac.h b/library/psa_crypto_mac.h index d923511605..6a5629618d 100644 --- a/library/psa_crypto_mac.h +++ b/library/psa_crypto_mac.h @@ -23,15 +23,93 @@ #include <psa/crypto.h> +/** Internal API for starting an HMAC operation, using PSA hash primitives. + * + * \note This API is not meant for application use. Applications should always + * use the top-level psa_mac_xxx APIs for doing HMAC operations. + * + * \param[in] hmac Context structure for this HMAC operation. Needs to have + * been zero-initialized prior to calling this function. + * \param[in] key Key to initialize the HMAC operation with. + * \param key_length Length (in bytes) of key \p key. + * \param hash_alg Hash algorithm to use for calculating the HMAC. + * + * \retval #PSA_SUCCESS + * Success. + * \return Any error code reported by psa_hash_compute(), psa_hash_setup() or + * psa_hash_update(). + */ psa_status_t psa_hmac_setup_internal( psa_hmac_internal_data *hmac, const uint8_t *key, size_t key_length, psa_algorithm_t hash_alg ); +/** Internal API for adding data to an HMAC operation, using PSA hash primitives. + * + * \note This API is not meant for application use. Applications should always + * use the top-level psa_mac_xxx APIs for doing HMAC operations. + * + * \param[in] hmac Context structure for this HMAC operation. Needs to have + * been initialized with psa_hmac_setup_internal(). + * \param[in] data Buffer containing the data to add to the current HMAC + * calculation. + * \param data_length Length (in bytes) of the input buffer \p data. + * + * \retval #PSA_SUCCESS + * Success. + * \return Any error code reported by psa_hash_update(). + */ +psa_status_t psa_hmac_update_internal( psa_hmac_internal_data *hmac, + const uint8_t *data, + size_t data_length ); + +/** Internal API for finalizing an HMAC operation, using PSA hash primitives. + * + * \note This API is not meant for application use. Applications should always + * use the top-level psa_mac_xxx APIs for doing HMAC operations. + * + * \param[in] hmac Context structure for this HMAC operation. Needs to have + * been initialized with psa_hmac_setup_internal(). + * \param[out] mac Buffer to output the calculated HMAC into. + * \param mac_size Size (in bytes) of the output buffer \p mac. + * + * \retval #PSA_SUCCESS + * Success. + * \return Any error code reported by psa_hash_setup(), psa_hash_update() or + * psa_hash_finish(). + */ psa_status_t psa_hmac_finish_internal( psa_hmac_internal_data *hmac, uint8_t *mac, size_t mac_size ); +/** Internal API for cloning an HMAC operation, using PSA hash primitives. + * + * \note This API is not meant for application use. Applications should always + * use the top-level psa_mac_xxx APIs for doing HMAC operations. + * + * \param[in] source Context structure to clone from. Needs to have been + * initialized with psa_hmac_setup_internal(). + * \param[out] destination Context structure to clone to. Needs to have been + * zero-initialized. + * + * \retval #PSA_SUCCESS + * Success. + * \return Any error code reported by psa_hash_clone(). + */ +psa_status_t psa_hmac_clone_internal( const psa_hmac_internal_data *source, + psa_hmac_internal_data *destination ); + +/** Internal API for aborting an HMAC operation, using PSA hash primitives. + * + * \note This API is not meant for application use. Applications should always + * use the top-level psa_mac_xxx APIs for doing HMAC operations. + * + * \param[in] hmac Context structure for the HMAC operation to abort. + * + * \retval #PSA_SUCCESS + * Success. + * \return Any error code reported by psa_hash_abort(). + */ psa_status_t psa_hmac_abort_internal( psa_hmac_internal_data *hmac ); /** Calculate the MAC (message authentication code) of a message using Mbed TLS.