Пример #1
0
/* BN_mod_lshift1 variant that may be used if  a  is non-negative
 * and less than  m */
int BN_mod_lshift1_quick(BIGNUM *r, const BIGNUM *a, const BIGNUM *m)
	{
	if (!BN_lshift1(r, a)) return 0;
	if (BN_cmp(r, m) >= 0)
		return BN_sub(r, r, m);
	return 1;
	}
Пример #2
0
int BN_div(BIGNUM *dv, BIGNUM *rem, const BIGNUM *m, const BIGNUM *d,
	   BN_CTX *ctx)
	{
	int i,nm,nd;
	int ret = 0;
	BIGNUM *D;

	bn_check_top(m);
	bn_check_top(d);
	if (BN_is_zero(d))
		{
		BNerr(BN_F_BN_DIV,BN_R_DIV_BY_ZERO);
		return(0);
		}

	if (BN_ucmp(m,d) < 0)
		{
		if (rem != NULL)
			{ if (BN_copy(rem,m) == NULL) return(0); }
		if (dv != NULL) BN_zero(dv);
		return(1);
		}

	BN_CTX_start(ctx);
	D = BN_CTX_get(ctx);
	if (dv == NULL) dv = BN_CTX_get(ctx);
	if (rem == NULL) rem = BN_CTX_get(ctx);
	if (D == NULL || dv == NULL || rem == NULL)
		goto end;

	nd=BN_num_bits(d);
	nm=BN_num_bits(m);
	if (BN_copy(D,d) == NULL) goto end;
	if (BN_copy(rem,m) == NULL) goto end;

	/* The next 2 are needed so we can do a dv->d[0]|=1 later
	 * since BN_lshift1 will only work once there is a value :-) */
	BN_zero(dv);
	if(bn_wexpand(dv,1) == NULL) goto end;
	dv->top=1;

	if (!BN_lshift(D,D,nm-nd)) goto end;
	for (i=nm-nd; i>=0; i--)
		{
		if (!BN_lshift1(dv,dv)) goto end;
		if (BN_ucmp(rem,D) >= 0)
			{
			dv->d[0]|=1;
			if (!BN_usub(rem,rem,D)) goto end;
			}
/* CAN IMPROVE (and have now :=) */
		if (!BN_rshift1(D,D)) goto end;
		}
	rem->neg=BN_is_zero(rem)?0:m->neg;
	dv->neg=m->neg^d->neg;
	ret = 1;
 end:
	BN_CTX_end(ctx);
	return(ret);
	}
Пример #3
0
int BN_mod_lshift1(BIGNUM *r, const BIGNUM *a, const BIGNUM *m, BN_CTX *ctx)
{
    if (!BN_lshift1(r, a))
        return 0;
    bn_check_top(r);
    return BN_nnmod(r, r, m, ctx);
}
Пример #4
0
/* The secret integers s0 and s1 must be in the range 0 < s < n for
   some n, and must be relatively prime to that n.  We know a priori
   that n is of the form 2**k * p for some small integer k and prime
   p.  Therefore, it suffices to choose a random integer in the range
   [0, n/2), multiply by two and add one (enforcing oddness), and then
   reject values which are divisible by p.  */
static BIGNUM *
random_s(const BIGNUM *n, const BIGNUM *p, BN_CTX *c)
{
  BIGNUM h, m, *r;

  BN_init(&h);
  BN_init(&m);
  FAILZ(r = BN_new());
  FAILZ(BN_copy(&h, n));
  FAILZ(BN_rshift1(&h, &h));

  do {
    FAILZ(BN_rand_range(r, &h));
    FAILZ(BN_lshift1(r, r));
    FAILZ(BN_add(r, r, BN_value_one()));
    FAILZ(BN_nnmod(&m, r, p, c));
  } while (BN_is_zero(&m));

  BN_clear(&h);
  BN_clear(&m);
  return r;

 fail:
  BN_clear(&h);
  BN_clear(&m);
  if (r) BN_clear_free(r);
  return 0;
}
Пример #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;
}
Пример #6
0
static int probable_prime_dh_safe(BIGNUM *p, int bits, const BIGNUM *padd,
	const BIGNUM *rem, BN_CTX *ctx)
	{
	int i,ret=0;
	BIGNUM *t1,*qadd,*q;

	bits--;
	BN_CTX_start(ctx);
	t1 = BN_CTX_get(ctx);
	q = BN_CTX_get(ctx);
	qadd = BN_CTX_get(ctx);
	if (qadd == NULL) goto err;

	if (!BN_rshift1(qadd,padd)) goto err;
		
	if (!BN_rand(q,bits,0,1)) goto err;

	/* we need ((rnd-rem) % add) == 0 */
	if (!BN_mod(t1,q,qadd,ctx)) goto err;
	if (!BN_sub(q,q,t1)) goto err;
	if (rem == NULL)
		{ if (!BN_add_word(q,1)) goto err; }
	else
		{
		if (!BN_rshift1(t1,rem)) goto err;
		if (!BN_add(q,q,t1)) goto err;
		}

	/* we now have a random number 'rand' to test. */
	if (!BN_lshift1(p,q)) goto err;
	if (!BN_add_word(p,1)) goto err;

loop:
	for (i=1; i<NUMPRIMES; i++)
		{
		/* check that p and q are prime */
		/* check that for p and q
		 * gcd(p-1,primes) == 1 (except for 2) */
		if ((BN_mod_word(p,(BN_ULONG)primes[i]) == 0) ||
			(BN_mod_word(q,(BN_ULONG)primes[i]) == 0))
			{
			if (!BN_add(p,p,padd)) goto err;
			if (!BN_add(q,q,qadd)) goto err;
			goto loop;
			}
		}
	ret=1;

err:
	BN_CTX_end(ctx);
	bn_check_top(p);
	return(ret);
	}
