/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * TLS 1.3 Protocol * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
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;
}
PORT_Assert(groupDef); switch (groupDef->keaType) { case ssl_kea_ecdh_hybrid: if (groupDef->name != ssl_grp_kem_xyber768d00 && groupDef->name != ssl_grp_kem_mlkem768x25519) {
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); return SECFailure;
} const sslNamedGroupDef *x25519 = ssl_LookupNamedGroup(ssl_grp_ec_curve25519);
sslEphemeralKeyPair *x25519Pair = ssl_LookupEphemeralKeyPair(ss, x25519); if (x25519Pair) {
keyPair = ssl_CopyEphemeralKeyPair(x25519Pair);
} if (!keyPair) {
rv = ssl_CreateECDHEphemeralKeyPair(ss, x25519, &keyPair); if (rv != SECSuccess) { return SECFailure;
}
}
keyPair->group = groupDef; break; case ssl_kea_ecdh: if (groupDef->name == ssl_grp_ec_curve25519) {
sslEphemeralKeyPair *hybridPair = ssl_LookupEphemeralKeyPair(ss, ssl_LookupNamedGroup(ssl_grp_kem_mlkem768x25519)); if (!hybridPair) {
hybridPair = ssl_LookupEphemeralKeyPair(ss, ssl_LookupNamedGroup(ssl_grp_kem_xyber768d00));
} if (hybridPair) { // We could use ssl_CopyEphemeralKeyPair here, but we would need to free // the KEM components. We should pull this out into a utility function when // we refactor to support multiple hybrid mechanisms.
keyPair = PORT_ZNew(sslEphemeralKeyPair); if (!keyPair) { return SECFailure;
}
PR_INIT_CLIST(&keyPair->link);
keyPair->group = groupDef;
keyPair->keys = ssl_GetKeyPairRef(hybridPair->keys);
}
} 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;
}
}
/* * Generate shares for ECDHE and FFDHE. This picks the first enabled group of * the requisite type and creates a share for that. * * Called from ssl3_SendClientHello.
*/
SECStatus
tls13_SetupClientHello(sslSocket *ss, sslClientHelloType chType)
{ unsignedint i;
SSL3Statistics *ssl3stats = SSL_GetStatistics();
NewSessionTicket *session_ticket = NULL;
sslSessionID *sid = ss->sec.ci.sid; unsignedint numShares = 0;
SECStatus rv;
/* Select the first enabled group. * TODO(ekr@rtfm.com): be smarter about offering the group
* 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 * 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);
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);
staticvoid
tls13_RestoreCipherInfo(sslSocket *ss, sslSessionID *sid)
{ /* Set these to match the cached value. * TODO(ekr@rtfm.com): Make a version with the "true" values. * Bug 1256137.
*/
ss->sec.authType = sid->authType;
ss->sec.authKeyBits = sid->authKeyBits;
ss->sec.originalKeaGroup = ssl_LookupNamedGroup(sid->keaGroup);
ss->sec.signatureScheme = sid->sigScheme;
}
if (sid->version != ss->version) { 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;
}
/* Server sids don't remember the server cert we previously sent, but they * do remember the type of certificate we originally used, so we can locate * it again, provided that the current ssl socket has had its server certs
* 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-RTT is only permitted if: * 1. The early data extension was present. * 2. We are resuming a session. * 3. The 0-RTT option is set. * 4. The ticket allowed 0-RTT. * 5. We negotiated the same ALPN value as in the ticket.
*/ 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, reset the ignore state so that decryption failure is
* 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 * every other PskKem value but DHE stateless resumption is disabled,
* 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 * mutually supported groups, regardless of what the client offered * for key shares.
*/ 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) the right authentication method, and * b) the right named curve (EC only) * * We might want to do some sort of ranking here later. For now, it's all
* 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 * the current handshake, then commit to using it now. We'll send a * DC as an extension and use the DC private key to sign the * handshake. * * This sets the signature scheme to be the signature scheme * indicated by the DC.
*/
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;
}
SSL_TRC(3, ("%d: TLS13[%d]: selected certificate authentication",
SSL_GETPID(), ss->fd));
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. */
SECStatus
tls13_HandleClientHelloPart2(sslSocket *ss, const SECItem *suites,
sslSessionID *sid, const PRUint8 *msg, unsignedint len)
{
SECStatus rv;
SSL3Statistics *ssl3stats = SSL_GetStatistics(); const sslNamedGroupDef *requestedGroup = NULL;
TLS13KeyShareEntry *clientShare = NULL;
ssl3CipherSuite previousCipherSuite = 0; const sslNamedGroupDef *previousGroup = NULL;
PRBool hrr = PR_FALSE;
PRBool previousOfferedEch;
/* 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/absent extension cause failure
* 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;
}
}
/* * struct { * ProtocolVersion server_version; * CipherSuite cipher_suite; * Extension extensions<2..2^16-1>; * } HelloRetryRequest; * * Note: this function takes an empty buffer and returns * a non-empty one on success, in which case the caller must * eventually clean up.
*/
SECStatus
tls13_ConstructHelloRetryRequest(sslSocket *ss,
ssl3CipherSuite cipherSuite, const sslNamedGroupDef *selectedGroup,
PRUint8 *cookie, unsignedint cookieLen, const PRUint8 *cookieGreaseEchSignal,
sslBuffer *buffer)
{
SECStatus rv;
sslBuffer extensionsBuf = SSL_BUFFER_EMPTY;
PORT_Assert(buffer->len == 0);
/* 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, * the HRR extension's payload must be set to 8 zero bytes, these are * overwritten with the accept_confirmation value after the handshake * transcript calculation. * If a client-facing or shared-mode server did not accept ECH when offered * OR if ECH GREASE is enabled on the server and a ECH extension was * received, a 8 byte random value is set as the extension's payload * [draft-ietf-tls-esni-14, Section 7]. * * The (temporary) payload is written to the extension in tls13exthandle.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) };
/* [draft-ietf-tls-tls13; S 4.4.1] says: * * Transcript-Hash(ClientHello1, HelloRetryRequest, ... MN) = * Hash(message_hash || // Handshake type * 00 00 Hash.length || // Handshake message length * Hash(ClientHello1) || // Hash of ClientHello1 * HelloRetryRequest ... MN) * * For an ECH handshake, the process occurs for the outer * transcript in |ss->ssl3.hs.messages| and the inner * transcript in |ss->ssl3.hs.echInnerMessages|.
*/ static SECStatus
tls13_ReinjectHandshakeTranscript(sslSocket *ss)
{
SSL3Hashes hashes = { 0 };
SSL3Hashes echInnerHashes = { 0 };
SECStatus rv;
/* 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;
}
/* * savedMsg contains the HelloRetryRequest message. When its extensions are parsed * in ssl3_HandleParsedExtensions, the handler for ECH HRR extensions (tls13_ClientHandleHrrEchXtn) * will take a reference into the message buffer. * * This reference is then used in tls13_MaybeHandleEchSignal in order to compute * the transcript for the ECH signal calculation. This was felt to be preferable * to re-parsing the HelloRetryRequest message in order to create the transcript. * * Consequently, savedMsg should not be moved or mutated between these * function calls.
*/
SECStatus
tls13_HandleHelloRetryRequest(sslSocket *ss, const PRUint8 *savedMsg,
PRUint32 savedLength)
{
SECStatus rv;
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 * ensure that a HelloRetryRequest isn't a no-op: we must have at least two * extensions, supported_versions plus one other. That other must be one * that we understand and recognize as being valid for HelloRetryRequest,
* 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, we should give it a chance to reach the network. This gives * the client a chance to perform the key exchange and decrypt the alert
* 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 * end up looking a lot like the old one.
*/
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 * send another ClientHello in response to a HelloRetryRequest. 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;
}
static SECStatus
tls13_SendCompressedCertificate(sslSocket *ss, sslBuffer *bufferCertificate)
{ /* TLS Certificate Compression. RFC 8879 */ /* As the encoding function takes as input a SECItem, * we convert bufferCertificate to certificateToEncode. * * encodedCertificate is used to store the certificate * after encoding.
*/
SECItem encodedCertificate = { siBuffer, NULL, 0 };
SECItem certificateToEncode = { siBuffer, NULL, 0 };
SECStatus rv = 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));
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 no compression mechanism was established or * the compression mechanism supports only decoding,
* we continue as before. */ if (ss->xtnData.compressionAlg == 0 || !tls13_FindCompressionAlgAndCheckIfSupportsEncoding(ss)) {
rv = ssl3_AppendHandshakeHeader(ss, ssl_hs_certificate,
1 + context.len + 3 + certChainLen); if (rv != SECSuccess) { goto loser; /* err set by AppendHandshake. */
}
rv = ssl3_AppendBufferToHandshake(ss, &bufferCertificate); if (rv != SECSuccess) { goto loser; /* err set by AppendHandshake. */
}
} else {
rv = tls13_SendCompressedCertificate(ss, &bufferCertificate); if (rv != SECSuccess) { goto loser; /* err set by tls13_SendCompressedCertificate. */
}
}
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, * he connection MUST be terminated with the "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;
}
/* 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, * the party receiving the invalid message MUST abort the connection * with the "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 * compression algorithm to the encoded Certificate message that * would have been sent if certificate compression was not in use. * * After decompression, the Certificate message MUST be processed as if * it were encoded without being compressed. This way, the parsing and * the verification have the same security properties as they would have * in TLS normally.
*/
rv = tls13_HandleCertificate(ss, decodedCert, decodedCertLen, PR_TRUE); if (rv != SECSuccess) { goto loser;
} /* We allow only one compressed certificate to be handled after each certificate compression advertisement.
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 * 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 */
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 (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));
}
/* Version isn't set when we send 0-RTT data. */
spec->version = PR_MAX(SSL_LIBRARY_VERSION_TLS_1_3, ss->version);
ssl_SaveCipherSpec(ss, spec); /* We want to keep read cipher specs around longer because * there are cases where we might get either epoch N or
* epoch N+1. */ if (IS_DTLS(ss) && spec->direction == ssl_secret_read) {
ssl_CipherSpecAddRef(spec);
}
SSL_TRC(3, ("%d: TLS13[%d]: Set Pending Cipher Suite to 0x%04x",
SSL_GETPID(), ss->fd, suite));
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;
}
/* * Initialize the cipher context. All TLS 1.3 operations are AEAD, * so they are all message contexts.
*/ static SECStatus
tls13_InitPendingContext(sslSocket *ss, ssl3CipherSpec *spec)
{
CK_MECHANISM_TYPE encMechanism;
CK_ATTRIBUTE_TYPE encMode;
SECItem iv;
SSLCipherAlgorithm calg;
/* * Called before sending alerts to set up the right key on the client. * We might encounter errors during the handshake where the current * key is ClearText or EarlyApplicationData. This * function switches to the Handshake key if possible.
*/
SECStatus
tls13_SetAlertCipherSpec(sslSocket *ss)
{
SECStatus rv;
if (ss->sec.isServer) { return SECSuccess;
} if (ss->version < SSL_LIBRARY_VERSION_TLS_1_3) { return SECSuccess;
} if (TLS13_IN_HS_STATE(ss, wait_server_hello)) { return SECSuccess;
} if ((ss->ssl3.cwSpec->epoch != TrafficKeyClearText) &&
(ss->ssl3.cwSpec->epoch != TrafficKeyEarlyApplicationData)) { return SECSuccess;
}
/* Install a new cipher spec for this direction. * * During the handshake, the values for |epoch| take values from the * TrafficKeyType enum. Afterwards, key update increments them.
*/ static SECStatus
tls13_SetCipherSpec(sslSocket *ss, PRUint16 epoch,
SSLSecretDirection direction, PRBool deleteSecret)
{
TrafficKeyType type;
SECStatus rv;
ssl3CipherSpec *spec = NULL;
ssl3CipherSpec **specp;
/* Flush out old handshake data. */
ssl_GetXmitBufLock(ss);
rv = ssl3_FlushHandshake(ss, ssl_SEND_FLAG_FORCE_INTO_BUFFER);
ssl_ReleaseXmitBufLock(ss); if (rv != SECSuccess) { return SECFailure;
}
/* Create the new spec. */
spec = ssl_CreateCipherSpec(ss, direction); if (!spec) { return SECFailure;
}
spec->epoch = epoch;
spec->nextSeqNum = 0; if (IS_DTLS(ss)) {
dtls_InitRecvdRecords(&spec->recvdRecords);
}
/* This depends on spec having a valid direction and epoch. */
rv = tls13_SetupPendingCipherSpec(ss, spec); if (rv != SECSuccess) { goto loser;
}
type = (TrafficKeyType)PR_MIN(TrafficKeyApplicationData, epoch);
rv = tls13_DeriveTrafficKeys(ss, spec, type, deleteSecret); if (rv != SECSuccess) { goto loser;
}
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));
/* draft-ietf-tls-tls13 Section 5.2.2 specifies the following * nonce algorithm: * * The length of the per-record nonce (iv_length) is set to max(8 bytes, * N_MIN) for the AEAD algorithm (see [RFC5116] Section 4). An AEAD * algorithm where N_MAX is less than 8 bytes MUST NOT be used with TLS. * The per-record nonce for the AEAD construction is formed as follows: * * 1. The 64-bit record sequence number is padded to the left with * zeroes to iv_length. * * 2. The padded sequence number is XORed with the static * client_write_iv or server_write_iv, depending on the role. * * The resulting quantity (of length iv_length) is used as the per- * record nonce. * * Existing suites have the same nonce size: N_MIN = N_MAX = 12 bytes * * See RFC 5288 and https://tools.ietf.org/html/draft-ietf-tls-chacha20-poly1305-04#section-2
*/ staticvoid
tls13_WriteNonce(constunsignedchar *ivIn, unsignedint ivInLen, constunsignedchar *nonce, unsignedint nonceLen, unsignedchar *ivOut, unsignedint ivOutLen)
{
size_t i; unsignedint offset = ivOutLen - nonceLen;
/* 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, but it doesn't know about the DTLS epic, so we add it here.
*/ 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 * instead of xored. We accomplish this by clearing ivOut
* 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;
}
return offset;
}
/* * Do a single AEAD for TLS. This differs from PK11_AEADOp in the following * ways. * 1) If context is not supplied, it treats the operation as a single shot * and creates a context from symKey and mech. * 2) It always assumes the tag will be at the end of the buffer * (in on decrypt, out on encrypt) just like the old single shot. * 3) If we aren't generating an IV, it uses tls13_WriteNonce to create the * nonce. * NOTE is context is supplied, symKey and mech are ignored
*/
SECStatus
tls13_AEAD(PK11Context *context, PRBool decrypt,
CK_GENERATOR_FUNCTION ivGen, unsignedint fixedbits, constunsignedchar *ivIn, unsignedchar *ivOut, unsignedint ivLen, constunsignedchar *nonceIn, unsignedint nonceLen, constunsignedchar *aad, unsignedint aadLen, unsignedchar *out, unsignedint *outLen, unsignedint maxout, unsignedint tagLen, constunsignedchar *in, unsignedint inLen)
{ unsignedchar *tag; unsignedchar iv[MAX_IV_LENGTH]; unsignedchar tagbuf[HASH_LENGTH_MAX];
SECStatus rv;
/* 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) {
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 * of the actual output buffer. This allows output buffer to be larger
* 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);
}
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;
}
hashAlg = ssl_SignatureSchemeToHashType(ss->ssl3.hs.signatureScheme);
rv = tls13_AddContextToHashes(ss, &hash, hashAlg,
PR_TRUE, &tbsHash); if (rv != SECSuccess) { return SECFailure;
}
rv = ssl3_SignHashes(ss, &tbsHash, privKey, &buf); if (rv == SECSuccess && !ss->sec.isServer) { /* Remember the info about the slot that did the signing. * Later, when doing an SSL restart handshake, verify this. * These calls are mere accessors, and can't fail.
*/
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 ssl3_SignHashes */
}
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 * tls13 CertificateVerify message * Caller must hold Handshake and RecvBuf locks.
*/
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;
SSLHashType hashAlg;
SSL3Hashes tbsHash;
SSL3Hashes hashes;
/* Set the |spki| used to verify the handshake. When verifying with a * delegated credential (DC), this corresponds to the DC public key; * otherwise it correspond to the public key of the peer's end-entity * certificate.
*/ if (tls13_IsVerifyingWithDelegatedCredential(ss)) { /* DelegatedCredential.cred.expected_cert_verify_algorithm is expected * to match CertificateVerify.scheme. * DelegatedCredential.cred.expected_cert_verify_algorithm must also be * the same as was reported in ssl3_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 * certificate to verify DelegatedCredential.signature, (2) check that * the certificate has the correct key usage, and (3) check that the DC * hasn't expired.
*/
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. * * When sending a ClientHello, we construct all the extensions with a dummy * value for the binder. To construct the binder, we commit the entire message * up to the point where the binders start. Then we calculate the hash using * the saved message (in ss->ssl3.hs.messages). This is written over the dummy
* 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 * the pre_shared_key extension is at the end of the buffer. Don't write * the binder, or the lengths that precede it (a 2 octet length for the list
* 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. This avoids an allocation and means that we don't need a
* 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. This avoids unnecessary disclosure of client credentials * to an unauthenticated server.
*/ 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;
}
/* GREASE NewSessionTicket: * When sending a NewSessionTicket message in TLS 1.3, a server MAY select * one or more GREASE extension values and advertise them as extensions
* with varying length and contents [RFC8701, SEction 4.1]. */ if (ss->opt.enableGrease) {
PR_ASSERT(ss->version >= SSL_LIBRARY_VERSION_TLS_1_3);
/* 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. * 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;
}
/* 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 * which doesn't have room for the record number. The AAD we * format is serialized record number followed by the true AD
* (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 * DTLS 1.3 (4.2.3). This will be the case until we support a cipher
* 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. * * Called by ssl3_HandleRecord. Caller must hold the spec read lock. * Therefore, we MUST not call SSL3_SendAlert(). * * If SECFailure is returned, we: * 1. Set |*alert| to the alert to be sent. * 2. Call PORT_SetError() with an appropriate code.
*/
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. * * For the inner content type as well as lower TLS versions this is checked * in ssl3con.c/ssl3_HandleNonApllicationData(). * * For DTLS 1.3 this is checked in ssl3gthr.c/dtls_GatherData(). DTLS drops * invalid records silently [RFC6347, Section 4.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 * add the specific ciphersuite expansion. * This way we detect overlong plaintexts/padding before decryption. * This check enforces size limitations more strict than the RFC.
* (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 * content type, so read from the right until we receive a
* 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;
/* Check for zero-length encrypted Alert and Handshake fragments * (zero-length + inner content type byte). * * Implementations MUST NOT send Handshake and Alert records that have a * zero-length TLSInnerPlaintext.content; if such a message is received, * the receiving implementation MUST terminate the connection with an
* "unexpected_message" alert [RFC8446, Section 5.4]. */ if (!plaintext->len && ((!IS_DTLS(ss) && cText->hdr[0] == ssl_ct_application_data) ||
(IS_DTLS(ss) && dtls_IsDtls13Ciphertext(spec->version, cText->hdr[0])))) { switch (*innerType) { case ssl_ct_alert:
*alert = unexpected_message;
PORT_SetError(SSL_ERROR_RX_MALFORMED_ALERT); return SECFailure; case ssl_ct_handshake:
*alert = unexpected_message;
PORT_SetError(SSL_ERROR_RX_MALFORMED_HANDSHAKE); return SECFailure; default: break;
}
}
/* Check that we haven't received too much 0-RTT data. */ if (spec->epoch == TrafficKeyEarlyApplicationData &&
*innerType == ssl_ct_application_data) { if (plaintext->len > spec->earlyDataRemaining) {
*alert = unexpected_message;
PORT_SetError(SSL_ERROR_TOO_MUCH_EARLY_DATA); return SECFailure;
}
spec->earlyDataRemaining -= plaintext->len;
}
SSL_TRC(10,
("%d: TLS13[%d]: %s received record of length=%d, type=%d",
SSL_GETPID(), ss->fd, SSL_ROLE(ss), plaintext->len, *innerType));
return SECSuccess;
}
/* 0-RTT is only permitted if: * * 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 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().
*/
PRBool
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) { return PR_FALSE;
} if (ss->ssl3.hs.helloRetry) { return PR_FALSE;
} if (!ss->opt.enable0RttData) { return PR_FALSE;
} if (PR_CLIST_IS_EMPTY(&ss->ssl3.hs.psks)) { return PR_FALSE;
}
sslPsk *psk = (sslPsk *)PR_LIST_HEAD(&ss->ssl3.hs.psks);
if (psk->zeroRttSuite == TLS_NULL_WITH_NULL_NULL) { return PR_FALSE;
} 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;
}
/* 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;
if (temp != tls13_EncodeVersion(SSL_LIBRARY_VERSION_TLS_1_3,
ss->protocolVariant)) { /* You cannot negotiate < TLS 1.3 with supported_versions. */
FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_SERVER_HELLO, illegal_parameter); return SECFailure;
}
/* Any endpoint receiving a Hello message with...ServerHello.legacy_version * set to 0x0300 (SSL3) MUST abort the handshake with a "protocol_version" * alert. [RFC8446, Section D.5] * * The ServerHello.legacy_version is read into the ss->version field by
* ssl_ClientReadVersion(). */ if (ss->version == SSL_LIBRARY_VERSION_3_0) {
FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_SERVER_HELLO, protocol_version); return SECFailure;
}
/* 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 * When accepting ECH, a different alert is generated.
*/
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;
}
/* GREASE ClientHello: * A client MAY select one or more GREASE extension values and * advertise them as extensions with varying length and contents
* [RFC8701, Section 3.1]. */ if (message == ssl_hs_client_hello) {
PR_ASSERT(ss->vrange.max >= SSL_LIBRARY_VERSION_TLS_1_3); /* Check if the first GREASE extension was already added. */ if (!ssl3_ExtensionAdvertised(ss, ss->ssl3.hs.grease->idx[grease_extension1])) {
*exType = ss->ssl3.hs.grease->idx[grease_extension1];
} else {
*exType = ss->ssl3.hs.grease->idx[grease_extension2];
}
} /* GREASE CertificateRequest: * When sending a CertificateRequest in TLS 1.3, a server MAY behave as * follows: A server MAY select one or more GREASE extension values and * advertise them as extensions with varying length and contents
* [RFC8701, Section 4.1]. */ elseif (message == ssl_hs_certificate_request) {
PR_ASSERT(ss->version >= SSL_LIBRARY_VERSION_TLS_1_3); /* Get random grease extension type. */
SECStatus rv = tls13_RandomGreaseValue(exType); if (rv != SECSuccess) { return SECFailure;
}
}
return SECSuccess;
}
Messung V0.5 in Prozent
¤ 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.0.208Bemerkung:
(vorverarbeitet am 2026-04-29)
¤
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.