Embed BN_MONT_CTX into EC_GROUP.
The delocate machinery makes it annoying to have pointers in structures.
Also this is a hair more compact.
Bug: 20
Change-Id: I2bc2dd97018277b5be55fd560f4171b7b85928ff
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/60929
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: Adam Langley <agl@google.com>
diff --git a/crypto/ec_extra/ec_derive.c b/crypto/ec_extra/ec_derive.c
index 7e666d5..efc95f2 100644
--- a/crypto/ec_extra/ec_derive.c
+++ b/crypto/ec_extra/ec_derive.c
@@ -75,10 +75,10 @@
// enough. 2^(num_bytes(order)) < 2^8 * order, so:
//
// priv < 2^8 * order * 2^128 < order * order < order * R
- !BN_from_montgomery(priv, priv, group->order, ctx) ||
+ !BN_from_montgomery(priv, priv, &group->order, ctx) ||
// Multiply by R^2 and do another Montgomery reduction to compute
// priv * R^-1 * R^2 * R^-1 = priv mod order.
- !BN_to_montgomery(priv, priv, group->order, ctx) ||
+ !BN_to_montgomery(priv, priv, &group->order, ctx) ||
!EC_POINT_mul(group, pub, priv, NULL, NULL, ctx) ||
!EC_KEY_set_group(key, group) || !EC_KEY_set_public_key(key, pub) ||
!EC_KEY_set_private_key(key, priv)) {
diff --git a/crypto/ec_extra/hash_to_curve.c b/crypto/ec_extra/hash_to_curve.c
index 380bc2e..d9d9d5b 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->N, 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->N.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->N.width > 0 && (group->field->N.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->N.width;
- if (!bn_copy_words(c1, num_c1, &group->field->N)) {
+ 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->N);
+ 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/bn/internal.h b/crypto/fipsmodule/bn/internal.h
index 7b939de..06ebe16 100644
--- a/crypto/fipsmodule/bn/internal.h
+++ b/crypto/fipsmodule/bn/internal.h
@@ -599,6 +599,13 @@
OPENSSL_EXPORT int bn_lcm_consttime(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
BN_CTX *ctx);
+// bn_mont_ctx_init zero-initialies |mont|.
+void bn_mont_ctx_init(BN_MONT_CTX *mont);
+
+// bn_mont_ctx_cleanup releases memory associated with |mont|, without freeing
+// |mont| itself.
+void bn_mont_ctx_cleanup(BN_MONT_CTX *mont);
+
// Constant-time modular arithmetic.
//
diff --git a/crypto/fipsmodule/bn/montgomery.c b/crypto/fipsmodule/bn/montgomery.c
index a5df5ff..f219d42 100644
--- a/crypto/fipsmodule/bn/montgomery.c
+++ b/crypto/fipsmodule/bn/montgomery.c
@@ -121,17 +121,24 @@
#include "../../internal.h"
+void bn_mont_ctx_init(BN_MONT_CTX *mont) {
+ OPENSSL_memset(mont, 0, sizeof(BN_MONT_CTX));
+ BN_init(&mont->RR);
+ BN_init(&mont->N);
+}
+
+void bn_mont_ctx_cleanup(BN_MONT_CTX *mont) {
+ BN_free(&mont->RR);
+ BN_free(&mont->N);
+}
+
BN_MONT_CTX *BN_MONT_CTX_new(void) {
BN_MONT_CTX *ret = OPENSSL_malloc(sizeof(BN_MONT_CTX));
-
if (ret == NULL) {
return NULL;
}
- OPENSSL_memset(ret, 0, sizeof(BN_MONT_CTX));
- BN_init(&ret->RR);
- BN_init(&ret->N);
-
+ bn_mont_ctx_init(ret);
return ret;
}
@@ -140,8 +147,7 @@
return;
}
- BN_free(&mont->RR);
- BN_free(&mont->N);
+ bn_mont_ctx_cleanup(mont);
OPENSSL_free(mont);
}
diff --git a/crypto/fipsmodule/ec/ec.c b/crypto/fipsmodule/ec/ec.c
index 1537491..a1d6e24 100644
--- a/crypto/fipsmodule/ec/ec.c
+++ b/crypto/fipsmodule/ec/ec.c
@@ -280,6 +280,8 @@
ret->references = 1;
ret->meth = meth;
+ bn_mont_ctx_init(&ret->field);
+ bn_mont_ctx_init(&ret->order);
if (!ec_GFp_simple_group_set_curve(ret, p, a, b, ctx)) {
EC_GROUP_free(ret);
@@ -291,16 +293,13 @@
static int ec_group_set_generator(EC_GROUP *group, const EC_AFFINE *generator,
const BIGNUM *order) {
- assert(group->generator == NULL);
+ assert(!group->has_order);
- BN_MONT_CTX_free(group->order);
- group->order = BN_MONT_CTX_new_for_modulus(order, NULL);
- if (group->order == NULL) {
+ if (!BN_MONT_CTX_set(&group->order, order, NULL)) {
return 0;
}
- group->field_greater_than_order = BN_cmp(&group->field->N, order) > 0;
-
+ group->field_greater_than_order = BN_cmp(&group->field.N, order) > 0;
group->generator = EC_POINT_new(group);
if (group->generator == NULL) {
return 0;
@@ -314,6 +313,7 @@
assert(!is_zero);
(void)is_zero;
+ group->has_order = 1;
return 1;
}
@@ -389,7 +389,7 @@
!BN_lshift1(tmp, order)) {
goto err;
}
- if (BN_cmp(tmp, &group->field->N) <= 0) {
+ if (BN_cmp(tmp, &group->field.N) <= 0) {
OPENSSL_PUT_ERROR(EC, EC_R_INVALID_GROUP_ORDER);
goto err;
}
@@ -521,9 +521,9 @@
return;
}
- ec_point_free(group->generator, 0 /* don't free group */);
- BN_MONT_CTX_free(group->order);
- BN_MONT_CTX_free(group->field);
+ ec_point_free(group->generator, /*free_group=*/0);
+ bn_mont_ctx_cleanup(&group->order);
+ bn_mont_ctx_cleanup(&group->field);
OPENSSL_free(group);
}
@@ -561,8 +561,8 @@
return a->meth != b->meth ||
a->generator == NULL ||
b->generator == NULL ||
- BN_cmp(&a->order->N, &b->order->N) != 0 ||
- BN_cmp(&a->field->N, &b->field->N) != 0 ||
+ BN_cmp(&a->order.N, &b->order.N) != 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);
@@ -573,8 +573,8 @@
}
const BIGNUM *EC_GROUP_get0_order(const EC_GROUP *group) {
- assert(group->order != NULL);
- return &group->order->N;
+ assert(group->has_order);
+ return &group->order.N;
}
int EC_GROUP_get_order(const EC_GROUP *group, BIGNUM *order, BN_CTX *ctx) {
@@ -585,7 +585,7 @@
}
int EC_GROUP_order_bits(const EC_GROUP *group) {
- return BN_num_bits(&group->order->N);
+ return BN_num_bits(&group->order.N);
}
int EC_GROUP_get_cofactor(const EC_GROUP *group, BIGNUM *cofactor,
@@ -602,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->N);
+ return BN_num_bits(&group->field.N);
}
const char *EC_curve_nid2nist(int nid) {
@@ -1162,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->N);
+ 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_key.c b/crypto/fipsmodule/ec/ec_key.c
index d21d509..90a4404 100644
--- a/crypto/fipsmodule/ec/ec_key.c
+++ b/crypto/fipsmodule/ec/ec_key.c
@@ -93,8 +93,8 @@
OPENSSL_memset(wrapped, 0, sizeof(EC_WRAPPED_SCALAR));
wrapped->bignum.d = wrapped->scalar.words;
- wrapped->bignum.width = group->order->N.width;
- wrapped->bignum.dmax = group->order->N.width;
+ wrapped->bignum.width = group->order.N.width;
+ wrapped->bignum.dmax = group->order.N.width;
wrapped->bignum.flags = BN_FLG_STATIC_DATA;
return wrapped;
}
diff --git a/crypto/fipsmodule/ec/ec_montgomery.c b/crypto/fipsmodule/ec/ec_montgomery.c
index 74c71be..92289a5 100644
--- a/crypto/fipsmodule/ec/ec_montgomery.c
+++ b/crypto/fipsmodule/ec/ec_montgomery.c
@@ -78,33 +78,33 @@
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->N.width,
- group->field);
+ 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->N.width, in->words,
- group->field->N.width, group->field);
+ 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->N.width,
- group->field);
+ 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->N.width, group->field);
+ 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->N.width, group->field);
+ group->field.N.width, &group->field);
}
void ec_GFp_mont_felem_to_bytes(const EC_GROUP *group, uint8_t *out,
@@ -127,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->N.width, words, num,
- group->field);
+ 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.
@@ -138,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->N.width, exp,
- num_exp, group->field);
+ 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,
@@ -425,7 +425,7 @@
const EC_JACOBIAN *p,
const EC_SCALAR *r) {
if (!group->field_greater_than_order ||
- group->field->N.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);
@@ -441,8 +441,7 @@
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->N.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);
@@ -454,10 +453,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->N.width);
- if (carry == 0 && bn_less_than_words(r_Z2.words, group->field->N.d,
- group->field->N.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)) {
diff --git a/crypto/fipsmodule/ec/felem.c b/crypto/fipsmodule/ec/felem.c
index e211f69..bc7bbb7 100644
--- a/crypto/fipsmodule/ec/felem.c
+++ b/crypto/fipsmodule/ec/felem.c
@@ -25,10 +25,9 @@
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->N);
+ size_t len = BN_num_bytes(&group->field.N);
assert(sizeof(bytes) >= len);
- if (BN_is_negative(in) ||
- BN_cmp(in, &group->field->N) >= 0 ||
+ if (BN_is_negative(in) || 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 +56,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->N.d, a->words,
- group->field->N.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->N.width; i++) {
+ for (int i = 0; i < group->field.N.width; i++) {
out->words[i] &= mask;
}
}
@@ -69,20 +68,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->N.d, tmp.words,
- group->field->N.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->N.d, tmp.words,
- group->field->N.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->N.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 +89,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->N.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->N.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 dc86684..64f41bb 100644
--- a/crypto/fipsmodule/ec/internal.h
+++ b/crypto/fipsmodule/ec/internal.h
@@ -591,8 +591,8 @@
// and Y are suitable for use as an |EC_AFFINE|.
EC_POINT *generator;
- BN_MONT_CTX *order;
- BN_MONT_CTX *field;
+ BN_MONT_CTX order;
+ BN_MONT_CTX field;
EC_FELEM a, b; // Curve coefficients.
EC_FELEM one; // The value one.
@@ -603,6 +603,9 @@
// arithmetic is optimized for -3.
int a_is_minus3;
+ // has_order is one if |generator| and |order| have been initialized.
+ int has_order;
+
// field_greater_than_order is one if |field| is greate than |order| and zero
// otherwise.
int field_greater_than_order;
diff --git a/crypto/fipsmodule/ec/oct.c b/crypto/fipsmodule/ec/oct.c
index 70e8956..6cb84f5 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->N);
+ 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->N));
+ 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->N));
+ 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->N);
+ 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->N);
+ 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->N) >= 0) {
+ if (BN_ucmp(x, &group->field.N) >= 0) {
OPENSSL_PUT_ERROR(EC, EC_R_INVALID_ENCODING);
goto err;
}
@@ -260,7 +260,7 @@
return 0;
}
- const BIGNUM *field = &group->field->N;
+ 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;
diff --git a/crypto/fipsmodule/ec/p256-nistz.c b/crypto/fipsmodule/ec/p256-nistz.c
index 9993941..cf09963 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->N.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->N.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->N.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->N.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->N.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->N.width == P256_LIMBS);
+ assert(group->field.N.width == P256_LIMBS);
ecp_nistz256_mod_inverse_sqr_mont(z_inv2, point->Z.words);
if (x != NULL) {
@@ -563,8 +563,8 @@
}
#endif
- assert(group->order->N.width == P256_LIMBS);
- if (!beeu_mod_inverse_vartime(out->words, in->words, group->order->N.d)) {
+ assert(group->order.N.width == P256_LIMBS);
+ if (!beeu_mod_inverse_vartime(out->words, in->words, group->order.N.d)) {
return 0;
}
@@ -580,8 +580,8 @@
return 0;
}
- assert(group->order->N.width == P256_LIMBS);
- assert(group->field->N.width == P256_LIMBS);
+ assert(group->order.N.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
@@ -599,8 +599,8 @@
// 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, r->words, group->order->N.d, P256_LIMBS);
- if (carry == 0 && bn_less_than_words(r_Z2, group->field->N.d, P256_LIMBS)) {
+ 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.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) {
diff --git a/crypto/fipsmodule/ec/p256.c b/crypto/fipsmodule/ec/p256.c
index 35b9d45..e532e2f 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->N.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->N.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->N.d, group->field->N.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) {
diff --git a/crypto/fipsmodule/ec/scalar.c b/crypto/fipsmodule/ec/scalar.c
index 5c6f664..a86ee0f 100644
--- a/crypto/fipsmodule/ec/scalar.c
+++ b/crypto/fipsmodule/ec/scalar.c
@@ -23,9 +23,8 @@
int ec_bignum_to_scalar(const EC_GROUP *group, EC_SCALAR *out,
const BIGNUM *in) {
- if (!bn_copy_words(out->words, group->order->N.width, in) ||
- !bn_less_than_words(out->words, group->order->N.d,
- group->order->N.width)) {
+ if (!bn_copy_words(out->words, group->order.N.width, in) ||
+ !bn_less_than_words(out->words, group->order.N.d, group->order.N.width)) {
OPENSSL_PUT_ERROR(EC, EC_R_INVALID_SCALAR);
return 0;
}
@@ -35,12 +34,12 @@
int ec_scalar_equal_vartime(const EC_GROUP *group, const EC_SCALAR *a,
const EC_SCALAR *b) {
return OPENSSL_memcmp(a->words, b->words,
- group->order->N.width * sizeof(BN_ULONG)) == 0;
+ group->order.N.width * sizeof(BN_ULONG)) == 0;
}
int ec_scalar_is_zero(const EC_GROUP *group, const EC_SCALAR *a) {
BN_ULONG mask = 0;
- for (int i = 0; i < group->order->N.width; i++) {
+ for (int i = 0; i < group->order.N.width; i++) {
mask |= a->words[i];
}
return mask == 0;
@@ -48,28 +47,27 @@
int ec_random_nonzero_scalar(const EC_GROUP *group, EC_SCALAR *out,
const uint8_t additional_data[32]) {
- return bn_rand_range_words(out->words, 1, group->order->N.d,
- group->order->N.width, additional_data);
+ return bn_rand_range_words(out->words, 1, group->order.N.d,
+ group->order.N.width, additional_data);
}
void ec_scalar_to_bytes(const EC_GROUP *group, uint8_t *out, size_t *out_len,
const EC_SCALAR *in) {
- size_t len = BN_num_bytes(&group->order->N);
- bn_words_to_big_endian(out, len, in->words, group->order->N.width);
+ size_t len = BN_num_bytes(&group->order.N);
+ bn_words_to_big_endian(out, len, in->words, group->order.N.width);
*out_len = len;
}
int ec_scalar_from_bytes(const EC_GROUP *group, EC_SCALAR *out,
const uint8_t *in, size_t len) {
- if (len != BN_num_bytes(&group->order->N)) {
+ if (len != BN_num_bytes(&group->order.N)) {
OPENSSL_PUT_ERROR(EC, EC_R_INVALID_SCALAR);
return 0;
}
- bn_big_endian_to_words(out->words, group->order->N.width, in, len);
+ bn_big_endian_to_words(out->words, group->order.N.width, in, len);
- if (!bn_less_than_words(out->words, group->order->N.d,
- group->order->N.width)) {
+ if (!bn_less_than_words(out->words, group->order.N.d, group->order.N.width)) {
OPENSSL_PUT_ERROR(EC, EC_R_INVALID_SCALAR);
return 0;
}
@@ -80,15 +78,15 @@
void ec_scalar_reduce(const EC_GROUP *group, EC_SCALAR *out,
const BN_ULONG *words, size_t num) {
// Convert "from" Montgomery form so the value is reduced modulo the order.
- bn_from_montgomery_small(out->words, group->order->N.width, words, num,
- group->order);
+ bn_from_montgomery_small(out->words, group->order.N.width, words, num,
+ &group->order);
// Convert "to" Montgomery form to remove the R^-1 factor added.
ec_scalar_to_montgomery(group, out, out);
}
void ec_scalar_add(const EC_GROUP *group, EC_SCALAR *r, const EC_SCALAR *a,
const EC_SCALAR *b) {
- const BIGNUM *order = &group->order->N;
+ const BIGNUM *order = &group->order.N;
BN_ULONG tmp[EC_MAX_WORDS];
bn_mod_add_words(r->words, a->words, b->words, order->d, tmp, order->width);
OPENSSL_cleanse(tmp, sizeof(tmp));
@@ -96,7 +94,7 @@
void ec_scalar_sub(const EC_GROUP *group, EC_SCALAR *r, const EC_SCALAR *a,
const EC_SCALAR *b) {
- const BIGNUM *order = &group->order->N;
+ const BIGNUM *order = &group->order.N;
BN_ULONG tmp[EC_MAX_WORDS];
bn_mod_sub_words(r->words, a->words, b->words, order->d, tmp, order->width);
OPENSSL_cleanse(tmp, sizeof(tmp));
@@ -110,35 +108,35 @@
void ec_scalar_select(const EC_GROUP *group, EC_SCALAR *out, BN_ULONG mask,
const EC_SCALAR *a, const EC_SCALAR *b) {
- const BIGNUM *order = &group->order->N;
+ const BIGNUM *order = &group->order.N;
bn_select_words(out->words, mask, a->words, b->words, order->width);
}
void ec_scalar_to_montgomery(const EC_GROUP *group, EC_SCALAR *r,
const EC_SCALAR *a) {
- const BIGNUM *order = &group->order->N;
- bn_to_montgomery_small(r->words, a->words, order->width, group->order);
+ const BIGNUM *order = &group->order.N;
+ bn_to_montgomery_small(r->words, a->words, order->width, &group->order);
}
void ec_scalar_from_montgomery(const EC_GROUP *group, EC_SCALAR *r,
const EC_SCALAR *a) {
- const BIGNUM *order = &group->order->N;
+ const BIGNUM *order = &group->order.N;
bn_from_montgomery_small(r->words, order->width, a->words, order->width,
- group->order);
+ &group->order);
}
void ec_scalar_mul_montgomery(const EC_GROUP *group, EC_SCALAR *r,
const EC_SCALAR *a, const EC_SCALAR *b) {
- const BIGNUM *order = &group->order->N;
+ const BIGNUM *order = &group->order.N;
bn_mod_mul_montgomery_small(r->words, a->words, b->words, order->width,
- group->order);
+ &group->order);
}
void ec_simple_scalar_inv0_montgomery(const EC_GROUP *group, EC_SCALAR *r,
const EC_SCALAR *a) {
- const BIGNUM *order = &group->order->N;
+ const BIGNUM *order = &group->order.N;
bn_mod_inverse0_prime_mont_small(r->words, a->words, order->width,
- group->order);
+ &group->order);
}
int ec_simple_scalar_to_montgomery_inv_vartime(const EC_GROUP *group,
diff --git a/crypto/fipsmodule/ec/simple.c b/crypto/fipsmodule/ec/simple.c
index 0b27040..624d3ce 100644
--- a/crypto/fipsmodule/ec/simple.c
+++ b/crypto/fipsmodule/ec/simple.c
@@ -104,12 +104,8 @@
goto err;
}
- group->field = BN_MONT_CTX_new_for_modulus(p, ctx);
- if (group->field == NULL) {
- goto err;
- }
-
- if (!ec_bignum_to_felem(group, &group->a, a) ||
+ if (!BN_MONT_CTX_set(&group->field, p, ctx) ||
+ !ec_bignum_to_felem(group, &group->a, a) ||
!ec_bignum_to_felem(group, &group->b, b) ||
!ec_bignum_to_felem(group, &group->one, BN_value_one())) {
goto err;
@@ -120,7 +116,7 @@
!BN_add_word(tmp, 3)) {
goto err;
}
- group->a_is_minus3 = (0 == BN_cmp(tmp, &group->field->N));
+ group->a_is_minus3 = (0 == BN_cmp(tmp, &group->field.N));
ret = 1;
@@ -131,7 +127,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->N)) ||
+ 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;
@@ -316,22 +312,21 @@
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->N);
- bn_words_to_big_endian(out, len, in->words, group->field->N.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->N)) {
+ 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->N.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->N.d,
- group->field->N.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 ce5b317..796c408 100644
--- a/crypto/fipsmodule/ec/simple_mul.c
+++ b/crypto/fipsmodule/ec/simple_mul.c
@@ -48,7 +48,7 @@
}
if (i % 5 == 0) {
// Compute the next window value.
- const size_t width = group->order->N.width;
+ const size_t width = group->order.N.width;
uint8_t window = bn_is_bit_set_words(scalar->words, width, i + 4) << 4;
window |= bn_is_bit_set_words(scalar->words, width, i + 3) << 3;
window |= bn_is_bit_set_words(scalar->words, width, i + 2) << 2;
@@ -99,7 +99,7 @@
EC_JACOBIAN *out,
const EC_JACOBIAN precomp[17],
const EC_SCALAR *scalar, unsigned i) {
- const size_t width = group->order->N.width;
+ const size_t width = group->order.N.width;
uint8_t window = bn_is_bit_set_words(scalar->words, width, i + 4) << 5;
window |= bn_is_bit_set_words(scalar->words, width, i + 3) << 4;
window |= bn_is_bit_set_words(scalar->words, width, i + 2) << 3;
@@ -212,7 +212,7 @@
EC_JACOBIAN *out,
const EC_PRECOMP *precomp,
const EC_SCALAR *scalar, unsigned i) {
- const size_t width = group->order->N.width;
+ const size_t width = group->order.N.width;
unsigned stride = ec_GFp_mont_comb_stride(group);
// Select the bits corresponding to the comb shifted up by |i|.
unsigned window = 0;
diff --git a/crypto/fipsmodule/ec/wnaf.c b/crypto/fipsmodule/ec/wnaf.c
index c9935fc..2cc0fbc 100644
--- a/crypto/fipsmodule/ec/wnaf.c
+++ b/crypto/fipsmodule/ec/wnaf.c
@@ -138,8 +138,8 @@
// we shift and add at most one copy of |bit|, this will continue to hold
// afterwards.
window_val >>= 1;
- window_val += bit * bn_is_bit_set_words(scalar->words,
- group->order->N.width, j + w + 1);
+ window_val += bit * bn_is_bit_set_words(scalar->words, group->order.N.width,
+ j + w + 1);
assert(window_val <= next_bit);
}