Complete, document and fully use internal HMAC API

Since HMAC moved into its own compilation unit, the internal API needed
to be documented and finalized. This means no more reaching deep into
the operation structure from within the PSA Crypto core. This will make
future refactoring work easier, since internal HMAC is now opaque to the
core.

Signed-off-by: Steven Cooreman <steven.cooreman@silabs.com>
This commit is contained in:
Steven Cooreman 2021-03-22 12:21:10 +01:00
parent 7515e7535d
commit 4fdf060a81
4 changed files with 132 additions and 27 deletions

View File

@ -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"

View File

@ -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,

View File

@ -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

View File

@ -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.