isaacpittman-hitachi / rpms / openssl

Forked from rpms/openssl 2 years ago
Clone

Blame SOURCES/openssl-1.1.1-cve-2019-1547.patch

067bfb
From 30c22fa8b1d840036b8e203585738df62a03cec8 Mon Sep 17 00:00:00 2001
067bfb
From: Billy Brumley <bbrumley@gmail.com>
067bfb
Date: Thu, 5 Sep 2019 21:25:37 +0300
067bfb
Subject: [PATCH] [crypto/ec] for ECC parameters with NULL or zero cofactor,
067bfb
 compute it
067bfb
067bfb
The cofactor argument to EC_GROUP_set_generator is optional, and SCA
067bfb
mitigations for ECC currently use it. So the library currently falls
067bfb
back to very old SCA-vulnerable code if the cofactor is not present.
067bfb
067bfb
This PR allows EC_GROUP_set_generator to compute the cofactor for all
067bfb
curves of cryptographic interest. Steering scalar multiplication to more
067bfb
SCA-robust code.
067bfb
067bfb
This issue affects persisted private keys in explicit parameter form,
067bfb
where the (optional) cofactor field is zero or absent.
067bfb
067bfb
It also affects curves not built-in to the library, but constructed
067bfb
programatically with explicit parameters, then calling
067bfb
EC_GROUP_set_generator with a nonsensical value (NULL, zero).
067bfb
067bfb
The very old scalar multiplication code is known to be vulnerable to
067bfb
local uarch attacks, outside of the OpenSSL threat model. New results
067bfb
suggest the code path is also vulnerable to traditional wall clock
067bfb
timing attacks.
067bfb
067bfb
CVE-2019-1547
067bfb
067bfb
Reviewed-by: Matt Caswell <matt@openssl.org>
067bfb
Reviewed-by: Tomas Mraz <tmraz@fedoraproject.org>
067bfb
Reviewed-by: Nicola Tuveri <nic.tuv@gmail.com>
067bfb
(Merged from https://github.com/openssl/openssl/pull/9781)
067bfb
---
067bfb
 crypto/ec/ec_lib.c | 103 ++++++++++++++++++++++++++++++++++++++++++---
067bfb
 1 file changed, 96 insertions(+), 7 deletions(-)
067bfb
067bfb
diff --git a/crypto/ec/ec_lib.c b/crypto/ec/ec_lib.c
067bfb
index 8cab5a5061..1289c8608e 100644
067bfb
--- a/crypto/ec/ec_lib.c
067bfb
+++ b/crypto/ec/ec_lib.c
067bfb
@@ -265,6 +265,67 @@ int EC_METHOD_get_field_type(const EC_METHOD *meth)
067bfb
 
067bfb
 static int ec_precompute_mont_data(EC_GROUP *);
067bfb
 
067bfb
+/*-
067bfb
+ * Try computing cofactor from the generator order (n) and field cardinality (q).
067bfb
+ * This works for all curves of cryptographic interest.
067bfb
+ *
067bfb
+ * Hasse thm: q + 1 - 2*sqrt(q) <= n*h <= q + 1 + 2*sqrt(q)
067bfb
+ * h_min = (q + 1 - 2*sqrt(q))/n
067bfb
+ * h_max = (q + 1 + 2*sqrt(q))/n
067bfb
+ * h_max - h_min = 4*sqrt(q)/n
067bfb
+ * So if n > 4*sqrt(q) holds, there is only one possible value for h:
067bfb
+ * h = \lfloor (h_min + h_max)/2 \rceil = \lfloor (q + 1)/n \rceil
067bfb
+ *
067bfb
+ * Otherwise, zero cofactor and return success.
067bfb
+ */
067bfb
+static int ec_guess_cofactor(EC_GROUP *group) {
067bfb
+    int ret = 0;
067bfb
+    BN_CTX *ctx = NULL;
067bfb
+    BIGNUM *q = NULL;
067bfb
+
067bfb
+    /*-
067bfb
+     * If the cofactor is too large, we cannot guess it.
067bfb
+     * The RHS of below is a strict overestimate of lg(4 * sqrt(q))
067bfb
+     */
067bfb
+    if (BN_num_bits(group->order) <= (BN_num_bits(group->field) + 1) / 2 + 3) {
067bfb
+        /* default to 0 */
067bfb
+        BN_zero(group->cofactor);
067bfb
+        /* return success */
067bfb
+        return 1;
067bfb
+    }
067bfb
+
067bfb
+    if ((ctx = BN_CTX_new()) == NULL)
067bfb
+        return 0;
067bfb
+
067bfb
+    BN_CTX_start(ctx);
067bfb
+    if ((q = BN_CTX_get(ctx)) == NULL)
067bfb
+        goto err;
067bfb
+
067bfb
+    /* set q = 2**m for binary fields; q = p otherwise */
067bfb
+    if (group->meth->field_type == NID_X9_62_characteristic_two_field) {
067bfb
+        BN_zero(q);
067bfb
+        if (!BN_set_bit(q, BN_num_bits(group->field) - 1))
067bfb
+            goto err;
067bfb
+    } else {
067bfb
+        if (!BN_copy(q, group->field))
067bfb
+            goto err;
067bfb
+    }
067bfb
+
067bfb
+    /* compute h = \lfloor (q + 1)/n \rceil = \lfloor (q + 1 + n/2)/n \rfloor */
067bfb
+    if (!BN_rshift1(group->cofactor, group->order) /* n/2 */
067bfb
+        || !BN_add(group->cofactor, group->cofactor, q) /* q + n/2 */
067bfb
+        /* q + 1 + n/2 */
067bfb
+        || !BN_add(group->cofactor, group->cofactor, BN_value_one())
067bfb
+        /* (q + 1 + n/2)/n */
067bfb
+        || !BN_div(group->cofactor, NULL, group->cofactor, group->order, ctx))
067bfb
+        goto err;
067bfb
+    ret = 1;
067bfb
+ err:
067bfb
+    BN_CTX_end(ctx);
067bfb
+    BN_CTX_free(ctx);
067bfb
+    return ret;
067bfb
+}
067bfb
+
067bfb
 int EC_GROUP_set_generator(EC_GROUP *group, const EC_POINT *generator,
067bfb
                            const BIGNUM *order, const BIGNUM *cofactor)
067bfb
 {
067bfb
@@ -273,6 +334,34 @@ int EC_GROUP_set_generator(EC_GROUP *group, const EC_POINT *generator,
067bfb
         return 0;
067bfb
     }
067bfb
 
067bfb
+    /* require group->field >= 1 */
067bfb
+    if (group->field == NULL || BN_is_zero(group->field)
067bfb
+        || BN_is_negative(group->field)) {
067bfb
+        ECerr(EC_F_EC_GROUP_SET_GENERATOR, EC_R_INVALID_FIELD);
067bfb
+        return 0;
067bfb
+    }
067bfb
+
067bfb
+    /*-
067bfb
+     * - require order >= 1
067bfb
+     * - enforce upper bound due to Hasse thm: order can be no more than one bit
067bfb
+     *   longer than field cardinality
067bfb
+     */
067bfb
+    if (order == NULL || BN_is_zero(order) || BN_is_negative(order)
067bfb
+        || BN_num_bits(order) > BN_num_bits(group->field) + 1) {
067bfb
+        ECerr(EC_F_EC_GROUP_SET_GENERATOR, EC_R_INVALID_GROUP_ORDER);
067bfb
+        return 0;
067bfb
+    }
067bfb
+
067bfb
+    /*-
067bfb
+     * Unfortunately the cofactor is an optional field in many standards.
067bfb
+     * Internally, the lib uses 0 cofactor as a marker for "unknown cofactor".
067bfb
+     * So accept cofactor == NULL or cofactor >= 0.
067bfb
+     */
067bfb
+    if (cofactor != NULL && BN_is_negative(cofactor)) {
067bfb
+        ECerr(EC_F_EC_GROUP_SET_GENERATOR, EC_R_UNKNOWN_COFACTOR);
067bfb
+        return 0;
067bfb
+    }
067bfb
+
067bfb
     if (group->generator == NULL) {
067bfb
         group->generator = EC_POINT_new(group);
067bfb
         if (group->generator == NULL)
067bfb
@@ -281,17 +370,17 @@ int EC_GROUP_set_generator(EC_GROUP *group, const EC_POINT *generator,
067bfb
     if (!EC_POINT_copy(group->generator, generator))
067bfb
         return 0;
067bfb
 
067bfb
-    if (order != NULL) {
067bfb
-        if (!BN_copy(group->order, order))
067bfb
-            return 0;
067bfb
-    } else
067bfb
-        BN_zero(group->order);
067bfb
+    if (!BN_copy(group->order, order))
067bfb
+        return 0;
067bfb
 
067bfb
-    if (cofactor != NULL) {
067bfb
+    /* Either take the provided positive cofactor, or try to compute it */
067bfb
+    if (cofactor != NULL && !BN_is_zero(cofactor)) {
067bfb
         if (!BN_copy(group->cofactor, cofactor))
067bfb
             return 0;
067bfb
-    } else
067bfb
+    } else if (!ec_guess_cofactor(group)) {
067bfb
         BN_zero(group->cofactor);
067bfb
+        return 0;
067bfb
+    }
067bfb
 
067bfb
     /*
067bfb
      * Some groups have an order with
067bfb
-- 
067bfb
2.20.1
067bfb