1 /* Copyright (c) 1997,2003-2006,2008 Apple Inc.
3 * badsig.c - Verify bad signature detect, CDSA version.
7 * 4 May 2000 Doug Mitchell
9 * 28 Apr 1998 Doug Mitchell at Apple
10 * Ported to CDSA 1.2, new Apple CSP.
11 * 15 Aug 1997 Doug Mitchell at Apple
12 * Ported from CryptKit ObjC version
13 * 26 Aug 1996 Doug Mitchell at NeXT
17 * text size = {random, from 100 bytes to 1 megabyte, in
18 * geometrical steps, i.e. the number of
19 * bytes would be 10^r, where r is random out of
20 * {2,3,4,5,6}, plus a random integer in {0,..99}};
23 * text contents = {random data, random size as specified above};
25 * generate signature, validate;
26 * for various bytes of ptext {
28 * verify bad signature;
29 * restore corrupted byte;
38 #include <Security/cssm.h>
40 #include <Security/cssm.h>
43 #include "cspdlTesting.h"
45 #define USAGE_NAME "noUsage"
46 #define USAGE_NAME_LEN (strlen(USAGE_NAME))
52 #define MIN_EXP 2 /* for data size 10**exp */
53 #define DEFAULT_MAX_EXP 2
55 #define INCR_DEFAULT 0 /* munge every incr bytes - zero means
56 * "adjust per ptext size" */
57 #define FEE_PASSWD_LEN 32 /* private data length in bytes, FEE only */
61 * Enumerate algs our own way to allow iteration.
64 #define ALG_FEE_SHA1 2
66 #define ALG_ANSI_ECDSA 4
69 #define ALG_RAW_RSA_SHA1 7
70 #define ALG_RAW_DSA_SHA1 8
71 #define ALG_RSA_SHA224 9
72 #define ALG_RSA_SHA256 10
73 #define ALG_RSA_SHA384 11
74 #define ALG_RSA_SHA512 12
75 #define ALG_ECDSA_SHA256 13
76 #define ALG_ECDSA_SHA384 14
77 #define ALG_ECDSA_SHA512 15
80 #define ALG_FIRST ALG_FEE_MD5
81 #define ALG_LAST ALG_ECDSA_SHA512
82 #define MAX_DATA_SIZE (100000 + 100) /* bytes */
84 static void usage(char **argv
)
86 printf("usage: %s [options]\n", argv
[0]);
87 printf(" Options:\n");
88 printf(" a=algorithm (f=FEE/MD5; F=FEE/SHA1; e=ECDSA; r=RSA; d=DSA; R=raw RSA; \n");
89 printf(" D=raw DSA; 2=RSA/SHA224; 6=RSA/SHA256; 3=RSA/SHA384; 5=RSA/SHA512; default=all)\n");
90 printf(" E=ECDSA/ANSI; 7=ECDSA/SHA256; 8=ECDSA/SHA384; 9=ECDSA/512; default=all\n");
91 printf(" l=loops (default=%d; 0=forever)\n", LOOPS_DEF
);
92 printf(" n=minExp (default=%d)\n", MIN_EXP
);
93 printf(" x=maxExp (default=%d, max=%d)\n", DEFAULT_MAX_EXP
, MAX_EXP
);
94 printf(" k=keySize (r=random; default fixed per algorithm)\n");
95 printf(" i=increment (default=%d)\n", INCR_DEFAULT
);
96 printf(" R(ef keys only)\n");
97 printf(" p=pauseInterval (default=0, no pause)\n");
98 printf(" P=primeType (m=Mersenne, f=FEE, g=general; FEE only)\n");
99 printf(" C=curveType (m=Montgomery, w=Weierstrass, g=general; FEE only)\n");
100 printf(" D (CSP/DL; default = bare CSP)\n");
101 printf(" v(erbose)\n");
102 printf(" q(uiet)\n");
109 static int doTest(CSSM_CSP_HANDLE cspHand
,
110 CSSM_ALGORITHMS sigAlg
, // CSSM_ALGID_xxx signature algorithm
111 CSSM_ALGORITHMS keyGenAlg
,
115 CSSM_BOOL randKeySize
,
119 CSSM_KEYBLOB_FORMAT pubFormat
,
121 CSSM_KEYBLOB_FORMAT privFormat
,
122 CSSM_BOOL stagedSign
,
123 CSSM_BOOL stagedVerify
,
125 uint32 primeType
, // CSSM_FEE_PRIME_TYPE_xxx, FEE only
126 uint32 curveType
, // CSSM_FEE_CURVE_TYPE_xxx, FEE only
127 CSSM_BOOL genParams
) // DSA only
131 CSSM_DATA sig
= {0, NULL
};
135 unsigned char origData
;
141 if(keyGenAlg
== CSSM_ALGID_FEE
) {
142 uint8 passwd
[FEE_PASSWD_LEN
];
143 CSSM_DATA pwdData
= {FEE_PASSWD_LEN
, passwd
};
144 CSSM_DATA_PTR pwdDataPtr
;
147 /* random params for this op */
148 randFeeKeyParams(sigAlg
, &keySize
, &primeType
, &curveType
);
150 /* else use caller's size, primeType, curveType */
153 simpleGenData(&pwdData
, FEE_PASSWD_LEN
, FEE_PASSWD_LEN
);
154 pwdDataPtr
= &pwdData
;
160 printf(" key size %u primeType %s curveType %s\n",
161 (unsigned)keySize
, primeTypeStr(primeType
), curveTypeStr(curveType
));
163 rtn
= cspGenFEEKeyPair(cspHand
,
181 keySize
= randKeySizeBits(keyGenAlg
, OT_Sign
);
184 printf(" key size %u\n", (unsigned)keySize
);
186 if(keyGenAlg
== CSSM_ALGID_DSA
) {
187 rtn
= cspGenDSAKeyPair(cspHand
,
203 rtn
= cspGenKeyPair(cspHand
,
220 rtn
= testError(quiet
);
224 crtn
= cspStagedSign(cspHand
,
232 crtn
= cspSign(cspHand
,
243 crtn
= cspStagedSigVerify(cspHand
,
252 crtn
= cspSigVerify(cspHand
,
260 printf("**Unexpected BAD signature\n");
261 return testError(quiet
);
263 data
= (unsigned char *)ptext
->Data
;
264 length
= ptext
->Length
;
265 for(byte
=0; byte
<length
; byte
+= incr
) {
266 if(verbose
&& ((loop
++ % LOG_FREQ
) == 0)) {
267 printf(" ..byte %d\n", byte
);
269 origData
= data
[byte
];
271 * Generate random non-zero byte
274 bits
= genRand(1, 0xff) & 0xff;
278 crtn
= cspStagedSigVerify(cspHand
,
284 CSSMERR_CSP_VERIFY_FAILED
); // expect failure
287 crtn
= cspSigVerify(cspHand
,
292 CSSMERR_CSP_VERIFY_FAILED
);
295 return testError(quiet
);
297 data
[byte
] = origData
;
300 /* free/delete keys */
301 if(cspFreeKey(cspHand
, &privKey
)) {
302 printf("Error freeing privKey\n");
305 if(cspFreeKey(cspHand
, &pubKey
)) {
306 printf("Error freeing pubKey\n");
313 int main(int argc
, char **argv
)
319 CSSM_CSP_HANDLE CSPHandle
;
320 CSSM_BOOL pubIsRef
= CSSM_TRUE
;
321 CSSM_BOOL privIsRef
= CSSM_TRUE
;
322 CSSM_BOOL stagedSign
;
326 CSSM_ALGORITHMS sigAlg
; // CSSM_ALGID_xxx
327 CSSM_ALGORITHMS keyGenAlg
;
328 unsigned currAlg
; // ALG_xxx
331 CSSM_BOOL genSeed
; // for FEE
332 CSSM_BOOL genParams
; // for DSA
333 CSSM_KEYBLOB_FORMAT pubFormat
= 0;
334 CSSM_KEYBLOB_FORMAT privFormat
= 0;
335 const char *pubFormStr
= "none";
336 const char *privFormStr
= "none";
341 unsigned loops
= LOOPS_DEF
;
342 CSSM_BOOL verbose
= CSSM_FALSE
;
343 unsigned minExp
= MIN_EXP
;
344 unsigned maxExp
= DEFAULT_MAX_EXP
;
345 CSSM_BOOL quiet
= CSSM_FALSE
;
346 CSSM_BOOL randKeySize
= CSSM_FALSE
;
347 uint32 keySizeInBits
= CSP_KEY_SIZE_DEFAULT
;
348 unsigned incr
= INCR_DEFAULT
;
349 unsigned minAlg
= ALG_FIRST
;
350 uint32 maxAlg
= ALG_LAST
;
351 unsigned pauseInterval
= 0;
352 CSSM_BOOL bareCsp
= CSSM_TRUE
;
353 uint32 primeType
= CSSM_FEE_PRIME_TYPE_DEFAULT
; // FEE only
354 uint32 curveType
= CSSM_FEE_CURVE_TYPE_DEFAULT
; // FEE only
355 CSSM_BOOL refKeysOnly
= CSSM_FALSE
;
357 for(arg
=1; arg
<argc
; arg
++) {
366 minAlg
= maxAlg
= ALG_FEE_MD5
;
369 minAlg
= maxAlg
= ALG_FEE_SHA1
;
372 minAlg
= maxAlg
= ALG_ECDSA
;
375 minAlg
= maxAlg
= ALG_ANSI_ECDSA
;
378 minAlg
= maxAlg
= ALG_ECDSA_SHA256
;
381 minAlg
= maxAlg
= ALG_ECDSA_SHA384
;
384 minAlg
= maxAlg
= ALG_ECDSA_SHA512
;
387 minAlg
= maxAlg
= ALG_RSA
;
390 minAlg
= maxAlg
= ALG_DSA
;
393 minAlg
= maxAlg
= ALG_RAW_RSA_SHA1
;
396 minAlg
= maxAlg
= ALG_RAW_DSA_SHA1
;
399 minAlg
= maxAlg
= ALG_RSA_SHA224
;
402 minAlg
= maxAlg
= ALG_RSA_SHA256
;
405 minAlg
= maxAlg
= ALG_RSA_SHA384
;
408 minAlg
= maxAlg
= ALG_RSA_SHA512
;
419 loops
= atoi(&argp
[2]);
422 minExp
= atoi(&argp
[2]);
425 maxExp
= atoi(&argp
[2]);
426 if(maxExp
> MAX_EXP
) {
432 randKeySize
= CSSM_TRUE
;
435 keySizeInBits
= atoi(&argp
[2]);
439 incr
= atoi(&argp
[2]);
442 pauseInterval
= atoi(&argp
[2]);
445 refKeysOnly
= CSSM_TRUE
;
450 curveType
= CSSM_FEE_CURVE_TYPE_MONTGOMERY
;
453 curveType
= CSSM_FEE_CURVE_TYPE_WEIERSTRASS
;
462 primeType
= CSSM_FEE_PRIME_TYPE_MERSENNE
;
465 primeType
= CSSM_FEE_PRIME_TYPE_FEE
;
468 primeType
= CSSM_FEE_PRIME_TYPE_GENERAL
;
475 bareCsp
= CSSM_FALSE
;
476 #if CSPDL_ALL_KEYS_ARE_REF
477 refKeysOnly
= CSSM_TRUE
;
491 ptext
.Data
= (uint8
*)CSSM_MALLOC(MAX_DATA_SIZE
);
492 /* length set in test loop */
493 if(ptext
.Data
== NULL
) {
494 printf("Insufficient heap\n");
497 printf("Starting badsig; args: ");
498 for(i
=1; i
<argc
; i
++) {
499 printf("%s ", argv
[i
]);
502 CSPHandle
= cspDlDbStartup(bareCsp
, NULL
);
506 for(currAlg
=minAlg
; currAlg
<=maxAlg
; currAlg
++) {
509 sigAlg
= CSSM_ALGID_FEE_MD5
;
511 keyGenAlg
= CSSM_ALGID_FEE
;
514 sigAlg
= CSSM_ALGID_FEE_SHA1
;
516 keyGenAlg
= CSSM_ALGID_FEE
;
519 sigAlg
= CSSM_ALGID_SHA1WithECDSA
;
521 keyGenAlg
= CSSM_ALGID_FEE
;
524 sigAlg
= CSSM_ALGID_SHA1WithECDSA
;
525 algStr
= "ANSI_ECDSA";
526 keyGenAlg
= CSSM_ALGID_ECDSA
;
528 case ALG_ECDSA_SHA256
:
529 sigAlg
= CSSM_ALGID_SHA256WithECDSA
;
530 algStr
= "ANSI_ECDSA_SHA256";
531 keyGenAlg
= CSSM_ALGID_ECDSA
;
533 case ALG_ECDSA_SHA384
:
534 sigAlg
= CSSM_ALGID_SHA384WithECDSA
;
535 algStr
= "ANSI_ECDSA_SHA384";
536 keyGenAlg
= CSSM_ALGID_ECDSA
;
538 case ALG_ECDSA_SHA512
:
539 sigAlg
= CSSM_ALGID_SHA512WithECDSA
;
540 algStr
= "ANSI_ECDSA_SHA512";
541 keyGenAlg
= CSSM_ALGID_ECDSA
;
544 sigAlg
= CSSM_ALGID_SHA1WithRSA
;
546 keyGenAlg
= CSSM_ALGID_RSA
;
549 sigAlg
= CSSM_ALGID_SHA1WithDSA
;
551 keyGenAlg
= CSSM_ALGID_DSA
;
553 case ALG_RAW_RSA_SHA1
:
554 sigAlg
= CSSM_ALGID_SHA1
;
555 algStr
= "Raw RSA/SHA1";
556 keyGenAlg
= CSSM_ALGID_RSA
;
558 case ALG_RAW_DSA_SHA1
:
559 sigAlg
= CSSM_ALGID_DSA
;
560 algStr
= "Raw DSA/SHA1";
561 keyGenAlg
= CSSM_ALGID_DSA
;
564 sigAlg
= CSSM_ALGID_SHA224WithRSA
;
565 algStr
= "RSA/SHA224";
566 keyGenAlg
= CSSM_ALGID_RSA
;
569 sigAlg
= CSSM_ALGID_SHA256WithRSA
;
570 algStr
= "RSA/SHA256";
571 keyGenAlg
= CSSM_ALGID_RSA
;
574 sigAlg
= CSSM_ALGID_SHA384WithRSA
;
575 algStr
= "RSA/SHA384";
576 keyGenAlg
= CSSM_ALGID_RSA
;
579 sigAlg
= CSSM_ALGID_SHA512WithRSA
;
580 algStr
= "RSA/SHA512";
581 keyGenAlg
= CSSM_ALGID_RSA
;
584 printf("***BRRZAP! alg parsing needs work.\n");
588 printf("Testing alg %s\n", algStr
);
590 for(loop
=1; ; loop
++) {
591 ptext
.Length
= genData(ptext
.Data
, minExp
, maxExp
, DT_Random
);
593 printf("..loop %d text size %lu\n", loop
, ptext
.Length
);
596 /* adjust increment as appropriate */
597 actualIncr
= (ptext
.Length
/ 50) + 1;
602 /* mix up some ref and data keys, as well as staging */
604 pubIsRef
= (loop
& 1) ? CSSM_TRUE
: CSSM_FALSE
;
605 privIsRef
= (loop
& 2) ? CSSM_TRUE
: CSSM_FALSE
;
608 /* variable alg-specific params */
610 case ALG_RAW_RSA_SHA1
:
611 case ALG_RAW_DSA_SHA1
:
612 /* staging not supported */
617 stagedSign
= (loop
& 4) ? CSSM_TRUE
: CSSM_FALSE
;
618 stagedVfy
= (loop
& 8) ? CSSM_TRUE
: CSSM_FALSE
;
621 genSeed
= CSSM_FALSE
;
627 genSeed
= (ptext
.Data
[0] & 1) ? CSSM_TRUE
: CSSM_FALSE
;
630 case ALG_RAW_DSA_SHA1
:
632 if(bareCsp
|| CSPDL_DSA_GEN_PARAMS
) {
633 /* alternate this one */
634 genParams
= (ptext
.Data
[0] & 2) ? CSSM_TRUE
: CSSM_FALSE
;;
637 /* CSPDL - no gen params */
638 genParams
= CSSM_FALSE
;
645 /* random raw key formats */
646 pubFormat
= CSSM_KEYBLOB_RAW_FORMAT_NONE
;
652 /* NONE, OCTET_STRING */
655 pubFormat
= CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING
;
656 pubFormStr
= "OctetString";
660 /* NONE, PKCS1, X509, OPENSSH, OPENSSHv2 */
664 break; // none/default, set above */
666 pubFormat
= CSSM_KEYBLOB_RAW_FORMAT_PKCS1
;
667 pubFormStr
= "PKCS1";
670 pubFormat
= CSSM_KEYBLOB_RAW_FORMAT_X509
;
674 pubFormat
= CSSM_KEYBLOB_RAW_FORMAT_OPENSSH
;
678 pubFormat
= CSSM_KEYBLOB_RAW_FORMAT_OPENSSH2
;
684 /* NONE, X509, FIPS186, OPENSSHv2 */
688 break; // none/default, set above */
690 pubFormat
= CSSM_KEYBLOB_RAW_FORMAT_X509
;
694 pubFormat
= CSSM_KEYBLOB_RAW_FORMAT_FIPS186
;
695 pubFormStr
= "FIPS186";
698 pubFormat
= CSSM_KEYBLOB_RAW_FORMAT_OPENSSH2
;
703 case CSSM_ALGID_ECDSA
:
704 /* no options - default is CSSM_KEYBLOB_RAW_FORMAT_NONE, X509 */
708 printf("***BRRRZAP! Key alg processing needed\n");
712 privFormat
= CSSM_KEYBLOB_RAW_FORMAT_NONE
;
713 privFormStr
= "None";
718 /* NONE, OCTET_STRING */
721 privFormat
= CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING
;
722 privFormStr
= "OctetString";
726 /* NONE, PKCS1, PKCS8, OPENSSH */
730 break; // none/default, set above */
732 privFormat
= CSSM_KEYBLOB_RAW_FORMAT_PKCS1
;
733 privFormStr
= "PKCS1";
736 privFormat
= CSSM_KEYBLOB_RAW_FORMAT_PKCS8
;
737 privFormStr
= "PKCS8";
740 privFormat
= CSSM_KEYBLOB_RAW_FORMAT_OPENSSH
;
741 privFormStr
= "SSH1";
746 /* NONE, FIPS186, PKCS8 */
750 break; // none/default, set above */
752 privFormat
= CSSM_KEYBLOB_RAW_FORMAT_FIPS186
;
753 privFormStr
= "FIPS186";
756 privFormat
= CSSM_KEYBLOB_RAW_FORMAT_PKCS8
;
757 privFormStr
= "PKCS8";
761 case CSSM_ALGID_ECDSA
:
763 privFormStr
= "PKCS8";
766 printf("***BRRRZAP! Key alg processing needed\n");
772 printf(" pubIsRef %d pubForm %s privIsRef %d privForm %s stagedSign %d stagedVfy %d"
774 (int)pubIsRef
, pubFormStr
, (int)privIsRef
, privFormStr
,
775 (int)stagedSign
, (int)stagedVfy
, (int)genSeed
);
800 if(loops
&& (loop
== loops
)) {
803 if(pauseInterval
&& ((loop
% pauseInterval
) == 0)) {
806 printf("Hit CR to proceed or q to quit: ");
815 CSSM_ModuleDetach(CSPHandle
);
816 if((rtn
== 0) && !quiet
) {
817 printf("%s test complete\n", argv
[0]);