Beispiel #1
0
/* BN_mod_add variant that may be used if both  a  and  b  are non-negative
 * and less than  m */
int BN_mod_add_quick(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m)
	{
	if (!BN_uadd(r, a, b)) return 0;
	if (BN_ucmp(r, m) >= 0)
		return BN_usub(r, r, m);
	return 1;
	}
Beispiel #2
0
int BN_add(BIGNUM *r, const BIGNUM *a, const BIGNUM *b) {
  const BIGNUM *tmp;
  int a_neg = a->neg, ret;

  //  a +  b	a+b
  //  a + -b	a-b
  // -a +  b	b-a
  // -a + -b	-(a+b)
  if (a_neg ^ b->neg) {
    // only one is negative
    if (a_neg) {
      tmp = a;
      a = b;
      b = tmp;
    }

    // we are now a - b
    if (BN_ucmp(a, b) < 0) {
      if (!BN_usub(r, b, a)) {
        return 0;
      }
      r->neg = 1;
    } else {
      if (!BN_usub(r, a, b)) {
        return 0;
      }
      r->neg = 0;
    }
    return 1;
  }

  ret = BN_uadd(r, a, b);
  r->neg = a_neg;
  return ret;
}
Beispiel #3
0
int BN_nist_mod_521(BIGNUM *r, const BIGNUM *a, const BIGNUM *field,
	BN_CTX *ctx)
	{
#if BN_BITS2 == 64
#define BN_NIST_521_TOP_MASK	(BN_ULONG)0x1FF
#elif BN_BITS2 == 32
#define BN_NIST_521_TOP_MASK	(BN_ULONG)0x1FF
#elif BN_BITS2 == 16
#define BN_NIST_521_TOP_MASK	(BN_ULONG)0x1FF
#elif BN_BITS2 == 8
#define BN_NIST_521_TOP_MASK	(BN_ULONG)0x1
#endif
	int	top, ret = 0;
	BN_ULONG *r_d;
	BIGNUM	*tmp;

	/* check whether a reduction is necessary */
	top = a->top;
	if (top < BN_NIST_521_TOP  || ( top == BN_NIST_521_TOP &&
           (!(a->d[BN_NIST_521_TOP-1] & ~(BN_NIST_521_TOP_MASK)))))
		return (r == a)? 1 : (BN_copy(r ,a) != NULL);

	BN_CTX_start(ctx);
	tmp = BN_CTX_get(ctx);
	if (!tmp)
		goto err;

	if (!bn_wexpand(tmp, BN_NIST_521_TOP))
		goto err;
	nist_cp_bn(tmp->d, a->d, BN_NIST_521_TOP);

	tmp->top = BN_NIST_521_TOP;
        tmp->d[BN_NIST_521_TOP-1]  &= BN_NIST_521_TOP_MASK;
	bn_correct_top(tmp);

	if (!BN_rshift(r, a, 521))
		goto err;

	if (!BN_uadd(r, tmp, r))
		goto err;
	top = r->top;
	r_d = r->d;
	if (top == BN_NIST_521_TOP  && 
           (r_d[BN_NIST_521_TOP-1] & ~(BN_NIST_521_TOP_MASK)))
		{
		BN_NIST_ADD_ONE(r_d)
		r_d[BN_NIST_521_TOP-1] &= BN_NIST_521_TOP_MASK; 
		}
	bn_correct_top(r);

	ret = 1;
err:
	BN_CTX_end(ctx);

	bn_check_top(r);
	return ret;
	}
