Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(345)

Side by Side Diff: net/base/x509_certificate.cc

Issue 2819018: Add support for parsing certificate formats other than raw, DER-encoded cert... (Closed) Base URL: http://src.chromium.org/svn/trunk/src/
Patch Set: Fixup some variables/comments per wtc Created 10 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « net/base/x509_certificate.h ('k') | net/base/x509_certificate_mac.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
OLDNEW
« no previous file with comments | « net/base/x509_certificate.h ('k') | net/base/x509_certificate_mac.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698