// http://stackoverflow.com/questions/356090/how-to-compute-the-nth-root-of-a-very-big-integer
static BIGNUM *nearest_cuberoot(BIGNUM *in)
{
    BN_CTX *ctx = BN_CTX_new();
    BN_CTX_start(ctx);

    BIGNUM *three = BN_CTX_get(ctx);
    BIGNUM *high = BN_CTX_get(ctx);
    BIGNUM *mid = BN_CTX_get(ctx);
    BIGNUM *low = BN_CTX_get(ctx);
    BIGNUM *tmp = BN_CTX_get(ctx);

    BN_set_word(three, 3);                                         // Create the constant 3
    BN_set_word(high, 1);                                          // high = 1

    do
    {
        BN_lshift1(high, high);                                    // high = high << 1 (high * 2)
        BN_exp(tmp, high, three, ctx);                             // tmp = high^3
    } while (BN_ucmp(tmp, in) <= -1);                              // while (tmp < in)

    BN_rshift1(low, high);                                         // low = high >> 1 (high / 2)

    while (BN_ucmp(low, high) <= -1)                               // while (low < high)
    {
        BN_add(tmp, low, high);                                    // tmp = low + high
        BN_rshift1(mid, tmp);                                      // mid = tmp >> 1 (tmp / 2)
        BN_exp(tmp, mid, three, ctx);                              // tmp = mid^3
        if (BN_ucmp(low, mid) <= -1 && BN_ucmp(tmp, in) <= -1)     // if (low < mid && tmp < in)
            BN_copy(low, mid);                                     // low = mid
        else if (BN_ucmp(high, mid) >= 1 && BN_ucmp(tmp, in) >= 1) // else if (high > mid && tmp > in)
            BN_copy(high, mid);                                    // high = mid
        else
        {
            // subtract 1 from mid because 1 will be added after the loop
            BN_sub_word(mid, 1);                                   // mid -= 1
            break;
        }
    }

    BN_add_word(mid, 1);                                           // mid += 1

    BIGNUM *result = BN_dup(mid);

    BN_CTX_end(ctx);
    BN_CTX_free(ctx);

    return result;
}
Пример #8
0
/* BN_mod_lshift variant that may be used if  a  is non-negative
 * and less than  m */
int BN_mod_lshift_quick(BIGNUM *r, const BIGNUM *a, int n, const BIGNUM *m)
	{
	if (r != a)
		{
		if (BN_copy(r, a) == NULL) return 0;
		}

	while (n > 0)
		{
		int max_shift;
		
		/* 0 < r < m */
		max_shift = BN_num_bits(m) - BN_num_bits(r);
		/* max_shift >= 0 */

		if (max_shift < 0)
			{
			BNerr(BN_F_BN_MOD_LSHIFT_QUICK, BN_R_INPUT_NOT_REDUCED);
			return 0;
			}

		if (max_shift > n)
			max_shift = n;

		if (max_shift)
			{
			if (!BN_lshift(r, r, max_shift)) return 0;
			n -= max_shift;
			}
		else
			{
			if (!BN_lshift1(r, r)) return 0;
			--n;
			}

		/* BN_num_bits(r) <= BN_num_bits(m) */

		if (BN_cmp(r, m) >= 0) 
			{
			if (!BN_sub(r, r, m)) return 0;
			}
		}
	bn_check_top(r);
	
	return 1;
	}
Пример #9
0
int test_lshift1(BIO *bp)
	{
	BIGNUM *a,*b,*c;
	int i;

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

	BN_bntest_rand(a,200,0,0); /**/
	a->neg=rand_neg();
	for (i=0; i<num0; i++)
		{
		BN_lshift1(b,a);
		if (bp != NULL)
			{
			if (!results)
				{
				BN_print(bp,a);
				BIO_puts(bp," * 2");
				BIO_puts(bp," - ");
				}
			BN_print(bp,b);
			BIO_puts(bp,"\n");
			}
		BN_add(c,a,a);
		BN_sub(a,b,c);
		if(!BN_is_zero(a))
		    {
		    fprintf(stderr,"Left shift one test failed!\n");
		    return 0;
		    }
		
		BN_copy(a,b);
		}
	BN_free(a);
	BN_free(b);
	BN_free(c);
	return(1);
	}
