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(&ltcPoint, &ltcPoint);
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, &ltcPoint, n, CURVE25519_KEYSIZE,
1499         curve25519_modbin, r2mod, curve25519_aCurveParam,
1500         curve25519_bCurveParam, CURVE25519_KEYSIZE, kLTC_PKHA_TimingEqualized,
1501         kLTC_PKHA_IntegerArith, &ltcPointOut, NULL);
1502 
1503     /* now need to map from Weierstrass form to Montgomery form */
1504     if (status == kStatus_Success) {
1505         status = LTC_PKHA_WeierstrassToCurve25519(&ltcPointOut, &ltcPointOut);
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, &ltc0, kLTC_Weierstrass /* result in W */);
2029 
2030     /* ltc1 = a*A */
2031     if (status == kStatus_Success) {
2032         status = LTC_PKHA_Ed25519ToWeierstrass(&pubKey, &ltc1);
2033     }
2034     if (status == kStatus_Success) {
2035         status = LTC_PKHA_Ed25519_PointMul(&ltc1, a, ED25519_KEY_SIZE, &ltc1,
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, &ltc0, &ltc1,
2047             curve25519_modbin, r2mod, a_coefEd25519, b_coefEd25519,
2048             ED25519_KEY_SIZE, kLTC_PKHA_IntegerArith, &ltc0);
2049     }
2050     /* map to Ed25519 */
2051     if (status == kStatus_Success) {
2052         status = LTC_PKHA_WeierstrassToEd25519(&ltc0, &ltc0);
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