]> git.saurik.com Git - apple/security.git/blob - libsecurity_keychain/lib/TrustRevocation.cpp
Security-55163.44.tar.gz
[apple/security.git] / libsecurity_keychain / lib / TrustRevocation.cpp
1 /*
2 * Copyright (c) 2002-2004 Apple Computer, 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 * TrustRevocation.cpp - private revocation policy manipulation
26 */
27
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>
35
36 /*
37 * These may go into an SPI header for the SecTrust object.
38 */
39 typedef enum {
40 /* this revocation policy disabled */
41 kSecDisabled,
42 /* try, but tolerate inability to complete */
43 kSecBestAttempt,
44 /* require successful revocation check if certificate indicates
45 * the policy is supported */
46 kSecRequireIfPresentInCertificate,
47 /* require for every cert */
48 kSecRequireForAllCertificates
49 } SecRevocationPolicyStyle;
50
51 using namespace KeychainCore;
52
53 /*
54 * Given an app-specified array of Policies, determine if at least one of them
55 * matches the given policy OID.
56 */
57 bool Trust::policySpecified(CFArrayRef policies, const CSSM_OID &inOid)
58 {
59 if(policies == NULL) {
60 return false;
61 }
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)) {
68 return true;
69 }
70 }
71 return false;
72 }
73
74 /*
75 * Given an app-specified array of Policies, determine if at least one of them
76 * is an explicit revocation policy.
77 */
78 bool Trust::revocationPolicySpecified(CFArrayRef policies)
79 {
80 if(policies == NULL) {
81 return false;
82 }
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)) {
89 return true;
90 }
91 if(oid == CssmOid::overlay(CSSMOID_APPLE_TP_REVOCATION_OCSP)) {
92 return true;
93 }
94 }
95 return false;
96 }
97
98 CFMutableArrayRef Trust::addSpecifiedRevocationPolicies(
99 uint32 &numAdded,
100 Allocator &alloc)
101 {
102 /* policies specified by SPI not implemented */
103 return NULL;
104 }
105
106 void Trust::freeSpecifiedRevocationPolicies(
107 CFArrayRef policies,
108 uint32 numAdded,
109 Allocator &alloc)
110 {
111 /* shouldn't be called */
112 MacOSError::throwMe(unimpErr);
113 }
114
115 static SecRevocationPolicyStyle parseRevStyle(CFStringRef val)
116 {
117 if(CFEqual(val, kSecRevocationOff)) {
118 return kSecDisabled;
119 }
120 else if(CFEqual(val, kSecRevocationBestAttempt)) {
121 return kSecBestAttempt;
122 }
123 else if(CFEqual(val, kSecRevocationRequireIfPresent)) {
124 return kSecRequireIfPresentInCertificate;
125 }
126 else if(CFEqual(val, kSecRevocationRequireForAll)) {
127 return kSecRequireForAllCertificates;
128 }
129 else {
130 return kSecDisabled;
131 }
132 }
133
134 CFDictionaryRef Trust::defaultRevocationSettings()
135 {
136 /*
137 defaults read ~/Library/Preferences/com.apple.security.revocation
138 {
139 CRLStyle = BestAttempt;
140 CRLSufficientPerCert = 1;
141 OCSPStyle = BestAttempt;
142 OCSPSufficientPerCert = 1;
143 RevocationFirst = OCSP;
144 }
145 */
146 const void *keys[] = {
147 kSecRevocationCrlStyle,
148 kSecRevocationCRLSufficientPerCert,
149 kSecRevocationOcspStyle,
150 kSecRevocationOCSPSufficientPerCert,
151 kSecRevocationWhichFirst
152 };
153 const void *values[] = {
154 kSecRevocationBestAttempt,
155 kCFBooleanTrue,
156 kSecRevocationBestAttempt,
157 kCFBooleanTrue,
158 kSecRevocationOcspFirst
159 };
160
161 return CFDictionaryCreate(kCFAllocatorDefault, keys,
162 values, sizeof(keys) / sizeof(*keys),
163 &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
164 }
165
166 CFMutableArrayRef Trust::addPreferenceRevocationPolicies(
167 uint32 &numAdded,
168 Allocator &alloc)
169 {
170 numAdded = 0;
171
172 /* any per-user prefs? */
173 Dictionary* pd = Dictionary::CreateDictionary(kSecRevocationDomain, Dictionary::US_User, true);
174 if (pd)
175 {
176 if (!pd->dict()) {
177 delete pd;
178 pd = NULL;
179 }
180 }
181
182 if(pd == NULL)
183 {
184 pd = Dictionary::CreateDictionary(kSecRevocationDomain, Dictionary::US_System, true);
185 if (!pd->dict()) {
186 delete pd;
187 pd = NULL;
188 }
189 }
190
191 if(pd == NULL)
192 {
193 CFDictionaryRef tempDict = defaultRevocationSettings();
194 if (tempDict == NULL)
195 return NULL;
196
197 pd = new Dictionary(tempDict);
198 CFRelease(tempDict);
199 }
200
201 auto_ptr<Dictionary> prefsDict(pd);
202
203 bool doOcsp = false;
204 bool doCrl = false;
205 CFStringRef val;
206 SecRevocationPolicyStyle ocspStyle = kSecBestAttempt;
207 SecRevocationPolicyStyle crlStyle = kSecBestAttempt;
208 SecPointer<Policy> ocspPolicy;
209 SecPointer<Policy> crlPolicy;
210
211 /* Are any revocation policies enabled? */
212 val = prefsDict->getStringValue(kSecRevocationOcspStyle);
213 if(val != NULL) {
214 ocspStyle = parseRevStyle(val);
215 if(ocspStyle != kSecDisabled) {
216 doOcsp = true;
217 }
218 }
219 val = prefsDict->getStringValue(kSecRevocationCrlStyle);
220 if(val != NULL) {
221 crlStyle = parseRevStyle(val);
222 if(crlStyle != kSecDisabled) {
223 doCrl = true;
224 }
225 }
226 if(!doCrl && !doOcsp) {
227 return NULL;
228 }
229
230 /* which policy first? */
231 bool ocspFirst = true; // default if both present
232 if(doCrl && doOcsp) {
233 val = prefsDict->getStringValue(kSecRevocationWhichFirst);
234 if((val != NULL) && CFEqual(val, kSecRevocationCrlFirst)) {
235 ocspFirst = false;
236 }
237 }
238
239 /* We're adding something to mPolicies, so make a copy we can work with */
240 CFMutableArrayRef policies = CFArrayCreateMutableCopy(NULL, 0, mPolicies);
241 if(policies == NULL) {
242 throw std::bad_alloc();
243 }
244
245 if(doOcsp) {
246 /* Cook up a new Policy object */
247 ocspPolicy = new Policy(mTP, CssmOid::overlay(CSSMOID_APPLE_TP_REVOCATION_OCSP));
248 CSSM_APPLE_TP_OCSP_OPTIONS opts;
249 memset(&opts, 0, sizeof(opts));
250 opts.Version = CSSM_APPLE_TP_OCSP_OPTS_VERSION;
251
252 /* Now fill in the OCSP-related blanks */
253 switch(ocspStyle) {
254 case kSecDisabled:
255 assert(0);
256 break;
257 case kSecBestAttempt:
258 /* default, nothing to set */
259 break;
260 case kSecRequireIfPresentInCertificate:
261 opts.Flags |= CSSM_TP_ACTION_OCSP_REQUIRE_IF_RESP_PRESENT;
262 break;
263 case kSecRequireForAllCertificates:
264 opts.Flags |= CSSM_TP_ACTION_OCSP_REQUIRE_PER_CERT;
265 break;
266 }
267
268 if(prefsDict->getBoolValue(kSecRevocationOCSPSufficientPerCert)) {
269 opts.Flags |= CSSM_TP_ACTION_OCSP_SUFFICIENT;
270 }
271
272 val = prefsDict->getStringValue(kSecOCSPLocalResponder);
273 if(val != NULL) {
274 CFDataRef cfData = CFStringCreateExternalRepresentation(NULL,
275 val, kCFStringEncodingUTF8, 0);
276 CFIndex len = CFDataGetLength(cfData);
277 opts.LocalResponder = (CSSM_DATA_PTR)alloc.malloc(sizeof(CSSM_DATA));
278 opts.LocalResponder->Data = (uint8 *)alloc.malloc(len);
279 opts.LocalResponder->Length = len;
280 memmove(opts.LocalResponder->Data, CFDataGetBytePtr(cfData), len);
281 CFRelease(cfData);
282 }
283
284 /* Policy manages its own copy of this data */
285 CSSM_DATA optData = {sizeof(opts), (uint8 *)&opts};
286 ocspPolicy->value() = optData;
287 numAdded++;
288 }
289
290 if(doCrl) {
291 /* Cook up a new Policy object */
292 crlPolicy = new Policy(mTP, CssmOid::overlay(CSSMOID_APPLE_TP_REVOCATION_CRL));
293 CSSM_APPLE_TP_CRL_OPTIONS opts;
294 memset(&opts, 0, sizeof(opts));
295 opts.Version = CSSM_APPLE_TP_CRL_OPTS_VERSION;
296
297 /* Now fill in the CRL-related blanks */
298 opts.CrlFlags = CSSM_TP_ACTION_FETCH_CRL_FROM_NET; // default true
299 switch(crlStyle) {
300 case kSecDisabled:
301 assert(0);
302 break;
303 case kSecBestAttempt:
304 /* default, nothing to set */
305 break;
306 case kSecRequireIfPresentInCertificate:
307 opts.CrlFlags |= CSSM_TP_ACTION_REQUIRE_CRL_IF_PRESENT;
308 break;
309 case kSecRequireForAllCertificates:
310 opts.CrlFlags |= CSSM_TP_ACTION_REQUIRE_CRL_PER_CERT;
311 break;
312 }
313 if(prefsDict->getBoolValue(kSecRevocationCRLSufficientPerCert)) {
314 opts.CrlFlags |= CSSM_TP_ACTION_CRL_SUFFICIENT;
315 }
316
317 /* Policy manages its own copy of this data */
318 CSSM_DATA optData = {sizeof(opts), (uint8 *)&opts};
319 crlPolicy->value() = optData;
320 numAdded++;
321 }
322
323 /* append in order */
324 if(doOcsp) {
325 if(doCrl) {
326 if(ocspFirst) {
327 /* these SecCFObject go away when the policies array does */
328 CFArrayAppendValue(policies, ocspPolicy->handle(false));
329 CFArrayAppendValue(policies, crlPolicy->handle(false));
330 }
331 else {
332 CFArrayAppendValue(policies, crlPolicy->handle(false));
333 CFArrayAppendValue(policies, ocspPolicy->handle(false));
334 }
335 }
336 else {
337 CFArrayAppendValue(policies, ocspPolicy->handle(false));
338 }
339
340 }
341 else {
342 assert(doCrl);
343 CFArrayAppendValue(policies, crlPolicy->handle(false));
344 }
345 return policies;
346 }
347
348 /*
349 * Called when we created the last numAdded Policies in the specified Policy array
350 */
351 void Trust::freePreferenceRevocationPolicies(
352 CFArrayRef policies,
353 uint32 numAdded,
354 Allocator &alloc)
355 {
356 uint32 numPolicies = (uint32)CFArrayGetCount(policies);
357 if(numPolicies < numAdded) {
358 /* should never happen - throw? */
359 assert(0);
360 return;
361 }
362 for(unsigned dex=numPolicies-numAdded; dex<numPolicies; dex++) {
363 SecPolicyRef secPol = (SecPolicyRef)CFArrayGetValueAtIndex(policies, dex);
364 //SecPointer<Policy> pol = Policy::required(SecPolicyRef(secPol));
365 Policy *pol = Policy::required(secPol);
366 const CssmOid &oid = pol->oid(); // required
367 const CssmData &optData = pol->value(); // optional
368
369 if(optData.Data) {
370 if(oid == CssmOid::overlay(CSSMOID_APPLE_TP_REVOCATION_CRL)) {
371 /* currently no CRL-specific policy data */
372 }
373 else if(oid == CssmOid::overlay(CSSMOID_APPLE_TP_REVOCATION_OCSP)) {
374 CSSM_APPLE_TP_OCSP_OPTIONS *opts = (CSSM_APPLE_TP_OCSP_OPTIONS *)optData.Data;
375 if(opts->LocalResponder != NULL) {
376 if(opts->LocalResponder->Data != NULL) {
377 alloc.free(opts->LocalResponder->Data);
378 }
379 alloc.free(opts->LocalResponder);
380 }
381 }
382 // managed by Policy alloc.free(optData.Data);
383 }
384 }
385 CFRelease(policies);
386 }
387
388 /*
389 * Comparator function to correctly order revocation policies.
390 */
391 static CFComparisonResult compareRevocationPolicies(
392 const void *policy1,
393 const void *policy2,
394 void *context)
395 {
396 SecPointer<Policy> pol1 = Policy::required(SecPolicyRef(policy1));
397 SecPointer<Policy> pol2 = Policy::required(SecPolicyRef(policy2));
398 const CssmOid &oid1 = pol1->oid();
399 const CssmOid &oid2 = pol2->oid();
400 if(oid1 == oid2) {
401 return kCFCompareEqualTo;
402 }
403 bool ocspFirst = true;
404 if(context != NULL && CFEqual((CFBooleanRef)context, kCFBooleanFalse)) {
405 ocspFirst = false;
406 }
407 const CssmOid lastRevocationOid = (ocspFirst) ?
408 CssmOid::overlay(CSSMOID_APPLE_TP_REVOCATION_CRL) :
409 CssmOid::overlay(CSSMOID_APPLE_TP_REVOCATION_OCSP);
410 const CssmOid firstRevocationOid = (ocspFirst) ?
411 CssmOid::overlay(CSSMOID_APPLE_TP_REVOCATION_OCSP) :
412 CssmOid::overlay(CSSMOID_APPLE_TP_REVOCATION_CRL);
413 if(oid1 == lastRevocationOid) {
414 /* should be ordered last, after all other policies */
415 return kCFCompareGreaterThan;
416 }
417 if(oid1 == firstRevocationOid) {
418 /* should be ordered after any policy except lastRevocationOid */
419 if(oid2 == lastRevocationOid) {
420 return kCFCompareLessThan;
421 }
422 return kCFCompareGreaterThan;
423 }
424 /* normal policy in first position, anything else in second position */
425 return kCFCompareLessThan;
426 }
427
428 /*
429 * This method reorders any revocation policies which may be present
430 * in the provided array so they are at the end and evaluated last.
431 */
432 void Trust::orderRevocationPolicies(
433 CFMutableArrayRef policies)
434 {
435 if(!policies || CFGetTypeID(policies) != CFArrayGetTypeID()) {
436 return;
437 }
438 /* check revocation prefs to determine which policy goes first */
439 CFBooleanRef ocspFirst = kCFBooleanTrue;
440 Dictionary* pd = Dictionary::CreateDictionary(kSecRevocationDomain, Dictionary::US_User, true);
441 if (pd) {
442 if (!pd->dict()) {
443 delete pd;
444 } else {
445 auto_ptr<Dictionary> prefsDict(pd);
446 CFStringRef val = prefsDict->getStringValue(kSecRevocationWhichFirst);
447 if((val != NULL) && CFEqual(val, kSecRevocationCrlFirst)) {
448 ocspFirst = kCFBooleanFalse;
449 }
450 }
451 }
452 #if POLICIES_DEBUG
453 CFShow(policies); // before sort
454 CFArraySortValues(policies, CFRangeMake(0, CFArrayGetCount(policies)), compareRevocationPolicies, (void*)ocspFirst);
455 CFShow(policies); // after sort, to see what changed
456 // check that policy order is what we expect
457 CFIndex numPolicies = CFArrayGetCount(policies);
458 for(CFIndex dex=0; dex<numPolicies; dex++) {
459 SecPolicyRef secPol = (SecPolicyRef)CFArrayGetValueAtIndex(policies, dex);
460 SecPointer<Policy> pol = Policy::required(SecPolicyRef(secPol));
461 const CssmOid &oid = pol->oid();
462 if(oid == CssmOid::overlay(CSSMOID_APPLE_TP_REVOCATION_OCSP)) {
463 CFStringRef s = CFStringCreateWithFormat(NULL, NULL, CFSTR("idx %d = OCSP"), dex);
464 CFShow(s);
465 CFRelease(s);
466 }
467 else if(oid == CssmOid::overlay(CSSMOID_APPLE_TP_REVOCATION_CRL)) {
468 CFStringRef s = CFStringCreateWithFormat(NULL, NULL, CFSTR("idx %d = CRL"), dex);
469 CFShow(s);
470 CFRelease(s);
471 }
472 else {
473 CFStringRef s = CFStringCreateWithFormat(NULL, NULL, CFSTR("idx %d = normal"), dex);
474 CFShow(s);
475 CFRelease(s);
476 }
477 }
478 #else
479 CFArraySortValues(policies, CFRangeMake(0, CFArrayGetCount(policies)), compareRevocationPolicies, (void*)ocspFirst);
480 #endif
481 }
482
483 /*
484 * This method returns a copy of the mPolicies array which ensures that
485 * revocation checking (preferably OCSP, otherwise CRL) will be attempted.
486 *
487 * If OCSP is already in the mPolicies array, this makes sure the
488 * CSSM_TP_ACTION_OCSP_REQUIRE_IF_RESP_PRESENT and CSSM_TP_ACTION_OCSP_SUFFICIENT
489 * flags are set. If it's not already in the array, a new policy object is added.
490 *
491 * If CRL is already in the mPolicies array, this makes sure the
492 * CSSM_TP_ACTION_FETCH_CRL_FROM_NET and CSSM_TP_ACTION_CRL_SUFFICIENT flags are
493 * set. If it's not already in the array, a new policy object is added.
494 *
495 * Caller is responsible for releasing the returned policies array.
496 */
497 CFMutableArrayRef Trust::forceRevocationPolicies(
498 uint32 &numAdded,
499 Allocator &alloc,
500 bool requirePerCert)
501 {
502 SecPointer<Policy> ocspPolicy;
503 SecPointer<Policy> crlPolicy;
504 CSSM_APPLE_TP_OCSP_OPT_FLAGS ocspFlags;
505 CSSM_APPLE_TP_CRL_OPT_FLAGS crlFlags;
506 bool hasOcspPolicy = false;
507 bool hasCrlPolicy = false;
508 numAdded = 0;
509
510 ocspFlags = CSSM_TP_ACTION_OCSP_SUFFICIENT;
511 crlFlags = CSSM_TP_ACTION_FETCH_CRL_FROM_NET | CSSM_TP_ACTION_CRL_SUFFICIENT;
512 if (requirePerCert) {
513 ocspFlags |= CSSM_TP_ACTION_OCSP_REQUIRE_IF_RESP_PRESENT;
514 crlFlags |= CSSM_TP_ACTION_REQUIRE_CRL_IF_PRESENT;
515 }
516
517 CFIndex numPolicies = (mPolicies) ? CFArrayGetCount(mPolicies) : 0;
518 for(CFIndex dex=0; dex<numPolicies; dex++) {
519 SecPolicyRef secPol = (SecPolicyRef)CFArrayGetValueAtIndex(mPolicies, dex);
520 SecPointer<Policy> pol = Policy::required(SecPolicyRef(secPol));
521 const CssmOid &oid = pol->oid();
522 const CssmData &optData = pol->value();
523 if(oid == CssmOid::overlay(CSSMOID_APPLE_TP_REVOCATION_OCSP)) {
524 // make sure OCSP options are set correctly
525 CSSM_APPLE_TP_OCSP_OPTIONS *opts = (CSSM_APPLE_TP_OCSP_OPTIONS *)optData.Data;
526 if (opts) {
527 opts->Flags |= ocspFlags;
528 } else {
529 CSSM_APPLE_TP_OCSP_OPTIONS newOpts;
530 memset(&newOpts, 0, sizeof(newOpts));
531 newOpts.Version = CSSM_APPLE_TP_OCSP_OPTS_VERSION;
532 newOpts.Flags = ocspFlags;
533 CSSM_DATA optData = {sizeof(newOpts), (uint8 *)&newOpts};
534 pol->value() = optData;
535 }
536 hasOcspPolicy = true;
537 }
538 else if(oid == CssmOid::overlay(CSSMOID_APPLE_TP_REVOCATION_CRL)) {
539 // make sure CRL options are set correctly
540 CSSM_APPLE_TP_CRL_OPTIONS *opts = (CSSM_APPLE_TP_CRL_OPTIONS *)optData.Data;
541 if (opts) {
542 opts->CrlFlags |= crlFlags;
543 } else {
544 CSSM_APPLE_TP_CRL_OPTIONS newOpts;
545 memset(&newOpts, 0, sizeof(newOpts));
546 newOpts.Version = CSSM_APPLE_TP_CRL_OPTS_VERSION;
547 newOpts.CrlFlags = crlFlags;
548 CSSM_DATA optData = {sizeof(newOpts), (uint8 *)&newOpts};
549 pol->value() = optData;
550 }
551 hasCrlPolicy = true;
552 }
553 }
554
555 /* We're potentially adding something to mPolicies, so make a copy we can work with */
556 CFMutableArrayRef policies = CFArrayCreateMutableCopy(NULL, 0, mPolicies);
557 if(policies == NULL) {
558 throw std::bad_alloc();
559 }
560
561 if(!hasOcspPolicy) {
562 /* Cook up a new Policy object */
563 ocspPolicy = new Policy(mTP, CssmOid::overlay(CSSMOID_APPLE_TP_REVOCATION_OCSP));
564 CSSM_APPLE_TP_OCSP_OPTIONS opts;
565 memset(&opts, 0, sizeof(opts));
566 opts.Version = CSSM_APPLE_TP_OCSP_OPTS_VERSION;
567 opts.Flags = ocspFlags;
568
569 /* Check prefs dict for local responder info */
570 Dictionary *prefsDict = NULL;
571 try { /* per-user prefs */
572 prefsDict = Dictionary::CreateDictionary(kSecRevocationDomain, Dictionary::US_User, true);
573 if (!prefsDict->dict()) {
574 delete prefsDict;
575 prefsDict = NULL;
576 }
577 }
578 catch(...) {}
579 if(prefsDict == NULL) {
580 try { /* system prefs */
581 prefsDict = Dictionary::CreateDictionary(kSecRevocationDomain, Dictionary::US_System, true);
582 if (!prefsDict->dict()) {
583 delete prefsDict;
584 prefsDict = NULL;
585 }
586 }
587 catch(...) {}
588 }
589 if(prefsDict != NULL) {
590 CFStringRef val = prefsDict->getStringValue(kSecOCSPLocalResponder);
591 if(val != NULL) {
592 CFDataRef cfData = CFStringCreateExternalRepresentation(NULL,
593 val, kCFStringEncodingUTF8, 0);
594 CFIndex len = CFDataGetLength(cfData);
595 opts.LocalResponder = (CSSM_DATA_PTR)alloc.malloc(sizeof(CSSM_DATA));
596 opts.LocalResponder->Data = (uint8 *)alloc.malloc(len);
597 opts.LocalResponder->Length = len;
598 memmove(opts.LocalResponder->Data, CFDataGetBytePtr(cfData), len);
599 CFRelease(cfData);
600 }
601 }
602
603 /* Policy manages its own copy of the options data */
604 CSSM_DATA optData = {sizeof(opts), (uint8 *)&opts};
605 ocspPolicy->value() = optData;
606
607 /* Policies array retains the Policy object */
608 CFArrayAppendValue(policies, ocspPolicy->handle(false));
609 numAdded++;
610
611 if(prefsDict != NULL)
612 delete prefsDict;
613 }
614
615 if(!hasCrlPolicy) {
616 /* Cook up a new Policy object */
617 crlPolicy = new Policy(mTP, CssmOid::overlay(CSSMOID_APPLE_TP_REVOCATION_CRL));
618 CSSM_APPLE_TP_CRL_OPTIONS opts;
619 memset(&opts, 0, sizeof(opts));
620 opts.Version = CSSM_APPLE_TP_CRL_OPTS_VERSION;
621 opts.CrlFlags = crlFlags;
622
623 /* Policy manages its own copy of this data */
624 CSSM_DATA optData = {sizeof(opts), (uint8 *)&opts};
625 crlPolicy->value() = optData;
626
627 /* Policies array retains the Policy object */
628 CFArrayAppendValue(policies, crlPolicy->handle(false));
629 numAdded++;
630 }
631
632 return policies;
633 }