summary refs log tree commit diff
path: root/gnu/packages/patches/openssl-1.1.0-CVE-2018-0495.patch
diff options
context:
space:
mode:
Diffstat (limited to 'gnu/packages/patches/openssl-1.1.0-CVE-2018-0495.patch')
-rw-r--r--gnu/packages/patches/openssl-1.1.0-CVE-2018-0495.patch152
1 files changed, 152 insertions, 0 deletions
diff --git a/gnu/packages/patches/openssl-1.1.0-CVE-2018-0495.patch b/gnu/packages/patches/openssl-1.1.0-CVE-2018-0495.patch
new file mode 100644
index 0000000000..15dedbcbd0
--- /dev/null
+++ b/gnu/packages/patches/openssl-1.1.0-CVE-2018-0495.patch
@@ -0,0 +1,152 @@
+Fix CVE-2018-0495:
+
+https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-0495
+https://www.nccgroup.trust/us/our-research/technical-advisory-return-of-the-hidden-number-problem/
+
+Patch copied from upstream source repository:
+
+https://github.com/openssl/openssl/commit/0c27d793745c7837b13646302b6890a556b7017a
+
+From 0c27d793745c7837b13646302b6890a556b7017a Mon Sep 17 00:00:00 2001
+From: Matt Caswell <matt@openssl.org>
+Date: Fri, 25 May 2018 12:10:13 +0100
+Subject: [PATCH] Add blinding to an ECDSA signature
+
+Keegan Ryan (NCC Group) has demonstrated a side channel attack on an
+ECDSA signature operation. During signing the signer calculates:
+
+s:= k^-1 * (m + r * priv_key) mod order
+
+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.
+
+Reviewed-by: Rich Salz <rsalz@openssl.org>
+---
+ CHANGES                |  4 +++
+ crypto/ec/ecdsa_ossl.c | 70 +++++++++++++++++++++++++++++++++++++-----
+ 2 files changed, 67 insertions(+), 7 deletions(-)
+
+diff --git a/crypto/ec/ecdsa_ossl.c b/crypto/ec/ecdsa_ossl.c
+index 72e2f0f28b..449be0e92a 100644
+--- a/crypto/ec/ecdsa_ossl.c
++++ b/crypto/ec/ecdsa_ossl.c
+@@ -210,7 +210,8 @@ ECDSA_SIG *ossl_ecdsa_sign_sig(const unsigned char *dgst, int dgst_len,
+                                EC_KEY *eckey)
+ {
+     int ok = 0, i;
+-    BIGNUM *kinv = NULL, *s, *m = NULL, *tmp = NULL;
++    BIGNUM *kinv = NULL, *s, *m = NULL, *tmp = NULL, *blind = NULL;
++    BIGNUM *blindm = NULL;
+     const BIGNUM *order, *ckinv;
+     BN_CTX *ctx = NULL;
+     const EC_GROUP *group;
+@@ -243,8 +244,18 @@ ECDSA_SIG *ossl_ecdsa_sign_sig(const unsigned char *dgst, int dgst_len,
+     }
+     s = ret->s;
+ 
+-    if ((ctx = BN_CTX_new()) == NULL ||
+-        (tmp = BN_new()) == NULL || (m = BN_new()) == NULL) {
++    ctx = BN_CTX_secure_new();
++    if (ctx == NULL) {
++        ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, ERR_R_MALLOC_FAILURE);
++        goto err;
++    }
++
++    BN_CTX_start(ctx);
++    tmp = BN_CTX_get(ctx);
++    m = BN_CTX_get(ctx);
++    blind = BN_CTX_get(ctx);
++    blindm = BN_CTX_get(ctx);
++    if (blindm == NULL) {
+         ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, ERR_R_MALLOC_FAILURE);
+         goto err;
+     }
+@@ -284,18 +295,64 @@ ECDSA_SIG *ossl_ecdsa_sign_sig(const unsigned char *dgst, int dgst_len,
+             }
+         }
+ 
+-        if (!BN_mod_mul(tmp, priv_key, ret->r, order, ctx)) {
++        /*
++         * The normal signature calculation is:
++         *
++         *   s := k^-1 * (m + r * priv_key) mod order
++         *
++         * We will blind this to protect against side channel attacks
++         *
++         *   s := k^-1 * blind^-1 * (blind * m + blind * r * priv_key) mod order
++         */
++
++        /* Generate a blinding value */
++        do {
++            if (!BN_rand(blind, BN_num_bits(order) - 1, BN_RAND_TOP_ANY,
++                         BN_RAND_BOTTOM_ANY))
++                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 order */
++        if (!BN_mod_mul(tmp, blind, priv_key, order, ctx)) {
+             ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, ERR_R_BN_LIB);
+             goto err;
+         }
+-        if (!BN_mod_add_quick(s, tmp, m, order)) {
++        if (!BN_mod_mul(tmp, tmp, ret->r, order, ctx)) {
+             ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, ERR_R_BN_LIB);
+             goto err;
+         }
++
++        /* blindm := blind * m mod order */
++        if (!BN_mod_mul(blindm, blind, m, order, ctx)) {
++            ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, ERR_R_BN_LIB);
++            goto err;
++        }
++
++        /* s : = (blind * priv_key * r) + (blind * m) mod order */
++        if (!BN_mod_add_quick(s, tmp, blindm, order)) {
++            ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, ERR_R_BN_LIB);
++            goto err;
++        }
++
++        /* s:= s * blind^-1 mod order */
++        if (BN_mod_inverse(blind, blind, order, ctx) == NULL) {
++            ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, ERR_R_BN_LIB);
++            goto err;
++        }
++        if (!BN_mod_mul(s, s, blind, order, ctx)) {
++            ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, ERR_R_BN_LIB);
++            goto err;
++        }
++
++        /* s := s * k^-1 mod order */
+         if (!BN_mod_mul(s, s, ckinv, order, ctx)) {
+             ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, ERR_R_BN_LIB);
+             goto err;
+         }
++
+         if (BN_is_zero(s)) {
+             /*
+              * if kinv and r have been supplied by the caller don't to
+@@ -317,9 +374,8 @@ ECDSA_SIG *ossl_ecdsa_sign_sig(const unsigned char *dgst, int dgst_len,
+         ECDSA_SIG_free(ret);
+         ret = NULL;
+     }
++    BN_CTX_end(ctx);
+     BN_CTX_free(ctx);
+-    BN_clear_free(m);
+-    BN_clear_free(tmp);
+     BN_clear_free(kinv);
+     return ret;
+ }
+-- 
+2.17.1
+