2 * Copyright (c) 2002-2004,2011-2012,2014 Apple Inc. All Rights Reserved.
4 * @APPLE_LICENSE_HEADER_START@
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
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.
21 * @APPLE_LICENSE_HEADER_END@
25 * TrustRevocation.cpp - private revocation policy manipulation
28 #include <security_keychain/Trust.h>
29 #include <security_utilities/cfutilities.h>
30 #include <security_utilities/simpleprefs.h>
31 #include <CoreFoundation/CFData.h>
32 #include "SecBridge.h"
33 #include <Security/cssmapplePriv.h>
34 #include <Security/oidsalg.h>
37 * These may go into an SPI header for the SecTrust object.
40 /* this revocation policy disabled */
42 /* try, but tolerate inability to complete */
44 /* require successful revocation check if certificate indicates
45 * the policy is supported */
46 kSecRequireIfPresentInCertificate
,
47 /* require for every cert */
48 kSecRequireForAllCertificates
49 } SecRevocationPolicyStyle
;
51 using namespace KeychainCore
;
54 * Given an app-specified array of Policies, determine if at least one of them
55 * matches the given policy OID.
57 bool Trust::policySpecified(CFArrayRef policies
, const CSSM_OID
&inOid
)
59 if(policies
== NULL
) {
62 CFIndex numPolicies
= CFArrayGetCount(policies
);
63 for(CFIndex dex
=0; dex
<numPolicies
; dex
++) {
64 SecPolicyRef secPol
= (SecPolicyRef
)CFArrayGetValueAtIndex(policies
, dex
);
65 SecPointer
<Policy
> pol
= Policy::required(SecPolicyRef(secPol
));
66 const CssmOid
&oid
= pol
->oid();
67 if(oid
== CssmOid::overlay(inOid
)) {
75 * Given an app-specified array of Policies, determine if at least one of them
76 * is an explicit revocation policy.
78 bool Trust::revocationPolicySpecified(CFArrayRef policies
)
80 if(policies
== NULL
) {
83 CFIndex numPolicies
= CFArrayGetCount(policies
);
84 for(CFIndex dex
=0; dex
<numPolicies
; dex
++) {
85 SecPolicyRef secPol
= (SecPolicyRef
)CFArrayGetValueAtIndex(policies
, dex
);
86 SecPointer
<Policy
> pol
= Policy::required(SecPolicyRef(secPol
));
87 const CssmOid
&oid
= pol
->oid();
88 if(oid
== CssmOid::overlay(CSSMOID_APPLE_TP_REVOCATION_CRL
)) {
91 if(oid
== CssmOid::overlay(CSSMOID_APPLE_TP_REVOCATION_OCSP
)) {
99 * Replace a unified revocation policy instance in the mPolicies array
100 * with specific instances of the OCSP and/or CRL policies which the TP
101 * module understands. Returns a (possibly) modified copy of the mPolicies
102 * array, which the caller is responsible for releasing.
104 CFMutableArrayRef
Trust::convertRevocationPolicy(
112 CFIndex numPolicies
= CFArrayGetCount(mPolicies
);
113 CFAllocatorRef allocator
= CFGetAllocator(mPolicies
);
114 CFMutableArrayRef policies
= CFArrayCreateMutableCopy(allocator
, numPolicies
, mPolicies
);
115 SecPolicyRef revPolicy
= NULL
;
116 for(CFIndex dex
=0; dex
<numPolicies
; dex
++) {
117 SecPolicyRef secPol
= (SecPolicyRef
)CFArrayGetValueAtIndex(policies
, dex
);
118 SecPointer
<Policy
> pol
= Policy::required(SecPolicyRef(secPol
));
119 const CssmOid
&oid
= pol
->oid();
120 if(oid
== CssmOid::overlay(CSSMOID_APPLE_TP_REVOCATION
)) {
123 CFRelease(revPolicy
);
125 CFArrayRemoveValueAtIndex(policies
, dex
--);
134 SecPointer
<Policy
> ocspPolicy
;
135 SecPointer
<Policy
> crlPolicy
;
137 // fetch policy value
138 CFOptionFlags policyFlags
= kSecRevocationUseAnyAvailableMethod
;
139 CSSM_DATA policyValue
= { 0, NULL
};
140 OSStatus status
= SecPolicyGetValue(revPolicy
, &policyValue
);
141 if (!status
&& policyValue
.Data
) {
142 policyFlags
= (CFOptionFlags
) *((CFOptionFlags
*)policyValue
.Data
);
144 if (mNetworkPolicy
== useNetworkDisabled
) {
145 policyFlags
= 0 | kSecRevocationNetworkAccessDisabled
;
147 CFRelease(revPolicy
); // all done with this policy reference
149 if (policyFlags
& kSecRevocationOCSPMethod
) {
150 /* cook up a new Policy object */
151 ocspPolicy
= new Policy(mTP
, CssmOid::overlay(CSSMOID_APPLE_TP_REVOCATION_OCSP
));
152 CSSM_APPLE_TP_OCSP_OPT_FLAGS ocspFlags
= CSSM_TP_ACTION_OCSP_SUFFICIENT
;
153 if (policyFlags
& kSecRevocationRequirePositiveResponse
) {
154 // FIXME: possibly set CSSM_TP_ACTION_REQUIRE_REV_PER_CERT in actionFlags,
155 // but verify whether that only applies to certs which specify a revocation method
157 CSSM_APPLE_TP_OCSP_OPTIONS opts
;
158 memset(&opts
, 0, sizeof(opts
));
159 opts
.Version
= CSSM_APPLE_TP_OCSP_OPTS_VERSION
;
160 opts
.Flags
= ocspFlags
;
162 /* Policy manages its own copy of this data */
163 CSSM_DATA optData
= {sizeof(opts
), (uint8
*)&opts
};
164 ocspPolicy
->value() = optData
;
166 /* Policies array retains the Policy object */
167 CFArrayAppendValue(policies
, ocspPolicy
->handle(false));
170 if (policyFlags
& kSecRevocationCRLMethod
) {
171 /* cook up a new Policy object */
172 crlPolicy
= new Policy(mTP
, CssmOid::overlay(CSSMOID_APPLE_TP_REVOCATION_CRL
));
173 CSSM_APPLE_TP_CRL_OPT_FLAGS crlFlags
= 0;
174 if (policyFlags
& kSecRevocationRequirePositiveResponse
) {
175 // FIXME: possibly set CSSM_TP_ACTION_REQUIRE_REV_PER_CERT in actionFlags,
176 // but verify whether that only applies to certs which specify a revocation method
178 CSSM_APPLE_TP_CRL_OPTIONS opts
;
179 memset(&opts
, 0, sizeof(opts
));
180 opts
.Version
= CSSM_APPLE_TP_CRL_OPTS_VERSION
;
181 opts
.CrlFlags
= crlFlags
;
183 /* Policy manages its own copy of this data */
184 CSSM_DATA optData
= {sizeof(opts
), (uint8
*)&opts
};
185 crlPolicy
->value() = optData
;
187 /* Policies array retains the Policy object */
188 CFArrayAppendValue(policies
, crlPolicy
->handle(false));
194 static SecRevocationPolicyStyle
parseRevStyle(CFStringRef val
)
196 if(CFEqual(val
, kSecRevocationOff
)) {
199 else if(CFEqual(val
, kSecRevocationBestAttempt
)) {
200 return kSecBestAttempt
;
202 else if(CFEqual(val
, kSecRevocationRequireIfPresent
)) {
203 return kSecRequireIfPresentInCertificate
;
205 else if(CFEqual(val
, kSecRevocationRequireForAll
)) {
206 return kSecRequireForAllCertificates
;
213 CFDictionaryRef
Trust::defaultRevocationSettings()
216 defaults read ~/Library/Preferences/com.apple.security.revocation
218 CRLStyle = BestAttempt;
219 CRLSufficientPerCert = 1;
220 OCSPStyle = BestAttempt;
221 OCSPSufficientPerCert = 1;
222 RevocationFirst = OCSP;
225 const void *keys
[] = {
226 kSecRevocationCrlStyle
,
227 kSecRevocationCRLSufficientPerCert
,
228 kSecRevocationOcspStyle
,
229 kSecRevocationOCSPSufficientPerCert
,
230 kSecRevocationWhichFirst
232 const void *values
[] = {
233 kSecRevocationBestAttempt
,
235 kSecRevocationBestAttempt
,
237 kSecRevocationOcspFirst
240 return CFDictionaryCreate(kCFAllocatorDefault
, keys
,
241 values
, sizeof(keys
) / sizeof(*keys
),
242 &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
);
245 CFMutableArrayRef
Trust::addPreferenceRevocationPolicies(
251 /* any per-user prefs? */
252 Dictionary
* pd
= Dictionary::CreateDictionary(kSecRevocationDomain
, Dictionary::US_User
, true);
263 pd
= Dictionary::CreateDictionary(kSecRevocationDomain
, Dictionary::US_System
, true);
272 CFDictionaryRef tempDict
= defaultRevocationSettings();
273 if (tempDict
== NULL
)
276 pd
= new Dictionary(tempDict
);
280 auto_ptr
<Dictionary
> prefsDict(pd
);
285 SecRevocationPolicyStyle ocspStyle
= kSecBestAttempt
;
286 SecRevocationPolicyStyle crlStyle
= kSecBestAttempt
;
287 SecPointer
<Policy
> ocspPolicy
;
288 SecPointer
<Policy
> crlPolicy
;
290 /* Are any revocation policies enabled? */
291 val
= prefsDict
->getStringValue(kSecRevocationOcspStyle
);
293 ocspStyle
= parseRevStyle(val
);
294 if(ocspStyle
!= kSecDisabled
) {
298 val
= prefsDict
->getStringValue(kSecRevocationCrlStyle
);
300 crlStyle
= parseRevStyle(val
);
301 if(crlStyle
!= kSecDisabled
) {
305 if(!doCrl
&& !doOcsp
) {
309 /* which policy first? */
310 bool ocspFirst
= true; // default if both present
311 if(doCrl
&& doOcsp
) {
312 val
= prefsDict
->getStringValue(kSecRevocationWhichFirst
);
313 if((val
!= NULL
) && CFEqual(val
, kSecRevocationCrlFirst
)) {
318 /* Must have at least one caller-specified policy
319 * (if they didn't specify any, it's a no-op evaluation, and if they wanted
320 * revocation checking only, that policy would already be in mPolicies) */
321 if (!mPolicies
|| !CFArrayGetCount(mPolicies
))
324 /* We're adding something to mPolicies, so make a copy we can work with */
325 CFMutableArrayRef policies
= CFArrayCreateMutableCopy(NULL
, 0, mPolicies
);
326 if(policies
== NULL
) {
327 throw std::bad_alloc();
331 /* Cook up a new Policy object */
332 ocspPolicy
= new Policy(mTP
, CssmOid::overlay(CSSMOID_APPLE_TP_REVOCATION_OCSP
));
333 CSSM_APPLE_TP_OCSP_OPTIONS opts
;
334 memset(&opts
, 0, sizeof(opts
));
335 opts
.Version
= CSSM_APPLE_TP_OCSP_OPTS_VERSION
;
337 /* Now fill in the OCSP-related blanks */
342 case kSecBestAttempt
:
343 /* default, nothing to set */
345 case kSecRequireIfPresentInCertificate
:
346 opts
.Flags
|= CSSM_TP_ACTION_OCSP_REQUIRE_IF_RESP_PRESENT
;
348 case kSecRequireForAllCertificates
:
349 opts
.Flags
|= CSSM_TP_ACTION_OCSP_REQUIRE_PER_CERT
;
353 if(prefsDict
->getBoolValue(kSecRevocationOCSPSufficientPerCert
)) {
354 opts
.Flags
|= CSSM_TP_ACTION_OCSP_SUFFICIENT
;
357 val
= prefsDict
->getStringValue(kSecOCSPLocalResponder
);
359 CFDataRef cfData
= CFStringCreateExternalRepresentation(NULL
,
360 val
, kCFStringEncodingUTF8
, 0);
361 CFIndex len
= CFDataGetLength(cfData
);
362 opts
.LocalResponder
= (CSSM_DATA_PTR
)alloc
.malloc(sizeof(CSSM_DATA
));
363 opts
.LocalResponder
->Data
= (uint8
*)alloc
.malloc(len
);
364 opts
.LocalResponder
->Length
= len
;
365 memmove(opts
.LocalResponder
->Data
, CFDataGetBytePtr(cfData
), len
);
369 /* Policy manages its own copy of this data */
370 CSSM_DATA optData
= {sizeof(opts
), (uint8
*)&opts
};
371 ocspPolicy
->value() = optData
;
376 /* Cook up a new Policy object */
377 crlPolicy
= new Policy(mTP
, CssmOid::overlay(CSSMOID_APPLE_TP_REVOCATION_CRL
));
378 CSSM_APPLE_TP_CRL_OPTIONS opts
;
379 memset(&opts
, 0, sizeof(opts
));
380 opts
.Version
= CSSM_APPLE_TP_CRL_OPTS_VERSION
;
382 /* Now fill in the CRL-related blanks */
383 opts
.CrlFlags
= CSSM_TP_ACTION_FETCH_CRL_FROM_NET
; // default true
388 case kSecBestAttempt
:
389 /* default, nothing to set */
391 case kSecRequireIfPresentInCertificate
:
392 opts
.CrlFlags
|= CSSM_TP_ACTION_REQUIRE_CRL_IF_PRESENT
;
394 case kSecRequireForAllCertificates
:
395 opts
.CrlFlags
|= CSSM_TP_ACTION_REQUIRE_CRL_PER_CERT
;
398 if(prefsDict
->getBoolValue(kSecRevocationCRLSufficientPerCert
)) {
399 opts
.CrlFlags
|= CSSM_TP_ACTION_CRL_SUFFICIENT
;
402 /* Policy manages its own copy of this data */
403 CSSM_DATA optData
= {sizeof(opts
), (uint8
*)&opts
};
404 crlPolicy
->value() = optData
;
408 /* append in order */
412 /* these SecCFObject go away when the policies array does */
413 CFArrayAppendValue(policies
, ocspPolicy
->handle(false));
414 CFArrayAppendValue(policies
, crlPolicy
->handle(false));
417 CFArrayAppendValue(policies
, crlPolicy
->handle(false));
418 CFArrayAppendValue(policies
, ocspPolicy
->handle(false));
422 CFArrayAppendValue(policies
, ocspPolicy
->handle(false));
428 CFArrayAppendValue(policies
, crlPolicy
->handle(false));
434 * Called when we created the last numAdded Policies in the specified Policy array
435 * (only frees the policy data associated with the extra policies that we inserted;
436 * this does not free the policies array itself.)
438 void Trust::freeAddedRevocationPolicyData(
443 uint32 numPolicies
= (uint32
)CFArrayGetCount(policies
);
444 if(numPolicies
< numAdded
) {
445 /* should never happen - throw? */
449 for(unsigned dex
=numPolicies
-numAdded
; dex
<numPolicies
; dex
++) {
450 SecPolicyRef secPol
= (SecPolicyRef
)CFArrayGetValueAtIndex(policies
, dex
);
451 //SecPointer<Policy> pol = Policy::required(SecPolicyRef(secPol));
452 Policy
*pol
= Policy::required(secPol
);
453 const CssmOid
&oid
= pol
->oid(); // required
454 const CssmData
&optData
= pol
->value(); // optional
457 if(oid
== CssmOid::overlay(CSSMOID_APPLE_TP_REVOCATION_CRL
)) {
458 /* currently no CRL-specific policy data */
460 else if(oid
== CssmOid::overlay(CSSMOID_APPLE_TP_REVOCATION_OCSP
)) {
461 CSSM_APPLE_TP_OCSP_OPTIONS
*opts
= (CSSM_APPLE_TP_OCSP_OPTIONS
*)optData
.Data
;
462 if(opts
->LocalResponder
!= NULL
) {
463 if(opts
->LocalResponder
->Data
!= NULL
) {
464 alloc
.free(opts
->LocalResponder
->Data
);
466 alloc
.free(opts
->LocalResponder
);
469 // managed by Policy alloc.free(optData.Data);
475 * Comparator function to correctly order revocation policies.
477 static CFComparisonResult
compareRevocationPolicies(
482 SecPointer
<Policy
> pol1
= Policy::required(SecPolicyRef(policy1
));
483 SecPointer
<Policy
> pol2
= Policy::required(SecPolicyRef(policy2
));
484 const CssmOid
&oid1
= pol1
->oid();
485 const CssmOid
&oid2
= pol2
->oid();
487 return kCFCompareEqualTo
;
489 bool ocspFirst
= true;
490 if(context
!= NULL
&& CFEqual((CFBooleanRef
)context
, kCFBooleanFalse
)) {
493 const CssmOid lastRevocationOid
= (ocspFirst
) ?
494 CssmOid::overlay(CSSMOID_APPLE_TP_REVOCATION_CRL
) :
495 CssmOid::overlay(CSSMOID_APPLE_TP_REVOCATION_OCSP
);
496 const CssmOid firstRevocationOid
= (ocspFirst
) ?
497 CssmOid::overlay(CSSMOID_APPLE_TP_REVOCATION_OCSP
) :
498 CssmOid::overlay(CSSMOID_APPLE_TP_REVOCATION_CRL
);
499 if(oid1
== lastRevocationOid
) {
500 /* should be ordered last, after all other policies */
501 return kCFCompareGreaterThan
;
503 if(oid1
== firstRevocationOid
) {
504 /* should be ordered after any policy except lastRevocationOid */
505 if(oid2
== lastRevocationOid
) {
506 return kCFCompareLessThan
;
508 return kCFCompareGreaterThan
;
510 /* normal policy in first position, anything else in second position */
511 return kCFCompareLessThan
;
515 * This method reorders any revocation policies which may be present
516 * in the provided array so they are at the end and evaluated last.
518 void Trust::orderRevocationPolicies(
519 CFMutableArrayRef policies
)
521 if(!policies
|| CFGetTypeID(policies
) != CFArrayGetTypeID()) {
524 /* check revocation prefs to determine which policy goes first */
525 CFBooleanRef ocspFirst
= kCFBooleanTrue
;
526 Dictionary
* pd
= Dictionary::CreateDictionary(kSecRevocationDomain
, Dictionary::US_User
, true);
531 auto_ptr
<Dictionary
> prefsDict(pd
);
532 CFStringRef val
= prefsDict
->getStringValue(kSecRevocationWhichFirst
);
533 if((val
!= NULL
) && CFEqual(val
, kSecRevocationCrlFirst
)) {
534 ocspFirst
= kCFBooleanFalse
;
539 CFShow(policies
); // before sort
540 CFArraySortValues(policies
, CFRangeMake(0, CFArrayGetCount(policies
)), compareRevocationPolicies
, (void*)ocspFirst
);
541 CFShow(policies
); // after sort, to see what changed
542 // check that policy order is what we expect
543 CFIndex numPolicies
= CFArrayGetCount(policies
);
544 for(CFIndex dex
=0; dex
<numPolicies
; dex
++) {
545 SecPolicyRef secPol
= (SecPolicyRef
)CFArrayGetValueAtIndex(policies
, dex
);
546 SecPointer
<Policy
> pol
= Policy::required(SecPolicyRef(secPol
));
547 const CssmOid
&oid
= pol
->oid();
548 if(oid
== CssmOid::overlay(CSSMOID_APPLE_TP_REVOCATION_OCSP
)) {
549 CFStringRef s
= CFStringCreateWithFormat(NULL
, NULL
, CFSTR("idx %d = OCSP"), dex
);
553 else if(oid
== CssmOid::overlay(CSSMOID_APPLE_TP_REVOCATION_CRL
)) {
554 CFStringRef s
= CFStringCreateWithFormat(NULL
, NULL
, CFSTR("idx %d = CRL"), dex
);
559 CFStringRef s
= CFStringCreateWithFormat(NULL
, NULL
, CFSTR("idx %d = normal"), dex
);
565 CFArraySortValues(policies
, CFRangeMake(0, CFArrayGetCount(policies
)), compareRevocationPolicies
, (void*)ocspFirst
);
570 * This method returns a copy of the mPolicies array which ensures that
571 * revocation checking (preferably OCSP, otherwise CRL) will be attempted.
573 * If OCSP is already in the mPolicies array, this makes sure the
574 * CSSM_TP_ACTION_OCSP_REQUIRE_IF_RESP_PRESENT and CSSM_TP_ACTION_OCSP_SUFFICIENT
575 * flags are set. If it's not already in the array, a new policy object is added.
577 * If CRL is already in the mPolicies array, this makes sure the
578 * CSSM_TP_ACTION_FETCH_CRL_FROM_NET and CSSM_TP_ACTION_CRL_SUFFICIENT flags are
579 * set. If it's not already in the array, a new policy object is added.
581 * Caller is responsible for releasing the returned policies array.
583 CFMutableArrayRef
Trust::forceRevocationPolicies(
588 SecPointer
<Policy
> ocspPolicy
;
589 SecPointer
<Policy
> crlPolicy
;
590 CSSM_APPLE_TP_OCSP_OPT_FLAGS ocspFlags
;
591 CSSM_APPLE_TP_CRL_OPT_FLAGS crlFlags
;
592 bool hasOcspPolicy
= false;
593 bool hasCrlPolicy
= false;
596 ocspFlags
= CSSM_TP_ACTION_OCSP_SUFFICIENT
;
597 crlFlags
= CSSM_TP_ACTION_FETCH_CRL_FROM_NET
| CSSM_TP_ACTION_CRL_SUFFICIENT
;
598 if (requirePerCert
) {
599 ocspFlags
|= CSSM_TP_ACTION_OCSP_REQUIRE_IF_RESP_PRESENT
;
600 crlFlags
|= CSSM_TP_ACTION_REQUIRE_CRL_IF_PRESENT
;
603 CFIndex numPolicies
= (mPolicies
) ? CFArrayGetCount(mPolicies
) : 0;
604 for(CFIndex dex
=0; dex
<numPolicies
; dex
++) {
605 SecPolicyRef secPol
= (SecPolicyRef
)CFArrayGetValueAtIndex(mPolicies
, dex
);
606 SecPointer
<Policy
> pol
= Policy::required(SecPolicyRef(secPol
));
607 const CssmOid
&oid
= pol
->oid();
608 const CssmData
&optData
= pol
->value();
609 if(oid
== CssmOid::overlay(CSSMOID_APPLE_TP_REVOCATION_OCSP
)) {
610 // make sure OCSP options are set correctly
611 CSSM_APPLE_TP_OCSP_OPTIONS
*opts
= (CSSM_APPLE_TP_OCSP_OPTIONS
*)optData
.Data
;
613 opts
->Flags
|= ocspFlags
;
615 CSSM_APPLE_TP_OCSP_OPTIONS newOpts
;
616 memset(&newOpts
, 0, sizeof(newOpts
));
617 newOpts
.Version
= CSSM_APPLE_TP_OCSP_OPTS_VERSION
;
618 newOpts
.Flags
= ocspFlags
;
619 CSSM_DATA optData
= {sizeof(newOpts
), (uint8
*)&newOpts
};
620 pol
->value() = optData
;
622 hasOcspPolicy
= true;
624 else if(oid
== CssmOid::overlay(CSSMOID_APPLE_TP_REVOCATION_CRL
)) {
625 // make sure CRL options are set correctly
626 CSSM_APPLE_TP_CRL_OPTIONS
*opts
= (CSSM_APPLE_TP_CRL_OPTIONS
*)optData
.Data
;
628 opts
->CrlFlags
|= crlFlags
;
630 CSSM_APPLE_TP_CRL_OPTIONS newOpts
;
631 memset(&newOpts
, 0, sizeof(newOpts
));
632 newOpts
.Version
= CSSM_APPLE_TP_CRL_OPTS_VERSION
;
633 newOpts
.CrlFlags
= crlFlags
;
634 CSSM_DATA optData
= {sizeof(newOpts
), (uint8
*)&newOpts
};
635 pol
->value() = optData
;
641 /* We're potentially adding something to mPolicies, so make a copy we can work with */
642 CFMutableArrayRef policies
= CFArrayCreateMutableCopy(NULL
, 0, mPolicies
);
643 if(policies
== NULL
) {
644 throw std::bad_alloc();
648 /* Cook up a new Policy object */
649 ocspPolicy
= new Policy(mTP
, CssmOid::overlay(CSSMOID_APPLE_TP_REVOCATION_OCSP
));
650 CSSM_APPLE_TP_OCSP_OPTIONS opts
;
651 memset(&opts
, 0, sizeof(opts
));
652 opts
.Version
= CSSM_APPLE_TP_OCSP_OPTS_VERSION
;
653 opts
.Flags
= ocspFlags
;
655 /* Check prefs dict for local responder info */
656 Dictionary
*prefsDict
= NULL
;
657 try { /* per-user prefs */
658 prefsDict
= Dictionary::CreateDictionary(kSecRevocationDomain
, Dictionary::US_User
, true);
659 if (!prefsDict
->dict()) {
665 if(prefsDict
== NULL
) {
666 try { /* system prefs */
667 prefsDict
= Dictionary::CreateDictionary(kSecRevocationDomain
, Dictionary::US_System
, true);
668 if (!prefsDict
->dict()) {
675 if(prefsDict
!= NULL
) {
676 CFStringRef val
= prefsDict
->getStringValue(kSecOCSPLocalResponder
);
678 CFDataRef cfData
= CFStringCreateExternalRepresentation(NULL
,
679 val
, kCFStringEncodingUTF8
, 0);
680 CFIndex len
= CFDataGetLength(cfData
);
681 opts
.LocalResponder
= (CSSM_DATA_PTR
)alloc
.malloc(sizeof(CSSM_DATA
));
682 opts
.LocalResponder
->Data
= (uint8
*)alloc
.malloc(len
);
683 opts
.LocalResponder
->Length
= len
;
684 memmove(opts
.LocalResponder
->Data
, CFDataGetBytePtr(cfData
), len
);
689 /* Policy manages its own copy of the options data */
690 CSSM_DATA optData
= {sizeof(opts
), (uint8
*)&opts
};
691 ocspPolicy
->value() = optData
;
693 /* Policies array retains the Policy object */
694 CFArrayAppendValue(policies
, ocspPolicy
->handle(false));
697 if(prefsDict
!= NULL
)
702 /* Cook up a new Policy object */
703 crlPolicy
= new Policy(mTP
, CssmOid::overlay(CSSMOID_APPLE_TP_REVOCATION_CRL
));
704 CSSM_APPLE_TP_CRL_OPTIONS opts
;
705 memset(&opts
, 0, sizeof(opts
));
706 opts
.Version
= CSSM_APPLE_TP_CRL_OPTS_VERSION
;
707 opts
.CrlFlags
= crlFlags
;
709 /* Policy manages its own copy of this data */
710 CSSM_DATA optData
= {sizeof(opts
), (uint8
*)&opts
};
711 crlPolicy
->value() = optData
;
713 /* Policies array retains the Policy object */
714 CFArrayAppendValue(policies
, crlPolicy
->handle(false));