1// Copyright (c) 2011 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "net/base/x509_certificate.h" 6 7#include <CommonCrypto/CommonDigest.h> 8#include <CoreServices/CoreServices.h> 9#include <Security/Security.h> 10#include <time.h> 11 12#include <vector> 13 14#include "base/lazy_instance.h" 15#include "base/logging.h" 16#include "base/mac/scoped_cftyperef.h" 17#include "base/memory/singleton.h" 18#include "base/pickle.h" 19#include "base/sha1.h" 20#include "base/sys_string_conversions.h" 21#include "crypto/cssm_init.h" 22#include "crypto/nss_util.h" 23#include "crypto/rsa_private_key.h" 24#include "net/base/asn1_util.h" 25#include "net/base/cert_status_flags.h" 26#include "net/base/cert_verify_result.h" 27#include "net/base/net_errors.h" 28#include "net/base/test_root_certs.h" 29#include "net/base/x509_certificate_known_roots_mac.h" 30#include "third_party/apple_apsl/cssmapplePriv.h" 31#include "third_party/nss/mozilla/security/nss/lib/certdb/cert.h" 32 33using base::mac::ScopedCFTypeRef; 34using base::Time; 35 36namespace net { 37 38namespace { 39 40typedef OSStatus (*SecTrustCopyExtendedResultFuncPtr)(SecTrustRef, 41 CFDictionaryRef*); 42 43int NetErrorFromOSStatus(OSStatus status) { 44 switch (status) { 45 case noErr: 46 return OK; 47 case errSecNotAvailable: 48 case errSecNoCertificateModule: 49 case errSecNoPolicyModule: 50 return ERR_NOT_IMPLEMENTED; 51 case errSecAuthFailed: 52 return ERR_ACCESS_DENIED; 53 default: 54 LOG(ERROR) << "Unknown error " << status << " mapped to ERR_FAILED"; 55 return ERR_FAILED; 56 } 57} 58 59int CertStatusFromOSStatus(OSStatus status) { 60 switch (status) { 61 case noErr: 62 return 0; 63 64 case CSSMERR_TP_INVALID_ANCHOR_CERT: 65 case CSSMERR_TP_NOT_TRUSTED: 66 case CSSMERR_TP_INVALID_CERT_AUTHORITY: 67 return CERT_STATUS_AUTHORITY_INVALID; 68 69 case CSSMERR_TP_CERT_EXPIRED: 70 case CSSMERR_TP_CERT_NOT_VALID_YET: 71 // "Expired" and "not yet valid" collapse into a single status. 72 return CERT_STATUS_DATE_INVALID; 73 74 case CSSMERR_TP_CERT_REVOKED: 75 case CSSMERR_TP_CERT_SUSPENDED: 76 return CERT_STATUS_REVOKED; 77 78 case CSSMERR_APPLETP_HOSTNAME_MISMATCH: 79 return CERT_STATUS_COMMON_NAME_INVALID; 80 81 case CSSMERR_APPLETP_CRL_NOT_FOUND: 82 case CSSMERR_APPLETP_INCOMPLETE_REVOCATION_CHECK: 83 case CSSMERR_APPLETP_OCSP_UNAVAILABLE: 84 return CERT_STATUS_NO_REVOCATION_MECHANISM; 85 86 case CSSMERR_APPLETP_CRL_NOT_TRUSTED: 87 case CSSMERR_APPLETP_CRL_SERVER_DOWN: 88 case CSSMERR_APPLETP_CRL_NOT_VALID_YET: 89 case CSSMERR_APPLETP_NETWORK_FAILURE: 90 case CSSMERR_APPLETP_OCSP_BAD_RESPONSE: 91 case CSSMERR_APPLETP_OCSP_NO_SIGNER: 92 case CSSMERR_APPLETP_OCSP_RESP_UNAUTHORIZED: 93 case CSSMERR_APPLETP_OCSP_RESP_SIG_REQUIRED: 94 case CSSMERR_APPLETP_OCSP_RESP_MALFORMED_REQ: 95 case CSSMERR_APPLETP_OCSP_RESP_INTERNAL_ERR: 96 case CSSMERR_APPLETP_OCSP_RESP_TRY_LATER: 97 // We asked for a revocation check, but didn't get it. 98 return CERT_STATUS_UNABLE_TO_CHECK_REVOCATION; 99 100 default: 101 // Failure was due to something Chromium doesn't define a 102 // specific status for (such as basic constraints violation, or 103 // unknown critical extension) 104 return CERT_STATUS_INVALID; 105 } 106} 107 108bool OverrideHostnameMismatch(const std::string& hostname, 109 std::vector<std::string>* dns_names) { 110 // SecTrustEvaluate() does not check dotted IP addresses. If 111 // hostname is provided as, say, 127.0.0.1, then the error 112 // CSSMERR_APPLETP_HOSTNAME_MISMATCH will always be returned, 113 // even if the certificate contains 127.0.0.1 as one of its names. 114 // We, however, want to allow that behavior. SecTrustEvaluate() 115 // only checks for digits and dots when considering whether a 116 // hostname is an IP address, so IPv6 and hex addresses go through 117 // its normal comparison. 118 bool is_dotted_ip = true; 119 bool override_hostname_mismatch = false; 120 for (std::string::const_iterator c = hostname.begin(); 121 c != hostname.end() && is_dotted_ip; ++c) 122 is_dotted_ip = (*c >= '0' && *c <= '9') || *c == '.'; 123 if (is_dotted_ip) { 124 for (std::vector<std::string>::const_iterator name = dns_names->begin(); 125 name != dns_names->end() && !override_hostname_mismatch; ++name) 126 override_hostname_mismatch = (*name == hostname); 127 } 128 return override_hostname_mismatch; 129} 130 131struct CSSMFields { 132 CSSMFields() : cl_handle(NULL), num_of_fields(0), fields(NULL) {} 133 ~CSSMFields() { 134 if (cl_handle) 135 CSSM_CL_FreeFields(cl_handle, num_of_fields, &fields); 136 } 137 138 CSSM_CL_HANDLE cl_handle; 139 uint32 num_of_fields; 140 CSSM_FIELD_PTR fields; 141}; 142 143OSStatus GetCertFields(X509Certificate::OSCertHandle cert_handle, 144 CSSMFields* fields) { 145 DCHECK(cert_handle); 146 DCHECK(fields); 147 148 CSSM_DATA cert_data; 149 OSStatus status = SecCertificateGetData(cert_handle, &cert_data); 150 if (status) 151 return status; 152 153 status = SecCertificateGetCLHandle(cert_handle, &fields->cl_handle); 154 if (status) { 155 DCHECK(!fields->cl_handle); 156 return status; 157 } 158 159 status = CSSM_CL_CertGetAllFields(fields->cl_handle, &cert_data, 160 &fields->num_of_fields, &fields->fields); 161 return status; 162} 163 164void GetCertGeneralNamesForOID(X509Certificate::OSCertHandle cert_handle, 165 CSSM_OID oid, CE_GeneralNameType name_type, 166 std::vector<std::string>* result) { 167 // For future extension: We only support general names of types 168 // GNT_RFC822Name, GNT_DNSName or GNT_URI. 169 DCHECK(name_type == GNT_RFC822Name || 170 name_type == GNT_DNSName || 171 name_type == GNT_URI); 172 173 CSSMFields fields; 174 OSStatus status = GetCertFields(cert_handle, &fields); 175 if (status) 176 return; 177 178 for (size_t field = 0; field < fields.num_of_fields; ++field) { 179 if (CSSMOIDEqual(&fields.fields[field].FieldOid, &oid)) { 180 CSSM_X509_EXTENSION_PTR cssm_ext = 181 reinterpret_cast<CSSM_X509_EXTENSION_PTR>( 182 fields.fields[field].FieldValue.Data); 183 CE_GeneralNames* alt_name = 184 reinterpret_cast<CE_GeneralNames*>(cssm_ext->value.parsedValue); 185 186 for (size_t name = 0; name < alt_name->numNames; ++name) { 187 const CE_GeneralName& name_struct = alt_name->generalName[name]; 188 // All of the general name types we support are encoded as 189 // IA5String. In general, we should be switching off 190 // |name_struct.nameType| and doing type-appropriate conversions. See 191 // certextensions.h and the comment immediately preceding 192 // CE_GeneralNameType for more information. 193 if (name_struct.nameType == name_type) { 194 const CSSM_DATA& name_data = name_struct.name; 195 std::string value = std::string( 196 reinterpret_cast<const char*>(name_data.Data), 197 name_data.Length); 198 result->push_back(value); 199 } 200 } 201 } 202 } 203} 204 205void GetCertDateForOID(X509Certificate::OSCertHandle cert_handle, 206 CSSM_OID oid, Time* result) { 207 *result = Time::Time(); 208 209 CSSMFields fields; 210 OSStatus status = GetCertFields(cert_handle, &fields); 211 if (status) 212 return; 213 214 for (size_t field = 0; field < fields.num_of_fields; ++field) { 215 if (CSSMOIDEqual(&fields.fields[field].FieldOid, &oid)) { 216 CSSM_X509_TIME* x509_time = reinterpret_cast<CSSM_X509_TIME*>( 217 fields.fields[field].FieldValue.Data); 218 if (x509_time->timeType != BER_TAG_UTC_TIME && 219 x509_time->timeType != BER_TAG_GENERALIZED_TIME) { 220 LOG(ERROR) << "Unsupported date/time format " 221 << x509_time->timeType; 222 return; 223 } 224 225 base::StringPiece time_string( 226 reinterpret_cast<const char*>(x509_time->time.Data), 227 x509_time->time.Length); 228 CertDateFormat format = x509_time->timeType == BER_TAG_UTC_TIME ? 229 CERT_DATE_FORMAT_UTC_TIME : CERT_DATE_FORMAT_GENERALIZED_TIME; 230 if (!ParseCertificateDate(time_string, format, result)) 231 LOG(ERROR) << "Invalid certificate date/time " << time_string; 232 return; 233 } 234 } 235} 236 237std::string GetCertSerialNumber(X509Certificate::OSCertHandle cert_handle) { 238 CSSMFields fields; 239 OSStatus status = GetCertFields(cert_handle, &fields); 240 if (status) 241 return ""; 242 243 std::string ret; 244 for (size_t field = 0; field < fields.num_of_fields; ++field) { 245 if (!CSSMOIDEqual(&fields.fields[field].FieldOid, 246 &CSSMOID_X509V1SerialNumber)) { 247 continue; 248 } 249 ret.assign( 250 reinterpret_cast<char*>(fields.fields[field].FieldValue.Data), 251 fields.fields[field].FieldValue.Length); 252 break; 253 } 254 255 // Remove leading zeros. 256 while (ret.size() > 1 && ret[0] == 0) 257 ret = ret.substr(1, ret.size() - 1); 258 259 return ret; 260} 261 262// Creates a SecPolicyRef for the given OID, with optional value. 263OSStatus CreatePolicy(const CSSM_OID* policy_OID, 264 void* option_data, 265 size_t option_length, 266 SecPolicyRef* policy) { 267 SecPolicySearchRef search; 268 OSStatus err = SecPolicySearchCreate(CSSM_CERT_X_509v3, policy_OID, NULL, 269 &search); 270 if (err) 271 return err; 272 err = SecPolicySearchCopyNext(search, policy); 273 CFRelease(search); 274 if (err) 275 return err; 276 277 if (option_data) { 278 CSSM_DATA options_data = { 279 option_length, 280 reinterpret_cast<uint8_t*>(option_data) 281 }; 282 err = SecPolicySetValue(*policy, &options_data); 283 if (err) { 284 CFRelease(*policy); 285 return err; 286 } 287 } 288 return noErr; 289} 290 291// Creates a series of SecPolicyRefs to be added to a SecTrustRef used to 292// validate a certificate for an SSL peer. |hostname| contains the name of 293// the SSL peer that the certificate should be verified against. |flags| is 294// a bitwise-OR of VerifyFlags that can further alter how trust is 295// validated, such as how revocation is checked. If successful, returns 296// noErr, and stores the resultant array of SecPolicyRefs in |policies|. 297OSStatus CreateTrustPolicies(const std::string& hostname, int flags, 298 ScopedCFTypeRef<CFArrayRef>* policies) { 299 // Create an SSL SecPolicyRef, and configure it to perform hostname 300 // validation. The hostname check does 99% of what we want, with the 301 // exception of dotted IPv4 addreses, which we handle ourselves below. 302 CSSM_APPLE_TP_SSL_OPTIONS tp_ssl_options = { 303 CSSM_APPLE_TP_SSL_OPTS_VERSION, 304 hostname.size(), 305 hostname.data(), 306 0 307 }; 308 SecPolicyRef ssl_policy; 309 OSStatus status = CreatePolicy(&CSSMOID_APPLE_TP_SSL, &tp_ssl_options, 310 sizeof(tp_ssl_options), &ssl_policy); 311 if (status) 312 return status; 313 ScopedCFTypeRef<SecPolicyRef> scoped_ssl_policy(ssl_policy); 314 315 // Manually add OCSP and CRL policies. If neither an OCSP or CRL policy is 316 // specified, the Apple TP module will add whatever the system settings 317 // are, which is not desirable here. 318 // 319 // Note that this causes any locally configured OCSP responder URL to be 320 // ignored. 321 CSSM_APPLE_TP_OCSP_OPTIONS tp_ocsp_options; 322 memset(&tp_ocsp_options, 0, sizeof(tp_ocsp_options)); 323 tp_ocsp_options.Version = CSSM_APPLE_TP_OCSP_OPTS_VERSION; 324 325 CSSM_APPLE_TP_CRL_OPTIONS tp_crl_options; 326 memset(&tp_crl_options, 0, sizeof(tp_crl_options)); 327 tp_crl_options.Version = CSSM_APPLE_TP_CRL_OPTS_VERSION; 328 329 if (flags & X509Certificate::VERIFY_REV_CHECKING_ENABLED) { 330 // If an OCSP responder is available, use it, and avoid fetching any 331 // CRLs for that certificate if possible, as they may be much larger. 332 tp_ocsp_options.Flags = CSSM_TP_ACTION_OCSP_SUFFICIENT; 333 // Ensure that CRLs can be fetched if a crlDistributionPoint extension 334 // is found. Otherwise, only the local CRL cache will be consulted. 335 tp_crl_options.CrlFlags |= CSSM_TP_ACTION_FETCH_CRL_FROM_NET; 336 } else { 337 // Disable OCSP network fetching, but still permit cached OCSP responses 338 // to be used. This is equivalent to the Windows code's usage of 339 // CERT_CHAIN_REVOCATION_CHECK_CACHE_ONLY. 340 tp_ocsp_options.Flags = CSSM_TP_ACTION_OCSP_DISABLE_NET; 341 // The default CrlFlags will ensure only cached CRLs are used. 342 } 343 344 SecPolicyRef ocsp_policy; 345 status = CreatePolicy(&CSSMOID_APPLE_TP_REVOCATION_OCSP, &tp_ocsp_options, 346 sizeof(tp_ocsp_options), &ocsp_policy); 347 if (status) 348 return status; 349 ScopedCFTypeRef<SecPolicyRef> scoped_ocsp_policy(ocsp_policy); 350 351 SecPolicyRef crl_policy; 352 status = CreatePolicy(&CSSMOID_APPLE_TP_REVOCATION_CRL, &tp_crl_options, 353 sizeof(tp_crl_options), &crl_policy); 354 if (status) 355 return status; 356 ScopedCFTypeRef<SecPolicyRef> scoped_crl_policy(crl_policy); 357 358 CFTypeRef local_policies[] = { ssl_policy, ocsp_policy, crl_policy }; 359 CFArrayRef policy_array = CFArrayCreate(kCFAllocatorDefault, local_policies, 360 arraysize(local_policies), 361 &kCFTypeArrayCallBacks); 362 if (!policy_array) 363 return memFullErr; 364 365 policies->reset(policy_array); 366 return noErr; 367} 368 369// Gets the issuer for a given cert, starting with the cert itself and 370// including the intermediate and finally root certificates (if any). 371// This function calls SecTrust but doesn't actually pay attention to the trust 372// result: it shouldn't be used to determine trust, just to traverse the chain. 373// Caller is responsible for releasing the value stored into *out_cert_chain. 374OSStatus CopyCertChain(SecCertificateRef cert_handle, 375 CFArrayRef* out_cert_chain) { 376 DCHECK(cert_handle); 377 DCHECK(out_cert_chain); 378 // Create an SSL policy ref configured for client cert evaluation. 379 SecPolicyRef ssl_policy; 380 OSStatus result = X509Certificate::CreateSSLClientPolicy(&ssl_policy); 381 if (result) 382 return result; 383 ScopedCFTypeRef<SecPolicyRef> scoped_ssl_policy(ssl_policy); 384 385 // Create a SecTrustRef. 386 ScopedCFTypeRef<CFArrayRef> input_certs(CFArrayCreate( 387 NULL, const_cast<const void**>(reinterpret_cast<void**>(&cert_handle)), 388 1, &kCFTypeArrayCallBacks)); 389 SecTrustRef trust_ref = NULL; 390 result = SecTrustCreateWithCertificates(input_certs, ssl_policy, &trust_ref); 391 if (result) 392 return result; 393 ScopedCFTypeRef<SecTrustRef> trust(trust_ref); 394 395 // Evaluate trust, which creates the cert chain. 396 SecTrustResultType status; 397 CSSM_TP_APPLE_EVIDENCE_INFO* status_chain; 398 result = SecTrustEvaluate(trust, &status); 399 if (result) 400 return result; 401 return SecTrustGetResult(trust, &status, out_cert_chain, &status_chain); 402} 403 404// Returns true if |purpose| is listed as allowed in |usage|. This 405// function also considers the "Any" purpose. If the attribute is 406// present and empty, we return false. 407bool ExtendedKeyUsageAllows(const CE_ExtendedKeyUsage* usage, 408 const CSSM_OID* purpose) { 409 for (unsigned p = 0; p < usage->numPurposes; ++p) { 410 if (CSSMOIDEqual(&usage->purposes[p], purpose)) 411 return true; 412 if (CSSMOIDEqual(&usage->purposes[p], &CSSMOID_ExtendedKeyUsageAny)) 413 return true; 414 } 415 return false; 416} 417 418// Test that a given |cert_handle| is actually a valid X.509 certificate, and 419// return true if it is. 420// 421// On OS X, SecCertificateCreateFromData() does not return any errors if 422// called with invalid data, as long as data is present. The actual decoding 423// of the certificate does not happen until an API that requires a CSSM 424// handle is called. While SecCertificateGetCLHandle is the most likely 425// candidate, as it performs the parsing, it does not check whether the 426// parsing was actually successful. Instead, SecCertificateGetSubject is 427// used (supported since 10.3), as a means to check that the certificate 428// parsed as a valid X.509 certificate. 429bool IsValidOSCertHandle(SecCertificateRef cert_handle) { 430 const CSSM_X509_NAME* sanity_check = NULL; 431 OSStatus status = SecCertificateGetSubject(cert_handle, &sanity_check); 432 return status == noErr && sanity_check; 433} 434 435// Parses |data| of length |length|, attempting to decode it as the specified 436// |format|. If |data| is in the specified format, any certificates contained 437// within are stored into |output|. 438void AddCertificatesFromBytes(const char* data, size_t length, 439 SecExternalFormat format, 440 X509Certificate::OSCertHandles* output) { 441 SecExternalFormat input_format = format; 442 ScopedCFTypeRef<CFDataRef> local_data(CFDataCreateWithBytesNoCopy( 443 kCFAllocatorDefault, reinterpret_cast<const UInt8*>(data), length, 444 kCFAllocatorNull)); 445 446 CFArrayRef items = NULL; 447 OSStatus status = SecKeychainItemImport(local_data, NULL, &input_format, 448 NULL, 0, NULL, NULL, &items); 449 if (status) { 450 DLOG(WARNING) << status << " Unable to import items from data of length " 451 << length; 452 return; 453 } 454 455 ScopedCFTypeRef<CFArrayRef> scoped_items(items); 456 CFTypeID cert_type_id = SecCertificateGetTypeID(); 457 458 for (CFIndex i = 0; i < CFArrayGetCount(items); ++i) { 459 SecKeychainItemRef item = reinterpret_cast<SecKeychainItemRef>( 460 const_cast<void*>(CFArrayGetValueAtIndex(items, i))); 461 462 // While inputFormat implies only certificates will be imported, if/when 463 // other formats (eg: PKCS#12) are supported, this may also include 464 // private keys or other items types, so filter appropriately. 465 if (CFGetTypeID(item) == cert_type_id) { 466 SecCertificateRef cert = reinterpret_cast<SecCertificateRef>(item); 467 // OS X ignores |input_format| if it detects that |local_data| is PEM 468 // encoded, attempting to decode data based on internal rules for PEM 469 // block headers. If a PKCS#7 blob is encoded with a PEM block of 470 // CERTIFICATE, OS X 10.5 will return a single, invalid certificate 471 // based on the decoded data. If this happens, the certificate should 472 // not be included in |output|. Because |output| is empty, 473 // CreateCertificateListfromBytes will use PEMTokenizer to decode the 474 // data. When called again with the decoded data, OS X will honor 475 // |input_format|, causing decode to succeed. On OS X 10.6, the data 476 // is properly decoded as a PKCS#7, whether PEM or not, which avoids 477 // the need to fallback to internal decoding. 478 if (IsValidOSCertHandle(cert)) { 479 CFRetain(cert); 480 output->push_back(cert); 481 } 482 } 483 } 484} 485 486struct CSSMOIDString { 487 const CSSM_OID* oid_; 488 std::string string_; 489}; 490 491typedef std::vector<CSSMOIDString> CSSMOIDStringVector; 492 493bool CERTNameToCSSMOIDVector(CERTName* name, CSSMOIDStringVector* out_values) { 494 struct OIDCSSMMap { 495 SECOidTag sec_OID_; 496 const CSSM_OID* cssm_OID_; 497 }; 498 499 const OIDCSSMMap kOIDs[] = { 500 { SEC_OID_AVA_COMMON_NAME, &CSSMOID_CommonName }, 501 { SEC_OID_AVA_COUNTRY_NAME, &CSSMOID_CountryName }, 502 { SEC_OID_AVA_LOCALITY, &CSSMOID_LocalityName }, 503 { SEC_OID_AVA_STATE_OR_PROVINCE, &CSSMOID_StateProvinceName }, 504 { SEC_OID_AVA_STREET_ADDRESS, &CSSMOID_StreetAddress }, 505 { SEC_OID_AVA_ORGANIZATION_NAME, &CSSMOID_OrganizationName }, 506 { SEC_OID_AVA_ORGANIZATIONAL_UNIT_NAME, &CSSMOID_OrganizationalUnitName }, 507 { SEC_OID_AVA_DN_QUALIFIER, &CSSMOID_DNQualifier }, 508 { SEC_OID_RFC1274_UID, &CSSMOID_UniqueIdentifier }, 509 { SEC_OID_PKCS9_EMAIL_ADDRESS, &CSSMOID_EmailAddress }, 510 }; 511 512 CERTRDN** rdns = name->rdns; 513 for (size_t rdn = 0; rdns[rdn]; ++rdn) { 514 CERTAVA** avas = rdns[rdn]->avas; 515 for (size_t pair = 0; avas[pair] != 0; ++pair) { 516 SECOidTag tag = CERT_GetAVATag(avas[pair]); 517 if (tag == SEC_OID_UNKNOWN) { 518 return false; 519 } 520 CSSMOIDString oidString; 521 bool found_oid = false; 522 for (size_t oid = 0; oid < ARRAYSIZE_UNSAFE(kOIDs); ++oid) { 523 if (kOIDs[oid].sec_OID_ == tag) { 524 SECItem* decode_item = CERT_DecodeAVAValue(&avas[pair]->value); 525 if (!decode_item) 526 return false; 527 528 // TODO(wtc): Pass decode_item to CERT_RFC1485_EscapeAndQuote. 529 std::string value(reinterpret_cast<char*>(decode_item->data), 530 decode_item->len); 531 oidString.oid_ = kOIDs[oid].cssm_OID_; 532 oidString.string_ = value; 533 out_values->push_back(oidString); 534 SECITEM_FreeItem(decode_item, PR_TRUE); 535 found_oid = true; 536 break; 537 } 538 } 539 if (!found_oid) { 540 DLOG(ERROR) << "Unrecognized OID: " << tag; 541 } 542 } 543 } 544 return true; 545} 546 547class ScopedCertName { 548 public: 549 explicit ScopedCertName(CERTName* name) : name_(name) { } 550 ~ScopedCertName() { 551 if (name_) CERT_DestroyName(name_); 552 } 553 operator CERTName*() { return name_; } 554 555 private: 556 CERTName* name_; 557}; 558 559class ScopedEncodedCertResults { 560 public: 561 explicit ScopedEncodedCertResults(CSSM_TP_RESULT_SET* results) 562 : results_(results) { } 563 ~ScopedEncodedCertResults() { 564 if (results_) { 565 CSSM_ENCODED_CERT* encCert = 566 reinterpret_cast<CSSM_ENCODED_CERT*>(results_->Results); 567 for (uint32 i = 0; i < results_->NumberOfResults; i++) { 568 crypto::CSSMFree(encCert[i].CertBlob.Data); 569 } 570 } 571 crypto::CSSMFree(results_->Results); 572 crypto::CSSMFree(results_); 573 } 574 575private: 576 CSSM_TP_RESULT_SET* results_; 577}; 578 579void AppendPublicKeyHashes(CFArrayRef chain, 580 std::vector<SHA1Fingerprint>* hashes) { 581 const CFIndex n = CFArrayGetCount(chain); 582 for (CFIndex i = 0; i < n; i++) { 583 SecCertificateRef cert = reinterpret_cast<SecCertificateRef>( 584 const_cast<void*>(CFArrayGetValueAtIndex(chain, i))); 585 586 CSSM_DATA cert_data; 587 OSStatus err = SecCertificateGetData(cert, &cert_data); 588 DCHECK_EQ(err, noErr); 589 base::StringPiece der_bytes(reinterpret_cast<const char*>(cert_data.Data), 590 cert_data.Length); 591 base::StringPiece spki_bytes; 592 if (!asn1::ExtractSPKIFromDERCert(der_bytes, &spki_bytes)) 593 continue; 594 595 SHA1Fingerprint hash; 596 CC_SHA1(spki_bytes.data(), spki_bytes.size(), hash.data); 597 hashes->push_back(hash); 598 } 599} 600 601} // namespace 602 603void X509Certificate::Initialize() { 604 const CSSM_X509_NAME* name; 605 OSStatus status = SecCertificateGetSubject(cert_handle_, &name); 606 if (!status) 607 subject_.Parse(name); 608 609 status = SecCertificateGetIssuer(cert_handle_, &name); 610 if (!status) 611 issuer_.Parse(name); 612 613 GetCertDateForOID(cert_handle_, CSSMOID_X509V1ValidityNotBefore, 614 &valid_start_); 615 GetCertDateForOID(cert_handle_, CSSMOID_X509V1ValidityNotAfter, 616 &valid_expiry_); 617 618 fingerprint_ = CalculateFingerprint(cert_handle_); 619 serial_number_ = GetCertSerialNumber(cert_handle_); 620} 621 622// IsIssuedByKnownRoot returns true if the given chain is rooted at a root CA 623// that we recognise as a standard root. 624// static 625bool X509Certificate::IsIssuedByKnownRoot(CFArrayRef chain) { 626 int n = CFArrayGetCount(chain); 627 if (n < 1) 628 return false; 629 SecCertificateRef root_ref = reinterpret_cast<SecCertificateRef>( 630 const_cast<void*>(CFArrayGetValueAtIndex(chain, n - 1))); 631 SHA1Fingerprint hash = X509Certificate::CalculateFingerprint(root_ref); 632 return IsSHA1HashInSortedArray( 633 hash, &kKnownRootCertSHA1Hashes[0][0], sizeof(kKnownRootCertSHA1Hashes)); 634} 635 636// static 637X509Certificate* X509Certificate::CreateSelfSigned( 638 crypto::RSAPrivateKey* key, 639 const std::string& subject, 640 uint32 serial_number, 641 base::TimeDelta valid_duration) { 642 DCHECK(key); 643 DCHECK(!subject.empty()); 644 645 if (valid_duration.InSeconds() > UINT32_MAX) { 646 LOG(ERROR) << "valid_duration too big" << valid_duration.InSeconds(); 647 valid_duration = base::TimeDelta::FromSeconds(UINT32_MAX); 648 } 649 650 // There is a comment in 651 // http://www.opensource.apple.com/source/security_certtool/security_certtool-31828/src/CertTool.cpp 652 // that serial_numbers being passed into CSSM_TP_SubmitCredRequest can't have 653 // their high bit set. We will continue though and mask it out below. 654 if (serial_number & 0x80000000) 655 LOG(ERROR) << "serial_number has high bit set " << serial_number; 656 657 // NSS is used to parse the subject string into a set of 658 // CSSM_OID/string pairs. There doesn't appear to be a system routine for 659 // parsing Distinguished Name strings. 660 crypto::EnsureNSSInit(); 661 662 CSSMOIDStringVector subject_name_oids; 663 ScopedCertName subject_name( 664 CERT_AsciiToName(const_cast<char*>(subject.c_str()))); 665 if (!CERTNameToCSSMOIDVector(subject_name, &subject_name_oids)) { 666 DLOG(ERROR) << "Unable to generate CSSMOIDMap from " << subject; 667 return NULL; 668 } 669 670 // Convert the map of oid/string pairs into an array of 671 // CSSM_APPLE_TP_NAME_OIDs. 672 std::vector<CSSM_APPLE_TP_NAME_OID> cssm_subject_names; 673 for(CSSMOIDStringVector::iterator iter = subject_name_oids.begin(); 674 iter != subject_name_oids.end(); ++iter) { 675 CSSM_APPLE_TP_NAME_OID cssm_subject_name; 676 cssm_subject_name.oid = iter->oid_; 677 cssm_subject_name.string = iter->string_.c_str(); 678 cssm_subject_names.push_back(cssm_subject_name); 679 } 680 681 if (cssm_subject_names.empty()) { 682 DLOG(ERROR) << "cssm_subject_names.size() == 0. Input: " << subject; 683 return NULL; 684 } 685 686 // Set up a certificate request. 687 CSSM_APPLE_TP_CERT_REQUEST certReq; 688 memset(&certReq, 0, sizeof(certReq)); 689 certReq.cspHand = crypto::GetSharedCSPHandle(); 690 certReq.clHand = crypto::GetSharedCLHandle(); 691 // See comment about serial numbers above. 692 certReq.serialNumber = serial_number & 0x7fffffff; 693 certReq.numSubjectNames = cssm_subject_names.size(); 694 certReq.subjectNames = &cssm_subject_names[0]; 695 certReq.numIssuerNames = 0; // Root. 696 certReq.issuerNames = NULL; 697 certReq.issuerNameX509 = NULL; 698 certReq.certPublicKey = key->public_key(); 699 certReq.issuerPrivateKey = key->key(); 700 // These are the Apple defaults. 701 certReq.signatureAlg = CSSM_ALGID_SHA1WithRSA; 702 certReq.signatureOid = CSSMOID_SHA1WithRSA; 703 certReq.notBefore = 0; 704 certReq.notAfter = static_cast<uint32>(valid_duration.InSeconds()); 705 certReq.numExtensions = 0; 706 certReq.extensions = NULL; 707 certReq.challengeString = NULL; 708 709 CSSM_TP_REQUEST_SET reqSet; 710 reqSet.NumberOfRequests = 1; 711 reqSet.Requests = &certReq; 712 713 CSSM_FIELD policyId; 714 memset(&policyId, 0, sizeof(policyId)); 715 policyId.FieldOid = CSSMOID_APPLE_TP_LOCAL_CERT_GEN; 716 717 CSSM_TP_CALLERAUTH_CONTEXT callerAuthContext; 718 memset(&callerAuthContext, 0, sizeof(callerAuthContext)); 719 callerAuthContext.Policy.NumberOfPolicyIds = 1; 720 callerAuthContext.Policy.PolicyIds = &policyId; 721 722 CSSM_TP_HANDLE tp_handle = crypto::GetSharedTPHandle(); 723 CSSM_DATA refId; 724 memset(&refId, 0, sizeof(refId)); 725 sint32 estTime; 726 CSSM_RETURN crtn = CSSM_TP_SubmitCredRequest(tp_handle, NULL, 727 CSSM_TP_AUTHORITY_REQUEST_CERTISSUE, &reqSet, &callerAuthContext, 728 &estTime, &refId); 729 if(crtn) { 730 DLOG(ERROR) << "CSSM_TP_SubmitCredRequest failed " << crtn; 731 return NULL; 732 } 733 734 CSSM_BOOL confirmRequired; 735 CSSM_TP_RESULT_SET *resultSet = NULL; 736 crtn = CSSM_TP_RetrieveCredResult(tp_handle, &refId, NULL, &estTime, 737 &confirmRequired, &resultSet); 738 ScopedEncodedCertResults scopedResults(resultSet); 739 crypto::CSSMFree(refId.Data); 740 if (crtn) { 741 DLOG(ERROR) << "CSSM_TP_RetrieveCredResult failed " << crtn; 742 return NULL; 743 } 744 745 if (confirmRequired) { 746 // Potential leak here of resultSet. |confirmRequired| should never be 747 // true. 748 DLOG(ERROR) << "CSSM_TP_RetrieveCredResult required confirmation"; 749 return NULL; 750 } 751 752 if (resultSet->NumberOfResults != 1) { 753 DLOG(ERROR) << "Unexpected number of results: " 754 << resultSet->NumberOfResults; 755 return NULL; 756 } 757 758 CSSM_ENCODED_CERT* encCert = 759 reinterpret_cast<CSSM_ENCODED_CERT*>(resultSet->Results); 760 base::mac::ScopedCFTypeRef<SecCertificateRef> scoped_cert; 761 SecCertificateRef certificate_ref = NULL; 762 OSStatus os_status = 763 SecCertificateCreateFromData(&encCert->CertBlob, encCert->CertType, 764 encCert->CertEncoding, &certificate_ref); 765 if (os_status != 0) { 766 DLOG(ERROR) << "SecCertificateCreateFromData failed: " << os_status; 767 return NULL; 768 } 769 scoped_cert.reset(certificate_ref); 770 771 return CreateFromHandle( 772 scoped_cert, X509Certificate::SOURCE_LONE_CERT_IMPORT, 773 X509Certificate::OSCertHandles()); 774} 775 776void X509Certificate::GetDNSNames(std::vector<std::string>* dns_names) const { 777 dns_names->clear(); 778 779 GetCertGeneralNamesForOID(cert_handle_, CSSMOID_SubjectAltName, GNT_DNSName, 780 dns_names); 781 782 if (dns_names->empty()) 783 dns_names->push_back(subject_.common_name); 784} 785 786int X509Certificate::Verify(const std::string& hostname, int flags, 787 CertVerifyResult* verify_result) const { 788 verify_result->Reset(); 789 790 if (IsBlacklisted()) { 791 verify_result->cert_status |= CERT_STATUS_REVOKED; 792 return ERR_CERT_REVOKED; 793 } 794 795 ScopedCFTypeRef<CFArrayRef> trust_policies; 796 OSStatus status = CreateTrustPolicies(hostname, flags, &trust_policies); 797 if (status) 798 return NetErrorFromOSStatus(status); 799 800 // Create and configure a SecTrustRef, which takes our certificate(s) 801 // and our SSL SecPolicyRef. SecTrustCreateWithCertificates() takes an 802 // array of certificates, the first of which is the certificate we're 803 // verifying, and the subsequent (optional) certificates are used for 804 // chain building. 805 CFMutableArrayRef cert_array = CFArrayCreateMutable(kCFAllocatorDefault, 0, 806 &kCFTypeArrayCallBacks); 807 if (!cert_array) 808 return ERR_OUT_OF_MEMORY; 809 ScopedCFTypeRef<CFArrayRef> scoped_cert_array(cert_array); 810 CFArrayAppendValue(cert_array, cert_handle_); 811 for (size_t i = 0; i < intermediate_ca_certs_.size(); ++i) 812 CFArrayAppendValue(cert_array, intermediate_ca_certs_[i]); 813 814 // From here on, only one thread can be active at a time. We have had a number 815 // of sporadic crashes in the SecTrustEvaluate call below, way down inside 816 // Apple's cert code, which we suspect are caused by a thread-safety issue. 817 // So as a speculative fix allow only one thread to use SecTrust on this cert. 818 base::AutoLock lock(verification_lock_); 819 820 SecTrustRef trust_ref = NULL; 821 status = SecTrustCreateWithCertificates(cert_array, trust_policies, 822 &trust_ref); 823 if (status) 824 return NetErrorFromOSStatus(status); 825 ScopedCFTypeRef<SecTrustRef> scoped_trust_ref(trust_ref); 826 827 if (TestRootCerts::HasInstance()) { 828 status = TestRootCerts::GetInstance()->FixupSecTrustRef(trust_ref); 829 if (status) 830 return NetErrorFromOSStatus(status); 831 } 832 833 CSSM_APPLE_TP_ACTION_DATA tp_action_data; 834 memset(&tp_action_data, 0, sizeof(tp_action_data)); 835 tp_action_data.Version = CSSM_APPLE_TP_ACTION_VERSION; 836 // Allow CSSM to download any missing intermediate certificates if an 837 // authorityInfoAccess extension or issuerAltName extension is present. 838 tp_action_data.ActionFlags = CSSM_TP_ACTION_FETCH_CERT_FROM_NET; 839 840 if (flags & VERIFY_REV_CHECKING_ENABLED) { 841 // Require a positive result from an OCSP responder or a CRL (or both) 842 // for every certificate in the chain. The Apple TP automatically 843 // excludes the self-signed root from this requirement. If a certificate 844 // is missing both a crlDistributionPoints extension and an 845 // authorityInfoAccess extension with an OCSP responder URL, then we 846 // will get a kSecTrustResultRecoverableTrustFailure back from 847 // SecTrustEvaluate(), with a 848 // CSSMERR_APPLETP_INCOMPLETE_REVOCATION_CHECK error code. In that case, 849 // we'll set our own result to include 850 // CERT_STATUS_NO_REVOCATION_MECHANISM. If one or both extensions are 851 // present, and a check fails (server unavailable, OCSP retry later, 852 // signature mismatch), then we'll set our own result to include 853 // CERT_STATUS_UNABLE_TO_CHECK_REVOCATION. 854 tp_action_data.ActionFlags |= CSSM_TP_ACTION_REQUIRE_REV_PER_CERT; 855 verify_result->cert_status |= CERT_STATUS_REV_CHECKING_ENABLED; 856 } else { 857 // EV requires revocation checking. 858 // Note, under the hood, SecTrustEvaluate() will modify the OCSP options 859 // so as to attempt OCSP fetching if it believes a certificate may chain 860 // to an EV root. However, because network fetches are disabled in 861 // CreateTrustPolicies() when revocation checking is disabled, these 862 // will only go against the local cache. 863 flags &= ~VERIFY_EV_CERT; 864 } 865 866 CFDataRef action_data_ref = 867 CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, 868 reinterpret_cast<UInt8*>(&tp_action_data), 869 sizeof(tp_action_data), kCFAllocatorNull); 870 if (!action_data_ref) 871 return ERR_OUT_OF_MEMORY; 872 ScopedCFTypeRef<CFDataRef> scoped_action_data_ref(action_data_ref); 873 status = SecTrustSetParameters(trust_ref, CSSM_TP_ACTION_DEFAULT, 874 action_data_ref); 875 if (status) 876 return NetErrorFromOSStatus(status); 877 878 // Verify the certificate. A non-zero result from SecTrustGetResult() 879 // indicates that some fatal error occurred and the chain couldn't be 880 // processed, not that the chain contains no errors. We need to examine the 881 // output of SecTrustGetResult() to determine that. 882 SecTrustResultType trust_result; 883 status = SecTrustEvaluate(trust_ref, &trust_result); 884 if (status) 885 return NetErrorFromOSStatus(status); 886 CFArrayRef completed_chain = NULL; 887 CSSM_TP_APPLE_EVIDENCE_INFO* chain_info; 888 status = SecTrustGetResult(trust_ref, &trust_result, &completed_chain, 889 &chain_info); 890 if (status) 891 return NetErrorFromOSStatus(status); 892 ScopedCFTypeRef<CFArrayRef> scoped_completed_chain(completed_chain); 893 894 // Evaluate the results 895 OSStatus cssm_result; 896 bool got_certificate_error = false; 897 switch (trust_result) { 898 case kSecTrustResultUnspecified: 899 case kSecTrustResultProceed: 900 // Certificate chain is valid and trusted ("unspecified" indicates that 901 // the user has not explicitly set a trust setting) 902 break; 903 904 case kSecTrustResultDeny: 905 case kSecTrustResultConfirm: 906 // Certificate chain is explicitly untrusted. For kSecTrustResultConfirm, 907 // we're following what Secure Transport does and treating it as 908 // "deny". 909 verify_result->cert_status |= CERT_STATUS_AUTHORITY_INVALID; 910 break; 911 912 case kSecTrustResultRecoverableTrustFailure: 913 // Certificate chain has a failure that can be overridden by the user. 914 status = SecTrustGetCssmResultCode(trust_ref, &cssm_result); 915 if (status) 916 return NetErrorFromOSStatus(status); 917 switch (cssm_result) { 918 case CSSMERR_TP_NOT_TRUSTED: 919 case CSSMERR_TP_INVALID_ANCHOR_CERT: 920 verify_result->cert_status |= CERT_STATUS_AUTHORITY_INVALID; 921 break; 922 case CSSMERR_TP_CERT_EXPIRED: 923 case CSSMERR_TP_CERT_NOT_VALID_YET: 924 verify_result->cert_status |= CERT_STATUS_DATE_INVALID; 925 break; 926 case CSSMERR_TP_CERT_REVOKED: 927 case CSSMERR_TP_CERT_SUSPENDED: 928 verify_result->cert_status |= CERT_STATUS_REVOKED; 929 break; 930 default: 931 // Look for specific per-certificate errors below. 932 break; 933 } 934 // Walk the chain of error codes in the CSSM_TP_APPLE_EVIDENCE_INFO 935 // structure which can catch multiple errors from each certificate. 936 for (CFIndex index = 0, chain_count = CFArrayGetCount(completed_chain); 937 index < chain_count; ++index) { 938 if (chain_info[index].StatusBits & CSSM_CERT_STATUS_EXPIRED || 939 chain_info[index].StatusBits & CSSM_CERT_STATUS_NOT_VALID_YET) 940 verify_result->cert_status |= CERT_STATUS_DATE_INVALID; 941 for (uint32 status_code_index = 0; 942 status_code_index < chain_info[index].NumStatusCodes; 943 ++status_code_index) { 944 got_certificate_error = true; 945 int cert_status = CertStatusFromOSStatus( 946 chain_info[index].StatusCodes[status_code_index]); 947 if (cert_status == CERT_STATUS_COMMON_NAME_INVALID) { 948 std::vector<std::string> names; 949 GetDNSNames(&names); 950 if (OverrideHostnameMismatch(hostname, &names)) 951 cert_status = 0; 952 } 953 verify_result->cert_status |= cert_status; 954 } 955 } 956 // Be paranoid and ensure that we recorded at least one certificate 957 // status on receiving kSecTrustResultRecoverableTrustFailure. The 958 // call to SecTrustGetCssmResultCode() should pick up when the chain 959 // is not trusted and the loop through CSSM_TP_APPLE_EVIDENCE_INFO 960 // should pick up everything else, but let's be safe. 961 if (!verify_result->cert_status && !got_certificate_error) { 962 verify_result->cert_status |= CERT_STATUS_INVALID; 963 NOTREACHED(); 964 } 965 break; 966 967 default: 968 status = SecTrustGetCssmResultCode(trust_ref, &cssm_result); 969 if (status) 970 return NetErrorFromOSStatus(status); 971 verify_result->cert_status |= CertStatusFromOSStatus(cssm_result); 972 if (!verify_result->cert_status) 973 verify_result->cert_status |= CERT_STATUS_INVALID; 974 break; 975 } 976 977 // TODO(wtc): Suppress CERT_STATUS_NO_REVOCATION_MECHANISM for now to be 978 // compatible with Windows, which in turn implements this behavior to be 979 // compatible with WinHTTP, which doesn't report this error (bug 3004). 980 verify_result->cert_status &= ~CERT_STATUS_NO_REVOCATION_MECHANISM; 981 982 if (IsCertStatusError(verify_result->cert_status)) 983 return MapCertStatusToNetError(verify_result->cert_status); 984 985 if (flags & VERIFY_EV_CERT) { 986 // Determine the certificate's EV status using SecTrustCopyExtendedResult(), 987 // which we need to look up because the function wasn't added until 988 // Mac OS X 10.5.7. 989 // Note: "ExtendedResult" means extended validation results. 990 CFBundleRef bundle = 991 CFBundleGetBundleWithIdentifier(CFSTR("com.apple.security")); 992 if (bundle) { 993 SecTrustCopyExtendedResultFuncPtr copy_extended_result = 994 reinterpret_cast<SecTrustCopyExtendedResultFuncPtr>( 995 CFBundleGetFunctionPointerForName(bundle, 996 CFSTR("SecTrustCopyExtendedResult"))); 997 if (copy_extended_result) { 998 CFDictionaryRef ev_dict = NULL; 999 status = copy_extended_result(trust_ref, &ev_dict); 1000 if (!status && ev_dict) { 1001 // The returned dictionary contains the EV organization name from the 1002 // server certificate, which we don't need at this point (and we 1003 // have other ways to access, anyway). All we care is that 1004 // SecTrustCopyExtendedResult() returned noErr and a non-NULL 1005 // dictionary. 1006 CFRelease(ev_dict); 1007 verify_result->cert_status |= CERT_STATUS_IS_EV; 1008 } 1009 } 1010 } 1011 } 1012 1013 AppendPublicKeyHashes(completed_chain, &verify_result->public_key_hashes); 1014 verify_result->is_issued_by_known_root = IsIssuedByKnownRoot(completed_chain); 1015 1016 if (IsPublicKeyBlacklisted(verify_result->public_key_hashes)) { 1017 verify_result->cert_status |= CERT_STATUS_AUTHORITY_INVALID; 1018 return MapCertStatusToNetError(verify_result->cert_status); 1019 } 1020 1021 return OK; 1022} 1023 1024bool X509Certificate::GetDEREncoded(std::string* encoded) { 1025 encoded->clear(); 1026 CSSM_DATA der_data; 1027 if(SecCertificateGetData(cert_handle_, &der_data) == noErr) { 1028 encoded->append(reinterpret_cast<char*>(der_data.Data), 1029 der_data.Length); 1030 return true; 1031 } 1032 return false; 1033} 1034 1035bool X509Certificate::VerifyEV() const { 1036 // We don't call this private method, but we do need to implement it because 1037 // it's defined in x509_certificate.h. We perform EV checking in the 1038 // Verify() above. 1039 NOTREACHED(); 1040 return false; 1041} 1042 1043// static 1044bool X509Certificate::IsSameOSCert(X509Certificate::OSCertHandle a, 1045 X509Certificate::OSCertHandle b) { 1046 DCHECK(a && b); 1047 if (a == b) 1048 return true; 1049 if (CFEqual(a, b)) 1050 return true; 1051 CSSM_DATA a_data, b_data; 1052 return SecCertificateGetData(a, &a_data) == noErr && 1053 SecCertificateGetData(b, &b_data) == noErr && 1054 a_data.Length == b_data.Length && 1055 memcmp(a_data.Data, b_data.Data, a_data.Length) == 0; 1056} 1057 1058// static 1059X509Certificate::OSCertHandle X509Certificate::CreateOSCertHandleFromBytes( 1060 const char* data, int length) { 1061 CSSM_DATA cert_data; 1062 cert_data.Data = const_cast<uint8*>(reinterpret_cast<const uint8*>(data)); 1063 cert_data.Length = length; 1064 1065 OSCertHandle cert_handle = NULL; 1066 OSStatus status = SecCertificateCreateFromData(&cert_data, 1067 CSSM_CERT_X_509v3, 1068 CSSM_CERT_ENCODING_DER, 1069 &cert_handle); 1070 if (status != noErr) 1071 return NULL; 1072 if (!IsValidOSCertHandle(cert_handle)) { 1073 CFRelease(cert_handle); 1074 return NULL; 1075 } 1076 return cert_handle; 1077} 1078 1079// static 1080X509Certificate::OSCertHandles X509Certificate::CreateOSCertHandlesFromBytes( 1081 const char* data, int length, Format format) { 1082 OSCertHandles results; 1083 1084 switch (format) { 1085 case FORMAT_SINGLE_CERTIFICATE: { 1086 OSCertHandle handle = CreateOSCertHandleFromBytes(data, length); 1087 if (handle) 1088 results.push_back(handle); 1089 break; 1090 } 1091 case FORMAT_PKCS7: 1092 AddCertificatesFromBytes(data, length, kSecFormatPKCS7, &results); 1093 break; 1094 default: 1095 NOTREACHED() << "Certificate format " << format << " unimplemented"; 1096 break; 1097 } 1098 1099 return results; 1100} 1101 1102// static 1103X509Certificate::OSCertHandle X509Certificate::DupOSCertHandle( 1104 OSCertHandle handle) { 1105 if (!handle) 1106 return NULL; 1107 return reinterpret_cast<OSCertHandle>(const_cast<void*>(CFRetain(handle))); 1108} 1109 1110// static 1111void X509Certificate::FreeOSCertHandle(OSCertHandle cert_handle) { 1112 CFRelease(cert_handle); 1113} 1114 1115// static 1116SHA1Fingerprint X509Certificate::CalculateFingerprint( 1117 OSCertHandle cert) { 1118 SHA1Fingerprint sha1; 1119 memset(sha1.data, 0, sizeof(sha1.data)); 1120 1121 CSSM_DATA cert_data; 1122 OSStatus status = SecCertificateGetData(cert, &cert_data); 1123 if (status) 1124 return sha1; 1125 1126 DCHECK(cert_data.Data); 1127 DCHECK_NE(cert_data.Length, 0U); 1128 1129 CC_SHA1(cert_data.Data, cert_data.Length, sha1.data); 1130 1131 return sha1; 1132} 1133 1134bool X509Certificate::SupportsSSLClientAuth() const { 1135 CSSMFields fields; 1136 if (GetCertFields(cert_handle_, &fields) != noErr) 1137 return false; 1138 1139 // Gather the extensions we care about. We do not support 1140 // CSSMOID_NetscapeCertType on OS X. 1141 const CE_ExtendedKeyUsage* ext_key_usage = NULL; 1142 const CE_KeyUsage* key_usage = NULL; 1143 for (unsigned f = 0; f < fields.num_of_fields; ++f) { 1144 const CSSM_FIELD& field = fields.fields[f]; 1145 const CSSM_X509_EXTENSION* ext = 1146 reinterpret_cast<const CSSM_X509_EXTENSION*>(field.FieldValue.Data); 1147 if (CSSMOIDEqual(&field.FieldOid, &CSSMOID_KeyUsage)) { 1148 key_usage = reinterpret_cast<const CE_KeyUsage*>(ext->value.parsedValue); 1149 } else if (CSSMOIDEqual(&field.FieldOid, &CSSMOID_ExtendedKeyUsage)) { 1150 ext_key_usage = 1151 reinterpret_cast<const CE_ExtendedKeyUsage*>(ext->value.parsedValue); 1152 } 1153 } 1154 1155 // RFC5280 says to take the intersection of the two extensions. 1156 // 1157 // Our underlying crypto libraries don't expose 1158 // ClientCertificateType, so for now we will not support fixed 1159 // Diffie-Hellman mechanisms. For rsa_sign, we need the 1160 // digitalSignature bit. 1161 // 1162 // In particular, if a key has the nonRepudiation bit and not the 1163 // digitalSignature one, we will not offer it to the user. 1164 if (key_usage && !((*key_usage) & CE_KU_DigitalSignature)) 1165 return false; 1166 if (ext_key_usage && !ExtendedKeyUsageAllows(ext_key_usage, 1167 &CSSMOID_ClientAuth)) 1168 return false; 1169 return true; 1170} 1171 1172bool X509Certificate::IsIssuedBy( 1173 const std::vector<CertPrincipal>& valid_issuers) { 1174 // Get the cert's issuer chain. 1175 CFArrayRef cert_chain = NULL; 1176 OSStatus result; 1177 result = CopyCertChain(os_cert_handle(), &cert_chain); 1178 if (result) 1179 return false; 1180 ScopedCFTypeRef<CFArrayRef> scoped_cert_chain(cert_chain); 1181 1182 // Check all the certs in the chain for a match. 1183 int n = CFArrayGetCount(cert_chain); 1184 for (int i = 0; i < n; ++i) { 1185 SecCertificateRef cert_handle = reinterpret_cast<SecCertificateRef>( 1186 const_cast<void*>(CFArrayGetValueAtIndex(cert_chain, i))); 1187 scoped_refptr<X509Certificate> cert(X509Certificate::CreateFromHandle( 1188 cert_handle, 1189 X509Certificate::SOURCE_LONE_CERT_IMPORT, 1190 X509Certificate::OSCertHandles())); 1191 for (unsigned j = 0; j < valid_issuers.size(); j++) { 1192 if (cert->issuer().Matches(valid_issuers[j])) 1193 return true; 1194 } 1195 } 1196 return false; 1197} 1198 1199// static 1200OSStatus X509Certificate::CreateSSLClientPolicy(SecPolicyRef* out_policy) { 1201 CSSM_APPLE_TP_SSL_OPTIONS tp_ssl_options = { 1202 CSSM_APPLE_TP_SSL_OPTS_VERSION, 1203 0, 1204 NULL, 1205 CSSM_APPLE_TP_SSL_CLIENT 1206 }; 1207 return CreatePolicy(&CSSMOID_APPLE_TP_SSL, 1208 &tp_ssl_options, 1209 sizeof(tp_ssl_options), 1210 out_policy); 1211} 1212 1213// static 1214bool X509Certificate::GetSSLClientCertificates( 1215 const std::string& server_domain, 1216 const std::vector<CertPrincipal>& valid_issuers, 1217 CertificateList* certs) { 1218 ScopedCFTypeRef<SecIdentityRef> preferred_identity; 1219 if (!server_domain.empty()) { 1220 // See if there's an identity preference for this domain: 1221 ScopedCFTypeRef<CFStringRef> domain_str( 1222 base::SysUTF8ToCFStringRef("https://" + server_domain)); 1223 SecIdentityRef identity = NULL; 1224 // While SecIdentityCopyPreferences appears to take a list of CA issuers 1225 // to restrict the identity search to, within Security.framework the 1226 // argument is ignored and filtering unimplemented. See 1227 // SecIdentity.cpp in libsecurity_keychain, specifically 1228 // _SecIdentityCopyPreferenceMatchingName(). 1229 if (SecIdentityCopyPreference(domain_str, 0, NULL, &identity) == noErr) 1230 preferred_identity.reset(identity); 1231 } 1232 1233 // Now enumerate the identities in the available keychains. 1234 SecIdentitySearchRef search = nil; 1235 OSStatus err = SecIdentitySearchCreate(NULL, CSSM_KEYUSE_SIGN, &search); 1236 ScopedCFTypeRef<SecIdentitySearchRef> scoped_search(search); 1237 while (!err) { 1238 SecIdentityRef identity = NULL; 1239 err = SecIdentitySearchCopyNext(search, &identity); 1240 if (err) 1241 break; 1242 ScopedCFTypeRef<SecIdentityRef> scoped_identity(identity); 1243 1244 SecCertificateRef cert_handle; 1245 err = SecIdentityCopyCertificate(identity, &cert_handle); 1246 if (err != noErr) 1247 continue; 1248 ScopedCFTypeRef<SecCertificateRef> scoped_cert_handle(cert_handle); 1249 1250 scoped_refptr<X509Certificate> cert( 1251 CreateFromHandle(cert_handle, SOURCE_LONE_CERT_IMPORT, 1252 OSCertHandles())); 1253 if (cert->HasExpired() || !cert->SupportsSSLClientAuth()) 1254 continue; 1255 1256 // Skip duplicates (a cert may be in multiple keychains). 1257 const SHA1Fingerprint& fingerprint = cert->fingerprint(); 1258 unsigned i; 1259 for (i = 0; i < certs->size(); ++i) { 1260 if ((*certs)[i]->fingerprint().Equals(fingerprint)) 1261 break; 1262 } 1263 if (i < certs->size()) 1264 continue; 1265 1266 bool is_preferred = preferred_identity && 1267 CFEqual(preferred_identity, identity); 1268 1269 // Make sure the issuer matches valid_issuers, if given. 1270 // But an explicit cert preference overrides this. 1271 if (!is_preferred && 1272 !valid_issuers.empty() && 1273 !cert->IsIssuedBy(valid_issuers)) 1274 continue; 1275 1276 // The cert passes, so add it to the vector. 1277 // If it's the preferred identity, add it at the start (so it'll be 1278 // selected by default in the UI.) 1279 if (is_preferred) 1280 certs->insert(certs->begin(), cert); 1281 else 1282 certs->push_back(cert); 1283 } 1284 1285 if (err != errSecItemNotFound) { 1286 LOG(ERROR) << "SecIdentitySearch error " << err; 1287 return false; 1288 } 1289 return true; 1290} 1291 1292CFArrayRef X509Certificate::CreateClientCertificateChain() const { 1293 // Initialize the result array with just the IdentityRef of the receiver: 1294 OSStatus result; 1295 SecIdentityRef identity; 1296 result = SecIdentityCreateWithCertificate(NULL, cert_handle_, &identity); 1297 if (result) { 1298 LOG(ERROR) << "SecIdentityCreateWithCertificate error " << result; 1299 return NULL; 1300 } 1301 ScopedCFTypeRef<CFMutableArrayRef> chain( 1302 CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks)); 1303 CFArrayAppendValue(chain, identity); 1304 1305 CFArrayRef cert_chain = NULL; 1306 result = CopyCertChain(cert_handle_, &cert_chain); 1307 ScopedCFTypeRef<CFArrayRef> scoped_cert_chain(cert_chain); 1308 if (result) { 1309 LOG(ERROR) << "CreateIdentityCertificateChain error " << result; 1310 return chain.release(); 1311 } 1312 1313 // Append the intermediate certs from SecTrust to the result array: 1314 if (cert_chain) { 1315 int chain_count = CFArrayGetCount(cert_chain); 1316 if (chain_count > 1) { 1317 CFArrayAppendArray(chain, 1318 cert_chain, 1319 CFRangeMake(1, chain_count - 1)); 1320 } 1321 } 1322 1323 return chain.release(); 1324} 1325 1326// static 1327X509Certificate::OSCertHandle 1328X509Certificate::ReadCertHandleFromPickle(const Pickle& pickle, 1329 void** pickle_iter) { 1330 const char* data; 1331 int length; 1332 if (!pickle.ReadData(pickle_iter, &data, &length)) 1333 return NULL; 1334 1335 return CreateOSCertHandleFromBytes(data, length); 1336} 1337 1338// static 1339bool X509Certificate::WriteCertHandleToPickle(OSCertHandle cert_handle, 1340 Pickle* pickle) { 1341 CSSM_DATA cert_data; 1342 OSStatus status = SecCertificateGetData(cert_handle, &cert_data); 1343 if (status) 1344 return false; 1345 1346 return pickle->WriteData(reinterpret_cast<char*>(cert_data.Data), 1347 cert_data.Length); 1348} 1349 1350} // namespace net 1351