1 /*
2  * Copyright (c) 2021-2023, 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  *  ======== ECCParamsLPF3SW.c ========
34  *
35  *  This file contains structure definitions for various ECC curves for use
36  *  on L devices.
37  */
38 
39 #include <stdbool.h>
40 #include <stdint.h>
41 #include <string.h>
42 
43 #include <ti/drivers/cryptoutils/ecc/ECCParams.h>
44 #include <ti/drivers/cryptoutils/cryptokey/CryptoKey.h>
45 
46 /*
47  * Curve parameters are formatted as little-endian integers with a prepended
48  * length word in words as required by the ECC SW library.
49  */
50 
51 /*
52  * NIST P256 curve params in little endian format.
53  * byte[0-3] are the param length word as required by the ECC SW library.
54  * byte[4] is the least significant byte of the curve parameter.
55  */
56 const ECC_NISTP256_Param ECC_NISTP256_generatorX = {
57     .byte = {0x08, 0x00, 0x00, 0x00, /* Length word prefix */
58              0x96, 0xc2, 0x98, 0xd8, 0x45, 0x39, 0xa1, 0xf4, 0xa0, 0x33, 0xeb, 0x2d, 0x81, 0x7d, 0x03, 0x77,
59              0xf2, 0x40, 0xa4, 0x63, 0xe5, 0xe6, 0xbc, 0xf8, 0x47, 0x42, 0x2c, 0xe1, 0xf2, 0xd1, 0x17, 0x6b}};
60 
61 const ECC_NISTP256_Param ECC_NISTP256_generatorY = {
62     .byte = {0x08, 0x00, 0x00, 0x00, /* Length word prefix */
63              0xf5, 0x51, 0xbf, 0x37, 0x68, 0x40, 0xb6, 0xcb, 0xce, 0x5e, 0x31, 0x6b, 0x57, 0x33, 0xce, 0x2b,
64              0x16, 0x9e, 0x0f, 0x7c, 0x4a, 0xeb, 0xe7, 0x8e, 0x9b, 0x7f, 0x1a, 0xfe, 0xe2, 0x42, 0xe3, 0x4f}};
65 
66 const ECC_NISTP256_Param ECC_NISTP256_prime = {
67     .byte = {0x08, 0x00, 0x00, 0x00, /* Length word prefix */
68              0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
69              0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff}};
70 
71 const ECC_NISTP256_Param ECC_NISTP256_a = {.byte = {0x08, 0x00, 0x00, 0x00, /* Length word prefix */
72                                                     0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
73                                                     0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
74                                                     0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff}};
75 
76 const ECC_NISTP256_Param ECC_NISTP256_b = {.byte = {0x08, 0x00, 0x00, 0x00, /* Length word prefix */
77                                                     0x4b, 0x60, 0xd2, 0x27, 0x3e, 0x3c, 0xce, 0x3b, 0xf6, 0xb0, 0x53,
78                                                     0xcc, 0xb0, 0x06, 0x1d, 0x65, 0xbc, 0x86, 0x98, 0x76, 0x55, 0xbd,
79                                                     0xeb, 0xb3, 0xe7, 0x93, 0x3a, 0xaa, 0xd8, 0x35, 0xc6, 0x5a}};
80 
81 const ECC_NISTP256_Param ECC_NISTP256_order = {
82     .byte = {0x08, 0x00, 0x00, 0x00, /* Length word prefix */
83              0x51, 0x25, 0x63, 0xfc, 0xc2, 0xca, 0xb9, 0xf3, 0x84, 0x9e, 0x17, 0xa7, 0xad, 0xfa, 0xe6, 0xbc,
84              0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff}};
85 
86 /*
87  * Curve params in Montgomery domain are used for public key validation only
88  * and are not prefixed with a length word.
89  */
90 /* Invert of square of Montgomery constant, k = 2^(256) mod p, p is the curve prime */
91 const ECC_NISTP256_Param ECC_NISTP256_k_mont = {
92     .byte = {0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xff, 0xff, 0xff,
93              0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00}};
94 
95 /* Converted to Montgomery domain by modular multiplication of ECC_NISTP256_a with ECC_NISTP224_k_mont */
96 const ECC_NISTP256_Param ECC_NISTP256_a_mont = {
97     .byte = {0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00,
98              0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, 0xff}};
99 
100 /* Converted to Montgomery domain by modular multiplication of ECC_NISTP256_b with ECC_NISTP224_k_mont */
101 const ECC_NISTP256_Param ECC_NISTP256_b_mont = {
102     .byte = {0xdf, 0xbd, 0xc4, 0x29, 0x62, 0xdf, 0x9c, 0xd8, 0x90, 0x30, 0x84, 0x78, 0xcd, 0x05, 0xf0, 0xac,
103              0xd6, 0x2e, 0x21, 0xf7, 0xab, 0x20, 0xa2, 0xe5, 0x34, 0x48, 0x87, 0x04, 0x1d, 0x06, 0x30, 0xdc}};
104 
105 const ECCParams_CurveParams ECCParams_NISTP256 = {.curveType  = ECCParams_CURVE_TYPE_SHORT_WEIERSTRASS_AN3,
106                                                   .length     = ECCParams_NISTP256_LENGTH,
107                                                   .prime      = ECC_NISTP256_prime.byte,
108                                                   .order      = ECC_NISTP256_order.byte,
109                                                   .a          = ECC_NISTP256_a.byte,
110                                                   .b          = ECC_NISTP256_b.byte,
111                                                   .generatorX = ECC_NISTP256_generatorX.byte,
112                                                   .generatorY = ECC_NISTP256_generatorY.byte,
113                                                   .cofactor   = 1};
114 
115 /*
116  * NIST P224 curve params in little endian format.
117  * byte[0-3] are the param length word as required by the ECC SW library.
118  * byte[4] is the least significant byte of the curve parameter.
119  */
120 const ECC_NISTP224_Param ECC_NISTP224_generatorX = {.byte = {0x07, 0x00, 0x00, 0x00, /* Length word prefix */
121                                                              0x21, 0x1d, 0x5c, 0x11, 0xd6, 0x80, 0x32, 0x34, 0x22, 0x11,
122                                                              0xc2, 0x56, 0xd3, 0xc1, 0x03, 0x4a, 0xb9, 0x90, 0x13, 0x32,
123                                                              0x7f, 0xbf, 0xb4, 0x6b, 0xbd, 0x0c, 0x0e, 0xb7}};
124 
125 const ECC_NISTP224_Param ECC_NISTP224_generatorY = {.byte = {
126                                                         0x07, 0x00, 0x00, 0x00, /* Length word prefix */
127                                                         0x34, 0x7e, 0x00, 0x85, 0x99, 0x81, 0xd5, 0x44, 0x64, 0x47,
128                                                         0x07, 0x5a, 0xa0, 0x75, 0x43, 0xcd, 0xe6, 0xdf, 0x22, 0x4c,
129                                                         0xfb, 0x23, 0xf7, 0xb5, 0x88, 0x63, 0x37, 0xbd,
130                                                     }};
131 
132 const ECC_NISTP224_Param ECC_NISTP224_prime = {.byte = {0x07, 0x00, 0x00, 0x00, /* Length word prefix */
133                                                         0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
134                                                         0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
135                                                         0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}};
136 
137 const ECC_NISTP224_Param ECC_NISTP224_a = {.byte = {0x07, 0x00, 0x00, 0x00, /* Length word prefix */
138                                                     0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
139                                                     0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
140                                                     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}};
141 
142 const ECC_NISTP224_Param ECC_NISTP224_b = {.byte = {0x07, 0x00, 0x00, 0x00, /* Length word prefix */
143                                                     0xb4, 0xff, 0x55, 0x23, 0x43, 0x39, 0x0b, 0x27, 0xba, 0xd8,
144                                                     0xbf, 0xd7, 0xb7, 0xb0, 0x44, 0x50, 0x56, 0x32, 0x41, 0xf5,
145                                                     0xab, 0xb3, 0x04, 0x0c, 0x85, 0x0a, 0x05, 0xb4}};
146 
147 const ECC_NISTP224_Param ECC_NISTP224_order = {.byte = {0x07, 0x00, 0x00, 0x00, /* Length word prefix */
148                                                         0x3d, 0x2a, 0x5c, 0x5c, 0x45, 0x29, 0xdd, 0x13, 0x3e, 0xf0,
149                                                         0xb8, 0xe0, 0xa2, 0x16, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
150                                                         0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}};
151 
152 /*
153  * Curve params in Montgomery domain are used for public key validation only
154  * and are not prefixed with a length word.
155  */
156 /* Invert of square of Montgomery constant, k = 2^(224) mod p, p is the curve prime */
157 const ECC_NISTP224_Param ECC_NISTP224_k_mont = {.byte = {0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
158                                                          0x00, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
159                                                          0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00}};
160 
161 /* Converted to Montgomery domain by modular multiplication of ECC_NISTP224_a with ECC_NISTP224_k_mont */
162 const ECC_NISTP224_Param ECC_NISTP224_a_mont = {.byte = {0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
163                                                          0x00, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
164                                                          0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}};
165 
166 /* Converted to Montgomery domain by modular multiplication of ECC_NISTP224_b with ECC_NISTP224_k_mont */
167 const ECC_NISTP224_Param ECC_NISTP224_b_mont = {.byte = {0xF7, 0xCD, 0x68, 0xE7, 0x10, 0x13, 0xF0, 0xCC, 0xC0, 0x1C,
168                                                          0x3B, 0x74, 0x50, 0x81, 0x52, 0xC8, 0x98, 0xBA, 0xCE, 0x3D,
169                                                          0x93, 0x2F, 0xC0, 0x7F, 0x33, 0xA6, 0x3F, 0x9C}};
170 
171 const ECCParams_CurveParams ECCParams_NISTP224 = {.curveType  = ECCParams_CURVE_TYPE_SHORT_WEIERSTRASS_AN3,
172                                                   .length     = ECCParams_NISTP224_LENGTH,
173                                                   .prime      = ECC_NISTP224_prime.byte,
174                                                   .order      = ECC_NISTP224_order.byte,
175                                                   .a          = ECC_NISTP224_a.byte,
176                                                   .b          = ECC_NISTP224_b.byte,
177                                                   .generatorX = ECC_NISTP224_generatorX.byte,
178                                                   .generatorY = ECC_NISTP224_generatorY.byte,
179                                                   .cofactor   = 1};
180 
181 /*
182  * Curve25519 curve params in little endian format.
183  * byte[0-3] are the param length word as required by the ECC SW library.
184  * byte[4] is the least significant byte of the curve parameter.
185  */
186 const ECC_Curve25519_Param ECC_Curve25519_generatorX = {
187     .byte = {0x08, 0x00, 0x00, 0x00, /* Length word prefix */
188              0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
189              0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}};
190 
191 const ECC_Curve25519_Param ECC_Curve25519_generatorY = {
192     .byte = {0x08, 0x00, 0x00, 0x00, /* Length word prefix */
193              0xd9, 0xd3, 0xce, 0x7e, 0xa2, 0xc5, 0xe9, 0x29, 0xb2, 0x61, 0x7c, 0x6d, 0x7e, 0x4d, 0x3d, 0x92,
194              0x4c, 0xd1, 0x48, 0x77, 0x2c, 0xdd, 0x1e, 0xe0, 0xb4, 0x86, 0xa0, 0xb8, 0xa1, 0x19, 0xae, 0x20}};
195 
196 const ECC_Curve25519_Param ECC_Curve25519_prime = {
197     .byte = {0x08, 0x00, 0x00, 0x00, /* Length word prefix */
198              0xed, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
199              0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f}};
200 
201 const ECC_Curve25519_Param ECC_Curve25519_a = {
202     .byte = {0x08, 0x00, 0x00, 0x00, /* Length word prefix */
203              0x06, 0x6d, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
204              0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}};
205 
206 const ECC_Curve25519_Param ECC_Curve25519_b = {
207     .byte = {0x08, 0x00, 0x00, 0x00, /* Length word prefix */
208              0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
209              0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}};
210 
211 const ECC_Curve25519_Param ECC_Curve25519_order = {
212     .byte = {0x08, 0x00, 0x00, 0x00, /* Length word prefix */
213              0xb9, 0xdc, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, 0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14,
214              0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}};
215 
216 const ECCParams_CurveParams ECCParams_Curve25519 = {.curveType  = ECCParams_CURVE_TYPE_MONTGOMERY,
217                                                     .length     = ECCParams_CURVE25519_LENGTH,
218                                                     .prime      = ECC_Curve25519_prime.byte,
219                                                     .order      = ECC_Curve25519_order.byte,
220                                                     .a          = ECC_Curve25519_a.byte,
221                                                     .b          = ECC_Curve25519_b.byte,
222                                                     .generatorX = ECC_Curve25519_generatorX.byte,
223                                                     .generatorY = ECC_Curve25519_generatorY.byte,
224                                                     .cofactor   = 1};
225 
226 /*
227  *  ======== ECCParams_formatCurve25519PrivateKey ========
228  */
ECCParams_formatCurve25519PrivateKey(CryptoKey * myPrivateKey)229 int_fast16_t ECCParams_formatCurve25519PrivateKey(CryptoKey *myPrivateKey)
230 {
231     myPrivateKey->u.plaintext.keyMaterial[31] &= 0xF8;
232     myPrivateKey->u.plaintext.keyMaterial[0] &= 0x7F;
233     myPrivateKey->u.plaintext.keyMaterial[0] |= 0x40;
234 
235     return ECCParams_STATUS_SUCCESS;
236 }
237 
238 /*
239  *  ======== ECCParams_getUncompressedGeneratorPoint ========
240  */
ECCParams_getUncompressedGeneratorPoint(const ECCParams_CurveParams * curveParams,uint8_t * buffer,size_t length)241 int_fast16_t ECCParams_getUncompressedGeneratorPoint(const ECCParams_CurveParams *curveParams,
242                                                      uint8_t *buffer,
243                                                      size_t length)
244 {
245 
246     size_t paramLength = curveParams->length;
247     size_t pointLength = (paramLength * 2) + 1;
248 
249     if (length < pointLength)
250     {
251         return ECCParams_STATUS_ERROR;
252     }
253 
254     /* Reverse and concatenate x and y */
255     uint32_t i = 0;
256     for (i = 0; i < paramLength; i++)
257     {
258         buffer[i + 1]               = curveParams->generatorX[paramLength + ECC_LENGTH_PREFIX_BYTES - i - 1];
259         buffer[i + 1 + paramLength] = curveParams->generatorY[paramLength + ECC_LENGTH_PREFIX_BYTES - i - 1];
260     }
261 
262     buffer[0] = 0x04;
263     /* Fill the remaining buffer with 0 if needed */
264     memset(buffer + pointLength, 0, length - pointLength);
265 
266     return ECCParams_STATUS_SUCCESS;
267 }
268