1 /* Copyright (c) 1997,2003-2006,2008,2010,2013 Apple Inc.
3 * cspwrap.c - wrappers to simplify access to CDSA
7 * 3 May 2000 Doug Mitchell
9 * 12 Aug 1997 Doug Mitchell at Apple
13 #include <Security/cssmapple.h>
14 #include <Security/cssm.h>
21 // #include <CarbonCore/MacTypes.h>
26 #define NULL ((void *)0)
29 #define MAX(a,b) ((a > b) ? a : b)
30 #define MIN(a,b) ((a < b) ? a : b)
33 #pragma mark --------- Key Generation ---------
38 #define FEE_PRIV_DATA_SIZE 20
40 * Debug/test only. BsafeCSP only (long since disabled, in Puma).
41 * This results in quicker but less secure RSA key generation.
43 #define RSA_WEAK_KEYS 0
46 * Force bad data in KeyData prior to generating, deriving, or
47 * wrapping key to ensure that the CSP ignores incoming
50 static void setBadKeyData(
53 key
->KeyData
.Data
= (uint8
*)0xeaaaeaaa; // bad ptr
54 key
->KeyData
.Length
= 1; // no key can fit here
58 * Generate key pair of arbitrary algorithm.
59 * FEE keys will have random private data.
61 CSSM_RETURN
cspGenKeyPair(CSSM_CSP_HANDLE cspHand
,
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
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
;
87 CSSM_RETURN ocrtn
= CSSM_OK
;
89 if(keySize
== CSP_KEY_SIZE_DEFAULT
) {
90 keySize
= cspDefaultKeySize(algorithm
);
93 /* pre-context-create algorithm-specific stuff */
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
;
105 /* else CSP generates random seed/key */
111 case CSSM_ALGID_ECDSA
:
114 printf("cspGenKeyPair: Unknown algorithm\n");
115 /* but what the hey */
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
);
126 crtn
= CSSM_CSP_CreateKeyGenContext(cspHand
,
129 privCDataPtr
, // Seed
136 printError("CSSM_CSP_CreateKeyGenContext", crtn
);
140 /* cook up attribute bits */
142 pubAttr
= CSSM_KEYATTR_RETURN_REF
| CSSM_KEYATTR_EXTRACTABLE
;
145 pubAttr
= CSSM_KEYATTR_RETURN_DATA
| CSSM_KEYATTR_EXTRACTABLE
;
148 privAttr
= CSSM_KEYATTR_RETURN_REF
| CSSM_KEYATTR_EXTRACTABLE
;
151 privAttr
= CSSM_KEYATTR_RETURN_DATA
| CSSM_KEYATTR_EXTRACTABLE
;
154 /* post-context-create algorithm-specific stuff */
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.
165 crtn
= AddContextAttribute(ccHand
,
170 CSSM_ALGMODE_CUSTOM
);
172 printError("CSSM_UpdateContextAttributes", crtn
);
176 #endif // RSA_WEAK_KEYS
181 * extra step - generate params - this just adds some
182 * info to the context
185 CSSM_DATA dummy
= {0, NULL
};
186 crtn
= CSSM_GenerateAlgorithmParams(ccHand
,
189 printError("CSSM_GenerateAlgorithmParams", crtn
);
192 appFreeCssmData(&dummy
, CSSM_FALSE
);
199 /* optional format specifiers */
200 if(!pubIsRef
&& (pubFormat
!= CSSM_KEYBLOB_RAW_FORMAT_NONE
)) {
201 crtn
= AddContextAttribute(ccHand
,
202 CSSM_ATTRIBUTE_PUBLIC_KEY_FORMAT
,
208 printError("AddContextAttribute(CSSM_ATTRIBUTE_PUBLIC_KEY_FORMAT)", crtn
);
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
220 printError("AddContextAttribute(CSSM_ATTRIBUTE_PRIVATE_KEY_FORMAT)", crtn
);
224 crtn
= CSSM_GenerateKeyPair(ccHand
,
231 &keyLabelData
, // same labels
232 NULL
, // CredAndAclEntry
235 printError("CSSM_GenerateKeyPair", crtn
);
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
;
249 switch(privKey
->KeyHeader
.BlobType
) {
250 case CSSM_KEYBLOB_RAW
:
253 printf("privKey blob type: exp raw, got %u\n",
254 (unsigned)privKey
->KeyHeader
.BlobType
);
255 ocrtn
= CSSM_ERRCODE_INTERNAL_ERROR
;
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
;
268 switch(pubKey
->KeyHeader
.BlobType
) {
269 case CSSM_KEYBLOB_RAW
:
272 printf("pubKey blob type: exp raw or raw_berder, got %u\n",
273 (unsigned)pubKey
->KeyHeader
.BlobType
);
274 ocrtn
= CSSM_ERRCODE_INTERNAL_ERROR
;
280 crtn
= CSSM_DeleteContext(ccHand
);
282 printError("CSSM_DeleteContext", crtn
);
283 ocrtn
= CSSM_ERRCODE_INTERNAL_ERROR
;
286 if(privData
.Data
!= NULL
) {
287 CSSM_FREE(privData
.Data
);
293 * Generate FEE key pair with optional primeType, curveType, and seed (password) data.
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.
314 CSSM_CC_HANDLE ccHand
;
315 CSSM_CRYPTO_DATA privCData
;
316 CSSM_CRYPTO_DATA_PTR privCDataPtr
= NULL
;
317 CSSM_DATA keyLabelData
;
320 CSSM_RETURN ocrtn
= CSSM_OK
;
322 /* pre-context-create algorithm-specific stuff */
324 privCData
.Param
= *((CSSM_DATA_PTR
)seedData
);
325 privCData
.Callback
= NULL
;
326 privCDataPtr
= &privCData
;
328 /* else CSP generates random seed/key */
330 if(keySize
== CSP_KEY_SIZE_DEFAULT
) {
331 keySize
= CSP_FEE_KEY_SIZE_DEFAULT
;
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
);
341 crtn
= CSSM_CSP_CreateKeyGenContext(cspHand
,
344 privCDataPtr
, // Seed
351 printError("CSSM_CSP_CreateKeyGenContext", crtn
);
355 /* cook up attribute bits */
357 pubAttr
= CSSM_KEYATTR_RETURN_REF
| CSSM_KEYATTR_EXTRACTABLE
;
360 pubAttr
= CSSM_KEYATTR_RETURN_DATA
| CSSM_KEYATTR_EXTRACTABLE
;
363 privAttr
= CSSM_KEYATTR_RETURN_REF
| CSSM_KEYATTR_EXTRACTABLE
;
366 privAttr
= CSSM_KEYATTR_RETURN_DATA
| CSSM_KEYATTR_EXTRACTABLE
;
369 /* optional post-context-create stuff */
370 if(primeType
!= CSSM_FEE_PRIME_TYPE_DEFAULT
) {
371 crtn
= AddContextAttribute(ccHand
,
372 CSSM_ATTRIBUTE_FEE_PRIME_TYPE
,
378 printError("AddContextAttribute(CSSM_ATTRIBUTE_FEE_PRIME_TYPE)", crtn
);
382 if(curveType
!= CSSM_FEE_CURVE_TYPE_DEFAULT
) {
383 crtn
= AddContextAttribute(ccHand
,
384 CSSM_ATTRIBUTE_FEE_CURVE_TYPE
,
390 printError("AddContextAttribute(CSSM_ATTRIBUTE_FEE_CURVE_TYPE)", crtn
);
395 if(pubFormat
!= CSSM_KEYBLOB_RAW_FORMAT_NONE
) {
396 crtn
= AddContextAttribute(ccHand
,
397 CSSM_ATTRIBUTE_PUBLIC_KEY_FORMAT
,
403 printError("AddContextAttribute(CSSM_ATTRIBUTE_PUBLIC_KEY_FORMAT)", crtn
);
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
415 printError("AddContextAttribute(CSSM_ATTRIBUTE_PRIVATE_KEY_FORMAT)", crtn
);
419 crtn
= CSSM_GenerateKeyPair(ccHand
,
426 &keyLabelData
, // same labels
427 NULL
, // CredAndAclEntry
430 printError("CSSM_GenerateKeyPair", crtn
);
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
;
444 switch(privKey
->KeyHeader
.BlobType
) {
445 case CSSM_KEYBLOB_RAW
:
448 printf("privKey blob type: exp raw, got %u\n",
449 (unsigned)privKey
->KeyHeader
.BlobType
);
450 ocrtn
= CSSM_ERRCODE_INTERNAL_ERROR
;
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
;
463 switch(pubKey
->KeyHeader
.BlobType
) {
464 case CSSM_KEYBLOB_RAW
:
467 printf("pubKey blob type: exp raw or raw_berder, got %u\n",
468 (unsigned)pubKey
->KeyHeader
.BlobType
);
469 ocrtn
= CSSM_ERRCODE_INTERNAL_ERROR
;
475 crtn
= CSSM_DeleteContext(ccHand
);
477 printError("CSSM_DeleteContext", crtn
);
478 ocrtn
= CSSM_ERRCODE_INTERNAL_ERROR
;
485 * Generate DSA key pair with optional generateAlgParams and optional
486 * incoming parameters.
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.
503 CSSM_DATA_PTR paramData
) // optional
506 CSSM_CC_HANDLE ccHand
;
507 CSSM_DATA keyLabelData
;
510 CSSM_RETURN ocrtn
= CSSM_OK
;
512 if(keySize
== CSP_KEY_SIZE_DEFAULT
) {
513 keySize
= CSP_DSA_KEY_SIZE_DEFAULT
;
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
);
522 crtn
= CSSM_CSP_CreateKeyGenContext(cspHand
,
532 printError("CSSM_CSP_CreateKeyGenContext", crtn
);
537 /* cook up attribute bits */
539 pubAttr
= CSSM_KEYATTR_RETURN_REF
| CSSM_KEYATTR_EXTRACTABLE
;
542 pubAttr
= CSSM_KEYATTR_RETURN_DATA
| CSSM_KEYATTR_EXTRACTABLE
;
545 privAttr
= CSSM_KEYATTR_RETURN_REF
| CSSM_KEYATTR_EXTRACTABLE
;
548 privAttr
= CSSM_KEYATTR_RETURN_DATA
| CSSM_KEYATTR_EXTRACTABLE
;
553 * extra step - generate params - this just adds some
554 * info to the context
556 CSSM_DATA dummy
= {0, NULL
};
557 crtn
= CSSM_GenerateAlgorithmParams(ccHand
,
560 printError("CSSM_GenerateAlgorithmParams", crtn
);
563 appFreeCssmData(&dummy
, CSSM_FALSE
);
566 /* optional format specifiers */
567 if(!pubIsRef
&& (pubFormat
!= CSSM_KEYBLOB_RAW_FORMAT_NONE
)) {
568 crtn
= AddContextAttribute(ccHand
,
569 CSSM_ATTRIBUTE_PUBLIC_KEY_FORMAT
,
575 printError("AddContextAttribute(CSSM_ATTRIBUTE_PUBLIC_KEY_FORMAT)", crtn
);
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
587 printError("AddContextAttribute(CSSM_ATTRIBUTE_PRIVATE_KEY_FORMAT)", crtn
);
592 crtn
= CSSM_GenerateKeyPair(ccHand
,
599 &keyLabelData
, // same labels
600 NULL
, // CredAndAclEntry
603 printError("CSSM_GenerateKeyPair", crtn
);
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
;
617 switch(privKey
->KeyHeader
.BlobType
) {
618 case CSSM_KEYBLOB_RAW
:
621 printf("privKey blob type: exp raw, got %u\n",
622 (unsigned)privKey
->KeyHeader
.BlobType
);
623 ocrtn
= CSSM_ERRCODE_INTERNAL_ERROR
;
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
;
636 switch(pubKey
->KeyHeader
.BlobType
) {
637 case CSSM_KEYBLOB_RAW
:
640 printf("pubKey blob type: exp raw or raw_berder, got %u\n",
641 (unsigned)pubKey
->KeyHeader
.BlobType
);
642 ocrtn
= CSSM_ERRCODE_INTERNAL_ERROR
;
648 crtn
= CSSM_DeleteContext(ccHand
);
650 printError("CSSM_DeleteContext", crtn
);
651 ocrtn
= CSSM_ERRCODE_INTERNAL_ERROR
;
658 uint32
cspDefaultKeySize(uint32 alg
)
660 uint32 keySizeInBits
;
663 keySizeInBits
= CSP_DES_KEY_SIZE_DEFAULT
;
665 case CSSM_ALGID_3DES_3KEY
:
666 case CSSM_ALGID_DESX
:
667 keySizeInBits
= CSP_DES3_KEY_SIZE_DEFAULT
;
670 keySizeInBits
= CSP_RC2_KEY_SIZE_DEFAULT
;
673 keySizeInBits
= CSP_RC4_KEY_SIZE_DEFAULT
;
676 keySizeInBits
= CSP_RC5_KEY_SIZE_DEFAULT
;
679 keySizeInBits
= CSP_ASC_KEY_SIZE_DEFAULT
;
681 case CSSM_ALGID_BLOWFISH
:
682 keySizeInBits
= CSP_BFISH_KEY_SIZE_DEFAULT
;
684 case CSSM_ALGID_CAST
:
685 keySizeInBits
= CSP_CAST_KEY_SIZE_DEFAULT
;
687 case CSSM_ALGID_IDEA
:
688 keySizeInBits
= CSP_IDEA_KEY_SIZE_DEFAULT
;
691 keySizeInBits
= CSP_AES_KEY_SIZE_DEFAULT
;
693 case CSSM_ALGID_SHA1HMAC
:
694 keySizeInBits
= CSP_HMAC_SHA_KEY_SIZE_DEFAULT
;
696 case CSSM_ALGID_MD5HMAC
:
697 keySizeInBits
= CSP_HMAC_MD5_KEY_SIZE_DEFAULT
;
700 keySizeInBits
= CSP_FEE_KEY_SIZE_DEFAULT
;
703 keySizeInBits
= CSP_RSA_KEY_SIZE_DEFAULT
;
706 keySizeInBits
= CSP_DSA_KEY_SIZE_DEFAULT
;
708 case CSSM_ALGID_ECDSA
:
709 keySizeInBits
= CSP_ECDSA_KEY_SIZE_DEFAULT
;
711 case CSSM_ALGID_NONE
:
712 keySizeInBits
= CSP_NULL_CRYPT_KEY_SIZE_DEF
;
715 printf("***cspDefaultKeySize: Unknown symmetric algorithm\n");
719 return keySizeInBits
;
723 * Create a random symmetric key.
725 CSSM_KEY_PTR
cspGenSymKey(CSSM_CSP_HANDLE cspHand
,
727 const char *keyLabel
,
728 unsigned keyLabelLen
,
729 uint32 keyUsage
, // CSSM_KEYUSE_ENCRYPT, etc.
730 uint32 keySizeInBits
,
733 CSSM_KEY_PTR symKey
= (CSSM_KEY_PTR
)CSSM_MALLOC(sizeof(CSSM_KEY
));
735 CSSM_CC_HANDLE ccHand
;
737 CSSM_DATA dummyLabel
;
740 printf("Insufficient heap space\n");
743 memset(symKey
, 0, sizeof(CSSM_KEY
));
744 setBadKeyData(symKey
);
745 if(keySizeInBits
== CSP_KEY_SIZE_DEFAULT
) {
746 keySizeInBits
= cspDefaultKeySize(alg
);
748 crtn
= CSSM_CSP_CreateKeyGenContext(cspHand
,
750 keySizeInBits
, // keySizeInBits
758 printError("CSSM_CSP_CreateKeyGenContext", crtn
);
762 keyAttr
= CSSM_KEYATTR_RETURN_REF
| CSSM_KEYATTR_EXTRACTABLE
;
765 keyAttr
= CSSM_KEYATTR_RETURN_DATA
| CSSM_KEYATTR_EXTRACTABLE
;
767 dummyLabel
.Length
= keyLabelLen
;
768 dummyLabel
.Data
= (uint8
*)keyLabel
;
770 crtn
= CSSM_GenerateKey(ccHand
,
777 printError("CSSM_GenerateKey", crtn
);
780 crtn
= CSSM_DeleteContext(ccHand
);
782 printError("CSSM_DeleteContext", crtn
);
792 * Derive symmetric key.
793 * Note in the X CSP, we never return an IV.
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
,
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
808 CSSM_KEY_PTR symKey
= (CSSM_KEY_PTR
)
809 CSSM_MALLOC(sizeof(CSSM_KEY
));
811 CSSM_CC_HANDLE ccHand
;
813 CSSM_DATA dummyLabel
;
814 CSSM_PKCS5_PBKDF2_PARAMS pbeParams
;
816 CSSM_ACCESS_CREDENTIALS creds
;
819 printf("Insufficient heap space\n");
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
);
828 crtn
= CSSM_CSP_CreateDeriveKeyContext(cspHand
,
839 printError("CSSM_CSP_CreateDeriveKeyContext", crtn
);
842 keyAttr
= CSSM_KEYATTR_EXTRACTABLE
;
844 keyAttr
|= (CSSM_KEYATTR_RETURN_REF
| CSSM_KEYATTR_SENSITIVE
);
847 keyAttr
|= CSSM_KEYATTR_RETURN_DATA
;
849 dummyLabel
.Length
= keyLabelLen
;
850 dummyLabel
.Data
= (uint8
*)keyLabel
;
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
,
863 NULL
, // cred and acl
866 printError("CSSM_DeriveKey", crtn
);
869 /* copy IV back to caller */
870 /* Nope, not supported */
872 if(pbeParams
.InitVector
.Data
!= NULL
) {
873 if(initVector
->Data
!= NULL
) {
874 if(initVector
->Length
< pbeParams
.InitVector
.Length
) {
875 printf("***Insufficient InitVector\n");
881 (uint8
*)CSSM_MALLOC(pbeParams
.InitVector
.Length
);
883 memmove(initVector
->Data
, pbeParams
.InitVector
.Data
,
884 pbeParams
.InitVector
.Length
);
885 initVector
->Length
= pbeParams
.InitVector
.Length
;
886 CSSM_FREE(pbeParams
.InitVector
.Data
);
889 printf("***Warning: CSSM_DeriveKey, no InitVector\n");
892 crtn
= CSSM_DeleteContext(ccHand
);
894 printError("CSSM_DeleteContext", crtn
);
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.
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
917 CSSM_KEYHEADER_PTR hdr
= &rawKey
.KeyHeader
;
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
);
933 /* convert to a ref key */
934 crtn
= cspRawKeyToRef(cspHand
, &rawKey
, refKey
);
935 appFreeCssmData(&rawKey
.KeyData
, CSSM_FALSE
);
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.
946 CSSM_RETURN
cspFreeKey(CSSM_CSP_HANDLE cspHand
,
950 crtn
= CSSM_FreeKey(cspHand
,
953 CSSM_FALSE
); // delete - OK? maybe should parameterize?
955 printError("CSSM_FreeKey", crtn
);
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.
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
;
979 maxSize
= MAX_KEY_SIZE_RC245_BYTES
* 8 ; // somewhat arbitrary
981 case CSSM_ALGID_BLOWFISH
:
985 case CSSM_ALGID_CAST
:
989 case CSSM_ALGID_IDEA
:
990 return CSP_IDEA_KEY_SIZE_DEFAULT
;
992 minSize
= CSP_RSA_KEY_SIZE_DEFAULT
;
996 /* signature only, no export restriction */
1000 case CSSM_ALGID_SHA1HMAC
:
1004 case CSSM_ALGID_MD5HMAC
:
1008 case CSSM_ALGID_FEE
:
1009 /* FEE requires discrete sizes */
1010 size
= genRand(1,4);
1015 if(alg
== CSSM_ALGID_FEE
) {
1026 printf("randKeySizeBits: internal error\n");
1029 case CSSM_ALGID_ECDSA
:
1030 case CSSM_ALGID_SHA1WithECDSA
:
1031 /* ECDSA require discrete sizes */
1032 size
= genRand(1,4);
1044 case CSSM_ALGID_AES
:
1045 size
= genRand(1, 3);
1054 case CSSM_ALGID_NONE
:
1055 return CSP_NULL_CRYPT_KEY_SIZE_DEF
;
1057 printf("randKeySizeBits: unknown alg\n");
1058 return CSP_KEY_SIZE_DEFAULT
;
1060 size
= genRand(minSize
, maxSize
);
1062 /* per-alg postprocessing.... */
1063 if(alg
!= CSSM_ALGID_RC2
) {
1067 case CSSM_ALGID_RSA
:
1068 // new for X - strong keys */
1071 case CSSM_ALGID_DSA
:
1072 /* size mod 64 == 0 */
1081 #pragma mark --------- Encrypt/Decrypt ---------
1087 * Common routine for encrypt/decrypt - cook up an appropriate context handle
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....
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
1103 const CSSM_DATA
*iv
, // optional
1104 uint32 effectiveKeySizeInBits
, // 0 means skip this attribute
1105 uint32 rounds
) // ditto
1107 CSSM_CC_HANDLE cryptHand
= 0;
1110 CSSM_ACCESS_CREDENTIALS creds
;
1112 memset(&creds
, 0, sizeof(CSSM_ACCESS_CREDENTIALS
));
1113 #if EFFECTIVE_SIZE_VIA_PARAMS
1114 params
= effectiveKeySizeInBits
;
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
,
1134 NULL
, // access cred
1141 printError("CSSM_CSP_CreateSymmetricContext", crtn
);
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
,
1156 printError("CSSM_CSP_CreateAsymmetricContext", crtn
);
1161 * FEED, some CFILE. Add (non-standard) second key attribute.
1163 crtn
= AddContextAttribute(cryptHand
,
1164 CSSM_ATTRIBUTE_PUBLIC_KEY
,
1165 sizeof(CSSM_KEY
), // currently sizeof CSSM_DATA
1170 printError("AddContextAttribute", crtn
);
1174 if(mode
!= CSSM_ALGMODE_NONE
) {
1175 /* special case, e.g., CSSM_ALGMODE_PUBLIC_KEY */
1176 crtn
= AddContextAttribute(cryptHand
,
1177 CSSM_ATTRIBUTE_MODE
,
1183 printError("AddContextAttribute", crtn
);
1189 printf("genCryptHandle: bogus algorithm\n");
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(
1204 printError("CSSM_UpdateContextAttributes", crtn
);
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(
1220 printError("CSSM_UpdateContextAttributes", crtn
);
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
1242 CSSM_CC_HANDLE cryptHand
;
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
;
1251 cryptHand
= genCryptHandle(cspHand
,
1258 effectiveKeySizeInBits
,
1260 if(cryptHand
== 0) {
1261 return CSSMERR_CSSM_INTERNAL_ERROR
;
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
1271 printError("CSSM_QuerySize", crtn
);
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");
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
;
1289 ctext
->Length
= origCtextLen
= querySize
.SizeOutputBlock
;
1290 memset(ctext
->Data
, 0, ctext
->Length
);
1294 origCtextLen
= ctext
->Length
;
1296 crtn
= CSSM_EncryptData(cryptHand
,
1303 if(crtn
== CSSM_OK
) {
1305 * Deal with remData - its contents are included in bytesEncrypted.
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 "
1314 if(newCdata
== NULL
) {
1315 printf("Insufficient heap space\n");
1316 ocrtn
= CSSM_ERRCODE_MEMORY_ERROR
;
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
;
1325 /* there's room left over */
1326 memmove(ctext
->Data
+ctext
->Length
, remData
.Data
, remData
.Length
);
1328 ctext
->Length
= bytesEncrypted
;
1330 // NOTE: We return the proper length in ctext....
1331 ctext
->Length
= bytesEncrypted
;
1335 restoreErr
= CSSM_TRUE
;
1336 printError("CSSM_EncryptData", crtn
);
1339 crtn
= CSSM_DeleteContext(cryptHand
);
1341 printError("CSSM_DeleteContext", crtn
);
1350 #define PAD_IMPLIES_RAND_PTEXTSIZE 1
1351 #define LOG_STAGED_OPS 0
1353 #define soprintf(s) printf s
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
1372 CSSM_CC_HANDLE cryptHand
;
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
;
1388 cryptHand
= genCryptHandle(cspHand
,
1395 effectiveKeySizeInBits
,
1397 if(cryptHand
== 0) {
1398 return CSSMERR_CSP_INTERNAL_ERROR
;
1400 if(cipherBlockSize
) {
1401 crtn
= AddContextAttribute(cryptHand
,
1402 CSSM_ATTRIBUTE_BLOCK_SIZE
,
1408 printError("CSSM_UpdateContextAttributes", crtn
);
1413 /* obtain total required ciphertext size and block size */
1414 querySize
.SizeInputBlock
= ptext
->Length
;
1415 crtn
= CSSM_QuerySize(cryptHand
,
1416 CSSM_TRUE
, // encrypt
1420 printError("CSSM_QuerySize(1)", crtn
);
1421 ocrtn
= CSSMERR_CSP_INTERNAL_ERROR
;
1424 if(querySize
.SizeOutputBlock
== 0) {
1425 /* CSP couldn't figure this out; skip our malloc - caller is taking its
1427 printf("***cspStagedEncrypt: warning: cipherTextSize unknown; aborting\n");
1428 ocrtn
= CSSMERR_CSP_INTERNAL_ERROR
;
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...*/
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
;
1445 memset(ctext
->Data
, 0, ctext
->Length
);
1448 crtn
= CSSM_EncryptDataInit(cryptHand
);
1450 printError("CSSM_EncryptDataInit", crtn
);
1455 toMove
= ptext
->Length
;
1456 thisPtext
.Data
= ptext
->Data
;
1459 thisMove
= genRand(1, toMove
);
1462 /* just do one pass thru this loop */
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
,
1477 printError("CSSM_EncryptDataUpdate", crtn
);
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
;
1487 if(bytesEncrypted
> ctext
->Length
) {
1488 printf("cspStagedEncrypt: ctext overflow!\n");
1492 if(bytesEncrypted
!= 0) {
1493 memmove(ctext
->Data
, ctextWork
.Data
, bytesEncrypted
);
1494 bytesEncryptedTotal
+= bytesEncrypted
;
1495 ctext
->Data
+= bytesEncrypted
;
1496 ctext
->Length
-= bytesEncrypted
;
1498 if(ctextWork
.Data
!= NULL
) {
1499 CSSM_FREE(ctextWork
.Data
);
1503 ctextWork
.Data
= NULL
;
1504 ctextWork
.Length
= 0;
1505 crtn
= CSSM_EncryptDataFinal(cryptHand
, &ctextWork
);
1507 printError("CSSM_EncryptDataFinal", crtn
);
1509 restoreErr
= CSSM_TRUE
;
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
;
1519 memmove(ctext
->Data
, ctextWork
.Data
, ctextWork
.Length
);
1521 if(ctextWork
.Data
) {
1522 /* this could have gotten mallocd and Length still be zero */
1523 CSSM_FREE(ctextWork
.Data
);
1526 /* retweeze ctext */
1527 ctext
->Data
= origCtext
;
1528 ctext
->Length
= bytesEncryptedTotal
;
1530 crtn
= CSSM_DeleteContext(cryptHand
);
1532 printError("CSSM_DeleteContext", crtn
);
1536 /* give caller the error from the encrypt */
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,
1556 CSSM_CC_HANDLE cryptHand
;
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
1563 cryptHand
= genCryptHandle(cspHand
,
1570 effectiveKeySizeInBits
,
1572 if(cryptHand
== 0) {
1573 return CSSMERR_CSP_INTERNAL_ERROR
;
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
1583 printError("CSSM_QuerySize", crtn
);
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");
1595 (uint8
*)appMalloc(querySize
.SizeOutputBlock
, NULL
);
1596 if(ptext
->Data
== NULL
) {
1597 printf("Insufficient heap space\n");
1598 ocrtn
= CSSMERR_CSP_MEMORY_ERROR
;
1601 ptext
->Length
= origPtextLen
= querySize
.SizeOutputBlock
;
1602 memset(ptext
->Data
, 0, ptext
->Length
);
1606 origPtextLen
= ptext
->Length
;
1608 crtn
= CSSM_DecryptData(cryptHand
,
1615 if(crtn
== CSSM_OK
) {
1617 * Deal with remData - its contents are included in bytesDecrypted.
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 "
1626 if(newPdata
== NULL
) {
1627 printf("Insufficient heap space\n");
1628 ocrtn
= CSSMERR_CSP_MEMORY_ERROR
;
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
;
1638 /* there's room left over */
1639 memmove(ptext
->Data
+ ptext
->Length
,
1640 remData
.Data
, remData
.Length
);
1642 ptext
->Length
= bytesDecrypted
;
1644 // NOTE: We return the proper length in ptext....
1645 ptext
->Length
= bytesDecrypted
;
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
1651 if(remData
.Data
!= NULL
) {
1652 appFree(remData
.Data
, NULL
);
1656 printError("CSSM_DecryptData", crtn
);
1660 crtn
= CSSM_DeleteContext(cryptHand
);
1662 printError("CSSM_DeleteContext", crtn
);
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
1682 CSSM_CC_HANDLE cryptHand
;
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
1695 cryptHand
= genCryptHandle(cspHand
,
1702 effectiveKeySizeInBits
,
1704 if(cryptHand
== 0) {
1705 return CSSMERR_CSP_INTERNAL_ERROR
;
1707 if(cipherBlockSize
) {
1708 crtn
= AddContextAttribute(cryptHand
,
1709 CSSM_ATTRIBUTE_BLOCK_SIZE
,
1715 printError("CSSM_UpdateContextAttributes", crtn
);
1720 /* obtain total required ciphertext size and block size */
1721 querySize
.SizeInputBlock
= ctext
->Length
;
1722 crtn
= CSSM_QuerySize(cryptHand
,
1723 CSSM_FALSE
, // encrypt
1727 printError("CSSM_QuerySize(1)", crtn
);
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
;
1739 // until exit, ptext->Length indicates remaining bytes of usable data in
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
;
1749 memset(ptext
->Data
, 0, ptext
->Length
);
1752 crtn
= CSSM_DecryptDataInit(cryptHand
);
1754 printError("CSSM_DecryptDataInit", crtn
);
1758 toMove
= ctext
->Length
;
1759 thisCtext
.Data
= ctext
->Data
;
1762 thisMove
= genRand(1, toMove
);
1765 /* just do one pass thru this loop */
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
,
1780 printError("CSSM_DecryptDataUpdate", crtn
);
1785 // NOTE: We return the proper length in ptext....
1786 ptextWork
.Length
= bytesDecrypted
;
1787 thisCtext
.Data
+= thisMove
;
1789 if(bytesDecrypted
> ptext
->Length
) {
1790 printf("cspStagedDecrypt: ptext overflow!\n");
1791 ocrtn
= CSSMERR_CSP_INTERNAL_ERROR
;
1794 if(bytesDecrypted
!= 0) {
1795 memmove(ptext
->Data
, ptextWork
.Data
, bytesDecrypted
);
1796 bytesDecryptedTotal
+= bytesDecrypted
;
1797 ptext
->Data
+= bytesDecrypted
;
1798 ptext
->Length
-= bytesDecrypted
;
1800 if(ptextWork
.Data
!= NULL
) {
1801 CSSM_FREE(ptextWork
.Data
);
1805 ptextWork
.Data
= NULL
;
1806 ptextWork
.Length
= 0;
1807 crtn
= CSSM_DecryptDataFinal(cryptHand
, &ptextWork
);
1809 printError("CSSM_DecryptDataFinal", crtn
);
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
;
1820 memmove(ptext
->Data
, ptextWork
.Data
, ptextWork
.Length
);
1822 if(ptextWork
.Data
) {
1823 /* this could have gotten mallocd and Length still be zero */
1824 CSSM_FREE(ptextWork
.Data
);
1827 /* retweeze ptext */
1828 ptext
->Data
= origPtext
;
1829 ptext
->Length
= bytesDecryptedTotal
;
1831 crtn
= CSSM_DeleteContext(cryptHand
);
1833 printError("CSSM_DeleteContext", crtn
);
1839 #pragma mark --------- sign/verify/MAC ---------
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
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
1855 CSSM_CC_HANDLE sigHand
;
1857 CSSM_RETURN ocrtn
= CSSM_OK
;
1858 const CSSM_DATA
*ptext
;
1859 CSSM_DATA digest
= {0, NULL
};
1860 CSSM_ALGORITHMS digestAlg
= CSSM_ALGID_NONE
;
1862 /* handle special cases for raw sign */
1864 case CSSM_ALGID_SHA1
:
1865 digestAlg
= CSSM_ALGID_SHA1
;
1866 algorithm
= CSSM_ALGID_RSA
;
1868 case CSSM_ALGID_MD5
:
1869 digestAlg
= CSSM_ALGID_MD5
;
1870 algorithm
= CSSM_ALGID_RSA
;
1872 case CSSM_ALGID_DSA
:
1873 digestAlg
= CSSM_ALGID_SHA1
;
1874 algorithm
= CSSM_ALGID_DSA
;
1879 if(digestAlg
!= CSSM_ALGID_NONE
) {
1880 crtn
= cspDigest(cspHand
,
1882 CSSM_FALSE
, // mallocDigest
1888 /* sign digest with raw RSA/DSA */
1894 crtn
= CSSM_CSP_CreateSignatureContext(cspHand
,
1900 printError("CSSM_CSP_CreateSignatureContext (1)", crtn
);
1903 crtn
= CSSM_SignData(sigHand
,
1909 printError("CSSM_SignData", crtn
);
1912 crtn
= CSSM_DeleteContext(sigHand
);
1914 printError("CSSM_DeleteContext", crtn
);
1917 if(digest
.Data
!= NULL
) {
1918 CSSM_FREE(digest
.Data
);
1924 * Staged sign. Each update does a random number of bytes 'till through.
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
1933 CSSM_CC_HANDLE sigHand
;
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
,
1945 printError("CSSM_CSP_CreateSignatureContext (1)", crtn
);
1948 crtn
= CSSM_SignDataInit(sigHand
);
1950 printError("CSSM_SignDataInit", crtn
);
1954 toMove
= text
->Length
;
1955 thisText
.Data
= text
->Data
;
1958 thisMove
= genRand(1, toMove
);
1963 thisText
.Length
= thisMove
;
1964 crtn
= CSSM_SignDataUpdate(sigHand
,
1968 printError("CSSM_SignDataUpdate", crtn
);
1972 thisText
.Data
+= thisMove
;
1975 crtn
= CSSM_SignDataFinal(sigHand
, sig
);
1977 printError("CSSM_SignDataFinal", crtn
);
1982 crtn
= CSSM_DeleteContext(sigHand
);
1984 printError("CSSM_DeleteContext", crtn
);
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
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
2005 CSSM_CC_HANDLE sigHand
;
2006 CSSM_RETURN ocrtn
= CSSM_OK
;
2008 const CSSM_DATA
*ptext
;
2009 CSSM_DATA digest
= {0, NULL
};
2010 CSSM_ALGORITHMS digestAlg
= CSSM_ALGID_NONE
;
2012 /* handle special cases for raw sign */
2014 case CSSM_ALGID_SHA1
:
2015 digestAlg
= CSSM_ALGID_SHA1
;
2016 algorithm
= CSSM_ALGID_RSA
;
2018 case CSSM_ALGID_MD5
:
2019 digestAlg
= CSSM_ALGID_MD5
;
2020 algorithm
= CSSM_ALGID_RSA
;
2022 case CSSM_ALGID_DSA
:
2023 digestAlg
= CSSM_ALGID_SHA1
;
2024 algorithm
= CSSM_ALGID_DSA
;
2029 if(digestAlg
!= CSSM_ALGID_NONE
) {
2030 crtn
= cspDigest(cspHand
,
2032 CSSM_FALSE
, // mallocDigest
2038 /* sign digest with raw RSA/DSA */
2044 crtn
= CSSM_CSP_CreateSignatureContext(cspHand
,
2050 printError("CSSM_CSP_CreateSignatureContext (3)", crtn
);
2054 crtn
= CSSM_VerifyData(sigHand
,
2059 if(crtn
!= expectResult
) {
2061 printf("Unexpected good Sig Verify\n");
2064 printError("CSSM_VerifyData", crtn
);
2066 ocrtn
= CSSMERR_CSSM_INTERNAL_ERROR
;
2068 crtn
= CSSM_DeleteContext(sigHand
);
2070 printError("CSSM_DeleteContext", crtn
);
2073 if(digest
.Data
!= NULL
) {
2074 CSSM_FREE(digest
.Data
);
2080 * Staged verify. Each update does a random number of bytes 'till through.
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
2091 CSSM_CC_HANDLE sigHand
;
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
,
2103 printError("CSSM_CSP_CreateSignatureContext (4)", crtn
);
2106 crtn
= CSSM_VerifyDataInit(sigHand
);
2108 printError("CSSM_VerifyDataInit", crtn
);
2112 toMove
= text
->Length
;
2113 thisText
.Data
= text
->Data
;
2116 thisMove
= genRand(1, toMove
);
2121 thisText
.Length
= thisMove
;
2122 crtn
= CSSM_VerifyDataUpdate(sigHand
,
2126 printError("CSSM_VerifyDataUpdate", crtn
);
2130 thisText
.Data
+= thisMove
;
2133 crtn
= CSSM_VerifyDataFinal(sigHand
, sig
);
2134 if(crtn
!= expectResult
) {
2136 printError("CSSM_VerifyDataFinal", crtn
);
2139 printf("Unexpected good Staged Sig Verify\n");
2141 ocrtn
= CSSMERR_CSSM_INTERNAL_ERROR
;
2144 crtn
= CSSM_DeleteContext(sigHand
);
2146 printError("CSSM_DeleteContext", crtn
);
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
2161 CSSM_CC_HANDLE macHand
;
2163 CSSM_RETURN ocrtn
= CSSM_OK
;
2164 crtn
= CSSM_CSP_CreateMacContext(cspHand
,
2169 printError("CSSM_CSP_CreateMacContext (1)", crtn
);
2172 crtn
= CSSM_GenerateMac(macHand
,
2177 printError("CSSM_GenerateMac", crtn
);
2180 crtn
= CSSM_DeleteContext(macHand
);
2182 printError("CSSM_DeleteContext", crtn
);
2189 * Staged generate mac.
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
2197 CSSM_BOOL multiUpdates
, // false:single update, true:multi updates
2198 CSSM_DATA_PTR mac
) // RETURNED
2200 CSSM_CC_HANDLE macHand
;
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
2207 crtn
= CSSM_CSP_CreateMacContext(cspHand
,
2212 printError("CSSM_CSP_CreateMacContext (2)", crtn
);
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
2224 printError("CSSM_QuerySize(mac)", crtn
);
2228 if(querySize
.SizeOutputBlock
== 0) {
2229 printf("Unknown mac size\n");
2230 ocrtn
= CSSMERR_CSSM_INTERNAL_ERROR
;
2233 mac
->Data
= (uint8
*)appMalloc(querySize
.SizeOutputBlock
, NULL
);
2234 if(mac
->Data
== NULL
) {
2235 printf("malloc failure\n");
2236 ocrtn
= CSSMERR_CSSM_MEMORY_ERROR
;
2239 mac
->Length
= querySize
.SizeOutputBlock
;
2242 crtn
= CSSM_GenerateMacInit(macHand
);
2244 printError("CSSM_GenerateMacInit", crtn
);
2248 toMove
= text
->Length
;
2249 thisText
.Data
= text
->Data
;
2253 thisMove
= genRand(1, toMove
);
2258 thisText
.Length
= thisMove
;
2259 crtn
= CSSM_GenerateMacUpdate(macHand
,
2263 printError("CSSM_GenerateMacUpdate", crtn
);
2267 thisText
.Data
+= thisMove
;
2270 crtn
= CSSM_GenerateMacFinal(macHand
, mac
);
2272 printError("CSSM_GenerateMacFinal", crtn
);
2277 crtn
= CSSM_DeleteContext(macHand
);
2279 printError("CSSM_DeleteContext", crtn
);
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
2293 CSSM_CC_HANDLE macHand
;
2294 CSSM_RETURN ocrtn
= CSSM_OK
;
2296 crtn
= CSSM_CSP_CreateMacContext(cspHand
,
2301 printError("CSSM_CSP_CreateMacContext (3)", crtn
);
2304 crtn
= CSSM_VerifyMac(macHand
,
2308 if(crtn
!= expectResult
) {
2310 printError("CSSM_VerifyMac", crtn
);
2313 printf("Unexpected good Mac Verify\n");
2315 ocrtn
= CSSMERR_CSSM_INTERNAL_ERROR
;
2317 crtn
= CSSM_DeleteContext(macHand
);
2319 printError("CSSM_DeleteContext", crtn
);
2326 * Staged mac verify. Each update does a random number of bytes 'till through.
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
2337 CSSM_CC_HANDLE macHand
;
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
2344 crtn
= CSSM_CSP_CreateMacContext(cspHand
,
2349 printError("CSSM_CSP_CreateMacContext (4)", crtn
);
2352 crtn
= CSSM_VerifyMacInit(macHand
);
2354 printError("CSSM_VerifyMacInit", crtn
);
2358 toMove
= text
->Length
;
2359 thisText
.Data
= text
->Data
;
2363 thisMove
= genRand(1, toMove
);
2368 thisText
.Length
= thisMove
;
2369 crtn
= CSSM_VerifyMacUpdate(macHand
,
2373 printError("CSSM_VerifyMacUpdate", crtn
);
2377 thisText
.Data
+= thisMove
;
2380 crtn
= CSSM_VerifyMacFinal(macHand
, mac
);
2381 if(crtn
!= expectResult
) {
2383 printError("CSSM_VerifyMacFinal", crtn
);
2386 printf("Unexpected good Staged Mac Verify\n");
2388 ocrtn
= CSSMERR_CSSM_INTERNAL_ERROR
;
2391 crtn
= CSSM_DeleteContext(macHand
);
2393 printError("CSSM_DeleteContext", crtn
);
2399 #pragma mark --------- Digest ---------
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
)
2410 CSSM_CC_HANDLE digestHand
;
2412 CSSM_RETURN ocrtn
= CSSM_OK
;
2414 crtn
= CSSM_CSP_CreateDigestContext(cspHand
,
2418 printError("CSSM_CSP_CreateDIgestContext (1)", crtn
);
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
2429 printError("CSSM_QuerySize(3)", crtn
);
2433 if(querySize
.SizeOutputBlock
== 0) {
2434 printf("Unknown digest size\n");
2435 ocrtn
= CSSMERR_CSSM_INTERNAL_ERROR
;
2438 digest
->Data
= (uint8
*)appMalloc(querySize
.SizeOutputBlock
, NULL
);
2439 if(digest
->Data
== NULL
) {
2440 printf("malloc failure\n");
2441 ocrtn
= CSSMERR_CSSM_MEMORY_ERROR
;
2444 digest
->Length
= querySize
.SizeOutputBlock
;
2446 crtn
= CSSM_DigestData(digestHand
,
2451 printError("CSSM_DigestData", crtn
);
2455 crtn
= CSSM_DeleteContext(digestHand
);
2457 printError("CSSM_DeleteContext", crtn
);
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
2467 CSSM_BOOL multiUpdates
, // false:single update, true:multi updates
2468 const CSSM_DATA
*text
,
2469 CSSM_DATA_PTR digest
)
2471 CSSM_CC_HANDLE digestHand
;
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
2478 crtn
= CSSM_CSP_CreateDigestContext(cspHand
,
2482 printError("CSSM_CSP_CreateDigestContext (2)", crtn
);
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
2493 printError("CSSM_QuerySize(4)", crtn
);
2497 if(querySize
.SizeOutputBlock
== 0) {
2498 printf("Unknown digest size\n");
2499 ocrtn
= CSSMERR_CSSM_INTERNAL_ERROR
;
2502 digest
->Data
= (uint8
*)appMalloc(querySize
.SizeOutputBlock
, NULL
);
2503 if(digest
->Data
== NULL
) {
2504 printf("malloc failure\n");
2505 ocrtn
= CSSMERR_CSSM_MEMORY_ERROR
;
2508 digest
->Length
= querySize
.SizeOutputBlock
;
2510 crtn
= CSSM_DigestDataInit(digestHand
);
2512 printError("CSSM_DigestDataInit", crtn
);
2516 toMove
= text
->Length
;
2517 thisText
.Data
= text
->Data
;
2520 thisMove
= genRand(1, toMove
);
2525 thisText
.Length
= thisMove
;
2526 crtn
= CSSM_DigestDataUpdate(digestHand
,
2530 printError("CSSM_DigestDataUpdate", crtn
);
2534 thisText
.Data
+= thisMove
;
2537 crtn
= CSSM_DigestDataFinal(digestHand
, digest
);
2539 printError("CSSM_DigestDataFinal", crtn
);
2544 crtn
= CSSM_DeleteContext(digestHand
);
2546 printError("CSSM_DeleteContext", crtn
);
2552 #pragma mark --------- wrap/unwrap ---------
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
2566 CSSM_CC_HANDLE ccHand
;
2568 CSSM_ACCESS_CREDENTIALS creds
;
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
,
2579 &creds
, // passPhrase,
2587 crtn
= CSSM_CSP_CreateAsymmetricContext(cspHand
,
2594 printError("cspWrapKey/CreateContext", crtn
);
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
,
2607 printError("CSSM_UpdateContextAttributes", crtn
);
2613 printError("cspWrapKey/CreateContext", crtn
);
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(
2627 printError("CSSM_UpdateContextAttributes", crtn
);
2631 crtn
= CSSM_WrapKey(ccHand
,
2634 descrData
, // DescriptiveData
2636 if(crtn
!= CSSM_OK
) {
2637 printError("CSSM_WrapKey", crtn
);
2639 if(CSSM_DeleteContext(ccHand
)) {
2640 printf("CSSM_DeleteContext failure\n");
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
)
2658 CSSM_CC_HANDLE ccHand
;
2660 CSSM_DATA labelData
;
2662 CSSM_ACCESS_CREDENTIALS creds
;
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
,
2680 crtn
= CSSM_CSP_CreateAsymmetricContext(cspHand
,
2682 &creds
, // passPhrase,
2684 unwrapPad
, // Padding
2687 printError("cspUnwrapKey/CreateContext", crtn
);
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
,
2700 printError("CSSM_UpdateContextAttributes", crtn
);
2706 printError("cspUnwrapKey/CreateContext", crtn
);
2709 labelData
.Data
= (uint8
*)keyLabel
;
2710 labelData
.Length
= keyLabelLen
;
2713 * New keyAttr - clear some old bits, make sure we ask for ref key
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
,
2721 wrappedKey
->KeyHeader
.KeyUsage
,
2724 NULL
, // CredAndAclEntry
2726 descrData
); // required
2727 if(crtn
!= CSSM_OK
) {
2728 printError("CSSM_UnwrapKey", crtn
);
2730 if(CSSM_DeleteContext(ccHand
)) {
2731 printf("CSSM_DeleteContext failure\n");
2737 * Simple NULL wrap to convert a reference key to a raw key.
2739 CSSM_RETURN
cspRefKeyToRaw(
2740 CSSM_CSP_HANDLE cspHand
,
2741 const CSSM_KEY
*refKey
,
2742 CSSM_KEY_PTR rawKey
) // init'd and RETURNED
2744 CSSM_DATA descData
= {0, 0};
2746 memset(rawKey
, 0, sizeof(CSSM_KEY
));
2747 return cspWrapKey(cspHand
,
2749 NULL
, // unwrappingKey
2752 CSSM_KEYBLOB_WRAPPED_FORMAT_NONE
,
2760 * Convert ref key to raw key with specified format.
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
2768 memset(rawKey
, 0, sizeof(CSSM_KEY
));
2769 CSSM_ATTRIBUTE_TYPE attrType
;
2771 switch(refKey
->KeyHeader
.KeyClass
) {
2772 case CSSM_KEYCLASS_PUBLIC_KEY
:
2773 attrType
= CSSM_ATTRIBUTE_PUBLIC_KEY_FORMAT
;
2775 case CSSM_KEYCLASS_PRIVATE_KEY
:
2776 attrType
= CSSM_ATTRIBUTE_PRIVATE_KEY_FORMAT
;
2778 case CSSM_KEYCLASS_SESSION_KEY
:
2779 attrType
= CSSM_ATTRIBUTE_SYMMETRIC_KEY_FORMAT
;
2782 printf("***Unknown key class\n");
2783 return CSSMERR_CSP_INVALID_KEY
;
2786 CSSM_DATA descData
= {0, 0};
2787 CSSM_CC_HANDLE ccHand
;
2790 CSSM_ACCESS_CREDENTIALS creds
;
2792 memset(rawKey
, 0, sizeof(CSSM_KEY
));
2793 memset(&creds
, 0, sizeof(CSSM_ACCESS_CREDENTIALS
));
2794 crtn
= CSSM_CSP_CreateSymmetricContext(cspHand
,
2798 NULL
, // unwrappingKey
2804 printError("cspRefKeyToRawWithFormat/CreateContext", crtn
);
2808 /* Add the spec for the resulting format */
2809 crtn
= AddContextAttribute(ccHand
,
2816 crtn
= CSSM_WrapKey(ccHand
,
2819 &descData
, // DescriptiveData
2821 if(crtn
!= CSSM_OK
) {
2822 printError("CSSM_WrapKey", crtn
);
2824 if(rawKey
->KeyHeader
.Format
!= format
) {
2825 printf("***cspRefKeyToRawWithFormat format scewup\n");
2826 crtn
= CSSMERR_CSP_INTERNAL_ERROR
;
2828 if(CSSM_DeleteContext(ccHand
)) {
2829 printf("CSSM_DeleteContext failure\n");
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
2840 CSSM_DATA descData
= {0, 0};
2842 memset(refKey
, 0, sizeof(CSSM_KEY
));
2843 return cspUnwrapKey(cspHand
,
2845 NULL
, // unwrappingKey
2849 NULL
, // init vector
2857 #pragma mark --------- FEE key/curve support ---------
2860 * Generate random key size, primeType, curveType for FEE key for specified op.
2862 * First just enumerate the curves we know about, with ECDSA-INcapable first
2866 uint32 keySizeInBits
;
2867 uint32 primeType
; // CSSM_FEE_PRIME_TYPE_xxx
2868 uint32 curveType
; // CSSM_FEE_CURVE_TYPE_xxx
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
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
},
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
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
},
2901 #endif /* FEE_PROTOTYPE_CURVES */
2902 #define NUM_FEE_CURVES (sizeof(feeCurves) / sizeof(feeCurveParams))
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
2912 feeCurveParams
*feeParams
;
2915 case CSSM_ALGID_SHA1WithECDSA
:
2916 minParams
= NUM_NON_ECDSA_CURVES
;
2922 die
= genRand(minParams
, (NUM_FEE_CURVES
- 1));
2923 feeParams
= &feeCurves
[die
];
2924 *keySizeInBits
= feeParams
->keySizeInBits
;
2925 *primeType
= feeParams
->primeType
;
2926 *curveType
= feeParams
->curveType
;
2930 * Obtain strings for primeType and curveType.
2932 const char *primeTypeStr(uint32 primeType
)
2936 case CSSM_FEE_PRIME_TYPE_MERSENNE
:
2939 case CSSM_FEE_PRIME_TYPE_FEE
:
2942 case CSSM_FEE_PRIME_TYPE_GENERAL
:
2945 case CSSM_FEE_PRIME_TYPE_DEFAULT
:
2949 p
= "***UNKNOWN***";
2955 const char *curveTypeStr(uint32 curveType
)
2959 case CSSM_FEE_CURVE_TYPE_DEFAULT
:
2962 case CSSM_FEE_CURVE_TYPE_MONTGOMERY
:
2965 case CSSM_FEE_CURVE_TYPE_WEIERSTRASS
:
2969 c
= "***UNKNOWN***";
2976 * Perform FEE Key exchange via CSSM_DeriveKey.
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
2985 /* remaining fields apply to derivedKey */
2987 const char *keyLabel
,
2988 unsigned keyLabelLen
,
2989 uint32 keyUsage
, // CSSM_KEYUSE_ENCRYPT, etc.
2990 uint32 keySizeInBits
)
2992 CSSM_CC_HANDLE dkHand
;
2994 CSSM_DATA labelData
;
2996 if(derivedKey
== NULL
) {
2997 printf("cspFeeKeyExchange: no derivedKey\n");
2998 return CSSMERR_CSSM_INTERNAL_ERROR
;
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
;
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
;
3012 memset(derivedKey
, 0, sizeof(CSSM_KEY
));
3014 crtn
= CSSM_CSP_CreateDeriveKeyContext(cspHand
,
3015 CSSM_ALGID_FEE_KEYEXCH
, // AlgorithmID
3016 keyAlg
, // alg of the derived key
3018 NULL
, // access creds
3020 0, // IterationCount
3023 NULL
); // PassPhrase
3025 printError("CSSM_CSP_CreateDeriveKeyContext");
3028 labelData
.Length
= keyLabelLen
;
3029 labelData
.Data
= (uint8
*)keyLabel
;
3030 crtn
= CSSM_DeriveKey(dkHand
,
3032 &pubKey
->KeyData
, // Param - pub key blob
3034 CSSM_KEYATTR_RETURN_REF
| CSSM_KEYATTR_EXTRACTABLE
|
3035 CSSM_KEYATTR_SENSITIVE
,
3039 /* FIXME - save/restore error */
3040 CSSM_DeleteContext(dkHand
);
3042 printError("CSSM_DeriveKey");
3048 #pragma mark --------- Key/DL/DB support ---------
3051 * Add a DL/DB handle to a crypto context.
3053 CSSM_RETURN
cspAddDlDbToContext(
3054 CSSM_CC_HANDLE ccHand
,
3055 CSSM_DL_HANDLE dlHand
,
3056 CSSM_DB_HANDLE dbHand
)
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
),
3068 * Common routine to do a basic DB lookup by label and key type.
3069 * Query is aborted prior to exit.
3071 static CSSM_DB_UNIQUE_RECORD_PTR
dlLookup(
3072 CSSM_DL_DB_HANDLE dlDbHand
,
3073 const CSSM_DATA
*keyLabel
,
3075 CSSM_HANDLE
*resultHand
, // RETURNED
3076 CSSM_DATA_PTR theData
, // RETURED
3077 CSSM_DB_RECORDTYPE
*recordType
) // RETURNED
3080 CSSM_SELECTION_PREDICATE predicate
;
3081 CSSM_DB_UNIQUE_RECORD_PTR record
= NULL
;
3086 query
.RecordType
= *recordType
= CSSM_DL_DB_RECORD_PUBLIC_KEY
;
3089 query
.RecordType
= *recordType
= CSSM_DL_DB_RECORD_PRIVATE_KEY
;
3092 query
.RecordType
= *recordType
= CSSM_DL_DB_RECORD_SYMMETRIC_KEY
;
3095 printf("Hey bozo! Give me a valid key type!\n");
3098 query
.Conjunctive
= CSSM_DB_NONE
;
3099 query
.NumSelectionPredicates
= 1;
3100 predicate
.DbOperator
= CSSM_DB_EQUAL
;
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
;
3110 query
.QueryLimits
.TimeLimit
= 0; // FIXME - meaningful?
3111 query
.QueryLimits
.SizeLimit
= 1; // FIXME - meaningful?
3112 query
.QueryFlags
= CSSM_QUERY_RETURN_DATA
; // FIXME - used?
3114 crtn
= CSSM_DL_DataGetFirst(dlDbHand
,
3120 /* abort only on success */
3121 if(crtn
== CSSM_OK
) {
3122 crtn
= CSSM_DL_DataAbortQuery(dlDbHand
, *resultHand
);
3124 printError("CSSM_DL_AbortQuery", crtn
);
3132 * Look up a key by label and type.
3134 CSSM_KEY_PTR
cspLookUpKeyByLabel(
3135 CSSM_DL_HANDLE dlHand
,
3136 CSSM_DB_HANDLE dbHand
,
3137 const CSSM_DATA
*labelData
,
3140 CSSM_DB_UNIQUE_RECORD_PTR record
;
3141 CSSM_HANDLE resultHand
;
3144 CSSM_DB_RECORDTYPE recordType
;
3145 CSSM_DL_DB_HANDLE dlDbHand
;
3147 dlDbHand
.DLHandle
= dlHand
;
3148 dlDbHand
.DBHandle
= dbHand
;
3151 theData
.Data
= NULL
;
3153 record
= dlLookup(dlDbHand
,
3159 if(record
== NULL
) {
3160 //printf("cspLookUpKeyByLabel: key not found\n");
3163 key
= (CSSM_KEY_PTR
)theData
.Data
;
3164 CSSM_DL_FreeUniqueRecord(dlDbHand
, record
);
3169 * Delete and free a key
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
,
3178 CSSM_DB_UNIQUE_RECORD_PTR record
;
3179 CSSM_HANDLE resultHand
;
3181 CSSM_RETURN crtn
= CSSM_OK
;
3182 CSSM_DB_RECORDTYPE recordType
;
3183 CSSM_DL_DB_HANDLE dlDbHand
;
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
;
3191 case CSSM_KEYCLASS_PRIVATE_KEY
:
3192 keyType
= CKT_Private
;
3194 case CSSM_KEYCLASS_SESSION_KEY
:
3195 keyType
= CKT_Session
;
3198 printf("Hey bozo! Give me a valid key type!\n");
3202 dlDbHand
.DLHandle
= dlHand
;
3203 dlDbHand
.DBHandle
= dbHand
;
3205 record
= dlLookup(dlDbHand
,
3209 NULL
, // don't want actual data
3211 if(record
== NULL
) {
3212 printf("cspDeleteKey: key not found in DL\n");
3213 return CSSMERR_DL_RECORD_NOT_FOUND
;
3217 crtn
= CSSM_DL_DataDelete(dlDbHand
, record
);
3219 printError("CSSM_DL_DataDelete", crtn
);
3221 CSSM_DL_FreeUniqueRecord(dlDbHand
, record
);
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?
3228 CSSM_FreeKey(cspHand
, NULL
, key
, CSSM_FALSE
);
3234 * Given any key in either blob or reference format,
3235 * obtain the associated SHA-1 hash.
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 */
3242 CSSM_CC_HANDLE ccHand
;
3248 /* validate input params */
3250 (hashData
== NULL
)) {
3251 printf("cspKeyHash: bogus args\n");
3252 return CSSMERR_CSSM_INTERNAL_ERROR
;
3255 /* cook up a context for a passthrough op */
3256 crtn
= CSSM_CSP_CreatePassThroughContext(cspHand
,
3260 printError("CSSM_CSP_CreatePassThroughContext", crtn
);
3264 /* now it's up to the CSP */
3265 crtn
= CSSM_CSP_PassThrough(ccHand
,
3266 CSSM_APPLECSP_KEYDIGEST
,
3270 printError("CSSM_CSP_PassThrough(PUBKEYHASH)", crtn
);
3276 CSSM_DeleteContext(ccHand
);