Пример #1
0
/* R = X mod M

   Using Barrett reduction.  Before using this function
   _gcry_mpi_barrett_init must have been called to do the
   precalculations.  CTX is the context created by this precalculation
   and also conveys M.  If the Barret reduction could no be done a
   straightforward reduction method is used.

   We assume that these conditions are met:
   Input:  x =(x_2k-1 ...x_0)_b
 	   m =(m_k-1 ....m_0)_b	  with m_k-1 != 0
   Output: r = x mod m
 */
void
_gcry_mpi_mod_barrett (gcry_mpi_t r, gcry_mpi_t x, mpi_barrett_t ctx)
{
  gcry_mpi_t m = ctx->m;
  int k = ctx->k;
  gcry_mpi_t y = ctx->y;
  gcry_mpi_t r1 = ctx->r1;
  gcry_mpi_t r2 = ctx->r2;
  int sign;

  mpi_normalize (x);
  if (mpi_get_nlimbs (x) > 2*k )
    {
      mpi_mod (r, x, m);
      return;
    }

  sign = x->sign;
  x->sign = 0;

  /* 1. q1 = floor( x / b^k-1)
   *    q2 = q1 * y
   *    q3 = floor( q2 / b^k+1 )
   * Actually, we don't need qx, we can work direct on r2
   */
  mpi_set ( r2, x );
  mpi_rshift_limbs ( r2, k-1 );
  mpi_mul ( r2, r2, y );
  mpi_rshift_limbs ( r2, k+1 );

  /* 2. r1 = x mod b^k+1
   *	r2 = q3 * m mod b^k+1
   *	r  = r1 - r2
   * 3. if r < 0 then  r = r + b^k+1
   */
  mpi_set ( r1, x );
  if ( r1->nlimbs > k+1 ) /* Quick modulo operation.  */
    r1->nlimbs = k+1;
  mpi_mul ( r2, r2, m );
  if ( r2->nlimbs > k+1 ) /* Quick modulo operation. */
    r2->nlimbs = k+1;
  mpi_sub ( r, r1, r2 );

  if ( mpi_has_sign ( r ) )
    {
      if (!ctx->r3)
        {
          ctx->r3 = mpi_alloc ( k + 2 );
          mpi_set_ui (ctx->r3, 1);
          mpi_lshift_limbs (ctx->r3, k + 1 );
        }
      mpi_add ( r, r, ctx->r3 );
    }

  /* 4. while r >= m do r = r - m */
  while ( mpi_cmp( r, m ) >= 0 )
    mpi_sub ( r, r, m );

  x->sign = sign;
}
Пример #2
0
/****************
 * Barrett reduction: We assume that these conditions are met:
 * Given x =(x_2k-1 ...x_0)_b
 *	 m =(m_k-1 ....m_0)_b	  with m_k-1 != 0
 * Output r = x mod m
 * Before using this function init_barret must be used to calucalte y and k.
 * Returns: false = no error
 *	    true = can't perform barret reduction
 */
static int
calc_barrett( gcry_mpi_t r, gcry_mpi_t x, gcry_mpi_t m, gcry_mpi_t y, int k, gcry_mpi_t r1, gcry_mpi_t r2 )
{
    int xx = k > 3 ? k-3:0;

    mpi_normalize( x );
    if( mpi_get_nlimbs(x) > 2*k )
	return 1; /* can't do it */

    /* 1. q1 = floor( x / b^k-1)
     *	  q2 = q1 * y
     *	  q3 = floor( q2 / b^k+1 )
     * Actually, we don't need qx, we can work direct on r2
     */
    mpi_set( r2, x );
    mpi_rshift_limbs( r2, k-1 );
    mpi_mul( r2, r2, y );
    mpi_rshift_limbs( r2, k+1 );

    /* 2. r1 = x mod b^k+1
     *	  r2 = q3 * m mod b^k+1
     *	  r  = r1 - r2
     * 3. if r < 0 then  r = r + b^k+1
     */
    mpi_set( r1, x );
    if( r1->nlimbs > k+1 ) /* quick modulo operation */
	r1->nlimbs = k+1;
    mpi_mul( r2, r2, m );
    if( r2->nlimbs > k+1 ) /* quick modulo operation */
	r2->nlimbs = k+1;
    mpi_sub( r, r1, r2 );

    if( mpi_has_sign (r) ) {
	gcry_mpi_t tmp;

	tmp = mpi_alloc( k + 2 );
	mpi_set_ui( tmp, 1 );
	mpi_lshift_limbs( tmp, k+1 );
	mpi_add( r, r, tmp );
	mpi_free(tmp);
    }

    /* 4. while r >= m do r = r - m */
    while( mpi_cmp( r, m ) >= 0 )
	mpi_sub( r, r, m );

    return 0;
}
Пример #3
0
/* Connert the bit string BITS of length NBITS into an octet string
   with a length of (QBITS+7)/8 bytes.  On success store the result at
   R_FRAME.  */
