ECDH.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2017-2020, 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  * @anchor ti_drivers_ECDH_Overview
38  * # Overview #
39  *
40  * Elliptic Curve Diffie-Hellman (ECDH) is a key agreement scheme between
41  * two parties based on the Diffie-Hellman key exchange protocol.
42  *
43  * It provides a means of generating a shared secret and derived symmetric key
44  * between the two parties over an insecure channel.
45  *
46  * It does not provide authentication. As such, it does not guarantee that the
47  * party you are exchanging keys with is truly the party you wish to establish a
48  * secured channel with.
49  *
50  * The two parties each generate a private key and a public key. The private key
51  * is a random integer in the interval [1, n - 1], where n is the order of a
52  * previously agreed upon curve. The public key is generated
53  * by multiplying the private key by the generator point of a previously agreed
54  * upon elliptic curve such as NISTP256 or Curve 25519. The public key is itself
55  * a point upon the elliptic curve. Each public key is then transmitted to the
56  * other party over a potentially insecure channel. The other party's public key
57  * is then multiplied with the private key, generating a shared secret. This
58  * shared secret is also a point on the curve. However, the entropy in the secret
59  * is not spread evenly throughout the shared secret. In order to generate one or more
60  * shared symmetric keys, the shared secret must be run through a key derivation
61  * function (KDF) that was previously agreed upon. Usually, only the X coordinate
62  * is processed in this way as it contains all the entropy of the shared secret and
63  * some curve implementations only provide the X coordinate. The key derivation function
64  * can take many forms, from simply hashing the X coordinate of the shared secret
65  * with SHA2 and truncating the result to generating multiple symmetric keys with
66  * HKDF, an HMAC based KDF.
67  *
68  * Key derivation functions in the context of symmetric key generation after
69  * elliptic curve based key exchange differ from KDFs used to generate keys from
70  * passwords a user provides in a login. Those KDFs such as bcrypt purposefully
71  * add additional computation to increase a system's resistance against brute
72  * force or dictionary attacks.
73  *
74  * @anchor ti_drivers_ECDH_Usage
75  * # Usage #
76  *
77  * ## Before starting an ECDH operation #
78  *
79  * Before starting an ECDH operation, the application must do the following:
80  * - Call ECDH_init() to initialize the driver
81  * - Call ECDH_Params_init() to initialize the ECDH_Params to default values.
82  * - Modify the ECDH_Params as desired
83  * - Call ECDH_open() to open an instance of the driver
84  *
85  * ## Generating your public-private key pair #
86  * To generate a public-private key pair for an agreed upon curve, the application
87  * must do the following:
88  * - Generate the keying material for the private key. This keying material must
89  * be an integer in the interval [1, n - 1], where n is the order of the curve.
90  * It should be stored in an array with the least significant byte of the integer
91  * hex representation stored in the highest address of the array (big-endian).
92  * The array should be the same length as the curve parameters of the curve used.
93  * The driver validates private keys against the provided curve by default.
94  * - Initialize the private key CryptoKey. CryptoKeys are opaque datastructures and representations
95  * of keying material and its storage. Depending on how the keying material
96  * is stored (RAM or flash, key store, key blob), the CryptoKey must be
97  * initialized differently. The ECDH API can handle all types of CryptoKey.
98  * However, not all device-specific implementions support all types of CryptoKey.
99  * Devices without a key store will not support CryptoKeys with keying material
100  * stored in a key store for example.
101  * All devices support plaintext CryptoKeys.
102  * - Initialize a blank CryptoKey for the public key. The CryptoKey will keep track
103  * of where the keying material for the public key should be copied and how
104  * long it is. It should have twice the length of the private key plus one.
105  * - Initialize the ECDH_OperationGeneratePublicKey struct and then populate it.
106  * - Call ECDH_generatePublicKey(). The generated keying material will be copied
107  * according the the CryptoKey passed in as the public key parameter. The CryptoKey
108  * will no longer be considered 'blank' after the operation.
109  *
110  * ## Calculating a shared secret #
111  * After trading public keys with the other party, the application should do the following
112  * to calculate the shared secret:
113  * - Initialize a CryptoKey as public key with the keying material received from the other
114  * party.
115  * - Initialize a blank CryptoKey with the same size as the previously initialized
116  * public key.
117  * - Initialize the ECDH_OperationComputeSharedSecret struct and then populate it.
118  * - Call ECDH_computeSharedSecret(). The shared secret will be copied to a location
119  * according to the shared secret CryptoKey passed to the function call. The driver
120  * will validate the supplied public key and reject invalid ones.
121  *
122  * ## Creating one or more symmetric keys from the shared secret #
123  * After calculating the shared secret between the application and the other party,
124  * the entropy in the shared secret must be evened out and stretched as needed. There are
125  * uncountable methods and algorithms to stretch an original seed entropy (the share secret)
126  * to generate symmetric keys.
127  * - Run the X coordinate of the resulting entropy through a key derivation function (KDF)
128  *
129  * ## After a key exchange #
130  * After the ECDH key exchange completes, the application should either start another operation
131  * or close the driver by calling ECDH_close()
132  *
133  * ## General usage #
134  * The API expects elliptic curves as defined in ti/drivers/cryptoutils/ecc/ECCParams.h.
135  * Several commonly used curves are provided. Check the device-specific ECDH documentation
136  * for curve type (short Weierstrass, Montgomery, Edwards) support for your device.
137  * ECDH support for a curve type on a device does not imply curve-type support for
138  * other ECC schemes.
139  *
140  * ## Key Formatting
141  * The ECDH API expects the private and public keys to be formatted in octet
142  * string format. The details of octet string formatting can be found in
143  * SEC 1: Elliptic Curve Cryptography.
144  *
145  * Private keys are formatted as big-endian integers of the same length as the
146  * curve length.
147  *
148  * Public keys and shared secrets are points on an elliptic curve. These points can
149  * be expressed in several ways. The most common one is in affine coordinates as an
150  * X,Y pair.
151  * This API uses points expressed in uncompressed affine coordinates by default.
152  * The octet string format requires a formatting byte in the first byte of the
153  * public key. When using uncompressed affine coordinates, this is the value
154  * 0x04.
155  * The point itself is stored as a concatenated array of X followed by Y.
156  * X and Y are big-endian. Some implementations do not require or yield
157  * the Y coordinate for ECDH on certain curves. It is recommended that the full
158  * keying material buffer of twice the curve param length is used to facilitate
159  * code-reuse. Implementations that do not use the Y coordinate will zero-out
160  * the Y-coordinate whenever they write a point to the CryptoKey.
161  *
162  * This API accepts and returns the keying material of public keys according
163  * to the following table:
164  *
165  * | Curve Type | Keying Material Array | Array Length |
166  * |--------------------|-----------------------|----------------------------|
167  * | Short Weierstrass | [0x04, X, Y] | 1 + 2 * Curve Param Length |
168  * | Montgomery | [0x04, X, Y] | 1 + 2 * Curve Param Length |
169  * | Edwards | [0x04, X, Y] | 1 + 2 * Curve Param Length |
170  *
171  * @anchor ti_drivers_ECDH_Synopsis
172  * ## Synopsis
173  * @anchor ti_drivers_ECDH_Synopsis_Code
174  * @code
175  * // Import ECDH Driver definitions
176  * #include <ti/drivers/ECDH.h>
177  *
178  * ECDH_init();
179  *
180  * // Since we are using default ECDH_Params, we just pass in NULL for that parameter.
181  * ecdhHandle = ECDH_open(0, NULL);
182  *
183  * // Initialize myPrivateKey and myPublicKey
184  * CryptoKeyPlaintext_initKey(&myPrivateKey, myPrivateKeyingMaterial, sizeof(myPrivateKeyingMaterial));
185  * CryptoKeyPlaintext_initBlankKey(&myPublicKey, myPublicKeyingMaterial, sizeof(myPublicKeyingMaterial));
186  *
187  * ECDH_OperationGeneratePublicKey_init(&operationGeneratePublicKey);
188  * operationGeneratePublicKey.curve = &ECCParams_NISTP256;
189  * operationGeneratePublicKey.myPrivateKey = &myPrivateKey;
190  * operationGeneratePublicKey.myPublicKey = &myPublicKey;
191  *
192  * // Generate the keying material for myPublicKey and store it in myPublicKeyingMaterial
193  * operationResult = ECDH_generatePublicKey(ecdhHandle, &operationGeneratePublicKey);
194  *
195  * // Now send the content of myPublicKeyingMaterial to theother party,
196  * // receive their public key, and copy their public keying material to theirPublicKeyingMaterial
197  *
198  * // Initialise their public CryptoKey and the shared secret CryptoKey
199  * CryptoKeyPlaintext_initKey(&theirPublicKey, theirPublicKeyingMaterial, sizeof(theirPublicKeyingMaterial));
200  * CryptoKeyPlaintext_initBlankKey(&sharedSecret, sharedSecretKeyingMaterial, sizeof(sharedSecretKeyingMaterial));
201  *
202  * // The ECC_NISTP256 struct is provided in ti/drivers/types/EccParams.h and the corresponding device-specific implementation
203  * ECDH_OperationComputeSharedSecret_init(&operationComputeSharedSecret);
204  * operationComputeSharedSecret.curve = &ECCParams_NISTP256;
205  * operationComputeSharedSecret.myPrivateKey = &myPrivateKey;
206  * operationComputeSharedSecret.theirPublicKey = &theirPublicKey;
207  * operationComputeSharedSecret.sharedSecret = &sharedSecret;
208  *
209  * // Compute the shared secret and copy it to sharedSecretKeyingMaterial
210  * operationResult = ECDH_computeSharedSecret(ecdhHandle, &operationComputeSharedSecret);
211  *
212  * // Close the driver
213  * ECDH_close(ecdhHandle);
214  *
215  * @endcode
216  *
217  * @anchor ti_drivers_ECDH_Examples
218  * # Examples #
219  *
220  * ## ECDH exchange with plaintext CryptoKeys #
221  *
222  * @code
223  *
224  * #include <ti/drivers/cryptoutils/cryptokey/CryptoKeyPlaintext.h>
225  * #include <ti/drivers/ECDH.h>
226  *
227  * #define CURVE_LENGTH 32
228  *
229  * ...
230  *
231  * // Our private key is 0x0000000000000000000000000000000000000000000000000000000000000001
232  * // In practice, this value should come from a TRNG, PRNG, PUF, or device-specific pre-seeded key
233  * uint8_t myPrivateKeyingMaterial[CURVE_LENGTH] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
234  * 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
235  * 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
236  * 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01};
237  * uint8_t myPublicKeyingMaterial[2 * CURVE_LENGTH + 1] = {0};
238  * uint8_t theirPublicKeyingMaterial[2 * CURVE_LENGTH + 1] = {0};
239  * uint8_t sharedSecretKeyingMaterial[2 * CURVE_LENGTH + 1] = {0};
240  * uint8_t symmetricKeyingMaterial[16] = {0};
241  *
242  * CryptoKey myPrivateKey;
243  * CryptoKey myPublicKey;
244  * CryptoKey theirPublicKey;
245  * CryptoKey sharedSecret;
246  * CryptoKey symmetricKey;
247  *
248  * ECDH_Handle ecdhHandle;
249  *
250  * int_fast16_t operationResult;
251  *
252  * ECDH_OperationGeneratePublicKey operationGeneratePublicKey;
253  *
254  * // Since we are using default ECDH_Params, we just pass in NULL for that parameter.
255  * ecdhHandle = ECDH_open(0, NULL);
256  *
257  * if (!ecdhHandle) {
258  * // Handle error
259  * }
260  *
261  * // Initialize myPrivateKey and myPublicKey
262  * CryptoKeyPlaintext_initKey(&myPrivateKey, myPrivateKeyingMaterial, sizeof(myPrivateKeyingMaterial));
263  * CryptoKeyPlaintext_initBlankKey(&myPublicKey, myPublicKeyingMaterial, sizeof(myPublicKeyingMaterial));
264  *
265  * ECDH_OperationGeneratePublicKey_init(&operationGeneratePublicKey);
266  * operationGeneratePublicKey.curve = &ECCParams_NISTP256;
267  * operationGeneratePublicKey.myPrivateKey = &myPrivateKey;
268  * operationGeneratePublicKey.myPublicKey = &myPublicKey;
269  *
270  * // Generate the keying material for myPublicKey and store it in myPublicKeyingMaterial
271  * operationResult = ECDH_generatePublicKey(ecdhHandle, &operationGeneratePublicKey);
272  *
273  * if (operationResult != ECDH_STATUS_SUCCESS) {
274  * // Handle error
275  * }
276  *
277  * // Now send the content of myPublicKeyingMaterial to theother party,
278  * // receive their public key, and copy their public keying material and the
279  * // 0x04 byte to theirPublicKeyingMaterial
280  *
281  * // Initialise their public CryptoKey and the shared secret CryptoKey
282  * CryptoKeyPlaintext_initKey(&theirPublicKey, theirPublicKeyingMaterial, sizeof(theirPublicKeyingMaterial));
283  * CryptoKeyPlaintext_initBlankKey(&sharedSecret, sharedSecretKeyingMaterial, sizeof(sharedSecretKeyingMaterial));
284  *
285  * // The ECC_NISTP256 struct is provided in ti/drivers/types/EccParams.h and the corresponding device-specific implementation
286  * ECDH_OperationComputeSharedSecret_init(&operationComputeSharedSecret);
287  * operationComputeSharedSecret.curve = &ECCParams_NISTP256;
288  * operationComputeSharedSecret.myPrivateKey = &myPrivateKey;
289  * operationComputeSharedSecret.theirPublicKey = &theirPublicKey;
290  * operationComputeSharedSecret.sharedSecret = &sharedSecret;
291  *
292  * // Compute the shared secret and copy it to sharedSecretKeyingMaterial
293  * operationResult = ECDH_computeSharedSecret(ecdhHandle, &operationComputeSharedSecret);
294  *
295  * if (operationResult != ECDH_STATUS_SUCCESS) {
296  * // Handle error
297  * }
298  *
299  * CryptoKeyPlaintext_initBlankKey(&symmetricKey, symmetricKeyingMaterial, sizeof(symmetricKeyingMaterial));
300  *
301  * // Set up a KDF such as HKDF and open the requisite cryptographic primitive driver to implement it
302  * // HKDF and SHA2 were chosen as an example and may not be available directly
303  *
304  * // At this point, you and the other party have both created the content within symmetricKeyingMaterial without
305  * // someone else listening to your communication channel being able to do so
306  *
307  * @endcode
308  *
309  *
310  */
311 
312 
313 #ifndef ti_drivers_ECDH__include
314 #define ti_drivers_ECDH__include
315 
316 #include <stdbool.h>
317 #include <stddef.h>
318 #include <stdint.h>
319 
322 
323 #ifdef __cplusplus
324 extern "C" {
325 #endif
326 
339 #define ECDH_STATUS_RESERVED (-32)
340 
347 #define ECDH_STATUS_SUCCESS (0)
348 
355 #define ECDH_STATUS_ERROR (-1)
356 
365 #define ECDH_STATUS_RESOURCE_UNAVAILABLE (-2)
366 
373 #define ECDH_STATUS_POINT_AT_INFINITY (-3)
374 
381 #define ECDH_STATUS_PRIVATE_KEY_LARGER_EQUAL_ORDER (-4)
382 
389 #define ECDH_STATUS_PRIVATE_KEY_ZERO (-5)
390 
397 #define ECDH_STATUS_PUBLIC_KEY_NOT_ON_CURVE (-6)
398 
406 #define ECDH_STATUS_PUBLIC_KEY_LARGER_THAN_PRIME (-7)
407 
411 #define ECDH_STATUS_CANCELED (-8)
412 
421 #define ECDH_STATUS_INVALID_KEY_SIZE (-9)
422 
434 typedef struct {
436  void *object;
437 
439  void const *hwAttrs;
440 } ECDH_Config;
441 
446 
468 typedef enum {
484 
485 
489 typedef struct {
499 
503 typedef struct {
518 
522 typedef union {
526 
530 typedef enum {
534 
553 typedef void (*ECDH_CallbackFxn) (ECDH_Handle handle,
554  int_fast16_t returnStatus,
555  ECDH_Operation operation,
556  ECDH_OperationType operationType);
557 
566 typedef struct {
569  uint32_t timeout;
570  void *custom;
573 } ECDH_Params;
574 
580 extern const ECDH_Params ECDH_defaultParams;
581 
590 void ECDH_init(void);
591 
604 void ECDH_Params_init(ECDH_Params *params);
605 
623 ECDH_Handle ECDH_open(uint_least8_t index, const ECDH_Params *params);
624 
634 void ECDH_close(ECDH_Handle handle);
635 
645 
655 
678 int_fast16_t ECDH_generatePublicKey(ECDH_Handle handle, ECDH_OperationGeneratePublicKey *operation);
679 
699 int_fast16_t ECDH_computeSharedSecret(ECDH_Handle handle, ECDH_OperationComputeSharedSecret *operation);
700 
717 int_fast16_t ECDH_cancelOperation(ECDH_Handle handle);
718 
742 ECDH_Handle ECDH_construct(ECDH_Config *config, const ECDH_Params *params);
743 
744 #ifdef __cplusplus
745 }
746 #endif
747 
748 #endif /* ti_drivers_ECDH__include */
ECDH_OperationType
Enum for the operation types supported by the driver.
Definition: ECDH.h:530
ECC Global configuration.
Definition: ECDH.h:434
The CryptoKey type is an opaque representation of a cryptographic key.
ECDH_Config * ECDH_Handle
A handle that is returned from an ECDH_open() call.
Definition: ECDH.h:445
ECDH_ReturnBehavior returnBehavior
Definition: ECDH.h:567
void ECDH_OperationGeneratePublicKey_init(ECDH_OperationGeneratePublicKey *operation)
Function to initialize an ECDH_OperationGeneratePublicKey struct to its defaults. ...
ECDH_OperationComputeSharedSecret * computeSharedSecret
Definition: ECDH.h:524
int_fast16_t ECDH_cancelOperation(ECDH_Handle handle)
Cancels an ongoing ECDH operation.
Definition: ECDH.h:479
void * object
Definition: ECDH.h:436
void * custom
Definition: ECDH.h:570
Struct containing the parameters required to compute the shared secret.
Definition: ECDH.h:503
CryptoKey datastructure.
Definition: CryptoKey.h:209
const CryptoKey * theirPublicKey
Definition: ECDH.h:510
ECDH_CallbackFxn callbackFxn
Definition: ECDH.h:568
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:553
void ECDH_OperationComputeSharedSecret_init(ECDH_OperationComputeSharedSecret *operation)
Function to initialize an ECDH_OperationComputeSharedSecret struct to its defaults.
ECDH_OperationGeneratePublicKey * generatePublicKey
Definition: ECDH.h:523
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:491
const CryptoKey * myPrivateKey
Definition: ECDH.h:507
const ECCParams_CurveParams * curve
Definition: ECDH.h:504
void ECDH_init(void)
This function initializes the ECC module.
ECC Parameters.
Definition: ECDH.h:566
Definition: ECDH.h:475
ECDH_Handle ECDH_open(uint_least8_t index, const ECDH_Params *params)
This function opens a given ECC peripheral.
uint32_t timeout
Definition: ECDH.h:569
CryptoKey * sharedSecret
Definition: ECDH.h:513
ECDH_ReturnBehavior
The way in which ECC function calls return after performing an encryption + authentication or decrypt...
Definition: ECDH.h:468
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:489
void ECDH_close(ECDH_Handle handle)
Function to close an ECC peripheral specified by the ECC handle.
const ECCParams_CurveParams * curve
Definition: ECDH.h:490
A structure containing the parameters of an elliptic curve in short Weierstrass form.
Definition: ECCParams.h:120
ECDH_Handle ECDH_construct(ECDH_Config *config, const ECDH_Params *params)
Constructs a new ECDH object.
void ECDH_Params_init(ECDH_Params *params)
Function to initialize the ECDH_Params struct to its defaults.
void const * hwAttrs
Definition: ECDH.h:439
CryptoKey * myPublicKey
Definition: ECDH.h:494
Union containing pointers to all supported operation structs.
Definition: ECDH.h:522
Definition: ECDH.h:469
© Copyright 1995-2020, Texas Instruments Incorporated. All rights reserved.
Trademarks | Privacy policy | Terms of use | Terms of sale