axs         15/05/27 03:59:16

  Added:                nss-3.19-raise_minimum_keysize_to_1024.patch
  Log:
  revbump, backported patch from nss-3.19.1 beta to prevent logjam vulnerability
  
  (Portage version: 2.2.18/cvs/Linux x86_64, signed Manifest commit with key 
2B6559ED)

Revision  Changes    Path
1.1                  
dev-libs/nss/files/nss-3.19-raise_minimum_keysize_to_1024.patch

file : 
http://sources.gentoo.org/viewvc.cgi/gentoo-x86/dev-libs/nss/files/nss-3.19-raise_minimum_keysize_to_1024.patch?rev=1.1&view=markup
plain: 
http://sources.gentoo.org/viewvc.cgi/gentoo-x86/dev-libs/nss/files/nss-3.19-raise_minimum_keysize_to_1024.patch?rev=1.1&content-type=text/plain

Index: nss-3.19-raise_minimum_keysize_to_1024.patch
===================================================================
# HG changeset patch
# User Martin Thomson <[email protected]>
# Date 1428438189 25200
#      Tue Apr 07 13:23:09 2015 -0700
# Node ID ae72d76f8d2472505b499c498191c3ce441b6a17
# Parent  17b065430727befe3251d63583b350d7dc120564
Bug 1138554 - Raising minimum key size on DH and RSA to 1023, r=wtc

diff -r 17b065430727 -r ae72d76f8d24 lib/cryptohi/keyhi.h
--- a/lib/cryptohi/keyhi.h      Wed May 20 16:28:19 2015 -0700
+++ b/lib/cryptohi/keyhi.h      Tue Apr 07 13:23:09 2015 -0700
@@ -37,6 +37,11 @@
 extern SECStatus
 SECKEY_UpdateCertPQG(CERTCertificate * subjectCert);
 
