[openssl] OpenSSL_1_1_0-stable update

nic.tuv at gmail.com nic.tuv at gmail.com
Sat Sep 7 09:50:23 UTC 2019


The branch OpenSSL_1_1_0-stable has been updated
       via  c31be97c64ab61d44d80fccce4deff976d4f9bbb (commit)
       via  7c1709c2da5414f5b6133d00a03fc8c5bf996c7a (commit)
      from  207a56437916a715bcf6e299c868c75a17ad8fc0 (commit)


- Log -----------------------------------------------------------------
commit c31be97c64ab61d44d80fccce4deff976d4f9bbb
Author: Billy Brumley <bbrumley at gmail.com>
Date:   Fri Sep 6 20:11:32 2019 +0300

    [test/recipes/30-test_evp_data] computing ECC cofactors: regression test
    
    Reviewed-by: Nicola Tuveri <nic.tuv at gmail.com>
    Reviewed-by: Matt Caswell <matt at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/9795)

commit 7c1709c2da5414f5b6133d00a03fc8c5bf996c7a
Author: Billy Brumley <bbrumley at gmail.com>
Date:   Fri Sep 6 19:34:53 2019 +0300

    [crypto/ec] for ECC parameters with NULL or zero cofactor, compute it
    
    The cofactor argument to EC_GROUP_set_generator is optional, and SCA
    mitigations for ECC currently use it. So the library currently falls
    back to very old SCA-vulnerable code if the cofactor is not present.
    
    This PR allows EC_GROUP_set_generator to compute the cofactor for all
    curves of cryptographic interest. Steering scalar multiplication to more
    SCA-robust code.
    
    This issue affects persisted private keys in explicit parameter form,
    where the (optional) cofactor field is zero or absent.
    
    It also affects curves not built-in to the library, but constructed
    programatically with explicit parameters, then calling
    EC_GROUP_set_generator with a nonsensical value (NULL, zero).
    
    The very old scalar multiplication code is known to be vulnerable to
    local uarch attacks, outside of the OpenSSL threat model. New results
    suggest the code path is also vulnerable to traditional wall clock
    timing attacks.
    
    CVE-2019-1547
    
    Reviewed-by: Nicola Tuveri <nic.tuv at gmail.com>
    Reviewed-by: Matt Caswell <matt at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/9795)

-----------------------------------------------------------------------

Summary of changes:
 CHANGES                                   |   8 ++-
 crypto/ec/ec_err.c                        |   1 +
 crypto/ec/ec_lib.c                        | 103 ++++++++++++++++++++++++++++--
 include/openssl/ec.h                      |   1 +
 test/recipes/30-test_evp_data/evppkey.txt |  50 +++++++++++++++
 5 files changed, 155 insertions(+), 8 deletions(-)

diff --git a/CHANGES b/CHANGES
index 2c89717497..1b6c1830e8 100644
--- a/CHANGES
+++ b/CHANGES
@@ -9,6 +9,13 @@
 
  Changes between 1.1.0k and 1.1.0l [xx XXX xxxx]
 
+  *) Compute ECC cofactors if not provided during EC_GROUP construction. Before
+     this change, EC_GROUP_set_generator would accept order and/or cofactor as
+     NULL. After this change, only the cofactor parameter can be NULL. It also
+     does some minimal sanity checks on the passed order.
+     (CVE-2019-1547)
+     [Billy Bob Brumley]
+
   *) Use Windows installation paths in the mingw builds
 
      Mingw isn't a POSIX environment per se, which means that Windows
@@ -16,7 +23,6 @@
      (CVE-2019-1552)
      [Richard Levitte]
 
-
  Changes between 1.1.0j and 1.1.0k [28 May 2019]
 
   *) Change the default RSA, DSA and DH size to 2048 bit instead of 1024.
