gfe-relnote: Enable initial obfuscators in QUIC_VERSION_99. Protected by quic_enable_version_99

PiperOrigin-RevId: 270834093
Change-Id: Ieee9980f6facc222ee700961a4a36791cf28ab39
diff --git a/quic/core/crypto/aead_base_decrypter.cc b/quic/core/crypto/aead_base_decrypter.cc
index 8fec273..b5db0db 100644
--- a/quic/core/crypto/aead_base_decrypter.cc
+++ b/quic/core/crypto/aead_base_decrypter.cc
@@ -186,6 +186,10 @@
   return key_size_;
 }
 
+size_t AeadBaseDecrypter::GetNoncePrefixSize() const {
+  return nonce_size_ - sizeof(QuicPacketNumber);
+}
+
 size_t AeadBaseDecrypter::GetIVSize() const {
   return nonce_size_;
 }
diff --git a/quic/core/crypto/aead_base_decrypter.h b/quic/core/crypto/aead_base_decrypter.h
index 8c7fa15..f0c5b01 100644
--- a/quic/core/crypto/aead_base_decrypter.h
+++ b/quic/core/crypto/aead_base_decrypter.h
@@ -41,6 +41,7 @@
                      size_t* output_length,
                      size_t max_output_length) override;
   size_t GetKeySize() const override;
+  size_t GetNoncePrefixSize() const override;
   size_t GetIVSize() const override;
   QuicStringPiece GetKey() const override;
   QuicStringPiece GetNoncePrefix() const override;
diff --git a/quic/core/crypto/crypto_utils.cc b/quic/core/crypto/crypto_utils.cc
index 2889098..4851748 100644
--- a/quic/core/crypto/crypto_utils.cc
+++ b/quic/core/crypto/crypto_utils.cc
@@ -10,6 +10,8 @@
 #include "third_party/boringssl/src/include/openssl/bytestring.h"
 #include "third_party/boringssl/src/include/openssl/hkdf.h"
 #include "third_party/boringssl/src/include/openssl/sha.h"
+#include "net/third_party/quiche/src/quic/core/crypto/aes_128_gcm_12_decrypter.h"
+#include "net/third_party/quiche/src/quic/core/crypto/aes_128_gcm_12_encrypter.h"
 #include "net/third_party/quiche/src/quic/core/crypto/aes_128_gcm_decrypter.h"
 #include "net/third_party/quiche/src/quic/core/crypto/aes_128_gcm_encrypter.h"
 #include "net/third_party/quiche/src/quic/core/crypto/crypto_handshake.h"
