nRF5 SDK v17.1.0
ECC - Elliptic Curve Cryptography

An Elliptic Curve Cryptography is a set of asymmetric cryptography algorithms. It uses private and public keys that are related to each other and create a key pair.

For detailed API documentation of this module, see Elliptic Curve Cryptography Key Management.

Key Management

A private key is known only to the owner. It cannot be shared with anyone. Leaking a private key causes serious security issues for products that use such a key. From the technical point of view, a private key is a random big integer (for example, 256-bit long) that fulfills the constraints defined by the curve parameters.

A public key can be shared with anyone. It is generated from a private key. This operation is one way, so it is computationally infeasible to compute a private key from a public key. From the technical point of view, a public key is a point on the elliptic curve over finite field, so it consists of x and y coordinates (or only one coordinate in case of Curve25519 and Ed25519). Each coordinate is a big integer with the same size as the associated private key.

A key pair is associated with a specific curve type and can be used only for the curve that it was created for. See Backends for a list of curve types supported by this library. A key pair is used for both ECDSA - Elliptic Curve Digital Signature Algorithm and ECDH - Elliptic Curve Diffie–Hellman.

API

In this library:

The library allows for conversion between this internal representation and raw format, which is an array of bytes containing two big integers in big-endian order or one integer in little-endian order in case of Curve25519 and Ed25519. Array types nrf_crypto_ecc_raw_private_key_t and nrf_crypto_ecc_raw_public_key_t are big enough to hold a raw key for any of the enabled curve types. There are also curve-specific types, for example nrf_crypto_ecc_secp256r1_private_key_t or nrf_crypto_ecc_secp256r1_raw_private_key_t that can be used to reduce memory consumption. See Memory saving for more details.

A public key and a private key can be generated using the nrf_crypto library. Use nrf_crypto_ecc_key_pair_generate to generate a key pair or nrf_crypto_ecc_public_key_calculate to only calculate a public key from a known private key. It is not necessary to store the private and public key pair together. A public key can be generated from a private key on demand. This reduces memory usage, but it causes slower access to public key. Use the following functions to run conversions between internal key representation and raw format:

Byte order of all the input and output byte arrays corresponds to the common practice in the ECC cryptography. Curve25519 and Ed25519 use little-endian, while the other curve types use big-endian. The function nrf_crypto_ecc_byte_order_invert can be used to convert between little-endian and big-endian. NRF_CRYPTO_CURVE25519_BIG_ENDIAN_ENABLED option can be set 1 to change the endiannes of Curve25519.

Each function that creates a new key needs a nrf_crypto_ecc_curve_info_t structure. Users should not define the content of this structure. Instead, the library defines it in global variables, such as g_nrf_crypto_ecc_secp256r1_curve_info for secp256r1.

Code examples

Private-public key pair generation:

keygen_context, // Keygen context
&my_private_key, // Output private key
&my_public_key); // Output public key

Public key generation from an existing private key:

err_code = nrf_crypto_ecc_public_key_calculate(&calc_context, // Context
&my_private_key, // Input private key
&my_public_key); // Output public key

Conversion of a raw private key to internal representation:

const uint8_t my_raw_private_key[] = {
0x23, 0x8F, 0x43, 0x88, ... // 32 bytes (256-bits) of raw private key
}
&my_private_key, // Output private key
my_raw_private_key, // Predefined raw private key bytes
sizeof(my_raw_private_key)); // Number of bytes in raw private key

Conversion of internal representation of a public key to a raw public key:

nrf_crypto_ecc_raw_public_key_t output_raw_public_key; // Raw key buffer
size_t raw_key_size = sizeof(output_raw_public_key);
err_code = nrf_crypto_ecc_public_key_to_raw(&public_key, // Public key
output_raw_public_key, // Raw key
&raw_key_size); // Raw size

Private and public keys can also be generated outside of the device using OpenSSL or other similar tools. The following two commands show how OpenSSL can be used to create a priv.pem file with a newly generated key pair and show the content in raw hex format:

openssl ecparam -name secp256r1 -genkey -noout -out priv.pem
openssl ec -in priv.pem -text -noout

Curve name "secp256r1" can be replaced by any other curve name in the above example. OpenSSL uses different naming for brainpool curves: "brainpoolPXYZr1" instead of "bpXYZr1". The public key in OpenSSL output resulting from this command is prefixed by byte '04' and a private key may be prefixed by a zero byte '00', so they must be removed before using the key in the nrf_crypto library.

Backends

The ECC part of the cryptography library uses the following backends to provide public key cryptography:

ECC functionality depends on the selected backend. Function availability is summarized in below table:

API functions CC310 mbed TLS Oberon µECC CC310_BL
nrf_crypto_ecc_key_pair_generate
nrf_crypto_ecc_public_key_calculate
nrf_crypto_ecc_private_key_from_raw
nrf_crypto_ecc_private_key_to_raw
nrf_crypto_ecc_public_key_from_raw
nrf_crypto_ecc_public_key_to_raw
nrf_crypto_ecc_private_key_free 1
nrf_crypto_ecc_public_key_free 1

