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