Hardware unique key

The hardware unique key library manages symmetric root keys on devices with the Arm CryptoCell security subsystem.


Hardware unique keys (HUKs) are device-specific keys that you can use with functions for key derivation to generate other keys. Applications can use the generated keys for symmetric cryptographic operations. By using HUKs, you can let your application use multiple keys without having to store them on the device, as they can be derived from a HUK, using a static label, when needed.


Use hardware unique keys only for key derivation, never directly for symmetric cryptographic operations.

The library supports 3 different types of HUKs, depending on the device:

  • Device root key (KDR). It is used for deriving general-purpose keys. In devices with the Arm CryptoCell CC310, it must be written to a specific KDR register during the boot process, using the hw_unique_key_load_kdr() function. The nRF Secure Immutable Bootloader does this automatically if you enable CONFIG_HW_UNIQUE_KEY in the bootloader image.

  • Master key encryption key (MKEK). It is used for deriving Key Encryption Keys (KEKs), which are used to encrypt other keys when these are stored. It is provided to CryptoCell when it is used.

  • Master key for encrypting external storage (MEXT). It is used to derive keys for encrypting data in external non-secure storage. It is provided to CryptoCell when it is used.

See the following table for an overview of the key types supported by each device:


CryptoCell version

Key Management Unit

Supported HUK types

nRF91 Series











KDR only

In devices with a Key Management Unit (KMU), like nRF91 Series or nRF5340, the keys reside in reserved slots in the KMU itself. The KMU can make the keys non-readable and non-writable from the application, while still accessible by the Arm CryptoCell.

In devices without a KMU, like nRF52840, the bootloader writes the key to the Arm CryptoCell and locks the flash memory page where the key is stored. In this case, only one key is supported.


To use hardware unique keys, you must first write them to the KMU or program them in the device firmware if no KMU is present. You can also write the HUKs by programming the device with a debugger. See tests/lib/hw_unique_key_tfm/write_kmu.py for an example of programming the KMU with a debugger.


The library provides a function for writing arbitrary keys and a function for writing random keys.

To use the library, enable the CONFIG_HW_UNIQUE_KEY option for the nRF Secure Immutable Bootloader image. Additionally, you can enable the CONFIG_HW_UNIQUE_KEY_RANDOM option to enable the hw_unique_key_write_random() function and its dependencies, to generate random keys.

See Configuring and building an application for information on how to enable the required configuration options.

You can then use the HUKs through the APIs in the CC3xx platform libraries. You can also derive a key using hw_unique_key_derive_key().


It is strongly recommended to generate random keys on-chip to avoid any outside knowledge of the keys. If the application needs a specific key that the manufacturer also knows, and this key is also unique to the device, do not provide such a key as a HUK. Instead, encrypt this key with another key derived from a hardware unique key, or store it in its own KMU slot.

API documentation

Header file: include/hw_unique_key.h
Source files: modules/lib/hw_unique_key/
group hw_unique_key

API for loading the Hardware Unique Key (HUK).

   The library supports loading the HUK:
       - To CryptoCell KDR registers.
       - To Cracen SEED registers.



Error value when the hardware unique key is missing.


Error value when writing the hardware unique key failed.


Error value when the generation of the hardware unique key failed.


Error value when key derivation using the hardware unique key failed.


Error value when the hardware unique key had a generic failure.


Return code for success.



enum hw_unique_key_slot


enumerator HUK_KEYSLOT_KDR


int hw_unique_key_write(enum hw_unique_key_slot key_slot, const uint8_t *key)

Write a Hardware Unique Key to the KMU.

This can only be done once (until a mass erase happens). This function waits for the flash operation to finish before returning.

  • key_slot[in] The keyslot to write to, see HUK_KEYSLOT_*.

  • key[in] The key to write. Must be HUK_SIZE_BYTES bytes long.


HW_UNIQUE_KEY_SUCCESS on success, otherwise a negative hardware unique key error code

int hw_unique_key_write_random(void)

Read random numbers from nrf_cc3xx_platform_ctr_drbg_get and write them to all slots with hw_unique_key_write.


HW_UNIQUE_KEY_SUCCESS on success, otherwise a negative hardware unique key error code

bool hw_unique_key_is_written(enum hw_unique_key_slot key_slot)

Check whether a Hardware Unique Key has been written to the KMU.

  • key_slot[in] The keyslot to check, see HUK_KEYSLOT_*.

Return values:
  • true – if a HUK has been written to the specified keyslot,

  • false – otherwise.

bool hw_unique_key_are_any_written(void)

Check whether any Hardware Unique Keys are written to the KMU.

Return values:
  • true – if one or more HUKs are written

  • false – if all HUKs are unwritten.

int hw_unique_key_load_kdr(void)

Load the Hardware Unique Key (HUK) into the KDR registers of the Cryptocell.

It also locks the flash page which contains the key material from reading and writing until the next reboot.


HW_UNIQUE_KEY_SUCCESS on success, otherwise a negative hardware unique key error code

int hw_unique_key_derive_key(enum hw_unique_key_slot key_slot, const uint8_t *context, size_t context_size, uint8_t const *label, size_t label_size, uint8_t *output, uint32_t output_size)

Derive a key from the specified HUK, using the nrf_cc3xx_platform API on CryptoCell. Cracen PSA driver APIs on Cracen.

See nrf_cc3xx_platform_kmu_shadow_key_derive() for more info.

  • key_slot[in] Keyslot to derive from.

  • context[in] Context for key derivation.

  • context_size[in] Size of context.

  • label[in] Label for key derivation.

  • label_size[in] Size of label.

  • output[out] The derived key.

  • output_size[in] Size of output.


HW_UNIQUE_KEY_SUCCESS on success, otherwise a negative hardware unique key error code