nRF5 SDK v17.0.2
HMAC - Hash-based message authentication code

Hash-based message authentication code (HMAC) is a mechanism for message authentication using a cryptographic hash function and a secret key. The algorithm takes a key and data of any length as input, and produces HMAC code with length defined by the underlying hash function. The HMAC standard is described in RFC 2104.

The nrf_crypto HMAC module supports SHA-256 and SHA-512.

HMAC frontend

The HMAC frontend (Hash-based message authentication code (HMAC) related functions) provide a common API that is independent of the backends. The application has control of the memory usage, as the work memory is part of the context structure that is provided to the HMAC API. This is a thin wrapper layer that provides input validation and normalization of the backend APIs.

Available backends

The following backends can be used for HMAC:

For information on configuring the backends, see Configuring nrf_crypto frontend and backends. It is possible to use a different backend for each hash. The following configuration defines are used to enable backend support for specific modes in the sdk_config file.

Hash Backend Implementation Enable define
SHA-256 CC310 Hardware NRF_CRYPTO_BACKEND_CC310_HMAC_SHA256_ENABLED
Oberon Software NRF_CRYPTO_BACKEND_OBERON_HMAC_SHA256_ENABLED
mbed TLS Software NRF_CRYPTO_BACKEND_MBEDTLS_HMAC_SHA256_ENABLED
SHA-512 CC310 Software NRF_CRYPTO_BACKEND_CC310_HMAC_SHA512_ENABLED
Oberon Software NRF_CRYPTO_BACKEND_OBERON_HMAC_SHA512_ENABLED
mbed TLS Software NRF_CRYPTO_BACKEND_MBEDTLS_HMAC_SHA512_ENABLED
Note
The CC310 implementation of SHA-512 is software based, and slower than the other supported backends. It is therefore not recommended to use CC310 for SHA-512.

HMAC usage

The most flexible way of using the HMAC module is using the nrf_crypto_init, nrf_crypto_hmac_update, and nrf_crypto_hmac_finalize functions. This allows processing data as it becomes available by repeatedly calling nrf_crypto_hmac_update.

  1. Enable nrf_crypto backed for HMAC in SDK configuration header file.
  2. Initialize nrf_crypto using nrf_crypto_init.
  3. Create a context of type nrf_crypto_hmac_context_t. This must be valid for the duration of the calculation.
  4. Initialize the context by providing a pointer to the key and a pointer to the constant info structure that defines the hash type. The info structure is either g_nrf_crypto_hmac_sha256_info for SHA-256 or g_nrf_crypto_hmac_sha512_info for SHA-512.
  5. Feed message data to the HMAC algorithm by calling nrf_crypto_hmac_update. This can be called repeatedly.
  6. Finalize the HMAC calculation using nrf_crypto_hmac_finalize. This will populate the digest buffer with the calculated HMAC. The digest length in bytes is nrf_hash_type_t:NRF_CRYPTO_HASH_SIZE_SHA256 for SHA-256 or nrf_hash_type_t:NRF_CRYPTO_HASH_SIZE_SHA512 for SHA-512.

The following example code demonstrates how to calculate HMAC SHA-256.

uint8_t data[] = {0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65};
uint8_t key[] = {0x6b, 0x65, 0x79};
uint8_t digest[NRF_CRYPTO_HASH_SIZE_SHA256];
size_t digest_len = sizeof(digest);
uint32_t err_code;
// Initialize crypto library before using any crypto functionality.
err_code = nrf_crypto_init();
APP_ERROR_CHECK(err_code);
// Initialize context, prividing the key and pointer to info structure.
err_code = nrf_crypto_hmac_init(&context,
key,
sizeof(key));
APP_ERROR_CHECK(err_code);
// Push message data.
err_code = nrf_crypto_hmac_update(&context, data, sizeof(data));
APP_ERROR_CHECK(err_code);
// Finish calculation.
err_code = nrf_crypto_hmac_finalize(&context, digest, &digest_len);
APP_ERROR_CHECK(err_code);

There is an integrated version of the HMAC frontend, nrf_crypto_hmac_calculate, which can be used when all data is available up front. The context is optional in this case, and is allocated internally using the Dynamic memory management module if the first parameter is set to NULL. The following example code demonstrates how to do the same calculation using the integrated function with internally allocated context memory.

NULL, // Context pointer..
&g_nrf_crypto_hmac_sha256_info, // Pointer to global info structure.
m_digest, // Pointer to digest (result) buffer.
&digest_len, // Updated during call.
m_key, // Pointer to key buffer.
sizeof(m_key), // Length of key.
m_data, // Pointer to input data buffer.
sizeof(m_data)); // Length of input data.

HMAC example project

Refer to HMAC Example for a usage example of this library.

For an example showing the verification procedure of HMAC, see Test Example.


Documentation feedback | Developer Zone | Subscribe | Updated