diff --git a/crypto/ec/ec_err.c b/crypto/ec/ec_err.c
index aeee2e8f4c..fe747d8cde 100644
--- a/crypto/ec/ec_err.c
+++ b/crypto/ec/ec_err.c
@@ -273,6 +273,7 @@ static ERR_STRING_DATA EC_str_reasons[] = {
     {ERR_REASON(EC_R_SLOT_FULL), "slot full"},
     {ERR_REASON(EC_R_UNDEFINED_GENERATOR), "undefined generator"},
     {ERR_REASON(EC_R_UNDEFINED_ORDER), "undefined order"},
+    {ERR_REASON(EC_R_UNKNOWN_COFACTOR), "unknown cofactor"},
     {ERR_REASON(EC_R_UNKNOWN_GROUP), "unknown group"},
     {ERR_REASON(EC_R_UNKNOWN_ORDER), "unknown order"},
     {ERR_REASON(EC_R_UNSUPPORTED_FIELD), "unsupported field"},
diff --git a/crypto/ec/ec_lib.c b/crypto/ec/ec_lib.c
index a7be03b627..eaf44ccef9 100644
--- a/crypto/ec/ec_lib.c
+++ b/crypto/ec/ec_lib.c
@@ -257,6 +257,67 @@ int EC_METHOD_get_field_type(const EC_METHOD *meth)
     return meth->field_type;
 }
 
