TI Driver for Elliptic Curve Diffie-Hellman key agreement scheme.
Elliptic Curve Diffie-Hellman (ECDH) is a key agreement scheme between two parties based on the Diffie-Hellman key exchange protocol.
It provides a means of generating a shared secret and derived symmetric key between the two parties over an insecure channel.
It does not provide authentication. As such, it does not guarantee that the party you are exchanging keys with is truly the party you wish to establish a secured channel with.
The two parties each generate a private key and a public key. The private key is a random integer in the interval [1, n - 1], where n is the order of a previously agreed upon curve. The public key is generated by multiplying the private key by the generator point of a previously agreed upon elliptic curve such as NISTP256 or Curve 25519. The public key is itself a point upon the elliptic curve. Each public key is then transmitted to the other party over a potentially insecure channel. The other party's public key is then multiplied with the private key, generating a shared secret. This shared secret is also a point on the curve. However, the entropy in the secret is not spread evenly throughout the shared secret. In order to generate one or more shared symmetric keys, the shared secret must be run through a key derivation function (KDF) that was previously agreed upon. Usually, only the X coordinate is processed in this way as it contains all the entropy of the shared secret and some curve implementations only provide the X coordinate. The key derivation function can take many forms, from simply hashing the X coordinate of the shared secret with SHA2 and truncating the result to generating multiple symmetric keys with HKDF, an HMAC based KDF.
Key derivation functions in the context of symmetric key generation after elliptic curve based key exchange differ from KDFs used to generate keys from passwords a user provides in a login. Those KDFs such as bcrypt purposefully add additional computation to increase a system's resistance against brute force or dictionary attacks.
Before starting an ECDH operation, the application must do the following:
To generate a public-private key pair for an agreed upon curve, the application must do the following:
After trading public keys with the other party, the application should do the following to calculate the shared secret:
After calculating the shared secret between the application and the other party, the entropy in the shared secret must be evened out and stretched as needed. There are uncountable methods and algorithms to stretch an original seed entropy (the share secret) to generate symmetric keys.
After the ECDH key exchange completes, the application should either start another operation or close the driver by calling ECDH_close()
The API expects elliptic curves as defined in ti/drivers/cryptoutils/ecc/ECCParams.h. Several commonly used curves are provided. Check the device-specific ECDH documentation for curve type (short Weierstrass, Montgomery, Edwards) support for your device. ECDH support for a curve type on a device does not imply curve-type support for other ECC schemes.
By default, the ECDH API expects the private and public keys to be formatted in big-endian format. The details of octet string formatting can be found in SEC 1: Elliptic Curve Cryptography.
Private keys can be formatted as big-endian or little-endian integers of the same length as the curve length.
Public keys and shared secrets are points on an elliptic curve. These points can be expressed in several ways. The most common one is in affine coordinates as an X,Y pair. This API uses points expressed in uncompressed affine coordinates by default. The big-endian format requires a formatting byte in the first byte of the public key. When using uncompressed affine coordinates, this is the value 0x04. The point itself is stored as a concatenated array of X followed by Y. X and Y maybe in big-endian or little-endian. Some implementations do not require or yield the Y coordinate for ECDH on certain curves. It is recommended that the full keying material buffer of twice the curve param length is used to facilitate code-reuse. Implementations that do not use the Y coordinate will zero-out the Y-coordinate whenever they write a point to the CryptoKey.
If device-supported, Montgomery curves can be stored as their X-only format based on the RFC-7748 specification. Here, only the X coordinate is packed in little-endian integers of the same length as the curve length.
This API accepts and returns the keying material of public keys according to the following table:
Curve Type | Keying Material Array | Array Length |
---|---|---|
Short Weierstrass | [0x04, X, Y] | 1 + 2 * Curve Param Length |
Montgomery | [0x04, X, Y] | 1 + 2 * Curve Param Length |
Montgomery | [X] | Curve Param Length |
Edwards | [0x04, X, Y] | 1 + 2 * Curve Param Length |
Note: This driver will automatically prune the private key according to RFC 7748 for the following curve: X25519
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <ti/drivers/cryptoutils/cryptokey/CryptoKey.h>
#include <ti/drivers/cryptoutils/ecc/ECCParams.h>
Go to the source code of this file.
Data Structures | |
struct | ECDH_Config |
ECC Global configuration. More... | |
struct | ECDH_OperationGeneratePublicKey |
Struct containing the parameters required to generate a public key. More... | |
struct | ECDH_OperationComputeSharedSecret |
Struct containing the parameters required to compute the shared secret. More... | |
union | ECDH_Operation |
Union containing pointers to all supported operation structs. More... | |
struct | ECDH_Params |
ECC Parameters. More... | |
Macros | |
#define | ECDH_STATUS_RESERVED (-32) |
#define | ECDH_STATUS_SUCCESS (0) |
Successful status code. More... | |
#define | ECDH_STATUS_ERROR (-1) |
Generic error status code. More... | |
#define | ECDH_STATUS_RESOURCE_UNAVAILABLE (-2) |
An error status code returned if the hardware or software resource is currently unavailable. More... | |
#define | ECDH_STATUS_POINT_AT_INFINITY (-3) |
The result of the operation is the point at infinity. More... | |
#define | ECDH_STATUS_PRIVATE_KEY_LARGER_EQUAL_ORDER (-4) |
The private key passed in is larger or equal to the order of the curve. More... | |
#define | ECDH_STATUS_PRIVATE_KEY_ZERO (-5) |
The private key passed in is zero. More... | |
#define | ECDH_STATUS_PUBLIC_KEY_NOT_ON_CURVE (-6) |
The public key of the other party does not lie upon the curve. More... | |
#define | ECDH_STATUS_PUBLIC_KEY_LARGER_THAN_PRIME (-7) |
A coordinate of the public key of the other party is too large. More... | |
#define | ECDH_STATUS_CANCELED (-8) |
The ongoing operation was canceled. More... | |
#define | ECDH_STATUS_INVALID_KEY_SIZE (-9) |
The provided CryptoKey does not match the expected size. More... | |
#define | ECDH_STATUS_KEYSTORE_ERROR (-10) |
Importing generated key into KeyStore failed. More... | |
Typedefs | |
typedef ECDH_Config * | ECDH_Handle |
A handle that is returned from an ECDH_open() call. More... | |
typedef void(* | ECDH_CallbackFxn) (ECDH_Handle handle, int_fast16_t returnStatus, ECDH_Operation operation, ECDH_OperationType operationType) |
The definition of a callback function used by the ECDH driver when used in ECDH_RETURN_BEHAVIOR_CALLBACK. More... | |
Enumerations | |
enum | ECDH_ReturnBehavior { ECDH_RETURN_BEHAVIOR_CALLBACK = 1, ECDH_RETURN_BEHAVIOR_BLOCKING = 2, ECDH_RETURN_BEHAVIOR_POLLING = 4 } |
The way in which ECDH function calls return after performing a public key generation or shared secret compution operation. More... | |
enum | ECDH_KeyMaterialEndianness { ECDH_BIG_ENDIAN_KEY = 0, ECDH_LITTLE_ENDIAN_KEY = 1 } |
enum | ECDH_OperationType { ECDH_OPERATION_TYPE_GENERATE_PUBLIC_KEY = 1, ECDH_OPERATION_TYPE_COMPUTE_SHARED_SECRET = 2 } |
Enum for the operation types supported by the driver. More... | |
Functions | |
void | ECDH_init (void) |
This function initializes the ECC module. More... | |
void | ECDH_Params_init (ECDH_Params *params) |
Function to initialize the ECDH_Params struct to its defaults. More... | |
ECDH_Handle | ECDH_open (uint_least8_t index, const ECDH_Params *params) |
This function opens a given ECC peripheral. More... | |
void | ECDH_close (ECDH_Handle handle) |
Function to close an ECC peripheral specified by the ECC handle. More... | |
void | ECDH_OperationGeneratePublicKey_init (ECDH_OperationGeneratePublicKey *operation) |
Function to initialize an ECDH_OperationGeneratePublicKey struct to its defaults. More... | |
void | ECDH_OperationComputeSharedSecret_init (ECDH_OperationComputeSharedSecret *operation) |
Function to initialize an ECDH_OperationComputeSharedSecret struct to its defaults. More... | |
int_fast16_t | ECDH_generatePublicKey (ECDH_Handle handle, ECDH_OperationGeneratePublicKey *operation) |
Generates a public key for use in key agreement. More... | |
int_fast16_t | ECDH_computeSharedSecret (ECDH_Handle handle, ECDH_OperationComputeSharedSecret *operation) |
Computes a shared secret. More... | |
int_fast16_t | ECDH_cancelOperation (ECDH_Handle handle) |
Cancels an ongoing ECDH operation. More... | |
ECDH_Handle | ECDH_construct (ECDH_Config *config, const ECDH_Params *params) |
Constructs a new ECDH object. More... | |
Variables | |
const ECDH_Params | ECDH_defaultParams |
Default ECDH_Params structure. More... | |
#define ECDH_STATUS_RESERVED (-32) |
Common ECDH status code reservation offset. ECC driver implementations should offset status codes with ECDH_STATUS_RESERVED growing negatively.
Example implementation specific status codes:
#define ECDH_STATUS_SUCCESS (0) |
Successful status code.
Functions return ECDH_STATUS_SUCCESS if the function was executed successfully.
#define ECDH_STATUS_ERROR (-1) |
Generic error status code.
Functions return ECDH_STATUS_ERROR if the function was not executed successfully.
#define ECDH_STATUS_RESOURCE_UNAVAILABLE (-2) |
An error status code returned if the hardware or software resource is currently unavailable.
ECC driver implementations may have hardware or software limitations on how many clients can simultaneously perform operations. This status code is returned if the mutual exclusion mechanism signals that an operation cannot currently be performed.
#define ECDH_STATUS_POINT_AT_INFINITY (-3) |
The result of the operation is the point at infinity.
The operation yielded the point at infinity on this curve. This point is not permitted for further use in ECC operations.
#define ECDH_STATUS_PRIVATE_KEY_LARGER_EQUAL_ORDER (-4) |
The private key passed in is larger or equal to the order of the curve.
Private keys must be integers in the interval [1, n - 1], where n is the order of the curve.
#define ECDH_STATUS_PRIVATE_KEY_ZERO (-5) |
The private key passed in is zero.
Private keys must be integers in the interval [1, n - 1], where n is the order of the curve.
#define ECDH_STATUS_PUBLIC_KEY_NOT_ON_CURVE (-6) |
The public key of the other party does not lie upon the curve.
The public key received from the other party does not lie upon the agreed upon curve.
#define ECDH_STATUS_PUBLIC_KEY_LARGER_THAN_PRIME (-7) |
A coordinate of the public key of the other party is too large.
A coordinate of the public key received from the other party is larger than the prime of the curve. This implies that the point was not correctly generated on that curve.
#define ECDH_STATUS_CANCELED (-8) |
The ongoing operation was canceled.
#define ECDH_STATUS_INVALID_KEY_SIZE (-9) |
The provided CryptoKey does not match the expected size.
The driver expects the private key to have the same length as other curve parameters and the public key to have a length of twice that plus one. If the provided CryptoKeys for the public and private keys do not match this scheme, this error will be returned.
#define ECDH_STATUS_KEYSTORE_ERROR (-10) |
Importing generated key into KeyStore failed.
Functions return ECDH_STATUS_KEYSTORE_ERROR if the KeyStore_PSA_importKey() did not return KEYSTORE_PSA_STATUS_SUCCESS
typedef ECDH_Config* ECDH_Handle |
A handle that is returned from an ECDH_open() call.
typedef void(* ECDH_CallbackFxn) (ECDH_Handle handle, int_fast16_t returnStatus, ECDH_Operation operation, ECDH_OperationType operationType) |
The definition of a callback function used by the ECDH driver when used in ECDH_RETURN_BEHAVIOR_CALLBACK.
handle | Handle of the client that started the ECDH operation. |
returnStatus | The result of the ECDH operation. May contain an error code if the result is the point at infinity for example. |
operation | A union of pointers to operation structs. Only one type of pointer is valid per call to the callback function. Which type is currently valid is determined by /c operationType. The union allows easier access to the struct's fields without the need to typecase the result. |
operationType | This parameter determined which operation the callback refers to and which type to access through /c operation. |
enum ECDH_ReturnBehavior |
The way in which ECDH function calls return after performing a public key generation or shared secret compution operation.
Callback return behavior is not supported by software-backed implementations. A NULL handle will be returned when attempting to open or construct a driver instance with an unsupported return behavior.
Not all ECDH operations exhibit the specified return behavior. Functions that do not require significant computation and cannot offload that computation to a background thread behave like regular functions. Which functions exhibit the specfied return behavior is not implementation dependent. Specifically, a software-backed implementation run on the same CPU as the application will emulate the return behavior while not actually offloading the computation to the background thread.
ECDH functions exhibiting the specified return behavior have restrictions on the context from which they may be called.
Task | Hwi | Swi | |
---|---|---|---|
ECDH_RETURN_BEHAVIOR_CALLBACK | X | X | X |
ECDH_RETURN_BEHAVIOR_BLOCKING | X | ||
ECDH_RETURN_BEHAVIOR_POLLING | X | X | X |
enum ECDH_OperationType |
void ECDH_init | ( | void | ) |
This function initializes the ECC module.
void ECDH_Params_init | ( | ECDH_Params * | params | ) |
Function to initialize the ECDH_Params struct to its defaults.
params | An pointer to ECDH_Params structure for initialization |
Defaults values are: returnBehavior = ECDH_RETURN_BEHAVIOR_BLOCKING callbackFxn = NULL timeout = SemaphoreP_WAIT_FOREVER custom = NULL
ECDH_Handle ECDH_open | ( | uint_least8_t | index, |
const ECDH_Params * | params | ||
) |
This function opens a given ECC peripheral.
index | Logical peripheral number for the ECC indexed into the ECDH_config table |
params | Pointer to an parameter block, if NULL it will use default values. |
void ECDH_close | ( | ECDH_Handle | handle | ) |
Function to close an ECC peripheral specified by the ECC handle.
handle | An ECC handle returned from ECDH_open() |
void ECDH_OperationGeneratePublicKey_init | ( | ECDH_OperationGeneratePublicKey * | operation | ) |
Function to initialize an ECDH_OperationGeneratePublicKey struct to its defaults.
operation | A pointer to ECDH_OperationGeneratePublicKey structure for initialization |
Defaults values are all zeros.
void ECDH_OperationComputeSharedSecret_init | ( | ECDH_OperationComputeSharedSecret * | operation | ) |
Function to initialize an ECDH_OperationComputeSharedSecret struct to its defaults.
operation | A pointer to ECDH_OperationComputeSharedSecret structure for initialization |
Defaults values are all zeros.
int_fast16_t ECDH_generatePublicKey | ( | ECDH_Handle | handle, |
ECDH_OperationGeneratePublicKey * | operation | ||
) |
Generates a public key for use in key agreement.
This function can be used to generate a public key from a private key.
handle | A ECDH handle returned from ECDH_open() |
operation | A pointer to a struct containing the requisite parameters to execute the function. |
operation
.ECDH_STATUS_SUCCESS | The operation succeeded. |
ECDH_STATUS_ERROR | The operation failed. |
ECDH_STATUS_RESOURCE_UNAVAILABLE | The required hardware resource was not available. Try again later. |
ECDH_STATUS_CANCELED | The operation was canceled. |
ECDH_STATUS_POINT_AT_INFINITY | The computed public key is the point at infinity. |
ECDH_STATUS_PRIVATE_KEY_ZERO | The provided private key is zero. |
ECDH_STATUS_PRIVATE_KEY_LARGER_EQUAL_ORDER | The provided private key is larger than or equal to the order of the curve. |
int_fast16_t ECDH_computeSharedSecret | ( | ECDH_Handle | handle, |
ECDH_OperationComputeSharedSecret * | operation | ||
) |
Computes a shared secret.
This secret can be used to generate shared keys for encryption and authentication.
handle | A ECDH handle returned from ECDH_open() |
operation | A pointer to a struct containing the requisite |
operation
. Generate a shared secret off-chip or using ECDH_generatePublicKey()ECDH_STATUS_SUCCESS | The operation succeeded. |
ECDH_STATUS_ERROR | The operation failed. |
ECDH_STATUS_RESOURCE_UNAVAILABLE | The required hardware resource was not available. Try again later. |
ECDH_STATUS_CANCELED | The operation was canceled. |
ECDH_STATUS_PUBLIC_KEY_NOT_ON_CURVE | The foreign public key is not a point on the specified curve. |
ECDH_STATUS_PUBLIC_KEY_LARGER_THAN_PRIME | One of the public key coordinates is larger the the curve's prime. |
int_fast16_t ECDH_cancelOperation | ( | ECDH_Handle | handle | ) |
Cancels an ongoing ECDH operation.
Asynchronously cancels an ECDH operation. Only available when using ECDH_RETURN_BEHAVIOR_CALLBACK or ECDH_RETURN_BEHAVIOR_BLOCKING. The operation will terminate as though an error occurred. The return status code of the operation will be ECDH_STATUS_CANCELED.
handle | Handle of the operation to cancel |
ECDH_STATUS_SUCCESS | The operation was canceled. |
ECDH_STATUS_ERROR | The operation was not canceled. There may be no operation to cancel. |
ECDH_Handle ECDH_construct | ( | ECDH_Config * | config, |
const ECDH_Params * | params | ||
) |
Constructs a new ECDH object.
Unlike ECDH_open(), ECDH_construct() does not require the hwAttrs and object to be allocated in a ECDH_Config array that is indexed into. Instead, the ECDH_Config, hwAttrs, and object can be allocated at any location. This allows for relatively simple run-time allocation of temporary driver instances on the stack or the heap. The drawback is that this makes it more difficult to write device-agnostic code. If you use an ifdef with DeviceFamily, you can choose the correct object and hwAttrs to allocate. That compilation unit will be tied to the device it was compiled for at this point. To change devices, recompilation of the application with a different DeviceFamily setting is necessary.
config | ECDH_Config describing the location of the object and hwAttrs. |
params | ECDH_Params to configure the driver instance. |
config
points to must be zeroed out prior to calling this function. Otherwise, unexpected behavior may ensue. const ECDH_Params ECDH_defaultParams |
Default ECDH_Params structure.