1/*
2 * Copyright (c) 2002-2013 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
36
37// String constant declarations
38
39#define SEC_CONST_DECL(k,v) CFTypeRef k = (CFTypeRef)(CFSTR(v));
40
41SEC_CONST_DECL (kSecPolicyAppleX509Basic, "1.2.840.113635.100.1.2");
42SEC_CONST_DECL (kSecPolicyAppleSSL, "1.2.840.113635.100.1.3");
43SEC_CONST_DECL (kSecPolicyAppleSMIME, "1.2.840.113635.100.1.8");
44SEC_CONST_DECL (kSecPolicyAppleEAP, "1.2.840.113635.100.1.9");
45SEC_CONST_DECL (kSecPolicyAppleIPsec, "1.2.840.113635.100.1.11");
46SEC_CONST_DECL (kSecPolicyAppleiChat, "1.2.840.113635.100.1.12");
47SEC_CONST_DECL (kSecPolicyApplePKINITClient, "1.2.840.113635.100.1.14");
48SEC_CONST_DECL (kSecPolicyApplePKINITServer, "1.2.840.113635.100.1.15");
49SEC_CONST_DECL (kSecPolicyAppleCodeSigning, "1.2.840.113635.100.1.16");
50SEC_CONST_DECL (kSecPolicyApplePackageSigning, "1.2.840.113635.100.1.17");
51SEC_CONST_DECL (kSecPolicyAppleIDValidation, "1.2.840.113635.100.1.18");
52SEC_CONST_DECL (kSecPolicyMacAppStoreReceipt, "1.2.840.113635.100.1.19");
53SEC_CONST_DECL (kSecPolicyAppleTimeStamping, "1.2.840.113635.100.1.20");
54SEC_CONST_DECL (kSecPolicyAppleRevocation, "1.2.840.113635.100.1.21");
55SEC_CONST_DECL (kSecPolicyApplePassbookSigning, "1.2.840.113635.100.1.22");
56SEC_CONST_DECL (kSecPolicyAppleMobileStore, "1.2.840.113635.100.1.23");
57SEC_CONST_DECL (kSecPolicyAppleEscrowService, "1.2.840.113635.100.1.24");
58SEC_CONST_DECL (kSecPolicyAppleProfileSigner, "1.2.840.113635.100.1.25");
59SEC_CONST_DECL (kSecPolicyAppleQAProfileSigner, "1.2.840.113635.100.1.26");
60SEC_CONST_DECL (kSecPolicyAppleTestMobileStore, "1.2.840.113635.100.1.27");
61
62
63SEC_CONST_DECL (kSecPolicyOid, "SecPolicyOid");
64SEC_CONST_DECL (kSecPolicyName, "SecPolicyName");
65SEC_CONST_DECL (kSecPolicyClient, "SecPolicyClient");
66SEC_CONST_DECL (kSecPolicyRevocationFlags, "SecPolicyRevocationFlags");
67SEC_CONST_DECL (kSecPolicyTeamIdentifier, "SecPolicyTeamIdentifier");
68
69SEC_CONST_DECL (kSecPolicyKU_DigitalSignature, "CE_KU_DigitalSignature");
70SEC_CONST_DECL (kSecPolicyKU_NonRepudiation, "CE_KU_NonRepudiation");
71SEC_CONST_DECL (kSecPolicyKU_KeyEncipherment, "CE_KU_KeyEncipherment");
72SEC_CONST_DECL (kSecPolicyKU_DataEncipherment, "CE_KU_DataEncipherment");
73SEC_CONST_DECL (kSecPolicyKU_KeyAgreement, "CE_KU_KeyAgreement");
74SEC_CONST_DECL (kSecPolicyKU_KeyCertSign, "CE_KU_KeyCertSign");
75SEC_CONST_DECL (kSecPolicyKU_CRLSign, "CE_KU_CRLSign");
76SEC_CONST_DECL (kSecPolicyKU_EncipherOnly, "CE_KU_EncipherOnly");
77SEC_CONST_DECL (kSecPolicyKU_DecipherOnly, "CE_KU_DecipherOnly");
78
79// Private functions
80
81SecPolicyRef SecPolicyCreateWithSecAsn1Oid(SecAsn1Oid *oidPtr);
82extern "C" { CFArrayRef SecPolicyCopyEscrowRootCertificates(void); }
83
84//
85// CF boilerplate
86//
87CFTypeID
88SecPolicyGetTypeID(void)
89{
90	BEGIN_SECAPI
91	return gTypes().Policy.typeID;
92	END_SECAPI1(_kCFRuntimeNotATypeID)
93}
94
95
96//
97// Sec API bridge functions
98//
99OSStatus
100SecPolicyGetOID(SecPolicyRef policyRef, CSSM_OID* oid)
101{
102	BEGIN_SECAPI
103	Required(oid) = Policy::required(policyRef)->oid();
104	END_SECAPI
105}
106
107OSStatus
108SecPolicyGetValue(SecPolicyRef policyRef, CSSM_DATA* value)
109{
110	BEGIN_SECAPI
111	Required(value) = Policy::required(policyRef)->value();
112	END_SECAPI
113}
114
115CFDictionaryRef
116SecPolicyCopyProperties(SecPolicyRef policyRef)
117{
118	/* can't use SECAPI macros, since this function does not return OSStatus */
119	CFDictionaryRef result = NULL;
120	try {
121		result = Policy::required(policyRef)->properties();
122	}
123	catch (...) {
124		if (result) {
125			CFRelease(result);
126			result = NULL;
127		}
128	};
129	return result;
130}
131
132OSStatus
133SecPolicySetValue(SecPolicyRef policyRef, const CSSM_DATA *value)
134{
135	BEGIN_SECAPI
136	Required(value);
137	const CssmData newValue(value->Data, value->Length);
138	Policy::required(policyRef)->setValue(newValue);
139	END_SECAPI
140}
141
142OSStatus
143SecPolicySetProperties(SecPolicyRef policyRef, CFDictionaryRef properties)
144{
145	BEGIN_SECAPI
146	Policy::required(policyRef)->setProperties(properties);
147	END_SECAPI
148}
149
150OSStatus
151SecPolicyGetTPHandle(SecPolicyRef policyRef, CSSM_TP_HANDLE* tpHandle)
152{
153	BEGIN_SECAPI
154	Required(tpHandle) = Policy::required(policyRef)->tp()->handle();
155	END_SECAPI
156}
157
158OSStatus
159SecPolicyCopyAll(CSSM_CERT_TYPE certificateType, CFArrayRef* policies)
160{
161	BEGIN_SECAPI
162	Required(policies);
163	CFMutableArrayRef currPolicies = NULL;
164	currPolicies = CFArrayCreateMutable(NULL, 0, NULL);
165	if ( currPolicies )
166	{
167		SecPointer<PolicyCursor> cursor(new PolicyCursor(NULL, NULL));
168		SecPointer<Policy> policy;
169		while ( cursor->next(policy) ) /* copies the next policy */
170		{
171			CFArrayAppendValue(currPolicies, policy->handle());  /* 'SecPolicyRef' appended */
172			CFRelease(policy->handle()); /* refcount bumped up when appended to array */
173		}
174		*policies = CFArrayCreateCopy(NULL, currPolicies);
175		CFRelease(currPolicies);
176		CFRelease(cursor->handle());
177	}
178	END_SECAPI
179}
180
181OSStatus
182SecPolicyCopy(CSSM_CERT_TYPE certificateType, const CSSM_OID *policyOID, SecPolicyRef* policy)
183{
184	Required(policy);
185	Required(policyOID);
186
187	SecPolicySearchRef srchRef = NULL;
188	OSStatus ortn;
189
190	ortn = SecPolicySearchCreate(certificateType, policyOID, NULL, &srchRef);
191	if(ortn) {
192		return ortn;
193	}
194	ortn = SecPolicySearchCopyNext(srchRef, policy);
195	CFRelease(srchRef);
196	return ortn;
197}
198
199/* new in 10.6 */
200SecPolicyRef
201SecPolicyCreateBasicX509(void)
202{
203	// return a SecPolicyRef object for the X.509 Basic policy
204	SecPolicyRef policy = nil;
205	SecPolicySearchRef policySearch = nil;
206	OSStatus status = SecPolicySearchCreate(CSSM_CERT_X_509v3, &CSSMOID_APPLE_X509_BASIC, NULL, &policySearch);
207	if (!status) {
208		status = SecPolicySearchCopyNext(policySearch, &policy);
209	}
210	if (policySearch) {
211		CFRelease(policySearch);
212	}
213	return policy;
214}
215
216/* new in 10.6 */
217SecPolicyRef
218SecPolicyCreateSSL(Boolean server, CFStringRef hostname)
219{
220	// return a SecPolicyRef object for the SSL policy, given hostname and client options
221	SecPolicyRef policy = nil;
222	SecPolicySearchRef policySearch = nil;
223	OSStatus status = SecPolicySearchCreate(CSSM_CERT_X_509v3, &CSSMOID_APPLE_TP_SSL, NULL, &policySearch);
224	if (!status) {
225		status = SecPolicySearchCopyNext(policySearch, &policy);
226	}
227	if (!status && policy) {
228		// set options for client-side or server-side policy evaluation
229		char *strbuf = NULL;
230		const char *hostnamestr = NULL;
231		if (hostname) {
232			hostnamestr = CFStringGetCStringPtr(hostname, kCFStringEncodingUTF8);
233			if (hostnamestr == NULL) {
234                CFIndex maxLen = CFStringGetMaximumSizeForEncoding(CFStringGetLength(hostname), kCFStringEncodingUTF8) + 1;
235				strbuf = (char *)malloc(maxLen);
236				if (CFStringGetCString(hostname, strbuf, maxLen, kCFStringEncodingUTF8)) {
237					hostnamestr = strbuf;
238				}
239			}
240		}
241        uint32 hostnamelen = (hostnamestr) ? (uint32)strlen(hostnamestr) : 0;
242        uint32 flags = (!server) ? CSSM_APPLE_TP_SSL_CLIENT : 0;
243        CSSM_APPLE_TP_SSL_OPTIONS opts = {CSSM_APPLE_TP_SSL_OPTS_VERSION, hostnamelen, hostnamestr, flags};
244        CSSM_DATA data = {sizeof(opts), (uint8*)&opts};
245        SecPolicySetValue(policy, &data);
246
247		if (strbuf) {
248			free(strbuf);
249		}
250    }
251	if (policySearch) {
252		CFRelease(policySearch);
253	}
254	return policy;
255}
256
257SecPolicyRef
258SecPolicyCreateWithSecAsn1Oid(SecAsn1Oid *oidPtr)
259{
260	SecPolicyRef policy = NULL;
261	try {
262		SecPointer<Policy> policyObj;
263		PolicyCursor::policy(oidPtr, policyObj);
264		policy = policyObj->handle();
265	}
266	catch (...) {}
267
268	return policy;
269}
270
271/* new in 10.7 */
272SecPolicyRef
273SecPolicyCreateWithOID(CFTypeRef policyOID)
274{
275	// for now, we only accept the policy constants that are defined in SecPolicy.h
276	CFStringRef oidStr = (CFStringRef)policyOID;
277	CSSM_OID *oidPtr = NULL;
278	SecPolicyRef policy = NULL;
279	struct oidmap_entry_t {
280		const CFTypeRef oidstr;
281		const SecAsn1Oid *oidptr;
282	};
283	const oidmap_entry_t oidmap[] = {
284		{ kSecPolicyAppleX509Basic, &CSSMOID_APPLE_X509_BASIC },
285		{ kSecPolicyAppleSSL, &CSSMOID_APPLE_TP_SSL },
286		{ kSecPolicyAppleSMIME, &CSSMOID_APPLE_TP_SMIME },
287		{ kSecPolicyAppleEAP, &CSSMOID_APPLE_TP_EAP },
288		{ kSecPolicyAppleIPsec, &CSSMOID_APPLE_TP_IP_SEC },
289		{ kSecPolicyAppleiChat, &CSSMOID_APPLE_TP_ICHAT },
290		{ kSecPolicyApplePKINITClient, &CSSMOID_APPLE_TP_PKINIT_CLIENT },
291		{ kSecPolicyApplePKINITServer, &CSSMOID_APPLE_TP_PKINIT_SERVER },
292		{ kSecPolicyAppleCodeSigning, &CSSMOID_APPLE_TP_CODE_SIGNING },
293		{ kSecPolicyMacAppStoreReceipt, &CSSMOID_APPLE_TP_MACAPPSTORE_RECEIPT },
294		{ kSecPolicyAppleIDValidation, &CSSMOID_APPLE_TP_APPLEID_SHARING },
295		{ kSecPolicyAppleTimeStamping, &CSSMOID_APPLE_TP_TIMESTAMPING },
296		{ kSecPolicyAppleRevocation, &CSSMOID_APPLE_TP_REVOCATION },
297		{ kSecPolicyApplePassbookSigning, &CSSMOID_APPLE_TP_PASSBOOK_SIGNING },
298		{ kSecPolicyAppleMobileStore, &CSSMOID_APPLE_TP_MOBILE_STORE },
299		{ kSecPolicyAppleEscrowService, &CSSMOID_APPLE_TP_ESCROW_SERVICE },
300		{ kSecPolicyAppleProfileSigner, &CSSMOID_APPLE_TP_PROFILE_SIGNING },
301		{ kSecPolicyAppleQAProfileSigner, &CSSMOID_APPLE_TP_QA_PROFILE_SIGNING },
302		{ kSecPolicyAppleTestMobileStore, &CSSMOID_APPLE_TP_TEST_MOBILE_STORE },
303	};
304	unsigned int i, oidmaplen = sizeof(oidmap) / sizeof(oidmap_entry_t);
305	for (i=0; i<oidmaplen; i++) {
306		CFStringRef str = (CFStringRef) oidmap[i].oidstr;
307		if (CFStringCompare(str, oidStr, 0) == kCFCompareEqualTo) {
308			oidPtr = (CSSM_OID*)oidmap[i].oidptr;
309			break;
310		}
311	}
312	if (oidPtr) {
313		SecPolicySearchRef policySearch = NULL;
314		OSStatus status = SecPolicySearchCreate(CSSM_CERT_X_509v3, oidPtr, NULL, &policySearch);
315		if (!status && policySearch) {
316			status = SecPolicySearchCopyNext(policySearch, &policy);
317			CFRelease(policySearch);
318		}
319		if (!policy && CFEqual(policyOID, kSecPolicyAppleRevocation)) {
320			policy = SecPolicyCreateRevocation(kSecRevocationUseAnyAvailableMethod);
321		}
322		if (!policy) {
323			policy = SecPolicyCreateWithSecAsn1Oid((SecAsn1Oid*)oidPtr);
324		}
325	}
326	return policy;
327}
328
329/* new in 10.9 */
330SecPolicyRef
331SecPolicyCreateWithProperties(CFTypeRef policyIdentifier, CFDictionaryRef properties)
332{
333	SecPolicyRef policy = SecPolicyCreateWithOID(policyIdentifier);
334	SecPolicySetProperties(policy, properties);
335
336	return policy;
337}
338
339/* new in 10.9 */
340SecPolicyRef
341SecPolicyCreateRevocation(CFOptionFlags revocationFlags)
342{
343	// return a SecPolicyRef object for the unified revocation policy
344	SecAsn1Oid *oidPtr = (SecAsn1Oid*)&CSSMOID_APPLE_TP_REVOCATION;
345	SecPolicyRef policy = SecPolicyCreateWithSecAsn1Oid(oidPtr);
346	//%%% FIXME set policy value with revocationFlags
347
348	return policy;
349}
350
351/* new in 10.9 ***FIXME*** TO BE REMOVED */
352CFArrayRef SecPolicyCopyEscrowRootCertificates(void)
353{
354	return SecCertificateCopyEscrowRoots(kSecCertificateProductionEscrowRoot);
355}
356
357