@@ -31,16 +33,31 @@
 
 namespace quic {
 
+namespace {
+
+// Implements the HKDF-Expand-Label function as defined in section 7.1 of RFC
+// 8446, except that it uses "quic " as the prefix instead of "tls13 ", as
+// specified by draft-ietf-quic-tls-14. The HKDF-Expand-Label function takes 4
+// explicit arguments (Secret, Label, Context, and Length), as well as
+// implicit PRF which is the hash function negotiated by TLS. Its use in QUIC
+// (as needed by the QUIC stack, instead of as used internally by the TLS
+// stack) is only for deriving initial secrets for obfuscation and for
+// calculating packet protection keys and IVs from the corresponding packet
+// protection secret. Neither of these uses need a Context (a zero-length
+// context is provided), so this argument is omitted here.
+//
+// The implicit PRF is explicitly passed into HkdfExpandLabel as |prf|; the
+// Secret, Label, and Length are passed in as |secret|, |label|, and
+// |out_len|, respectively. The resulting expanded secret is returned.
+//
 // TODO(nharper): HkdfExpandLabel and SetKeyAndIV (below) implement what is
 // specified in draft-ietf-quic-tls-16. The latest editors' draft has changed
 // derivation again, and this will need to be updated to reflect those (and any
 // other future) changes.
-// static
-std::vector<uint8_t> CryptoUtils::HkdfExpandLabel(
-    const EVP_MD* prf,
-    const std::vector<uint8_t>& secret,
-    const std::string& label,
-    size_t out_len) {
+std::vector<uint8_t> HkdfExpandLabel(const EVP_MD* prf,
+                                     const std::vector<uint8_t>& secret,
+                                     const std::string& label,
+                                     size_t out_len) {
   bssl::ScopedCBB quic_hkdf_label;
   CBB inner_label;
   const char label_prefix[] = "tls13 ";
@@ -71,15 +88,17 @@
   return out;
 }
 
+}  // namespace
+
 void CryptoUtils::SetKeyAndIV(const EVP_MD* prf,
                               const std::vector<uint8_t>& pp_secret,
                               QuicCrypter* crypter) {
-  std::vector<uint8_t> key = CryptoUtils::HkdfExpandLabel(
-      prf, pp_secret, "quic key", crypter->GetKeySize());
-  std::vector<uint8_t> iv = CryptoUtils::HkdfExpandLabel(
-      prf, pp_secret, "quic iv", crypter->GetIVSize());
-  std::vector<uint8_t> pn = CryptoUtils::HkdfExpandLabel(
-      prf, pp_secret, "quic hp", crypter->GetKeySize());
+  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());
+  std::vector<uint8_t> pn =
+      HkdfExpandLabel(prf, pp_secret, "quic hp", crypter->GetKeySize());
   crypter->SetKey(
       QuicStringPiece(reinterpret_cast<char*>(key.data()), key.size()));
   crypter->SetIV(
@@ -91,13 +110,35 @@
 namespace {
 
 static_assert(kQuicIetfDraftVersion == 23, "Salts do not match draft version");
-// Salt from https://tools.ietf.org/html/draft-ietf-quic-tls-24#section-5.2
+// Salt from https://tools.ietf.org/html/draft-ietf-quic-tls-23#section-5.2
 const uint8_t kInitialSalt[] = {0xc3, 0xee, 0xf7, 0x12, 0xc7, 0x2e, 0xbb,
                                 0x5a, 0x11, 0xa7, 0xd2, 0x43, 0x2b, 0xb4,
                                 0x63, 0x65, 0xbe, 0xf9, 0xf5, 0x02};
 
 const char kPreSharedKeyLabel[] = "QUIC PSK";
 
+// This is the same as SetKeyAndIV, except it is for use with Google QUIC crypto
+// style crypters (which have a different nonce construction and auth tag
+// length). The labels for HkdfExpandLabel have also been changed to be prefixed
+// with "gquic" instead of "quic".
+void SetKeyAndNonceForGoogleQuicInitialCrypter(
+    const EVP_MD* prf,
+    const std::vector<uint8_t>& pp_secret,
+    QuicCrypter* crypter) {
+  std::vector<uint8_t> key =
+      HkdfExpandLabel(prf, pp_secret, "gquic key", crypter->GetKeySize());
+  std::vector<uint8_t> iv = HkdfExpandLabel(prf, pp_secret, "gquic iv",
+                                            crypter->GetNoncePrefixSize());
+  std::vector<uint8_t> pn =
+      HkdfExpandLabel(prf, pp_secret, "gquic hp", crypter->GetKeySize());
+  crypter->SetKey(
+      QuicStringPiece(reinterpret_cast<char*>(key.data()), key.size()));
+  crypter->SetNoncePrefix(
+      QuicStringPiece(reinterpret_cast<char*>(iv.data()), iv.size()));
+  crypter->SetHeaderProtectionKey(
+      QuicStringPiece(reinterpret_cast<char*>(pn.data()), pn.size()));
+}
+
 }  // namespace
 
 // static
@@ -142,15 +183,27 @@
     encryption_label = server_label;
     decryption_label = client_label;
   }
-  crypters->encrypter = std::make_unique<Aes128GcmEncrypter>();
   std::vector<uint8_t> encryption_secret = HkdfExpandLabel(
       hash, handshake_secret, encryption_label, EVP_MD_size(hash));
-  SetKeyAndIV(hash, encryption_secret, crypters->encrypter.get());
-
-  crypters->decrypter = std::make_unique<Aes128GcmDecrypter>();
   std::vector<uint8_t> decryption_secret = HkdfExpandLabel(
       hash, handshake_secret, decryption_label, EVP_MD_size(hash));
-  SetKeyAndIV(hash, decryption_secret, crypters->decrypter.get());
+
+  // Create an encrypter and decrypter that have an auth tag of the same length
+  // as the encrypters/decrypters used with the handshake protocol for this
+  // version.
+  if (version.handshake_protocol == PROTOCOL_TLS1_3) {
+    crypters->encrypter = std::make_unique<Aes128GcmEncrypter>();
+    SetKeyAndIV(hash, encryption_secret, crypters->encrypter.get());
+    crypters->decrypter = std::make_unique<Aes128GcmDecrypter>();
+    SetKeyAndIV(hash, decryption_secret, crypters->decrypter.get());
+  } else {
+    crypters->encrypter = std::make_unique<Aes128Gcm12Encrypter>();
+    SetKeyAndNonceForGoogleQuicInitialCrypter(hash, encryption_secret,
+                                              crypters->encrypter.get());
+    crypters->decrypter = std::make_unique<Aes128Gcm12Decrypter>();
+    SetKeyAndNonceForGoogleQuicInitialCrypter(hash, decryption_secret,
+                                              crypters->decrypter.get());
+  }
 }
 
 // static
diff --git a/quic/core/crypto/crypto_utils.h b/quic/core/crypto/crypto_utils.h
index 0eae972..6f198d6 100644
--- a/quic/core/crypto/crypto_utils.h
+++ b/quic/core/crypto/crypto_utils.h
@@ -202,27 +202,6 @@
   // Returns a hash of the serialized |message|.
   static std::string HashHandshakeMessage(const CryptoHandshakeMessage& message,
                                           Perspective perspective);
-
- private:
-  // Implements the HKDF-Expand-Label function as defined in section 7.1 of RFC
-  // 8446, except that it uses "quic " as the prefix instead of "tls13 ", as
-  // specified by draft-ietf-quic-tls-14. The HKDF-Expand-Label function takes 4
-  // explicit arguments (Secret, Label, Context, and Length), as well as
-  // implicit PRF which is the hash function negotiated by TLS. Its use in QUIC
-  // (as needed by the QUIC stack, instead of as used internally by the TLS
-  // stack) is only for deriving initial secrets for obfuscation and for
-  // calculating packet protection keys and IVs from the corresponding packet
-  // protection secret. Neither of these uses need a Context (a zero-length
-  // context is provided), so this argument is omitted here.
-  //
-  // The implicit PRF is explicitly passed into HkdfExpandLabel as |prf|; the
-  // Secret, Label, and Length are passed in as |secret|, |label|, and
-  // |out_len|, respectively. The resulting expanded secret is returned.
-  static std::vector<uint8_t> HkdfExpandLabel(
-      const EVP_MD* prf,
-      const std::vector<uint8_t>& secret,
-      const std::string& label,
-      size_t out_len);
 };
 
 }  // namespace quic
