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