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    &copy,
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    &divide,
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    &ltc_ecc_fp_mulmod,
826 #else
827    &ltc_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    &ltc_ecc_projective_add_point,
834    &ltc_ecc_projective_dbl_point,
835 #endif /* LTC_MECC_ACCEL */
836    &ltc_ecc_map,
837 #ifdef LTC_ECC_SHAMIR
838 #ifdef LTC_MECC_FP
839    &ltc_ecc_fp_mul2add,
840 #else
841    &ltc_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