xref: /aosp_15_r20/external/cronet/net/third_party/quiche/src/quiche/quic/core/crypto/client_proof_source_test.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright (c) 2021 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "quiche/quic/core/crypto/client_proof_source.h"
6 
7 #include "quiche/quic/platform/api/quic_expect_bug.h"
8 #include "quiche/quic/platform/api/quic_test.h"
9 #include "quiche/quic/test_tools/test_certificates.h"
10 
11 namespace quic {
12 namespace test {
13 
14 quiche::QuicheReferenceCountedPointer<ClientProofSource::Chain>
TestCertChain()15 TestCertChain() {
16   return quiche::QuicheReferenceCountedPointer<ClientProofSource::Chain>(
17       new ClientProofSource::Chain({std::string(kTestCertificate)}));
18 }
19 
TestPrivateKey()20 CertificatePrivateKey TestPrivateKey() {
21   CBS private_key_cbs;
22   CBS_init(&private_key_cbs,
23            reinterpret_cast<const uint8_t*>(kTestCertificatePrivateKey.data()),
24            kTestCertificatePrivateKey.size());
25 
26   return CertificatePrivateKey(
27       bssl::UniquePtr<EVP_PKEY>(EVP_parse_private_key(&private_key_cbs)));
28 }
29 
TestCertAndKey()30 const ClientProofSource::CertAndKey* TestCertAndKey() {
31   static const ClientProofSource::CertAndKey cert_and_key(TestCertChain(),
32                                                           TestPrivateKey());
33   return &cert_and_key;
34 }
35 
36 quiche::QuicheReferenceCountedPointer<ClientProofSource::Chain>
NullCertChain()37 NullCertChain() {
38   return quiche::QuicheReferenceCountedPointer<ClientProofSource::Chain>();
39 }
40 
41 quiche::QuicheReferenceCountedPointer<ClientProofSource::Chain>
EmptyCertChain()42 EmptyCertChain() {
43   return quiche::QuicheReferenceCountedPointer<ClientProofSource::Chain>(
44       new ClientProofSource::Chain(std::vector<std::string>()));
45 }
46 
BadCertChain()47 quiche::QuicheReferenceCountedPointer<ClientProofSource::Chain> BadCertChain() {
48   return quiche::QuicheReferenceCountedPointer<ClientProofSource::Chain>(
49       new ClientProofSource::Chain({"This is the content of a bad cert."}));
50 }
51 
EmptyPrivateKey()52 CertificatePrivateKey EmptyPrivateKey() {
53   return CertificatePrivateKey(bssl::UniquePtr<EVP_PKEY>(EVP_PKEY_new()));
54 }
55 
56 #define VERIFY_CERT_AND_KEY_MATCHES(lhs, rhs) \
57   do {                                        \
58     SCOPED_TRACE(testing::Message());         \
59     VerifyCertAndKeyMatches(lhs.get(), rhs);  \
60   } while (0)
61 
VerifyCertAndKeyMatches(const ClientProofSource::CertAndKey * lhs,const ClientProofSource::CertAndKey * rhs)62 void VerifyCertAndKeyMatches(const ClientProofSource::CertAndKey* lhs,
63                              const ClientProofSource::CertAndKey* rhs) {
64   if (lhs == rhs) {
65     return;
66   }
67 
68   if (lhs == nullptr) {
69     ADD_FAILURE() << "lhs is nullptr, but rhs is not";
70     return;
71   }
72 
73   if (rhs == nullptr) {
74     ADD_FAILURE() << "rhs is nullptr, but lhs is not";
75     return;
76   }
77 
78   if (1 != EVP_PKEY_cmp(lhs->private_key.private_key(),
79                         rhs->private_key.private_key())) {
80     ADD_FAILURE() << "Private keys mismatch";
81     return;
82   }
83 
84   const ClientProofSource::Chain* lhs_chain = lhs->chain.get();
85   const ClientProofSource::Chain* rhs_chain = rhs->chain.get();
86 
87   if (lhs_chain == rhs_chain) {
88     return;
89   }
90 
91   if (lhs_chain == nullptr) {
92     ADD_FAILURE() << "lhs->chain is nullptr, but rhs->chain is not";
93     return;
94   }
95 
96   if (rhs_chain == nullptr) {
97     ADD_FAILURE() << "rhs->chain is nullptr, but lhs->chain is not";
98     return;
99   }
100 
101   if (lhs_chain->certs.size() != rhs_chain->certs.size()) {
102     ADD_FAILURE() << "Cert chain length differ. lhs:" << lhs_chain->certs.size()
103                   << ", rhs:" << rhs_chain->certs.size();
104     return;
105   }
106 
107   for (size_t i = 0; i < lhs_chain->certs.size(); ++i) {
108     if (lhs_chain->certs[i] != rhs_chain->certs[i]) {
109       ADD_FAILURE() << "The " << i << "-th certs differ.";
110       return;
111     }
112   }
113 
114   // All good.
115 }
116 
TEST(DefaultClientProofSource,FullDomain)117 TEST(DefaultClientProofSource, FullDomain) {
118   DefaultClientProofSource proof_source;
119   ASSERT_TRUE(proof_source.AddCertAndKey({"www.google.com"}, TestCertChain(),
120                                          TestPrivateKey()));
121   VERIFY_CERT_AND_KEY_MATCHES(proof_source.GetCertAndKey("www.google.com"),
122                               TestCertAndKey());
123   EXPECT_EQ(proof_source.GetCertAndKey("*.google.com"), nullptr);
124   EXPECT_EQ(proof_source.GetCertAndKey("*"), nullptr);
125 }
126 
TEST(DefaultClientProofSource,WildcardDomain)127 TEST(DefaultClientProofSource, WildcardDomain) {
128   DefaultClientProofSource proof_source;
129   ASSERT_TRUE(proof_source.AddCertAndKey({"*.google.com"}, TestCertChain(),
130                                          TestPrivateKey()));
131   VERIFY_CERT_AND_KEY_MATCHES(proof_source.GetCertAndKey("www.google.com"),
132                               TestCertAndKey());
133   VERIFY_CERT_AND_KEY_MATCHES(proof_source.GetCertAndKey("*.google.com"),
134                               TestCertAndKey());
135   EXPECT_EQ(proof_source.GetCertAndKey("*"), nullptr);
136 }
137 
TEST(DefaultClientProofSource,DefaultDomain)138 TEST(DefaultClientProofSource, DefaultDomain) {
139   DefaultClientProofSource proof_source;
140   ASSERT_TRUE(
141       proof_source.AddCertAndKey({"*"}, TestCertChain(), TestPrivateKey()));
142   VERIFY_CERT_AND_KEY_MATCHES(proof_source.GetCertAndKey("www.google.com"),
143                               TestCertAndKey());
144   VERIFY_CERT_AND_KEY_MATCHES(proof_source.GetCertAndKey("*.google.com"),
145                               TestCertAndKey());
146   VERIFY_CERT_AND_KEY_MATCHES(proof_source.GetCertAndKey("*"),
147                               TestCertAndKey());
148 }
149 
TEST(DefaultClientProofSource,FullAndWildcard)150 TEST(DefaultClientProofSource, FullAndWildcard) {
151   DefaultClientProofSource proof_source;
152   ASSERT_TRUE(proof_source.AddCertAndKey({"www.google.com", "*.google.com"},
153                                          TestCertChain(), TestPrivateKey()));
154   VERIFY_CERT_AND_KEY_MATCHES(proof_source.GetCertAndKey("www.google.com"),
155                               TestCertAndKey());
156   VERIFY_CERT_AND_KEY_MATCHES(proof_source.GetCertAndKey("foo.google.com"),
157                               TestCertAndKey());
158   EXPECT_EQ(proof_source.GetCertAndKey("www.example.com"), nullptr);
159   EXPECT_EQ(proof_source.GetCertAndKey("*"), nullptr);
160 }
161 
TEST(DefaultClientProofSource,FullWildcardAndDefault)162 TEST(DefaultClientProofSource, FullWildcardAndDefault) {
163   DefaultClientProofSource proof_source;
164   ASSERT_TRUE(
165       proof_source.AddCertAndKey({"www.google.com", "*.google.com", "*"},
166                                  TestCertChain(), TestPrivateKey()));
167   VERIFY_CERT_AND_KEY_MATCHES(proof_source.GetCertAndKey("www.google.com"),
168                               TestCertAndKey());
169   VERIFY_CERT_AND_KEY_MATCHES(proof_source.GetCertAndKey("foo.google.com"),
170                               TestCertAndKey());
171   VERIFY_CERT_AND_KEY_MATCHES(proof_source.GetCertAndKey("www.example.com"),
172                               TestCertAndKey());
173   VERIFY_CERT_AND_KEY_MATCHES(proof_source.GetCertAndKey("*.google.com"),
174                               TestCertAndKey());
175   VERIFY_CERT_AND_KEY_MATCHES(proof_source.GetCertAndKey("*"),
176                               TestCertAndKey());
177 }
178 
TEST(DefaultClientProofSource,EmptyCerts)179 TEST(DefaultClientProofSource, EmptyCerts) {
180   DefaultClientProofSource proof_source;
181   EXPECT_QUIC_BUG(ASSERT_FALSE(proof_source.AddCertAndKey(
182                       {"*"}, NullCertChain(), TestPrivateKey())),
183                   "Certificate chain is empty");
184 
185   EXPECT_QUIC_BUG(ASSERT_FALSE(proof_source.AddCertAndKey(
186                       {"*"}, EmptyCertChain(), TestPrivateKey())),
187                   "Certificate chain is empty");
188   EXPECT_EQ(proof_source.GetCertAndKey("*"), nullptr);
189 }
190 
TEST(DefaultClientProofSource,BadCerts)191 TEST(DefaultClientProofSource, BadCerts) {
192   DefaultClientProofSource proof_source;
193   EXPECT_QUIC_BUG(ASSERT_FALSE(proof_source.AddCertAndKey({"*"}, BadCertChain(),
194                                                           TestPrivateKey())),
195                   "Unabled to parse leaf certificate");
196   EXPECT_EQ(proof_source.GetCertAndKey("*"), nullptr);
197 }
198 
TEST(DefaultClientProofSource,KeyMismatch)199 TEST(DefaultClientProofSource, KeyMismatch) {
200   DefaultClientProofSource proof_source;
201   EXPECT_QUIC_BUG(ASSERT_FALSE(proof_source.AddCertAndKey(
202                       {"www.google.com"}, TestCertChain(), EmptyPrivateKey())),
203                   "Private key does not match the leaf certificate");
204   EXPECT_EQ(proof_source.GetCertAndKey("*"), nullptr);
205 }
206 
207 }  // namespace test
208 }  // namespace quic
209