1/*
2 * Copyright (c) 2008-2012 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/*
25 * SecPolicyServer.c - Trust policies dealing with certificate revocation.
26 */
27
28#include <securityd/SecPolicyServer.h>
29#include <Security/SecPolicyInternal.h>
30#include <Security/SecPolicyPriv.h>
31#include <utilities/SecIOFormat.h>
32#include <securityd/asynchttp.h>
33#include <securityd/policytree.h>
34#include <CoreFoundation/CFTimeZone.h>
35#include <wctype.h>
36#include <libDER/oids.h>
37#include <CoreFoundation/CFNumber.h>
38#include <Security/SecCertificateInternal.h>
39#include <AssertMacros.h>
40#include <utilities/debugging.h>
41#include <security_asn1/SecAsn1Coder.h>
42#include <security_asn1/ocspTemplates.h>
43#include <security_asn1/oidsalg.h>
44#include <security_asn1/oidsocsp.h>
45#include <CommonCrypto/CommonDigest.h>
46#include <Security/SecFramework.h>
47#include <Security/SecPolicyInternal.h>
48#include <Security/SecTrustPriv.h>
49#include <Security/SecInternal.h>
50#include <CFNetwork/CFHTTPMessage.h>
51#include <CFNetwork/CFHTTPStream.h>
52#include <SystemConfiguration/SCDynamicStoreCopySpecific.h>
53#include <asl.h>
54#include <securityd/SecOCSPRequest.h>
55#include <securityd/SecOCSPResponse.h>
56#include <securityd/asynchttp.h>
57#include <securityd/SecTrustServer.h>
58#include <securityd/SecOCSPCache.h>
59#include <utilities/array_size.h>
60#include <utilities/SecCFWrappers.h>
61#include "OTATrustUtilities.h"
62
63#define ocspdErrorLog(args...)     asl_log(NULL, NULL, ASL_LEVEL_ERR, ## args)
64
65/* Set this to 1 to dump the ocsp responses received in DER form in /tmp. */
66#ifndef DUMP_OCSPRESPONSES
67#define DUMP_OCSPRESPONSES  0
68#endif
69
70#if DUMP_OCSPRESPONSES
71
72#include <unistd.h>
73#include <fcntl.h>
74
75static void secdumpdata(CFDataRef data, const char *name) {
76    int fd = open(name, O_CREAT | O_WRONLY | O_TRUNC, 0666);
77    write(fd, CFDataGetBytePtr(data), CFDataGetLength(data));
78    close(fd);
79}
80
81#endif
82
83
84/********************************************************
85 ****************** SecPolicy object ********************
86 ********************************************************/
87
88static CFMutableDictionaryRef gSecPolicyLeafCallbacks = NULL;
89static CFMutableDictionaryRef gSecPolicyPathCallbacks = NULL;
90
91static CFArrayRef SecPolicyAnchorDigestsForEVPolicy(const DERItem *policyOID)
92{
93	CFArrayRef result = NULL;
94	SecOTAPKIRef otapkiRef = SecOTAPKICopyCurrentOTAPKIRef();
95	if (NULL == otapkiRef)
96	{
97		return result;
98	}
99
100	CFDictionaryRef evToPolicyAnchorDigest = SecOTAPKICopyEVPolicyToAnchorMapping(otapkiRef);
101	CFRelease(otapkiRef);
102
103    if (NULL == evToPolicyAnchorDigest)
104    {
105        return result;
106    }
107
108    CFArrayRef roots = NULL;
109    CFStringRef oid = SecDERItemCopyOIDDecimalRepresentation(kCFAllocatorDefault, policyOID);
110    if (oid && evToPolicyAnchorDigest)
111	{
112        result = (CFArrayRef)CFDictionaryGetValue(evToPolicyAnchorDigest, oid);
113		if (roots && CFGetTypeID(result) != CFArrayGetTypeID())
114		{
115            ocspdErrorLog("EVRoot.plist has non array value");
116            result = NULL;
117        }
118        CFRelease(oid);
119    }
120    return result;
121}
122
123
124static bool SecPolicyIsEVPolicy(const DERItem *policyOID) {
125    return SecPolicyAnchorDigestsForEVPolicy(policyOID);
126}
127
128static bool SecPolicyRootCACertificateIsEV(SecCertificateRef certificate,
129    policy_set_t valid_policies) {
130    /* Ensure that this certificate is a valid anchor for one of the
131       certificate policy oids specified in the leaf. */
132    CFDataRef digest = SecCertificateGetSHA1Digest(certificate);
133    policy_set_t ix;
134    bool good_ev_anchor = false;
135    for (ix = valid_policies; ix; ix = ix->oid_next) {
136        CFArrayRef digests = SecPolicyAnchorDigestsForEVPolicy(&ix->oid);
137        if (digests && CFArrayContainsValue(digests,
138            CFRangeMake(0, CFArrayGetCount(digests)), digest)) {
139            secdebug("ev", "found anchor for policy oid");
140            good_ev_anchor = true;
141            break;
142        }
143    }
144    require_quiet(good_ev_anchor, notEV);
145
146    CFAbsoluteTime october2006 = 178761600;
147    if (SecCertificateVersion(certificate) >= 3
148        && SecCertificateNotValidBefore(certificate) >= october2006) {
149        const SecCEBasicConstraints *bc = SecCertificateGetBasicConstraints(certificate);
150        require_quiet(bc && bc->isCA == true, notEV);
151        SecKeyUsage ku = SecCertificateGetKeyUsage(certificate);
152        require_quiet((ku & (kSecKeyUsageKeyCertSign | kSecKeyUsageCRLSign))
153            == (kSecKeyUsageKeyCertSign | kSecKeyUsageCRLSign), notEV);
154    }
155
156    CFAbsoluteTime jan2011 = 315532800;
157    if (SecCertificateNotValidBefore(certificate) < jan2011) {
158        /* At least MD5, SHA-1 with RSA 2048 or ECC NIST P-256. */
159    } else {
160        /* At least SHA-1, SHA-256, SHA-384 or SHA-512 with RSA 2048 or
161           ECC NIST P-256. */
162    }
163
164    return true;
165notEV:
166    return false;
167}
168
169static bool SecPolicySubordinateCACertificateCouldBeEV(SecCertificateRef certificate) {
170    const SecCECertificatePolicies *cp;
171    cp = SecCertificateGetCertificatePolicies(certificate);
172    require_quiet(cp && cp->numPolicies > 0, notEV);
173    /* SecCertificateGetCRLDistributionPoints() is a noop right now */
174#if 0
175    CFArrayRef cdp = SecCertificateGetCRLDistributionPoints(certificate);
176    require_quiet(cdp && CFArrayGetCount(cdp) > 0, notEV);
177#endif
178    const SecCEBasicConstraints *bc = SecCertificateGetBasicConstraints(certificate);
179    require_quiet(bc && bc->isCA == true, notEV);
180    SecKeyUsage ku = SecCertificateGetKeyUsage(certificate);
181    require_quiet((ku & (kSecKeyUsageKeyCertSign | kSecKeyUsageCRLSign))
182        == (kSecKeyUsageKeyCertSign | kSecKeyUsageCRLSign), notEV);
183    CFAbsoluteTime jan2011 = 315532800;
184    if (SecCertificateNotValidBefore(certificate) < jan2011) {
185        /* At least SHA-1 with RSA 1024 or ECC NIST P-256. */
186    } else {
187        /* At least SHA-1, SHA-256, SHA-284 or SHA-512 with RSA 2028 or
188           ECC NIST P-256. */
189    }
190
191    return true;
192notEV:
193    return false;
194}
195
196bool SecPolicySubscriberCertificateCouldBeEV(SecCertificateRef certificate) {
197    /* 3. Subscriber Certificate. */
198
199    /* (a) certificate Policies */
200    const SecCECertificatePolicies *cp;
201    cp = SecCertificateGetCertificatePolicies(certificate);
202    require_quiet(cp && cp->numPolicies > 0, notEV);
203    /* Now find at least one policy in here that has a qualifierID of id-qt 2
204       and a policyQualifier that is a URI to the CPS and an EV policy OID. */
205    uint32_t ix = 0;
206    bool found_ev_anchor_for_leaf_policy = false;
207    for (ix = 0; ix < cp->numPolicies; ++ix) {
208        if (SecPolicyIsEVPolicy(&cp->policies[ix].policyIdentifier)) {
209            found_ev_anchor_for_leaf_policy = true;
210        }
211    }
212    require_quiet(found_ev_anchor_for_leaf_policy, notEV);
213
214    /* SecCertificateGetCRLDistributionPoints() is a noop right now */
215#if 0
216    /* (b) cRLDistributionPoint
217       (c) authorityInformationAccess */
218    CFArrayRef cdp = SecCertificateGetCRLDistributionPoints(certificate);
219    if (cdp) {
220        require_quiet(CFArrayGetCount(cdp) > 0, notEV);
221    } else {
222        CFArrayRef or = SecCertificateGetOCSPResponders(certificate);
223        require_quiet(or && CFArrayGetCount(or) > 0, notEV);
224        //CFArrayRef ci = SecCertificateGetCAIssuers(certificate);
225    }
226#endif
227
228    /* (d) basicConstraints
229       If present, the cA field MUST be set false. */
230    const SecCEBasicConstraints *bc = SecCertificateGetBasicConstraints(certificate);
231    if (bc) {
232        require_quiet(bc->isCA == false, notEV);
233    }
234
235    /* (e) keyUsage. */
236    SecKeyUsage ku = SecCertificateGetKeyUsage(certificate);
237    if (ku) {
238        require_quiet((ku & (kSecKeyUsageKeyCertSign | kSecKeyUsageCRLSign)) == 0, notEV);
239    }
240
241#if 0
242    /* The EV Cert Spec errata specifies this, though this is a check for SSL
243       not specifically EV. */
244
245    /* (e) extKeyUsage
246
247Either the value id-kp-serverAuth [RFC5280] or id-kp-clientAuth [RFC5280] or both values MUST be present. Other values SHOULD NOT be present. */
248    SecCertificateCopyExtendedKeyUsage(certificate);
249#endif
250
251    CFAbsoluteTime jan2011 = 315532800;
252    if (SecCertificateNotValidAfter(certificate) < jan2011) {
253        /* At least SHA-1 with RSA 1024 or ECC NIST P-256. */
254    } else {
255        /* At least SHA-1, SHA-256, SHA-284 or SHA-512 with RSA 2028 or
256           ECC NIST P-256. */
257    }
258
259    return true;
260notEV:
261    return false;
262}
263
264/********************************************************
265 **************** SecPolicy Callbacks *******************
266 ********************************************************/
267static void SecPolicyCheckCriticalExtensions(SecPVCRef pvc,
268	CFStringRef key) {
269}
270
271static void SecPolicyCheckIdLinkage(SecPVCRef pvc,
272	CFStringRef key) {
273	CFIndex ix, count = SecPVCGetCertificateCount(pvc);
274	CFDataRef parentSubjectKeyID = NULL;
275	for (ix = count - 1; ix >= 0; --ix) {
276		SecCertificateRef cert = SecPVCGetCertificateAtIndex(pvc, ix);
277		/* If the previous certificate in the chain had a SubjectKeyID,
278		   make sure it matches the current certificates AuthorityKeyID. */
279		if (parentSubjectKeyID) {
280			/* @@@ According to RFC 2459 neither AuthorityKeyID nor
281			   SubjectKeyID can be critical.  Currenty we don't check
282			   for this. */
283			CFDataRef authorityKeyID = SecCertificateGetAuthorityKeyID(cert);
284			if (authorityKeyID) {
285				if (!CFEqual(parentSubjectKeyID, authorityKeyID)) {
286					/* AuthorityKeyID doesn't match issuers SubjectKeyID. */
287					if (!SecPVCSetResult(pvc, key, ix, kCFBooleanFalse))
288						return;
289				}
290			}
291		}
292
293		parentSubjectKeyID = SecCertificateGetSubjectKeyID(cert);
294	}
295}
296
297static bool keyusage_allows(SecKeyUsage keyUsage, CFTypeRef xku) {
298    if (!xku || CFGetTypeID(xku) != CFNumberGetTypeID())
299        return false;
300
301    SInt32 dku;
302    CFNumberGetValue((CFNumberRef)xku, kCFNumberSInt32Type, &dku);
303    SecKeyUsage ku = (SecKeyUsage)dku;
304    return (keyUsage & ku) == ku;
305}
306
307static void SecPolicyCheckKeyUsage(SecPVCRef pvc,
308	CFStringRef key) {
309    SecCertificateRef leaf = SecPVCGetCertificateAtIndex(pvc, 0);
310    SecKeyUsage keyUsage = SecCertificateGetKeyUsage(leaf);
311    bool match = false;
312    SecPolicyRef policy = SecPVCGetPolicy(pvc);
313    CFTypeRef xku = CFDictionaryGetValue(policy->_options, key);
314    if (isArray(xku)) {
315        CFIndex ix, count = CFArrayGetCount(xku);
316        for (ix = 0; ix < count; ++ix) {
317            CFTypeRef ku = CFArrayGetValueAtIndex(xku, ix);
318            if (keyusage_allows(keyUsage, ku)) {
319                match = true;
320                break;
321            }
322        }
323    } else {
324        match = keyusage_allows(keyUsage, xku);
325    }
326    if (!match) {
327        SecPVCSetResult(pvc, key, 0, kCFBooleanFalse);
328    }
329}
330
331static bool extendedkeyusage_allows(CFArrayRef extendedKeyUsage,
332                                    CFTypeRef xeku) {
333    if (!xeku || CFGetTypeID(xeku) != CFDataGetTypeID())
334        return false;
335    if (extendedKeyUsage) {
336        CFRange all = { 0, CFArrayGetCount(extendedKeyUsage) };
337        return CFArrayContainsValue(extendedKeyUsage, all, xeku);
338    } else {
339        /* Certificate has no extended key usage, only a match if the policy
340           contains a 0 length CFDataRef. */
341        return CFDataGetLength((CFDataRef)xeku) == 0;
342    }
343}
344
345/* AUDIT[securityd](done):
346   policy->_options is a caller provided dictionary, only its cf type has
347   been checked.
348 */
349static void SecPolicyCheckExtendedKeyUsage(SecPVCRef pvc, CFStringRef key) {
350    SecCertificateRef leaf = SecPVCGetCertificateAtIndex(pvc, 0);
351    CFArrayRef leafExtendedKeyUsage = SecCertificateCopyExtendedKeyUsage(leaf);
352    bool match = false;
353    SecPolicyRef policy = SecPVCGetPolicy(pvc);
354    CFTypeRef xeku = CFDictionaryGetValue(policy->_options, key);
355    if (isArray(xeku)) {
356        CFIndex ix, count = CFArrayGetCount(xeku);
357        for (ix = 0; ix < count; ix++) {
358            CFTypeRef eku = CFArrayGetValueAtIndex(xeku, ix);
359            if (extendedkeyusage_allows(leafExtendedKeyUsage, eku)) {
360                match = true;
361                break;
362            }
363        }
364    } else {
365        match = extendedkeyusage_allows(leafExtendedKeyUsage, xeku);
366    }
367    CFReleaseSafe(leafExtendedKeyUsage);
368    if (!match) {
369        SecPVCSetResult(pvc, key, 0, kCFBooleanFalse);
370    }
371}
372
373#if 0
374static void SecPolicyCheckBasicContraintsCommon(SecPVCRef pvc,
375	CFStringRef key, bool strict) {
376	CFIndex ix, count = SecPVCGetCertificateCount(pvc);
377	for (ix = 0; ix < count; ++ix) {
378		SecCertificateRef cert = SecPVCGetCertificateAtIndex(pvc, ix);
379		const SecCEBasicConstraints *bc =
380			SecCertificateGetBasicConstraints(cert);
381		if (bc) {
382			if (strict) {
383				if (ix == 0) {
384					/* Leaf certificate has basic constraints extension. */
385					if (!SecPVCSetResult(pvc, key, ix, kCFBooleanFalse))
386						return;
387				} else if (!bc->critical) {
388					/* Basic constraints extension is not marked critical. */
389					if (!SecPVCSetResult(pvc, key, ix, kCFBooleanFalse))
390						return;
391				}
392			}
393
394			if (ix > 0 || count == 1) {
395				if (!bc->isCA) {
396					/* Non leaf certificate marked as isCA false. */
397					if (!SecPVCSetResult(pvc, key, ix, kCFBooleanFalse))
398						return;
399				}
400
401				if (bc->pathLenConstraintPresent) {
402					if (bc->pathLenConstraint < (uint32_t)(ix - 1)) {
403#if 0
404						/* @@@ If a self signed certificate is issued by
405						   another cert that is trusted, then we are supposed
406						   to treat the self signed cert itself as the anchor
407						   for path length purposes. */
408						CFIndex ssix = SecCertificatePathSelfSignedIndex(path);
409						if (ssix >= 0 && ix >= ssix) {
410							/* It's ok if the pathLenConstraint isn't met for
411							   certificates signing a self signed cert in the
412							   chain. */
413						} else
414#endif
415						{
416							/* Path Length Constraint Exceeded. */
417							if (!SecPVCSetResult(pvc, key, ix,
418								kCFBooleanFalse))
419								return;
420						}
421					}
422				}
423			}
424		} else if (strict && ix > 0) {
425			/* In strict mode all CA certificates *MUST* have a critical
426			   basic constraints extension and the leaf certificate
427			   *MUST NOT* have a basic constraints extension. */
428			/* CA certificate is missing basicConstraints extension. */
429			if (!SecPVCSetResult(pvc, key, ix, kCFBooleanFalse))
430				return;
431		}
432	}
433}
434#endif
435
436static void SecPolicyCheckBasicContraints(SecPVCRef pvc,
437	CFStringRef key) {
438	//SecPolicyCheckBasicContraintsCommon(pvc, key, false);
439}
440
441static void SecPolicyCheckNonEmptySubject(SecPVCRef pvc,
442	CFStringRef key) {
443	CFIndex ix, count = SecPVCGetCertificateCount(pvc);
444	for (ix = 0; ix < count; ++ix) {
445		SecCertificateRef cert = SecPVCGetCertificateAtIndex(pvc, ix);
446		/* If the certificate has a subject, or
447		   if it doesn't, and it's the leaf and not self signed,
448		   and also has a critical subjectAltName extension it's valid. */
449		if (!SecCertificateHasSubject(cert)) {
450			if (ix == 0 && count > 1) {
451				if (!SecCertificateHasCriticalSubjectAltName(cert)) {
452					/* Leaf certificate with empty subject does not have
453					   a critical subject alt name extension. */
454					if (!SecPVCSetResult(pvc, key, ix, kCFBooleanFalse))
455						return;
456				}
457			} else {
458				/* CA certificate has empty subject. */
459				if (!SecPVCSetResult(pvc, key, ix, kCFBooleanFalse))
460					return;
461			}
462		}
463	}
464}
465
466static void SecPolicyCheckQualifiedCertStatements(SecPVCRef pvc,
467	CFStringRef key) {
468}
469
470/* Compare hostname, to a server name obtained from the server's cert
471   Obtained from the SubjectAltName or the CommonName entry in the Subject.
472   Limited wildcard checking is performed here as outlined in
473
474   RFC 2818 Section 3.1.  Server Identity
475
476   [...] Names may contain the wildcard
477   character * which is considered to match any single domain name
478   component or component fragment. E.g., *.a.com matches foo.a.com but
479   not bar.foo.a.com. f*.com matches foo.com but not bar.com.
480   [...]
481
482   Trailing '.' characters in the hostname will be ignored.
483
484   Returns true on match, else false.
485 */
486static bool SecDNSMatch(CFStringRef hostname, CFStringRef servername) {
487	CFStringInlineBuffer hbuf, sbuf;
488	CFIndex hix, six,
489		hlength = CFStringGetLength(hostname),
490		slength = CFStringGetLength(servername);
491	CFRange hrange = { 0, hlength }, srange = { 0, slength };
492	CFStringInitInlineBuffer(hostname, &hbuf, hrange);
493	CFStringInitInlineBuffer(servername, &sbuf, srange);
494
495	for (hix = six = 0; six < slength; ++six) {
496		UniChar hch, sch = CFStringGetCharacterFromInlineBuffer(&sbuf, six);
497		if (sch == '*') {
498			if (six + 1 >= slength) {
499				/* Trailing '*' in servername, match until end of hostname or
500				   trailing '.'.  */
501				do {
502					if (hix >= hlength) {
503						/* If we reach the end of the hostname we have a
504						   match. */
505						return true;
506					}
507					hch = CFStringGetCharacterFromInlineBuffer(&hbuf, hix++);
508				} while (hch != '.');
509				/* We reached the end of servername and found a '.' in
510				   hostname.  Return true if hostname has a single
511				   trailing '.' return false if there is anything after it. */
512				return hix == hlength;
513			}
514
515			/* Grab the character after the '*'. */
516			sch = CFStringGetCharacterFromInlineBuffer(&sbuf, ++six);
517			if (sch != '.') {
518				/* We have something of the form '*foo.com'.  Or '**.com'
519				   We don't deal with that yet, since it might require
520				   backtracking. Also RFC 2818 doesn't seem to require it. */
521				return false;
522			}
523
524			/* We're looking at the '.' after the '*' in something of the
525			   form 'foo*.com' or '*.com'. Match until next '.' in hostname. */
526			do {
527				/* Since we're not at the end of servername yet (that case
528				   was handeled above), running out of chars in hostname
529				   means we don't have a match. */
530				if (hix >= hlength)
531					return false;
532				hch = CFStringGetCharacterFromInlineBuffer(&hbuf, hix++);
533			} while (hch != '.');
534		} else {
535			/* We're looking at a non wildcard character in the servername.
536			   If we reached the end of hostname it's not a match. */
537			if (hix >= hlength)
538				return false;
539
540			/* Otherwise make sure the hostname matches the character in the
541			   servername, case insensitively. */
542			hch = CFStringGetCharacterFromInlineBuffer(&hbuf, hix++);
543			if (towlower(hch) != towlower(sch))
544				return false;
545		}
546	}
547
548	if (hix < hlength) {
549		/* We reached the end of servername but we have one or more characters
550		   left to compare against in the hostname. */
551		if (hix + 1 == hlength &&
552			CFStringGetCharacterFromInlineBuffer(&hbuf, hix) == '.') {
553			/* Hostname has a single trailing '.', we're ok with that. */
554			return true;
555		}
556		/* Anything else is not a match. */
557		return false;
558	}
559
560	return true;
561}
562
563/* AUDIT[securityd](done):
564   policy->_options is a caller provided dictionary, only its cf type has
565   been checked.
566 */
567static void SecPolicyCheckSSLHostname(SecPVCRef pvc,
568	CFStringRef key) {
569	/* @@@ Consider what to do if the caller passes in no hostname.  Should
570	   we then still fail if the leaf has no dnsNames or IPAddresses at all? */
571	SecPolicyRef policy = SecPVCGetPolicy(pvc);
572	CFStringRef hostName = (CFStringRef)
573		CFDictionaryGetValue(policy->_options, key);
574    if (!isString(hostName)) {
575        /* @@@ We can't return an error here and making the evaluation fail
576           won't help much either. */
577        return;
578    }
579
580	SecCertificateRef leaf = SecPVCGetCertificateAtIndex(pvc, 0);
581	bool dnsMatch = false;
582	CFArrayRef dnsNames = SecCertificateCopyDNSNames(leaf);
583	if (dnsNames) {
584		CFIndex ix, count = CFArrayGetCount(dnsNames);
585		for (ix = 0; ix < count; ++ix) {
586			CFStringRef dns = (CFStringRef)CFArrayGetValueAtIndex(dnsNames, ix);
587			if (SecDNSMatch(hostName, dns)) {
588				dnsMatch = true;
589				break;
590			}
591		}
592		CFRelease(dnsNames);
593	}
594
595    if (!dnsMatch) {
596        /* Maybe hostname is an IPv4 or IPv6 address, let's compare against
597           the values returned by SecCertificateCopyIPAddresses() instead. */
598        CFArrayRef ipAddresses = SecCertificateCopyIPAddresses(leaf);
599        if (ipAddresses) {
600            CFIndex ix, count = CFArrayGetCount(ipAddresses);
601            for (ix = 0; ix < count; ++ix) {
602                CFStringRef ipAddress = (CFStringRef)CFArrayGetValueAtIndex(ipAddresses, ix);
603                if (!CFStringCompare(hostName, ipAddress, kCFCompareCaseInsensitive)) {
604                    dnsMatch = true;
605                    break;
606                }
607            }
608            CFRelease(ipAddresses);
609        }
610    }
611
612	if (!dnsMatch) {
613		/* Hostname mismatch or no hostnames found in certificate. */
614		SecPVCSetResult(pvc, key, 0, kCFBooleanFalse);
615    }
616    if ((dnsMatch || pvc->details)
617        && SecPolicySubscriberCertificateCouldBeEV(leaf)) {
618        secdebug("policy", "enabling optionally_ev");
619        pvc->optionally_ev = true;
620        /* optionally_ev => check_revocation, so we don't enable revocation
621           checking here, since we don't want it on for non EV ssl certs.  */
622#if 0
623        /* Check revocation status if the certificate asks for it (and we
624           support it) currently we only support ocsp. */
625        CFArrayRef ocspResponders = SecCertificateGetOCSPResponders(leaf);
626        if (ocspResponders) {
627            SecPVCSetCheckRevocation(pvc);
628        }
629#endif
630    }
631}
632
633/* AUDIT[securityd](done):
634 policy->_options is a caller provided dictionary, only its cf type has
635 been checked.
636 */
637static void SecPolicyCheckEmail(SecPVCRef pvc, CFStringRef key) {
638	SecPolicyRef policy = SecPVCGetPolicy(pvc);
639	CFStringRef email = (CFStringRef)CFDictionaryGetValue(policy->_options, key);
640	bool match = false;
641    if (!isString(email)) {
642        /* We can't return an error here and making the evaluation fail
643         won't help much either. */
644        return;
645    }
646
647	SecCertificateRef leaf = SecPVCGetCertificateAtIndex(pvc, 0);
648	CFArrayRef addrs = SecCertificateCopyRFC822Names(leaf);
649	if (addrs) {
650		CFIndex ix, count = CFArrayGetCount(addrs);
651		for (ix = 0; ix < count; ++ix) {
652			CFStringRef addr = (CFStringRef)CFArrayGetValueAtIndex(addrs, ix);
653			if (!CFStringCompare(email, addr, kCFCompareCaseInsensitive)) {
654				match = true;
655				break;
656			}
657		}
658		CFRelease(addrs);
659	}
660
661	if (!match) {
662		/* Hostname mismatch or no hostnames found in certificate. */
663		SecPVCSetResult(pvc, key, 0, kCFBooleanFalse);
664    }
665}
666
667static void SecPolicyCheckValidIntermediates(SecPVCRef pvc,
668	CFStringRef key) {
669	CFIndex ix, count = SecPVCGetCertificateCount(pvc);
670	CFAbsoluteTime verifyTime = SecPVCGetVerifyTime(pvc);
671	for (ix = 1; ix < count - 1; ++ix) {
672		SecCertificateRef cert = SecPVCGetCertificateAtIndex(pvc, ix);
673		if (!SecCertificateIsValid(cert, verifyTime)) {
674			/* Intermediate certificate has expired. */
675			if (!SecPVCSetResult(pvc, key, ix, kCFBooleanFalse))
676				return;
677		}
678	}
679}
680
681static void SecPolicyCheckValidLeaf(SecPVCRef pvc,
682	CFStringRef key) {
683	CFAbsoluteTime verifyTime = SecPVCGetVerifyTime(pvc);
684	SecCertificateRef cert = SecPVCGetCertificateAtIndex(pvc, 0);
685	if (!SecCertificateIsValid(cert, verifyTime)) {
686		/* Leaf certificate has expired. */
687		if (!SecPVCSetResult(pvc, key, 0, kCFBooleanFalse))
688			return;
689	}
690}
691
692static void SecPolicyCheckValidRoot(SecPVCRef pvc,
693	CFStringRef key) {
694	CFIndex ix, count = SecPVCGetCertificateCount(pvc);
695	CFAbsoluteTime verifyTime = SecPVCGetVerifyTime(pvc);
696	ix = count - 1;
697	SecCertificateRef cert = SecPVCGetCertificateAtIndex(pvc, ix);
698	if (!SecCertificateIsValid(cert, verifyTime)) {
699		/* Root certificate has expired. */
700		if (!SecPVCSetResult(pvc, key, ix, kCFBooleanFalse))
701			return;
702	}
703}
704
705/* AUDIT[securityd](done):
706   policy->_options is a caller provided dictionary, only its cf type has
707   been checked.
708 */
709static void SecPolicyCheckIssuerCommonName(SecPVCRef pvc,
710	CFStringRef key) {
711    CFIndex count = SecPVCGetCertificateCount(pvc);
712    if (count < 2) {
713		/* Can't check intermediates common name if there is no intermediate. */
714		SecPVCSetResult(pvc, key, 0, kCFBooleanFalse);
715        return;
716    }
717
718	SecCertificateRef cert = SecPVCGetCertificateAtIndex(pvc, 1);
719	SecPolicyRef policy = SecPVCGetPolicy(pvc);
720    CFStringRef commonName =
721        (CFStringRef)CFDictionaryGetValue(policy->_options, key);
722    if (!isString(commonName)) {
723        /* @@@ We can't return an error here and making the evaluation fail
724           won't help much either. */
725        return;
726    }
727    CFArrayRef commonNames = SecCertificateCopyCommonNames(cert);
728    if (!commonNames || CFArrayGetCount(commonNames) != 1 ||
729        !CFEqual(commonName, CFArrayGetValueAtIndex(commonNames, 0))) {
730		/* Common Name mismatch. */
731		SecPVCSetResult(pvc, key, 0, kCFBooleanFalse);
732	}
733    CFReleaseSafe(commonNames);
734}
735
736/* AUDIT[securityd](done):
737   policy->_options is a caller provided dictionary, only its cf type has
738   been checked.
739 */
740static void SecPolicyCheckSubjectCommonName(SecPVCRef pvc,
741	CFStringRef key) {
742	SecCertificateRef cert = SecPVCGetCertificateAtIndex(pvc, 0);
743	SecPolicyRef policy = SecPVCGetPolicy(pvc);
744	CFStringRef common_name = (CFStringRef)CFDictionaryGetValue(policy->_options,
745		key);
746    if (!isString(common_name)) {
747        /* @@@ We can't return an error here and making the evaluation fail
748           won't help much either. */
749        return;
750    }
751	CFArrayRef commonNames = SecCertificateCopyCommonNames(cert);
752	if (!commonNames || CFArrayGetCount(commonNames) != 1 ||
753		!CFEqual(common_name, CFArrayGetValueAtIndex(commonNames, 0))) {
754		/* Common Name mismatch. */
755		SecPVCSetResult(pvc, key, 0, kCFBooleanFalse);
756	}
757	CFReleaseSafe(commonNames);
758}
759
760/* AUDIT[securityd](done):
761   policy->_options is a caller provided dictionary, only its cf type has
762   been checked.
763 */
764static void SecPolicyCheckSubjectCommonNamePrefix(SecPVCRef pvc,
765	CFStringRef key) {
766	SecCertificateRef cert = SecPVCGetCertificateAtIndex(pvc, 0);
767	SecPolicyRef policy = SecPVCGetPolicy(pvc);
768    CFStringRef prefix = (CFStringRef)CFDictionaryGetValue(policy->_options,
769		key);
770    if (!isString(prefix)) {
771        /* @@@ We can't return an error here and making the evaluation fail
772           won't help much either. */
773        return;
774    }
775    CFArrayRef commonNames = SecCertificateCopyCommonNames(cert);
776    if (!commonNames || CFArrayGetCount(commonNames) != 1 ||
777        !CFStringHasPrefix(CFArrayGetValueAtIndex(commonNames, 0), prefix)) {
778		/* Common Name prefix mismatch. */
779		SecPVCSetResult(pvc, key, 0, kCFBooleanFalse);
780	}
781    CFReleaseSafe(commonNames);
782}
783
784/* AUDIT[securityd](done):
785   policy->_options is a caller provided dictionary, only its cf type has
786   been checked.
787 */
788static void SecPolicyCheckSubjectCommonNameTEST(SecPVCRef pvc,
789	CFStringRef key) {
790	SecCertificateRef cert = SecPVCGetCertificateAtIndex(pvc, 0);
791	SecPolicyRef policy = SecPVCGetPolicy(pvc);
792	CFStringRef common_name = (CFStringRef)CFDictionaryGetValue(policy->_options,
793		key);
794    if (!isString(common_name)) {
795        /* @@@ We can't return an error here and making the evaluation fail
796           won't help much either. */
797        return;
798    }
799	CFArrayRef commonNames = SecCertificateCopyCommonNames(cert);
800	if (!commonNames || CFArrayGetCount(commonNames) != 1) {
801        CFStringRef cert_common_name = CFArrayGetValueAtIndex(commonNames, 0);
802        CFStringRef test_common_name = common_name ?
803            CFStringCreateWithFormat(kCFAllocatorDefault,
804                NULL, CFSTR("TEST %@ TEST"), common_name) :
805            NULL;
806		if (!CFEqual(common_name, cert_common_name) &&
807            (!test_common_name || !CFEqual(test_common_name, cert_common_name)))
808                /* Common Name mismatch. */
809                SecPVCSetResult(pvc, key, 0, kCFBooleanFalse);
810        CFReleaseSafe(test_common_name);
811	}
812	CFReleaseSafe(commonNames);
813}
814
815/* AUDIT[securityd](done):
816   policy->_options is a caller provided dictionary, only its cf type has
817   been checked.
818 */
819static void SecPolicyCheckNotValidBefore(SecPVCRef pvc,
820	CFStringRef key) {
821	SecCertificateRef cert = SecPVCGetCertificateAtIndex(pvc, 0);
822	SecPolicyRef policy = SecPVCGetPolicy(pvc);
823    CFDateRef date = (CFDateRef)CFDictionaryGetValue(policy->_options, key);
824    if (!isDate(date)) {
825        /* @@@ We can't return an error here and making the evaluation fail
826           won't help much either. */
827        return;
828    }
829	CFAbsoluteTime at = CFDateGetAbsoluteTime(date);
830	if (SecCertificateNotValidBefore(cert) <= at) {
831		/* Leaf certificate has not valid before that is too old. */
832		if (!SecPVCSetResult(pvc, key, 0, kCFBooleanFalse))
833			return;
834	}
835}
836
837/* AUDIT[securityd](done):
838   policy->_options is a caller provided dictionary, only its cf type has
839   been checked.
840 */
841static void SecPolicyCheckChainLength(SecPVCRef pvc,
842	CFStringRef key) {
843	CFIndex count = SecPVCGetCertificateCount(pvc);
844	SecPolicyRef policy = SecPVCGetPolicy(pvc);
845    CFNumberRef chainLength =
846        (CFNumberRef)CFDictionaryGetValue(policy->_options, key);
847    CFIndex value;
848    if (!chainLength || CFGetTypeID(chainLength) != CFNumberGetTypeID() ||
849        !CFNumberGetValue(chainLength, kCFNumberCFIndexType, &value)) {
850        /* @@@ We can't return an error here and making the evaluation fail
851           won't help much either. */
852        return;
853    }
854    if (value != count) {
855		/* Chain length doesn't match policy requirement. */
856		if (!SecPVCSetResult(pvc, key, 0, kCFBooleanFalse))
857			return;
858    }
859}
860
861/* AUDIT[securityd](done):
862   policy->_options is a caller provided dictionary, only its cf type has
863   been checked.
864 */
865static void SecPolicyCheckAnchorSHA1(SecPVCRef pvc,
866	CFStringRef key) {
867    CFIndex count = SecPVCGetCertificateCount(pvc);
868	SecCertificateRef cert = SecPVCGetCertificateAtIndex(pvc, count - 1);
869	SecPolicyRef policy = SecPVCGetPolicy(pvc);
870    CFTypeRef value = CFDictionaryGetValue(policy->_options, key);
871    CFDataRef anchorSHA1 = SecCertificateGetSHA1Digest(cert);
872
873    bool foundMatch = false;
874
875    if (isData(value))
876        foundMatch = CFEqual(anchorSHA1, value);
877    else if (isArray(value))
878        foundMatch = CFArrayContainsValue((CFArrayRef) value, CFRangeMake(0, CFArrayGetCount((CFArrayRef) value)), anchorSHA1);
879    else {
880        /* @@@ We only support Data and Array but we can't return an error here so.
881               we let the evaluation fail (not much help) and assert in debug. */
882        assert(false);
883    }
884
885    if (!foundMatch)
886        if (!SecPVCSetResult(pvc, kSecPolicyCheckAnchorSHA1, 0, kCFBooleanFalse))
887            return;
888
889    return;
890}
891
892/* AUDIT[securityd](done):
893   policy->_options is a caller provided dictionary, only its cf type has
894   been checked.
895 */
896static void SecPolicyCheckSubjectOrganization(SecPVCRef pvc,
897	CFStringRef key) {
898	SecCertificateRef cert = SecPVCGetCertificateAtIndex(pvc, 0);
899	SecPolicyRef policy = SecPVCGetPolicy(pvc);
900	CFStringRef org = (CFStringRef)CFDictionaryGetValue(policy->_options,
901		key);
902    if (!isString(org)) {
903        /* @@@ We can't return an error here and making the evaluation fail
904           won't help much either. */
905        return;
906    }
907	CFArrayRef organization = SecCertificateCopyOrganization(cert);
908	if (!organization || CFArrayGetCount(organization) != 1 ||
909		!CFEqual(org, CFArrayGetValueAtIndex(organization, 0))) {
910		/* Leaf Subject Organization mismatch. */
911		SecPVCSetResult(pvc, key, 0, kCFBooleanFalse);
912	}
913	CFReleaseSafe(organization);
914}
915
916static void SecPolicyCheckSubjectOrganizationalUnit(SecPVCRef pvc,
917	CFStringRef key) {
918	SecCertificateRef cert = SecPVCGetCertificateAtIndex(pvc, 0);
919	SecPolicyRef policy = SecPVCGetPolicy(pvc);
920	CFStringRef orgUnit = (CFStringRef)CFDictionaryGetValue(policy->_options,
921		key);
922    if (!isString(orgUnit)) {
923        /* @@@ We can't return an error here and making the evaluation fail
924           won't help much either. */
925        return;
926    }
927	CFArrayRef organizationalUnit = SecCertificateCopyOrganizationalUnit(cert);
928	if (!organizationalUnit || CFArrayGetCount(organizationalUnit) != 1 ||
929		!CFEqual(orgUnit, CFArrayGetValueAtIndex(organizationalUnit, 0))) {
930		/* Leaf Subject Organizational Unit mismatch. */
931		SecPVCSetResult(pvc, key, 0, kCFBooleanFalse);
932	}
933	CFReleaseSafe(organizationalUnit);
934}
935
936/* AUDIT[securityd](done):
937   policy->_options is a caller provided dictionary, only its cf type has
938   been checked.
939 */
940static void SecPolicyCheckEAPTrustedServerNames(SecPVCRef pvc,
941	CFStringRef key) {
942	SecPolicyRef policy = SecPVCGetPolicy(pvc);
943	CFArrayRef trustedServerNames = (CFArrayRef)
944		CFDictionaryGetValue(policy->_options, key);
945    /* No names specified means we accept any name. */
946    if (!trustedServerNames)
947        return;
948    if (!isArray(trustedServerNames)) {
949        /* @@@ We can't return an error here and making the evaluation fail
950           won't help much either. */
951        return;
952    }
953
954    CFIndex tsnCount = CFArrayGetCount(trustedServerNames);
955	SecCertificateRef leaf = SecPVCGetCertificateAtIndex(pvc, 0);
956	bool dnsMatch = false;
957	CFArrayRef dnsNames = SecCertificateCopyDNSNames(leaf);
958	if (dnsNames) {
959		CFIndex ix, count = CFArrayGetCount(dnsNames);
960        // @@@ This is O(N^2) unfortunately we can't do better easily unless
961        // we don't do wildcard matching. */
962		for (ix = 0; !dnsMatch && ix < count; ++ix) {
963			CFStringRef dns = (CFStringRef)CFArrayGetValueAtIndex(dnsNames, ix);
964            CFIndex tix;
965            for (tix = 0; tix < tsnCount; ++tix) {
966                CFStringRef serverName =
967                    (CFStringRef)CFArrayGetValueAtIndex(trustedServerNames, tix);
968                if (!isString(serverName)) {
969                    /* @@@ We can't return an error here and making the
970                       evaluation fail won't help much either. */
971                    CFReleaseSafe(dnsNames);
972                    return;
973                }
974                /* we purposefully reverse the arguments here such that dns names
975                   from the cert are matched against a server name list, where
976                   the server names list can contain wildcards and the dns name
977                   cannot.  References: http://support.microsoft.com/kb/941123
978                   It's easy to find occurrences where people tried to use
979                   wildcard certificates and were told that those don't work
980                   in this context. */
981                if (SecDNSMatch(dns, serverName)) {
982                    dnsMatch = true;
983                    break;
984                }
985            }
986		}
987		CFRelease(dnsNames);
988	}
989
990	if (!dnsMatch) {
991		/* Hostname mismatch or no hostnames found in certificate. */
992		SecPVCSetResult(pvc, key, 0, kCFBooleanFalse);
993	}
994}
995
996static const unsigned char UTN_USERFirst_Hardware_Serial[][16] = {
997{ 0xd8, 0xf3, 0x5f, 0x4e, 0xb7, 0x87, 0x2b, 0x2d, 0xab, 0x06, 0x92, 0xe3, 0x15, 0x38, 0x2f, 0xb0 },
998{ 0x92, 0x39, 0xd5, 0x34, 0x8f, 0x40, 0xd1, 0x69, 0x5a, 0x74, 0x54, 0x70, 0xe1, 0xf2, 0x3f, 0x43 },
999{ 0xb0, 0xb7, 0x13, 0x3e, 0xd0, 0x96, 0xf9, 0xb5, 0x6f, 0xae, 0x91, 0xc8, 0x74, 0xbd, 0x3a, 0xc0 },
1000{ 0xe9, 0x02, 0x8b, 0x95, 0x78, 0xe4, 0x15, 0xdc, 0x1a, 0x71, 0x0a, 0x2b, 0x88, 0x15, 0x44, 0x47 },
1001{ 0x39, 0x2a, 0x43, 0x4f, 0x0e, 0x07, 0xdf, 0x1f, 0x8a, 0xa3, 0x05, 0xde, 0x34, 0xe0, 0xc2, 0x29 },
1002{ 0x3e, 0x75, 0xce, 0xd4, 0x6b, 0x69, 0x30, 0x21, 0x21, 0x88, 0x30, 0xae, 0x86, 0xa8, 0x2a, 0x71 },
1003{ 0xd7, 0x55, 0x8f, 0xda, 0xf5, 0xf1, 0x10, 0x5b, 0xb2, 0x13, 0x28, 0x2b, 0x70, 0x77, 0x29, 0xa3 },
1004{ 0x04, 0x7e, 0xcb, 0xe9, 0xfc, 0xa5, 0x5f, 0x7b, 0xd0, 0x9e, 0xae, 0x36, 0xe1, 0x0c, 0xae, 0x1e },
1005{ 0xf5, 0xc8, 0x6a, 0xf3, 0x61, 0x62, 0xf1, 0x3a, 0x64, 0xf5, 0x4f, 0x6d, 0xc9, 0x58, 0x7c, 0x06 } };
1006
1007static const unsigned char UTN_USERFirst_Hardware_Normalized_Issuer[] = {
1008  0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55,
1009  0x53, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x02,
1010  0x55, 0x54, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13,
1011  0x0e, 0x53, 0x41, 0x4c, 0x54, 0x20, 0x4c, 0x41, 0x4b, 0x45, 0x20, 0x43,
1012  0x49, 0x54, 0x59, 0x31, 0x1e, 0x30, 0x1c, 0x06, 0x03, 0x55, 0x04, 0x0a,
1013  0x13, 0x15, 0x54, 0x48, 0x45, 0x20, 0x55, 0x53, 0x45, 0x52, 0x54, 0x52,
1014  0x55, 0x53, 0x54, 0x20, 0x4e, 0x45, 0x54, 0x57, 0x4f, 0x52, 0x4b, 0x31,
1015  0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x18, 0x48, 0x54,
1016  0x54, 0x50, 0x3a, 0x2f, 0x2f, 0x57, 0x57, 0x57, 0x2e, 0x55, 0x53, 0x45,
1017  0x52, 0x54, 0x52, 0x55, 0x53, 0x54, 0x2e, 0x43, 0x4f, 0x4d, 0x31, 0x1f,
1018  0x30, 0x1d, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x16, 0x55, 0x54, 0x4e,
1019  0x2d, 0x55, 0x53, 0x45, 0x52, 0x46, 0x49, 0x52, 0x53, 0x54, 0x2d, 0x48,
1020  0x41, 0x52, 0x44, 0x57, 0x41, 0x52, 0x45
1021};
1022static const unsigned int UTN_USERFirst_Hardware_Normalized_Issuer_len = 151;
1023
1024
1025static void SecPolicyCheckBlackListedLeaf(SecPVCRef pvc,
1026	CFStringRef key) {
1027	SecCertificateRef cert = SecPVCGetCertificateAtIndex(pvc, 0);
1028    CFDataRef issuer = cert ? SecCertificateGetNormalizedIssuerContent(cert) : NULL;
1029
1030    if (issuer && (CFDataGetLength(issuer) == (CFIndex)UTN_USERFirst_Hardware_Normalized_Issuer_len) &&
1031        (0 == memcmp(UTN_USERFirst_Hardware_Normalized_Issuer, CFDataGetBytePtr(issuer),
1032            UTN_USERFirst_Hardware_Normalized_Issuer_len)))
1033    {
1034        CFDataRef serial = SecCertificateCopySerialNumber(cert);
1035        if (serial) {
1036            CFIndex serial_length = CFDataGetLength(serial);
1037            const uint8_t *serial_ptr = CFDataGetBytePtr(serial);
1038
1039            while ((serial_length > 0) && (*serial_ptr == 0)) {
1040                serial_ptr++;
1041                serial_length--;
1042            }
1043
1044            if (serial_length == (CFIndex)sizeof(*UTN_USERFirst_Hardware_Serial)) {
1045                unsigned int i;
1046                for (i = 0; i < array_size(UTN_USERFirst_Hardware_Serial); i++)
1047                {
1048                    if (0 == memcmp(UTN_USERFirst_Hardware_Serial[i],
1049                        serial_ptr, sizeof(*UTN_USERFirst_Hardware_Serial)))
1050                    {
1051                        SecPVCSetResult(pvc, key, 0, kCFBooleanFalse);
1052                        CFReleaseSafe(serial);
1053                        return;
1054                    }
1055                }
1056            }
1057            CFRelease(serial);
1058        }
1059    }
1060
1061	SecOTAPKIRef otapkiRef = SecOTAPKICopyCurrentOTAPKIRef();
1062	if (NULL != otapkiRef)
1063	{
1064		CFSetRef blackListedKeys = SecOTAPKICopyBlackListSet(otapkiRef);
1065		CFRelease(otapkiRef);
1066		if (NULL != blackListedKeys)
1067		{
1068			/* Check for blacklisted intermediates keys. */
1069			CFDataRef dgst = SecCertificateCopyPublicKeySHA1Digest(cert);
1070			if (dgst)
1071			{
1072				/* Check dgst against blacklist. */
1073				if (CFSetContainsValue(blackListedKeys, dgst))
1074				{
1075					SecPVCSetResult(pvc, key, 0, kCFBooleanFalse);
1076				}
1077				CFRelease(dgst);
1078			}
1079			CFRelease(blackListedKeys);
1080		}
1081	}
1082}
1083
1084static void SecPolicyCheckGrayListedLeaf(SecPVCRef pvc, CFStringRef key)
1085{
1086	SecOTAPKIRef otapkiRef = SecOTAPKICopyCurrentOTAPKIRef();
1087	if (NULL != otapkiRef)
1088	{
1089		CFSetRef grayListedKeys = SecOTAPKICopyGrayList(otapkiRef);
1090		CFRelease(otapkiRef);
1091		if (NULL != grayListedKeys)
1092		{
1093			SecCertificateRef cert = SecPVCGetCertificateAtIndex(pvc, 0);
1094
1095			CFDataRef dgst = SecCertificateCopyPublicKeySHA1Digest(cert);
1096			if (dgst)
1097			{
1098				/* Check dgst against gray. */
1099				if (CFSetContainsValue(grayListedKeys, dgst))
1100				{
1101					SecPVCSetResult(pvc, key, 0, kCFBooleanFalse);
1102				}
1103				CFRelease(dgst);
1104			}
1105			CFRelease(grayListedKeys);
1106		}
1107	}
1108 }
1109
1110static void SecPolicyCheckLeafMarkerOid(SecPVCRef pvc, CFStringRef key)
1111{
1112	SecCertificateRef cert = SecPVCGetCertificateAtIndex(pvc, 0);
1113    SecPolicyRef policy = SecPVCGetPolicy(pvc);
1114    CFTypeRef value = CFDictionaryGetValue(policy->_options, key);
1115
1116    if (value && SecCertificateHasMarkerExtension(cert, value))
1117        return;
1118
1119    SecPVCSetResult(pvc, key, 0, kCFBooleanFalse);
1120}
1121
1122static void SecPolicyCheckIntermediateMarkerOid(SecPVCRef pvc, CFStringRef key)
1123{
1124    CFIndex ix, count = SecPVCGetCertificateCount(pvc);
1125    SecPolicyRef policy = SecPVCGetPolicy(pvc);
1126    CFTypeRef value = CFDictionaryGetValue(policy->_options, key);
1127
1128    for (ix = 1; ix < count - 1; ix++) {
1129        SecCertificateRef cert = SecPVCGetCertificateAtIndex(pvc, ix);
1130        if (SecCertificateHasMarkerExtension(cert, value))
1131            return;
1132    }
1133    SecPVCSetResult(pvc, key, 0, kCFBooleanFalse);
1134}
1135
1136
1137
1138/****************************************************************************
1139 *********************** New rfc5280 Chain Validation ***********************
1140 ****************************************************************************/
1141
1142#if 0
1143typedef struct cert_path *cert_path_t;
1144struct cert_path {
1145    int length;
1146};
1147
1148typedef struct x500_name *x500_name_t;
1149struct x500_name {
1150};
1151
1152typedef struct algorithm_id *algorithm_id_t;
1153struct algorithm_id {
1154    oid_t algorithm_oid;
1155    der_t parameters;
1156};
1157
1158typedef struct trust_anchor *trust_anchor_t;
1159struct trust_anchor {
1160    x500_name_t issuer_name;
1161    algorithm_id_t public_key_algorithm; /* includes optional params */
1162    SecKeyRef public_key;
1163};
1164
1165typedef struct certificate_policy *certificate_policy_t;
1166struct certificate_policy {
1167    policy_qualifier_t qualifiers;
1168    oid_t oid;
1169    SLIST_ENTRY(certificate_policy) policies;
1170};
1171
1172typedef struct policy_mapping *policy_mapping_t;
1173struct policy_mapping {
1174    SLIST_ENTRY(policy_mapping) mappings;
1175    oid_t issuer_domain_policy;
1176    oid_t subject_domain_policy;
1177};
1178
1179typedef struct root_name *root_name_t;
1180struct root_name {
1181};
1182#endif
1183
1184struct policy_tree_add_ctx {
1185    oid_t p_oid;
1186    policy_qualifier_t p_q;
1187};
1188
1189/* For each node of depth i-1 in the valid_policy_tree where P-OID is in the expected_policy_set, create a child node as follows: set the valid_policy to P-OID, set the qualifier_set to P-Q, and set the expected_policy_set to {P-OID}. */
1190static bool policy_tree_add_if_match(policy_tree_t node, void *ctx) {
1191    struct policy_tree_add_ctx *info = (struct policy_tree_add_ctx *)ctx;
1192    policy_set_t policy_set;
1193    for (policy_set = node->expected_policy_set;
1194        policy_set;
1195        policy_set = policy_set->oid_next) {
1196        if (oid_equal(policy_set->oid, info->p_oid)) {
1197            policy_tree_add_child(node, &info->p_oid, info->p_q);
1198            return true;
1199        }
1200    }
1201    return false;
1202}
1203
1204/* If the valid_policy_tree includes a node of depth i-1 with the valid_policy anyPolicy, generate a child node with the following values: set the valid_policy to P-OID, set the qualifier_set to P-Q, and set the expected_policy_set to {P-OID}. */
1205static bool policy_tree_add_if_any(policy_tree_t node, void *ctx) {
1206    struct policy_tree_add_ctx *info = (struct policy_tree_add_ctx *)ctx;
1207    if (oid_equal(node->valid_policy, oidAnyPolicy)) {
1208        policy_tree_add_child(node, &info->p_oid, info->p_q);
1209        return true;
1210    }
1211    return false;
1212}
1213
1214/* Return true iff node has a child with a valid_policy equal to oid. */
1215static bool policy_tree_has_child_with_oid(policy_tree_t node,
1216    const oid_t *oid) {
1217    policy_tree_t child;
1218    for (child = node->children; child; child = child->siblings) {
1219        if (oid_equal(child->valid_policy, (*oid))) {
1220            return true;
1221        }
1222    }
1223    return false;
1224}
1225
1226/* For each node in the valid_policy_tree of depth i-1, for each value in the expected_policy_set (including anyPolicy) that does not appear in a child node, create a child node with the following values: set the valid_policy to the value from the expected_policy_set in the parent node, set the qualifier_set to AP-Q, and set the expected_policy_set to the value in the valid_policy from this node. */
1227static bool policy_tree_add_expected(policy_tree_t node, void *ctx) {
1228    policy_qualifier_t p_q = (policy_qualifier_t)ctx;
1229    policy_set_t policy_set;
1230    bool added_node = false;
1231    for (policy_set = node->expected_policy_set;
1232        policy_set;
1233        policy_set = policy_set->oid_next) {
1234        if (!policy_tree_has_child_with_oid(node, &policy_set->oid)) {
1235            policy_tree_add_child(node, &policy_set->oid, p_q);
1236            added_node = true;
1237        }
1238    }
1239    return added_node;
1240}
1241
1242#if 0
1243/* For each node where ID-P is the valid_policy, set expected_policy_set to the set of subjectDomainPolicy values that are specified as equivalent to ID-P by the policy mappings extension. */
1244static bool policy_tree_map(policy_tree_t node, void *ctx) {
1245    /* Can't map oidAnyPolicy. */
1246    if (oid_equal(node->valid_policy, oidAnyPolicy))
1247        return false;
1248
1249    const SecCEPolicyMappings *pm = (const SecCEPolicyMappings *)ctx;
1250    uint32_t mapping_ix, mapping_count = pm->numMappings;
1251    policy_set_t policy_set = NULL;
1252    /* First count how many mappings match this nodes valid_policy. */
1253    for (mapping_ix = 0; mapping_ix < mapping_count; ++mapping_ix) {
1254        const SecCEPolicyMapping *mapping = &pm->mappings[mapping_ix];
1255        if (oid_equal(node->valid_policy, mapping->issuerDomainPolicy)) {
1256            policy_set_t p_node = (policy_set_t)malloc(sizeof(*policy_set));
1257            p_node->oid = mapping->subjectDomainPolicy;
1258            p_node->oid_next = policy_set ? policy_set : NULL;
1259            policy_set = p_node;
1260        }
1261    }
1262    if (policy_set) {
1263        policy_tree_set_expected_policy(node, policy_set);
1264        return true;
1265    }
1266    return false;
1267}
1268#endif
1269
1270#define POLICY_MAPPING 0
1271#define POLICY_SUBTREES 0
1272
1273/* rfc5280 basic cert processing. */
1274static void SecPolicyCheckBasicCertificateProcessing(SecPVCRef pvc,
1275	CFStringRef key) {
1276    /* Inputs */
1277    //cert_path_t path;
1278    CFIndex count = SecPVCGetCertificateCount(pvc);
1279    /* 64 bits cast: worst case here is we truncate the number of cert, and the validation may fail */
1280    assert((unsigned long)count<=UINT32_MAX); /* Debug check. Correct as long as CFIndex is long */
1281    uint32_t n = (uint32_t)count;
1282    bool is_anchored = SecPVCIsAnchored(pvc);
1283    if (is_anchored) {
1284        /* If the anchor is trusted we don't procces the last cert in the
1285           chain (root). */
1286        n--;
1287    } else {
1288        /* Add a detail for the root not being trusted. */
1289        if (SecPVCSetResultForced(pvc, kSecPolicyCheckAnchorTrusted,
1290            n - 1, kCFBooleanFalse, true))
1291            return;
1292    }
1293
1294    CFAbsoluteTime verify_time = SecPVCGetVerifyTime(pvc);
1295    //policy_set_t user_initial_policy_set = NULL;
1296    //trust_anchor_t anchor;
1297    bool initial_policy_mapping_inhibit = false;
1298    bool initial_explicit_policy = false;
1299    bool initial_any_policy_inhibit = false;
1300#if POLICY_SUBTREES
1301    root_name_t initial_permitted_subtrees = NULL;
1302    root_name_t initial_excluded_subtrees = NULL;
1303#endif
1304
1305    /* Initialization */
1306    pvc->valid_policy_tree = policy_tree_create(&oidAnyPolicy, NULL);
1307#if POLICY_SUBTREES
1308    root_name_t permitted_subtrees = initial_permitted_subtrees;
1309    root_name_t excluded_subtrees = initial_excluded_subtrees;
1310#endif
1311    uint32_t explicit_policy = initial_explicit_policy ? 0 : n + 1;
1312    uint32_t inhibit_any_policy = initial_any_policy_inhibit ? 0 : n + 1;
1313    uint32_t policy_mapping = initial_policy_mapping_inhibit ? 0 : n + 1;
1314
1315#if 0
1316    /* Path builder ensures we only get cert chains with proper issuer
1317       chaining with valid signatures along the way. */
1318    algorithm_id_t working_public_key_algorithm = anchor->public_key_algorithm;
1319    SecKeyRef working_public_key = anchor->public_key;
1320    x500_name_t working_issuer_name = anchor->issuer_name;
1321#endif
1322    uint32_t i, max_path_length = n;
1323    SecCertificateRef cert = NULL;
1324    for (i = 1; i <= n; ++i) {
1325        /* Process Cert */
1326        cert = SecPVCGetCertificateAtIndex(pvc, n - i);
1327        bool is_self_issued = SecPVCIsCertificateAtIndexSelfSigned(pvc, n - i);
1328
1329        /* (a) Verify the basic certificate information. */
1330        /* @@@ Ensure that cert was signed with working_public_key_algorithm
1331           using the working_public_key and the working_public_key_parameters. */
1332#if 1
1333        /* Already done by chain builder. */
1334        if (!SecCertificateIsValid(cert, verify_time)) {
1335            CFStringRef fail_key = i == n ? kSecPolicyCheckValidLeaf : kSecPolicyCheckValidIntermediates;
1336            if (!SecPVCSetResult(pvc, fail_key, n - i, kCFBooleanFalse))
1337                return;
1338        }
1339#endif
1340#if 0
1341        /* Check revocation status if the certificate asks for it. */
1342        CFArrayRef ocspResponders = SecCertificateGetOCSPResponders(cert);
1343        if (ocspResponders) {
1344            SecPVCSetCheckRevocation(pvc);
1345        }
1346#endif
1347        /* @@@ cert.issuer == working_issuer_name. */
1348
1349#if POLICY_SUBTREES
1350        /* (b) (c) */
1351        if (!is_self_issued || i == n) {
1352            /* Verify that the subject name is within one of the permitted_subtrees for X.500 distinguished names, and verify that each of the alternative names in the subjectAltName extension (critical or non-critical) is within one of the permitted_subtrees for that name type. */
1353            /* Verify that the subject name is not within any of the excluded_subtrees for X.500 distinguished names, and verify that each of the alternative names in the subjectAltName extension (critical or non-critical) is not within any of the excluded_subtrees for that name type. */
1354        }
1355#endif
1356        /* (d) */
1357        if (pvc->valid_policy_tree) {
1358            const SecCECertificatePolicies *cp =
1359                SecCertificateGetCertificatePolicies(cert);
1360            size_t policy_ix, policy_count = cp ? cp->numPolicies : 0;
1361            for (policy_ix = 0; policy_ix < policy_count; ++policy_ix) {
1362                const SecCEPolicyInformation *policy = &cp->policies[policy_ix];
1363                oid_t p_oid = policy->policyIdentifier;
1364                policy_qualifier_t p_q = &policy->policyQualifiers;
1365                struct policy_tree_add_ctx ctx = { p_oid, p_q };
1366                if (!oid_equal(p_oid, oidAnyPolicy)) {
1367                    if (!policy_tree_walk_depth(pvc->valid_policy_tree, i - 1,
1368                        policy_tree_add_if_match, &ctx)) {
1369                        policy_tree_walk_depth(pvc->valid_policy_tree, i - 1,
1370                        policy_tree_add_if_any, &ctx);
1371                    }
1372                }
1373            }
1374            /* The certificate policies extension includes the policy
1375               anyPolicy with the qualifier set AP-Q and either
1376               (a) inhibit_anyPolicy is greater than 0 or
1377               (b) i < n and the certificate is self-issued. */
1378            if (inhibit_any_policy > 0 || (i < n && is_self_issued)) {
1379                for (policy_ix = 0; policy_ix < policy_count; ++policy_ix) {
1380                    const SecCEPolicyInformation *policy = &cp->policies[policy_ix];
1381                    oid_t p_oid = policy->policyIdentifier;
1382                    policy_qualifier_t p_q = &policy->policyQualifiers;
1383                    if (oid_equal(p_oid, oidAnyPolicy)) {
1384                        policy_tree_walk_depth(pvc->valid_policy_tree, i - 1,
1385                            policy_tree_add_expected, (void *)p_q);
1386                    }
1387                }
1388            }
1389            policy_tree_prune_childless(&pvc->valid_policy_tree, i - 1);
1390            /* (e) */
1391            if (!cp) {
1392                if (pvc->valid_policy_tree)
1393                    policy_tree_prune(&pvc->valid_policy_tree);
1394            }
1395        }
1396        /* (f) Verify that either explicit_policy is greater than 0 or the
1397           valid_policy_tree is not equal to NULL. */
1398        if (!pvc->valid_policy_tree && explicit_policy == 0) {
1399            /* valid_policy_tree is empty and explicit policy is 0, illegal. */
1400            if (!SecPVCSetResultForced(pvc, key /* @@@ Need custom key */, n - i, kCFBooleanFalse, true))
1401                return;
1402        }
1403        /* If Last Cert in Path */
1404        if (i == n)
1405            break;
1406
1407        /* Prepare for Next Cert */
1408#if POLICY_MAPPING
1409        /* (a) verify that anyPolicy does not appear as an
1410           issuerDomainPolicy or a subjectDomainPolicy */
1411        CFDictionaryRef pm = SecCertificateGetPolicyMappings(cert);
1412        if (pm) {
1413            uint32_t mapping_ix, mapping_count = pm->numMappings;
1414            for (mapping_ix = 0; mapping_ix < mapping_count; ++mapping_ix) {
1415                const SecCEPolicyMapping *mapping = &pm->mappings[mapping_ix];
1416                if (oid_equal(mapping->issuerDomainPolicy, oidAnyPolicy)
1417                    || oid_equal(mapping->subjectDomainPolicy, oidAnyPolicy)) {
1418                    /* Policy mapping uses anyPolicy, illegal. */
1419                    if (!SecPVCSetResultForced(pvc, key /* @@@ Need custom key */, n - i, kCFBooleanFalse))
1420                        return;
1421                }
1422            }
1423            /* (b) */
1424            /* (1) If the policy_mapping variable is greater than 0 */
1425            if (policy_mapping > 0) {
1426                if (!policy_tree_walk_depth(pvc->valid_policy_tree, i,
1427                    policy_tree_map, (void *)pm)) {
1428                        /* If no node of depth i in the valid_policy_tree has a valid_policy of ID-P but there is a node of depth i with a valid_policy of anyPolicy, then generate a child node of the node of depth i-1 that has a valid_policy of anyPolicy as follows:
1429
1430            (i)    set the valid_policy to ID-P;
1431
1432            (ii)   set the qualifier_set to the qualifier set of the
1433                   policy anyPolicy in the certificate policies
1434                   extension of certificate i; and
1435    (iii) set the expected_policy_set to the set of subjectDomainPolicy values that are specified as equivalent to ID-P by the policy mappings extension. */
1436                    }
1437            } else {
1438    #if 0
1439                /* (i)    delete each node of depth i in the valid_policy_tree
1440                   where ID-P is the valid_policy. */
1441                struct policy_tree_map_ctx ctx = { idp_oid, sdp_oid };
1442                policy_tree_walk_depth(pvc->valid_policy_tree, i,
1443                    policy_tree_delete_if_match, &ctx);
1444    #endif
1445                /* (ii)   If there is a node in the valid_policy_tree of depth
1446                   i-1 or less without any child nodes, delete that
1447                   node.  Repeat this step until there are no nodes of
1448                   depth i-1 or less without children. */
1449                policy_tree_prune_childless(&pvc->valid_policy_tree, i - 1);
1450            }
1451        }
1452#endif /* POLICY_MAPPING */
1453        /* (c)(d)(e)(f) */
1454        //working_issuer_name = SecCertificateGetNormalizedSubjectContent(cert);
1455        //working_public_key = SecCertificateCopyPublicKey(cert);
1456        //working_public_key_parameters = SecCertificateCopyPublicKeyParameters(cert);
1457        //working_public_key_algorithm = SecCertificateCopyPublicKeyAlgorithm(cert);
1458#if POLICY_SUBTREES
1459        /* (g) If a name constraints extension is included in the certificate, modify the permitted_subtrees and excluded_subtrees state variables as follows:
1460 */
1461        /* @@@ handle name constraints. */
1462#endif
1463        /* (h) */
1464        if (!is_self_issued) {
1465            if (explicit_policy)
1466                explicit_policy--;
1467            if (policy_mapping)
1468                policy_mapping--;
1469            if (inhibit_any_policy)
1470                inhibit_any_policy--;
1471        }
1472        /* (i) */
1473        const SecCEPolicyConstraints *pc =
1474            SecCertificateGetPolicyConstraints(cert);
1475        if (pc) {
1476            if (pc->requireExplicitPolicyPresent
1477                && pc->requireExplicitPolicy < explicit_policy) {
1478                explicit_policy = pc->requireExplicitPolicy;
1479            }
1480            if (pc->inhibitPolicyMappingPresent
1481                && pc->inhibitPolicyMapping < policy_mapping) {
1482                policy_mapping = pc->inhibitPolicyMapping;
1483            }
1484        }
1485        /* (j) */
1486        uint32_t iap = SecCertificateGetInhibitAnyPolicySkipCerts(cert);
1487        if (iap < inhibit_any_policy) {
1488            inhibit_any_policy = iap;
1489        }
1490        /* (k) */
1491		const SecCEBasicConstraints *bc =
1492			SecCertificateGetBasicConstraints(cert);
1493#if 0 /* Checked in chain builder pre signature verify already. */
1494        if (!bc || !bc->isCA) {
1495            /* Basic constraints not present or not marked as isCA, illegal. */
1496            if (!SecPVCSetResult(pvc, kSecPolicyCheckBasicContraints,
1497                n - i, kCFBooleanFalse))
1498                return;
1499        }
1500#endif
1501        /* (l) */
1502        if (!is_self_issued) {
1503            if (max_path_length > 0) {
1504                max_path_length--;
1505            } else {
1506                /* max_path_len exceeded, illegal. */
1507                if (!SecPVCSetResult(pvc, kSecPolicyCheckBasicContraints,
1508                    n - i, kCFBooleanFalse))
1509                    return;
1510            }
1511        }
1512        /* (m) */
1513        if (bc && bc->pathLenConstraintPresent
1514            && bc->pathLenConstraint < max_path_length) {
1515            max_path_length = bc->pathLenConstraint;
1516        }
1517#if 0 /* Checked in chain builder pre signature verify already. */
1518        /* (n) If a key usage extension is present, verify that the keyCertSign bit is set. */
1519        SecKeyUsage keyUsage = SecCertificateGetKeyUsage(cert);
1520        if (keyUsage && !(keyUsage & kSecKeyUsageKeyCertSign)) {
1521            if (!SecPVCSetResultForced(pvc, kSecPolicyCheckKeyUsage,
1522                n - i, kCFBooleanFalse, true))
1523                return;
1524        }
1525#endif
1526        /* (o) Recognize and process any other critical extension present in the certificate. Process any other recognized non-critical extension present in the certificate that is relevant to path processing. */
1527        if (SecCertificateHasUnknownCriticalExtension(cert)) {
1528			/* Certificate contains one or more unknown critical extensions. */
1529			if (!SecPVCSetResult(pvc, kSecPolicyCheckCriticalExtensions,
1530                n - i, kCFBooleanFalse))
1531				return;
1532		}
1533    }
1534    /* Wrap up */
1535    cert = SecPVCGetCertificateAtIndex(pvc, 0);
1536    /* (a) */
1537    if (explicit_policy)
1538        explicit_policy--;
1539    /* (b) */
1540    const SecCEPolicyConstraints *pc = SecCertificateGetPolicyConstraints(cert);
1541    if (pc) {
1542        if (pc->requireExplicitPolicyPresent
1543            && pc->requireExplicitPolicy == 0) {
1544            explicit_policy = 0;
1545        }
1546    }
1547    /* (c) */
1548    //working_public_key = SecCertificateCopyPublicKey(cert);
1549    /* (d) */
1550    /* If the subjectPublicKeyInfo field of the certificate contains an algorithm field with null parameters or parameters are omitted, compare the certificate subjectPublicKey algorithm to the working_public_key_algorithm. If the certificate subjectPublicKey algorithm and the
1551working_public_key_algorithm are different, set the working_public_key_parameters to null. */
1552    //working_public_key_parameters = SecCertificateCopyPublicKeyParameters(cert);
1553    /* (e) */
1554    //working_public_key_algorithm = SecCertificateCopyPublicKeyAlgorithm(cert);
1555    /* (f) Recognize and process any other critical extension present in the certificate n. Process any other recognized non-critical extension present in certificate n that is relevant to path processing. */
1556    if (SecCertificateHasUnknownCriticalExtension(cert)) {
1557        /* Certificate contains one or more unknown critical extensions. */
1558        if (!SecPVCSetResult(pvc, kSecPolicyCheckCriticalExtensions,
1559                             0, kCFBooleanFalse))
1560            return;
1561    }
1562    /* (g) Calculate the intersection of the valid_policy_tree and the user-initial-policy-set, as follows */
1563
1564    if (pvc->valid_policy_tree) {
1565#if !defined(NDEBUG)
1566        policy_tree_dump(pvc->valid_policy_tree);
1567#endif
1568        /* (g3c4) */
1569        //policy_tree_prune_childless(&pvc->valid_policy_tree, n - 1);
1570    }
1571
1572    /* If either (1) the value of explicit_policy variable is greater than
1573       zero or (2) the valid_policy_tree is not NULL, then path processing
1574       has succeeded. */
1575    if (!pvc->valid_policy_tree && explicit_policy == 0) {
1576        /* valid_policy_tree is empty and explicit policy is 0, illegal. */
1577        if (!SecPVCSetResultForced(pvc, key /* @@@ Need custom key */, 0, kCFBooleanFalse, true))
1578            return;
1579    }
1580}
1581
1582static policy_set_t policies_for_cert(SecCertificateRef cert) {
1583    policy_set_t policies = NULL;
1584    const SecCECertificatePolicies *cp =
1585        SecCertificateGetCertificatePolicies(cert);
1586    size_t policy_ix, policy_count = cp ? cp->numPolicies : 0;
1587    for (policy_ix = 0; policy_ix < policy_count; ++policy_ix) {
1588        policy_set_add(&policies, &cp->policies[policy_ix].policyIdentifier);
1589    }
1590    return policies;
1591}
1592
1593static void SecPolicyCheckEV(SecPVCRef pvc,
1594	CFStringRef key) {
1595	CFIndex ix, count = SecPVCGetCertificateCount(pvc);
1596    policy_set_t valid_policies = NULL;
1597
1598	for (ix = 0; ix < count; ++ix) {
1599		SecCertificateRef cert = SecPVCGetCertificateAtIndex(pvc, ix);
1600        policy_set_t policies = policies_for_cert(cert);
1601        if (ix == 0) {
1602            /* Subscriber */
1603            /* anyPolicy in the leaf isn't allowed for EV, so only init
1604               valid_policies if we have real policies. */
1605            if (!policy_set_contains(policies, &oidAnyPolicy)) {
1606                valid_policies = policies;
1607                policies = NULL;
1608            }
1609        } else if (ix < count - 1) {
1610            /* Subordinate CA */
1611            if (!SecPolicySubordinateCACertificateCouldBeEV(cert)) {
1612                secdebug("ev", "subordinate certificate is not ev");
1613                if (SecPVCSetResultForced(pvc, key,
1614                    ix, kCFBooleanFalse, true)) {
1615                    policy_set_free(valid_policies);
1616                    policy_set_free(policies);
1617                    return;
1618                }
1619            }
1620            policy_set_intersect(&valid_policies, policies);
1621        } else {
1622            /* Root CA */
1623            if (!SecPolicyRootCACertificateIsEV(cert, valid_policies)) {
1624                secdebug("ev", "anchor certificate is not ev");
1625                if (SecPVCSetResultForced(pvc, key,
1626                    ix, kCFBooleanFalse, true)) {
1627                    policy_set_free(valid_policies);
1628                    policy_set_free(policies);
1629                    return;
1630                }
1631            }
1632        }
1633        policy_set_free(policies);
1634        if (!valid_policies) {
1635            secdebug("ev", "valid_policies set is empty: chain not ev");
1636            /* If we ever get into a state where no policies are valid anymore
1637               this can't be an ev chain. */
1638            if (SecPVCSetResultForced(pvc, key,
1639                ix, kCFBooleanFalse, true)) {
1640                return;
1641            }
1642        }
1643	}
1644
1645    policy_set_free(valid_policies);
1646
1647    /* (a) EV Subscriber Certificates   Each EV Certificate issued by the CA to a
1648Subscriber MUST contain an OID defined by the CA in the certificate’s
1649certificatePolicies extension that: (i) indicates which CA policy statement relates
1650to that certificate, (ii) asserts the CA’s adherence to and compliance with these
1651Guidelines, and (iii), by pre-agreement with the Application Software Vendor,
1652marks the certificate as being an EV Certificate.
1653(b) EV Subordinate CA Certificates
1654(1) Certificates issued to Subordinate CAs that are not controlled by the issuing
1655CA MUST contain one or more OIDs defined by the issuing CA that
1656explicitly identify the EV Policies that are implemented by the Subordinate
1657CA;
1658(2) Certificates issued to Subordinate CAs that are controlled by the Root CA
1659MAY contain the special anyPolicy OID (2.5.29.32.0).
1660(c) Root CA Certificates  Root CA Certificates SHOULD NOT contain the
1661certificatePolicies or extendedKeyUsage extensions.
1662*/
1663}
1664
1665
1666static void SecPolicyCheckCertificatePolicyOid(SecPVCRef pvc, CFStringRef key)
1667{
1668	CFIndex ix, count = SecPVCGetCertificateCount(pvc);
1669    SecPolicyRef policy = SecPVCGetPolicy(pvc);
1670    CFTypeRef value = CFDictionaryGetValue(policy->_options, key);
1671	DERItem	key_value;
1672	key_value.data = NULL;
1673	key_value.length = 0;
1674
1675	if (CFGetTypeID(value) == CFDataGetTypeID())
1676	{
1677		CFDataRef key_data = (CFDataRef)value;
1678		key_value.data = (DERByte *)CFDataGetBytePtr(key_data);
1679		key_value.length = (DERSize)CFDataGetLength(key_data);
1680
1681		for (ix = 0; ix < count; ix++) {
1682	        SecCertificateRef cert = SecPVCGetCertificateAtIndex(pvc, ix);
1683            policy_set_t policies = policies_for_cert(cert);
1684
1685			if (policy_set_contains(policies, &key_value)) {
1686				return;
1687			}
1688		}
1689		SecPVCSetResult(pvc, key, 0, kCFBooleanFalse);
1690	}
1691}
1692
1693
1694static void SecPolicyCheckRevocation(SecPVCRef pvc,
1695	CFStringRef key) {
1696    SecPVCSetCheckRevocation(pvc);
1697}
1698
1699static void SecPolicyCheckNoNetworkAccess(SecPVCRef pvc,
1700	CFStringRef key) {
1701    SecPathBuilderSetCanAccessNetwork(pvc->builder, false);
1702}
1703
1704// MARK: -
1705// MARK: SecRVCRef
1706/********************************************************
1707 ****************** SecRVCRef Functions *****************
1708 ********************************************************/
1709
1710/* Revocation verification context. */
1711struct OpaqueSecRVC {
1712    /* Will contain the response data. */
1713    asynchttp_t http;
1714
1715    /* Pointer to the pvc for this revocation check. */
1716    SecPVCRef pvc;
1717
1718    /* The ocsp request we send to each responder. */
1719    SecOCSPRequestRef ocspRequest;
1720
1721    /* Index of cert in pvc that this RVC is for 0 = leaf, etc. */
1722    CFIndex certIX;
1723
1724    /* Index in array returned by SecCertificateGetOCSPResponders() for current
1725       responder. */
1726    CFIndex responderIX;
1727
1728    /* URL of current responder. */
1729    CFURLRef responder;
1730
1731    /* Date until which this revocation status is valid. */
1732    CFAbsoluteTime nextUpdate;
1733
1734    bool done;
1735};
1736typedef struct OpaqueSecRVC *SecRVCRef;
1737
1738static void SecRVCDelete(SecRVCRef rvc) {
1739    secdebug("alloc", "%p", rvc);
1740    asynchttp_free(&rvc->http);
1741    SecOCSPRequestFinalize(rvc->ocspRequest);
1742}
1743
1744/* Return the next responder we should contact for this rvc or NULL if we
1745   exhausted them all. */
1746static CFURLRef SecRVCGetNextResponder(SecRVCRef rvc) {
1747    SecCertificateRef cert = SecPVCGetCertificateAtIndex(rvc->pvc, rvc->certIX);
1748    CFArrayRef ocspResponders = SecCertificateGetOCSPResponders(cert);
1749    if (ocspResponders) {
1750        CFIndex responderCount = CFArrayGetCount(ocspResponders);
1751        while (rvc->responderIX < responderCount) {
1752            CFURLRef responder = CFArrayGetValueAtIndex(ocspResponders, rvc->responderIX);
1753            rvc->responderIX++;
1754            CFStringRef scheme = CFURLCopyScheme(responder);
1755            if (scheme) {
1756                /* We only support http and https responders currently. */
1757                bool valid_responder = (CFEqual(CFSTR("http"), scheme) ||
1758                                        CFEqual(CFSTR("https"), scheme));
1759                CFRelease(scheme);
1760                if (valid_responder)
1761                    return responder;
1762            }
1763        }
1764    }
1765    return NULL;
1766}
1767
1768/* Fire off an async http request for this certs revocation status, return
1769   false if request was queued, true if we're done. */
1770static bool SecRVCFetchNext(SecRVCRef rvc) {
1771    while ((rvc->responder = SecRVCGetNextResponder(rvc))) {
1772        CFDataRef request = SecOCSPRequestGetDER(rvc->ocspRequest);
1773        if (!request)
1774            goto errOut;
1775
1776        if (!asyncHttpPost(rvc->responder, request, &rvc->http)) {
1777            /* Async request was posted, wait for reply. */
1778            return false;
1779        }
1780    }
1781
1782errOut:
1783    rvc->done = true;
1784    return true;
1785}
1786
1787/* Proccess a verified ocsp response for a given cert. Return true if the
1788   certificate status was obtained. */
1789static bool SecOCSPSingleResponseProccess(SecOCSPSingleResponseRef this,
1790    SecRVCRef rvc) {
1791    bool proccessed;
1792	switch (this->certStatus) {
1793    case CS_Good:
1794        secdebug("ocsp", "CS_Good for cert %" PRIdCFIndex, rvc->certIX);
1795        /* @@@ Mark cert as valid until a given date (nextUpdate if we have one)
1796           in the info dictionary. */
1797        //cert.revokeCheckGood(true);
1798        rvc->nextUpdate = this->nextUpdate;
1799        proccessed = true;
1800        break;
1801    case CS_Revoked:
1802        secdebug("ocsp", "CS_Revoked for cert %" PRIdCFIndex, rvc->certIX);
1803        /* @@@ Mark cert as revoked (with reason) at revocation date in
1804           the info dictionary, or perhaps we should use a different key per
1805           reason?   That way a client using exceptions can ignore some but
1806           not all reasons. */
1807        SInt32 reason = this->crlReason;
1808        CFNumberRef cfreason = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &reason);
1809        SecPVCSetResultForced(rvc->pvc, kSecPolicyCheckRevocation, rvc->certIX,
1810            cfreason, true);
1811        CFRelease(cfreason);
1812        proccessed = true;
1813        break;
1814    case CS_Unknown:
1815        /* not an error, no per-cert status, nothing here */
1816        secdebug("ocsp", "CS_Unknown for cert %" PRIdCFIndex, rvc->certIX);
1817        proccessed = false;
1818        break;
1819    default:
1820        secdebug("ocsp", "BAD certStatus (%d) for cert %" PRIdCFIndex,
1821            (int)this->certStatus, rvc->certIX);
1822        proccessed = false;
1823        break;
1824	}
1825
1826	return proccessed;
1827}
1828
1829static bool SecOCSPResponseVerify(SecOCSPResponseRef ocspResponse, SecRVCRef rvc) {
1830    bool trusted;
1831    SecCertificatePathRef issuer = SecCertificatePathCopyFromParent(rvc->pvc->path, rvc->certIX + 1);
1832    SecCertificatePathRef signer = SecOCSPResponseCopySigner(ocspResponse, issuer);
1833    CFRelease(issuer);
1834
1835    if (signer) {
1836        if (signer == issuer) {
1837            /* We already know we trust issuer since it's the path we are
1838               trying to verify minus the leaf. */
1839            secdebug("ocsp", "ocsp responder: %@ response signed by issuer",
1840                rvc->responder);
1841            trusted = true;
1842        } else {
1843            secdebug("ocsp",
1844                "ocsp responder: %@ response signed by cert issued by issuer",
1845                rvc->responder);
1846            /* @@@ Now check that we trust signer. */
1847            const void *ocspSigner = SecPolicyCreateOCSPSigner();
1848            CFArrayRef policies = CFArrayCreate(kCFAllocatorDefault,
1849                &ocspSigner, 1, &kCFTypeArrayCallBacks);
1850            CFRelease(ocspSigner);
1851            CFAbsoluteTime verifyTime = SecOCSPResponseVerifyTime(ocspResponse);
1852            struct OpaqueSecPVC ospvc;
1853            SecPVCInit(&ospvc, rvc->pvc->builder, policies, verifyTime);
1854            CFRelease(policies);
1855            SecPVCSetPath(&ospvc, signer, NULL);
1856            SecPVCLeafChecks(&ospvc);
1857            if (ospvc.result) {
1858                bool completed = SecPVCPathChecks(&ospvc);
1859                /* If completed is false we are waiting for a callback, this
1860                   shouldn't happen since we aren't asking for details, no
1861                   revocation checking is done. */
1862                if (!completed) {
1863                    ocspdErrorLog("SecPVCPathChecks unexpectedly started "
1864                        "background job!");
1865                    /* @@@ assert() or abort here perhaps? */
1866                }
1867            }
1868            if (ospvc.result) {
1869                secdebug("ocsp", "response satisfies ocspSigner policy (%@)",
1870                    rvc->responder);
1871                trusted = true;
1872            } else {
1873                /* @@@ We don't trust the cert so don't use this response. */
1874                ocspdErrorLog("ocsp response signed by certificate which "
1875                    "does not satisfy ocspSigner policy");
1876                trusted = false;
1877            }
1878            SecPVCDelete(&ospvc);
1879        }
1880
1881        CFRelease(signer);
1882    } else {
1883        /* @@@ No signer found for this ocsp response, discard it. */
1884        secdebug("ocsp", "ocsp responder: %@ no signer found for response",
1885            rvc->responder);
1886        trusted = false;
1887    }
1888
1889#if DUMP_OCSPRESPONSES
1890    char buf[40];
1891    snprintf(buf, 40, "/tmp/ocspresponse%ld%s.der",
1892        rvc->certIX, (trusted ? "t" : "u"));
1893    secdumpdata(ocspResponse->data, buf);
1894#endif
1895
1896    return trusted;
1897}
1898
1899/* Callback from async http code after an ocsp response has been received. */
1900static void SecOCSPFetchCompleted(asynchttp_t *http, CFTimeInterval maxAge) {
1901    SecRVCRef rvc = (SecRVCRef)http->info;
1902    SecPVCRef pvc = rvc->pvc;
1903    SecOCSPResponseRef ocspResponse = NULL;
1904    if (http->response) {
1905        CFDataRef data = CFHTTPMessageCopyBody(http->response);
1906        if (data) {
1907            /* Parse the returned data as if it's an ocspResponse. */
1908            ocspResponse = SecOCSPResponseCreate(data, maxAge);
1909            CFRelease(data);
1910        }
1911    }
1912
1913    if (ocspResponse) {
1914        SecOCSPResponseStatus orStatus = SecOCSPGetResponseStatus(ocspResponse);
1915        if (orStatus == kSecOCSPSuccess) {
1916            SecOCSPSingleResponseRef sr =
1917                SecOCSPResponseCopySingleResponse(ocspResponse, rvc->ocspRequest);
1918            if (!sr) {
1919                /* The ocsp response didn't have a singleResponse for the cert
1920                   we are looking for, let's try the next responder. */
1921                secdebug("ocsp",
1922                    "ocsp responder: %@ did not include status of requested cert",
1923                    rvc->responder);
1924            } else {
1925                /* We got a singleResponse for the cert we are interested in,
1926                   let's proccess it. */
1927                /* @@@ If the responder doesn't have the ocsp-nocheck extension
1928                   we should check whether the leaf was revoked (we are
1929                   already checking the rest of the chain). */
1930                /* Check the OCSP response signature and verify the
1931                   response. */
1932                if (SecOCSPResponseVerify(ocspResponse, rvc)) {
1933                    secdebug("ocsp","responder: %@ sent proper response",
1934                        rvc->responder);
1935
1936                    if (SecOCSPSingleResponseProccess(sr, rvc)) {
1937                        if (rvc->nextUpdate == 0) {
1938                            rvc->nextUpdate =
1939                                SecOCSPResponseGetExpirationTime(ocspResponse);
1940                        }
1941                        /* If the singleResponse had meaningful information, we
1942                           cache the response. */
1943                        SecOCSPCacheAddResponse(ocspResponse, rvc->responder);
1944                        rvc->done = true;
1945                    }
1946                }
1947                SecOCSPSingleResponseDestroy(sr);
1948            }
1949        } else {
1950            /* ocsp response not ok.  Let's try next responder. */
1951            secdebug("ocsp", "responder: %@ returned status: %d",
1952                rvc->responder, orStatus);
1953#if 0
1954            if (!SecPVCSetResultForced(pvc, kSecPolicyCheckRevocation,
1955                rvc->certIX, kCFBooleanFalse, true))
1956                return;
1957#endif
1958        }
1959        SecOCSPResponseFinalize(ocspResponse);
1960    }
1961
1962    if (!rvc->done) {
1963        /* Clear the data for the next response. */
1964        asynchttp_free(http);
1965        SecRVCFetchNext(rvc);
1966    }
1967
1968    if (rvc->done) {
1969        SecRVCDelete(rvc);
1970        if (!--pvc->asyncJobCount) {
1971            SecPathBuilderStep(pvc->builder);
1972        }
1973    }
1974}
1975
1976static void SecRVCInit(SecRVCRef rvc, SecPVCRef pvc, CFIndex certIX) {
1977    secdebug("alloc", "%p", rvc);
1978    rvc->pvc = pvc;
1979    rvc->certIX = certIX;
1980    rvc->http.queue = SecPathBuilderGetQueue(pvc->builder);
1981    rvc->http.completed = SecOCSPFetchCompleted;
1982    rvc->http.info = rvc;
1983    rvc->ocspRequest = NULL;
1984    rvc->responderIX = 0;
1985    rvc->responder = NULL;
1986    rvc->nextUpdate = 0;
1987    rvc->done = false;
1988}
1989
1990
1991static bool SecPVCCheckRevocation(SecPVCRef pvc) {
1992    secdebug("ocsp", "checking revocation");
1993	CFIndex certIX, certCount = SecPVCGetCertificateCount(pvc);
1994    bool completed = true;
1995    if (certCount <= 1) {
1996		/* Can't verify without an issuer; we're done */
1997        return completed;
1998    }
1999    if (!SecPVCIsAnchored(pvc)) {
2000        /* We can't check revocation for chains without a trusted anchor. */
2001        return completed;
2002    }
2003    certCount--;
2004
2005#if 0
2006    /* @@@ Implement getting this value from the client.
2007       Optional responder passed in though policy. */
2008    CFURLRef localResponder = NULL;
2009    /* Generate a nonce in outgoing request if true. */
2010	bool genNonce = false;
2011    /* Require a nonce in response if true. */
2012	bool requireRespNonce = false;
2013	bool cacheReadDisable = false;
2014	bool cacheWriteDisable = false;
2015#endif
2016
2017    if (pvc->rvcs) {
2018        /* We have done revocation checking already, we're done. */
2019        secdebug("ocsp", "Not rechecking revocation");
2020        return completed;
2021    }
2022
2023    /* Setup things so we check revocation status of all certs except the
2024       anchor. */
2025    pvc->rvcs = calloc(sizeof(struct OpaqueSecRVC), certCount);
2026
2027#if 0
2028    /* Lookup cached revocation data for each certificate. */
2029	for (certIX = 0; certIX < certCount; ++certIX) {
2030		SecCertificateRef cert = SecPVCGetCertificateAtIndex(rvc->pvc, rvc->certIX);
2031        CFArrayRef ocspResponders = SecCertificateGetOCSPResponders(cert);
2032		if (ocspResponders) {
2033            /* First look though passed in ocsp responses. */
2034            //SecPVCGetOCSPResponseForCertificateAtIndex(pvc, ix, singleResponse);
2035
2036            /* Then look though shared cache (we don't care which responder
2037               something came from here). */
2038            CFDataRef ocspResponse = SecOCSPCacheCopyMatching(SecCertIDRef certID, NULL);
2039
2040            /* Now let's parse the response. */
2041            if (decodeOCSPResponse(ocspResp)) {
2042                secdebug("ocsp", "response ok: %@", ocspResp);
2043            } else {
2044                secdebug("ocsp", "response bad: %@", ocspResp);
2045                /* ocsp response not ok. */
2046                if (!SecPVCSetResultForced(pvc, key, ix, kCFBooleanFalse, true))
2047                    return completed;
2048            }
2049            CFReleaseSafe(ocspResp);
2050		} else {
2051            /* Check if certificate has any crl distributionPoints. */
2052            CFArrayRef distributionPoints = SecCertificateGetCRLDistributionPoints(cert);
2053            if (distributionPoints) {
2054                /* Look for a cached CRL and potentially delta CRL for this certificate. */
2055            }
2056        }
2057	}
2058#endif
2059
2060    /* Note that if we are multi threaded and a job completes after it
2061       is started but before we return from this function, we don't want
2062       a callback to decrement asyncJobCount to zero before we finish issuing
2063       all the jobs. To avoid this we pretend we issued certCount async jobs,
2064       and decrement pvc->asyncJobCount for each cert that we don't start a
2065       background fetch for. */
2066    pvc->asyncJobCount = (unsigned int) certCount;
2067
2068    /* Loop though certificates again and issue an ocsp fetch if the
2069       revocation status checking isn't done yet. */
2070	for (certIX = 0; certIX < certCount; ++certIX) {
2071        secdebug("ocsp", "checking revocation for cert: %ld", certIX);
2072        SecRVCRef rvc = &((SecRVCRef)pvc->rvcs)[certIX];
2073        SecRVCInit(rvc, pvc, certIX);
2074        if (rvc->done)
2075            continue;
2076
2077        SecCertificateRef cert = SecPVCGetCertificateAtIndex(rvc->pvc,
2078            rvc->certIX);
2079        /* The certIX + 1 is ok here since certCount is always at least 1
2080           less than the actual number of certs. */
2081        SecCertificateRef issuer = SecPVCGetCertificateAtIndex(rvc->pvc,
2082            rvc->certIX + 1);
2083
2084        rvc->ocspRequest = SecOCSPRequestCreate(cert, issuer);
2085        SecOCSPResponseRef ocspResponse;
2086        ocspResponse = SecOCSPCacheCopyMatching(rvc->ocspRequest, NULL);
2087        if (ocspResponse) {
2088            SecOCSPSingleResponseRef sr =
2089                SecOCSPResponseCopySingleResponse(ocspResponse, rvc->ocspRequest);
2090            if (!sr) {
2091                /* The cached ocsp response didn't have a singleResponse for
2092                   the cert we are looking for, it's shouldn't be in the cache. */
2093                secdebug("ocsp", "cached ocsp response did not include status"
2094                    " of requested cert");
2095            } else {
2096                /* We got a singleResponse for the cert we are interested in,
2097                   let's proccess it. */
2098
2099                /* @@@ If the responder doesn't have the ocsp-nocheck extension
2100                   we should check whether the leaf was revoked (we are
2101                   already checking the rest of the chain). */
2102                /* Recheck the OCSP response signature and verify the
2103                   response. */
2104                if (SecOCSPResponseVerify(ocspResponse, rvc)) {
2105                    secdebug("ocsp","cached response still has valid signature");
2106
2107                    if (SecOCSPSingleResponseProccess(sr, rvc)) {
2108                        CFAbsoluteTime expTime =
2109                            SecOCSPResponseGetExpirationTime(ocspResponse);
2110                        if (rvc->nextUpdate == 0 || expTime < rvc->nextUpdate)
2111                            rvc->nextUpdate = expTime;
2112                        rvc->done = true;
2113                    }
2114                }
2115                SecOCSPSingleResponseDestroy(sr);
2116            }
2117            SecOCSPResponseFinalize(ocspResponse);
2118        }
2119
2120        /* Unless we succefully checked the revocation status of this cert
2121           based on the cache, Attempt to fire off an async http request
2122           for this certs revocation status. */
2123        bool fetch_done = true;
2124        if (rvc->done || !SecPathBuilderCanAccessNetwork(pvc->builder) ||
2125            (fetch_done = SecRVCFetchNext(rvc))) {
2126            /* We got a cache hit or we aren't allowed to access the network,
2127               or the async http post failed. */
2128            SecRVCDelete(rvc);
2129            /* We didn't really start a background job for this cert. */
2130            pvc->asyncJobCount--;
2131        } else if (!fetch_done) {
2132            /* We started at least one background fetch. */
2133            completed = false;
2134        }
2135    }
2136
2137    /* Return false if we started any background jobs. */
2138    /* We can't just return !pvc->asyncJobCount here, since if we started any
2139       jobs the completion callback will be called eventually and it will call
2140       SecPathBuilderStep(). If for some reason everything completed before we
2141       get here we still want the outer SecPathBuilderStep() to terminate so we
2142       keep track of whether we started any jobs and return false if so. */
2143    return completed;
2144}
2145
2146
2147void SecPolicyServerInitalize(void) {
2148	gSecPolicyLeafCallbacks = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
2149		&kCFTypeDictionaryKeyCallBacks, NULL);
2150	gSecPolicyPathCallbacks = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
2151		&kCFTypeDictionaryKeyCallBacks, NULL);
2152	CFDictionaryAddValue(gSecPolicyPathCallbacks,
2153		kSecPolicyCheckBasicCertificateProcessing,
2154        SecPolicyCheckBasicCertificateProcessing);
2155	CFDictionaryAddValue(gSecPolicyPathCallbacks,
2156		kSecPolicyCheckCriticalExtensions, SecPolicyCheckCriticalExtensions);
2157	CFDictionaryAddValue(gSecPolicyPathCallbacks,
2158		kSecPolicyCheckIdLinkage, SecPolicyCheckIdLinkage);
2159	CFDictionaryAddValue(gSecPolicyLeafCallbacks,
2160		kSecPolicyCheckKeyUsage, SecPolicyCheckKeyUsage);
2161	CFDictionaryAddValue(gSecPolicyLeafCallbacks,
2162		kSecPolicyCheckExtendedKeyUsage, SecPolicyCheckExtendedKeyUsage);
2163	CFDictionaryAddValue(gSecPolicyLeafCallbacks,
2164		kSecPolicyCheckBasicContraints, SecPolicyCheckBasicContraints);
2165	CFDictionaryAddValue(gSecPolicyLeafCallbacks,
2166		kSecPolicyCheckNonEmptySubject, SecPolicyCheckNonEmptySubject);
2167	CFDictionaryAddValue(gSecPolicyLeafCallbacks,
2168		kSecPolicyCheckQualifiedCertStatements,
2169		SecPolicyCheckQualifiedCertStatements);
2170	CFDictionaryAddValue(gSecPolicyLeafCallbacks,
2171		kSecPolicyCheckSSLHostname, SecPolicyCheckSSLHostname);
2172	CFDictionaryAddValue(gSecPolicyLeafCallbacks,
2173        kSecPolicyCheckEmail, SecPolicyCheckEmail);
2174	CFDictionaryAddValue(gSecPolicyPathCallbacks,
2175		kSecPolicyCheckValidIntermediates, SecPolicyCheckValidIntermediates);
2176	CFDictionaryAddValue(gSecPolicyLeafCallbacks,
2177		kSecPolicyCheckValidLeaf, SecPolicyCheckValidLeaf);
2178	CFDictionaryAddValue(gSecPolicyPathCallbacks,
2179		kSecPolicyCheckValidRoot, SecPolicyCheckValidRoot);
2180	CFDictionaryAddValue(gSecPolicyPathCallbacks,
2181		kSecPolicyCheckIssuerCommonName, SecPolicyCheckIssuerCommonName);
2182	CFDictionaryAddValue(gSecPolicyLeafCallbacks,
2183		kSecPolicyCheckSubjectCommonNamePrefix,
2184		SecPolicyCheckSubjectCommonNamePrefix);
2185	CFDictionaryAddValue(gSecPolicyLeafCallbacks,
2186		kSecPolicyCheckSubjectCommonName,
2187		SecPolicyCheckSubjectCommonName);
2188	CFDictionaryAddValue(gSecPolicyLeafCallbacks,
2189		kSecPolicyCheckNotValidBefore,
2190		SecPolicyCheckNotValidBefore);
2191	CFDictionaryAddValue(gSecPolicyPathCallbacks,
2192		kSecPolicyCheckChainLength, SecPolicyCheckChainLength);
2193	CFDictionaryAddValue(gSecPolicyPathCallbacks,
2194		kSecPolicyCheckAnchorSHA1, SecPolicyCheckAnchorSHA1);
2195	CFDictionaryAddValue(gSecPolicyLeafCallbacks,
2196		kSecPolicyCheckSubjectOrganization,
2197		SecPolicyCheckSubjectOrganization);
2198	CFDictionaryAddValue(gSecPolicyLeafCallbacks,
2199		kSecPolicyCheckSubjectOrganizationalUnit,
2200		SecPolicyCheckSubjectOrganizationalUnit);
2201	CFDictionaryAddValue(gSecPolicyLeafCallbacks,
2202		kSecPolicyCheckEAPTrustedServerNames,
2203        SecPolicyCheckEAPTrustedServerNames);
2204	CFDictionaryAddValue(gSecPolicyLeafCallbacks,
2205		kSecPolicyCheckSubjectCommonNameTEST,
2206		SecPolicyCheckSubjectCommonNameTEST);
2207	CFDictionaryAddValue(gSecPolicyLeafCallbacks,
2208		kSecPolicyCheckRevocation,
2209		SecPolicyCheckRevocation);
2210	CFDictionaryAddValue(gSecPolicyLeafCallbacks,
2211		kSecPolicyCheckNoNetworkAccess,
2212		SecPolicyCheckNoNetworkAccess);
2213    CFDictionaryAddValue(gSecPolicyLeafCallbacks,
2214        kSecPolicyCheckBlackListedLeaf,
2215        SecPolicyCheckBlackListedLeaf);
2216	CFDictionaryAddValue(gSecPolicyLeafCallbacks,
2217        kSecPolicyCheckGrayListedLeaf,
2218        SecPolicyCheckGrayListedLeaf);
2219    CFDictionaryAddValue(gSecPolicyLeafCallbacks,
2220        kSecPolicyCheckLeafMarkerOid,
2221        SecPolicyCheckLeafMarkerOid);
2222    CFDictionaryAddValue(gSecPolicyPathCallbacks,
2223        kSecPolicyCheckIntermediateMarkerOid,
2224        SecPolicyCheckIntermediateMarkerOid);
2225	CFDictionaryAddValue(gSecPolicyLeafCallbacks,
2226		kSecPolicyCheckCertificatePolicy,
2227		SecPolicyCheckCertificatePolicyOid);
2228}
2229
2230/* AUDIT[securityd](done):
2231   array (ok) is a caller provided array, only its cf type has
2232   been checked.
2233   The options (ok) field ends up in policy->_options unchecked, so every access
2234   of policy->_options needs to be validated.
2235 */
2236static SecPolicyRef SecPolicyCreateWithArray(CFArrayRef array) {
2237    SecPolicyRef policy = NULL;
2238    require_quiet(array && CFArrayGetCount(array) == 2, errOut);
2239    CFStringRef oid = (CFStringRef)CFArrayGetValueAtIndex(array, 0);
2240    require_quiet(isString(oid), errOut);
2241    CFDictionaryRef options = (CFDictionaryRef)CFArrayGetValueAtIndex(array, 1);
2242    require_quiet(isDictionary(options), errOut);
2243    policy = SecPolicyCreate(oid, options);
2244errOut:
2245    return policy;
2246}
2247
2248/* AUDIT[securityd](done):
2249   value (ok) is an element in a caller provided array.
2250 */
2251static void deserializePolicy(const void *value, void *context) {
2252    CFArrayRef policyArray = (CFArrayRef)value;
2253    if (isArray(policyArray)) {
2254        CFTypeRef deserializedPolicy = SecPolicyCreateWithArray(policyArray);
2255        if (deserializedPolicy) {
2256            CFArrayAppendValue((CFMutableArrayRef)context, deserializedPolicy);
2257            CFRelease(deserializedPolicy);
2258        }
2259    }
2260}
2261
2262/* AUDIT[securityd](done):
2263   serializedPolicies (ok) is a caller provided array, only its cf type has
2264   been checked.
2265 */
2266CFArrayRef SecPolicyArrayDeserialize(CFArrayRef serializedPolicies) {
2267    CFMutableArrayRef result = NULL;
2268    require_quiet(isArray(serializedPolicies), errOut);
2269    CFIndex count = CFArrayGetCount(serializedPolicies);
2270    result = CFArrayCreateMutable(kCFAllocatorDefault, count, &kCFTypeArrayCallBacks);
2271    CFRange all_policies = { 0, count };
2272    CFArrayApplyFunction(serializedPolicies, all_policies, deserializePolicy, result);
2273errOut:
2274    return result;
2275}
2276
2277// MARK: -
2278// MARK: SecPVCRef
2279/********************************************************
2280 ****************** SecPVCRef Functions *****************
2281 ********************************************************/
2282
2283void SecPVCInit(SecPVCRef pvc, SecPathBuilderRef builder, CFArrayRef policies,
2284    CFAbsoluteTime verifyTime) {
2285    secdebug("alloc", "%p", pvc);
2286    // Weird logging policies crashes.
2287    //secdebug("policy", "%@", policies);
2288    pvc->builder = builder;
2289    pvc->policies = policies;
2290    if (policies)
2291        CFRetain(policies);
2292    pvc->verifyTime = verifyTime;
2293    pvc->path = NULL;
2294    pvc->details = NULL;
2295    pvc->info = NULL;
2296    pvc->valid_policy_tree = NULL;
2297    pvc->callbacks = NULL;
2298    pvc->policyIX = 0;
2299    pvc->rvcs = NULL;
2300    pvc->asyncJobCount = 0;
2301    pvc->check_revocation = false;
2302    pvc->optionally_ev = false;
2303    pvc->is_ev = false;
2304	pvc->result = true;
2305}
2306
2307static void SecPVCDeleteRVCs(SecPVCRef pvc) {
2308    secdebug("alloc", "%p", pvc);
2309    if (pvc->rvcs) {
2310        free(pvc->rvcs);
2311        pvc->rvcs = NULL;
2312    }
2313}
2314
2315void SecPVCDelete(SecPVCRef pvc) {
2316    secdebug("alloc", "%p", pvc);
2317    CFReleaseNull(pvc->policies);
2318    CFReleaseNull(pvc->details);
2319    CFReleaseNull(pvc->info);
2320    if (pvc->valid_policy_tree) {
2321        policy_tree_prune(&pvc->valid_policy_tree);
2322    }
2323    SecPVCDeleteRVCs(pvc);
2324}
2325
2326void SecPVCSetPath(SecPVCRef pvc, SecCertificatePathRef path,
2327    CFArrayRef details) {
2328    secdebug("policy", "%@", path);
2329    if (pvc->path != path) {
2330        /* Changing path makes us clear the Revocation Verification Contexts */
2331        SecPVCDeleteRVCs(pvc);
2332        pvc->path = path;
2333    }
2334    pvc->details = details;
2335    CFReleaseNull(pvc->info);
2336    if (pvc->valid_policy_tree) {
2337        policy_tree_prune(&pvc->valid_policy_tree);
2338    }
2339    pvc->policyIX = 0;
2340	pvc->result = true;
2341}
2342
2343SecPolicyRef SecPVCGetPolicy(SecPVCRef pvc) {
2344	return (SecPolicyRef)CFArrayGetValueAtIndex(pvc->policies, pvc->policyIX);
2345}
2346
2347CFIndex SecPVCGetCertificateCount(SecPVCRef pvc) {
2348	return SecCertificatePathGetCount(pvc->path);
2349}
2350
2351SecCertificateRef SecPVCGetCertificateAtIndex(SecPVCRef pvc, CFIndex ix) {
2352	return SecCertificatePathGetCertificateAtIndex(pvc->path, ix);
2353}
2354
2355bool SecPVCIsCertificateAtIndexSelfSigned(SecPVCRef pvc, CFIndex ix) {
2356    return SecCertificatePathSelfSignedIndex(pvc->path) == ix;
2357}
2358
2359void SecPVCSetCheckRevocation(SecPVCRef pvc) {
2360    pvc->check_revocation = true;
2361    secdebug("ocsp", "deferred revocation checking enabled");
2362}
2363
2364bool SecPVCIsAnchored(SecPVCRef pvc) {
2365    return SecCertificatePathIsAnchored(pvc->path);
2366}
2367
2368CFAbsoluteTime SecPVCGetVerifyTime(SecPVCRef pvc) {
2369	return pvc->verifyTime;
2370}
2371
2372/* AUDIT[securityd](done):
2373   policy->_options is a caller provided dictionary, only its cf type has
2374   been checked.
2375 */
2376bool SecPVCSetResultForced(SecPVCRef pvc,
2377	CFStringRef key, CFIndex ix, CFTypeRef result, bool force) {
2378
2379    secdebug("policy", "cert[%d]: %@ =(%s)[%s]> %@", (int) ix, key,
2380        (pvc->callbacks == gSecPolicyLeafCallbacks ? "leaf"
2381            : (pvc->callbacks == gSecPolicyPathCallbacks ? "path"
2382                : "custom")),
2383        (force ? "force" : ""), result);
2384
2385    /* If this is not something the current policy cares about ignore
2386       this error and return true so our caller continues evaluation. */
2387    if (!force) {
2388        /* @@@ The right long term fix might be to check if none of the passed
2389           in policies contain this key, since not all checks are run for all
2390           policies. */
2391        SecPolicyRef policy = SecPVCGetPolicy(pvc);
2392        if (policy && !CFDictionaryContainsKey(policy->_options, key))
2393            return true;
2394    }
2395
2396	/* @@@ Check to see if the SecTrustSettings for the certificate in question
2397	   tell us to ignore this error. */
2398	pvc->result = false;
2399	if (!pvc->details)
2400		return false;
2401
2402	CFMutableDictionaryRef detail =
2403		(CFMutableDictionaryRef)CFArrayGetValueAtIndex(pvc->details, ix);
2404
2405	/* Perhaps detail should have an array of results per key?  As it stands
2406       in the case of multiple policy failures the last failure stands.  */
2407	CFDictionarySetValue(detail, key, result);
2408
2409	return true;
2410}
2411
2412bool SecPVCSetResult(SecPVCRef pvc,
2413	CFStringRef key, CFIndex ix, CFTypeRef result) {
2414    return SecPVCSetResultForced(pvc, key, ix, result, false);
2415}
2416
2417/* AUDIT[securityd](done):
2418   key(ok) is a caller provided.
2419   value(ok, unused) is a caller provided.
2420 */
2421static void SecPVCValidateKey(const void *key, const void *value,
2422	void *context) {
2423	SecPVCRef pvc = (SecPVCRef)context;
2424
2425	/* If our caller doesn't want full details and we failed earlier there is
2426	   no point in doing additional checks. */
2427	if (!pvc->result && !pvc->details)
2428		return;
2429
2430	SecPolicyCheckFunction fcn = (SecPolicyCheckFunction)
2431		CFDictionaryGetValue(pvc->callbacks, key);
2432
2433	if (!fcn) {
2434#if 0
2435    /* Why not to have optional policy checks rant:
2436       Not all keys are in all dictionaries anymore, so why not make checks
2437       optional?  This way a client can ask for something and the server will
2438       do a best effort based on the supported flags.  It works since they are
2439       synchronized now, but we need some debug checking here for now. */
2440		pvc->result = false;
2441#endif
2442        if (pvc->callbacks == gSecPolicyLeafCallbacks) {
2443            if (!CFDictionaryContainsKey(gSecPolicyPathCallbacks, key)) {
2444                pvc->result = false;
2445            }
2446        } else if (pvc->callbacks == gSecPolicyPathCallbacks) {
2447            if (!CFDictionaryContainsKey(gSecPolicyLeafCallbacks, key)) {
2448                pvc->result = false;
2449            }
2450        } else {
2451            /* Non standard valdation phase, nothing is optional. */
2452            pvc->result = false;
2453        }
2454		return;
2455	}
2456
2457	fcn(pvc, (CFStringRef)key);
2458}
2459
2460/* AUDIT[securityd](done):
2461   policy->_options is a caller provided dictionary, only its cf type has
2462   been checked.
2463 */
2464bool SecPVCLeafChecks(SecPVCRef pvc) {
2465    pvc->result = true;
2466    CFArrayRef policies = pvc->policies;
2467	CFIndex ix, count = CFArrayGetCount(policies);
2468	for (ix = 0; ix < count; ++ix) {
2469		SecPolicyRef policy = (SecPolicyRef)CFArrayGetValueAtIndex(policies, ix);
2470        pvc->policyIX = ix;
2471        /* Validate all keys for all policies. */
2472        pvc->callbacks = gSecPolicyLeafCallbacks;
2473        CFDictionaryApplyFunction(policy->_options, SecPVCValidateKey, pvc);
2474        if (!pvc->result && !pvc->details)
2475            return pvc->result;
2476	}
2477
2478    return pvc->result;
2479}
2480
2481bool SecPVCParentCertificateChecks(SecPVCRef pvc, CFIndex ix) {
2482    /* Check stuff common to intermediate and anchors. */
2483	CFAbsoluteTime verifyTime = SecPVCGetVerifyTime(pvc);
2484	SecCertificateRef cert = SecPVCGetCertificateAtIndex(pvc, ix);
2485    bool is_anchor = (ix == SecPVCGetCertificateCount(pvc) - 1
2486        && SecPVCIsAnchored(pvc));
2487	if (!SecCertificateIsValid(cert, verifyTime)) {
2488		/* Certificate has expired. */
2489		if (!SecPVCSetResult(pvc, is_anchor ? kSecPolicyCheckValidRoot
2490            : kSecPolicyCheckValidIntermediates, ix, kCFBooleanFalse))
2491            goto errOut;
2492	}
2493
2494    if (is_anchor) {
2495        /* Perform anchor specific checks. */
2496        /* Don't think we have any of these. */
2497    } else {
2498        /* Perform intermediate specific checks. */
2499
2500        /* (k) */
2501		const SecCEBasicConstraints *bc =
2502			SecCertificateGetBasicConstraints(cert);
2503        if (!bc || !bc->isCA) {
2504            /* Basic constraints not present or not marked as isCA, illegal. */
2505            if (!SecPVCSetResultForced(pvc, kSecPolicyCheckBasicContraints,
2506                ix, kCFBooleanFalse, true))
2507                goto errOut;
2508        }
2509        /* Consider adding (l) max_path_length checking here. */
2510
2511        /* (n) If a key usage extension is present, verify that the keyCertSign bit is set. */
2512        SecKeyUsage keyUsage = SecCertificateGetKeyUsage(cert);
2513        if (keyUsage && !(keyUsage & kSecKeyUsageKeyCertSign)) {
2514            if (!SecPVCSetResultForced(pvc, kSecPolicyCheckKeyUsage,
2515                ix, kCFBooleanFalse, true))
2516                goto errOut;
2517        }
2518    }
2519
2520errOut:
2521    return pvc->result;
2522}
2523
2524bool SecPVCBlackListedKeyChecks(SecPVCRef pvc, CFIndex ix) {
2525    /* Check stuff common to intermediate and anchors. */
2526
2527	SecOTAPKIRef otapkiRef = SecOTAPKICopyCurrentOTAPKIRef();
2528	if (NULL != otapkiRef)
2529	{
2530		CFSetRef blackListedKeys = SecOTAPKICopyBlackListSet(otapkiRef);
2531		CFRelease(otapkiRef);
2532		if (NULL != blackListedKeys)
2533		{
2534			SecCertificateRef cert = SecPVCGetCertificateAtIndex(pvc, ix);
2535		    bool is_anchor = (ix == SecPVCGetCertificateCount(pvc) - 1
2536		                      && SecPVCIsAnchored(pvc));
2537		    if (!is_anchor) {
2538		        /* Check for blacklisted intermediates keys. */
2539		        CFDataRef dgst = SecCertificateCopyPublicKeySHA1Digest(cert);
2540		        if (dgst) {
2541		            /* Check dgst against blacklist. */
2542		            if (CFSetContainsValue(blackListedKeys, dgst)) {
2543		                SecPVCSetResultForced(pvc, kSecPolicyCheckBlackListedKey,
2544		                                      ix, kCFBooleanFalse, true);
2545		            }
2546		            CFRelease(dgst);
2547		        }
2548		    }
2549			CFRelease(blackListedKeys);
2550		    return pvc->result;
2551		}
2552	}
2553	// Assume OK
2554	return true;
2555}
2556
2557bool SecPVCGrayListedKeyChecks(SecPVCRef pvc, CFIndex ix)
2558{
2559    /* Check stuff common to intermediate and anchors. */
2560	SecOTAPKIRef otapkiRef = SecOTAPKICopyCurrentOTAPKIRef();
2561	if (NULL != otapkiRef)
2562	{
2563		CFSetRef grayListKeys = SecOTAPKICopyGrayList(otapkiRef);
2564		CFRelease(otapkiRef);
2565		if (NULL != grayListKeys)
2566		{
2567			SecCertificateRef cert = SecPVCGetCertificateAtIndex(pvc, ix);
2568		    bool is_anchor = (ix == SecPVCGetCertificateCount(pvc) - 1
2569		                      && SecPVCIsAnchored(pvc));
2570		    if (!is_anchor) {
2571		        /* Check for gray listed intermediates keys. */
2572		        CFDataRef dgst = SecCertificateCopyPublicKeySHA1Digest(cert);
2573		        if (dgst) {
2574		            /* Check dgst against gray list. */
2575		            if (CFSetContainsValue(grayListKeys, dgst)) {
2576		                SecPVCSetResultForced(pvc, kSecPolicyCheckGrayListedKey,
2577		                                      ix, kCFBooleanFalse, true);
2578		            }
2579		            CFRelease(dgst);
2580		        }
2581		    }
2582			CFRelease(grayListKeys);
2583		    return pvc->result;
2584		}
2585	}
2586	// Assume ok
2587	return true;
2588}
2589
2590/* AUDIT[securityd](done):
2591   policy->_options is a caller provided dictionary, only its cf type has
2592   been checked.
2593 */
2594bool SecPVCPathChecks(SecPVCRef pvc) {
2595    secdebug("policy", "begin path: %@", pvc->path);
2596    bool completed = true;
2597    /* This needs to be initialized before we call any function that might call
2598       SecPVCSetResultForced(). */
2599    pvc->policyIX = 0;
2600    SecPolicyCheckIdLinkage(pvc, kSecPolicyCheckIdLinkage);
2601    if (pvc->result || pvc->details) {
2602        SecPolicyCheckBasicCertificateProcessing(pvc,
2603            kSecPolicyCheckBasicCertificateProcessing);
2604    }
2605
2606    CFArrayRef policies = pvc->policies;
2607	CFIndex count = CFArrayGetCount(policies);
2608	for (; pvc->policyIX < count; ++pvc->policyIX) {
2609        /* Validate all keys for all policies. */
2610        pvc->callbacks = gSecPolicyPathCallbacks;
2611		SecPolicyRef policy = SecPVCGetPolicy(pvc);
2612        CFDictionaryApplyFunction(policy->_options, SecPVCValidateKey, pvc);
2613        if (!pvc->result && !pvc->details)
2614            return completed;
2615	}
2616
2617    /* Check the things we can't check statically for the certificate path. */
2618    /* Critical Extensions, chainLength. */
2619
2620    /* Policy tests. */
2621    pvc->is_ev = false;
2622    if ((pvc->result || pvc->details) && pvc->optionally_ev) {
2623        bool pre_ev_check_result = pvc->result;
2624        SecPolicyCheckEV(pvc, kSecPolicyCheckExtendedValidation);
2625        pvc->is_ev = pvc->result;
2626        /* If ev checking failed, we still want to accept this chain
2627           as a non EV one, if it was valid as such. */
2628        pvc->result = pre_ev_check_result;
2629    }
2630    /* Check revocation only if the chain is valid so far.  Then only check
2631       revocation if the client asked for it explicitly or is_ev is
2632       true. */
2633    if (pvc->result && (pvc->is_ev || pvc->check_revocation)) {
2634        completed = SecPVCCheckRevocation(pvc);
2635    }
2636
2637//errOut:
2638    secdebug("policy", "end %strusted completed: %d path: %@",
2639        (pvc->result ? "" : "not "), completed, pvc->path);
2640    return completed;
2641}
2642
2643/* This function returns 0 to indicate revocation checking was not completed
2644   for this certificate chain, otherwise return to date at which the first
2645   piece of revocation checking info we used expires.  */
2646CFAbsoluteTime SecPVCGetEarliestNextUpdate(SecPVCRef pvc) {
2647	CFIndex certIX, certCount = SecPVCGetCertificateCount(pvc);
2648    CFAbsoluteTime enu = 0;
2649    if (certCount <= 1 || !pvc->rvcs) {
2650        return enu;
2651    }
2652    certCount--;
2653
2654	for (certIX = 0; certIX < certCount; ++certIX) {
2655        SecRVCRef rvc = &((SecRVCRef)pvc->rvcs)[certIX];
2656        if (rvc->nextUpdate == 0) {
2657            if (certIX > 0) {
2658                /* We allow for CA certs to not be revocation checked if they
2659                   have no ocspResponders to check against, but the leaf
2660                   must be checked in order for us to claim we did revocation
2661                   checking. */
2662                SecCertificateRef cert =
2663                    SecPVCGetCertificateAtIndex(rvc->pvc, rvc->certIX);
2664                CFArrayRef ocspResponders = SecCertificateGetOCSPResponders(cert);
2665                if (!ocspResponders || CFArrayGetCount(ocspResponders) == 0) {
2666                    /* We can't check this cert so we don't consider it a soft
2667                       failure that we didn't. Ideally we should support crl
2668                       checking and remove this workaround, since that more
2669                       strict. */
2670                    continue;
2671                }
2672            }
2673            secdebug("ocsp", "revocation checking soft failure for cert: %ld",
2674                certIX);
2675            enu = rvc->nextUpdate;
2676            break;
2677        }
2678        if (enu == 0 || rvc->nextUpdate < enu) {
2679            enu = rvc->nextUpdate;
2680        }
2681#if 0
2682        /* Perhaps we don't want to do this since some policies might
2683           ignore the certificate experation but still use revocation
2684           checking. */
2685
2686        /* Earliest certificate expiration date. */
2687		SecCertificateRef cert = SecPVCGetCertificateAtIndex(rvc->pvc, rvc->certIX);
2688        CFAbsoluteTime nva = SecCertificateNotValidAfter(cert);
2689        if (nva && (enu == 0 || nva < enu)
2690            enu = nva;
2691#endif
2692    }
2693
2694    secdebug("ocsp", "revocation valid until: %lg", enu);
2695    return enu;
2696}
2697