Don't store a redundant copy of the EC_GROUP field modulus One less value to initialize statically. Also this simplifies EC_GROUP initialization. While I'm here, reorder EC_GROUP to pad better. This lets us simplify the init bits slightly. It does mean p224-64.c, the one EC_GROUP that doesn't use Montgomery reduction, carries around a wasted Montgomery context, but it'll make generating the tables statically much easier. Also once the data is pre-generated, the cost is minimal. Bug: 20 Change-Id: Ib66e655ce5a0902ab3ed6695fcbb46aa87683885 Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/60928 Reviewed-by: Adam Langley <agl@google.com> Commit-Queue: David Benjamin <davidben@google.com>
diff --git a/crypto/ec_extra/hash_to_curve.c b/crypto/ec_extra/hash_to_curve.c index 433205c..380bc2e 100644 --- a/crypto/ec_extra/hash_to_curve.c +++ b/crypto/ec_extra/hash_to_curve.c
@@ -179,12 +179,12 @@ size_t msg_len) { size_t L; uint8_t buf[4 * EC_MAX_BYTES]; - if (!num_bytes_to_derive(&L, &group->field, k) || + if (!num_bytes_to_derive(&L, &group->field->N, k) || !expand_message_xmd(md, buf, 2 * L, msg, msg_len, dst, dst_len)) { return 0; } BN_ULONG words[2 * EC_MAX_WORDS]; - size_t num_words = 2 * group->field.width; + size_t num_words = 2 * group->field->N.width; big_endian_to_words(words, num_words, buf, L); group->meth->felem_reduce(group, out1, words, num_words); big_endian_to_words(words, num_words, buf + L, L); @@ -231,7 +231,7 @@ } OPENSSL_UNUSED static int is_3mod4(const EC_GROUP *group) { - return group->field.width > 0 && (group->field.d[0] & 3) == 3; + return group->field->N.width > 0 && (group->field->N.d[0] & 3) == 3; } // sqrt_ratio_3mod4 implements the operation described in appendix F.2.1.2 @@ -354,8 +354,8 @@ // Compute |c1| = (p - 3) / 4. BN_ULONG c1[EC_MAX_WORDS]; - size_t num_c1 = group->field.width; - if (!bn_copy_words(c1, num_c1, &group->field)) { + size_t num_c1 = group->field->N.width; + if (!bn_copy_words(c1, num_c1, &group->field->N)) { return 0; } bn_rshift_words(c1, c1, /*shift=*/2, /*num=*/num_c1); @@ -371,7 +371,7 @@ static int felem_from_u8(const EC_GROUP *group, EC_FELEM *out, uint8_t a) { uint8_t bytes[EC_MAX_BYTES] = {0}; - size_t len = BN_num_bytes(&group->field); + size_t len = BN_num_bytes(&group->field->N); bytes[len - 1] = a; return ec_felem_from_bytes(group, out, bytes, len); }
diff --git a/crypto/fipsmodule/ec/ec.c b/crypto/fipsmodule/ec/ec.c index 6f2a44c..1537491 100644 --- a/crypto/fipsmodule/ec/ec.c +++ b/crypto/fipsmodule/ec/ec.c
@@ -270,20 +270,9 @@ #endif } -EC_GROUP *ec_group_new(const EC_METHOD *meth) { - EC_GROUP *ret; - - if (meth == NULL) { - OPENSSL_PUT_ERROR(EC, EC_R_SLOT_FULL); - return NULL; - } - - if (meth->group_init == 0) { - OPENSSL_PUT_ERROR(EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); - return NULL; - } - - ret = OPENSSL_malloc(sizeof(EC_GROUP)); +EC_GROUP *ec_group_new(const EC_METHOD *meth, const BIGNUM *p, const BIGNUM *a, + const BIGNUM *b, BN_CTX *ctx) { + EC_GROUP *ret = OPENSSL_malloc(sizeof(EC_GROUP)); if (ret == NULL) { return NULL; } @@ -292,8 +281,8 @@ ret->references = 1; ret->meth = meth; - if (!meth->group_init(ret)) { - OPENSSL_free(ret); + if (!ec_GFp_simple_group_set_curve(ret, p, a, b, ctx)) { + EC_GROUP_free(ret); return NULL; } @@ -310,7 +299,7 @@ return 0; } - group->field_greater_than_order = BN_cmp(&group->field, order) > 0; + group->field_greater_than_order = BN_cmp(&group->field->N, order) > 0; group->generator = EC_POINT_new(group); if (group->generator == NULL) { @@ -355,11 +344,8 @@ goto err; } - ret = ec_group_new(EC_GFp_mont_method()); - if (ret == NULL || - !ret->meth->group_set_curve(ret, p, a_reduced, b_reduced, ctx)) { - EC_GROUP_free(ret); - ret = NULL; + ret = ec_group_new(EC_GFp_mont_method(), p, a_reduced, b_reduced, ctx); + if (ret == NULL) { goto err; } @@ -403,7 +389,7 @@ !BN_lshift1(tmp, order)) { goto err; } - if (BN_cmp(tmp, &group->field) <= 0) { + if (BN_cmp(tmp, &group->field->N) <= 0) { OPENSSL_PUT_ERROR(EC, EC_R_INVALID_GROUP_ORDER); goto err; } @@ -442,9 +428,8 @@ goto err; } - group = ec_group_new(curve->method); - if (group == NULL || - !group->meth->group_set_curve(group, p, a, b, ctx)) { + group = ec_group_new(curve->method, p, a, b, ctx); + if (group == NULL) { OPENSSL_PUT_ERROR(EC, ERR_R_EC_LIB); goto err; } @@ -453,11 +438,8 @@ EC_FELEM x, y; if (!ec_felem_from_bytes(group, &x, params + 3 * param_len, param_len) || !ec_felem_from_bytes(group, &y, params + 4 * param_len, param_len) || - !ec_point_set_affine_coordinates(group, &G, &x, &y)) { - goto err; - } - - if (!ec_group_set_generator(group, &G, order)) { + !ec_point_set_affine_coordinates(group, &G, &x, &y) || + !ec_group_set_generator(group, &G, order)) { goto err; } @@ -539,13 +521,9 @@ return; } - if (group->meth->group_finish != NULL) { - group->meth->group_finish(group); - } - ec_point_free(group->generator, 0 /* don't free group */); BN_MONT_CTX_free(group->order); - + BN_MONT_CTX_free(group->field); OPENSSL_free(group); } @@ -584,7 +562,7 @@ a->generator == NULL || b->generator == NULL || BN_cmp(&a->order->N, &b->order->N) != 0 || - BN_cmp(&a->field, &b->field) != 0 || + BN_cmp(&a->field->N, &b->field->N) != 0 || !ec_felem_equal(a, &a->a, &b->a) || !ec_felem_equal(a, &a->b, &b->b) || !ec_GFp_simple_points_equal(a, &a->generator->raw, &b->generator->raw); @@ -624,7 +602,7 @@ int EC_GROUP_get_curve_name(const EC_GROUP *group) { return group->curve_name; } unsigned EC_GROUP_get_degree(const EC_GROUP *group) { - return BN_num_bits(&group->field); + return BN_num_bits(&group->field->N); } const char *EC_curve_nid2nist(int nid) { @@ -1184,7 +1162,7 @@ int ec_get_x_coordinate_as_bytes(const EC_GROUP *group, uint8_t *out, size_t *out_len, size_t max_out, const EC_JACOBIAN *p) { - size_t len = BN_num_bytes(&group->field); + size_t len = BN_num_bytes(&group->field->N); assert(len <= EC_MAX_BYTES); if (max_out < len) { OPENSSL_PUT_ERROR(EC, EC_R_BUFFER_TOO_SMALL);
diff --git a/crypto/fipsmodule/ec/ec_montgomery.c b/crypto/fipsmodule/ec/ec_montgomery.c index 8d99238..74c71be 100644 --- a/crypto/fipsmodule/ec/ec_montgomery.c +++ b/crypto/fipsmodule/ec/ec_montgomery.c
@@ -76,67 +76,35 @@ #include "internal.h" -int ec_GFp_mont_group_init(EC_GROUP *group) { - int ok; - - ok = ec_GFp_simple_group_init(group); - group->mont = NULL; - return ok; -} - -void ec_GFp_mont_group_finish(EC_GROUP *group) { - BN_MONT_CTX_free(group->mont); - group->mont = NULL; - ec_GFp_simple_group_finish(group); -} - -int ec_GFp_mont_group_set_curve(EC_GROUP *group, const BIGNUM *p, - const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) { - BN_MONT_CTX_free(group->mont); - group->mont = BN_MONT_CTX_new_for_modulus(p, ctx); - if (group->mont == NULL) { - OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB); - return 0; - } - - if (!ec_GFp_simple_group_set_curve(group, p, a, b, ctx)) { - BN_MONT_CTX_free(group->mont); - group->mont = NULL; - return 0; - } - - return 1; -} - static void ec_GFp_mont_felem_to_montgomery(const EC_GROUP *group, EC_FELEM *out, const EC_FELEM *in) { - bn_to_montgomery_small(out->words, in->words, group->field.width, - group->mont); + bn_to_montgomery_small(out->words, in->words, group->field->N.width, + group->field); } static void ec_GFp_mont_felem_from_montgomery(const EC_GROUP *group, EC_FELEM *out, const EC_FELEM *in) { - bn_from_montgomery_small(out->words, group->field.width, in->words, - group->field.width, group->mont); + bn_from_montgomery_small(out->words, group->field->N.width, in->words, + group->field->N.width, group->field); } static void ec_GFp_mont_felem_inv0(const EC_GROUP *group, EC_FELEM *out, const EC_FELEM *a) { - bn_mod_inverse0_prime_mont_small(out->words, a->words, group->field.width, - group->mont); + bn_mod_inverse0_prime_mont_small(out->words, a->words, group->field->N.width, + group->field); } void ec_GFp_mont_felem_mul(const EC_GROUP *group, EC_FELEM *r, const EC_FELEM *a, const EC_FELEM *b) { - bn_mod_mul_montgomery_small(r->words, a->words, b->words, group->field.width, - group->mont); + bn_mod_mul_montgomery_small(r->words, a->words, b->words, + group->field->N.width, group->field); } void ec_GFp_mont_felem_sqr(const EC_GROUP *group, EC_FELEM *r, const EC_FELEM *a) { - bn_mod_mul_montgomery_small(r->words, a->words, a->words, group->field.width, - group->mont); + bn_mod_mul_montgomery_small(r->words, a->words, a->words, + group->field->N.width, group->field); } void ec_GFp_mont_felem_to_bytes(const EC_GROUP *group, uint8_t *out, @@ -159,8 +127,8 @@ void ec_GFp_mont_felem_reduce(const EC_GROUP *group, EC_FELEM *out, const BN_ULONG *words, size_t num) { // Convert "from" Montgomery form so the value is reduced mod p. - bn_from_montgomery_small(out->words, group->field.width, words, num, - group->mont); + bn_from_montgomery_small(out->words, group->field->N.width, words, num, + group->field); // Convert "to" Montgomery form to remove the R^-1 factor added. ec_GFp_mont_felem_to_montgomery(group, out, out); // Convert to Montgomery form to match this implementation's representation. @@ -170,8 +138,8 @@ void ec_GFp_mont_felem_exp(const EC_GROUP *group, EC_FELEM *out, const EC_FELEM *a, const BN_ULONG *exp, size_t num_exp) { - bn_mod_exp_mont_small(out->words, a->words, group->field.width, exp, num_exp, - group->mont); + bn_mod_exp_mont_small(out->words, a->words, group->field->N.width, exp, + num_exp, group->field); } static int ec_GFp_mont_point_get_affine_coordinates(const EC_GROUP *group, @@ -457,7 +425,7 @@ const EC_JACOBIAN *p, const EC_SCALAR *r) { if (!group->field_greater_than_order || - group->field.width != group->order->N.width) { + group->field->N.width != group->order->N.width) { // Do not bother optimizing this case. p > order in all commonly-used // curves. return ec_GFp_simple_cmp_x_coordinate(group, p, r); @@ -473,7 +441,8 @@ EC_FELEM r_Z2, Z2_mont, X; ec_GFp_mont_felem_mul(group, &Z2_mont, &p->Z, &p->Z); // r < order < p, so this is valid. - OPENSSL_memcpy(r_Z2.words, r->words, group->field.width * sizeof(BN_ULONG)); + OPENSSL_memcpy(r_Z2.words, r->words, + group->field->N.width * sizeof(BN_ULONG)); ec_GFp_mont_felem_mul(group, &r_Z2, &r_Z2, &Z2_mont); ec_GFp_mont_felem_from_montgomery(group, &X, &p->X); @@ -485,10 +454,10 @@ // Therefore there is a small possibility, less than 1/2^128, that group_order // < p.x < P. in that case we need not only to compare against |r| but also to // compare against r+group_order. - BN_ULONG carry = - bn_add_words(r_Z2.words, r->words, group->order->N.d, group->field.width); - if (carry == 0 && - bn_less_than_words(r_Z2.words, group->field.d, group->field.width)) { + BN_ULONG carry = bn_add_words(r_Z2.words, r->words, group->order->N.d, + group->field->N.width); + if (carry == 0 && bn_less_than_words(r_Z2.words, group->field->N.d, + group->field->N.width)) { // r + group_order < p, so compare (r + group_order) * Z^2 against X. ec_GFp_mont_felem_mul(group, &r_Z2, &r_Z2, &Z2_mont); if (ec_felem_equal(group, &r_Z2, &X)) { @@ -500,9 +469,6 @@ } DEFINE_METHOD_FUNCTION(EC_METHOD, EC_GFp_mont_method) { - out->group_init = ec_GFp_mont_group_init; - out->group_finish = ec_GFp_mont_group_finish; - out->group_set_curve = ec_GFp_mont_group_set_curve; out->point_get_affine_coordinates = ec_GFp_mont_point_get_affine_coordinates; out->jacobian_to_affine_batch = ec_GFp_mont_jacobian_to_affine_batch; out->add = ec_GFp_mont_add;
diff --git a/crypto/fipsmodule/ec/felem.c b/crypto/fipsmodule/ec/felem.c index e462514..e211f69 100644 --- a/crypto/fipsmodule/ec/felem.c +++ b/crypto/fipsmodule/ec/felem.c
@@ -25,10 +25,10 @@ int ec_bignum_to_felem(const EC_GROUP *group, EC_FELEM *out, const BIGNUM *in) { uint8_t bytes[EC_MAX_BYTES]; - size_t len = BN_num_bytes(&group->field); + size_t len = BN_num_bytes(&group->field->N); assert(sizeof(bytes) >= len); if (BN_is_negative(in) || - BN_cmp(in, &group->field) >= 0 || + BN_cmp(in, &group->field->N) >= 0 || !BN_bn2bin_padded(bytes, len, in)) { OPENSSL_PUT_ERROR(EC, EC_R_COORDINATES_OUT_OF_RANGE); return 0; @@ -57,11 +57,11 @@ void ec_felem_neg(const EC_GROUP *group, EC_FELEM *out, const EC_FELEM *a) { // -a is zero if a is zero and p-a otherwise. BN_ULONG mask = ec_felem_non_zero_mask(group, a); - BN_ULONG borrow = - bn_sub_words(out->words, group->field.d, a->words, group->field.width); + BN_ULONG borrow = bn_sub_words(out->words, group->field->N.d, a->words, + group->field->N.width); assert(borrow == 0); (void)borrow; - for (int i = 0; i < group->field.width; i++) { + for (int i = 0; i < group->field->N.width; i++) { out->words[i] &= mask; } } @@ -69,20 +69,20 @@ void ec_felem_add(const EC_GROUP *group, EC_FELEM *out, const EC_FELEM *a, const EC_FELEM *b) { EC_FELEM tmp; - bn_mod_add_words(out->words, a->words, b->words, group->field.d, tmp.words, - group->field.width); + bn_mod_add_words(out->words, a->words, b->words, group->field->N.d, tmp.words, + group->field->N.width); } void ec_felem_sub(const EC_GROUP *group, EC_FELEM *out, const EC_FELEM *a, const EC_FELEM *b) { EC_FELEM tmp; - bn_mod_sub_words(out->words, a->words, b->words, group->field.d, tmp.words, - group->field.width); + bn_mod_sub_words(out->words, a->words, b->words, group->field->N.d, tmp.words, + group->field->N.width); } BN_ULONG ec_felem_non_zero_mask(const EC_GROUP *group, const EC_FELEM *a) { BN_ULONG mask = 0; - for (int i = 0; i < group->field.width; i++) { + for (int i = 0; i < group->field->N.width; i++) { mask |= a->words[i]; } return ~constant_time_is_zero_w(mask); @@ -90,11 +90,11 @@ void ec_felem_select(const EC_GROUP *group, EC_FELEM *out, BN_ULONG mask, const EC_FELEM *a, const EC_FELEM *b) { - bn_select_words(out->words, mask, a->words, b->words, group->field.width); + bn_select_words(out->words, mask, a->words, b->words, group->field->N.width); } int ec_felem_equal(const EC_GROUP *group, const EC_FELEM *a, const EC_FELEM *b) { return CRYPTO_memcmp(a->words, b->words, - group->field.width * sizeof(BN_ULONG)) == 0; + group->field->N.width * sizeof(BN_ULONG)) == 0; }
diff --git a/crypto/fipsmodule/ec/internal.h b/crypto/fipsmodule/ec/internal.h index 4676aa5..dc86684 100644 --- a/crypto/fipsmodule/ec/internal.h +++ b/crypto/fipsmodule/ec/internal.h
@@ -472,11 +472,6 @@ // Implementation details. struct ec_method_st { - int (*group_init)(EC_GROUP *); - void (*group_finish)(EC_GROUP *); - int (*group_set_curve)(EC_GROUP *, const BIGNUM *p, const BIGNUM *a, - const BIGNUM *b, BN_CTX *); - // point_get_affine_coordinates sets |*x| and |*y| to the affine coordinates // of |p|. Either |x| or |y| may be NULL to omit it. It returns one on success // and zero if |p| is the point at infinity. It leaks whether |p| was the @@ -596,16 +591,13 @@ // and Y are suitable for use as an |EC_AFFINE|. EC_POINT *generator; - int curve_name; // optional NID for named curve - BN_MONT_CTX *order; - - // The following members are handled by the method functions, - // even if they appear generic - - BIGNUM field; // For curves over GF(p), this is the modulus. + BN_MONT_CTX *field; EC_FELEM a, b; // Curve coefficients. + EC_FELEM one; // The value one. + + int curve_name; // optional NID for named curve // a_is_minus3 is one if |a| is -3 mod |field| and zero otherwise. Point // arithmetic is optimized for -3. @@ -616,10 +608,6 @@ int field_greater_than_order; CRYPTO_refcount_t references; - - BN_MONT_CTX *mont; // Montgomery structure. - - EC_FELEM one; // The value one. } /* EC_GROUP */; struct ec_point_st { @@ -633,7 +621,8 @@ EC_JACOBIAN raw; } /* EC_POINT */; -EC_GROUP *ec_group_new(const EC_METHOD *meth); +EC_GROUP *ec_group_new(const EC_METHOD *meth, const BIGNUM *p, const BIGNUM *a, + const BIGNUM *b, BN_CTX *ctx); void ec_GFp_mont_mul(const EC_GROUP *group, EC_JACOBIAN *r, const EC_JACOBIAN *p, const EC_SCALAR *scalar); @@ -672,8 +661,6 @@ const EC_SCALAR *scalars, size_t num); // method functions in simple.c -int ec_GFp_simple_group_init(EC_GROUP *); -void ec_GFp_simple_group_finish(EC_GROUP *); int ec_GFp_simple_group_set_curve(EC_GROUP *, const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *); int ec_GFp_simple_group_get_curve(const EC_GROUP *, BIGNUM *p, BIGNUM *a, @@ -705,10 +692,6 @@ const uint8_t *in, size_t len); // method functions in montgomery.c -int ec_GFp_mont_group_init(EC_GROUP *); -int ec_GFp_mont_group_set_curve(EC_GROUP *, const BIGNUM *p, const BIGNUM *a, - const BIGNUM *b, BN_CTX *); -void ec_GFp_mont_group_finish(EC_GROUP *); void ec_GFp_mont_felem_mul(const EC_GROUP *, EC_FELEM *r, const EC_FELEM *a, const EC_FELEM *b); void ec_GFp_mont_felem_sqr(const EC_GROUP *, EC_FELEM *r, const EC_FELEM *a);
diff --git a/crypto/fipsmodule/ec/oct.c b/crypto/fipsmodule/ec/oct.c index eb77643..70e8956 100644 --- a/crypto/fipsmodule/ec/oct.c +++ b/crypto/fipsmodule/ec/oct.c
@@ -80,7 +80,7 @@ return 0; } - const size_t field_len = BN_num_bytes(&group->field); + const size_t field_len = BN_num_bytes(&group->field->N); size_t output_len = 1 /* type byte */ + field_len; if (form == POINT_CONVERSION_UNCOMPRESSED) { // Uncompressed points have a second coordinate. @@ -100,11 +100,11 @@ size_t field_len; ec_felem_to_bytes(group, buf + 1, &field_len, &point->X); - assert(field_len == BN_num_bytes(&group->field)); + assert(field_len == BN_num_bytes(&group->field->N)); if (form == POINT_CONVERSION_UNCOMPRESSED) { ec_felem_to_bytes(group, buf + 1 + field_len, &field_len, &point->Y); - assert(field_len == BN_num_bytes(&group->field)); + assert(field_len == BN_num_bytes(&group->field->N)); buf[0] = form; } else { uint8_t y_buf[EC_MAX_BYTES]; @@ -117,7 +117,7 @@ int ec_point_from_uncompressed(const EC_GROUP *group, EC_AFFINE *out, const uint8_t *in, size_t len) { - const size_t field_len = BN_num_bytes(&group->field); + const size_t field_len = BN_num_bytes(&group->field->N); if (len != 1 + 2 * field_len || in[0] != POINT_CONVERSION_UNCOMPRESSED) { OPENSSL_PUT_ERROR(EC, EC_R_INVALID_ENCODING); return 0; @@ -155,7 +155,7 @@ } const int y_bit = form & 1; - const size_t field_len = BN_num_bytes(&group->field); + const size_t field_len = BN_num_bytes(&group->field->N); form = form & ~1u; if (form != POINT_CONVERSION_COMPRESSED || len != 1 /* type byte */ + field_len) { @@ -182,7 +182,7 @@ if (x == NULL || !BN_bin2bn(buf + 1, field_len, x)) { goto err; } - if (BN_ucmp(x, &group->field) >= 0) { + if (BN_ucmp(x, &group->field->N) >= 0) { OPENSSL_PUT_ERROR(EC, EC_R_INVALID_ENCODING); goto err; } @@ -260,7 +260,8 @@ return 0; } - if (BN_is_negative(x) || BN_cmp(x, &group->field) >= 0) { + const BIGNUM *field = &group->field->N; + if (BN_is_negative(x) || BN_cmp(x, field) >= 0) { OPENSSL_PUT_ERROR(EC, EC_R_INVALID_COMPRESSED_POINT); return 0; } @@ -295,31 +296,31 @@ // so y is one of the square roots of x^3 + a*x + b. // tmp1 := x^3 - if (!BN_mod_sqr(tmp2, x, &group->field, ctx) || - !BN_mod_mul(tmp1, tmp2, x, &group->field, ctx)) { + if (!BN_mod_sqr(tmp2, x, field, ctx) || + !BN_mod_mul(tmp1, tmp2, x, field, ctx)) { goto err; } // tmp1 := tmp1 + a*x if (group->a_is_minus3) { - if (!bn_mod_lshift1_consttime(tmp2, x, &group->field, ctx) || - !bn_mod_add_consttime(tmp2, tmp2, x, &group->field, ctx) || - !bn_mod_sub_consttime(tmp1, tmp1, tmp2, &group->field, ctx)) { + if (!bn_mod_lshift1_consttime(tmp2, x, field, ctx) || + !bn_mod_add_consttime(tmp2, tmp2, x, field, ctx) || + !bn_mod_sub_consttime(tmp1, tmp1, tmp2, field, ctx)) { goto err; } } else { - if (!BN_mod_mul(tmp2, a, x, &group->field, ctx) || - !bn_mod_add_consttime(tmp1, tmp1, tmp2, &group->field, ctx)) { + if (!BN_mod_mul(tmp2, a, x, field, ctx) || + !bn_mod_add_consttime(tmp1, tmp1, tmp2, field, ctx)) { goto err; } } // tmp1 := tmp1 + b - if (!bn_mod_add_consttime(tmp1, tmp1, b, &group->field, ctx)) { + if (!bn_mod_add_consttime(tmp1, tmp1, b, field, ctx)) { goto err; } - if (!BN_mod_sqrt(y, tmp1, &group->field, ctx)) { + if (!BN_mod_sqrt(y, tmp1, field, ctx)) { uint32_t err = ERR_peek_last_error(); if (ERR_GET_LIB(err) == ERR_LIB_BN && ERR_GET_REASON(err) == BN_R_NOT_A_SQUARE) { @@ -336,7 +337,7 @@ OPENSSL_PUT_ERROR(EC, EC_R_INVALID_COMPRESSION_BIT); goto err; } - if (!BN_usub(y, &group->field, y)) { + if (!BN_usub(y, field, y)) { goto err; } }
diff --git a/crypto/fipsmodule/ec/p224-64.c b/crypto/fipsmodule/ec/p224-64.c index b646e82..9d0242c 100644 --- a/crypto/fipsmodule/ec/p224-64.c +++ b/crypto/fipsmodule/ec/p224-64.c
@@ -1142,9 +1142,6 @@ } DEFINE_METHOD_FUNCTION(EC_METHOD, EC_GFp_nistp224_method) { - out->group_init = ec_GFp_simple_group_init; - out->group_finish = ec_GFp_simple_group_finish; - out->group_set_curve = ec_GFp_simple_group_set_curve; out->point_get_affine_coordinates = ec_GFp_nistp224_point_get_affine_coordinates; out->add = ec_GFp_nistp224_add;
diff --git a/crypto/fipsmodule/ec/p256-nistz.c b/crypto/fipsmodule/ec/p256-nistz.c index 8936a9c..9993941 100644 --- a/crypto/fipsmodule/ec/p256-nistz.c +++ b/crypto/fipsmodule/ec/p256-nistz.c
@@ -191,7 +191,7 @@ const EC_SCALAR *p_scalar) { assert(p != NULL); assert(p_scalar != NULL); - assert(group->field.width == P256_LIMBS); + assert(group->field->N.width == P256_LIMBS); static const size_t kWindowSize = 5; static const crypto_word_t kMask = (1 << (5 /* kWindowSize */ + 1)) - 1; @@ -208,7 +208,7 @@ // not stored. All other values are actually stored with an offset of -1 in // table. P256_POINT *row = table; - assert(group->field.width == P256_LIMBS); + assert(group->field->N.width == P256_LIMBS); OPENSSL_memcpy(row[1 - 1].X, p->X.words, P256_LIMBS * sizeof(BN_ULONG)); OPENSSL_memcpy(row[1 - 1].Y, p->Y.words, P256_LIMBS * sizeof(BN_ULONG)); OPENSSL_memcpy(row[1 - 1].Z, p->Z.words, P256_LIMBS * sizeof(BN_ULONG)); @@ -305,7 +305,7 @@ alignas(32) P256_POINT out; ecp_nistz256_windowed_mul(group, &out, p, scalar); - assert(group->field.width == P256_LIMBS); + assert(group->field->N.width == P256_LIMBS); OPENSSL_memcpy(r->X.words, out.X, P256_LIMBS * sizeof(BN_ULONG)); OPENSSL_memcpy(r->Y.words, out.Y, P256_LIMBS * sizeof(BN_ULONG)); OPENSSL_memcpy(r->Z.words, out.Z, P256_LIMBS * sizeof(BN_ULONG)); @@ -349,7 +349,7 @@ ecp_nistz256_point_add_affine(&p, &p, &t); } - assert(group->field.width == P256_LIMBS); + assert(group->field->N.width == P256_LIMBS); OPENSSL_memcpy(r->X.words, p.X, P256_LIMBS * sizeof(BN_ULONG)); OPENSSL_memcpy(r->Y.words, p.Y, P256_LIMBS * sizeof(BN_ULONG)); OPENSSL_memcpy(r->Z.words, p.Z, P256_LIMBS * sizeof(BN_ULONG)); @@ -413,7 +413,7 @@ ecp_nistz256_windowed_mul(group, &tmp, p_, p_scalar); ecp_nistz256_point_add(&p, &p, &tmp); - assert(group->field.width == P256_LIMBS); + assert(group->field->N.width == P256_LIMBS); OPENSSL_memcpy(r->X.words, p.X, P256_LIMBS * sizeof(BN_ULONG)); OPENSSL_memcpy(r->Y.words, p.Y, P256_LIMBS * sizeof(BN_ULONG)); OPENSSL_memcpy(r->Z.words, p.Z, P256_LIMBS * sizeof(BN_ULONG)); @@ -429,7 +429,7 @@ } BN_ULONG z_inv2[P256_LIMBS]; - assert(group->field.width == P256_LIMBS); + assert(group->field->N.width == P256_LIMBS); ecp_nistz256_mod_inverse_sqr_mont(z_inv2, point->Z.words); if (x != NULL) { @@ -581,7 +581,7 @@ } assert(group->order->N.width == P256_LIMBS); - assert(group->field.width == P256_LIMBS); + assert(group->field->N.width == P256_LIMBS); // We wish to compare X/Z^2 with r. This is equivalent to comparing X with // r*Z^2. Note that X and Z are represented in Montgomery form, while r is @@ -600,7 +600,7 @@ // < p.x < P. in that case we need not only to compare against |r| but also to // compare against r+group_order. BN_ULONG carry = bn_add_words(r_Z2, r->words, group->order->N.d, P256_LIMBS); - if (carry == 0 && bn_less_than_words(r_Z2, group->field.d, P256_LIMBS)) { + if (carry == 0 && bn_less_than_words(r_Z2, group->field->N.d, P256_LIMBS)) { // r + group_order < p, so compare (r + group_order) * Z^2 against X. ecp_nistz256_mul_mont(r_Z2, r_Z2, Z2_mont); if (OPENSSL_memcmp(r_Z2, X, sizeof(r_Z2)) == 0) { @@ -612,9 +612,6 @@ } DEFINE_METHOD_FUNCTION(EC_METHOD, EC_GFp_nistz256_method) { - out->group_init = ec_GFp_mont_group_init; - out->group_finish = ec_GFp_mont_group_finish; - out->group_set_curve = ec_GFp_mont_group_set_curve; out->point_get_affine_coordinates = ecp_nistz256_get_affine; out->add = ecp_nistz256_add; out->dbl = ecp_nistz256_dbl;
diff --git a/crypto/fipsmodule/ec/p256.c b/crypto/fipsmodule/ec/p256.c index ce9a57f..35b9d45 100644 --- a/crypto/fipsmodule/ec/p256.c +++ b/crypto/fipsmodule/ec/p256.c
@@ -710,12 +710,12 @@ // Therefore there is a small possibility, less than 1/2^128, that group_order // < p.x < P. in that case we need not only to compare against |r| but also to // compare against r+group_order. - assert(group->field.width == group->order->N.width); + assert(group->field->N.width == group->order->N.width); EC_FELEM tmp; - BN_ULONG carry = - bn_add_words(tmp.words, r->words, group->order->N.d, group->field.width); + BN_ULONG carry = bn_add_words(tmp.words, r->words, group->order->N.d, + group->field->N.width); if (carry == 0 && - bn_less_than_words(tmp.words, group->field.d, group->field.width)) { + bn_less_than_words(tmp.words, group->field->N.d, group->field->N.width)) { fiat_p256_from_generic(r_Z2, &tmp); fiat_p256_mul(r_Z2, r_Z2, Z2_mont); if (OPENSSL_memcmp(&r_Z2, &X, sizeof(r_Z2)) == 0) { @@ -727,9 +727,6 @@ } DEFINE_METHOD_FUNCTION(EC_METHOD, EC_GFp_nistp256_method) { - out->group_init = ec_GFp_mont_group_init; - out->group_finish = ec_GFp_mont_group_finish; - out->group_set_curve = ec_GFp_mont_group_set_curve; out->point_get_affine_coordinates = ec_GFp_nistp256_point_get_affine_coordinates; out->add = ec_GFp_nistp256_add;
diff --git a/crypto/fipsmodule/ec/simple.c b/crypto/fipsmodule/ec/simple.c index 6498bdc..0b27040 100644 --- a/crypto/fipsmodule/ec/simple.c +++ b/crypto/fipsmodule/ec/simple.c
@@ -88,16 +88,6 @@ // used, it is a Montgomery representation (i.e. 'encoding' means multiplying // by some factor R). -int ec_GFp_simple_group_init(EC_GROUP *group) { - BN_init(&group->field); - group->a_is_minus3 = 0; - return 1; -} - -void ec_GFp_simple_group_finish(EC_GROUP *group) { - BN_free(&group->field); -} - int ec_GFp_simple_group_set_curve(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) { @@ -114,13 +104,10 @@ goto err; } - // group->field - if (!BN_copy(&group->field, p)) { + group->field = BN_MONT_CTX_new_for_modulus(p, ctx); + if (group->field == NULL) { goto err; } - BN_set_negative(&group->field, 0); - // Store the field in minimal form, so it can be used with |BN_ULONG| arrays. - bn_set_minimal_width(&group->field); if (!ec_bignum_to_felem(group, &group->a, a) || !ec_bignum_to_felem(group, &group->b, b) || @@ -133,7 +120,7 @@ !BN_add_word(tmp, 3)) { goto err; } - group->a_is_minus3 = (0 == BN_cmp(tmp, &group->field)); + group->a_is_minus3 = (0 == BN_cmp(tmp, &group->field->N)); ret = 1; @@ -144,7 +131,7 @@ int ec_GFp_simple_group_get_curve(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, BIGNUM *b) { - if ((p != NULL && !BN_copy(p, &group->field)) || + if ((p != NULL && !BN_copy(p, &group->field->N)) || (a != NULL && !ec_felem_to_bignum(group, a, &group->a)) || (b != NULL && !ec_felem_to_bignum(group, b, &group->b))) { return 0; @@ -329,21 +316,22 @@ void ec_GFp_simple_felem_to_bytes(const EC_GROUP *group, uint8_t *out, size_t *out_len, const EC_FELEM *in) { - size_t len = BN_num_bytes(&group->field); - bn_words_to_big_endian(out, len, in->words, group->field.width); + size_t len = BN_num_bytes(&group->field->N); + bn_words_to_big_endian(out, len, in->words, group->field->N.width); *out_len = len; } int ec_GFp_simple_felem_from_bytes(const EC_GROUP *group, EC_FELEM *out, const uint8_t *in, size_t len) { - if (len != BN_num_bytes(&group->field)) { + if (len != BN_num_bytes(&group->field->N)) { OPENSSL_PUT_ERROR(EC, EC_R_DECODE_ERROR); return 0; } - bn_big_endian_to_words(out->words, group->field.width, in, len); + bn_big_endian_to_words(out->words, group->field->N.width, in, len); - if (!bn_less_than_words(out->words, group->field.d, group->field.width)) { + if (!bn_less_than_words(out->words, group->field->N.d, + group->field->N.width)) { OPENSSL_PUT_ERROR(EC, EC_R_DECODE_ERROR); return 0; }
diff --git a/crypto/fipsmodule/ec/simple_mul.c b/crypto/fipsmodule/ec/simple_mul.c index 62786e6..ce5b317 100644 --- a/crypto/fipsmodule/ec/simple_mul.c +++ b/crypto/fipsmodule/ec/simple_mul.c
@@ -169,7 +169,7 @@ } static unsigned ec_GFp_mont_comb_stride(const EC_GROUP *group) { - return (BN_num_bits(&group->field) + EC_MONT_PRECOMP_COMB_SIZE - 1) / + return (EC_GROUP_get_degree(group) + EC_MONT_PRECOMP_COMB_SIZE - 1) / EC_MONT_PRECOMP_COMB_SIZE; }
diff --git a/crypto/trust_token/pmbtoken.c b/crypto/trust_token/pmbtoken.c index 93a0191..be093fc 100644 --- a/crypto/trust_token/pmbtoken.c +++ b/crypto/trust_token/pmbtoken.c
@@ -160,7 +160,7 @@ return 0; } } else { - size_t plen = 1 + 2 * BN_num_bytes(&group->field); + size_t plen = ec_point_byte_len(group, POINT_CONVERSION_UNCOMPRESSED); if (!CBS_get_bytes(cbs, &child, plen)) { return 0; } @@ -912,7 +912,7 @@ } // Skip over any unused requests. - size_t point_len = 1 + 2 * BN_num_bytes(&group->field); + size_t point_len = ec_point_byte_len(group, POINT_CONVERSION_UNCOMPRESSED); size_t token_len = point_len; if (method->prefix_point) { token_len += 2; @@ -1015,7 +1015,7 @@ // Serialize the token. Include |key_id| to avoid an extra copy in the layer // above. CBB token_cbb; - size_t point_len = 1 + 2 * BN_num_bytes(&group->field); + size_t point_len = ec_point_byte_len(group, POINT_CONVERSION_UNCOMPRESSED); if (!CBB_init(&token_cbb, 4 + TRUST_TOKEN_NONCE_SIZE + 3 * (2 + point_len)) || !CBB_add_u32(&token_cbb, key_id) ||
diff --git a/crypto/trust_token/trust_token_test.cc b/crypto/trust_token/trust_token_test.cc index df679b6..37fdc85 100644 --- a/crypto/trust_token/trust_token_test.cc +++ b/crypto/trust_token/trust_token_test.cc
@@ -1080,15 +1080,14 @@ ASSERT_TRUE(CBS_get_u32(&real_response, &parsed_public_metadata)); ASSERT_TRUE(CBB_add_u32(bad_response.get(), parsed_public_metadata)); - const EC_GROUP *group = EC_GROUP_new_by_curve_name(NID_secp384r1); - size_t token_length = - TRUST_TOKEN_NONCE_SIZE + 2 * (1 + 2 * BN_num_bytes(&group->field)); + const size_t kP384PointLen = 1 + 2 * (384 / 8); + size_t token_length = TRUST_TOKEN_NONCE_SIZE + 2 * kP384PointLen; if (method() == TRUST_TOKEN_experiment_v1()) { token_length += 4; } if (method() == TRUST_TOKEN_experiment_v2_voprf() || method() == TRUST_TOKEN_pst_v1_voprf()) { - token_length = 1 + 2 * BN_num_bytes(&group->field); + token_length = kP384PointLen; } for (size_t i = 0; i < count; i++) { ASSERT_TRUE(CBB_add_bytes(bad_response.get(), CBS_data(&real_response), @@ -1149,15 +1148,14 @@ ASSERT_TRUE(CBS_get_u32(&real_response, &parsed_public_metadata)); ASSERT_TRUE(CBB_add_u32(bad_response.get(), parsed_public_metadata)); - const EC_GROUP *group = EC_GROUP_new_by_curve_name(NID_secp384r1); - size_t token_length = - TRUST_TOKEN_NONCE_SIZE + 2 * (1 + 2 * BN_num_bytes(&group->field)); + const size_t kP384PointLen = 1 + 2 * (384 / 8); + size_t token_length = TRUST_TOKEN_NONCE_SIZE + 2 * kP384PointLen; if (method() == TRUST_TOKEN_experiment_v1()) { token_length += 4; } if (method() == TRUST_TOKEN_experiment_v2_voprf() || method() == TRUST_TOKEN_pst_v1_voprf()) { - token_length = 1 + 2 * BN_num_bytes(&group->field); + token_length = kP384PointLen; } for (size_t i = 0; i < count; i++) { ASSERT_TRUE(CBB_add_bytes(bad_response.get(), CBS_data(&real_response),
diff --git a/crypto/trust_token/voprf.c b/crypto/trust_token/voprf.c index e62aca5..15939d3 100644 --- a/crypto/trust_token/voprf.c +++ b/crypto/trust_token/voprf.c
@@ -83,7 +83,7 @@ static int cbs_get_point(CBS *cbs, const EC_GROUP *group, EC_AFFINE *out) { CBS child; - size_t plen = 1 + 2 * BN_num_bytes(&group->field); + size_t plen = ec_point_byte_len(group, POINT_CONVERSION_UNCOMPRESSED); if (!CBS_get_bytes(cbs, &child, plen) || !ec_point_from_uncompressed(group, out, CBS_data(&child), CBS_len(&child))) { @@ -567,7 +567,7 @@ } // Skip over any unused requests. - size_t point_len = 1 + 2 * BN_num_bytes(&group->field); + size_t point_len = ec_point_byte_len(group, POINT_CONVERSION_UNCOMPRESSED); if (!CBS_skip(cbs, point_len * (num_requested - num_to_issue))) { OPENSSL_PUT_ERROR(TRUST_TOKEN, TRUST_TOKEN_R_DECODE_FAILURE); goto err; @@ -645,7 +645,7 @@ // Serialize the token. Include |key_id| to avoid an extra copy in the layer // above. CBB token_cbb; - size_t point_len = 1 + 2 * BN_num_bytes(&group->field); + size_t point_len = ec_point_byte_len(group, POINT_CONVERSION_UNCOMPRESSED); if (!CBB_init(&token_cbb, 4 + TRUST_TOKEN_NONCE_SIZE + (2 + point_len)) || !CBB_add_u32(&token_cbb, key_id) || !CBB_add_bytes(&token_cbb, pretoken->salt, TRUST_TOKEN_NONCE_SIZE) || @@ -944,7 +944,7 @@ } // Skip over any unused requests. - size_t point_len = 1 + 2 * BN_num_bytes(&group->field); + size_t point_len = ec_point_byte_len(group, POINT_CONVERSION_UNCOMPRESSED); if (!CBS_skip(cbs, point_len * (num_requested - num_to_issue))) { OPENSSL_PUT_ERROR(TRUST_TOKEN, TRUST_TOKEN_R_DECODE_FAILURE); goto err; @@ -1044,7 +1044,7 @@ // Serialize the token. Include |key_id| to avoid an extra copy in the layer // above. CBB token_cbb; - size_t point_len = 1 + 2 * BN_num_bytes(&group->field); + size_t point_len = ec_point_byte_len(group, POINT_CONVERSION_UNCOMPRESSED); if (!CBB_init(&token_cbb, 4 + TRUST_TOKEN_NONCE_SIZE + (2 + point_len)) || !CBB_add_u32(&token_cbb, key_id) || !CBB_add_bytes(&token_cbb, pretoken->salt, TRUST_TOKEN_NONCE_SIZE) ||