Пример #10
0
static int test_check_public_key(void)
{
    int ret = 0;
    BIGNUM *n = NULL, *e = NULL;
    RSA *key = NULL;

    ret = TEST_ptr(key = RSA_new())
          /* check NULL pointers fail */
          && TEST_false(rsa_sp800_56b_check_public(key))
          /* load public key */
          && TEST_ptr(e = bn_load_new(cav_e, sizeof(cav_e)))
          && TEST_ptr(n = bn_load_new(cav_n, sizeof(cav_n)))
          && TEST_true(RSA_set0_key(key, n, e, NULL));
    if (!ret) {
        BN_free(e);
        BN_free(n);
        goto end;
    }
    /* check public key is valid */
    ret = TEST_true(rsa_sp800_56b_check_public(key))
          /* check fail if n is even */
          && TEST_true(BN_add_word(n, 1))
          && TEST_false(rsa_sp800_56b_check_public(key))
          && TEST_true(BN_sub_word(n, 1))
          /* check fail if n is wrong number of bits */
          && TEST_true(BN_lshift1(n, n))
          && TEST_false(rsa_sp800_56b_check_public(key))
          && TEST_true(BN_rshift1(n, n))
          /* test odd exponent fails */
          && TEST_true(BN_add_word(e, 1))
          && TEST_false(rsa_sp800_56b_check_public(key))
          && TEST_true(BN_sub_word(e, 1))
          /* modulus fails composite check */
          && TEST_true(BN_add_word(n, 2))
          && TEST_false(rsa_sp800_56b_check_public(key));
end:
    RSA_free(key);
    return ret;
}
Пример #11
0
int
dsa_builtin_paramgen(DSA *ret, size_t bits, size_t qbits, const EVP_MD *evpmd,
    const unsigned char *seed_in, size_t seed_len, unsigned char *seed_out,
    int *counter_ret, unsigned long *h_ret, BN_GENCB *cb)
{
	int ok = 0;
	unsigned char seed[SHA256_DIGEST_LENGTH];
	unsigned char md[SHA256_DIGEST_LENGTH];
	unsigned char buf[SHA256_DIGEST_LENGTH], buf2[SHA256_DIGEST_LENGTH];
	BIGNUM *r0, *W, *X, *c, *test;
	BIGNUM *g = NULL, *q = NULL, *p = NULL;
	BN_MONT_CTX *mont = NULL;
	int i, k, n = 0, m = 0, qsize = qbits >> 3;
	int counter = 0;
	int r = 0;
	BN_CTX *ctx = NULL;
	unsigned int h = 2;

	if (qsize != SHA_DIGEST_LENGTH && qsize != SHA224_DIGEST_LENGTH &&
	    qsize != SHA256_DIGEST_LENGTH)
		/* invalid q size */
		return 0;

	if (evpmd == NULL)
		/* use SHA1 as default */
		evpmd = EVP_sha1();

	if (bits < 512)
		bits = 512;

	bits = (bits + 63) / 64 * 64;

	/*
	 * NB: seed_len == 0 is special case: copy generated seed to
 	 * seed_in if it is not NULL.
 	 */
	if (seed_len && seed_len < (size_t)qsize)
		seed_in = NULL;		/* seed buffer too small -- ignore */
	/*
	 * App. 2.2 of FIPS PUB 186 allows larger SEED,
	 * but our internal buffers are restricted to 160 bits
	 */
	if (seed_len > (size_t)qsize) 
		seed_len = qsize;
	if (seed_in != NULL)
		memcpy(seed, seed_in, seed_len);

	if ((ctx=BN_CTX_new()) == NULL)
		goto err;

	if ((mont=BN_MONT_CTX_new()) == NULL)
		goto err;

	BN_CTX_start(ctx);
	r0 = BN_CTX_get(ctx);
	g = BN_CTX_get(ctx);
	W = BN_CTX_get(ctx);
	q = BN_CTX_get(ctx);
	X = BN_CTX_get(ctx);
	c = BN_CTX_get(ctx);
	p = BN_CTX_get(ctx);
	test = BN_CTX_get(ctx);

	if (!BN_lshift(test, BN_value_one(), bits - 1))
		goto err;

	for (;;) {
		for (;;) { /* find q */
			int seed_is_random;

			/* step 1 */
			if (!BN_GENCB_call(cb, 0, m++))
				goto err;

			if (!seed_len) {
				RAND_pseudo_bytes(seed, qsize);
				seed_is_random = 1;
			} else {
				seed_is_random = 0;
				/* use random seed if 'seed_in' turns out
				   to be bad */
				seed_len = 0;
			}
			memcpy(buf, seed, qsize);
			memcpy(buf2, seed, qsize);
			/* precompute "SEED + 1" for step 7: */
			for (i = qsize - 1; i >= 0; i--) {
				buf[i]++;
				if (buf[i] != 0)
					break;
			}

			/* step 2 */
			if (!EVP_Digest(seed, qsize, md,   NULL, evpmd, NULL))
				goto err;
			if (!EVP_Digest(buf,  qsize, buf2, NULL, evpmd, NULL))
				goto err;
			for (i = 0; i < qsize; i++)
				md[i] ^= buf2[i];

			/* step 3 */
			md[0] |= 0x80;
			md[qsize - 1] |= 0x01;
			if (!BN_bin2bn(md, qsize, q))
				goto err;

			/* step 4 */
			r = BN_is_prime_fasttest_ex(q, DSS_prime_checks, ctx,
			    seed_is_random, cb);
			if (r > 0)
				break;
			if (r != 0)
				goto err;

			/* do a callback call */
			/* step 5 */
		}

		if (!BN_GENCB_call(cb, 2, 0))
			goto err;
		if (!BN_GENCB_call(cb, 3, 0))
			goto err;

		/* step 6 */
		counter = 0;
		/* "offset = 2" */

		n = (bits - 1) / 160;

		for (;;) {
			if (counter != 0 && !BN_GENCB_call(cb, 0, counter))
				goto err;

			/* step 7 */
			BN_zero(W);
			/* now 'buf' contains "SEED + offset - 1" */
			for (k = 0; k <= n; k++) {
				/* obtain "SEED + offset + k" by incrementing: */
				for (i = qsize - 1; i >= 0; i--) {
					buf[i]++;
					if (buf[i] != 0)
						break;
				}

				if (!EVP_Digest(buf, qsize, md ,NULL, evpmd,
				    NULL))
					goto err;

				/* step 8 */
				if (!BN_bin2bn(md, qsize, r0))
					goto err;
				if (!BN_lshift(r0, r0, (qsize << 3) * k))
					goto err;
				if (!BN_add(W, W, r0))
					goto err;
			}

			/* more of step 8 */
			if (!BN_mask_bits(W, bits - 1))
				goto err;
			if (!BN_copy(X, W))
				goto err;
			if (!BN_add(X, X, test))
				goto err;

			/* step 9 */
			if (!BN_lshift1(r0, q))
				goto err;
			if (!BN_mod(c, X, r0, ctx))
				goto err;
			if (!BN_sub(r0, c, BN_value_one()))
				goto err;
			if (!BN_sub(p, X, r0))
				goto err;

			/* step 10 */
			if (BN_cmp(p, test) >= 0) {
				/* step 11 */
				r = BN_is_prime_fasttest_ex(p, DSS_prime_checks,
				    ctx, 1, cb);
				if (r > 0)
					goto end; /* found it */
				if (r != 0)
					goto err;
			}

			/* step 13 */
			counter++;
			/* "offset = offset + n + 1" */

			/* step 14 */
			if (counter >= 4096)
				break;
		}
	}
end:
	if (!BN_GENCB_call(cb, 2, 1))
		goto err;

	/* We now need to generate g */
	/* Set r0=(p-1)/q */
	if (!BN_sub(test, p, BN_value_one()))
		goto err;
	if (!BN_div(r0, NULL, test, q, ctx))
		goto err;

	if (!BN_set_word(test, h))
		goto err;
	if (!BN_MONT_CTX_set(mont, p, ctx))
		goto err;

	for (;;) {
		/* g=test^r0%p */
		if (!BN_mod_exp_mont(g, test, r0, p, ctx, mont))
			goto err;
		if (!BN_is_one(g))
			break;
		if (!BN_add(test, test, BN_value_one()))
			goto err;
		h++;
	}

	if (!BN_GENCB_call(cb, 3, 1))
		goto err;

	ok = 1;
err:
	if (ok) {
		if (ret->p)
			BN_free(ret->p);
		if (ret->q)
			BN_free(ret->q);
		if (ret->g)
			BN_free(ret->g);
		ret->p = BN_dup(p);
		ret->q = BN_dup(q);
		ret->g = BN_dup(g);
		if (ret->p == NULL || ret->q == NULL || ret->g == NULL) {
			ok = 0;
			goto err;
		}
		if (counter_ret != NULL)
			*counter_ret = counter;
		if (h_ret != NULL)
			*h_ret = h;
		if (seed_out)
			memcpy(seed_out, seed, qsize);
	}
	if (ctx) {
		BN_CTX_end(ctx);
		BN_CTX_free(ctx);
	}
	if (mont != NULL)
		BN_MONT_CTX_free(mont);
	return ok;
}
Пример #12
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);
	}
