[openssl-commits] [openssl] OpenSSL_1_0_2-stable update
Matt Caswell
matt at openssl.org
Thu Jun 21 09:31:21 UTC 2018
The branch OpenSSL_1_0_2-stable has been updated
via 41d23d435221411b4d70c08b6c5424d0afcf4c19 (commit)
from 8fbbbdd5fcfeca62d339d1db11887da2a298ee8e (commit)
- Log -----------------------------------------------------------------
commit 41d23d435221411b4d70c08b6c5424d0afcf4c19
Author: Matt Caswell <matt at openssl.org>
Date: Tue Jun 19 15:07:02 2018 +0100
Add blinding to a DSA signature
This extends the recently added ECDSA signature blinding to blind DSA too.
This is based on side channel attacks demonstrated by Keegan Ryan (NCC
Group) for ECDSA which are likely to be able to be applied to DSA.
Normally, as in ECDSA, during signing the signer calculates:
s:= k^-1 * (m + r * priv_key) mod order
In ECDSA, the addition operation above provides a sufficient signal for a
flush+reload attack to derive the private key given sufficient signature
operations.
As a mitigation (based on a suggestion from Keegan) we add blinding to
the operation so that:
s := k^-1 * blind^-1 (blind * m + blind * r * priv_key) mod order
Since this attack is a localhost side channel only no CVE is assigned.
This commit also tweaks the previous ECDSA blinding so that blinding is
only removed at the last possible step.
Reviewed-by: Rich Salz <rsalz at openssl.org>
Reviewed-by: Richard Levitte <levitte at openssl.org>
(Merged from https://github.com/openssl/openssl/pull/6524)
-----------------------------------------------------------------------
Summary of changes:
CHANGES | 4 +--
crypto/dsa/dsa_ossl.c | 73 +++++++++++++++++++++++++++++++++++--------------
crypto/ecdsa/ecs_ossl.c | 14 +++++-----
3 files changed, 61 insertions(+), 30 deletions(-)
diff --git a/CHANGES b/CHANGES
index a3861ab..f9562dd 100644
--- a/CHANGES
+++ b/CHANGES
@@ -9,8 +9,8 @@
Changes between 1.0.2o and 1.0.2p [xx XXX xxxx]
- *) Add blinding to an ECDSA signature to protect against side channel attacks
- discovered by Keegan Ryan (NCC Group).
+ *) Add blinding to ECDSA and DSA signatures to protect against side channel
+ attacks discovered by Keegan Ryan (NCC Group).
[Matt Caswell]
*) When unlocking a pass phrase protected PEM file or PKCS#8 container, we
diff --git a/crypto/dsa/dsa_ossl.c b/crypto/dsa/dsa_ossl.c
index aa10dd1..2dcfede 100644
--- a/crypto/dsa/dsa_ossl.c
+++ b/crypto/dsa/dsa_ossl.c
@@ -133,17 +133,13 @@ const DSA_METHOD *DSA_OpenSSL(void)
static DSA_SIG *dsa_do_sign(const unsigned char *dgst, int dlen, DSA *dsa)
{
BIGNUM *kinv = NULL, *r = NULL, *s = NULL;
- BIGNUM m;
- BIGNUM xr;
+ BIGNUM *m, *blind, *blindm, *tmp;
BN_CTX *ctx = NULL;
int reason = ERR_R_BN_LIB;
DSA_SIG *ret = NULL;
int noredo = 0;
- BN_init(&m);
- BN_init(&xr);
-
- if (!dsa->p || !dsa->q || !dsa->g) {
+ if (dsa->p == NULL || dsa->q == NULL || dsa->g == NULL) {
reason = DSA_R_MISSING_PARAMETERS;
goto err;
}
@@ -154,6 +150,13 @@ static DSA_SIG *dsa_do_sign(const unsigned char *dgst, int dlen, DSA *dsa)
ctx = BN_CTX_new();
if (ctx == NULL)
goto err;
+ m = BN_CTX_get(ctx);
+ blind = BN_CTX_get(ctx);
+ blindm = BN_CTX_get(ctx);
+ tmp = BN_CTX_get(ctx);
+ if (tmp == NULL)
+ goto err;
+
redo:
if ((dsa->kinv == NULL) || (dsa->r == NULL)) {
if (!DSA_sign_setup(dsa, ctx, &kinv, &r))
@@ -173,20 +176,52 @@ static DSA_SIG *dsa_do_sign(const unsigned char *dgst, int dlen, DSA *dsa)
* 4.2
*/
dlen = BN_num_bytes(dsa->q);
- if (BN_bin2bn(dgst, dlen, &m) == NULL)
+ if (BN_bin2bn(dgst, dlen, m) == NULL)
goto err;
- /* Compute s = inv(k) (m + xr) mod q */
- if (!BN_mod_mul(&xr, dsa->priv_key, r, dsa->q, ctx))
- goto err; /* s = xr */
- if (!BN_add(s, &xr, &m))
- goto err; /* s = m + xr */
- if (BN_cmp(s, dsa->q) > 0)
- if (!BN_sub(s, s, dsa->q))
+ /*
+ * The normal signature calculation is:
+ *
+ * s := k^-1 * (m + r * priv_key) mod q
+ *
+ * We will blind this to protect against side channel attacks
+ *
+ * s := blind^-1 * k^-1 * (blind * m + blind * r * priv_key) mod q
+ */
+
+ /* Generate a blinding value */
+ do {
+ if (!BN_rand(blind, BN_num_bits(dsa->q) - 1, -1, 0))
goto err;
+ } while (BN_is_zero(blind));
+ BN_set_flags(blind, BN_FLG_CONSTTIME);
+ BN_set_flags(blindm, BN_FLG_CONSTTIME);
+ BN_set_flags(tmp, BN_FLG_CONSTTIME);
+
+ /* tmp := blind * priv_key * r mod q */
+ if (!BN_mod_mul(tmp, blind, dsa->priv_key, dsa->q, ctx))
+ goto err;
+ if (!BN_mod_mul(tmp, tmp, r, dsa->q, ctx))
+ goto err;
+
+ /* blindm := blind * m mod q */
+ if (!BN_mod_mul(blindm, blind, m, dsa->q, ctx))
+ goto err;
+
+ /* s : = (blind * priv_key * r) + (blind * m) mod q */
+ if (!BN_mod_add_quick(s, tmp, blindm, dsa->q))
+ goto err;
+
+ /* s := s * k^-1 mod q */
if (!BN_mod_mul(s, s, kinv, dsa->q, ctx))
goto err;
+ /* s:= s * blind^-1 mod q */
+ if (BN_mod_inverse(blind, blind, dsa->q, ctx) == NULL)
+ goto err;
+ if (!BN_mod_mul(s, s, blind, dsa->q, ctx))
+ goto err;
+
/*
* Redo if r or s is zero as required by FIPS 186-3: this is very
* unlikely.
@@ -210,13 +245,9 @@ static DSA_SIG *dsa_do_sign(const unsigned char *dgst, int dlen, DSA *dsa)
BN_free(r);
BN_free(s);
}
- if (ctx != NULL)
- BN_CTX_free(ctx);
- BN_clear_free(&m);
- BN_clear_free(&xr);
- if (kinv != NULL) /* dsa->kinv is NULL now if we used it */
- BN_clear_free(kinv);
- return (ret);
+ BN_CTX_free(ctx);
+ BN_clear_free(kinv);
+ return ret;
}
static int dsa_sign_setup(DSA *dsa, BN_CTX *ctx_in, BIGNUM **kinvp,
diff --git a/crypto/ecdsa/ecs_ossl.c b/crypto/ecdsa/ecs_ossl.c
index 1d37551..6115df7 100644
--- a/crypto/ecdsa/ecs_ossl.c
+++ b/crypto/ecdsa/ecs_ossl.c
@@ -334,7 +334,7 @@ static ECDSA_SIG *ecdsa_do_sign(const unsigned char *dgst, int dgst_len,
*
* We will blind this to protect against side channel attacks
*
- * s := k^-1 * blind^-1 * (blind * m + blind * r * priv_key) mod order
+ * s := blind^-1 * k^-1 * (blind * m + blind * r * priv_key) mod order
*/
/* Generate a blinding value */
@@ -368,18 +368,18 @@ static ECDSA_SIG *ecdsa_do_sign(const unsigned char *dgst, int dgst_len,
goto err;
}
- /* s:= s * blind^-1 mod order */
- if (BN_mod_inverse(blind, blind, order, ctx) == NULL) {
+ /* s := s * k^-1 mod order */
+ if (!BN_mod_mul(s, s, ckinv, order, ctx)) {
ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_BN_LIB);
goto err;
}
- if (!BN_mod_mul(s, s, blind, order, ctx)) {
+
+ /* s:= s * blind^-1 mod order */
+ if (BN_mod_inverse(blind, blind, order, ctx) == NULL) {
ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_BN_LIB);
goto err;
}
-
- /* s := s * k^-1 mod order */
- if (!BN_mod_mul(s, s, ckinv, order, ctx)) {
+ if (!BN_mod_mul(s, s, blind, order, ctx)) {
ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_BN_LIB);
goto err;
}
More information about the openssl-commits
mailing list