summaryrefslogtreecommitdiff
path: root/lib/ssl
diff options
context:
space:
mode:
authorMartin Thomson <martin.thomson@gmail.com>2017-10-09 11:30:43 +1100
committerMartin Thomson <martin.thomson@gmail.com>2017-10-09 11:30:43 +1100
commite78fea278cc67fa308ea7b62630c02f8217c3630 (patch)
tree0d43bcc8af95c8b3c6632571f5121faf4092588c /lib/ssl
parent474f1bcabd34eee91a34831260ea514660162d2f (diff)
parentc21e2ced85ff55b338ea1758179d358126d9204b (diff)
downloadnss-hg-e78fea278cc67fa308ea7b62630c02f8217c3630.tar.gz
Merge NSS trunk to NSS_TLS13_DRAFT19_BRANCH
Diffstat (limited to 'lib/ssl')
-rw-r--r--lib/ssl/ssl3con.c165
-rw-r--r--lib/ssl/ssl3exthandle.c37
-rw-r--r--lib/ssl/sslimpl.h9
-rw-r--r--lib/ssl/sslinfo.c13
-rw-r--r--lib/ssl/sslsnce.c10
-rw-r--r--lib/ssl/sslsock.c7
-rw-r--r--lib/ssl/sslt.h8
-rw-r--r--lib/ssl/tls13con.c31
8 files changed, 188 insertions, 92 deletions
diff --git a/lib/ssl/ssl3con.c b/lib/ssl/ssl3con.c
index d3f0d40b7..5bf4b1cdd 100644
--- a/lib/ssl/ssl3con.c
+++ b/lib/ssl/ssl3con.c
@@ -230,11 +230,15 @@ static const unsigned int ssl_compression_method_count =
static PRBool
ssl_CompressionEnabled(sslSocket *ss, SSLCompressionMethod compression)
{
- SSL3ProtocolVersion version;
-
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. */
@@ -254,6 +258,7 @@ ssl_CompressionEnabled(sslSocket *ss, SSLCompressionMethod compression)
return ss->opt.enableDeflate;
}
#endif
+#endif
return PR_FALSE;
}
@@ -5967,35 +5972,14 @@ ssl3_SendRSAClientKeyExchange(sslSocket *ss, SECKEYPublicKey *svrPubKey)
goto loser;
}
-#ifdef NSS_ALLOW_SSLKEYLOGFILE
- if (ssl_keylog_iob) {
+#ifdef TRACE
+ if (ssl_trace >= 100) {
SECStatus extractRV = PK11_ExtractKeyValue(pms);
if (extractRV == SECSuccess) {
SECItem *keyData = PK11_GetKeyData(pms);
if (keyData && keyData->data && keyData->len) {
-#ifdef TRACE
- if (ssl_trace >= 100) {
- ssl_PrintBuf(ss, "Pre-Master Secret",
- keyData->data, keyData->len);
- }
-#endif
- if (ssl_keylog_iob && enc_pms.len >= 8 && keyData->len == 48) {
- /* https://developer.mozilla.org/en/NSS_Key_Log_Format */
-
- /* There could be multiple, concurrent writers to the
- * keylog, so we have to do everything in a single call to
- * fwrite. */
- char buf[4 + 8 * 2 + 1 + 48 * 2 + 1];
-
- strcpy(buf, "RSA ");
- hexEncode(buf + 4, enc_pms.data, 8);
- buf[20] = ' ';
- hexEncode(buf + 21, keyData->data, 48);
- buf[sizeof(buf) - 1] = '\n';
-
- fwrite(buf, sizeof(buf), 1, ssl_keylog_iob);
- fflush(ssl_keylog_iob);
- }
+ ssl_PrintBuf(ss, "Pre-Master Secret",
+ keyData->data, keyData->len);
}
}
}
@@ -6869,6 +6853,8 @@ ssl3_HandleServerHelloPart2(sslSocket *ss, const SECItem *sidBytes,
ss->sec.authKeyBits = sid->authKeyBits;
ss->sec.keaType = sid->keaType;
ss->sec.keaKeyBits = sid->keaKeyBits;
+ ss->sec.originalKeaGroup = ssl_LookupNamedGroup(sid->keaGroup);
+ ss->sec.signatureScheme = sid->sigScheme;
if (sid->u.ssl3.keys.msIsWrapped) {
PK11SlotInfo *slot;
@@ -7879,6 +7865,7 @@ ssl3_NewSessionID(sslSocket *ss, PRBool is_server)
sid->references = 1;
sid->cached = never_cached;
sid->version = ss->version;
+ sid->sigScheme = ssl_sig_none;
sid->u.ssl3.keys.resumable = PR_TRUE;
sid->u.ssl3.policy = SSL_ALLOWED;
@@ -8492,29 +8479,33 @@ ssl3_HandleClientHello(sslSocket *ss, PRUint8 *b, PRUint32 length)
}
}
}
+
/* This is a second check for TLS 1.3 and re-handshake to stop us
* from re-handshake up to TLS 1.3, so it happens after version
* negotiation. */
- if (ss->firstHsDone && ss->version >= SSL_LIBRARY_VERSION_TLS_1_3) {
- desc = unexpected_message;
- errCode = SSL_ERROR_RENEGOTIATION_NOT_ALLOWED;
- goto alert_loser;
- }
- if (ss->firstHsDone &&
- (ss->opt.enableRenegotiation == SSL_RENEGOTIATE_REQUIRES_XTN ||
- ss->opt.enableRenegotiation == SSL_RENEGOTIATE_TRANSITIONAL) &&
- !ssl3_ExtensionNegotiated(ss, ssl_renegotiation_info_xtn)) {
- desc = no_renegotiation;
- level = alert_warning;
- errCode = SSL_ERROR_RENEGOTIATION_NOT_ALLOWED;
- goto alert_loser;
- }
- if ((ss->opt.requireSafeNegotiation ||
- (ss->firstHsDone && ss->peerRequestedProtection)) &&
- !ssl3_ExtensionNegotiated(ss, ssl_renegotiation_info_xtn)) {
- desc = handshake_failure;
- errCode = SSL_ERROR_UNSAFE_NEGOTIATION;
- goto alert_loser;
+ if (ss->version >= SSL_LIBRARY_VERSION_TLS_1_3) {
+ if (ss->firstHsDone) {
+ desc = unexpected_message;
+ errCode = SSL_ERROR_RENEGOTIATION_NOT_ALLOWED;
+ goto alert_loser;
+ }
+ } else {
+ if (ss->firstHsDone &&
+ (ss->opt.enableRenegotiation == SSL_RENEGOTIATE_REQUIRES_XTN ||
+ ss->opt.enableRenegotiation == SSL_RENEGOTIATE_TRANSITIONAL) &&
+ !ssl3_ExtensionNegotiated(ss, ssl_renegotiation_info_xtn)) {
+ desc = no_renegotiation;
+ level = alert_warning;
+ errCode = SSL_ERROR_RENEGOTIATION_NOT_ALLOWED;
+ goto alert_loser;
+ }
+ if ((ss->opt.requireSafeNegotiation ||
+ (ss->firstHsDone && ss->peerRequestedProtection)) &&
+ !ssl3_ExtensionNegotiated(ss, ssl_renegotiation_info_xtn)) {
+ desc = handshake_failure;
+ errCode = SSL_ERROR_UNSAFE_NEGOTIATION;
+ goto alert_loser;
+ }
}
/* We do stateful resumes only if we are in TLS < 1.3 and
@@ -8875,6 +8866,8 @@ compression_found:
ss->sec.authKeyBits = sid->authKeyBits;
ss->sec.keaType = sid->keaType;
ss->sec.keaKeyBits = sid->keaKeyBits;
+ ss->sec.originalKeaGroup = ssl_LookupNamedGroup(sid->keaGroup);
+ ss->sec.signatureScheme = sid->sigScheme;
ss->sec.localCert =
CERT_DupCertificate(ss->sec.serverCert->serverCert);
@@ -8946,6 +8939,7 @@ compression_found:
}
if (sid) { /* we had a sid, but it's no longer valid, free it */
+ ss->statelessResume = PR_FALSE;
SSL_AtomicIncrementLong(&ssl3stats.hch_sid_cache_not_ok);
ss->sec.uncache(sid);
ssl_FreeSID(sid);
@@ -11133,40 +11127,44 @@ ssl3_SendNextProto(sslSocket *ss)
return rv;
}
-/* called from ssl3_SendFinished
+/* called from ssl3_SendFinished and tls13_DeriveSecret.
*
* This function is simply a debugging aid and therefore does not return a
* SECStatus. */
-static void
-ssl3_RecordKeyLog(sslSocket *ss)
+void
+ssl3_RecordKeyLog(sslSocket *ss, const char *label, PK11SymKey *secret)
{
#ifdef NSS_ALLOW_SSLKEYLOGFILE
SECStatus rv;
SECItem *keyData;
- char buf[14 /* "CLIENT_RANDOM " */ +
- SSL3_RANDOM_LENGTH * 2 /* client_random */ +
- 1 /* " " */ +
- 48 * 2 /* master secret */ +
- 1 /* new line */];
- unsigned int j;
+ /* Longest label is "CLIENT_HANDSHAKE_TRAFFIC_SECRET", master secret is 48
+ * bytes which happens to be the largest in TLS 1.3 as well (SHA384).
+ * Maximum line length: "CLIENT_HANDSHAKE_TRAFFIC_SECRET" (31) + " " (1) +
+ * client_random (32*2) + " " (1) +
+ * traffic_secret (48*2) + "\n" (1) = 194. */
+ char buf[200];
+ unsigned int offset, len;
PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
if (!ssl_keylog_iob)
return;
- rv = PK11_ExtractKeyValue(ss->ssl3.cwSpec->master_secret);
+ rv = PK11_ExtractKeyValue(secret);
if (rv != SECSuccess)
return;
- ssl_GetSpecReadLock(ss);
-
/* keyData does not need to be freed. */
- keyData = PK11_GetKeyData(ss->ssl3.cwSpec->master_secret);
- if (!keyData || !keyData->data || keyData->len != 48) {
- ssl_ReleaseSpecReadLock(ss);
+ keyData = PK11_GetKeyData(secret);
+ if (!keyData || !keyData->data)
+ return;
+
+ len = strlen(label) + 1 + /* label + space */
+ SSL3_RANDOM_LENGTH * 2 + 1 + /* client random (hex) + space */
+ keyData->len * 2 + 1; /* secret (hex) + newline */
+ PORT_Assert(len <= sizeof(buf));
+ if (len > sizeof(buf))
return;
- }
/* https://developer.mozilla.org/en/NSS_Key_Log_Format */
@@ -11174,23 +11172,22 @@ ssl3_RecordKeyLog(sslSocket *ss)
* keylog, so we have to do everything in a single call to
* fwrite. */
- memcpy(buf, "CLIENT_RANDOM ", 14);
- j = 14;
- hexEncode(buf + j, ss->ssl3.hs.client_random.rand, SSL3_RANDOM_LENGTH);
- j += SSL3_RANDOM_LENGTH * 2;
- buf[j++] = ' ';
- hexEncode(buf + j, keyData->data, 48);
- j += 48 * 2;
- buf[j++] = '\n';
-
- PORT_Assert(j == sizeof(buf));
-
- ssl_ReleaseSpecReadLock(ss);
-
- if (fwrite(buf, sizeof(buf), 1, ssl_keylog_iob) != 1)
- return;
- fflush(ssl_keylog_iob);
- return;
+ strcpy(buf, label);
+ offset = strlen(label);
+ buf[offset++] += ' ';
+ hexEncode(buf + offset, ss->ssl3.hs.client_random.rand, SSL3_RANDOM_LENGTH);
+ offset += SSL3_RANDOM_LENGTH * 2;
+ buf[offset++] = ' ';
+ hexEncode(buf + offset, keyData->data, keyData->len);
+ offset += keyData->len * 2;
+ buf[offset++] = '\n';
+
+ PORT_Assert(offset == len);
+
+ PZ_Lock(ssl_keylog_lock);
+ if (fwrite(buf, len, 1, ssl_keylog_iob) == 1)
+ fflush(ssl_keylog_iob);
+ PZ_Unlock(ssl_keylog_lock);
#endif
}
@@ -11257,7 +11254,7 @@ ssl3_SendFinished(sslSocket *ss, PRInt32 flags)
goto fail; /* error code set by ssl3_FlushHandshake */
}
- ssl3_RecordKeyLog(ss);
+ ssl3_RecordKeyLog(ss, "CLIENT_RANDOM", ss->ssl3.cwSpec->master_secret);
return SECSuccess;
@@ -11537,6 +11534,12 @@ ssl3_FillInCachedSID(sslSocket *ss, sslSessionID *sid, PK11SymKey *secret)
sid->authKeyBits = ss->sec.authKeyBits;
sid->keaType = ss->sec.keaType;
sid->keaKeyBits = ss->sec.keaKeyBits;
+ if (ss->sec.keaGroup) {
+ sid->keaGroup = ss->sec.keaGroup->name;
+ } else {
+ sid->keaGroup = ssl_grp_none;
+ }
+ sid->sigScheme = ss->sec.signatureScheme;
sid->lastAccessTime = sid->creationTime = ssl_TimeUsec();
sid->expirationTime = sid->creationTime + ssl3_sid_timeout * PR_USEC_PER_SEC;
sid->localCert = CERT_DupCertificate(ss->sec.localCert);
diff --git a/lib/ssl/ssl3exthandle.c b/lib/ssl/ssl3exthandle.c
index a9c678184..c3d32f696 100644
--- a/lib/ssl/ssl3exthandle.c
+++ b/lib/ssl/ssl3exthandle.c
@@ -750,6 +750,19 @@ ssl3_EncodeSessionTicket(sslSocket *ss, const NewSessionTicket *ticket,
rv = sslBuffer_AppendNumber(&plaintext, ss->sec.keaKeyBits, 4);
if (rv != SECSuccess)
goto loser;
+ if (ss->sec.keaGroup) {
+ rv = sslBuffer_AppendNumber(&plaintext, ss->sec.keaGroup->name, 4);
+ if (rv != SECSuccess)
+ goto loser;
+ } else {
+ /* No kea group. Write 0 as invalid value. */
+ rv = sslBuffer_AppendNumber(&plaintext, 0, 4);
+ if (rv != SECSuccess)
+ goto loser;
+ }
+ rv = sslBuffer_AppendNumber(&plaintext, ss->sec.signatureScheme, 4);
+ if (rv != SECSuccess)
+ goto loser;
/* certificate type */
PORT_Assert(SSL_CERT_IS(ss->sec.serverCert, ss->sec.authType));
@@ -1007,6 +1020,18 @@ ssl_ParseSessionTicket(sslSocket *ss, const SECItem *decryptedTicket,
return SECFailure;
}
parsedTicket->keaKeyBits = temp;
+ rv = ssl3_ExtConsumeHandshakeNumber(ss, &temp, 4, &buffer, &len);
+ if (rv != SECSuccess) {
+ PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
+ return SECFailure;
+ }
+ parsedTicket->originalKeaGroup = temp;
+ rv = ssl3_ExtConsumeHandshakeNumber(ss, &temp, 4, &buffer, &len);
+ if (rv != SECSuccess) {
+ PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
+ return SECFailure;
+ }
+ parsedTicket->signatureScheme = (SSLSignatureScheme)temp;
/* Read the optional named curve. */
rv = ssl3_ExtConsumeHandshakeNumber(ss, &temp, 1, &buffer, &len);
@@ -1184,7 +1209,9 @@ ssl_CreateSIDFromTicket(sslSocket *ss, const SECItem *rawTicket,
sid->authKeyBits = parsedTicket->authKeyBits;
sid->keaType = parsedTicket->keaType;
sid->keaKeyBits = parsedTicket->keaKeyBits;
+ sid->keaGroup = parsedTicket->originalKeaGroup;
sid->namedCurve = parsedTicket->namedCurve;
+ sid->sigScheme = parsedTicket->signatureScheme;
rv = SECITEM_CopyItem(NULL, &sid->u.ssl3.locked.sessionTicket.ticket,
rawTicket);
@@ -1378,14 +1405,12 @@ ssl3_SendRenegotiationInfoXtn(const sslSocket *ss, TLSExtensionData *xtnData,
PRInt32 len = 0;
SECStatus rv;
- /* In draft-ietf-tls-renegotiation-03, it is NOT RECOMMENDED to send
- * both the SCSV and the empty RI, so when we send SCSV in
- * the initial handshake, we don't also send RI.
+ /* In RFC 5746, it is NOT RECOMMENDED to send both the SCSV and the empty
+ * RI, so when we send SCSV in the initial handshake, we don't also send RI.
*/
- if (!ss || ss->ssl3.hs.sendingSCSV) {
- return SECSuccess;
+ if (ss->ssl3.hs.sendingSCSV) {
+ return 0;
}
-
if (ss->firstHsDone) {
len = ss->sec.isServer ? ss->ssl3.hs.finishedBytes * 2
: ss->ssl3.hs.finishedBytes;
diff --git a/lib/ssl/sslimpl.h b/lib/ssl/sslimpl.h
index 28d326617..81b22760b 100644
--- a/lib/ssl/sslimpl.h
+++ b/lib/ssl/sslimpl.h
@@ -551,6 +551,8 @@ struct sslSessionIDStr {
PRUint32 authKeyBits;
SSLKEAType keaType;
PRUint32 keaKeyBits;
+ SSLNamedGroup keaGroup;
+ SSLSignatureScheme sigScheme;
union {
struct {
@@ -1014,6 +1016,8 @@ typedef struct SessionTicketStr {
PRUint32 authKeyBits;
SSLKEAType keaType;
PRUint32 keaKeyBits;
+ SSLNamedGroup originalKeaGroup;
+ SSLSignatureScheme signatureScheme;
const sslNamedGroupDef *namedCurve; /* For certificate lookup. */
/*
@@ -1082,6 +1086,7 @@ struct sslSecurityInfoStr {
SSLKEAType keaType;
PRUint32 keaKeyBits;
const sslNamedGroupDef *keaGroup;
+ const sslNamedGroupDef *originalKeaGroup;
/* The selected certificate (for servers only). */
const sslServerCert *serverCert;
@@ -1260,6 +1265,7 @@ extern char ssl_debug;
extern char ssl_trace;
extern FILE *ssl_trace_iob;
extern FILE *ssl_keylog_iob;
+extern PZLock *ssl_keylog_lock;
extern PRUint32 ssl3_sid_timeout;
extern PRUint32 ssl_ticket_lifetime;
extern PRUint32 ssl_max_early_data_size;
@@ -1873,6 +1879,9 @@ ssl3_TLSPRFWithMasterSecret(sslSocket *ss, ssl3CipherSpec *spec,
const unsigned char *val, unsigned int valLen,
unsigned char *out, unsigned int outLen);
+extern void
+ssl3_RecordKeyLog(sslSocket *ss, const char *label, PK11SymKey *secret);
+
PRBool ssl_AlpnTagAllowed(const sslSocket *ss, const SECItem *tag);
#ifdef TRACE
diff --git a/lib/ssl/sslinfo.c b/lib/ssl/sslinfo.c
index f2b680d00..a8b4f2f26 100644
--- a/lib/ssl/sslinfo.c
+++ b/lib/ssl/sslinfo.c
@@ -79,11 +79,22 @@ SSL_GetChannelInfo(PRFileDesc *fd, SSLChannelInfo *info, PRUintn len)
/* Get these fromm |ss->sec| because that is accurate
* even with TLS 1.3 disaggregated cipher suites. */
inf.keaType = ss->sec.keaType;
- inf.keaGroup = ss->sec.keaGroup ? ss->sec.keaGroup->name : ssl_grp_none;
+ inf.originalKeaGroup = ss->sec.originalKeaGroup
+ ? ss->sec.originalKeaGroup->name
+ : ssl_grp_none;
+ inf.keaGroup = ss->sec.keaGroup
+ ? ss->sec.keaGroup->name
+ : ssl_grp_none;
inf.keaKeyBits = ss->sec.keaKeyBits;
inf.authType = ss->sec.authType;
inf.authKeyBits = ss->sec.authKeyBits;
inf.signatureScheme = ss->sec.signatureScheme;
+ /* If this is a resumed session, signatureScheme isn't set in ss->sec.
+ * Use the signature scheme from the previous handshake. */
+ if (inf.signatureScheme == ssl_sig_none && sid->sigScheme) {
+ inf.signatureScheme = sid->sigScheme;
+ }
+ inf.resumed = ss->statelessResume || ss->ssl3.hs.isResuming;
}
if (sid) {
unsigned int sidLen;
diff --git a/lib/ssl/sslsnce.c b/lib/ssl/sslsnce.c
index cf9b0b424..7b86e074a 100644
--- a/lib/ssl/sslsnce.c
+++ b/lib/ssl/sslsnce.c
@@ -99,7 +99,9 @@ struct sidCacheEntryStr {
/* 2 */ PRUint16 authKeyBits;
/* 2 */ PRUint16 keaType;
/* 2 */ PRUint16 keaKeyBits;
- /* 84 - common header total */
+ /* 4 */ PRUint32 signatureScheme;
+ /* 4 */ PRUint32 keaGroup;
+ /* 92 - common header total */
union {
struct {
@@ -117,7 +119,7 @@ struct sidCacheEntryStr {
/* force sizeof(sidCacheEntry) to be a multiple of cache line size */
struct {
- /*124 */ PRUint8 filler[124]; /* 84+124==208, a multiple of 16 */
+ /*112 */ PRUint8 filler[112]; /* 80+112==192, a multiple of 16 */
} forceSize;
} u;
};
@@ -433,6 +435,8 @@ ConvertFromSID(sidCacheEntry *to, sslSessionID *from)
to->authKeyBits = from->authKeyBits;
to->keaType = from->keaType;
to->keaKeyBits = from->keaKeyBits;
+ to->keaGroup = from->keaGroup;
+ to->signatureScheme = from->sigScheme;
to->u.ssl3.cipherSuite = from->u.ssl3.cipherSuite;
to->u.ssl3.compression = (PRUint16)from->u.ssl3.compression;
@@ -543,6 +547,8 @@ ConvertToSID(sidCacheEntry *from,
to->authKeyBits = from->authKeyBits;
to->keaType = from->keaType;
to->keaKeyBits = from->keaKeyBits;
+ to->keaGroup = from->keaGroup;
+ to->sigScheme = from->signatureScheme;
return to;
diff --git a/lib/ssl/sslsock.c b/lib/ssl/sslsock.c
index 7dcd6ceab..9d8002759 100644
--- a/lib/ssl/sslsock.c
+++ b/lib/ssl/sslsock.c
@@ -119,6 +119,7 @@ FILE *ssl_trace_iob;
#ifdef NSS_ALLOW_SSLKEYLOGFILE
FILE *ssl_keylog_iob;
+PZLock *ssl_keylog_lock;
#endif
char lockStatus[] = "Locks are ENABLED. ";
@@ -3577,6 +3578,12 @@ ssl_SetDefaultsFromEnvironment(void)
ssl_keylog_iob);
}
SSL_TRACE(("SSL: logging SSL/TLS secrets to %s", ev));
+ ssl_keylog_lock = PR_NewLock();
+ if (!ssl_keylog_lock) {
+ SSL_TRACE(("SSL: failed to create key log lock"));
+ fclose(ssl_keylog_iob);
+ ssl_keylog_iob = NULL;
+ }
}
}
#endif
diff --git a/lib/ssl/sslt.h b/lib/ssl/sslt.h
index b4127d77f..177d24f7a 100644
--- a/lib/ssl/sslt.h
+++ b/lib/ssl/sslt.h
@@ -297,6 +297,14 @@ typedef struct SSLChannelInfoStr {
SSLAuthType authType;
SSLSignatureScheme signatureScheme;
+ /* The following fields were added in NSS 3.34. */
+ /* When the session was resumed this holds the key exchange group of the
+ * original handshake. */
+ SSLNamedGroup originalKeaGroup;
+ /* This field is PR_TRUE when the session is resumed and PR_FALSE
+ * otherwise. */
+ PRBool resumed;
+
/* When adding new fields to this structure, please document the
* NSS version in which they were added. */
} SSLChannelInfo;
diff --git a/lib/ssl/tls13con.c b/lib/ssl/tls13con.c
index 0d563f274..7099ea7e3 100644
--- a/lib/ssl/tls13con.c
+++ b/lib/ssl/tls13con.c
@@ -67,6 +67,7 @@ static SECStatus
tls13_DeriveSecretWrap(sslSocket *ss, PK11SymKey *key,
const char *prefix,
const char *suffix,
+ const char *keylogLabel,
PK11SymKey **dest);
static SECStatus
tls13_DeriveSecret(sslSocket *ss, PK11SymKey *key,
@@ -120,6 +121,13 @@ 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";
+const char keylogLabelServerHsTrafficSecret[] = "SERVER_HANDSHAKE_TRAFFIC_SECRET";
+const char keylogLabelClientTrafficSecret[] = "CLIENT_TRAFFIC_SECRET_0";
+const char keylogLabelServerTrafficSecret[] = "SERVER_TRAFFIC_SECRET_0";
+const char keylogLabelExporterSecret[] = "EXPORTER_SECRET";
+
#define TRAFFIC_SECRET(ss, dir, name) ((ss->sec.isServer ^ \
(dir == CipherSpecWrite)) \
? ss->ssl3.hs.client##name \
@@ -822,6 +830,7 @@ tls13_ComputeHandshakeSecrets(sslSocket *ss)
rv = tls13_DeriveSecretWrap(ss, ss->ssl3.hs.currentSecret,
kHkdfLabelClient,
kHkdfLabelHandshakeTrafficSecret,
+ keylogLabelClientHsTrafficSecret,
&ss->ssl3.hs.clientHsTrafficSecret);
if (rv != SECSuccess) {
LOG_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE);
@@ -830,6 +839,7 @@ tls13_ComputeHandshakeSecrets(sslSocket *ss)
rv = tls13_DeriveSecretWrap(ss, ss->ssl3.hs.currentSecret,
kHkdfLabelServer,
kHkdfLabelHandshakeTrafficSecret,
+ keylogLabelServerHsTrafficSecret,
&ss->ssl3.hs.serverHsTrafficSecret);
if (rv != SECSuccess) {
LOG_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE);
@@ -872,6 +882,7 @@ tls13_ComputeApplicationSecrets(sslSocket *ss)
rv = tls13_DeriveSecretWrap(ss, ss->ssl3.hs.currentSecret,
kHkdfLabelClient,
kHkdfLabelApplicationTrafficSecret,
+ keylogLabelClientTrafficSecret,
&ss->ssl3.hs.clientTrafficSecret);
if (rv != SECSuccess) {
return SECFailure;
@@ -879,6 +890,7 @@ tls13_ComputeApplicationSecrets(sslSocket *ss)
rv = tls13_DeriveSecretWrap(ss, ss->ssl3.hs.currentSecret,
kHkdfLabelServer,
kHkdfLabelApplicationTrafficSecret,
+ keylogLabelServerTrafficSecret,
&ss->ssl3.hs.serverTrafficSecret);
if (rv != SECSuccess) {
return SECFailure;
@@ -886,6 +898,7 @@ tls13_ComputeApplicationSecrets(sslSocket *ss)
rv = tls13_DeriveSecretWrap(ss, ss->ssl3.hs.currentSecret,
NULL, kHkdfLabelExporterMasterSecret,
+ keylogLabelExporterSecret,
&ss->ssl3.hs.exporterSecret);
if (rv != SECSuccess) {
return SECFailure;
@@ -904,6 +917,7 @@ tls13_ComputeFinalSecrets(sslSocket *ss)
rv = tls13_DeriveSecretWrap(ss, ss->ssl3.hs.currentSecret,
NULL, kHkdfLabelResumptionMasterSecret,
+ NULL,
&ss->ssl3.hs.resumptionMasterSecret);
PK11_FreeSymKey(ss->ssl3.hs.currentSecret);
ss->ssl3.hs.currentSecret = NULL;
@@ -923,6 +937,8 @@ tls13_RestoreCipherInfo(sslSocket *ss, sslSessionID *sid)
*/
ss->sec.authType = sid->authType;
ss->sec.authKeyBits = sid->authKeyBits;
+ ss->sec.originalKeaGroup = ssl_LookupNamedGroup(sid->keaGroup);
+ ss->sec.signatureScheme = sid->sigScheme;
}
/* Check whether resumption-PSK is allowed. */
@@ -1588,6 +1604,7 @@ tls13_HandleClientHelloPart2(sslSocket *ss,
rv = tls13_DeriveSecretWrap(ss, ss->ssl3.hs.currentSecret,
kHkdfLabelClient,
kHkdfLabelEarlyTrafficSecret,
+ keylogLabelClientEarlyTrafficSecret,
&ss->ssl3.hs.clientEarlyTrafficSecret);
if (rv != SECSuccess) {
FATAL_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE, internal_error);
@@ -2826,6 +2843,7 @@ static SECStatus
tls13_DeriveSecretWrap(sslSocket *ss, PK11SymKey *key,
const char *prefix,
const char *suffix,
+ const char *keylogLabel,
PK11SymKey **dest)
{
SECStatus rv;
@@ -2855,8 +2873,16 @@ tls13_DeriveSecretWrap(sslSocket *ss, PK11SymKey *key,
return SECFailure;
}
- return tls13_DeriveSecret(ss, key, label, strlen(label),
- &hashes, dest);
+ rv = tls13_DeriveSecret(ss, key, label, strlen(label),
+ &hashes, dest);
+ if (rv != SECSuccess) {
+ return SECFailure;
+ }
+
+ if (keylogLabel) {
+ ssl3_RecordKeyLog(ss, keylogLabel, *dest);
+ }
+ return SECSuccess;
}
/* Derive traffic keys for the next cipher spec in the queue. */
@@ -4813,6 +4839,7 @@ tls13_MaybeDo0RTTHandshake(sslSocket *ss)
rv = tls13_DeriveSecretWrap(ss, ss->ssl3.hs.currentSecret,
kHkdfLabelClient,
kHkdfLabelEarlyTrafficSecret,
+ keylogLabelClientEarlyTrafficSecret,
&ss->ssl3.hs.clientEarlyTrafficSecret);
if (rv != SECSuccess)
return SECFailure;