Example #1
0
/*
 * mpi_to_weave takes an array of bignums, a matrix in which each bignum 
 * occupies all the columns of a row, and transposes it into a matrix in 
 * which each bignum occupies a column of every row.  The first row of the
 * input matrix becomes the first column of the output matrix.  The n'th
 * row of input becomes the n'th column of output.  The input data is said
 * to be "interleaved" or "woven" into the output matrix.
 *
 * The array of bignums is left in this woven form.  Each time a single
 * bignum value is needed, it is recreated by fetching the n'th column, 
 * forming a single row which is the new bignum.
 *
 * The purpose of this interleaving is make it impossible to determine which
 * of the bignums is being used in any one operation by examining the pattern
 * of cache misses.
 *
 * The weaving function does not transpose the entire input matrix in one call.
 * It transposes 4 rows of mp_ints into their respective columns of output.
 *
 * There are two different implementations of the weaving and unweaving code
 * in this file.  One uses byte loads and stores.  The second uses loads and
 * stores of mp_weave_word size values.  The weaved forms of these two 
 * implementations differ.  Consequently, each one has its own explanation.
 *
 * Here is the explanation for the byte-at-a-time implementation.
 *
 * This implementation treats each mp_int bignum as an array of bytes, 
 * rather than as an array of mp_digits.  It stores those bytes as a 
 * column of bytes in the output matrix.  It doesn't care if the machine
 * uses big-endian or little-endian byte ordering within mp_digits.
 * The first byte of the mp_digit array becomes the first byte in the output
 * column, regardless of whether that byte is the MSB or LSB of the mp_digit.
 *
 * "bignums" is an array of mp_ints.
 * It points to four rows, four mp_ints, a subset of a larger array of mp_ints.
 *
 * "weaved" is the weaved output matrix. 
 * The first byte of bignums[0] is stored in weaved[0].
 * 
 * "nBignums" is the total number of bignums in the array of which "bignums" 
 * is a part.  
 *
 * "nDigits" is the size in mp_digits of each mp_int in the "bignums" array. 
 * mp_ints that use less than nDigits digits are logically padded with zeros 
 * while being stored in the weaved array.
 */
mp_err mpi_to_weave(const mp_int  *bignums, 
                    unsigned char *weaved, 
		    mp_size nDigits,  /* in each mp_int of input */
		    mp_size nBignums) /* in the entire source array */
{
  mp_size i;
  unsigned char * endDest = weaved + (nDigits * nBignums * sizeof(mp_digit));

  for (i=0; i < WEAVE_WORD_SIZE; i++) {
    mp_size used = MP_USED(&bignums[i]);
    unsigned char *pSrc   = (unsigned char *)MP_DIGITS(&bignums[i]);
    unsigned char *endSrc = pSrc + (used * sizeof(mp_digit));
    unsigned char *pDest  = weaved + i;

    ARGCHK(MP_SIGN(&bignums[i]) == MP_ZPOS, MP_BADARG);
    ARGCHK(used <= nDigits, MP_BADARG);

    for (; pSrc < endSrc; pSrc++) {
      *pDest = *pSrc;
      pDest += nBignums;
    }
    while (pDest < endDest) {
      *pDest = 0;
      pDest += nBignums;
    }
  }

  return MP_OKAY;
}
Example #2
0
mp_err  mpp_divis_vector(mp_int *a, const mp_digit *vec, int size, int *which)
{
  ARGCHK(a != NULL && vec != NULL && size > 0, MP_BADARG);
  
  return s_mpp_divp(a, vec, size, which);

} /* end mpp_divis_vector() */
Example #3
0
/* Elliptic curve scalar-point multiplication. Computes R(x, y) = k1 * G +
 * k2 * P(x, y), where G is the generator (base point) of the group of
 * points on the elliptic curve. Allows k1 = NULL or { k2, P } = NULL.
 * Input and output values are assumed to be NOT field-encoded. */