static gpg_err_code_t
bits2octets (unsigned char **r_frame,
             const void *bits, unsigned int nbits,
             gcry_mpi_t q, unsigned int qbits)
{
  gpg_err_code_t rc;
  gcry_mpi_t z1;

  /* z1 = bits2int (b) */
  rc = _gcry_mpi_scan (&z1, GCRYMPI_FMT_USG, bits, (nbits+7)/8, NULL);
  if (rc)
    return rc;
  if (nbits > qbits)
    mpi_rshift (z1, z1, nbits - qbits);

  /* z2 - z1 mod q */
  if (mpi_cmp (z1, q) >= 0)
    mpi_sub (z1, z1, q);

  /* Convert to an octet string.  */
  rc = int2octets (r_frame, z1, (qbits+7)/8);

  mpi_free (z1);
  return rc;
}
Пример #4
0
static void
do_sub(void)
{
    if( stackidx < 2 ) {
	fputs("stack underflow\n", stderr);
	return;
    }
    mpi_sub( stack[stackidx-2], stack[stackidx-2], stack[stackidx-1] );
    stackidx--;
}
Пример #5
0
Файл: mpr.c Проект: aosm/X11
void
mpr_subi(mpr *rop, mpr *op1, long op2)
{
    mpi prod;

    memset(&prod, '\0', sizeof(mpi));

    mpi_muli(&prod, mpr_den(op1), op2);
    mpi_sub(mpr_num(rop), mpr_num(op1), &prod);
    mpi_clear(&prod);
}
Пример #6
0
Файл: mpr.c Проект: aosm/X11
static void
mpr_addsub(mpr *rop, mpr *op1, mpr *op2, int sub)
{
    mpi prod1, prod2;

    memset(&prod1, '\0', sizeof(mpi));
    memset(&prod2, '\0', sizeof(mpi));

    mpi_mul(&prod1, mpr_num(op1), mpr_den(op2));
    mpi_mul(&prod2, mpr_num(op2), mpr_den(op1));

    if (sub)
	mpi_sub(mpr_num(rop), &prod1, &prod2);
    else
	mpi_add(mpr_num(rop), &prod1, &prod2);

    mpi_clear(&prod1);
    mpi_clear(&prod2);

    mpi_mul(mpr_den(rop), mpr_den(op1), mpr_den(op2));
}
Пример #7
0
static void
ec_mulm (gcry_mpi_t w, gcry_mpi_t u, gcry_mpi_t v, mpi_ec_t ctx)
{
#if 0
  /* NOTE: This code works only for limb sizes of 32 bit.  */
  mpi_limb_t *wp, *sp;

  if (ctx->nist_nbits == 192)
    {
      mpi_mul (w, u, v);
      mpi_resize (w, 12);
      wp = w->d;

      sp = ctx->s[0]->d;
      sp[0*2+0] = wp[0*2+0];
      sp[0*2+1] = wp[0*2+1];
      sp[1*2+0] = wp[1*2+0];
      sp[1*2+1] = wp[1*2+1];
      sp[2*2+0] = wp[2*2+0];
      sp[2*2+1] = wp[2*2+1];

      sp = ctx->s[1]->d;
      sp[0*2+0] = wp[3*2+0];
      sp[0*2+1] = wp[3*2+1];
      sp[1*2+0] = wp[3*2+0];
      sp[1*2+1] = wp[3*2+1];
      sp[2*2+0] = 0;
      sp[2*2+1] = 0;

      sp = ctx->s[2]->d;
      sp[0*2+0] = 0;
      sp[0*2+1] = 0;
      sp[1*2+0] = wp[4*2+0];
      sp[1*2+1] = wp[4*2+1];
      sp[2*2+0] = wp[4*2+0];
      sp[2*2+1] = wp[4*2+1];

      sp = ctx->s[3]->d;
      sp[0*2+0] = wp[5*2+0];
      sp[0*2+1] = wp[5*2+1];
      sp[1*2+0] = wp[5*2+0];
      sp[1*2+1] = wp[5*2+1];
      sp[2*2+0] = wp[5*2+0];
      sp[2*2+1] = wp[5*2+1];

      ctx->s[0]->nlimbs = 6;
      ctx->s[1]->nlimbs = 6;
      ctx->s[2]->nlimbs = 6;
      ctx->s[3]->nlimbs = 6;

      mpi_add (ctx->c, ctx->s[0], ctx->s[1]);
      mpi_add (ctx->c, ctx->c, ctx->s[2]);
      mpi_add (ctx->c, ctx->c, ctx->s[3]);

      while ( mpi_cmp (ctx->c, ctx->p ) >= 0 )
        mpi_sub ( ctx->c, ctx->c, ctx->p );
      mpi_set (w, ctx->c);
    }
  else if (ctx->nist_nbits == 384)
    {
      int i;
      mpi_mul (w, u, v);
      mpi_resize (w, 24);
      wp = w->d;

#define NEXT(a) do { ctx->s[(a)]->nlimbs = 12; \
                     sp = ctx->s[(a)]->d; \
                     i = 0; } while (0)
#define X(a) do { sp[i++] = wp[(a)];} while (0)
#define X0(a) do { sp[i++] = 0; } while (0)
      NEXT(0);
      X(0);X(1);X(2);X(3);X(4);X(5);X(6);X(7);X(8);X(9);X(10);X(11);
      NEXT(1);
      X0();X0();X0();X0();X(21);X(22);X(23);X0();X0();X0();X0();X0();
      NEXT(2);
      X(12);X(13);X(14);X(15);X(16);X(17);X(18);X(19);X(20);X(21);X(22);X(23);
      NEXT(3);
      X(21);X(22);X(23);X(12);X(13);X(14);X(15);X(16);X(17);X(18);X(19);X(20);
      NEXT(4);
      X0();X(23);X0();X(20);X(12);X(13);X(14);X(15);X(16);X(17);X(18);X(19);
      NEXT(5);
      X0();X0();X0();X0();X(20);X(21);X(22);X(23);X0();X0();X0();X0();
      NEXT(6);
      X(20);X0();X0();X(21);X(22);X(23);X0();X0();X0();X0();X0();X0();
      NEXT(7);
      X(23);X(12);X(13);X(14);X(15);X(16);X(17);X(18);X(19);X(20);X(21);X(22);
      NEXT(8);
      X0();X(20);X(21);X(22);X(23);X0();X0();X0();X0();X0();X0();X0();
      NEXT(9);
      X0();X0();X0();X(23);X(23);X0();X0();X0();X0();X0();X0();X0();
#undef X0
#undef X
#undef NEXT
      mpi_add (ctx->c, ctx->s[0], ctx->s[1]);
      mpi_add (ctx->c, ctx->c, ctx->s[1]);
      mpi_add (ctx->c, ctx->c, ctx->s[2]);
      mpi_add (ctx->c, ctx->c, ctx->s[3]);
      mpi_add (ctx->c, ctx->c, ctx->s[4]);
      mpi_add (ctx->c, ctx->c, ctx->s[5]);
      mpi_add (ctx->c, ctx->c, ctx->s[6]);
      mpi_sub (ctx->c, ctx->c, ctx->s[7]);
      mpi_sub (ctx->c, ctx->c, ctx->s[8]);
      mpi_sub (ctx->c, ctx->c, ctx->s[9]);

      while ( mpi_cmp (ctx->c, ctx->p ) >= 0 )
        mpi_sub ( ctx->c, ctx->c, ctx->p );
      while ( ctx->c->sign )
        mpi_add ( ctx->c, ctx->c, ctx->p );
      mpi_set (w, ctx->c);
    }
  else
