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 highest address of the array (big-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 plus one.
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  * ## Key Formatting
143  * The ECDH API expects the private and public keys to be formatted in octet
144  * string format. The details of octet string formatting can be found in
145  * SEC 1: Elliptic Curve Cryptography.
146  *
147  * Private keys are formatted as big-endian integers of the same length as the
148  * curve length.
149  *
150  * Public keys and shared secrets are points on an elliptic curve. These points can
151  * be expressed in several ways. The most common one is in affine coordinates as an
152  * X,Y pair.
153  * This API uses points expressed in uncompressed affine coordinates by default.
154  * The octet string format requires a formatting byte in the first byte of the
155  * public key. When using uncompressed affine coordinates, this is the value
156  * 0x04.
157  * The point itself is stored as a concatenated array of X followed by Y.
158  * X and Y are big-endian. Some implementations do not require or yield
159  * the Y coordinate for ECDH on certain curves. It is recommended that the full
160  * keying material buffer of twice the curve param length is used to facilitate
161  * code-reuse. Implementations that do not use the Y coordinate will zero-out
162  * the Y-coordinate whenever they write a point to the CryptoKey.
163  *
164  * This API accepts and returns the keying material of public keys according
165  * to the following table:
166  *
167  * | Curve Type | Keying Material Array | Array Length |
168  * |--------------------|-----------------------|----------------------------|
169  * | Short Weierstrass | [0x04, X, Y] | 1 + 2 * Curve Param Length |
170  * | Montgomery | [0x04, X, Y] | 1 + 2 * Curve Param Length |
171  * | Edwards | [0x04, X, Y] | 1 + 2 * Curve Param Length |
172  *
173  * @anchor ti_drivers_ECDH_Synopsis
174  * ## Synopsis
175  * @anchor ti_drivers_ECDH_Synopsis_Code
176  * @code
177  * // Import ECDH Driver definitions
178  * #include <ti/drivers/ECDH.h>
179  *
180  * ECDH_init();
181  *
182  * // Since we are using default ECDH_Params, we just pass in NULL for that parameter.
183  * ecdhHandle = ECDH_open(0, NULL);
184  *
185  * // Initialize myPrivateKey and myPublicKey
186  * CryptoKeyPlaintext_initKey(&myPrivateKey, myPrivateKeyingMaterial, sizeof(myPrivateKeyingMaterial));
187  * CryptoKeyPlaintext_initBlankKey(&myPublicKey, myPublicKeyingMaterial, sizeof(myPublicKeyingMaterial));
188  *
189  * ECDH_OperationGeneratePublicKey_init(&operationGeneratePublicKey);
190  * operationGeneratePublicKey.curve = &ECCParams_NISTP256;
191  * operationGeneratePublicKey.myPrivateKey = &myPrivateKey;
192  * operationGeneratePublicKey.myPublicKey = &myPublicKey;
193  *
194  * // Generate the keying material for myPublicKey and store it in myPublicKeyingMaterial
195  * operationResult = ECDH_generatePublicKey(ecdhHandle, &operationGeneratePublicKey);
196  *
197  * // Now send the content of myPublicKeyingMaterial to theother party,
198  * // receive their public key, and copy their public keying material to theirPublicKeyingMaterial
199  *
200  * // Initialise their public CryptoKey and the shared secret CryptoKey
201  * CryptoKeyPlaintext_initKey(&theirPublicKey, theirPublicKeyingMaterial, sizeof(theirPublicKeyingMaterial));
202  * CryptoKeyPlaintext_initBlankKey(&sharedSecret, sharedSecretKeyingMaterial, sizeof(sharedSecretKeyingMaterial));
203  *
204  * // The ECC_NISTP256 struct is provided in ti/drivers/types/EccParams.h and the corresponding device-specific implementation
205  * ECDH_OperationComputeSharedSecret_init(&operationComputeSharedSecret);
206  * operationComputeSharedSecret.curve = &ECCParams_NISTP256;
207  * operationComputeSharedSecret.myPrivateKey = &myPrivateKey;
208  * operationComputeSharedSecret.theirPublicKey = &theirPublicKey;
209  * operationComputeSharedSecret.sharedSecret = &sharedSecret;
210  *
211  * // Compute the shared secret and copy it to sharedSecretKeyingMaterial
212  * operationResult = ECDH_computeSharedSecret(ecdhHandle, &operationComputeSharedSecret);
213  *
214  * // Close the driver
215  * ECDH_close(ecdhHandle);
216  *
217  * @endcode
218  *
219  * @anchor ti_drivers_ECDH_Examples
220  * # Examples #
221  *
222  * ## ECDH exchange with plaintext CryptoKeys #
223  *
224  * @code
225  *
226  * #include <ti/drivers/cryptoutils/cryptokey/CryptoKeyPlaintext.h>
227  * #include <ti/drivers/ECDH.h>
228  *
229  * #define CURVE_LENGTH 32
230  *
231  * ...
232  *
233  * // Our private key is 0x0000000000000000000000000000000000000000000000000000000000000001
234  * // In practice, this value should come from a TRNG, PRNG, PUF, or device-specific pre-seeded key
235  * uint8_t myPrivateKeyingMaterial[CURVE_LENGTH] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
236  * 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
237  * 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
238  * 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01};
239  * uint8_t myPublicKeyingMaterial[2 * CURVE_LENGTH + 1] = {0};
240  * uint8_t theirPublicKeyingMaterial[2 * CURVE_LENGTH + 1] = {0};
241  * uint8_t sharedSecretKeyingMaterial[2 * CURVE_LENGTH + 1] = {0};
242  * uint8_t symmetricKeyingMaterial[16] = {0};
243  *
244  * CryptoKey myPrivateKey;
245  * CryptoKey myPublicKey;
246  * CryptoKey theirPublicKey;
247  * CryptoKey sharedSecret;
248  * CryptoKey symmetricKey;
249  *
250  * ECDH_Handle ecdhHandle;
251  *
252  * int_fast16_t operationResult;
253  *
254  * ECDH_OperationGeneratePublicKey operationGeneratePublicKey;
255  *
256  * // Since we are using default ECDH_Params, we just pass in NULL for that parameter.
257  * ecdhHandle = ECDH_open(0, NULL);
258  *
259  * if (!ecdhHandle) {
260  * // Handle error
261  * }
262  *
263  * // Initialize myPrivateKey and myPublicKey
264  * CryptoKeyPlaintext_initKey(&myPrivateKey, myPrivateKeyingMaterial, sizeof(myPrivateKeyingMaterial));
265  * CryptoKeyPlaintext_initBlankKey(&myPublicKey, myPublicKeyingMaterial, sizeof(myPublicKeyingMaterial));
266  *
267  * ECDH_OperationGeneratePublicKey_init(&operationGeneratePublicKey);
268  * operationGeneratePublicKey.curve = &ECCParams_NISTP256;
269  * operationGeneratePublicKey.myPrivateKey = &myPrivateKey;
270  * operationGeneratePublicKey.myPublicKey = &myPublicKey;
271  *
272  * // Generate the keying material for myPublicKey and store it in myPublicKeyingMaterial
273  * operationResult = ECDH_generatePublicKey(ecdhHandle, &operationGeneratePublicKey);
274  *
275  * if (operationResult != ECDH_STATUS_SUCCESS) {
276  * // Handle error
277  * }
278  *
279  * // Now send the content of myPublicKeyingMaterial to theother party,
280  * // receive their public key, and copy their public keying material and the
281  * // 0x04 byte to theirPublicKeyingMaterial
282  *
283  * // Initialise their public CryptoKey and the shared secret CryptoKey
284  * CryptoKeyPlaintext_initKey(&theirPublicKey, theirPublicKeyingMaterial, sizeof(theirPublicKeyingMaterial));
285  * CryptoKeyPlaintext_initBlankKey(&sharedSecret, sharedSecretKeyingMaterial, sizeof(sharedSecretKeyingMaterial));
286  *
287  * // The ECC_NISTP256 struct is provided in ti/drivers/types/EccParams.h and the corresponding device-specific implementation
288  * ECDH_OperationComputeSharedSecret_init(&operationComputeSharedSecret);
289  * operationComputeSharedSecret.curve = &ECCParams_NISTP256;
290  * operationComputeSharedSecret.myPrivateKey = &myPrivateKey;
291  * operationComputeSharedSecret.theirPublicKey = &theirPublicKey;
292  * operationComputeSharedSecret.sharedSecret = &sharedSecret;
293  *
294  * // Compute the shared secret and copy it to sharedSecretKeyingMaterial
295  * operationResult = ECDH_computeSharedSecret(ecdhHandle, &operationComputeSharedSecret);
296  *
297  * if (operationResult != ECDH_STATUS_SUCCESS) {
298  * // Handle error
299  * }
300  *
301  * CryptoKeyPlaintext_initBlankKey(&symmetricKey, symmetricKeyingMaterial, sizeof(symmetricKeyingMaterial));
302  *
303  * // Set up a KDF such as HKDF and open the requisite cryptographic primitive driver to implement it
304  * // HKDF and SHA2 were chosen as an example and may not be available directly
305  *
306  * // At this point, you and the other party have both created the content within symmetricKeyingMaterial without
307  * // someone else listening to your communication channel being able to do so
308  *
309  * @endcode
310  *
311  *
312  */
313 
314 
315 #ifndef ti_drivers_ECDH__include
316 #define ti_drivers_ECDH__include
317 
318 #include <stdbool.h>
319 #include <stddef.h>
320 #include <stdint.h>
321 
324 
325 #ifdef __cplusplus
326 extern "C" {
327 #endif
328 
341 #define ECDH_STATUS_RESERVED (-32)
342 
349 #define ECDH_STATUS_SUCCESS (0)
350 
357 #define ECDH_STATUS_ERROR (-1)
358 
367 #define ECDH_STATUS_RESOURCE_UNAVAILABLE (-2)
368 
375 #define ECDH_STATUS_POINT_AT_INFINITY (-3)
376 
383 #define ECDH_STATUS_PRIVATE_KEY_LARGER_EQUAL_ORDER (-4)
384 
391 #define ECDH_STATUS_PRIVATE_KEY_ZERO (-5)
392 
399 #define ECDH_STATUS_PUBLIC_KEY_NOT_ON_CURVE (-6)
400 
408 #define ECDH_STATUS_PUBLIC_KEY_LARGER_THAN_PRIME (-7)
409 
413 #define ECDH_STATUS_CANCELED (-8)
414 
423 #define ECDH_STATUS_INVALID_KEY_SIZE (-9)
424 
436 typedef struct {
438  void *object;
439 
441  void const *hwAttrs;
442 } ECDH_Config;
443 
448 
470 typedef enum {
486 
487 
491 typedef struct {
501 
505 typedef struct {
520 
524 typedef union {
528 
532 typedef enum {
536 
555 typedef void (*ECDH_CallbackFxn) (ECDH_Handle handle,
556  int_fast16_t returnStatus,
557  ECDH_Operation operation,
558  ECDH_OperationType operationType);
559 
568 typedef struct {
571  uint32_t timeout;
572  void *custom;
575 } ECDH_Params;
576 
582 extern const ECDH_Params ECDH_defaultParams;
583 
592 void ECDH_init(void);
593 
606 void ECDH_Params_init(ECDH_Params *params);
607 
625 ECDH_Handle ECDH_open(uint_least8_t index, const ECDH_Params *params);
626 
636 void ECDH_close(ECDH_Handle handle);
637 
647 
657 
680 int_fast16_t ECDH_generatePublicKey(ECDH_Handle handle, ECDH_OperationGeneratePublicKey *operation);
681 
701 int_fast16_t ECDH_computeSharedSecret(ECDH_Handle handle, ECDH_OperationComputeSharedSecret *operation);
702 
716 int_fast16_t ECDH_cancelOperation(ECDH_Handle handle);
717 
741 ECDH_Handle ECDH_construct(ECDH_Config *config, const ECDH_Params *params);
742 
743 #ifdef __cplusplus
744 }
745 #endif
746 
747 #endif /* ti_drivers_ECDH__include */
ECDH_OperationType
Enum for the operation types supported by the driver.
Definition: ECDH.h:532
ECC Global configuration.
Definition: ECDH.h:436
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:447
ECDH_ReturnBehavior returnBehavior
Definition: ECDH.h:569
void ECDH_OperationGeneratePublicKey_init(ECDH_OperationGeneratePublicKey *operation)
Function to initialize an ECDH_OperationGeneratePublicKey struct to its defaults. ...
ECDH_OperationComputeSharedSecret * computeSharedSecret
Definition: ECDH.h:526
int_fast16_t ECDH_cancelOperation(ECDH_Handle handle)
Cancels an ongoing ECDH operation.
Definition: ECDH.h:481
void * object
Definition: ECDH.h:438
void * custom
Definition: ECDH.h:572
Struct containing the parameters required to compute the shared secret.
Definition: ECDH.h:505
CryptoKey datastructure.
Definition: CryptoKey.h:209
const CryptoKey * theirPublicKey
Definition: ECDH.h:512
ECDH_CallbackFxn callbackFxn
Definition: ECDH.h:570
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:555
void ECDH_OperationComputeSharedSecret_init(ECDH_OperationComputeSharedSecret *operation)
Function to initialize an ECDH_OperationComputeSharedSecret struct to its defaults.
ECDH_OperationGeneratePublicKey * generatePublicKey
Definition: ECDH.h:525
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:493
const CryptoKey * myPrivateKey
Definition: ECDH.h:509
const ECCParams_CurveParams * curve
Definition: ECDH.h:506
void ECDH_init(void)
This function initializes the ECC module.
ECC Parameters.
Definition: ECDH.h:568
Definition: ECDH.h:477
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:571
CryptoKey * sharedSecret
Definition: ECDH.h:515
ECDH_ReturnBehavior
The way in which ECC function calls return after performing an encryption + authentication or decrypt...
Definition: ECDH.h:470
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:491
void ECDH_close(ECDH_Handle handle)
Function to close an ECC peripheral specified by the ECC handle.
const ECCParams_CurveParams * curve
Definition: ECDH.h:492
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:441
CryptoKey * myPublicKey
Definition: ECDH.h:496
Union containing pointers to all supported operation structs.
Definition: ECDH.h:524
Definition: ECDH.h:471
© Copyright 1995-2019, Texas Instruments Incorporated. All rights reserved.
Trademarks | Privacy policy | Terms of use | Terms of sale