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() == 4u,
98 "Supported versions out of sync with HKDF labels");
99 if (version == ParsedQuicVersion::RFCv2()) {
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 kRFCv2InitialSalt[] = {
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
164 // ParsedQuicVersion::ReservedForNegotiation().
165 const uint8_t kReservedForNegotiationSalt[] = {
166 0xf9, 0x64, 0xbf, 0x45, 0x3a, 0x1f, 0x1b, 0x80, 0xa5, 0xf8,
167 0x82, 0x03, 0x77, 0xd4, 0xaf, 0xca, 0x58, 0x0e, 0xe7, 0x43};
168
InitialSaltForVersion(const ParsedQuicVersion & version,size_t * out_len)169 const uint8_t* InitialSaltForVersion(const ParsedQuicVersion& version,
170 size_t* out_len) {
171 static_assert(SupportedVersions().size() == 4u,
172 "Supported versions out of sync with initial encryption salts");
173 if (version == ParsedQuicVersion::RFCv2()) {
174 *out_len = ABSL_ARRAYSIZE(kRFCv2InitialSalt);
175 return kRFCv2InitialSalt;
176 } else if (version == ParsedQuicVersion::RFCv1()) {
177 *out_len = ABSL_ARRAYSIZE(kRFCv1InitialSalt);
178 return kRFCv1InitialSalt;
179 } else if (version == ParsedQuicVersion::Draft29()) {
180 *out_len = ABSL_ARRAYSIZE(kDraft29InitialSalt);
181 return kDraft29InitialSalt;
182 } else if (version == ParsedQuicVersion::ReservedForNegotiation()) {
183 *out_len = ABSL_ARRAYSIZE(kReservedForNegotiationSalt);
184 return kReservedForNegotiationSalt;
185 }
186 QUIC_BUG(quic_bug_10699_1)
187 << "No initial obfuscation salt for version " << version;
188 *out_len = ABSL_ARRAYSIZE(kReservedForNegotiationSalt);
189 return kReservedForNegotiationSalt;
190 }
191
192 const char kPreSharedKeyLabel[] = "QUIC PSK";
193
194 // Retry Integrity Protection Keys and Nonces.
195 // https://tools.ietf.org/html/draft-ietf-quic-tls-29#section-5.8
196 // When introducing a new Google version, generate a new key by running
197 // `openssl rand -hex 16`.
198 const uint8_t kDraft29RetryIntegrityKey[] = {0xcc, 0xce, 0x18, 0x7e, 0xd0, 0x9a,
199 0x09, 0xd0, 0x57, 0x28, 0x15, 0x5a,
200 0x6c, 0xb9, 0x6b, 0xe1};
201 const uint8_t kDraft29RetryIntegrityNonce[] = {
202 0xe5, 0x49, 0x30, 0xf9, 0x7f, 0x21, 0x36, 0xf0, 0x53, 0x0a, 0x8c, 0x1c};
203 const uint8_t kRFCv1RetryIntegrityKey[] = {0xbe, 0x0c, 0x69, 0x0b, 0x9f, 0x66,
204 0x57, 0x5a, 0x1d, 0x76, 0x6b, 0x54,
205 0xe3, 0x68, 0xc8, 0x4e};
206 const uint8_t kRFCv1RetryIntegrityNonce[] = {
207 0x46, 0x15, 0x99, 0xd3, 0x5d, 0x63, 0x2b, 0xf2, 0x23, 0x98, 0x25, 0xbb};
208 const uint8_t kRFCv2RetryIntegrityKey[] = {0x8f, 0xb4, 0xb0, 0x1b, 0x56, 0xac,
209 0x48, 0xe2, 0x60, 0xfb, 0xcb, 0xce,
210 0xad, 0x7c, 0xcc, 0x92};
211 const uint8_t kRFCv2RetryIntegrityNonce[] = {
212 0xd8, 0x69, 0x69, 0xbc, 0x2d, 0x7c, 0x6d, 0x99, 0x90, 0xef, 0xb0, 0x4a};
213 // Retry integrity key used by ParsedQuicVersion::ReservedForNegotiation().
214 const uint8_t kReservedForNegotiationRetryIntegrityKey[] = {
215 0xf2, 0xcd, 0x8f, 0xe0, 0x36, 0xd0, 0x25, 0x35,
216 0x03, 0xe6, 0x7c, 0x7b, 0xd2, 0x44, 0xca, 0xd9};
217 // When introducing a new Google version, generate a new nonce by running
218 // `openssl rand -hex 12`.
219 // Retry integrity nonce used by ParsedQuicVersion::ReservedForNegotiation().
220 const uint8_t kReservedForNegotiationRetryIntegrityNonce[] = {
221 0x35, 0x9f, 0x16, 0xd1, 0xed, 0x80, 0x90, 0x8e, 0xec, 0x85, 0xc4, 0xd6};
222
RetryIntegrityKeysForVersion(const ParsedQuicVersion & version,absl::string_view * key,absl::string_view * nonce)223 bool RetryIntegrityKeysForVersion(const ParsedQuicVersion& version,
224 absl::string_view* key,
225 absl::string_view* nonce) {
226 static_assert(SupportedVersions().size() == 4u,
227 "Supported versions out of sync with retry integrity keys");
228 if (!version.UsesTls()) {
229 QUIC_BUG(quic_bug_10699_2)
230 << "Attempted to get retry integrity keys for invalid version "
231 << version;
232 return false;
233 } else if (version == ParsedQuicVersion::RFCv2()) {
234 *key = absl::string_view(
235 reinterpret_cast<const char*>(kRFCv2RetryIntegrityKey),
236 ABSL_ARRAYSIZE(kRFCv2RetryIntegrityKey));
237 *nonce = absl::string_view(
238 reinterpret_cast<const char*>(kRFCv2RetryIntegrityNonce),
239 ABSL_ARRAYSIZE(kRFCv2RetryIntegrityNonce));
240 return true;
241 } else if (version == ParsedQuicVersion::RFCv1()) {
242 *key = absl::string_view(
243 reinterpret_cast<const char*>(kRFCv1RetryIntegrityKey),
244 ABSL_ARRAYSIZE(kRFCv1RetryIntegrityKey));
245 *nonce = absl::string_view(
246 reinterpret_cast<const char*>(kRFCv1RetryIntegrityNonce),
247 ABSL_ARRAYSIZE(kRFCv1RetryIntegrityNonce));
248 return true;
249 } else if (version == ParsedQuicVersion::Draft29()) {
250 *key = absl::string_view(
251 reinterpret_cast<const char*>(kDraft29RetryIntegrityKey),
252 ABSL_ARRAYSIZE(kDraft29RetryIntegrityKey));
253 *nonce = absl::string_view(
254 reinterpret_cast<const char*>(kDraft29RetryIntegrityNonce),
255 ABSL_ARRAYSIZE(kDraft29RetryIntegrityNonce));
256 return true;
257 } else if (version == ParsedQuicVersion::ReservedForNegotiation()) {
258 *key = absl::string_view(
259 reinterpret_cast<const char*>(kReservedForNegotiationRetryIntegrityKey),
260 ABSL_ARRAYSIZE(kReservedForNegotiationRetryIntegrityKey));
261 *nonce = absl::string_view(
262 reinterpret_cast<const char*>(
263 kReservedForNegotiationRetryIntegrityNonce),
264 ABSL_ARRAYSIZE(kReservedForNegotiationRetryIntegrityNonce));
265 return true;
266 }
267 QUIC_BUG(quic_bug_10699_3)
268 << "Attempted to get retry integrity keys for version " << version;
269 return false;
270 }
271
272 } // namespace
273
274 // static
CreateInitialObfuscators(Perspective perspective,ParsedQuicVersion version,QuicConnectionId connection_id,CrypterPair * crypters)275 void CryptoUtils::CreateInitialObfuscators(Perspective perspective,
276 ParsedQuicVersion version,
277 QuicConnectionId connection_id,
278 CrypterPair* crypters) {
279 QUIC_DLOG(INFO) << "Creating "
280 << (perspective == Perspective::IS_CLIENT ? "client"
281 : "server")
282 << " crypters for version " << version << " with CID "
283 << connection_id;
284 if (!version.UsesInitialObfuscators()) {
285 crypters->encrypter = std::make_unique<NullEncrypter>(perspective);
286 crypters->decrypter = std::make_unique<NullDecrypter>(perspective);
287 return;
288 }
289 QUIC_BUG_IF(quic_bug_12871_1, !QuicUtils::IsConnectionIdValidForVersion(
290 connection_id, version.transport_version))
291 << "CreateTlsInitialCrypters: attempted to use connection ID "
292 << connection_id << " which is invalid with version " << version;
293 const EVP_MD* hash = EVP_sha256();
294
295 size_t salt_len;
296 const uint8_t* salt = InitialSaltForVersion(version, &salt_len);
297 std::vector<uint8_t> handshake_secret;
298 handshake_secret.resize(EVP_MAX_MD_SIZE);
299 size_t handshake_secret_len;
300 const bool hkdf_extract_success =
301 HKDF_extract(handshake_secret.data(), &handshake_secret_len, hash,
302 reinterpret_cast<const uint8_t*>(connection_id.data()),
303 connection_id.length(), salt, salt_len);
304 QUIC_BUG_IF(quic_bug_12871_2, !hkdf_extract_success)
305 << "HKDF_extract failed when creating initial crypters";
306 handshake_secret.resize(handshake_secret_len);
307
308 const std::string client_label = "client in";
309 const std::string server_label = "server in";
310 std::string encryption_label, decryption_label;
311 if (perspective == Perspective::IS_CLIENT) {
312 encryption_label = client_label;
313 decryption_label = server_label;
314 } else {
315 encryption_label = server_label;
316 decryption_label = client_label;
317 }
318 std::vector<uint8_t> encryption_secret = HkdfExpandLabel(
319 hash, handshake_secret, encryption_label, EVP_MD_size(hash));
320 crypters->encrypter = std::make_unique<Aes128GcmEncrypter>();
321 InitializeCrypterSecrets(hash, encryption_secret, version,
322 crypters->encrypter.get());
323
324 std::vector<uint8_t> decryption_secret = HkdfExpandLabel(
325 hash, handshake_secret, decryption_label, EVP_MD_size(hash));
326 crypters->decrypter = std::make_unique<Aes128GcmDecrypter>();
327 InitializeCrypterSecrets(hash, decryption_secret, version,
328 crypters->decrypter.get());
329 }
330
331 // static
ValidateRetryIntegrityTag(ParsedQuicVersion version,QuicConnectionId original_connection_id,absl::string_view retry_without_tag,absl::string_view integrity_tag)332 bool CryptoUtils::ValidateRetryIntegrityTag(
333 ParsedQuicVersion version, QuicConnectionId original_connection_id,
334 absl::string_view retry_without_tag, absl::string_view integrity_tag) {
335 unsigned char computed_integrity_tag[kRetryIntegrityTagLength];
336 if (integrity_tag.length() != ABSL_ARRAYSIZE(computed_integrity_tag)) {
337 QUIC_BUG(quic_bug_10699_4)
338 << "Invalid retry integrity tag length " << integrity_tag.length();
339 return false;
340 }
341 char retry_pseudo_packet[kMaxIncomingPacketSize + 256];
342 QuicDataWriter writer(ABSL_ARRAYSIZE(retry_pseudo_packet),
343 retry_pseudo_packet);
344 if (!writer.WriteLengthPrefixedConnectionId(original_connection_id)) {
345 QUIC_BUG(quic_bug_10699_5)
346 << "Failed to write original connection ID in retry pseudo packet";
347 return false;
348 }
349 if (!writer.WriteStringPiece(retry_without_tag)) {
350 QUIC_BUG(quic_bug_10699_6)
351 << "Failed to write retry without tag in retry pseudo packet";
352 return false;
353 }
354 absl::string_view key;
355 absl::string_view nonce;
356 if (!RetryIntegrityKeysForVersion(version, &key, &nonce)) {
357 // RetryIntegrityKeysForVersion already logs failures.
358 return false;
359 }
360 Aes128GcmEncrypter crypter;
361 crypter.SetKey(key);
362 absl::string_view associated_data(writer.data(), writer.length());
363 absl::string_view plaintext; // Plaintext is empty.
364 if (!crypter.Encrypt(nonce, associated_data, plaintext,
365 computed_integrity_tag)) {
366 QUIC_BUG(quic_bug_10699_7) << "Failed to compute retry integrity tag";
367 return false;
368 }
369 if (CRYPTO_memcmp(computed_integrity_tag, integrity_tag.data(),
370 ABSL_ARRAYSIZE(computed_integrity_tag)) != 0) {
371 QUIC_DLOG(ERROR) << "Failed to validate retry integrity tag";
372 return false;
373 }
374 return true;
375 }
376
377 // static
GenerateNonce(QuicWallTime now,QuicRandom * random_generator,absl::string_view orbit,std::string * nonce)378 void CryptoUtils::GenerateNonce(QuicWallTime now, QuicRandom* random_generator,
379 absl::string_view orbit, std::string* nonce) {
380 // a 4-byte timestamp + 28 random bytes.
381 nonce->reserve(kNonceSize);
382 nonce->resize(kNonceSize);
383
384 uint32_t gmt_unix_time = static_cast<uint32_t>(now.ToUNIXSeconds());
385 // The time in the nonce must be encoded in big-endian because the
386 // strike-register depends on the nonces being ordered by time.
387 (*nonce)[0] = static_cast<char>(gmt_unix_time >> 24);
388 (*nonce)[1] = static_cast<char>(gmt_unix_time >> 16);
389 (*nonce)[2] = static_cast<char>(gmt_unix_time >> 8);
390 (*nonce)[3] = static_cast<char>(gmt_unix_time);
391 size_t bytes_written = 4;
392
393 if (orbit.size() == 8) {
394 memcpy(&(*nonce)[bytes_written], orbit.data(), orbit.size());
395 bytes_written += orbit.size();
396 }
397
398 random_generator->RandBytes(&(*nonce)[bytes_written],
399 kNonceSize - bytes_written);
400 }
401
402 // 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)403 bool CryptoUtils::DeriveKeys(
404 const ParsedQuicVersion& version, absl::string_view premaster_secret,
405 QuicTag aead, absl::string_view client_nonce,
406 absl::string_view server_nonce, absl::string_view pre_shared_key,
407 const std::string& hkdf_input, Perspective perspective,
408 Diversification diversification, CrypterPair* crypters,
409 std::string* subkey_secret) {
410 // If the connection is using PSK, concatenate it with the pre-master secret.
411 std::unique_ptr<char[]> psk_premaster_secret;
412 if (!pre_shared_key.empty()) {
413 const absl::string_view label(kPreSharedKeyLabel);
414 const size_t psk_premaster_secret_size = label.size() + 1 +
415 pre_shared_key.size() + 8 +
416 premaster_secret.size() + 8;
417
418 psk_premaster_secret = std::make_unique<char[]>(psk_premaster_secret_size);
419 QuicDataWriter writer(psk_premaster_secret_size, psk_premaster_secret.get(),
420 quiche::HOST_BYTE_ORDER);
421
422 if (!writer.WriteStringPiece(label) || !writer.WriteUInt8(0) ||
423 !writer.WriteStringPiece(pre_shared_key) ||
424 !writer.WriteUInt64(pre_shared_key.size()) ||
425 !writer.WriteStringPiece(premaster_secret) ||
426 !writer.WriteUInt64(premaster_secret.size()) ||
427 writer.remaining() != 0) {
428 return false;
429 }
430
431 premaster_secret = absl::string_view(psk_premaster_secret.get(),
432 psk_premaster_secret_size);
433 }
434
435 crypters->encrypter = QuicEncrypter::Create(version, aead);
436 crypters->decrypter = QuicDecrypter::Create(version, aead);
437
438 size_t key_bytes = crypters->encrypter->GetKeySize();
439 size_t nonce_prefix_bytes = crypters->encrypter->GetNoncePrefixSize();
440 if (version.UsesInitialObfuscators()) {
441 nonce_prefix_bytes = crypters->encrypter->GetIVSize();
442 }
443 size_t subkey_secret_bytes =
444 subkey_secret == nullptr ? 0 : premaster_secret.length();
445
446 absl::string_view nonce = client_nonce;
447 std::string nonce_storage;
448 if (!server_nonce.empty()) {
449 nonce_storage = std::string(client_nonce) + std::string(server_nonce);
450 nonce = nonce_storage;
451 }
452
453 QuicHKDF hkdf(premaster_secret, nonce, hkdf_input, key_bytes,
454 nonce_prefix_bytes, subkey_secret_bytes);
455
456 // Key derivation depends on the key diversification method being employed.
457 // both the client and the server support never doing key diversification.
458 // The server also supports immediate diversification, and the client
459 // supports pending diversification.
460 switch (diversification.mode()) {
461 case Diversification::NEVER: {
462 if (perspective == Perspective::IS_SERVER) {
463 if (!crypters->encrypter->SetKey(hkdf.server_write_key()) ||
464 !crypters->encrypter->SetNoncePrefixOrIV(version,
465 hkdf.server_write_iv()) ||
466 !crypters->encrypter->SetHeaderProtectionKey(
467 hkdf.server_hp_key()) ||
468 !crypters->decrypter->SetKey(hkdf.client_write_key()) ||
469 !crypters->decrypter->SetNoncePrefixOrIV(version,
470 hkdf.client_write_iv()) ||
471 !crypters->decrypter->SetHeaderProtectionKey(
472 hkdf.client_hp_key())) {
473 return false;
474 }
475 } else {
476 if (!crypters->encrypter->SetKey(hkdf.client_write_key()) ||
477 !crypters->encrypter->SetNoncePrefixOrIV(version,
478 hkdf.client_write_iv()) ||
479 !crypters->encrypter->SetHeaderProtectionKey(
480 hkdf.client_hp_key()) ||
481 !crypters->decrypter->SetKey(hkdf.server_write_key()) ||
482 !crypters->decrypter->SetNoncePrefixOrIV(version,
483 hkdf.server_write_iv()) ||
484 !crypters->decrypter->SetHeaderProtectionKey(
485 hkdf.server_hp_key())) {
486 return false;
487 }
488 }
489 break;
490 }
491 case Diversification::PENDING: {
492 if (perspective == Perspective::IS_SERVER) {
493 QUIC_BUG(quic_bug_10699_8)
494 << "Pending diversification is only for clients.";
495 return false;
496 }
497
498 if (!crypters->encrypter->SetKey(hkdf.client_write_key()) ||
499 !crypters->encrypter->SetNoncePrefixOrIV(version,
500 hkdf.client_write_iv()) ||
501 !crypters->encrypter->SetHeaderProtectionKey(hkdf.client_hp_key()) ||
502 !crypters->decrypter->SetPreliminaryKey(hkdf.server_write_key()) ||
503 !crypters->decrypter->SetNoncePrefixOrIV(version,
504 hkdf.server_write_iv()) ||
505 !crypters->decrypter->SetHeaderProtectionKey(hkdf.server_hp_key())) {
506 return false;
507 }
508 break;
509 }
510 case Diversification::NOW: {
511 if (perspective == Perspective::IS_CLIENT) {
512 QUIC_BUG(quic_bug_10699_9)
513 << "Immediate diversification is only for servers.";
514 return false;
515 }
516
517 std::string key, nonce_prefix;
518 QuicDecrypter::DiversifyPreliminaryKey(
519 hkdf.server_write_key(), hkdf.server_write_iv(),
520 *diversification.nonce(), key_bytes, nonce_prefix_bytes, &key,
521 &nonce_prefix);
522 if (!crypters->decrypter->SetKey(hkdf.client_write_key()) ||
523 !crypters->decrypter->SetNoncePrefixOrIV(version,
524 hkdf.client_write_iv()) ||
525 !crypters->decrypter->SetHeaderProtectionKey(hkdf.client_hp_key()) ||
526 !crypters->encrypter->SetKey(key) ||
527 !crypters->encrypter->SetNoncePrefixOrIV(version, nonce_prefix) ||
528 !crypters->encrypter->SetHeaderProtectionKey(hkdf.server_hp_key())) {
529 return false;
530 }
531 break;
532 }
533 default:
534 QUICHE_DCHECK(false);
535 }
536
537 if (subkey_secret != nullptr) {
538 *subkey_secret = std::string(hkdf.subkey_secret());
539 }
540
541 return true;
542 }
543
544 // static
ComputeLeafCertHash(absl::string_view cert)545 uint64_t CryptoUtils::ComputeLeafCertHash(absl::string_view cert) {
546 return QuicUtils::FNV1a_64_Hash(cert);
547 }
548
ValidateServerHello(const CryptoHandshakeMessage & server_hello,const ParsedQuicVersionVector & negotiated_versions,std::string * error_details)549 QuicErrorCode CryptoUtils::ValidateServerHello(
550 const CryptoHandshakeMessage& server_hello,
551 const ParsedQuicVersionVector& negotiated_versions,
552 std::string* error_details) {
553 QUICHE_DCHECK(error_details != nullptr);
554
555 if (server_hello.tag() != kSHLO) {
556 *error_details = "Bad tag";
557 return QUIC_INVALID_CRYPTO_MESSAGE_TYPE;
558 }
559
560 QuicVersionLabelVector supported_version_labels;
561 if (server_hello.GetVersionLabelList(kVER, &supported_version_labels) !=
562 QUIC_NO_ERROR) {
563 *error_details = "server hello missing version list";
564 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
565 }
566
567 return ValidateServerHelloVersions(supported_version_labels,
568 negotiated_versions, error_details);
569 }
570
ValidateServerHelloVersions(const QuicVersionLabelVector & server_versions,const ParsedQuicVersionVector & negotiated_versions,std::string * error_details)571 QuicErrorCode CryptoUtils::ValidateServerHelloVersions(
572 const QuicVersionLabelVector& server_versions,
573 const ParsedQuicVersionVector& negotiated_versions,
574 std::string* error_details) {
575 if (!negotiated_versions.empty()) {
576 bool mismatch = server_versions.size() != negotiated_versions.size();
577 for (size_t i = 0; i < server_versions.size() && !mismatch; ++i) {
578 mismatch =
579 server_versions[i] != CreateQuicVersionLabel(negotiated_versions[i]);
580 }
581 // The server sent a list of supported versions, and the connection
582 // reports that there was a version negotiation during the handshake.
583 // Ensure that these two lists are identical.
584 if (mismatch) {
585 *error_details = absl::StrCat(
586 "Downgrade attack detected: ServerVersions(", server_versions.size(),
587 ")[", QuicVersionLabelVectorToString(server_versions, ",", 30),
588 "] NegotiatedVersions(", negotiated_versions.size(), ")[",
589 ParsedQuicVersionVectorToString(negotiated_versions, ",", 30), "]");
590 return QUIC_VERSION_NEGOTIATION_MISMATCH;
591 }
592 }
593 return QUIC_NO_ERROR;
594 }
595
ValidateClientHello(const CryptoHandshakeMessage & client_hello,ParsedQuicVersion version,const ParsedQuicVersionVector & supported_versions,std::string * error_details)596 QuicErrorCode CryptoUtils::ValidateClientHello(
597 const CryptoHandshakeMessage& client_hello, ParsedQuicVersion version,
598 const ParsedQuicVersionVector& supported_versions,
599 std::string* error_details) {
600 if (client_hello.tag() != kCHLO) {
601 *error_details = "Bad tag";
602 return QUIC_INVALID_CRYPTO_MESSAGE_TYPE;
603 }
604
605 // If the client's preferred version is not the version we are currently
606 // speaking, then the client went through a version negotiation. In this
607 // case, we need to make sure that we actually do not support this version
608 // and that it wasn't a downgrade attack.
609 QuicVersionLabel client_version_label;
610 if (client_hello.GetVersionLabel(kVER, &client_version_label) !=
611 QUIC_NO_ERROR) {
612 *error_details = "client hello missing version list";
613 return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
614 }
615 return ValidateClientHelloVersion(client_version_label, version,
616 supported_versions, error_details);
617 }
618
ValidateClientHelloVersion(QuicVersionLabel client_version,ParsedQuicVersion connection_version,const ParsedQuicVersionVector & supported_versions,std::string * error_details)619 QuicErrorCode CryptoUtils::ValidateClientHelloVersion(
620 QuicVersionLabel client_version, ParsedQuicVersion connection_version,
621 const ParsedQuicVersionVector& supported_versions,
622 std::string* error_details) {
623 if (client_version != CreateQuicVersionLabel(connection_version)) {
624 // Check to see if |client_version| is actually on the supported versions
625 // list. If not, the server doesn't support that version and it's not a
626 // downgrade attack.
627 for (size_t i = 0; i < supported_versions.size(); ++i) {
628 if (client_version == CreateQuicVersionLabel(supported_versions[i])) {
629 *error_details = absl::StrCat(
630 "Downgrade attack detected: ClientVersion[",
631 QuicVersionLabelToString(client_version), "] ConnectionVersion[",
632 ParsedQuicVersionToString(connection_version),
633 "] SupportedVersions(", supported_versions.size(), ")[",
634 ParsedQuicVersionVectorToString(supported_versions, ",", 30), "]");
635 return QUIC_VERSION_NEGOTIATION_MISMATCH;
636 }
637 }
638 }
639 return QUIC_NO_ERROR;
640 }
641
642 // static
ValidateChosenVersion(const QuicVersionLabel & version_information_chosen_version,const ParsedQuicVersion & session_version,std::string * error_details)643 bool CryptoUtils::ValidateChosenVersion(
644 const QuicVersionLabel& version_information_chosen_version,
645 const ParsedQuicVersion& session_version, std::string* error_details) {
646 if (version_information_chosen_version !=
647 CreateQuicVersionLabel(session_version)) {
648 *error_details = absl::StrCat(
649 "Detected version mismatch: version_information contained ",
650 QuicVersionLabelToString(version_information_chosen_version),
651 " instead of ", ParsedQuicVersionToString(session_version));
652 return false;
653 }
654 return true;
655 }
656
657 // static
ValidateServerVersions(const QuicVersionLabelVector & version_information_other_versions,const ParsedQuicVersion & session_version,const ParsedQuicVersionVector & client_original_supported_versions,std::string * error_details)658 bool CryptoUtils::ValidateServerVersions(
659 const QuicVersionLabelVector& version_information_other_versions,
660 const ParsedQuicVersion& session_version,
661 const ParsedQuicVersionVector& client_original_supported_versions,
662 std::string* error_details) {
663 if (client_original_supported_versions.empty()) {
664 // We did not receive a version negotiation packet.
665 return true;
666 }
667 // Parse the server's other versions.
668 ParsedQuicVersionVector parsed_other_versions =
669 ParseQuicVersionLabelVector(version_information_other_versions);
670 // Find the first version that we originally supported that is listed in the
671 // server's other versions.
672 ParsedQuicVersion expected_version = ParsedQuicVersion::Unsupported();
673 for (const ParsedQuicVersion& client_version :
674 client_original_supported_versions) {
675 if (std::find(parsed_other_versions.begin(), parsed_other_versions.end(),
676 client_version) != parsed_other_versions.end()) {
677 expected_version = client_version;
678 break;
679 }
680 }
681 if (expected_version != session_version) {
682 *error_details = absl::StrCat(
683 "Downgrade attack detected: used ",
684 ParsedQuicVersionToString(session_version), " but ServerVersions(",
685 version_information_other_versions.size(), ")[",
686 QuicVersionLabelVectorToString(version_information_other_versions, ",",
687 30),
688 "] ClientOriginalVersions(", client_original_supported_versions.size(),
689 ")[",
690 ParsedQuicVersionVectorToString(client_original_supported_versions, ",",
691 30),
692 "]");
693 return false;
694 }
695 return true;
696 }
697
698 #define RETURN_STRING_LITERAL(x) \
699 case x: \
700 return #x
701
702 // Returns the name of the HandshakeFailureReason as a char*
703 // static
HandshakeFailureReasonToString(HandshakeFailureReason reason)704 const char* CryptoUtils::HandshakeFailureReasonToString(
705 HandshakeFailureReason reason) {
706 switch (reason) {
707 RETURN_STRING_LITERAL(HANDSHAKE_OK);
708 RETURN_STRING_LITERAL(CLIENT_NONCE_UNKNOWN_FAILURE);
709 RETURN_STRING_LITERAL(CLIENT_NONCE_INVALID_FAILURE);
710 RETURN_STRING_LITERAL(CLIENT_NONCE_NOT_UNIQUE_FAILURE);
711 RETURN_STRING_LITERAL(CLIENT_NONCE_INVALID_ORBIT_FAILURE);
712 RETURN_STRING_LITERAL(CLIENT_NONCE_INVALID_TIME_FAILURE);
713 RETURN_STRING_LITERAL(CLIENT_NONCE_STRIKE_REGISTER_TIMEOUT);
714 RETURN_STRING_LITERAL(CLIENT_NONCE_STRIKE_REGISTER_FAILURE);
715
716 RETURN_STRING_LITERAL(SERVER_NONCE_DECRYPTION_FAILURE);
717 RETURN_STRING_LITERAL(SERVER_NONCE_INVALID_FAILURE);
718 RETURN_STRING_LITERAL(SERVER_NONCE_NOT_UNIQUE_FAILURE);
719 RETURN_STRING_LITERAL(SERVER_NONCE_INVALID_TIME_FAILURE);
720 RETURN_STRING_LITERAL(SERVER_NONCE_REQUIRED_FAILURE);
721
722 RETURN_STRING_LITERAL(SERVER_CONFIG_INCHOATE_HELLO_FAILURE);
723 RETURN_STRING_LITERAL(SERVER_CONFIG_UNKNOWN_CONFIG_FAILURE);
724
725 RETURN_STRING_LITERAL(SOURCE_ADDRESS_TOKEN_INVALID_FAILURE);
726 RETURN_STRING_LITERAL(SOURCE_ADDRESS_TOKEN_DECRYPTION_FAILURE);
727 RETURN_STRING_LITERAL(SOURCE_ADDRESS_TOKEN_PARSE_FAILURE);
728 RETURN_STRING_LITERAL(SOURCE_ADDRESS_TOKEN_DIFFERENT_IP_ADDRESS_FAILURE);
729 RETURN_STRING_LITERAL(SOURCE_ADDRESS_TOKEN_CLOCK_SKEW_FAILURE);
730 RETURN_STRING_LITERAL(SOURCE_ADDRESS_TOKEN_EXPIRED_FAILURE);
731
732 RETURN_STRING_LITERAL(INVALID_EXPECTED_LEAF_CERTIFICATE);
733 RETURN_STRING_LITERAL(MAX_FAILURE_REASON);
734 }
735 // Return a default value so that we return this when |reason| doesn't match
736 // any HandshakeFailureReason.. This can happen when the message by the peer
737 // (attacker) has invalid reason.
738 return "INVALID_HANDSHAKE_FAILURE_REASON";
739 }
740
741 #undef RETURN_STRING_LITERAL // undef for jumbo builds
742
743 // static
EarlyDataReasonToString(ssl_early_data_reason_t reason)744 std::string CryptoUtils::EarlyDataReasonToString(
745 ssl_early_data_reason_t reason) {
746 const char* reason_string = SSL_early_data_reason_string(reason);
747 if (reason_string != nullptr) {
748 return std::string("ssl_early_data_") + reason_string;
749 }
750 QUIC_BUG_IF(quic_bug_12871_3,
751 reason < 0 || reason > ssl_early_data_reason_max_value)
752 << "Unknown ssl_early_data_reason_t " << reason;
753 return "unknown ssl_early_data_reason_t";
754 }
755
756 // static
HashHandshakeMessage(const CryptoHandshakeMessage & message,Perspective)757 std::string CryptoUtils::HashHandshakeMessage(
758 const CryptoHandshakeMessage& message, Perspective /*perspective*/) {
759 std::string output;
760 const QuicData& serialized = message.GetSerialized();
761 uint8_t digest[SHA256_DIGEST_LENGTH];
762 SHA256(reinterpret_cast<const uint8_t*>(serialized.data()),
763 serialized.length(), digest);
764 output.assign(reinterpret_cast<const char*>(digest), sizeof(digest));
765 return output;
766 }
767
768 // static
GetSSLCapabilities(const SSL * ssl,bssl::UniquePtr<uint8_t> * capabilities,size_t * capabilities_len)769 bool CryptoUtils::GetSSLCapabilities(const SSL* ssl,
770 bssl::UniquePtr<uint8_t>* capabilities,
771 size_t* capabilities_len) {
772 uint8_t* buffer;
773 bssl::ScopedCBB cbb;
774
775 if (!CBB_init(cbb.get(), 128) ||
776 !SSL_serialize_capabilities(ssl, cbb.get()) ||
777 !CBB_finish(cbb.get(), &buffer, capabilities_len)) {
778 return false;
779 }
780
781 *capabilities = bssl::UniquePtr<uint8_t>(buffer);
782 return true;
783 }
784
785 // static
GenerateProofPayloadToBeSigned(absl::string_view chlo_hash,absl::string_view server_config)786 std::optional<std::string> CryptoUtils::GenerateProofPayloadToBeSigned(
787 absl::string_view chlo_hash, absl::string_view server_config) {
788 size_t payload_size = sizeof(kProofSignatureLabel) + sizeof(uint32_t) +
789 chlo_hash.size() + server_config.size();
790 std::string payload;
791 payload.resize(payload_size);
792 QuicDataWriter payload_writer(payload_size, payload.data(),
793 quiche::Endianness::HOST_BYTE_ORDER);
794 bool success = payload_writer.WriteBytes(kProofSignatureLabel,
795 sizeof(kProofSignatureLabel)) &&
796 payload_writer.WriteUInt32(chlo_hash.size()) &&
797 payload_writer.WriteStringPiece(chlo_hash) &&
798 payload_writer.WriteStringPiece(server_config);
799 if (!success) {
800 return std::nullopt;
801 }
802 return payload;
803 }
804
805 } // namespace quic
806