#endif /*0*/
    mpi_mulm (w, u, v, ctx->p);
}
Пример #8
0
int mpi_subm(MPI w, MPI u, MPI v, MPI m)
{
	if (mpi_sub(w, u, v) < 0 || mpi_fdiv_r(w, w, m) < 0)
		return -ENOMEM;
	return 0;
}
Пример #9
0
/*
 * Double/Single->Single modulo division (mpi/mpi)
 * *a %= *b
 * Divisor's MSW must be >= 0x8000
 */
void mpi_moduu(uint16_t* a, const uint16_t* b)
{
    uint16_t* pr = a + MPI_NUMBER_SIZE;// Initial partial remainder is the dividend's upper half
    uint8_t count = MPI_NUMBER_SIZE+1;
    uint8_t flag = 0; // If PR has N+1 significant words, this flag = 1
    uint32_t pq; // Partial quotient
    uint32_t carry;

    // Loop through the lower half of the dividend, bringing digits down to the PR
    do
    {
        if(flag)
        {
            // Number of words in PR is 1 more than in the divisor. Apply pq guessing
            pq = (((uint32_t)pr[MPI_NUMBER_SIZE])<<16) | (uint32_t)pr[MPI_NUMBER_SIZE-1];
            pq /= (uint32_t)b[MPI_NUMBER_SIZE-1];
            if(pq>0xFFFF)
                pq = 0xFFFF; // Divide overflow, use pq=0xFFFF
            // Multiply the divisor by pq, subtract the result from PR
            if(!mpi_mulsubuuk(pr,b,pq))
            {
                // trial pq was too high (max 1 or 2 too high), add the divisor back and check
                carry = mpi_add(pr,b);
                carry += pr[MPI_NUMBER_SIZE];
                pr[MPI_NUMBER_SIZE] = carry&0xFFFF;
                if(!(carry&0x10000))
                {
                    // Trial pq was still too high, add the divisor back again
                    carry = mpi_add(pr,b);
                    carry += pr[MPI_NUMBER_SIZE];
                    pr[MPI_NUMBER_SIZE] = carry&0xFFFF;
                }
            }
            // pr[MPI_NUMBER_SIZE] must be 0 here, but another digit will come at the next loop iteration
            flag = pr[MPI_NUMBER_SIZE-1]!=0;
        }
        else
        {
            // PR has N significant words or less
            if(pr[MPI_NUMBER_SIZE-1]) // MSW of PR
            {
                // PR has N significant words, same as dividend
                if(mpi_cmp(pr,b)>=0)
                {
                    // PR is >= divisor, pq=1, update PR
                    mpi_sub(pr,b);
                    // If MSW of PR after subtraction is >0, there will be N+1 words
                    flag = pr[MPI_NUMBER_SIZE-1]!=0;
                }
                else
                {
                    // PR is < divisor, pq=0, there will be N+1 words
                    flag = 1;
                }
            }
            else
            {
                // PR has less than N significant words. pq=0, leave the flag at 0
            }
        }
        pr--; // Bring in another digit from the dividend into PR
    } while(--count);
}
Пример #10
0
/****************
 * Calculate the multiplicative inverse X of A mod N
 * That is: Find the solution x for
 *		1 = (a*x) mod n
 */