+/*
+** Return the number of bits in the provided big integer.  This assumes that 
the
+** SECItem contains a big-endian number and counts from the first non-zero bit.
+*/
+extern unsigned SECKEY_BigIntegerBitLength(const SECItem *number);
 
 /*
 ** Return the strength of the public key in bytes
diff -r 17b065430727 -r ae72d76f8d24 lib/cryptohi/seckey.c
--- a/lib/cryptohi/seckey.c     Wed May 20 16:28:19 2015 -0700
+++ b/lib/cryptohi/seckey.c     Tue Apr 07 13:23:09 2015 -0700
@@ -178,8 +178,8 @@
     PK11SlotInfo *slot;
 
     if (!param || !param->base.data || !param->prime.data ||
-        param->prime.len < 512/8 || param->base.len == 0 || 
-        param->base.len > param->prime.len + 1 || 
+        SECKEY_BigIntegerBitLength(&param->prime) < DH_MIN_P_BITS ||
+        param->base.len == 0 || param->base.len > param->prime.len + 1 ||
        (param->base.len == 1 && param->base.data[0] == 0)) {
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
        return NULL;
@@ -941,61 +941,76 @@
     }
 }
 
+/* The number of bits in the number from the first non-zero bit onward. */
+unsigned
+SECKEY_BigIntegerBitLength(const SECItem *number)
+{
+    const unsigned char *p;
+    unsigned octets;
+    unsigned bits;
+
+    if (!number || !number->data) {
+        PORT_SetError(SEC_ERROR_INVALID_KEY);
+        return 0;
+    }
+
+    p = number->data;
+    octets = number->len;
+    while (octets > 0 && !*p) {
+        ++p;
+        --octets;
+    }
+    if (octets == 0) {
+        return 0;
+    }
+    /* bits = 7..1 because we know at least one bit is set already */
+    /* Note: This could do a binary search, but this is faster for keys if we
+     * assume that good keys will have the MSB set. */
+    for (bits = 7; bits > 0; --bits) {
+        if (*p & (1 << bits)) {
+            break;
+        }
+    }
+    return octets * 8 + bits - 7;
+}
+
 /* returns key strength in bytes (not bits) */
 unsigned
 SECKEY_PublicKeyStrength(const SECKEYPublicKey *pubk)
 {
-    unsigned char b0;
-    unsigned size;
-
-    /* interpret modulus length as key strength */
-    if (!pubk)
-       goto loser;
-    switch (pubk->keyType) {
-    case rsaKey:
-       if (!pubk->u.rsa.modulus.data) break;
-       b0 = pubk->u.rsa.modulus.data[0];
-       return b0 ? pubk->u.rsa.modulus.len : pubk->u.rsa.modulus.len - 1;
-    case dsaKey:
-       if (!pubk->u.dsa.publicValue.data) break;
-       b0 = pubk->u.dsa.publicValue.data[0];
-       return b0 ? pubk->u.dsa.publicValue.len :
-           pubk->u.dsa.publicValue.len - 1;
-    case dhKey:
-       if (!pubk->u.dh.publicValue.data) break;
-       b0 = pubk->u.dh.publicValue.data[0];
-       return b0 ? pubk->u.dh.publicValue.len :
-           pubk->u.dh.publicValue.len - 1;
-    case ecKey:
-       /* Get the key size in bits and adjust */
-       size =  SECKEY_ECParamsToKeySize(&pubk->u.ec.DEREncodedParams);
-       return (size + 7)/8;
-    default:
-       break;
-    }
-loser:
-    PORT_SetError(SEC_ERROR_INVALID_KEY);
-    return 0;
+    return (SECKEY_PublicKeyStrengthInBits(pubk) + 7) / 8;
 }
 
 /* returns key strength in bits */
 unsigned
 SECKEY_PublicKeyStrengthInBits(const SECKEYPublicKey *pubk)
 {
-    unsigned size;
+    unsigned bitSize = 0;
+
+    if (!pubk) {
+        PORT_SetError(SEC_ERROR_INVALID_KEY);
+        return 0;
+    }
+
+    /* interpret modulus length as key strength */
     switch (pubk->keyType) {
     case rsaKey:
+        bitSize = SECKEY_BigIntegerBitLength(&pubk->u.rsa.modulus);
+        break;
     case dsaKey:
+        bitSize = SECKEY_BigIntegerBitLength(&pubk->u.dsa.publicValue);
+        break;
     case dhKey:
-       return SECKEY_PublicKeyStrength(pubk) * 8; /* 1 byte = 8 bits */
+        bitSize = SECKEY_BigIntegerBitLength(&pubk->u.dh.publicValue);
+        break;
     case ecKey:
-       size = SECKEY_ECParamsToKeySize(&pubk->u.ec.DEREncodedParams);
-       return size;
+        bitSize = SECKEY_ECParamsToKeySize(&pubk->u.ec.DEREncodedParams);
+        break;
     default:
-       break;
+        PORT_SetError(SEC_ERROR_INVALID_KEY);
+        break;
     }
-    PORT_SetError(SEC_ERROR_INVALID_KEY);
-    return 0;
+    return bitSize;
 }
 
 /* returns signature length in bytes (not bits) */
diff -r 17b065430727 -r ae72d76f8d24 lib/freebl/blapit.h
--- a/lib/freebl/blapit.h       Wed May 20 16:28:19 2015 -0700
+++ b/lib/freebl/blapit.h       Tue Apr 07 13:23:09 2015 -0700
@@ -138,10 +138,10 @@
  * These values come from the initial key size limits from the PKCS #11
  * module. They may be arbitrarily adjusted to any value freebl supports.
  */
-#define RSA_MIN_MODULUS_BITS   128
+#define RSA_MIN_MODULUS_BITS   512
 #define RSA_MAX_MODULUS_BITS 16384
 #define RSA_MAX_EXPONENT_BITS   64
