1 /*
2  * Copyright (c) 2017-2024, 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 can be stored in big-endian or little-endian format.
91  *        The array should be the same length as the curve parameters of the curve used.
92  *        The driver validates private keys against the provided curve by default.
93  *      - Initialize the private key CryptoKey. CryptoKeys are opaque data structures and representations
94  *        of keying material and its storage. Depending on how the keying material
95  *        is stored (RAM or flash, key store), the CryptoKey must be
96  *        initialized differently. The ECDH API can handle all types of CryptoKey.
97  *        However, not all device-specific implementations support all types of CryptoKey.
98  *        Devices without a key store will not support CryptoKeys with keying material
99  *        stored in a key store for example.
100  *        All devices support plaintext CryptoKeys.
101  *      - Initialize a blank CryptoKey for the public key. The CryptoKey will keep track
102  *        of where the keying material for the public key should be copied and how
103  *        long it is. SEC 1-based big-endian format public keys should have key material twice the length
104  *        of the private key plus one. Little-endian format public keys should have key material the
105  *        length of the private key for Montgomery curve X-only public keys or have key material twice
106  *        the length of the private for other curves
107  *      - Initialize the ECDH_OperationGeneratePublicKey struct and then populate it. By
108  *        default, big-endian public keys will be generated.
109  *      - If using RFC 7748-style public keys, initialize the operation's public key
110  *        data format to be ECDH_LITTLE_ENDIAN_KEY.
111  *      - Call ECDH_generatePublicKey(). The generated keying material will be copied
112  *        according the the CryptoKey passed in as the public key parameter. The CryptoKey
113  *        will no longer be considered 'blank' after the operation.
114  *
115  * ## Calculating a shared secret #
116  * After trading public keys with the other party, the application should do the following
117  * to calculate the shared secret:
118  *      - Initialize a CryptoKey as public key with the keying material received from the other
119  *        party.
120  *      - Initialize the private key CryptoKey with the key used to generate your
121  *        public key. CryptoKeys are opaque data structures and representations
122  *        of keying material and its storage. Depending on how the keying material
123  *        is stored (RAM or flash, key store), the CryptoKey must be
124  *        initialized differently. The ECDH API can handle all types of CryptoKey.
125  *        However, not all device-specific implementations support all types of CryptoKey.
126  *        Devices without a key store will not support CryptoKeys with keying material
127  *        stored in a key store for example.
128  *        All devices support plaintext CryptoKeys.
129  *      - Initialize a blank CryptoKey with the same size as the previously initialized
130  *        public key.
131  *      - Initialize the ECDH_OperationComputeSharedSecret struct and then populate it. By
132  *        default, big-endian input keys will be assumed and big-endian shared secrets
133  *        will be generated.
134  *      - If importing RFC 7748-style public keys, initialize the operation's key material
135  *        endianess to be ECDH_LITTLE_ENDIAN_KEY.
136  *      - Call ECDH_computeSharedSecret(). The shared secret will be copied to a location
137  *        according to the shared secret CryptoKey passed to the function call. The driver
138  *        will validate the supplied public key and reject invalid ones.
139  *
140  * ## Creating one or more symmetric keys from the shared secret #
141  * After calculating the shared secret between the application and the other party,
142  * the entropy in the shared secret must be evened out and stretched as needed. There are
143  * uncountable methods and algorithms to stretch an original seed entropy (the share secret)
144  * to generate symmetric keys.
145  *      - Run the X coordinate of the resulting entropy through a key derivation function (KDF)
146  *
147  * ## After a key exchange #
148  * After the ECDH key exchange completes, the application should either start another operation
149  * or close the driver by calling ECDH_close()
150  *
151  * ## General usage #
152  * The API expects elliptic curves as defined in ti/drivers/cryptoutils/ecc/ECCParams.h.
153  * Several commonly used curves are provided. Check the device-specific ECDH documentation
154  * for curve type (short Weierstrass, Montgomery, Edwards) support for your device.
155  * ECDH support for a curve type on a device does not imply curve-type support for
156  * other ECC schemes.
157  *
158  * ## Key Formatting
159  * By default, the ECDH API expects the private and public keys to be formatted in
160  * big-endian format. The details of octet string formatting can be found in
161  * SEC 1: Elliptic Curve Cryptography.
162  *
163  * Private keys can be formatted as big-endian or little-endian integers of the same
164  * length as the curve length.
165  *
166  * Public keys and shared secrets are points on an elliptic curve. These points can
167  * be expressed in several ways. The most common one is in affine coordinates as an
168  * X,Y pair.
169  * This API uses points expressed in uncompressed affine coordinates by default.
170  * The big-endian format requires a formatting byte in the first byte of the
171  * public key. When using uncompressed affine coordinates, this is the value
172  * 0x04.
173  * The point itself is stored as a concatenated array of X followed by Y.
174  * X and Y maybe in big-endian or little-endian. Some implementations do not require or
175  * yield the Y coordinate for ECDH on certain curves. It is recommended that the full
176  * keying material buffer of twice the curve param length is used to facilitate
177  * code-reuse. Implementations that do not use the Y coordinate will zero-out
178  * the Y-coordinate whenever they write a point to the CryptoKey.
179  *
180  * If device-supported, Montgomery curves can be stored as their X-only format
181  * based on the RFC-7748 specification. Here, only the X coordinate is packed
182  * in little-endian integers of the same length as the curve length.
183  *
184  * This API accepts and returns the keying material of public keys according
185  * to the following table:
186  *
187  * | Curve Type         | Keying Material Array | Array Length               |
188  * |--------------------|-----------------------|----------------------------|
189  * | Short Weierstrass  | [0x04, X, Y]          | 1 + 2 * Curve Param Length |
190  * | Montgomery         | [0x04, X, Y]          | 1 + 2 * Curve Param Length |
191  * | Montgomery         | [X]                   | Curve Param Length         |
192  * | Edwards            | [0x04, X, Y]          | 1 + 2 * Curve Param Length |
193  *
194  * Note: This driver will automatically prune the private key according to
195  *       RFC 7748 for the following curve:
196  *           X25519
197  *
198  * @anchor ti_drivers_ECDH_Synopsis
199  * ## Synopsis
200  * @anchor ti_drivers_ECDH_Synopsis_Code
201  * @code
202  * // Import ECDH Driver definitions
203  * #include <ti/drivers/ECDH.h>
204  *
205  * ECDH_init();
206  *
207  * // Since we are using default ECDH_Params, we just pass in NULL for that parameter.
208  * ecdhHandle = ECDH_open(0, NULL);
209  *
210  * // Initialize myPrivateKey and myPublicKey
211  * CryptoKeyPlaintext_initKey(&myPrivateKey, myPrivateKeyingMaterial, sizeof(myPrivateKeyingMaterial));
212  * CryptoKeyPlaintext_initBlankKey(&myPublicKey, myPublicKeyingMaterial, sizeof(myPublicKeyingMaterial));
213  *
214  * ECDH_OperationGeneratePublicKey_init(&operationGeneratePublicKey);
215  * operationGeneratePublicKey.curve                 = &ECCParams_NISTP256;
216  * operationGeneratePublicKey.myPrivateKey          = &myPrivateKey;
217  * operationGeneratePublicKey.myPublicKey           = &myPublicKey;
218  *
219  * // Generate the keying material for myPublicKey and store it in myPublicKeyingMaterial
220  * operationResult = ECDH_generatePublicKey(ecdhHandle, &operationGeneratePublicKey);
221  *
222  * // Now send the content of myPublicKeyingMaterial to the other party,
223  * // receive their public key, and copy their public keying material to theirPublicKeyingMaterial
224  *
225  * // Initialize their public CryptoKey and the shared secret CryptoKey
226  * CryptoKeyPlaintext_initKey(&theirPublicKey, theirPublicKeyingMaterial, sizeof(theirPublicKeyingMaterial));
227  * CryptoKeyPlaintext_initBlankKey(&sharedSecret, sharedSecretKeyingMaterial, sizeof(sharedSecretKeyingMaterial));
228  *
229  * // The ECC_NISTP256 struct is provided in ti/drivers/types/EccParams.h and the corresponding device-specific
230  * implementation ECDH_OperationComputeSharedSecret_init(&operationComputeSharedSecret);
231  * operationComputeSharedSecret.curve                      = &ECCParams_NISTP256;
232  * operationComputeSharedSecret.myPrivateKey               = &myPrivateKey;
233  * operationComputeSharedSecret.theirPublicKey             = &theirPublicKey;
234  * operationComputeSharedSecret.sharedSecret               = &sharedSecret;
235  *
236  * // Compute the shared secret and copy it to sharedSecretKeyingMaterial
237  * operationResult = ECDH_computeSharedSecret(ecdhHandle, &operationComputeSharedSecret);
238  *
239  * // Close the driver
240  * ECDH_close(ecdhHandle);
241  *
242  * @endcode
243  *
244  * ## Synopsis for X25519 X-only key exchange
245  * @anchor ti_drivers_ECDH_X25519_Code
246  * @code
247  * // Import ECDH Driver definitions
248  * #include <ti/drivers/ECDH.h>
249  *
250  * ECDH_init();
251  *
252  * // Since we are using default ECDH_Params, we just pass in NULL for that parameter.
253  * ecdhHandle = ECDH_open(0, NULL);
254  *
255  * // For CC27XX devices only,
256  * // Since the ECDH driver for CC27XX relies on one HW engine (the HSM) for all of its operations
257  * // If the HSM boot up sequence fails, ECDH_open() will return NULL.
258  * if (!ecdhHandle) {
259  *     // Handle error
260  * }
261  *
262  *
263  * // Initialize myPrivateKey and myPublicKey
264  * CryptoKeyPlaintext_initKey(&myPrivateKey, myPrivateKeyingMaterial, sizeof(myPrivateKeyingMaterial));
265  * // Note that the public key size is only 32 bytes
266  * CryptoKeyPlaintext_initBlankKey(&myPublicKey, myPublicKeyingMaterial, sizeof(myPublicKeyingMaterial));
267  *
268  * ECDH_OperationGeneratePublicKey_init(&operationGeneratePublicKey);
269  * operationGeneratePublicKey.curve                 = &ECCParams_Curve25519;
270  * operationGeneratePublicKey.myPrivateKey          = &myPrivateKey;
271  * operationGeneratePublicKey.myPublicKey           = &myPublicKey;
272  * // If generating public key in little-endian format, we use the following format:
273  * operationGeneratePublicKey.keyMaterialEndianness = ECDH_LITTLE_ENDIAN_KEY;
274  *
275  * // Generate the keying material for myPublicKey and store it in myPublicKeyingMaterial
276  * operationResult = ECDH_generatePublicKey(ecdhHandle, &operationGeneratePublicKey);
277  *
278  * // Now send the content of myPublicKeyingMaterial to the other party,
279  * // receive their public key, and copy their public keying material to theirPublicKeyingMaterial
280  *
281  * // Initialize 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
286  * implementation ECDH_OperationComputeSharedSecret_init(&operationComputeSharedSecret);
287  * operationComputeSharedSecret.curve                      = &ECCParams_Curve25519;
288  * operationComputeSharedSecret.myPrivateKey               = &myPrivateKey;
289  * operationComputeSharedSecret.theirPublicKey             = &theirPublicKey;
290  * operationComputeSharedSecret.sharedSecret               = &sharedSecret;
291  * // If receiving and generating keys in little-endian format, we use the following format:
292  * operationComputeSharedSecret.keyMaterialEndianness      = ECDH_LITTLE_ENDIAN_KEY;
293  *
294  * // Compute the shared secret and copy it to sharedSecretKeyingMaterial
295  * operationResult = ECDH_computeSharedSecret(ecdhHandle, &operationComputeSharedSecret);
296  *
297  * // Close the driver
298  * ECDH_close(ecdhHandle);
299  *
300  * @endcode
301  *
302  * @anchor ti_drivers_ECDH_Examples
303  * # Examples #
304  *
305  * ## ECDH exchange with plaintext CryptoKeys #
306  *
307  * @code
308  *
309  * #include <ti/drivers/cryptoutils/cryptokey/CryptoKeyPlaintext.h>
310  * #include <ti/drivers/ECDH.h>
311  *
312  * #define CURVE_LENGTH 32
313  *
314  * ...
315  *
316  * // Our private key is 0x0000000000000000000000000000000000000000000000000000000000000001
317  * // In practice, this value should come from a TRNG, PRNG, PUF, or device-specific pre-seeded key
318  * uint8_t myPrivateKeyingMaterial[CURVE_LENGTH] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
319  *                                                  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
320  *                                                  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
321  *                                                  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01};
322  * uint8_t myPublicKeyingMaterial[2 * CURVE_LENGTH + 1] = {0};
323  * uint8_t theirPublicKeyingMaterial[2 * CURVE_LENGTH + 1] = {0};
324  * uint8_t sharedSecretKeyingMaterial[2 * CURVE_LENGTH + 1] = {0};
325  * uint8_t symmetricKeyingMaterial[16] = {0};
326  *
327  * CryptoKey myPrivateKey;
328  * CryptoKey myPublicKey;
329  * CryptoKey theirPublicKey;
330  * CryptoKey sharedSecret;
331  * CryptoKey symmetricKey;
332  *
333  * ECDH_Handle ecdhHandle;
334  *
335  * int_fast16_t operationResult;
336  *
337  * ECDH_OperationGeneratePublicKey operationGeneratePublicKey;
338  *
339  * // Since we are using default ECDH_Params, we just pass in NULL for that parameter.
340  * ecdhHandle = ECDH_open(0, NULL);
341  *
342  * if (!ecdhHandle) {
343  *     // Handle error
344  * }
345  *
346  * // Initialize myPrivateKey and myPublicKey
347  * CryptoKeyPlaintext_initKey(&myPrivateKey, myPrivateKeyingMaterial, sizeof(myPrivateKeyingMaterial));
348  * CryptoKeyPlaintext_initBlankKey(&myPublicKey, myPublicKeyingMaterial, sizeof(myPublicKeyingMaterial));
349  *
350  * ECDH_OperationGeneratePublicKey_init(&operationGeneratePublicKey);
351  * operationGeneratePublicKey.curve                 = &ECCParams_NISTP256;
352  * operationGeneratePublicKey.myPrivateKey          = &myPrivateKey;
353  * operationGeneratePublicKey.myPublicKey           =  &myPublicKey;
354  *
355  * // Generate the keying material for myPublicKey and store it in myPublicKeyingMaterial
356  * operationResult = ECDH_generatePublicKey(ecdhHandle, &operationGeneratePublicKey);
357  *
358  * if (operationResult != ECDH_STATUS_SUCCESS) {
359  *     // Handle error
360  * }
361  *
362  * // Now send the content of myPublicKeyingMaterial to the other party,
363  * // receive their public key, and copy their public keying material and the
364  * // 0x04 byte to theirPublicKeyingMaterial
365  *
366  * // Initialise their public CryptoKey and the shared secret CryptoKey
367  * CryptoKeyPlaintext_initKey(&theirPublicKey, theirPublicKeyingMaterial, sizeof(theirPublicKeyingMaterial));
368  * CryptoKeyPlaintext_initBlankKey(&sharedSecret, sharedSecretKeyingMaterial, sizeof(sharedSecretKeyingMaterial));
369  *
370  * // The ECC_NISTP256 struct is provided in ti/drivers/types/EccParams.h and the corresponding device-specific
371  * implementation ECDH_OperationComputeSharedSecret_init(&operationComputeSharedSecret);
372  * operationComputeSharedSecret.curve                      = &ECCParams_NISTP256;
373  * operationComputeSharedSecret.myPrivateKey               = &myPrivateKey;
374  * operationComputeSharedSecret.theirPublicKey             = &theirPublicKey;
375  * operationComputeSharedSecret.sharedSecret               = &sharedSecret;
376  *
377  * // Compute the shared secret and copy it to sharedSecretKeyingMaterial
378  * operationResult = ECDH_computeSharedSecret(ecdhHandle, &operationComputeSharedSecret);
379  *
380  * if (operationResult != ECDH_STATUS_SUCCESS) {
381  *     // Handle error
382  * }
383  *
384  * CryptoKeyPlaintext_initBlankKey(&symmetricKey, symmetricKeyingMaterial, sizeof(symmetricKeyingMaterial));
385  *
386  * // Set up a KDF such as HKDF and open the requisite cryptographic primitive driver to implement it
387  * // HKDF and SHA2 were chosen as an example and may not be available directly
388  *
389  * // At this point, you and the other party have both created the content within symmetricKeyingMaterial without
390  * // someone else listening to your communication channel being able to do so
391  *
392  * @endcode
393  *
394  *
395  */
396 
397 #ifndef ti_drivers_ECDH__include
398 #define ti_drivers_ECDH__include
399 
400 #include <stdbool.h>
401 #include <stddef.h>
402 #include <stdint.h>
403 
404 #include <ti/drivers/cryptoutils/cryptokey/CryptoKey.h>
405 #include <ti/drivers/cryptoutils/ecc/ECCParams.h>
406 
407 #ifdef __cplusplus
408 extern "C" {
409 #endif
410 
411 /*!
412  * Common ECDH status code reservation offset.
413  * ECC driver implementations should offset status codes with
414  * ECDH_STATUS_RESERVED growing negatively.
415  *
416  * Example implementation specific status codes:
417  * @code
418  * #define ECCXYZ_STATUS_ERROR0    ECDH_STATUS_RESERVED - 0
419  * #define ECCXYZ_STATUS_ERROR1    ECDH_STATUS_RESERVED - 1
420  * #define ECCXYZ_STATUS_ERROR2    ECDH_STATUS_RESERVED - 2
421  * @endcode
422  */
423 #define ECDH_STATUS_RESERVED (-32)
424 
425 /*!
426  * @brief   Successful status code.
427  *
428  * Functions return ECDH_STATUS_SUCCESS if the function was executed
429  * successfully.
430  */
431 #define ECDH_STATUS_SUCCESS (0)
432 
433 /*!
434  * @brief   Generic error status code.
435  *
436  * Functions return ECDH_STATUS_ERROR if the function was not executed
437  * successfully.
438  */
439 #define ECDH_STATUS_ERROR (-1)
440 
441 /*!
442  * @brief   An error status code returned if the hardware or software resource
443  * is currently unavailable.
444  *
445  * ECC driver implementations may have hardware or software limitations on how
446  * many clients can simultaneously perform operations. This status code is returned
447  * if the mutual exclusion mechanism signals that an operation cannot currently be performed.
448  */
449 #define ECDH_STATUS_RESOURCE_UNAVAILABLE (-2)
450 
451 /*!
452  * @brief   The result of the operation is the point at infinity.
453  *
454  * The operation yielded the point at infinity on this curve. This point is
455  * not permitted for further use in ECC operations.
456  */
457 #define ECDH_STATUS_POINT_AT_INFINITY (-3)
458 
459 /*!
460  * @brief   The private key passed in is larger or equal to the order of the curve.
461  *
462  * Private keys must be integers in the interval [1, n - 1], where n is the
463  * order of the curve.
464  */
465 #define ECDH_STATUS_PRIVATE_KEY_LARGER_EQUAL_ORDER (-4)
466 
467 /*!
468  * @brief   The private key passed in is zero.
469  *
470  * Private keys must be integers in the interval [1, n - 1], where n is the
471  * order of the curve.
472  */
473 #define ECDH_STATUS_PRIVATE_KEY_ZERO (-5)
474 
475 /*!
476  * @brief   The public key of the other party does not lie upon the curve.
477  *
478  * The public key received from the other party does not lie upon the agreed upon
479  * curve.
480  */
481 #define ECDH_STATUS_PUBLIC_KEY_NOT_ON_CURVE (-6)
482 
483 /*!
484  * @brief   A coordinate of the public key of the other party is too large.
485  *
486  * A coordinate of the public key received from the other party is larger than
487  * the prime of the curve. This implies that the point was not correctly
488  * generated on that curve.
489  */
490 #define ECDH_STATUS_PUBLIC_KEY_LARGER_THAN_PRIME (-7)
491 
492 /*!
493  *  @brief  The ongoing operation was canceled.
494  */
495 #define ECDH_STATUS_CANCELED (-8)
496 
497 /*!
498  *  @brief  The provided CryptoKey does not match the expected size
499  *
500  *  The driver expects the private key to have the same length as other curve
501  *  parameters and the public key to have a length of twice that plus one.
502  *  If the provided CryptoKeys for the public and private keys do not match this
503  *  scheme, this error will be returned.
504  */
505 #define ECDH_STATUS_INVALID_KEY_SIZE (-9)
506 
507 /*!
508  * @brief   Importing generated key into KeyStore failed
509  *
510  * Functions return ECDH_STATUS_KEYSTORE_ERROR if the KeyStore_PSA_importKey()
511  * did not return KEYSTORE_PSA_STATUS_SUCCESS
512  */
513 #define ECDH_STATUS_KEYSTORE_ERROR (-10)
514 
515 /*!
516  *  @brief ECC Global configuration
517  *
518  *  The ECDH_Config structure contains a set of pointers used to characterize
519  *  the ECC driver implementation.
520  *
521  *  This structure needs to be defined before calling ECDH_init() and it must
522  *  not be changed thereafter.
523  *
524  *  @sa     ECDH_init()
525  */
526 typedef struct
527 {
528     /*! Pointer to a driver specific data object */
529     void *object;
530 
531     /*! Pointer to a driver specific hardware attributes structure */
532     void const *hwAttrs;
533 } ECDH_Config;
534 
535 /*!
536  *  @brief  A handle that is returned from an ECDH_open() call.
537  */
538 typedef ECDH_Config *ECDH_Handle;
539 
540 /*!
541  * @brief   The way in which ECDH function calls return after performing a
542  * public key generation or shared secret compution operation.
543  *
544  * Callback return behavior is not supported by software-backed implementations.
545  * A NULL handle will be returned when attempting to open or construct a driver
546  * instance with an unsupported return behavior.
547  *
548  * Not all ECDH operations exhibit the specified return behavior. Functions that
549  * do not require significant computation and cannot offload that computation to
550  * a background thread behave like regular functions. Which functions exhibit
551  * the specfied return behavior is not implementation dependent. Specifically, a
552  * software-backed implementation run on the same CPU as the application will
553  * emulate the return behavior while not actually offloading the computation to
554  * the background thread.
555  *
556  * ECDH functions exhibiting the specified return behavior have restrictions on
557  * the context from which they may be called.
558  *
559  * |                                | Task  | Hwi   | Swi   |
560  * |--------------------------------|-------|-------|-------|
561  * |ECDH_RETURN_BEHAVIOR_CALLBACK   | X     | X     | X     |
562  * |ECDH_RETURN_BEHAVIOR_BLOCKING   | X     |       |       |
563  * |ECDH_RETURN_BEHAVIOR_POLLING    | X     | X     | X     |
564  *
565  */
566 typedef enum
567 {
568     ECDH_RETURN_BEHAVIOR_CALLBACK = 1, /*!< The function call will return immediately while the
569                                         *   ECC operation goes on in the background. The registered
570                                         *   callback function is called after the operation completes.
571                                         *   The context the callback function is called (task, HWI, SWI)
572                                         *   is implementation-dependent.
573                                         */
574     ECDH_RETURN_BEHAVIOR_BLOCKING = 2, /*!< The function call will block while ECC operation goes
575                                         *   on in the background. ECC operation results are available
576                                         *   after the function returns.
577                                         */
578     ECDH_RETURN_BEHAVIOR_POLLING  = 4, /*!< The function call will continuously poll a flag while ECC
579                                         *   operation goes on in the background. ECC operation results
580                                         *   are available after the function returns.
581                                         */
582 } ECDH_ReturnBehavior;
583 
584 typedef enum
585 {
586     ECDH_BIG_ENDIAN_KEY    = 0, /*!< All ECDH key material (private key, public key, and shared secret (when used))
587                                  *   are in big-endian format
588                                  */
589     ECDH_LITTLE_ENDIAN_KEY = 1, /*!< All ECDH key material (private key, public key, and shared secret (when used))
590                                  *   are in little-endian format
591                                  */
592 } ECDH_KeyMaterialEndianness;
593 
594 /*!
595  *  @brief  Struct containing the parameters required to generate a public key.
596  */
597 typedef struct
598 {
599     const ECCParams_CurveParams *curve; /*!< A pointer to the elliptic curve parameters for myPrivateKey */
600     const CryptoKey *myPrivateKey;      /*!< A pointer to the private ECC key from which the new public
601                                          *   key will be generated. (maybe your static key)
602                                          */
603     CryptoKey *myPublicKey;             /*!< A pointer to a public ECC key which has been initialized blank.
604                                          *   Newly generated key will be placed in this location.
605                                          *   The formatting byte will be filled in by the driver if the
606                                          *   keyMaterialEndianness requires it.
607                                          */
608     ECDH_KeyMaterialEndianness keyMaterialEndianness; /*!< All keyMaterials, including myPrivate and myPublicKey,
609                                                        *   are either in big-endian (default) or little-endian format
610                                                        */
611 } ECDH_OperationGeneratePublicKey;
612 
613 /*!
614  *  @brief  Struct containing the parameters required to compute the shared secret.
615  */
616 typedef struct
617 {
618     const ECCParams_CurveParams *curve;               /*!< A pointer to the elliptic curve parameters for myPrivateKey.
619                                                        *   If ECDH_generateKey() was used, this should be the same private key.
620                                                        */
621     const CryptoKey *myPrivateKey;                    /*!< A pointer to the private ECC key which will be used in to
622                                                        *   compute the shared secret.
623                                                        */
624     const CryptoKey *theirPublicKey;                  /*!< A pointer to the public key of the party with whom the
625                                                        *   shared secret will be generated.
626                                                        */
627     CryptoKey *sharedSecret;                          /*!< A pointer to a CryptoKey which has been initialized blank.
628                                                        *   The shared secret will be placed here.
629                                                        *   The formatting byte will be filled in by the driver if the
630                                                        *   keyMaterialEndianness requires it.
631                                                        */
632     ECDH_KeyMaterialEndianness keyMaterialEndianness; /*!< All keyMaterials, including myPrivate, theirPublicKey, and
633                                                        *   sharedSecret are either in big-endian (default) or little-
634                                                        *   endian format
635                                                        */
636 } ECDH_OperationComputeSharedSecret;
637 
638 /*!
639  *  @brief  Union containing pointers to all supported operation structs.
640  */
641 typedef union
642 {
643     ECDH_OperationGeneratePublicKey *generatePublicKey; /*!< A pointer to an ECDH_OperationGeneratePublicKey struct */
644     ECDH_OperationComputeSharedSecret *computeSharedSecret; /*!< A pointer to an ECDH_OperationComputeSharedSecret
645                                                              * struct
646                                                              */
647 } ECDH_Operation;
648 
649 /*!
650  *  @brief  Enum for the operation types supported by the driver.
651  */
652 typedef enum
653 {
654     ECDH_OPERATION_TYPE_GENERATE_PUBLIC_KEY   = 1,
655     ECDH_OPERATION_TYPE_COMPUTE_SHARED_SECRET = 2,
656 } ECDH_OperationType;
657 
658 /*!
659  *  @brief  The definition of a callback function used by the ECDH driver
660  *          when used in ::ECDH_RETURN_BEHAVIOR_CALLBACK
661  *
662  *  @param  handle Handle of the client that started the ECDH operation.
663  *
664  *  @param  returnStatus The result of the ECDH operation. May contain an error code
665  *          if the result is the point at infinity for example.
666  *
667  *  @param  operation A union of pointers to operation structs. Only one type
668  *          of pointer is valid per call to the callback function. Which type
669  *          is currently valid is determined by /c operationType. The union
670  *          allows easier access to the struct's fields without the need to
671  *          typecase the result.
672  *
673  *  @param  operationType This parameter determined which operation the
674  *          callback refers to and which type to access through /c operation.
675  */
676 typedef void (*ECDH_CallbackFxn)(ECDH_Handle handle,
677                                  int_fast16_t returnStatus,
678                                  ECDH_Operation operation,
679                                  ECDH_OperationType operationType);
680 
681 /*!
682  *  @brief  ECC Parameters
683  *
684  *  ECC Parameters are used to with the ECDH_open() call. Default values for
685  *  these parameters are set using ECDH_Params_init().
686  *
687  *  @sa     ECDH_Params_init()
688  */
689 typedef struct
690 {
691     ECDH_ReturnBehavior returnBehavior; /*!< Blocking, callback, or polling return behavior */
692     ECDH_CallbackFxn callbackFxn;       /*!< Callback function pointer */
693     uint32_t timeout;                   /*!< Timeout of the operation */
694     void *custom;                       /*!< Custom argument used by driver
695                                          *   implementation
696                                          */
697 } ECDH_Params;
698 
699 /*!
700  *  @brief Default ECDH_Params structure
701  *
702  *  @sa     ECDH_Params_init()
703  */
704 extern const ECDH_Params ECDH_defaultParams;
705 
706 /*!
707  *  @brief  This function initializes the ECC module.
708  *
709  *  @pre    The ECDH_config structure must exist and be persistent before this
710  *          function can be called. This function must also be called before
711  *          any other ECC driver APIs. This function call does not modify any
712  *          peripheral registers.
713  */
714 void ECDH_init(void);
715 
716 /*!
717  *  @brief  Function to initialize the ECDH_Params struct to its defaults
718  *
719  *  @param  params      An pointer to ECDH_Params structure for
720  *                      initialization
721  *
722  *  Defaults values are:
723  *      returnBehavior              = ECDH_RETURN_BEHAVIOR_BLOCKING
724  *      callbackFxn                 = NULL
725  *      timeout                     = SemaphoreP_WAIT_FOREVER
726  *      custom                      = NULL
727  */
728 void ECDH_Params_init(ECDH_Params *params);
729 
730 /*!
731  *  @brief  This function opens a given ECC peripheral.
732  *
733  *  @pre    ECC controller has been initialized using ECDH_init()
734  *
735  *  @param  index         Logical peripheral number for the ECC indexed into
736  *                        the ECDH_config table
737  *
738  *  @param  params        Pointer to an parameter block, if NULL it will use
739  *                        default values.
740  *
741  *  @return An ECDH_Handle on success or a NULL on an error or if it has been
742  *          opened already.
743  *
744  *  @sa     ECDH_init()
745  *  @sa     ECDH_close()
746  */
747 ECDH_Handle ECDH_open(uint_least8_t index, const ECDH_Params *params);
748 
749 /*!
750  *  @brief  Function to close an ECC peripheral specified by the ECC handle
751  *
752  *  @pre    ECDH_open() has to be called first.
753  *
754  *  @param  handle An ECC handle returned from ECDH_open()
755  *
756  *  @sa     ECDH_open()
757  */
758 void ECDH_close(ECDH_Handle handle);
759 
760 /*!
761  *  @brief  Function to initialize an ECDH_OperationGeneratePublicKey struct to its defaults
762  *
763  *  @param  operation   A pointer to ECDH_OperationGeneratePublicKey structure for
764  *                      initialization
765  *
766  *  Defaults values are all zeros.
767  */
768 void ECDH_OperationGeneratePublicKey_init(ECDH_OperationGeneratePublicKey *operation);
769 
770 /*!
771  *  @brief  Function to initialize an ECDH_OperationComputeSharedSecret struct to its defaults
772  *
773  *  @param  operation   A pointer to ECDH_OperationComputeSharedSecret structure for
774  *                      initialization
775  *
776  *  Defaults values are all zeros.
777  */
778 void ECDH_OperationComputeSharedSecret_init(ECDH_OperationComputeSharedSecret *operation);
779 
780 /*!
781  *  @brief Generates a public key for use in key agreement.
782  *
783  *  This function can be used to generate a public key from a private key.
784  *
785  *  @param      handle          A ECDH handle returned from ECDH_open()
786  *
787  *  @param      operation       A pointer to a struct containing the requisite
788  *                              parameters to execute the function.
789  *
790  *  @pre Call ECDH_OperationGeneratePublicKey_init() on @c operation.
791  *
792  *  @post ECDH_computeSharedSecret()
793  *
794  *  @retval #ECDH_STATUS_SUCCESS                          The operation succeeded.
795  *  @retval #ECDH_STATUS_ERROR                            The operation failed.
796  *  @retval #ECDH_STATUS_RESOURCE_UNAVAILABLE             The required hardware resource was not available. Try again
797  * later.
798  *  @retval #ECDH_STATUS_CANCELED                         The operation was canceled.
799  *  @retval #ECDH_STATUS_POINT_AT_INFINITY                The computed public key is the point at infinity.
800  *  @retval #ECDH_STATUS_PRIVATE_KEY_ZERO                 The provided private key is zero.
801  *  @retval #ECDH_STATUS_PRIVATE_KEY_LARGER_EQUAL_ORDER   The provided private key is larger than or equal to the order
802  * of the curve.
803  *
804  */
805 int_fast16_t ECDH_generatePublicKey(ECDH_Handle handle, ECDH_OperationGeneratePublicKey *operation);
806 
807 /*!
808  *  @brief Computes a shared secret
809  *
810  *  This secret can be used to generate shared keys for encryption and authentication.
811  *
812  *  @param      handle              A ECDH handle returned from ECDH_open()
813  *
814  *  @param      operation       A pointer to a struct containing the requisite
815  *
816  *  @pre Call ECDH_OperationComputeSharedSecret_init() on \c operation.
817  *       Generate a shared secret off-chip or using ECDH_generatePublicKey()
818  *
819  *  @retval #ECDH_STATUS_SUCCESS                        The operation succeeded.
820  *  @retval #ECDH_STATUS_ERROR                          The operation failed.
821  *  @retval #ECDH_STATUS_RESOURCE_UNAVAILABLE           The required hardware resource was not available. Try again
822  * later.
823  *  @retval #ECDH_STATUS_CANCELED                       The operation was canceled.
824  *  @retval #ECDH_STATUS_PUBLIC_KEY_NOT_ON_CURVE        The foreign public key is not a point on the specified curve.
825  *  @retval #ECDH_STATUS_PUBLIC_KEY_LARGER_THAN_PRIME   One of the public key coordinates is larger the the curve's
826  * prime.
827  */
828 int_fast16_t ECDH_computeSharedSecret(ECDH_Handle handle, ECDH_OperationComputeSharedSecret *operation);
829 
830 /*!
831  *  @brief Cancels an ongoing ECDH operation.
832  *
833  *  Asynchronously cancels an ECDH operation. Only available when using
834  *  ECDH_RETURN_BEHAVIOR_CALLBACK or ECDH_RETURN_BEHAVIOR_BLOCKING.
835  *  The operation will terminate as though an error occurred. The
836  *  return status code of the operation will be ECDH_STATUS_CANCELED.
837  *
838  *  @param  handle Handle of the operation to cancel
839  *
840  *  @retval #ECDH_STATUS_SUCCESS               The operation was canceled.
841  *  @retval #ECDH_STATUS_ERROR                 The operation was not canceled. There may be no operation to cancel.
842  */
843 int_fast16_t ECDH_cancelOperation(ECDH_Handle handle);
844 
845 /**
846  *  @brief  Constructs a new ECDH object
847  *
848  *  Unlike #ECDH_open(), #ECDH_construct() does not require the hwAttrs and
849  *  object to be allocated in a #ECDH_Config array that is indexed into.
850  *  Instead, the #ECDH_Config, hwAttrs, and object can be allocated at any
851  *  location. This allows for relatively simple run-time allocation of temporary
852  *  driver instances on the stack or the heap.
853  *  The drawback is that this makes it more difficult to write device-agnostic
854  *  code. If you use an ifdef with DeviceFamily, you can choose the correct
855  *  object and hwAttrs to allocate. That compilation unit will be tied to the
856  *  device it was compiled for at this point. To change devices, recompilation
857  *  of the application with a different DeviceFamily setting is necessary.
858  *
859  *  @param  config #ECDH_Config describing the location of the object and hwAttrs.
860  *
861  *  @param  params #ECDH_Params to configure the driver instance.
862  *
863  *  @return        Returns a #ECDH_Handle on success or NULL on failure.
864  *
865  *  @pre    The object struct @c config points to must be zeroed out prior to
866  *          calling this function. Otherwise, unexpected behavior may ensue.
867  */
868 ECDH_Handle ECDH_construct(ECDH_Config *config, const ECDH_Params *params);
869 
870 #ifdef __cplusplus
871 }
872 #endif
873 
874 #endif /* ti_drivers_ECDH__include */
875