int mpi_invm(MPI x, const MPI a, const MPI n)
{
	/* Extended Euclid's algorithm (See TAOPC Vol II, 4.5.2, Alg X)
	 * modified according to Michael Penk's solution for Exercice 35
	 * with further enhancement */
	MPI u = NULL, v = NULL;
	MPI u1 = NULL, u2 = NULL, u3 = NULL;
	MPI v1 = NULL, v2 = NULL, v3 = NULL;
	MPI t1 = NULL, t2 = NULL, t3 = NULL;
	unsigned k;
	int sign;
	int odd = 0;
	int rc = -ENOMEM;

	if (mpi_copy(&u, a) < 0)
		goto cleanup;
	if (mpi_copy(&v, n) < 0)
		goto cleanup;

	for (k = 0; !mpi_test_bit(u, 0) && !mpi_test_bit(v, 0); k++) {
		if (mpi_rshift(u, u, 1) < 0)
			goto cleanup;
		if (mpi_rshift(v, v, 1) < 0)
			goto cleanup;
	}
	odd = mpi_test_bit(v, 0);

	u1 = mpi_alloc_set_ui(1);
	if (!u1)
		goto cleanup;
	if (!odd) {
		u2 = mpi_alloc_set_ui(0);
		if (!u2)
			goto cleanup;
	}
	if (mpi_copy(&u3, u) < 0)
		goto cleanup;
	if (mpi_copy(&v1, v) < 0)
		goto cleanup;
	if (!odd) {
		v2 = mpi_alloc(mpi_get_nlimbs(u));
		if (!v2)
			goto cleanup;
		if (mpi_sub(v2, u1, u) < 0)
			goto cleanup;	/* U is used as const 1 */
	}
	if (mpi_copy(&v3, v) < 0)
		goto cleanup;
	if (mpi_test_bit(u, 0)) {	/* u is odd */
		t1 = mpi_alloc_set_ui(0);
		if (!t1)
			goto cleanup;
		if (!odd) {
			t2 = mpi_alloc_set_ui(1);
			if (!t2)
				goto cleanup;
			t2->sign = 1;
		}
		if (mpi_copy(&t3, v) < 0)
			goto cleanup;
		t3->sign = !t3->sign;
		goto Y4;
	} else {
		t1 = mpi_alloc_set_ui(1);
		if (!t1)
			goto cleanup;
		if (!odd) {
			t2 = mpi_alloc_set_ui(0);
			if (!t2)
				goto cleanup;
		}
		if (mpi_copy(&t3, u) < 0)
			goto cleanup;
	}
	do {
		do {
			if (!odd) {
				if (mpi_test_bit(t1, 0) || mpi_test_bit(t2, 0)) {	/* one is odd */
					if (mpi_add(t1, t1, v) < 0)
						goto cleanup;
					if (mpi_sub(t2, t2, u) < 0)
						goto cleanup;
				}
				if (mpi_rshift(t1, t1, 1) < 0)
					goto cleanup;
				if (mpi_rshift(t2, t2, 1) < 0)
					goto cleanup;
				if (mpi_rshift(t3, t3, 1) < 0)
					goto cleanup;
			} else {
				if (mpi_test_bit(t1, 0))
					if (mpi_add(t1, t1, v) < 0)
						goto cleanup;
				if (mpi_rshift(t1, t1, 1) < 0)
					goto cleanup;
				if (mpi_rshift(t3, t3, 1) < 0)
					goto cleanup;
			}
Y4:
			;
		} while (!mpi_test_bit(t3, 0));	/* while t3 is even */

		if (!t3->sign) {
			if (mpi_set(u1, t1) < 0)
				goto cleanup;
			if (!odd)
				if (mpi_set(u2, t2) < 0)
					goto cleanup;
			if (mpi_set(u3, t3) < 0)
				goto cleanup;
		} else {
			if (mpi_sub(v1, v, t1) < 0)
				goto cleanup;
			sign = u->sign;
			u->sign = !u->sign;
			if (!odd)
				if (mpi_sub(v2, u, t2) < 0)
					goto cleanup;
			u->sign = sign;
			sign = t3->sign;
			t3->sign = !t3->sign;
			if (mpi_set(v3, t3) < 0)
				goto cleanup;
			t3->sign = sign;
		}
		if (mpi_sub(t1, u1, v1) < 0)
			goto cleanup;
		if (!odd)
			if (mpi_sub(t2, u2, v2) < 0)
				goto cleanup;
		if (mpi_sub(t3, u3, v3) < 0)
			goto cleanup;
		if (t1->sign) {
			if (mpi_add(t1, t1, v) < 0)
				goto cleanup;
			if (!odd)
				if (mpi_sub(t2, t2, u) < 0)
					goto cleanup;
		}
	} while (mpi_cmp_ui(t3, 0));	/* while t3 != 0 */
	/* mpi_lshift( u3, k ); */
	rc = mpi_set(x, u1);

cleanup:
	mpi_free(u1);
	mpi_free(v1);
	mpi_free(t1);
	if (!odd) {
		mpi_free(u2);
		mpi_free(v2);
		mpi_free(t2);
	}
	mpi_free(u3);
	mpi_free(v3);
	mpi_free(t3);

	mpi_free(u);
	mpi_free(v);
	return rc;
}
Пример #11
0
/****************
 * Calculate the multiplicative inverse X of A mod N
 * That is: Find the solution x for
 *		1 = (a*x) mod n
 */
