"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "nss/lib/ssl/tls13hashstate.c" between
nss-3.61.tar.gz and nss-3.62.tar.gz

About: NSS is a set of libraries, APIs, utilities, and documentation designed to support cross-platform development of security-enabled client and server applications. It provides a complete implementation of the crypto libraries used by Mozilla and other companies.

tls13hashstate.c  (nss-3.61):tls13hashstate.c  (nss-3.62)
skipping to change at line 27 skipping to change at line 27
#include "tls13hashstate.h" #include "tls13hashstate.h"
/* /*
* The cookie is structured as a self-encrypted structure with the * The cookie is structured as a self-encrypted structure with the
* inner value being. * inner value being.
* *
* struct { * struct {
* uint8 indicator = 0xff; // To disambiguate from tickets. * uint8 indicator = 0xff; // To disambiguate from tickets.
* uint16 cipherSuite; // Selected cipher suite. * uint16 cipherSuite; // Selected cipher suite.
* uint16 keyShare; // Requested key share group (0=none) * uint16 keyShare; // Requested key share group (0=none)
* HpkeKdfId kdfId; // ECH KDF (uint16)
* HpkeAeadId aeadId; // ECH AEAD (uint16)
* opaque echConfigId<0..255>; // ECH config_id
* opaque echHpkeCtx<0..65535>; // ECH serialized HPKE context
* opaque applicationToken<0..65535>; // Application token * opaque applicationToken<0..65535>; // Application token
* echConfigId<0..255>; // Encrypted Client Hello config_id
* echHrrPsk<0..255>; // Encrypted Client Hello HRR PSK
* opaque ch_hash[rest_of_buffer]; // H(ClientHello) * opaque ch_hash[rest_of_buffer]; // H(ClientHello)
* } CookieInner; * } CookieInner;
* *
* An empty echConfigId means that ECH was not offered in the first ClientHello. * An empty echConfigId means that ECH was not offered in the first ClientHello.
* An empty echHrrPsk means that ECH was not accepted in CH1. * An empty echHrrPsk means that ECH was not accepted in CH1.
*/ */
SECStatus SECStatus
tls13_MakeHrrCookie(sslSocket *ss, const sslNamedGroupDef *selectedGroup, tls13_MakeHrrCookie(sslSocket *ss, const sslNamedGroupDef *selectedGroup,
const PRUint8 *appToken, unsigned int appTokenLen, const PRUint8 *appToken, unsigned int appTokenLen,
PRUint8 *buf, unsigned int *len, unsigned int maxlen) PRUint8 *buf, unsigned int *len, unsigned int maxlen)
{ {
SECStatus rv; SECStatus rv;
SSL3Hashes hashes; SSL3Hashes hashes;
PRUint8 cookie[1024]; PRUint8 cookie[1024];
sslBuffer cookieBuf = SSL_BUFFER(cookie); sslBuffer cookieBuf = SSL_BUFFER(cookie);
static const PRUint8 indicator = 0xff; static const PRUint8 indicator = 0xff;
SECItem hrrNonceInfoItem = { siBuffer, (unsigned char *)kHpkeInfoEchHrr, SECItem *echHpkeCtx = NULL;
strlen(kHpkeInfoEchHrr) };
PK11SymKey *echHrrPsk = NULL;
SECItem *rawEchPsk = NULL;
/* Encode header. */ /* Encode header. */
rv = sslBuffer_Append(&cookieBuf, &indicator, 1); rv = sslBuffer_Append(&cookieBuf, &indicator, 1);
if (rv != SECSuccess) { if (rv != SECSuccess) {
return SECFailure; return SECFailure;
} }
rv = sslBuffer_AppendNumber(&cookieBuf, ss->ssl3.hs.cipher_suite, 2); rv = sslBuffer_AppendNumber(&cookieBuf, ss->ssl3.hs.cipher_suite, 2);
if (rv != SECSuccess) { if (rv != SECSuccess) {
return SECFailure; return SECFailure;
} }
rv = sslBuffer_AppendNumber(&cookieBuf, rv = sslBuffer_AppendNumber(&cookieBuf,
selectedGroup ? selectedGroup->name : 0, 2); selectedGroup ? selectedGroup->name : 0, 2);
if (rv != SECSuccess) { if (rv != SECSuccess) {
return SECFailure; return SECFailure;
} }
/* Application token. */ if (ss->xtnData.ech) {
rv = sslBuffer_AppendVariable(&cookieBuf, appToken, appTokenLen, 2); rv = sslBuffer_AppendNumber(&cookieBuf, ss->xtnData.ech->kdfId, 2);
if (rv != SECSuccess) {
return SECFailure;
}
/* Received ECH config_id, regardless of acceptance or possession
* of a matching ECHConfig. If rejecting ECH, this is essentially a boolean
* indicating that ECH was offered in CH1. If accepting ECH, this config_id
* will be used for the ECH decryption in CH2. */
if (ss->xtnData.echConfigId.len) {
rv = sslBuffer_AppendVariable(&cookieBuf, ss->xtnData.echConfigId.data,
ss->xtnData.echConfigId.len, 1);
} else {
PORT_Assert(!ssl3_FindExtension(ss, ssl_tls13_encrypted_client_hello_xtn
));
rv = sslBuffer_AppendNumber(&cookieBuf, 0, 1);
}
if (rv != SECSuccess) {
return SECFailure;
}
/* Extract and encode the ech-hrr-key, if ECH was accepted
* (i.e. an Open() succeeded. */
if (ss->ssl3.hs.echAccepted) {
rv = PK11_HPKE_ExportSecret(ss->ssl3.hs.echHpkeCtx, &hrrNonceInfoItem, 3
2, &echHrrPsk);
if (rv != SECSuccess) { if (rv != SECSuccess) {
return SECFailure; return SECFailure;
} }
rv = PK11_ExtractKeyValue(echHrrPsk); rv = sslBuffer_AppendNumber(&cookieBuf, ss->xtnData.ech->aeadId, 2);
if (rv != SECSuccess) { if (rv != SECSuccess) {
PK11_FreeSymKey(echHrrPsk);
return SECFailure; return SECFailure;
} }
rawEchPsk = PK11_GetKeyData(echHrrPsk);
if (!rawEchPsk) { /* Received ECH config_id, regardless of acceptance or possession
PK11_FreeSymKey(echHrrPsk); * of a matching ECHConfig. */
PORT_Assert(ss->xtnData.ech->configId.len == 8);
rv = sslBuffer_AppendVariable(&cookieBuf, ss->xtnData.ech->configId.data
,
ss->xtnData.ech->configId.len, 1);
if (rv != SECSuccess) {
return SECFailure;
}
/* There might be no HPKE Context, e.g. when we lack a matching ECHConfi
g. */
if (ss->ssl3.hs.echHpkeCtx) {
rv = PK11_HPKE_ExportContext(ss->ssl3.hs.echHpkeCtx, NULL, &echHpkeC
tx);
if (rv != SECSuccess) {
return SECFailure;
}
rv = sslBuffer_AppendVariable(&cookieBuf, echHpkeCtx->data, echHpkeC
tx->len, 2);
SECITEM_ZfreeItem(echHpkeCtx, PR_TRUE);
} else {
/* Zero length HPKE context. */
rv = sslBuffer_AppendNumber(&cookieBuf, 0, 2);
}
if (rv != SECSuccess) {
return SECFailure; return SECFailure;
} }
rv = sslBuffer_AppendVariable(&cookieBuf, rawEchPsk->data, rawEchPsk->le
n, 1);
PK11_FreeSymKey(echHrrPsk);
} else { } else {
/* Zero length ech_hrr_key. */ rv = sslBuffer_AppendNumber(&cookieBuf, 0, 7);
rv = sslBuffer_AppendNumber(&cookieBuf, 0, 1); if (rv != SECSuccess) {
return SECFailure;
}
} }
/* Application token. */
rv = sslBuffer_AppendVariable(&cookieBuf, appToken, appTokenLen, 2);
if (rv != SECSuccess) { if (rv != SECSuccess) {
return SECFailure; return SECFailure;
} }
/* Compute and encode hashes. */ /* Compute and encode hashes. */
rv = tls13_ComputeHandshakeHashes(ss, &hashes); rv = tls13_ComputeHandshakeHashes(ss, &hashes);
if (rv != SECSuccess) { if (rv != SECSuccess) {
return SECFailure; return SECFailure;
} }
rv = sslBuffer_Append(&cookieBuf, hashes.u.raw, hashes.len); rv = sslBuffer_Append(&cookieBuf, hashes.u.raw, hashes.len);
skipping to change at line 134 skipping to change at line 132
/* Encrypt right into the buffer. */ /* Encrypt right into the buffer. */
rv = ssl_SelfEncryptProtect(ss, cookieBuf.buf, cookieBuf.len, rv = ssl_SelfEncryptProtect(ss, cookieBuf.buf, cookieBuf.len,
buf, len, maxlen); buf, len, maxlen);
if (rv != SECSuccess) { if (rv != SECSuccess) {
return SECFailure; return SECFailure;
} }
return SECSuccess; 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. */
SECStatus SECStatus
tls13_RecoverHashState(sslSocket *ss, tls13_HandleHrrCookie(sslSocket *ss,
unsigned char *cookie, unsigned int cookieLen, unsigned char *cookie, unsigned int cookieLen,
ssl3CipherSuite *previousCipherSuite, ssl3CipherSuite *previousCipherSuite,
const sslNamedGroupDef **previousGroup, const sslNamedGroupDef **previousGroup,
PRBool *previousEchOffered) PRBool *previousEchOffered,
HpkeKdfId *previousEchKdfId,
HpkeAeadId *previousEchAeadId,
SECItem *previousEchConfigId,
HpkeContext **previousEchHpkeCtx,
PRBool recoverState)
{ {
SECStatus rv; SECStatus rv;
unsigned char plaintext[1024]; unsigned char plaintext[1024];
unsigned int plaintextLen = 0; unsigned int plaintextLen = 0;
sslBuffer messageBuf = SSL_BUFFER_EMPTY; sslBuffer messageBuf = SSL_BUFFER_EMPTY;
sslReadBuffer echPskBuf; sslReadBuffer echHpkeBuf = { 0 };
sslReadBuffer echConfigIdBuf; sslReadBuffer echConfigIdBuf = { 0 };
PRUint64 sentinel; PRUint64 sentinel;
PRUint64 cipherSuite; PRUint64 cipherSuite;
HpkeContext *hpkeContext = NULL;
HpkeKdfId echKdfId;
HpkeAeadId echAeadId;
PRUint64 group; PRUint64 group;
PRUint64 tmp64;
const sslNamedGroupDef *selectedGroup; const sslNamedGroupDef *selectedGroup;
PRUint64 appTokenLen; PRUint64 appTokenLen;
rv = ssl_SelfEncryptUnprotect(ss, cookie, cookieLen, rv = ssl_SelfEncryptUnprotect(ss, cookie, cookieLen,
plaintext, &plaintextLen, sizeof(plaintext)); plaintext, &plaintextLen, sizeof(plaintext));
if (rv != SECSuccess) { if (rv != SECSuccess) {
return SECFailure; return SECFailure;
} }
sslReader reader = SSL_READER(plaintext, plaintextLen); sslReader reader = SSL_READER(plaintext, plaintextLen);
skipping to change at line 183 skipping to change at line 193
} }
/* The named group, if any. */ /* The named group, if any. */
rv = sslRead_ReadNumber(&reader, 2, &group); rv = sslRead_ReadNumber(&reader, 2, &group);
if (rv != SECSuccess) { if (rv != SECSuccess) {
FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_CLIENT_HELLO, illegal_parameter); FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_CLIENT_HELLO, illegal_parameter);
return SECFailure; return SECFailure;
} }
selectedGroup = ssl_LookupNamedGroup(group); selectedGroup = ssl_LookupNamedGroup(group);
/* Application token. */ /* ECH Ciphersuite */
PORT_Assert(ss->xtnData.applicationToken.len == 0); rv = sslRead_ReadNumber(&reader, 2, &tmp64);
rv = sslRead_ReadNumber(&reader, 2, &appTokenLen);
if (rv != SECSuccess) { if (rv != SECSuccess) {
FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_CLIENT_HELLO, illegal_parameter); FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_CLIENT_HELLO, illegal_parameter);
return SECFailure; return SECFailure;
} }
if (SECITEM_AllocItem(NULL, &ss->xtnData.applicationToken, echKdfId = (HpkeKdfId)tmp64;
appTokenLen) == NULL) {
FATAL_ERROR(ss, PORT_GetError(), internal_error); rv = sslRead_ReadNumber(&reader, 2, &tmp64);
return SECFailure;
}
ss->xtnData.applicationToken.len = appTokenLen;
sslReadBuffer appTokenReader = { 0 };
rv = sslRead_Read(&reader, appTokenLen, &appTokenReader);
if (rv != SECSuccess) { if (rv != SECSuccess) {
FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_CLIENT_HELLO, illegal_parameter); FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_CLIENT_HELLO, illegal_parameter);
return SECFailure; return SECFailure;
} }
PORT_Assert(appTokenReader.len == appTokenLen); echAeadId = (HpkeAeadId)tmp64;
PORT_Memcpy(ss->xtnData.applicationToken.data, appTokenReader.buf, appTokenL
en);
/* ECH Config ID, which may be empty. */ /* ECH Config ID and HPKE context may be empty. */
rv = sslRead_ReadVariable(&reader, 1, &echConfigIdBuf); rv = sslRead_ReadVariable(&reader, 1, &echConfigIdBuf);
if (rv != SECSuccess) { if (rv != SECSuccess) {
FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_CLIENT_HELLO, illegal_parameter); FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_CLIENT_HELLO, illegal_parameter);
return SECFailure; return SECFailure;
} }
/* ECH HRR PSK, if present, is already used by tls13_GetEchInfoFromCookie */ rv = sslRead_ReadVariable(&reader, 2, &echHpkeBuf);
rv = sslRead_ReadVariable(&reader, 1, &echPskBuf);
if (rv != SECSuccess) { if (rv != SECSuccess) {
FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_CLIENT_HELLO, illegal_parameter); FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_CLIENT_HELLO, illegal_parameter);
return SECFailure; return SECFailure;
} }
/* The remainder is the hash. */ /* Application token. */
unsigned int hashLen = SSL_READER_REMAINING(&reader); rv = sslRead_ReadNumber(&reader, 2, &appTokenLen);
if (hashLen != tls13_GetHashSize(ss)) { if (rv != SECSuccess) {
FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_CLIENT_HELLO, illegal_parameter); FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_CLIENT_HELLO, illegal_parameter);
return SECFailure; return SECFailure;
} }
sslReadBuffer appTokenReader = { 0 };
/* Now reinject the message. */ rv = sslRead_Read(&reader, appTokenLen, &appTokenReader);
SSL_ASSERT_HASHES_EMPTY(ss);
rv = ssl_HashHandshakeMessageInt(ss, ssl_hs_message_hash, 0,
SSL_READER_CURRENT(&reader), hashLen,
ssl3_UpdateHandshakeHashes);
if (rv != SECSuccess) { if (rv != SECSuccess) {
FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_CLIENT_HELLO, illegal_parameter);
return SECFailure; return SECFailure;
} }
PORT_Assert(appTokenReader.len == appTokenLen);
/* And finally reinject the HRR. */ if (recoverState) {
rv = tls13_ConstructHelloRetryRequest(ss, cipherSuite, PORT_Assert(ss->xtnData.applicationToken.len == 0);
selectedGroup, if (SECITEM_AllocItem(NULL, &ss->xtnData.applicationToken,
cookie, cookieLen, appTokenLen) == NULL) {
&messageBuf); FATAL_ERROR(ss, PORT_GetError(), internal_error);
if (rv != SECSuccess) { return SECFailure;
return SECFailure; }
PORT_Memcpy(ss->xtnData.applicationToken.data, appTokenReader.buf, appTo
kenLen);
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_paramet
er);
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,
&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;
}
} }
rv = ssl_HashHandshakeMessageInt(ss, ssl_hs_server_hello, 0, if (previousEchHpkeCtx && echHpkeBuf.len) {
SSL_BUFFER_BASE(&messageBuf), const SECItem hpkeItem = { siBuffer, CONST_CAST(unsigned char, echHpkeBu
SSL_BUFFER_LEN(&messageBuf), f.buf),
ssl3_UpdateHandshakeHashes); echHpkeBuf.len };
sslBuffer_Clear(&messageBuf); hpkeContext = PK11_HPKE_ImportContext(&hpkeItem, NULL);
if (rv != SECSuccess) { if (!hpkeContext) {
return SECFailure; FATAL_ERROR(ss, PORT_GetError(), illegal_parameter);
return SECFailure;
}
}
if (previousEchConfigId && echConfigIdBuf.len) {
SECItem tmp = { siBuffer, NULL, 0 };
rv = SECITEM_MakeItem(NULL, &tmp, echConfigIdBuf.buf, echConfigIdBuf.len
);
if (rv != SECSuccess) {
PK11_HPKE_DestroyContext(hpkeContext, PR_TRUE);
FATAL_ERROR(ss, PORT_GetError(), internal_error);
return SECFailure;
}
*previousEchConfigId = tmp;
} }
*previousCipherSuite = cipherSuite; if (previousEchKdfId) {
*previousGroup = selectedGroup; *previousEchKdfId = echKdfId;
*previousEchOffered = echConfigIdBuf.len > 0; }
if (previousEchAeadId) {
*previousEchAeadId = echAeadId;
}
if (previousEchHpkeCtx) {
*previousEchHpkeCtx = hpkeContext;
}
if (previousCipherSuite) {
*previousCipherSuite = cipherSuite;
}
if (previousGroup) {
*previousGroup = selectedGroup;
}
if (previousEchOffered) {
*previousEchOffered = echConfigIdBuf.len > 0;
}
return SECSuccess; return SECSuccess;
} }
 End of changes. 27 change blocks. 
94 lines changed or deleted 161 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)