Implement QUIC Header Protection

gfe-relnote: Protected by QUIC_VERSION_99
PiperOrigin-RevId: 247137283
Change-Id: I1deb08d304b7739c3c8fa6b995e55fbd8652dc1e
diff --git a/quic/core/crypto/aes_base_encrypter.cc b/quic/core/crypto/aes_base_encrypter.cc
index 49fc71d..cdb21b8 100644
--- a/quic/core/crypto/aes_base_encrypter.cc
+++ b/quic/core/crypto/aes_base_encrypter.cc
@@ -11,7 +11,7 @@
 
 bool AesBaseEncrypter::SetHeaderProtectionKey(QuicStringPiece key) {
   if (key.size() != GetKeySize()) {
-    QUIC_BUG << "Invalid key size for header protection";
+    QUIC_BUG << "Invalid key size for header protection: " << key.size();
     return false;
   }
   if (AES_set_encrypt_key(reinterpret_cast<const uint8_t*>(key.data()),
diff --git a/quic/core/crypto/crypto_utils.cc b/quic/core/crypto/crypto_utils.cc
index 724f245..57edda0 100644
--- a/quic/core/crypto/crypto_utils.cc
+++ b/quic/core/crypto/crypto_utils.cc
@@ -76,10 +76,14 @@
       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());
   crypter->SetKey(
       QuicStringPiece(reinterpret_cast<char*>(key.data()), key.size()));
   crypter->SetIV(
       QuicStringPiece(reinterpret_cast<char*>(iv.data()), iv.size()));
+  crypter->SetHeaderProtectionKey(
+      QuicStringPiece(reinterpret_cast<char*>(pn.data()), pn.size()));
 }
 
 namespace {
@@ -224,15 +228,23 @@
       if (perspective == Perspective::IS_SERVER) {
         if (!crypters->encrypter->SetKey(hkdf.server_write_key()) ||
             !crypters->encrypter->SetNoncePrefix(hkdf.server_write_iv()) ||
+            !crypters->encrypter->SetHeaderProtectionKey(
+                hkdf.server_hp_key()) ||
             !crypters->decrypter->SetKey(hkdf.client_write_key()) ||
-            !crypters->decrypter->SetNoncePrefix(hkdf.client_write_iv())) {
+            !crypters->decrypter->SetNoncePrefix(hkdf.client_write_iv()) ||
+            !crypters->decrypter->SetHeaderProtectionKey(
+                hkdf.client_hp_key())) {
           return false;
         }
       } else {
         if (!crypters->encrypter->SetKey(hkdf.client_write_key()) ||
             !crypters->encrypter->SetNoncePrefix(hkdf.client_write_iv()) ||
+            !crypters->encrypter->SetHeaderProtectionKey(
+                hkdf.client_hp_key()) ||
             !crypters->decrypter->SetKey(hkdf.server_write_key()) ||
-            !crypters->decrypter->SetNoncePrefix(hkdf.server_write_iv())) {
+            !crypters->decrypter->SetNoncePrefix(hkdf.server_write_iv()) ||
+            !crypters->decrypter->SetHeaderProtectionKey(
+                hkdf.server_hp_key())) {
           return false;
         }
       }
@@ -246,8 +258,10 @@
 
       if (!crypters->encrypter->SetKey(hkdf.client_write_key()) ||
           !crypters->encrypter->SetNoncePrefix(hkdf.client_write_iv()) ||
+          !crypters->encrypter->SetHeaderProtectionKey(hkdf.client_hp_key()) ||
           !crypters->decrypter->SetPreliminaryKey(hkdf.server_write_key()) ||
-          !crypters->decrypter->SetNoncePrefix(hkdf.server_write_iv())) {
+          !crypters->decrypter->SetNoncePrefix(hkdf.server_write_iv()) ||
+          !crypters->decrypter->SetHeaderProtectionKey(hkdf.server_hp_key())) {
         return false;
       }
       break;
@@ -265,8 +279,10 @@
           &nonce_prefix);
       if (!crypters->decrypter->SetKey(hkdf.client_write_key()) ||
           !crypters->decrypter->SetNoncePrefix(hkdf.client_write_iv()) ||
+          !crypters->decrypter->SetHeaderProtectionKey(hkdf.client_hp_key()) ||
           !crypters->encrypter->SetKey(key) ||
-          !crypters->encrypter->SetNoncePrefix(nonce_prefix)) {
+          !crypters->encrypter->SetNoncePrefix(nonce_prefix) ||
+          !crypters->encrypter->SetHeaderProtectionKey(hkdf.server_hp_key())) {
         return false;
       }
       break;
diff --git a/quic/core/crypto/quic_hkdf.cc b/quic/core/crypto/quic_hkdf.cc
index 3754cab..1bd9ad5 100644
--- a/quic/core/crypto/quic_hkdf.cc
+++ b/quic/core/crypto/quic_hkdf.cc
@@ -39,8 +39,8 @@
                    size_t server_iv_bytes_to_generate,
                    size_t subkey_secret_bytes_to_generate) {
   const size_t material_length =
-      client_key_bytes_to_generate + client_iv_bytes_to_generate +
-      server_key_bytes_to_generate + server_iv_bytes_to_generate +
+      2 * client_key_bytes_to_generate + client_iv_bytes_to_generate +
+      2 * server_key_bytes_to_generate + server_iv_bytes_to_generate +
       subkey_secret_bytes_to_generate;
   DCHECK_LT(material_length, kMaxKeyMaterialSize);
 
@@ -85,6 +85,19 @@
   if (subkey_secret_bytes_to_generate) {
     subkey_secret_ = QuicStringPiece(reinterpret_cast<char*>(&output_[j]),
                                      subkey_secret_bytes_to_generate);
+    j += subkey_secret_bytes_to_generate;
+  }
+  // Repeat client and server key bytes for header protection keys.
+  if (client_key_bytes_to_generate) {
+    client_hp_key_ = QuicStringPiece(reinterpret_cast<char*>(&output_[j]),
+                                     client_key_bytes_to_generate);
+    j += client_key_bytes_to_generate;
+  }
+
+  if (server_key_bytes_to_generate) {
+    server_hp_key_ = QuicStringPiece(reinterpret_cast<char*>(&output_[j]),
+                                     server_key_bytes_to_generate);
+    j += server_key_bytes_to_generate;
   }
 }
 
diff --git a/quic/core/crypto/quic_hkdf.h b/quic/core/crypto/quic_hkdf.h
index fb80f7b..c57b894 100644
--- a/quic/core/crypto/quic_hkdf.h
+++ b/quic/core/crypto/quic_hkdf.h
@@ -54,6 +54,8 @@
   QuicStringPiece server_write_key() const { return server_write_key_; }
   QuicStringPiece server_write_iv() const { return server_write_iv_; }
   QuicStringPiece subkey_secret() const { return subkey_secret_; }
+  QuicStringPiece client_hp_key() const { return client_hp_key_; }
+  QuicStringPiece server_hp_key() const { return server_hp_key_; }
 
  private:
   std::vector<uint8_t> output_;
@@ -63,6 +65,8 @@
   QuicStringPiece client_write_iv_;
   QuicStringPiece server_write_iv_;
   QuicStringPiece subkey_secret_;
+  QuicStringPiece client_hp_key_;
+  QuicStringPiece server_hp_key_;
 };
 
 }  // namespace quic