summaryrefslogtreecommitdiff
path: root/libs/nss/src/lib/ssl/tls13con.c
diff options
context:
space:
mode:
Diffstat (limited to 'libs/nss/src/lib/ssl/tls13con.c')
-rw-r--r--libs/nss/src/lib/ssl/tls13con.c639
1 files changed, 430 insertions, 209 deletions
diff --git a/libs/nss/src/lib/ssl/tls13con.c b/libs/nss/src/lib/ssl/tls13con.c
index b8f31c3f0..5d51d3c5c 100644
--- a/libs/nss/src/lib/ssl/tls13con.c
+++ b/libs/nss/src/lib/ssl/tls13con.c
@@ -25,6 +25,7 @@
#include "tls13exthandle.h"
#include "tls13hashstate.h"
#include "tls13subcerts.h"
+#include "tls13psk.h"
static SECStatus tls13_SetCipherSpec(sslSocket *ss, PRUint16 epoch,
SSLSecretDirection install,
@@ -65,13 +66,15 @@ tls13_DeriveSecret(sslSocket *ss, PK11SymKey *key,
const char *label,
unsigned int labelLen,
const SSL3Hashes *hashes,
- PK11SymKey **dest);
+ PK11SymKey **dest,
+ SSLHashType hash);
static SECStatus tls13_SendEndOfEarlyData(sslSocket *ss);
-static SECStatus tls13_HandleEndOfEarlyData(sslSocket *ss, PRUint8 *b,
+static SECStatus tls13_HandleEndOfEarlyData(sslSocket *ss, const PRUint8 *b,
PRUint32 length);
+static SECStatus tls13_MaybeHandleSuppressedEndOfEarlyData(sslSocket *ss);
static SECStatus tls13_SendFinished(sslSocket *ss, PK11SymKey *baseKey);
static SECStatus tls13_ComputePskBinderHash(sslSocket *ss, unsigned int prefix,
- SSL3Hashes *hashes);
+ SSL3Hashes *hashes, SSLHashType type);
static SECStatus tls13_VerifyFinished(sslSocket *ss, SSLHandshakeType message,
PK11SymKey *secret,
PRUint8 *b, PRUint32 length,
@@ -85,14 +88,14 @@ static SECStatus tls13_SendNewSessionTicket(sslSocket *ss,
unsigned int appTokenLen);
static SECStatus tls13_HandleNewSessionTicket(sslSocket *ss, PRUint8 *b,
PRUint32 length);
-static SECStatus tls13_ComputeEarlySecrets(sslSocket *ss);
+static SECStatus tls13_ComputeEarlySecretsWithPsk(sslSocket *ss);
static SECStatus tls13_ComputeHandshakeSecrets(sslSocket *ss);
static SECStatus tls13_ComputeApplicationSecrets(sslSocket *ss);
static SECStatus tls13_ComputeFinalSecrets(sslSocket *ss);
static SECStatus tls13_ComputeFinished(
- sslSocket *ss, PK11SymKey *baseKey, const SSL3Hashes *hashes,
- PRBool sending, PRUint8 *output, unsigned int *outputLen,
- unsigned int maxOutputLen);
+ sslSocket *ss, PK11SymKey *baseKey, SSLHashType hashType,
+ const SSL3Hashes *hashes, PRBool sending, PRUint8 *output,
+ unsigned int *outputLen, unsigned int maxOutputLen);
static SECStatus tls13_SendClientSecondRound(sslSocket *ss);
static SECStatus tls13_SendClientSecondFlight(sslSocket *ss,
PRBool sendClientCert,
@@ -102,7 +105,8 @@ static SECStatus tls13_FinishHandshake(sslSocket *ss);
const char kHkdfLabelClient[] = "c";
const char kHkdfLabelServer[] = "s";
const char kHkdfLabelDerivedSecret[] = "derived";
-const char kHkdfLabelPskBinderKey[] = "res binder";
+const char kHkdfLabelResPskBinderKey[] = "res binder";
+const char kHkdfLabelExtPskBinderKey[] = "ext binder";
const char kHkdfLabelEarlyTrafficSecret[] = "e traffic";
const char kHkdfLabelEarlyExporterSecret[] = "e exp master";
const char kHkdfLabelHandshakeTrafficSecret[] = "hs traffic";
@@ -264,6 +268,16 @@ tls13_GetHashForCipherSuite(ssl3CipherSuite suite)
SSLHashType
tls13_GetHash(const sslSocket *ss)
{
+ /* suite_def may not be set yet when doing EPSK 0-Rtt. */
+ if (!ss->ssl3.hs.suite_def) {
+ if (ss->xtnData.selectedPsk) {
+ return ss->xtnData.selectedPsk->hash;
+ }
+ /* This should never happen. */
+ PORT_Assert(0);
+ return ssl_hash_none;
+ }
+
/* All TLS 1.3 cipher suites must have an explict PRF hash. */
PORT_Assert(ss->ssl3.hs.suite_def->prf_hash != ssl_hash_none);
return ss->ssl3.hs.suite_def->prf_hash;
@@ -318,9 +332,9 @@ tls13_GetHashSize(const sslSocket *ss)
}
static CK_MECHANISM_TYPE
-tls13_GetHmacMechanism(sslSocket *ss)
+tls13_GetHmacMechanismFromHash(SSLHashType hashType)
{
- switch (tls13_GetHash(ss)) {
+ switch (hashType) {
case ssl_hash_sha256:
return CKM_SHA256_HMAC;
case ssl_hash_sha384:
@@ -331,19 +345,25 @@ tls13_GetHmacMechanism(sslSocket *ss)
return CKM_SHA256_HMAC;
}
+static CK_MECHANISM_TYPE
+tls13_GetHmacMechanism(const sslSocket *ss)
+{
+ return tls13_GetHmacMechanismFromHash(tls13_GetHash(ss));
+}
+
SECStatus
tls13_ComputeHash(sslSocket *ss, SSL3Hashes *hashes,
- const PRUint8 *buf, unsigned int len)
+ const PRUint8 *buf, unsigned int len,
+ SSLHashType hash)
{
SECStatus rv;
- rv = PK11_HashBuf(ssl3_HashTypeToOID(tls13_GetHash(ss)),
- hashes->u.raw, buf, len);
+ rv = PK11_HashBuf(ssl3_HashTypeToOID(hash), hashes->u.raw, buf, len);
if (rv != SECSuccess) {
FATAL_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE, internal_error);
return SECFailure;
}
- hashes->len = tls13_GetHashSize(ss);
+ hashes->len = tls13_GetHashSizeForHash(hash);
return SECSuccess;
}
@@ -461,40 +481,50 @@ tls13_SetupClientHello(sslSocket *ss, sslClientHelloType chType)
return SECFailure;
}
- /* Below here checks if we can do stateless resumption. */
- if (sid->cached == never_cached ||
- sid->version < SSL_LIBRARY_VERSION_TLS_1_3) {
- return SECSuccess;
- }
+ /* Try to do stateless resumption, if we can. */
+ if (sid->cached != never_cached &&
+ sid->version >= SSL_LIBRARY_VERSION_TLS_1_3) {
+ /* The caller must be holding sid->u.ssl3.lock for reading. */
+ session_ticket = &sid->u.ssl3.locked.sessionTicket;
+ PORT_Assert(session_ticket && session_ticket->ticket.data);
- /* The caller must be holding sid->u.ssl3.lock for reading. */
- session_ticket = &sid->u.ssl3.locked.sessionTicket;
- PORT_Assert(session_ticket && session_ticket->ticket.data);
+ if (ssl_TicketTimeValid(ss, session_ticket)) {
+ ss->statelessResume = PR_TRUE;
+ }
- if (ssl_TicketTimeValid(ss, session_ticket)) {
- ss->statelessResume = PR_TRUE;
- }
+ if (ss->statelessResume) {
+ PORT_Assert(ss->sec.ci.sid);
+ rv = tls13_RecoverWrappedSharedSecret(ss, ss->sec.ci.sid);
+ if (rv != SECSuccess) {
+ FATAL_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE, internal_error);
+ SSL_AtomicIncrementLong(&ssl3stats->sch_sid_cache_not_ok);
+ ssl_UncacheSessionID(ss);
+ ssl_FreeSID(ss->sec.ci.sid);
+ ss->sec.ci.sid = NULL;
+ return SECFailure;
+ }
- if (ss->statelessResume) {
- PORT_Assert(ss->sec.ci.sid);
- rv = tls13_RecoverWrappedSharedSecret(ss, ss->sec.ci.sid);
- if (rv != SECSuccess) {
- FATAL_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE, internal_error);
- SSL_AtomicIncrementLong(&ssl3stats->sch_sid_cache_not_ok);
- ssl_UncacheSessionID(ss);
- ssl_FreeSID(ss->sec.ci.sid);
- ss->sec.ci.sid = NULL;
- return SECFailure;
+ ss->ssl3.hs.cipher_suite = ss->sec.ci.sid->u.ssl3.cipherSuite;
+ rv = ssl3_SetupCipherSuite(ss, PR_FALSE);
+ if (rv != SECSuccess) {
+ FATAL_ERROR(ss, PORT_GetError(), internal_error);
+ return SECFailure;
+ }
+ PORT_Assert(!PR_CLIST_IS_EMPTY(&ss->ssl3.hs.psks));
}
+ }
- ss->ssl3.hs.cipher_suite = ss->sec.ci.sid->u.ssl3.cipherSuite;
- rv = ssl3_SetupCipherSuite(ss, PR_FALSE);
- if (rv != SECSuccess) {
- FATAL_ERROR(ss, PORT_GetError(), internal_error);
- return SECFailure;
+ /* Derive the binder keys if any PSKs. */
+ if (!PR_CLIST_IS_EMPTY(&ss->ssl3.hs.psks)) {
+ /* If an External PSK specified a suite, use that. */
+ sslPsk *psk = (sslPsk *)PR_LIST_HEAD(&ss->ssl3.hs.psks);
+ if (!ss->statelessResume &&
+ psk->type == ssl_psk_external &&
+ psk->zeroRttSuite != TLS_NULL_WITH_NULL_NULL) {
+ ss->ssl3.hs.cipher_suite = psk->zeroRttSuite;
}
- rv = tls13_ComputeEarlySecrets(ss);
+ rv = tls13_ComputeEarlySecretsWithPsk(ss);
if (rv != SECSuccess) {
FATAL_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE, internal_error);
return SECFailure;
@@ -876,6 +906,12 @@ SSLExp_SendCertificateRequest(PRFileDesc *fd)
return SECFailure;
}
+ /* Disallow a CertificateRequest if this connection uses an external PSK. */
+ if (ss->sec.authType == ssl_auth_psk) {
+ PORT_SetError(SSL_ERROR_FEATURE_DISABLED);
+ return SECFailure;
+ }
+
rv = TLS13_CHECK_HS_STATE(ss, SEC_ERROR_INVALID_ARGS,
idle_handshake);
if (rv != SECSuccess) {
@@ -989,20 +1025,34 @@ tls13_RecoverWrappedSharedSecret(sslSocket *ss, sslSessionID *sid)
wrappedMS.data = sid->u.ssl3.keys.wrapped_master_secret;
wrappedMS.len = sid->u.ssl3.keys.wrapped_master_secret_len;
- /* unwrap the "master secret" which is actually RMS. */
- ss->ssl3.hs.resumptionMasterSecret = ssl_unwrapSymKey(
- wrapKey, sid->u.ssl3.masterWrapMech,
- NULL, &wrappedMS,
- CKM_SSL3_MASTER_KEY_DERIVE,
- CKA_DERIVE,
- tls13_GetHashSizeForHash(hashType),
- CKF_SIGN | CKF_VERIFY, ss->pkcs11PinArg);
+ PK11SymKey *unwrappedPsk = ssl_unwrapSymKey(wrapKey, sid->u.ssl3.masterWrapMech,
+ NULL, &wrappedMS, CKM_SSL3_MASTER_KEY_DERIVE,
+ CKA_DERIVE, tls13_GetHashSizeForHash(hashType),
+ CKF_SIGN | CKF_VERIFY, ss->pkcs11PinArg);
PK11_FreeSymKey(wrapKey);
- if (!ss->ssl3.hs.resumptionMasterSecret) {
+ if (!unwrappedPsk) {
return SECFailure;
}
+ sslPsk *rpsk = tls13_MakePsk(unwrappedPsk, ssl_psk_resume, hashType, NULL);
+ if (!rpsk) {
+ PK11_FreeSymKey(unwrappedPsk);
+ return SECFailure;
+ }
+ if (sid->u.ssl3.locked.sessionTicket.flags & ticket_allow_early_data) {
+ rpsk->maxEarlyData = sid->u.ssl3.locked.sessionTicket.max_early_data_size;
+ rpsk->zeroRttSuite = sid->u.ssl3.cipherSuite;
+ }
+ PRINT_KEY(50, (ss, "Recovered RMS", rpsk->key));
+ PORT_Assert(PR_CLIST_IS_EMPTY(&ss->ssl3.hs.psks) ||
+ ((sslPsk *)PR_LIST_HEAD(&ss->ssl3.hs.psks))->type != ssl_psk_resume);
- PRINT_KEY(50, (ss, "Recovered RMS", ss->ssl3.hs.resumptionMasterSecret));
+ if (ss->sec.isServer) {
+ /* In server, we couldn't select the RPSK in the extension handler
+ * since it was not unwrapped yet. We're committed now, so select
+ * it and add it to the list (to ensure it is freed). */
+ ss->xtnData.selectedPsk = rpsk;
+ }
+ PR_APPEND_LINK(&rpsk->link, &ss->ssl3.hs.psks);
return SECSuccess;
}
@@ -1060,38 +1110,45 @@ tls13_RecoverWrappedSharedSecret(sslSocket *ss, sslSessionID *sid)
* = resumption_master_secret
*
*/
-
static SECStatus
-tls13_ComputeEarlySecrets(sslSocket *ss)
+tls13_ComputeEarlySecretsWithPsk(sslSocket *ss)
{
- SECStatus rv = SECSuccess;
+ SECStatus rv;
SSL_TRC(5, ("%d: TLS13[%d]: compute early secrets (%s)",
SSL_GETPID(), ss->fd, SSL_ROLE(ss)));
- /* Extract off the resumptionMasterSecret (if present), else pass the NULL
- * resumptionMasterSecret which will be internally translated to zeroes. */
PORT_Assert(!ss->ssl3.hs.currentSecret);
- rv = tls13_HkdfExtract(NULL, ss->ssl3.hs.resumptionMasterSecret,
- tls13_GetHash(ss), &ss->ssl3.hs.currentSecret);
+ sslPsk *psk = NULL;
+
+ if (ss->sec.isServer) {
+ psk = ss->xtnData.selectedPsk;
+ } else {
+ /* Client to use the first PSK for early secrets. */
+ PORT_Assert(!PR_CLIST_IS_EMPTY(&ss->ssl3.hs.psks));
+ psk = (sslPsk *)PR_LIST_HEAD(&ss->ssl3.hs.psks);
+ }
+ PORT_Assert(psk && psk->key);
+ PORT_Assert(psk->hash != ssl_hash_none);
+
+ PK11SymKey *earlySecret = NULL;
+ rv = tls13_HkdfExtract(NULL, psk->key, psk->hash, &earlySecret);
if (rv != SECSuccess) {
return SECFailure;
}
- PORT_Assert(ss->statelessResume == (ss->ssl3.hs.resumptionMasterSecret != NULL));
- if (ss->statelessResume) {
- PK11_FreeSymKey(ss->ssl3.hs.resumptionMasterSecret);
- ss->ssl3.hs.resumptionMasterSecret = NULL;
-
- rv = tls13_DeriveSecretNullHash(ss, ss->ssl3.hs.currentSecret,
- kHkdfLabelPskBinderKey,
- strlen(kHkdfLabelPskBinderKey),
- &ss->ssl3.hs.pskBinderKey);
- if (rv != SECSuccess) {
- return SECFailure;
- }
+ /* No longer need the raw input key */
+ PK11_FreeSymKey(psk->key);
+ psk->key = NULL;
+ const char *label = (psk->type == ssl_psk_resume) ? kHkdfLabelResPskBinderKey : kHkdfLabelExtPskBinderKey;
+ rv = tls13_DeriveSecretNullHash(ss, earlySecret,
+ label, strlen(label),
+ &psk->binderKey, psk->hash);
+ if (rv != SECSuccess) {
+ PK11_FreeSymKey(earlySecret);
+ return SECFailure;
}
- PORT_Assert(!ss->ssl3.hs.resumptionMasterSecret);
+ ss->ssl3.hs.currentSecret = earlySecret;
return SECSuccess;
}
@@ -1101,7 +1158,7 @@ static SECStatus
tls13_DeriveEarlySecrets(sslSocket *ss)
{
SECStatus rv;
-
+ PORT_Assert(ss->ssl3.hs.currentSecret);
rv = tls13_DeriveSecretWrap(ss, ss->ssl3.hs.currentSecret,
kHkdfLabelClient,
kHkdfLabelEarlyTrafficSecret,
@@ -1139,7 +1196,15 @@ tls13_ComputeHandshakeSecrets(sslSocket *ss)
SSL_TRC(5, ("%d: TLS13[%d]: compute handshake secrets (%s)",
SSL_GETPID(), ss->fd, SSL_ROLE(ss)));
- /* First update |currentSecret| to add |dheSecret|, if any. */
+ /* If no PSK, generate the default early secret. */
+ if (!ss->ssl3.hs.currentSecret) {
+ PORT_Assert(!ss->xtnData.selectedPsk);
+ rv = tls13_HkdfExtract(NULL, NULL,
+ tls13_GetHash(ss), &ss->ssl3.hs.currentSecret);
+ if (rv != SECSuccess) {
+ return SECFailure;
+ }
+ }
PORT_Assert(ss->ssl3.hs.currentSecret);
PORT_Assert(ss->ssl3.hs.dheSecret);
@@ -1147,7 +1212,7 @@ tls13_ComputeHandshakeSecrets(sslSocket *ss)
rv = tls13_DeriveSecretNullHash(ss, ss->ssl3.hs.currentSecret,
kHkdfLabelDerivedSecret,
strlen(kHkdfLabelDerivedSecret),
- &derivedSecret);
+ &derivedSecret, tls13_GetHash(ss));
if (rv != SECSuccess) {
LOG_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE);
return rv;
@@ -1206,7 +1271,7 @@ tls13_ComputeHandshakeSecrets(sslSocket *ss)
rv = tls13_DeriveSecretNullHash(ss, ss->ssl3.hs.currentSecret,
kHkdfLabelDerivedSecret,
strlen(kHkdfLabelDerivedSecret),
- &derivedSecret);
+ &derivedSecret, tls13_GetHash(ss));
if (rv != SECSuccess) {
LOG_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE);
return rv;
@@ -1278,7 +1343,7 @@ tls13_ComputeFinalSecrets(sslSocket *ss)
PORT_Assert(!ss->ssl3.crSpec->masterSecret);
PORT_Assert(!ss->ssl3.cwSpec->masterSecret);
-
+ PORT_Assert(ss->ssl3.hs.currentSecret);
rv = tls13_DeriveSecretWrap(ss, ss->ssl3.hs.currentSecret,
NULL, kHkdfLabelResumptionMasterSecret,
NULL,
@@ -1319,7 +1384,14 @@ tls13_CanResume(sslSocket *ss, const sslSessionID *sid)
return PR_FALSE;
}
+#ifdef UNSAFE_FUZZER_MODE
+ /* When fuzzing, sid could contain garbage that will crash tls13_GetHashForCipherSuite.
+ * Do a direct comparison of cipher suites. This makes us refuse to resume when the
+ * protocol allows it, but resumption is discretionary anyway. */
+ if (sid->u.ssl3.cipherSuite != ss->ssl3.hs.cipher_suite) {
+#else
if (tls13_GetHashForCipherSuite(sid->u.ssl3.cipherSuite) != tls13_GetHashForCipherSuite(ss->ssl3.hs.cipher_suite)) {
+#endif
return PR_FALSE;
}
@@ -1339,21 +1411,40 @@ static PRBool
tls13_CanNegotiateZeroRtt(sslSocket *ss, const sslSessionID *sid)
{
PORT_Assert(ss->ssl3.hs.zeroRttState == ssl_0rtt_sent);
+ sslPsk *psk = ss->xtnData.selectedPsk;
- if (!sid)
+ if (!ss->opt.enable0RttData) {
return PR_FALSE;
- PORT_Assert(ss->statelessResume);
- if (!ss->statelessResume)
+ }
+ if (!psk) {
return PR_FALSE;
- if (ss->ssl3.hs.cipher_suite != sid->u.ssl3.cipherSuite)
+ }
+ if (psk->zeroRttSuite == TLS_NULL_WITH_NULL_NULL) {
return PR_FALSE;
- if (!ss->opt.enable0RttData)
+ }
+ if (!psk->maxEarlyData) {
return PR_FALSE;
- if (!(sid->u.ssl3.locked.sessionTicket.flags & ticket_allow_early_data))
+ }
+ if (ss->ssl3.hs.cipher_suite != psk->zeroRttSuite) {
return PR_FALSE;
- if (SECITEM_CompareItem(&ss->xtnData.nextProto,
- &sid->u.ssl3.alpnSelection) != 0)
+ }
+ if (psk->type == ssl_psk_resume) {
+ if (!sid) {
+ return PR_FALSE;
+ }
+ PORT_Assert(sid->u.ssl3.locked.sessionTicket.flags & ticket_allow_early_data);
+ PORT_Assert(ss->statelessResume);
+ if (!ss->statelessResume) {
+ return PR_FALSE;
+ }
+ if (SECITEM_CompareItem(&ss->xtnData.nextProto,
+ &sid->u.ssl3.alpnSelection) != 0) {
+ return PR_FALSE;
+ }
+ } else if (psk->type != ssl_psk_external) {
+ PORT_Assert(0);
return PR_FALSE;
+ }
if (tls13_IsReplay(ss, sid)) {
return PR_FALSE;
@@ -1406,7 +1497,7 @@ tls13_NegotiateZeroRtt(sslSocket *ss, const sslSessionID *sid)
}
SSL_TRC(3, ("%d: TLS13[%d]: enable 0-RTT", SSL_GETPID(), ss->fd));
- PORT_Assert(ss->statelessResume);
+ PORT_Assert(ss->xtnData.selectedPsk);
ss->ssl3.hs.zeroRttState = ssl_0rtt_accepted;
ss->ssl3.hs.zeroRttIgnore = ssl_0rtt_ignore_none;
ss->ssl3.hs.zeroRttSuite = ss->ssl3.hs.cipher_suite;
@@ -1458,7 +1549,7 @@ tls13_NegotiateKeyExchange(sslSocket *ss,
const sslNamedGroupDef *preferredGroup = NULL;
/* We insist on DHE. */
- if (ss->statelessResume) {
+ if (ssl3_ExtensionNegotiated(ss, ssl_tls13_pre_shared_key_xtn)) {
if (!ssl3_ExtensionNegotiated(ss, ssl_tls13_psk_key_exchange_modes_xtn)) {
FATAL_ERROR(ss, SSL_ERROR_MISSING_PSK_KEY_EXCHANGE_MODES,
missing_extension);
@@ -1482,8 +1573,8 @@ tls13_NegotiateKeyExchange(sslSocket *ss,
return SECFailure;
}
- SSL_TRC(3, ("%d: TLS13[%d]: selected KE = %s",
- SSL_GETPID(), ss->fd, ss->statelessResume ? "PSK + (EC)DHE" : "(EC)DHE"));
+ SSL_TRC(3, ("%d: TLS13[%d]: selected KE = %s", SSL_GETPID(),
+ ss->fd, ss->statelessResume || ss->xtnData.selectedPsk ? "PSK + (EC)DHE" : "(EC)DHE"));
/* Find the preferred group and an according client key share available. */
for (index = 0; index < SSL_NAMED_GROUP_COUNT; ++index) {
@@ -1671,26 +1762,42 @@ tls13_MaybeSendHelloRetry(sslSocket *ss, const sslNamedGroupDef *requestedGroup,
static SECStatus
tls13_NegotiateAuthentication(sslSocket *ss)
{
- SECStatus rv;
-
if (ss->statelessResume) {
- SSL_TRC(3, ("%d: TLS13[%d]: selected PSK authentication",
+ SSL_TRC(3, ("%d: TLS13[%d]: selected resumption PSK authentication",
SSL_GETPID(), ss->fd));
ss->ssl3.hs.signatureScheme = ssl_sig_none;
ss->ssl3.hs.kea_def_mutable.authKeyType = ssl_auth_psk;
+ /* Overwritten by tls13_RestoreCipherInfo. */
+ ss->sec.authType = ssl_auth_psk;
return SECSuccess;
+ } else if (ss->xtnData.selectedPsk) {
+ /* If the EPSK doesn't specify a suite, use what was negotiated.
+ * Else, only use the EPSK if we negotiated that suite. */
+ if (ss->xtnData.selectedPsk->zeroRttSuite == TLS_NULL_WITH_NULL_NULL ||
+ ss->ssl3.hs.cipher_suite == ss->xtnData.selectedPsk->zeroRttSuite) {
+ SSL_TRC(3, ("%d: TLS13[%d]: selected external PSK authentication",
+ SSL_GETPID(), ss->fd));
+ ss->ssl3.hs.signatureScheme = ssl_sig_none;
+ ss->ssl3.hs.kea_def_mutable.authKeyType = ssl_auth_psk;
+ ss->sec.authType = ssl_auth_psk;
+ return SECSuccess;
+ }
+ }
+
+ /* If there were PSKs, they are no longer needed. */
+ if (ss->xtnData.selectedPsk) {
+ tls13_DestroyPskList(&ss->ssl3.hs.psks);
+ ss->xtnData.selectedPsk = NULL;
}
SSL_TRC(3, ("%d: TLS13[%d]: selected certificate authentication",
SSL_GETPID(), ss->fd));
- /* We've now established that we need to sign.... */
- rv = tls13_SelectServerCert(ss);
+ SECStatus rv = tls13_SelectServerCert(ss);
if (rv != SECSuccess) {
return SECFailure;
}
return SECSuccess;
}
-
/* Called from ssl3_HandleClientHello after we have parsed the
* ClientHello and are sure that we are going to do TLS 1.3
* or fail. */
@@ -1854,40 +1961,51 @@ tls13_HandleClientHelloPart2(sslSocket *ss,
goto loser;
}
- if (ss->statelessResume) {
- /* We are now committed to trying to resume. */
- PORT_Assert(sid);
-
- /* Check that the negotiated SNI and the cached SNI match. */
- if (SECITEM_CompareItem(&sid->u.ssl3.srvName,
- &ss->ssl3.hs.srvVirtName) != SECEqual) {
- FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_CLIENT_HELLO,
- handshake_failure);
- goto loser;
- }
+ if (ss->sec.authType == ssl_auth_psk) {
+ if (ss->statelessResume) {
+ /* We are now committed to trying to resume. */
+ PORT_Assert(sid);
+ /* Check that the negotiated SNI and the cached SNI match. */
+ if (SECITEM_CompareItem(&sid->u.ssl3.srvName,
+ &ss->ssl3.hs.srvVirtName) != SECEqual) {
+ FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_CLIENT_HELLO,
+ handshake_failure);
+ goto loser;
+ }
- ss->sec.serverCert = ssl_FindServerCert(ss, sid->authType,
- sid->namedCurve);
- PORT_Assert(ss->sec.serverCert);
+ ss->sec.serverCert = ssl_FindServerCert(ss, sid->authType,
+ sid->namedCurve);
+ PORT_Assert(ss->sec.serverCert);
- rv = tls13_RecoverWrappedSharedSecret(ss, sid);
- if (rv != SECSuccess) {
- SSL_AtomicIncrementLong(&ssl3stats->hch_sid_cache_not_ok);
- FATAL_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE, internal_error);
- goto loser;
- }
- tls13_RestoreCipherInfo(ss, sid);
+ rv = tls13_RecoverWrappedSharedSecret(ss, sid);
+ if (rv != SECSuccess) {
+ SSL_AtomicIncrementLong(&ssl3stats->hch_sid_cache_not_ok);
+ FATAL_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE, internal_error);
+ goto loser;
+ }
+ tls13_RestoreCipherInfo(ss, sid);
- ss->sec.localCert = CERT_DupCertificate(ss->sec.serverCert->serverCert);
- if (sid->peerCert != NULL) {
- ss->sec.peerCert = CERT_DupCertificate(sid->peerCert);
+ ss->sec.localCert = CERT_DupCertificate(ss->sec.serverCert->serverCert);
+ if (sid->peerCert != NULL) {
+ ss->sec.peerCert = CERT_DupCertificate(sid->peerCert);
+ }
+ } else if (sid) {
+ /* We should never have a SID in the non-resumption case. */
+ PORT_Assert(0);
+ ssl_UncacheSessionID(ss);
+ ssl_FreeSID(sid);
+ sid = NULL;
}
-
ssl3_RegisterExtensionSender(
ss, &ss->xtnData,
ssl_tls13_pre_shared_key_xtn, tls13_ServerSendPreSharedKeyXtn);
-
tls13_NegotiateZeroRtt(ss, sid);
+
+ rv = tls13_ComputeEarlySecretsWithPsk(ss);
+ if (rv != SECSuccess) {
+ FATAL_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE, internal_error);
+ return SECFailure;
+ }
} else {
if (sid) { /* we had a sid, but it's no longer valid, free it */
SSL_AtomicIncrementLong(&ssl3stats->hch_sid_cache_not_ok);
@@ -1898,35 +2016,34 @@ tls13_HandleClientHelloPart2(sslSocket *ss,
tls13_NegotiateZeroRtt(ss, NULL);
}
- /* Need to compute early secrets. */
- rv = tls13_ComputeEarlySecrets(ss);
- if (rv != SECSuccess) {
- FATAL_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE, internal_error);
- return SECFailure;
+ if (ss->statelessResume) {
+ PORT_Assert(ss->xtnData.selectedPsk);
+ PORT_Assert(ss->ssl3.hs.kea_def_mutable.authKeyType == ssl_auth_psk);
}
- /* Now that we have the binder key check the binder. */
- if (ss->statelessResume) {
+ /* Now that we have the binder key, check the binder. */
+ if (ss->xtnData.selectedPsk) {
SSL3Hashes hashes;
-
PORT_Assert(ss->ssl3.hs.messages.len > ss->xtnData.pskBindersLen);
rv = tls13_ComputePskBinderHash(
ss,
ss->ssl3.hs.messages.len - ss->xtnData.pskBindersLen,
- &hashes);
+ &hashes, tls13_GetHash(ss));
if (rv != SECSuccess) {
FATAL_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE, internal_error);
goto loser;
}
+ PORT_Assert(ss->xtnData.selectedPsk->hash == tls13_GetHash(ss));
+ PORT_Assert(ss->ssl3.hs.suite_def);
rv = tls13_VerifyFinished(ss, ssl_hs_client_hello,
- ss->ssl3.hs.pskBinderKey,
+ ss->xtnData.selectedPsk->binderKey,
ss->xtnData.pskBinder.data,
ss->xtnData.pskBinder.len,
&hashes);
- if (rv != SECSuccess) {
- goto loser;
- }
+ }
+ if (rv != SECSuccess) {
+ goto loser;
}
/* This needs to go after we verify the psk binder. */
@@ -1953,7 +2070,7 @@ tls13_HandleClientHelloPart2(sslSocket *ss,
SSL_AtomicIncrementLong(&ssl3stats->hch_sid_cache_not_ok);
ssl_UncacheSessionID(ss);
ssl_FreeSID(sid);
- } else {
+ } else if (!ss->xtnData.selectedPsk) {
SSL_AtomicIncrementLong(&ssl3stats->hch_sid_cache_misses);
}
@@ -1983,6 +2100,10 @@ tls13_HandleClientHelloPart2(sslSocket *ss,
return SECFailure;
}
+ /* We're done with PSKs */
+ tls13_DestroyPskList(&ss->ssl3.hs.psks);
+ ss->xtnData.selectedPsk = NULL;
+
return SECSuccess;
loser:
@@ -2314,7 +2435,8 @@ tls13_ReinjectHandshakeTranscript(sslSocket *ss)
// First compute the hash.
rv = tls13_ComputeHash(ss, &hashes,
ss->ssl3.hs.messages.buf,
- ss->ssl3.hs.messages.len);
+ ss->ssl3.hs.messages.len,
+ tls13_GetHash(ss));
if (rv != SECSuccess) {
return SECFailure;
}
@@ -2331,7 +2453,6 @@ tls13_ReinjectHandshakeTranscript(sslSocket *ss)
return SECSuccess;
}
-
static unsigned int
ssl_ListCount(PRCList *list)
{
@@ -2454,6 +2575,12 @@ tls13_HandleCertificateRequest(sslSocket *ss, PRUint8 *b, PRUint32 length)
return SECFailure;
}
+ /* MUST NOT combine external PSKs with certificate authentication. */
+ if (ss->sec.authType == ssl_auth_psk) {
+ FATAL_ERROR(ss, SSL_ERROR_RX_UNEXPECTED_CERT_REQUEST, unexpected_message);
+ return SECFailure;
+ }
+
if (tls13_IsPostHandshake(ss)) {
PORT_Assert(ss->ssl3.hs.shaPostHandshake == NULL);
ss->ssl3.hs.shaPostHandshake = PK11_CloneContext(ss->ssl3.hs.sha);
@@ -2569,6 +2696,8 @@ tls13_HandleCertificateRequest(sslSocket *ss, PRUint8 *b, PRUint32 length)
PRBool
tls13_ShouldRequestClientAuth(sslSocket *ss)
{
+ /* Even if we are configured to request a certificate, we can't
+ * if this handshake used a PSK, even when we are resuming. */
return ss->opt.requestCertificate &&
ss->ssl3.hs.kea_def->authKeyType != ssl_auth_psk;
}
@@ -2737,7 +2866,9 @@ tls13_SendServerHelloSequence(sslSocket *ss)
}
}
- ss->ssl3.hs.serverHelloTime = ssl_Time(ss);
+ /* Here we set a baseline value for our RTT estimation.
+ * This value is updated when we get a response from the client. */
+ ss->ssl3.hs.rttEstimate = ssl_Time(ss);
return SECSuccess;
}
@@ -2749,14 +2880,22 @@ tls13_HandleServerHelloPart2(sslSocket *ss)
SSL3Statistics *ssl3stats = SSL_GetStatistics();
if (ssl3_ExtensionNegotiated(ss, ssl_tls13_pre_shared_key_xtn)) {
- PORT_Assert(ss->statelessResume);
+ PORT_Assert(!PR_CLIST_IS_EMPTY(&ss->ssl3.hs.psks));
+ PORT_Assert(ss->xtnData.selectedPsk);
+
+ if (ss->xtnData.selectedPsk->type != ssl_psk_resume) {
+ ss->statelessResume = PR_FALSE;
+ }
} else {
+ /* We may have offered a PSK. If the server didn't negotiate
+ * it, clear this state to re-extract the Early Secret. */
if (ss->ssl3.hs.currentSecret) {
- PORT_Assert(ss->statelessResume);
+ PORT_Assert(ssl3_ExtensionAdvertised(ss, ssl_tls13_pre_shared_key_xtn));
PK11_FreeSymKey(ss->ssl3.hs.currentSecret);
ss->ssl3.hs.currentSecret = NULL;
}
ss->statelessResume = PR_FALSE;
+ ss->xtnData.selectedPsk = NULL;
}
if (ss->statelessResume) {
@@ -2773,19 +2912,22 @@ tls13_HandleServerHelloPart2(sslSocket *ss)
ss->ssl3.hs.kea_def_mutable = *ss->ssl3.hs.kea_def;
ss->ssl3.hs.kea_def = &ss->ssl3.hs.kea_def_mutable;
- if (ss->statelessResume) {
- /* PSK */
+ if (ss->xtnData.selectedPsk) {
ss->ssl3.hs.kea_def_mutable.authKeyType = ssl_auth_psk;
- tls13_RestoreCipherInfo(ss, sid);
- if (sid->peerCert) {
- ss->sec.peerCert = CERT_DupCertificate(sid->peerCert);
- }
+ if (ss->statelessResume) {
+ tls13_RestoreCipherInfo(ss, sid);
+ if (sid->peerCert) {
+ ss->sec.peerCert = CERT_DupCertificate(sid->peerCert);
+ }
- SSL_AtomicIncrementLong(&ssl3stats->hsh_sid_cache_hits);
- SSL_AtomicIncrementLong(&ssl3stats->hsh_sid_stateless_resumes);
+ SSL_AtomicIncrementLong(&ssl3stats->hsh_sid_cache_hits);
+ SSL_AtomicIncrementLong(&ssl3stats->hsh_sid_stateless_resumes);
+ } else {
+ ss->sec.authType = ssl_auth_psk;
+ }
} else {
- /* !PSK */
- if (ssl3_ExtensionAdvertised(ss, ssl_tls13_pre_shared_key_xtn)) {
+ if (ss->statelessResume &&
+ ssl3_ExtensionAdvertised(ss, ssl_tls13_pre_shared_key_xtn)) {
SSL_AtomicIncrementLong(&ssl3stats->hsh_sid_cache_misses);
}
if (sid->cached == in_client_cache) {
@@ -2794,18 +2936,6 @@ tls13_HandleServerHelloPart2(sslSocket *ss)
}
}
- if (!ss->ssl3.hs.currentSecret) {
- PORT_Assert(!ss->statelessResume);
-
- /* If we don't already have the Early Secret we need to make it
- * now. */
- rv = tls13_ComputeEarlySecrets(ss);
- if (rv != SECSuccess) {
- FATAL_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE, internal_error);
- return SECFailure;
- }
- }
-
/* Discard current SID and make a new one, though it may eventually
* end up looking a lot like the old one.
*/
@@ -3105,6 +3235,13 @@ tls13_HandleCertificate(sslSocket *ss, PRUint8 *b, PRUint32 length)
PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
if (ss->sec.isServer) {
+ /* Receiving this message might be the first sign we have that
+ * early data is over, so pretend we received EOED. */
+ rv = tls13_MaybeHandleSuppressedEndOfEarlyData(ss);
+ if (rv != SECSuccess) {
+ return SECFailure; /* Code already set. */
+ }
+
if (ss->ssl3.clientCertRequested) {
rv = TLS13_CHECK_HS_STATE(ss, SSL_ERROR_RX_UNEXPECTED_CERTIFICATE,
idle_handshake);
@@ -3116,8 +3253,9 @@ tls13_HandleCertificate(sslSocket *ss, PRUint8 *b, PRUint32 length)
rv = TLS13_CHECK_HS_STATE(ss, SSL_ERROR_RX_UNEXPECTED_CERTIFICATE,
wait_cert_request, wait_server_cert);
}
- if (rv != SECSuccess)
+ if (rv != SECSuccess) {
return SECFailure;
+ }
/* We can ignore any other cleartext from the client. */
if (ss->sec.isServer && IS_DTLS(ss)) {
@@ -3131,6 +3269,11 @@ tls13_HandleCertificate(sslSocket *ss, PRUint8 *b, PRUint32 length)
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
return SECFailure;
}
+ } else if (ss->sec.isServer) {
+ /* Our first shot an getting an RTT estimate. If the client took extra
+ * time to fetch a certificate, this will be bad, but we can't do much
+ * about that. */
+ ss->ssl3.hs.rttEstimate = ssl_Time(ss) - ss->ssl3.hs.rttEstimate;
}
/* Process the context string */
@@ -3302,15 +3445,14 @@ tls13_DeriveSecret(sslSocket *ss, PK11SymKey *key,
const char *label,
unsigned int labelLen,
const SSL3Hashes *hashes,
- PK11SymKey **dest)
+ PK11SymKey **dest,
+ SSLHashType hash)
{
SECStatus rv;
- rv = tls13_HkdfExpandLabel(key, tls13_GetHash(ss),
- hashes->u.raw, hashes->len,
- label, labelLen,
- CKM_HKDF_DERIVE,
- tls13_GetHashSize(ss),
+ rv = tls13_HkdfExpandLabel(key, hash, hashes->u.raw, hashes->len,
+ label, labelLen, CKM_HKDF_DERIVE,
+ tls13_GetHashSizeForHash(hash),
ss->protocolVariant, dest);
if (rv != SECSuccess) {
LOG_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE);
@@ -3324,18 +3466,19 @@ SECStatus
tls13_DeriveSecretNullHash(sslSocket *ss, PK11SymKey *key,
const char *label,
unsigned int labelLen,
- PK11SymKey **dest)
+ PK11SymKey **dest,
+ SSLHashType hash)
{
SSL3Hashes hashes;
SECStatus rv;
PRUint8 buf[] = { 0 };
- rv = tls13_ComputeHash(ss, &hashes, buf, 0);
+ rv = tls13_ComputeHash(ss, &hashes, buf, 0, hash);
if (rv != SECSuccess) {
return SECFailure;
}
- return tls13_DeriveSecret(ss, key, label, labelLen, &hashes, dest);
+ return tls13_DeriveSecret(ss, key, label, labelLen, &hashes, dest, hash);
}
/* Convenience wrapper that lets us supply a separate prefix and suffix. */
@@ -3374,7 +3517,7 @@ tls13_DeriveSecretWrap(sslSocket *ss, PK11SymKey *key,
}
rv = tls13_DeriveSecret(ss, key, label, strlen(label),
- &hashes, dest);
+ &hashes, dest, tls13_GetHash(ss));
if (rv != SECSuccess) {
return SECFailure;
}
@@ -3538,8 +3681,10 @@ tls13_SetupPendingCipherSpec(sslSocket *ss, ssl3CipherSpec *spec)
spec->cipherDef = ssl_GetBulkCipherDef(ssl_LookupCipherSuiteDef(suite));
if (spec->epoch == TrafficKeyEarlyApplicationData) {
- spec->earlyDataRemaining =
- ss->sec.ci.sid->u.ssl3.locked.sessionTicket.max_early_data_size;
+ if (ss->xtnData.selectedPsk &&
+ ss->xtnData.selectedPsk->zeroRttSuite != TLS_NULL_WITH_NULL_NULL) {
+ spec->earlyDataRemaining = ss->xtnData.selectedPsk->maxEarlyData;
+ }
}
tls13_SetSpecRecordVersion(ss, spec);
@@ -4005,7 +4150,7 @@ tls13_HandleEncryptedExtensions(sslSocket *ss, PRUint8 *b, PRUint32 length)
/* We can only get here if we offered 0-RTT. */
if (ssl3_ExtensionNegotiated(ss, ssl_tls13_early_data_xtn)) {
PORT_Assert(ss->ssl3.hs.zeroRttState == ssl_0rtt_sent);
- if (!ss->statelessResume) {
+ if (!ss->xtnData.selectedPsk) {
/* Illegal to accept 0-RTT without also accepting PSK. */
FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_ENCRYPTED_EXTENSIONS,
illegal_parameter);
@@ -4043,6 +4188,10 @@ tls13_HandleEncryptedExtensions(sslSocket *ss, PRUint8 *b, PRUint32 length)
TLS13_SET_HS_STATE(ss, wait_cert_request);
}
+ /* Client is done with any PSKs */
+ tls13_DestroyPskList(&ss->ssl3.hs.psks);
+ ss->xtnData.selectedPsk = NULL;
+
return SECSuccess;
}
@@ -4322,7 +4471,7 @@ loser:
static SECStatus
tls13_ComputePskBinderHash(sslSocket *ss, unsigned int prefixLength,
- SSL3Hashes *hashes)
+ SSL3Hashes *hashes, SSLHashType hashType)
{
SECStatus rv;
@@ -4332,14 +4481,14 @@ tls13_ComputePskBinderHash(sslSocket *ss, unsigned int prefixLength,
PRINT_BUF(10, (NULL, "Handshake hash computed over ClientHello prefix",
ss->ssl3.hs.messages.buf, prefixLength));
- rv = PK11_HashBuf(ssl3_HashTypeToOID(tls13_GetHash(ss)),
+ rv = PK11_HashBuf(ssl3_HashTypeToOID(hashType),
hashes->u.raw, ss->ssl3.hs.messages.buf, prefixLength);
if (rv != SECSuccess) {
ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE);
return SECFailure;
}
- hashes->len = tls13_GetHashSize(ss);
+ hashes->len = tls13_GetHashSizeForHash(hashType);
PRINT_BUF(10, (NULL, "PSK Binder hash", hashes->u.raw, hashes->len));
return SECSuccess;
@@ -4357,7 +4506,10 @@ tls13_WriteExtensionsWithBinder(sslSocket *ss, sslBuffer *extensions)
{
SSL3Hashes hashes;
SECStatus rv;
- unsigned int size = tls13_GetHashSize(ss);
+
+ PORT_Assert(!PR_CLIST_IS_EMPTY(&ss->ssl3.hs.psks));
+ sslPsk *psk = (sslPsk *)PR_LIST_HEAD(&ss->ssl3.hs.psks);
+ unsigned int size = tls13_GetHashSizeForHash(psk->hash);
unsigned int prefixLen = extensions->len - size - 3;
unsigned int finishedLen;
@@ -4378,15 +4530,18 @@ tls13_WriteExtensionsWithBinder(sslSocket *ss, sslBuffer *extensions)
}
/* Calculate the binder based on what has been written out. */
- rv = tls13_ComputePskBinderHash(ss, ss->ssl3.hs.messages.len, &hashes);
+ rv = tls13_ComputePskBinderHash(ss, ss->ssl3.hs.messages.len,
+ &hashes, psk->hash);
if (rv != SECSuccess) {
return SECFailure;
}
/* Write the binder into the extensions buffer, over the zeros we reserved
- * previously. This avoids an allocation and means that we don't need a
+ * previously. This avoids an allocation and means that we don't need a
* separate write for the extra bits that precede the binder. */
- rv = tls13_ComputeFinished(ss, ss->ssl3.hs.pskBinderKey, &hashes, PR_TRUE,
+ PORT_Assert(psk->binderKey);
+ rv = tls13_ComputeFinished(ss, psk->binderKey,
+ psk->hash, &hashes, PR_TRUE,
extensions->buf + extensions->len - size,
&finishedLen, size);
if (rv != SECSuccess) {
@@ -4406,13 +4561,13 @@ tls13_WriteExtensionsWithBinder(sslSocket *ss, sslBuffer *extensions)
static SECStatus
tls13_ComputeFinished(sslSocket *ss, PK11SymKey *baseKey,
- const SSL3Hashes *hashes,
+ SSLHashType hashType, const SSL3Hashes *hashes,
PRBool sending, PRUint8 *output, unsigned int *outputLen,
unsigned int maxOutputLen)
{
SECStatus rv;
PK11Context *hmacCtx = NULL;
- CK_MECHANISM_TYPE macAlg = tls13_GetHmacMechanism(ss);
+ CK_MECHANISM_TYPE macAlg = tls13_GetHmacMechanismFromHash(hashType);
SECItem param = { siBuffer, NULL, 0 };
unsigned int outputLenUint;
const char *label = kHkdfLabelFinishedSecret;
@@ -4424,18 +4579,16 @@ tls13_ComputeFinished(sslSocket *ss, PK11SymKey *baseKey,
PRINT_BUF(50, (ss, "Handshake hash", hashes->u.raw, hashes->len));
/* Now derive the appropriate finished secret from the base secret. */
- rv = tls13_HkdfExpandLabel(baseKey,
- tls13_GetHash(ss),
- NULL, 0,
- label, strlen(label),
- tls13_GetHmacMechanism(ss),
- tls13_GetHashSize(ss),
+ rv = tls13_HkdfExpandLabel(baseKey, hashType,
+ NULL, 0, label, strlen(label),
+ tls13_GetHmacMechanismFromHash(hashType),
+ tls13_GetHashSizeForHash(hashType),
ss->protocolVariant, &secret);
if (rv != SECSuccess) {
goto abort;
}
- PORT_Assert(hashes->len == tls13_GetHashSize(ss));
+ PORT_Assert(hashes->len == tls13_GetHashSizeForHash(hashType));
hmacCtx = PK11_CreateContextBySymKey(macAlg, CKA_SIGN,
secret, &param);
if (!hmacCtx) {
@@ -4450,7 +4603,7 @@ tls13_ComputeFinished(sslSocket *ss, PK11SymKey *baseKey,
if (rv != SECSuccess)
goto abort;
- PORT_Assert(maxOutputLen >= tls13_GetHashSize(ss));
+ PORT_Assert(maxOutputLen >= tls13_GetHashSizeForHash(hashType));
rv = PK11_DigestFinal(hmacCtx, output, &outputLenUint, maxOutputLen);
if (rv != SECSuccess)
goto abort;
@@ -4494,7 +4647,7 @@ tls13_SendFinished(sslSocket *ss, PK11SymKey *baseKey)
}
ssl_GetSpecReadLock(ss);
- rv = tls13_ComputeFinished(ss, baseKey, &hashes, PR_TRUE,
+ rv = tls13_ComputeFinished(ss, baseKey, tls13_GetHash(ss), &hashes, PR_TRUE,
finishedBuf, &finishedLen, sizeof(finishedBuf));
ssl_ReleaseSpecReadLock(ss);
if (rv != SECSuccess) {
@@ -4531,7 +4684,7 @@ tls13_VerifyFinished(sslSocket *ss, SSLHandshakeType message,
return SECFailure;
}
- rv = tls13_ComputeFinished(ss, secret, hashes, PR_FALSE,
+ rv = tls13_ComputeFinished(ss, secret, tls13_GetHash(ss), hashes, PR_FALSE,
finishedBuf, &finishedLen, sizeof(finishedBuf));
if (rv != SECSuccess) {
FATAL_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE, internal_error);
@@ -4621,6 +4774,20 @@ tls13_ServerHandleFinished(sslSocket *ss, PRUint8 *b, PRUint32 length)
SSL_TRC(3, ("%d: TLS13[%d]: server handle finished handshake",
SSL_GETPID(), ss->fd));
+ if (!tls13_ShouldRequestClientAuth(ss)) {
+ /* Receiving this message might be the first sign we have that
+ * early data is over, so pretend we received EOED. */
+ rv = tls13_MaybeHandleSuppressedEndOfEarlyData(ss);
+ if (rv != SECSuccess) {
+ return SECFailure; /* Code already set. */
+ }
+
+ if (!tls13_IsPostHandshake(ss)) {
+ /* Finalize the RTT estimate. */
+ ss->ssl3.hs.rttEstimate = ssl_Time(ss) - ss->ssl3.hs.rttEstimate;
+ }
+ }
+
rv = tls13_CommonHandleFinished(ss,
ss->firstHsDone ? ss->ssl3.hs.clientTrafficSecret : ss->ssl3.hs.clientHsTrafficSecret,
b, length);
@@ -4684,7 +4851,8 @@ tls13_ServerHandleFinished(sslSocket *ss, PRUint8 *b, PRUint32 length)
}
ssl_GetXmitBufLock(ss);
- if (ss->opt.enableSessionTickets) {
+ /* If resumption, authType is the original value and not ssl_auth_psk. */
+ if (ss->opt.enableSessionTickets && ss->sec.authType != ssl_auth_psk) {
rv = tls13_SendNewSessionTicket(ss, NULL, 0);
if (rv != SECSuccess) {
goto loser;
@@ -5067,6 +5235,14 @@ SSLExp_SendSessionTicket(PRFileDesc *fd, const PRUint8 *token,
return SECFailure;
}
+ /* Disable tickets if we can trace this connection back to a PSK.
+ * We aren't able to issue tickets (currently) without a certificate.
+ * As PSK =~ resumption, there is no reason to do this. */
+ if (ss->sec.authType == ssl_auth_psk) {
+ PORT_SetError(SSL_ERROR_FEATURE_DISABLED);
+ return SECFailure;
+ }
+
ssl_GetSSL3HandshakeLock(ss);
ssl_GetXmitBufLock(ss);
rv = tls13_SendNewSessionTicket(ss, token, tokenLen);
@@ -5541,6 +5717,10 @@ tls13_UnprotectRecord(sslSocket *ss,
cText->buf->buf, /* in */
cText->buf->len); /* inlen */
if (rv != SECSuccess) {
+ if (IS_DTLS(ss)) {
+ spec->deprotectionFailures++;
+ }
+
SSL_TRC(3,
("%d: TLS13[%d]: record has bogus MAC",
SSL_GETPID(), ss->fd));
@@ -5601,9 +5781,10 @@ tls13_UnprotectRecord(sslSocket *ss,
* 1. We are doing TLS 1.3
* 2. This isn't a second ClientHello (in response to HelloRetryRequest)
* 3. The 0-RTT option is set.
- * 4. We have a valid ticket.
- * 5. The server is willing to accept 0-RTT.
- * 6. We have not changed our ALPN settings to disallow the ALPN tag
+ * 4. We have a valid ticket or an External PSK.
+ * 5. If resuming:
+ * 5a. The server is willing to accept 0-RTT.
+ * 5b. We have not changed our ALPN settings to disallow the ALPN tag
* in the ticket.
*
* Called from tls13_ClientSendEarlyDataXtn().
@@ -5613,17 +5794,39 @@ tls13_ClientAllow0Rtt(const sslSocket *ss, const sslSessionID *sid)
{
/* We checked that the cipher suite was still allowed back in
* ssl3_SendClientHello. */
- if (sid->version < SSL_LIBRARY_VERSION_TLS_1_3)
+ if (sid->version < SSL_LIBRARY_VERSION_TLS_1_3) {
return PR_FALSE;
- if (ss->ssl3.hs.helloRetry)
+ }
+ if (ss->ssl3.hs.helloRetry) {
return PR_FALSE;
- if (!ss->opt.enable0RttData)
+ }
+ if (!ss->opt.enable0RttData) {
return PR_FALSE;
- if (!ss->statelessResume)
+ }
+ if (PR_CLIST_IS_EMPTY(&ss->ssl3.hs.psks)) {
return PR_FALSE;
- if ((sid->u.ssl3.locked.sessionTicket.flags & ticket_allow_early_data) == 0)
+ }
+ sslPsk *psk = (sslPsk *)PR_LIST_HEAD(&ss->ssl3.hs.psks);
+
+ if (psk->zeroRttSuite == TLS_NULL_WITH_NULL_NULL) {
return PR_FALSE;
- return ssl_AlpnTagAllowed(ss, &sid->u.ssl3.alpnSelection);
+ }
+ if (!psk->maxEarlyData) {
+ return PR_FALSE;
+ }
+
+ if (psk->type == ssl_psk_external) {
+ return psk->hash == tls13_GetHashForCipherSuite(psk->zeroRttSuite);
+ }
+ if (psk->type == ssl_psk_resume) {
+ if (!ss->statelessResume)
+ return PR_FALSE;
+ if ((sid->u.ssl3.locked.sessionTicket.flags & ticket_allow_early_data) == 0)
+ return PR_FALSE;
+ return ssl_AlpnTagAllowed(ss, &sid->u.ssl3.alpnSelection);
+ }
+ PORT_Assert(0);
+ return PR_FALSE;
}
SECStatus
@@ -5670,6 +5873,9 @@ tls13_MaybeDo0RTTHandshake(sslSocket *ss)
}
}
+ /* If we're trying 0-RTT, derive from the first PSK */
+ PORT_Assert(!PR_CLIST_IS_EMPTY(&ss->ssl3.hs.psks) && !ss->xtnData.selectedPsk);
+ ss->xtnData.selectedPsk = (sslPsk *)PR_LIST_HEAD(&ss->ssl3.hs.psks);
rv = tls13_DeriveEarlySecrets(ss);
if (rv != SECSuccess) {
return SECFailure;
@@ -5681,6 +5887,7 @@ tls13_MaybeDo0RTTHandshake(sslSocket *ss)
rv = tls13_SetCipherSpec(ss, TrafficKeyEarlyApplicationData,
ssl_secret_write, PR_TRUE);
+ ss->xtnData.selectedPsk = NULL;
if (rv != SECSuccess) {
return SECFailure;
}
@@ -5735,12 +5942,14 @@ tls13_SendEndOfEarlyData(sslSocket *ss)
{
SECStatus rv;
- SSL_TRC(3, ("%d: TLS13[%d]: send EndOfEarlyData", SSL_GETPID(), ss->fd));
PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
- rv = ssl3_AppendHandshakeHeader(ss, ssl_hs_end_of_early_data, 0);
- if (rv != SECSuccess) {
- return rv; /* err set by AppendHandshake. */
+ if (!ss->opt.suppressEndOfEarlyData) {
+ SSL_TRC(3, ("%d: TLS13[%d]: send EndOfEarlyData", SSL_GETPID(), ss->fd));
+ rv = ssl3_AppendHandshakeHeader(ss, ssl_hs_end_of_early_data, 0);
+ if (rv != SECSuccess) {
+ return rv; /* err set by AppendHandshake. */
+ }
}
ss->ssl3.hs.zeroRttState = ssl_0rtt_done;
@@ -5748,7 +5957,7 @@ tls13_SendEndOfEarlyData(sslSocket *ss)
}
static SECStatus
-tls13_HandleEndOfEarlyData(sslSocket *ss, PRUint8 *b, PRUint32 length)
+tls13_HandleEndOfEarlyData(sslSocket *ss, const PRUint8 *b, PRUint32 length)
{
SECStatus rv;
@@ -5791,6 +6000,18 @@ tls13_HandleEndOfEarlyData(sslSocket *ss, PRUint8 *b, PRUint32 length)
return SECSuccess;
}
+static SECStatus
+tls13_MaybeHandleSuppressedEndOfEarlyData(sslSocket *ss)
+{
+ PORT_Assert(ss->sec.isServer);
+ if (!ss->opt.suppressEndOfEarlyData ||
+ ss->ssl3.hs.zeroRttState != ssl_0rtt_accepted) {
+ return SECSuccess;
+ }
+
+ return tls13_HandleEndOfEarlyData(ss, NULL, 0);
+}
+
SECStatus
tls13_HandleEarlyApplicationData(sslSocket *ss, sslBuffer *origBuf)
{