/* * 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); memset(outBuf, 0xEE, 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<MARKER_LENGTH; dex++) { if(textMarker[dex] != MARKER_BYTE) { printf("***lib scribbled on our textMarker memory (op=%s)!\n", forEncrypt ? "encrypt" : "decrypt"); crtn = (CCCryptorStatus)-1; } } if(ctxSize) { for(dex=0; dex<MARKER_LENGTH; dex++) { if(ctxMarker[dex] != MARKER_BYTE) { printf("***lib scribbled on our ctxMarker memory (op=%s)!\n", forEncrypt ? "encrypt" : "decrypt"); crtn = (CCCryptorStatus)-1; } } } errOut: if(crtn) { if(outBuf) { free(outBuf); } } if(cryptor) { CCCryptorRelease(cryptor); } return crtn; }
int main(int argc, char **argv) { unsigned loops = LOOPS_DEF; unsigned bufSize = BUFSIZE_DEF; unsigned algFirst = ALG_FIRST; unsigned algLast = ALG_LAST; bool ecbMode = false; extern char *optarg; int arg; while ((arg = getopt(argc, argv, "a:l:b:eh")) != -1) { switch (arg) { case 'a': switch(optarg[0]) { case 'a': algFirst = algLast = ALG_AES_128; break; case 'n': algFirst = algLast = ALG_AES_192; break; case 'A': algFirst = algLast = ALG_AES_256; break; case 'd': algFirst = algLast = ALG_DES; break; case '3': algFirst = algLast = ALG_3DES; break; case 'c': algFirst = algLast = ALG_CAST; case '4': algFirst = algLast = ALG_RC4; } break; case 'l': loops = atoi(optarg); break; case 'b': bufSize = atoi(optarg); break; case 'e': ecbMode = true; break; case 'h': usage(argv); } } if(optind != argc) { usage(argv); } /* * encrypt and decrypt on workBuf * save original ptext in saveBuf, compare at end as sanity check * for ECB only */ unsigned char *workBuf = (unsigned char *)malloc(bufSize); unsigned char *saveBuf = (unsigned char *)malloc(bufSize); if((workBuf == NULL) || (saveBuf == NULL)) { printf("***malloc failure\n"); exit(1); } appGetRandomBytes(workBuf, bufSize); memmove(saveBuf, workBuf, bufSize); uint8_t keyBytes[MAX_KEY_SIZE]; size_t keyLength; appGetRandomBytes(keyBytes, MAX_KEY_SIZE); CCCryptorRef cryptor; CCAlgorithm alg; CCOptions options = 0; OSStatus ortn; if(ecbMode) { options |= kCCOptionECBMode; } unsigned currAlg; for(currAlg=algFirst; currAlg<=algLast; currAlg++) { const char *algStr = NULL; switch(currAlg) { case ALG_DES: keyLength = kCCKeySizeDES; alg = kCCAlgorithmDES; algStr = "DES "; break; case ALG_3DES: keyLength = kCCKeySize3DES; alg = kCCAlgorithm3DES; algStr = "3DES"; break; case ALG_AES_128: keyLength = kCCKeySizeAES128; alg = kCCAlgorithmAES128; algStr = "AES128"; break; case ALG_AES_192: keyLength = kCCKeySizeAES192; alg = kCCAlgorithmAES128; algStr = "AES192"; break; case ALG_AES_256: keyLength = kCCKeySizeAES256; alg = kCCAlgorithmAES128; algStr = "AES256"; break; case ALG_CAST: keyLength = kCCKeySizeMaxCAST; alg = kCCAlgorithmCAST; algStr = "CAST"; break; case ALG_RC4: keyLength = kCCKeySizeMaxRC4; alg = kCCAlgorithmRC4; algStr = "RC4"; break; } printf("Algorithm: %s keySize: %u mode: %s loops: %u bufSize: %u\n", algStr, (unsigned)keyLength, ecbMode ? "ECB" : "CBC", (unsigned)loops, (unsigned)bufSize); CFAbsoluteTime start, end; unsigned loop; size_t thisMoved; /* encrypt: GO */ start = CFAbsoluteTimeGetCurrent(); ortn = CCCryptorCreate(kCCEncrypt, alg, options, keyBytes, keyLength, NULL, &cryptor); if(ortn) { printCCError("CCCryptorCreate", ortn); exit(1); } for(loop=0; loop<loops; loop++) { ortn = CCCryptorUpdate(cryptor, workBuf, bufSize, workBuf, bufSize, &thisMoved); if(ortn) { printCCError("CCCryptorUpdate", ortn); exit(1); } } /* no padding, CCCryptFinal not needed */ end = CFAbsoluteTimeGetCurrent(); printf(" encrypt %u * %u bytes took %gs: %g KBytes/s\n", (unsigned)loops, (unsigned)bufSize, end - start, (loops * bufSize) / (end - start) / 1024.0); /* dncrypt: GO */ start = CFAbsoluteTimeGetCurrent(); ortn = CCCryptorCreate(kCCDecrypt, alg, options, keyBytes, keyLength, NULL, &cryptor); if(ortn) { printCCError("CCCryptorCreate", ortn); exit(1); } for(loop=0; loop<loops; loop++) { ortn = CCCryptorUpdate(cryptor, workBuf, bufSize, workBuf, bufSize, &thisMoved); if(ortn) { printCCError("CCCryptorUpdate", ortn); exit(1); } } /* no padding, CCCryptFinal not needed */ end = CFAbsoluteTimeGetCurrent(); printf(" decrypt %u * %u bytes took %gs: %g KBytes/s\n", (unsigned)loops, (unsigned)bufSize, end - start, (loops * bufSize) / (end - start) / 1024.0); if(ecbMode) { if(memcmp(workBuf, saveBuf, bufSize)) { printf("***plaintext miscompare!\n"); } } } return 0; }