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