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;
}
/* avoid pairwise check in non-FIPS mode */ /* the only difference between CKM_ML_KEM_KEY_PAIR_GEN and *CKM_NSS_ML_KEM_KEY_PAIR_GENisthelatterskipsthepairwiseconsistency
* check and is only supported by softoken */ if ((mechanism == CKM_ML_KEM_KEY_PAIR_GEN) && !PK11_IsFIPS() &&
PK11_DoesMechanism(slot, CKM_NSS_ML_KEM_KEY_PAIR_GEN)) {
mechanism = CKM_NSS_ML_KEM_KEY_PAIR_GEN;
}
/* only copy the ECDH component of an ephemeral KeyPair */
sslEphemeralKeyPair *
tls13_CopyECDHKeyFromHybrid(sslEphemeralKeyPair *copyKeyPair, const sslNamedGroupDef *groupDef)
{ /* We could use ssl_CopyEphemeralKeyPair here, but we would need to free
* the KEM components. So we only copy the ECDH keys */
sslEphemeralKeyPair *keyPair = PORT_ZNew(sslEphemeralKeyPair); if (!keyPair) { return NULL;
}
PR_INIT_CLIST(&keyPair->link);
keyPair->group = groupDef;
keyPair->keys = ssl_GetKeyPairRef(copyKeyPair->keys); return keyPair;
}
/* *findahybridkeyPairtheymightcontainthesameecdhkeysowe *canreusethem.EachecgroupcanmaptomorethanonehybridPair
*/
sslEphemeralKeyPair *
tls13_FindHybridKeyPair(sslSocket *ss, const sslNamedGroupDef *groupDef)
{
sslEphemeralKeyPair *hybridPair = NULL; switch (groupDef->name) { case ssl_grp_ec_secp256r1: /* future, this may be a loop to check multiple named groups */
hybridPair = ssl_LookupEphemeralKeyPair(ss,
ssl_LookupNamedGroup(ssl_grp_kem_secp256r1mlkem768)); break; case ssl_grp_ec_secp384r1:
hybridPair = ssl_LookupEphemeralKeyPair(ss,
ssl_LookupNamedGroup(ssl_grp_kem_secp384r1mlkem1024)); break; case ssl_grp_ec_curve25519: { /* a loop to check multiple named groups */
SSLNamedGroup gnames[] = { ssl_grp_kem_xyber768d00,
ssl_grp_kem_mlkem768x25519 }; for (int i = 0; i < PR_ARRAY_SIZE(gnames); i++) {
hybridPair = ssl_LookupEphemeralKeyPair(ss,
ssl_LookupNamedGroup(gnames[i])); if (hybridPair != NULL) { break;
}
} break;
} default:
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); return NULL;
} return hybridPair;
}
PORT_Assert(groupDef); switch (groupDef->keaType) { case ssl_kea_ecdh_hybrid: switch (groupDef->name) { case ssl_grp_kem_secp256r1mlkem768:
ecGroup = ssl_LookupNamedGroup(ssl_grp_ec_secp256r1); break; case ssl_grp_kem_secp384r1mlkem1024:
ecGroup = ssl_LookupNamedGroup(ssl_grp_ec_secp384r1); break; case ssl_grp_kem_xyber768d00: case ssl_grp_kem_mlkem768x25519:
ecGroup = ssl_LookupNamedGroup(ssl_grp_ec_curve25519); break; default:
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); return SECFailure;
} if (ecGroup == NULL) {
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); return SECFailure;
}
keyPair = ssl_LookupEphemeralKeyPair(ss, ecGroup); if (keyPair) {
keyPair = ssl_CopyEphemeralKeyPair(keyPair);
} if (!keyPair) {
rv = ssl_CreateECDHEphemeralKeyPair(ss, ecGroup, &keyPair); if (rv != SECSuccess) { return SECFailure;
}
}
keyPair->group = groupDef; break; case ssl_kea_ecdh:
keyPair = tls13_FindHybridKeyPair(ss, groupDef); if (keyPair) {
keyPair = tls13_CopyECDHKeyFromHybrid(keyPair, groupDef);
} if (!keyPair) {
rv = ssl_CreateECDHEphemeralKeyPair(ss, groupDef, &keyPair); if (rv != SECSuccess) { return SECFailure;
}
} break; case ssl_kea_dh:
params = ssl_GetDHEParams(groupDef);
PORT_Assert(params->name != ssl_grp_ffdhe_custom);
rv = ssl_CreateDHEKeyPair(groupDef, params, &keyPair); if (rv != SECSuccess) { return SECFailure;
} break; default:
PORT_Assert(0);
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); return SECFailure;
}
// If we're creating an ECDH + KEM hybrid share and we're the client, then // we still need to generate the KEM key pair. Otherwise we're done. if (groupDef->keaType == ssl_kea_ecdh_hybrid && !ss->sec.isServer) {
rv = tls13_CreateKEMKeyPair(ss, groupDef, &keyPair->kemKeys); if (rv != SECSuccess) {
ssl_FreeEphemeralKeyPair(keyPair); return SECFailure;
}
}
/* Select the first enabled group. *TODO(ekr@rtfm.com):besmarteraboutofferingthegroup
* that the other side negotiated if we are resuming. */
PORT_Assert(PR_CLIST_IS_EMPTY(&ss->ephemeralKeyPairs)); for (i = 0; i < SSL_NAMED_GROUP_COUNT; ++i) { if (!ss->namedGroupPreferences[i]) { continue;
}
rv = tls13_AddKeyShare(ss, ss->namedGroupPreferences[i]); if (rv != SECSuccess) { return SECFailure;
} if (++numShares > ss->additionalShares) { break;
}
}
if (PR_CLIST_IS_EMPTY(&ss->ephemeralKeyPairs)) {
PORT_SetError(SSL_ERROR_NO_CIPHERS_SUPPORTED); return SECFailure;
}
/* 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);
if (ssl_TicketTimeValid(ss, session_ticket)) {
ss->statelessResume = PR_TRUE;
}
/* 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;
}
if (epoch == PR_UINT16_MAX) { /* Good chance that this is an overflow from too many updates. */
FATAL_ERROR(ss, SSL_ERROR_TOO_MANY_KEY_UPDATES, internal_error); return SECFailure;
}
++epoch;
/* If we have been asked to buffer, then do so. This allows us to coalesce
* a KeyUpdate with a pending write. */
rv = ssl3_FlushHandshake(ss, buffer ? ssl_SEND_FLAG_FORCE_INTO_BUFFER : 0); if (rv != SECSuccess) { goto loser; /* error code set by ssl3_FlushHandshake */
}
ssl_ReleaseXmitBufLock(ss);
rv = tls13_UpdateTrafficKeys(ss, ssl_secret_write); if (rv != SECSuccess) { goto loser; /* error code set by tls13_UpdateTrafficKeys */
}
/* Remember that we are the ones that initiated this KeyUpdate. */ if (rv == SECSuccess) {
ss->ssl3.peerRequestedKeyUpdate = PR_FALSE;
}
ssl_ReleaseSSL3HandshakeLock(ss); return rv;
}
/* Checking that we have not yet registed an algorithm with the same ID. */ for (int i = 0; i < ss->ssl3.supportedCertCompressionAlgorithmsCount; i++) { if (ss->ssl3.supportedCertCompressionAlgorithms[i].id == alg.id) { goto loser;
}
}
/* If we're handing the DTLS1.3 message, we silently fail if there is a parsing problem. */ static SECStatus
tls13_HandleKeyUpdate(sslSocket *ss, PRUint8 *b, unsignedint length)
{
SECStatus rv;
PRUint32 update;
if (!tls13_IsPostHandshake(ss)) {
FATAL_ERROR(ss, SSL_ERROR_RX_UNEXPECTED_KEY_UPDATE, unexpected_message); return SECFailure;
}
rv = TLS13_CHECK_HS_STATE(ss, SSL_ERROR_RX_UNEXPECTED_KEY_UPDATE,
idle_handshake); if (rv != SECSuccess) { /* We should never be idle_handshake prior to firstHsDone. */
FATAL_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE, internal_error); return SECFailure;
}
/* Not supported. */ if (IS_DTLS(ss)) {
PORT_SetError(SSL_ERROR_FEATURE_NOT_SUPPORTED_FOR_VERSION); return SECFailure;
}
if (!tls13_IsPostHandshake(ss)) {
PORT_SetError(SEC_ERROR_INVALID_ARGS); return SECFailure;
}
if (ss->ssl3.clientCertRequested) {
PORT_SetError(PR_WOULD_BLOCK_ERROR); 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;
}
/* TODO(ekr@rtfm.com): Would it be better to check all the states here? */ switch (ss->ssl3.hs.msg_type) { case ssl_hs_certificate: return tls13_HandleCertificate(ss, b, length, PR_FALSE); case ssl_hs_compressed_certificate: return tls13_HandleCertificateDecode(ss, b, length); case ssl_hs_certificate_request: return tls13_HandleCertificateRequest(ss, b, length);
case ssl_hs_certificate_verify: return tls13_HandleCertificateVerify(ss, b, length);
case ssl_hs_encrypted_extensions: return tls13_HandleEncryptedExtensions(ss, b, length);
case ssl_hs_new_session_ticket: return tls13_HandleNewSessionTicket(ss, b, length);
case ssl_hs_finished: if (ss->sec.isServer) { return tls13_ServerHandleFinished(ss, b, length);
} else { return tls13_ClientHandleFinished(ss, b, length);
}
case ssl_hs_end_of_early_data: return tls13_HandleEndOfEarlyData(ss, b, length);
case ssl_hs_key_update: return tls13_HandleKeyUpdate(ss, b, length);
/* Now find the hash used as the PRF for the previous handshake. */
hashType = tls13_GetHashForCipherSuite(sid->u.ssl3.cipherSuite);
/* If we are the server, we compute the wrapping key, but if we
* are the client, its coordinates are stored with the ticket. */ if (ss->sec.isServer) {
wrapKey = ssl3_GetWrappingKey(ss, NULL,
sid->u.ssl3.masterWrapMech,
ss->pkcs11PinArg);
} else {
PK11SlotInfo *slot = SECMOD_LookupSlot(sid->u.ssl3.masterModuleID,
sid->u.ssl3.masterSlotID); if (!slot) return SECFailure;
if (ss->sec.isServer) { /* In server, we couldn't select the RPSK in the extension handler *sinceitwasnotunwrappedyet.We'recommittednow,soselect
* 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);
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);
if (sid->version != ss->version) { return PR_FALSE;
}
#ifdef UNSAFE_FUZZER_MODE /* When fuzzing, sid could contain garbage that will crash tls13_GetHashForCipherSuite. *Doadirectcomparisonofciphersuites.Thismakesusrefusetoresumewhenthe
* 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;
}
/* Server sids don't remember the server cert we previously sent, but they *dorememberthetypeofcertificateweoriginallyused,sowecanlocate *itagain,providedthatthecurrentsslsockethashaditsservercerts
* configured the same as the previous one. */
sc = ssl_FindServerCert(ss, sid->authType, sid->namedCurve); if (!sc || !sc->serverCert) { return PR_FALSE;
}
if (!ss->opt.enable0RttData) { return PR_FALSE;
} if (!psk) { return PR_FALSE;
} if (psk->zeroRttSuite == TLS_NULL_WITH_NULL_NULL) { return PR_FALSE;
} if (!psk->maxEarlyData) { return PR_FALSE;
} if (ss->ssl3.hs.cipher_suite != psk->zeroRttSuite) { return PR_FALSE;
} 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;
}
} elseif (psk->type != ssl_psk_external) {
PORT_Assert(0); return PR_FALSE;
}
if (tls13_IsReplay(ss, sid)) { return PR_FALSE;
}
return PR_TRUE;
}
/* Called from tls13_HandleClientHelloPart2 to update the state of 0-RTT handling. * *0-RTTisonlypermittedif: *1.Theearlydataextensionwaspresent. *2.Weareresumingasession. *3.The0-RTToptionisset. *4.Theticketallowed0-RTT. *5.WenegotiatedthesameALPNvalueasintheticket.
*/ staticvoid
tls13_NegotiateZeroRtt(sslSocket *ss, const sslSessionID *sid)
{
SSL_TRC(3, ("%d: TLS13[%d]: negotiate 0-RTT %p",
SSL_GETPID(), ss->fd, sid));
/* tls13_ServerHandleEarlyDataXtn sets this to ssl_0rtt_sent, so this will
* be ssl_0rtt_none unless early_data is present. */ if (ss->ssl3.hs.zeroRttState == ssl_0rtt_none) { return;
}
if (ss->ssl3.hs.zeroRttState == ssl_0rtt_ignored) { /* HelloRetryRequest causes 0-RTT to be ignored. On the second *ClientHello,resettheignorestatesothatdecryptionfailureis
* handled normally. */ if (ss->ssl3.hs.zeroRttIgnore == ssl_0rtt_ignore_hrr) {
PORT_Assert(ss->ssl3.hs.helloRetry);
ss->ssl3.hs.zeroRttState = ssl_0rtt_none;
ss->ssl3.hs.zeroRttIgnore = ssl_0rtt_ignore_none;
} else {
SSL_TRC(3, ("%d: TLS13[%d]: application ignored 0-RTT",
SSL_GETPID(), ss->fd));
} return;
}
/* Check if the offered group is acceptable. */ static PRBool
tls13_isGroupAcceptable(const sslNamedGroupDef *offered, const sslNamedGroupDef *preferredGroup)
{ /* We accept epsilon (e) bits around the offered group size. */ constunsignedint e = 2;
/* We insist on DHE. */ 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); return SECFailure;
} /* Since the server insists on DHE to provide forward secracy, for *everyotherPskKemvaluebutDHEstatelessresumptionisdisabled,
* this includes other specified and GREASE values. */ if (!memchr(ss->xtnData.psk_ke_modes.data, tls13_psk_dh_ke,
ss->xtnData.psk_ke_modes.len)) {
SSL_TRC(3, ("%d: TLS13[%d]: client offered PSK without DH",
SSL_GETPID(), ss->fd));
ss->statelessResume = PR_FALSE;
}
}
/* Now figure out which key share we like the best out of the *mutuallysupportedgroups,regardlessofwhattheclientoffered *forkeyshares.
*/ if (!ssl3_ExtensionNegotiated(ss, ssl_supported_groups_xtn)) {
FATAL_ERROR(ss, SSL_ERROR_MISSING_SUPPORTED_GROUPS_EXTENSION,
missing_extension); return SECFailure;
}
/* Find the preferred group and an according client key share available. */ for (index = 0; index < SSL_NAMED_GROUP_COUNT; ++index) { /* Continue to the next group if this one is not enabled. */ if (!ss->namedGroupPreferences[index]) { /* There's a gap in the preferred groups list. Assume this is a group
* that's not supported by the client but preferred by the server. */ if (preferredGroup) {
entry = NULL; break;
} continue;
}
/* Check if the client sent a key share for this group. */
entry = tls13_FindKeyShareEntry(ss, ss->namedGroupPreferences[index]);
if (preferredGroup) { /* We already found our preferred group but the group didn't have a share. */ if (entry) { /* The client sent a key share with group ss->namedGroupPreferences[index] */ if (tls13_isGroupAcceptable(ss->namedGroupPreferences[index],
preferredGroup)) { /* This is not the preferred group, but it's acceptable */
preferredGroup = ss->namedGroupPreferences[index];
} else { /* The proposed group is not acceptable. */
entry = NULL;
}
} break;
} else { /* The first enabled group is the preferred group. */
preferredGroup = ss->namedGroupPreferences[index]; if (entry) { break;
}
}
}
if (!preferredGroup) {
FATAL_ERROR(ss, SSL_ERROR_NO_CYPHER_OVERLAP, handshake_failure); return SECFailure;
}
SSL_TRC(3, ("%d: TLS13[%d]: group = %d", SSL_GETPID(), ss->fd,
preferredGroup->name));
/* Either provide a share, or provide a group that should be requested in a
* HelloRetryRequest, but not both. */ if (entry) {
PORT_Assert(preferredGroup == entry->group);
*clientShare = entry;
*requestedGroup = NULL;
} else {
*clientShare = NULL;
*requestedGroup = preferredGroup;
} return SECSuccess;
}
if (!ssl3_ExtensionNegotiated(ss, ssl_signature_algorithms_xtn)) {
FATAL_ERROR(ss, SSL_ERROR_MISSING_SIGNATURE_ALGORITHMS_EXTENSION,
missing_extension); return SECFailure;
}
/* This picks the first certificate that has: *a)therightauthenticationmethod,and *b)therightnamedcurve(EConly) * *Wemightwanttodosomesortofrankingherelater.Fornow,it'sall
* based on what order they are configured in. */ for (cursor = PR_NEXT_LINK(&ss->serverCerts);
cursor != &ss->serverCerts;
cursor = PR_NEXT_LINK(cursor)) {
sslServerCert *cert = (sslServerCert *)cursor;
if (SSL_CERT_IS_ONLY(cert, ssl_auth_rsa_decrypt)) { continue;
}
/* If we can use a delegated credential (DC) for authentication in *thecurrenthandshake,thencommittousingitnow.We'llsenda *DCasanextensionandusetheDCprivatekeytosignthe *handshake. * *Thissetsthesignatureschemetobethesignaturescheme *indicatedbytheDC.
*/
rv = tls13_MaybeSetDelegatedCredential(ss); if (rv != SECSuccess) { return SECFailure; /* Failure indicates an internal error. */
}
/* These use SSL3_SendAlert directly to avoid an assertion in
* tls13_FatalError(), which is ordinarily OK. */ if (action == ssl_hello_retry_request && ss->ssl3.hs.helloRetry) {
(void)SSL3_SendAlert(ss, alert_fatal, internal_error);
PORT_SetError(SSL_ERROR_APP_CALLBACK_ERROR); return SECFailure;
}
/* We may have received ECH, but have to start over with CH2. */
ss->ssl3.hs.echAccepted = PR_FALSE;
PK11_HPKE_DestroyContext(ss->ssl3.hs.echHpkeCtx, PR_TRUE);
ss->ssl3.hs.echHpkeCtx = NULL;
*hrrSent = PR_TRUE; return SECSuccess;
}
static SECStatus
tls13_NegotiateAuthentication(sslSocket *ss)
{ if (ss->statelessResume) {
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;
} elseif (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;
}
/* If the legacy_version field is set to 0x300 or smaller,
* reject the connection with protocol_version alert. */ if (ss->clientHelloVersion <= SSL_LIBRARY_VERSION_3_0) {
FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_CLIENT_HELLO, protocol_version); goto loser;
}
ss->ssl3.hs.endOfFlight = PR_TRUE;
if (ssl3_ExtensionNegotiated(ss, ssl_tls13_early_data_xtn)) {
ss->ssl3.hs.zeroRttState = ssl_0rtt_sent;
}
/* If we are going around again, then we should make sure that the cipher
* suite selection doesn't change. That's a sign of client shennanigans. */ if (ss->ssl3.hs.helloRetry) {
/* Update sequence numbers before checking the cookie so that any alerts
* we generate are sent with the right sequence numbers. */ if (IS_DTLS(ss)) { /* Count the first ClientHello and the HelloRetryRequest. */
ss->ssl3.hs.sendMessageSeq = 1;
ss->ssl3.hs.recvMessageSeq = 1;
ssl_GetSpecWriteLock(ss); /* Increase the write sequence number. The read sequence number
* will be reset after this to early data or handshake. */
ss->ssl3.cwSpec->nextSeqNum = 1;
ssl_ReleaseSpecWriteLock(ss);
}
if (!ssl3_ExtensionNegotiated(ss, ssl_tls13_cookie_xtn) ||
!ss->xtnData.cookie.len) {
FATAL_ERROR(ss, SSL_ERROR_MISSING_COOKIE_EXTENSION,
missing_extension); goto loser;
}
PRINT_BUF(50, (ss, "Client sent cookie",
ss->xtnData.cookie.data, ss->xtnData.cookie.len));
/* Now merge the ClientHello into the hash state. */
rv = ssl_HashHandshakeMessage(ss, ssl_hs_client_hello, msg, len); if (rv != SECSuccess) {
FATAL_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE, internal_error); goto loser;
}
/* Now create a synthetic kea_def that we can tweak. */
ss->ssl3.hs.kea_def_mutable = *ss->ssl3.hs.kea_def;
ss->ssl3.hs.kea_def = &ss->ssl3.hs.kea_def_mutable;
/* Note: We call this quite a bit earlier than with TLS 1.2 and
* before. */
rv = ssl3_ServerCallSNICallback(ss); if (rv != SECSuccess) { goto loser; /* An alert has already been sent. */
}
/* Check if we could in principle resume. */ if (ss->statelessResume) {
PORT_Assert(sid); if (!sid) {
FATAL_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE, internal_error); return SECFailure;
} if (!tls13_CanResume(ss, sid)) {
ss->statelessResume = PR_FALSE;
}
}
/* Select key exchange. */
rv = tls13_NegotiateKeyExchange(ss, &requestedGroup, &clientShare); if (rv != SECSuccess) { goto loser;
} /* We should get either one of these, but not both. */
PORT_Assert((requestedGroup && !clientShare) ||
(!requestedGroup && clientShare));
/* After HelloRetryRequest, check consistency of cipher and group. */ if (ss->ssl3.hs.helloRetry) {
PORT_Assert(previousCipherSuite); if (ss->ssl3.hs.cipher_suite != previousCipherSuite) {
FATAL_ERROR(ss, SSL_ERROR_BAD_2ND_CLIENT_HELLO,
illegal_parameter); goto loser;
} if (!clientShare) {
FATAL_ERROR(ss, SSL_ERROR_BAD_2ND_CLIENT_HELLO,
illegal_parameter); goto loser;
}
/* CH1/CH2 must either both include ECH, or both exclude it. */ if (previousOfferedEch != (ss->xtnData.ech != NULL)) {
FATAL_ERROR(ss, SSL_ERROR_BAD_2ND_CLIENT_HELLO,
previousOfferedEch ? missing_extension : illegal_parameter); goto loser;
}
/* If we requested a new key share, check that the client provided just
* one of the right type. */ if (previousGroup) { if (PR_PREV_LINK(&ss->xtnData.remoteKeyShares) !=
PR_NEXT_LINK(&ss->xtnData.remoteKeyShares)) {
FATAL_ERROR(ss, SSL_ERROR_BAD_2ND_CLIENT_HELLO,
illegal_parameter); goto loser;
} if (clientShare->group != previousGroup) {
FATAL_ERROR(ss, SSL_ERROR_BAD_2ND_CLIENT_HELLO,
illegal_parameter); goto loser;
}
}
}
rv = tls13_MaybeSendHelloRetry(ss, requestedGroup, &hrr); if (rv != SECSuccess) { goto loser;
} if (hrr) { if (sid) { /* Free the sid. */
ssl_UncacheSessionID(ss);
ssl_FreeSID(sid);
}
PORT_Assert(ss->ssl3.hs.helloRetry); return SECSuccess;
}
/* Select the authentication (this is also handshake shape). */
rv = tls13_NegotiateAuthentication(ss); if (rv != SECSuccess) { 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;
}
/* This needs to go after we verify the psk binder. */
rv = ssl3_InitHandshakeHashes(ss); if (rv != SECSuccess) { goto loser;
}
/* If this is TLS 1.3 we are expecting a ClientKeyShare *extension.Missing/absentextensioncausefailure
* below. */
rv = tls13_HandleClientKeyShare(ss, clientShare); if (rv != SECSuccess) { goto loser; /* An alert was sent already. */
}
/* From this point we are either committed to resumption, or not. */ if (ss->statelessResume) {
SSL_AtomicIncrementLong(&ssl3stats->hch_sid_cache_hits);
SSL_AtomicIncrementLong(&ssl3stats->hch_sid_stateless_resumes);
} else { if (sid) { /* We had a sid, but it's no longer valid, free it. */
SSL_AtomicIncrementLong(&ssl3stats->hch_sid_cache_not_ok);
ssl_UncacheSessionID(ss);
ssl_FreeSID(sid);
} elseif (!ss->xtnData.selectedPsk) {
SSL_AtomicIncrementLong(&ssl3stats->hch_sid_cache_misses);
}
sid = ssl3_NewSessionID(ss, PR_TRUE); if (!sid) {
FATAL_ERROR(ss, PORT_GetError(), internal_error); return SECFailure;
}
} /* Take ownership of the session. */
ss->sec.ci.sid = sid;
sid = NULL;
if (ss->ssl3.hs.zeroRttState == ssl_0rtt_accepted) {
rv = tls13_DeriveEarlySecrets(ss); if (rv != SECSuccess) {
FATAL_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE, internal_error); return SECFailure;
}
}
/* Note: cookie is pointing to a stack variable, so is only valid
* now. */
ss->xtnData.selectedGroup = selectedGroup;
ss->xtnData.cookie.data = cookie;
ss->xtnData.cookie.len = cookieLen;
/* Set restored ss->ssl3.hs.greaseEchBuf value for ECH HRR extension
* reconstruction. */ if (cookieGreaseEchSignal) {
PORT_Assert(!ss->ssl3.hs.greaseEchBuf.len);
rv = sslBuffer_Append(&ss->ssl3.hs.greaseEchBuf,
cookieGreaseEchSignal,
TLS13_ECH_SIGNAL_LEN); if (rv != SECSuccess) { goto loser;
}
}
rv = ssl_ConstructExtensions(ss, &extensionsBuf,
ssl_hs_hello_retry_request); /* Reset ss->ssl3.hs.greaseEchBuf if it was changed. */ if (cookieGreaseEchSignal) {
sslBuffer_Clear(&ss->ssl3.hs.greaseEchBuf);
} if (rv != SECSuccess) { goto loser;
} /* These extensions can't be empty. */
PORT_Assert(SSL_BUFFER_LEN(&extensionsBuf) > 0);
/* Clean up cookie so we're not pointing at random memory. */
ss->xtnData.cookie.data = NULL;
ss->xtnData.cookie.len = 0;
/* If an ECH backend or shared-mode server accepted ECH when offered, *theHRRextension'spayloadmustbesetto8zerobytes,theseare *overwrittenwiththeaccept_confirmationvalueafterthehandshake *transcriptcalculation. *Ifaclient-facingorshared-modeserverdidnotacceptECHwhenoffered *ORifECHGREASEisenabledontheserverandaECHextensionwas *received,a8byterandomvalueissetastheextension'spayload *[draft-ietf-tls-esni-14,Section7]. * *The(temporary)payloadiswrittentotheextensionintls13exthandle.c/
* tls13_ServerSendHrrEchXtn(). */ if (ss->xtnData.ech) {
PRUint8 echGreaseRaw[TLS13_ECH_SIGNAL_LEN] = { 0 }; if (!(ss->ssl3.hs.echAccepted ||
(ss->opt.enableTls13BackendEch &&
ss->xtnData.ech &&
ss->xtnData.ech->receivedInnerXtn))) {
rv = PK11_GenerateRandom(echGreaseRaw, TLS13_ECH_SIGNAL_LEN); if (rv != SECSuccess) { return SECFailure;
}
SSL_TRC(100, ("Generated random value for ECH HRR GREASE."));
}
sslBuffer echGreaseBuffer = SSL_BUFFER_EMPTY;
rv = sslBuffer_Append(&echGreaseBuffer, echGreaseRaw, sizeof(echGreaseRaw)); if (rv != SECSuccess) { return SECFailure;
} /* HRR GREASE/accept_confirmation zero bytes placeholder buffer. */
ss->ssl3.hs.greaseEchBuf = echGreaseBuffer;
}
/* Compute the cookie we are going to need. */
rv = tls13_MakeHrrCookie(ss, requestedGroup,
appToken, appTokenLen,
cookie, &cookieLen, sizeof(cookie)); if (rv != SECSuccess) {
FATAL_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE, internal_error); return SECFailure;
}
/* Now build the body of the message. */
rv = tls13_ConstructHelloRetryRequest(ss, ss->ssl3.hs.cipher_suite,
requestedGroup,
cookie, cookieLen,
NULL, &messageBuf); if (rv != SECSuccess) {
FATAL_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE, internal_error); return SECFailure;
}
/* And send it. */
ssl_GetXmitBufLock(ss);
rv = ssl3_AppendHandshakeHeader(ss, ssl_hs_server_hello,
SSL_BUFFER_LEN(&messageBuf)); if (rv != SECSuccess) { goto loser;
}
rv = ssl3_AppendBufferToHandshake(ss, &messageBuf); if (rv != SECSuccess) { goto loser;
}
sslBuffer_Clear(&messageBuf); /* Done with messageBuf */
if (ss->ssl3.hs.fakeSid.len) {
PRInt32 sent;
PORT_Assert(!IS_DTLS(ss));
rv = ssl3_SendChangeCipherSpecsInt(ss); if (rv != SECSuccess) { goto loser;
} /* ssl3_SendChangeCipherSpecsInt() only flushes to the output buffer, so we
* have to force a send. */
sent = ssl_SendSavedWriteData(ss); if (sent < 0 && PORT_GetError() != PR_WOULD_BLOCK_ERROR) {
PORT_SetError(SSL_ERROR_SOCKET_WRITE_FAILURE); goto loser;
}
} else {
rv = ssl3_FlushHandshake(ss, 0); if (rv != SECSuccess) { goto loser; /* error code set by ssl3_FlushHandshake */
}
}
/* We depend on this being exactly one record and one message. */
PORT_Assert(!IS_DTLS(ss) || (ss->ssl3.hs.sendMessageSeq == 1 &&
ss->ssl3.cwSpec->nextSeqNum == 1));
ssl_ReleaseXmitBufLock(ss);
ss->ssl3.hs.helloRetry = PR_TRUE;
/* We received early data but have to ignore it because we sent a retry. */ if (ss->ssl3.hs.zeroRttState == ssl_0rtt_sent) {
ss->ssl3.hs.zeroRttState = ssl_0rtt_ignored;
ss->ssl3.hs.zeroRttIgnore = ssl_0rtt_ignore_hrr;
}
/* We should have exactly one key share. */
PORT_Assert(!PR_CLIST_IS_EMPTY(&ss->ephemeralKeyPairs));
PORT_Assert(PR_PREV_LINK(&ss->ephemeralKeyPairs) ==
PR_NEXT_LINK(&ss->ephemeralKeyPairs));
SSL_TRC(3, ("%d: TLS13[%d]: begin send certificate_request",
SSL_GETPID(), ss->fd));
if (ss->firstHsDone) {
PORT_Assert(ss->ssl3.hs.shaPostHandshake == NULL);
ss->ssl3.hs.shaPostHandshake = PK11_CloneContext(ss->ssl3.hs.sha); if (ss->ssl3.hs.shaPostHandshake == NULL) {
ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE); return SECFailure;
}
}
rv = ssl_ConstructExtensions(ss, &extensionBuf, ssl_hs_certificate_request); if (rv != SECSuccess) { return SECFailure; /* Code already set. */
} /* We should always have at least one of these. */
PORT_Assert(SSL_BUFFER_LEN(&extensionBuf) > 0);
/* Create a new request context for post-handshake authentication */ if (ss->firstHsDone) {
PRUint8 context[16];
SECItem contextItem = { siBuffer, context, sizeof(context) };
/* First compute the hash. */
rv = tls13_ComputeHash(ss, &hashes,
ss->ssl3.hs.messages.buf,
ss->ssl3.hs.messages.len,
tls13_GetHash(ss)); if (rv != SECSuccess) { return SECFailure;
}
if (ss->ssl3.hs.echHpkeCtx) {
rv = tls13_ComputeHash(ss, &echInnerHashes,
ss->ssl3.hs.echInnerMessages.buf,
ss->ssl3.hs.echInnerMessages.len,
tls13_GetHash(ss)); if (rv != SECSuccess) { return SECFailure;
}
}
ssl3_RestartHandshakeHashes(ss);
/* Reinject the message. The Default context variant updates
* the default hash state. Use it for both non-ECH and ECH Outer. */
rv = ssl_HashHandshakeMessageDefault(ss, ssl_hs_message_hash,
hashes.u.raw, hashes.len); if (rv != SECSuccess) { return SECFailure;
}
if (ss->ssl3.hs.echHpkeCtx) {
rv = ssl_HashHandshakeMessageEchInner(ss, ssl_hs_message_hash,
echInnerHashes.u.raw,
echInnerHashes.len); if (rv != SECSuccess) { return SECFailure;
}
}
return SECSuccess;
} staticunsignedint
ssl_ListCount(PRCList *list)
{ unsignedint c = 0;
PRCList *cur; for (cur = PR_NEXT_LINK(list); cur != list; cur = PR_NEXT_LINK(cur)) {
++c;
} return c;
}
if (ss->ssl3.hs.zeroRttState == ssl_0rtt_sent) {
ss->ssl3.hs.zeroRttState = ssl_0rtt_ignored; /* Restore the null cipher spec for writing. */
ssl_GetSpecWriteLock(ss);
ssl_CipherSpecRelease(ss->ssl3.cwSpec);
ss->ssl3.cwSpec = ssl_FindCipherSpecByEpoch(ss, ssl_secret_write,
TrafficKeyClearText);
PORT_Assert(ss->ssl3.cwSpec);
ssl_ReleaseSpecWriteLock(ss);
} else {
PORT_Assert(ss->ssl3.hs.zeroRttState == ssl_0rtt_none);
} /* Set the spec version, because we want to send CH now with 0303 */
tls13_SetSpecRecordVersion(ss, ss->ssl3.cwSpec);
/* Extensions must contain more than just supported_versions. This will *ensurethataHelloRetryRequestisn'tano-op:wemusthaveatleasttwo *extensions,supported_versionsplusoneother.Thatothermustbeone *thatweunderstandandrecognizeasbeingvalidforHelloRetryRequest,
* and should alter our next Client Hello. */ unsignedint requiredExtensions = 1; /* The ECH HRR extension is a no-op from the client's perspective. */ if (ss->xtnData.ech) {
requiredExtensions++;
} if (ssl_ListCount(&ss->ssl3.hs.remoteExtensions) <= requiredExtensions) {
FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_HELLO_RETRY_REQUEST,
decode_error); return SECFailure;
}
/* Unless it is a post-handshake client auth, the certificate
* request context must be empty. */ if (!tls13_IsPostHandshake(ss) && context.len > 0) {
FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_CERT_REQUEST, illegal_parameter); return SECFailure;
}
if (length) {
FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_CERT_REQUEST, decode_error); return SECFailure;
}
/* Process all the extensions. */
rv = ssl3_HandleExtensions(ss, &extensionsData.data, &extensionsData.len,
ssl_hs_certificate_request); if (rv != SECSuccess) { return SECFailure;
}
if (!ss->xtnData.numSigSchemes) {
FATAL_ERROR(ss, SSL_ERROR_MISSING_SIGNATURE_ALGORITHMS_EXTENSION,
missing_extension); return SECFailure;
}
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;
}
rv = tls13_ComputeHandshakeSecret(ss); if (rv != SECSuccess) { return SECFailure; /* error code is set. */
}
rv = ssl3_SendServerHello(ss); if (rv != SECSuccess) { return rv; /* err code is set. */
}
if (ss->ssl3.hs.fakeSid.len) {
PORT_Assert(!IS_DTLS(ss));
SECITEM_FreeItem(&ss->ssl3.hs.fakeSid, PR_FALSE); if (!ss->ssl3.hs.helloRetry) {
rv = ssl3_SendChangeCipherSpecsInt(ss); if (rv != SECSuccess) { return rv;
}
}
}
rv = tls13_SendEncryptedServerSequence(ss); if (rv != SECSuccess) {
err = PORT_GetError();
} /* Even if we get an error, since the ServerHello was successfully *serialized,weshouldgiveitachancetoreachthenetwork.Thisgives *theclientachancetoperformthekeyexchangeanddecryptthealert
* we're about to send. */
rv |= ssl3_FlushHandshake(ss, 0); if (rv != SECSuccess) { if (err) {
PORT_SetError(err);
} return SECFailure;
}
/* Compute the rest of the secrets except for the resumption
* and exporter secret. */
rv = tls13_ComputeApplicationSecrets(ss); if (rv != SECSuccess) {
LOG_ERROR(ss, PORT_GetError()); return SECFailure;
}
/* 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;
}
if (ssl3_ExtensionNegotiated(ss, ssl_tls13_pre_shared_key_xtn)) {
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) { /* We might have dropped incompatible PSKs on HRR
* (see RFC8466, Section 4.1.4). */
PORT_Assert(ss->ssl3.hs.helloRetry ||
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) {
PORT_Assert(sid->version >= SSL_LIBRARY_VERSION_TLS_1_3); if (tls13_GetHash(ss) !=
tls13_GetHashForCipherSuite(sid->u.ssl3.cipherSuite)) {
FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_SERVER_HELLO,
illegal_parameter); return SECFailure;
}
}
/* Now create a synthetic kea_def that we can tweak. */
ss->ssl3.hs.kea_def_mutable = *ss->ssl3.hs.kea_def;
ss->ssl3.hs.kea_def = &ss->ssl3.hs.kea_def_mutable;
if (ss->xtnData.selectedPsk) {
ss->ssl3.hs.kea_def_mutable.authKeyType = ssl_auth_psk; 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);
} else {
ss->sec.authType = ssl_auth_psk;
}
} else { 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) { /* If we tried to resume and failed, let's not try again. */
ssl_UncacheSessionID(ss);
}
}
/* Discard current SID and make a new one, though it may eventually *enduplookingalotliketheoldone.
*/
ssl_FreeSID(sid);
ss->sec.ci.sid = sid = ssl3_NewSessionID(ss, PR_FALSE); if (sid == NULL) {
FATAL_ERROR(ss, PORT_GetError(), internal_error); return SECFailure;
} if (ss->statelessResume) {
PORT_Assert(ss->sec.peerCert);
sid->peerCert = CERT_DupCertificate(ss->sec.peerCert);
}
sid->version = ss->version;
rv = tls13_ComputeHandshakeSecret(ss); if (rv != SECSuccess) { return SECFailure; /* error code is set. */
}
rv = tls13_MaybeHandleEchSignal(ss, savedMsg, savedLength, PR_FALSE); if (rv != SECSuccess) { return SECFailure; /* error code is set. */
}
rv = tls13_ComputeHandshakeSecrets(ss); if (rv != SECSuccess) { return SECFailure; /* error code is set. */
}
if (ss->ssl3.hs.zeroRttState == ssl_0rtt_sent) { /* When we send 0-RTT, we saved the null spec in case we needed it to *sendanotherClientHelloinresponsetoaHelloRetryRequest.Now
* that we won't be receiving a HelloRetryRequest, release the spec. */
ssl_CipherSpecReleaseByEpoch(ss, ssl_secret_write, TrafficKeyClearText);
}
/* This list should have one entry. */ if (PR_CLIST_IS_EMPTY(&ss->xtnData.remoteKeyShares)) {
FATAL_ERROR(ss, SSL_ERROR_MISSING_KEY_SHARE, missing_extension); return SECFailure;
}
SSL_TRC(30, ("%d: TLS13[%d]: %s is encoding the certificate using the %s compression algorithm",
SSL_GETPID(), ss->fd, SSL_ROLE(ss),
ssl3_mapCertificateCompressionAlgorithmToName(ss, ss->xtnData.compressionAlg)));
PRINT_BUF(50, (NULL, "The certificate before encoding:",
bufferCertificate->buf, bufferCertificate->len));
/* The CompressedCertificate message is formed as follows: *struct{ *CertificateCompressionAlgorithmalgorithm; *uint24uncompressed_length; *opaquecompressed_certificate_message<1..2^24-1>; *}CompressedCertificate;
*/
if (encodedCertificate.len < 1) {
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); goto loser;
}
rv = ssl3_AppendHandshakeHeader(ss, ssl_hs_compressed_certificate,
encodedCertificate.len + 2 + 3 + 3); if (rv != SECSuccess) { goto loser; /* err set by AppendHandshake. */
}
rv = ssl3_AppendHandshakeNumber(ss, ss->xtnData.compressionAlg, 2); if (rv != SECSuccess) { goto loser; /* err set by AppendHandshake. */
}
rv = ssl3_AppendHandshakeNumber(ss, lengthUnencodedMessage, 3); if (rv != SECSuccess) { goto loser; /* err set by AppendHandshake. */
}
PRINT_BUF(30, (NULL, "The encoded certificate: ",
encodedCertificate.data, encodedCertificate.len));
rv = ssl3_AppendHandshakeVariable(ss, encodedCertificate.data, encodedCertificate.len, 3); if (rv != SECSuccess) { goto loser; /* err set by AppendHandshake. */
}
if (ss->sec.isServer) {
PORT_Assert(!ss->sec.localCert); /* A server certificate is selected in tls13_SelectServerCert(). */
PORT_Assert(ss->sec.serverCert);
if (!ss->sec.isServer) {
PORT_Assert(ss->ssl3.hs.clientCertRequested);
context = ss->xtnData.certReqContext;
}
if (certChain) { for (i = 0; i < certChain->len; i++) { /* Each cert is 3 octet length, cert, and extensions */
certChainLen += 3 + certChain->certs[i].len + 2;
}
/* Build the extensions. This only applies to the leaf cert, because we
* don't yet send extensions for non-leaf certs. */
rv = ssl_ConstructExtensions(ss, &extensionBuf, ssl_hs_certificate); if (rv != SECSuccess) { return SECFailure; /* code already set */
} /* extensionBuf.len is only added once, for the leaf cert. */
certChainLen += SSL_BUFFER_LEN(&extensionBuf);
}
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. */
}
PRBool compressionAlgorithmIsSupported = PR_FALSE;
SECStatus (*certificateDecodingFunc)(const SECItem *, unsignedchar *output, size_t outputLen, size_t *usedLen) = NULL; for (int i = 0; i < ss->ssl3.supportedCertCompressionAlgorithmsCount; i++) { if (ss->ssl3.supportedCertCompressionAlgorithms[i].id == compressionAlg) {
compressionAlgorithmIsSupported = PR_TRUE;
certificateDecodingFunc = ss->ssl3.supportedCertCompressionAlgorithms[i].decode;
}
}
/* Peer selected a compression algorithm we do not support (and did not advertise). */ if (!compressionAlgorithmIsSupported) {
PORT_SetError(SEC_ERROR_CERTIFICATE_COMPRESSION_ALGORITHM_NOT_SUPPORTED);
FATAL_ERROR(ss, PORT_GetError(), illegal_parameter); return SECFailure;
}
/* The algorithm does not support decoding. */ if (certificateDecodingFunc == NULL) {
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
FATAL_ERROR(ss, PORT_GetError(), illegal_parameter); return SECFailure;
}
SSL_TRC(30, ("%d: TLS13[%d]: %s is decoding the certificate using the %s compression algorithm",
SSL_GETPID(), ss->fd, SSL_ROLE(ss),
ssl3_mapCertificateCompressionAlgorithmToName(ss, compressionAlg)));
PRUint32 decodedCertLen = 0;
rv = ssl3_ConsumeHandshakeNumber(ss, &decodedCertLen, 3, &b, &length); if (rv != SECSuccess) { return SECFailure; /* alert has been sent */
}
/* If the received CompressedCertificate message cannot be decompressed, *heconnectionMUSTbeterminatedwiththe"bad_certificate"alert.
*/ if (decodedCertLen == 0) {
SSL_TRC(50, ("%d: TLS13[%d]: %s decoded certificate length is incorrect",
SSL_GETPID(), ss->fd, SSL_ROLE(ss),
ssl3_mapCertificateCompressionAlgorithmToName(ss, compressionAlg)));
FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_CERTIFICATE, bad_certificate); return SECFailure;
}
/* Cap the decompressed size to prevent memory exhaustion. The wire field *isauint24(max16MB)buttheCompressedCertificatepathbypassesthe *128KBcapappliedtoregularhandshakemessages.100KBmatchesthelimit
* enforced by OpenSSL and BoringSSL. */ #define MAX_CERT_UNCOMPRESSED_LEN (100 * 1024) if (decodedCertLen > MAX_CERT_UNCOMPRESSED_LEN) {
SSL_TRC(50, ("%d: TLS13[%d]: %s uncompressed_length %u exceeds limit %u",
SSL_GETPID(), ss->fd, SSL_ROLE(ss),
decodedCertLen, MAX_CERT_UNCOMPRESSED_LEN));
FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_CERTIFICATE, bad_certificate); return SECFailure;
} #undef MAX_CERT_UNCOMPRESSED_LEN
/* opaque compressed_certificate_message<1..2^24-1>; */
PRUint32 compressedCertLen = 0;
rv = ssl3_ConsumeHandshakeNumber(ss, &compressedCertLen, 3, &b, &length); if (rv != SECSuccess) { return SECFailure; /* alert has been sent */
}
if (rv != SECSuccess) {
SSL_TRC(50, ("%d: TLS13[%d]: %s decoding of the certificate has failed",
SSL_GETPID(), ss->fd, SSL_ROLE(ss),
ssl3_mapCertificateCompressionAlgorithmToName(ss, compressionAlg)));
FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_CERTIFICATE, bad_certificate); goto loser;
}
PRINT_BUF(60, (ss, "consume bytes:", b, compressedCertLen));
*b += compressedCertLen;
length -= compressedCertLen;
/* If, after decompression, the specified length does not match the actual length, *thepartyreceivingtheinvalidmessageMUSTaborttheconnection *withthe"bad_certificate"alert.
*/ if (actualCertLen != decodedCertLen) {
SSL_TRC(50, ("%d: TLS13[%d]: %s certificate length does not correspond to extension length",
SSL_GETPID(), ss->fd, SSL_ROLE(ss),
ssl3_mapCertificateCompressionAlgorithmToName(ss, compressionAlg)));
FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_CERTIFICATE, bad_certificate); goto loser;
}
/* compressed_certificate_message: The result of applying the indicated *compressionalgorithmtotheencodedCertificatemessagethat *wouldhavebeensentifcertificatecompressionwasnotinuse. * *Afterdecompression,theCertificatemessageMUSTbeprocessedasif *itwereencodedwithoutbeingcompressed.Thisway,theparsingand *theverificationhavethesamesecuritypropertiesastheywouldhave *inTLSnormally.
*/
rv = tls13_HandleCertificate(ss, decodedCert, decodedCertLen, PR_TRUE); if (rv != SECSuccess) { goto loser;
} /* We allow only one compressed certificate to be handled after each certificatecompressionadvertisement.
See test CertificateCompression_TwoEncodedCertificateRequests. */
ss->xtnData.certificateCompressionAdvertised = PR_FALSE;
PORT_Free(decodedCert); return SECSuccess;
/* We can ignore any other cleartext from the client. */ if (ss->sec.isServer && IS_DTLS(ss)) {
ssl_CipherSpecReleaseByEpoch(ss, ssl_secret_read, TrafficKeyClearText);
dtls_ReceivedFirstMessageInFlight(ss);
}
/* AlreadyHashed is true only when Certificate Compression is used. */ if (ss->firstHsDone && !alreadyHashed) {
rv = ssl_HashPostHandshakeMessage(ss, ssl_hs_certificate, b, length); if (rv != SECSuccess) {
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); return SECFailure;
}
}
if (!ss->firstHsDone && ss->sec.isServer) { /* Our first shot an getting an RTT estimate. If the client took extra *timetofetchacertificate,thiswillbebad,butwecan'tdomuch
* about that. */
ss->ssl3.hs.rttEstimate = ssl_Time(ss) - ss->ssl3.hs.rttEstimate;
}
/* Process the context string */
rv = ssl3_ConsumeHandshakeVariable(ss, &context, 1, &b, &length); if (rv != SECSuccess) return SECFailure;
if (!certList.len) { if (!ss->sec.isServer) { /* Servers always need to send some cert. */
FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_CERTIFICATE, bad_certificate); return SECFailure;
} else { /* This is TLS's version of a no_certificate alert. */ /* I'm a server. I've requested a client cert. He hasn't got one. */
rv = ssl3_HandleNoCertificate(ss); if (rv != SECSuccess) { return SECFailure;
}
/* Now clean up. */
ssl3_CleanupPeerCerts(ss);
ss->ssl3.peerCertArena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); if (ss->ssl3.peerCertArena == NULL) {
FATAL_ERROR(ss, SEC_ERROR_NO_MEMORY, internal_error); return SECFailure;
}
while (certList.len) {
SECItem derCert; // will hold a weak reference into certList
rv = tls13_HandleCertificateEntry(ss, &certList, first,
&derCert); if (rv != SECSuccess) {
ss->xtnData.signedCertTimestamps.len = 0; return SECFailure;
}
if (first) {
ss->sec.peerCert = CERT_NewTempCertificate(ss->dbHandle, &derCert,
NULL, PR_FALSE, PR_TRUE); if (!ss->sec.peerCert) {
PRErrorCode errCode = PORT_GetError(); switch (errCode) { case PR_OUT_OF_MEMORY_ERROR: case SEC_ERROR_BAD_DATABASE: case SEC_ERROR_NO_MEMORY:
FATAL_ERROR(ss, errCode, internal_error); return SECFailure; default:
ssl3_SendAlertForCertError(ss, errCode); return SECFailure;
}
}
/* if we are server & sending or !server & !sending, update the scheme */ /* only update on server cert verify */ if ((direction == sig_sign && ss->sec.isServer) ||
(direction == sig_verify && !ss->sec.isServer)) {
ss->sec.signatureScheme = scheme;
ss->sec.authType = ssl_SignatureSchemeToAuthType(scheme);
} return SECSuccess;
if (deleteSecret) {
PK11_FreeSymKey(prk);
*prkp = NULL;
} return SECSuccess;
loser: return SECFailure;
}
void
tls13_SetSpecRecordVersion(sslSocket *ss, ssl3CipherSpec *spec)
{ /* Set the record version to pretend to be (D)TLS 1.2. */ if (IS_DTLS(ss)) {
spec->recordVersion = SSL_LIBRARY_VERSION_DTLS_1_2_WIRE;
} else {
spec->recordVersion = SSL_LIBRARY_VERSION_TLS_1_2;
}
SSL_TRC(10, ("%d: TLS13[%d]: set spec=%d record version to 0x%04x",
SSL_GETPID(), ss->fd, spec, spec->recordVersion));
}
if (spec->epoch == TrafficKeyEarlyApplicationData) { if (ss->xtnData.selectedPsk &&
ss->xtnData.selectedPsk->zeroRttSuite != TLS_NULL_WITH_NULL_NULL) {
spec->earlyDataRemaining = ss->xtnData.selectedPsk->maxEarlyData;
}
}
tls13_SetSpecRecordVersion(ss, spec);
/* The record size limit is reduced by one so that the remainder of the
* record handling code can use the same checks for all versions. */ if (ssl3_ExtensionNegotiated(ss, ssl_record_size_limit_xtn)) {
spec->recordSizeLimit = ((spec->direction == ssl_secret_read)
? ss->opt.recordSizeLimit
: ss->xtnData.recordSizeLimit) - 1;
} else {
spec->recordSizeLimit = MAX_FRAGMENT_LENGTH;
} return SECSuccess;
}
PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss)); if (ss->ssl3.hs.hashType == handshake_hash_unknown) { /* Backup: if we haven't done any hashing, then hash now.
* This happens when we are doing 0-RTT on the client. */
ctx = PK11_CreateDigestContext(ssl3_HashTypeToOID(tls13_GetHash(ss))); if (!ctx) {
ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE); return SECFailure;
}
if (PK11_DigestBegin(ctx) != SECSuccess) {
ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE); goto loser;
}
/* One might expect this to use ss->ssl3.hs.echAccepted,
* but with 0-RTT we don't know that yet. */
useEchInner = ss->sec.isServer ? PR_FALSE : !!ss->ssl3.hs.echHpkeCtx;
transcript = useEchInner ? &ss->ssl3.hs.echInnerMessages : &ss->ssl3.hs.messages;
PRINT_BUF(10, (ss, "Handshake hash computed over saved messages",
transcript->buf,
transcript->len));
/* XOR the last n bytes of the IV with the nonce (should be a counter). */ for (i = 0; i < nonceLen; ++i) {
ivOut[offset + i] ^= nonce[i];
}
PRINT_BUF(50, (NULL, "Nonce", ivOut, ivOutLen));
}
/* Setup the IV for AEAD encrypt. The PKCS #11 module will add the *counter,butitdoesn'tknowabouttheDTLSepic,soweaddithere.
*/ unsignedint
tls13_SetupAeadIv(PRBool isDTLS, SSL3ProtocolVersion v, unsignedchar *ivOut, unsignedchar *ivIn, unsignedint offset, unsignedint ivLen, DTLSEpoch epoch)
{
PORT_Memcpy(ivOut, ivIn, ivLen); if (isDTLS && v < SSL_LIBRARY_VERSION_TLS_1_3) { /* handle the tls 1.2 counter mode case, the epoc is copied *insteadofxored.WeaccomplishthisbyclearingivOut
* before running xor. */ if (offset >= ivLen) {
ivOut[offset] = ivOut[offset + 1] = 0;
}
ivOut[offset] ^= (unsignedchar)(epoch >> BPB) & 0xff;
ivOut[offset + 1] ^= (unsignedchar)(epoch)&0xff;
offset += 2;
}
/* must have either context or the symKey set */ if (!context) {
PORT_SetError(SEC_ERROR_INVALID_ARGS); return SECFailure;
}
PORT_Assert(ivLen <= MAX_IV_LENGTH);
PORT_Assert(tagLen <= HASH_LENGTH_MAX); if (!ivOut) {
ivOut = iv; /* caller doesn't need a returned, iv */
}
if (ivGen == CKG_NO_GENERATE) {
tls13_WriteNonce(ivIn, ivLen, nonceIn, nonceLen, ivOut, ivLen);
} elseif (ivIn != ivOut) {
PORT_Memcpy(ivOut, ivIn, ivLen);
} if (decrypt) { if (inLen < tagLen) {
PORT_SetError(SEC_ERROR_INPUT_LEN); return SECFailure;
}
inLen = inLen - tagLen;
tag = (unsignedchar *)in + inLen; /* tag is const on decrypt, but returned on encrypt */
} else { /* tag is written to a separate buffer, then added to the end *oftheactualoutputbuffer.Thisallowsoutputbuffertobelarger
* than the input buffer and everything still work */
tag = tagbuf;
}
rv = PK11_AEADOp(context, ivGen, fixedbits, ivOut, ivLen, aad, aadLen,
out, (int *)outLen, maxout, tag, tagLen, in, inLen); /* on encrypt SSL always puts the tag at the end of the buffer */ if ((rv == SECSuccess) && !(decrypt)) { unsignedint len = *outLen; /* make sure there is still space */ if (len + tagLen > maxout) {
PORT_SetError(SEC_ERROR_OUTPUT_LEN); return SECFailure;
}
PORT_Memcpy(out + len, tag, tagLen);
*outLen += tagLen;
} return rv;
}
/* If we are doing 0-RTT, then we already have an ALPN value. Stash
* it for comparison. */ if (ss->ssl3.hs.zeroRttState == ssl_0rtt_sent &&
ss->xtnData.nextProtoState == SSL_NEXT_PROTO_EARLY_VALUE) {
oldAlpn = ss->xtnData.nextProto;
ss->xtnData.nextProto.data = NULL;
ss->xtnData.nextProtoState = SSL_NEXT_PROTO_NO_SUPPORT;
}
rv = ssl3_ParseExtensions(ss, &b, &length); if (rv != SECSuccess) { return SECFailure; /* Error code set below */
}
/* Handle the rest of the extensions. */
rv = ssl3_HandleParsedExtensions(ss, ssl_hs_encrypted_extensions); if (rv != SECSuccess) { return SECFailure; /* Error code set below */
}
/* 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->xtnData.selectedPsk) { /* Illegal to accept 0-RTT without also accepting PSK. */
FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_ENCRYPTED_EXTENSIONS,
illegal_parameter); return SECFailure;
}
ss->ssl3.hs.zeroRttState = ssl_0rtt_accepted;
/* Check that the server negotiated the same ALPN (if any). */ if (SECITEM_CompareItem(&oldAlpn, &ss->xtnData.nextProto)) {
SECITEM_FreeItem(&oldAlpn, PR_FALSE);
FATAL_ERROR(ss, SSL_ERROR_NEXT_PROTOCOL_DATA_INVALID,
illegal_parameter); return SECFailure;
} /* Check that the server negotiated the same cipher suite. */ if (ss->ssl3.hs.cipher_suite != ss->ssl3.hs.zeroRttSuite) {
FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_ENCRYPTED_EXTENSIONS,
illegal_parameter); return SECFailure;
}
} elseif (ss->ssl3.hs.zeroRttState == ssl_0rtt_sent) { /* Though we sent 0-RTT, the early_data extension wasn't present so the
* state is unmodified; the server must have rejected 0-RTT. */
ss->ssl3.hs.zeroRttState = ssl_0rtt_ignored;
ss->ssl3.hs.zeroRttIgnore = ssl_0rtt_ignore_trial;
} else {
PORT_Assert(ss->ssl3.hs.zeroRttState == ssl_0rtt_none ||
(ss->ssl3.hs.helloRetry &&
ss->ssl3.hs.zeroRttState == ssl_0rtt_ignored));
}
/* We should have picked a signature scheme when we received a
* CertificateRequest, or when we picked a server certificate. */
PORT_Assert(ss->ssl3.hs.signatureScheme != ssl_sig_none); if (ss->ssl3.hs.signatureScheme == ssl_sig_none) {
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); return SECFailure;
}
rv = tls13_SignOrVerifyHashWithContext(ss, &hash, privKey, NULL,
ss->ssl3.hs.signatureScheme,
sig_sign, &buf); if (rv == SECSuccess && !ss->sec.isServer) { /* Remember the info about the slot that did the signing. *Later,whendoinganSSLrestarthandshake,verifythis. *Thesecallsaremereaccessors,andcan'tfail.
*/
PK11SlotInfo *slot;
sslSessionID *sid = ss->sec.ci.sid;
slot = PK11_GetSlotFromPrivateKey(privKey);
sid->u.ssl3.clAuthSeries = PK11_GetSlotSeries(slot);
sid->u.ssl3.clAuthSlotID = PK11_GetSlotID(slot);
sid->u.ssl3.clAuthModuleID = PK11_GetModuleID(slot);
sid->u.ssl3.clAuthValid = PR_TRUE;
PK11_FreeSlot(slot);
} if (rv != SECSuccess) { goto done; /* err code was set by tls13_SignOrVerifyHashWithContext */
}
len = buf.len + 2 + 2;
rv = ssl3_AppendHandshakeHeader(ss, ssl_hs_certificate_verify, len); if (rv != SECSuccess) { goto done; /* error code set by AppendHandshake */
}
rv = ssl3_AppendHandshakeNumber(ss, ss->ssl3.hs.signatureScheme, 2); if (rv != SECSuccess) { goto done; /* err set by AppendHandshakeNumber */
}
rv = ssl3_AppendHandshakeVariable(ss, buf.data, buf.len, 2); if (rv != SECSuccess) { goto done; /* error code set by AppendHandshake */
}
done: /* For parity with the allocation functions, which don't use
* SECITEM_AllocItem(). */ if (buf.data)
PORT_Free(buf.data); return rv;
}
/* Called from tls13_CompleteHandleHandshakeMessage() when it has deciphered a complete *tls13CertificateVerifymessage *CallermustholdHandshakeandRecvBuflocks.
*/
SECStatus
tls13_HandleCertificateVerify(sslSocket *ss, PRUint8 *b, PRUint32 length)
{
sslDelegatedCredential *dc = ss->xtnData.peerDelegCred;
CERTSubjectPublicKeyInfo *spki;
SECKEYPublicKey *pubKey = NULL;
SECItem signed_hash = { siBuffer, NULL, 0 };
SECStatus rv;
SSLSignatureScheme sigScheme;
SSL3Hashes hashes;
/* Set the |spki| used to verify the handshake. When verifying with a *delegatedcredential(DC),thiscorrespondstotheDCpublickey; *otherwiseitcorrespondtothepublickeyofthepeer'send-entity *certificate.
*/ if (tls13_IsVerifyingWithDelegatedCredential(ss)) { /* DelegatedCredential.cred.expected_cert_verify_algorithm is expected *tomatchCertificateVerify.scheme. *DelegatedCredential.cred.expected_cert_verify_algorithmmustalsobe *thesameaswasreportedinssl3_AuthCertificate.
*/ if (sigScheme != dc->expectedCertVerifyAlg || sigScheme != ss->sec.signatureScheme) {
FATAL_ERROR(ss, SSL_ERROR_DC_CERT_VERIFY_ALG_MISMATCH, illegal_parameter); return SECFailure;
}
/* Verify the DC has three steps: (1) use the peer's end-entity *certificatetoverifyDelegatedCredential.signature,(2)checkthat *thecertificatehasthecorrectkeyusage,and(3)checkthattheDC *hasn'texpired.
*/
rv = tls13_VerifyDelegatedCredential(ss, dc); if (rv != SECSuccess) { /* Calls FATAL_ERROR() */ return SECFailure;
}
/* Set the auth type and verify it is what we captured in ssl3_AuthCertificate */ if (!ss->sec.isServer) {
ss->sec.authType = ssl_SignatureSchemeToAuthType(sigScheme);
uint32_t prelimAuthKeyBits = ss->sec.authKeyBits;
rv = ssl_SetAuthKeyBits(ss, pubKey); if (rv != SECSuccess) { goto loser; /* Alert sent and code set. */
}
/* Request a client certificate now if one was requested. */ if (ss->ssl3.hs.clientCertRequested) {
PORT_Assert(!ss->sec.isServer);
rv = ssl3_BeginHandleCertificateRequest(
ss, ss->xtnData.sigSchemes, ss->xtnData.numSigSchemes,
&ss->xtnData.certReqAuthorities); if (rv != SECSuccess) {
FATAL_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE, internal_error); goto loser;
}
}
loser: if (ctx) {
PK11_DestroyContext(ctx, PR_TRUE);
} return SECFailure;
}
/* Compute and inject the PSK Binder for sending. * *WhensendingaClientHello,weconstructalltheextensionswithadummy *valueforthebinder.Toconstructthebinder,wecommittheentiremessage *uptothepointwherethebindersstart.Thenwecalculatethehashusing *thesavedmessage(inss->ssl3.hs.messages).Thisiswrittenoverthedummy
* binder, after which we write the remainder of the binder extension. */
SECStatus
tls13_WriteExtensionsWithBinder(sslSocket *ss, sslBuffer *extensions, sslBuffer *chBuf)
{
SSL3Hashes hashes;
SECStatus rv;
/* Only write the extension up to the point before the binders. Assume that *thepre_shared_keyextensionisattheendofthebuffer.Don'twrite *thebinder,orthelengthsthatprecedeit(a2octetlengthforthelist
* of all binders, plus a 1 octet length for the binder length). */
rv = sslBuffer_Append(chBuf, extensions->buf, prefixLen); if (rv != SECSuccess) { return SECFailure;
}
/* Calculate the binder based on what has been written out. */
rv = tls13_ComputePskBinderHash(ss, chBuf->buf, chBuf->len, &hashes, psk->hash); if (rv != SECSuccess) { return SECFailure;
}
/* Write the binder into the extensions buffer, over the zeros we reserved *previously.Thisavoidsanallocationandmeansthatwedon'tneeda
* separate write for the extra bits that precede the binder. */
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) { return SECFailure;
}
PORT_Assert(finishedLen == size);
/* Write out the remainder of the extension. */
rv = sslBuffer_Append(chBuf, extensions->buf + prefixLen,
extensions->len - prefixLen); if (rv != SECSuccess) { return SECFailure;
}
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;
}
}
if (IS_DTLS(ss)) {
ssl_CipherSpecReleaseByEpoch(ss, ssl_secret_read, TrafficKeyClearText); /* We need to keep the handshake cipher spec so we can
* read re-transmitted client Finished. */
rv = dtls_StartTimer(ss, ss->ssl3.hs.hdTimer,
DTLS_RETRANSMIT_FINISHED_MS,
dtls13_HolddownTimerCb); if (rv != SECSuccess) { return SECFailure;
}
}
ssl_GetXmitBufLock(ss); /* 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;
}
rv = ssl3_FlushHandshake(ss, 0); if (rv != SECSuccess) { goto loser;
}
}
ssl_ReleaseXmitBufLock(ss); return SECSuccess;
/* Do the parts of sending the client's second round that require
* the XmitBuf lock. */ static SECStatus
tls13_SendClientSecondFlight(sslSocket *ss)
{
SECStatus rv; unsignedint offset = 0;
if (ss->firstHsDone) {
rv = ssl3_UpdatePostHandshakeHashes(ss,
SSL_BUFFER_BASE(&ss->sec.ci.sendBuf) + offset,
SSL_BUFFER_LEN(&ss->sec.ci.sendBuf) - offset); if (rv != SECSuccess) { goto alert_error; /* err code was set. */
}
}
}
rv = tls13_SendFinished(ss, ss->firstHsDone ? ss->ssl3.hs.clientTrafficSecret : ss->ssl3.hs.clientHsTrafficSecret); if (rv != SECSuccess) { goto alert_error; /* err code was set. */
}
rv = ssl3_FlushHandshake(ss, 0); if (rv != SECSuccess) { /* No point in sending an alert here because we're not going to
* be able to send it if we couldn't flush the handshake. */ goto error;
}
/* Defer client authentication sending if we are still waiting for server *authentication.Thisavoidsunnecessarydisclosureofclientcredentials *toanunauthenticatedserver.
*/ if (ss->ssl3.hs.restartTarget) {
PR_NOT_REACHED("unexpected ss->ssl3.hs.restartTarget");
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); return SECFailure;
} if (ss->ssl3.hs.authCertificatePending || ss->ssl3.hs.clientCertificatePending) {
SSL_TRC(3, ("%d: TLS13[%d]: deferring tls13_SendClientSecondRound because" " certificate authentication is still pending.",
SSL_GETPID(), ss->fd));
ss->ssl3.hs.restartTarget = tls13_SendClientSecondRound;
PORT_SetError(PR_WOULD_BLOCK_ERROR); return SECFailure;
}
/* Max early data size extension. */ if (max_early_data_size_len) {
rv = ssl3_AppendHandshakeNumber(
ss, ssl_tls13_early_data_xtn, 2); if (rv != SECSuccess) goto loser;
/* Disable tickets if we can trace this connection back to a PSK. *Wearen'tabletoissuetickets(currently)withoutacertificate.
* 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;
}
/* Replace a previous session ticket when
* we receive a second NewSessionTicket message. */ if (ss->sec.ci.sid->cached == in_client_cache ||
ss->sec.ci.sid->cached == in_external_cache) { /* Create a new session ID. */
sslSessionID *sid = ssl3_NewSessionID(ss, PR_FALSE); if (!sid) { return SECFailure;
}
/* Copy over the peerCert. */
PORT_Assert(ss->sec.ci.sid->peerCert);
sid->peerCert = CERT_DupCertificate(ss->sec.ci.sid->peerCert); if (!sid->peerCert) {
ssl_FreeSID(sid); return SECFailure;
}
/* Destroy the old SID. */
ssl_UncacheSessionID(ss);
ssl_FreeSID(ss->sec.ci.sid);
ss->sec.ci.sid = sid;
}
for (i = 0; i < PR_ARRAY_SIZE(KnownExtensions); i++) { /* Hacky check for message numbers > 30. */
PORT_Assert(!(KnownExtensions[i].messages & (1U << 31))); if (KnownExtensions[i].ex_value == extension) { break;
}
} if (i >= PR_ARRAY_SIZE(KnownExtensions)) { return tls13_extension_unknown;
}
/* Return "disallowed" if the message mask bit isn't set. */ if (!(_M(message) & KnownExtensions[i].messages)) { return tls13_extension_disallowed;
}
return tls13_extension_allowed;
}
#undef _M #undef _M1 #undef _M2 #undef _M3
/* We cheat a bit on additional data because the AEAD interface *whichdoesn'thaveroomfortherecordnumber.TheAADwe *formatisserializedrecordnumberfollowedbythetrueAD
* (i.e., the record header) plus the serialized record number. */ static SECStatus
tls13_FormatAdditionalData(
sslSocket *ss, const PRUint8 *header, unsignedint headerLen,
DTLSEpoch epoch, sslSequenceNumber seqNum,
PRUint8 *aad, unsignedint *aadLength, unsignedint maxLength)
{
SECStatus rv;
sslBuffer buf = SSL_BUFFER_FIXED(aad, maxLength);
/* If the following condition holds, we can skip the padding logic for *DTLS1.3(4.2.3).Thiswillbethecaseuntilwesupportacipher
* with tag length < 15B. */
PORT_Assert(tagLen + 1/* cType */ >= 16);
/* Add the content type at the end. */
*(SSL_BUFFER_NEXT(wrBuf) + contentLen) = type;
/* Create the header (ugly that we have to do it twice). */
rv = ssl_InsertRecordHeader(ss, cwSpec, ssl_ct_application_data,
&buf, &needsLength); if (rv != SECSuccess) { return SECFailure;
} if (needsLength) {
rv = sslBuffer_AppendNumber(&buf, contentLen + 1 + tagLen, 2); if (rv != SECSuccess) { return SECFailure;
}
}
rv = tls13_FormatAdditionalData(ss, SSL_BUFFER_BASE(&buf), SSL_BUFFER_LEN(&buf),
cwSpec->epoch, cwSpec->nextSeqNum,
aad, &aadLen, sizeof(aad)); if (rv != SECSuccess) { return SECFailure;
} /* set up initial IV value */
ivOffset = tls13_SetupAeadIv(IS_DTLS(ss), cwSpec->version, ivOut, cwSpec->keyMaterial.iv,
ivOffset, ivLen, cwSpec->epoch);
rv = tls13_AEAD(cwSpec->cipherContext, PR_FALSE,
CKG_GENERATE_COUNTER_XOR, ivOffset * BPB,
ivOut, ivOut, ivLen, /* iv */
NULL, 0, /* nonce */
aad + sizeof(sslSequenceNumber), /* aad */
aadLen - sizeof(sslSequenceNumber),
SSL_BUFFER_NEXT(wrBuf), /* output */
&len, /* out len */
SSL_BUFFER_SPACE(wrBuf), /* max out */
tagLen,
SSL_BUFFER_NEXT(wrBuf), /* input */
contentLen + 1); /* input len */ if (rv != SECSuccess) {
PORT_SetError(SSL_ERROR_ENCRYPTION_FAILURE); return SECFailure;
}
rv = sslBuffer_Skip(wrBuf, len, NULL);
PORT_Assert(rv == SECSuccess);
}
return SECSuccess;
}
/* Unprotect a TLS 1.3 record and leave the result in plaintext. * *Calledbyssl3_HandleRecord.Callermustholdthespecreadlock. *Therefore,weMUSTnotcallSSL3_SendAlert(). * *IfSECFailureisreturned,we: *1.Set|*alert|tothealerttobesent. *2.CallPORT_SetError()withanappropriatecode.
*/
SECStatus
tls13_UnprotectRecord(sslSocket *ss,
ssl3CipherSpec *spec,
SSL3Ciphertext *cText,
sslBuffer *plaintext,
SSLContentType *innerType,
SSL3AlertDescription *alert)
{ const ssl3BulkCipherDef *cipher_def = spec->cipherDef; constint ivLen = cipher_def->iv_size + cipher_def->explicit_nonce_size; constint tagLen = cipher_def->tag_size; constint innerTypeLen = 1;
/* Verify that the outer content type is right. * *FortheinnercontenttypeaswellaslowerTLSversionsthisischecked *inssl3con.c/ssl3_HandleNonApllicationData(). * *ForDTLS1.3thisischeckedinssl3gthr.c/dtls_GatherData().DTLSdrops *invalidrecordssilently[RFC6347,Section4.1.2.7]. *
* Also allow the DTLS short header in TLS 1.3. */ if (!(cText->hdr[0] == ssl_ct_application_data ||
(IS_DTLS(ss) &&
ss->version >= SSL_LIBRARY_VERSION_TLS_1_3 &&
(cText->hdr[0] & 0xe0) == 0x20))) {
SSL_TRC(3,
("%d: TLS13[%d]: record has invalid exterior type=%2.2x",
SSL_GETPID(), ss->fd, cText->hdr[0]));
PORT_SetError(SSL_ERROR_RX_UNEXPECTED_RECORD_TYPE);
*alert = unexpected_message; return SECFailure;
}
/* We can perform this test in variable time because the record's total
* length and the ciphersuite are both public knowledge. */ if (cText->buf->len < tagLen) {
SSL_TRC(3,
("%d: TLS13[%d]: record too short to contain valid AEAD data",
SSL_GETPID(), ss->fd));
PORT_SetError(SSL_ERROR_BAD_MAC_READ); return SECFailure;
}
/* Check if the ciphertext can be valid if we assume maximum plaintext and *addthespecificciphersuiteexpansion. *Thiswaywedetectoverlongplaintexts/paddingbeforedecryption. *ThischeckenforcessizelimitationsmorestrictthantheRFC.
* (see RFC8446, Section 5.2) */ if (cText->buf->len > (spec->recordSizeLimit + innerTypeLen + tagLen)) {
*alert = record_overflow;
PORT_SetError(SSL_ERROR_RX_RECORD_TOO_LONG); return SECFailure;
}
/* Check the version number in the record. Stream only. */ if (!IS_DTLS(ss)) {
SSL3ProtocolVersion version =
((SSL3ProtocolVersion)cText->hdr[1] << 8) |
(SSL3ProtocolVersion)cText->hdr[2]; if (version != spec->recordVersion) { /* Do we need a better error here? */
SSL_TRC(3, ("%d: TLS13[%d]: record has bogus version",
SSL_GETPID(), ss->fd)); return SECFailure;
}
}
SSL_TRC(3,
("%d: TLS13[%d]: record has bogus MAC",
SSL_GETPID(), ss->fd));
PORT_SetError(SSL_ERROR_BAD_MAC_READ); return SECFailure;
}
/* There is a similar test in ssl3_HandleRecord, but this test is needed to
* account for padding. */ if (plaintext->len > spec->recordSizeLimit + innerTypeLen) {
*alert = record_overflow;
PORT_SetError(SSL_ERROR_RX_RECORD_TOO_LONG); return SECFailure;
}
/* The record is right-padded with 0s, followed by the true *contenttype,soreadfromtherightuntilwereceivea
* nonzero byte. */ while (plaintext->len > 0 && !(plaintext->buf[plaintext->len - 1])) {
--plaintext->len;
}
/* Bogus padding. */ if (plaintext->len < 1) {
SSL_TRC(3, ("%d: TLS13[%d]: empty record", SSL_GETPID(), ss->fd)); /* It's safe to report this specifically because it happened
* after the MAC has been verified. */
*alert = unexpected_message;
PORT_SetError(SSL_ERROR_BAD_BLOCK_PADDING); return SECFailure;
}
/* Record the type. */
*innerType = (SSLContentType)plaintext->buf[plaintext->len - 1];
--plaintext->len;
/* Don't do anything if there is no early_data xtn, which means we're
* not doing early data. */ if (!ssl3_ExtensionAdvertised(ss, ssl_tls13_early_data_xtn)) { return SECSuccess;
}
ss->ssl3.hs.zeroRttState = ssl_0rtt_sent;
ss->ssl3.hs.zeroRttSuite = ss->ssl3.hs.cipher_suite; /* Note: Reset the preliminary info here rather than just add 0-RTT. We are
* only guessing what might happen at this point.*/
ss->ssl3.hs.preliminaryInfo = ssl_preinfo_0rtt_cipher_suite;
SSL_TRC(3, ("%d: TLS13[%d]: in 0-RTT mode", SSL_GETPID(), ss->fd));
/* Set the ALPN data as if it was negotiated. We check in the ServerHello
* handler that the server negotiates the same value. */ if (ss->sec.ci.sid->u.ssl3.alpnSelection.len) {
ss->xtnData.nextProtoState = SSL_NEXT_PROTO_EARLY_VALUE;
rv = SECITEM_CopyItem(NULL, &ss->xtnData.nextProto,
&ss->sec.ci.sid->u.ssl3.alpnSelection); if (rv != SECSuccess) { return SECFailure;
}
}
if (ss->opt.enableTls13CompatMode && !IS_DTLS(ss)) { /* Pretend that this is a proper ChangeCipherSpec even though it is sent
* before receiving the ServerHello. */
ssl_GetSpecWriteLock(ss);
tls13_SetSpecRecordVersion(ss, ss->ssl3.cwSpec);
ssl_ReleaseSpecWriteLock(ss);
ssl_GetXmitBufLock(ss);
rv = ssl3_SendChangeCipherSpecsInt(ss);
ssl_ReleaseXmitBufLock(ss); if (rv != SECSuccess) { return SECFailure;
}
}
/* If we have any message that was saved for later hashing.
* The updated hash is then used in tls13_DeriveEarlySecrets. */
rv = ssl3_MaybeUpdateHashWithSavedRecord(ss); if (rv != SECSuccess) { return SECFailure;
}
/* 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;
}
/* Save cwSpec in case we get a HelloRetryRequest and have to send another
* ClientHello. */
ssl_CipherSpecAddRef(ss->ssl3.cwSpec);
if (tocpy > (len - offset)) { if (IS_DTLS(ss)) { /* In DTLS, we only return entire records.
* So offset and consumed are always zero. */
PORT_Assert(offset == 0);
PORT_Assert(msg->consumed == 0);
PORT_SetError(SSL_ERROR_RX_SHORT_DTLS_READ); return -1;
}
/* We shouldn't be getting any more early data, and if we do,
* it is because of reordering and we drop it. */ if (IS_DTLS(ss)) {
ssl_CipherSpecReleaseByEpoch(ss, ssl_secret_read,
TrafficKeyEarlyApplicationData);
dtls_ReceivedFirstMessageInFlight(ss);
}
/* Update the version based on the extension, as necessary. */
versionExtension = ssl3_FindExtension(ss, ssl_tls13_supported_versions_xtn); if (!versionExtension) { return SECSuccess;
}
/* Struct copy so we don't damage the extension. */
it = versionExtension->data;
/* Pick the highest version we support that is also advertised. */
SECStatus
tls13_NegotiateVersion(sslSocket *ss, const TLSExtension *supportedVersions)
{
PRUint16 version; /* Make a copy so we're nondestructive. */
SECItem data = supportedVersions->data;
SECItem versions;
SECStatus rv;
rv = ssl3_ConsumeHandshakeVariable(ss, &versions, 1,
&data.data, &data.len); if (rv != SECSuccess) { return SECFailure;
} if (data.len || !versions.len || (versions.len & 1)) {
FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_CLIENT_HELLO, illegal_parameter); return SECFailure;
} for (version = ss->vrange.max; version >= ss->vrange.min; --version) { if (version < SSL_LIBRARY_VERSION_TLS_1_3 &&
(ss->ssl3.hs.helloRetry || ss->ssl3.hs.echAccepted)) { /* Prevent negotiating to a lower version after 1.3 HRR or ECH *WhenacceptingECH,adifferentalertisgenerated.
*/
SSL3AlertDescription alert = ss->ssl3.hs.echAccepted ? illegal_parameter : protocol_version;
PORT_SetError(SSL_ERROR_UNSUPPORTED_VERSION);
FATAL_ERROR(ss, SSL_ERROR_UNSUPPORTED_VERSION, alert); return SECFailure;
}
/* This is TLS 1.3 or might negotiate to it. */
PRBool
tls13_MaybeTls13(sslSocket *ss)
{ if (ss->version >= SSL_LIBRARY_VERSION_TLS_1_3) { return PR_TRUE;
}
if (ss->vrange.max < SSL_LIBRARY_VERSION_TLS_1_3) { return PR_FALSE;
}
if (!(ss->ssl3.hs.preliminaryInfo & ssl_preinfo_version)) { return PR_TRUE;
}
return PR_FALSE;
}
/* Setup random client GREASE values according to RFC8701. State must be kept
* so an equal ClientHello might be send on HelloRetryRequest. */
SECStatus
tls13_ClientGreaseSetup(sslSocket *ss)
{ if (!ss->opt.enableGrease) { return SECSuccess;
}
/* Generate a random GREASE value according to RFC8701.
* This function does not provide valid PskKeyExchangeMode GREASE values! */
SECStatus
tls13_RandomGreaseValue(PRUint16 *out)
{
PRUint8 random;
if (PK11_GenerateRandom(&random, sizeof(random)) != SECSuccess) { return SECFailure;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.