• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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, 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   bool ok;
182   EXPECT_QUIC_BUG(
183       ok = proof_source.AddCertAndKey({"*"}, NullCertChain(), TestPrivateKey()),
184       "Certificate chain is empty");
185   ASSERT_FALSE(ok);
186 
187   EXPECT_QUIC_BUG(ok = proof_source.AddCertAndKey({"*"}, EmptyCertChain(),
188                                                   TestPrivateKey()),
189                   "Certificate chain is empty");
190   ASSERT_FALSE(ok);
191   EXPECT_EQ(proof_source.GetCertAndKey("*"), nullptr);
192 }
193 
TEST(DefaultClientProofSource,BadCerts)194 TEST(DefaultClientProofSource, BadCerts) {
195   DefaultClientProofSource proof_source;
196   bool ok;
197   EXPECT_QUIC_BUG(
198       ok = proof_source.AddCertAndKey({"*"}, BadCertChain(), TestPrivateKey()),
199       "Unabled to parse leaf certificate");
200   ASSERT_FALSE(ok);
201   EXPECT_EQ(proof_source.GetCertAndKey("*"), nullptr);
202 }
203 
TEST(DefaultClientProofSource,KeyMismatch)204 TEST(DefaultClientProofSource, KeyMismatch) {
205   DefaultClientProofSource proof_source;
206   bool ok;
207   EXPECT_QUIC_BUG(ok = proof_source.AddCertAndKey(
208                       {"www.google.com"}, TestCertChain(), EmptyPrivateKey()),
209                   "Private key does not match the leaf certificate");
210   ASSERT_FALSE(ok);
211   EXPECT_EQ(proof_source.GetCertAndKey("*"), nullptr);
212 }
213 
214 }  // namespace test
215 }  // namespace quic
216