Beispiel #4
0
int BN_sub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b)
{
    int max;
    int add = 0, neg = 0;

    bn_check_top(a);
    bn_check_top(b);

    /*-
     *  a -  b      a-b
     *  a - -b      a+b
     * -a -  b      -(a+b)
     * -a - -b      b-a
     */
    if (a->neg) {
        if (b->neg) {
            const BIGNUM *tmp;

            tmp = a;
            a = b;
            b = tmp;
        } else {
            add = 1;
            neg = 1;
        }
    } else {
        if (b->neg) {
            add = 1;
            neg = 0;
        }
    }

    if (add) {
        if (!BN_uadd(r, a, b))
            return 0;
        r->neg = neg;
        return 1;
    }

    /* We are actually doing a - b :-) */

    max = (a->top > b->top) ? a->top : b->top;
    if (bn_wexpand(r, max) == NULL)
        return 0;
    if (BN_ucmp(a, b) < 0) {
        if (!BN_usub(r, b, a))
            return 0;
        r->neg = 1;
    } else {
        if (!BN_usub(r, a, b))
            return 0;
        r->neg = 0;
    }
    bn_check_top(r);
    return 1;
}
Beispiel #5
0
static RSA *
fermat_question_ask(const RSA *rsa)
{
  BIGNUM
    *a = BN_new(),
    *b = BN_new(),
    *a2 = BN_new(),
    *b2 = BN_new();
  BIGNUM *n = rsa->n;
  BIGNUM
    *tmp = BN_new(),
    *rem = BN_new(),
    *dssdelta = BN_new();
  BN_CTX *ctx = BN_CTX_new();
  RSA *ret = NULL;

  BN_sqrtmod(tmp, rem, n, ctx);
  /* Δ = |p - q| = |a + b - a + b| = |2b| > √N  2⁻¹⁰⁰ */
  /* BN_rshift(dssdelta, tmp, 101); */
  BN_one(dssdelta);
  BN_lshift(dssdelta, dssdelta, BN_num_bits(n) / 4 + 10);

  BN_copy(a, tmp);
  BN_sqr(a2, a, ctx);

  do {
    /* a² += 2a + 1 */
    BN_lshift1(tmp, a);
    BN_uiadd1(tmp);
    BN_add(a2, a2, tmp);
    /* a += 1 */
    BN_uiadd1(a);
    /* b² = a² - N */
    BN_usub(b2, a2, n);
    /* b */
    BN_sqrtmod(b, rem, b2, ctx);
  } while (!BN_is_zero(rem) && BN_cmp(b, dssdelta) < 1);

  if (BN_is_zero(rem)) {
    BN_uadd(a, a, b);
    ret = qa_RSA_recover(rsa, a, ctx);
  }

  BN_CTX_free(ctx);
  BN_free(a);
  BN_free(b);
  BN_free(a2);
  BN_free(b2);
  BN_free(dssdelta);
  BN_free(tmp);
  BN_free(rem);
  return ret;
}
Beispiel #6
0
int BN_sub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b) {
  int add = 0, neg = 0;
  const BIGNUM *tmp;

  //  a -  b	a-b
  //  a - -b	a+b
  // -a -  b	-(a+b)
  // -a - -b	b-a
  if (a->neg) {
    if (b->neg) {
      tmp = a;
      a = b;
      b = tmp;
    } else {
      add = 1;
      neg = 1;
    }
  } else {
    if (b->neg) {
      add = 1;
      neg = 0;
    }
  }

  if (add) {
    if (!BN_uadd(r, a, b)) {
      return 0;
    }

    r->neg = neg;
    return 1;
  }

  if (BN_ucmp(a, b) < 0) {
    if (!BN_usub(r, b, a)) {
      return 0;
    }
    r->neg = 1;
  } else {
    if (!BN_usub(r, a, b)) {
      return 0;
    }
    r->neg = 0;
  }

  return 1;
}
Beispiel #7
0
/* r can == a or b */
int BN_add(BIGNUM *r, const BIGNUM *a, const BIGNUM *b)
{
    int a_neg = a->neg, ret;

    bn_check_top(a);
    bn_check_top(b);

    /*-
     *  a +  b      a+b
     *  a + -b      a-b
     * -a +  b      b-a
     * -a + -b      -(a+b)
     */
    if (a_neg ^ b->neg) {
        /* only one is negative */
        if (a_neg) {
            const BIGNUM *tmp;

            tmp = a;
            a = b;
            b = tmp;
        }

        /* we are now a - b */

        if (BN_ucmp(a, b) < 0) {
            if (!BN_usub(r, b, a))
                return 0;
            r->neg = 1;
        } else {
            if (!BN_usub(r, a, b))
                return 0;
            r->neg = 0;
        }
        return 1;
    }

    ret = BN_uadd(r, a, b);
    r->neg = a_neg;
    bn_check_top(r);
    return ret;
}
Beispiel #8
0
/* r can == a or b */
int BN_add(BIGNUM *r, const BIGNUM *a, const BIGNUM *b)
	{
	const BIGNUM *tmp;

	bn_check_top(a);
	bn_check_top(b);

	/*  a +  b	a+b
	 *  a + -b	a-b
	 * -a +  b	b-a
	 * -a + -b	-(a+b)
	 */
	if (a->neg ^ b->neg)
		{
		/* only one is negative */
		if (a->neg)
			{ tmp=a; a=b; b=tmp; }

		/* we are now a - b */

		if (BN_ucmp(a,b) < 0)
			{
			if (!BN_usub(r,b,a)) return(0);
			r->neg=1;
			}
		else
			{
			if (!BN_usub(r,a,b)) return(0);
			r->neg=0;
			}
		return(1);
		}

	if (a->neg) /* both are neg */
		r->neg=1;
	else
		r->neg=0;

	if (!BN_uadd(r,a,b)) return(0);
	return(1);
	}
