From 4f2eb1914bdac3ed3ee504ad86061281dbe0d074 Mon Sep 17 00:00:00 2001 From: Matt Johnston Date: Fri, 9 Feb 2018 21:44:05 +0800 Subject: Update to libtomcrypt 1.18.1, merged with Dropbear changes --- libtomcrypt/demos/constants.c | 86 +++ libtomcrypt/demos/demo_dynamic.py | 309 ++++++++ libtomcrypt/demos/hashsum.c | 333 +++++++-- libtomcrypt/demos/ltcrypt.c | 205 +++++ libtomcrypt/demos/openssl-enc.c | 397 ++++++++++ libtomcrypt/demos/sizes.c | 79 ++ libtomcrypt/demos/small.c | 14 +- libtomcrypt/demos/timing.c | 1478 ++++++++++++++++++++++++++++++++++++- libtomcrypt/demos/tv_gen.c | 346 ++++----- 9 files changed, 2977 insertions(+), 270 deletions(-) create mode 100644 libtomcrypt/demos/constants.c create mode 100644 libtomcrypt/demos/demo_dynamic.py create mode 100644 libtomcrypt/demos/ltcrypt.c create mode 100644 libtomcrypt/demos/openssl-enc.c create mode 100644 libtomcrypt/demos/sizes.c (limited to 'libtomcrypt/demos') diff --git a/libtomcrypt/demos/constants.c b/libtomcrypt/demos/constants.c new file mode 100644 index 0000000..f747eb5 --- /dev/null +++ b/libtomcrypt/demos/constants.c @@ -0,0 +1,86 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + */ +#include "tomcrypt.h" + +#if defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112L +#include +#else +#define basename(x) x +#endif + +/** + @file demo_crypt_constants.c + + Demo how to get various constants to dynamic languages + like Python + + Larry Bugbee, February 2013 +*/ + +static void _print_line(const char* cmd, const char* desc) +{ + printf(" %-16s - %s\n", cmd, desc); +} + +int main(int argc, char **argv) +{ + if (argc == 1) { + /* given a specific constant name, get and print its value */ + char name[] = "CTR_COUNTER_BIG_ENDIAN"; + int value; + char *names_list; + unsigned int names_list_len; + + if (crypt_get_constant(name, &value) != 0) exit(EXIT_FAILURE); + printf("\n %s is %d \n\n", name, value); + + /* get and print the length of the names (and values) list */ + + if (crypt_list_all_constants(NULL, &names_list_len) != 0) exit(EXIT_FAILURE); + printf(" need to allocate %u bytes \n\n", names_list_len); + + /* get and print the names (and values) list */ + if ((names_list = malloc(names_list_len)) == NULL) exit(EXIT_FAILURE); + if (crypt_list_all_constants(names_list, &names_list_len) != 0) exit(EXIT_FAILURE); + printf(" supported constants:\n\n%s\n\n", names_list); + free(names_list); + } else if (argc == 2) { + if (strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "--help") == 0) { + char* base = strdup(basename(argv[0])); + printf("Usage: %s [-a] [-s name]\n\n", base); + _print_line("", "The old behavior of the demo"); + _print_line("-a", "Only lists all constants"); + _print_line("-s name", "List a single constant given as argument"); + _print_line("-h", "The help you're looking at"); + free(base); + } else if (strcmp(argv[1], "-a") == 0) { + char *names_list; + unsigned int names_list_len; + /* get and print the length of the names (and values) list */ + if (crypt_list_all_constants(NULL, &names_list_len) != 0) exit(EXIT_FAILURE); + /* get and print the names (and values) list */ + names_list = malloc(names_list_len); + if (crypt_list_all_constants(names_list, &names_list_len) != 0) exit(EXIT_FAILURE); + printf("%s\n", names_list); + } + } else if (argc == 3) { + if (strcmp(argv[1], "-s") == 0) { + int value; + if (crypt_get_constant(argv[2], &value) != 0) exit(EXIT_FAILURE); + printf("%s,%u\n", argv[2], value); + } + } + + return 0; +} + + +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/libtomcrypt/demos/demo_dynamic.py b/libtomcrypt/demos/demo_dynamic.py new file mode 100644 index 0000000..a0699e4 --- /dev/null +++ b/libtomcrypt/demos/demo_dynamic.py @@ -0,0 +1,309 @@ + + +""" + demo_dynamic.py v2b + + This program demonstrates Python's use of the dynamic + language support additions to LTC, namely access to LTC + constants, struct and union sizes, and the binding of a + math package to LTC. Also provided are simple code + fragments to illustrate how one might write a Python + wrapper for LTC and how an app might call the wrapper. + This or a similar model should work for Ruby and other + dynamic languages. + + This instance uses Python's ctypes and requires a single + .dylib linking together LTC and a math library. Building + a single .dylib is needed because LTC wants a fairly tight + relationship between itself and the mathlib. (ctypes can + load multiple .dylibs, but it does not support this level + of tight coupling between otherwise independent libraries.) + + My .dylib was created on OSX/macOS with the following: + sudo make -j5 -f makefile.shared \ + CFLAGS="-DUSE_TFM -DTFM_DESC -I/usr/local/include" \ + EXTRALIBS=/usr/local/lib/libtfm.a install + + For python 2.7.12 on Ubuntu Xenial the following worked for + me (without MPI support): + sudo make -f makefile.shared install PREFIX="/usr" + + Reminder: you don't need to bind in a math library unless + you are going to use LTC functions that need a + mathlib. For example, public key crypto requires + a mathlib; hashing and symmetric encryption do not. + + ------ + + This code was originally written for Python 2.7 with the + ctypes standard library. This version is modified to run + under both Python 2.7 and 3.6. + + Arguably the biggest change for Python3 has to do with + strings. Under Python2, native strings are ASCII bytes and + passing them to LTC is natural and requires no conversion. + Under Python3 all native strings are Unicode which requires + they be converted to bytes before use by LTC. + + Note the following for Python3. + - ASCII keys, IVs and other string arguments must be + 'bytes'. Define them with a 'b' prefix or convert + via the 'bytes()' function. + - "strings" returned from LTC are bytes and conversion + to Unicode might be necessary for proper printing. + If so, use .decode('utf-8'). + - The Python2 'print' statement becomes a function in + Python3 which requires parenthesis, eg. 'print()'. + + NB: Unicode is achieved under Python2 by either defining + a Unicode string with a 'u' prefix or passing ASCII + strings thru the 'unicode()' function. + + Larry Bugbee + March 2014 v1 + August 2017 v2b + +""" + + +import sys +from ctypes import * +from ctypes.util import find_library + +# switches to enable/disable selected output +SHOW_ALL_CONSTANTS = True +SHOW_ALL_SIZES = True +SHOW_SELECTED_CONSTANTS = True +SHOW_SELECTED_SIZES = True +SHOW_BUILD_OPTIONS_ALGS = True +SHOW_SHA256_EXAMPLE = True +SHOW_CHACHA_EXAMPLE = True + +print(' ') +print(' demo_dynamic.py') + +def inprint(s, indent=0): + "prints strings indented, including multline strings" + for line in s.split('\n'): + print(' '*indent + line) + +#------------------------------------------------------------------------------- +# load the .dylib + +libname = 'tomcrypt' +libpath = find_library(libname) +print(' ') +print(' path to library %s: %s' % (libname, libpath)) + +LTC = cdll.LoadLibrary(libpath) +print(' loaded: %s' % LTC) +print(' ') + + +#------------------------------------------------------------------------------- +# get list of all supported constants followed by a list of all +# supported sizes. One alternative: these lists may be parsed +# and used as needed. + +if SHOW_ALL_CONSTANTS: + print('-'*60) + print(' all supported constants and their values:') + + # get size to allocate for constants output list + str_len = c_int(0) + ret = LTC.crypt_list_all_constants(None, byref(str_len)) + print(' need to allocate %d bytes to build list \n' % str_len.value) + + # allocate that size and get (name, size) pairs, each pair + # separated by a newline char. + names_sizes = c_buffer(str_len.value) + ret = LTC.crypt_list_all_constants(names_sizes, byref(str_len)) + print(names_sizes.value.decode("utf-8")) + print(' ') + + +if SHOW_ALL_SIZES: + print('-'*60) + print(' all supported sizes:') + + # get size to allocate for sizes output list + str_len = c_int(0) + ret = LTC.crypt_list_all_sizes(None, byref(str_len)) + print(' need to allocate %d bytes to build list \n' % str_len.value) + + # allocate that size and get (name, size) pairs, each pair + # separated by a newline char. + names_sizes = c_buffer(str_len.value) + ret = LTC.crypt_list_all_sizes(names_sizes, byref(str_len)) + print(names_sizes.value.decode("utf-8")) + print(' ') + + +#------------------------------------------------------------------------------- +# get individually named constants and sizes + +if SHOW_SELECTED_CONSTANTS: + print('-'*60) + print('\n selected constants:') + + names = [ + b'ENDIAN_LITTLE', + b'ENDIAN_64BITWORD', + b'PK_PUBLIC', + b'LTC_MILLER_RABIN_REPS', + b'CTR_COUNTER_BIG_ENDIAN', + ] + for name in names: + const_value = c_int(0) + rc = LTC.crypt_get_constant(name, byref(const_value)) + value = const_value.value + print(' %-25s %d' % (name.decode("utf-8"), value)) + print(' ') + +if SHOW_SELECTED_SIZES: + print('-'*60) + print('\n selected sizes:') + + names = [ + b'rijndael_key', + b'rsa_key', + b'symmetric_CTR', + b'twofish_key', + b'ecc_point', + b'gcm_state', + b'sha512_state', + ] + for name in names: + size_value = c_int(0) + rc = LTC.crypt_get_size(name, byref(size_value)) + value = size_value.value + print(' %-25s %d' % (name.decode("utf-8"), value)) + print(' ') + + +#------------------------------------------------------------------------------- +#------------------------------------------------------------------------------- +# LibTomCrypt exposes one interesting string that can be accessed +# via Python's ctypes module, "crypt_build_settings", which +# provides a list of this build's compiler switches and supported +# algorithms. If someday LTC exposes other interesting strings, +# they can be found with: +# nm /usr/local/lib/libtomcrypt.dylib | grep " D " + +def get_named_string(lib, name): + return c_char_p.in_dll(lib, name).value.decode("utf-8") + +if SHOW_BUILD_OPTIONS_ALGS: + print('-'*60) + print('This is a string compiled into LTC showing compile') + print('options and algorithms supported by this build \n') +# print(get_named_string(LTC, 'crypt_build_settings')) + inprint(get_named_string(LTC, 'crypt_build_settings'), 4) + + +#------------------------------------------------------------------------------- +#------------------------------------------------------------------------------- +# here is an example of how Python code can be written to access +# LTC's implementation of SHA256 and ChaCha, + +# - - - - - - - - - - - - - +# definitions + +from binascii import hexlify, unhexlify + +def _err2str(err): + # define return type + errstr = LTC.error_to_string + errstr.restype = c_char_p + # get and return err string + return errstr(err) + +def _get_size(name): + size = c_int(0) + rc = LTC.crypt_get_size(bytes(name), byref(size)) + if rc != 0: + raise Exception('LTC.crypt_get_size(%s) rc = %d' % (name, rc)) + return size.value + +def _get_constant(name): + constant = c_int(0) + rc = LTC.crypt_get_constant(bytes(name), byref(constant)) + if rc != 0: + raise Exception('LTC.crypt_get_constant(%s) rc = %d' % (name, rc)) + return constant.value + +CRYPT_OK = _get_constant(b'CRYPT_OK') + +class SHA256(object): + def __init__(self): + self.state = c_buffer(_get_size(b'sha256_state')) + LTC.sha256_init(byref(self.state)) + def update(self, data): + LTC.sha256_process(byref(self.state), data, len(data)) + def digest(self): + md = c_buffer(32) + LTC.sha256_done(byref(self.state), byref(md)) + return md.raw + +class ChaCha(object): + def __init__(self, key, rounds): + self.state = c_buffer(_get_size(b'chacha_state')) + self.counter = c_int(1) + err = LTC.chacha_setup(byref(self.state), key, len(key), rounds) + if err != CRYPT_OK: + raise Exception('LTC.chacha_setup(), err = %d, "%s"' % (err, _err2str(err))) + def set_iv32(self, iv): + err = LTC.chacha_ivctr32(byref(self.state), iv, len(iv), byref(self.counter)) + if err != CRYPT_OK: + raise Exception('LTC.chacha_ivctr32(), err = %d, "%s"' % (err, _err2str(err))) + def crypt(self, datain): + dataout = c_buffer(len(datain)) + err = LTC.chacha_crypt(byref(self.state), datain, len(datain), byref(dataout)) + if err != CRYPT_OK: + raise Exception('LTC.chacha_crypt(), err = %d, "%s"' % (err, _err2str(err))) + return dataout.raw + +# - - - - - - - - - - - - - +# a SHA256 app fragment + +if SHOW_SHA256_EXAMPLE: + print('-'*60) + data = b'hello world' # we want bytes, not Unicode + + sha256 = SHA256() + sha256.update(data) + md = sha256.digest() + + template = '\n the SHA256 digest for "%s" is %s \n' + print(template % (data, hexlify(md))) + +# - - - - - - - - - - - - - +# a ChaCha app fragment + +if SHOW_CHACHA_EXAMPLE: + print('-'*60) + key = b'hownowbrowncow\x00\x00' # exactly 16 or 32 bytes + rounds = 12 # common values: 8, 12, 20 + iv = b'123456789012' # exactly 12 bytes + plain = b'Kilroy was here, there, and everywhere!' + + cha = ChaCha(key, rounds) + cha.set_iv32(iv) + cipher = cha.crypt(plain) + + template = '\n ChaCha%d ciphertext for "%s" is "%s"' + print(template % (rounds, plain, hexlify(cipher))) + + cha.set_iv32(iv) # reset to decrypt + decrypted = cha.crypt(cipher) + + template = ' ChaCha%d decoded text for "%s" is "%s" \n' + print(template % (rounds, plain, decrypted.decode("utf-8"))) + +# Footnote: Keys should be erased fm memory as soon as possible after use, +# and that includes Python. For a tip on how to do that in Python, see +# http://buggywhip.blogspot.com/2010/12/erase-keys-and-credit-card-numbers-in.html + +#------------------------------------------------------------------------------- +#------------------------------------------------------------------------------- +#------------------------------------------------------------------------------- diff --git a/libtomcrypt/demos/hashsum.c b/libtomcrypt/demos/hashsum.c index 4e31501..aee0bd2 100644 --- a/libtomcrypt/demos/hashsum.c +++ b/libtomcrypt/demos/hashsum.c @@ -1,3 +1,12 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + */ + /* * Written by Daniel Richards 6/7/2002 * hash.c: This app uses libtomcrypt to hash either stdin or a file @@ -9,111 +18,283 @@ #include -int errno; +#if defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112L +#include +#else +#define basename(x) x +#endif -void register_algs(); +#if !defined(PATH_MAX) && defined(_MSC_VER) +#include +#define PATH_MAX MAX_PATH +#endif -int main(int argc, char **argv) +/* thanks http://stackoverflow.com/a/8198009 */ +#define _base(x) ((x >= '0' && x <= '9') ? '0' : \ + (x >= 'a' && x <= 'f') ? 'a' - 10 : \ + (x >= 'A' && x <= 'F') ? 'A' - 10 : \ + '\255') +#define HEXOF(x) (x - _base(x)) + +static char* hashsum; + +static void cleanup(void) { - int idx, x, z; - unsigned long w; - unsigned char hash_buffer[MAXBLOCKSIZE]; - hash_state md; + free(hashsum); +} - /* You need to register algorithms before using them */ - register_algs(); - if (argc < 2) { - printf("usage: ./hash algorithm file [file ...]\n"); - printf("Algorithms:\n"); - for (x = 0; hash_descriptor[x].name != NULL; x++) { - printf(" %s (%d)\n", hash_descriptor[x].name, hash_descriptor[x].ID); +static void die(int status) +{ + unsigned long w, x; + FILE* o = status == EXIT_SUCCESS ? stdout : stderr; + fprintf(o, "usage: %s -a algorithm [-c] [file...]\n\n", hashsum); + fprintf(o, "\t-c\tCheck the hash(es) of the file(s) written in [file].\n"); + fprintf(o, "\t\t(-a not required)\n"); + fprintf(o, "\nAlgorithms:\n\t"); + w = 0; + for (x = 0; hash_descriptor[x].name != NULL; x++) { + w += fprintf(o, "%-14s", hash_descriptor[x].name); + if (w >= 70) { + fprintf(o, "\n\t"); + w = 0; } - exit(EXIT_SUCCESS); } + if (w != 0) fprintf(o, "\n"); + exit(status); +} - idx = find_hash(argv[1]); - if (idx == -1) { - fprintf(stderr, "\nInvalid hash specified on command line.\n"); - return -1; +static void printf_hex(unsigned char* hash_buffer, unsigned long w) +{ + unsigned long x; + for (x = 0; x < w; x++) { + printf("%02x",hash_buffer[x]); } +} - if (argc == 2) { - hash_descriptor[idx].init(&md); - do { - x = fread(hash_buffer, 1, sizeof(hash_buffer), stdin); - hash_descriptor[idx].process(&md, hash_buffer, x); - } while (x == sizeof(hash_buffer)); - hash_descriptor[idx].done(&md, hash_buffer); - for (x = 0; x < (int)hash_descriptor[idx].hashsize; x++) { - printf("%02x",hash_buffer[x]); +static void check_file(int argn, int argc, char **argv) +{ + int err, failed, invalid; + unsigned char is_buffer[MAXBLOCKSIZE], should_buffer[MAXBLOCKSIZE]; + char buf[PATH_MAX + (MAXBLOCKSIZE * 3)]; + /* iterate through all files */ + while(argn < argc) { + char* s; + FILE* f = fopen(argv[argn], "rb"); + if(f == NULL) { + int n = snprintf(buf, sizeof(buf), "%s: %s", hashsum, argv[argn]); + if (n > 0 && n < (int)sizeof(buf)) + perror(buf); + else + perror(argv[argn]); + exit(EXIT_FAILURE); } - printf(" (stdin)\n"); - } else { - for (z = 2; z < argc; z++) { - w = sizeof(hash_buffer); - if ((errno = hash_file(idx,argv[z],hash_buffer,&w)) != CRYPT_OK) { - printf("File hash error: %s\n", error_to_string(errno)); - } else { - for (x = 0; x < (int)hash_descriptor[idx].hashsize; x++) { - printf("%02x",hash_buffer[x]); - } - printf(" %s\n", argv[z]); + failed = 0; + invalid = 0; + /* read the file line by line */ + while((s = fgets(buf, sizeof(buf), f)) != NULL) + { + int tries, n; + unsigned long hash_len, w, x; + char* space = strstr(s, " "); + + /* skip lines with comments */ + if (buf[0] == '#') continue; + + if (space == NULL) { + fprintf(stderr, "%s: no properly formatted checksum lines found\n", hashsum); + goto ERR; + } + + hash_len = space - s; + hash_len /= 2; + + if (hash_len > sizeof(should_buffer)) { + fprintf(stderr, "%s: hash too long\n", hashsum); + goto ERR; + } + + /* convert the hex-string back to binary */ + for (x = 0; x < hash_len; ++x) { + should_buffer[x] = HEXOF(s[x*2]) << 4 | HEXOF(s[x*2 + 1]); } + + space++; + if (*space != '*') { + fprintf(stderr, "%s: unsupported input mode '%c'\n", hashsum, *space); + goto ERR; + } + space++; + + for (n = 0; n < (buf + sizeof(buf)) - space; ++n) { + if(iscntrl((int)space[n])) { + space[n] = '\0'; + break; + } + } + + /* try all hash algorithms that have the appropriate hash size */ + tries = 0; + for (x = 0; hash_descriptor[x].name != NULL; ++x) { + if (hash_descriptor[x].hashsize == hash_len) { + tries++; + w = sizeof(is_buffer); + if ((err = hash_file(x, space, is_buffer, &w)) != CRYPT_OK) { + fprintf(stderr, "%s: File hash error: %s: %s\n", hashsum, space, error_to_string(err)); +ERR: + fclose(f); + exit(EXIT_FAILURE); + } + if(XMEMCMP(should_buffer, is_buffer, w) == 0) { + printf("%s: OK\n", space); + break; + } + } + } /* for */ + if (hash_descriptor[x].name == NULL) { + if(tries > 0) { + printf("%s: FAILED\n", space); + failed++; + } + else { + invalid++; + } + } + } /* while */ + fclose(f); + if(invalid) { + fprintf(stderr, "%s: WARNING: %d %s is improperly formatted\n", hashsum, invalid, invalid > 1?"lines":"line"); + } + if(failed) { + fprintf(stderr, "%s: WARNING: %d computed %s did NOT match\n", hashsum, failed, failed > 1?"checksums":"checksum"); } + argn++; } - return EXIT_SUCCESS; + exit(EXIT_SUCCESS); } -void register_algs(void) +int main(int argc, char **argv) { - int err; + int idxs[TAB_SIZE], idx, check, y, z, err, argn; + unsigned long w, x; + unsigned char hash_buffer[MAXBLOCKSIZE]; -#ifdef LTC_TIGER - register_hash (&tiger_desc); -#endif -#ifdef LTC_MD2 - register_hash (&md2_desc); -#endif -#ifdef LTC_MD4 - register_hash (&md4_desc); -#endif -#ifdef LTC_MD5 - register_hash (&md5_desc); -#endif + hashsum = strdup(basename(argv[0])); + atexit(cleanup); + + /* You need to register algorithms before using them */ + register_all_ciphers(); + register_all_hashes(); + if (argc > 1 && (strcmp("-h", argv[1]) == 0 || strcmp("--help", argv[1]) == 0)) { + die(EXIT_SUCCESS); + } + if (argc < 3) { + die(EXIT_FAILURE); + } + + for (x = 0; x < sizeof(idxs)/sizeof(idxs[0]); ++x) { + idxs[x] = -2; + } + argn = 1; + check = 0; + idx = 0; + + while(argn < argc){ + if(strcmp("-a", argv[argn]) == 0) { + argn++; + if(argn < argc) { + idxs[idx] = find_hash(argv[argn]); + if (idxs[idx] == -1) { + struct { + const char* is; + const char* should; + } shasum_compat[] = + { #ifdef LTC_SHA1 - register_hash (&sha1_desc); + { "1", sha1_desc.name }, #endif #ifdef LTC_SHA224 - register_hash (&sha224_desc); + { "224", sha224_desc.name }, #endif #ifdef LTC_SHA256 - register_hash (&sha256_desc); + { "256", sha256_desc.name }, #endif #ifdef LTC_SHA384 - register_hash (&sha384_desc); + { "384", sha384_desc.name }, #endif #ifdef LTC_SHA512 - register_hash (&sha512_desc); -#endif -#ifdef LTC_RIPEMD128 - register_hash (&rmd128_desc); + { "512", sha512_desc.name }, #endif -#ifdef LTC_RIPEMD160 - register_hash (&rmd160_desc); +#ifdef LTC_SHA512_224 + { "512224", sha512_224_desc.name }, #endif -#ifdef LTC_WHIRLPOOL - register_hash (&whirlpool_desc); -#endif -#ifdef LTC_CHC_HASH - register_hash(&chc_desc); - if ((err = chc_register(register_cipher(&aes_enc_desc))) != CRYPT_OK) { - printf("chc_register error: %s\n", error_to_string(err)); - exit(EXIT_FAILURE); - } +#ifdef LTC_SHA512_256 + { "512256", sha512_256_desc.name }, #endif + { NULL, NULL } + }; + for (x = 0; shasum_compat[x].is != NULL; ++x) { + if(XSTRCMP(shasum_compat[x].is, argv[argn]) == 0) { + idxs[idx] = find_hash(shasum_compat[x].should); + break; + } + } + } + if (idxs[idx] == -1) { + fprintf(stderr, "%s: Unrecognized algorithm\n", hashsum); + die(EXIT_FAILURE); + } + idx++; + if ((size_t)idx >= sizeof(idxs)/sizeof(idxs[0])) { + fprintf(stderr, "%s: Too many '-a' options chosen\n", hashsum); + die(EXIT_FAILURE); + } + argn++; + continue; + } + else { + die(EXIT_FAILURE); + } + } + if(strcmp("-c", argv[argn]) == 0) { + check = 1; + argn++; + continue; + } + break; + } + + if (check == 1) { + check_file(argn, argc, argv); + } + if (argc == argn) { + w = sizeof(hash_buffer); + if ((err = hash_filehandle(idxs[0], stdin, hash_buffer, &w)) != CRYPT_OK) { + fprintf(stderr, "%s: File hash error: %s\n", hashsum, error_to_string(err)); + return EXIT_FAILURE; + } else { + for (x = 0; x < w; x++) { + printf("%02x",hash_buffer[x]); + } + printf(" *-\n"); + } + } else { + for (z = argn; z < argc; z++) { + for (y = 0; y < idx; ++y) { + w = sizeof(hash_buffer); + if ((err = hash_file(idxs[y],argv[z],hash_buffer,&w)) != CRYPT_OK) { + fprintf(stderr, "%s: File hash error: %s\n", hashsum, error_to_string(err)); + return EXIT_FAILURE; + } else { + printf_hex(hash_buffer, w); + printf(" *%s\n", argv[z]); + } + } + } + } + return EXIT_SUCCESS; } -/* $Source$ */ -/* $Revision$ */ -/* $Date$ */ +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/libtomcrypt/demos/ltcrypt.c b/libtomcrypt/demos/ltcrypt.c new file mode 100644 index 0000000..024c005 --- /dev/null +++ b/libtomcrypt/demos/ltcrypt.c @@ -0,0 +1,205 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + */ + +/* encrypt V1.1 Fri Oct 18 04:28:03 NZDT 2002 */ +/* File de/encryption, using libtomcrypt */ +/* Written by Daniel Richards */ +/* Help from Tom St Denis with various bits */ +/* This code is public domain, no rights reserved. */ +/* Encrypts by default, -d flag enables decryption */ +/* ie: ./encrypt blowfish story.txt story.ct */ +/* ./encrypt -d blowfish story.ct story.pt */ + +#include + +int usage(char *name) +{ + int x; + + printf("Usage encrypt: %s cipher infile outfile\n", name); + printf("Usage decrypt: %s -d cipher infile outfile\n", name); + printf("Usage test: %s -t cipher\nCiphers:\n", name); + for (x = 0; cipher_descriptor[x].name != NULL; x++) { + printf("%s\n",cipher_descriptor[x].name); + } + exit(1); +} + +int main(int argc, char *argv[]) +{ + unsigned char plaintext[512],ciphertext[512]; + unsigned char tmpkey[512], key[MAXBLOCKSIZE], IV[MAXBLOCKSIZE]; + unsigned char inbuf[512]; /* i/o block size */ + unsigned long outlen, y, ivsize, x, decrypt; + symmetric_CTR ctr; + int cipher_idx, hash_idx, ks; + char *infile, *outfile, *cipher; + prng_state prng; + FILE *fdin, *fdout; + int err; + + /* register algs, so they can be printed */ + register_all_ciphers(); + register_all_hashes(); + register_all_prngs(); + + if (argc < 4) { + if ((argc > 2) && (!strcmp(argv[1], "-t"))) { + cipher = argv[2]; + cipher_idx = find_cipher(cipher); + if (cipher_idx == -1) { + printf("Invalid cipher %s entered on command line.\n", cipher); + exit(-1); + } /* if */ + if (cipher_descriptor[cipher_idx].test) + { + if (cipher_descriptor[cipher_idx].test() != CRYPT_OK) + { + printf("Error when testing cipher %s.\n", cipher); + exit(-1); + } + else + { + printf("Testing cipher %s succeeded.\n", cipher); + exit(0); + } /* if ... else */ + } /* if */ + } + return usage(argv[0]); + } + + if (!strcmp(argv[1], "-d")) { + decrypt = 1; + cipher = argv[2]; + infile = argv[3]; + outfile = argv[4]; + } else { + decrypt = 0; + cipher = argv[1]; + infile = argv[2]; + outfile = argv[3]; + } + + /* file handles setup */ + fdin = fopen(infile,"rb"); + if (fdin == NULL) { + perror("Can't open input for reading"); + exit(-1); + } + + fdout = fopen(outfile,"wb"); + if (fdout == NULL) { + perror("Can't open output for writing"); + exit(-1); + } + + cipher_idx = find_cipher(cipher); + if (cipher_idx == -1) { + printf("Invalid cipher entered on command line.\n"); + exit(-1); + } + + hash_idx = find_hash("sha256"); + if (hash_idx == -1) { + printf("LTC_SHA256 not found...?\n"); + exit(-1); + } + + ivsize = cipher_descriptor[cipher_idx].block_length; + ks = hash_descriptor[hash_idx].hashsize; + if (cipher_descriptor[cipher_idx].keysize(&ks) != CRYPT_OK) { + printf("Invalid keysize???\n"); + exit(-1); + } + + printf("\nEnter key: "); + if(fgets((char *)tmpkey,sizeof(tmpkey), stdin) == NULL) + exit(-1); + outlen = sizeof(key); + if ((err = hash_memory(hash_idx,tmpkey,strlen((char *)tmpkey),key,&outlen)) != CRYPT_OK) { + printf("Error hashing key: %s\n", error_to_string(err)); + exit(-1); + } + + if (decrypt) { + /* Need to read in IV */ + if (fread(IV,1,ivsize,fdin) != ivsize) { + printf("Error reading IV from input.\n"); + exit(-1); + } + + if ((err = ctr_start(cipher_idx,IV,key,ks,0,CTR_COUNTER_LITTLE_ENDIAN,&ctr)) != CRYPT_OK) { + printf("ctr_start error: %s\n",error_to_string(err)); + exit(-1); + } + + /* IV done */ + do { + y = fread(inbuf,1,sizeof(inbuf),fdin); + + if ((err = ctr_decrypt(inbuf,plaintext,y,&ctr)) != CRYPT_OK) { + printf("ctr_decrypt error: %s\n", error_to_string(err)); + exit(-1); + } + + if (fwrite(plaintext,1,y,fdout) != y) { + printf("Error writing to file.\n"); + exit(-1); + } + } while (y == sizeof(inbuf)); + fclose(fdin); + fclose(fdout); + + } else { /* encrypt */ + /* Setup yarrow for random bytes for IV */ + + if ((err = rng_make_prng(128, find_prng("yarrow"), &prng, NULL)) != CRYPT_OK) { + printf("Error setting up PRNG, %s\n", error_to_string(err)); + } + + /* You can use rng_get_bytes on platforms that support it */ + /* x = rng_get_bytes(IV,ivsize,NULL);*/ + x = yarrow_read(IV,ivsize,&prng); + if (x != ivsize) { + printf("Error reading PRNG for IV required.\n"); + exit(-1); + } + + if (fwrite(IV,1,ivsize,fdout) != ivsize) { + printf("Error writing IV to output.\n"); + exit(-1); + } + + if ((err = ctr_start(cipher_idx,IV,key,ks,0,CTR_COUNTER_LITTLE_ENDIAN,&ctr)) != CRYPT_OK) { + printf("ctr_start error: %s\n",error_to_string(err)); + exit(-1); + } + + do { + y = fread(inbuf,1,sizeof(inbuf),fdin); + + if ((err = ctr_encrypt(inbuf,ciphertext,y,&ctr)) != CRYPT_OK) { + printf("ctr_encrypt error: %s\n", error_to_string(err)); + exit(-1); + } + + if (fwrite(ciphertext,1,y,fdout) != y) { + printf("Error writing to output.\n"); + exit(-1); + } + } while (y == sizeof(inbuf)); + fclose(fdout); + fclose(fdin); + } + return 0; +} + +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/libtomcrypt/demos/openssl-enc.c b/libtomcrypt/demos/openssl-enc.c new file mode 100644 index 0000000..3aca04f --- /dev/null +++ b/libtomcrypt/demos/openssl-enc.c @@ -0,0 +1,397 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + */ + +/* + * Demo to do the rough equivalent of: + * + * openssl enc -aes-256-cbc -pass pass:foobar -in infile -out outfile -p + * + * Compilation: + * + * $(CC) -I /path/to/headers -L .../libs \ + * -o openssl-enc \ + * openssl-enc.c -ltomcrypt + * + * Usage: + * + * ./openssl-enc infile outfile "passphrase" [salt] + * + * If provided, the salt must be EXACTLY a 16-char hex string. + * + * Demo is an example of: + * + * - (When decrypting) yanking salt out of the OpenSSL "Salted__..." header + * - OpenSSL-compatible key derivation (in OpenSSL's modified PKCS#5v1 approach) + * - Grabbing an Initialization Vector from the key generator + * - Performing simple block encryption using AES + * - PKCS#7-type padding (which hopefully can get ripped out of this demo and + * made a libtomcrypt thing someday). + * + * This program is free for all purposes without any express guarantee it + * works. If you really want to see a license here, assume the WTFPL :-) + * + * BJ Black, bblack@barracuda.com, https://wjblack.com + * + * BUGS: + * Passing a password on a command line is a HORRIBLE idea. Don't use + * this program for serious work! + */ + +#include + +#ifndef LTC_RIJNDAEL +#error Cannot compile this demo; Rijndael (AES) required +#endif +#ifndef LTC_CBC_MODE +#error Cannot compile this demo; CBC mode required +#endif +#ifndef LTC_PKCS_5 +#error Cannot compile this demo; PKCS5 required +#endif +#ifndef LTC_RNG_GET_BYTES +#error Cannot compile this demo; random generator required +#endif +#ifndef LTC_MD5 +#error Cannot compile this demo; MD5 required +#endif + +/* OpenSSL by default only runs one hash round */ +#define OPENSSL_ITERATIONS 1 +/* Use aes-256-cbc, so 256 bits of key, 128 of IV */ +#define KEY_LENGTH (256>>3) +#define IV_LENGTH (128>>3) +/* PKCS#5v1 requires exactly an 8-byte salt */ +#define SALT_LENGTH 8 +/* The header OpenSSL puts on an encrypted file */ +static char salt_header[] = { 'S', 'a', 'l', 't', 'e', 'd', '_', '_' }; + +#include +#include +#include + +/* A simple way to handle the possibility that a block may increase in size + after padding. */ +union paddable { + unsigned char unpad[1024]; + unsigned char pad[1024+MAXBLOCKSIZE]; +}; + +/* + * Print usage and exit with a bad status (and perror() if any errno). + * + * Input: argv[0] and the error string + * Output: + * Side Effects: print messages and barf (does exit(3)) + */ +void barf(const char *pname, const char *err) +{ + printf("Usage: %s infile outfile passphrase [salt]\n", pname); + printf("\n"); + printf(" # encrypts infile->outfile, random salt\n"); + printf(" %s enc infile outfile \"passphrase\"\n", pname); + printf("\n"); + printf(" # encrypts infile->outfile, salt from cmdline\n"); + printf(" %s enc infile outfile pass 0123456789abcdef\n", pname); + printf("\n"); + printf(" # decrypts infile->outfile, pulls salt from infile\n"); + printf(" %s dec infile outfile pass\n", pname); + printf("\n"); + printf(" # decrypts infile->outfile, salt specified\n"); + printf(" # (don't try to read the salt from infile)\n"); + printf(" %s dec infile outfile pass 0123456789abcdef" + "\n", pname); + printf("\n"); + printf("Application Error: %s\n", err); + if(errno) + perror(" System Error"); + exit(-1); +} + +/* + * Parse a salt value passed in on the cmdline. + * + * Input: string passed in and a buf to put it in (exactly 8 bytes!) + * Output: CRYPT_OK if parsed OK, CRYPT_ERROR if not + * Side Effects: none + */ +int parse_hex_salt(unsigned char *in, unsigned char *out) +{ + int idx; + for(idx=0; idxpad+nb, padval, padval); + return nb+padval; + } else { + /* We are UNPADDING this block (and removing bytes) + We really just need to verify that the pad bytes are correct, + so start at the end of the string and work backwards. */ + + /* Figure out what the padlength should be by looking at the + last byte */ + idx = nb-1; + padval = buf->pad[idx]; + + /* padval must be nonzero and <= block length */ + if(padval <= 0 || padval > block_length) + return 0; + + /* First byte's accounted for; do the rest */ + idx--; + + while(idx >= (off_t)(nb-padval)) + if(buf->pad[idx] != padval) + return 0; + else + idx--; + + /* If we got here, the pad checked out, so return a smaller + number of bytes than nb (basically where we left off+1) */ + return idx+1; + } +} + +/* + * Perform an encrypt/decrypt operation to/from files using AES+CBC+PKCS7 pad. + * Set encrypt to 1 to encrypt, 0 to decrypt. + * + * Input: in/out files, key, iv, and mode + * Output: CRYPT_OK if no error + * Side Effects: bytes slurped from infile, pushed to outfile, fds updated. + */ +int do_crypt(FILE *infd, FILE *outfd, unsigned char *key, unsigned char *iv, + int encrypt) +{ + union paddable inbuf, outbuf; + int cipher, ret; + symmetric_CBC cbc; + size_t nb; + + /* Register your cipher! */ + cipher = register_cipher(&aes_desc); + if(cipher == -1) + return CRYPT_INVALID_CIPHER; + + /* Start a CBC session with cipher/key/val params */ + ret = cbc_start(cipher, iv, key, KEY_LENGTH, 0, &cbc); + if( ret != CRYPT_OK ) + return -1; + + do { + /* Get bytes from the source */ + nb = fread(inbuf.unpad, 1, sizeof(inbuf.unpad), infd); + if(!nb) + return encrypt ? CRYPT_OK : CRYPT_ERROR; + + /* Barf if we got a read error */ + if(ferror(infd)) + return CRYPT_ERROR; + + if(encrypt) { + /* We're encrypting, so pad first (if at EOF) and then + crypt */ + if(feof(infd)) + nb = pkcs7_pad(&inbuf, nb, + aes_desc.block_length, 1); + + ret = cbc_encrypt(inbuf.pad, outbuf.pad, nb, &cbc); + if(ret != CRYPT_OK) + return ret; + + } else { + /* We're decrypting, so decrypt and then unpad if at + EOF */ + ret = cbc_decrypt(inbuf.unpad, outbuf.unpad, nb, &cbc); + if( ret != CRYPT_OK ) + return ret; + + if( feof(infd) ) + nb = pkcs7_pad(&outbuf, nb, + aes_desc.block_length, 0); + if(nb == 0) + /* The file didn't decrypt correctly */ + return CRYPT_ERROR; + + } + + /* Push bytes to outfile */ + if(fwrite(outbuf.unpad, 1, nb, outfd) != nb) + return CRYPT_ERROR; + + } while(!feof(infd)); + + /* Close up */ + cbc_done(&cbc); + + return CRYPT_OK; +} + +/* Convenience macro for the various barfable places below */ +#define BARF(a) { \ + if(infd) fclose(infd); \ + if(outfd) { fclose(outfd); remove(argv[3]); } \ + barf(argv[0], a); \ +} +/* + * The main routine. Mostly validate cmdline params, open files, run the KDF, + * and do the crypt. + */ +int main(int argc, char *argv[]) { + unsigned char salt[SALT_LENGTH]; + FILE *infd = NULL, *outfd = NULL; + int encrypt = -1; + int hash = -1; + int ret; + unsigned char keyiv[KEY_LENGTH + IV_LENGTH]; + unsigned long keyivlen = (KEY_LENGTH + IV_LENGTH); + unsigned char *key, *iv; + + /* Check proper number of cmdline args */ + if(argc < 5 || argc > 6) + BARF("Invalid number of arguments"); + + /* Check proper mode of operation */ + if (!strncmp(argv[1], "enc", 3)) + encrypt = 1; + else if(!strncmp(argv[1], "dec", 3)) + encrypt = 0; + else + BARF("Bad command name"); + + /* Check we can open infile/outfile */ + infd = fopen(argv[2], "rb"); + if(infd == NULL) + BARF("Could not open infile"); + outfd = fopen(argv[3], "wb"); + if(outfd == NULL) + BARF("Could not open outfile"); + + /* Get the salt from wherever */ + if(argc == 6) { + /* User-provided */ + if(parse_hex_salt((unsigned char*) argv[5], salt) != CRYPT_OK) + BARF("Bad user-specified salt"); + } else if(!strncmp(argv[1], "enc", 3)) { + /* Encrypting; get from RNG */ + if(rng_get_bytes(salt, sizeof(salt), NULL) != sizeof(salt)) + BARF("Not enough random data"); + } else { + /* Parse from infile (decrypt only) */ + if(parse_openssl_header(infd, salt) != CRYPT_OK) + BARF("Invalid OpenSSL header in infile"); + } + + /* Fetch the MD5 hasher for PKCS#5 */ + hash = register_hash(&md5_desc); + if(hash == -1) + BARF("Could not register MD5 hash"); + + /* Set things to a sane initial state */ + zeromem(keyiv, sizeof(keyiv)); + key = keyiv + 0; /* key comes first */ + iv = keyiv + KEY_LENGTH; /* iv comes next */ + + /* Run the key derivation from the provided passphrase. This gets us + the key and iv. */ + ret = pkcs_5_alg1_openssl((unsigned char*)argv[4], strlen(argv[4]), salt, + OPENSSL_ITERATIONS, hash, keyiv, &keyivlen ); + if(ret != CRYPT_OK) + BARF("Could not derive key/iv from passphrase"); + + /* Display the salt/key/iv like OpenSSL cmdline does when -p */ + printf("salt="); dump_bytes(salt, sizeof(salt)); printf("\n"); + printf("key="); dump_bytes(key, KEY_LENGTH); printf("\n"); + printf("iv ="); dump_bytes(iv, IV_LENGTH ); printf("\n"); + + /* If we're encrypting, write the salt header as OpenSSL does */ + if(!strncmp(argv[1], "enc", 3)) { + if(fwrite(salt_header, 1, sizeof(salt_header), outfd) != + sizeof(salt_header) ) + BARF("Error writing salt header to outfile"); + if(fwrite(salt, 1, sizeof(salt), outfd) != sizeof(salt)) + BARF("Error writing salt to outfile"); + } + + /* At this point, the files are open, the salt has been figured out, + and we're ready to pump data through crypt. */ + + /* Do the crypt operation */ + if(do_crypt(infd, outfd, key, iv, encrypt) != CRYPT_OK) + BARF("Error during crypt operation"); + + /* Clean up */ + fclose(infd); fclose(outfd); + return 0; +} + +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/libtomcrypt/demos/sizes.c b/libtomcrypt/demos/sizes.c new file mode 100644 index 0000000..54d1979 --- /dev/null +++ b/libtomcrypt/demos/sizes.c @@ -0,0 +1,79 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + */ + +#include "tomcrypt.h" + +#if defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112L +#include +#else +#define basename(x) x +#endif +/** + @file demo_crypt_sizes.c + + Demo how to get various sizes to dynamic languages + like Python - Larry Bugbee, February 2013 +*/ + +static void _print_line(const char* cmd, const char* desc) +{ + printf(" %-16s - %s\n", cmd, desc); +} + +int main(int argc, char **argv) +{ + if (argc == 1) { + /* given a specific size name, get and print its size */ + char name[] = "ltc_hash_descriptor"; + unsigned int size; + char *sizes_list; + unsigned int sizes_list_len; + if (crypt_get_size(name, &size) != 0) exit(EXIT_FAILURE); + printf("\n size of '%s' is %u \n\n", name, size); + + /* get and print the length of the names (and sizes) list */ + if (crypt_list_all_sizes(NULL, &sizes_list_len) != 0) exit(EXIT_FAILURE); + printf(" need to allocate %u bytes \n\n", sizes_list_len); + + /* get and print the names (and sizes) list */ + sizes_list = malloc(sizes_list_len); + if (crypt_list_all_sizes(sizes_list, &sizes_list_len) != 0) exit(EXIT_FAILURE); + printf(" supported sizes:\n\n%s\n\n", sizes_list); + } else if (argc == 2) { + if (strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "--help") == 0) { + char* base = strdup(basename(argv[0])); + printf("Usage: %s [-a] [-s name]\n\n", base); + _print_line("", "The old behavior of the demo"); + _print_line("-a", "Only lists all sizes"); + _print_line("-s name", "List a single size given as argument"); + _print_line("-h", "The help you're looking at"); + free(base); + } else if (strcmp(argv[1], "-a") == 0) { + char *sizes_list; + unsigned int sizes_list_len; + /* get and print the length of the names (and sizes) list */ + if (crypt_list_all_sizes(NULL, &sizes_list_len) != 0) exit(EXIT_FAILURE); + /* get and print the names (and sizes) list */ + sizes_list = malloc(sizes_list_len); + if (crypt_list_all_sizes(sizes_list, &sizes_list_len) != 0) exit(EXIT_FAILURE); + printf("%s\n", sizes_list); + } + } else if (argc == 3) { + if (strcmp(argv[1], "-s") == 0) { + unsigned int size; + if (crypt_get_size(argv[2], &size) != 0) exit(EXIT_FAILURE); + printf("%s,%u\n", argv[2], size); + } + } + return 0; +} + +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/libtomcrypt/demos/small.c b/libtomcrypt/demos/small.c index 8d43821..de1f93d 100644 --- a/libtomcrypt/demos/small.c +++ b/libtomcrypt/demos/small.c @@ -1,3 +1,11 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + */ /* small demo app that just includes a cipher/hash/prng */ #include @@ -9,6 +17,6 @@ int main(void) return 0; } -/* $Source$ */ -/* $Revision$ */ -/* $Date$ */ +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/libtomcrypt/demos/timing.c b/libtomcrypt/demos/timing.c index 76fd8cd..14a59df 100644 --- a/libtomcrypt/demos/timing.c +++ b/libtomcrypt/demos/timing.c @@ -1,10 +1,1435 @@ -#include +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + */ +#include -int main(void) +#if defined(_WIN32) + #define PRI64 "I64d" +#else + #define PRI64 "ll" +#endif + +static prng_state yarrow_prng; + +/* timing */ +#define KTIMES 25 +#define TIMES 100000 + +static struct list { + int id; + ulong64 spd1, spd2, avg; +} results[100]; +static int no_results; + +static int sorter(const void *a, const void *b) +{ + const struct list *A, *B; + A = a; + B = b; + if (A->avg < B->avg) return -1; + if (A->avg > B->avg) return 1; + return 0; +} + +static void tally_results(int type) +{ + int x; + + /* qsort the results */ + qsort(results, no_results, sizeof(struct list), &sorter); + + fprintf(stderr, "\n"); + if (type == 0) { + for (x = 0; x < no_results; x++) { + fprintf(stderr, "%-20s: Schedule at %6lu\n", cipher_descriptor[results[x].id].name, (unsigned long)results[x].spd1); + } + } else if (type == 1) { + for (x = 0; x < no_results; x++) { + printf + ("%-20s[%3d]: Encrypt at %5"PRI64"u, Decrypt at %5"PRI64"u\n", cipher_descriptor[results[x].id].name, cipher_descriptor[results[x].id].ID, results[x].spd1, results[x].spd2); + } + } else { + for (x = 0; x < no_results; x++) { + printf + ("%-20s: Process at %5"PRI64"u\n", hash_descriptor[results[x].id].name, results[x].spd1 / 1000); + } + } +} + +/* RDTSC from Scott Duplichan */ +static ulong64 rdtsc (void) + { + #if defined __GNUC__ && !defined(LTC_NO_ASM) + #if defined(__i386__) || defined(__x86_64__) + /* version from http://www.mcs.anl.gov/~kazutomo/rdtsc.html + * the old code always got a warning issued by gcc, clang did not complain... + */ + unsigned hi, lo; + __asm__ __volatile__ ("rdtsc" : "=a"(lo), "=d"(hi)); + return ((ulong64)lo)|( ((ulong64)hi)<<32); + #elif defined(LTC_PPC32) || defined(TFM_PPC32) + unsigned long a, b; + __asm__ __volatile__ ("mftbu %1 \nmftb %0\n":"=r"(a), "=r"(b)); + return (((ulong64)b) << 32ULL) | ((ulong64)a); + #elif defined(__ia64__) /* gcc-IA64 version */ + unsigned long result; + __asm__ __volatile__("mov %0=ar.itc" : "=r"(result) :: "memory"); + while (__builtin_expect ((int) result == -1, 0)) + __asm__ __volatile__("mov %0=ar.itc" : "=r"(result) :: "memory"); + return result; + #elif defined(__sparc__) + #if defined(__arch64__) + ulong64 a; + asm volatile("rd %%tick,%0" : "=r" (a)); + return a; + #else + register unsigned long x, y; + __asm__ __volatile__ ("rd %%tick, %0; clruw %0, %1; srlx %0, 32, %0" : "=r" (x), "=r" (y) : "0" (x), "1" (y)); + return ((unsigned long long) x << 32) | y; + #endif + #else + return XCLOCK(); + #endif + + /* Microsoft and Intel Windows compilers */ + #elif defined _M_IX86 && !defined(LTC_NO_ASM) + __asm rdtsc + #elif defined _M_AMD64 && !defined(LTC_NO_ASM) + return __rdtsc (); + #elif defined _M_IA64 && !defined(LTC_NO_ASM) + #if defined __INTEL_COMPILER + #include + #endif + return __getReg (3116); + #else + return XCLOCK(); + #endif + } + +static ulong64 timer, skew = 0; + +static void t_start(void) +{ + timer = rdtsc(); +} + +static ulong64 t_read(void) +{ + return rdtsc() - timer; +} + +static void init_timer(void) +{ + ulong64 c1, c2, t1, t2; + unsigned long y1; + + c1 = c2 = (ulong64)-1; + for (y1 = 0; y1 < TIMES*100; y1++) { + t_start(); + t1 = t_read(); + t2 = (t_read() - t1)>>1; + + c1 = (t1 > c1) ? t1 : c1; + c2 = (t2 > c2) ? t2 : c2; + } + skew = c2 - c1; + fprintf(stderr, "Clock Skew: %lu\n", (unsigned long)skew); +} + +static void time_keysched(void) +{ + unsigned long x, y1; + ulong64 t1, c1; + symmetric_key skey; + int kl; + int (*func) (const unsigned char *, int , int , symmetric_key *); + unsigned char key[MAXBLOCKSIZE]; + + fprintf(stderr, "\n\nKey Schedule Time Trials for the Symmetric Ciphers:\n(Times are cycles per key)\n"); + no_results = 0; + for (x = 0; cipher_descriptor[x].name != NULL; x++) { +#define DO1(k) func(k, kl, 0, &skey); + + func = cipher_descriptor[x].setup; + kl = cipher_descriptor[x].min_key_length; + c1 = (ulong64)-1; + for (y1 = 0; y1 < KTIMES; y1++) { + yarrow_read(key, kl, &yarrow_prng); + t_start(); + DO1(key); + t1 = t_read(); + c1 = (t1 > c1) ? c1 : t1; + } + t1 = c1 - skew; + results[no_results].spd1 = results[no_results].avg = t1; + results[no_results++].id = x; + fprintf(stderr, "."); fflush(stdout); + +#undef DO1 + } + tally_results(0); +} + +#ifdef LTC_ECB_MODE +static void time_cipher_ecb(void) +{ + unsigned long x, y1; + ulong64 t1, t2, c1, c2, a1, a2; + symmetric_ECB ecb; + unsigned char key[MAXBLOCKSIZE] = { 0 }, pt[4096] = { 0 }; + int err; + + fprintf(stderr, "\n\nECB Time Trials for the Symmetric Ciphers:\n"); + no_results = 0; + for (x = 0; cipher_descriptor[x].name != NULL; x++) { + ecb_start(x, key, cipher_descriptor[x].min_key_length, 0, &ecb); + + /* sanity check on cipher */ + if ((err = cipher_descriptor[x].test()) != CRYPT_OK) { + fprintf(stderr, "\n\nERROR: Cipher %s failed self-test %s\n", cipher_descriptor[x].name, error_to_string(err)); + exit(EXIT_FAILURE); + } + +#define DO1 ecb_encrypt(pt, pt, sizeof(pt), &ecb); +#define DO2 DO1 DO1 + + c1 = c2 = (ulong64)-1; + for (y1 = 0; y1 < 100; y1++) { + t_start(); + DO1; + t1 = t_read(); + DO2; + t2 = t_read(); + t2 -= t1; + + c1 = (t1 > c1 ? c1 : t1); + c2 = (t2 > c2 ? c2 : t2); + } + a1 = c2 - c1 - skew; + +#undef DO1 +#undef DO2 +#define DO1 ecb_decrypt(pt, pt, sizeof(pt), &ecb); +#define DO2 DO1 DO1 + + c1 = c2 = (ulong64)-1; + for (y1 = 0; y1 < 100; y1++) { + t_start(); + DO1; + t1 = t_read(); + DO2; + t2 = t_read(); + t2 -= t1; + + c1 = (t1 > c1 ? c1 : t1); + c2 = (t2 > c2 ? c2 : t2); + } + a2 = c2 - c1 - skew; + ecb_done(&ecb); + + results[no_results].id = x; + results[no_results].spd1 = a1/(sizeof(pt)/cipher_descriptor[x].block_length); + results[no_results].spd2 = a2/(sizeof(pt)/cipher_descriptor[x].block_length); + results[no_results].avg = (results[no_results].spd1 + results[no_results].spd2+1)/2; + ++no_results; + fprintf(stderr, "."); fflush(stdout); + +#undef DO2 +#undef DO1 + } + tally_results(1); +} +#else +static void time_cipher_ecb(void) { fprintf(stderr, "NO ECB\n"); return 0; } +#endif + +#ifdef LTC_CBC_MODE +static void time_cipher_cbc(void) +{ + unsigned long x, y1; + ulong64 t1, t2, c1, c2, a1, a2; + symmetric_CBC cbc; + unsigned char key[MAXBLOCKSIZE] = { 0 }, pt[4096] = { 0 }; + int err; + + fprintf(stderr, "\n\nCBC Time Trials for the Symmetric Ciphers:\n"); + no_results = 0; + for (x = 0; cipher_descriptor[x].name != NULL; x++) { + cbc_start(x, pt, key, cipher_descriptor[x].min_key_length, 0, &cbc); + + /* sanity check on cipher */ + if ((err = cipher_descriptor[x].test()) != CRYPT_OK) { + fprintf(stderr, "\n\nERROR: Cipher %s failed self-test %s\n", cipher_descriptor[x].name, error_to_string(err)); + exit(EXIT_FAILURE); + } + +#define DO1 cbc_encrypt(pt, pt, sizeof(pt), &cbc); +#define DO2 DO1 DO1 + + c1 = c2 = (ulong64)-1; + for (y1 = 0; y1 < 100; y1++) { + t_start(); + DO1; + t1 = t_read(); + DO2; + t2 = t_read(); + t2 -= t1; + + c1 = (t1 > c1 ? c1 : t1); + c2 = (t2 > c2 ? c2 : t2); + } + a1 = c2 - c1 - skew; + +#undef DO1 +#undef DO2 +#define DO1 cbc_decrypt(pt, pt, sizeof(pt), &cbc); +#define DO2 DO1 DO1 + + c1 = c2 = (ulong64)-1; + for (y1 = 0; y1 < 100; y1++) { + t_start(); + DO1; + t1 = t_read(); + DO2; + t2 = t_read(); + t2 -= t1; + + c1 = (t1 > c1 ? c1 : t1); + c2 = (t2 > c2 ? c2 : t2); + } + a2 = c2 - c1 - skew; + cbc_done(&cbc); + + results[no_results].id = x; + results[no_results].spd1 = a1/(sizeof(pt)/cipher_descriptor[x].block_length); + results[no_results].spd2 = a2/(sizeof(pt)/cipher_descriptor[x].block_length); + results[no_results].avg = (results[no_results].spd1 + results[no_results].spd2+1)/2; + ++no_results; + fprintf(stderr, "."); fflush(stdout); + +#undef DO2 +#undef DO1 + } + tally_results(1); +} +#else +static void time_cipher_cbc(void) { fprintf(stderr, "NO CBC\n"); return 0; } +#endif + +#ifdef LTC_CTR_MODE +static void time_cipher_ctr(void) +{ + unsigned long x, y1; + ulong64 t1, t2, c1, c2, a1, a2; + symmetric_CTR ctr; + unsigned char key[MAXBLOCKSIZE] = { 0 }, pt[4096] = { 0 }; + int err; + + fprintf(stderr, "\n\nCTR Time Trials for the Symmetric Ciphers:\n"); + no_results = 0; + for (x = 0; cipher_descriptor[x].name != NULL; x++) { + ctr_start(x, pt, key, cipher_descriptor[x].min_key_length, 0, CTR_COUNTER_LITTLE_ENDIAN, &ctr); + + /* sanity check on cipher */ + if ((err = cipher_descriptor[x].test()) != CRYPT_OK) { + fprintf(stderr, "\n\nERROR: Cipher %s failed self-test %s\n", cipher_descriptor[x].name, error_to_string(err)); + exit(EXIT_FAILURE); + } + +#define DO1 ctr_encrypt(pt, pt, sizeof(pt), &ctr); +#define DO2 DO1 DO1 + + c1 = c2 = (ulong64)-1; + for (y1 = 0; y1 < 100; y1++) { + t_start(); + DO1; + t1 = t_read(); + DO2; + t2 = t_read(); + t2 -= t1; + + c1 = (t1 > c1 ? c1 : t1); + c2 = (t2 > c2 ? c2 : t2); + } + a1 = c2 - c1 - skew; + +#undef DO1 +#undef DO2 +#define DO1 ctr_decrypt(pt, pt, sizeof(pt), &ctr); +#define DO2 DO1 DO1 + + c1 = c2 = (ulong64)-1; + for (y1 = 0; y1 < 100; y1++) { + t_start(); + DO1; + t1 = t_read(); + DO2; + t2 = t_read(); + t2 -= t1; + + c1 = (t1 > c1 ? c1 : t1); + c2 = (t2 > c2 ? c2 : t2); + } + a2 = c2 - c1 - skew; + ctr_done(&ctr); + + results[no_results].id = x; + results[no_results].spd1 = a1/(sizeof(pt)/cipher_descriptor[x].block_length); + results[no_results].spd2 = a2/(sizeof(pt)/cipher_descriptor[x].block_length); + results[no_results].avg = (results[no_results].spd1 + results[no_results].spd2+1)/2; + ++no_results; + fprintf(stderr, "."); fflush(stdout); + +#undef DO2 +#undef DO1 + } + tally_results(1); +} +#else +static void time_cipher_ctr(void) { fprintf(stderr, "NO CTR\n"); return 0; } +#endif + +#ifdef LTC_LRW_MODE +static void time_cipher_lrw(void) +{ + unsigned long x, y1; + ulong64 t1, t2, c1, c2, a1, a2; + symmetric_LRW lrw; + unsigned char key[MAXBLOCKSIZE] = { 0 }, pt[4096] = { 0 }; + int err; + + fprintf(stderr, "\n\nLRW Time Trials for the Symmetric Ciphers:\n"); + no_results = 0; + for (x = 0; cipher_descriptor[x].name != NULL; x++) { + if (cipher_descriptor[x].block_length != 16) continue; + lrw_start(x, pt, key, cipher_descriptor[x].min_key_length, key, 0, &lrw); + + /* sanity check on cipher */ + if ((err = cipher_descriptor[x].test()) != CRYPT_OK) { + fprintf(stderr, "\n\nERROR: Cipher %s failed self-test %s\n", cipher_descriptor[x].name, error_to_string(err)); + exit(EXIT_FAILURE); + } + +#define DO1 lrw_encrypt(pt, pt, sizeof(pt), &lrw); +#define DO2 DO1 DO1 + + c1 = c2 = (ulong64)-1; + for (y1 = 0; y1 < 100; y1++) { + t_start(); + DO1; + t1 = t_read(); + DO2; + t2 = t_read(); + t2 -= t1; + + c1 = (t1 > c1 ? c1 : t1); + c2 = (t2 > c2 ? c2 : t2); + } + a1 = c2 - c1 - skew; + +#undef DO1 +#undef DO2 +#define DO1 lrw_decrypt(pt, pt, sizeof(pt), &lrw); +#define DO2 DO1 DO1 + + c1 = c2 = (ulong64)-1; + for (y1 = 0; y1 < 100; y1++) { + t_start(); + DO1; + t1 = t_read(); + DO2; + t2 = t_read(); + t2 -= t1; + + c1 = (t1 > c1 ? c1 : t1); + c2 = (t2 > c2 ? c2 : t2); + } + a2 = c2 - c1 - skew; + + lrw_done(&lrw); + + results[no_results].id = x; + results[no_results].spd1 = a1/(sizeof(pt)/cipher_descriptor[x].block_length); + results[no_results].spd2 = a2/(sizeof(pt)/cipher_descriptor[x].block_length); + results[no_results].avg = (results[no_results].spd1 + results[no_results].spd2+1)/2; + ++no_results; + fprintf(stderr, "."); fflush(stdout); + +#undef DO2 +#undef DO1 + } + tally_results(1); +} +#else +static void time_cipher_lrw(void) { fprintf(stderr, "NO LRW\n"); return 0; } +#endif + + +static void time_hash(void) +{ + unsigned long x, y1, len; + ulong64 t1, t2, c1, c2; + hash_state md; + int (*func)(hash_state *, const unsigned char *, unsigned long), err; + unsigned char pt[MAXBLOCKSIZE] = { 0 }; + + + fprintf(stderr, "\n\nHASH Time Trials for:\n"); + no_results = 0; + for (x = 0; hash_descriptor[x].name != NULL; x++) { + + /* sanity check on hash */ + if ((err = hash_descriptor[x].test()) != CRYPT_OK) { + fprintf(stderr, "\n\nERROR: Hash %s failed self-test %s\n", hash_descriptor[x].name, error_to_string(err)); + exit(EXIT_FAILURE); + } + + hash_descriptor[x].init(&md); + +#define DO1 func(&md,pt,len); +#define DO2 DO1 DO1 + + func = hash_descriptor[x].process; + len = hash_descriptor[x].blocksize; + + c1 = c2 = (ulong64)-1; + for (y1 = 0; y1 < TIMES; y1++) { + t_start(); + DO1; + t1 = t_read(); + DO2; + t2 = t_read() - t1; + c1 = (t1 > c1) ? c1 : t1; + c2 = (t2 > c2) ? c2 : t2; + } + t1 = c2 - c1 - skew; + t1 = ((t1 * CONST64(1000))) / ((ulong64)hash_descriptor[x].blocksize); + results[no_results].id = x; + results[no_results].spd1 = results[no_results].avg = t1; + ++no_results; + fprintf(stderr, "."); fflush(stdout); +#undef DO2 +#undef DO1 + } + tally_results(2); +} + +/*#warning you need an mp_rand!!!*/ +#if !defined(USE_LTM) && !defined(USE_TFM) && !defined(USE_GMP) && !defined(EXT_MATH_LIB) + #undef LTC_MPI + #undef LTC_TEST_MPI +#else + #define LTC_TEST_MPI +#endif + +#ifdef LTC_MPI +static void time_mult(void) +{ + ulong64 t1, t2; + unsigned long x, y; + void *a, *b, *c; + + fprintf(stderr, "Timing Multiplying:\n"); + mp_init_multi(&a,&b,&c,NULL); + for (x = 128/MP_DIGIT_BIT; x <= (unsigned long)1536/MP_DIGIT_BIT; x += 128/MP_DIGIT_BIT) { + mp_rand(a, x); + mp_rand(b, x); + +#define DO1 mp_mul(a, b, c); +#define DO2 DO1; DO1; + + t2 = -1; + for (y = 0; y < TIMES; y++) { + t_start(); + t1 = t_read(); + DO2; + t1 = (t_read() - t1)>>1; + if (t1 < t2) t2 = t1; + } + fprintf(stderr, "%4lu bits: %9"PRI64"u cycles\n", x*MP_DIGIT_BIT, t2); + } + mp_clear_multi(a,b,c,NULL); + +#undef DO1 +#undef DO2 +} + +static void time_sqr(void) +{ + ulong64 t1, t2; + unsigned long x, y; + void *a, *b; + + fprintf(stderr, "Timing Squaring:\n"); + mp_init_multi(&a,&b,NULL); + for (x = 128/MP_DIGIT_BIT; x <= (unsigned long)1536/MP_DIGIT_BIT; x += 128/MP_DIGIT_BIT) { + mp_rand(a, x); + +#define DO1 mp_sqr(a, b); +#define DO2 DO1; DO1; + + t2 = -1; + for (y = 0; y < TIMES; y++) { + t_start(); + t1 = t_read(); + DO2; + t1 = (t_read() - t1)>>1; + if (t1 < t2) t2 = t1; + } + fprintf(stderr, "%4lu bits: %9"PRI64"u cycles\n", x*MP_DIGIT_BIT, t2); + } + mp_clear_multi(a,b,NULL); + +#undef DO1 +#undef DO2 +} +#else +static void time_mult(void) { fprintf(stderr, "NO MULT\n"); } +static void time_sqr(void) { fprintf(stderr, "NO SQR\n"); } +#endif + +static void time_prng(void) +{ + ulong64 t1, t2; + unsigned char buf[4096]; + prng_state tprng; + unsigned long x, y; + int err; + + fprintf(stderr, "Timing PRNGs (cycles/byte output, cycles add_entropy (32 bytes) :\n"); + for (x = 0; prng_descriptor[x].name != NULL; x++) { + + /* sanity check on prng */ + if ((err = prng_descriptor[x].test()) != CRYPT_OK) { + fprintf(stderr, "\n\nERROR: PRNG %s failed self-test %s\n", prng_descriptor[x].name, error_to_string(err)); + exit(EXIT_FAILURE); + } + + prng_descriptor[x].start(&tprng); + zeromem(buf, 256); + prng_descriptor[x].add_entropy(buf, 256, &tprng); + prng_descriptor[x].ready(&tprng); + t2 = -1; + +#define DO1 if (prng_descriptor[x].read(buf, 4096, &tprng) != 4096) { fprintf(stderr, "\n\nERROR READ != 4096\n\n"); exit(EXIT_FAILURE); } +#define DO2 DO1 DO1 + for (y = 0; y < 10000; y++) { + t_start(); + t1 = t_read(); + DO2; + t1 = (t_read() - t1)>>1; + if (t1 < t2) t2 = t1; + } + fprintf(stderr, "%20s: %5"PRI64"u ", prng_descriptor[x].name, t2>>12); +#undef DO2 +#undef DO1 + +#define DO1 prng_descriptor[x].start(&tprng); prng_descriptor[x].add_entropy(buf, 32, &tprng); prng_descriptor[x].ready(&tprng); prng_descriptor[x].done(&tprng); +#define DO2 DO1 DO1 + for (y = 0; y < 10000; y++) { + t_start(); + t1 = t_read(); + DO2; + t1 = (t_read() - t1)>>1; + if (t1 < t2) t2 = t1; + } + fprintf(stderr, "%5"PRI64"u\n", t2); +#undef DO2 +#undef DO1 + + } +} + +#if defined(LTC_MDSA) && defined(LTC_TEST_MPI) +/* time various DSA operations */ +static void time_dsa(void) +{ + dsa_key key; + ulong64 t1, t2; + unsigned long x, y; + int err; +static const struct { + int group, modulus; +} groups[] = { +{ 20, 96 }, +{ 20, 128 }, +{ 24, 192 }, +{ 28, 256 }, +#ifndef TFM_DESC +{ 32, 512 }, +#endif +}; + + for (x = 0; x < (sizeof(groups)/sizeof(groups[0])); x++) { + t2 = 0; + for (y = 0; y < 4; y++) { + t_start(); + t1 = t_read(); + if ((err = dsa_generate_pqg(&yarrow_prng, find_prng("yarrow"), groups[x].group, groups[x].modulus, &key)) != CRYPT_OK) { + fprintf(stderr, "\n\ndsa_generate_pqg says %s, wait...no it should say %s...damn you!\n", error_to_string(err), error_to_string(CRYPT_OK)); + exit(EXIT_FAILURE); + } + if ((err = dsa_generate_key(&yarrow_prng, find_prng("yarrow"), &key)) != CRYPT_OK) { + fprintf(stderr, "\n\ndsa_make_key says %s, wait...no it should say %s...damn you!\n", error_to_string(err), error_to_string(CRYPT_OK)); + exit(EXIT_FAILURE); + } + t1 = t_read() - t1; + t2 += t1; + +#ifdef LTC_PROFILE + t2 <<= 2; + break; +#endif + if (y < 3) { + dsa_free(&key); + } + } + t2 >>= 2; + fprintf(stderr, "DSA-(%lu, %lu) make_key took %15"PRI64"u cycles\n", (unsigned long)groups[x].group*8, (unsigned long)groups[x].modulus*8, t2); + dsa_free(&key); + } + fprintf(stderr, "\n\n"); +} +#else +static void time_dsa(void) { fprintf(stderr, "NO DSA\n"); } +#endif + + +#if defined(LTC_MRSA) && defined(LTC_TEST_MPI) +/* time various RSA operations */ +static void time_rsa(void) +{ + rsa_key key; + ulong64 t1, t2; + unsigned char buf[2][2048] = { 0 }; + unsigned long x, y, z, zzz; + int err, zz, stat; + + for (x = 1024; x <= 2048; x += 256) { + t2 = 0; + for (y = 0; y < 4; y++) { + t_start(); + t1 = t_read(); + if ((err = rsa_make_key(&yarrow_prng, find_prng("yarrow"), x/8, 65537, &key)) != CRYPT_OK) { + fprintf(stderr, "\n\nrsa_make_key says %s, wait...no it should say %s...damn you!\n", error_to_string(err), error_to_string(CRYPT_OK)); + exit(EXIT_FAILURE); + } + t1 = t_read() - t1; + t2 += t1; + +#ifdef LTC_PROFILE + t2 <<= 2; + break; +#endif + + if (y < 3) { + rsa_free(&key); + } + } + t2 >>= 2; + fprintf(stderr, "RSA-%lu make_key took %15"PRI64"u cycles\n", x, t2); + + t2 = 0; + for (y = 0; y < 16; y++) { + t_start(); + t1 = t_read(); + z = sizeof(buf[1]); + if ((err = rsa_encrypt_key(buf[0], 32, buf[1], &z, (const unsigned char *)"testprog", 8, &yarrow_prng, + find_prng("yarrow"), find_hash("sha1"), + &key)) != CRYPT_OK) { + fprintf(stderr, "\n\nrsa_encrypt_key says %s, wait...no it should say %s...damn you!\n", error_to_string(err), error_to_string(CRYPT_OK)); + exit(EXIT_FAILURE); + } + t1 = t_read() - t1; + t2 += t1; +#ifdef LTC_PROFILE + t2 <<= 4; + break; +#endif + } + t2 >>= 4; + fprintf(stderr, "RSA-%lu encrypt_key took %15"PRI64"u cycles\n", x, t2); + + t2 = 0; + for (y = 0; y < 2048; y++) { + t_start(); + t1 = t_read(); + zzz = sizeof(buf[0]); + if ((err = rsa_decrypt_key(buf[1], z, buf[0], &zzz, (const unsigned char *)"testprog", 8, find_hash("sha1"), + &zz, &key)) != CRYPT_OK) { + fprintf(stderr, "\n\nrsa_decrypt_key says %s, wait...no it should say %s...damn you!\n", error_to_string(err), error_to_string(CRYPT_OK)); + exit(EXIT_FAILURE); + } + t1 = t_read() - t1; + t2 += t1; +#ifdef LTC_PROFILE + t2 <<= 11; + break; +#endif + } + t2 >>= 11; + fprintf(stderr, "RSA-%lu decrypt_key took %15"PRI64"u cycles\n", x, t2); + + t2 = 0; + for (y = 0; y < 256; y++) { + t_start(); + t1 = t_read(); + z = sizeof(buf[1]); + if ((err = rsa_sign_hash(buf[0], 20, buf[1], &z, &yarrow_prng, + find_prng("yarrow"), find_hash("sha1"), 8, &key)) != CRYPT_OK) { + fprintf(stderr, "\n\nrsa_sign_hash says %s, wait...no it should say %s...damn you!\n", error_to_string(err), error_to_string(CRYPT_OK)); + exit(EXIT_FAILURE); + } + t1 = t_read() - t1; + t2 += t1; +#ifdef LTC_PROFILE + t2 <<= 8; + break; +#endif + } + t2 >>= 8; + fprintf(stderr, "RSA-%lu sign_hash took %15"PRI64"u cycles\n", x, t2); + + t2 = 0; + for (y = 0; y < 2048; y++) { + t_start(); + t1 = t_read(); + if ((err = rsa_verify_hash(buf[1], z, buf[0], 20, find_hash("sha1"), 8, &stat, &key)) != CRYPT_OK) { + fprintf(stderr, "\n\nrsa_verify_hash says %s, wait...no it should say %s...damn you!\n", error_to_string(err), error_to_string(CRYPT_OK)); + exit(EXIT_FAILURE); + } + if (stat == 0) { + fprintf(stderr, "\n\nrsa_verify_hash for RSA-%lu failed to verify signature(%lu)\n", x, y); + exit(EXIT_FAILURE); + } + t1 = t_read() - t1; + t2 += t1; +#ifdef LTC_PROFILE + t2 <<= 11; + break; +#endif + } + t2 >>= 11; + fprintf(stderr, "RSA-%lu verify_hash took %15"PRI64"u cycles\n", x, t2); + fprintf(stderr, "\n\n"); + rsa_free(&key); + } +} +#else +static void time_rsa(void) { fprintf(stderr, "NO RSA\n"); } +#endif + +#if defined(LTC_MKAT) && defined(LTC_TEST_MPI) +/* time various KAT operations */ +static void time_katja(void) +{ + katja_key key; + ulong64 t1, t2; + unsigned char buf[2][4096]; + unsigned long x, y, z, zzz; + int err, zz; + + for (x = 1024; x <= 2048; x += 256) { + t2 = 0; + for (y = 0; y < 4; y++) { + t_start(); + t1 = t_read(); + if ((err = katja_make_key(&yarrow_prng, find_prng("yarrow"), x/8, &key)) != CRYPT_OK) { + fprintf(stderr, "\n\nkatja_make_key says %s, wait...no it should say %s...damn you!\n", error_to_string(err), error_to_string(CRYPT_OK)); + exit(EXIT_FAILURE); + } + t1 = t_read() - t1; + t2 += t1; + + if (y < 3) { + katja_free(&key); + } + } + t2 >>= 2; + fprintf(stderr, "Katja-%lu make_key took %15"PRI64"u cycles\n", x, t2); + + t2 = 0; + for (y = 0; y < 16; y++) { + t_start(); + t1 = t_read(); + z = sizeof(buf[1]); + if ((err = katja_encrypt_key(buf[0], 32, buf[1], &z, "testprog", 8, &yarrow_prng, + find_prng("yarrow"), find_hash("sha1"), + &key)) != CRYPT_OK) { + fprintf(stderr, "\n\nkatja_encrypt_key says %s, wait...no it should say %s...damn you!\n", error_to_string(err), error_to_string(CRYPT_OK)); + exit(EXIT_FAILURE); + } + t1 = t_read() - t1; + t2 += t1; + } + t2 >>= 4; + fprintf(stderr, "Katja-%lu encrypt_key took %15"PRI64"u cycles\n", x, t2); + + t2 = 0; + for (y = 0; y < 2048; y++) { + t_start(); + t1 = t_read(); + zzz = sizeof(buf[0]); + if ((err = katja_decrypt_key(buf[1], z, buf[0], &zzz, "testprog", 8, find_hash("sha1"), + &zz, &key)) != CRYPT_OK) { + fprintf(stderr, "\n\nkatja_decrypt_key says %s, wait...no it should say %s...damn you!\n", error_to_string(err), error_to_string(CRYPT_OK)); + exit(EXIT_FAILURE); + } + t1 = t_read() - t1; + t2 += t1; + } + t2 >>= 11; + fprintf(stderr, "Katja-%lu decrypt_key took %15"PRI64"u cycles\n", x, t2); + + + katja_free(&key); + } +} +#else +static void time_katja(void) { fprintf(stderr, "NO Katja\n"); } +#endif + +#if defined(LTC_MDH) && defined(LTC_TEST_MPI) +/* time various DH operations */ +static void time_dh(void) +{ + dh_key key; + ulong64 t1, t2; + unsigned long i, x, y; + int err; + static unsigned long sizes[] = {768/8, 1024/8, 1536/8, 2048/8, +#ifndef TFM_DESC + 3072/8, 4096/8, 6144/8, 8192/8, +#endif + 100000 + }; + + for (x = sizes[i=0]; x < 100000; x = sizes[++i]) { + t2 = 0; + for (y = 0; y < 16; y++) { + if((err = dh_set_pg_groupsize(x, &key)) != CRYPT_OK) { + fprintf(stderr, "\n\ndh_set_pg_groupsize says %s, wait...no it should say %s...damn you!\n", error_to_string(err), error_to_string(CRYPT_OK)); + exit(EXIT_FAILURE); + } + + t_start(); + t1 = t_read(); + if ((err = dh_generate_key(&yarrow_prng, find_prng("yarrow"), &key)) != CRYPT_OK) { + fprintf(stderr, "\n\ndh_make_key says %s, wait...no it should say %s...damn you!\n", error_to_string(err), error_to_string(CRYPT_OK)); + exit(EXIT_FAILURE); + } + t1 = t_read() - t1; + t2 += t1; + + dh_free(&key); + } + t2 >>= 4; + fprintf(stderr, "DH-%4lu make_key took %15"PRI64"u cycles\n", x*8, t2); + } +} +#else +static void time_dh(void) { fprintf(stderr, "NO DH\n"); } +#endif + +#if defined(LTC_MECC) && defined(LTC_TEST_MPI) +/* time various ECC operations */ +static void time_ecc(void) +{ + ecc_key key; + ulong64 t1, t2; + unsigned char buf[2][256] = { 0 }; + unsigned long i, w, x, y, z; + int err, stat; + static unsigned long sizes[] = { +#ifdef LTC_ECC112 +112/8, +#endif +#ifdef LTC_ECC128 +128/8, +#endif +#ifdef LTC_ECC160 +160/8, +#endif +#ifdef LTC_ECC192 +192/8, +#endif +#ifdef LTC_ECC224 +224/8, +#endif +#ifdef LTC_ECC256 +256/8, +#endif +#ifdef LTC_ECC384 +384/8, +#endif +#ifdef LTC_ECC521 +521/8, +#endif +100000}; + + for (x = sizes[i=0]; x < 100000; x = sizes[++i]) { + t2 = 0; + for (y = 0; y < 256; y++) { + t_start(); + t1 = t_read(); + if ((err = ecc_make_key(&yarrow_prng, find_prng("yarrow"), x, &key)) != CRYPT_OK) { + fprintf(stderr, "\n\necc_make_key says %s, wait...no it should say %s...damn you!\n", error_to_string(err), error_to_string(CRYPT_OK)); + exit(EXIT_FAILURE); + } + t1 = t_read() - t1; + t2 += t1; + +#ifdef LTC_PROFILE + t2 <<= 8; + break; +#endif + + if (y < 255) { + ecc_free(&key); + } + } + t2 >>= 8; + fprintf(stderr, "ECC-%lu make_key took %15"PRI64"u cycles\n", x*8, t2); + + t2 = 0; + for (y = 0; y < 256; y++) { + t_start(); + t1 = t_read(); + z = sizeof(buf[1]); + if ((err = ecc_encrypt_key(buf[0], 20, buf[1], &z, &yarrow_prng, find_prng("yarrow"), find_hash("sha1"), + &key)) != CRYPT_OK) { + fprintf(stderr, "\n\necc_encrypt_key says %s, wait...no it should say %s...damn you!\n", error_to_string(err), error_to_string(CRYPT_OK)); + exit(EXIT_FAILURE); + } + t1 = t_read() - t1; + t2 += t1; +#ifdef LTC_PROFILE + t2 <<= 8; + break; +#endif + } + t2 >>= 8; + fprintf(stderr, "ECC-%lu encrypt_key took %15"PRI64"u cycles\n", x*8, t2); + + t2 = 0; + for (y = 0; y < 256; y++) { + t_start(); + t1 = t_read(); + w = 20; + if ((err = ecc_decrypt_key(buf[1], z, buf[0], &w, &key)) != CRYPT_OK) { + fprintf(stderr, "\n\necc_decrypt_key says %s, wait...no it should say %s...damn you!\n", error_to_string(err), error_to_string(CRYPT_OK)); + exit(EXIT_FAILURE); + } + t1 = t_read() - t1; + t2 += t1; +#ifdef LTC_PROFILE + t2 <<= 8; + break; +#endif + } + t2 >>= 8; + fprintf(stderr, "ECC-%lu decrypt_key took %15"PRI64"u cycles\n", x*8, t2); + + t2 = 0; + for (y = 0; y < 256; y++) { + t_start(); + t1 = t_read(); + z = sizeof(buf[1]); + if ((err = ecc_sign_hash(buf[0], 20, buf[1], &z, &yarrow_prng, + find_prng("yarrow"), &key)) != CRYPT_OK) { + fprintf(stderr, "\n\necc_sign_hash says %s, wait...no it should say %s...damn you!\n", error_to_string(err), error_to_string(CRYPT_OK)); + exit(EXIT_FAILURE); + } + t1 = t_read() - t1; + t2 += t1; +#ifdef LTC_PROFILE + t2 <<= 8; + break; +#endif + } + t2 >>= 8; + fprintf(stderr, "ECC-%lu sign_hash took %15"PRI64"u cycles\n", x*8, t2); + + t2 = 0; + for (y = 0; y < 256; y++) { + t_start(); + t1 = t_read(); + if ((err = ecc_verify_hash(buf[1], z, buf[0], 20, &stat, &key)) != CRYPT_OK) { + fprintf(stderr, "\n\necc_verify_hash says %s, wait...no it should say %s...damn you!\n", error_to_string(err), error_to_string(CRYPT_OK)); + exit(EXIT_FAILURE); + } + if (stat == 0) { + fprintf(stderr, "\n\necc_verify_hash for ECC-%lu failed to verify signature(%lu)\n", x*8, y); + exit(EXIT_FAILURE); + } + t1 = t_read() - t1; + t2 += t1; +#ifdef LTC_PROFILE + t2 <<= 8; + break; +#endif + } + t2 >>= 8; + fprintf(stderr, "ECC-%lu verify_hash took %15"PRI64"u cycles\n", x*8, t2); + + fprintf(stderr, "\n\n"); + ecc_free(&key); + } +} +#else +static void time_ecc(void) { fprintf(stderr, "NO ECC\n"); } +#endif + +static void time_macs_(unsigned long MAC_SIZE) +{ +#if defined(LTC_OMAC) || defined(LTC_XCBC) || defined(LTC_F9_MODE) || defined(LTC_PMAC) || defined(LTC_PELICAN) || defined(LTC_HMAC) + unsigned char *buf, key[16], tag[16]; + ulong64 t1, t2; + unsigned long x, z; + int err, cipher_idx, hash_idx; + + fprintf(stderr, "\nMAC Timings (cycles/byte on %luKB blocks):\n", MAC_SIZE); + + buf = XMALLOC(MAC_SIZE*1024); + if (buf == NULL) { + fprintf(stderr, "\n\nout of heap yo\n\n"); + exit(EXIT_FAILURE); + } + + cipher_idx = find_cipher("aes"); + hash_idx = find_hash("sha1"); + + if (cipher_idx == -1 || hash_idx == -1) { + fprintf(stderr, "Warning the MAC tests requires AES and SHA1 to operate... so sorry\n"); + exit(EXIT_FAILURE); + } + + yarrow_read(buf, MAC_SIZE*1024, &yarrow_prng); + yarrow_read(key, 16, &yarrow_prng); + +#ifdef LTC_OMAC + t2 = -1; + for (x = 0; x < 10000; x++) { + t_start(); + t1 = t_read(); + z = 16; + if ((err = omac_memory(cipher_idx, key, 16, buf, MAC_SIZE*1024, tag, &z)) != CRYPT_OK) { + fprintf(stderr, "\n\nomac-%s error... %s\n", cipher_descriptor[cipher_idx].name, error_to_string(err)); + exit(EXIT_FAILURE); + } + t1 = t_read() - t1; + if (t1 < t2) t2 = t1; + } + fprintf(stderr, "OMAC-%s\t\t%9"PRI64"u\n", cipher_descriptor[cipher_idx].name, t2/(ulong64)(MAC_SIZE*1024)); +#endif + +#ifdef LTC_XCBC + t2 = -1; + for (x = 0; x < 10000; x++) { + t_start(); + t1 = t_read(); + z = 16; + if ((err = xcbc_memory(cipher_idx, key, 16, buf, MAC_SIZE*1024, tag, &z)) != CRYPT_OK) { + fprintf(stderr, "\n\nxcbc-%s error... %s\n", cipher_descriptor[cipher_idx].name, error_to_string(err)); + exit(EXIT_FAILURE); + } + t1 = t_read() - t1; + if (t1 < t2) t2 = t1; + } + fprintf(stderr, "XCBC-%s\t\t%9"PRI64"u\n", cipher_descriptor[cipher_idx].name, t2/(ulong64)(MAC_SIZE*1024)); +#endif + +#ifdef LTC_F9_MODE + t2 = -1; + for (x = 0; x < 10000; x++) { + t_start(); + t1 = t_read(); + z = 16; + if ((err = f9_memory(cipher_idx, key, 16, buf, MAC_SIZE*1024, tag, &z)) != CRYPT_OK) { + fprintf(stderr, "\n\nF9-%s error... %s\n", cipher_descriptor[cipher_idx].name, error_to_string(err)); + exit(EXIT_FAILURE); + } + t1 = t_read() - t1; + if (t1 < t2) t2 = t1; + } + fprintf(stderr, "F9-%s\t\t\t%9"PRI64"u\n", cipher_descriptor[cipher_idx].name, t2/(ulong64)(MAC_SIZE*1024)); +#endif + +#ifdef LTC_PMAC + t2 = -1; + for (x = 0; x < 10000; x++) { + t_start(); + t1 = t_read(); + z = 16; + if ((err = pmac_memory(cipher_idx, key, 16, buf, MAC_SIZE*1024, tag, &z)) != CRYPT_OK) { + fprintf(stderr, "\n\npmac-%s error... %s\n", cipher_descriptor[cipher_idx].name, error_to_string(err)); + exit(EXIT_FAILURE); + } + t1 = t_read() - t1; + if (t1 < t2) t2 = t1; + } + fprintf(stderr, "PMAC-%s\t\t%9"PRI64"u\n", cipher_descriptor[cipher_idx].name, t2/(ulong64)(MAC_SIZE*1024)); +#endif + +#ifdef LTC_PELICAN + t2 = -1; + for (x = 0; x < 10000; x++) { + t_start(); + t1 = t_read(); + z = 16; + if ((err = pelican_memory(key, 16, buf, MAC_SIZE*1024, tag)) != CRYPT_OK) { + fprintf(stderr, "\n\npelican error... %s\n", error_to_string(err)); + exit(EXIT_FAILURE); + } + t1 = t_read() - t1; + if (t1 < t2) t2 = t1; + } + fprintf(stderr, "PELICAN \t\t%9"PRI64"u\n", t2/(ulong64)(MAC_SIZE*1024)); +#endif + +#ifdef LTC_HMAC + t2 = -1; + for (x = 0; x < 10000; x++) { + t_start(); + t1 = t_read(); + z = 16; + if ((err = hmac_memory(hash_idx, key, 16, buf, MAC_SIZE*1024, tag, &z)) != CRYPT_OK) { + fprintf(stderr, "\n\nhmac-%s error... %s\n", hash_descriptor[hash_idx].name, error_to_string(err)); + exit(EXIT_FAILURE); + } + t1 = t_read() - t1; + if (t1 < t2) t2 = t1; + } + fprintf(stderr, "HMAC-%s\t\t%9"PRI64"u\n", hash_descriptor[hash_idx].name, t2/(ulong64)(MAC_SIZE*1024)); +#endif + + XFREE(buf); +#else + LTC_UNUSED_PARAM(MAC_SIZE); + fprintf(stderr, "NO MACs\n"); +#endif +} + +static void time_macs(void) +{ + time_macs_(1); + time_macs_(4); + time_macs_(32); +} + +static void time_encmacs_(unsigned long MAC_SIZE) +{ +#if defined(LTC_EAX_MODE) || defined(LTC_OCB_MODE) || defined(LTC_OCB3_MODE) || defined(LTC_CCM_MODE) || defined(LTC_GCM_MODE) + unsigned char *buf, IV[16], key[16], tag[16]; + ulong64 t1, t2; + unsigned long x, z; + int err, cipher_idx; + symmetric_key skey; + + fprintf(stderr, "\nENC+MAC Timings (zero byte AAD, 16 byte IV, cycles/byte on %luKB blocks):\n", MAC_SIZE); + + buf = XMALLOC(MAC_SIZE*1024); + if (buf == NULL) { + fprintf(stderr, "\n\nout of heap yo\n\n"); + exit(EXIT_FAILURE); + } + + cipher_idx = find_cipher("aes"); + + yarrow_read(buf, MAC_SIZE*1024, &yarrow_prng); + yarrow_read(key, 16, &yarrow_prng); + yarrow_read(IV, 16, &yarrow_prng); + +#ifdef LTC_EAX_MODE + t2 = -1; + for (x = 0; x < 10000; x++) { + t_start(); + t1 = t_read(); + z = 16; + if ((err = eax_encrypt_authenticate_memory(cipher_idx, key, 16, IV, 16, NULL, 0, buf, MAC_SIZE*1024, buf, tag, &z)) != CRYPT_OK) { + fprintf(stderr, "\nEAX error... %s\n", error_to_string(err)); + exit(EXIT_FAILURE); + } + t1 = t_read() - t1; + if (t1 < t2) t2 = t1; + } + fprintf(stderr, "EAX \t\t\t%9"PRI64"u\n", t2/(ulong64)(MAC_SIZE*1024)); +#endif + +#ifdef LTC_OCB_MODE + t2 = -1; + for (x = 0; x < 10000; x++) { + t_start(); + t1 = t_read(); + z = 16; + if ((err = ocb_encrypt_authenticate_memory(cipher_idx, key, 16, IV, buf, MAC_SIZE*1024, buf, tag, &z)) != CRYPT_OK) { + fprintf(stderr, "\nOCB error... %s\n", error_to_string(err)); + exit(EXIT_FAILURE); + } + t1 = t_read() - t1; + if (t1 < t2) t2 = t1; + } + fprintf(stderr, "OCB \t\t\t%9"PRI64"u\n", t2/(ulong64)(MAC_SIZE*1024)); +#endif + +#ifdef LTC_OCB3_MODE + t2 = -1; + for (x = 0; x < 10000; x++) { + t_start(); + t1 = t_read(); + z = 16; + if ((err = ocb3_encrypt_authenticate_memory(cipher_idx, key, 16, IV, 15, (unsigned char*)"", 0, buf, MAC_SIZE*1024, buf, tag, &z)) != CRYPT_OK) { + fprintf(stderr, "\nOCB3 error... %s\n", error_to_string(err)); + exit(EXIT_FAILURE); + } + t1 = t_read() - t1; + if (t1 < t2) t2 = t1; + } + fprintf(stderr, "OCB3 \t\t\t%9"PRI64"u\n", t2/(ulong64)(MAC_SIZE*1024)); +#endif + +#ifdef LTC_CCM_MODE + t2 = -1; + for (x = 0; x < 10000; x++) { + t_start(); + t1 = t_read(); + z = 16; + if ((err = ccm_memory(cipher_idx, key, 16, NULL, IV, 16, NULL, 0, buf, MAC_SIZE*1024, buf, tag, &z, CCM_ENCRYPT)) != CRYPT_OK) { + fprintf(stderr, "\nCCM error... %s\n", error_to_string(err)); + exit(EXIT_FAILURE); + } + t1 = t_read() - t1; + if (t1 < t2) t2 = t1; + } + fprintf(stderr, "CCM (no-precomp) \t%9"PRI64"u\n", t2/(ulong64)(MAC_SIZE*1024)); + + cipher_descriptor[cipher_idx].setup(key, 16, 0, &skey); + t2 = -1; + for (x = 0; x < 10000; x++) { + t_start(); + t1 = t_read(); + z = 16; + if ((err = ccm_memory(cipher_idx, key, 16, &skey, IV, 16, NULL, 0, buf, MAC_SIZE*1024, buf, tag, &z, CCM_ENCRYPT)) != CRYPT_OK) { + fprintf(stderr, "\nCCM error... %s\n", error_to_string(err)); + exit(EXIT_FAILURE); + } + t1 = t_read() - t1; + if (t1 < t2) t2 = t1; + } + fprintf(stderr, "CCM (precomp) \t\t%9"PRI64"u\n", t2/(ulong64)(MAC_SIZE*1024)); + cipher_descriptor[cipher_idx].done(&skey); +#endif + +#ifdef LTC_GCM_MODE + t2 = -1; + for (x = 0; x < 100; x++) { + t_start(); + t1 = t_read(); + z = 16; + if ((err = gcm_memory(cipher_idx, key, 16, IV, 16, NULL, 0, buf, MAC_SIZE*1024, buf, tag, &z, GCM_ENCRYPT)) != CRYPT_OK) { + fprintf(stderr, "\nGCM error... %s\n", error_to_string(err)); + exit(EXIT_FAILURE); + } + t1 = t_read() - t1; + if (t1 < t2) t2 = t1; + } + fprintf(stderr, "GCM (no-precomp)\t%9"PRI64"u\n", t2/(ulong64)(MAC_SIZE*1024)); + + { + gcm_state gcm +#ifdef LTC_GCM_TABLES_SSE2 +__attribute__ ((aligned (16))) +#endif +; + + if ((err = gcm_init(&gcm, cipher_idx, key, 16)) != CRYPT_OK) { fprintf(stderr, "gcm_init: %s\n", error_to_string(err)); exit(EXIT_FAILURE); } + t2 = -1; + for (x = 0; x < 10000; x++) { + t_start(); + t1 = t_read(); + z = 16; + if ((err = gcm_reset(&gcm)) != CRYPT_OK) { + fprintf(stderr, "\nGCM error[%d]... %s\n", __LINE__, error_to_string(err)); + exit(EXIT_FAILURE); + } + if ((err = gcm_add_iv(&gcm, IV, 16)) != CRYPT_OK) { + fprintf(stderr, "\nGCM error[%d]... %s\n", __LINE__, error_to_string(err)); + exit(EXIT_FAILURE); + } + if ((err = gcm_add_aad(&gcm, NULL, 0)) != CRYPT_OK) { + fprintf(stderr, "\nGCM error[%d]... %s\n", __LINE__, error_to_string(err)); + exit(EXIT_FAILURE); + } + if ((err = gcm_process(&gcm, buf, MAC_SIZE*1024, buf, GCM_ENCRYPT)) != CRYPT_OK) { + fprintf(stderr, "\nGCM error[%d]... %s\n", __LINE__, error_to_string(err)); + exit(EXIT_FAILURE); + } + + if ((err = gcm_done(&gcm, tag, &z)) != CRYPT_OK) { + fprintf(stderr, "\nGCM error[%d]... %s\n", __LINE__, error_to_string(err)); + exit(EXIT_FAILURE); + } + t1 = t_read() - t1; + if (t1 < t2) t2 = t1; + } + fprintf(stderr, "GCM (precomp)\t\t%9"PRI64"u\n", t2/(ulong64)(MAC_SIZE*1024)); + } + +#endif + XFREE(buf); +#else + LTC_UNUSED_PARAM(MAC_SIZE); + fprintf(stderr, "NO ENCMACs\n"); +#endif + +} + +static void time_encmacs(void) +{ + time_encmacs_(1); + time_encmacs_(4); + time_encmacs_(32); +} + +#define LTC_TEST_FN(f) { f, #f } +int main(int argc, char **argv) +{ +int err; + +const struct { + void (*fn)(void); + const char* name; +} test_functions[] = { + LTC_TEST_FN(time_keysched), + LTC_TEST_FN(time_cipher_ecb), + LTC_TEST_FN(time_cipher_cbc), + LTC_TEST_FN(time_cipher_ctr), + LTC_TEST_FN(time_cipher_lrw), + LTC_TEST_FN(time_hash), + LTC_TEST_FN(time_macs), + LTC_TEST_FN(time_encmacs), + LTC_TEST_FN(time_prng), + LTC_TEST_FN(time_mult), + LTC_TEST_FN(time_sqr), + LTC_TEST_FN(time_rsa), + LTC_TEST_FN(time_dsa), + LTC_TEST_FN(time_ecc), + LTC_TEST_FN(time_dh), + LTC_TEST_FN(time_katja) +}; +char *single_test = NULL; +unsigned int i; init_timer(); -reg_algs(); +register_all_ciphers(); +register_all_hashes(); +register_all_prngs(); #ifdef USE_LTM ltc_mp = ltm_desc; @@ -12,31 +1437,32 @@ reg_algs(); ltc_mp = tfm_desc; #elif defined(USE_GMP) ltc_mp = gmp_desc; -#else - extern ltc_math_descriptor EXT_MATH_LIB; - ltc_mp = EXT_MATH_LIB; -#endif - -time_keysched(); -time_cipher(); -time_cipher2(); -time_cipher3(); -time_cipher4(); -time_hash(); -time_macs(); -time_encmacs(); -time_prng(); -time_mult(); -time_sqr(); -time_rsa(); -time_ecc(); -#ifdef USE_LTM -time_katja(); +#elif defined(EXT_MATH_LIB) + { + extern ltc_math_descriptor EXT_MATH_LIB; + ltc_mp = EXT_MATH_LIB; + } #endif + +if ((err = rng_make_prng(128, find_prng("yarrow"), &yarrow_prng, NULL)) != CRYPT_OK) { + fprintf(stderr, "rng_make_prng failed: %s\n", error_to_string(err)); + exit(EXIT_FAILURE); +} + +/* single test name from commandline */ +if (argc > 1) single_test = argv[1]; + +for (i = 0; i < sizeof(test_functions)/sizeof(test_functions[0]); ++i) { + if (single_test && strstr(test_functions[i].name, single_test) == NULL) { + continue; + } + test_functions[i].fn(); +} + return EXIT_SUCCESS; } -/* $Source$ */ -/* $Revision$ */ -/* $Date$ */ +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ diff --git a/libtomcrypt/demos/tv_gen.c b/libtomcrypt/demos/tv_gen.c index 4518ebd..127c114 100644 --- a/libtomcrypt/demos/tv_gen.c +++ b/libtomcrypt/demos/tv_gen.c @@ -1,129 +1,25 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + */ #include -void reg_algs(void) -{ - int err; - -#ifdef LTC_RIJNDAEL - register_cipher (&aes_desc); -#endif -#ifdef LTC_BLOWFISH - register_cipher (&blowfish_desc); -#endif -#ifdef LTC_XTEA - register_cipher (&xtea_desc); -#endif -#ifdef LTC_RC5 - register_cipher (&rc5_desc); -#endif -#ifdef LTC_RC6 - register_cipher (&rc6_desc); -#endif -#ifdef LTC_SAFERP - register_cipher (&saferp_desc); -#endif -#ifdef LTC_TWOFISH - register_cipher (&twofish_desc); -#endif -#ifdef LTC_SAFER - register_cipher (&safer_k64_desc); - register_cipher (&safer_sk64_desc); - register_cipher (&safer_k128_desc); - register_cipher (&safer_sk128_desc); -#endif -#ifdef LTC_RC2 - register_cipher (&rc2_desc); -#endif -#ifdef LTC_DES - register_cipher (&des_desc); - register_cipher (&des3_desc); -#endif -#ifdef LTC_CAST5 - register_cipher (&cast5_desc); -#endif -#ifdef LTC_NOEKEON - register_cipher (&noekeon_desc); -#endif -#ifdef LTC_SKIPJACK - register_cipher (&skipjack_desc); -#endif -#ifdef LTC_ANUBIS - register_cipher (&anubis_desc); -#endif -#ifdef LTC_KHAZAD - register_cipher (&khazad_desc); -#endif - -#ifdef LTC_TIGER - register_hash (&tiger_desc); -#endif -#ifdef LTC_MD2 - register_hash (&md2_desc); -#endif -#ifdef LTC_MD4 - register_hash (&md4_desc); -#endif -#ifdef LTC_MD5 - register_hash (&md5_desc); -#endif -#ifdef LTC_SHA1 - register_hash (&sha1_desc); -#endif -#ifdef LTC_SHA224 - register_hash (&sha224_desc); -#endif -#ifdef LTC_SHA256 - register_hash (&sha256_desc); -#endif -#ifdef LTC_SHA384 - register_hash (&sha384_desc); -#endif -#ifdef LTC_SHA512 - register_hash (&sha512_desc); -#endif -#ifdef LTC_RIPEMD128 - register_hash (&rmd128_desc); -#endif -#ifdef LTC_RIPEMD160 - register_hash (&rmd160_desc); -#endif -#ifdef LTC_WHIRLPOOL - register_hash (&whirlpool_desc); -#endif -#ifdef LTC_CHC_HASH - register_hash(&chc_desc); - if ((err = chc_register(register_cipher(&aes_desc))) != CRYPT_OK) { - printf("chc_register error: %s\n", error_to_string(err)); - exit(EXIT_FAILURE); - } -#endif - -#ifdef USE_LTM - ltc_mp = ltm_desc; -#elif defined(USE_TFM) - ltc_mp = tfm_desc; -#elif defined(USE_GMP) - ltc_mp = gmp_desc; -#else - extern ltc_math_descriptor EXT_MATH_LIB; - ltc_mp = EXT_MATH_LIB; -#endif - - -} - void hash_gen(void) { unsigned char md[MAXBLOCKSIZE], *buf; unsigned long outlen, x, y, z; FILE *out; int err; - + out = fopen("hash_tv.txt", "w"); if (out == NULL) { perror("can't open hash_tv"); } - + fprintf(out, "Hash Test Vectors:\n\nThese are the hashes of nn bytes '00 01 02 03 .. (nn-1)'\n\n"); for (x = 0; hash_descriptor[x].name != NULL; x++) { buf = XMALLOC(2 * hash_descriptor[x].blocksize + 1); @@ -160,16 +56,16 @@ void cipher_gen(void) int err, kl, lastkl; FILE *out; symmetric_key skey; - + out = fopen("cipher_tv.txt", "w"); - - fprintf(out, + + fprintf(out, "Cipher Test Vectors\n\nThese are test encryptions with key of nn bytes '00 01 02 03 .. (nn-1)' and original PT of the same style.\n" "The output of step N is used as the key and plaintext for step N+1 (key bytes repeated as required to fill the key)\n\n"); - + for (x = 0; cipher_descriptor[x].name != NULL; x++) { fprintf(out, "Cipher: %s\n", cipher_descriptor[x].name); - + /* three modes, smallest, medium, large keys */ lastkl = 10000; for (y = 0; y < 3; y++) { @@ -199,7 +95,7 @@ void cipher_gen(void) printf("setup error: %s\n", error_to_string(err)); exit(EXIT_FAILURE); } - + for (z = 0; (int)z < cipher_descriptor[x].block_length; z++) { pt[z] = (unsigned char)z; } @@ -226,7 +122,7 @@ void cipher_gen(void) fprintf(out, "\n"); } fclose(out); -} +} void hmac_gen(void) { @@ -234,17 +130,17 @@ void hmac_gen(void) int x, y, z, err; FILE *out; unsigned long len; - + out = fopen("hmac_tv.txt", "w"); - fprintf(out, -"LTC_HMAC Tests. In these tests messages of N bytes long (00,01,02,...,NN-1) are LTC_HMACed. The initial key is\n" -"of the same format (the same length as the HASH output size). The LTC_HMAC key in step N+1 is the LTC_HMAC output of\n" + fprintf(out, +"HMAC Tests. In these tests messages of N bytes long (00,01,02,...,NN-1) are HMACed. The initial key is\n" +"of the same format (the same length as the HASH output size). The HMAC key in step N+1 is the HMAC output of\n" "step N.\n\n"); for (x = 0; hash_descriptor[x].name != NULL; x++) { - fprintf(out, "LTC_HMAC-%s\n", hash_descriptor[x].name); - + fprintf(out, "HMAC-%s\n", hash_descriptor[x].name); + /* initial key */ for (y = 0; y < (int)hash_descriptor[x].hashsize; y++) { key[y] = (y&255); @@ -255,7 +151,7 @@ void hmac_gen(void) perror("Can't malloc memory"); exit(EXIT_FAILURE); } - + for (y = 0; y <= (int)(hash_descriptor[x].blocksize * 2); y++) { for (z = 0; z < y; z++) { input[z] = (unsigned char)(z & 255); @@ -279,19 +175,20 @@ void hmac_gen(void) } fclose(out); } - + void omac_gen(void) { +#ifdef LTC_OMAC unsigned char key[MAXBLOCKSIZE], output[MAXBLOCKSIZE], input[MAXBLOCKSIZE*2+2]; int err, x, y, z, kl; FILE *out; unsigned long len; - + out = fopen("omac_tv.txt", "w"); - fprintf(out, -"LTC_OMAC Tests. In these tests messages of N bytes long (00,01,02,...,NN-1) are LTC_OMAC'ed. The initial key is\n" -"of the same format (length specified per cipher). The LTC_OMAC key in step N+1 is the LTC_OMAC output of\n" + fprintf(out, +"OMAC Tests. In these tests messages of N bytes long (00,01,02,...,NN-1) are OMAC'ed. The initial key is\n" +"of the same format (length specified per cipher). The OMAC key in step N+1 is the OMAC output of\n" "step N (repeated as required to fill the array).\n\n"); for (x = 0; cipher_descriptor[x].name != NULL; x++) { @@ -303,13 +200,13 @@ void omac_gen(void) if (cipher_descriptor[x].keysize(&kl) != CRYPT_OK) { kl = cipher_descriptor[x].max_key_length; } - fprintf(out, "LTC_OMAC-%s (%d byte key)\n", cipher_descriptor[x].name, kl); - + fprintf(out, "OMAC-%s (%d byte key)\n", cipher_descriptor[x].name, kl); + /* initial key/block */ for (y = 0; y < kl; y++) { key[y] = (y & 255); } - + for (y = 0; y <= (int)(cipher_descriptor[x].block_length*2); y++) { for (z = 0; z < y; z++) { input[z] = (unsigned char)(z & 255); @@ -333,20 +230,22 @@ void omac_gen(void) fprintf(out, "\n"); } fclose(out); +#endif } void pmac_gen(void) { +#ifdef LTC_PMAC unsigned char key[MAXBLOCKSIZE], output[MAXBLOCKSIZE], input[MAXBLOCKSIZE*2+2]; int err, x, y, z, kl; FILE *out; unsigned long len; - + out = fopen("pmac_tv.txt", "w"); - fprintf(out, -"PMAC Tests. In these tests messages of N bytes long (00,01,02,...,NN-1) are LTC_OMAC'ed. The initial key is\n" -"of the same format (length specified per cipher). The LTC_OMAC key in step N+1 is the LTC_OMAC output of\n" + fprintf(out, +"PMAC Tests. In these tests messages of N bytes long (00,01,02,...,NN-1) are PMAC'ed. The initial key is\n" +"of the same format (length specified per cipher). The PMAC key in step N+1 is the PMAC output of\n" "step N (repeated as required to fill the array).\n\n"); for (x = 0; cipher_descriptor[x].name != NULL; x++) { @@ -359,12 +258,12 @@ void pmac_gen(void) kl = cipher_descriptor[x].max_key_length; } fprintf(out, "PMAC-%s (%d byte key)\n", cipher_descriptor[x].name, kl); - + /* initial key/block */ for (y = 0; y < kl; y++) { key[y] = (y & 255); } - + for (y = 0; y <= (int)(cipher_descriptor[x].block_length*2); y++) { for (z = 0; z < y; z++) { input[z] = (unsigned char)(z & 255); @@ -388,13 +287,15 @@ void pmac_gen(void) fprintf(out, "\n"); } fclose(out); +#endif } void eax_gen(void) { +#ifdef LTC_EAX_MODE int err, kl, x, y1, z; FILE *out; - unsigned char key[MAXBLOCKSIZE], nonce[MAXBLOCKSIZE*2], header[MAXBLOCKSIZE*2], + unsigned char key[MAXBLOCKSIZE], nonce[MAXBLOCKSIZE*2], header[MAXBLOCKSIZE*2], plaintext[MAXBLOCKSIZE*2], tag[MAXBLOCKSIZE]; unsigned long len; @@ -418,7 +319,7 @@ void eax_gen(void) for (z = 0; z < kl; z++) { key[z] = (z & 255); } - + for (y1 = 0; y1 <= (int)(cipher_descriptor[x].block_length*2); y1++){ for (z = 0; z < y1; z++) { plaintext[z] = (unsigned char)(z & 255); @@ -448,13 +349,15 @@ void eax_gen(void) fprintf(out, "\n"); } fclose(out); +#endif } void ocb_gen(void) { +#ifdef LTC_OCB_MODE int err, kl, x, y1, z; FILE *out; - unsigned char key[MAXBLOCKSIZE], nonce[MAXBLOCKSIZE*2], + unsigned char key[MAXBLOCKSIZE], nonce[MAXBLOCKSIZE*2], plaintext[MAXBLOCKSIZE*2], tag[MAXBLOCKSIZE]; unsigned long len; @@ -483,7 +386,7 @@ void ocb_gen(void) for (z = 0; z < cipher_descriptor[x].block_length; z++) { nonce[z] = z; } - + for (y1 = 0; y1 <= (int)(cipher_descriptor[x].block_length*2); y1++){ for (z = 0; z < y1; z++) { plaintext[z] = (unsigned char)(z & 255); @@ -511,14 +414,81 @@ void ocb_gen(void) fprintf(out, "\n"); } fclose(out); +#endif } +void ocb3_gen(void) +{ +#ifdef LTC_OCB3_MODE + int err, kl, x, y1, z, noncelen; + FILE *out; + unsigned char key[MAXBLOCKSIZE], nonce[MAXBLOCKSIZE*2], + plaintext[MAXBLOCKSIZE*2], tag[MAXBLOCKSIZE]; + unsigned long len; + + out = fopen("ocb3_tv.txt", "w"); + fprintf(out, "OCB3 Test Vectors. Uses the 00010203...NN-1 pattern for nonce/plaintext/key. The outputs\n" + "are of the form ciphertext,tag for a given NN. The key for step N>1 is the tag of the previous\n" + "step repeated sufficiently. The nonce is fixed throughout. AAD is fixed to 3 bytes (ASCII) 'AAD'.\n\n"); + + for (x = 0; cipher_descriptor[x].name != NULL; x++) { + kl = cipher_descriptor[x].block_length; + + /* skip ciphers which do not have 64 or 128 bit block sizes */ + if (kl != 16) continue; + + if (cipher_descriptor[x].keysize(&kl) != CRYPT_OK) { + kl = cipher_descriptor[x].max_key_length; + } + fprintf(out, "OCB3-%s (%d byte key)\n", cipher_descriptor[x].name, kl); + + /* the key */ + for (z = 0; z < kl; z++) { + key[z] = (z & 255); + } + + /* fixed nonce */ + noncelen = MIN(15, cipher_descriptor[x].block_length); + for (z = 0; z < noncelen; z++) { + nonce[z] = z; + } + + for (y1 = 0; y1 <= (int)(cipher_descriptor[x].block_length*2); y1++){ + for (z = 0; z < y1; z++) { + plaintext[z] = (unsigned char)(z & 255); + } + len = 16; + if ((err = ocb3_encrypt_authenticate_memory(x, key, kl, nonce, noncelen, (unsigned char*)"AAD", 3, plaintext, y1, plaintext, tag, &len)) != CRYPT_OK) { + printf("Error OCB3'ing: %s\n", error_to_string(err)); + exit(EXIT_FAILURE); + } + fprintf(out, "%3d: ", y1); + for (z = 0; z < y1; z++) { + fprintf(out, "%02X", plaintext[z]); + } + fprintf(out, ", "); + for (z = 0; z <(int)len; z++) { + fprintf(out, "%02X", tag[z]); + } + fprintf(out, "\n"); + + /* forward the key */ + for (z = 0; z < kl; z++) { + key[z] = tag[z % len]; + } + } + fprintf(out, "\n"); + } + fclose(out); +#endif +} void ccm_gen(void) { +#ifdef LTC_CCM_MODE int err, kl, x, y1, z; FILE *out; - unsigned char key[MAXBLOCKSIZE], nonce[MAXBLOCKSIZE*2], + unsigned char key[MAXBLOCKSIZE], nonce[MAXBLOCKSIZE*2], plaintext[MAXBLOCKSIZE*2], tag[MAXBLOCKSIZE]; unsigned long len; @@ -547,7 +517,7 @@ void ccm_gen(void) for (z = 0; z < cipher_descriptor[x].block_length; z++) { nonce[z] = z; } - + for (y1 = 0; y1 <= (int)(cipher_descriptor[x].block_length*2); y1++){ for (z = 0; z < y1; z++) { plaintext[z] = (unsigned char)(z & 255); @@ -557,6 +527,10 @@ void ccm_gen(void) printf("Error CCM'ing: %s\n", error_to_string(err)); exit(EXIT_FAILURE); } + if (len == 0) { + printf("Error CCM'ing: zero length\n"); + exit(EXIT_FAILURE); + } fprintf(out, "%3d: ", y1); for (z = 0; z < y1; z++) { fprintf(out, "%02X", plaintext[z]); @@ -575,10 +549,12 @@ void ccm_gen(void) fprintf(out, "\n"); } fclose(out); +#endif } void gcm_gen(void) { +#ifdef LTC_GCM_MODE int err, kl, x, y1, z; FILE *out; unsigned char key[MAXBLOCKSIZE], plaintext[MAXBLOCKSIZE*2], tag[MAXBLOCKSIZE]; @@ -604,8 +580,8 @@ void gcm_gen(void) for (z = 0; z < kl; z++) { key[z] = (z & 255); } - - for (y1 = 0; y1 <= (int)(cipher_descriptor[x].block_length*2); y1++){ + + for (y1 = 1; y1 <= (int)(cipher_descriptor[x].block_length*2); y1++){ for (z = 0; z < y1; z++) { plaintext[z] = (unsigned char)(z & 255); } @@ -614,6 +590,10 @@ void gcm_gen(void) printf("Error GCM'ing: %s\n", error_to_string(err)); exit(EXIT_FAILURE); } + if (len == 0) { + printf("Error GCM'ing: zero length\n"); + exit(EXIT_FAILURE); + } fprintf(out, "%3d: ", y1); for (z = 0; z < y1; z++) { fprintf(out, "%02X", plaintext[z]); @@ -632,19 +612,20 @@ void gcm_gen(void) fprintf(out, "\n"); } fclose(out); +#endif } void base64_gen(void) { FILE *out; - unsigned char dst[256], src[32]; - unsigned long x, y, len; - + unsigned char dst[256], src[32], ch; + unsigned long x, len; + out = fopen("base64_tv.txt", "w"); fprintf(out, "Base64 vectors. These are the base64 encodings of the strings 00,01,02...NN-1\n\n"); for (x = 0; x <= 32; x++) { - for (y = 0; y < x; y++) { - src[y] = y; + for (ch = 0; ch < x; ch++) { + src[ch] = ch; } len = sizeof(dst); base64_encode(src, x, dst, &len); @@ -681,7 +662,7 @@ void ecc_gen(void) mp_read_radix(modulus, (char *)ltc_ecc_sets[x].prime, 16); mp_read_radix(G->x, (char *)ltc_ecc_sets[x].Gx, 16); mp_read_radix(G->y, (char *)ltc_ecc_sets[x].Gy, 16); - mp_set(G->z, 1); + mp_set(G->z, 1); while (mp_cmp(k, order) == LTC_MP_LT) { ltc_mp.ecc_ptmul(k, G, R, modulus, 1); @@ -699,11 +680,12 @@ void ecc_gen(void) void lrw_gen(void) { +#ifdef LTC_LRW_MODE FILE *out; unsigned char tweak[16], key[16], iv[16], buf[1024]; int x, y, err; symmetric_LRW lrw; - + /* initialize default key and tweak */ for (x = 0; x < 16; x++) { tweak[x] = key[x] = iv[x] = x; @@ -760,27 +742,61 @@ void lrw_gen(void) lrw_done(&lrw); } fclose(out); -} +#endif +} int main(void) { - reg_algs(); + register_all_ciphers(); + register_all_hashes(); + register_all_prngs(); +#ifdef USE_LTM + ltc_mp = ltm_desc; +#elif defined(USE_TFM) + ltc_mp = tfm_desc; +#elif defined(USE_GMP) + ltc_mp = gmp_desc; +#elif defined(EXT_MATH_LIB) + extern ltc_math_descriptor EXT_MATH_LIB; + ltc_mp = EXT_MATH_LIB; +#else + fprintf(stderr, "No MPI provider available\n"); + exit(EXIT_FAILURE); +#endif + printf("Generating hash vectors..."); fflush(stdout); hash_gen(); printf("done\n"); printf("Generating cipher vectors..."); fflush(stdout); cipher_gen(); printf("done\n"); - printf("Generating LTC_HMAC vectors..."); fflush(stdout); hmac_gen(); printf("done\n"); - printf("Generating LTC_OMAC vectors..."); fflush(stdout); omac_gen(); printf("done\n"); + printf("Generating HMAC vectors..."); fflush(stdout); hmac_gen(); printf("done\n"); +#ifdef LTC_OMAC + printf("Generating OMAC vectors..."); fflush(stdout); omac_gen(); printf("done\n"); +#endif +#ifdef LTC_PMAC printf("Generating PMAC vectors..."); fflush(stdout); pmac_gen(); printf("done\n"); +#endif +#ifdef LTC_EAX_MODE printf("Generating EAX vectors..."); fflush(stdout); eax_gen(); printf("done\n"); +#endif +#ifdef LTC_OCB_MODE printf("Generating OCB vectors..."); fflush(stdout); ocb_gen(); printf("done\n"); +#endif +#ifdef LTC_OCB3_MODE + printf("Generating OCB3 vectors..."); fflush(stdout); ocb3_gen(); printf("done\n"); +#endif +#ifdef LTC_CCM_MODE printf("Generating CCM vectors..."); fflush(stdout); ccm_gen(); printf("done\n"); +#endif +#ifdef LTC_GCM_MODE printf("Generating GCM vectors..."); fflush(stdout); gcm_gen(); printf("done\n"); - printf("Generating LTC_BASE64 vectors..."); fflush(stdout); base64_gen(); printf("done\n"); +#endif + printf("Generating BASE64 vectors..."); fflush(stdout); base64_gen(); printf("done\n"); printf("Generating MATH vectors..."); fflush(stdout); math_gen(); printf("done\n"); printf("Generating ECC vectors..."); fflush(stdout); ecc_gen(); printf("done\n"); +#ifdef LTC_LRW_MODE printf("Generating LRW vectors..."); fflush(stdout); lrw_gen(); printf("done\n"); +#endif return 0; } -/* $Source$ */ -/* $Revision$ */ -/* $Date$ */ +/* ref: $Format:%D$ */ +/* git commit: $Format:%H$ */ +/* commit time: $Format:%ai$ */ -- cgit v1.2.3