]>
git.saurik.com Git - apple/security.git/blob - SecurityTests/cspxutils/ccSymTest/ccSymTest.cpp
1 /* Copyright (c) 2006,2008 Apple Inc.
3 * ccSymTest.c - test CommonCrypto symmetric encrypt/decrypt.
8 #include <CommonCrypto/CommonCryptor.h>
10 #include <CoreServices/../Frameworks/CarbonCore.framework/Headers/MacErrors.h>
16 #define MIN_DATA_SIZE 8
17 #define MAX_DATA_SIZE 10000 /* bytes */
18 #define MAX_KEY_SIZE kCCKeySizeMaxRC4 /* bytes */
19 #define MAX_BLOCK_SIZE kCCBlockSizeAES128 /* bytes */
20 #define LOOP_NOTIFY 250
23 * Enumerate algs our own way to allow iteration.
26 ALG_AES_128
= 1, /* 128 bit block, 128 bit key */
27 ALG_AES_192
, /* 128 bit block, 192 bit key */
28 ALG_AES_256
, /* 128 bit block, 256 bit key */
33 /* these aren't in CommonCrypto (yet?) */
38 ALG_NULL
/* normally not used */
40 #define ALG_FIRST ALG_AES_128
41 #define ALG_LAST ALG_RC4
46 #define logSize(s) printf s
51 static void usage(char **argv
)
53 printf("usage: %s [options]\n", argv
[0]);
54 printf(" Options:\n");
55 printf(" a=algorithm (d=DES; 3=3DES; a=AES128; n=AES192; A=AES256; \n");
56 printf(" c=CAST; 4=RC4; default=all)\n");
57 printf(" l=loops (default=%d; 0=forever)\n", LOOPS_DEF
);
58 printf(" m=maxPtextSize (default=%d)\n", MAX_DATA_SIZE
);
59 printf(" n=minPtextSize (default=%d)\n", MIN_DATA_SIZE
);
60 printf(" k=keySizeInBytes\n");
61 printf(" p=pauseInterval (default=0, no pause)\n");
62 printf(" o (no padding, well-aligned plaintext)\n");
63 printf(" e (ECB only)\n");
64 printf(" E (CBC only, no ECB)\n");
65 printf(" u (no multi-update ops)\n");
66 printf(" U (only multi-update ops)\n");
67 printf(" x (always allocate context)\n");
68 printf(" X (never allocate context)\n");
69 printf(" v(erbose)\n");
75 static void printCCError(const char *str
, CCCryptorStatus crtn
)
81 case kCCSuccess
: errStr
= "kCCSuccess"; break;
82 case kCCParamError
: errStr
= "kCCParamError"; break;
83 case kCCBufferTooSmall
: errStr
= "kCCBufferTooSmall"; break;
84 case kCCMemoryFailure
: errStr
= "kCCMemoryFailure"; break;
85 case kCCAlignmentError
: errStr
= "kCCAlignmentError"; break;
86 case kCCDecodeError
: errStr
= "kCCDecodeError"; break;
87 case kCCUnimplemented
: errStr
= "kCCUnimplemented"; break;
89 sprintf(unknownStr
, "Unknown(%ld)\n", (long)crtn
);
93 printf("***%s returned %s\n", str
, errStr
);
96 /* max context size */
97 #define CC_MAX_CTX_SIZE kCCContextSizeRC4
100 * We write a marker at end of expected output and at end of caller-allocated
101 * CCCryptorRef, and check at the end to make sure they weren't written
103 #define MARKER_LENGTH 8
104 #define MARKER_BYTE 0x7e
107 * Test harness for CCCryptor with lots of options.
109 CCCryptorStatus
doCCCrypt(
114 const void *keyBytes
, size_t keyLen
,
117 bool inPlace
, /* !doPadding only */
118 size_t ctxSize
, /* if nonzero, we allocate ctx */
120 const uint8_t *inText
, size_t inTextLen
,
121 uint8_t **outText
, size_t *outTextLen
) /* both returned, WE malloc */
123 CCCryptorRef cryptor
= NULL
;
124 CCCryptorStatus crtn
;
125 CCOperation op
= forEncrypt
? kCCEncrypt
: kCCDecrypt
;
126 CCOptions options
= 0;
127 uint8_t *outBuf
= NULL
; /* mallocd output buffer */
128 uint8_t *outp
; /* running ptr into outBuf */
129 const uint8
*inp
; /* running ptr into inText */
130 size_t outLen
; /* bytes remaining in outBuf */
131 size_t toMove
; /* bytes remaining in inText */
132 size_t thisMoveOut
; /* output from CCCryptUpdate()/CCCryptFinal() */
133 size_t outBytes
; /* total bytes actually produced in outBuf */
134 char ctx
[CC_MAX_CTX_SIZE
]; /* for CCCryptorCreateFromData() */
135 uint8_t *textMarker
= NULL
; /* 8 bytes of marker here after expected end of
137 char *ctxMarker
= NULL
; /* ditto for caller-provided context */
139 size_t askedOutSize
; /* from the lib */
140 size_t thisOutLen
; /* dataOutAvailable we use */
142 if(ctxSize
> CC_MAX_CTX_SIZE
) {
143 printf("***HEY! Adjust CC_MAX_CTX_SIZE!\n");
147 options
|= kCCOptionECBMode
;
150 options
|= kCCOptionPKCS7Padding
;
153 /* just hack this one */
156 outLen
+= MAX_BLOCK_SIZE
;
159 outBuf
= (uint8_t *)malloc(outLen
+ MARKER_LENGTH
);
161 /* library should not touch this memory */
162 textMarker
= outBuf
+ outLen
;
163 memset(textMarker
, MARKER_BYTE
, MARKER_LENGTH
);
165 /* subsequent errors to errOut: */
168 memmove(outBuf
, inText
, inTextLen
);
178 crtn
= CCCrypt(op
, encrAlg
, options
,
179 keyBytes
, keyLen
, iv
,
181 outBuf
, 0, &askedOutSize
);
182 if(crtn
!= kCCBufferTooSmall
) {
183 printf("***Did not get kCCBufferTooSmall as expected\n");
184 printf(" alg %d inTextLen %lu cbc %d padding %d keyLen %lu\n",
185 (int)encrAlg
, (unsigned long)inTextLen
, (int)doCbc
, (int)doPadding
,
186 (unsigned long)keyLen
);
187 printCCError("CCCrypt", crtn
);
191 outLen
= askedOutSize
;
193 crtn
= CCCrypt(op
, encrAlg
, options
,
194 keyBytes
, keyLen
, iv
,
196 outBuf
, outLen
, &outLen
);
198 printCCError("CCCrypt", crtn
);
202 *outTextLen
= outLen
;
206 /* random multi updates */
208 size_t ctxSizeCreated
;
211 crtn
= CCCryptorCreateFromData(op
, encrAlg
, options
,
212 keyBytes
, keyLen
, iv
,
213 ctx
, 0 /* ctxSize */,
214 &cryptor
, &askedOutSize
);
215 if(crtn
!= kCCBufferTooSmall
) {
216 printf("***Did not get kCCBufferTooSmall as expected\n");
217 printCCError("CCCryptorCreateFromData", crtn
);
221 ctxSize
= askedOutSize
;
223 crtn
= CCCryptorCreateFromData(op
, encrAlg
, options
,
224 keyBytes
, keyLen
, iv
,
225 ctx
, ctxSize
, &cryptor
, &ctxSizeCreated
);
227 printCCError("CCCryptorCreateFromData", crtn
);
230 ctxMarker
= ctx
+ ctxSizeCreated
;
231 memset(ctxMarker
, MARKER_BYTE
, MARKER_LENGTH
);
234 crtn
= CCCryptorCreate(op
, encrAlg
, options
,
235 keyBytes
, keyLen
, iv
,
238 printCCError("CCCryptorCreate", crtn
);
243 toMove
= inTextLen
; /* total to go */
245 outBytes
= 0; /* bytes actually produced in outBuf */
248 uint32 thisMoveIn
; /* input to CCryptUpdate() */
250 thisMoveIn
= genRand(1, toMove
);
251 logSize(("###ptext segment len %lu\n", (unsigned long)thisMoveIn
));
253 thisOutLen
= CCCryptorGetOutputLength(cryptor
, thisMoveIn
, false);
258 crtn
= CCCryptorUpdate(cryptor
, inp
, thisMoveIn
,
259 outp
, thisOutLen
, &thisMoveOut
);
261 printCCError("CCCryptorUpdate", crtn
);
265 toMove
-= thisMoveIn
;
267 outLen
-= thisMoveOut
;
268 outBytes
+= thisMoveOut
;
272 /* Final is not needed if padding is disabled */
274 thisOutLen
= CCCryptorGetOutputLength(cryptor
, 0, true);
279 crtn
= CCCryptorFinal(cryptor
, outp
, thisOutLen
, &thisMoveOut
);
287 printCCError("CCCryptorFinal", crtn
);
291 outBytes
+= thisMoveOut
;
293 *outTextLen
= outBytes
;
296 for(dex
=0; dex
<MARKER_LENGTH
; dex
++) {
297 if(textMarker
[dex
] != MARKER_BYTE
) {
298 printf("***lib scribbled on our textMarker memory (op=%s)!\n",
299 forEncrypt
? "encrypt" : "decrypt");
300 crtn
= (CCCryptorStatus
)-1;
304 for(dex
=0; dex
<MARKER_LENGTH
; dex
++) {
305 if(ctxMarker
[dex
] != MARKER_BYTE
) {
306 printf("***lib scribbled on our ctxMarker memory (op=%s)!\n",
307 forEncrypt
? "encrypt" : "decrypt");
308 crtn
= (CCCryptorStatus
)-1;
320 CCCryptorRelease(cryptor
);
325 static int doTest(const uint8_t *ptext
,
330 bool nullIV
, /* if CBC, use NULL IV */
331 uint32 keySizeInBytes
,
339 uint8_t keyBytes
[MAX_KEY_SIZE
];
340 uint8_t iv
[MAX_BLOCK_SIZE
];
341 uint8_t *ivPtrEncrypt
;
342 uint8_t *ivPtrDecrypt
;
343 uint8_t *ctext
= NULL
; /* mallocd by doCCCrypt */
345 uint8_t *rptext
= NULL
; /* mallocd by doCCCrypt */
347 CCCryptorStatus crtn
;
351 appGetRandomBytes(keyBytes
, keySizeInBytes
);
353 /* random IV if needed */
356 memset(iv
, 0, MAX_BLOCK_SIZE
);
358 /* flip a coin, give one side NULL, the other size zeroes */
359 if(genRand(1,2) == 1) {
369 appGetRandomBytes(iv
, MAX_BLOCK_SIZE
);
379 crtn
= doCCCrypt(true, encrAlg
, doCbc
, doPadding
,
380 keyBytes
, keySizeInBytes
, ivPtrEncrypt
,
381 stagedEncr
, inPlace
, ctxSize
, askOutSize
,
385 rtn
= testError(quiet
);
391 logSize(("###ctext len %lu\n", ctextLen
));
393 crtn
= doCCCrypt(false, encrAlg
, doCbc
, doPadding
,
394 keyBytes
, keySizeInBytes
, ivPtrDecrypt
,
395 stagedDecr
, inPlace
, ctxSize
, askOutSize
,
397 &rptext
, &rptextLen
);
399 rtn
= testError(quiet
);
405 logSize(("###rptext len %lu\n", rptextLen
));
407 /* compare ptext, rptext */
408 if(ptextLen
!= rptextLen
) {
409 printf("Ptext length mismatch: expect %lu, got %lu\n", ptextLen
, rptextLen
);
410 rtn
= testError(quiet
);
415 if(memcmp(ptext
, rptext
, ptextLen
)) {
416 printf("***data miscompare\n");
417 rtn
= testError(quiet
);
429 bool isBitSet(unsigned bit
, unsigned word
)
432 printf("We don't have that many bits\n");
435 unsigned mask
= 1 << bit
;
436 return (word
& mask
) ? true : false;
439 int main(int argc
, char **argv
)
454 int currAlg
; // ALG_xxx
455 uint32 minKeySizeInBytes
;
456 uint32 maxKeySizeInBytes
;
457 uint32 keySizeInBytes
;
459 uint32 blockSize
; // for noPadding case
460 size_t ctxSize
; // always set per alg
461 size_t ctxSizeUsed
; // passed to doTest
462 bool askOutSize
; // inquire output size each op
467 bool keySizeSpec
= false; // false: use rand key size
468 SymAlg minAlg
= ALG_FIRST
;
469 SymAlg maxAlg
= ALG_LAST
;
470 unsigned loops
= LOOPS_DEF
;
471 bool verbose
= false;
472 size_t minPtextSize
= MIN_DATA_SIZE
;
473 size_t maxPtextSize
= MAX_DATA_SIZE
;
475 unsigned pauseInterval
= 0;
476 bool paddingSpec
= false; // true: user calls doPadding, const
477 bool cbcSpec
= false; // ditto for doCbc
478 bool stagedSpec
= false; // ditto for stagedEncr and stagedDecr
479 bool inPlace
= false; // en/decrypt in place for ECB
480 bool allocCtxSpec
= false; // use allocCtx
481 bool allocCtx
= false; // allocate context ourself
483 for(arg
=1; arg
<argc
; arg
++) {
492 minAlg
= maxAlg
= ALG_ASC
;
495 minAlg
= maxAlg
= ALG_DES
;
498 minAlg
= maxAlg
= ALG_3DES
;
501 minAlg
= maxAlg
= ALG_RC2
;
504 minAlg
= maxAlg
= ALG_RC4
;
507 minAlg
= maxAlg
= ALG_RC5
;
510 minAlg
= maxAlg
= ALG_AES_128
;
513 minAlg
= maxAlg
= ALG_AES_192
;
516 minAlg
= maxAlg
= ALG_AES_256
;
519 minAlg
= maxAlg
= ALG_BFISH
;
522 minAlg
= maxAlg
= ALG_CAST
;
527 if(maxAlg
> ALG_LAST
) {
528 /* we left them in the switch but we can't use them */
533 loops
= atoi(&argp
[2]);
536 minPtextSize
= atoi(&argp
[2]);
539 maxPtextSize
= atoi(&argp
[2]);
542 minKeySizeInBytes
= maxKeySizeInBytes
= atoi(&argp
[2]);
560 pauseInterval
= atoi(&argp
[2]);;
589 ptext
= (uint8
*)malloc(maxPtextSize
);
591 printf("Insufficient heap space\n");
594 /* ptext length set in test loop */
596 printf("Starting ccSymTest; args: ");
597 for(i
=1; i
<argc
; i
++) {
598 printf("%s ", argv
[i
]);
604 printf("Top of test; hit CR to proceed: ");
608 for(currAlg
=minAlg
; currAlg
<=maxAlg
; currAlg
++) {
611 encrAlg
= kCCAlgorithmDES
;
612 blockSize
= kCCBlockSizeDES
;
613 minKeySizeInBytes
= kCCKeySizeDES
;
614 maxKeySizeInBytes
= minKeySizeInBytes
;
615 ctxSize
= kCCContextSizeDES
;
619 encrAlg
= kCCAlgorithm3DES
;
620 blockSize
= kCCBlockSize3DES
;
621 minKeySizeInBytes
= kCCKeySize3DES
;
622 maxKeySizeInBytes
= minKeySizeInBytes
;
623 ctxSize
= kCCContextSize3DES
;
627 encrAlg
= kCCAlgorithmAES128
;
628 blockSize
= kCCBlockSizeAES128
;
629 minKeySizeInBytes
= kCCKeySizeAES128
;
630 maxKeySizeInBytes
= minKeySizeInBytes
;
631 ctxSize
= kCCContextSizeAES128
;
635 encrAlg
= kCCAlgorithmAES128
;
636 blockSize
= kCCBlockSizeAES128
;
637 minKeySizeInBytes
= kCCKeySizeAES192
;
638 maxKeySizeInBytes
= minKeySizeInBytes
;
639 ctxSize
= kCCContextSizeAES128
;
643 encrAlg
= kCCAlgorithmAES128
;
644 blockSize
= kCCBlockSizeAES128
;
645 minKeySizeInBytes
= kCCKeySizeAES256
;
646 maxKeySizeInBytes
= minKeySizeInBytes
;
647 ctxSize
= kCCContextSizeAES128
;
651 encrAlg
= kCCAlgorithmCAST
;
652 blockSize
= kCCBlockSizeCAST
;
653 minKeySizeInBytes
= kCCKeySizeMinCAST
;
654 maxKeySizeInBytes
= kCCKeySizeMaxCAST
;
655 ctxSize
= kCCContextSizeCAST
;
659 encrAlg
= kCCAlgorithmRC4
;
661 minKeySizeInBytes
= kCCKeySizeMinRC4
;
662 maxKeySizeInBytes
= kCCKeySizeMaxRC4
;
663 ctxSize
= kCCContextSizeRC4
;
667 printf("***BRRZAP!\n");
670 if(!quiet
|| verbose
) {
671 printf("Testing alg %s\n", algStr
);
673 for(loop
=1; ; loop
++) {
674 ptextLen
= genRand(minPtextSize
, maxPtextSize
);
675 appGetRandomBytes(ptext
, ptextLen
);
677 /* per-loop settings */
679 if(minKeySizeInBytes
== maxKeySizeInBytes
) {
680 keySizeInBytes
= minKeySizeInBytes
;
683 keySizeInBytes
= genRand(minKeySizeInBytes
, maxKeySizeInBytes
);
693 doCbc
= isBitSet(0, loop
);
696 doPadding
= isBitSet(1, loop
);
699 if(!doPadding
&& (blockSize
!= 0)) {
700 /* align plaintext */
701 ptextLen
= (ptextLen
/ blockSize
) * blockSize
;
703 ptextLen
= blockSize
;
707 stagedEncr
= isBitSet(2, loop
);
708 stagedDecr
= isBitSet(3, loop
);
711 nullIV
= isBitSet(4, loop
);
716 inPlace
= isBitSet(5, loop
);
718 ctxSizeUsed
= allocCtx
? ctxSize
: 0;
720 else if(isBitSet(6, loop
)) {
721 ctxSizeUsed
= ctxSize
;
726 askOutSize
= isBitSet(7, loop
);
728 if(verbose
|| ((loop
% LOOP_NOTIFY
) == 0)) {
729 printf("..loop %3d ptextLen %lu keyLen %d cbc=%d padding=%d stagedEncr=%d "
731 loop
, (unsigned long)ptextLen
, (int)keySizeInBytes
,
732 (int)doCbc
, (int)doPadding
,
733 (int)stagedEncr
, (int)stagedDecr
);
734 printf(" nullIV %d inPlace %d ctxSize %d askOutSize %d\n",
735 (int)nullIV
, (int)inPlace
, (int)ctxSizeUsed
, (int)askOutSize
);
739 if(doTest(ptext
, ptextLen
,
740 encrAlg
, doCbc
, doPadding
, nullIV
,
742 stagedEncr
, stagedDecr
, inPlace
, ctxSizeUsed
, askOutSize
,
747 if(pauseInterval
&& ((loop
% pauseInterval
) == 0)) {
750 printf("Hit CR to proceed, q to abort: ");
756 if(loops
&& (loop
== loops
)) {
769 printf("ModuleDetach/Unload complete; hit CR to exit: ");
772 if((rtn
== 0) && !quiet
) {
773 printf("%s test complete\n", argv
[0]);