nRF5 SDK v13.0.0
Cryptography library

The cryptography library provides functions that implement several variants of public key cryptography. These cryptography functions are required for the BLE Secure DFU Bootloader. You can also include the library in your application (independently of the bootloader). The implementation can use different backends.

Note
The API of the library has changed in nRF5 SDK v13.0.0. If you have used the library before, you must update your code. Note that the implementation of the library in nRF5 SDK v13.0.0-1.alpha is not final and more changes might be required.

The cryptographic functionality that is supported depends on the backend that is used. All backends support the following cryptographic schemes:

In addition, the library can be used to calculate a hash (or digest) of the input data, based on a SHA-1 or SHA-2 family cryptographic hash algorithm.

Signing concepts

If you plan to use the cryptography library, you should familiarize yourself with the general concepts of asymmetric cryptography. The following concepts are important to know:

Signature

A digital signature attests the authenticity of a set of data. Usually, it contains a signed hash or digest of the same data. The recipient of the data can then verify the signature by hashing the data and comparing the hash to the one obtained from the signature.

The signature is generated using a private key and a hashing algorithm. It can be verified using a public key.

Private key

A private key (also called signing key in the context of ECDSA) is a key that identifies its owner. You should never share your private key with anybody. When you use it to sign data, you affirm that the data is yours, because no one else knows the private key that is required for signing.

To be understood by the cryptography library, private keys must be based on one of the curves defined in NRF_CRYPTO_CURVES. See Backends for an overview of which of these curves are supported by the different backends.

Public key

A public key (also called verification key in the context of ECDSA) is openly available and can be used to verify the input data based on the signature and the hash of the input data.

The public key is calculated based on the private key. This means that if you plan to send signed data, you must create a public key and share it with the recipient so that the recipient can verify the signature.

Shared secret

A shared secret, or a shared key, is a key that is known only to the involved parties. The shared secret can be negotiated over an insecure channel between parties that each have a public-private key pair. After the shared secret is calculated on both sides, it can be used to encrypt communication between the parties.

Shared secrets are currently not used in secure DFU, but they can be used in different contexts (for example, they are required for Bluetooth LE Secure Connections).

Working with keys

The cryptography library requires private and public keys. A public key can be computed from a private key, but the private key must always be provided.

If your keys should be valid for only one device or even only one connection, you can generate them at run time. Simply generate a random number as private key and compute the corresponding public key by calling nrf_crypto_ecc_public_key_calculate.

If you need static keys for use on multiple devices, you should generate the keys externally. The following example commands use Nordic Semiconductor's nrfutil tool (see the nrfutil documentation) to generate keys based on the secp256r1 curve:

# Generate a private key in c:\vault\priv.pem
nrfutil keys generate c:\vault\priv.pem
# Display the generated private key (in little-endian format)
nrfutil keys display --key sk --format hex c:\vault\priv.pem
# Display the generated private key (in code format to be
# used with nrf_crypto)
nrfutil keys display --key sk --format code c:\vault\priv.pem
# Display the public key that corresponds to the generated private key
# (in little-endian format)
nrfutil keys display --key pk --format hex c:\vault\priv.pem
# Display the public key that corresponds to the generated private key
# (in code format to be used with nrf_crypto)
nrfutil keys display --key pk --format code c:\vault\priv.pem
# Write the public key that corresponds to the generated private key
# to the file public_key.c (in code format)
nrfutil keys display --key pk --format code c:\vault\priv.pem --out_file public_key.c

You can also generate keys using OpenSSL. See the OpenSSL documentation for instructions on how to generate a private key. Issue the following command to display the contents of the .pem key file:

openssl ec -in c:\safe\priv.pem -text -noout

This command will display both the private and the public key in big-endian format. To use these keys with the cryptography library, you must reverse the byte order. Also, the public key will be prefixed by a byte with the value "0x04", which you should ignore.

Make sure to store the private key securely and with limited access. If the private key is lost, you cannot reproduce it and therefore cannot provide signed data anymore.

Backends

The cryptography library provides one common API that can be used with different backends. Currently, two backends are available: a pure software backend that uses a well-known open source library (micro-ecc) and a hardware-accelerated backend (CryptoCell).

The software backend is compatible with all supported SoCs. Before you can use it, you must install the micro-ecc library. See Software backend (micro-ecc) for more information about this backend.

The hardware-accelerated backend is faster, consumes less power, and offers more functionality. Using the hardware-accelerated backend also decreases the size of the application. However, this backend requires hardware support and is therefore available only on the nRF52840 SoC. See Hardware-accelerated backend (CryptoCell) for more information about this backend.

The following table shows which cryptographic curves are supported by which backend:

Cryptographic curve Software backend Hardware-accelerated backend
NRF_CRYPTO_CURVE_SECP160R1 -
NRF_CRYPTO_CURVE_SECP192R1 -
NRF_CRYPTO_CURVE_SECP224R1 -
NRF_CRYPTO_CURVE_SECP256R1
NRF_CRYPTO_CURVE_SECP384R1 -
NRF_CRYPTO_CURVE_SECP521R1 -
NRF_CRYPTO_CURVE_SECP192K1 -
NRF_CRYPTO_CURVE_SECP224K1 -
NRF_CRYPTO_CURVE_SECP256K1 -

