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
};
141 policyValue
= Policy::required(revPolicy
)->value();
144 policyValue
.Data
= NULL
;
146 if (policyValue
.Data
) {
147 policyFlags
= (CFOptionFlags
) *((CFOptionFlags
*)policyValue
.Data
);
149 if (mNetworkPolicy
== useNetworkDisabled
) {
150 policyFlags
= 0 | kSecRevocationNetworkAccessDisabled
;
152 CFRelease(revPolicy
); // all done with this policy reference
154 if (policyFlags
& kSecRevocationOCSPMethod
) {
155 /* cook up a new Policy object */
156 ocspPolicy
= new Policy(mTP
, CssmOid::overlay(CSSMOID_APPLE_TP_REVOCATION_OCSP
));
157 CSSM_APPLE_TP_OCSP_OPT_FLAGS ocspFlags
= CSSM_TP_ACTION_OCSP_SUFFICIENT
;
158 if (policyFlags
& kSecRevocationRequirePositiveResponse
) {
159 ocspFlags
|= CSSM_TP_ACTION_OCSP_REQUIRE_IF_RESP_PRESENT
;
161 CSSM_APPLE_TP_OCSP_OPTIONS opts
;
162 memset(&opts
, 0, sizeof(opts
));
163 opts
.Version
= CSSM_APPLE_TP_OCSP_OPTS_VERSION
;
164 opts
.Flags
= ocspFlags
;
166 /* Policy manages its own copy of this data */
167 CSSM_DATA optData
= {sizeof(opts
), (uint8
*)&opts
};
168 ocspPolicy
->value() = optData
;
170 /* Policies array retains the Policy object */
171 CFArrayAppendValue(policies
, ocspPolicy
->handle(false));
174 if (policyFlags
& kSecRevocationCRLMethod
) {
175 /* cook up a new Policy object */
176 crlPolicy
= new Policy(mTP
, CssmOid::overlay(CSSMOID_APPLE_TP_REVOCATION_CRL
));
177 CSSM_APPLE_TP_CRL_OPT_FLAGS crlFlags
= 0;
178 if (policyFlags
& kSecRevocationRequirePositiveResponse
) {
179 crlFlags
|= CSSM_TP_ACTION_REQUIRE_CRL_IF_PRESENT
;
181 CSSM_APPLE_TP_CRL_OPTIONS opts
;
182 memset(&opts
, 0, sizeof(opts
));
183 opts
.Version
= CSSM_APPLE_TP_CRL_OPTS_VERSION
;
184 opts
.CrlFlags
= crlFlags
;
186 /* Policy manages its own copy of this data */
187 CSSM_DATA optData
= {sizeof(opts
), (uint8
*)&opts
};
188 crlPolicy
->value() = optData
;
190 /* Policies array retains the Policy object */
191 CFArrayAppendValue(policies
, crlPolicy
->handle(false));
197 static SecRevocationPolicyStyle
parseRevStyle(CFStringRef val
)
199 if(CFEqual(val
, kSecRevocationOff
)) {
202 else if(CFEqual(val
, kSecRevocationBestAttempt
)) {
203 return kSecBestAttempt
;
205 else if(CFEqual(val
, kSecRevocationRequireIfPresent
)) {
206 return kSecRequireIfPresentInCertificate
;
208 else if(CFEqual(val
, kSecRevocationRequireForAll
)) {
209 return kSecRequireForAllCertificates
;
216 CFDictionaryRef
Trust::defaultRevocationSettings()
219 defaults read ~/Library/Preferences/com.apple.security.revocation
221 CRLStyle = BestAttempt;
222 CRLSufficientPerCert = 1;
223 OCSPStyle = BestAttempt;
224 OCSPSufficientPerCert = 1;
225 RevocationFirst = OCSP;
228 const void *keys
[] = {
229 kSecRevocationCrlStyle
,
230 kSecRevocationCRLSufficientPerCert
,
231 kSecRevocationOcspStyle
,
232 kSecRevocationOCSPSufficientPerCert
,
233 kSecRevocationWhichFirst
235 const void *values
[] = {
236 kSecRevocationBestAttempt
,
238 kSecRevocationBestAttempt
,
240 kSecRevocationOcspFirst
243 return CFDictionaryCreate(kCFAllocatorDefault
, keys
,
244 values
, sizeof(keys
) / sizeof(*keys
),
245 &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
);
248 CFMutableArrayRef
Trust::addPreferenceRevocationPolicies(
249 bool ocspEnabledOnBestAttempt
,
250 bool crlEnabledOnBestAttempt
,
256 /* any per-user prefs? */
257 Dictionary
* pd
= Dictionary::CreateDictionary(kSecRevocationDomain
, Dictionary::US_User
, true);
268 pd
= Dictionary::CreateDictionary(kSecRevocationDomain
, Dictionary::US_System
, true);
277 CFDictionaryRef tempDict
= defaultRevocationSettings();
278 if (tempDict
== NULL
)
281 pd
= new Dictionary(tempDict
);
285 auto_ptr
<Dictionary
> prefsDict(pd
);
290 SecRevocationPolicyStyle ocspStyle
= kSecBestAttempt
;
291 SecRevocationPolicyStyle crlStyle
= kSecBestAttempt
;
292 SecPointer
<Policy
> ocspPolicy
;
293 SecPointer
<Policy
> crlPolicy
;
295 /* Are any revocation policies enabled? */
296 val
= prefsDict
->getStringValue(kSecRevocationOcspStyle
);
298 ocspStyle
= parseRevStyle(val
);
299 if(ocspStyle
!= kSecDisabled
) {
302 if(ocspStyle
== kSecBestAttempt
) {
303 doOcsp
= ocspEnabledOnBestAttempt
;
306 val
= prefsDict
->getStringValue(kSecRevocationCrlStyle
);
308 crlStyle
= parseRevStyle(val
);
309 if(crlStyle
!= kSecDisabled
) {
312 if(crlStyle
== kSecBestAttempt
) {
313 doCrl
= crlEnabledOnBestAttempt
;
317 if(!doCrl
&& !doOcsp
) {
321 /* which policy first? */
322 bool ocspFirst
= true; // default if both present
323 if(doCrl
&& doOcsp
) {
324 val
= prefsDict
->getStringValue(kSecRevocationWhichFirst
);
325 if((val
!= NULL
) && CFEqual(val
, kSecRevocationCrlFirst
)) {
330 /* Must have at least one caller-specified policy
331 * (if they didn't specify any, it's a no-op evaluation, and if they wanted
332 * revocation checking only, that policy would already be in mPolicies) */
333 if (!mPolicies
|| !CFArrayGetCount(mPolicies
))
336 /* We're adding something to mPolicies, so make a copy we can work with */
337 CFMutableArrayRef policies
= CFArrayCreateMutableCopy(NULL
, 0, mPolicies
);
338 if(policies
== NULL
) {
339 throw std::bad_alloc();
343 /* Cook up a new Policy object */
344 ocspPolicy
= new Policy(mTP
, CssmOid::overlay(CSSMOID_APPLE_TP_REVOCATION_OCSP
));
345 CSSM_APPLE_TP_OCSP_OPTIONS opts
;
346 memset(&opts
, 0, sizeof(opts
));
347 opts
.Version
= CSSM_APPLE_TP_OCSP_OPTS_VERSION
;
349 /* Now fill in the OCSP-related blanks */
354 case kSecBestAttempt
:
355 /* default, nothing to set */
357 case kSecRequireIfPresentInCertificate
:
358 opts
.Flags
|= CSSM_TP_ACTION_OCSP_REQUIRE_IF_RESP_PRESENT
;
360 case kSecRequireForAllCertificates
:
361 opts
.Flags
|= CSSM_TP_ACTION_OCSP_REQUIRE_PER_CERT
;
365 if(prefsDict
->getBoolValue(kSecRevocationOCSPSufficientPerCert
)) {
366 opts
.Flags
|= CSSM_TP_ACTION_OCSP_SUFFICIENT
;
369 val
= prefsDict
->getStringValue(kSecOCSPLocalResponder
);
371 CFDataRef cfData
= CFStringCreateExternalRepresentation(NULL
,
372 val
, kCFStringEncodingUTF8
, 0);
373 CFIndex len
= CFDataGetLength(cfData
);
374 opts
.LocalResponder
= (CSSM_DATA_PTR
)alloc
.malloc(sizeof(CSSM_DATA
));
375 opts
.LocalResponder
->Data
= (uint8
*)alloc
.malloc(len
);
376 opts
.LocalResponder
->Length
= len
;
377 memmove(opts
.LocalResponder
->Data
, CFDataGetBytePtr(cfData
), len
);
381 /* Policy manages its own copy of this data */
382 CSSM_DATA optData
= {sizeof(opts
), (uint8
*)&opts
};
383 ocspPolicy
->value() = optData
;
388 /* Cook up a new Policy object */
389 crlPolicy
= new Policy(mTP
, CssmOid::overlay(CSSMOID_APPLE_TP_REVOCATION_CRL
));
390 CSSM_APPLE_TP_CRL_OPTIONS opts
;
391 memset(&opts
, 0, sizeof(opts
));
392 opts
.Version
= CSSM_APPLE_TP_CRL_OPTS_VERSION
;
394 /* Now fill in the CRL-related blanks */
395 opts
.CrlFlags
= CSSM_TP_ACTION_FETCH_CRL_FROM_NET
; // default true
400 case kSecBestAttempt
:
401 /* default, nothing to set */
403 case kSecRequireIfPresentInCertificate
:
404 opts
.CrlFlags
|= CSSM_TP_ACTION_REQUIRE_CRL_IF_PRESENT
;
406 case kSecRequireForAllCertificates
:
407 opts
.CrlFlags
|= CSSM_TP_ACTION_REQUIRE_CRL_PER_CERT
;
410 if(prefsDict
->getBoolValue(kSecRevocationCRLSufficientPerCert
)) {
411 opts
.CrlFlags
|= CSSM_TP_ACTION_CRL_SUFFICIENT
;
414 /* Policy manages its own copy of this data */
415 CSSM_DATA optData
= {sizeof(opts
), (uint8
*)&opts
};
416 crlPolicy
->value() = optData
;
420 /* append in order */
424 /* these SecCFObject go away when the policies array does */
425 CFArrayAppendValue(policies
, ocspPolicy
->handle(false));
426 CFArrayAppendValue(policies
, crlPolicy
->handle(false));
429 CFArrayAppendValue(policies
, crlPolicy
->handle(false));
430 CFArrayAppendValue(policies
, ocspPolicy
->handle(false));
434 CFArrayAppendValue(policies
, ocspPolicy
->handle(false));
439 CFArrayAppendValue(policies
, crlPolicy
->handle(false));
445 * Called when we created the last numAdded Policies in the specified Policy array
446 * (only frees the policy data associated with the extra policies that we inserted;
447 * this does not free the policies array itself.)
449 void Trust::freeAddedRevocationPolicyData(
454 uint32 numPolicies
= (uint32
)CFArrayGetCount(policies
);
455 if(numPolicies
< numAdded
) {
456 /* should never happen - throw? */
460 for(unsigned dex
=numPolicies
-numAdded
; dex
<numPolicies
; dex
++) {
461 SecPolicyRef secPol
= (SecPolicyRef
)CFArrayGetValueAtIndex(policies
, dex
);
462 //SecPointer<Policy> pol = Policy::required(SecPolicyRef(secPol));
463 Policy
*pol
= Policy::required(secPol
);
464 const CssmOid
&oid
= pol
->oid(); // required
465 const CssmData
&optData
= pol
->value(); // optional
468 if(oid
== CssmOid::overlay(CSSMOID_APPLE_TP_REVOCATION_CRL
)) {
469 /* currently no CRL-specific policy data */
471 else if(oid
== CssmOid::overlay(CSSMOID_APPLE_TP_REVOCATION_OCSP
)) {
472 CSSM_APPLE_TP_OCSP_OPTIONS
*opts
= (CSSM_APPLE_TP_OCSP_OPTIONS
*)optData
.Data
;
473 if(opts
->LocalResponder
!= NULL
) {
474 if(opts
->LocalResponder
->Data
!= NULL
) {
475 alloc
.free(opts
->LocalResponder
->Data
);
477 alloc
.free(opts
->LocalResponder
);
480 // managed by Policy alloc.free(optData.Data);
486 * Comparator function to correctly order revocation policies.
488 static CFComparisonResult
compareRevocationPolicies(
493 SecPointer
<Policy
> pol1
= Policy::required(SecPolicyRef(policy1
));
494 SecPointer
<Policy
> pol2
= Policy::required(SecPolicyRef(policy2
));
495 const CssmOid
&oid1
= pol1
->oid();
496 const CssmOid
&oid2
= pol2
->oid();
498 return kCFCompareEqualTo
;
500 bool ocspFirst
= true;
501 if(context
!= NULL
&& CFEqual((CFBooleanRef
)context
, kCFBooleanFalse
)) {
504 const CssmOid lastRevocationOid
= (ocspFirst
) ?
505 CssmOid::overlay(CSSMOID_APPLE_TP_REVOCATION_CRL
) :
506 CssmOid::overlay(CSSMOID_APPLE_TP_REVOCATION_OCSP
);
507 const CssmOid firstRevocationOid
= (ocspFirst
) ?
508 CssmOid::overlay(CSSMOID_APPLE_TP_REVOCATION_OCSP
) :
509 CssmOid::overlay(CSSMOID_APPLE_TP_REVOCATION_CRL
);
510 if(oid1
== lastRevocationOid
) {
511 /* should be ordered last, after all other policies */
512 return kCFCompareGreaterThan
;
514 if(oid1
== firstRevocationOid
) {
515 /* should be ordered after any policy except lastRevocationOid */
516 if(oid2
== lastRevocationOid
) {
517 return kCFCompareLessThan
;
519 return kCFCompareGreaterThan
;
521 /* normal policy in first position, anything else in second position */
522 return kCFCompareLessThan
;
526 * This method reorders any revocation policies which may be present
527 * in the provided array so they are at the end and evaluated last.
529 void Trust::orderRevocationPolicies(
530 CFMutableArrayRef policies
)
532 if(!policies
|| CFGetTypeID(policies
) != CFArrayGetTypeID()) {
535 /* check revocation prefs to determine which policy goes first */
536 CFBooleanRef ocspFirst
= kCFBooleanTrue
;
537 Dictionary
* pd
= Dictionary::CreateDictionary(kSecRevocationDomain
, Dictionary::US_User
, true);
542 auto_ptr
<Dictionary
> prefsDict(pd
);
543 CFStringRef val
= prefsDict
->getStringValue(kSecRevocationWhichFirst
);
544 if((val
!= NULL
) && CFEqual(val
, kSecRevocationCrlFirst
)) {
545 ocspFirst
= kCFBooleanFalse
;
550 CFShow(policies
); // before sort
551 CFArraySortValues(policies
, CFRangeMake(0, CFArrayGetCount(policies
)), compareRevocationPolicies
, (void*)ocspFirst
);
552 CFShow(policies
); // after sort, to see what changed
553 // check that policy order is what we expect
554 CFIndex numPolicies
= CFArrayGetCount(policies
);
555 for(CFIndex dex
=0; dex
<numPolicies
; dex
++) {
556 SecPolicyRef secPol
= (SecPolicyRef
)CFArrayGetValueAtIndex(policies
, dex
);
557 SecPointer
<Policy
> pol
= Policy::required(SecPolicyRef(secPol
));
558 const CssmOid
&oid
= pol
->oid();
559 if(oid
== CssmOid::overlay(CSSMOID_APPLE_TP_REVOCATION_OCSP
)) {
560 CFStringRef s
= CFStringCreateWithFormat(NULL
, NULL
, CFSTR("idx %d = OCSP"), dex
);
564 else if(oid
== CssmOid::overlay(CSSMOID_APPLE_TP_REVOCATION_CRL
)) {
565 CFStringRef s
= CFStringCreateWithFormat(NULL
, NULL
, CFSTR("idx %d = CRL"), dex
);
570 CFStringRef s
= CFStringCreateWithFormat(NULL
, NULL
, CFSTR("idx %d = normal"), dex
);
576 CFArraySortValues(policies
, CFRangeMake(0, CFArrayGetCount(policies
)), compareRevocationPolicies
, (void*)ocspFirst
);
581 * This method returns a copy of the mPolicies array which ensures that
582 * revocation checking (preferably OCSP, otherwise CRL) will be attempted.
584 * If OCSP is already in the mPolicies array, this makes sure the
585 * CSSM_TP_ACTION_OCSP_REQUIRE_IF_RESP_PRESENT and CSSM_TP_ACTION_OCSP_SUFFICIENT
586 * flags are set. If it's not already in the array, a new policy object is added.
588 * If CRL is already in the mPolicies array, this makes sure the
589 * CSSM_TP_ACTION_FETCH_CRL_FROM_NET and CSSM_TP_ACTION_CRL_SUFFICIENT flags are
590 * set. If it's not already in the array, a new policy object is added.
592 * Caller is responsible for releasing the returned policies array.
594 CFMutableArrayRef
Trust::forceRevocationPolicies(
601 SecPointer
<Policy
> ocspPolicy
;
602 SecPointer
<Policy
> crlPolicy
;
603 CSSM_APPLE_TP_OCSP_OPT_FLAGS ocspFlags
;
604 CSSM_APPLE_TP_CRL_OPT_FLAGS crlFlags
;
605 bool hasOcspPolicy
= false;
606 bool hasCrlPolicy
= false;
609 ocspFlags
= CSSM_TP_ACTION_OCSP_SUFFICIENT
;
610 crlFlags
= CSSM_TP_ACTION_FETCH_CRL_FROM_NET
| CSSM_TP_ACTION_CRL_SUFFICIENT
;
611 if (requirePerCert
) {
612 ocspFlags
|= CSSM_TP_ACTION_OCSP_REQUIRE_IF_RESP_PRESENT
;
613 crlFlags
|= CSSM_TP_ACTION_REQUIRE_CRL_IF_PRESENT
;
616 CFIndex numPolicies
= (mPolicies
) ? CFArrayGetCount(mPolicies
) : 0;
617 for(CFIndex dex
=0; dex
<numPolicies
; dex
++) {
618 SecPolicyRef secPol
= (SecPolicyRef
)CFArrayGetValueAtIndex(mPolicies
, dex
);
619 SecPointer
<Policy
> pol
= Policy::required(SecPolicyRef(secPol
));
620 const CssmOid
&oid
= pol
->oid();
621 const CssmData
&optData
= pol
->value();
622 if(oid
== CssmOid::overlay(CSSMOID_APPLE_TP_REVOCATION_OCSP
)) {
623 // make sure OCSP options are set correctly
624 CSSM_APPLE_TP_OCSP_OPTIONS
*opts
= (CSSM_APPLE_TP_OCSP_OPTIONS
*)optData
.Data
;
626 opts
->Flags
|= ocspFlags
;
628 CSSM_APPLE_TP_OCSP_OPTIONS newOpts
;
629 memset(&newOpts
, 0, sizeof(newOpts
));
630 newOpts
.Version
= CSSM_APPLE_TP_OCSP_OPTS_VERSION
;
631 newOpts
.Flags
= ocspFlags
;
632 CSSM_DATA optData
= {sizeof(newOpts
), (uint8
*)&newOpts
};
633 pol
->value() = optData
;
635 hasOcspPolicy
= true;
637 else if(oid
== CssmOid::overlay(CSSMOID_APPLE_TP_REVOCATION_CRL
)) {
638 // make sure CRL options are set correctly
639 CSSM_APPLE_TP_CRL_OPTIONS
*opts
= (CSSM_APPLE_TP_CRL_OPTIONS
*)optData
.Data
;
641 opts
->CrlFlags
|= crlFlags
;
643 CSSM_APPLE_TP_CRL_OPTIONS newOpts
;
644 memset(&newOpts
, 0, sizeof(newOpts
));
645 newOpts
.Version
= CSSM_APPLE_TP_CRL_OPTS_VERSION
;
646 newOpts
.CrlFlags
= crlFlags
;
647 CSSM_DATA optData
= {sizeof(newOpts
), (uint8
*)&newOpts
};
648 pol
->value() = optData
;
654 /* We're potentially adding something to mPolicies, so make a copy we can work with */
655 CFMutableArrayRef policies
= CFArrayCreateMutableCopy(NULL
, 0, mPolicies
);
656 if(policies
== NULL
) {
657 throw std::bad_alloc();
660 if(!hasOcspPolicy
&& ocspEnabled
) {
661 /* Cook up a new Policy object */
662 ocspPolicy
= new Policy(mTP
, CssmOid::overlay(CSSMOID_APPLE_TP_REVOCATION_OCSP
));
663 CSSM_APPLE_TP_OCSP_OPTIONS opts
;
664 memset(&opts
, 0, sizeof(opts
));
665 opts
.Version
= CSSM_APPLE_TP_OCSP_OPTS_VERSION
;
666 opts
.Flags
= ocspFlags
;
668 /* Check prefs dict for local responder info */
669 Dictionary
*prefsDict
= NULL
;
670 try { /* per-user prefs */
671 prefsDict
= Dictionary::CreateDictionary(kSecRevocationDomain
, Dictionary::US_User
, true);
672 if (!prefsDict
->dict()) {
678 if(prefsDict
== NULL
) {
679 try { /* system prefs */
680 prefsDict
= Dictionary::CreateDictionary(kSecRevocationDomain
, Dictionary::US_System
, true);
681 if (!prefsDict
->dict()) {
688 if(prefsDict
!= NULL
) {
689 CFStringRef val
= prefsDict
->getStringValue(kSecOCSPLocalResponder
);
691 CFDataRef cfData
= CFStringCreateExternalRepresentation(NULL
,
692 val
, kCFStringEncodingUTF8
, 0);
693 CFIndex len
= CFDataGetLength(cfData
);
694 opts
.LocalResponder
= (CSSM_DATA_PTR
)alloc
.malloc(sizeof(CSSM_DATA
));
695 opts
.LocalResponder
->Data
= (uint8
*)alloc
.malloc(len
);
696 opts
.LocalResponder
->Length
= len
;
697 memmove(opts
.LocalResponder
->Data
, CFDataGetBytePtr(cfData
), len
);
702 /* Policy manages its own copy of the options data */
703 CSSM_DATA optData
= {sizeof(opts
), (uint8
*)&opts
};
704 ocspPolicy
->value() = optData
;
706 /* Policies array retains the Policy object */
707 CFArrayAppendValue(policies
, ocspPolicy
->handle(false));
710 if(prefsDict
!= NULL
)
714 if(!hasCrlPolicy
&& crlEnabled
) {
715 /* Cook up a new Policy object */
716 crlPolicy
= new Policy(mTP
, CssmOid::overlay(CSSMOID_APPLE_TP_REVOCATION_CRL
));
717 CSSM_APPLE_TP_CRL_OPTIONS opts
;
718 memset(&opts
, 0, sizeof(opts
));
719 opts
.Version
= CSSM_APPLE_TP_CRL_OPTS_VERSION
;
720 opts
.CrlFlags
= crlFlags
;
722 /* Policy manages its own copy of this data */
723 CSSM_DATA optData
= {sizeof(opts
), (uint8
*)&opts
};
724 crlPolicy
->value() = optData
;
726 /* Policies array retains the Policy object */
727 CFArrayAppendValue(policies
, crlPolicy
->handle(false));