OLD | NEW |
| (Empty) |
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 "net/cert/x509_certificate.h" | |
6 | |
7 #include "base/basictypes.h" | |
8 #include "base/files/file_path.h" | |
9 #include "base/memory/scoped_ptr.h" | |
10 #include "base/pickle.h" | |
11 #include "base/sha1.h" | |
12 #include "base/strings/string_number_conversions.h" | |
13 #include "base/strings/string_split.h" | |
14 #include "base/strings/string_util.h" | |
15 #include "crypto/rsa_private_key.h" | |
16 #include "net/base/net_errors.h" | |
17 #include "net/base/test_data_directory.h" | |
18 #include "net/cert/asn1_util.h" | |
19 #include "net/test/cert_test_util.h" | |
20 #include "net/test/test_certificate_data.h" | |
21 #include "testing/gtest/include/gtest/gtest.h" | |
22 | |
23 #if defined(USE_NSS) | |
24 #include <cert.h> | |
25 #endif | |
26 | |
27 #if defined(OS_WIN) | |
28 #include "base/win/windows_version.h" | |
29 #endif | |
30 | |
31 using base::HexEncode; | |
32 using base::Time; | |
33 | |
34 namespace net { | |
35 | |
36 // Certificates for test data. They're obtained with: | |
37 // | |
38 // $ openssl s_client -connect [host]:443 -showcerts > /tmp/host.pem < /dev/null | |
39 // $ openssl x509 -inform PEM -outform DER < /tmp/host.pem > /tmp/host.der | |
40 // | |
41 // For fingerprint | |
42 // $ openssl x509 -inform DER -fingerprint -noout < /tmp/host.der | |
43 | |
44 // For valid_start, valid_expiry | |
45 // $ openssl x509 -inform DER -text -noout < /tmp/host.der | | |
46 // grep -A 2 Validity | |
47 // $ date +%s -d '<date str>' | |
48 | |
49 // Google's cert. | |
50 uint8 google_fingerprint[] = { | |
51 0xab, 0xbe, 0x5e, 0xb4, 0x93, 0x88, 0x4e, 0xe4, 0x60, 0xc6, 0xef, 0xf8, | |
52 0xea, 0xd4, 0xb1, 0x55, 0x4b, 0xc9, 0x59, 0x3c | |
53 }; | |
54 | |
55 // webkit.org's cert. | |
56 uint8 webkit_fingerprint[] = { | |
57 0xa1, 0x4a, 0x94, 0x46, 0x22, 0x8e, 0x70, 0x66, 0x2b, 0x94, 0xf9, 0xf8, | |
58 0x57, 0x83, 0x2d, 0xa2, 0xff, 0xbc, 0x84, 0xc2 | |
59 }; | |
60 | |
61 // thawte.com's cert (it's EV-licious!). | |
62 uint8 thawte_fingerprint[] = { | |
63 0x85, 0x04, 0x2d, 0xfd, 0x2b, 0x0e, 0xc6, 0xc8, 0xaf, 0x2d, 0x77, 0xd6, | |
64 0xa1, 0x3a, 0x64, 0x04, 0x27, 0x90, 0x97, 0x37 | |
65 }; | |
66 | |
67 // A certificate for https://www.unosoft.hu/, whose AIA extension contains | |
68 // an LDAP URL without a host name. | |
69 uint8 unosoft_hu_fingerprint[] = { | |
70 0x32, 0xff, 0xe3, 0xbe, 0x2c, 0x3b, 0xc7, 0xca, 0xbf, 0x2d, 0x64, 0xbd, | |
71 0x25, 0x66, 0xf2, 0xec, 0x8b, 0x0f, 0xbf, 0xd8 | |
72 }; | |
73 | |
74 // The fingerprint of the Google certificate used in the parsing tests, | |
75 // which is newer than the one included in the x509_certificate_data.h | |
76 uint8 google_parse_fingerprint[] = { | |
77 0x40, 0x50, 0x62, 0xe5, 0xbe, 0xfd, 0xe4, 0xaf, 0x97, 0xe9, 0x38, 0x2a, | |
78 0xf1, 0x6c, 0xc8, 0x7c, 0x8f, 0xb7, 0xc4, 0xe2 | |
79 }; | |
80 | |
81 // The fingerprint for the Thawte SGC certificate | |
82 uint8 thawte_parse_fingerprint[] = { | |
83 0xec, 0x07, 0x10, 0x03, 0xd8, 0xf5, 0xa3, 0x7f, 0x42, 0xc4, 0x55, 0x7f, | |
84 0x65, 0x6a, 0xae, 0x86, 0x65, 0xfa, 0x4b, 0x02 | |
85 }; | |
86 | |
87 // Dec 18 00:00:00 2009 GMT | |
88 const double kGoogleParseValidFrom = 1261094400; | |
89 // Dec 18 23:59:59 2011 GMT | |
90 const double kGoogleParseValidTo = 1324252799; | |
91 | |
92 void CheckGoogleCert(const scoped_refptr<X509Certificate>& google_cert, | |
93 uint8* expected_fingerprint, | |
94 double valid_from, double valid_to) { | |
95 ASSERT_NE(static_cast<X509Certificate*>(NULL), google_cert.get()); | |
96 | |
97 const CertPrincipal& subject = google_cert->subject(); | |
98 EXPECT_EQ("www.google.com", subject.common_name); | |
99 EXPECT_EQ("Mountain View", subject.locality_name); | |
100 EXPECT_EQ("California", subject.state_or_province_name); | |
101 EXPECT_EQ("US", subject.country_name); | |
102 EXPECT_EQ(0U, subject.street_addresses.size()); | |
103 ASSERT_EQ(1U, subject.organization_names.size()); | |
104 EXPECT_EQ("Google Inc", subject.organization_names[0]); | |
105 EXPECT_EQ(0U, subject.organization_unit_names.size()); | |
106 EXPECT_EQ(0U, subject.domain_components.size()); | |
107 | |
108 const CertPrincipal& issuer = google_cert->issuer(); | |
109 EXPECT_EQ("Thawte SGC CA", issuer.common_name); | |
110 EXPECT_EQ("", issuer.locality_name); | |
111 EXPECT_EQ("", issuer.state_or_province_name); | |
112 EXPECT_EQ("ZA", issuer.country_name); | |
113 EXPECT_EQ(0U, issuer.street_addresses.size()); | |
114 ASSERT_EQ(1U, issuer.organization_names.size()); | |
115 EXPECT_EQ("Thawte Consulting (Pty) Ltd.", issuer.organization_names[0]); | |
116 EXPECT_EQ(0U, issuer.organization_unit_names.size()); | |
117 EXPECT_EQ(0U, issuer.domain_components.size()); | |
118 | |
119 // Use DoubleT because its epoch is the same on all platforms | |
120 const Time& valid_start = google_cert->valid_start(); | |
121 EXPECT_EQ(valid_from, valid_start.ToDoubleT()); | |
122 | |
123 const Time& valid_expiry = google_cert->valid_expiry(); | |
124 EXPECT_EQ(valid_to, valid_expiry.ToDoubleT()); | |
125 | |
126 const SHA1HashValue& fingerprint = google_cert->fingerprint(); | |
127 for (size_t i = 0; i < 20; ++i) | |
128 EXPECT_EQ(expected_fingerprint[i], fingerprint.data[i]); | |
129 | |
130 std::vector<std::string> dns_names; | |
131 google_cert->GetDNSNames(&dns_names); | |
132 ASSERT_EQ(1U, dns_names.size()); | |
133 EXPECT_EQ("www.google.com", dns_names[0]); | |
134 } | |
135 | |
136 TEST(X509CertificateTest, GoogleCertParsing) { | |
137 scoped_refptr<X509Certificate> google_cert( | |
138 X509Certificate::CreateFromBytes( | |
139 reinterpret_cast<const char*>(google_der), sizeof(google_der))); | |
140 | |
141 CheckGoogleCert(google_cert, google_fingerprint, | |
142 1238192407, // Mar 27 22:20:07 2009 GMT | |
143 1269728407); // Mar 27 22:20:07 2010 GMT | |
144 } | |
145 | |
146 TEST(X509CertificateTest, WebkitCertParsing) { | |
147 scoped_refptr<X509Certificate> webkit_cert(X509Certificate::CreateFromBytes( | |
148 reinterpret_cast<const char*>(webkit_der), sizeof(webkit_der))); | |
149 | |
150 ASSERT_NE(static_cast<X509Certificate*>(NULL), webkit_cert.get()); | |
151 | |
152 const CertPrincipal& subject = webkit_cert->subject(); | |
153 EXPECT_EQ("Cupertino", subject.locality_name); | |
154 EXPECT_EQ("California", subject.state_or_province_name); | |
155 EXPECT_EQ("US", subject.country_name); | |
156 EXPECT_EQ(0U, subject.street_addresses.size()); | |
157 ASSERT_EQ(1U, subject.organization_names.size()); | |
158 EXPECT_EQ("Apple Inc.", subject.organization_names[0]); | |
159 ASSERT_EQ(1U, subject.organization_unit_names.size()); | |
160 EXPECT_EQ("Mac OS Forge", subject.organization_unit_names[0]); | |
161 EXPECT_EQ(0U, subject.domain_components.size()); | |
162 | |
163 const CertPrincipal& issuer = webkit_cert->issuer(); | |
164 EXPECT_EQ("Go Daddy Secure Certification Authority", issuer.common_name); | |
165 EXPECT_EQ("Scottsdale", issuer.locality_name); | |
166 EXPECT_EQ("Arizona", issuer.state_or_province_name); | |
167 EXPECT_EQ("US", issuer.country_name); | |
168 EXPECT_EQ(0U, issuer.street_addresses.size()); | |
169 ASSERT_EQ(1U, issuer.organization_names.size()); | |
170 EXPECT_EQ("GoDaddy.com, Inc.", issuer.organization_names[0]); | |
171 ASSERT_EQ(1U, issuer.organization_unit_names.size()); | |
172 EXPECT_EQ("http://certificates.godaddy.com/repository", | |
173 issuer.organization_unit_names[0]); | |
174 EXPECT_EQ(0U, issuer.domain_components.size()); | |
175 | |
176 // Use DoubleT because its epoch is the same on all platforms | |
177 const Time& valid_start = webkit_cert->valid_start(); | |
178 EXPECT_EQ(1205883319, valid_start.ToDoubleT()); // Mar 18 23:35:19 2008 GMT | |
179 | |
180 const Time& valid_expiry = webkit_cert->valid_expiry(); | |
181 EXPECT_EQ(1300491319, valid_expiry.ToDoubleT()); // Mar 18 23:35:19 2011 GMT | |
182 | |
183 const SHA1HashValue& fingerprint = webkit_cert->fingerprint(); | |
184 for (size_t i = 0; i < 20; ++i) | |
185 EXPECT_EQ(webkit_fingerprint[i], fingerprint.data[i]); | |
186 | |
187 std::vector<std::string> dns_names; | |
188 webkit_cert->GetDNSNames(&dns_names); | |
189 ASSERT_EQ(2U, dns_names.size()); | |
190 EXPECT_EQ("*.webkit.org", dns_names[0]); | |
191 EXPECT_EQ("webkit.org", dns_names[1]); | |
192 | |
193 // Test that the wildcard cert matches properly. | |
194 bool unused = false; | |
195 EXPECT_TRUE(webkit_cert->VerifyNameMatch("www.webkit.org", &unused)); | |
196 EXPECT_TRUE(webkit_cert->VerifyNameMatch("foo.webkit.org", &unused)); | |
197 EXPECT_TRUE(webkit_cert->VerifyNameMatch("webkit.org", &unused)); | |
198 EXPECT_FALSE(webkit_cert->VerifyNameMatch("www.webkit.com", &unused)); | |
199 EXPECT_FALSE(webkit_cert->VerifyNameMatch("www.foo.webkit.com", &unused)); | |
200 } | |
201 | |
202 TEST(X509CertificateTest, ThawteCertParsing) { | |
203 scoped_refptr<X509Certificate> thawte_cert(X509Certificate::CreateFromBytes( | |
204 reinterpret_cast<const char*>(thawte_der), sizeof(thawte_der))); | |
205 | |
206 ASSERT_NE(static_cast<X509Certificate*>(NULL), thawte_cert.get()); | |
207 | |
208 const CertPrincipal& subject = thawte_cert->subject(); | |
209 EXPECT_EQ("www.thawte.com", subject.common_name); | |
210 EXPECT_EQ("Mountain View", subject.locality_name); | |
211 EXPECT_EQ("California", subject.state_or_province_name); | |
212 EXPECT_EQ("US", subject.country_name); | |
213 EXPECT_EQ(0U, subject.street_addresses.size()); | |
214 ASSERT_EQ(1U, subject.organization_names.size()); | |
215 EXPECT_EQ("Thawte Inc", subject.organization_names[0]); | |
216 EXPECT_EQ(0U, subject.organization_unit_names.size()); | |
217 EXPECT_EQ(0U, subject.domain_components.size()); | |
218 | |
219 const CertPrincipal& issuer = thawte_cert->issuer(); | |
220 EXPECT_EQ("thawte Extended Validation SSL CA", issuer.common_name); | |
221 EXPECT_EQ("", issuer.locality_name); | |
222 EXPECT_EQ("", issuer.state_or_province_name); | |
223 EXPECT_EQ("US", issuer.country_name); | |
224 EXPECT_EQ(0U, issuer.street_addresses.size()); | |
225 ASSERT_EQ(1U, issuer.organization_names.size()); | |
226 EXPECT_EQ("thawte, Inc.", issuer.organization_names[0]); | |
227 ASSERT_EQ(1U, issuer.organization_unit_names.size()); | |
228 EXPECT_EQ("Terms of use at https://www.thawte.com/cps (c)06", | |
229 issuer.organization_unit_names[0]); | |
230 EXPECT_EQ(0U, issuer.domain_components.size()); | |
231 | |
232 // Use DoubleT because its epoch is the same on all platforms | |
233 const Time& valid_start = thawte_cert->valid_start(); | |
234 EXPECT_EQ(1227052800, valid_start.ToDoubleT()); // Nov 19 00:00:00 2008 GMT | |
235 | |
236 const Time& valid_expiry = thawte_cert->valid_expiry(); | |
237 EXPECT_EQ(1263772799, valid_expiry.ToDoubleT()); // Jan 17 23:59:59 2010 GMT | |
238 | |
239 const SHA1HashValue& fingerprint = thawte_cert->fingerprint(); | |
240 for (size_t i = 0; i < 20; ++i) | |
241 EXPECT_EQ(thawte_fingerprint[i], fingerprint.data[i]); | |
242 | |
243 std::vector<std::string> dns_names; | |
244 thawte_cert->GetDNSNames(&dns_names); | |
245 ASSERT_EQ(1U, dns_names.size()); | |
246 EXPECT_EQ("www.thawte.com", dns_names[0]); | |
247 } | |
248 | |
249 // Test that all desired AttributeAndValue pairs can be extracted when only | |
250 // a single RelativeDistinguishedName is present. "Normally" there is only | |
251 // one AVA per RDN, but some CAs place all AVAs within a single RDN. | |
252 // This is a regression test for http://crbug.com/101009 | |
253 TEST(X509CertificateTest, MultivalueRDN) { | |
254 base::FilePath certs_dir = GetTestCertsDirectory(); | |
255 | |
256 scoped_refptr<X509Certificate> multivalue_rdn_cert = | |
257 ImportCertFromFile(certs_dir, "multivalue_rdn.pem"); | |
258 ASSERT_NE(static_cast<X509Certificate*>(NULL), multivalue_rdn_cert.get()); | |
259 | |
260 const CertPrincipal& subject = multivalue_rdn_cert->subject(); | |
261 EXPECT_EQ("Multivalue RDN Test", subject.common_name); | |
262 EXPECT_EQ("", subject.locality_name); | |
263 EXPECT_EQ("", subject.state_or_province_name); | |
264 EXPECT_EQ("US", subject.country_name); | |
265 EXPECT_EQ(0U, subject.street_addresses.size()); | |
266 ASSERT_EQ(1U, subject.organization_names.size()); | |
267 EXPECT_EQ("Chromium", subject.organization_names[0]); | |
268 ASSERT_EQ(1U, subject.organization_unit_names.size()); | |
269 EXPECT_EQ("Chromium net_unittests", subject.organization_unit_names[0]); | |
270 ASSERT_EQ(1U, subject.domain_components.size()); | |
271 EXPECT_EQ("Chromium", subject.domain_components[0]); | |
272 } | |
273 | |
274 // Test that characters which would normally be escaped in the string form, | |
275 // such as '=' or '"', are not escaped when parsed as individual components. | |
276 // This is a regression test for http://crbug.com/102839 | |
277 TEST(X509CertificateTest, UnescapedSpecialCharacters) { | |
278 base::FilePath certs_dir = GetTestCertsDirectory(); | |
279 | |
280 scoped_refptr<X509Certificate> unescaped_cert = | |
281 ImportCertFromFile(certs_dir, "unescaped.pem"); | |
282 ASSERT_NE(static_cast<X509Certificate*>(NULL), unescaped_cert.get()); | |
283 | |
284 const CertPrincipal& subject = unescaped_cert->subject(); | |
285 EXPECT_EQ("127.0.0.1", subject.common_name); | |
286 EXPECT_EQ("Mountain View", subject.locality_name); | |
287 EXPECT_EQ("California", subject.state_or_province_name); | |
288 EXPECT_EQ("US", subject.country_name); | |
289 ASSERT_EQ(1U, subject.street_addresses.size()); | |
290 EXPECT_EQ("1600 Amphitheatre Parkway", subject.street_addresses[0]); | |
291 ASSERT_EQ(1U, subject.organization_names.size()); | |
292 EXPECT_EQ("Chromium = \"net_unittests\"", subject.organization_names[0]); | |
293 ASSERT_EQ(2U, subject.organization_unit_names.size()); | |
294 EXPECT_EQ("net_unittests", subject.organization_unit_names[0]); | |
295 EXPECT_EQ("Chromium", subject.organization_unit_names[1]); | |
296 EXPECT_EQ(0U, subject.domain_components.size()); | |
297 } | |
298 | |
299 TEST(X509CertificateTest, SerialNumbers) { | |
300 scoped_refptr<X509Certificate> google_cert( | |
301 X509Certificate::CreateFromBytes( | |
302 reinterpret_cast<const char*>(google_der), sizeof(google_der))); | |
303 | |
304 static const uint8 google_serial[16] = { | |
305 0x01,0x2a,0x39,0x76,0x0d,0x3f,0x4f,0xc9, | |
306 0x0b,0xe7,0xbd,0x2b,0xcf,0x95,0x2e,0x7a, | |
307 }; | |
308 | |
309 ASSERT_EQ(sizeof(google_serial), google_cert->serial_number().size()); | |
310 EXPECT_TRUE(memcmp(google_cert->serial_number().data(), google_serial, | |
311 sizeof(google_serial)) == 0); | |
312 | |
313 // We also want to check a serial number where the first byte is >= 0x80 in | |
314 // case the underlying library tries to pad it. | |
315 scoped_refptr<X509Certificate> paypal_null_cert( | |
316 X509Certificate::CreateFromBytes( | |
317 reinterpret_cast<const char*>(paypal_null_der), | |
318 sizeof(paypal_null_der))); | |
319 | |
320 static const uint8 paypal_null_serial[3] = {0x00, 0xf0, 0x9b}; | |
321 ASSERT_EQ(sizeof(paypal_null_serial), | |
322 paypal_null_cert->serial_number().size()); | |
323 EXPECT_TRUE(memcmp(paypal_null_cert->serial_number().data(), | |
324 paypal_null_serial, sizeof(paypal_null_serial)) == 0); | |
325 } | |
326 | |
327 TEST(X509CertificateTest, SHA256FingerprintsCorrectly) { | |
328 scoped_refptr<X509Certificate> google_cert(X509Certificate::CreateFromBytes( | |
329 reinterpret_cast<const char*>(google_der), sizeof(google_der))); | |
330 | |
331 static const uint8 google_sha256_fingerprint[32] = { | |
332 0x21, 0xaf, 0x58, 0x74, 0xea, 0x6b, 0xad, 0xbd, 0xe4, 0xb3, 0xb1, | |
333 0xaa, 0x53, 0x32, 0x80, 0x8f, 0xbf, 0x8a, 0x24, 0x7d, 0x98, 0xec, | |
334 0x7f, 0x77, 0x49, 0x38, 0x42, 0x81, 0x26, 0x7f, 0xed, 0x38}; | |
335 | |
336 SHA256HashValue fingerprint = | |
337 X509Certificate::CalculateFingerprint256(google_cert->os_cert_handle()); | |
338 | |
339 for (size_t i = 0; i < 32; ++i) | |
340 EXPECT_EQ(google_sha256_fingerprint[i], fingerprint.data[i]); | |
341 } | |
342 | |
343 TEST(X509CertificateTest, CAFingerprints) { | |
344 base::FilePath certs_dir = GetTestCertsDirectory(); | |
345 | |
346 scoped_refptr<X509Certificate> server_cert = | |
347 ImportCertFromFile(certs_dir, "salesforce_com_test.pem"); | |
348 ASSERT_NE(static_cast<X509Certificate*>(NULL), server_cert.get()); | |
349 | |
350 scoped_refptr<X509Certificate> intermediate_cert1 = | |
351 ImportCertFromFile(certs_dir, "verisign_intermediate_ca_2011.pem"); | |
352 ASSERT_NE(static_cast<X509Certificate*>(NULL), intermediate_cert1.get()); | |
353 | |
354 scoped_refptr<X509Certificate> intermediate_cert2 = | |
355 ImportCertFromFile(certs_dir, "verisign_intermediate_ca_2016.pem"); | |
356 ASSERT_NE(static_cast<X509Certificate*>(NULL), intermediate_cert2.get()); | |
357 | |
358 X509Certificate::OSCertHandles intermediates; | |
359 intermediates.push_back(intermediate_cert1->os_cert_handle()); | |
360 scoped_refptr<X509Certificate> cert_chain1 = | |
361 X509Certificate::CreateFromHandle(server_cert->os_cert_handle(), | |
362 intermediates); | |
363 | |
364 intermediates.clear(); | |
365 intermediates.push_back(intermediate_cert2->os_cert_handle()); | |
366 scoped_refptr<X509Certificate> cert_chain2 = | |
367 X509Certificate::CreateFromHandle(server_cert->os_cert_handle(), | |
368 intermediates); | |
369 | |
370 // No intermediate CA certicates. | |
371 intermediates.clear(); | |
372 scoped_refptr<X509Certificate> cert_chain3 = | |
373 X509Certificate::CreateFromHandle(server_cert->os_cert_handle(), | |
374 intermediates); | |
375 | |
376 static const uint8 cert_chain1_ca_fingerprint[20] = { | |
377 0xc2, 0xf0, 0x08, 0x7d, 0x01, 0xe6, 0x86, 0x05, 0x3a, 0x4d, | |
378 0x63, 0x3e, 0x7e, 0x70, 0xd4, 0xef, 0x65, 0xc2, 0xcc, 0x4f | |
379 }; | |
380 static const uint8 cert_chain2_ca_fingerprint[20] = { | |
381 0xd5, 0x59, 0xa5, 0x86, 0x66, 0x9b, 0x08, 0xf4, 0x6a, 0x30, | |
382 0xa1, 0x33, 0xf8, 0xa9, 0xed, 0x3d, 0x03, 0x8e, 0x2e, 0xa8 | |
383 }; | |
384 // The SHA-1 hash of nothing. | |
385 static const uint8 cert_chain3_ca_fingerprint[20] = { | |
386 0xda, 0x39, 0xa3, 0xee, 0x5e, 0x6b, 0x4b, 0x0d, 0x32, 0x55, | |
387 0xbf, 0xef, 0x95, 0x60, 0x18, 0x90, 0xaf, 0xd8, 0x07, 0x09 | |
388 }; | |
389 EXPECT_TRUE(memcmp(cert_chain1->ca_fingerprint().data, | |
390 cert_chain1_ca_fingerprint, 20) == 0); | |
391 EXPECT_TRUE(memcmp(cert_chain2->ca_fingerprint().data, | |
392 cert_chain2_ca_fingerprint, 20) == 0); | |
393 EXPECT_TRUE(memcmp(cert_chain3->ca_fingerprint().data, | |
394 cert_chain3_ca_fingerprint, 20) == 0); | |
395 | |
396 // Test the SHA-256 hash calculation functions explicitly since they are not | |
397 // used by X509Certificate internally. | |
398 static const uint8 cert_chain1_ca_fingerprint_256[32] = { | |
399 0x51, 0x15, 0x30, 0x49, 0x97, 0x54, 0xf8, 0xb4, 0x17, 0x41, | |
400 0x6b, 0x58, 0x78, 0xb0, 0x89, 0xd2, 0xc3, 0xae, 0x66, 0xc1, | |
401 0x16, 0x80, 0xa0, 0x78, 0xe7, 0x53, 0x45, 0xa2, 0xfb, 0x80, | |
402 0xe1, 0x07 | |
403 }; | |
404 static const uint8 cert_chain2_ca_fingerprint_256[32] = { | |
405 0x00, 0xbd, 0x2b, 0x0e, 0xdd, 0x83, 0x40, 0xb1, 0x74, 0x6c, | |
406 0xc3, 0x95, 0xc0, 0xe3, 0x55, 0xb2, 0x16, 0x58, 0x53, 0xfd, | |
407 0xb9, 0x3c, 0x52, 0xda, 0xdd, 0xa8, 0x22, 0x8b, 0x07, 0x00, | |
408 0x2d, 0xce | |
409 }; | |
410 // The SHA-256 hash of nothing. | |
411 static const uint8 cert_chain3_ca_fingerprint_256[32] = { | |
412 0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14, 0x9a, 0xfb, | |
413 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24, 0x27, 0xae, 0x41, 0xe4, | |
414 0x64, 0x9b, 0x93, 0x4c, 0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, | |
415 0xb8, 0x55 | |
416 }; | |
417 SHA256HashValue ca_fingerprint_256_1 = | |
418 X509Certificate::CalculateCAFingerprint256( | |
419 cert_chain1->GetIntermediateCertificates()); | |
420 SHA256HashValue ca_fingerprint_256_2 = | |
421 X509Certificate::CalculateCAFingerprint256( | |
422 cert_chain2->GetIntermediateCertificates()); | |
423 SHA256HashValue ca_fingerprint_256_3 = | |
424 X509Certificate::CalculateCAFingerprint256( | |
425 cert_chain3->GetIntermediateCertificates()); | |
426 EXPECT_TRUE(memcmp(ca_fingerprint_256_1.data, | |
427 cert_chain1_ca_fingerprint_256, 32) == 0); | |
428 EXPECT_TRUE(memcmp(ca_fingerprint_256_2.data, | |
429 cert_chain2_ca_fingerprint_256, 32) == 0); | |
430 EXPECT_TRUE(memcmp(ca_fingerprint_256_3.data, | |
431 cert_chain3_ca_fingerprint_256, 32) == 0); | |
432 | |
433 static const uint8 cert_chain1_chain_fingerprint_256[32] = { | |
434 0xac, 0xff, 0xcc, 0x63, 0x0d, 0xd0, 0xa7, 0x19, 0x78, 0xb5, | |
435 0x8a, 0x47, 0x8b, 0x67, 0x97, 0xcb, 0x8d, 0xe1, 0x6a, 0x8a, | |
436 0x57, 0x70, 0xda, 0x9a, 0x53, 0x72, 0xe2, 0xa0, 0x08, 0xab, | |
437 0xcc, 0x8f | |
438 }; | |
439 static const uint8 cert_chain2_chain_fingerprint_256[32] = { | |
440 0x67, 0x3a, 0x11, 0x20, 0xd6, 0x94, 0x14, 0xe4, 0x16, 0x9f, | |
441 0x58, 0xe2, 0x8b, 0xf7, 0x27, 0xed, 0xbb, 0xe8, 0xa7, 0xff, | |
442 0x1c, 0x8c, 0x0f, 0x21, 0x38, 0x16, 0x7c, 0xad, 0x1f, 0x22, | |
443 0x6f, 0x9b | |
444 }; | |
445 static const uint8 cert_chain3_chain_fingerprint_256[32] = { | |
446 0x16, 0x7a, 0xbd, 0xb4, 0x57, 0x04, 0x65, 0x3c, 0x3b, 0xef, | |
447 0x6e, 0x6a, 0xa6, 0x02, 0x73, 0x30, 0x3e, 0x34, 0x1b, 0x43, | |
448 0xc2, 0x7c, 0x98, 0x52, 0x9f, 0x34, 0x7f, 0x55, 0x97, 0xe9, | |
449 0x1a, 0x10 | |
450 }; | |
451 SHA256HashValue chain_fingerprint_256_1 = | |
452 X509Certificate::CalculateChainFingerprint256( | |
453 cert_chain1->os_cert_handle(), | |
454 cert_chain1->GetIntermediateCertificates()); | |
455 SHA256HashValue chain_fingerprint_256_2 = | |
456 X509Certificate::CalculateChainFingerprint256( | |
457 cert_chain2->os_cert_handle(), | |
458 cert_chain2->GetIntermediateCertificates()); | |
459 SHA256HashValue chain_fingerprint_256_3 = | |
460 X509Certificate::CalculateChainFingerprint256( | |
461 cert_chain3->os_cert_handle(), | |
462 cert_chain3->GetIntermediateCertificates()); | |
463 EXPECT_TRUE(memcmp(chain_fingerprint_256_1.data, | |
464 cert_chain1_chain_fingerprint_256, 32) == 0); | |
465 EXPECT_TRUE(memcmp(chain_fingerprint_256_2.data, | |
466 cert_chain2_chain_fingerprint_256, 32) == 0); | |
467 EXPECT_TRUE(memcmp(chain_fingerprint_256_3.data, | |
468 cert_chain3_chain_fingerprint_256, 32) == 0); | |
469 } | |
470 | |
471 TEST(X509CertificateTest, ParseSubjectAltNames) { | |
472 base::FilePath certs_dir = GetTestCertsDirectory(); | |
473 | |
474 scoped_refptr<X509Certificate> san_cert = | |
475 ImportCertFromFile(certs_dir, "subjectAltName_sanity_check.pem"); | |
476 ASSERT_NE(static_cast<X509Certificate*>(NULL), san_cert.get()); | |
477 | |
478 std::vector<std::string> dns_names; | |
479 std::vector<std::string> ip_addresses; | |
480 san_cert->GetSubjectAltName(&dns_names, &ip_addresses); | |
481 | |
482 // Ensure that DNS names are correctly parsed. | |
483 ASSERT_EQ(1U, dns_names.size()); | |
484 EXPECT_EQ("test.example", dns_names[0]); | |
485 | |
486 // Ensure that both IPv4 and IPv6 addresses are correctly parsed. | |
487 ASSERT_EQ(2U, ip_addresses.size()); | |
488 | |
489 static const uint8 kIPv4Address[] = { | |
490 0x7F, 0x00, 0x00, 0x02 | |
491 }; | |
492 ASSERT_EQ(arraysize(kIPv4Address), ip_addresses[0].size()); | |
493 EXPECT_EQ(0, memcmp(ip_addresses[0].data(), kIPv4Address, | |
494 arraysize(kIPv4Address))); | |
495 | |
496 static const uint8 kIPv6Address[] = { | |
497 0xFE, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |
498 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 | |
499 }; | |
500 ASSERT_EQ(arraysize(kIPv6Address), ip_addresses[1].size()); | |
501 EXPECT_EQ(0, memcmp(ip_addresses[1].data(), kIPv6Address, | |
502 arraysize(kIPv6Address))); | |
503 | |
504 // Ensure the subjectAltName dirName has not influenced the handling of | |
505 // the subject commonName. | |
506 EXPECT_EQ("127.0.0.1", san_cert->subject().common_name); | |
507 } | |
508 | |
509 TEST(X509CertificateTest, ExtractSPKIFromDERCert) { | |
510 base::FilePath certs_dir = GetTestCertsDirectory(); | |
511 scoped_refptr<X509Certificate> cert = | |
512 ImportCertFromFile(certs_dir, "nist.der"); | |
513 ASSERT_NE(static_cast<X509Certificate*>(NULL), cert.get()); | |
514 | |
515 std::string derBytes; | |
516 EXPECT_TRUE(X509Certificate::GetDEREncoded(cert->os_cert_handle(), | |
517 &derBytes)); | |
518 | |
519 base::StringPiece spkiBytes; | |
520 EXPECT_TRUE(asn1::ExtractSPKIFromDERCert(derBytes, &spkiBytes)); | |
521 | |
522 uint8 hash[base::kSHA1Length]; | |
523 base::SHA1HashBytes(reinterpret_cast<const uint8*>(spkiBytes.data()), | |
524 spkiBytes.size(), hash); | |
525 | |
526 EXPECT_EQ(0, memcmp(hash, kNistSPKIHash, sizeof(hash))); | |
527 } | |
528 | |
529 TEST(X509CertificateTest, ExtractCRLURLsFromDERCert) { | |
530 base::FilePath certs_dir = GetTestCertsDirectory(); | |
531 scoped_refptr<X509Certificate> cert = | |
532 ImportCertFromFile(certs_dir, "nist.der"); | |
533 ASSERT_NE(static_cast<X509Certificate*>(NULL), cert.get()); | |
534 | |
535 std::string derBytes; | |
536 EXPECT_TRUE(X509Certificate::GetDEREncoded(cert->os_cert_handle(), | |
537 &derBytes)); | |
538 | |
539 std::vector<base::StringPiece> crl_urls; | |
540 EXPECT_TRUE(asn1::ExtractCRLURLsFromDERCert(derBytes, &crl_urls)); | |
541 | |
542 EXPECT_EQ(1u, crl_urls.size()); | |
543 if (crl_urls.size() > 0) { | |
544 EXPECT_EQ("http://SVRSecure-G3-crl.verisign.com/SVRSecureG3.crl", | |
545 crl_urls[0].as_string()); | |
546 } | |
547 } | |
548 | |
549 // Tests X509CertificateCache via X509Certificate::CreateFromHandle. We | |
550 // call X509Certificate::CreateFromHandle several times and observe whether | |
551 // it returns a cached or new OSCertHandle. | |
552 TEST(X509CertificateTest, Cache) { | |
553 X509Certificate::OSCertHandle google_cert_handle; | |
554 X509Certificate::OSCertHandle thawte_cert_handle; | |
555 | |
556 // Add a single certificate to the certificate cache. | |
557 google_cert_handle = X509Certificate::CreateOSCertHandleFromBytes( | |
558 reinterpret_cast<const char*>(google_der), sizeof(google_der)); | |
559 scoped_refptr<X509Certificate> cert1(X509Certificate::CreateFromHandle( | |
560 google_cert_handle, X509Certificate::OSCertHandles())); | |
561 X509Certificate::FreeOSCertHandle(google_cert_handle); | |
562 | |
563 // Add the same certificate, but as a new handle. | |
564 google_cert_handle = X509Certificate::CreateOSCertHandleFromBytes( | |
565 reinterpret_cast<const char*>(google_der), sizeof(google_der)); | |
566 scoped_refptr<X509Certificate> cert2(X509Certificate::CreateFromHandle( | |
567 google_cert_handle, X509Certificate::OSCertHandles())); | |
568 X509Certificate::FreeOSCertHandle(google_cert_handle); | |
569 | |
570 // A new X509Certificate should be returned. | |
571 EXPECT_NE(cert1.get(), cert2.get()); | |
572 // But both instances should share the underlying OS certificate handle. | |
573 EXPECT_EQ(cert1->os_cert_handle(), cert2->os_cert_handle()); | |
574 EXPECT_EQ(0u, cert1->GetIntermediateCertificates().size()); | |
575 EXPECT_EQ(0u, cert2->GetIntermediateCertificates().size()); | |
576 | |
577 // Add the same certificate, but this time with an intermediate. This | |
578 // should result in the intermediate being cached. Note that this is not | |
579 // a legitimate chain, but is suitable for testing. | |
580 google_cert_handle = X509Certificate::CreateOSCertHandleFromBytes( | |
581 reinterpret_cast<const char*>(google_der), sizeof(google_der)); | |
582 thawte_cert_handle = X509Certificate::CreateOSCertHandleFromBytes( | |
583 reinterpret_cast<const char*>(thawte_der), sizeof(thawte_der)); | |
584 X509Certificate::OSCertHandles intermediates; | |
585 intermediates.push_back(thawte_cert_handle); | |
586 scoped_refptr<X509Certificate> cert3(X509Certificate::CreateFromHandle( | |
587 google_cert_handle, intermediates)); | |
588 X509Certificate::FreeOSCertHandle(google_cert_handle); | |
589 X509Certificate::FreeOSCertHandle(thawte_cert_handle); | |
590 | |
591 // Test that the new certificate, even with intermediates, results in the | |
592 // same underlying handle being used. | |
593 EXPECT_EQ(cert1->os_cert_handle(), cert3->os_cert_handle()); | |
594 // Though they use the same OS handle, the intermediates should be different. | |
595 EXPECT_NE(cert1->GetIntermediateCertificates().size(), | |
596 cert3->GetIntermediateCertificates().size()); | |
597 } | |
598 | |
599 TEST(X509CertificateTest, Pickle) { | |
600 X509Certificate::OSCertHandle google_cert_handle = | |
601 X509Certificate::CreateOSCertHandleFromBytes( | |
602 reinterpret_cast<const char*>(google_der), sizeof(google_der)); | |
603 X509Certificate::OSCertHandle thawte_cert_handle = | |
604 X509Certificate::CreateOSCertHandleFromBytes( | |
605 reinterpret_cast<const char*>(thawte_der), sizeof(thawte_der)); | |
606 | |
607 X509Certificate::OSCertHandles intermediates; | |
608 intermediates.push_back(thawte_cert_handle); | |
609 scoped_refptr<X509Certificate> cert = X509Certificate::CreateFromHandle( | |
610 google_cert_handle, intermediates); | |
611 ASSERT_NE(static_cast<X509Certificate*>(NULL), cert.get()); | |
612 | |
613 X509Certificate::FreeOSCertHandle(google_cert_handle); | |
614 X509Certificate::FreeOSCertHandle(thawte_cert_handle); | |
615 | |
616 Pickle pickle; | |
617 cert->Persist(&pickle); | |
618 | |
619 PickleIterator iter(pickle); | |
620 scoped_refptr<X509Certificate> cert_from_pickle = | |
621 X509Certificate::CreateFromPickle( | |
622 &iter, X509Certificate::PICKLETYPE_CERTIFICATE_CHAIN_V3); | |
623 ASSERT_NE(static_cast<X509Certificate*>(NULL), cert_from_pickle.get()); | |
624 EXPECT_TRUE(X509Certificate::IsSameOSCert( | |
625 cert->os_cert_handle(), cert_from_pickle->os_cert_handle())); | |
626 const X509Certificate::OSCertHandles& cert_intermediates = | |
627 cert->GetIntermediateCertificates(); | |
628 const X509Certificate::OSCertHandles& pickle_intermediates = | |
629 cert_from_pickle->GetIntermediateCertificates(); | |
630 ASSERT_EQ(cert_intermediates.size(), pickle_intermediates.size()); | |
631 for (size_t i = 0; i < cert_intermediates.size(); ++i) { | |
632 EXPECT_TRUE(X509Certificate::IsSameOSCert(cert_intermediates[i], | |
633 pickle_intermediates[i])); | |
634 } | |
635 } | |
636 | |
637 TEST(X509CertificateTest, IntermediateCertificates) { | |
638 scoped_refptr<X509Certificate> webkit_cert( | |
639 X509Certificate::CreateFromBytes( | |
640 reinterpret_cast<const char*>(webkit_der), sizeof(webkit_der))); | |
641 | |
642 scoped_refptr<X509Certificate> thawte_cert( | |
643 X509Certificate::CreateFromBytes( | |
644 reinterpret_cast<const char*>(thawte_der), sizeof(thawte_der))); | |
645 | |
646 X509Certificate::OSCertHandle google_handle; | |
647 // Create object with no intermediates: | |
648 google_handle = X509Certificate::CreateOSCertHandleFromBytes( | |
649 reinterpret_cast<const char*>(google_der), sizeof(google_der)); | |
650 X509Certificate::OSCertHandles intermediates1; | |
651 scoped_refptr<X509Certificate> cert1; | |
652 cert1 = X509Certificate::CreateFromHandle(google_handle, intermediates1); | |
653 EXPECT_EQ(0u, cert1->GetIntermediateCertificates().size()); | |
654 | |
655 // Create object with 2 intermediates: | |
656 X509Certificate::OSCertHandles intermediates2; | |
657 intermediates2.push_back(webkit_cert->os_cert_handle()); | |
658 intermediates2.push_back(thawte_cert->os_cert_handle()); | |
659 scoped_refptr<X509Certificate> cert2; | |
660 cert2 = X509Certificate::CreateFromHandle(google_handle, intermediates2); | |
661 | |
662 // Verify it has all the intermediates: | |
663 const X509Certificate::OSCertHandles& cert2_intermediates = | |
664 cert2->GetIntermediateCertificates(); | |
665 ASSERT_EQ(2u, cert2_intermediates.size()); | |
666 EXPECT_TRUE(X509Certificate::IsSameOSCert(cert2_intermediates[0], | |
667 webkit_cert->os_cert_handle())); | |
668 EXPECT_TRUE(X509Certificate::IsSameOSCert(cert2_intermediates[1], | |
669 thawte_cert->os_cert_handle())); | |
670 | |
671 // Cleanup | |
672 X509Certificate::FreeOSCertHandle(google_handle); | |
673 } | |
674 | |
675 TEST(X509CertificateTest, IsIssuedByEncoded) { | |
676 base::FilePath certs_dir = GetTestCertsDirectory(); | |
677 | |
678 // Test a client certificate from MIT. | |
679 scoped_refptr<X509Certificate> mit_davidben_cert( | |
680 ImportCertFromFile(certs_dir, "mit.davidben.der")); | |
681 ASSERT_NE(static_cast<X509Certificate*>(NULL), mit_davidben_cert.get()); | |
682 | |
683 std::string mit_issuer(reinterpret_cast<const char*>(MITDN), | |
684 sizeof(MITDN)); | |
685 | |
686 // Test a certificate from Google, issued by Thawte | |
687 scoped_refptr<X509Certificate> google_cert( | |
688 ImportCertFromFile(certs_dir, "google.single.der")); | |
689 ASSERT_NE(static_cast<X509Certificate*>(NULL), google_cert.get()); | |
690 | |
691 std::string thawte_issuer(reinterpret_cast<const char*>(ThawteDN), | |
692 sizeof(ThawteDN)); | |
693 | |
694 // Check that the David Ben certificate is issued by MIT, but not | |
695 // by Thawte. | |
696 std::vector<std::string> issuers; | |
697 issuers.clear(); | |
698 issuers.push_back(mit_issuer); | |
699 EXPECT_TRUE(mit_davidben_cert->IsIssuedByEncoded(issuers)); | |
700 EXPECT_FALSE(google_cert->IsIssuedByEncoded(issuers)); | |
701 | |
702 // Check that the Google certificate is issued by Thawte and not | |
703 // by MIT. | |
704 issuers.clear(); | |
705 issuers.push_back(thawte_issuer); | |
706 EXPECT_FALSE(mit_davidben_cert->IsIssuedByEncoded(issuers)); | |
707 EXPECT_TRUE(google_cert->IsIssuedByEncoded(issuers)); | |
708 | |
709 // Check that they both pass when given a list of the two issuers. | |
710 issuers.clear(); | |
711 issuers.push_back(mit_issuer); | |
712 issuers.push_back(thawte_issuer); | |
713 EXPECT_TRUE(mit_davidben_cert->IsIssuedByEncoded(issuers)); | |
714 EXPECT_TRUE(google_cert->IsIssuedByEncoded(issuers)); | |
715 } | |
716 | |
717 TEST(X509CertificateTest, IsSelfSigned) { | |
718 base::FilePath certs_dir = GetTestCertsDirectory(); | |
719 | |
720 scoped_refptr<X509Certificate> cert( | |
721 ImportCertFromFile(certs_dir, "mit.davidben.der")); | |
722 ASSERT_NE(static_cast<X509Certificate*>(NULL), cert.get()); | |
723 EXPECT_FALSE(X509Certificate::IsSelfSigned(cert->os_cert_handle())); | |
724 | |
725 scoped_refptr<X509Certificate> self_signed( | |
726 ImportCertFromFile(certs_dir, "aia-root.pem")); | |
727 ASSERT_NE(static_cast<X509Certificate*>(NULL), self_signed.get()); | |
728 EXPECT_TRUE(X509Certificate::IsSelfSigned(self_signed->os_cert_handle())); | |
729 } | |
730 | |
731 TEST(X509CertificateTest, IsIssuedByEncodedWithIntermediates) { | |
732 static const unsigned char kPolicyRootDN[] = { | |
733 0x30, 0x1e, 0x31, 0x1c, 0x30, 0x1a, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, | |
734 0x13, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x20, 0x54, 0x65, 0x73, 0x74, | |
735 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41 | |
736 }; | |
737 static const unsigned char kPolicyIntermediateDN[] = { | |
738 0x30, 0x26, 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, | |
739 0x1b, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x20, 0x54, 0x65, 0x73, 0x74, | |
740 0x20, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x74, | |
741 0x65, 0x20, 0x43, 0x41 | |
742 }; | |
743 | |
744 base::FilePath certs_dir = GetTestCertsDirectory(); | |
745 | |
746 CertificateList policy_chain = CreateCertificateListFromFile( | |
747 certs_dir, "explicit-policy-chain.pem", X509Certificate::FORMAT_AUTO); | |
748 ASSERT_EQ(3u, policy_chain.size()); | |
749 | |
750 // The intermediate CA certificate's policyConstraints extension has a | |
751 // requireExplicitPolicy field with SkipCerts=0. | |
752 std::string policy_intermediate_dn( | |
753 reinterpret_cast<const char*>(kPolicyIntermediateDN), | |
754 sizeof(kPolicyIntermediateDN)); | |
755 std::string policy_root_dn(reinterpret_cast<const char*>(kPolicyRootDN), | |
756 sizeof(kPolicyRootDN)); | |
757 | |
758 X509Certificate::OSCertHandles intermediates; | |
759 intermediates.push_back(policy_chain[1]->os_cert_handle()); | |
760 scoped_refptr<X509Certificate> cert_chain = | |
761 X509Certificate::CreateFromHandle(policy_chain[0]->os_cert_handle(), | |
762 intermediates); | |
763 | |
764 std::vector<std::string> issuers; | |
765 | |
766 // Check that the chain is issued by the intermediate. | |
767 issuers.clear(); | |
768 issuers.push_back(policy_intermediate_dn); | |
769 EXPECT_TRUE(cert_chain->IsIssuedByEncoded(issuers)); | |
770 | |
771 // Check that the chain is also issued by the root. | |
772 issuers.clear(); | |
773 issuers.push_back(policy_root_dn); | |
774 EXPECT_TRUE(cert_chain->IsIssuedByEncoded(issuers)); | |
775 | |
776 // Check that the chain is issued by either the intermediate or the root. | |
777 issuers.clear(); | |
778 issuers.push_back(policy_intermediate_dn); | |
779 issuers.push_back(policy_root_dn); | |
780 EXPECT_TRUE(cert_chain->IsIssuedByEncoded(issuers)); | |
781 | |
782 // Check that an empty issuers list returns false. | |
783 issuers.clear(); | |
784 EXPECT_FALSE(cert_chain->IsIssuedByEncoded(issuers)); | |
785 | |
786 // Check that the chain is not issued by Verisign | |
787 std::string mit_issuer(reinterpret_cast<const char*>(VerisignDN), | |
788 sizeof(VerisignDN)); | |
789 issuers.clear(); | |
790 issuers.push_back(mit_issuer); | |
791 EXPECT_FALSE(cert_chain->IsIssuedByEncoded(issuers)); | |
792 } | |
793 | |
794 // Tests that FreeOSCertHandle ignores NULL on each OS. | |
795 TEST(X509CertificateTest, FreeNullHandle) { | |
796 X509Certificate::FreeOSCertHandle(NULL); | |
797 } | |
798 | |
799 #if defined(USE_NSS) | |
800 TEST(X509CertificateTest, GetDefaultNickname) { | |
801 base::FilePath certs_dir = GetTestCertsDirectory(); | |
802 | |
803 scoped_refptr<X509Certificate> test_cert( | |
804 ImportCertFromFile(certs_dir, "no_subject_common_name_cert.pem")); | |
805 ASSERT_NE(static_cast<X509Certificate*>(NULL), test_cert.get()); | |
806 | |
807 std::string nickname = test_cert->GetDefaultNickname(USER_CERT); | |
808 EXPECT_EQ("wtc@google.com's COMODO Client Authentication and " | |
809 "Secure Email CA ID", nickname); | |
810 } | |
811 #endif | |
812 | |
813 const struct CertificateFormatTestData { | |
814 const char* file_name; | |
815 X509Certificate::Format format; | |
816 uint8* chain_fingerprints[3]; | |
817 } kFormatTestData[] = { | |
818 // DER Parsing - single certificate, DER encoded | |
819 { "google.single.der", X509Certificate::FORMAT_SINGLE_CERTIFICATE, | |
820 { google_parse_fingerprint, | |
821 NULL, } }, | |
822 // DER parsing - single certificate, PEM encoded | |
823 { "google.single.pem", X509Certificate::FORMAT_SINGLE_CERTIFICATE, | |
824 { google_parse_fingerprint, | |
825 NULL, } }, | |
826 // PEM parsing - single certificate, PEM encoded with a PEB of | |
827 // "CERTIFICATE" | |
828 { "google.single.pem", X509Certificate::FORMAT_PEM_CERT_SEQUENCE, | |
829 { google_parse_fingerprint, | |
830 NULL, } }, | |
831 // PEM parsing - sequence of certificates, PEM encoded with a PEB of | |
832 // "CERTIFICATE" | |
833 { "google.chain.pem", X509Certificate::FORMAT_PEM_CERT_SEQUENCE, | |
834 { google_parse_fingerprint, | |
835 thawte_parse_fingerprint, | |
836 NULL, } }, | |
837 // PKCS#7 parsing - "degenerate" SignedData collection of certificates, DER | |
838 // encoding | |
839 { "google.binary.p7b", X509Certificate::FORMAT_PKCS7, | |
840 { google_parse_fingerprint, | |
841 thawte_parse_fingerprint, | |
842 NULL, } }, | |
843 // PKCS#7 parsing - "degenerate" SignedData collection of certificates, PEM | |
844 // encoded with a PEM PEB of "CERTIFICATE" | |
845 { "google.pem_cert.p7b", X509Certificate::FORMAT_PKCS7, | |
846 { google_parse_fingerprint, | |
847 thawte_parse_fingerprint, | |
848 NULL, } }, | |
849 // PKCS#7 parsing - "degenerate" SignedData collection of certificates, PEM | |
850 // encoded with a PEM PEB of "PKCS7" | |
851 { "google.pem_pkcs7.p7b", X509Certificate::FORMAT_PKCS7, | |
852 { google_parse_fingerprint, | |
853 thawte_parse_fingerprint, | |
854 NULL, } }, | |
855 // All of the above, this time using auto-detection | |
856 { "google.single.der", X509Certificate::FORMAT_AUTO, | |
857 { google_parse_fingerprint, | |
858 NULL, } }, | |
859 { "google.single.pem", X509Certificate::FORMAT_AUTO, | |
860 { google_parse_fingerprint, | |
861 NULL, } }, | |
862 { "google.chain.pem", X509Certificate::FORMAT_AUTO, | |
863 { google_parse_fingerprint, | |
864 thawte_parse_fingerprint, | |
865 NULL, } }, | |
866 { "google.binary.p7b", X509Certificate::FORMAT_AUTO, | |
867 { google_parse_fingerprint, | |
868 thawte_parse_fingerprint, | |
869 NULL, } }, | |
870 { "google.pem_cert.p7b", X509Certificate::FORMAT_AUTO, | |
871 { google_parse_fingerprint, | |
872 thawte_parse_fingerprint, | |
873 NULL, } }, | |
874 { "google.pem_pkcs7.p7b", X509Certificate::FORMAT_AUTO, | |
875 { google_parse_fingerprint, | |
876 thawte_parse_fingerprint, | |
877 NULL, } }, | |
878 }; | |
879 | |
880 class X509CertificateParseTest | |
881 : public testing::TestWithParam<CertificateFormatTestData> { | |
882 public: | |
883 virtual ~X509CertificateParseTest() {} | |
884 void SetUp() override { test_data_ = GetParam(); } | |
885 void TearDown() override {} | |
886 | |
887 protected: | |
888 CertificateFormatTestData test_data_; | |
889 }; | |
890 | |
891 TEST_P(X509CertificateParseTest, CanParseFormat) { | |
892 base::FilePath certs_dir = GetTestCertsDirectory(); | |
893 CertificateList certs = CreateCertificateListFromFile( | |
894 certs_dir, test_data_.file_name, test_data_.format); | |
895 ASSERT_FALSE(certs.empty()); | |
896 ASSERT_LE(certs.size(), arraysize(test_data_.chain_fingerprints)); | |
897 CheckGoogleCert(certs.front(), google_parse_fingerprint, | |
898 kGoogleParseValidFrom, kGoogleParseValidTo); | |
899 | |
900 size_t i; | |
901 for (i = 0; i < arraysize(test_data_.chain_fingerprints); ++i) { | |
902 if (test_data_.chain_fingerprints[i] == NULL) { | |
903 // No more test certificates expected - make sure no more were | |
904 // returned before marking this test a success. | |
905 EXPECT_EQ(i, certs.size()); | |
906 break; | |
907 } | |
908 | |
909 // A cert is expected - make sure that one was parsed. | |
910 ASSERT_LT(i, certs.size()); | |
911 | |
912 // Compare the parsed certificate with the expected certificate, by | |
913 // comparing fingerprints. | |
914 const X509Certificate* cert = certs[i].get(); | |
915 const SHA1HashValue& actual_fingerprint = cert->fingerprint(); | |
916 uint8* expected_fingerprint = test_data_.chain_fingerprints[i]; | |
917 | |
918 for (size_t j = 0; j < 20; ++j) | |
919 EXPECT_EQ(expected_fingerprint[j], actual_fingerprint.data[j]); | |
920 } | |
921 } | |
922 | |
923 INSTANTIATE_TEST_CASE_P(, X509CertificateParseTest, | |
924 testing::ValuesIn(kFormatTestData)); | |
925 | |
926 struct CertificateNameVerifyTestData { | |
927 // true iff we expect hostname to match an entry in cert_names. | |
928 bool expected; | |
929 // The hostname to match. | |
930 const char* hostname; | |
931 // Common name, may be used if |dns_names| or |ip_addrs| are empty. | |
932 const char* common_name; | |
933 // Comma separated list of certificate names to match against. Any occurrence | |
934 // of '#' will be replaced with a null character before processing. | |
935 const char* dns_names; | |
936 // Comma separated list of certificate IP Addresses to match against. Each | |
937 // address is x prefixed 16 byte hex code for v6 or dotted-decimals for v4. | |
938 const char* ip_addrs; | |
939 }; | |
940 | |
941 // GTest 'magic' pretty-printer, so that if/when a test fails, it knows how | |
942 // to output the parameter that was passed. Without this, it will simply | |
943 // attempt to print out the first twenty bytes of the object, which depending | |
944 // on platform and alignment, may result in an invalid read. | |
945 void PrintTo(const CertificateNameVerifyTestData& data, std::ostream* os) { | |
946 ASSERT_TRUE(data.hostname && data.common_name); | |
947 // Using StringPiece to allow for optional fields being NULL. | |
948 *os << " expected: " << data.expected | |
949 << "; hostname: " << data.hostname | |
950 << "; common_name: " << data.common_name | |
951 << "; dns_names: " << base::StringPiece(data.dns_names) | |
952 << "; ip_addrs: " << base::StringPiece(data.ip_addrs); | |
953 } | |
954 | |
955 const CertificateNameVerifyTestData kNameVerifyTestData[] = { | |
956 { true, "foo.com", "foo.com" }, | |
957 { true, "f", "f" }, | |
958 { false, "h", "i" }, | |
959 { true, "bar.foo.com", "*.foo.com" }, | |
960 { true, "www.test.fr", "common.name", | |
961 "*.test.com,*.test.co.uk,*.test.de,*.test.fr" }, | |
962 { true, "wwW.tESt.fr", "common.name", | |
963 ",*.*,*.test.de,*.test.FR,www" }, | |
964 { false, "f.uk", ".uk" }, | |
965 { false, "w.bar.foo.com", "?.bar.foo.com" }, | |
966 { false, "www.foo.com", "(www|ftp).foo.com" }, | |
967 { false, "www.foo.com", "www.foo.com#" }, // # = null char. | |
968 { false, "www.foo.com", "", "www.foo.com#*.foo.com,#,#" }, | |
969 { false, "www.house.example", "ww.house.example" }, | |
970 { false, "test.org", "", "www.test.org,*.test.org,*.org" }, | |
971 { false, "w.bar.foo.com", "w*.bar.foo.com" }, | |
972 { false, "www.bar.foo.com", "ww*ww.bar.foo.com" }, | |
973 { false, "wwww.bar.foo.com", "ww*ww.bar.foo.com" }, | |
974 { false, "wwww.bar.foo.com", "w*w.bar.foo.com" }, | |
975 { false, "wwww.bar.foo.com", "w*w.bar.foo.c0m" }, | |
976 { false, "WALLY.bar.foo.com", "wa*.bar.foo.com" }, | |
977 { false, "wally.bar.foo.com", "*Ly.bar.foo.com" }, | |
978 { true, "ww%57.foo.com", "", "www.foo.com" }, | |
979 { true, "www&.foo.com", "www%26.foo.com" }, | |
980 // Common name must not be used if subject alternative name was provided. | |
981 { false, "www.test.co.jp", "www.test.co.jp", | |
982 "*.test.de,*.jp,www.test.co.uk,www.*.co.jp" }, | |
983 { false, "www.bar.foo.com", "www.bar.foo.com", | |
984 "*.foo.com,*.*.foo.com,*.*.bar.foo.com,*..bar.foo.com," }, | |
985 { false, "www.bath.org", "www.bath.org", "", "20.30.40.50" }, | |
986 { false, "66.77.88.99", "www.bath.org", "www.bath.org" }, | |
987 // IDN tests | |
988 { true, "xn--poema-9qae5a.com.br", "xn--poema-9qae5a.com.br" }, | |
989 { true, "www.xn--poema-9qae5a.com.br", "*.xn--poema-9qae5a.com.br" }, | |
990 { false, "xn--poema-9qae5a.com.br", "", "*.xn--poema-9qae5a.com.br," | |
991 "xn--poema-*.com.br," | |
992 "xn--*-9qae5a.com.br," | |
993 "*--poema-9qae5a.com.br" }, | |
994 // The following are adapted from the examples quoted from | |
995 // http://tools.ietf.org/html/rfc6125#section-6.4.3 | |
996 // (e.g., *.example.com would match foo.example.com but | |
997 // not bar.foo.example.com or example.com). | |
998 { true, "foo.example.com", "*.example.com" }, | |
999 { false, "bar.foo.example.com", "*.example.com" }, | |
1000 { false, "example.com", "*.example.com" }, | |
1001 // Partial wildcards are disallowed, though RFC 2818 rules allow them. | |
1002 // That is, forms such as baz*.example.net, *baz.example.net, and | |
1003 // b*z.example.net should NOT match domains. Instead, the wildcard must | |
1004 // always be the left-most label, and only a single label. | |
1005 { false, "baz1.example.net", "baz*.example.net" }, | |
1006 { false, "foobaz.example.net", "*baz.example.net" }, | |
1007 { false, "buzz.example.net", "b*z.example.net" }, | |
1008 { false, "www.test.example.net", "www.*.example.net" }, | |
1009 // Wildcards should not be valid for public registry controlled domains, | |
1010 // and unknown/unrecognized domains, at least three domain components must | |
1011 // be present. | |
1012 { true, "www.test.example", "*.test.example" }, | |
1013 { true, "test.example.co.uk", "*.example.co.uk" }, | |
1014 { false, "test.example", "*.exmaple" }, | |
1015 { false, "example.co.uk", "*.co.uk" }, | |
1016 { false, "foo.com", "*.com" }, | |
1017 { false, "foo.us", "*.us" }, | |
1018 { false, "foo", "*" }, | |
1019 // IDN variants of wildcards and registry controlled domains. | |
1020 { true, "www.xn--poema-9qae5a.com.br", "*.xn--poema-9qae5a.com.br" }, | |
1021 { true, "test.example.xn--mgbaam7a8h", "*.example.xn--mgbaam7a8h" }, | |
1022 { false, "xn--poema-9qae5a.com.br", "*.com.br" }, | |
1023 { false, "example.xn--mgbaam7a8h", "*.xn--mgbaam7a8h" }, | |
1024 // Wildcards should be permissible for 'private' registry controlled | |
1025 // domains. | |
1026 { true, "www.appspot.com", "*.appspot.com" }, | |
1027 { true, "foo.s3.amazonaws.com", "*.s3.amazonaws.com" }, | |
1028 // Multiple wildcards are not valid. | |
1029 { false, "foo.example.com", "*.*.com" }, | |
1030 { false, "foo.bar.example.com", "*.bar.*.com" }, | |
1031 // Absolute vs relative DNS name tests. Although not explicitly specified | |
1032 // in RFC 6125, absolute reference names (those ending in a .) should | |
1033 // match either absolute or relative presented names. | |
1034 { true, "foo.com", "foo.com." }, | |
1035 { true, "foo.com.", "foo.com" }, | |
1036 { true, "foo.com.", "foo.com." }, | |
1037 { true, "f", "f." }, | |
1038 { true, "f.", "f" }, | |
1039 { true, "f.", "f." }, | |
1040 { true, "www-3.bar.foo.com", "*.bar.foo.com." }, | |
1041 { true, "www-3.bar.foo.com.", "*.bar.foo.com" }, | |
1042 { true, "www-3.bar.foo.com.", "*.bar.foo.com." }, | |
1043 { false, ".", "." }, | |
1044 { false, "example.com", "*.com." }, | |
1045 { false, "example.com.", "*.com" }, | |
1046 { false, "example.com.", "*.com." }, | |
1047 { false, "foo.", "*." }, | |
1048 { false, "foo", "*." }, | |
1049 { false, "foo.co.uk", "*.co.uk." }, | |
1050 { false, "foo.co.uk.", "*.co.uk." }, | |
1051 // IP addresses in common name; IPv4 only. | |
1052 { true, "127.0.0.1", "127.0.0.1" }, | |
1053 { true, "192.168.1.1", "192.168.1.1" }, | |
1054 { true, "676768", "0.10.83.160" }, | |
1055 { true, "1.2.3", "1.2.0.3" }, | |
1056 { false, "192.169.1.1", "192.168.1.1" }, | |
1057 { false, "12.19.1.1", "12.19.1.1/255.255.255.0" }, | |
1058 { false, "FEDC:ba98:7654:3210:FEDC:BA98:7654:3210", | |
1059 "FEDC:BA98:7654:3210:FEDC:ba98:7654:3210" }, | |
1060 { false, "1111:2222:3333:4444:5555:6666:7777:8888", | |
1061 "1111:2222:3333:4444:5555:6666:7777:8888" }, | |
1062 { false, "::192.9.5.5", "[::192.9.5.5]" }, | |
1063 // No wildcard matching in valid IP addresses | |
1064 { false, "::192.9.5.5", "*.9.5.5" }, | |
1065 { false, "2010:836B:4179::836B:4179", "*:836B:4179::836B:4179" }, | |
1066 { false, "192.168.1.11", "*.168.1.11" }, | |
1067 { false, "FEDC:BA98:7654:3210:FEDC:BA98:7654:3210", "*.]" }, | |
1068 // IP addresses in subject alternative name (common name ignored) | |
1069 { true, "10.1.2.3", "", "", "10.1.2.3" }, | |
1070 { true, "14.15", "", "", "14.0.0.15" }, | |
1071 { false, "10.1.2.7", "10.1.2.7", "", "10.1.2.6,10.1.2.8" }, | |
1072 { false, "10.1.2.8", "10.20.2.8", "foo" }, | |
1073 { true, "::4.5.6.7", "", "", "x00000000000000000000000004050607" }, | |
1074 { false, "::6.7.8.9", "::6.7.8.9", "::6.7.8.9", | |
1075 "x00000000000000000000000006070808,x0000000000000000000000000607080a," | |
1076 "xff000000000000000000000006070809,6.7.8.9" }, | |
1077 { true, "FE80::200:f8ff:fe21:67cf", "no.common.name", "", | |
1078 "x00000000000000000000000006070808,xfe800000000000000200f8fffe2167cf," | |
1079 "xff0000000000000000000000060708ff,10.0.0.1" }, | |
1080 // Numeric only hostnames (none of these are considered valid IP addresses). | |
1081 { false, "12345.6", "12345.6" }, | |
1082 { false, "121.2.3.512", "", "1*1.2.3.512,*1.2.3.512,1*.2.3.512,*.2.3.512", | |
1083 "121.2.3.0"}, | |
1084 { false, "1.2.3.4.5.6", "*.2.3.4.5.6" }, | |
1085 { true, "1.2.3.4.5", "", "1.2.3.4.5" }, | |
1086 // Invalid host names. | |
1087 { false, "junk)(£)$*!@~#", "junk)(£)$*!@~#" }, | |
1088 { false, "www.*.com", "www.*.com" }, | |
1089 { false, "w$w.f.com", "w$w.f.com" }, | |
1090 { false, "nocolonallowed:example", "", "nocolonallowed:example" }, | |
1091 { false, "www-1.[::FFFF:129.144.52.38]", "*.[::FFFF:129.144.52.38]" }, | |
1092 { false, "[::4.5.6.9]", "", "", "x00000000000000000000000004050609" }, | |
1093 }; | |
1094 | |
1095 class X509CertificateNameVerifyTest | |
1096 : public testing::TestWithParam<CertificateNameVerifyTestData> { | |
1097 }; | |
1098 | |
1099 TEST_P(X509CertificateNameVerifyTest, VerifyHostname) { | |
1100 CertificateNameVerifyTestData test_data = GetParam(); | |
1101 | |
1102 std::string common_name(test_data.common_name); | |
1103 ASSERT_EQ(std::string::npos, common_name.find(',')); | |
1104 std::replace(common_name.begin(), common_name.end(), '#', '\0'); | |
1105 | |
1106 std::vector<std::string> dns_names, ip_addressses; | |
1107 if (test_data.dns_names) { | |
1108 // Build up the certificate DNS names list. | |
1109 std::string dns_name_line(test_data.dns_names); | |
1110 std::replace(dns_name_line.begin(), dns_name_line.end(), '#', '\0'); | |
1111 base::SplitString(dns_name_line, ',', &dns_names); | |
1112 } | |
1113 | |
1114 if (test_data.ip_addrs) { | |
1115 // Build up the certificate IP address list. | |
1116 std::string ip_addrs_line(test_data.ip_addrs); | |
1117 std::vector<std::string> ip_addressses_ascii; | |
1118 base::SplitString(ip_addrs_line, ',', &ip_addressses_ascii); | |
1119 for (size_t i = 0; i < ip_addressses_ascii.size(); ++i) { | |
1120 std::string& addr_ascii = ip_addressses_ascii[i]; | |
1121 ASSERT_NE(0U, addr_ascii.length()); | |
1122 if (addr_ascii[0] == 'x') { // Hex encoded address | |
1123 addr_ascii.erase(0, 1); | |
1124 std::vector<uint8> bytes; | |
1125 EXPECT_TRUE(base::HexStringToBytes(addr_ascii, &bytes)) | |
1126 << "Could not parse hex address " << addr_ascii << " i = " << i; | |
1127 ip_addressses.push_back(std::string(reinterpret_cast<char*>(&bytes[0]), | |
1128 bytes.size())); | |
1129 ASSERT_EQ(16U, ip_addressses.back().size()) << i; | |
1130 } else { // Decimal groups | |
1131 std::vector<std::string> decimals_ascii; | |
1132 base::SplitString(addr_ascii, '.', &decimals_ascii); | |
1133 EXPECT_EQ(4U, decimals_ascii.size()) << i; | |
1134 std::string addr_bytes; | |
1135 for (size_t j = 0; j < decimals_ascii.size(); ++j) { | |
1136 int decimal_value; | |
1137 EXPECT_TRUE(base::StringToInt(decimals_ascii[j], &decimal_value)); | |
1138 EXPECT_GE(decimal_value, 0); | |
1139 EXPECT_LE(decimal_value, 255); | |
1140 addr_bytes.push_back(static_cast<char>(decimal_value)); | |
1141 } | |
1142 ip_addressses.push_back(addr_bytes); | |
1143 ASSERT_EQ(4U, ip_addressses.back().size()) << i; | |
1144 } | |
1145 } | |
1146 } | |
1147 | |
1148 bool unused = false; | |
1149 EXPECT_EQ(test_data.expected, X509Certificate::VerifyHostname( | |
1150 test_data.hostname, common_name, dns_names, ip_addressses, &unused)); | |
1151 } | |
1152 | |
1153 INSTANTIATE_TEST_CASE_P(, X509CertificateNameVerifyTest, | |
1154 testing::ValuesIn(kNameVerifyTestData)); | |
1155 | |
1156 const struct PublicKeyInfoTestData { | |
1157 const char* cert_file; | |
1158 size_t expected_bits; | |
1159 X509Certificate::PublicKeyType expected_type; | |
1160 } kPublicKeyInfoTestData[] = { | |
1161 { "768-rsa-ee-by-768-rsa-intermediate.pem", 768, | |
1162 X509Certificate::kPublicKeyTypeRSA }, | |
1163 { "1024-rsa-ee-by-768-rsa-intermediate.pem", 1024, | |
1164 X509Certificate::kPublicKeyTypeRSA }, | |
1165 { "prime256v1-ecdsa-ee-by-1024-rsa-intermediate.pem", 256, | |
1166 X509Certificate::kPublicKeyTypeECDSA }, | |
1167 }; | |
1168 | |
1169 class X509CertificatePublicKeyInfoTest | |
1170 : public testing::TestWithParam<PublicKeyInfoTestData> { | |
1171 }; | |
1172 | |
1173 TEST_P(X509CertificatePublicKeyInfoTest, GetPublicKeyInfo) { | |
1174 PublicKeyInfoTestData data = GetParam(); | |
1175 | |
1176 #if defined(OS_WIN) | |
1177 if (base::win::GetVersion() < base::win::VERSION_VISTA && | |
1178 data.expected_type == X509Certificate::kPublicKeyTypeECDSA) { | |
1179 // ECC is only supported on Vista+. Skip the test. | |
1180 return; | |
1181 } | |
1182 #endif | |
1183 | |
1184 scoped_refptr<X509Certificate> cert( | |
1185 ImportCertFromFile(GetTestCertsDirectory(), data.cert_file)); | |
1186 ASSERT_TRUE(cert.get()); | |
1187 | |
1188 size_t actual_bits = 0; | |
1189 X509Certificate::PublicKeyType actual_type = | |
1190 X509Certificate::kPublicKeyTypeUnknown; | |
1191 | |
1192 X509Certificate::GetPublicKeyInfo(cert->os_cert_handle(), &actual_bits, | |
1193 &actual_type); | |
1194 | |
1195 EXPECT_EQ(data.expected_bits, actual_bits); | |
1196 EXPECT_EQ(data.expected_type, actual_type); | |
1197 } | |
1198 | |
1199 INSTANTIATE_TEST_CASE_P(, X509CertificatePublicKeyInfoTest, | |
1200 testing::ValuesIn(kPublicKeyInfoTestData)); | |
1201 | |
1202 } // namespace net | |
OLD | NEW |