1 /*
2 * Copyright (c) 2001-2020, Arm Limited and Contributors. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7 #include <string.h>
8 #include "cc_pal_types.h"
9 #include "cc_pal_mem.h"
10 #include "cc_hash_defs.h"
11 #include "cc_common.h"
12 #include "cc_rnd_error.h"
13 #include "cc_ec_mont_api.h"
14 #include "mbedtls_cc_ec_mont_edw_error.h"
15 #include "ec_mont_local.h"
16 #include "ec_mont.h"
17 #include "cc_general_defs.h"
18 #include "mbedtls/md.h"
19
20 // RL Debug
21 #include "pki_dbg.h"
22
23 /******************************************************************************/
24 /*!
25 The function performs EC Montgomery scalar multiplication:
26 resPoint = scalar * point.<br>
27 <br>
28 Note: all byte arrays have LE order of bytes, i.e. LS byte is on left most place.<br>
29 <br>
30 return CCError_t
31 */
CC_EcMontScalarmult(uint8_t * pResPoint,size_t * pResPointSize,const uint8_t * pScalar,size_t scalarSize,const uint8_t * pInPoint,size_t inPointSize,CCEcMontTempBuff_t * pEcMontTempBuff)32 CEXPORT_C CCError_t CC_EcMontScalarmult(
33 uint8_t *pResPoint, /*!< [out] Pointer to the public (secret) key. */
34 size_t *pResPointSize, /*!< [in/out] Pointer to the size of the public key in bytes.
35 In - the size of the buffer. must be at least EC modulus
36 size (for curve25519 - 32 bytes).
37 Out - the actual size. */
38 const uint8_t *pScalar, /*!< [in] Pointer to the secret (private) key. */
39 size_t scalarSize, /*!< [in] Pointer to the size of the secret key in bytes;
40 must be equal to EC order size (for curve25519 - 32 bytes). */
41 const uint8_t *pInPoint, /*!< [in] Pointer to the input point (compressed). */
42 size_t inPointSize, /*!< [in] Size of the point - must be equal to CC_EC_MONT_MOD_SIZE_IN_BYTES. */
43 CCEcMontTempBuff_t *pEcMontTempBuff) /*!< [in] pointer temp buffer. */
44 {
45 CCError_t err = CC_OK;
46 /* pointers to aligned buffers */
47 uint32_t *pResPoint32, *pScalar32, *pInPoint32;
48 size_t ecOrdSizeBytes, ecModSizeBytes;
49 size_t scalarSizeWords;
50 /* the pointer to EC domain (curve). */
51 const CCEcMontDomain_t *pEcDomain;
52 uint32_t ls, ms;
53
54
55 if (pResPoint == NULL || pResPointSize == NULL ||
56 pScalar == NULL || pInPoint == NULL ||
57 pEcMontTempBuff == NULL) {
58 return CC_EC_MONT_INVALID_INPUT_POINTER_ERROR;
59 }
60
61 /* get domain */
62 pEcDomain = EcMontGetCurve25519Domain();
63
64
65 /* set EC domain parameters sizes */
66 scalarSizeWords = pEcDomain->ecOrdSizeInWords;
67 ecModSizeBytes = pEcDomain->ecModSizeInWords * sizeof(uint32_t);
68 ecOrdSizeBytes = pEcDomain->ecOrdSizeInWords * sizeof(uint32_t);
69
70 /* check sizes */
71 if (*pResPointSize < ecModSizeBytes ||
72 inPointSize != ecModSizeBytes ||
73 scalarSize != ecOrdSizeBytes) {
74 return CC_EC_MONT_INVALID_INPUT_SIZE_ERROR;
75 }
76
77 /* set pointers to temp buffer */
78 pScalar32 = pEcMontTempBuff->ecMontScalar;
79 pResPoint32 = pEcMontTempBuff->ecMontResPoint;
80 pInPoint32 = pEcMontTempBuff->ecMontInPoint;
81
82 /* convert input byte arrays to LE word arrays */
83 CC_CommonConvertLsbMsbBytesToLswMswWords(pScalar32, (uint8_t*)pScalar, scalarSize);
84 CC_CommonConvertLsbMsbBytesToLswMswWords(pInPoint32, (uint8_t*)pInPoint, ecModSizeBytes);
85
86 /* revert changed bytes in the scalar */
87 ls = pScalar32[0]; ms = pScalar32[scalarSizeWords-1];
88
89 /* set scalar bits according to EC Montgomery curve25519 algorithm:
90 byte[31] = (byte[31] & 127) | 64; byte[0] &= 248; */
91 pScalar32[scalarSizeWords-1] = (pScalar32[scalarSizeWords-1] & 0x7FFFFFFF) | 0x40000000;
92 pScalar32[0] &= 0xFFFFFFF8;
93
94 /* call llf pScalar multiplication function */
95 err = EcMontScalarmult(
96 pResPoint32,
97 pScalar32,
98 pInPoint32,
99 pEcDomain);
100 if (err) {
101 err = CC_ECMONT_INTERNAL_ERROR;
102 goto EndWithError;
103 }
104
105 /* revert changed bytes in the scalar */
106 pScalar32[0] = ls; pScalar32[scalarSizeWords-1] = ms;
107
108 /* output pResPoint to LE bytes array */
109 CC_CommonConvertLswMswWordsToLsbMsbBytes(pResPoint, pResPoint32, pEcDomain->ecModSizeInWords);
110 *pResPointSize = ecModSizeBytes;
111
112 EndWithError:
113 /* zeroing temp buffers, they are not used as input/output */
114 if ((uint8_t*)pScalar32 != pScalar) {
115 CC_PalMemSetZero((uint8_t*)pScalar32, ecModSizeBytes);
116 }
117 if ((uint8_t*)pResPoint32 != pResPoint) {
118 CC_PalMemSetZero((uint8_t*)pResPoint32, ecModSizeBytes);
119 }
120 if ((uint8_t*)pInPoint32 != pInPoint) {
121 CC_PalMemSetZero((uint8_t*)pInPoint32, ecModSizeBytes);
122 }
123
124 CC_PalMemSetZero(&pEcMontTempBuff->ecMontScalrMultTempBuff, sizeof(CCEcMontScalrMultTempBuff_t));
125 return err;
126
127 }
128
129 /*********************************************************************/
130 /*!
131 @brief The function performs EC Montgomery (Curve25519) scalar multiplication of base point:
132 res = scalar * base_point.
133
134 Note: all byte arrays have LE order of bytes, i.e. LS byte is on left most place.
135
136
137 @return CC_OK on success,
138 @return A non-zero value on failure as defined mbedtls_cc_ec_mont_edw_error.h.
139 */
140
CC_EcMontScalarmultBase(uint8_t * pResPoint,size_t * pResPointSize,const uint8_t * pScalar,size_t scalarSize,CCEcMontTempBuff_t * pEcMontTempBuff)141 CEXPORT_C CCError_t CC_EcMontScalarmultBase(
142 uint8_t *pResPoint, /*!< [out] Pointer to the public (secret) key. */
143 size_t *pResPointSize, /*!< [in/out] Pointer to the size of the public key in bytes.
144 In - the size of buffer must be at least EC modulus size
145 (for curve25519 - 32 bytes);
146 Out - the actual size. */
147 const uint8_t *pScalar, /*!< [in] Pointer to the secret (private) key. */
148 size_t scalarSize, /*!< [in] Pointer to the size of the scalar in bytes -
149 must be equal to EC order size (for curve25519 - 32 bytes). */
150 CCEcMontTempBuff_t *pEcMontTempBuff) /*!< [in] pointer to the temp buffer. */
151 {
152 CCError_t err = CC_OK;
153 /* pointers to aligned buffers */
154 uint32_t *pResPoint32, *pScalar32;
155 size_t ecOrdSizeBytes, ecModSizeBytes;
156 size_t scalarSizeWords;
157 const CCEcMontDomain_t *pEcDomain;
158 uint32_t ls, ms;
159
160 /* check parameters */
161 if (pResPoint == NULL || pResPointSize == NULL ||
162 pScalar == NULL || pEcMontTempBuff == NULL) {
163 return CC_EC_MONT_INVALID_INPUT_POINTER_ERROR;
164 }
165
166 /* get domain */
167 pEcDomain = EcMontGetCurve25519Domain();
168
169 /* set EC domain parameters sizes */
170 scalarSizeWords = pEcDomain->ecOrdSizeInWords;
171 ecModSizeBytes = pEcDomain->ecModSizeInWords * sizeof(uint32_t);
172 ecOrdSizeBytes = scalarSizeWords * sizeof(uint32_t);
173
174 /* check sizes */
175 if (*pResPointSize < ecModSizeBytes ||
176 scalarSize != ecOrdSizeBytes) {
177 return CC_EC_MONT_INVALID_INPUT_SIZE_ERROR;
178 }
179
180 /* set pointers to temp buffer */
181 pScalar32 = pEcMontTempBuff->ecMontScalar;
182 pResPoint32 = pEcMontTempBuff->ecMontResPoint;
183
184 /* convert input byte arrays to LE word arrays */
185 CC_CommonConvertLsbMsbBytesToLswMswWords(pScalar32, (uint8_t*)pScalar, scalarSize);
186
187 /* revert changed bytes in the scalar */
188 ls = pScalar32[0]; ms = pScalar32[scalarSizeWords-1];
189
190 /* set scalar bits according to EC Montgomery curve25519 algorithm:
191 byte[31] = (byte[31] & 127) | 64; byte[0] &= 248; */
192 pScalar32[scalarSizeWords-1] = (pScalar32[scalarSizeWords-1] & 0x7FFFFFFF) | 0x40000000;
193 pScalar32[0] &= 0xFFFFFFF8;
194
195 /* call llf pScalar multiplication function */
196 err = EcMontScalarmult(
197 pResPoint32,
198 pScalar32,
199 (uint32_t*)pEcDomain->ecGenX,
200 pEcDomain);
201 if (err) {
202 err = CC_ECMONT_INTERNAL_ERROR;
203 goto EndWithError;
204 }
205
206 /* revert changed bytes in the scalar */
207 pScalar32[0] = ls; pScalar32[scalarSizeWords-1] = ms;
208
209 /* output pResPoint to LE bytes array */
210 CC_CommonConvertLswMswWordsToLsbMsbBytes(pResPoint, pResPoint32,
211 pEcDomain->ecModSizeInWords);
212 *pResPointSize = ecModSizeBytes;
213
214
215 EndWithError:
216 /* zeroing temp buffers if they are not used as input/output */
217 if ((uint8_t*)pScalar32 != pScalar) {
218 CC_PalMemSetZero((uint8_t*)pScalar32, ecModSizeBytes);
219 }
220 if ((uint8_t*)pResPoint32 != pResPoint) {
221 CC_PalMemSetZero((uint8_t*)pResPoint32, ecModSizeBytes);
222 }
223
224 return err;
225
226 }
227 /********************************************************************/
228
ecMontKeyPairBase(uint8_t * pPublKey,size_t * pPublKeySize,uint8_t * pSecrKey,size_t * pSecrKeySize,const uint8_t * pInPoint,CCRndContext_t * pRndContext,CCEcMontTempBuff_t * pEcMontTempBuff)229 static CCError_t ecMontKeyPairBase (
230 uint8_t *pPublKey, /*!< [out] Pointer to the public key. */
231 size_t *pPublKeySize, /*!< [in/out] Pointer to the size of the public key in bytes
232 In - the size of the buffer must be at least EC order size
233 (for curve25519 - 32 bytes);
234 Out - the actual size. */
235 uint8_t *pSecrKey, /*!< [out] Pointer to the secret key, including. */
236 size_t *pSecrKeySize, /*!< [in/out] Pointer to the size of buffer for the secret key in bytes -
237 must be at least EC order size (for curve25519 - 32 bytes). */
238 const uint8_t *pInPoint, /*!< [in] Pointer to the input point (compressed). must be of size CC_EC_MONT_MOD_SIZE_IN_BYTES */
239 CCRndContext_t *pRndContext, /*!< [in/out] Pointer to the RND context buffer. */
240 CCEcMontTempBuff_t *pEcMontTempBuff) /*!< [in] pointer to EC domain (curve). */
241 {
242 /* DEFINITIONS */
243
244 CCError_t err = CC_OK;
245 uint32_t ecScalarSizeBytes, ecModSizeBytes;
246 CCRndGenerateVectWorkFunc_t RndGenerateVectFunc;
247 /* the pointer to EC domain (curve). */
248 const CCEcMontDomain_t *pEcDomain;
249
250
251 /* FUNCTION LOGIC */
252
253 /* check input parameters */
254 if (pSecrKey == NULL || pSecrKeySize == NULL ||
255 pPublKey == NULL || pPublKeySize == NULL ||
256 pRndContext == NULL || pEcMontTempBuff == NULL) {
257 return CC_EC_MONT_INVALID_INPUT_POINTER_ERROR;
258 }
259
260 /* get domain */
261 pEcDomain = EcMontGetCurve25519Domain();
262
263 /* EC pScalar size in bytes */
264 ecScalarSizeBytes = pEcDomain->ecOrdSizeInWords * sizeof(uint32_t);
265 ecModSizeBytes = pEcDomain->ecModSizeInWords * sizeof(uint32_t);
266
267 if (*pSecrKeySize < ecScalarSizeBytes ||
268 *pPublKeySize < ecScalarSizeBytes) {
269 return CC_EC_MONT_INVALID_INPUT_SIZE_ERROR;
270 }
271
272 /* generaate secret key (seed) */
273 RndGenerateVectFunc = pRndContext->rndGenerateVectFunc;
274 if(RndGenerateVectFunc == NULL)
275 return CC_RND_GEN_VECTOR_FUNC_ERROR;
276
277 err = RndGenerateVectFunc(
278 (void *)pRndContext->rndState,
279 (unsigned char *)pSecrKey,
280 (size_t)ecScalarSizeBytes);
281 if (err) {
282 goto End;
283 }
284
285 *pPublKeySize = ecModSizeBytes;
286
287 /* calculate public key by pScalar mult. */
288 if (pInPoint != NULL)
289 {
290 err = CC_EcMontScalarmult(
291 pPublKey,
292 pPublKeySize,
293 pSecrKey,
294 ecScalarSizeBytes,
295 pInPoint,
296 CC_EC_MONT_MOD_SIZE_IN_BYTES,
297 pEcMontTempBuff);
298 }
299 else /* use the curve base point*/
300 {
301 err = CC_EcMontScalarmultBase(
302 pPublKey,
303 pPublKeySize,
304 pSecrKey,
305 ecScalarSizeBytes,
306 pEcMontTempBuff);
307 }
308 if (err) {
309 goto End;
310 }
311
312 /* output results */
313 *pSecrKeySize = ecScalarSizeBytes;
314
315 End:
316
317 CC_PalMemSetZero(pEcMontTempBuff, sizeof(CCEcMontTempBuff_t));
318
319 if (err) {
320 CC_PalMemSetZero(pPublKey, ecModSizeBytes);
321 CC_PalMemSetZero(pSecrKey, ecScalarSizeBytes);
322 }
323 return err;
324
325 }
326
327
328 /*******************************************************************/
329 /*!
330 @brief The function randomly generates private and public keys for Montgomery
331 Curve25519, with a configurable base point.
332
333
334 \note All byte arrays are in LE order of bytes, i.e. LS byte is on the left most place. \par
335 \note LS and MS bits of the Secret key are set according to EC Montgomery scalar mult. algorithm:
336 secrKey[0] &= 248; secrKey[31] &= 127; secrKey[31] |= 64;
337
338 @return CC_OK on success,
339 @return A non-zero value on failure as defined mbedtls_cc_ec_mont_edw_error.h.
340
341 */
CC_EcMontKeyPairBase(uint8_t * pPublKey,size_t * pPublKeySize,uint8_t * pSecrKey,size_t * pSecrKeySize,const uint8_t * pInPoint,size_t inPointSize,CCRndContext_t * pRndContext,CCEcMontTempBuff_t * pEcMontTempBuff)342 CEXPORT_C CCError_t CC_EcMontKeyPairBase(
343 uint8_t *pPublKey, /*!< [out] Pointer to the public key. */
344 size_t *pPublKeySize, /*!< [in/out] Pointer to the size of the public key in bytes.
345 In - the size of the buffer must be at least EC order size
346 (for curve25519 - 32 bytes);
347 Out - the actual size. */
348 uint8_t *pSecrKey, /*!< [out] Pointer to the secret key, including. */
349 size_t *pSecrKeySize, /*!< [in/out] Pointer to the size of buffer for the secret key in bytes -
350 must be at least EC order size (for curve25519 - 32 bytes). */
351 const uint8_t *pInPoint, /*!< [in] Pointer to the input point (compressed). */
352 size_t inPointSize, /*!< [in] Size of the point - must be equal to CC_EC_MONT_MOD_SIZE_IN_BYTES. */
353 CCRndContext_t *pRndContext, /*!< [in/out] Pointer to the RND context buffer. */
354 CCEcMontTempBuff_t *pEcMontTempBuff) /*!< [in] pointer to EC domain (curve). */
355 {
356 if (inPointSize != CC_EC_MONT_MOD_SIZE_IN_BYTES)
357 {
358 return CC_EC_MONT_INVALID_INPUT_SIZE_ERROR;
359 }
360
361 return ecMontKeyPairBase(pPublKey, pPublKeySize, pSecrKey, pSecrKeySize, pInPoint, pRndContext, pEcMontTempBuff);
362 }
363
364 /*******************************************************************/
365 /*!
366 @brief The function randomly generates private and public keys for Montgomery
367 Curve25519. it uses CC_EcMontKeyPair with the Generator point of the Curve
368
369
370 \note All byte arrays are in LE order of bytes, i.e. LS byte is on the left most place. \par
371 \note LS and MS bits of the Secret key are set according to EC Montgomery scalar mult. algorithm:
372 secrKey[0] &= 248; secrKey[31] &= 127; secrKey[31] |= 64;
373
374 @return CC_OK on success,
375 @return A non-zero value on failure as defined mbedtls_cc_ec_mont_edw_error.h.
376
377 */
CC_EcMontKeyPair(uint8_t * pPublKey,size_t * pPublKeySize,uint8_t * pSecrKey,size_t * pSecrKeySize,CCRndContext_t * pRndContext,CCEcMontTempBuff_t * pEcMontTempBuff)378 CEXPORT_C CCError_t CC_EcMontKeyPair(
379 uint8_t *pPublKey, /*!< [out] Pointer to the public key. */
380 size_t *pPublKeySize, /*!< [in/out] Pointer to the size of the public key in bytes.
381 In - the size of the buffer must be at least EC order size
382 (for curve25519 - 32 bytes);
383 Out - the actual size. */
384 uint8_t *pSecrKey, /*!< [out] Pointer to the secret key, including. */
385 size_t *pSecrKeySize, /*!< [in/out] Pointer to the size of buffer for the secret key in bytes -
386 must be at least EC order size (for curve25519 - 32 bytes). */
387 CCRndContext_t *pRndContext, /*!< [in/out] Pointer to the RND context buffer. */
388 CCEcMontTempBuff_t *pEcMontTempBuff) /*!< [in] pointer to EC domain (curve). */
389 {
390
391 return ecMontKeyPairBase(pPublKey, pPublKeySize, pSecrKey, pSecrKeySize, NULL, pRndContext, pEcMontTempBuff);
392 }
393
394 /*******************************************************************/
395 /**
396 @brief The function generates private and public keys for Montgomery Curve25519
397 using given seed.
398
399 Note: all byte arrays have LE order of bytes, i.e. LS byte is on left most place.
400
401 @return CC_OK on success,
402 @return a non-zero value on failure as defined mbedtls_cc_ec_mont_edw_error.h.
403 */
CC_EcMontSeedKeyPair(uint8_t * pPublKey,size_t * pPublKeySize,uint8_t * pSecrKey,size_t * pSecrKeySize,const uint8_t * pSeed,size_t seedSize,CCEcMontTempBuff_t * pEcMontTempBuff)404 CEXPORT_C CCError_t CC_EcMontSeedKeyPair (
405 uint8_t *pPublKey, /*!< [out] Pointer to the public (secret) key. */
406 size_t *pPublKeySize, /*!< [in/out] Pointer to the size of the public key in bytes.
407 In - the size of buffer must be at least EC order size
408 (for curve25519 - 32 bytes);
409 Out - the actual size. */
410 uint8_t *pSecrKey, /*!< [out] Pointer to the secret (private) key. */
411 size_t *pSecrKeySize, /*!< [in/out] Pointer to the size of the secret key in bytes
412 In - the size of buffer must be at least EC order size
413 (for curve25519 - 32 bytes);
414 Out - the actual size. */
415 const uint8_t *pSeed, /*!< [in] Pointer to the given seed - 32 bytes. */
416 size_t seedSize, /*!< [in/] Size of the seed in bytes (must be equal to CC_EC_MONT_SEEDBYTES). */
417 CCEcMontTempBuff_t *pEcMontTempBuff) /*!< [in] pointer temp buffer. */
418 {
419 /* DEFINITIONS */
420
421 CCError_t err = CC_OK;
422 uint8_t *pScalar, *pRes;
423 CCHashResultBuf_t *pHashResult; /*takes 64 bytes in pEcMontTempBuff*/
424 uint32_t ecOrdSizeBytes, ecMontSizeBytes;
425 /* the pointer to EC domain (curve). */
426 const CCEcMontDomain_t *pEcDomain;
427 const mbedtls_md_info_t *md_info=NULL;
428
429 /* FUNCTION LOGIC */
430
431
432 /* check input parameters */
433 if (pSecrKey == NULL || pSecrKeySize == NULL ||
434 pPublKey == NULL || pPublKeySize == NULL ||
435 pSeed == NULL || pEcMontTempBuff == NULL) {
436 return CC_EC_MONT_INVALID_INPUT_POINTER_ERROR;
437 }
438
439 /* get domain */
440 pEcDomain = EcMontGetCurve25519Domain();
441
442 ecOrdSizeBytes = pEcDomain->ecOrdSizeInWords*sizeof(uint32_t);
443 ecMontSizeBytes = pEcDomain->ecModSizeInWords*sizeof(uint32_t);
444
445 if (*pSecrKeySize < ecOrdSizeBytes ||
446 seedSize != ecOrdSizeBytes) {
447 return CC_EC_MONT_INVALID_INPUT_SIZE_ERROR;
448 }
449
450 pHashResult = (CCHashResultBuf_t*)pEcMontTempBuff;
451 pScalar = (uint8_t*)&pEcMontTempBuff->ecMontScalar;
452 pRes = (uint8_t*)&pEcMontTempBuff->ecMontResPoint;
453
454 /* copy seed into buffer with phys. memory (HW HASH requirement) */
455 CC_PalMemCopy(pScalar, pSeed, seedSize);
456
457 /* calculate secret key; note pScalar points *
458 * to the same mem. as pHashResult */
459 md_info = mbedtls_md_info_from_string( HashAlgMode2mbedtlsString[CC_HASH_SHA512_mode] );
460 if (NULL == md_info) {
461 err = CC_EC_MONT_INVALID_INPUT_SIZE_ERROR;
462 goto End;
463
464 }
465 err = mbedtls_md(md_info,
466 pScalar,
467 seedSize,
468 (unsigned char *)(*pHashResult));
469 if (err) {
470 goto End;
471 }
472
473 /* calculate the public key */
474 err = CC_EcMontScalarmultBase(
475 (uint8_t*)&pEcMontTempBuff->ecMontResPoint[0],
476 pPublKeySize,
477 pScalar, // check endianness !
478 ecOrdSizeBytes,
479 pEcMontTempBuff);
480
481 if (err) {
482 goto End;
483 }
484
485 /* set actual sizes of Secr. and publ. keys */
486 *pSecrKeySize = ecOrdSizeBytes;
487 *pPublKeySize = ecMontSizeBytes;
488
489 /* output secret and publ. keys */
490 CC_PalMemCopy(pSecrKey, (uint8_t*)pScalar, *pSecrKeySize);
491 CC_PalMemCopy(pPublKey, pRes, *pPublKeySize);
492
493 End:
494 /* clean the temp buffers */
495 CC_PalMemSetZero((uint8_t*)pEcMontTempBuff, sizeof(CCEcMontTempBuff_t));
496 if (err) {
497 CC_PalMemSetZero(pSecrKey, ecOrdSizeBytes);
498 CC_PalMemSetZero(pPublKey, ecMontSizeBytes);
499 }
500
501 return err;
502 }
503
504