summaryrefslogtreecommitdiffstats
path: root/security/nss/lib/ssl/tls13con.c
diff options
context:
space:
mode:
Diffstat (limited to 'security/nss/lib/ssl/tls13con.c')
-rw-r--r--security/nss/lib/ssl/tls13con.c1048
1 files changed, 672 insertions, 376 deletions
diff --git a/security/nss/lib/ssl/tls13con.c b/security/nss/lib/ssl/tls13con.c
index c3528a52f..5d51d3c5c 100644
--- a/security/nss/lib/ssl/tls13con.c
+++ b/security/nss/lib/ssl/tls13con.c
@@ -25,28 +25,11 @@
#include "tls13exthandle.h"
#include "tls13hashstate.h"
#include "tls13subcerts.h"
+#include "tls13psk.h"
static SECStatus tls13_SetCipherSpec(sslSocket *ss, PRUint16 epoch,
SSLSecretDirection install,
PRBool deleteSecret);
-static SECStatus tls13_AESGCM(const ssl3KeyMaterial *keys,
- PRBool doDecrypt,
- unsigned char *out,
- unsigned int *outlen,
- unsigned int maxout,
- const unsigned char *in,
- unsigned int inlen,
- const unsigned char *additionalData,
- unsigned int additionalDataLen);
-static SECStatus tls13_ChaCha20Poly1305(const ssl3KeyMaterial *keys,
- PRBool doDecrypt,
- unsigned char *out,
- unsigned int *outlen,
- unsigned int maxout,
- const unsigned char *in,
- unsigned int inlen,
- const unsigned char *additionalData,
- unsigned int additionalDataLen);
static SECStatus tls13_SendServerHelloSequence(sslSocket *ss);
static SECStatus tls13_SendEncryptedExtensions(sslSocket *ss);
static void tls13_SetKeyExchangeType(sslSocket *ss, const sslNamedGroupDef *group);
@@ -83,13 +66,15 @@ tls13_DeriveSecret(sslSocket *ss, PK11SymKey *key,
const char *label,
unsigned int labelLen,
const SSL3Hashes *hashes,
- PK11SymKey **dest);
+ PK11SymKey **dest,
+ SSLHashType hash);
static SECStatus tls13_SendEndOfEarlyData(sslSocket *ss);
-static SECStatus tls13_HandleEndOfEarlyData(sslSocket *ss, PRUint8 *b,
+static SECStatus tls13_HandleEndOfEarlyData(sslSocket *ss, const PRUint8 *b,
PRUint32 length);
+static SECStatus tls13_MaybeHandleSuppressedEndOfEarlyData(sslSocket *ss);
static SECStatus tls13_SendFinished(sslSocket *ss, PK11SymKey *baseKey);
static SECStatus tls13_ComputePskBinderHash(sslSocket *ss, unsigned int prefix,
- SSL3Hashes *hashes);
+ SSL3Hashes *hashes, SSLHashType type);
static SECStatus tls13_VerifyFinished(sslSocket *ss, SSLHandshakeType message,
PK11SymKey *secret,
PRUint8 *b, PRUint32 length,
@@ -103,14 +88,14 @@ static SECStatus tls13_SendNewSessionTicket(sslSocket *ss,
unsigned int appTokenLen);
static SECStatus tls13_HandleNewSessionTicket(sslSocket *ss, PRUint8 *b,
PRUint32 length);
-static SECStatus tls13_ComputeEarlySecrets(sslSocket *ss);
+static SECStatus tls13_ComputeEarlySecretsWithPsk(sslSocket *ss);
static SECStatus tls13_ComputeHandshakeSecrets(sslSocket *ss);
static SECStatus tls13_ComputeApplicationSecrets(sslSocket *ss);
static SECStatus tls13_ComputeFinalSecrets(sslSocket *ss);
static SECStatus tls13_ComputeFinished(
- sslSocket *ss, PK11SymKey *baseKey, const SSL3Hashes *hashes,
- PRBool sending, PRUint8 *output, unsigned int *outputLen,
- unsigned int maxOutputLen);
+ sslSocket *ss, PK11SymKey *baseKey, SSLHashType hashType,
+ const SSL3Hashes *hashes, PRBool sending, PRUint8 *output,
+ unsigned int *outputLen, unsigned int maxOutputLen);
static SECStatus tls13_SendClientSecondRound(sslSocket *ss);
static SECStatus tls13_SendClientSecondFlight(sslSocket *ss,
PRBool sendClientCert,
@@ -120,7 +105,8 @@ static SECStatus tls13_FinishHandshake(sslSocket *ss);
const char kHkdfLabelClient[] = "c";
const char kHkdfLabelServer[] = "s";
const char kHkdfLabelDerivedSecret[] = "derived";
-const char kHkdfLabelPskBinderKey[] = "res binder";
+const char kHkdfLabelResPskBinderKey[] = "res binder";
+const char kHkdfLabelExtPskBinderKey[] = "ext binder";
const char kHkdfLabelEarlyTrafficSecret[] = "e traffic";
const char kHkdfLabelEarlyExporterSecret[] = "e exp master";
const char kHkdfLabelHandshakeTrafficSecret[] = "hs traffic";
@@ -131,6 +117,7 @@ const char kHkdfLabelExporterMasterSecret[] = "exp master";
const char kHkdfLabelResumption[] = "resumption";
const char kHkdfLabelTrafficUpdate[] = "traffic upd";
const char kHkdfPurposeKey[] = "key";
+const char kHkdfPurposeSn[] = "sn";
const char kHkdfPurposeIv[] = "iv";
const char keylogLabelClientEarlyTrafficSecret[] = "CLIENT_EARLY_TRAFFIC_SECRET";
@@ -281,11 +268,49 @@ tls13_GetHashForCipherSuite(ssl3CipherSuite suite)
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;
}
+SECStatus
+tls13_GetHashAndCipher(PRUint16 version, PRUint16 cipherSuite,
+ SSLHashType *hash, const ssl3BulkCipherDef **cipher)
+{
+ if (version < SSL_LIBRARY_VERSION_TLS_1_3) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ }
+
+ // Lookup and check the suite.
+ SSLVersionRange vrange = { version, version };
+ if (!ssl3_CipherSuiteAllowedForVersionRange(cipherSuite, &vrange)) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ }
+ const ssl3CipherSuiteDef *suiteDef = ssl_LookupCipherSuiteDef(cipherSuite);
+ const ssl3BulkCipherDef *cipherDef = ssl_GetBulkCipherDef(suiteDef);
+ if (cipherDef->type != type_aead) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ }
+ *hash = suiteDef->prf_hash;
+ if (cipher != NULL) {
+ *cipher = cipherDef;
+ }
+ return SECSuccess;
+}
+
unsigned int
tls13_GetHashSizeForHash(SSLHashType hash)
{
@@ -306,30 +331,10 @@ tls13_GetHashSize(const sslSocket *ss)
return tls13_GetHashSizeForHash(tls13_GetHash(ss));
}
-CK_MECHANISM_TYPE
-tls13_GetHkdfMechanismForHash(SSLHashType hash)
-{
- switch (hash) {
- case ssl_hash_sha256:
- return CKM_NSS_HKDF_SHA256;
- case ssl_hash_sha384:
- return CKM_NSS_HKDF_SHA384;
- default:
- PORT_Assert(0);
- }
- return CKM_NSS_HKDF_SHA256;
-}
-
-CK_MECHANISM_TYPE
-tls13_GetHkdfMechanism(sslSocket *ss)
-{
- return tls13_GetHkdfMechanismForHash(tls13_GetHash(ss));
-}
-
static CK_MECHANISM_TYPE
-tls13_GetHmacMechanism(sslSocket *ss)
+tls13_GetHmacMechanismFromHash(SSLHashType hashType)
{
- switch (tls13_GetHash(ss)) {
+ switch (hashType) {
case ssl_hash_sha256:
return CKM_SHA256_HMAC;
case ssl_hash_sha384:
@@ -340,19 +345,25 @@ tls13_GetHmacMechanism(sslSocket *ss)
return CKM_SHA256_HMAC;
}
+static CK_MECHANISM_TYPE
+tls13_GetHmacMechanism(const sslSocket *ss)
+{
+ return tls13_GetHmacMechanismFromHash(tls13_GetHash(ss));
+}
+
SECStatus
tls13_ComputeHash(sslSocket *ss, SSL3Hashes *hashes,
- const PRUint8 *buf, unsigned int len)
+ const PRUint8 *buf, unsigned int len,
+ SSLHashType hash)
{
SECStatus rv;
- rv = PK11_HashBuf(ssl3_HashTypeToOID(tls13_GetHash(ss)),
- hashes->u.raw, buf, len);
+ rv = PK11_HashBuf(ssl3_HashTypeToOID(hash), hashes->u.raw, buf, len);
if (rv != SECSuccess) {
FATAL_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE, internal_error);
return SECFailure;
}
- hashes->len = tls13_GetHashSize(ss);
+ hashes->len = tls13_GetHashSizeForHash(hash);
return SECSuccess;
}
@@ -470,40 +481,50 @@ tls13_SetupClientHello(sslSocket *ss, sslClientHelloType chType)
return SECFailure;
}
- /* Below here checks if we can do stateless resumption. */
- if (sid->cached == never_cached ||
- sid->version < SSL_LIBRARY_VERSION_TLS_1_3) {
- return SECSuccess;
- }
+ /* 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);
- /* 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;
+ }
- if (ssl_TicketTimeValid(ss, session_ticket)) {
- ss->statelessResume = PR_TRUE;
- }
+ if (ss->statelessResume) {
+ PORT_Assert(ss->sec.ci.sid);
+ rv = tls13_RecoverWrappedSharedSecret(ss, ss->sec.ci.sid);
+ if (rv != SECSuccess) {
+ FATAL_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE, internal_error);
+ SSL_AtomicIncrementLong(&ssl3stats->sch_sid_cache_not_ok);
+ ssl_UncacheSessionID(ss);
+ ssl_FreeSID(ss->sec.ci.sid);
+ ss->sec.ci.sid = NULL;
+ return SECFailure;
+ }
- if (ss->statelessResume) {
- PORT_Assert(ss->sec.ci.sid);
- rv = tls13_RecoverWrappedSharedSecret(ss, ss->sec.ci.sid);
- if (rv != SECSuccess) {
- FATAL_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE, internal_error);
- SSL_AtomicIncrementLong(&ssl3stats->sch_sid_cache_not_ok);
- ssl_UncacheSessionID(ss);
- ssl_FreeSID(ss->sec.ci.sid);
- ss->sec.ci.sid = NULL;
- return SECFailure;
+ ss->ssl3.hs.cipher_suite = ss->sec.ci.sid->u.ssl3.cipherSuite;
+ rv = ssl3_SetupCipherSuite(ss, PR_FALSE);
+ if (rv != SECSuccess) {
+ FATAL_ERROR(ss, PORT_GetError(), internal_error);
+ return SECFailure;
+ }
+ PORT_Assert(!PR_CLIST_IS_EMPTY(&ss->ssl3.hs.psks));
}
+ }
- ss->ssl3.hs.cipher_suite = ss->sec.ci.sid->u.ssl3.cipherSuite;
- rv = ssl3_SetupCipherSuite(ss, PR_FALSE);
- if (rv != SECSuccess) {
- FATAL_ERROR(ss, PORT_GetError(), internal_error);
- return SECFailure;
+ /* 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;
}
- rv = tls13_ComputeEarlySecrets(ss);
+ rv = tls13_ComputeEarlySecretsWithPsk(ss);
if (rv != SECSuccess) {
FATAL_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE, internal_error);
return SECFailure;
@@ -595,7 +616,7 @@ tls13_HandleKeyShare(sslSocket *ss,
key = PK11_PubDeriveWithKDF(
keyPair->privKey, peerKey, PR_FALSE, NULL, NULL, mechanism,
- tls13_GetHkdfMechanismForHash(hash), CKA_DERIVE, keySize, CKD_NULL, NULL, NULL);
+ CKM_HKDF_DERIVE, CKA_DERIVE, keySize, CKD_NULL, NULL, NULL);
if (!key) {
ssl_MapLowLevelError(SSL_ERROR_KEY_EXCHANGE_FAILURE);
goto loser;
@@ -641,6 +662,7 @@ tls13_UpdateTrafficKeys(sslSocket *ss, SSLSecretDirection direction)
strlen(kHkdfLabelTrafficUpdate),
tls13_GetHmacMechanism(ss),
tls13_GetHashSize(ss),
+ ss->protocolVariant,
&updatedSecret);
if (rv != SECSuccess) {
return SECFailure;
@@ -884,6 +906,12 @@ SSLExp_SendCertificateRequest(PRFileDesc *fd)
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;
+ }
+
rv = TLS13_CHECK_HS_STATE(ss, SEC_ERROR_INVALID_ARGS,
idle_handshake);
if (rv != SECSuccess) {
@@ -997,20 +1025,34 @@ tls13_RecoverWrappedSharedSecret(sslSocket *ss, sslSessionID *sid)
wrappedMS.data = sid->u.ssl3.keys.wrapped_master_secret;
wrappedMS.len = sid->u.ssl3.keys.wrapped_master_secret_len;
- /* unwrap the "master secret" which is actually RMS. */
- ss->ssl3.hs.resumptionMasterSecret = ssl_unwrapSymKey(
- wrapKey, sid->u.ssl3.masterWrapMech,
- NULL, &wrappedMS,
- CKM_SSL3_MASTER_KEY_DERIVE,
- CKA_DERIVE,
- tls13_GetHashSizeForHash(hashType),
- CKF_SIGN | CKF_VERIFY, ss->pkcs11PinArg);
+ PK11SymKey *unwrappedPsk = ssl_unwrapSymKey(wrapKey, sid->u.ssl3.masterWrapMech,
+ NULL, &wrappedMS, CKM_SSL3_MASTER_KEY_DERIVE,
+ CKA_DERIVE, tls13_GetHashSizeForHash(hashType),
+ CKF_SIGN | CKF_VERIFY, ss->pkcs11PinArg);
PK11_FreeSymKey(wrapKey);
- if (!ss->ssl3.hs.resumptionMasterSecret) {
+ if (!unwrappedPsk) {
return SECFailure;
}
+ sslPsk *rpsk = tls13_MakePsk(unwrappedPsk, ssl_psk_resume, hashType, NULL);
+ if (!rpsk) {
+ PK11_FreeSymKey(unwrappedPsk);
+ return SECFailure;
+ }
+ if (sid->u.ssl3.locked.sessionTicket.flags & ticket_allow_early_data) {
+ rpsk->maxEarlyData = sid->u.ssl3.locked.sessionTicket.max_early_data_size;
+ rpsk->zeroRttSuite = sid->u.ssl3.cipherSuite;
+ }
+ PRINT_KEY(50, (ss, "Recovered RMS", rpsk->key));
+ PORT_Assert(PR_CLIST_IS_EMPTY(&ss->ssl3.hs.psks) ||
+ ((sslPsk *)PR_LIST_HEAD(&ss->ssl3.hs.psks))->type != ssl_psk_resume);
- PRINT_KEY(50, (ss, "Recovered RMS", ss->ssl3.hs.resumptionMasterSecret));
+ 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);
return SECSuccess;
}
@@ -1068,38 +1110,45 @@ tls13_RecoverWrappedSharedSecret(sslSocket *ss, sslSessionID *sid)
* = resumption_master_secret
*
*/
-
static SECStatus
-tls13_ComputeEarlySecrets(sslSocket *ss)
+tls13_ComputeEarlySecretsWithPsk(sslSocket *ss)
{
- SECStatus rv = SECSuccess;
+ SECStatus rv;
SSL_TRC(5, ("%d: TLS13[%d]: compute early secrets (%s)",
SSL_GETPID(), ss->fd, SSL_ROLE(ss)));
- /* Extract off the resumptionMasterSecret (if present), else pass the NULL
- * resumptionMasterSecret which will be internally translated to zeroes. */
PORT_Assert(!ss->ssl3.hs.currentSecret);
- rv = tls13_HkdfExtract(NULL, ss->ssl3.hs.resumptionMasterSecret,
- tls13_GetHash(ss), &ss->ssl3.hs.currentSecret);
+ sslPsk *psk = NULL;
+
+ 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);
+
+ PK11SymKey *earlySecret = NULL;
+ rv = tls13_HkdfExtract(NULL, psk->key, psk->hash, &earlySecret);
if (rv != SECSuccess) {
return SECFailure;
}
- PORT_Assert(ss->statelessResume == (ss->ssl3.hs.resumptionMasterSecret != NULL));
- if (ss->statelessResume) {
- PK11_FreeSymKey(ss->ssl3.hs.resumptionMasterSecret);
- ss->ssl3.hs.resumptionMasterSecret = NULL;
-
- rv = tls13_DeriveSecretNullHash(ss, ss->ssl3.hs.currentSecret,
- kHkdfLabelPskBinderKey,
- strlen(kHkdfLabelPskBinderKey),
- &ss->ssl3.hs.pskBinderKey);
- if (rv != SECSuccess) {
- return SECFailure;
- }
+ /* No longer need the raw input key */
+ PK11_FreeSymKey(psk->key);
+ psk->key = NULL;
+ const char *label = (psk->type == ssl_psk_resume) ? kHkdfLabelResPskBinderKey : kHkdfLabelExtPskBinderKey;
+ rv = tls13_DeriveSecretNullHash(ss, earlySecret,
+ label, strlen(label),
+ &psk->binderKey, psk->hash);
+ if (rv != SECSuccess) {
+ PK11_FreeSymKey(earlySecret);
+ return SECFailure;
}
- PORT_Assert(!ss->ssl3.hs.resumptionMasterSecret);
+ ss->ssl3.hs.currentSecret = earlySecret;
return SECSuccess;
}
@@ -1109,7 +1158,7 @@ static SECStatus
tls13_DeriveEarlySecrets(sslSocket *ss)
{
SECStatus rv;
-
+ PORT_Assert(ss->ssl3.hs.currentSecret);
rv = tls13_DeriveSecretWrap(ss, ss->ssl3.hs.currentSecret,
kHkdfLabelClient,
kHkdfLabelEarlyTrafficSecret,
@@ -1147,7 +1196,15 @@ tls13_ComputeHandshakeSecrets(sslSocket *ss)
SSL_TRC(5, ("%d: TLS13[%d]: compute handshake secrets (%s)",
SSL_GETPID(), ss->fd, SSL_ROLE(ss)));
- /* First update |currentSecret| to add |dheSecret|, if any. */
+ /* If no PSK, generate the default early secret. */
+ if (!ss->ssl3.hs.currentSecret) {
+ PORT_Assert(!ss->xtnData.selectedPsk);
+ rv = tls13_HkdfExtract(NULL, NULL,
+ tls13_GetHash(ss), &ss->ssl3.hs.currentSecret);
+ if (rv != SECSuccess) {
+ return SECFailure;
+ }
+ }
PORT_Assert(ss->ssl3.hs.currentSecret);
PORT_Assert(ss->ssl3.hs.dheSecret);
@@ -1155,7 +1212,7 @@ tls13_ComputeHandshakeSecrets(sslSocket *ss)
rv = tls13_DeriveSecretNullHash(ss, ss->ssl3.hs.currentSecret,
kHkdfLabelDerivedSecret,
strlen(kHkdfLabelDerivedSecret),
- &derivedSecret);
+ &derivedSecret, tls13_GetHash(ss));
if (rv != SECSuccess) {
LOG_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE);
return rv;
@@ -1214,7 +1271,7 @@ tls13_ComputeHandshakeSecrets(sslSocket *ss)
rv = tls13_DeriveSecretNullHash(ss, ss->ssl3.hs.currentSecret,
kHkdfLabelDerivedSecret,
strlen(kHkdfLabelDerivedSecret),
- &derivedSecret);
+ &derivedSecret, tls13_GetHash(ss));
if (rv != SECSuccess) {
LOG_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE);
return rv;
@@ -1286,7 +1343,7 @@ tls13_ComputeFinalSecrets(sslSocket *ss)
PORT_Assert(!ss->ssl3.crSpec->masterSecret);
PORT_Assert(!ss->ssl3.cwSpec->masterSecret);
-
+ PORT_Assert(ss->ssl3.hs.currentSecret);
rv = tls13_DeriveSecretWrap(ss, ss->ssl3.hs.currentSecret,
NULL, kHkdfLabelResumptionMasterSecret,
NULL,
@@ -1327,7 +1384,14 @@ tls13_CanResume(sslSocket *ss, const sslSessionID *sid)
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;
}
@@ -1347,21 +1411,40 @@ static PRBool
tls13_CanNegotiateZeroRtt(sslSocket *ss, const sslSessionID *sid)
{
PORT_Assert(ss->ssl3.hs.zeroRttState == ssl_0rtt_sent);
+ sslPsk *psk = ss->xtnData.selectedPsk;
- if (!sid)
+ if (!ss->opt.enable0RttData) {
return PR_FALSE;
- PORT_Assert(ss->statelessResume);
- if (!ss->statelessResume)
+ }
+ if (!psk) {
return PR_FALSE;
- if (ss->ssl3.hs.cipher_suite != sid->u.ssl3.cipherSuite)
+ }
+ if (psk->zeroRttSuite == TLS_NULL_WITH_NULL_NULL) {
return PR_FALSE;
- if (!ss->opt.enable0RttData)
+ }
+ if (!psk->maxEarlyData) {
return PR_FALSE;
- if (!(sid->u.ssl3.locked.sessionTicket.flags & ticket_allow_early_data))
+ }
+ if (ss->ssl3.hs.cipher_suite != psk->zeroRttSuite) {
return PR_FALSE;
- if (SECITEM_CompareItem(&ss->xtnData.nextProto,
- &sid->u.ssl3.alpnSelection) != 0)
+ }
+ 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;
+ }
+ } else if (psk->type != ssl_psk_external) {
+ PORT_Assert(0);
return PR_FALSE;
+ }
if (tls13_IsReplay(ss, sid)) {
return PR_FALSE;
@@ -1414,7 +1497,7 @@ tls13_NegotiateZeroRtt(sslSocket *ss, const sslSessionID *sid)
}
SSL_TRC(3, ("%d: TLS13[%d]: enable 0-RTT", SSL_GETPID(), ss->fd));
- PORT_Assert(ss->statelessResume);
+ PORT_Assert(ss->xtnData.selectedPsk);
ss->ssl3.hs.zeroRttState = ssl_0rtt_accepted;
ss->ssl3.hs.zeroRttIgnore = ssl_0rtt_ignore_none;
ss->ssl3.hs.zeroRttSuite = ss->ssl3.hs.cipher_suite;
@@ -1466,7 +1549,7 @@ tls13_NegotiateKeyExchange(sslSocket *ss,
const sslNamedGroupDef *preferredGroup = NULL;
/* We insist on DHE. */
- if (ss->statelessResume) {
+ 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);
@@ -1490,8 +1573,8 @@ tls13_NegotiateKeyExchange(sslSocket *ss,
return SECFailure;
}
- SSL_TRC(3, ("%d: TLS13[%d]: selected KE = %s",
- SSL_GETPID(), ss->fd, ss->statelessResume ? "PSK + (EC)DHE" : "(EC)DHE"));
+ SSL_TRC(3, ("%d: TLS13[%d]: selected KE = %s", SSL_GETPID(),
+ ss->fd, ss->statelessResume || ss->xtnData.selectedPsk ? "PSK + (EC)DHE" : "(EC)DHE"));
/* Find the preferred group and an according client key share available. */
for (index = 0; index < SSL_NAMED_GROUP_COUNT; ++index) {
@@ -1679,26 +1762,42 @@ tls13_MaybeSendHelloRetry(sslSocket *ss, const sslNamedGroupDef *requestedGroup,
static SECStatus
tls13_NegotiateAuthentication(sslSocket *ss)
{
- SECStatus rv;
-
if (ss->statelessResume) {
- SSL_TRC(3, ("%d: TLS13[%d]: selected PSK authentication",
+ 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;
+ } else if (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));
- /* We've now established that we need to sign.... */
- rv = tls13_SelectServerCert(ss);
+ 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. */
@@ -1862,40 +1961,51 @@ tls13_HandleClientHelloPart2(sslSocket *ss,
goto loser;
}
- 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;
- }
+ 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;
+ }
- ss->sec.serverCert = ssl_FindServerCert(ss, sid->authType,
- sid->namedCurve);
- PORT_Assert(ss->sec.serverCert);
+ ss->sec.serverCert = ssl_FindServerCert(ss, sid->authType,
+ sid->namedCurve);
+ PORT_Assert(ss->sec.serverCert);
- rv = tls13_RecoverWrappedSharedSecret(ss, sid);
- if (rv != SECSuccess) {
- SSL_AtomicIncrementLong(&ssl3stats->hch_sid_cache_not_ok);
- FATAL_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE, internal_error);
- goto loser;
- }
- tls13_RestoreCipherInfo(ss, sid);
+ rv = tls13_RecoverWrappedSharedSecret(ss, sid);
+ if (rv != SECSuccess) {
+ SSL_AtomicIncrementLong(&ssl3stats->hch_sid_cache_not_ok);
+ FATAL_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE, internal_error);
+ goto loser;
+ }
+ tls13_RestoreCipherInfo(ss, sid);
- ss->sec.localCert = CERT_DupCertificate(ss->sec.serverCert->serverCert);
- if (sid->peerCert != NULL) {
- ss->sec.peerCert = CERT_DupCertificate(sid->peerCert);
+ ss->sec.localCert = CERT_DupCertificate(ss->sec.serverCert->serverCert);
+ if (sid->peerCert != NULL) {
+ ss->sec.peerCert = CERT_DupCertificate(sid->peerCert);
+ }
+ } else if (sid) {
+ /* We should never have a SID in the non-resumption case. */
+ PORT_Assert(0);
+ ssl_UncacheSessionID(ss);
+ ssl_FreeSID(sid);
+ sid = NULL;
}
-
ssl3_RegisterExtensionSender(
ss, &ss->xtnData,
ssl_tls13_pre_shared_key_xtn, tls13_ServerSendPreSharedKeyXtn);
-
tls13_NegotiateZeroRtt(ss, sid);
+
+ rv = tls13_ComputeEarlySecretsWithPsk(ss);
+ if (rv != SECSuccess) {
+ FATAL_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE, internal_error);
+ return SECFailure;
+ }
} else {
if (sid) { /* we had a sid, but it's no longer valid, free it */
SSL_AtomicIncrementLong(&ssl3stats->hch_sid_cache_not_ok);
@@ -1906,35 +2016,34 @@ tls13_HandleClientHelloPart2(sslSocket *ss,
tls13_NegotiateZeroRtt(ss, NULL);
}
- /* Need to compute early secrets. */
- rv = tls13_ComputeEarlySecrets(ss);
- if (rv != SECSuccess) {
- FATAL_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE, internal_error);
- return SECFailure;
+ if (ss->statelessResume) {
+ PORT_Assert(ss->xtnData.selectedPsk);
+ PORT_Assert(ss->ssl3.hs.kea_def_mutable.authKeyType == ssl_auth_psk);
}
- /* Now that we have the binder key check the binder. */
- if (ss->statelessResume) {
+ /* Now that we have the binder key, check the binder. */
+ if (ss->xtnData.selectedPsk) {
SSL3Hashes hashes;
-
PORT_Assert(ss->ssl3.hs.messages.len > ss->xtnData.pskBindersLen);
rv = tls13_ComputePskBinderHash(
ss,
ss->ssl3.hs.messages.len - ss->xtnData.pskBindersLen,
- &hashes);
+ &hashes, tls13_GetHash(ss));
if (rv != SECSuccess) {
FATAL_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE, internal_error);
goto loser;
}
+ PORT_Assert(ss->xtnData.selectedPsk->hash == tls13_GetHash(ss));
+ PORT_Assert(ss->ssl3.hs.suite_def);
rv = tls13_VerifyFinished(ss, ssl_hs_client_hello,
- ss->ssl3.hs.pskBinderKey,
+ ss->xtnData.selectedPsk->binderKey,
ss->xtnData.pskBinder.data,
ss->xtnData.pskBinder.len,
&hashes);
- if (rv != SECSuccess) {
- goto loser;
- }
+ }
+ if (rv != SECSuccess) {
+ goto loser;
}
/* This needs to go after we verify the psk binder. */
@@ -1961,7 +2070,7 @@ tls13_HandleClientHelloPart2(sslSocket *ss,
SSL_AtomicIncrementLong(&ssl3stats->hch_sid_cache_not_ok);
ssl_UncacheSessionID(ss);
ssl_FreeSID(sid);
- } else {
+ } else if (!ss->xtnData.selectedPsk) {
SSL_AtomicIncrementLong(&ssl3stats->hch_sid_cache_misses);
}
@@ -1991,6 +2100,10 @@ tls13_HandleClientHelloPart2(sslSocket *ss,
return SECFailure;
}
+ /* We're done with PSKs */
+ tls13_DestroyPskList(&ss->ssl3.hs.psks);
+ ss->xtnData.selectedPsk = NULL;
+
return SECSuccess;
loser:
@@ -2322,7 +2435,8 @@ tls13_ReinjectHandshakeTranscript(sslSocket *ss)
// First compute the hash.
rv = tls13_ComputeHash(ss, &hashes,
ss->ssl3.hs.messages.buf,
- ss->ssl3.hs.messages.len);
+ ss->ssl3.hs.messages.len,
+ tls13_GetHash(ss));
if (rv != SECSuccess) {
return SECFailure;
}
@@ -2339,7 +2453,6 @@ tls13_ReinjectHandshakeTranscript(sslSocket *ss)
return SECSuccess;
}
-
static unsigned int
ssl_ListCount(PRCList *list)
{
@@ -2462,6 +2575,12 @@ tls13_HandleCertificateRequest(sslSocket *ss, PRUint8 *b, PRUint32 length)
return SECFailure;
}
+ /* MUST NOT combine external PSKs with certificate authentication. */
+ if (ss->sec.authType == ssl_auth_psk) {
+ FATAL_ERROR(ss, SSL_ERROR_RX_UNEXPECTED_CERT_REQUEST, unexpected_message);
+ return SECFailure;
+ }
+
if (tls13_IsPostHandshake(ss)) {
PORT_Assert(ss->ssl3.hs.shaPostHandshake == NULL);
ss->ssl3.hs.shaPostHandshake = PK11_CloneContext(ss->ssl3.hs.sha);
@@ -2577,6 +2696,8 @@ tls13_HandleCertificateRequest(sslSocket *ss, PRUint8 *b, PRUint32 length)
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;
}
@@ -2745,7 +2866,9 @@ tls13_SendServerHelloSequence(sslSocket *ss)
}
}
- ss->ssl3.hs.serverHelloTime = ssl_Time(ss);
+ /* 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;
}
@@ -2757,14 +2880,22 @@ tls13_HandleServerHelloPart2(sslSocket *ss)
SSL3Statistics *ssl3stats = SSL_GetStatistics();
if (ssl3_ExtensionNegotiated(ss, ssl_tls13_pre_shared_key_xtn)) {
- PORT_Assert(ss->statelessResume);
+ 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) {
- PORT_Assert(ss->statelessResume);
+ PORT_Assert(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) {
@@ -2781,19 +2912,22 @@ tls13_HandleServerHelloPart2(sslSocket *ss)
ss->ssl3.hs.kea_def_mutable = *ss->ssl3.hs.kea_def;
ss->ssl3.hs.kea_def = &ss->ssl3.hs.kea_def_mutable;
- if (ss->statelessResume) {
- /* PSK */
+ if (ss->xtnData.selectedPsk) {
ss->ssl3.hs.kea_def_mutable.authKeyType = ssl_auth_psk;
- tls13_RestoreCipherInfo(ss, sid);
- if (sid->peerCert) {
- ss->sec.peerCert = CERT_DupCertificate(sid->peerCert);
- }
+ 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);
+ SSL_AtomicIncrementLong(&ssl3stats->hsh_sid_cache_hits);
+ SSL_AtomicIncrementLong(&ssl3stats->hsh_sid_stateless_resumes);
+ } else {
+ ss->sec.authType = ssl_auth_psk;
+ }
} else {
- /* !PSK */
- if (ssl3_ExtensionAdvertised(ss, ssl_tls13_pre_shared_key_xtn)) {
+ 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) {
@@ -2802,18 +2936,6 @@ tls13_HandleServerHelloPart2(sslSocket *ss)
}
}
- if (!ss->ssl3.hs.currentSecret) {
- PORT_Assert(!ss->statelessResume);
-
- /* If we don't already have the Early Secret we need to make it
- * now. */
- rv = tls13_ComputeEarlySecrets(ss);
- if (rv != SECSuccess) {
- FATAL_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE, internal_error);
- return SECFailure;
- }
- }
-
/* Discard current SID and make a new one, though it may eventually
* end up looking a lot like the old one.
*/
@@ -3113,6 +3235,13 @@ tls13_HandleCertificate(sslSocket *ss, PRUint8 *b, PRUint32 length)
PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
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. */
+ }
+
if (ss->ssl3.clientCertRequested) {
rv = TLS13_CHECK_HS_STATE(ss, SSL_ERROR_RX_UNEXPECTED_CERTIFICATE,
idle_handshake);
@@ -3124,8 +3253,9 @@ tls13_HandleCertificate(sslSocket *ss, PRUint8 *b, PRUint32 length)
rv = TLS13_CHECK_HS_STATE(ss, SSL_ERROR_RX_UNEXPECTED_CERTIFICATE,
wait_cert_request, wait_server_cert);
}
- if (rv != SECSuccess)
+ if (rv != SECSuccess) {
return SECFailure;
+ }
/* We can ignore any other cleartext from the client. */
if (ss->sec.isServer && IS_DTLS(ss)) {
@@ -3139,6 +3269,11 @@ tls13_HandleCertificate(sslSocket *ss, PRUint8 *b, PRUint32 length)
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
return SECFailure;
}
+ } else if (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 */
@@ -3310,15 +3445,15 @@ tls13_DeriveSecret(sslSocket *ss, PK11SymKey *key,
const char *label,
unsigned int labelLen,
const SSL3Hashes *hashes,
- PK11SymKey **dest)
+ PK11SymKey **dest,
+ SSLHashType hash)
{
SECStatus rv;
- rv = tls13_HkdfExpandLabel(key, tls13_GetHash(ss),
- hashes->u.raw, hashes->len,
- label, labelLen,
- tls13_GetHkdfMechanism(ss),
- tls13_GetHashSize(ss), dest);
+ rv = tls13_HkdfExpandLabel(key, hash, hashes->u.raw, hashes->len,
+ label, labelLen, CKM_HKDF_DERIVE,
+ tls13_GetHashSizeForHash(hash),
+ ss->protocolVariant, dest);
if (rv != SECSuccess) {
LOG_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE);
return SECFailure;
@@ -3331,18 +3466,19 @@ SECStatus
tls13_DeriveSecretNullHash(sslSocket *ss, PK11SymKey *key,
const char *label,
unsigned int labelLen,
- PK11SymKey **dest)
+ PK11SymKey **dest,
+ SSLHashType hash)
{
SSL3Hashes hashes;
SECStatus rv;
PRUint8 buf[] = { 0 };
- rv = tls13_ComputeHash(ss, &hashes, buf, 0);
+ rv = tls13_ComputeHash(ss, &hashes, buf, 0, hash);
if (rv != SECSuccess) {
return SECFailure;
}
- return tls13_DeriveSecret(ss, key, label, labelLen, &hashes, dest);
+ return tls13_DeriveSecret(ss, key, label, labelLen, &hashes, dest, hash);
}
/* Convenience wrapper that lets us supply a separate prefix and suffix. */
@@ -3381,7 +3517,7 @@ tls13_DeriveSecretWrap(sslSocket *ss, PK11SymKey *key,
}
rv = tls13_DeriveSecret(ss, key, label, strlen(label),
- &hashes, dest);
+ &hashes, dest, tls13_GetHash(ss));
if (rv != SECSuccess) {
return SECFailure;
}
@@ -3467,6 +3603,7 @@ tls13_DeriveTrafficKeys(sslSocket *ss, ssl3CipherSpec *spec,
NULL, 0,
kHkdfPurposeKey, strlen(kHkdfPurposeKey),
bulkAlgorithm, keySize,
+ ss->protocolVariant,
&spec->keyMaterial.key);
if (rv != SECSuccess) {
LOG_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE);
@@ -3474,9 +3611,21 @@ tls13_DeriveTrafficKeys(sslSocket *ss, ssl3CipherSpec *spec,
goto loser;
}
+ if (IS_DTLS(ss) && spec->epoch > 0) {
+ rv = ssl_CreateMaskingContextInner(spec->version, ss->ssl3.hs.cipher_suite,
+ ss->protocolVariant, prk, kHkdfPurposeSn,
+ strlen(kHkdfPurposeSn), &spec->maskContext);
+ if (rv != SECSuccess) {
+ LOG_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE);
+ PORT_Assert(0);
+ goto loser;
+ }
+ }
+
rv = tls13_HkdfExpandLabelRaw(prk, tls13_GetHash(ss),
NULL, 0,
kHkdfPurposeIv, strlen(kHkdfPurposeIv),
+ ss->protocolVariant,
spec->keyMaterial.iv, ivSize);
if (rv != SECSuccess) {
LOG_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE);
@@ -3507,21 +3656,6 @@ tls13_SetSpecRecordVersion(sslSocket *ss, ssl3CipherSpec *spec)
SSL_GETPID(), ss->fd, spec, spec->recordVersion));
}
-SSLAEADCipher
-tls13_GetAead(const ssl3BulkCipherDef *cipherDef)
-{
- switch (cipherDef->calg) {
- case ssl_calg_aes_gcm:
- return tls13_AESGCM;
- case ssl_calg_chacha20:
- return tls13_ChaCha20Poly1305;
- default:
- PORT_Assert(PR_FALSE);
- PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
- return NULL;
- }
-}
-
static SECStatus
tls13_SetupPendingCipherSpec(sslSocket *ss, ssl3CipherSpec *spec)
{
@@ -3545,14 +3679,12 @@ tls13_SetupPendingCipherSpec(sslSocket *ss, ssl3CipherSpec *spec)
SSL_GETPID(), ss->fd, suite));
spec->cipherDef = ssl_GetBulkCipherDef(ssl_LookupCipherSuiteDef(suite));
- spec->aead = tls13_GetAead(spec->cipherDef);
- if (!spec->aead) {
- return SECFailure;
- }
if (spec->epoch == TrafficKeyEarlyApplicationData) {
- spec->earlyDataRemaining =
- ss->sec.ci.sid->u.ssl3.locked.sessionTicket.max_early_data_size;
+ if (ss->xtnData.selectedPsk &&
+ ss->xtnData.selectedPsk->zeroRttSuite != TLS_NULL_WITH_NULL_NULL) {
+ spec->earlyDataRemaining = ss->xtnData.selectedPsk->maxEarlyData;
+ }
}
tls13_SetSpecRecordVersion(ss, spec);
@@ -3571,6 +3703,38 @@ tls13_SetupPendingCipherSpec(sslSocket *ss, ssl3CipherSpec *spec)
}
/*
+ * 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;
+
+ calg = spec->cipherDef->calg;
+
+ encMechanism = ssl3_Alg2Mech(calg);
+ encMode = CKA_NSS_MESSAGE | ((spec->direction == ssl_secret_write) ? CKA_ENCRYPT : CKA_DECRYPT);
+ iv.data = NULL;
+ iv.len = 0;
+
+ /*
+ * build the context
+ */
+ spec->cipherContext = PK11_CreateContextBySymKey(encMechanism, encMode,
+ spec->keyMaterial.key,
+ &iv);
+ if (!spec->cipherContext) {
+ ssl_MapLowLevelError(SSL_ERROR_SYM_KEY_CONTEXT_FAILURE);
+ return SECFailure;
+ }
+ return SECSuccess;
+}
+
+/*
* 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
@@ -3649,6 +3813,11 @@ tls13_SetCipherSpec(sslSocket *ss, PRUint16 epoch,
goto loser;
}
+ rv = tls13_InitPendingContext(ss, spec);
+ if (rv != SECSuccess) {
+ goto loser;
+ }
+
/* Now that we've set almost everything up, finally cut over. */
specp = (direction == ssl_secret_read) ? &ss->ssl3.crSpec : &ss->ssl3.cwSpec;
ssl_GetSpecWriteLock(ss);
@@ -3811,100 +3980,113 @@ tls13_DestroyEarlyData(PRCList *list)
* See RFC 5288 and https://tools.ietf.org/html/draft-ietf-tls-chacha20-poly1305-04#section-2
*/
static void
-tls13_WriteNonce(const ssl3KeyMaterial *keys,
- const unsigned char *seqNumBuf, unsigned int seqNumLen,
- unsigned char *nonce, unsigned int nonceLen)
+tls13_WriteNonce(const unsigned char *ivIn, unsigned int ivInLen,
+ const unsigned char *nonce, unsigned int nonceLen,
+ unsigned char *ivOut, unsigned int ivOutLen)
{
size_t i;
+ unsigned int offset = ivOutLen - nonceLen;
- PORT_Assert(nonceLen == 12);
- memcpy(nonce, keys->iv, 12);
+ PORT_Assert(ivInLen <= ivOutLen);
+ PORT_Assert(nonceLen <= ivOutLen);
+ PORT_Memset(ivOut, 0, ivOutLen);
+ PORT_Memcpy(ivOut, ivIn, ivInLen);
- /* XOR the last 8 bytes of the IV with the sequence number. */
- PORT_Assert(seqNumLen == 8);
- for (i = 0; i < 8; ++i) {
- nonce[4 + i] ^= seqNumBuf[i];
+ /* 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", nonce, nonceLen));
+ PRINT_BUF(50, (NULL, "Nonce", ivOut, ivOutLen));
}
-/* Implement the SSLAEADCipher interface defined in sslimpl.h.
- *
- * That interface takes the additional data (see below) and reinterprets that as
- * a sequence number. In TLS 1.3 there is no additional data so this value is
- * just the encoded sequence number.
+/* 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.
*/
-SECStatus
-tls13_AEAD(const ssl3KeyMaterial *keys, PRBool doDecrypt,
- unsigned char *out, unsigned int *outlen, unsigned int maxout,
- const unsigned char *in, unsigned int inlen,
- CK_MECHANISM_TYPE mechanism,
- unsigned char *aeadParams, unsigned int aeadParamLength)
+unsigned int
+tls13_SetupAeadIv(PRBool isDTLS, unsigned char *ivOut, unsigned char *ivIn,
+ unsigned int offset, unsigned int ivLen, DTLSEpoch epoch)
{
- SECItem param = {
- siBuffer, aeadParams, aeadParamLength
- };
-
- if (doDecrypt) {
- return PK11_Decrypt(keys->key, mechanism, &param,
- out, outlen, maxout, in, inlen);
+ PORT_Memcpy(ivOut, ivIn, ivLen);
+ if (isDTLS) {
+ /* 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] ^= (unsigned char)(epoch >> BPB) & 0xff;
+ ivOut[offset + 1] ^= (unsigned char)(epoch)&0xff;
+ offset += 2;
}
- return PK11_Encrypt(keys->key, mechanism, &param,
- out, outlen, maxout, in, inlen);
+ return offset;
}
-static SECStatus
-tls13_AESGCM(const ssl3KeyMaterial *keys,
- PRBool doDecrypt,
- unsigned char *out,
- unsigned int *outlen,
- unsigned int maxout,
- const unsigned char *in,
- unsigned int inlen,
- const unsigned char *additionalData,
- unsigned int additionalDataLen)
+/*
+ * 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, unsigned int fixedbits,
+ const unsigned char *ivIn, unsigned char *ivOut, unsigned int ivLen,
+ const unsigned char *nonceIn, unsigned int nonceLen,
+ const unsigned char *aad, unsigned int aadLen,
+ unsigned char *out, unsigned int *outLen, unsigned int maxout,
+ unsigned int tagLen, const unsigned char *in, unsigned int inLen)
{
- CK_GCM_PARAMS gcmParams;
- unsigned char nonce[12];
-
- PORT_Assert(additionalDataLen >= 8);
- memset(&gcmParams, 0, sizeof(gcmParams));
- gcmParams.pIv = nonce;
- gcmParams.ulIvLen = sizeof(nonce);
- gcmParams.pAAD = (PRUint8 *)(additionalData + 8);
- gcmParams.ulAADLen = additionalDataLen - 8;
- gcmParams.ulTagBits = 128; /* GCM measures tag length in bits. */
-
- tls13_WriteNonce(keys, additionalData, 8,
- nonce, sizeof(nonce));
- return tls13_AEAD(keys, doDecrypt, out, outlen, maxout, in, inlen,
- CKM_AES_GCM,
- (unsigned char *)&gcmParams, sizeof(gcmParams));
-}
+ unsigned char *tag;
+ unsigned char iv[MAX_IV_LENGTH];
+ unsigned char tagbuf[HASH_LENGTH_MAX];
+ SECStatus rv;
-static SECStatus
-tls13_ChaCha20Poly1305(const ssl3KeyMaterial *keys, PRBool doDecrypt,
- unsigned char *out, unsigned int *outlen, unsigned int maxout,
- const unsigned char *in, unsigned int inlen,
- const unsigned char *additionalData,
- unsigned int additionalDataLen)
-{
- CK_NSS_AEAD_PARAMS aeadParams;
- unsigned char nonce[12];
-
- PORT_Assert(additionalDataLen > 8);
- memset(&aeadParams, 0, sizeof(aeadParams));
- aeadParams.pNonce = nonce;
- aeadParams.ulNonceLen = sizeof(nonce);
- aeadParams.pAAD = (PRUint8 *)(additionalData + 8);
- aeadParams.ulAADLen = additionalDataLen - 8;
- aeadParams.ulTagLen = 16; /* The Poly1305 tag is 16 octets. */
-
- tls13_WriteNonce(keys, additionalData, 8,
- nonce, sizeof(nonce));
- return tls13_AEAD(keys, doDecrypt, out, outlen, maxout, in, inlen,
- CKM_NSS_CHACHA20_POLY1305,
- (unsigned char *)&aeadParams, sizeof(aeadParams));
+ /* 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);
+ } else if (ivIn != ivOut) {
+ PORT_Memcpy(ivOut, ivIn, ivLen);
+ }
+ if (decrypt) {
+ inLen = inLen - tagLen;
+ tag = (unsigned char *)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)) {
+ unsigned int 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;
}
static SECStatus
@@ -3968,7 +4150,7 @@ tls13_HandleEncryptedExtensions(sslSocket *ss, PRUint8 *b, PRUint32 length)
/* 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->statelessResume) {
+ if (!ss->xtnData.selectedPsk) {
/* Illegal to accept 0-RTT without also accepting PSK. */
FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_ENCRYPTED_EXTENSIONS,
illegal_parameter);
@@ -4006,6 +4188,10 @@ tls13_HandleEncryptedExtensions(sslSocket *ss, PRUint8 *b, PRUint32 length)
TLS13_SET_HS_STATE(ss, wait_cert_request);
}
+ /* Client is done with any PSKs */
+ tls13_DestroyPskList(&ss->ssl3.hs.psks);
+ ss->xtnData.selectedPsk = NULL;
+
return SECSuccess;
}
@@ -4285,7 +4471,7 @@ loser:
static SECStatus
tls13_ComputePskBinderHash(sslSocket *ss, unsigned int prefixLength,
- SSL3Hashes *hashes)
+ SSL3Hashes *hashes, SSLHashType hashType)
{
SECStatus rv;
@@ -4295,14 +4481,14 @@ tls13_ComputePskBinderHash(sslSocket *ss, unsigned int prefixLength,
PRINT_BUF(10, (NULL, "Handshake hash computed over ClientHello prefix",
ss->ssl3.hs.messages.buf, prefixLength));
- rv = PK11_HashBuf(ssl3_HashTypeToOID(tls13_GetHash(ss)),
+ rv = PK11_HashBuf(ssl3_HashTypeToOID(hashType),
hashes->u.raw, ss->ssl3.hs.messages.buf, prefixLength);
if (rv != SECSuccess) {
ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE);
return SECFailure;
}
- hashes->len = tls13_GetHashSize(ss);
+ hashes->len = tls13_GetHashSizeForHash(hashType);
PRINT_BUF(10, (NULL, "PSK Binder hash", hashes->u.raw, hashes->len));
return SECSuccess;
@@ -4320,7 +4506,10 @@ tls13_WriteExtensionsWithBinder(sslSocket *ss, sslBuffer *extensions)
{
SSL3Hashes hashes;
SECStatus rv;
- unsigned int size = tls13_GetHashSize(ss);
+
+ PORT_Assert(!PR_CLIST_IS_EMPTY(&ss->ssl3.hs.psks));
+ sslPsk *psk = (sslPsk *)PR_LIST_HEAD(&ss->ssl3.hs.psks);
+ unsigned int size = tls13_GetHashSizeForHash(psk->hash);
unsigned int prefixLen = extensions->len - size - 3;
unsigned int finishedLen;
@@ -4341,15 +4530,18 @@ tls13_WriteExtensionsWithBinder(sslSocket *ss, sslBuffer *extensions)
}
/* Calculate the binder based on what has been written out. */
- rv = tls13_ComputePskBinderHash(ss, ss->ssl3.hs.messages.len, &hashes);
+ rv = tls13_ComputePskBinderHash(ss, ss->ssl3.hs.messages.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
+ * previously. This avoids an allocation and means that we don't need a
* separate write for the extra bits that precede the binder. */
- rv = tls13_ComputeFinished(ss, ss->ssl3.hs.pskBinderKey, &hashes, PR_TRUE,
+ 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) {
@@ -4369,13 +4561,13 @@ tls13_WriteExtensionsWithBinder(sslSocket *ss, sslBuffer *extensions)
static SECStatus
tls13_ComputeFinished(sslSocket *ss, PK11SymKey *baseKey,
- const SSL3Hashes *hashes,
+ SSLHashType hashType, const SSL3Hashes *hashes,
PRBool sending, PRUint8 *output, unsigned int *outputLen,
unsigned int maxOutputLen)
{
SECStatus rv;
PK11Context *hmacCtx = NULL;
- CK_MECHANISM_TYPE macAlg = tls13_GetHmacMechanism(ss);
+ CK_MECHANISM_TYPE macAlg = tls13_GetHmacMechanismFromHash(hashType);
SECItem param = { siBuffer, NULL, 0 };
unsigned int outputLenUint;
const char *label = kHkdfLabelFinishedSecret;
@@ -4387,17 +4579,16 @@ tls13_ComputeFinished(sslSocket *ss, PK11SymKey *baseKey,
PRINT_BUF(50, (ss, "Handshake hash", hashes->u.raw, hashes->len));
/* Now derive the appropriate finished secret from the base secret. */
- rv = tls13_HkdfExpandLabel(baseKey,
- tls13_GetHash(ss),
- NULL, 0,
- label, strlen(label),
- tls13_GetHmacMechanism(ss),
- tls13_GetHashSize(ss), &secret);
+ rv = tls13_HkdfExpandLabel(baseKey, hashType,
+ NULL, 0, label, strlen(label),
+ tls13_GetHmacMechanismFromHash(hashType),
+ tls13_GetHashSizeForHash(hashType),
+ ss->protocolVariant, &secret);
if (rv != SECSuccess) {
goto abort;
}
- PORT_Assert(hashes->len == tls13_GetHashSize(ss));
+ PORT_Assert(hashes->len == tls13_GetHashSizeForHash(hashType));
hmacCtx = PK11_CreateContextBySymKey(macAlg, CKA_SIGN,
secret, &param);
if (!hmacCtx) {
@@ -4412,7 +4603,7 @@ tls13_ComputeFinished(sslSocket *ss, PK11SymKey *baseKey,
if (rv != SECSuccess)
goto abort;
- PORT_Assert(maxOutputLen >= tls13_GetHashSize(ss));
+ PORT_Assert(maxOutputLen >= tls13_GetHashSizeForHash(hashType));
rv = PK11_DigestFinal(hmacCtx, output, &outputLenUint, maxOutputLen);
if (rv != SECSuccess)
goto abort;
@@ -4456,7 +4647,7 @@ tls13_SendFinished(sslSocket *ss, PK11SymKey *baseKey)
}
ssl_GetSpecReadLock(ss);
- rv = tls13_ComputeFinished(ss, baseKey, &hashes, PR_TRUE,
+ rv = tls13_ComputeFinished(ss, baseKey, tls13_GetHash(ss), &hashes, PR_TRUE,
finishedBuf, &finishedLen, sizeof(finishedBuf));
ssl_ReleaseSpecReadLock(ss);
if (rv != SECSuccess) {
@@ -4493,7 +4684,7 @@ tls13_VerifyFinished(sslSocket *ss, SSLHandshakeType message,
return SECFailure;
}
- rv = tls13_ComputeFinished(ss, secret, hashes, PR_FALSE,
+ rv = tls13_ComputeFinished(ss, secret, tls13_GetHash(ss), hashes, PR_FALSE,
finishedBuf, &finishedLen, sizeof(finishedBuf));
if (rv != SECSuccess) {
FATAL_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE, internal_error);
@@ -4583,6 +4774,20 @@ tls13_ServerHandleFinished(sslSocket *ss, PRUint8 *b, PRUint32 length)
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;
+ }
+ }
+
rv = tls13_CommonHandleFinished(ss,
ss->firstHsDone ? ss->ssl3.hs.clientTrafficSecret : ss->ssl3.hs.clientHsTrafficSecret,
b, length);
@@ -4646,7 +4851,8 @@ tls13_ServerHandleFinished(sslSocket *ss, PRUint8 *b, PRUint32 length)
}
ssl_GetXmitBufLock(ss);
- if (ss->opt.enableSessionTickets) {
+ /* 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;
@@ -4929,8 +5135,9 @@ tls13_SendNewSessionTicket(sslSocket *ss, const PRUint8 *appToken,
ticketNonce, sizeof(ticketNonce),
kHkdfLabelResumption,
strlen(kHkdfLabelResumption),
- tls13_GetHkdfMechanism(ss),
- tls13_GetHashSize(ss), &secret);
+ CKM_HKDF_DERIVE,
+ tls13_GetHashSize(ss),
+ ss->protocolVariant, &secret);
if (rv != SECSuccess) {
goto loser;
}
@@ -5028,6 +5235,14 @@ SSLExp_SendSessionTicket(PRFileDesc *fd, const PRUint8 *token,
return SECFailure;
}
+ /* 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;
+ }
+
ssl_GetSSL3HandshakeLock(ss);
ssl_GetXmitBufLock(ss);
rv = tls13_SendNewSessionTicket(ss, token, tokenLen);
@@ -5163,8 +5378,9 @@ tls13_HandleNewSessionTicket(sslSocket *ss, PRUint8 *b, PRUint32 length)
ticket_nonce.data, ticket_nonce.len,
kHkdfLabelResumption,
strlen(kHkdfLabelResumption),
- tls13_GetHkdfMechanism(ss),
- tls13_GetHashSize(ss), &secret);
+ CKM_HKDF_DERIVE,
+ tls13_GetHashSize(ss),
+ ss->protocolVariant, &secret);
if (rv != SECSuccess) {
return SECFailure;
}
@@ -5348,11 +5564,20 @@ tls13_ProtectRecord(sslSocket *ss,
sslBuffer buf = SSL_BUFFER_FIXED(hdr, sizeof(hdr));
PRBool needsLength;
PRUint8 aad[21];
+ const int ivLen = cipher_def->iv_size + cipher_def->explicit_nonce_size;
+ unsigned int ivOffset = ivLen - sizeof(sslSequenceNumber);
+ unsigned char ivOut[MAX_IV_LENGTH];
+
unsigned int aadLen;
unsigned int len;
PORT_Assert(cipher_def->type == type_aead);
+ /* 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;
@@ -5363,9 +5588,7 @@ tls13_ProtectRecord(sslSocket *ss,
return SECFailure;
}
if (needsLength) {
- rv = sslBuffer_AppendNumber(&buf, contentLen + 1 +
- cwSpec->cipherDef->tag_size,
- 2);
+ rv = sslBuffer_AppendNumber(&buf, contentLen + 1 + tagLen, 2);
if (rv != SECSuccess) {
return SECFailure;
}
@@ -5376,14 +5599,22 @@ tls13_ProtectRecord(sslSocket *ss,
if (rv != SECSuccess) {
return SECFailure;
}
- rv = cwSpec->aead(&cwSpec->keyMaterial,
- PR_FALSE, /* do encrypt */
- SSL_BUFFER_NEXT(wrBuf), /* output */
- &len, /* out len */
- SSL_BUFFER_SPACE(wrBuf), /* max out */
- SSL_BUFFER_NEXT(wrBuf), /* input */
- contentLen + 1, /* input len */
- aad, aadLen);
+ /* set up initial IV value */
+ ivOffset = tls13_SetupAeadIv(IS_DTLS(ss), 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;
@@ -5413,6 +5644,9 @@ tls13_UnprotectRecord(sslSocket *ss,
SSL3AlertDescription *alert)
{
const ssl3BulkCipherDef *cipher_def = spec->cipherDef;
+ const int ivLen = cipher_def->iv_size + cipher_def->explicit_nonce_size;
+ const int tagLen = cipher_def->tag_size;
+
PRUint8 aad[21];
unsigned int aadLen;
SECStatus rv;
@@ -5440,7 +5674,7 @@ tls13_UnprotectRecord(sslSocket *ss,
/* 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 < cipher_def->tag_size) {
+ if (cText->buf->len < tagLen) {
SSL_TRC(3,
("%d: TLS13[%d]: record too short to contain valid AEAD data",
SSL_GETPID(), ss->fd));
@@ -5467,17 +5701,26 @@ tls13_UnprotectRecord(sslSocket *ss,
spec->epoch, cText->seqNum,
aad, &aadLen, sizeof(aad));
if (rv != SECSuccess) {
+
return SECFailure;
}
- rv = spec->aead(&spec->keyMaterial,
- PR_TRUE, /* do decrypt */
- plaintext->buf, /* out */
+ rv = tls13_AEAD(spec->cipherContext, PR_TRUE,
+ CKG_NO_GENERATE, 0, /* ignored for decrypt */
+ spec->keyMaterial.iv, NULL, ivLen, /* iv */
+ aad, sizeof(sslSequenceNumber), /* nonce */
+ aad + sizeof(sslSequenceNumber), /* aad */
+ aadLen - sizeof(sslSequenceNumber),
+ plaintext->buf, /* output */
&plaintext->len, /* outlen */
plaintext->space, /* maxout */
+ tagLen,
cText->buf->buf, /* in */
- cText->buf->len, /* inlen */
- aad, aadLen);
+ cText->buf->len); /* inlen */
if (rv != SECSuccess) {
+ if (IS_DTLS(ss)) {
+ spec->deprotectionFailures++;
+ }
+
SSL_TRC(3,
("%d: TLS13[%d]: record has bogus MAC",
SSL_GETPID(), ss->fd));
@@ -5538,9 +5781,10 @@ tls13_UnprotectRecord(sslSocket *ss,
* 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.
- * 5. The server is willing to accept 0-RTT.
- * 6. We have not changed our ALPN settings to disallow the ALPN tag
+ * 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().
@@ -5550,17 +5794,39 @@ 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)
+ if (sid->version < SSL_LIBRARY_VERSION_TLS_1_3) {
return PR_FALSE;
- if (ss->ssl3.hs.helloRetry)
+ }
+ if (ss->ssl3.hs.helloRetry) {
return PR_FALSE;
- if (!ss->opt.enable0RttData)
+ }
+ if (!ss->opt.enable0RttData) {
return PR_FALSE;
- if (!ss->statelessResume)
+ }
+ if (PR_CLIST_IS_EMPTY(&ss->ssl3.hs.psks)) {
return PR_FALSE;
- if ((sid->u.ssl3.locked.sessionTicket.flags & ticket_allow_early_data) == 0)
+ }
+ sslPsk *psk = (sslPsk *)PR_LIST_HEAD(&ss->ssl3.hs.psks);
+
+ if (psk->zeroRttSuite == TLS_NULL_WITH_NULL_NULL) {
return PR_FALSE;
- return ssl_AlpnTagAllowed(ss, &sid->u.ssl3.alpnSelection);
+ }
+ 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;
}
SECStatus
@@ -5607,6 +5873,9 @@ tls13_MaybeDo0RTTHandshake(sslSocket *ss)
}
}
+ /* 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;
@@ -5618,6 +5887,7 @@ tls13_MaybeDo0RTTHandshake(sslSocket *ss)
rv = tls13_SetCipherSpec(ss, TrafficKeyEarlyApplicationData,
ssl_secret_write, PR_TRUE);
+ ss->xtnData.selectedPsk = NULL;
if (rv != SECSuccess) {
return SECFailure;
}
@@ -5672,12 +5942,14 @@ tls13_SendEndOfEarlyData(sslSocket *ss)
{
SECStatus rv;
- SSL_TRC(3, ("%d: TLS13[%d]: send EndOfEarlyData", SSL_GETPID(), ss->fd));
PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
- rv = ssl3_AppendHandshakeHeader(ss, ssl_hs_end_of_early_data, 0);
- if (rv != SECSuccess) {
- return rv; /* err set by AppendHandshake. */
+ if (!ss->opt.suppressEndOfEarlyData) {
+ SSL_TRC(3, ("%d: TLS13[%d]: send EndOfEarlyData", SSL_GETPID(), ss->fd));
+ rv = ssl3_AppendHandshakeHeader(ss, ssl_hs_end_of_early_data, 0);
+ if (rv != SECSuccess) {
+ return rv; /* err set by AppendHandshake. */
+ }
}
ss->ssl3.hs.zeroRttState = ssl_0rtt_done;
@@ -5685,7 +5957,7 @@ tls13_SendEndOfEarlyData(sslSocket *ss)
}
static SECStatus
-tls13_HandleEndOfEarlyData(sslSocket *ss, PRUint8 *b, PRUint32 length)
+tls13_HandleEndOfEarlyData(sslSocket *ss, const PRUint8 *b, PRUint32 length)
{
SECStatus rv;
@@ -5728,6 +6000,18 @@ tls13_HandleEndOfEarlyData(sslSocket *ss, PRUint8 *b, PRUint32 length)
return SECSuccess;
}
+static SECStatus
+tls13_MaybeHandleSuppressedEndOfEarlyData(sslSocket *ss)
+{
+ PORT_Assert(ss->sec.isServer);
+ if (!ss->opt.suppressEndOfEarlyData ||
+ ss->ssl3.hs.zeroRttState != ssl_0rtt_accepted) {
+ return SECSuccess;
+ }
+
+ return tls13_HandleEndOfEarlyData(ss, NULL, 0);
+}
+
SECStatus
tls13_HandleEarlyApplicationData(sslSocket *ss, sslBuffer *origBuf)
{
@@ -5763,14 +6047,26 @@ tls13_HandleEarlyApplicationData(sslSocket *ss, sslBuffer *origBuf)
}
PRUint16
-tls13_EncodeDraftVersion(SSL3ProtocolVersion version, SSLProtocolVariant variant)
+tls13_EncodeVersion(SSL3ProtocolVersion version, SSLProtocolVariant variant)
{
+ if (variant == ssl_variant_datagram) {
+ /* TODO: When DTLS 1.3 is out of draft, replace this with
+ * dtls_TLSVersionToDTLSVersion(). */
+ switch (version) {
#ifdef DTLS_1_3_DRAFT_VERSION
- if (version == SSL_LIBRARY_VERSION_TLS_1_3 &&
- variant == ssl_variant_datagram) {
- return 0x7f00 | DTLS_1_3_DRAFT_VERSION;
- }
+ case SSL_LIBRARY_VERSION_TLS_1_3:
+ return 0x7f00 | DTLS_1_3_DRAFT_VERSION;
#endif
+ case SSL_LIBRARY_VERSION_TLS_1_2:
+ return SSL_LIBRARY_VERSION_DTLS_1_2_WIRE;
+ case SSL_LIBRARY_VERSION_TLS_1_1:
+ /* TLS_1_1 maps to DTLS_1_0, see sslproto.h. */
+ return SSL_LIBRARY_VERSION_DTLS_1_0_WIRE;
+ default:
+ PORT_Assert(0);
+ }
+ }
+ /* Stream-variant encodings do not change. */
return (PRUint16)version;
}
@@ -5800,8 +6096,8 @@ tls13_ClientReadSupportedVersion(sslSocket *ss)
return SECFailure;
}
- if (temp != tls13_EncodeDraftVersion(SSL_LIBRARY_VERSION_TLS_1_3,
- ss->protocolVariant)) {
+ 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;
@@ -5840,7 +6136,7 @@ tls13_NegotiateVersion(sslSocket *ss, const TLSExtension *supportedVersions)
return SECFailure;
}
- PRUint16 wire = tls13_EncodeDraftVersion(version, ss->protocolVariant);
+ PRUint16 wire = tls13_EncodeVersion(version, ss->protocolVariant);
unsigned long offset;
for (offset = 0; offset < versions.len; offset += 2) {