X-Git-Url: https://git.saurik.com/apple/security.git/blobdiff_plain/80e2389990082500d76eb566d4946be3e786c3ef..d8f41ccd20de16f8ebe2ccc84d47bf1cb2b26bbb:/SecurityTests/cspxutils/ccSymTest/ccSymTest.cpp diff --git a/SecurityTests/cspxutils/ccSymTest/ccSymTest.cpp b/SecurityTests/cspxutils/ccSymTest/ccSymTest.cpp new file mode 100644 index 00000000..83401500 --- /dev/null +++ b/SecurityTests/cspxutils/ccSymTest/ccSymTest.cpp @@ -0,0 +1,777 @@ +/* Copyright (c) 2006,2008 Apple Inc. + * + * ccSymTest.c - test CommonCrypto symmetric encrypt/decrypt. + */ +#include +#include +#include +#include +#include "common.h" +#include + +/* + * Defaults. + */ +#define LOOPS_DEF 500 +#define MIN_DATA_SIZE 8 +#define MAX_DATA_SIZE 10000 /* bytes */ +#define MAX_KEY_SIZE kCCKeySizeMaxRC4 /* bytes */ +#define MAX_BLOCK_SIZE kCCBlockSizeAES128 /* bytes */ +#define LOOP_NOTIFY 250 + +/* + * Enumerate algs our own way to allow iteration. + */ +typedef enum { + ALG_AES_128 = 1, /* 128 bit block, 128 bit key */ + ALG_AES_192, /* 128 bit block, 192 bit key */ + ALG_AES_256, /* 128 bit block, 256 bit key */ + ALG_DES, + ALG_3DES, + ALG_CAST, + ALG_RC4, + /* these aren't in CommonCrypto (yet?) */ + ALG_RC2, + ALG_RC5, + ALG_BFISH, + ALG_ASC, + ALG_NULL /* normally not used */ +} SymAlg; +#define ALG_FIRST ALG_AES_128 +#define ALG_LAST ALG_RC4 + + +#define LOG_SIZE 0 +#if LOG_SIZE +#define logSize(s) printf s +#else +#define logSize(s) +#endif + +static void usage(char **argv) +{ + printf("usage: %s [options]\n", argv[0]); + printf(" Options:\n"); + printf(" a=algorithm (d=DES; 3=3DES; a=AES128; n=AES192; A=AES256; \n"); + printf(" c=CAST; 4=RC4; default=all)\n"); + printf(" l=loops (default=%d; 0=forever)\n", LOOPS_DEF); + printf(" m=maxPtextSize (default=%d)\n", MAX_DATA_SIZE); + printf(" n=minPtextSize (default=%d)\n", MIN_DATA_SIZE); + printf(" k=keySizeInBytes\n"); + printf(" p=pauseInterval (default=0, no pause)\n"); + printf(" o (no padding, well-aligned plaintext)\n"); + printf(" e (ECB only)\n"); + printf(" E (CBC only, no ECB)\n"); + printf(" u (no multi-update ops)\n"); + printf(" U (only multi-update ops)\n"); + printf(" x (always allocate context)\n"); + printf(" X (never allocate context)\n"); + printf(" v(erbose)\n"); + printf(" q(uiet)\n"); + printf(" h(elp)\n"); + exit(1); +} + +static void printCCError(const char *str, CCCryptorStatus crtn) +{ + const char *errStr; + char unknownStr[200]; + + switch(crtn) { + case kCCSuccess: errStr = "kCCSuccess"; break; + case kCCParamError: errStr = "kCCParamError"; break; + case kCCBufferTooSmall: errStr = "kCCBufferTooSmall"; break; + case kCCMemoryFailure: errStr = "kCCMemoryFailure"; break; + case kCCAlignmentError: errStr = "kCCAlignmentError"; break; + case kCCDecodeError: errStr = "kCCDecodeError"; break; + case kCCUnimplemented: errStr = "kCCUnimplemented"; break; + default: + sprintf(unknownStr, "Unknown(%ld)\n", (long)crtn); + errStr = unknownStr; + break; + } + printf("***%s returned %s\n", str, errStr); +} + +/* max context size */ +#define CC_MAX_CTX_SIZE kCCContextSizeRC4 + +/* + * We write a marker at end of expected output and at end of caller-allocated + * CCCryptorRef, and check at the end to make sure they weren't written + */ +#define MARKER_LENGTH 8 +#define MARKER_BYTE 0x7e + +/* + * Test harness for CCCryptor with lots of options. + */ +CCCryptorStatus doCCCrypt( + bool forEncrypt, + CCAlgorithm encrAlg, + bool doCbc, + bool doPadding, + const void *keyBytes, size_t keyLen, + const void *iv, + bool randUpdates, + bool inPlace, /* !doPadding only */ + size_t ctxSize, /* if nonzero, we allocate ctx */ + bool askOutSize, + const uint8_t *inText, size_t inTextLen, + uint8_t **outText, size_t *outTextLen) /* both returned, WE malloc */ +{ + CCCryptorRef cryptor = NULL; + CCCryptorStatus crtn; + CCOperation op = forEncrypt ? kCCEncrypt : kCCDecrypt; + CCOptions options = 0; + uint8_t *outBuf = NULL; /* mallocd output buffer */ + uint8_t *outp; /* running ptr into outBuf */ + const uint8 *inp; /* running ptr into inText */ + size_t outLen; /* bytes remaining in outBuf */ + size_t toMove; /* bytes remaining in inText */ + size_t thisMoveOut; /* output from CCCryptUpdate()/CCCryptFinal() */ + size_t outBytes; /* total bytes actually produced in outBuf */ + char ctx[CC_MAX_CTX_SIZE]; /* for CCCryptorCreateFromData() */ + uint8_t *textMarker = NULL; /* 8 bytes of marker here after expected end of + * output */ + char *ctxMarker = NULL; /* ditto for caller-provided context */ + unsigned dex; + size_t askedOutSize; /* from the lib */ + size_t thisOutLen; /* dataOutAvailable we use */ + + if(ctxSize > CC_MAX_CTX_SIZE) { + printf("***HEY! Adjust CC_MAX_CTX_SIZE!\n"); + exit(1); + } + if(!doCbc) { + options |= kCCOptionECBMode; + } + if(doPadding) { + options |= kCCOptionPKCS7Padding; + } + + /* just hack this one */ + outLen = inTextLen; + if(forEncrypt) { + outLen += MAX_BLOCK_SIZE; + } + + outBuf = (uint8_t *)malloc(outLen + MARKER_LENGTH); + + /* library should not touch this memory */ + textMarker = outBuf + outLen; + memset(textMarker, MARKER_BYTE, MARKER_LENGTH); + + /* subsequent errors to errOut: */ + + if(inPlace) { + memmove(outBuf, inText, inTextLen); + inp = outBuf; + } + else { + inp = inText; + } + + if(!randUpdates) { + /* one shot */ + if(askOutSize) { + crtn = CCCrypt(op, encrAlg, options, + keyBytes, keyLen, iv, + inp, inTextLen, + outBuf, 0, &askedOutSize); + if(crtn != kCCBufferTooSmall) { + printf("***Did not get kCCBufferTooSmall as expected\n"); + printf(" alg %d inTextLen %lu cbc %d padding %d keyLen %lu\n", + (int)encrAlg, (unsigned long)inTextLen, (int)doCbc, (int)doPadding, + (unsigned long)keyLen); + printCCError("CCCrypt", crtn); + crtn = -1; + goto errOut; + } + outLen = askedOutSize; + } + crtn = CCCrypt(op, encrAlg, options, + keyBytes, keyLen, iv, + inp, inTextLen, + outBuf, outLen, &outLen); + if(crtn) { + printCCError("CCCrypt", crtn); + goto errOut; + } + *outText = outBuf; + *outTextLen = outLen; + goto errOut; + } + + /* random multi updates */ + if(ctxSize) { + size_t ctxSizeCreated; + + if(askOutSize) { + crtn = CCCryptorCreateFromData(op, encrAlg, options, + keyBytes, keyLen, iv, + ctx, 0 /* ctxSize */, + &cryptor, &askedOutSize); + if(crtn != kCCBufferTooSmall) { + printf("***Did not get kCCBufferTooSmall as expected\n"); + printCCError("CCCryptorCreateFromData", crtn); + crtn = -1; + goto errOut; + } + ctxSize = askedOutSize; + } + crtn = CCCryptorCreateFromData(op, encrAlg, options, + keyBytes, keyLen, iv, + ctx, ctxSize, &cryptor, &ctxSizeCreated); + if(crtn) { + printCCError("CCCryptorCreateFromData", crtn); + return crtn; + } + ctxMarker = ctx + ctxSizeCreated; + memset(ctxMarker, MARKER_BYTE, MARKER_LENGTH); + } + else { + crtn = CCCryptorCreate(op, encrAlg, options, + keyBytes, keyLen, iv, + &cryptor); + if(crtn) { + printCCError("CCCryptorCreate", crtn); + return crtn; + } + } + + toMove = inTextLen; /* total to go */ + outp = outBuf; + outBytes = 0; /* bytes actually produced in outBuf */ + + while(toMove) { + uint32 thisMoveIn; /* input to CCryptUpdate() */ + + thisMoveIn = genRand(1, toMove); + logSize(("###ptext segment len %lu\n", (unsigned long)thisMoveIn)); + if(askOutSize) { + thisOutLen = CCCryptorGetOutputLength(cryptor, thisMoveIn, false); + } + else { + thisOutLen = outLen; + } + crtn = CCCryptorUpdate(cryptor, inp, thisMoveIn, + outp, thisOutLen, &thisMoveOut); + if(crtn) { + printCCError("CCCryptorUpdate", crtn); + goto errOut; + } + inp += thisMoveIn; + toMove -= thisMoveIn; + outp += thisMoveOut; + outLen -= thisMoveOut; + outBytes += thisMoveOut; + } + + if(doPadding) { + /* Final is not needed if padding is disabled */ + if(askOutSize) { + thisOutLen = CCCryptorGetOutputLength(cryptor, 0, true); + } + else { + thisOutLen = outLen; + } + crtn = CCCryptorFinal(cryptor, outp, thisOutLen, &thisMoveOut); + } + else { + thisMoveOut = 0; + crtn = kCCSuccess; + } + + if(crtn) { + printCCError("CCCryptorFinal", crtn); + goto errOut; + } + + outBytes += thisMoveOut; + *outText = outBuf; + *outTextLen = outBytes; + crtn = kCCSuccess; + + for(dex=0; dex 31) { + printf("We don't have that many bits\n"); + exit(1); + } + unsigned mask = 1 << bit; + return (word & mask) ? true : false; +} + +int main(int argc, char **argv) +{ + int arg; + char *argp; + unsigned loop; + uint8 *ptext; + size_t ptextLen; + bool stagedEncr; + bool stagedDecr; + bool doPadding; + bool doCbc; + bool nullIV; + const char *algStr; + CCAlgorithm encrAlg; + int i; + int currAlg; // ALG_xxx + uint32 minKeySizeInBytes; + uint32 maxKeySizeInBytes; + uint32 keySizeInBytes; + int rtn = 0; + uint32 blockSize; // for noPadding case + size_t ctxSize; // always set per alg + size_t ctxSizeUsed; // passed to doTest + bool askOutSize; // inquire output size each op + + /* + * User-spec'd params + */ + bool keySizeSpec = false; // false: use rand key size + SymAlg minAlg = ALG_FIRST; + SymAlg maxAlg = ALG_LAST; + unsigned loops = LOOPS_DEF; + bool verbose = false; + size_t minPtextSize = MIN_DATA_SIZE; + size_t maxPtextSize = MAX_DATA_SIZE; + bool quiet = false; + unsigned pauseInterval = 0; + bool paddingSpec = false; // true: user calls doPadding, const + bool cbcSpec = false; // ditto for doCbc + bool stagedSpec = false; // ditto for stagedEncr and stagedDecr + bool inPlace = false; // en/decrypt in place for ECB + bool allocCtxSpec = false; // use allocCtx + bool allocCtx = false; // allocate context ourself + + for(arg=1; arg ALG_LAST) { + /* we left them in the switch but we can't use them */ + usage(argv); + } + break; + case 'l': + loops = atoi(&argp[2]); + break; + case 'n': + minPtextSize = atoi(&argp[2]); + break; + case 'm': + maxPtextSize = atoi(&argp[2]); + break; + case 'k': + minKeySizeInBytes = maxKeySizeInBytes = atoi(&argp[2]); + keySizeSpec = true; + break; + case 'x': + allocCtxSpec = true; + allocCtx = true; + break; + case 'X': + allocCtxSpec = true; + allocCtx = false; + break; + case 'v': + verbose = true; + break; + case 'q': + quiet = true; + break; + case 'p': + pauseInterval = atoi(&argp[2]);; + break; + case 'o': + doPadding = false; + paddingSpec = true; + break; + case 'e': + doCbc = false; + cbcSpec = true; + break; + case 'E': + doCbc = true; + cbcSpec = true; + break; + case 'u': + stagedEncr = false; + stagedDecr = false; + stagedSpec = true; + break; + case 'U': + stagedEncr = true; + stagedDecr = true; + stagedSpec = true; + break; + case 'h': + default: + usage(argv); + } + } + ptext = (uint8 *)malloc(maxPtextSize); + if(ptext == NULL) { + printf("Insufficient heap space\n"); + exit(1); + } + /* ptext length set in test loop */ + + printf("Starting ccSymTest; args: "); + for(i=1; i