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