diff options
author | Wan-Teh Chang <wtc@google.com> | 2013-06-17 14:11:17 -0700 |
---|---|---|
committer | Wan-Teh Chang <wtc@google.com> | 2013-06-17 14:11:17 -0700 |
commit | 8ea1963f4099b4d5b19d563e511e9a3d42c639af (patch) | |
tree | a95433aa9233cac65f6c26e3447af8bef40a652f | |
parent | 034529fa47025fa9f5d2e2b10e7c6474a789c47a (diff) | |
download | nss-hg-8ea1963f4099b4d5b19d563e511e9a3d42c639af.tar.gz |
Bug 480514: Support TLS 1.2 in the PKCS #11 bypass mode. Delay the
creation of handshake hash contexts and buffer handshake messages
until we have established the handshake hash functions. Remove
redundant ssl3_InitState calls. Remove NSS_SURVIVE_DOUBLE_BYPASS_FAILURE
support. r=agl.
-rw-r--r-- | lib/ssl/config.mk | 4 | ||||
-rw-r--r-- | lib/ssl/derive.c | 67 | ||||
-rw-r--r-- | lib/ssl/ssl3con.c | 335 | ||||
-rw-r--r-- | lib/ssl/sslimpl.h | 35 | ||||
-rw-r--r-- | lib/ssl/sslsock.c | 9 |
5 files changed, 247 insertions, 203 deletions
diff --git a/lib/ssl/config.mk b/lib/ssl/config.mk index 1a717fa90..da8b9ef77 100644 --- a/lib/ssl/config.mk +++ b/lib/ssl/config.mk @@ -7,10 +7,6 @@ ifdef NISCC_TEST DEFINES += -DNISCC_TEST endif -ifdef NSS_SURVIVE_DOUBLE_BYPASS_FAILURE -DEFINES += -DNSS_SURVIVE_DOUBLE_BYPASS_FAILURE -endif - ifdef NSS_NO_PKCS11_BYPASS DEFINES += -DNO_PKCS11_BYPASS else diff --git a/lib/ssl/derive.c b/lib/ssl/derive.c index 420e6781e..35cfe2512 100644 --- a/lib/ssl/derive.c +++ b/lib/ssl/derive.c @@ -81,9 +81,11 @@ ssl3_KeyAndMacDeriveBypass( 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; @@ -115,7 +117,13 @@ ssl3_KeyAndMacDeriveBypass( 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 @@ -150,8 +158,13 @@ ssl3_KeyAndMacDeriveBypass( 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; } @@ -239,22 +252,34 @@ ssl3_KeyAndMacDeriveBypass( 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; - - /* - ** server_write_IV[CipherSpec.IV_size] - */ - buildSSLKey(&key_block[i], IVSize, &pwSpec->server.write_iv_item, \ - "Domestic Server 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; + } } PORT_Assert(i <= block_bytes); - } else if (!isTLS) { /* ** Generate SSL3 Export write keys and IVs. @@ -417,6 +442,7 @@ ssl3_MasterKeyDeriveBypass( 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; @@ -452,7 +478,12 @@ ssl3_MasterKeyDeriveBypass( 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); } diff --git a/lib/ssl/ssl3con.c b/lib/ssl/ssl3con.c index 959f65b51..f5087be84 100644 --- a/lib/ssl/ssl3con.c +++ b/lib/ssl/ssl3con.c @@ -58,7 +58,6 @@ static SECStatus ssl3_SendFinished( sslSocket *ss, PRInt32 flags); 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); @@ -1060,6 +1059,9 @@ ssl3_ComputeCommonKeyHash(SECOidTag hashAlg, } 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; @@ -1523,7 +1525,8 @@ ssl3_InitCompressionContext(ssl3CipherSpec *pwSpec) } #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. */ @@ -1539,7 +1542,6 @@ ssl3_InitPendingContextsBypass(sslSocket *ss) unsigned int optArg1 = 0; unsigned int optArg2 = 0; PRBool server_encrypts = ss->sec.isServer; - CK_ULONG macLength; SSLCipherAlgorithm calg; SSLCompressionMethod compression_method; SECStatus rv; @@ -1550,11 +1552,6 @@ ssl3_InitPendingContextsBypass(sslSocket *ss) 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; @@ -3436,18 +3433,6 @@ ssl3_DeriveMasterSecret(sslSocket *ss, PK11SymKey *pms) */ 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, @@ -3617,34 +3602,90 @@ loser: 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; @@ -3659,83 +3700,30 @@ ssl3_RestartHandshakeHashes(sslSocket *ss) { 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() @@ -3749,31 +3737,27 @@ ssl3_UpdateHandshakeHashes(sslSocket *ss, const unsigned char *b, 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; @@ -3901,10 +3885,6 @@ ssl3_AppendHandshakeHeader(sslSocket *ss, SSL3HandshakeType t, PRUint32 length) 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) { @@ -4235,7 +4215,27 @@ ssl3_ComputeHandshakeHashes(sslSocket * ss, 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]; @@ -4320,7 +4320,8 @@ ssl3_ComputeHandshakeHashes(sslSocket * ss, #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]; @@ -4331,7 +4332,7 @@ ssl3_ComputeHandshakeHashes(sslSocket * ss, 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) { @@ -4352,8 +4353,7 @@ ssl3_ComputeHandshakeHashes(sslSocket * ss, 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; } @@ -4362,7 +4362,7 @@ tls12_loser: } } } else { - /* compute hases with PKCS11 */ + /* compute hashes with PKCS11 */ PK11Context * md5; PK11Context * sha = NULL; unsigned char *md5StateBuf = NULL; @@ -4527,6 +4527,10 @@ ssl3_StartHandshakeHash(sslSocket *ss, unsigned char * buf, int length) 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( @@ -4586,8 +4590,6 @@ ssl3_SendClientHello(sslSocket *ss, PRBool resending) */ 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; @@ -5846,12 +5848,8 @@ ssl3_HandleServerHello(sslSocket *ss, SSL3Opaque *b, PRUint32 length) 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; @@ -5904,7 +5902,7 @@ ssl3_HandleServerHello(sslSocket *ss, SSL3Opaque *b, PRUint32 length) } 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(); @@ -7071,6 +7069,7 @@ ssl3_HandleClientHello(sslSocket *ss, SSL3Opaque *b, PRUint32 length) 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); @@ -7098,11 +7097,6 @@ ssl3_HandleClientHello(sslSocket *ss, SSL3Opaque *b, PRUint32 length) 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; @@ -7141,7 +7135,7 @@ ssl3_HandleClientHello(sslSocket *ss, SSL3Opaque *b, PRUint32 length) goto alert_loser; } - rv = ssl3_InitTLS12HandshakeHash(ss); + rv = ssl3_InitHandshakeHashes(ss); if (rv != SECSuccess) { desc = internal_error; errCode = PORT_GetError(); @@ -7868,6 +7862,11 @@ ssl3_HandleV2ClientHello(sslSocket *ss, unsigned char *buffer, int length) 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; @@ -7889,7 +7888,7 @@ ssl3_HandleV2ClientHello(sslSocket *ss, unsigned char *buffer, int length) goto alert_loser; } - rv = ssl3_InitTLS12HandshakeHash(ss); + rv = ssl3_InitHandshakeHashes(ss); if (rv != SECSuccess) { desc = internal_error; errCode = PORT_GetError(); @@ -8624,6 +8623,7 @@ ssl3_HandleRSAClientKeyExchange(sslSocket *ss, 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; @@ -9632,7 +9632,12 @@ ssl3_TLSPRFWithMasterSecret(ssl3CipherSpec *spec, const char *label, 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 } @@ -10142,10 +10147,6 @@ ssl3_HandleHandshakeMessage(sslSocket *ss, SSL3Opaque *b, PRUint32 length) } 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); @@ -10154,8 +10155,6 @@ ssl3_HandleHandshakeMessage(sslSocket *ss, SSL3Opaque *b, PRUint32 length) /* 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; @@ -11094,8 +11093,6 @@ ssl3_InitCipherSpec(sslSocket *ss, ssl3CipherSpec *spec) /* Called from: ssl3_SendRecord ** ssl3_StartHandshakeHash() <- ssl2_BeginClientHandshake() ** ssl3_SendClientHello() -** ssl3_HandleServerHello() -** ssl3_HandleClientHello() ** ssl3_HandleV2ClientHello() ** ssl3_HandleRecord() ** @@ -11106,7 +11103,6 @@ ssl3_InitCipherSpec(sslSocket *ss, ssl3CipherSpec *spec) static SECStatus ssl3_InitState(sslSocket *ss) { - SECStatus rv; PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss)); if (ss->ssl3.initialized) @@ -11139,12 +11135,12 @@ ssl3_InitState(sslSocket *ss) 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. @@ -11439,8 +11435,12 @@ ssl3_DestroySSL3Info(sslSocket *ss) /* 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) { @@ -11449,9 +11449,6 @@ ssl3_DestroySSL3Info(sslSocket *ss) 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); } diff --git a/lib/ssl/sslimpl.h b/lib/ssl/sslimpl.h index b0abfd597..90e9567c1 100644 --- a/lib/ssl/sslimpl.h +++ b/lib/ssl/sslimpl.h @@ -487,7 +487,9 @@ typedef PRUint16 DTLSEpoch; 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 @@ -766,6 +768,12 @@ typedef struct DTLSQueuedMessageStr { 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 @@ -774,11 +782,31 @@ typedef struct SSL3HandshakeStateStr { 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; @@ -796,7 +824,6 @@ const ssl3CipherSuiteDef *suite_def; 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 */ diff --git a/lib/ssl/sslsock.c b/lib/ssl/sslsock.c index 2733f5e9d..cd4a7a73e 100644 --- a/lib/ssl/sslsock.c +++ b/lib/ssl/sslsock.c @@ -782,10 +782,7 @@ SSL_OptionSet(PRFileDesc *fd, PRInt32 which, PRBool on) 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 @@ -1880,10 +1877,6 @@ SSL_VersionRangeSet(PRFileDesc *fd, const SSLVersionRange *vrange) ssl_GetSSL3HandshakeLock(ss); ss->vrange = *vrange; - /* 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); |