]> git.saurik.com Git - apple/security.git/blob - SecurityTests/cspxutils/utilLib/cspwrap.c
Security-57740.31.2.tar.gz
[apple/security.git] / SecurityTests / cspxutils / utilLib / cspwrap.c
1 /* Copyright (c) 1997,2003-2006,2008,2010,2013 Apple Inc.
2 *
3 * cspwrap.c - wrappers to simplify access to CDSA
4 *
5 * Revision History
6 * ----------------
7 * 3 May 2000 Doug Mitchell
8 * Ported to X/CDSA2.
9 * 12 Aug 1997 Doug Mitchell at Apple
10 * Created.
11 */
12
13 #include <Security/cssmapple.h>
14 #include <Security/cssm.h>
15 #include "cspwrap.h"
16 #include "common.h"
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <string.h>
20 /* MCF hack */
21 // #include <CarbonCore/MacTypes.h>
22 #include <MacTypes.h>
23 /* end MCF */
24
25 #ifndef NULL
26 #define NULL ((void *)0)
27 #endif /* NULL */
28 #ifndef MAX
29 #define MAX(a,b) ((a > b) ? a : b)
30 #define MIN(a,b) ((a < b) ? a : b)
31 #endif
32
33 #pragma mark --------- Key Generation ---------
34
35 /*
36 * Key generation
37 */
38 #define FEE_PRIV_DATA_SIZE 20
39 /*
40 * Debug/test only. BsafeCSP only (long since disabled, in Puma).
41 * This results in quicker but less secure RSA key generation.
42 */
43 #define RSA_WEAK_KEYS 0
44
45 /*
46 * Force bad data in KeyData prior to generating, deriving, or
47 * wrapping key to ensure that the CSP ignores incoming
48 * KeyData.
49 */
50 static void setBadKeyData(
51 CSSM_KEY_PTR key)
52 {
53 key->KeyData.Data = (uint8 *)0xeaaaeaaa; // bad ptr
54 key->KeyData.Length = 1; // no key can fit here
55 }
56
57 /*
58 * Generate key pair of arbitrary algorithm.
59 * FEE keys will have random private data.
60 */
61 CSSM_RETURN cspGenKeyPair(CSSM_CSP_HANDLE cspHand,
62 uint32 algorithm,
63 const char *keyLabel,
64 unsigned keyLabelLen,
65 uint32 keySize, // in bits
66 CSSM_KEY_PTR pubKey, // mallocd by caller
67 CSSM_BOOL pubIsRef, // true - reference key, false - data
68 uint32 pubKeyUsage, // CSSM_KEYUSE_ENCRYPT, etc.
69 CSSM_KEYBLOB_FORMAT pubFormat, // Optional. Specify 0 or CSSM_KEYBLOB_RAW_FORMAT_NONE
70 // to get the default format.
71 CSSM_KEY_PTR privKey, // mallocd by caller
72 CSSM_BOOL privIsRef, // true - reference key, false - data
73 uint32 privKeyUsage, // CSSM_KEYUSE_DECRYPT, etc.
74 CSSM_KEYBLOB_FORMAT privFormat, // optional 0 ==> default
75 CSSM_BOOL genSeed) // FEE only. True: we generate seed and CSP
76 // will hash it. False: CSP generates random
77 // seed.
78 {
79 CSSM_RETURN crtn;
80 CSSM_CC_HANDLE ccHand;
81 CSSM_DATA privData = {0, NULL}; // mallocd for FEE
82 CSSM_CRYPTO_DATA privCData;
83 CSSM_CRYPTO_DATA_PTR privCDataPtr = NULL;
84 CSSM_DATA keyLabelData;
85 uint32 pubAttr;
86 uint32 privAttr;
87 CSSM_RETURN ocrtn = CSSM_OK;
88
89 if(keySize == CSP_KEY_SIZE_DEFAULT) {
90 keySize = cspDefaultKeySize(algorithm);
91 }
92
93 /* pre-context-create algorithm-specific stuff */
94 switch(algorithm) {
95 case CSSM_ALGID_FEE:
96 if(genSeed) {
97 /* cook up random privData */
98 privData.Data = (uint8 *)CSSM_MALLOC(FEE_PRIV_DATA_SIZE);
99 privData.Length = FEE_PRIV_DATA_SIZE;
100 appGetRandomBytes(privData.Data, FEE_PRIV_DATA_SIZE);
101 privCData.Param = privData;
102 privCData.Callback = NULL;
103 privCDataPtr = &privCData;
104 }
105 /* else CSP generates random seed/key */
106 break;
107 case CSSM_ALGID_RSA:
108 break;
109 case CSSM_ALGID_DSA:
110 break;
111 case CSSM_ALGID_ECDSA:
112 break;
113 default:
114 printf("cspGenKeyPair: Unknown algorithm\n");
115 /* but what the hey */
116 privCDataPtr = NULL;
117 break;
118 }
119 keyLabelData.Data = (uint8 *)keyLabel,
120 keyLabelData.Length = keyLabelLen;
121 memset(pubKey, 0, sizeof(CSSM_KEY));
122 memset(privKey, 0, sizeof(CSSM_KEY));
123 setBadKeyData(pubKey);
124 setBadKeyData(privKey);
125
126 crtn = CSSM_CSP_CreateKeyGenContext(cspHand,
127 algorithm,
128 keySize,
129 privCDataPtr, // Seed
130 NULL, // Salt
131 NULL, // StartDate
132 NULL, // EndDate
133 NULL, // Params
134 &ccHand);
135 if(crtn) {
136 printError("CSSM_CSP_CreateKeyGenContext", crtn);
137 ocrtn = crtn;
138 goto abort;
139 }
140 /* cook up attribute bits */
141 if(pubIsRef) {
142 pubAttr = CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_EXTRACTABLE;
143 }
144 else {
145 pubAttr = CSSM_KEYATTR_RETURN_DATA | CSSM_KEYATTR_EXTRACTABLE;
146 }
147 if(privIsRef) {
148 privAttr = CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_EXTRACTABLE;
149 }
150 else {
151 privAttr = CSSM_KEYATTR_RETURN_DATA | CSSM_KEYATTR_EXTRACTABLE;
152 }
153
154 /* post-context-create algorithm-specific stuff */
155 switch(algorithm) {
156 case CSSM_ALGID_RSA:
157
158 #if RSA_WEAK_KEYS
159 {
160 /* for testing, speed up key gen by using the
161 * undocumented "CUSTOM" key gen mode. This
162 * results in the CSP using AI_RsaKeyGen instead of
163 * AI_RSAStrongKeyGen.
164 */
165 crtn = AddContextAttribute(ccHand,
166 CSSM_ATTRIBUTE_MODE,
167 sizeof(uint32),
168 CAT_Uint32,
169 NULL,
170 CSSM_ALGMODE_CUSTOM);
171 if(crtn) {
172 printError("CSSM_UpdateContextAttributes", crtn);
173 return crtn;
174 }
175 }
176 #endif // RSA_WEAK_KEYS
177 break;
178
179 case CSSM_ALGID_DSA:
180 /*
181 * extra step - generate params - this just adds some
182 * info to the context
183 */
184 {
185 CSSM_DATA dummy = {0, NULL};
186 crtn = CSSM_GenerateAlgorithmParams(ccHand,
187 keySize, &dummy);
188 if(crtn) {
189 printError("CSSM_GenerateAlgorithmParams", crtn);
190 return crtn;
191 }
192 appFreeCssmData(&dummy, CSSM_FALSE);
193 }
194 break;
195 default:
196 break;
197 }
198
199 /* optional format specifiers */
200 if(!pubIsRef && (pubFormat != CSSM_KEYBLOB_RAW_FORMAT_NONE)) {
201 crtn = AddContextAttribute(ccHand,
202 CSSM_ATTRIBUTE_PUBLIC_KEY_FORMAT,
203 sizeof(uint32),
204 CAT_Uint32,
205 NULL,
206 pubFormat);
207 if(crtn) {
208 printError("AddContextAttribute(CSSM_ATTRIBUTE_PUBLIC_KEY_FORMAT)", crtn);
209 return crtn;
210 }
211 }
212 if(!privIsRef && (privFormat != CSSM_KEYBLOB_RAW_FORMAT_NONE)) {
213 crtn = AddContextAttribute(ccHand,
214 CSSM_ATTRIBUTE_PRIVATE_KEY_FORMAT,
215 sizeof(uint32), // currently sizeof CSSM_DATA
216 CAT_Uint32,
217 NULL,
218 privFormat);
219 if(crtn) {
220 printError("AddContextAttribute(CSSM_ATTRIBUTE_PRIVATE_KEY_FORMAT)", crtn);
221 return crtn;
222 }
223 }
224 crtn = CSSM_GenerateKeyPair(ccHand,
225 pubKeyUsage,
226 pubAttr,
227 &keyLabelData,
228 pubKey,
229 privKeyUsage,
230 privAttr,
231 &keyLabelData, // same labels
232 NULL, // CredAndAclEntry
233 privKey);
234 if(crtn) {
235 printError("CSSM_GenerateKeyPair", crtn);
236 ocrtn = crtn;
237 goto abort;
238 }
239 /* basic checks...*/
240 if(privIsRef) {
241 if(privKey->KeyHeader.BlobType != CSSM_KEYBLOB_REFERENCE) {
242 printf("privKey blob type: exp %u got %u\n",
243 CSSM_KEYBLOB_REFERENCE, (unsigned)privKey->KeyHeader.BlobType);
244 ocrtn = CSSM_ERRCODE_INTERNAL_ERROR;
245 goto abort;
246 }
247 }
248 else {
249 switch(privKey->KeyHeader.BlobType) {
250 case CSSM_KEYBLOB_RAW:
251 break;
252 default:
253 printf("privKey blob type: exp raw, got %u\n",
254 (unsigned)privKey->KeyHeader.BlobType);
255 ocrtn = CSSM_ERRCODE_INTERNAL_ERROR;
256 goto abort;
257 }
258 }
259 if(pubIsRef) {
260 if(pubKey->KeyHeader.BlobType != CSSM_KEYBLOB_REFERENCE) {
261 printf("pubKey blob type: exp %u got %u\n",
262 CSSM_KEYBLOB_REFERENCE, (unsigned)pubKey->KeyHeader.BlobType);
263 ocrtn = CSSM_ERRCODE_INTERNAL_ERROR;
264 goto abort;
265 }
266 }
267 else {
268 switch(pubKey->KeyHeader.BlobType) {
269 case CSSM_KEYBLOB_RAW:
270 break;
271 default:
272 printf("pubKey blob type: exp raw or raw_berder, got %u\n",
273 (unsigned)pubKey->KeyHeader.BlobType);
274 ocrtn = CSSM_ERRCODE_INTERNAL_ERROR;
275 goto abort;
276 }
277 }
278 abort:
279 if(ccHand != 0) {
280 crtn = CSSM_DeleteContext(ccHand);
281 if(crtn) {
282 printError("CSSM_DeleteContext", crtn);
283 ocrtn = CSSM_ERRCODE_INTERNAL_ERROR;
284 }
285 }
286 if(privData.Data != NULL) {
287 CSSM_FREE(privData.Data);
288 }
289 return ocrtn;
290 }
291
292 /*
293 * Generate FEE key pair with optional primeType, curveType, and seed (password) data.
294 */
295 CSSM_RETURN cspGenFEEKeyPair(CSSM_CSP_HANDLE cspHand,
296 const char *keyLabel,
297 unsigned keyLabelLen,
298 uint32 keySize, // in bits
299 uint32 primeType, // CSSM_FEE_PRIME_TYPE_MERSENNE, etc.
300 uint32 curveType, // CSSM_FEE_CURVE_TYPE_MONTGOMERY, etc.
301 CSSM_KEY_PTR pubKey, // mallocd by caller
302 CSSM_BOOL pubIsRef, // true - reference key, false - data
303 uint32 pubKeyUsage, // CSSM_KEYUSE_ENCRYPT, etc.
304 CSSM_KEYBLOB_FORMAT pubFormat, // Optional. Specify 0 or CSSM_KEYBLOB_RAW_FORMAT_NONE
305 // to get the default format.
306 CSSM_KEY_PTR privKey, // mallocd by caller
307 CSSM_BOOL privIsRef, // true - reference key, false - data
308 uint32 privKeyUsage, // CSSM_KEYUSE_DECRYPT, etc.
309 CSSM_KEYBLOB_FORMAT privFormat, // optional 0 ==> default
310 const CSSM_DATA *seedData) // Present: CSP will hash this for private data.
311 // NULL: CSP generates random seed.
312 {
313 CSSM_RETURN crtn;
314 CSSM_CC_HANDLE ccHand;
315 CSSM_CRYPTO_DATA privCData;
316 CSSM_CRYPTO_DATA_PTR privCDataPtr = NULL;
317 CSSM_DATA keyLabelData;
318 uint32 pubAttr;
319 uint32 privAttr;
320 CSSM_RETURN ocrtn = CSSM_OK;
321
322 /* pre-context-create algorithm-specific stuff */
323 if(seedData) {
324 privCData.Param = *((CSSM_DATA_PTR)seedData);
325 privCData.Callback = NULL;
326 privCDataPtr = &privCData;
327 }
328 /* else CSP generates random seed/key */
329
330 if(keySize == CSP_KEY_SIZE_DEFAULT) {
331 keySize = CSP_FEE_KEY_SIZE_DEFAULT;
332 }
333
334 keyLabelData.Data = (uint8 *)keyLabel,
335 keyLabelData.Length = keyLabelLen;
336 memset(pubKey, 0, sizeof(CSSM_KEY));
337 memset(privKey, 0, sizeof(CSSM_KEY));
338 setBadKeyData(pubKey);
339 setBadKeyData(privKey);
340
341 crtn = CSSM_CSP_CreateKeyGenContext(cspHand,
342 CSSM_ALGID_FEE,
343 keySize,
344 privCDataPtr, // Seed
345 NULL, // Salt
346 NULL, // StartDate
347 NULL, // EndDate
348 NULL, // Params
349 &ccHand);
350 if(crtn) {
351 printError("CSSM_CSP_CreateKeyGenContext", crtn);
352 ocrtn = crtn;
353 goto abort;
354 }
355 /* cook up attribute bits */
356 if(pubIsRef) {
357 pubAttr = CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_EXTRACTABLE;
358 }
359 else {
360 pubAttr = CSSM_KEYATTR_RETURN_DATA | CSSM_KEYATTR_EXTRACTABLE;
361 }
362 if(privIsRef) {
363 privAttr = CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_EXTRACTABLE;
364 }
365 else {
366 privAttr = CSSM_KEYATTR_RETURN_DATA | CSSM_KEYATTR_EXTRACTABLE;
367 }
368
369 /* optional post-context-create stuff */
370 if(primeType != CSSM_FEE_PRIME_TYPE_DEFAULT) {
371 crtn = AddContextAttribute(ccHand,
372 CSSM_ATTRIBUTE_FEE_PRIME_TYPE,
373 sizeof(uint32),
374 CAT_Uint32,
375 NULL,
376 primeType);
377 if(crtn) {
378 printError("AddContextAttribute(CSSM_ATTRIBUTE_FEE_PRIME_TYPE)", crtn);
379 return crtn;
380 }
381 }
382 if(curveType != CSSM_FEE_CURVE_TYPE_DEFAULT) {
383 crtn = AddContextAttribute(ccHand,
384 CSSM_ATTRIBUTE_FEE_CURVE_TYPE,
385 sizeof(uint32),
386 CAT_Uint32,
387 NULL,
388 curveType);
389 if(crtn) {
390 printError("AddContextAttribute(CSSM_ATTRIBUTE_FEE_CURVE_TYPE)", crtn);
391 return crtn;
392 }
393 }
394
395 if(pubFormat != CSSM_KEYBLOB_RAW_FORMAT_NONE) {
396 crtn = AddContextAttribute(ccHand,
397 CSSM_ATTRIBUTE_PUBLIC_KEY_FORMAT,
398 sizeof(uint32),
399 CAT_Uint32,
400 NULL,
401 pubFormat);
402 if(crtn) {
403 printError("AddContextAttribute(CSSM_ATTRIBUTE_PUBLIC_KEY_FORMAT)", crtn);
404 return crtn;
405 }
406 }
407 if(privFormat != CSSM_KEYBLOB_RAW_FORMAT_NONE) {
408 crtn = AddContextAttribute(ccHand,
409 CSSM_ATTRIBUTE_PRIVATE_KEY_FORMAT,
410 sizeof(uint32), // currently sizeof CSSM_DATA
411 CAT_Uint32,
412 NULL,
413 pubFormat);
414 if(crtn) {
415 printError("AddContextAttribute(CSSM_ATTRIBUTE_PRIVATE_KEY_FORMAT)", crtn);
416 return crtn;
417 }
418 }
419 crtn = CSSM_GenerateKeyPair(ccHand,
420 pubKeyUsage,
421 pubAttr,
422 &keyLabelData,
423 pubKey,
424 privKeyUsage,
425 privAttr,
426 &keyLabelData, // same labels
427 NULL, // CredAndAclEntry
428 privKey);
429 if(crtn) {
430 printError("CSSM_GenerateKeyPair", crtn);
431 ocrtn = crtn;
432 goto abort;
433 }
434 /* basic checks...*/
435 if(privIsRef) {
436 if(privKey->KeyHeader.BlobType != CSSM_KEYBLOB_REFERENCE) {
437 printf("privKey blob type: exp %u got %u\n",
438 CSSM_KEYBLOB_REFERENCE, (unsigned)privKey->KeyHeader.BlobType);
439 ocrtn = CSSM_ERRCODE_INTERNAL_ERROR;
440 goto abort;
441 }
442 }
443 else {
444 switch(privKey->KeyHeader.BlobType) {
445 case CSSM_KEYBLOB_RAW:
446 break;
447 default:
448 printf("privKey blob type: exp raw, got %u\n",
449 (unsigned)privKey->KeyHeader.BlobType);
450 ocrtn = CSSM_ERRCODE_INTERNAL_ERROR;
451 goto abort;
452 }
453 }
454 if(pubIsRef) {
455 if(pubKey->KeyHeader.BlobType != CSSM_KEYBLOB_REFERENCE) {
456 printf("pubKey blob type: exp %u got %u\n",
457 CSSM_KEYBLOB_REFERENCE, (unsigned)pubKey->KeyHeader.BlobType);
458 ocrtn = CSSM_ERRCODE_INTERNAL_ERROR;
459 goto abort;
460 }
461 }
462 else {
463 switch(pubKey->KeyHeader.BlobType) {
464 case CSSM_KEYBLOB_RAW:
465 break;
466 default:
467 printf("pubKey blob type: exp raw or raw_berder, got %u\n",
468 (unsigned)pubKey->KeyHeader.BlobType);
469 ocrtn = CSSM_ERRCODE_INTERNAL_ERROR;
470 goto abort;
471 }
472 }
473 abort:
474 if(ccHand != 0) {
475 crtn = CSSM_DeleteContext(ccHand);
476 if(crtn) {
477 printError("CSSM_DeleteContext", crtn);
478 ocrtn = CSSM_ERRCODE_INTERNAL_ERROR;
479 }
480 }
481 return ocrtn;
482 }
483
484 /*
485 * Generate DSA key pair with optional generateAlgParams and optional
486 * incoming parameters.
487 */
488 CSSM_RETURN cspGenDSAKeyPair(CSSM_CSP_HANDLE cspHand,
489 const char *keyLabel,
490 unsigned keyLabelLen,
491 uint32 keySize, // in bits
492 CSSM_KEY_PTR pubKey, // mallocd by caller
493 CSSM_BOOL pubIsRef, // true - reference key, false - data
494 uint32 pubKeyUsage, // CSSM_KEYUSE_ENCRYPT, etc.
495 CSSM_KEYBLOB_FORMAT pubFormat, // Optional. Specify 0 or CSSM_KEYBLOB_RAW_FORMAT_NONE
496 // to get the default format.
497 CSSM_KEY_PTR privKey, // mallocd by caller
498 CSSM_BOOL privIsRef, // true - reference key, false - data
499 uint32 privKeyUsage, // CSSM_KEYUSE_DECRYPT, etc.
500 CSSM_KEYBLOB_FORMAT privFormat, // Optional. Specify 0 or CSSM_KEYBLOB_RAW_FORMAT_NONE
501 // to get the default format.
502 CSSM_BOOL genParams,
503 CSSM_DATA_PTR paramData) // optional
504 {
505 CSSM_RETURN crtn;
506 CSSM_CC_HANDLE ccHand;
507 CSSM_DATA keyLabelData;
508 uint32 pubAttr;
509 uint32 privAttr;
510 CSSM_RETURN ocrtn = CSSM_OK;
511
512 if(keySize == CSP_KEY_SIZE_DEFAULT) {
513 keySize = CSP_DSA_KEY_SIZE_DEFAULT;
514 }
515 keyLabelData.Data = (uint8 *)keyLabel,
516 keyLabelData.Length = keyLabelLen;
517 memset(pubKey, 0, sizeof(CSSM_KEY));
518 memset(privKey, 0, sizeof(CSSM_KEY));
519 setBadKeyData(pubKey);
520 setBadKeyData(privKey);
521
522 crtn = CSSM_CSP_CreateKeyGenContext(cspHand,
523 CSSM_ALGID_DSA,
524 keySize,
525 NULL, // Seed
526 NULL, // Salt
527 NULL, // StartDate
528 NULL, // EndDate
529 paramData,
530 &ccHand);
531 if(crtn) {
532 printError("CSSM_CSP_CreateKeyGenContext", crtn);
533 ocrtn = crtn;
534 goto abort;
535 }
536
537 /* cook up attribute bits */
538 if(pubIsRef) {
539 pubAttr = CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_EXTRACTABLE;
540 }
541 else {
542 pubAttr = CSSM_KEYATTR_RETURN_DATA | CSSM_KEYATTR_EXTRACTABLE;
543 }
544 if(privIsRef) {
545 privAttr = CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_EXTRACTABLE;
546 }
547 else {
548 privAttr = CSSM_KEYATTR_RETURN_DATA | CSSM_KEYATTR_EXTRACTABLE;
549 }
550
551 if(genParams) {
552 /*
553 * extra step - generate params - this just adds some
554 * info to the context
555 */
556 CSSM_DATA dummy = {0, NULL};
557 crtn = CSSM_GenerateAlgorithmParams(ccHand,
558 keySize, &dummy);
559 if(crtn) {
560 printError("CSSM_GenerateAlgorithmParams", crtn);
561 return crtn;
562 }
563 appFreeCssmData(&dummy, CSSM_FALSE);
564 }
565
566 /* optional format specifiers */
567 if(!pubIsRef && (pubFormat != CSSM_KEYBLOB_RAW_FORMAT_NONE)) {
568 crtn = AddContextAttribute(ccHand,
569 CSSM_ATTRIBUTE_PUBLIC_KEY_FORMAT,
570 sizeof(uint32),
571 CAT_Uint32,
572 NULL,
573 pubFormat);
574 if(crtn) {
575 printError("AddContextAttribute(CSSM_ATTRIBUTE_PUBLIC_KEY_FORMAT)", crtn);
576 return crtn;
577 }
578 }
579 if(!privIsRef && (privFormat != CSSM_KEYBLOB_RAW_FORMAT_NONE)) {
580 crtn = AddContextAttribute(ccHand,
581 CSSM_ATTRIBUTE_PRIVATE_KEY_FORMAT,
582 sizeof(uint32), // currently sizeof CSSM_DATA
583 CAT_Uint32,
584 NULL,
585 privFormat);
586 if(crtn) {
587 printError("AddContextAttribute(CSSM_ATTRIBUTE_PRIVATE_KEY_FORMAT)", crtn);
588 return crtn;
589 }
590 }
591
592 crtn = CSSM_GenerateKeyPair(ccHand,
593 pubKeyUsage,
594 pubAttr,
595 &keyLabelData,
596 pubKey,
597 privKeyUsage,
598 privAttr,
599 &keyLabelData, // same labels
600 NULL, // CredAndAclEntry
601 privKey);
602 if(crtn) {
603 printError("CSSM_GenerateKeyPair", crtn);
604 ocrtn = crtn;
605 goto abort;
606 }
607 /* basic checks...*/
608 if(privIsRef) {
609 if(privKey->KeyHeader.BlobType != CSSM_KEYBLOB_REFERENCE) {
610 printf("privKey blob type: exp %u got %u\n",
611 CSSM_KEYBLOB_REFERENCE, (unsigned)privKey->KeyHeader.BlobType);
612 ocrtn = CSSM_ERRCODE_INTERNAL_ERROR;
613 goto abort;
614 }
615 }
616 else {
617 switch(privKey->KeyHeader.BlobType) {
618 case CSSM_KEYBLOB_RAW:
619 break;
620 default:
621 printf("privKey blob type: exp raw, got %u\n",
622 (unsigned)privKey->KeyHeader.BlobType);
623 ocrtn = CSSM_ERRCODE_INTERNAL_ERROR;
624 goto abort;
625 }
626 }
627 if(pubIsRef) {
628 if(pubKey->KeyHeader.BlobType != CSSM_KEYBLOB_REFERENCE) {
629 printf("pubKey blob type: exp %u got %u\n",
630 CSSM_KEYBLOB_REFERENCE, (unsigned)pubKey->KeyHeader.BlobType);
631 ocrtn = CSSM_ERRCODE_INTERNAL_ERROR;
632 goto abort;
633 }
634 }
635 else {
636 switch(pubKey->KeyHeader.BlobType) {
637 case CSSM_KEYBLOB_RAW:
638 break;
639 default:
640 printf("pubKey blob type: exp raw or raw_berder, got %u\n",
641 (unsigned)pubKey->KeyHeader.BlobType);
642 ocrtn = CSSM_ERRCODE_INTERNAL_ERROR;
643 goto abort;
644 }
645 }
646 abort:
647 if(ccHand != 0) {
648 crtn = CSSM_DeleteContext(ccHand);
649 if(crtn) {
650 printError("CSSM_DeleteContext", crtn);
651 ocrtn = CSSM_ERRCODE_INTERNAL_ERROR;
652 }
653 }
654 return ocrtn;
655 }
656
657
658 uint32 cspDefaultKeySize(uint32 alg)
659 {
660 uint32 keySizeInBits;
661 switch(alg) {
662 case CSSM_ALGID_DES:
663 keySizeInBits = CSP_DES_KEY_SIZE_DEFAULT;
664 break;
665 case CSSM_ALGID_3DES_3KEY:
666 case CSSM_ALGID_DESX:
667 keySizeInBits = CSP_DES3_KEY_SIZE_DEFAULT;
668 break;
669 case CSSM_ALGID_RC2:
670 keySizeInBits = CSP_RC2_KEY_SIZE_DEFAULT;
671 break;
672 case CSSM_ALGID_RC4:
673 keySizeInBits = CSP_RC4_KEY_SIZE_DEFAULT;
674 break;
675 case CSSM_ALGID_RC5:
676 keySizeInBits = CSP_RC5_KEY_SIZE_DEFAULT;
677 break;
678 case CSSM_ALGID_ASC:
679 keySizeInBits = CSP_ASC_KEY_SIZE_DEFAULT;
680 break;
681 case CSSM_ALGID_BLOWFISH:
682 keySizeInBits = CSP_BFISH_KEY_SIZE_DEFAULT;
683 break;
684 case CSSM_ALGID_CAST:
685 keySizeInBits = CSP_CAST_KEY_SIZE_DEFAULT;
686 break;
687 case CSSM_ALGID_IDEA:
688 keySizeInBits = CSP_IDEA_KEY_SIZE_DEFAULT;
689 break;
690 case CSSM_ALGID_AES:
691 keySizeInBits = CSP_AES_KEY_SIZE_DEFAULT;
692 break;
693 case CSSM_ALGID_SHA1HMAC:
694 keySizeInBits = CSP_HMAC_SHA_KEY_SIZE_DEFAULT;
695 break;
696 case CSSM_ALGID_MD5HMAC:
697 keySizeInBits = CSP_HMAC_MD5_KEY_SIZE_DEFAULT;
698 break;
699 case CSSM_ALGID_FEE:
700 keySizeInBits = CSP_FEE_KEY_SIZE_DEFAULT;
701 break;
702 case CSSM_ALGID_RSA:
703 keySizeInBits = CSP_RSA_KEY_SIZE_DEFAULT;
704 break;
705 case CSSM_ALGID_DSA:
706 keySizeInBits = CSP_DSA_KEY_SIZE_DEFAULT;
707 break;
708 case CSSM_ALGID_ECDSA:
709 keySizeInBits = CSP_ECDSA_KEY_SIZE_DEFAULT;
710 break;
711 case CSSM_ALGID_NONE:
712 keySizeInBits = CSP_NULL_CRYPT_KEY_SIZE_DEF;
713 break;
714 default:
715 printf("***cspDefaultKeySize: Unknown symmetric algorithm\n");
716 keySizeInBits = 0;
717 break;
718 }
719 return keySizeInBits;
720 }
721
722 /*
723 * Create a random symmetric key.
724 */
725 CSSM_KEY_PTR cspGenSymKey(CSSM_CSP_HANDLE cspHand,
726 uint32 alg,
727 const char *keyLabel,
728 unsigned keyLabelLen,
729 uint32 keyUsage, // CSSM_KEYUSE_ENCRYPT, etc.
730 uint32 keySizeInBits,
731 CSSM_BOOL refKey)
732 {
733 CSSM_KEY_PTR symKey = (CSSM_KEY_PTR)CSSM_MALLOC(sizeof(CSSM_KEY));
734 CSSM_RETURN crtn;
735 CSSM_CC_HANDLE ccHand;
736 uint32 keyAttr;
737 CSSM_DATA dummyLabel;
738
739 if(symKey == NULL) {
740 printf("Insufficient heap space\n");
741 return NULL;
742 }
743 memset(symKey, 0, sizeof(CSSM_KEY));
744 setBadKeyData(symKey);
745 if(keySizeInBits == CSP_KEY_SIZE_DEFAULT) {
746 keySizeInBits = cspDefaultKeySize(alg);
747 }
748 crtn = CSSM_CSP_CreateKeyGenContext(cspHand,
749 alg,
750 keySizeInBits, // keySizeInBits
751 NULL, // Seed
752 NULL, // Salt
753 NULL, // StartDate
754 NULL, // EndDate
755 NULL, // Params
756 &ccHand);
757 if(crtn) {
758 printError("CSSM_CSP_CreateKeyGenContext", crtn);
759 goto errorOut;
760 }
761 if(refKey) {
762 keyAttr = CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_EXTRACTABLE;
763 }
764 else {
765 keyAttr = CSSM_KEYATTR_RETURN_DATA | CSSM_KEYATTR_EXTRACTABLE;
766 }
767 dummyLabel.Length = keyLabelLen;
768 dummyLabel.Data = (uint8 *)keyLabel;
769
770 crtn = CSSM_GenerateKey(ccHand,
771 keyUsage,
772 keyAttr,
773 &dummyLabel,
774 NULL, // ACL
775 symKey);
776 if(crtn) {
777 printError("CSSM_GenerateKey", crtn);
778 goto errorOut;
779 }
780 crtn = CSSM_DeleteContext(ccHand);
781 if(crtn) {
782 printError("CSSM_DeleteContext", crtn);
783 goto errorOut;
784 }
785 return symKey;
786 errorOut:
787 CSSM_FREE(symKey);
788 return NULL;
789 }
790
791 /*
792 * Derive symmetric key.
793 * Note in the X CSP, we never return an IV.
794 */
795 CSSM_KEY_PTR cspDeriveKey(CSSM_CSP_HANDLE cspHand,
796 uint32 deriveAlg, // CSSM_ALGID_PKCS5_PBKDF2, etc.
797 uint32 keyAlg, // CSSM_ALGID_RC5, etc.
798 const char *keyLabel,
799 unsigned keyLabelLen,
800 uint32 keyUsage, // CSSM_KEYUSE_ENCRYPT, etc.
801 uint32 keySizeInBits,
802 CSSM_BOOL isRefKey,
803 CSSM_DATA_PTR password, // in PKCS-5 lingo
804 CSSM_DATA_PTR salt, // ditto
805 uint32 iterationCnt, // ditto
806 CSSM_DATA_PTR initVector) // mallocd & RETURNED
807 {
808 CSSM_KEY_PTR symKey = (CSSM_KEY_PTR)
809 CSSM_MALLOC(sizeof(CSSM_KEY));
810 CSSM_RETURN crtn;
811 CSSM_CC_HANDLE ccHand;
812 uint32 keyAttr;
813 CSSM_DATA dummyLabel;
814 CSSM_PKCS5_PBKDF2_PARAMS pbeParams;
815 CSSM_DATA pbeData;
816 CSSM_ACCESS_CREDENTIALS creds;
817
818 if(symKey == NULL) {
819 printf("Insufficient heap space\n");
820 return NULL;
821 }
822 memset(symKey, 0, sizeof(CSSM_KEY));
823 setBadKeyData(symKey);
824 memset(&creds, 0, sizeof(CSSM_ACCESS_CREDENTIALS));
825 if(keySizeInBits == CSP_KEY_SIZE_DEFAULT) {
826 keySizeInBits = cspDefaultKeySize(keyAlg);
827 }
828 crtn = CSSM_CSP_CreateDeriveKeyContext(cspHand,
829 deriveAlg,
830 keyAlg,
831 keySizeInBits,
832 &creds,
833 NULL, // BaseKey
834 iterationCnt,
835 salt,
836 NULL, // seed
837 &ccHand);
838 if(crtn) {
839 printError("CSSM_CSP_CreateDeriveKeyContext", crtn);
840 goto errorOut;
841 }
842 keyAttr = CSSM_KEYATTR_EXTRACTABLE;
843 if(isRefKey) {
844 keyAttr |= (CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_SENSITIVE);
845 }
846 else {
847 keyAttr |= CSSM_KEYATTR_RETURN_DATA;
848 }
849 dummyLabel.Length = keyLabelLen;
850 dummyLabel.Data = (uint8 *)keyLabel;
851
852 /* passing in password is pretty strange....*/
853 pbeParams.Passphrase = *password;
854 pbeParams.PseudoRandomFunction =
855 CSSM_PKCS5_PBKDF2_PRF_HMAC_SHA1;
856 pbeData.Data = (uint8 *)&pbeParams;
857 pbeData.Length = sizeof(pbeParams);
858 crtn = CSSM_DeriveKey(ccHand,
859 &pbeData,
860 keyUsage,
861 keyAttr,
862 &dummyLabel,
863 NULL, // cred and acl
864 symKey);
865 if(crtn) {
866 printError("CSSM_DeriveKey", crtn);
867 goto errorOut;
868 }
869 /* copy IV back to caller */
870 /* Nope, not supported */
871 #if 0
872 if(pbeParams.InitVector.Data != NULL) {
873 if(initVector->Data != NULL) {
874 if(initVector->Length < pbeParams.InitVector.Length) {
875 printf("***Insufficient InitVector\n");
876 goto errorOut;
877 }
878 }
879 else {
880 initVector->Data =
881 (uint8 *)CSSM_MALLOC(pbeParams.InitVector.Length);
882 }
883 memmove(initVector->Data, pbeParams.InitVector.Data,
884 pbeParams.InitVector.Length);
885 initVector->Length = pbeParams.InitVector.Length;
886 CSSM_FREE(pbeParams.InitVector.Data);
887 }
888 else {
889 printf("***Warning: CSSM_DeriveKey, no InitVector\n");
890 }
891 #endif
892 crtn = CSSM_DeleteContext(ccHand);
893 if(crtn) {
894 printError("CSSM_DeleteContext", crtn);
895 goto errorOut;
896 }
897 return symKey;
898 errorOut:
899 CSSM_FREE(symKey);
900 return NULL;
901 }
902
903 /*
904 * Cook up a symmetric key with specified key bits and other
905 * params. Currently the CSPDL can only deal with reference keys except when
906 * doing wrap/unwrap, so we manually cook up a raw key, then we null-unwrap it.
907 */
908 CSSM_RETURN cspGenSymKeyWithBits(
909 CSSM_CSP_HANDLE cspHand,
910 CSSM_ALGORITHMS keyAlg,
911 CSSM_KEYUSE keyUsage,
912 const CSSM_DATA *keyBits,
913 unsigned keySizeInBytes,
914 CSSM_KEY_PTR refKey) // init'd and RETURNED
915 {
916 CSSM_KEY rawKey;
917 CSSM_KEYHEADER_PTR hdr = &rawKey.KeyHeader;
918 CSSM_RETURN crtn;
919
920 /* set up a raw key the CSP will accept */
921 memset(&rawKey, 0, sizeof(CSSM_KEY));
922 hdr->HeaderVersion = CSSM_KEYHEADER_VERSION;
923 hdr->BlobType = CSSM_KEYBLOB_RAW;
924 hdr->Format = CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING;
925 hdr->AlgorithmId = keyAlg;
926 hdr->KeyClass = CSSM_KEYCLASS_SESSION_KEY;
927 hdr->LogicalKeySizeInBits = keySizeInBytes * 8;
928 hdr->KeyAttr = CSSM_KEYATTR_EXTRACTABLE;
929 hdr->KeyUsage = keyUsage;
930 appSetupCssmData(&rawKey.KeyData, keySizeInBytes);
931 memmove(rawKey.KeyData.Data, keyBits->Data, keySizeInBytes);
932
933 /* convert to a ref key */
934 crtn = cspRawKeyToRef(cspHand, &rawKey, refKey);
935 appFreeCssmData(&rawKey.KeyData, CSSM_FALSE);
936 return crtn;
937 }
938
939 /*
940 * Free a key. This frees a CSP's resources associated with the key if
941 * the key is a reference key. It also frees key->KeyData. The CSSM_KEY
942 * struct itself is not freed.
943 * Note this has no effect on the CSP or DL cached keys unless the incoming
944 * key is a reference key.
945 */
946 CSSM_RETURN cspFreeKey(CSSM_CSP_HANDLE cspHand,
947 CSSM_KEY_PTR key)
948 {
949 CSSM_RETURN crtn;
950 crtn = CSSM_FreeKey(cspHand,
951 NULL, // access cred
952 key,
953 CSSM_FALSE); // delete - OK? maybe should parameterize?
954 if(crtn) {
955 printError("CSSM_FreeKey", crtn);
956 }
957 return crtn;
958 }
959
960 /* generate a random and reasonable key size in bits for specified CSSM algorithm */
961 uint32 randKeySizeBits(uint32 alg,
962 opType op) // OT_Encrypt, etc.
963 {
964 uint32 minSize;
965 uint32 maxSize;
966 uint32 size;
967
968 switch(alg) {
969 case CSSM_ALGID_DES:
970 return CSP_DES_KEY_SIZE_DEFAULT;
971 case CSSM_ALGID_3DES_3KEY:
972 case CSSM_ALGID_DESX:
973 return CSP_DES3_KEY_SIZE_DEFAULT;
974 case CSSM_ALGID_ASC:
975 case CSSM_ALGID_RC2:
976 case CSSM_ALGID_RC4:
977 case CSSM_ALGID_RC5:
978 minSize = 5 * 8;
979 maxSize = MAX_KEY_SIZE_RC245_BYTES * 8 ; // somewhat arbitrary
980 break;
981 case CSSM_ALGID_BLOWFISH:
982 minSize = 32;
983 maxSize = 448;
984 break;
985 case CSSM_ALGID_CAST:
986 minSize = 40;
987 maxSize = 128;
988 break;
989 case CSSM_ALGID_IDEA:
990 return CSP_IDEA_KEY_SIZE_DEFAULT;
991 case CSSM_ALGID_RSA:
992 minSize = CSP_RSA_KEY_SIZE_DEFAULT;
993 maxSize = 1024;
994 break;
995 case CSSM_ALGID_DSA:
996 /* signature only, no export restriction */
997 minSize = 512;
998 maxSize = 1024;
999 break;
1000 case CSSM_ALGID_SHA1HMAC:
1001 minSize = 20 * 8;
1002 maxSize = 256 * 8;
1003 break;
1004 case CSSM_ALGID_MD5HMAC:
1005 minSize = 16 * 8;
1006 maxSize = 256 * 8;
1007 break;
1008 case CSSM_ALGID_FEE:
1009 /* FEE requires discrete sizes */
1010 size = genRand(1,4);
1011 switch(size) {
1012 case 1:
1013 return 31;
1014 case 2:
1015 if(alg == CSSM_ALGID_FEE) {
1016 return 127;
1017 }
1018 else {
1019 return 128;
1020 }
1021 case 3:
1022 return 161;
1023 case 4:
1024 return 192;
1025 default:
1026 printf("randKeySizeBits: internal error\n");
1027 return 0;
1028 }
1029 case CSSM_ALGID_ECDSA:
1030 case CSSM_ALGID_SHA1WithECDSA:
1031 /* ECDSA require discrete sizes */
1032 size = genRand(1,4);
1033 switch(size) {
1034 case 1:
1035 return 192;
1036 case 2:
1037 return 256;
1038 case 3:
1039 return 384;
1040 case 4:
1041 default:
1042 return 521;
1043 }
1044 case CSSM_ALGID_AES:
1045 size = genRand(1, 3);
1046 switch(size) {
1047 case 1:
1048 return 128;
1049 case 2:
1050 return 192;
1051 case 3:
1052 return 256;
1053 }
1054 case CSSM_ALGID_NONE:
1055 return CSP_NULL_CRYPT_KEY_SIZE_DEF;
1056 default:
1057 printf("randKeySizeBits: unknown alg\n");
1058 return CSP_KEY_SIZE_DEFAULT;
1059 }
1060 size = genRand(minSize, maxSize);
1061
1062 /* per-alg postprocessing.... */
1063 if(alg != CSSM_ALGID_RC2) {
1064 size &= ~0x7;
1065 }
1066 switch(alg) {
1067 case CSSM_ALGID_RSA:
1068 // new for X - strong keys */
1069 size &= ~(16 - 1);
1070 break;
1071 case CSSM_ALGID_DSA:
1072 /* size mod 64 == 0 */
1073 size &= ~(64 - 1);
1074 break;
1075 default:
1076 break;
1077 }
1078 return size;
1079 }
1080
1081 #pragma mark --------- Encrypt/Decrypt ---------
1082
1083 /*
1084 * Encrypt/Decrypt
1085 */
1086 /*
1087 * Common routine for encrypt/decrypt - cook up an appropriate context handle
1088 */
1089 /*
1090 * When true, effectiveKeySizeInBits is passed down via the Params argument.
1091 * Otherwise, we add a customized context attribute.
1092 * Setting this true works with the stock Intel CSSM; this may well change.
1093 * Note this overloading prevent us from specifying RC5 rounds....
1094 */
1095 #define EFFECTIVE_SIZE_VIA_PARAMS 0
1096 CSSM_CC_HANDLE genCryptHandle(CSSM_CSP_HANDLE cspHand,
1097 uint32 algorithm, // CSSM_ALGID_FEED, etc.
1098 uint32 mode, // CSSM_ALGMODE_CBC, etc. - only for symmetric algs
1099 CSSM_PADDING padding, // CSSM_PADDING_PKCS1, etc.
1100 const CSSM_KEY *key0,
1101 const CSSM_KEY *key1, // for CSSM_ALGID_FEED only - must be the
1102 // public key
1103 const CSSM_DATA *iv, // optional
1104 uint32 effectiveKeySizeInBits, // 0 means skip this attribute
1105 uint32 rounds) // ditto
1106 {
1107 CSSM_CC_HANDLE cryptHand = 0;
1108 uint32 params;
1109 CSSM_RETURN crtn;
1110 CSSM_ACCESS_CREDENTIALS creds;
1111
1112 memset(&creds, 0, sizeof(CSSM_ACCESS_CREDENTIALS));
1113 #if EFFECTIVE_SIZE_VIA_PARAMS
1114 params = effectiveKeySizeInBits;
1115 #else
1116 params = 0;
1117 #endif
1118 switch(algorithm) {
1119 case CSSM_ALGID_DES:
1120 case CSSM_ALGID_3DES_3KEY_EDE:
1121 case CSSM_ALGID_DESX:
1122 case CSSM_ALGID_ASC:
1123 case CSSM_ALGID_RC2:
1124 case CSSM_ALGID_RC4:
1125 case CSSM_ALGID_RC5:
1126 case CSSM_ALGID_AES:
1127 case CSSM_ALGID_BLOWFISH:
1128 case CSSM_ALGID_CAST:
1129 case CSSM_ALGID_IDEA:
1130 case CSSM_ALGID_NONE: // used for wrapKey()
1131 crtn = CSSM_CSP_CreateSymmetricContext(cspHand,
1132 algorithm,
1133 mode,
1134 NULL, // access cred
1135 key0,
1136 iv, // InitVector
1137 padding,
1138 NULL, // Params
1139 &cryptHand);
1140 if(crtn) {
1141 printError("CSSM_CSP_CreateSymmetricContext", crtn);
1142 return 0;
1143 }
1144 break;
1145 case CSSM_ALGID_FEED:
1146 case CSSM_ALGID_FEEDEXP:
1147 case CSSM_ALGID_FEECFILE:
1148 case CSSM_ALGID_RSA:
1149 crtn = CSSM_CSP_CreateAsymmetricContext(cspHand,
1150 algorithm,
1151 &creds, // access
1152 key0,
1153 padding,
1154 &cryptHand);
1155 if(crtn) {
1156 printError("CSSM_CSP_CreateAsymmetricContext", crtn);
1157 return 0;
1158 }
1159 if(key1 != NULL) {
1160 /*
1161 * FEED, some CFILE. Add (non-standard) second key attribute.
1162 */
1163 crtn = AddContextAttribute(cryptHand,
1164 CSSM_ATTRIBUTE_PUBLIC_KEY,
1165 sizeof(CSSM_KEY), // currently sizeof CSSM_DATA
1166 CAT_Ptr,
1167 key1,
1168 0);
1169 if(crtn) {
1170 printError("AddContextAttribute", crtn);
1171 return 0;
1172 }
1173 }
1174 if(mode != CSSM_ALGMODE_NONE) {
1175 /* special case, e.g., CSSM_ALGMODE_PUBLIC_KEY */
1176 crtn = AddContextAttribute(cryptHand,
1177 CSSM_ATTRIBUTE_MODE,
1178 sizeof(uint32),
1179 CAT_Uint32,
1180 NULL,
1181 mode);
1182 if(crtn) {
1183 printError("AddContextAttribute", crtn);
1184 return 0;
1185 }
1186 }
1187 break;
1188 default:
1189 printf("genCryptHandle: bogus algorithm\n");
1190 return 0;
1191 }
1192 #if !EFFECTIVE_SIZE_VIA_PARAMS
1193 /* add optional EffectiveKeySizeInBits and rounds attributes */
1194 if(effectiveKeySizeInBits != 0) {
1195 CSSM_CONTEXT_ATTRIBUTE attr;
1196 attr.AttributeType = CSSM_ATTRIBUTE_EFFECTIVE_BITS;
1197 attr.AttributeLength = sizeof(uint32);
1198 attr.Attribute.Uint32 = effectiveKeySizeInBits;
1199 crtn = CSSM_UpdateContextAttributes(
1200 cryptHand,
1201 1,
1202 &attr);
1203 if(crtn) {
1204 printError("CSSM_UpdateContextAttributes", crtn);
1205 return crtn;
1206 }
1207 }
1208 #endif
1209
1210 if(rounds != 0) {
1211 CSSM_CONTEXT_ATTRIBUTE attr;
1212 attr.AttributeType = CSSM_ATTRIBUTE_ROUNDS;
1213 attr.AttributeLength = sizeof(uint32);
1214 attr.Attribute.Uint32 = rounds;
1215 crtn = CSSM_UpdateContextAttributes(
1216 cryptHand,
1217 1,
1218 &attr);
1219 if(crtn) {
1220 printError("CSSM_UpdateContextAttributes", crtn);
1221 return crtn;
1222 }
1223 }
1224
1225 return cryptHand;
1226 }
1227
1228 CSSM_RETURN cspEncrypt(CSSM_CSP_HANDLE cspHand,
1229 uint32 algorithm, // CSSM_ALGID_FEED, etc.
1230 uint32 mode, // CSSM_ALGMODE_CBC, etc. - only for symmetric algs
1231 CSSM_PADDING padding, // CSSM_PADDING_PKCS1, etc.
1232 const CSSM_KEY *key, // public or session key
1233 const CSSM_KEY *pubKey, // for CSSM_ALGID_FEED, CSSM_ALGID_FEECFILE only
1234 uint32 effectiveKeySizeInBits, // 0 means skip this attribute
1235 uint32 rounds, // ditto
1236 const CSSM_DATA *iv, // init vector, optional
1237 const CSSM_DATA *ptext,
1238 CSSM_DATA_PTR ctext, // RETURNED
1239 CSSM_BOOL mallocCtext) // if true, and ctext empty, malloc
1240 // by getting size from CSP
1241 {
1242 CSSM_CC_HANDLE cryptHand;
1243 CSSM_RETURN crtn;
1244 CSSM_SIZE bytesEncrypted;
1245 CSSM_DATA remData = {0, NULL};
1246 CSSM_RETURN ocrtn = CSSM_OK;
1247 unsigned origCtextLen; // the amount we malloc, if any
1248 CSSM_RETURN savedErr = CSSM_OK;
1249 CSSM_BOOL restoreErr = CSSM_FALSE;
1250
1251 cryptHand = genCryptHandle(cspHand,
1252 algorithm,
1253 mode,
1254 padding,
1255 key,
1256 pubKey,
1257 iv,
1258 effectiveKeySizeInBits,
1259 rounds);
1260 if(cryptHand == 0) {
1261 return CSSMERR_CSSM_INTERNAL_ERROR;
1262 }
1263 if(mallocCtext && (ctext->Length == 0)) {
1264 CSSM_QUERY_SIZE_DATA querySize;
1265 querySize.SizeInputBlock = ptext->Length;
1266 crtn = CSSM_QuerySize(cryptHand,
1267 CSSM_TRUE, // encrypt
1268 1,
1269 &querySize);
1270 if(crtn) {
1271 printError("CSSM_QuerySize", crtn);
1272 ocrtn = crtn;
1273 goto abort;
1274 }
1275 if(querySize.SizeOutputBlock == 0) {
1276 /* CSP couldn't figure this out; skip our malloc */
1277 printf("***cspEncrypt: warning: cipherTextSize unknown; "
1278 "skipping malloc\n");
1279 origCtextLen = 0;
1280 }
1281 else {
1282 ctext->Data = (uint8 *)
1283 appMalloc(querySize.SizeOutputBlock, NULL);
1284 if(ctext->Data == NULL) {
1285 printf("Insufficient heap space\n");
1286 ocrtn = CSSM_ERRCODE_MEMORY_ERROR;
1287 goto abort;
1288 }
1289 ctext->Length = origCtextLen = querySize.SizeOutputBlock;
1290 memset(ctext->Data, 0, ctext->Length);
1291 }
1292 }
1293 else {
1294 origCtextLen = ctext->Length;
1295 }
1296 crtn = CSSM_EncryptData(cryptHand,
1297 ptext,
1298 1,
1299 ctext,
1300 1,
1301 &bytesEncrypted,
1302 &remData);
1303 if(crtn == CSSM_OK) {
1304 /*
1305 * Deal with remData - its contents are included in bytesEncrypted.
1306 */
1307 if((remData.Length != 0) && mallocCtext) {
1308 /* shouldn't happen - right? */
1309 if(bytesEncrypted > origCtextLen) {
1310 /* malloc and copy a new one */
1311 uint8 *newCdata = (uint8 *)appMalloc(bytesEncrypted, NULL);
1312 printf("**Warning: app malloced cipherBuf, but got nonzero "
1313 "remData!\n");
1314 if(newCdata == NULL) {
1315 printf("Insufficient heap space\n");
1316 ocrtn = CSSM_ERRCODE_MEMORY_ERROR;
1317 goto abort;
1318 }
1319 memmove(newCdata, ctext->Data, ctext->Length);
1320 memmove(newCdata+ctext->Length, remData.Data, remData.Length);
1321 CSSM_FREE(ctext->Data);
1322 ctext->Data = newCdata;
1323 }
1324 else {
1325 /* there's room left over */
1326 memmove(ctext->Data+ctext->Length, remData.Data, remData.Length);
1327 }
1328 ctext->Length = bytesEncrypted;
1329 }
1330 // NOTE: We return the proper length in ctext....
1331 ctext->Length = bytesEncrypted;
1332 }
1333 else {
1334 savedErr = crtn;
1335 restoreErr = CSSM_TRUE;
1336 printError("CSSM_EncryptData", crtn);
1337 }
1338 abort:
1339 crtn = CSSM_DeleteContext(cryptHand);
1340 if(crtn) {
1341 printError("CSSM_DeleteContext", crtn);
1342 ocrtn = crtn;
1343 }
1344 if(restoreErr) {
1345 ocrtn = savedErr;
1346 }
1347 return ocrtn;
1348 }
1349
1350 #define PAD_IMPLIES_RAND_PTEXTSIZE 1
1351 #define LOG_STAGED_OPS 0
1352 #if LOG_STAGED_OPS
1353 #define soprintf(s) printf s
1354 #else
1355 #define soprintf(s)
1356 #endif
1357
1358 CSSM_RETURN cspStagedEncrypt(CSSM_CSP_HANDLE cspHand,
1359 uint32 algorithm, // CSSM_ALGID_FEED, etc.
1360 uint32 mode, // CSSM_ALGMODE_CBC, etc. - only for symmetric algs
1361 CSSM_PADDING padding, // CSSM_PADDING_PKCS1, etc.
1362 const CSSM_KEY *key, // public or session key
1363 const CSSM_KEY *pubKey, // for CSSM_ALGID_FEED, CSSM_ALGID_FEECFILE only
1364 uint32 effectiveKeySizeInBits, // 0 means skip this attribute
1365 uint32 cipherBlockSize, // ditto
1366 uint32 rounds, // ditto
1367 const CSSM_DATA *iv, // init vector, optional
1368 const CSSM_DATA *ptext,
1369 CSSM_DATA_PTR ctext, // RETURNED, we malloc
1370 CSSM_BOOL multiUpdates) // false:single update, true:multi updates
1371 {
1372 CSSM_CC_HANDLE cryptHand;
1373 CSSM_RETURN crtn;
1374 CSSM_SIZE bytesEncrypted; // per update
1375 CSSM_SIZE bytesEncryptedTotal = 0;
1376 CSSM_RETURN ocrtn = CSSM_OK; // 'our' crtn
1377 unsigned toMove; // remaining
1378 unsigned thisMove; // bytes to encrypt on this update
1379 CSSM_DATA thisPtext; // running ptr into ptext
1380 CSSM_DATA ctextWork; // per update, mallocd by CSP
1381 CSSM_QUERY_SIZE_DATA querySize;
1382 uint8 *origCtext; // initial ctext->Data
1383 unsigned origCtextLen; // amount we mallocd
1384 CSSM_BOOL restoreErr = CSSM_FALSE;
1385 CSSM_RETURN savedErr = CSSM_OK;
1386
1387
1388 cryptHand = genCryptHandle(cspHand,
1389 algorithm,
1390 mode,
1391 padding,
1392 key,
1393 pubKey,
1394 iv,
1395 effectiveKeySizeInBits,
1396 rounds);
1397 if(cryptHand == 0) {
1398 return CSSMERR_CSP_INTERNAL_ERROR;
1399 }
1400 if(cipherBlockSize) {
1401 crtn = AddContextAttribute(cryptHand,
1402 CSSM_ATTRIBUTE_BLOCK_SIZE,
1403 sizeof(uint32),
1404 CAT_Uint32,
1405 NULL,
1406 cipherBlockSize);
1407 if(crtn) {
1408 printError("CSSM_UpdateContextAttributes", crtn);
1409 goto abort;
1410 }
1411 }
1412
1413 /* obtain total required ciphertext size and block size */
1414 querySize.SizeInputBlock = ptext->Length;
1415 crtn = CSSM_QuerySize(cryptHand,
1416 CSSM_TRUE, // encrypt
1417 1,
1418 &querySize);
1419 if(crtn) {
1420 printError("CSSM_QuerySize(1)", crtn);
1421 ocrtn = CSSMERR_CSP_INTERNAL_ERROR;
1422 goto abort;
1423 }
1424 if(querySize.SizeOutputBlock == 0) {
1425 /* CSP couldn't figure this out; skip our malloc - caller is taking its
1426 * chances */
1427 printf("***cspStagedEncrypt: warning: cipherTextSize unknown; aborting\n");
1428 ocrtn = CSSMERR_CSP_INTERNAL_ERROR;
1429 goto abort;
1430 }
1431 else {
1432 origCtextLen = querySize.SizeOutputBlock;
1433 if(algorithm == CSSM_ALGID_ASC) {
1434 /* ASC is weird - the more chunks we do, the bigger the
1435 * resulting ctext...*/
1436 origCtextLen *= 2;
1437 }
1438 ctext->Length = origCtextLen;
1439 ctext->Data = origCtext = (uint8 *)appMalloc(origCtextLen, NULL);
1440 if(ctext->Data == NULL) {
1441 printf("Insufficient heap space\n");
1442 ocrtn = CSSMERR_CSP_MEMORY_ERROR;
1443 goto abort;
1444 }
1445 memset(ctext->Data, 0, ctext->Length);
1446 }
1447
1448 crtn = CSSM_EncryptDataInit(cryptHand);
1449 if(crtn) {
1450 printError("CSSM_EncryptDataInit", crtn);
1451 ocrtn = crtn;
1452 goto abort;
1453 }
1454
1455 toMove = ptext->Length;
1456 thisPtext.Data = ptext->Data;
1457 while(toMove) {
1458 if(multiUpdates) {
1459 thisMove = genRand(1, toMove);
1460 }
1461 else {
1462 /* just do one pass thru this loop */
1463 thisMove = toMove;
1464 }
1465 thisPtext.Length = thisMove;
1466 /* let CSP do the individual mallocs */
1467 ctextWork.Data = NULL;
1468 ctextWork.Length = 0;
1469 soprintf(("*** EncryptDataUpdate: ptextLen 0x%x\n", thisMove));
1470 crtn = CSSM_EncryptDataUpdate(cryptHand,
1471 &thisPtext,
1472 1,
1473 &ctextWork,
1474 1,
1475 &bytesEncrypted);
1476 if(crtn) {
1477 printError("CSSM_EncryptDataUpdate", crtn);
1478 ocrtn = crtn;
1479 goto abort;
1480 }
1481 // NOTE: We return the proper length in ctext....
1482 ctextWork.Length = bytesEncrypted;
1483 soprintf(("*** EncryptDataUpdate: ptextLen 0x%x bytesEncrypted 0x%x\n",
1484 thisMove, bytesEncrypted));
1485 thisPtext.Data += thisMove;
1486 toMove -= thisMove;
1487 if(bytesEncrypted > ctext->Length) {
1488 printf("cspStagedEncrypt: ctext overflow!\n");
1489 ocrtn = crtn;
1490 goto abort;
1491 }
1492 if(bytesEncrypted != 0) {
1493 memmove(ctext->Data, ctextWork.Data, bytesEncrypted);
1494 bytesEncryptedTotal += bytesEncrypted;
1495 ctext->Data += bytesEncrypted;
1496 ctext->Length -= bytesEncrypted;
1497 }
1498 if(ctextWork.Data != NULL) {
1499 CSSM_FREE(ctextWork.Data);
1500 }
1501 }
1502 /* OK, one more */
1503 ctextWork.Data = NULL;
1504 ctextWork.Length = 0;
1505 crtn = CSSM_EncryptDataFinal(cryptHand, &ctextWork);
1506 if(crtn) {
1507 printError("CSSM_EncryptDataFinal", crtn);
1508 savedErr = crtn;
1509 restoreErr = CSSM_TRUE;
1510 goto abort;
1511 }
1512 if(ctextWork.Length != 0) {
1513 bytesEncryptedTotal += ctextWork.Length;
1514 if(ctextWork.Length > ctext->Length) {
1515 printf("cspStagedEncrypt: ctext overflow (2)!\n");
1516 ocrtn = CSSMERR_CSP_INTERNAL_ERROR;
1517 goto abort;
1518 }
1519 memmove(ctext->Data, ctextWork.Data, ctextWork.Length);
1520 }
1521 if(ctextWork.Data) {
1522 /* this could have gotten mallocd and Length still be zero */
1523 CSSM_FREE(ctextWork.Data);
1524 }
1525
1526 /* retweeze ctext */
1527 ctext->Data = origCtext;
1528 ctext->Length = bytesEncryptedTotal;
1529 abort:
1530 crtn = CSSM_DeleteContext(cryptHand);
1531 if(crtn) {
1532 printError("CSSM_DeleteContext", crtn);
1533 ocrtn = crtn;
1534 }
1535 if(restoreErr) {
1536 /* give caller the error from the encrypt */
1537 ocrtn = savedErr;
1538 }
1539 return ocrtn;
1540 }
1541
1542 CSSM_RETURN cspDecrypt(CSSM_CSP_HANDLE cspHand,
1543 uint32 algorithm, // CSSM_ALGID_FEED, etc.
1544 uint32 mode, // CSSM_ALGMODE_CBC, etc. - only for symmetric algs
1545 CSSM_PADDING padding, // CSSM_PADDING_PKCS1, etc.
1546 const CSSM_KEY *key, // public or session key
1547 const CSSM_KEY *pubKey, // for CSSM_ALGID_FEED, CSSM_ALGID_FEECFILE only
1548 uint32 effectiveKeySizeInBits, // 0 means skip this attribute
1549 uint32 rounds, // ditto
1550 const CSSM_DATA *iv, // init vector, optional
1551 const CSSM_DATA *ctext,
1552 CSSM_DATA_PTR ptext, // RETURNED
1553 CSSM_BOOL mallocPtext) // if true and ptext->Length = 0,
1554 // we'll malloc
1555 {
1556 CSSM_CC_HANDLE cryptHand;
1557 CSSM_RETURN crtn;
1558 CSSM_RETURN ocrtn = CSSM_OK;
1559 CSSM_SIZE bytesDecrypted;
1560 CSSM_DATA remData = {0, NULL};
1561 unsigned origPtextLen; // the amount we malloc, if any
1562
1563 cryptHand = genCryptHandle(cspHand,
1564 algorithm,
1565 mode,
1566 padding,
1567 key,
1568 pubKey,
1569 iv,
1570 effectiveKeySizeInBits,
1571 rounds);
1572 if(cryptHand == 0) {
1573 return CSSMERR_CSP_INTERNAL_ERROR;
1574 }
1575 if(mallocPtext && (ptext->Length == 0)) {
1576 CSSM_QUERY_SIZE_DATA querySize;
1577 querySize.SizeInputBlock = ctext->Length;
1578 crtn = CSSM_QuerySize(cryptHand,
1579 CSSM_FALSE, // encrypt
1580 1,
1581 &querySize);
1582 if(crtn) {
1583 printError("CSSM_QuerySize", crtn);
1584 ocrtn = crtn;
1585 goto abort;
1586 }
1587 if(querySize.SizeOutputBlock == 0) {
1588 /* CSP couldn't figure this one out; skip our malloc */
1589 printf("***cspDecrypt: warning: plainTextSize unknown; "
1590 "skipping malloc\n");
1591 origPtextLen = 0;
1592 }
1593 else {
1594 ptext->Data =
1595 (uint8 *)appMalloc(querySize.SizeOutputBlock, NULL);
1596 if(ptext->Data == NULL) {
1597 printf("Insufficient heap space\n");
1598 ocrtn = CSSMERR_CSP_MEMORY_ERROR;
1599 goto abort;
1600 }
1601 ptext->Length = origPtextLen = querySize.SizeOutputBlock;
1602 memset(ptext->Data, 0, ptext->Length);
1603 }
1604 }
1605 else {
1606 origPtextLen = ptext->Length;
1607 }
1608 crtn = CSSM_DecryptData(cryptHand,
1609 ctext,
1610 1,
1611 ptext,
1612 1,
1613 &bytesDecrypted,
1614 &remData);
1615 if(crtn == CSSM_OK) {
1616 /*
1617 * Deal with remData - its contents are included in bytesDecrypted.
1618 */
1619 if((remData.Length != 0) && mallocPtext) {
1620 /* shouldn't happen - right? */
1621 if(bytesDecrypted > origPtextLen) {
1622 /* malloc and copy a new one */
1623 uint8 *newPdata = (uint8 *)appMalloc(bytesDecrypted, NULL);
1624 printf("**Warning: app malloced ClearBuf, but got nonzero "
1625 "remData!\n");
1626 if(newPdata == NULL) {
1627 printf("Insufficient heap space\n");
1628 ocrtn = CSSMERR_CSP_MEMORY_ERROR;
1629 goto abort;
1630 }
1631 memmove(newPdata, ptext->Data, ptext->Length);
1632 memmove(newPdata + ptext->Length,
1633 remData.Data, remData.Length);
1634 CSSM_FREE(ptext->Data);
1635 ptext->Data = newPdata;
1636 }
1637 else {
1638 /* there's room left over */
1639 memmove(ptext->Data + ptext->Length,
1640 remData.Data, remData.Length);
1641 }
1642 ptext->Length = bytesDecrypted;
1643 }
1644 // NOTE: We return the proper length in ptext....
1645 ptext->Length = bytesDecrypted;
1646
1647 // FIXME - sometimes get mallocd RemData here, but never any valid data
1648 // there...side effect of CSPFullPluginSession's buffer handling logic;
1649 // but will we ever actually see valid data in RemData? So far we never
1650 // have....
1651 if(remData.Data != NULL) {
1652 appFree(remData.Data, NULL);
1653 }
1654 }
1655 else {
1656 printError("CSSM_DecryptData", crtn);
1657 ocrtn = crtn;
1658 }
1659 abort:
1660 crtn = CSSM_DeleteContext(cryptHand);
1661 if(crtn) {
1662 printError("CSSM_DeleteContext", crtn);
1663 ocrtn = crtn;
1664 }
1665 return ocrtn;
1666 }
1667
1668 CSSM_RETURN cspStagedDecrypt(CSSM_CSP_HANDLE cspHand,
1669 uint32 algorithm, // CSSM_ALGID_FEED, etc.
1670 uint32 mode, // CSSM_ALGMODE_CBC, etc. - only for symmetric algs
1671 CSSM_PADDING padding, // CSSM_PADDING_PKCS1, etc.
1672 const CSSM_KEY *key, // public or session key
1673 const CSSM_KEY *pubKey, // for CSSM_ALGID_FEED, CSSM_ALGID_FEECFILE only
1674 uint32 effectiveKeySizeInBits, // 0 means skip this attribute
1675 uint32 cipherBlockSize, // ditto
1676 uint32 rounds, // ditto
1677 const CSSM_DATA *iv, // init vector, optional
1678 const CSSM_DATA *ctext,
1679 CSSM_DATA_PTR ptext, // RETURNED, we malloc
1680 CSSM_BOOL multiUpdates) // false:single update, true:multi updates
1681 {
1682 CSSM_CC_HANDLE cryptHand;
1683 CSSM_RETURN crtn;
1684 CSSM_SIZE bytesDecrypted; // per update
1685 CSSM_SIZE bytesDecryptedTotal = 0;
1686 CSSM_RETURN ocrtn = CSSM_OK; // 'our' crtn
1687 unsigned toMove; // remaining
1688 unsigned thisMove; // bytes to encrypt on this update
1689 CSSM_DATA thisCtext; // running ptr into ptext
1690 CSSM_DATA ptextWork; // per update, mallocd by CSP
1691 CSSM_QUERY_SIZE_DATA querySize;
1692 uint8 *origPtext; // initial ptext->Data
1693 unsigned origPtextLen; // amount we mallocd
1694
1695 cryptHand = genCryptHandle(cspHand,
1696 algorithm,
1697 mode,
1698 padding,
1699 key,
1700 pubKey,
1701 iv,
1702 effectiveKeySizeInBits,
1703 rounds);
1704 if(cryptHand == 0) {
1705 return CSSMERR_CSP_INTERNAL_ERROR;
1706 }
1707 if(cipherBlockSize) {
1708 crtn = AddContextAttribute(cryptHand,
1709 CSSM_ATTRIBUTE_BLOCK_SIZE,
1710 sizeof(uint32),
1711 CAT_Uint32,
1712 NULL,
1713 cipherBlockSize);
1714 if(crtn) {
1715 printError("CSSM_UpdateContextAttributes", crtn);
1716 goto abort;
1717 }
1718 }
1719
1720 /* obtain total required ciphertext size and block size */
1721 querySize.SizeInputBlock = ctext->Length;
1722 crtn = CSSM_QuerySize(cryptHand,
1723 CSSM_FALSE, // encrypt
1724 1,
1725 &querySize);
1726 if(crtn) {
1727 printError("CSSM_QuerySize(1)", crtn);
1728 ocrtn = crtn;
1729 goto abort;
1730 }
1731
1732 /* required ptext size should be independent of number of chunks */
1733 if(querySize.SizeOutputBlock == 0) {
1734 printf("***warning: cspStagedDecrypt: plainTextSize unknown; aborting\n");
1735 ocrtn = CSSMERR_CSP_INTERNAL_ERROR;
1736 goto abort;
1737 }
1738 else {
1739 // until exit, ptext->Length indicates remaining bytes of usable data in
1740 // ptext->Data
1741 ptext->Length = origPtextLen = querySize.SizeOutputBlock;
1742 ptext->Data = origPtext =
1743 (uint8 *)appMalloc(origPtextLen, NULL);
1744 if(ptext->Data == NULL) {
1745 printf("Insufficient heap space\n");
1746 ocrtn = CSSMERR_CSP_INTERNAL_ERROR;
1747 goto abort;
1748 }
1749 memset(ptext->Data, 0, ptext->Length);
1750 }
1751
1752 crtn = CSSM_DecryptDataInit(cryptHand);
1753 if(crtn) {
1754 printError("CSSM_DecryptDataInit", crtn);
1755 ocrtn = crtn;
1756 goto abort;
1757 }
1758 toMove = ctext->Length;
1759 thisCtext.Data = ctext->Data;
1760 while(toMove) {
1761 if(multiUpdates) {
1762 thisMove = genRand(1, toMove);
1763 }
1764 else {
1765 /* just do one pass thru this loop */
1766 thisMove = toMove;
1767 }
1768 thisCtext.Length = thisMove;
1769 /* let CSP do the individual mallocs */
1770 ptextWork.Data = NULL;
1771 ptextWork.Length = 0;
1772 soprintf(("*** DecryptDataUpdate: ctextLen 0x%x\n", thisMove));
1773 crtn = CSSM_DecryptDataUpdate(cryptHand,
1774 &thisCtext,
1775 1,
1776 &ptextWork,
1777 1,
1778 &bytesDecrypted);
1779 if(crtn) {
1780 printError("CSSM_DecryptDataUpdate", crtn);
1781 ocrtn = crtn;
1782 goto abort;
1783 }
1784 //
1785 // NOTE: We return the proper length in ptext....
1786 ptextWork.Length = bytesDecrypted;
1787 thisCtext.Data += thisMove;
1788 toMove -= thisMove;
1789 if(bytesDecrypted > ptext->Length) {
1790 printf("cspStagedDecrypt: ptext overflow!\n");
1791 ocrtn = CSSMERR_CSP_INTERNAL_ERROR;
1792 goto abort;
1793 }
1794 if(bytesDecrypted != 0) {
1795 memmove(ptext->Data, ptextWork.Data, bytesDecrypted);
1796 bytesDecryptedTotal += bytesDecrypted;
1797 ptext->Data += bytesDecrypted;
1798 ptext->Length -= bytesDecrypted;
1799 }
1800 if(ptextWork.Data != NULL) {
1801 CSSM_FREE(ptextWork.Data);
1802 }
1803 }
1804 /* OK, one more */
1805 ptextWork.Data = NULL;
1806 ptextWork.Length = 0;
1807 crtn = CSSM_DecryptDataFinal(cryptHand, &ptextWork);
1808 if(crtn) {
1809 printError("CSSM_DecryptDataFinal", crtn);
1810 ocrtn = crtn;
1811 goto abort;
1812 }
1813 if(ptextWork.Length != 0) {
1814 bytesDecryptedTotal += ptextWork.Length;
1815 if(ptextWork.Length > ptext->Length) {
1816 printf("cspStagedDecrypt: ptext overflow (2)!\n");
1817 ocrtn = CSSMERR_CSP_INTERNAL_ERROR;
1818 goto abort;
1819 }
1820 memmove(ptext->Data, ptextWork.Data, ptextWork.Length);
1821 }
1822 if(ptextWork.Data) {
1823 /* this could have gotten mallocd and Length still be zero */
1824 CSSM_FREE(ptextWork.Data);
1825 }
1826
1827 /* retweeze ptext */
1828 ptext->Data = origPtext;
1829 ptext->Length = bytesDecryptedTotal;
1830 abort:
1831 crtn = CSSM_DeleteContext(cryptHand);
1832 if(crtn) {
1833 printError("CSSM_DeleteContext", crtn);
1834 ocrtn = crtn;
1835 }
1836 return ocrtn;
1837 }
1838
1839 #pragma mark --------- sign/verify/MAC ---------
1840
1841 /*
1842 * Signature routines
1843 * This all-in-one sign op has a special case for RSA keys. If the requested
1844 * alg is MD5 or SHA1, we'll do a manual digest op followed by raw RSA sign.
1845 * Likewise, if it's CSSM_ALGID_DSA, we'll do manual SHA1 digest followed by
1846 * raw DSA sign.
1847 */
1848
1849 CSSM_RETURN cspSign(CSSM_CSP_HANDLE cspHand,
1850 uint32 algorithm, // CSSM_ALGID_FEE_MD5, etc.
1851 CSSM_KEY_PTR key, // private key
1852 const CSSM_DATA *text,
1853 CSSM_DATA_PTR sig) // RETURNED
1854 {
1855 CSSM_CC_HANDLE sigHand;
1856 CSSM_RETURN crtn;
1857 CSSM_RETURN ocrtn = CSSM_OK;
1858 const CSSM_DATA *ptext;
1859 CSSM_DATA digest = {0, NULL};
1860 CSSM_ALGORITHMS digestAlg = CSSM_ALGID_NONE;
1861
1862 /* handle special cases for raw sign */
1863 switch(algorithm) {
1864 case CSSM_ALGID_SHA1:
1865 digestAlg = CSSM_ALGID_SHA1;
1866 algorithm = CSSM_ALGID_RSA;
1867 break;
1868 case CSSM_ALGID_MD5:
1869 digestAlg = CSSM_ALGID_MD5;
1870 algorithm = CSSM_ALGID_RSA;
1871 break;
1872 case CSSM_ALGID_DSA:
1873 digestAlg = CSSM_ALGID_SHA1;
1874 algorithm = CSSM_ALGID_DSA;
1875 break;
1876 default:
1877 break;
1878 }
1879 if(digestAlg != CSSM_ALGID_NONE) {
1880 crtn = cspDigest(cspHand,
1881 digestAlg,
1882 CSSM_FALSE, // mallocDigest
1883 text,
1884 &digest);
1885 if(crtn) {
1886 return crtn;
1887 }
1888 /* sign digest with raw RSA/DSA */
1889 ptext = &digest;
1890 }
1891 else {
1892 ptext = text;
1893 }
1894 crtn = CSSM_CSP_CreateSignatureContext(cspHand,
1895 algorithm,
1896 NULL, // passPhrase
1897 key,
1898 &sigHand);
1899 if(crtn) {
1900 printError("CSSM_CSP_CreateSignatureContext (1)", crtn);
1901 return crtn;
1902 }
1903 crtn = CSSM_SignData(sigHand,
1904 ptext,
1905 1,
1906 digestAlg,
1907 sig);
1908 if(crtn) {
1909 printError("CSSM_SignData", crtn);
1910 ocrtn = crtn;
1911 }
1912 crtn = CSSM_DeleteContext(sigHand);
1913 if(crtn) {
1914 printError("CSSM_DeleteContext", crtn);
1915 ocrtn = crtn;
1916 }
1917 if(digest.Data != NULL) {
1918 CSSM_FREE(digest.Data);
1919 }
1920 return ocrtn;
1921 }
1922
1923 /*
1924 * Staged sign. Each update does a random number of bytes 'till through.
1925 */
1926 CSSM_RETURN cspStagedSign(CSSM_CSP_HANDLE cspHand,
1927 uint32 algorithm, // CSSM_ALGID_FEE_MD5, etc.
1928 CSSM_KEY_PTR key, // private key
1929 const CSSM_DATA *text,
1930 CSSM_BOOL multiUpdates, // false:single update, true:multi updates
1931 CSSM_DATA_PTR sig) // RETURNED
1932 {
1933 CSSM_CC_HANDLE sigHand;
1934 CSSM_RETURN crtn;
1935 CSSM_RETURN ocrtn = CSSM_OK;
1936 unsigned thisMove; // this update
1937 unsigned toMove; // total to go
1938 CSSM_DATA thisText; // actaully passed to update
1939 crtn = CSSM_CSP_CreateSignatureContext(cspHand,
1940 algorithm,
1941 NULL, // passPhrase
1942 key,
1943 &sigHand);
1944 if(crtn) {
1945 printError("CSSM_CSP_CreateSignatureContext (1)", crtn);
1946 return crtn;
1947 }
1948 crtn = CSSM_SignDataInit(sigHand);
1949 if(crtn) {
1950 printError("CSSM_SignDataInit", crtn);
1951 ocrtn = crtn;
1952 goto abort;
1953 }
1954 toMove = text->Length;
1955 thisText.Data = text->Data;
1956 while(toMove) {
1957 if(multiUpdates) {
1958 thisMove = genRand(1, toMove);
1959 }
1960 else {
1961 thisMove = toMove;
1962 }
1963 thisText.Length = thisMove;
1964 crtn = CSSM_SignDataUpdate(sigHand,
1965 &thisText,
1966 1);
1967 if(crtn) {
1968 printError("CSSM_SignDataUpdate", crtn);
1969 ocrtn = crtn;
1970 goto abort;
1971 }
1972 thisText.Data += thisMove;
1973 toMove -= thisMove;
1974 }
1975 crtn = CSSM_SignDataFinal(sigHand, sig);
1976 if(crtn) {
1977 printError("CSSM_SignDataFinal", crtn);
1978 ocrtn = crtn;
1979 goto abort;
1980 }
1981 abort:
1982 crtn = CSSM_DeleteContext(sigHand);
1983 if(crtn) {
1984 printError("CSSM_DeleteContext", crtn);
1985 ocrtn = crtn;
1986 }
1987 return ocrtn;
1988 }
1989
1990 /*
1991 * This all-in-one verify op has a special case for RSA keys. If the requested
1992 * alg is MD5 or SHA1, we'll do a manual digest op followed by raw RSA verify.
1993 * Likewise, if it's CSSM_ALGID_DSA, we'll do manual SHA1 digest followed by
1994 * raw DSA sign.
1995 */
1996
1997 CSSM_RETURN cspSigVerify(CSSM_CSP_HANDLE cspHand,
1998 uint32 algorithm, // CSSM_ALGID_FEE_MD5, etc.
1999 CSSM_KEY_PTR key, // public key
2000 const CSSM_DATA *text,
2001 const CSSM_DATA *sig,
2002 CSSM_RETURN expectResult) // expected result is verify failure
2003 // CSSM_OK - expect success
2004 {
2005 CSSM_CC_HANDLE sigHand;
2006 CSSM_RETURN ocrtn = CSSM_OK;
2007 CSSM_RETURN crtn;
2008 const CSSM_DATA *ptext;
2009 CSSM_DATA digest = {0, NULL};
2010 CSSM_ALGORITHMS digestAlg = CSSM_ALGID_NONE;
2011
2012 /* handle special cases for raw sign */
2013 switch(algorithm) {
2014 case CSSM_ALGID_SHA1:
2015 digestAlg = CSSM_ALGID_SHA1;
2016 algorithm = CSSM_ALGID_RSA;
2017 break;
2018 case CSSM_ALGID_MD5:
2019 digestAlg = CSSM_ALGID_MD5;
2020 algorithm = CSSM_ALGID_RSA;
2021 break;
2022 case CSSM_ALGID_DSA:
2023 digestAlg = CSSM_ALGID_SHA1;
2024 algorithm = CSSM_ALGID_DSA;
2025 break;
2026 default:
2027 break;
2028 }
2029 if(digestAlg != CSSM_ALGID_NONE) {
2030 crtn = cspDigest(cspHand,
2031 digestAlg,
2032 CSSM_FALSE, // mallocDigest
2033 text,
2034 &digest);
2035 if(crtn) {
2036 return crtn;
2037 }
2038 /* sign digest with raw RSA/DSA */
2039 ptext = &digest;
2040 }
2041 else {
2042 ptext = text;
2043 }
2044 crtn = CSSM_CSP_CreateSignatureContext(cspHand,
2045 algorithm,
2046 NULL, // passPhrase
2047 key,
2048 &sigHand);
2049 if(crtn) {
2050 printError("CSSM_CSP_CreateSignatureContext (3)", crtn);
2051 return crtn;
2052 }
2053
2054 crtn = CSSM_VerifyData(sigHand,
2055 ptext,
2056 1,
2057 digestAlg,
2058 sig);
2059 if(crtn != expectResult) {
2060 if(!crtn) {
2061 printf("Unexpected good Sig Verify\n");
2062 }
2063 else {
2064 printError("CSSM_VerifyData", crtn);
2065 }
2066 ocrtn = CSSMERR_CSSM_INTERNAL_ERROR;
2067 }
2068 crtn = CSSM_DeleteContext(sigHand);
2069 if(crtn) {
2070 printError("CSSM_DeleteContext", crtn);
2071 ocrtn = crtn;
2072 }
2073 if(digest.Data != NULL) {
2074 CSSM_FREE(digest.Data);
2075 }
2076 return ocrtn;
2077 }
2078
2079 /*
2080 * Staged verify. Each update does a random number of bytes 'till through.
2081 */
2082 CSSM_RETURN cspStagedSigVerify(CSSM_CSP_HANDLE cspHand,
2083 uint32 algorithm, // CSSM_ALGID_FEE_MD5, etc.
2084 CSSM_KEY_PTR key, // private key
2085 const CSSM_DATA *text,
2086 const CSSM_DATA *sig,
2087 CSSM_BOOL multiUpdates, // false:single update, true:multi updates
2088 CSSM_RETURN expectResult) // expected result is verify failure
2089 // CSSM_TRUE - expect success
2090 {
2091 CSSM_CC_HANDLE sigHand;
2092 CSSM_RETURN crtn;
2093 CSSM_RETURN ocrtn = CSSM_OK;
2094 unsigned thisMove; // this update
2095 unsigned toMove; // total to go
2096 CSSM_DATA thisText; // actaully passed to update
2097 crtn = CSSM_CSP_CreateSignatureContext(cspHand,
2098 algorithm,
2099 NULL, // passPhrase
2100 key,
2101 &sigHand);
2102 if(crtn) {
2103 printError("CSSM_CSP_CreateSignatureContext (4)", crtn);
2104 return crtn;
2105 }
2106 crtn = CSSM_VerifyDataInit(sigHand);
2107 if(crtn) {
2108 printError("CSSM_VerifyDataInit", crtn);
2109 ocrtn = crtn;
2110 goto abort;
2111 }
2112 toMove = text->Length;
2113 thisText.Data = text->Data;
2114 while(toMove) {
2115 if(multiUpdates) {
2116 thisMove = genRand(1, toMove);
2117 }
2118 else {
2119 thisMove = toMove;
2120 }
2121 thisText.Length = thisMove;
2122 crtn = CSSM_VerifyDataUpdate(sigHand,
2123 &thisText,
2124 1);
2125 if(crtn) {
2126 printError("CSSM_VerifyDataUpdate", crtn);
2127 ocrtn = crtn;
2128 goto abort;
2129 }
2130 thisText.Data += thisMove;
2131 toMove -= thisMove;
2132 }
2133 crtn = CSSM_VerifyDataFinal(sigHand, sig);
2134 if(crtn != expectResult) {
2135 if(crtn) {
2136 printError("CSSM_VerifyDataFinal", crtn);
2137 }
2138 else {
2139 printf("Unexpected good Staged Sig Verify\n");
2140 }
2141 ocrtn = CSSMERR_CSSM_INTERNAL_ERROR;
2142 }
2143 abort:
2144 crtn = CSSM_DeleteContext(sigHand);
2145 if(crtn) {
2146 printError("CSSM_DeleteContext", crtn);
2147 ocrtn = crtn;
2148 }
2149 return ocrtn;
2150 }
2151
2152 /*
2153 * MAC routines
2154 */
2155 CSSM_RETURN cspGenMac(CSSM_CSP_HANDLE cspHand,
2156 uint32 algorithm, // CSSM_ALGID_FEE_MD5, etc.
2157 CSSM_KEY_PTR key, // session key
2158 const CSSM_DATA *text,
2159 CSSM_DATA_PTR mac) // RETURNED
2160 {
2161 CSSM_CC_HANDLE macHand;
2162 CSSM_RETURN crtn;
2163 CSSM_RETURN ocrtn = CSSM_OK;
2164 crtn = CSSM_CSP_CreateMacContext(cspHand,
2165 algorithm,
2166 key,
2167 &macHand);
2168 if(crtn) {
2169 printError("CSSM_CSP_CreateMacContext (1)", crtn);
2170 return crtn;
2171 }
2172 crtn = CSSM_GenerateMac(macHand,
2173 text,
2174 1,
2175 mac);
2176 if(crtn) {
2177 printError("CSSM_GenerateMac", crtn);
2178 ocrtn = crtn;
2179 }
2180 crtn = CSSM_DeleteContext(macHand);
2181 if(crtn) {
2182 printError("CSSM_DeleteContext", crtn);
2183 ocrtn = crtn;
2184 }
2185 return ocrtn;
2186 }
2187
2188 /*
2189 * Staged generate mac.
2190 */
2191 CSSM_RETURN cspStagedGenMac(CSSM_CSP_HANDLE cspHand,
2192 uint32 algorithm, // CSSM_ALGID_FEE_MD5, etc.
2193 CSSM_KEY_PTR key, // private key
2194 const CSSM_DATA *text,
2195 CSSM_BOOL mallocMac, // if true and digest->Length = 0, we'll
2196 // malloc
2197 CSSM_BOOL multiUpdates, // false:single update, true:multi updates
2198 CSSM_DATA_PTR mac) // RETURNED
2199 {
2200 CSSM_CC_HANDLE macHand;
2201 CSSM_RETURN crtn;
2202 CSSM_RETURN ocrtn = CSSM_OK;
2203 unsigned thisMove; // this update
2204 unsigned toMove; // total to go
2205 CSSM_DATA thisText; // actaully passed to update
2206
2207 crtn = CSSM_CSP_CreateMacContext(cspHand,
2208 algorithm,
2209 key,
2210 &macHand);
2211 if(crtn) {
2212 printError("CSSM_CSP_CreateMacContext (2)", crtn);
2213 return crtn;
2214 }
2215
2216 if(mallocMac && (mac->Length == 0)) {
2217 /* malloc mac - ask CSP for size */
2218 CSSM_QUERY_SIZE_DATA querySize = {0, 0};
2219 crtn = CSSM_QuerySize(macHand,
2220 CSSM_TRUE, // encrypt
2221 1,
2222 &querySize);
2223 if(crtn) {
2224 printError("CSSM_QuerySize(mac)", crtn);
2225 ocrtn = crtn;
2226 goto abort;
2227 }
2228 if(querySize.SizeOutputBlock == 0) {
2229 printf("Unknown mac size\n");
2230 ocrtn = CSSMERR_CSSM_INTERNAL_ERROR;
2231 goto abort;
2232 }
2233 mac->Data = (uint8 *)appMalloc(querySize.SizeOutputBlock, NULL);
2234 if(mac->Data == NULL) {
2235 printf("malloc failure\n");
2236 ocrtn = CSSMERR_CSSM_MEMORY_ERROR;
2237 goto abort;
2238 }
2239 mac->Length = querySize.SizeOutputBlock;
2240 }
2241
2242 crtn = CSSM_GenerateMacInit(macHand);
2243 if(crtn) {
2244 printError("CSSM_GenerateMacInit", crtn);
2245 ocrtn = crtn;
2246 goto abort;
2247 }
2248 toMove = text->Length;
2249 thisText.Data = text->Data;
2250
2251 while(toMove) {
2252 if(multiUpdates) {
2253 thisMove = genRand(1, toMove);
2254 }
2255 else {
2256 thisMove = toMove;
2257 }
2258 thisText.Length = thisMove;
2259 crtn = CSSM_GenerateMacUpdate(macHand,
2260 &thisText,
2261 1);
2262 if(crtn) {
2263 printError("CSSM_GenerateMacUpdate", crtn);
2264 ocrtn = crtn;
2265 goto abort;
2266 }
2267 thisText.Data += thisMove;
2268 toMove -= thisMove;
2269 }
2270 crtn = CSSM_GenerateMacFinal(macHand, mac);
2271 if(crtn) {
2272 printError("CSSM_GenerateMacFinal", crtn);
2273 ocrtn = crtn;
2274 goto abort;
2275 }
2276 abort:
2277 crtn = CSSM_DeleteContext(macHand);
2278 if(crtn) {
2279 printError("CSSM_DeleteContext", crtn);
2280 ocrtn = crtn;
2281 }
2282 return ocrtn;
2283 }
2284
2285 CSSM_RETURN cspMacVerify(CSSM_CSP_HANDLE cspHand,
2286 uint32 algorithm, // CSSM_ALGID_FEE_MD5, etc.
2287 CSSM_KEY_PTR key, // public key
2288 const CSSM_DATA *text,
2289 const CSSM_DATA_PTR mac,
2290 CSSM_RETURN expectResult) // expected result
2291 // CSSM_OK - expect success
2292 {
2293 CSSM_CC_HANDLE macHand;
2294 CSSM_RETURN ocrtn = CSSM_OK;
2295 CSSM_RETURN crtn;
2296 crtn = CSSM_CSP_CreateMacContext(cspHand,
2297 algorithm,
2298 key,
2299 &macHand);
2300 if(crtn) {
2301 printError("CSSM_CSP_CreateMacContext (3)", crtn);
2302 return crtn;
2303 }
2304 crtn = CSSM_VerifyMac(macHand,
2305 text,
2306 1,
2307 mac);
2308 if(crtn != expectResult) {
2309 if(crtn) {
2310 printError("CSSM_VerifyMac", crtn);
2311 }
2312 else {
2313 printf("Unexpected good Mac Verify\n");
2314 }
2315 ocrtn = CSSMERR_CSSM_INTERNAL_ERROR;
2316 }
2317 crtn = CSSM_DeleteContext(macHand);
2318 if(crtn) {
2319 printError("CSSM_DeleteContext", crtn);
2320 ocrtn = crtn;
2321 }
2322 return ocrtn;
2323 }
2324
2325 /*
2326 * Staged mac verify. Each update does a random number of bytes 'till through.
2327 */
2328 CSSM_RETURN cspStagedMacVerify(CSSM_CSP_HANDLE cspHand,
2329 uint32 algorithm, // CSSM_ALGID_FEE_MD5, etc.
2330 CSSM_KEY_PTR key, // private key
2331 const CSSM_DATA *text,
2332 const CSSM_DATA_PTR mac,
2333 CSSM_BOOL multiUpdates, // false:single update, true:multi updates
2334 CSSM_RETURN expectResult) // expected result is verify failure
2335 // CSSM_OK - expect success
2336 {
2337 CSSM_CC_HANDLE macHand;
2338 CSSM_RETURN crtn;
2339 CSSM_RETURN ocrtn = CSSM_OK;
2340 unsigned thisMove; // this update
2341 unsigned toMove; // total to go
2342 CSSM_DATA thisText; // actaully passed to update
2343
2344 crtn = CSSM_CSP_CreateMacContext(cspHand,
2345 algorithm,
2346 key,
2347 &macHand);
2348 if(crtn) {
2349 printError("CSSM_CSP_CreateMacContext (4)", crtn);
2350 return crtn;
2351 }
2352 crtn = CSSM_VerifyMacInit(macHand);
2353 if(crtn) {
2354 printError("CSSM_VerifyMacInit", crtn);
2355 ocrtn = crtn;
2356 goto abort;
2357 }
2358 toMove = text->Length;
2359 thisText.Data = text->Data;
2360
2361 while(toMove) {
2362 if(multiUpdates) {
2363 thisMove = genRand(1, toMove);
2364 }
2365 else {
2366 thisMove = toMove;
2367 }
2368 thisText.Length = thisMove;
2369 crtn = CSSM_VerifyMacUpdate(macHand,
2370 &thisText,
2371 1);
2372 if(crtn) {
2373 printError("CSSM_VerifyMacUpdate", crtn);
2374 ocrtn = crtn;
2375 goto abort;
2376 }
2377 thisText.Data += thisMove;
2378 toMove -= thisMove;
2379 }
2380 crtn = CSSM_VerifyMacFinal(macHand, mac);
2381 if(crtn != expectResult) {
2382 if(crtn) {
2383 printError("CSSM_VerifyMacFinal", crtn);
2384 }
2385 else {
2386 printf("Unexpected good Staged Mac Verify\n");
2387 }
2388 ocrtn = CSSMERR_CSSM_INTERNAL_ERROR;
2389 }
2390 abort:
2391 crtn = CSSM_DeleteContext(macHand);
2392 if(crtn) {
2393 printError("CSSM_DeleteContext", crtn);
2394 ocrtn = crtn;
2395 }
2396 return ocrtn;
2397 }
2398
2399 #pragma mark --------- Digest ---------
2400
2401 /*
2402 * Digest functions
2403 */
2404 CSSM_RETURN cspDigest(CSSM_CSP_HANDLE cspHand,
2405 uint32 algorithm, // CSSM_ALGID_MD5, etc.
2406 CSSM_BOOL mallocDigest, // if true and digest->Length = 0, we'll malloc
2407 const CSSM_DATA *text,
2408 CSSM_DATA_PTR digest)
2409 {
2410 CSSM_CC_HANDLE digestHand;
2411 CSSM_RETURN crtn;
2412 CSSM_RETURN ocrtn = CSSM_OK;
2413
2414 crtn = CSSM_CSP_CreateDigestContext(cspHand,
2415 algorithm,
2416 &digestHand);
2417 if(crtn) {
2418 printError("CSSM_CSP_CreateDIgestContext (1)", crtn);
2419 return crtn;
2420 }
2421 if(mallocDigest && (digest->Length == 0)) {
2422 /* malloc digest - ask CSP for size */
2423 CSSM_QUERY_SIZE_DATA querySize = {0, 0};
2424 crtn = CSSM_QuerySize(digestHand,
2425 CSSM_FALSE, // encrypt
2426 1,
2427 &querySize);
2428 if(crtn) {
2429 printError("CSSM_QuerySize(3)", crtn);
2430 ocrtn = crtn;
2431 goto abort;
2432 }
2433 if(querySize.SizeOutputBlock == 0) {
2434 printf("Unknown digest size\n");
2435 ocrtn = CSSMERR_CSSM_INTERNAL_ERROR;
2436 goto abort;
2437 }
2438 digest->Data = (uint8 *)appMalloc(querySize.SizeOutputBlock, NULL);
2439 if(digest->Data == NULL) {
2440 printf("malloc failure\n");
2441 ocrtn = CSSMERR_CSSM_MEMORY_ERROR;
2442 goto abort;
2443 }
2444 digest->Length = querySize.SizeOutputBlock;
2445 }
2446 crtn = CSSM_DigestData(digestHand,
2447 text,
2448 1,
2449 digest);
2450 if(crtn) {
2451 printError("CSSM_DigestData", crtn);
2452 ocrtn = crtn;
2453 }
2454 abort:
2455 crtn = CSSM_DeleteContext(digestHand);
2456 if(crtn) {
2457 printError("CSSM_DeleteContext", crtn);
2458 ocrtn = crtn;
2459 }
2460 return ocrtn;
2461 }
2462
2463 CSSM_RETURN cspStagedDigest(CSSM_CSP_HANDLE cspHand,
2464 uint32 algorithm, // CSSM_ALGID_MD5, etc.
2465 CSSM_BOOL mallocDigest, // if true and digest->Length = 0, we'll
2466 // malloc
2467 CSSM_BOOL multiUpdates, // false:single update, true:multi updates
2468 const CSSM_DATA *text,
2469 CSSM_DATA_PTR digest)
2470 {
2471 CSSM_CC_HANDLE digestHand;
2472 CSSM_RETURN crtn;
2473 CSSM_RETURN ocrtn = CSSM_OK;
2474 unsigned thisMove; // this update
2475 unsigned toMove; // total to go
2476 CSSM_DATA thisText; // actually passed to update
2477
2478 crtn = CSSM_CSP_CreateDigestContext(cspHand,
2479 algorithm,
2480 &digestHand);
2481 if(crtn) {
2482 printError("CSSM_CSP_CreateDigestContext (2)", crtn);
2483 return crtn;
2484 }
2485 if(mallocDigest && (digest->Length == 0)) {
2486 /* malloc digest - ask CSP for size */
2487 CSSM_QUERY_SIZE_DATA querySize = {0, 0};
2488 crtn = CSSM_QuerySize(digestHand,
2489 CSSM_FALSE, // encrypt
2490 1,
2491 &querySize);
2492 if(crtn) {
2493 printError("CSSM_QuerySize(4)", crtn);
2494 ocrtn = crtn;
2495 goto abort;
2496 }
2497 if(querySize.SizeOutputBlock == 0) {
2498 printf("Unknown digest size\n");
2499 ocrtn = CSSMERR_CSSM_INTERNAL_ERROR;
2500 goto abort;
2501 }
2502 digest->Data = (uint8 *)appMalloc(querySize.SizeOutputBlock, NULL);
2503 if(digest->Data == NULL) {
2504 printf("malloc failure\n");
2505 ocrtn = CSSMERR_CSSM_MEMORY_ERROR;
2506 goto abort;
2507 }
2508 digest->Length = querySize.SizeOutputBlock;
2509 }
2510 crtn = CSSM_DigestDataInit(digestHand);
2511 if(crtn) {
2512 printError("CSSM_DigestDataInit", crtn);
2513 ocrtn = crtn;
2514 goto abort;
2515 }
2516 toMove = text->Length;
2517 thisText.Data = text->Data;
2518 while(toMove) {
2519 if(multiUpdates) {
2520 thisMove = genRand(1, toMove);
2521 }
2522 else {
2523 thisMove = toMove;
2524 }
2525 thisText.Length = thisMove;
2526 crtn = CSSM_DigestDataUpdate(digestHand,
2527 &thisText,
2528 1);
2529 if(crtn) {
2530 printError("CSSM_DigestDataUpdate", crtn);
2531 ocrtn = crtn;
2532 goto abort;
2533 }
2534 thisText.Data += thisMove;
2535 toMove -= thisMove;
2536 }
2537 crtn = CSSM_DigestDataFinal(digestHand, digest);
2538 if(crtn) {
2539 printError("CSSM_DigestDataFinal", crtn);
2540 ocrtn = crtn;
2541 goto abort;
2542 }
2543 abort:
2544 crtn = CSSM_DeleteContext(digestHand);
2545 if(crtn) {
2546 printError("CSSM_DeleteContext", crtn);
2547 ocrtn = crtn;
2548 }
2549 return ocrtn;
2550 }
2551
2552 #pragma mark --------- wrap/unwrap ---------
2553
2554 /* wrap key function. */
2555 CSSM_RETURN cspWrapKey(CSSM_CSP_HANDLE cspHand,
2556 const CSSM_KEY *unwrappedKey,
2557 const CSSM_KEY *wrappingKey,
2558 CSSM_ALGORITHMS wrapAlg,
2559 CSSM_ENCRYPT_MODE wrapMode,
2560 CSSM_KEYBLOB_FORMAT wrapFormat, // NONE, PKCS7, PKCS8
2561 CSSM_PADDING wrapPad,
2562 CSSM_DATA_PTR initVector, // for some wrapping algs
2563 CSSM_DATA_PTR descrData, // optional
2564 CSSM_KEY_PTR wrappedKey) // RETURNED
2565 {
2566 CSSM_CC_HANDLE ccHand;
2567 CSSM_RETURN crtn;
2568 CSSM_ACCESS_CREDENTIALS creds;
2569
2570 memset(wrappedKey, 0, sizeof(CSSM_KEY));
2571 setBadKeyData(wrappedKey);
2572 memset(&creds, 0, sizeof(CSSM_ACCESS_CREDENTIALS));
2573 /* special case for NULL wrap - no wrapping key */
2574 if((wrappingKey == NULL) ||
2575 (wrappingKey->KeyHeader.KeyClass == CSSM_KEYCLASS_SESSION_KEY)) {
2576 crtn = CSSM_CSP_CreateSymmetricContext(cspHand,
2577 wrapAlg,
2578 wrapMode,
2579 &creds, // passPhrase,
2580 wrappingKey,
2581 initVector,
2582 wrapPad, // Padding
2583 0, // Params
2584 &ccHand);
2585 }
2586 else {
2587 crtn = CSSM_CSP_CreateAsymmetricContext(cspHand,
2588 wrapAlg,
2589 &creds,
2590 wrappingKey,
2591 wrapPad, // padding
2592 &ccHand);
2593 if(crtn) {
2594 printError("cspWrapKey/CreateContext", crtn);
2595 return crtn;
2596 }
2597 if(initVector) {
2598 /* manually add IV for CMS. The actual low-level encrypt doesn't
2599 * use it (and must ignore it). */
2600 crtn = AddContextAttribute(ccHand,
2601 CSSM_ATTRIBUTE_INIT_VECTOR,
2602 sizeof(CSSM_DATA),
2603 CAT_Ptr,
2604 initVector,
2605 0);
2606 if(crtn) {
2607 printError("CSSM_UpdateContextAttributes", crtn);
2608 return crtn;
2609 }
2610 }
2611 }
2612 if(crtn) {
2613 printError("cspWrapKey/CreateContext", crtn);
2614 return crtn;
2615 }
2616 if(wrapFormat != CSSM_KEYBLOB_WRAPPED_FORMAT_NONE) {
2617 /* only add this attribute if it's not the default */
2618 CSSM_CONTEXT_ATTRIBUTE attr;
2619 attr.AttributeType = CSSM_ATTRIBUTE_WRAPPED_KEY_FORMAT;
2620 attr.AttributeLength = sizeof(uint32);
2621 attr.Attribute.Uint32 = wrapFormat;
2622 crtn = CSSM_UpdateContextAttributes(
2623 ccHand,
2624 1,
2625 &attr);
2626 if(crtn) {
2627 printError("CSSM_UpdateContextAttributes", crtn);
2628 return crtn;
2629 }
2630 }
2631 crtn = CSSM_WrapKey(ccHand,
2632 &creds,
2633 unwrappedKey,
2634 descrData, // DescriptiveData
2635 wrappedKey);
2636 if(crtn != CSSM_OK) {
2637 printError("CSSM_WrapKey", crtn);
2638 }
2639 if(CSSM_DeleteContext(ccHand)) {
2640 printf("CSSM_DeleteContext failure\n");
2641 }
2642 return crtn;
2643 }
2644
2645 /* unwrap key function. */
2646 CSSM_RETURN cspUnwrapKey(CSSM_CSP_HANDLE cspHand,
2647 const CSSM_KEY *wrappedKey,
2648 const CSSM_KEY *unwrappingKey,
2649 CSSM_ALGORITHMS unwrapAlg,
2650 CSSM_ENCRYPT_MODE unwrapMode,
2651 CSSM_PADDING unwrapPad,
2652 CSSM_DATA_PTR initVector, // for some wrapping algs
2653 CSSM_KEY_PTR unwrappedKey, // RETURNED
2654 CSSM_DATA_PTR descrData, // required
2655 const char *keyLabel,
2656 unsigned keyLabelLen)
2657 {
2658 CSSM_CC_HANDLE ccHand;
2659 CSSM_RETURN crtn;
2660 CSSM_DATA labelData;
2661 uint32 keyAttr;
2662 CSSM_ACCESS_CREDENTIALS creds;
2663
2664 memset(unwrappedKey, 0, sizeof(CSSM_KEY));
2665 setBadKeyData(unwrappedKey);
2666 memset(&creds, 0, sizeof(CSSM_ACCESS_CREDENTIALS));
2667 if((unwrappingKey == NULL) ||
2668 (unwrappingKey->KeyHeader.KeyClass == CSSM_KEYCLASS_SESSION_KEY)) {
2669 crtn = CSSM_CSP_CreateSymmetricContext(cspHand,
2670 unwrapAlg,
2671 unwrapMode,
2672 &creds,
2673 unwrappingKey,
2674 initVector,
2675 unwrapPad,
2676 0, // Params
2677 &ccHand);
2678 }
2679 else {
2680 crtn = CSSM_CSP_CreateAsymmetricContext(cspHand,
2681 unwrapAlg,
2682 &creds, // passPhrase,
2683 unwrappingKey,
2684 unwrapPad, // Padding
2685 &ccHand);
2686 if(crtn) {
2687 printError("cspUnwrapKey/CreateContext", crtn);
2688 return crtn;
2689 }
2690 if(initVector) {
2691 /* manually add IV for CMS. The actual low-level encrypt doesn't
2692 * use it (and must ignore it). */
2693 crtn = AddContextAttribute(ccHand,
2694 CSSM_ATTRIBUTE_INIT_VECTOR,
2695 sizeof(CSSM_DATA),
2696 CAT_Ptr,
2697 initVector,
2698 0);
2699 if(crtn) {
2700 printError("CSSM_UpdateContextAttributes", crtn);
2701 return crtn;
2702 }
2703 }
2704 }
2705 if(crtn) {
2706 printError("cspUnwrapKey/CreateContext", crtn);
2707 return crtn;
2708 }
2709 labelData.Data = (uint8 *)keyLabel;
2710 labelData.Length = keyLabelLen;
2711
2712 /*
2713 * New keyAttr - clear some old bits, make sure we ask for ref key
2714 */
2715 keyAttr = wrappedKey->KeyHeader.KeyAttr;
2716 keyAttr &= ~(CSSM_KEYATTR_ALWAYS_SENSITIVE | CSSM_KEYATTR_NEVER_EXTRACTABLE);
2717 keyAttr |= CSSM_KEYATTR_RETURN_REF;
2718 crtn = CSSM_UnwrapKey(ccHand,
2719 NULL, // PublicKey
2720 wrappedKey,
2721 wrappedKey->KeyHeader.KeyUsage,
2722 keyAttr,
2723 &labelData,
2724 NULL, // CredAndAclEntry
2725 unwrappedKey,
2726 descrData); // required
2727 if(crtn != CSSM_OK) {
2728 printError("CSSM_UnwrapKey", crtn);
2729 }
2730 if(CSSM_DeleteContext(ccHand)) {
2731 printf("CSSM_DeleteContext failure\n");
2732 }
2733 return crtn;
2734 }
2735
2736 /*
2737 * Simple NULL wrap to convert a reference key to a raw key.
2738 */
2739 CSSM_RETURN cspRefKeyToRaw(
2740 CSSM_CSP_HANDLE cspHand,
2741 const CSSM_KEY *refKey,
2742 CSSM_KEY_PTR rawKey) // init'd and RETURNED
2743 {
2744 CSSM_DATA descData = {0, 0};
2745
2746 memset(rawKey, 0, sizeof(CSSM_KEY));
2747 return cspWrapKey(cspHand,
2748 refKey,
2749 NULL, // unwrappingKey
2750 CSSM_ALGID_NONE,
2751 CSSM_ALGMODE_NONE,
2752 CSSM_KEYBLOB_WRAPPED_FORMAT_NONE,
2753 CSSM_PADDING_NONE,
2754 NULL, // IV
2755 &descData,
2756 rawKey);
2757 }
2758
2759 /*
2760 * Convert ref key to raw key with specified format.
2761 */
2762 CSSM_RETURN cspRefKeyToRawWithFormat(
2763 CSSM_CSP_HANDLE cspHand,
2764 const CSSM_KEY *refKey,
2765 CSSM_KEYBLOB_FORMAT format,
2766 CSSM_KEY_PTR rawKey) // init'd and RETURNED
2767 {
2768 memset(rawKey, 0, sizeof(CSSM_KEY));
2769 CSSM_ATTRIBUTE_TYPE attrType;
2770
2771 switch(refKey->KeyHeader.KeyClass) {
2772 case CSSM_KEYCLASS_PUBLIC_KEY:
2773 attrType = CSSM_ATTRIBUTE_PUBLIC_KEY_FORMAT;
2774 break;
2775 case CSSM_KEYCLASS_PRIVATE_KEY:
2776 attrType = CSSM_ATTRIBUTE_PRIVATE_KEY_FORMAT;
2777 break;
2778 case CSSM_KEYCLASS_SESSION_KEY:
2779 attrType = CSSM_ATTRIBUTE_SYMMETRIC_KEY_FORMAT;
2780 break;
2781 default:
2782 printf("***Unknown key class\n");
2783 return CSSMERR_CSP_INVALID_KEY;
2784 }
2785
2786 CSSM_DATA descData = {0, 0};
2787 CSSM_CC_HANDLE ccHand;
2788 CSSM_RETURN crtn;
2789 // uint32 keyAttr;
2790 CSSM_ACCESS_CREDENTIALS creds;
2791
2792 memset(rawKey, 0, sizeof(CSSM_KEY));
2793 memset(&creds, 0, sizeof(CSSM_ACCESS_CREDENTIALS));
2794 crtn = CSSM_CSP_CreateSymmetricContext(cspHand,
2795 CSSM_ALGID_NONE,
2796 CSSM_ALGMODE_NONE,
2797 &creds,
2798 NULL, // unwrappingKey
2799 NULL, // initVector
2800 CSSM_PADDING_NONE,
2801 NULL, // Reserved
2802 &ccHand);
2803 if(crtn) {
2804 printError("cspRefKeyToRawWithFormat/CreateContext", crtn);
2805 return crtn;
2806 }
2807
2808 /* Add the spec for the resulting format */
2809 crtn = AddContextAttribute(ccHand,
2810 attrType,
2811 sizeof(uint32),
2812 CAT_Uint32,
2813 NULL,
2814 format);
2815
2816 crtn = CSSM_WrapKey(ccHand,
2817 &creds,
2818 refKey,
2819 &descData, // DescriptiveData
2820 rawKey);
2821 if(crtn != CSSM_OK) {
2822 printError("CSSM_WrapKey", crtn);
2823 }
2824 if(rawKey->KeyHeader.Format != format) {
2825 printf("***cspRefKeyToRawWithFormat format scewup\n");
2826 crtn = CSSMERR_CSP_INTERNAL_ERROR;
2827 }
2828 if(CSSM_DeleteContext(ccHand)) {
2829 printf("CSSM_DeleteContext failure\n");
2830 }
2831 return crtn;
2832 }
2833
2834 /* unwrap raw key --> ref */
2835 CSSM_RETURN cspRawKeyToRef(
2836 CSSM_CSP_HANDLE cspHand,
2837 const CSSM_KEY *rawKey,
2838 CSSM_KEY_PTR refKey) // init'd and RETURNED
2839 {
2840 CSSM_DATA descData = {0, 0};
2841
2842 memset(refKey, 0, sizeof(CSSM_KEY));
2843 return cspUnwrapKey(cspHand,
2844 rawKey,
2845 NULL, // unwrappingKey
2846 CSSM_ALGID_NONE,
2847 CSSM_ALGMODE_NONE,
2848 CSSM_PADDING_NONE,
2849 NULL, // init vector
2850 refKey,
2851 &descData,
2852 "noLabel",
2853 7);
2854 }
2855
2856
2857 #pragma mark --------- FEE key/curve support ---------
2858
2859 /*
2860 * Generate random key size, primeType, curveType for FEE key for specified op.
2861 *
2862 * First just enumerate the curves we know about, with ECDSA-INcapable first
2863 */
2864
2865 typedef struct {
2866 uint32 keySizeInBits;
2867 uint32 primeType; // CSSM_FEE_PRIME_TYPE_xxx
2868 uint32 curveType; // CSSM_FEE_CURVE_TYPE_xxx
2869 } feeCurveParams;
2870
2871 #define FEE_PROTOTYPE_CURVES 0
2872 #if FEE_PROTOTYPE_CURVES
2873 /* obsolete as of 4/9/2001 */
2874 static feeCurveParams feeCurves[] = {
2875 { 31, CSSM_FEE_PRIME_TYPE_MERSENNE, CSSM_FEE_CURVE_TYPE_MONTGOMERY },
2876 { 127, CSSM_FEE_PRIME_TYPE_MERSENNE, CSSM_FEE_CURVE_TYPE_MONTGOMERY },
2877 { 127, CSSM_FEE_PRIME_TYPE_GENERAL, CSSM_FEE_CURVE_TYPE_MONTGOMERY },
2878 #define NUM_NON_ECDSA_CURVES 3
2879
2880 /* start of Weierstrass, IEEE P1363-capable curves */
2881 { 31, CSSM_FEE_PRIME_TYPE_MERSENNE, CSSM_FEE_CURVE_TYPE_WEIERSTRASS },
2882 { 40, CSSM_FEE_PRIME_TYPE_FEE, CSSM_FEE_CURVE_TYPE_WEIERSTRASS },
2883 { 127, CSSM_FEE_PRIME_TYPE_MERSENNE, CSSM_FEE_CURVE_TYPE_WEIERSTRASS },
2884 { 160, CSSM_FEE_PRIME_TYPE_FEE, CSSM_FEE_CURVE_TYPE_WEIERSTRASS },
2885 { 160, CSSM_FEE_PRIME_TYPE_GENERAL, CSSM_FEE_CURVE_TYPE_WEIERSTRASS },
2886 { 192, CSSM_FEE_PRIME_TYPE_FEE, CSSM_FEE_CURVE_TYPE_WEIERSTRASS },
2887 };
2888 #else /* FEE_PROTOTYPE_CURVES */
2889 static feeCurveParams feeCurves[] = {
2890 { 31, CSSM_FEE_PRIME_TYPE_MERSENNE, CSSM_FEE_CURVE_TYPE_MONTGOMERY },
2891 { 127, CSSM_FEE_PRIME_TYPE_MERSENNE, CSSM_FEE_CURVE_TYPE_MONTGOMERY },
2892 #define NUM_NON_ECDSA_CURVES 2
2893
2894 /* start of Weierstrass, IEEE P1363-capable curves */
2895 { 31, CSSM_FEE_PRIME_TYPE_MERSENNE, CSSM_FEE_CURVE_TYPE_WEIERSTRASS },
2896 { 128, CSSM_FEE_PRIME_TYPE_FEE, CSSM_FEE_CURVE_TYPE_WEIERSTRASS },
2897 { 161, CSSM_FEE_PRIME_TYPE_FEE, CSSM_FEE_CURVE_TYPE_WEIERSTRASS },
2898 { 161, CSSM_FEE_PRIME_TYPE_GENERAL, CSSM_FEE_CURVE_TYPE_WEIERSTRASS },
2899 { 192, CSSM_FEE_PRIME_TYPE_GENERAL, CSSM_FEE_CURVE_TYPE_WEIERSTRASS },
2900 };
2901 #endif /* FEE_PROTOTYPE_CURVES */
2902 #define NUM_FEE_CURVES (sizeof(feeCurves) / sizeof(feeCurveParams))
2903
2904 void randFeeKeyParams(
2905 CSSM_ALGORITHMS alg, // ALGID_FEED, CSSM_ALGID_FEE_MD5, etc.
2906 uint32 *keySizeInBits, // RETURNED
2907 uint32 *primeType, // CSSM_FEE_PRIME_TYPE_xxx, RETURNED
2908 uint32 *curveType) // CSSM_FEE_CURVE_TYPE_xxx, RETURNED
2909 {
2910 unsigned minParams;
2911 unsigned die;
2912 feeCurveParams *feeParams;
2913
2914 switch(alg) {
2915 case CSSM_ALGID_SHA1WithECDSA:
2916 minParams = NUM_NON_ECDSA_CURVES;
2917 break;
2918 default:
2919 minParams = 0;
2920 break;
2921 }
2922 die = genRand(minParams, (NUM_FEE_CURVES - 1));
2923 feeParams = &feeCurves[die];
2924 *keySizeInBits = feeParams->keySizeInBits;
2925 *primeType = feeParams->primeType;
2926 *curveType = feeParams->curveType;
2927 }
2928
2929 /*
2930 * Obtain strings for primeType and curveType.
2931 */
2932 const char *primeTypeStr(uint32 primeType)
2933 {
2934 const char *p;
2935 switch(primeType) {
2936 case CSSM_FEE_PRIME_TYPE_MERSENNE:
2937 p = "Mersenne";
2938 break;
2939 case CSSM_FEE_PRIME_TYPE_FEE:
2940 p = "FEE";
2941 break;
2942 case CSSM_FEE_PRIME_TYPE_GENERAL:
2943 p = "General";
2944 break;
2945 case CSSM_FEE_PRIME_TYPE_DEFAULT:
2946 p = "Default";
2947 break;
2948 default:
2949 p = "***UNKNOWN***";
2950 break;
2951 }
2952 return p;
2953 }
2954
2955 const char *curveTypeStr(uint32 curveType)
2956 {
2957 const char *c;
2958 switch(curveType) {
2959 case CSSM_FEE_CURVE_TYPE_DEFAULT:
2960 c = "Default";
2961 break;
2962 case CSSM_FEE_CURVE_TYPE_MONTGOMERY:
2963 c = "Montgomery";
2964 break;
2965 case CSSM_FEE_CURVE_TYPE_WEIERSTRASS:
2966 c = "Weierstrass";
2967 break;
2968 default:
2969 c = "***UNKNOWN***";
2970 break;
2971 }
2972 return c;
2973 }
2974
2975 /*
2976 * Perform FEE Key exchange via CSSM_DeriveKey.
2977 */
2978 #if 0
2979 /* Not implemented in OS X */
2980 CSSM_RETURN cspFeeKeyExchange(CSSM_CSP_HANDLE cspHand,
2981 CSSM_KEY_PTR privKey,
2982 CSSM_KEY_PTR pubKey,
2983 CSSM_KEY_PTR derivedKey, // mallocd by caller
2984
2985 /* remaining fields apply to derivedKey */
2986 uint32 keyAlg,
2987 const char *keyLabel,
2988 unsigned keyLabelLen,
2989 uint32 keyUsage, // CSSM_KEYUSE_ENCRYPT, etc.
2990 uint32 keySizeInBits)
2991 {
2992 CSSM_CC_HANDLE dkHand;
2993 CSSM_RETURN crtn;
2994 CSSM_DATA labelData;
2995
2996 if(derivedKey == NULL) {
2997 printf("cspFeeKeyExchange: no derivedKey\n");
2998 return CSSMERR_CSSM_INTERNAL_ERROR;
2999 }
3000 if((pubKey == NULL) ||
3001 (pubKey->KeyHeader.KeyClass != CSSM_KEYCLASS_PUBLIC_KEY) ||
3002 (pubKey->KeyHeader.BlobType != CSSM_KEYBLOB_RAW)) {
3003 printf("cspFeeKeyExchange: bad pubKey\n");
3004 return CSSMERR_CSSM_INTERNAL_ERROR;
3005 }
3006 if((privKey == NULL) ||
3007 (privKey->KeyHeader.KeyClass != CSSM_KEYCLASS_PRIVATE_KEY) ||
3008 (privKey->KeyHeader.BlobType != CSSM_KEYBLOB_REFERENCE)) {
3009 printf("cspFeeKeyExchange: bad privKey\n");
3010 return CSSMERR_CSSM_INTERNAL_ERROR;
3011 }
3012 memset(derivedKey, 0, sizeof(CSSM_KEY));
3013
3014 crtn = CSSM_CSP_CreateDeriveKeyContext(cspHand,
3015 CSSM_ALGID_FEE_KEYEXCH, // AlgorithmID
3016 keyAlg, // alg of the derived key
3017 keySizeInBits,
3018 NULL, // access creds
3019 // FIXME
3020 0, // IterationCount
3021 NULL, // Salt
3022 NULL, // Seed
3023 NULL); // PassPhrase
3024 if(dkHand == 0) {
3025 printError("CSSM_CSP_CreateDeriveKeyContext");
3026 return CSSM_FAIL;
3027 }
3028 labelData.Length = keyLabelLen;
3029 labelData.Data = (uint8 *)keyLabel;
3030 crtn = CSSM_DeriveKey(dkHand,
3031 privKey,
3032 &pubKey->KeyData, // Param - pub key blob
3033 keyUsage,
3034 CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_EXTRACTABLE |
3035 CSSM_KEYATTR_SENSITIVE,
3036 &labelData,
3037 derivedKey);
3038
3039 /* FIXME - save/restore error */
3040 CSSM_DeleteContext(dkHand);
3041 if(crtn) {
3042 printError("CSSM_DeriveKey");
3043 }
3044 return crtn;
3045 }
3046 #endif
3047
3048 #pragma mark --------- Key/DL/DB support ---------
3049
3050 /*
3051 * Add a DL/DB handle to a crypto context.
3052 */
3053 CSSM_RETURN cspAddDlDbToContext(
3054 CSSM_CC_HANDLE ccHand,
3055 CSSM_DL_HANDLE dlHand,
3056 CSSM_DB_HANDLE dbHand)
3057 {
3058 CSSM_DL_DB_HANDLE dlDb = { dlHand, dbHand };
3059 return AddContextAttribute(ccHand,
3060 CSSM_ATTRIBUTE_DL_DB_HANDLE,
3061 sizeof(CSSM_ATTRIBUTE_DL_DB_HANDLE),
3062 CAT_Ptr,
3063 &dlDb,
3064 0);
3065 }
3066
3067 /*
3068 * Common routine to do a basic DB lookup by label and key type.
3069 * Query is aborted prior to exit.
3070 */
3071 static CSSM_DB_UNIQUE_RECORD_PTR dlLookup(
3072 CSSM_DL_DB_HANDLE dlDbHand,
3073 const CSSM_DATA *keyLabel,
3074 CT_KeyType keyType,
3075 CSSM_HANDLE *resultHand, // RETURNED
3076 CSSM_DATA_PTR theData, // RETURED
3077 CSSM_DB_RECORDTYPE *recordType) // RETURNED
3078 {
3079 CSSM_QUERY query;
3080 CSSM_SELECTION_PREDICATE predicate;
3081 CSSM_DB_UNIQUE_RECORD_PTR record = NULL;
3082 CSSM_RETURN crtn;
3083
3084 switch(keyType) {
3085 case CKT_Public:
3086 query.RecordType = *recordType = CSSM_DL_DB_RECORD_PUBLIC_KEY;
3087 break;
3088 case CKT_Private:
3089 query.RecordType = *recordType = CSSM_DL_DB_RECORD_PRIVATE_KEY;
3090 break;
3091 case CKT_Session:
3092 query.RecordType = *recordType = CSSM_DL_DB_RECORD_SYMMETRIC_KEY;
3093 break;
3094 default:
3095 printf("Hey bozo! Give me a valid key type!\n");
3096 return NULL;
3097 }
3098 query.Conjunctive = CSSM_DB_NONE;
3099 query.NumSelectionPredicates = 1;
3100 predicate.DbOperator = CSSM_DB_EQUAL;
3101
3102 predicate.Attribute.Info.AttributeNameFormat =
3103 CSSM_DB_ATTRIBUTE_NAME_AS_STRING;
3104 predicate.Attribute.Info.Label.AttributeName = (char *) "Label";
3105 predicate.Attribute.Info.AttributeFormat = CSSM_DB_ATTRIBUTE_FORMAT_BLOB;
3106 /* hope this cast is OK */
3107 predicate.Attribute.Value = (CSSM_DATA_PTR)keyLabel;
3108 query.SelectionPredicate = &predicate;
3109
3110 query.QueryLimits.TimeLimit = 0; // FIXME - meaningful?
3111 query.QueryLimits.SizeLimit = 1; // FIXME - meaningful?
3112 query.QueryFlags = CSSM_QUERY_RETURN_DATA; // FIXME - used?
3113
3114 crtn = CSSM_DL_DataGetFirst(dlDbHand,
3115 &query,
3116 resultHand,
3117 NULL,
3118 theData,
3119 &record);
3120 /* abort only on success */
3121 if(crtn == CSSM_OK) {
3122 crtn = CSSM_DL_DataAbortQuery(dlDbHand, *resultHand);
3123 if(crtn) {
3124 printError("CSSM_DL_AbortQuery", crtn);
3125 return NULL;
3126 }
3127 }
3128 return record;
3129 }
3130
3131 /*
3132 * Look up a key by label and type.
3133 */
3134 CSSM_KEY_PTR cspLookUpKeyByLabel(
3135 CSSM_DL_HANDLE dlHand,
3136 CSSM_DB_HANDLE dbHand,
3137 const CSSM_DATA *labelData,
3138 CT_KeyType keyType)
3139 {
3140 CSSM_DB_UNIQUE_RECORD_PTR record;
3141 CSSM_HANDLE resultHand;
3142 CSSM_DATA theData;
3143 CSSM_KEY_PTR key;
3144 CSSM_DB_RECORDTYPE recordType;
3145 CSSM_DL_DB_HANDLE dlDbHand;
3146
3147 dlDbHand.DLHandle = dlHand;
3148 dlDbHand.DBHandle = dbHand;
3149
3150 theData.Length = 0;
3151 theData.Data = NULL;
3152
3153 record = dlLookup(dlDbHand,
3154 labelData,
3155 keyType,
3156 &resultHand,
3157 &theData,
3158 &recordType);
3159 if(record == NULL) {
3160 //printf("cspLookUpKeyByLabel: key not found\n");
3161 return NULL;
3162 }
3163 key = (CSSM_KEY_PTR)theData.Data;
3164 CSSM_DL_FreeUniqueRecord(dlDbHand, record);
3165 return key;
3166 }
3167
3168 /*
3169 * Delete and free a key
3170 */
3171 CSSM_RETURN cspDeleteKey(
3172 CSSM_CSP_HANDLE cspHand, // for free
3173 CSSM_DL_HANDLE dlHand, // for delete
3174 CSSM_DB_HANDLE dbHand, // ditto
3175 const CSSM_DATA *labelData,
3176 CSSM_KEY_PTR key)
3177 {
3178 CSSM_DB_UNIQUE_RECORD_PTR record;
3179 CSSM_HANDLE resultHand;
3180 CT_KeyType keyType;
3181 CSSM_RETURN crtn = CSSM_OK;
3182 CSSM_DB_RECORDTYPE recordType;
3183 CSSM_DL_DB_HANDLE dlDbHand;
3184
3185 if(key->KeyHeader.KeyAttr & CSSM_KEYATTR_PERMANENT) {
3186 /* first do a lookup based in this key's fields */
3187 switch(key->KeyHeader.KeyClass) {
3188 case CSSM_KEYCLASS_PUBLIC_KEY:
3189 keyType = CKT_Public;
3190 break;
3191 case CSSM_KEYCLASS_PRIVATE_KEY:
3192 keyType = CKT_Private;
3193 break;
3194 case CSSM_KEYCLASS_SESSION_KEY:
3195 keyType = CKT_Session;
3196 break;
3197 default:
3198 printf("Hey bozo! Give me a valid key type!\n");
3199 return -1;
3200 }
3201
3202 dlDbHand.DLHandle = dlHand;
3203 dlDbHand.DBHandle = dbHand;
3204
3205 record = dlLookup(dlDbHand,
3206 labelData,
3207 keyType,
3208 &resultHand,
3209 NULL, // don't want actual data
3210 &recordType);
3211 if(record == NULL) {
3212 printf("cspDeleteKey: key not found in DL\n");
3213 return CSSMERR_DL_RECORD_NOT_FOUND;
3214 }
3215
3216 /* OK, nuke it */
3217 crtn = CSSM_DL_DataDelete(dlDbHand, record);
3218 if(crtn) {
3219 printError("CSSM_DL_DataDelete", crtn);
3220 }
3221 CSSM_DL_FreeUniqueRecord(dlDbHand, record);
3222 }
3223
3224 /* CSSM_FreeKey() should fail due to the delete, but it will
3225 * still free KeyData....
3226 * FIXME - we should be able to do this in this one single call - right?
3227 */
3228 CSSM_FreeKey(cspHand, NULL, key, CSSM_FALSE);
3229
3230 return crtn;
3231 }
3232
3233 /*
3234 * Given any key in either blob or reference format,
3235 * obtain the associated SHA-1 hash.
3236 */
3237 CSSM_RETURN cspKeyHash(
3238 CSSM_CSP_HANDLE cspHand,
3239 const CSSM_KEY_PTR key, /* public key */
3240 CSSM_DATA_PTR *hashData) /* hash mallocd and RETURNED here */
3241 {
3242 CSSM_CC_HANDLE ccHand;
3243 CSSM_RETURN crtn;
3244 CSSM_DATA_PTR dp;
3245
3246 *hashData = NULL;
3247
3248 /* validate input params */
3249 if((key == NULL) ||
3250 (hashData == NULL)) {
3251 printf("cspKeyHash: bogus args\n");
3252 return CSSMERR_CSSM_INTERNAL_ERROR;
3253 }
3254
3255 /* cook up a context for a passthrough op */
3256 crtn = CSSM_CSP_CreatePassThroughContext(cspHand,
3257 key,
3258 &ccHand);
3259 if(ccHand == 0) {
3260 printError("CSSM_CSP_CreatePassThroughContext", crtn);
3261 return crtn;
3262 }
3263
3264 /* now it's up to the CSP */
3265 crtn = CSSM_CSP_PassThrough(ccHand,
3266 CSSM_APPLECSP_KEYDIGEST,
3267 NULL,
3268 (void **)&dp);
3269 if(crtn) {
3270 printError("CSSM_CSP_PassThrough(PUBKEYHASH)", crtn);
3271 }
3272 else {
3273 *hashData = dp;
3274 crtn = CSSM_OK;
3275 }
3276 CSSM_DeleteContext(ccHand);
3277 return crtn;
3278 }
3279