Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/boringssl.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'crypto/ec/ec_montgomery.c')
-rw-r--r--crypto/ec/ec_montgomery.c128
1 files changed, 90 insertions, 38 deletions
diff --git a/crypto/ec/ec_montgomery.c b/crypto/ec/ec_montgomery.c
index 62b0d7f6..35df3651 100644
--- a/crypto/ec/ec_montgomery.c
+++ b/crypto/ec/ec_montgomery.c
@@ -79,23 +79,18 @@ int ec_GFp_mont_group_init(EC_GROUP *group) {
ok = ec_GFp_simple_group_init(group);
group->mont = NULL;
- group->one = NULL;
return ok;
}
void ec_GFp_mont_group_finish(EC_GROUP *group) {
BN_MONT_CTX_free(group->mont);
group->mont = NULL;
- BN_free(group->one);
- group->one = NULL;
ec_GFp_simple_group_finish(group);
}
int ec_GFp_mont_group_copy(EC_GROUP *dest, const EC_GROUP *src) {
BN_MONT_CTX_free(dest->mont);
dest->mont = NULL;
- BN_clear_free(dest->one);
- dest->one = NULL;
if (!ec_GFp_simple_group_copy(dest, src)) {
return 0;
@@ -110,12 +105,6 @@ int ec_GFp_mont_group_copy(EC_GROUP *dest, const EC_GROUP *src) {
goto err;
}
}
- if (src->one != NULL) {
- dest->one = BN_dup(src->one);
- if (dest->one == NULL) {
- goto err;
- }
- }
return 1;
@@ -129,13 +118,10 @@ 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();
@@ -152,29 +138,20 @@ int ec_GFp_mont_group_set_curve(EC_GROUP *group, const BIGNUM *p,
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;
}
@@ -218,19 +195,6 @@ int ec_GFp_mont_field_decode(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a,
return BN_from_montgomery(r, a, group->mont, ctx);
}
-int ec_GFp_mont_field_set_to_one(const EC_GROUP *group, BIGNUM *r,
- BN_CTX *ctx) {
- if (group->one == NULL) {
- OPENSSL_PUT_ERROR(EC, EC_R_NOT_INITIALIZED);
- return 0;
- }
-
- if (!BN_copy(r, group->one)) {
- return 0;
- }
- return 1;
-}
-
static int ec_GFp_mont_check_pub_key_order(const EC_GROUP *group,
const EC_POINT* pub_key,
BN_CTX *ctx) {
@@ -251,20 +215,108 @@ err:
return ret;
}
+static int ec_GFp_mont_point_get_affine_coordinates(const EC_GROUP *group,
+ const EC_POINT *point,
+ BIGNUM *x, BIGNUM *y,
+ BN_CTX *ctx) {
+ if (EC_POINT_is_at_infinity(group, point)) {
+ OPENSSL_PUT_ERROR(EC, EC_R_POINT_AT_INFINITY);
+ return 0;
+ }
+
+ BN_CTX *new_ctx = NULL;
+ if (ctx == NULL) {
+ ctx = new_ctx = BN_CTX_new();
+ if (ctx == NULL) {
+ return 0;
+ }
+ }
+
+ int ret = 0;
+
+ BN_CTX_start(ctx);
+
+ if (BN_cmp(&point->Z, &group->one) == 0) {
+ /* |point| is already affine. */
+ if (x != NULL && !BN_from_montgomery(x, &point->X, group->mont, ctx)) {
+ goto err;
+ }
+ if (y != NULL && !BN_from_montgomery(y, &point->Y, group->mont, ctx)) {
+ goto err;
+ }
+ } else {
+ /* transform (X, Y, Z) into (x, y) := (X/Z^2, Y/Z^3) */
+
+ BIGNUM *Z_1 = BN_CTX_get(ctx);
+ BIGNUM *Z_2 = BN_CTX_get(ctx);
+ BIGNUM *Z_3 = BN_CTX_get(ctx);
+ if (Z_1 == NULL ||
+ Z_2 == NULL ||
+ Z_3 == NULL) {
+ goto err;
+ }
+
+ /* The straightforward way to calculate the inverse of a Montgomery-encoded
+ * value where the result is Montgomery-encoded is:
+ *
+ * |BN_from_montgomery| + |BN_mod_inverse| + |BN_to_montgomery|.
+ *
+ * This is equivalent, but more efficient, because |BN_from_montgomery|
+ * is more efficient (at least in theory) than |BN_to_montgomery|, since it
+ * doesn't have to do the multiplication before the reduction. */
+ if (!BN_from_montgomery(Z_1, &point->Z, group->mont, ctx) ||
+ !BN_from_montgomery(Z_1, Z_1, group->mont, ctx) ||
+ !BN_mod_inverse(Z_1, Z_1, &group->field, ctx)) {
+ goto err;
+ }
+
+ if (!BN_mod_mul_montgomery(Z_2, Z_1, Z_1, group->mont, ctx)) {
+ goto err;
+ }
+
+ /* Instead of using |BN_from_montgomery| to convert the |x| coordinate
+ * and then calling |BN_from_montgomery| again to convert the |y|
+ * coordinate below, convert the common factor |Z_2| once now, saving one
+ * reduction. */
+ if (!BN_from_montgomery(Z_2, Z_2, group->mont, ctx)) {
+ goto err;
+ }
+
+ if (x != NULL) {
+ if (!BN_mod_mul_montgomery(x, &point->X, Z_2, group->mont, ctx)) {
+ goto err;
+ }
+ }
+
+ if (y != NULL) {
+ if (!BN_mod_mul_montgomery(Z_3, Z_2, Z_1, group->mont, ctx) ||
+ !BN_mod_mul_montgomery(y, &point->Y, Z_3, group->mont, ctx)) {
+ goto err;
+ }
+ }
+ }
+
+ ret = 1;
+
+err:
+ BN_CTX_end(ctx);
+ BN_CTX_free(new_ctx);
+ return ret;
+}
+
const EC_METHOD *EC_GFp_mont_method(void) {
static const EC_METHOD ret = {
ec_GFp_mont_group_init,
ec_GFp_mont_group_finish,
ec_GFp_mont_group_copy,
ec_GFp_mont_group_set_curve,
- ec_GFp_simple_point_get_affine_coordinates,
+ ec_GFp_mont_point_get_affine_coordinates,
ec_wNAF_mul /* XXX: Not constant time. */,
ec_GFp_mont_check_pub_key_order,
ec_GFp_mont_field_mul,
ec_GFp_mont_field_sqr,
ec_GFp_mont_field_encode,
ec_GFp_mont_field_decode,
- ec_GFp_mont_field_set_to_one,
};
return &ret;