mp_err
ec_pts_mul_basic(const mp_int *k1, const mp_int *k2, const mp_int *px,
                                 const mp_int *py, mp_int *rx, mp_int *ry,
                                 const ECGroup *group)
{
        mp_err res = MP_OKAY;
        mp_int sx, sy;

        ARGCHK(group != NULL, MP_BADARG);
        ARGCHK(!((k1 == NULL)
                         && ((k2 == NULL) || (px == NULL)
                                 || (py == NULL))), MP_BADARG);

        /* if some arguments are not defined used ECPoint_mul */
        if (k1 == NULL) {
                return ECPoint_mul(group, k2, px, py, rx, ry);
        } else if ((k2 == NULL) || (px == NULL) || (py == NULL)) {
                return ECPoint_mul(group, k1, NULL, NULL, rx, ry);
        }

        MP_DIGITS(&sx) = 0;
        MP_DIGITS(&sy) = 0;
        MP_CHECKOK(mp_init(&sx, FLAG(k1)));
        MP_CHECKOK(mp_init(&sy, FLAG(k1)));

        MP_CHECKOK(ECPoint_mul(group, k1, NULL, NULL, &sx, &sy));
        MP_CHECKOK(ECPoint_mul(group, k2, px, py, rx, ry));

        if (group->meth->field_enc) {
                MP_CHECKOK(group->meth->field_enc(&sx, &sx, group->meth));
                MP_CHECKOK(group->meth->field_enc(&sy, &sy, group->meth));
                MP_CHECKOK(group->meth->field_enc(rx, rx, group->meth));
                MP_CHECKOK(group->meth->field_enc(ry, ry, group->meth));
        }

        MP_CHECKOK(group->point_add(&sx, &sy, rx, ry, rx, ry, group));

        if (group->meth->field_dec) {
                MP_CHECKOK(group->meth->field_dec(rx, rx, group->meth));
                MP_CHECKOK(group->meth->field_dec(ry, ry, group->meth));
        }

  CLEANUP:
        mp_clear(&sx);
        mp_clear(&sy);
        return res;
}
Example #4
0
/*! c <- REDC( a * b ) mod N
    \param a < N  i.e. "reduced"
    \param b < N  i.e. "reduced"
    \param mmm modulus N and n0' of N
*/
mp_err
s_mp_mul_mont(const mp_int *a, const mp_int *b, mp_int *c,
              mp_mont_modulus *mmm)
{
    mp_digit *pb;
    mp_digit m_i;
    mp_err res;
    mp_size ib; /* "index b": index of current digit of B */
    mp_size useda, usedb;

    ARGCHK(a != NULL && b != NULL && c != NULL, MP_BADARG);

    if (MP_USED(a) < MP_USED(b)) {
        const mp_int *xch = b; /* switch a and b, to do fewer outer loops */
        b = a;
        a = xch;
    }

    MP_USED(c) = 1;
    MP_DIGIT(c, 0) = 0;
    ib = (MP_USED(&mmm->N) << 1) + 1;
    if ((res = s_mp_pad(c, ib)) != MP_OKAY)
        goto CLEANUP;

    useda = MP_USED(a);
    pb = MP_DIGITS(b);
    s_mpv_mul_d(MP_DIGITS(a), useda, *pb++, MP_DIGITS(c));
    s_mp_setz(MP_DIGITS(c) + useda + 1, ib - (useda + 1));
    m_i = MP_DIGIT(c, 0) * mmm->n0prime;
    s_mp_mul_d_add_offset(&mmm->N, m_i, c, 0);

    /* Outer loop:  Digits of b */
    usedb = MP_USED(b);
    for (ib = 1; ib < usedb; ib++) {
        mp_digit b_i = *pb++;

        /* Inner product:  Digits of a */
        if (b_i)
            s_mpv_mul_d_add_prop(MP_DIGITS(a), useda, b_i, MP_DIGITS(c) + ib);
        m_i = MP_DIGIT(c, ib) * mmm->n0prime;
        s_mp_mul_d_add_offset(&mmm->N, m_i, c, ib);
    }
    if (usedb < MP_USED(&mmm->N)) {
        for (usedb = MP_USED(&mmm->N); ib < usedb; ++ib) {
            m_i = MP_DIGIT(c, ib) * mmm->n0prime;
            s_mp_mul_d_add_offset(&mmm->N, m_i, c, ib);
        }
    }
    s_mp_clamp(c);
    s_mp_rshd(c, MP_USED(&mmm->N)); /* c /= R */
    if (s_mp_cmp(c, &mmm->N) >= 0) {
        MP_CHECKOK(s_mp_sub(c, &mmm->N));
    }
    res = MP_OKAY;

CLEANUP:
    return res;
}
Example #5
0
mp_err   mp_pkcs1v15_encrypt(char *msg, int mlen,
			     mp_int *e, mp_int *modulus,
			     char **out, int *olen,
			     rnd_f rand)
{
  int    k;
  char   *buf;
  mp_err res;
  mp_int mrep;

  ARGCHK(msg != NULL && mlen >= 0 && e != NULL &&
	 modulus != NULL && out != NULL && olen != NULL, MP_BADARG);

  k = mp_unsigned_bin_size(modulus); /* length of modulus, in bytes */
  if((buf = malloc(k)) == NULL)
    return MP_MEM;

  /* Encode according to PKCS #1 v1.5 */
  if((res = mp_pkcs1v15_encode(msg, mlen, buf, k, rand)) != MP_OKAY) 
    goto CLEANUP;

  /* Convert encoded message to a big number for encryption */
  if((res = mp_init(&mrep)) != MP_OKAY)
    goto CLEANUP;

  if((res = mp_os2ip(&mrep, buf, k)) != MP_OKAY) {
    mp_clear(&mrep);
    goto CLEANUP;
  }

  /* Now, encrypt... */
  if((res = mp_rsaep(&mrep, e, modulus, &mrep)) != MP_OKAY) {
    mp_clear(&mrep);
    goto CLEANUP;
  }

  /* Unpack message representative... */
  if((res = mp_i2osp(&mrep, buf, k)) != MP_OKAY) {
    mp_clear(&mrep);
    goto CLEANUP;
  }

  mp_clear(&mrep);
  *out = buf;
  *olen = k;

  return MP_OKAY;

 CLEANUP:
  memset(buf, 0, k);
  free(buf);
  return res;

} /* end mp_pkcs1v15_encrypt() */
Example #6
0
mp_err  mpp_random_size(mp_int *a, mp_size prec)
{
  mp_err   res;

  ARGCHK(a != NULL && prec > 0, MP_BADARG);
  
  if((res = s_mp_pad(a, prec)) != MP_OKAY)
    return res;

  return mpp_random(a);

} /* end mpp_random_size() */
Example #7
0
mp_err   mp_rsavp(mp_int *sig, mp_int *e, mp_int *modulus, mp_int *msg)
{
  ARGCHK(sig != NULL && e != NULL &&
	 modulus != NULL && msg != NULL, MP_BADARG);

  if((mp_cmp_z(sig) < 0) || 
     (mp_cmp(sig, modulus) >= 0)) {
    return MP_RANGE;
  }

  return mp_exptmod(sig, e, modulus, msg);

} /* end mp_rsavp() */
Example #8
0
mp_err   mp_rsasp(mp_int *msg, mp_int *d, mp_int *modulus, mp_int *sig)
{
  ARGCHK(msg != NULL && d != NULL &&
	 modulus != NULL && sig != NULL, MP_BADARG);

  if((mp_cmp_z(msg) < 0) ||
     (mp_cmp(msg, modulus) >= 0)) {
    return MP_RANGE;
  }

  return mp_exptmod(msg, d, modulus, sig);

} /* end mp_rsasp() */
Example #9
0
mp_err   mp_rsaep(mp_int *msg, mp_int *e, mp_int *modulus, mp_int *cipher)
{
  ARGCHK(msg != NULL && e != NULL && 
	 modulus != NULL && cipher != NULL, MP_BADARG);

  /* Insure that message representative is in range of modulus */
  if((mp_cmp_z(msg) < 0) ||
     (mp_cmp(msg, modulus) >= 0)) {
    return MP_RANGE;
  }

  return mp_exptmod(msg, e, modulus, cipher);

} /* end mp_rsaep() */
Example #10
0
mp_err   mp_rsadp(mp_int *cipher, mp_int *d, mp_int *modulus, mp_int *msg)
{
  ARGCHK(cipher != NULL && d != NULL && 
	 modulus != NULL && msg != NULL, MP_BADARG);

  /* Insure that ciphertext representative is in range of modulus */
  if((mp_cmp_z(cipher) < 0) || 
     (mp_cmp(cipher, modulus) >= 0)) {
    return MP_RANGE;
  }

  return mp_exptmod(cipher, d, modulus, msg);

} /* end mp_rsadp() */
Example #11
0
/* Elliptic curve scalar-point multiplication. Computes R(x, y) = k * P(x,
 * y).  If x, y = NULL, then P is assumed to be the generator (base point)
 * of the group of points on the elliptic curve. Input and output values
 * are assumed to be NOT field-encoded. */
mp_err
ECPoint_mul(const ECGroup *group, const mp_int *k, const mp_int *px,
                        const mp_int *py, mp_int *rx, mp_int *ry)
{
        mp_err res = MP_OKAY;
        mp_int kt;

        ARGCHK((k != NULL) && (group != NULL), MP_BADARG);
        MP_DIGITS(&kt) = 0;

        /* want scalar to be less than or equal to group order */
        if (mp_cmp(k, &group->order) > 0) {
                MP_CHECKOK(mp_init(&kt, FLAG(k)));
                MP_CHECKOK(mp_mod(k, &group->order, &kt));
        } else {
                MP_SIGN(&kt) = MP_ZPOS;
                MP_USED(&kt) = MP_USED(k);
                MP_ALLOC(&kt) = MP_ALLOC(k);
                MP_DIGITS(&kt) = MP_DIGITS(k);
        }

        if ((px == NULL) || (py == NULL)) {
                if (group->base_point_mul) {
                        MP_CHECKOK(group->base_point_mul(&kt, rx, ry, group));
                } else {
                        MP_CHECKOK(group->
                                           point_mul(&kt, &group->genx, &group->geny, rx, ry,
                                                                 group));
                }
        } else {
                if (group->meth->field_enc) {
                        MP_CHECKOK(group->meth->field_enc(px, rx, group->meth));
                        MP_CHECKOK(group->meth->field_enc(py, ry, group->meth));
                        MP_CHECKOK(group->point_mul(&kt, rx, ry, rx, ry, group));
                } else {
                        MP_CHECKOK(group->point_mul(&kt, px, py, rx, ry, group));
                }
        }
        if (group->meth->field_dec) {
                MP_CHECKOK(group->meth->field_dec(rx, rx, group->meth));
                MP_CHECKOK(group->meth->field_dec(ry, ry, group->meth));
        }

  CLEANUP:
        if (MP_DIGITS(&kt) != MP_DIGITS(k)) {
                mp_clear(&kt);
        }
        return res;
}
Example #12
0
/* Elliptic curve scalar-point multiplication. Computes R(x, y) = k1 * G +
 * k2 * P(x, y), where G is the generator (base point) of the group of
 * points on the elliptic curve. Allows k1 = NULL or { k2, P } = NULL.
 * Input and output values are assumed to be NOT field-encoded. */