-#define DH_MIN_P_BITS         128
+#define DH_MIN_P_BITS        1023
 #define DH_MAX_P_BITS        16384
 
 /*
@@ -181,7 +181,7 @@
 
 #define DSA1_Q_BITS      160
 #define DSA_MAX_P_BITS 3072
-#define DSA_MIN_P_BITS  512
+#define DSA_MIN_P_BITS  1023
 #define DSA_MAX_Q_BITS   256
 #define DSA_MIN_Q_BITS   160
 
diff -r 17b065430727 -r ae72d76f8d24 lib/nss/nss.def
--- a/lib/nss/nss.def   Wed May 20 16:28:19 2015 -0700
+++ b/lib/nss/nss.def   Tue Apr 07 13:23:09 2015 -0700
@@ -1076,3 +1076,9 @@
 ;+    local:
 ;+       *;
 ;+};
+;+NSS_3.19.1 {         # NSS 3.19.1 release
+;+    global:
+SECKEY_BigIntegerBitLength;
+;+    local:
+;+       *;
+;+};
diff -r 17b065430727 -r ae72d76f8d24 lib/ssl/SSLerrs.h
--- a/lib/ssl/SSLerrs.h Wed May 20 16:28:19 2015 -0700
+++ b/lib/ssl/SSLerrs.h Tue Apr 07 13:23:09 2015 -0700
@@ -422,3 +422,6 @@
 ER3(SSL_ERROR_INAPPROPRIATE_FALLBACK_ALERT, (SSL_ERROR_BASE + 131),
 "The server rejected the handshake because the client downgraded to a lower "
 "TLS version than the server supports.")
+
+ER3(SSL_ERROR_WEAK_SERVER_CERT_KEY, (SSL_ERROR_BASE + 132),
+"The server certificate included a public key that was too weak.")
diff -r 17b065430727 -r ae72d76f8d24 lib/ssl/ssl3con.c
--- a/lib/ssl/ssl3con.c Wed May 20 16:28:19 2015 -0700
+++ b/lib/ssl/ssl3con.c Tue Apr 07 13:23:09 2015 -0700
@@ -6599,29 +6599,6 @@
     return SECFailure;
 }
 
-/* ssl3_BigIntGreaterThanOne returns true iff |mpint|, taken as an unsigned,
- * big-endian integer is > 1 */
-static PRBool
-ssl3_BigIntGreaterThanOne(const SECItem* mpint) {
-    unsigned char firstNonZeroByte = 0;
-    unsigned int i;
-
-    for (i = 0; i < mpint->len; i++) {
-       if (mpint->data[i]) {
-           firstNonZeroByte = mpint->data[i];
-           break;
-       }
-    }
-
-    if (firstNonZeroByte == 0)
-       return PR_FALSE;
-    if (firstNonZeroByte > 1)
-       return PR_TRUE;
-
-    /* firstNonZeroByte == 1, therefore mpint > 1 iff the first non-zero byte
-     * is followed by another byte. */
-    return (i < mpint->len - 1);
-}
 
 /* Called from ssl3_HandleHandshakeMessage() when it has deciphered a complete
  * ssl3 ServerKeyExchange message.
@@ -6666,6 +6643,12 @@
        if (rv != SECSuccess) {
            goto loser;         /* malformed. */
        }
