• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1Index: net/third_party/nss/ssl/ssl3con.c
2===================================================================
3--- net/third_party/nss/ssl/ssl3con.c	(revision 220594)
4+++ net/third_party/nss/ssl/ssl3con.c	(working copy)
5@@ -3933,6 +3933,20 @@
6 		ssl_MapLowLevelError(SSL_ERROR_DIGEST_FAILURE);
7 		return SECFailure;
8 	    }
9+
10+	    /* A backup SHA-1 hash for a potential client auth signature. */
11+	    if (!ss->sec.isServer) {
12+		ss->ssl3.hs.md5 = PK11_CreateDigestContext(SEC_OID_SHA1);
13+		if (ss->ssl3.hs.md5 == NULL) {
14+		    ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE);
15+		    return SECFailure;
16+		}
17+
18+		if (PK11_DigestBegin(ss->ssl3.hs.md5) != SECSuccess) {
19+		    ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE);
20+		    return SECFailure;
21+		}
22+	    }
23 	} else {
24 	    /* Both ss->ssl3.hs.md5 and ss->ssl3.hs.sha should be NULL or
25 	     * created successfully. */
26@@ -4043,6 +4057,13 @@
27 	    ssl_MapLowLevelError(SSL_ERROR_DIGEST_FAILURE);
28 	    return rv;
29 	}
30+	if (ss->ssl3.hs.md5) {
31+	    rv = PK11_DigestOp(ss->ssl3.hs.md5, b, l);
32+	    if (rv != SECSuccess) {
33+		ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE);
34+		return rv;
35+	    }
36+	}
37     } else {
38 	rv = PK11_DigestOp(ss->ssl3.hs.md5, b, l);
39 	if (rv != SECSuccess) {
40@@ -4791,6 +4812,30 @@
41     return rv;
42 }
43
44+static SECStatus
45+ssl3_ComputeBackupHandshakeHashes(sslSocket * ss,
46+				  SSL3Hashes * hashes) /* output goes here. */
47+{
48+    SECStatus rv = SECSuccess;
49+
50+    PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) );
51+    PORT_Assert( ss->ssl3.hs.hashType == handshake_hash_single );
52+
53+    rv = PK11_DigestFinal(ss->ssl3.hs.md5, hashes->u.raw, &hashes->len,
54+			  sizeof(hashes->u.raw));
55+    if (rv != SECSuccess) {
56+	ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE);
57+	rv = SECFailure;
58+	goto loser;
59+    }
60+    hashes->hashAlg = SEC_OID_SHA1;
61+
62+loser:
63+    PK11_DestroyContext(ss->ssl3.hs.md5, PR_TRUE);
64+    ss->ssl3.hs.md5 = NULL;
65+    return rv;
66+}
67+
68 /*
69  * SSL 2 based implementations pass in the initial outbound buffer
70  * so that the handshake hash can contain the included information.
71@@ -6044,7 +6089,17 @@
72 		SSL_GETPID(), ss->fd));
73
74     ssl_GetSpecReadLock(ss);
75-    rv = ssl3_ComputeHandshakeHashes(ss, ss->ssl3.pwSpec, &hashes, 0);
76+    /* In TLS 1.2, ssl3_ComputeHandshakeHashes always uses the handshake hash
77+     * function (SHA-256). If the server or the client does not support SHA-256
78+     * as a signature hash, we can either maintain a backup SHA-1 handshake
79+     * hash or buffer all handshake messages.
80+     */
81+    if (ss->ssl3.hs.hashType == handshake_hash_single && ss->ssl3.hs.md5) {
82+	rv = ssl3_ComputeBackupHandshakeHashes(ss, &hashes);
83+	PORT_Assert(ss->ssl3.hs.md5 == NULL);
84+    } else {
85+	rv = ssl3_ComputeHandshakeHashes(ss, ss->ssl3.pwSpec, &hashes, 0);
86+    }
87     ssl_ReleaseSpecReadLock(ss);
88     if (rv != SECSuccess) {
89 	goto done;	/* err code was set by ssl3_ComputeHandshakeHashes */
90@@ -6098,11 +6153,6 @@
91 	if (rv != SECSuccess) {
92 	    goto done;
93 	}
94-	/* We always sign using the handshake hash function. It's possible that
95-	 * a server could support SHA-256 as the handshake hash but not as a
96-	 * signature hash. In that case we wouldn't be able to do client
97-	 * certificates with it. The alternative is to buffer all handshake
98-	 * messages. */
99 	sigAndHash.hashAlg = hashes.hashAlg;
100
101 	rv = ssl3_AppendSignatureAndHashAlgorithm(ss, &sigAndHash);
102@@ -6802,6 +6852,70 @@
103 }
104
105
106+/*
107+ * Returns true if the client authentication key is an RSA or DSA key that
108+ * may be able to sign only SHA-1 hashes.
109+ */
110+static PRBool
111+ssl3_ClientKeyPrefersSHA1(sslSocket *ss)
112+{
113+    SECKEYPublicKey *pubk;
114+    PRBool prefer_sha1 = PR_FALSE;
115+
116+#if defined(NSS_PLATFORM_CLIENT_AUTH) && defined(_WIN32)
117+    /* If the key is in CAPI, assume conservatively that the CAPI service
118+     * provider may be unable to sign SHA-256 hashes.
119+     */
120+    if (ss->ssl3.platformClientKey->dwKeySpec != CERT_NCRYPT_KEY_SPEC) {
121+	/* CAPI only supports RSA and DSA signatures, so we don't need to
122+	 * check the key type. */
123+	return PR_TRUE;
124+    }
125+#endif  /* NSS_PLATFORM_CLIENT_AUTH && _WIN32 */
126+
127+    /* If the key is a 1024-bit RSA or DSA key, assume conservatively that
128+     * it may be unable to sign SHA-256 hashes. This is the case for older
129+     * Estonian ID cards that have 1024-bit RSA keys. In FIPS 186-2 and
130+     * older, DSA key size is at most 1024 bits and the hash function must
131+     * be SHA-1.
132+     */
133+    pubk = CERT_ExtractPublicKey(ss->ssl3.clientCertificate);
134+    if (pubk == NULL) {
135+	return PR_FALSE;
136+    }
137+    if (pubk->keyType == rsaKey || pubk->keyType == dsaKey) {
138+	prefer_sha1 = SECKEY_PublicKeyStrength(pubk) <= 128;
139+    }
140+    SECKEY_DestroyPublicKey(pubk);
141+    return prefer_sha1;
142+}
143+
144+/* Destroys the backup handshake hash context if we don't need it. */
145+static void
146+ssl3_DestroyBackupHandshakeHashIfNotNeeded(sslSocket *ss,
147+					   const SECItem *algorithms)
148+{
149+    PRBool need_backup_hash = PR_FALSE;
150+    unsigned int i;
151+
152+    PORT_Assert(ss->ssl3.hs.md5);
153+    if (ssl3_ClientKeyPrefersSHA1(ss)) {
154+	/* Use SHA-1 if the server supports it. */
155+	for (i = 0; i < algorithms->len; i += 2) {
156+	    if (algorithms->data[i] == tls_hash_sha1 &&
157+		(algorithms->data[i+1] == tls_sig_rsa ||
158+		 algorithms->data[i+1] == tls_sig_dsa)) {
159+		need_backup_hash = PR_TRUE;
160+		break;
161+	    }
162+	}
163+    }
164+    if (!need_backup_hash) {
165+	PK11_DestroyContext(ss->ssl3.hs.md5, PR_TRUE);
166+	ss->ssl3.hs.md5 = NULL;
167+    }
168+}
169+
170 typedef struct dnameNode {
171     struct dnameNode *next;
172     SECItem           name;
173@@ -6994,6 +7108,9 @@
174 		}
175 		goto send_no_certificate;
176 	    }
177+	    if (isTLS12) {
178+		ssl3_DestroyBackupHandshakeHashIfNotNeeded(ss, &algorithms);
179+	    }
180 	    break;  /* not an error */
181 	}
182 #endif   /* NSS_PLATFORM_CLIENT_AUTH */
183@@ -7029,6 +7146,9 @@
184 	    }
185 	    goto send_no_certificate;
186 	}
187+	if (isTLS12) {
188+	    ssl3_DestroyBackupHandshakeHashIfNotNeeded(ss, &algorithms);
189+	}
190 	break;	/* not an error */
191
192     case SECFailure:
193@@ -7227,6 +7347,13 @@
194 		     (ss->ssl3.platformClientKey ||
195 		     ss->ssl3.clientPrivateKey != NULL);
196
197+    if (!sendClientCert &&
198+	ss->ssl3.hs.hashType == handshake_hash_single && ss->ssl3.hs.md5) {
199+	/* Don't need the backup handshake hash. */
200+	PK11_DestroyContext(ss->ssl3.hs.md5, PR_TRUE);
201+	ss->ssl3.hs.md5 = NULL;
202+    }
203+
204     /* We must wait for the server's certificate to be authenticated before
205      * sending the client certificate in order to disclosing the client
206      * certificate to an attacker that does not have a valid cert for the
207Index: net/third_party/nss/ssl/sslimpl.h
208===================================================================
209--- net/third_party/nss/ssl/sslimpl.h	(revision 220594)
210+++ net/third_party/nss/ssl/sslimpl.h	(working copy)
211@@ -838,6 +838,9 @@
212      * SSL 3.0 - TLS 1.1 use both |md5| and |sha|. |md5| is used for MD5 and
213      * |sha| for SHA-1.
214      * TLS 1.2 and later use only |sha|, for SHA-256. */
215+    /* NOTE: On the client side, TLS 1.2 and later use |md5| as a backup
216+     * handshake hash for generating client auth signatures. Confusingly, the
217+     * backup hash function is SHA-1. */
218     PK11Context *         md5;
219     PK11Context *         sha;
220
221