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" |
18 #include "base/time.h" | 19 #include "base/time.h" |
| 20 #include "net/base/pem_tokenizer.h" |
19 | 21 |
20 namespace net { | 22 namespace net { |
21 | 23 |
22 namespace { | 24 namespace { |
23 | 25 |
24 // Returns true if this cert fingerprint is the null (all zero) fingerprint. | 26 // Returns true if this cert fingerprint is the null (all zero) fingerprint. |
25 // We use this as a bogus fingerprint value. | 27 // We use this as a bogus fingerprint value. |
26 bool IsNullFingerprint(const SHA1Fingerprint& fingerprint) { | 28 bool IsNullFingerprint(const SHA1Fingerprint& fingerprint) { |
27 for (size_t i = 0; i < arraysize(fingerprint.data); ++i) { | 29 for (size_t i = 0; i < arraysize(fingerprint.data); ++i) { |
28 if (fingerprint.data[i] != 0) | 30 if (fingerprint.data[i] != 0) |
29 return false; | 31 return false; |
30 } | 32 } |
31 return true; | 33 return true; |
32 } | 34 } |
33 | 35 |
| 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_SINGLE_CERTIFICATE, |
| 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 |
34 } // namespace | 48 } // namespace |
35 | 49 |
36 // static | 50 // static |
37 bool X509Certificate::IsSameOSCert(X509Certificate::OSCertHandle a, | 51 bool X509Certificate::IsSameOSCert(X509Certificate::OSCertHandle a, |
38 X509Certificate::OSCertHandle b) { | 52 X509Certificate::OSCertHandle b) { |
39 DCHECK(a && b); | 53 DCHECK(a && b); |
40 if (a == b) | 54 if (a == b) |
41 return true; | 55 return true; |
42 #if defined(OS_WIN) | 56 #if defined(OS_WIN) |
43 return a->cbCertEncoded == b->cbCertEncoded && | 57 return a->cbCertEncoded == b->cbCertEncoded && |
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
179 if (!cert_handle) | 193 if (!cert_handle) |
180 return NULL; | 194 return NULL; |
181 | 195 |
182 X509Certificate* cert = CreateFromHandle(cert_handle, | 196 X509Certificate* cert = CreateFromHandle(cert_handle, |
183 SOURCE_LONE_CERT_IMPORT, | 197 SOURCE_LONE_CERT_IMPORT, |
184 OSCertHandles()); | 198 OSCertHandles()); |
185 FreeOSCertHandle(cert_handle); | 199 FreeOSCertHandle(cert_handle); |
186 return cert; | 200 return cert; |
187 } | 201 } |
188 | 202 |
| 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_CERT_SEQUENCE) |
| 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_CERT_SEQUENCE; |
| 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_CERT_SEQUENCE) { |
| 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_CERT_SEQUENCE |
| 257 // is handled above, and continues processing until a certificate fails |
| 258 // to parse. |
| 259 break; |
| 260 } |
| 261 } |
| 262 |
| 263 CertificateList results; |
| 264 // No certificates parsed. |
| 265 if (certificates.empty()) |
| 266 return results; |
| 267 |
| 268 for (OSCertHandles::iterator it = certificates.begin(); |
| 269 it != certificates.end(); ++it) { |
| 270 X509Certificate* result = CreateFromHandle(*it, SOURCE_LONE_CERT_IMPORT, |
| 271 OSCertHandles()); |
| 272 results.push_back(scoped_refptr<X509Certificate>(result)); |
| 273 FreeOSCertHandle(*it); |
| 274 } |
| 275 |
| 276 return results; |
| 277 } |
| 278 |
189 X509Certificate::X509Certificate(OSCertHandle cert_handle, | 279 X509Certificate::X509Certificate(OSCertHandle cert_handle, |
190 Source source, | 280 Source source, |
191 const OSCertHandles& intermediates) | 281 const OSCertHandles& intermediates) |
192 : cert_handle_(DupOSCertHandle(cert_handle)), | 282 : cert_handle_(DupOSCertHandle(cert_handle)), |
193 source_(source) { | 283 source_(source) { |
194 #if defined(OS_MACOSX) || defined(OS_WIN) | 284 #if defined(OS_MACOSX) || defined(OS_WIN) |
195 // Copy/retain the intermediate cert handles. | 285 // Copy/retain the intermediate cert handles. |
196 for (size_t i = 0; i < intermediates.size(); ++i) | 286 for (size_t i = 0; i < intermediates.size(); ++i) |
197 intermediate_ca_certs_.push_back(DupOSCertHandle(intermediates[i])); | 287 intermediate_ca_certs_.push_back(DupOSCertHandle(intermediates[i])); |
198 #endif | 288 #endif |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
242 | 332 |
243 bool X509Certificate::HasIntermediateCertificates(const OSCertHandles& certs) { | 333 bool X509Certificate::HasIntermediateCertificates(const OSCertHandles& certs) { |
244 for (size_t i = 0; i < certs.size(); ++i) { | 334 for (size_t i = 0; i < certs.size(); ++i) { |
245 if (!HasIntermediateCertificate(certs[i])) | 335 if (!HasIntermediateCertificate(certs[i])) |
246 return false; | 336 return false; |
247 } | 337 } |
248 return true; | 338 return true; |
249 } | 339 } |
250 | 340 |
251 } // namespace net | 341 } // namespace net |
OLD | NEW |