Home | History | Annotate | Download | only in math
      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 (at) 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 */
     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 
     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 
     56 static void deinit(void *a)
     57 {
     58    LTC_ARGCHKVD(a != NULL);
     59    XFREE(a);
     60 }
     61 
     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 
     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 
     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 ---- */
     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 
     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 
    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 
    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 
    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 
    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 
    145 static int count_bits(void *a)
    146 {
    147    LTC_ARGCHK(a != NULL);
    148    return fp_count_bits(a);
    149 }
    150 
    151 static int count_lsb_bits(void *a)
    152 {
    153    LTC_ARGCHK(a != NULL);
    154    return fp_cnt_lsb(a);
    155 }
    156 
    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 */
    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 */
    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 */
    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 */
    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 */
    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 */
    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 
    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 */
    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 
    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 */
    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 
    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 */
    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 */
    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 
    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 */
    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 */
    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 */
    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 
    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 
    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 */
    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 */
    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 */
    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 */
    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 */
    384 static void montgomery_deinit(void *a)
    385 {
    386    XFREE(a);
    387 }
    388 
    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 
    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 
    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 */
    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