mp_err
ECPoints_mul(const ECGroup *group, const mp_int *k1, const mp_int *k2,
                         const mp_int *px, const mp_int *py, mp_int *rx, mp_int *ry)
{
        mp_err res = MP_OKAY;
        mp_int k1t, k2t;
        const mp_int *k1p, *k2p;

        MP_DIGITS(&k1t) = 0;
        MP_DIGITS(&k2t) = 0;

        ARGCHK(group != NULL, MP_BADARG);

        /* want scalar to be less than or equal to group order */
        if (k1 != NULL) {
                if (mp_cmp(k1, &group->order) >= 0) {
                        MP_CHECKOK(mp_init(&k1t, FLAG(k1)));
                        MP_CHECKOK(mp_mod(k1, &group->order, &k1t));
                        k1p = &k1t;
                } else {
                        k1p = k1;
                }
        } else {
                k1p = k1;
        }
        if (k2 != NULL) {
                if (mp_cmp(k2, &group->order) >= 0) {
                        MP_CHECKOK(mp_init(&k2t, FLAG(k2)));
                        MP_CHECKOK(mp_mod(k2, &group->order, &k2t));
                        k2p = &k2t;
                } else {
                        k2p = k2;
                }
        } else {
                k2p = k2;
        }

        /* if points_mul is defined, then use it */
        if (group->points_mul) {
                res = group->points_mul(k1p, k2p, px, py, rx, ry, group);
        } else {
                res = ec_pts_mul_simul_w2(k1p, k2p, px, py, rx, ry, group);
        }

  CLEANUP:
        mp_clear(&k1t);
        mp_clear(&k2t);
        return res;
}
Example #13
0
mp_err   mp_pkcs1v15_decrypt(char *msg, int mlen,
			     mp_int *d, mp_int *modulus,
			     char **out, int *olen)
{
  int     k;
  char   *buf;
  mp_err  res;
  mp_int  mrep;

  ARGCHK(msg != NULL && d != NULL && modulus != NULL &&
	 out != NULL && olen != NULL, MP_BADARG);

  k = mp_unsigned_bin_size(modulus);  /* size of modulus, in bytes */
  if(mlen != k)
    return MP_UNDEF;
  if((buf = malloc(k)) == NULL)
    return MP_MEM;

  /* Convert ciphertext to integer representative */
  if((res = mp_init(&mrep)) != MP_OKAY) {
    free(buf);
    return res;
  }

  if((res = mp_os2ip(&mrep, msg, mlen)) != MP_OKAY) 
    goto CLEANUP;

  /* Decrypt ... */
  if((res = mp_rsadp(&mrep, d, modulus, &mrep)) != MP_OKAY)
    goto CLEANUP;

  if((res = mp_i2osp(&mrep, buf, k)) != MP_OKAY)
    goto CLEANUP;

  if((res = mp_pkcs1v15_decode(buf, k, buf, olen)) == MP_OKAY) {
    *out = buf;
    return MP_OKAY;
  } 

 CLEANUP:
  memset(buf, 0, k - 1);
  free(buf);
  mp_clear(&mrep);
  return res;
    
} /* end mp_pkcs1v15_decrypt() */
Example #14
0
mp_err  mpp_random(mp_int *a)

{
  mp_digit  next = 0;
  unsigned int       ix, jx;

  ARGCHK(a != NULL, MP_BADARG);

  for(ix = 0; ix < USED(a); ix++) {
    for(jx = 0; jx < sizeof(mp_digit); jx++) {
      next = (next << CHAR_BIT) | (RANDOM() & UCHAR_MAX);
    }
    DIGIT(a, ix) = next;
  }

  return MP_OKAY;

} /* end mpp_random() */
Example #15
0
/*
  mpp_divis_primes(a, np)

  Test whether a is divisible by any of the first 'np' primes.  If it
  is, returns MP_YES and sets *np to the value of the digit that did
  it.  If not, returns MP_NO.
 */
mp_err  mpp_divis_primes(mp_int *a, mp_digit *np)
{
  int     size, which;
  mp_err  res;

  ARGCHK(a != NULL && np != NULL, MP_BADARG);

  size = (int)*np;
  if(size > prime_tab_size)
    size = prime_tab_size;

  res = mpp_divis_vector(a, prime_tab, size, &which);
  if(res == MP_YES) 
    *np = prime_tab[which];

  return res;

} /* end mpp_divis_primes() */
Example #16
0
mp_err   mp_i2osp(mp_int *x, char *out, int len)
{
  int    xlen;

  ARGCHK(x != NULL && out != NULL && len > 0, MP_BADARG);

  if((xlen = mp_unsigned_bin_size(x)) > len) {
    return MP_RANGE;
  }

  xlen -= len;
  if(xlen > 0)
    memset(out, 0, xlen);

  mp_to_unsigned_bin(x, (unsigned char *)out + xlen);

  return MP_OKAY;
 
} /* end mp_i2osp() */
Example #17
0
mp_err mpl_bit_set(mp_int *a, int bit)
{
  unsigned int ddigit,bbit;
  mp_err   res;
  //int bob;

  ARGCHK(a != NULL, MP_BADARG);

  //bob=DIGIT_BIT;
  ddigit = bit / DIGIT_BIT;
  bbit	 = bit % DIGIT_BIT;

  if((res = s_mp_pad(a,ddigit+1)) != MP_OKAY)
    return res;

  DIGIT(a, ddigit) = DIGIT(a, ddigit) | (1 << bbit);  
  return MP_OKAY;

} 
Example #18
0
mp_err  mpp_divis_d(mp_int *a, mp_digit d)
{
  mp_err     res;
  mp_digit   rem;

  ARGCHK(a != NULL, MP_BADARG);

  if(d == 0)
    return MP_NO;

  if((res = mp_mod_d(a, d, &rem)) != MP_OKAY)
    return res;

  if(rem == 0)
    return MP_YES;
  else
    return MP_NO;

} /* end mpp_divis_d() */
Example #19
0
mp_err mpl_bit_clear(mp_int *a, int bit)
{
  unsigned int ddigit,bbit;

  ARGCHK(a != NULL, MP_BADARG);

  ddigit = bit / DIGIT_BIT;
  bbit	 = bit % DIGIT_BIT;

  if( ddigit >= USED(a) ) //il faut clear un bit déjà clear...
	  return MP_OKAY;

  DIGIT(a, ddigit) = DIGIT(a, ddigit) &  ~(1 << bbit);
  
  //Enleve les espace inutiles si requis
  s_mp_clamp(a)

  return MP_OKAY;
} 
Example #20
0
mp_err   mp_pkcs1v15_encode(char *msg, int mlen, 
			    char *emsg, int emlen, rnd_f rand)
{
  int    poffset;

  ARGCHK(msg != NULL && mlen >= 0 &&
	 emsg != NULL && emlen > 0 && rand != NULL, MP_BADARG);

  if(mlen > emlen - 10)
    return MP_RANGE;

  emsg[0] = 0x02;
  poffset = emlen - mlen;        /* offset of end of padding */
  (rand)(emsg + 1, poffset - 2); /* generate random pad      */
  emsg[poffset - 1] = 0x00;      /* zero separator           */

  memcpy(emsg + poffset, msg, mlen);

  return MP_OKAY;

} /* end mp_pkcs1v15_encode() */
Example #21
0
mp_err   mp_pkcs1v15_decode(char *emsg, int emlen, char *msg, int *mlen)
{
  int    ix, jx, outlen;

  ARGCHK(emsg != NULL, MP_BADARG);

  /* If message is less than minimum length, it's an error */
  if(emlen < 10)
    return MP_RANGE;

  /* Check the format of the packet, error if it's invalid */
  if(emsg[0] != 0x02)
    return MP_UNDEF;

  /* Look for zero separator */
  for(ix = 9; ix < emlen; ix++)
    if(emsg[ix] == 0x00)
      break;

  if(ix == emlen)
    return MP_UNDEF;

  /* Make sure padding bytes are valid */
  for(jx = 1; jx < ix; jx++)
    if(emsg[jx] == 0)
      return MP_UNDEF;

  outlen = emlen - (ix + 1);
  if(msg != NULL && outlen > 0)
    memmove(msg, emsg + (ix + 1), outlen);

  if(mlen != NULL)
    *mlen = outlen;
  
  return MP_OKAY;

} /* end mp_pkcs1v15_decode() */
Example #22
0
/* Computes R = nP where R is (rx, ry) and P is the base point. Elliptic
 * curve points P and R can be identical. Uses mixed Modified-Jacobian
 * co-ordinates for doubling and Chudnovsky Jacobian coordinates for
 * additions. Assumes input is already field-encoded using field_enc, and
 * returns output that is still field-encoded. Uses 5-bit window NAF
 * method (algorithm 11) for scalar-point multiplication from Brown,
 * Hankerson, Lopez, Menezes. Software Implementation of the NIST Elliptic
 * Curves Over Prime Fields. */
