2 * asymCompat.c - test compatibilty of two different implementations of a
3 * RSA and DSA - one in the standard AppleCSP, one in BSAFE.
9 #include <Security/cssm.h>
10 #include <Security/cssmapple.h>
13 #include "bsafeUtils.h"
15 #include "cspdlTesting.h"
20 #define OLOOPS_DEF 10 /* outer loops, one set of keys per loop */
21 #define SIG_LOOPS_DEF 100 /* sig loops */
22 #define ENC_LOOPS_DEF 100 /* encrypt/decrypt loops */
23 #define MAX_TEXT_SIZE 1025
25 #define LOOP_NOTIFY 20
27 static void usage(char **argv
)
29 printf("usage: %s [options]\n", argv
[0]);
30 printf(" Options:\n");
31 printf(" a=algorithm (r=RSA; d=DSA; default=both)\n");
32 printf(" l=outerloops (default=%d; 0=forever)\n", OLOOPS_DEF
);
33 printf(" s=sigLoops (default=%d)\n", SIG_LOOPS_DEF
);
34 printf(" e=encryptLoops (default=%d)\n", ENC_LOOPS_DEF
);
35 printf(" k=keySizeInBits; default is random\n");
36 printf(" S (sign/verify only)\n");
37 printf(" E (encrypt/decrypt only)\n");
38 printf(" r (generate ref keys)\n");
39 printf(" R (generate public ref keys)\n");
40 printf(" p=pauseInterval (default=0, no pause)\n");
41 printf(" D (CSP/DL; default = bare CSP)\n");
42 printf(" v(erbose)\n");
48 static const char *algToStr(CSSM_ALGORITHMS sigAlg
)
51 case CSSM_ALGID_RSA
: return "RSA";
52 case CSSM_ALGID_DSA
: return "DSA";
53 case CSSM_ALGID_SHA1WithRSA
: return "SHA1WithRSA";
54 case CSSM_ALGID_MD5WithRSA
: return "MD5WithRSA";
55 case CSSM_ALGID_SHA1WithDSA
: return "SHA1WithDSA";
57 printf("***Unknown sigAlg\n");
65 * CDSA private key decrypt with blinding option.
67 static CSSM_RETURN
_cspDecrypt(CSSM_CSP_HANDLE cspHand
,
68 uint32 algorithm
, // CSSM_ALGID_FEED, etc.
69 uint32 mode
, // CSSM_ALGMODE_CBC, etc. - only for symmetric algs
70 CSSM_PADDING padding
, // CSSM_PADDING_PKCS1, etc.
72 const CSSM_KEY
*key
, // public or session key
73 const CSSM_DATA
*ctext
,
74 CSSM_DATA_PTR ptext
) // RETURNED
76 CSSM_CC_HANDLE cryptHand
;
78 CSSM_RETURN ocrtn
= CSSM_OK
;
79 CSSM_SIZE bytesDecrypted
;
80 CSSM_DATA remData
= {0, NULL
};
82 cryptHand
= genCryptHandle(cspHand
,
89 0, // effectiveKeySizeInBits,
92 return CSSMERR_CSP_INTERNAL_ERROR
;
95 CSSM_CONTEXT_ATTRIBUTE newAttr
;
96 newAttr
.AttributeType
= CSSM_ATTRIBUTE_RSA_BLINDING
;
97 newAttr
.AttributeLength
= sizeof(uint32
);
98 newAttr
.Attribute
.Uint32
= 1;
99 crtn
= CSSM_UpdateContextAttributes(cryptHand
, 1, &newAttr
);
101 printError("CSSM_UpdateContextAttributes", crtn
);
106 crtn
= CSSM_DecryptData(cryptHand
,
113 if(crtn
== CSSM_OK
) {
114 // NOTE: We return the proper length in ptext....
115 ptext
->Length
= bytesDecrypted
;
117 // FIXME - sometimes get mallocd RemData here, but never any valid data
118 // there...side effect of CSPFullPluginSession's buffer handling logic;
119 // but will we ever actually see valid data in RemData? So far we never
121 if(remData
.Data
!= NULL
) {
122 appFree(remData
.Data
, NULL
);
126 printError("CSSM_DecryptData", crtn
);
129 crtn
= CSSM_DeleteContext(cryptHand
);
131 printError("CSSM_DeleteContext", crtn
);
137 /* sign with RSA blinging option */
138 static CSSM_RETURN
_cspSign(CSSM_CSP_HANDLE cspHand
,
139 uint32 algorithm
, // CSSM_ALGID_FEE_MD5, etc.
140 CSSM_KEY_PTR key
, // private key
141 const CSSM_DATA
*text
,
142 CSSM_BOOL rsaBlinding
,
143 CSSM_DATA_PTR sig
) // RETURNED
145 CSSM_CC_HANDLE sigHand
;
147 CSSM_RETURN ocrtn
= CSSM_OK
;
148 const CSSM_DATA
*ptext
;
149 CSSM_DATA digest
= {0, NULL
};
150 CSSM_ALGORITHMS digestAlg
= CSSM_ALGID_NONE
;
152 /* handle special cases for raw sign */
154 case CSSM_ALGID_SHA1
:
155 digestAlg
= CSSM_ALGID_SHA1
;
156 algorithm
= CSSM_ALGID_RSA
;
159 digestAlg
= CSSM_ALGID_MD5
;
160 algorithm
= CSSM_ALGID_RSA
;
163 digestAlg
= CSSM_ALGID_SHA1
;
164 algorithm
= CSSM_ALGID_DSA
;
169 if(digestAlg
!= CSSM_ALGID_NONE
) {
170 crtn
= cspDigest(cspHand
,
172 CSSM_FALSE
, // mallocDigest
178 /* sign digest with raw RSA/DSA */
184 crtn
= CSSM_CSP_CreateSignatureContext(cspHand
,
190 printError("CSSM_CSP_CreateSignatureContext (1)", crtn
);
194 CSSM_CONTEXT_ATTRIBUTE newAttr
;
195 newAttr
.AttributeType
= CSSM_ATTRIBUTE_RSA_BLINDING
;
196 newAttr
.AttributeLength
= sizeof(uint32
);
197 newAttr
.Attribute
.Uint32
= 1;
198 crtn
= CSSM_UpdateContextAttributes(sigHand
, 1, &newAttr
);
200 printError("CSSM_UpdateContextAttributes", crtn
);
204 crtn
= CSSM_SignData(sigHand
,
210 printError("CSSM_SignData", crtn
);
213 crtn
= CSSM_DeleteContext(sigHand
);
215 printError("CSSM_DeleteContext", crtn
);
218 if(digest
.Data
!= NULL
) {
219 CSSM_FREE(digest
.Data
);
228 * for specified numLoops {
229 * generate random text;
230 * sign with BSAFE priv key, verify with CDSA pub key;
231 * sign with CDSA priv key, verify with BSAFE pub key;
235 CSSM_CSP_HANDLE cspHand
,
238 /* one matched key pair */
240 CSSM_KEY_PTR cdsaPubKey
,
242 /* another matched key pair */
243 CSSM_KEY_PTR cdsaPrivKey
,
247 unsigned maxPtextSize
,
248 CSSM_ALGORITHMS sigAlg
,
249 CSSM_BOOL rsaBlinding
,
254 CSSM_DATA sig
= {0, NULL
};
256 uint32 keySizeInBits
= cdsaPrivKey
->KeyHeader
.LogicalKeySizeInBits
;
259 printf(" ...sig alg %s keySize %u\n", algToStr(sigAlg
), (unsigned)keySizeInBits
);
261 for(loop
=0; loop
<numLoops
; loop
++) {
262 simpleGenData(ptext
, 1, maxPtextSize
);
264 if(verbose
|| ((loop
% LOOP_NOTIFY
) == 0)) {
265 printf(" ...loop %d keySize %u textSize %lu\n",
266 loop
, (unsigned)cdsaPrivKey
->KeyHeader
.LogicalKeySizeInBits
,
267 (unsigned long)ptext
->Length
);
271 /* sign with BSAFE, verify with CDSA */
272 crtn
= buSign(bsafePrivKey
,
278 return testError(quiet
);
280 crtn
= cspSigVerify(cspHand
,
287 printf("***ERROR: Sign with BSAFE, vfy with CDSA, alg %s\n",
289 if(testError(quiet
)) {
293 appFreeCssmData(&sig
, CSSM_FALSE
);
295 /* sign with CDSA, verify with BSAFE */
296 crtn
= _cspSign(cspHand
,
303 return testError(quiet
);
305 crtn
= buVerify(bsafePubKey
,
310 printf("***ERROR: Sign with CDSA, vfy with BSAFE, alg %s\n",
312 if(testError(quiet
)) {
316 appFreeCssmData(&sig
, CSSM_FALSE
);
322 * RSA Encrypt/decrypt test.
324 * for specified numLoops {
325 * generate random text;
326 * encrypt with BSAFE pub key, decrypt with CDSA priv key, verify;
327 * encrypt with CDSA pub key, decrypt with BSAFE priv key, verify;
330 static int encryptTest(
331 CSSM_CSP_HANDLE cspHand
,
334 /* one matched key pair */
336 CSSM_KEY_PTR cdsaPubKey
,
338 /* another matched key pair */
339 CSSM_KEY_PTR cdsaPrivKey
,
343 unsigned maxPtextSize
,
344 CSSM_BOOL rsaBlinding
,
349 CSSM_DATA ctext
= {0, NULL
};
350 CSSM_DATA rptext
= {0, NULL
};
352 unsigned actKeySizeBytes
;
354 actKeySizeBytes
= cdsaPrivKey
->KeyHeader
.LogicalKeySizeInBits
/ 8;
355 if(actKeySizeBytes
< 12) {
356 printf("***Key with %u key bits is too small for RSA encrypt\n",
357 (unsigned)cdsaPrivKey
->KeyHeader
.LogicalKeySizeInBits
);
360 if(maxPtextSize
> (actKeySizeBytes
- 11)) {
361 maxPtextSize
= actKeySizeBytes
- 11;
364 printf(" ...encr alg RSA\n");
366 for(loop
=0; loop
<numLoops
; loop
++) {
367 simpleGenData(ptext
, 1, maxPtextSize
);
369 if(verbose
|| ((loop
% LOOP_NOTIFY
) == 0)) {
370 printf(" ...loop %d keySize %u textSize %lu\n",
371 loop
, (unsigned)cdsaPrivKey
->KeyHeader
.LogicalKeySizeInBits
,
372 (unsigned long)ptext
->Length
);
376 /* encrypt with BSAFE, decrypt with CDSA */
377 crtn
= buEncryptDecrypt(bsafePubKey
,
378 CSSM_TRUE
, // encrypt
382 cdsaPrivKey
->KeyHeader
.LogicalKeySizeInBits
,
387 return testError(quiet
);
389 crtn
= _cspDecrypt(cspHand
,
398 printf("***ERROR: encrypt with BSAFE, decrypt with CDSA\n");
399 return testError(quiet
);
401 if(!appCompareCssmData(ptext
, &rptext
)) {
402 printf("***DATA MISCOMPARE: encrypt with BSAFE, decrypt with CDSA\n");
403 return testError(quiet
);
405 appFreeCssmData(&ctext
, CSSM_FALSE
);
406 appFreeCssmData(&rptext
, CSSM_FALSE
);
408 /* encrypt with CDSA, decrypt with BSAFE */
409 crtn
= cspEncrypt(cspHand
,
414 NULL
, // (FEE) pub key
415 0, // effectiveKeyBits
420 CSSM_FALSE
); // mallocCtext
422 return testError(quiet
);
424 crtn
= buEncryptDecrypt(bsafePrivKey
,
425 CSSM_FALSE
, // encrypt
429 cdsaPrivKey
->KeyHeader
.LogicalKeySizeInBits
,
434 printf("***ERROR: encrypt with CDSA, decrypt with BSAFE\n");
435 return testError(quiet
);
437 if(!appCompareCssmData(ptext
, &rptext
)) {
438 printf("***DATA MISCOMPARE: encrypt with CDSA, decrypt with BSAFE\n");
439 return testError(quiet
);
441 appFreeCssmData(&ctext
, CSSM_FALSE
);
442 appFreeCssmData(&rptext
, CSSM_FALSE
);
448 CSSM_CSP_HANDLE cspHand
,
449 CSSM_ALGORITHMS keyAlg
, // RSA/DSA
450 CSSM_ALGORITHMS sigAlg
,
451 unsigned sigLoops
, // may be zero
452 unsigned encrLoops
, // ditto; it will be zero for DSA
453 CSSM_BOOL rsaBlinding
,
455 unsigned maxPtextSize
,
456 uint32 keySizeInBits
, // 0 --> random per alg
457 CSSM_BOOL pubRefKeys
,
458 CSSM_BOOL privRefKeys
,
459 CSSM_BOOL bareCsp
, // for other workarounds
463 CSSM_KEY cdsaGenPubKey
;
464 CSSM_KEY cdsaGenPrivKey
; // only used to create bsafeDerivePrivKey
465 CSSM_KEY cdsaTempKey
; // raw key if privRefKeys true
466 CSSM_KEY cdsaDerivePrivKey
; // same as bsafeGenPrivKey
467 BU_KEY bsafeGenPubKey
;
468 BU_KEY bsafeGenPrivKey
; // only used to create cdsaDerivePrivKey
469 BU_KEY bsafeDerivePrivKey
; // same as cdsaGenPrivKey
470 unsigned actKeySizeBits
;
475 /* random key size */
476 actKeySizeBits
= randKeySizeBits(keyAlg
, OT_Encrypt
);
479 /* caller/user specified */
480 actKeySizeBits
= keySizeInBits
;
483 printf(" ...generating %s key pair, keySize %d bits...\n",
484 algToStr(keyAlg
), actKeySizeBits
);
488 * Generate two keypairs
490 if(keyAlg
== CSSM_ALGID_DSA
) {
491 CSSM_BOOL doGenParams
;
493 if(bareCsp
|| CSPDL_DSA_GEN_PARAMS
) {
494 doGenParams
= CSSM_TRUE
;
497 /* CSPDL - no gen params */
498 doGenParams
= CSSM_FALSE
;
500 crtn
= cspGenDSAKeyPair(cspHand
,
507 CSSM_KEYBLOB_RAW_FORMAT_NONE
,
511 CSSM_KEYBLOB_RAW_FORMAT_NONE
,
512 doGenParams
, // genParams
516 crtn
= cspGenKeyPair(cspHand
,
524 CSSM_KEYBLOB_RAW_FORMAT_NONE
,
528 CSSM_KEYBLOB_RAW_FORMAT_NONE
,
529 CSSM_FALSE
); // genSeed not used
532 return testError(quiet
);
534 crtn
= buGenKeyPair(actKeySizeBits
,
539 return testError(quiet
);
543 * Convert private keys to other library.
544 * NOTE: the reason we're only converting private keys is solely due to the
545 * fact that BSAFE does not handle PKCS1 formatted public key blobs. Very odd.
546 * But it's too much of a pain to re-implement that wheel here, and SSL and
547 * cert handling in general verify the CSP's PKCS1-style public key handling.
550 /* first generate a temporary raw CDSA key */
551 crtn
= buBsafePrivKeyToCdsa(keyAlg
,
556 return testError(quiet
);
559 /* convert it to the ref key we'll actually use */
560 crtn
= cspRawKeyToRef(cspHand
, &cdsaTempKey
, &cdsaDerivePrivKey
);
561 cspFreeKey(cspHand
, &cdsaTempKey
);
564 crtn
= buBsafePrivKeyToCdsa(keyAlg
,
570 return testError(quiet
);
573 /* we have a CDSA priv ref key; convert it to raw format */
574 crtn
= cspRefKeyToRaw(cspHand
, &cdsaGenPrivKey
, &cdsaTempKey
);
576 return testError(quiet
);
578 /* now convert it to BSAFE */
579 crtn
= buCdsaPrivKeyToBsafe(&cdsaTempKey
, &bsafeDerivePrivKey
);
580 cspFreeKey(cspHand
, &cdsaTempKey
);
583 crtn
= buCdsaPrivKeyToBsafe(&cdsaGenPrivKey
, &bsafeDerivePrivKey
);
586 return testError(quiet
);
590 rtn
= sigTest(cspHand
,
608 rtn
= encryptTest(cspHand
,
624 /* free all six keys */
625 buFreeKey(bsafeGenPubKey
);
626 buFreeKey(bsafeGenPrivKey
);
627 buFreeKey(bsafeDerivePrivKey
);
628 cspFreeKey(cspHand
, &cdsaGenPubKey
);
629 cspFreeKey(cspHand
, &cdsaGenPrivKey
);
630 cspFreeKey(cspHand
, &cdsaDerivePrivKey
);
634 int main(int argc
, char **argv
)
640 CSSM_CSP_HANDLE cspHand
;
647 uint32 keySizeInBits
= 0;
648 unsigned oloops
= OLOOPS_DEF
;
649 unsigned sigLoops
= SIG_LOOPS_DEF
;
650 unsigned encrLoops
= ENC_LOOPS_DEF
;
651 CSSM_BOOL verbose
= CSSM_FALSE
;
652 CSSM_BOOL quiet
= CSSM_FALSE
;
653 unsigned pauseInterval
= 0;
654 CSSM_BOOL bareCsp
= CSSM_TRUE
;
655 CSSM_BOOL doDSA
= CSSM_TRUE
;
656 CSSM_BOOL doRSA
= CSSM_TRUE
;
657 CSSM_BOOL pubRefKeys
= CSSM_FALSE
;
658 CSSM_BOOL privRefKeys
= CSSM_FALSE
;
660 for(arg
=1; arg
<argc
; arg
++) {
679 oloops
= atoi(&argp
[2]);
682 sigLoops
= atoi(&argp
[2]);
685 encrLoops
= atoi(&argp
[2]);
688 keySizeInBits
= atoi(&argp
[2]);
694 privRefKeys
= CSSM_TRUE
;
697 pubRefKeys
= CSSM_TRUE
;
700 bareCsp
= CSSM_FALSE
;
701 #if CSPDL_ALL_KEYS_ARE_REF
702 privRefKeys
= CSSM_TRUE
;
703 pubRefKeys
= CSSM_TRUE
;
716 pauseInterval
= atoi(&argp
[2]);;
723 ptext
.Data
= (uint8
*)CSSM_MALLOC(MAX_TEXT_SIZE
);
724 if(ptext
.Data
== NULL
) {
725 printf("Insufficient heap space\n");
728 /* ptext length set in inner test loops */
730 printf("Starting asymCompat; args: ");
731 for(i
=1; i
<argc
; i
++) {
732 printf("%s ", argv
[i
]);
735 cspHand
= cspDlDbStartup(bareCsp
, NULL
);
741 printf("Top of test; hit CR to proceed: ");
744 for(loop
=1; ; loop
++) {
746 if(verbose
|| ((loop
% LOOP_NOTIFY
) == 0)) {
747 printf("...oloop %d\n", loop
);
752 CSSM_ALGORITHMS sigAlg
;
754 sigAlg
= CSSM_ALGID_SHA1WithRSA
;
757 sigAlg
= CSSM_ALGID_MD5WithRSA
;
760 /* enable RSA blinding on half the loops for RSA */
761 CSSM_BOOL rsaBlinding
= CSSM_FALSE
;
763 rsaBlinding
= CSSM_TRUE
;
766 rtn
= doTest(cspHand
,
785 rtn
= doTest(cspHand
,
787 CSSM_ALGID_SHA1WithDSA
,
789 0, // encrLoops - none for DSA
790 CSSM_FALSE
, // blinding
803 if(oloops
&& (loop
== oloops
)) {
806 if(pauseInterval
&& (loop
% pauseInterval
) == 0) {
808 printf("hit CR to proceed: ");
813 cspShutdown(cspHand
, bareCsp
);
816 printf("ModuleDetach/Unload complete; hit CR to exit: ");
819 if((rtn
== 0) && !quiet
) {
820 printf("%s test complete\n", argv
[0]);
822 CSSM_FREE(ptext
.Data
);