int ec_key_simple_generate_key(EC_KEY *eckey) { int ok = 0; BN_CTX *ctx = NULL; BIGNUM *priv_key = NULL; const BIGNUM *order = NULL; EC_POINT *pub_key = NULL; if ((ctx = BN_CTX_new()) == NULL) goto err; if (eckey->priv_key == NULL) { priv_key = BN_new(); if (priv_key == NULL) goto err; } else priv_key = eckey->priv_key; order = EC_GROUP_get0_order(eckey->group); if (order == NULL) goto err; do if (!BN_priv_rand_range(priv_key, order)) goto err; while (BN_is_zero(priv_key)) ; if (eckey->pub_key == NULL) { pub_key = EC_POINT_new(eckey->group); if (pub_key == NULL) goto err; } else pub_key = eckey->pub_key; if (!EC_POINT_mul(eckey->group, pub_key, priv_key, NULL, NULL, ctx)) goto err; eckey->priv_key = priv_key; eckey->pub_key = pub_key; ok = 1; err: if (eckey->pub_key == NULL) EC_POINT_free(pub_key); if (eckey->priv_key != priv_key) BN_free(priv_key); BN_CTX_free(ctx); return ok; }
/*- * Apply randomization of EC point projective coordinates: * * (X, Y ,Z ) = (lambda^2*X, lambda^3*Y, lambda*Z) * lambda = [1,group->field) * */ int ec_GFp_simple_blind_coordinates(const EC_GROUP *group, EC_POINT *p, BN_CTX *ctx) { int ret = 0; BIGNUM *lambda = NULL; BIGNUM *temp = NULL; BN_CTX_start(ctx); lambda = BN_CTX_get(ctx); temp = BN_CTX_get(ctx); if (temp == NULL) { ECerr(EC_F_EC_GFP_SIMPLE_BLIND_COORDINATES, ERR_R_MALLOC_FAILURE); goto err; } /* make sure lambda is not zero */ do { if (!BN_priv_rand_range(lambda, group->field)) { ECerr(EC_F_EC_GFP_SIMPLE_BLIND_COORDINATES, ERR_R_BN_LIB); goto err; } } while (BN_is_zero(lambda)); /* if field_encode defined convert between representations */ if (group->meth->field_encode != NULL && !group->meth->field_encode(group, lambda, lambda, ctx)) goto err; if (!group->meth->field_mul(group, p->Z, p->Z, lambda, ctx)) goto err; if (!group->meth->field_sqr(group, temp, lambda, ctx)) goto err; if (!group->meth->field_mul(group, p->X, p->X, temp, ctx)) goto err; if (!group->meth->field_mul(group, temp, temp, lambda, ctx)) goto err; if (!group->meth->field_mul(group, p->Y, p->Y, temp, ctx)) goto err; p->Z_is_one = 0; ret = 1; err: BN_CTX_end(ctx); return ret; }
int BN_is_prime_fasttest_ex(const BIGNUM *a, int checks, BN_CTX *ctx_passed, int do_trial_division, BN_GENCB *cb) { int i, j, ret = -1; int k; BN_CTX *ctx = NULL; BIGNUM *A1, *A1_odd, *check; /* taken from ctx */ BN_MONT_CTX *mont = NULL; if (BN_cmp(a, BN_value_one()) <= 0) return 0; if (checks == BN_prime_checks) checks = BN_prime_checks_for_size(BN_num_bits(a)); /* 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); if (do_trial_division) { for (i = 1; i < NUMPRIMES; i++) { BN_ULONG mod = BN_mod_word(a, primes[i]); if (mod == (BN_ULONG)-1) goto err; if (mod == 0) return BN_is_word(a, primes[i]); } if (!BN_GENCB_call(cb, 1, -1)) goto err; } if (ctx_passed != NULL) ctx = ctx_passed; else if ((ctx = BN_CTX_new()) == NULL) goto err; BN_CTX_start(ctx); A1 = BN_CTX_get(ctx); A1_odd = BN_CTX_get(ctx); check = BN_CTX_get(ctx); if (check == NULL) goto err; /* compute A1 := a - 1 */ if (!BN_copy(A1, a)) goto err; if (!BN_sub_word(A1, 1)) goto err; if (BN_is_zero(A1)) { ret = 0; goto err; } /* write A1 as A1_odd * 2^k */ k = 1; while (!BN_is_bit_set(A1, k)) k++; if (!BN_rshift(A1_odd, A1, k)) goto err; /* Montgomery setup for computations mod a */ mont = BN_MONT_CTX_new(); if (mont == NULL) goto err; if (!BN_MONT_CTX_set(mont, a, ctx)) goto err; for (i = 0; i < checks; i++) { if (!BN_priv_rand_range(check, A1)) goto err; if (!BN_add_word(check, 1)) goto err; /* now 1 <= check < a */ j = witness(check, a, A1, A1_odd, k, ctx, mont); if (j == -1) goto err; if (j) { ret = 0; goto err; } if (!BN_GENCB_call(cb, 1, i)) goto err; } ret = 1; err: if (ctx != NULL) { BN_CTX_end(ctx); if (ctx_passed == NULL) BN_CTX_free(ctx); } BN_MONT_CTX_free(mont); return ret; }
/* * Refer to FIPS 186-4 C.3.2 Enhanced Miller-Rabin Probabilistic Primality Test. * OR C.3.1 Miller-Rabin Probabilistic Primality Test (if enhanced is zero). * The Step numbers listed in the code refer to the enhanced case. * * if enhanced is set, then status returns one of the following: * BN_PRIMETEST_PROBABLY_PRIME * BN_PRIMETEST_COMPOSITE_WITH_FACTOR * BN_PRIMETEST_COMPOSITE_NOT_POWER_OF_PRIME * if enhanced is zero, then status returns either * BN_PRIMETEST_PROBABLY_PRIME or * BN_PRIMETEST_COMPOSITE * * returns 0 if there was an error, otherwise it returns 1. */ int bn_miller_rabin_is_prime(const BIGNUM *w, int iterations, BN_CTX *ctx, BN_GENCB *cb, int enhanced, int *status) { int i, j, a, ret = 0; BIGNUM *g, *w1, *w3, *x, *m, *z, *b; BN_MONT_CTX *mont = NULL; /* w must be odd */ if (!BN_is_odd(w)) return 0; BN_CTX_start(ctx); g = BN_CTX_get(ctx); w1 = BN_CTX_get(ctx); w3 = BN_CTX_get(ctx); x = BN_CTX_get(ctx); m = BN_CTX_get(ctx); z = BN_CTX_get(ctx); b = BN_CTX_get(ctx); if (!(b != NULL /* w1 := w - 1 */ && BN_copy(w1, w) && BN_sub_word(w1, 1) /* w3 := w - 3 */ && BN_copy(w3, w) && BN_sub_word(w3, 3))) goto err; /* check w is larger than 3, otherwise the random b will be too small */ if (BN_is_zero(w3) || BN_is_negative(w3)) goto err; /* (Step 1) Calculate largest integer 'a' such that 2^a divides w-1 */ a = 1; while (!BN_is_bit_set(w1, a)) a++; /* (Step 2) m = (w-1) / 2^a */ if (!BN_rshift(m, w1, a)) goto err; /* Montgomery setup for computations mod a */ mont = BN_MONT_CTX_new(); if (mont == NULL || !BN_MONT_CTX_set(mont, w, ctx)) goto err; if (iterations == BN_prime_checks) iterations = BN_prime_checks_for_size(BN_num_bits(w)); /* (Step 4) */ for (i = 0; i < iterations; ++i) { /* (Step 4.1) obtain a Random string of bits b where 1 < b < w-1 */ if (!BN_priv_rand_range(b, w3) || !BN_add_word(b, 2)) /* 1 < b < w-1 */ goto err; if (enhanced) { /* (Step 4.3) */ if (!BN_gcd(g, b, w, ctx)) goto err; /* (Step 4.4) */ if (!BN_is_one(g)) { *status = BN_PRIMETEST_COMPOSITE_WITH_FACTOR; ret = 1; goto err; } } /* (Step 4.5) z = b^m mod w */ if (!BN_mod_exp_mont(z, b, m, w, ctx, mont)) goto err; /* (Step 4.6) if (z = 1 or z = w-1) */ if (BN_is_one(z) || BN_cmp(z, w1) == 0) goto outer_loop; /* (Step 4.7) for j = 1 to a-1 */ for (j = 1; j < a ; ++j) { /* (Step 4.7.1 - 4.7.2) x = z. z = x^2 mod w */ if (!BN_copy(x, z) || !BN_mod_mul(z, x, x, w, ctx)) goto err; /* (Step 4.7.3) */ if (BN_cmp(z, w1) == 0) goto outer_loop; /* (Step 4.7.4) */ if (BN_is_one(z)) goto composite; } /* At this point z = b^((w-1)/2) mod w */ /* (Steps 4.8 - 4.9) x = z, z = x^2 mod w */ if (!BN_copy(x, z) || !BN_mod_mul(z, x, x, w, ctx)) goto err; /* (Step 4.10) */ if (BN_is_one(z)) goto composite; /* (Step 4.11) x = b^(w-1) mod w */ if (!BN_copy(x, z)) goto err; composite: if (enhanced) { /* (Step 4.1.2) g = GCD(x-1, w) */ if (!BN_sub_word(x, 1) || !BN_gcd(g, x, w, ctx)) goto err; /* (Steps 4.1.3 - 4.1.4) */ if (BN_is_one(g)) *status = BN_PRIMETEST_COMPOSITE_NOT_POWER_OF_PRIME; else *status = BN_PRIMETEST_COMPOSITE_WITH_FACTOR; } else { *status = BN_PRIMETEST_COMPOSITE; } ret = 1; goto err; outer_loop: ; /* (Step 4.1.5) */ if (!BN_GENCB_call(cb, 1, i)) goto err; } /* (Step 5) */ *status = BN_PRIMETEST_PROBABLY_PRIME; ret = 1; err: BN_clear(g); BN_clear(w1); BN_clear(w3); BN_clear(x); BN_clear(m); BN_clear(z); BN_clear(b); BN_CTX_end(ctx); BN_MONT_CTX_free(mont); return ret; }
static int ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in, BIGNUM **kinvp, BIGNUM **rp, const unsigned char *dgst, int dlen) { BN_CTX *ctx = NULL; BIGNUM *k = NULL, *r = NULL, *X = NULL; const BIGNUM *order; EC_POINT *tmp_point = NULL; const EC_GROUP *group; int ret = 0; int order_bits; if (eckey == NULL || (group = EC_KEY_get0_group(eckey)) == NULL) { ECerr(EC_F_ECDSA_SIGN_SETUP, ERR_R_PASSED_NULL_PARAMETER); return 0; } if (!EC_KEY_can_sign(eckey)) { ECerr(EC_F_ECDSA_SIGN_SETUP, EC_R_CURVE_DOES_NOT_SUPPORT_SIGNING); return 0; } if (ctx_in == NULL) { if ((ctx = BN_CTX_new()) == NULL) { ECerr(EC_F_ECDSA_SIGN_SETUP, ERR_R_MALLOC_FAILURE); return 0; } } else ctx = ctx_in; k = BN_new(); /* this value is later returned in *kinvp */ r = BN_new(); /* this value is later returned in *rp */ X = BN_new(); if (k == NULL || r == NULL || X == NULL) { ECerr(EC_F_ECDSA_SIGN_SETUP, ERR_R_MALLOC_FAILURE); goto err; } if ((tmp_point = EC_POINT_new(group)) == NULL) { ECerr(EC_F_ECDSA_SIGN_SETUP, ERR_R_EC_LIB); goto err; } order = EC_GROUP_get0_order(group); if (order == NULL) { ECerr(EC_F_ECDSA_SIGN_SETUP, ERR_R_EC_LIB); goto err; } /* Preallocate space */ order_bits = BN_num_bits(order); if (!BN_set_bit(k, order_bits) || !BN_set_bit(r, order_bits) || !BN_set_bit(X, order_bits)) goto err; do { /* get random k */ do if (dgst != NULL) { if (!BN_generate_dsa_nonce (k, order, EC_KEY_get0_private_key(eckey), dgst, dlen, ctx)) { ECerr(EC_F_ECDSA_SIGN_SETUP, EC_R_RANDOM_NUMBER_GENERATION_FAILED); goto err; } } else { if (!BN_priv_rand_range(k, order)) { ECerr(EC_F_ECDSA_SIGN_SETUP, EC_R_RANDOM_NUMBER_GENERATION_FAILED); goto err; } } while (BN_is_zero(k)); /* compute r the x-coordinate of generator * k */ if (!EC_POINT_mul(group, tmp_point, k, NULL, NULL, ctx)) { ECerr(EC_F_ECDSA_SIGN_SETUP, ERR_R_EC_LIB); goto err; } if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) == NID_X9_62_prime_field) { if (!EC_POINT_get_affine_coordinates_GFp (group, tmp_point, X, NULL, ctx)) { ECerr(EC_F_ECDSA_SIGN_SETUP, ERR_R_EC_LIB); goto err; } } #ifndef OPENSSL_NO_EC2M else { /* NID_X9_62_characteristic_two_field */ if (!EC_POINT_get_affine_coordinates_GF2m(group, tmp_point, X, NULL, ctx)) { ECerr(EC_F_ECDSA_SIGN_SETUP, ERR_R_EC_LIB); goto err; } } #endif if (!BN_nnmod(r, X, order, ctx)) { ECerr(EC_F_ECDSA_SIGN_SETUP, ERR_R_BN_LIB); goto err; } } while (BN_is_zero(r)); /* Check if optimized inverse is implemented */ if (EC_GROUP_do_inverse_ord(group, k, k, ctx) == 0) { /* compute the inverse of k */ if (group->mont_data != NULL) { /* * We want inverse in constant time, therefore we utilize the fact * order must be prime and use Fermats Little Theorem instead. */ if (!BN_set_word(X, 2)) { ECerr(EC_F_ECDSA_SIGN_SETUP, ERR_R_BN_LIB); goto err; } if (!BN_mod_sub(X, order, X, order, ctx)) { ECerr(EC_F_ECDSA_SIGN_SETUP, ERR_R_BN_LIB); goto err; } BN_set_flags(X, BN_FLG_CONSTTIME); if (!BN_mod_exp_mont_consttime(k, k, X, order, ctx, group->mont_data)) { ECerr(EC_F_ECDSA_SIGN_SETUP, ERR_R_BN_LIB); goto err; } } else { if (!BN_mod_inverse(k, k, order, ctx)) { ECerr(EC_F_ECDSA_SIGN_SETUP, ERR_R_BN_LIB); goto err; } } } /* clear old values if necessary */ BN_clear_free(*rp); BN_clear_free(*kinvp); /* save the pre-computed values */ *rp = r; *kinvp = k; ret = 1; err: if (!ret) { BN_clear_free(k); BN_clear_free(r); } if (ctx != ctx_in) BN_CTX_free(ctx); EC_POINT_free(tmp_point); BN_clear_free(X); return ret; }