| Index: net/third_party/nss/patches/tls12backuphash.patch
|
| ===================================================================
|
| --- net/third_party/nss/patches/tls12backuphash.patch (revision 0)
|
| +++ net/third_party/nss/patches/tls12backuphash.patch (revision 0)
|
| @@ -0,0 +1,163 @@
|
| +Index: net/third_party/nss/ssl/ssl3con.c
|
| +===================================================================
|
| +--- net/third_party/nss/ssl/ssl3con.c (revision 219342)
|
| ++++ net/third_party/nss/ssl/ssl3con.c (working copy)
|
| +@@ -3933,6 +3933,22 @@
|
| + ssl_MapLowLevelError(SSL_ERROR_DIGEST_FAILURE);
|
| + return SECFailure;
|
| + }
|
| ++
|
| ++#ifdef _WIN32
|
| ++ /* A backup SHA-1 hash for a potential client auth signature. */
|
| ++ if (!ss->sec.isServer) {
|
| ++ ss->ssl3.hs.md5 = PK11_CreateDigestContext(SEC_OID_SHA1);
|
| ++ if (ss->ssl3.hs.md5 == NULL) {
|
| ++ ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE);
|
| ++ return SECFailure;
|
| ++ }
|
| ++
|
| ++ if (PK11_DigestBegin(ss->ssl3.hs.md5) != SECSuccess) {
|
| ++ ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE);
|
| ++ return SECFailure;
|
| ++ }
|
| ++ }
|
| ++#endif
|
| + } else {
|
| + /* Both ss->ssl3.hs.md5 and ss->ssl3.hs.sha should be NULL or
|
| + * created successfully. */
|
| +@@ -4043,6 +4059,13 @@
|
| + ssl_MapLowLevelError(SSL_ERROR_DIGEST_FAILURE);
|
| + return rv;
|
| + }
|
| ++ if (ss->ssl3.hs.md5) {
|
| ++ rv = PK11_DigestOp(ss->ssl3.hs.md5, b, l);
|
| ++ if (rv != SECSuccess) {
|
| ++ ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE);
|
| ++ return rv;
|
| ++ }
|
| ++ }
|
| + } else {
|
| + rv = PK11_DigestOp(ss->ssl3.hs.md5, b, l);
|
| + if (rv != SECSuccess) {
|
| +@@ -4791,6 +4814,30 @@
|
| + return rv;
|
| + }
|
| +
|
| ++static SECStatus
|
| ++ssl3_ComputeBackupHandshakeHashes(sslSocket * ss,
|
| ++ SSL3Hashes * hashes) /* output goes here. */
|
| ++{
|
| ++ SECStatus rv = SECSuccess;
|
| ++
|
| ++ PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) );
|
| ++ PORT_Assert( ss->ssl3.hs.hashType == handshake_hash_single );
|
| ++
|
| ++ rv = PK11_DigestFinal(ss->ssl3.hs.md5, hashes->u.raw, &hashes->len,
|
| ++ sizeof(hashes->u.raw));
|
| ++ if (rv != SECSuccess) {
|
| ++ ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE);
|
| ++ rv = SECFailure;
|
| ++ goto loser;
|
| ++ }
|
| ++ hashes->hashAlg = SEC_OID_SHA1;
|
| ++
|
| ++loser:
|
| ++ PK11_DestroyContext(ss->ssl3.hs.md5, PR_TRUE);
|
| ++ ss->ssl3.hs.md5 = NULL;
|
| ++ return rv;
|
| ++}
|
| ++
|
| + /*
|
| + * SSL 2 based implementations pass in the initial outbound buffer
|
| + * so that the handshake hash can contain the included information.
|
| +@@ -6044,7 +6091,17 @@
|
| + SSL_GETPID(), ss->fd));
|
| +
|
| + ssl_GetSpecReadLock(ss);
|
| +- rv = ssl3_ComputeHandshakeHashes(ss, ss->ssl3.pwSpec, &hashes, 0);
|
| ++ /* In TLS 1.2, ssl3_ComputeHandshakeHashes always uses the handshake hash
|
| ++ * function (SHA-256). If the server or the client does not support SHA-256
|
| ++ * as a signature hash, we can either maintain a backup SHA-1 handshake
|
| ++ * hash or buffer all handshake messages.
|
| ++ */
|
| ++ if (ss->ssl3.hs.hashType == handshake_hash_single && ss->ssl3.hs.md5) {
|
| ++ rv = ssl3_ComputeBackupHandshakeHashes(ss, &hashes);
|
| ++ PORT_Assert(ss->ssl3.hs.md5 == NULL);
|
| ++ } else {
|
| ++ rv = ssl3_ComputeHandshakeHashes(ss, ss->ssl3.pwSpec, &hashes, 0);
|
| ++ }
|
| + ssl_ReleaseSpecReadLock(ss);
|
| + if (rv != SECSuccess) {
|
| + goto done; /* err code was set by ssl3_ComputeHandshakeHashes */
|
| +@@ -6098,11 +6155,6 @@
|
| + if (rv != SECSuccess) {
|
| + goto done;
|
| + }
|
| +- /* We always sign using the handshake hash function. It's possible that
|
| +- * a server could support SHA-256 as the handshake hash but not as a
|
| +- * signature hash. In that case we wouldn't be able to do client
|
| +- * certificates with it. The alternative is to buffer all handshake
|
| +- * messages. */
|
| + sigAndHash.hashAlg = hashes.hashAlg;
|
| +
|
| + rv = ssl3_AppendSignatureAndHashAlgorithm(ss, &sigAndHash);
|
| +@@ -6994,6 +7046,31 @@
|
| + }
|
| + goto send_no_certificate;
|
| + }
|
| ++
|
| ++ if (isTLS12 && ss->ssl3.hs.md5) {
|
| ++ PRBool need_backup_hash = PR_FALSE;
|
| ++#ifdef _WIN32
|
| ++ /* If the key is in CAPI, assume conservatively that the CAPI
|
| ++ * service provider may be unable to sign SHA-256 hashes.
|
| ++ * Use SHA-1 if the server supports it. */
|
| ++ if (ss->ssl3.platformClientKey->dwKeySpec !=
|
| ++ CERT_NCRYPT_KEY_SPEC) {
|
| ++ for (i = 0; i < algorithms.len; i += 2) {
|
| ++ /* CAPI only supports RSA and DSA signatures. */
|
| ++ if (algorithms.data[i] == tls_hash_sha1 &&
|
| ++ (algorithms.data[i+1] == tls_sig_rsa ||
|
| ++ algorithms.data[i+1] == tls_sig_dsa)) {
|
| ++ need_backup_hash = PR_TRUE;
|
| ++ break;
|
| ++ }
|
| ++ }
|
| ++ }
|
| ++#endif /* _WIN32 */
|
| ++ if (!need_backup_hash) {
|
| ++ PK11_DestroyContext(ss->ssl3.hs.md5, PR_TRUE);
|
| ++ ss->ssl3.hs.md5 = NULL;
|
| ++ }
|
| ++ }
|
| + break; /* not an error */
|
| + }
|
| + #endif /* NSS_PLATFORM_CLIENT_AUTH */
|
| +@@ -7227,6 +7304,13 @@
|
| + (ss->ssl3.platformClientKey ||
|
| + ss->ssl3.clientPrivateKey != NULL);
|
| +
|
| ++ if (!sendClientCert &&
|
| ++ ss->ssl3.hs.hashType == handshake_hash_single && ss->ssl3.hs.md5) {
|
| ++ /* Don't need the backup handshake hash. */
|
| ++ PK11_DestroyContext(ss->ssl3.hs.md5, PR_TRUE);
|
| ++ ss->ssl3.hs.md5 = NULL;
|
| ++ }
|
| ++
|
| + /* We must wait for the server's certificate to be authenticated before
|
| + * sending the client certificate in order to disclosing the client
|
| + * certificate to an attacker that does not have a valid cert for the
|
| +Index: net/third_party/nss/ssl/sslimpl.h
|
| +===================================================================
|
| +--- net/third_party/nss/ssl/sslimpl.h (revision 219342)
|
| ++++ net/third_party/nss/ssl/sslimpl.h (working copy)
|
| +@@ -838,6 +838,9 @@
|
| + * SSL 3.0 - TLS 1.1 use both |md5| and |sha|. |md5| is used for MD5 and
|
| + * |sha| for SHA-1.
|
| + * TLS 1.2 and later use only |sha|, for SHA-256. */
|
| ++ /* NOTE: On Windows, TLS 1.2 and later use |md5| as a backup handshake hash
|
| ++ * for generating client auth signatures. Confusingly, the backup hash
|
| ++ * function is SHA-1. */
|
| + PK11Context * md5;
|
| + PK11Context * sha;
|
| +
|
|
|