See Recommended elliptic curves for federal government use, SEC 2: Recommended Elliptic Curve Domain Parameters, and other sources for detailed information about this curves.

The following table shows which hashing algorithms are supported by which backend:

Hashing algorithm Software backend Hardware-accelerated backend
NRF_CRYPTO_HASH_TYPE_MD5 -
NRF_CRYPTO_HASH_TYPE_SHA1 -
NRF_CRYPTO_HASH_TYPE_SHA224 -
NRF_CRYPTO_HASH_TYPE_SHA256
NRF_CRYPTO_HASH_TYPE_SHA384 -
NRF_CRYPTO_HASH_TYPE_SHA512 -

Software backend (micro-ecc)

micro-ecc is an open source library that performs cryptographic operations. It is optimized for small program size while maintaining high processing speed. The micro-ecc backend supports all current nRF5 Series devices.

When using micro-ecc, you must ensure compliance with the license of the library as stated in the LICENSE.txt file that is included in micro-ecc.

The cryptography library expects to find the compiled micro-ecc library in InstallFolder\external\micro-ecc\micro-ecc.

To install micro-ecc, complete the following steps:

  1. Install version 4.9-2015-q3-update of the GCC compiler toolchain for ARM. You can use ARM's Launchpad to find the toolchain for your operating system.
  2. Make sure that make is installed (see, for example, MinGW, GNU Make, or Xcode).
  3. Clone the micro-ecc GitHub repository into InstallFolder\external\micro-ecc\micro-ecc.
  4. Enter the subdirectory for the SoC and the toolchain that you are using to build your application:
    • InstallFolder\external\micro-ecc\nrf52_keil\armgcc
    • InstallFolder\external\micro-ecc\nrf52_iar\armgcc
    • InstallFolder\external\micro-ecc\nrf52_armgcc\armgcc
  5. Run make to compile the micro-ecc library.
Note
If you compile the micro-ecc library without using the provided Makefiles, make sure to use the default compilation options with -Os and optimization level 3. If you change the preprocessor macros (most importantly, uECC_VLI_NATIVE_LITTLE_ENDIAN=1), the library might not work properly.

The micro-ecc library does not support hashing or random number generation. However, when you use the micro-ecc backend, you can enable software implementations for this functionality separately.

Hardware-accelerated backend (CryptoCell)

This information applies to the nRF52840 SoC only.

The hardware-accelerated backend uses cryptography hardware to perform cryptographic operations. The required CryptoCell hardware is available on the nRF52840 SoC, but not on the nRF52832 SoC. See the nRF52840 Product Specification for detailed information about CryptoCell.

Applications that use the hardware-accelerated backend usually consume less power and are faster and smaller in size than applications that use the software backend. Therefore, you should use the CryptoCell backend on devices that support it.

CryptoCell provides more functionality than what is currently supported by the cryptography library. If you require advanced cryptographic operations, use the CryptoCell API directly. See the CryptoCell API documentation for an overview of all available objects and functions. To get started, see the Experimental: CryptoCell examples.

Selecting the backend

You select the backend that you want to use in the SDK configuration header file of your project.

To use the cryptography library with the software backend, ensure that you have installed the micro-ecc library. Then enable the following modules:

To use the cryptography library with the hardware-accelerated backend, enable the following modules:

See the BLE Secure DFU Bootloader as an example for an application that uses the software backend. The Experimental: LE Secure Connections Multirole Example uses the hardware-accelerated backend.

Library usage

Before you use the cryptography library, run nrf_crypto_init to initialize it.

To create a public key from a private key, call nrf_crypto_ecc_public_key_calculate and specify which curve to use. This public key should be shared with other applications to enable them to verify signed data. Remember though that you should not share your private key, so calculating public keys in an application can be a risk.

Note
The format of private and public keys depends on the backend that you use. Therefore, if you want to send a public key to another device, store it so it can be used by other modules, or use in functions outside of this module, you should convert it to raw format to make sure it can be understood. To do so, use the functions nrf_crypto_ecc_private_key_to_raw and nrf_crypto_ecc_public_key_to_raw. When working with a public key that you retrieved from flash, from another module, or from another device, use nrf_crypto_ecc_public_key_from_raw to convert it to the format that is used by the cryptography library.

To sign data, first call nrf_crypto_hash_compute and specify which hashing algorithm to use. This function creates a hash (or digest) of the data. Next, create a signature for the hash by calling nrf_crypto_ecdsa_sign_hash with your private key and the curve that you want to use as input. To verify the signature, the other application must first calculate the hash of the data (using nrf_crypto_hash_compute) and then call nrf_crypto_ecdsa_verify_hash with the computed hash and your public key as input.

To calculate a shared secret between two applications, each application must call nrf_crypto_ecdh_shared_secret_compute with their own private key and the other application's public key as input.


Documentation feedback | Developer Zone | Subscribe | Updated