Implement QUICv2 in QUICHE. This CL reflects draft-ietf-quic-v2-01, except for the version negotiation bits -- therefore, the enable flag is blocked by the VN bug. There are a bunch of changes to line breaks, particularly in quic_framer, that I believe came from the recently updated code checkers. I'm ignoring some new code checks that suggest changes to existing code constructs -- perhaps we should address the defensive coding stuff in another CL. Protected by FLAGS_quic_reloadable_flag_quic_enable_version_rfcv2. PiperOrigin-RevId: 424961568
diff --git a/quic/core/crypto/crypto_utils.cc b/quic/core/crypto/crypto_utils.cc index 50bbfef..05bbdfe 100644 --- a/quic/core/crypto/crypto_utils.cc +++ b/quic/core/crypto/crypto_utils.cc
@@ -57,8 +57,7 @@ // |out_len|, respectively. The resulting expanded secret is returned. std::vector<uint8_t> HkdfExpandLabel(const EVP_MD* prf, const std::vector<uint8_t>& secret, - const std::string& label, - size_t out_len) { + const std::string& label, size_t out_len) { bssl::ScopedCBB quic_hkdf_label; CBB inner_label; const char label_prefix[] = "tls13 "; @@ -91,13 +90,23 @@ } // namespace +const std::string getLabelForVersion(const ParsedQuicVersion& version, + const absl::string_view& predicate) { + static_assert(SupportedVersions().size() == 6u, + "Supported versions out of sync with HKDF labels"); + if (version == ParsedQuicVersion::V2Draft01()) { + return absl::StrCat("quicv2 ", predicate); + } else { + return absl::StrCat("quic ", predicate); + } +} + void CryptoUtils::InitializeCrypterSecrets( - const EVP_MD* prf, - const std::vector<uint8_t>& pp_secret, - QuicCrypter* crypter) { - SetKeyAndIV(prf, pp_secret, crypter); - std::vector<uint8_t> header_protection_key = - GenerateHeaderProtectionKey(prf, pp_secret, crypter->GetKeySize()); + const EVP_MD* prf, const std::vector<uint8_t>& pp_secret, + const ParsedQuicVersion& version, QuicCrypter* crypter) { + SetKeyAndIV(prf, pp_secret, version, crypter); + std::vector<uint8_t> header_protection_key = GenerateHeaderProtectionKey( + prf, pp_secret, version, crypter->GetKeySize()); crypter->SetHeaderProtectionKey( absl::string_view(reinterpret_cast<char*>(header_protection_key.data()), header_protection_key.size())); @@ -105,11 +114,13 @@ void CryptoUtils::SetKeyAndIV(const EVP_MD* prf, const std::vector<uint8_t>& pp_secret, + const ParsedQuicVersion& version, QuicCrypter* crypter) { std::vector<uint8_t> key = - HkdfExpandLabel(prf, pp_secret, "quic key", crypter->GetKeySize()); - std::vector<uint8_t> iv = - HkdfExpandLabel(prf, pp_secret, "quic iv", crypter->GetIVSize()); + HkdfExpandLabel(prf, pp_secret, getLabelForVersion(version, "key"), + crypter->GetKeySize()); + std::vector<uint8_t> iv = HkdfExpandLabel( + prf, pp_secret, getLabelForVersion(version, "iv"), crypter->GetIVSize()); crypter->SetKey( absl::string_view(reinterpret_cast<char*>(key.data()), key.size())); crypter->SetIV( @@ -117,16 +128,17 @@ } std::vector<uint8_t> CryptoUtils::GenerateHeaderProtectionKey( - const EVP_MD* prf, - const std::vector<uint8_t>& pp_secret, - size_t out_len) { - return HkdfExpandLabel(prf, pp_secret, "quic hp", out_len); + const EVP_MD* prf, const std::vector<uint8_t>& pp_secret, + const ParsedQuicVersion& version, size_t out_len) { + return HkdfExpandLabel(prf, pp_secret, getLabelForVersion(version, "hp"), + out_len); } std::vector<uint8_t> CryptoUtils::GenerateNextKeyPhaseSecret( - const EVP_MD* prf, + const EVP_MD* prf, const ParsedQuicVersion& version, const std::vector<uint8_t>& current_secret) { - return HkdfExpandLabel(prf, current_secret, "quic ku", current_secret.size()); + return HkdfExpandLabel(prf, current_secret, getLabelForVersion(version, "ku"), + current_secret.size()); } namespace { @@ -138,6 +150,9 @@ const uint8_t kRFCv1InitialSalt[] = {0x38, 0x76, 0x2c, 0xf7, 0xf5, 0x59, 0x34, 0xb3, 0x4d, 0x17, 0x9a, 0xe6, 0xa4, 0xc8, 0x0c, 0xad, 0xcc, 0xbb, 0x7f, 0x0a}; +const uint8_t kV2Draft01InitialSalt[] = { + 0xa7, 0x07, 0xc2, 0x03, 0xa5, 0x9b, 0x47, 0x18, 0x4a, 0x1d, + 0x62, 0xca, 0x57, 0x04, 0x06, 0xea, 0x7a, 0xe3, 0xe5, 0xd3}; // Salts used by deployed versions of QUIC. When introducing a new version, // generate a new salt by running `openssl rand -hex 20`. @@ -154,9 +169,12 @@ const uint8_t* InitialSaltForVersion(const ParsedQuicVersion& version, size_t* out_len) { - static_assert(SupportedVersions().size() == 5u, + static_assert(SupportedVersions().size() == 6u, "Supported versions out of sync with initial encryption salts"); - if (version == ParsedQuicVersion::RFCv1()) { + if (version == ParsedQuicVersion::V2Draft01()) { + *out_len = ABSL_ARRAYSIZE(kV2Draft01InitialSalt); + return kV2Draft01InitialSalt; + } else if (version == ParsedQuicVersion::RFCv1()) { *out_len = ABSL_ARRAYSIZE(kRFCv1InitialSalt); return kRFCv1InitialSalt; } else if (version == ParsedQuicVersion::Draft29()) { @@ -191,6 +209,11 @@ 0xe3, 0x68, 0xc8, 0x4e}; const uint8_t kRFCv1RetryIntegrityNonce[] = { 0x46, 0x15, 0x99, 0xd3, 0x5d, 0x63, 0x2b, 0xf2, 0x23, 0x98, 0x25, 0xbb}; +const uint8_t kV2Draft01RetryIntegrityKey[] = { + 0xba, 0x85, 0x8d, 0xc7, 0xb4, 0x3d, 0xe5, 0xdb, + 0xf8, 0x76, 0x17, 0xff, 0x4a, 0xb2, 0x53, 0xdb}; +const uint8_t kV2Draft01RetryIntegrityNonce[] = { + 0x14, 0x1b, 0x99, 0xc2, 0x39, 0xb0, 0x3e, 0x78, 0x5d, 0x6a, 0x2e, 0x9f}; // Retry integrity key used by ParsedQuicVersion::ReservedForNegotiation(). const uint8_t kReservedForNegotiationRetryIntegrityKey[] = { 0xf2, 0xcd, 0x8f, 0xe0, 0x36, 0xd0, 0x25, 0x35, @@ -204,13 +227,21 @@ bool RetryIntegrityKeysForVersion(const ParsedQuicVersion& version, absl::string_view* key, absl::string_view* nonce) { - static_assert(SupportedVersions().size() == 5u, + static_assert(SupportedVersions().size() == 6u, "Supported versions out of sync with retry integrity keys"); if (!version.UsesTls()) { QUIC_BUG(quic_bug_10699_2) << "Attempted to get retry integrity keys for invalid version " << version; return false; + } else if (version == ParsedQuicVersion::V2Draft01()) { + *key = absl::string_view( + reinterpret_cast<const char*>(kV2Draft01RetryIntegrityKey), + ABSL_ARRAYSIZE(kV2Draft01RetryIntegrityKey)); + *nonce = absl::string_view( + reinterpret_cast<const char*>(kV2Draft01RetryIntegrityNonce), + ABSL_ARRAYSIZE(kV2Draft01RetryIntegrityNonce)); + return true; } else if (version == ParsedQuicVersion::RFCv1()) { *key = absl::string_view( reinterpret_cast<const char*>(kRFCv1RetryIntegrityKey), @@ -291,20 +322,20 @@ std::vector<uint8_t> encryption_secret = HkdfExpandLabel( hash, handshake_secret, encryption_label, EVP_MD_size(hash)); crypters->encrypter = std::make_unique<Aes128GcmEncrypter>(); - InitializeCrypterSecrets(hash, encryption_secret, crypters->encrypter.get()); + InitializeCrypterSecrets(hash, encryption_secret, version, + crypters->encrypter.get()); std::vector<uint8_t> decryption_secret = HkdfExpandLabel( hash, handshake_secret, decryption_label, EVP_MD_size(hash)); crypters->decrypter = std::make_unique<Aes128GcmDecrypter>(); - InitializeCrypterSecrets(hash, decryption_secret, crypters->decrypter.get()); + InitializeCrypterSecrets(hash, decryption_secret, version, + crypters->decrypter.get()); } // static bool CryptoUtils::ValidateRetryIntegrityTag( - ParsedQuicVersion version, - QuicConnectionId original_connection_id, - absl::string_view retry_without_tag, - absl::string_view integrity_tag) { + ParsedQuicVersion version, QuicConnectionId original_connection_id, + absl::string_view retry_without_tag, absl::string_view integrity_tag) { unsigned char computed_integrity_tag[kRetryIntegrityTagLength]; if (integrity_tag.length() != ABSL_ARRAYSIZE(computed_integrity_tag)) { QUIC_BUG(quic_bug_10699_4) @@ -348,10 +379,8 @@ } // static -void CryptoUtils::GenerateNonce(QuicWallTime now, - QuicRandom* random_generator, - absl::string_view orbit, - std::string* nonce) { +void CryptoUtils::GenerateNonce(QuicWallTime now, QuicRandom* random_generator, + absl::string_view orbit, std::string* nonce) { // a 4-byte timestamp + 28 random bytes. nonce->reserve(kNonceSize); nonce->resize(kNonceSize); @@ -375,17 +404,13 @@ } // static -bool CryptoUtils::DeriveKeys(const ParsedQuicVersion& version, - absl::string_view premaster_secret, - QuicTag aead, - absl::string_view client_nonce, - absl::string_view server_nonce, - absl::string_view pre_shared_key, - const std::string& hkdf_input, - Perspective perspective, - Diversification diversification, - CrypterPair* crypters, - std::string* subkey_secret) { +bool CryptoUtils::DeriveKeys( + const ParsedQuicVersion& version, absl::string_view premaster_secret, + QuicTag aead, absl::string_view client_nonce, + absl::string_view server_nonce, absl::string_view pre_shared_key, + const std::string& hkdf_input, Perspective perspective, + Diversification diversification, CrypterPair* crypters, + std::string* subkey_secret) { // If the connection is using PSK, concatenate it with the pre-master secret. std::unique_ptr<char[]> psk_premaster_secret; if (!pre_shared_key.empty()) { @@ -573,8 +598,7 @@ } QuicErrorCode CryptoUtils::ValidateClientHello( - const CryptoHandshakeMessage& client_hello, - ParsedQuicVersion version, + const CryptoHandshakeMessage& client_hello, ParsedQuicVersion version, const ParsedQuicVersionVector& supported_versions, std::string* error_details) { if (client_hello.tag() != kCHLO) { @@ -597,8 +621,7 @@ } QuicErrorCode CryptoUtils::ValidateClientHelloVersion( - QuicVersionLabel client_version, - ParsedQuicVersion connection_version, + QuicVersionLabel client_version, ParsedQuicVersion connection_version, const ParsedQuicVersionVector& supported_versions, std::string* error_details) { if (client_version != CreateQuicVersionLabel(connection_version)) { @@ -736,8 +759,7 @@ // static std::string CryptoUtils::HashHandshakeMessage( - const CryptoHandshakeMessage& message, - Perspective /*perspective*/) { + const CryptoHandshakeMessage& message, Perspective /*perspective*/) { std::string output; const QuicData& serialized = message.GetSerialized(); uint8_t digest[SHA256_DIGEST_LENGTH];
diff --git a/quic/core/crypto/crypto_utils.h b/quic/core/crypto/crypto_utils.h index 8884f6f..fce6201 100644 --- a/quic/core/crypto/crypto_utils.h +++ b/quic/core/crypto/crypto_utils.h
@@ -79,9 +79,11 @@ // on the given QuicCrypter |*crypter|. // This follows the derivation described in section 7.3 of RFC 8446, except // with the label prefix in HKDF-Expand-Label changed from "tls13 " to "quic " - // as described in draft-ietf-quic-tls-14, section 5.1. + // as described in draft-ietf-quic-tls-14, section 5.1, or "quicv2 " as + // described in draft-ietf-quic-v2-01. static void InitializeCrypterSecrets(const EVP_MD* prf, const std::vector<uint8_t>& pp_secret, + const ParsedQuicVersion& version, QuicCrypter* crypter); // Derives the key and IV from the packet protection secret and sets those @@ -90,17 +92,17 @@ // called before using |crypter|. static void SetKeyAndIV(const EVP_MD* prf, const std::vector<uint8_t>& pp_secret, + const ParsedQuicVersion& version, QuicCrypter* crypter); // Derives the header protection key from the packet protection secret. static std::vector<uint8_t> GenerateHeaderProtectionKey( - const EVP_MD* prf, - const std::vector<uint8_t>& pp_secret, - size_t out_len); + const EVP_MD* prf, const std::vector<uint8_t>& pp_secret, + const ParsedQuicVersion& version, size_t out_len); // Given a secret for key phase n, return the secret for phase n+1. static std::vector<uint8_t> GenerateNextKeyPhaseSecret( - const EVP_MD* prf, + const EVP_MD* prf, const ParsedQuicVersion& version, const std::vector<uint8_t>& current_secret); // IETF QUIC encrypts ENCRYPTION_INITIAL messages with a version-specific key @@ -130,10 +132,8 @@ // <4 bytes> current time // <8 bytes> |orbit| (or random if |orbit| is empty) // <20 bytes> random - static void GenerateNonce(QuicWallTime now, - QuicRandom* random_generator, - absl::string_view orbit, - std::string* nonce); + static void GenerateNonce(QuicWallTime now, QuicRandom* random_generator, + absl::string_view orbit, std::string* nonce); // DeriveKeys populates |crypters->encrypter|, |crypters->decrypter|, and // |subkey_secret| (optional -- may be null) given the contents of @@ -155,15 +155,12 @@ // |SetDiversificationNonce| with a diversification nonce will be needed to // complete keying. static bool DeriveKeys(const ParsedQuicVersion& version, - absl::string_view premaster_secret, - QuicTag aead, + absl::string_view premaster_secret, QuicTag aead, absl::string_view client_nonce, absl::string_view server_nonce, absl::string_view pre_shared_key, - const std::string& hkdf_input, - Perspective perspective, - Diversification diversification, - CrypterPair* crypters, + const std::string& hkdf_input, Perspective perspective, + Diversification diversification, CrypterPair* crypters, std::string* subkey_secret); // Computes the FNV-1a hash of the provided DER-encoded cert for use in the @@ -199,8 +196,7 @@ // Returns QUIC_NO_ERROR if this is the case or returns the appropriate error // code and sets |error_details|. static QuicErrorCode ValidateClientHello( - const CryptoHandshakeMessage& client_hello, - ParsedQuicVersion version, + const CryptoHandshakeMessage& client_hello, ParsedQuicVersion version, const ParsedQuicVersionVector& supported_versions, std::string* error_details); @@ -212,8 +208,7 @@ // Returns QUIC_NO_ERROR if this is the case or returns the appropriate error // code and sets |error_details|. static QuicErrorCode ValidateClientHelloVersion( - QuicVersionLabel client_version, - ParsedQuicVersion connection_version, + QuicVersionLabel client_version, ParsedQuicVersion connection_version, const ParsedQuicVersionVector& supported_versions, std::string* error_details);
diff --git a/quic/core/crypto/crypto_utils_test.cc b/quic/core/crypto/crypto_utils_test.cc index 251f136..df1546a 100644 --- a/quic/core/crypto/crypto_utils_test.cc +++ b/quic/core/crypto/crypto_utils_test.cc
@@ -8,6 +8,7 @@ #include "absl/base/macros.h" #include "absl/strings/escaping.h" +#include "absl/strings/string_view.h" #include "quic/core/quic_utils.h" #include "quic/platform/api/quic_test.h" #include "quic/test_tools/quic_test_utils.h" @@ -165,6 +166,48 @@ EXPECT_FALSE(error_details.empty()); } +// Test that the library is using the correct labels for each version, and +// therefore generating correct obfuscators, using the test vectors in appendix +// A of each RFC or internet-draft. +TEST_F(CryptoUtilsTest, ValidateCryptoLabels) { + // if the number of HTTP/3 QUIC versions has changed, we need to change the + // expected_keys hardcoded into this test. Regrettably, this is not a + // compile-time constant. + EXPECT_EQ(AllSupportedVersionsWithTls().size(), 3u); + const char draft_29_key[] = {// test vector from draft-ietf-quic-tls-29, A.1 + 0x14, 0x9d, 0x0b, 0x16, 0x62, 0xab, 0x87, 0x1f, + 0xbe, 0x63, 0xc4, 0x9b, 0x5e, 0x65, 0x5a, 0x5d}; + const char v1_key[] = {// test vector from RFC 9001, A.1 + 0xcf, 0x3a, 0x53, 0x31, 0x65, 0x3c, 0x36, 0x4c, + 0x88, 0xf0, 0xf3, 0x79, 0xb6, 0x06, 0x7e, 0x37}; + const char v2_01_key[] = {// test vector from draft-ietf-quic-v2-01 + 0x15, 0xd5, 0xb4, 0xd9, 0xa2, 0xb8, 0x91, 0x6a, + 0xa3, 0x9b, 0x1b, 0xfe, 0x57, 0x4d, 0x2a, 0xad}; + const char connection_id[] = // test vector from both docs + {0x83, 0x94, 0xc8, 0xf0, 0x3e, 0x51, 0x57, 0x08}; + const QuicConnectionId cid(connection_id, sizeof(connection_id)); + const char* key_str; + size_t key_size; + for (const ParsedQuicVersion& version : AllSupportedVersionsWithTls()) { + if (version == ParsedQuicVersion::Draft29()) { + key_str = draft_29_key; + key_size = sizeof(draft_29_key); + } else if (version == ParsedQuicVersion::RFCv1()) { + key_str = v1_key; + key_size = sizeof(v1_key); + } else { // draft-ietf-quic-v2-01 + key_str = v2_01_key; + key_size = sizeof(v2_01_key); + } + const absl::string_view expected_key{key_str, key_size}; + + CrypterPair crypters; + CryptoUtils::CreateInitialObfuscators(Perspective::IS_SERVER, version, cid, + &crypters); + EXPECT_EQ(crypters.encrypter->GetKey(), expected_key); + } +} + } // namespace } // namespace test } // namespace quic
diff --git a/quic/core/handshaker_delegate_interface.h b/quic/core/handshaker_delegate_interface.h index 1e47d16..7fbc5ae 100644 --- a/quic/core/handshaker_delegate_interface.h +++ b/quic/core/handshaker_delegate_interface.h
@@ -7,6 +7,7 @@ #include "quic/core/crypto/transport_parameters.h" #include "quic/core/quic_types.h" +#include "quic/core/quic_versions.h" namespace quic { @@ -21,15 +22,12 @@ // Called when new decryption key of |level| is available. Returns true if // decrypter is set successfully, otherwise, returns false. virtual bool OnNewDecryptionKeyAvailable( - EncryptionLevel level, - std::unique_ptr<QuicDecrypter> decrypter, - bool set_alternative_decrypter, - bool latch_once_used) = 0; + EncryptionLevel level, std::unique_ptr<QuicDecrypter> decrypter, + bool set_alternative_decrypter, bool latch_once_used) = 0; // Called when new encryption key of |level| is available. virtual void OnNewEncryptionKeyAvailable( - EncryptionLevel level, - std::unique_ptr<QuicEncrypter> encrypter) = 0; + EncryptionLevel level, std::unique_ptr<QuicEncrypter> encrypter) = 0; // Called to set default encryption level to |level|. Only used in QUIC // crypto. @@ -68,8 +66,7 @@ // On failure, returns a QuicErrorCode and saves a detailed error in // |error_details|. virtual QuicErrorCode ProcessTransportParameters( - const TransportParameters& params, - bool is_resumption, + const TransportParameters& params, bool is_resumption, std::string* error_details) = 0; // Called at the end of an handshake operation callback. @@ -77,6 +74,10 @@ // Whether a packet flusher is currently attached. virtual bool PacketFlusherAttached() const = 0; + + // Get the QUIC version currently in use. tls_handshaker needs this to pass + // to crypto_utils to apply version-dependent HKDF labels. + virtual ParsedQuicVersion parsed_version() const = 0; }; } // namespace quic
diff --git a/quic/core/http/end_to_end_test.cc b/quic/core/http/end_to_end_test.cc index aa1ef09..cf84969 100644 --- a/quic/core/http/end_to_end_test.cc +++ b/quic/core/http/end_to_end_test.cc
@@ -485,8 +485,7 @@ } } - void AddToCache(absl::string_view path, - int response_code, + void AddToCache(absl::string_view path, int response_code, absl::string_view body) { memory_cache_backend_.AddSimpleResponse(server_hostname_, path, response_code, body); @@ -657,16 +656,14 @@ } bool SendSynchronousRequestAndCheckResponse( - QuicTestClient* client, - const std::string& request, + QuicTestClient* client, const std::string& request, const std::string& expected_response) { std::string received_response = client->SendSynchronousRequest(request); return CheckResponse(client, received_response, expected_response); } bool SendSynchronousRequestAndCheckResponse( - const std::string& request, - const std::string& expected_response) { + const std::string& request, const std::string& expected_response) { return SendSynchronousRequestAndCheckResponse(client_.get(), request, expected_response); } @@ -844,8 +841,7 @@ }; // Run all end to end tests with all supported versions. -INSTANTIATE_TEST_SUITE_P(EndToEndTests, - EndToEndTest, +INSTANTIATE_TEST_SUITE_P(EndToEndTests, EndToEndTest, ::testing::ValuesIn(GetTestParams()), ::testing::PrintToStringParamName()); @@ -3210,8 +3206,7 @@ class DuplicatePacketWithSpoofedSelfAddressWriter : public QuicPacketWriterWrapper { public: - WriteResult WritePacket(const char* buffer, - size_t buf_len, + WriteResult WritePacket(const char* buffer, size_t buf_len, const QuicIpAddress& self_address, const QuicSocketAddress& peer_address, PerPacketOptions* options) override { @@ -4385,13 +4380,10 @@ class ServerStreamWithErrorResponseBody : public QuicSimpleServerStream { public: ServerStreamWithErrorResponseBody( - QuicStreamId id, - QuicSpdySession* session, + QuicStreamId id, QuicSpdySession* session, QuicSimpleServerBackend* quic_simple_server_backend, std::string response_body) - : QuicSimpleServerStream(id, - session, - BIDIRECTIONAL, + : QuicSimpleServerStream(id, session, BIDIRECTIONAL, quic_simple_server_backend), response_body_(std::move(response_body)) {} @@ -4420,8 +4412,7 @@ ~StreamWithErrorFactory() override = default; QuicSimpleServerStream* CreateStream( - QuicStreamId id, - QuicSpdySession* session, + QuicStreamId id, QuicSpdySession* session, QuicSimpleServerBackend* quic_simple_server_backend) override { return new ServerStreamWithErrorResponseBody( id, session, quic_simple_server_backend, response_body_); @@ -4434,12 +4425,9 @@ // A test server stream that drops all received body. class ServerStreamThatDropsBody : public QuicSimpleServerStream { public: - ServerStreamThatDropsBody(QuicStreamId id, - QuicSpdySession* session, + ServerStreamThatDropsBody(QuicStreamId id, QuicSpdySession* session, QuicSimpleServerBackend* quic_simple_server_backend) - : QuicSimpleServerStream(id, - session, - BIDIRECTIONAL, + : QuicSimpleServerStream(id, session, BIDIRECTIONAL, quic_simple_server_backend) {} ~ServerStreamThatDropsBody() override = default; @@ -4481,8 +4469,7 @@ ~ServerStreamThatDropsBodyFactory() override = default; QuicSimpleServerStream* CreateStream( - QuicStreamId id, - QuicSpdySession* session, + QuicStreamId id, QuicSpdySession* session, QuicSimpleServerBackend* quic_simple_server_backend) override { return new ServerStreamThatDropsBody(id, session, quic_simple_server_backend); @@ -4493,13 +4480,9 @@ class ServerStreamThatSendsHugeResponse : public QuicSimpleServerStream { public: ServerStreamThatSendsHugeResponse( - QuicStreamId id, - QuicSpdySession* session, - QuicSimpleServerBackend* quic_simple_server_backend, - int64_t body_bytes) - : QuicSimpleServerStream(id, - session, - BIDIRECTIONAL, + QuicStreamId id, QuicSpdySession* session, + QuicSimpleServerBackend* quic_simple_server_backend, int64_t body_bytes) + : QuicSimpleServerStream(id, session, BIDIRECTIONAL, quic_simple_server_backend), body_bytes_(body_bytes) {} @@ -4529,8 +4512,7 @@ ~ServerStreamThatSendsHugeResponseFactory() override = default; QuicSimpleServerStream* CreateStream( - QuicStreamId id, - QuicSpdySession* session, + QuicStreamId id, QuicSpdySession* session, QuicSimpleServerBackend* quic_simple_server_backend) override { return new ServerStreamThatSendsHugeResponse( id, session, quic_simple_server_backend, body_bytes_); @@ -5255,8 +5237,7 @@ // called. class PacketHoldingWriter : public QuicPacketWriterWrapper { public: - WriteResult WritePacket(const char* buffer, - size_t buf_len, + WriteResult WritePacket(const char* buffer, size_t buf_len, const QuicIpAddress& self_address, const QuicSocketAddress& peer_address, PerPacketOptions* options) override { @@ -5710,8 +5691,7 @@ : error_returned_(false), version_(version) {} ~BadShloPacketWriter() override {} - WriteResult WritePacket(const char* buffer, - size_t buf_len, + WriteResult WritePacket(const char* buffer, size_t buf_len, const QuicIpAddress& self_address, const QuicSocketAddress& peer_address, quic::PerPacketOptions* options) override { @@ -5728,6 +5708,9 @@ } bool TypeByteIsServerHello(uint8_t type_byte) { + if (version_.UsesV2PacketTypes()) { + return ((type_byte & 0x30) >> 4) == 3; + } if (version_.UsesQuicCrypto()) { // ENCRYPTION_ZERO_RTT packet. return ((type_byte & 0x30) >> 4) == 1; @@ -5784,21 +5767,23 @@ class BadShloPacketWriter2 : public QuicPacketWriterWrapper { public: - BadShloPacketWriter2() : error_returned_(false) {} + BadShloPacketWriter2(ParsedQuicVersion version) + : error_returned_(false), version_(version) {} ~BadShloPacketWriter2() override {} - WriteResult WritePacket(const char* buffer, - size_t buf_len, + WriteResult WritePacket(const char* buffer, size_t buf_len, const QuicIpAddress& self_address, const QuicSocketAddress& peer_address, quic::PerPacketOptions* options) override { const uint8_t type_byte = buffer[0]; - if ((type_byte & FLAGS_LONG_HEADER) && - (((type_byte & 0x30) >> 4) == 1 || (type_byte & 0x7F) == 0x7C)) { - QUIC_DVLOG(1) << "Dropping ZERO_RTT_PACKET packet"; - return WriteResult(WRITE_STATUS_OK, buf_len); - } - if (!error_returned_ && !(type_byte & FLAGS_LONG_HEADER)) { + + if (type_byte & FLAGS_LONG_HEADER) { + if (((type_byte & 0x30 >> 4) == (version_.UsesV2PacketTypes() ? 2 : 1)) || + ((type_byte & 0x7F) == 0x7C)) { + QUIC_DVLOG(1) << "Dropping ZERO_RTT_PACKET packet"; + return WriteResult(WRITE_STATUS_OK, buf_len); + } + } else if (!error_returned_) { QUIC_DVLOG(1) << "Return write error for short header packet"; error_returned_ = true; return WriteResult(WRITE_STATUS_ERROR, QUIC_EMSGSIZE); @@ -5809,6 +5794,7 @@ private: bool error_returned_; + ParsedQuicVersion version_; }; TEST_P(EndToEndTest, ForwardSecureConnectionClose) { @@ -5839,7 +5825,7 @@ dispatcher, // This causes the all server sent ZERO_RTT_PROTECTED packets to be // dropped, and first short header packet causes write error. - new BadShloPacketWriter2()); + new BadShloPacketWriter2(version_)); server_thread_->Resume(); client_.reset(CreateQuicClient(client_writer_)); EXPECT_EQ("", client_->SendSynchronousRequest("/foo")); @@ -6028,8 +6014,7 @@ public: explicit CopyingPacketWriter(int num_packets_to_copy) : num_packets_to_copy_(num_packets_to_copy) {} - WriteResult WritePacket(const char* buffer, - size_t buf_len, + WriteResult WritePacket(const char* buffer, size_t buf_len, const QuicIpAddress& self_address, const QuicSocketAddress& peer_address, PerPacketOptions* options) override {
diff --git a/quic/core/quic_connection_test.cc b/quic/core/quic_connection_test.cc index 393bfd8..053849f 100644 --- a/quic/core/quic_connection_test.cc +++ b/quic/core/quic_connection_test.cc
@@ -184,19 +184,12 @@ TestConnection(QuicConnectionId connection_id, QuicSocketAddress initial_self_address, QuicSocketAddress initial_peer_address, - TestConnectionHelper* helper, - TestAlarmFactory* alarm_factory, - TestPacketWriter* writer, - Perspective perspective, + TestConnectionHelper* helper, TestAlarmFactory* alarm_factory, + TestPacketWriter* writer, Perspective perspective, ParsedQuicVersion version) - : QuicConnection(connection_id, - initial_self_address, - initial_peer_address, - helper, - alarm_factory, - writer, - /* owns_writer= */ false, - perspective, + : QuicConnection(connection_id, initial_self_address, + initial_peer_address, helper, alarm_factory, writer, + /* owns_writer= */ false, perspective, SupportedVersions(version)), notifier_(nullptr) { writer->set_perspective(perspective); @@ -215,11 +208,9 @@ QuicConnectionPeer::SetLossAlgorithm(this, loss_algorithm); } - void SendPacket(EncryptionLevel /*level*/, - uint64_t packet_number, + void SendPacket(EncryptionLevel /*level*/, uint64_t packet_number, std::unique_ptr<QuicPacket> packet, - HasRetransmittableData retransmittable, - bool has_ack, + HasRetransmittableData retransmittable, bool has_ack, bool has_pending_frames) { ScopedPacketFlusher flusher(this); char buffer[kMaxOutgoingPacketSize]; @@ -239,8 +230,7 @@ } QuicConsumedData SaveAndSendStreamData(QuicStreamId id, - const struct iovec* iov, - int iov_count, + const struct iovec* iov, int iov_count, size_t total_length, QuicStreamOffset offset, StreamSendingState state) { @@ -555,8 +545,7 @@ // Run tests with combinations of {ParsedQuicVersion, AckResponse}. struct TestParams { - TestParams(ParsedQuicVersion version, - AckResponse ack_response, + TestParams(ParsedQuicVersion version, AckResponse ack_response, bool no_stop_waiting) : version(version), ack_response(ack_response), @@ -609,30 +598,20 @@ protected: QuicConnectionTest() : connection_id_(TestConnectionId()), - framer_(SupportedVersions(version()), - QuicTime::Zero(), - Perspective::IS_CLIENT, - connection_id_.length()), + framer_(SupportedVersions(version()), QuicTime::Zero(), + Perspective::IS_CLIENT, connection_id_.length()), send_algorithm_(new StrictMock<MockSendAlgorithm>), loss_algorithm_(new MockLossAlgorithm()), helper_(new TestConnectionHelper(&clock_, &random_generator_)), alarm_factory_(new TestAlarmFactory()), - peer_framer_(SupportedVersions(version()), - QuicTime::Zero(), - Perspective::IS_SERVER, - connection_id_.length()), - peer_creator_(connection_id_, - &peer_framer_, + peer_framer_(SupportedVersions(version()), QuicTime::Zero(), + Perspective::IS_SERVER, connection_id_.length()), + peer_creator_(connection_id_, &peer_framer_, /*delegate=*/nullptr), writer_( new TestPacketWriter(version(), &clock_, Perspective::IS_CLIENT)), - connection_(connection_id_, - kSelfAddress, - kPeerAddress, - helper_.get(), - alarm_factory_.get(), - writer_.get(), - Perspective::IS_CLIENT, + connection_(connection_id_, kSelfAddress, kPeerAddress, helper_.get(), + alarm_factory_.get(), writer_.get(), Perspective::IS_CLIENT, version()), creator_(QuicConnectionPeer::GetPacketCreator(&connection_)), manager_(QuicConnectionPeer::GetSentPacketManager(&connection_)), @@ -872,16 +851,14 @@ QuicReceivedPacket(encrypted_buffer, encrypted_length, clock_.Now())); } - size_t ProcessFramePacketAtLevel(uint64_t number, - QuicFrame frame, + size_t ProcessFramePacketAtLevel(uint64_t number, QuicFrame frame, EncryptionLevel level) { QuicFrames frames; frames.push_back(frame); return ProcessFramesPacketAtLevel(number, frames, level); } - size_t ProcessFramesPacketAtLevel(uint64_t number, - const QuicFrames& frames, + size_t ProcessFramesPacketAtLevel(uint64_t number, const QuicFrames& frames, EncryptionLevel level) { QuicPacketHeader header = ConstructPacketHeader(number, level); // Set the correct encryption level and encrypter on peer_creator and @@ -1025,8 +1002,7 @@ return encrypted_length; } - size_t ProcessDataPacketAtLevel(uint64_t number, - bool has_stop_waiting, + size_t ProcessDataPacketAtLevel(uint64_t number, bool has_stop_waiting, EncryptionLevel level) { std::unique_ptr<QuicPacket> packet( ConstructDataPacket(number, has_stop_waiting, level)); @@ -1055,8 +1031,7 @@ QuicReceivedPacket(buffer, encrypted_length, QuicTime::Zero(), false)); } - QuicByteCount SendStreamDataToPeer(QuicStreamId id, - absl::string_view data, + QuicByteCount SendStreamDataToPeer(QuicStreamId id, absl::string_view data, QuicStreamOffset offset, StreamSendingState state, QuicPacketNumber* last_packet) { @@ -1084,8 +1059,7 @@ .Times(AnyNumber()); } - void SendRstStream(QuicStreamId id, - QuicRstStreamErrorCode error, + void SendRstStream(QuicStreamId id, QuicRstStreamErrorCode error, QuicStreamOffset bytes_written) { notifier_.WriteOrBufferRstStream(id, error, bytes_written); connection_.OnStreamReset(id, error); @@ -10499,7 +10473,12 @@ return; } - // These values come from draft-ietf-quic-tls Appendix A.4. + // These values come from draft-ietf-quic-v2 Appendix A.4. + uint8_t retry_packet_rfcv2[] = { + 0xcf, 0x70, 0x9a, 0x50, 0xc4, 0x00, 0x08, 0xf0, 0x67, 0xa5, 0x50, 0x2a, + 0x42, 0x62, 0xb5, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x1d, 0xc7, 0x11, 0x30, + 0xcd, 0x1e, 0xd3, 0x9d, 0x6e, 0xfc, 0xee, 0x5c, 0x85, 0x80, 0x65, 0x01}; + // These values come from RFC9001 Appendix A.4. uint8_t retry_packet_rfcv1[] = { 0xff, 0x00, 0x00, 0x00, 0x01, 0x00, 0x08, 0xf0, 0x67, 0xa5, 0x50, 0x2a, 0x42, 0x62, 0xb5, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x04, 0xa2, 0x65, 0xba, @@ -10511,7 +10490,10 @@ uint8_t* retry_packet; size_t retry_packet_length; - if (version() == ParsedQuicVersion::RFCv1()) { + if (version() == ParsedQuicVersion::V2Draft01()) { + retry_packet = retry_packet_rfcv2; + retry_packet_length = ABSL_ARRAYSIZE(retry_packet_rfcv2); + } else if (version() == ParsedQuicVersion::RFCv1()) { retry_packet = retry_packet_rfcv1; retry_packet_length = ABSL_ARRAYSIZE(retry_packet_rfcv1); } else if (version() == ParsedQuicVersion::Draft29()) {
diff --git a/quic/core/quic_dispatcher_test.cc b/quic/core/quic_dispatcher_test.cc index ca4ae48..add5164 100644 --- a/quic/core/quic_dispatcher_test.cc +++ b/quic/core/quic_dispatcher_test.cc
@@ -1521,7 +1521,7 @@ dispatcher_->ProcessPacket(server_address_, client_address, received_packet); } -static_assert(quic::SupportedVersions().size() == 5u, +static_assert(quic::SupportedVersions().size() == 6u, "Please add new RejectDeprecatedVersion tests above this assert " "when deprecating versions");
diff --git a/quic/core/quic_flags_list.h b/quic/core/quic_flags_list.h index 7482050..90e3fbd 100644 --- a/quic/core/quic_flags_list.h +++ b/quic/core/quic_flags_list.h
@@ -135,6 +135,8 @@ QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_fix_pacing_sender_bursts, false) // When true, set the initial congestion control window from connection options in QuicSentPacketManager rather than TcpCubicSenderBytes. QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_unified_iw_options, true) +// When true, support draft-ietf-quic-v2-01 +QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_enable_version_2_draft_01, false) // When true, the B203 connection option causes the Bbr2Sender to ignore inflight_hi during PROBE_UP and increase it when the bytes delivered without loss are higher. QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_bbr2_ignore_inflight_hi_in_probe_up, true) // When true, the B205 connection option enables extra acked in STARTUP, and B204 adds new logic to decrease it whenever max bandwidth increases.
diff --git a/quic/core/quic_framer.cc b/quic/core/quic_framer.cc index 79ace5a..6d2d9c7 100644 --- a/quic/core/quic_framer.cc +++ b/quic/core/quic_framer.cc
@@ -170,8 +170,7 @@ } } -QuicPacketNumberLength ReadAckPacketNumberLength( - uint8_t flags) { +QuicPacketNumberLength ReadAckPacketNumberLength(uint8_t flags) { switch (flags & PACKET_FLAGS_8BYTE_PACKET) { case PACKET_FLAGS_8BYTE_PACKET: return PACKET_6BYTE_PACKET_NUMBER; @@ -197,16 +196,17 @@ return static_cast<QuicPacketNumberLength>((type & 0x03) + 1); } -uint8_t LongHeaderTypeToOnWireValue(QuicLongHeaderType type) { +uint8_t LongHeaderTypeToOnWireValue(QuicLongHeaderType type, + const ParsedQuicVersion& version) { switch (type) { case INITIAL: - return 0; + return version.UsesV2PacketTypes() ? (1 << 4) : 0; case ZERO_RTT_PROTECTED: - return 1 << 4; + return version.UsesV2PacketTypes() ? (2 << 4) : (1 << 4); case HANDSHAKE: - return 2 << 4; + return version.UsesV2PacketTypes() ? (3 << 4) : (2 << 4); case RETRY: - return 3 << 4; + return version.UsesV2PacketTypes() ? 0 : (3 << 4); case VERSION_NEGOTIATION: return 0xF0; // Value does not matter default: @@ -215,20 +215,23 @@ } } -bool GetLongHeaderType(uint8_t type, QuicLongHeaderType* long_header_type) { +bool GetLongHeaderType(uint8_t type, const ParsedQuicVersion& version, + QuicLongHeaderType* long_header_type) { QUICHE_DCHECK((type & FLAGS_LONG_HEADER)); switch ((type & 0x30) >> 4) { case 0: - *long_header_type = INITIAL; + *long_header_type = version.UsesV2PacketTypes() ? RETRY : INITIAL; break; case 1: - *long_header_type = ZERO_RTT_PROTECTED; + *long_header_type = + version.UsesV2PacketTypes() ? INITIAL : ZERO_RTT_PROTECTED; break; case 2: - *long_header_type = HANDSHAKE; + *long_header_type = + version.UsesV2PacketTypes() ? ZERO_RTT_PROTECTED : HANDSHAKE; break; case 3: - *long_header_type = RETRY; + *long_header_type = version.UsesV2PacketTypes() ? HANDSHAKE : RETRY; break; default: QUIC_BUG(quic_bug_10850_4) << "Unreachable statement"; @@ -331,8 +334,7 @@ return full_packet_number > 0 || version.HasIetfQuicFrames(); } -bool AppendIetfConnectionIds(bool version_flag, - bool use_length_prefix, +bool AppendIetfConnectionIds(bool version_flag, bool use_length_prefix, QuicConnectionId destination_connection_id, QuicConnectionId source_connection_id, QuicDataWriter* writer) { @@ -533,8 +535,7 @@ // static size_t QuicFramer::GetConnectionCloseFrameSize( - QuicTransportVersion version, - const QuicConnectionCloseFrame& frame) { + QuicTransportVersion version, const QuicConnectionCloseFrame& frame) { if (!VersionHasIetfQuicFrames(version)) { // Not IETF QUIC, return Google QUIC CONNECTION CLOSE frame size. return kQuicFrameTypeSize + kQuicErrorCodeSize + @@ -569,8 +570,7 @@ // static size_t QuicFramer::GetWindowUpdateFrameSize( - QuicTransportVersion version, - const QuicWindowUpdateFrame& frame) { + QuicTransportVersion version, const QuicWindowUpdateFrame& frame) { if (!VersionHasIetfQuicFrames(version)) { return kQuicFrameTypeSize + kQuicMaxStreamIdSize + kQuicMaxStreamOffsetSize; } @@ -599,8 +599,7 @@ // static size_t QuicFramer::GetStreamsBlockedFrameSize( - QuicTransportVersion version, - const QuicStreamsBlockedFrame& frame) { + QuicTransportVersion version, const QuicStreamsBlockedFrame& frame) { if (!VersionHasIetfQuicFrames(version)) { QUIC_BUG(quic_bug_10850_10) << "In version " << version @@ -658,8 +657,7 @@ // static size_t QuicFramer::GetRetransmittableControlFrameSize( - QuicTransportVersion version, - const QuicFrame& frame) { + QuicTransportVersion version, const QuicFrame& frame) { switch (frame.type) { case PING_FRAME: // Ping has no payload. @@ -793,11 +791,8 @@ } size_t QuicFramer::GetSerializedFrameLength( - const QuicFrame& frame, - size_t free_bytes, - bool first_frame, - bool last_frame, - QuicPacketNumberLength packet_number_length) { + const QuicFrame& frame, size_t free_bytes, bool first_frame, + bool last_frame, QuicPacketNumberLength packet_number_length) { // Prevent a rare crash reported in b/19458523. if (frame.type == ACK_FRAME && frame.ack_frame == nullptr) { QUIC_BUG(quic_bug_10850_13) @@ -887,8 +882,7 @@ } size_t QuicFramer::BuildDataPacket(const QuicPacketHeader& header, - const QuicFrames& frames, - char* buffer, + const QuicFrames& frames, char* buffer, size_t packet_length, EncryptionLevel level) { QUIC_BUG_IF(quic_bug_12975_2, @@ -1345,10 +1339,8 @@ // static std::unique_ptr<QuicEncryptedPacket> QuicFramer::BuildVersionNegotiationPacket( QuicConnectionId server_connection_id, - QuicConnectionId client_connection_id, - bool ietf_quic, - bool use_length_prefix, - const ParsedQuicVersionVector& versions) { + QuicConnectionId client_connection_id, bool ietf_quic, + bool use_length_prefix, const ParsedQuicVersionVector& versions) { QUIC_CODE_COUNT(quic_build_version_negotiation); if (use_length_prefix) { QUICHE_DCHECK(ietf_quic); @@ -1420,8 +1412,7 @@ // static std::unique_ptr<QuicEncryptedPacket> QuicFramer::BuildIetfVersionNegotiationPacket( - bool use_length_prefix, - QuicConnectionId server_connection_id, + bool use_length_prefix, QuicConnectionId server_connection_id, QuicConnectionId client_connection_id, const ParsedQuicVersionVector& versions) { QUIC_DVLOG(1) << "Building IETF version negotiation packet with" @@ -1566,8 +1557,7 @@ } bool QuicFramer::ProcessVersionNegotiationPacket( - QuicDataReader* reader, - const QuicPacketHeader& header) { + QuicDataReader* reader, const QuicPacketHeader& header) { QUICHE_DCHECK_EQ(Perspective::IS_CLIENT, perspective_); QuicVersionNegotiationPacket packet( @@ -1667,8 +1657,7 @@ // If the IETF length field only spans part of the outer packet, // then there is a coalesced packet after this one. void QuicFramer::MaybeProcessCoalescedPacket( - const QuicDataReader& encrypted_reader, - uint64_t remaining_bytes_length, + const QuicDataReader& encrypted_reader, uint64_t remaining_bytes_length, const QuicPacketHeader& header) { if (header.remaining_packet_length >= remaining_bytes_length) { // There is no coalesced packet. @@ -2221,7 +2210,7 @@ if (header.version_flag) { type = static_cast<uint8_t>( FLAGS_LONG_HEADER | FLAGS_FIXED_BIT | - LongHeaderTypeToOnWireValue(header.long_packet_type) | + LongHeaderTypeToOnWireValue(header.long_packet_type, version_) | PacketNumberLengthToOnWireValue(header.packet_number_length)); } else { type = static_cast<uint8_t>( @@ -2357,8 +2346,7 @@ uint64_t QuicFramer::CalculatePacketNumberFromWire( QuicPacketNumberLength packet_number_length, - QuicPacketNumber base_packet_number, - uint64_t packet_number) const { + QuicPacketNumber base_packet_number, uint64_t packet_number) const { // The new packet number might have wrapped to the next epoch, or // it might have reverse wrapped to the previous epoch, or it might // remain in the same epoch. Select the packet number closest to the @@ -2632,7 +2620,8 @@ set_detailed_error("Fixed bit is 0 in long header."); return false; } - if (!GetLongHeaderType(type, &header->long_packet_type)) { + if (!GetLongHeaderType(type, header->version, + &header->long_packet_type)) { set_detailed_error("Illegal long header type value."); return false; } @@ -2690,14 +2679,11 @@ // static bool QuicFramer::ProcessAndValidateIetfConnectionIdLength( - QuicDataReader* reader, - ParsedQuicVersion version, - Perspective perspective, + QuicDataReader* reader, ParsedQuicVersion version, Perspective perspective, bool should_update_expected_server_connection_id_length, uint8_t* expected_server_connection_id_length, uint8_t* destination_connection_id_length, - uint8_t* source_connection_id_length, - std::string* detailed_error) { + uint8_t* source_connection_id_length, std::string* detailed_error) { uint8_t connection_id_lengths_byte; if (!reader->ReadBytes(&connection_id_lengths_byte, 1)) { *detailed_error = "Unable to read ConnectionId length."; @@ -2880,10 +2866,8 @@ } bool QuicFramer::ProcessAndCalculatePacketNumber( - QuicDataReader* reader, - QuicPacketNumberLength packet_number_length, - QuicPacketNumber base_packet_number, - uint64_t* packet_number) { + QuicDataReader* reader, QuicPacketNumberLength packet_number_length, + QuicPacketNumber base_packet_number, uint64_t* packet_number) { uint64_t wire_packet_number; if (!reader->ReadBytesToUInt64(packet_number_length, &wire_packet_number)) { return false; @@ -3131,8 +3115,7 @@ // static bool QuicFramer::IsIetfFrameTypeExpectedForEncryptionLevel( - uint64_t frame_type, - EncryptionLevel level) { + uint64_t frame_type, EncryptionLevel level) { switch (level) { case ENCRYPTION_INITIAL: case ENCRYPTION_HANDSHAKE: @@ -3560,8 +3543,7 @@ } } // namespace -bool QuicFramer::ProcessStreamFrame(QuicDataReader* reader, - uint8_t frame_type, +bool QuicFramer::ProcessStreamFrame(QuicDataReader* reader, uint8_t frame_type, QuicStreamFrame* frame) { uint8_t stream_flags = frame_type; @@ -3748,12 +3730,12 @@ // Determine the two lengths from the frame type: largest acked length, // ack block length. - const QuicPacketNumberLength ack_block_length = ReadAckPacketNumberLength( - ExtractBits(frame_type, kQuicSequenceNumberLengthNumBits, - kActBlockLengthOffset)); - const QuicPacketNumberLength largest_acked_length = ReadAckPacketNumberLength( - ExtractBits(frame_type, kQuicSequenceNumberLengthNumBits, - kLargestAckedOffset)); + const QuicPacketNumberLength ack_block_length = + ReadAckPacketNumberLength(ExtractBits( + frame_type, kQuicSequenceNumberLengthNumBits, kActBlockLengthOffset)); + const QuicPacketNumberLength largest_acked_length = + ReadAckPacketNumberLength(ExtractBits( + frame_type, kQuicSequenceNumberLengthNumBits, kLargestAckedOffset)); uint64_t largest_acked; if (!reader->ReadBytesToUInt64(largest_acked_length, &largest_acked)) { @@ -4364,11 +4346,9 @@ // static absl::string_view QuicFramer::GetAssociatedDataFromEncryptedPacket( - QuicTransportVersion version, - const QuicEncryptedPacket& encrypted, + QuicTransportVersion version, const QuicEncryptedPacket& encrypted, QuicConnectionIdLength destination_connection_id_length, - QuicConnectionIdLength source_connection_id_length, - bool includes_version, + QuicConnectionIdLength source_connection_id_length, bool includes_version, bool includes_diversification_nonce, QuicPacketNumberLength packet_number_length, QuicVariableLengthIntegerLength retry_token_length_length, @@ -4397,8 +4377,7 @@ } void QuicFramer::SetAlternativeDecrypter( - EncryptionLevel level, - std::unique_ptr<QuicDecrypter> decrypter, + EncryptionLevel level, std::unique_ptr<QuicDecrypter> decrypter, bool latch_once_used) { QUICHE_DCHECK_NE(level, decrypter_level_); QUICHE_DCHECK(!version_.KnowsWhichDecrypterToUse()); @@ -4523,10 +4502,8 @@ } size_t QuicFramer::EncryptInPlace(EncryptionLevel level, - QuicPacketNumber packet_number, - size_t ad_len, - size_t total_len, - size_t buffer_len, + QuicPacketNumber packet_number, size_t ad_len, + size_t total_len, size_t buffer_len, char* buffer) { QUICHE_DCHECK(packet_number.IsInitialized()); if (encrypter_[level] == nullptr) { @@ -4568,10 +4545,8 @@ } // namespace -bool QuicFramer::ApplyHeaderProtection(EncryptionLevel level, - char* buffer, - size_t buffer_len, - size_t ad_len) { +bool QuicFramer::ApplyHeaderProtection(EncryptionLevel level, char* buffer, + size_t buffer_len, size_t ad_len) { QuicDataReader buffer_reader(buffer, buffer_len); QuicDataWriter buffer_writer(buffer_len, buffer); // The sample starts 4 bytes after the start of the packet number. @@ -4615,7 +4590,7 @@ QuicLongHeaderType header_type; if (IsLongHeader(type_byte)) { bitmask = 0x0f; - if (!GetLongHeaderType(type_byte, &header_type)) { + if (!GetLongHeaderType(type_byte, version_, &header_type)) { return false; } } @@ -4781,8 +4756,7 @@ size_t QuicFramer::EncryptPayload(EncryptionLevel level, QuicPacketNumber packet_number, - const QuicPacket& packet, - char* buffer, + const QuicPacket& packet, char* buffer, size_t buffer_len) { QUICHE_DCHECK(packet_number.IsInitialized()); if (encrypter_[level] == nullptr) { @@ -4867,8 +4841,7 @@ absl::string_view encrypted, absl::string_view associated_data, const QuicPacketHeader& header, - char* decrypted_buffer, - size_t buffer_length, + char* decrypted_buffer, size_t buffer_length, size_t* decrypted_length, EncryptionLevel* decrypted_level) { if (!EncryptionLevelIsValid(decrypter_level_)) { @@ -5100,8 +5073,7 @@ } size_t QuicFramer::GetAckFrameSize( - const QuicAckFrame& ack, - QuicPacketNumberLength /*packet_number_length*/) { + const QuicAckFrame& ack, QuicPacketNumberLength /*packet_number_length*/) { QUICHE_DCHECK(!ack.packets.Empty()); size_t ack_size = 0; @@ -5141,8 +5113,7 @@ } size_t QuicFramer::ComputeFrameLength( - const QuicFrame& frame, - bool last_frame_in_packet, + const QuicFrame& frame, bool last_frame_in_packet, QuicPacketNumberLength packet_number_length) { switch (frame.type) { case STREAM_FRAME: @@ -5370,8 +5341,7 @@ } // static -bool QuicFramer::AppendStreamId(size_t stream_id_length, - QuicStreamId stream_id, +bool QuicFramer::AppendStreamId(size_t stream_id_length, QuicStreamId stream_id, QuicDataWriter* writer) { if (stream_id_length == 0 || stream_id_length > 4) { QUIC_BUG(quic_bug_10850_77) @@ -5397,8 +5367,7 @@ // static bool QuicFramer::AppendAckBlock(uint8_t gap, QuicPacketNumberLength length_length, - uint64_t length, - QuicDataWriter* writer) { + uint64_t length, QuicDataWriter* writer) { if (length == 0) { if (!IsValidPacketNumberLength(length_length)) { QUIC_BUG(quic_bug_10850_79) @@ -5976,8 +5945,7 @@ } bool QuicFramer::AppendConnectionCloseFrame( - const QuicConnectionCloseFrame& frame, - QuicDataWriter* writer) { + const QuicConnectionCloseFrame& frame, QuicDataWriter* writer) { if (VersionHasIetfQuicFrames(version_.transport_version)) { return AppendIetfConnectionCloseFrame(frame, writer); } @@ -6084,8 +6052,7 @@ } bool QuicFramer::IsVersionNegotiation( - const QuicPacketHeader& header, - bool packet_has_ietf_packet_header) const { + const QuicPacketHeader& header, bool packet_has_ietf_packet_header) const { if (!packet_has_ietf_packet_header && perspective_ == Perspective::IS_CLIENT) { return header.version_flag; @@ -6097,8 +6064,7 @@ } bool QuicFramer::AppendIetfConnectionCloseFrame( - const QuicConnectionCloseFrame& frame, - QuicDataWriter* writer) { + const QuicConnectionCloseFrame& frame, QuicDataWriter* writer) { if (frame.close_type != IETF_QUIC_TRANSPORT_CONNECTION_CLOSE && frame.close_type != IETF_QUIC_APPLICATION_CONNECTION_CLOSE) { QUIC_BUG(quic_bug_10850_90) @@ -6135,8 +6101,7 @@ } bool QuicFramer::ProcessIetfConnectionCloseFrame( - QuicDataReader* reader, - QuicConnectionCloseType type, + QuicDataReader* reader, QuicConnectionCloseType type, QuicConnectionCloseFrame* frame) { frame->close_type = type; @@ -6263,8 +6228,7 @@ } bool QuicFramer::ProcessStopSendingFrame( - QuicDataReader* reader, - QuicStopSendingFrame* stop_sending_frame) { + QuicDataReader* reader, QuicStopSendingFrame* stop_sending_frame) { if (!ReadUint32FromVarint62(reader, IETF_STOP_SENDING, &stop_sending_frame->stream_id)) { return false; @@ -6281,8 +6245,7 @@ } bool QuicFramer::AppendStopSendingFrame( - const QuicStopSendingFrame& stop_sending_frame, - QuicDataWriter* writer) { + const QuicStopSendingFrame& stop_sending_frame, QuicDataWriter* writer) { if (!writer->WriteVarInt62(stop_sending_frame.stream_id)) { set_detailed_error("Can not write stop sending stream id"); return false; @@ -6438,8 +6401,7 @@ } bool QuicFramer::AppendNewConnectionIdFrame( - const QuicNewConnectionIdFrame& frame, - QuicDataWriter* writer) { + const QuicNewConnectionIdFrame& frame, QuicDataWriter* writer) { if (!writer->WriteVarInt62(frame.sequence_number)) { set_detailed_error("Can not write New Connection ID sequence number"); return false; @@ -6500,8 +6462,7 @@ } bool QuicFramer::AppendRetireConnectionIdFrame( - const QuicRetireConnectionIdFrame& frame, - QuicDataWriter* writer) { + const QuicRetireConnectionIdFrame& frame, QuicDataWriter* writer) { if (!writer->WriteVarInt62(frame.sequence_number)) { set_detailed_error("Can not write Retire Connection ID sequence number"); return false; @@ -6510,8 +6471,7 @@ } bool QuicFramer::ProcessRetireConnectionIdFrame( - QuicDataReader* reader, - QuicRetireConnectionIdFrame* frame) { + QuicDataReader* reader, QuicRetireConnectionIdFrame* frame) { if (!reader->ReadVarInt62(&frame->sequence_number)) { set_detailed_error( "Unable to read retire connection ID frame sequence number."); @@ -6567,8 +6527,7 @@ } uint8_t QuicFramer::GetIetfStreamFrameTypeByte( - const QuicStreamFrame& frame, - bool last_frame_in_packet) const { + const QuicStreamFrame& frame, bool last_frame_in_packet) const { QUICHE_DCHECK(VersionHasIetfQuicFrames(version_.transport_version)); uint8_t type_byte = IETF_STREAM; if (!last_frame_in_packet) { @@ -6662,14 +6621,10 @@ // static QuicErrorCode QuicFramer::ParsePublicHeaderGoogleQuic( - QuicDataReader* reader, - uint8_t* first_byte, - PacketHeaderFormat* format, - bool* version_present, - QuicVersionLabel* version_label, + QuicDataReader* reader, uint8_t* first_byte, PacketHeaderFormat* format, + bool* version_present, QuicVersionLabel* version_label, ParsedQuicVersion* parsed_version, - QuicConnectionId* destination_connection_id, - std::string* detailed_error) { + QuicConnectionId* destination_connection_id, std::string* detailed_error) { *format = GOOGLE_QUIC_PACKET; *version_present = (*first_byte & PACKET_PUBLIC_FLAGS_VERSION) != 0; uint8_t destination_connection_id_length = 0; @@ -6696,10 +6651,8 @@ const QuicVersionLabel kProxVersionLabel = 0x50524F58; // "PROX" inline bool PacketHasLengthPrefixedConnectionIds( - const QuicDataReader& reader, - ParsedQuicVersion parsed_version, - QuicVersionLabel version_label, - uint8_t first_byte) { + const QuicDataReader& reader, ParsedQuicVersion parsed_version, + QuicVersionLabel version_label, uint8_t first_byte) { if (parsed_version.IsKnown()) { return parsed_version.HasLengthPrefixedConnectionIds(); } @@ -6733,12 +6686,9 @@ } inline bool ParseLongHeaderConnectionIds( - QuicDataReader* reader, - bool has_length_prefix, - QuicVersionLabel version_label, - QuicConnectionId* destination_connection_id, - QuicConnectionId* source_connection_id, - std::string* detailed_error) { + QuicDataReader* reader, bool has_length_prefix, + QuicVersionLabel version_label, QuicConnectionId* destination_connection_id, + QuicConnectionId* source_connection_id, std::string* detailed_error) { if (has_length_prefix) { if (!reader->ReadLengthPrefixedConnectionId(destination_connection_id)) { *detailed_error = "Unable to read destination connection ID."; @@ -6795,21 +6745,15 @@ // static QuicErrorCode QuicFramer::ParsePublicHeader( - QuicDataReader* reader, - uint8_t expected_destination_connection_id_length, - bool ietf_format, - uint8_t* first_byte, - PacketHeaderFormat* format, - bool* version_present, - bool* has_length_prefix, - QuicVersionLabel* version_label, - ParsedQuicVersion* parsed_version, + QuicDataReader* reader, uint8_t expected_destination_connection_id_length, + bool ietf_format, uint8_t* first_byte, PacketHeaderFormat* format, + bool* version_present, bool* has_length_prefix, + QuicVersionLabel* version_label, ParsedQuicVersion* parsed_version, QuicConnectionId* destination_connection_id, QuicConnectionId* source_connection_id, QuicLongHeaderType* long_packet_type, QuicVariableLengthIntegerLength* retry_token_length_length, - absl::string_view* retry_token, - std::string* detailed_error) { + absl::string_view* retry_token, std::string* detailed_error) { *version_present = false; *has_length_prefix = false; *version_label = 0; @@ -6875,7 +6819,7 @@ } // Parse long packet type. - if (!GetLongHeaderType(*first_byte, long_packet_type)) { + if (!GetLongHeaderType(*first_byte, *parsed_version, long_packet_type)) { *detailed_error = "Unable to parse long packet type."; return QUIC_INVALID_PACKET_HEADER; } @@ -6903,8 +6847,7 @@ // static bool QuicFramer::WriteClientVersionNegotiationProbePacket( - char* packet_bytes, - QuicByteCount packet_length, + char* packet_bytes, QuicByteCount packet_length, const char* destination_connection_id_bytes, uint8_t destination_connection_id_length) { if (packet_bytes == nullptr) { @@ -6981,10 +6924,8 @@ // static bool QuicFramer::ParseServerVersionNegotiationProbeResponse( - const char* packet_bytes, - QuicByteCount packet_length, - char* source_connection_id_bytes, - uint8_t* source_connection_id_length_out, + const char* packet_bytes, QuicByteCount packet_length, + char* source_connection_id_bytes, uint8_t* source_connection_id_length_out, std::string* detailed_error) { if (detailed_error == nullptr) { QUIC_BUG(quic_bug_10850_101) << "Invalid error_details";
diff --git a/quic/core/quic_framer_test.cc b/quic/core/quic_framer_test.cc index 28b7c20..207329c 100644 --- a/quic/core/quic_framer_test.cc +++ b/quic/core/quic_framer_test.cc
@@ -105,10 +105,8 @@ bool SetHeaderProtectionKey(absl::string_view /*key*/) override { return true; } - bool EncryptPacket(uint64_t packet_number, - absl::string_view associated_data, - absl::string_view plaintext, - char* output, + bool EncryptPacket(uint64_t packet_number, absl::string_view associated_data, + absl::string_view plaintext, char* output, size_t* output_length, size_t /*max_output_length*/) override { packet_number_ = QuicPacketNumber(packet_number); @@ -162,10 +160,8 @@ bool SetDiversificationNonce(const DiversificationNonce& /*key*/) override { return true; } - bool DecryptPacket(uint64_t packet_number, - absl::string_view associated_data, - absl::string_view ciphertext, - char* output, + bool DecryptPacket(uint64_t packet_number, absl::string_view associated_data, + absl::string_view ciphertext, char* output, size_t* output_length, size_t /*max_output_length*/) override { packet_number_ = QuicPacketNumber(packet_number); @@ -197,9 +193,7 @@ }; std::unique_ptr<QuicEncryptedPacket> EncryptPacketWithTagAndPhase( - const QuicPacket& packet, - uint8_t tag, - bool phase) { + const QuicPacket& packet, uint8_t tag, bool phase) { std::string packet_data = std::string(packet.AsStringPiece()); if (phase) { packet_data[0] |= FLAGS_KEY_PHASE_BIT; @@ -692,9 +686,7 @@ decrypter_(new test::TestDecrypter()), version_(GetParam()), start_(QuicTime::Zero() + QuicTime::Delta::FromMicroseconds(0x10)), - framer_(AllSupportedVersions(), - start_, - Perspective::IS_SERVER, + framer_(AllSupportedVersions(), start_, Perspective::IS_SERVER, kQuicDefaultConnectionIdLength) { framer_.set_version(version_); if (framer_.version().KnowsWhichDecrypterToUse()) { @@ -726,6 +718,19 @@ return (CreateQuicVersionLabel(version_) >> 8 * (3 - pos)) & 0xff; } + // Helper functions to take a v1 long header packet and make it v2. These are + // not needed for short header packets, but if sent, this function will exit + // cleanly. It needs to be called twice for coalesced packets (see references + // to length_of_first_coalesced_packet below for examples of how to do this). + inline void ReviseFirstByteByVersion(unsigned char packet_ietf[]) { + if (version_.UsesV2PacketTypes() && (packet_ietf[0] >= 0x80)) { + packet_ietf[0] = (packet_ietf[0] + 0x10) | 0xc0; + } + } + inline void ReviseFirstByteByVersion(PacketFragments& packet_ietf) { + ReviseFirstByteByVersion(&packet_ietf[0].fragment[0]); + } + bool CheckEncryption(QuicPacketNumber packet_number, QuicPacket* packet) { if (packet_number != encrypter_->packet_number_) { QUIC_LOG(ERROR) << "Encrypted incorrect packet number. expected " @@ -762,8 +767,7 @@ } bool CheckDecryption( - const QuicEncryptedPacket& encrypted, - bool includes_version, + const QuicEncryptedPacket& encrypted, bool includes_version, bool includes_diversification_nonce, QuicConnectionIdLength destination_connection_id_length, QuicConnectionIdLength source_connection_id_length, @@ -838,15 +842,13 @@ } } - if (expected_error.empty()) - continue; + if (expected_error.empty()) continue; CheckProcessingFails(*packet, i, expected_error, error_code); } } - void CheckProcessingFails(const QuicEncryptedPacket& packet, - size_t len, + void CheckProcessingFails(const QuicEncryptedPacket& packet, size_t len, std::string expected_error, QuicErrorCode error_code) { QuicEncryptedPacket encrypted(packet.data(), len, false); @@ -855,8 +857,7 @@ EXPECT_EQ(error_code, framer_.error()) << "len: " << len; } - void CheckProcessingFails(unsigned char* packet, - size_t len, + void CheckProcessingFails(unsigned char* packet, size_t len, std::string expected_error, QuicErrorCode error_code) { QuicEncryptedPacket encrypted(AsChars(packet), len, false); @@ -894,8 +895,7 @@ // N starts at 1. QuicStreamId GetNthStreamid(QuicTransportVersion transport_version, - Perspective perspective, - bool bidirectional, + Perspective perspective, bool bidirectional, int n) { if (bidirectional) { return QuicUtils::GetFirstBidirectionalStreamId(transport_version, @@ -931,8 +931,7 @@ GetQuicVersionByte(3) // Run all framer tests with all supported versions of QUIC. -INSTANTIATE_TEST_SUITE_P(QuicFramerTests, - QuicFramerTest, +INSTANTIATE_TEST_SUITE_P(QuicFramerTests, QuicFramerTest, ::testing::ValuesIn(AllSupportedVersions()), ::testing::PrintToStringParamName()); @@ -1273,6 +1272,7 @@ unsigned char* p = packet; size_t p_length = ABSL_ARRAYSIZE(packet); if (framer_.version().HasLongHeaderLengths()) { + ReviseFirstByteByVersion(packet49); p = packet49; p_length = ABSL_ARRAYSIZE(packet49); } @@ -1379,6 +1379,7 @@ unsigned char* p = packet; size_t p_length = ABSL_ARRAYSIZE(packet); if (framer_.version().HasLongHeaderLengths()) { + ReviseFirstByteByVersion(packet49); p = packet49; p_length = ABSL_ARRAYSIZE(packet49); } else if (framer_.version().HasIetfInvariantHeader()) { @@ -1669,6 +1670,7 @@ }; // clang-format on + ReviseFirstByteByVersion(packet49); PacketFragments& fragments = framer_.version().HasLongHeaderLengths() ? packet49 @@ -2970,6 +2972,7 @@ ? VARIABLE_LENGTH_INTEGER_LENGTH_1 : VARIABLE_LENGTH_INTEGER_LENGTH_0; + ReviseFirstByteByVersion(packet_ietf); PacketFragments& fragments = VersionHasIetfQuicFrames(framer_.transport_version()) ? packet_ietf @@ -6420,6 +6423,7 @@ unsigned char* p = packet; size_t p_length = ABSL_ARRAYSIZE(packet); if (framer_.version().UsesTls()) { + ReviseFirstByteByVersion(packet_with_tag); p = packet_with_tag; p_length = ABSL_ARRAYSIZE(packet_with_tag); } else if (framer_.version().HasLongHeaderLengths()) { @@ -7115,6 +7119,7 @@ unsigned char* p = packet; size_t p_size = ABSL_ARRAYSIZE(packet); if (VersionHasIetfQuicFrames(framer_.transport_version())) { + ReviseFirstByteByVersion(packet_ietf); p = packet_ietf; p_size = ABSL_ARRAYSIZE(packet_ietf); } else if (framer_.version().HasLongHeaderLengths()) { @@ -13034,10 +13039,16 @@ 'R', 'L', 'D', '?', }; // clang-format on + const size_t first_packet_ietf_size = 46; + // If the first packet changes, the attempt to fix the first byte of the + // second packet will fail. + EXPECT_EQ(packet_ietf[first_packet_ietf_size], 0xD3); unsigned char* p = packet; size_t p_length = ABSL_ARRAYSIZE(packet); if (framer_.version().HasIetfQuicFrames()) { + ReviseFirstByteByVersion(packet_ietf); + ReviseFirstByteByVersion(&packet_ietf[first_packet_ietf_size]); p = packet_ietf; p_length = ABSL_ARRAYSIZE(packet_ietf); } @@ -13157,6 +13168,7 @@ unsigned char* p = packet; size_t p_length = ABSL_ARRAYSIZE(packet); if (framer_.version().HasIetfQuicFrames()) { + ReviseFirstByteByVersion(packet_ietf); p = packet_ietf; p_length = ABSL_ARRAYSIZE(packet_ietf); } @@ -13304,10 +13316,16 @@ 'R', 'L', 'D', '?', }; // clang-format on + const size_t first_packet_ietf_size = 46; + // If the first packet changes, the attempt to fix the first byte of the + // second packet will fail. + EXPECT_EQ(packet_ietf[first_packet_ietf_size], 0xD3); unsigned char* p = packet; size_t p_length = ABSL_ARRAYSIZE(packet); if (framer_.version().HasIetfQuicFrames()) { + ReviseFirstByteByVersion(packet_ietf); + ReviseFirstByteByVersion(&packet_ietf[first_packet_ietf_size]); p = packet_ietf; p_length = ABSL_ARRAYSIZE(packet_ietf); } @@ -13415,6 +13433,7 @@ unsigned char* p = packet; size_t p_length = ABSL_ARRAYSIZE(packet); if (framer_.version().HasLongHeaderLengths()) { + ReviseFirstByteByVersion(packet49); p = packet49; p_length = ABSL_ARRAYSIZE(packet49); } else if (framer_.version().HasIetfInvariantHeader()) { @@ -13517,6 +13536,7 @@ unsigned char* p = packet; size_t p_length = ABSL_ARRAYSIZE(packet); if (framer_.version().HasLongHeaderLengths()) { + ReviseFirstByteByVersion(packet49); p = packet49; p_length = ABSL_ARRAYSIZE(packet49); } else if (framer_.version().HasIetfInvariantHeader()) { @@ -13677,10 +13697,15 @@ }; // clang-format on const size_t length_of_first_coalesced_packet = 46; + // If the first packet changes, the attempt to fix the first byte of the + // second packet will fail. + EXPECT_EQ(packet_ietf[length_of_first_coalesced_packet], 0xD3); unsigned char* p = packet; size_t p_length = ABSL_ARRAYSIZE(packet); if (framer_.version().HasIetfQuicFrames()) { + ReviseFirstByteByVersion(packet_ietf); + ReviseFirstByteByVersion(&packet_ietf[length_of_first_coalesced_packet]); p = packet_ietf; p_length = ABSL_ARRAYSIZE(packet_ietf); } @@ -13844,10 +13869,16 @@ 'R', 'L', 'D', '?', }; // clang-format on + const size_t length_of_first_coalesced_packet = 46; + // If the first packet changes, the attempt to fix the first byte of the + // second packet will fail. + EXPECT_EQ(packet_ietf[length_of_first_coalesced_packet], 0xD3); unsigned char* p = packet; size_t p_length = ABSL_ARRAYSIZE(packet); if (framer_.version().HasIetfQuicFrames()) { + ReviseFirstByteByVersion(packet_ietf); + ReviseFirstByteByVersion(&packet_ietf[length_of_first_coalesced_packet]); p = packet_ietf; p_length = ABSL_ARRAYSIZE(packet_ietf); } @@ -13949,10 +13980,16 @@ // version would be here but we cut off the invalid coalesced header. }; // clang-format on + const size_t length_of_first_coalesced_packet = 46; + // If the first packet changes, the attempt to fix the first byte of the + // second packet will fail. + EXPECT_EQ(packet_ietf[length_of_first_coalesced_packet], 0xD3); unsigned char* p = packet; size_t p_length = ABSL_ARRAYSIZE(packet); if (framer_.version().HasIetfQuicFrames()) { + ReviseFirstByteByVersion(packet_ietf); + ReviseFirstByteByVersion(&packet_ietf[length_of_first_coalesced_packet]); p = packet_ietf; p_length = ABSL_ARRAYSIZE(packet_ietf); } @@ -14180,6 +14217,7 @@ QuicEncryptedPacket(AsChars(long_header_packet), ABSL_ARRAYSIZE(long_header_packet), false))); } else { + ReviseFirstByteByVersion(long_header_packet_ietf); EXPECT_TRUE(framer_.ProcessPacket( QuicEncryptedPacket(AsChars(long_header_packet_ietf), ABSL_ARRAYSIZE(long_header_packet_ietf), false))); @@ -14708,9 +14746,11 @@ 0x00, }; // clang-format on + unsigned char* p = packet; size_t p_length = ABSL_ARRAYSIZE(packet); if (framer_.version().HasLongHeaderLengths()) { + ReviseFirstByteByVersion(packet49); p = packet49; p_length = ABSL_ARRAYSIZE(packet49); } @@ -14776,6 +14816,7 @@ unsigned char* p = packet; size_t p_length = ABSL_ARRAYSIZE(packet); if (framer_.version().HasLongHeaderLengths()) { + ReviseFirstByteByVersion(packet49); p = packet49; p_length = ABSL_ARRAYSIZE(packet49); } @@ -15615,6 +15656,7 @@ }; // clang-format on + ReviseFirstByteByVersion(packet); QuicEncryptedPacket encrypted(AsChars(packet), ABSL_ARRAYSIZE(packet), false); EXPECT_FALSE(framer_.ProcessPacket(encrypted));
diff --git a/quic/core/quic_session.h b/quic/core/quic_session.h index d06e1fe..88ae992 100644 --- a/quic/core/quic_session.h +++ b/quic/core/quic_session.h
@@ -312,6 +312,7 @@ std::string* error_details) override; void OnHandshakeCallbackDone() override; bool PacketFlusherAttached() const override; + ParsedQuicVersion parsed_version() const override { return version(); } // Implement StreamDelegateInterface. void OnStreamError(QuicErrorCode error_code,
diff --git a/quic/core/quic_version_manager.cc b/quic/core/quic_version_manager.cc index 13e590d..4a84797 100644 --- a/quic/core/quic_version_manager.cc +++ b/quic/core/quic_version_manager.cc
@@ -36,9 +36,11 @@ } void QuicVersionManager::MaybeRefilterSupportedVersions() { - static_assert(SupportedVersions().size() == 5u, + static_assert(SupportedVersions().size() == 6u, "Supported versions out of sync"); - if (disable_version_rfcv1_ != + if (enable_version_2_draft_01_ != + GetQuicReloadableFlag(quic_enable_version_2_draft_01) || + disable_version_rfcv1_ != GetQuicReloadableFlag(quic_disable_version_rfcv1) || disable_version_draft_29_ != GetQuicReloadableFlag(quic_disable_version_draft_29) || @@ -48,6 +50,8 @@ GetQuicReloadableFlag(quic_disable_version_q046) || disable_version_q043_ != GetQuicReloadableFlag(quic_disable_version_q043)) { + enable_version_2_draft_01_ = + GetQuicReloadableFlag(quic_enable_version_2_draft_01); disable_version_rfcv1_ = GetQuicReloadableFlag(quic_disable_version_rfcv1); disable_version_draft_29_ = GetQuicReloadableFlag(quic_disable_version_draft_29);
diff --git a/quic/core/quic_version_manager.h b/quic/core/quic_version_manager.h index af44d34..44e134a 100644 --- a/quic/core/quic_version_manager.h +++ b/quic/core/quic_version_manager.h
@@ -55,6 +55,8 @@ private: // Cached value of reloadable flags. + // quic_enable_version_2_draft_01 flag + bool enable_version_2_draft_01_ = false; // quic_disable_version_rfcv1 flag bool disable_version_rfcv1_ = true; // quic_disable_version_draft_29 flag
diff --git a/quic/core/quic_version_manager_test.cc b/quic/core/quic_version_manager_test.cc index 403009a..aa4581e 100644 --- a/quic/core/quic_version_manager_test.cc +++ b/quic/core/quic_version_manager_test.cc
@@ -18,11 +18,12 @@ class QuicVersionManagerTest : public QuicTest {}; TEST_F(QuicVersionManagerTest, QuicVersionManager) { - static_assert(SupportedVersions().size() == 5u, + static_assert(SupportedVersions().size() == 6u, "Supported versions out of sync"); for (const ParsedQuicVersion& version : AllSupportedVersions()) { QuicEnableVersion(version); } + QuicDisableVersion(ParsedQuicVersion::V2Draft01()); QuicDisableVersion(ParsedQuicVersion::RFCv1()); QuicDisableVersion(ParsedQuicVersion::Draft29()); QuicVersionManager manager(AllSupportedVersions()); @@ -65,6 +66,20 @@ manager.GetSupportedVersionsWithOnlyHttp3()); EXPECT_THAT(manager.GetSupportedAlpns(), ElementsAre("h3", "h3-29", "h3-Q050", "h3-Q046", "h3-Q043")); + + offset++; + QuicEnableVersion(ParsedQuicVersion::V2Draft01()); + expected_parsed_versions.insert(expected_parsed_versions.begin(), + ParsedQuicVersion::V2Draft01()); + EXPECT_EQ(expected_parsed_versions, manager.GetSupportedVersions()); + EXPECT_EQ(FilterSupportedVersions(AllSupportedVersions()), + manager.GetSupportedVersions()); + EXPECT_EQ(3u, manager.GetSupportedVersionsWithOnlyHttp3().size()); + EXPECT_EQ(CurrentSupportedHttp3Versions(), + manager.GetSupportedVersionsWithOnlyHttp3()); + EXPECT_THAT( + manager.GetSupportedAlpns(), + ElementsAre("h3", "h3", "h3-29", "h3-Q050", "h3-Q046", "h3-Q043")); } } // namespace
diff --git a/quic/core/quic_versions.cc b/quic/core/quic_versions.cc index 4c9e661..63d21a1 100644 --- a/quic/core/quic_versions.cc +++ b/quic/core/quic_versions.cc
@@ -42,11 +42,13 @@ } void SetVersionFlag(const ParsedQuicVersion& version, bool should_enable) { - static_assert(SupportedVersions().size() == 5u, + static_assert(SupportedVersions().size() == 6u, "Supported versions out of sync"); const bool enable = should_enable; const bool disable = !should_enable; - if (version == ParsedQuicVersion::RFCv1()) { + if (version == ParsedQuicVersion::V2Draft01()) { + SetQuicReloadableFlag(quic_enable_version_2_draft_01, enable); + } else if (version == ParsedQuicVersion::RFCv1()) { SetQuicReloadableFlag(quic_disable_version_rfcv1, disable); } else if (version == ParsedQuicVersion::Draft29()) { SetQuicReloadableFlag(quic_disable_version_draft_29, disable); @@ -182,6 +184,11 @@ return handshake_protocol == PROTOCOL_QUIC_CRYPTO; } +bool ParsedQuicVersion::UsesV2PacketTypes() const { + QUICHE_DCHECK(IsKnown()); + return transport_version == QUIC_VERSION_IETF_2_DRAFT_01; +} + bool VersionHasLengthPrefixedConnectionIds( QuicTransportVersion transport_version) { QUICHE_DCHECK(transport_version != QUIC_VERSION_UNSUPPORTED); @@ -213,9 +220,11 @@ } QuicVersionLabel CreateQuicVersionLabel(ParsedQuicVersion parsed_version) { - static_assert(SupportedVersions().size() == 5u, + static_assert(SupportedVersions().size() == 6u, "Supported versions out of sync"); - if (parsed_version == ParsedQuicVersion::RFCv1()) { + if (parsed_version == ParsedQuicVersion::V2Draft01()) { + return MakeVersionLabel(0x70, 0x9a, 0x50, 0xc4); + } else if (parsed_version == ParsedQuicVersion::RFCv1()) { return MakeVersionLabel(0x00, 0x00, 0x00, 0x01); } else if (parsed_version == ParsedQuicVersion::Draft29()) { return MakeVersionLabel(0xff, 0x00, 0x00, 29); @@ -411,10 +420,16 @@ ParsedQuicVersionVector FilterSupportedVersions( ParsedQuicVersionVector versions) { + static_assert(SupportedVersions().size() == 6u, + "Supported versions out of sync"); ParsedQuicVersionVector filtered_versions; filtered_versions.reserve(versions.size()); for (const ParsedQuicVersion& version : versions) { - if (version == ParsedQuicVersion::RFCv1()) { + if (version == ParsedQuicVersion::V2Draft01()) { + if (GetQuicReloadableFlag(quic_enable_version_2_draft_01)) { + filtered_versions.push_back(version); + } + } else if (version == ParsedQuicVersion::RFCv1()) { if (!GetQuicReloadableFlag(quic_disable_version_rfcv1)) { filtered_versions.push_back(version); } @@ -444,8 +459,7 @@ } ParsedQuicVersionVector ParsedVersionOfIndex( - const ParsedQuicVersionVector& versions, - int index) { + const ParsedQuicVersionVector& versions, int index) { ParsedQuicVersionVector version; int version_count = versions.size(); if (index >= 0 && index < version_count) { @@ -461,8 +475,7 @@ } std::string QuicVersionLabelVectorToString( - const QuicVersionLabelVector& version_labels, - const std::string& separator, + const QuicVersionLabelVector& version_labels, const std::string& separator, size_t skip_after_nth_version) { std::string result; for (size_t i = 0; i < version_labels.size(); ++i) { @@ -490,6 +503,7 @@ RETURN_STRING_LITERAL(QUIC_VERSION_50); RETURN_STRING_LITERAL(QUIC_VERSION_IETF_DRAFT_29); RETURN_STRING_LITERAL(QUIC_VERSION_IETF_RFC_V1); + RETURN_STRING_LITERAL(QUIC_VERSION_IETF_2_DRAFT_01); RETURN_STRING_LITERAL(QUIC_VERSION_UNSUPPORTED); RETURN_STRING_LITERAL(QUIC_VERSION_RESERVED_FOR_NEGOTIATION); } @@ -508,10 +522,13 @@ } std::string ParsedQuicVersionToString(ParsedQuicVersion version) { - static_assert(SupportedVersions().size() == 5u, + static_assert(SupportedVersions().size() == 6u, "Supported versions out of sync"); if (version == UnsupportedQuicVersion()) { return "0"; + } else if (version == ParsedQuicVersion::V2Draft01()) { + QUICHE_DCHECK(version.UsesHttp3()); + return "v2draft01"; } else if (version == ParsedQuicVersion::RFCv1()) { QUICHE_DCHECK(version.UsesHttp3()); return "RFCv1"; @@ -536,8 +553,7 @@ } std::string ParsedQuicVersionVectorToString( - const ParsedQuicVersionVector& versions, - const std::string& separator, + const ParsedQuicVersionVector& versions, const std::string& separator, size_t skip_after_nth_version) { std::string result; for (size_t i = 0; i < versions.size(); ++i) { @@ -604,7 +620,9 @@ } std::string AlpnForVersion(ParsedQuicVersion parsed_version) { - if (parsed_version == ParsedQuicVersion::RFCv1()) { + if (parsed_version == ParsedQuicVersion::V2Draft01()) { + return "h3"; + } else if (parsed_version == ParsedQuicVersion::RFCv1()) { return "h3"; } else if (parsed_version == ParsedQuicVersion::Draft29()) { return "h3-29";
diff --git a/quic/core/quic_versions.h b/quic/core/quic_versions.h index 331a99c..6c2144a 100644 --- a/quic/core/quic_versions.h +++ b/quic/core/quic_versions.h
@@ -122,8 +122,9 @@ // Number 70 used to represent draft-ietf-quic-transport-25. // Number 71 used to represent draft-ietf-quic-transport-27. // Number 72 used to represent draft-ietf-quic-transport-28. - QUIC_VERSION_IETF_DRAFT_29 = 73, // draft-ietf-quic-transport-29. - QUIC_VERSION_IETF_RFC_V1 = 80, // RFC 9000. + QUIC_VERSION_IETF_DRAFT_29 = 73, // draft-ietf-quic-transport-29. + QUIC_VERSION_IETF_RFC_V1 = 80, // RFC 9000. + QUIC_VERSION_IETF_2_DRAFT_01 = 81, // draft-ietf-quic-v2-01. // Version 99 was a dumping ground for IETF QUIC changes which were not yet // ready for production between 2018-02 and 2020-02. @@ -171,6 +172,7 @@ QuicTransportVersion transport_version) { bool transport_version_is_valid = false; constexpr QuicTransportVersion valid_transport_versions[] = { + QUIC_VERSION_IETF_2_DRAFT_01, QUIC_VERSION_IETF_RFC_V1, QUIC_VERSION_IETF_DRAFT_29, QUIC_VERSION_50, @@ -195,7 +197,8 @@ return transport_version != QUIC_VERSION_UNSUPPORTED && transport_version != QUIC_VERSION_RESERVED_FOR_NEGOTIATION && transport_version != QUIC_VERSION_IETF_DRAFT_29 && - transport_version != QUIC_VERSION_IETF_RFC_V1; + transport_version != QUIC_VERSION_IETF_RFC_V1 && + transport_version != QUIC_VERSION_IETF_2_DRAFT_01; case PROTOCOL_TLS1_3: return transport_version != QUIC_VERSION_UNSUPPORTED && transport_version != QUIC_VERSION_50 && @@ -245,6 +248,10 @@ transport_version != other.transport_version; } + static constexpr ParsedQuicVersion V2Draft01() { + return ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_IETF_2_DRAFT_01); + } + static constexpr ParsedQuicVersion RFCv1() { return ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_IETF_RFC_V1); } @@ -361,6 +368,9 @@ // Returns whether this version uses PROTOCOL_QUIC_CRYPTO. bool UsesQuicCrypto() const; + + // Returns whether this version uses the QUICv2 Long Header Packet Types. + bool UsesV2PacketTypes() const; }; QUIC_EXPORT_PRIVATE ParsedQuicVersion UnsupportedQuicVersion(); @@ -377,8 +387,7 @@ using ParsedQuicVersionVector = std::vector<ParsedQuicVersion>; QUIC_EXPORT_PRIVATE std::ostream& operator<<( - std::ostream& os, - const ParsedQuicVersionVector& versions); + std::ostream& os, const ParsedQuicVersionVector& versions); // Representation of the on-the-wire QUIC version number. Will be written/read // to the wire in network-byte-order. @@ -386,27 +395,25 @@ using QuicVersionLabelVector = std::vector<QuicVersionLabel>; QUIC_EXPORT_PRIVATE std::ostream& operator<<( - std::ostream& os, - const QuicVersionLabelVector& version_labels); + std::ostream& os, const QuicVersionLabelVector& version_labels); // This vector contains all crypto handshake protocols that are supported. constexpr std::array<HandshakeProtocol, 2> SupportedHandshakeProtocols() { return {PROTOCOL_TLS1_3, PROTOCOL_QUIC_CRYPTO}; } -constexpr std::array<ParsedQuicVersion, 5> SupportedVersions() { +constexpr std::array<ParsedQuicVersion, 6> SupportedVersions() { return { - ParsedQuicVersion::RFCv1(), ParsedQuicVersion::Draft29(), - ParsedQuicVersion::Q050(), ParsedQuicVersion::Q046(), - ParsedQuicVersion::Q043(), + ParsedQuicVersion::V2Draft01(), ParsedQuicVersion::RFCv1(), + ParsedQuicVersion::Draft29(), ParsedQuicVersion::Q050(), + ParsedQuicVersion::Q046(), ParsedQuicVersion::Q043(), }; } using QuicTransportVersionVector = std::vector<QuicTransportVersion>; QUIC_EXPORT_PRIVATE std::ostream& operator<<( - std::ostream& os, - const QuicTransportVersionVector& transport_versions); + std::ostream& os, const QuicTransportVersionVector& transport_versions); // Returns a vector of supported QUIC versions. QUIC_EXPORT_PRIVATE ParsedQuicVersionVector AllSupportedVersions(); @@ -494,8 +501,7 @@ // QuicVersionLabel values in the supplied |version_labels| vector. The values // after the (0-based) |skip_after_nth_version|'th are skipped. QUIC_EXPORT_PRIVATE std::string QuicVersionLabelVectorToString( - const QuicVersionLabelVector& version_labels, - const std::string& separator, + const QuicVersionLabelVector& version_labels, const std::string& separator, size_t skip_after_nth_version); // Returns comma separated list of string representations of QuicVersionLabel @@ -529,8 +535,7 @@ // ParsedQuicVersion values in the supplied |versions| vector. The values after // the (0-based) |skip_after_nth_version|'th are skipped. QUIC_EXPORT_PRIVATE std::string ParsedQuicVersionVectorToString( - const ParsedQuicVersionVector& versions, - const std::string& separator, + const ParsedQuicVersionVector& versions, const std::string& separator, size_t skip_after_nth_version); // Returns comma separated list of string representations of ParsedQuicVersion
diff --git a/quic/core/quic_versions_test.cc b/quic/core/quic_versions_test.cc index d60bd4d..6f384dd 100644 --- a/quic/core/quic_versions_test.cc +++ b/quic/core/quic_versions_test.cc
@@ -120,9 +120,13 @@ ParseQuicVersionLabel(MakeVersionLabel(0xff, 0x00, 0x00, 0x1d))); EXPECT_EQ(ParsedQuicVersion::RFCv1(), ParseQuicVersionLabel(MakeVersionLabel(0x00, 0x00, 0x00, 0x01))); - EXPECT_EQ((ParsedQuicVersionVector{ParsedQuicVersion::RFCv1(), + EXPECT_EQ(ParsedQuicVersion::V2Draft01(), + ParseQuicVersionLabel(MakeVersionLabel(0x70, 0x9a, 0x50, 0xc4))); + EXPECT_EQ((ParsedQuicVersionVector{ParsedQuicVersion::V2Draft01(), + ParsedQuicVersion::RFCv1(), ParsedQuicVersion::Draft29()}), ParseQuicVersionLabelVector(QuicVersionLabelVector{ + MakeVersionLabel(0x70, 0x9a, 0x50, 0xc4), MakeVersionLabel(0x00, 0x00, 0x00, 0x01), MakeVersionLabel(0xaa, 0xaa, 0xaa, 0xaa), MakeVersionLabel(0xff, 0x00, 0x00, 0x1d)})); @@ -217,6 +221,8 @@ CreateQuicVersionLabel(ParsedQuicVersion::Draft29())); EXPECT_EQ(MakeVersionLabel(0x00, 0x00, 0x00, 0x01), CreateQuicVersionLabel(ParsedQuicVersion::RFCv1())); + EXPECT_EQ(MakeVersionLabel(0x70, 0x9a, 0x50, 0xc4), + CreateQuicVersionLabel(ParsedQuicVersion::V2Draft01())); // Make sure the negotiation reserved version is in the IETF reserved space. EXPECT_EQ( @@ -291,6 +297,8 @@ EXPECT_EQ("Q050", ParsedQuicVersionToString(ParsedQuicVersion::Q050())); EXPECT_EQ("draft29", ParsedQuicVersionToString(ParsedQuicVersion::Draft29())); EXPECT_EQ("RFCv1", ParsedQuicVersionToString(ParsedQuicVersion::RFCv1())); + EXPECT_EQ("v2draft01", + ParsedQuicVersionToString(ParsedQuicVersion::V2Draft01())); ParsedQuicVersionVector versions_vector = {ParsedQuicVersion::Q043()}; EXPECT_EQ("Q043", ParsedQuicVersionVectorToString(versions_vector)); @@ -357,23 +365,25 @@ // yet a typo was made in doing the #defines and it was caught // only in some test far removed from here... Better safe than sorry. TEST_F(QuicVersionsTest, CheckTransportVersionNumbersForTypos) { - static_assert(SupportedVersions().size() == 5u, + static_assert(SupportedVersions().size() == 6u, "Supported versions out of sync"); EXPECT_EQ(QUIC_VERSION_43, 43); EXPECT_EQ(QUIC_VERSION_46, 46); EXPECT_EQ(QUIC_VERSION_50, 50); EXPECT_EQ(QUIC_VERSION_IETF_DRAFT_29, 73); EXPECT_EQ(QUIC_VERSION_IETF_RFC_V1, 80); + EXPECT_EQ(QUIC_VERSION_IETF_2_DRAFT_01, 81); } TEST_F(QuicVersionsTest, AlpnForVersion) { - static_assert(SupportedVersions().size() == 5u, + static_assert(SupportedVersions().size() == 6u, "Supported versions out of sync"); EXPECT_EQ("h3-Q043", AlpnForVersion(ParsedQuicVersion::Q043())); EXPECT_EQ("h3-Q046", AlpnForVersion(ParsedQuicVersion::Q046())); EXPECT_EQ("h3-Q050", AlpnForVersion(ParsedQuicVersion::Q050())); EXPECT_EQ("h3-29", AlpnForVersion(ParsedQuicVersion::Draft29())); EXPECT_EQ("h3", AlpnForVersion(ParsedQuicVersion::RFCv1())); + EXPECT_EQ("h3", AlpnForVersion(ParsedQuicVersion::V2Draft01())); } TEST_F(QuicVersionsTest, QuicVersionEnabling) { @@ -423,8 +433,12 @@ EXPECT_NE(CreateQuicVersionLabel(version1), CreateQuicVersionLabel(version2)) << version1 << " " << version2; - EXPECT_NE(AlpnForVersion(version1), AlpnForVersion(version2)) - << version1 << " " << version2; + // The one pair where ALPNs are the same. + if ((version1 != ParsedQuicVersion::V2Draft01()) && + (version2 != ParsedQuicVersion::RFCv1())) { + EXPECT_NE(AlpnForVersion(version1), AlpnForVersion(version2)) + << version1 << " " << version2; + } } } }
diff --git a/quic/core/tls_handshaker.cc b/quic/core/tls_handshaker.cc index ad7dafb..2eee1cc 100644 --- a/quic/core/tls_handshaker.cc +++ b/quic/core/tls_handshaker.cc
@@ -25,8 +25,7 @@ TlsHandshaker::ProofVerifierCallbackImpl::~ProofVerifierCallbackImpl() {} void TlsHandshaker::ProofVerifierCallbackImpl::Run( - bool ok, - const std::string& /*error_details*/, + bool ok, const std::string& /*error_details*/, std::unique_ptr<ProofVerifyDetails>* details) { if (parent_ == nullptr) { return; @@ -42,9 +41,7 @@ parent_->AdvanceHandshake(); } -void TlsHandshaker::ProofVerifierCallbackImpl::Cancel() { - parent_ = nullptr; -} +void TlsHandshaker::ProofVerifierCallbackImpl::Cancel() { parent_ = nullptr; } TlsHandshaker::TlsHandshaker(QuicCryptoStream* stream, QuicSession* session) : stream_(stream), handshaker_delegate_(session) {} @@ -243,10 +240,13 @@ std::unique_ptr<QuicEncrypter> encrypter = QuicEncrypter::CreateFromCipherSuite(SSL_CIPHER_get_id(cipher)); const EVP_MD* prf = Prf(cipher); - CryptoUtils::SetKeyAndIV(prf, write_secret, encrypter.get()); + CryptoUtils::SetKeyAndIV(prf, write_secret, + handshaker_delegate_->parsed_version(), + encrypter.get()); std::vector<uint8_t> header_protection_key = - CryptoUtils::GenerateHeaderProtectionKey(prf, write_secret, - encrypter->GetKeySize()); + CryptoUtils::GenerateHeaderProtectionKey( + prf, write_secret, handshaker_delegate_->parsed_version(), + encrypter->GetKeySize()); encrypter->SetHeaderProtectionKey( absl::string_view(reinterpret_cast<char*>(header_protection_key.data()), header_protection_key.size())); @@ -266,10 +266,13 @@ std::unique_ptr<QuicDecrypter> decrypter = QuicDecrypter::CreateFromCipherSuite(SSL_CIPHER_get_id(cipher)); const EVP_MD* prf = Prf(cipher); - CryptoUtils::SetKeyAndIV(prf, read_secret, decrypter.get()); + CryptoUtils::SetKeyAndIV(prf, read_secret, + handshaker_delegate_->parsed_version(), + decrypter.get()); std::vector<uint8_t> header_protection_key = - CryptoUtils::GenerateHeaderProtectionKey(prf, read_secret, - decrypter->GetKeySize()); + CryptoUtils::GenerateHeaderProtectionKey( + prf, read_secret, handshaker_delegate_->parsed_version(), + decrypter->GetKeySize()); decrypter->SetHeaderProtectionKey( absl::string_view(reinterpret_cast<char*>(header_protection_key.data()), header_protection_key.size())); @@ -296,14 +299,16 @@ } const SSL_CIPHER* cipher = SSL_get_current_cipher(ssl()); const EVP_MD* prf = Prf(cipher); - latest_read_secret_ = - CryptoUtils::GenerateNextKeyPhaseSecret(prf, latest_read_secret_); - latest_write_secret_ = - CryptoUtils::GenerateNextKeyPhaseSecret(prf, latest_write_secret_); + latest_read_secret_ = CryptoUtils::GenerateNextKeyPhaseSecret( + prf, handshaker_delegate_->parsed_version(), latest_read_secret_); + latest_write_secret_ = CryptoUtils::GenerateNextKeyPhaseSecret( + prf, handshaker_delegate_->parsed_version(), latest_write_secret_); std::unique_ptr<QuicDecrypter> decrypter = QuicDecrypter::CreateFromCipherSuite(SSL_CIPHER_get_id(cipher)); - CryptoUtils::SetKeyAndIV(prf, latest_read_secret_, decrypter.get()); + CryptoUtils::SetKeyAndIV(prf, latest_read_secret_, + handshaker_delegate_->parsed_version(), + decrypter.get()); decrypter->SetHeaderProtectionKey(absl::string_view( reinterpret_cast<char*>(one_rtt_read_header_protection_key_.data()), one_rtt_read_header_protection_key_.size())); @@ -322,7 +327,9 @@ const SSL_CIPHER* cipher = SSL_get_current_cipher(ssl()); std::unique_ptr<QuicEncrypter> encrypter = QuicEncrypter::CreateFromCipherSuite(SSL_CIPHER_get_id(cipher)); - CryptoUtils::SetKeyAndIV(Prf(cipher), latest_write_secret_, encrypter.get()); + CryptoUtils::SetKeyAndIV(Prf(cipher), latest_write_secret_, + handshaker_delegate_->parsed_version(), + encrypter.get()); encrypter->SetHeaderProtectionKey(absl::string_view( reinterpret_cast<char*>(one_rtt_write_header_protection_key_.data()), one_rtt_write_header_protection_key_.size()));