diff --git a/fuzz/tls_mutators.cc b/fuzz/tls_mutators.cc index e9770cb39f..1b77bc118e 100644 --- a/fuzz/tls_mutators.cc +++ b/fuzz/tls_mutators.cc @@ -6,7 +6,9 @@ #include "tls_parser.h" #include "ssl.h" +extern "C" { #include "sslimpl.h" +} using namespace nss_test; diff --git a/gtests/ssl_gtest/libssl_internals.c b/gtests/ssl_gtest/libssl_internals.c index 97b8354aec..2187547c14 100644 --- a/gtests/ssl_gtest/libssl_internals.c +++ b/gtests/ssl_gtest/libssl_internals.c @@ -351,30 +351,6 @@ unsigned char *SSLInt_CipherSpecToIv(PRBool isServer, ssl3CipherSpec *spec) { return GetKeyingMaterial(isServer, spec)->write_iv; } -SECStatus SSLInt_EnableShortHeaders(PRFileDesc *fd) { - sslSocket *ss; - - ss = ssl_FindSocket(fd); - if (!ss) { - return SECFailure; - } - - ss->opt.enableShortHeaders = PR_TRUE; - return SECSuccess; -} - -SECStatus SSLInt_UsingShortHeaders(PRFileDesc *fd, PRBool *result) { - sslSocket *ss; - - ss = ssl_FindSocket(fd); - if (!ss) { - return SECFailure; - } - - *result = ss->ssl3.hs.shortHeaders; - return SECSuccess; -} - void SSLInt_SetTicketLifetime(uint32_t lifetime) { ssl_ticket_lifetime = lifetime; } diff --git a/gtests/ssl_gtest/libssl_internals.h b/gtests/ssl_gtest/libssl_internals.h index 33709c4b4e..c1b484aa83 100644 --- a/gtests/ssl_gtest/libssl_internals.h +++ b/gtests/ssl_gtest/libssl_internals.h @@ -48,8 +48,6 @@ PK11SymKey *SSLInt_CipherSpecToKey(PRBool isServer, ssl3CipherSpec *spec); SSLCipherAlgorithm SSLInt_CipherSpecToAlgorithm(PRBool isServer, ssl3CipherSpec *spec); unsigned char *SSLInt_CipherSpecToIv(PRBool isServer, ssl3CipherSpec *spec); -SECStatus SSLInt_EnableShortHeaders(PRFileDesc *fd); -SECStatus SSLInt_UsingShortHeaders(PRFileDesc *fd, PRBool *result); void SSLInt_SetTicketLifetime(uint32_t lifetime); void SSLInt_SetMaxEarlyDataSize(uint32_t size); SECStatus SSLInt_SetSocketMaxEarlyDataSize(PRFileDesc *fd, uint32_t size); diff --git a/gtests/ssl_gtest/ssl_loopback_unittest.cc b/gtests/ssl_gtest/ssl_loopback_unittest.cc index 77703dd8ef..65633c7421 100644 --- a/gtests/ssl_gtest/ssl_loopback_unittest.cc +++ b/gtests/ssl_gtest/ssl_loopback_unittest.cc @@ -315,14 +315,6 @@ TEST_F(TlsConnectStreamTls13, Tls13FailedWriteSecondFlight) { client_->CheckErrorCode(SSL_ERROR_SOCKET_WRITE_FAILURE); } -TEST_F(TlsConnectStreamTls13, NegotiateShortHeaders) { - client_->SetShortHeadersEnabled(); - server_->SetShortHeadersEnabled(); - client_->ExpectShortHeaders(); - server_->ExpectShortHeaders(); - Connect(); -} - INSTANTIATE_TEST_CASE_P( GenericStream, TlsConnectGeneric, ::testing::Combine(TlsConnectTestBase::kTlsVariantsStream, diff --git a/gtests/ssl_gtest/tls_agent.cc b/gtests/ssl_gtest/tls_agent.cc index 9e8dab1399..f05bec6e82 100644 --- a/gtests/ssl_gtest/tls_agent.cc +++ b/gtests/ssl_gtest/tls_agent.cc @@ -73,7 +73,6 @@ TlsAgent::TlsAgent(const std::string& name, Role role, handshake_callback_(), auth_certificate_callback_(), sni_callback_(), - expect_short_headers_(false), skip_version_checks_(false) { memset(&info_, 0, sizeof(info_)); memset(&csinfo_, 0, sizeof(csinfo_)); @@ -407,13 +406,6 @@ void TlsAgent::SetFallbackSCSVEnabled(bool en) { EXPECT_EQ(SECSuccess, rv); } -void TlsAgent::SetShortHeadersEnabled() { - EXPECT_TRUE(EnsureTlsSetup()); - - SECStatus rv = SSLInt_EnableShortHeaders(ssl_fd()); - EXPECT_EQ(SECSuccess, rv); -} - void TlsAgent::SetVersionRange(uint16_t minver, uint16_t maxver) { vrange_.min = minver; vrange_.max = maxver; @@ -437,8 +429,6 @@ void TlsAgent::SetServerKeyBits(uint16_t bits) { server_key_bits_ = bits; } void TlsAgent::ExpectReadWriteError() { expect_readwrite_error_ = true; } -void TlsAgent::ExpectShortHeaders() { expect_short_headers_ = true; } - void TlsAgent::SkipVersionChecks() { skip_version_checks_ = true; } void TlsAgent::SetSignatureSchemes(const SSLSignatureScheme* schemes, @@ -764,10 +754,6 @@ void TlsAgent::Connected() { } } - PRBool short_headers; - rv = SSLInt_UsingShortHeaders(ssl_fd(), &short_headers); - EXPECT_EQ(SECSuccess, rv); - EXPECT_EQ((PRBool)expect_short_headers_, short_headers); SetState(STATE_CONNECTED); } diff --git a/gtests/ssl_gtest/tls_agent.h b/gtests/ssl_gtest/tls_agent.h index 4bccb9a849..285845b91b 100644 --- a/gtests/ssl_gtest/tls_agent.h +++ b/gtests/ssl_gtest/tls_agent.h @@ -126,7 +126,6 @@ class TlsAgent : public PollTarget { void SetSessionCacheEnabled(bool en); void Set0RttEnabled(bool en); void SetFallbackSCSVEnabled(bool en); - void SetShortHeadersEnabled(); void SetVersionRange(uint16_t minver, uint16_t maxver); void GetVersionRange(uint16_t* minver, uint16_t* maxver); void CheckPreliminaryInfo(); @@ -136,7 +135,6 @@ class TlsAgent : public PollTarget { void ExpectReadWriteError(); void EnableFalseStart(); void ExpectResumption(); - void ExpectShortHeaders(); void SkipVersionChecks(); void SetSignatureSchemes(const SSLSignatureScheme* schemes, size_t count); void EnableAlpn(const uint8_t* val, size_t len); @@ -388,7 +386,6 @@ class TlsAgent : public PollTarget { HandshakeCallbackFunction handshake_callback_; AuthCertificateCallbackFunction auth_certificate_callback_; SniCallbackFunction sni_callback_; - bool expect_short_headers_; bool skip_version_checks_; }; diff --git a/lib/ssl/dtlscon.c b/lib/ssl/dtlscon.c index fbd1779dbb..ba28a4708d 100644 --- a/lib/ssl/dtlscon.c +++ b/lib/ssl/dtlscon.c @@ -346,7 +346,7 @@ dtls_HandleHandshake(sslSocket *ss, sslBuffer *origBuf) (fragment_offset == 0) && (fragment_length == message_length)) { /* Complete next message. Process immediately */ - ss->ssl3.hs.msg_type = (SSL3HandshakeType)type; + ss->ssl3.hs.msg_type = (SSLHandshakeType)type; ss->ssl3.hs.msg_len = message_length; rv = dtls_HandleHandshakeMessage(ss, buf.buf, @@ -391,7 +391,7 @@ dtls_HandleHandshake(sslSocket *ss, sslBuffer *origBuf) ss->ssl3.hs.recvdHighWater = 0; PORT_Memset(ss->ssl3.hs.recvdFragments.buf, 0, ss->ssl3.hs.recvdFragments.space); - ss->ssl3.hs.msg_type = (SSL3HandshakeType)type; + ss->ssl3.hs.msg_type = (SSLHandshakeType)type; ss->ssl3.hs.msg_len = message_length; } diff --git a/lib/ssl/manifest.mn b/lib/ssl/manifest.mn index fbb88baffa..91fcfa763a 100644 --- a/lib/ssl/manifest.mn +++ b/lib/ssl/manifest.mn @@ -25,7 +25,7 @@ CSRCS = \ sslauth.c \ sslcon.c \ ssldef.c \ - ssl3encode.c \ + sslencode.c \ sslenum.c \ sslerr.c \ sslerrstrs.c \ diff --git a/lib/ssl/selfencrypt.c b/lib/ssl/selfencrypt.c index 6d6e25cfc6..8c9e374b03 100644 --- a/lib/ssl/selfencrypt.c +++ b/lib/ssl/selfencrypt.c @@ -11,7 +11,7 @@ #include "pk11func.h" #include "ssl.h" #include "sslt.h" -#include "ssl3encode.h" +#include "sslencode.h" #include "sslimpl.h" #include "selfencrypt.h" diff --git a/lib/ssl/ssl.gyp b/lib/ssl/ssl.gyp index 03b2d6014a..ea360f6671 100644 --- a/lib/ssl/ssl.gyp +++ b/lib/ssl/ssl.gyp @@ -17,7 +17,6 @@ 'selfencrypt.c', 'ssl3con.c', 'ssl3ecc.c', - 'ssl3encode.c', 'ssl3ext.c', 'ssl3exthandle.c', 'ssl3gthr.c', @@ -25,6 +24,7 @@ 'sslcert.c', 'sslcon.c', 'ssldef.c', + 'sslencode.c', 'sslenum.c', 'sslerr.c', 'sslerrstrs.c', diff --git a/lib/ssl/ssl3con.c b/lib/ssl/ssl3con.c index 23e8d2ec54..ca37ae9160 100644 --- a/lib/ssl/ssl3con.c +++ b/lib/ssl/ssl3con.c @@ -554,49 +554,49 @@ ssl3_DecodeHandshakeType(int msgType) static char line[40]; switch (msgType) { - case hello_request: + case ssl_hs_hello_request: rv = "hello_request (0)"; break; - case client_hello: + case ssl_hs_client_hello: rv = "client_hello (1)"; break; - case server_hello: + case ssl_hs_server_hello: rv = "server_hello (2)"; break; - case hello_verify_request: + case ssl_hs_hello_verify_request: rv = "hello_verify_request (3)"; break; - case new_session_ticket: + case ssl_hs_new_session_ticket: rv = "session_ticket (4)"; break; - case end_of_early_data: + case ssl_hs_end_of_early_data: rv = "end_of_early_data (5)"; break; - case hello_retry_request: + case ssl_hs_hello_retry_request: rv = "hello_retry_request (6)"; break; - case encrypted_extensions: + case ssl_hs_encrypted_extensions: rv = "encrypted_extensions (8)"; break; - case certificate: + case ssl_hs_certificate: rv = "certificate (11)"; break; - case server_key_exchange: + case ssl_hs_server_key_exchange: rv = "server_key_exchange (12)"; break; - case certificate_request: + case ssl_hs_certificate_request: rv = "certificate_request (13)"; break; - case server_hello_done: + case ssl_hs_server_hello_done: rv = "server_hello_done (14)"; break; - case certificate_verify: + case ssl_hs_certificate_verify: rv = "certificate_verify (15)"; break; - case client_key_exchange: + case ssl_hs_client_key_exchange: rv = "client_key_exchange (16)"; break; - case finished: + case ssl_hs_finished: rv = "finished (20)"; break; default: @@ -2550,13 +2550,7 @@ ssl_ProtectRecord(sslSocket *ss, ssl3CipherSpec *cwSpec, PRUint8 *ptr = wrBuf->buf; SECStatus rv; - if (ss->ssl3.hs.shortHeaders) { - PORT_Assert(!IS_DTLS(ss)); - PORT_Assert(ss->version >= SSL_LIBRARY_VERSION_TLS_1_3); - headerLen = TLS13_RECORD_HEADER_LENGTH_SHORT; - } else { - headerLen = IS_DTLS(ss) ? DTLS_RECORD_HEADER_LENGTH : SSL3_RECORD_HEADER_LENGTH; - } + headerLen = IS_DTLS(ss) ? DTLS_RECORD_HEADER_LENGTH : SSL3_RECORD_HEADER_LENGTH; protBuf.buf = wrBuf->buf + headerLen; protBuf.len = 0; protBuf.space = wrBuf->space - headerLen; @@ -2590,33 +2584,28 @@ ssl_ProtectRecord(sslSocket *ss, ssl3CipherSpec *cwSpec, PORT_Assert(protBuf.len <= MAX_FRAGMENT_LENGTH + (isTLS13 ? 256 : 1024)); wrBuf->len = protBuf.len + headerLen; - if (ss->ssl3.hs.shortHeaders) { - PORT_Assert(!IS_DTLS(ss)); /* Decoder not yet implemented. */ - (void)ssl_EncodeUintX(0x8000 | protBuf.len, 2, ptr); - } else { #ifndef UNSAFE_FUZZER_MODE - if (isTLS13 && cipher_def->calg != ssl_calg_null) { - *ptr++ = content_application_data; - } else + if (isTLS13 && cipher_def->calg != ssl_calg_null) { + *ptr++ = content_application_data; + } else #endif - { - *ptr++ = type; - } + { + *ptr++ = type; + } - if (IS_DTLS(ss)) { - version = isTLS13 ? SSL_LIBRARY_VERSION_TLS_1_1 : version; - version = dtls_TLSVersionToDTLSVersion(version); + if (IS_DTLS(ss)) { + version = isTLS13 ? SSL_LIBRARY_VERSION_TLS_1_1 : version; + version = dtls_TLSVersionToDTLSVersion(version); - ptr = ssl_EncodeUintX(version, 2, ptr); - ptr = ssl_EncodeUintX(cwSpec->write_seq_num, 8, ptr); - } else { - if (capRecordVersion || isTLS13) { - version = PR_MIN(SSL_LIBRARY_VERSION_TLS_1_0, version); - } - ptr = ssl_EncodeUintX(version, 2, ptr); + ptr = ssl_EncodeUintX(version, 2, ptr); + ptr = ssl_EncodeUintX(cwSpec->write_seq_num, 8, ptr); + } else { + if (capRecordVersion || isTLS13) { + version = PR_MIN(SSL_LIBRARY_VERSION_TLS_1_0, version); } - (void)ssl_EncodeUintX(protBuf.len, 2, ptr); + ptr = ssl_EncodeUintX(version, 2, ptr); } + (void)ssl_EncodeUintX(protBuf.len, 2, ptr); ++cwSpec->write_seq_num; return SECSuccess; @@ -4143,7 +4132,7 @@ ssl3_UpdateHandshakeHashes(sslSocket *ss, const unsigned char *b, unsigned int l * Most rely on ssl3_AppendHandshake to set the error code. **************************************************************************/ SECStatus -ssl3_AppendHandshake(sslSocket *ss, const void *void_src, PRInt32 bytes) +ssl3_AppendHandshake(sslSocket *ss, const void *void_src, unsigned int bytes) { unsigned char *src = (unsigned char *)void_src; int room = ss->sec.ci.sendBuf.space - ss->sec.ci.sendBuf.len; @@ -4186,36 +4175,17 @@ ssl3_AppendHandshake(sslSocket *ss, const void *void_src, PRInt32 bytes) } SECStatus -ssl3_AppendHandshakeNumber(sslSocket *ss, PRInt32 num, PRInt32 lenSize) +ssl3_AppendHandshakeNumber(sslSocket *ss, PRUint64 num, unsigned int lenSize) { - SECStatus rv; - PRUint8 b[4]; - PRUint8 *p = b; - - PORT_Assert(lenSize <= 4 && lenSize > 0); - if (lenSize < 4 && num >= (1L << (lenSize * 8))) { - PORT_SetError(SSL_ERROR_TX_RECORD_TOO_LONG); - return SECFailure; - } - - switch (lenSize) { - case 4: - *p++ = (num >> 24) & 0xff; - case 3: - *p++ = (num >> 16) & 0xff; - case 2: - *p++ = (num >> 8) & 0xff; - case 1: - *p = num & 0xff; - } + PRUint8 b[sizeof(num)]; SSL_TRC(60, ("%d: number:", SSL_GETPID())); - rv = ssl3_AppendHandshake(ss, &b[0], lenSize); - return rv; /* error code set by AppendHandshake, if applicable. */ + (void)ssl_EncodeUintX(num, lenSize, b); + return ssl3_AppendHandshake(ss, b, lenSize); } SECStatus ssl3_AppendHandshakeVariable( - sslSocket *ss, const PRUint8 *src, PRInt32 bytes, PRInt32 lenSize) + sslSocket *ss, const PRUint8 *src, unsigned int bytes, unsigned int lenSize) { SECStatus rv; @@ -4234,7 +4204,20 @@ ssl3_AppendHandshakeVariable( } SECStatus -ssl3_AppendHandshakeHeader(sslSocket *ss, SSL3HandshakeType t, PRUint32 length) +ssl3_AppendBufferToHandshake(sslSocket *ss, sslBuffer *buf) +{ + return ssl3_AppendHandshake(ss, buf->buf, buf->len); +} + +SECStatus +ssl3_AppendBufferToHandshakeVariable(sslSocket *ss, sslBuffer *buf, + unsigned int lenSize) +{ + return ssl3_AppendHandshakeVariable(ss, buf->buf, buf->len, lenSize); +} + +SECStatus +ssl3_AppendHandshakeHeader(sslSocket *ss, SSLHandshakeType t, PRUint32 length) { SECStatus rv; @@ -4946,7 +4929,8 @@ ssl3_SendClientHello(sslSocket *ss, sslClientHelloType type) int actual_count = 0; PRBool isTLS = PR_FALSE; PRBool requestingResume = PR_FALSE, fallbackSCSV = PR_FALSE; - PRInt32 total_exten_len = 0; + PRBool unlockNeeded = PR_FALSE; + sslBuffer extensionBuf = { NULL, 0, 0 }; unsigned numCompressionMethods; PRUint16 version; PRInt32 flags; @@ -5172,9 +5156,10 @@ ssl3_SendClientHello(sslSocket *ss, sslClientHelloType type) * NewSessionTicket that will cause the ticket in the sid to be replaced. * Once we've copied the session ticket into our ClientHello message, it * is OK for the ticket to change, so we just need to make sure we hold - * the lock across the calls to ssl3_CallHelloExtensionSenders. + * the lock across the calls to ssl_ConstructExtensions. */ if (sid->u.ssl3.lock) { + unlockNeeded = PR_TRUE; PR_RWLock_Rlock(sid->u.ssl3.lock); } @@ -5182,24 +5167,14 @@ ssl3_SendClientHello(sslSocket *ss, sslClientHelloType type) type == client_hello_initial) { rv = tls13_SetupClientHello(ss); if (rv != SECSuccess) { - return SECFailure; + goto loser; } } if (isTLS || (ss->firstHsDone && ss->peerRequestedProtection)) { - PRUint32 maxBytes = 65535; /* 2^16 - 1 */ - PRInt32 extLen; - - extLen = ssl3_CallHelloExtensionSenders(ss, PR_FALSE, maxBytes, NULL); - if (extLen < 0) { - if (sid->u.ssl3.lock) { - PR_RWLock_Unlock(sid->u.ssl3.lock); - } - return SECFailure; + rv = ssl_ConstructExtensions(ss, &extensionBuf, ssl_hs_client_hello); + if (rv != SECSuccess) { + goto loser; } - total_exten_len += extLen; - - if (total_exten_len > 0) - total_exten_len += 2; } if (IS_DTLS(ss)) { @@ -5209,10 +5184,7 @@ ssl3_SendClientHello(sslSocket *ss, sslClientHelloType type) /* how many suites are permitted by policy and user preference? */ num_suites = count_cipher_suites(ss, ss->ssl3.policy); if (!num_suites) { - if (sid->u.ssl3.lock) { - PR_RWLock_Unlock(sid->u.ssl3.lock); - } - return SECFailure; /* count_cipher_suites has set error code. */ + goto loser; /* count_cipher_suites has set error code. */ } fallbackSCSV = ss->opt.enableFallbackSCSV && (!requestingResume || @@ -5237,25 +5209,22 @@ ssl3_SendClientHello(sslSocket *ss, sslClientHelloType type) ? 0 : sid->u.ssl3.sessionIDLength) + 2 + num_suites * sizeof(ssl3CipherSuite) + - 1 + numCompressionMethods + total_exten_len; + 1 + numCompressionMethods; if (IS_DTLS(ss)) { length += 1 + ss->ssl3.hs.cookie.len; } - if (total_exten_len > 0) { - ssl3_CalculatePaddingExtLen(ss, length); - if (ss->xtnData.paddingLen) { - total_exten_len += 4 + ss->xtnData.paddingLen; - length += 4 + ss->xtnData.paddingLen; + if (extensionBuf.len) { + rv = ssl_InsertPaddingExtension(ss, length, &extensionBuf); + if (rv != SECSuccess) { + goto loser; /* err set by ssl_InsertPaddingExtension */ } + length += 2 + extensionBuf.len; } - rv = ssl3_AppendHandshakeHeader(ss, client_hello, length); + rv = ssl3_AppendHandshakeHeader(ss, ssl_hs_client_hello, length); if (rv != SECSuccess) { - if (sid->u.ssl3.lock) { - PR_RWLock_Unlock(sid->u.ssl3.lock); - } - return rv; /* err set by ssl3_AppendHandshake* */ + goto loser; /* err set by ssl3_AppendHandshake* */ } if (ss->firstHsDone) { @@ -5273,29 +5242,20 @@ ssl3_SendClientHello(sslSocket *ss, sslClientHelloType type) rv = ssl3_AppendHandshakeNumber(ss, ss->clientHelloVersion, 2); } if (rv != SECSuccess) { - if (sid->u.ssl3.lock) { - PR_RWLock_Unlock(sid->u.ssl3.lock); - } - return rv; /* err set by ssl3_AppendHandshake* */ + goto loser; /* err set by ssl3_AppendHandshake* */ } /* Generate a new random if this is the first attempt. */ if (type == client_hello_initial) { rv = ssl3_GetNewRandom(&ss->ssl3.hs.client_random); if (rv != SECSuccess) { - if (sid->u.ssl3.lock) { - PR_RWLock_Unlock(sid->u.ssl3.lock); - } - return rv; /* err set by GetNewRandom. */ + goto loser; /* err set by GetNewRandom. */ } } rv = ssl3_AppendHandshake(ss, &ss->ssl3.hs.client_random, SSL3_RANDOM_LENGTH); if (rv != SECSuccess) { - if (sid->u.ssl3.lock) { - PR_RWLock_Unlock(sid->u.ssl3.lock); - } - return rv; /* err set by ssl3_AppendHandshake* */ + goto loser; /* err set by ssl3_AppendHandshake* */ } if (sid->version < SSL_LIBRARY_VERSION_TLS_1_3) @@ -5304,29 +5264,20 @@ ssl3_SendClientHello(sslSocket *ss, sslClientHelloType type) else rv = ssl3_AppendHandshakeNumber(ss, 0, 1); if (rv != SECSuccess) { - if (sid->u.ssl3.lock) { - PR_RWLock_Unlock(sid->u.ssl3.lock); - } - return rv; /* err set by ssl3_AppendHandshake* */ + goto loser; /* err set by ssl3_AppendHandshake* */ } if (IS_DTLS(ss)) { rv = ssl3_AppendHandshakeVariable( ss, ss->ssl3.hs.cookie.data, ss->ssl3.hs.cookie.len, 1); if (rv != SECSuccess) { - if (sid->u.ssl3.lock) { - PR_RWLock_Unlock(sid->u.ssl3.lock); - } - return rv; /* err set by ssl3_AppendHandshake* */ + goto loser; /* err set by ssl3_AppendHandshake* */ } } rv = ssl3_AppendHandshakeNumber(ss, num_suites * sizeof(ssl3CipherSuite), 2); if (rv != SECSuccess) { - if (sid->u.ssl3.lock) { - PR_RWLock_Unlock(sid->u.ssl3.lock); - } - return rv; /* err set by ssl3_AppendHandshake* */ + goto loser; /* err set by ssl3_AppendHandshake* */ } if (ss->ssl3.hs.sendingSCSV) { @@ -5334,10 +5285,7 @@ ssl3_SendClientHello(sslSocket *ss, sslClientHelloType type) rv = ssl3_AppendHandshakeNumber(ss, TLS_EMPTY_RENEGOTIATION_INFO_SCSV, sizeof(ssl3CipherSuite)); if (rv != SECSuccess) { - if (sid->u.ssl3.lock) { - PR_RWLock_Unlock(sid->u.ssl3.lock); - } - return rv; /* err set by ssl3_AppendHandshake* */ + goto loser; /* err set by ssl3_AppendHandshake* */ } actual_count++; } @@ -5345,10 +5293,7 @@ ssl3_SendClientHello(sslSocket *ss, sslClientHelloType type) rv = ssl3_AppendHandshakeNumber(ss, TLS_FALLBACK_SCSV, sizeof(ssl3CipherSuite)); if (rv != SECSuccess) { - if (sid->u.ssl3.lock) { - PR_RWLock_Unlock(sid->u.ssl3.lock); - } - return rv; /* err set by ssl3_AppendHandshake* */ + goto loser; /* err set by ssl3_AppendHandshake* */ } actual_count++; } @@ -5357,20 +5302,14 @@ ssl3_SendClientHello(sslSocket *ss, sslClientHelloType type) if (config_match(suite, ss->ssl3.policy, &ss->vrange, ss)) { actual_count++; if (actual_count > num_suites) { - if (sid->u.ssl3.lock) { - PR_RWLock_Unlock(sid->u.ssl3.lock); - } /* set error card removal/insertion error */ PORT_SetError(SSL_ERROR_TOKEN_INSERTION_REMOVAL); - return SECFailure; + goto loser; } rv = ssl3_AppendHandshakeNumber(ss, suite->cipher_suite, sizeof(ssl3CipherSuite)); if (rv != SECSuccess) { - if (sid->u.ssl3.lock) { - PR_RWLock_Unlock(sid->u.ssl3.lock); - } - return rv; /* err set by ssl3_AppendHandshake* */ + goto loser; /* err set by ssl3_AppendHandshake* */ } } } @@ -5380,57 +5319,40 @@ ssl3_SendClientHello(sslSocket *ss, sslClientHelloType type) * the server.. */ if (actual_count != num_suites) { /* Card removal/insertion error */ - if (sid->u.ssl3.lock) { - PR_RWLock_Unlock(sid->u.ssl3.lock); - } PORT_SetError(SSL_ERROR_TOKEN_INSERTION_REMOVAL); - return SECFailure; + goto loser; } rv = ssl3_AppendHandshakeNumber(ss, numCompressionMethods, 1); if (rv != SECSuccess) { - if (sid->u.ssl3.lock) { - PR_RWLock_Unlock(sid->u.ssl3.lock); - } - return rv; /* err set by ssl3_AppendHandshake* */ + goto loser; /* err set by ssl3_AppendHandshake* */ } for (i = 0; i < ssl_compression_method_count; i++) { if (!ssl_CompressionEnabled(ss, ssl_compression_methods[i])) continue; rv = ssl3_AppendHandshakeNumber(ss, ssl_compression_methods[i], 1); if (rv != SECSuccess) { - if (sid->u.ssl3.lock) { - PR_RWLock_Unlock(sid->u.ssl3.lock); - } - return rv; /* err set by ssl3_AppendHandshake* */ + goto loser; /* err set by ssl3_AppendHandshake* */ } } - if (total_exten_len) { - PRUint32 maxBytes = total_exten_len - 2; - PRInt32 extLen; - - rv = ssl3_AppendHandshakeNumber(ss, maxBytes, 2); - if (rv != SECSuccess) { - if (sid->u.ssl3.lock) { - PR_RWLock_Unlock(sid->u.ssl3.lock); - } - return rv; /* err set by AppendHandshake. */ + if (extensionBuf.len) { + /* If we are sending a PSK binder, replace the dummy value. Note that + * we only set statelessResume on the client in TLS 1.3. */ + if (ss->statelessResume && + ss->xtnData.sentSessionTicketInClientHello) { + rv = tls13_WriteExtensionsWithBinder(ss, &extensionBuf); + } else { + rv = ssl3_AppendBufferToHandshakeVariable(ss, &extensionBuf, 2); } - - extLen = ssl3_CallHelloExtensionSenders(ss, PR_TRUE, maxBytes, NULL); - if (extLen < 0) { - if (sid->u.ssl3.lock) { - PR_RWLock_Unlock(sid->u.ssl3.lock); - } - return SECFailure; + if (rv != SECSuccess) { + goto loser; /* err set by AppendHandshake. */ } - maxBytes -= extLen; - - PORT_Assert(!maxBytes); } + sslBuffer_Clear(&extensionBuf); if (sid->u.ssl3.lock) { + unlockNeeded = PR_FALSE; PR_RWLock_Unlock(sid->u.ssl3.lock); } @@ -5463,6 +5385,13 @@ ssl3_SendClientHello(sslSocket *ss, sslClientHelloType type) ss->ssl3.hs.ws = wait_server_hello; return SECSuccess; + +loser: + if (unlockNeeded) { + PR_RWLock_Unlock(sid->u.ssl3.lock); + } + sslBuffer_Clear(&extensionBuf); + return SECFailure; } /* Called from ssl3_HandlePostHelloHandshakeMessage() when it has deciphered a @@ -6071,7 +6000,7 @@ ssl3_SendRSAClientKeyExchange(sslSocket *ss, SECKEYPublicKey *svrPubKey) } #endif - rv = ssl3_AppendHandshakeHeader(ss, client_key_exchange, + rv = ssl3_AppendHandshakeHeader(ss, ssl_hs_client_key_exchange, isTLS ? enc_pms.len + 2 : enc_pms.len); if (rv != SECSuccess) { @@ -6110,27 +6039,27 @@ ssl3_SendRSAClientKeyExchange(sslSocket *ss, SECKEYPublicKey *svrPubKey) /* DH shares need to be padded to the size of their prime. Some implementations * require this. TLS 1.3 also requires this. */ SECStatus -ssl_AppendPaddedDHKeyShare(const sslSocket *ss, const SECKEYPublicKey *pubKey, +ssl_AppendPaddedDHKeyShare(sslBuffer *buf, const SECKEYPublicKey *pubKey, PRBool appendLength) { SECStatus rv; unsigned int pad = pubKey->u.dh.prime.len - pubKey->u.dh.publicValue.len; if (appendLength) { - rv = ssl3_ExtAppendHandshakeNumber(ss, pubKey->u.dh.prime.len, 2); + rv = sslBuffer_AppendNumber(buf, pubKey->u.dh.prime.len, 2); if (rv != SECSuccess) { return rv; } } while (pad) { - rv = ssl3_ExtAppendHandshakeNumber(ss, 0, 1); + rv = sslBuffer_AppendNumber(buf, 0, 1); if (rv != SECSuccess) { return rv; } --pad; } - rv = ssl3_ExtAppendHandshake(ss, pubKey->u.dh.publicValue.data, - pubKey->u.dh.publicValue.len); + rv = sslBuffer_Append(buf, pubKey->u.dh.publicValue.data, + pubKey->u.dh.publicValue.len); if (rv != SECSuccess) { return rv; } @@ -6154,6 +6083,7 @@ ssl3_SendDHClientKeyExchange(sslSocket *ss, SECKEYPublicKey *svrPubKey) }; sslEphemeralKeyPair *keyPair = NULL; SECKEYPublicKey *pubKey; + sslBuffer dhBuf = { NULL, 0, 0 }; PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss)); PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss)); @@ -6213,15 +6143,19 @@ ssl3_SendDHClientKeyExchange(sslSocket *ss, SECKEYPublicKey *svrPubKey) } /* Note: send the DH share padded to avoid triggering bugs. */ - rv = ssl3_AppendHandshakeHeader(ss, client_key_exchange, + rv = ssl3_AppendHandshakeHeader(ss, ssl_hs_client_key_exchange, params->prime.len + 2); if (rv != SECSuccess) { goto loser; /* err set by ssl3_AppendHandshake* */ } - rv = ssl_AppendPaddedDHKeyShare(ss, pubKey, PR_TRUE); + rv = ssl_AppendPaddedDHKeyShare(&dhBuf, pubKey, PR_TRUE); if (rv != SECSuccess) { goto loser; /* err set by ssl_AppendPaddedDHKeyShare */ } + rv = ssl3_AppendBufferToHandshake(ss, &dhBuf); + if (rv != SECSuccess) { + goto loser; /* err set by ssl3_AppendBufferToHandshake */ + } rv = ssl3_InitPendingCipherSpec(ss, pms); if (rv != SECSuccess) { @@ -6229,6 +6163,7 @@ ssl3_SendDHClientKeyExchange(sslSocket *ss, SECKEYPublicKey *svrPubKey) goto loser; } + sslBuffer_Clear(&dhBuf); PK11_FreeSymKey(pms); ssl_FreeEphemeralKeyPair(keyPair); return SECSuccess; @@ -6238,6 +6173,7 @@ ssl3_SendDHClientKeyExchange(sslSocket *ss, SECKEYPublicKey *svrPubKey) PK11_FreeSymKey(pms); if (keyPair) ssl_FreeEphemeralKeyPair(keyPair); + sslBuffer_Clear(&dhBuf); return SECFailure; } @@ -6536,7 +6472,7 @@ ssl3_SendCertificateVerify(sslSocket *ss, SECKEYPrivateKey *privKey) len = buf.len + 2 + (isTLS12 ? 2 : 0); - rv = ssl3_AppendHandshakeHeader(ss, certificate_verify, len); + rv = ssl3_AppendHandshakeHeader(ss, ssl_hs_certificate_verify, len); if (rv != SECSuccess) { goto done; /* error code set by AppendHandshake */ } @@ -6816,7 +6752,7 @@ ssl3_HandleServerHello(sslSocket *ss, PRUint8 *b, PRUint32 length) goto alert_loser; } else { rv = ssl3_HandleExtensions(ss, &extensions.data, - &extensions.len, server_hello); + &extensions.len, ssl_hs_server_hello); if (rv != SECSuccess) goto alert_loser; } @@ -7870,7 +7806,7 @@ ssl3_SendHelloRequest(sslSocket *ss) PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss)); PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss)); - rv = ssl3_AppendHandshakeHeader(ss, hello_request, 0); + rv = ssl3_AppendHandshakeHeader(ss, ssl_hs_hello_request, 0); if (rv != SECSuccess) { return rv; /* err set by AppendHandshake */ } @@ -8202,7 +8138,7 @@ ssl3_ServerCallSNICallback(sslSocket *ss) * the name from the offered list and reconfigured the socket. */ ssl3_RegisterExtensionSender(ss, &ss->xtnData, ssl_server_name_xtn, - ssl3_SendServerNameXtn); + ssl_SendEmptyExtension); } else { /* Callback returned index outside of the boundary. */ PORT_Assert((unsigned int)ret < ss->xtnData.sniNameArrSize); @@ -8499,7 +8435,7 @@ ssl3_HandleClientHello(sslSocket *ss, PRUint8 *b, PRUint32 length) #endif /* Now parse the rest of the extensions. */ - rv = ssl3_HandleParsedExtensions(ss, client_hello); + rv = ssl3_HandleParsedExtensions(ss, ssl_hs_client_hello); if (rv != SECSuccess) { goto loser; /* malformed */ } @@ -8534,7 +8470,7 @@ ssl3_HandleClientHello(sslSocket *ss, PRUint8 *b, PRUint32 length) if (suite_i == TLS_EMPTY_RENEGOTIATION_INFO_SCSV) { PRUint8 *b2 = (PRUint8 *)emptyRIext; PRUint32 L2 = sizeof emptyRIext; - (void)ssl3_HandleExtensions(ss, &b2, &L2, client_hello); + (void)ssl3_HandleExtensions(ss, &b2, &L2, ssl_hs_client_hello); break; } } @@ -8999,9 +8935,8 @@ ssl3_HandleClientHelloPart2(sslSocket *ss, */ if (ssl3_ExtensionNegotiated(ss, ssl_session_ticket_xtn) && ssl3_KEASupportsTickets(ss->ssl3.hs.kea_def)) { - ssl3_RegisterExtensionSender(ss, &ss->xtnData, - ssl_session_ticket_xtn, - ssl3_SendSessionTicketXtn); + ssl3_RegisterExtensionSender(ss, &ss->xtnData, ssl_session_ticket_xtn, + ssl_SendEmptyExtension); } rv = ssl3_ServerCallSNICallback(ss); @@ -9222,7 +9157,7 @@ ssl3_HandleV2ClientHello(sslSocket *ss, unsigned char *buffer, int length, if (suite_i == TLS_EMPTY_RENEGOTIATION_INFO_SCSV) { PRUint8 *b2 = (PRUint8 *)emptyRIext; PRUint32 L2 = sizeof emptyRIext; - (void)ssl3_HandleExtensions(ss, &b2, &L2, client_hello); + (void)ssl3_HandleExtensions(ss, &b2, &L2, ssl_hs_client_hello); break; } } @@ -9290,9 +9225,8 @@ ssl3_SendServerHello(sslSocket *ss) { sslSessionID *sid; SECStatus rv; - PRUint32 maxBytes = 65535; + sslBuffer extensionBuf = { NULL, 0, 0 }; PRUint32 length; - PRInt32 extensions_len = 0; SSL3ProtocolVersion version; SSL_TRC(3, ("%d: SSL3[%d]: send server_hello handshake", SSL_GETPID(), @@ -9309,10 +9243,10 @@ ssl3_SendServerHello(sslSocket *ss) sid = ss->sec.ci.sid; - extensions_len = ssl3_CallHelloExtensionSenders( - ss, PR_FALSE, maxBytes, &ss->xtnData.serverHelloSenders[0]); - if (extensions_len > 0) - extensions_len += 2; /* Add sizeof total extension length */ + rv = ssl_ConstructExtensions(ss, &extensionBuf, ssl_hs_server_hello); + if (rv != SECSuccess) { + return SECFailure; + } /* TLS 1.3 doesn't use the session_id or compression_method * fields in the ServerHello. */ @@ -9324,11 +9258,13 @@ ssl3_SendServerHello(sslSocket *ss) if (ss->version < SSL_LIBRARY_VERSION_TLS_1_3) { length += 1; /* Compression */ } - length += extensions_len; + if (extensionBuf.len) { + length += 2 + extensionBuf.len; + } - rv = ssl3_AppendHandshakeHeader(ss, server_hello, length); + rv = ssl3_AppendHandshakeHeader(ss, ssl_hs_server_hello, length); if (rv != SECSuccess) { - return rv; /* err set by AppendHandshake. */ + goto loser; /* err set by AppendHandshake. */ } if (IS_DTLS(ss) && ss->version < SSL_LIBRARY_VERSION_TLS_1_3) { @@ -9339,13 +9275,13 @@ ssl3_SendServerHello(sslSocket *ss) rv = ssl3_AppendHandshakeNumber(ss, version, 2); if (rv != SECSuccess) { - return rv; /* err set by AppendHandshake. */ + goto loser; /* err set by AppendHandshake. */ } /* Random already generated in ssl3_HandleClientHello */ rv = ssl3_AppendHandshake( ss, &ss->ssl3.hs.server_random, SSL3_RANDOM_LENGTH); if (rv != SECSuccess) { - return rv; /* err set by AppendHandshake. */ + goto loser; /* err set by AppendHandshake. */ } if (ss->version < SSL_LIBRARY_VERSION_TLS_1_3) { @@ -9356,45 +9292,40 @@ ssl3_SendServerHello(sslSocket *ss) rv = ssl3_AppendHandshakeNumber(ss, 0, 1); } if (rv != SECSuccess) { - return rv; /* err set by AppendHandshake. */ + goto loser; /* err set by AppendHandshake. */ } } rv = ssl3_AppendHandshakeNumber(ss, ss->ssl3.hs.cipher_suite, 2); if (rv != SECSuccess) { - return rv; /* err set by AppendHandshake. */ + goto loser; /* err set by AppendHandshake. */ } if (ss->version < SSL_LIBRARY_VERSION_TLS_1_3) { rv = ssl3_AppendHandshakeNumber(ss, ss->ssl3.hs.compression, 1); if (rv != SECSuccess) { - return rv; /* err set by AppendHandshake. */ + goto loser; /* err set by AppendHandshake. */ } } - if (extensions_len) { - PRInt32 sent_len; - - extensions_len -= 2; - rv = ssl3_AppendHandshakeNumber(ss, extensions_len, 2); - if (rv != SECSuccess) - return rv; /* err set by ssl3_AppendHandshakeNumber */ - sent_len = ssl3_CallHelloExtensionSenders(ss, PR_TRUE, extensions_len, - &ss->xtnData.serverHelloSenders[0]); - PORT_Assert(sent_len == extensions_len); - if (sent_len != extensions_len) { - if (sent_len >= 0) - PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); - return SECFailure; + if (extensionBuf.len) { + rv = ssl3_AppendBufferToHandshakeVariable(ss, &extensionBuf, 2); + if (rv != SECSuccess) { + goto loser; /* err set by ssl3_AppendHandshakeVariable */ } } if (ss->version < SSL_LIBRARY_VERSION_TLS_1_3) { rv = ssl3_SetupPendingCipherSpec(ss); if (rv != SECSuccess) { - return rv; /* err set by ssl3_SetupPendingCipherSpec */ + goto loser; /* err set by ssl3_SetupPendingCipherSpec */ } } + sslBuffer_Clear(&extensionBuf); return SECSuccess; + +loser: + sslBuffer_Clear(&extensionBuf); + return SECFailure; } SECStatus @@ -9451,6 +9382,7 @@ ssl3_SendDHServerKeyExchange(sslSocket *ss) SECKEYPublicKey *pubKey; SECKEYPrivateKey *certPrivateKey; const sslNamedGroupDef *groupDef; + sslBuffer dhBuf = { NULL, 0, 0 }; if (kea_def->kea != kea_dhe_dss && kea_def->kea != kea_dhe_rsa) { /* TODO: Support DH_anon. It might be sufficient to drop the signature. @@ -9510,7 +9442,7 @@ ssl3_SendDHServerKeyExchange(sslSocket *ss) length += 2; } - rv = ssl3_AppendHandshakeHeader(ss, server_key_exchange, length); + rv = ssl3_AppendHandshakeHeader(ss, ssl_hs_server_key_exchange, length); if (rv != SECSuccess) { goto loser; /* err set by AppendHandshake. */ } @@ -9527,7 +9459,11 @@ ssl3_SendDHServerKeyExchange(sslSocket *ss) goto loser; /* err set by AppendHandshake. */ } - rv = ssl_AppendPaddedDHKeyShare(ss, pubKey, PR_TRUE); + rv = ssl_AppendPaddedDHKeyShare(&dhBuf, pubKey, PR_TRUE); + if (rv != SECSuccess) { + goto loser; /* err set by AppendPaddedDHKeyShare. */ + } + rv = ssl3_AppendBufferToHandshake(ss, &dhBuf); if (rv != SECSuccess) { goto loser; /* err set by AppendHandshake. */ } @@ -9544,12 +9480,15 @@ ssl3_SendDHServerKeyExchange(sslSocket *ss) if (rv != SECSuccess) { goto loser; /* err set by AppendHandshake. */ } + + sslBuffer_Clear(&dhBuf); PORT_Free(signed_hash.data); return SECSuccess; loser: if (signed_hash.data) PORT_Free(signed_hash.data); + sslBuffer_Clear(&dhBuf); return SECFailure; } @@ -9661,7 +9600,7 @@ ssl3_SendCertificateRequest(sslSocket *ss) length += 2 + sigAlgsLength; } - rv = ssl3_AppendHandshakeHeader(ss, certificate_request, length); + rv = ssl3_AppendHandshakeHeader(ss, ssl_hs_certificate_request, length); if (rv != SECSuccess) { return rv; /* err set by AppendHandshake. */ } @@ -9700,7 +9639,7 @@ ssl3_SendServerHelloDone(sslSocket *ss) PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss)); PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss)); - rv = ssl3_AppendHandshakeHeader(ss, server_hello_done, 0); + rv = ssl3_AppendHandshakeHeader(ss, ssl_hs_server_hello_done, 0); if (rv != SECSuccess) { return rv; /* err set by AppendHandshake. */ } @@ -9765,13 +9704,12 @@ ssl3_HandleCertificateVerify(sslSocket *ss, PRUint8 *b, PRUint32 length, hashAlg = ssl_SignatureSchemeToHashType(sigScheme); - if (hashes->u.pointer_to_hash_input.data) { - rv = ssl3_ComputeHandshakeHash(hashes->u.pointer_to_hash_input.data, - hashes->u.pointer_to_hash_input.len, - hashAlg, &localHashes); - } else { - rv = SECFailure; - } + /* Read from the message buffer, but we need to use only up to the end + * of the previous handshake message. The length of the transcript up to + * that point is saved in |hashes->u.transcriptLen|. */ + rv = ssl3_ComputeHandshakeHash(ss->ssl3.hs.messages.buf, + hashes->u.transcriptLen, + hashAlg, &localHashes); if (rv == SECSuccess) { hashesForVerify = &localHashes; @@ -10183,7 +10121,7 @@ ssl3_SendEmptyCertificate(sslSocket *ss) isTLS13 = PR_TRUE; } - rv = ssl3_AppendHandshakeHeader(ss, certificate, len + 3); + rv = ssl3_AppendHandshakeHeader(ss, ssl_hs_certificate, len + 3); if (rv != SECSuccess) { return rv; } @@ -10215,7 +10153,7 @@ ssl3_SendNewSessionTicket(sslSocket *ss) /* Serialize the handshake message. Length = * lifetime (4) + ticket length (2) + ticket. */ - rv = ssl3_AppendHandshakeHeader(ss, new_session_ticket, + rv = ssl3_AppendHandshakeHeader(ss, ssl_hs_new_session_ticket, 4 + 2 + ticket.len); if (rv != SECSuccess) goto loser; @@ -10426,7 +10364,7 @@ ssl3_SendCertificate(sslSocket *ss) } } - rv = ssl3_AppendHandshakeHeader(ss, certificate, + rv = ssl3_AppendHandshakeHeader(ss, ssl_hs_certificate, contextLen + certChainLen + 3); if (rv != SECSuccess) { return rv; /* err set by AppendHandshake. */ @@ -10501,7 +10439,7 @@ ssl3_SendCertificateStatus(sslSocket *ss) /* Use the array's first item only (single stapling) */ len = 1 + statusToSend->items[0].len + 3; - rv = ssl3_AppendHandshakeHeader(ss, certificate_status, len); + rv = ssl3_AppendHandshakeHeader(ss, ssl_hs_certificate_status, len); if (rv != SECSuccess) { return rv; /* err set by AppendHandshake. */ } @@ -11141,7 +11079,7 @@ ssl3_SendNextProto(sslSocket *ss) padding_len = 32 - ((ss->xtnData.nextProto.len + 2) % 32); - rv = ssl3_AppendHandshakeHeader(ss, next_proto, ss->xtnData.nextProto.len + 2 + padding_len); + rv = ssl3_AppendHandshakeHeader(ss, ssl_hs_next_proto, ss->xtnData.nextProto.len + 2 + padding_len); if (rv != SECSuccess) { return rv; /* error code set by AppendHandshakeHeader */ } @@ -11256,7 +11194,7 @@ ssl3_SendFinished(sslSocket *ss, PRInt32 flags) else ss->ssl3.hs.finishedMsgs.tFinished[0] = tlsFinished; ss->ssl3.hs.finishedBytes = sizeof tlsFinished; - rv = ssl3_AppendHandshakeHeader(ss, finished, sizeof tlsFinished); + rv = ssl3_AppendHandshakeHeader(ss, ssl_hs_finished, sizeof tlsFinished); if (rv != SECSuccess) goto fail; /* err set by AppendHandshake. */ rv = ssl3_AppendHandshake(ss, &tlsFinished, sizeof tlsFinished); @@ -11269,7 +11207,7 @@ ssl3_SendFinished(sslSocket *ss, PRInt32 flags) ss->ssl3.hs.finishedMsgs.sFinished[0] = hashes.u.s; PORT_Assert(hashes.len == sizeof hashes.u.s); ss->ssl3.hs.finishedBytes = sizeof hashes.u.s; - rv = ssl3_AppendHandshakeHeader(ss, finished, sizeof hashes.u.s); + rv = ssl3_AppendHandshakeHeader(ss, ssl_hs_finished, sizeof hashes.u.s); if (rv != SECSuccess) goto fail; /* err set by AppendHandshake. */ rv = ssl3_AppendHandshake(ss, &hashes.u.s, sizeof hashes.u.s); @@ -11642,7 +11580,7 @@ ssl3_HandleHandshakeMessage(sslSocket *ss, PRUint8 *b, PRUint32 length, PRBool endOfRecord) { SECStatus rv = SECSuccess; - SSL3HandshakeType type = ss->ssl3.hs.msg_type; + SSLHandshakeType type = ss->ssl3.hs.msg_type; SSL3Hashes hashes; /* computed hashes are put here. */ SSL3Hashes *hashesPtr = NULL; /* Set when hashes are computed */ PRUint8 hdr[4]; @@ -11657,9 +11595,10 @@ ssl3_HandleHandshakeMessage(sslSocket *ss, PRUint8 *b, PRUint32 length, * current message. */ if (ss->version < SSL_LIBRARY_VERSION_TLS_1_3) { - if ((type == finished) && (ss->ssl3.hs.ws == wait_finished)) { + if ((type == ssl_hs_finished) && (ss->ssl3.hs.ws == wait_finished)) { computeHashes = PR_TRUE; - } else if ((type == certificate_verify) && (ss->ssl3.hs.ws == wait_cert_verify)) { + } else if ((type == ssl_hs_certificate_verify) && + (ss->ssl3.hs.ws == wait_cert_verify)) { if (ss->ssl3.hs.hashType == handshake_hash_record) { /* We cannot compute the hash yet. We must wait until we have * decoded the certificate_verify message in @@ -11671,24 +11610,24 @@ ssl3_HandleHandshakeMessage(sslSocket *ss, PRUint8 *b, PRUint32 length, * additional handshake messages will have been added to the * buffer, e.g. the certificate_verify message itself.) * - * Therefore, we use SSL3Hashes.u.pointer_to_hash_input - * to signal the current state of the buffer. + * Therefore, we use SSL3Hashes.u.transcriptLen to save how much + * data there is and read directly from ss->ssl3.hs.messages + * when calculating the hashes. * * ssl3_HandleCertificateVerify will detect * hashType == handshake_hash_record * and use that information to calculate the hash. */ - hashes.u.pointer_to_hash_input.data = ss->ssl3.hs.messages.buf; - hashes.u.pointer_to_hash_input.len = ss->ssl3.hs.messages.len; + hashes.u.transcriptLen = ss->ssl3.hs.messages.len; hashesPtr = &hashes; } else { computeHashes = PR_TRUE; } } } else { - if (type == certificate_verify) { + if (type == ssl_hs_certificate_verify) { computeHashes = TLS13_IN_HS_STATE(ss, wait_cert_verify); - } else if (type == finished) { + } else if (type == ssl_hs_finished) { computeHashes = TLS13_IN_HS_STATE(ss, wait_cert_request, wait_finished); } @@ -11700,7 +11639,7 @@ ssl3_HandleHandshakeMessage(sslSocket *ss, PRUint8 *b, PRUint32 length, ssl3CipherSpec *rSpec = ss->version >= SSL_LIBRARY_VERSION_TLS_1_3 ? ss->ssl3.crSpec : ss->ssl3.prSpec; - if (type == finished) { + if (type == ssl_hs_finished) { sender = ss->sec.isServer ? sender_client : sender_server; rSpec = ss->ssl3.crSpec; } @@ -11723,13 +11662,13 @@ ssl3_HandleHandshakeMessage(sslSocket *ss, PRUint8 *b, PRUint32 length, /* Start new handshake hashes when we start a new handshake. Unless this is * TLS 1.3 and we sent a HelloRetryRequest. */ - if (ss->ssl3.hs.msg_type == client_hello && !ss->ssl3.hs.helloRetry) { + if (ss->ssl3.hs.msg_type == ssl_hs_client_hello && !ss->ssl3.hs.helloRetry) { ssl3_RestartHandshakeHashes(ss); } /* We should not include hello_request and hello_verify_request messages * in the handshake hashes */ - if ((ss->ssl3.hs.msg_type != hello_request) && - (ss->ssl3.hs.msg_type != hello_verify_request)) { + if ((ss->ssl3.hs.msg_type != ssl_hs_hello_request) && + (ss->ssl3.hs.msg_type != ssl_hs_hello_verify_request)) { rv = ssl3_UpdateHandshakeHashes(ss, (unsigned char *)hdr, 4); if (rv != SECSuccess) return rv; /* err code already set. */ @@ -11765,7 +11704,7 @@ ssl3_HandleHandshakeMessage(sslSocket *ss, PRUint8 *b, PRUint32 length, PORT_SetError(0); /* each message starts with no error. */ if (ss->ssl3.hs.ws == wait_certificate_status && - ss->ssl3.hs.msg_type != certificate_status) { + ss->ssl3.hs.msg_type != ssl_hs_certificate_status) { /* If we negotiated the certificate_status extension then we deferred * certificate validation until we get the CertificateStatus messsage. * But the CertificateStatus message is optional. If the server did @@ -11782,7 +11721,7 @@ ssl3_HandleHandshakeMessage(sslSocket *ss, PRUint8 *b, PRUint32 length, epoch = ss->ssl3.crSpec->epoch; switch (ss->ssl3.hs.msg_type) { - case client_hello: + case ssl_hs_client_hello: if (!ss->sec.isServer) { (void)SSL3_SendAlert(ss, alert_fatal, unexpected_message); PORT_SetError(SSL_ERROR_RX_UNEXPECTED_CLIENT_HELLO); @@ -11790,7 +11729,7 @@ ssl3_HandleHandshakeMessage(sslSocket *ss, PRUint8 *b, PRUint32 length, } rv = ssl3_HandleClientHello(ss, b, length); break; - case server_hello: + case ssl_hs_server_hello: if (ss->sec.isServer) { (void)SSL3_SendAlert(ss, alert_fatal, unexpected_message); PORT_SetError(SSL_ERROR_RX_UNEXPECTED_SERVER_HELLO); @@ -11831,7 +11770,7 @@ ssl3_HandlePostHelloHandshakeMessage(sslSocket *ss, PRUint8 *b, PORT_Assert(ss->version < SSL_LIBRARY_VERSION_TLS_1_3); switch (ss->ssl3.hs.msg_type) { - case hello_request: + case ssl_hs_hello_request: if (length != 0) { (void)ssl3_DecodeError(ss); PORT_SetError(SSL_ERROR_RX_MALFORMED_HELLO_REQUEST); @@ -11845,13 +11784,13 @@ ssl3_HandlePostHelloHandshakeMessage(sslSocket *ss, PRUint8 *b, rv = ssl3_HandleHelloRequest(ss); break; - case hello_retry_request: + case ssl_hs_hello_retry_request: /* This arrives here because - as a client - we haven't received a * final decision on the version from the server. */ rv = tls13_HandleHelloRetryRequest(ss, b, length); break; - case hello_verify_request: + case ssl_hs_hello_verify_request: if (!IS_DTLS(ss) || ss->sec.isServer) { (void)SSL3_SendAlert(ss, alert_fatal, unexpected_message); PORT_SetError(SSL_ERROR_RX_UNEXPECTED_HELLO_VERIFY_REQUEST); @@ -11859,13 +11798,13 @@ ssl3_HandlePostHelloHandshakeMessage(sslSocket *ss, PRUint8 *b, } rv = dtls_HandleHelloVerifyRequest(ss, b, length); break; - case certificate: + case ssl_hs_certificate: rv = ssl3_HandleCertificate(ss, b, length); break; - case certificate_status: + case ssl_hs_certificate_status: rv = ssl3_HandleCertificateStatus(ss, b, length); break; - case server_key_exchange: + case ssl_hs_server_key_exchange: if (ss->sec.isServer) { (void)SSL3_SendAlert(ss, alert_fatal, unexpected_message); PORT_SetError(SSL_ERROR_RX_UNEXPECTED_SERVER_KEY_EXCH); @@ -11873,7 +11812,7 @@ ssl3_HandlePostHelloHandshakeMessage(sslSocket *ss, PRUint8 *b, } rv = ssl3_HandleServerKeyExchange(ss, b, length); break; - case certificate_request: + case ssl_hs_certificate_request: if (ss->sec.isServer) { (void)SSL3_SendAlert(ss, alert_fatal, unexpected_message); PORT_SetError(SSL_ERROR_RX_UNEXPECTED_CERT_REQUEST); @@ -11881,7 +11820,7 @@ ssl3_HandlePostHelloHandshakeMessage(sslSocket *ss, PRUint8 *b, } rv = ssl3_HandleCertificateRequest(ss, b, length); break; - case server_hello_done: + case ssl_hs_server_hello_done: if (length != 0) { (void)ssl3_DecodeError(ss); PORT_SetError(SSL_ERROR_RX_MALFORMED_HELLO_DONE); @@ -11894,7 +11833,7 @@ ssl3_HandlePostHelloHandshakeMessage(sslSocket *ss, PRUint8 *b, } rv = ssl3_HandleServerHelloDone(ss); break; - case certificate_verify: + case ssl_hs_certificate_verify: if (!ss->sec.isServer) { (void)SSL3_SendAlert(ss, alert_fatal, unexpected_message); PORT_SetError(SSL_ERROR_RX_UNEXPECTED_CERT_VERIFY); @@ -11902,7 +11841,7 @@ ssl3_HandlePostHelloHandshakeMessage(sslSocket *ss, PRUint8 *b, } rv = ssl3_HandleCertificateVerify(ss, b, length, hashesPtr); break; - case client_key_exchange: + case ssl_hs_client_key_exchange: if (!ss->sec.isServer) { (void)SSL3_SendAlert(ss, alert_fatal, unexpected_message); PORT_SetError(SSL_ERROR_RX_UNEXPECTED_CLIENT_KEY_EXCH); @@ -11910,7 +11849,7 @@ ssl3_HandlePostHelloHandshakeMessage(sslSocket *ss, PRUint8 *b, } rv = ssl3_HandleClientKeyExchange(ss, b, length); break; - case new_session_ticket: + case ssl_hs_new_session_ticket: if (ss->sec.isServer) { (void)SSL3_SendAlert(ss, alert_fatal, unexpected_message); PORT_SetError(SSL_ERROR_RX_UNEXPECTED_NEW_SESSION_TICKET); @@ -11918,7 +11857,7 @@ ssl3_HandlePostHelloHandshakeMessage(sslSocket *ss, PRUint8 *b, } rv = ssl3_HandleNewSessionTicket(ss, b, length); break; - case finished: + case ssl_hs_finished: rv = ssl3_HandleFinished(ss, b, length, hashesPtr); break; default: @@ -11960,7 +11899,7 @@ ssl3_HandleHandshake(sslSocket *ss, sslBuffer *origBuf) t = *(buf->buf++); buf->len--; if (ss->ssl3.hs.header_bytes++ == 0) - ss->ssl3.hs.msg_type = (SSL3HandshakeType)t; + ss->ssl3.hs.msg_type = (SSLHandshakeType)t; else ss->ssl3.hs.msg_len = (ss->ssl3.hs.msg_len << 8) + t; if (ss->ssl3.hs.header_bytes < 4) diff --git a/lib/ssl/ssl3ecc.c b/lib/ssl/ssl3ecc.c index b440b4b024..85e2e2722d 100644 --- a/lib/ssl/ssl3ecc.c +++ b/lib/ssl/ssl3ecc.c @@ -219,7 +219,7 @@ ssl3_SendECDHClientKeyExchange(sslSocket *ss, SECKEYPublicKey *svrPubKey) goto loser; } - rv = ssl3_AppendHandshakeHeader(ss, client_key_exchange, + rv = ssl3_AppendHandshakeHeader(ss, ssl_hs_client_key_exchange, pubKey->u.ec.publicValue.len + 1); if (rv != SECSuccess) { goto loser; /* err set by ssl3_AppendHandshake* */ @@ -250,19 +250,6 @@ ssl3_SendECDHClientKeyExchange(sslSocket *ss, SECKEYPublicKey *svrPubKey) return SECFailure; } -/* This function encodes the key_exchange field in - * the KeyShareEntry structure. */ -SECStatus -tls13_EncodeECDHEKeyShareKEX(const sslSocket *ss, const SECKEYPublicKey *pubKey) -{ - PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss)); - PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss)); - PORT_Assert(pubKey->keyType == ecKey); - - return ssl3_ExtAppendHandshake(ss, pubKey->u.ec.publicValue.data, - pubKey->u.ec.publicValue.len); -} - /* ** Called from ssl3_HandleClientKeyExchange() */ @@ -731,7 +718,7 @@ ssl3_SendECDHServerKeyExchange(sslSocket *ss) 1 + pubKey->u.ec.publicValue.len + (isTLS12 ? 2 : 0) + 2 + signed_hash.len; - rv = ssl3_AppendHandshakeHeader(ss, server_key_exchange, length); + rv = ssl3_AppendHandshakeHeader(ss, ssl_hs_server_key_exchange, length); if (rv != SECSuccess) { goto loser; /* err set by AppendHandshake. */ } @@ -870,20 +857,15 @@ ssl_IsDHEEnabled(const sslSocket *ss) } /* Send our Supported Groups extension. */ -PRInt32 -ssl_SendSupportedGroupsXtn(const sslSocket *ss, - TLSExtensionData *xtnData, - PRBool append, PRUint32 maxBytes) +SECStatus +ssl_SendSupportedGroupsXtn(const sslSocket *ss, TLSExtensionData *xtnData, + sslBuffer *buf, PRBool *added) { - PRInt32 extension_length; - unsigned char enabledGroups[64]; - unsigned int enabledGroupsLen = 0; unsigned int i; PRBool ec; PRBool ff = PR_FALSE; - - if (!ss) - return 0; + SECStatus rv; + sslBuffer tmpBuf = { NULL, 0, 0 }; /* We only send FF supported groups if we require DH named groups * or if TLS 1.3 is a possibility. */ @@ -892,13 +874,14 @@ ssl_SendSupportedGroupsXtn(const sslSocket *ss, if (ss->opt.requireDHENamedGroups) { ff = ssl_IsDHEEnabled(ss); } - if (!ec && !ff) - return 0; + if (!ec && !ff) { + return SECSuccess; + } } else { ec = ff = PR_TRUE; } - PORT_Assert(sizeof(enabledGroups) > SSL_NAMED_GROUP_COUNT * 2); + /* Reserve space for the length. */ for (i = 0; i < SSL_NAMED_GROUP_COUNT; ++i) { const sslNamedGroupDef *group = ss->namedGroupPreferences[i]; if (!group) { @@ -911,78 +894,55 @@ ssl_SendSupportedGroupsXtn(const sslSocket *ss, continue; } - if (append) { - (void)ssl_EncodeUintX(group->name, 2, &enabledGroups[enabledGroupsLen]); - } - enabledGroupsLen += 2; - } - - if (enabledGroupsLen == 0) { - return 0; - } - - extension_length = - 2 /* extension type */ + - 2 /* extension length */ + - 2 /* enabled groups length */ + - enabledGroupsLen; - - if (maxBytes < (PRUint32)extension_length) { - return 0; - } - - if (append) { - SECStatus rv; - rv = ssl3_ExtAppendHandshakeNumber(ss, ssl_supported_groups_xtn, 2); - if (rv != SECSuccess) - return -1; - rv = ssl3_ExtAppendHandshakeNumber(ss, extension_length - 4, 2); - if (rv != SECSuccess) - return -1; - rv = ssl3_ExtAppendHandshakeVariable(ss, enabledGroups, - enabledGroupsLen, 2); - if (rv != SECSuccess) - return -1; - if (!ss->sec.isServer) { - xtnData->advertised[xtnData->numAdvertised++] = - ssl_supported_groups_xtn; + rv = sslBuffer_AppendNumber(&tmpBuf, group->name, 2); + if (rv != SECSuccess) { + sslBuffer_Clear(&tmpBuf); + return SECFailure; } } - return extension_length; + + if (!tmpBuf.len) { + sslBuffer_Clear(&tmpBuf); + /* We added nothing, don't send the extension. */ + return SECSuccess; + } + + rv = sslBuffer_AppendBufferVariable(buf, &tmpBuf, 2); + sslBuffer_Clear(&tmpBuf); + if (rv != SECSuccess) { + return SECFailure; + } + + *added = PR_TRUE; + return SECSuccess; } /* Send our "canned" (precompiled) Supported Point Formats extension, * which says that we only support uncompressed points. */ -PRInt32 -ssl3_SendSupportedPointFormatsXtn( - const sslSocket *ss, - TLSExtensionData *xtnData, - PRBool append, - PRUint32 maxBytes) +SECStatus +ssl3_SendSupportedPointFormatsXtn(const sslSocket *ss, TLSExtensionData *xtnData, + sslBuffer *buf, PRBool *added) { - static const PRUint8 ecPtFmt[6] = { - 0, 11, /* Extension type */ - 0, 2, /* octets that follow */ - 1, /* octets that follow */ - 0 /* uncompressed type only */ - }; + SECStatus rv; /* No point in doing this unless we have a socket that supports ECC. * Similarly, no point if we are going to do TLS 1.3 only or we have already * picked TLS 1.3 (server) given that it doesn't use point formats. */ if (!ss || !ssl_IsECCEnabled(ss) || ss->vrange.min >= SSL_LIBRARY_VERSION_TLS_1_3 || - (ss->sec.isServer && ss->version >= SSL_LIBRARY_VERSION_TLS_1_3)) - return 0; - if (append && maxBytes >= (sizeof ecPtFmt)) { - SECStatus rv = ssl3_ExtAppendHandshake(ss, ecPtFmt, (sizeof ecPtFmt)); - if (rv != SECSuccess) - return -1; - if (!ss->sec.isServer) { - xtnData->advertised[xtnData->numAdvertised++] = - ssl_ec_point_formats_xtn; - } + (ss->sec.isServer && ss->version >= SSL_LIBRARY_VERSION_TLS_1_3)) { + return SECSuccess; } - return sizeof(ecPtFmt); + rv = sslBuffer_AppendNumber(buf, 1, 1); /* length */ + if (rv != SECSuccess) { + return SECFailure; + } + rv = sslBuffer_AppendNumber(buf, 0, 1); /* uncompressed type only */ + if (rv != SECSuccess) { + return SECFailure; + } + + *added = PR_TRUE; + return SECSuccess; } diff --git a/lib/ssl/ssl3encode.c b/lib/ssl/ssl3encode.c deleted file mode 100644 index 960208a0f7..0000000000 --- a/lib/ssl/ssl3encode.c +++ /dev/null @@ -1,85 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is PRIVATE to SSL. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "prnetdb.h" -#include "seccomon.h" -#include "secerr.h" -#include "ssl3encode.h" - -SECStatus -ssl3_AppendToItem(SECItem *item, const unsigned char *buf, PRUint32 bytes) -{ - if (bytes > item->len) { - PORT_SetError(SEC_ERROR_INVALID_ARGS); - return SECFailure; - } - - PORT_Memcpy(item->data, buf, bytes); - item->data += bytes; - item->len -= bytes; - return SECSuccess; -} - -SECStatus -ssl3_AppendNumberToItem(SECItem *item, PRUint32 num, PRInt32 lenSize) -{ - SECStatus rv; - PRUint8 b[4]; - - ssl_EncodeUintX(num, lenSize, b); - rv = ssl3_AppendToItem(item, &b[0], lenSize); - return rv; -} - -SECStatus -ssl3_ConsumeFromItem(SECItem *item, unsigned char **buf, PRUint32 bytes) -{ - if (bytes > item->len) { - PORT_SetError(SEC_ERROR_BAD_DATA); - return SECFailure; - } - - *buf = item->data; - item->data += bytes; - item->len -= bytes; - return SECSuccess; -} - -SECStatus -ssl3_ConsumeNumberFromItem(SECItem *item, PRUint32 *num, PRUint32 bytes) -{ - int i; - - if (bytes > item->len || bytes > sizeof(*num)) { - PORT_SetError(SEC_ERROR_BAD_DATA); - return SECFailure; - } - - *num = 0; - for (i = 0; i < bytes; i++) { - *num = (*num << 8) + item->data[i]; - } - - item->data += bytes; - item->len -= bytes; - - return SECSuccess; -} - -/* Helper function to encode an unsigned integer into a buffer. */ -PRUint8 * -ssl_EncodeUintX(PRUint64 value, unsigned int bytes, PRUint8 *to) -{ - PRUint64 encoded; - - PORT_Assert(bytes > 0 && bytes <= sizeof(encoded)); - - encoded = PR_htonll(value); - memcpy(to, ((unsigned char *)(&encoded)) + (sizeof(encoded) - bytes), bytes); - return to + bytes; -} diff --git a/lib/ssl/ssl3ext.c b/lib/ssl/ssl3ext.c index 22dfb4cdae..08eec25a92 100644 --- a/lib/ssl/ssl3ext.c +++ b/lib/ssl/ssl3ext.c @@ -16,6 +16,17 @@ #include "ssl3exthandle.h" #include "tls13exthandle.h" +/* Callback function that handles a received extension. */ +typedef SECStatus (*ssl3ExtensionHandlerFunc)(const sslSocket *ss, + TLSExtensionData *xtnData, + SECItem *data); + +/* Row in a table of hello extension handlers. */ +typedef struct { + SSLExtensionType ex_type; + ssl3ExtensionHandlerFunc ex_handler; +} ssl3ExtensionHandler; + /* Table of handlers for received TLS hello extensions, one per extension. * In the second generation, this table will be dynamic, and functions * will be registered here. @@ -37,10 +48,8 @@ static const ssl3ExtensionHandler clientHelloHandlers[] = { { ssl_tls13_key_share_xtn, &tls13_ServerHandleKeyShareXtn }, { ssl_tls13_pre_shared_key_xtn, &tls13_ServerHandlePreSharedKeyXtn }, { ssl_tls13_early_data_xtn, &tls13_ServerHandleEarlyDataXtn }, - { ssl_tls13_psk_key_exchange_modes_xtn, - &tls13_ServerHandlePskKeyExchangeModesXtn }, - { ssl_tls13_short_header_xtn, &tls13_HandleShortHeaderXtn }, - { -1, NULL } + { ssl_tls13_psk_key_exchange_modes_xtn, &tls13_ServerHandlePskModesXtn }, + { 0, NULL } }; /* These two tables are used by the client, to handle server hello @@ -59,39 +68,38 @@ static const ssl3ExtensionHandler serverHelloHandlersTLS[] = { { ssl_tls13_key_share_xtn, &tls13_ClientHandleKeyShareXtn }, { ssl_tls13_pre_shared_key_xtn, &tls13_ClientHandlePreSharedKeyXtn }, { ssl_tls13_early_data_xtn, &tls13_ClientHandleEarlyDataXtn }, - { ssl_tls13_short_header_xtn, &tls13_HandleShortHeaderXtn }, - { -1, NULL } + { 0, NULL } }; static const ssl3ExtensionHandler helloRetryRequestHandlers[] = { { ssl_tls13_key_share_xtn, tls13_ClientHandleKeyShareXtnHrr }, { ssl_tls13_cookie_xtn, tls13_ClientHandleHrrCookie }, - { -1, NULL } + { 0, NULL } }; static const ssl3ExtensionHandler serverHelloHandlersSSL3[] = { { ssl_renegotiation_info_xtn, &ssl3_HandleRenegotiationInfoXtn }, - { -1, NULL } + { 0, NULL } }; static const ssl3ExtensionHandler newSessionTicketHandlers[] = { { ssl_tls13_early_data_xtn, &tls13_ClientHandleTicketEarlyDataXtn }, - { -1, NULL } + { 0, NULL } }; /* This table is used by the client to handle server certificates in TLS 1.3 */ static const ssl3ExtensionHandler serverCertificateHandlers[] = { { ssl_signed_cert_timestamp_xtn, &ssl3_ClientHandleSignedCertTimestampXtn }, { ssl_cert_status_xtn, &ssl3_ClientHandleStatusRequestXtn }, - { -1, NULL } + { 0, NULL } }; static const ssl3ExtensionHandler certificateRequestHandlers[] = { { ssl_signature_algorithms_xtn, &ssl3_HandleSigAlgsXtn }, { ssl_tls13_certificate_authorities_xtn, &tls13_ClientHandleCertAuthoritiesXtn }, - { -1, NULL } + { 0, NULL } }; /* Tables of functions to format TLS hello extensions, one function per @@ -104,14 +112,14 @@ static const ssl3ExtensionHandler certificateRequestHandlers[] = { * the client hello is empty (for example, the extended master secret * extension, if it were listed last). See bug 1243641. */ -static const ssl3HelloExtensionSender clientHelloSendersTLS[] = +static const sslExtensionBuilder clientHelloSendersTLS[] = { - { ssl_server_name_xtn, &ssl3_SendServerNameXtn }, + { ssl_server_name_xtn, &ssl3_ClientSendServerNameXtn }, { ssl_extended_master_secret_xtn, &ssl3_SendExtendedMasterSecretXtn }, { ssl_renegotiation_info_xtn, &ssl3_SendRenegotiationInfoXtn }, { ssl_supported_groups_xtn, &ssl_SendSupportedGroupsXtn }, { ssl_ec_point_formats_xtn, &ssl3_SendSupportedPointFormatsXtn }, - { ssl_session_ticket_xtn, &ssl3_SendSessionTicketXtn }, + { ssl_session_ticket_xtn, &ssl3_ClientSendSessionTicketXtn }, { ssl_next_proto_nego_xtn, &ssl3_ClientSendNextProtoNegoXtn }, { ssl_app_layer_protocol_xtn, &ssl3_ClientSendAppProtoXtn }, { ssl_use_srtp_xtn, &ssl3_ClientSendUseSRTPXtn }, @@ -124,22 +132,25 @@ static const ssl3HelloExtensionSender clientHelloSendersTLS[] = * client hello is empty. They are not intolerant of TLS 1.2, so list * signature_algorithms at the end. See bug 1243641. */ { ssl_tls13_supported_versions_xtn, &tls13_ClientSendSupportedVersionsXtn }, - { ssl_tls13_short_header_xtn, &tls13_SendShortHeaderXtn }, { ssl_signature_algorithms_xtn, &ssl3_SendSigAlgsXtn }, { ssl_tls13_cookie_xtn, &tls13_ClientSendHrrCookieXtn }, - { ssl_tls13_psk_key_exchange_modes_xtn, - &tls13_ClientSendPskKeyExchangeModesXtn }, - { ssl_padding_xtn, &ssl3_ClientSendPaddingExtension }, + { ssl_tls13_psk_key_exchange_modes_xtn, &tls13_ClientSendPskModesXtn }, /* The pre_shared_key extension MUST be last. */ { ssl_tls13_pre_shared_key_xtn, &tls13_ClientSendPreSharedKeyXtn }, { 0, NULL } }; -static const ssl3HelloExtensionSender clientHelloSendersSSL3[] = { +static const sslExtensionBuilder clientHelloSendersSSL3[] = { { ssl_renegotiation_info_xtn, &ssl3_SendRenegotiationInfoXtn }, { 0, NULL } }; +static const sslExtensionBuilder tls13_cert_req_senders[] = { + { ssl_signature_algorithms_xtn, &ssl3_SendSigAlgsXtn }, + { ssl_tls13_certificate_authorities_xtn, &tls13_SendCertAuthoritiesXtn }, + { 0, NULL } +}; + static PRBool arrayContainsExtension(const PRUint16 *array, PRUint32 len, PRUint16 ex_type) { @@ -254,46 +265,47 @@ ssl3_FindExtension(sslSocket *ss, SSLExtensionType extension_type) */ SECStatus ssl3_HandleParsedExtensions(sslSocket *ss, - SSL3HandshakeType handshakeMessage) + SSLHandshakeType handshakeMessage) { const ssl3ExtensionHandler *handlers; + const ssl3ExtensionHandler *handler; /* HelloRetryRequest doesn't set ss->version. It might be safe to * do so, but we weren't entirely sure. TODO(ekr@rtfm.com). */ PRBool isTLS13 = (ss->version >= SSL_LIBRARY_VERSION_TLS_1_3) || - (handshakeMessage == hello_retry_request); + (handshakeMessage == ssl_hs_hello_retry_request); /* The following messages can include extensions that were not included in * the original ClientHello. */ - PRBool allowNotOffered = (handshakeMessage == client_hello) || - (handshakeMessage == certificate_request) || - (handshakeMessage == new_session_ticket); + PRBool allowNotOffered = (handshakeMessage == ssl_hs_client_hello) || + (handshakeMessage == ssl_hs_certificate_request) || + (handshakeMessage == ssl_hs_new_session_ticket); PRCList *cursor; switch (handshakeMessage) { - case client_hello: + case ssl_hs_client_hello: handlers = clientHelloHandlers; break; - case new_session_ticket: + case ssl_hs_new_session_ticket: PORT_Assert(ss->version >= SSL_LIBRARY_VERSION_TLS_1_3); handlers = newSessionTicketHandlers; break; - case hello_retry_request: + case ssl_hs_hello_retry_request: handlers = helloRetryRequestHandlers; break; - case encrypted_extensions: + case ssl_hs_encrypted_extensions: PORT_Assert(ss->version >= SSL_LIBRARY_VERSION_TLS_1_3); /* fall through */ - case server_hello: + case ssl_hs_server_hello: if (ss->version > SSL_LIBRARY_VERSION_3_0) { handlers = serverHelloHandlersTLS; } else { handlers = serverHelloHandlersSSL3; } break; - case certificate: + case ssl_hs_certificate: PORT_Assert(!ss->sec.isServer); handlers = serverCertificateHandlers; break; - case certificate_request: + case ssl_hs_certificate_request: PORT_Assert(!ss->sec.isServer); handlers = certificateRequestHandlers; break; @@ -307,7 +319,6 @@ ssl3_HandleParsedExtensions(sslSocket *ss, cursor != &ss->ssl3.hs.remoteExtensions; cursor = PR_NEXT_LINK(cursor)) { TLSExtension *extension = (TLSExtension *)cursor; - const ssl3ExtensionHandler *handler; /* Check whether the server sent an extension which was not advertised * in the ClientHello. @@ -353,13 +364,12 @@ ssl3_HandleParsedExtensions(sslSocket *ss, } /* find extension_type in table of Hello Extension Handlers */ - for (handler = handlers; handler->ex_type >= 0; handler++) { + for (handler = handlers; handler->ex_handler; ++handler) { /* if found, call this handler */ if (handler->ex_type == extension->type) { SECStatus rv; rv = (*handler->ex_handler)(ss, &ss->xtnData, - (PRUint16)extension->type, &extension->data); if (rv != SECSuccess) { if (!ss->ssl3.fatalAlertSent) { @@ -380,7 +390,7 @@ ssl3_HandleParsedExtensions(sslSocket *ss, SECStatus ssl3_HandleExtensions(sslSocket *ss, PRUint8 **b, PRUint32 *length, - SSL3HandshakeType handshakeMessage) + SSLHandshakeType handshakeMessage) { SECStatus rv; @@ -402,22 +412,24 @@ SECStatus ssl3_RegisterExtensionSender(const sslSocket *ss, TLSExtensionData *xtnData, PRUint16 ex_type, - ssl3HelloExtensionSenderFunc cb) + sslExtensionBuilderFunc cb) { int i; - ssl3HelloExtensionSender *sender; + sslExtensionBuilder *sender; if (ss->version < SSL_LIBRARY_VERSION_TLS_1_3) { sender = &xtnData->serverHelloSenders[0]; } else { - if (tls13_ExtensionStatus(ex_type, server_hello) == + if (tls13_ExtensionStatus(ex_type, ssl_hs_server_hello) == tls13_extension_allowed) { - PORT_Assert(tls13_ExtensionStatus(ex_type, encrypted_extensions) == + PORT_Assert(tls13_ExtensionStatus(ex_type, + ssl_hs_encrypted_extensions) == tls13_extension_disallowed); sender = &xtnData->serverHelloSenders[0]; - } else if (tls13_ExtensionStatus(ex_type, encrypted_extensions) == + } else if (tls13_ExtensionStatus(ex_type, + ssl_hs_encrypted_extensions) == tls13_extension_allowed) { sender = &xtnData->encryptedExtensionsSenders[0]; - } else if (tls13_ExtensionStatus(ex_type, certificate) == + } else if (tls13_ExtensionStatus(ex_type, ssl_hs_certificate) == tls13_extension_allowed) { sender = &xtnData->certificateSenders[0]; } else { @@ -444,31 +456,199 @@ ssl3_RegisterExtensionSender(const sslSocket *ss, return SECFailure; } -/* call each of the extension senders and return the accumulated length */ -PRInt32 -ssl3_CallHelloExtensionSenders(sslSocket *ss, PRBool append, PRUint32 maxBytes, - const ssl3HelloExtensionSender *sender) +/* Call extension handlers for the given message. */ +SECStatus +ssl_ConstructExtensions(sslSocket *ss, sslBuffer *buf, SSLHandshakeType message) { - PRInt32 total_exten_len = 0; + const sslExtensionBuilder *sender; + SECStatus rv; - if (!sender) { - if (ss->vrange.max > SSL_LIBRARY_VERSION_3_0) { - sender = &clientHelloSendersTLS[0]; - } else { - sender = &clientHelloSendersSSL3[0]; + PORT_Assert(buf->len == 0); + + switch (message) { + case ssl_hs_client_hello: + if (ss->vrange.max > SSL_LIBRARY_VERSION_3_0) { + sender = clientHelloSendersTLS; + } else { + sender = clientHelloSendersSSL3; + } + break; + + case ssl_hs_server_hello: + sender = ss->xtnData.serverHelloSenders; + break; + + case ssl_hs_certificate_request: + PORT_Assert(ss->version >= SSL_LIBRARY_VERSION_TLS_1_3); + sender = tls13_cert_req_senders; + break; + + case ssl_hs_certificate: + PORT_Assert(ss->version >= SSL_LIBRARY_VERSION_TLS_1_3); + sender = ss->xtnData.certificateSenders; + break; + + case ssl_hs_encrypted_extensions: + PORT_Assert(ss->version >= SSL_LIBRARY_VERSION_TLS_1_3); + sender = ss->xtnData.encryptedExtensionsSenders; + break; + + default: + PORT_Assert(0); + PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); + return SECFailure; + } + + for (; sender->ex_sender; ++sender) { + PRBool append = PR_FALSE; + unsigned int start = buf->len; + unsigned int length; + + /* Save space for the extension type and length. Note that we don't grow + * the buffer now; rely on sslBuffer_Append* to do that. */ + buf->len += 4; + rv = (*sender->ex_sender)(ss, &ss->xtnData, buf, &append); + if (rv != SECSuccess) { + goto loser; + } + + /* Save the length and go back to the start. */ + length = buf->len - start - 4; + buf->len = start; + if (!append) { + continue; + } + + buf->len = start; + rv = sslBuffer_AppendNumber(buf, sender->ex_type, 2); + if (rv != SECSuccess) { + goto loser; /* Code already set. */ + } + rv = sslBuffer_AppendNumber(buf, length, 2); + if (rv != SECSuccess) { + goto loser; /* Code already set. */ } + /* Skip over the extension body. */ + buf->len += length; + + if (message == ssl_hs_client_hello) { + ss->xtnData.advertised[ss->xtnData.numAdvertised++] = + sender->ex_type; + } + } + + if (buf->len > 0xffff) { + PORT_SetError(SSL_ERROR_TX_RECORD_TOO_LONG); + goto loser; } - while (sender->ex_sender) { - PRInt32 extLen = (*sender->ex_sender)(ss, &ss->xtnData, append, maxBytes); - if (extLen < 0) { - return -1; + return SECSuccess; + +loser: + sslBuffer_Clear(buf); + return SECFailure; +} + +/* This extension sender can be used anywhere that an always empty extension is + * needed. Mostly that is for ServerHello where sender registration is dynamic; + * ClientHello senders are usually conditional in some way. */ +SECStatus +ssl_SendEmptyExtension(const sslSocket *ss, TLSExtensionData *xtnData, + sslBuffer *buf, PRBool *append) +{ + *append = PR_TRUE; + return SECSuccess; +} + +/* Takes the size of the ClientHello, less the record header, and determines how + * much padding is required. */ +static unsigned int +ssl_CalculatePaddingExtLen(const sslSocket *ss, unsigned int clientHelloLength) +{ + unsigned int recordLength = 1 /* handshake message type */ + + 3 /* handshake message length */ + + clientHelloLength; + unsigned int extensionLen; + + /* Don't pad for DTLS, for SSLv3, or for renegotiation. */ + if (IS_DTLS(ss) || + ss->vrange.max < SSL_LIBRARY_VERSION_TLS_1_0 || + ss->firstHsDone) { + return 0; + } + + /* A padding extension may be included to ensure that the record containing + * the ClientHello doesn't have a length between 256 and 511 bytes + * (inclusive). Initial ClientHello records with such lengths trigger bugs + * in F5 devices. */ + if (recordLength < 256 || recordLength >= 512) { + return 0; + } + + extensionLen = 512 - recordLength; + /* Extensions take at least four bytes to encode. Always include at least + * one byte of data if we are padding. Some servers will time out or + * terminate the connection if the last ClientHello extension is empty. */ + if (extensionLen < 5) { + extensionLen = 5; + } + + return extensionLen - 4; +} + +/* ssl3_SendPaddingExtension possibly adds an extension which ensures that a + * ClientHello record is either < 256 bytes or is >= 512 bytes. This ensures + * that we don't trigger bugs in F5 products. + * + * This takes an existing extension buffer, |buf|, and the length of the + * remainder of the ClientHello, |prefixLen|. It modifies the extension buffer + * to insert padding at the right place. + */ +SECStatus +ssl_InsertPaddingExtension(const sslSocket *ss, unsigned int prefixLen, + sslBuffer *buf) +{ + static unsigned char padding[252] = { 0 }; + unsigned int paddingLen; + unsigned int tailLen; + SECStatus rv; + + /* Account for the size of the header, the length field of the extensions + * block and the size of the existing extensions. */ + paddingLen = ssl_CalculatePaddingExtLen(ss, prefixLen + 2 + buf->len); + if (!paddingLen) { + return SECSuccess; + } + + /* Move the tail if there is one. This only happens if we are sending the + * TLS 1.3 PSK extension, which needs to be at the end. */ + if (ss->xtnData.paddingOffset) { + PORT_Assert(buf->len > ss->xtnData.paddingOffset); + tailLen = buf->len - ss->xtnData.paddingOffset; + rv = sslBuffer_Grow(buf, buf->len + 4 + paddingLen); + if (rv != SECSuccess) { + return SECFailure; } - maxBytes -= extLen; - total_exten_len += extLen; - ++sender; + PORT_Memmove(buf->buf + ss->xtnData.paddingOffset + 4 + paddingLen, + buf->buf + ss->xtnData.paddingOffset, + tailLen); + buf->len = ss->xtnData.paddingOffset; + } else { + tailLen = 0; } - return total_exten_len; + + rv = sslBuffer_AppendNumber(buf, ssl_padding_xtn, 2); + if (rv != SECSuccess) { + return SECFailure; /* Code already set. */ + } + rv = sslBuffer_AppendVariable(buf, padding, paddingLen, 2); + if (rv != SECSuccess) { + return SECFailure; /* Code already set. */ + } + + buf->len += tailLen; + + return SECSuccess; } void @@ -514,28 +694,6 @@ ssl3_ResetExtensionData(TLSExtensionData *xtnData) } /* Thunks to let extension handlers operate on const sslSocket* objects. */ -SECStatus -ssl3_ExtAppendHandshake(const sslSocket *ss, const void *void_src, - PRInt32 bytes) -{ - return ssl3_AppendHandshake((sslSocket *)ss, void_src, bytes); -} - -SECStatus -ssl3_ExtAppendHandshakeNumber(const sslSocket *ss, PRInt32 num, - PRInt32 lenSize) -{ - return ssl3_AppendHandshakeNumber((sslSocket *)ss, num, lenSize); -} - -SECStatus -ssl3_ExtAppendHandshakeVariable(const sslSocket *ss, - const PRUint8 *src, PRInt32 bytes, - PRInt32 lenSize) -{ - return ssl3_AppendHandshakeVariable((sslSocket *)ss, src, bytes, lenSize); -} - void ssl3_ExtSendAlert(const sslSocket *ss, SSL3AlertLevel level, SSL3AlertDescription desc) diff --git a/lib/ssl/ssl3ext.h b/lib/ssl/ssl3ext.h index b70efa3bb1..f8906b8582 100644 --- a/lib/ssl/ssl3ext.h +++ b/lib/ssl/ssl3ext.h @@ -9,44 +9,31 @@ #ifndef __ssl3ext_h_ #define __ssl3ext_h_ +#include "sslencode.h" + typedef enum { sni_nametype_hostname } SNINameType; typedef struct TLSExtensionDataStr TLSExtensionData; -/* registerable callback function that either appends extension to buffer +/* Registerable callback function that either appends extension to buffer * or returns length of data that it would have appended. */ -typedef PRInt32 (*ssl3HelloExtensionSenderFunc)(const sslSocket *ss, - TLSExtensionData *xtnData, - PRBool append, - PRUint32 maxBytes); - -/* registerable callback function that handles a received extension, - * of the given type. - */ -typedef SECStatus (*ssl3ExtensionHandlerFunc)(const sslSocket *ss, - TLSExtensionData *xtnData, - PRUint16 ex_type, - SECItem *data); +typedef SECStatus (*sslExtensionBuilderFunc)(const sslSocket *ss, + TLSExtensionData *xtnData, + sslBuffer *buf, PRBool *added); /* row in a table of hello extension senders */ typedef struct { PRInt32 ex_type; - ssl3HelloExtensionSenderFunc ex_sender; -} ssl3HelloExtensionSender; - -/* row in a table of hello extension handlers */ -typedef struct { - PRInt32 ex_type; - ssl3ExtensionHandlerFunc ex_handler; -} ssl3ExtensionHandler; + sslExtensionBuilderFunc ex_sender; +} sslExtensionBuilder; struct TLSExtensionDataStr { /* registered callbacks that send server hello extensions */ - ssl3HelloExtensionSender serverHelloSenders[SSL_MAX_EXTENSIONS]; - ssl3HelloExtensionSender encryptedExtensionsSenders[SSL_MAX_EXTENSIONS]; - ssl3HelloExtensionSender certificateSenders[SSL_MAX_EXTENSIONS]; + sslExtensionBuilder serverHelloSenders[SSL_MAX_EXTENSIONS]; + sslExtensionBuilder encryptedExtensionsSenders[SSL_MAX_EXTENSIONS]; + sslExtensionBuilder certificateSenders[SSL_MAX_EXTENSIONS]; /* Keep track of the extensions that are negotiated. */ PRUint16 numAdvertised; @@ -54,9 +41,6 @@ struct TLSExtensionDataStr { PRUint16 advertised[SSL_MAX_EXTENSIONS]; PRUint16 negotiated[SSL_MAX_EXTENSIONS]; - /* Amount of padding we need to add. */ - PRUint16 paddingLen; - /* SessionTicket Extension related data. */ PRBool ticketTimestampVerified; PRBool emptySessionTicket; @@ -102,9 +86,10 @@ struct TLSExtensionDataStr { PRUint16 dtlsSRTPCipherSuite; /* 0 if not selected */ - SECItem pskBinder; /* The PSK binder for the first PSK (TLS 1.3) */ - unsigned long pskBinderPrefixLen; /* The length of the binder input. */ - PRCList remoteKeyShares; /* The other side's public keys (TLS 1.3) */ + unsigned int paddingOffset; /* Where to insert padding. 0 = end. */ + SECItem pskBinder; /* The PSK binder for the first PSK (TLS 1.3) */ + unsigned int pskBinderPrefixLen; /* The length of the binder input. */ + PRCList remoteKeyShares; /* The other side's public keys (TLS 1.3) */ }; typedef struct TLSExtensionStr { @@ -115,11 +100,11 @@ typedef struct TLSExtensionStr { SECStatus ssl3_HandleExtensions(sslSocket *ss, PRUint8 **b, PRUint32 *length, - SSL3HandshakeType handshakeMessage); + SSLHandshakeType handshakeMessage); SECStatus ssl3_ParseExtensions(sslSocket *ss, PRUint8 **b, PRUint32 *length); SECStatus ssl3_HandleParsedExtensions(sslSocket *ss, - SSL3HandshakeType handshakeMessage); + SSLHandshakeType handshakeMessage); TLSExtension *ssl3_FindExtension(sslSocket *ss, SSLExtensionType extension_type); void ssl3_DestroyRemoteExtensions(PRCList *list); @@ -132,21 +117,15 @@ PRBool ssl3_ClientExtensionAdvertised(const sslSocket *ss, PRUint16 ex_type); SECStatus ssl3_RegisterExtensionSender(const sslSocket *ss, TLSExtensionData *xtnData, PRUint16 ex_type, - ssl3HelloExtensionSenderFunc cb); -PRInt32 ssl3_CallHelloExtensionSenders(sslSocket *ss, PRBool append, PRUint32 maxBytes, - const ssl3HelloExtensionSender *sender); - -void ssl3_CalculatePaddingExtLen(sslSocket *ss, - unsigned int clientHelloLength); + sslExtensionBuilderFunc cb); +SECStatus ssl_ConstructExtensions(sslSocket *ss, sslBuffer *buf, + SSLHandshakeType message); +SECStatus ssl_SendEmptyExtension(const sslSocket *ss, TLSExtensionData *xtnData, + sslBuffer *buf, PRBool *append); +SECStatus ssl_InsertPaddingExtension(const sslSocket *ss, unsigned int prefixLen, + sslBuffer *buf); /* Thunks to let us operate on const sslSocket* objects. */ -SECStatus ssl3_ExtAppendHandshake(const sslSocket *ss, const void *void_src, - PRInt32 bytes); -SECStatus ssl3_ExtAppendHandshakeNumber(const sslSocket *ss, PRInt32 num, - PRInt32 lenSize); -SECStatus ssl3_ExtAppendHandshakeVariable(const sslSocket *ss, - const PRUint8 *src, PRInt32 bytes, - PRInt32 lenSize); void ssl3_ExtSendAlert(const sslSocket *ss, SSL3AlertLevel level, SSL3AlertDescription desc); void ssl3_ExtDecodeError(const sslSocket *ss); diff --git a/lib/ssl/ssl3exthandle.c b/lib/ssl/ssl3exthandle.c index 516f9cd79f..5723281572 100644 --- a/lib/ssl/ssl3exthandle.c +++ b/lib/ssl/ssl3exthandle.c @@ -13,7 +13,6 @@ #include "blapit.h" #include "prinit.h" #include "selfencrypt.h" -#include "ssl3encode.h" #include "ssl3ext.h" #include "ssl3exthandle.h" #include "tls13exthandle.h" /* For tls13_ServerSendStatusRequestXtn. */ @@ -22,70 +21,48 @@ * unless that name is a dotted decimal string. * Used by client and server. */ -PRInt32 -ssl3_SendServerNameXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRBool append, - PRUint32 maxBytes) +SECStatus +ssl3_ClientSendServerNameXtn(const sslSocket *ss, TLSExtensionData *xtnData, + sslBuffer *buf, PRBool *added) { + unsigned int len; + PRNetAddr netAddr; SECStatus rv; - if (!ss) - return 0; - if (!ss->sec.isServer) { - PRUint32 len; - PRNetAddr netAddr; - - /* must have a hostname */ - if (!ss->url || !ss->url[0]) - return 0; - /* must not be an IPv4 or IPv6 address */ - if (PR_SUCCESS == PR_StringToNetAddr(ss->url, &netAddr)) { - /* is an IP address (v4 or v6) */ - return 0; - } - len = PORT_Strlen(ss->url); - if (append && maxBytes >= len + 9) { - /* extension_type */ - rv = ssl3_ExtAppendHandshakeNumber(ss, ssl_server_name_xtn, 2); - if (rv != SECSuccess) - return -1; - /* length of extension_data */ - rv = ssl3_ExtAppendHandshakeNumber(ss, len + 5, 2); - if (rv != SECSuccess) - return -1; - /* length of server_name_list */ - rv = ssl3_ExtAppendHandshakeNumber(ss, len + 3, 2); - if (rv != SECSuccess) - return -1; - /* Name Type (sni_host_name) */ - rv = ssl3_ExtAppendHandshake(ss, "\0", 1); - if (rv != SECSuccess) - return -1; - /* HostName (length and value) */ - rv = ssl3_ExtAppendHandshakeVariable(ss, (PRUint8 *)ss->url, len, 2); - if (rv != SECSuccess) - return -1; - if (!ss->sec.isServer) { - xtnData->advertised[xtnData->numAdvertised++] = - ssl_server_name_xtn; - } - } - return len + 9; + + /* must have a hostname */ + if (!ss->url || !ss->url[0]) { + return SECSuccess; } - /* Server side */ - if (append && maxBytes >= 4) { - rv = ssl3_ExtAppendHandshakeNumber(ss, ssl_server_name_xtn, 2); - if (rv != SECSuccess) - return -1; - /* length of extension_data */ - rv = ssl3_ExtAppendHandshakeNumber(ss, 0, 2); - if (rv != SECSuccess) - return -1; + /* must not be an IPv4 or IPv6 address */ + if (PR_SUCCESS == PR_StringToNetAddr(ss->url, &netAddr)) { + /* is an IP address (v4 or v6) */ + return SECSuccess; + } + len = PORT_Strlen(ss->url); + /* length of server_name_list */ + rv = sslBuffer_AppendNumber(buf, len + 3, 2); + if (rv != SECSuccess) { + return SECFailure; } - return 4; + /* Name Type (sni_host_name) */ + rv = sslBuffer_AppendNumber(buf, 0, 1); + if (rv != SECSuccess) { + return SECFailure; + } + /* HostName (length and value) */ + rv = sslBuffer_AppendVariable(buf, (const PRUint8 *)ss->url, len, 2); + if (rv != SECSuccess) { + return SECFailure; + } + + *added = PR_TRUE; + return SECSuccess; } /* Handle an incoming SNI extension. */ SECStatus -ssl3_HandleServerNameXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRUint16 ex_type, SECItem *data) +ssl3_HandleServerNameXtn(const sslSocket *ss, TLSExtensionData *xtnData, + SECItem *data) { SECItem *names = NULL; PRUint32 listLenBytes = 0; @@ -194,88 +171,54 @@ ssl3_FreeSniNameArray(TLSExtensionData *xtnData) * sends an empty ticket. Servers always send empty tickets. */ PRInt32 -ssl3_SendSessionTicketXtn( - const sslSocket *ss, - TLSExtensionData *xtnData, - PRBool append, - PRUint32 maxBytes) +ssl3_ClientSendSessionTicketXtn(const sslSocket *ss, TLSExtensionData *xtnData, + sslBuffer *buf, PRBool *added) { - PRInt32 extension_length; NewSessionTicket *session_ticket = NULL; sslSessionID *sid = ss->sec.ci.sid; + SECStatus rv; + + PORT_Assert(!ss->sec.isServer); /* Never send an extension with a ticket for TLS 1.3, but * OK to send the empty one in case the server does 1.2. */ if (sid->cached == in_client_cache && sid->version >= SSL_LIBRARY_VERSION_TLS_1_3) { - return 0; + return SECSuccess; } /* Ignore the SessionTicket extension if processing is disabled. */ - if (!ss->opt.enableSessionTickets) - return 0; - - /* Empty extension length = extension_type (2-bytes) + - * length(extension_data) (2-bytes) - */ - extension_length = 4; + if (!ss->opt.enableSessionTickets) { + return SECSuccess; + } - /* If we are a client then send a session ticket if one is availble. - * Servers that support the extension and are willing to negotiate the - * the extension always respond with an empty extension. + /* Send a session ticket if one is available. + * + * The caller must be holding sid->u.ssl3.lock for reading. We cannot + * just acquire and release the lock within this function because the + * caller will call this function twice, and we need the inputs to be + * consistent between the two calls. Note that currently the caller + * will only be holding the lock when we are the client and when we're + * attempting to resume an existing session. */ - if (!ss->sec.isServer) { - /* The caller must be holding sid->u.ssl3.lock for reading. We cannot - * just acquire and release the lock within this function because the - * caller will call this function twice, and we need the inputs to be - * consistent between the two calls. Note that currently the caller - * will only be holding the lock when we are the client and when we're - * attempting to resume an existing session. - */ + session_ticket = &sid->u.ssl3.locked.sessionTicket; + if (session_ticket->ticket.data && + (xtnData->ticketTimestampVerified || + ssl_TicketTimeValid(session_ticket))) { - session_ticket = &sid->u.ssl3.locked.sessionTicket; - if (session_ticket->ticket.data) { - if (xtnData->ticketTimestampVerified) { - extension_length += session_ticket->ticket.len; - } else if (!append && ssl_TicketTimeValid(session_ticket)) { - extension_length += session_ticket->ticket.len; - xtnData->ticketTimestampVerified = PR_TRUE; - } - } - } + xtnData->ticketTimestampVerified = PR_FALSE; - if (maxBytes < (PRUint32)extension_length) { - PORT_Assert(0); - return 0; - } - if (append) { - SECStatus rv; - /* extension_type */ - rv = ssl3_ExtAppendHandshakeNumber(ss, ssl_session_ticket_xtn, 2); - if (rv != SECSuccess) - goto loser; - if (session_ticket && session_ticket->ticket.data && - xtnData->ticketTimestampVerified) { - rv = ssl3_ExtAppendHandshakeVariable(ss, session_ticket->ticket.data, - session_ticket->ticket.len, 2); - xtnData->ticketTimestampVerified = PR_FALSE; - xtnData->sentSessionTicketInClientHello = PR_TRUE; - } else { - rv = ssl3_ExtAppendHandshakeNumber(ss, 0, 2); + rv = sslBuffer_Append(buf, session_ticket->ticket.data, + session_ticket->ticket.len); + if (rv != SECSuccess) { + return SECFailure; } - if (rv != SECSuccess) - goto loser; - if (!ss->sec.isServer) { - xtnData->advertised[xtnData->numAdvertised++] = - ssl_session_ticket_xtn; - } + xtnData->sentSessionTicketInClientHello = PR_TRUE; } - return extension_length; -loser: - xtnData->ticketTimestampVerified = PR_FALSE; - return -1; + *added = PR_TRUE; + return SECSuccess; } PRBool @@ -301,7 +244,7 @@ ssl_AlpnTagAllowed(const sslSocket *ss, const SECItem *tag) /* handle an incoming Next Protocol Negotiation extension. */ SECStatus -ssl3_ServerHandleNextProtoNegoXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRUint16 ex_type, +ssl3_ServerHandleNextProtoNegoXtn(const sslSocket *ss, TLSExtensionData *xtnData, SECItem *data) { PORT_Assert(ss->version < SSL_LIBRARY_VERSION_TLS_1_3); @@ -312,7 +255,7 @@ ssl3_ServerHandleNextProtoNegoXtn(const sslSocket *ss, TLSExtensionData *xtnData return SECFailure; } - xtnData->negotiated[xtnData->numNegotiated++] = ex_type; + xtnData->negotiated[xtnData->numNegotiated++] = ssl_next_proto_nego_xtn; /* TODO: server side NPN support would require calling * ssl3_RegisterServerHelloExtensionSender here in order to echo the @@ -346,7 +289,7 @@ ssl3_ValidateNextProtoNego(const unsigned char *data, unsigned int length) /* protocol selection handler for ALPN (server side) and NPN (client side) */ static SECStatus ssl3_SelectAppProtocol(const sslSocket *ss, TLSExtensionData *xtnData, - PRUint16 ex_type, SECItem *data) + PRUint16 extension, SECItem *data) { SECStatus rv; unsigned char resultBuffer[255]; @@ -383,7 +326,7 @@ ssl3_SelectAppProtocol(const sslSocket *ss, TLSExtensionData *xtnData, SECITEM_FreeItem(&xtnData->nextProto, PR_FALSE); - if (ex_type == ssl_app_layer_protocol_xtn && + if (extension == ssl_app_layer_protocol_xtn && xtnData->nextProtoState != SSL_NEXT_PROTO_NEGOTIATED) { /* The callback might say OK, but then it picks a default value - one * that was not listed. That's OK for NPN, but not ALPN. */ @@ -392,13 +335,14 @@ ssl3_SelectAppProtocol(const sslSocket *ss, TLSExtensionData *xtnData, return SECFailure; } - xtnData->negotiated[xtnData->numNegotiated++] = ex_type; + xtnData->negotiated[xtnData->numNegotiated++] = extension; return SECITEM_CopyItem(NULL, &xtnData->nextProto, &result); } /* handle an incoming ALPN extension at the server */ SECStatus -ssl3_ServerHandleAppProtoXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRUint16 ex_type, SECItem *data) +ssl3_ServerHandleAppProtoXtn(const sslSocket *ss, TLSExtensionData *xtnData, + SECItem *data) { PRUint32 count; SECStatus rv; @@ -425,15 +369,16 @@ ssl3_ServerHandleAppProtoXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRU return SECSuccess; } - rv = ssl3_SelectAppProtocol(ss, xtnData, ex_type, data); + rv = ssl3_SelectAppProtocol(ss, xtnData, ssl_app_layer_protocol_xtn, data); if (rv != SECSuccess) { return rv; } /* prepare to send back a response, if we negotiated */ if (xtnData->nextProtoState == SSL_NEXT_PROTO_NEGOTIATED) { - rv = ssl3_RegisterExtensionSender( - ss, xtnData, ex_type, ssl3_ServerSendAppProtoXtn); + rv = ssl3_RegisterExtensionSender(ss, xtnData, + ssl_app_layer_protocol_xtn, + ssl3_ServerSendAppProtoXtn); if (rv != SECSuccess) { ssl3_ExtSendAlert(ss, alert_fatal, internal_error); PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); @@ -444,7 +389,7 @@ ssl3_ServerHandleAppProtoXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRU } SECStatus -ssl3_ClientHandleNextProtoNegoXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRUint16 ex_type, +ssl3_ClientHandleNextProtoNegoXtn(const sslSocket *ss, TLSExtensionData *xtnData, SECItem *data) { PORT_Assert(ss->version < SSL_LIBRARY_VERSION_TLS_1_3); @@ -473,11 +418,12 @@ ssl3_ClientHandleNextProtoNegoXtn(const sslSocket *ss, TLSExtensionData *xtnData return SECFailure; } - return ssl3_SelectAppProtocol(ss, xtnData, ex_type, data); + return ssl3_SelectAppProtocol(ss, xtnData, ssl_next_proto_nego_xtn, data); } SECStatus -ssl3_ClientHandleAppProtoXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRUint16 ex_type, SECItem *data) +ssl3_ClientHandleAppProtoXtn(const sslSocket *ss, TLSExtensionData *xtnData, + SECItem *data) { SECStatus rv; PRUint32 list_len; @@ -524,265 +470,168 @@ ssl3_ClientHandleAppProtoXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRU SECITEM_FreeItem(&xtnData->nextProto, PR_FALSE); xtnData->nextProtoState = SSL_NEXT_PROTO_SELECTED; - xtnData->negotiated[xtnData->numNegotiated++] = ex_type; + xtnData->negotiated[xtnData->numNegotiated++] = ssl_app_layer_protocol_xtn; return SECITEM_CopyItem(NULL, &xtnData->nextProto, &protocol_name); } -PRInt32 -ssl3_ClientSendNextProtoNegoXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRBool append, - PRUint32 maxBytes) +SECStatus +ssl3_ClientSendNextProtoNegoXtn(const sslSocket *ss, TLSExtensionData *xtnData, + sslBuffer *buf, PRBool *added) { - PRInt32 extension_length; - /* Renegotiations do not send this extension. */ if (!ss->opt.enableNPN || !ss->nextProtoCallback || ss->firstHsDone) { - return 0; - } - - extension_length = 4; - - if (maxBytes < (PRUint32)extension_length) { - return 0; - } - if (append) { - SECStatus rv; - rv = ssl3_ExtAppendHandshakeNumber(ss, ssl_next_proto_nego_xtn, 2); - if (rv != SECSuccess) - goto loser; - rv = ssl3_ExtAppendHandshakeNumber(ss, 0, 2); - if (rv != SECSuccess) - goto loser; - xtnData->advertised[xtnData->numAdvertised++] = - ssl_next_proto_nego_xtn; + return SECSuccess; } - return extension_length; - -loser: - return -1; + *added = PR_TRUE; + return SECSuccess; } -PRInt32 -ssl3_ClientSendAppProtoXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRBool append, PRUint32 maxBytes) +SECStatus +ssl3_ClientSendAppProtoXtn(const sslSocket *ss, TLSExtensionData *xtnData, + sslBuffer *buf, PRBool *added) { - PRInt32 extension_length; - unsigned char *alpn_protos = NULL; + SECStatus rv; + const unsigned int len = ss->opt.nextProtoNego.len; /* Renegotiations do not send this extension. */ if (!ss->opt.enableALPN || !ss->opt.nextProtoNego.data || ss->firstHsDone) { - return 0; + return SECSuccess; } - extension_length = 2 /* extension type */ + 2 /* extension length */ + - 2 /* protocol name list length */ + - ss->opt.nextProtoNego.len; + /* NPN requires that the client's fallback protocol is first in the + * list. However, ALPN sends protocols in preference order. So move the + * first protocol to the end of the list. */ - if (maxBytes < (PRUint32)extension_length) { - return 0; - } - if (append) { - /* NPN requires that the client's fallback protocol is first in the - * list. However, ALPN sends protocols in preference order. So we - * allocate a buffer and move the first protocol to the end of the - * list. */ - SECStatus rv; - const unsigned int len = ss->opt.nextProtoNego.len; + if (len > 0) { + /* Each protocol string is prefixed with a single byte length. */ + unsigned int i; - alpn_protos = PORT_Alloc(len); - if (alpn_protos == NULL) { + rv = sslBuffer_AppendNumber(buf, len, 2); + if (rv != SECSuccess) { return SECFailure; } - if (len > 0) { - /* Each protocol string is prefixed with a single byte length. */ - unsigned int i = ss->opt.nextProtoNego.data[0] + 1; - if (i <= len) { - memcpy(alpn_protos, &ss->opt.nextProtoNego.data[i], len - i); - memcpy(alpn_protos + len - i, ss->opt.nextProtoNego.data, i); - } else { - /* This seems to be invalid data so we'll send as-is. */ - memcpy(alpn_protos, ss->opt.nextProtoNego.data, len); - } - } - rv = ssl3_ExtAppendHandshakeNumber(ss, ssl_app_layer_protocol_xtn, 2); - if (rv != SECSuccess) { - goto loser; - } - rv = ssl3_ExtAppendHandshakeNumber(ss, extension_length - 4, 2); - if (rv != SECSuccess) { - goto loser; - } - rv = ssl3_ExtAppendHandshakeVariable(ss, alpn_protos, len, 2); - PORT_Free(alpn_protos); - alpn_protos = NULL; - if (rv != SECSuccess) { - goto loser; + i = ss->opt.nextProtoNego.data[0] + 1; + if (i <= len) { + rv = sslBuffer_Append(buf, &ss->opt.nextProtoNego.data[i], len - i); + if (rv != SECSuccess) { + return SECFailure; + } + rv = sslBuffer_Append(buf, ss->opt.nextProtoNego.data, i); + if (rv != SECSuccess) { + return SECFailure; + } + } else { + /* This seems to be invalid data so we'll send as-is. */ + rv = sslBuffer_Append(buf, ss->opt.nextProtoNego.data, len); + if (rv != SECSuccess) { + return SECFailure; + } } - xtnData->advertised[xtnData->numAdvertised++] = - ssl_app_layer_protocol_xtn; } - return extension_length; - -loser: - if (alpn_protos) { - PORT_Free(alpn_protos); - } - return -1; + *added = PR_TRUE; + return SECSuccess; } -PRInt32 -ssl3_ServerSendAppProtoXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRBool append, PRUint32 maxBytes) +SECStatus +ssl3_ServerSendAppProtoXtn(const sslSocket *ss, TLSExtensionData *xtnData, + sslBuffer *buf, PRBool *added) { - PRInt32 extension_length; + SECStatus rv; - /* we're in over our heads if any of these fail */ + /* We're in over our heads if any of these fail */ PORT_Assert(ss->opt.enableALPN); PORT_Assert(xtnData->nextProto.data); PORT_Assert(xtnData->nextProto.len > 0); PORT_Assert(xtnData->nextProtoState == SSL_NEXT_PROTO_NEGOTIATED); PORT_Assert(!ss->firstHsDone); - extension_length = 2 /* extension type */ + 2 /* extension length */ + - 2 /* protocol name list */ + 1 /* name length */ + - xtnData->nextProto.len; - - if (maxBytes < (PRUint32)extension_length) { - return 0; + rv = sslBuffer_AppendNumber(buf, xtnData->nextProto.len + 1, 2); + if (rv != SECSuccess) { + return SECFailure; } - if (append) { - SECStatus rv; - rv = ssl3_ExtAppendHandshakeNumber(ss, ssl_app_layer_protocol_xtn, 2); - if (rv != SECSuccess) { - return -1; - } - rv = ssl3_ExtAppendHandshakeNumber(ss, extension_length - 4, 2); - if (rv != SECSuccess) { - return -1; - } - rv = ssl3_ExtAppendHandshakeNumber(ss, xtnData->nextProto.len + 1, 2); - if (rv != SECSuccess) { - return -1; - } - rv = ssl3_ExtAppendHandshakeVariable(ss, xtnData->nextProto.data, - xtnData->nextProto.len, 1); - if (rv != SECSuccess) { - return -1; - } + rv = sslBuffer_AppendVariable(buf, xtnData->nextProto.data, + xtnData->nextProto.len, 1); + if (rv != SECSuccess) { + return SECFailure; } - return extension_length; + *added = PR_TRUE; + return SECSuccess; } SECStatus -ssl3_ServerHandleStatusRequestXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRUint16 ex_type, +ssl3_ServerHandleStatusRequestXtn(const sslSocket *ss, TLSExtensionData *xtnData, SECItem *data) { - ssl3HelloExtensionSenderFunc sender; + sslExtensionBuilderFunc sender; PORT_Assert(ss->sec.isServer); /* remember that we got this extension. */ - xtnData->negotiated[xtnData->numNegotiated++] = ex_type; + xtnData->negotiated[xtnData->numNegotiated++] = ssl_cert_status_xtn; if (ss->version >= SSL_LIBRARY_VERSION_TLS_1_3) { sender = tls13_ServerSendStatusRequestXtn; } else { sender = ssl3_ServerSendStatusRequestXtn; } - return ssl3_RegisterExtensionSender(ss, xtnData, ex_type, sender); + return ssl3_RegisterExtensionSender(ss, xtnData, ssl_cert_status_xtn, sender); } -PRInt32 -ssl3_ServerSendStatusRequestXtn( - const sslSocket *ss, - TLSExtensionData *xtnData, - PRBool append, - PRUint32 maxBytes) +SECStatus +ssl3_ServerSendStatusRequestXtn(const sslSocket *ss, TLSExtensionData *xtnData, + sslBuffer *buf, PRBool *added) { - PRInt32 extension_length; const sslServerCert *serverCert = ss->sec.serverCert; - SECStatus rv; if (!serverCert->certStatusArray || !serverCert->certStatusArray->len) { - return 0; - } - - extension_length = 2 + 2; - if (maxBytes < (PRUint32)extension_length) { - return 0; - } - if (append) { - /* extension_type */ - rv = ssl3_ExtAppendHandshakeNumber(ss, ssl_cert_status_xtn, 2); - if (rv != SECSuccess) - return -1; - /* length of extension_data */ - rv = ssl3_ExtAppendHandshakeNumber(ss, 0, 2); - if (rv != SECSuccess) - return -1; - /* The certificate status data is sent in ssl3_SendCertificateStatus. */ + return SECSuccess; } - return extension_length; + *added = PR_TRUE; + return SECSuccess; } /* ssl3_ClientSendStatusRequestXtn builds the status_request extension on the * client side. See RFC 6066 section 8. */ -PRInt32 -ssl3_ClientSendStatusRequestXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRBool append, - PRUint32 maxBytes) +SECStatus +ssl3_ClientSendStatusRequestXtn(const sslSocket *ss, TLSExtensionData *xtnData, + sslBuffer *buf, PRBool *added) { - PRInt32 extension_length; - - if (!ss->opt.enableOCSPStapling) - return 0; - - /* extension_type (2-bytes) + - * length(extension_data) (2-bytes) + - * status_type (1) + - * responder_id_list length (2) + - * request_extensions length (2) - */ - extension_length = 9; + SECStatus rv; - if (maxBytes < (PRUint32)extension_length) { - PORT_Assert(0); - return 0; + if (!ss->opt.enableOCSPStapling) { + return SECSuccess; } - if (append) { - SECStatus rv; - - /* extension_type */ - rv = ssl3_ExtAppendHandshakeNumber(ss, ssl_cert_status_xtn, 2); - if (rv != SECSuccess) - return -1; - rv = ssl3_ExtAppendHandshakeNumber(ss, extension_length - 4, 2); - if (rv != SECSuccess) - return -1; - rv = ssl3_ExtAppendHandshakeNumber(ss, 1 /* status_type ocsp */, 1); - if (rv != SECSuccess) - return -1; - /* A zero length responder_id_list means that the responders are - * implicitly known to the server. */ - rv = ssl3_ExtAppendHandshakeNumber(ss, 0, 2); - if (rv != SECSuccess) - return -1; - /* A zero length request_extensions means that there are no extensions. - * Specifically, we don't set the id-pkix-ocsp-nonce extension. This - * means that the server can replay a cached OCSP response to us. */ - rv = ssl3_ExtAppendHandshakeNumber(ss, 0, 2); - if (rv != SECSuccess) - return -1; - xtnData->advertised[xtnData->numAdvertised++] = ssl_cert_status_xtn; + rv = sslBuffer_AppendNumber(buf, 1 /* status_type ocsp */, 1); + if (rv != SECSuccess) { + return SECFailure; + } + /* A zero length responder_id_list means that the responders are + * implicitly known to the server. */ + rv = sslBuffer_AppendNumber(buf, 0, 2); + if (rv != SECSuccess) { + return SECFailure; } - return extension_length; + /* A zero length request_extensions means that there are no extensions. + * Specifically, we don't set the id-pkix-ocsp-nonce extension. This + * means that the server can replay a cached OCSP response to us. */ + rv = sslBuffer_AppendNumber(buf, 0, 2); + if (rv != SECSuccess) { + return SECFailure; + } + + *added = PR_TRUE; + return SECSuccess; } SECStatus -ssl3_ClientHandleStatusRequestXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRUint16 ex_type, +ssl3_ClientHandleStatusRequestXtn(const sslSocket *ss, TLSExtensionData *xtnData, SECItem *data) { /* In TLS 1.3, the extension carries the OCSP response. */ @@ -800,7 +649,7 @@ ssl3_ClientHandleStatusRequestXtn(const sslSocket *ss, TLSExtensionData *xtnData } /* Keep track of negotiated extensions. */ - xtnData->negotiated[xtnData->numNegotiated++] = ex_type; + xtnData->negotiated[xtnData->numNegotiated++] = ssl_cert_status_xtn; return SECSuccess; } @@ -1070,7 +919,7 @@ ssl3_EncodeSessionTicket(sslSocket *ss, * message is expected during the handshake. */ SECStatus -ssl3_ClientHandleSessionTicketXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRUint16 ex_type, +ssl3_ClientHandleSessionTicketXtn(const sslSocket *ss, TLSExtensionData *xtnData, SECItem *data) { PORT_Assert(ss->version < SSL_LIBRARY_VERSION_TLS_1_3); @@ -1080,7 +929,7 @@ ssl3_ClientHandleSessionTicketXtn(const sslSocket *ss, TLSExtensionData *xtnData } /* Keep track of negotiated extensions. */ - xtnData->negotiated[xtnData->numNegotiated++] = ex_type; + xtnData->negotiated[xtnData->numNegotiated++] = ssl_session_ticket_xtn; return SECSuccess; } @@ -1456,7 +1305,7 @@ ssl3_ProcessSessionTicketCommon(sslSocket *ss, SECItem *data) } SECStatus -ssl3_ServerHandleSessionTicketXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRUint16 ex_type, +ssl3_ServerHandleSessionTicketXtn(const sslSocket *ss, TLSExtensionData *xtnData, SECItem *data) { PORT_Assert(ss->version < SSL_LIBRARY_VERSION_TLS_1_3); @@ -1472,7 +1321,7 @@ ssl3_ServerHandleSessionTicketXtn(const sslSocket *ss, TLSExtensionData *xtnData } /* Keep track of negotiated extensions. */ - xtnData->negotiated[xtnData->numNegotiated++] = ex_type; + xtnData->negotiated[xtnData->numNegotiated++] = ssl_session_ticket_xtn; /* Parse the received ticket sent in by the client. We are * lenient about some parse errors, falling back to a fullshake @@ -1493,57 +1342,41 @@ ssl3_ServerHandleSessionTicketXtn(const sslSocket *ss, TLSExtensionData *xtnData * Verify Data (TLS): 12 bytes (client) or 24 bytes (server) * Verify Data (SSL): 36 bytes (client) or 72 bytes (server) */ -PRInt32 -ssl3_SendRenegotiationInfoXtn( - const sslSocket *ss, - TLSExtensionData *xtnData, - PRBool append, - PRUint32 maxBytes) +SECStatus +ssl3_SendRenegotiationInfoXtn(const sslSocket *ss, TLSExtensionData *xtnData, + sslBuffer *buf, PRBool *added) { PRInt32 len = 0; - PRInt32 needed; + SECStatus rv; /* In draft-ietf-tls-renegotiation-03, it is NOT RECOMMENDED to send * both the SCSV and the empty RI, so when we send SCSV in * the initial handshake, we don't also send RI. */ - if (!ss || ss->ssl3.hs.sendingSCSV) - return 0; + if (!ss || ss->ssl3.hs.sendingSCSV) { + return SECSuccess; + } + if (ss->firstHsDone) { len = ss->sec.isServer ? ss->ssl3.hs.finishedBytes * 2 : ss->ssl3.hs.finishedBytes; } - needed = 5 + len; - if (maxBytes < (PRUint32)needed) { - return 0; - } - if (append) { - SECStatus rv; - /* extension_type */ - rv = ssl3_ExtAppendHandshakeNumber(ss, ssl_renegotiation_info_xtn, 2); - if (rv != SECSuccess) - return -1; - /* length of extension_data */ - rv = ssl3_ExtAppendHandshakeNumber(ss, len + 1, 2); - if (rv != SECSuccess) - return -1; - /* verify_Data from previous Finished message(s) */ - rv = ssl3_ExtAppendHandshakeVariable(ss, - ss->ssl3.hs.finishedMsgs.data, len, 1); - if (rv != SECSuccess) - return -1; - if (!ss->sec.isServer) { - xtnData->advertised[xtnData->numAdvertised++] = - ssl_renegotiation_info_xtn; - } + + /* verify_Data from previous Finished message(s) */ + rv = sslBuffer_AppendVariable(buf, + ss->ssl3.hs.finishedMsgs.data, len, 1); + if (rv != SECSuccess) { + return SECFailure; } - return needed; + + *added = PR_TRUE; + return SECSuccess; } /* This function runs in both the client and server. */ SECStatus ssl3_HandleRenegotiationInfoXtn(const sslSocket *ss, TLSExtensionData *xtnData, - PRUint16 ex_type, SECItem *data) + SECItem *data) { SECStatus rv = SECSuccess; PRUint32 len = 0; @@ -1567,97 +1400,78 @@ ssl3_HandleRenegotiationInfoXtn(const sslSocket *ss, TLSExtensionData *xtnData, /* remember that we got this extension and it was correct. */ CONST_CAST(sslSocket, ss) ->peerRequestedProtection = 1; - xtnData->negotiated[xtnData->numNegotiated++] = ex_type; + xtnData->negotiated[xtnData->numNegotiated++] = ssl_renegotiation_info_xtn; if (ss->sec.isServer) { /* prepare to send back the appropriate response */ - rv = ssl3_RegisterExtensionSender(ss, xtnData, ex_type, + rv = ssl3_RegisterExtensionSender(ss, xtnData, + ssl_renegotiation_info_xtn, ssl3_SendRenegotiationInfoXtn); } return rv; } -PRInt32 -ssl3_ClientSendUseSRTPXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRBool append, PRUint32 maxBytes) +SECStatus +ssl3_ClientSendUseSRTPXtn(const sslSocket *ss, TLSExtensionData *xtnData, + sslBuffer *buf, PRBool *added) { - PRUint32 ext_data_len; - PRInt16 i; + unsigned int i; SECStatus rv; - if (!ss) - return 0; - - if (!IS_DTLS(ss) || !ss->ssl3.dtlsSRTPCipherCount) - return 0; /* Not relevant */ - - ext_data_len = 2 + 2 * ss->ssl3.dtlsSRTPCipherCount + 1; + if (!IS_DTLS(ss) || !ss->ssl3.dtlsSRTPCipherCount) { + return SECSuccess; /* Not relevant */ + } - if (append && maxBytes >= 4 + ext_data_len) { - /* Extension type */ - rv = ssl3_ExtAppendHandshakeNumber(ss, ssl_use_srtp_xtn, 2); - if (rv != SECSuccess) - return -1; - /* Length of extension data */ - rv = ssl3_ExtAppendHandshakeNumber(ss, ext_data_len, 2); - if (rv != SECSuccess) - return -1; - /* Length of the SRTP cipher list */ - rv = ssl3_ExtAppendHandshakeNumber(ss, - 2 * ss->ssl3.dtlsSRTPCipherCount, - 2); - if (rv != SECSuccess) - return -1; - /* The SRTP ciphers */ - for (i = 0; i < ss->ssl3.dtlsSRTPCipherCount; i++) { - rv = ssl3_ExtAppendHandshakeNumber(ss, - ss->ssl3.dtlsSRTPCiphers[i], - 2); - if (rv != SECSuccess) - return -1; + /* Length of the SRTP cipher list */ + rv = sslBuffer_AppendNumber(buf, 2 * ss->ssl3.dtlsSRTPCipherCount, 2); + if (rv != SECSuccess) { + return SECFailure; + } + /* The SRTP ciphers */ + for (i = 0; i < ss->ssl3.dtlsSRTPCipherCount; i++) { + rv = sslBuffer_AppendNumber(buf, ss->ssl3.dtlsSRTPCiphers[i], 2); + if (rv != SECSuccess) { + return SECFailure; } - /* Empty MKI value */ - ssl3_ExtAppendHandshakeVariable(ss, NULL, 0, 1); - - xtnData->advertised[xtnData->numAdvertised++] = - ssl_use_srtp_xtn; + } + /* Empty MKI value */ + rv = sslBuffer_AppendNumber(buf, 0, 1); + if (rv != SECSuccess) { + return SECFailure; } - return 4 + ext_data_len; + *added = PR_TRUE; + return SECSuccess; } -PRInt32 -ssl3_ServerSendUseSRTPXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRBool append, PRUint32 maxBytes) +SECStatus +ssl3_ServerSendUseSRTPXtn(const sslSocket *ss, TLSExtensionData *xtnData, + sslBuffer *buf, PRBool *added) { SECStatus rv; - /* Server side */ - if (!append || maxBytes < 9) { - return 9; - } - - /* Extension type */ - rv = ssl3_ExtAppendHandshakeNumber(ss, ssl_use_srtp_xtn, 2); - if (rv != SECSuccess) - return -1; - /* Length of extension data */ - rv = ssl3_ExtAppendHandshakeNumber(ss, 5, 2); - if (rv != SECSuccess) - return -1; /* Length of the SRTP cipher list */ - rv = ssl3_ExtAppendHandshakeNumber(ss, 2, 2); - if (rv != SECSuccess) - return -1; + rv = sslBuffer_AppendNumber(buf, 2, 2); + if (rv != SECSuccess) { + return SECFailure; + } /* The selected cipher */ - rv = ssl3_ExtAppendHandshakeNumber(ss, xtnData->dtlsSRTPCipherSuite, 2); - if (rv != SECSuccess) - return -1; + rv = sslBuffer_AppendNumber(buf, xtnData->dtlsSRTPCipherSuite, 2); + if (rv != SECSuccess) { + return SECFailure; + } /* Empty MKI value */ - ssl3_ExtAppendHandshakeVariable(ss, NULL, 0, 1); + rv = sslBuffer_AppendNumber(buf, 0, 1); + if (rv != SECSuccess) { + return SECFailure; + } - return 9; + *added = PR_TRUE; + return SECSuccess; } SECStatus -ssl3_ClientHandleUseSRTPXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRUint16 ex_type, SECItem *data) +ssl3_ClientHandleUseSRTPXtn(const sslSocket *ss, TLSExtensionData *xtnData, + SECItem *data) { SECStatus rv; SECItem ciphers = { siBuffer, NULL, 0 }; @@ -1727,7 +1541,8 @@ ssl3_ClientHandleUseSRTPXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRUi } SECStatus -ssl3_ServerHandleUseSRTPXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRUint16 ex_type, SECItem *data) +ssl3_ServerHandleUseSRTPXtn(const sslSocket *ss, TLSExtensionData *xtnData, + SECItem *data) { SECStatus rv; SECItem ciphers = { siBuffer, NULL, 0 }; @@ -1803,7 +1618,7 @@ ssl3_ServerHandleUseSRTPXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRUi * extensions. See https://tools.ietf.org/html/rfc5246#section-7.4.1.4.1 */ SECStatus ssl3_HandleSigAlgsXtn(const sslSocket *ss, TLSExtensionData *xtnData, - PRUint16 ex_type, SECItem *data) + SECItem *data) { SECStatus rv; @@ -1833,176 +1648,54 @@ ssl3_HandleSigAlgsXtn(const sslSocket *ss, TLSExtensionData *xtnData, } /* Keep track of negotiated extensions. */ - xtnData->negotiated[xtnData->numNegotiated++] = ex_type; + xtnData->negotiated[xtnData->numNegotiated++] = ssl_signature_algorithms_xtn; return SECSuccess; } /* ssl3_ClientSendSigAlgsXtn sends the signature_algorithm extension for TLS * 1.2 ClientHellos. */ -PRInt32 +SECStatus ssl3_SendSigAlgsXtn(const sslSocket *ss, TLSExtensionData *xtnData, - PRBool append, PRUint32 maxBytes) + sslBuffer *buf, PRBool *added) { - PRInt32 extension_length; - PRUint8 buf[MAX_SIGNATURE_SCHEMES * 2]; + PRUint8 schemes[MAX_SIGNATURE_SCHEMES * 2]; PRUint32 len; SECStatus rv; if (ss->vrange.max < SSL_LIBRARY_VERSION_TLS_1_2) { - return 0; - } - - rv = ssl3_EncodeSigAlgs(ss, buf, sizeof(buf), &len); - if (rv != SECSuccess) { - return -1; - } - - extension_length = - 2 /* extension type */ + - 2 /* extension length */ + - 2 /* supported_signature_algorithms length */ + - len; - - if (maxBytes < extension_length) { - PORT_Assert(0); - return 0; - } - - if (append) { - SECStatus rv; - rv = ssl3_ExtAppendHandshakeNumber(ss, ssl_signature_algorithms_xtn, 2); - if (rv != SECSuccess) { - return -1; - } - rv = ssl3_ExtAppendHandshakeNumber(ss, len + 2, 2); - if (rv != SECSuccess) { - return -1; - } - - rv = ssl3_ExtAppendHandshakeVariable(ss, buf, len, 2); - if (rv != SECSuccess) { - return -1; - } - - xtnData->advertised[xtnData->numAdvertised++] = - ssl_signature_algorithms_xtn; - } - - return extension_length; -} - -/* Takes the size of the ClientHello, less the record header, and determines how - * much padding is required. */ -void -ssl3_CalculatePaddingExtLen(sslSocket *ss, - unsigned int clientHelloLength) -{ - unsigned int recordLength = 1 /* handshake message type */ + - 3 /* handshake message length */ + - clientHelloLength; - unsigned int extensionLen; - - /* Don't pad for DTLS, for SSLv3, or for renegotiation. */ - if (IS_DTLS(ss) || - ss->vrange.max < SSL_LIBRARY_VERSION_TLS_1_0 || - ss->firstHsDone) { - return; - } - - /* A padding extension may be included to ensure that the record containing - * the ClientHello doesn't have a length between 256 and 511 bytes - * (inclusive). Initial ClientHello records with such lengths trigger bugs - * in F5 devices. */ - if (recordLength < 256 || recordLength >= 512) { - return; - } - - extensionLen = 512 - recordLength; - /* Extensions take at least four bytes to encode. Always include at least - * one byte of data if we are padding. Some servers will time out or - * terminate the connection if the last ClientHello extension is empty. */ - if (extensionLen < 4 + 1) { - extensionLen = 4 + 1; - } - - ss->xtnData.paddingLen = extensionLen - 4; -} - -/* ssl3_SendPaddingExtension possibly adds an extension which ensures that a - * ClientHello record is either < 256 bytes or is >= 512 bytes. This ensures - * that we don't trigger bugs in F5 products. */ -PRInt32 -ssl3_ClientSendPaddingExtension(const sslSocket *ss, TLSExtensionData *xtnData, - PRBool append, PRUint32 maxBytes) -{ - static unsigned char padding[252] = { 0 }; - unsigned int extensionLen; - SECStatus rv; - - /* On the length-calculation pass, report zero total length. The record - * will be larger on the second pass if needed. */ - if (!append || !xtnData->paddingLen) { - return 0; - } - - extensionLen = xtnData->paddingLen + 4; - if (extensionLen > maxBytes || - xtnData->paddingLen > sizeof(padding)) { - PORT_Assert(0); - return -1; + return SECSuccess; } - rv = ssl3_ExtAppendHandshakeNumber(ss, ssl_padding_xtn, 2); + rv = ssl3_EncodeSigAlgs(ss, schemes, sizeof(schemes), &len); if (rv != SECSuccess) { - return -1; + return SECFailure; } - rv = ssl3_ExtAppendHandshakeVariable(ss, padding, xtnData->paddingLen, 2); + rv = sslBuffer_AppendVariable(buf, schemes, len, 2); if (rv != SECSuccess) { return -1; } - return extensionLen; + *added = PR_TRUE; + return SECSuccess; } -PRInt32 -ssl3_SendExtendedMasterSecretXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRBool append, - PRUint32 maxBytes) +SECStatus +ssl3_SendExtendedMasterSecretXtn(const sslSocket *ss, TLSExtensionData *xtnData, + sslBuffer *buf, PRBool *added) { - PRInt32 extension_length; - if (!ss->opt.enableExtendedMS) { - return 0; + return SECSuccess; } /* Always send the extension in this function, since the * client always sends it and this function is only called on * the server if we negotiated the extension. */ - extension_length = 4; /* Type + length (0) */ - if (maxBytes < extension_length) { - PORT_Assert(0); - return 0; - } - - if (append) { - SECStatus rv; - rv = ssl3_ExtAppendHandshakeNumber(ss, ssl_extended_master_secret_xtn, 2); - if (rv != SECSuccess) - goto loser; - rv = ssl3_ExtAppendHandshakeNumber(ss, 0, 2); - if (rv != SECSuccess) - goto loser; - xtnData->advertised[xtnData->numAdvertised++] = - ssl_extended_master_secret_xtn; - } - - return extension_length; - -loser: - return -1; + *added = PR_TRUE; + return SECSuccess; } SECStatus -ssl3_HandleExtendedMasterSecretXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRUint16 ex_type, +ssl3_HandleExtendedMasterSecretXtn(const sslSocket *ss, TLSExtensionData *xtnData, SECItem *data) { PORT_Assert(ss->version < SSL_LIBRARY_VERSION_TLS_1_3); @@ -2026,54 +1719,34 @@ ssl3_HandleExtendedMasterSecretXtn(const sslSocket *ss, TLSExtensionData *xtnDat SSL_GETPID(), ss->fd)); /* Keep track of negotiated extensions. */ - xtnData->negotiated[xtnData->numNegotiated++] = ex_type; + xtnData->negotiated[xtnData->numNegotiated++] = ssl_extended_master_secret_xtn; if (ss->sec.isServer) { - return ssl3_RegisterExtensionSender( - ss, xtnData, ex_type, ssl3_SendExtendedMasterSecretXtn); + return ssl3_RegisterExtensionSender(ss, xtnData, + ssl_extended_master_secret_xtn, + ssl_SendEmptyExtension); } return SECSuccess; } /* ssl3_ClientSendSignedCertTimestampXtn sends the signed_certificate_timestamp * extension for TLS ClientHellos. */ -PRInt32 -ssl3_ClientSendSignedCertTimestampXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRBool append, - PRUint32 maxBytes) +SECStatus +ssl3_ClientSendSignedCertTimestampXtn(const sslSocket *ss, + TLSExtensionData *xtnData, + sslBuffer *buf, PRBool *added) { - PRInt32 extension_length = 2 /* extension_type */ + - 2 /* length(extension_data) */; - /* Only send the extension if processing is enabled. */ - if (!ss->opt.enableSignedCertTimestamps) - return 0; - - if (append && maxBytes >= extension_length) { - SECStatus rv; - /* extension_type */ - rv = ssl3_ExtAppendHandshakeNumber(ss, - ssl_signed_cert_timestamp_xtn, - 2); - if (rv != SECSuccess) - goto loser; - /* zero length */ - rv = ssl3_ExtAppendHandshakeNumber(ss, 0, 2); - if (rv != SECSuccess) - goto loser; - xtnData->advertised[xtnData->numAdvertised++] = - ssl_signed_cert_timestamp_xtn; - } else if (maxBytes < extension_length) { - PORT_Assert(0); - return 0; + if (!ss->opt.enableSignedCertTimestamps) { + return SECSuccess; } - return extension_length; -loser: - return -1; + *added = PR_TRUE; + return SECSuccess; } SECStatus -ssl3_ClientHandleSignedCertTimestampXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRUint16 ex_type, +ssl3_ClientHandleSignedCertTimestampXtn(const sslSocket *ss, TLSExtensionData *xtnData, SECItem *data) { /* We do not yet know whether we'll be resuming a session or creating @@ -2093,54 +1766,34 @@ ssl3_ClientHandleSignedCertTimestampXtn(const sslSocket *ss, TLSExtensionData *x } *scts = *data; /* Keep track of negotiated extensions. */ - xtnData->negotiated[xtnData->numNegotiated++] = ex_type; + xtnData->negotiated[xtnData->numNegotiated++] = ssl_signed_cert_timestamp_xtn; return SECSuccess; } -PRInt32 +SECStatus ssl3_ServerSendSignedCertTimestampXtn(const sslSocket *ss, TLSExtensionData *xtnData, - PRBool append, - PRUint32 maxBytes) + sslBuffer *buf, PRBool *added) { - PRInt32 extension_length; const SECItem *scts = &ss->sec.serverCert->signedCertTimestamps; + SECStatus rv; if (!scts->len) { /* No timestamps to send */ - return 0; + return SECSuccess; } - extension_length = 2 /* extension_type */ + - 2 /* length(extension_data) */ + - scts->len; - - if (maxBytes < extension_length) { - PORT_Assert(0); - return 0; - } - if (append) { - SECStatus rv; - /* extension_type */ - rv = ssl3_ExtAppendHandshakeNumber(ss, - ssl_signed_cert_timestamp_xtn, - 2); - if (rv != SECSuccess) { - return -1; - } - /* extension_data */ - rv = ssl3_ExtAppendHandshakeVariable(ss, scts->data, scts->len, 2); - if (rv != SECSuccess) { - return -1; - } + rv = sslBuffer_Append(buf, scts->data, scts->len); + if (rv != SECSuccess) { + return SECFailure; } - return extension_length; + *added = PR_TRUE; + return SECSuccess; } SECStatus ssl3_ServerHandleSignedCertTimestampXtn(const sslSocket *ss, TLSExtensionData *xtnData, - PRUint16 ex_type, SECItem *data) { if (data->len != 0) { @@ -2149,10 +1802,11 @@ ssl3_ServerHandleSignedCertTimestampXtn(const sslSocket *ss, return SECFailure; } - xtnData->negotiated[xtnData->numNegotiated++] = ex_type; + xtnData->negotiated[xtnData->numNegotiated++] = ssl_signed_cert_timestamp_xtn; PORT_Assert(ss->sec.isServer); - return ssl3_RegisterExtensionSender( - ss, xtnData, ex_type, ssl3_ServerSendSignedCertTimestampXtn); + return ssl3_RegisterExtensionSender(ss, xtnData, + ssl_signed_cert_timestamp_xtn, + ssl3_ServerSendSignedCertTimestampXtn); } /* Just make sure that the remote client supports uncompressed points, @@ -2160,7 +1814,6 @@ ssl3_ServerHandleSignedCertTimestampXtn(const sslSocket *ss, */ SECStatus ssl3_HandleSupportedPointFormatsXtn(const sslSocket *ss, TLSExtensionData *xtnData, - PRUint16 ex_type, SECItem *data) { int i; @@ -2175,10 +1828,9 @@ ssl3_HandleSupportedPointFormatsXtn(const sslSocket *ss, TLSExtensionData *xtnDa for (i = data->len; --i > 0;) { if (data->data[i] == 0) { /* indicate that we should send a reply */ - SECStatus rv; - rv = ssl3_RegisterExtensionSender(ss, xtnData, ex_type, - &ssl3_SendSupportedPointFormatsXtn); - return rv; + return ssl3_RegisterExtensionSender( + ss, xtnData, ssl_ec_point_formats_xtn, + &ssl3_SendSupportedPointFormatsXtn); } } @@ -2263,7 +1915,7 @@ ssl_UpdateSupportedGroups(sslSocket *ss, SECItem *data) */ SECStatus ssl_HandleSupportedGroupsXtn(const sslSocket *ss, TLSExtensionData *xtnData, - PRUint16 ex_type, SECItem *data) + SECItem *data) { SECStatus rv; @@ -2273,7 +1925,7 @@ ssl_HandleSupportedGroupsXtn(const sslSocket *ss, TLSExtensionData *xtnData, /* TLS 1.3 permits the server to send this extension so make it so. */ if (ss->sec.isServer && ss->version >= SSL_LIBRARY_VERSION_TLS_1_3) { - rv = ssl3_RegisterExtensionSender(ss, xtnData, ex_type, + rv = ssl3_RegisterExtensionSender(ss, xtnData, ssl_supported_groups_xtn, &ssl_SendSupportedGroupsXtn); if (rv != SECSuccess) { return SECFailure; /* error already set. */ @@ -2281,7 +1933,7 @@ ssl_HandleSupportedGroupsXtn(const sslSocket *ss, TLSExtensionData *xtnData, } /* Remember that we negotiated this extension. */ - xtnData->negotiated[xtnData->numNegotiated++] = ex_type; + xtnData->negotiated[xtnData->numNegotiated++] = ssl_supported_groups_xtn; return SECSuccess; } diff --git a/lib/ssl/ssl3exthandle.h b/lib/ssl/ssl3exthandle.h index 281020b953..75ef38631b 100644 --- a/lib/ssl/ssl3exthandle.h +++ b/lib/ssl/ssl3exthandle.h @@ -9,90 +9,113 @@ #ifndef __ssl3exthandle_h_ #define __ssl3exthandle_h_ -PRInt32 ssl3_SendRenegotiationInfoXtn(const sslSocket *ss, TLSExtensionData *xtnData, - PRBool append, PRUint32 maxBytes); -SECStatus ssl3_HandleRenegotiationInfoXtn(const sslSocket *ss, TLSExtensionData *xtnData, - PRUint16 ex_type, SECItem *data); -SECStatus ssl3_ClientHandleNextProtoNegoXtn(const sslSocket *ss, TLSExtensionData *xtnData, - PRUint16 ex_type, SECItem *data); -SECStatus ssl3_ClientHandleAppProtoXtn(const sslSocket *ss, TLSExtensionData *xtnData, - PRUint16 ex_type, SECItem *data); -SECStatus ssl3_ServerHandleNextProtoNegoXtn(const sslSocket *ss, TLSExtensionData *xtnData, - PRUint16 ex_type, SECItem *data); -SECStatus ssl3_ServerHandleAppProtoXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRUint16 ex_type, +#include "sslencode.h" + +SECStatus ssl3_SendRenegotiationInfoXtn(const sslSocket *ss, + TLSExtensionData *xtnData, + sslBuffer *buf, PRBool *added); +SECStatus ssl3_HandleRenegotiationInfoXtn(const sslSocket *ss, + TLSExtensionData *xtnData, + SECItem *data); +SECStatus ssl3_ClientHandleNextProtoNegoXtn(const sslSocket *ss, + TLSExtensionData *xtnData, + SECItem *data); +SECStatus ssl3_ClientHandleAppProtoXtn(const sslSocket *ss, + TLSExtensionData *xtnData, + SECItem *data); +SECStatus ssl3_ServerHandleNextProtoNegoXtn(const sslSocket *ss, + TLSExtensionData *xtnData, + SECItem *data); +SECStatus ssl3_ServerHandleAppProtoXtn(const sslSocket *ss, + TLSExtensionData *xtnData, SECItem *data); -PRInt32 ssl3_ClientSendNextProtoNegoXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRBool append, - PRUint32 maxBytes); -PRInt32 ssl3_ClientSendAppProtoXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRBool append, - PRUint32 maxBytes); -PRInt32 ssl3_ServerSendAppProtoXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRBool append, - PRUint32 maxBytes); -PRInt32 ssl3_ClientSendUseSRTPXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRBool append, - PRUint32 maxBytes); -PRInt32 ssl3_ServerSendUseSRTPXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRBool append, - PRUint32 maxBytes); -SECStatus ssl3_ClientHandleUseSRTPXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRUint16 ex_type, +SECStatus ssl3_ClientSendNextProtoNegoXtn(const sslSocket *ss, + TLSExtensionData *xtnData, + sslBuffer *buf, PRBool *added); +SECStatus ssl3_ClientSendAppProtoXtn(const sslSocket *ss, + TLSExtensionData *xtnData, + sslBuffer *buf, PRBool *added); +SECStatus ssl3_ServerSendAppProtoXtn(const sslSocket *ss, + TLSExtensionData *xtnData, + sslBuffer *buf, PRBool *added); +SECStatus ssl3_ClientSendUseSRTPXtn(const sslSocket *ss, + TLSExtensionData *xtnData, + sslBuffer *buf, PRBool *added); +SECStatus ssl3_ServerSendUseSRTPXtn(const sslSocket *ss, + TLSExtensionData *xtnData, + sslBuffer *buf, PRBool *added); +SECStatus ssl3_ClientHandleUseSRTPXtn(const sslSocket *ss, + TLSExtensionData *xtnData, SECItem *data); -SECStatus ssl3_ServerHandleUseSRTPXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRUint16 ex_type, +SECStatus ssl3_ServerHandleUseSRTPXtn(const sslSocket *ss, + TLSExtensionData *xtnData, SECItem *data); -PRInt32 ssl3_ServerSendStatusRequestXtn(const sslSocket *ss, TLSExtensionData *xtnData, - PRBool append, PRUint32 maxBytes); -SECStatus ssl3_ServerHandleStatusRequestXtn(const sslSocket *ss, TLSExtensionData *xtnData, - PRUint16 ex_type, SECItem *data); -SECStatus ssl3_ClientHandleStatusRequestXtn(const sslSocket *ss, TLSExtensionData *xtnData, - PRUint16 ex_type, +SECStatus ssl3_ServerSendStatusRequestXtn(const sslSocket *ss, + TLSExtensionData *xtnData, + sslBuffer *buf, PRBool *added); +SECStatus ssl3_ServerHandleStatusRequestXtn(const sslSocket *ss, + TLSExtensionData *xtnData, + SECItem *data); +SECStatus ssl3_ClientHandleStatusRequestXtn(const sslSocket *ss, + TLSExtensionData *xtnData, SECItem *data); -PRInt32 ssl3_ClientSendStatusRequestXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRBool append, - PRUint32 maxBytes); -PRInt32 ssl3_SendSigAlgsXtn(const sslSocket *ss, TLSExtensionData *xtnData, - PRBool append, PRUint32 maxBytes); +SECStatus ssl3_ClientSendStatusRequestXtn(const sslSocket *ss, + TLSExtensionData *xtnData, + sslBuffer *buf, PRBool *added); +SECStatus ssl3_SendSigAlgsXtn(const sslSocket *ss, TLSExtensionData *xtnData, + sslBuffer *buf, PRBool *added); SECStatus ssl3_HandleSigAlgsXtn(const sslSocket *ss, TLSExtensionData *xtnData, - PRUint16 ex_type, SECItem *data); + SECItem *data); -PRInt32 ssl3_ClientSendPaddingExtension(const sslSocket *ss, TLSExtensionData *xtnData, - PRBool append, PRUint32 maxBytes); +SECStatus ssl3_ClientSendPaddingExtension(const sslSocket *ss, + TLSExtensionData *xtnData, + sslBuffer *buf, PRBool *added); -PRInt32 ssl3_ClientSendSignedCertTimestampXtn(const sslSocket *ss, TLSExtensionData *xtnData, - PRBool append, - PRUint32 maxBytes); -SECStatus ssl3_ClientHandleSignedCertTimestampXtn(const sslSocket *ss, TLSExtensionData *xtnData, - PRUint16 ex_type, +SECStatus ssl3_ClientSendSignedCertTimestampXtn(const sslSocket *ss, + TLSExtensionData *xtnData, + sslBuffer *buf, PRBool *added); +SECStatus ssl3_ClientHandleSignedCertTimestampXtn(const sslSocket *ss, + TLSExtensionData *xtnData, SECItem *data); -PRInt32 ssl3_ServerSendSignedCertTimestampXtn(const sslSocket *ss, TLSExtensionData *xtnData, - PRBool append, - PRUint32 maxBytes); -SECStatus ssl3_ServerHandleSignedCertTimestampXtn(const sslSocket *ss, TLSExtensionData *xtnData, - PRUint16 ex_type, +SECStatus ssl3_ServerSendSignedCertTimestampXtn(const sslSocket *ss, + TLSExtensionData *xtnData, + sslBuffer *buf, PRBool *added); +SECStatus ssl3_ServerHandleSignedCertTimestampXtn(const sslSocket *ss, + TLSExtensionData *xtnData, SECItem *data); -PRInt32 ssl3_SendExtendedMasterSecretXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRBool append, - PRUint32 maxBytes); -SECStatus ssl3_HandleExtendedMasterSecretXtn(const sslSocket *ss, TLSExtensionData *xtnData, - PRUint16 ex_type, +SECStatus ssl3_SendExtendedMasterSecretXtn(const sslSocket *ss, + TLSExtensionData *xtnData, + sslBuffer *buf, PRBool *added); +SECStatus ssl3_HandleExtendedMasterSecretXtn(const sslSocket *ss, + TLSExtensionData *xtnData, SECItem *data); SECStatus ssl3_ProcessSessionTicketCommon(sslSocket *ss, SECItem *data); -PRInt32 ssl3_SendServerNameXtn(const sslSocket *ss, - TLSExtensionData *xtnData, - PRBool append, - PRUint32 maxBytes); -SECStatus ssl3_HandleServerNameXtn(const sslSocket *ss, TLSExtensionData *xtnData, - PRUint16 ex_type, SECItem *data); -SECStatus ssl_HandleSupportedGroupsXtn(const sslSocket *ss, TLSExtensionData *xtnData, - PRUint16 ex_type, SECItem *data); -SECStatus ssl3_HandleSupportedPointFormatsXtn(const sslSocket *ss, TLSExtensionData *xtnData, - PRUint16 ex_type, SECItem *data); -SECStatus ssl3_ClientHandleSessionTicketXtn(const sslSocket *ss, TLSExtensionData *xtnData, - PRUint16 ex_type, SECItem *data); -SECStatus ssl3_ServerHandleSessionTicketXtn(const sslSocket *ss, TLSExtensionData *xtnData, - PRUint16 ex_type, SECItem *data); -PRInt32 ssl3_SendSessionTicketXtn(const sslSocket *ss, - TLSExtensionData *xtnData, - PRBool append, - PRUint32 maxBytes); - -PRInt32 ssl_SendSupportedGroupsXtn(const sslSocket *ss, +SECStatus ssl3_ClientSendServerNameXtn(const sslSocket *ss, + TLSExtensionData *xtnData, + sslBuffer *buf, PRBool *added); +SECStatus ssl3_HandleServerNameXtn(const sslSocket *ss, TLSExtensionData *xtnData, - PRBool append, PRUint32 maxBytes); -PRInt32 ssl3_SendSupportedPointFormatsXtn(const sslSocket *ss, + SECItem *data); +SECStatus ssl_HandleSupportedGroupsXtn(const sslSocket *ss, + TLSExtensionData *xtnData, + SECItem *data); +SECStatus ssl3_HandleSupportedPointFormatsXtn(const sslSocket *ss, + TLSExtensionData *xtnData, + SECItem *data); +SECStatus ssl3_ClientHandleSessionTicketXtn(const sslSocket *ss, + TLSExtensionData *xtnData, + SECItem *data); +SECStatus ssl3_ServerHandleSessionTicketXtn(const sslSocket *ss, + TLSExtensionData *xtnData, + SECItem *data); +SECStatus ssl3_ClientSendSessionTicketXtn(const sslSocket *ss, TLSExtensionData *xtnData, - PRBool append, PRUint32 maxBytes); + sslBuffer *buf, PRBool *added); + +SECStatus ssl_SendSupportedGroupsXtn(const sslSocket *ss, + TLSExtensionData *xtnData, + sslBuffer *buf, PRBool *added); +SECStatus ssl3_SendSupportedPointFormatsXtn(const sslSocket *ss, + TLSExtensionData *xtnData, + sslBuffer *buf, PRBool *added); #endif diff --git a/lib/ssl/ssl3gthr.c b/lib/ssl/ssl3gthr.c index cf6f4cb33e..ae76ae8dca 100644 --- a/lib/ssl/ssl3gthr.c +++ b/lib/ssl/ssl3gthr.c @@ -98,7 +98,7 @@ ssl3_GatherData(sslSocket *ss, sslGather *gs, int flags, ssl2Gather *ssl2gs) PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss)); if (gs->state == GS_INIT) { gs->state = GS_HEADER; - gs->remainder = ss->ssl3.hs.shortHeaders ? 2 : 5; + gs->remainder = 5; gs->offset = 0; gs->writeOffset = 0; gs->readOffset = 0; @@ -156,19 +156,7 @@ ssl3_GatherData(sslSocket *ss, sslGather *gs, int flags, ssl2Gather *ssl2gs) /* Should have a non-SSLv2 record header in gs->hdr. Extract * the length of the following encrypted data, and then * read in the rest of the record into gs->inbuf. */ - if (ss->ssl3.hs.shortHeaders) { - PRUint16 len = (gs->hdr[0] << 8) | gs->hdr[1]; - if (!(len & 0x8000)) { - SSL_DBG(("%d: SSL3[%d]: incorrectly formatted header")); - SSL3_SendAlert(ss, alert_fatal, illegal_parameter); - gs->state = GS_INIT; - PORT_SetError(SSL_ERROR_BAD_MAC_READ); - return SECFailure; - } - gs->remainder = len & ~0x8000; - } else { - gs->remainder = (gs->hdr[3] << 8) | gs->hdr[4]; - } + gs->remainder = (gs->hdr[3] << 8) | gs->hdr[4]; } else { /* Probably an SSLv2 record header. No need to handle any * security escapes (gs->hdr[0] & 0x40) as we wouldn't get @@ -493,13 +481,8 @@ ssl3_GatherCompleteHandshake(sslSocket *ss, int flags) * If it's a change cipher spec, alert, or handshake message, * ss->gs.buf.len will be 0 when ssl3_HandleRecord returns SECSuccess. */ - if (ss->ssl3.hs.shortHeaders) { - cText.type = content_application_data; - cText.version = SSL_LIBRARY_VERSION_TLS_1_0; - } else { - cText.type = (SSL3ContentType)ss->gs.hdr[0]; - cText.version = (ss->gs.hdr[1] << 8) | ss->gs.hdr[2]; - } + cText.type = (SSL3ContentType)ss->gs.hdr[0]; + cText.version = (ss->gs.hdr[1] << 8) | ss->gs.hdr[2]; if (IS_DTLS(ss)) { sslSequenceNumber seq_num; diff --git a/lib/ssl/ssl3prot.h b/lib/ssl/ssl3prot.h index 762071530b..44f071f190 100644 --- a/lib/ssl/ssl3prot.h +++ b/lib/ssl/ssl3prot.h @@ -30,7 +30,6 @@ typedef PRUint16 ssl3CipherSuite; #define SSL3_RANDOM_LENGTH 32 #define SSL3_RECORD_HEADER_LENGTH 5 -#define TLS13_RECORD_HEADER_LENGTH_SHORT 2 /* SSL3_RECORD_HEADER_LENGTH + epoch/sequence_number */ #define DTLS_RECORD_HEADER_LENGTH 13 @@ -126,26 +125,6 @@ typedef struct { SSL3AlertDescription description; } SSL3Alert; -typedef enum { - hello_request = 0, - client_hello = 1, - server_hello = 2, - hello_verify_request = 3, - new_session_ticket = 4, - end_of_early_data = 5, - hello_retry_request = 6, - encrypted_extensions = 8, - certificate = 11, - server_key_exchange = 12, - certificate_request = 13, - server_hello_done = 14, - certificate_verify = 15, - client_key_exchange = 16, - finished = 20, - certificate_status = 22, - next_proto = 67, -} SSL3HandshakeType; - typedef struct { PRUint8 empty; } SSL3HelloRequest; @@ -235,7 +214,7 @@ typedef struct { union { PRUint8 raw[64]; SSL3HashesIndividually s; - SECItem pointer_to_hash_input; + unsigned int transcriptLen; } u; } SSL3Hashes; diff --git a/lib/ssl/sslencode.c b/lib/ssl/sslencode.c new file mode 100644 index 0000000000..61f18ee5c3 --- /dev/null +++ b/lib/ssl/sslencode.c @@ -0,0 +1,170 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is PRIVATE to SSL. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "nss.h" +#include "prnetdb.h" +#include "ssl.h" +#include "sslimpl.h" + +/* Helper function to encode an unsigned integer into a buffer. */ +PRUint8 * +ssl_EncodeUintX(PRUint64 value, unsigned int bytes, PRUint8 *to) +{ + PRUint64 encoded; + + PORT_Assert(bytes > 0 && bytes <= sizeof(encoded)); + + encoded = PR_htonll(value); + memcpy(to, ((unsigned char *)(&encoded)) + (sizeof(encoded) - bytes), bytes); + return to + bytes; +} + +/* Grow a buffer to hold newLen bytes of data. When used for recv/xmit buffers, + * the caller must hold xmitBufLock or recvBufLock, as appropriate. */ +SECStatus +sslBuffer_Grow(sslBuffer *b, unsigned int newLen) +{ + newLen = PR_MAX(newLen, b->len + 1024); + if (newLen > b->space) { + unsigned char *newBuf; + if (b->buf) { + newBuf = (unsigned char *)PORT_Realloc(b->buf, newLen); + } else { + newBuf = (unsigned char *)PORT_Alloc(newLen); + } + if (!newBuf) { + return SECFailure; + } + b->buf = newBuf; + b->space = newLen; + } + return SECSuccess; +} + +SECStatus +sslBuffer_Append(sslBuffer *b, const void *data, unsigned int len) +{ + SECStatus rv = sslBuffer_Grow(b, b->len + len); + if (rv != SECSuccess) { + return rv; /* Code already set. */ + } + PORT_Memcpy(b->buf + b->len, data, len); + b->len += len; + return SECSuccess; +} + +SECStatus +sslBuffer_AppendNumber(sslBuffer *b, PRUint64 v, unsigned int size) +{ + SECStatus rv = sslBuffer_Grow(b, b->len + size); + if (rv != SECSuccess) { + return rv; + } + (void)ssl_EncodeUintX(v, size, b->buf + b->len); + b->len += size; + return SECSuccess; +} + +SECStatus +sslBuffer_AppendVariable(sslBuffer *b, const PRUint8 *data, unsigned int len, + unsigned int size) +{ + SECStatus rv = sslBuffer_Grow(b, b->len + len + size); + if (rv != SECSuccess) { + return rv; + } + (void)ssl_EncodeUintX(len, size, b->buf + b->len); + b->len += size; + PORT_Memcpy(b->buf + b->len, data, len); + b->len += len; + return SECSuccess; +} + +SECStatus +sslBuffer_AppendBuffer(sslBuffer *b, const sslBuffer *append) +{ + return sslBuffer_Append(b, append->buf, append->len); +} + +SECStatus +sslBuffer_AppendBufferVariable(sslBuffer *b, const sslBuffer *append, + unsigned int size) +{ + return sslBuffer_AppendVariable(b, append->buf, append->len, size); +} + +void +sslBuffer_Clear(sslBuffer *b) +{ + if (b->buf) { + PORT_Free(b->buf); + b->buf = NULL; + b->len = 0; + b->space = 0; + } +} + +SECStatus +ssl3_AppendToItem(SECItem *item, const unsigned char *buf, PRUint32 bytes) +{ + if (bytes > item->len) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; + } + + PORT_Memcpy(item->data, buf, bytes); + item->data += bytes; + item->len -= bytes; + return SECSuccess; +} + +SECStatus +ssl3_AppendNumberToItem(SECItem *item, PRUint32 num, PRInt32 lenSize) +{ + SECStatus rv; + PRUint8 b[sizeof(num)]; + + ssl_EncodeUintX(num, lenSize, b); + rv = ssl3_AppendToItem(item, &b[0], lenSize); + return rv; +} + +SECStatus +ssl3_ConsumeFromItem(SECItem *item, unsigned char **buf, PRUint32 bytes) +{ + if (bytes > item->len) { + PORT_SetError(SEC_ERROR_BAD_DATA); + return SECFailure; + } + + *buf = item->data; + item->data += bytes; + item->len -= bytes; + return SECSuccess; +} + +SECStatus +ssl3_ConsumeNumberFromItem(SECItem *item, PRUint32 *num, PRUint32 bytes) +{ + int i; + + if (bytes > item->len || bytes > sizeof(*num)) { + PORT_SetError(SEC_ERROR_BAD_DATA); + return SECFailure; + } + + *num = 0; + for (i = 0; i < bytes; i++) { + *num = (*num << 8) + item->data[i]; + } + + item->data += bytes; + item->len -= bytes; + + return SECSuccess; +} diff --git a/lib/ssl/ssl3encode.h b/lib/ssl/sslencode.h similarity index 54% rename from lib/ssl/ssl3encode.h rename to lib/ssl/sslencode.h index 3b88f7e7b3..49c4397ee5 100644 --- a/lib/ssl/ssl3encode.h +++ b/lib/ssl/sslencode.h @@ -6,10 +6,29 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#ifndef __ssl3encode_h_ -#define __ssl3encode_h_ +#ifndef __sslencode_h_ +#define __sslencode_h_ -#include "seccomon.h" +PRUint8 *ssl_EncodeUintX(PRUint64 value, unsigned int bytes, PRUint8 *to); + +/* + ** A buffer object. + */ +typedef struct sslBufferStr { + PRUint8 *buf; + unsigned int len; + unsigned int space; +} sslBuffer; + +SECStatus sslBuffer_Grow(sslBuffer *b, unsigned int newLen); +SECStatus sslBuffer_Append(sslBuffer *b, const void *data, unsigned int len); +SECStatus sslBuffer_AppendNumber(sslBuffer *b, PRUint64 v, unsigned int size); +SECStatus sslBuffer_AppendVariable(sslBuffer *b, const PRUint8 *data, + unsigned int len, unsigned int size); +SECStatus sslBuffer_AppendBuffer(sslBuffer *b, const sslBuffer *append); +SECStatus sslBuffer_AppendBufferVariable(sslBuffer *b, const sslBuffer *append, + unsigned int size); +void sslBuffer_Clear(sslBuffer *b); /* All of these functions modify the underlying SECItem, and so should * be performed on a shallow copy.*/ @@ -21,6 +40,5 @@ SECStatus ssl3_ConsumeFromItem(SECItem *item, unsigned char **buf, PRUint32 bytes); SECStatus ssl3_ConsumeNumberFromItem(SECItem *item, PRUint32 *num, PRUint32 bytes); -PRUint8 *ssl_EncodeUintX(PRUint64 value, unsigned int bytes, PRUint8 *to); -#endif +#endif /* __sslencode_h_ */ diff --git a/lib/ssl/sslimpl.h b/lib/ssl/sslimpl.h index 4c4ff1c52c..6cc497411e 100644 --- a/lib/ssl/sslimpl.h +++ b/lib/ssl/sslimpl.h @@ -36,6 +36,7 @@ typedef struct sslSocketStr sslSocket; typedef struct ssl3CipherSpecStr ssl3CipherSpec; #include "ssl3ext.h" +#include "sslencode.h" /* to make some of these old enums public without namespace pollution, ** it was necessary to prepend ssl_ to the names. @@ -174,7 +175,6 @@ typedef struct { PRBool assumeSupported; } sslNamedGroupDef; -typedef struct sslBufferStr sslBuffer; typedef struct sslConnectInfoStr sslConnectInfo; typedef struct sslGatherStr sslGather; typedef struct sslSecurityInfoStr sslSecurityInfo; @@ -233,15 +233,6 @@ struct sslSocketOpsStr { 0x04000000 /* TLS only */ #define ssl_SEND_FLAG_MASK 0x7f000000 -/* -** A buffer object. -*/ -struct sslBufferStr { - unsigned char *buf; - unsigned int len; - unsigned int space; -}; - /* ** SSL3 cipher suite policy and preference struct. */ @@ -789,7 +780,7 @@ typedef struct SSL3HandshakeStateStr { unsigned int header_bytes; /* number of bytes consumed from handshake */ /* message for message type and header length */ - SSL3HandshakeType msg_type; + SSLHandshakeType msg_type; unsigned long msg_len; PRBool isResuming; /* we are resuming (not used in TLS 1.3) */ PRBool sendingSCSV; /* instead of empty RI */ @@ -873,7 +864,6 @@ typedef struct SSL3HandshakeStateStr { PRBool clientCertRequested; /* True if CertificateRequest received. */ ssl3KEADef kea_def_mutable; /* Used to hold the writable kea_def * we use for TLS 1.3 */ - PRBool shortHeaders; /* Assigned if we are doing short headers. */ } SSL3HandshakeState; /* @@ -1142,6 +1132,7 @@ struct sslSocketStr { void *pkcs11PinArg; SSLNextProtoCallback nextProtoCallback; void *nextProtoArg; + PRCList extensionHandlers; PRIntervalTime rTimeout; /* timeout for NSPR I/O */ PRIntervalTime wTimeout; /* timeout for NSPR I/O */ @@ -1322,11 +1313,6 @@ extern SECStatus ssl_BeginClientHandshake(sslSocket *ss); extern SECStatus ssl_BeginServerHandshake(sslSocket *ss); extern int ssl_Do1stHandshake(sslSocket *ss); -extern SECStatus sslBuffer_Grow(sslBuffer *b, unsigned int newLen); -extern SECStatus sslBuffer_Append(sslBuffer *b, const void *data, - unsigned int len); -extern void sslBuffer_Clear(sslBuffer *b); - extern void ssl_ChooseSessionIDProcs(sslSecurityInfo *sec); extern void ssl3_InitCipherSpec(ssl3CipherSpec *spec); @@ -1574,7 +1560,7 @@ extern PRBool ssl_HaveEphemeralKeyPair(const sslSocket *ss, const sslNamedGroupDef *groupDef); extern void ssl_FreeEphemeralKeyPairs(sslSocket *ss); -extern SECStatus ssl_AppendPaddedDHKeyShare(const sslSocket *ss, +extern SECStatus ssl_AppendPaddedDHKeyShare(sslBuffer *buf, const SECKEYPublicKey *pubKey, PRBool appendLength); extern const ssl3DHParams *ssl_GetDHEParams(const sslNamedGroupDef *groupDef); @@ -1655,8 +1641,6 @@ extern SECStatus ssl3_SendECDHServerKeyExchange(sslSocket *ss); extern SECStatus ssl_ImportECDHKeyShare( sslSocket *ss, SECKEYPublicKey *peerKey, PRUint8 *b, PRUint32 length, const sslNamedGroupDef *curve); -SECStatus tls13_EncodeECDHEKeyShareKEX(const sslSocket *ss, - const SECKEYPublicKey *pubKey); extern SECStatus ssl3_ComputeCommonKeyHash(SSLHashType hashAlg, PRUint8 *hashBuf, @@ -1665,13 +1649,16 @@ extern SECStatus ssl3_ComputeCommonKeyHash(SSLHashType hashAlg, extern void ssl3_DestroyCipherSpec(ssl3CipherSpec *spec, PRBool freeSrvName); extern SECStatus ssl3_InitPendingCipherSpec(sslSocket *ss, PK11SymKey *pms); extern SECStatus ssl3_AppendHandshake(sslSocket *ss, const void *void_src, - PRInt32 bytes); + unsigned int bytes); extern SECStatus ssl3_AppendHandshakeHeader(sslSocket *ss, - SSL3HandshakeType t, PRUint32 length); -extern SECStatus ssl3_AppendHandshakeNumber(sslSocket *ss, PRInt32 num, - PRInt32 lenSize); -extern SECStatus ssl3_AppendHandshakeVariable(sslSocket *ss, - const PRUint8 *src, PRInt32 bytes, PRInt32 lenSize); + SSLHandshakeType t, unsigned int length); +extern SECStatus ssl3_AppendHandshakeNumber(sslSocket *ss, PRUint64 num, + unsigned int lenSize); +extern SECStatus ssl3_AppendHandshakeVariable(sslSocket *ss, const PRUint8 *src, + unsigned int bytes, unsigned int lenSize); +extern SECStatus ssl3_AppendBufferToHandshake(sslSocket *ss, sslBuffer *buf); +extern SECStatus ssl3_AppendBufferToHandshakeVariable(sslSocket *ss, sslBuffer *buf, + unsigned int lenSize); extern SECStatus ssl3_AppendSignatureAndHashAlgorithm( sslSocket *ss, const SSLSignatureAndHashAlg *sigAndHash); extern SECStatus ssl3_ConsumeHandshake(sslSocket *ss, void *v, PRUint32 bytes, @@ -1682,8 +1669,6 @@ extern SECStatus ssl3_ConsumeHandshakeNumber(sslSocket *ss, PRUint32 *num, extern SECStatus ssl3_ConsumeHandshakeVariable(sslSocket *ss, SECItem *i, PRUint32 bytes, PRUint8 **b, PRUint32 *length); -extern PRUint8 *ssl_EncodeUintX(PRUint64 value, unsigned int bytes, - PRUint8 *to); extern PRBool ssl_IsSupportedSignatureScheme(SSLSignatureScheme scheme); extern SECStatus ssl_CheckSignatureSchemeConsistency( sslSocket *ss, SSLSignatureScheme scheme, CERTCertificate *cert); diff --git a/lib/ssl/sslsecur.c b/lib/ssl/sslsecur.c index 8bec3d327a..83f914f057 100644 --- a/lib/ssl/sslsecur.c +++ b/lib/ssl/sslsecur.c @@ -1,3 +1,4 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * Various SSL functions. * @@ -434,58 +435,6 @@ SSL_ForceHandshakeWithTimeout(PRFileDesc *fd, /************************************************************************/ -/* -** Grow a buffer to hold newLen bytes of data. -** Called for both recv buffers and xmit buffers. -** Caller must hold xmitBufLock or recvBufLock, as appropriate. -*/ -SECStatus -sslBuffer_Grow(sslBuffer *b, unsigned int newLen) -{ - newLen = PR_MAX(newLen, MAX_FRAGMENT_LENGTH + 2048); - if (newLen > b->space) { - unsigned char *newBuf; - if (b->buf) { - newBuf = (unsigned char *)PORT_Realloc(b->buf, newLen); - } else { - newBuf = (unsigned char *)PORT_Alloc(newLen); - } - if (!newBuf) { - return SECFailure; - } - SSL_TRC(10, ("%d: SSL: grow buffer from %d to %d", - SSL_GETPID(), b->space, newLen)); - b->buf = newBuf; - b->space = newLen; - } - return SECSuccess; -} - -SECStatus -sslBuffer_Append(sslBuffer *b, const void *data, unsigned int len) -{ - unsigned int newLen = b->len + len; - SECStatus rv; - - rv = sslBuffer_Grow(b, newLen); - if (rv != SECSuccess) - return rv; - PORT_Memcpy(b->buf + b->len, data, len); - b->len += len; - return SECSuccess; -} - -void -sslBuffer_Clear(sslBuffer *b) -{ - if (b->buf) { - PORT_Free(b->buf); - b->buf = NULL; - b->len = 0; - b->space = 0; - } -} - /* ** Save away write data that is trying to be written before the security ** handshake has been completed. When the handshake is completed, we will diff --git a/lib/ssl/sslsock.c b/lib/ssl/sslsock.c index 99828c85b1..6c593d1c69 100644 --- a/lib/ssl/sslsock.c +++ b/lib/ssl/sslsock.c @@ -78,12 +78,7 @@ static sslOptions ssl_defaults = { PR_FALSE, /* enableExtendedMS */ PR_FALSE, /* enableSignedCertTimestamps */ PR_FALSE, /* requireDHENamedGroups */ - PR_FALSE, /* enable0RttData */ -#ifdef NSS_ENABLE_TLS13_SHORT_HEADERS - PR_TRUE /* enableShortHeaders */ -#else - PR_FALSE /* enableShortHeaders */ -#endif + PR_FALSE /* enable0RttData */ }; /* diff --git a/lib/ssl/sslt.h b/lib/ssl/sslt.h index 3b298faf12..b6cbe1273f 100644 --- a/lib/ssl/sslt.h +++ b/lib/ssl/sslt.h @@ -13,6 +13,26 @@ #include "secitem.h" #include "certt.h" +typedef enum { + ssl_hs_hello_request = 0, + ssl_hs_client_hello = 1, + ssl_hs_server_hello = 2, + ssl_hs_hello_verify_request = 3, + ssl_hs_new_session_ticket = 4, + ssl_hs_end_of_early_data = 5, + ssl_hs_hello_retry_request = 6, + ssl_hs_encrypted_extensions = 8, + ssl_hs_certificate = 11, + ssl_hs_server_key_exchange = 12, + ssl_hs_certificate_request = 13, + ssl_hs_server_hello_done = 14, + ssl_hs_certificate_verify = 15, + ssl_hs_client_key_exchange = 16, + ssl_hs_finished = 20, + ssl_hs_certificate_status = 22, + ssl_hs_next_proto = 67 +} SSLHandshakeType; + typedef struct SSL3StatisticsStr { /* statistics from ssl3_SendClientHello (sch) */ long sch_sid_cache_hits; diff --git a/lib/ssl/tls13con.c b/lib/ssl/tls13con.c index 4bacd0d4fa..9b9ef970fa 100644 --- a/lib/ssl/tls13con.c +++ b/lib/ssl/tls13con.c @@ -87,10 +87,9 @@ static SECStatus tls13_SendEndOfEarlyData(sslSocket *ss); static SECStatus tls13_HandleEndOfEarlyData(sslSocket *ss, PRUint8 *b, PRUint32 length); static SECStatus tls13_SendFinished(sslSocket *ss, PK11SymKey *baseKey); -static SECStatus tls13_ComputePskBinderHash(sslSocket *ss, - unsigned long prefixLength, +static SECStatus tls13_ComputePskBinderHash(sslSocket *ss, unsigned int prefix, SSL3Hashes *hashes); -static SECStatus tls13_VerifyFinished(sslSocket *ss, SSL3HandshakeType message, +static SECStatus tls13_VerifyFinished(sslSocket *ss, SSLHandshakeType message, PK11SymKey *secret, PRUint8 *b, PRUint32 length, const SSL3Hashes *hashes); @@ -599,26 +598,26 @@ tls13_HandlePostHelloHandshakeMessage(sslSocket *ss, PRUint8 *b, /* TODO(ekr@rtfm.com): Would it be better to check all the states here? */ switch (ss->ssl3.hs.msg_type) { - case certificate: + case ssl_hs_certificate: return tls13_HandleCertificate(ss, b, length); - case certificate_request: + case ssl_hs_certificate_request: return tls13_HandleCertificateRequest(ss, b, length); - case certificate_verify: + case ssl_hs_certificate_verify: if (!hashesPtr) { FATAL_ERROR(ss, SSL_ERROR_RX_UNEXPECTED_CERT_VERIFY, unexpected_message); return SECFailure; } return tls13_HandleCertificateVerify(ss, b, length, hashesPtr); - case encrypted_extensions: + case ssl_hs_encrypted_extensions: return tls13_HandleEncryptedExtensions(ss, b, length); - case new_session_ticket: + case ssl_hs_new_session_ticket: return tls13_HandleNewSessionTicket(ss, b, length); - case finished: + case ssl_hs_finished: if (!hashesPtr) { FATAL_ERROR(ss, SSL_ERROR_RX_UNEXPECTED_FINISHED, unexpected_message); return SECFailure; @@ -628,7 +627,7 @@ tls13_HandlePostHelloHandshakeMessage(sslSocket *ss, PRUint8 *b, } return tls13_ClientHandleFinished(ss, b, length, hashesPtr); - case end_of_early_data: + case ssl_hs_end_of_early_data: return tls13_HandleEndOfEarlyData(ss, b, length); default: @@ -1423,7 +1422,7 @@ tls13_HandleClientHelloPart2(sslSocket *ss, goto loser; } - rv = tls13_VerifyFinished(ss, client_hello, + rv = tls13_VerifyFinished(ss, ssl_hs_client_hello, ss->ssl3.hs.pskBinderKey, ss->xtnData.pskBinder.data, ss->xtnData.pskBinder.len, @@ -1517,7 +1516,7 @@ tls13_SendHelloRetryRequest(sslSocket *ss, const sslNamedGroupDef *selectedGroup } ssl_GetXmitBufLock(ss); - rv = ssl3_AppendHandshakeHeader(ss, hello_retry_request, + rv = ssl3_AppendHandshakeHeader(ss, ssl_hs_hello_retry_request, 2 + /* version */ 2 + /* cipher suite */ 2 + /* extension length */ @@ -1633,12 +1632,6 @@ tls13_HandleClientKeyShare(sslSocket *ss, TLS13KeyShareEntry *peerShare) return rv; /* Error code set already. */ } -static const ssl3HelloExtensionSender tls13_cert_req_senders[] = { - { ssl_signature_algorithms_xtn, &ssl3_SendSigAlgsXtn }, - { ssl_tls13_certificate_authorities_xtn, &tls13_SendCertAuthoritiesXtn }, - { 0, NULL } -}; - /* * [draft-ietf-tls-tls13-11] Section 6.3.3.2 * @@ -1661,39 +1654,42 @@ static SECStatus tls13_SendCertificateRequest(sslSocket *ss) { SECStatus rv; - PRInt32 extLen; + sslBuffer extensionBuf = { NULL, 0, 0 }; SSL_TRC(3, ("%d: TLS13[%d]: begin send certificate_request", SSL_GETPID(), ss->fd)); - extLen = ssl3_CallHelloExtensionSenders(ss, PR_FALSE, 0xffff, - tls13_cert_req_senders); - PORT_Assert(extLen > 0); /* These can't be empty. */ + rv = ssl_ConstructExtensions(ss, &extensionBuf, ssl_hs_certificate_request); + if (rv != SECSuccess) { + return SECFailure; /* Code already set. */ + } + PORT_Assert(extensionBuf.len > 0); /* These can't be empty. */ - rv = ssl3_AppendHandshakeHeader(ss, certificate_request, + rv = ssl3_AppendHandshakeHeader(ss, ssl_hs_certificate_request, 1 + 0 + /* empty request context */ - 2 + extLen /* len + extensions */); + 2 + /* extension length */ + extensionBuf.len /* extensions */); if (rv != SECSuccess) { - return rv; /* err set by AppendHandshake. */ + goto loser; /* err set by AppendHandshake. */ } /* Context. */ rv = ssl3_AppendHandshakeNumber(ss, 0, 1); if (rv != SECSuccess) { - return rv; /* err set by AppendHandshake. */ + goto loser; /* err set by AppendHandshake. */ } /* Extensions. */ - rv = ssl3_AppendHandshakeNumber(ss, extLen, 2); + rv = ssl3_AppendBufferToHandshakeVariable(ss, &extensionBuf, 2); if (rv != SECSuccess) { - return rv; /* err set by AppendHandshake. */ - } - extLen = ssl3_CallHelloExtensionSenders(ss, PR_TRUE, extLen, - tls13_cert_req_senders); - if (extLen < 0) { - return SECFailure; /* rely on the extension sender setting code */ + goto loser; /* err set by AppendHandshake. */ } + sslBuffer_Clear(&extensionBuf); return SECSuccess; + +loser: + sslBuffer_Clear(&extensionBuf); + return SECFailure; } SECStatus @@ -1773,7 +1769,7 @@ tls13_HandleHelloRetryRequest(sslSocket *ss, PRUint8 *b, PRUint32 length) return SECFailure; } - rv = ssl3_HandleExtensions(ss, &b, &length, hello_retry_request); + rv = ssl3_HandleExtensions(ss, &b, &length, ssl_hs_hello_retry_request); if (rv != SECSuccess) { return SECFailure; /* Error code set below */ } @@ -1839,7 +1835,7 @@ tls13_HandleCertificateRequest(sslSocket *ss, PRUint8 *b, PRUint32 length) /* Process all the extensions. */ rv = ssl3_HandleExtensions(ss, &extensionsData.data, &extensionsData.len, - certificate_request); + ssl_hs_certificate_request); if (rv != SECSuccess) { return SECFailure; } @@ -1877,12 +1873,10 @@ tls13_SendEncryptedServerSequence(sslSocket *ss) return SECFailure; } - ss->ssl3.hs.shortHeaders = ssl3_ExtensionNegotiated( - ss, ssl_tls13_short_header_xtn); - if (ss->ssl3.hs.zeroRttState == ssl_0rtt_accepted) { - rv = ssl3_RegisterExtensionSender(ss, &ss->xtnData, ssl_tls13_early_data_xtn, - tls13_ServerSendEarlyDataXtn); + rv = ssl3_RegisterExtensionSender(ss, &ss->xtnData, + ssl_tls13_early_data_xtn, + ssl_SendEmptyExtension); if (rv != SECSuccess) { return SECFailure; /* Error code set already. */ } @@ -2087,9 +2081,6 @@ tls13_HandleServerHelloPart2(sslSocket *ss) return SECFailure; /* error code is set. */ } - ss->ssl3.hs.shortHeaders = ssl3_ExtensionNegotiated( - ss, ssl_tls13_short_header_xtn); - rv = tls13_SetCipherSpec(ss, TrafficKeyHandshake, CipherSpecRead, PR_FALSE); if (rv != SECSuccess) { @@ -2190,8 +2181,7 @@ tls13_SendCertificate(sslSocket *ss) int certChainLen = 0; int i; SECItem context = { siBuffer, NULL, 0 }; - PRInt32 extensionsLen = 0; - PRUint32 maxBytes = 65535; + sslBuffer extensionBuf = { NULL, 0, 0 }; SSL_TRC(3, ("%d: TLS1.3[%d]: send certificate handshake", SSL_GETPID(), ss->fd)); @@ -2214,24 +2204,27 @@ tls13_SendCertificate(sslSocket *ss) ss->sec.localCert = CERT_DupCertificate(ss->ssl3.clientCertificate); } - /* Get the extensions length. This only applies to the leaf cert, - * because we don't yet send extensions for non-leaf certs. */ - extensionsLen = ssl3_CallHelloExtensionSenders( - ss, PR_FALSE, maxBytes, &ss->xtnData.certificateSenders[0]); - if (!ss->sec.isServer) { PORT_Assert(ss->ssl3.hs.clientCertRequested); context = ss->xtnData.certReqContext; } if (certChain) { for (i = 0; i < certChain->len; i++) { - certChainLen += - 3 + certChain->certs[i].len + /* cert length + cert */ - 2 + (!i ? extensionsLen : 0); /* extensions length + extensions */ + /* Each cert is 3 octet length, cert, and extensions */ + certChainLen += 3 + certChain->certs[i].len + 2; + } + + /* Build the extensions. This only applies to the leaf cert, because we + * don't yet send extensions for non-leaf certs. */ + rv = ssl_ConstructExtensions(ss, &extensionBuf, ssl_hs_certificate); + if (rv != SECSuccess) { + return SECFailure; /* code already set */ } + /* extensionBuf.len is only added once, for the leaf cert. */ + certChainLen += extensionBuf.len; } - rv = ssl3_AppendHandshakeHeader(ss, certificate, + rv = ssl3_AppendHandshakeHeader(ss, ssl_hs_certificate, 1 + context.len + 3 + certChainLen); if (rv != SECSuccess) { return SECFailure; /* err set by AppendHandshake. */ @@ -2240,50 +2233,44 @@ tls13_SendCertificate(sslSocket *ss) rv = ssl3_AppendHandshakeVariable(ss, context.data, context.len, 1); if (rv != SECSuccess) { - return SECFailure; /* err set by AppendHandshake. */ + goto loser; /* err set by AppendHandshake. */ } rv = ssl3_AppendHandshakeNumber(ss, certChainLen, 3); if (rv != SECSuccess) { - return SECFailure; /* err set by AppendHandshake. */ + goto loser; /* err set by AppendHandshake. */ } if (certChain) { for (i = 0; i < certChain->len; i++) { - PRInt32 sentLen; - rv = ssl3_AppendHandshakeVariable(ss, certChain->certs[i].data, certChain->certs[i].len, 3); if (rv != SECSuccess) { - return SECFailure; /* err set by AppendHandshake. */ + goto loser; /* err set by AppendHandshake. */ } if (i) { /* Not end-entity. */ rv = ssl3_AppendHandshakeNumber(ss, 0, 2); if (rv != SECSuccess) { - return SECFailure; /* err set by AppendHandshake. */ + goto loser; /* err set by AppendHandshake. */ } continue; } /* End-entity, send extensions. */ - rv = ssl3_AppendHandshakeNumber(ss, extensionsLen, 2); + rv = ssl3_AppendBufferToHandshakeVariable(ss, &extensionBuf, 2); if (rv != SECSuccess) { - return SECFailure; /* err set by AppendHandshake. */ - } - - sentLen = ssl3_CallHelloExtensionSenders( - ss, PR_TRUE, extensionsLen, - &ss->xtnData.certificateSenders[0]); - PORT_Assert(sentLen == extensionsLen); - if (sentLen != extensionsLen) { - LOG_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE); - return SECFailure; + goto loser; /* err set by AppendHandshake. */ } } } + sslBuffer_Clear(&extensionBuf); return SECSuccess; + +loser: + sslBuffer_Clear(&extensionBuf); + return SECFailure; } static SECStatus @@ -2311,7 +2298,7 @@ tls13_HandleCertificateEntry(sslSocket *ss, SECItem *data, PRBool first, if (first && !ss->sec.isServer) { rv = ssl3_HandleExtensions(ss, &extensionsData.data, &extensionsData.len, - certificate); + ssl_hs_certificate); if (rv != SECSuccess) { return SECFailure; } @@ -3109,7 +3096,7 @@ tls13_HandleEncryptedExtensions(sslSocket *ss, PRUint8 *b, PRUint32 length) ss->xtnData.nextProto.data = NULL; ss->xtnData.nextProtoState = SSL_NEXT_PROTO_NO_SUPPORT; } - rv = ssl3_HandleExtensions(ss, &b, &length, encrypted_extensions); + rv = ssl3_HandleExtensions(ss, &b, &length, ssl_hs_encrypted_extensions); if (rv != SECSuccess) { return SECFailure; /* Error code set below */ } @@ -3161,10 +3148,8 @@ tls13_HandleEncryptedExtensions(sslSocket *ss, PRUint8 *b, PRUint32 length) static SECStatus tls13_SendEncryptedExtensions(sslSocket *ss) { + sslBuffer extensions = { NULL, 0, 0 }; SECStatus rv; - PRInt32 extensions_len = 0; - PRInt32 sent_len = 0; - PRUint32 maxBytes = 65535; SSL_TRC(3, ("%d: TLS13[%d]: send encrypted extensions handshake", SSL_GETPID(), ss->fd)); @@ -3172,31 +3157,28 @@ tls13_SendEncryptedExtensions(sslSocket *ss) PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss)); PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss)); - extensions_len = ssl3_CallHelloExtensionSenders( - ss, PR_FALSE, maxBytes, &ss->xtnData.encryptedExtensionsSenders[0]); - - rv = ssl3_AppendHandshakeHeader(ss, encrypted_extensions, - extensions_len + 2); + rv = ssl_ConstructExtensions(ss, &extensions, ssl_hs_encrypted_extensions); if (rv != SECSuccess) { - LOG_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE); return SECFailure; } - rv = ssl3_AppendHandshakeNumber(ss, extensions_len, 2); + + rv = ssl3_AppendHandshakeHeader(ss, ssl_hs_encrypted_extensions, + extensions.len + 2); if (rv != SECSuccess) { LOG_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE); - return SECFailure; + goto loser; } - sent_len = ssl3_CallHelloExtensionSenders( - ss, PR_TRUE, extensions_len, - &ss->xtnData.encryptedExtensionsSenders[0]); - PORT_Assert(sent_len == extensions_len); - if (sent_len != extensions_len) { + rv = ssl3_AppendBufferToHandshakeVariable(ss, &extensions, 2); + if (rv != SECSuccess) { LOG_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE); - PORT_Assert(sent_len == 0); - return SECFailure; + goto loser; } - + sslBuffer_Clear(&extensions); return SECSuccess; + +loser: + sslBuffer_Clear(&extensions); + return SECFailure; } SECStatus @@ -3257,7 +3239,7 @@ tls13_SendCertificateVerify(sslSocket *ss, SECKEYPrivateKey *privKey) len = buf.len + 2 + 2; - rv = ssl3_AppendHandshakeHeader(ss, certificate_verify, len); + rv = ssl3_AppendHandshakeHeader(ss, ssl_hs_certificate_verify, len); if (rv != SECSuccess) { goto done; /* error code set by AppendHandshake */ } @@ -3365,7 +3347,7 @@ tls13_HandleCertificateVerify(sslSocket *ss, PRUint8 *b, PRUint32 length, } static SECStatus -tls13_ComputePskBinderHash(sslSocket *ss, unsigned long prefixLength, +tls13_ComputePskBinderHash(sslSocket *ss, unsigned int prefixLength, SSL3Hashes *hashes) { SECStatus rv; @@ -3377,38 +3359,75 @@ tls13_ComputePskBinderHash(sslSocket *ss, unsigned long 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)), - hashes->u.raw, - ss->ssl3.hs.messages.buf, prefixLength); + hashes->u.raw, ss->ssl3.hs.messages.buf, prefixLength); if (rv != SECSuccess) { ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE); - goto loser; + return SECFailure; } - hashes->len = tls13_GetHashSize(ss); - PRINT_BUF(10, (NULL, "PSK Binder hash", - hashes->u.raw, hashes->len)); + hashes->len = tls13_GetHashSize(ss); + PRINT_BUF(10, (NULL, "PSK Binder hash", hashes->u.raw, hashes->len)); return SECSuccess; - -loser: - return SECFailure; } -/* Compute the PSK Binder This is kind of sneaky.*/ + +/* Compute and inject the PSK Binder for sending. + * + * When sending a ClientHello, we construct all the extensions with a dummy + * value for the binder. To construct the binder, we commit the entire message + * up to the point where the binders start. Then we calculate the hash using + * the saved message (in ss->ssl3.hs.messages). This is written over the dummy + * binder, after which we write the remainder of the binder extension. */ SECStatus -tls13_ComputePskBinder(sslSocket *ss, PRBool sending, - unsigned int prefixLength, - PRUint8 *output, unsigned int *outputLen, - unsigned int maxOutputLen) +tls13_WriteExtensionsWithBinder(sslSocket *ss, sslBuffer *extensions) { SSL3Hashes hashes; SECStatus rv; + unsigned int size = tls13_GetHashSize(ss); + unsigned int prefixLen = extensions->len - size - 3; + unsigned int finishedLen; - rv = tls13_ComputePskBinderHash(ss, prefixLength, &hashes); - if (rv != SECSuccess) + PORT_Assert(extensions->len - size - 3 >= 0); + + rv = ssl3_AppendHandshakeNumber(ss, extensions->len, 2); + if (rv != SECSuccess) { return SECFailure; + } - return tls13_ComputeFinished(ss, ss->ssl3.hs.pskBinderKey, &hashes, - sending, output, outputLen, maxOutputLen); + /* Only write the extension up to the point before the binders. Assume that + * the pre_shared_key extension is at the end of the buffer. Don't write + * the binder, or the lengths that precede it (a 2 octet length for the list + * of all binders, plus a 1 octet length for the binder length). */ + rv = ssl3_AppendHandshake(ss, extensions->buf, prefixLen); + if (rv != SECSuccess) { + return SECFailure; + } + + /* Calculate the binder based on what has been written out. */ + rv = tls13_ComputePskBinderHash(ss, ss->ssl3.hs.messages.len, &hashes); + 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 + * separate write for the extra bits that precede the binder. */ + rv = tls13_ComputeFinished(ss, ss->ssl3.hs.pskBinderKey, &hashes, PR_TRUE, + extensions->buf + extensions->len - size, + &finishedLen, size); + if (rv != SECSuccess) { + return SECFailure; + } + PORT_Assert(finishedLen == size); + + /* Write out the remainder of the extension. */ + rv = ssl3_AppendHandshake(ss, extensions->buf + prefixLen, + extensions->len - prefixLen); + if (rv != SECSuccess) { + return SECFailure; + } + + return SECSuccess; } static SECStatus @@ -3507,7 +3526,7 @@ tls13_SendFinished(sslSocket *ss, PK11SymKey *baseKey) return SECFailure; } - rv = ssl3_AppendHandshakeHeader(ss, finished, finishedLen); + rv = ssl3_AppendHandshakeHeader(ss, ssl_hs_finished, finishedLen); if (rv != SECSuccess) { return SECFailure; /* Error code already set. */ } @@ -3522,7 +3541,7 @@ tls13_SendFinished(sslSocket *ss, PK11SymKey *baseKey) } static SECStatus -tls13_VerifyFinished(sslSocket *ss, SSL3HandshakeType message, +tls13_VerifyFinished(sslSocket *ss, SSLHandshakeType message, PK11SymKey *secret, PRUint8 *b, PRUint32 length, const SSL3Hashes *hashes) @@ -3545,7 +3564,7 @@ tls13_VerifyFinished(sslSocket *ss, SSL3HandshakeType message, if (length != finishedLen) { #ifndef UNSAFE_FUZZER_MODE - FATAL_ERROR(ss, message == finished ? SSL_ERROR_RX_MALFORMED_FINISHED : SSL_ERROR_RX_MALFORMED_CLIENT_HELLO, illegal_parameter); + FATAL_ERROR(ss, message == ssl_hs_finished ? SSL_ERROR_RX_MALFORMED_FINISHED : SSL_ERROR_RX_MALFORMED_CLIENT_HELLO, illegal_parameter); return SECFailure; #endif } @@ -3579,7 +3598,7 @@ tls13_ClientHandleFinished(sslSocket *ss, PRUint8 *b, PRUint32 length, return SECFailure; } - rv = tls13_VerifyFinished(ss, finished, + rv = tls13_VerifyFinished(ss, ssl_hs_finished, ss->ssl3.hs.serverHsTrafficSecret, b, length, hashes); if (rv != SECSuccess) @@ -3612,7 +3631,7 @@ tls13_ServerHandleFinished(sslSocket *ss, PRUint8 *b, PRUint32 length, secret = ss->ssl3.hs.clientEarlyTrafficSecret; } - rv = tls13_VerifyFinished(ss, finished, secret, b, length, hashes); + rv = tls13_VerifyFinished(ss, ssl_hs_finished, secret, b, length, hashes); if (rv != SECSuccess) return SECFailure; @@ -3863,7 +3882,7 @@ tls13_SendNewSessionTicket(sslSocket *ss) 2 + /* ticket length */ ticket_data.len; - rv = ssl3_AppendHandshakeHeader(ss, new_session_ticket, + rv = ssl3_AppendHandshakeHeader(ss, ssl_hs_new_session_ticket, message_length); if (rv != SECSuccess) goto loser; @@ -3978,7 +3997,7 @@ tls13_HandleNewSessionTicket(sslSocket *ss, PRUint8 *b, PRUint32 length) } rv = ssl3_HandleExtensions(ss, &data.data, - &data.len, new_session_ticket); + &data.len, ssl_hs_new_session_ticket); if (rv != SECSuccess) { FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_NEW_SESSION_TICKET, decode_error); @@ -4037,7 +4056,8 @@ tls13_HandleNewSessionTicket(sslSocket *ss, PRUint8 *b, PRUint32 length) return SECSuccess; } -#define _M1(a) (1 << PR_MIN(a, 31)) +#define _M(a) (1 << PR_MIN(a, 31)) +#define _M1(a) (_M(ssl_hs_##a)) #define _M2(a, b) (_M1(a) | _M1(b)) #define _M3(a, b, c) (_M1(a) | _M2(b, c)) @@ -4068,17 +4088,17 @@ static const struct { }; tls13ExtensionStatus -tls13_ExtensionStatus(PRUint16 extension, SSL3HandshakeType message) +tls13_ExtensionStatus(PRUint16 extension, SSLHandshakeType message) { unsigned int i; - PORT_Assert((message == client_hello) || - (message == server_hello) || - (message == hello_retry_request) || - (message == encrypted_extensions) || - (message == new_session_ticket) || - (message == certificate) || - (message == certificate_request)); + PORT_Assert((message == ssl_hs_client_hello) || + (message == ssl_hs_server_hello) || + (message == ssl_hs_hello_retry_request) || + (message == ssl_hs_encrypted_extensions) || + (message == ssl_hs_new_session_ticket) || + (message == ssl_hs_certificate) || + (message == ssl_hs_certificate_request)); for (i = 0; i < PR_ARRAY_SIZE(KnownExtensions); i++) { /* Hacky check for message numbers > 30. */ @@ -4092,7 +4112,7 @@ tls13_ExtensionStatus(PRUint16 extension, SSL3HandshakeType message) } /* Return "disallowed" if the message mask bit isn't set. */ - if (!(_M1(message) & KnownExtensions[i].messages)) { + if (!(_M(message) & KnownExtensions[i].messages)) { SSL_TRC(3, ("%d: TLS13: unexpected extension %d in message %d", SSL_GETPID(), extension, message)); @@ -4102,6 +4122,7 @@ tls13_ExtensionStatus(PRUint16 extension, SSL3HandshakeType message) return tls13_extension_allowed; } +#undef _M #undef _M1 #undef _M2 #undef _M3 @@ -4419,7 +4440,7 @@ tls13_SendEndOfEarlyData(sslSocket *ss) SSL_TRC(3, ("%d: TLS13[%d]: send EndOfEarlyData", SSL_GETPID(), ss->fd)); PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss)); - rv = ssl3_AppendHandshakeHeader(ss, end_of_early_data, 0); + rv = ssl3_AppendHandshakeHeader(ss, ssl_hs_end_of_early_data, 0); if (rv != SECSuccess) { return rv; /* err set by AppendHandshake. */ } diff --git a/lib/ssl/tls13con.h b/lib/ssl/tls13con.h index 3f881bd6f0..2d57afd187 100644 --- a/lib/ssl/tls13con.h +++ b/lib/ssl/tls13con.h @@ -61,10 +61,7 @@ PRInt32 tls13_LimitEarlyData(sslSocket *ss, SSL3ContentType type, PRInt32 toSend PRBool tls13_AllowPskCipher(const sslSocket *ss, const ssl3CipherSuiteDef *cipher_def); PRBool tls13_PskSuiteEnabled(sslSocket *ss); -SECStatus tls13_ComputePskBinder(sslSocket *ss, PRBool sending, - unsigned int prefixLength, - PRUint8 *output, unsigned int *outputLen, - unsigned int maxOutputLen); +SECStatus tls13_WriteExtensionsWithBinder(sslSocket *ss, sslBuffer *extensions); SECStatus tls13_HandleClientHelloPart2(sslSocket *ss, const SECItem *suites, sslSessionID *sid); @@ -82,7 +79,7 @@ void tls13_CipherSpecAddRef(ssl3CipherSpec *spec); void tls13_CipherSpecRelease(ssl3CipherSpec *spec); void tls13_DestroyCipherSpecs(PRCList *list); tls13ExtensionStatus tls13_ExtensionStatus(PRUint16 extension, - SSL3HandshakeType message); + SSLHandshakeType message); SECStatus tls13_ProtectRecord(sslSocket *ss, ssl3CipherSpec *cwSpec, SSL3ContentType type, diff --git a/lib/ssl/tls13exthandle.c b/lib/ssl/tls13exthandle.c index 107a4719ec..0f23fc3be2 100644 --- a/lib/ssl/tls13exthandle.c +++ b/lib/ssl/tls13exthandle.c @@ -14,50 +14,35 @@ #include "ssl3exthandle.h" #include "tls13exthandle.h" -PRInt32 -tls13_ServerSendStatusRequestXtn( - const sslSocket *ss, - TLSExtensionData *xtnData, - PRBool append, - PRUint32 maxBytes) +SECStatus +tls13_ServerSendStatusRequestXtn(const sslSocket *ss, TLSExtensionData *xtnData, + sslBuffer *buf, PRBool *added) { - PRInt32 extension_length; const sslServerCert *serverCert = ss->sec.serverCert; const SECItem *item; SECStatus rv; if (!serverCert->certStatusArray || !serverCert->certStatusArray->len) { - return 0; + return SECSuccess; } item = &serverCert->certStatusArray->items[0]; /* Only send the first entry. */ - extension_length = 2 + 2 + 1 /* status_type */ + 3 + item->len; - if (maxBytes < (PRUint32)extension_length) { - return 0; + /* status_type == ocsp */ + rv = sslBuffer_AppendNumber(buf, 1 /*ocsp*/, 1); + if (rv != SECSuccess) { + return SECFailure; } - if (append) { - /* extension_type */ - rv = ssl3_ExtAppendHandshakeNumber(ss, ssl_cert_status_xtn, 2); - if (rv != SECSuccess) - return -1; - /* length of extension_data */ - rv = ssl3_ExtAppendHandshakeNumber(ss, extension_length - 4, 2); - if (rv != SECSuccess) - return -1; - /* status_type == ocsp */ - rv = ssl3_ExtAppendHandshakeNumber(ss, 1 /*ocsp*/, 1); - if (rv != SECSuccess) - return rv; /* err set by AppendHandshake. */ - /* opaque OCSPResponse<1..2^24-1> */ - rv = ssl3_ExtAppendHandshakeVariable(ss, item->data, item->len, 3); - if (rv != SECSuccess) - return rv; /* err set by AppendHandshake. */ + /* opaque OCSPResponse<1..2^24-1> */ + rv = sslBuffer_AppendVariable(buf, item->data, item->len, 3); + if (rv != SECSuccess) { + return SECFailure; } - return extension_length; + *added = PR_TRUE; + return SECSuccess; } /* @@ -101,41 +86,27 @@ tls13_SizeOfKeyShareEntry(const SECKEYPublicKey *pubKey) return 0; } -static PRUint32 -tls13_SizeOfClientKeyShareExtension(const sslSocket *ss) -{ - PRCList *cursor; - /* Size is: extension(2) + extension_len(2) + client_shares(2) */ - PRUint32 size = 2 + 2 + 2; - for (cursor = PR_NEXT_LINK(&ss->ephemeralKeyPairs); - cursor != &ss->ephemeralKeyPairs; - cursor = PR_NEXT_LINK(cursor)) { - sslEphemeralKeyPair *keyPair = (sslEphemeralKeyPair *)cursor; - size += tls13_SizeOfKeyShareEntry(keyPair->keys->pubKey); - } - return size; -} - static SECStatus -tls13_EncodeKeyShareEntry(const sslSocket *ss, const sslEphemeralKeyPair *keyPair) +tls13_EncodeKeyShareEntry(sslBuffer *buf, const sslEphemeralKeyPair *keyPair) { SECStatus rv; SECKEYPublicKey *pubKey = keyPair->keys->pubKey; unsigned int size = tls13_SizeOfKeyShareEntry(pubKey); - rv = ssl3_ExtAppendHandshakeNumber(ss, keyPair->group->name, 2); + rv = sslBuffer_AppendNumber(buf, keyPair->group->name, 2); if (rv != SECSuccess) return rv; - rv = ssl3_ExtAppendHandshakeNumber(ss, size - 4, 2); + rv = sslBuffer_AppendNumber(buf, size - 4, 2); if (rv != SECSuccess) return rv; switch (pubKey->keyType) { case ecKey: - rv = tls13_EncodeECDHEKeyShareKEX(ss, pubKey); + rv = sslBuffer_Append(buf, pubKey->u.ec.publicValue.data, + pubKey->u.ec.publicValue.len); break; case dhKey: - rv = ssl_AppendPaddedDHKeyShare(ss, pubKey, PR_FALSE); + rv = ssl_AppendPaddedDHKeyShare(buf, pubKey, PR_FALSE); break; default: PORT_Assert(0); @@ -146,14 +117,16 @@ tls13_EncodeKeyShareEntry(const sslSocket *ss, const sslEphemeralKeyPair *keyPai return rv; } -PRInt32 -tls13_ClientSendKeyShareXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRBool append, - PRUint32 maxBytes) +SECStatus +tls13_ClientSendKeyShareXtn(const sslSocket *ss, TLSExtensionData *xtnData, + sslBuffer *buf, PRBool *added) { - PRUint32 extension_length; + SECStatus rv; + PRCList *cursor; + unsigned int lengthOffset; if (ss->vrange.max < SSL_LIBRARY_VERSION_TLS_1_3) { - return 0; + return SECSuccess; } /* Optimistically try to send an ECDHE key using the @@ -161,47 +134,25 @@ tls13_ClientSendKeyShareXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRBo SSL_TRC(3, ("%d: TLS13[%d]: send client key share xtn", SSL_GETPID(), ss->fd)); - extension_length = tls13_SizeOfClientKeyShareExtension(ss); - if (maxBytes < extension_length) { - PORT_Assert(0); - return 0; - } - - if (append) { - SECStatus rv; - PRCList *cursor; - - rv = ssl3_ExtAppendHandshakeNumber(ss, ssl_tls13_key_share_xtn, 2); - if (rv != SECSuccess) - goto loser; + /* Save the offset to the length. */ + lengthOffset = buf->len; + buf->len += 2; - /* The extension length */ - rv = ssl3_ExtAppendHandshakeNumber(ss, extension_length - 4, 2); - if (rv != SECSuccess) - goto loser; - - /* The length of KeyShares */ - rv = ssl3_ExtAppendHandshakeNumber(ss, extension_length - 6, 2); - if (rv != SECSuccess) - goto loser; - - for (cursor = PR_NEXT_LINK(&ss->ephemeralKeyPairs); - cursor != &ss->ephemeralKeyPairs; - cursor = PR_NEXT_LINK(cursor)) { - sslEphemeralKeyPair *keyPair = (sslEphemeralKeyPair *)cursor; - rv = tls13_EncodeKeyShareEntry(ss, keyPair); - if (rv != SECSuccess) - goto loser; + for (cursor = PR_NEXT_LINK(&ss->ephemeralKeyPairs); + cursor != &ss->ephemeralKeyPairs; + cursor = PR_NEXT_LINK(cursor)) { + sslEphemeralKeyPair *keyPair = (sslEphemeralKeyPair *)cursor; + rv = tls13_EncodeKeyShareEntry(buf, keyPair); + if (rv != SECSuccess) { + return SECFailure; } - - xtnData->advertised[xtnData->numAdvertised++] = - ssl_tls13_key_share_xtn; } + PORT_Assert(buf->len >= lengthOffset + 2); + (void)ssl_EncodeUintX(buf->len - lengthOffset - 2, 2, + buf->buf + lengthOffset); - return extension_length; - -loser: - return -1; + *added = PR_TRUE; + return SECSuccess; } static SECStatus @@ -250,7 +201,8 @@ tls13_HandleKeyShareEntry(const sslSocket *ss, TLSExtensionData *xtnData, SECIte * |xtnData->remoteKeyShares| for future use. The key * share is processed in tls13_HandleServerKeyShare(). */ SECStatus -tls13_ClientHandleKeyShareXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRUint16 ex_type, SECItem *data) +tls13_ClientHandleKeyShareXtn(const sslSocket *ss, TLSExtensionData *xtnData, + SECItem *data) { SECStatus rv; PORT_Assert(PR_CLIST_IS_EMPTY(&xtnData->remoteKeyShares)); @@ -281,7 +233,8 @@ tls13_ClientHandleKeyShareXtn(const sslSocket *ss, TLSExtensionData *xtnData, PR } SECStatus -tls13_ClientHandleKeyShareXtnHrr(const sslSocket *ss, TLSExtensionData *xtnData, PRUint16 ex_type, SECItem *data) +tls13_ClientHandleKeyShareXtnHrr(const sslSocket *ss, TLSExtensionData *xtnData, + SECItem *data) { SECStatus rv; PRUint32 tmp; @@ -331,7 +284,8 @@ tls13_ClientHandleKeyShareXtnHrr(const sslSocket *ss, TLSExtensionData *xtnData, * |xtnData->remoteKeyShares| for future use. The key * share is processed in tls13_HandleClientKeyShare(). */ SECStatus -tls13_ServerHandleKeyShareXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRUint16 ex_type, SECItem *data) +tls13_ServerHandleKeyShareXtn(const sslSocket *ss, TLSExtensionData *xtnData, + SECItem *data) { SECStatus rv; PRUint32 length; @@ -381,12 +335,10 @@ tls13_ServerHandleKeyShareXtn(const sslSocket *ss, TLSExtensionData *xtnData, PR return SECFailure; } -PRInt32 -tls13_ServerSendKeyShareXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRBool append, - PRUint32 maxBytes) +SECStatus +tls13_ServerSendKeyShareXtn(const sslSocket *ss, TLSExtensionData *xtnData, + sslBuffer *buf, PRBool *added) { - PRUint32 extension_length; - PRUint32 entry_length; SECStatus rv; sslEphemeralKeyPair *keyPair; @@ -397,31 +349,13 @@ tls13_ServerSendKeyShareXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRBo keyPair = (sslEphemeralKeyPair *)PR_NEXT_LINK(&ss->ephemeralKeyPairs); - entry_length = tls13_SizeOfKeyShareEntry(keyPair->keys->pubKey); - extension_length = 2 + 2 + entry_length; /* Type + length + entry_length */ - if (maxBytes < extension_length) { - PORT_Assert(0); - return 0; - } - - if (append) { - rv = ssl3_ExtAppendHandshakeNumber(ss, ssl_tls13_key_share_xtn, 2); - if (rv != SECSuccess) - goto loser; - - rv = ssl3_ExtAppendHandshakeNumber(ss, entry_length, 2); - if (rv != SECSuccess) - goto loser; - - rv = tls13_EncodeKeyShareEntry(ss, keyPair); - if (rv != SECSuccess) - goto loser; + rv = tls13_EncodeKeyShareEntry(buf, keyPair); + if (rv != SECSuccess) { + return SECFailure; } - return extension_length; - -loser: - return -1; + *added = PR_TRUE; + return SECSuccess; } /* Called by clients. @@ -448,107 +382,76 @@ tls13_ServerSendKeyShareXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRBo * Presently the only way to get a PSK is by resumption, so this is * really a ticket label and there will be at most one. */ -PRInt32 +SECStatus tls13_ClientSendPreSharedKeyXtn(const sslSocket *ss, TLSExtensionData *xtnData, - PRBool append, - PRUint32 maxBytes) + sslBuffer *buf, PRBool *added) { - PRInt32 extension_length; - PRInt32 identities_length; - PRInt32 binders_length; NewSessionTicket *session_ticket; + PRTime age; + const static PRUint8 binder[TLS13_MAX_FINISHED_SIZE] = { 0 }; + unsigned int binderLen; + SECStatus rv; /* We only set statelessResume on the client in TLS 1.3 code. */ - if (!ss->statelessResume) - return 0; + if (!ss->statelessResume) { + return SECSuccess; + } + + /* Save where this extension starts so that if we have to add padding, it + * can be inserted before this extension. */ + PORT_Assert(buf->len >= 4); + xtnData->paddingOffset = buf->len - 4; PORT_Assert(ss->vrange.max >= SSL_LIBRARY_VERSION_TLS_1_3); - /* The length computations are simplified by the fact that there - * is just one ticket at most. */ + /* Send a single ticket identity. */ session_ticket = &ss->sec.ci.sid->u.ssl3.locked.sessionTicket; - identities_length = - 2 + /* vector length */ - 2 + session_ticket->ticket.len + /* identity length + ticket len */ - 4; /* obfuscated_ticket_age */ - binders_length = - 2 + /* vector length */ - 1 + tls13_GetHashSizeForHash( - tls13_GetHashForCipherSuite(ss->sec.ci.sid->u.ssl3.cipherSuite)); - extension_length = - 2 + 2 + /* Type + length */ - identities_length + binders_length; - - if (maxBytes < (PRUint32)extension_length) { - PORT_Assert(0); - return 0; - } - - if (append) { - SECStatus rv; - PRTime age; - unsigned int prefixLength; - PRUint8 binder[TLS13_MAX_FINISHED_SIZE]; - unsigned int binderLen; - - /* extension_type */ - rv = ssl3_ExtAppendHandshakeNumber(ss, ssl_tls13_pre_shared_key_xtn, 2); - if (rv != SECSuccess) - goto loser; - rv = ssl3_ExtAppendHandshakeNumber(ss, extension_length - 4, 2); - if (rv != SECSuccess) - goto loser; - rv = ssl3_ExtAppendHandshakeNumber(ss, identities_length - 2, 2); - if (rv != SECSuccess) - goto loser; - rv = ssl3_ExtAppendHandshakeVariable(ss, session_ticket->ticket.data, - session_ticket->ticket.len, 2); - if (rv != SECSuccess) - goto loser; + rv = sslBuffer_AppendNumber(buf, 2 + /* identity length */ + session_ticket->ticket.len + /* ticket */ + 4 /* obfuscated_ticket_age */, + 2); + if (rv != SECSuccess) + goto loser; + rv = sslBuffer_AppendVariable(buf, session_ticket->ticket.data, + session_ticket->ticket.len, 2); + if (rv != SECSuccess) + goto loser; - /* Obfuscated age. */ - age = PR_Now() - session_ticket->received_timestamp; - age /= PR_USEC_PER_MSEC; - age += session_ticket->ticket_age_add; - rv = ssl3_ExtAppendHandshakeNumber(ss, age, 4); - if (rv != SECSuccess) - goto loser; + /* Obfuscated age. */ + age = PR_Now() - session_ticket->received_timestamp; + age /= PR_USEC_PER_MSEC; + age += session_ticket->ticket_age_add; + rv = sslBuffer_AppendNumber(buf, age, 4); + if (rv != SECSuccess) + goto loser; - /* Now the binders. */ - prefixLength = ss->ssl3.hs.messages.len; - rv = tls13_ComputePskBinder(CONST_CAST(sslSocket, ss), PR_TRUE, - prefixLength, binder, &binderLen, - sizeof(binder)); - if (rv != SECSuccess) - goto loser; - PORT_Assert(binderLen == tls13_GetHashSize(ss)); - rv = ssl3_ExtAppendHandshakeNumber(ss, binders_length - 2, 2); - if (rv != SECSuccess) - goto loser; - rv = ssl3_ExtAppendHandshakeVariable(ss, - binder, binderLen, 1); - if (rv != SECSuccess) - goto loser; + /* Write out the binder list length. */ + binderLen = tls13_GetHashSize(ss); + rv = sslBuffer_AppendNumber(buf, binderLen + 1, 2); + if (rv != SECSuccess) + goto loser; + /* Write zeroes for the binder for the moment. */ + rv = sslBuffer_AppendVariable(buf, binder, binderLen, 1); + if (rv != SECSuccess) + goto loser; - PRINT_BUF(50, (ss, "Sending PreSharedKey value", - session_ticket->ticket.data, - session_ticket->ticket.len)); + PRINT_BUF(50, (ss, "Sending PreSharedKey value", + session_ticket->ticket.data, + session_ticket->ticket.len)); - xtnData->sentSessionTicketInClientHello = PR_TRUE; - xtnData->advertised[xtnData->numAdvertised++] = - ssl_tls13_pre_shared_key_xtn; - } - return extension_length; + xtnData->sentSessionTicketInClientHello = PR_TRUE; + *added = PR_TRUE; + return SECSuccess; loser: xtnData->ticketTimestampVerified = PR_FALSE; - return -1; + return SECFailure; } /* Handle a TLS 1.3 PreSharedKey Extension. We only accept PSKs * that contain session tickets. */ SECStatus -tls13_ServerHandlePreSharedKeyXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRUint16 ex_type, +tls13_ServerHandlePreSharedKeyXtn(const sslSocket *ss, TLSExtensionData *xtnData, SECItem *data) { SECItem inner; @@ -635,7 +538,7 @@ tls13_ServerHandlePreSharedKeyXtn(const sslSocket *ss, TLSExtensionData *xtnData /* Keep track of negotiated extensions. Note that this does not * mean we are resuming. */ - xtnData->negotiated[xtnData->numNegotiated++] = ex_type; + xtnData->negotiated[xtnData->numNegotiated++] = ssl_tls13_pre_shared_key_xtn; return SECSuccess; @@ -645,43 +548,27 @@ tls13_ServerHandlePreSharedKeyXtn(const sslSocket *ss, TLSExtensionData *xtnData return SECFailure; } -PRInt32 +SECStatus tls13_ServerSendPreSharedKeyXtn(const sslSocket *ss, TLSExtensionData *xtnData, - PRBool append, - PRUint32 maxBytes) + sslBuffer *buf, PRBool *added) { - PRInt32 extension_length = - 2 + 2 + 2; /* type + len + index */ SECStatus rv; - if (maxBytes < (PRUint32)extension_length) { - PORT_Assert(0); - return 0; - } - - if (append) { - rv = ssl3_ExtAppendHandshakeNumber(ss, ssl_tls13_pre_shared_key_xtn, 2); - if (rv != SECSuccess) - return -1; - - rv = ssl3_ExtAppendHandshakeNumber(ss, 2, 2); - if (rv != SECSuccess) - return -1; - - /* We only process the first session ticket the client sends, - * so the index is always 0. */ - rv = ssl3_ExtAppendHandshakeNumber(ss, 0, 2); - if (rv != SECSuccess) - return -1; + /* We only process the first session ticket the client sends, + * so the index is always 0. */ + rv = sslBuffer_AppendNumber(buf, 0, 2); + if (rv != SECSuccess) { + return SECFailure; } - return extension_length; + *added = PR_TRUE; + return SECSuccess; } /* Handle a TLS 1.3 PreSharedKey Extension. We only accept PSKs * that contain session tickets. */ SECStatus -tls13_ClientHandlePreSharedKeyXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRUint16 ex_type, +tls13_ClientHandlePreSharedKeyXtn(const sslSocket *ss, TLSExtensionData *xtnData, SECItem *data) { PRUint32 index; @@ -713,7 +600,7 @@ tls13_ClientHandlePreSharedKeyXtn(const sslSocket *ss, TLSExtensionData *xtnData } /* Keep track of negotiated extensions. */ - xtnData->negotiated[xtnData->numNegotiated++] = ex_type; + xtnData->negotiated[xtnData->numNegotiated++] = ssl_tls13_pre_shared_key_xtn; return SECSuccess; } @@ -721,43 +608,20 @@ tls13_ClientHandlePreSharedKeyXtn(const sslSocket *ss, TLSExtensionData *xtnData /* * struct { } EarlyDataIndication; */ -PRInt32 +SECStatus tls13_ClientSendEarlyDataXtn(const sslSocket *ss, TLSExtensionData *xtnData, - PRBool append, - PRUint32 maxBytes) + sslBuffer *buf, PRBool *added) { - SECStatus rv; - PRInt32 extension_length; - - if (!tls13_ClientAllow0Rtt(ss, ss->sec.ci.sid)) - return 0; - - /* type + length */ - extension_length = 2 + 2; - - if (maxBytes < (PRUint32)extension_length) { - PORT_Assert(0); - return 0; - } - - if (append) { - rv = ssl3_ExtAppendHandshakeNumber(ss, ssl_tls13_early_data_xtn, 2); - if (rv != SECSuccess) - return -1; - - rv = ssl3_ExtAppendHandshakeNumber(ss, 0, 2); - if (rv != SECSuccess) - return -1; - - xtnData->advertised[xtnData->numAdvertised++] = - ssl_tls13_early_data_xtn; + if (!tls13_ClientAllow0Rtt(ss, ss->sec.ci.sid)) { + return SECSuccess; } - return extension_length; + *added = PR_TRUE; + return SECSuccess; } SECStatus -tls13_ServerHandleEarlyDataXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRUint16 ex_type, +tls13_ServerHandleEarlyDataXtn(const sslSocket *ss, TLSExtensionData *xtnData, SECItem *data) { SSL_TRC(3, ("%d: TLS13[%d]: handle early_data extension", @@ -779,44 +643,14 @@ tls13_ServerHandleEarlyDataXtn(const sslSocket *ss, TLSExtensionData *xtnData, P return SECFailure; } - xtnData->negotiated[xtnData->numNegotiated++] = ex_type; + xtnData->negotiated[xtnData->numNegotiated++] = ssl_tls13_early_data_xtn; return SECSuccess; } -/* This is only registered if we are sending it. */ -PRInt32 -tls13_ServerSendEarlyDataXtn(const sslSocket *ss, TLSExtensionData *xtnData, - PRBool append, - PRUint32 maxBytes) -{ - SSL_TRC(3, ("%d: TLS13[%d]: send early_data extension", - SSL_GETPID(), ss->fd)); - - PORT_Assert(ss->ssl3.hs.zeroRttState == ssl_0rtt_accepted); - if (maxBytes < 4) { - PORT_Assert(0); - return 0; - } - - if (append) { - SECStatus rv; - - rv = ssl3_ExtAppendHandshakeNumber(ss, ssl_tls13_early_data_xtn, 2); - if (rv != SECSuccess) - return -1; - - rv = ssl3_ExtAppendHandshakeNumber(ss, 0, 2); - if (rv != SECSuccess) - return -1; - } - - return 4; -} - /* This will only be called if we also offered the extension. */ SECStatus -tls13_ClientHandleEarlyDataXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRUint16 ex_type, +tls13_ClientHandleEarlyDataXtn(const sslSocket *ss, TLSExtensionData *xtnData, SECItem *data) { SSL_TRC(3, ("%d: TLS13[%d]: handle early_data extension", @@ -834,14 +668,14 @@ tls13_ClientHandleEarlyDataXtn(const sslSocket *ss, TLSExtensionData *xtnData, P } /* Keep track of negotiated extensions. */ - xtnData->negotiated[xtnData->numNegotiated++] = ex_type; + xtnData->negotiated[xtnData->numNegotiated++] = ssl_tls13_early_data_xtn; return SECSuccess; } SECStatus tls13_ClientHandleTicketEarlyDataXtn(const sslSocket *ss, TLSExtensionData *xtnData, - PRUint16 ex_type, SECItem *data) + SECItem *data) { PRUint32 utmp; SECStatus rv; @@ -876,56 +710,34 @@ tls13_ClientHandleTicketEarlyDataXtn(const sslSocket *ss, TLSExtensionData *xtnD * ProtocolVersion versions<2..254>; * } SupportedVersions; */ -PRInt32 -tls13_ClientSendSupportedVersionsXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRBool append, - PRUint32 maxBytes) +SECStatus +tls13_ClientSendSupportedVersionsXtn(const sslSocket *ss, TLSExtensionData *xtnData, + sslBuffer *buf, PRBool *added) { - PRInt32 extensions_len; PRUint16 version; + unsigned int size; SECStatus rv; if (ss->vrange.max < SSL_LIBRARY_VERSION_TLS_1_3) { - return 0; + return SECSuccess; } SSL_TRC(3, ("%d: TLS13[%d]: send supported_versions extension", SSL_GETPID(), ss->fd)); - /* Extension type, extension len fiels, vector len field, - * length of the values. */ - extensions_len = 2 + 2 + 1 + - 2 * (ss->vrange.max - ss->vrange.min + 1); - - if (maxBytes < (PRUint32)extensions_len) { - PORT_Assert(0); - return 0; - } - - if (append) { - rv = ssl3_ExtAppendHandshakeNumber(ss, ssl_tls13_supported_versions_xtn, 2); - if (rv != SECSuccess) - return -1; - - rv = ssl3_ExtAppendHandshakeNumber(ss, extensions_len - 4, 2); - if (rv != SECSuccess) - return -1; + size = 2 * (ss->vrange.max - ss->vrange.min + 1); + rv = sslBuffer_AppendNumber(buf, size, 1); + if (rv != SECSuccess) + return -1; - rv = ssl3_ExtAppendHandshakeNumber(ss, extensions_len - 5, 1); + for (version = ss->vrange.max; version >= ss->vrange.min; --version) { + rv = sslBuffer_AppendNumber(buf, tls13_EncodeDraftVersion(version), 2); if (rv != SECSuccess) - return -1; - - for (version = ss->vrange.max; version >= ss->vrange.min; --version) { - rv = ssl3_ExtAppendHandshakeNumber( - ss, tls13_EncodeDraftVersion(version), 2); - if (rv != SECSuccess) - return -1; - } - - xtnData->advertised[xtnData->numAdvertised++] = - ssl_tls13_supported_versions_xtn; + return SECFailure; } - return extensions_len; + *added = PR_TRUE; + return SECSuccess; } /* @@ -934,7 +746,8 @@ tls13_ClientSendSupportedVersionsXtn(const sslSocket *ss, TLSExtensionData *xtnD * } Cookie; */ SECStatus -tls13_ClientHandleHrrCookie(const sslSocket *ss, TLSExtensionData *xtnData, PRUint16 ex_type, SECItem *data) +tls13_ClientHandleHrrCookie(const sslSocket *ss, TLSExtensionData *xtnData, + SECItem *data) { SECStatus rv; @@ -960,41 +773,26 @@ tls13_ClientHandleHrrCookie(const sslSocket *ss, TLSExtensionData *xtnData, PRUi return SECSuccess; } -PRInt32 -tls13_ClientSendHrrCookieXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRBool append, PRUint32 maxBytes) +SECStatus +tls13_ClientSendHrrCookieXtn(const sslSocket *ss, TLSExtensionData *xtnData, + sslBuffer *buf, PRBool *added) { - PRInt32 extension_len; + SECStatus rv; if (ss->vrange.max < SSL_LIBRARY_VERSION_TLS_1_3 || !ss->ssl3.hs.cookie.len) { - return 0; + return SECSuccess; } SSL_TRC(3, ("%d: TLS13[%d]: send cookie extension", SSL_GETPID(), ss->fd)); - - /* Extension type, length, cookie length, cookie value. */ - extension_len = 2 + 2 + 2 + ss->ssl3.hs.cookie.len; - - if (maxBytes < (PRUint32)extension_len) { - PORT_Assert(0); - return 0; + rv = sslBuffer_AppendVariable(buf, ss->ssl3.hs.cookie.data, + ss->ssl3.hs.cookie.len, 2); + if (rv != SECSuccess) { + return SECFailure; } - if (append) { - SECStatus rv = ssl3_ExtAppendHandshakeNumber(ss, ssl_tls13_cookie_xtn, 2); - if (rv != SECSuccess) - return -1; - - rv = ssl3_ExtAppendHandshakeNumber(ss, extension_len - 4, 2); - if (rv != SECSuccess) - return -1; - - rv = ssl3_ExtAppendHandshakeVariable(ss, ss->ssl3.hs.cookie.data, - ss->ssl3.hs.cookie.len, 2); - if (rv != SECSuccess) - return -1; - } - return extension_len; + *added = PR_TRUE; + return SECSuccess; } /* @@ -1004,54 +802,33 @@ tls13_ClientSendHrrCookieXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRB * PskKeyExchangeMode ke_modes<1..255>; * } PskKeyExchangeModes; */ -PRInt32 -tls13_ClientSendPskKeyExchangeModesXtn(const sslSocket *ss, - TLSExtensionData *xtnData, - PRBool append, PRUint32 maxBytes) +SECStatus +tls13_ClientSendPskModesXtn(const sslSocket *ss, TLSExtensionData *xtnData, + sslBuffer *buf, PRBool *added) { static const PRUint8 ke_modes[] = { tls13_psk_dh_ke }; - static const unsigned long ke_modes_len = sizeof(ke_modes); - PRInt32 extension_len; + SECStatus rv; if (ss->vrange.max < SSL_LIBRARY_VERSION_TLS_1_3 || ss->opt.noCache) { - return 0; + return SECSuccess; } - extension_len = - 2 + 2 + /* Type + length */ - 1 + ke_modes_len; /* key exchange modes vector */ - SSL_TRC(3, ("%d: TLS13[%d]: send psk key exchange modes extension", SSL_GETPID(), ss->fd)); - if (maxBytes < (PRUint32)extension_len) { - PORT_Assert(0); - return 0; + rv = sslBuffer_AppendVariable(buf, ke_modes, sizeof(ke_modes), 1); + if (rv != SECSuccess) { + return SECFailure; } - if (append) { - SECStatus rv = ssl3_ExtAppendHandshakeNumber( - ss, ssl_tls13_psk_key_exchange_modes_xtn, 2); - if (rv != SECSuccess) - return -1; - - rv = ssl3_ExtAppendHandshakeNumber(ss, extension_len - 4, 2); - if (rv != SECSuccess) - return -1; - - rv = ssl3_ExtAppendHandshakeVariable( - ss, ke_modes, ke_modes_len, 1); - if (rv != SECSuccess) - return -1; - } - return extension_len; + *added = PR_TRUE; + return SECSuccess; } SECStatus -tls13_ServerHandlePskKeyExchangeModesXtn(const sslSocket *ss, - TLSExtensionData *xtnData, - PRUint16 ex_type, SECItem *data) +tls13_ServerHandlePskModesXtn(const sslSocket *ss, TLSExtensionData *xtnData, + SECItem *data) { SECStatus rv; @@ -1076,121 +853,16 @@ tls13_ServerHandlePskKeyExchangeModesXtn(const sslSocket *ss, } /* Keep track of negotiated extensions. */ - xtnData->negotiated[xtnData->numNegotiated++] = ex_type; + xtnData->negotiated[xtnData->numNegotiated++] = + ssl_tls13_psk_key_exchange_modes_xtn; return SECSuccess; } -PRInt32 -tls13_SendShortHeaderXtn(const sslSocket *ss, - TLSExtensionData *xtnData, - PRBool append, PRUint32 maxBytes) -{ - PRUint32 extension_len = 2 + 2; /* Type + length (0). */ - - if (!ss->opt.enableShortHeaders) { - return 0; - } - - /* Presently this is incompatible with 0-RTT. We will fix if - * it becomes more than an experiment. */ - if (ss->opt.enable0RttData) { - return 0; - } - - if (IS_DTLS(ss)) { - return 0; - } - - /* Don't send this if TLS 1.3 isn't at least possible. */ - if (ss->vrange.max < SSL_LIBRARY_VERSION_TLS_1_3) { - /* This should only happen on the client. */ - PORT_Assert(!ss->sec.isServer); - return 0; - } - - SSL_TRC(3, ("%d: TLS13[%d]: send short_header extension", - SSL_GETPID(), ss->fd)); - - if (maxBytes < extension_len) { - PORT_Assert(0); - return 0; - } - - if (append) { - SECStatus rv; - - rv = ssl3_ExtAppendHandshakeNumber(ss, ssl_tls13_short_header_xtn, 2); - if (rv != SECSuccess) - return -1; - - rv = ssl3_ExtAppendHandshakeNumber(ss, 0, 2); - if (rv != SECSuccess) - return -1; - - xtnData->advertised[xtnData->numAdvertised++] = - ssl_tls13_short_header_xtn; - } - - return extension_len; -} - SECStatus -tls13_HandleShortHeaderXtn( - const sslSocket *ss, TLSExtensionData *xtnData, PRUint16 ex_type, - SECItem *data) -{ - SSL_TRC(3, ("%d: TLS13[%d]: handle short_header extension", - SSL_GETPID(), ss->fd)); - - /* The client might have asked for this, but we didn't negotiate TLS 1.3. */ - if (ss->version < SSL_LIBRARY_VERSION_TLS_1_3) { - return SECSuccess; - } - - /* Presently this is incompatible with 0-RTT. We will fix if - * it becomes more than an experiment. */ - if (ss->opt.enable0RttData) { - return SECSuccess; - } - - if (IS_DTLS(ss)) { - PORT_SetError(SSL_ERROR_EXTENSION_DISALLOWED_FOR_VERSION); - return SECFailure; - } - - if (data->len) { - PORT_SetError(SSL_ERROR_RX_MALFORMED_HANDSHAKE); - return SECFailure; - } - - if (!ss->opt.enableShortHeaders) { - /* Ignore. */ - return SECSuccess; - } - - /* Keep track of negotiated extensions. */ - xtnData->negotiated[xtnData->numNegotiated++] = ex_type; - - if (ss->sec.isServer) { - SECStatus rv; - - rv = ssl3_RegisterExtensionSender(ss, xtnData, - ssl_tls13_short_header_xtn, - tls13_SendShortHeaderXtn); - if (rv != SECSuccess) { - return SECFailure; - } - } - - return SECSuccess; -} - -PRInt32 tls13_SendCertAuthoritiesXtn(const sslSocket *ss, TLSExtensionData *xtnData, - PRBool append, PRUint32 maxBytes) + sslBuffer *buf, PRBool *added) { - unsigned int extensionLen; unsigned int calen; const SECItem *name; unsigned int nnames; @@ -1200,50 +872,35 @@ tls13_SendCertAuthoritiesXtn(const sslSocket *ss, TLSExtensionData *xtnData, rv = ssl_GetCertificateRequestCAs(ss, &calen, &name, &nnames); if (rv != SECSuccess) { - return -1; + return SECFailure; } if (!calen) { - return 0; + return SECSuccess; } - extensionLen = 2 + 2 + 2 + calen; /* type, length, inner length, CA list */ - if (maxBytes < extensionLen) { - PORT_Assert(0); - return 0; + rv = sslBuffer_AppendNumber(buf, calen, 2); + if (rv != SECSuccess) { + return SECFailure; } - if (append) { - rv = ssl3_ExtAppendHandshakeNumber(ss, ssl_tls13_certificate_authorities_xtn, 2); + while (nnames) { + rv = sslBuffer_AppendVariable(buf, name->data, name->len, 2); if (rv != SECSuccess) { - return -1; - } - rv = ssl3_ExtAppendHandshakeNumber(ss, calen + 2, 2); - if (rv != SECSuccess) { - return -1; - } - rv = ssl3_ExtAppendHandshakeNumber(ss, calen, 2); - if (rv != SECSuccess) { - return -1; - } - - while (nnames) { - rv = ssl3_ExtAppendHandshakeVariable(ss, name->data, name->len, 2); - if (rv != SECSuccess) { - return -1; - } - ++name; - --nnames; + return SECFailure; } + ++name; + --nnames; } - return extensionLen; + *added = PR_TRUE; + return SECSuccess; } SECStatus tls13_ClientHandleCertAuthoritiesXtn(const sslSocket *ss, TLSExtensionData *xtnData, - PRUint16 ex_type, SECItem *data) + SECItem *data) { SECStatus rv; PLArenaPool *arena; diff --git a/lib/ssl/tls13exthandle.h b/lib/ssl/tls13exthandle.h index 7b7b3f8743..0de2af57dd 100644 --- a/lib/ssl/tls13exthandle.h +++ b/lib/ssl/tls13exthandle.h @@ -9,73 +9,68 @@ #ifndef __tls13exthandle_h_ #define __tls13exthandle_h_ -PRInt32 tls13_ServerSendStatusRequestXtn(const sslSocket *ss, TLSExtensionData *xtnData, - PRBool append, PRUint32 maxBytes); -PRInt32 tls13_ClientSendKeyShareXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRBool append, - PRUint32 maxBytes); -SECStatus tls13_ClientHandleKeyShareXtn(const sslSocket *ss, TLSExtensionData *xtnData, - PRUint16 ex_type, +SECStatus tls13_ServerSendStatusRequestXtn(const sslSocket *ss, + TLSExtensionData *xtnData, + sslBuffer *buf, PRBool *append); +SECStatus tls13_ClientSendKeyShareXtn(const sslSocket *ss, + TLSExtensionData *xtnData, + sslBuffer *buf, PRBool *append); +SECStatus tls13_ClientHandleKeyShareXtn(const sslSocket *ss, + TLSExtensionData *xtnData, SECItem *data); -SECStatus tls13_ClientHandleKeyShareXtnHrr(const sslSocket *ss, TLSExtensionData *xtnData, - PRUint16 ex_type, +SECStatus tls13_ClientHandleKeyShareXtnHrr(const sslSocket *ss, + TLSExtensionData *xtnData, SECItem *data); -SECStatus tls13_ServerHandleKeyShareXtn(const sslSocket *ss, TLSExtensionData *xtnData, - PRUint16 ex_type, +SECStatus tls13_ServerHandleKeyShareXtn(const sslSocket *ss, + TLSExtensionData *xtnData, SECItem *data); -PRInt32 tls13_ServerSendKeyShareXtn(const sslSocket *ss, - TLSExtensionData *xtnData, - PRBool append, - PRUint32 maxBytes); -PRInt32 tls13_ClientSendPreSharedKeyXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRBool append, - PRUint32 maxBytes); -SECStatus tls13_ServerHandlePreSharedKeyXtn(const sslSocket *ss, TLSExtensionData *xtnData, - PRUint16 ex_type, +SECStatus tls13_ServerSendKeyShareXtn(const sslSocket *ss, + TLSExtensionData *xtnData, + sslBuffer *buf, PRBool *append); +SECStatus tls13_ClientSendPreSharedKeyXtn(const sslSocket *ss, + TLSExtensionData *xtnData, + sslBuffer *buf, PRBool *append); +SECStatus tls13_ServerHandlePreSharedKeyXtn(const sslSocket *ss, + TLSExtensionData *xtnData, SECItem *data); -SECStatus tls13_ClientHandlePreSharedKeyXtn(const sslSocket *ss, TLSExtensionData *xtnData, - PRUint16 ex_type, +SECStatus tls13_ClientHandlePreSharedKeyXtn(const sslSocket *ss, + TLSExtensionData *xtnData, SECItem *data); -PRInt32 tls13_ServerSendPreSharedKeyXtn(const sslSocket *ss, TLSExtensionData *xtnData, - PRBool append, - PRUint32 maxBytes); -PRInt32 tls13_ClientSendEarlyDataXtn(const sslSocket *ss, TLSExtensionData *xtnData, - PRBool append, - PRUint32 maxBytes); -SECStatus tls13_ServerHandleEarlyDataXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRUint16 ex_type, +SECStatus tls13_ServerSendPreSharedKeyXtn(const sslSocket *ss, + TLSExtensionData *xtnData, + sslBuffer *buf, PRBool *append); +SECStatus tls13_ClientSendEarlyDataXtn(const sslSocket *ss, + TLSExtensionData *xtnData, + sslBuffer *buf, PRBool *append); +SECStatus tls13_ServerHandleEarlyDataXtn(const sslSocket *ss, + TLSExtensionData *xtnData, SECItem *data); -SECStatus tls13_ClientHandleEarlyDataXtn(const sslSocket *ss, TLSExtensionData *xtnData, PRUint16 ex_type, +SECStatus tls13_ClientHandleEarlyDataXtn(const sslSocket *ss, + TLSExtensionData *xtnData, SECItem *data); -PRInt32 tls13_ServerSendEarlyDataXtn(const sslSocket *ss, TLSExtensionData *xtnData, - PRBool append, - PRUint32 maxBytes); -SECStatus tls13_ClientHandleTicketEarlyDataXtn( - const sslSocket *ss, TLSExtensionData *xtnData, PRUint16 ex_type, - SECItem *data); -PRInt32 tls13_ClientSendSupportedVersionsXtn(const sslSocket *ss, TLSExtensionData *xtnData, - PRBool append, - PRUint32 maxBytes); -SECStatus tls13_ClientHandleHrrCookie(const sslSocket *ss, TLSExtensionData *xtnData, PRUint16 ex_type, - SECItem *data); -PRInt32 tls13_ClientSendHrrCookieXtn(const sslSocket *ss, TLSExtensionData *xtnData, - PRBool append, - PRUint32 maxBytes); -PRInt32 tls13_ClientSendPskKeyExchangeModesXtn(const sslSocket *ss, +SECStatus tls13_ClientHandleTicketEarlyDataXtn(const sslSocket *ss, TLSExtensionData *xtnData, - PRBool append, PRUint32 maxBytes); -SECStatus tls13_ServerHandlePskKeyExchangeModesXtn(const sslSocket *ss, - TLSExtensionData *xtnData, - PRUint16 ex_type, SECItem *data); -PRInt32 tls13_SendShortHeaderXtn(const sslSocket *ss, - TLSExtensionData *xtnData, - PRBool append, PRUint32 maxBytes); -SECStatus tls13_HandleShortHeaderXtn( - const sslSocket *ss, TLSExtensionData *xtnData, PRUint16 ex_type, - SECItem *data); - -PRInt32 tls13_SendCertAuthoritiesXtn(const sslSocket *ss, - TLSExtensionData *xtnData, - PRBool append, PRUint32 maxBytes); + SECItem *data); +SECStatus tls13_ClientSendSupportedVersionsXtn(const sslSocket *ss, + TLSExtensionData *xtnData, + sslBuffer *buf, PRBool *append); +SECStatus tls13_ClientHandleHrrCookie(const sslSocket *ss, + TLSExtensionData *xtnData, + SECItem *data); +SECStatus tls13_ClientSendHrrCookieXtn(const sslSocket *ss, + TLSExtensionData *xtnData, + sslBuffer *buf, PRBool *append); +SECStatus tls13_ClientSendPskModesXtn(const sslSocket *ss, + TLSExtensionData *xtnData, + sslBuffer *buf, PRBool *append); +SECStatus tls13_ServerHandlePskModesXtn(const sslSocket *ss, + TLSExtensionData *xtnData, + SECItem *data); +SECStatus tls13_SendCertAuthoritiesXtn(const sslSocket *ss, + TLSExtensionData *xtnData, + sslBuffer *buf, PRBool *append); SECStatus tls13_ClientHandleCertAuthoritiesXtn(const sslSocket *ss, TLSExtensionData *xtnData, - PRUint16 ex_type, SECItem *data); + SECItem *data); #endif