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;