xref: /aosp_15_r20/external/cronet/net/third_party/quiche/src/quiche/quic/test_tools/crypto_test_utils_test.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 <utility>
8 
9 #include "absl/strings/escaping.h"
10 #include "absl/strings/string_view.h"
11 #include "quiche/quic/core/proto/crypto_server_config_proto.h"
12 #include "quiche/quic/core/quic_utils.h"
13 #include "quiche/quic/platform/api/quic_test.h"
14 #include "quiche/quic/test_tools/mock_clock.h"
15 
16 namespace quic {
17 namespace test {
18 
19 class ShloVerifier {
20  public:
ShloVerifier(QuicCryptoServerConfig * crypto_config,QuicSocketAddress server_addr,QuicSocketAddress client_addr,const QuicClock * clock,quiche::QuicheReferenceCountedPointer<QuicSignedServerConfig> signed_config,QuicCompressedCertsCache * compressed_certs_cache,ParsedQuicVersion version)21   ShloVerifier(QuicCryptoServerConfig* crypto_config,
22                QuicSocketAddress server_addr, QuicSocketAddress client_addr,
23                const QuicClock* clock,
24                quiche::QuicheReferenceCountedPointer<QuicSignedServerConfig>
25                    signed_config,
26                QuicCompressedCertsCache* compressed_certs_cache,
27                ParsedQuicVersion version)
28       : crypto_config_(crypto_config),
29         server_addr_(server_addr),
30         client_addr_(client_addr),
31         clock_(clock),
32         signed_config_(signed_config),
33         compressed_certs_cache_(compressed_certs_cache),
34         params_(new QuicCryptoNegotiatedParameters),
35         version_(version) {}
36 
37   class ValidateClientHelloCallback : public ValidateClientHelloResultCallback {
38    public:
ValidateClientHelloCallback(ShloVerifier * shlo_verifier)39     explicit ValidateClientHelloCallback(ShloVerifier* shlo_verifier)
40         : shlo_verifier_(shlo_verifier) {}
Run(quiche::QuicheReferenceCountedPointer<ValidateClientHelloResultCallback::Result> result,std::unique_ptr<ProofSource::Details>)41     void Run(quiche::QuicheReferenceCountedPointer<
42                  ValidateClientHelloResultCallback::Result>
43                  result,
44              std::unique_ptr<ProofSource::Details> /* details */) override {
45       shlo_verifier_->ValidateClientHelloDone(result);
46     }
47 
48    private:
49     ShloVerifier* shlo_verifier_;
50   };
51 
52   std::unique_ptr<ValidateClientHelloCallback>
GetValidateClientHelloCallback()53   GetValidateClientHelloCallback() {
54     return std::make_unique<ValidateClientHelloCallback>(this);
55   }
56 
server_nonce()57   absl::string_view server_nonce() { return server_nonce_; }
chlo_accepted() const58   bool chlo_accepted() const { return chlo_accepted_; }
59 
60  private:
ValidateClientHelloDone(const quiche::QuicheReferenceCountedPointer<ValidateClientHelloResultCallback::Result> & result)61   void ValidateClientHelloDone(
62       const quiche::QuicheReferenceCountedPointer<
63           ValidateClientHelloResultCallback::Result>& result) {
64     result_ = result;
65     crypto_config_->ProcessClientHello(
66         result_, /*reject_only=*/false,
67         /*connection_id=*/TestConnectionId(1), server_addr_, client_addr_,
68         version_, AllSupportedVersions(), clock_, QuicRandom::GetInstance(),
69         compressed_certs_cache_, params_, signed_config_,
70         /*total_framing_overhead=*/50, kDefaultMaxPacketSize,
71         GetProcessClientHelloCallback());
72   }
73 
74   class ProcessClientHelloCallback : public ProcessClientHelloResultCallback {
75    public:
ProcessClientHelloCallback(ShloVerifier * shlo_verifier)76     explicit ProcessClientHelloCallback(ShloVerifier* shlo_verifier)
77         : shlo_verifier_(shlo_verifier) {}
Run(QuicErrorCode,const std::string &,std::unique_ptr<CryptoHandshakeMessage> message,std::unique_ptr<DiversificationNonce>,std::unique_ptr<ProofSource::Details>)78     void Run(QuicErrorCode /*error*/, const std::string& /*error_details*/,
79              std::unique_ptr<CryptoHandshakeMessage> message,
80              std::unique_ptr<DiversificationNonce> /*diversification_nonce*/,
81              std::unique_ptr<ProofSource::Details> /*proof_source_details*/)
82         override {
83       shlo_verifier_->ProcessClientHelloDone(std::move(message));
84     }
85 
86    private:
87     ShloVerifier* shlo_verifier_;
88   };
89 
GetProcessClientHelloCallback()90   std::unique_ptr<ProcessClientHelloCallback> GetProcessClientHelloCallback() {
91     return std::make_unique<ProcessClientHelloCallback>(this);
92   }
93 
ProcessClientHelloDone(std::unique_ptr<CryptoHandshakeMessage> message)94   void ProcessClientHelloDone(std::unique_ptr<CryptoHandshakeMessage> message) {
95     if (message->tag() == kSHLO) {
96       chlo_accepted_ = true;
97     } else {
98       QUIC_LOG(INFO) << "Fail to pass validation. Get "
99                      << message->DebugString();
100       chlo_accepted_ = false;
101       EXPECT_EQ(1u, result_->info.reject_reasons.size());
102       EXPECT_EQ(SERVER_NONCE_REQUIRED_FAILURE, result_->info.reject_reasons[0]);
103       server_nonce_ = result_->info.server_nonce;
104     }
105   }
106 
107   QuicCryptoServerConfig* crypto_config_;
108   QuicSocketAddress server_addr_;
109   QuicSocketAddress client_addr_;
110   const QuicClock* clock_;
111   quiche::QuicheReferenceCountedPointer<QuicSignedServerConfig> signed_config_;
112   QuicCompressedCertsCache* compressed_certs_cache_;
113 
114   quiche::QuicheReferenceCountedPointer<QuicCryptoNegotiatedParameters> params_;
115   quiche::QuicheReferenceCountedPointer<
116       ValidateClientHelloResultCallback::Result>
117       result_;
118 
119   const ParsedQuicVersion version_;
120   bool chlo_accepted_ = false;
121   absl::string_view server_nonce_;
122 };
123 
124 class CryptoTestUtilsTest : public QuicTest {};
125 
TEST_F(CryptoTestUtilsTest,TestGenerateFullCHLO)126 TEST_F(CryptoTestUtilsTest, TestGenerateFullCHLO) {
127   MockClock clock;
128   QuicCryptoServerConfig crypto_config(
129       QuicCryptoServerConfig::TESTING, QuicRandom::GetInstance(),
130       crypto_test_utils::ProofSourceForTesting(), KeyExchangeSource::Default());
131   QuicSocketAddress server_addr(QuicIpAddress::Any4(), 5);
132   QuicSocketAddress client_addr(QuicIpAddress::Loopback4(), 1);
133   quiche::QuicheReferenceCountedPointer<QuicSignedServerConfig> signed_config(
134       new QuicSignedServerConfig);
135   QuicCompressedCertsCache compressed_certs_cache(
136       QuicCompressedCertsCache::kQuicCompressedCertsCacheSize);
137   CryptoHandshakeMessage full_chlo;
138 
139   QuicCryptoServerConfig::ConfigOptions old_config_options;
140   old_config_options.id = "old-config-id";
141   crypto_config.AddDefaultConfig(QuicRandom::GetInstance(), &clock,
142                                  old_config_options);
143   QuicCryptoServerConfig::ConfigOptions new_config_options;
144   QuicServerConfigProtobuf primary_config = crypto_config.GenerateConfig(
145       QuicRandom::GetInstance(), &clock, new_config_options);
146   primary_config.set_primary_time(clock.WallNow().ToUNIXSeconds());
147   std::unique_ptr<CryptoHandshakeMessage> msg =
148       crypto_config.AddConfig(primary_config, clock.WallNow());
149   absl::string_view orbit;
150   ASSERT_TRUE(msg->GetStringPiece(kORBT, &orbit));
151   std::string nonce;
152   CryptoUtils::GenerateNonce(clock.WallNow(), QuicRandom::GetInstance(), orbit,
153                              &nonce);
154   std::string nonce_hex = "#" + absl::BytesToHexString(nonce);
155 
156   char public_value[32];
157   memset(public_value, 42, sizeof(public_value));
158   std::string pub_hex = "#" + absl::BytesToHexString(absl::string_view(
159                                   public_value, sizeof(public_value)));
160 
161   // The methods below use a PROTOCOL_QUIC_CRYPTO version so we pick the
162   // first one from the list of supported versions.
163   QuicTransportVersion transport_version = QUIC_VERSION_UNSUPPORTED;
164   for (const ParsedQuicVersion& version : AllSupportedVersions()) {
165     if (version.handshake_protocol == PROTOCOL_QUIC_CRYPTO) {
166       transport_version = version.transport_version;
167       break;
168     }
169   }
170   ASSERT_NE(QUIC_VERSION_UNSUPPORTED, transport_version);
171 
172   CryptoHandshakeMessage inchoate_chlo = crypto_test_utils::CreateCHLO(
173       {{"PDMD", "X509"},
174        {"AEAD", "AESG"},
175        {"KEXS", "C255"},
176        {"COPT", "SREJ"},
177        {"PUBS", pub_hex},
178        {"NONC", nonce_hex},
179        {"VER\0",
180         QuicVersionLabelToString(CreateQuicVersionLabel(
181             ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, transport_version)))}},
182       kClientHelloMinimumSize);
183 
184   crypto_test_utils::GenerateFullCHLO(inchoate_chlo, &crypto_config,
185                                       server_addr, client_addr,
186                                       transport_version, &clock, signed_config,
187                                       &compressed_certs_cache, &full_chlo);
188   // Verify that full_chlo can pass crypto_config's verification.
189   ShloVerifier shlo_verifier(
190       &crypto_config, server_addr, client_addr, &clock, signed_config,
191       &compressed_certs_cache,
192       ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, transport_version));
193   crypto_config.ValidateClientHello(
194       full_chlo, client_addr, server_addr, transport_version, &clock,
195       signed_config, shlo_verifier.GetValidateClientHelloCallback());
196   ASSERT_EQ(shlo_verifier.chlo_accepted(),
197             !GetQuicReloadableFlag(quic_require_handshake_confirmation));
198   if (!shlo_verifier.chlo_accepted()) {
199     ShloVerifier shlo_verifier2(
200         &crypto_config, server_addr, client_addr, &clock, signed_config,
201         &compressed_certs_cache,
202         ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, transport_version));
203     full_chlo.SetStringPiece(
204         kServerNonceTag,
205         "#" + absl::BytesToHexString(shlo_verifier.server_nonce()));
206     crypto_config.ValidateClientHello(
207         full_chlo, client_addr, server_addr, transport_version, &clock,
208         signed_config, shlo_verifier2.GetValidateClientHelloCallback());
209     EXPECT_TRUE(shlo_verifier2.chlo_accepted()) << full_chlo.DebugString();
210   }
211 }
212 
213 }  // namespace test
214 }  // namespace quic
215