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 |