Exemple #1
0
/* computes T = REDC(T), 2^b == R */
mp_err s_mp_redc(mp_int *T, mp_mont_modulus *mmm)
{
  mp_err res;
  mp_size i;

  i = MP_USED(T) + MP_USED(&mmm->N) + 2;
  MP_CHECKOK( s_mp_pad(T, i) );
  for (i = 0; i < MP_USED(&mmm->N); ++i ) {
    mp_digit m_i = MP_DIGIT(T, i) * mmm->n0prime;
    /* T += N * m_i * (MP_RADIX ** i); */
    MP_CHECKOK( s_mp_mul_d_add_offset(&mmm->N, m_i, T, i) );
  }
  s_mp_clamp(T);

  /* T /= R */
  s_mp_div_2d(T, mmm->b); 

  if ((res = s_mp_cmp(T, &mmm->N)) >= 0) {
    /* T = T - N */
    MP_CHECKOK( s_mp_sub(T, &mmm->N) );
#ifdef DEBUG
    if ((res = mp_cmp(T, &mmm->N)) >= 0) {
      res = MP_UNDEF;
      goto CLEANUP;
    }
#endif
  }
  res = MP_OKAY;
CLEANUP:
  return res;
}
Exemple #2
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;
}
Exemple #3
0
int main(int argc, char *argv[])
{
    instant_t    start, finish;
    mp_int       prime, gen, expt, res;
    unsigned int ix, diff;
    int          num;

    srand(time(NULL));

    if(argc < 2) {
        fprintf(stderr, "Usage: %s <num-tests>\n", argv[0]);
        return 1;
    }

    if((num = atoi(argv[1])) < 0)
        num = -num;

    if(num == 0)
        ++num;

    mp_init(&prime);
    mp_init(&gen);
    mp_init(&res);
    mp_read_radix(&prime, g_prime, 16);
    mp_read_radix(&gen, g_gen, 16);

    mp_init_size(&expt, USED(&prime) - 1);
    s_mp_pad(&expt, USED(&prime) - 1);

    printf("Testing %d modular exponentations ... \n", num);

    start = now();
    for(ix = 0; ix < num; ix++) {
        mpp_random(&expt);
        mp_exptmod(&gen, &expt, &prime, &res);
    }
    finish = now();

    diff = (finish.sec - start.sec) * 1000000;
    diff += finish.usec;
    diff -= start.usec;

    printf("%d operations took %u usec (%.3f sec)\n",
           num, diff, (double)diff / 1000000.0);
    printf("That is %.3f sec per operation.\n",
           ((double)diff / 1000000.0) / num);

    mp_clear(&expt);
    mp_clear(&res);
    mp_clear(&gen);
    mp_clear(&prime);

    return 0;
}
Exemple #4
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() */
Exemple #5
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;

} 
Exemple #6
0
int main(int argc, char *argv[])
{
  int        ix, num, prec = 8;
  unsigned   int d;
  instant_t  start, finish;
  time_t     seed;
  mp_int     a, m, c;

  seed = time(NULL);

  if(argc < 2) {
    fprintf(stderr, "Usage: %s <num-tests> [<precision>]\n", argv[0]);
    return 1;
  }

  if((num = atoi(argv[1])) < 0)
    num = -num;

  if(!num) {
    fprintf(stderr, "%s: must perform at least 1 test\n", argv[0]);
    return 1;
  }

  if(argc > 2) {
    if((prec = atoi(argv[2])) <= 0)
      prec = 8;
  }
  
  printf("Test 3a: Modular exponentiation timing test\n"
	 "Precision:  %d digits (%d bits)\n"
	 "# of tests: %d\n\n", prec, prec * DIGIT_BIT, num);

  mp_init_size(&a, prec);
  mp_init_size(&m, prec);
  mp_init_size(&c, prec);
  s_mp_pad(&a, prec);
  s_mp_pad(&m, prec);
  s_mp_pad(&c, prec);

  printf("Testing modular exponentiation ... \n");
  srand((unsigned int)seed);

  start = now();
  for(ix = 0; ix < num; ix++) {
    mpp_random(&a);
    mpp_random(&c);
    mpp_random(&m);
    mp_exptmod(&a, &c, &m, &c);
  }
  finish = now();

  d = (finish.sec - start.sec) * 1000000;
  d -= start.usec; d += finish.usec;

  printf("Total time elapsed:        %u usec\n", d);
  printf("Time per exponentiation:   %u usec (%.3f sec)\n", 
	 (d / num), (double)(d / num) / 1000000);

  mp_clear(&c);
  mp_clear(&a);
  mp_clear(&m);

  return 0;
}
Exemple #7
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() */
Exemple #8
0
/* Do modular exponentiation using floating point multiply code. */
mp_err mp_exptmod_f(const mp_int *   montBase, 
                    const mp_int *   exponent, 
		    const mp_int *   modulus, 
		    mp_int *         result, 
		    mp_mont_modulus *mmm, 
		    int              nLen, 
		    mp_size          bits_in_exponent, 
		    mp_size          window_bits,
		    mp_size          odd_ints)
{
  mp_digit *mResult;
  double   *dBuf = 0, *dm1, *dn, *dSqr, *d16Tmp, *dTmp;
  double    dn0;
  mp_size   i;
  mp_err    res;
  int       expOff;
  int       dSize = 0, oddPowSize, dTmpSize;
  mp_int    accum1;
  double   *oddPowers[MAX_ODD_INTS];

  /* function for computing n0prime only works if n0 is odd */

  MP_DIGITS(&accum1) = 0;

  for (i = 0; i < MAX_ODD_INTS; ++i)
    oddPowers[i] = 0;

  MP_CHECKOK( mp_init_size(&accum1, 3 * nLen + 2) );

  mp_set(&accum1, 1);
  MP_CHECKOK( s_mp_to_mont(&accum1, mmm, &accum1) );
  MP_CHECKOK( s_mp_pad(&accum1, nLen) );

  oddPowSize = 2 * nLen + 1;
  dTmpSize   = 2 * oddPowSize;
  dSize = sizeof(double) * (nLen * 4 + 1 + 
			    ((odd_ints + 1) * oddPowSize) + dTmpSize);
  dBuf   = (double *)malloc(dSize);
  dm1    = dBuf;		/* array of d32 */
  dn     = dBuf   + nLen;	/* array of d32 */
  dSqr   = dn     + nLen;    	/* array of d32 */
  d16Tmp = dSqr   + nLen;	/* array of d16 */
  dTmp   = d16Tmp + oddPowSize;

  for (i = 0; i < odd_ints; ++i) {
      oddPowers[i] = dTmp;
      dTmp += oddPowSize;
  }
  mResult = (mp_digit *)(dTmp + dTmpSize);	/* size is nLen + 1 */

  /* Make dn and dn0 */
  conv_i32_to_d32(dn, MP_DIGITS(modulus), nLen);
  dn0 = (double)(mmm->n0prime & 0xffff);

  /* Make dSqr */
  conv_i32_to_d32_and_d16(dm1, oddPowers[0], MP_DIGITS(montBase), nLen);
  mont_mulf_noconv(mResult, dm1, oddPowers[0], 
		   dTmp, dn, MP_DIGITS(modulus), nLen, dn0);
  conv_i32_to_d32(dSqr, mResult, nLen);

  for (i = 1; i < odd_ints; ++i) {
    mont_mulf_noconv(mResult, dSqr, oddPowers[i - 1], 
		     dTmp, dn, MP_DIGITS(modulus), nLen, dn0);
    conv_i32_to_d16(oddPowers[i], mResult, nLen);
  }

  s_mp_copy(MP_DIGITS(&accum1), mResult, nLen); /* from, to, len */

  for (expOff = bits_in_exponent - window_bits; expOff >= 0; expOff -= window_bits) {
    mp_size smallExp;
    MP_CHECKOK( mpl_get_bits(exponent, expOff, window_bits) );
    smallExp = (mp_size)res;

    if (window_bits == 1) {
      if (!smallExp) {
	SQR;
      } else if (smallExp & 1) {
	SQR; MUL(0); 
      } else {
	ABORT;
      }
    } else if (window_bits == 4) {
      if (!smallExp) {
	SQR; SQR; SQR; SQR;
      } else if (smallExp & 1) {
	SQR; SQR; SQR; SQR; MUL(smallExp/2); 
      } else if (smallExp & 2) {
	SQR; SQR; SQR; MUL(smallExp/4); SQR; 
      } else if (smallExp & 4) {
	SQR; SQR; MUL(smallExp/8); SQR; SQR; 
      } else if (smallExp & 8) {
	SQR; MUL(smallExp/16); SQR; SQR; SQR; 
      } else {
	ABORT;
      }
    } else if (window_bits == 5) {
      if (!smallExp) {
	SQR; SQR; SQR; SQR; SQR; 
      } else if (smallExp & 1) {
	SQR; SQR; SQR; SQR; SQR; MUL(smallExp/2);
      } else if (smallExp & 2) {
	SQR; SQR; SQR; SQR; MUL(smallExp/4); SQR;
      } else if (smallExp & 4) {
	SQR; SQR; SQR; MUL(smallExp/8); SQR; SQR;
      } else if (smallExp & 8) {
	SQR; SQR; MUL(smallExp/16); SQR; SQR; SQR;
      } else if (smallExp & 0x10) {
	SQR; MUL(smallExp/32); SQR; SQR; SQR; SQR;
      } else {
	ABORT;
      }
    } else if (window_bits == 6) {
      if (!smallExp) {
	SQR; SQR; SQR; SQR; SQR; SQR;
      } else if (smallExp & 1) {
	SQR; SQR; SQR; SQR; SQR; SQR; MUL(smallExp/2); 
      } else if (smallExp & 2) {
	SQR; SQR; SQR; SQR; SQR; MUL(smallExp/4); SQR; 
      } else if (smallExp & 4) {
	SQR; SQR; SQR; SQR; MUL(smallExp/8); SQR; SQR; 
      } else if (smallExp & 8) {
	SQR; SQR; SQR; MUL(smallExp/16); SQR; SQR; SQR; 
      } else if (smallExp & 0x10) {
	SQR; SQR; MUL(smallExp/32); SQR; SQR; SQR; SQR; 
      } else if (smallExp & 0x20) {
	SQR; MUL(smallExp/64); SQR; SQR; SQR; SQR; SQR; 
      } else {
	ABORT;
      }
    } else {
      ABORT;
    }
  }

  s_mp_copy(mResult, MP_DIGITS(&accum1), nLen); /* from, to, len */

  res = s_mp_redc(&accum1, mmm);
  mp_exch(&accum1, result);

CLEANUP:
  mp_clear(&accum1);
  if (dBuf) {
    if (dSize)
      memset(dBuf, 0, dSize);
    free(dBuf);
  }

  return res;
}
Exemple #9
0
mp_err mp_exptmod(const mp_int *inBase, const mp_int *exponent, 
		  const mp_int *modulus, mp_int *result)
{
  const mp_int *base;
  mp_size bits_in_exponent, i, window_bits, odd_ints;
  mp_err  res;
  int     nLen;
  mp_int  montBase, goodBase;
  mp_mont_modulus mmm;
#ifdef MP_USING_CACHE_SAFE_MOD_EXP
  static unsigned int max_window_bits;
#endif

  /* function for computing n0prime only works if n0 is odd */
  if (!mp_isodd(modulus))
    return s_mp_exptmod(inBase, exponent, modulus, result);

  MP_DIGITS(&montBase) = 0;
  MP_DIGITS(&goodBase) = 0;

  if (mp_cmp(inBase, modulus) < 0) {
    base = inBase;
  } else {
    MP_CHECKOK( mp_init(&goodBase) );
    base = &goodBase;
    MP_CHECKOK( mp_mod(inBase, modulus, &goodBase) );
  }

  nLen  = MP_USED(modulus);
  MP_CHECKOK( mp_init_size(&montBase, 2 * nLen + 2) );

  mmm.N = *modulus;			/* a copy of the mp_int struct */

  /* compute n0', given n0, n0' = -(n0 ** -1) mod MP_RADIX
  **		where n0 = least significant mp_digit of N, the modulus.
  */
  mmm.n0prime = 0 - s_mp_invmod_radix( MP_DIGIT(modulus, 0) );

  MP_CHECKOK( s_mp_to_mont(base, &mmm, &montBase) );

  bits_in_exponent = mpl_significant_bits(exponent);
#ifdef MP_USING_CACHE_SAFE_MOD_EXP
  if (mp_using_cache_safe_exp) {
    if (bits_in_exponent > 780)
	window_bits = 6;
    else if (bits_in_exponent > 256)
	window_bits = 5;
    else if (bits_in_exponent > 20)
	window_bits = 4;
       /* RSA public key exponents are typically under 20 bits (common values 
        * are: 3, 17, 65537) and a 4-bit window is inefficient
        */
    else 
	window_bits = 1;
  } else
#endif
  if (bits_in_exponent > 480)
    window_bits = 6;
  else if (bits_in_exponent > 160)
    window_bits = 5;
  else if (bits_in_exponent > 20)
    window_bits = 4;
  /* RSA public key exponents are typically under 20 bits (common values 
   * are: 3, 17, 65537) and a 4-bit window is inefficient
   */
  else 
    window_bits = 1;

#ifdef MP_USING_CACHE_SAFE_MOD_EXP
  /*
   * clamp the window size based on
   * the cache line size.
   */
  if (!max_window_bits) {
    unsigned long cache_size = s_mpi_getProcessorLineSize();
    /* processor has no cache, use 'fast' code always */
    if (cache_size == 0) {
      mp_using_cache_safe_exp = 0;
    } 
    if ((cache_size == 0) || (cache_size >= 64)) {
      max_window_bits = 6;
    } else if (cache_size >= 32) {
      max_window_bits = 5;
    } else if (cache_size >= 16) {
      max_window_bits = 4;
    } else max_window_bits = 1; /* should this be an assert? */
  }

  /* clamp the window size down before we caclulate bits_in_exponent */
  if (mp_using_cache_safe_exp) {
    if (window_bits > max_window_bits) {
      window_bits = max_window_bits;
    }
  }
#endif

  odd_ints = 1 << (window_bits - 1);
  i = bits_in_exponent % window_bits;
  if (i != 0) {
    bits_in_exponent += window_bits - i;
  } 

#ifdef MP_USING_MONT_MULF
  if (mp_using_mont_mulf) {
    MP_CHECKOK( s_mp_pad(&montBase, nLen) );
    res = mp_exptmod_f(&montBase, exponent, modulus, result, &mmm, nLen, 
		     bits_in_exponent, window_bits, odd_ints);
  } else
#endif
#ifdef MP_USING_CACHE_SAFE_MOD_EXP
  if (mp_using_cache_safe_exp) {
    res = mp_exptmod_safe_i(&montBase, exponent, modulus, result, &mmm, nLen, 
		     bits_in_exponent, window_bits, 1 << window_bits);
  } else
#endif
  res = mp_exptmod_i(&montBase, exponent, modulus, result, &mmm, nLen, 
		     bits_in_exponent, window_bits, odd_ints);

CLEANUP:
  mp_clear(&montBase);
  mp_clear(&goodBase);
  /* Don't mp_clear mmm.N because it is merely a copy of modulus.
  ** Just zap it.
  */
  memset(&mmm, 0, sizeof mmm);
  return res;
}
Exemple #10
0
/* 6 words */
mp_err
ec_GFp_sub_6(const mp_int *a, const mp_int *b, mp_int *r,
             const GFMethod *meth)
{
    mp_err res = MP_OKAY;
    mp_digit b0 = 0, b1 = 0, b2 = 0, b3 = 0, b4 = 0, b5 = 0;
    mp_digit r0 = 0, r1 = 0, r2 = 0, r3 = 0, r4 = 0, r5 = 0;
    mp_digit borrow;

    switch (MP_USED(a)) {
        case 6:
            r5 = MP_DIGIT(a, 5);
        case 5:
            r4 = MP_DIGIT(a, 4);
        case 4:
            r3 = MP_DIGIT(a, 3);
        case 3:
            r2 = MP_DIGIT(a, 2);
        case 2:
            r1 = MP_DIGIT(a, 1);
        case 1:
            r0 = MP_DIGIT(a, 0);
    }
    switch (MP_USED(b)) {
        case 6:
            b5 = MP_DIGIT(b, 5);
        case 5:
            b4 = MP_DIGIT(b, 4);
        case 4:
            b3 = MP_DIGIT(b, 3);
        case 3:
            b2 = MP_DIGIT(b, 2);
        case 2:
            b1 = MP_DIGIT(b, 1);
        case 1:
            b0 = MP_DIGIT(b, 0);
    }

    borrow = 0;
    MP_SUB_BORROW(r0, b0, r0, borrow);
    MP_SUB_BORROW(r1, b1, r1, borrow);
    MP_SUB_BORROW(r2, b2, r2, borrow);
    MP_SUB_BORROW(r3, b3, r3, borrow);
    MP_SUB_BORROW(r4, b4, r4, borrow);
    MP_SUB_BORROW(r5, b5, r5, borrow);

    /* Do quick 'add' if we've gone under 0
     * (subtract the 2's complement of the curve field) */
    if (borrow) {
        b5 = MP_DIGIT(&meth->irr, 5);
        b4 = MP_DIGIT(&meth->irr, 4);
        b3 = MP_DIGIT(&meth->irr, 3);
        b2 = MP_DIGIT(&meth->irr, 2);
        b1 = MP_DIGIT(&meth->irr, 1);
        b0 = MP_DIGIT(&meth->irr, 0);
        borrow = 0;
        MP_ADD_CARRY(b0, r0, r0, borrow);
        MP_ADD_CARRY(b1, r1, r1, borrow);
        MP_ADD_CARRY(b2, r2, r2, borrow);
        MP_ADD_CARRY(b3, r3, r3, borrow);
        MP_ADD_CARRY(b4, r4, r4, borrow);
        MP_ADD_CARRY(b5, r5, r5, borrow);
    }

    MP_CHECKOK(s_mp_pad(r, 6));
    MP_DIGIT(r, 5) = r5;
    MP_DIGIT(r, 4) = r4;
    MP_DIGIT(r, 3) = r3;
    MP_DIGIT(r, 2) = r2;
    MP_DIGIT(r, 1) = r1;
    MP_DIGIT(r, 0) = r0;
    MP_SIGN(r) = MP_ZPOS;
    MP_USED(r) = 6;
    s_mp_clamp(r);

CLEANUP:
    return res;
}
Exemple #11
0
/* 4 words */
mp_err
ec_GFp_sub_4(const mp_int *a, const mp_int *b, mp_int *r,
             const GFMethod *meth)
{
    mp_err res = MP_OKAY;
    mp_digit b0 = 0, b1 = 0, b2 = 0, b3 = 0;
    mp_digit r0 = 0, r1 = 0, r2 = 0, r3 = 0;
    mp_digit borrow;

    switch (MP_USED(a)) {
        case 4:
            r3 = MP_DIGIT(a, 3);
        case 3:
            r2 = MP_DIGIT(a, 2);
        case 2:
            r1 = MP_DIGIT(a, 1);
        case 1:
            r0 = MP_DIGIT(a, 0);
    }
    switch (MP_USED(b)) {
        case 4:
            b3 = MP_DIGIT(b, 3);
        case 3:
            b2 = MP_DIGIT(b, 2);
        case 2:
            b1 = MP_DIGIT(b, 1);
        case 1:
            b0 = MP_DIGIT(b, 0);
    }

#ifndef MPI_AMD64_ADD
    borrow = 0;
    MP_SUB_BORROW(r0, b0, r0, borrow);
    MP_SUB_BORROW(r1, b1, r1, borrow);
    MP_SUB_BORROW(r2, b2, r2, borrow);
    MP_SUB_BORROW(r3, b3, r3, borrow);
#else
    __asm__(
        "xorq   %4,%4           \n\t"
        "subq   %5,%0           \n\t"
        "sbbq   %6,%1           \n\t"
        "sbbq   %7,%2           \n\t"
        "sbbq   %8,%3           \n\t"
        "adcq   $0,%4           \n\t"
        : "=r"(r0), "=r"(r1), "=r"(r2), "=r"(r3), "=r"(borrow)
        : "r"(b0), "r"(b1), "r"(b2), "r"(b3),
          "0"(r0), "1"(r1), "2"(r2), "3"(r3)
        : "%cc");
#endif

    /* Do quick 'add' if we've gone under 0
     * (subtract the 2's complement of the curve field) */
    if (borrow) {
        b3 = MP_DIGIT(&meth->irr, 3);
        b2 = MP_DIGIT(&meth->irr, 2);
        b1 = MP_DIGIT(&meth->irr, 1);
        b0 = MP_DIGIT(&meth->irr, 0);
#ifndef MPI_AMD64_ADD
        borrow = 0;
        MP_ADD_CARRY(b0, r0, r0, borrow);
        MP_ADD_CARRY(b1, r1, r1, borrow);
        MP_ADD_CARRY(b2, r2, r2, borrow);
        MP_ADD_CARRY(b3, r3, r3, borrow);
#else
        __asm__(
            "addq   %4,%0           \n\t"
            "adcq   %5,%1           \n\t"
            "adcq   %6,%2           \n\t"
            "adcq   %7,%3           \n\t"
            : "=r"(r0), "=r"(r1), "=r"(r2), "=r"(r3)
            : "r"(b0), "r"(b1), "r"(b2), "r"(b3),
              "0"(r0), "1"(r1), "2"(r2), "3"(r3)
            : "%cc");
#endif
    }
#ifdef MPI_AMD64_ADD
    /* compiler fakeout? */
    if ((r3 == b0) && (r1 == b0) && (r0 == b0)) {
        MP_CHECKOK(s_mp_pad(r, 4));
    }
#endif
    MP_CHECKOK(s_mp_pad(r, 4));
    MP_DIGIT(r, 3) = r3;
    MP_DIGIT(r, 2) = r2;
    MP_DIGIT(r, 1) = r1;
    MP_DIGIT(r, 0) = r0;
    MP_SIGN(r) = MP_ZPOS;
    MP_USED(r) = 4;
    s_mp_clamp(r);

CLEANUP:
    return res;
}
Exemple #12
0
/* 6 words */
mp_err
ec_GFp_add_6(const mp_int *a, const mp_int *b, mp_int *r,
             const GFMethod *meth)
{
    mp_err res = MP_OKAY;
    mp_digit a0 = 0, a1 = 0, a2 = 0, a3 = 0, a4 = 0, a5 = 0;
    mp_digit r0 = 0, r1 = 0, r2 = 0, r3 = 0, r4 = 0, r5 = 0;
    mp_digit carry;

    switch (MP_USED(a)) {
        case 6:
            a5 = MP_DIGIT(a, 5);
        case 5:
            a4 = MP_DIGIT(a, 4);
        case 4:
            a3 = MP_DIGIT(a, 3);
        case 3:
            a2 = MP_DIGIT(a, 2);
        case 2:
            a1 = MP_DIGIT(a, 1);
        case 1:
            a0 = MP_DIGIT(a, 0);
    }
    switch (MP_USED(b)) {
        case 6:
            r5 = MP_DIGIT(b, 5);
        case 5:
            r4 = MP_DIGIT(b, 4);
        case 4:
            r3 = MP_DIGIT(b, 3);
        case 3:
            r2 = MP_DIGIT(b, 2);
        case 2:
            r1 = MP_DIGIT(b, 1);
        case 1:
            r0 = MP_DIGIT(b, 0);
    }

    carry = 0;
    MP_ADD_CARRY(a0, r0, r0, carry);
    MP_ADD_CARRY(a1, r1, r1, carry);
    MP_ADD_CARRY(a2, r2, r2, carry);
    MP_ADD_CARRY(a3, r3, r3, carry);
    MP_ADD_CARRY(a4, r4, r4, carry);
    MP_ADD_CARRY(a5, r5, r5, carry);

    MP_CHECKOK(s_mp_pad(r, 6));
    MP_DIGIT(r, 5) = r5;
    MP_DIGIT(r, 4) = r4;
    MP_DIGIT(r, 3) = r3;
    MP_DIGIT(r, 2) = r2;
    MP_DIGIT(r, 1) = r1;
    MP_DIGIT(r, 0) = r0;
    MP_SIGN(r) = MP_ZPOS;
    MP_USED(r) = 6;

    /* Do quick 'subract' if we've gone over
     * (add the 2's complement of the curve field) */
    a5 = MP_DIGIT(&meth->irr, 5);
    if (carry || r5 > a5 ||
        ((r5 == a5) && mp_cmp(r, &meth->irr) != MP_LT)) {
        a4 = MP_DIGIT(&meth->irr, 4);
        a3 = MP_DIGIT(&meth->irr, 3);
        a2 = MP_DIGIT(&meth->irr, 2);
        a1 = MP_DIGIT(&meth->irr, 1);
        a0 = MP_DIGIT(&meth->irr, 0);
        carry = 0;
        MP_SUB_BORROW(r0, a0, r0, carry);
        MP_SUB_BORROW(r1, a1, r1, carry);
        MP_SUB_BORROW(r2, a2, r2, carry);
        MP_SUB_BORROW(r3, a3, r3, carry);
        MP_SUB_BORROW(r4, a4, r4, carry);
        MP_SUB_BORROW(r5, a5, r5, carry);
        MP_DIGIT(r, 5) = r5;
        MP_DIGIT(r, 4) = r4;
        MP_DIGIT(r, 3) = r3;
        MP_DIGIT(r, 2) = r2;
        MP_DIGIT(r, 1) = r1;
        MP_DIGIT(r, 0) = r0;
    }

    s_mp_clamp(r);

CLEANUP:
    return res;
}
Exemple #13
0
/* 4 words */
mp_err
ec_GFp_add_4(const mp_int *a, const mp_int *b, mp_int *r,
             const GFMethod *meth)
{
    mp_err res = MP_OKAY;
    mp_digit a0 = 0, a1 = 0, a2 = 0, a3 = 0;
    mp_digit r0 = 0, r1 = 0, r2 = 0, r3 = 0;
    mp_digit carry;

    switch (MP_USED(a)) {
        case 4:
            a3 = MP_DIGIT(a, 3);
        case 3:
            a2 = MP_DIGIT(a, 2);
        case 2:
            a1 = MP_DIGIT(a, 1);
        case 1:
            a0 = MP_DIGIT(a, 0);
    }
    switch (MP_USED(b)) {
        case 4:
            r3 = MP_DIGIT(b, 3);
        case 3:
            r2 = MP_DIGIT(b, 2);
        case 2:
            r1 = MP_DIGIT(b, 1);
        case 1:
            r0 = MP_DIGIT(b, 0);
    }

#ifndef MPI_AMD64_ADD
    carry = 0;
    MP_ADD_CARRY(a0, r0, r0, carry);
    MP_ADD_CARRY(a1, r1, r1, carry);
    MP_ADD_CARRY(a2, r2, r2, carry);
    MP_ADD_CARRY(a3, r3, r3, carry);
#else
    __asm__(
        "xorq   %4,%4           \n\t"
        "addq   %5,%0           \n\t"
        "adcq   %6,%1           \n\t"
        "adcq   %7,%2           \n\t"
        "adcq   %8,%3           \n\t"
        "adcq   $0,%4           \n\t"
        : "=r"(r0), "=r"(r1), "=r"(r2), "=r"(r3), "=r"(carry)
        : "r"(a0), "r"(a1), "r"(a2), "r"(a3),
          "0"(r0), "1"(r1), "2"(r2), "3"(r3)
        : "%cc");
#endif

    MP_CHECKOK(s_mp_pad(r, 4));
    MP_DIGIT(r, 3) = r3;
    MP_DIGIT(r, 2) = r2;
    MP_DIGIT(r, 1) = r1;
    MP_DIGIT(r, 0) = r0;
    MP_SIGN(r) = MP_ZPOS;
    MP_USED(r) = 4;

    /* Do quick 'subract' if we've gone over
     * (add the 2's complement of the curve field) */
    a3 = MP_DIGIT(&meth->irr, 3);
    if (carry || r3 > a3 ||
        ((r3 == a3) && mp_cmp(r, &meth->irr) != MP_LT)) {
        a2 = MP_DIGIT(&meth->irr, 2);
        a1 = MP_DIGIT(&meth->irr, 1);
        a0 = MP_DIGIT(&meth->irr, 0);
#ifndef MPI_AMD64_ADD
        carry = 0;
        MP_SUB_BORROW(r0, a0, r0, carry);
        MP_SUB_BORROW(r1, a1, r1, carry);
        MP_SUB_BORROW(r2, a2, r2, carry);
        MP_SUB_BORROW(r3, a3, r3, carry);
#else
        __asm__(
            "subq   %4,%0           \n\t"
            "sbbq   %5,%1           \n\t"
            "sbbq   %6,%2           \n\t"
            "sbbq   %7,%3           \n\t"
            : "=r"(r0), "=r"(r1), "=r"(r2), "=r"(r3)
            : "r"(a0), "r"(a1), "r"(a2), "r"(a3),
              "0"(r0), "1"(r1), "2"(r2), "3"(r3)
            : "%cc");
#endif
        MP_DIGIT(r, 3) = r3;
        MP_DIGIT(r, 2) = r2;
        MP_DIGIT(r, 1) = r1;
        MP_DIGIT(r, 0) = r0;
    }