mp_err
ec_GFp_pt_mul_jm_wNAF(const mp_int *n, const mp_int *px, const mp_int *py,
                                          mp_int *rx, mp_int *ry, const ECGroup *group)
{
        mp_err res = MP_OKAY;
        mp_int precomp[16][2], rz, tpx, tpy;
        mp_int raz4;
        mp_int scratch[MAX_SCRATCH];
        signed char *naf = NULL;
        int i, orderBitSize;

        MP_DIGITS(&rz) = 0;
        MP_DIGITS(&raz4) = 0;
        MP_DIGITS(&tpx) = 0;
        MP_DIGITS(&tpy) = 0;
        for (i = 0; i < 16; i++) {
                MP_DIGITS(&precomp[i][0]) = 0;
                MP_DIGITS(&precomp[i][1]) = 0;
        }
        for (i = 0; i < MAX_SCRATCH; i++) {
                MP_DIGITS(&scratch[i]) = 0;
        }

        ARGCHK(group != NULL, MP_BADARG);
        ARGCHK((n != NULL) && (px != NULL) && (py != NULL), MP_BADARG);

        /* initialize precomputation table */
        MP_CHECKOK(mp_init(&tpx, FLAG(n)));
        MP_CHECKOK(mp_init(&tpy, FLAG(n)));;
        MP_CHECKOK(mp_init(&rz, FLAG(n)));
        MP_CHECKOK(mp_init(&raz4, FLAG(n)));

        for (i = 0; i < 16; i++) {
                MP_CHECKOK(mp_init(&precomp[i][0], FLAG(n)));
                MP_CHECKOK(mp_init(&precomp[i][1], FLAG(n)));
        }
        for (i = 0; i < MAX_SCRATCH; i++) {
                MP_CHECKOK(mp_init(&scratch[i], FLAG(n)));
        }

        /* Set out[8] = P */
        MP_CHECKOK(mp_copy(px, &precomp[8][0]));
        MP_CHECKOK(mp_copy(py, &precomp[8][1]));

        /* Set (tpx, tpy) = 2P */
        MP_CHECKOK(group->
                           point_dbl(&precomp[8][0], &precomp[8][1], &tpx, &tpy,
                                                 group));

        /* Set 3P, 5P, ..., 15P */
        for (i = 8; i < 15; i++) {
                MP_CHECKOK(group->
                                   point_add(&precomp[i][0], &precomp[i][1], &tpx, &tpy,
                                                         &precomp[i + 1][0], &precomp[i + 1][1],
                                                         group));
        }

        /* Set -15P, -13P, ..., -P */
        for (i = 0; i < 8; i++) {
                MP_CHECKOK(mp_copy(&precomp[15 - i][0], &precomp[i][0]));
                MP_CHECKOK(group->meth->
                                   field_neg(&precomp[15 - i][1], &precomp[i][1],
                                                         group->meth));
        }

        /* R = inf */
        MP_CHECKOK(ec_GFp_pt_set_inf_jac(rx, ry, &rz));

        orderBitSize = mpl_significant_bits(&group->order);

        /* Allocate memory for NAF */
#ifdef _KERNEL
        naf = (signed char *) kmem_alloc((orderBitSize + 1), FLAG(n));
#else
        naf = (signed char *) malloc(sizeof(signed char) * (orderBitSize + 1));
        if (naf == NULL) {
                res = MP_MEM;
                goto CLEANUP;
        }
#endif

        /* Compute 5NAF */
        ec_compute_wNAF(naf, orderBitSize, n, 5);

        /* wNAF method */
        for (i = orderBitSize; i >= 0; i--) {
                /* R = 2R */
                ec_GFp_pt_dbl_jm(rx, ry, &rz, &raz4, rx, ry, &rz,
                                             &raz4, scratch, group);
                if (naf[i] != 0) {
                        ec_GFp_pt_add_jm_aff(rx, ry, &rz, &raz4,
                                                                 &precomp[(naf[i] + 15) / 2][0],
                                                                 &precomp[(naf[i] + 15) / 2][1], rx, ry,
                                                                 &rz, &raz4, scratch, group);
                }
        }

        /* convert result S to affine coordinates */
        MP_CHECKOK(ec_GFp_pt_jac2aff(rx, ry, &rz, rx, ry, group));

  CLEANUP:
        for (i = 0; i < MAX_SCRATCH; i++) {
                mp_clear(&scratch[i]);
        }
        for (i = 0; i < 16; i++) {
                mp_clear(&precomp[i][0]);
                mp_clear(&precomp[i][1]);
        }
        mp_clear(&tpx);
        mp_clear(&tpy);
        mp_clear(&rz);
        mp_clear(&raz4);
#ifdef _KERNEL
        kmem_free(naf, (orderBitSize + 1));
#else
        free(naf);
#endif
        return res;
}
Example #23
0
/* Elliptic curve scalar-point multiplication. Computes R(x, y) = k1 * G + 
 * k2 * P(x, y), where G is the generator (base point) of the group of
 * points on the elliptic curve. Allows k1 = NULL or { k2, P } = NULL.
 * Uses mixed Jacobian-affine coordinates. Input and output values are
 * assumed to be NOT field-encoded. Uses algorithm 15 (simultaneous
 * multiple point multiplication) from Brown, Hankerson, Lopez, Menezes.
 * Software Implementation of the NIST Elliptic Curves over Prime Fields. */