Beispiel #9
0
BIGNUM *BN_mod_inverse(BIGNUM *in,
	const BIGNUM *a, const BIGNUM *n, BN_CTX *ctx)
	{
	BIGNUM *A,*B,*X,*Y,*M,*D,*T,*R=NULL;
	BIGNUM *ret=NULL;
	int sign;

	if ((BN_get_flags(a, BN_FLG_CONSTTIME) != 0) || (BN_get_flags(n, BN_FLG_CONSTTIME) != 0))
		{
		return BN_mod_inverse_no_branch(in, a, n, ctx);
		}

	bn_check_top(a);
	bn_check_top(n);

	BN_CTX_start(ctx);
	A = BN_CTX_get(ctx);
	B = BN_CTX_get(ctx);
	X = BN_CTX_get(ctx);
	D = BN_CTX_get(ctx);
	M = BN_CTX_get(ctx);
	Y = BN_CTX_get(ctx);
	T = BN_CTX_get(ctx);
	if (T == NULL) goto err;

	if (in == NULL)
		R=BN_new();
	else
		R=in;
	if (R == NULL) goto err;

	BN_one(X);
	BN_zero(Y);
	if (BN_copy(B,a) == NULL) goto err;
	if (BN_copy(A,n) == NULL) goto err;
	A->neg = 0;
	if (B->neg || (BN_ucmp(B, A) >= 0))
		{
		if (!BN_nnmod(B, B, A, ctx)) goto err;
		}
	sign = -1;
	/* From  B = a mod |n|,  A = |n|  it follows that
	 *
	 *      0 <= B < A,
	 *     -sign*X*a  ==  B   (mod |n|),
	 *      sign*Y*a  ==  A   (mod |n|).
	 */

	if (BN_is_odd(n) && (BN_num_bits(n) <= (BN_BITS <= 32 ? 450 : 2048)))
		{
		/* Binary inversion algorithm; requires odd modulus.
		 * This is faster than the general algorithm if the modulus
		 * is sufficiently small (about 400 .. 500 bits on 32-bit
		 * sytems, but much more on 64-bit systems) */
		int shift;
		
		while (!BN_is_zero(B))
			{
			/*
			 *      0 < B < |n|,
			 *      0 < A <= |n|,
			 * (1) -sign*X*a  ==  B   (mod |n|),
			 * (2)  sign*Y*a  ==  A   (mod |n|)
			 */

			/* Now divide  B  by the maximum possible power of two in the integers,
			 * and divide  X  by the same value mod |n|.
			 * When we're done, (1) still holds. */
			shift = 0;
			while (!BN_is_bit_set(B, shift)) /* note that 0 < B */
				{
				shift++;
				
				if (BN_is_odd(X))
					{
					if (!BN_uadd(X, X, n)) goto err;
					}
				/* now X is even, so we can easily divide it by two */
				if (!BN_rshift1(X, X)) goto err;
				}
			if (shift > 0)
				{
				if (!BN_rshift(B, B, shift)) goto err;
				}


			/* Same for  A  and  Y.  Afterwards, (2) still holds. */
			shift = 0;
			while (!BN_is_bit_set(A, shift)) /* note that 0 < A */
				{
				shift++;
				
				if (BN_is_odd(Y))
					{
					if (!BN_uadd(Y, Y, n)) goto err;
					}
				/* now Y is even */
				if (!BN_rshift1(Y, Y)) goto err;
				}
			if (shift > 0)
				{
				if (!BN_rshift(A, A, shift)) goto err;
				}

			
			/* We still have (1) and (2).
			 * Both  A  and  B  are odd.
			 * The following computations ensure that
			 *
			 *     0 <= B < |n|,
			 *      0 < A < |n|,
			 * (1) -sign*X*a  ==  B   (mod |n|),
			 * (2)  sign*Y*a  ==  A   (mod |n|),
			 *
			 * and that either  A  or  B  is even in the next iteration.
			 */
			if (BN_ucmp(B, A) >= 0)
				{
				/* -sign*(X + Y)*a == B - A  (mod |n|) */
				if (!BN_uadd(X, X, Y)) goto err;
				/* NB: we could use BN_mod_add_quick(X, X, Y, n), but that
				 * actually makes the algorithm slower */
				if (!BN_usub(B, B, A)) goto err;
				}
			else
				{
				/*  sign*(X + Y)*a == A - B  (mod |n|) */
				if (!BN_uadd(Y, Y, X)) goto err;
				/* as above, BN_mod_add_quick(Y, Y, X, n) would slow things down */
				if (!BN_usub(A, A, B)) goto err;
				}
			}
		}
	else
		{
		/* general inversion algorithm */

		while (!BN_is_zero(B))
			{
			BIGNUM *tmp;
			
			/*
			 *      0 < B < A,
			 * (*) -sign*X*a  ==  B   (mod |n|),
			 *      sign*Y*a  ==  A   (mod |n|)
			 */
			
			/* (D, M) := (A/B, A%B) ... */
			if (BN_num_bits(A) == BN_num_bits(B))
				{
				if (!BN_one(D)) goto err;
				if (!BN_sub(M,A,B)) goto err;
				}
			else if (BN_num_bits(A) == BN_num_bits(B) + 1)
				{
				/* A/B is 1, 2, or 3 */
				if (!BN_lshift1(T,B)) goto err;
				if (BN_ucmp(A,T) < 0)
					{
					/* A < 2*B, so D=1 */
					if (!BN_one(D)) goto err;
					if (!BN_sub(M,A,B)) goto err;
					}
				else
					{
					/* A >= 2*B, so D=2 or D=3 */
					if (!BN_sub(M,A,T)) goto err;
					if (!BN_add(D,T,B)) goto err; /* use D (:= 3*B) as temp */
					if (BN_ucmp(A,D) < 0)
						{
						/* A < 3*B, so D=2 */
						if (!BN_set_word(D,2)) goto err;
						/* M (= A - 2*B) already has the correct value */
						}
					else
						{
						/* only D=3 remains */
						if (!BN_set_word(D,3)) goto err;
						/* currently  M = A - 2*B,  but we need  M = A - 3*B */
						if (!BN_sub(M,M,B)) goto err;
						}
					}
				}
			else
				{
				if (!BN_div(D,M,A,B,ctx)) goto err;
				}
			
			/* Now
			 *      A = D*B + M;
			 * thus we have
			 * (**)  sign*Y*a  ==  D*B + M   (mod |n|).
			 */
			
			tmp=A; /* keep the BIGNUM object, the value does not matter */
			
			/* (A, B) := (B, A mod B) ... */
			A=B;
			B=M;
			/* ... so we have  0 <= B < A  again */
			
			/* Since the former  M  is now  B  and the former  B  is now  A,
			 * (**) translates into
			 *       sign*Y*a  ==  D*A + B    (mod |n|),
			 * i.e.
			 *       sign*Y*a - D*A  ==  B    (mod |n|).
			 * Similarly, (*) translates into
			 *      -sign*X*a  ==  A          (mod |n|).
			 *
			 * Thus,
			 *   sign*Y*a + D*sign*X*a  ==  B  (mod |n|),
			 * i.e.
			 *        sign*(Y + D*X)*a  ==  B  (mod |n|).
			 *
			 * So if we set  (X, Y, sign) := (Y + D*X, X, -sign),  we arrive back at
			 *      -sign*X*a  ==  B   (mod |n|),
			 *       sign*Y*a  ==  A   (mod |n|).
			 * Note that  X  and  Y  stay non-negative all the time.
			 */
			
			/* most of the time D is very small, so we can optimize tmp := D*X+Y */
			if (BN_is_one(D))
				{
				if (!BN_add(tmp,X,Y)) goto err;
				}
			else
				{
				if (BN_is_word(D,2))
					{
					if (!BN_lshift1(tmp,X)) goto err;
					}
				else if (BN_is_word(D,4))
					{
					if (!BN_lshift(tmp,X,2)) goto err;
					}
				else if (D->top == 1)
					{
					if (!BN_copy(tmp,X)) goto err;
					if (!BN_mul_word(tmp,D->d[0])) goto err;
					}
				else
					{
					if (!BN_mul(tmp,D,X,ctx)) goto err;
					}
				if (!BN_add(tmp,tmp,Y)) goto err;
				}
			
			M=Y; /* keep the BIGNUM object, the value does not matter */
			Y=X;
			X=tmp;
			sign = -sign;
			}
		}
		
	/*
	 * The while loop (Euclid's algorithm) ends when
	 *      A == gcd(a,n);
	 * we have
	 *       sign*Y*a  ==  A  (mod |n|),
	 * where  Y  is non-negative.
	 */

	if (sign < 0)
		{
		if (!BN_sub(Y,n,Y)) goto err;
		}
	/* Now  Y*a  ==  A  (mod |n|).  */
	

	if (BN_is_one(A))
		{
		/* Y*a == 1  (mod |n|) */
		if (!Y->neg && BN_ucmp(Y,n) < 0)
			{
			if (!BN_copy(R,Y)) goto err;
			}
		else
			{
			if (!BN_nnmod(R,Y,n,ctx)) goto err;
			}
		}
	else
		{
		BNerr(BN_F_BN_MOD_INVERSE,BN_R_NO_INVERSE);
		goto err;
		}
	ret=R;
err:
	if ((ret == NULL) && (in == NULL)) BN_free(R);
	BN_CTX_end(ctx);
	bn_check_top(ret);
	return(ret);
	}
