]> git.saurik.com Git - apple/security.git/blob - libsecurity_cdsa_utils/lib/cuCdsaUtils.cpp
Security-55163.44.tar.gz
[apple/security.git] / libsecurity_cdsa_utils / lib / cuCdsaUtils.cpp
1 /*
2 * Copyright (c) 2001-2003 Apple Computer, 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 CSSM_RETURN cuAddContextAttribute(CSSM_CC_HANDLE CCHandle,
394 uint32 AttributeType,
395 uint32 AttributeLength,
396 const void *AttributePtr)
397 {
398 CSSM_CONTEXT_ATTRIBUTE newAttr;
399 CSSM_RETURN crtn;
400
401 newAttr.AttributeType = AttributeType;
402 newAttr.AttributeLength = AttributeLength;
403 newAttr.Attribute.Data = (CSSM_DATA_PTR)AttributePtr;
404 crtn = CSSM_UpdateContextAttributes(CCHandle, 1, &newAttr);
405 if(crtn) {
406 cuPrintError("CSSM_UpdateContextAttributes", crtn);
407 }
408 return crtn;
409 }
410
411
412 /*
413 * Derive symmetric key.
414 * Note in the X CSP, we never return an IV.
415 */
416 CSSM_RETURN cuCspDeriveKey(CSSM_CSP_HANDLE cspHand,
417 uint32 keyAlg, // CSSM_ALGID_RC5, etc.
418 const char *keyLabel,
419 unsigned keyLabelLen,
420 uint32 keyUsage, // CSSM_KEYUSE_ENCRYPT, etc.
421 uint32 keySizeInBits,
422 CSSM_DATA_PTR password, // in PKCS-5 lingo
423 CSSM_DATA_PTR salt, // ditto
424 uint32 iterationCnt, // ditto
425 CSSM_KEY_PTR key)
426 {
427 CSSM_RETURN crtn;
428 CSSM_CC_HANDLE ccHand;
429 uint32 keyAttr;
430 CSSM_DATA dummyLabel;
431 CSSM_PKCS5_PBKDF2_PARAMS pbeParams;
432 CSSM_DATA pbeData;
433 CSSM_ACCESS_CREDENTIALS creds;
434
435 memset(key, 0, sizeof(CSSM_KEY));
436 memset(&creds, 0, sizeof(CSSM_ACCESS_CREDENTIALS));
437 crtn = CSSM_CSP_CreateDeriveKeyContext(cspHand,
438 CSSM_ALGID_PKCS5_PBKDF2,
439 keyAlg,
440 keySizeInBits,
441 &creds,
442 NULL, // BaseKey
443 iterationCnt,
444 salt,
445 NULL, // seed
446 &ccHand);
447 if(crtn) {
448 cuPrintError("CSSM_CSP_CreateDeriveKeyContext", crtn);
449 return crtn;
450 }
451 keyAttr = CSSM_KEYATTR_EXTRACTABLE | CSSM_KEYATTR_RETURN_REF |
452 CSSM_KEYATTR_SENSITIVE;
453 dummyLabel.Length = keyLabelLen;
454 dummyLabel.Data = (uint8 *)keyLabel;
455
456 /* passing in password is pretty strange....*/
457 pbeParams.Passphrase = *password;
458 pbeParams.PseudoRandomFunction = CSSM_PKCS5_PBKDF2_PRF_HMAC_SHA1;
459 pbeData.Data = (uint8 *)&pbeParams;
460 pbeData.Length = sizeof(pbeParams);
461 crtn = CSSM_DeriveKey(ccHand,
462 &pbeData,
463 keyUsage,
464 keyAttr,
465 &dummyLabel,
466 NULL, // cred and acl
467 key);
468 if(crtn) {
469 cuPrintError("CSSM_DeriveKey", crtn);
470 return crtn;
471 }
472 crtn = CSSM_DeleteContext(ccHand);
473 if(crtn) {
474 cuPrintError("CSSM_DeleteContext", crtn);
475 }
476 return crtn;
477 }
478
479 /*
480 * Generate key pair of arbitrary algorithm.
481 */
482
483 /* CSP DL currently does not perform DSA generate params; let CSP do it implicitly */
484 #define DO_DSA_GEN_PARAMS 0
485
486 CSSM_RETURN cuCspGenKeyPair(CSSM_CSP_HANDLE cspHand,
487 CSSM_DL_DB_HANDLE *dlDbHand, // optional
488 uint32 algorithm,
489 const char *keyLabel,
490 unsigned keyLabelLen,
491 uint32 keySize, // in bits
492 CSSM_KEY_PTR pubKey, // mallocd by caller
493 CSSM_KEYUSE pubKeyUsage, // CSSM_KEYUSE_ENCRYPT, etc.
494 CSSM_KEYATTR_FLAGS pubAttrs, // CSSM_KEYATTR_EXTRACTABLE, etc.
495 CSSM_KEY_PTR privKey, // mallocd by caller
496 CSSM_KEYUSE privKeyUsage, // CSSM_KEYUSE_DECRYPT, etc.
497 CSSM_KEYATTR_FLAGS privAttrs) // CSSM_KEYATTR_EXTRACTABLE, etc.
498 {
499 CSSM_RETURN crtn;
500 CSSM_RETURN ocrtn;
501 CSSM_CC_HANDLE ccHand;
502 CSSM_DATA keyLabelData;
503
504 keyLabelData.Data = (uint8 *)keyLabel,
505 keyLabelData.Length = keyLabelLen;
506 memset(pubKey, 0, sizeof(CSSM_KEY));
507 memset(privKey, 0, sizeof(CSSM_KEY));
508
509 crtn = CSSM_CSP_CreateKeyGenContext(cspHand,
510 algorithm,
511 keySize,
512 NULL, // Seed
513 NULL, // Salt
514 NULL, // StartDate
515 NULL, // EndDate
516 NULL, // Params
517 &ccHand);
518 if(crtn) {
519 cuPrintError("CSSM_CSP_CreateKeyGenContext", crtn);
520 return crtn;
521 }
522
523 /* post-context-create algorithm-specific stuff */
524 switch(algorithm) {
525 #if DO_DSA_GEN_PARAMS
526 case CSSM_ALGID_DSA:
527 /*
528 * extra step - generate params - this just adds some
529 * info to the context
530 */
531 {
532 CSSM_DATA dummy = {0, NULL};
533 crtn = CSSM_GenerateAlgorithmParams(ccHand,
534 keySize, &dummy);
535 if(crtn) {
536 cuPrintError("CSSM_GenerateAlgorithmParams", crtn);
537 CSSM_DeleteContext(ccHand);
538 return crtn;
539 }
540 cuAppFree(dummy.Data, NULL);
541 }
542 break;
543 #endif /* DO_DSA_GEN_PARAMS */
544 default:
545 break;
546 }
547
548 /* optionally specify DL/DB storage location */
549 if(dlDbHand) {
550 crtn = cuAddContextAttribute(ccHand,
551 CSSM_ATTRIBUTE_DL_DB_HANDLE,
552 sizeof(CSSM_ATTRIBUTE_DL_DB_HANDLE),
553 dlDbHand);
554 if(crtn) {
555 CSSM_DeleteContext(ccHand);
556 return crtn;
557 }
558 }
559 ocrtn = CSSM_GenerateKeyPair(ccHand,
560 pubKeyUsage,
561 pubAttrs,
562 &keyLabelData,
563 pubKey,
564 privKeyUsage,
565 privAttrs,
566 &keyLabelData, // same labels
567 NULL, // CredAndAclEntry
568 privKey);
569 if(ocrtn) {
570 cuPrintError("CSSM_GenerateKeyPair", ocrtn);
571 }
572 crtn = CSSM_DeleteContext(ccHand);
573 if(crtn) {
574 cuPrintError("CSSM_DeleteContext", crtn);
575 if(ocrtn == CSSM_OK) {
576 /* error on CSSM_GenerateKeyPair takes precedence */
577 ocrtn = crtn;
578 }
579 }
580 return ocrtn;
581 }
582
583
584 /*
585 * Add a certificate to an open Keychain.
586 */
587 CSSM_RETURN cuAddCertToKC(
588 SecKeychainRef keychain,
589 const CSSM_DATA *cert,
590 CSSM_CERT_TYPE certType,
591 CSSM_CERT_ENCODING certEncoding,
592 const char *printName, // C string
593 const CSSM_DATA *keyLabel) // ??
594 {
595 SecCertificateRef certificate;
596
597 OSStatus rslt = SecCertificateCreateFromData(cert, certType, certEncoding, &certificate);
598 if (!rslt)
599 {
600 rslt = SecCertificateAddToKeychain(certificate, keychain);
601 CFRelease(certificate);
602 }
603
604 return rslt;
605 }
606
607 /*
608 * Convert a CSSM_DATA_PTR, referring to a DER-encoded int, to an
609 * unsigned.
610 */
611 unsigned cuDER_ToInt(const CSSM_DATA *DER_Data)
612 {
613 uint32 rtn = 0;
614 unsigned i = 0;
615
616 while(i < DER_Data->Length) {
617 rtn |= DER_Data->Data[i];
618 if(++i == DER_Data->Length) {
619 break;
620 }
621 rtn <<= 8;
622 }
623 return rtn;
624 }
625
626 /*
627 * Log CSSM error.
628 */
629 void cuPrintError(const char *op, CSSM_RETURN err)
630 {
631 cssmPerror(op, err);
632 }
633
634 /*
635 * Verify a CRL against system anchors and intermediate certs.
636 */
637 CSSM_RETURN cuCrlVerify(
638 CSSM_TP_HANDLE tpHand,
639 CSSM_CL_HANDLE clHand,
640 CSSM_CSP_HANDLE cspHand,
641 const CSSM_DATA *crlData,
642 CSSM_DL_DB_HANDLE_PTR certKeychain, // intermediate certs
643 const CSSM_DATA *anchors, // optional - if NULL, use Trust Settings
644 uint32 anchorCount)
645 {
646 /* main job is building a CSSM_TP_VERIFY_CONTEXT and its components */
647 CSSM_TP_VERIFY_CONTEXT vfyCtx;
648 CSSM_TP_CALLERAUTH_CONTEXT authCtx;
649
650 memset(&vfyCtx, 0, sizeof(CSSM_TP_VERIFY_CONTEXT));
651 memset(&authCtx, 0, sizeof(CSSM_TP_CALLERAUTH_CONTEXT));
652
653 /* CSSM_TP_CALLERAUTH_CONTEXT components */
654 /*
655 typedef struct cssm_tp_callerauth_context {
656 CSSM_TP_POLICYINFO Policy;
657 CSSM_TIMESTRING VerifyTime;
658 CSSM_TP_STOP_ON VerificationAbortOn;
659 CSSM_TP_VERIFICATION_RESULTS_CALLBACK CallbackWithVerifiedCert;
660 uint32 NumberOfAnchorCerts;
661 CSSM_DATA_PTR AnchorCerts;
662 CSSM_DL_DB_LIST_PTR DBList;
663 CSSM_ACCESS_CREDENTIALS_PTR CallerCredentials;
664 } CSSM_TP_CALLERAUTH_CONTEXT, *CSSM_TP_CALLERAUTH_CONTEXT_PTR;
665 */
666 CSSM_FIELD policyId;
667 CSSM_APPLE_TP_CRL_OPTIONS crlOpts;
668 policyId.FieldOid = CSSMOID_APPLE_TP_REVOCATION_CRL;
669 policyId.FieldValue.Data = (uint8 *)&crlOpts;
670 policyId.FieldValue.Length = sizeof(crlOpts);
671 crlOpts.Version = CSSM_APPLE_TP_CRL_OPTS_VERSION;
672 /* perhaps this should be user-specifiable */
673 crlOpts.CrlFlags = CSSM_TP_ACTION_FETCH_CRL_FROM_NET;
674 crlOpts.crlStore = NULL;
675
676 authCtx.Policy.NumberOfPolicyIds = 1;
677 authCtx.Policy.PolicyIds = &policyId;
678 authCtx.Policy.PolicyControl = NULL;
679
680 authCtx.VerifyTime = NULL;
681 authCtx.VerificationAbortOn = CSSM_TP_STOP_ON_POLICY;
682 authCtx.CallbackWithVerifiedCert = NULL;
683
684 /* anchors */
685 authCtx.NumberOfAnchorCerts = anchorCount;
686 authCtx.AnchorCerts = const_cast<CSSM_DATA_PTR>(anchors);
687
688 /* DBList of intermediate certs, plus possible System.keychain and
689 * system roots */
690 CSSM_DL_DB_HANDLE handles[3];
691 unsigned numDbs = 0;
692 CSSM_DL_HANDLE dlHand = 0;
693 if(certKeychain != NULL) {
694 handles[0] = *certKeychain;
695 numDbs++;
696 }
697 if(anchors == NULL) {
698 /* Trust Settings requires two more DBs */
699 if(numDbs == 0) {
700 /* new DL handle */
701 dlHand = cuDlStartup();
702 handles[numDbs].DLHandle = dlHand;
703 handles[numDbs + 1].DLHandle = dlHand;
704 }
705 else {
706 /* use the same one passed in for certKeychain */
707 handles[numDbs].DLHandle = handles[0].DLHandle;
708 handles[numDbs + 1].DLHandle = handles[0].DLHandle;
709 }
710 handles[numDbs].DBHandle = cuDbStartupByName(handles[numDbs].DLHandle,
711 (char*) ADMIN_CERT_STORE_PATH, CSSM_FALSE, CSSM_TRUE);
712 numDbs++;
713
714 handles[numDbs].DBHandle = cuDbStartupByName(handles[numDbs].DLHandle,
715 (char*) SYSTEM_ROOT_STORE_PATH, CSSM_FALSE, CSSM_TRUE);
716 numDbs++;
717 }
718 CSSM_DL_DB_LIST dlDbList;
719 dlDbList.DLDBHandle = handles;
720 dlDbList.NumHandles = numDbs;
721
722 authCtx.DBList = &dlDbList;
723 authCtx.CallerCredentials = NULL;
724
725 /* CSSM_TP_VERIFY_CONTEXT */
726 vfyCtx.ActionData.Data = NULL;
727 vfyCtx.ActionData.Length = 0;
728 vfyCtx.Action = CSSM_TP_ACTION_DEFAULT;
729 vfyCtx.Cred = &authCtx;
730
731 /* CSSM_APPLE_TP_ACTION_DATA */
732 CSSM_APPLE_TP_ACTION_DATA tpAction;
733 if(anchors == NULL) {
734 /* enable Trust Settings */
735 tpAction.Version = CSSM_APPLE_TP_ACTION_VERSION;
736 tpAction.ActionFlags = CSSM_TP_ACTION_TRUST_SETTINGS;
737 vfyCtx.ActionData.Data = (uint8 *)&tpAction;
738 vfyCtx.ActionData.Length = sizeof(tpAction);
739 }
740
741 /* cook up CSSM_ENCODED_CRL */
742 CSSM_ENCODED_CRL encCrl;
743 encCrl.CrlType = CSSM_CRL_TYPE_X_509v2;
744 encCrl.CrlEncoding = CSSM_CRL_ENCODING_DER;
745 encCrl.CrlBlob = *crlData;
746
747 /* CDSA API requires a SignerCertGroup; for us, all the certs are in
748 * certKeyChain... */
749 CSSM_CERTGROUP certGroup;
750 certGroup.CertType = CSSM_CERT_X_509v1;
751 certGroup.CertEncoding = CSSM_CERT_ENCODING_DER;
752 certGroup.NumCerts = 0;
753 certGroup.GroupList.CertList = NULL;
754 certGroup.CertGroupType = CSSM_CERTGROUP_DATA;
755
756 CSSM_RETURN crtn = CSSM_TP_CrlVerify(tpHand,
757 clHand,
758 cspHand,
759 &encCrl,
760 &certGroup,
761 &vfyCtx,
762 NULL); // RevokerVerifyResult
763 if(crtn) {
764 cuPrintError("CSSM_TP_CrlVerify", crtn);
765 }
766 if(anchors == NULL) {
767 /* close the DBs and maybe the DL we opened */
768 unsigned dexToClose = (certKeychain == NULL) ? 0 : 1;
769 CSSM_DL_DbClose(handles[dexToClose++]);
770 CSSM_DL_DbClose(handles[dexToClose]);
771 if(dlHand != 0) {
772 cuDlDetachUnload(dlHand);
773 }
774 }
775 return crtn;
776 }
777