mp_err
ec_GFp_pts_mul_jac(const mp_int *k1, const mp_int *k2, const mp_int *px,
				   const mp_int *py, mp_int *rx, mp_int *ry,
				   const ECGroup *group)
{
	mp_err res = MP_OKAY;
	mp_int precomp[4][4][2];
	mp_int rz;
	const mp_int *a, *b;
	unsigned int i, j;
	int ai, bi, d;

	for (i = 0; i < 4; i++) {
		for (j = 0; j < 4; j++) {
			MP_DIGITS(&precomp[i][j][0]) = 0;
			MP_DIGITS(&precomp[i][j][1]) = 0;
		}
	}
	MP_DIGITS(&rz) = 0;

	ARGCHK(group != NULL, MP_BADARG);
	ARGCHK(!((k1 == NULL)
			 && ((k2 == NULL) || (px == NULL)
				 || (py == NULL))), MP_BADARG);

	/* if some arguments are not defined used ECPoint_mul */
	if (k1 == NULL) {
		return ECPoint_mul(group, k2, px, py, rx, ry);
	} else if ((k2 == NULL) || (px == NULL) || (py == NULL)) {
		return ECPoint_mul(group, k1, NULL, NULL, rx, ry);
	}

	/* initialize precomputation table */
	for (i = 0; i < 4; i++) {
		for (j = 0; j < 4; j++) {
			MP_CHECKOK(mp_init(&precomp[i][j][0]));
			MP_CHECKOK(mp_init(&precomp[i][j][1]));
		}
	}

	/* fill precomputation table */
	/* assign {k1, k2} = {a, b} such that len(a) >= len(b) */
	if (mpl_significant_bits(k1) < mpl_significant_bits(k2)) {
		a = k2;
		b = k1;
		if (group->meth->field_enc) {
			MP_CHECKOK(group->meth->
					   field_enc(px, &precomp[1][0][0], group->meth));
			MP_CHECKOK(group->meth->
					   field_enc(py, &precomp[1][0][1], group->meth));
		} else {
			MP_CHECKOK(mp_copy(px, &precomp[1][0][0]));
			MP_CHECKOK(mp_copy(py, &precomp[1][0][1]));
		}
		MP_CHECKOK(mp_copy(&group->genx, &precomp[0][1][0]));
		MP_CHECKOK(mp_copy(&group->geny, &precomp[0][1][1]));
	} else {
		a = k1;
		b = k2;
		MP_CHECKOK(mp_copy(&group->genx, &precomp[1][0][0]));
		MP_CHECKOK(mp_copy(&group->geny, &precomp[1][0][1]));
		if (group->meth->field_enc) {
			MP_CHECKOK(group->meth->
					   field_enc(px, &precomp[0][1][0], group->meth));
			MP_CHECKOK(group->meth->
					   field_enc(py, &precomp[0][1][1], group->meth));
		} else {
			MP_CHECKOK(mp_copy(px, &precomp[0][1][0]));
			MP_CHECKOK(mp_copy(py, &precomp[0][1][1]));
		}
	}
	/* precompute [*][0][*] */
	mp_zero(&precomp[0][0][0]);
	mp_zero(&precomp[0][0][1]);
	MP_CHECKOK(group->
			   point_dbl(&precomp[1][0][0], &precomp[1][0][1],
						 &precomp[2][0][0], &precomp[2][0][1], group));
	MP_CHECKOK(group->
			   point_add(&precomp[1][0][0], &precomp[1][0][1],
						 &precomp[2][0][0], &precomp[2][0][1],
						 &precomp[3][0][0], &precomp[3][0][1], group));
	/* precompute [*][1][*] */
	for (i = 1; i < 4; i++) {
		MP_CHECKOK(group->
				   point_add(&precomp[0][1][0], &precomp[0][1][1],
							 &precomp[i][0][0], &precomp[i][0][1],
							 &precomp[i][1][0], &precomp[i][1][1], group));
	}
	/* precompute [*][2][*] */
	MP_CHECKOK(group->
			   point_dbl(&precomp[0][1][0], &precomp[0][1][1],
						 &precomp[0][2][0], &precomp[0][2][1], group));
	for (i = 1; i < 4; i++) {
		MP_CHECKOK(group->
				   point_add(&precomp[0][2][0], &precomp[0][2][1],
							 &precomp[i][0][0], &precomp[i][0][1],
							 &precomp[i][2][0], &precomp[i][2][1], group));
	}
	/* precompute [*][3][*] */
	MP_CHECKOK(group->
			   point_add(&precomp[0][1][0], &precomp[0][1][1],
						 &precomp[0][2][0], &precomp[0][2][1],
						 &precomp[0][3][0], &precomp[0][3][1], group));
	for (i = 1; i < 4; i++) {
		MP_CHECKOK(group->
				   point_add(&precomp[0][3][0], &precomp[0][3][1],
							 &precomp[i][0][0], &precomp[i][0][1],
							 &precomp[i][3][0], &precomp[i][3][1], group));
	}

	d = (mpl_significant_bits(a) + 1) / 2;

	/* R = inf */
	MP_CHECKOK(mp_init(&rz));
	MP_CHECKOK(ec_GFp_pt_set_inf_jac(rx, ry, &rz));

        for (i = d; i-- > 0;) {
		ai = MP_GET_BIT(a, 2 * i + 1);
		ai <<= 1;
		ai |= MP_GET_BIT(a, 2 * i);
		bi = MP_GET_BIT(b, 2 * i + 1);
		bi <<= 1;
		bi |= MP_GET_BIT(b, 2 * i);
		/* R = 2^2 * R */
		MP_CHECKOK(ec_GFp_pt_dbl_jac(rx, ry, &rz, rx, ry, &rz, group));
		MP_CHECKOK(ec_GFp_pt_dbl_jac(rx, ry, &rz, rx, ry, &rz, group));
		/* R = R + (ai * A + bi * B) */
		MP_CHECKOK(ec_GFp_pt_add_jac_aff
				   (rx, ry, &rz, &precomp[ai][bi][0], &precomp[ai][bi][1],
					rx, ry, &rz, group));
	}

	MP_CHECKOK(ec_GFp_pt_jac2aff(rx, ry, &rz, rx, ry, group));

	if (group->meth->field_dec) {
		MP_CHECKOK(group->meth->field_dec(rx, rx, group->meth));
		MP_CHECKOK(group->meth->field_dec(ry, ry, group->meth));
	}

  CLEANUP:
	mp_clear(&rz);
	for (i = 0; i < 4; i++) {
		for (j = 0; j < 4; j++) {
			mp_clear(&precomp[i][j][0]);
			mp_clear(&precomp[i][j][1]);
		}
	}
	return res;
}
Example #24
0
/* Computes R = nP where R is (rx, ry) and P is (px, py). The parameters
 * a, b and p are the elliptic curve coefficients and the prime that
 * determines the field GFp.  Elliptic curve points P and R can be
 * identical.  Uses mixed Jacobian-affine coordinates. Assumes input is
 * already field-encoded using field_enc, and returns output that is still 
 * field-encoded. Uses 4-bit window method. */
