ECDH.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2017-2019, Texas Instruments Incorporated
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * * Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  *
12  * * Redistributions in binary form must reproduce the above copyright
13  * notice, this list of conditions and the following disclaimer in the
14  * documentation and/or other materials provided with the distribution.
15  *
16  * * Neither the name of Texas Instruments Incorporated nor the names of
17  * its contributors may be used to endorse or promote products derived
18  * from this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
22  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
27  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
30  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32 /*!****************************************************************************
33  * @file ECDH.h
34  *
35  * @brief TI Driver for Elliptic Curve Diffie-Hellman key agreement scheme.
36  *
37  * @warning This is a beta API. It may change in future releases.
38  *
39  * @anchor ti_drivers_ECDH_Overview
40  * # Overview #
41  *
42  * Elliptic Curve Diffie-Hellman (ECDH) is a key agreement scheme between
43  * two parties based on the Diffie-Hellman key exchange protocol.
44  *
45  * It provides a means of generating a shared secret and derived symmetric key
46  * between the two parties over an insecure channel.
47  *
48  * It does not provide authentication. As such, it does not guarantee that the
49  * party you are exchanging keys with is truly the party you wish to establish a
50  * secured channel with.
51  *
52  * The two parties each generate a private key and a public key. The private key
53  * is a random integer in the interval [1, n - 1], where n is the order of a
54  * previously agreed upon curve. The public key is generated
55  * by multiplying the private key by the generator point of a previously agreed
56  * upon elliptic curve such as NISTP256 or Curve 25519. The public key is itself
57  * a point upon the elliptic curve. Each public key is then transmitted to the
58  * other party over a potentially insecure channel. The other party's public key
59  * is then multiplied with the private key, generating a shared secret. This
60  * shared secret is also a point on the curve. However, the entropy in the secret
61  * is not spread evenly throughout the shared secret. In order to generate one or more
62  * shared symmetric keys, the shared secret must be run through a key derivation
63  * function (KDF) that was previously agreed upon. Usually, only the X coordinate
64  * is processed in this way as it contains all the entropy of the shared secret and
65  * some curve implementations only provide the X coordinate. The key derivation function
66  * can take many forms, from simply hashing the X coordinate of the shared secret
67  * with SHA2 and truncating the result to generating multiple symmetric keys with
68  * HKDF, an HMAC based KDF.
69  *
70  * Key derivation functions in the context of symmetric key generation after
71  * elliptic curve based key exchange differ from KDFs used to generate keys from
72  * passwords a user provides in a login. Those KDFs such as bcrypt purposefully
73  * add additional computation to increase a system's resistance against brute
74  * force or dictionary attacks.
75  *
76  * @anchor ti_drivers_ECDH_Usage
77  * # Usage #
78  *
79  * ## Before starting an ECDH operation #
80  *
81  * Before starting an ECDH operation, the application must do the following:
82  * - Call ECDH_init() to initialize the driver
83  * - Call ECDH_Params_init() to initialize the ECDH_Params to default values.
84  * - Modify the ECDH_Params as desired
85  * - Call ECDH_open() to open an instance of the driver
86  *
87  * ## Generating your public-private key pair #
88  * To generate a public-private key pair for an agreed upon curve, the application
89  * must do the following:
90  * - Generate the keying material for the private key. This keying material must
91  * be an integer in the interval [1, n - 1], where n is the order of the curve.
92  * It should be stored in an array with the least significant byte of the integer
93  * hex representation stored in the lowest address of the array (little-endian).
94  * The array should be the same length as the curve parameters of the curve used.
95  * The driver validates private keys against the provided curve by default.
96  * - Initialize the private key CryptoKey. CryptoKeys are opaque datastructures and representations
97  * of keying material and its storage. Depending on how the keying material
98  * is stored (RAM or flash, key store, key blob), the CryptoKey must be
99  * initialized differently. The ECDH API can handle all types of CryptoKey.
100  * However, not all device-specific implementions support all types of CryptoKey.
101  * Devices without a key store will not support CryptoKeys with keying material
102  * stored in a key store for example.
103  * All devices support plaintext CryptoKeys.
104  * - Initialize a blank CryptoKey for the public key. The CryptoKey will keep track
105  * of where the keying material for the public key should be copied and how
106  * long it is. It should have twice the length of the private key.
107  * - Initialize the ECDH_OperationGeneratePublicKey struct and then populate it.
108  * - Call ECDH_generatePublicKey(). The generated keying material will be copied
109  * according the the CryptoKey passed in as the public key parameter. The CryptoKey
110  * will no longer be considered 'blank' after the operation.
111  *
112  * ## Calculating a shared secret #
113  * After trading public keys with the other party, the application should do the following
114  * to calculate the shared secret:
115  * - Initialize a CryptoKey as public key with the keying material received from the other
116  * party.
117  * - Initialize a blank CryptoKey with the same size as the previously initialized
118  * public key.
119  * - Initialize the ECDH_OperationComputeSharedSecret struct and then populate it.
120  * - Call ECDH_computeSharedSecret(). The shared secret will be copied to a location
121  * according to the shared secret CryptoKey passed to the function call. The driver
122  * will validate the supplied public key and reject invalid ones.
123  *
124  * ## Creating one or more symmetric keys from the shared secret #
125  * After calculating the shared secret between the application and the other party,
126  * the entropy in the shared secret must be evened out and stretched as needed. There are
127  * uncountable methods and algorithms to stretch an original seed entropy (the share secret)
128  * to generate symmetric keys.
129  * - Run the X coordinate of the resulting entropy through a key derivation function (KDF)
130  *
131  * ## After a key exchange #
132  * After the ECDH key exchange completes, the application should either start another operation
133  * or close the driver by calling ECDH_close()
134  *
135  * ## General usage #
136  * The API expects elliptic curves as defined in ti/drivers/cryptoutils/ecc/ECCParams.h.
137  * Several commonly used curves are provided. Check the device-specific ECDH documentation
138  * for curve type (short Weierstrass, Montgomery, Edwards) support for your device.
139  * ECDH support for a curve type on a device does not imply curve-type support for
140  * other ECC schemes.
141  *
142  * Public keys and shared secrets are points on an elliptic curve. These points can
143  * be expressed in several ways. The most common one is in affine coordinates as an
144  * X,Y pair.
145  * This API uses points expressed in affine coordinates.
146  * The point is stored as a concatenated array of X followed by Y in a location
147  * described by its CryptoKey. Some implementations do not require or yield
148  * the Y coordinate for ECDH on certain curves. It is recommended that the full
149  * keying material buffer of twice the curve param length is used to facilitate
150  * code-reuse. Implementations that do not use the Y coordinate will zero-out
151  * the Y-coordinate whenever they write a point to the CryptoKey.
152  *
153  * This API accepts and returns the keying material of public keys according
154  * to the following table:
155  *
156  * | Curve Type | Keying Material Array | Array Length |
157  * |--------------------|-----------------------|---------------------------|
158  * | Short Weierstrass | [X, Y] | 2 * Curve Param Length |
159  * | Montgomery | [X, Y] | 2 * Curve Param Length |
160  * | Edwards | [X, Y] | 2 * Curve Param Length |
161  *
162  * @anchor ti_drivers_ECDH_Synopsis
163  * ## Synopsis
164  * @anchor ti_drivers_ECDH_Synopsis_Code
165  * @code
166  * // Import ECDH Driver definitions
167  * #include <ti/drivers/ECDH.h>
168  *
169  * ECDH_init();
170  *
171  * // Since we are using default ECDH_Params, we just pass in NULL for that parameter.
172  * ecdhHandle = ECDH_open(0, NULL);
173  *
174  * // Initialize myPrivateKey and myPublicKey
175  * CryptoKeyPlaintext_initKey(&myPrivateKey, myPrivateKeyingMaterial, sizeof(myPrivateKeyingMaterial));
176  * CryptoKeyPlaintext_initBlankKey(&myPublicKey, myPublicKeyingMaterial, sizeof(myPublicKeyingMaterial));
177  *
178  * ECDH_OperationGeneratePublicKey_init(&operationGeneratePublicKey);
179  * operationGeneratePublicKey.curve = &ECCParams_NISTP256;
180  * operationGeneratePublicKey.myPrivateKey = &myPrivateKey;
181  * operationGeneratePublicKey.myPublicKey = &myPublicKey;
182  *
183  * // Generate the keying material for myPublicKey and store it in myPublicKeyingMaterial
184  * operationResult = ECDH_generatePublicKey(ecdhHandle, &operationGeneratePublicKey);
185  *
186  * // Now send the content of myPublicKeyingMaterial to theother party,
187  * // receive their public key, and copy their public keying material to theirPublicKeyingMaterial
188  *
189  * // Initialise their public CryptoKey and the shared secret CryptoKey
190  * CryptoKeyPlaintext_initKey(&theirPublicKey, theirPublicKeyingMaterial, sizeof(theirPublicKeyingMaterial));
191  * CryptoKeyPlaintext_initBlankKey(&sharedSecret, sharedSecretKeyingMaterial, sizeof(sharedSecretKeyingMaterial));
192  *
193  * // The ECC_NISTP256 struct is provided in ti/drivers/types/EccParams.h and the corresponding device-specific implementation
194  * ECDH_OperationComputeSharedSecret_init(&operationComputeSharedSecret);
195  * operationComputeSharedSecret.curve = &ECCParams_NISTP256;
196  * operationComputeSharedSecret.myPrivateKey = &myPrivateKey;
197  * operationComputeSharedSecret.theirPublicKey = &theirPublicKey;
198  * operationComputeSharedSecret.sharedSecret = &sharedSecret;
199  *
200  * // Compute the shared secret and copy it to sharedSecretKeyingMaterial
201  * operationResult = ECDH_computeSharedSecret(ecdhHandle, &operationComputeSharedSecret);
202  *
203  * // Close the driver
204  * ECDH_close(ecdhHandle);
205  *
206  * @endcode
207  *
208  * @anchor ti_drivers_ECDH_Examples
209  * # Examples #
210  *
211  * ## ECDH exchange with plaintext CryptoKeys #
212  *
213  * @code
214  *
215  * #include <ti/drivers/cryptoutils/cryptokey/CryptoKeyPlaintext.h>
216  * #include <ti/drivers/ECDH.h>
217  *
218  * ...
219  *
220  * // Our private key is 0x0000000000000000000000000000000000000000000000000000000000000001
221  * // In practice, this value should come from a TRNG, PRNG, PUF, or device-specific pre-seeded key
222  * uint8_t myPrivateKeyingMaterial[32] = {0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
223  * 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
224  * 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
225  * 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
226  * uint8_t myPublicKeyingMaterial[64] = {0};
227  * uint8_t theirPublicKeyingMaterial[64] = {0};
228  * uint8_t sharedSecretKeyingMaterial[64] = {0};
229  * uint8_t symmetricKeyingMaterial[16] = {0};
230  *
231  * CryptoKey myPrivateKey;
232  * CryptoKey myPublicKey;
233  * CryptoKey theirPublicKey;
234  * CryptoKey sharedSecret;
235  * CryptoKey symmetricKey;
236  *
237  * ECDH_Handle ecdhHandle;
238  *
239  * int_fast16_t operationResult;
240  *
241  * ECDH_OperationGeneratePublicKey operationGeneratePublicKey;
242  *
243  * // Since we are using default ECDH_Params, we just pass in NULL for that parameter.
244  * ecdhHandle = ECDH_open(0, NULL);
245  *
246  * if (!ecdhHandle) {
247  * // Handle error
248  * }
249  *
250  * // Initialize myPrivateKey and myPublicKey
251  * CryptoKeyPlaintext_initKey(&myPrivateKey, myPrivateKeyingMaterial, sizeof(myPrivateKeyingMaterial));
252  * CryptoKeyPlaintext_initBlankKey(&myPublicKey, myPublicKeyingMaterial, sizeof(myPublicKeyingMaterial));
253  *
254  * ECDH_OperationGeneratePublicKey_init(&operationGeneratePublicKey);
255  * operationGeneratePublicKey.curve = &ECCParams_NISTP256;
256  * operationGeneratePublicKey.myPrivateKey = &myPrivateKey;
257  * operationGeneratePublicKey.myPublicKey = &myPublicKey;
258  *
259  * // Generate the keying material for myPublicKey and store it in myPublicKeyingMaterial
260  * operationResult = ECDH_generatePublicKey(ecdhHandle, &operationGeneratePublicKey);
261  *
262  * if (operationResult != ECDH_STATUS_SUCCESS) {
263  * // Handle error
264  * }
265  *
266  * // Now send the content of myPublicKeyingMaterial to theother party,
267  * // receive their public key, and copy their public keying material to theirPublicKeyingMaterial
268  *
269  * // Initialise their public CryptoKey and the shared secret CryptoKey
270  * CryptoKeyPlaintext_initKey(&theirPublicKey, theirPublicKeyingMaterial, sizeof(theirPublicKeyingMaterial));
271  * CryptoKeyPlaintext_initBlankKey(&sharedSecret, sharedSecretKeyingMaterial, sizeof(sharedSecretKeyingMaterial));
272  *
273  * // The ECC_NISTP256 struct is provided in ti/drivers/types/EccParams.h and the corresponding device-specific implementation
274  * ECDH_OperationComputeSharedSecret_init(&operationComputeSharedSecret);
275  * operationComputeSharedSecret.curve = &ECCParams_NISTP256;
276  * operationComputeSharedSecret.myPrivateKey = &myPrivateKey;
277  * operationComputeSharedSecret.theirPublicKey = &theirPublicKey;
278  * operationComputeSharedSecret.sharedSecret = &sharedSecret;
279  *
280  * // Compute the shared secret and copy it to sharedSecretKeyingMaterial
281  * operationResult = ECDH_computeSharedSecret(ecdhHandle, &operationComputeSharedSecret);
282  *
283  * if (operationResult != ECDH_STATUS_SUCCESS) {
284  * // Handle error
285  * }
286  *
287  * CryptoKeyPlaintext_initBlankKey(&symmetricKey, symmetricKeyingMaterial, sizeof(symmetricKeyingMaterial));
288  *
289  * // Set up a KDF such as HKDF and open the requisite cryptographic primitive driver to implement it
290  * // HKDF and SHA2 were chosen as an example and may not be available directly
291  *
292  * // At this point, you and the other party have both created the content within symmetricKeyingMaterial without
293  * // someone else listening to your communication channel being able to do so
294  *
295  * @endcode
296  *
297  *
298  */
299 
300 
301 #ifndef ti_drivers_ECDH__include
302 #define ti_drivers_ECDH__include
303 
304 #ifdef __cplusplus
305 extern "C" {
306 #endif
307 
308 #include <stdbool.h>
309 #include <stddef.h>
310 #include <stdint.h>
311 
314 
327 #define ECDH_STATUS_RESERVED (-32)
328 
335 #define ECDH_STATUS_SUCCESS (0)
336 
343 #define ECDH_STATUS_ERROR (-1)
344 
353 #define ECDH_STATUS_RESOURCE_UNAVAILABLE (-2)
354 
361 #define ECDH_STATUS_POINT_AT_INFINITY (-3)
362 
369 #define ECDH_STATUS_PRIVATE_KEY_LARGER_EQUAL_ORDER (-4)
370 
377 #define ECDH_STATUS_PRIVATE_KEY_ZERO (-5)
378 
385 #define ECDH_STATUS_PUBLIC_KEY_NOT_ON_CURVE (-6)
386 
394 #define ECDH_STATUS_PUBLIC_KEY_LARGER_THAN_PRIME (-7)
395 
399 #define ECDH_STATUS_CANCELED (-8)
400 
404 typedef struct ECDH_Config *ECDH_Handle;
405 
427 typedef enum {
443 
444 
456 typedef struct ECDH_Config {
458  void *object;
459 
461  void const *hwAttrs;
462 } ECDH_Config;
463 
467 typedef struct {
476 
480 typedef struct {
494 
498 typedef union {
502 
506 typedef enum {
510 
529 typedef void (*ECDH_CallbackFxn) (ECDH_Handle handle,
530  int_fast16_t returnStatus,
531  ECDH_Operation operation,
532  ECDH_OperationType operationType);
533 
542 typedef struct {
545  uint32_t timeout;
546  void *custom;
549 } ECDH_Params;
550 
556 extern const ECDH_Params ECDH_defaultParams;
557 
566 void ECDH_init(void);
567 
580 void ECDH_Params_init(ECDH_Params *params);
581 
599 ECDH_Handle ECDH_open(uint_least8_t index, ECDH_Params *params);
600 
610 void ECDH_close(ECDH_Handle handle);
611 
621 
631 
654 int_fast16_t ECDH_generatePublicKey(ECDH_Handle handle, ECDH_OperationGeneratePublicKey *operation);
655 
675 int_fast16_t ECDH_computeSharedSecret(ECDH_Handle handle, ECDH_OperationComputeSharedSecret *operation);
676 
690 int_fast16_t ECDH_cancelOperation(ECDH_Handle handle);
691 
692 #ifdef __cplusplus
693 }
694 #endif
695 
696 #endif /* ti_drivers_ECDH__include */
ECDH_OperationType
Enum for the operation types supported by the driver.
Definition: ECDH.h:506
ECC Global configuration.
Definition: ECDH.h:456
The CryptoKey type is an opaque representation of a cryptographic key.
ECDH_Handle ECDH_open(uint_least8_t index, ECDH_Params *params)
This function opens a given ECC peripheral.
ECDH_ReturnBehavior returnBehavior
Definition: ECDH.h:543
void ECDH_OperationGeneratePublicKey_init(ECDH_OperationGeneratePublicKey *operation)
Function to initialize an ECDH_OperationGeneratePublicKey struct to its defaults. ...
ECDH_OperationComputeSharedSecret * computeSharedSecret
Definition: ECDH.h:500
int_fast16_t ECDH_cancelOperation(ECDH_Handle handle)
Cancels an ongoing ECDH operation.
Definition: ECDH.h:438
void * object
Definition: ECDH.h:458
struct ECDH_Config ECDH_Config
ECC Global configuration.
CryptoKey datastructure.
Definition: CryptoKey.h:210
void * custom
Definition: ECDH.h:546
Struct containing the parameters required to compute the shared secret.
Definition: ECDH.h:480
const CryptoKey * theirPublicKey
Definition: ECDH.h:487
A structure containing the parameters of an elliptic curve in short Weierstrass form.
Definition: ECCParams.h:111
ECDH_CallbackFxn callbackFxn
Definition: ECDH.h:544
const ECDH_Params ECDH_defaultParams
Default ECDH_Params structure.
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_CALLB...
Definition: ECDH.h:529
void ECDH_OperationComputeSharedSecret_init(ECDH_OperationComputeSharedSecret *operation)
Function to initialize an ECDH_OperationComputeSharedSecret struct to its defaults.
ECDH_OperationGeneratePublicKey * generatePublicKey
Definition: ECDH.h:499
int_fast16_t ECDH_generatePublicKey(ECDH_Handle handle, ECDH_OperationGeneratePublicKey *operation)
Generates a public key for use in key agreement.
const CryptoKey * myPrivateKey
Definition: ECDH.h:469
const CryptoKey * myPrivateKey
Definition: ECDH.h:484
const ECCParams_CurveParams * curve
Definition: ECDH.h:481
void ECDH_init(void)
This function initializes the ECC module.
ECC Parameters.
Definition: ECDH.h:542
Definition: ECDH.h:434
uint32_t timeout
Definition: ECDH.h:545
CryptoKey * sharedSecret
Definition: ECDH.h:490
ECDH_ReturnBehavior
The way in which ECC function calls return after performing an encryption + authentication or decrypt...
Definition: ECDH.h:427
int_fast16_t ECDH_computeSharedSecret(ECDH_Handle handle, ECDH_OperationComputeSharedSecret *operation)
Computes a shared secret.
Struct containing the parameters required to generate a public key.
Definition: ECDH.h:467
void ECDH_close(ECDH_Handle handle)
Function to close an ECC peripheral specified by the ECC handle.
const ECCParams_CurveParams * curve
Definition: ECDH.h:468
void ECDH_Params_init(ECDH_Params *params)
Function to initialize the ECDH_Params struct to its defaults.
void const * hwAttrs
Definition: ECDH.h:461
struct ECDH_Config * ECDH_Handle
A handle that is returned from an ECDH_open() call.
Definition: ECDH.h:404
CryptoKey * myPublicKey
Definition: ECDH.h:472
Union containing pointers to all supported operation structs.
Definition: ECDH.h:498
Definition: ECDH.h:428
© Copyright 1995-2019, Texas Instruments Incorporated. All rights reserved.
Trademarks | Privacy policy | Terms of use | Terms of sale