Пример #13
0
int xDSA_paramgen(DSA *ret, int bits)

{
	int ok=0;
	unsigned char seed[SHA_DIGEST_LENGTH];
	unsigned char md[SHA_DIGEST_LENGTH];
	unsigned char buf[SHA_DIGEST_LENGTH], buf2[SHA_DIGEST_LENGTH];
	BIGNUM *r0, *W, *X, *c, *test;
	BIGNUM *g=NULL, *q=NULL, *p=NULL;
	BN_MONT_CTX *mont=NULL;
	int k, n=0, i, b;
	int counter=0;
	int r=0;
	BN_CTX *ctx=NULL;
	unsigned int h=2;

	if (bits < 512)
		bits=512;
	bits=(bits+63)/64*64;



	if ((ctx=BN_CTX_new()) == NULL)
		goto err;

	if ((mont=BN_MONT_CTX_new()) == NULL)
		goto err;

	BN_CTX_start(ctx);
	r0 = BN_CTX_get(ctx);
	g = BN_CTX_get(ctx);
	W = BN_CTX_get(ctx);
	q = BN_CTX_get(ctx);
	X = BN_CTX_get(ctx);
	c = BN_CTX_get(ctx);
	p = BN_CTX_get(ctx);
	test = BN_CTX_get(ctx);

	if (!BN_lshift(test, BN_value_one(), bits-1))
		goto err;

	for (;;) {
		for (;;) /* find q */
		{
			int seed_is_random;
			/* step 1 */
			xRAND_bytes(seed, SHA_DIGEST_LENGTH);
			seed_is_random = 1;

			memcpy(buf, seed, SHA_DIGEST_LENGTH);
			memcpy(buf2, seed, SHA_DIGEST_LENGTH);
			/* precompute "SEED + 1" for step 7: */
			for (i=SHA_DIGEST_LENGTH-1; i >= 0; i--) {
				buf[i]++;
				if (buf[i] != 0)
					break;
			}
			/* step 2 */
			EVP_Digest(seed, SHA_DIGEST_LENGTH, md, NULL, HASH, NULL);
			EVP_Digest(buf, SHA_DIGEST_LENGTH, buf2, NULL, HASH, NULL);
			for (i=0; i<SHA_DIGEST_LENGTH; i++)
				md[i]^=buf2[i];
			/* step 3 */
			md[0]|=0x80;
			md[SHA_DIGEST_LENGTH-1]|=0x01;
			if (!BN_bin2bn(md, SHA_DIGEST_LENGTH, q))
				goto err;
			/* step 4 */
			r = xBN_is_prime_fasttest_ex(q, DSS_prime_checks, ctx,
					seed_is_random);
			if (r > 0)
				break;
			if (r != 0)
				goto err;
			/* do a callback call */
			/* step 5 */
		}

		/* step 6 */
		counter=0;
		/* "offset = 2" */

		n=(bits-1)/160;
		b=(bits-1)-n*160;

		for (;;) {

			/* step 7 */
			BN_zero(W);
			/* now 'buf' contains "SEED + offset - 1" */
			for (k=0; k<=n; k++) {
				/* obtain "SEED + offset + k" by incrementing: */
				for (i=SHA_DIGEST_LENGTH-1; i >= 0; i--) {
					buf[i]++;
					if (buf[i] != 0)
						break;
				}

				EVP_Digest(buf, SHA_DIGEST_LENGTH, md, NULL, HASH, NULL);
				/* step 8 */
				if (!BN_bin2bn(md, SHA_DIGEST_LENGTH, r0))
					goto err;
				if (!BN_lshift(r0, r0, 160*k))
					goto err;
				if (!BN_add(W, W, r0))
					goto err;
			}

			/* more of step 8 */
			if (!BN_mask_bits(W, bits-1))
				goto err;
			if (!BN_copy(X, W))
				goto err;
			if (!BN_add(X, X, test))
				goto err;
			/* step 9 */
			if (!BN_lshift1(r0, q))
				goto err;
			if (!BN_mod(c,X,r0,ctx))
				goto err;
			if (!BN_sub(r0, c, BN_value_one()))
				goto err;
			if (!BN_sub(p, X, r0))
				goto err;
			/* step 10 */
			if (BN_cmp(p, test) >= 0) {
				/* step 11 */
				
				r = xBN_is_prime_fasttest_ex(p, DSS_prime_checks, ctx, 1);
				if (r > 0)
					goto end;
				/* found it */
				if (r != 0)
					goto err;
			}
			/* step 13 */
			counter++;
			/* "offset = offset + n + 1" */
			
			/* step 14 */
			if (counter >= 4096)
				break;
		}
	}
end: 
	
	/* We now need to generate g */
	/* Set r0=(p-1)/q */
	if (!BN_sub(test, p, BN_value_one()))
		goto err;
	if (!BN_div(r0, NULL, test, q, ctx))
		goto err;

	if (!BN_set_word(test, h))
		goto err;
	if (!BN_MONT_CTX_set(mont, p, ctx))
		goto err;

	for (;;) {
		/* g=test^r0%p */
		if (!BN_mod_exp_mont(g, test, r0, p, ctx, mont))
			goto err;
		if (!BN_is_one(g))
			break;
		if (!BN_add(test, test, BN_value_one()))
			goto err;
		h++;
	}


	ok=1;
	err:
	if (ok) {
		if (ret->p)
			BN_free(ret->p);
		if (ret->q)
			BN_free(ret->q);
		if (ret->g)
			BN_free(ret->g);
		ret->p=BN_dup(p);
		ret->q=BN_dup(q);
		ret->g=BN_dup(g);
		if (ret->p == NULL || ret->q == NULL || ret->g == NULL) {
			ok=0;
			goto err;
		}

	}
	if (ctx) {
		BN_CTX_end(ctx);
		BN_CTX_free(ctx);
	}
	if (mont != NULL)
		BN_MONT_CTX_free(mont);
	return ok;
}
Пример #14
0
int dsa_builtin_paramgen2(DSA *ret, size_t L, size_t N,
	const EVP_MD *evpmd, const unsigned char *seed_in, size_t seed_len,
	unsigned char *seed_out,
	int *counter_ret, unsigned long *h_ret, BN_GENCB *cb)
	{
	int ok=-1;
	unsigned char *seed = NULL;
	unsigned char md[EVP_MAX_MD_SIZE];
	int mdsize;
	BIGNUM *r0,*W,*X,*c,*test;
	BIGNUM *g=NULL,*q=NULL,*p=NULL;
	BN_MONT_CTX *mont=NULL;
	int i, k, n=0, m=0, qsize = N >> 3;
	int counter=0;
	int r=0;
	BN_CTX *ctx=NULL;
	unsigned int h=2;

#ifdef OPENSSL_FIPS
	if(FIPS_selftest_failed())
	    {
	    FIPSerr(FIPS_F_DSA_BUILTIN_PARAMGEN2,
		    FIPS_R_FIPS_SELFTEST_FAILED);
	    goto err;
	    }

	if (!fips_check_dsa_prng(ret, L, N))
		goto err;
#endif

	if (evpmd == NULL)
		{
		if (N == 160)
			evpmd = EVP_sha1();
		else if (N == 224)
			evpmd = EVP_sha224();
		else
			evpmd = EVP_sha256();
		}

	mdsize = M_EVP_MD_size(evpmd);

	if (seed_len == 0)
		seed_len = mdsize;

	seed = OPENSSL_malloc(seed_len);

	if (!seed)
		goto err;

	if (seed_in)
		memcpy(seed, seed_in, seed_len);

	if ((ctx=BN_CTX_new()) == NULL)
		goto err;

	if ((mont=BN_MONT_CTX_new()) == NULL)
		goto err;

	BN_CTX_start(ctx);
	r0 = BN_CTX_get(ctx);
	g = BN_CTX_get(ctx);
	W = BN_CTX_get(ctx);
	q = BN_CTX_get(ctx);
	X = BN_CTX_get(ctx);
	c = BN_CTX_get(ctx);
	p = BN_CTX_get(ctx);
	test = BN_CTX_get(ctx);

	if (!BN_lshift(test,BN_value_one(),L-1))
		goto err;
	for (;;)
		{
		for (;;) /* find q */
			{
			unsigned char *pmd;
			/* step 1 */
			if(!BN_GENCB_call(cb, 0, m++))
				goto err;

			if (!seed_in)
				{
				if (RAND_pseudo_bytes(seed, seed_len) < 0)
					goto err;
				}
			/* step 2 */
			if (!EVP_Digest(seed, seed_len, md, NULL, evpmd, NULL))
				goto err;
			/* Take least significant bits of md */
			if (mdsize > qsize)
				pmd = md + mdsize - qsize;
			else
				pmd = md;

			if (mdsize < qsize)
				memset(md + mdsize, 0, qsize - mdsize);

			/* step 3 */
			pmd[0] |= 0x80;
			pmd[qsize-1] |= 0x01;
			if (!BN_bin2bn(pmd, qsize, q))
				goto err;

			/* step 4 */
			r = BN_is_prime_fasttest_ex(q, DSS_prime_checks, ctx,
					seed_in ? 1 : 0, cb);
			if (r > 0)
				break;
			if (r != 0)
				goto err;
			/* Provided seed didn't produce a prime: error */
			if (seed_in)
				{
				ok = 0;
				DSAerr(DSA_F_DSA_BUILTIN_PARAMGEN2, DSA_R_Q_NOT_PRIME);
				goto err;
				}

			/* do a callback call */
			/* step 5 */
			}
		/* Copy seed to seed_out before we mess with it */
		if (seed_out)
			memcpy(seed_out, seed, seed_len);

		if(!BN_GENCB_call(cb, 2, 0)) goto err;
		if(!BN_GENCB_call(cb, 3, 0)) goto err;

		/* step 6 */
		counter=0;
		/* "offset = 1" */

		n=(L-1)/(mdsize << 3);

		for (;;)
			{
			if ((counter != 0) && !BN_GENCB_call(cb, 0, counter))
				goto err;

			/* step 7 */
			BN_zero(W);
			/* now 'buf' contains "SEED + offset - 1" */
			for (k=0; k<=n; k++)
				{
				/* obtain "SEED + offset + k" by incrementing: */
				for (i = seed_len-1; i >= 0; i--)
					{
					seed[i]++;
					if (seed[i] != 0)
						break;
					}

				if (!EVP_Digest(seed, seed_len, md ,NULL, evpmd,
									NULL))
					goto err;

				/* step 8 */
				if (!BN_bin2bn(md, mdsize, r0))
					goto err;
				if (!BN_lshift(r0,r0,(mdsize << 3)*k)) goto err;
				if (!BN_add(W,W,r0)) goto err;
				}

			/* more of step 8 */
			if (!BN_mask_bits(W,L-1)) goto err;
			if (!BN_copy(X,W)) goto err;
			if (!BN_add(X,X,test)) goto err;

			/* step 9 */
			if (!BN_lshift1(r0,q)) goto err;
			if (!BN_mod(c,X,r0,ctx)) goto err;
			if (!BN_sub(r0,c,BN_value_one())) goto err;
			if (!BN_sub(p,X,r0)) goto err;

			/* step 10 */
			if (BN_cmp(p,test) >= 0)
				{
				/* step 11 */
				r = BN_is_prime_fasttest_ex(p, DSS_prime_checks,
						ctx, 1, cb);
				if (r > 0)
						goto end; /* found it */
				if (r != 0)
					goto err;
				}

			/* step 13 */
			counter++;
			/* "offset = offset + n + 1" */

			/* step 14 */
			if (counter >= 4096) break;
			}
		}
end:
	if(!BN_GENCB_call(cb, 2, 1))
		goto err;

	/* We now need to generate g */
	/* Set r0=(p-1)/q */
	if (!BN_sub(test,p,BN_value_one())) goto err;
	if (!BN_div(r0,NULL,test,q,ctx)) goto err;

	if (!BN_set_word(test,h)) goto err;
	if (!BN_MONT_CTX_set(mont,p,ctx)) goto err;

	for (;;)
		{
		/* g=test^r0%p */
		if (!BN_mod_exp_mont(g,test,r0,p,ctx,mont)) goto err;
		if (!BN_is_one(g)) break;
		if (!BN_add(test,test,BN_value_one())) goto err;
		h++;
		}

	if(!BN_GENCB_call(cb, 3, 1))
		goto err;

	ok=1;
err:
	if (ok == 1)
		{
		if(ret->p) BN_free(ret->p);
		if(ret->q) BN_free(ret->q);
		if(ret->g) BN_free(ret->g);
		ret->p=BN_dup(p);
		ret->q=BN_dup(q);
		ret->g=BN_dup(g);
		if (ret->p == NULL || ret->q == NULL || ret->g == NULL)
			{
			ok=-1;
			goto err;
			}
		if (counter_ret != NULL) *counter_ret=counter;
		if (h_ret != NULL) *h_ret=h;
		}
	if (seed)
		OPENSSL_free(seed);
	if(ctx)
		{
		BN_CTX_end(ctx);
		BN_CTX_free(ctx);
		}
	if (mont != NULL) BN_MONT_CTX_free(mont);
	return ok;
	}
