/* min <= return <= max */ static unsigned genRand(unsigned min, unsigned max) { unsigned i; if(min == max) { return min; } appGetRandomBytes(&i, 4); return (min + (i % (max - min + 1))); }
int main(int argc, char **argv) { int arg; char *argp; unsigned loop; uint8 *ptext; size_t ptextLen; bool stagedEncr = false; bool stagedDecr = false; bool doPadding; bool doCbc = false; bool nullIV; const char *algStr; CCAlgorithm encrAlg; int i; int currAlg; // ALG_xxx uint32 minKeySizeInBytes; uint32 maxKeySizeInBytes; uint32 keySizeInBytes = 0; 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<argc; arg++) { argp = argv[arg]; switch(argp[0]) { case 'a': if(argp[1] != '=') { usage(argv); } switch(argp[2]) { case 's': minAlg = maxAlg = ALG_ASC; break; case 'd': minAlg = maxAlg = ALG_DES; break; case '3': minAlg = maxAlg = ALG_3DES; break; case '2': minAlg = maxAlg = ALG_RC2; break; case '4': minAlg = maxAlg = ALG_RC4; break; case '5': minAlg = maxAlg = ALG_RC5; break; case 'a': minAlg = maxAlg = ALG_AES_128; break; case 'n': minAlg = maxAlg = ALG_AES_192; break; case 'A': minAlg = maxAlg = ALG_AES_256; break; case 'b': minAlg = maxAlg = ALG_BFISH; break; case 'c': minAlg = maxAlg = ALG_CAST; break; default: usage(argv); } if(maxAlg > 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<argc; i++) { printf("%s ", argv[i]); } printf("\n"); if(pauseInterval) { fpurge(stdin); printf("Top of test; hit CR to proceed: "); getchar(); } for(currAlg=minAlg; currAlg<=maxAlg; currAlg++) { switch(currAlg) { case ALG_DES: encrAlg = kCCAlgorithmDES; blockSize = kCCBlockSizeDES; minKeySizeInBytes = kCCKeySizeDES; maxKeySizeInBytes = minKeySizeInBytes; ctxSize = kCCContextSizeDES; algStr = "DES"; break; case ALG_3DES: encrAlg = kCCAlgorithm3DES; blockSize = kCCBlockSize3DES; minKeySizeInBytes = kCCKeySize3DES; maxKeySizeInBytes = minKeySizeInBytes; ctxSize = kCCContextSize3DES; algStr = "3DES"; break; case ALG_AES_128: encrAlg = kCCAlgorithmAES128; blockSize = kCCBlockSizeAES128; minKeySizeInBytes = kCCKeySizeAES128; maxKeySizeInBytes = minKeySizeInBytes; ctxSize = kCCContextSizeAES128; algStr = "AES128"; break; case ALG_AES_192: encrAlg = kCCAlgorithmAES128; blockSize = kCCBlockSizeAES128; minKeySizeInBytes = kCCKeySizeAES192; maxKeySizeInBytes = minKeySizeInBytes; ctxSize = kCCContextSizeAES128; algStr = "AES192"; break; case ALG_AES_256: encrAlg = kCCAlgorithmAES128; blockSize = kCCBlockSizeAES128; minKeySizeInBytes = kCCKeySizeAES256; maxKeySizeInBytes = minKeySizeInBytes; ctxSize = kCCContextSizeAES128; algStr = "AES256"; break; case ALG_CAST: encrAlg = kCCAlgorithmCAST; blockSize = kCCBlockSizeCAST; minKeySizeInBytes = kCCKeySizeMinCAST; maxKeySizeInBytes = kCCKeySizeMaxCAST; ctxSize = kCCContextSizeCAST; algStr = "CAST"; break; case ALG_RC4: encrAlg = kCCAlgorithmRC4; blockSize = 0; minKeySizeInBytes = kCCKeySizeMinRC4; maxKeySizeInBytes = kCCKeySizeMaxRC4; ctxSize = kCCContextSizeRC4; algStr = "RC4"; break; default: printf("***BRRZAP!\n"); exit(1); } if(!quiet || verbose) { printf("Testing alg %s\n", algStr); } for(loop=1; ; loop++) { ptextLen = genRand(minPtextSize, maxPtextSize); appGetRandomBytes(ptext, ptextLen); /* per-loop settings */ if(!keySizeSpec) { if(minKeySizeInBytes == maxKeySizeInBytes) { keySizeInBytes = minKeySizeInBytes; } else { keySizeInBytes = genRand(minKeySizeInBytes, maxKeySizeInBytes); } } if(blockSize == 0) { /* stream cipher */ doCbc = false; doPadding = false; } else { if(!cbcSpec) { doCbc = isBitSet(0, loop); } if(!paddingSpec) { doPadding = isBitSet(1, loop); } } if(!doPadding && (blockSize != 0)) { /* align plaintext */ ptextLen = (ptextLen / blockSize) * blockSize; if(ptextLen == 0) { ptextLen = blockSize; } } if(!stagedSpec) { stagedEncr = isBitSet(2, loop); stagedDecr = isBitSet(3, loop); } if(doCbc) { nullIV = isBitSet(4, loop); } else { nullIV = false; } inPlace = isBitSet(5, loop); if(allocCtxSpec) { ctxSizeUsed = allocCtx ? ctxSize : 0; } else if(isBitSet(6, loop)) { ctxSizeUsed = ctxSize; } else { ctxSizeUsed = 0; } askOutSize = isBitSet(7, loop); if(!quiet) { if(verbose || ((loop % LOOP_NOTIFY) == 0)) { printf("..loop %3d ptextLen %lu keyLen %d cbc=%d padding=%d stagedEncr=%d " "stagedDecr=%d\n", loop, (unsigned long)ptextLen, (int)keySizeInBytes, (int)doCbc, (int)doPadding, (int)stagedEncr, (int)stagedDecr); printf(" nullIV %d inPlace %d ctxSize %d askOutSize %d\n", (int)nullIV, (int)inPlace, (int)ctxSizeUsed, (int)askOutSize); } } if(doTest(ptext, ptextLen, encrAlg, doCbc, doPadding, nullIV, keySizeInBytes, stagedEncr, stagedDecr, inPlace, ctxSizeUsed, askOutSize, quiet)) { rtn = 1; break; } if(pauseInterval && ((loop % pauseInterval) == 0)) { char c; fpurge(stdin); printf("Hit CR to proceed, q to abort: "); c = getchar(); if(c == 'q') { goto testDone; } } if(loops && (loop == loops)) { break; } } /* main loop */ if(rtn) { break; } } /* for algs */ testDone: if(pauseInterval) { fpurge(stdin); printf("ModuleDetach/Unload complete; hit CR to exit: "); getchar(); } if((rtn == 0) && !quiet) { printf("%s test complete\n", argv[0]); } free(ptext); return rtn; }
static int doTest(const uint8_t *ptext, size_t ptextLen, CCAlgorithm encrAlg, bool doCbc, bool doPadding, bool nullIV, /* if CBC, use NULL IV */ uint32 keySizeInBytes, bool stagedEncr, bool stagedDecr, bool inPlace, size_t ctxSize, bool askOutSize, bool quiet) { uint8_t keyBytes[MAX_KEY_SIZE]; uint8_t iv[MAX_BLOCK_SIZE]; uint8_t *ivPtrEncrypt; uint8_t *ivPtrDecrypt; uint8_t *ctext = NULL; /* mallocd by doCCCrypt */ size_t ctextLen = 0; uint8_t *rptext = NULL; /* mallocd by doCCCrypt */ size_t rptextLen; CCCryptorStatus crtn; int rtn = 0; /* random key */ appGetRandomBytes(keyBytes, keySizeInBytes); /* random IV if needed */ if(doCbc) { if(nullIV) { memset(iv, 0, MAX_BLOCK_SIZE); /* flip a coin, give one side NULL, the other size zeroes */ if(genRand(1,2) == 1) { ivPtrEncrypt = NULL; ivPtrDecrypt = iv; } else { ivPtrEncrypt = iv; ivPtrDecrypt = NULL; } } else { appGetRandomBytes(iv, MAX_BLOCK_SIZE); ivPtrEncrypt = iv; ivPtrDecrypt = iv; } } else { ivPtrEncrypt = NULL; ivPtrDecrypt = NULL; } crtn = doCCCrypt(true, encrAlg, doCbc, doPadding, keyBytes, keySizeInBytes, ivPtrEncrypt, stagedEncr, inPlace, ctxSize, askOutSize, ptext, ptextLen, &ctext, &ctextLen); if(crtn) { rtn = testError(quiet); if(rtn) { goto abort; } } logSize(("###ctext len %lu\n", ctextLen)); crtn = doCCCrypt(false, encrAlg, doCbc, doPadding, keyBytes, keySizeInBytes, ivPtrDecrypt, stagedDecr, inPlace, ctxSize, askOutSize, ctext, ctextLen, &rptext, &rptextLen); if(crtn) { rtn = testError(quiet); if(rtn) { goto abort; } } logSize(("###rptext len %lu\n", rptextLen)); /* compare ptext, rptext */ if(ptextLen != rptextLen) { printf("Ptext length mismatch: expect %lu, got %lu\n", ptextLen, rptextLen); rtn = testError(quiet); if(rtn) { goto abort; } } if(memcmp(ptext, rptext, ptextLen)) { printf("***data miscompare\n"); rtn = testError(quiet); } abort: if(ctext) { free(ctext); } if(rptext) { free(rptext); } return rtn; }
int main(int argc, char **argv) { RingBuffer serverToClientRing; RingBuffer clientToServerRing; unsigned numBufs = DEFAULT_NUM_BUFS; unsigned bufSize = DEFAULT_BUF_SIZE; unsigned chunkSize = DEFAULT_CHUNK; unsigned char clientBuf[DEFAULT_CHUNK]; unsigned char serverBuf[DEFAULT_CHUNK]; RingBufferArgs clientArgs; RingBufferArgs serverArgs; bool abortFlag = false; pthread_t client_thread = NULL; int result; OSStatus ortn; unsigned char sessionTicket[SESSION_TICKET_SIZE]; int ourRtn = 0; CFArrayRef idArray = NULL; /* for SSLSetCertificate */ CFArrayRef anchorArray = NULL; /* trusted roots */ char *hostName = NULL; /* user-spec'd variables */ char *kcName = NULL; unsigned xferSize = DEFAULT_XFER; bool pauseOnError = false; bool runForever = false; bool skipPAC = false; extern int optind; extern char *optarg; int arg; optind = 1; while ((arg = getopt(argc, argv, "x:c:k:h:np")) != -1) { switch (arg) { case 'x': { unsigned xsize = atoi(optarg); if(xsize == 0) { runForever = true; /* and leave xferSize alone */ } else { xferSize = xsize; } break; } case 'k': kcName = optarg; break; case 'n': skipPAC = true; break; case 'h': /* mainly to test EAP session ticket and ServerName simultaneously */ hostName = optarg; break; case 'p': pauseOnError = true; break; default: usage(argv); } } if(optind != argc) { usage(argv); } /* set up ring buffers */ ringBufSetup(&serverToClientRing, "serveToClient", numBufs, bufSize); ringBufSetup(&clientToServerRing, "clientToServe", numBufs, bufSize); /* get optional server SecIdentity */ if(kcName) { SecKeychainRef kcRef = NULL; SecCertificateRef anchorCert = NULL; SecIdentityRef idRef = NULL; idArray = getSslCerts(kcName, CSSM_FALSE, /* encryptOnly */ CSSM_FALSE, /* completeCertChain */ NULL, /* anchorFile */ &kcRef); if(idArray == NULL) { printf("***Can't get signing cert from %s\n", kcName); exit(1); } idRef = (SecIdentityRef)CFArrayGetValueAtIndex(idArray, 0); ortn = SecIdentityCopyCertificate(idRef, &anchorCert); if(ortn) { cssmPerror("SecIdentityCopyCertificate", ortn); exit(1); } anchorArray = CFArrayCreate(NULL, (const void **)&anchorCert, 1, &kCFTypeArrayCallBacks); CFRelease(kcRef); CFRelease(anchorCert); } /* set up server side */ memset(&serverArgs, 0, sizeof(serverArgs)); serverArgs.xferSize = xferSize; serverArgs.xferBuf = serverBuf; serverArgs.chunkSize = chunkSize; serverArgs.ringWrite = &serverToClientRing; serverArgs.ringRead = &clientToServerRing; serverArgs.goFlag = &clientArgs.iAmReady; serverArgs.abortFlag = &abortFlag; serverArgs.pauseOnError = pauseOnError; appGetRandomBytes(serverArgs.sharedSecret, SHARED_SECRET_SIZE); if(!skipPAC) { serverArgs.setMasterSecret = true; } serverArgs.idArray = idArray; serverArgs.trustedRoots = anchorArray; /* set up client side */ memset(&clientArgs, 0, sizeof(clientArgs)); clientArgs.xferSize = xferSize; clientArgs.xferBuf = clientBuf; clientArgs.chunkSize = chunkSize; clientArgs.ringWrite = &clientToServerRing; clientArgs.ringRead = &serverToClientRing; clientArgs.goFlag = &serverArgs.iAmReady; clientArgs.abortFlag = &abortFlag; clientArgs.pauseOnError = pauseOnError; memmove(clientArgs.sharedSecret, serverArgs.sharedSecret, SHARED_SECRET_SIZE); clientArgs.hostName = hostName; /* for now set up an easily recognizable ticket */ for(unsigned dex=0; dex<SESSION_TICKET_SIZE; dex++) { sessionTicket[dex] = dex; } clientArgs.sessionTicket = sessionTicket; clientArgs.sessionTicketLen = SESSION_TICKET_SIZE; /* client always tries setting the master secret in this test */ clientArgs.setMasterSecret = true; clientArgs.trustedRoots = anchorArray; /* fire up client thread */ result = pthread_create(&client_thread, NULL, rbClientThread, &clientArgs); if(result) { printf("***pthread_create returned %d, aborting\n", result); exit(1); } /* * And the server pseudo thread. This returns when all data has been transferred. */ ortn = rbServerThread(&serverArgs); if(abortFlag) { printf("***Test aborted.\n"); exit(1); } printf("\n"); printf("SSL Protocol Version : %s\n", sslGetProtocolVersionString(serverArgs.negotiatedProt)); printf("SSL Cipher : %s\n", sslGetCipherSuiteString(serverArgs.negotiatedCipher)); if(skipPAC) { if(clientArgs.sessionWasResumed) { printf("***skipPAC true, but client reported sessionWasResumed\n"); ourRtn = -1; } if(serverArgs.sessionWasResumed) { printf("***skipPAC true, but server reported sessionWasResumed\n"); ourRtn = -1; } if(ourRtn == 0) { printf("...PAC session attempted by client; refused by server;\n"); printf(" Normal session proceeded correctly.\n"); } } else { if(!clientArgs.sessionWasResumed) { printf("***client reported !sessionWasResumed\n"); ourRtn = -1; } if(!serverArgs.sessionWasResumed) { printf("***server reported !sessionWasResumed\n"); ourRtn = -1; } if(memcmp(clientBuf, serverBuf, DEFAULT_CHUNK)) { printf("***Data miscompare***\n"); ourRtn = -1; } if(ourRtn == 0) { printf("...PAC session resumed correctly.\n"); } } /* FIXME other stuff? */ return ourRtn; }
int CommonCryptoSymRegression(int argc, char *const *argv) { unsigned loop; uint8_t *ptext; size_t ptextLen; bool stagedEncr = false; bool stagedDecr = false; bool doPadding; bool doCbc = false; bool nullIV; const char *algStr; CCAlgorithm encrAlg; int i; int currAlg; // ALG_xxx uint32_t minKeySizeInBytes; uint32_t maxKeySizeInBytes; uint32_t keySizeInBytes = 0; int rtn = 0; uint32_t 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 = true; 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 plan_tests(kTestTestCount); ptext = (uint8_t *)malloc(maxPtextSize); if(ptext == NULL) { diag("Insufficient heap space\n"); exit(1); } /* ptext length set in test loop */ if(!quiet) diag("Starting ccSymTest; args: "); for(i=1; i<argc; i++) { if(!quiet) diag("%s ", argv[i]); } if(!quiet) diag("\n"); if(pauseInterval) { fpurge(stdin); diag("Top of test; hit CR to proceed: "); getchar(); } for(currAlg=minAlg; currAlg<=maxAlg; currAlg++) { switch(currAlg) { case ALG_DES: encrAlg = kCCAlgorithmDES; blockSize = kCCBlockSizeDES; minKeySizeInBytes = kCCKeySizeDES; maxKeySizeInBytes = minKeySizeInBytes; ctxSize = kCCContextSizeDES; algStr = "DES"; diag("Running DES Tests"); break; case ALG_3DES: encrAlg = kCCAlgorithm3DES; blockSize = kCCBlockSize3DES; minKeySizeInBytes = kCCKeySize3DES; maxKeySizeInBytes = minKeySizeInBytes; ctxSize = kCCContextSize3DES; algStr = "3DES"; diag("Running 3DES Tests"); break; case ALG_AES_128: encrAlg = kCCAlgorithmAES128; blockSize = kCCBlockSizeAES128; minKeySizeInBytes = kCCKeySizeAES128; maxKeySizeInBytes = minKeySizeInBytes; ctxSize = kCCContextSizeAES128; algStr = "AES128"; diag("Running AES (128 bit key) Tests"); break; case ALG_AES_192: encrAlg = kCCAlgorithmAES128; blockSize = kCCBlockSizeAES128; minKeySizeInBytes = kCCKeySizeAES192; maxKeySizeInBytes = minKeySizeInBytes; ctxSize = kCCContextSizeAES128; algStr = "AES192"; diag("Running AES (192 bit key) Tests"); break; case ALG_AES_256: encrAlg = kCCAlgorithmAES128; blockSize = kCCBlockSizeAES128; minKeySizeInBytes = kCCKeySizeAES256; maxKeySizeInBytes = minKeySizeInBytes; ctxSize = kCCContextSizeAES128; algStr = "AES256"; diag("Running AES (256 bit key) Tests"); break; case ALG_CAST: encrAlg = kCCAlgorithmCAST; blockSize = kCCBlockSizeCAST; minKeySizeInBytes = kCCKeySizeMinCAST; maxKeySizeInBytes = kCCKeySizeMaxCAST; ctxSize = kCCContextSizeCAST; algStr = "CAST"; diag("Running CAST Tests"); break; case ALG_RC4: encrAlg = kCCAlgorithmRC4; blockSize = 0; minKeySizeInBytes = kCCKeySizeMinRC4; maxKeySizeInBytes = kCCKeySizeMaxRC4; ctxSize = kCCContextSizeRC4; algStr = "RC4"; diag("Running RC4 Tests"); break; default: diag("***BRRZAP!\n"); exit(1); } if(!quiet || verbose) { diag("Testing alg %s\n", algStr); } for(loop=1; ; loop++) { ptextLen = (size_t) genRand((unsigned int) minPtextSize, (unsigned int) maxPtextSize); appGetRandomBytes(ptext, ptextLen); /* per-loop settings */ if(!keySizeSpec) { if(minKeySizeInBytes == maxKeySizeInBytes) { keySizeInBytes = minKeySizeInBytes; } else { keySizeInBytes = genRand(minKeySizeInBytes, maxKeySizeInBytes); } } if(blockSize == 0) { /* stream cipher */ doCbc = false; doPadding = false; } else { if(!cbcSpec) { doCbc = isBitSet(0, loop); } if(!paddingSpec) { doPadding = isBitSet(1, loop); } } if(!doPadding && (blockSize != 0)) { /* align plaintext */ ptextLen = (ptextLen / blockSize) * blockSize; if(ptextLen == 0) { ptextLen = blockSize; } } if(!stagedSpec) { stagedEncr = isBitSet(2, loop); stagedDecr = isBitSet(3, loop); } if(doCbc) { nullIV = isBitSet(4, loop); } else { nullIV = false; } inPlace = isBitSet(5, loop); if(allocCtxSpec) { ctxSizeUsed = allocCtx ? ctxSize : 0; } else if(isBitSet(6, loop)) { ctxSizeUsed = ctxSize; } else { ctxSizeUsed = 0; } askOutSize = isBitSet(7, loop); if(!quiet) { if(verbose || ((loop % LOOP_NOTIFY) == 0)) { diag("..loop %3d ptextLen %lu keyLen %d cbc=%d padding=%d stagedEncr=%d " "stagedDecr=%d\n", loop, (unsigned long)ptextLen, (int)keySizeInBytes, (int)doCbc, (int)doPadding, (int)stagedEncr, (int)stagedDecr); diag(" nullIV %d inPlace %d ctxSize %d askOutSize %d\n", (int)nullIV, (int)inPlace, (int)ctxSizeUsed, (int)askOutSize); } } if(doTest(ptext, ptextLen, encrAlg, doCbc, doPadding, nullIV, keySizeInBytes, stagedEncr, stagedDecr, inPlace, ctxSizeUsed, askOutSize, quiet)) { rtn = 1; break; } if(pauseInterval && ((loop % pauseInterval) == 0)) { char c; fpurge(stdin); diag("Hit CR to proceed, q to abort: "); c = getchar(); if(c == 'q') { goto testDone; } } if(loops && (loop == loops)) { break; } } /* main loop */ if(rtn) { break; } } /* for algs */ testDone: ok(rtn == 0, "ccSymTest"); if(pauseInterval) { fpurge(stdin); diag("ModuleDetach/Unload complete; hit CR to exit: "); getchar(); } if((rtn == 0) && !quiet) { diag("%s test complete\n", argv[0]); } free(ptext); return rtn; }
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; }