• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "quiche/quic/core/crypto/crypto_utils.h"
6 
7 #include <memory>
8 #include <string>
9 #include <utility>
10 
11 #include "absl/base/macros.h"
12 #include "absl/strings/str_cat.h"
13 #include "absl/strings/string_view.h"
14 #include "openssl/bytestring.h"
15 #include "openssl/hkdf.h"
16 #include "openssl/mem.h"
17 #include "openssl/sha.h"
18 #include "quiche/quic/core/crypto/aes_128_gcm_12_decrypter.h"
19 #include "quiche/quic/core/crypto/aes_128_gcm_12_encrypter.h"
20 #include "quiche/quic/core/crypto/aes_128_gcm_decrypter.h"
21 #include "quiche/quic/core/crypto/aes_128_gcm_encrypter.h"
22 #include "quiche/quic/core/crypto/crypto_handshake.h"
23 #include "quiche/quic/core/crypto/crypto_protocol.h"
24 #include "quiche/quic/core/crypto/null_decrypter.h"
25 #include "quiche/quic/core/crypto/null_encrypter.h"
26 #include "quiche/quic/core/crypto/quic_decrypter.h"
27 #include "quiche/quic/core/crypto/quic_encrypter.h"
28 #include "quiche/quic/core/crypto/quic_hkdf.h"
29 #include "quiche/quic/core/crypto/quic_random.h"
30 #include "quiche/quic/core/quic_connection_id.h"
31 #include "quiche/quic/core/quic_constants.h"
32 #include "quiche/quic/core/quic_data_writer.h"
33 #include "quiche/quic/core/quic_time.h"
34 #include "quiche/quic/core/quic_utils.h"
35 #include "quiche/quic/core/quic_versions.h"
36 #include "quiche/quic/platform/api/quic_bug_tracker.h"
37 #include "quiche/quic/platform/api/quic_logging.h"
38 #include "quiche/common/quiche_endian.h"
39 
40 namespace quic {
41 
42 namespace {
43 
44 // Implements the HKDF-Expand-Label function as defined in section 7.1 of RFC
45 // 8446. The HKDF-Expand-Label function takes 4 explicit arguments (Secret,
46 // Label, Context, and Length), as well as implicit PRF which is the hash
47 // function negotiated by TLS. Its use in QUIC (as needed by the QUIC stack,
48 // instead of as used internally by the TLS stack) is only for deriving initial
49 // secrets for obfuscation, for calculating packet protection keys and IVs from
50 // the corresponding packet protection secret and key update in the same quic
51 // session. None of these uses need a Context (a zero-length context is
52 // provided), so this argument is omitted here.
53 //
54 // The implicit PRF is explicitly passed into HkdfExpandLabel as |prf|; the
55 // Secret, Label, and Length are passed in as |secret|, |label|, and
56 // |out_len|, respectively. The resulting expanded secret is returned.
HkdfExpandLabel(const EVP_MD * prf,absl::Span<const uint8_t> secret,const std::string & label,size_t out_len)57 std::vector<uint8_t> HkdfExpandLabel(const EVP_MD* prf,
58                                      absl::Span<const uint8_t> secret,
59                                      const std::string& label, size_t out_len) {
60   bssl::ScopedCBB quic_hkdf_label;
61   CBB inner_label;
62   const char label_prefix[] = "tls13 ";
63   // 20 = size(u16) + size(u8) + len("tls13 ") +
64   //      max_len("client in", "server in", "quicv2 key", ... ) +
65   //      size(u8);
66   static const size_t max_quic_hkdf_label_length = 20;
67   if (!CBB_init(quic_hkdf_label.get(), max_quic_hkdf_label_length) ||
68       !CBB_add_u16(quic_hkdf_label.get(), out_len) ||
69       !CBB_add_u8_length_prefixed(quic_hkdf_label.get(), &inner_label) ||
70       !CBB_add_bytes(&inner_label,
71                      reinterpret_cast<const uint8_t*>(label_prefix),
72                      ABSL_ARRAYSIZE(label_prefix) - 1) ||
73       !CBB_add_bytes(&inner_label,
74                      reinterpret_cast<const uint8_t*>(label.data()),
75                      label.size()) ||
76       // Zero length |Context|.
77       !CBB_add_u8(quic_hkdf_label.get(), 0) ||
78       !CBB_flush(quic_hkdf_label.get())) {
79     QUIC_LOG(ERROR) << "Building HKDF label failed";
80     return std::vector<uint8_t>();
81   }
82   std::vector<uint8_t> out;
83   out.resize(out_len);
84   if (!HKDF_expand(out.data(), out_len, prf, secret.data(), secret.size(),
85                    CBB_data(quic_hkdf_label.get()),
86                    CBB_len(quic_hkdf_label.get()))) {
87     QUIC_LOG(ERROR) << "Running HKDF-Expand-Label failed";
88     return std::vector<uint8_t>();
89   }
90   return out;
91 }
92 
93 }  // namespace
94 
getLabelForVersion(const ParsedQuicVersion & version,const absl::string_view & predicate)95 const std::string getLabelForVersion(const ParsedQuicVersion& version,
96                                      const absl::string_view& predicate) {
97   static_assert(SupportedVersions().size() == 6u,
98                 "Supported versions out of sync with HKDF labels");
99   if (version == ParsedQuicVersion::V2Draft08()) {
100     return absl::StrCat("quicv2 ", predicate);
101   } else {
102     return absl::StrCat("quic ", predicate);
103   }
104 }
105 
InitializeCrypterSecrets(const EVP_MD * prf,const std::vector<uint8_t> & pp_secret,const ParsedQuicVersion & version,QuicCrypter * crypter)106 void CryptoUtils::InitializeCrypterSecrets(
107     const EVP_MD* prf, const std::vector<uint8_t>& pp_secret,
108     const ParsedQuicVersion& version, QuicCrypter* crypter) {
109   SetKeyAndIV(prf, pp_secret, version, crypter);
110   std::vector<uint8_t> header_protection_key = GenerateHeaderProtectionKey(
111       prf, pp_secret, version, crypter->GetKeySize());
112   crypter->SetHeaderProtectionKey(
113       absl::string_view(reinterpret_cast<char*>(header_protection_key.data()),
114                         header_protection_key.size()));
115 }
116 
SetKeyAndIV(const EVP_MD * prf,absl::Span<const uint8_t> pp_secret,const ParsedQuicVersion & version,QuicCrypter * crypter)117 void CryptoUtils::SetKeyAndIV(const EVP_MD* prf,
118                               absl::Span<const uint8_t> pp_secret,
119                               const ParsedQuicVersion& version,
120                               QuicCrypter* crypter) {
121   std::vector<uint8_t> key =
122       HkdfExpandLabel(prf, pp_secret, getLabelForVersion(version, "key"),
123                       crypter->GetKeySize());
124   std::vector<uint8_t> iv = HkdfExpandLabel(
125       prf, pp_secret, getLabelForVersion(version, "iv"), crypter->GetIVSize());
126   crypter->SetKey(
127       absl::string_view(reinterpret_cast<char*>(key.data()), key.size()));
128   crypter->SetIV(
129       absl::string_view(reinterpret_cast<char*>(iv.data()), iv.size()));
130 }
131 
GenerateHeaderProtectionKey(const EVP_MD * prf,absl::Span<const uint8_t> pp_secret,const ParsedQuicVersion & version,size_t out_len)132 std::vector<uint8_t> CryptoUtils::GenerateHeaderProtectionKey(
133     const EVP_MD* prf, absl::Span<const uint8_t> pp_secret,
134     const ParsedQuicVersion& version, size_t out_len) {
135   return HkdfExpandLabel(prf, pp_secret, getLabelForVersion(version, "hp"),
136                          out_len);
137 }
138 
GenerateNextKeyPhaseSecret(const EVP_MD * prf,const ParsedQuicVersion & version,const std::vector<uint8_t> & current_secret)139 std::vector<uint8_t> CryptoUtils::GenerateNextKeyPhaseSecret(
140     const EVP_MD* prf, const ParsedQuicVersion& version,
141     const std::vector<uint8_t>& current_secret) {
142   return HkdfExpandLabel(prf, current_secret, getLabelForVersion(version, "ku"),
143                          current_secret.size());
144 }
145 
146 namespace {
147 
148 // Salt from https://tools.ietf.org/html/draft-ietf-quic-tls-29#section-5.2
149 const uint8_t kDraft29InitialSalt[] = {0xaf, 0xbf, 0xec, 0x28, 0x99, 0x93, 0xd2,
150                                        0x4c, 0x9e, 0x97, 0x86, 0xf1, 0x9c, 0x61,
151                                        0x11, 0xe0, 0x43, 0x90, 0xa8, 0x99};
152 const uint8_t kRFCv1InitialSalt[] = {0x38, 0x76, 0x2c, 0xf7, 0xf5, 0x59, 0x34,
153                                      0xb3, 0x4d, 0x17, 0x9a, 0xe6, 0xa4, 0xc8,
154                                      0x0c, 0xad, 0xcc, 0xbb, 0x7f, 0x0a};
155 const uint8_t kV2Draft08InitialSalt[] = {
156     0x0d, 0xed, 0xe3, 0xde, 0xf7, 0x00, 0xa6, 0xdb, 0x81, 0x93,
157     0x81, 0xbe, 0x6e, 0x26, 0x9d, 0xcb, 0xf9, 0xbd, 0x2e, 0xd9,
158 };
159 
160 // Salts used by deployed versions of QUIC. When introducing a new version,
161 // generate a new salt by running `openssl rand -hex 20`.
162 
163 // Salt to use for initial obfuscators in version Q050.
164 const uint8_t kQ050Salt[] = {0x50, 0x45, 0x74, 0xef, 0xd0, 0x66, 0xfe,
165                              0x2f, 0x9d, 0x94, 0x5c, 0xfc, 0xdb, 0xd3,
166                              0xa7, 0xf0, 0xd3, 0xb5, 0x6b, 0x45};
167 // Salt to use for initial obfuscators in
168 // ParsedQuicVersion::ReservedForNegotiation().
169 const uint8_t kReservedForNegotiationSalt[] = {
170     0xf9, 0x64, 0xbf, 0x45, 0x3a, 0x1f, 0x1b, 0x80, 0xa5, 0xf8,
171     0x82, 0x03, 0x77, 0xd4, 0xaf, 0xca, 0x58, 0x0e, 0xe7, 0x43};
172 
InitialSaltForVersion(const ParsedQuicVersion & version,size_t * out_len)173 const uint8_t* InitialSaltForVersion(const ParsedQuicVersion& version,
174                                      size_t* out_len) {
175   static_assert(SupportedVersions().size() == 6u,
176                 "Supported versions out of sync with initial encryption salts");
177   if (version == ParsedQuicVersion::V2Draft08()) {
178     *out_len = ABSL_ARRAYSIZE(kV2Draft08InitialSalt);
179     return kV2Draft08InitialSalt;
180   } else if (version == ParsedQuicVersion::RFCv1()) {
181     *out_len = ABSL_ARRAYSIZE(kRFCv1InitialSalt);
182     return kRFCv1InitialSalt;
183   } else if (version == ParsedQuicVersion::Draft29()) {
184     *out_len = ABSL_ARRAYSIZE(kDraft29InitialSalt);
185     return kDraft29InitialSalt;
186   } else if (version == ParsedQuicVersion::Q050()) {
187     *out_len = ABSL_ARRAYSIZE(kQ050Salt);
188     return kQ050Salt;
189   } else if (version == ParsedQuicVersion::ReservedForNegotiation()) {
190     *out_len = ABSL_ARRAYSIZE(kReservedForNegotiationSalt);
191     return kReservedForNegotiationSalt;
192   }
193   QUIC_BUG(quic_bug_10699_1)
194       << "No initial obfuscation salt for version " << version;
195   *out_len = ABSL_ARRAYSIZE(kReservedForNegotiationSalt);
196   return kReservedForNegotiationSalt;
197 }
198 
199 const char kPreSharedKeyLabel[] = "QUIC PSK";
200 
201 // Retry Integrity Protection Keys and Nonces.
202 // https://tools.ietf.org/html/draft-ietf-quic-tls-29#section-5.8
203 // When introducing a new Google version, generate a new key by running
204 // `openssl rand -hex 16`.
205 const uint8_t kDraft29RetryIntegrityKey[] = {0xcc, 0xce, 0x18, 0x7e, 0xd0, 0x9a,
206                                              0x09, 0xd0, 0x57, 0x28, 0x15, 0x5a,
207                                              0x6c, 0xb9, 0x6b, 0xe1};
208 const uint8_t kDraft29RetryIntegrityNonce[] = {
209     0xe5, 0x49, 0x30, 0xf9, 0x7f, 0x21, 0x36, 0xf0, 0x53, 0x0a, 0x8c, 0x1c};
210 const uint8_t kRFCv1RetryIntegrityKey[] = {0xbe, 0x0c, 0x69, 0x0b, 0x9f, 0x66,
211                                            0x57, 0x5a, 0x1d, 0x76, 0x6b, 0x54,
212                                            0xe3, 0x68, 0xc8, 0x4e};
213 const uint8_t kRFCv1RetryIntegrityNonce[] = {
214     0x46, 0x15, 0x99, 0xd3, 0x5d, 0x63, 0x2b, 0xf2, 0x23, 0x98, 0x25, 0xbb};
215 const uint8_t kV2Draft08RetryIntegrityKey[] = {
216     0x8f, 0xb4, 0xb0, 0x1b, 0x56, 0xac, 0x48, 0xe2,
217     0x60, 0xfb, 0xcb, 0xce, 0xad, 0x7c, 0xcc, 0x92};
218 const uint8_t kV2Draft08RetryIntegrityNonce[] = {
219     0xd8, 0x69, 0x69, 0xbc, 0x2d, 0x7c, 0x6d, 0x99, 0x90, 0xef, 0xb0, 0x4a};
220 // Retry integrity key used by ParsedQuicVersion::ReservedForNegotiation().
221 const uint8_t kReservedForNegotiationRetryIntegrityKey[] = {
222     0xf2, 0xcd, 0x8f, 0xe0, 0x36, 0xd0, 0x25, 0x35,
223     0x03, 0xe6, 0x7c, 0x7b, 0xd2, 0x44, 0xca, 0xd9};
224 // When introducing a new Google version, generate a new nonce by running
225 // `openssl rand -hex 12`.
226 // Retry integrity nonce used by ParsedQuicVersion::ReservedForNegotiation().
227 const uint8_t kReservedForNegotiationRetryIntegrityNonce[] = {
228     0x35, 0x9f, 0x16, 0xd1, 0xed, 0x80, 0x90, 0x8e, 0xec, 0x85, 0xc4, 0xd6};
229 
RetryIntegrityKeysForVersion(const ParsedQuicVersion & version,absl::string_view * key,absl::string_view * nonce)230 bool RetryIntegrityKeysForVersion(const ParsedQuicVersion& version,
231                                   absl::string_view* key,
232                                   absl::string_view* nonce) {
233   static_assert(SupportedVersions().size() == 6u,
234                 "Supported versions out of sync with retry integrity keys");
235   if (!version.UsesTls()) {
236     QUIC_BUG(quic_bug_10699_2)
237         << "Attempted to get retry integrity keys for invalid version "
238         << version;
239     return false;
240   } else if (version == ParsedQuicVersion::V2Draft08()) {
241     *key = absl::string_view(
242         reinterpret_cast<const char*>(kV2Draft08RetryIntegrityKey),
243         ABSL_ARRAYSIZE(kV2Draft08RetryIntegrityKey));
244     *nonce = absl::string_view(
245         reinterpret_cast<const char*>(kV2Draft08RetryIntegrityNonce),
246         ABSL_ARRAYSIZE(kV2Draft08RetryIntegrityNonce));
247     return true;
248   } else if (version == ParsedQuicVersion::RFCv1()) {
249     *key = absl::string_view(
250         reinterpret_cast<const char*>(kRFCv1RetryIntegrityKey),
251         ABSL_ARRAYSIZE(kRFCv1RetryIntegrityKey));
252     *nonce = absl::string_view(
253         reinterpret_cast<const char*>(kRFCv1RetryIntegrityNonce),
254         ABSL_ARRAYSIZE(kRFCv1RetryIntegrityNonce));
255     return true;
256   } else if (version == ParsedQuicVersion::Draft29()) {
257     *key = absl::string_view(
258         reinterpret_cast<const char*>(kDraft29RetryIntegrityKey),
259         ABSL_ARRAYSIZE(kDraft29RetryIntegrityKey));
260     *nonce = absl::string_view(
261         reinterpret_cast<const char*>(kDraft29RetryIntegrityNonce),
262         ABSL_ARRAYSIZE(kDraft29RetryIntegrityNonce));
263     return true;
264   } else if (version == ParsedQuicVersion::ReservedForNegotiation()) {
265     *key = absl::string_view(
266         reinterpret_cast<const char*>(kReservedForNegotiationRetryIntegrityKey),
267         ABSL_ARRAYSIZE(kReservedForNegotiationRetryIntegrityKey));
268     *nonce = absl::string_view(
269         reinterpret_cast<const char*>(
270             kReservedForNegotiationRetryIntegrityNonce),
271         ABSL_ARRAYSIZE(kReservedForNegotiationRetryIntegrityNonce));
272     return true;
273   }
274   QUIC_BUG(quic_bug_10699_3)
275       << "Attempted to get retry integrity keys for version " << version;
276   return false;
277 }
278 
279 }  // namespace
280 
281 // static
CreateInitialObfuscators(Perspective perspective,ParsedQuicVersion version,QuicConnectionId connection_id,CrypterPair * crypters)282 void CryptoUtils::CreateInitialObfuscators(Perspective perspective,
283                                            ParsedQuicVersion version,
284                                            QuicConnectionId connection_id,
285                                            CrypterPair* crypters) {
286   QUIC_DLOG(INFO) << "Creating "
287                   << (perspective == Perspective::IS_CLIENT ? "client"
288                                                             : "server")
289                   << " crypters for version " << version << " with CID "
290                   << connection_id;
291   if (!version.UsesInitialObfuscators()) {
292     crypters->encrypter = std::make_unique<NullEncrypter>(perspective);
293     crypters->decrypter = std::make_unique<NullDecrypter>(perspective);
294     return;
295   }
296   QUIC_BUG_IF(quic_bug_12871_1, !QuicUtils::IsConnectionIdValidForVersion(
297                                     connection_id, version.transport_version))
298       << "CreateTlsInitialCrypters: attempted to use connection ID "
299       << connection_id << " which is invalid with version " << version;
300   const EVP_MD* hash = EVP_sha256();
301 
302   size_t salt_len;
303   const uint8_t* salt = InitialSaltForVersion(version, &salt_len);
304   std::vector<uint8_t> handshake_secret;
305   handshake_secret.resize(EVP_MAX_MD_SIZE);
306   size_t handshake_secret_len;
307   const bool hkdf_extract_success =
308       HKDF_extract(handshake_secret.data(), &handshake_secret_len, hash,
309                    reinterpret_cast<const uint8_t*>(connection_id.data()),
310                    connection_id.length(), salt, salt_len);
311   QUIC_BUG_IF(quic_bug_12871_2, !hkdf_extract_success)
312       << "HKDF_extract failed when creating initial crypters";
313   handshake_secret.resize(handshake_secret_len);
314 
315   const std::string client_label = "client in";
316   const std::string server_label = "server in";
317   std::string encryption_label, decryption_label;
318   if (perspective == Perspective::IS_CLIENT) {
319     encryption_label = client_label;
320     decryption_label = server_label;
321   } else {
322     encryption_label = server_label;
323     decryption_label = client_label;
324   }
325   std::vector<uint8_t> encryption_secret = HkdfExpandLabel(
326       hash, handshake_secret, encryption_label, EVP_MD_size(hash));
327   crypters->encrypter = std::make_unique<Aes128GcmEncrypter>();
328   InitializeCrypterSecrets(hash, encryption_secret, version,
329                            crypters->encrypter.get());
330 
331   std::vector<uint8_t> decryption_secret = HkdfExpandLabel(
332       hash, handshake_secret, decryption_label, EVP_MD_size(hash));
333   crypters->decrypter = std::make_unique<Aes128GcmDecrypter>();
334   InitializeCrypterSecrets(hash, decryption_secret, version,
335                            crypters->decrypter.get());
336 }
337 
338 // static
ValidateRetryIntegrityTag(ParsedQuicVersion version,QuicConnectionId original_connection_id,absl::string_view retry_without_tag,absl::string_view integrity_tag)339 bool CryptoUtils::ValidateRetryIntegrityTag(
340     ParsedQuicVersion version, QuicConnectionId original_connection_id,
341     absl::string_view retry_without_tag, absl::string_view integrity_tag) {
342   unsigned char computed_integrity_tag[kRetryIntegrityTagLength];
343   if (integrity_tag.length() != ABSL_ARRAYSIZE(computed_integrity_tag)) {
344     QUIC_BUG(quic_bug_10699_4)
345         << "Invalid retry integrity tag length " << integrity_tag.length();
346     return false;
347   }
348   char retry_pseudo_packet[kMaxIncomingPacketSize + 256];
349   QuicDataWriter writer(ABSL_ARRAYSIZE(retry_pseudo_packet),
350                         retry_pseudo_packet);
351   if (!writer.WriteLengthPrefixedConnectionId(original_connection_id)) {
352     QUIC_BUG(quic_bug_10699_5)
353         << "Failed to write original connection ID in retry pseudo packet";
354     return false;
355   }
356   if (!writer.WriteStringPiece(retry_without_tag)) {
357     QUIC_BUG(quic_bug_10699_6)
358         << "Failed to write retry without tag in retry pseudo packet";
359     return false;
360   }
361   absl::string_view key;
362   absl::string_view nonce;
363   if (!RetryIntegrityKeysForVersion(version, &key, &nonce)) {
364     // RetryIntegrityKeysForVersion already logs failures.
365     return false;
366   }
367   Aes128GcmEncrypter crypter;
368   crypter.SetKey(key);
369   absl::string_view associated_data(writer.data(), writer.length());
370   absl::string_view plaintext;  // Plaintext is empty.
371   if (!crypter.Encrypt(nonce, associated_data, plaintext,
372                        computed_integrity_tag)) {
373     QUIC_BUG(quic_bug_10699_7) << "Failed to compute retry integrity tag";
374     return false;
375   }
376   if (CRYPTO_memcmp(computed_integrity_tag, integrity_tag.data(),
377                     ABSL_ARRAYSIZE(computed_integrity_tag)) != 0) {
378     QUIC_DLOG(ERROR) << "Failed to validate retry integrity tag";
379     return false;
380   }
381   return true;
382 }
383 
384 // static
GenerateNonce(QuicWallTime now,QuicRandom * random_generator,absl::string_view orbit,std::string * nonce)385 void CryptoUtils::GenerateNonce(QuicWallTime now, QuicRandom* random_generator,
386                                 absl::string_view orbit, std::string* nonce) {
387   // a 4-byte timestamp + 28 random bytes.
388   nonce->reserve(kNonceSize);
389   nonce->resize(kNonceSize);
390 
391   uint32_t gmt_unix_time = static_cast<uint32_t>(now.ToUNIXSeconds());
392   // The time in the nonce must be encoded in big-endian because the
393   // strike-register depends on the nonces being ordered by time.
394   (*nonce)[0] = static_cast<char>(gmt_unix_time >> 24);
395   (*nonce)[1] = static_cast<char>(gmt_unix_time >> 16);
396   (*nonce)[2] = static_cast<char>(gmt_unix_time >> 8);
397   (*nonce)[3] = static_cast<char>(gmt_unix_time);
398   size_t bytes_written = 4;
399 
400   if (orbit.size() == 8) {
401     memcpy(&(*nonce)[bytes_written], orbit.data(), orbit.size());
402     bytes_written += orbit.size();
403   }
404 
405   random_generator->RandBytes(&(*nonce)[bytes_written],
406                               kNonceSize - bytes_written);
407 }
408 
409 // static
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)410 bool CryptoUtils::DeriveKeys(
411     const ParsedQuicVersion& version, absl::string_view premaster_secret,
412     QuicTag aead, absl::string_view client_nonce,
413     absl::string_view server_nonce, absl::string_view pre_shared_key,
414     const std::string& hkdf_input, Perspective perspective,
415     Diversification diversification, CrypterPair* crypters,
416     std::string* subkey_secret) {
417   // If the connection is using PSK, concatenate it with the pre-master secret.
418   std::unique_ptr<char[]> psk_premaster_secret;
419   if (!pre_shared_key.empty()) {
420     const absl::string_view label(kPreSharedKeyLabel);
421     const size_t psk_premaster_secret_size = label.size() + 1 +
422                                              pre_shared_key.size() + 8 +
423                                              premaster_secret.size() + 8;
424 
425     psk_premaster_secret = std::make_unique<char[]>(psk_premaster_secret_size);
426     QuicDataWriter writer(psk_premaster_secret_size, psk_premaster_secret.get(),
427                           quiche::HOST_BYTE_ORDER);
428 
429     if (!writer.WriteStringPiece(label) || !writer.WriteUInt8(0) ||
430         !writer.WriteStringPiece(pre_shared_key) ||
431         !writer.WriteUInt64(pre_shared_key.size()) ||
432         !writer.WriteStringPiece(premaster_secret) ||
433         !writer.WriteUInt64(premaster_secret.size()) ||
434         writer.remaining() != 0) {
435       return false;
436     }
437 
438     premaster_secret = absl::string_view(psk_premaster_secret.get(),
439                                          psk_premaster_secret_size);
440   }
441 
442   crypters->encrypter = QuicEncrypter::Create(version, aead);
443   crypters->decrypter = QuicDecrypter::Create(version, aead);
444 
445   size_t key_bytes = crypters->encrypter->GetKeySize();
446   size_t nonce_prefix_bytes = crypters->encrypter->GetNoncePrefixSize();
447   if (version.UsesInitialObfuscators()) {
448     nonce_prefix_bytes = crypters->encrypter->GetIVSize();
449   }
450   size_t subkey_secret_bytes =
451       subkey_secret == nullptr ? 0 : premaster_secret.length();
452 
453   absl::string_view nonce = client_nonce;
454   std::string nonce_storage;
455   if (!server_nonce.empty()) {
456     nonce_storage = std::string(client_nonce) + std::string(server_nonce);
457     nonce = nonce_storage;
458   }
459 
460   QuicHKDF hkdf(premaster_secret, nonce, hkdf_input, key_bytes,
461                 nonce_prefix_bytes, subkey_secret_bytes);
462 
463   // Key derivation depends on the key diversification method being employed.
464   // both the client and the server support never doing key diversification.
465   // The server also supports immediate diversification, and the client
466   // supports pending diversification.
467   switch (diversification.mode()) {
468     case Diversification::NEVER: {
469       if (perspective == Perspective::IS_SERVER) {
470         if (!crypters->encrypter->SetKey(hkdf.server_write_key()) ||
471             !crypters->encrypter->SetNoncePrefixOrIV(version,
472                                                      hkdf.server_write_iv()) ||
473             !crypters->encrypter->SetHeaderProtectionKey(
474                 hkdf.server_hp_key()) ||
475             !crypters->decrypter->SetKey(hkdf.client_write_key()) ||
476             !crypters->decrypter->SetNoncePrefixOrIV(version,
477                                                      hkdf.client_write_iv()) ||
478             !crypters->decrypter->SetHeaderProtectionKey(
479                 hkdf.client_hp_key())) {
480           return false;
481         }
482       } else {
483         if (!crypters->encrypter->SetKey(hkdf.client_write_key()) ||
484             !crypters->encrypter->SetNoncePrefixOrIV(version,
485                                                      hkdf.client_write_iv()) ||
486             !crypters->encrypter->SetHeaderProtectionKey(
487                 hkdf.client_hp_key()) ||
488             !crypters->decrypter->SetKey(hkdf.server_write_key()) ||
489             !crypters->decrypter->SetNoncePrefixOrIV(version,
490                                                      hkdf.server_write_iv()) ||
491             !crypters->decrypter->SetHeaderProtectionKey(
492                 hkdf.server_hp_key())) {
493           return false;
494         }
495       }
496       break;
497     }
498     case Diversification::PENDING: {
499       if (perspective == Perspective::IS_SERVER) {
500         QUIC_BUG(quic_bug_10699_8)
501             << "Pending diversification is only for clients.";
502         return false;
503       }
504 
505       if (!crypters->encrypter->SetKey(hkdf.client_write_key()) ||
506           !crypters->encrypter->SetNoncePrefixOrIV(version,
507                                                    hkdf.client_write_iv()) ||
508           !crypters->encrypter->SetHeaderProtectionKey(hkdf.client_hp_key()) ||
509           !crypters->decrypter->SetPreliminaryKey(hkdf.server_write_key()) ||
510           !crypters->decrypter->SetNoncePrefixOrIV(version,
511                                                    hkdf.server_write_iv()) ||
512           !crypters->decrypter->SetHeaderProtectionKey(hkdf.server_hp_key())) {
513         return false;
514       }
515       break;
516     }
517     case Diversification::NOW: {
518       if (perspective == Perspective::IS_CLIENT) {
519         QUIC_BUG(quic_bug_10699_9)
520             << "Immediate diversification is only for servers.";
521         return false;
522       }
523 
524       std::string key, nonce_prefix;
525       QuicDecrypter::DiversifyPreliminaryKey(
526           hkdf.server_write_key(), hkdf.server_write_iv(),
527           *diversification.nonce(), key_bytes, nonce_prefix_bytes, &key,
528           &nonce_prefix);
529       if (!crypters->decrypter->SetKey(hkdf.client_write_key()) ||
530           !crypters->decrypter->SetNoncePrefixOrIV(version,
531                                                    hkdf.client_write_iv()) ||
532           !crypters->decrypter->SetHeaderProtectionKey(hkdf.client_hp_key()) ||
533           !crypters->encrypter->SetKey(key) ||
534           !crypters->encrypter->SetNoncePrefixOrIV(version, nonce_prefix) ||
535           !crypters->encrypter->SetHeaderProtectionKey(hkdf.server_hp_key())) {
536         return false;
537       }
538       break;
539     }
540     default:
541       QUICHE_DCHECK(false);
542   }
543 
544   if (subkey_secret != nullptr) {
545     *subkey_secret = std::string(hkdf.subkey_secret());
546   }
547 
548   return true;
549 }
550 
551 // static
ComputeLeafCertHash(absl::string_view cert)552 uint64_t CryptoUtils::ComputeLeafCertHash(absl::string_view cert) {
553   return QuicUtils::FNV1a_64_Hash(cert);
554 }
555 
ValidateServerHello(const CryptoHandshakeMessage & server_hello,const ParsedQuicVersionVector & negotiated_versions,std::string * error_details)556 QuicErrorCode CryptoUtils::ValidateServerHello(
557     const CryptoHandshakeMessage& server_hello,
558     const ParsedQuicVersionVector& negotiated_versions,
559     std::string* error_details) {
560   QUICHE_DCHECK(error_details != nullptr);
561 
562   if (server_hello.tag() != kSHLO) {
563     *error_details = "Bad tag";
564     return QUIC_INVALID_CRYPTO_MESSAGE_TYPE;
565   }
566 
567   QuicVersionLabelVector supported_version_labels;
568   if (server_hello.GetVersionLabelList(kVER, &supported_version_labels) !=
569       QUIC_NO_ERROR) {
570     *error_details = "server hello missing version list";
571     return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
572   }
573 
574   return ValidateServerHelloVersions(supported_version_labels,
575                                      negotiated_versions, error_details);
576 }
577 
ValidateServerHelloVersions(const QuicVersionLabelVector & server_versions,const ParsedQuicVersionVector & negotiated_versions,std::string * error_details)578 QuicErrorCode CryptoUtils::ValidateServerHelloVersions(
579     const QuicVersionLabelVector& server_versions,
580     const ParsedQuicVersionVector& negotiated_versions,
581     std::string* error_details) {
582   if (!negotiated_versions.empty()) {
583     bool mismatch = server_versions.size() != negotiated_versions.size();
584     for (size_t i = 0; i < server_versions.size() && !mismatch; ++i) {
585       mismatch =
586           server_versions[i] != CreateQuicVersionLabel(negotiated_versions[i]);
587     }
588     // The server sent a list of supported versions, and the connection
589     // reports that there was a version negotiation during the handshake.
590     // Ensure that these two lists are identical.
591     if (mismatch) {
592       *error_details = absl::StrCat(
593           "Downgrade attack detected: ServerVersions(", server_versions.size(),
594           ")[", QuicVersionLabelVectorToString(server_versions, ",", 30),
595           "] NegotiatedVersions(", negotiated_versions.size(), ")[",
596           ParsedQuicVersionVectorToString(negotiated_versions, ",", 30), "]");
597       return QUIC_VERSION_NEGOTIATION_MISMATCH;
598     }
599   }
600   return QUIC_NO_ERROR;
601 }
602 
ValidateClientHello(const CryptoHandshakeMessage & client_hello,ParsedQuicVersion version,const ParsedQuicVersionVector & supported_versions,std::string * error_details)603 QuicErrorCode CryptoUtils::ValidateClientHello(
604     const CryptoHandshakeMessage& client_hello, ParsedQuicVersion version,
605     const ParsedQuicVersionVector& supported_versions,
606     std::string* error_details) {
607   if (client_hello.tag() != kCHLO) {
608     *error_details = "Bad tag";
609     return QUIC_INVALID_CRYPTO_MESSAGE_TYPE;
610   }
611 
612   // If the client's preferred version is not the version we are currently
613   // speaking, then the client went through a version negotiation.  In this
614   // case, we need to make sure that we actually do not support this version
615   // and that it wasn't a downgrade attack.
616   QuicVersionLabel client_version_label;
617   if (client_hello.GetVersionLabel(kVER, &client_version_label) !=
618       QUIC_NO_ERROR) {
619     *error_details = "client hello missing version list";
620     return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
621   }
622   return ValidateClientHelloVersion(client_version_label, version,
623                                     supported_versions, error_details);
624 }
625 
ValidateClientHelloVersion(QuicVersionLabel client_version,ParsedQuicVersion connection_version,const ParsedQuicVersionVector & supported_versions,std::string * error_details)626 QuicErrorCode CryptoUtils::ValidateClientHelloVersion(
627     QuicVersionLabel client_version, ParsedQuicVersion connection_version,
628     const ParsedQuicVersionVector& supported_versions,
629     std::string* error_details) {
630   if (client_version != CreateQuicVersionLabel(connection_version)) {
631     // Check to see if |client_version| is actually on the supported versions
632     // list. If not, the server doesn't support that version and it's not a
633     // downgrade attack.
634     for (size_t i = 0; i < supported_versions.size(); ++i) {
635       if (client_version == CreateQuicVersionLabel(supported_versions[i])) {
636         *error_details = absl::StrCat(
637             "Downgrade attack detected: ClientVersion[",
638             QuicVersionLabelToString(client_version), "] ConnectionVersion[",
639             ParsedQuicVersionToString(connection_version),
640             "] SupportedVersions(", supported_versions.size(), ")[",
641             ParsedQuicVersionVectorToString(supported_versions, ",", 30), "]");
642         return QUIC_VERSION_NEGOTIATION_MISMATCH;
643       }
644     }
645   }
646   return QUIC_NO_ERROR;
647 }
648 
649 // static
ValidateChosenVersion(const QuicVersionLabel & version_information_chosen_version,const ParsedQuicVersion & session_version,std::string * error_details)650 bool CryptoUtils::ValidateChosenVersion(
651     const QuicVersionLabel& version_information_chosen_version,
652     const ParsedQuicVersion& session_version, std::string* error_details) {
653   if (version_information_chosen_version !=
654       CreateQuicVersionLabel(session_version)) {
655     *error_details = absl::StrCat(
656         "Detected version mismatch: version_information contained ",
657         QuicVersionLabelToString(version_information_chosen_version),
658         " instead of ", ParsedQuicVersionToString(session_version));
659     return false;
660   }
661   return true;
662 }
663 
664 // static
ValidateServerVersions(const QuicVersionLabelVector & version_information_other_versions,const ParsedQuicVersion & session_version,const ParsedQuicVersionVector & client_original_supported_versions,std::string * error_details)665 bool CryptoUtils::ValidateServerVersions(
666     const QuicVersionLabelVector& version_information_other_versions,
667     const ParsedQuicVersion& session_version,
668     const ParsedQuicVersionVector& client_original_supported_versions,
669     std::string* error_details) {
670   if (client_original_supported_versions.empty()) {
671     // We did not receive a version negotiation packet.
672     return true;
673   }
674   // Parse the server's other versions.
675   ParsedQuicVersionVector parsed_other_versions =
676       ParseQuicVersionLabelVector(version_information_other_versions);
677   // Find the first version that we originally supported that is listed in the
678   // server's other versions.
679   ParsedQuicVersion expected_version = ParsedQuicVersion::Unsupported();
680   for (const ParsedQuicVersion& client_version :
681        client_original_supported_versions) {
682     if (std::find(parsed_other_versions.begin(), parsed_other_versions.end(),
683                   client_version) != parsed_other_versions.end()) {
684       expected_version = client_version;
685       break;
686     }
687   }
688   if (expected_version != session_version) {
689     *error_details = absl::StrCat(
690         "Downgrade attack detected: used ",
691         ParsedQuicVersionToString(session_version), " but ServerVersions(",
692         version_information_other_versions.size(), ")[",
693         QuicVersionLabelVectorToString(version_information_other_versions, ",",
694                                        30),
695         "] ClientOriginalVersions(", client_original_supported_versions.size(),
696         ")[",
697         ParsedQuicVersionVectorToString(client_original_supported_versions, ",",
698                                         30),
699         "]");
700     return false;
701   }
702   return true;
703 }
704 
705 #define RETURN_STRING_LITERAL(x) \
706   case x:                        \
707     return #x
708 
709 // Returns the name of the HandshakeFailureReason as a char*
710 // static
HandshakeFailureReasonToString(HandshakeFailureReason reason)711 const char* CryptoUtils::HandshakeFailureReasonToString(
712     HandshakeFailureReason reason) {
713   switch (reason) {
714     RETURN_STRING_LITERAL(HANDSHAKE_OK);
715     RETURN_STRING_LITERAL(CLIENT_NONCE_UNKNOWN_FAILURE);
716     RETURN_STRING_LITERAL(CLIENT_NONCE_INVALID_FAILURE);
717     RETURN_STRING_LITERAL(CLIENT_NONCE_NOT_UNIQUE_FAILURE);
718     RETURN_STRING_LITERAL(CLIENT_NONCE_INVALID_ORBIT_FAILURE);
719     RETURN_STRING_LITERAL(CLIENT_NONCE_INVALID_TIME_FAILURE);
720     RETURN_STRING_LITERAL(CLIENT_NONCE_STRIKE_REGISTER_TIMEOUT);
721     RETURN_STRING_LITERAL(CLIENT_NONCE_STRIKE_REGISTER_FAILURE);
722 
723     RETURN_STRING_LITERAL(SERVER_NONCE_DECRYPTION_FAILURE);
724     RETURN_STRING_LITERAL(SERVER_NONCE_INVALID_FAILURE);
725     RETURN_STRING_LITERAL(SERVER_NONCE_NOT_UNIQUE_FAILURE);
726     RETURN_STRING_LITERAL(SERVER_NONCE_INVALID_TIME_FAILURE);
727     RETURN_STRING_LITERAL(SERVER_NONCE_REQUIRED_FAILURE);
728 
729     RETURN_STRING_LITERAL(SERVER_CONFIG_INCHOATE_HELLO_FAILURE);
730     RETURN_STRING_LITERAL(SERVER_CONFIG_UNKNOWN_CONFIG_FAILURE);
731 
732     RETURN_STRING_LITERAL(SOURCE_ADDRESS_TOKEN_INVALID_FAILURE);
733     RETURN_STRING_LITERAL(SOURCE_ADDRESS_TOKEN_DECRYPTION_FAILURE);
734     RETURN_STRING_LITERAL(SOURCE_ADDRESS_TOKEN_PARSE_FAILURE);
735     RETURN_STRING_LITERAL(SOURCE_ADDRESS_TOKEN_DIFFERENT_IP_ADDRESS_FAILURE);
736     RETURN_STRING_LITERAL(SOURCE_ADDRESS_TOKEN_CLOCK_SKEW_FAILURE);
737     RETURN_STRING_LITERAL(SOURCE_ADDRESS_TOKEN_EXPIRED_FAILURE);
738 
739     RETURN_STRING_LITERAL(INVALID_EXPECTED_LEAF_CERTIFICATE);
740     RETURN_STRING_LITERAL(MAX_FAILURE_REASON);
741   }
742   // Return a default value so that we return this when |reason| doesn't match
743   // any HandshakeFailureReason.. This can happen when the message by the peer
744   // (attacker) has invalid reason.
745   return "INVALID_HANDSHAKE_FAILURE_REASON";
746 }
747 
748 #undef RETURN_STRING_LITERAL  // undef for jumbo builds
749 
750 // static
EarlyDataReasonToString(ssl_early_data_reason_t reason)751 std::string CryptoUtils::EarlyDataReasonToString(
752     ssl_early_data_reason_t reason) {
753   const char* reason_string = SSL_early_data_reason_string(reason);
754   if (reason_string != nullptr) {
755     return std::string("ssl_early_data_") + reason_string;
756   }
757   QUIC_BUG_IF(quic_bug_12871_3,
758               reason < 0 || reason > ssl_early_data_reason_max_value)
759       << "Unknown ssl_early_data_reason_t " << reason;
760   return "unknown ssl_early_data_reason_t";
761 }
762 
763 // static
HashHandshakeMessage(const CryptoHandshakeMessage & message,Perspective)764 std::string CryptoUtils::HashHandshakeMessage(
765     const CryptoHandshakeMessage& message, Perspective /*perspective*/) {
766   std::string output;
767   const QuicData& serialized = message.GetSerialized();
768   uint8_t digest[SHA256_DIGEST_LENGTH];
769   SHA256(reinterpret_cast<const uint8_t*>(serialized.data()),
770          serialized.length(), digest);
771   output.assign(reinterpret_cast<const char*>(digest), sizeof(digest));
772   return output;
773 }
774 
775 // static
GetSSLCapabilities(const SSL * ssl,bssl::UniquePtr<uint8_t> * capabilities,size_t * capabilities_len)776 bool CryptoUtils::GetSSLCapabilities(const SSL* ssl,
777                                      bssl::UniquePtr<uint8_t>* capabilities,
778                                      size_t* capabilities_len) {
779   uint8_t* buffer;
780   bssl::ScopedCBB cbb;
781 
782   if (!CBB_init(cbb.get(), 128) ||
783       !SSL_serialize_capabilities(ssl, cbb.get()) ||
784       !CBB_finish(cbb.get(), &buffer, capabilities_len)) {
785     return false;
786   }
787 
788   *capabilities = bssl::UniquePtr<uint8_t>(buffer);
789   return true;
790 }
791 
792 // static
GenerateProofPayloadToBeSigned(absl::string_view chlo_hash,absl::string_view server_config)793 absl::optional<std::string> CryptoUtils::GenerateProofPayloadToBeSigned(
794     absl::string_view chlo_hash, absl::string_view server_config) {
795   size_t payload_size = sizeof(kProofSignatureLabel) + sizeof(uint32_t) +
796                         chlo_hash.size() + server_config.size();
797   std::string payload;
798   payload.resize(payload_size);
799   QuicDataWriter payload_writer(payload_size, payload.data(),
800                                 quiche::Endianness::HOST_BYTE_ORDER);
801   bool success = payload_writer.WriteBytes(kProofSignatureLabel,
802                                            sizeof(kProofSignatureLabel)) &&
803                  payload_writer.WriteUInt32(chlo_hash.size()) &&
804                  payload_writer.WriteStringPiece(chlo_hash) &&
805                  payload_writer.WriteStringPiece(server_config);
806   if (!success) {
807     return absl::nullopt;
808   }
809   return payload;
810 }
811 
812 }  // namespace quic
813