Пример #15
0
DSA *DSA_generate_parameters(int bits,
		unsigned char *seed_in, int seed_len,
		int *counter_ret, unsigned long *h_ret,
		void (*callback)(int, int, void *),
		void *cb_arg)
	{
	int ok=0;
	unsigned char seed[SHA_DIGEST_LENGTH];
	unsigned char md[SHA_DIGEST_LENGTH];
	unsigned char buf[SHA_DIGEST_LENGTH],buf2[SHA_DIGEST_LENGTH];
	BIGNUM *r0,*W,*X,*c,*test;
	BIGNUM *g=NULL,*q=NULL,*p=NULL;
	BN_MONT_CTX *mont=NULL;
	int k,n=0,i,b,m=0;
	int counter=0;
	int r=0;
	BN_CTX *ctx=NULL,*ctx2=NULL,*ctx3=NULL;
	unsigned int h=2;
	DSA *ret=NULL;

	if (bits < 512) bits=512;
	bits=(bits+63)/64*64;

	if (seed_len < 20)
		seed_in = NULL; /* seed buffer too small -- ignore */
	if (seed_len > 20) 
		seed_len = 20; /* App. 2.2 of FIPS PUB 186 allows larger SEED,
		                * but our internal buffers are restricted to 160 bits*/
	if ((seed_in != NULL) && (seed_len == 20))
		memcpy(seed,seed_in,seed_len);

	if ((ctx=BN_CTX_new()) == NULL) goto err;
	if ((ctx2=BN_CTX_new()) == NULL) goto err;
	if ((ctx3=BN_CTX_new()) == NULL) goto err;
	if ((ret=DSA_new()) == NULL) goto err;

	if ((mont=BN_MONT_CTX_new()) == NULL) goto err;

	BN_CTX_start(ctx2);
	r0 = BN_CTX_get(ctx2);
	g = BN_CTX_get(ctx2);
	W = BN_CTX_get(ctx2);
	q = BN_CTX_get(ctx2);
	X = BN_CTX_get(ctx2);
	c = BN_CTX_get(ctx2);
	p = BN_CTX_get(ctx2);
	test = BN_CTX_get(ctx2);
	if (test == NULL) goto err;

	if (!BN_lshift(test,BN_value_one(),bits-1)) goto err;

	for (;;)
		{
		for (;;) /* find q */
			{
			int seed_is_random;

			/* step 1 */
			if (callback != NULL) callback(0,m++,cb_arg);

			if (!seed_len)
				{
				RAND_pseudo_bytes(seed,SHA_DIGEST_LENGTH);
				seed_is_random = 1;
				}
			else
				{
				seed_is_random = 0;
				seed_len=0; /* use random seed if 'seed_in' turns out to be bad*/
				}
			memcpy(buf,seed,SHA_DIGEST_LENGTH);
			memcpy(buf2,seed,SHA_DIGEST_LENGTH);
			/* precompute "SEED + 1" for step 7: */
			for (i=SHA_DIGEST_LENGTH-1; i >= 0; i--)
				{
				buf[i]++;
				if (buf[i] != 0) break;
				}

			/* step 2 */
			EVP_Digest(seed,SHA_DIGEST_LENGTH,md,NULL,HASH, NULL);
			EVP_Digest(buf,SHA_DIGEST_LENGTH,buf2,NULL,HASH, NULL);
			for (i=0; i<SHA_DIGEST_LENGTH; i++)
				md[i]^=buf2[i];

			/* step 3 */
			md[0]|=0x80;
			md[SHA_DIGEST_LENGTH-1]|=0x01;
			if (!BN_bin2bn(md,SHA_DIGEST_LENGTH,q)) goto err;

			/* step 4 */
			r = BN_is_prime_fasttest(q, DSS_prime_checks, callback, ctx3, cb_arg, seed_is_random);
			if (r > 0)
				break;
			if (r != 0)
				goto err;

			/* do a callback call */
			/* step 5 */
			}

		if (callback != NULL) callback(2,0,cb_arg);
		if (callback != NULL) callback(3,0,cb_arg);

		/* step 6 */
		counter=0;
		/* "offset = 2" */

		n=(bits-1)/160;
		b=(bits-1)-n*160;

		for (;;)
			{
			if (callback != NULL && counter != 0)
				callback(0,counter,cb_arg);

			/* step 7 */
			if (!BN_zero(W)) goto err;
			/* now 'buf' contains "SEED + offset - 1" */
			for (k=0; k<=n; k++)
				{
				/* obtain "SEED + offset + k" by incrementing: */
				for (i=SHA_DIGEST_LENGTH-1; i >= 0; i--)
					{
					buf[i]++;
					if (buf[i] != 0) break;
					}

				EVP_Digest(buf,SHA_DIGEST_LENGTH,md,NULL,HASH, NULL);

				/* step 8 */
				if (!BN_bin2bn(md,SHA_DIGEST_LENGTH,r0))
					goto err;
				if (!BN_lshift(r0,r0,160*k)) goto err;
				if (!BN_add(W,W,r0)) goto err;
				}

			/* more of step 8 */
			if (!BN_mask_bits(W,bits-1)) goto err;
			if (!BN_copy(X,W)) goto err;
			if (!BN_add(X,X,test)) goto err;

			/* step 9 */
			if (!BN_lshift1(r0,q)) goto err;
			if (!BN_mod(c,X,r0,ctx)) goto err;
			if (!BN_sub(r0,c,BN_value_one())) goto err;
			if (!BN_sub(p,X,r0)) goto err;

			/* step 10 */
			if (BN_cmp(p,test) >= 0)
				{
				/* step 11 */
				r = BN_is_prime_fasttest(p, DSS_prime_checks, callback, ctx3, cb_arg, 1);
				if (r > 0)
						goto end; /* found it */
				if (r != 0)
					goto err;
				}

			/* step 13 */
			counter++;
			/* "offset = offset + n + 1" */

			/* step 14 */
			if (counter >= 4096) break;
			}
		}
end:
	if (callback != NULL) callback(2,1,cb_arg);

	/* We now need to generate g */
	/* Set r0=(p-1)/q */
	if (!BN_sub(test,p,BN_value_one())) goto err;
	if (!BN_div(r0,NULL,test,q,ctx)) goto err;

	if (!BN_set_word(test,h)) goto err;
	if (!BN_MONT_CTX_set(mont,p,ctx)) goto err;

	for (;;)
		{
		/* g=test^r0%p */
		if (!BN_mod_exp_mont(g,test,r0,p,ctx,mont)) goto err;
		if (!BN_is_one(g)) break;
		if (!BN_add(test,test,BN_value_one())) goto err;
		h++;
		}

	if (callback != NULL) callback(3,1,cb_arg);

	ok=1;
err:
	if (!ok)
		{
		if (ret != NULL) DSA_free(ret);
		}
	else
		{
		ret->p=BN_dup(p);
		ret->q=BN_dup(q);
		ret->g=BN_dup(g);
		if (ret->p == NULL || ret->q == NULL || ret->g == NULL)
			{
			ok=0;
			goto err;
			}
		if ((m > 1) && (seed_in != NULL)) memcpy(seed_in,seed,20);
		if (counter_ret != NULL) *counter_ret=counter;
		if (h_ret != NULL) *h_ret=h;
		}
	if (ctx != NULL) BN_CTX_free(ctx);
	if (ctx2 != NULL)
		{
		BN_CTX_end(ctx2);
		BN_CTX_free(ctx2);
		}
	if (ctx3 != NULL) BN_CTX_free(ctx3);
	if (mont != NULL) BN_MONT_CTX_free(mont);
	return(ok?ret:NULL);
	}
