Bootloader crypto

The bootloader crypto library is the cryptography library that is used by the nRF Secure Immutable Bootloader.

The API is public because applications that are booted by the immutable bootloader can call functions from this library via the bootloader’s code, through external APIs. See External APIs for more information.

The library provides the following functionality:

  • SHA256 hashing

  • SECP256R1 signature validation

  • Root-of-trust firmware validation, which is the function the bootloader uses to validate a firmware’s signature and digest, using the SHA256 and SECP256R1 algorithms

These functions are available as separate external APIs. The API can be used the same way regardless of which backend is used.

Backends

When using the library, you can choose between the following backends:

  • Hardware backend nrf_cc310_bl crypto library (can only be used if Arm CryptoCell CC310 is available)

  • Software backend nrf_oberon crypto library

  • Another image’s instance of the bootloader crypto library, called via external APIs. The other image chooses its own backend.

To configure which backend is used for hashing, set one of the following configuration options:

To configure which backend is used for firmware verification, set one of the following configuration options:

API documentation

Header file: include/bl_crypto.h
Source files: subsys/bootloader/bl_crypto/ and subsys/bootloader/bl_crypto_client/
group bl_crypto

Defines

EHASHINV
ESIGINV
SHA256_CTX_SIZE

Typedefs

typedef uint32_t bl_sha256_ctx_t[128 / 4]
typedef int (*bl_root_of_trust_verify_t)(const uint8_t *public_key, const uint8_t *public_key_hash, const uint8_t *signature, const uint8_t *firmware, const uint32_t firmware_len)
typedef int (*bl_sha256_init_t)(bl_sha256_ctx_t *ctx)
typedef int (*bl_sha256_update_t)(bl_sha256_ctx_t *ctx, const uint8_t *data, uint32_t data_len)
typedef int (*bl_sha256_finalize_t)(bl_sha256_ctx_t *ctx, uint8_t *output)
typedef int (*bl_sha256_verify_t)(const uint8_t *data, uint32_t data_len, const uint8_t *expected)
typedef int (*bl_secp256r1_validate_t)(const uint8_t *hash, uint32_t hash_len, const uint8_t *signature, const uint8_t *public_key)

Functions

int bl_crypto_init(void)

Initialize bootloader crypto module.

Returns 0

On success.

Returns -EFAULT

If crypto module reported an error.

int bl_root_of_trust_verify(const uint8_t *public_key, const uint8_t *public_key_hash, const uint8_t *signature, const uint8_t *firmware, const uint32_t firmware_len)

Verify a signature using configured signature and SHA-256.

Verifies the public key against the public key hash, then verifies the hash of the signed data against the signature using the public key.

Remark

No parameter can be NULL.

Parameters
  • public_key[in] Public key.

  • public_key_hash[in] Expected hash of the public key. This is the root of trust.

  • signature[in] Firmware signature.

  • firmware[in] Firmware.

  • firmware_len[in] Length of firmware.

Returns 0

On success.

Returns -EHASHINV

If public_key_hash didn’t match public_key.

Returns -ESIGINV

If signature validation failed.

Returns

Any error code from bl_sha256_init, bl_sha256_update, bl_sha256_finalize, or bl_secp256r1_validate if something else went wrong.

int bl_root_of_trust_verify_external(const uint8_t *public_key, const uint8_t *public_key_hash, const uint8_t *signature, const uint8_t *firmware, const uint32_t firmware_len)

Implementation of rot_verify that is safe to be called from EXT_API.

See bl_root_of_trust_verify for docs.

int bl_sha256_init(bl_sha256_ctx_t *ctx)

Initialize a sha256 operation context variable.

Parameters
  • ctx[out] Context to be initialized.

Returns 0

On success.

Returns -EINVAL

If ctx was NULL.

int bl_sha256_update(bl_sha256_ctx_t *ctx, const uint8_t *data, uint32_t data_len)

Hash a portion of data.

Warning

ctx must be initialized before being used in this function. An uninitialized ctx might not be reported as an error. Also, ctx must not be used if it has been finalized, though this might also not be reported as an error.

Parameters
  • ctx[in] Context variable. Must have been initialized.

  • data[in] Data to hash.

  • data_len[in] Length of data.

Returns 0

On success.

Returns -EINVAL

If ctx was NULL, uninitialized, or corrupted.

Returns -ENOSYS

If the context has already been finalized.

int bl_sha256_finalize(bl_sha256_ctx_t *ctx, uint8_t *output)

Finalize a hash result.

Parameters
  • ctx[in] Context variable.

  • output[out] Where to put the resulting digest. Must be at least 32 bytes long.

Returns 0

On success.

Returns -EINVAL

If ctx was NULL or corrupted, or output was NULL.

int bl_sha256_verify(const uint8_t *data, uint32_t data_len, const uint8_t *expected)

Calculate a digest and verify it directly.

Parameters
  • data[in] The data to hash.

  • data_len[in] The length of data.

  • expected[in] The expected digest over data.

Returns 0

If the procedure succeeded and the resulting digest is identical to expected.

Returns -EHASHINV

If the procedure succeeded, but the digests don’t match.

Returns

Any error code from bl_sha256_init, bl_sha256_update, or bl_sha256_finalize if something else went wrong.

int bl_secp256r1_validate(const uint8_t *hash, uint32_t hash_len, const uint8_t *signature, const uint8_t *public_key)

Validate a secp256r1 signature.

Parameters
  • hash[in] The hash to validate against.

  • hash_len[in] The length of the hash.

  • signature[in] The signature to validate.

  • public_key[in] The public key to validate with.

Returns 0

The operation succeeded and the signature is valid for the hash.

Returns -EINVAL

A parameter was NULL, or the hash_len was not 32 bytes.

Returns -ESIGINV

The signature validation failed.

struct bl_rot_verify_ext_api
#include <bl_crypto.h>

Structure describing the BL_ROT_VERIFY EXT_API.

struct bl_sha256_ext_api
#include <bl_crypto.h>

Structure describing the BL_SHA256 EXT_API.

struct bl_secp256r1_ext_api
#include <bl_crypto.h>

Structure describing the BL_SECP256R1 EXT_API.