diff options
author | Moonchild <mcwerewolf@gmail.com> | 2018-02-06 12:02:47 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-02-06 12:02:47 +0100 |
commit | 389c60da5e01761f4a11ef539ffa26e4c1b17875 (patch) | |
tree | c6033924a0de9be1ab140596e305898c651bf57e /security/nss/lib/ssl/tls13con.c | |
parent | 7c9b585349c985df0cf6ace83da5dadba8b5c677 (diff) | |
parent | f017b749ea9f1586d2308504553d40bf4cc5439d (diff) | |
download | UXP-389c60da5e01761f4a11ef539ffa26e4c1b17875.tar UXP-389c60da5e01761f4a11ef539ffa26e4c1b17875.tar.gz UXP-389c60da5e01761f4a11ef539ffa26e4c1b17875.tar.lz UXP-389c60da5e01761f4a11ef539ffa26e4c1b17875.tar.xz UXP-389c60da5e01761f4a11ef539ffa26e4c1b17875.zip |
Merge pull request #13 from MoonchildProductions/ported-upstream
Ported upstream
Diffstat (limited to 'security/nss/lib/ssl/tls13con.c')
-rw-r--r-- | security/nss/lib/ssl/tls13con.c | 315 |
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) { |