1 /* ksdk_port.c
2 *
3 * Copyright (C) 2006-2021 wolfSSL Inc.
4 *
5 * This file is part of wolfSSL.
6 *
7 * wolfSSL is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * wolfSSL is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
20 */
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include <wolfssl/wolfcrypt/settings.h>
27 #ifdef NO_INLINE
28 #include <wolfssl/wolfcrypt/misc.h>
29 #else
30 #define WOLFSSL_MISC_INCLUDED
31 #include <wolfcrypt/src/misc.c>
32 #endif
33
34 /* If FREESCALE_LTC_TFM or FREESCALE_LTC_ECC */
35 #if defined(FREESCALE_LTC_TFM) || defined(FREESCALE_LTC_ECC)
36
37 #include <wolfssl/wolfcrypt/port/nxp/ksdk_port.h>
38 #include <wolfssl/wolfcrypt/random.h>
39 #include <wolfssl/wolfcrypt/error-crypt.h>
40 #include <wolfssl/wolfcrypt/logging.h>
41 #include <stdint.h>
42
43 #define ERROR_OUT(res) { ret = (res); goto done; }
44
45 /* For debugging only - Enable this to do software tests of each operation */
46 /* #define ENABLE_NXPLTC_TESTS */
47 #ifdef ENABLE_NXPLTC_TESTS
48 static int doLtcTest = 0;
49 #endif
50
ksdk_port_init(void)51 int ksdk_port_init(void)
52 {
53 #if defined(FREESCALE_LTC_TFM)
54 LTC_Init(LTC0);
55 #endif
56
57 return 0;
58 }
59
60 /* Reverse array in memory (in place) */
ltc_reverse_array(uint8_t * src,size_t src_len)61 static void ltc_reverse_array(uint8_t *src, size_t src_len)
62 {
63 unsigned int i;
64
65 for (i = 0; i < src_len / 2; i++) {
66 uint8_t tmp;
67
68 tmp = src[i];
69 src[i] = src[src_len - 1 - i];
70 src[src_len - 1 - i] = tmp;
71 }
72 }
73
74
75 #ifndef WOLFSSL_SP_MATH
76 /* same as mp_to_unsigned_bin() with mp_reverse() skipped */
mp_to_unsigned_lsb_bin(mp_int * a,unsigned char * b)77 static int mp_to_unsigned_lsb_bin(mp_int *a, unsigned char *b)
78 {
79 int res;
80 mp_int t;
81
82 res = mp_init_copy(&t, a);
83 if (res == MP_OKAY) {
84 res = mp_to_unsigned_bin_at_pos(0, &t, b);
85 if (res >= 0)
86 res = 0;
87 #ifndef USE_FAST_MATH
88 mp_clear(&t);
89 #endif
90 }
91
92 return res;
93 }
94 #endif
95
ltc_get_lsb_bin_from_mp_int(uint8_t * dst,mp_int * A,uint16_t * psz)96 static int ltc_get_lsb_bin_from_mp_int(uint8_t *dst, mp_int *A, uint16_t *psz)
97 {
98 int res;
99 uint16_t sz;
100
101 sz = mp_unsigned_bin_size(A);
102 #ifndef WOLFSSL_SP_MATH
103 /* result is lsbyte at lowest addr as required by LTC */
104 res = mp_to_unsigned_lsb_bin(A, dst);
105 #else
106 res = mp_to_unsigned_bin(A, dst);
107 if (res == MP_OKAY) {
108 ltc_reverse_array(dst, sz);
109 }
110 #endif
111 *psz = sz;
112 return res;
113 }
114
115 /* LTC TFM */
116 #if defined(FREESCALE_LTC_TFM)
117
118 /* these function are used by wolfSSL upper layers (like RSA) */
119
120 /* c = a * b */
mp_mul(mp_int * A,mp_int * B,mp_int * C)121 int mp_mul(mp_int *A, mp_int *B, mp_int *C)
122 {
123 int res = MP_OKAY;
124 status_t status;
125 int szA, szB;
126
127 #ifdef ENABLE_NXPLTC_TESTS
128 mp_int t;
129 mp_init(&t);
130 if (doLtcTest)
131 wolfcrypt_mp_mul(A, B, &t);
132 #endif
133
134 szA = mp_unsigned_bin_size(A);
135 szB = mp_unsigned_bin_size(B);
136
137 /* if unsigned mul can fit into LTC PKHA let's use it, otherwise call
138 * software mul */
139 if ((szA <= LTC_MAX_INT_BYTES / 2) && (szB <= LTC_MAX_INT_BYTES / 2)) {
140 uint8_t *ptrA = (uint8_t*)XMALLOC(LTC_MAX_INT_BYTES, NULL,
141 DYNAMIC_TYPE_BIGINT);
142 uint8_t *ptrB = (uint8_t*)XMALLOC(LTC_MAX_INT_BYTES, NULL,
143 DYNAMIC_TYPE_BIGINT);
144 uint8_t *ptrN = (uint8_t*)XMALLOC(LTC_MAX_INT_BYTES, NULL,
145 DYNAMIC_TYPE_BIGINT);
146 uint8_t *ptrC = (uint8_t*)XMALLOC(LTC_MAX_INT_BYTES, NULL,
147 DYNAMIC_TYPE_BIGINT);
148
149 /* unsigned multiply */
150 #if (!defined(WOLFSSL_SP_MATH) && !defined(WOLFSSL_SP_MATH_ALL)) || \
151 defined(WOLFSSL_SP_INT_NEGATIVE)
152 int neg = (A->sign == B->sign) ? MP_ZPOS : MP_NEG;
153 #endif
154
155 if (ptrA && ptrB && ptrN && ptrC) {
156 uint16_t sizeA, sizeB, sizeN, sizeC = 0;
157
158 res = ltc_get_lsb_bin_from_mp_int(ptrA, A, &sizeA);
159 if (res == MP_OKAY)
160 res = ltc_get_lsb_bin_from_mp_int(ptrB, B, &sizeB);
161 if (res == MP_OKAY) {
162 sizeN = sizeA + sizeB;
163 XMEMSET(ptrN, 0xFF, sizeN);
164 XMEMSET(ptrC, 0, LTC_MAX_INT_BYTES);
165
166 status = LTC_PKHA_ModMul(LTC_BASE,
167 ptrA, sizeA, /* first integer */
168 ptrB, sizeB, /* second integer */
169 ptrN, sizeN, /* modulus */
170 ptrC, &sizeC, /* out */
171 kLTC_PKHA_IntegerArith, kLTC_PKHA_NormalValue,
172 kLTC_PKHA_NormalValue, kLTC_PKHA_TimingEqualized);
173 if (status == kStatus_Success) {
174 ltc_reverse_array(ptrC, sizeC);
175 res = mp_read_unsigned_bin(C, ptrC, sizeC);
176
177 #if (!defined(WOLFSSL_SP_MATH) && !defined(WOLFSSL_SP_MATH_ALL)) || \
178 defined(WOLFSSL_SP_INT_NEGATIVE)
179 /* fix sign */
180 C->sign = neg;
181 #endif
182 }
183 else {
184 res = MP_VAL;
185 }
186 }
187 }
188
189 if (ptrA) {
190 XFREE(ptrA, NULL, DYNAMIC_TYPE_BIGINT);
191 }
192 if (ptrB) {
193 XFREE(ptrB, NULL, DYNAMIC_TYPE_BIGINT);
194 }
195 if (ptrN) {
196 XFREE(ptrN, NULL, DYNAMIC_TYPE_BIGINT);
197 }
198 if (ptrC) {
199 XFREE(ptrC, NULL, DYNAMIC_TYPE_BIGINT);
200 }
201 }
202 else {
203 #ifdef WOLFSSL_SP_MATH
204 res = sp_mul(A, B, C);
205 #else
206 res = wolfcrypt_mp_mul(A, B, C);
207 #endif
208 }
209
210 #ifdef ENABLE_NXPLTC_TESTS
211 /* compare hardware vs software */
212 if (doLtcTest && mp_cmp(&t, C) != MP_EQ) {
213 printf("mp_mul test fail!\n");
214
215 mp_dump("C", C, 0);
216 mp_dump("C soft", &t, 0);
217 }
218 mp_clear(&t);
219 #endif
220
221 return res;
222 }
223
224 /* c = a mod b, 0 <= c < b */
mp_mod(mp_int * a,mp_int * b,mp_int * c)225 int mp_mod(mp_int *a, mp_int *b, mp_int *c)
226 {
227 int res = MP_OKAY;
228 int szA, szB;
229
230 #ifdef ENABLE_NXPLTC_TESTS
231 mp_int t;
232 mp_init(&t);
233 if (doLtcTest)
234 wolfcrypt_mp_mod(a, b, &t);
235 #endif
236
237 szA = mp_unsigned_bin_size(a);
238 szB = mp_unsigned_bin_size(b);
239 if ((szA <= LTC_MAX_INT_BYTES) && (szB <= LTC_MAX_INT_BYTES)) {
240 uint8_t *ptrA = (uint8_t*)XMALLOC(LTC_MAX_INT_BYTES, NULL,
241 DYNAMIC_TYPE_BIGINT);
242 uint8_t *ptrB = (uint8_t*)XMALLOC(LTC_MAX_INT_BYTES, NULL,
243 DYNAMIC_TYPE_BIGINT);
244 uint8_t *ptrC = (uint8_t*)XMALLOC(LTC_MAX_INT_BYTES, NULL,
245 DYNAMIC_TYPE_BIGINT);
246
247 #if (!defined(WOLFSSL_SP_MATH) && !defined(WOLFSSL_SP_MATH_ALL)) || \
248 defined(WOLFSSL_SP_INT_NEGATIVE)
249 /* get sign for the result */
250 int neg = (a->sign == b->sign) ? MP_ZPOS : MP_NEG;
251 #endif
252
253 /* get remainder of unsigned a divided by unsigned b */
254 if (ptrA && ptrB && ptrC) {
255 uint16_t sizeA, sizeB, sizeC;
256
257 res = ltc_get_lsb_bin_from_mp_int(ptrA, a, &sizeA);
258 if (res == MP_OKAY)
259 res = ltc_get_lsb_bin_from_mp_int(ptrB, b, &sizeB);
260 if (res == MP_OKAY) {
261 if (kStatus_Success ==
262 LTC_PKHA_ModRed(LTC_BASE, ptrA, sizeA, ptrB, sizeB, ptrC,
263 &sizeC, kLTC_PKHA_IntegerArith))
264 {
265 ltc_reverse_array(ptrC, sizeC);
266 res = mp_read_unsigned_bin(c, ptrC, sizeC);
267
268 #if (!defined(WOLFSSL_SP_MATH) && !defined(WOLFSSL_SP_MATH_ALL)) || \
269 defined(WOLFSSL_SP_INT_NEGATIVE)
270 /* fix sign */
271 c->sign = neg;
272 #endif
273 }
274 else {
275 res = MP_VAL;
276 }
277 }
278 }
279 else {
280 res = MP_MEM;
281 }
282
283 if (ptrA) {
284 XFREE(ptrA, NULL, DYNAMIC_TYPE_BIGINT);
285 }
286 if (ptrB) {
287 XFREE(ptrB, NULL, DYNAMIC_TYPE_BIGINT);
288 }
289 if (ptrC) {
290 XFREE(ptrC, NULL, DYNAMIC_TYPE_BIGINT);
291 }
292 }
293 else {
294 #if defined(FREESCALE_LTC_TFM_RSA_4096_ENABLE)
295 res = wolfcrypt_mp_mod(a, b, c);
296 #else
297 res = NOT_COMPILED_IN;
298 #endif
299 }
300
301 #ifdef ENABLE_NXPLTC_TESTS
302 /* compare hardware vs software */
303 if (doLtcTest && mp_cmp(&t, c) != MP_EQ) {
304 printf("mp_mod test fail!\n");
305
306 mp_dump("C", c, 0);
307 mp_dump("C soft", &t, 0);
308 }
309 mp_clear(&t);
310 #endif
311
312 return res;
313 }
314
315 /* c = 1/a (mod b) for odd b only */
mp_invmod(mp_int * a,mp_int * b,mp_int * c)316 int mp_invmod(mp_int *a, mp_int *b, mp_int *c)
317 {
318 int res = MP_OKAY;
319 int szA, szB;
320
321 #ifdef ENABLE_NXPLTC_TESTS
322 mp_int t;
323 mp_init(&t);
324 if (doLtcTest)
325 wolfcrypt_mp_invmod(a, b, &t);
326 #endif
327
328 szA = mp_unsigned_bin_size(a);
329 szB = mp_unsigned_bin_size(b);
330 if ((szA <= LTC_MAX_INT_BYTES) && (szB <= LTC_MAX_INT_BYTES)) {
331 uint8_t *ptrA = (uint8_t*)XMALLOC(LTC_MAX_INT_BYTES, NULL,
332 DYNAMIC_TYPE_BIGINT);
333 uint8_t *ptrB = (uint8_t*)XMALLOC(LTC_MAX_INT_BYTES, NULL,
334 DYNAMIC_TYPE_BIGINT);
335 uint8_t *ptrC = (uint8_t*)XMALLOC(LTC_MAX_INT_BYTES, NULL,
336 DYNAMIC_TYPE_BIGINT);
337
338 if (ptrA && ptrB && ptrC) {
339 uint16_t sizeA, sizeB, sizeC;
340
341 res = ltc_get_lsb_bin_from_mp_int(ptrA, a, &sizeA);
342 if (res == MP_OKAY)
343 res = ltc_get_lsb_bin_from_mp_int(ptrB, b, &sizeB);
344
345 /* if a >= b then reduce */
346 /* TODO: Perhaps always do mod reduce depending on hardware performance */
347 if (res == MP_OKAY &&
348 LTC_PKHA_CompareBigNum(ptrA, sizeA, ptrB, sizeB) >= 0) {
349 if (LTC_PKHA_ModRed(LTC_BASE, ptrA, sizeA, ptrB, sizeB,
350 ptrA, &sizeA, kLTC_PKHA_IntegerArith) != kStatus_Success) {
351 res = MP_VAL;
352 }
353 }
354 if (res == MP_OKAY) {
355 if (LTC_PKHA_ModInv(LTC_BASE, ptrA, sizeA, ptrB, sizeB, ptrC,
356 &sizeC, kLTC_PKHA_IntegerArith) == kStatus_Success) {
357 ltc_reverse_array(ptrC, sizeC);
358 res = mp_read_unsigned_bin(c, ptrC, sizeC);
359
360
361 #if (!defined(WOLFSSL_SP_MATH) && !defined(WOLFSSL_SP_MATH_ALL)) || \
362 defined(WOLFSSL_SP_INT_NEGATIVE)
363 c->sign = a->sign;
364 #endif
365 }
366 else {
367 res = MP_VAL;
368 }
369 }
370 }
371 else {
372 res = MP_MEM;
373 }
374
375 if (ptrA) {
376 XFREE(ptrA, NULL, DYNAMIC_TYPE_BIGINT);
377 }
378 if (ptrB) {
379 XFREE(ptrB, NULL, DYNAMIC_TYPE_BIGINT);
380 }
381 if (ptrC) {
382 XFREE(ptrC, NULL, DYNAMIC_TYPE_BIGINT);
383 }
384 }
385 else {
386 #if defined(FREESCALE_LTC_TFM_RSA_4096_ENABLE)
387 res = wolfcrypt_mp_invmod(a, b, c);
388 #else
389 res = NOT_COMPILED_IN;
390 #endif
391 }
392
393 #ifdef ENABLE_NXPLTC_TESTS
394 /* compare hardware vs software */
395 if (doLtcTest && mp_cmp(&t, c) != MP_EQ) {
396 printf("mp_invmod test fail!\n");
397
398 mp_dump("C", c, 0);
399 mp_dump("C soft", &t, 0);
400 }
401 mp_clear(&t);
402 #endif
403
404 return res;
405 }
406
407 /* d = a * b (mod c) */
408 /* with blinding enabled ptr a can equal ptr d */
mp_mulmod(mp_int * a,mp_int * b,mp_int * c,mp_int * d)409 int mp_mulmod(mp_int *a, mp_int *b, mp_int *c, mp_int *d)
410 {
411 int res = MP_OKAY;
412 status_t status;
413 int szA, szB, szC;
414
415 #ifdef ENABLE_NXPLTC_TESTS
416 mp_int t;
417 mp_init(&t);
418 if (doLtcTest)
419 wolfcrypt_mp_mulmod(a, b, c, &t);
420 #endif
421
422 szA = mp_unsigned_bin_size(a);
423 szB = mp_unsigned_bin_size(b);
424 szC = mp_unsigned_bin_size(c);
425
426 /* LTC hardware seems to have issue with ModMul with 511 bytes or more,
427 so use software math */
428 if ((szA + szB < LTC_MAX_INT_BYTES-1) && (szC <= LTC_MAX_INT_BYTES))
429 {
430 uint8_t *ptrA, *ptrB, *ptrC, *ptrD;
431
432 ptrA = (uint8_t*)XMALLOC(LTC_MAX_INT_BYTES, NULL, DYNAMIC_TYPE_BIGINT);
433 ptrB = (uint8_t*)XMALLOC(LTC_MAX_INT_BYTES, NULL, DYNAMIC_TYPE_BIGINT);
434 ptrC = (uint8_t*)XMALLOC(LTC_MAX_INT_BYTES, NULL, DYNAMIC_TYPE_BIGINT);
435 ptrD = (uint8_t*)XMALLOC(LTC_MAX_INT_BYTES, NULL, DYNAMIC_TYPE_BIGINT);
436
437 if (ptrA && ptrB && ptrC && ptrD) {
438 uint16_t sizeA, sizeB, sizeC, sizeD = 0;
439
440 /* unsigned multiply */
441 #if (!defined(WOLFSSL_SP_MATH) && !defined(WOLFSSL_SP_MATH_ALL)) || \
442 defined(WOLFSSL_SP_INT_NEGATIVE)
443 int neg = (a->sign == b->sign) ? MP_ZPOS : MP_NEG;
444 #endif
445
446 /* Multiply A * B = D */
447 res = ltc_get_lsb_bin_from_mp_int(ptrA, a, &sizeA);
448 if (res == MP_OKAY)
449 res = ltc_get_lsb_bin_from_mp_int(ptrB, b, &sizeB);
450 if (res == MP_OKAY) {
451 /* modulus C is all F's for integer multiply */
452 sizeC = sizeA + sizeB;
453 XMEMSET(ptrC, 0xFF, sizeC);
454 XMEMSET(ptrD, 0, LTC_MAX_INT_BYTES);
455
456 status = LTC_PKHA_ModMul(LTC_BASE,
457 ptrA, sizeA, /* first integer */
458 ptrB, sizeB, /* second integer */
459 ptrC, sizeC, /* modulus */
460 ptrD, &sizeD, /* out */
461 kLTC_PKHA_IntegerArith, kLTC_PKHA_NormalValue,
462 kLTC_PKHA_NormalValue, kLTC_PKHA_TimingEqualized);
463 if (status != kStatus_Success)
464 res = MP_VAL;
465 }
466 /* load modulus */
467 if (res == MP_OKAY)
468 res = ltc_get_lsb_bin_from_mp_int(ptrC, c, &sizeC);
469 /* perform D mod C = D */
470 if (res == MP_OKAY) {
471 status = LTC_PKHA_ModRed(LTC_BASE,
472 ptrD, sizeD,
473 ptrC, sizeC,
474 ptrD, &sizeD,
475 kLTC_PKHA_IntegerArith);
476 if (status != kStatus_Success)
477 res = MP_VAL;
478 }
479 if (res == MP_OKAY) {
480 ltc_reverse_array(ptrD, sizeD);
481 res = mp_read_unsigned_bin(d, ptrD, sizeD);
482
483 #if (!defined(WOLFSSL_SP_MATH) && !defined(WOLFSSL_SP_MATH_ALL)) || \
484 defined(WOLFSSL_SP_INT_NEGATIVE)
485 /* fix sign */
486 d->sign = neg;
487 #endif
488 }
489 }
490 else {
491 res = MP_MEM;
492 }
493
494 if (ptrA) {
495 XFREE(ptrA, NULL, DYNAMIC_TYPE_BIGINT);
496 }
497 if (ptrB) {
498 XFREE(ptrB, NULL, DYNAMIC_TYPE_BIGINT);
499 }
500 if (ptrC) {
501 XFREE(ptrC, NULL, DYNAMIC_TYPE_BIGINT);
502 }
503 if (ptrD) {
504 XFREE(ptrD, NULL, DYNAMIC_TYPE_BIGINT);
505 }
506 }
507 else {
508 #if defined(FREESCALE_LTC_TFM_RSA_4096_ENABLE)
509 res = wolfcrypt_mp_mulmod(a, b, c, d);
510 #else
511 res = NOT_COMPILED_IN;
512 #endif
513 }
514
515 #ifdef ENABLE_NXPLTC_TESTS
516 /* compare hardware vs software */
517 if (doLtcTest && mp_cmp(&t, d) != MP_EQ) {
518 printf("mp_mulmod test fail!\n");
519
520 mp_dump("D", d, 0);
521 mp_dump("D soft", &t, 0);
522 }
523 mp_clear(&t);
524 #endif
525
526 return res;
527 }
528
529 /* Y = G^X mod P */
ltc_mp_exptmod(mp_int * G,mp_int * X,mp_int * P,mp_int * Y,int useConstTime)530 int ltc_mp_exptmod(mp_int *G, mp_int *X, mp_int *P, mp_int *Y, int useConstTime)
531 {
532 int res = MP_OKAY;
533 int szG, szX, szP;
534
535 #ifdef ENABLE_NXPLTC_TESTS
536 mp_int t;
537 mp_init(&t);
538 if (doLtcTest)
539 wolfcrypt_mp_exptmod(G, X, P, &t);
540 #endif
541
542 szG = mp_unsigned_bin_size(G);
543 szX = mp_unsigned_bin_size(X);
544 szP = mp_unsigned_bin_size(P);
545
546 if ((szG <= LTC_MAX_INT_BYTES) &&
547 (szX <= LTC_MAX_INT_BYTES) &&
548 (szP <= LTC_MAX_INT_BYTES))
549 {
550 uint16_t sizeG, sizeX, sizeP, sizeY;
551 uint8_t *ptrG, *ptrX, *ptrP, *ptrY;
552
553 ptrG = (uint8_t*)XMALLOC(LTC_MAX_INT_BYTES, NULL, DYNAMIC_TYPE_BIGINT);
554 ptrX = (uint8_t*)XMALLOC(LTC_MAX_INT_BYTES, NULL, DYNAMIC_TYPE_BIGINT);
555 ptrP = (uint8_t*)XMALLOC(LTC_MAX_INT_BYTES, NULL, DYNAMIC_TYPE_BIGINT);
556 ptrY = (uint8_t*)XMALLOC(LTC_MAX_INT_BYTES, NULL, DYNAMIC_TYPE_BIGINT);
557 if (ptrG && ptrX && ptrP && ptrY) {
558 res = ltc_get_lsb_bin_from_mp_int(ptrG, G, &sizeG);
559 if (res == MP_OKAY)
560 res = ltc_get_lsb_bin_from_mp_int(ptrX, X, &sizeX);
561 if (res == MP_OKAY)
562 res = ltc_get_lsb_bin_from_mp_int(ptrP, P, &sizeP);
563
564 /* if G >= P then reduce */
565 /* TODO: Perhaps always do mod reduce depending on hardware performance */
566 if (res == MP_OKAY &&
567 LTC_PKHA_CompareBigNum(ptrG, sizeG, ptrP, sizeP) >= 0) {
568 res = LTC_PKHA_ModRed(LTC_BASE,
569 ptrG, sizeG,
570 ptrP, sizeP,
571 ptrG, &sizeG, kLTC_PKHA_IntegerArith);
572 res = (res == kStatus_Success) ? MP_OKAY: MP_VAL;
573 }
574 if (res == MP_OKAY) {
575 res = LTC_PKHA_ModExp(LTC_BASE,
576 ptrG, sizeG, /* integer input */
577 ptrP, sizeP, /* modulus */
578 ptrX, sizeX, /* expenoent */
579 ptrY, &sizeY, /* out */
580 kLTC_PKHA_IntegerArith, kLTC_PKHA_NormalValue,
581 useConstTime ? kLTC_PKHA_TimingEqualized :
582 kLTC_PKHA_NoTimingEqualized);
583 res = (res == kStatus_Success) ? MP_OKAY: MP_VAL;
584 }
585 if (res == MP_OKAY) {
586 ltc_reverse_array(ptrY, sizeY);
587 res = mp_read_unsigned_bin(Y, ptrY, sizeY);
588 }
589 }
590 else {
591 res = MP_MEM;
592 }
593
594 if (ptrY) {
595 XFREE(ptrY, NULL, DYNAMIC_TYPE_BIGINT);
596 }
597 if (ptrP) {
598 XFREE(ptrP, NULL, DYNAMIC_TYPE_BIGINT);
599 }
600 if (ptrX) {
601 XFREE(ptrX, NULL, DYNAMIC_TYPE_BIGINT);
602 }
603 if (ptrG) {
604 XFREE(ptrG, NULL, DYNAMIC_TYPE_BIGINT);
605 }
606 }
607 else {
608 #if defined(FREESCALE_LTC_TFM_RSA_4096_ENABLE)
609 res = wolfcrypt_mp_exptmod(G, X, P, Y);
610 #else
611 res = NOT_COMPILED_IN;
612 #endif
613 }
614
615 #ifdef ENABLE_NXPLTC_TESTS
616 /* compare hardware vs software */
617 if (doLtcTest && mp_cmp(&t, Y) != MP_EQ) {
618 printf("mp_exptmod test fail!\n");
619
620 mp_dump("Y", Y, 0);
621 mp_dump("Y soft", &t, 0);
622 }
623 mp_clear(&t);
624 #endif
625
626 return res;
627 }
628
mp_exptmod(mp_int * G,mp_int * X,mp_int * P,mp_int * Y)629 int mp_exptmod(mp_int *G, mp_int *X, mp_int *P, mp_int *Y)
630 {
631 return ltc_mp_exptmod(G, X, P, Y, 1);
632 }
633
mp_exptmod_nct(mp_int * G,mp_int * X,mp_int * P,mp_int * Y)634 int mp_exptmod_nct(mp_int * G, mp_int * X, mp_int * P, mp_int * Y)
635 {
636 return ltc_mp_exptmod(G, X, P, Y, 0);
637 }
638
639 #if !defined(NO_DH) || !defined(NO_DSA) || !defined(NO_RSA) || \
640 defined(WOLFSSL_KEY_GEN)
mp_prime_is_prime_ex(mp_int * a,int t,int * result,WC_RNG * rng)641 int mp_prime_is_prime_ex(mp_int* a, int t, int* result, WC_RNG* rng)
642 {
643 int res = MP_OKAY;
644 int szA;
645
646 #ifdef ENABLE_NXPLTC_TESTS
647 int result_soft = 0;
648 if (doLtcTest)
649 mp_prime_is_prime_ex(a, t, &result_soft, rng);
650 #endif
651
652 szA = mp_unsigned_bin_size(a);
653 if (szA <= LTC_MAX_INT_BYTES) {
654 uint16_t sizeA, sizeB;
655 uint8_t *ptrA, *ptrB;
656
657 sizeB = mp_count_bits(a);
658 /* The base size is the number of bits / 8. One is added if the number
659 * of bits isn't an even 8. */
660 sizeB = (sizeB / 8) + ((sizeB % 8) ? 1 : 0);
661
662 ptrA = (uint8_t*)XMALLOC(LTC_MAX_INT_BYTES, NULL, DYNAMIC_TYPE_BIGINT);
663 ptrB = (uint8_t*)XMALLOC(sizeB, NULL, DYNAMIC_TYPE_BIGINT);
664 if (ptrA == NULL || ptrB == NULL) {
665 res = MEMORY_E;
666 }
667
668 if (res == MP_OKAY) {
669 #ifndef WC_NO_RNG
670 /* A NULL rng will return as bad function arg */
671 res = wc_RNG_GenerateBlock(rng, ptrB, sizeB);
672 #else
673 res = NOT_COMPILED_IN;
674 #endif
675 }
676
677 if (res == MP_OKAY) {
678 res = ltc_get_lsb_bin_from_mp_int(ptrA, a, &sizeA);
679 }
680 if (res == MP_OKAY) {
681 if (LTC_PKHA_PrimalityTest(LTC_BASE,
682 ptrB, sizeB, /* seed */
683 (uint8_t*)&t, sizeof(t), /* trials */
684 ptrA, sizeA, /* candidate */
685 (bool*)result) != kStatus_Success) {
686 res = MP_MEM;
687 }
688 }
689
690 if (ptrB) {
691 XFREE(ptrB, NULL, DYNAMIC_TYPE_BIGINT);
692 }
693 if (ptrA) {
694 XFREE(ptrA, NULL, DYNAMIC_TYPE_BIGINT);
695 }
696 }
697 else {
698 #if defined(FREESCALE_LTC_TFM_RSA_4096_ENABLE)
699 res = wolfcrypt_mp_prime_is_prime_ex(a, t, result, rng);
700 #else
701 res = NOT_COMPILED_IN;
702 #endif
703 }
704
705 #ifdef ENABLE_NXPLTC_TESTS
706 /* compare hardware vs software */
707 if (doLtcTest && *result != result_soft) {
708 printf("Fail! mp_prime_is_prime_ex %d != %d\n", *result, result_soft);
709 }
710 #endif
711
712 return res;
713 }
714
mp_prime_is_prime(mp_int * a,int t,int * result)715 int mp_prime_is_prime(mp_int* a, int t, int* result)
716 {
717 /* the NXP LTC prime check requires an RNG, so use software version */
718 return wolfcrypt_mp_prime_is_prime_ex(a, t, result, NULL);
719 }
720 #endif /* !NO_RSA || !NO_DSA || !NO_DH || WOLFSSL_KEY_GEN */
721
722 #endif /* FREESCALE_LTC_TFM */
723
724
725 /* ECC */
726 #if defined(HAVE_ECC) && defined(FREESCALE_LTC_ECC)
727
728 /* convert from mp_int to LTC integer, as array of bytes of size sz.
729 * if mp_int has less bytes than sz, add zero bytes at most significant byte
730 * positions.
731 * This is when for example modulus is 32 bytes (P-256 curve)
732 * and mp_int has only 31 bytes, we add leading zeros
733 * so that result array has 32 bytes, same as modulus (sz).
734 */
ltc_get_from_mp_int(uint8_t * dst,mp_int * a,int sz)735 static int ltc_get_from_mp_int(uint8_t *dst, mp_int *a, int sz)
736 {
737 int res;
738 int szbin;
739 int offset;
740
741 /* check how many bytes are in the mp_int */
742 szbin = mp_unsigned_bin_size(a);
743
744 /* compute offset from dst */
745 offset = sz - szbin;
746 if (offset < 0)
747 offset = 0;
748 if (offset > sz)
749 offset = sz;
750
751 /* add leading zeroes */
752 if (offset)
753 XMEMSET(dst, 0, offset);
754
755 /* convert mp_int to array of bytes */
756 res = mp_to_unsigned_bin(a, dst + offset);
757
758 if (res == MP_OKAY) {
759 /* reverse array for LTC direct use */
760 ltc_reverse_array(dst, sz);
761 }
762
763 return res;
764 }
765
766 /* ECC specs in lsbyte at lowest address format for direct use by LTC PKHA
767 * driver functions */
768 #if defined(HAVE_ECC192) || defined(HAVE_ALL_CURVES)
769 #define ECC192
770 #endif
771 #if defined(HAVE_ECC224) || defined(HAVE_ALL_CURVES)
772 #define ECC224
773 #endif
774 #if !defined(NO_ECC256) || defined(HAVE_ALL_CURVES)
775 #define ECC256
776 #endif
777 #if defined(HAVE_ECC384) || defined(HAVE_ALL_CURVES)
778 #define ECC384
779 #endif
780
781 #ifdef ECC192
782 #ifndef NO_ECC_SECP
783 static const uint8_t ltc_secp192r1_modulus[24] = {
784 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF,
785 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
786 static const uint8_t ltc_secp192r1_r2modn[24] = {
787 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
788 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
789 static const uint8_t ltc_secp192r1_aCurveParam[24] = {
790 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF,
791 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
792 static const uint8_t ltc_secp192r1_bCurveParam[24] = {
793 0xB1, 0xB9, 0x46, 0xC1, 0xEC, 0xDE, 0xB8, 0xFE, 0x49, 0x30, 0x24, 0x72,
794 0xAB, 0xE9, 0xA7, 0x0F, 0xE7, 0x80, 0x9C, 0xE5, 0x19, 0x05, 0x21, 0x64};
795 #endif
796 #ifdef HAVE_ECC_KOBLITZ
797 static const uint8_t ltc_secp192k1_modulus[24] = {
798 0x37, 0xEE, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
799 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
800 static const uint8_t ltc_secp192k1_r2modn[24] = {
801 0xD1, 0x4F, 0x3C, 0x01, 0x92, 0x23, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
802 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
803 static const uint8_t ltc_secp192k1_aCurveParam[24] = {
804 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
805 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
806 static const uint8_t ltc_secp192k1_bCurveParam[24] = {
807 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
808 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
809 #endif
810 #endif /* ECC192 */
811
812 #ifdef ECC224
813 #ifndef NO_ECC_SECP
814 static const uint8_t ltc_secp224r1_modulus[28] = {
815 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
816 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
817 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
818 static const uint8_t ltc_secp224r1_r2modn[28] = {
819 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
820 0x00, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
821 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00};
822 static const uint8_t ltc_secp224r1_aCurveParam[28] = {
823 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
824 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
825 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
826 static const uint8_t ltc_secp224r1_bCurveParam[28] = {
827 0xB4, 0xFF, 0x55, 0x23, 0x43, 0x39, 0x0B, 0x27, 0xBA, 0xD8,
828 0xBF, 0xD7, 0xB7, 0xB0, 0x44, 0x50, 0x56, 0x32, 0x41, 0xF5,
829 0xAB, 0xB3, 0x04, 0x0C, 0x85, 0x0A, 0x05, 0xB4};
830 #endif
831 #ifdef HAVE_ECC_KOBLITZ
832 static const uint8_t ltc_secp224k1_modulus[28] = {
833 0x6D, 0xE5, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
834 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
835 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
836 static const uint8_t ltc_secp224k1_r2modn[28] = {
837 0x69, 0x30, 0xC2, 0x02, 0x26, 0x35, 0x00, 0x00, 0x01, 0x00,
838 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
839 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
840 static const uint8_t ltc_secp224k1_aCurveParam[28] = {
841 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
842 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
843 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
844 static const uint8_t ltc_secp224k1_bCurveParam[28] = {
845 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
846 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
847 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
848 #endif
849 #endif /* ECC224 */
850
851 #ifdef ECC256
852 #ifndef NO_ECC_SECP
853 static const uint8_t ltc_secp256r1_modulus[32] = {
854 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
855 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
856 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF};
857 static const uint8_t ltc_secp256r1_r2modn[32] = { /* R^2 mod N */
858 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF,
859 0xFF, 0xFB, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
860 0xFF, 0xFF, 0xFD, 0xFF, 0xFF, 0xFF, 0x04, 0x00, 0x00, 0x00};
861 static const uint8_t ltc_secp256r1_aCurveParam[32] = {
862 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
863 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
864 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF};
865 static const uint8_t ltc_secp256r1_bCurveParam[32] = {
866 0x4B, 0x60, 0xD2, 0x27, 0x3E, 0x3C, 0xCE, 0x3B, 0xF6, 0xB0, 0x53,
867 0xCC, 0xB0, 0x06, 0x1D, 0x65, 0xBC, 0x86, 0x98, 0x76, 0x55, 0xBD,
868 0xEB, 0xB3, 0xE7, 0x93, 0x3A, 0xAA, 0xD8, 0x35, 0xC6, 0x5A};
869 #endif
870 #ifdef HAVE_ECC_KOBLITZ
871 static const uint8_t ltc_secp256k1_modulus[32] = {
872 0x2F, 0xFC, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
873 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
874 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
875 static const uint8_t ltc_secp256k1_r2modn[32] = { /* R^2 mod N */
876 0xA1, 0x90, 0x0E, 0x00, 0xA2, 0x07, 0x00, 0x00, 0x01, 0x00, 0x00,
877 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
878 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
879 static const uint8_t ltc_secp256k1_aCurveParam[32] = {
880 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
881 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
882 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
883 static const uint8_t ltc_secp256k1_bCurveParam[32] = {
884 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
885 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
886 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
887 #endif
888 #endif /* ECC256 */
889
890 #ifdef ECC384
891 #ifndef NO_ECC_SECP
892 static const uint8_t ltc_secp384r1_modulus[48] = {
893 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
894 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
895 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
896 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
897 static const uint8_t ltc_secp384r1_r2modn[48] = {
898 0x01, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
899 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff,
900 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
901 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
902 static const uint8_t ltc_secp384r1_aCurveParam[48] = {
903 0xfc, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
904 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
905 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
906 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
907 static const uint8_t ltc_secp384r1_bCurveParam[48] = {
908 0xef, 0x2a, 0xec, 0xd3, 0xed, 0xc8, 0x85, 0x2a, 0x9d, 0xd1, 0x2e, 0x8a,
909 0x8d, 0x39, 0x56, 0xc6, 0x5a, 0x87, 0x13, 0x50, 0x8f, 0x08, 0x14, 0x03,
910 0x12, 0x41, 0x81, 0xfe, 0x6e, 0x9c, 0x1d, 0x18, 0x19, 0x2d, 0xf8, 0xe3,
911 0x6b, 0x05, 0x8e, 0x98, 0xe4, 0xe7, 0x3e, 0xe2, 0xa7, 0x2f, 0x31, 0xb3};
912 #endif
913 #endif /* ECC384 */
914
ltc_get_ecc_specs(const uint8_t ** modulus,const uint8_t ** r2modn,const uint8_t ** aCurveParam,const uint8_t ** bCurveParam,const uint8_t * prime,int size)915 static int ltc_get_ecc_specs(const uint8_t **modulus, const uint8_t **r2modn,
916 const uint8_t **aCurveParam, const uint8_t **bCurveParam, const uint8_t *prime,
917 int size)
918 {
919 switch (size) {
920 #ifdef ECC256
921 case 32:
922 #ifndef NO_ECC_SECP
923 if (XMEMCMP(prime, ltc_secp256r1_modulus, size) == 0) {
924 *modulus = ltc_secp256r1_modulus;
925 *r2modn = ltc_secp256r1_r2modn;
926 *aCurveParam = ltc_secp256r1_aCurveParam;
927 *bCurveParam = ltc_secp256r1_bCurveParam;
928 return 0;
929 }
930 #endif
931 #ifdef HAVE_ECC_KOBLITZ
932 if (XMEMCMP(prime, ltc_secp256k1_modulus, size) == 0) {
933 *modulus = ltc_secp256k1_modulus;
934 *r2modn = ltc_secp256k1_r2modn;
935 *aCurveParam = ltc_secp256k1_aCurveParam;
936 *bCurveParam = ltc_secp256k1_bCurveParam;
937 return 0;
938 }
939 #endif
940 break;
941 #endif /* ECC256 */
942
943 #ifdef ECC224
944 case 28:
945 #ifndef NO_ECC_SECP
946 if (XMEMCMP(prime, ltc_secp224r1_modulus, size) == 0) {
947 *modulus = ltc_secp224r1_modulus;
948 *r2modn = ltc_secp224r1_r2modn;
949 *aCurveParam = ltc_secp224r1_aCurveParam;
950 *bCurveParam = ltc_secp224r1_bCurveParam;
951 return 0;
952 }
953 #endif
954 #ifdef HAVE_ECC_KOBLITZ
955 if (XMEMCMP(prime, ltc_secp224k1_modulus, size) == 0) {
956 *modulus = ltc_secp224k1_modulus;
957 *r2modn = ltc_secp224k1_r2modn;
958 *aCurveParam = ltc_secp224k1_aCurveParam;
959 *bCurveParam = ltc_secp224k1_bCurveParam;
960 return 0;
961 }
962 #endif
963 break;
964 #endif /* ECC224 */
965
966 #ifdef ECC192
967 case 24:
968 #ifndef NO_ECC_SECP
969 if (XMEMCMP(prime, ltc_secp192r1_modulus, size) == 0) {
970 *modulus = ltc_secp192r1_modulus;
971 *r2modn = ltc_secp192r1_r2modn;
972 *aCurveParam = ltc_secp192r1_aCurveParam;
973 *bCurveParam = ltc_secp192r1_bCurveParam;
974 return 0;
975 }
976 #endif
977 #ifdef HAVE_ECC_KOBLITZ
978 if (XMEMCMP(prime, ltc_secp192k1_modulus, size) == 0) {
979 *modulus = ltc_secp192k1_modulus;
980 *r2modn = ltc_secp192k1_r2modn;
981 *aCurveParam = ltc_secp192k1_aCurveParam;
982 *bCurveParam = ltc_secp192k1_bCurveParam;
983 return 0;
984 }
985 #endif
986 break;
987 #endif /* ECC192 */
988
989 #ifdef ECC384
990 case 48:
991 #ifndef NO_ECC_SECP
992 if (XMEMCMP(prime, ltc_secp384r1_modulus, size) == 0) {
993 *modulus = ltc_secp384r1_modulus;
994 *r2modn = ltc_secp384r1_r2modn;
995 *aCurveParam = ltc_secp384r1_aCurveParam;
996 *bCurveParam = ltc_secp384r1_bCurveParam;
997 return 0;
998 }
999 #endif
1000 break;
1001 #endif /* ECC384 */
1002
1003 default:
1004 break;
1005 }
1006
1007 return -1;
1008 }
1009
1010 /**
1011 Perform a point multiplication (timing resistant)
1012 k The scalar to multiply by
1013 G The base point
1014 R [out] Destination for kG
1015 modulus The modulus of the field the ECC curve is in
1016 map Boolean whether to map back to affine or not
1017 (1==map, 0 == leave in projective)
1018 return MP_OKAY on success
1019 */
wc_ecc_mulmod_ex(const mp_int * k,ecc_point * G,ecc_point * R,mp_int * a,mp_int * modulus,int map,void * heap)1020 int wc_ecc_mulmod_ex(const mp_int *k, ecc_point *G, ecc_point *R, mp_int* a,
1021 mp_int *modulus, int map, void* heap)
1022 {
1023 ltc_pkha_ecc_point_t B;
1024 uint8_t size;
1025 int szModulus;
1026 int szkbin;
1027 bool point_of_infinity;
1028 status_t status;
1029 int res;
1030
1031 uint8_t Gxbin[LTC_MAX_ECC_BITS / 8];
1032 uint8_t Gybin[LTC_MAX_ECC_BITS / 8];
1033 uint8_t kbin[LTC_MAX_INT_BYTES];
1034
1035 const uint8_t *modbin;
1036 const uint8_t *aCurveParam;
1037 const uint8_t *bCurveParam;
1038 const uint8_t *r2modn;
1039
1040 (void)a;
1041 (void)heap;
1042
1043 if (k == NULL || G == NULL || R == NULL || modulus == NULL) {
1044 return ECC_BAD_ARG_E;
1045 }
1046
1047 szModulus = mp_unsigned_bin_size(modulus);
1048 szkbin = mp_unsigned_bin_size(k);
1049
1050 /* make sure LTC big number variable is large enough */
1051 if (szModulus > LTC_MAX_INT_BYTES / 2) {
1052 return MP_MEM;
1053 }
1054
1055 res = ltc_get_from_mp_int(kbin, (mp_int*)k, szkbin);
1056 if (res == MP_OKAY)
1057 res = ltc_get_from_mp_int(Gxbin, G->x, szModulus);
1058 if (res == MP_OKAY)
1059 res = ltc_get_from_mp_int(Gybin, G->y, szModulus);
1060 if (res != MP_OKAY)
1061 return res;
1062
1063 size = szModulus;
1064
1065 /* find LTC friendly parameters for the selected curve */
1066 if (ltc_get_ecc_specs(&modbin, &r2modn, &aCurveParam, &bCurveParam,
1067 (const uint8_t *)modulus->dp, size) != 0) {
1068 return ECC_BAD_ARG_E;
1069 }
1070
1071 B.X = &Gxbin[0];
1072 B.Y = &Gybin[0];
1073
1074 status = LTC_PKHA_ECC_PointMul(LTC_BASE, &B, kbin, szkbin, modbin, r2modn,
1075 aCurveParam, bCurveParam, size, kLTC_PKHA_TimingEqualized,
1076 kLTC_PKHA_IntegerArith, &B, &point_of_infinity);
1077 if (status != kStatus_Success) {
1078 return MP_VAL;
1079 }
1080
1081 ltc_reverse_array(Gxbin, size);
1082 ltc_reverse_array(Gybin, size);
1083 res = mp_read_unsigned_bin(R->x, Gxbin, size);
1084 if (res == MP_OKAY) {
1085 res = mp_read_unsigned_bin(R->y, Gybin, size);
1086 /* if k is negative, we compute the multiplication with abs(-k)
1087 * with result (x, y) and modify the result to (x, -y)
1088 */
1089 #if (!defined(WOLFSSL_SP_MATH) && !defined(WOLFSSL_SP_MATH_ALL)) || \
1090 defined(WOLFSSL_SP_INT_NEGATIVE)
1091 R->y->sign = k->sign;
1092 #endif
1093 }
1094 if (res == MP_OKAY)
1095 res = mp_set(R->z, 1);
1096
1097 return res;
1098 }
1099
wc_ecc_mulmod_ex2(const mp_int * k,ecc_point * G,ecc_point * R,mp_int * a,mp_int * modulus,mp_int * order,WC_RNG * rng,int map,void * heap)1100 int wc_ecc_mulmod_ex2(const mp_int* k, ecc_point *G, ecc_point *R, mp_int* a,
1101 mp_int* modulus, mp_int* order, WC_RNG* rng, int map,
1102 void* heap)
1103 {
1104 (void)order;
1105 (void)rng;
1106 return wc_ecc_mulmod_ex(k, G, R, a, modulus, map, heap);
1107 }
1108
ecc_map_ex(ecc_point * P,mp_int * modulus,mp_digit mp,int ct)1109 int ecc_map_ex(ecc_point* P, mp_int* modulus, mp_digit mp, int ct)
1110 {
1111 /* this is handled in hardware, so no projective mapping needed */
1112 (void)P;
1113 (void)modulus;
1114 (void)mp;
1115 (void)ct;
1116 return MP_OKAY;
1117 }
1118
wc_ecc_point_add(ecc_point * mG,ecc_point * mQ,ecc_point * mR,mp_int * m)1119 int wc_ecc_point_add(ecc_point *mG, ecc_point *mQ, ecc_point *mR, mp_int *m)
1120 {
1121 int res;
1122 ltc_pkha_ecc_point_t A, B;
1123 int size;
1124 status_t status;
1125
1126 uint8_t Gxbin[LTC_MAX_ECC_BITS / 8];
1127 uint8_t Gybin[LTC_MAX_ECC_BITS / 8];
1128 uint8_t Qxbin[LTC_MAX_ECC_BITS / 8];
1129 uint8_t Qybin[LTC_MAX_ECC_BITS / 8];
1130 const uint8_t *modbin;
1131 const uint8_t *aCurveParam;
1132 const uint8_t *bCurveParam;
1133 const uint8_t *r2modn;
1134
1135 size = mp_unsigned_bin_size(m);
1136
1137 /* find LTC friendly parameters for the selected curve */
1138 if (ltc_get_ecc_specs(&modbin, &r2modn, &aCurveParam, &bCurveParam,
1139 (const uint8_t *)m->dp, size) != 0) {
1140 res = ECC_BAD_ARG_E;
1141 }
1142 else {
1143 res = ltc_get_from_mp_int(Gxbin, mG->x, size);
1144 if (res == MP_OKAY)
1145 res = ltc_get_from_mp_int(Gybin, mG->y, size);
1146 if (res == MP_OKAY)
1147 res = ltc_get_from_mp_int(Qxbin, mQ->x, size);
1148 if (res == MP_OKAY)
1149 res = ltc_get_from_mp_int(Qybin, mQ->y, size);
1150
1151 if (res != MP_OKAY)
1152 return res;
1153
1154 A.X = Gxbin;
1155 A.Y = Gybin;
1156
1157 B.X = Qxbin;
1158 B.Y = Qybin;
1159
1160 status = LTC_PKHA_ECC_PointAdd(LTC_BASE, &A, &B, modbin, r2modn,
1161 aCurveParam, bCurveParam, size, kLTC_PKHA_IntegerArith, &A);
1162 if (status != kStatus_Success) {
1163 res = MP_VAL;
1164 }
1165 else {
1166 ltc_reverse_array(Gxbin, size);
1167 ltc_reverse_array(Gybin, size);
1168 res = mp_read_unsigned_bin(mR->x, Gxbin, size);
1169 if (res == MP_OKAY)
1170 res = mp_read_unsigned_bin(mR->y, Gybin, size);
1171 if (res == MP_OKAY)
1172 res = mp_set(mR->z, 1);
1173 }
1174 }
1175 return res;
1176 }
1177
1178 #if defined(HAVE_ED25519) || defined(HAVE_CURVE25519)
1179 /* Weierstrass parameters of prime 2^255 - 19 */
1180 static const uint8_t curve25519_modbin[32] = {
1181 0xed, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1182 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1183 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f};
1184 /* precomputed R2modN for the curve25519 */
1185 static const uint8_t r2mod[32] = {
1186 0xa4, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1187 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1188 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
1189
1190 /* invThree = ModInv(3,curve25519_modbin) in LSB first */
1191 static const uint8_t invThree[32] = {
1192 0x49, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
1193 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
1194 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55};
1195
1196 /*
1197 *
1198 * finds square root in finite field when modulus congruent to 5 modulo 8
1199 * this is fixed to curve25519 modulus 2^255 - 19 which is congruent to
1200 * 5 modulo 8.
1201 *
1202 * This function solves equation: res^2 = a mod (2^255 - 19)
1203 *
1204 p = prime
1205 p % 8 must be 5
1206
1207 v = ModularArithmetic.powmod(2*a, (p-5)/8, p)
1208 i = (2*a*v**2) % p
1209 r1 = 1*a*v*(i - 1) % p
1210 r2 = -1*a*v*(i - 1) % p
1211 puts "Gy=0x#{r2.to_s(16)}"
1212 */
LTC_PKHA_Prime25519SquareRootMod(const uint8_t * A,size_t sizeA,uint8_t * res,size_t * szRes,int sign)1213 status_t LTC_PKHA_Prime25519SquareRootMod(const uint8_t *A, size_t sizeA,
1214 uint8_t *res, size_t *szRes, int sign)
1215 {
1216 status_t status;
1217 const uint8_t curve25519_param[] = {
1218 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1219 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1220 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f};
1221 uint8_t twoA[sizeof(curve25519_modbin)] = {0};
1222 uint8_t V[sizeof(curve25519_modbin)] = {0};
1223 uint8_t I[sizeof(curve25519_modbin)] = {0};
1224 uint8_t VV[sizeof(curve25519_modbin)] = {0};
1225 uint16_t szTwoA = 0;
1226 uint16_t szV = 0;
1227 uint16_t szVV = 0;
1228 uint16_t szI = 0;
1229 uint16_t szRes16 = 0;
1230 uint8_t one = 1;
1231
1232 /* twoA = 2*A % p */
1233 status = LTC_PKHA_ModAdd(LTC_BASE, A, sizeA, A, sizeA, curve25519_modbin,
1234 sizeof(curve25519_modbin), twoA, &szTwoA, kLTC_PKHA_IntegerArith);
1235
1236 /* V = ModularArithmetic.powmod(twoA, (p-5)/8, p) */
1237 if (status == kStatus_Success) {
1238 status =
1239 LTC_PKHA_ModExp(LTC_BASE, twoA, szTwoA, curve25519_modbin,
1240 sizeof(curve25519_modbin), curve25519_param,
1241 sizeof(curve25519_param), V, &szV, kLTC_PKHA_IntegerArith,
1242 kLTC_PKHA_NormalValue, kLTC_PKHA_TimingEqualized);
1243 }
1244
1245 /* VV = V*V % p */
1246 if (status == kStatus_Success) {
1247 status = LTC_PKHA_ModMul(LTC_BASE, V, szV, V, szV, curve25519_modbin,
1248 sizeof(curve25519_modbin), VV, &szVV, kLTC_PKHA_IntegerArith,
1249 kLTC_PKHA_NormalValue, kLTC_PKHA_NormalValue,
1250 kLTC_PKHA_TimingEqualized);
1251 }
1252
1253 /* I = twoA * VV = 2*A*V*V % p */
1254 if (status == kStatus_Success) {
1255 status = LTC_PKHA_ModMul(LTC_BASE, twoA, szTwoA, VV, szVV,
1256 curve25519_modbin, sizeof(curve25519_modbin), I, &szI,
1257 kLTC_PKHA_IntegerArith, kLTC_PKHA_NormalValue,
1258 kLTC_PKHA_NormalValue, kLTC_PKHA_TimingEqualized);
1259 }
1260
1261 /* I = I - 1 */
1262 /* just temp for maximum integer - for non-modular subtract */
1263 XMEMSET(VV, 0xff, sizeof(VV));
1264 if (LTC_PKHA_CompareBigNum(I, szI, &one, sizeof(one)) >= 0) {
1265 if (status == kStatus_Success) {
1266 status = LTC_PKHA_ModSub1(LTC_BASE, I, szI, &one, sizeof(one),
1267 VV, sizeof(VV), I, &szI);
1268 }
1269 }
1270 else {
1271 if (status == kStatus_Success) {
1272 status = LTC_PKHA_ModSub1(LTC_BASE, curve25519_modbin,
1273 sizeof(curve25519_modbin), &one, sizeof(one), VV, sizeof(VV), I,
1274 &szI);
1275 }
1276 }
1277
1278 /* res = a*v mod p */
1279 status = LTC_PKHA_ModMul(LTC_BASE, A, sizeA, V, szV, curve25519_modbin,
1280 sizeof(curve25519_modbin), res, &szRes16, kLTC_PKHA_IntegerArith,
1281 kLTC_PKHA_NormalValue, kLTC_PKHA_NormalValue,
1282 kLTC_PKHA_TimingEqualized);
1283
1284 /* res = res * (i-1) mod p */
1285 if (status == kStatus_Success) {
1286 status = LTC_PKHA_ModMul(LTC_BASE, res, szRes16, I, szI,
1287 curve25519_modbin, sizeof(curve25519_modbin), res, &szRes16,
1288 kLTC_PKHA_IntegerArith, kLTC_PKHA_NormalValue,
1289 kLTC_PKHA_NormalValue, kLTC_PKHA_TimingEqualized);
1290 }
1291
1292 /* if X mod 2 != X_0 then we need the -X
1293 *
1294 * X mod 2 get from LSB bit0
1295 */
1296 if ((status == kStatus_Success) &&
1297 ((bool)sign != (bool)(res[0] & 0x01u)))
1298 {
1299 status = LTC_PKHA_ModSub1(LTC_BASE, curve25519_modbin,
1300 sizeof(curve25519_modbin), res, szRes16, VV, sizeof(VV), res,
1301 &szRes16); /* -a = p - a */
1302 }
1303
1304 if (status == kStatus_Success) {
1305 *szRes = szRes16;
1306 }
1307
1308 return status;
1309 }
1310 #endif /* HAVE_ED25519 || HAVE_CURVE25519 */
1311
1312
1313 #ifdef HAVE_CURVE25519
1314
1315 /* for LTC we need Weierstrass format of curve25519 parameters
1316 * these two are base point X and Y.
1317 * in LSB first format (native for LTC)
1318 */
1319 static const ECPoint ecBasePoint = {
1320 {0x5a, 0x24, 0xad, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
1321 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
1322 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x2a},
1323 {0xd9, 0xd3, 0xce, 0x7e, 0xa2, 0xc5, 0xe9, 0x29, 0xb2, 0x61, 0x7c,
1324 0x6d, 0x7e, 0x4d, 0x3d, 0x92, 0x4c, 0xd1, 0x48, 0x77, 0x2c, 0xdd,
1325 0x1e, 0xe0, 0xb4, 0x86, 0xa0, 0xb8, 0xa1, 0x19, 0xae, 0x20},
1326 };
1327
nxp_ltc_curve25519_GetBasePoint(void)1328 const ECPoint *nxp_ltc_curve25519_GetBasePoint(void)
1329 {
1330 return &ecBasePoint;
1331 }
1332
1333 static const uint8_t curve25519_aCurveParam[CURVE25519_KEYSIZE] = {
1334 0x44, 0xa1, 0x14, 0x49, 0x98, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
1335 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
1336 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
1337 0xaa, 0xaa, 0xaa, 0xaa, 0x2a};
1338
1339 static const uint8_t curve25519_bCurveParam[CURVE25519_KEYSIZE] = {
1340 0x64, 0xc8, 0x10, 0x77, 0x9c, 0x5e, 0x0b, 0x26, 0xb4, 0x97, 0xd0,
1341 0x5e, 0x42, 0x7b, 0x09, 0xed,
1342 0x25, 0xb4, 0x97, 0xd0, 0x5e, 0x42, 0x7b, 0x09, 0xed, 0x25, 0xb4,
1343 0x97, 0xd0, 0x5e, 0x42, 0x7b};
1344
1345 /* transform a point on Montgomery curve to a point on Weierstrass curve */
LTC_PKHA_Curve25519ToWeierstrass(const ltc_pkha_ecc_point_t * ltcPointIn,ltc_pkha_ecc_point_t * ltcPointOut)1346 status_t LTC_PKHA_Curve25519ToWeierstrass(
1347 const ltc_pkha_ecc_point_t *ltcPointIn,ltc_pkha_ecc_point_t *ltcPointOut)
1348 {
1349 /* offset X point (in Montgomery) so that it becomes Weierstrass */
1350 const uint8_t offset[] = {
1351 0x51, 0x24, 0xad, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
1352 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
1353 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x2a};
1354 uint16_t sizeRes = 0;
1355 status_t status;
1356 status = LTC_PKHA_ModAdd(LTC_BASE, ltcPointIn->X, CURVE25519_KEYSIZE,
1357 offset, sizeof(offset), curve25519_modbin, CURVE25519_KEYSIZE,
1358 ltcPointOut->X, &sizeRes, kLTC_PKHA_IntegerArith);
1359
1360 if (status == kStatus_Success) {
1361 if (ltcPointOut->Y != ltcPointIn->Y) {
1362 XMEMCPY(ltcPointOut->Y, ltcPointIn->Y, CURVE25519_KEYSIZE);
1363 }
1364 }
1365
1366 return status;
1367 }
1368
1369 /* transform a point on Weierstrass curve to a point on Montgomery curve */
LTC_PKHA_WeierstrassToCurve25519(const ltc_pkha_ecc_point_t * ltcPointIn,ltc_pkha_ecc_point_t * ltcPointOut)1370 status_t LTC_PKHA_WeierstrassToCurve25519(
1371 const ltc_pkha_ecc_point_t *ltcPointIn, ltc_pkha_ecc_point_t *ltcPointOut)
1372 {
1373 status_t status;
1374 uint16_t resultSize = 0;
1375 const uint8_t three = 0x03;
1376
1377 status = LTC_PKHA_ModMul(LTC_BASE, &three, sizeof(three), ltcPointIn->X,
1378 CURVE25519_KEYSIZE, curve25519_modbin, CURVE25519_KEYSIZE,
1379 ltcPointOut->X, &resultSize, kLTC_PKHA_IntegerArith,
1380 kLTC_PKHA_NormalValue, kLTC_PKHA_NormalValue,
1381 kLTC_PKHA_TimingEqualized);
1382
1383 if (status == kStatus_Success) {
1384 const uint8_t A[] = {0x06, 0x6d, 0x07};
1385 if (LTC_PKHA_CompareBigNum(ltcPointOut->X, resultSize, A, sizeof(A))) {
1386 status = LTC_PKHA_ModSub1(LTC_BASE, ltcPointOut->X, resultSize, A,
1387 sizeof(A), curve25519_modbin, CURVE25519_KEYSIZE,
1388 ltcPointOut->X, &resultSize);
1389 }
1390 else {
1391 status = LTC_PKHA_ModSub2(LTC_BASE, ltcPointOut->X, resultSize, A,
1392 sizeof(A), curve25519_modbin, CURVE25519_KEYSIZE,
1393 ltcPointOut->X, &resultSize);
1394 }
1395 }
1396
1397 if (status == kStatus_Success) {
1398 status = LTC_PKHA_ModMul(LTC_BASE, invThree, CURVE25519_KEYSIZE,
1399 ltcPointOut->X, resultSize, curve25519_modbin, CURVE25519_KEYSIZE,
1400 ltcPointOut->X, &resultSize, kLTC_PKHA_IntegerArith,
1401 kLTC_PKHA_NormalValue, kLTC_PKHA_NormalValue,
1402 kLTC_PKHA_TimingEqualized);
1403 }
1404
1405 if (status == kStatus_Success) {
1406 if (ltcPointOut->Y != ltcPointIn->Y) {
1407 XMEMCPY(ltcPointOut->Y, ltcPointIn->Y, CURVE25519_KEYSIZE);
1408 }
1409 }
1410
1411 return status;
1412 }
1413
1414 /* Y = square root (X^3 + 486662*X^2 + X) */
LTC_PKHA_Curve25519ComputeY(ltc_pkha_ecc_point_t * ltcPoint)1415 status_t LTC_PKHA_Curve25519ComputeY(ltc_pkha_ecc_point_t *ltcPoint)
1416 {
1417 uint8_t three = 3;
1418 const uint8_t A[] = {0x06, 0x6d, 0x07};
1419 uint8_t U[CURVE25519_KEYSIZE] = {0};
1420 uint8_t X2[CURVE25519_KEYSIZE] = {0};
1421 uint16_t sizeU = 0;
1422 uint16_t sizeX2 = 0;
1423 size_t szRes = 0;
1424 status_t status;
1425
1426 /* X^3 */
1427 status = LTC_PKHA_ModExp(LTC_BASE, ltcPoint->X, CURVE25519_KEYSIZE,
1428 curve25519_modbin, CURVE25519_KEYSIZE, &three, 1, U, &sizeU,
1429 kLTC_PKHA_IntegerArith, kLTC_PKHA_NormalValue,
1430 kLTC_PKHA_TimingEqualized);
1431
1432 /* X^2 */
1433 if (status == kStatus_Success) {
1434 status = LTC_PKHA_ModMul(LTC_BASE, ltcPoint->X, CURVE25519_KEYSIZE,
1435 ltcPoint->X, CURVE25519_KEYSIZE, curve25519_modbin,
1436 CURVE25519_KEYSIZE, X2, &sizeX2, kLTC_PKHA_IntegerArith,
1437 kLTC_PKHA_NormalValue, kLTC_PKHA_NormalValue,
1438 kLTC_PKHA_TimingEqualized);
1439 }
1440
1441 /* 486662*X^2 */
1442 if (status == kStatus_Success) {
1443 status = LTC_PKHA_ModMul(LTC_BASE, A, sizeof(A), X2, sizeX2,
1444 curve25519_modbin, CURVE25519_KEYSIZE, X2, &sizeX2,
1445 kLTC_PKHA_IntegerArith, kLTC_PKHA_NormalValue,
1446 kLTC_PKHA_NormalValue, kLTC_PKHA_TimingEqualized);
1447 }
1448
1449 /* X^3 + 486662*X^2 */
1450 if (status == kStatus_Success) {
1451 status = LTC_PKHA_ModAdd(LTC_BASE, U, sizeU, X2, sizeX2,
1452 curve25519_modbin, CURVE25519_KEYSIZE, U, &sizeU,
1453 kLTC_PKHA_IntegerArith);
1454 }
1455
1456 /* U = X^3 + 486662*X^2 + X */
1457 if (status == kStatus_Success) {
1458 status = LTC_PKHA_ModAdd(LTC_BASE, U, sizeU, ltcPoint->X,
1459 CURVE25519_KEYSIZE, curve25519_modbin, CURVE25519_KEYSIZE, U,
1460 &sizeU, kLTC_PKHA_IntegerArith);
1461 }
1462
1463 /* Y = modular square root of U (U is Y^2) */
1464 if (status == kStatus_Success) {
1465 status = LTC_PKHA_Prime25519SquareRootMod(U, sizeU, ltcPoint->Y,
1466 &szRes, 1);
1467 }
1468
1469 return status;
1470 }
1471
1472 /* Q = n*P */
1473 /* if type is set, the input point p is in Montgomery curve coordinates,
1474 so there is a map to Weierstrass curve */
1475 /* q output point is always in Montgomery curve coordinates */
nxp_ltc_curve25519(ECPoint * q,const byte * n,const ECPoint * p,fsl_ltc_ecc_coordinate_system_t type)1476 int nxp_ltc_curve25519(ECPoint *q, const byte *n, const ECPoint *p,
1477 fsl_ltc_ecc_coordinate_system_t type)
1478 {
1479 status_t status;
1480 ltc_pkha_ecc_point_t ltcPoint;
1481 ltc_pkha_ecc_point_t ltcPointOut;
1482 ECPoint pIn = {{0}};
1483
1484 XMEMCPY(&pIn, p, sizeof(*p));
1485 ltcPoint.X = &pIn.point[0];
1486 ltcPoint.Y = &pIn.pointY[0];
1487
1488 /* if input point P is on Curve25519 Montgomery curve, transform
1489 it to Weierstrass equivalent */
1490 if (type == kLTC_Curve25519) {
1491 LTC_PKHA_Curve25519ToWeierstrass(<cPoint, <cPoint);
1492 }
1493
1494 ltcPointOut.X = &q->point[0];
1495 ltcPointOut.Y = &q->pointY[0];
1496 /* curve25519_modbin, r2mod, curve25519_aCurveParam, curve25519_bCurveParam
1497 * are Weierstrass equivalent with Curve25519 */
1498 status = LTC_PKHA_ECC_PointMul(LTC_BASE, <cPoint, n, CURVE25519_KEYSIZE,
1499 curve25519_modbin, r2mod, curve25519_aCurveParam,
1500 curve25519_bCurveParam, CURVE25519_KEYSIZE, kLTC_PKHA_TimingEqualized,
1501 kLTC_PKHA_IntegerArith, <cPointOut, NULL);
1502
1503 /* now need to map from Weierstrass form to Montgomery form */
1504 if (status == kStatus_Success) {
1505 status = LTC_PKHA_WeierstrassToCurve25519(<cPointOut, <cPointOut);
1506 }
1507
1508 return (status == kStatus_Success) ? 0 : IS_POINT_E;
1509 }
1510
1511 #endif /* HAVE_CURVE25519 */
1512
1513
1514 #ifdef HAVE_ED25519
1515 /* a and d are Edwards curve parameters -1 and -121665/121666 prime is 2^255 - 19.
1516 *
1517 * https://en.wikipedia.org/wiki/Montgomery_curve#Equivalence_with_Edward_curves
1518 */
1519
1520 /* d parameter of ed25519 */
1521 static const uint8_t d_coefEd25519[] = {
1522 0xa3, 0x78, 0x59, 0x13, 0xca, 0x4d, 0xeb, 0x75, 0xab, 0xd8, 0x41,
1523 0x41, 0x4d, 0x0a, 0x70, 0x00, 0x98, 0xe8, 0x79, 0x77, 0x79, 0x40,
1524 0xc7, 0x8c, 0x73, 0xfe, 0x6f, 0x2b, 0xee, 0x6c, 0x03, 0x52};
1525
1526 /* Montgomery curve parameter A for a Montgomery curve equivalent with ed25519 */
1527 static const uint8_t A_coefEd25519[] = {
1528 0x06, 0x6d, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1529 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1530 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
1531
1532 /* Montgomery curve parameter B for a Montgomery curve equivalent with ed25519 */
1533 static const uint8_t B_coefEd25519[] = {
1534 0xe5, 0x92, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1535 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1536 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f};
1537
1538 /* these are pre-computed constants used in computations */
1539
1540 /* = 3*B */
1541 static const uint8_t threeB_coefEd25519[] = {
1542 0xd5, 0xb8, 0xe9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1543 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1544 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f};
1545
1546 /* = -A */
1547 static const uint8_t minus_A_coefEd25519[] = {
1548 0xe7, 0x92, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1549 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1550 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f};
1551
1552 /* = 1/B */
1553 static const uint8_t invB_coefEd25519[] = {
1554 0xc4, 0xa1, 0x29, 0x7b, 0x8d, 0x2c, 0x85, 0x22, 0xd5, 0x89, 0xaf,
1555 0xaf, 0x6c, 0xfd, 0xe3, 0xff, 0xd9, 0x85, 0x21, 0xa2, 0xe1, 0x2f,
1556 0xce, 0x1c, 0x63, 0x00, 0x24, 0x75, 0xc4, 0x24, 0x7f, 0x6b};
1557
1558 /* = 1/(3*B) */
1559 static const uint8_t A_mul_invThreeB_coefEd25519[] = {
1560 0xb9, 0x3e, 0xe4, 0xad, 0xa1, 0x37, 0xa7, 0x93, 0x1c, 0xa4, 0x35,
1561 0xe0, 0x0c, 0x57, 0xbd, 0xaa, 0x6e, 0x51, 0x94, 0x3e, 0x14, 0xe0,
1562 0xcb, 0xec, 0xbd, 0xff, 0xe7, 0xb1, 0x27, 0x92, 0x00, 0x63};
1563
1564 /* Weierstrass curve parameter a for a Weierstrass curve equivalent with ed25519 */
1565 static const uint8_t a_coefEd25519[] = {
1566 0x2d, 0x17, 0xbc, 0xf8, 0x8e, 0xe1, 0x71, 0xac, 0xf7, 0x2a, 0xa5,
1567 0x0c, 0x5d, 0xb6, 0xb8, 0x6b, 0xd6, 0x3d, 0x7b, 0x61, 0x0d, 0xe1,
1568 0x97, 0x31, 0xe6, 0xbe, 0xb9, 0xa5, 0xd3, 0xac, 0x4e, 0x5d};
1569
1570 /* Weierstrass curve parameter b for a Weierstrass curve equivalent with ed25519 */
1571 static const uint8_t b_coefEd25519[] = {
1572 0xa4, 0xb2, 0x64, 0xf3, 0xc1, 0xeb, 0x04, 0x90, 0x32, 0xbc, 0x9f,
1573 0x6b, 0x97, 0x31, 0x48, 0xf5, 0xd5, 0x80, 0x57, 0x10, 0x06, 0xdb,
1574 0x0d, 0x55, 0xe0, 0xb3, 0xd0, 0xcf, 0x9b, 0xb2, 0x11, 0x1d};
1575
1576 /* Ed25519 basepoint B mapped to Weierstrass equivalent */
1577 static uint8_t Wx_Ed25519[ED25519_KEY_SIZE] = {
1578 0x35, 0xef, 0x5a, 0x02, 0x9b, 0xc8, 0x55, 0xca, 0x9a, 0x7c, 0x61,
1579 0x0d, 0xdf, 0x3f, 0xc1, 0xa9, 0x18, 0x06, 0xc2, 0xf1, 0x02, 0x8f,
1580 0x0b, 0xf0, 0x39, 0x03, 0x2c, 0xd0, 0x0f, 0xdd, 0x78, 0x2a};
1581 static uint8_t Wy_Ed25519[ED25519_KEY_SIZE] = {
1582 0x14, 0x1d, 0x2c, 0xf6, 0xf3, 0x30, 0x78, 0x9b, 0x65, 0x31, 0x71,
1583 0x80, 0x61, 0xd0, 0x6f, 0xcf, 0x23, 0x83, 0x79, 0x63, 0xa5, 0x3b,
1584 0x48, 0xbe, 0x2e, 0xa2, 0x1d, 0xc7, 0xa5, 0x44, 0xc6, 0x29};
1585
1586 static const ltc_pkha_ecc_point_t basepointEd25519 = {
1587 Wx_Ed25519, Wy_Ed25519,
1588 };
1589
LTC_PKHA_Ed25519_BasePoint(void)1590 const ltc_pkha_ecc_point_t *LTC_PKHA_Ed25519_BasePoint(void)
1591 {
1592 return &basepointEd25519;
1593 }
1594
1595 /* input point is on Weierstrass curve, typeOut determines the coordinates
1596 system of output point (either Weierstrass or Ed25519) */
LTC_PKHA_Ed25519_PointMul(const ltc_pkha_ecc_point_t * ltcPointIn,const uint8_t * N,size_t sizeN,ltc_pkha_ecc_point_t * ltcPointOut,fsl_ltc_ecc_coordinate_system_t typeOut)1597 status_t LTC_PKHA_Ed25519_PointMul(const ltc_pkha_ecc_point_t *ltcPointIn,
1598 const uint8_t *N,
1599 size_t sizeN,
1600 ltc_pkha_ecc_point_t *ltcPointOut,
1601 fsl_ltc_ecc_coordinate_system_t typeOut)
1602 {
1603 uint16_t szN = (uint16_t)sizeN;
1604 status_t status;
1605 /* input on W, output in W, W parameters of ECC curve are Ed25519 curve
1606 parameters mapped to Weierstrass curve */
1607 status = LTC_PKHA_ECC_PointMul(LTC_BASE, ltcPointIn, N, szN,
1608 curve25519_modbin, r2mod, a_coefEd25519, b_coefEd25519,
1609 ED25519_KEY_SIZE, kLTC_PKHA_TimingEqualized, kLTC_PKHA_IntegerArith,
1610 ltcPointOut, NULL);
1611
1612 /* Weierstrass coordinates to Ed25519 coordinates */
1613 if ((status == kStatus_Success) && (typeOut == kLTC_Ed25519)) {
1614 status = LTC_PKHA_WeierstrassToEd25519(ltcPointOut, ltcPointOut);
1615 }
1616 return status;
1617 }
1618
LTC_PKHA_Ed25519ToWeierstrass(const ltc_pkha_ecc_point_t * ltcPointIn,ltc_pkha_ecc_point_t * ltcPointOut)1619 status_t LTC_PKHA_Ed25519ToWeierstrass(const ltc_pkha_ecc_point_t *ltcPointIn,
1620 ltc_pkha_ecc_point_t *ltcPointOut)
1621 {
1622 status_t status;
1623 uint8_t Mx[ED25519_KEY_SIZE] = {0};
1624 uint8_t My[ED25519_KEY_SIZE] = {0};
1625 uint8_t temp[ED25519_KEY_SIZE] = {0};
1626 uint8_t temp2[ED25519_KEY_SIZE] = {0};
1627 const uint8_t max[32] = {
1628 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1629 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1630 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
1631 const uint8_t *Ex;
1632 const uint8_t *Ey;
1633 uint8_t *Gx;
1634 uint8_t *Gy;
1635 uint16_t szMx = 0;
1636 uint16_t szGx = 0;
1637 uint16_t szMy = 0;
1638 uint16_t szGy = 0;
1639 uint16_t szTemp = 0;
1640 uint16_t szTemp2 = 0;
1641 uint8_t one = 1;
1642
1643 Ex = ltcPointIn->X;
1644 Ey = ltcPointIn->Y;
1645 Gx = ltcPointOut->X;
1646 Gy = ltcPointOut->Y;
1647 /* # (Ex, Ey) on Ed (a_ed, d) to (x, y) on M (A,B)
1648 Mx = (1 + Ey) * ModularArithmetic.invert(1 - Ey, prime) % prime
1649 My = (1 + Ey) * ModularArithmetic.invert((1 - Ey)*Ex, prime) % prime */
1650
1651 /* Gx = ((Mx * ModularArithmetic.invert(B, prime)) +
1652 (A * ModularArithmetic.invert(3*B, prime))) % prime
1653 Gy = (My * ModularArithmetic.invert(B, prime)) % prime */
1654
1655 /* temp = 1 + Ey */
1656 status = LTC_PKHA_ModAdd(LTC_BASE, Ey, ED25519_KEY_SIZE, &one, sizeof(one),
1657 curve25519_modbin, sizeof(curve25519_modbin), temp, &szTemp,
1658 kLTC_PKHA_IntegerArith);
1659
1660 /* temp2 = 1 - Ey = 1 + (p - Ey) */
1661 if (status == kStatus_Success) {
1662 status = LTC_PKHA_ModSub1(LTC_BASE, curve25519_modbin,
1663 sizeof(curve25519_modbin), Ey, ED25519_KEY_SIZE, max, sizeof(max),
1664 temp2, &szTemp2);
1665 }
1666 if (status == kStatus_Success) {
1667 status = LTC_PKHA_ModAdd(LTC_BASE, temp2, szTemp2, &one, sizeof(one),
1668 curve25519_modbin, sizeof(curve25519_modbin), temp2, &szTemp2,
1669 kLTC_PKHA_IntegerArith);
1670 }
1671
1672 /* Mx = ModInv(temp2,prime) */
1673 if (status == kStatus_Success) {
1674 status = LTC_PKHA_ModInv(LTC_BASE, temp2, szTemp2, curve25519_modbin,
1675 sizeof(curve25519_modbin), Mx, &szMx, kLTC_PKHA_IntegerArith);
1676 }
1677
1678 /* Mx = Mx * temp */
1679 if (status == kStatus_Success) {
1680 status = LTC_PKHA_ModMul(LTC_BASE, Mx, szMx, temp, szTemp,
1681 curve25519_modbin, ED25519_KEY_SIZE, Mx, &szMx,
1682 kLTC_PKHA_IntegerArith, kLTC_PKHA_NormalValue,
1683 kLTC_PKHA_NormalValue, kLTC_PKHA_TimingEqualized);
1684 }
1685
1686 /* My = temp2 * Ex */
1687 if (status == kStatus_Success) {
1688 status = LTC_PKHA_ModMul(LTC_BASE, Ex, ED25519_KEY_SIZE, temp2,
1689 szTemp2, curve25519_modbin, ED25519_KEY_SIZE, My, &szMy,
1690 kLTC_PKHA_IntegerArith, kLTC_PKHA_NormalValue,
1691 kLTC_PKHA_NormalValue, kLTC_PKHA_TimingEqualized);
1692 }
1693
1694 /* My = ModInv(My, prime) */
1695 if (status == kStatus_Success) {
1696 status = LTC_PKHA_ModInv(LTC_BASE, My, szMy, curve25519_modbin,
1697 sizeof(curve25519_modbin), My, &szMy, kLTC_PKHA_IntegerArith);
1698 }
1699 /* My = My * temp */
1700 if (status == kStatus_Success) {
1701 status = LTC_PKHA_ModMul(LTC_BASE, My, szMy, temp, szTemp,
1702 curve25519_modbin, ED25519_KEY_SIZE, My, &szMy,
1703 kLTC_PKHA_IntegerArith, kLTC_PKHA_NormalValue,
1704 kLTC_PKHA_NormalValue, kLTC_PKHA_TimingEqualized);
1705 }
1706
1707 /* Gx = Mx * invB_coefEd25519 + A_mul_invThreeB_coefEd25519 */
1708 if (status == kStatus_Success) {
1709 status = LTC_PKHA_ModMul(LTC_BASE, Mx, szMx, invB_coefEd25519,
1710 sizeof(invB_coefEd25519), curve25519_modbin, ED25519_KEY_SIZE, Gx,
1711 &szGx, kLTC_PKHA_IntegerArith, kLTC_PKHA_NormalValue,
1712 kLTC_PKHA_NormalValue, kLTC_PKHA_TimingEqualized);
1713 }
1714 if (status == kStatus_Success) {
1715 status = LTC_PKHA_ModAdd(LTC_BASE, Gx, szGx,
1716 A_mul_invThreeB_coefEd25519, sizeof(A_mul_invThreeB_coefEd25519),
1717 curve25519_modbin, sizeof(curve25519_modbin), Gx, &szGx,
1718 kLTC_PKHA_IntegerArith);
1719 }
1720
1721 /* Gy = My * invB_coefEd25519 */
1722 if (status == kStatus_Success) {
1723 status = LTC_PKHA_ModMul(LTC_BASE, My, szMy, invB_coefEd25519,
1724 sizeof(invB_coefEd25519), curve25519_modbin, ED25519_KEY_SIZE, Gy,
1725 &szGy, kLTC_PKHA_IntegerArith, kLTC_PKHA_NormalValue,
1726 kLTC_PKHA_NormalValue, kLTC_PKHA_TimingEqualized);
1727 }
1728
1729 return status;
1730 }
1731
1732 /*
1733 # (Gx, Gy) on W to (Ex, Ey) on E
1734 My = (B*Gy) % prime
1735 Mx = ((3*B*Gx-A)*ModularArithmetic.invert(3, prime)) % prime
1736 Ex = Mx*ModularArithmetic.invert(My, prime) % prime
1737 Ey = (Mx - 1)*ModularArithmetic.invert(Mx + 1, prime) % prime
1738 */
LTC_PKHA_WeierstrassToEd25519(const ltc_pkha_ecc_point_t * ltcPointIn,ltc_pkha_ecc_point_t * ltcPointOut)1739 status_t LTC_PKHA_WeierstrassToEd25519(const ltc_pkha_ecc_point_t *ltcPointIn,
1740 ltc_pkha_ecc_point_t *ltcPointOut)
1741 {
1742 status_t status;
1743 uint8_t Mx[ED25519_KEY_SIZE] = {0};
1744 uint8_t My[ED25519_KEY_SIZE] = {0};
1745 uint8_t temp[ED25519_KEY_SIZE] = {0};
1746 const uint8_t *Gx;
1747 const uint8_t *Gy;
1748 uint8_t *Ex;
1749 uint8_t *Ey;
1750 uint16_t szMx = 0;
1751 uint16_t szEx = 0;
1752 uint16_t szMy = 0;
1753 uint16_t szEy = 0;
1754 uint16_t szTemp = 0;
1755 uint8_t one = 1;
1756
1757 Gx = ltcPointIn->X;
1758 Gy = ltcPointIn->Y;
1759 Ex = ltcPointOut->X;
1760 Ey = ltcPointOut->Y;
1761
1762 /* My = (B*Gy) % prime */
1763 status = LTC_PKHA_ModMul(LTC_BASE, B_coefEd25519, sizeof(B_coefEd25519),
1764 Gy, ED25519_KEY_SIZE, curve25519_modbin, ED25519_KEY_SIZE, My, &szMy,
1765 kLTC_PKHA_IntegerArith, kLTC_PKHA_NormalValue, kLTC_PKHA_NormalValue,
1766 kLTC_PKHA_TimingEqualized);
1767
1768 /* temp = 3*B*Gx mod p */
1769 if (status == kStatus_Success) {
1770 status = LTC_PKHA_ModMul(LTC_BASE, threeB_coefEd25519,
1771 sizeof(threeB_coefEd25519), Gx, ED25519_KEY_SIZE, curve25519_modbin,
1772 ED25519_KEY_SIZE, temp, &szTemp, kLTC_PKHA_IntegerArith,
1773 kLTC_PKHA_NormalValue, kLTC_PKHA_NormalValue,
1774 kLTC_PKHA_TimingEqualized);
1775 }
1776 /* temp = (temp - A) mod p */
1777 if (status == kStatus_Success) {
1778 status = LTC_PKHA_ModAdd(LTC_BASE, temp, szTemp, minus_A_coefEd25519,
1779 sizeof(minus_A_coefEd25519), curve25519_modbin,
1780 sizeof(curve25519_modbin), temp, &szTemp, kLTC_PKHA_IntegerArith);
1781 }
1782 /* Mx = (temp/3) mod p */
1783 if (status == kStatus_Success) {
1784 status = LTC_PKHA_ModMul(LTC_BASE, temp, szTemp, invThree,
1785 sizeof(invThree), curve25519_modbin, sizeof(curve25519_modbin), Mx,
1786 &szMx, kLTC_PKHA_IntegerArith, kLTC_PKHA_NormalValue,
1787 kLTC_PKHA_NormalValue, kLTC_PKHA_TimingEqualized);
1788 }
1789 /* temp = 1/My mod p */
1790 if (status == kStatus_Success) {
1791 status = LTC_PKHA_ModInv(LTC_BASE, My, szMy, curve25519_modbin,
1792 sizeof(curve25519_modbin), temp, &szTemp, kLTC_PKHA_IntegerArith);
1793 }
1794 /* Ex = Mx * temp mod p */
1795 if (status == kStatus_Success) {
1796 status = LTC_PKHA_ModMul(LTC_BASE, temp, szTemp, Mx, szMx,
1797 curve25519_modbin, sizeof(curve25519_modbin), Ex, &szEx,
1798 kLTC_PKHA_IntegerArith, kLTC_PKHA_NormalValue,
1799 kLTC_PKHA_NormalValue, kLTC_PKHA_TimingEqualized);
1800 }
1801
1802 /* temp = Mx + 1 mod p */
1803 if (status == kStatus_Success) {
1804 status = LTC_PKHA_ModAdd(LTC_BASE, Mx, szMx, &one, sizeof(one),
1805 curve25519_modbin, sizeof(curve25519_modbin), temp, &szTemp,
1806 kLTC_PKHA_IntegerArith);
1807 }
1808 /* temp = 1/temp mod p */
1809 if (status == kStatus_Success) {
1810 status = LTC_PKHA_ModInv(LTC_BASE, temp, szTemp, curve25519_modbin,
1811 sizeof(curve25519_modbin), temp, &szTemp, kLTC_PKHA_IntegerArith);
1812 }
1813 /* Mx = (Mx - 1) mod p */
1814 if (status == kStatus_Success) {
1815 if (LTC_PKHA_CompareBigNum(Mx, szMx, &one, sizeof(one)) >= 0) {
1816 status = LTC_PKHA_ModSub1(LTC_BASE, Mx, szMx, &one, sizeof(one),
1817 curve25519_modbin, sizeof(curve25519_modbin), Mx, &szMx);
1818 }
1819 else {
1820 /* Mx is zero, so it is modulus, thus we do modulus - 1 */
1821 XMEMCPY(Mx, curve25519_modbin, sizeof(curve25519_modbin));
1822 Mx[0]--;
1823 }
1824 }
1825 /* Ey = Mx * temp mod p */
1826 if (status == kStatus_Success) {
1827 status = LTC_PKHA_ModMul(LTC_BASE, temp, szTemp, Mx, szMx,
1828 curve25519_modbin, sizeof(curve25519_modbin), Ey, &szEy,
1829 kLTC_PKHA_IntegerArith, kLTC_PKHA_NormalValue,
1830 kLTC_PKHA_NormalValue, kLTC_PKHA_TimingEqualized);
1831 }
1832
1833 return status;
1834 }
1835
LTC_PKHA_Ed25519_PointDecompress(const uint8_t * pubkey,size_t pubKeySize,ltc_pkha_ecc_point_t * ltcPointOut)1836 status_t LTC_PKHA_Ed25519_PointDecompress(const uint8_t *pubkey,
1837 size_t pubKeySize, ltc_pkha_ecc_point_t *ltcPointOut)
1838 {
1839 status_t status;
1840 const uint8_t one = 1;
1841
1842 /* pubkey contains the Y coordinate and a sign of X
1843 */
1844
1845 /* x^2 = ((y^2 - 1) / (d*y^2 +1)) mod p */
1846
1847 /* decode Y from pubkey */
1848 XMEMCPY(ltcPointOut->Y, pubkey, pubKeySize);
1849 ltcPointOut->Y[pubKeySize - 1] &= ~0x80u;
1850 int sign = (int)(bool)(pubkey[pubKeySize - 1] & 0x80u);
1851
1852 uint8_t U[ED25519_KEY_SIZE] = {0};
1853 uint8_t V[ED25519_KEY_SIZE] = {0};
1854 uint8_t *X = ltcPointOut->X;
1855 uint8_t *Y = ltcPointOut->Y;
1856 uint16_t szU = 0;
1857 uint16_t szV = 0;
1858 size_t szRes = 0;
1859
1860 /* decode X from pubkey */
1861
1862 /* U = y * y mod p */
1863 status = LTC_PKHA_ModMul(LTC_BASE, Y, ED25519_KEY_SIZE, Y,
1864 ED25519_KEY_SIZE, curve25519_modbin, ED25519_KEY_SIZE, U, &szU,
1865 kLTC_PKHA_IntegerArith, kLTC_PKHA_NormalValue, kLTC_PKHA_NormalValue,
1866 kLTC_PKHA_TimingEqualized);
1867 XMEMCPY(V, U, szU);
1868 szV = szU;
1869
1870 /* U = U - 1 = y^2 - 1 */
1871 if (status == kStatus_Success) {
1872 if (LTC_PKHA_CompareBigNum(U, szU, &one, sizeof(one)) >= 0) {
1873 status = LTC_PKHA_ModSub1(LTC_BASE, U, szU, &one, sizeof(one),
1874 curve25519_modbin, sizeof(curve25519_modbin), U, &szU);
1875 }
1876 else {
1877 /* U is zero, so it is modulus, thus we do modulus - 1 */
1878 XMEMCPY(U, curve25519_modbin, sizeof(curve25519_modbin));
1879 U[0]--;
1880 }
1881 }
1882
1883 /* V = d*y*y + 1 */
1884 if (status == kStatus_Success) {
1885 status = LTC_PKHA_ModMul(LTC_BASE, V, szV, d_coefEd25519,
1886 ED25519_KEY_SIZE, curve25519_modbin, ED25519_KEY_SIZE, V, &szV,
1887 kLTC_PKHA_IntegerArith, kLTC_PKHA_NormalValue,
1888 kLTC_PKHA_NormalValue, kLTC_PKHA_TimingEqualized);
1889 }
1890
1891 if (status == kStatus_Success) {
1892 status = LTC_PKHA_ModAdd(LTC_BASE, V, szV, &one, sizeof(one),
1893 curve25519_modbin, sizeof(curve25519_modbin), V, &szV,
1894 kLTC_PKHA_IntegerArith);
1895 }
1896
1897 /* U = U / V (mod p) */
1898 if (status == kStatus_Success) {
1899 status = LTC_PKHA_ModInv(LTC_BASE, V, szV, curve25519_modbin,
1900 sizeof(curve25519_modbin), V, &szV, kLTC_PKHA_IntegerArith);
1901 }
1902 if (status == kStatus_Success) {
1903 status = LTC_PKHA_ModMul(LTC_BASE, V, szV, U, szU, curve25519_modbin,
1904 ED25519_KEY_SIZE, U, &szU, kLTC_PKHA_IntegerArith,
1905 kLTC_PKHA_NormalValue, kLTC_PKHA_NormalValue,
1906 kLTC_PKHA_TimingEqualized);
1907 }
1908
1909 /* get square root */
1910 if (status == kStatus_Success) {
1911 status = LTC_PKHA_Prime25519SquareRootMod(U, szU, X, &szRes, sign);
1912 }
1913
1914 return status;
1915 }
1916
1917 /* LSByte first of Ed25519 parameter l = 2^252 +
1918 * 27742317777372353535851937790883648493 */
1919 static const uint8_t l_coefEdDSA[] = {
1920 0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, 0xd6, 0x9c, 0xf7,
1921 0xa2, 0xde, 0xf9, 0xde, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1922 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10};
1923
1924 /*
1925 Input:
1926 s[0]+256*s[1]+...+256^63*s[63] = s
1927
1928 Output:
1929 s[0]+256*s[1]+...+256^31*s[31] = s mod l
1930 where l = 2^252 + 27742317777372353535851937790883648493.
1931 Overwrites s in place.
1932 */
LTC_PKHA_sc_reduce(uint8_t * a)1933 status_t LTC_PKHA_sc_reduce(uint8_t *a)
1934 {
1935 uint16_t szA = 0;
1936 return LTC_PKHA_ModRed(LTC_BASE, a, 64, l_coefEdDSA, sizeof(l_coefEdDSA),
1937 a, &szA, kLTC_PKHA_IntegerArith);
1938 }
1939
1940 /*
1941 Input:
1942 a[0]+256*a[1]+...+256^31*a[31] = a
1943 b[0]+256*b[1]+...+256^31*b[31] = b
1944 c[0]+256*c[1]+...+256^31*c[31] = c
1945
1946 Output:
1947 s[0]+256*s[1]+...+256^31*s[31] = (ab+c) mod l
1948 where l = 2^252 + 27742317777372353535851937790883648493.
1949 */
LTC_PKHA_sc_muladd(uint8_t * s,const uint8_t * a,const uint8_t * b,const uint8_t * c)1950 status_t LTC_PKHA_sc_muladd(uint8_t *s, const uint8_t *a,
1951 const uint8_t *b, const uint8_t *c)
1952 {
1953 uint16_t szS = 0;
1954 uint16_t szB = 0;
1955 uint8_t tempB[32] = {0};
1956 status_t status;
1957
1958 /* Assume only b can be larger than modulus. It is called durind
1959 * wc_ed25519_sign_msg() where hram (=a) and nonce(=c)
1960 * have been reduced by LTC_PKHA_sc_reduce()
1961 * Thus reducing b only.
1962 */
1963 status = LTC_PKHA_ModRed(LTC_BASE, b, 32, l_coefEdDSA, sizeof(l_coefEdDSA),
1964 tempB, &szB, kLTC_PKHA_IntegerArith);
1965
1966 if (status == kStatus_Success) {
1967 status = LTC_PKHA_ModMul(LTC_BASE, a, 32, tempB, szB, l_coefEdDSA,
1968 sizeof(l_coefEdDSA), s, &szS, kLTC_PKHA_IntegerArith,
1969 kLTC_PKHA_NormalValue, kLTC_PKHA_NormalValue,
1970 kLTC_PKHA_TimingEqualized);
1971 }
1972
1973 if (status == kStatus_Success) {
1974 status = LTC_PKHA_ModAdd(LTC_BASE, s, szS, c, 32, l_coefEdDSA, 32, s,
1975 &szS, kLTC_PKHA_IntegerArith);
1976 }
1977
1978 return status;
1979 }
1980
1981 /*
1982 r = a * A + b * B
1983 where A is public key point, B is basepoint
1984 where a = a[0]+256*a[1]+...+256^31 a[31].
1985 and b = b[0]+256*b[1]+...+256^31 b[31].
1986 B is the Ed25519 base point (x,4/5) with x positive.
1987 */
LTC_PKHA_SignatureForVerify(uint8_t * rcheck,const unsigned char * a,const unsigned char * b,ed25519_key * key)1988 status_t LTC_PKHA_SignatureForVerify(uint8_t *rcheck, const unsigned char *a,
1989 const unsigned char *b, ed25519_key *key)
1990 {
1991 /* To verify a signature on a message M, first split the signature
1992 into two 32-octet halves. Decode the first half as a point R,
1993 and the second half as an integer s, in the range 0 <= s < q. If
1994 the decoding fails, the signature is invalid. */
1995
1996 /* Check the group equation 8s B = 8 R + 8k A. */
1997
1998 /*
1999 Uses a fast single-signature verification SB = R + H(R,A,M)A becomes
2000 SB - H(R,A,M)A saving decompression of R
2001 */
2002 uint8_t X0[ED25519_PUB_KEY_SIZE] = {0};
2003 uint8_t X1[ED25519_PUB_KEY_SIZE] = {0};
2004 uint8_t Y0[ED25519_PUB_KEY_SIZE] = {0};
2005 uint8_t Y1[ED25519_PUB_KEY_SIZE] = {0};
2006 const uint8_t max[32] = {
2007 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2008 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2009 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
2010 ltc_pkha_ecc_point_t ltc0;
2011 ltc_pkha_ecc_point_t ltc1;
2012 ltc_pkha_ecc_point_t pubKey;
2013 status_t status;
2014
2015 /* The equality for the negative of a point P, in affine coordinates,
2016 is -P = -(x,y) = (x, -y) */
2017 uint16_t szY = 32;
2018
2019 ltc0.X = X0;
2020 ltc1.X = X1;
2021 ltc0.Y = Y0;
2022 ltc1.Y = Y1;
2023 pubKey.X = key->pointX;
2024 pubKey.Y = key->pointY;
2025
2026 /* ltc0 = b*B */
2027 status = LTC_PKHA_Ed25519_PointMul(LTC_PKHA_Ed25519_BasePoint(), b,
2028 ED25519_KEY_SIZE, <c0, kLTC_Weierstrass /* result in W */);
2029
2030 /* ltc1 = a*A */
2031 if (status == kStatus_Success) {
2032 status = LTC_PKHA_Ed25519ToWeierstrass(&pubKey, <c1);
2033 }
2034 if (status == kStatus_Success) {
2035 status = LTC_PKHA_Ed25519_PointMul(<c1, a, ED25519_KEY_SIZE, <c1,
2036 kLTC_Weierstrass /* result in W */);
2037 }
2038
2039 /* R = b*B - a*A */
2040 if (status == kStatus_Success) {
2041 status = LTC_PKHA_ModSub1(LTC_BASE, curve25519_modbin,
2042 sizeof(curve25519_modbin), ltc1.Y, szY, max, sizeof(max), ltc1.Y,
2043 &szY);
2044 }
2045 if (status == kStatus_Success) {
2046 status = LTC_PKHA_ECC_PointAdd(LTC_BASE, <c0, <c1,
2047 curve25519_modbin, r2mod, a_coefEd25519, b_coefEd25519,
2048 ED25519_KEY_SIZE, kLTC_PKHA_IntegerArith, <c0);
2049 }
2050 /* map to Ed25519 */
2051 if (status == kStatus_Success) {
2052 status = LTC_PKHA_WeierstrassToEd25519(<c0, <c0);
2053 }
2054 if (((uint32_t)ltc0.X[0]) & 0x01u) {
2055 ltc0.Y[ED25519_KEY_SIZE - 1] |= 0x80u;
2056 }
2057
2058 XMEMCPY(rcheck, ltc0.Y, ED25519_KEY_SIZE);
2059 return status;
2060 }
2061
LTC_PKHA_Ed25519_Compress(const ltc_pkha_ecc_point_t * ltcPointIn,uint8_t * p)2062 status_t LTC_PKHA_Ed25519_Compress(const ltc_pkha_ecc_point_t *ltcPointIn,
2063 uint8_t *p)
2064 {
2065 /* compress */
2066 /* get sign of X per https://tools.ietf.org/html/draft-josefsson-eddsa-ed25519-02
2067 * To form the encoding of the point, copy the least
2068 significant bit of the x-coordinate to the most significant bit of
2069 the final octet
2070 */
2071 XMEMCPY(p, ltcPointIn->Y, ED25519_KEY_SIZE);
2072 if (((uint32_t)ltcPointIn->X[0]) & 0x01u) {
2073 p[ED25519_KEY_SIZE - 1] |= 0x80u;
2074 }
2075 return kStatus_Success;
2076 }
2077
2078 #endif /* HAVE_ED25519 */
2079 #endif /* FREESCALE_LTC_ECC */
2080
2081
2082 #undef ERROR_OUT
2083
2084 #endif /* FREESCALE_LTC_TFM || FREESCALE_LTC_ECC */
2085