예제 #1
0
파일: mpi-add.c 프로젝트: BridgeNY/purdue
void
mpi_sub(MPI w, MPI u, MPI v)
{
    if( w == v ) {
	MPI vv = mpi_copy(v);
	vv->sign = !vv->sign;
	mpi_add( w, u, vv );
	mpi_free(vv);
    }
    else {
	/* fixme: this is not thread-save (we temp. modify v) */
	v->sign = !v->sign;
	mpi_add( w, u, v );
	v->sign = !v->sign;
    }
}
예제 #2
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;
}
예제 #3
0
파일: mpi-div.c 프로젝트: 3null/fastsocket
int
mpi_fdiv_qr( MPI quot, MPI rem, MPI dividend, MPI divisor )
{
    int divisor_sign = divisor->sign;
    MPI temp_divisor = NULL;

    if( quot == divisor || rem == divisor ) {
	if (mpi_copy( &temp_divisor, divisor ) < 0)
		return -ENOMEM;
	divisor = temp_divisor;
    }

    if (mpi_tdiv_qr( quot, rem, dividend, divisor ) < 0)
	    goto nomem;

    if( (divisor_sign ^ dividend->sign) && rem->nlimbs ) {
	    if (mpi_sub_ui( quot, quot, 1 ) < 0)
		    goto nomem;
	    if (mpi_add( rem, rem, divisor) < 0)
		    goto nomem;
    }

    if( temp_divisor )
	mpi_free(temp_divisor);

    return 0;

 nomem:
    mpi_free(temp_divisor);
    return -ENOMEM;
}
예제 #4
0
파일: mpi-div.c 프로젝트: 3null/fastsocket
int
mpi_fdiv_r( MPI rem, MPI dividend, MPI divisor )
{
	int rc = -ENOMEM;
	int divisor_sign = divisor->sign;
	MPI temp_divisor = NULL;

	/* We need the original value of the divisor after the remainder has been
	 * preliminary calculated.	We have to copy it to temporary space if it's
	 * the same variable as REM.  */
	if( rem == divisor ) {
		if (mpi_copy( &temp_divisor, divisor ) < 0) goto nomem;
		divisor = temp_divisor;
	}

	if (mpi_tdiv_qr(NULL, rem, dividend, divisor ) < 0) goto nomem;
	if( ((divisor_sign?1:0) ^ (dividend->sign?1:0)) && rem->nlimbs )
		if (mpi_add( rem, rem, divisor) < 0) goto nomem;

	rc = 0;

 nomem:
	if( temp_divisor )
		mpi_free(temp_divisor);
	return rc;
}
예제 #5
0
int mpi_sub(MPI w, MPI u, MPI v)
{
	int rc;

	if (w == v) {
		MPI vv;
		if (mpi_copy(&vv, v) < 0)
			return -ENOMEM;
		vv->sign = !vv->sign;
		rc = mpi_add(w, u, vv);
		mpi_free(vv);
	} else {
		
		v->sign = !v->sign;
		rc = mpi_add(w, u, v);
		v->sign = !v->sign;
	}
	return rc;
}
예제 #6
0
파일: mpicalc.c 프로젝트: cobaugh/rt-rpm
static void
do_add(void)
{
    if( stackidx < 2 ) {
	fputs("stack underflow\n",stderr);
	return;
    }
    mpi_add( stack[stackidx-2], stack[stackidx-2], stack[stackidx-1] );
    stackidx--;
}
예제 #7
0
파일: mpi.c 프로젝트: ifzz/weecrypt
void
mpi_add_u32(const mpi *a, uint32_t b, mpi *s)
{
    /* TODO: optimize. */
    mpi_t bb;

    mpi_init_u32(bb, b);
    mpi_add(a, bb, s);
    mpi_free(bb);
}
예제 #8
0
파일: mpr.c 프로젝트: aosm/X11
void
mpr_addi(mpr *rop, mpr *op1, long op2)
{
    mpi prod;

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

    mpi_muli(&prod, mpr_den(op1), op2);
    mpi_add(mpr_num(rop), mpr_num(op1), &prod);
    mpi_clear(&prod);
}
예제 #9
0
파일: mpi_crt.c 프로젝트: fmela/weecrypt
int
mpi_crt_finish(mpi_crt_ctx *ctx, mpi *a)
{
    if (ctx->i == 0)
	return -1;
    if (mpi_is_neg(ctx->x))
	mpi_add(ctx->x, ctx->m, a);
    else
	mpi_set_mpi(a, ctx->x);
    mpi_free(ctx->x);
    mpi_free(ctx->m);
    return 0;
}
예제 #10
0
파일: mpi.c 프로젝트: ifzz/weecrypt
/* FIXME: I don't think this works for A==C or B==C .. */
void
mpi_sub(const mpi *a, const mpi *b, mpi *c)
{
    /* A - A = 0 */
    if (mpi_cmp_eq(a, b)) {
        mpi_zero(c);
        return;
    }
    /* A - 0 = A */
    if (b->size == 0) {
        mpi_set_mpi(c, a);
        return;
    }
    if (b == c) {
        c->sign ^= 1;
        mpi_add(a, b, c);
    } else {
        /* here, a could = c */
        ((mpi *)b)->sign ^= 1;
        mpi_add(a, b, c);
        ((mpi *)b)->sign ^= 1;
    }
}
예제 #11
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;
}
예제 #12
0
파일: mpi_modinv.c 프로젝트: ifzz/weecrypt
/* Find multiplicative inverse B^-1 of B (mod M) such that B*B^-1 (mod M) = 1.
 * If such an inverse exists, stores the inverse in INV and returns 1.
 * Returns 0 otherwise. */
