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>
diff --git a/include/psa/crypto_builtin_composites.h b/include/psa/crypto_builtin_composites.h
index fd7f6f9..2fb0633 100644
--- a/include/psa/crypto_builtin_composites.h
+++ b/include/psa/crypto_builtin_composites.h
@@ -53,6 +53,8 @@
/** 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 3ca8c9d..0ef73df 100644
--- a/library/psa_crypto.c
+++ b/library/psa_crypto.c
@@ -3331,19 +3331,19 @@
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 @@
{
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 @@
/* 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 @@
/* 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 @@
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 @@
}
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 72386d8..5a7bc2c 100644
--- a/library/psa_crypto_mac.c
+++ b/library/psa_crypto_mac.c
@@ -139,6 +139,13 @@
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 @@
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 d923511..6a56296 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.