diff --git a/quic/core/crypto/null_decrypter.cc b/quic/core/crypto/null_decrypter.cc
index e89fecc..af0a886 100644
--- a/quic/core/crypto/null_decrypter.cc
+++ b/quic/core/crypto/null_decrypter.cc
@@ -80,6 +80,10 @@
   return 0;
 }
 
+size_t NullDecrypter::GetNoncePrefixSize() const {
+  return 0;
+}
+
 size_t NullDecrypter::GetIVSize() const {
   return 0;
 }
diff --git a/quic/core/crypto/null_decrypter.h b/quic/core/crypto/null_decrypter.h
index 06c361d..aac25bb 100644
--- a/quic/core/crypto/null_decrypter.h
+++ b/quic/core/crypto/null_decrypter.h
@@ -44,6 +44,7 @@
   std::string GenerateHeaderProtectionMask(
       QuicDataReader* sample_reader) override;
   size_t GetKeySize() const override;
+  size_t GetNoncePrefixSize() const override;
   size_t GetIVSize() const override;
   QuicStringPiece GetKey() const override;
   QuicStringPiece GetNoncePrefix() const override;
diff --git a/quic/core/crypto/quic_crypter.h b/quic/core/crypto/quic_crypter.h
index c698dfb..5f07836 100644
--- a/quic/core/crypto/quic_crypter.h
+++ b/quic/core/crypto/quic_crypter.h
@@ -72,10 +72,15 @@
   // Sets the key to use for header protection.
   virtual bool SetHeaderProtectionKey(QuicStringPiece key) = 0;
 