+/*-
+ * Try computing cofactor from the generator order (n) and field cardinality (q).
+ * This works for all curves of cryptographic interest.
+ *
+ * Hasse thm: q + 1 - 2*sqrt(q) <= n*h <= q + 1 + 2*sqrt(q)
+ * h_min = (q + 1 - 2*sqrt(q))/n
+ * h_max = (q + 1 + 2*sqrt(q))/n
+ * h_max - h_min = 4*sqrt(q)/n
+ * So if n > 4*sqrt(q) holds, there is only one possible value for h:
+ * h = \lfloor (h_min + h_max)/2 \rceil = \lfloor (q + 1)/n \rceil
+ *
+ * Otherwise, zero cofactor and return success.
+ */
+static int ec_guess_cofactor(EC_GROUP *group) {
+    int ret = 0;
+    BN_CTX *ctx = NULL;
+    BIGNUM *q = NULL;
+
+    /*-
+     * If the cofactor is too large, we cannot guess it.
+     * The RHS of below is a strict overestimate of lg(4 * sqrt(q))
+     */
+    if (BN_num_bits(group->order) <= (BN_num_bits(group->field) + 1) / 2 + 3) {
+        /* default to 0 */
+        BN_zero(group->cofactor);
+        /* return success */
+        return 1;
+    }
+
+    if ((ctx = BN_CTX_new()) == NULL)
+        return 0;
+
+    BN_CTX_start(ctx);
+    if ((q = BN_CTX_get(ctx)) == NULL)
+        goto err;
+
+    /* set q = 2**m for binary fields; q = p otherwise */
+    if (group->meth->field_type == NID_X9_62_characteristic_two_field) {
+        BN_zero(q);
+        if (!BN_set_bit(q, BN_num_bits(group->field) - 1))
+            goto err;
+    } else {
+        if (!BN_copy(q, group->field))
+            goto err;
+    }
+
+    /* compute h = \lfloor (q + 1)/n \rceil = \lfloor (q + 1 + n/2)/n \rfloor */
+    if (!BN_rshift1(group->cofactor, group->order) /* n/2 */
+        || !BN_add(group->cofactor, group->cofactor, q) /* q + n/2 */
+        /* q + 1 + n/2 */
+        || !BN_add(group->cofactor, group->cofactor, BN_value_one())
+        /* (q + 1 + n/2)/n */
+        || !BN_div(group->cofactor, NULL, group->cofactor, group->order, ctx))
+        goto err;
+    ret = 1;
+ err:
+    BN_CTX_end(ctx);
+    BN_CTX_free(ctx);
+    return ret;
+}
+
 int EC_GROUP_set_generator(EC_GROUP *group, const EC_POINT *generator,
                            const BIGNUM *order, const BIGNUM *cofactor)
 {
@@ -265,6 +326,34 @@ int EC_GROUP_set_generator(EC_GROUP *group, const EC_POINT *generator,
         return 0;
     }
 
+    /* require group->field >= 1 */
+    if (group->field == NULL || BN_is_zero(group->field)
+        || BN_is_negative(group->field)) {
+        ECerr(EC_F_EC_GROUP_SET_GENERATOR, EC_R_INVALID_FIELD);
+        return 0;
+    }
+
+    /*-
+     * - require order >= 1
+     * - enforce upper bound due to Hasse thm: order can be no more than one bit
+     *   longer than field cardinality
+     */
+    if (order == NULL || BN_is_zero(order) || BN_is_negative(order)
+        || BN_num_bits(order) > BN_num_bits(group->field) + 1) {
+        ECerr(EC_F_EC_GROUP_SET_GENERATOR, EC_R_INVALID_GROUP_ORDER);
+        return 0;
+    }
+
+    /*-
+     * Unfortunately the cofactor is an optional field in many standards.
+     * Internally, the lib uses 0 cofactor as a marker for "unknown cofactor".
+     * So accept cofactor == NULL or cofactor >= 0.
+     */
+    if (cofactor != NULL && BN_is_negative(cofactor)) {
+        ECerr(EC_F_EC_GROUP_SET_GENERATOR, EC_R_UNKNOWN_COFACTOR);
+        return 0;
+    }
+
     if (group->generator == NULL) {
         group->generator = EC_POINT_new(group);
         if (group->generator == NULL)
@@ -273,17 +362,17 @@ int EC_GROUP_set_generator(EC_GROUP *group, const EC_POINT *generator,
     if (!EC_POINT_copy(group->generator, generator))
         return 0;
 
-    if (order != NULL) {
-        if (!BN_copy(group->order, order))
-            return 0;
-    } else
-        BN_zero(group->order);
+    if (!BN_copy(group->order, order))
+        return 0;
 
-    if (cofactor != NULL) {
+    /* Either take the provided positive cofactor, or try to compute it */
+    if (cofactor != NULL && !BN_is_zero(cofactor)) {
         if (!BN_copy(group->cofactor, cofactor))
             return 0;
-    } else
+    } else if (!ec_guess_cofactor(group)) {
         BN_zero(group->cofactor);
+        return 0;
+    }
 
     /*
      * Some groups have an order with
diff --git a/include/openssl/ec.h b/include/openssl/ec.h
index bea6b8c372..c4aeaed5c1 100644
--- a/include/openssl/ec.h
+++ b/include/openssl/ec.h
@@ -1568,6 +1568,7 @@ int ERR_load_EC_strings(void);
 # define EC_R_SLOT_FULL                                   108
 # define EC_R_UNDEFINED_GENERATOR                         113
 # define EC_R_UNDEFINED_ORDER                             128
+# define EC_R_UNKNOWN_COFACTOR                            164
 # define EC_R_UNKNOWN_GROUP                               129
 # define EC_R_UNKNOWN_ORDER                               114
 # define EC_R_UNSUPPORTED_FIELD                           131
diff --git a/test/recipes/30-test_evp_data/evppkey.txt b/test/recipes/30-test_evp_data/evppkey.txt
index e0d8b4ff10..061ecb22ed 100644
--- a/test/recipes/30-test_evp_data/evppkey.txt
+++ b/test/recipes/30-test_evp_data/evppkey.txt
@@ -16147,3 +16147,53 @@ Result = KEYPAIR_MISMATCH
 PrivPubKeyPair = DSA-1024-BIS:DSA-1024-PUBLIC
 Result = KEYPAIR_MISMATCH
 
+# Title=explicit parameters with no cofactor test
+
+PrivateKey=P256_explicit
+-----BEGIN PRIVATE KEY-----
+MIIBMAIBADCCAQAGByqGSM49AgEwgfQCAQEwLAYHKoZIzj0BAQIhAP////8AAAABAAAAAAAAAAAA
+AAAA////////////////MFsEIP////8AAAABAAAAAAAAAAAAAAAA///////////////8BCBaxjXY
+qjqT57PrvVV2mIa8ZR0GsMxTsPY7zjw+J9JgSwMVAMSdNgiG5wSTamZ44ROdJreBn36QBEEEaxfR
+8uEsQkf4vOblY6RA8ncDfYEt6zOg9KE5RdiYwpZP40Li/hp/m47n60p8D54WK84zV2sxXs7LtkBo
+N79R9QIhAP////8AAAAA//////////+85vqtpxeehPO5ysL8YyVRBCcwJQIBAQQgya+p2EW6dRZr
+XCFXZ7HWk05Qw9s26JsSe4piKxIPZyE=
+-----END PRIVATE KEY-----
+
+PublicKey=P256_explicit_PUB
+-----BEGIN PUBLIC KEY-----
+MIIBSDCCAQAGByqGSM49AgEwgfQCAQEwLAYHKoZIzj0BAQIhAP////8AAAABAAAAAAAAAAAAAAAA
+////////////////MFsEIP////8AAAABAAAAAAAAAAAAAAAA///////////////8BCBaxjXYqjqT
+57PrvVV2mIa8ZR0GsMxTsPY7zjw+J9JgSwMVAMSdNgiG5wSTamZ44ROdJreBn36QBEEEaxfR8uEs
+Qkf4vOblY6RA8ncDfYEt6zOg9KE5RdiYwpZP40Li/hp/m47n60p8D54WK84zV2sxXs7LtkBoN79R
+9QIhAP////8AAAAA//////////+85vqtpxeehPO5ysL8YyVRA0IABGD+1LolWp0xyWHrdMY1bWjA
+SbiSO2H6bOZpYi5g8p+2eQP+EAi4vJmkGunpVii8ZPLxsgwtfp9Rd6PClNRGIpk=
+-----END PUBLIC KEY-----
+
+PrivPubKeyPair=P256_explicit:P256_explicit_PUB
+
+PrivateKey=P384_explicit
+-----BEGIN PRIVATE KEY-----
+MIIBoQIBADCCAWEGByqGSM49AgEwggFUAgEBMDwGByqGSM49AQECMQD/////////////////////
+/////////////////////v////8AAAAAAAAAAP////8wewQw////////////////////////////
+//////////////7/////AAAAAAAAAAD////8BDCzMS+n4j7n5JiOBWvj+C0ZGB2cbv6BQRIDFAiP
+UBOHWsZWOY2KLtGdKoXI7dPsKu8DFQCjNZJqoxmieh0AiWpnc6SCes2scwRhBKqHyiK+iwU3jrHH
+HvMgrXRuHTtii6ebmFn3QeCCVCo4VQLyXb9VKWw6VF44cnYKtzYX3kqWJixvXZ6Yv5KS3Cn49B29
+KJoUfOnaMRO18LjACmCxzh1+gZ16Qx18kOoOXwIxAP///////////////////////////////8dj
+TYH0Ny3fWBoNskiwp3rs7BlqzMUpcwQ3MDUCAQEEMGudPa0uG4wcBbGYdbZln03iPDtme/KXupqk
+d0B4cTfYltVyTkxwqCX4csnqYNLt9Q==
+-----END PRIVATE KEY-----
+
+PublicKey=P384_explicit_PUB
+-----BEGIN PUBLIC KEY-----
+MIIByTCCAWEGByqGSM49AgEwggFUAgEBMDwGByqGSM49AQECMQD/////////////////////////
+/////////////////v////8AAAAAAAAAAP////8wewQw////////////////////////////////
+//////////7/////AAAAAAAAAAD////8BDCzMS+n4j7n5JiOBWvj+C0ZGB2cbv6BQRIDFAiPUBOH
+WsZWOY2KLtGdKoXI7dPsKu8DFQCjNZJqoxmieh0AiWpnc6SCes2scwRhBKqHyiK+iwU3jrHHHvMg
+rXRuHTtii6ebmFn3QeCCVCo4VQLyXb9VKWw6VF44cnYKtzYX3kqWJixvXZ6Yv5KS3Cn49B29KJoU
+fOnaMRO18LjACmCxzh1+gZ16Qx18kOoOXwIxAP///////////////////////////////8djTYH0
+Ny3fWBoNskiwp3rs7BlqzMUpcwNiAATsOk5BW04ZpFaGGAKfQn+l2pqLxK6S4C4GquUoazAMZN74
+8OqQVYZgZKJUUVSAvBOAFdm3LX1XJE6o75rAxiGJZwilk2f537n1TKhLPxydsSiLIxw64NT+c0T9
+JTMmRyA=
+-----END PUBLIC KEY-----
+
+PrivPubKeyPair=P384_explicit:P384_explicit_PUB


More information about the openssl-commits mailing list