mp_err
ec_GFp_pt_mul_jac(const mp_int *n, const mp_int *px, const mp_int *py,
				  mp_int *rx, mp_int *ry, const ECGroup *group)
{
	mp_err res = MP_OKAY;
	mp_int precomp[16][2], rz;
	int i, ni, d;

	MP_DIGITS(&rz) = 0;
	for (i = 0; i < 16; i++) {
		MP_DIGITS(&precomp[i][0]) = 0;
		MP_DIGITS(&precomp[i][1]) = 0;
	}

	ARGCHK(group != NULL, MP_BADARG);
	ARGCHK((n != NULL) && (px != NULL) && (py != NULL), MP_BADARG);

	/* initialize precomputation table */
	for (i = 0; i < 16; i++) {
		MP_CHECKOK(mp_init(&precomp[i][0]));
		MP_CHECKOK(mp_init(&precomp[i][1]));
	}

	/* fill precomputation table */
	mp_zero(&precomp[0][0]);
	mp_zero(&precomp[0][1]);
	MP_CHECKOK(mp_copy(px, &precomp[1][0]));
	MP_CHECKOK(mp_copy(py, &precomp[1][1]));
	for (i = 2; i < 16; i++) {
		MP_CHECKOK(group->
				   point_add(&precomp[1][0], &precomp[1][1],
							 &precomp[i - 1][0], &precomp[i - 1][1],
							 &precomp[i][0], &precomp[i][1], group));
	}

	d = (mpl_significant_bits(n) + 3) / 4;

	/* R = inf */
	MP_CHECKOK(mp_init(&rz));
	MP_CHECKOK(ec_GFp_pt_set_inf_jac(rx, ry, &rz));

	for (i = d - 1; i >= 0; i--) {
		/* compute window ni */
		ni = MP_GET_BIT(n, 4 * i + 3);
		ni <<= 1;
		ni |= MP_GET_BIT(n, 4 * i + 2);
		ni <<= 1;
		ni |= MP_GET_BIT(n, 4 * i + 1);
		ni <<= 1;
		ni |= MP_GET_BIT(n, 4 * i);
		/* R = 2^4 * R */
		MP_CHECKOK(ec_GFp_pt_dbl_jac(rx, ry, &rz, rx, ry, &rz, group));
		MP_CHECKOK(ec_GFp_pt_dbl_jac(rx, ry, &rz, rx, ry, &rz, group));
		MP_CHECKOK(ec_GFp_pt_dbl_jac(rx, ry, &rz, rx, ry, &rz, group));
		MP_CHECKOK(ec_GFp_pt_dbl_jac(rx, ry, &rz, rx, ry, &rz, group));
		/* R = R + (ni * P) */
		MP_CHECKOK(ec_GFp_pt_add_jac_aff
				   (rx, ry, &rz, &precomp[ni][0], &precomp[ni][1], rx, ry,
					&rz, group));
	}

	/* convert result S to affine coordinates */
	MP_CHECKOK(ec_GFp_pt_jac2aff(rx, ry, &rz, rx, ry, group));

  CLEANUP:
	mp_clear(&rz);
	for (i = 0; i < 16; i++) {
		mp_clear(&precomp[i][0]);
		mp_clear(&precomp[i][1]);
	}
	return res;
}
Example #25
0
mp_err mpp_make_prime(mp_int *start, mp_size nBits, mp_size strong,
		      unsigned long * nTries)
{
  mp_digit      np;
  mp_err        res;
  int           i	= 0;
  mp_int        trial;
  mp_int        q;
  mp_size       num_tests;
  unsigned char *sieve;
  
  ARGCHK(start != 0, MP_BADARG);
  ARGCHK(nBits > 16, MP_RANGE);

  sieve = malloc(SIEVE_SIZE);
  ARGCHK(sieve != NULL, MP_MEM);

  MP_DIGITS(&trial) = 0;
  MP_DIGITS(&q) = 0;
  MP_CHECKOK( mp_init(&trial) );
  MP_CHECKOK( mp_init(&q)     );
  /* values taken from table 4.4, HandBook of Applied Cryptography */
  if (nBits >= 1300) {
    num_tests = 2;
  } else if (nBits >= 850) {
    num_tests = 3;
  } else if (nBits >= 650) {
    num_tests = 4;
  } else if (nBits >= 550) {
    num_tests = 5;
  } else if (nBits >= 450) {
    num_tests = 6;
  } else if (nBits >= 400) {
    num_tests = 7;
  } else if (nBits >= 350) {
    num_tests = 8;
  } else if (nBits >= 300) {
    num_tests = 9;
  } else if (nBits >= 250) {
    num_tests = 12;
  } else if (nBits >= 200) {
    num_tests = 15;
  } else if (nBits >= 150) {
    num_tests = 18;
  } else if (nBits >= 100) {
    num_tests = 27;
  } else
    num_tests = 50;

  if (strong) 
    --nBits;
  MP_CHECKOK( mpl_set_bit(start, nBits - 1, 1) );
  MP_CHECKOK( mpl_set_bit(start,         0, 1) );
  for (i = mpl_significant_bits(start) - 1; i >= nBits; --i) {
    MP_CHECKOK( mpl_set_bit(start, i, 0) );
  }
  /* start sieveing with prime value of 3. */
  MP_CHECKOK(mpp_sieve(start, prime_tab + 1, prime_tab_size - 1, 
		       sieve, SIEVE_SIZE) );

#ifdef DEBUG_SIEVE
  res = 0;
  for (i = 0; i < SIEVE_SIZE; ++i) {
    if (!sieve[i])
      ++res;
  }
  fprintf(stderr,"sieve found %d potential primes.\n", res);
#define FPUTC(x,y) fputc(x,y)
#else
#define FPUTC(x,y) 
#endif

  res = MP_NO;
  for(i = 0; i < SIEVE_SIZE; ++i) {
    if (sieve[i])	/* this number is composite */
      continue;
    MP_CHECKOK( mp_add_d(start, 2 * i, &trial) );
    FPUTC('.', stderr);
    /* run a Fermat test */
    res = mpp_fermat(&trial, 2);
    if (res != MP_OKAY) {
      if (res == MP_NO)
	continue;	/* was composite */
      goto CLEANUP;
    }
      
    FPUTC('+', stderr);
    /* If that passed, run some Miller-Rabin tests	*/
    res = mpp_pprime(&trial, num_tests);
    if (res != MP_OKAY) {
      if (res == MP_NO)
	continue;	/* was composite */
      goto CLEANUP;
    }
    FPUTC('!', stderr);

    if (!strong) 
      break;	/* success !! */

    /* At this point, we have strong evidence that our candidate
       is itself prime.  If we want a strong prime, we need now
       to test q = 2p + 1 for primality...
     */
    MP_CHECKOK( mp_mul_2(&trial, &q) );
    MP_CHECKOK( mp_add_d(&q, 1, &q)  );

    /* Test q for small prime divisors ... */
    np = prime_tab_size;
    res = mpp_divis_primes(&q, &np);
    if (res == MP_YES) { /* is composite */
      mp_clear(&q);
      continue;
    }
    if (res != MP_NO) 
      goto CLEANUP;

    /* And test with Fermat, as with its parent ... */
    res = mpp_fermat(&q, 2);
    if (res != MP_YES) {
      mp_clear(&q);
      if (res == MP_NO)
	continue;	/* was composite */
      goto CLEANUP;
    }

    /* And test with Miller-Rabin, as with its parent ... */
    res = mpp_pprime(&q, num_tests);
    if (res != MP_YES) {
      mp_clear(&q);
      if (res == MP_NO)
	continue;	/* was composite */
      goto CLEANUP;
    }

    /* If it passed, we've got a winner */
    mp_exch(&q, &trial);
    mp_clear(&q);
    break;

  } /* end of loop through sieved values */
  if (res == MP_YES) 
    mp_exch(&trial, start);
CLEANUP:
  mp_clear(&trial);
  mp_clear(&q);
  if (nTries)
    *nTries += i;
  if (sieve != NULL) {
  	memset(sieve, 0, SIEVE_SIZE);
  	free (sieve);
  }
  return res;
}
Example #26
0
mp_err  mpp_pprime(mp_int *a, int nt)
{
  mp_err   res;
  mp_int   x, amo, m, z;	/* "amo" = "a minus one" */
  int      iter;
  unsigned int jx;
  mp_size  b;

  ARGCHK(a != NULL, MP_BADARG);

  MP_DIGITS(&x) = 0;
  MP_DIGITS(&amo) = 0;
  MP_DIGITS(&m) = 0;
  MP_DIGITS(&z) = 0;

  /* Initialize temporaries... */
  MP_CHECKOK( mp_init(&amo));
  /* Compute amo = a - 1 for what follows...    */
  MP_CHECKOK( mp_sub_d(a, 1, &amo) );

  b = mp_trailing_zeros(&amo);
  if (!b) { /* a was even ? */
    res = MP_NO;
    goto CLEANUP;
  }

  MP_CHECKOK( mp_init_size(&x, MP_USED(a)) );
  MP_CHECKOK( mp_init(&z) );
  MP_CHECKOK( mp_init(&m) );
  MP_CHECKOK( mp_div_2d(&amo, b, &m, 0) );

  /* Do the test nt times... */
  for(iter = 0; iter < nt; iter++) {

    /* Choose a random value for x < a          */
    s_mp_pad(&x, USED(a));
    mpp_random(&x);
    MP_CHECKOK( mp_mod(&x, a, &x) );

    /* Compute z = (x ** m) mod a               */
    MP_CHECKOK( mp_exptmod(&x, &m, a, &z) );
    
    if(mp_cmp_d(&z, 1) == 0 || mp_cmp(&z, &amo) == 0) {
      res = MP_YES;
      continue;
    }
    
    res = MP_NO;  /* just in case the following for loop never executes. */
    for (jx = 1; jx < b; jx++) {
      /* z = z^2 (mod a) */
      MP_CHECKOK( mp_sqrmod(&z, a, &z) );
      res = MP_NO;	/* previous line set res to MP_YES */

      if(mp_cmp_d(&z, 1) == 0) {
	break;
      }
      if(mp_cmp(&z, &amo) == 0) {
	res = MP_YES;
	break;
      } 
    } /* end testing loop */

    /* If the test passes, we will continue iterating, but a failed
       test means the candidate is definitely NOT prime, so we will
       immediately break out of this loop
     */
    if(res == MP_NO)
      break;

  } /* end iterations loop */
  
CLEANUP:
  mp_clear(&m);
  mp_clear(&z);
  mp_clear(&x);
  mp_clear(&amo);
  return res;

} /* end mpp_pprime() */
Example #27
0
/*
 * on some platforms character stores into memory is very expensive since they
 * generate a read/modify/write operation on the bus. On those platforms
 * we need to do integer writes to the bus. Because of some unrolled code,
 * in this current code the size of mp_weave_word must be four. The code that
 * makes this assumption explicity is called out. (on some platforms a write
 * of 4 bytes still requires a single read-modify-write operation.
 *
 * This function is takes the identical parameters as the function above, 
 * however it lays out the final array differently. Where the previous function
 * treats the mpi_int as an byte array, this function treats it as an array of
 * mp_digits where each digit is stored in big endian order.
 * 
 * since we need to interleave on a byte by byte basis, we need to collect 
 * several mpi structures together into a single uint32 before we write. We
 * also need to make sure the uint32 is arranged so that the first value of 
 * the first array winds up in b[0]. This means construction of that uint32
 * is endian specific (even though the layout of the mp_digits in the array 
 * is always big endian).
 *
 * The final data is stored as follows :
 *
 * Our same logical array p array, m is sizeof(mp_digit),
 * N is still count and n is now b_size. If we define p[i].digit[j]0 as the 
 * most significant byte of the word p[i].digit[j], p[i].digit[j]1 as 
 * the next most significant byte of p[i].digit[j], ...  and p[i].digit[j]m-1
 * is the least significant byte. 
 * Our array would look like:
 * p[0].digit[0]0     p[1].digit[0]0    ...  p[N-2].digit[0]0    p[N-1].digit[0]0
 * p[0].digit[0]1     p[1].digit[0]1    ...  p[N-2].digit[0]1    p[N-1].digit[0]1
 *                .                                         .
 * p[0].digit[0]m-1   p[1].digit[0]m-1  ...  p[N-2].digit[0]m-1  p[N-1].digit[0]m-1
 * p[0].digit[1]0     p[1].digit[1]0    ...  p[N-2].digit[1]0    p[N-1].digit[1]0
 *                .                                         .
 *                .                                         .
 * p[0].digit[n-1]m-2 p[1].digit[n-1]m-2 ... p[N-2].digit[n-1]m-2 p[N-1].digit[n-1]m-2
 * p[0].digit[n-1]m-1 p[1].digit[n-1]m-1 ... p[N-2].digit[n-1]m-1 p[N-1].digit[n-1]m-1 
 *
 */
