diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/ssl/config.mk | 5 | ||||
-rw-r--r-- | lib/ssl/dtls13con.c | 30 | ||||
-rw-r--r-- | lib/ssl/dtls13con.h | 1 | ||||
-rw-r--r-- | lib/ssl/dtlscon.c | 9 | ||||
-rw-r--r-- | lib/ssl/ssl.gyp | 8 | ||||
-rw-r--r-- | lib/ssl/ssl.h | 3 | ||||
-rw-r--r-- | lib/ssl/ssl3con.c | 1120 | ||||
-rw-r--r-- | lib/ssl/ssl3exthandle.c | 16 | ||||
-rw-r--r-- | lib/ssl/sslimpl.h | 23 | ||||
-rw-r--r-- | lib/ssl/sslinfo.c | 22 | ||||
-rw-r--r-- | lib/ssl/sslsnce.c | 6 | ||||
-rw-r--r-- | lib/ssl/sslsock.c | 8 | ||||
-rw-r--r-- | lib/ssl/sslspec.c | 121 | ||||
-rw-r--r-- | lib/ssl/sslspec.h | 71 | ||||
-rw-r--r-- | lib/ssl/tls13con.c | 189 |
15 files changed, 528 insertions, 1104 deletions
diff --git a/lib/ssl/config.mk b/lib/ssl/config.mk index c8b053cab..d13613f78 100644 --- a/lib/ssl/config.mk +++ b/lib/ssl/config.mk @@ -57,11 +57,6 @@ endif endif -ifdef NSS_SSL_ENABLE_ZLIB -DEFINES += -DNSS_SSL_ENABLE_ZLIB -include $(CORE_DEPTH)/coreconf/zlib.mk -endif - ifdef NSS_DISABLE_TLS_1_3 DEFINES += -DNSS_DISABLE_TLS_1_3 endif diff --git a/lib/ssl/dtls13con.c b/lib/ssl/dtls13con.c index 8a8e29956..b17b28a21 100644 --- a/lib/ssl/dtls13con.c +++ b/lib/ssl/dtls13con.c @@ -244,36 +244,6 @@ dtls13_HandleOutOfEpochRecord(sslSocket *ss, const ssl3CipherSpec *spec, return SECFailure; } -/* Store the null cipher spec with the right refct. */ -SECStatus -dtls13_SaveNullCipherSpec(sslSocket *ss, const ssl3CipherSpec *crSpec) -{ - ssl3CipherSpec *spec; - extern const char kKeyPhaseCleartext[]; - PORT_Assert(IS_DTLS(ss)); - - spec = PORT_ZNew(ssl3CipherSpec); - if (!spec) { - PORT_SetError(SEC_ERROR_NO_MEMORY); - return SECFailure; - } - spec->refCt = 1; - spec->cipher_def = crSpec->cipher_def; - spec->mac_def = crSpec->mac_def; - spec->decode = crSpec->decode; - spec->epoch = crSpec->epoch; - PORT_Memcpy(&spec->recvdRecords, &crSpec->recvdRecords, - sizeof(spec->recvdRecords)); - spec->direction = CipherSpecRead; - spec->phase = kKeyPhaseCleartext; - spec->read_seq_num = crSpec->write_seq_num; - spec->refCt = 1; - - PR_APPEND_LINK(&spec->link, &ss->ssl3.hs.cipherSpecs); - - return SECSuccess; -} - SECStatus dtls13_HandleAck(sslSocket *ss, sslBuffer *databuf) { diff --git a/lib/ssl/dtls13con.h b/lib/ssl/dtls13con.h index 7e494a7bb..70731ec6b 100644 --- a/lib/ssl/dtls13con.h +++ b/lib/ssl/dtls13con.h @@ -20,7 +20,6 @@ SECStatus dtls13_HandleOutOfEpochRecord(sslSocket *ss, const ssl3CipherSpec *spe SSL3ContentType rType, sslBuffer *databuf); SECStatus dtls13_HandleAck(sslSocket *ss, sslBuffer *databuf); -SECStatus dtls13_SaveNullCipherSpec(sslSocket *ss, const ssl3CipherSpec *crSpec); SECStatus dtls13_SendAck(sslSocket *ss); void dtls13_SendAckCb(sslSocket *ss); diff --git a/lib/ssl/dtlscon.c b/lib/ssl/dtlscon.c index 44239d637..52e924183 100644 --- a/lib/ssl/dtlscon.c +++ b/lib/ssl/dtlscon.c @@ -729,7 +729,7 @@ dtls_TransmitMessageFlight(sslSocket *ss, PRBool *messagesSent) &ss->ssl3.hs.dtlsSentHandshake, msgSeq, 0, msg->len, msg->cwSpec->epoch, - msg->cwSpec->write_seq_num); + msg->cwSpec->seqNum); if (rv != SECSuccess) { break; } @@ -834,7 +834,7 @@ dtls_TransmitMessageFlight(sslSocket *ss, PRBool *messagesSent) &ss->ssl3.hs.dtlsSentHandshake, msgSeq, fragment_offset, fragment_len, msg->cwSpec->epoch, - msg->cwSpec->write_seq_num); + msg->cwSpec->seqNum); if (rv != SECSuccess) { break; } @@ -1041,9 +1041,6 @@ static void dtls_FinishedTimerCb(sslSocket *ss) { dtls_FreeHandshakeMessages(&ss->ssl3.hs.lastMessageFlight); - if (ss->version < SSL_LIBRARY_VERSION_TLS_1_3) { - ssl_FreeCipherSpec(ss->ssl3.pwSpec); - } } /* Cancel the Finished hold-down timer and destroy the @@ -1063,7 +1060,7 @@ dtls_RehandshakeCleanup(sslSocket *ss) } PORT_Assert((ss->version < SSL_LIBRARY_VERSION_TLS_1_3)); dtls_CancelAllTimers(ss); - ssl_FreeCipherSpec(ss->ssl3.pwSpec); + dtls_FreeHandshakeMessages(&ss->ssl3.hs.lastMessageFlight); ss->ssl3.hs.sendMessageSeq = 0; ss->ssl3.hs.recvMessageSeq = 0; } diff --git a/lib/ssl/ssl.gyp b/lib/ssl/ssl.gyp index 287f65202..3694ab91a 100644 --- a/lib/ssl/ssl.gyp +++ b/lib/ssl/ssl.gyp @@ -62,14 +62,6 @@ 'unix_err.c' ], }], - [ 'ssl_enable_zlib==1', { - 'dependencies': [ - '<(DEPTH)/lib/zlib/zlib.gyp:nss_zlib' - ], - 'defines': [ - 'NSS_SSL_ENABLE_ZLIB', - ], - }], [ 'fuzz_tls==1', { 'defines': [ 'UNSAFE_FUZZER_MODE', diff --git a/lib/ssl/ssl.h b/lib/ssl/ssl.h index 80b08569f..9be8a6003 100644 --- a/lib/ssl/ssl.h +++ b/lib/ssl/ssl.h @@ -107,8 +107,7 @@ SSL_IMPORT PRFileDesc *DTLS_ImportFD(PRFileDesc *model, PRFileDesc *fd); #define SSL_NO_LOCKS 17 /* Don't use locks for protection */ #define SSL_ENABLE_SESSION_TICKETS 18 /* Enable TLS SessionTicket */ /* extension (off by default) */ -#define SSL_ENABLE_DEFLATE 19 /* Enable TLS compression with */ - /* DEFLATE (off by default) */ +#define SSL_ENABLE_DEFLATE 19 /* (unsupported, deprecated, off) */ #define SSL_ENABLE_RENEGOTIATION 20 /* Values below (default: never) */ #define SSL_REQUIRE_SAFE_NEGOTIATION 21 /* Peer must send Signaling */ /* Cipher Suite Value (SCSV) or */ diff --git a/lib/ssl/ssl3con.c b/lib/ssl/ssl3con.c index 639533b8c..c2dd4d0a7 100644 --- a/lib/ssl/ssl3con.c +++ b/lib/ssl/ssl3con.c @@ -34,9 +34,6 @@ #include "blapi.h" #include <stdio.h> -#ifdef NSS_SSL_ENABLE_ZLIB -#include "zlib.h" -#endif static PK11SymKey *ssl3_GenerateRSAPMS(sslSocket *ss, ssl3CipherSpec *spec, PK11SlotInfo *serverKeySlot); @@ -53,7 +50,6 @@ static SECStatus ssl3_SendServerHelloDone(sslSocket *ss); static SECStatus ssl3_SendServerKeyExchange(sslSocket *ss); static SECStatus ssl3_HandleClientHelloPart2(sslSocket *ss, SECItem *suites, - SECItem *comps, sslSessionID *sid, const PRUint8 *msg, unsigned int len); @@ -210,57 +206,6 @@ ssl3_CheckCipherSuiteOrderConsistency() } #endif -/* This list of SSL3 compression methods is sorted in descending order of - * precedence (desirability). It only includes compression methods we - * implement. - */ -static const SSLCompressionMethod ssl_compression_methods[] = { -#ifdef NSS_SSL_ENABLE_ZLIB - ssl_compression_deflate, -#endif - ssl_compression_null -}; - -static const unsigned int ssl_compression_method_count = - PR_ARRAY_SIZE(ssl_compression_methods); - -/* compressionEnabled returns true iff the compression algorithm is enabled - * for the given SSL socket. */ -static PRBool -ssl_CompressionEnabled(sslSocket *ss, SSLCompressionMethod compression) -{ - if (compression == ssl_compression_null) { - return PR_TRUE; /* Always enabled */ - } -/* Compression was disabled in NSS 3.33. It is temporarily possible - * to re-enable it by unifdefing the following block. We will remove - * compression entirely in future versions of NSS. */ -#if 0 - SSL3ProtocolVersion version; - - if (ss->sec.isServer) { - /* We can't easily check that the client didn't attempt TLS 1.3, - * so this will have to do. */ - PORT_Assert(ss->version < SSL_LIBRARY_VERSION_TLS_1_3); - version = ss->version; - } else { - version = ss->vrange.max; - } - if (version >= SSL_LIBRARY_VERSION_TLS_1_3) { - return PR_FALSE; - } -#ifdef NSS_SSL_ENABLE_ZLIB - if (compression == ssl_compression_deflate) { - if (IS_DTLS(ss)) { - return PR_FALSE; - } - return ss->opt.enableDeflate; - } -#endif -#endif - return PR_FALSE; -} - static const /*SSL3ClientCertificateType */ PRUint8 certificate_types[] = { ct_RSA_sign, ct_ECDSA_sign, @@ -1435,57 +1380,30 @@ loser: return SECFailure; } -/* Called twice, only from ssl3_DestroyCipherSpec (immediately below). */ -static void -ssl3_CleanupKeyMaterial(ssl3KeyMaterial *mat) +static SECStatus +ssl3_SetupPendingCipherSpec(sslSocket *ss, CipherSpecDirection direction, + const ssl3CipherSuiteDef *suiteDef, + ssl3CipherSpec **specp) { - if (mat->write_key != NULL) { - PK11_FreeSymKey(mat->write_key); - mat->write_key = NULL; - } - if (mat->write_mac_key != NULL) { - PK11_FreeSymKey(mat->write_mac_key); - mat->write_mac_key = NULL; - } - if (mat->write_mac_context != NULL) { - PK11_DestroyContext(mat->write_mac_context, PR_TRUE); - mat->write_mac_context = NULL; - } -} + ssl3CipherSpec *spec; + const ssl3CipherSpec *prev; -/* Called from ssl3_SendChangeCipherSpecs() and -** ssl3_HandleChangeCipherSpecs() -** ssl3_DestroySSL3Info -** Caller must hold SpecWriteLock. -*/ -void -ssl3_DestroyCipherSpec(ssl3CipherSpec *spec, PRBool freeSrvName) -{ - /* PORT_Assert( ss->opt.noLocks || ssl_HaveSpecWriteLock(ss)); Don't have ss! */ - if (spec->encodeContext) { - PK11_DestroyContext(spec->encodeContext, PR_TRUE); - spec->encodeContext = NULL; - } - if (spec->decodeContext) { - PK11_DestroyContext(spec->decodeContext, PR_TRUE); - spec->decodeContext = NULL; - } - if (spec->destroyCompressContext && spec->compressContext) { - spec->destroyCompressContext(spec->compressContext, 1); - spec->compressContext = NULL; - } - if (spec->destroyDecompressContext && spec->decompressContext) { - spec->destroyDecompressContext(spec->decompressContext, 1); - spec->decompressContext = NULL; - } - if (spec->master_secret != NULL) { - PK11_FreeSymKey(spec->master_secret); - spec->master_secret = NULL; + spec = ssl_CreateCipherSpec(ss, direction); + if (!spec) { + return SECFailure; } - ssl3_CleanupKeyMaterial(&spec->client); - ssl3_CleanupKeyMaterial(&spec->server); - spec->destroyCompressContext = NULL; - spec->destroyDecompressContext = NULL; + + spec->cipherDef = ssl_GetBulkCipherDef(suiteDef); + spec->macDef = ssl_GetMacDef(ss, suiteDef); + + spec->cipherContext = NULL; + + prev = (direction == CipherSpecWrite) ? ss->ssl3.cwSpec : ss->ssl3.crSpec; + spec->epoch = prev->epoch + 1; + + ssl_SaveCipherSpec(ss, spec); + *specp = spec; + return SECSuccess; } /* Fill in the pending cipher spec with info from the selected ciphersuite. @@ -1495,210 +1413,60 @@ ssl3_DestroyCipherSpec(ssl3CipherSpec *spec, PRBool freeSrvName) ** Acquires & releases SpecWriteLock. */ SECStatus -ssl3_SetupPendingCipherSpec(sslSocket *ss) +ssl3_SetupBothPendingCipherSpecs(sslSocket *ss) { - ssl3CipherSpec *pwSpec; - ssl3CipherSpec *cwSpec; ssl3CipherSuite suite = ss->ssl3.hs.cipher_suite; SSL3KeyExchangeAlgorithm kea; - const ssl3CipherSuiteDef *suite_def; + const ssl3CipherSuiteDef *suiteDef; + SECStatus rv; PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss)); PORT_Assert(ss->version < SSL_LIBRARY_VERSION_TLS_1_3); ssl_GetSpecWriteLock(ss); /*******************************/ - pwSpec = ss->ssl3.pwSpec; - PORT_Assert(pwSpec == ss->ssl3.prSpec); - /* This hack provides maximal interoperability with SSL 3 servers. */ - cwSpec = ss->ssl3.cwSpec; - if (cwSpec->mac_def->mac == ssl_mac_null) { + if (ss->ssl3.cwSpec->macDef->mac == ssl_mac_null) { /* SSL records are not being MACed. */ - cwSpec->version = ss->version; + ss->ssl3.cwSpec->version = ss->version; } - pwSpec->version = ss->version; - SSL_TRC(3, ("%d: SSL3[%d]: Set XXX Pending Cipher Suite to 0x%04x", SSL_GETPID(), ss->fd, suite)); - suite_def = ssl_LookupCipherSuiteDef(suite); - if (suite_def == NULL) { - ssl_ReleaseSpecWriteLock(ss); - return SECFailure; /* error code set by ssl_LookupCipherSuiteDef */ + suiteDef = ssl_LookupCipherSuiteDef(suite); + if (suiteDef == NULL) { + goto loser; } if (IS_DTLS(ss)) { /* Double-check that we did not pick an RC4 suite */ - PORT_Assert(suite_def->bulk_cipher_alg != cipher_rc4); + PORT_Assert(suiteDef->bulk_cipher_alg != cipher_rc4); } - kea = suite_def->key_exchange_alg; + ss->ssl3.hs.suite_def = suiteDef; - ss->ssl3.hs.suite_def = suite_def; + kea = suiteDef->key_exchange_alg; ss->ssl3.hs.kea_def = &kea_defs[kea]; PORT_Assert(ss->ssl3.hs.kea_def->kea == kea); - pwSpec->cipher_def = ssl_GetBulkCipherDef(suite_def); - pwSpec->mac_def = ssl_GetMacDef(ss, suite_def); - - pwSpec->encodeContext = NULL; - pwSpec->decodeContext = NULL; - - pwSpec->mac_size = pwSpec->mac_def->mac_size; - - pwSpec->compression_method = ss->ssl3.hs.compression; - pwSpec->compressContext = NULL; - pwSpec->decompressContext = NULL; - - ssl_ReleaseSpecWriteLock(ss); /*******************************/ - return SECSuccess; -} - -#ifdef NSS_SSL_ENABLE_ZLIB -#define SSL3_DEFLATE_CONTEXT_SIZE sizeof(z_stream) - -static SECStatus -ssl3_MapZlibError(int zlib_error) -{ - switch (zlib_error) { - case Z_OK: - return SECSuccess; - default: - return SECFailure; - } -} - -static SECStatus -ssl3_DeflateInit(void *void_context) -{ - z_stream *context = void_context; - context->zalloc = NULL; - context->zfree = NULL; - context->opaque = NULL; - - return ssl3_MapZlibError(deflateInit(context, Z_DEFAULT_COMPRESSION)); -} - -static SECStatus -ssl3_InflateInit(void *void_context) -{ - z_stream *context = void_context; - context->zalloc = NULL; - context->zfree = NULL; - context->opaque = NULL; - context->next_in = NULL; - context->avail_in = 0; - - return ssl3_MapZlibError(inflateInit(context)); -} - -static SECStatus -ssl3_DeflateCompress(void *void_context, unsigned char *out, int *out_len, - int maxout, const unsigned char *in, int inlen) -{ - z_stream *context = void_context; - - if (!inlen) { - *out_len = 0; - return SECSuccess; - } - - context->next_in = (unsigned char *)in; - context->avail_in = inlen; - context->next_out = out; - context->avail_out = maxout; - if (deflate(context, Z_SYNC_FLUSH) != Z_OK) { - return SECFailure; - } - if (context->avail_out == 0) { - /* We ran out of space! */ - SSL_TRC(3, ("%d: SSL3[%d] Ran out of buffer while compressing", - SSL_GETPID())); - return SECFailure; - } - - *out_len = maxout - context->avail_out; - return SECSuccess; -} - -static SECStatus -ssl3_DeflateDecompress(void *void_context, unsigned char *out, int *out_len, - int maxout, const unsigned char *in, int inlen) -{ - z_stream *context = void_context; - - if (!inlen) { - *out_len = 0; - return SECSuccess; + rv = ssl3_SetupPendingCipherSpec(ss, CipherSpecRead, suiteDef, + &ss->ssl3.prSpec); + if (rv != SECSuccess) { + goto loser; } - - context->next_in = (unsigned char *)in; - context->avail_in = inlen; - context->next_out = out; - context->avail_out = maxout; - if (inflate(context, Z_SYNC_FLUSH) != Z_OK) { - PORT_SetError(SSL_ERROR_DECOMPRESSION_FAILURE); - return SECFailure; + rv = ssl3_SetupPendingCipherSpec(ss, CipherSpecWrite, suiteDef, + &ss->ssl3.pwSpec); + if (rv != SECSuccess) { + goto loser; } - *out_len = maxout - context->avail_out; - return SECSuccess; -} - -static SECStatus -ssl3_DestroyCompressContext(void *void_context, PRBool unused) -{ - deflateEnd(void_context); - PORT_Free(void_context); - return SECSuccess; -} - -static SECStatus -ssl3_DestroyDecompressContext(void *void_context, PRBool unused) -{ - inflateEnd(void_context); - PORT_Free(void_context); + ssl_ReleaseSpecWriteLock(ss); /*******************************/ return SECSuccess; -} - -#endif /* NSS_SSL_ENABLE_ZLIB */ -/* Initialize the compression functions and contexts for the given - * CipherSpec. */ -static SECStatus -ssl3_InitCompressionContext(ssl3CipherSpec *pwSpec) -{ - /* Setup the compression functions */ - switch (pwSpec->compression_method) { - case ssl_compression_null: - pwSpec->compressor = NULL; - pwSpec->decompressor = NULL; - pwSpec->compressContext = NULL; - pwSpec->decompressContext = NULL; - pwSpec->destroyCompressContext = NULL; - pwSpec->destroyDecompressContext = NULL; - break; -#ifdef NSS_SSL_ENABLE_ZLIB - case ssl_compression_deflate: - pwSpec->compressor = ssl3_DeflateCompress; - pwSpec->decompressor = ssl3_DeflateDecompress; - pwSpec->compressContext = PORT_Alloc(SSL3_DEFLATE_CONTEXT_SIZE); - pwSpec->decompressContext = PORT_Alloc(SSL3_DEFLATE_CONTEXT_SIZE); - pwSpec->destroyCompressContext = ssl3_DestroyCompressContext; - pwSpec->destroyDecompressContext = ssl3_DestroyDecompressContext; - ssl3_DeflateInit(pwSpec->compressContext); - ssl3_InflateInit(pwSpec->decompressContext); - break; -#endif /* NSS_SSL_ENABLE_ZLIB */ - default: - PORT_Assert(0); - PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); - return SECFailure; - } - - return SECSuccess; +loser: + ssl_ReleaseSpecWriteLock(ss); + return SECFailure; } /* ssl3_BuildRecordPseudoHeader writes the SSL/TLS pseudo-header (the data @@ -1783,7 +1551,7 @@ ssl3_AESGCM(ssl3KeyMaterial *keys, /* See https://tools.ietf.org/html/rfc5288#section-3 for details of how the * nonce is formed. */ - memcpy(nonce, keys->write_iv, 4); + memcpy(nonce, keys->iv, 4); if (doDecrypt) { memcpy(nonce + 4, in, explicitNonceLen); in += explicitNonceLen; @@ -1812,10 +1580,10 @@ ssl3_AESGCM(ssl3KeyMaterial *keys, gcmParams.ulTagBits = tagSize * 8; if (doDecrypt) { - rv = PK11_Decrypt(keys->write_key, CKM_AES_GCM, ¶m, out, &uOutLen, + rv = PK11_Decrypt(keys->key, CKM_AES_GCM, ¶m, out, &uOutLen, maxout, in, inlen); } else { - rv = PK11_Encrypt(keys->write_key, CKM_AES_GCM, ¶m, out, &uOutLen, + rv = PK11_Encrypt(keys->key, CKM_AES_GCM, ¶m, out, &uOutLen, maxout, in, inlen); } *outlen += (int)uOutLen; @@ -1842,7 +1610,7 @@ ssl3_ChaCha20Poly1305(ssl3KeyMaterial *keys, PRBool doDecrypt, /* See * https://tools.ietf.org/html/draft-ietf-tls-chacha20-poly1305-04#section-2 * for details of how the nonce is formed. */ - PORT_Memcpy(nonce, keys->write_iv, 12); + PORT_Memcpy(nonce, keys->iv, 12); /* XOR the last 8 bytes of the IV with the sequence number. */ PORT_Assert(additionalDataLen >= 8); @@ -1861,10 +1629,10 @@ ssl3_ChaCha20Poly1305(ssl3KeyMaterial *keys, PRBool doDecrypt, aeadParams.ulTagLen = tagSize; if (doDecrypt) { - rv = PK11_Decrypt(keys->write_key, CKM_NSS_CHACHA20_POLY1305, ¶m, + rv = PK11_Decrypt(keys->key, CKM_NSS_CHACHA20_POLY1305, ¶m, out, &uOutLen, maxout, in, inlen); } else { - rv = PK11_Encrypt(keys->write_key, CKM_NSS_CHACHA20_POLY1305, ¶m, + rv = PK11_Encrypt(keys->key, CKM_NSS_CHACHA20_POLY1305, ¶m, out, &uOutLen, maxout, in, inlen); } *outlen = (int)uOutLen; @@ -1877,42 +1645,35 @@ ssl3_ChaCha20Poly1305(ssl3KeyMaterial *keys, PRBool doDecrypt, * Caller holds Spec write lock. */ static SECStatus -ssl3_InitPendingContexts(sslSocket *ss, ssl3CipherSpec *pwSpec) +ssl3_InitPendingContexts(sslSocket *ss, ssl3CipherSpec *spec) { - const ssl3BulkCipherDef *cipher_def; - PK11Context *serverContext = NULL; - PK11Context *clientContext = NULL; SECItem *param; CK_MECHANISM_TYPE mechanism; - CK_MECHANISM_TYPE mac_mech; + CK_ATTRIBUTE_TYPE mode; CK_ULONG macLength; SECItem iv; + int ivLen; SECItem mac_param; SSLCipherAlgorithm calg; PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss)); PORT_Assert(ss->opt.noLocks || ssl_HaveSpecWriteLock(ss)); - PORT_Assert(ss->ssl3.prSpec == ss->ssl3.pwSpec); - cipher_def = pwSpec->cipher_def; - macLength = pwSpec->mac_size; - calg = cipher_def->calg; + macLength = spec->macDef->mac_size; + calg = spec->cipherDef->calg; PORT_Assert(alg2Mech[calg].calg == calg); - pwSpec->client.write_mac_context = NULL; - pwSpec->server.write_mac_context = NULL; + spec->keyMaterial.macContext = NULL; - if (cipher_def->type == type_aead) { - pwSpec->encode = NULL; - pwSpec->decode = NULL; - pwSpec->encodeContext = NULL; - pwSpec->decodeContext = NULL; + if (spec->cipherDef->type == type_aead) { + spec->cipher = NULL; + spec->cipherContext = NULL; switch (calg) { case ssl_calg_aes_gcm: - pwSpec->aead = ssl3_AESGCM; + spec->aead = ssl3_AESGCM; break; case ssl_calg_chacha20: - pwSpec->aead = ssl3_ChaCha20Poly1305; + spec->aead = ssl3_ChaCha20Poly1305; break; default: PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); @@ -1925,21 +1686,13 @@ ssl3_InitPendingContexts(sslSocket *ss, ssl3CipherSpec *pwSpec) ** Now setup the MAC contexts, ** crypto contexts are setup below. */ - - mac_mech = pwSpec->mac_def->mmech; mac_param.data = (unsigned char *)&macLength; mac_param.len = sizeof(macLength); mac_param.type = 0; - pwSpec->client.write_mac_context = PK11_CreateContextBySymKey( - mac_mech, CKA_SIGN, pwSpec->client.write_mac_key, &mac_param); - if (pwSpec->client.write_mac_context == NULL) { - ssl_MapLowLevelError(SSL_ERROR_SYM_KEY_CONTEXT_FAILURE); - goto fail; - } - pwSpec->server.write_mac_context = PK11_CreateContextBySymKey( - mac_mech, CKA_SIGN, pwSpec->server.write_mac_key, &mac_param); - if (pwSpec->server.write_mac_context == NULL) { + spec->keyMaterial.macContext = PK11_CreateContextBySymKey( + spec->macDef->mmech, CKA_SIGN, spec->keyMaterial.macKey, &mac_param); + if (!spec->keyMaterial.macContext) { ssl_MapLowLevelError(SSL_ERROR_SYM_KEY_CONTEXT_FAILURE); goto fail; } @@ -1947,85 +1700,43 @@ ssl3_InitPendingContexts(sslSocket *ss, ssl3CipherSpec *pwSpec) /* ** Now setup the crypto contexts. */ - - pwSpec->encode = Null_Cipher; - pwSpec->decode = Null_Cipher; if (calg == ssl_calg_null) { + spec->cipher = Null_Cipher; return SECSuccess; } + + spec->cipher = (SSLCipher)PK11_CipherOp; mechanism = ssl3_Alg2Mech(calg); + mode = (spec->direction == CipherSpecWrite) ? CKA_ENCRYPT : CKA_DECRYPT; /* - * build the server context + * build the context */ - iv.data = pwSpec->server.write_iv; - iv.len = cipher_def->iv_size; + iv.data = spec->keyMaterial.iv; + iv.len = spec->cipherDef->iv_size; param = PK11_ParamFromIV(mechanism, &iv); - if (param == NULL) { + if (!param) { ssl_MapLowLevelError(SSL_ERROR_IV_PARAM_FAILURE); goto fail; } - serverContext = PK11_CreateContextBySymKey(mechanism, - (ss->sec.isServer ? CKA_ENCRYPT - : CKA_DECRYPT), - pwSpec->server.write_key, param); - iv.data = PK11_IVFromParam(mechanism, param, (int *)&iv.len); - if (iv.data) - PORT_Memcpy(pwSpec->server.write_iv, iv.data, iv.len); - SECITEM_FreeItem(param, PR_TRUE); - if (serverContext == NULL) { - ssl_MapLowLevelError(SSL_ERROR_SYM_KEY_CONTEXT_FAILURE); - goto fail; - } - - /* - * build the client context - */ - iv.data = pwSpec->client.write_iv; - iv.len = cipher_def->iv_size; - - param = PK11_ParamFromIV(mechanism, &iv); - if (param == NULL) { - ssl_MapLowLevelError(SSL_ERROR_IV_PARAM_FAILURE); - goto fail; + spec->cipherContext = PK11_CreateContextBySymKey(mechanism, mode, + spec->keyMaterial.key, + param); + iv.data = PK11_IVFromParam(mechanism, param, &ivLen); + if (iv.data) { + PORT_Assert(ivLen == spec->cipherDef->iv_size); + PORT_Memcpy(spec->keyMaterial.iv, iv.data, ivLen); } - clientContext = PK11_CreateContextBySymKey(mechanism, - (ss->sec.isServer ? CKA_DECRYPT - : CKA_ENCRYPT), - pwSpec->client.write_key, param); - iv.data = PK11_IVFromParam(mechanism, param, (int *)&iv.len); - if (iv.data) - PORT_Memcpy(pwSpec->client.write_iv, iv.data, iv.len); SECITEM_FreeItem(param, PR_TRUE); - if (clientContext == NULL) { + if (!spec->cipherContext) { ssl_MapLowLevelError(SSL_ERROR_SYM_KEY_CONTEXT_FAILURE); goto fail; } - pwSpec->encode = (SSLCipher)PK11_CipherOp; - pwSpec->decode = (SSLCipher)PK11_CipherOp; - - pwSpec->encodeContext = (ss->sec.isServer) ? serverContext : clientContext; - pwSpec->decodeContext = (ss->sec.isServer) ? clientContext : serverContext; - - serverContext = NULL; - clientContext = NULL; - - ssl3_InitCompressionContext(pwSpec); return SECSuccess; fail: - if (serverContext != NULL) - PK11_DestroyContext(serverContext, PR_TRUE); - if (pwSpec->client.write_mac_context != NULL) { - PK11_DestroyContext(pwSpec->client.write_mac_context, PR_TRUE); - pwSpec->client.write_mac_context = NULL; - } - if (pwSpec->server.write_mac_context != NULL) { - PK11_DestroyContext(pwSpec->server.write_mac_context, PR_TRUE); - pwSpec->server.write_mac_context = NULL; - } - + ssl_DestroyKeyMaterial(&spec->keyMaterial); return SECFailure; } @@ -2046,6 +1757,7 @@ ssl3_InitPendingCipherSpecs(sslSocket *ss, PK11SymKey *secret, PRBool derive) { PK11SymKey *masterSecret; ssl3CipherSpec *pwSpec; + ssl3CipherSpec *prSpec; SECStatus rv; PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss)); @@ -2053,9 +1765,9 @@ ssl3_InitPendingCipherSpecs(sslSocket *ss, PK11SymKey *secret, PRBool derive) ssl_GetSpecWriteLock(ss); /**************************************/ - PORT_Assert(ss->ssl3.prSpec == ss->ssl3.pwSpec); PORT_Assert(ss->ssl3.pwSpec); PORT_Assert(ss->ssl3.cwSpec->epoch == ss->ssl3.crSpec->epoch); + prSpec = ss->ssl3.prSpec; pwSpec = ss->ssl3.pwSpec; if (ss->ssl3.cwSpec->epoch == PR_UINT16_MAX) { @@ -2086,17 +1798,23 @@ ssl3_InitPendingCipherSpecs(sslSocket *ss, PK11SymKey *secret, PRBool derive) goto loser; } - pwSpec->master_secret = masterSecret; + prSpec->masterSecret = masterSecret; + pwSpec->masterSecret = PK11_ReferenceSymKey(masterSecret); + rv = ssl3_InitPendingContexts(ss, ss->ssl3.prSpec); + if (rv != SECSuccess) { + goto loser; + } + rv = ssl3_InitPendingContexts(ss, ss->ssl3.pwSpec); if (rv != SECSuccess) { goto loser; } /* With keys created, get ready to read and write records. */ - pwSpec->epoch = ss->ssl3.cwSpec->epoch + 1; - pwSpec->read_seq_num = pwSpec->write_seq_num = 0; + prSpec->seqNum = pwSpec->seqNum = 0; + prSpec->epoch = pwSpec->epoch = ss->ssl3.crSpec->epoch + 1; if (IS_DTLS(ss)) { - dtls_InitRecvdRecords(&pwSpec->recvdRecords); + dtls_InitRecvdRecords(&prSpec->recvdRecords); } ssl_ReleaseSpecWriteLock(ss); /******************************/ @@ -2138,7 +1856,6 @@ static const unsigned char mac_pad_2[60] = { static SECStatus ssl3_ComputeRecordMAC( ssl3CipherSpec *spec, - PRBool useServerMacKey, const unsigned char *header, unsigned int headerLen, const PRUint8 *input, @@ -2146,26 +1863,23 @@ ssl3_ComputeRecordMAC( unsigned char *outbuf, unsigned int *outLength) { - const ssl3MACDef *mac_def; + int macSize = spec->macDef->mac_size; SECStatus rv; PRINT_BUF(95, (NULL, "frag hash1: header", header, headerLen)); PRINT_BUF(95, (NULL, "frag hash1: input", input, inputLength)); - mac_def = spec->mac_def; - if (mac_def->mac == ssl_mac_null) { + if (macSize == 0) { *outLength = 0; return SECSuccess; } - PK11Context *mac_context = - (useServerMacKey ? spec->server.write_mac_context - : spec->client.write_mac_context); - rv = PK11_DigestBegin(mac_context); - rv |= PK11_DigestOp(mac_context, header, headerLen); - rv |= PK11_DigestOp(mac_context, input, inputLength); - rv |= PK11_DigestFinal(mac_context, outbuf, outLength, spec->mac_size); - PORT_Assert(rv != SECSuccess || *outLength == (unsigned)spec->mac_size); + PK11Context *context = spec->keyMaterial.macContext; + rv = PK11_DigestBegin(context); + rv |= PK11_DigestOp(context, header, headerLen); + rv |= PK11_DigestOp(context, input, inputLength); + rv |= PK11_DigestFinal(context, outbuf, outLength, macSize); + PORT_Assert(rv != SECSuccess || *outLength == (unsigned)macSize); PRINT_BUF(95, (NULL, "frag hash2: result", outbuf, *outLength)); @@ -2185,7 +1899,6 @@ ssl3_ComputeRecordMAC( static SECStatus ssl3_ComputeRecordMACConstantTime( ssl3CipherSpec *spec, - PRBool useServerMacKey, const unsigned char *header, unsigned int headerLen, const PRUint8 *input, @@ -2197,13 +1910,13 @@ ssl3_ComputeRecordMACConstantTime( CK_MECHANISM_TYPE macType; CK_NSS_MAC_CONSTANT_TIME_PARAMS params; SECItem param, inputItem, outputItem; + int macSize = spec->macDef->mac_size; SECStatus rv; - PK11SymKey *key; - PORT_Assert(inputLen >= spec->mac_size); + PORT_Assert(inputLen >= spec->macDef->mac_size); PORT_Assert(originalLen >= inputLen); - if (spec->mac_def->mac == ssl_mac_null) { + if (macSize == 0) { *outLen = 0; return SECSuccess; } @@ -2213,7 +1926,7 @@ ssl3_ComputeRecordMACConstantTime( macType = CKM_NSS_SSL3_MAC_CONSTANT_TIME; } - params.macAlg = spec->mac_def->mmech; + params.macAlg = spec->macDef->mmech; params.ulBodyTotalLen = originalLen; params.pHeader = (unsigned char *)header; /* const cast */ params.ulHeaderLen = headerLen; @@ -2230,19 +1943,14 @@ ssl3_ComputeRecordMACConstantTime( outputItem.len = *outLen; outputItem.type = 0; - key = spec->server.write_mac_key; - if (!useServerMacKey) { - key = spec->client.write_mac_key; - } - - rv = PK11_SignWithSymKey(key, macType, ¶m, &outputItem, &inputItem); + rv = PK11_SignWithSymKey(spec->keyMaterial.macKey, macType, ¶m, + &outputItem, &inputItem); if (rv != SECSuccess) { if (PORT_GetError() == SEC_ERROR_INVALID_ALGORITHM) { /* ssl3_ComputeRecordMAC() expects the MAC to have been removed * from the input length already. */ - return ssl3_ComputeRecordMAC(spec, useServerMacKey, - header, headerLen, - input, inputLen - spec->mac_size, + return ssl3_ComputeRecordMAC(spec, header, headerLen, + input, inputLen - macSize, outbuf, outLen); } @@ -2252,7 +1960,7 @@ ssl3_ComputeRecordMACConstantTime( return rv; } - PORT_Assert(outputItem.len == (unsigned)spec->mac_size); + PORT_Assert(outputItem.len == (unsigned)macSize); *outLen = outputItem.len; return rv; @@ -2288,16 +1996,15 @@ ssl3_ClientAuthTokenPresent(sslSessionID *sid) /* Caller must hold the spec read lock. */ SECStatus -ssl3_CompressMACEncryptRecord(ssl3CipherSpec *cwSpec, - PRBool isServer, - PRBool isDTLS, - PRBool capRecordVersion, - SSL3ContentType type, - const PRUint8 *pIn, - PRUint32 contentLen, - sslBuffer *wrBuf) -{ - const ssl3BulkCipherDef *cipher_def; +ssl3_MACEncryptRecord(ssl3CipherSpec *cwSpec, + PRBool isServer, + PRBool isDTLS, + PRBool capRecordVersion, + SSL3ContentType type, + const PRUint8 *pIn, + PRUint32 contentLen, + sslBuffer *wrBuf) +{ SECStatus rv; PRUint32 macLen = 0; PRUint32 fragLen; @@ -2306,16 +2013,14 @@ ssl3_CompressMACEncryptRecord(ssl3CipherSpec *cwSpec, unsigned char pseudoHeader[13]; unsigned int pseudoHeaderLen; - cipher_def = cwSpec->cipher_def; - - if (cipher_def->type == type_block && + if (cwSpec->cipherDef->type == type_block && cwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_1) { /* Prepend the per-record explicit IV using technique 2b from * RFC 4346 section 6.2.3.2: The IV is a cryptographically * strong random number XORed with the CBC residue from the previous * record. */ - ivLen = cipher_def->iv_size; + ivLen = cwSpec->cipherDef->iv_size; if (ivLen > wrBuf->space) { PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); return SECFailure; @@ -2325,7 +2030,7 @@ ssl3_CompressMACEncryptRecord(ssl3CipherSpec *cwSpec, ssl_MapLowLevelError(SSL_ERROR_GENERATE_RANDOM_FAILURE); return rv; } - rv = cwSpec->encode(cwSpec->encodeContext, + rv = cwSpec->cipher(cwSpec->cipherContext, wrBuf->buf, /* output */ (int *)&wrBuf->len, /* outlen */ ivLen, /* max outlen */ @@ -2337,24 +2042,14 @@ ssl3_CompressMACEncryptRecord(ssl3CipherSpec *cwSpec, } } - if (cwSpec->compressor) { - int outlen; - rv = cwSpec->compressor(cwSpec->compressContext, wrBuf->buf + ivLen, - &outlen, wrBuf->space - ivLen, pIn, contentLen); - if (rv != SECSuccess) - return rv; - pIn = wrBuf->buf + ivLen; - contentLen = outlen; - } - pseudoHeaderLen = ssl3_BuildRecordPseudoHeader( - pseudoHeader, cwSpec->epoch, cwSpec->write_seq_num, type, + pseudoHeader, cwSpec->epoch, cwSpec->seqNum, type, cwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_0, cwSpec->version, isDTLS, contentLen); PORT_Assert(pseudoHeaderLen <= sizeof(pseudoHeader)); - if (cipher_def->type == type_aead) { - const int nonceLen = cipher_def->explicit_nonce_size; - const int tagLen = cipher_def->tag_size; + if (cwSpec->cipherDef->type == type_aead) { + const int nonceLen = cwSpec->cipherDef->explicit_nonce_size; + const int tagLen = cwSpec->cipherDef->tag_size; if (nonceLen + contentLen + tagLen > wrBuf->space) { PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); @@ -2362,7 +2057,7 @@ ssl3_CompressMACEncryptRecord(ssl3CipherSpec *cwSpec, } rv = cwSpec->aead( - isServer ? &cwSpec->server : &cwSpec->client, + &cwSpec->keyMaterial, PR_FALSE, /* do encrypt */ wrBuf->buf, /* output */ (int *)&wrBuf->len, /* out len */ @@ -2374,10 +2069,12 @@ ssl3_CompressMACEncryptRecord(ssl3CipherSpec *cwSpec, return SECFailure; } } else { + int blockSize = cwSpec->cipherDef->block_size; + /* * Add the MAC */ - rv = ssl3_ComputeRecordMAC(cwSpec, isServer, pseudoHeader, + rv = ssl3_ComputeRecordMAC(cwSpec, pseudoHeader, pseudoHeaderLen, pIn, contentLen, wrBuf->buf + ivLen + contentLen, &macLen); if (rv != SECSuccess) { @@ -2393,16 +2090,16 @@ ssl3_CompressMACEncryptRecord(ssl3CipherSpec *cwSpec, * Pad the text (if we're doing a block cipher) * then Encrypt it */ - if (cipher_def->type == type_block) { + if (cwSpec->cipherDef->type == type_block) { unsigned char *pBuf; int padding_length; int i; - oddLen = contentLen % cipher_def->block_size; + oddLen = contentLen % blockSize; /* Assume blockSize is a power of two */ - padding_length = cipher_def->block_size - 1 - ((fragLen) & (cipher_def->block_size - 1)); + padding_length = blockSize - 1 - ((fragLen) & (blockSize - 1)); fragLen += padding_length + 1; - PORT_Assert((fragLen % cipher_def->block_size) == 0); + PORT_Assert((fragLen % blockSize) == 0); /* Pad according to TLS rules (also acceptable to SSL3). */ pBuf = &wrBuf->buf[ivLen + fragLen - 1]; @@ -2420,13 +2117,13 @@ ssl3_CompressMACEncryptRecord(ssl3CipherSpec *cwSpec, } if (oddLen) { p2Len += oddLen; - PORT_Assert((cipher_def->block_size < 2) || - (p2Len % cipher_def->block_size) == 0); + PORT_Assert((blockSize < 2) || + (p2Len % blockSize) == 0); memmove(wrBuf->buf + ivLen + p1Len, pIn + p1Len, oddLen); } if (p1Len > 0) { int cipherBytesPart1 = -1; - rv = cwSpec->encode(cwSpec->encodeContext, + rv = cwSpec->cipher(cwSpec->cipherContext, wrBuf->buf + ivLen, /* output */ &cipherBytesPart1, /* actual outlen */ p1Len, /* max outlen */ @@ -2441,7 +2138,7 @@ ssl3_CompressMACEncryptRecord(ssl3CipherSpec *cwSpec, } if (p2Len > 0) { int cipherBytesPart2 = -1; - rv = cwSpec->encode(cwSpec->encodeContext, + rv = cwSpec->cipher(cwSpec->cipherContext, wrBuf->buf + ivLen + p1Len, &cipherBytesPart2, /* output and actual outLen */ p2Len, /* max outlen */ @@ -2470,7 +2167,7 @@ ssl_InsertRecordHeader(const sslSocket *ss, ssl3CipherSpec *cwSpec, SECStatus rv; #ifndef UNSAFE_FUZZER_MODE - if (isTLS13 && cwSpec->cipher_def->calg != ssl_calg_null) { + if (isTLS13 && cwSpec->cipherDef->calg != ssl_calg_null) { rv = sslBuffer_AppendNumber(wrBuf, content_application_data, 1); } else #endif @@ -2493,7 +2190,7 @@ ssl_InsertRecordHeader(const sslSocket *ss, ssl3CipherSpec *cwSpec, if (rv != SECSuccess) { return SECFailure; } - rv = sslBuffer_AppendNumber(wrBuf, cwSpec->write_seq_num, 6); + rv = sslBuffer_AppendNumber(wrBuf, cwSpec->seqNum, 6); if (rv != SECSuccess) { return SECFailure; } @@ -2526,11 +2223,12 @@ ssl_ProtectRecord(sslSocket *ss, ssl3CipherSpec *cwSpec, PRBool isTLS13; SECStatus rv; + PORT_Assert(cwSpec->direction == CipherSpecWrite); PORT_Assert(SSL_BUFFER_LEN(wrBuf) == 0); - PORT_Assert(cwSpec->cipher_def->max_records <= RECORD_SEQ_MAX); - if (cwSpec->write_seq_num >= cwSpec->cipher_def->max_records) { + PORT_Assert(cwSpec->cipherDef->max_records <= RECORD_SEQ_MAX); + if (cwSpec->seqNum >= cwSpec->cipherDef->max_records) { SSL_TRC(3, ("%d: SSL[-]: write sequence number at limit 0x%0llx", - SSL_GETPID(), cwSpec->write_seq_num)); + SSL_GETPID(), cwSpec->seqNum)); PORT_SetError(SSL_ERROR_TOO_MANY_RECORDS); return SECFailure; } @@ -2552,9 +2250,9 @@ ssl_ProtectRecord(sslSocket *ss, ssl3CipherSpec *cwSpec, if (isTLS13) { rv = tls13_ProtectRecord(ss, cwSpec, type, pIn, contentLen, &protBuf); } else { - rv = ssl3_CompressMACEncryptRecord(cwSpec, ss->sec.isServer, - IS_DTLS(ss), capRecordVersion, type, - pIn, contentLen, &protBuf); + rv = ssl3_MACEncryptRecord(cwSpec, ss->sec.isServer, + IS_DTLS(ss), capRecordVersion, type, + pIn, contentLen, &protBuf); } #endif if (rv != SECSuccess) { @@ -2575,7 +2273,7 @@ ssl_ProtectRecord(sslSocket *ss, ssl3CipherSpec *cwSpec, PORT_Assert(0); /* Can't fail. */ return SECFailure; } - ++cwSpec->write_seq_num; + ++cwSpec->seqNum; return SECSuccess; } @@ -2594,8 +2292,8 @@ ssl_ProtectNextRecord(sslSocket *ss, ssl3CipherSpec *spec, contentLen = PR_MIN(nIn, MAX_FRAGMENT_LENGTH); spaceNeeded = contentLen + SSL3_BUFFER_FUDGE; if (spec->version >= SSL_LIBRARY_VERSION_TLS_1_1 && - spec->cipher_def->type == type_block) { - spaceNeeded += spec->cipher_def->iv_size; + spec->cipherDef->type == type_block) { + spaceNeeded += spec->cipherDef->iv_size; } if (spaceNeeded > SSL_BUFFER_SPACE(wrBuf)) { rv = sslBuffer_Grow(wrBuf, spaceNeeded); @@ -2692,7 +2390,10 @@ ssl3_SendRecord(sslSocket *ss, ** trying to send an alert. */ PR_ASSERT(type == content_alert); - ssl3_InitState(ss); + rv = ssl3_InitState(ss); + if (rv != SECSuccess) { + return SECFailure; + } } /* check for Token Presence */ @@ -2841,7 +2542,7 @@ ssl3_SendApplicationData(sslSocket *ss, const unsigned char *in, */ if (len > 1 && ss->opt.cbcRandomIV && ss->version < SSL_LIBRARY_VERSION_TLS_1_1 && - ss->ssl3.cwSpec->cipher_def->type == type_block /* CBC */) { + ss->ssl3.cwSpec->cipherDef->type == type_block /* CBC */) { splitNeeded = PR_TRUE; } @@ -3376,7 +3077,6 @@ static SECStatus ssl3_SendChangeCipherSpecs(sslSocket *ss) { PRUint8 change = change_cipher_spec_choice; - ssl3CipherSpec *pwSpec; SECStatus rv; PRInt32 sent; @@ -3405,26 +3105,18 @@ ssl3_SendChangeCipherSpecs(sslSocket *ss) /* swap the pending and current write specs. */ ssl_GetSpecWriteLock(ss); /**************************************/ - pwSpec = ss->ssl3.pwSpec; - ss->ssl3.pwSpec = ss->ssl3.cwSpec; - ss->ssl3.cwSpec = pwSpec; + ssl_CipherSpecRelease(ss->ssl3.cwSpec); + ss->ssl3.cwSpec = ss->ssl3.pwSpec; + ss->ssl3.pwSpec = NULL; SSL_TRC(3, ("%d: SSL3[%d] Set Current Write Cipher Suite to Pending", SSL_GETPID(), ss->fd)); - /* We need to free up the contexts, keys and certs ! */ - /* If we are really through with the old cipher spec - * (Both the read and write sides have changed) destroy it. - */ - if (ss->ssl3.prSpec == ss->ssl3.pwSpec) { - if (!IS_DTLS(ss)) { - ssl3_DestroyCipherSpec(ss->ssl3.pwSpec, PR_FALSE /*freeSrvName*/); - } else { - /* With DTLS, we need to set a holddown timer in case the final - * message got lost */ - rv = dtls_StartHolddownTimer(ss); - } + /* With DTLS, we need to set a holddown timer in case the final + * message got lost */ + if (IS_DTLS(ss) && ss->ssl3.crSpec->epoch == ss->ssl3.cwSpec->epoch) { + rv = dtls_StartHolddownTimer(ss); } ssl_ReleaseSpecWriteLock(ss); /**************************************/ @@ -3440,7 +3132,6 @@ ssl3_SendChangeCipherSpecs(sslSocket *ss) static SECStatus ssl3_HandleChangeCipherSpecs(sslSocket *ss, sslBuffer *buf) { - ssl3CipherSpec *prSpec; SSL3WaitState ws = ss->ssl3.hs.ws; SSL3ChangeCipherSpecChoice change; @@ -3483,24 +3174,17 @@ ssl3_HandleChangeCipherSpecs(sslSocket *ss, sslBuffer *buf) } buf->len = 0; + SSL_TRC(3, ("%d: SSL3[%d] Set Current Read Cipher Suite to Pending", + SSL_GETPID(), ss->fd)); /* Swap the pending and current read specs. */ ssl_GetSpecWriteLock(ss); /*************************************/ - prSpec = ss->ssl3.prSpec; + PORT_Assert(ss->ssl3.prSpec); + ssl_CipherSpecRelease(ss->ssl3.crSpec); + ss->ssl3.crSpec = ss->ssl3.prSpec; + ss->ssl3.prSpec = NULL; + ssl_ReleaseSpecWriteLock(ss); /*************************************/ - ss->ssl3.prSpec = ss->ssl3.crSpec; - ss->ssl3.crSpec = prSpec; ss->ssl3.hs.ws = wait_finished; - - SSL_TRC(3, ("%d: SSL3[%d] Set Current Read Cipher Suite to Pending", - SSL_GETPID(), ss->fd)); - - /* If we are really through with the old cipher prSpec - * (Both the read and write sides have changed) destroy it. - */ - if (ss->ssl3.prSpec == ss->ssl3.pwSpec) { - ssl3_DestroyCipherSpec(ss->ssl3.prSpec, PR_FALSE /*freeSrvName*/); - } - ssl_ReleaseSpecWriteLock(ss); /*************************************/ return SECSuccess; } @@ -3766,7 +3450,6 @@ ssl3_ComputeMasterSecret(sslSocket *ss, PK11SymKey *pms, { PORT_Assert(pms != NULL); PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss)); - PORT_Assert(ss->ssl3.prSpec == ss->ssl3.pwSpec); if (ssl3_ExtensionNegotiated(ss, ssl_extended_master_secret_xtn)) { return tls_ComputeExtendedMasterSecretInt(ss, pms, msp); @@ -3794,12 +3477,15 @@ static SECStatus ssl3_DeriveConnectionKeys(sslSocket *ss, PK11SymKey *masterSecret) { ssl3CipherSpec *pwSpec = ss->ssl3.pwSpec; + ssl3CipherSpec *prSpec = ss->ssl3.prSpec; + ssl3CipherSpec *clientSpec; + ssl3CipherSpec *serverSpec; unsigned char *cr = (unsigned char *)&ss->ssl3.hs.client_random; unsigned char *sr = (unsigned char *)&ss->ssl3.hs.server_random; PRBool isTLS = (PRBool)(ss->version > SSL_LIBRARY_VERSION_3_0); PRBool isTLS12 = (PRBool)(isTLS && ss->version >= SSL_LIBRARY_VERSION_TLS_1_2); - const ssl3BulkCipherDef *cipher_def = pwSpec->cipher_def; + const ssl3BulkCipherDef *cipher_def = pwSpec->cipherDef; PK11SlotInfo *slot = NULL; PK11SymKey *symKey = NULL; void *pwArg = ss->pkcs11PinArg; @@ -3816,21 +3502,26 @@ ssl3_DeriveConnectionKeys(sslSocket *ss, PK11SymKey *masterSecret) PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss)); PORT_Assert(ss->opt.noLocks || ssl_HaveSpecWriteLock(ss)); - PORT_Assert(ss->ssl3.prSpec == ss->ssl3.pwSpec); PORT_Assert(masterSecret); + /* These functions operate in terms of who is writing specs. */ + if (ss->sec.isServer) { + clientSpec = prSpec; + serverSpec = pwSpec; + } else { + clientSpec = pwSpec; + serverSpec = prSpec; + } + /* * generate the key material */ - key_material_params.ulMacSizeInBits = pwSpec->mac_size * BPB; - key_material_params.ulKeySizeInBits = cipher_def->secret_key_size * BPB; - key_material_params.ulIVSizeInBits = cipher_def->iv_size * BPB; if (cipher_def->type == type_block && - pwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_1) { + ss->version >= SSL_LIBRARY_VERSION_TLS_1_1) { /* Block ciphers in >= TLS 1.1 use a per-record, explicit IV. */ key_material_params.ulIVSizeInBits = 0; - memset(pwSpec->client.write_iv, 0, cipher_def->iv_size); - memset(pwSpec->server.write_iv, 0, cipher_def->iv_size); + PORT_Memset(clientSpec->keyMaterial.iv, 0, cipher_def->iv_size); + PORT_Memset(serverSpec->keyMaterial.iv, 0, cipher_def->iv_size); } key_material_params.bIsExport = PR_FALSE; @@ -3840,17 +3531,20 @@ ssl3_DeriveConnectionKeys(sslSocket *ss, PK11SymKey *masterSecret) key_material_params.RandomInfo.ulServerRandomLen = SSL3_RANDOM_LENGTH; key_material_params.pReturnedKeyMaterial = &returnedKeys; - returnedKeys.pIVClient = pwSpec->client.write_iv; - returnedKeys.pIVServer = pwSpec->server.write_iv; - keySize = cipher_def->key_size; - if (skipKeysAndIVs) { keySize = 0; - key_material_params.ulKeySizeInBits = 0; - key_material_params.ulIVSizeInBits = 0; returnedKeys.pIVClient = NULL; returnedKeys.pIVServer = NULL; + key_material_params.ulKeySizeInBits = 0; + key_material_params.ulIVSizeInBits = 0; + } else { + keySize = cipher_def->key_size; + returnedKeys.pIVClient = clientSpec->keyMaterial.iv; + returnedKeys.pIVServer = serverSpec->keyMaterial.iv; + key_material_params.ulKeySizeInBits = cipher_def->secret_key_size * BPB; + key_material_params.ulIVSizeInBits = cipher_def->iv_size * BPB; } + key_material_params.ulMacSizeInBits = pwSpec->macDef->mac_size * BPB; calg = cipher_def->calg; bulk_mechanism = ssl3_Alg2Mech(calg); @@ -3885,29 +3579,33 @@ ssl3_DeriveConnectionKeys(sslSocket *ss, PK11SymKey *masterSecret) slot = PK11_GetSlotFromKey(symKey); PK11_FreeSlot(slot); /* slot is held until the key is freed */ - pwSpec->client.write_mac_key = + clientSpec->keyMaterial.macKey = PK11_SymKeyFromHandle(slot, symKey, PK11_OriginDerive, - CKM_SSL3_SHA1_MAC, returnedKeys.hClientMacSecret, PR_TRUE, pwArg); - if (pwSpec->client.write_mac_key == NULL) { + CKM_SSL3_SHA1_MAC, returnedKeys.hClientMacSecret, + PR_TRUE, pwArg); + if (clientSpec->keyMaterial.macKey == NULL) { goto loser; /* loser sets err */ } - pwSpec->server.write_mac_key = + serverSpec->keyMaterial.macKey = PK11_SymKeyFromHandle(slot, symKey, PK11_OriginDerive, - CKM_SSL3_SHA1_MAC, returnedKeys.hServerMacSecret, PR_TRUE, pwArg); - if (pwSpec->server.write_mac_key == NULL) { + CKM_SSL3_SHA1_MAC, returnedKeys.hServerMacSecret, + PR_TRUE, pwArg); + if (serverSpec->keyMaterial.macKey == NULL) { goto loser; /* loser sets err */ } if (!skipKeysAndIVs) { - pwSpec->client.write_key = + clientSpec->keyMaterial.key = PK11_SymKeyFromHandle(slot, symKey, PK11_OriginDerive, - bulk_mechanism, returnedKeys.hClientKey, PR_TRUE, pwArg); - if (pwSpec->client.write_key == NULL) { + bulk_mechanism, returnedKeys.hClientKey, + PR_TRUE, pwArg); + if (clientSpec->keyMaterial.key == NULL) { goto loser; /* loser sets err */ } - pwSpec->server.write_key = + serverSpec->keyMaterial.key = PK11_SymKeyFromHandle(slot, symKey, PK11_OriginDerive, - bulk_mechanism, returnedKeys.hServerKey, PR_TRUE, pwArg); - if (pwSpec->server.write_key == NULL) { + bulk_mechanism, returnedKeys.hServerKey, + PR_TRUE, pwArg); + if (serverSpec->keyMaterial.key == NULL) { goto loser; /* loser sets err */ } } @@ -3915,8 +3613,7 @@ ssl3_DeriveConnectionKeys(sslSocket *ss, PK11SymKey *masterSecret) return SECSuccess; loser: - if (symKey) - PK11_FreeSymKey(symKey); + PK11_FreeSymKey(symKey); ssl_MapLowLevelError(SSL_ERROR_SESSION_KEY_GEN_FAILURE); return SECFailure; } @@ -4652,7 +4349,7 @@ ssl3_ComputeHandshakeHashes(sslSocket *ss, /* compute hashes for SSL3. */ unsigned char s[4]; - if (!spec->master_secret) { + if (!spec->masterSecret) { PORT_SetError(SSL_ERROR_RX_UNEXPECTED_HANDSHAKE); rv = SECFailure; goto loser; @@ -4668,10 +4365,9 @@ ssl3_ComputeHandshakeHashes(sslSocket *ss, PRINT_BUF(95, (NULL, "MD5 inner: sender", s, 4)); } - PRINT_BUF(95, (NULL, "MD5 inner: MAC Pad 1", mac_pad_1, - md5Pad)); + PRINT_BUF(95, (NULL, "MD5 inner: MAC Pad 1", mac_pad_1, md5Pad)); - rv |= PK11_DigestKey(md5, spec->master_secret); + rv |= PK11_DigestKey(md5, spec->masterSecret); rv |= PK11_DigestOp(md5, mac_pad_1, md5Pad); rv |= PK11_DigestFinal(md5, md5_inner, &outLength, MD5_LENGTH); PORT_Assert(rv != SECSuccess || outLength == MD5_LENGTH); @@ -4688,10 +4384,9 @@ ssl3_ComputeHandshakeHashes(sslSocket *ss, PRINT_BUF(95, (NULL, "SHA inner: sender", s, 4)); } - PRINT_BUF(95, (NULL, "SHA inner: MAC Pad 1", mac_pad_1, - shaPad)); + PRINT_BUF(95, (NULL, "SHA inner: MAC Pad 1", mac_pad_1, shaPad)); - rv |= PK11_DigestKey(sha, spec->master_secret); + rv |= PK11_DigestKey(sha, spec->masterSecret); rv |= PK11_DigestOp(sha, mac_pad_1, shaPad); rv |= PK11_DigestFinal(sha, sha_inner, &outLength, SHA1_LENGTH); PORT_Assert(rv != SECSuccess || outLength == SHA1_LENGTH); @@ -4703,12 +4398,11 @@ ssl3_ComputeHandshakeHashes(sslSocket *ss, PRINT_BUF(95, (NULL, "SHA inner: result", sha_inner, outLength)); - PRINT_BUF(95, (NULL, "MD5 outer: MAC Pad 2", mac_pad_2, - md5Pad)); + PRINT_BUF(95, (NULL, "MD5 outer: MAC Pad 2", mac_pad_2, md5Pad)); PRINT_BUF(95, (NULL, "MD5 outer: MD5 inner", md5_inner, MD5_LENGTH)); rv |= PK11_DigestBegin(md5); - rv |= PK11_DigestKey(md5, spec->master_secret); + rv |= PK11_DigestKey(md5, spec->masterSecret); rv |= PK11_DigestOp(md5, mac_pad_2, md5Pad); rv |= PK11_DigestOp(md5, md5_inner, MD5_LENGTH); } @@ -4723,12 +4417,11 @@ ssl3_ComputeHandshakeHashes(sslSocket *ss, PRINT_BUF(60, (NULL, "MD5 outer: result", hashes->u.s.md5, MD5_LENGTH)); if (!isTLS) { - PRINT_BUF(95, (NULL, "SHA outer: MAC Pad 2", mac_pad_2, - shaPad)); + PRINT_BUF(95, (NULL, "SHA outer: MAC Pad 2", mac_pad_2, shaPad)); PRINT_BUF(95, (NULL, "SHA outer: SHA inner", sha_inner, SHA1_LENGTH)); rv |= PK11_DigestBegin(sha); - rv |= PK11_DigestKey(sha, spec->master_secret); + rv |= PK11_DigestKey(sha, spec->masterSecret); rv |= PK11_DigestOp(sha, mac_pad_2, shaPad); rv |= PK11_DigestOp(sha, sha_inner, SHA1_LENGTH); } @@ -4811,7 +4504,6 @@ SECStatus ssl3_SendClientHello(sslSocket *ss, sslClientHelloType type) { sslSessionID *sid; - ssl3CipherSpec *cwSpec; SECStatus rv; int i; int length; @@ -4821,7 +4513,6 @@ ssl3_SendClientHello(sslSocket *ss, sslClientHelloType type) PRBool requestingResume = PR_FALSE, fallbackSCSV = PR_FALSE; PRBool unlockNeeded = PR_FALSE; sslBuffer extensionBuf = SSL_BUFFER_EMPTY; - unsigned numCompressionMethods; PRUint16 version; PRInt32 flags; unsigned int cookieLen = ss->ssl3.hs.cookie.len; @@ -4847,7 +4538,10 @@ ssl3_SendClientHello(sslSocket *ss, sslClientHelloType type) ClientHello, which isn't used in DTLS 1.3. */ cookieLen = 0; } else { - ssl3_InitState(ss); + rv = ssl3_InitState(ss); + if (rv != SECSuccess) { + return SECFailure; + } ssl3_RestartHandshakeHashes(ss); } @@ -5023,10 +4717,9 @@ ssl3_SendClientHello(sslSocket *ss, sslClientHelloType type) isTLS = (version > SSL_LIBRARY_VERSION_3_0); ssl_GetSpecWriteLock(ss); - cwSpec = ss->ssl3.cwSpec; - if (cwSpec->mac_def->mac == ssl_mac_null) { + if (ss->ssl3.cwSpec->macDef->mac == ssl_mac_null) { /* SSL records are not being MACed. */ - cwSpec->version = version; + ss->ssl3.cwSpec->version = version; } ssl_ReleaseSpecWriteLock(ss); @@ -5091,19 +4784,12 @@ ssl3_SendClientHello(sslSocket *ss, sslClientHelloType type) ++num_suites; } - /* count compression methods */ - numCompressionMethods = 0; - for (i = 0; i < ssl_compression_method_count; i++) { - if (ssl_CompressionEnabled(ss, ssl_compression_methods[i])) - numCompressionMethods++; - } - length = sizeof(SSL3ProtocolVersion) + SSL3_RANDOM_LENGTH + 1 + (sid->version >= SSL_LIBRARY_VERSION_TLS_1_3 ? 0 : sid->u.ssl3.sessionIDLength) + 2 + num_suites * sizeof(ssl3CipherSuite) + - 1 + numCompressionMethods; + 1 + 1 /* compression methods */; if (IS_DTLS(ss)) { length += 1 + cookieLen; } @@ -5217,17 +4903,14 @@ ssl3_SendClientHello(sslSocket *ss, sslClientHelloType type) goto loser; } - rv = ssl3_AppendHandshakeNumber(ss, numCompressionMethods, 1); + /* Compression methods */ + rv = ssl3_AppendHandshakeNumber(ss, 1, 1); if (rv != SECSuccess) { goto loser; /* err set by ssl3_AppendHandshake* */ } - for (i = 0; i < ssl_compression_method_count; i++) { - if (!ssl_CompressionEnabled(ss, ssl_compression_methods[i])) - continue; - rv = ssl3_AppendHandshakeNumber(ss, ssl_compression_methods[i], 1); - if (rv != SECSuccess) { - goto loser; /* err set by ssl3_AppendHandshake* */ - } + rv = ssl3_AppendHandshakeNumber(ss, ssl_compression_null, 1); + if (rv != SECSuccess) { + goto loser; /* err set by ssl3_AppendHandshake* */ } if (extensionBuf.len) { @@ -6450,7 +6133,6 @@ static SECStatus ssl3_HandleServerHello(sslSocket *ss, PRUint8 *b, PRUint32 length) { PRUint32 temp; - int i; int errCode = SSL_ERROR_RX_MALFORMED_SERVER_HELLO; SECStatus rv; SECItem sidBytes = { siBuffer, NULL, 0 }; @@ -6584,29 +6266,15 @@ ssl3_HandleServerHello(sslSocket *ss, PRUint8 *b, PRUint32 length) } if (ss->version < SSL_LIBRARY_VERSION_TLS_1_3) { - PRBool found = PR_FALSE; - /* find selected compression method in our list. */ rv = ssl3_ConsumeHandshakeNumber(ss, &temp, 1, &b, &length); if (rv != SECSuccess) { goto loser; /* alert has been sent */ } - for (i = 0; i < ssl_compression_method_count; i++) { - if (temp == ssl_compression_methods[i]) { - if (!ssl_CompressionEnabled(ss, ssl_compression_methods[i])) { - break; /* failure */ - } - found = PR_TRUE; - break; /* success */ - } - } - if (!found) { + if (temp != ssl_compression_null) { desc = handshake_failure; errCode = SSL_ERROR_NO_COMPRESSION_OVERLAP; goto alert_loser; } - ss->ssl3.hs.compression = (SSLCompressionMethod)temp; - } else { - ss->ssl3.hs.compression = ssl_compression_null; } /* Note that if !isTLS and the extra stuff is not extensions, we @@ -6729,7 +6397,7 @@ ssl3_HandleServerHelloPart2(sslSocket *ss, const SECItem *sidBytes, /* we need to call ssl3_SetupPendingCipherSpec here so we can check the * key exchange algorithm. */ - rv = ssl3_SetupPendingCipherSpec(ss); + rv = ssl3_SetupBothPendingCipherSpecs(ss); if (rv != SECSuccess) { goto alert_loser; /* error code is set. */ } @@ -7394,7 +7062,7 @@ ssl3_CompleteHandleCertificateRequest(sslSocket *ss, case SECFailure: default: send_no_certificate: - if (ss->ssl3.prSpec->version > SSL_LIBRARY_VERSION_3_0) { + if (ss->version > SSL_LIBRARY_VERSION_3_0) { ss->ssl3.sendEmptyCert = PR_TRUE; } else { (void)SSL3_SendAlert(ss, alert_warning, no_certificate); @@ -7425,7 +7093,7 @@ ssl3_CheckFalseStart(sslSocket *ss) * sufficiently strong that the attack can gain no advantage. * Therefore we always require an 80-bit cipher. */ ssl_GetSpecReadLock(ss); - maybeFalseStart = ss->ssl3.cwSpec->cipher_def->secret_key_size >= 10; + maybeFalseStart = ss->ssl3.cwSpec->cipherDef->secret_key_size >= 10; ssl_ReleaseSpecReadLock(ss); if (!maybeFalseStart) { @@ -8343,6 +8011,12 @@ ssl3_HandleClientHello(sslSocket *ss, PRUint8 *b, PRUint32 length) if (comps.len != 1 || comps.data[0] != ssl_compression_null) { goto alert_loser; } + } else { + /* Other versions need to include null somewhere. */ + if (comps.len < 1 || + !memchr(comps.data, ssl_compression_null, comps.len)) { + goto alert_loser; + } } if (!ssl3_ExtensionNegotiated(ss, ssl_renegotiation_info_xtn)) { @@ -8475,7 +8149,7 @@ ssl3_HandleClientHello(sslSocket *ss, PRUint8 *b, PRUint32 length) if (ss->version >= SSL_LIBRARY_VERSION_TLS_1_3) { rv = tls13_HandleClientHelloPart2(ss, &suites, sid, savedMsg, savedLen); } else { - rv = ssl3_HandleClientHelloPart2(ss, &suites, &comps, sid, + rv = ssl3_HandleClientHelloPart2(ss, &suites, sid, savedMsg, savedLen); } if (rv != SECSuccess) { @@ -8527,7 +8201,6 @@ ssl3_UnwrapMasterSecretServer(sslSocket *ss, sslSessionID *sid, PK11SymKey **ms) static SECStatus ssl3_HandleClientHelloPart2(sslSocket *ss, SECItem *suites, - SECItem *comps, sslSessionID *sid, const PRUint8 *msg, unsigned int len) @@ -8546,9 +8219,8 @@ ssl3_HandleClientHelloPart2(sslSocket *ss, goto alert_loser; } - /* If we already have a session for this client, be sure to pick the - ** same cipher suite and compression method we picked before. - ** This is not a loop, despite appearances. + /* If we already have a session for this client, be sure to pick the same + ** cipher suite we picked before. This is not a loop, despite appearances. */ if (sid) do { @@ -8557,18 +8229,6 @@ ssl3_HandleClientHelloPart2(sslSocket *ss, SSLVersionRange vrange = { ss->version, ss->version }; #endif - /* Check that the cached compression method is still enabled. */ - if (!ssl_CompressionEnabled(ss, sid->u.ssl3.compression)) - break; - - /* Check that the cached compression method is in the client's list */ - for (i = 0; i < comps->len; i++) { - if (comps->data[i] == sid->u.ssl3.compression) - break; - } - if (i == comps->len) - break; - suite = ss->cipherSuites; /* Find the entry for the cipher suite used in the cached session. */ for (j = ssl_V3_SUITES_IMPLEMENTED; j > 0; --j, ++suite) { @@ -8603,10 +8263,7 @@ ssl3_HandleClientHelloPart2(sslSocket *ss, goto alert_loser; } - /* Use the cached compression method. */ - ss->ssl3.hs.compression = - sid->u.ssl3.compression; - goto compression_found; + goto cipher_found; } } } while (0); @@ -8629,25 +8286,8 @@ ssl3_HandleClientHelloPart2(sslSocket *ss, goto alert_loser; } - /* Select a compression algorithm. */ - for (i = 0; i < comps->len; i++) { - SSLCompressionMethod method = (SSLCompressionMethod)comps->data[i]; - if (!ssl_CompressionEnabled(ss, method)) - continue; - for (j = 0; j < ssl_compression_method_count; j++) { - if (method == ssl_compression_methods[j]) { - ss->ssl3.hs.compression = ssl_compression_methods[j]; - goto compression_found; - } - } - } - errCode = SSL_ERROR_NO_COMPRESSION_OVERLAP; - /* null compression must be supported */ - goto alert_loser; - -compression_found: +cipher_found: suites->data = NULL; - comps->data = NULL; /* If there are any failures while processing the old sid, * we don't consider them to be errors. Instead, We just behave @@ -8660,8 +8300,7 @@ compression_found: PK11SymKey *masterSecret; if (sid->version != ss->version || - sid->u.ssl3.cipherSuite != ss->ssl3.hs.cipher_suite || - sid->u.ssl3.compression != ss->ssl3.hs.compression) { + sid->u.ssl3.cipherSuite != ss->ssl3.hs.cipher_suite) { break; /* not an error */ } @@ -8724,8 +8363,6 @@ compression_found: /* * Old SID passed all tests, so resume this old session. - * - * XXX make sure compression still matches */ SSL_AtomicIncrementLong(&ssl3stats.hch_sid_cache_hits); if (ss->statelessResume) @@ -8912,7 +8549,10 @@ ssl3_HandleV2ClientHello(sslSocket *ss, unsigned char *buffer, int length, goto loser; } - ssl3_InitState(ss); + rv = ssl3_InitState(ss); + if (rv != SECSuccess) { + goto loser; + } ssl3_RestartHandshakeHashes(ss); if (ss->ssl3.hs.ws != wait_client_hello) { @@ -9042,8 +8682,6 @@ suite_found: goto alert_loser; } - ss->ssl3.hs.compression = ssl_compression_null; - rv = ssl3_SelectServerCert(ss); if (rv != SECSuccess) { errCode = PORT_GetError(); @@ -9176,7 +8814,7 @@ ssl3_SendServerHello(sslSocket *ss) goto loser; /* err set by AppendHandshake. */ } if (ss->version < SSL_LIBRARY_VERSION_TLS_1_3) { - rv = ssl3_AppendHandshakeNumber(ss, ss->ssl3.hs.compression, 1); + rv = ssl3_AppendHandshakeNumber(ss, ssl_compression_null, 1); if (rv != SECSuccess) { goto loser; /* err set by AppendHandshake. */ } @@ -9189,9 +8827,9 @@ ssl3_SendServerHello(sslSocket *ss) } if (ss->version < SSL_LIBRARY_VERSION_TLS_1_3) { - rv = ssl3_SetupPendingCipherSpec(ss); + rv = ssl3_SetupBothPendingCipherSpecs(ss); if (rv != SECSuccess) { - goto loser; /* err set by ssl3_SetupPendingCipherSpec */ + goto loser; /* err set */ } } @@ -9663,9 +9301,9 @@ ssl3_GenerateRSAPMS(sslSocket *ss, ssl3CipherSpec *spec, ** slot already hold the SpecWriteLock. */ PORT_Assert(ss->opt.noLocks || ssl_HaveSpecWriteLock(ss)); - PORT_Assert(ss->ssl3.prSpec == ss->ssl3.pwSpec); + PORT_Assert(ss->ssl3.prSpec->epoch == ss->ssl3.pwSpec->epoch); - calg = spec->cipher_def->calg; + calg = spec->cipherDef->calg; /* First get an appropriate slot. */ mechanism_array[0] = CKM_SSL3_PRE_MASTER_KEY_GEN; @@ -9733,7 +9371,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); + PORT_Assert(ss->ssl3.prSpec->epoch == ss->ssl3.pwSpec->epoch); enc_pms.data = b; enc_pms.len = length; @@ -10027,7 +9665,7 @@ ssl3_SendNewSessionTicket(sslSocket *ss) NewSessionTicket nticket = { 0 }; rv = ssl3_EncodeSessionTicket(ss, &nticket, NULL, 0, - ss->ssl3.pwSpec->master_secret, &ticket); + ss->ssl3.pwSpec->masterSecret, &ticket); if (rv != SECSuccess) goto loser; @@ -10865,8 +10503,8 @@ ssl3_ComputeTLSFinished(sslSocket *ss, ssl3CipherSpec *spec, PK11Context *prf_context; unsigned int retLen; - PORT_Assert(spec->master_secret); - if (!spec->master_secret) { + PORT_Assert(spec->masterSecret); + if (!spec->masterSecret) { PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); return SECFailure; } @@ -10881,7 +10519,7 @@ ssl3_ComputeTLSFinished(sslSocket *ss, ssl3CipherSpec *spec, param.data = (unsigned char *)&tls_mac_params; param.len = sizeof(tls_mac_params); prf_context = PK11_CreateContextBySymKey(CKM_TLS_MAC, CKA_SIGN, - spec->master_secret, ¶m); + spec->masterSecret, ¶m); if (!prf_context) return SECFailure; @@ -10912,8 +10550,8 @@ ssl3_TLSPRFWithMasterSecret(sslSocket *ss, ssl3CipherSpec *spec, unsigned int retLen; SECStatus rv; - if (!spec->master_secret) { - PORT_Assert(spec->master_secret); + if (!spec->masterSecret) { + PORT_Assert(spec->masterSecret); PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); return SECFailure; } @@ -10928,7 +10566,7 @@ ssl3_TLSPRFWithMasterSecret(sslSocket *ss, ssl3CipherSpec *spec, mech = CKM_NSS_TLS_PRF_GENERAL_SHA256; } prf_context = PK11_CreateContextBySymKey(mech, CKA_SIGN, - spec->master_secret, ¶m); + spec->masterSecret, ¶m); if (!prf_context) return SECFailure; @@ -11105,7 +10743,7 @@ ssl3_SendFinished(sslSocket *ss, PRInt32 flags) goto fail; /* error code set by ssl3_FlushHandshake */ } - ssl3_RecordKeyLog(ss, "CLIENT_RANDOM", ss->ssl3.cwSpec->master_secret); + ssl3_RecordKeyLog(ss, "CLIENT_RANDOM", ss->ssl3.cwSpec->masterSecret); return SECSuccess; @@ -11348,7 +10986,7 @@ xmit_loser: } if (sid->cached == never_cached && !ss->opt.noCache) { - rv = ssl3_FillInCachedSID(ss, sid, ss->ssl3.crSpec->master_secret); + rv = ssl3_FillInCachedSID(ss, sid, ss->ssl3.crSpec->masterSecret); /* If the wrap failed, we don't cache the sid. * The connection continues normally however. @@ -11378,7 +11016,6 @@ ssl3_FillInCachedSID(sslSocket *ss, sslSessionID *sid, PK11SymKey *secret) /* fill in the sid */ sid->u.ssl3.cipherSuite = ss->ssl3.hs.cipher_suite; - sid->u.ssl3.compression = ss->ssl3.hs.compression; sid->u.ssl3.policy = ss->ssl3.policy; sid->version = ss->version; sid->authType = ss->sec.authType; @@ -12086,7 +11723,7 @@ ssl3_UnprotectRecord(sslSocket *ss, SSL3Ciphertext *cText, sslBuffer *plaintext, SSL3AlertDescription *alert) { - const ssl3BulkCipherDef *cipher_def = spec->cipher_def; + const ssl3BulkCipherDef *cipher_def = spec->cipherDef; PRBool isTLS; unsigned int good; unsigned int ivLen = 0; @@ -12101,8 +11738,10 @@ ssl3_UnprotectRecord(sslSocket *ss, unsigned int hashBytes = MAX_MAC_LENGTH + 1; SECStatus rv; + PORT_Assert(spec->direction == CipherSpecRead); + good = ~0U; - minLength = spec->mac_size; + minLength = spec->macDef->mac_size; if (cipher_def->type == type_block) { /* CBC records have a padding length byte at the end. */ minLength++; @@ -12144,7 +11783,7 @@ ssl3_UnprotectRecord(sslSocket *ss, * the block it doesn't matter. The decryption of the next block * depends only on the ciphertext of the IV block. */ - rv = spec->decode(spec->decodeContext, iv, &decoded, + rv = spec->cipher(spec->cipherContext, iv, &decoded, sizeof(iv), cText->buf->buf, ivLen); good &= SECStatusToMask(rv); @@ -12172,18 +11811,17 @@ ssl3_UnprotectRecord(sslSocket *ss, cipher_def->tag_size; headerLen = ssl3_BuildRecordPseudoHeader( header, spec->epoch, - IS_DTLS(ss) ? cText->seq_num : spec->read_seq_num, + IS_DTLS(ss) ? cText->seq_num : spec->seqNum, rType, isTLS, cText->version, IS_DTLS(ss), decryptedLen); PORT_Assert(headerLen <= sizeof(header)); - rv = spec->aead( - ss->sec.isServer ? &spec->client : &spec->server, - PR_TRUE, /* do decrypt */ - plaintext->buf, /* out */ - (int *)&plaintext->len, /* outlen */ - plaintext->space, /* maxout */ - cText->buf->buf, /* in */ - cText->buf->len, /* inlen */ - header, headerLen); + rv = spec->aead(&spec->keyMaterial, + PR_TRUE, /* do decrypt */ + plaintext->buf, /* out */ + (int *)&plaintext->len, /* outlen */ + plaintext->space, /* maxout */ + cText->buf->buf, /* in */ + cText->buf->len, /* inlen */ + header, headerLen); if (rv != SECSuccess) { good = 0; } @@ -12194,8 +11832,8 @@ ssl3_UnprotectRecord(sslSocket *ss, } /* decrypt from cText buf to plaintext. */ - rv = spec->decode( - spec->decodeContext, plaintext->buf, (int *)&plaintext->len, + rv = spec->cipher( + spec->cipherContext, plaintext->buf, (int *)&plaintext->len, plaintext->space, cText->buf->buf + ivLen, cText->buf->len - ivLen); if (rv != SECSuccess) { goto decrypt_loser; @@ -12208,7 +11846,7 @@ ssl3_UnprotectRecord(sslSocket *ss, /* If it's a block cipher, check and strip the padding. */ if (cipher_def->type == type_block) { const unsigned int blockSize = cipher_def->block_size; - const unsigned int macSize = spec->mac_size; + const unsigned int macSize = spec->macDef->mac_size; if (!isTLS) { good &= SECStatusToMask(ssl_RemoveSSLv3CBCPadding( @@ -12222,31 +11860,31 @@ ssl3_UnprotectRecord(sslSocket *ss, /* compute the MAC */ headerLen = ssl3_BuildRecordPseudoHeader( header, spec->epoch, - IS_DTLS(ss) ? cText->seq_num : spec->read_seq_num, + IS_DTLS(ss) ? cText->seq_num : spec->seqNum, rType, isTLS, cText->version, IS_DTLS(ss), - plaintext->len - spec->mac_size); + plaintext->len - spec->macDef->mac_size); PORT_Assert(headerLen <= sizeof(header)); if (cipher_def->type == type_block) { rv = ssl3_ComputeRecordMACConstantTime( - spec, (PRBool)(!ss->sec.isServer), header, headerLen, + spec, header, headerLen, plaintext->buf, plaintext->len, originalLen, hash, &hashBytes); ssl_CBCExtractMAC(plaintext, originalLen, givenHashBuf, - spec->mac_size); + spec->macDef->mac_size); givenHash = givenHashBuf; /* plaintext->len will always have enough space to remove the MAC * because in ssl_Remove{SSLv3|TLS}CBCPadding we only adjust * plaintext->len if the result has enough space for the MAC and we * tested the unadjusted size against minLength, above. */ - plaintext->len -= spec->mac_size; + plaintext->len -= spec->macDef->mac_size; } else { /* This is safe because we checked the minLength above. */ - plaintext->len -= spec->mac_size; + plaintext->len -= spec->macDef->mac_size; rv = ssl3_ComputeRecordMAC( - spec, (PRBool)(!ss->sec.isServer), header, headerLen, + spec, header, headerLen, plaintext->buf, plaintext->len, hash, &hashBytes); /* We can read the MAC directly from the record because its location @@ -12256,8 +11894,8 @@ ssl3_UnprotectRecord(sslSocket *ss, good &= SECStatusToMask(rv); - if (hashBytes != (unsigned)spec->mac_size || - NSS_SecureMemcmp(givenHash, hash, spec->mac_size) != 0) { + if (hashBytes != (unsigned)spec->macDef->mac_size || + NSS_SecureMemcmp(givenHash, hash, spec->macDef->mac_size) != 0) { /* We're allowed to leak whether or not the MAC check was correct */ good = 0; } @@ -12274,68 +11912,6 @@ ssl3_UnprotectRecord(sslSocket *ss, } static SECStatus -ssl3_Decompress(sslSocket *ss, ssl3CipherSpec *crSpec, - sslBuffer *plaintext, /* Compressed */ - sslBuffer *databuf /* Uncompressed, outparam */) -{ - SECStatus rv; - - PORT_Assert(ss->version < SSL_LIBRARY_VERSION_TLS_1_3); - - if (databuf->space < plaintext->len + SSL3_COMPRESSION_MAX_EXPANSION) { - rv = sslBuffer_Grow( - databuf, plaintext->len + SSL3_COMPRESSION_MAX_EXPANSION); - if (rv != SECSuccess) { - SSL_DBG(("%d: SSL3[%d]: HandleRecord, tried to get %d bytes", - SSL_GETPID(), ss->fd, - plaintext->len + - SSL3_COMPRESSION_MAX_EXPANSION)); - /* sslBuffer_Grow has set a memory error code. */ - /* Perhaps we should send an alert. (but we have no memory!) */ - return SECFailure; - } - } - - rv = crSpec->decompressor(crSpec->decompressContext, - databuf->buf, - (int *)&databuf->len, - databuf->space, - plaintext->buf, - plaintext->len); - - if (rv != SECSuccess) { - int err = ssl_MapLowLevelError(SSL_ERROR_DECOMPRESSION_FAILURE); - SSL3_SendAlert(ss, alert_fatal, - (crSpec->version > SSL_LIBRARY_VERSION_3_0) ? decompression_failure : bad_record_mac); - - /* There appears to be a bug with (at least) Apache + OpenSSL where - * resumed SSLv3 connections don't actually use compression. See - * comments 93-95 of - * https://bugzilla.mozilla.org/show_bug.cgi?id=275744 - * - * So, if we get a decompression error, and the record appears to - * be already uncompressed, then we return a more specific error - * code to hopefully save somebody some debugging time in the - * future. - */ - if (plaintext->len >= 4) { - unsigned int len = ((unsigned int)plaintext->buf[1] << 16) | - ((unsigned int)plaintext->buf[2] << 8) | - (unsigned int)plaintext->buf[3]; - if (len == plaintext->len - 4) { - /* This appears to be uncompressed already */ - err = SSL_ERROR_RX_UNEXPECTED_UNCOMPRESSED_RECORD; - } - } - - PORT_SetError(err); - return SECFailure; - } - - return SECSuccess; -} - -static SECStatus ssl3_HandleNonApplicationData(sslSocket *ss, SSL3ContentType rType, DTLSEpoch epoch, sslSequenceNumber seqNum, sslBuffer *databuf) @@ -12421,7 +11997,7 @@ ssl3_GetCipherSpec(sslSocket *ss, sslSequenceNumber seq) return NULL; } -/* if cText is non-null, then decipher, check MAC, and decompress the +/* if cText is non-null, then decipher and check the MAC of the * SSL record from cText->buf (typically gs->inbuf) * into databuf (typically gs->buf), and any previous contents of databuf * is lost. Then handle databuf according to its SSL record type, @@ -12431,8 +12007,8 @@ ssl3_GetCipherSpec(sslSocket *ss, sslSequenceNumber seq) * checked, and is already sitting in databuf. It is processed as an SSL * Handshake message. * - * DOES NOT process the decrypted/decompressed application data. - * On return, databuf contains the decrypted/decompressed record. + * DOES NOT process the decrypted application data. + * On return, databuf contains the decrypted record. * * Called from ssl3_GatherCompleteHandshake * ssl3_RestartHandshakeAfterCertReq @@ -12454,14 +12030,16 @@ ssl3_HandleRecord(sslSocket *ss, SSL3Ciphertext *cText, sslBuffer *databuf) PRBool outOfOrderSpec = PR_FALSE; SSL3ContentType rType; sslBuffer *plaintext; - sslBuffer temp_buf = SSL_BUFFER_EMPTY; /* for decompression */ SSL3AlertDescription alert = internal_error; PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss)); if (!ss->ssl3.initialized) { ssl_GetSSL3HandshakeLock(ss); - ssl3_InitState(ss); + rv = ssl3_InitState(ss); ssl_ReleaseSSL3HandshakeLock(ss); + if (rv != SECSuccess) { + return SECFailure; + } } /* check for Token Presence */ @@ -12508,9 +12086,9 @@ ssl3_HandleRecord(sslSocket *ss, SSL3Ciphertext *cText, sslBuffer *databuf) return SECSuccess; } } else { - seqNum = spec->read_seq_num + 1; + seqNum = spec->seqNum + 1; } - if (seqNum >= spec->cipher_def->max_records) { + if (seqNum >= spec->cipherDef->max_records) { ssl_ReleaseSpecReadLock(ss); /*****************************/ SSL_TRC(3, ("%d: SSL[%d]: read sequence number at limit 0x%0llx", SSL_GETPID(), ss->fd, seqNum)); @@ -12518,13 +12096,7 @@ ssl3_HandleRecord(sslSocket *ss, SSL3Ciphertext *cText, sslBuffer *databuf) return SECFailure; } - /* If we will be decompressing the buffer we need to decrypt somewhere - * other than into databuf */ - if (spec->decompressor) { - plaintext = &temp_buf; - } else { - plaintext = databuf; - } + plaintext = databuf; plaintext->len = 0; /* filled in by Unprotect call below. */ /* We're waiting for another ClientHello, which will appear unencrypted. @@ -12560,7 +12132,7 @@ ssl3_HandleRecord(sslSocket *ss, SSL3Ciphertext *cText, sslBuffer *databuf) * because we still hold the spec read lock. Instead, if they * return SECFailure, they set *alert to the alert to be sent. */ if (spec->version < SSL_LIBRARY_VERSION_TLS_1_3 || - spec->cipher_def->calg == ssl_calg_null) { + spec->cipherDef->calg == ssl_calg_null) { /* Unencrypted TLS 1.3 records use the pre-TLS 1.3 format. */ rv = ssl3_UnprotectRecord(ss, spec, cText, plaintext, &alert); } else { @@ -12573,9 +12145,6 @@ ssl3_HandleRecord(sslSocket *ss, SSL3Ciphertext *cText, sslBuffer *databuf) SSL_DBG(("%d: SSL3[%d]: decryption failed", SSL_GETPID(), ss->fd)); - /* Clear the temp buffer used for decompression upon failure. */ - sslBuffer_Clear(&temp_buf); - if (IS_DTLS(ss) || (ss->sec.isServer && ss->ssl3.hs.zeroRttIgnore == ssl_0rtt_ignore_trial)) { @@ -12593,7 +12162,7 @@ ssl3_HandleRecord(sslSocket *ss, SSL3Ciphertext *cText, sslBuffer *databuf) } /* SECSuccess */ - spec->read_seq_num = PR_MAX(spec->read_seq_num, seqNum); + spec->seqNum = PR_MAX(spec->seqNum, seqNum); if (IS_DTLS(ss)) { dtls_RecordSetRecvd(&spec->recvdRecords, seqNum); } @@ -12615,21 +12184,7 @@ ssl3_HandleRecord(sslSocket *ss, SSL3Ciphertext *cText, sslBuffer *databuf) return dtls13_HandleOutOfEpochRecord(ss, spec, rType, databuf); } - /* possibly decompress the record. If we aren't using compression then - * plaintext == databuf and so the uncompressed data is already in - * databuf. */ - if (spec->decompressor) { - rv = ssl3_Decompress(ss, spec, plaintext, databuf); - sslBuffer_Clear(&temp_buf); - if (rv != SECSuccess) { - return SECFailure; - } - } - - /* - ** Check the length again (this is checking the post-decompressed - ** limit). - */ + /* Check the length of the plaintext. */ if (isTLS && databuf->len > MAX_FRAGMENT_LENGTH) { SSL3_SendAlert(ss, alert_fatal, record_overflow); PORT_SetError(SSL_ERROR_RX_RECORD_TOO_LONG); @@ -12670,41 +12225,6 @@ ssl_InitSecState(sslSecurityInfo *sec) sec->keaGroup = NULL; } -/* Called from ssl3_InitState, immediately below. */ -/* Caller must hold the SpecWriteLock. */ -void -ssl3_InitCipherSpec(ssl3CipherSpec *spec) -{ - spec->cipher_def = ssl_GetBulkCipherDefById(cipher_null); - spec->mac_def = ssl_GetMacDefByAlg(ssl_mac_null); - spec->encode = Null_Cipher; - spec->decode = Null_Cipher; - spec->compressor = NULL; - spec->decompressor = NULL; - spec->destroyCompressContext = NULL; - spec->destroyDecompressContext = NULL; - spec->mac_size = 0; - spec->master_secret = NULL; - - spec->client.write_key = NULL; - spec->client.write_mac_key = NULL; - spec->client.write_mac_context = NULL; - - spec->server.write_key = NULL; - spec->server.write_mac_key = NULL; - spec->server.write_mac_context = NULL; - - spec->write_seq_num = 0; - spec->read_seq_num = 0; - spec->epoch = 0; - - spec->refCt = 128; /* Arbitrarily high number to prevent - * non-TLS 1.3 cipherSpecs from being - * GCed. This will be overwritten with - * a valid refCt for TLS 1.3. */ - dtls_InitRecvdRecords(&spec->recvdRecords); -} - /* Called from: ssl3_SendRecord ** ssl3_SendClientHello() ** ssl3_HandleV2ClientHello() @@ -12712,25 +12232,31 @@ ssl3_InitCipherSpec(ssl3CipherSpec *spec) ** ** This function should perhaps acquire and release the SpecWriteLock. */ -void +SECStatus ssl3_InitState(sslSocket *ss) { + SECStatus rv; + PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss)); - if (ss->ssl3.initialized) - return; /* Function should be idempotent */ + if (ss->ssl3.initialized) { + return SECSuccess; /* Function should be idempotent */ + } ss->ssl3.policy = SSL_ALLOWED; ssl_InitSecState(&ss->sec); ssl_GetSpecWriteLock(ss); - ss->ssl3.crSpec = ss->ssl3.cwSpec = &ss->ssl3.specs[0]; - ss->ssl3.prSpec = ss->ssl3.pwSpec = &ss->ssl3.specs[1]; - ssl3_InitCipherSpec(ss->ssl3.crSpec); - ssl3_InitCipherSpec(ss->ssl3.prSpec); - ss->ssl3.crSpec->version = ss->ssl3.prSpec->version = ss->vrange.max; + PR_INIT_CLIST(&ss->ssl3.hs.cipherSpecs); + rv = ssl_SetupNullCipherSpec(ss, CipherSpecRead); + rv |= ssl_SetupNullCipherSpec(ss, CipherSpecWrite); + ss->ssl3.pwSpec = ss->ssl3.prSpec = NULL; ssl_ReleaseSpecWriteLock(ss); + if (rv != SECSuccess) { + /* Rely on ssl_CreateNullCipherSpec() to set error code. */ + return SECFailure; + } ss->ssl3.hs.sendingSCSV = PR_FALSE; ss->ssl3.hs.preliminaryInfo = 0; @@ -12757,7 +12283,6 @@ ssl3_InitState(sslSocket *ss) ss->ssl3.hs.serverHsTrafficSecret = NULL; ss->ssl3.hs.clientTrafficSecret = NULL; ss->ssl3.hs.serverTrafficSecret = NULL; - PR_INIT_CLIST(&ss->ssl3.hs.cipherSpecs); PORT_Assert(!ss->ssl3.hs.messages.buf && !ss->ssl3.hs.messages.space); ss->ssl3.hs.messages.buf = NULL; @@ -12772,6 +12297,7 @@ ssl3_InitState(sslSocket *ss) ssl_FilterSupportedGroups(ss); ss->ssl3.initialized = PR_TRUE; + return SECSuccess; } /* record the export policy for this cipher suite */ @@ -13103,10 +12629,6 @@ ssl3_DestroySSL3Info(sslSocket *ss) SECITEM_FreeItem(&ss->ssl3.hs.newSessionTicket.ticket, PR_FALSE); SECITEM_FreeItem(&ss->ssl3.hs.srvVirtName, PR_FALSE); - /* free up the CipherSpecs */ - ssl3_DestroyCipherSpec(&ss->ssl3.specs[0], PR_TRUE /*freeSrvName*/); - ssl3_DestroyCipherSpec(&ss->ssl3.specs[1], PR_TRUE /*freeSrvName*/); - /* Destroy the DTLS data */ if (IS_DTLS(ss)) { dtls_FreeHandshakeMessages(&ss->ssl3.hs.lastMessageFlight); diff --git a/lib/ssl/ssl3exthandle.c b/lib/ssl/ssl3exthandle.c index b52b79a4e..96060d14e 100644 --- a/lib/ssl/ssl3exthandle.c +++ b/lib/ssl/ssl3exthandle.c @@ -654,7 +654,7 @@ ssl3_ClientHandleStatusRequestXtn(const sslSocket *ss, TLSExtensionData *xtnData } PRUint32 ssl_ticket_lifetime = 2 * 24 * 60 * 60; /* 2 days in seconds */ -#define TLS_EX_SESS_TICKET_VERSION (0x0107) +#define TLS_EX_SESS_TICKET_VERSION (0x0108) /* * Called from ssl3_SendNewSessionTicket, tls13_SendNewSessionTicket @@ -721,11 +721,6 @@ ssl3_EncodeSessionTicket(sslSocket *ss, const NewSessionTicket *ticket, if (rv != SECSuccess) goto loser; - /* compression */ - rv = sslBuffer_AppendNumber(&plaintext, ss->ssl3.hs.compression, 1); - if (rv != SECSuccess) - goto loser; - /* cipher spec parameters */ rv = sslBuffer_AppendNumber(&plaintext, ss->sec.authType, 1); if (rv != SECSuccess) @@ -973,14 +968,6 @@ ssl_ParseSessionTicket(sslSocket *ss, const SECItem *decryptedTicket, } parsedTicket->cipher_suite = (ssl3CipherSuite)temp; - /* Read compression_method. */ - rv = ssl3_ExtConsumeHandshakeNumber(ss, &temp, 1, &buffer, &len); - if (rv != SECSuccess) { - PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); - return SECFailure; - } - parsedTicket->compression_method = (SSLCompressionMethod)temp; - /* Read cipher spec parameters. */ rv = ssl3_ExtConsumeHandshakeNumber(ss, &temp, 1, &buffer, &len); if (rv != SECSuccess) { @@ -1182,7 +1169,6 @@ ssl_CreateSIDFromTicket(sslSocket *ss, const SECItem *rawTicket, sid->version = parsedTicket->ssl_version; sid->creationTime = parsedTicket->timestamp; sid->u.ssl3.cipherSuite = parsedTicket->cipher_suite; - sid->u.ssl3.compression = parsedTicket->compression_method; sid->authType = parsedTicket->authType; sid->authKeyBits = parsedTicket->authKeyBits; sid->keaType = parsedTicket->keaType; diff --git a/lib/ssl/sslimpl.h b/lib/ssl/sslimpl.h index f2becb3f8..618b0c59b 100644 --- a/lib/ssl/sslimpl.h +++ b/lib/ssl/sslimpl.h @@ -243,7 +243,6 @@ typedef struct sslOptionsStr { unsigned int detectRollBack : 1; unsigned int noLocks : 1; unsigned int enableSessionTickets : 1; - unsigned int enableDeflate : 1; unsigned int enableRenegotiation : 2; unsigned int requireSafeNegotiation : 1; unsigned int enableFalseStart : 1; @@ -401,7 +400,6 @@ struct sslSessionIDStr { PRUint8 sessionID[SSL3_SESSIONID_BYTES]; ssl3CipherSuite cipherSuite; - SSLCompressionMethod compression; int policy; ssl3SidKeys keys; /* mechanism used to wrap master secret */ @@ -603,7 +601,6 @@ typedef struct SSL3HandshakeStateStr { const ssl3KEADef *kea_def; ssl3CipherSuite cipher_suite; const ssl3CipherSuiteDef *suite_def; - SSLCompressionMethod compression; sslBuffer msg_body; /* protected by recvBufLock */ /* partial handshake message from record layer */ unsigned int header_bytes; @@ -751,7 +748,6 @@ struct ssl3StateStr { /* used by server. trusted CAs for this socket. */ PRBool initialized; SSL3HandshakeState hs; - ssl3CipherSpec specs[2]; /* one is current, one is pending. */ PRUint16 mtu; /* Our estimate of the MTU */ @@ -820,7 +816,6 @@ typedef struct SessionTicketStr { PRBool valid; SSL3ProtocolVersion ssl_version; ssl3CipherSuite cipher_suite; - SSLCompressionMethod compression_method; SSLAuthType authType; PRUint32 authKeyBits; SSLKEAType keaType; @@ -1193,7 +1188,7 @@ extern SECStatus ssl_CipherPrefSetDefault(PRInt32 which, PRBool enabled); extern SECStatus ssl3_ConstrainRangeByPolicy(void); -extern void ssl3_InitState(sslSocket *ss); +extern SECStatus ssl3_InitState(sslSocket *ss); extern SECStatus Null_Cipher(void *ctx, unsigned char *output, int *outputLen, int maxOutputLen, const unsigned char *input, int inputLen); @@ -1222,21 +1217,11 @@ extern PRInt32 ssl3_SendRecord(sslSocket *ss, ssl3CipherSpec *cwSpec, /* Clear any PRCList, optionally calling f on the value. */ void ssl_ClearPRCList(PRCList *list, void (*f)(void *)); -#ifdef NSS_SSL_ENABLE_ZLIB /* - * The DEFLATE algorithm can result in an expansion of 0.1% + 12 bytes. For a - * maximum TLS record payload of 2**14 bytes, that's 29 bytes. + * Make sure there is room in the write buffer for padding and + * cryptographic expansions. */ -#define SSL3_COMPRESSION_MAX_EXPANSION 29 -#else /* !NSS_SSL_ENABLE_ZLIB */ -#define SSL3_COMPRESSION_MAX_EXPANSION 0 -#endif - -/* - * make sure there is room in the write buffer for padding and - * other compression and cryptographic expansions. - */ -#define SSL3_BUFFER_FUDGE 100 + SSL3_COMPRESSION_MAX_EXPANSION +#define SSL3_BUFFER_FUDGE 100 #define SSL_LOCK_READER(ss) \ if (ss->recvLock) \ diff --git a/lib/ssl/sslinfo.c b/lib/ssl/sslinfo.c index 2fd3d1b23..e03523650 100644 --- a/lib/ssl/sslinfo.c +++ b/lib/ssl/sslinfo.c @@ -8,21 +8,6 @@ #include "sslproto.h" #include "tls13hkdf.h" -static const char * -ssl_GetCompressionMethodName(SSLCompressionMethod compression) -{ - switch (compression) { - case ssl_compression_null: - return "NULL"; -#ifdef NSS_ENABLE_ZLIB - case ssl_compression_deflate: - return "DEFLATE"; -#endif - default: - return "???"; - } -} - SECStatus SSL_GetChannelInfo(PRFileDesc *fd, SSLChannelInfo *info, PRUintn len) { @@ -63,10 +48,9 @@ SSL_GetChannelInfo(PRFileDesc *fd, SSLChannelInfo *info, PRUintn len) * See bug 275744 comment 69 and bug 766137. */ inf.cipherSuite = ss->ssl3.hs.cipher_suite; - inf.compressionMethod = ss->ssl3.cwSpec->compression_method; ssl_ReleaseSpecReadLock(ss); - inf.compressionMethodName = - ssl_GetCompressionMethodName(inf.compressionMethod); + inf.compressionMethod = ssl_compression_null; + inf.compressionMethodName = "NULL"; /* Fill in the cipher details from the cipher suite. */ rv = SSL_GetCipherSuiteInfo(inf.cipherSuite, @@ -510,7 +494,7 @@ SSL_ExportKeyingMaterial(PRFileDesc *fd, * secret is available and we have sent ChangeCipherSpec. */ ssl_GetSpecReadLock(ss); - if (!ss->ssl3.cwSpec->master_secret) { + if (!ss->ssl3.cwSpec->masterSecret) { PORT_SetError(SSL_ERROR_HANDSHAKE_NOT_COMPLETED); rv = SECFailure; } else { diff --git a/lib/ssl/sslsnce.c b/lib/ssl/sslsnce.c index 3d068afc3..279f3c015 100644 --- a/lib/ssl/sslsnce.c +++ b/lib/ssl/sslsnce.c @@ -106,8 +106,6 @@ struct sidCacheEntryStr { union { struct { /* 2 */ ssl3CipherSuite cipherSuite; - /* 2 */ PRUint16 compression; /* SSLCompressionMethod */ - /* 52 */ ssl3SidKeys keys; /* keys, wrapped as needed. */ /* 4 */ PRUint32 masterWrapMech; @@ -115,7 +113,7 @@ struct sidCacheEntryStr { /* 4 */ PRInt32 srvNameIndex; /* 32 */ PRUint8 srvNameHash[SHA256_LENGTH]; /* SHA256 name hash */ /* 2 */ PRUint16 namedCurve; -/*102 */} ssl3; +/*100 */} ssl3; /* force sizeof(sidCacheEntry) to be a multiple of cache line size */ struct { @@ -439,7 +437,6 @@ ConvertFromSID(sidCacheEntry *to, sslSessionID *from) to->signatureScheme = from->sigScheme; to->u.ssl3.cipherSuite = from->u.ssl3.cipherSuite; - to->u.ssl3.compression = (PRUint16)from->u.ssl3.compression; to->u.ssl3.keys = from->u.ssl3.keys; to->u.ssl3.masterWrapMech = from->u.ssl3.masterWrapMech; to->sessionIDLength = from->u.ssl3.sessionIDLength; @@ -482,7 +479,6 @@ ConvertToSID(sidCacheEntry *from, to->u.ssl3.sessionIDLength = from->sessionIDLength; to->u.ssl3.cipherSuite = from->u.ssl3.cipherSuite; - to->u.ssl3.compression = (SSLCompressionMethod)from->u.ssl3.compression; to->u.ssl3.keys = from->u.ssl3.keys; to->u.ssl3.masterWrapMech = from->u.ssl3.masterWrapMech; if (from->u.ssl3.srvNameIndex != -1 && psnce) { diff --git a/lib/ssl/sslsock.c b/lib/ssl/sslsock.c index 9d8002759..f6cb5ad9b 100644 --- a/lib/ssl/sslsock.c +++ b/lib/ssl/sslsock.c @@ -65,7 +65,6 @@ static sslOptions ssl_defaults = { PR_TRUE, /* detectRollBack */ PR_FALSE, /* noLocks */ PR_FALSE, /* enableSessionTickets */ - PR_FALSE, /* enableDeflate */ 2, /* enableRenegotiation (default: requires extension) */ PR_FALSE, /* requireSafeNegotiation */ PR_FALSE, /* enableFalseStart */ @@ -739,7 +738,7 @@ SSL_OptionSet(PRFileDesc *fd, PRInt32 which, PRIntn val) break; case SSL_ENABLE_DEFLATE: - ss->opt.enableDeflate = val; + /* Feature disabled: Report success, do nothing. */ break; case SSL_ENABLE_RENEGOTIATION: @@ -891,7 +890,7 @@ SSL_OptionGet(PRFileDesc *fd, PRInt32 which, PRIntn *pVal) val = ss->opt.enableSessionTickets; break; case SSL_ENABLE_DEFLATE: - val = ss->opt.enableDeflate; + val = PR_FALSE; break; case SSL_ENABLE_RENEGOTIATION: val = ss->opt.enableRenegotiation; @@ -1011,7 +1010,7 @@ SSL_OptionGetDefault(PRInt32 which, PRIntn *pVal) val = ssl_defaults.enableSessionTickets; break; case SSL_ENABLE_DEFLATE: - val = ssl_defaults.enableDeflate; + val = PR_FALSE; break; case SSL_ENABLE_RENEGOTIATION: val = ssl_defaults.enableRenegotiation; @@ -1177,7 +1176,6 @@ SSL_OptionSetDefault(PRInt32 which, PRIntn val) break; case SSL_ENABLE_DEFLATE: - ssl_defaults.enableDeflate = val; break; case SSL_ENABLE_RENEGOTIATION: diff --git a/lib/ssl/sslspec.c b/lib/ssl/sslspec.c index ca08cae1c..f19e842a6 100644 --- a/lib/ssl/sslspec.c +++ b/lib/ssl/sslspec.c @@ -62,19 +62,14 @@ static const ssl3BulkCipherDef ssl_bulk_cipher_defs[] = { /* clang-format on */ const ssl3BulkCipherDef * -ssl_GetBulkCipherDefById(SSL3BulkCipher bulkCipher) +ssl_GetBulkCipherDef(const ssl3CipherSuiteDef *suiteDef) { + SSL3BulkCipher bulkCipher = suiteDef->bulk_cipher_alg; PORT_Assert(bulkCipher < PR_ARRAY_SIZE(ssl_bulk_cipher_defs)); PORT_Assert(ssl_bulk_cipher_defs[bulkCipher].cipher == bulkCipher); return &ssl_bulk_cipher_defs[bulkCipher]; } -const ssl3BulkCipherDef * -ssl_GetBulkCipherDef(const ssl3CipherSuiteDef *suiteDef) -{ - return ssl_GetBulkCipherDefById(suiteDef->bulk_cipher_alg); -} - /* indexed by SSL3MACAlgorithm */ static const ssl3MACDef ssl_mac_defs[] = { /* pad_size is only used for SSL 3.0 MAC. See RFC 6101 Sec. 5.2.3.1. */ @@ -151,9 +146,47 @@ ssl_CreateCipherSpec(sslSocket *ss, CipherSpecDirection direction) SSL_TRC(10, ("%d: SSL[%d]: new %s spec %d ct=%d", SSL_GETPID(), ss->fd, SPEC_DIR(spec), spec, spec->refCt)); + return spec; +} +void +ssl_SaveCipherSpec(sslSocket *ss, ssl3CipherSpec *spec) +{ PR_APPEND_LINK(&spec->link, &ss->ssl3.hs.cipherSpecs); - return spec; +} + +/* Called from ssl3_InitState. */ +/* Caller must hold the SpecWriteLock. */ +SECStatus +ssl_SetupNullCipherSpec(sslSocket *ss, CipherSpecDirection dir) +{ + ssl3CipherSpec *spec; + + PORT_Assert(ss->opt.noLocks || ssl_HaveSpecWriteLock(ss)); + + spec = ssl_CreateCipherSpec(ss, dir); + if (!spec) { + return SECFailure; + } + + spec->version = ss->vrange.max; /* Override with the maximum. */ + + spec->cipherDef = &ssl_bulk_cipher_defs[cipher_null]; + PORT_Assert(spec->cipherDef->cipher == cipher_null); + spec->macDef = &ssl_mac_defs[ssl_mac_null]; + PORT_Assert(spec->macDef->mac == ssl_mac_null); + spec->cipher = Null_Cipher; + + spec->phase = "cleartext"; + dtls_InitRecvdRecords(&spec->recvdRecords); + + ssl_SaveCipherSpec(ss, spec); + if (dir == CipherSpecRead) { + ss->ssl3.crSpec = spec; + } else { + ss->ssl3.cwSpec = spec; + } + return SECSuccess; } void @@ -164,57 +197,32 @@ ssl_CipherSpecAddRef(ssl3CipherSpec *spec) SSL_GETPID(), SPEC_DIR(spec), spec, spec->refCt)); } -/* Called twice, only from ssl3_DestroyCipherSpec (immediately below). */ -static void -ssl3_CleanupKeyMaterial(ssl3KeyMaterial *mat) +void +ssl_DestroyKeyMaterial(ssl3KeyMaterial *keyMaterial) { - if (mat->write_key != NULL) { - PK11_FreeSymKey(mat->write_key); - mat->write_key = NULL; - } - if (mat->write_mac_key != NULL) { - PK11_FreeSymKey(mat->write_mac_key); - mat->write_mac_key = NULL; - } - if (mat->write_mac_context != NULL) { - PK11_DestroyContext(mat->write_mac_context, PR_TRUE); - mat->write_mac_context = NULL; + PK11_FreeSymKey(keyMaterial->key); + PK11_FreeSymKey(keyMaterial->macKey); + if (keyMaterial->macContext != NULL) { + PK11_DestroyContext(keyMaterial->macContext, PR_TRUE); } } -/* Called from ssl3_SendChangeCipherSpecs() and -** ssl3_HandleChangeCipherSpecs() -** ssl3_DestroySSL3Info -** Caller must hold SpecWriteLock. -*/ -void +static void ssl_FreeCipherSpec(ssl3CipherSpec *spec) { + SSL_TRC(10, ("%d: SSL[-]: Freeing %s spec %d. epoch=%d", + SSL_GETPID(), SPEC_DIR(spec), spec, spec->epoch)); + + PR_REMOVE_LINK(&spec->link); + /* PORT_Assert( ss->opt.noLocks || ssl_HaveSpecWriteLock(ss)); Don't have ss! */ - if (spec->encodeContext) { - PK11_DestroyContext(spec->encodeContext, PR_TRUE); - spec->encodeContext = NULL; - } - if (spec->decodeContext) { - PK11_DestroyContext(spec->decodeContext, PR_TRUE); - spec->decodeContext = NULL; - } - if (spec->destroyCompressContext && spec->compressContext) { - spec->destroyCompressContext(spec->compressContext, 1); - spec->compressContext = NULL; - } - if (spec->destroyDecompressContext && spec->decompressContext) { - spec->destroyDecompressContext(spec->decompressContext, 1); - spec->decompressContext = NULL; - } - if (spec->master_secret != NULL) { - PK11_FreeSymKey(spec->master_secret); - spec->master_secret = NULL; + if (spec->cipherContext) { + PK11_DestroyContext(spec->cipherContext, PR_TRUE); } - ssl3_CleanupKeyMaterial(&spec->client); - ssl3_CleanupKeyMaterial(&spec->server); - spec->destroyCompressContext = NULL; - spec->destroyDecompressContext = NULL; + PK11_FreeSymKey(spec->masterSecret); + ssl_DestroyKeyMaterial(&spec->keyMaterial); + + PORT_ZFree(spec, sizeof(*spec)); } /* This function is never called on a spec which is on the @@ -222,14 +230,16 @@ ssl_FreeCipherSpec(ssl3CipherSpec *spec) void ssl_CipherSpecRelease(ssl3CipherSpec *spec) { + if (!spec) { + return; + } + PORT_Assert(spec->refCt > 0); --spec->refCt; SSL_TRC(10, ("%d: SSL[-]: decrement refct for %s spec %d. epoch=%d new ct = %d", SSL_GETPID(), SPEC_DIR(spec), spec, spec->epoch, spec->refCt)); if (!spec->refCt) { - PR_REMOVE_LINK(&spec->link); ssl_FreeCipherSpec(spec); - PORT_Free(spec); } } @@ -237,10 +247,7 @@ void ssl_DestroyCipherSpecs(PRCList *list) { while (!PR_CLIST_IS_EMPTY(list)) { - PRCList *cur_p = PR_LIST_TAIL(list); - PR_REMOVE_LINK(cur_p); - ssl_FreeCipherSpec((ssl3CipherSpec *)cur_p); - PORT_Free(cur_p); + ssl_FreeCipherSpec((ssl3CipherSpec *)PR_LIST_TAIL(list)); } } diff --git a/lib/ssl/sslspec.h b/lib/ssl/sslspec.h index 1e64acc75..38fbc59ef 100644 --- a/lib/ssl/sslspec.h +++ b/lib/ssl/sslspec.h @@ -98,10 +98,10 @@ struct ssl3MACDefStr { #define MAX_IV_LENGTH 24 typedef struct { - PK11SymKey *write_key; - PK11SymKey *write_mac_key; - PK11Context *write_mac_context; - PRUint8 write_iv[MAX_IV_LENGTH]; + PK11SymKey *key; + PK11SymKey *macKey; + PK11Context *macContext; + PRUint8 iv[MAX_IV_LENGTH]; } ssl3KeyMaterial; typedef SECStatus (*SSLCipher)(void *context, @@ -120,13 +120,6 @@ typedef SECStatus (*SSLAEADCipher)( int inlen, const unsigned char *additionalData, int additionalDataLen); -typedef SECStatus (*SSLCompressor)(void *context, - unsigned char *out, - int *outlen, - int maxout, - const unsigned char *in, - int inlen); -typedef SECStatus (*SSLDestroy)(void *context, PRBool freeit); /* The DTLS anti-replay window in number of packets. Defined here because we * need it in the cipher spec. Note that this is a ring buffer but left and @@ -145,60 +138,52 @@ typedef struct DTLSRecvdRecordsStr { } DTLSRecvdRecords; /* -** These are the "specs" in the "ssl3" struct. -** Access to the pointers to these specs, and all the specs' contents -** (direct and indirect) is protected by the reader/writer lock ss->specLock. -*/ + * These are the "specs" used for reading and writing records. Access to the + * pointers to these specs, and all the specs' contents (direct and indirect) is + * protected by the reader/writer lock ss->specLock. + */ struct ssl3CipherSpecStr { PRCList link; - const ssl3BulkCipherDef *cipher_def; - const ssl3MACDef *mac_def; - SSLCompressionMethod compression_method; - int mac_size; - SSLCipher encode; - SSLCipher decode; - SSLAEADCipher aead; - void *encodeContext; - void *decodeContext; - SSLCompressor compressor; /* Don't name these fields compress */ - SSLCompressor decompressor; /* and uncompress because zconf.h */ - /* may define them as macros. */ - SSLDestroy destroyCompressContext; - void *compressContext; - SSLDestroy destroyDecompressContext; - void *decompressContext; - PK11SymKey *master_secret; - sslSequenceNumber write_seq_num; - sslSequenceNumber read_seq_num; + PRUint8 refCt; + + CipherSpecDirection direction; SSL3ProtocolVersion version; - ssl3KeyMaterial client; - ssl3KeyMaterial server; + + const ssl3BulkCipherDef *cipherDef; + const ssl3MACDef *macDef; + + SSLCipher cipher; + SSLAEADCipher aead; + void *cipherContext; + + PK11SymKey *masterSecret; + ssl3KeyMaterial keyMaterial; + DTLSEpoch epoch; + const char *phase; + sslSequenceNumber seqNum; DTLSRecvdRecords recvdRecords; + /* The number of 0-RTT bytes that can be sent or received in TLS 1.3. This * will be zero for everything but 0-RTT. */ PRUint32 earlyDataRemaining; - - PRUint8 refCt; - CipherSpecDirection direction; - const char *phase; }; typedef void (*sslCipherSpecChangedFunc)(void *arg, PRBool sending, ssl3CipherSpec *newSpec); -const ssl3BulkCipherDef *ssl_GetBulkCipherDefById(SSL3BulkCipher bulkCipher); const ssl3BulkCipherDef *ssl_GetBulkCipherDef(const ssl3CipherSuiteDef *cipher_def); const ssl3MACDef *ssl_GetMacDefByAlg(SSL3MACAlgorithm mac); const ssl3MACDef *ssl_GetMacDef(const sslSocket *ss, const ssl3CipherSuiteDef *suiteDef); ssl3CipherSpec *ssl_CreateCipherSpec(sslSocket *ss, CipherSpecDirection direction); +void ssl_SaveCipherSpec(sslSocket *ss, ssl3CipherSpec *spec); void ssl_CipherSpecAddRef(ssl3CipherSpec *spec); -void ssl_FreeCipherSpec(ssl3CipherSpec *spec); void ssl_CipherSpecRelease(ssl3CipherSpec *spec); void ssl_DestroyCipherSpecs(PRCList *list); -ssl3CipherSpec *ssl_CreateNullCipherSpec(sslSocket *ss, CipherSpecDirection dir); +void ssl_DestroyKeyMaterial(ssl3KeyMaterial *keyMaterial); +SECStatus ssl_SetupNullCipherSpec(sslSocket *ss, CipherSpecDirection dir); ssl3CipherSpec *ssl_FindCipherSpecByEpoch(sslSocket *ss, CipherSpecDirection direction, DTLSEpoch epoch); diff --git a/lib/ssl/tls13con.c b/lib/ssl/tls13con.c index d7cf2ff27..ed0a2ed9e 100644 --- a/lib/ssl/tls13con.c +++ b/lib/ssl/tls13con.c @@ -119,7 +119,6 @@ const char kHkdfLabelExporterMasterSecret[] = "exp master"; const char kHkdfLabelResumption[] = "resumption"; const char kHkdfPurposeKey[] = "key"; const char kHkdfPurposeIv[] = "iv"; -const char kKeyPhaseCleartext[] = "clear"; const char keylogLabelClientEarlyTrafficSecret[] = "CLIENT_EARLY_TRAFFIC_SECRET"; const char keylogLabelClientHsTrafficSecret[] = "CLIENT_HANDSHAKE_TRAFFIC_SECRET"; @@ -908,8 +907,8 @@ tls13_ComputeFinalSecrets(sslSocket *ss) { SECStatus rv; - PORT_Assert(!ss->ssl3.crSpec->master_secret); - PORT_Assert(!ss->ssl3.cwSpec->master_secret); + PORT_Assert(!ss->ssl3.crSpec->masterSecret); + PORT_Assert(!ss->ssl3.cwSpec->masterSecret); rv = tls13_DeriveSecretWrap(ss, ss->ssl3.hs.currentSecret, NULL, kHkdfLabelResumptionMasterSecret, @@ -1375,7 +1374,7 @@ tls13_HandleClientHelloPart2(sslSocket *ss, ssl_GetSpecWriteLock(ss); /* Increase the write sequence number. The read sequence number * will be reset after this to early data or handshake. */ - ss->ssl3.cwSpec->write_seq_num = 1; + ss->ssl3.cwSpec->seqNum = 1; ssl_ReleaseSpecWriteLock(ss); } @@ -1754,7 +1753,7 @@ tls13_SendHelloRetryRequest(sslSocket *ss, } /* We depend on this being exactly one record and one message. */ PORT_Assert(!IS_DTLS(ss) || (ss->ssl3.hs.sendMessageSeq == 1 && - ss->ssl3.cwSpec->write_seq_num == 1)); + ss->ssl3.cwSpec->seqNum == 1)); ssl_ReleaseXmitBufLock(ss); ss->ssl3.hs.helloRetry = PR_TRUE; @@ -1954,8 +1953,9 @@ tls13_HandleHelloRetryRequest(sslSocket *ss, PRUint8 *b, PRUint32 length) /* Restore the null cipher spec for writing. */ ssl_GetSpecWriteLock(ss); ssl_CipherSpecRelease(ss->ssl3.cwSpec); - ss->ssl3.cwSpec = ss->ssl3.crSpec; - PORT_Assert(ss->ssl3.cwSpec->cipher_def->cipher == cipher_null); + ss->ssl3.cwSpec = ssl_FindCipherSpecByEpoch(ss, CipherSpecWrite, + TrafficKeyClearText); + PORT_Assert(ss->ssl3.cwSpec); ssl_ReleaseSpecWriteLock(ss); } else { PORT_Assert(ss->ssl3.hs.zeroRttState == ssl_0rtt_none); @@ -2204,6 +2204,10 @@ tls13_SendServerHelloSequence(sslSocket *ss) return SECFailure; } + if (IS_DTLS(ss)) { + /* We need this for reading ACKs. */ + ssl_CipherSpecAddRef(ss->ssl3.crSpec); + } if (ss->ssl3.hs.zeroRttState == ssl_0rtt_accepted) { rv = tls13_SetCipherSpec(ss, TrafficKeyEarlyApplicationData, @@ -2217,13 +2221,6 @@ tls13_SendServerHelloSequence(sslSocket *ss) PORT_Assert(ss->ssl3.hs.zeroRttState == ssl_0rtt_none || ss->ssl3.hs.zeroRttState == ssl_0rtt_ignored); - if (IS_DTLS(ss)) { - /* Store the cleartext cipherSpec so we can decrypt ACKs. */ - dtls13_SaveNullCipherSpec(ss, ss->ssl3.crSpec); - if (rv != SECSuccess) { - return SECFailure; - } - } rv = tls13_SetCipherSpec(ss, TrafficKeyHandshake, CipherSpecRead, PR_FALSE); @@ -2328,6 +2325,15 @@ tls13_HandleServerHelloPart2(sslSocket *ss) return SECFailure; /* error code is set. */ } + if (ss->ssl3.hs.zeroRttState == ssl_0rtt_sent) { + /* When we send 0-RTT, we saved the cipher spec in case we needed it to + * send another ClientHello in case we received an HRR from the server. + * Since we were successful, we can release the spec. */ + ssl3CipherSpec *spec = ssl_FindCipherSpecByEpoch(ss, CipherSpecWrite, + TrafficKeyClearText); + ssl_CipherSpecRelease(spec); + } + rv = tls13_SetCipherSpec(ss, TrafficKeyHandshake, CipherSpecRead, PR_FALSE); if (rv != SECSuccess) { @@ -2861,32 +2867,27 @@ tls13_DeriveSecretWrap(sslSocket *ss, PK11SymKey *key, static SECStatus tls13_DeriveTrafficKeys(sslSocket *ss, ssl3CipherSpec *spec, TrafficKeyType type, - CipherSpecDirection direction, PRBool deleteSecret) { - size_t keySize = spec->cipher_def->key_size; - size_t ivSize = spec->cipher_def->iv_size + - spec->cipher_def->explicit_nonce_size; /* This isn't always going to - * work, but it does for - * AES-GCM */ - CK_MECHANISM_TYPE bulkAlgorithm = ssl3_Alg2Mech(spec->cipher_def->calg); + size_t keySize = spec->cipherDef->key_size; + size_t ivSize = spec->cipherDef->iv_size + + spec->cipherDef->explicit_nonce_size; /* This isn't always going to + * work, but it does for + * AES-GCM */ + CK_MECHANISM_TYPE bulkAlgorithm = ssl3_Alg2Mech(spec->cipherDef->calg); PK11SymKey **prkp = NULL; PK11SymKey *prk = NULL; PRBool clientKey; - ssl3KeyMaterial *target; - const char *phase; SECStatus rv; /* These labels are just used for debugging. */ static const char kHkdfPhaseEarlyApplicationDataKeys[] = "early application data"; static const char kHkdfPhaseHandshakeKeys[] = "handshake data"; static const char kHkdfPhaseApplicationDataKeys[] = "application data"; - if (ss->sec.isServer ^ (direction == CipherSpecWrite)) { + if (ss->sec.isServer ^ (spec->direction == CipherSpecWrite)) { clientKey = PR_TRUE; - target = &spec->client; } else { clientKey = PR_FALSE; - target = &spec->server; } PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss)); @@ -2894,16 +2895,16 @@ tls13_DeriveTrafficKeys(sslSocket *ss, ssl3CipherSpec *spec, switch (type) { case TrafficKeyEarlyApplicationData: PORT_Assert(clientKey); - phase = kHkdfPhaseEarlyApplicationDataKeys; prkp = &ss->ssl3.hs.clientEarlyTrafficSecret; + spec->phase = kHkdfPhaseEarlyApplicationDataKeys; break; case TrafficKeyHandshake: - phase = kHkdfPhaseHandshakeKeys; prkp = clientKey ? &ss->ssl3.hs.clientHsTrafficSecret : &ss->ssl3.hs.serverHsTrafficSecret; + spec->phase = kHkdfPhaseHandshakeKeys; break; case TrafficKeyApplicationData: - phase = kHkdfPhaseApplicationDataKeys; prkp = clientKey ? &ss->ssl3.hs.clientTrafficSecret : &ss->ssl3.hs.serverTrafficSecret; + spec->phase = kHkdfPhaseApplicationDataKeys; break; default: LOG_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE); @@ -2913,17 +2914,15 @@ tls13_DeriveTrafficKeys(sslSocket *ss, ssl3CipherSpec *spec, PORT_Assert(prkp != NULL); prk = *prkp; - SSL_TRC(3, ("%d: TLS13[%d]: deriving %s traffic keys phase='%s'", - SSL_GETPID(), ss->fd, - (direction == CipherSpecWrite) ? "write" : "read", phase)); - PORT_Assert(phase); - spec->phase = phase; + SSL_TRC(3, ("%d: TLS13[%d]: deriving %s traffic keys epoch=%d (%s)", + SSL_GETPID(), ss->fd, SPEC_DIR(spec), + spec->epoch, spec->phase)); rv = tls13_HkdfExpandLabel(prk, tls13_GetHash(ss), NULL, 0, kHkdfPurposeKey, strlen(kHkdfPurposeKey), bulkAlgorithm, keySize, - &target->write_key); + &spec->keyMaterial.key); if (rv != SECSuccess) { LOG_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE); PORT_Assert(0); @@ -2933,7 +2932,7 @@ tls13_DeriveTrafficKeys(sslSocket *ss, ssl3CipherSpec *spec, rv = tls13_HkdfExpandLabelRaw(prk, tls13_GetHash(ss), NULL, 0, kHkdfPurposeIv, strlen(kHkdfPurposeIv), - target->write_iv, ivSize); + spec->keyMaterial.iv, ivSize); if (rv != SECSuccess) { LOG_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE); PORT_Assert(0); @@ -2962,11 +2961,19 @@ tls13_SetupPendingCipherSpec(sslSocket *ss, ssl3CipherSpec *spec) /* Version isn't set when we send 0-RTT data. */ spec->version = PR_MAX(SSL_LIBRARY_VERSION_TLS_1_3, ss->version); + ssl_SaveCipherSpec(ss, spec); + /* We want to keep read cipher specs around longer because + * there are cases where we might get either epoch N or + * epoch N+1. */ + if (IS_DTLS(ss) && spec->direction == CipherSpecRead) { + ssl_CipherSpecAddRef(spec); + } + SSL_TRC(3, ("%d: TLS13[%d]: Set Pending Cipher Suite to 0x%04x", SSL_GETPID(), ss->fd, suite)); - spec->cipher_def = bulk; - switch (spec->cipher_def->calg) { + spec->cipherDef = bulk; + switch (bulk->calg) { case ssl_calg_aes_gcm: spec->aead = tls13_AESGCM; break; @@ -2976,9 +2983,7 @@ tls13_SetupPendingCipherSpec(sslSocket *ss, ssl3CipherSpec *spec) default: PORT_Assert(0); return SECFailure; - break; } - return SECSuccess; } @@ -3023,7 +3028,8 @@ tls13_SetCipherSpec(sslSocket *ss, TrafficKeyType type, { SECStatus rv; ssl3CipherSpec *spec = NULL; - ssl3CipherSpec **specp = (direction == CipherSpecRead) ? &ss->ssl3.crSpec : &ss->ssl3.cwSpec; + ssl3CipherSpec **specp; + /* Flush out old handshake data. */ ssl_GetXmitBufLock(ss); rv = ssl3_FlushHandshake(ss, ssl_SEND_FLAG_FORCE_INTO_BUFFER); @@ -3034,23 +3040,14 @@ tls13_SetCipherSpec(sslSocket *ss, TrafficKeyType type, /* Create the new spec. */ spec = ssl_CreateCipherSpec(ss, direction); - /* We want to keep read cipher specs around longer because - * there are cases where we might get either epoch N or - * epoch N+1. */ - if (IS_DTLS(ss) && direction == CipherSpecRead) { - ++spec->refCt; + if (!spec) { + return SECFailure; } - ss->ssl3.pwSpec = ss->ssl3.prSpec = spec; - rv = tls13_SetupPendingCipherSpec(ss, spec); if (rv != SECSuccess) return SECFailure; - rv = tls13_DeriveTrafficKeys(ss, spec, type, direction, - deleteSecret); - if (rv != SECSuccess) { - return SECFailure; - } + specp = (direction == CipherSpecRead) ? &ss->ssl3.crSpec : &ss->ssl3.cwSpec; /* We use the epoch for cipher suite identification, so increment * it in both TLS and DTLS. */ @@ -3058,26 +3055,29 @@ tls13_SetCipherSpec(sslSocket *ss, TrafficKeyType type, return SECFailure; } spec->epoch = (PRUint16)type; - spec->read_seq_num = spec->write_seq_num = 0; + spec->seqNum = 0; if (IS_DTLS(ss)) { dtls_InitRecvdRecords(&spec->recvdRecords); } - if (type == TrafficKeyEarlyApplicationData) { spec->earlyDataRemaining = ss->sec.ci.sid->u.ssl3.locked.sessionTicket.max_early_data_size; } + rv = tls13_DeriveTrafficKeys(ss, spec, type, deleteSecret); + if (rv != SECSuccess) { + return SECFailure; + } + /* Now that we've set almost everything up, finally cut over. */ ssl_GetSpecWriteLock(ss); ssl_CipherSpecRelease(*specp); /* May delete old cipher. */ *specp = spec; /* Overwrite. */ ssl_ReleaseSpecWriteLock(ss); - SSL_TRC(3, ("%d: TLS13[%d]: %s installed key for phase='%s'.%d dir=%s", - SSL_GETPID(), ss->fd, SSL_ROLE(ss), - spec->phase, spec->epoch, - direction == CipherSpecRead ? "read" : "write")); + SSL_TRC(3, ("%d: TLS13[%d]: %s installed key for epoch=%d (%s) dir=%s", + SSL_GETPID(), ss->fd, SSL_ROLE(ss), spec->epoch, + spec->phase, SPEC_DIR(spec))); if (ss->ssl3.changedCipherSpecFunc) { ss->ssl3.changedCipherSpecFunc(ss->ssl3.changedCipherSpecArg, @@ -3212,7 +3212,7 @@ tls13_WriteNonce(ssl3KeyMaterial *keys, size_t i; PORT_Assert(nonceLen == 12); - memcpy(nonce, keys->write_iv, 12); + memcpy(nonce, keys->iv, 12); /* XOR the last 8 bytes of the IV with the sequence number. */ PORT_Assert(seqNumLen == 8); @@ -3242,10 +3242,10 @@ tls13_AEAD(ssl3KeyMaterial *keys, PRBool doDecrypt, }; if (doDecrypt) { - rv = PK11_Decrypt(keys->write_key, mechanism, ¶m, + rv = PK11_Decrypt(keys->key, mechanism, ¶m, out, &uOutLen, maxout, in, inlen); } else { - rv = PK11_Encrypt(keys->write_key, mechanism, ¶m, + rv = PK11_Encrypt(keys->key, mechanism, ¶m, out, &uOutLen, maxout, in, inlen); } *outlen = (int)uOutLen; @@ -4560,13 +4560,14 @@ tls13_ProtectRecord(sslSocket *ss, PRUint32 contentLen, sslBuffer *wrBuf) { - const ssl3BulkCipherDef *cipher_def = cwSpec->cipher_def; + const ssl3BulkCipherDef *cipher_def = cwSpec->cipherDef; const int tagLen = cipher_def->tag_size; SECStatus rv; - SSL_TRC(3, ("%d: TLS13[%d]: spec=%d (%s) protect record 0x%0llx len=%u", - SSL_GETPID(), ss->fd, cwSpec, cwSpec->phase, - cwSpec->write_seq_num, contentLen)); + PORT_Assert(cwSpec->direction == CipherSpecWrite); + SSL_TRC(3, ("%d: TLS13[%d]: spec=%d epoch=%d protect 0x%0llx len=%u", + SSL_GETPID(), ss->fd, cwSpec, cwSpec->epoch, + cwSpec->seqNum, contentLen)); if (contentLen + 1 + tagLen > wrBuf->space) { PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); @@ -4588,18 +4589,17 @@ tls13_ProtectRecord(sslSocket *ss, wrBuf->buf[contentLen] = type; rv = tls13_FormatAdditionalData(ss, aad, sizeof(aad), cwSpec->epoch, - cwSpec->write_seq_num); + cwSpec->seqNum); if (rv != SECSuccess) { return SECFailure; } - rv = cwSpec->aead( - ss->sec.isServer ? &cwSpec->server : &cwSpec->client, - PR_FALSE, /* do encrypt */ - wrBuf->buf, /* output */ - (int *)&wrBuf->len, /* out len */ - wrBuf->space, /* max out */ - wrBuf->buf, contentLen + 1, /* input */ - aad, sizeof(aad)); + rv = cwSpec->aead(&cwSpec->keyMaterial, + PR_FALSE, /* do encrypt */ + wrBuf->buf, /* output */ + (int *)&wrBuf->len, /* out len */ + wrBuf->space, /* max out */ + wrBuf->buf, contentLen + 1, /* input */ + aad, sizeof(aad)); if (rv != SECSuccess) { PORT_SetError(SSL_ERROR_ENCRYPTION_FAILURE); return SECFailure; @@ -4624,15 +4624,22 @@ tls13_UnprotectRecord(sslSocket *ss, SSL3Ciphertext *cText, sslBuffer *plaintext, SSL3AlertDescription *alert) { - const ssl3BulkCipherDef *cipher_def = spec->cipher_def; + const ssl3BulkCipherDef *cipher_def = spec->cipherDef; + sslSequenceNumber seqNum; PRUint8 aad[8]; SECStatus rv; *alert = bad_record_mac; /* Default alert for most issues. */ - SSL_TRC(3, ("%d: TLS13[%d]: spec=%d (%s) unprotect record 0x%0llx len=%u", - SSL_GETPID(), ss->fd, spec, spec->phase, - spec->read_seq_num, cText->buf->len)); + PORT_Assert(spec->direction == CipherSpecRead); + if (IS_DTLS(ss)) { + seqNum = cText->seq_num & RECORD_SEQ_MASK; + } else { + seqNum = spec->seqNum; + } + SSL_TRC(3, ("%d: TLS13[%d]: spec=%d epoch=%d unprotect 0x%0llx len=%u", + SSL_GETPID(), ss->fd, spec, spec->epoch, seqNum, + cText->buf->len)); /* We can perform this test in variable time because the record's total * length and the ciphersuite are both public knowledge. */ @@ -4666,20 +4673,18 @@ tls13_UnprotectRecord(sslSocket *ss, /* Decrypt */ PORT_Assert(cipher_def->type == type_aead); - rv = tls13_FormatAdditionalData(ss, aad, sizeof(aad), spec->epoch, - IS_DTLS(ss) ? cText->seq_num : spec->read_seq_num); + rv = tls13_FormatAdditionalData(ss, aad, sizeof(aad), spec->epoch, seqNum); if (rv != SECSuccess) { return SECFailure; } - rv = spec->aead( - ss->sec.isServer ? &spec->client : &spec->server, - PR_TRUE, /* do decrypt */ - plaintext->buf, /* out */ - (int *)&plaintext->len, /* outlen */ - plaintext->space, /* maxout */ - cText->buf->buf, /* in */ - cText->buf->len, /* inlen */ - aad, sizeof(aad)); + rv = spec->aead(&spec->keyMaterial, + PR_TRUE, /* do decrypt */ + plaintext->buf, /* out */ + (int *)&plaintext->len, /* outlen */ + plaintext->space, /* maxout */ + cText->buf->buf, /* in */ + cText->buf->len, /* inlen */ + aad, sizeof(aad)); if (rv != SECSuccess) { SSL_TRC(3, ("%d: TLS13[%d]: record has bogus MAC", @@ -4796,6 +4801,10 @@ tls13_MaybeDo0RTTHandshake(sslSocket *ss) if (rv != SECSuccess) return SECFailure; + /* Save cwSpec in case we get a HelloRetryRequest and have to send another + * ClientHello. */ + ssl_CipherSpecAddRef(ss->ssl3.cwSpec); + rv = tls13_SetCipherSpec(ss, TrafficKeyEarlyApplicationData, CipherSpecWrite, PR_TRUE); if (rv != SECSuccess) { |