/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * 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/. */
if (ss->vrange.max < SSL_LIBRARY_VERSION_TLS_1_3) { return SECSuccess;
}
/* Optimistically try to send an ECDHE key using the
* preexisting key (in future will be keys) */
SSL_TRC(3, ("%d: TLS13[%d]: send client key share xtn",
SSL_GETPID(), ss->fd));
/* Save the offset to the length. */
rv = sslBuffer_Skip(buf, 2, &lengthOffset); if (rv != SECSuccess) { return SECFailure;
}
/* GREASE KeyShareEntry: * [The client] MAY also send KeyShareEntry values for a subset of those * selected in the "key_share" extension. For each of these, the * "key_exchange" field MAY be any value [RFC8701, Section 3.1]. * * By default we do not send KeyShares for every NamedGroup so the * ServerKeyShare handshake message / additional round-trip is not
* triggered by sending GREASE KeyShareEntries. */ if (ss->opt.enableGrease) {
rv = sslBuffer_AppendNumber(buf, ss->ssl3.hs.grease->idx[grease_group], 2); if (rv != SECSuccess) return rv; /* Entry length */
rv = sslBuffer_AppendNumber(buf, 2, 2); if (rv != SECSuccess) return rv; /* Entry value */
rv = sslBuffer_AppendNumber(buf, 0xCD, 2); if (rv != SECSuccess) return rv;
}
/* This has to happen here because we want to consume * the entire entry even if the group is unknown
* or disabled. */ /* If the group is disabled, continue. */ if (!groupDef) { return SECSuccess;
}
return SECFailure;
} /* Handle an incoming KeyShare extension at the client and copy to * |xtnData->remoteKeyShares| for future use. The key
* share is processed in tls13_HandleServerKeyShare(). */
SECStatus
tls13_ClientHandleKeyShareXtn(const sslSocket *ss, TLSExtensionData *xtnData,
SECItem *data)
{
SECStatus rv;
PORT_Assert(PR_CLIST_IS_EMPTY(&xtnData->remoteKeyShares));
TLS13KeyShareEntry *ks = NULL;
PORT_Assert(!ss->sec.isServer);
/* The server must not send this extension when negotiating < TLS 1.3. */ if (ss->version < SSL_LIBRARY_VERSION_TLS_1_3) {
PORT_SetError(SSL_ERROR_EXTENSION_DISALLOWED_FOR_VERSION); return SECFailure;
}
group = ssl_LookupNamedGroup((SSLNamedGroup)tmp); /* If the group is not enabled, or we already have a share for the
* requested group, abort. */ if (!ssl_NamedGroupEnabled(ss, group) ||
ssl_HaveEphemeralKeyPair(ss, group)) {
ssl3_ExtSendAlert(ss, alert_fatal, illegal_parameter);
PORT_SetError(SSL_ERROR_RX_MALFORMED_HELLO_RETRY_REQUEST); return SECFailure;
}
/* Now delete all the key shares per [draft-ietf-tls-tls13 S 4.1.2] */
ssl_FreeEphemeralKeyPairs(CONST_CAST(sslSocket, ss));
/* And replace with our new share. */
rv = tls13_AddKeyShare(CONST_CAST(sslSocket, ss), group); if (rv != SECSuccess) {
ssl3_ExtSendAlert(ss, alert_fatal, internal_error);
PORT_SetError(SEC_ERROR_KEYGEN_FAIL); return SECFailure;
}
return SECSuccess;
}
/* Handle an incoming KeyShare extension at the server and copy to * |xtnData->remoteKeyShares| for future use. The key
* share is processed in tls13_HandleClientKeyShare(). */
SECStatus
tls13_ServerHandleKeyShareXtn(const sslSocket *ss, TLSExtensionData *xtnData,
SECItem *data)
{
SECStatus rv;
PRUint32 length;
/* There should be exactly one key share. */
PORT_Assert(!PR_CLIST_IS_EMPTY(&ss->ephemeralKeyPairs));
PORT_Assert(PR_PREV_LINK(&ss->ephemeralKeyPairs) ==
PR_NEXT_LINK(&ss->ephemeralKeyPairs));
/* Exit early if no PSKs or max version < 1.3. */ if (PR_CLIST_IS_EMPTY(&ss->ssl3.hs.psks) ||
ss->vrange.max < SSL_LIBRARY_VERSION_TLS_1_3) { return SECSuccess;
}
/* ...or if PSK type is resumption, but we're not resuming. */
sslPsk *psk = (sslPsk *)PR_LIST_HEAD(&ss->ssl3.hs.psks); if (psk->type == ssl_psk_resume && !ss->statelessResume) { return SECSuccess;
}
/* ...or if PSKs are incompatible with negotiated ciphersuites * (different hash algorithms) on HRR. * * In addition, in its updated ClientHello, the client SHOULD NOT offer any * pre-shared keys associated with a hash other than that of the selected * cipher suite. This allows the client to avoid having to compute partial * hash transcripts for multiple hashes in the second ClientHello
* [RFC8446, Section 4.1.4]. */ if (ss->ssl3.hs.helloRetry &&
(psk->hash != ss->ssl3.hs.suite_def->prf_hash)) { return SECSuccess;
}
/* Save where this extension starts so that if we have to add padding, it
* can be inserted before this extension. */
PORT_Assert(buf->len >= 4);
xtnData->lastXtnOffset = buf->len - 4;
PORT_Assert(psk->type == ssl_psk_resume || psk->type == ssl_psk_external);
binderLen = tls13_GetHashSizeForHash(psk->hash); if (psk->type == ssl_psk_resume) { /* Send a single ticket identity. */
NewSessionTicket *session_ticket = &ss->sec.ci.sid->u.ssl3.locked.sessionTicket;
identityLen = session_ticket->ticket.len;
identity = session_ticket->ticket.data;
/* Obfuscated age. */
age = ssl_Time(ss) - session_ticket->received_timestamp;
age /= PR_USEC_PER_MSEC;
age += session_ticket->ticket_age_add;
PRINT_BUF(50, (ss, "Sending Resumption PSK with identity", identity, identityLen));
} elseif (psk->type == ssl_psk_external) {
identityLen = psk->label.len;
identity = psk->label.data;
age = 0;
PRINT_BUF(50, (ss, "Sending External PSK with label", identity, identityLen));
} else {
PORT_Assert(0);
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); return SECFailure;
}
/* Write out the binder list length. */
rv = sslBuffer_AppendNumber(buf, binderLen + 1, 2); if (rv != SECSuccess) { goto loser;
}
/* Write zeroes for the binder for the moment. These
* are overwritten in tls13_WriteExtensionsWithBinder. */
rv = sslBuffer_AppendVariable(buf, binder, binderLen, 1); if (rv != SECSuccess) { goto loser;
}
if (psk->type == ssl_psk_resume) {
xtnData->sentSessionTicketInClientHello = PR_TRUE;
}
/* If we are doing < TLS 1.3, then ignore this. */ if (ss->version < SSL_LIBRARY_VERSION_TLS_1_3) { return SECSuccess;
}
/* The application token is set via the cookie extension if this is the * second ClientHello. Don't set it twice. The cookie extension handler * sets |helloRetry| and that will have been called already because this
* extension always comes last. */ if (!ss->ssl3.hs.helloRetry) {
appToken = &xtnData->applicationToken;
} else {
appToken = NULL;
}
if (!numIdentities) { /* Check any configured external PSK for a matching label.
* If none exists, try to parse it as a ticket. */
PORT_Assert(!xtnData->selectedPsk); for (PRCList *cur_p = PR_LIST_HEAD(&ss->ssl3.hs.psks);
cur_p != &ss->ssl3.hs.psks;
cur_p = PR_NEXT_LINK(cur_p)) {
sslPsk *psk = (sslPsk *)cur_p; if (psk->type != ssl_psk_external ||
SECITEM_CompareItem(&psk->label, &label) != SECEqual) { continue;
}
PRINT_BUF(50, (ss, "Using External PSK with label",
psk->label.data, psk->label.len));
xtnData->selectedPsk = psk;
}
if (!xtnData->selectedPsk) {
PRINT_BUF(50, (ss, "Handling PreSharedKey value",
label.data, label.len));
rv = ssl3_ProcessSessionTicketCommon( CONST_CAST(sslSocket, ss), &label, appToken); /* This only happens if we have an internal error, not * a malformed ticket. Bogus tickets just don't resume
* and return SECSuccess. */ if (rv != SECSuccess) { return SECFailure;
}
if (ss->sec.ci.sid) { /* xtnData->ticketAge contains the baseline we use for * calculating the ticket age (i.e., our RTT estimate less the * value of ticket_age_add). * * Add that to the obfuscated ticket age to recover the client's * view of the ticket age plus the estimated RTT. *
* See ssl3_EncodeSessionTicket() for details. */
xtnData->ticketAge += obfuscatedAge;
/* We are not committed to resumption until after unwrapping the * RMS in tls13_HandleClientHelloPart2. The RPSK will be stored
* in ss->xtnData.selectedPsk at that point, so continue. */
}
}
}
++numIdentities;
}
xtnData->pskBindersLen = data->len;
/* Parse the binders list. */
rv = ssl3_ExtConsumeHandshakeVariable(ss,
&inner, 2, &data->data, &data->len); if (rv != SECSuccess) return SECFailure; if (data->len) { goto alert_loser;
}
while (inner.len) {
SECItem binder;
rv = ssl3_ExtConsumeHandshakeVariable(ss, &binder, 1,
&inner.data, &inner.len); if (rv != SECSuccess) return rv; if (binder.len < 32) { goto alert_loser;
}
if (!numBinders) {
xtnData->pskBinder = binder;
}
++numBinders;
}
if (numBinders != numIdentities) goto alert_loser;
if (ss->statelessResume) {
PORT_Assert(!ss->xtnData.selectedPsk);
} elseif (!xtnData->selectedPsk) { /* No matching EPSK. */ return SECSuccess;
}
/* We only process the first session ticket the client sends,
* so the index is always 0. */
rv = sslBuffer_AppendNumber(buf, 0, 2); if (rv != SECSuccess) { return SECFailure;
}
/* The server must not send this extension when negotiating < TLS 1.3. */ if (ss->version < SSL_LIBRARY_VERSION_TLS_1_3) {
PORT_SetError(SSL_ERROR_EXTENSION_DISALLOWED_FOR_VERSION); return SECFailure;
}
/* This should be the end of the extension. */ if (data->len) {
PORT_SetError(SSL_ERROR_MALFORMED_PRE_SHARED_KEY); return SECFailure;
}
/* We only sent one PSK label so index must be equal to 0 */ if (index) {
ssl3_ExtSendAlert(ss, alert_fatal, illegal_parameter);
PORT_SetError(SSL_ERROR_MALFORMED_PRE_SHARED_KEY); return SECFailure;
}
/* This will only be called if we also offered the extension. */
SECStatus
tls13_ClientHandleEarlyDataXtn(const sslSocket *ss, TLSExtensionData *xtnData,
SECItem *data)
{
SSL_TRC(3, ("%d: TLS13[%d]: handle early_data extension",
SSL_GETPID(), ss->fd));
/* The server must not send this extension when negotiating < TLS 1.3. */ if (ss->version < SSL_LIBRARY_VERSION_TLS_1_3) {
PORT_SetError(SSL_ERROR_EXTENSION_DISALLOWED_FOR_VERSION); return SECFailure;
}
if (data->len) {
PORT_SetError(SSL_ERROR_MALFORMED_EARLY_DATA); return SECFailure;
}
/* Keep track of negotiated extensions. */
xtnData->negotiated[xtnData->numNegotiated++] = ssl_tls13_early_data_xtn;
/* The server must not send this extension when negotiating < TLS 1.3. */ if (ss->version < SSL_LIBRARY_VERSION_TLS_1_3) {
PORT_SetError(SSL_ERROR_EXTENSION_DISALLOWED_FOR_VERSION); return SECFailure;
}
if (ss->opt.enableDtls13VersionCompat &&
ss->protocolVariant == ssl_variant_datagram) { switch (version) { case SSL_LIBRARY_VERSION_TLS_1_2: case SSL_LIBRARY_VERSION_TLS_1_1:
rv = sslBuffer_AppendNumber(buf, (PRUint16)version, 2); break; default: continue;
} if (rv != SECSuccess) { return SECFailure;
}
}
}
/* GREASE SupportedVersions: * A client MAY select one or more GREASE version values and advertise them
* in the "supported_versions" extension, if sent [RFC8701, Section 3.1]. */ if (ss->opt.enableGrease) {
rv = sslBuffer_AppendNumber(buf, ss->ssl3.hs.grease->idx[grease_version], 2); if (rv != SECSuccess) { return SECFailure;
}
}
/* IMPORTANT: this is only valid while the HelloRetryRequest is still valid. */
rv = ssl3_ExtConsumeHandshakeVariable(
ss, &CONST_CAST(sslSocket, ss)->ssl3.hs.cookie, 2,
&data->data, &data->len); if (rv != SECSuccess) {
PORT_SetError(SSL_ERROR_RX_MALFORMED_HELLO_RETRY_REQUEST); return SECFailure;
} if (!ss->ssl3.hs.cookie.len || data->len) {
ssl3_ExtSendAlert(ss, alert_fatal, decode_error);
PORT_SetError(SSL_ERROR_RX_MALFORMED_HELLO_RETRY_REQUEST); return SECFailure;
}
if (data->len) {
PORT_SetError(SSL_ERROR_RX_MALFORMED_CLIENT_HELLO); return SECFailure;
}
/* Only one post-handshake message is supported: a single
* NST immediately following the client Finished. */ if (!IS_DTLS(ss)) { /* Keep track of negotiated extensions. */
xtnData->negotiated[xtnData->numNegotiated++] = ssl_tls13_post_handshake_auth_xtn;
}
/* GREASE PskKeyExchangeMode: * A client MAY select one or more GREASE PskKeyExchangeMode values and * advertise them in the "psk_key_exchange_modes" extension, if sent
* [RFC8701, Section 3.1]. */ if (ss->opt.enableGrease) {
rv = sslBuffer_AppendVariable(buf, (PRUint8[]){ tls13_psk_dh_ke, ss->ssl3.hs.grease->pskKem }, 2, 1);
} else {
rv = sslBuffer_AppendVariable(buf, (PRUint8[]){ tls13_psk_dh_ke }, 1, 1);
} if (rv != SECSuccess) { return SECFailure;
}
/* IMPORTANT: We aren't copying these values, just setting pointers.
* They will only be valid as long as the ClientHello is in memory. */
rv = ssl3_ExtConsumeHandshakeVariable(ss,
&xtnData->psk_ke_modes, 1,
&data->data, &data->len); if (rv != SECSuccess) return rv; if (!xtnData->psk_ke_modes.len || data->len) {
PORT_SetError(SSL_ERROR_MALFORMED_PSK_KEY_EXCHANGE_MODES); return SECFailure;
}
/* Keep track of negotiated extensions. */
xtnData->negotiated[xtnData->numNegotiated++] =
ssl_tls13_psk_key_exchange_modes_xtn;
/* The [retry config] response is valid only when the server used the * ClientHelloOuter. If the server sent this extension in response to the * inner variant [ECH was accepted], then the client MUST abort with an
* "unsupported_extension" alert [draft-ietf-tls-esni-14, Section 5]. */ if (ss->ssl3.hs.echAccepted) {
PORT_SetError(SSL_ERROR_RX_UNEXPECTED_EXTENSION);
ssl3_ExtSendAlert(ss, alert_fatal, unsupported_extension); return SECFailure;
}
/* If the server is configured with any ECHConfigs, it MUST include the * "encrypted_client_hello" extension in its EncryptedExtensions with the * "retry_configs" field set to one or more ECHConfig structures with
* up-to-date keys [draft-ietf-tls-esni-14, Section 7.1]. */ if (ss->ssl3.hs.msg_type != ssl_hs_encrypted_extensions) {
PORT_SetError(SSL_ERROR_RX_UNEXPECTED_EXTENSION); if (ss->version < SSL_LIBRARY_VERSION_TLS_1_3) { /* For TLS < 1.3 the extension is unkown/unsupported. */
ssl3_ExtSendAlert(ss, alert_fatal, unsupported_extension);
} else { /* For TLS 1.3 the extension is known but prohibited outside EE
* (see RFC8446, Section 4.2 for alert rationale). */
ssl3_ExtSendAlert(ss, alert_fatal, illegal_parameter);
} return SECFailure;
}
PORT_Assert(!xtnData->ech);
xtnData->ech = PORT_ZNew(sslEchXtnState); if (!xtnData->ech) { return SECFailure;
}
/* Parse the list to determine 1) That the configs are valid
* and properly encoded, and 2) If any are compatible. */
rv = tls13_DecodeEchConfigs(data, &parsedConfigs); if (rv == SECFailure) {
ssl3_ExtSendAlert(ss, alert_fatal, decode_error);
PORT_SetError(SSL_ERROR_RX_MALFORMED_ECH_CONFIG); return SECFailure;
} /* Don't mark ECH negotiated on rejection with retry_config. * Save the the raw configs so the application can retry. If
* we sent GREASE ECH (no echHpkeCtx), don't apply retry_configs. */ if (ss->ssl3.hs.echHpkeCtx && !PR_CLIST_IS_EMPTY(&parsedConfigs)) {
rv = SECITEM_CopyItem(NULL, &xtnData->ech->retryConfigs, data);
}
tls13_DestroyEchConfigs(&parsedConfigs);
return rv;
}
/* Indicates support for the delegated credentials extension. This should be
* hooked while processing the ClientHello. */
SECStatus
tls13_ClientSendDelegatedCredentialsXtn(const sslSocket *ss,
TLSExtensionData *xtnData,
sslBuffer *buf, PRBool *added)
{ /* Only send the extension if support is enabled and the client can
* negotiate TLS 1.3. */ if (ss->vrange.max < SSL_LIBRARY_VERSION_TLS_1_3 ||
!ss->opt.enableDelegatedCredentials) { return SECSuccess;
}
/* Filter the schemes that are enabled and acceptable. Save these in * the "advertised" list, then encode them to be sent. If we receive * a DC in response, validate that it matches one of the advertised
* schemes. */
SSLSignatureScheme filtered[MAX_SIGNATURE_SCHEMES] = { 0 }; unsignedint filteredCount = 0;
SECStatus rv = ssl3_FilterSigAlgs(ss, ss->vrange.max,
PR_TRUE /* disableRsae */,
PR_FALSE /* forCert */,
MAX_SIGNATURE_SCHEMES,
filtered,
&filteredCount); if (rv != SECSuccess) { return SECFailure;
}
/* If no schemes available for the DC extension, don't send it. */ if (!filteredCount) { return SECSuccess;
}
/* Parses the delegated credential (DC) offered by the server. This should be * hooked while processing the server's CertificateVerify. * * Only the DC sent with the end-entity certificate is to be parsed. This is * ensured by |tls13_HandleCertificateEntry|, which only processes extensions * for the first certificate in the chain.
*/
SECStatus
tls13_ClientHandleDelegatedCredentialsXtn(const sslSocket *ss,
TLSExtensionData *xtnData,
SECItem *data)
{ if (!ss->opt.enableDelegatedCredentials ||
ss->version < SSL_LIBRARY_VERSION_TLS_1_3) {
ssl3_ExtSendAlert(ss, alert_fatal, illegal_parameter);
PORT_SetError(SSL_ERROR_RX_UNEXPECTED_EXTENSION); return SECFailure;
}
/* When using RSA, the public key MUST NOT use the rsaEncryption OID. */ if (dc->expectedCertVerifyAlg == ssl_sig_rsa_pss_rsae_sha256 ||
dc->expectedCertVerifyAlg == ssl_sig_rsa_pss_rsae_sha384 ||
dc->expectedCertVerifyAlg == ssl_sig_rsa_pss_rsae_sha512) { goto alert_loser;
}
/* The algorithm and expected_cert_verify_algorithm fields MUST be of a * type advertised by the client in the SignatureSchemeList and are * considered invalid otherwise. Clients that receive invalid delegated * credentials MUST terminate the connection with an "illegal_parameter"
* alert. */
PRBool found = PR_FALSE; for (unsignedint i = 0; i < ss->xtnData.numDelegCredSigSchemesAdvertised; ++i) { if (dc->expectedCertVerifyAlg == ss->xtnData.delegCredSigSchemesAdvertised[i]) {
found = PR_TRUE; break;
}
} if (found == PR_FALSE) { goto alert_loser;
}
// Check the dc->alg, if necessary. if (dc->alg != dc->expectedCertVerifyAlg) {
found = PR_FALSE; for (unsignedint i = 0; i < ss->xtnData.numDelegCredSigSchemesAdvertised; ++i) { if (dc->alg == ss->xtnData.delegCredSigSchemesAdvertised[i]) {
found = PR_TRUE; break;
}
} if (found == PR_FALSE) { goto alert_loser;
}
}
/* Adds the DC extension if we're committed to authenticating with a DC. */ static SECStatus
tls13_ServerSendDelegatedCredentialsXtn(const sslSocket *ss,
TLSExtensionData *xtnData,
sslBuffer *buf, PRBool *added)
{ if (tls13_IsSigningWithDelegatedCredential(ss)) { const SECItem *dc = &ss->sec.serverCert->delegCred;
SECStatus rv;
rv = sslBuffer_Append(buf, dc->data, dc->len); if (rv != SECSuccess) { return SECFailure;
}
*added = PR_TRUE;
} return SECSuccess;
}
/* The client has indicated support of DCs. We can't act on this information * until we've committed to signing with a DC, so just set a callback for
* sending the DC extension later. */
SECStatus
tls13_ServerHandleDelegatedCredentialsXtn(const sslSocket *ss,
TLSExtensionData *xtnData,
SECItem *data)
{ if (xtnData->delegCredSigSchemes) {
PORT_Free(xtnData->delegCredSigSchemes);
xtnData->delegCredSigSchemes = NULL;
xtnData->numDelegCredSigSchemes = 0;
}
SECStatus rv = ssl_ParseSignatureSchemes(ss, NULL,
&xtnData->delegCredSigSchemes,
&xtnData->numDelegCredSigSchemes,
&data->data, &data->len); if (rv != SECSuccess) {
ssl3_ExtSendAlert(ss, alert_fatal, decode_error);
PORT_SetError(SSL_ERROR_RX_MALFORMED_CLIENT_HELLO); return SECFailure;
} if (xtnData->numDelegCredSigSchemes == 0) {
ssl3_ExtSendAlert(ss, alert_fatal, handshake_failure);
PORT_SetError(SSL_ERROR_UNSUPPORTED_SIGNATURE_ALGORITHM); return SECFailure;
} /* Check for trailing data. */ if (data->len != 0) {
ssl3_ExtSendAlert(ss, alert_fatal, decode_error);
PORT_SetError(SSL_ERROR_RX_MALFORMED_CLIENT_HELLO); return SECFailure;
}
/* If an ECH server sends the HRR ECH extension after it accepted ECH, the * extension's payload must be set to 8 zero bytes, these are overwritten with * the accept_confirmation value after the required transcript calculation. * If a client-facing/shared-mode server did not accept ECH when offered in CH * 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]. * * Depending on the acceptance of ECH, zero or random bytes are written to
* ss->ssl3.hs.greaseEchBuf.buf in tls13con.c/tls13_SendHelloRetryRequest(). */
SECStatus
tls13_ServerSendHrrEchXtn(const sslSocket *ss, TLSExtensionData *xtnData,
sslBuffer *buf, PRBool *added)
{
SECStatus rv; /* Do not send HRR ECH extension if TLS < 1.3 was negotiated OR no ECH * extension was received OR the server is NOT in any ECH server mode AND
* ECH GREASE is NOT enabled. */ if (ss->version < SSL_LIBRARY_VERSION_TLS_1_3 ||
!xtnData->ech ||
(!ss->echPubKey && !ss->opt.enableTls13BackendEch && !ss->opt.enableTls13GreaseEch)) {
SSL_TRC(100, ("%d: TLS13[%d]: server not sending HRR ECH Xtn",
SSL_GETPID(), ss->fd)); return SECSuccess;
}
SSL_TRC(100, ("%d: TLS13[%d]: server sending HRR ECH Xtn",
SSL_GETPID(), ss->fd));
PR_ASSERT(SSL_BUFFER_LEN(&ss->ssl3.hs.greaseEchBuf) == TLS13_ECH_SIGNAL_LEN);
PRINT_BUF(100, (ss, "grease_ech_confirmation", ss->ssl3.hs.greaseEchBuf.buf, TLS13_ECH_SIGNAL_LEN));
rv = sslBuffer_AppendBuffer(buf, &ss->ssl3.hs.greaseEchBuf); if (rv != SECSuccess) { return SECFailure;
}
*added = PR_TRUE; return SECSuccess;
}
/* payload, which must be final and non-empty. */
xtnData->ech->payloadStart = data->data + 2; /* Move past length */
rv = ssl3_ExtConsumeHandshakeVariable(ss, &encryptedCh, 2,
&data->data, &data->len); if (rv != SECSuccess) { goto alert_loser;
} if (data->len || !encryptedCh.len) { goto alert_loser;
}
if (!ss->ssl3.hs.helloRetry) { /* In the real ECH HRR case, config_id and enc should be empty. This
* is checked after acceptance, because it might be GREASE ECH. */ if (!senderPubKey.len) { goto alert_loser;
}
constchar *
ssl3_mapCertificateCompressionAlgorithmToName(const sslSocket *ss, SSLCertificateCompressionAlgorithmID alg)
{ for (int i = 0; i < ss->ssl3.supportedCertCompressionAlgorithmsCount; i++) { if (ss->ssl3.supportedCertCompressionAlgorithms[i].id == alg) { return ss->ssl3.supportedCertCompressionAlgorithms[i].name;
}
} return"unknown";
}
SECStatus
ssl3_HandleCertificateCompressionXtn(const sslSocket *ss,
TLSExtensionData *xtnData,
SECItem *data)
{ /* This extension is only supported with TLS 1.3 [RFC8446] and newer; * if TLS 1.2 [RFC5246] or earlier is negotiated, the peers MUST ignore this extension.
*/ if (ss->version < SSL_LIBRARY_VERSION_TLS_1_3) {
SSL_TRC(50, ("%d: TLS13[%d]: ignore certificate_compression extension",
SSL_GETPID(), ss->fd)); return SECSuccess;
}
/* Each of the algorithm is 2 bytes. */ if (lengthSupportedAlgorithms % 2 != 0) { goto alert_loser;
}
if (data->len != lengthSupportedAlgorithms) { goto alert_loser;
}
SECStatus algFound = SECFailure;
/* We use the first common algorithm we found. */ for (int i = 0; i < lengthSupportedAlgorithms / 2; i++) {
rv = ssl3_ExtConsumeHandshakeNumber(ss, &certComprAlgId, 2, &data->data, &data->len); if (rv != SECSuccess) { goto alert_loser;
}
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.