int
_gcry_mpi_invm (gcry_mpi_t x, gcry_mpi_t a, gcry_mpi_t n)
{
#if 0
    gcry_mpi_t u, v, u1, u2, u3, v1, v2, v3, q, t1, t2, t3;
    gcry_mpi_t ta, tb, tc;

    u = mpi_copy(a);
    v = mpi_copy(n);
    u1 = mpi_alloc_set_ui(1);
    u2 = mpi_alloc_set_ui(0);
    u3 = mpi_copy(u);
    v1 = mpi_alloc_set_ui(0);
    v2 = mpi_alloc_set_ui(1);
    v3 = mpi_copy(v);
    q  = mpi_alloc( mpi_get_nlimbs(u)+1 );
    t1 = mpi_alloc( mpi_get_nlimbs(u)+1 );
    t2 = mpi_alloc( mpi_get_nlimbs(u)+1 );
    t3 = mpi_alloc( mpi_get_nlimbs(u)+1 );
    while( mpi_cmp_ui( v3, 0 ) ) {
	mpi_fdiv_q( q, u3, v3 );
	mpi_mul(t1, v1, q); mpi_mul(t2, v2, q); mpi_mul(t3, v3, q);
	mpi_sub(t1, u1, t1); mpi_sub(t2, u2, t2); mpi_sub(t3, u3, t3);
	mpi_set(u1, v1); mpi_set(u2, v2); mpi_set(u3, v3);
	mpi_set(v1, t1); mpi_set(v2, t2); mpi_set(v3, t3);
    }
    /*	log_debug("result:\n");
	log_mpidump("q =", q );
	log_mpidump("u1=", u1);
	log_mpidump("u2=", u2);
	log_mpidump("u3=", u3);
	log_mpidump("v1=", v1);
	log_mpidump("v2=", v2); */
    mpi_set(x, u1);

    mpi_free(u1);
    mpi_free(u2);
    mpi_free(u3);
    mpi_free(v1);
    mpi_free(v2);
    mpi_free(v3);
    mpi_free(q);
    mpi_free(t1);
    mpi_free(t2);
    mpi_free(t3);
    mpi_free(u);
    mpi_free(v);
#elif 0
    /* Extended Euclid's algorithm (See TAOCP Vol II, 4.5.2, Alg X)
     * modified according to Michael Penk's solution for Exercise 35 */

    /* FIXME: we can simplify this in most cases (see Knuth) */
    gcry_mpi_t u, v, u1, u2, u3, v1, v2, v3, t1, t2, t3;
    unsigned k;
    int sign;

    u = mpi_copy(a);
    v = mpi_copy(n);
    for(k=0; !mpi_test_bit(u,0) && !mpi_test_bit(v,0); k++ ) {
	mpi_rshift(u, u, 1);
	mpi_rshift(v, v, 1);
    }


    u1 = mpi_alloc_set_ui(1);
    u2 = mpi_alloc_set_ui(0);
    u3 = mpi_copy(u);
    v1 = mpi_copy(v);				   /* !-- used as const 1 */
    v2 = mpi_alloc( mpi_get_nlimbs(u) ); mpi_sub( v2, u1, u );
    v3 = mpi_copy(v);
    if( mpi_test_bit(u, 0) ) { /* u is odd */
	t1 = mpi_alloc_set_ui(0);
	t2 = mpi_alloc_set_ui(1); t2->sign = 1;
	t3 = mpi_copy(v); t3->sign = !t3->sign;
	goto Y4;
    }
    else {
	t1 = mpi_alloc_set_ui(1);
	t2 = mpi_alloc_set_ui(0);
	t3 = mpi_copy(u);
    }
    do {
	do {
	    if( mpi_test_bit(t1, 0) || mpi_test_bit(t2, 0) ) { /* one is odd */
		mpi_add(t1, t1, v);
		mpi_sub(t2, t2, u);
	    }
	    mpi_rshift(t1, t1, 1);
	    mpi_rshift(t2, t2, 1);
	    mpi_rshift(t3, t3, 1);
	  Y4:
	    ;
	} while( !mpi_test_bit( t3, 0 ) ); /* while t3 is even */

	if( !t3->sign ) {
	    mpi_set(u1, t1);
	    mpi_set(u2, t2);
	    mpi_set(u3, t3);
	}
	else {
	    mpi_sub(v1, v, t1);
	    sign = u->sign; u->sign = !u->sign;
	    mpi_sub(v2, u, t2);
	    u->sign = sign;
	    sign = t3->sign; t3->sign = !t3->sign;
	    mpi_set(v3, t3);
	    t3->sign = sign;
	}
	mpi_sub(t1, u1, v1);
	mpi_sub(t2, u2, v2);
	mpi_sub(t3, u3, v3);
	if( t1->sign ) {
	    mpi_add(t1, t1, v);
	    mpi_sub(t2, t2, u);
	}
    } while( mpi_cmp_ui( t3, 0 ) ); /* while t3 != 0 */
    /* mpi_lshift( u3, k ); */
    mpi_set(x, u1);

    mpi_free(u1);
    mpi_free(u2);
    mpi_free(u3);
    mpi_free(v1);
    mpi_free(v2);
    mpi_free(v3);
    mpi_free(t1);
    mpi_free(t2);
    mpi_free(t3);
#else
    /* Extended Euclid's algorithm (See TAOCP Vol II, 4.5.2, Alg X)
     * modified according to Michael Penk's solution for Exercise 35
     * with further enhancement */
    gcry_mpi_t u, v, u1, u2=NULL, u3, v1, v2=NULL, v3, t1, t2=NULL, t3;
    unsigned k;
    int sign;
    int odd ;

    if (!mpi_cmp_ui (a, 0))
        return 0; /* Inverse does not exists.  */
    if (!mpi_cmp_ui (n, 1))
        return 0; /* Inverse does not exists.  */

    u = mpi_copy(a);
    v = mpi_copy(n);

    for(k=0; !mpi_test_bit(u,0) && !mpi_test_bit(v,0); k++ ) {
	mpi_rshift(u, u, 1);
	mpi_rshift(v, v, 1);
    }
    odd = mpi_test_bit(v,0);

    u1 = mpi_alloc_set_ui(1);
    if( !odd )
	u2 = mpi_alloc_set_ui(0);
    u3 = mpi_copy(u);
    v1 = mpi_copy(v);
    if( !odd ) {
	v2 = mpi_alloc( mpi_get_nlimbs(u) );
	mpi_sub( v2, u1, u ); /* U is used as const 1 */
    }
    v3 = mpi_copy(v);
    if( mpi_test_bit(u, 0) ) { /* u is odd */
	t1 = mpi_alloc_set_ui(0);
	if( !odd ) {
	    t2 = mpi_alloc_set_ui(1); t2->sign = 1;
	}
	t3 = mpi_copy(v); t3->sign = !t3->sign;
	goto Y4;
    }
    else {
	t1 = mpi_alloc_set_ui(1);
	if( !odd )
	    t2 = mpi_alloc_set_ui(0);
	t3 = mpi_copy(u);
    }
    do {
	do {
	    if( !odd ) {
		if( mpi_test_bit(t1, 0) || mpi_test_bit(t2, 0) ) { /* one is odd */
		    mpi_add(t1, t1, v);
		    mpi_sub(t2, t2, u);
		}
		mpi_rshift(t1, t1, 1);
		mpi_rshift(t2, t2, 1);
		mpi_rshift(t3, t3, 1);
	    }
	    else {
		if( mpi_test_bit(t1, 0) )
		    mpi_add(t1, t1, v);
		mpi_rshift(t1, t1, 1);
		mpi_rshift(t3, t3, 1);
	    }
	  Y4:
	    ;
	} while( !mpi_test_bit( t3, 0 ) ); /* while t3 is even */

	if( !t3->sign ) {
	    mpi_set(u1, t1);
	    if( !odd )
		mpi_set(u2, t2);
	    mpi_set(u3, t3);
	}
	else {
	    mpi_sub(v1, v, t1);
	    sign = u->sign; u->sign = !u->sign;
	    if( !odd )
		mpi_sub(v2, u, t2);
	    u->sign = sign;
	    sign = t3->sign; t3->sign = !t3->sign;
	    mpi_set(v3, t3);
	    t3->sign = sign;
	}
	mpi_sub(t1, u1, v1);
	if( !odd )
	    mpi_sub(t2, u2, v2);
	mpi_sub(t3, u3, v3);
	if( t1->sign ) {
	    mpi_add(t1, t1, v);
	    if( !odd )
		mpi_sub(t2, t2, u);
	}
    } while( mpi_cmp_ui( t3, 0 ) ); /* while t3 != 0 */
    /* mpi_lshift( u3, k ); */
    mpi_set(x, u1);

    mpi_free(u1);
    mpi_free(v1);
    mpi_free(t1);
    if( !odd ) {
	mpi_free(u2);
	mpi_free(v2);
	mpi_free(t2);
    }
    mpi_free(u3);
    mpi_free(v3);
    mpi_free(t3);

    mpi_free(u);
    mpi_free(v);
#endif
    return 1;
}
Пример #12
0
void
mpi_subm( MPI w, MPI u, MPI v, MPI m)
{
    mpi_sub(w, u, v);
    mpi_fdiv_r( w, w, m );
}
Пример #13
0
/* Recover X from Y and SIGN (which actually is a parity bit).  */
gpg_err_code_t
_gcry_ecc_eddsa_recover_x (gcry_mpi_t x, gcry_mpi_t y, int sign, mpi_ec_t ec)
{
  gpg_err_code_t rc = 0;
  gcry_mpi_t u, v, v3, t;
  static gcry_mpi_t p58, seven;

  if (ec->dialect != ECC_DIALECT_ED25519)
    return GPG_ERR_NOT_IMPLEMENTED;

  if (!p58)
    p58 = scanval ("0FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
                   "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD");
  if (!seven)
    seven = mpi_set_ui (NULL, 7);

  u   = mpi_new (0);
  v   = mpi_new (0);
  v3  = mpi_new (0);
  t   = mpi_new (0);

  /* Compute u and v */
  /* u = y^2    */
  mpi_mulm (u, y, y, ec->p);
  /* v = b*y^2   */
  mpi_mulm (v, ec->b, u, ec->p);
  /* u = y^2-1  */
  mpi_sub_ui (u, u, 1);
  /* v = b*y^2+1 */
  mpi_add_ui (v, v, 1);

  /* Compute sqrt(u/v) */
  /* v3 = v^3 */
  mpi_powm (v3, v, mpi_const (MPI_C_THREE), ec->p);
  /* t = v3 * v3 * u * v = u * v^7 */
  mpi_powm (t, v, seven, ec->p);
  mpi_mulm (t, t, u, ec->p);
  /* t = t^((p-5)/8) = (u * v^7)^((p-5)/8)  */
  mpi_powm (t, t, p58, ec->p);
  /* x = t * u * v^3 = (u * v^3) * (u * v^7)^((p-5)/8) */
  mpi_mulm (t, t, u, ec->p);
  mpi_mulm (x, t, v3, ec->p);

  /* Adjust if needed.  */
  /* t = v * x^2  */
  mpi_mulm (t, x, x, ec->p);
  mpi_mulm (t, t, v, ec->p);
  /* -t == u ? x = x * sqrt(-1) */
  mpi_neg (t, t);
  if (!mpi_cmp (t, u))
    {
      static gcry_mpi_t m1;  /* Fixme: this is not thread-safe.  */
      if (!m1)
        m1 = scanval ("2B8324804FC1DF0B2B4D00993DFBD7A7"
                      "2F431806AD2FE478C4EE1B274A0EA0B0");
      mpi_mulm (x, x, m1, ec->p);
      /* t = v * x^2  */
      mpi_mulm (t, x, x, ec->p);
      mpi_mulm (t, t, v, ec->p);
      /* -t == u ? x = x * sqrt(-1) */
      mpi_neg (t, t);
      if (!mpi_cmp (t, u))
        rc = GPG_ERR_INV_OBJ;
    }

  /* Choose the desired square root according to parity */
  if (mpi_test_bit (x, 0) != !!sign)
    mpi_sub (x, ec->p, x);

  mpi_free (t);
  mpi_free (v3);
  mpi_free (v);
  mpi_free (u);

  return rc;
}