mp_err mpi_to_weave(const mp_int *a, unsigned char *b, 
					mp_size b_size, mp_size count)
{
  mp_size i;
  mp_digit *digitsa0;
  mp_digit *digitsa1;
  mp_digit *digitsa2;
  mp_digit *digitsa3;
  mp_size   useda0;
  mp_size   useda1;
  mp_size   useda2;
  mp_size   useda3;
  mp_weave_word *weaved = (mp_weave_word *)b;

  count = count/sizeof(mp_weave_word);

  /* this code pretty much depends on this ! */
#if MP_ARGCHK == 2
  assert(WEAVE_WORD_SIZE == 4); 
  assert(sizeof(mp_weave_word) == 4);
#endif

  digitsa0 = MP_DIGITS(&a[0]);
  digitsa1 = MP_DIGITS(&a[1]);
  digitsa2 = MP_DIGITS(&a[2]);
  digitsa3 = MP_DIGITS(&a[3]);
  useda0 = MP_USED(&a[0]);
  useda1 = MP_USED(&a[1]);
  useda2 = MP_USED(&a[2]);
  useda3 = MP_USED(&a[3]);

  ARGCHK(MP_SIGN(&a[0]) == MP_ZPOS, MP_BADARG);
  ARGCHK(MP_SIGN(&a[1]) == MP_ZPOS, MP_BADARG);
  ARGCHK(MP_SIGN(&a[2]) == MP_ZPOS, MP_BADARG);
  ARGCHK(MP_SIGN(&a[3]) == MP_ZPOS, MP_BADARG);
  ARGCHK(useda0 <= b_size, MP_BADARG);
  ARGCHK(useda1 <= b_size, MP_BADARG);
  ARGCHK(useda2 <= b_size, MP_BADARG);
  ARGCHK(useda3 <= b_size, MP_BADARG);

#define SAFE_FETCH(digit, used, word) ((word) < (used) ? (digit[word]) : 0)

  for (i=0; i < b_size; i++) {
    mp_digit d0 = SAFE_FETCH(digitsa0,useda0,i);
    mp_digit d1 = SAFE_FETCH(digitsa1,useda1,i);
    mp_digit d2 = SAFE_FETCH(digitsa2,useda2,i);
    mp_digit d3 = SAFE_FETCH(digitsa3,useda3,i);
    register mp_weave_word acc;

/*
 * ONE_STEP takes the MSB of each of our current digits and places that
 * byte in the appropriate position for writing to the weaved array.
 *  On little endian:
 *   b3 b2 b1 b0
 *  On big endian:
 *   b0 b1 b2 b3
 *  When the data is written it would always wind up:
 *   b[0] = b0
 *   b[1] = b1
 *   b[2] = b2
 *   b[3] = b3
 *
 * Once we've written the MSB, we shift the whole digit up left one
 * byte, putting the Next Most Significant Byte in the MSB position,
 * so we we repeat the next one step that byte will be written.
 * NOTE: This code assumes sizeof(mp_weave_word) and MP_WEAVE_WORD_SIZE
 * is 4.
 */
#ifdef MP_IS_LITTLE_ENDIAN 
#define MPI_WEAVE_ONE_STEP \
    acc  = (d0 >> (MP_DIGIT_BIT-8))  & 0x000000ff; d0 <<= 8; /*b0*/ \
    acc |= (d1 >> (MP_DIGIT_BIT-16)) & 0x0000ff00; d1 <<= 8; /*b1*/ \
    acc |= (d2 >> (MP_DIGIT_BIT-24)) & 0x00ff0000; d2 <<= 8; /*b2*/ \
    acc |= (d3 >> (MP_DIGIT_BIT-32)) & 0xff000000; d3 <<= 8; /*b3*/ \
    *weaved = acc; weaved += count;
#else 
#define MPI_WEAVE_ONE_STEP \
    acc  = (d0 >> (MP_DIGIT_BIT-32)) & 0xff000000; d0 <<= 8; /*b0*/ \
    acc |= (d1 >> (MP_DIGIT_BIT-24)) & 0x00ff0000; d1 <<= 8; /*b1*/ \
    acc |= (d2 >> (MP_DIGIT_BIT-16)) & 0x0000ff00; d2 <<= 8; /*b2*/ \
    acc |= (d3 >> (MP_DIGIT_BIT-8))  & 0x000000ff; d3 <<= 8; /*b3*/ \
    *weaved = acc; weaved += count;
#endif 
   switch (sizeof(mp_digit)) {
   case 32:
    MPI_WEAVE_ONE_STEP
    MPI_WEAVE_ONE_STEP
    MPI_WEAVE_ONE_STEP
    MPI_WEAVE_ONE_STEP
    MPI_WEAVE_ONE_STEP
    MPI_WEAVE_ONE_STEP
    MPI_WEAVE_ONE_STEP
    MPI_WEAVE_ONE_STEP
    MPI_WEAVE_ONE_STEP
    MPI_WEAVE_ONE_STEP
    MPI_WEAVE_ONE_STEP
    MPI_WEAVE_ONE_STEP
    MPI_WEAVE_ONE_STEP
    MPI_WEAVE_ONE_STEP
    MPI_WEAVE_ONE_STEP
    MPI_WEAVE_ONE_STEP
   case 16:
    MPI_WEAVE_ONE_STEP
    MPI_WEAVE_ONE_STEP
    MPI_WEAVE_ONE_STEP
    MPI_WEAVE_ONE_STEP
    MPI_WEAVE_ONE_STEP
    MPI_WEAVE_ONE_STEP
    MPI_WEAVE_ONE_STEP
    MPI_WEAVE_ONE_STEP
   case 8:
    MPI_WEAVE_ONE_STEP
    MPI_WEAVE_ONE_STEP
    MPI_WEAVE_ONE_STEP
    MPI_WEAVE_ONE_STEP
   case 4:
    MPI_WEAVE_ONE_STEP
    MPI_WEAVE_ONE_STEP
   case 2:
    MPI_WEAVE_ONE_STEP
   case 1:
    MPI_WEAVE_ONE_STEP
    break;
   }
  }

  return MP_OKAY;
}
Example #28
0
/* Computes R = nP where R is (rx, ry) and P is (px, py). The parameters
 * a, b and p are the elliptic curve coefficients and the prime that
 * determines the field GFp.  Elliptic curve points P and R can be
 * identical.  Uses Jacobian coordinates. Uses 4-bit window method. */
