Index: net/third_party/nss/patches/tls12handshakehashes.patch |
=================================================================== |
--- net/third_party/nss/patches/tls12handshakehashes.patch (revision 0) |
+++ net/third_party/nss/patches/tls12handshakehashes.patch (revision 0) |
@@ -0,0 +1,814 @@ |
+Index: net/third_party/nss/ssl/derive.c |
+=================================================================== |
+--- net/third_party/nss/ssl/derive.c (revision 206496) |
++++ net/third_party/nss/ssl/derive.c (working copy) |
+@@ -82,9 +82,11 @@ |
+ unsigned int effKeySize; /* effective size of cipher keys */ |
+ unsigned int macSize; /* size of MAC secret */ |
+ unsigned int IVSize; /* size of IV */ |
++ PRBool explicitIV = PR_FALSE; |
+ SECStatus rv = SECFailure; |
+ SECStatus status = SECSuccess; |
+ PRBool isFIPS = PR_FALSE; |
++ PRBool isTLS12 = pwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_2; |
+ |
+ SECItem srcr; |
+ SECItem crsr; |
+@@ -116,7 +118,13 @@ |
+ if (keySize == 0) { |
+ effKeySize = IVSize = 0; /* only MACing */ |
+ } |
+- block_needed = 2 * (macSize + effKeySize + ((!isExport) * IVSize)); |
++ if (cipher_def->type == type_block && |
++ pwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_1) { |
++ /* Block ciphers in >= TLS 1.1 use a per-record, explicit IV. */ |
++ explicitIV = PR_TRUE; |
++ } |
++ block_needed = |
++ 2 * (macSize + effKeySize + ((!isExport && !explicitIV) * IVSize)); |
+ |
+ /* |
+ * clear out our returned keys so we can recover on failure |
+@@ -151,8 +159,13 @@ |
+ keyblk.data = key_block; |
+ keyblk.len = block_needed; |
+ |
+- status = TLS_PRF(&pwSpec->msItem, "key expansion", &srcr, &keyblk, |
+- isFIPS); |
++ if (isTLS12) { |
++ status = TLS_P_hash(HASH_AlgSHA256, &pwSpec->msItem, |
++ "key expansion", &srcr, &keyblk, isFIPS); |
++ } else { |
++ status = TLS_PRF(&pwSpec->msItem, "key expansion", &srcr, &keyblk, |
++ isFIPS); |
++ } |
+ if (status != SECSuccess) { |
+ goto key_and_mac_derive_fail; |
+ } |
+@@ -240,22 +253,34 @@ |
+ i += keySize; |
+ |
+ if (IVSize > 0) { |
+- /* |
+- ** client_write_IV[CipherSpec.IV_size] |
+- */ |
+- buildSSLKey(&key_block[i], IVSize, &pwSpec->client.write_iv_item, \ |
+- "Domestic Client Write IV"); |
+- i += IVSize; |
++ if (explicitIV) { |
++ static unsigned char zero_block[32]; |
++ PORT_Assert(IVSize <= sizeof zero_block); |
++ buildSSLKey(&zero_block[0], IVSize, \ |
++ &pwSpec->client.write_iv_item, \ |
++ "Domestic Client Write IV"); |
++ buildSSLKey(&zero_block[0], IVSize, \ |
++ &pwSpec->server.write_iv_item, \ |
++ "Domestic Server Write IV"); |
++ } else { |
++ /* |
++ ** client_write_IV[CipherSpec.IV_size] |
++ */ |
++ buildSSLKey(&key_block[i], IVSize, \ |
++ &pwSpec->client.write_iv_item, \ |
++ "Domestic Client Write IV"); |
++ i += IVSize; |
+ |
+- /* |
+- ** server_write_IV[CipherSpec.IV_size] |
+- */ |
+- buildSSLKey(&key_block[i], IVSize, &pwSpec->server.write_iv_item, \ |
+- "Domestic Server Write IV"); |
+- i += IVSize; |
++ /* |
++ ** server_write_IV[CipherSpec.IV_size] |
++ */ |
++ buildSSLKey(&key_block[i], IVSize, \ |
++ &pwSpec->server.write_iv_item, \ |
++ "Domestic Server Write IV"); |
++ i += IVSize; |
++ } |
+ } |
+ PORT_Assert(i <= block_bytes); |
+- |
+ } else if (!isTLS) { |
+ /* |
+ ** Generate SSL3 Export write keys and IVs. |
+@@ -418,6 +443,7 @@ |
+ unsigned char * key_block = pwSpec->key_block; |
+ SECStatus rv = SECSuccess; |
+ PRBool isFIPS = PR_FALSE; |
++ PRBool isTLS12 = pwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_2; |
+ |
+ SECItem crsr; |
+ |
+@@ -453,7 +479,12 @@ |
+ master.data = key_block; |
+ master.len = SSL3_MASTER_SECRET_LENGTH; |
+ |
+- rv = TLS_PRF(pms, "master secret", &crsr, &master, isFIPS); |
++ if (isTLS12) { |
++ rv = TLS_P_hash(HASH_AlgSHA256, pms, "master secret", &crsr, |
++ &master, isFIPS); |
++ } else { |
++ rv = TLS_PRF(pms, "master secret", &crsr, &master, isFIPS); |
++ } |
+ if (rv != SECSuccess) { |
+ PORT_SetError(SSL_ERROR_SESSION_KEY_GEN_FAILURE); |
+ } |
+Index: net/third_party/nss/ssl/sslsock.c |
+=================================================================== |
+--- net/third_party/nss/ssl/sslsock.c (revision 206496) |
++++ net/third_party/nss/ssl/sslsock.c (working copy) |
+@@ -796,10 +796,7 @@ |
+ rv = SECFailure; |
+ } else { |
+ if (PR_FALSE != on) { |
+- /* PKCS#11 bypass is not supported with TLS 1.2. */ |
+- if (ss->vrange.max >= SSL_LIBRARY_VERSION_TLS_1_2) { |
+- ss->opt.bypassPKCS11 = PR_FALSE; |
+- } else if (PR_SUCCESS == SSL_BypassSetup() ) { |
++ if (PR_SUCCESS == SSL_BypassSetup() ) { |
+ #ifdef NO_PKCS11_BYPASS |
+ ss->opt.bypassPKCS11 = PR_FALSE; |
+ #else |
+@@ -1964,10 +1961,6 @@ |
+ } |
+ ss->vrange.max = SSL_LIBRARY_VERSION_TLS_1_1; |
+ } |
+- /* PKCS#11 bypass is not supported with TLS 1.2. */ |
+- if (ss->vrange.max >= SSL_LIBRARY_VERSION_TLS_1_2) { |
+- ss->opt.bypassPKCS11 = PR_FALSE; |
+- } |
+ |
+ ssl_ReleaseSSL3HandshakeLock(ss); |
+ ssl_Release1stHandshakeLock(ss); |
+Index: net/third_party/nss/ssl/ssl3con.c |
+=================================================================== |
+--- net/third_party/nss/ssl/ssl3con.c (revision 206496) |
++++ net/third_party/nss/ssl/ssl3con.c (working copy) |
+@@ -69,7 +69,6 @@ |
+ static SECStatus ssl3_SendServerHello( sslSocket *ss); |
+ static SECStatus ssl3_SendServerHelloDone( sslSocket *ss); |
+ static SECStatus ssl3_SendServerKeyExchange( sslSocket *ss); |
+-static SECStatus ssl3_NewHandshakeHashes( sslSocket *ss); |
+ static SECStatus ssl3_UpdateHandshakeHashes( sslSocket *ss, |
+ const unsigned char *b, |
+ unsigned int l); |
+@@ -1072,6 +1071,9 @@ |
+ } else if (hashAlg == SEC_OID_SHA384) { |
+ SHA384_HashBuf(hashes->u.raw, hashBuf, bufLen); |
+ hashes->len = SHA384_LENGTH; |
++ } else if (hashAlg == SEC_OID_SHA512) { |
++ SHA512_HashBuf(hashes->u.raw, hashBuf, bufLen); |
++ hashes->len = SHA512_LENGTH; |
+ } else { |
+ PORT_SetError(SSL_ERROR_UNSUPPORTED_HASH_ALGORITHM); |
+ return SECFailure; |
+@@ -1535,7 +1537,8 @@ |
+ } |
+ |
+ #ifndef NO_PKCS11_BYPASS |
+-/* Initialize encryption and MAC contexts for pending spec. |
++/* Initialize encryption contexts for pending spec. |
++ * MAC contexts are set up when computing the mac, not here. |
+ * Master Secret already is derived in spec->msItem |
+ * Caller holds Spec write lock. |
+ */ |
+@@ -1551,7 +1554,6 @@ |
+ unsigned int optArg1 = 0; |
+ unsigned int optArg2 = 0; |
+ PRBool server_encrypts = ss->sec.isServer; |
+- CK_ULONG macLength; |
+ SSLCipherAlgorithm calg; |
+ SSLCompressionMethod compression_method; |
+ SECStatus rv; |
+@@ -1562,12 +1564,7 @@ |
+ |
+ pwSpec = ss->ssl3.pwSpec; |
+ cipher_def = pwSpec->cipher_def; |
+- macLength = pwSpec->mac_size; |
+ |
+- /* MAC setup is done when computing the mac, not here. |
+- * Now setup the crypto contexts. |
+- */ |
+- |
+ calg = cipher_def->calg; |
+ compression_method = pwSpec->compression_method; |
+ |
+@@ -3459,18 +3456,6 @@ |
+ */ |
+ rv = PK11_ExtractKeyValue(pwSpec->master_secret); |
+ if (rv != SECSuccess) { |
+-#if defined(NSS_SURVIVE_DOUBLE_BYPASS_FAILURE) |
+- /* The double bypass failed. |
+- * Attempt to revert to an all PKCS#11, non-bypass method. |
+- * Do we need any unacquired locks here? |
+- */ |
+- ss->opt.bypassPKCS11 = 0; |
+- rv = ssl3_NewHandshakeHashes(ss); |
+- if (rv == SECSuccess) { |
+- rv = ssl3_UpdateHandshakeHashes(ss, ss->ssl3.hs.messages.buf, |
+- ss->ssl3.hs.messages.len); |
+- } |
+-#endif |
+ return rv; |
+ } |
+ /* This returns the address of the secItem inside the key struct, |
+@@ -3640,34 +3625,90 @@ |
+ return SECFailure; |
+ } |
+ |
+-/* ssl3_InitTLS12HandshakeHash creates a handshake hash context for TLS 1.2, |
+- * if needed, and hashes in any buffered messages in ss->ssl3.hs.messages. */ |
++/* ssl3_InitHandshakeHashes creates handshake hash contexts and hashes in |
++ * buffered messages in ss->ssl3.hs.messages. */ |
+ static SECStatus |
+-ssl3_InitTLS12HandshakeHash(sslSocket *ss) |
++ssl3_InitHandshakeHashes(sslSocket *ss) |
+ { |
+- if (ss->version >= SSL_LIBRARY_VERSION_TLS_1_2 && |
+- ss->ssl3.hs.tls12_handshake_hash == NULL) { |
+- /* If we ever support ciphersuites where the PRF hash isn't SHA-256 |
+- * then this will need to be updated. */ |
+- ss->ssl3.hs.tls12_handshake_hash = |
+- PK11_CreateDigestContext(SEC_OID_SHA256); |
+- if (!ss->ssl3.hs.tls12_handshake_hash || |
+- PK11_DigestBegin(ss->ssl3.hs.tls12_handshake_hash) != SECSuccess) { |
+- ssl_MapLowLevelError(SSL_ERROR_DIGEST_FAILURE); |
+- return SECFailure; |
++ SSL_TRC(30,("%d: SSL3[%d]: start handshake hashes", SSL_GETPID(), ss->fd)); |
++ |
++ PORT_Assert(ss->ssl3.hs.hashType == handshake_hash_unknown); |
++#ifndef NO_PKCS11_BYPASS |
++ if (ss->opt.bypassPKCS11) { |
++ PORT_Assert(!ss->ssl3.hs.sha_obj && !ss->ssl3.hs.sha_clone); |
++ if (ss->version >= SSL_LIBRARY_VERSION_TLS_1_2) { |
++ /* If we ever support ciphersuites where the PRF hash isn't SHA-256 |
++ * then this will need to be updated. */ |
++ ss->ssl3.hs.sha_obj = HASH_GetRawHashObject(HASH_AlgSHA256); |
++ if (!ss->ssl3.hs.sha_obj) { |
++ ssl_MapLowLevelError(SSL_ERROR_DIGEST_FAILURE); |
++ return SECFailure; |
++ } |
++ ss->ssl3.hs.sha_clone = (void (*)(void *, void *))SHA256_Clone; |
++ ss->ssl3.hs.hashType = handshake_hash_single; |
++ ss->ssl3.hs.sha_obj->begin(ss->ssl3.hs.sha_cx); |
++ } else { |
++ ss->ssl3.hs.hashType = handshake_hash_combo; |
++ MD5_Begin((MD5Context *)ss->ssl3.hs.md5_cx); |
++ SHA1_Begin((SHA1Context *)ss->ssl3.hs.sha_cx); |
+ } |
+- } |
++ } else |
++#endif |
++ { |
++ PORT_Assert(!ss->ssl3.hs.md5 && !ss->ssl3.hs.sha); |
++ /* |
++ * note: We should probably lookup an SSL3 slot for these |
++ * handshake hashes in hopes that we wind up with the same slots |
++ * that the master secret will wind up in ... |
++ */ |
++ if (ss->version >= SSL_LIBRARY_VERSION_TLS_1_2) { |
++ /* If we ever support ciphersuites where the PRF hash isn't SHA-256 |
++ * then this will need to be updated. */ |
++ ss->ssl3.hs.sha = PK11_CreateDigestContext(SEC_OID_SHA256); |
++ if (ss->ssl3.hs.sha == NULL) { |
++ ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE); |
++ return SECFailure; |
++ } |
++ ss->ssl3.hs.hashType = handshake_hash_single; |
+ |
+- if (ss->ssl3.hs.tls12_handshake_hash && ss->ssl3.hs.messages.len > 0) { |
+- if (PK11_DigestOp(ss->ssl3.hs.tls12_handshake_hash, |
+- ss->ssl3.hs.messages.buf, |
+- ss->ssl3.hs.messages.len) != SECSuccess) { |
+- ssl_MapLowLevelError(SSL_ERROR_DIGEST_FAILURE); |
+- return SECFailure; |
++ if (PK11_DigestBegin(ss->ssl3.hs.sha) != SECSuccess) { |
++ ssl_MapLowLevelError(SSL_ERROR_DIGEST_FAILURE); |
++ return SECFailure; |
++ } |
++ } else { |
++ /* Both ss->ssl3.hs.md5 and ss->ssl3.hs.sha should be NULL or |
++ * created successfully. */ |
++ ss->ssl3.hs.md5 = PK11_CreateDigestContext(SEC_OID_MD5); |
++ if (ss->ssl3.hs.md5 == NULL) { |
++ ssl_MapLowLevelError(SSL_ERROR_MD5_DIGEST_FAILURE); |
++ return SECFailure; |
++ } |
++ ss->ssl3.hs.sha = PK11_CreateDigestContext(SEC_OID_SHA1); |
++ if (ss->ssl3.hs.sha == NULL) { |
++ PK11_DestroyContext(ss->ssl3.hs.md5, PR_TRUE); |
++ ss->ssl3.hs.md5 = NULL; |
++ ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE); |
++ return SECFailure; |
++ } |
++ ss->ssl3.hs.hashType = handshake_hash_combo; |
++ |
++ if (PK11_DigestBegin(ss->ssl3.hs.md5) != SECSuccess) { |
++ ssl_MapLowLevelError(SSL_ERROR_MD5_DIGEST_FAILURE); |
++ return SECFailure; |
++ } |
++ if (PK11_DigestBegin(ss->ssl3.hs.sha) != SECSuccess) { |
++ ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE); |
++ return SECFailure; |
++ } |
+ } |
+ } |
+ |
+- if (ss->ssl3.hs.messages.buf && !ss->opt.bypassPKCS11) { |
++ if (ss->ssl3.hs.messages.len > 0) { |
++ if (ssl3_UpdateHandshakeHashes(ss, ss->ssl3.hs.messages.buf, |
++ ss->ssl3.hs.messages.len) != |
++ SECSuccess) { |
++ return SECFailure; |
++ } |
+ PORT_Free(ss->ssl3.hs.messages.buf); |
+ ss->ssl3.hs.messages.buf = NULL; |
+ ss->ssl3.hs.messages.len = 0; |
+@@ -3682,83 +3723,30 @@ |
+ { |
+ SECStatus rv = SECSuccess; |
+ |
++ SSL_TRC(30,("%d: SSL3[%d]: reset handshake hashes", |
++ SSL_GETPID(), ss->fd )); |
++ ss->ssl3.hs.hashType = handshake_hash_unknown; |
+ ss->ssl3.hs.messages.len = 0; |
+ #ifndef NO_PKCS11_BYPASS |
+- if (ss->opt.bypassPKCS11) { |
+- MD5_Begin((MD5Context *)ss->ssl3.hs.md5_cx); |
+- SHA1_Begin((SHA1Context *)ss->ssl3.hs.sha_cx); |
+- } else |
++ ss->ssl3.hs.sha_obj = NULL; |
++ ss->ssl3.hs.sha_clone = NULL; |
+ #endif |
+- { |
+- if (ss->ssl3.hs.tls12_handshake_hash) { |
+- rv = PK11_DigestBegin(ss->ssl3.hs.tls12_handshake_hash); |
+- if (rv != SECSuccess) { |
+- ssl_MapLowLevelError(SSL_ERROR_DIGEST_FAILURE); |
+- return rv; |
+- } |
+- } |
+- rv = PK11_DigestBegin(ss->ssl3.hs.md5); |
+- if (rv != SECSuccess) { |
+- ssl_MapLowLevelError(SSL_ERROR_MD5_DIGEST_FAILURE); |
+- return rv; |
+- } |
+- rv = PK11_DigestBegin(ss->ssl3.hs.sha); |
+- if (rv != SECSuccess) { |
+- ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE); |
+- return rv; |
+- } |
+- } |
+- return rv; |
+-} |
+- |
+-static SECStatus |
+-ssl3_NewHandshakeHashes(sslSocket *ss) |
+-{ |
+- PK11Context *md5 = NULL; |
+- PK11Context *sha = NULL; |
+- |
+- /* |
+- * note: We should probably lookup an SSL3 slot for these |
+- * handshake hashes in hopes that we wind up with the same slots |
+- * that the master secret will wind up in ... |
+- */ |
+- SSL_TRC(30,("%d: SSL3[%d]: start handshake hashes", SSL_GETPID(), ss->fd)); |
+- PORT_Assert(!ss->ssl3.hs.messages.buf && !ss->ssl3.hs.messages.space); |
+- ss->ssl3.hs.messages.buf = NULL; |
+- ss->ssl3.hs.messages.space = 0; |
+- |
+- ss->ssl3.hs.md5 = md5 = PK11_CreateDigestContext(SEC_OID_MD5); |
+- ss->ssl3.hs.sha = sha = PK11_CreateDigestContext(SEC_OID_SHA1); |
+- ss->ssl3.hs.tls12_handshake_hash = NULL; |
+- if (md5 == NULL) { |
+- ssl_MapLowLevelError(SSL_ERROR_MD5_DIGEST_FAILURE); |
+- goto loser; |
+- } |
+- if (sha == NULL) { |
+- ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE); |
+- goto loser; |
+- } |
+- if (SECSuccess == ssl3_RestartHandshakeHashes(ss)) { |
+- return SECSuccess; |
+- } |
+- |
+-loser: |
+- if (md5 != NULL) { |
+- PK11_DestroyContext(md5, PR_TRUE); |
++ if (ss->ssl3.hs.md5) { |
++ PK11_DestroyContext(ss->ssl3.hs.md5,PR_TRUE); |
+ ss->ssl3.hs.md5 = NULL; |
+ } |
+- if (sha != NULL) { |
+- PK11_DestroyContext(sha, PR_TRUE); |
++ if (ss->ssl3.hs.sha) { |
++ PK11_DestroyContext(ss->ssl3.hs.sha,PR_TRUE); |
+ ss->ssl3.hs.sha = NULL; |
+ } |
+- return SECFailure; |
+- |
++ return rv; |
+ } |
+ |
+ /* |
+ * Handshake messages |
+ */ |
+-/* Called from ssl3_AppendHandshake() |
++/* Called from ssl3_InitHandshakeHashes() |
++** ssl3_AppendHandshake() |
+ ** ssl3_StartHandshakeHash() |
+ ** ssl3_HandleV2ClientHello() |
+ ** ssl3_HandleHandshakeMessage() |
+@@ -3772,31 +3760,27 @@ |
+ |
+ PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) ); |
+ |
+- PRINT_BUF(90, (NULL, "MD5 & SHA handshake hash input:", b, l)); |
+- |
+- if ((ss->version == 0 || ss->version >= SSL_LIBRARY_VERSION_TLS_1_2) && |
+- !ss->opt.bypassPKCS11 && |
+- ss->ssl3.hs.tls12_handshake_hash == NULL) { |
+- /* For TLS 1.2 connections we need to buffer the handshake messages |
+- * until we have established which PRF hash function to use. */ |
+- rv = sslBuffer_Append(&ss->ssl3.hs.messages, b, l); |
+- if (rv != SECSuccess) { |
+- return rv; |
+- } |
++ /* We need to buffer the handshake messages until we have established |
++ * which handshake hash function to use. */ |
++ if (ss->ssl3.hs.hashType == handshake_hash_unknown) { |
++ return sslBuffer_Append(&ss->ssl3.hs.messages, b, l); |
+ } |
+ |
++ PRINT_BUF(90, (NULL, "handshake hash input:", b, l)); |
++ |
+ #ifndef NO_PKCS11_BYPASS |
+ if (ss->opt.bypassPKCS11) { |
+- MD5_Update((MD5Context *)ss->ssl3.hs.md5_cx, b, l); |
+- SHA1_Update((SHA1Context *)ss->ssl3.hs.sha_cx, b, l); |
+-#if defined(NSS_SURVIVE_DOUBLE_BYPASS_FAILURE) |
+- rv = sslBuffer_Append(&ss->ssl3.hs.messages, b, l); |
+-#endif |
++ if (ss->ssl3.hs.hashType == handshake_hash_single) { |
++ ss->ssl3.hs.sha_obj->update(ss->ssl3.hs.sha_cx, b, l); |
++ } else { |
++ MD5_Update((MD5Context *)ss->ssl3.hs.md5_cx, b, l); |
++ SHA1_Update((SHA1Context *)ss->ssl3.hs.sha_cx, b, l); |
++ } |
+ return rv; |
+ } |
+ #endif |
+- if (ss->ssl3.hs.tls12_handshake_hash) { |
+- rv = PK11_DigestOp(ss->ssl3.hs.tls12_handshake_hash, b, l); |
++ if (ss->ssl3.hs.hashType == handshake_hash_single) { |
++ rv = PK11_DigestOp(ss->ssl3.hs.sha, b, l); |
+ if (rv != SECSuccess) { |
+ ssl_MapLowLevelError(SSL_ERROR_DIGEST_FAILURE); |
+ return rv; |
+@@ -3924,10 +3908,6 @@ |
+ |
+ SSL_TRC(30,("%d: SSL3[%d]: append handshake header: type %s", |
+ SSL_GETPID(), ss->fd, ssl3_DecodeHandshakeType(t))); |
+- PRINT_BUF(60, (ss, "MD5 handshake hash:", |
+- (unsigned char*)ss->ssl3.hs.md5_cx, MD5_LENGTH)); |
+- PRINT_BUF(95, (ss, "SHA handshake hash:", |
+- (unsigned char*)ss->ssl3.hs.sha_cx, SHA1_LENGTH)); |
+ |
+ rv = ssl3_AppendHandshakeNumber(ss, t, 1); |
+ if (rv != SECSuccess) { |
+@@ -4275,8 +4255,28 @@ |
+ hashes->hashAlg = SEC_OID_UNKNOWN; |
+ |
+ #ifndef NO_PKCS11_BYPASS |
+- if (ss->opt.bypassPKCS11) { |
++ if (ss->opt.bypassPKCS11 && |
++ ss->ssl3.hs.hashType == handshake_hash_single) { |
+ /* compute them without PKCS11 */ |
++ PRUint64 sha_cx[MAX_MAC_CONTEXT_LLONGS]; |
++ |
++ if (!spec->msItem.data) { |
++ PORT_SetError(SSL_ERROR_RX_UNEXPECTED_HANDSHAKE); |
++ return SECFailure; |
++ } |
++ |
++ ss->ssl3.hs.sha_clone(sha_cx, ss->ssl3.hs.sha_cx); |
++ ss->ssl3.hs.sha_obj->end(sha_cx, hashes->u.raw, &hashes->len, |
++ sizeof(hashes->u.raw)); |
++ |
++ PRINT_BUF(60, (NULL, "SHA-256: result", hashes->u.raw, hashes->len)); |
++ |
++ /* If we ever support ciphersuites where the PRF hash isn't SHA-256 |
++ * then this will need to be updated. */ |
++ hashes->hashAlg = SEC_OID_SHA256; |
++ rv = SECSuccess; |
++ } else if (ss->opt.bypassPKCS11) { |
++ /* compute them without PKCS11 */ |
+ PRUint64 md5_cx[MAX_MAC_CONTEXT_LLONGS]; |
+ PRUint64 sha_cx[MAX_MAC_CONTEXT_LLONGS]; |
+ |
+@@ -4360,7 +4360,8 @@ |
+ #undef shacx |
+ } else |
+ #endif |
+- if (ss->ssl3.hs.tls12_handshake_hash) { |
++ if (ss->ssl3.hs.hashType == handshake_hash_single) { |
++ /* compute hashes with PKCS11 */ |
+ PK11Context *h; |
+ unsigned int stateLen; |
+ unsigned char stackBuf[1024]; |
+@@ -4371,7 +4372,7 @@ |
+ return SECFailure; |
+ } |
+ |
+- h = ss->ssl3.hs.tls12_handshake_hash; |
++ h = ss->ssl3.hs.sha; |
+ stateBuf = PK11_SaveContextAlloc(h, stackBuf, |
+ sizeof(stackBuf), &stateLen); |
+ if (stateBuf == NULL) { |
+@@ -4392,8 +4393,7 @@ |
+ |
+ tls12_loser: |
+ if (stateBuf) { |
+- if (PK11_RestoreContext(ss->ssl3.hs.tls12_handshake_hash, stateBuf, |
+- stateLen) != SECSuccess) { |
++ if (PK11_RestoreContext(h, stateBuf, stateLen) != SECSuccess) { |
+ ssl_MapLowLevelError(SSL_ERROR_DIGEST_FAILURE); |
+ rv = SECFailure; |
+ } |
+@@ -4402,7 +4402,7 @@ |
+ } |
+ } |
+ } else { |
+- /* compute hases with PKCS11 */ |
++ /* compute hashes with PKCS11 */ |
+ PK11Context * md5; |
+ PK11Context * sha = NULL; |
+ unsigned char *md5StateBuf = NULL; |
+@@ -4567,6 +4567,10 @@ |
+ if (rv != SECSuccess) { |
+ goto done; /* ssl3_InitState has set the error code. */ |
+ } |
++ rv = ssl3_RestartHandshakeHashes(ss); |
++ if (rv != SECSuccess) { |
++ goto done; |
++ } |
+ |
+ PORT_Memset(&ss->ssl3.hs.client_random, 0, SSL3_RANDOM_LENGTH); |
+ PORT_Memcpy( |
+@@ -4626,8 +4630,6 @@ |
+ */ |
+ PORT_Memset(&ss->xtnData, 0, sizeof(TLSExtensionData)); |
+ |
+- SSL_TRC(30,("%d: SSL3[%d]: reset handshake hashes", |
+- SSL_GETPID(), ss->fd )); |
+ rv = ssl3_RestartHandshakeHashes(ss); |
+ if (rv != SECSuccess) { |
+ return rv; |
+@@ -5897,12 +5899,8 @@ |
+ SSL_GETPID(), ss->fd)); |
+ PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) ); |
+ PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) ); |
++ PORT_Assert( ss->ssl3.initialized ); |
+ |
+- rv = ssl3_InitState(ss); |
+- if (rv != SECSuccess) { |
+- errCode = PORT_GetError(); /* ssl3_InitState has set the error code. */ |
+- goto alert_loser; |
+- } |
+ if (ss->ssl3.hs.ws != wait_server_hello) { |
+ errCode = SSL_ERROR_RX_UNEXPECTED_SERVER_HELLO; |
+ desc = unexpected_message; |
+@@ -5970,7 +5968,7 @@ |
+ } |
+ isTLS = (ss->version > SSL_LIBRARY_VERSION_3_0); |
+ |
+- rv = ssl3_InitTLS12HandshakeHash(ss); |
++ rv = ssl3_InitHandshakeHashes(ss); |
+ if (rv != SECSuccess) { |
+ desc = internal_error; |
+ errCode = PORT_GetError(); |
+@@ -7308,6 +7306,7 @@ |
+ |
+ PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) ); |
+ PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss)); |
++ PORT_Assert( ss->ssl3.initialized ); |
+ |
+ /* Get peer name of client */ |
+ rv = ssl_GetPeerInfo(ss); |
+@@ -7335,11 +7334,6 @@ |
+ PORT_Memset(&ss->xtnData, 0, sizeof(TLSExtensionData)); |
+ ss->statelessResume = PR_FALSE; |
+ |
+- rv = ssl3_InitState(ss); |
+- if (rv != SECSuccess) { |
+- return rv; /* ssl3_InitState has set the error code. */ |
+- } |
+- |
+ if ((ss->ssl3.hs.ws != wait_client_hello) && |
+ (ss->ssl3.hs.ws != idle_handshake)) { |
+ desc = unexpected_message; |
+@@ -7378,7 +7372,7 @@ |
+ goto alert_loser; |
+ } |
+ |
+- rv = ssl3_InitTLS12HandshakeHash(ss); |
++ rv = ssl3_InitHandshakeHashes(ss); |
+ if (rv != SECSuccess) { |
+ desc = internal_error; |
+ errCode = PORT_GetError(); |
+@@ -8106,6 +8100,11 @@ |
+ ssl_ReleaseSSL3HandshakeLock(ss); |
+ return rv; /* ssl3_InitState has set the error code. */ |
+ } |
++ rv = ssl3_RestartHandshakeHashes(ss); |
++ if (rv != SECSuccess) { |
++ ssl_ReleaseSSL3HandshakeLock(ss); |
++ return rv; |
++ } |
+ |
+ if (ss->ssl3.hs.ws != wait_client_hello) { |
+ desc = unexpected_message; |
+@@ -8127,7 +8126,7 @@ |
+ goto alert_loser; |
+ } |
+ |
+- rv = ssl3_InitTLS12HandshakeHash(ss); |
++ rv = ssl3_InitHandshakeHashes(ss); |
+ if (rv != SECSuccess) { |
+ desc = internal_error; |
+ errCode = PORT_GetError(); |
+@@ -8858,6 +8857,7 @@ |
+ |
+ PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) ); |
+ PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) ); |
++ PORT_Assert( ss->ssl3.prSpec == ss->ssl3.pwSpec ); |
+ |
+ enc_pms.data = b; |
+ enc_pms.len = length; |
+@@ -9886,7 +9886,12 @@ |
+ inData.len = valLen; |
+ outData.data = out; |
+ outData.len = outLen; |
+- rv = TLS_PRF(&spec->msItem, label, &inData, &outData, isFIPS); |
++ if (spec->version >= SSL_LIBRARY_VERSION_TLS_1_2) { |
++ rv = TLS_P_hash(HASH_AlgSHA256, &spec->msItem, label, &inData, |
++ &outData, isFIPS); |
++ } else { |
++ rv = TLS_PRF(&spec->msItem, label, &inData, &outData, isFIPS); |
++ } |
+ PORT_Assert(rv != SECSuccess || outData.len == outLen); |
+ #endif |
+ } |
+@@ -10560,10 +10565,6 @@ |
+ } |
+ SSL_TRC(30,("%d: SSL3[%d]: handle handshake message: %s", SSL_GETPID(), |
+ ss->fd, ssl3_DecodeHandshakeType(ss->ssl3.hs.msg_type))); |
+- PRINT_BUF(60, (ss, "MD5 handshake hash:", |
+- (unsigned char*)ss->ssl3.hs.md5_cx, MD5_LENGTH)); |
+- PRINT_BUF(95, (ss, "SHA handshake hash:", |
+- (unsigned char*)ss->ssl3.hs.sha_cx, SHA1_LENGTH)); |
+ |
+ hdr[0] = (PRUint8)ss->ssl3.hs.msg_type; |
+ hdr[1] = (PRUint8)(length >> 16); |
+@@ -10572,8 +10573,6 @@ |
+ |
+ /* Start new handshake hashes when we start a new handshake */ |
+ if (ss->ssl3.hs.msg_type == client_hello) { |
+- SSL_TRC(30,("%d: SSL3[%d]: reset handshake hashes", |
+- SSL_GETPID(), ss->fd )); |
+ rv = ssl3_RestartHandshakeHashes(ss); |
+ if (rv != SECSuccess) { |
+ return rv; |
+@@ -11526,8 +11525,6 @@ |
+ /* Called from: ssl3_SendRecord |
+ ** ssl3_StartHandshakeHash() <- ssl2_BeginClientHandshake() |
+ ** ssl3_SendClientHello() |
+-** ssl3_HandleServerHello() |
+-** ssl3_HandleClientHello() |
+ ** ssl3_HandleV2ClientHello() |
+ ** ssl3_HandleRecord() |
+ ** |
+@@ -11538,7 +11535,6 @@ |
+ static SECStatus |
+ ssl3_InitState(sslSocket *ss) |
+ { |
+- SECStatus rv; |
+ PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss)); |
+ |
+ if (ss->ssl3.initialized) |
+@@ -11571,12 +11567,12 @@ |
+ dtls_SetMTU(ss, 0); /* Set the MTU to the highest plateau */ |
+ } |
+ |
+- rv = ssl3_NewHandshakeHashes(ss); |
+- if (rv == SECSuccess) { |
+- ss->ssl3.initialized = PR_TRUE; |
+- } |
++ PORT_Assert(!ss->ssl3.hs.messages.buf && !ss->ssl3.hs.messages.space); |
++ ss->ssl3.hs.messages.buf = NULL; |
++ ss->ssl3.hs.messages.space = 0; |
+ |
+- return rv; |
++ ss->ssl3.initialized = PR_TRUE; |
++ return SECSuccess; |
+ } |
+ |
+ /* Returns a reference counted object that contains a key pair. |
+@@ -11942,8 +11938,12 @@ |
+ /* clean up handshake */ |
+ #ifndef NO_PKCS11_BYPASS |
+ if (ss->opt.bypassPKCS11) { |
+- SHA1_DestroyContext((SHA1Context *)ss->ssl3.hs.sha_cx, PR_FALSE); |
+- MD5_DestroyContext((MD5Context *)ss->ssl3.hs.md5_cx, PR_FALSE); |
++ if (ss->ssl3.hs.hashType == handshake_hash_combo) { |
++ SHA1_DestroyContext((SHA1Context *)ss->ssl3.hs.sha_cx, PR_FALSE); |
++ MD5_DestroyContext((MD5Context *)ss->ssl3.hs.md5_cx, PR_FALSE); |
++ } else if (ss->ssl3.hs.hashType == handshake_hash_single) { |
++ ss->ssl3.hs.sha_obj->destroy(ss->ssl3.hs.sha_cx, PR_FALSE); |
++ } |
+ } |
+ #endif |
+ if (ss->ssl3.hs.md5) { |
+@@ -11952,9 +11952,6 @@ |
+ if (ss->ssl3.hs.sha) { |
+ PK11_DestroyContext(ss->ssl3.hs.sha,PR_TRUE); |
+ } |
+- if (ss->ssl3.hs.tls12_handshake_hash) { |
+- PK11_DestroyContext(ss->ssl3.hs.tls12_handshake_hash,PR_TRUE); |
+- } |
+ if (ss->ssl3.hs.clientSigAndHash) { |
+ PORT_Free(ss->ssl3.hs.clientSigAndHash); |
+ } |
+Index: net/third_party/nss/ssl/sslimpl.h |
+=================================================================== |
+--- net/third_party/nss/ssl/sslimpl.h (revision 206496) |
++++ net/third_party/nss/ssl/sslimpl.h (working copy) |
+@@ -506,7 +506,9 @@ |
+ |
+ typedef void (*DTLSTimerCb)(sslSocket *); |
+ |
+-#define MAX_MAC_CONTEXT_BYTES 400 |
++#define MAX_MAC_CONTEXT_BYTES 400 /* 400 is large enough for MD5, SHA-1, and |
++ * SHA-256. For SHA-384 support, increase |
++ * it to 712. */ |
+ #define MAX_MAC_CONTEXT_LLONGS (MAX_MAC_CONTEXT_BYTES / 8) |
+ |
+ #define MAX_CIPHER_CONTEXT_BYTES 2080 |
+@@ -788,6 +790,12 @@ |
+ PRUint16 len; /* The data length */ |
+ } DTLSQueuedMessage; |
+ |
++typedef enum { |
++ handshake_hash_unknown = 0, |
++ handshake_hash_combo = 1, /* The MD5/SHA-1 combination */ |
++ handshake_hash_single = 2 /* A single hash */ |
++} SSL3HandshakeHashType; |
++ |
+ /* |
+ ** This is the "hs" member of the "ssl3" struct. |
+ ** This entire struct is protected by ssl3HandshakeLock |
+@@ -796,11 +804,31 @@ |
+ SSL3Random server_random; |
+ SSL3Random client_random; |
+ SSL3WaitState ws; |
++ |
++ /* This group of members is used for handshake running hashes. */ |
++ SSL3HandshakeHashType hashType; |
++ sslBuffer messages; /* Accumulated handshake messages */ |
++#ifndef NO_PKCS11_BYPASS |
++ /* Bypass mode: |
++ * SSL 3.0 - TLS 1.1 use both |md5_cx| and |sha_cx|. |md5_cx| is used for |
++ * MD5 and |sha_cx| for SHA-1. |
++ * TLS 1.2 and later use only |sha_cx|, for SHA-256. NOTE: When we support |
++ * SHA-384, increase MAX_MAC_CONTEXT_BYTES to 712. */ |
+ PRUint64 md5_cx[MAX_MAC_CONTEXT_LLONGS]; |
+ PRUint64 sha_cx[MAX_MAC_CONTEXT_LLONGS]; |
+- PK11Context * md5; /* handshake running hashes */ |
++ const SECHashObject * sha_obj; |
++ /* The function prototype of sha_obj->clone() does not match the prototype |
++ * of the freebl <HASH>_Clone functions, so we need a dedicated function |
++ * pointer for the <HASH>_Clone function. */ |
++ void (*sha_clone)(void *dest, void *src); |
++#endif |
++ /* PKCS #11 mode: |
++ * 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. */ |
++ PK11Context * md5; |
+ PK11Context * sha; |
+- PK11Context * tls12_handshake_hash; |
++ |
+ const ssl3KEADef * kea_def; |
+ ssl3CipherSuite cipher_suite; |
+ const ssl3CipherSuiteDef *suite_def; |
+@@ -818,7 +846,6 @@ |
+ PRBool sendingSCSV; /* instead of empty RI */ |
+ sslBuffer msgState; /* current state for handshake messages*/ |
+ /* protected by recvBufLock */ |
+- sslBuffer messages; /* Accumulated handshake messages */ |
+ PRUint16 finishedBytes; /* size of single finished below */ |
+ union { |
+ TLSFinished tFinished[2]; /* client, then server */ |