1 - Key-free functions are implemented only in mbed TLS backend. Other backends have empty functions to keep API compatibility.

Dependencies

RNG - Random Number Generator is required for the nrf_crypto_ecc_key_pair_generate function. It must be correctly configured and initialized before calling the function.

Enabling the curves

Each supported curve type can be independently selected from any of the enabled backends. This can be done using the SDK configuration header file. For example:

#define NRF_CRYPTO_BACKEND_CC310_ENABLED 1 // Enable the CC310 backend.
#define NRF_CRYPTO_BACKEND_CC310_ECC_SECP256R1_ENABLED 1 // Enable secp256r1 curve implementation in the CC310 backend.
#define NRF_CRYPTO_BACKEND_CC310_ECC_SECP521R1_ENABLED 1 // Enable secp521r1 curve implementation in the CC310 backend.
#define NRF_CRYPTO_BACKEND_OBERON_ENABLED 1 // Enable Oberon cryptography library backend.
#define NRF_CRYPTO_BACKEND_OBERON_ECC_CURVE25519_ENABLED 1// Enable Curve25519 signature scheme in the Oberon cryptography library backend.

In this example, users can use curve secp256r1, curve secp521r1, and Curve25519 in their application. Curves secp256r1 and secp521r1 will be realized by the CC310 library and Curve25519 will be realized by the Oberon crypto library.

It is not possible to enable the same curve in two or more backends. This results in a compilation error. For more details, see Configuring nrf_crypto frontend and backends.

Memory saving

The first step to memory saving is to disable all curves that are not used (see Enabling the curves). This allows to remove unused code and reduces the size of some unions. Additionally, backends have different memory requirements, so choosing a different backend can help.

All ECC API (including ECDSA and ECDH) uses types that are big enough to hold data for the biggest curve. In situations in which the exact curve type is known, you can use curve-specific types. Type casting must be done to pass a curve-specific type in a parameter. There is no point in using curve-specific types when only one curve is enabled. The following example table shows types specific to curve secp256r1.

General type secp256r1 type
nrf_crypto_ecc_private_key_t nrf_crypto_ecc_secp256r1_private_key_t
nrf_crypto_ecc_public_key_t nrf_crypto_ecc_secp256r1_public_key_t
nrf_crypto_ecc_raw_private_key_t nrf_crypto_ecc_secp256r1_raw_private_key_t
nrf_crypto_ecc_raw_public_key_t nrf_crypto_ecc_secp256r1_raw_public_key_t
nrf_crypto_ecc_key_pair_generate_context_t nrf_crypto_ecc_secp256r1_key_pair_generate_context_t
nrf_crypto_ecc_public_key_calculate_context_t nrf_crypto_ecc_secp256r1_public_key_calculate_context_t
nrf_crypto_ecdh_context_t nrf_crypto_ecdh_secp256r1_context_t
nrf_crypto_ecdh_shared_secret_t nrf_crypto_ecdh_secp256r1_shared_secret_t
nrf_crypto_ecdsa_signature_t nrf_crypto_ecdsa_secp256r1_signature_t
nrf_crypto_ecdsa_sign_context_t nrf_crypto_ecdsa_secp256r1_sign_context_t
nrf_crypto_ecdsa_verify_context_t nrf_crypto_ecdsa_secp256r1_verify_context_t

The following example demonstrates how to use curve-specific types to hold a newly generated key pair.

ret_code_t err_code;
&keygen_context, // Context
(nrf_crypto_ecc_private_key_t *)&private_key, // Output private key
(nrf_crypto_ecc_public_key_t *)&public_key); // Output public key
Warning
Casting pointer types removes type checking that is done during compilation. You must make sure that the provided parameter is big enough for the currently used curve. See Memory management in nrf_crypto.

Supported curve types

Backends offer different types of curves and schemes. To use a specific curve, an appropriate backend and curve inside it must be enabled. The following table summarizes backend support for different types of curves and schemes.

CC310 mbed TLS Oberon µECC CC310_BL
NIST Group
secp160r1
secp160r2
secp192r1
secp224r1
secp256r1
secp384r1
secp521r1
Koblitz Group
secp160k1
secp192k1
secp224k1
secp256k1
Brainpool Group
bp256r1
bp384r1
bp512r1
Curve25519 Group
Curve25519 1
Ed25519 2

1 - Curve25519 allows only ECDH. ECDSA is not possible using Curve25519.
2 - Ed25519 is a digital signature scheme only. It does not allow ECDH.

Examples

See ECDH Example and ECDSA Example for an example of how to handle the keys.


Documentation feedback | Developer Zone | Subscribe | Updated