| 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 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 106 OSStatus status = cached_cert.GetField(&CSSMOID_X509V1SerialNumber, | 106 OSStatus status = cached_cert.GetField(&CSSMOID_X509V1SerialNumber, |
| 107 &serial_number); | 107 &serial_number); |
| 108 if (status || !serial_number.field()) | 108 if (status || !serial_number.field()) |
| 109 return std::string(); | 109 return std::string(); |
| 110 | 110 |
| 111 return std::string( | 111 return std::string( |
| 112 reinterpret_cast<const char*>(serial_number.field()->Data), | 112 reinterpret_cast<const char*>(serial_number.field()->Data), |
| 113 serial_number.field()->Length); | 113 serial_number.field()->Length); |
| 114 } | 114 } |
| 115 | 115 |
| 116 // Returns true if |purpose| is listed as allowed in |usage|. This | |
| 117 // function also considers the "Any" purpose. If the attribute is | |
| 118 // present and empty, we return false. | |
| 119 bool ExtendedKeyUsageAllows(const CE_ExtendedKeyUsage* usage, | |
| 120 const CSSM_OID* purpose) { | |
| 121 for (unsigned p = 0; p < usage->numPurposes; ++p) { | |
| 122 if (CSSMOIDEqual(&usage->purposes[p], purpose)) | |
| 123 return true; | |
| 124 if (CSSMOIDEqual(&usage->purposes[p], &CSSMOID_ExtendedKeyUsageAny)) | |
| 125 return true; | |
| 126 } | |
| 127 return false; | |
| 128 } | |
| 129 | |
| 130 // Test that a given |cert_handle| is actually a valid X.509 certificate, and | 116 // Test that a given |cert_handle| is actually a valid X.509 certificate, and |
| 131 // return true if it is. | 117 // return true if it is. |
| 132 // | 118 // |
| 133 // On OS X, SecCertificateCreateFromData() does not return any errors if | 119 // On OS X, SecCertificateCreateFromData() does not return any errors if |
| 134 // called with invalid data, as long as data is present. The actual decoding | 120 // called with invalid data, as long as data is present. The actual decoding |
| 135 // of the certificate does not happen until an API that requires a CSSM | 121 // of the certificate does not happen until an API that requires a CSSM |
| 136 // handle is called. While SecCertificateGetCLHandle is the most likely | 122 // handle is called. While SecCertificateGetCLHandle is the most likely |
| 137 // candidate, as it performs the parsing, it does not check whether the | 123 // candidate, as it performs the parsing, it does not check whether the |
| 138 // parsing was actually successful. Instead, SecCertificateGetSubject is | 124 // parsing was actually successful. Instead, SecCertificateGetSubject is |
| 139 // used (supported since 10.3), as a means to check that the certificate | 125 // used (supported since 10.3), as a means to check that the certificate |
| (...skipping 251 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 391 OSStatus status = SecCertificateGetData(intermediates[i], &cert_data); | 377 OSStatus status = SecCertificateGetData(intermediates[i], &cert_data); |
| 392 if (status) | 378 if (status) |
| 393 return sha256; | 379 return sha256; |
| 394 CC_SHA256_Update(&sha256_ctx, cert_data.Data, cert_data.Length); | 380 CC_SHA256_Update(&sha256_ctx, cert_data.Data, cert_data.Length); |
| 395 } | 381 } |
| 396 CC_SHA256_Final(sha256.data, &sha256_ctx); | 382 CC_SHA256_Final(sha256.data, &sha256_ctx); |
| 397 | 383 |
| 398 return sha256; | 384 return sha256; |
| 399 } | 385 } |
| 400 | 386 |
| 401 bool X509Certificate::SupportsSSLClientAuth() const { | |
| 402 x509_util::CSSMCachedCertificate cached_cert; | |
| 403 OSStatus status = cached_cert.Init(cert_handle_); | |
| 404 if (status) | |
| 405 return false; | |
| 406 | |
| 407 // RFC5280 says to take the intersection of the two extensions. | |
| 408 // | |
| 409 // Our underlying crypto libraries don't expose | |
| 410 // ClientCertificateType, so for now we will not support fixed | |
| 411 // Diffie-Hellman mechanisms. For rsa_sign, we need the | |
| 412 // digitalSignature bit. | |
| 413 // | |
| 414 // In particular, if a key has the nonRepudiation bit and not the | |
| 415 // digitalSignature one, we will not offer it to the user. | |
| 416 x509_util::CSSMFieldValue key_usage; | |
| 417 status = cached_cert.GetField(&CSSMOID_KeyUsage, &key_usage); | |
| 418 if (status == CSSM_OK && key_usage.field()) { | |
| 419 const CSSM_X509_EXTENSION* ext = key_usage.GetAs<CSSM_X509_EXTENSION>(); | |
| 420 const CE_KeyUsage* key_usage_value = | |
| 421 reinterpret_cast<const CE_KeyUsage*>(ext->value.parsedValue); | |
| 422 if (!((*key_usage_value) & CE_KU_DigitalSignature)) | |
| 423 return false; | |
| 424 } | |
| 425 | |
| 426 status = cached_cert.GetField(&CSSMOID_ExtendedKeyUsage, &key_usage); | |
| 427 if (status == CSSM_OK && key_usage.field()) { | |
| 428 const CSSM_X509_EXTENSION* ext = key_usage.GetAs<CSSM_X509_EXTENSION>(); | |
| 429 const CE_ExtendedKeyUsage* ext_key_usage = | |
| 430 reinterpret_cast<const CE_ExtendedKeyUsage*>(ext->value.parsedValue); | |
| 431 if (!ExtendedKeyUsageAllows(ext_key_usage, &CSSMOID_ClientAuth)) | |
| 432 return false; | |
| 433 } | |
| 434 return true; | |
| 435 } | |
| 436 | |
| 437 CFMutableArrayRef X509Certificate::CreateOSCertChainForCert() const { | 387 CFMutableArrayRef X509Certificate::CreateOSCertChainForCert() const { |
| 438 CFMutableArrayRef cert_list = | 388 CFMutableArrayRef cert_list = |
| 439 CFArrayCreateMutable(kCFAllocatorDefault, 0, | 389 CFArrayCreateMutable(kCFAllocatorDefault, 0, |
| 440 &kCFTypeArrayCallBacks); | 390 &kCFTypeArrayCallBacks); |
| 441 if (!cert_list) | 391 if (!cert_list) |
| 442 return NULL; | 392 return NULL; |
| 443 | 393 |
| 444 CFArrayAppendValue(cert_list, os_cert_handle()); | 394 CFArrayAppendValue(cert_list, os_cert_handle()); |
| 445 for (size_t i = 0; i < intermediate_ca_certs_.size(); ++i) | 395 for (size_t i = 0; i < intermediate_ca_certs_.size(); ++i) |
| 446 CFArrayAppendValue(cert_list, intermediate_ca_certs_[i]); | 396 CFArrayAppendValue(cert_list, intermediate_ca_certs_[i]); |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 551 return false; | 501 return false; |
| 552 | 502 |
| 553 if (CSSM_CL_CertVerify(cl_handle, 0, &cert_data, &cert_data, NULL, 0)) | 503 if (CSSM_CL_CertVerify(cl_handle, 0, &cert_data, &cert_data, NULL, 0)) |
| 554 return false; | 504 return false; |
| 555 return true; | 505 return true; |
| 556 } | 506 } |
| 557 | 507 |
| 558 #pragma clang diagnostic pop // "-Wdeprecated-declarations" | 508 #pragma clang diagnostic pop // "-Wdeprecated-declarations" |
| 559 | 509 |
| 560 } // namespace net | 510 } // namespace net |
| OLD | NEW |