mp_err
ec_GFp_point_mul_jac_4w_fp(const mp_int *n, const mp_int *px,
						   const mp_int *py, mp_int *rx, mp_int *ry,
						   const ECGroup *ecgroup)
{
	mp_err res = MP_OKAY;
	ecfp_jac_pt precomp[16], r;
	ecfp_aff_pt p;
	EC_group_fp *group;

	mp_int rz;
	int i, ni, d;

	ARGCHK(ecgroup != NULL, MP_BADARG);
	ARGCHK((n != NULL) && (px != NULL) && (py != NULL), MP_BADARG);

	group = (EC_group_fp *) ecgroup->extra1;
	MP_DIGITS(&rz) = 0;
	MP_CHECKOK(mp_init(&rz));

	/* init p, da */
	ecfp_i2fp(p.x, px, ecgroup);
	ecfp_i2fp(p.y, py, ecgroup);
	ecfp_i2fp(group->curvea, &ecgroup->curvea, ecgroup);

	/* Do precomputation */
	group->precompute_jac(precomp, &p, group);

	/* Do main body of calculations */
	d = (mpl_significant_bits(n) + 3) / 4;

	/* R = inf */
	for (i = 0; i < group->numDoubles; i++) {
		r.z[i] = 0;
	}

	for (i = d - 1; i >= 0; i--) {
		/* compute window ni */
		ni = MP_GET_BIT(n, 4 * i + 3);
		ni <<= 1;
		ni |= MP_GET_BIT(n, 4 * i + 2);
		ni <<= 1;
		ni |= MP_GET_BIT(n, 4 * i + 1);
		ni <<= 1;
		ni |= MP_GET_BIT(n, 4 * i);

		/* R = 2^4 * R */
		group->pt_dbl_jac(&r, &r, group);
		group->pt_dbl_jac(&r, &r, group);
		group->pt_dbl_jac(&r, &r, group);
		group->pt_dbl_jac(&r, &r, group);

		/* R = R + (ni * P) */
		group->pt_add_jac(&r, &precomp[ni], &r, group);
	}

	/* Convert back to integer */
	ecfp_fp2i(rx, r.x, ecgroup);
	ecfp_fp2i(ry, r.y, ecgroup);
	ecfp_fp2i(&rz, r.z, ecgroup);

	/* convert result S to affine coordinates */
	MP_CHECKOK(ec_GFp_pt_jac2aff(rx, ry, &rz, rx, ry, ecgroup));

  CLEANUP:
	mp_clear(&rz);
	return res;
}