1/* 2 * Copyright (c) 2002-2014 Apple Inc. All Rights Reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. Please obtain a copy of the License at 10 * http://www.opensource.apple.com/apsl/ and read it before using this 11 * file. 12 * 13 * The Original Code and all software distributed under the License are 14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 * Please see the License for the specific language governing rights and 19 * limitations under the License. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 23 24#include <CoreFoundation/CFString.h> 25#include <CoreFoundation/CFNumber.h> 26#include <CoreFoundation/CFArray.h> 27#include <Security/SecItem.h> 28#include <Security/SecPolicy.h> 29#include <Security/SecPolicyPriv.h> 30#include <Security/SecCertificate.h> 31#include <Security/SecCertificatePriv.h> 32#include <security_keychain/Policies.h> 33#include <security_keychain/PolicyCursor.h> 34#include "SecBridge.h" 35#include "utilities/SecCFRelease.h" 36 37 38// String constant declarations 39 40#define SEC_CONST_DECL(k,v) CFTypeRef k = (CFTypeRef)(CFSTR(v)); 41 42SEC_CONST_DECL (kSecPolicyAppleX509Basic, "1.2.840.113635.100.1.2"); 43SEC_CONST_DECL (kSecPolicyAppleSSL, "1.2.840.113635.100.1.3"); 44SEC_CONST_DECL (kSecPolicyAppleSMIME, "1.2.840.113635.100.1.8"); 45SEC_CONST_DECL (kSecPolicyAppleEAP, "1.2.840.113635.100.1.9"); 46SEC_CONST_DECL (kSecPolicyAppleIPsec, "1.2.840.113635.100.1.11"); 47SEC_CONST_DECL (kSecPolicyAppleiChat, "1.2.840.113635.100.1.12"); 48SEC_CONST_DECL (kSecPolicyApplePKINITClient, "1.2.840.113635.100.1.14"); 49SEC_CONST_DECL (kSecPolicyApplePKINITServer, "1.2.840.113635.100.1.15"); 50SEC_CONST_DECL (kSecPolicyAppleCodeSigning, "1.2.840.113635.100.1.16"); 51SEC_CONST_DECL (kSecPolicyApplePackageSigning, "1.2.840.113635.100.1.17"); 52SEC_CONST_DECL (kSecPolicyAppleIDValidation, "1.2.840.113635.100.1.18"); 53SEC_CONST_DECL (kSecPolicyMacAppStoreReceipt, "1.2.840.113635.100.1.19"); 54SEC_CONST_DECL (kSecPolicyAppleTimeStamping, "1.2.840.113635.100.1.20"); 55SEC_CONST_DECL (kSecPolicyAppleRevocation, "1.2.840.113635.100.1.21"); 56SEC_CONST_DECL (kSecPolicyApplePassbookSigning, "1.2.840.113635.100.1.22"); 57SEC_CONST_DECL (kSecPolicyAppleMobileStore, "1.2.840.113635.100.1.23"); 58SEC_CONST_DECL (kSecPolicyAppleEscrowService, "1.2.840.113635.100.1.24"); 59SEC_CONST_DECL (kSecPolicyAppleProfileSigner, "1.2.840.113635.100.1.25"); 60SEC_CONST_DECL (kSecPolicyAppleQAProfileSigner, "1.2.840.113635.100.1.26"); 61SEC_CONST_DECL (kSecPolicyAppleTestMobileStore, "1.2.840.113635.100.1.27"); 62#if TARGET_OS_IPHONE 63SEC_CONST_DECL (kSecPolicyAppleOTAPKISigner, "1.2.840.113635.100.1.28"); 64SEC_CONST_DECL (kSecPolicyAppleTestOTAPKISigner, "1.2.840.113635.100.1.29"); 65/* FIXME: this policy name should be deprecated and replaced with "kSecPolicyAppleIDValidationRecordSigning" */ 66SEC_CONST_DECL (kSecPolicyAppleIDValidationRecordSigningPolicy, "1.2.840.113625.100.1.30"); 67SEC_CONST_DECL (kSecPolicyAppleSMPEncryption, "1.2.840.113625.100.1.31"); 68SEC_CONST_DECL (kSecPolicyAppleTestSMPEncryption, "1.2.840.113625.100.1.32"); 69#endif 70SEC_CONST_DECL (kSecPolicyAppleServerAuthentication, "1.2.840.113635.100.1.33"); 71SEC_CONST_DECL (kSecPolicyApplePCSEscrowService, "1.2.840.113635.100.1.34"); 72 73SEC_CONST_DECL (kSecPolicyOid, "SecPolicyOid"); 74SEC_CONST_DECL (kSecPolicyName, "SecPolicyName"); 75SEC_CONST_DECL (kSecPolicyClient, "SecPolicyClient"); 76SEC_CONST_DECL (kSecPolicyRevocationFlags, "SecPolicyRevocationFlags"); 77SEC_CONST_DECL (kSecPolicyTeamIdentifier, "SecPolicyTeamIdentifier"); 78 79SEC_CONST_DECL (kSecPolicyKU_DigitalSignature, "CE_KU_DigitalSignature"); 80SEC_CONST_DECL (kSecPolicyKU_NonRepudiation, "CE_KU_NonRepudiation"); 81SEC_CONST_DECL (kSecPolicyKU_KeyEncipherment, "CE_KU_KeyEncipherment"); 82SEC_CONST_DECL (kSecPolicyKU_DataEncipherment, "CE_KU_DataEncipherment"); 83SEC_CONST_DECL (kSecPolicyKU_KeyAgreement, "CE_KU_KeyAgreement"); 84SEC_CONST_DECL (kSecPolicyKU_KeyCertSign, "CE_KU_KeyCertSign"); 85SEC_CONST_DECL (kSecPolicyKU_CRLSign, "CE_KU_CRLSign"); 86SEC_CONST_DECL (kSecPolicyKU_EncipherOnly, "CE_KU_EncipherOnly"); 87SEC_CONST_DECL (kSecPolicyKU_DecipherOnly, "CE_KU_DecipherOnly"); 88 89// Private functions 90 91SecPolicyRef SecPolicyCreateWithSecAsn1Oid(SecAsn1Oid *oidPtr); 92extern "C" { CFArrayRef SecPolicyCopyEscrowRootCertificates(void); } 93 94// 95// CF boilerplate 96// 97CFTypeID 98SecPolicyGetTypeID(void) 99{ 100 BEGIN_SECAPI 101 return gTypes().Policy.typeID; 102 END_SECAPI1(_kCFRuntimeNotATypeID) 103} 104 105 106// 107// Sec API bridge functions 108// 109OSStatus 110SecPolicyGetOID(SecPolicyRef policyRef, CSSM_OID* oid) 111{ 112 BEGIN_SECAPI 113 Required(oid) = Policy::required(policyRef)->oid(); 114 END_SECAPI 115} 116 117OSStatus 118SecPolicyGetValue(SecPolicyRef policyRef, CSSM_DATA* value) 119{ 120 BEGIN_SECAPI 121 Required(value) = Policy::required(policyRef)->value(); 122 END_SECAPI 123} 124 125CFDictionaryRef 126SecPolicyCopyProperties(SecPolicyRef policyRef) 127{ 128 /* can't use SECAPI macros, since this function does not return OSStatus */ 129 CFDictionaryRef result = NULL; 130 try { 131 result = Policy::required(policyRef)->properties(); 132 } 133 catch (...) { 134 if (result) { 135 CFRelease(result); 136 result = NULL; 137 } 138 }; 139 return result; 140} 141 142OSStatus 143SecPolicySetValue(SecPolicyRef policyRef, const CSSM_DATA *value) 144{ 145 BEGIN_SECAPI 146 Required(value); 147 const CssmData newValue(value->Data, value->Length); 148 Policy::required(policyRef)->setValue(newValue); 149 END_SECAPI 150} 151 152OSStatus 153SecPolicySetProperties(SecPolicyRef policyRef, CFDictionaryRef properties) 154{ 155 BEGIN_SECAPI 156 Policy::required(policyRef)->setProperties(properties); 157 END_SECAPI 158} 159 160OSStatus 161SecPolicyGetTPHandle(SecPolicyRef policyRef, CSSM_TP_HANDLE* tpHandle) 162{ 163 BEGIN_SECAPI 164 Required(tpHandle) = Policy::required(policyRef)->tp()->handle(); 165 END_SECAPI 166} 167 168OSStatus 169SecPolicyCopyAll(CSSM_CERT_TYPE certificateType, CFArrayRef* policies) 170{ 171 BEGIN_SECAPI 172 Required(policies); 173 CFMutableArrayRef currPolicies = NULL; 174 currPolicies = CFArrayCreateMutable(NULL, 0, NULL); 175 if ( currPolicies ) 176 { 177 SecPointer<PolicyCursor> cursor(new PolicyCursor(NULL, NULL)); 178 SecPointer<Policy> policy; 179 while ( cursor->next(policy) ) /* copies the next policy */ 180 { 181 CFArrayAppendValue(currPolicies, policy->handle()); /* 'SecPolicyRef' appended */ 182 CFRelease(policy->handle()); /* refcount bumped up when appended to array */ 183 } 184 *policies = CFArrayCreateCopy(NULL, currPolicies); 185 CFRelease(currPolicies); 186 CFRelease(cursor->handle()); 187 } 188 END_SECAPI 189} 190 191OSStatus 192SecPolicyCopy(CSSM_CERT_TYPE certificateType, const CSSM_OID *policyOID, SecPolicyRef* policy) 193{ 194 Required(policy); 195 Required(policyOID); 196 197 SecPolicySearchRef srchRef = NULL; 198 OSStatus ortn; 199 200 ortn = SecPolicySearchCreate(certificateType, policyOID, NULL, &srchRef); 201 if(ortn) { 202 return ortn; 203 } 204 ortn = SecPolicySearchCopyNext(srchRef, policy); 205 CFRelease(srchRef); 206 return ortn; 207} 208 209/* new in 10.6 */ 210SecPolicyRef 211SecPolicyCreateBasicX509(void) 212{ 213 // return a SecPolicyRef object for the X.509 Basic policy 214 SecPolicyRef policy = nil; 215 SecPolicySearchRef policySearch = nil; 216 OSStatus status = SecPolicySearchCreate(CSSM_CERT_X_509v3, &CSSMOID_APPLE_X509_BASIC, NULL, &policySearch); 217 if (!status) { 218 status = SecPolicySearchCopyNext(policySearch, &policy); 219 } 220 if (policySearch) { 221 CFRelease(policySearch); 222 } 223 return policy; 224} 225 226/* new in 10.6 */ 227SecPolicyRef 228SecPolicyCreateSSL(Boolean server, CFStringRef hostname) 229{ 230 // return a SecPolicyRef object for the SSL policy, given hostname and client options 231 SecPolicyRef policy = nil; 232 SecPolicySearchRef policySearch = nil; 233 OSStatus status = SecPolicySearchCreate(CSSM_CERT_X_509v3, &CSSMOID_APPLE_TP_SSL, NULL, &policySearch); 234 if (!status) { 235 status = SecPolicySearchCopyNext(policySearch, &policy); 236 } 237 if (!status && policy) { 238 // set options for client-side or server-side policy evaluation 239 char *strbuf = NULL; 240 const char *hostnamestr = NULL; 241 if (hostname) { 242 hostnamestr = CFStringGetCStringPtr(hostname, kCFStringEncodingUTF8); 243 if (hostnamestr == NULL) { 244 CFIndex maxLen = CFStringGetMaximumSizeForEncoding(CFStringGetLength(hostname), kCFStringEncodingUTF8) + 1; 245 strbuf = (char *)malloc(maxLen); 246 if (CFStringGetCString(hostname, strbuf, maxLen, kCFStringEncodingUTF8)) { 247 hostnamestr = strbuf; 248 } 249 } 250 } 251 uint32 hostnamelen = (hostnamestr) ? (uint32)strlen(hostnamestr) : 0; 252 uint32 flags = (!server) ? CSSM_APPLE_TP_SSL_CLIENT : 0; 253 CSSM_APPLE_TP_SSL_OPTIONS opts = {CSSM_APPLE_TP_SSL_OPTS_VERSION, hostnamelen, hostnamestr, flags}; 254 CSSM_DATA data = {sizeof(opts), (uint8*)&opts}; 255 SecPolicySetValue(policy, &data); 256 257 if (strbuf) { 258 free(strbuf); 259 } 260 } 261 if (policySearch) { 262 CFRelease(policySearch); 263 } 264 return policy; 265} 266 267SecPolicyRef 268SecPolicyCreateWithSecAsn1Oid(SecAsn1Oid *oidPtr) 269{ 270 SecPolicyRef policy = NULL; 271 try { 272 SecPointer<Policy> policyObj; 273 PolicyCursor::policy(oidPtr, policyObj); 274 policy = policyObj->handle(); 275 } 276 catch (...) {} 277 278 return policy; 279} 280 281/* new in 10.7 */ 282SecPolicyRef 283SecPolicyCreateWithOID(CFTypeRef policyOID) 284{ 285 // for now, we only accept the policy constants that are defined in SecPolicy.h 286 CFStringRef oidStr = (CFStringRef)policyOID; 287 CSSM_OID *oidPtr = NULL; 288 SecPolicyRef policy = NULL; 289 if (!oidStr) { 290 return policy; 291 } 292 struct oidmap_entry_t { 293 const CFTypeRef oidstr; 294 const SecAsn1Oid *oidptr; 295 }; 296 const oidmap_entry_t oidmap[] = { 297 { kSecPolicyAppleX509Basic, &CSSMOID_APPLE_X509_BASIC }, 298 { kSecPolicyAppleSSL, &CSSMOID_APPLE_TP_SSL }, 299 { kSecPolicyAppleSMIME, &CSSMOID_APPLE_TP_SMIME }, 300 { kSecPolicyAppleEAP, &CSSMOID_APPLE_TP_EAP }, 301 { kSecPolicyAppleIPsec, &CSSMOID_APPLE_TP_IP_SEC }, 302 { kSecPolicyAppleiChat, &CSSMOID_APPLE_TP_ICHAT }, 303 { kSecPolicyApplePKINITClient, &CSSMOID_APPLE_TP_PKINIT_CLIENT }, 304 { kSecPolicyApplePKINITServer, &CSSMOID_APPLE_TP_PKINIT_SERVER }, 305 { kSecPolicyAppleCodeSigning, &CSSMOID_APPLE_TP_CODE_SIGNING }, 306 { kSecPolicyMacAppStoreReceipt, &CSSMOID_APPLE_TP_MACAPPSTORE_RECEIPT }, 307 { kSecPolicyAppleIDValidation, &CSSMOID_APPLE_TP_APPLEID_SHARING }, 308 { kSecPolicyAppleTimeStamping, &CSSMOID_APPLE_TP_TIMESTAMPING }, 309 { kSecPolicyAppleRevocation, &CSSMOID_APPLE_TP_REVOCATION }, 310 { kSecPolicyApplePassbookSigning, &CSSMOID_APPLE_TP_PASSBOOK_SIGNING }, 311 { kSecPolicyAppleMobileStore, &CSSMOID_APPLE_TP_MOBILE_STORE }, 312 { kSecPolicyAppleEscrowService, &CSSMOID_APPLE_TP_ESCROW_SERVICE }, 313 { kSecPolicyAppleProfileSigner, &CSSMOID_APPLE_TP_PROFILE_SIGNING }, 314 { kSecPolicyAppleQAProfileSigner, &CSSMOID_APPLE_TP_QA_PROFILE_SIGNING }, 315 { kSecPolicyAppleTestMobileStore, &CSSMOID_APPLE_TP_TEST_MOBILE_STORE }, 316 { kSecPolicyApplePCSEscrowService, &CSSMOID_APPLE_TP_PCS_ESCROW_SERVICE }, 317 }; 318 unsigned int i, oidmaplen = sizeof(oidmap) / sizeof(oidmap_entry_t); 319 for (i=0; i<oidmaplen; i++) { 320 CFStringRef str = (CFStringRef) oidmap[i].oidstr; 321 if (CFStringCompare(str, oidStr, 0) == kCFCompareEqualTo) { 322 oidPtr = (CSSM_OID*)oidmap[i].oidptr; 323 break; 324 } 325 } 326 if (CFEqual(oidStr, kSecPolicyAppleServerAuthentication)) { 327 return SecPolicyCreateAppleSSLService(NULL); 328 } 329 if (oidPtr) { 330 SecPolicySearchRef policySearch = NULL; 331 OSStatus status = SecPolicySearchCreate(CSSM_CERT_X_509v3, oidPtr, NULL, &policySearch); 332 if (!status && policySearch) { 333 status = SecPolicySearchCopyNext(policySearch, &policy); 334 CFRelease(policySearch); 335 } 336 if (!policy && CFEqual(policyOID, kSecPolicyAppleRevocation)) { 337 policy = SecPolicyCreateRevocation(kSecRevocationUseAnyAvailableMethod); 338 } 339 if (!policy) { 340 policy = SecPolicyCreateWithSecAsn1Oid((SecAsn1Oid*)oidPtr); 341 } 342 } 343 return policy; 344} 345 346/* new in 10.9 */ 347SecPolicyRef 348SecPolicyCreateWithProperties(CFTypeRef policyIdentifier, CFDictionaryRef properties) 349{ 350 SecPolicyRef policy = SecPolicyCreateWithOID(policyIdentifier); 351 SecPolicySetProperties(policy, properties); 352 353 return policy; 354} 355 356/* new in 10.9 */ 357SecPolicyRef 358SecPolicyCreateRevocation(CFOptionFlags revocationFlags) 359{ 360 // return a SecPolicyRef object for the unified revocation policy 361 SecAsn1Oid *oidPtr = (SecAsn1Oid*)&CSSMOID_APPLE_TP_REVOCATION; 362 SecPolicyRef policy = SecPolicyCreateWithSecAsn1Oid(oidPtr); 363 if (policy) { 364 CSSM_DATA policyData = { (CSSM_SIZE)sizeof(CFOptionFlags), (uint8*)&revocationFlags }; 365 SecPolicySetValue(policy, &policyData); 366 } 367 return policy; 368} 369 370/* new in 10.9 ***FIXME*** TO BE REMOVED */ 371CFArrayRef SecPolicyCopyEscrowRootCertificates(void) 372{ 373 return SecCertificateCopyEscrowRoots(kSecCertificateProductionEscrowRoot); 374} 375 376SecPolicyRef SecPolicyCreateAppleIDSService(CFStringRef hostname) 377{ 378 return SecPolicyCreateSSL(true, hostname); 379} 380 381SecPolicyRef SecPolicyCreateApplePushService(CFStringRef hostname) 382{ 383 return SecPolicyCreateSSL(true, hostname); 384} 385 386SecPolicyRef SecPolicyCreateAppleMMCSService(CFStringRef hostname) 387{ 388 return SecPolicyCreateSSL(true, hostname); 389} 390 391SecPolicyRef SecPolicyCreateAppleSSLService(CFStringRef hostname) 392{ 393 // SSL server, pinned to an Apple intermediate 394 SecPolicyRef policy = SecPolicyCreateSSL(true, hostname); 395 if (policy) { 396 // change options for policy evaluation 397 char *strbuf = NULL; 398 const char *hostnamestr = NULL; 399 if (hostname) { 400 hostnamestr = CFStringGetCStringPtr(hostname, kCFStringEncodingUTF8); 401 if (hostnamestr == NULL) { 402 CFIndex maxLen = CFStringGetMaximumSizeForEncoding(CFStringGetLength(hostname), kCFStringEncodingUTF8) + 1; 403 strbuf = (char *)malloc(maxLen); 404 if (CFStringGetCString(hostname, strbuf, maxLen, kCFStringEncodingUTF8)) { 405 hostnamestr = strbuf; 406 } 407 } 408 } 409 uint32 hostnamelen = (hostnamestr) ? (uint32)strlen(hostnamestr) : 0; 410 uint32 flags = 0x00000002; // 2nd-lowest bit set to require Apple intermediate pin 411 CSSM_APPLE_TP_SSL_OPTIONS opts = {CSSM_APPLE_TP_SSL_OPTS_VERSION, hostnamelen, hostnamestr, flags}; 412 CSSM_DATA data = {sizeof(opts), (uint8*)&opts}; 413 SecPolicySetValue(policy, &data); 414 } 415 return policy; 416} 417#include <security_utilities/cfutilities.h> 418/* New in 10.10 */ 419// Takes the "context" policies to extract the revocation and apply it to timeStamp. 420CFArrayRef 421SecPolicyCreateAppleTimeStampingAndRevocationPolicies(CFTypeRef policyOrArray) 422{ 423 /* can't use SECAPI macros, since this function does not return OSStatus */ 424 CFArrayRef resultPolicyArray=NULL; 425 try { 426 // Set default policy 427 CFRef<CFArrayRef> policyArray = cfArrayize(policyOrArray); 428 CFRef<SecPolicyRef> defaultPolicy = SecPolicyCreateWithOID(kSecPolicyAppleTimeStamping); 429 CFRef<CFMutableArrayRef> appleTimeStampingPolicies = makeCFMutableArray(1,defaultPolicy.get()); 430 431 // Parse the policy and add revocation related ones 432 CFIndex numPolicies = CFArrayGetCount(policyArray); 433 for(CFIndex dex=0; dex<numPolicies; dex++) { 434 SecPolicyRef secPol = (SecPolicyRef)CFArrayGetValueAtIndex(policyArray, dex); 435 SecPointer<Policy> pol = Policy::required(SecPolicyRef(secPol)); 436 const CssmOid &oid = pol->oid(); 437 if ((oid == CssmOid::overlay(CSSMOID_APPLE_TP_REVOCATION)) 438 || (oid == CssmOid::overlay(CSSMOID_APPLE_TP_REVOCATION_CRL)) 439 || (oid == CssmOid::overlay(CSSMOID_APPLE_TP_REVOCATION_OCSP))) 440 { 441 CFArrayAppendValue(appleTimeStampingPolicies, secPol); 442 } 443 } 444 // Transfer of ownership 445 resultPolicyArray=appleTimeStampingPolicies.yield(); 446 } 447 catch (...) { 448 CFReleaseNull(resultPolicyArray); 449 }; 450 return resultPolicyArray; 451} 452 453 454