+        /* This exchange method is only used by export cipher suites.
+         * Those are broken and so this code will eventually be removed. */
+        if (SECKEY_BigIntegerBitLength(&modulus) < 512) {
+            desc = isTLS ? insufficient_security : illegal_parameter;
+            goto alert_loser;
+        }
        rv = ssl3_ConsumeHandshakeVariable(ss, &exponent, 2, &b, &length);
        if (rv != SECSuccess) {
            goto loser;         /* malformed. */
@@ -6751,12 +6734,16 @@
        SECItem          dh_p      = {siBuffer, NULL, 0};
        SECItem          dh_g      = {siBuffer, NULL, 0};
        SECItem          dh_Ys     = {siBuffer, NULL, 0};
+        unsigned dh_p_bits;
+        unsigned dh_g_bits;
+        unsigned dh_Ys_bits;
 
        rv = ssl3_ConsumeHandshakeVariable(ss, &dh_p, 2, &b, &length);
        if (rv != SECSuccess) {
            goto loser;         /* malformed. */
        }
-       if (dh_p.len < 512/8) {
+        dh_p_bits = SECKEY_BigIntegerBitLength(&dh_p);
+        if (dh_p_bits < DH_MIN_P_BITS) {
            errCode = SSL_ERROR_WEAK_SERVER_EPHEMERAL_DH_KEY;
            goto alert_loser;
        }
@@ -6764,13 +6751,16 @@
        if (rv != SECSuccess) {
            goto loser;         /* malformed. */
        }
-       if (dh_g.len > dh_p.len || !ssl3_BigIntGreaterThanOne(&dh_g))
+        /* Abort if dh_g is 0, 1, or obviously too big. */
+        dh_g_bits = SECKEY_BigIntegerBitLength(&dh_g);
+        if (dh_g_bits > dh_p_bits || dh_g_bits <= 1)
            goto alert_loser;
        rv = ssl3_ConsumeHandshakeVariable(ss, &dh_Ys, 2, &b, &length);
        if (rv != SECSuccess) {
            goto loser;         /* malformed. */
        }
-       if (dh_Ys.len > dh_p.len || !ssl3_BigIntGreaterThanOne(&dh_Ys))
+        dh_Ys_bits = SECKEY_BigIntegerBitLength(&dh_Ys);
+        if (dh_Ys_bits > dh_p_bits || dh_Ys_bits <= 1)
            goto alert_loser;
        if (isTLS12) {
            rv = ssl3_ConsumeSignatureAndHashAlgorithm(ss, &b, &length,
@@ -10057,33 +10047,25 @@
        if (pubKey) {
            ss->sec.keaKeyBits = ss->sec.authKeyBits =
                SECKEY_PublicKeyStrengthInBits(pubKey);
-#ifndef NSS_DISABLE_ECC
-           if (ss->sec.keaType == kt_ecdh) {
-               /* Get authKeyBits from signing key.
-                * XXX The code below uses a quick approximation of
-                * key size based on cert->signatureWrap.signature.data
-                * (which contains the DER encoded signature). The field
-                * cert->signatureWrap.signature.len contains the
-                * length of the encoded signature in bits.
-                */
-               if (ss->ssl3.hs.kea_def->kea == kea_ecdh_ecdsa) {
-                   ss->sec.authKeyBits = 
-                       cert->signatureWrap.signature.data[3]*8;
-                   if (cert->signatureWrap.signature.data[4] == 0x00)
-                           ss->sec.authKeyBits -= 8;
-                   /* 
-                    * XXX: if cert is not signed by ecdsa we should
-                    * destroy pubKey and goto bad_cert
-                    */
-               } else if (ss->ssl3.hs.kea_def->kea == kea_ecdh_rsa) {
-                   ss->sec.authKeyBits = cert->signatureWrap.signature.len;
-                   /* 
-                    * XXX: if cert is not signed by rsa we should
-                    * destroy pubKey and goto bad_cert
-                    */
-               }
-           }
-#endif /* NSS_DISABLE_ECC */
+            KeyType pubKeyType = SECKEY_GetPublicKeyType(pubKey);
+            /* Too small: not good enough. Send a fatal alert. */
+            /* TODO: Use 1023 for RSA because a higher RSA_MIN_MODULUS_BITS
+             * breaks export cipher suites; when those are removed, increase
+             * RSA_MIN_MODULUS_BITS and use that here. */
+            /* We aren't checking EC here on the understanding that we only
+             * support curves we like, a decision that might need revisiting. 
*/
+            if (((pubKeyType == rsaKey || pubKeyType == rsaPssKey ||
+                  pubKeyType == rsaOaepKey) && ss->sec.authKeyBits < 1023) ||
+                (pubKeyType == dsaKey && ss->sec.authKeyBits < DSA_MIN_P_BITS) 
||
+                (pubKeyType == dhKey && ss->sec.authKeyBits < DH_MIN_P_BITS)) {
+                PORT_SetError(SSL_ERROR_WEAK_SERVER_CERT_KEY);
+                (void)SSL3_SendAlert(ss, alert_fatal,
+                                     ss->version >= SSL_LIBRARY_VERSION_TLS_1_0
+                                     ? insufficient_security
+                                     : illegal_parameter);
+                SECKEY_DestroyPublicKey(pubKey);
+                return SECFailure;
+            }
            SECKEY_DestroyPublicKey(pubKey); 
            pubKey = NULL;
        }
diff -r 17b065430727 -r ae72d76f8d24 lib/ssl/sslerr.h
--- a/lib/ssl/sslerr.h  Wed May 20 16:28:19 2015 -0700
+++ b/lib/ssl/sslerr.h  Tue Apr 07 13:23:09 2015 -0700
@@ -198,6 +198,8 @@
 
 SSL_ERROR_INAPPROPRIATE_FALLBACK_ALERT  = (SSL_ERROR_BASE + 131),
 
+SSL_ERROR_WEAK_SERVER_CERT_KEY          = (SSL_ERROR_BASE + 132),
+
 SSL_ERROR_END_OF_LIST   /* let the c compiler determine the value of this. */
 } SSLErrorCodes;
 #endif /* NO_SECURITY_ERROR_ENUM */




Reply via email to