summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorMartin Thomson <martin.thomson@gmail.com>2017-09-11 15:49:53 +1000
committerMartin Thomson <martin.thomson@gmail.com>2017-09-11 15:49:53 +1000
commit65cfc6ceb022925e5190e167dee34801abe12236 (patch)
tree89e9ea635b5967e9ae21fd176afa4c8b4f719069 /lib
parent2d32981b4593350b2a4ea6d1492a982ad1543b14 (diff)
downloadnss-hg-65cfc6ceb022925e5190e167dee34801abe12236.tar.gz
Bug 1398679 - Make cipher specs properly directional, r?ekr
This makes each cipher spec unidirectional. This is a tiny bit less efficient in TLS 1.2 and earlier, where some of the material could be shared (primarily the master secret), but it is much more efficient for TLS 1.3. Also, there is now only one variable of each type on the specs. Up to now, the specs had two copies of almost everything to support being used for both read and write. Now there are separate specs for reading and writing. We only duplicate the pointers to the master secret, and the cipher definitions. This also does away with the backing array that was used to hold two copies of specs. Cipher specs are allocated on the heap as they are used and reference counted, using the same system as is already used for TLS 1.3. This uses the |direction| attribute that was previously added for TLS 1.3 and uses that more thoroughly. Finally, this REMOVES compression support from libssl entirely.
Diffstat (limited to 'lib')
-rw-r--r--lib/ssl/config.mk5
-rw-r--r--lib/ssl/dtls13con.c30
-rw-r--r--lib/ssl/dtls13con.h1
-rw-r--r--lib/ssl/dtlscon.c9
-rw-r--r--lib/ssl/ssl.gyp8
-rw-r--r--lib/ssl/ssl.h3
-rw-r--r--lib/ssl/ssl3con.c1120
-rw-r--r--lib/ssl/ssl3exthandle.c16
-rw-r--r--lib/ssl/sslimpl.h23
-rw-r--r--lib/ssl/sslinfo.c22
-rw-r--r--lib/ssl/sslsnce.c6
-rw-r--r--lib/ssl/sslsock.c8
-rw-r--r--lib/ssl/sslspec.c121
-rw-r--r--lib/ssl/sslspec.h71
-rw-r--r--lib/ssl/tls13con.c189
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, &param, out, &uOutLen,
+ rv = PK11_Decrypt(keys->key, CKM_AES_GCM, &param, out, &uOutLen,
maxout, in, inlen);
} else {
- rv = PK11_Encrypt(keys->write_key, CKM_AES_GCM, &param, out, &uOutLen,
+ rv = PK11_Encrypt(keys->key, CKM_AES_GCM, &param, 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, &param,
+ rv = PK11_Decrypt(keys->key, CKM_NSS_CHACHA20_POLY1305, &param,
out, &uOutLen, maxout, in, inlen);
} else {
- rv = PK11_Encrypt(keys->write_key, CKM_NSS_CHACHA20_POLY1305, &param,
+ rv = PK11_Encrypt(keys->key, CKM_NSS_CHACHA20_POLY1305, &param,
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, &param, &outputItem, &inputItem);
+ rv = PK11_SignWithSymKey(spec->keyMaterial.macKey, macType, &param,
+ &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, &param);
+ spec->masterSecret, &param);
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, &param);
+ spec->masterSecret, &param);
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, &param,
+ rv = PK11_Decrypt(keys->key, mechanism, &param,
out, &uOutLen, maxout, in, inlen);
} else {
- rv = PK11_Encrypt(keys->write_key, mechanism, &param,
+ rv = PK11_Encrypt(keys->key, mechanism, &param,
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) {