+  // GetKeySize, GetIVSize, and GetNoncePrefixSize are used to know how many
+  // bytes of key material needs to be derived from the master secret.
+
   // Returns the size in bytes of a key for the algorithm.
   virtual size_t GetKeySize() const = 0;
   // Returns the size in bytes of an IV to use with the algorithm.
   virtual size_t GetIVSize() const = 0;
+  // Returns the size in bytes of the fixed initial part of the nonce.
+  virtual size_t GetNoncePrefixSize() const = 0;
 };
 
 }  // namespace quic
diff --git a/quic/core/crypto/quic_encrypter.h b/quic/core/crypto/quic_encrypter.h
index 6a69fcc..15acd02 100644
--- a/quic/core/crypto/quic_encrypter.h
+++ b/quic/core/crypto/quic_encrypter.h
@@ -47,14 +47,6 @@
   // be empty.
   virtual std::string GenerateHeaderProtectionMask(QuicStringPiece sample) = 0;
 
-  // GetKeySize() and GetNoncePrefixSize() tell the HKDF class how many bytes
-  // of key material needs to be derived from the master secret.
-  // NOTE: the sizes returned by GetKeySize() and GetNoncePrefixSize() are
-  // also correct for the QuicDecrypter of the same algorithm.
-
-  // Returns the size in bytes of the fixed initial part of the nonce.
-  virtual size_t GetNoncePrefixSize() const = 0;
-
   // Returns the maximum length of plaintext that can be encrypted
   // to ciphertext no larger than |ciphertext_size|.
   virtual size_t GetMaxPlaintextSize(size_t ciphertext_size) const = 0;
diff --git a/quic/core/quic_connection.cc b/quic/core/quic_connection.cc
index c3ba88b..c260e81 100644
--- a/quic/core/quic_connection.cc
+++ b/quic/core/quic_connection.cc
@@ -362,6 +362,7 @@
 
 void QuicConnection::InstallInitialCrypters(QuicConnectionId connection_id) {
   if (!framer_.framer_doesnt_create_initial_encrypter() &&
+      !version().UsesInitialObfuscators() &&
       version().handshake_protocol != PROTOCOL_TLS1_3) {
     // Initial crypters are currently only supported with TLS.
     return;
diff --git a/quic/core/quic_connection_test.cc b/quic/core/quic_connection_test.cc
index 3d59d14..2f8f6a7 100644
--- a/quic/core/quic_connection_test.cc
+++ b/quic/core/quic_connection_test.cc
@@ -225,6 +225,7 @@
   }
 
   size_t GetKeySize() const override { return 0; }
+  size_t GetNoncePrefixSize() const override { return 0; }
   size_t GetIVSize() const override { return 0; }
   QuicStringPiece GetKey() const override { return QuicStringPiece(); }
   QuicStringPiece GetNoncePrefix() const override { return QuicStringPiece(); }
diff --git a/quic/core/quic_dispatcher.cc b/quic/core/quic_dispatcher.cc
index 3187c78..4d7a2d7 100644
--- a/quic/core/quic_dispatcher.cc
+++ b/quic/core/quic_dispatcher.cc
@@ -135,7 +135,8 @@
         creator_(server_connection_id, &framer_, &collector_),
         time_wait_list_manager_(time_wait_list_manager) {
     framer_.set_data_producer(&collector_);
-    if (framer_.framer_doesnt_create_initial_encrypter()) {
+    if (framer_.framer_doesnt_create_initial_encrypter() ||
+        version.UsesInitialObfuscators()) {
       framer_.SetInitialObfuscators(server_connection_id);
     }
   }
diff --git a/quic/core/quic_framer_test.cc b/quic/core/quic_framer_test.cc
index fd8d287..d343c0d 100644
--- a/quic/core/quic_framer_test.cc
+++ b/quic/core/quic_framer_test.cc
@@ -164,6 +164,7 @@
     return std::string(5, 0);
   }
   size_t GetKeySize() const override { return 0; }
+  size_t GetNoncePrefixSize() const override { return 0; }
   size_t GetIVSize() const override { return 0; }
   QuicStringPiece GetKey() const override { return QuicStringPiece(); }
   QuicStringPiece GetNoncePrefix() const override { return QuicStringPiece(); }
@@ -13035,7 +13036,8 @@
   header.long_packet_type = INITIAL;
   header.length_length = VARIABLE_LENGTH_INTEGER_LENGTH_2;
   header.retry_token_length_length = VARIABLE_LENGTH_INTEGER_LENGTH_1;
-  QuicFrames frames = {QuicFrame(QuicPingFrame())};
+  QuicFrames frames = {QuicFrame(QuicPingFrame()),
+                       QuicFrame(QuicPaddingFrame(3))};
 
   std::unique_ptr<QuicPacket> data(BuildDataPacket(header, frames));
   ASSERT_NE(nullptr, data);
diff --git a/quic/core/quic_versions.cc b/quic/core/quic_versions.cc
index 64cfcca..223780b 100644
--- a/quic/core/quic_versions.cc
+++ b/quic/core/quic_versions.cc
@@ -55,7 +55,8 @@
 }
 
 bool ParsedQuicVersion::UsesInitialObfuscators() const {
-  return handshake_protocol == PROTOCOL_TLS1_3;
+  return transport_version == QUIC_VERSION_99 ||
+         handshake_protocol == PROTOCOL_TLS1_3;
 }
 
 bool ParsedQuicVersion::AllowsLowFlowControlLimits() const {
diff --git a/quic/test_tools/quic_test_utils.cc b/quic/test_tools/quic_test_utils.cc
index 2637702..dae5857 100644
--- a/quic/test_tools/quic_test_utils.cc
+++ b/quic/test_tools/quic_test_utils.cc
@@ -107,6 +107,19 @@
   return ack;
 }
 
