OLD | NEW |
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "net/base/x509_certificate.h" | 5 #include "net/base/x509_certificate.h" |
6 | 6 |
7 #if defined(OS_MACOSX) | 7 #if defined(OS_MACOSX) |
8 #include <Security/Security.h> | 8 #include <Security/Security.h> |
9 #elif defined(USE_NSS) | 9 #elif defined(USE_NSS) |
10 #include <cert.h> | 10 #include <cert.h> |
11 #endif | 11 #endif |
12 | 12 |
13 #include <map> | 13 #include <map> |
14 | 14 |
15 #include "base/histogram.h" | 15 #include "base/histogram.h" |
16 #include "base/logging.h" | 16 #include "base/logging.h" |
17 #include "base/singleton.h" | 17 #include "base/singleton.h" |
18 #include "base/string_piece.h" | |
19 #include "base/time.h" | 18 #include "base/time.h" |
20 #include "net/base/pem_tokenizer.h" | |
21 | 19 |
22 namespace net { | 20 namespace net { |
23 | 21 |
24 namespace { | 22 namespace { |
25 | 23 |
26 // Returns true if this cert fingerprint is the null (all zero) fingerprint. | 24 // Returns true if this cert fingerprint is the null (all zero) fingerprint. |
27 // We use this as a bogus fingerprint value. | 25 // We use this as a bogus fingerprint value. |
28 bool IsNullFingerprint(const SHA1Fingerprint& fingerprint) { | 26 bool IsNullFingerprint(const SHA1Fingerprint& fingerprint) { |
29 for (size_t i = 0; i < arraysize(fingerprint.data); ++i) { | 27 for (size_t i = 0; i < arraysize(fingerprint.data); ++i) { |
30 if (fingerprint.data[i] != 0) | 28 if (fingerprint.data[i] != 0) |
31 return false; | 29 return false; |
32 } | 30 } |
33 return true; | 31 return true; |
34 } | 32 } |
35 | 33 |
36 // Indicates the order to use when trying to decode binary data, which is | |
37 // based on (speculation) as to what will be most common -> least common | |
38 const X509Certificate::Format kFormatDecodePriority[] = { | |
39 X509Certificate::FORMAT_DER, | |
40 X509Certificate::FORMAT_PKCS7 | |
41 }; | |
42 | |
43 // The PEM block header used for DER certificates | |
44 const char kCertificateHeader[] = "CERTIFICATE"; | |
45 // The PEM block header used for PKCS#7 data | |
46 const char kPKCS7Header[] = "PKCS7"; | |
47 | |
48 } // namespace | 34 } // namespace |
49 | 35 |
50 // static | 36 // static |
51 bool X509Certificate::IsSameOSCert(X509Certificate::OSCertHandle a, | 37 bool X509Certificate::IsSameOSCert(X509Certificate::OSCertHandle a, |
52 X509Certificate::OSCertHandle b) { | 38 X509Certificate::OSCertHandle b) { |
53 DCHECK(a && b); | 39 DCHECK(a && b); |
54 if (a == b) | 40 if (a == b) |
55 return true; | 41 return true; |
56 #if defined(OS_WIN) | 42 #if defined(OS_WIN) |
57 return a->cbCertEncoded == b->cbCertEncoded && | 43 return a->cbCertEncoded == b->cbCertEncoded && |
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
193 if (!cert_handle) | 179 if (!cert_handle) |
194 return NULL; | 180 return NULL; |
195 | 181 |
196 X509Certificate* cert = CreateFromHandle(cert_handle, | 182 X509Certificate* cert = CreateFromHandle(cert_handle, |
197 SOURCE_LONE_CERT_IMPORT, | 183 SOURCE_LONE_CERT_IMPORT, |
198 OSCertHandles()); | 184 OSCertHandles()); |
199 FreeOSCertHandle(cert_handle); | 185 FreeOSCertHandle(cert_handle); |
200 return cert; | 186 return cert; |
201 } | 187 } |
202 | 188 |
203 CertificateList X509Certificate::CreateCertificateListFromBytes( | |
204 const char* data, int length, int format) { | |
205 OSCertHandles certificates; | |
206 | |
207 // Try each of the formats, in order of parse preference, to see if |data| | |
208 // contains the binary representation of a Format. | |
209 for (size_t i = 0; certificates.empty() && | |
210 i < arraysize(kFormatDecodePriority); ++i) { | |
211 if (format & kFormatDecodePriority[i]) | |
212 certificates = CreateOSCertHandlesFromBytes(data, length, | |
213 kFormatDecodePriority[i]); | |
214 } | |
215 | |
216 // No certs were read. Check to see if it is in a PEM-encoded form. | |
217 if (certificates.empty()) { | |
218 base::StringPiece data_string(data, length); | |
219 std::vector<std::string> pem_headers; | |
220 | |
221 // To maintain compatibility with NSS/Firefox, CERTIFICATE is a universally | |
222 // valid PEM block header for any format. | |
223 pem_headers.push_back(kCertificateHeader); | |
224 if (format & FORMAT_PKCS7) | |
225 pem_headers.push_back(kPKCS7Header); | |
226 | |
227 PEMTokenizer pem_tok(data_string, pem_headers); | |
228 while (pem_tok.GetNext()) { | |
229 std::string decoded(pem_tok.data()); | |
230 | |
231 OSCertHandle handle = NULL; | |
232 if (format & FORMAT_PEM) | |
233 handle = CreateOSCertHandleFromBytes(decoded.c_str(), decoded.size()); | |
234 if (handle != NULL) { | |
235 // Parsed a DER encoded certificate. All PEM blocks that follow must | |
236 // also be DER encoded certificates wrapped inside of PEM blocks. | |
237 format = FORMAT_PEM; | |
238 certificates.push_back(handle); | |
239 continue; | |
240 } | |
241 | |
242 // If the first block failed to parse as a DER certificate, and | |
243 // formats other than PEM are acceptable, check to see if the decoded | |
244 // data is one of the accepted formats. | |
245 if (format & ~FORMAT_PEM) { | |
246 for (size_t i = 0; certificates.empty() && | |
247 i < arraysize(kFormatDecodePriority); ++i) { | |
248 if (format & kFormatDecodePriority[i]) { | |
249 certificates = CreateOSCertHandlesFromBytes(decoded.c_str(), | |
250 decoded.size(), kFormatDecodePriority[i]); | |
251 } | |
252 } | |
253 } | |
254 | |
255 // Stop parsing after the first block for any format but a sequence of | |
256 // PEM-encoded DER certificates. The case of FORMAT_PEM is handled | |
257 // above, and continues processing until a certificate fails to parse. | |
258 break; | |
259 } | |
260 } | |
261 | |
262 CertificateList results; | |
263 // No certificates parsed. | |
264 if (certificates.empty()) | |
265 return results; | |
266 | |
267 for (OSCertHandles::iterator it = certificates.begin(); | |
268 it != certificates.end(); ++it) { | |
269 X509Certificate* result = CreateFromHandle(*it, SOURCE_LONE_CERT_IMPORT, | |
270 OSCertHandles()); | |
271 results.push_back(scoped_refptr<X509Certificate>(result)); | |
272 FreeOSCertHandle(*it); | |
273 } | |
274 | |
275 return results; | |
276 } | |
277 | |
278 X509Certificate::X509Certificate(OSCertHandle cert_handle, | 189 X509Certificate::X509Certificate(OSCertHandle cert_handle, |
279 Source source, | 190 Source source, |
280 const OSCertHandles& intermediates) | 191 const OSCertHandles& intermediates) |
281 : cert_handle_(DupOSCertHandle(cert_handle)), | 192 : cert_handle_(DupOSCertHandle(cert_handle)), |
282 source_(source) { | 193 source_(source) { |
283 #if defined(OS_MACOSX) || defined(OS_WIN) | 194 #if defined(OS_MACOSX) || defined(OS_WIN) |
284 // Copy/retain the intermediate cert handles. | 195 // Copy/retain the intermediate cert handles. |
285 for (size_t i = 0; i < intermediates.size(); ++i) | 196 for (size_t i = 0; i < intermediates.size(); ++i) |
286 intermediate_ca_certs_.push_back(DupOSCertHandle(intermediates[i])); | 197 intermediate_ca_certs_.push_back(DupOSCertHandle(intermediates[i])); |
287 #endif | 198 #endif |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
331 | 242 |
332 bool X509Certificate::HasIntermediateCertificates(const OSCertHandles& certs) { | 243 bool X509Certificate::HasIntermediateCertificates(const OSCertHandles& certs) { |
333 for (size_t i = 0; i < certs.size(); ++i) { | 244 for (size_t i = 0; i < certs.size(); ++i) { |
334 if (!HasIntermediateCertificate(certs[i])) | 245 if (!HasIntermediateCertificate(certs[i])) |
335 return false; | 246 return false; |
336 } | 247 } |
337 return true; | 248 return true; |
338 } | 249 } |
339 | 250 |
340 } // namespace net | 251 } // namespace net |
OLD | NEW |