summaryrefslogtreecommitdiffstats
path: root/crypto/ec
diff options
context:
space:
mode:
authorSohaib ul Hassan <soh.19.hassan@gmail.com>2018-06-16 17:07:40 +0300
committerMatt Caswell <matt@openssl.org>2018-06-19 11:43:59 +0100
commitf667820c16a44245a4a898a568936c47a9b0ee6e (patch)
treefb283e5052edca879596771fbe1cf8e9387bad1d /crypto/ec
parentddb634fe6f9aeea34fe036cf804903b4240d38ac (diff)
Implement coordinate blinding for EC_POINT
This commit implements coordinate blinding, i.e., it randomizes the representative of an elliptic curve point in its equivalence class, for prime curves implemented through EC_GFp_simple_method, EC_GFp_mont_method, and EC_GFp_nist_method. This commit is derived from the patch https://marc.info/?l=openssl-dev&m=131194808413635 by Billy Brumley. Coordinate blinding is a generally useful side-channel countermeasure and is (mostly) free. The function itself takes a few field multiplicationss, but is usually only necessary at the beginning of a scalar multiplication (as implemented in the patch). When used this way, it makes the values that variables take (i.e., field elements in an algorithm state) unpredictable. For instance, this mitigates chosen EC point side-channel attacks for settings such as ECDH and EC private key decryption, for the aforementioned curves. For EC_METHODs using different coordinate representations this commit does nothing, but the corresponding coordinate blinding function can be easily added in the future to extend these changes to such curves. Co-authored-by: Nicola Tuveri <nic.tuv@gmail.com> Co-authored-by: Billy Brumley <bbrumley@gmail.com> Reviewed-by: Andy Polyakov <appro@openssl.org> Reviewed-by: Matt Caswell <matt@openssl.org> (Merged from https://github.com/openssl/openssl/pull/6501)
Diffstat (limited to 'crypto/ec')
-rw-r--r--crypto/ec/ec2_smpl.c4
-rw-r--r--crypto/ec/ec_err.c2
-rw-r--r--crypto/ec/ec_lcl.h5
-rw-r--r--crypto/ec/ec_lib.c18
-rw-r--r--crypto/ec/ec_mult.c11
-rw-r--r--crypto/ec/ecp_mont.c4
-rw-r--r--crypto/ec/ecp_nist.c4
-rw-r--r--crypto/ec/ecp_nistp224.c4
-rw-r--r--crypto/ec/ecp_nistp521.c4
-rw-r--r--crypto/ec/ecp_nistz256.c3
-rw-r--r--crypto/ec/ecp_smpl.c58
11 files changed, 110 insertions, 7 deletions
diff --git a/crypto/ec/ec2_smpl.c b/crypto/ec/ec2_smpl.c
index b79e60b8b5..cef6ba4c65 100644
--- a/crypto/ec/ec2_smpl.c
+++ b/crypto/ec/ec2_smpl.c
@@ -64,7 +64,9 @@ const EC_METHOD *EC_GF2m_simple_method(void)
ec_key_simple_generate_public_key,
0, /* keycopy */
0, /* keyfinish */
- ecdh_simple_compute_key
+ ecdh_simple_compute_key,
+ 0, /* field_inverse_mod_ord */
+ 0 /* blind_coordinates */
};
return &ret;
diff --git a/crypto/ec/ec_err.c b/crypto/ec/ec_err.c
index 6a1be2eb3b..342b84fecb 100644
--- a/crypto/ec/ec_err.c
+++ b/crypto/ec/ec_err.c
@@ -116,6 +116,8 @@ static const ERR_STRING_DATA EC_str_functs[] = {
"ec_GFp_nist_field_sqr"},
{ERR_PACK(ERR_LIB_EC, EC_F_EC_GFP_NIST_GROUP_SET_CURVE, 0),
"ec_GFp_nist_group_set_curve"},
+ {ERR_PACK(ERR_LIB_EC, EC_F_EC_GFP_SIMPLE_BLIND_COORDINATES, 0),
+ "ec_GFp_simple_blind_coordinates"},
{ERR_PACK(ERR_LIB_EC, EC_F_EC_GFP_SIMPLE_GROUP_CHECK_DISCRIMINANT, 0),
"ec_GFp_simple_group_check_discriminant"},
{ERR_PACK(ERR_LIB_EC, EC_F_EC_GFP_SIMPLE_GROUP_SET_CURVE, 0),
diff --git a/crypto/ec/ec_lcl.h b/crypto/ec/ec_lcl.h
index 5e14071aec..006e3b6e16 100644
--- a/crypto/ec/ec_lcl.h
+++ b/crypto/ec/ec_lcl.h
@@ -176,6 +176,7 @@ struct ec_method_st {
/* Inverse modulo order */
int (*field_inverse_mod_ord)(const EC_GROUP *, BIGNUM *r, BIGNUM *x,
BN_CTX *ctx);
+ int (*blind_coordinates)(const EC_GROUP *group, EC_POINT *p, BN_CTX *ctx);
};
/*
@@ -382,6 +383,8 @@ int ec_GFp_simple_field_mul(const EC_GROUP *, BIGNUM *r, const BIGNUM *a,
const BIGNUM *b, BN_CTX *);
int ec_GFp_simple_field_sqr(const EC_GROUP *, BIGNUM *r, const BIGNUM *a,
BN_CTX *);
+int ec_GFp_simple_blind_coordinates(const EC_GROUP *group, EC_POINT *p,
+ BN_CTX *ctx);
/* method functions in ecp_mont.c */
int ec_GFp_mont_group_init(EC_GROUP *);
@@ -635,3 +638,5 @@ void X25519_public_from_private(uint8_t out_public_value[32],
int EC_GROUP_do_inverse_ord(const EC_GROUP *group, BIGNUM *res,
BIGNUM *x, BN_CTX *ctx);
+
+int ec_point_blind_coordinates(const EC_GROUP *group, EC_POINT *p, BN_CTX *ctx);
diff --git a/crypto/ec/ec_lib.c b/crypto/ec/ec_lib.c
index 30b11f75e9..d0393e8bad 100644
--- a/crypto/ec/ec_lib.c
+++ b/crypto/ec/ec_lib.c
@@ -1025,3 +1025,21 @@ int EC_GROUP_do_inverse_ord(const EC_GROUP *group, BIGNUM *res,
else
return 0;
}
+
+/*-
+ * Coordinate blinding for EC_POINT.
+ *
+ * The underlying EC_METHOD can optionally implement this function:
+ * underlying implementations should return 0 on errors, or 1 on
+ * success.
+ *
+ * This wrapper returns 1 in case the underlying EC_METHOD does not
+ * support coordinate blinding.
+ */
+int ec_point_blind_coordinates(const EC_GROUP *group, EC_POINT *p, BN_CTX *ctx)
+{
+ if (group->meth->blind_coordinates == NULL)
+ return 1; /* ignore if not implemented */
+
+ return group->meth->blind_coordinates(group, p, ctx);
+}
diff --git a/crypto/ec/ec_mult.c b/crypto/ec/ec_mult.c
index 05a3aca0a4..b668e87ff7 100644
--- a/crypto/ec/ec_mult.c
+++ b/crypto/ec/ec_mult.c
@@ -211,6 +211,17 @@ static int ec_mul_consttime(const EC_GROUP *group, EC_POINT *r,
|| (bn_wexpand(r->Z, group_top) == NULL))
goto err;
+ /*-
+ * Apply coordinate blinding for EC_POINT.
+ *
+ * The underlying EC_METHOD can optionally implement this function:
+ * ec_point_blind_coordinates() returns 0 in case of errors or 1 on
+ * success or if coordinate blinding is not implemented for this
+ * group.
+ */
+ if (!ec_point_blind_coordinates(group, s, ctx))
+ goto err;
+
/* top bit is a 1, in a fixed pos */
if (!EC_POINT_copy(r, s))
goto err;
diff --git a/crypto/ec/ecp_mont.c b/crypto/ec/ecp_mont.c
index 1a760d1239..27ece3b43c 100644
--- a/crypto/ec/ecp_mont.c
+++ b/crypto/ec/ecp_mont.c
@@ -61,7 +61,9 @@ const EC_METHOD *EC_GFp_mont_method(void)
ec_key_simple_generate_public_key,
0, /* keycopy */
0, /* keyfinish */
- ecdh_simple_compute_key
+ ecdh_simple_compute_key,
+ 0, /* field_inverse_mod_ord */
+ ec_GFp_simple_blind_coordinates
};
return &ret;
diff --git a/crypto/ec/ecp_nist.c b/crypto/ec/ecp_nist.c
index 16c4cce313..aaa73d62d7 100644
--- a/crypto/ec/ecp_nist.c
+++ b/crypto/ec/ecp_nist.c
@@ -63,7 +63,9 @@ const EC_METHOD *EC_GFp_nist_method(void)
ec_key_simple_generate_public_key,
0, /* keycopy */
0, /* keyfinish */
- ecdh_simple_compute_key
+ ecdh_simple_compute_key,
+ 0, /* field_inverse_mod_ord */
+ ec_GFp_simple_blind_coordinates
};
return &ret;
diff --git a/crypto/ec/ecp_nistp224.c b/crypto/ec/ecp_nistp224.c
index 364b7f246d..6e7c687c43 100644
--- a/crypto/ec/ecp_nistp224.c
+++ b/crypto/ec/ecp_nistp224.c
@@ -290,7 +290,9 @@ const EC_METHOD *EC_GFp_nistp224_method(void)
ec_key_simple_generate_public_key,
0, /* keycopy */
0, /* keyfinish */
- ecdh_simple_compute_key
+ ecdh_simple_compute_key,
+ 0, /* field_inverse_mod_ord */
+ 0 /* blind_coordinates */
};
return &ret;
diff --git a/crypto/ec/ecp_nistp521.c b/crypto/ec/ecp_nistp521.c
index 3f68ae3c1c..43f3e2d9ee 100644
--- a/crypto/ec/ecp_nistp521.c
+++ b/crypto/ec/ecp_nistp521.c
@@ -1658,7 +1658,9 @@ const EC_METHOD *EC_GFp_nistp521_method(void)
ec_key_simple_generate_public_key,
0, /* keycopy */
0, /* keyfinish */
- ecdh_simple_compute_key
+ ecdh_simple_compute_key,
+ 0, /* field_inverse_mod_ord */
+ 0 /* blind_coordinates */
};
return &ret;
diff --git a/crypto/ec/ecp_nistz256.c b/crypto/ec/ecp_nistz256.c
index d3603fbbec..02925616b1 100644
--- a/crypto/ec/ecp_nistz256.c
+++ b/crypto/ec/ecp_nistz256.c
@@ -1730,7 +1730,8 @@ const EC_METHOD *EC_GFp_nistz256_method(void)
0, /* keycopy */
0, /* keyfinish */
ecdh_simple_compute_key,
- ecp_nistz256_inv_mod_ord /* can be #define-d NULL */
+ ecp_nistz256_inv_mod_ord, /* can be #define-d NULL */
+ 0 /* blind_coordinates */
};
return &ret;
diff --git a/crypto/ec/ecp_smpl.c b/crypto/ec/ecp_smpl.c
index 35d15a6882..e0e4996cfd 100644
--- a/crypto/ec/ecp_smpl.c
+++ b/crypto/ec/ecp_smpl.c
@@ -62,7 +62,9 @@ const EC_METHOD *EC_GFp_simple_method(void)
ec_key_simple_generate_public_key,
0, /* keycopy */
0, /* keyfinish */
- ecdh_simple_compute_key
+ ecdh_simple_compute_key,
+ 0, /* field_inverse_mod_ord */
+ ec_GFp_simple_blind_coordinates
};
return &ret;
@@ -1363,3 +1365,57 @@ int ec_GFp_simple_field_sqr(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a,
{
return BN_mod_sqr(r, a, group->field, ctx);
}
+
+/*-
+ * 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;
+}
+