Пример #16
0
static int dsa_builtin_paramgen(DSA *ret, int bits,
                                unsigned char *seed_in, int seed_len,
                                int *counter_ret, unsigned long *h_ret, BN_GENCB *cb)
{
    int ok=0;
    unsigned char seed[SHA_DIGEST_LENGTH];
    unsigned char md[SHA_DIGEST_LENGTH];
    unsigned char buf[SHA_DIGEST_LENGTH],buf2[SHA_DIGEST_LENGTH];
    BIGNUM *r0,*W,*X,*c,*test;
    BIGNUM *g=NULL,*q=NULL,*p=NULL;
    BN_MONT_CTX *mont=NULL;
    int k,n=0,i,b,m=0;
    int counter=0;
    int r=0;
    BN_CTX *ctx=NULL;
    unsigned int h=2;

    if(FIPS_selftest_failed())
    {
        FIPSerr(FIPS_F_DSA_BUILTIN_PARAMGEN,
                FIPS_R_FIPS_SELFTEST_FAILED);
        goto err;
    }

    if (FIPS_mode() && (bits < OPENSSL_DSA_FIPS_MIN_MODULUS_BITS))
    {
        DSAerr(DSA_F_DSA_BUILTIN_PARAMGEN, DSA_R_KEY_SIZE_TOO_SMALL);
        goto err;
    }

    if (bits < 512) bits=512;
    bits=(bits+63)/64*64;

    /* NB: seed_len == 0 is special case: copy generated seed to
     * seed_in if it is not NULL.
     */
    if (seed_len && (seed_len < 20))
        seed_in = NULL; /* seed buffer too small -- ignore */
    if (seed_len > 20)
        seed_len = 20; /* App. 2.2 of FIPS PUB 186 allows larger SEED,
		                * but our internal buffers are restricted to 160 bits*/
    if ((seed_in != NULL) && (seed_len == 20))
    {
        memcpy(seed,seed_in,seed_len);
        /* set seed_in to NULL to avoid it being copied back */
        seed_in = NULL;
    }

    if ((ctx=BN_CTX_new()) == NULL) goto err;

    if ((mont=BN_MONT_CTX_new()) == NULL) goto err;

    BN_CTX_start(ctx);
    r0 = BN_CTX_get(ctx);
    g = BN_CTX_get(ctx);
    W = BN_CTX_get(ctx);
    q = BN_CTX_get(ctx);
    X = BN_CTX_get(ctx);
    c = BN_CTX_get(ctx);
    p = BN_CTX_get(ctx);
    test = BN_CTX_get(ctx);

    if (!BN_lshift(test,BN_value_one(),bits-1))
        goto err;

    for (;;)
    {
        for (;;) /* find q */
        {
            int seed_is_random;

            /* step 1 */
            if(!BN_GENCB_call(cb, 0, m++))
                goto err;

            if (!seed_len)
            {
                RAND_pseudo_bytes(seed,SHA_DIGEST_LENGTH);
                seed_is_random = 1;
            }
            else
            {
                seed_is_random = 0;
                seed_len=0; /* use random seed if 'seed_in' turns out to be bad*/
            }
            memcpy(buf,seed,SHA_DIGEST_LENGTH);
            memcpy(buf2,seed,SHA_DIGEST_LENGTH);
            /* precompute "SEED + 1" for step 7: */
            for (i=SHA_DIGEST_LENGTH-1; i >= 0; i--)
            {
                buf[i]++;
                if (buf[i] != 0) break;
            }

            /* step 2 */
            EVP_Digest(seed,SHA_DIGEST_LENGTH,md,NULL,HASH, NULL);
            EVP_Digest(buf,SHA_DIGEST_LENGTH,buf2,NULL,HASH, NULL);
            for (i=0; i<SHA_DIGEST_LENGTH; i++)
                md[i]^=buf2[i];

            /* step 3 */
            md[0]|=0x80;
            md[SHA_DIGEST_LENGTH-1]|=0x01;
            if (!BN_bin2bn(md,SHA_DIGEST_LENGTH,q)) goto err;

            /* step 4 */
            r = BN_is_prime_fasttest_ex(q, DSS_prime_checks, ctx,
                                        seed_is_random, cb);
            if (r > 0)
                break;
            if (r != 0)
                goto err;

            /* do a callback call */
            /* step 5 */
        }

        if(!BN_GENCB_call(cb, 2, 0)) goto err;
        if(!BN_GENCB_call(cb, 3, 0)) goto err;

        /* step 6 */
        counter=0;
        /* "offset = 2" */

        n=(bits-1)/160;
        b=(bits-1)-n*160;

        for (;;)
        {
            if ((counter != 0) && !BN_GENCB_call(cb, 0, counter))
                goto err;

            /* step 7 */
            BN_zero(W);
            /* now 'buf' contains "SEED + offset - 1" */
            for (k=0; k<=n; k++)
            {
                /* obtain "SEED + offset + k" by incrementing: */
                for (i=SHA_DIGEST_LENGTH-1; i >= 0; i--)
                {
                    buf[i]++;
                    if (buf[i] != 0) break;
                }

                EVP_Digest(buf,SHA_DIGEST_LENGTH,md,NULL,HASH, NULL);

                /* step 8 */
                if (!BN_bin2bn(md,SHA_DIGEST_LENGTH,r0))
                    goto err;
                if (!BN_lshift(r0,r0,160*k)) goto err;
                if (!BN_add(W,W,r0)) goto err;
            }

            /* more of step 8 */
            if (!BN_mask_bits(W,bits-1)) goto err;
            if (!BN_copy(X,W)) goto err;
            if (!BN_add(X,X,test)) goto err;

            /* step 9 */
            if (!BN_lshift1(r0,q)) goto err;
            if (!BN_mod(c,X,r0,ctx)) goto err;
            if (!BN_sub(r0,c,BN_value_one())) goto err;
            if (!BN_sub(p,X,r0)) goto err;

            /* step 10 */
            if (BN_cmp(p,test) >= 0)
            {
                /* step 11 */
                r = BN_is_prime_fasttest_ex(p, DSS_prime_checks,
                                            ctx, 1, cb);
                if (r > 0)
                    goto end; /* found it */
                if (r != 0)
                    goto err;
            }

            /* step 13 */
            counter++;
            /* "offset = offset + n + 1" */

            /* step 14 */
            if (counter >= 4096) break;
        }
    }
end:
    if(!BN_GENCB_call(cb, 2, 1))
        goto err;

    /* We now need to generate g */
    /* Set r0=(p-1)/q */
    if (!BN_sub(test,p,BN_value_one())) goto err;
    if (!BN_div(r0,NULL,test,q,ctx)) goto err;

    if (!BN_set_word(test,h)) goto err;
    if (!BN_MONT_CTX_set(mont,p,ctx)) goto err;

    for (;;)
    {
        /* g=test^r0%p */
        if (!BN_mod_exp_mont(g,test,r0,p,ctx,mont)) goto err;
        if (!BN_is_one(g)) break;
        if (!BN_add(test,test,BN_value_one())) goto err;
        h++;
    }

    if(!BN_GENCB_call(cb, 3, 1))
        goto err;

    ok=1;
err:
    if (ok)
    {
        if(ret->p) BN_free(ret->p);
        if(ret->q) BN_free(ret->q);
        if(ret->g) BN_free(ret->g);
        ret->p=BN_dup(p);
        ret->q=BN_dup(q);
        ret->g=BN_dup(g);
        if (ret->p == NULL || ret->q == NULL || ret->g == NULL)
        {
            ok=0;
            goto err;
        }
        if (seed_in != NULL) memcpy(seed_in,seed,20);
        if (counter_ret != NULL) *counter_ret=counter;
        if (h_ret != NULL) *h_ret=h;
    }
    if(ctx)
    {
        BN_CTX_end(ctx);
        BN_CTX_free(ctx);
    }
    if (mont != NULL) BN_MONT_CTX_free(mont);
    return ok;
}
Пример #17
0
static int probable_prime_dh_safe(BIGNUM *p, int bits, const BIGNUM *padd,
                                  const BIGNUM *rem, BN_CTX *ctx) {
  int i, ret = 0;
  BIGNUM *t1, *qadd, *q;

  bits--;
  BN_CTX_start(ctx);
  t1 = BN_CTX_get(ctx);
  q = BN_CTX_get(ctx);
  qadd = BN_CTX_get(ctx);
  if (qadd == NULL) {
    goto err;
  }

  if (!BN_rshift1(qadd, padd)) {
    goto err;
  }

  if (!BN_rand(q, bits, BN_RAND_TOP_ONE, BN_RAND_BOTTOM_ODD)) {
    goto err;
  }

  /* we need ((rnd-rem) % add) == 0 */
  if (!BN_mod(t1, q, qadd, ctx)) {
    goto err;
  }

  if (!BN_sub(q, q, t1)) {
    goto err;
  }

  if (rem == NULL) {
    if (!BN_add_word(q, 1)) {
      goto err;
    }
  } else {
    if (!BN_rshift1(t1, rem)) {
      goto err;
    }
    if (!BN_add(q, q, t1)) {
      goto err;
    }
  }

  /* we now have a random number 'rand' to test. */
  if (!BN_lshift1(p, q)) {
    goto err;
  }
  if (!BN_add_word(p, 1)) {
    goto err;
  }

loop:
  for (i = 1; i < NUMPRIMES; i++) {
    /* check that p and q are prime */
    /* check that for p and q
     * gcd(p-1,primes) == 1 (except for 2) */
    BN_ULONG pmod = BN_mod_word(p, (BN_ULONG)primes[i]);
    BN_ULONG qmod = BN_mod_word(q, (BN_ULONG)primes[i]);
    if (pmod == (BN_ULONG)-1 || qmod == (BN_ULONG)-1) {
      goto err;
    }
    if (pmod == 0 || qmod == 0) {
      if (!BN_add(p, p, padd)) {
        goto err;
      }
      if (!BN_add(q, q, qadd)) {
        goto err;
      }
      goto loop;
    }
  }

  ret = 1;

err:
  BN_CTX_end(ctx);
  return ret;
}