+EncryptionLevel HeaderToEncryptionLevel(const QuicPacketHeader& header) {
+  if (header.form == IETF_QUIC_SHORT_HEADER_PACKET) {
+    return ENCRYPTION_FORWARD_SECURE;
+  } else if (header.form == IETF_QUIC_LONG_HEADER_PACKET) {
+    if (header.long_packet_type == HANDSHAKE) {
+      return ENCRYPTION_HANDSHAKE;
+    } else if (header.long_packet_type == ZERO_RTT_PROTECTED) {
+      return ENCRYPTION_ZERO_RTT;
+    }
+  }
+  return ENCRYPTION_INITIAL;
+}
+
 std::unique_ptr<QuicPacket> BuildUnsizedDataPacket(
     QuicFramer* framer,
     const QuicPacketHeader& header,
@@ -133,16 +146,7 @@
     const QuicFrames& frames,
     size_t packet_size) {
   char* buffer = new char[packet_size];
-  EncryptionLevel level = ENCRYPTION_INITIAL;
-  if (header.form == IETF_QUIC_SHORT_HEADER_PACKET) {
-    level = ENCRYPTION_FORWARD_SECURE;
-  } else if (header.form == IETF_QUIC_LONG_HEADER_PACKET) {
-    if (header.long_packet_type == HANDSHAKE) {
-      level = ENCRYPTION_HANDSHAKE;
-    } else if (header.long_packet_type == ZERO_RTT_PROTECTED) {
-      level = ENCRYPTION_ZERO_RTT;
-    }
-  }
+  EncryptionLevel level = HeaderToEncryptionLevel(header);
   size_t length =
       framer->BuildDataPacket(header, frames, buffer, packet_size, level);
   DCHECK_NE(0u, length);
diff --git a/quic/test_tools/quic_test_utils.h b/quic/test_tools/quic_test_utils.h
index 94f25fc..c12587d 100644
--- a/quic/test_tools/quic_test_utils.h
+++ b/quic/test_tools/quic_test_utils.h
@@ -205,6 +205,11 @@
 QuicAckFrame MakeAckFrameWithAckBlocks(size_t num_ack_blocks,
                                        uint64_t least_unacked);
 
+// Returns the encryption level that corresponds to the header type in
+// |header|. If the header is for GOOGLE_QUIC_PACKET instead of an
+// IETF-invariants packet, this function returns ENCRYPTION_INITIAL.
+EncryptionLevel HeaderToEncryptionLevel(const QuicPacketHeader& header);
+
 // Returns a QuicPacket that is owned by the caller, and
 // is populated with the fields in |header| and |frames|, or is nullptr if the
 // packet could not be created.