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 {