Home | History | Annotate | Download | only in ecc
      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 /* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b
     13  *
     14  * All curves taken from NIST recommendation paper of July 1999
     15  * Available at http://csrc.nist.gov/cryptval/dss.htm
     16  */
     17 #include "tomcrypt.h"
     18 
     19 /**
     20   @file ltc_ecc_mulmod.c
     21   ECC Crypto, Tom St Denis
     22 */
     23 
     24 #ifdef MECC
     25 #ifndef LTC_ECC_TIMING_RESISTANT
     26 
     27 /* size of sliding window, don't change this! */
     28 #define WINSIZE 4
     29 
     30 /**
     31    Perform a point multiplication
     32    @param k    The scalar to multiply by
     33    @param G    The base point
     34    @param R    [out] Destination for kG
     35    @param modulus  The modulus of the field the ECC curve is in
     36    @param map      Boolean whether to map back to affine or not (1==map, 0 == leave in projective)
     37    @return CRYPT_OK on success
     38 */
     39 int ltc_ecc_mulmod(void *k, ecc_point *G, ecc_point *R, void *modulus, int map)
     40 {
     41    ecc_point *tG, *M[8];
     42    int        i, j, err;
     43    void       *mu, *mp;
     44    unsigned long buf;
     45    int        first, bitbuf, bitcpy, bitcnt, mode, digidx;
     46 
     47    LTC_ARGCHK(k       != NULL);
     48    LTC_ARGCHK(G       != NULL);
     49    LTC_ARGCHK(R       != NULL);
     50    LTC_ARGCHK(modulus != NULL);
     51 
     52    /* init montgomery reduction */
     53    if ((err = mp_montgomery_setup(modulus, &mp)) != CRYPT_OK) {
     54       return err;
     55    }
     56    if ((err = mp_init(&mu)) != CRYPT_OK) {
     57       mp_montgomery_free(mp);
     58       return err;
     59    }
     60    if ((err = mp_montgomery_normalization(mu, modulus)) != CRYPT_OK) {
     61       mp_montgomery_free(mp);
     62       mp_clear(mu);
     63       return err;
     64    }
     65 
     66   /* alloc ram for window temps */
     67   for (i = 0; i < 8; i++) {
     68       M[i] = ltc_ecc_new_point();
     69       if (M[i] == NULL) {
     70          for (j = 0; j < i; j++) {
     71              ltc_ecc_del_point(M[j]);
     72          }
     73          mp_montgomery_free(mp);
     74          mp_clear(mu);
     75          return CRYPT_MEM;
     76       }
     77   }
     78 
     79    /* make a copy of G incase R==G */
     80    tG = ltc_ecc_new_point();
     81    if (tG == NULL)                                                                   { err = CRYPT_MEM; goto done; }
     82 
     83    /* tG = G  and convert to montgomery */
     84    if (mp_cmp_d(mu, 1) == LTC_MP_EQ) {
     85       if ((err = mp_copy(G->x, tG->x)) != CRYPT_OK)                                  { goto done; }
     86       if ((err = mp_copy(G->y, tG->y)) != CRYPT_OK)                                  { goto done; }
     87       if ((err = mp_copy(G->z, tG->z)) != CRYPT_OK)                                  { goto done; }
     88    } else {
     89       if ((err = mp_mulmod(G->x, mu, modulus, tG->x)) != CRYPT_OK)                   { goto done; }
     90       if ((err = mp_mulmod(G->y, mu, modulus, tG->y)) != CRYPT_OK)                   { goto done; }
     91       if ((err = mp_mulmod(G->z, mu, modulus, tG->z)) != CRYPT_OK)                   { goto done; }
     92    }
     93    mp_clear(mu);
     94    mu = NULL;
     95 
     96    /* calc the M tab, which holds kG for k==8..15 */
     97    /* M[0] == 8G */
     98    if ((err = ltc_mp.ecc_ptdbl(tG, M[0], modulus, mp)) != CRYPT_OK)                 { goto done; }
     99    if ((err = ltc_mp.ecc_ptdbl(M[0], M[0], modulus, mp)) != CRYPT_OK)               { goto done; }
    100    if ((err = ltc_mp.ecc_ptdbl(M[0], M[0], modulus, mp)) != CRYPT_OK)               { goto done; }
    101 
    102    /* now find (8+k)G for k=1..7 */
    103    for (j = 9; j < 16; j++) {
    104        if ((err = ltc_mp.ecc_ptadd(M[j-9], tG, M[j-8], modulus, mp)) != CRYPT_OK)   { goto done; }
    105    }
    106 
    107    /* setup sliding window */
    108    mode   = 0;
    109    bitcnt = 1;
    110    buf    = 0;
    111    digidx = mp_get_digit_count(k) - 1;
    112    bitcpy = bitbuf = 0;
    113    first  = 1;
    114 
    115    /* perform ops */
    116    for (;;) {
    117      /* grab next digit as required */
    118      if (--bitcnt == 0) {
    119        if (digidx == -1) {
    120           break;
    121        }
    122        buf    = mp_get_digit(k, digidx);
    123        bitcnt = (int) ltc_mp.bits_per_digit;
    124        --digidx;
    125      }
    126 
    127      /* grab the next msb from the ltiplicand */
    128      i = (buf >> (ltc_mp.bits_per_digit - 1)) & 1;
    129      buf <<= 1;
    130 
    131      /* skip leading zero bits */
    132      if (mode == 0 && i == 0) {
    133         continue;
    134      }
    135 
    136      /* if the bit is zero and mode == 1 then we double */
    137      if (mode == 1 && i == 0) {
    138         if ((err = ltc_mp.ecc_ptdbl(R, R, modulus, mp)) != CRYPT_OK)                 { goto done; }
    139         continue;
    140      }
    141 
    142      /* else we add it to the window */
    143      bitbuf |= (i << (WINSIZE - ++bitcpy));
    144      mode = 2;
    145 
    146      if (bitcpy == WINSIZE) {
    147        /* if this is the first window we do a simple copy */
    148        if (first == 1) {
    149           /* R = kG [k = first window] */
    150           if ((err = mp_copy(M[bitbuf-8]->x, R->x)) != CRYPT_OK)                     { goto done; }
    151           if ((err = mp_copy(M[bitbuf-8]->y, R->y)) != CRYPT_OK)                     { goto done; }
    152           if ((err = mp_copy(M[bitbuf-8]->z, R->z)) != CRYPT_OK)                     { goto done; }
    153           first = 0;
    154        } else {
    155          /* normal window */
    156          /* ok window is filled so double as required and add  */
    157          /* double first */
    158          for (j = 0; j < WINSIZE; j++) {
    159            if ((err = ltc_mp.ecc_ptdbl(R, R, modulus, mp)) != CRYPT_OK)              { goto done; }
    160          }
    161 
    162          /* then add, bitbuf will be 8..15 [8..2^WINSIZE] guaranteed */
    163          if ((err = ltc_mp.ecc_ptadd(R, M[bitbuf-8], R, modulus, mp)) != CRYPT_OK)   { goto done; }
    164        }
    165        /* empty window and reset */
    166        bitcpy = bitbuf = 0;
    167        mode = 1;
    168     }
    169   }
    170 
    171    /* if bits remain then double/add */
    172    if (mode == 2 && bitcpy > 0) {
    173      /* double then add */
    174      for (j = 0; j < bitcpy; j++) {
    175        /* only double if we have had at least one add first */
    176        if (first == 0) {
    177           if ((err = ltc_mp.ecc_ptdbl(R, R, modulus, mp)) != CRYPT_OK)              { goto done; }
    178        }
    179 
    180        bitbuf <<= 1;
    181        if ((bitbuf & (1 << WINSIZE)) != 0) {
    182          if (first == 1){
    183             /* first add, so copy */
    184             if ((err = mp_copy(tG->x, R->x)) != CRYPT_OK)                           { goto done; }
    185             if ((err = mp_copy(tG->y, R->y)) != CRYPT_OK)                           { goto done; }
    186             if ((err = mp_copy(tG->z, R->z)) != CRYPT_OK)                           { goto done; }
    187             first = 0;
    188          } else {
    189             /* then add */
    190             if ((err = ltc_mp.ecc_ptadd(R, tG, R, modulus, mp)) != CRYPT_OK)        { goto done; }
    191          }
    192        }
    193      }
    194    }
    195 
    196    /* map R back from projective space */
    197    if (map) {
    198       err = ltc_ecc_map(R, modulus, mp);
    199    } else {
    200       err = CRYPT_OK;
    201    }
    202 done:
    203    if (mu != NULL) {
    204       mp_clear(mu);
    205    }
    206    mp_montgomery_free(mp);
    207    ltc_ecc_del_point(tG);
    208    for (i = 0; i < 8; i++) {
    209        ltc_ecc_del_point(M[i]);
    210    }
    211    return err;
    212 }
    213 
    214 #endif
    215 
    216 #undef WINSIZE
    217 
    218 #endif
    219 
    220 /* $Source: /cvs/libtom/libtomcrypt/src/pk/ecc/ltc_ecc_mulmod.c,v $ */
    221 /* $Revision: 1.24 $ */
    222 /* $Date: 2006/12/04 05:07:59 $ */
    223