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.c315
1 files changed, 158 insertions, 157 deletions
diff --git a/security/nss/lib/ssl/tls13con.c b/security/nss/lib/ssl/tls13con.c
index c6a584748..560493848 100644
--- a/security/nss/lib/ssl/tls13con.c
+++ b/security/nss/lib/ssl/tls13con.c
@@ -22,9 +22,10 @@
#include "tls13exthandle.h"
typedef enum {
- TrafficKeyEarlyApplicationData,
- TrafficKeyHandshake,
- TrafficKeyApplicationData
+ TrafficKeyClearText = 0,
+ TrafficKeyEarlyApplicationData = 1,
+ TrafficKeyHandshake = 2,
+ TrafficKeyApplicationData = 3
} TrafficKeyType;
typedef enum {
@@ -56,17 +57,17 @@ static SECStatus tls13_SendHelloRetryRequest(sslSocket *ss,
const sslNamedGroupDef *selectedGroup);
static SECStatus tls13_HandleServerKeyShare(sslSocket *ss);
-static SECStatus tls13_HandleEncryptedExtensions(sslSocket *ss, SSL3Opaque *b,
+static SECStatus tls13_HandleEncryptedExtensions(sslSocket *ss, PRUint8 *b,
PRUint32 length);
static SECStatus tls13_SendCertificate(sslSocket *ss);
static SECStatus tls13_HandleCertificate(
- sslSocket *ss, SSL3Opaque *b, PRUint32 length);
-static SECStatus tls13_HandleCertificateRequest(sslSocket *ss, SSL3Opaque *b,
+ sslSocket *ss, PRUint8 *b, PRUint32 length);
+static SECStatus tls13_HandleCertificateRequest(sslSocket *ss, PRUint8 *b,
PRUint32 length);
static SECStatus
tls13_SendCertificateVerify(sslSocket *ss, SECKEYPrivateKey *privKey);
static SECStatus tls13_HandleCertificateVerify(
- sslSocket *ss, SSL3Opaque *b, PRUint32 length,
+ sslSocket *ss, PRUint8 *b, PRUint32 length,
SSL3Hashes *hashes);
static SECStatus tls13_RecoverWrappedSharedSecret(sslSocket *ss,
sslSessionID *sid);
@@ -76,7 +77,6 @@ tls13_DeriveSecret(sslSocket *ss, PK11SymKey *key,
const char *suffix,
const SSL3Hashes *hashes,
PK11SymKey **dest);
-static void tls13_SetNullCipherSpec(sslSocket *ss, ssl3CipherSpec **specp);
static SECStatus tls13_SendEndOfEarlyData(sslSocket *ss);
static SECStatus tls13_SendFinished(sslSocket *ss, PK11SymKey *baseKey);
static SECStatus tls13_ComputePskBinderHash(sslSocket *ss,
@@ -84,15 +84,15 @@ static SECStatus tls13_ComputePskBinderHash(sslSocket *ss,
SSL3Hashes *hashes);
static SECStatus tls13_VerifyFinished(sslSocket *ss, SSL3HandshakeType message,
PK11SymKey *secret,
- SSL3Opaque *b, PRUint32 length,
+ PRUint8 *b, PRUint32 length,
const SSL3Hashes *hashes);
static SECStatus tls13_ClientHandleFinished(sslSocket *ss,
- SSL3Opaque *b, PRUint32 length,
+ PRUint8 *b, PRUint32 length,
const SSL3Hashes *hashes);
static SECStatus tls13_ServerHandleFinished(sslSocket *ss,
- SSL3Opaque *b, PRUint32 length,
+ PRUint8 *b, PRUint32 length,
const SSL3Hashes *hashes);
-static SECStatus tls13_HandleNewSessionTicket(sslSocket *ss, SSL3Opaque *b,
+static SECStatus tls13_HandleNewSessionTicket(sslSocket *ss, PRUint8 *b,
PRUint32 length);
static SECStatus tls13_ComputeHandshakeHashes(sslSocket *ss,
SSL3Hashes *hashes);
@@ -132,7 +132,7 @@ const SSL3ProtocolVersion kDtlsRecordVersion = SSL_LIBRARY_VERSION_TLS_1_1;
PR_STATIC_ASSERT(SSL_LIBRARY_VERSION_MAX_SUPPORTED <=
SSL_LIBRARY_VERSION_TLS_1_3);
-/* Use this instead of FATAL_ERROR when an alert isn't possible. */
+/* Use this instead of FATAL_ERROR when no alert shall be sent. */
#define LOG_ERROR(ss, prError) \
do { \
SSL_TRC(3, ("%d: TLS13[%d]: fatal error %d in %s (%s:%d)", \
@@ -163,15 +163,21 @@ static char *
tls13_HandshakeState(SSL3WaitState st)
{
switch (st) {
+ STATE_CASE(idle_handshake);
STATE_CASE(wait_client_hello);
STATE_CASE(wait_client_cert);
+ STATE_CASE(wait_client_key);
STATE_CASE(wait_cert_verify);
+ STATE_CASE(wait_change_cipher);
STATE_CASE(wait_finished);
STATE_CASE(wait_server_hello);
+ STATE_CASE(wait_certificate_status);
STATE_CASE(wait_server_cert);
+ STATE_CASE(wait_server_key);
STATE_CASE(wait_cert_request);
+ STATE_CASE(wait_hello_done);
+ STATE_CASE(wait_new_session_ticket);
STATE_CASE(wait_encrypted_extensions);
- STATE_CASE(idle_handshake);
default:
break;
}
@@ -426,10 +432,7 @@ tls13_SetupClientHello(sslSocket *ss)
session_ticket = &sid->u.ssl3.locked.sessionTicket;
PORT_Assert(session_ticket && session_ticket->ticket.data);
- if (session_ticket->ticket_lifetime_hint == 0 ||
- (session_ticket->ticket_lifetime_hint +
- session_ticket->received_timestamp >
- ssl_Time())) {
+ if (ssl_TicketTimeValid(session_ticket)) {
ss->statelessResume = PR_TRUE;
}
@@ -465,7 +468,7 @@ tls13_SetupClientHello(sslSocket *ss)
static SECStatus
tls13_ImportDHEKeyShare(sslSocket *ss, SECKEYPublicKey *peerKey,
- SSL3Opaque *b, PRUint32 length,
+ PRUint8 *b, PRUint32 length,
SECKEYPublicKey *pubKey)
{
SECStatus rv;
@@ -556,7 +559,7 @@ loser:
}
SECStatus
-tls13_HandlePostHelloHandshakeMessage(sslSocket *ss, SSL3Opaque *b,
+tls13_HandlePostHelloHandshakeMessage(sslSocket *ss, PRUint8 *b,
PRUint32 length, SSL3Hashes *hashesPtr)
{
if (ss->sec.isServer && ss->ssl3.hs.zeroRttIgnore != ssl_0rtt_ignore_none) {
@@ -625,13 +628,9 @@ tls13_RecoverWrappedSharedSecret(sslSocket *ss, sslSessionID *sid)
hashType = tls13_GetHashForCipherSuite(sid->u.ssl3.cipherSuite);
/* If we are the server, we compute the wrapping key, but if we
- * are the client, it's coordinates are stored with the ticket. */
+ * are the client, its coordinates are stored with the ticket. */
if (ss->sec.isServer) {
- const sslServerCert *serverCert;
-
- serverCert = ssl_FindServerCert(ss, &sid->certType);
- PORT_Assert(serverCert);
- wrapKey = ssl3_GetWrappingKey(ss, NULL, serverCert,
+ wrapKey = ssl3_GetWrappingKey(ss, NULL,
sid->u.ssl3.masterWrapMech,
ss->pkcs11PinArg);
} else {
@@ -934,7 +933,7 @@ tls13_CanResume(sslSocket *ss, const sslSessionID *sid)
* do remember the type of certificate we originally used, so we can locate
* it again, provided that the current ssl socket has had its server certs
* configured the same as the previous one. */
- sc = ssl_FindServerCert(ss, &sid->certType);
+ sc = ssl_FindServerCert(ss, sid->authType, sid->namedCurve);
if (!sc || !sc->serverCert) {
return PR_FALSE;
}
@@ -943,27 +942,6 @@ tls13_CanResume(sslSocket *ss, const sslSessionID *sid)
}
static PRBool
-tls13_AlpnTagAllowed(const sslSocket *ss, const SECItem *tag)
-{
- const unsigned char *data = ss->opt.nextProtoNego.data;
- unsigned int length = ss->opt.nextProtoNego.len;
- unsigned int offset = 0;
-
- if (!tag->len)
- return PR_TRUE;
-
- while (offset < length) {
- unsigned int taglen = (unsigned int)data[offset];
- if ((taglen == tag->len) &&
- !PORT_Memcmp(data + offset + 1, tag->data, tag->len))
- return PR_TRUE;
- offset += 1 + taglen;
- }
-
- return PR_FALSE;
-}
-
-static PRBool
tls13_CanNegotiateZeroRtt(sslSocket *ss, const sslSessionID *sid)
{
PORT_Assert(ss->ssl3.hs.zeroRttState == ssl_0rtt_sent);
@@ -1158,6 +1136,30 @@ tls13_NegotiateKeyExchange(sslSocket *ss, TLS13KeyShareEntry **clientShare)
return SECSuccess;
}
+SSLAuthType
+ssl_SignatureSchemeToAuthType(SSLSignatureScheme scheme)
+{
+ switch (scheme) {
+ case ssl_sig_rsa_pkcs1_sha1:
+ case ssl_sig_rsa_pkcs1_sha256:
+ case ssl_sig_rsa_pkcs1_sha384:
+ case ssl_sig_rsa_pkcs1_sha512:
+ /* We report PSS signatures as being just RSA signatures. */
+ case ssl_sig_rsa_pss_sha256:
+ case ssl_sig_rsa_pss_sha384:
+ case ssl_sig_rsa_pss_sha512:
+ return ssl_auth_rsa_sign;
+ case ssl_sig_ecdsa_secp256r1_sha256:
+ case ssl_sig_ecdsa_secp384r1_sha384:
+ case ssl_sig_ecdsa_secp521r1_sha512:
+ case ssl_sig_ecdsa_sha1:
+ return ssl_auth_ecdsa;
+ default:
+ PORT_Assert(0);
+ }
+ return ssl_auth_null;
+}
+
SECStatus
tls13_SelectServerCert(sslSocket *ss)
{
@@ -1181,8 +1183,7 @@ tls13_SelectServerCert(sslSocket *ss)
cursor = PR_NEXT_LINK(cursor)) {
sslServerCert *cert = (sslServerCert *)cursor;
- if (cert->certType.authType == ssl_auth_rsa_pss ||
- cert->certType.authType == ssl_auth_rsa_decrypt) {
+ if (SSL_CERT_IS_ONLY(cert, ssl_auth_rsa_decrypt)) {
continue;
}
@@ -1195,8 +1196,8 @@ tls13_SelectServerCert(sslSocket *ss)
if (rv == SECSuccess) {
/* Found one. */
ss->sec.serverCert = cert;
- ss->sec.authType = cert->certType.authType;
- ss->ssl3.hs.kea_def_mutable.authKeyType = cert->certType.authType;
+ ss->sec.authType = ss->ssl3.hs.kea_def_mutable.authKeyType =
+ ssl_SignatureSchemeToAuthType(ss->ssl3.hs.signatureScheme);
ss->sec.authKeyBits = cert->serverKeyBits;
return SECSuccess;
}
@@ -1227,8 +1228,6 @@ tls13_NegotiateAuthentication(sslSocket *ss)
if (rv != SECSuccess) {
return SECFailure;
}
- ss->ssl3.hs.kea_def_mutable.authKeyType =
- ss->sec.serverCert->certType.authType;
return SECSuccess;
}
@@ -1248,16 +1247,6 @@ tls13_HandleClientHelloPart2(sslSocket *ss,
if (ssl3_ExtensionNegotiated(ss, ssl_tls13_early_data_xtn)) {
ss->ssl3.hs.zeroRttState = ssl_0rtt_sent;
-
- if (IS_DTLS(ss)) {
- /* Save the null spec, which we should be currently reading. We will
- * use this when 0-RTT sending is over. */
- ssl_GetSpecReadLock(ss);
- ss->ssl3.hs.nullSpec = ss->ssl3.crSpec;
- tls13_CipherSpecAddRef(ss->ssl3.hs.nullSpec);
- PORT_Assert(ss->ssl3.hs.nullSpec->cipher_def->cipher == cipher_null);
- ssl_ReleaseSpecReadLock(ss);
- }
}
#ifndef PARANOID
@@ -1340,6 +1329,10 @@ tls13_HandleClientHelloPart2(sslSocket *ss,
goto loser;
}
+ 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);
@@ -1348,12 +1341,11 @@ tls13_HandleClientHelloPart2(sslSocket *ss,
}
tls13_RestoreCipherInfo(ss, sid);
- ss->sec.serverCert = ssl_FindServerCert(ss, &sid->certType);
- PORT_Assert(ss->sec.serverCert);
ss->sec.localCert = CERT_DupCertificate(ss->sec.serverCert->serverCert);
if (sid->peerCert != NULL) {
ss->sec.peerCert = CERT_DupCertificate(sid->peerCert);
}
+
ssl3_RegisterExtensionSender(
ss, &ss->xtnData,
ssl_tls13_pre_shared_key_xtn, tls13_ServerSendPreSharedKeyXtn);
@@ -1614,9 +1606,9 @@ static SECStatus
tls13_SendCertificateRequest(sslSocket *ss)
{
SECStatus rv;
- int calen;
+ unsigned int calen;
SECItem *names;
- int nnames;
+ unsigned int nnames;
SECItem *name;
int i;
PRUint8 sigSchemes[MAX_SIGNATURE_SCHEMES * 2];
@@ -1632,7 +1624,10 @@ tls13_SendCertificateRequest(sslSocket *ss)
return rv;
}
- ssl3_GetCertificateRequestCAs(ss, &calen, &names, &nnames);
+ rv = ssl_GetCertificateRequestCAs(ss, &calen, &names, &nnames);
+ if (rv != SECSuccess) {
+ return rv;
+ }
length = 1 + 0 /* length byte for empty request context */ +
2 + sigSchemesLength + 2 + calen + 2;
@@ -1667,10 +1662,10 @@ tls13_SendCertificateRequest(sslSocket *ss)
}
SECStatus
-tls13_HandleHelloRetryRequest(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
+tls13_HandleHelloRetryRequest(sslSocket *ss, PRUint8 *b, PRUint32 length)
{
SECStatus rv;
- PRInt32 tmp;
+ PRUint32 tmp;
SSL3ProtocolVersion version;
SSL_TRC(3, ("%d: TLS13[%d]: handle hello retry request",
@@ -1700,9 +1695,13 @@ tls13_HandleHelloRetryRequest(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
}
if (ss->ssl3.hs.zeroRttState == ssl_0rtt_sent) {
- /* Oh well, back to the start. */
- tls13_SetNullCipherSpec(ss, &ss->ssl3.cwSpec);
ss->ssl3.hs.zeroRttState = ssl_0rtt_ignored;
+ /* Restore the null cipher spec for writing. */
+ ssl_GetSpecWriteLock(ss);
+ tls13_CipherSpecRelease(ss->ssl3.cwSpec);
+ ss->ssl3.cwSpec = ss->ssl3.crSpec;
+ PORT_Assert(ss->ssl3.cwSpec->cipher_def->cipher == cipher_null);
+ ssl_ReleaseSpecWriteLock(ss);
} else {
PORT_Assert(ss->ssl3.hs.zeroRttState == ssl_0rtt_none);
}
@@ -1719,8 +1718,8 @@ tls13_HandleHelloRetryRequest(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
}
/* Extensions. */
- tmp = ssl3_ConsumeHandshakeNumber(ss, 2, &b, &length);
- if (tmp < 0) {
+ rv = ssl3_ConsumeHandshakeNumber(ss, &tmp, 2, &b, &length);
+ if (rv != SECSuccess) {
return SECFailure; /* error code already set */
}
/* Extensions must be non-empty and use the remainder of the message.
@@ -1752,13 +1751,13 @@ tls13_HandleHelloRetryRequest(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
}
static SECStatus
-tls13_HandleCertificateRequest(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
+tls13_HandleCertificateRequest(sslSocket *ss, PRUint8 *b, PRUint32 length)
{
SECStatus rv;
TLS13CertificateRequest *certRequest = NULL;
SECItem context = { siBuffer, NULL, 0 };
PLArenaPool *arena;
- PRInt32 extensionsLength;
+ SECItem extensionsData = { siBuffer, NULL, 0 };
SSL_TRC(3, ("%d: TLS13[%d]: handle certificate_request sequence",
SSL_GETPID(), ss->fd));
@@ -1805,7 +1804,7 @@ tls13_HandleCertificateRequest(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
&certRequest->signatureSchemes,
&certRequest->signatureSchemeCount,
&b, &length);
- if (rv != SECSuccess) {
+ if (rv != SECSuccess || certRequest->signatureSchemeCount == 0) {
FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_CERT_REQUEST,
decode_error);
goto loser;
@@ -1816,14 +1815,16 @@ tls13_HandleCertificateRequest(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
if (rv != SECSuccess)
goto loser; /* alert already sent */
- /* Verify that the extensions length is correct. */
- extensionsLength = ssl3_ConsumeHandshakeNumber(ss, 2, &b, &length);
- if (extensionsLength < 0) {
- goto loser; /* alert already sent */
+ /* Verify that the extensions are sane. */
+ rv = ssl3_ConsumeHandshakeVariable(ss, &extensionsData, 2, &b, &length);
+ if (rv != SECSuccess) {
+ goto loser;
}
- if (extensionsLength != length) {
- FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_CERT_REQUEST,
- illegal_parameter);
+
+ /* Process all the extensions (note: currently a no-op). */
+ rv = ssl3_HandleExtensions(ss, &extensionsData.data, &extensionsData.len,
+ certificate_request);
+ if (rv != SECSuccess) {
goto loser;
}
@@ -2327,7 +2328,7 @@ tls13_HandleCertificateEntry(sslSocket *ss, SECItem *data, PRBool first,
* Caller must hold Handshake and RecvBuf locks.
*/
static SECStatus
-tls13_HandleCertificate(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
+tls13_HandleCertificate(sslSocket *ss, PRUint8 *b, PRUint32 length)
{
SECStatus rv;
SECItem context = { siBuffer, NULL, 0 };
@@ -2758,7 +2759,7 @@ tls13_SetCipherSpec(sslSocket *ss, TrafficKeyType type,
if ((*specp)->epoch == PR_UINT16_MAX) {
return SECFailure;
}
- spec->epoch = (*specp)->epoch + 1;
+ spec->epoch = (PRUint16)type;
if (!IS_DTLS(ss)) {
spec->read_seq_num = spec->write_seq_num = 0;
@@ -2770,6 +2771,11 @@ tls13_SetCipherSpec(sslSocket *ss, TrafficKeyType type,
dtls_InitRecvdRecords(&spec->recvdRecords);
}
+ if (type == TrafficKeyEarlyApplicationData) {
+ spec->earlyDataRemaining =
+ ss->sec.ci.sid->u.ssl3.locked.sessionTicket.max_early_data_size;
+ }
+
/* Now that we've set almost everything up, finally cut over. */
ssl_GetSpecWriteLock(ss);
tls13_CipherSpecRelease(*specp); /* May delete old cipher. */
@@ -2781,6 +2787,10 @@ tls13_SetCipherSpec(sslSocket *ss, TrafficKeyType type,
spec->phase, spec->epoch,
direction == CipherSpecRead ? "read" : "write"));
+ if (ss->ssl3.changedCipherSpecFunc) {
+ ss->ssl3.changedCipherSpecFunc(ss->ssl3.changedCipherSpecArg,
+ direction == CipherSpecWrite, spec);
+ }
return SECSuccess;
}
@@ -2929,6 +2939,7 @@ tls13_WriteNonce(ssl3KeyMaterial *keys,
for (i = 0; i < 8; ++i) {
nonce[4 + i] ^= seqNumBuf[i];
}
+ PRINT_BUF(50, (NULL, "Nonce", nonce, nonceLen));
}
/* Implement the SSLAEADCipher interface defined in sslimpl.h.
@@ -3015,10 +3026,10 @@ tls13_ChaCha20Poly1305(ssl3KeyMaterial *keys, PRBool doDecrypt,
}
static SECStatus
-tls13_HandleEncryptedExtensions(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
+tls13_HandleEncryptedExtensions(sslSocket *ss, PRUint8 *b, PRUint32 length)
{
SECStatus rv;
- PRInt32 innerLength;
+ PRUint32 innerLength;
SECItem oldNpn = { siBuffer, NULL, 0 };
PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
@@ -3033,8 +3044,8 @@ tls13_HandleEncryptedExtensions(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
return SECFailure;
}
- innerLength = ssl3_ConsumeHandshakeNumber(ss, 2, &b, &length);
- if (innerLength < 0) {
+ rv = ssl3_ConsumeHandshakeNumber(ss, &innerLength, 2, &b, &length);
+ if (rv != SECSuccess) {
return SECFailure; /* Alert already sent. */
}
if (innerLength != length) {
@@ -3227,7 +3238,7 @@ done:
* Caller must hold Handshake and RecvBuf locks.
*/
SECStatus
-tls13_HandleCertificateVerify(sslSocket *ss, SSL3Opaque *b, PRUint32 length,
+tls13_HandleCertificateVerify(sslSocket *ss, PRUint8 *b, PRUint32 length,
SSL3Hashes *hashes)
{
SECItem signed_hash = { siBuffer, NULL, 0 };
@@ -3286,16 +3297,7 @@ tls13_HandleCertificateVerify(sslSocket *ss, SSL3Opaque *b, PRUint32 length,
/* Set the auth type. */
if (!ss->sec.isServer) {
- switch (ssl_SignatureSchemeToKeyType(sigScheme)) {
- case rsaKey:
- ss->sec.authType = ssl_auth_rsa_sign;
- break;
- case ecKey:
- ss->sec.authType = ssl_auth_ecdsa;
- break;
- default:
- PORT_Assert(PR_FALSE);
- }
+ ss->sec.authType = ssl_SignatureSchemeToAuthType(sigScheme);
}
/* Request a client certificate now if one was requested. */
@@ -3477,7 +3479,7 @@ tls13_SendFinished(sslSocket *ss, PK11SymKey *baseKey)
static SECStatus
tls13_VerifyFinished(sslSocket *ss, SSL3HandshakeType message,
PK11SymKey *secret,
- SSL3Opaque *b, PRUint32 length,
+ PRUint8 *b, PRUint32 length,
const SSL3Hashes *hashes)
{
SECStatus rv;
@@ -3515,7 +3517,7 @@ tls13_VerifyFinished(sslSocket *ss, SSL3HandshakeType message,
}
static SECStatus
-tls13_ClientHandleFinished(sslSocket *ss, SSL3Opaque *b, PRUint32 length,
+tls13_ClientHandleFinished(sslSocket *ss, PRUint8 *b, PRUint32 length,
const SSL3Hashes *hashes)
{
SECStatus rv;
@@ -3542,7 +3544,7 @@ tls13_ClientHandleFinished(sslSocket *ss, SSL3Opaque *b, PRUint32 length,
}
static SECStatus
-tls13_ServerHandleFinished(sslSocket *ss, SSL3Opaque *b, PRUint32 length,
+tls13_ServerHandleFinished(sslSocket *ss, PRUint8 *b, PRUint32 length,
const SSL3Hashes *hashes)
{
SECStatus rv;
@@ -3715,17 +3717,10 @@ tls13_SendClientSecondRound(sslSocket *ss)
return SECWouldBlock;
}
- if (ss->ssl3.hs.zeroRttState != ssl_0rtt_none) {
- if (ss->ssl3.hs.zeroRttState == ssl_0rtt_accepted) {
- rv = tls13_SendEndOfEarlyData(ss);
- if (rv != SECSuccess) {
- return SECFailure; /* Error code already set. */
- }
- }
- if (IS_DTLS(ss) && !ss->ssl3.hs.helloRetry) {
- /* Reset the counters so that the next epoch isn't set
- * incorrectly. */
- tls13_SetNullCipherSpec(ss, &ss->ssl3.cwSpec);
+ if (ss->ssl3.hs.zeroRttState == ssl_0rtt_accepted) {
+ rv = tls13_SendEndOfEarlyData(ss);
+ if (rv != SECSuccess) {
+ return SECFailure; /* Error code already set. */
}
}
@@ -3787,7 +3782,7 @@ tls13_SendClientSecondRound(sslSocket *ss)
* } NewSessionTicket;
*/
-#define MAX_EARLY_DATA_SIZE (2 << 16) /* Arbitrary limit. */
+PRUint32 ssl_max_early_data_size = (2 << 16); /* Arbitrary limit. */
SECStatus
tls13_SendNewSessionTicket(sslSocket *ss)
@@ -3802,7 +3797,7 @@ tls13_SendNewSessionTicket(sslSocket *ss)
ticket.flags |= ticket_allow_early_data;
max_early_data_size_len = 8; /* type + len + value. */
}
- ticket.ticket_lifetime_hint = TLS_EX_SESS_TICKET_LIFETIME_HINT;
+ ticket.ticket_lifetime_hint = ssl_ticket_lifetime;
rv = ssl3_EncodeSessionTicket(ss, &ticket, &ticket_data);
if (rv != SECSuccess)
@@ -3821,7 +3816,7 @@ tls13_SendNewSessionTicket(sslSocket *ss)
goto loser;
/* This is a fixed value. */
- rv = ssl3_AppendHandshakeNumber(ss, TLS_EX_SESS_TICKET_LIFETIME_HINT, 4);
+ rv = ssl3_AppendHandshakeNumber(ss, ssl_ticket_lifetime, 4);
if (rv != SECSuccess)
goto loser;
@@ -3857,7 +3852,7 @@ tls13_SendNewSessionTicket(sslSocket *ss)
if (rv != SECSuccess)
goto loser;
- rv = ssl3_AppendHandshakeNumber(ss, MAX_EARLY_DATA_SIZE, 4);
+ rv = ssl3_AppendHandshakeNumber(ss, ssl_max_early_data_size, 4);
if (rv != SECSuccess)
goto loser;
}
@@ -3873,10 +3868,9 @@ loser:
}
static SECStatus
-tls13_HandleNewSessionTicket(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
+tls13_HandleNewSessionTicket(sslSocket *ss, PRUint8 *b, PRUint32 length)
{
SECStatus rv;
- PRInt32 tmp;
PRUint32 utmp;
NewSessionTicket ticket = { 0 };
SECItem data;
@@ -3896,14 +3890,14 @@ tls13_HandleNewSessionTicket(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
return SECFailure;
}
- ticket.received_timestamp = ssl_Time();
- tmp = ssl3_ConsumeHandshakeNumber(ss, 4, &b, &length);
- if (tmp < 0) {
+ ticket.received_timestamp = PR_Now();
+ rv = ssl3_ConsumeHandshakeNumber(ss, &ticket.ticket_lifetime_hint, 4, &b,
+ &length);
+ if (rv != SECSuccess) {
FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_NEW_SESSION_TICKET,
decode_error);
return SECFailure;
}
- ticket.ticket_lifetime_hint = (PRUint32)tmp;
ticket.ticket.type = siBuffer;
rv = ssl3_ConsumeHandshake(ss, &utmp, sizeof(utmp),
@@ -4042,7 +4036,8 @@ tls13_ExtensionAllowed(PRUint16 extension, SSL3HandshakeType message)
(message == hello_retry_request) ||
(message == encrypted_extensions) ||
(message == new_session_ticket) ||
- (message == certificate));
+ (message == certificate) ||
+ (message == certificate_request));
for (i = 0; i < PR_ARRAY_SIZE(KnownExtensions); i++) {
if (KnownExtensions[i].ex_value == extension)
@@ -4102,11 +4097,33 @@ tls13_FormatAdditionalData(PRUint8 *aad, unsigned int length,
PORT_Assert((ptr - aad) == length);
}
+PRInt32
+tls13_LimitEarlyData(sslSocket *ss, SSL3ContentType type, PRInt32 toSend)
+{
+ PRInt32 reduced;
+
+ PORT_Assert(type == content_application_data);
+ PORT_Assert(ss->vrange.max >= SSL_LIBRARY_VERSION_TLS_1_3);
+ PORT_Assert(!ss->firstHsDone);
+ if (ss->ssl3.cwSpec->epoch != TrafficKeyEarlyApplicationData) {
+ return toSend;
+ }
+
+ if (IS_DTLS(ss) && toSend > ss->ssl3.cwSpec->earlyDataRemaining) {
+ /* Don't split application data records in DTLS. */
+ return 0;
+ }
+
+ reduced = PR_MIN(toSend, ss->ssl3.cwSpec->earlyDataRemaining);
+ ss->ssl3.cwSpec->earlyDataRemaining -= reduced;
+ return reduced;
+}
+
SECStatus
tls13_ProtectRecord(sslSocket *ss,
ssl3CipherSpec *cwSpec,
SSL3ContentType type,
- const SSL3Opaque *pIn,
+ const PRUint8 *pIn,
PRUint32 contentLen,
sslBuffer *wrBuf)
{
@@ -4253,6 +4270,17 @@ tls13_UnprotectRecord(sslSocket *ss, SSL3Ciphertext *cText, sslBuffer *plaintext
cText->type = plaintext->buf[plaintext->len - 1];
--plaintext->len;
+ /* Check that we haven't received too much 0-RTT data. */
+ if (crSpec->epoch == TrafficKeyEarlyApplicationData &&
+ cText->type == content_application_data) {
+ if (plaintext->len > crSpec->earlyDataRemaining) {
+ *alert = unexpected_message;
+ PORT_SetError(SSL_ERROR_TOO_MUCH_EARLY_DATA);
+ return SECFailure;
+ }
+ crSpec->earlyDataRemaining -= plaintext->len;
+ }
+
SSL_TRC(10,
("%d: TLS13[%d]: %s received record of length=%d type=%d",
SSL_GETPID(), ss->fd, SSL_ROLE(ss),
@@ -4288,7 +4316,7 @@ tls13_ClientAllow0Rtt(const sslSocket *ss, const sslSessionID *sid)
return PR_FALSE;
if ((sid->u.ssl3.locked.sessionTicket.flags & ticket_allow_early_data) == 0)
return PR_FALSE;
- return tls13_AlpnTagAllowed(ss, &sid->u.ssl3.alpnSelection);
+ return ssl_AlpnTagAllowed(ss, &sid->u.ssl3.alpnSelection);
}
SECStatus
@@ -4317,15 +4345,8 @@ tls13_MaybeDo0RTTHandshake(sslSocket *ss)
return rv;
}
- /* Null spec... */
- ssl_GetSpecReadLock(ss);
- ss->ssl3.hs.nullSpec = ss->ssl3.cwSpec;
- tls13_CipherSpecAddRef(ss->ssl3.hs.nullSpec);
- ssl_ReleaseSpecReadLock(ss);
-
/* Cipher suite already set in tls13_SetupClientHello. */
- ss->ssl3.hs.preliminaryInfo = 0; /* TODO(ekr@rtfm.com) Fill this in.
- * bug 1281255. */
+ ss->ssl3.hs.preliminaryInfo = 0;
rv = tls13_DeriveSecret(ss, ss->ssl3.hs.currentSecret,
kHkdfLabelClient,
@@ -4366,21 +4387,6 @@ tls13_Read0RttData(sslSocket *ss, void *buf, PRInt32 len)
return len;
}
-/* 0-RTT data will be followed by a different cipher spec; this resets the
- * current spec to the null spec so that the following state can be set as
- * though 0-RTT didn't happen. TODO: work out if this is the best plan. */
-static void
-tls13_SetNullCipherSpec(sslSocket *ss, ssl3CipherSpec **specp)
-{
- PORT_Assert(ss->ssl3.hs.nullSpec);
-
- ssl_GetSpecWriteLock(ss);
- tls13_CipherSpecRelease(*specp);
- *specp = ss->ssl3.hs.nullSpec;
- ssl_ReleaseSpecWriteLock(ss);
- ss->ssl3.hs.nullSpec = NULL;
-}
-
static SECStatus
tls13_SendEndOfEarlyData(sslSocket *ss)
{
@@ -4413,11 +4419,6 @@ tls13_HandleEndOfEarlyData(sslSocket *ss)
PORT_Assert(TLS13_IN_HS_STATE(ss, ss->opt.requestCertificate ? wait_client_cert : wait_finished));
- if (IS_DTLS(ss)) {
- /* Reset the cipher spec so that the epoch counter is properly reset. */
- tls13_SetNullCipherSpec(ss, &ss->ssl3.crSpec);
- }
-
rv = tls13_SetCipherSpec(ss, TrafficKeyHandshake,
CipherSpecRead, PR_FALSE);
if (rv != SECSuccess) {