diff options
Diffstat (limited to 'libs/nss/src/lib/ssl/tls13con.c')
-rw-r--r-- | libs/nss/src/lib/ssl/tls13con.c | 639 |
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, ¶m); 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) { |