Beispiel #10
0
int
DH_check_pubkey(const DH *dh, const BIGNUM *pub_key, int *codes)
{
    BIGNUM *bn = NULL, *sum = NULL;
    int ret = 0;

    *codes = 0;

    /**
     * Checks that the function performs are:
     * - pub_key is not negative
     */

    if (BN_is_negative(pub_key))
	goto out;

    /**
     * - pub_key > 1    and    pub_key < p - 1,
     *    to avoid small subgroups attack.
     */

    bn = BN_new();
    if (bn == NULL)
	goto out;

    if (!BN_set_word(bn, 1))
	goto out;

    if (BN_cmp(bn, pub_key) >= 0)
	*codes |= DH_CHECK_PUBKEY_TOO_SMALL;

    sum = BN_new();
    if (sum == NULL)
	goto out;

    BN_uadd(sum, pub_key, bn);

    if (BN_cmp(sum, dh->p) >= 0)
	*codes |= DH_CHECK_PUBKEY_TOO_LARGE;

    /**
     * - if g == 2, pub_key have more then one bit set,
     *   if bits set is 1, log_2(pub_key) is trival
     */

    if (!BN_set_word(bn, 2))
	goto out;

    if (BN_cmp(bn, dh->g) == 0) {
	unsigned i, n = BN_num_bits(pub_key);
	unsigned bits = 0;

	for (i = 0; i <= n; i++)
	    if (BN_is_bit_set(pub_key, i))
		bits++;

	if (bits < 2) {
	    *codes |= DH_CHECK_PUBKEY_TOO_SMALL;
	    goto out;
	}
    }

    ret = 1;
out:
    if (bn)
	BN_free(bn);
    if (sum)
	BN_free(sum);

    return ret;
}
Beispiel #11
0
static int
test_BN_uadd(void)
{
    BIGNUM *a, *b, *c;
    char *p;

    a = BN_new();
    b = BN_new();
    c = BN_new();

    BN_set_word(a, 1);
    BN_set_word(b, 2);

    BN_uadd(c, a, b);

    if (BN_get_word(c) != 3)
	return 1;

    BN_uadd(c, b, a);

    if (BN_get_word(c) != 3)
	return 1;

    BN_set_word(b, 0xff);

    BN_uadd(c, a, b);
    if (BN_get_word(c) != 0x100)
	return 1;

    BN_uadd(c, b, a);
    if (BN_get_word(c) != 0x100)
	return 1;

    BN_set_word(a, 0xff);

    BN_uadd(c, a, b);
    if (BN_get_word(c) != 0x1fe)
	return 1;

    BN_uadd(c, b, a);
    if (BN_get_word(c) != 0x1fe)
	return 1;


    BN_free(a);
    BN_free(b);

    BN_hex2bn(&a, "50212A3B611D46642C825A16A354CE0FD4D85DD2");
    BN_hex2bn(&b, "84B6C7E8D28ACA1614954DA");

    BN_uadd(c, b, a);
    p = BN_bn2hex(c);
    if (strcmp(p, "50212A3B611D466434CDC695307D7AB13621B2AC") != 0) {
	free(p);
	return 1;
    }
    free(p);

    BN_uadd(c, a, b);
    p = BN_bn2hex(c);
    if (strcmp(p, "50212A3B611D466434CDC695307D7AB13621B2AC") != 0) {
	free(p);
	return 1;
    }
    free(p);

    BN_free(a);
    BN_free(b);
    BN_free(c);

    return 0;
}