/* 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; }
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); }
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); }
/* 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; }
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; }
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; }
/* 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; }
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); }
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; }
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; }
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); }
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; }
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; }
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); }
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; }
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; }