OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 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/cert/x509_certificate.h" | 5 #include "net/cert/x509_certificate.h" |
6 | 6 |
7 #include <CommonCrypto/CommonDigest.h> | 7 #include <CommonCrypto/CommonDigest.h> |
8 #include <CoreServices/CoreServices.h> | 8 #include <CoreServices/CoreServices.h> |
9 #include <Security/Security.h> | 9 #include <Security/Security.h> |
10 | 10 |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
110 OSStatus status = cached_cert.GetField(&CSSMOID_X509V1SerialNumber, | 110 OSStatus status = cached_cert.GetField(&CSSMOID_X509V1SerialNumber, |
111 &serial_number); | 111 &serial_number); |
112 if (status || !serial_number.field()) | 112 if (status || !serial_number.field()) |
113 return std::string(); | 113 return std::string(); |
114 | 114 |
115 return std::string( | 115 return std::string( |
116 reinterpret_cast<const char*>(serial_number.field()->Data), | 116 reinterpret_cast<const char*>(serial_number.field()->Data), |
117 serial_number.field()->Length); | 117 serial_number.field()->Length); |
118 } | 118 } |
119 | 119 |
120 // Test that a given |cert_handle| is actually a valid X.509 certificate, and | |
121 // return true if it is. | |
122 // | |
123 // On OS X, SecCertificateCreateFromData() does not return any errors if | |
124 // called with invalid data, as long as data is present. The actual decoding | |
125 // of the certificate does not happen until an API that requires a CSSM | |
126 // handle is called. While SecCertificateGetCLHandle is the most likely | |
127 // candidate, as it performs the parsing, it does not check whether the | |
128 // parsing was actually successful. Instead, SecCertificateGetSubject is | |
129 // used (supported since 10.3), as a means to check that the certificate | |
130 // parsed as a valid X.509 certificate. | |
131 bool IsValidOSCertHandle(SecCertificateRef cert_handle) { | |
132 const CSSM_X509_NAME* sanity_check = NULL; | |
133 OSStatus status = SecCertificateGetSubject(cert_handle, &sanity_check); | |
134 return status == noErr && sanity_check; | |
135 } | |
136 | |
137 // Parses |data| of length |length|, attempting to decode it as the specified | 120 // Parses |data| of length |length|, attempting to decode it as the specified |
138 // |format|. If |data| is in the specified format, any certificates contained | 121 // |format|. If |data| is in the specified format, any certificates contained |
139 // within are stored into |output|. | 122 // within are stored into |output|. |
140 void AddCertificatesFromBytes(const char* data, size_t length, | 123 void AddCertificatesFromBytes(const char* data, size_t length, |
141 SecExternalFormat format, | 124 SecExternalFormat format, |
142 X509Certificate::OSCertHandles* output) { | 125 X509Certificate::OSCertHandles* output) { |
143 SecExternalFormat input_format = format; | 126 SecExternalFormat input_format = format; |
144 ScopedCFTypeRef<CFDataRef> local_data(CFDataCreateWithBytesNoCopy( | 127 ScopedCFTypeRef<CFDataRef> local_data(CFDataCreateWithBytesNoCopy( |
145 kCFAllocatorDefault, reinterpret_cast<const UInt8*>(data), | 128 kCFAllocatorDefault, reinterpret_cast<const UInt8*>(data), |
146 base::checked_cast<CFIndex>(length), kCFAllocatorNull)); | 129 base::checked_cast<CFIndex>(length), kCFAllocatorNull)); |
(...skipping 28 matching lines...) Expand all Loading... |
175 // encoded, attempting to decode data based on internal rules for PEM | 158 // encoded, attempting to decode data based on internal rules for PEM |
176 // block headers. If a PKCS#7 blob is encoded with a PEM block of | 159 // block headers. If a PKCS#7 blob is encoded with a PEM block of |
177 // CERTIFICATE, OS X 10.5 will return a single, invalid certificate | 160 // CERTIFICATE, OS X 10.5 will return a single, invalid certificate |
178 // based on the decoded data. If this happens, the certificate should | 161 // based on the decoded data. If this happens, the certificate should |
179 // not be included in |output|. Because |output| is empty, | 162 // not be included in |output|. Because |output| is empty, |
180 // CreateCertificateListfromBytes will use PEMTokenizer to decode the | 163 // CreateCertificateListfromBytes will use PEMTokenizer to decode the |
181 // data. When called again with the decoded data, OS X will honor | 164 // data. When called again with the decoded data, OS X will honor |
182 // |input_format|, causing decode to succeed. On OS X 10.6, the data | 165 // |input_format|, causing decode to succeed. On OS X 10.6, the data |
183 // is properly decoded as a PKCS#7, whether PEM or not, which avoids | 166 // is properly decoded as a PKCS#7, whether PEM or not, which avoids |
184 // the need to fallback to internal decoding. | 167 // the need to fallback to internal decoding. |
185 if (IsValidOSCertHandle(cert)) { | 168 if (x509_util::IsValidSecCertificate(cert)) { |
186 CFRetain(cert); | 169 CFRetain(cert); |
187 output->push_back(cert); | 170 output->push_back(cert); |
188 } | 171 } |
189 } | 172 } |
190 } | 173 } |
191 } | 174 } |
192 | 175 |
193 } // namespace | 176 } // namespace |
194 | 177 |
195 bool X509Certificate::Initialize() { | 178 bool X509Certificate::Initialize() { |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
291 bool X509Certificate::IsSameOSCert(X509Certificate::OSCertHandle a, | 274 bool X509Certificate::IsSameOSCert(X509Certificate::OSCertHandle a, |
292 X509Certificate::OSCertHandle b) { | 275 X509Certificate::OSCertHandle b) { |
293 DCHECK(a && b); | 276 DCHECK(a && b); |
294 return CFEqual(a, b); | 277 return CFEqual(a, b); |
295 } | 278 } |
296 | 279 |
297 // static | 280 // static |
298 X509Certificate::OSCertHandle X509Certificate::CreateOSCertHandleFromBytes( | 281 X509Certificate::OSCertHandle X509Certificate::CreateOSCertHandleFromBytes( |
299 const char* data, | 282 const char* data, |
300 size_t length) { | 283 size_t length) { |
301 CSSM_DATA cert_data; | 284 return x509_util::CreateSecCertificateFromBytes( |
302 cert_data.Data = const_cast<uint8_t*>(reinterpret_cast<const uint8_t*>(data)); | 285 reinterpret_cast<const uint8_t*>(data), length) |
303 cert_data.Length = length; | 286 .release(); |
304 | |
305 OSCertHandle cert_handle = NULL; | |
306 OSStatus status = SecCertificateCreateFromData(&cert_data, | |
307 CSSM_CERT_X_509v3, | |
308 CSSM_CERT_ENCODING_DER, | |
309 &cert_handle); | |
310 if (status != noErr) | |
311 return NULL; | |
312 if (!IsValidOSCertHandle(cert_handle)) { | |
313 CFRelease(cert_handle); | |
314 return NULL; | |
315 } | |
316 return cert_handle; | |
317 } | 287 } |
318 | 288 |
319 // static | 289 // static |
320 X509Certificate::OSCertHandles X509Certificate::CreateOSCertHandlesFromBytes( | 290 X509Certificate::OSCertHandles X509Certificate::CreateOSCertHandlesFromBytes( |
321 const char* data, | 291 const char* data, |
322 size_t length, | 292 size_t length, |
323 Format format) { | 293 Format format) { |
324 OSCertHandles results; | 294 OSCertHandles results; |
325 | 295 |
326 switch (format) { | 296 switch (format) { |
(...skipping 23 matching lines...) Expand all Loading... |
350 } | 320 } |
351 | 321 |
352 // static | 322 // static |
353 void X509Certificate::FreeOSCertHandle(OSCertHandle cert_handle) { | 323 void X509Certificate::FreeOSCertHandle(OSCertHandle cert_handle) { |
354 if (cert_handle) | 324 if (cert_handle) |
355 CFRelease(cert_handle); | 325 CFRelease(cert_handle); |
356 } | 326 } |
357 | 327 |
358 // static | 328 // static |
359 SHA256HashValue X509Certificate::CalculateFingerprint256(OSCertHandle cert) { | 329 SHA256HashValue X509Certificate::CalculateFingerprint256(OSCertHandle cert) { |
360 SHA256HashValue sha256; | 330 return x509_util::CalculateFingerprint256(cert); |
361 memset(sha256.data, 0, sizeof(sha256.data)); | |
362 | |
363 CSSM_DATA cert_data; | |
364 OSStatus status = SecCertificateGetData(cert, &cert_data); | |
365 if (status) | |
366 return sha256; | |
367 | |
368 DCHECK(cert_data.Data); | |
369 DCHECK_NE(cert_data.Length, 0U); | |
370 | |
371 CC_SHA256(cert_data.Data, cert_data.Length, sha256.data); | |
372 | |
373 return sha256; | |
374 } | 331 } |
375 | 332 |
376 // static | 333 // static |
377 SHA256HashValue X509Certificate::CalculateCAFingerprint256( | 334 SHA256HashValue X509Certificate::CalculateCAFingerprint256( |
378 const OSCertHandles& intermediates) { | 335 const OSCertHandles& intermediates) { |
379 SHA256HashValue sha256; | 336 SHA256HashValue sha256; |
380 memset(sha256.data, 0, sizeof(sha256.data)); | 337 memset(sha256.data, 0, sizeof(sha256.data)); |
381 | 338 |
382 // The CC_SHA(3cc) man page says all CC_SHA256_xxx routines return 1, so | 339 // The CC_SHA(3cc) man page says all CC_SHA256_xxx routines return 1, so |
383 // we don't check their return values. | 340 // we don't check their return values. |
384 CC_SHA256_CTX sha256_ctx; | 341 CC_SHA256_CTX sha256_ctx; |
385 CC_SHA256_Init(&sha256_ctx); | 342 CC_SHA256_Init(&sha256_ctx); |
386 CSSM_DATA cert_data; | 343 CSSM_DATA cert_data; |
387 for (size_t i = 0; i < intermediates.size(); ++i) { | 344 for (size_t i = 0; i < intermediates.size(); ++i) { |
388 OSStatus status = SecCertificateGetData(intermediates[i], &cert_data); | 345 OSStatus status = SecCertificateGetData(intermediates[i], &cert_data); |
389 if (status) | 346 if (status) |
390 return sha256; | 347 return sha256; |
391 CC_SHA256_Update(&sha256_ctx, cert_data.Data, cert_data.Length); | 348 CC_SHA256_Update(&sha256_ctx, cert_data.Data, cert_data.Length); |
392 } | 349 } |
393 CC_SHA256_Final(sha256.data, &sha256_ctx); | 350 CC_SHA256_Final(sha256.data, &sha256_ctx); |
394 | 351 |
395 return sha256; | 352 return sha256; |
396 } | 353 } |
397 | 354 |
398 CFMutableArrayRef X509Certificate::CreateOSCertChainForCert() const { | |
399 CFMutableArrayRef cert_list = | |
400 CFArrayCreateMutable(kCFAllocatorDefault, 0, | |
401 &kCFTypeArrayCallBacks); | |
402 if (!cert_list) | |
403 return NULL; | |
404 | |
405 CFArrayAppendValue(cert_list, os_cert_handle()); | |
406 for (size_t i = 0; i < intermediate_ca_certs_.size(); ++i) | |
407 CFArrayAppendValue(cert_list, intermediate_ca_certs_[i]); | |
408 | |
409 return cert_list; | |
410 } | |
411 | |
412 // static | 355 // static |
413 X509Certificate::OSCertHandle X509Certificate::ReadOSCertHandleFromPickle( | 356 X509Certificate::OSCertHandle X509Certificate::ReadOSCertHandleFromPickle( |
414 base::PickleIterator* pickle_iter) { | 357 base::PickleIterator* pickle_iter) { |
415 const char* data; | 358 const char* data; |
416 int length; | 359 int length; |
417 if (!pickle_iter->ReadData(&data, &length)) | 360 if (!pickle_iter->ReadData(&data, &length)) |
418 return NULL; | 361 return NULL; |
419 | 362 |
420 return CreateOSCertHandleFromBytes(data, length); | 363 return CreateOSCertHandleFromBytes(data, length); |
421 } | 364 } |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
474 break; | 417 break; |
475 default: | 418 default: |
476 *type = kPublicKeyTypeUnknown; | 419 *type = kPublicKeyTypeUnknown; |
477 *size_bits = 0; | 420 *size_bits = 0; |
478 break; | 421 break; |
479 } | 422 } |
480 } | 423 } |
481 | 424 |
482 // static | 425 // static |
483 bool X509Certificate::IsSelfSigned(OSCertHandle cert_handle) { | 426 bool X509Certificate::IsSelfSigned(OSCertHandle cert_handle) { |
484 x509_util::CSSMCachedCertificate cached_cert; | 427 return x509_util::IsSelfSigned(cert_handle); |
485 OSStatus status = cached_cert.Init(cert_handle); | |
486 if (status != noErr) | |
487 return false; | |
488 | |
489 x509_util::CSSMFieldValue subject; | |
490 status = cached_cert.GetField(&CSSMOID_X509V1SubjectNameStd, &subject); | |
491 if (status != CSSM_OK || !subject.field()) | |
492 return false; | |
493 | |
494 x509_util::CSSMFieldValue issuer; | |
495 status = cached_cert.GetField(&CSSMOID_X509V1IssuerNameStd, &issuer); | |
496 if (status != CSSM_OK || !issuer.field()) | |
497 return false; | |
498 | |
499 if (subject.field()->Length != issuer.field()->Length || | |
500 memcmp(subject.field()->Data, issuer.field()->Data, | |
501 issuer.field()->Length) != 0) { | |
502 return false; | |
503 } | |
504 | |
505 CSSM_CL_HANDLE cl_handle = CSSM_INVALID_HANDLE; | |
506 status = SecCertificateGetCLHandle(cert_handle, &cl_handle); | |
507 if (status) | |
508 return false; | |
509 CSSM_DATA cert_data; | |
510 status = SecCertificateGetData(cert_handle, &cert_data); | |
511 if (status) | |
512 return false; | |
513 | |
514 if (CSSM_CL_CertVerify(cl_handle, 0, &cert_data, &cert_data, NULL, 0)) | |
515 return false; | |
516 return true; | |
517 } | 428 } |
518 | 429 |
519 #pragma clang diagnostic pop // "-Wdeprecated-declarations" | 430 #pragma clang diagnostic pop // "-Wdeprecated-declarations" |
520 | 431 |
521 } // namespace net | 432 } // namespace net |
OLD | NEW |