*/
#include "aes.h"
+#include "arcfour.h"
+#include "blowfish.h"
+#include "cast128.h"
+#include "des.h"
+#include "serpent.h"
+#include "twofish.h"
+
#include "cbc.h"
+#include <assert.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
-/* Encrypt 1MB, 1K at a time. */
-#define BENCH_SIZE 1024
+/* Encrypt 100MB, 1K at a time. */
+#define BENCH_BLOCK 1024
+#define BENCH_COUNT 10240
typedef void (*crypt_func)(void *ctx,
unsigned length, uint8_t *dst,
const uint8_t *src);
+
+typedef void (*setkey_func)(void *ctx,
+ unsigned length,
+ const uint8_t *key);
+
static double
time_function(void (*f)(void *arg), void *arg)
{
struct bench_cipher_info *info = arg;
unsigned i;
- for (i = 0; i<BENCH_SIZE; i++)
- info->crypt(info->ctx, BENCH_SIZE, info->data, info->data);
+ for (i = 0; i<BENCH_COUNT; i++)
+ info->crypt(info->ctx, BENCH_BLOCK, info->data, info->data);
}
struct bench_cbc_info
struct bench_cbc_info *info = arg;
unsigned i;
- for (i = 0; i<BENCH_SIZE; i++)
+ for (i = 0; i<BENCH_COUNT; i++)
cbc_encrypt(info->ctx, info->crypt,
info->block_size, info->iv,
- BENCH_SIZE, info->data, info->data);
+ BENCH_BLOCK, info->data, info->data);
}
static void
struct bench_cbc_info *info = arg;
unsigned i;
- for (i = 0; i<BENCH_SIZE; i++)
+ for (i = 0; i<BENCH_COUNT; i++)
cbc_decrypt(info->ctx, info->crypt,
info->block_size, info->iv,
- BENCH_SIZE, info->data, info->data);
+ BENCH_BLOCK, info->data, info->data);
}
/* Set data[i] = floor(sqrt(i)) */
init_data(uint8_t *data)
{
unsigned i,j;
- for (i = j = 0; i<BENCH_SIZE; i++)
+ for (i = j = 0; i<BENCH_BLOCK; i++)
{
if (j*j < i)
j++;
}
static void
-bench(const char *name, void (*f)(void *), void *arg)
+init_key(unsigned length,
+ uint8_t *key)
{
- printf("%15s: %f\n", name, time_function(f, arg));
+ unsigned i;
+ for (i = 0; i<length; i++)
+ key[i] = i;
}
-int
-main(int argc, char **argv)
+struct cipher
{
- /* Time block ciphers */
- uint8_t iv[AES_BLOCK_SIZE];
- uint8_t key[AES_MAX_KEY_SIZE];
+ const char *name;
+ unsigned context_size;
- uint8_t data[BENCH_SIZE];
+ unsigned block_size;
+ unsigned key_size;
+
+ setkey_func setkey;
+ crypt_func encrypt;
+ crypt_func decrypt;
+};
+
+
+static void
+time_cipher(struct cipher *cipher)
+{
+ void *ctx = alloca(cipher->context_size);
+ uint8_t *key = alloca(cipher->key_size);
+
+ uint8_t data[BENCH_BLOCK];
+
+ printf("\n");
+
+ init_data(data);
{
- struct aes_ctx ctx;
struct bench_cipher_info info
- = { &ctx, (crypt_func) aes_encrypt, data };
+ = { ctx, cipher->encrypt, data };
- memset(key, 0, sizeof(key));
-
- aes_set_key(&ctx, sizeof(key), key);
- init_data(data);
-
- bench("AES (ECB encrypt)", bench_cipher, &info);
+ init_key(cipher->key_size, key);
+ cipher->setkey(ctx, cipher->key_size, key);
+
+ printf("%13s (ECB encrypt): %f\n", cipher->name,
+ time_function(bench_cipher, &info));
}
-
+
{
- struct aes_ctx ctx;
struct bench_cipher_info info
- = { &ctx, (crypt_func) aes_decrypt, data };
+ = { ctx, cipher->decrypt, data };
- memset(key, 0, sizeof(key));
-
- aes_set_key(&ctx, sizeof(key), key);
- init_data(data);
-
- bench("AES (ECB decrypt)", bench_cipher, &info);
+ init_key(cipher->key_size, key);
+ cipher->setkey(ctx, cipher->key_size, key);
+
+ printf("%13s (ECB decrypt): %f\n", cipher->name,
+ time_function(bench_cipher, &info));
}
- {
- struct aes_ctx ctx;
- struct bench_cbc_info info
- = { &ctx, (crypt_func) aes_encrypt, data, AES_BLOCK_SIZE, iv };
+ if (cipher->block_size)
+ {
+ uint8_t *iv = alloca(cipher->block_size);
+
+ /* Do CBC mode */
+ {
+ struct bench_cbc_info info
+ = { ctx, cipher->encrypt, data, cipher->block_size, iv };
- memset(key, 0, sizeof(key));
- memset(iv, 0, sizeof(iv));
+ memset(iv, 0, sizeof(iv));
- aes_set_key(&ctx, sizeof(key), key);
- init_data(data);
+ cipher->setkey(ctx, cipher->key_size, key);
- bench("AES (CBC encrypt)", bench_cbc_encrypt, &info);
- }
+ printf("%13s (CBC encrypt): %f\n", cipher->name,
+ time_function(bench_cbc_encrypt,
+ &info));
+ }
- {
- struct aes_ctx ctx;
- struct bench_cbc_info info
- = { &ctx, (crypt_func) aes_decrypt, data, AES_BLOCK_SIZE, iv };
+ {
+ struct bench_cbc_info info
+ = { ctx, cipher->decrypt, data, cipher->block_size, iv };
- memset(key, 0, sizeof(key));
- memset(iv, 0, sizeof(iv));
+ memset(iv, 0, sizeof(iv));
- aes_set_key(&ctx, sizeof(key), key);
- init_data(data);
+ cipher->setkey(ctx, cipher->key_size, key);
- bench("AES (CBC decrypt)", bench_cbc_decrypt, &info);
- }
+ printf("%13s (CBC decrypt): %f\n", cipher->name,
+ time_function(bench_cbc_decrypt,
+ &info));
+ }
+ }
+}
+
+/* DES uses a different signature for the key set function.
+ * And we have to adjust parity. */
+static void
+des_set_key_hack(void *c, unsigned length, const uint8_t *key)
+{
+ struct des_ctx *ctx = c;
+ uint8_t pkey[DES_KEY_SIZE];
+
+ assert(length == DES_KEY_SIZE);
+ des_fix_parity(DES_KEY_SIZE, pkey, key);
+ if (!des_set_key(ctx, pkey))
+ abort();
+}
+
+static void
+des3_set_key_hack(void *c, unsigned length, const uint8_t *key)
+{
+ struct des3_ctx *ctx = c;
+ uint8_t pkey[DES3_KEY_SIZE];
+
+ assert(length == DES3_KEY_SIZE);
+ des_fix_parity(DES3_KEY_SIZE, pkey, key);
+ if (!des3_set_key(ctx, pkey))
+ abort();
+}
+
+#define NCIPHERS 12
+
+int
+main(int argc, char **argv)
+{
+ unsigned i;
+ struct cipher ciphers[NCIPHERS] =
+ {
+ { "AES-128", sizeof(struct aes_ctx),
+ AES_BLOCK_SIZE, 16,
+ (setkey_func) aes_set_key,
+ (crypt_func) aes_encrypt,
+ (crypt_func) aes_decrypt
+ },
+ { "AES-192", sizeof(struct aes_ctx),
+ AES_BLOCK_SIZE, 24,
+ (setkey_func) aes_set_key,
+ (crypt_func) aes_encrypt,
+ (crypt_func) aes_decrypt
+ },
+ { "AES-256", sizeof(struct aes_ctx),
+ AES_BLOCK_SIZE, 32,
+ (setkey_func) aes_set_key,
+ (crypt_func) aes_encrypt,
+ (crypt_func) aes_decrypt
+ },
+ { "ARCFOUR-128", sizeof(struct arcfour_ctx),
+ 0, ARCFOUR_KEY_SIZE,
+ (setkey_func) arcfour_set_key,
+ (crypt_func) arcfour_crypt,
+ (crypt_func) arcfour_crypt
+ },
+ { "BLOWFISH-128", sizeof(struct blowfish_ctx),
+ BLOWFISH_BLOCK_SIZE, BLOWFISH_KEY_SIZE,
+ (setkey_func) blowfish_set_key,
+ (crypt_func) blowfish_encrypt,
+ (crypt_func) blowfish_decrypt
+ },
+ { "CAST-128", sizeof(struct cast128_ctx),
+ CAST128_BLOCK_SIZE, CAST128_KEY_SIZE,
+ (setkey_func) cast128_set_key,
+ (crypt_func) cast128_encrypt,
+ (crypt_func) cast128_decrypt
+ },
+ { "DES", sizeof(struct des_ctx),
+ DES_BLOCK_SIZE, DES_KEY_SIZE,
+ des_set_key_hack,
+ (crypt_func) des_encrypt,
+ (crypt_func) des_decrypt
+ },
+ { "DES3", sizeof(struct des3_ctx),
+ DES3_BLOCK_SIZE, DES3_KEY_SIZE,
+ des3_set_key_hack,
+ (crypt_func) des3_encrypt,
+ (crypt_func) des3_decrypt
+ },
+ { "SERPENT-256", sizeof(struct serpent_ctx),
+ SERPENT_BLOCK_SIZE, SERPENT_KEY_SIZE,
+ (setkey_func) serpent_set_key,
+ (crypt_func) serpent_encrypt,
+ (crypt_func) serpent_decrypt
+ },
+ { "TWOFISH-128", sizeof(struct twofish_ctx),
+ TWOFISH_BLOCK_SIZE, 16,
+ (setkey_func) twofish_set_key,
+ (crypt_func) twofish_encrypt,
+ (crypt_func) twofish_decrypt
+ },
+ { "TWOFISH-192", sizeof(struct twofish_ctx),
+ TWOFISH_BLOCK_SIZE, 24,
+ (setkey_func) twofish_set_key,
+ (crypt_func) twofish_encrypt,
+ (crypt_func) twofish_decrypt
+ },
+ { "TWOFISH-256", sizeof(struct twofish_ctx),
+ TWOFISH_BLOCK_SIZE, 32,
+ (setkey_func) twofish_set_key,
+ (crypt_func) twofish_encrypt,
+ (crypt_func) twofish_decrypt
+ },
+ };
+ for (i = 0; i<NCIPHERS; i++)
+ time_cipher(ciphers + i);
+
return 0;
}