]> git.saurik.com Git - apple/security.git/blob - OSX/libsecurity_cdsa_utils/lib/cuCdsaUtils.cpp
Security-57740.31.2.tar.gz
[apple/security.git] / OSX / libsecurity_cdsa_utils / lib / cuCdsaUtils.cpp
1 /*
2 * Copyright (c) 2001-2003,2011-2012,2014 Apple Inc. All Rights Reserved.
3 *
4 * The contents of this file constitute Original Code as defined in and are
5 * subject to the Apple Public Source License Version 1.2 (the 'License').
6 * You may not use this file except in compliance with the License. Please
7 * obtain a copy of the License at http://www.apple.com/publicsource and
8 * read it before using this file.
9 *
10 * This Original Code and all software distributed under the License are
11 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
12 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
13 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
14 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
15 * Please see the License for the specific language governing rights and
16 * limitations under the License.
17 */
18
19 /*
20 File: cuCdsaUtils.cpp
21
22 Description: common CDSA access utilities
23
24 Author: dmitch
25 */
26
27 #include "cuCdsaUtils.h"
28 #include <stdlib.h>
29 #include <stdio.h>
30 #include <Security/SecCertificate.h>
31 #include <Security/cssmapple.h> /* for cssmPerror() */
32 #include <Security/oidsalg.h>
33 #include <Security/TrustSettingsSchema.h>
34 #include <strings.h>
35
36 static CSSM_VERSION vers = {2, 0};
37 static const CSSM_GUID testGuid = { 0xFADE, 0, 0, { 1,2,3,4,5,6,7,0 }};
38
39 /*
40 * Standard app-level memory functions required by CDSA.
41 */
42 void * cuAppMalloc (CSSM_SIZE size, void *allocRef) {
43 return( malloc(size) );
44 }
45
46 void cuAppFree (void *mem_ptr, void *allocRef) {
47 free(mem_ptr);
48 return;
49 }
50
51 void * cuAppRealloc (void *ptr, CSSM_SIZE size, void *allocRef) {
52 return( realloc( ptr, size ) );
53 }
54
55 void * cuAppCalloc (uint32 num, CSSM_SIZE size, void *allocRef) {
56 return( calloc( num, size ) );
57 }
58
59 static CSSM_API_MEMORY_FUNCS memFuncs = {
60 cuAppMalloc,
61 cuAppFree,
62 cuAppRealloc,
63 cuAppCalloc,
64 NULL
65 };
66
67 CSSM_BOOL cuCompareCssmData(const CSSM_DATA *d1,
68 const CSSM_DATA *d2)
69 {
70 if(d1->Length != d2->Length) {
71 return CSSM_FALSE;
72 }
73 if(memcmp(d1->Data, d2->Data, d1->Length)) {
74 return CSSM_FALSE;
75 }
76 return CSSM_TRUE;
77 }
78
79 /*
80 * Init CSSM; returns CSSM_FALSE on error. Reusable.
81 */
82 static CSSM_BOOL cssmInitd = CSSM_FALSE;
83
84 CSSM_BOOL cuCssmStartup()
85 {
86 CSSM_RETURN crtn;
87 CSSM_PVC_MODE pvcPolicy = CSSM_PVC_NONE;
88
89 if(cssmInitd) {
90 return CSSM_TRUE;
91 }
92 crtn = CSSM_Init (&vers,
93 CSSM_PRIVILEGE_SCOPE_NONE,
94 &testGuid,
95 CSSM_KEY_HIERARCHY_NONE,
96 &pvcPolicy,
97 NULL /* reserved */);
98 if(crtn != CSSM_OK)
99 {
100 cuPrintError("CSSM_Init", crtn);
101 return CSSM_FALSE;
102 }
103 else {
104 cssmInitd = CSSM_TRUE;
105 return CSSM_TRUE;
106 }
107 }
108
109 /*
110 * Attach to CSP. Returns zero on error.
111 */
112 CSSM_CSP_HANDLE cuCspStartup(
113 CSSM_BOOL bareCsp) // true ==> CSP, false ==> CSP/DL
114 {
115 CSSM_CSP_HANDLE cspHand;
116 CSSM_RETURN crtn;
117 const CSSM_GUID *guid;
118
119 /* common CSSM init */
120 if(cuCssmStartup() == CSSM_FALSE) {
121 return 0;
122 }
123 if(bareCsp) {
124 guid = &gGuidAppleCSP;
125 }
126 else {
127 guid = &gGuidAppleCSPDL;
128 }
129 crtn = CSSM_ModuleLoad(guid,
130 CSSM_KEY_HIERARCHY_NONE,
131 NULL, // eventHandler
132 NULL); // AppNotifyCallbackCtx
133 if(crtn) {
134 cuPrintError("CSSM_ModuleLoad()", crtn);
135 return 0;
136 }
137 crtn = CSSM_ModuleAttach (guid,
138 &vers,
139 &memFuncs, // memFuncs
140 0, // SubserviceID
141 CSSM_SERVICE_CSP,
142 0, // AttachFlags
143 CSSM_KEY_HIERARCHY_NONE,
144 NULL, // FunctionTable
145 0, // NumFuncTable
146 NULL, // reserved
147 &cspHand);
148 if(crtn) {
149 cuPrintError("CSSM_ModuleAttach()", crtn);
150 return 0;
151 }
152 return cspHand;
153 }
154
155 /* Attach to DL side of CSPDL */
156 CSSM_DL_HANDLE cuDlStartup()
157 {
158 CSSM_DL_HANDLE dlHand = 0;
159 CSSM_RETURN crtn;
160
161 if(cuCssmStartup() == CSSM_FALSE) {
162 return 0;
163 }
164 crtn = CSSM_ModuleLoad(&gGuidAppleCSPDL,
165 CSSM_KEY_HIERARCHY_NONE,
166 NULL, // eventHandler
167 NULL); // AppNotifyCallbackCtx
168 if(crtn) {
169 cuPrintError("CSSM_ModuleLoad(Apple CSPDL)", crtn);
170 return 0;
171 }
172 crtn = CSSM_ModuleAttach (&gGuidAppleCSPDL,
173 &vers,
174 &memFuncs, // memFuncs
175 0, // SubserviceID
176 CSSM_SERVICE_DL,
177 0, // AttachFlags
178 CSSM_KEY_HIERARCHY_NONE,
179 NULL, // FunctionTable
180 0, // NumFuncTable
181 NULL, // reserved
182 &dlHand);
183 if(crtn) {
184 cuPrintError("CSSM_ModuleAttach(Apple CSPDL)", crtn);
185 return 0;
186 }
187 return dlHand;
188 }
189
190 CSSM_CL_HANDLE cuClStartup()
191 {
192 CSSM_CL_HANDLE clHand;
193 CSSM_RETURN crtn;
194
195 if(cuCssmStartup() == CSSM_FALSE) {
196 return 0;
197 }
198 crtn = CSSM_ModuleLoad(&gGuidAppleX509CL,
199 CSSM_KEY_HIERARCHY_NONE,
200 NULL, // eventHandler
201 NULL); // AppNotifyCallbackCtx
202 if(crtn) {
203 cuPrintError("CSSM_ModuleLoad(AppleCL)", crtn);
204 return 0;
205 }
206 crtn = CSSM_ModuleAttach (&gGuidAppleX509CL,
207 &vers,
208 &memFuncs, // memFuncs
209 0, // SubserviceID
210 CSSM_SERVICE_CL, // SubserviceFlags - Where is this used?
211 0, // AttachFlags
212 CSSM_KEY_HIERARCHY_NONE,
213 NULL, // FunctionTable
214 0, // NumFuncTable
215 NULL, // reserved
216 &clHand);
217 if(crtn) {
218 cuPrintError("CSSM_ModuleAttach(AppleCL)", crtn);
219 return 0;
220 }
221 else {
222 return clHand;
223 }
224 }
225
226 CSSM_TP_HANDLE cuTpStartup()
227 {
228 CSSM_TP_HANDLE tpHand;
229 CSSM_RETURN crtn;
230
231 if(cuCssmStartup() == CSSM_FALSE) {
232 return 0;
233 }
234 crtn = CSSM_ModuleLoad(&gGuidAppleX509TP,
235 CSSM_KEY_HIERARCHY_NONE,
236 NULL, // eventHandler
237 NULL); // AppNotifyCallbackCtx
238 if(crtn) {
239 cuPrintError("CSSM_ModuleLoad(AppleTP)", crtn);
240 return 0;
241 }
242 crtn = CSSM_ModuleAttach (&gGuidAppleX509TP,
243 &vers,
244 &memFuncs, // memFuncs
245 0, // SubserviceID
246 CSSM_SERVICE_TP, // SubserviceFlags
247 0, // AttachFlags
248 CSSM_KEY_HIERARCHY_NONE,
249 NULL, // FunctionTable
250 0, // NumFuncTable
251 NULL, // reserved
252 &tpHand);
253 if(crtn) {
254 cuPrintError("CSSM_ModuleAttach(AppleTP)", crtn);
255 return 0;
256 }
257 else {
258 return tpHand;
259 }
260 }
261
262 /* detach and unload */
263 CSSM_RETURN cuCspDetachUnload(
264 CSSM_CSP_HANDLE cspHand,
265 CSSM_BOOL bareCsp) // true ==> CSP, false ==> CSP/DL
266 {
267 CSSM_RETURN crtn = CSSM_ModuleDetach(cspHand);
268 if(crtn) {
269 return crtn;
270 }
271 const CSSM_GUID *guid;
272 if(bareCsp) {
273 guid = &gGuidAppleCSP;
274 }
275 else {
276 guid = &gGuidAppleCSPDL;
277 }
278 return CSSM_ModuleUnload(guid, NULL, NULL);
279 }
280
281 CSSM_RETURN cuClDetachUnload(
282 CSSM_CL_HANDLE clHand)
283 {
284 CSSM_RETURN crtn = CSSM_ModuleDetach(clHand);
285 if(crtn) {
286 return crtn;
287 }
288 return CSSM_ModuleUnload(&gGuidAppleX509CL, NULL, NULL);
289
290 }
291
292 CSSM_RETURN cuDlDetachUnload(
293 CSSM_DL_HANDLE dlHand)
294 {
295 CSSM_RETURN crtn = CSSM_ModuleDetach(dlHand);
296 if(crtn) {
297 return crtn;
298 }
299 return CSSM_ModuleUnload(&gGuidAppleCSPDL, NULL, NULL);
300
301 }
302 CSSM_RETURN cuTpDetachUnload(
303 CSSM_TP_HANDLE tpHand)
304 {
305 CSSM_RETURN crtn = CSSM_ModuleDetach(tpHand);
306 if(crtn) {
307 return crtn;
308 }
309 return CSSM_ModuleUnload(&gGuidAppleX509TP, NULL, NULL);
310
311 }
312
313 /*
314 * open a DB, ensure it's empty.
315 */
316 CSSM_DB_HANDLE cuDbStartup(
317 CSSM_DL_HANDLE dlHand, // from dlStartup()
318 const char *dbName)
319 {
320 CSSM_DB_HANDLE dbHand = 0;
321 CSSM_RETURN crtn;
322 CSSM_DBINFO dbInfo;
323
324 /* first delete possible existing DB, ignore error */
325 crtn = CSSM_DL_DbDelete(dlHand, dbName, NULL, NULL);
326 switch(crtn) {
327 /* only allowed error is "no such file" */
328 case CSSM_OK:
329 case CSSMERR_DL_DATASTORE_DOESNOT_EXIST:
330 break;
331 default:
332 cuPrintError("CSSM_DL_DbDelete", crtn);
333 return 0;
334 }
335
336 memset(&dbInfo, 0, sizeof(CSSM_DBINFO));
337
338 /* now create it */
339 crtn = CSSM_DL_DbCreate(dlHand,
340 dbName,
341 NULL, // DbLocation
342 &dbInfo,
343 // &Security::KeychainCore::Schema::DBInfo,
344 CSSM_DB_ACCESS_PRIVILEGED,
345 NULL, // CredAndAclEntry
346 NULL, // OpenParameters
347 &dbHand);
348 if(crtn) {
349 cuPrintError("CSSM_DL_DbCreate", crtn);
350 }
351 return dbHand;
352 }
353
354 /*
355 * Attach to existing DB or create an empty new one.
356 */
357 CSSM_DB_HANDLE cuDbStartupByName(CSSM_DL_HANDLE dlHand,
358 char *dbName,
359 CSSM_BOOL doCreate,
360 CSSM_BOOL quiet)
361 {
362 CSSM_RETURN crtn;
363 CSSM_DB_HANDLE dbHand;
364
365 /* try open existing DB in either case */
366
367 crtn = CSSM_DL_DbOpen(dlHand,
368 dbName,
369 NULL, // DbLocation
370 CSSM_DB_ACCESS_READ | CSSM_DB_ACCESS_WRITE,
371 NULL, // CSSM_ACCESS_CREDENTIALS *AccessCred
372 NULL, // void *OpenParameters
373 &dbHand);
374 if(crtn == CSSM_OK) {
375 return dbHand;
376 }
377 if(!doCreate) {
378 if(!quiet) {
379 printf("***no such data base (%s)\n", dbName);
380 cuPrintError("CSSM_DL_DbOpen", crtn);
381 }
382 return 0;
383 }
384 /* have to create one */
385 return cuDbStartup(dlHand, dbName);
386 }
387
388 /*
389 * Given a context specified via a CSSM_CC_HANDLE, add a new
390 * CSSM_CONTEXT_ATTRIBUTE to the context as specified by AttributeType,
391 * AttributeLength, and an untyped pointer.
392 */
393 static
394 CSSM_RETURN cuAddContextAttribute(CSSM_CC_HANDLE CCHandle,
395 uint32 AttributeType,
396 uint32 AttributeLength,
397 const void *AttributePtr)
398 {
399 CSSM_CONTEXT_ATTRIBUTE newAttr;
400 CSSM_RETURN crtn;
401
402 newAttr.AttributeType = AttributeType;
403 newAttr.AttributeLength = AttributeLength;
404 newAttr.Attribute.Data = (CSSM_DATA_PTR)AttributePtr;
405 crtn = CSSM_UpdateContextAttributes(CCHandle, 1, &newAttr);
406 if(crtn) {
407 cuPrintError("CSSM_UpdateContextAttributes", crtn);
408 }
409 return crtn;
410 }
411
412
413 /*
414 * Derive symmetric key.
415 * Note in the X CSP, we never return an IV.
416 */
417 CSSM_RETURN cuCspDeriveKey(CSSM_CSP_HANDLE cspHand,
418 uint32 keyAlg, // CSSM_ALGID_RC5, etc.
419 const char *keyLabel,
420 unsigned keyLabelLen,
421 uint32 keyUsage, // CSSM_KEYUSE_ENCRYPT, etc.
422 uint32 keySizeInBits,
423 CSSM_DATA_PTR password, // in PKCS-5 lingo
424 CSSM_DATA_PTR salt, // ditto
425 uint32 iterationCnt, // ditto
426 CSSM_KEY_PTR key)
427 {
428 CSSM_RETURN crtn;
429 CSSM_CC_HANDLE ccHand;
430 uint32 keyAttr;
431 CSSM_DATA dummyLabel;
432 CSSM_PKCS5_PBKDF2_PARAMS pbeParams;
433 CSSM_DATA pbeData;
434 CSSM_ACCESS_CREDENTIALS creds;
435
436 memset(key, 0, sizeof(CSSM_KEY));
437 memset(&creds, 0, sizeof(CSSM_ACCESS_CREDENTIALS));
438 crtn = CSSM_CSP_CreateDeriveKeyContext(cspHand,
439 CSSM_ALGID_PKCS5_PBKDF2,
440 keyAlg,
441 keySizeInBits,
442 &creds,
443 NULL, // BaseKey
444 iterationCnt,
445 salt,
446 NULL, // seed
447 &ccHand);
448 if(crtn) {
449 cuPrintError("CSSM_CSP_CreateDeriveKeyContext", crtn);
450 return crtn;
451 }
452 keyAttr = CSSM_KEYATTR_EXTRACTABLE | CSSM_KEYATTR_RETURN_REF |
453 CSSM_KEYATTR_SENSITIVE;
454 dummyLabel.Length = keyLabelLen;
455 dummyLabel.Data = (uint8 *)keyLabel;
456
457 /* passing in password is pretty strange....*/
458 pbeParams.Passphrase = *password;
459 pbeParams.PseudoRandomFunction = CSSM_PKCS5_PBKDF2_PRF_HMAC_SHA1;
460 pbeData.Data = (uint8 *)&pbeParams;
461 pbeData.Length = sizeof(pbeParams);
462 crtn = CSSM_DeriveKey(ccHand,
463 &pbeData,
464 keyUsage,
465 keyAttr,
466 &dummyLabel,
467 NULL, // cred and acl
468 key);
469 if(crtn) {
470 cuPrintError("CSSM_DeriveKey", crtn);
471 return crtn;
472 }
473 crtn = CSSM_DeleteContext(ccHand);
474 if(crtn) {
475 cuPrintError("CSSM_DeleteContext", crtn);
476 }
477 return crtn;
478 }
479
480 /*
481 * Generate key pair of arbitrary algorithm.
482 */
483
484 /* CSP DL currently does not perform DSA generate params; let CSP do it implicitly */
485 #define DO_DSA_GEN_PARAMS 0
486
487 CSSM_RETURN cuCspGenKeyPair(CSSM_CSP_HANDLE cspHand,
488 CSSM_DL_DB_HANDLE *dlDbHand, // optional
489 uint32 algorithm,
490 const char *keyLabel,
491 unsigned keyLabelLen,
492 uint32 keySize, // in bits
493 CSSM_KEY_PTR pubKey, // mallocd by caller
494 CSSM_KEYUSE pubKeyUsage, // CSSM_KEYUSE_ENCRYPT, etc.
495 CSSM_KEYATTR_FLAGS pubAttrs, // CSSM_KEYATTR_EXTRACTABLE, etc.
496 CSSM_KEY_PTR privKey, // mallocd by caller
497 CSSM_KEYUSE privKeyUsage, // CSSM_KEYUSE_DECRYPT, etc.
498 CSSM_KEYATTR_FLAGS privAttrs) // CSSM_KEYATTR_EXTRACTABLE, etc.
499 {
500 CSSM_RETURN crtn;
501 CSSM_RETURN ocrtn;
502 CSSM_CC_HANDLE ccHand;
503 CSSM_DATA keyLabelData;
504
505 keyLabelData.Data = (uint8 *)keyLabel,
506 keyLabelData.Length = keyLabelLen;
507 memset(pubKey, 0, sizeof(CSSM_KEY));
508 memset(privKey, 0, sizeof(CSSM_KEY));
509
510 crtn = CSSM_CSP_CreateKeyGenContext(cspHand,
511 algorithm,
512 keySize,
513 NULL, // Seed
514 NULL, // Salt
515 NULL, // StartDate
516 NULL, // EndDate
517 NULL, // Params
518 &ccHand);
519 if(crtn) {
520 cuPrintError("CSSM_CSP_CreateKeyGenContext", crtn);
521 return crtn;
522 }
523
524 /* post-context-create algorithm-specific stuff */
525 switch(algorithm) {
526 #if DO_DSA_GEN_PARAMS
527 case CSSM_ALGID_DSA:
528 /*
529 * extra step - generate params - this just adds some
530 * info to the context
531 */
532 {
533 CSSM_DATA dummy = {0, NULL};
534 crtn = CSSM_GenerateAlgorithmParams(ccHand,
535 keySize, &dummy);
536 if(crtn) {
537 cuPrintError("CSSM_GenerateAlgorithmParams", crtn);
538 CSSM_DeleteContext(ccHand);
539 return crtn;
540 }
541 cuAppFree(dummy.Data, NULL);
542 }
543 break;
544 #endif /* DO_DSA_GEN_PARAMS */
545 default:
546 break;
547 }
548
549 /* optionally specify DL/DB storage location */
550 if(dlDbHand) {
551 crtn = cuAddContextAttribute(ccHand,
552 CSSM_ATTRIBUTE_DL_DB_HANDLE,
553 sizeof(CSSM_ATTRIBUTE_DL_DB_HANDLE),
554 dlDbHand);
555 if(crtn) {
556 CSSM_DeleteContext(ccHand);
557 return crtn;
558 }
559 }
560 ocrtn = CSSM_GenerateKeyPair(ccHand,
561 pubKeyUsage,
562 pubAttrs,
563 &keyLabelData,
564 pubKey,
565 privKeyUsage,
566 privAttrs,
567 &keyLabelData, // same labels
568 NULL, // CredAndAclEntry
569 privKey);
570 if(ocrtn) {
571 cuPrintError("CSSM_GenerateKeyPair", ocrtn);
572 }
573 crtn = CSSM_DeleteContext(ccHand);
574 if(crtn) {
575 cuPrintError("CSSM_DeleteContext", crtn);
576 if(ocrtn == CSSM_OK) {
577 /* error on CSSM_GenerateKeyPair takes precedence */
578 ocrtn = crtn;
579 }
580 }
581 return ocrtn;
582 }
583
584
585 /*
586 * Add a certificate to an open Keychain.
587 */
588 CSSM_RETURN cuAddCertToKC(
589 SecKeychainRef keychain,
590 const CSSM_DATA *cert,
591 CSSM_CERT_TYPE certType,
592 CSSM_CERT_ENCODING certEncoding,
593 const char *printName, // C string
594 const CSSM_DATA *keyLabel) // ??
595 {
596 SecCertificateRef certificate;
597
598 OSStatus rslt = SecCertificateCreateFromData(cert, certType, certEncoding, &certificate);
599 if (!rslt)
600 {
601 rslt = SecCertificateAddToKeychain(certificate, keychain);
602 CFRelease(certificate);
603 }
604
605 return rslt;
606 }
607
608 /*
609 * Convert a CSSM_DATA_PTR, referring to a DER-encoded int, to an
610 * unsigned.
611 */
612 unsigned cuDER_ToInt(const CSSM_DATA *DER_Data)
613 {
614 uint32 rtn = 0;
615 unsigned i = 0;
616
617 while(i < DER_Data->Length) {
618 rtn |= DER_Data->Data[i];
619 if(++i == DER_Data->Length) {
620 break;
621 }
622 rtn <<= 8;
623 }
624 return rtn;
625 }
626
627 /*
628 * Log CSSM error.
629 */
630 void cuPrintError(const char *op, CSSM_RETURN err)
631 {
632 cssmPerror(op, err);
633 }
634
635 /*
636 * Verify a CRL against system anchors and intermediate certs.
637 */
638 CSSM_RETURN cuCrlVerify(
639 CSSM_TP_HANDLE tpHand,
640 CSSM_CL_HANDLE clHand,
641 CSSM_CSP_HANDLE cspHand,
642 const CSSM_DATA *crlData,
643 CSSM_DL_DB_HANDLE_PTR certKeychain, // intermediate certs
644 const CSSM_DATA *anchors, // optional - if NULL, use Trust Settings
645 uint32 anchorCount)
646 {
647 /* main job is building a CSSM_TP_VERIFY_CONTEXT and its components */
648 CSSM_TP_VERIFY_CONTEXT vfyCtx;
649 CSSM_TP_CALLERAUTH_CONTEXT authCtx;
650
651 memset(&vfyCtx, 0, sizeof(CSSM_TP_VERIFY_CONTEXT));
652 memset(&authCtx, 0, sizeof(CSSM_TP_CALLERAUTH_CONTEXT));
653
654 /* CSSM_TP_CALLERAUTH_CONTEXT components */
655 /*
656 typedef struct cssm_tp_callerauth_context {
657 CSSM_TP_POLICYINFO Policy;
658 CSSM_TIMESTRING VerifyTime;
659 CSSM_TP_STOP_ON VerificationAbortOn;
660 CSSM_TP_VERIFICATION_RESULTS_CALLBACK CallbackWithVerifiedCert;
661 uint32 NumberOfAnchorCerts;
662 CSSM_DATA_PTR AnchorCerts;
663 CSSM_DL_DB_LIST_PTR DBList;
664 CSSM_ACCESS_CREDENTIALS_PTR CallerCredentials;
665 } CSSM_TP_CALLERAUTH_CONTEXT, *CSSM_TP_CALLERAUTH_CONTEXT_PTR;
666 */
667 CSSM_FIELD policyId;
668 CSSM_APPLE_TP_CRL_OPTIONS crlOpts;
669 policyId.FieldOid = CSSMOID_APPLE_TP_REVOCATION_CRL;
670 policyId.FieldValue.Data = (uint8 *)&crlOpts;
671 policyId.FieldValue.Length = sizeof(crlOpts);
672 crlOpts.Version = CSSM_APPLE_TP_CRL_OPTS_VERSION;
673 /* perhaps this should be user-specifiable */
674 crlOpts.CrlFlags = CSSM_TP_ACTION_FETCH_CRL_FROM_NET;
675 crlOpts.crlStore = NULL;
676
677 authCtx.Policy.NumberOfPolicyIds = 1;
678 authCtx.Policy.PolicyIds = &policyId;
679 authCtx.Policy.PolicyControl = NULL;
680
681 authCtx.VerifyTime = NULL;
682 authCtx.VerificationAbortOn = CSSM_TP_STOP_ON_POLICY;
683 authCtx.CallbackWithVerifiedCert = NULL;
684
685 /* anchors */
686 authCtx.NumberOfAnchorCerts = anchorCount;
687 authCtx.AnchorCerts = const_cast<CSSM_DATA_PTR>(anchors);
688
689 /* DBList of intermediate certs, plus possible System.keychain and
690 * system roots */
691 CSSM_DL_DB_HANDLE handles[3];
692 unsigned numDbs = 0;
693 CSSM_DL_HANDLE dlHand = 0;
694 if(certKeychain != NULL) {
695 handles[0] = *certKeychain;
696 numDbs++;
697 }
698 if(anchors == NULL) {
699 /* Trust Settings requires two more DBs */
700 if(numDbs == 0) {
701 /* new DL handle */
702 dlHand = cuDlStartup();
703 handles[numDbs].DLHandle = dlHand;
704 handles[numDbs + 1].DLHandle = dlHand;
705 }
706 else {
707 /* use the same one passed in for certKeychain */
708 handles[numDbs].DLHandle = handles[0].DLHandle;
709 handles[numDbs + 1].DLHandle = handles[0].DLHandle;
710 }
711 handles[numDbs].DBHandle = cuDbStartupByName(handles[numDbs].DLHandle,
712 (char*) ADMIN_CERT_STORE_PATH, CSSM_FALSE, CSSM_TRUE);
713 numDbs++;
714
715 handles[numDbs].DBHandle = cuDbStartupByName(handles[numDbs].DLHandle,
716 (char*) SYSTEM_ROOT_STORE_PATH, CSSM_FALSE, CSSM_TRUE);
717 numDbs++;
718 }
719 CSSM_DL_DB_LIST dlDbList;
720 dlDbList.DLDBHandle = handles;
721 dlDbList.NumHandles = numDbs;
722
723 authCtx.DBList = &dlDbList;
724 authCtx.CallerCredentials = NULL;
725
726 /* CSSM_TP_VERIFY_CONTEXT */
727 vfyCtx.ActionData.Data = NULL;
728 vfyCtx.ActionData.Length = 0;
729 vfyCtx.Action = CSSM_TP_ACTION_DEFAULT;
730 vfyCtx.Cred = &authCtx;
731
732 /* CSSM_APPLE_TP_ACTION_DATA */
733 CSSM_APPLE_TP_ACTION_DATA tpAction;
734 if(anchors == NULL) {
735 /* enable Trust Settings */
736 tpAction.Version = CSSM_APPLE_TP_ACTION_VERSION;
737 tpAction.ActionFlags = CSSM_TP_ACTION_TRUST_SETTINGS;
738 vfyCtx.ActionData.Data = (uint8 *)&tpAction;
739 vfyCtx.ActionData.Length = sizeof(tpAction);
740 }
741
742 /* cook up CSSM_ENCODED_CRL */
743 CSSM_ENCODED_CRL encCrl;
744 encCrl.CrlType = CSSM_CRL_TYPE_X_509v2;
745 encCrl.CrlEncoding = CSSM_CRL_ENCODING_DER;
746 encCrl.CrlBlob = *crlData;
747
748 /* CDSA API requires a SignerCertGroup; for us, all the certs are in
749 * certKeyChain... */
750 CSSM_CERTGROUP certGroup;
751 certGroup.CertType = CSSM_CERT_X_509v1;
752 certGroup.CertEncoding = CSSM_CERT_ENCODING_DER;
753 certGroup.NumCerts = 0;
754 certGroup.GroupList.CertList = NULL;
755 certGroup.CertGroupType = CSSM_CERTGROUP_DATA;
756
757 CSSM_RETURN crtn = CSSM_TP_CrlVerify(tpHand,
758 clHand,
759 cspHand,
760 &encCrl,
761 &certGroup,
762 &vfyCtx,
763 NULL); // RevokerVerifyResult
764 if(crtn) {
765 cuPrintError("CSSM_TP_CrlVerify", crtn);
766 }
767 if(anchors == NULL) {
768 /* close the DBs and maybe the DL we opened */
769 unsigned dexToClose = (certKeychain == NULL) ? 0 : 1;
770 CSSM_DL_DbClose(handles[dexToClose++]);
771 CSSM_DL_DbClose(handles[dexToClose]);
772 if(dlHand != 0) {
773 cuDlDetachUnload(dlHand);
774 }
775 }
776 return crtn;
777 }
778