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
33 using base::mac::ScopedCFTypeRef;
34 using base::Time;
35
36 namespace net {
37
38 namespace {
39
40 typedef OSStatus (*SecTrustCopyExtendedResultFuncPtr)(SecTrustRef,
41 CFDictionaryRef*);
42
NetErrorFromOSStatus(OSStatus status)43 int 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
CertStatusFromOSStatus(OSStatus status)59 int 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
OverrideHostnameMismatch(const std::string & hostname,std::vector<std::string> * dns_names)108 bool 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
131 struct CSSMFields {
CSSMFieldsnet::__anonc9d927630111::CSSMFields132 CSSMFields() : cl_handle(NULL), num_of_fields(0), fields(NULL) {}
~CSSMFieldsnet::__anonc9d927630111::CSSMFields133 ~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
GetCertFields(X509Certificate::OSCertHandle cert_handle,CSSMFields * fields)143 OSStatus 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
GetCertGeneralNamesForOID(X509Certificate::OSCertHandle cert_handle,CSSM_OID oid,CE_GeneralNameType name_type,std::vector<std::string> * result)164 void 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
GetCertDateForOID(X509Certificate::OSCertHandle cert_handle,CSSM_OID oid,Time * result)205 void 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
GetCertSerialNumber(X509Certificate::OSCertHandle cert_handle)237 std::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.
CreatePolicy(const CSSM_OID * policy_OID,void * option_data,size_t option_length,SecPolicyRef * policy)263 OSStatus 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|.
CreateTrustPolicies(const std::string & hostname,int flags,ScopedCFTypeRef<CFArrayRef> * policies)297 OSStatus 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.
CopyCertChain(SecCertificateRef cert_handle,CFArrayRef * out_cert_chain)374 OSStatus 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.
ExtendedKeyUsageAllows(const CE_ExtendedKeyUsage * usage,const CSSM_OID * purpose)407 bool 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.
IsValidOSCertHandle(SecCertificateRef cert_handle)429 bool 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|.
AddCertificatesFromBytes(const char * data,size_t length,SecExternalFormat format,X509Certificate::OSCertHandles * output)438 void 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
486 struct CSSMOIDString {
487 const CSSM_OID* oid_;
488 std::string string_;
489 };
490
491 typedef std::vector<CSSMOIDString> CSSMOIDStringVector;
492
CERTNameToCSSMOIDVector(CERTName * name,CSSMOIDStringVector * out_values)493 bool 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
547 class ScopedCertName {
548 public:
ScopedCertName(CERTName * name)549 explicit ScopedCertName(CERTName* name) : name_(name) { }
~ScopedCertName()550 ~ScopedCertName() {
551 if (name_) CERT_DestroyName(name_);
552 }
operator CERTName*()553 operator CERTName*() { return name_; }
554
555 private:
556 CERTName* name_;
557 };
558
559 class ScopedEncodedCertResults {
560 public:
ScopedEncodedCertResults(CSSM_TP_RESULT_SET * results)561 explicit ScopedEncodedCertResults(CSSM_TP_RESULT_SET* results)
562 : results_(results) { }
~ScopedEncodedCertResults()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
575 private:
576 CSSM_TP_RESULT_SET* results_;
577 };
578
AppendPublicKeyHashes(CFArrayRef chain,std::vector<SHA1Fingerprint> * hashes)579 void 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
Initialize()603 void 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
IsIssuedByKnownRoot(CFArrayRef chain)625 bool 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
CreateSelfSigned(crypto::RSAPrivateKey * key,const std::string & subject,uint32 serial_number,base::TimeDelta valid_duration)637 X509Certificate* 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
GetDNSNames(std::vector<std::string> * dns_names) const776 void 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
Verify(const std::string & hostname,int flags,CertVerifyResult * verify_result) const786 int 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
GetDEREncoded(std::string * encoded)1024 bool 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
VerifyEV() const1035 bool 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
IsSameOSCert(X509Certificate::OSCertHandle a,X509Certificate::OSCertHandle b)1044 bool 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
CreateOSCertHandleFromBytes(const char * data,int length)1059 X509Certificate::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
CreateOSCertHandlesFromBytes(const char * data,int length,Format format)1080 X509Certificate::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
DupOSCertHandle(OSCertHandle handle)1103 X509Certificate::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
FreeOSCertHandle(OSCertHandle cert_handle)1111 void X509Certificate::FreeOSCertHandle(OSCertHandle cert_handle) {
1112 CFRelease(cert_handle);
1113 }
1114
1115 // static
CalculateFingerprint(OSCertHandle cert)1116 SHA1Fingerprint 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
SupportsSSLClientAuth() const1134 bool 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
IsIssuedBy(const std::vector<CertPrincipal> & valid_issuers)1172 bool 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
CreateSSLClientPolicy(SecPolicyRef * out_policy)1200 OSStatus 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
GetSSLClientCertificates(const std::string & server_domain,const std::vector<CertPrincipal> & valid_issuers,CertificateList * certs)1214 bool 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
CreateClientCertificateChain() const1292 CFArrayRef 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
1327 X509Certificate::OSCertHandle
ReadCertHandleFromPickle(const Pickle & pickle,void ** pickle_iter)1328 X509Certificate::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
WriteCertHandleToPickle(OSCertHandle cert_handle,Pickle * pickle)1339 bool 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