summaryrefslogtreecommitdiffstats
path: root/crypto
diff options
context:
space:
mode:
authorSohaib ul Hassan <soh.19.hassan@gmail.com>2018-06-16 17:07:40 +0300
committerNicola Tuveri <nic.tuv@gmail.com>2018-10-02 18:12:37 +0300
commit875ba8b21ecc65ad9a6bdc66971e50461660fcbb (patch)
tree749cdf416adb049643c3e142372e510619028ce0 /crypto
parente5d1825728e41dbd650b9969a40bace692010408 (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: Tim Hudson <tjh@openssl.org> Reviewed-by: Nicola Tuveri <nic.tuv@gmail.com> Reviewed-by: Andy Polyakov <appro@openssl.org> (Merged from https://github.com/openssl/openssl/pull/6526)
Diffstat (limited to 'crypto')
-rw-r--r--crypto/ec/ec2_smpl.c3
-rw-r--r--crypto/ec/ec_err.c4
-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.c3
-rw-r--r--crypto/ec/ecp_nist.c3
-rw-r--r--crypto/ec/ecp_nistp224.c3
-rw-r--r--crypto/ec/ecp_nistp521.c3
-rw-r--r--crypto/ec/ecp_nistz256.c3
-rw-r--r--crypto/ec/ecp_smpl.c57
11 files changed, 105 insertions, 8 deletions
diff --git a/crypto/ec/ec2_smpl.c b/crypto/ec/ec2_smpl.c
index 28b91d5102..cdacce61ac 100644
--- a/crypto/ec/ec2_smpl.c
+++ b/crypto/ec/ec2_smpl.c
@@ -83,7 +83,8 @@ 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 /* blind_coordinates */
};
return &ret;
diff --git a/crypto/ec/ec_err.c b/crypto/ec/ec_err.c
index e4c2c1c1a4..717c92e984 100644
--- a/crypto/ec/ec_err.c
+++ b/crypto/ec/ec_err.c
@@ -1,6 +1,6 @@
/*
* Generated by util/mkerr.pl DO NOT EDIT
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
@@ -97,6 +97,8 @@ static ERR_STRING_DATA EC_str_functs[] = {
{ERR_FUNC(EC_F_EC_GFP_NIST_FIELD_SQR), "ec_GFp_nist_field_sqr"},
{ERR_FUNC(EC_F_EC_GFP_NIST_GROUP_SET_CURVE),
"ec_GFp_nist_group_set_curve"},
+ {ERR_FUNC(EC_F_EC_GFP_SIMPLE_BLIND_COORDINATES),
+ "ec_GFp_simple_blind_coordinates"},
{ERR_FUNC(EC_F_EC_GFP_SIMPLE_GROUP_CHECK_DISCRIMINANT),
"ec_GFp_simple_group_check_discriminant"},
{ERR_FUNC(EC_F_EC_GFP_SIMPLE_GROUP_SET_CURVE),
diff --git a/crypto/ec/ec_lcl.h b/crypto/ec/ec_lcl.h
index d8141704cf..ca1776efdb 100644
--- a/crypto/ec/ec_lcl.h
+++ b/crypto/ec/ec_lcl.h
@@ -169,6 +169,7 @@ struct ec_method_st {
/* custom ECDH operation */
int (*ecdh_compute_key)(unsigned char **pout, size_t *poutlen,
const EC_POINT *pub_key, const EC_KEY *ecdh);
+ int (*blind_coordinates)(const EC_GROUP *group, EC_POINT *p, BN_CTX *ctx);
};
/*
@@ -375,6 +376,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 *);
@@ -627,3 +630,5 @@ int X25519(uint8_t out_shared_key[32], const uint8_t private_key[32],
const uint8_t peer_public_value[32]);
void X25519_public_from_private(uint8_t out_public_value[32],
const uint8_t private_key[32]);
+
+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 d665556d57..a7be03b627 100644
--- a/crypto/ec/ec_lib.c
+++ b/crypto/ec/ec_lib.c
@@ -1017,3 +1017,21 @@ int ec_group_simple_order_bits(const EC_GROUP *group)
return 0;
return BN_num_bits(group->order);
}
+
+/*-
+ * 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 71ec910c99..22bb30ffa1 100644
--- a/crypto/ec/ec_mult.c
+++ b/crypto/ec/ec_mult.c
@@ -216,6 +216,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 994cc1d0ff..1e0a3e0df8 100644
--- a/crypto/ec/ecp_mont.c
+++ b/crypto/ec/ecp_mont.c
@@ -66,7 +66,8 @@ 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,
+ ec_GFp_simple_blind_coordinates
};
return &ret;
diff --git a/crypto/ec/ecp_nist.c b/crypto/ec/ecp_nist.c
index 615563bc38..66b88d5ccd 100644
--- a/crypto/ec/ecp_nist.c
+++ b/crypto/ec/ecp_nist.c
@@ -68,7 +68,8 @@ 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,
+ ec_GFp_simple_blind_coordinates
};
return &ret;
diff --git a/crypto/ec/ecp_nistp224.c b/crypto/ec/ecp_nistp224.c
index 0cd994fc23..7dc5309f71 100644
--- a/crypto/ec/ecp_nistp224.c
+++ b/crypto/ec/ecp_nistp224.c
@@ -290,7 +290,8 @@ 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 /* blind_coordinates */
};
return &ret;
diff --git a/crypto/ec/ecp_nistp521.c b/crypto/ec/ecp_nistp521.c
index 133f089fd2..74d56e3336 100644
--- a/crypto/ec/ecp_nistp521.c
+++ b/crypto/ec/ecp_nistp521.c
@@ -1642,7 +1642,8 @@ 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 /* blind_coordinates */
};
return &ret;
diff --git a/crypto/ec/ecp_nistz256.c b/crypto/ec/ecp_nistz256.c
index 4dbe216927..7eafce649b 100644
--- a/crypto/ec/ecp_nistz256.c
+++ b/crypto/ec/ecp_nistz256.c
@@ -1536,7 +1536,8 @@ const EC_METHOD *EC_GFp_nistz256_method(void)
ec_key_simple_generate_public_key,
0, /* keycopy */
0, /* keyfinish */
- ecdh_simple_compute_key
+ ecdh_simple_compute_key,
+ 0 /* blind_coordinates */
};
return &ret;
diff --git a/crypto/ec/ecp_smpl.c b/crypto/ec/ecp_smpl.c
index e3b88315fd..2015f1173b 100644
--- a/crypto/ec/ecp_smpl.c
+++ b/crypto/ec/ecp_smpl.c
@@ -67,7 +67,8 @@ 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,
+ ec_GFp_simple_blind_coordinates
};
return &ret;
@@ -1368,3 +1369,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_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;
+}
+