int
mpi_modinv(const mpi *m, const mpi *b, mpi *inv)
{
    ASSERT(mpi_cmp(b, m) < 0);

    mpi_t v, g;
    mpi_init(v);
    mpi_init(g);
    mpi_gcdext(b, m, inv, v, g);
    mpi_free(v);
    int g_is_one = mpi_is_one(g);
    mpi_free(g);
    if (g_is_one) {
        if (mpi_is_neg(inv))
            mpi_add(inv, m, inv);
        return 1;
    } else {
        return 0;
    }
}
예제 #13
0
void
mpi_fdiv_qr( MPI quot, MPI rem, MPI dividend, MPI divisor )
{
    int divisor_sign = divisor->sign;
    MPI temp_divisor = NULL;

    if( quot == divisor || rem == divisor ) {
	temp_divisor = mpi_copy_gpg( divisor );
	divisor = temp_divisor;
    }

    mpi_tdiv_qr( quot, rem, dividend, divisor );

    if( (divisor_sign ^ dividend->sign) && rem->nlimbs ) {
	mpi_sub_ui( quot, quot, 1 );
	mpi_add( rem, rem, divisor);
    }

    if( temp_divisor )
	mpi_free_gpg(temp_divisor);
}
예제 #14
0
void
_gcry_mpi_fdiv_qr( gcry_mpi_t quot, gcry_mpi_t rem, gcry_mpi_t dividend, gcry_mpi_t divisor )
{
    int divisor_sign = divisor->sign;
    gcry_mpi_t temp_divisor = NULL;

    if( quot == divisor || rem == divisor ) {
	temp_divisor = mpi_copy( divisor );
	divisor = temp_divisor;
    }

    _gcry_mpi_tdiv_qr( quot, rem, dividend, divisor );

    if( (divisor_sign ^ dividend->sign) && rem->nlimbs ) {
	mpi_sub_ui( quot, quot, 1 );
	mpi_add( rem, rem, divisor);
    }

    if( temp_divisor )
	mpi_free(temp_divisor);
}
예제 #15
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));
}
예제 #16
0
void
mpi_fdiv_r( MPI rem, MPI dividend, MPI divisor )
{
    int divisor_sign = divisor->sign;
    MPI temp_divisor = NULL;

    /* We need the original value of the divisor after the remainder has been
     * preliminary calculated.	We have to copy it to temporary space if it's
     * the same variable as REM.  */
    if( rem == divisor ) {
	temp_divisor = mpi_copy_gpg( divisor );
	divisor = temp_divisor;
    }

    mpi_tdiv_r( rem, dividend, divisor );

    if( ((divisor_sign?1:0) ^ (dividend->sign?1:0)) && rem->nlimbs )
	mpi_add( rem, rem, divisor);

    if( temp_divisor )
	mpi_free_gpg(temp_divisor);
}
예제 #17
0
파일: mpi_crt.c 프로젝트: fmela/weecrypt
int
mpi_crt_step(mpi_crt_ctx *ctx, const mpi *a_i, const mpi *m_i)
{
    if (ctx->i == 0) {
	mpi_init_mpi(ctx->x, a_i);
	mpi_init_mpi(ctx->m, m_i);
    } else {
	mpi_t u, v, gcd;

	mpi_init(u);
	mpi_init(v);
	mpi_init(gcd);

	mpi_gcdext(ctx->m, m_i, u, v, gcd);
	if (!mpi_is_one(gcd)) {
	    mpi_free(u);
	    mpi_free(v);
	    mpi_free(gcd);
	    mpi_free(ctx->x);
	    mpi_free(ctx->m);
	    ctx->i = 0;
	    return -1;
	}

	mpi_mul(u, ctx->m, u);
	mpi_mul(u, a_i, u);
	mpi_mul(v, m_i, v);
	mpi_mul(v, ctx->x, v);
	mpi_add(u, v, ctx->x);
	mpi_mul(ctx->m, m_i, ctx->m);
	mpi_mod(ctx->x, ctx->m, ctx->x);

	mpi_free(u);
	mpi_free(v);
	mpi_free(gcd);
    }
    ctx->i++;
    return 0;
}
예제 #18
0
파일: ec.c 프로젝트: Greenchik/libgcrypt
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);
}
예제 #19
0
파일: mpi-add.c 프로젝트: BridgeNY/purdue
void
mpi_addm( MPI w, MPI u, MPI v, MPI m)
{
    mpi_add(w, u, v);
    mpi_fdiv_r( w, w, m );
}
예제 #20
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;
}
예제 #21
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;
}
예제 #22
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);
}
예제 #23
0
int mpi_addm(MPI w, MPI u, MPI v, MPI m)
{
	if (mpi_add(w, u, v) < 0 || mpi_fdiv_r(w, w, m) < 0)
		return -ENOMEM;
	return 0;
}