Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > a2cd3dae78b2c9731ea9c4f42484efff > files > 32

nss-3.21.3-2.el5_11.src.rpm

diff -up ./lib/ssl/ssl3con.c.moz-1314604 ./lib/ssl/ssl3con.c
--- ./lib/ssl/ssl3con.c.moz-1314604	2016-11-07 21:30:40.035272554 +0100
+++ ./lib/ssl/ssl3con.c	2016-11-07 21:31:14.876273952 +0100
@@ -6196,6 +6196,7 @@ sendDHClientKeyExchange(sslSocket * ss,
 
     if (pms == NULL) {
 	ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE);
+	rv = SECFailure;
 	goto loser;
     }
 
@@ -6939,7 +6940,6 @@ ssl3_HandleServerKeyExchange(sslSocket *
 	SECItem          dh_Ys     = {siBuffer, NULL, 0};
         unsigned dh_p_bits;
         unsigned dh_g_bits;
-        unsigned dh_Ys_bits;
         PRInt32  minDH;
 
     	rv = ssl3_ConsumeHandshakeVariable(ss, &dh_p, 2, &b, &length);
@@ -6968,9 +6968,10 @@ ssl3_HandleServerKeyExchange(sslSocket *
     	if (rv != SECSuccess) {
 	    goto loser;		/* malformed. */
 	}
-        dh_Ys_bits = SECKEY_BigIntegerBitLength(&dh_Ys);
-        if (dh_Ys_bits > dh_p_bits || dh_Ys_bits <= 1)
-	    goto alert_loser;
+        if (!ssl_IsValidDHEShare(&dh_p, &dh_Ys)) {
+            errCode = SSL_ERROR_WEAK_SERVER_EPHEMERAL_DH_KEY;
+            goto alert_loser;
+        }
 	if (isTLS12) {
 	    rv = ssl3_ConsumeSignatureAndHashAlgorithm(ss, &b, &length,
 						       &sigAndHash);
@@ -9906,6 +9907,12 @@ ssl3_HandleDHClientKeyExchange(sslSocket
 	goto loser;
     }
 
+    if (!ssl_IsValidDHEShare(&srvrPubKey->u.dh.prime,
+                             &clntPubKey.u.dh.publicValue)) {
+        PORT_SetError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE);
+        return SECFailure;
+    }
+
     isTLS = (PRBool)(ss->ssl3.prSpec->version > SSL_LIBRARY_VERSION_3_0);
 
     if (isTLS) target = CKM_TLS_MASTER_KEY_DERIVE_DH;
diff -up ./lib/ssl/sslimpl.h.moz-1314604 ./lib/ssl/sslimpl.h
--- ./lib/ssl/sslimpl.h.moz-1314604	2016-11-07 21:30:40.028272553 +0100
+++ ./lib/ssl/sslimpl.h	2016-11-07 21:30:40.047272554 +0100
@@ -1647,6 +1647,7 @@ int ssl3_GatherCompleteHandshake(sslSock
 extern SECStatus ssl3_CreateRSAStepDownKeys(sslSocket *ss);
 
 extern SECStatus ssl3_SelectDHParams(sslSocket *ss);
+extern PRBool ssl_IsValidDHEShare(const SECItem *dh_p, const SECItem *dh_Ys);
 
 #ifndef NSS_DISABLE_ECC
 extern void      ssl3_FilterECCipherSuitesByServerCerts(sslSocket *ss);
diff -up ./lib/ssl/sslsock.c.moz-1314604 ./lib/ssl/sslsock.c
--- ./lib/ssl/sslsock.c.moz-1314604	2016-11-07 21:30:40.040272554 +0100
+++ ./lib/ssl/sslsock.c	2016-11-07 21:30:40.048272554 +0100
@@ -1462,6 +1462,54 @@ SSL_DHEGroupPrefSet(PRFileDesc *fd,
     return SECSuccess;
 }
 
+/* This validates dh_Ys against the group prime. */
+PRBool
+ssl_IsValidDHEShare(const SECItem *dh_p, const SECItem *dh_Ys)
+{
+    unsigned int size_p = SECKEY_BigIntegerBitLength(dh_p);
+    unsigned int size_y = SECKEY_BigIntegerBitLength(dh_Ys);
+    unsigned int commonPart;
+    int cmp;
+
+    if (dh_p->len == 0 || dh_Ys->len == 0) {
+        return PR_FALSE;
+    }
+
+    /* Check that the prime is at least odd. */
+    if ((dh_p->data[dh_p->len - 1] & 0x01) == 0) {
+        return PR_FALSE;
+    }
+    /* dh_Ys can't be 1, or bigger than dh_p. */
+    if (size_y <= 1 || size_y > size_p) {
+        return PR_FALSE;
+    }
+    /* If dh_Ys is shorter, then it's definitely smaller than p-1. */
+    if (size_y < size_p) {
+        return PR_TRUE;
+    }
+
+    /* Compare the common part of each, minus the final octet. */
+    commonPart = (size_p + 7) / 8;
+    PORT_Assert(commonPart <= dh_Ys->len);
+    PORT_Assert(commonPart <= dh_p->len);
+    cmp = PORT_Memcmp(dh_Ys->data + dh_Ys->len - commonPart,
+                      dh_p->data + dh_p->len - commonPart, commonPart - 1);
+    if (cmp < 0) {
+        return PR_TRUE;
+    }
+    if (cmp > 0) {
+        return PR_FALSE;
+    }
+
+    /* The last octet of the prime is the only thing that is different and that
+     * has to be two greater than the share, otherwise we have Ys == p - 1,
+     * and that means small subgroups. */
+    if (dh_Ys->data[dh_Ys->len - 1] >= (dh_p->data[dh_p->len - 1] - 1)) {
+        return PR_FALSE;
+    }
+
+    return PR_TRUE;
+}
 
 PRCallOnceType gWeakDHParamsRegisterOnce;
 int gWeakDHParamsRegisterError;