/* * Set the coordinates of an EC_POINT using affine coordinates. Note that * the simple implementation only uses affine coordinates. */ int ec_GF2m_simple_point_set_affine_coordinates(const EC_GROUP *group, EC_POINT *point, const BIGNUM *x, const BIGNUM *y, BN_CTX *ctx) { int ret = 0; if (x == NULL || y == NULL) { ECerr(EC_F_EC_GF2M_SIMPLE_POINT_SET_AFFINE_COORDINATES, ERR_R_PASSED_NULL_PARAMETER); return 0; } if (!BN_copy(&point->X, x)) goto err; BN_set_negative(&point->X, 0); if (!BN_copy(&point->Y, y)) goto err; BN_set_negative(&point->Y, 0); if (!BN_copy(&point->Z, BN_value_one())) goto err; BN_set_negative(&point->Z, 0); point->Z_is_one = 1; ret = 1; err: return ret; }
/* Gets the affine coordinates of an EC_POINT. * Note that the simple implementation only uses affine coordinates. */ int ec_GF2m_simple_point_get_affine_coordinates(const EC_GROUP *group, const EC_POINT *point, BIGNUM *x, BIGNUM *y, BN_CTX *ctx) { int ret = 0; if (EC_POINT_is_at_infinity(group, point)) { ECerr(EC_F_EC_GF2M_SIMPLE_POINT_GET_AFFINE_COORDINATES, EC_R_POINT_AT_INFINITY); return 0; } if (BN_cmp(&point->Z, BN_value_one())) { ECerr(EC_F_EC_GF2M_SIMPLE_POINT_GET_AFFINE_COORDINATES, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); return 0; } if (x != NULL) { if (!BN_copy(x, &point->X)) goto err; BN_set_negative(x, 0); } if (y != NULL) { if (!BN_copy(y, &point->Y)) goto err; BN_set_negative(y, 0); } ret = 1; err: return ret; }
static int test_bad_key(void) { RSA *key = RSA_new(); BIGNUM e; BN_init(&e); BN_set_word(&e, RSA_F4); if (!RSA_generate_key_ex(key, 512, &e, NULL)) { fprintf(stderr, "RSA_generate_key_ex failed.\n"); ERR_print_errors_fp(stderr); return 0; } if (!BN_add(key->p, key->p, BN_value_one())) { fprintf(stderr, "BN error.\n"); ERR_print_errors_fp(stderr); return 0; } if (RSA_check_key(key)) { fprintf(stderr, "RSA_check_key passed with invalid key!\n"); return 0; } ERR_clear_error(); BN_free(&e); RSA_free(key); return 1; }
/* 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; }
int ec_GFp_mont_group_set_curve(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) { BN_CTX *new_ctx = NULL; BN_MONT_CTX *mont = NULL; BIGNUM *one = NULL; int ret = 0; if (group->field_data1 != NULL) { BN_MONT_CTX_free(group->field_data1); group->field_data1 = NULL; } if (group->field_data2 != NULL) { BN_free(group->field_data2); group->field_data2 = NULL; } if (ctx == NULL) { ctx = new_ctx = BN_CTX_new(); if (ctx == NULL) return 0; } mont = BN_MONT_CTX_new(); if (mont == NULL) goto err; if (!BN_MONT_CTX_set(mont, p, ctx)) { ECerr(EC_F_EC_GFP_MONT_GROUP_SET_CURVE, ERR_R_BN_LIB); goto err; } one = BN_new(); if (one == NULL) goto err; if (!BN_to_montgomery(one, BN_value_one(), mont, ctx)) goto err; group->field_data1 = mont; mont = NULL; group->field_data2 = one; one = NULL; ret = ec_GFp_simple_group_set_curve(group, p, a, b, ctx); if (!ret) { BN_MONT_CTX_free(group->field_data1); group->field_data1 = NULL; BN_free(group->field_data2); group->field_data2 = NULL; } err: if (new_ctx != NULL) BN_CTX_free(new_ctx); if (mont != NULL) BN_MONT_CTX_free(mont); if (one != NULL) BN_free(one); return ret; }
int dh_pub_is_valid(const DH *dh, const BIGNUM *dh_pub) { int i; int n = BN_num_bits(dh_pub); int bits_set = 0; BIGNUM *tmp; const BIGNUM *p; if (BN_is_negative(dh_pub)) { logit("invalid public DH value: negative"); return 0; } if (BN_cmp(dh_pub, BN_value_one()) != 1) { /* pub_exp <= 1 */ logit("invalid public DH value: <= 1"); return 0; } if ((tmp = BN_new()) == NULL) { error("%s: BN_new failed", __func__); return 0; } DH_get0_pqg(dh, &p, NULL, NULL); if (!BN_sub(tmp, p, BN_value_one()) || BN_cmp(dh_pub, tmp) != -1) { /* pub_exp > p-2 */ BN_clear_free(tmp); logit("invalid public DH value: >= p-1"); return 0; } BN_clear_free(tmp); for (i = 0; i <= n; i++) if (BN_is_bit_set(dh_pub, i)) bits_set++; debug2("bits set: %d/%d", bits_set, BN_num_bits(p)); /* * if g==2 and bits_set==1 then computing log_g(dh_pub) is trivial */ if (bits_set < 4) { logit("invalid public DH value (%d/%d)", bits_set, BN_num_bits(p)); return 0; } return 1; }
a1int &a1int::operator ++ (void) { BIGNUM *bn = ASN1_INTEGER_to_BN(in, NULL); BN_add(bn, bn, BN_value_one()); BN_to_ASN1_INTEGER(bn, in); BN_free(bn); return *this; }
void test_lehmer_thm(void) { BIGNUM *v = BN_new(), *v2 = BN_new(), *h = BN_new(), *n = BN_new(), *p = BN_new(), *q = BN_new(), *g = BN_new(); BN_CTX *ctx = BN_CTX_new(); BN_dec2bn(&v, "2"); BN_dec2bn(&p, "181857351165158586099319592412492032999818333818932850952491024" "131283899677766672100915923041329384157985577418702469610834914" "6296393743554494871840505599"); BN_dec2bn(&q, "220481921324130321200060036818685031159071785249502660004347524" "831733577485433929892260897846567483448177204481081755191897197" "38283711758138566145322943999"); BN_mul(n, p, q, ctx); /* p + 1 */ BN_dec2bn(&h, "181857351165158586099319592412492032999818333818932850952491024" "131283899677766672100915923041329384157985577418702469610834914" "6296393743554494871840505600"); lucas(v, h, n, ctx); BN_sub(v2, v, BN_value_two()); BN_gcd(g, v2, n, ctx); assert(!BN_is_one(g)); /* another test */ BN_dec2bn(&v, "3"); BN_dec2bn(&p, "181857351165158586099319592412492032999818333818932850952491024" "131283899677766672100915923041329384157985577418702469610834914" "62963937435544948718405055999"); BN_generate_prime(q, 512, 1, NULL, NULL, NULL, NULL); BN_mul(n, p, q, ctx); BN_sub(h, p, BN_value_one()); BN_mul(h, h, BN_value_two(), ctx); lucas(v, h, n, ctx); BN_mod_sub(v2, v, BN_value_two(), n, ctx); BN_gcd(g, v2, n, ctx); assert(!BN_is_one(g)); assert(BN_cmp(g, n)); BN_free(q); BN_free(p); BN_free(v); BN_free(v2); BN_free(h); BN_CTX_free(ctx); }
static int old_dsa_priv_decode(EVP_PKEY *pkey, const unsigned char **pder, int derlen) { DSA *dsa; BN_CTX *ctx = NULL; BIGNUM *j, *p1, *newp1; if (!(dsa = d2i_DSAPrivateKey(NULL, pder, derlen))) { DSAerror(ERR_R_DSA_LIB); return 0; } ctx = BN_CTX_new(); if (ctx == NULL) goto err; /* * Check that p and q are consistent with each other. */ j = BN_CTX_get(ctx); p1 = BN_CTX_get(ctx); newp1 = BN_CTX_get(ctx); if (j == NULL || p1 == NULL || newp1 == NULL) goto err; /* p1 = p - 1 */ if (BN_sub(p1, dsa->p, BN_value_one()) == 0) goto err; /* j = (p - 1) / q */ if (BN_div_ct(j, NULL, p1, dsa->q, ctx) == 0) goto err; /* q * j should == p - 1 */ if (BN_mul(newp1, dsa->q, j, ctx) == 0) goto err; if (BN_cmp(newp1, p1) != 0) { DSAerror(DSA_R_BAD_Q_VALUE); goto err; } /* * Check that q is not a composite number. */ if (BN_is_prime_ex(dsa->q, BN_prime_checks, ctx, NULL) <= 0) { DSAerror(DSA_R_BAD_Q_VALUE); goto err; } BN_CTX_free(ctx); EVP_PKEY_assign_DSA(pkey, dsa); return 1; err: BN_CTX_free(ctx); DSA_free(dsa); return 0; }
int ec_GFp_simple_point_set_affine_coordinates(const EC_GROUP * group, EC_POINT * point, const BIGNUM * x, const BIGNUM * y, BN_CTX * ctx) { if (x == NULL || y == NULL) { /* unlike for projective coordinates, we do not tolerate this */ ECerror(ERR_R_PASSED_NULL_PARAMETER); return 0; } return EC_POINT_set_Jprojective_coordinates_GFp(group, point, x, y, BN_value_one(), ctx); }
/* calculate p-1 and q-1 */ void rsa_generate_additional_parameters(RSA *rsa) { BIGNUM *aux; BN_CTX *ctx; if ((aux = BN_new()) == NULL) fatal("rsa_generate_additional_parameters: BN_new failed"); if ((ctx = BN_CTX_new()) == NULL) fatal("rsa_generate_additional_parameters: BN_CTX_new failed"); if ((BN_sub(aux, rsa->q, BN_value_one()) == 0) || (BN_mod(rsa->dmq1, rsa->d, aux, ctx) == 0) || (BN_sub(aux, rsa->p, BN_value_one()) == 0) || (BN_mod(rsa->dmp1, rsa->d, aux, ctx) == 0)) fatal("rsa_generate_additional_parameters: BN_sub/mod failed"); BN_clear_free(aux); BN_CTX_free(ctx); }
int BN_is_prime_fasttest_ex(const BIGNUM *a, int checks, BN_CTX *ctx, int do_trial_division, BN_GENCB *cb) { if (BN_cmp(a, BN_value_one()) <= 0) { return 0; } /* first look for small factors */ if (!BN_is_odd(a)) { /* a is even => a is prime if and only if a == 2 */ return BN_is_word(a, 2); } /* Enhanced Miller-Rabin does not work for three. */ if (BN_is_word(a, 3)) { return 1; } if (do_trial_division) { for (int i = 1; i < NUMPRIMES; i++) { BN_ULONG mod = BN_mod_word(a, primes[i]); if (mod == (BN_ULONG)-1) { return -1; } if (mod == 0) { return BN_is_word(a, primes[i]); } } if (!BN_GENCB_call(cb, 1, -1)) { return -1; } } int ret = -1; BN_CTX *ctx_allocated = NULL; if (ctx == NULL) { ctx_allocated = BN_CTX_new(); if (ctx_allocated == NULL) { return -1; } ctx = ctx_allocated; } enum bn_primality_result_t result; if (!BN_enhanced_miller_rabin_primality_test(&result, a, checks, ctx, cb)) { goto err; } ret = (result == bn_probably_prime); err: BN_CTX_free(ctx_allocated); return ret; }
uint8_t sane_key(RSA *rsa) { // checks sanity of a RSA key (PKCS#1 v2.1) uint8_t sane = 1; BN_CTX *ctx = BN_CTX_new(); BN_CTX_start(ctx); BIGNUM *p1 = BN_CTX_get(ctx), // p - 1 *q1 = BN_CTX_get(ctx), // q - 1 *chk = BN_CTX_get(ctx), // storage to run checks with *gcd = BN_CTX_get(ctx), // GCD(p - 1, q - 1) *lambda = BN_CTX_get(ctx); // LCM(p - 1, q - 1) BN_sub(p1, rsa->p, BN_value_one()); // p - 1 BN_sub(q1, rsa->q, BN_value_one()); // q - 1 BN_gcd(gcd, p1, q1, ctx); // gcd(p - 1, q - 1) BN_lcm(lambda, p1, q1, gcd, ctx); // lambda(n) BN_gcd(chk, lambda, rsa->e, ctx); // check if e is coprime to lambda(n) if(!BN_is_one(chk)) sane = 0; // check if public exponent e is less than n - 1 BN_sub(chk, rsa->e, rsa->n); // subtract n from e to avoid checking BN_is_zero if(!chk->neg) sane = 0; BN_mod_inverse(rsa->d, rsa->e, lambda, ctx); // d BN_mod(rsa->dmp1, rsa->d, p1, ctx); // d mod (p - 1) BN_mod(rsa->dmq1, rsa->d, q1, ctx); // d mod (q - 1) BN_mod_inverse(rsa->iqmp, rsa->q, rsa->p, ctx); // q ^ -1 mod p BN_CTX_end(ctx); BN_CTX_free(ctx); // this is excessive but you're better off safe than (very) sorry // in theory this should never be true unless I made a mistake ;) if((RSA_check_key(rsa) != 1) && sane) { fprintf(stderr, "WARNING: Key looked okay, but OpenSSL says otherwise!\n"); sane = 0; } return sane; }
int ec_GFp_mont_group_set_curve(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) { BN_CTX *new_ctx = NULL; BN_MONT_CTX *mont = NULL; BIGNUM *one = NULL; int ret = 0; BN_MONT_CTX_free(group->mont); group->mont = NULL; BN_free(group->one); group->one = NULL; if (ctx == NULL) { ctx = new_ctx = BN_CTX_new(); if (ctx == NULL) { return 0; } } mont = BN_MONT_CTX_new(); if (mont == NULL) { goto err; } if (!BN_MONT_CTX_set(mont, p, ctx)) { OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB); goto err; } one = BN_new(); if (one == NULL || !BN_to_montgomery(one, BN_value_one(), mont, ctx)) { goto err; } group->mont = mont; mont = NULL; group->one = one; one = NULL; ret = ec_GFp_simple_group_set_curve(group, p, a, b, ctx); if (!ret) { BN_MONT_CTX_free(group->mont); group->mont = NULL; BN_free(group->one); group->one = NULL; } err: BN_CTX_free(new_ctx); BN_MONT_CTX_free(mont); BN_free(one); return ret; }
/* calculate p-1 and q-1 */ static void rsa_generate_additional_parameters(RSA *rsa) { BIGNUM *aux = NULL; BN_CTX *ctx = NULL; if ((aux = BN_new()) == NULL) goto error; if ((ctx = BN_CTX_new()) == NULL) goto error; if ((BN_sub(aux, rsa->q, BN_value_one()) == 0) || (BN_mod(rsa->dmq1, rsa->d, aux, ctx) == 0) || (BN_sub(aux, rsa->p, BN_value_one()) == 0) || (BN_mod(rsa->dmp1, rsa->d, aux, ctx) == 0)) goto error; error: if (aux) BN_clear_free(aux); if (ctx) BN_CTX_free(ctx); }
BOOL rsautil_quickimport(RSA *rsa, BIGNUM *e_value, BIGNUM *p_value, BIGNUM *q_value, OPTIONAL BIGNUM *n_value) { BIGNUM *r0, *r1, *r2; BN_CTX *ctx; ctx = BN_CTX_new(); BN_CTX_start(ctx); r0 = BN_CTX_get(ctx); r1 = BN_CTX_get(ctx); r2 = BN_CTX_get(ctx); rsa->n = BN_new(); rsa->d = BN_new(); rsa->e = BN_new(); rsa->p = BN_new(); rsa->q = BN_new(); rsa->dmp1 = BN_new(); rsa->dmq1 = BN_new(); rsa->iqmp = BN_new(); BN_copy(rsa->e, e_value); BN_copy(rsa->p, p_value); BN_copy(rsa->q, q_value); if(n_value) BN_copy(rsa->n, n_value); else BN_mul(rsa->n, rsa->p, rsa->q, ctx); BN_sub(r1, rsa->p, BN_value_one()); BN_sub(r2, rsa->q, BN_value_one()); BN_mul(r0, r1, r2, ctx); BN_mod_inverse(rsa->d, rsa->e, r0, ctx); BN_mod(rsa->dmp1, rsa->d, r1, ctx); BN_mod(rsa->dmq1, rsa->d, r2, ctx); BN_mod_inverse(rsa->iqmp, rsa->q, rsa->p, ctx); BN_CTX_end(ctx); BN_CTX_free(ctx); return (RSA_check_key(rsa) == 1); }
static void schnorr_selftest(void) { BIGNUM *x; struct modp_group *grp; u_int i; char *hh; grp = jpake_default_group(); if ((x = BN_new()) == NULL) fatal("%s: BN_new", __func__); SCHNORR_DEBUG_BN((grp->p, "%s: grp->p = ", __func__)); SCHNORR_DEBUG_BN((grp->q, "%s: grp->q = ", __func__)); SCHNORR_DEBUG_BN((grp->g, "%s: grp->g = ", __func__)); /* [1, 20) */ for (i = 1; i < 20; i++) { printf("x = %u\n", i); fflush(stdout); if (BN_set_word(x, i) != 1) fatal("%s: set x word", __func__); schnorr_selftest_one(grp->p, grp->q, grp->g, x); } /* 100 x random [0, p) */ for (i = 0; i < 100; i++) { if (BN_rand_range(x, grp->p) != 1) fatal("%s: BN_rand_range", __func__); hh = BN_bn2hex(x); printf("x = (random) 0x%s\n", hh); free(hh); fflush(stdout); schnorr_selftest_one(grp->p, grp->q, grp->g, x); } /* [q-20, q) */ if (BN_set_word(x, 20) != 1) fatal("%s: BN_set_word (x = 20)", __func__); if (BN_sub(x, grp->q, x) != 1) fatal("%s: BN_sub (q - x)", __func__); for (i = 0; i < 19; i++) { hh = BN_bn2hex(x); printf("x = (q - %d) 0x%s\n", 20 - i, hh); free(hh); fflush(stdout); schnorr_selftest_one(grp->p, grp->q, grp->g, x); if (BN_add(x, x, BN_value_one()) != 1) fatal("%s: BN_add (x + 1)", __func__); } BN_free(x); }
BIGNUM * DH_get_order(const DH *dh, BN_CTX *ctx) { BIGNUM *order = NULL, *bn = NULL; const BIGNUM *p, *g; check(dh && ctx, "Invalid argument"); BN_CTX_start(ctx); DH_get0_pqg(dh, &p, NULL, &g); /* suppose the order of g is q-1 */ order = DH_get_q(dh, ctx); bn = BN_CTX_get(ctx); if (!bn || !order || !BN_sub_word(order, 1) || !BN_mod_exp(bn, g, order, p, ctx)) goto err; if (BN_cmp(bn, BN_value_one()) != 0) { /* if bn != 1, then q-1 is not the order of g, but p-1 should be */ if (!BN_sub(order, p, BN_value_one()) || !BN_mod_exp(bn, g, order, p, ctx)) goto err; check(BN_cmp(bn, BN_value_one()) == 0, "Unable to get order"); } BN_CTX_end(ctx); return order; err: if (order) BN_clear_free(order); BN_CTX_end(ctx); return NULL; }
static BIGNUM *rsa_get_public_exp(const BIGNUM *d, const BIGNUM *p, const BIGNUM *q, BN_CTX *ctx) { BIGNUM *ret = NULL, *r0, *r1, *r2; if (d == NULL || p == NULL || q == NULL) return NULL; BN_CTX_start(ctx); r0 = BN_CTX_get(ctx); r1 = BN_CTX_get(ctx); r2 = BN_CTX_get(ctx); if (r2 == NULL) goto err; if (!BN_sub(r1, p, BN_value_one())) goto err; if (!BN_sub(r2, q, BN_value_one())) goto err; if (!BN_mul(r0, r1, r2, ctx)) goto err; ret = BN_mod_inverse(NULL, d, r0, ctx); err: BN_CTX_end(ctx); return ret; }
static int test_check_public_exponent(void) { int ret = 0; BIGNUM *e = NULL; ret = TEST_ptr(e = BN_new()) /* e is too small */ && TEST_true(BN_set_word(e, 65535)) && TEST_false(rsa_check_public_exponent(e)) /* e is even will fail */ && TEST_true(BN_set_word(e, 65536)) && TEST_false(rsa_check_public_exponent(e)) /* e is ok */ && TEST_true(BN_set_word(e, 65537)) && TEST_true(rsa_check_public_exponent(e)) /* e = 2^256 is too big */ && TEST_true(BN_lshift(e, BN_value_one(), 256)) && TEST_false(rsa_check_public_exponent(e)) /* e = 2^256-1 is odd and in range */ && TEST_true(BN_sub(e, e, BN_value_one())) && TEST_true(rsa_check_public_exponent(e)); BN_free(e); return ret; }
/* encrypts (or decrypts) with private key, not sensitive to timing attacks (blind encryption) */ void rsa_encrypt_secure(BIGNUM* m, const BIGNUM* d, const BIGNUM* e, const BIGNUM* n, const unsigned char * r_bin, int r_len) { BN_CTX *ctx; BIGNUM *tmp = BN_new(); BIGNUM *r = BN_new(); BIGNUM *r_inv = BN_new(); ctx = BN_CTX_new(); BN_bin2bn(r_bin, r_len, r); BN_mod(r, r, n, ctx); /* r = r % n */ /* printf(" r input: ");BN_print_fp(stdout, r); printf(" n: ");BN_print_fp(stdout, n); printf("\n"); */ BN_mod(tmp, n, r, ctx); /*printf("r=");BN_print_fp(stdout, r); printf("; tmp=");BN_print_fp(stdout, tmp);*/ while (BN_is_zero(tmp)) { /* */ BN_mod_add(r, r, BN_value_one(), n, ctx); BN_mod(tmp, n, r, ctx); /*printf("r=");BN_print_fp(stdout, r); printf("; tmp=");BN_print_fp(stdout, tmp);*/ } /*printf("\n");*/ BN_mod_inverse(r_inv, r, n, ctx); /* printf(" r = ");BN_print_fp(stdout, r); printf(" r_inv = ");BN_print_fp(stdout, r_inv); printf(" n = ");BN_print_fp(stdout, n); printf("\n"); */ BN_mod_exp(r, r, e, n, ctx); /* r = r^e % n */ BN_mod_mul(m, m, r, n, ctx); /* m = m * r % n */ rsa_encrypt(m, d, n); BN_mod_mul(m, m, r_inv, n, ctx); BN_free(r); BN_free(r_inv); BN_free(tmp); BN_CTX_free(ctx); }
int MKEM_generate_message(const MKEM *kp, uint8_t *secret, uint8_t *message) { BIGNUM u; uint8_t pad; int rv = -1; BN_init(&u); if (BN_rand_range(&u, kp->params->maxu) && BN_add(&u, &u, BN_value_one()) && RAND_bytes(&pad, 1) && !MKEM_generate_message_u(kp, &u, pad, secret, message)) rv = 0; BN_clear(&u); return rv; }
/* See FIPS 186-4 C.3.1 Miller Rabin Probabilistic Primality Test. */ int BN_is_prime_fasttest_ex(const BIGNUM *w, int checks, BN_CTX *ctx_passed, int do_trial_division, BN_GENCB *cb) { int i, status, ret = -1; BN_CTX *ctx = NULL; /* w must be bigger than 1 */ if (BN_cmp(w, BN_value_one()) <= 0) return 0; /* w must be odd */ if (BN_is_odd(w)) { /* Take care of the really small prime 3 */ if (BN_is_word(w, 3)) return 1; } else { /* 2 is the only even prime */ return BN_is_word(w, 2); } /* first look for small factors */ if (do_trial_division) { for (i = 1; i < NUMPRIMES; i++) { BN_ULONG mod = BN_mod_word(w, primes[i]); if (mod == (BN_ULONG)-1) return -1; if (mod == 0) return BN_is_word(w, primes[i]); } if (!BN_GENCB_call(cb, 1, -1)) return -1; } if (ctx_passed != NULL) ctx = ctx_passed; else if ((ctx = BN_CTX_new()) == NULL) goto err; ret = bn_miller_rabin_is_prime(w, checks, ctx, cb, 0, &status); if (!ret) goto err; ret = (status == BN_PRIMETEST_PROBABLY_PRIME); err: if (ctx_passed == NULL) BN_CTX_free(ctx); return ret; }
int example_EC_POINT_mul() { /* This example ensures that 10×∞ + G = G, in P-256. */ EC_GROUP *group = NULL; EC_POINT *p = NULL, *result = NULL; BIGNUM *n = NULL; int ret = 0; const EC_POINT *generator; group = EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1); p = EC_POINT_new(group); result = EC_POINT_new(group); n = BN_new(); if (p == NULL || result == NULL || group == NULL || n == NULL || !EC_POINT_set_to_infinity(group, p) || !BN_set_word(n, 10)) { goto err; } /* First check that 10×∞ = ∞. */ if (!EC_POINT_mul(group, result, NULL, p, n, NULL) || !EC_POINT_is_at_infinity(group, result)) { goto err; } generator = EC_GROUP_get0_generator(group); /* Now check that 10×∞ + G = G. */ if (!EC_POINT_mul(group, result, BN_value_one(), p, n, NULL) || EC_POINT_cmp(group, result, generator, NULL) != 0) { goto err; } ret = 1; err: BN_free(n); EC_POINT_free(result); EC_POINT_free(p); EC_GROUP_free(group); return ret; }
EC_POINT *embed(const polypseud_ctx *ctx, const unsigned char *data, const size_t len) { BIGNUM *t1 = BN_bin2bn(data, len, NULL); BIGNUM *x = BN_new(); BN_mod(x, t1, ctx->p, ctx->bn_ctx); EC_POINT *point = EC_POINT_new(ctx->ec_group); unsigned char counter = 0; int success = 0; while(!success) { success = EC_POINT_set_compressed_coordinates_GFp(ctx->ec_group, point, x, 1, ctx->bn_ctx); if(!success) { if(counter == 0) { BN_lshift(x, x, 8); } BN_add(x, x, BN_value_one()); } } BN_free(x); BN_free(t1); return point; }
int ec_GFp_simple_point_set_affine_coordinates(const EC_GROUP *group, EC_POINT *point, const BIGNUM *x, const BIGNUM *y, BN_CTX *ctx) { if (x == NULL || y == NULL) { /* unlike for projective coordinates, we do not tolerate this */ OPENSSL_PUT_ERROR(EC, ERR_R_PASSED_NULL_PARAMETER); return 0; } if (!ec_point_set_Jprojective_coordinates_GFp(group, point, x, y, BN_value_one(), ctx)) { return 0; } if (!ec_GFp_simple_is_on_curve(group, point, ctx)) { OPENSSL_PUT_ERROR(EC, EC_R_POINT_IS_NOT_ON_CURVE); return 0; } return 1; }
static int dss_paramcheck(int nmod, BIGNUM *p, BIGNUM *q, BIGNUM *g, BN_CTX *ctx) { BIGNUM *rem = NULL; if (BN_num_bits(p) != nmod) return 0; if (BN_num_bits(q) != 160) return 0; if (BN_is_prime_ex(p, BN_prime_checks, ctx, NULL) != 1) return 0; if (BN_is_prime_ex(q, BN_prime_checks, ctx, NULL) != 1) return 0; rem = BN_new(); if (!BN_mod(rem, p, q, ctx) || !BN_is_one(rem) || (BN_cmp(g, BN_value_one()) <= 0) || !BN_mod_exp(rem, g, q, p, ctx) || !BN_is_one(rem)) { BN_free(rem); return 0; } /* Todo: check g */ BN_free(rem); return 1; }
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; }
int process_peer_commit (pwd_session_t *sess, uint8_t *commit, BN_CTX *bnctx) { uint8_t *ptr; BIGNUM *x = NULL, *y = NULL, *cofactor = NULL; EC_POINT *K = NULL, *point = NULL; int res = 1; if (((sess->peer_scalar = BN_new()) == NULL) || ((sess->k = BN_new()) == NULL) || ((cofactor = BN_new()) == NULL) || ((x = BN_new()) == NULL) || ((y = BN_new()) == NULL) || ((point = EC_POINT_new(sess->group)) == NULL) || ((K = EC_POINT_new(sess->group)) == NULL) || ((sess->peer_element = EC_POINT_new(sess->group)) == NULL)) { DEBUG2("pwd: failed to allocate room to process peer's commit"); goto fin; } if (!EC_GROUP_get_cofactor(sess->group, cofactor, NULL)) { DEBUG2("pwd: unable to get group co-factor"); goto fin; } /* element, x then y, followed by scalar */ ptr = (uint8_t *)commit; BN_bin2bn(ptr, BN_num_bytes(sess->prime), x); ptr += BN_num_bytes(sess->prime); BN_bin2bn(ptr, BN_num_bytes(sess->prime), y); ptr += BN_num_bytes(sess->prime); BN_bin2bn(ptr, BN_num_bytes(sess->order), sess->peer_scalar); if (!EC_POINT_set_affine_coordinates_GFp(sess->group, sess->peer_element, x, y, bnctx)) { DEBUG2("pwd: unable to get coordinates of peer's element"); goto fin; } /* check to ensure peer's element is not in a small sub-group */ if (BN_cmp(cofactor, BN_value_one())) { if (!EC_POINT_mul(sess->group, point, NULL, sess->peer_element, cofactor, NULL)) { DEBUG2("pwd: unable to multiply element by co-factor"); goto fin; } if (EC_POINT_is_at_infinity(sess->group, point)) { DEBUG2("pwd: peer's element is in small sub-group"); goto fin; } } /* compute the shared key, k */ if ((!EC_POINT_mul(sess->group, K, NULL, sess->pwe, sess->peer_scalar, bnctx)) || (!EC_POINT_add(sess->group, K, K, sess->peer_element, bnctx)) || (!EC_POINT_mul(sess->group, K, NULL, K, sess->private_value, bnctx))) { DEBUG2("pwd: unable to compute shared key, k"); goto fin; } /* ensure that the shared key isn't in a small sub-group */ if (BN_cmp(cofactor, BN_value_one())) { if (!EC_POINT_mul(sess->group, K, NULL, K, cofactor, NULL)) { DEBUG2("pwd: unable to multiply k by co-factor"); goto fin; } } /* * This check is strictly speaking just for the case above where * co-factor > 1 but it was suggested that even though this is probably * never going to happen it is a simple and safe check "just to be * sure" so let's be safe. */ if (EC_POINT_is_at_infinity(sess->group, K)) { DEBUG2("pwd: k is point-at-infinity!"); goto fin; } if (!EC_POINT_get_affine_coordinates_GFp(sess->group, K, sess->k, NULL, bnctx)) { DEBUG2("pwd: unable to get shared secret from K"); goto fin; } res = 0; fin: EC_POINT_free(K); EC_POINT_free(point); BN_free(cofactor); BN_free(x); BN_free(y); return res; }
int compute_password_element (pwd_session_t *sess, uint16_t grp_num, char *password, int password_len, char *id_server, int id_server_len, char *id_peer, int id_peer_len, uint32_t *token) { BIGNUM *x_candidate = NULL, *rnd = NULL, *cofactor = NULL; HMAC_CTX ctx; uint8_t pwe_digest[SHA256_DIGEST_LENGTH], *prfbuf = NULL, ctr; int nid, is_odd, primebitlen, primebytelen, ret = 0; switch (grp_num) { /* from IANA registry for IKE D-H groups */ case 19: nid = NID_X9_62_prime256v1; break; case 20: nid = NID_secp384r1; break; case 21: nid = NID_secp521r1; break; case 25: nid = NID_X9_62_prime192v1; break; case 26: nid = NID_secp224r1; break; default: DEBUG("unknown group %d", grp_num); goto fail; } sess->pwe = NULL; sess->order = NULL; sess->prime = NULL; if ((sess->group = EC_GROUP_new_by_curve_name(nid)) == NULL) { DEBUG("unable to create EC_GROUP"); goto fail; } if (((rnd = BN_new()) == NULL) || ((cofactor = BN_new()) == NULL) || ((sess->pwe = EC_POINT_new(sess->group)) == NULL) || ((sess->order = BN_new()) == NULL) || ((sess->prime = BN_new()) == NULL) || ((x_candidate = BN_new()) == NULL)) { DEBUG("unable to create bignums"); goto fail; } if (!EC_GROUP_get_curve_GFp(sess->group, sess->prime, NULL, NULL, NULL)) { DEBUG("unable to get prime for GFp curve"); goto fail; } if (!EC_GROUP_get_order(sess->group, sess->order, NULL)) { DEBUG("unable to get order for curve"); goto fail; } if (!EC_GROUP_get_cofactor(sess->group, cofactor, NULL)) { DEBUG("unable to get cofactor for curve"); goto fail; } primebitlen = BN_num_bits(sess->prime); primebytelen = BN_num_bytes(sess->prime); if ((prfbuf = talloc_zero_array(sess, uint8_t, primebytelen)) == NULL) { DEBUG("unable to alloc space for prf buffer"); goto fail; } ctr = 0; while (1) { if (ctr > 10) { DEBUG("unable to find random point on curve for group %d, something's fishy", grp_num); goto fail; } ctr++; /* * compute counter-mode password value and stretch to prime * pwd-seed = H(token | peer-id | server-id | password | * counter) */ H_Init(&ctx); H_Update(&ctx, (uint8_t *)token, sizeof(*token)); H_Update(&ctx, (uint8_t *)id_peer, id_peer_len); H_Update(&ctx, (uint8_t *)id_server, id_server_len); H_Update(&ctx, (uint8_t *)password, password_len); H_Update(&ctx, (uint8_t *)&ctr, sizeof(ctr)); H_Final(&ctx, pwe_digest); BN_bin2bn(pwe_digest, SHA256_DIGEST_LENGTH, rnd); eap_pwd_kdf(pwe_digest, SHA256_DIGEST_LENGTH, "EAP-pwd Hunting And Pecking", strlen("EAP-pwd Hunting And Pecking"), prfbuf, primebitlen); BN_bin2bn(prfbuf, primebytelen, x_candidate); /* * eap_pwd_kdf() returns a string of bits 0..primebitlen but * BN_bin2bn will treat that string of bits as a big endian * number. If the primebitlen is not an even multiple of 8 * then excessive bits-- those _after_ primebitlen-- so now * we have to shift right the amount we masked off. */ if (primebitlen % 8) { BN_rshift(x_candidate, x_candidate, (8 - (primebitlen % 8))); } if (BN_ucmp(x_candidate, sess->prime) >= 0) { continue; } /* * need to unambiguously identify the solution, if there is * one... */ if (BN_is_odd(rnd)) { is_odd = 1; } else { is_odd = 0; } /* * solve the quadratic equation, if it's not solvable then we * don't have a point */ if (!EC_POINT_set_compressed_coordinates_GFp(sess->group, sess->pwe, x_candidate, is_odd, NULL)) { continue; } /* * If there's a solution to the equation then the point must be * on the curve so why check again explicitly? OpenSSL code * says this is required by X9.62. We're not X9.62 but it can't * hurt just to be sure. */ if (!EC_POINT_is_on_curve(sess->group, sess->pwe, NULL)) { DEBUG("EAP-pwd: point is not on curve"); continue; } if (BN_cmp(cofactor, BN_value_one())) { /* make sure the point is not in a small sub-group */ if (!EC_POINT_mul(sess->group, sess->pwe, NULL, sess->pwe, cofactor, NULL)) { DEBUG("EAP-pwd: cannot multiply generator by order"); continue; } if (EC_POINT_is_at_infinity(sess->group, sess->pwe)) { DEBUG("EAP-pwd: point is at infinity"); continue; } } /* if we got here then we have a new generator. */ break; } sess->group_num = grp_num; if (0) { fail: /* DON'T free sess, it's in handler->opaque */ ret = -1; } /* cleanliness and order.... */ BN_free(cofactor); BN_free(x_candidate); BN_free(rnd); talloc_free(prfbuf); return ret; }