mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-19 23:07:33 +09:00
Replace NSS with Pale Moon's
This commit is contained in:
parent
ff1e5e48bf
commit
8c2e376f94
2870 changed files with 1762232 additions and 1374220 deletions
|
|
@ -12,6 +12,7 @@
|
|||
#include "sslimpl.h"
|
||||
#include "selfencrypt.h"
|
||||
#include "tls13con.h"
|
||||
#include "tls13ech.h"
|
||||
#include "tls13err.h"
|
||||
#include "tls13hashstate.h"
|
||||
|
||||
|
|
@ -23,9 +24,16 @@
|
|||
* uint8 indicator = 0xff; // To disambiguate from tickets.
|
||||
* uint16 cipherSuite; // Selected cipher suite.
|
||||
* uint16 keyShare; // Requested key share group (0=none)
|
||||
* PRUint8 echConfigId; // ECH config_id
|
||||
* HpkeKdfId kdfId; // ECH KDF (uint16)
|
||||
* HpkeAeadId aeadId; // ECH AEAD (uint16)
|
||||
* opaque echHpkeCtx<0..65535>; // ECH serialized HPKE context
|
||||
* opaque applicationToken<0..65535>; // Application token
|
||||
* opaque ch_hash[rest_of_buffer]; // H(ClientHello)
|
||||
* } CookieInner;
|
||||
*
|
||||
* An empty echConfigId means that ECH was not offered in the first ClientHello.
|
||||
* An empty echHrrPsk means that ECH was not accepted in CH1.
|
||||
*/
|
||||
SECStatus
|
||||
tls13_MakeHrrCookie(sslSocket *ss, const sslNamedGroupDef *selectedGroup,
|
||||
|
|
@ -37,6 +45,7 @@ tls13_MakeHrrCookie(sslSocket *ss, const sslNamedGroupDef *selectedGroup,
|
|||
PRUint8 cookie[1024];
|
||||
sslBuffer cookieBuf = SSL_BUFFER(cookie);
|
||||
static const PRUint8 indicator = 0xff;
|
||||
SECItem *echHpkeCtx = NULL;
|
||||
|
||||
/* Encode header. */
|
||||
rv = sslBuffer_Append(&cookieBuf, &indicator, 1);
|
||||
|
|
@ -53,6 +62,60 @@ tls13_MakeHrrCookie(sslSocket *ss, const sslNamedGroupDef *selectedGroup,
|
|||
return SECFailure;
|
||||
}
|
||||
|
||||
if (ss->xtnData.ech) {
|
||||
/* Record that we received ECH. See sslEchCookieData */
|
||||
rv = sslBuffer_AppendNumber(&cookieBuf, PR_TRUE, 1);
|
||||
if (rv != SECSuccess) {
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
rv = sslBuffer_AppendNumber(&cookieBuf, ss->xtnData.ech->configId,
|
||||
1);
|
||||
if (rv != SECSuccess) {
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
rv = sslBuffer_AppendNumber(&cookieBuf, ss->xtnData.ech->kdfId, 2);
|
||||
if (rv != SECSuccess) {
|
||||
return SECFailure;
|
||||
}
|
||||
rv = sslBuffer_AppendNumber(&cookieBuf, ss->xtnData.ech->aeadId, 2);
|
||||
if (rv != SECSuccess) {
|
||||
return SECFailure;
|
||||
}
|
||||
/* We need to send a ECH HRR Extension containing a signal for the client,
|
||||
* we must store the signal in the cookie so we can reconstruct the transcript
|
||||
* later. To avoid leaking whether ECH was accepted in the length of the cookie
|
||||
* we include the empty signal in the cookie regardless.
|
||||
*/
|
||||
PR_ASSERT(SSL_BUFFER_LEN(&ss->ssl3.hs.greaseEchBuf) == TLS13_ECH_SIGNAL_LEN);
|
||||
rv = sslBuffer_AppendBuffer(&cookieBuf, &ss->ssl3.hs.greaseEchBuf);
|
||||
if (rv != SECSuccess) {
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
/* There might be no HPKE Context, e.g. when we lack a matching ECHConfig. */
|
||||
if (ss->ssl3.hs.echHpkeCtx) {
|
||||
rv = PK11_HPKE_ExportContext(ss->ssl3.hs.echHpkeCtx, NULL, &echHpkeCtx);
|
||||
if (rv != SECSuccess) {
|
||||
return SECFailure;
|
||||
}
|
||||
rv = sslBuffer_AppendVariable(&cookieBuf, echHpkeCtx->data, echHpkeCtx->len, 2);
|
||||
SECITEM_ZfreeItem(echHpkeCtx, PR_TRUE);
|
||||
} else {
|
||||
/* Zero length HPKE context. */
|
||||
rv = sslBuffer_AppendNumber(&cookieBuf, 0, 2);
|
||||
}
|
||||
if (rv != SECSuccess) {
|
||||
return SECFailure;
|
||||
}
|
||||
} else {
|
||||
rv = sslBuffer_AppendNumber(&cookieBuf, PR_FALSE, 1);
|
||||
if (rv != SECSuccess) {
|
||||
return SECFailure;
|
||||
}
|
||||
}
|
||||
|
||||
/* Application token. */
|
||||
rv = sslBuffer_AppendVariable(&cookieBuf, appToken, appTokenLen, 2);
|
||||
if (rv != SECSuccess) {
|
||||
|
|
@ -79,34 +142,48 @@ tls13_MakeHrrCookie(sslSocket *ss, const sslNamedGroupDef *selectedGroup,
|
|||
return SECSuccess;
|
||||
}
|
||||
|
||||
/* Recover the hash state from the cookie. */
|
||||
/* Given a cookie and cookieLen, decrypt and parse, returning
|
||||
* any values that were requested via the "previous_" params. If
|
||||
* recoverState is true, the transcript state and application
|
||||
* token are restored. Note that previousEchKdfId, previousEchAeadId,
|
||||
* previousEchConfigId, and previousEchHpkeCtx are not modified if ECH was not
|
||||
* previously negotiated (i.e., previousEchOffered is PR_FALSE). */
|
||||
SECStatus
|
||||
tls13_RecoverHashState(sslSocket *ss,
|
||||
unsigned char *cookie, unsigned int cookieLen,
|
||||
ssl3CipherSuite *previousCipherSuite,
|
||||
const sslNamedGroupDef **previousGroup)
|
||||
tls13_HandleHrrCookie(sslSocket *ss,
|
||||
unsigned char *cookie, unsigned int cookieLen,
|
||||
ssl3CipherSuite *previousCipherSuite,
|
||||
const sslNamedGroupDef **previousGroup,
|
||||
PRBool *previousOfferedEch,
|
||||
sslEchCookieData *echData,
|
||||
PRBool recoverState)
|
||||
{
|
||||
SECStatus rv;
|
||||
unsigned char plaintext[1024];
|
||||
unsigned int plaintextLen = 0;
|
||||
sslBuffer messageBuf = SSL_BUFFER_EMPTY;
|
||||
sslReadBuffer echHpkeBuf = { 0 };
|
||||
PRBool receivedEch;
|
||||
PRUint64 sentinel;
|
||||
PRUint64 cipherSuite;
|
||||
sslEchCookieData parsedEchData = { 0 };
|
||||
sslReadBuffer greaseReadBuf = { 0 };
|
||||
PRUint64 group;
|
||||
PRUint64 tmp64;
|
||||
const sslNamedGroupDef *selectedGroup;
|
||||
PRUint64 appTokenLen;
|
||||
|
||||
rv = ssl_SelfEncryptUnprotect(ss, cookie, cookieLen,
|
||||
plaintext, &plaintextLen, sizeof(plaintext));
|
||||
if (rv != SECSuccess) {
|
||||
SSL_TRC(100, ("Error decrypting cookie."));
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
sslReader reader = SSL_READER(plaintext, plaintextLen);
|
||||
|
||||
/* Should start with 0xff. */
|
||||
/* Should start with the sentinel value. */
|
||||
rv = sslRead_ReadNumber(&reader, 1, &sentinel);
|
||||
if ((rv != SECSuccess) || (sentinel != 0xff)) {
|
||||
if ((rv != SECSuccess) || (sentinel != TLS13_COOKIE_SENTINEL)) {
|
||||
FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_CLIENT_HELLO, illegal_parameter);
|
||||
return SECFailure;
|
||||
}
|
||||
|
|
@ -125,19 +202,69 @@ tls13_RecoverHashState(sslSocket *ss,
|
|||
}
|
||||
selectedGroup = ssl_LookupNamedGroup(group);
|
||||
|
||||
/* Was ECH received. */
|
||||
rv = sslRead_ReadNumber(&reader, 1, &tmp64);
|
||||
if (rv != SECSuccess) {
|
||||
FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_CLIENT_HELLO, illegal_parameter);
|
||||
return SECFailure;
|
||||
}
|
||||
receivedEch = tmp64 == PR_TRUE;
|
||||
*previousOfferedEch = receivedEch;
|
||||
if (receivedEch) {
|
||||
/* ECH config ID */
|
||||
rv = sslRead_ReadNumber(&reader, 1, &tmp64);
|
||||
if (rv != SECSuccess) {
|
||||
FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_CLIENT_HELLO, illegal_parameter);
|
||||
return SECFailure;
|
||||
}
|
||||
parsedEchData.configId = (PRUint8)tmp64;
|
||||
|
||||
/* ECH Ciphersuite */
|
||||
rv = sslRead_ReadNumber(&reader, 2, &tmp64);
|
||||
if (rv != SECSuccess) {
|
||||
FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_CLIENT_HELLO, illegal_parameter);
|
||||
return SECFailure;
|
||||
}
|
||||
parsedEchData.kdfId = (HpkeKdfId)tmp64;
|
||||
|
||||
rv = sslRead_ReadNumber(&reader, 2, &tmp64);
|
||||
if (rv != SECSuccess) {
|
||||
FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_CLIENT_HELLO, illegal_parameter);
|
||||
return SECFailure;
|
||||
}
|
||||
parsedEchData.aeadId = (HpkeAeadId)tmp64;
|
||||
|
||||
/* ECH accept_confirmation signal. */
|
||||
rv = sslRead_Read(&reader, TLS13_ECH_SIGNAL_LEN, &greaseReadBuf);
|
||||
if (rv != SECSuccess) {
|
||||
FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_CLIENT_HELLO, illegal_parameter);
|
||||
return SECFailure;
|
||||
}
|
||||
PORT_Memcpy(parsedEchData.signal, greaseReadBuf.buf, TLS13_ECH_SIGNAL_LEN);
|
||||
|
||||
/* ECH HPKE context may be empty. */
|
||||
rv = sslRead_ReadVariable(&reader, 2, &echHpkeBuf);
|
||||
if (rv != SECSuccess) {
|
||||
FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_CLIENT_HELLO, illegal_parameter);
|
||||
return SECFailure;
|
||||
}
|
||||
if (echData && echHpkeBuf.len) {
|
||||
const SECItem hpkeItem = { siBuffer, CONST_CAST(unsigned char, echHpkeBuf.buf),
|
||||
echHpkeBuf.len };
|
||||
parsedEchData.hpkeCtx = PK11_HPKE_ImportContext(&hpkeItem, NULL);
|
||||
if (!parsedEchData.hpkeCtx) {
|
||||
FATAL_ERROR(ss, PORT_GetError(), illegal_parameter);
|
||||
return SECFailure;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Application token. */
|
||||
PORT_Assert(ss->xtnData.applicationToken.len == 0);
|
||||
rv = sslRead_ReadNumber(&reader, 2, &appTokenLen);
|
||||
if (rv != SECSuccess) {
|
||||
FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_CLIENT_HELLO, illegal_parameter);
|
||||
return SECFailure;
|
||||
}
|
||||
if (SECITEM_AllocItem(NULL, &ss->xtnData.applicationToken,
|
||||
appTokenLen) == NULL) {
|
||||
FATAL_ERROR(ss, PORT_GetError(), internal_error);
|
||||
return SECFailure;
|
||||
}
|
||||
ss->xtnData.applicationToken.len = appTokenLen;
|
||||
sslReadBuffer appTokenReader = { 0 };
|
||||
rv = sslRead_Read(&reader, appTokenLen, &appTokenReader);
|
||||
if (rv != SECSuccess) {
|
||||
|
|
@ -145,43 +272,61 @@ tls13_RecoverHashState(sslSocket *ss,
|
|||
return SECFailure;
|
||||
}
|
||||
PORT_Assert(appTokenReader.len == appTokenLen);
|
||||
PORT_Memcpy(ss->xtnData.applicationToken.data, appTokenReader.buf, appTokenLen);
|
||||
|
||||
/* The remainder is the hash. */
|
||||
unsigned int hashLen = SSL_READER_REMAINING(&reader);
|
||||
if (hashLen != tls13_GetHashSize(ss)) {
|
||||
FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_CLIENT_HELLO, illegal_parameter);
|
||||
return SECFailure;
|
||||
if (recoverState) {
|
||||
PORT_Assert(ss->xtnData.applicationToken.len == 0);
|
||||
if (SECITEM_AllocItem(NULL, &ss->xtnData.applicationToken,
|
||||
appTokenLen) == NULL) {
|
||||
FATAL_ERROR(ss, PORT_GetError(), internal_error);
|
||||
return SECFailure;
|
||||
}
|
||||
PORT_Memcpy(ss->xtnData.applicationToken.data, appTokenReader.buf, appTokenLen);
|
||||
ss->xtnData.applicationToken.len = appTokenLen;
|
||||
|
||||
/* The remainder is the hash. */
|
||||
unsigned int hashLen = SSL_READER_REMAINING(&reader);
|
||||
if (hashLen != tls13_GetHashSize(ss)) {
|
||||
FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_CLIENT_HELLO, illegal_parameter);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
/* Now reinject the message. */
|
||||
SSL_ASSERT_HASHES_EMPTY(ss);
|
||||
rv = ssl_HashHandshakeMessageInt(ss, ssl_hs_message_hash, 0,
|
||||
SSL_READER_CURRENT(&reader), hashLen,
|
||||
ssl3_UpdateHandshakeHashes);
|
||||
if (rv != SECSuccess) {
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
/* And finally reinject the HRR. */
|
||||
rv = tls13_ConstructHelloRetryRequest(ss, cipherSuite,
|
||||
selectedGroup,
|
||||
cookie, cookieLen,
|
||||
parsedEchData.signal,
|
||||
&messageBuf);
|
||||
if (rv != SECSuccess) {
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
rv = ssl_HashHandshakeMessageInt(ss, ssl_hs_server_hello, 0,
|
||||
SSL_BUFFER_BASE(&messageBuf),
|
||||
SSL_BUFFER_LEN(&messageBuf),
|
||||
ssl3_UpdateHandshakeHashes);
|
||||
sslBuffer_Clear(&messageBuf);
|
||||
if (rv != SECSuccess) {
|
||||
return SECFailure;
|
||||
}
|
||||
}
|
||||
|
||||
/* Now reinject the message. */
|
||||
SSL_ASSERT_HASHES_EMPTY(ss);
|
||||
rv = ssl_HashHandshakeMessageInt(ss, ssl_hs_message_hash, 0,
|
||||
SSL_READER_CURRENT(&reader), hashLen,
|
||||
ssl3_UpdateHandshakeHashes);
|
||||
if (rv != SECSuccess) {
|
||||
return SECFailure;
|
||||
if (previousCipherSuite) {
|
||||
*previousCipherSuite = cipherSuite;
|
||||
}
|
||||
|
||||
/* And finally reinject the HRR. */
|
||||
rv = tls13_ConstructHelloRetryRequest(ss, cipherSuite,
|
||||
selectedGroup,
|
||||
cookie, cookieLen,
|
||||
&messageBuf);
|
||||
if (rv != SECSuccess) {
|
||||
return SECFailure;
|
||||
if (previousGroup) {
|
||||
*previousGroup = selectedGroup;
|
||||
}
|
||||
|
||||
rv = ssl_HashHandshakeMessageInt(ss, ssl_hs_server_hello, 0,
|
||||
SSL_BUFFER_BASE(&messageBuf),
|
||||
SSL_BUFFER_LEN(&messageBuf),
|
||||
ssl3_UpdateHandshakeHashes);
|
||||
sslBuffer_Clear(&messageBuf);
|
||||
if (rv != SECSuccess) {
|
||||
return SECFailure;
|
||||
if (echData) {
|
||||
PORT_Memcpy(echData, &parsedEchData, sizeof(parsedEchData));
|
||||
}
|
||||
|
||||
*previousCipherSuite = cipherSuite;
|
||||
*previousGroup = selectedGroup;
|
||||
return SECSuccess;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue