1 // SPDX-License-Identifier: BSD-2-Clause
2 /* LibTomCrypt, modular cryptographic library -- Tom St Denis
3 *
4 * LibTomCrypt is a library that provides various cryptographic
5 * algorithms in a highly modular and flexible manner.
6 *
7 * The library is free for all purposes without any express
8 * guarantee it works.
9 */
10
11 #define DESC_DEF_ONLY
12 #include "tomcrypt_private.h"
13
14 #ifdef TFM_DESC
15
16 #include <tfm.h>
17
18 static const struct {
19 int tfm_code, ltc_code;
20 } tfm_to_ltc_codes[] = {
21 { FP_OKAY , CRYPT_OK},
22 { FP_MEM , CRYPT_MEM},
23 { FP_VAL , CRYPT_INVALID_ARG},
24 };
25
26 /**
27 Convert a tfm error to a LTC error (Possibly the most powerful function ever! Oh wait... no)
28 @param err The error to convert
29 @return The equivalent LTC error code or CRYPT_ERROR if none found
30 */
tfm_to_ltc_error(int err)31 static int tfm_to_ltc_error(int err)
32 {
33 int x;
34
35 for (x = 0; x < (int)(sizeof(tfm_to_ltc_codes)/sizeof(tfm_to_ltc_codes[0])); x++) {
36 if (err == tfm_to_ltc_codes[x].tfm_code) {
37 return tfm_to_ltc_codes[x].ltc_code;
38 }
39 }
40 return CRYPT_ERROR;
41 }
42
init(void ** a)43 static int init(void **a)
44 {
45 LTC_ARGCHK(a != NULL);
46
47 *a = XCALLOC(1, sizeof(fp_int));
48 if (*a == NULL) {
49 return CRYPT_MEM;
50 }
51 fp_init(*a);
52 return CRYPT_OK;
53 }
54
deinit(void * a)55 static void deinit(void *a)
56 {
57 LTC_ARGCHKVD(a != NULL);
58 XFREE(a);
59 }
60
neg(void * a,void * b)61 static int neg(void *a, void *b)
62 {
63 LTC_ARGCHK(a != NULL);
64 LTC_ARGCHK(b != NULL);
65 fp_neg(((fp_int*)a), ((fp_int*)b));
66 return CRYPT_OK;
67 }
68
copy(void * a,void * b)69 static int copy(void *a, void *b)
70 {
71 LTC_ARGCHK(a != NULL);
72 LTC_ARGCHK(b != NULL);
73 fp_copy(a, b);
74 return CRYPT_OK;
75 }
76
init_copy(void ** a,void * b)77 static int init_copy(void **a, void *b)
78 {
79 if (init(a) != CRYPT_OK) {
80 return CRYPT_MEM;
81 }
82 return copy(b, *a);
83 }
84
85 /* ---- trivial ---- */
set_int(void * a,ltc_mp_digit b)86 static int set_int(void *a, ltc_mp_digit b)
87 {
88 LTC_ARGCHK(a != NULL);
89 fp_set(a, b);
90 return CRYPT_OK;
91 }
92
get_int(void * a)93 static unsigned long get_int(void *a)
94 {
95 fp_int *A;
96 LTC_ARGCHK(a != NULL);
97 A = a;
98 return A->used > 0 ? A->dp[0] : 0;
99 }
100
get_digit(void * a,int n)101 static ltc_mp_digit get_digit(void *a, int n)
102 {
103 fp_int *A;
104 LTC_ARGCHK(a != NULL);
105 A = a;
106 return (n >= A->used || n < 0) ? 0 : A->dp[n];
107 }
108
get_digit_count(void * a)109 static int get_digit_count(void *a)
110 {
111 fp_int *A;
112 LTC_ARGCHK(a != NULL);
113 A = a;
114 return A->used;
115 }
116
compare(void * a,void * b)117 static int compare(void *a, void *b)
118 {
119 int ret;
120 LTC_ARGCHK(a != NULL);
121 LTC_ARGCHK(b != NULL);
122 ret = fp_cmp(a, b);
123 switch (ret) {
124 case FP_LT: return LTC_MP_LT;
125 case FP_EQ: return LTC_MP_EQ;
126 case FP_GT: return LTC_MP_GT;
127 }
128 return 0;
129 }
130
compare_d(void * a,ltc_mp_digit b)131 static int compare_d(void *a, ltc_mp_digit b)
132 {
133 int ret;
134 LTC_ARGCHK(a != NULL);
135 ret = fp_cmp_d(a, b);
136 switch (ret) {
137 case FP_LT: return LTC_MP_LT;
138 case FP_EQ: return LTC_MP_EQ;
139 case FP_GT: return LTC_MP_GT;
140 }
141 return 0;
142 }
143
count_bits(void * a)144 static int count_bits(void *a)
145 {
146 LTC_ARGCHK(a != NULL);
147 return fp_count_bits(a);
148 }
149
count_lsb_bits(void * a)150 static int count_lsb_bits(void *a)
151 {
152 LTC_ARGCHK(a != NULL);
153 return fp_cnt_lsb(a);
154 }
155
twoexpt(void * a,int n)156 static int twoexpt(void *a, int n)
157 {
158 LTC_ARGCHK(a != NULL);
159 fp_2expt(a, n);
160 return CRYPT_OK;
161 }
162
163 /* ---- conversions ---- */
164
165 /* read ascii string */
read_radix(void * a,const char * b,int radix)166 static int read_radix(void *a, const char *b, int radix)
167 {
168 LTC_ARGCHK(a != NULL);
169 LTC_ARGCHK(b != NULL);
170 return tfm_to_ltc_error(fp_read_radix(a, (char *)b, radix));
171 }
172
173 /* write one */
write_radix(void * a,char * b,int radix)174 static int write_radix(void *a, char *b, int radix)
175 {
176 LTC_ARGCHK(a != NULL);
177 LTC_ARGCHK(b != NULL);
178 return tfm_to_ltc_error(fp_toradix(a, b, radix));
179 }
180
181 /* get size as unsigned char string */
unsigned_size(void * a)182 static unsigned long unsigned_size(void *a)
183 {
184 LTC_ARGCHK(a != NULL);
185 return fp_unsigned_bin_size(a);
186 }
187
188 /* store */
unsigned_write(void * a,unsigned char * b)189 static int unsigned_write(void *a, unsigned char *b)
190 {
191 LTC_ARGCHK(a != NULL);
192 LTC_ARGCHK(b != NULL);
193 fp_to_unsigned_bin(a, b);
194 return CRYPT_OK;
195 }
196
197 /* read */
unsigned_read(void * a,unsigned char * b,unsigned long len)198 static int unsigned_read(void *a, unsigned char *b, unsigned long len)
199 {
200 LTC_ARGCHK(a != NULL);
201 LTC_ARGCHK(b != NULL);
202 fp_read_unsigned_bin(a, b, len);
203 return CRYPT_OK;
204 }
205
206 /* add */
add(void * a,void * b,void * c)207 static int add(void *a, void *b, void *c)
208 {
209 LTC_ARGCHK(a != NULL);
210 LTC_ARGCHK(b != NULL);
211 LTC_ARGCHK(c != NULL);
212 fp_add(a, b, c);
213 return CRYPT_OK;
214 }
215
addi(void * a,ltc_mp_digit b,void * c)216 static int addi(void *a, ltc_mp_digit b, void *c)
217 {
218 LTC_ARGCHK(a != NULL);
219 LTC_ARGCHK(c != NULL);
220 fp_add_d(a, b, c);
221 return CRYPT_OK;
222 }
223
224 /* sub */
sub(void * a,void * b,void * c)225 static int sub(void *a, void *b, void *c)
226 {
227 LTC_ARGCHK(a != NULL);
228 LTC_ARGCHK(b != NULL);
229 LTC_ARGCHK(c != NULL);
230 fp_sub(a, b, c);
231 return CRYPT_OK;
232 }
233
subi(void * a,ltc_mp_digit b,void * c)234 static int subi(void *a, ltc_mp_digit b, void *c)
235 {
236 LTC_ARGCHK(a != NULL);
237 LTC_ARGCHK(c != NULL);
238 fp_sub_d(a, b, c);
239 return CRYPT_OK;
240 }
241
242 /* mul */
mul(void * a,void * b,void * c)243 static int mul(void *a, void *b, void *c)
244 {
245 LTC_ARGCHK(a != NULL);
246 LTC_ARGCHK(b != NULL);
247 LTC_ARGCHK(c != NULL);
248 fp_mul(a, b, c);
249 return CRYPT_OK;
250 }
251
muli(void * a,ltc_mp_digit b,void * c)252 static int muli(void *a, ltc_mp_digit b, void *c)
253 {
254 LTC_ARGCHK(a != NULL);
255 LTC_ARGCHK(c != NULL);
256 fp_mul_d(a, b, c);
257 return CRYPT_OK;
258 }
259
260 /* sqr */
sqr(void * a,void * b)261 static int sqr(void *a, void *b)
262 {
263 LTC_ARGCHK(a != NULL);
264 LTC_ARGCHK(b != NULL);
265 fp_sqr(a, b);
266 return CRYPT_OK;
267 }
268
269 /* sqrtmod_prime - NOT SUPPORTED */
270
271 /* div */
divide(void * a,void * b,void * c,void * d)272 static int divide(void *a, void *b, void *c, void *d)
273 {
274 LTC_ARGCHK(a != NULL);
275 LTC_ARGCHK(b != NULL);
276 return tfm_to_ltc_error(fp_div(a, b, c, d));
277 }
278
div_2(void * a,void * b)279 static int div_2(void *a, void *b)
280 {
281 LTC_ARGCHK(a != NULL);
282 LTC_ARGCHK(b != NULL);
283 fp_div_2(a, b);
284 return CRYPT_OK;
285 }
286
287 /* modi */
modi(void * a,ltc_mp_digit b,ltc_mp_digit * c)288 static int modi(void *a, ltc_mp_digit b, ltc_mp_digit *c)
289 {
290 fp_digit tmp;
291 int err;
292
293 LTC_ARGCHK(a != NULL);
294 LTC_ARGCHK(c != NULL);
295
296 if ((err = tfm_to_ltc_error(fp_mod_d(a, b, &tmp))) != CRYPT_OK) {
297 return err;
298 }
299 *c = tmp;
300 return CRYPT_OK;
301 }
302
303 /* gcd */
gcd(void * a,void * b,void * c)304 static int gcd(void *a, void *b, void *c)
305 {
306 LTC_ARGCHK(a != NULL);
307 LTC_ARGCHK(b != NULL);
308 LTC_ARGCHK(c != NULL);
309 fp_gcd(a, b, c);
310 return CRYPT_OK;
311 }
312
313 /* lcm */
lcm(void * a,void * b,void * c)314 static int lcm(void *a, void *b, void *c)
315 {
316 LTC_ARGCHK(a != NULL);
317 LTC_ARGCHK(b != NULL);
318 LTC_ARGCHK(c != NULL);
319 fp_lcm(a, b, c);
320 return CRYPT_OK;
321 }
322
addmod(void * a,void * b,void * c,void * d)323 static int addmod(void *a, void *b, void *c, void *d)
324 {
325 LTC_ARGCHK(a != NULL);
326 LTC_ARGCHK(b != NULL);
327 LTC_ARGCHK(c != NULL);
328 LTC_ARGCHK(d != NULL);
329 return tfm_to_ltc_error(fp_addmod(a,b,c,d));
330 }
331
submod(void * a,void * b,void * c,void * d)332 static int submod(void *a, void *b, void *c, void *d)
333 {
334 LTC_ARGCHK(a != NULL);
335 LTC_ARGCHK(b != NULL);
336 LTC_ARGCHK(c != NULL);
337 LTC_ARGCHK(d != NULL);
338 return tfm_to_ltc_error(fp_submod(a,b,c,d));
339 }
340
mulmod(void * a,void * b,void * c,void * d)341 static int mulmod(void *a, void *b, void *c, void *d)
342 {
343 LTC_ARGCHK(a != NULL);
344 LTC_ARGCHK(b != NULL);
345 LTC_ARGCHK(c != NULL);
346 LTC_ARGCHK(d != NULL);
347 return tfm_to_ltc_error(fp_mulmod(a,b,c,d));
348 }
349
sqrmod(void * a,void * b,void * c)350 static int sqrmod(void *a, void *b, void *c)
351 {
352 LTC_ARGCHK(a != NULL);
353 LTC_ARGCHK(b != NULL);
354 LTC_ARGCHK(c != NULL);
355 return tfm_to_ltc_error(fp_sqrmod(a,b,c));
356 }
357
358 /* invmod */
invmod(void * a,void * b,void * c)359 static int invmod(void *a, void *b, void *c)
360 {
361 LTC_ARGCHK(a != NULL);
362 LTC_ARGCHK(b != NULL);
363 LTC_ARGCHK(c != NULL);
364 return tfm_to_ltc_error(fp_invmod(a, b, c));
365 }
366
367 /* setup */
montgomery_setup(void * a,void ** b)368 static int montgomery_setup(void *a, void **b)
369 {
370 int err;
371 LTC_ARGCHK(a != NULL);
372 LTC_ARGCHK(b != NULL);
373 *b = XCALLOC(1, sizeof(fp_digit));
374 if (*b == NULL) {
375 return CRYPT_MEM;
376 }
377 if ((err = tfm_to_ltc_error(fp_montgomery_setup(a, (fp_digit *)*b))) != CRYPT_OK) {
378 XFREE(*b);
379 }
380 return err;
381 }
382
383 /* get normalization value */
montgomery_normalization(void * a,void * b)384 static int montgomery_normalization(void *a, void *b)
385 {
386 LTC_ARGCHK(a != NULL);
387 LTC_ARGCHK(b != NULL);
388 fp_montgomery_calc_normalization(a, b);
389 return CRYPT_OK;
390 }
391
392 /* reduce */
montgomery_reduce(void * a,void * b,void * c)393 static int montgomery_reduce(void *a, void *b, void *c)
394 {
395 LTC_ARGCHK(a != NULL);
396 LTC_ARGCHK(b != NULL);
397 LTC_ARGCHK(c != NULL);
398 fp_montgomery_reduce(a, b, *((fp_digit *)c));
399 return CRYPT_OK;
400 }
401
402 /* clean up */
montgomery_deinit(void * a)403 static void montgomery_deinit(void *a)
404 {
405 XFREE(a);
406 }
407
exptmod(void * a,void * b,void * c,void * d)408 static int exptmod(void *a, void *b, void *c, void *d)
409 {
410 LTC_ARGCHK(a != NULL);
411 LTC_ARGCHK(b != NULL);
412 LTC_ARGCHK(c != NULL);
413 LTC_ARGCHK(d != NULL);
414 return tfm_to_ltc_error(fp_exptmod(a,b,c,d));
415 }
416
isprime(void * a,int b,int * c)417 static int isprime(void *a, int b, int *c)
418 {
419 LTC_ARGCHK(a != NULL);
420 LTC_ARGCHK(c != NULL);
421 if (b == 0) {
422 b = LTC_MILLER_RABIN_REPS;
423 } /* if */
424 *c = (fp_isprime_ex(a, b) == FP_YES) ? LTC_MP_YES : LTC_MP_NO;
425 return CRYPT_OK;
426 }
427
428 #if defined(LTC_MECC) && defined(LTC_MECC_ACCEL)
429
tfm_ecc_projective_dbl_point(const ecc_point * P,ecc_point * R,void * ma,void * modulus,void * Mp)430 static int tfm_ecc_projective_dbl_point(const ecc_point *P, ecc_point *R, void *ma, void *modulus, void *Mp)
431 {
432 fp_int t1, t2;
433 fp_digit mp;
434 int err, inf;
435
436 LTC_ARGCHK(P != NULL);
437 LTC_ARGCHK(R != NULL);
438 LTC_ARGCHK(modulus != NULL);
439 LTC_ARGCHK(Mp != NULL);
440
441 mp = *((fp_digit*)Mp);
442
443 fp_init(&t1);
444 fp_init(&t2);
445
446 if (P != R) {
447 fp_copy(P->x, R->x);
448 fp_copy(P->y, R->y);
449 fp_copy(P->z, R->z);
450 }
451
452 if ((err = ltc_ecc_is_point_at_infinity(P, modulus, &inf)) != CRYPT_OK) return err;
453 if (inf) {
454 /* if P is point at infinity >> Result = point at infinity */
455 ltc_mp.set_int(R->x, 1);
456 ltc_mp.set_int(R->y, 1);
457 ltc_mp.set_int(R->z, 0);
458 return CRYPT_OK;
459 }
460
461 /* t1 = Z * Z */
462 fp_sqr(R->z, &t1);
463 fp_montgomery_reduce(&t1, modulus, mp);
464 /* Z = Y * Z */
465 fp_mul(R->z, R->y, R->z);
466 fp_montgomery_reduce(R->z, modulus, mp);
467 /* Z = 2Z */
468 fp_add(R->z, R->z, R->z);
469 if (fp_cmp(R->z, modulus) != FP_LT) {
470 fp_sub(R->z, modulus, R->z);
471 }
472
473 if (ma == NULL) { /* special case for curves with a == -3 (10% faster than general case) */
474 /* T2 = X - T1 */
475 fp_sub(R->x, &t1, &t2);
476 if (fp_cmp_d(&t2, 0) == LTC_MP_LT) {
477 fp_add(&t2, modulus, &t2);
478 }
479 /* T1 = X + T1 */
480 fp_add(&t1, R->x, &t1);
481 if (fp_cmp(&t1, modulus) != FP_LT) {
482 fp_sub(&t1, modulus, &t1);
483 }
484 /* T2 = T1 * T2 */
485 fp_mul(&t1, &t2, &t2);
486 fp_montgomery_reduce(&t2, modulus, mp);
487 /* T1 = 2T2 */
488 fp_add(&t2, &t2, &t1);
489 if (fp_cmp(&t1, modulus) != FP_LT) {
490 fp_sub(&t1, modulus, &t1);
491 }
492 /* T1 = T1 + T2 */
493 fp_add(&t1, &t2, &t1);
494 if (fp_cmp(&t1, modulus) != FP_LT) {
495 fp_sub(&t1, modulus, &t1);
496 }
497 }
498 else {
499 /* T2 = T1 * T1 */
500 fp_sqr(&t1, &t2);
501 fp_montgomery_reduce(&t2, modulus, mp);
502 /* T1 = T2 * a */
503 fp_mul(&t2, ma, &t1);
504 fp_montgomery_reduce(&t1, modulus, mp);
505 /* T2 = X * X */
506 fp_sqr(R->x, &t2);
507 fp_montgomery_reduce(&t2, modulus, mp);
508 /* T1 = T1 + T2 */
509 fp_add(&t1, &t2, &t1);
510 if (fp_cmp(&t1, modulus) != FP_LT) {
511 fp_sub(&t1, modulus, &t1);
512 }
513 /* T1 = T1 + T2 */
514 fp_add(&t1, &t2, &t1);
515 if (fp_cmp(&t1, modulus) != FP_LT) {
516 fp_sub(&t1, modulus, &t1);
517 }
518 /* T1 = T1 + T2 */
519 fp_add(&t1, &t2, &t1);
520 if (fp_cmp(&t1, modulus) != FP_LT) {
521 fp_sub(&t1, modulus, &t1);
522 }
523 }
524
525 /* Y = 2Y */
526 fp_add(R->y, R->y, R->y);
527 if (fp_cmp(R->y, modulus) != FP_LT) {
528 fp_sub(R->y, modulus, R->y);
529 }
530 /* Y = Y * Y */
531 fp_sqr(R->y, R->y);
532 fp_montgomery_reduce(R->y, modulus, mp);
533 /* T2 = Y * Y */
534 fp_sqr(R->y, &t2);
535 fp_montgomery_reduce(&t2, modulus, mp);
536 /* T2 = T2/2 */
537 if (fp_isodd(&t2)) {
538 fp_add(&t2, modulus, &t2);
539 }
540 fp_div_2(&t2, &t2);
541 /* Y = Y * X */
542 fp_mul(R->y, R->x, R->y);
543 fp_montgomery_reduce(R->y, modulus, mp);
544
545 /* X = T1 * T1 */
546 fp_sqr(&t1, R->x);
547 fp_montgomery_reduce(R->x, modulus, mp);
548 /* X = X - Y */
549 fp_sub(R->x, R->y, R->x);
550 if (fp_cmp_d(R->x, 0) == FP_LT) {
551 fp_add(R->x, modulus, R->x);
552 }
553 /* X = X - Y */
554 fp_sub(R->x, R->y, R->x);
555 if (fp_cmp_d(R->x, 0) == FP_LT) {
556 fp_add(R->x, modulus, R->x);
557 }
558
559 /* Y = Y - X */
560 fp_sub(R->y, R->x, R->y);
561 if (fp_cmp_d(R->y, 0) == FP_LT) {
562 fp_add(R->y, modulus, R->y);
563 }
564 /* Y = Y * T1 */
565 fp_mul(R->y, &t1, R->y);
566 fp_montgomery_reduce(R->y, modulus, mp);
567 /* Y = Y - T2 */
568 fp_sub(R->y, &t2, R->y);
569 if (fp_cmp_d(R->y, 0) == FP_LT) {
570 fp_add(R->y, modulus, R->y);
571 }
572
573 return CRYPT_OK;
574 }
575
576 /**
577 Add two ECC points
578 @param P The point to add
579 @param Q The point to add
580 @param R [out] The destination of the double
581 @param modulus The modulus of the field the ECC curve is in
582 @param Mp The "b" value from montgomery_setup()
583 @return CRYPT_OK on success
584 */
tfm_ecc_projective_add_point(const ecc_point * P,const ecc_point * Q,ecc_point * R,void * ma,void * modulus,void * Mp)585 static int tfm_ecc_projective_add_point(const ecc_point *P, const ecc_point *Q, ecc_point *R, void *ma, void *modulus, void *Mp)
586 {
587 fp_int t1, t2, x, y, z;
588 fp_digit mp;
589 int err, inf;
590
591 LTC_ARGCHK(P != NULL);
592 LTC_ARGCHK(Q != NULL);
593 LTC_ARGCHK(R != NULL);
594 LTC_ARGCHK(modulus != NULL);
595 LTC_ARGCHK(Mp != NULL);
596
597 mp = *((fp_digit*)Mp);
598
599 fp_init(&t1);
600 fp_init(&t2);
601 fp_init(&x);
602 fp_init(&y);
603 fp_init(&z);
604
605 if ((err = ltc_ecc_is_point_at_infinity(P, modulus, &inf)) != CRYPT_OK) return err;
606 if (inf) {
607 /* P is point at infinity >> Result = Q */
608 ltc_mp.copy(Q->x, R->x);
609 ltc_mp.copy(Q->y, R->y);
610 ltc_mp.copy(Q->z, R->z);
611 return CRYPT_OK;
612 }
613
614 if ((err = ltc_ecc_is_point_at_infinity(Q, modulus, &inf)) != CRYPT_OK) return err;
615 if (inf) {
616 /* Q is point at infinity >> Result = P */
617 ltc_mp.copy(P->x, R->x);
618 ltc_mp.copy(P->y, R->y);
619 ltc_mp.copy(P->z, R->z);
620 return CRYPT_OK;
621 }
622
623 /* should we dbl instead? */
624 fp_sub(modulus, Q->y, &t1);
625 if ( (fp_cmp(P->x, Q->x) == FP_EQ) &&
626 (Q->z != NULL && fp_cmp(P->z, Q->z) == FP_EQ) &&
627 (fp_cmp(P->y, Q->y) == FP_EQ || fp_cmp(P->y, &t1) == FP_EQ)) {
628 return tfm_ecc_projective_dbl_point(P, R, ma, modulus, Mp);
629 }
630
631 fp_copy(P->x, &x);
632 fp_copy(P->y, &y);
633 fp_copy(P->z, &z);
634
635 /* if Z is one then these are no-operations */
636 if (Q->z != NULL) {
637 /* T1 = Z' * Z' */
638 fp_sqr(Q->z, &t1);
639 fp_montgomery_reduce(&t1, modulus, mp);
640 /* X = X * T1 */
641 fp_mul(&t1, &x, &x);
642 fp_montgomery_reduce(&x, modulus, mp);
643 /* T1 = Z' * T1 */
644 fp_mul(Q->z, &t1, &t1);
645 fp_montgomery_reduce(&t1, modulus, mp);
646 /* Y = Y * T1 */
647 fp_mul(&t1, &y, &y);
648 fp_montgomery_reduce(&y, modulus, mp);
649 }
650
651 /* T1 = Z*Z */
652 fp_sqr(&z, &t1);
653 fp_montgomery_reduce(&t1, modulus, mp);
654 /* T2 = X' * T1 */
655 fp_mul(Q->x, &t1, &t2);
656 fp_montgomery_reduce(&t2, modulus, mp);
657 /* T1 = Z * T1 */
658 fp_mul(&z, &t1, &t1);
659 fp_montgomery_reduce(&t1, modulus, mp);
660 /* T1 = Y' * T1 */
661 fp_mul(Q->y, &t1, &t1);
662 fp_montgomery_reduce(&t1, modulus, mp);
663
664 /* Y = Y - T1 */
665 fp_sub(&y, &t1, &y);
666 if (fp_cmp_d(&y, 0) == FP_LT) {
667 fp_add(&y, modulus, &y);
668 }
669 /* T1 = 2T1 */
670 fp_add(&t1, &t1, &t1);
671 if (fp_cmp(&t1, modulus) != FP_LT) {
672 fp_sub(&t1, modulus, &t1);
673 }
674 /* T1 = Y + T1 */
675 fp_add(&t1, &y, &t1);
676 if (fp_cmp(&t1, modulus) != FP_LT) {
677 fp_sub(&t1, modulus, &t1);
678 }
679 /* X = X - T2 */
680 fp_sub(&x, &t2, &x);
681 if (fp_cmp_d(&x, 0) == FP_LT) {
682 fp_add(&x, modulus, &x);
683 }
684 /* T2 = 2T2 */
685 fp_add(&t2, &t2, &t2);
686 if (fp_cmp(&t2, modulus) != FP_LT) {
687 fp_sub(&t2, modulus, &t2);
688 }
689 /* T2 = X + T2 */
690 fp_add(&t2, &x, &t2);
691 if (fp_cmp(&t2, modulus) != FP_LT) {
692 fp_sub(&t2, modulus, &t2);
693 }
694
695 /* if Z' != 1 */
696 if (Q->z != NULL) {
697 /* Z = Z * Z' */
698 fp_mul(&z, Q->z, &z);
699 fp_montgomery_reduce(&z, modulus, mp);
700 }
701
702 /* Z = Z * X */
703 fp_mul(&z, &x, &z);
704 fp_montgomery_reduce(&z, modulus, mp);
705
706 /* T1 = T1 * X */
707 fp_mul(&t1, &x, &t1);
708 fp_montgomery_reduce(&t1, modulus, mp);
709 /* X = X * X */
710 fp_sqr(&x, &x);
711 fp_montgomery_reduce(&x, modulus, mp);
712 /* T2 = T2 * x */
713 fp_mul(&t2, &x, &t2);
714 fp_montgomery_reduce(&t2, modulus, mp);
715 /* T1 = T1 * X */
716 fp_mul(&t1, &x, &t1);
717 fp_montgomery_reduce(&t1, modulus, mp);
718
719 /* X = Y*Y */
720 fp_sqr(&y, &x);
721 fp_montgomery_reduce(&x, modulus, mp);
722 /* X = X - T2 */
723 fp_sub(&x, &t2, &x);
724 if (fp_cmp_d(&x, 0) == FP_LT) {
725 fp_add(&x, modulus, &x);
726 }
727
728 /* T2 = T2 - X */
729 fp_sub(&t2, &x, &t2);
730 if (fp_cmp_d(&t2, 0) == FP_LT) {
731 fp_add(&t2, modulus, &t2);
732 }
733 /* T2 = T2 - X */
734 fp_sub(&t2, &x, &t2);
735 if (fp_cmp_d(&t2, 0) == FP_LT) {
736 fp_add(&t2, modulus, &t2);
737 }
738 /* T2 = T2 * Y */
739 fp_mul(&t2, &y, &t2);
740 fp_montgomery_reduce(&t2, modulus, mp);
741 /* Y = T2 - T1 */
742 fp_sub(&t2, &t1, &y);
743 if (fp_cmp_d(&y, 0) == FP_LT) {
744 fp_add(&y, modulus, &y);
745 }
746 /* Y = Y/2 */
747 if (fp_isodd(&y)) {
748 fp_add(&y, modulus, &y);
749 }
750 fp_div_2(&y, &y);
751
752 fp_copy(&x, R->x);
753 fp_copy(&y, R->y);
754 fp_copy(&z, R->z);
755
756 return CRYPT_OK;
757 }
758
759
760 #endif
761
set_rand(void * a,int size)762 static int set_rand(void *a, int size)
763 {
764 LTC_ARGCHK(a != NULL);
765 fp_rand(a, size);
766 return CRYPT_OK;
767 }
768
769 const ltc_math_descriptor tfm_desc = {
770
771 "TomsFastMath",
772 (int)DIGIT_BIT,
773
774 &init,
775 &init_copy,
776 &deinit,
777
778 &neg,
779 ©,
780
781 &set_int,
782 &get_int,
783 &get_digit,
784 &get_digit_count,
785 &compare,
786 &compare_d,
787 &count_bits,
788 &count_lsb_bits,
789 &twoexpt,
790
791 &read_radix,
792 &write_radix,
793 &unsigned_size,
794 &unsigned_write,
795 &unsigned_read,
796
797 &add,
798 &addi,
799 &sub,
800 &subi,
801 &mul,
802 &muli,
803 &sqr,
804 NULL, /* TODO: &sqrtmod_prime */
805 ÷,
806 &div_2,
807 &modi,
808 &gcd,
809 &lcm,
810
811 &mulmod,
812 &sqrmod,
813 &invmod,
814
815 &montgomery_setup,
816 &montgomery_normalization,
817 &montgomery_reduce,
818 &montgomery_deinit,
819
820 &exptmod,
821 &isprime,
822
823 #ifdef LTC_MECC
824 #ifdef LTC_MECC_FP
825 <c_ecc_fp_mulmod,
826 #else
827 <c_ecc_mulmod,
828 #endif /* LTC_MECC_FP */
829 #ifdef LTC_MECC_ACCEL
830 &tfm_ecc_projective_add_point,
831 &tfm_ecc_projective_dbl_point,
832 #else
833 <c_ecc_projective_add_point,
834 <c_ecc_projective_dbl_point,
835 #endif /* LTC_MECC_ACCEL */
836 <c_ecc_map,
837 #ifdef LTC_ECC_SHAMIR
838 #ifdef LTC_MECC_FP
839 <c_ecc_fp_mul2add,
840 #else
841 <c_ecc_mul2add,
842 #endif /* LTC_MECC_FP */
843 #else
844 NULL,
845 #endif /* LTC_ECC_SHAMIR */
846 #else
847 NULL, NULL, NULL, NULL, NULL,
848 #endif /* LTC_MECC */
849
850 #ifdef LTC_MRSA
851 &rsa_make_key,
852 &rsa_exptmod,
853 #else
854 NULL, NULL,
855 #endif
856 &addmod,
857 &submod,
858
859 set_rand,
860
861 };
862
863
864 #endif
865
866 /* ref: $Format:%D$ */
867 /* git commit: $Format:%H$ */
868 /* commit time: $Format:%ai$ */
869