]>
Commit | Line | Data |
---|---|---|
b1ab9ed8 A |
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 | */ | |
427c49bc | 393 | static |
b1ab9ed8 A |
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 |