/** * @file throughputTest.c * @version $Format:%h%d$ * */ /* * Copyright (c) 2013-2017 Rambus Inc. * Copyright (c) PeerSec Networks, 2002-2011 * All Rights Reserved * * The latest version of this code is available at http://www.matrixssl.org * * This software is open source; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This General Public License does NOT permit incorporating this software * into proprietary programs. If you are unable to comply with the GPL, a * commercial license for this software may be purchased from Rambus at * http://www.rambus.com/ * * This program is distributed in WITHOUT ANY WARRANTY; without even the * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * http://www.gnu.org/copyleft/gpl.html */ /******************************************************************************/ #ifndef _POSIX_C_SOURCE # define _POSIX_C_SOURCE 200112L #endif #ifndef NEED_PS_TIME_CONCRETE # define NEED_PS_TIME_CONCRETE #endif #include "crypto/cryptoImpl.h" #include "osdep_string.h" #include "osdep_stdio.h" #include "osdep-types.h" #define DATABYTES_AMOUNT 100 * 1048576 /* # x 1MB (1024-byte variety) */ #define TINY_CHUNKS 16 #define CHACHA20_TINY_CHUNKS 64 #define SMALL_CHUNKS 256 #define MEDIUM_CHUNKS 1024 #define LARGE_CHUNKS 4096 #define HUGE_CHUNKS 16 * 1024 # ifdef USE_AES_CBC static unsigned char iv[16] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }; static unsigned char key[32] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f }; # endif enum { AES_ENC_ALG = 1, AES_DEC_ALG, AES_GCM_ALG, ARC4_ALG, DES3_ALG, SEED_ALG, IDEA_ALG, AES_HMAC_ALG, AES_HMAC256_ALG, SHA1_ALG, SHA256_ALG, SHA384_ALG, SHA512_ALG, MD5_ALG, CHACHA20POLY1305IETF_ALG }; #if defined(USE_AES_CBC) && (defined(USE_HMAC_SHA1) || defined(USE_HMAC_SHA256)) static void runWithHmac(psCipherContext_t *ctx, psHmac_t *hmac, int32 hashSize, int32 chunk, int32 alg) { psTime_t start, end; unsigned char *dataChunk; int32 bytesSent, bytesToSend, round; unsigned char mac[MAX_HASH_SIZE]; # ifdef USE_HIGHRES_TIME int32 mod; int64 diffu; # else int32 diffm; # endif dataChunk = psMalloc(NULL, chunk); Memset(dataChunk, 0x0, chunk); bytesToSend = (DATABYTES_AMOUNT / chunk) * chunk; bytesSent = 0; switch (alg) { # ifdef USE_AES # ifdef USE_HMAC_SHA1 case AES_HMAC_ALG: psGetTime(&start, NULL); while (bytesSent < bytesToSend) { # ifdef USE_HMAC_TLS static unsigned char hmacKey[64] = { 0, }; unsigned char mac_tmp[20]; psHmacSha1Tls(hmacKey, 20, dataChunk, chunk, NULL, 0, NULL, 0, 0, mac_tmp); # else psHmacSha1Update(&hmac->u.sha1, dataChunk, chunk); # endif # ifdef USE_AES_CBC psAesEncryptCBC(&ctx->aes, dataChunk, dataChunk, chunk); # endif bytesSent += chunk; } psHmacSha1Final(&hmac->u.sha1, mac); psGetTime(&end, NULL); break; # endif # ifdef USE_HMAC_SHA256 case AES_HMAC256_ALG: psGetTime(&start, NULL); while (bytesSent < bytesToSend) { # ifdef USE_HMAC_TLS static unsigned char hmacKey[64] = { 0, }; unsigned char mac_tmp[32]; psHmacSha2Tls(hmacKey, 32, dataChunk, chunk, NULL, 0, NULL, 0, 0, mac_tmp, 32); # else psHmacSha256Update(&hmac->u.sha256, dataChunk, chunk); # endif # ifdef USE_AES_CBC psAesEncryptCBC(&ctx->aes, dataChunk, dataChunk, chunk); # endif bytesSent += chunk; } psHmacSha256Final(&hmac->u.sha256, mac); psGetTime(&end, NULL); break; # endif # endif default: Printf("Skipping HMAC Test\n"); psFree(dataChunk, NULL); return; } # ifdef USE_HIGHRES_TIME diffu = psDiffUsecs(start, end); round = (bytesToSend / diffu); mod = (bytesToSend % diffu); Printf("%d byte chunks in %lld usecs total for rate of %d.%d MB/sec\n", chunk, (unsigned long long) diffu, round, mod); # else diffm = psDiffMsecs(start, end, NULL); round = (bytesToSend / diffm) / 1000; Printf("%d byte chunks in %d msecs total for rate of %d MB/sec\n", chunk, diffm, round); # endif psFree(dataChunk, NULL); } #endif /* USE_AES_CBC && USE_HMAC */ # ifdef USE_AES_CBC static void runTime(psCipherContext_t *ctx, psCipherGivContext_t *ctx_giv, int32 chunk, int32 alg) { psTime_t start, end; unsigned char *dataChunk; int32 bytesSent, bytesToSend, round; #ifdef USE_HIGHRES_TIME int32 mod; int64 diffu; #else int32 diffm; #endif dataChunk = psMalloc(NULL, chunk + 16); Memset(dataChunk, 0x0, chunk); bytesToSend = (DATABYTES_AMOUNT / chunk) * chunk; bytesSent = 0; switch (alg) { #ifdef USE_AES_CBC case AES_ENC_ALG: Printf("Encrypt "); psGetTime(&start, NULL); while (bytesSent < bytesToSend) { psAesEncryptCBC(&ctx->aes, dataChunk, dataChunk, chunk); bytesSent += chunk; } psGetTime(&end, NULL); break; case AES_DEC_ALG: Printf("Decrypt "); psGetTime(&start, NULL); while (bytesSent < bytesToSend) { psAesDecryptCBC(&ctx->aes, dataChunk, dataChunk, chunk); bytesSent += chunk; } psGetTime(&end, NULL); break; #endif #ifdef USE_AES_GCM case AES_GCM_ALG: psGetTime(&start, NULL); while (bytesSent < bytesToSend) { psAesEncryptGCM(&ctx->aesgcm, dataChunk, dataChunk, chunk); bytesSent += chunk; } psAesGetGCMTag(&ctx->aesgcm, 16, dataChunk); psGetTime(&end, NULL); break; #endif #ifdef USE_ARC4 case ARC4_ALG: psGetTime(&start, NULL); while (bytesSent < bytesToSend) { psArc4(&ctx->arc4, dataChunk, dataChunk, chunk); bytesSent += chunk; } psGetTime(&end, NULL); break; #endif #ifdef USE_3DES case DES3_ALG: psGetTime(&start, NULL); while (bytesSent < bytesToSend) { psDes3Encrypt(&ctx->des3, dataChunk, dataChunk, chunk); bytesSent += chunk; } psGetTime(&end, NULL); break; #endif #ifdef USE_SEED case SEED_ALG: psGetTime(&start, NULL); while (bytesSent < bytesToSend) { psSeedEncrypt(&ctx->seed, dataChunk, dataChunk, chunk); bytesSent += chunk; } psGetTime(&end, NULL); break; #endif #ifdef USE_IDEA case IDEA_ALG: psGetTime(&start, NULL); while (bytesSent < bytesToSend) { psIdeaEncrypt(&ctx->idea, dataChunk, dataChunk, chunk); bytesSent += chunk; } psGetTime(&end, NULL); break; #endif #ifdef USE_CHACHA20_POLY1305_IETF case CHACHA20POLY1305IETF_ALG: { static unsigned char chacha20_iv[] = { 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f }; static unsigned char chacha20_aad[] = { 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, }; psGetTime(&start, NULL); while (bytesSent < bytesToSend) { psChacha20Poly1305IetfEncryptDetached( &ctx->chacha20poly1305ietf, dataChunk, chunk, chacha20_iv, chacha20_aad, sizeof chacha20_aad, dataChunk, chacha20_aad); bytesSent += chunk; } psGetTime(&end, NULL); break; } #endif default: psFree(dataChunk, NULL); return; } psFree(dataChunk, NULL); #ifdef USE_HIGHRES_TIME diffu = psDiffUsecs(start, end); round = (bytesToSend / diffu); mod = (bytesToSend % diffu); Printf("%d byte chunks in %lld usecs total for rate of %d.%d MB/sec\n", chunk, (unsigned long long) diffu, round, mod); #else diffm = psDiffMsecs(start, end, NULL); if (diffm > 0) { round = (bytesToSend / diffm) / 1000; Printf("%d byte chunks in %d msecs total for rate of %d MB/sec\n", chunk, diffm, round); } else { diffm = 1; round = (bytesToSend / diffm) / 1000; Printf("%d byte chunks in less than %d msec total for rate of more than %d MB/sec\n", chunk, diffm, round); Printf("Use USE_HIGHRES_TIME for more accurate results.\n"); } #endif } # endif /* USE_AES_CBC */ /******************************************************************************/ #ifdef USE_AES_CBC static int32 psAesTestCBC(void) { int32 err; psCipherContext_t eCtx; # if defined(USE_MATRIX_AES_CBC) && !defined(PS_AES_IMPROVE_PERF_INCREASE_CODESIZE) Printf("##########\n#\n# "); Printf("AES speeds can be improved by enabling\n# "); Printf("PS_AES_IMPROVE_PERF_INCREASE_CODESIZE in cryptoConfig.h\n"); Printf("#\n#\n#########\n"); # endif Printf("***** AES-128 CBC *****\n"); if ((err = psAesInitCBC(&eCtx.aes, iv, key, 16, PS_AES_ENCRYPT)) != PS_SUCCESS) { Printf("FAILED: returned %d\n", err); return err; } runTime(&eCtx, NULL, TINY_CHUNKS, AES_ENC_ALG); runTime(&eCtx, NULL, SMALL_CHUNKS, AES_ENC_ALG); runTime(&eCtx, NULL, MEDIUM_CHUNKS, AES_ENC_ALG); runTime(&eCtx, NULL, LARGE_CHUNKS, AES_ENC_ALG); runTime(&eCtx, NULL, LARGE_CHUNKS, AES_DEC_ALG); runTime(&eCtx, NULL, HUGE_CHUNKS, AES_ENC_ALG); runTime(&eCtx, NULL, HUGE_CHUNKS, AES_DEC_ALG); psAesClearCBC(&eCtx.aes); Printf("***** AES-192 CBC *****\n"); if ((err = psAesInitCBC(&eCtx.aes, iv, key, 24, PS_AES_ENCRYPT)) != PS_SUCCESS) { Printf("FAILED: returned %d\n", err); return err; } runTime(&eCtx, NULL, TINY_CHUNKS, AES_ENC_ALG); runTime(&eCtx, NULL, SMALL_CHUNKS, AES_ENC_ALG); runTime(&eCtx, NULL, MEDIUM_CHUNKS, AES_ENC_ALG); runTime(&eCtx, NULL, LARGE_CHUNKS, AES_ENC_ALG); runTime(&eCtx, NULL, LARGE_CHUNKS, AES_DEC_ALG); runTime(&eCtx, NULL, HUGE_CHUNKS, AES_ENC_ALG); runTime(&eCtx, NULL, HUGE_CHUNKS, AES_DEC_ALG); psAesClearCBC(&eCtx.aes); Printf("***** AES-256 CBC *****\n"); if ((err = psAesInitCBC(&eCtx.aes, iv, key, 32, PS_AES_ENCRYPT)) != PS_SUCCESS) { Printf("FAILED: returned %d\n", err); return err; } runTime(&eCtx, NULL, TINY_CHUNKS, AES_ENC_ALG); runTime(&eCtx, NULL, SMALL_CHUNKS, AES_ENC_ALG); runTime(&eCtx, NULL, MEDIUM_CHUNKS, AES_ENC_ALG); runTime(&eCtx, NULL, LARGE_CHUNKS, AES_ENC_ALG); runTime(&eCtx, NULL, LARGE_CHUNKS, AES_DEC_ALG); runTime(&eCtx, NULL, HUGE_CHUNKS, AES_ENC_ALG); runTime(&eCtx, NULL, HUGE_CHUNKS, AES_DEC_ALG); psAesClearCBC(&eCtx.aes); return 0; } # if defined(USE_HMAC_SHA1) || defined(USE_HMAC_SHA256) static int32 psAesTestCBCHmac(void) { int32 err; psCipherContext_t eCtx; psHmac_t hCtx; # if defined(USE_MATRIX_AES_CBC) && !defined(PS_AES_IMPROVE_PERF_INCREASE_CODESIZE) Printf("##########\n#\n# "); Printf("AES speeds can be improved by enabling\n# "); Printf("PS_AES_IMPROVE_PERF_INCREASE_CODESIZE in cryptoConfig.h\n"); Printf("#\n#\n#########\n"); # endif # ifdef USE_HMAC_SHA1 Printf("***** AES-128 CBC + SHA1-HMAC *****\n"); if ((err = psAesInitCBC(&eCtx.aes, iv, key, 16, PS_AES_ENCRYPT)) != PS_SUCCESS) { Printf("FAILED: returned %d\n", err); return err; } psHmacSha1Init(&hCtx.u.sha1, key, SHA1_HASH_SIZE); runWithHmac(&eCtx, &hCtx, 0, TINY_CHUNKS, AES_HMAC_ALG); psHmacSha1Init(&hCtx.u.sha1, key, SHA1_HASH_SIZE); runWithHmac(&eCtx, &hCtx, 0, SMALL_CHUNKS, AES_HMAC_ALG); psHmacSha1Init(&hCtx.u.sha1, key, SHA1_HASH_SIZE); runWithHmac(&eCtx, &hCtx, 0, MEDIUM_CHUNKS, AES_HMAC_ALG); psHmacSha1Init(&hCtx.u.sha1, key, SHA1_HASH_SIZE); runWithHmac(&eCtx, &hCtx, 0, LARGE_CHUNKS, AES_HMAC_ALG); psHmacSha1Init(&hCtx.u.sha1, key, SHA1_HASH_SIZE); runWithHmac(&eCtx, &hCtx, 0, HUGE_CHUNKS, AES_HMAC_ALG); psAesClearCBC(&eCtx.aes); Printf("***** AES-256 CBC + SHA1-HMAC *****\n"); if ((err = psAesInitCBC(&eCtx.aes, iv, key, 32, PS_AES_ENCRYPT)) != PS_SUCCESS) { Printf("FAILED: returned %d\n", err); return err; } psHmacSha1Init(&hCtx.u.sha1, key, SHA1_HASH_SIZE); runWithHmac(&eCtx, &hCtx, 0, TINY_CHUNKS, AES_HMAC_ALG); psHmacSha1Init(&hCtx.u.sha1, key, SHA1_HASH_SIZE); runWithHmac(&eCtx, &hCtx, 0, SMALL_CHUNKS, AES_HMAC_ALG); psHmacSha1Init(&hCtx.u.sha1, key, SHA1_HASH_SIZE); runWithHmac(&eCtx, &hCtx, 0, MEDIUM_CHUNKS, AES_HMAC_ALG); psHmacSha1Init(&hCtx.u.sha1, key, SHA1_HASH_SIZE); runWithHmac(&eCtx, &hCtx, 0, LARGE_CHUNKS, AES_HMAC_ALG); psHmacSha1Init(&hCtx.u.sha1, key, SHA1_HASH_SIZE); runWithHmac(&eCtx, &hCtx, 0, HUGE_CHUNKS, AES_HMAC_ALG); psAesClearCBC(&eCtx.aes); # endif # ifdef USE_HMAC_SHA256 Printf("***** AES-128 CBC + SHA256-HMAC *****\n"); if ((err = psAesInitCBC(&eCtx.aes, iv, key, 16, PS_AES_ENCRYPT)) != PS_SUCCESS) { Printf("FAILED: returned %d\n", err); return err; } psHmacSha256Init(&hCtx.u.sha256, key, 32); runWithHmac(&eCtx, &hCtx, SHA256_HASH_SIZE, TINY_CHUNKS, AES_HMAC256_ALG); psHmacSha256Init(&hCtx.u.sha256, key, 32); runWithHmac(&eCtx, &hCtx, SHA256_HASH_SIZE, SMALL_CHUNKS, AES_HMAC256_ALG); psHmacSha256Init(&hCtx.u.sha256, key, 32); runWithHmac(&eCtx, &hCtx, SHA256_HASH_SIZE, MEDIUM_CHUNKS, AES_HMAC256_ALG); psHmacSha256Init(&hCtx.u.sha256, key, 32); runWithHmac(&eCtx, &hCtx, SHA256_HASH_SIZE, LARGE_CHUNKS, AES_HMAC256_ALG); psHmacSha256Init(&hCtx.u.sha256, key, 32); runWithHmac(&eCtx, &hCtx, SHA256_HASH_SIZE, HUGE_CHUNKS, AES_HMAC256_ALG); psAesClearCBC(&eCtx.aes); Printf("***** AES-256 CBC + SHA256-HMAC *****\n"); if ((err = psAesInitCBC(&eCtx.aes, iv, key, 32, PS_AES_ENCRYPT)) != PS_SUCCESS) { Printf("FAILED: returned %d\n", err); return err; } psHmacSha256Init(&hCtx.u.sha256, key, 32); runWithHmac(&eCtx, &hCtx, SHA256_HASH_SIZE, TINY_CHUNKS, AES_HMAC256_ALG); psHmacSha256Init(&hCtx.u.sha256, key, 32); runWithHmac(&eCtx, &hCtx, SHA256_HASH_SIZE, SMALL_CHUNKS, AES_HMAC256_ALG); psHmacSha256Init(&hCtx.u.sha256, key, 32); runWithHmac(&eCtx, &hCtx, SHA256_HASH_SIZE, MEDIUM_CHUNKS, AES_HMAC256_ALG); psHmacSha256Init(&hCtx.u.sha256, key, 32); runWithHmac(&eCtx, &hCtx, SHA256_HASH_SIZE, LARGE_CHUNKS, AES_HMAC256_ALG); psHmacSha256Init(&hCtx.u.sha256, key, 32); runWithHmac(&eCtx, &hCtx, SHA256_HASH_SIZE, HUGE_CHUNKS, AES_HMAC256_ALG); psHmacSha256Init(&hCtx.u.sha256, key, 32); psAesClearCBC(&eCtx.aes); # endif return 0; } # endif /* USE_HMAC */ /******************************************************************************/ # ifdef USE_AES_GCM int32 psAesTestGCM(void) { int32 err; psCipherContext_t eCtx; psCipherGivContext_t eCtxGiv; Memset(&eCtxGiv, 0, sizeof(eCtxGiv)); # ifndef USE_LIBSODIUM_AES_GCM Printf("***** AES-GCM-128 *****\n"); if ((err = psAesInitGCM(&eCtx.aesgcm, key, 16)) != PS_SUCCESS) { Printf("FAILED: psAesInitGCM returned %d\n", err); return err; } psAesReadyGCM(&eCtx.aesgcm, iv, iv, 16); runTime(&eCtx, &eCtxGiv, TINY_CHUNKS, AES_GCM_ALG); runTime(&eCtx, &eCtxGiv, SMALL_CHUNKS, AES_GCM_ALG); runTime(&eCtx, &eCtxGiv, MEDIUM_CHUNKS, AES_GCM_ALG); runTime(&eCtx, &eCtxGiv, LARGE_CHUNKS, AES_GCM_ALG); runTime(&eCtx, &eCtxGiv, HUGE_CHUNKS, AES_GCM_ALG); # else Printf("***** Skipping AES-GCM-128 *****\n"); # endif /* !USE_LIBSODIUM */ Printf("***** AES-GCM-256 *****\n"); if ((err = psAesInitGCM(&eCtx.aesgcm, key, 32)) != PS_SUCCESS) { Printf("FAILED: psAesInitGCM returned %d\n", err); return err; } psAesReadyGCM(&eCtx.aesgcm, iv, iv, 16); runTime(&eCtx, &eCtxGiv, TINY_CHUNKS, AES_GCM_ALG); runTime(&eCtx, &eCtxGiv, SMALL_CHUNKS, AES_GCM_ALG); runTime(&eCtx, &eCtxGiv, MEDIUM_CHUNKS, AES_GCM_ALG); runTime(&eCtx, &eCtxGiv, LARGE_CHUNKS, AES_GCM_ALG); runTime(&eCtx, &eCtxGiv, HUGE_CHUNKS, AES_GCM_ALG); psAesClearGCM(&eCtx.aesgcm); return PS_SUCCESS; } # endif /* USE_AES_GCM */ # ifdef USE_AES_CTR int32 psAesTestCTR(void) { return PS_SUCCESS; } # endif /* USE_AES_CTR */ #endif /* USE_AES */ /******************************************************************************/ #ifdef USE_3DES int32 psDes3Test(void) { psCipherContext_t eCtx; # if defined(USE_MATRIX_3DES) && !defined(PS_3DES_IMPROVE_PERF_INCREASE_CODESIZE) Printf("##########\n#\n# "); Printf("3DES speeds can be improved by enabling\n# "); Printf("PS_3DES_IMPROVE_PERF_INCREASE_CODESIZE in cryptoConfig.h\n"); Printf("#\n#\n#########\n"); # endif psDes3Init(&eCtx.des3, iv, key); runTime(&eCtx, NULL, TINY_CHUNKS, DES3_ALG); runTime(&eCtx, NULL, SMALL_CHUNKS, DES3_ALG); runTime(&eCtx, NULL, MEDIUM_CHUNKS, DES3_ALG); runTime(&eCtx, NULL, LARGE_CHUNKS, DES3_ALG); runTime(&eCtx, NULL, HUGE_CHUNKS, DES3_ALG); psDes3Clear(&eCtx.des3); return 0; } #endif /* USE_3DES */ /******************************************************************************/ #ifdef USE_ARC4 int32 psArc4Test(void) { psCipherContext_t eCtx; psArc4Init(&eCtx.arc4, key, 16); runTime(&eCtx, NULL, TINY_CHUNKS, ARC4_ALG); runTime(&eCtx, NULL, SMALL_CHUNKS, ARC4_ALG); runTime(&eCtx, NULL, MEDIUM_CHUNKS, ARC4_ALG); runTime(&eCtx, NULL, LARGE_CHUNKS, ARC4_ALG); runTime(&eCtx, NULL, HUGE_CHUNKS, ARC4_ALG); psArc4Clear(&eCtx.arc4); return 0; } #endif /* USE_ARC4 */ /******************************************************************************/ #ifdef USE_SEED int32 psSeedTest(void) { psCipherContext_t eCtx; psSeedInit(&eCtx.seed, iv, key); runTime(&eCtx, NULL, TINY_CHUNKS, SEED_ALG); runTime(&eCtx, NULL, SMALL_CHUNKS, SEED_ALG); runTime(&eCtx, NULL, MEDIUM_CHUNKS, SEED_ALG); runTime(&eCtx, NULL, LARGE_CHUNKS, SEED_ALG); runTime(&eCtx, NULL, HUGE_CHUNKS, SEED_ALG); psSeedClear(&eCtx.seed); return PS_SUCCESS; } #endif /* USE_SEED */ /******************************************************************************/ #ifdef USE_IDEA int32 psIdeaTest(void) { psCipherContext_t eCtx; psIdeaInit(&eCtx.idea, iv, key); runTime(&eCtx, NULL, TINY_CHUNKS, IDEA_ALG); runTime(&eCtx, NULL, SMALL_CHUNKS, IDEA_ALG); runTime(&eCtx, NULL, MEDIUM_CHUNKS, IDEA_ALG); runTime(&eCtx, NULL, LARGE_CHUNKS, IDEA_ALG); runTime(&eCtx, NULL, HUGE_CHUNKS, IDEA_ALG); psIdeaClear(&eCtx.idea); return PS_SUCCESS; } #endif /* USE_IDEA */ /******************************************************************************/ void runDigestTime(psDigestContext_t *ctx, int32 chunk, int32 alg) { psTime_t start, end; unsigned char *dataChunk; unsigned char hashout[64]; int32 bytesSent, bytesToSend, round; psRes_t rv; #ifdef USE_HIGHRES_TIME int32 mod; int64 diffu; #else int32 diffm; #endif (void)rv; dataChunk = psMalloc(NULL, chunk); bytesToSend = (DATABYTES_AMOUNT / chunk) * chunk; bytesSent = 0; switch (alg) { #ifdef USE_SHA1 case SHA1_ALG: psSha1Init(&ctx->u.sha1); psGetTime(&start, NULL); while (bytesSent < bytesToSend) { psSha1Update(&ctx->u.sha1, dataChunk, chunk); bytesSent += chunk; } psSha1Final(&ctx->u.sha1, hashout); psGetTime(&end, NULL); break; #endif #ifdef USE_SHA256 case SHA256_ALG: psSha256Init(&ctx->u.sha256); psGetTime(&start, NULL); while (bytesSent < bytesToSend) { psSha256Update(&ctx->u.sha256, dataChunk, chunk); bytesSent += chunk; } psSha256Final(&ctx->u.sha256, hashout); psGetTime(&end, NULL); break; #endif #ifdef USE_SHA384 case SHA384_ALG: psSha384Init(&ctx->u.sha384); psGetTime(&start, NULL); while (bytesSent < bytesToSend) { psSha384Update(&ctx->u.sha384, dataChunk, chunk); bytesSent += chunk; } psSha384Final(&ctx->u.sha384, hashout); psGetTime(&end, NULL); break; #endif #ifdef USE_SHA512 case SHA512_ALG: psSha512Init(&ctx->u.sha512); psGetTime(&start, NULL); while (bytesSent < bytesToSend) { psSha512Update(&ctx->u.sha512, dataChunk, chunk); bytesSent += chunk; } psSha512Final(&ctx->u.sha512, hashout); psGetTime(&end, NULL); break; #endif #ifdef USE_MD5 case MD5_ALG: rv = psMd5Init(&ctx->u.md5); if (rv != PS_SUCCESS) goto skipped; psGetTime(&start, NULL); while (bytesSent < bytesToSend) { psMd5Update(&ctx->u.md5, dataChunk, chunk); bytesSent += chunk; } psMd5Final(&ctx->u.md5, hashout); psGetTime(&end, NULL); break; #endif default: #ifdef USE_MD5 skipped: #endif psFree(dataChunk, NULL); Printf("Skipping Digest Tests\n"); return; } #ifdef USE_HIGHRES_TIME diffu = psDiffUsecs(start, end); round = (bytesToSend / diffu); mod = (bytesToSend % diffu); Printf("%d byte chunks in %lld usecs total for rate of %d.%d MB/sec\n", chunk, (unsigned long long) diffu, round, mod); #else diffm = psDiffMsecs(start, end, NULL); round = (bytesToSend / diffm) / 1000; Printf("%d byte chunks in %d msecs total for rate of %d MB/sec\n", chunk, diffm, round); #endif psFree(dataChunk, NULL); } /******************************************************************************/ #ifdef USE_SHA1 int32 psSha1Test(void) { psDigestContext_t ctx; # if defined(USE_MATRIX_SHA1) && !defined(PS_SHA1_IMPROVE_PERF_INCREASE_CODESIZE) Printf("##########\n#\n# "); Printf("SHA-1 speeds can be improved by enabling\n# "); Printf("PS_SHA1_IMPROVE_PERF_INCREASE_CODESIZE in cryptoConfig.h\n"); Printf("#\n#\n#########\n"); # endif runDigestTime(&ctx, TINY_CHUNKS, SHA1_ALG); runDigestTime(&ctx, SMALL_CHUNKS, SHA1_ALG); runDigestTime(&ctx, MEDIUM_CHUNKS, SHA1_ALG); runDigestTime(&ctx, LARGE_CHUNKS, SHA1_ALG); runDigestTime(&ctx, HUGE_CHUNKS, SHA1_ALG); return PS_SUCCESS; } #endif /* USE_SHA1 */ /******************************************************************************/ /******************************************************************************/ #ifdef USE_SHA256 int32 psSha256Test(void) { psDigestContext_t ctx; runDigestTime(&ctx, TINY_CHUNKS, SHA256_ALG); runDigestTime(&ctx, SMALL_CHUNKS, SHA256_ALG); runDigestTime(&ctx, MEDIUM_CHUNKS, SHA256_ALG); runDigestTime(&ctx, LARGE_CHUNKS, SHA256_ALG); runDigestTime(&ctx, HUGE_CHUNKS, SHA256_ALG); return PS_SUCCESS; } #endif /* USE_SHA256 */ /******************************************************************************/ #ifdef USE_SHA384 int32 psSha384Test(void) { psDigestContext_t ctx; runDigestTime(&ctx, TINY_CHUNKS, SHA384_ALG); runDigestTime(&ctx, SMALL_CHUNKS, SHA384_ALG); runDigestTime(&ctx, MEDIUM_CHUNKS, SHA384_ALG); runDigestTime(&ctx, LARGE_CHUNKS, SHA384_ALG); runDigestTime(&ctx, HUGE_CHUNKS, SHA384_ALG); return PS_SUCCESS; } #endif /* USE_SHA384 */ #ifdef USE_SHA512 int32 psSha512Test(void) { psDigestContext_t ctx; runDigestTime(&ctx, TINY_CHUNKS, SHA512_ALG); runDigestTime(&ctx, SMALL_CHUNKS, SHA512_ALG); runDigestTime(&ctx, MEDIUM_CHUNKS, SHA512_ALG); runDigestTime(&ctx, LARGE_CHUNKS, SHA512_ALG); runDigestTime(&ctx, HUGE_CHUNKS, SHA512_ALG); return PS_SUCCESS; } #endif /* USE_SHA512 */ /******************************************************************************/ #ifdef USE_MD5 int32 psMd5Test(void) { psDigestContext_t ctx; # if defined(USE_MATRIX_MD5) && !defined(PS_MD5_IMPROVE_PERF_INCREASE_CODESIZE) Printf("##########\n#\n# "); Printf("MD5 speeds can be improved by enabling\n# "); Printf("PS_MD5_IMPROVE_PERF_INCREASE_CODESIZE in cryptoConfig.h\n"); Printf("#\n#\n#########\n"); # endif runDigestTime(&ctx, TINY_CHUNKS, MD5_ALG); runDigestTime(&ctx, SMALL_CHUNKS, MD5_ALG); runDigestTime(&ctx, MEDIUM_CHUNKS, MD5_ALG); runDigestTime(&ctx, LARGE_CHUNKS, MD5_ALG); runDigestTime(&ctx, HUGE_CHUNKS, MD5_ALG); return PS_SUCCESS; } #endif /* USE_MD5 */ /******************************************************************************/ /******************************************************************************/ #ifdef USE_MD4 int32 psMd4Test(void) { return PS_SUCCESS; } #endif /* USE_MD4 */ /******************************************************************************/ /******************************************************************************/ #ifdef USE_MD2 int32 psMd2Test(void) { return PS_SUCCESS; } #endif /* USE_MD2 */ /******************************************************************************/ # ifdef USE_CHACHA20_POLY1305_IETF static unsigned char chacha20_key[] = { 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f }; int32 psChacha20Poly1305IetfTest(void) { psCipherContext_t cip; psChacha20Poly1305Ietf_t *ctx = &(cip.chacha20poly1305ietf); psChacha20Poly1305IetfInit(ctx, chacha20_key); /* Use sizes starting from CHACHA20 minimum block. */ runTime(&cip, NULL, CHACHA20_TINY_CHUNKS, CHACHA20POLY1305IETF_ALG); runTime(&cip, NULL, SMALL_CHUNKS, CHACHA20POLY1305IETF_ALG); runTime(&cip, NULL, MEDIUM_CHUNKS, CHACHA20POLY1305IETF_ALG); runTime(&cip, NULL, LARGE_CHUNKS, CHACHA20POLY1305IETF_ALG); runTime(&cip, NULL, HUGE_CHUNKS, CHACHA20POLY1305IETF_ALG); return PS_SUCCESS; } # endif /* USE_CHACHA20_POLY1305_IETF */ /******************************************************************************/ typedef struct { int32 (*fn)(void); char name[64]; } test_t; static test_t tests[] = { #ifdef USE_AES_CBC { psAesTestCBC, "***** AES-CBC TESTS *****" }, # if defined(USE_HMAC_SHA1) || defined(USE_HMAC_SHA256) { psAesTestCBCHmac, "***** AES-CBC + HMAC TESTS *****" }, # endif # ifdef USE_AES_GCM { psAesTestGCM, "***** AES-GCM TESTS *****" }, # endif # ifdef USE_AES_CTR { psAesTestCTR, "***** AES-CTR TESTS *****" }, # endif #else { NULL, "AES" }, #endif #ifdef USE_3DES { psDes3Test #else { NULL #endif , "***** 3DES TESTS *****" }, #ifdef USE_SEED { psSeedTest #else { NULL #endif , "***** SEED TESTS *****" }, #ifdef USE_IDEA { psIdeaTest #else { NULL #endif , "***** IDEA TESTS *****" }, #ifdef USE_ARC4 { psArc4Test #else { NULL #endif , "***** RC4 TESTS *****" }, #ifdef USE_SHA1 { psSha1Test #else { NULL #endif , "***** SHA1 TESTS *****" }, #ifdef USE_SHA256 { psSha256Test #else { NULL #endif , "***** SHA256 TESTS *****" }, #ifdef USE_SHA384 { psSha384Test #else { NULL #endif , "***** SHA384 TESTS *****" }, #ifdef USE_SHA512 { psSha512Test #else { NULL #endif , "***** SHA512 TESTS *****" }, #ifdef USE_MD5 { psMd5Test #else { NULL #endif , "***** MD5 TESTS *****" }, #ifdef USE_MD4 { psMd4Test #else { NULL #endif , "***** MD4 TESTS *****" }, #ifdef USE_MD2 { psMd2Test #else { NULL #endif , "***** MD2 TESTS *****" }, #ifdef USE_CHACHA20_POLY1305_IETF { psChacha20Poly1305IetfTest #else { NULL #endif , "***** CHACHA20-POLY1305 *****" }, { NULL, "" } }; /******************************************************************************/ /* Main */ int main(int argc, char **argv) { int32 i; int l; if (argc > 1) { if (!Strcmp(argv[1], "--list")) { Printf("Tests:\n"); for (i = 0; *tests[i].name; i++) { Printf("%s\n", tests[i].name); } return 0; } for(l = 1; l < argc; l++) { for (i = 0; *tests[i].name; i++) { if (Strstr(tests[i].name, argv[l])) { break; } } if (!*tests[i].name) { Fprintf(stderr, "Test not found: %s\n", argv[l]); Fprintf(stderr, "Usage: %s [--list | test...]\n", argv[0]); exit(1); } } } if (psCryptoOpen(PSCRYPTO_CONFIG) < PS_SUCCESS) { Printf("Failed to initialize library: psCryptoOpen failed\n"); return -1; } for (i = 0; *tests[i].name; i++) { for(l = 1; argc > 1 && l < argc; l++) { if (Strstr(tests[i].name, argv[l])) { break; } } if (l == argc && argc > 1) { continue; } if (tests[i].fn) { Printf("%s\n", tests[i].name); tests[i].fn(); } else { Printf("%s: SKIPPED\n", tests[i].name); } } psCryptoClose(); #ifdef WIN32 Printf("Press any key to close"); getchar(); #endif return 0; }