• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2012 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/test_tools/crypto_test_utils.h"
6 
7 #include <algorithm>
8 #include <memory>
9 #include <string>
10 #include <utility>
11 
12 #include "absl/strings/escaping.h"
13 #include "absl/strings/str_cat.h"
14 #include "absl/strings/string_view.h"
15 #include "absl/types/optional.h"
16 #include "openssl/bn.h"
17 #include "openssl/ec.h"
18 #include "openssl/ecdsa.h"
19 #include "openssl/nid.h"
20 #include "openssl/sha.h"
21 #include "quiche/quic/core/crypto/certificate_view.h"
22 #include "quiche/quic/core/crypto/channel_id.h"
23 #include "quiche/quic/core/crypto/crypto_handshake.h"
24 #include "quiche/quic/core/crypto/crypto_utils.h"
25 #include "quiche/quic/core/crypto/proof_source_x509.h"
26 #include "quiche/quic/core/crypto/quic_crypto_server_config.h"
27 #include "quiche/quic/core/crypto/quic_decrypter.h"
28 #include "quiche/quic/core/crypto/quic_encrypter.h"
29 #include "quiche/quic/core/crypto/quic_random.h"
30 #include "quiche/quic/core/proto/crypto_server_config_proto.h"
31 #include "quiche/quic/core/quic_clock.h"
32 #include "quiche/quic/core/quic_crypto_client_stream.h"
33 #include "quiche/quic/core/quic_crypto_server_stream_base.h"
34 #include "quiche/quic/core/quic_crypto_stream.h"
35 #include "quiche/quic/core/quic_server_id.h"
36 #include "quiche/quic/core/quic_types.h"
37 #include "quiche/quic/core/quic_utils.h"
38 #include "quiche/quic/core/quic_versions.h"
39 #include "quiche/quic/platform/api/quic_bug_tracker.h"
40 #include "quiche/quic/platform/api/quic_hostname_utils.h"
41 #include "quiche/quic/platform/api/quic_logging.h"
42 #include "quiche/quic/platform/api/quic_socket_address.h"
43 #include "quiche/quic/platform/api/quic_test.h"
44 #include "quiche/quic/test_tools/quic_connection_peer.h"
45 #include "quiche/quic/test_tools/quic_framer_peer.h"
46 #include "quiche/quic/test_tools/quic_stream_peer.h"
47 #include "quiche/quic/test_tools/quic_test_utils.h"
48 #include "quiche/quic/test_tools/simple_quic_framer.h"
49 #include "quiche/quic/test_tools/test_certificates.h"
50 #include "quiche/common/test_tools/quiche_test_utils.h"
51 
52 namespace quic {
53 namespace test {
54 
55 namespace crypto_test_utils {
56 
57 namespace {
58 
59 using testing::_;
60 
61 // CryptoFramerVisitor is a framer visitor that records handshake messages.
62 class CryptoFramerVisitor : public CryptoFramerVisitorInterface {
63  public:
CryptoFramerVisitor()64   CryptoFramerVisitor() : error_(false) {}
65 
OnError(CryptoFramer *)66   void OnError(CryptoFramer* /*framer*/) override { error_ = true; }
67 
OnHandshakeMessage(const CryptoHandshakeMessage & message)68   void OnHandshakeMessage(const CryptoHandshakeMessage& message) override {
69     messages_.push_back(message);
70   }
71 
error() const72   bool error() const { return error_; }
73 
messages() const74   const std::vector<CryptoHandshakeMessage>& messages() const {
75     return messages_;
76   }
77 
78  private:
79   bool error_;
80   std::vector<CryptoHandshakeMessage> messages_;
81 };
82 
83 // HexChar parses |c| as a hex character. If valid, it sets |*value| to the
84 // value of the hex character and returns true. Otherwise it returns false.
HexChar(char c,uint8_t * value)85 bool HexChar(char c, uint8_t* value) {
86   if (c >= '0' && c <= '9') {
87     *value = c - '0';
88     return true;
89   }
90   if (c >= 'a' && c <= 'f') {
91     *value = c - 'a' + 10;
92     return true;
93   }
94   if (c >= 'A' && c <= 'F') {
95     *value = c - 'A' + 10;
96     return true;
97   }
98   return false;
99 }
100 
101 }  // anonymous namespace
102 
FakeClientOptions()103 FakeClientOptions::FakeClientOptions() {}
104 
~FakeClientOptions()105 FakeClientOptions::~FakeClientOptions() {}
106 
107 namespace {
108 // This class is used by GenerateFullCHLO() to extract SCID and STK from
109 // REJ and to construct a full CHLO with these fields and given inchoate
110 // CHLO.
111 class FullChloGenerator {
112  public:
FullChloGenerator(QuicCryptoServerConfig * crypto_config,QuicSocketAddress server_addr,QuicSocketAddress client_addr,const QuicClock * clock,ParsedQuicVersion version,quiche::QuicheReferenceCountedPointer<QuicSignedServerConfig> signed_config,QuicCompressedCertsCache * compressed_certs_cache,CryptoHandshakeMessage * out)113   FullChloGenerator(
114       QuicCryptoServerConfig* crypto_config, QuicSocketAddress server_addr,
115       QuicSocketAddress client_addr, const QuicClock* clock,
116       ParsedQuicVersion version,
117       quiche::QuicheReferenceCountedPointer<QuicSignedServerConfig>
118           signed_config,
119       QuicCompressedCertsCache* compressed_certs_cache,
120       CryptoHandshakeMessage* out)
121       : crypto_config_(crypto_config),
122         server_addr_(server_addr),
123         client_addr_(client_addr),
124         clock_(clock),
125         version_(version),
126         signed_config_(signed_config),
127         compressed_certs_cache_(compressed_certs_cache),
128         out_(out),
129         params_(new QuicCryptoNegotiatedParameters) {}
130 
131   class ValidateClientHelloCallback : public ValidateClientHelloResultCallback {
132    public:
ValidateClientHelloCallback(FullChloGenerator * generator)133     explicit ValidateClientHelloCallback(FullChloGenerator* generator)
134         : generator_(generator) {}
Run(quiche::QuicheReferenceCountedPointer<ValidateClientHelloResultCallback::Result> result,std::unique_ptr<ProofSource::Details>)135     void Run(quiche::QuicheReferenceCountedPointer<
136                  ValidateClientHelloResultCallback::Result>
137                  result,
138              std::unique_ptr<ProofSource::Details> /* details */) override {
139       generator_->ValidateClientHelloDone(std::move(result));
140     }
141 
142    private:
143     FullChloGenerator* generator_;
144   };
145 
146   std::unique_ptr<ValidateClientHelloCallback>
GetValidateClientHelloCallback()147   GetValidateClientHelloCallback() {
148     return std::make_unique<ValidateClientHelloCallback>(this);
149   }
150 
151  private:
ValidateClientHelloDone(quiche::QuicheReferenceCountedPointer<ValidateClientHelloResultCallback::Result> result)152   void ValidateClientHelloDone(quiche::QuicheReferenceCountedPointer<
153                                ValidateClientHelloResultCallback::Result>
154                                    result) {
155     result_ = result;
156     crypto_config_->ProcessClientHello(
157         result_, /*reject_only=*/false, TestConnectionId(1), server_addr_,
158         client_addr_, version_, {version_}, clock_, QuicRandom::GetInstance(),
159         compressed_certs_cache_, params_, signed_config_,
160         /*total_framing_overhead=*/50, kDefaultMaxPacketSize,
161         GetProcessClientHelloCallback());
162   }
163 
164   class ProcessClientHelloCallback : public ProcessClientHelloResultCallback {
165    public:
ProcessClientHelloCallback(FullChloGenerator * generator)166     explicit ProcessClientHelloCallback(FullChloGenerator* generator)
167         : generator_(generator) {}
Run(QuicErrorCode error,const std::string & error_details,std::unique_ptr<CryptoHandshakeMessage> message,std::unique_ptr<DiversificationNonce>,std::unique_ptr<ProofSource::Details>)168     void Run(QuicErrorCode error, const std::string& error_details,
169              std::unique_ptr<CryptoHandshakeMessage> message,
170              std::unique_ptr<DiversificationNonce> /*diversification_nonce*/,
171              std::unique_ptr<ProofSource::Details> /*proof_source_details*/)
172         override {
173       ASSERT_TRUE(message) << QuicErrorCodeToString(error) << " "
174                            << error_details;
175       generator_->ProcessClientHelloDone(std::move(message));
176     }
177 
178    private:
179     FullChloGenerator* generator_;
180   };
181 
GetProcessClientHelloCallback()182   std::unique_ptr<ProcessClientHelloCallback> GetProcessClientHelloCallback() {
183     return std::make_unique<ProcessClientHelloCallback>(this);
184   }
185 
ProcessClientHelloDone(std::unique_ptr<CryptoHandshakeMessage> rej)186   void ProcessClientHelloDone(std::unique_ptr<CryptoHandshakeMessage> rej) {
187     // Verify output is a REJ.
188     EXPECT_THAT(rej->tag(), testing::Eq(kREJ));
189 
190     QUIC_VLOG(1) << "Extract valid STK and SCID from\n" << rej->DebugString();
191     absl::string_view srct;
192     ASSERT_TRUE(rej->GetStringPiece(kSourceAddressTokenTag, &srct));
193 
194     absl::string_view scfg;
195     ASSERT_TRUE(rej->GetStringPiece(kSCFG, &scfg));
196     std::unique_ptr<CryptoHandshakeMessage> server_config(
197         CryptoFramer::ParseMessage(scfg));
198 
199     absl::string_view scid;
200     ASSERT_TRUE(server_config->GetStringPiece(kSCID, &scid));
201 
202     *out_ = result_->client_hello;
203     out_->SetStringPiece(kSCID, scid);
204     out_->SetStringPiece(kSourceAddressTokenTag, srct);
205     uint64_t xlct = LeafCertHashForTesting();
206     out_->SetValue(kXLCT, xlct);
207   }
208 
209  protected:
210   QuicCryptoServerConfig* crypto_config_;
211   QuicSocketAddress server_addr_;
212   QuicSocketAddress client_addr_;
213   const QuicClock* clock_;
214   ParsedQuicVersion version_;
215   quiche::QuicheReferenceCountedPointer<QuicSignedServerConfig> signed_config_;
216   QuicCompressedCertsCache* compressed_certs_cache_;
217   CryptoHandshakeMessage* out_;
218 
219   quiche::QuicheReferenceCountedPointer<QuicCryptoNegotiatedParameters> params_;
220   quiche::QuicheReferenceCountedPointer<
221       ValidateClientHelloResultCallback::Result>
222       result_;
223 };
224 
225 }  // namespace
226 
CryptoServerConfigForTesting()227 std::unique_ptr<QuicCryptoServerConfig> CryptoServerConfigForTesting() {
228   return std::make_unique<QuicCryptoServerConfig>(
229       QuicCryptoServerConfig::TESTING, QuicRandom::GetInstance(),
230       ProofSourceForTesting(), KeyExchangeSource::Default());
231 }
232 
HandshakeWithFakeServer(QuicConfig * server_quic_config,QuicCryptoServerConfig * crypto_config,MockQuicConnectionHelper * helper,MockAlarmFactory * alarm_factory,PacketSavingConnection * client_conn,QuicCryptoClientStreamBase * client,std::string alpn)233 int HandshakeWithFakeServer(QuicConfig* server_quic_config,
234                             QuicCryptoServerConfig* crypto_config,
235                             MockQuicConnectionHelper* helper,
236                             MockAlarmFactory* alarm_factory,
237                             PacketSavingConnection* client_conn,
238                             QuicCryptoClientStreamBase* client,
239                             std::string alpn) {
240   auto* server_conn = new testing::NiceMock<PacketSavingConnection>(
241       helper, alarm_factory, Perspective::IS_SERVER,
242       ParsedVersionOfIndex(client_conn->supported_versions(), 0));
243 
244   QuicCompressedCertsCache compressed_certs_cache(
245       QuicCompressedCertsCache::kQuicCompressedCertsCacheSize);
246   SetupCryptoServerConfigForTest(
247       server_conn->clock(), server_conn->random_generator(), crypto_config);
248 
249   TestQuicSpdyServerSession server_session(
250       server_conn, *server_quic_config, client_conn->supported_versions(),
251       crypto_config, &compressed_certs_cache);
252   // Call SetServerApplicationStateForResumption so that the fake server
253   // supports 0-RTT in TLS.
254   server_session.Initialize();
255   server_session.GetMutableCryptoStream()
256       ->SetServerApplicationStateForResumption(
257           std::make_unique<ApplicationState>());
258   EXPECT_CALL(*server_session.helper(),
259               CanAcceptClientHello(testing::_, testing::_, testing::_,
260                                    testing::_, testing::_))
261       .Times(testing::AnyNumber());
262   EXPECT_CALL(*server_conn, OnCanWrite()).Times(testing::AnyNumber());
263   EXPECT_CALL(*client_conn, OnCanWrite()).Times(testing::AnyNumber());
264   EXPECT_CALL(*server_conn, SendCryptoData(_, _, _))
265       .Times(testing::AnyNumber());
266   EXPECT_CALL(server_session, SelectAlpn(_))
267       .WillRepeatedly([alpn](const std::vector<absl::string_view>& alpns) {
268         return std::find(alpns.cbegin(), alpns.cend(), alpn);
269       });
270 
271   // The client's handshake must have been started already.
272   QUICHE_CHECK_NE(0u, client_conn->encrypted_packets_.size());
273 
274   CommunicateHandshakeMessages(client_conn, client, server_conn,
275                                server_session.GetMutableCryptoStream());
276   if (client_conn->connected() && server_conn->connected()) {
277     CompareClientAndServerKeys(client, server_session.GetMutableCryptoStream());
278   }
279 
280   return client->num_sent_client_hellos();
281 }
282 
HandshakeWithFakeClient(MockQuicConnectionHelper * helper,MockAlarmFactory * alarm_factory,PacketSavingConnection * server_conn,QuicCryptoServerStreamBase * server,const QuicServerId & server_id,const FakeClientOptions & options,std::string alpn)283 int HandshakeWithFakeClient(MockQuicConnectionHelper* helper,
284                             MockAlarmFactory* alarm_factory,
285                             PacketSavingConnection* server_conn,
286                             QuicCryptoServerStreamBase* server,
287                             const QuicServerId& server_id,
288                             const FakeClientOptions& options,
289                             std::string alpn) {
290   // This function does not do version negotiation; read the supported versions
291   // directly from the server connection instead.
292   ParsedQuicVersionVector supported_versions =
293       server_conn->supported_versions();
294   if (options.only_tls_versions) {
295     supported_versions.erase(
296         std::remove_if(supported_versions.begin(), supported_versions.end(),
297                        [](const ParsedQuicVersion& version) {
298                          return version.handshake_protocol != PROTOCOL_TLS1_3;
299                        }),
300         supported_versions.end());
301     QUICHE_CHECK(!options.only_quic_crypto_versions);
302   } else if (options.only_quic_crypto_versions) {
303     supported_versions.erase(
304         std::remove_if(supported_versions.begin(), supported_versions.end(),
305                        [](const ParsedQuicVersion& version) {
306                          return version.handshake_protocol !=
307                                 PROTOCOL_QUIC_CRYPTO;
308                        }),
309         supported_versions.end());
310   }
311   PacketSavingConnection* client_conn = new PacketSavingConnection(
312       helper, alarm_factory, Perspective::IS_CLIENT, supported_versions);
313   // Advance the time, because timers do not like uninitialized times.
314   client_conn->AdvanceTime(QuicTime::Delta::FromSeconds(1));
315 
316   QuicCryptoClientConfig crypto_config(ProofVerifierForTesting());
317   TestQuicSpdyClientSession client_session(client_conn, DefaultQuicConfig(),
318                                            supported_versions, server_id,
319                                            &crypto_config);
320 
321   EXPECT_CALL(client_session, OnProofValid(testing::_))
322       .Times(testing::AnyNumber());
323   EXPECT_CALL(client_session, OnProofVerifyDetailsAvailable(testing::_))
324       .Times(testing::AnyNumber());
325   EXPECT_CALL(*client_conn, OnCanWrite()).Times(testing::AnyNumber());
326   if (!alpn.empty()) {
327     EXPECT_CALL(client_session, GetAlpnsToOffer())
328         .WillRepeatedly(testing::Return(std::vector<std::string>({alpn})));
329   } else {
330     EXPECT_CALL(client_session, GetAlpnsToOffer())
331         .WillRepeatedly(testing::Return(std::vector<std::string>(
332             {AlpnForVersion(client_conn->version())})));
333   }
334   client_session.GetMutableCryptoStream()->CryptoConnect();
335   QUICHE_CHECK_EQ(1u, client_conn->encrypted_packets_.size());
336 
337   CommunicateHandshakeMessages(client_conn,
338                                client_session.GetMutableCryptoStream(),
339                                server_conn, server);
340 
341   if (server->one_rtt_keys_available() && server->encryption_established()) {
342     CompareClientAndServerKeys(client_session.GetMutableCryptoStream(), server);
343   }
344 
345   return client_session.GetCryptoStream()->num_sent_client_hellos();
346 }
347 
SetupCryptoServerConfigForTest(const QuicClock * clock,QuicRandom * rand,QuicCryptoServerConfig * crypto_config)348 void SetupCryptoServerConfigForTest(const QuicClock* clock, QuicRandom* rand,
349                                     QuicCryptoServerConfig* crypto_config) {
350   QuicCryptoServerConfig::ConfigOptions options;
351   options.channel_id_enabled = true;
352   std::unique_ptr<CryptoHandshakeMessage> scfg =
353       crypto_config->AddDefaultConfig(rand, clock, options);
354 }
355 
SendHandshakeMessageToStream(QuicCryptoStream * stream,const CryptoHandshakeMessage & message,Perspective)356 void SendHandshakeMessageToStream(QuicCryptoStream* stream,
357                                   const CryptoHandshakeMessage& message,
358                                   Perspective /*perspective*/) {
359   const QuicData& data = message.GetSerialized();
360   QuicSession* session = QuicStreamPeer::session(stream);
361   if (!QuicVersionUsesCryptoFrames(session->transport_version())) {
362     QuicStreamFrame frame(
363         QuicUtils::GetCryptoStreamId(session->transport_version()), false,
364         stream->crypto_bytes_read(), data.AsStringPiece());
365     stream->OnStreamFrame(frame);
366   } else {
367     EncryptionLevel level = session->connection()->last_decrypted_level();
368     QuicCryptoFrame frame(level, stream->BytesReadOnLevel(level),
369                           data.AsStringPiece());
370     stream->OnCryptoFrame(frame);
371   }
372 }
373 
CommunicateHandshakeMessages(PacketSavingConnection * client_conn,QuicCryptoStream * client,PacketSavingConnection * server_conn,QuicCryptoStream * server)374 void CommunicateHandshakeMessages(PacketSavingConnection* client_conn,
375                                   QuicCryptoStream* client,
376                                   PacketSavingConnection* server_conn,
377                                   QuicCryptoStream* server) {
378   size_t client_i = 0, server_i = 0;
379   while (client_conn->connected() && server_conn->connected() &&
380          (!client->one_rtt_keys_available() ||
381           !server->one_rtt_keys_available())) {
382     ASSERT_GT(client_conn->encrypted_packets_.size(), client_i);
383     QUIC_LOG(INFO) << "Processing "
384                    << client_conn->encrypted_packets_.size() - client_i
385                    << " packets client->server";
386     MovePackets(client_conn, &client_i, server, server_conn,
387                 Perspective::IS_SERVER, /*process_stream_data=*/false);
388 
389     if (client->one_rtt_keys_available() && server->one_rtt_keys_available() &&
390         server_conn->encrypted_packets_.size() == server_i) {
391       break;
392     }
393     ASSERT_GT(server_conn->encrypted_packets_.size(), server_i);
394     QUIC_LOG(INFO) << "Processing "
395                    << server_conn->encrypted_packets_.size() - server_i
396                    << " packets server->client";
397     MovePackets(server_conn, &server_i, client, client_conn,
398                 Perspective::IS_CLIENT, /*process_stream_data=*/false);
399   }
400 }
401 
CommunicateHandshakeMessagesUntil(PacketSavingConnection * client_conn,QuicCryptoStream * client,std::function<bool ()> client_condition,PacketSavingConnection * server_conn,QuicCryptoStream * server,std::function<bool ()> server_condition,bool process_stream_data)402 bool CommunicateHandshakeMessagesUntil(PacketSavingConnection* client_conn,
403                                        QuicCryptoStream* client,
404                                        std::function<bool()> client_condition,
405                                        PacketSavingConnection* server_conn,
406                                        QuicCryptoStream* server,
407                                        std::function<bool()> server_condition,
408                                        bool process_stream_data) {
409   size_t client_next_packet_to_deliver =
410       client_conn->number_of_packets_delivered_;
411   size_t server_next_packet_to_deliver =
412       server_conn->number_of_packets_delivered_;
413   while (
414       client_conn->connected() && server_conn->connected() &&
415       (!client_condition() || !server_condition()) &&
416       (client_conn->encrypted_packets_.size() > client_next_packet_to_deliver ||
417        server_conn->encrypted_packets_.size() >
418            server_next_packet_to_deliver)) {
419     if (!server_condition()) {
420       QUIC_LOG(INFO) << "Processing "
421                      << client_conn->encrypted_packets_.size() -
422                             client_next_packet_to_deliver
423                      << " packets client->server";
424       MovePackets(client_conn, &client_next_packet_to_deliver, server,
425                   server_conn, Perspective::IS_SERVER, process_stream_data);
426     }
427     if (!client_condition()) {
428       QUIC_LOG(INFO) << "Processing "
429                      << server_conn->encrypted_packets_.size() -
430                             server_next_packet_to_deliver
431                      << " packets server->client";
432       MovePackets(server_conn, &server_next_packet_to_deliver, client,
433                   client_conn, Perspective::IS_CLIENT, process_stream_data);
434     }
435   }
436   client_conn->number_of_packets_delivered_ = client_next_packet_to_deliver;
437   server_conn->number_of_packets_delivered_ = server_next_packet_to_deliver;
438   bool result = client_condition() && server_condition();
439   if (!result) {
440     QUIC_LOG(INFO) << "CommunicateHandshakeMessagesUnti failed with state: "
441                       "client connected? "
442                    << client_conn->connected() << " server connected? "
443                    << server_conn->connected() << " client condition met? "
444                    << client_condition() << " server condition met? "
445                    << server_condition();
446   }
447   return result;
448 }
449 
AdvanceHandshake(PacketSavingConnection * client_conn,QuicCryptoStream * client,size_t client_i,PacketSavingConnection * server_conn,QuicCryptoStream * server,size_t server_i)450 std::pair<size_t, size_t> AdvanceHandshake(PacketSavingConnection* client_conn,
451                                            QuicCryptoStream* client,
452                                            size_t client_i,
453                                            PacketSavingConnection* server_conn,
454                                            QuicCryptoStream* server,
455                                            size_t server_i) {
456   if (client_conn->encrypted_packets_.size() != client_i) {
457     QUIC_LOG(INFO) << "Processing "
458                    << client_conn->encrypted_packets_.size() - client_i
459                    << " packets client->server";
460     MovePackets(client_conn, &client_i, server, server_conn,
461                 Perspective::IS_SERVER, /*process_stream_data=*/false);
462   }
463 
464   if (server_conn->encrypted_packets_.size() != server_i) {
465     QUIC_LOG(INFO) << "Processing "
466                    << server_conn->encrypted_packets_.size() - server_i
467                    << " packets server->client";
468     MovePackets(server_conn, &server_i, client, client_conn,
469                 Perspective::IS_CLIENT, /*process_stream_data=*/false);
470   }
471 
472   return std::make_pair(client_i, server_i);
473 }
474 
GetValueForTag(const CryptoHandshakeMessage & message,QuicTag tag)475 std::string GetValueForTag(const CryptoHandshakeMessage& message, QuicTag tag) {
476   auto it = message.tag_value_map().find(tag);
477   if (it == message.tag_value_map().end()) {
478     return std::string();
479   }
480   return it->second;
481 }
482 
LeafCertHashForTesting()483 uint64_t LeafCertHashForTesting() {
484   quiche::QuicheReferenceCountedPointer<ProofSource::Chain> chain;
485   QuicSocketAddress server_address(QuicIpAddress::Any4(), 42);
486   QuicSocketAddress client_address(QuicIpAddress::Any4(), 43);
487   QuicCryptoProof proof;
488   std::unique_ptr<ProofSource> proof_source(ProofSourceForTesting());
489 
490   class Callback : public ProofSource::Callback {
491    public:
492     Callback(bool* ok,
493              quiche::QuicheReferenceCountedPointer<ProofSource::Chain>* chain)
494         : ok_(ok), chain_(chain) {}
495 
496     void Run(
497         bool ok,
498         const quiche::QuicheReferenceCountedPointer<ProofSource::Chain>& chain,
499         const QuicCryptoProof& /* proof */,
500         std::unique_ptr<ProofSource::Details> /* details */) override {
501       *ok_ = ok;
502       *chain_ = chain;
503     }
504 
505    private:
506     bool* ok_;
507     quiche::QuicheReferenceCountedPointer<ProofSource::Chain>* chain_;
508   };
509 
510   // Note: relies on the callback being invoked synchronously
511   bool ok = false;
512   proof_source->GetProof(
513       server_address, client_address, "", "",
514       AllSupportedVersionsWithQuicCrypto().front().transport_version, "",
515       std::unique_ptr<ProofSource::Callback>(new Callback(&ok, &chain)));
516   if (!ok || chain->certs.empty()) {
517     QUICHE_DCHECK(false) << "Proof generation failed";
518     return 0;
519   }
520 
521   return QuicUtils::FNV1a_64_Hash(chain->certs.at(0));
522 }
523 
FillInDummyReject(CryptoHandshakeMessage * rej)524 void FillInDummyReject(CryptoHandshakeMessage* rej) {
525   rej->set_tag(kREJ);
526 
527   // Minimum SCFG that passes config validation checks.
528   // clang-format off
529   unsigned char scfg[] = {
530     // SCFG
531     0x53, 0x43, 0x46, 0x47,
532     // num entries
533     0x01, 0x00,
534     // padding
535     0x00, 0x00,
536     // EXPY
537     0x45, 0x58, 0x50, 0x59,
538     // EXPY end offset
539     0x08, 0x00, 0x00, 0x00,
540     // Value
541     '1',  '2',  '3',  '4',
542     '5',  '6',  '7',  '8'
543   };
544   // clang-format on
545   rej->SetValue(kSCFG, scfg);
546   rej->SetStringPiece(kServerNonceTag, "SERVER_NONCE");
547   int64_t ttl = 2 * 24 * 60 * 60;
548   rej->SetValue(kSTTL, ttl);
549   std::vector<QuicTag> reject_reasons;
550   reject_reasons.push_back(CLIENT_NONCE_INVALID_FAILURE);
551   rej->SetVector(kRREJ, reject_reasons);
552 }
553 
554 namespace {
555 
556 #define RETURN_STRING_LITERAL(x) \
557   case x:                        \
558     return #x
559 
EncryptionLevelString(EncryptionLevel level)560 std::string EncryptionLevelString(EncryptionLevel level) {
561   switch (level) {
562     RETURN_STRING_LITERAL(ENCRYPTION_INITIAL);
563     RETURN_STRING_LITERAL(ENCRYPTION_HANDSHAKE);
564     RETURN_STRING_LITERAL(ENCRYPTION_ZERO_RTT);
565     RETURN_STRING_LITERAL(ENCRYPTION_FORWARD_SECURE);
566     default:
567       return "";
568   }
569 }
570 
CompareCrypters(const QuicEncrypter * encrypter,const QuicDecrypter * decrypter,std::string label)571 void CompareCrypters(const QuicEncrypter* encrypter,
572                      const QuicDecrypter* decrypter, std::string label) {
573   if (encrypter == nullptr || decrypter == nullptr) {
574     ADD_FAILURE() << "Expected non-null crypters; have " << encrypter << " and "
575                   << decrypter << " for " << label;
576     return;
577   }
578   absl::string_view encrypter_key = encrypter->GetKey();
579   absl::string_view encrypter_iv = encrypter->GetNoncePrefix();
580   absl::string_view decrypter_key = decrypter->GetKey();
581   absl::string_view decrypter_iv = decrypter->GetNoncePrefix();
582   quiche::test::CompareCharArraysWithHexError(
583       label + " key", encrypter_key.data(), encrypter_key.length(),
584       decrypter_key.data(), decrypter_key.length());
585   quiche::test::CompareCharArraysWithHexError(
586       label + " iv", encrypter_iv.data(), encrypter_iv.length(),
587       decrypter_iv.data(), decrypter_iv.length());
588 }
589 
590 }  // namespace
591 
CompareClientAndServerKeys(QuicCryptoClientStreamBase * client,QuicCryptoServerStreamBase * server)592 void CompareClientAndServerKeys(QuicCryptoClientStreamBase* client,
593                                 QuicCryptoServerStreamBase* server) {
594   QuicFramer* client_framer = QuicConnectionPeer::GetFramer(
595       QuicStreamPeer::session(client)->connection());
596   QuicFramer* server_framer = QuicConnectionPeer::GetFramer(
597       QuicStreamPeer::session(server)->connection());
598   for (EncryptionLevel level :
599        {ENCRYPTION_HANDSHAKE, ENCRYPTION_ZERO_RTT, ENCRYPTION_FORWARD_SECURE}) {
600     SCOPED_TRACE(EncryptionLevelString(level));
601     const QuicEncrypter* client_encrypter(
602         QuicFramerPeer::GetEncrypter(client_framer, level));
603     const QuicDecrypter* server_decrypter(
604         QuicFramerPeer::GetDecrypter(server_framer, level));
605     if (level == ENCRYPTION_FORWARD_SECURE ||
606         !((level == ENCRYPTION_HANDSHAKE || level == ENCRYPTION_ZERO_RTT ||
607            client_encrypter == nullptr) &&
608           (level == ENCRYPTION_ZERO_RTT || server_decrypter == nullptr))) {
609       CompareCrypters(client_encrypter, server_decrypter,
610                       "client " + EncryptionLevelString(level) + " write");
611     }
612     const QuicEncrypter* server_encrypter(
613         QuicFramerPeer::GetEncrypter(server_framer, level));
614     const QuicDecrypter* client_decrypter(
615         QuicFramerPeer::GetDecrypter(client_framer, level));
616     if (level == ENCRYPTION_FORWARD_SECURE ||
617         !(server_encrypter == nullptr &&
618           (level == ENCRYPTION_HANDSHAKE || level == ENCRYPTION_ZERO_RTT ||
619            client_decrypter == nullptr))) {
620       CompareCrypters(server_encrypter, client_decrypter,
621                       "server " + EncryptionLevelString(level) + " write");
622     }
623   }
624 
625   absl::string_view client_subkey_secret =
626       client->crypto_negotiated_params().subkey_secret;
627   absl::string_view server_subkey_secret =
628       server->crypto_negotiated_params().subkey_secret;
629   quiche::test::CompareCharArraysWithHexError(
630       "subkey secret", client_subkey_secret.data(),
631       client_subkey_secret.length(), server_subkey_secret.data(),
632       server_subkey_secret.length());
633 }
634 
ParseTag(const char * tagstr)635 QuicTag ParseTag(const char* tagstr) {
636   const size_t len = strlen(tagstr);
637   QUICHE_CHECK_NE(0u, len);
638 
639   QuicTag tag = 0;
640 
641   if (tagstr[0] == '#') {
642     QUICHE_CHECK_EQ(static_cast<size_t>(1 + 2 * 4), len);
643     tagstr++;
644 
645     for (size_t i = 0; i < 8; i++) {
646       tag <<= 4;
647 
648       uint8_t v = 0;
649       QUICHE_CHECK(HexChar(tagstr[i], &v));
650       tag |= v;
651     }
652 
653     return tag;
654   }
655 
656   QUICHE_CHECK_LE(len, 4u);
657   for (size_t i = 0; i < 4; i++) {
658     tag >>= 8;
659     if (i < len) {
660       tag |= static_cast<uint32_t>(tagstr[i]) << 24;
661     }
662   }
663 
664   return tag;
665 }
666 
CreateCHLO(std::vector<std::pair<std::string,std::string>> tags_and_values)667 CryptoHandshakeMessage CreateCHLO(
668     std::vector<std::pair<std::string, std::string>> tags_and_values) {
669   return CreateCHLO(tags_and_values, -1);
670 }
671 
CreateCHLO(std::vector<std::pair<std::string,std::string>> tags_and_values,int minimum_size_bytes)672 CryptoHandshakeMessage CreateCHLO(
673     std::vector<std::pair<std::string, std::string>> tags_and_values,
674     int minimum_size_bytes) {
675   CryptoHandshakeMessage msg;
676   msg.set_tag(MakeQuicTag('C', 'H', 'L', 'O'));
677 
678   if (minimum_size_bytes > 0) {
679     msg.set_minimum_size(minimum_size_bytes);
680   }
681 
682   for (const auto& tag_and_value : tags_and_values) {
683     const std::string& tag = tag_and_value.first;
684     const std::string& value = tag_and_value.second;
685 
686     const QuicTag quic_tag = ParseTag(tag.c_str());
687 
688     size_t value_len = value.length();
689     if (value_len > 0 && value[0] == '#') {
690       // This is ascii encoded hex.
691       std::string hex_value =
692           absl::HexStringToBytes(absl::string_view(&value[1]));
693       msg.SetStringPiece(quic_tag, hex_value);
694       continue;
695     }
696     msg.SetStringPiece(quic_tag, value);
697   }
698 
699   // The CryptoHandshakeMessage needs to be serialized and parsed to ensure
700   // that any padding is included.
701   std::unique_ptr<QuicData> bytes =
702       CryptoFramer::ConstructHandshakeMessage(msg);
703   std::unique_ptr<CryptoHandshakeMessage> parsed(
704       CryptoFramer::ParseMessage(bytes->AsStringPiece()));
705   QUICHE_CHECK(parsed);
706 
707   return *parsed;
708 }
709 
MovePackets(PacketSavingConnection * source_conn,size_t * inout_packet_index,QuicCryptoStream * dest_stream,PacketSavingConnection * dest_conn,Perspective dest_perspective,bool process_stream_data)710 void MovePackets(PacketSavingConnection* source_conn,
711                  size_t* inout_packet_index, QuicCryptoStream* dest_stream,
712                  PacketSavingConnection* dest_conn,
713                  Perspective dest_perspective, bool process_stream_data) {
714   SimpleQuicFramer framer(source_conn->supported_versions(), dest_perspective);
715   QuicFramerPeer::SetLastSerializedServerConnectionId(framer.framer(),
716                                                       TestConnectionId());
717 
718   SimpleQuicFramer null_encryption_framer(source_conn->supported_versions(),
719                                           dest_perspective);
720   QuicFramerPeer::SetLastSerializedServerConnectionId(
721       null_encryption_framer.framer(), TestConnectionId());
722 
723   size_t index = *inout_packet_index;
724   for (; index < source_conn->encrypted_packets_.size(); index++) {
725     if (!dest_conn->connected()) {
726       QUIC_LOG(INFO)
727           << "Destination connection disconnected. Skipping packet at index "
728           << index;
729       continue;
730     }
731     // In order to properly test the code we need to perform encryption and
732     // decryption so that the crypters latch when expected. The crypters are in
733     // |dest_conn|, but we don't want to try and use them there. Instead we swap
734     // them into |framer|, perform the decryption with them, and then swap ther
735     // back.
736     QuicConnectionPeer::SwapCrypters(dest_conn, framer.framer());
737     QuicConnectionPeer::AddBytesReceived(
738         dest_conn, source_conn->encrypted_packets_[index]->length());
739     if (!framer.ProcessPacket(*source_conn->encrypted_packets_[index])) {
740       // The framer will be unable to decrypt zero-rtt packets sent during
741       // handshake or forward-secure packets sent after the handshake is
742       // complete. Don't treat them as handshake packets.
743       QuicConnectionPeer::SwapCrypters(dest_conn, framer.framer());
744       continue;
745     }
746     QuicConnectionPeer::SwapCrypters(dest_conn, framer.framer());
747 
748     // Install a packet flusher such that the packets generated by |dest_conn|
749     // in response to this packet are more likely to be coalesced and/or batched
750     // in the writer.
751     QuicConnection::ScopedPacketFlusher flusher(dest_conn);
752 
753     dest_conn->OnDecryptedPacket(
754         source_conn->encrypted_packets_[index]->length(),
755         framer.last_decrypted_level());
756 
757     if (dest_stream->handshake_protocol() == PROTOCOL_TLS1_3) {
758       // Try to process the packet with a framer that only has the NullDecrypter
759       // for decryption. If ProcessPacket succeeds, that means the packet was
760       // encrypted with the NullEncrypter. With the TLS handshaker in use, no
761       // packets should ever be encrypted with the NullEncrypter, instead
762       // they're encrypted with an obfuscation cipher based on QUIC version and
763       // connection ID.
764       QUIC_LOG(INFO) << "Attempting to decrypt with NullDecrypter: "
765                         "expect a decryption failure on the next log line.";
766       ASSERT_FALSE(null_encryption_framer.ProcessPacket(
767           *source_conn->encrypted_packets_[index]))
768           << "No TLS packets should be encrypted with the NullEncrypter";
769     }
770 
771     // Since we're using QuicFramers separate from the connections to move
772     // packets, the QuicConnection never gets notified about what level the last
773     // packet was decrypted at. This is needed by TLS to know what encryption
774     // level was used for the data it's receiving, so we plumb this information
775     // from the SimpleQuicFramer back into the connection.
776     dest_conn->OnDecryptedPacket(
777         source_conn->encrypted_packets_[index]->length(),
778         framer.last_decrypted_level());
779 
780     QuicConnectionPeer::SetCurrentPacket(
781         dest_conn, source_conn->encrypted_packets_[index]->AsStringPiece());
782     for (const auto& stream_frame : framer.stream_frames()) {
783       if (process_stream_data &&
784           dest_stream->handshake_protocol() == PROTOCOL_TLS1_3) {
785         // Deliver STREAM_FRAME such that application state is available and can
786         // be stored along with resumption ticket in session cache,
787         dest_conn->OnStreamFrame(*stream_frame);
788       } else {
789         // Ignore stream frames that are sent on other streams in the crypto
790         // event.
791         if (stream_frame->stream_id == dest_stream->id()) {
792           dest_stream->OnStreamFrame(*stream_frame);
793         }
794       }
795     }
796     for (const auto& crypto_frame : framer.crypto_frames()) {
797       dest_stream->OnCryptoFrame(*crypto_frame);
798     }
799     if (!framer.connection_close_frames().empty() && dest_conn->connected()) {
800       dest_conn->OnConnectionCloseFrame(framer.connection_close_frames()[0]);
801     }
802   }
803   *inout_packet_index = index;
804 
805   QuicConnectionPeer::SetCurrentPacket(dest_conn,
806                                        absl::string_view(nullptr, 0));
807 }
808 
GenerateDefaultInchoateCHLO(const QuicClock * clock,QuicTransportVersion version,QuicCryptoServerConfig * crypto_config)809 CryptoHandshakeMessage GenerateDefaultInchoateCHLO(
810     const QuicClock* clock, QuicTransportVersion version,
811     QuicCryptoServerConfig* crypto_config) {
812   // clang-format off
813   return CreateCHLO(
814       {{"PDMD", "X509"},
815        {"AEAD", "AESG"},
816        {"KEXS", "C255"},
817        {"PUBS", GenerateClientPublicValuesHex().c_str()},
818        {"NONC", GenerateClientNonceHex(clock, crypto_config).c_str()},
819        {"VER\0", QuicVersionLabelToString(
820            CreateQuicVersionLabel(
821             ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, version))).c_str()}},
822       kClientHelloMinimumSize);
823   // clang-format on
824 }
825 
GenerateClientNonceHex(const QuicClock * clock,QuicCryptoServerConfig * crypto_config)826 std::string GenerateClientNonceHex(const QuicClock* clock,
827                                    QuicCryptoServerConfig* crypto_config) {
828   QuicCryptoServerConfig::ConfigOptions old_config_options;
829   QuicCryptoServerConfig::ConfigOptions new_config_options;
830   old_config_options.id = "old-config-id";
831   crypto_config->AddDefaultConfig(QuicRandom::GetInstance(), clock,
832                                   old_config_options);
833   QuicServerConfigProtobuf primary_config = crypto_config->GenerateConfig(
834       QuicRandom::GetInstance(), clock, new_config_options);
835   primary_config.set_primary_time(clock->WallNow().ToUNIXSeconds());
836   std::unique_ptr<CryptoHandshakeMessage> msg =
837       crypto_config->AddConfig(primary_config, clock->WallNow());
838   absl::string_view orbit;
839   QUICHE_CHECK(msg->GetStringPiece(kORBT, &orbit));
840   std::string nonce;
841   CryptoUtils::GenerateNonce(clock->WallNow(), QuicRandom::GetInstance(), orbit,
842                              &nonce);
843   return ("#" + absl::BytesToHexString(nonce));
844 }
845 
GenerateClientPublicValuesHex()846 std::string GenerateClientPublicValuesHex() {
847   char public_value[32];
848   memset(public_value, 42, sizeof(public_value));
849   return ("#" + absl::BytesToHexString(
850                     absl::string_view(public_value, sizeof(public_value))));
851 }
852 
GenerateFullCHLO(const CryptoHandshakeMessage & inchoate_chlo,QuicCryptoServerConfig * crypto_config,QuicSocketAddress server_addr,QuicSocketAddress client_addr,QuicTransportVersion transport_version,const QuicClock * clock,quiche::QuicheReferenceCountedPointer<QuicSignedServerConfig> signed_config,QuicCompressedCertsCache * compressed_certs_cache,CryptoHandshakeMessage * out)853 void GenerateFullCHLO(
854     const CryptoHandshakeMessage& inchoate_chlo,
855     QuicCryptoServerConfig* crypto_config, QuicSocketAddress server_addr,
856     QuicSocketAddress client_addr, QuicTransportVersion transport_version,
857     const QuicClock* clock,
858     quiche::QuicheReferenceCountedPointer<QuicSignedServerConfig> signed_config,
859     QuicCompressedCertsCache* compressed_certs_cache,
860     CryptoHandshakeMessage* out) {
861   // Pass a inchoate CHLO.
862   FullChloGenerator generator(
863       crypto_config, server_addr, client_addr, clock,
864       ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, transport_version), signed_config,
865       compressed_certs_cache, out);
866   crypto_config->ValidateClientHello(
867       inchoate_chlo, client_addr, server_addr, transport_version, clock,
868       signed_config, generator.GetValidateClientHelloCallback());
869 }
870 
871 namespace {
872 
873 constexpr char kTestProofHostname[] = "test.example.com";
874 
875 class TestProofSource : public ProofSourceX509 {
876  public:
TestProofSource()877   TestProofSource()
878       : ProofSourceX509(
879             quiche::QuicheReferenceCountedPointer<ProofSource::Chain>(
880                 new ProofSource::Chain(
881                     std::vector<std::string>{std::string(kTestCertificate)})),
882             std::move(*CertificatePrivateKey::LoadFromDer(
883                 kTestCertificatePrivateKey))) {
884     QUICHE_DCHECK(valid());
885   }
886 
887  protected:
MaybeAddSctsForHostname(absl::string_view,std::string & leaf_cert_scts)888   void MaybeAddSctsForHostname(absl::string_view /*hostname*/,
889                                std::string& leaf_cert_scts) override {
890     leaf_cert_scts = "Certificate Transparency is really nice";
891   }
892 };
893 
894 class TestProofVerifier : public ProofVerifier {
895  public:
TestProofVerifier()896   TestProofVerifier()
897       : certificate_(std::move(
898             *CertificateView::ParseSingleCertificate(kTestCertificate))) {}
899 
900   class Details : public ProofVerifyDetails {
901    public:
Clone() const902     ProofVerifyDetails* Clone() const override { return new Details(*this); }
903   };
904 
VerifyProof(const std::string & hostname,const uint16_t port,const std::string & server_config,QuicTransportVersion,absl::string_view chlo_hash,const std::vector<std::string> & certs,const std::string & cert_sct,const std::string & signature,const ProofVerifyContext * context,std::string * error_details,std::unique_ptr<ProofVerifyDetails> * details,std::unique_ptr<ProofVerifierCallback> callback)905   QuicAsyncStatus VerifyProof(
906       const std::string& hostname, const uint16_t port,
907       const std::string& server_config,
908       QuicTransportVersion /*transport_version*/, absl::string_view chlo_hash,
909       const std::vector<std::string>& certs, const std::string& cert_sct,
910       const std::string& signature, const ProofVerifyContext* context,
911       std::string* error_details, std::unique_ptr<ProofVerifyDetails>* details,
912       std::unique_ptr<ProofVerifierCallback> callback) override {
913     absl::optional<std::string> payload =
914         CryptoUtils::GenerateProofPayloadToBeSigned(chlo_hash, server_config);
915     if (!payload.has_value()) {
916       *error_details = "Failed to serialize signed payload";
917       return QUIC_FAILURE;
918     }
919     if (!certificate_.VerifySignature(*payload, signature,
920                                       SSL_SIGN_RSA_PSS_RSAE_SHA256)) {
921       *error_details = "Invalid signature";
922       return QUIC_FAILURE;
923     }
924 
925     uint8_t out_alert;
926     return VerifyCertChain(hostname, port, certs, /*ocsp_response=*/"",
927                            cert_sct, context, error_details, details,
928                            &out_alert, std::move(callback));
929   }
930 
VerifyCertChain(const std::string & hostname,const uint16_t,const std::vector<std::string> & certs,const std::string &,const std::string &,const ProofVerifyContext *,std::string * error_details,std::unique_ptr<ProofVerifyDetails> * details,uint8_t *,std::unique_ptr<ProofVerifierCallback>)931   QuicAsyncStatus VerifyCertChain(
932       const std::string& hostname, const uint16_t /*port*/,
933       const std::vector<std::string>& certs,
934       const std::string& /*ocsp_response*/, const std::string& /*cert_sct*/,
935       const ProofVerifyContext* /*context*/, std::string* error_details,
936       std::unique_ptr<ProofVerifyDetails>* details, uint8_t* /*out_alert*/,
937       std::unique_ptr<ProofVerifierCallback> /*callback*/) override {
938     std::string normalized_hostname =
939         QuicHostnameUtils::NormalizeHostname(hostname);
940     if (normalized_hostname != kTestProofHostname) {
941       *error_details = absl::StrCat("Invalid hostname, expected ",
942                                     kTestProofHostname, " got ", hostname);
943       return QUIC_FAILURE;
944     }
945     if (certs.empty() || certs.front() != kTestCertificate) {
946       *error_details = "Received certificate different from the expected";
947       return QUIC_FAILURE;
948     }
949     *details = std::make_unique<Details>();
950     return QUIC_SUCCESS;
951   }
952 
CreateDefaultContext()953   std::unique_ptr<ProofVerifyContext> CreateDefaultContext() override {
954     return nullptr;
955   }
956 
957  private:
958   CertificateView certificate_;
959 };
960 
961 }  // namespace
962 
ProofSourceForTesting()963 std::unique_ptr<ProofSource> ProofSourceForTesting() {
964   return std::make_unique<TestProofSource>();
965 }
966 
ProofVerifierForTesting()967 std::unique_ptr<ProofVerifier> ProofVerifierForTesting() {
968   return std::make_unique<TestProofVerifier>();
969 }
970 
CertificateHostnameForTesting()971 std::string CertificateHostnameForTesting() { return kTestProofHostname; }
972 
ProofVerifyContextForTesting()973 std::unique_ptr<ProofVerifyContext> ProofVerifyContextForTesting() {
974   return nullptr;
975 }
976 
977 }  // namespace crypto_test_utils
978 }  // namespace test
979 }  // namespace quic
980