diff options
author | Matt Johnston <matt@ucc.asn.au> | 2007-01-11 04:29:08 +0000 |
---|---|---|
committer | Matt Johnston <matt@ucc.asn.au> | 2007-01-11 04:29:08 +0000 |
commit | 943636c3e13f50bc0e29c5f69974541a296a3be2 (patch) | |
tree | 02a55d7bff75c51e641a556ad331460a1d1270b6 /libtomcrypt/src/prngs | |
parent | 0a60ef26bd13e6007c4fdd0f09b5a8d4785113c0 (diff) | |
parent | 9d5ed350a749368c84254c11e7616ce3c891193a (diff) |
propagate from branch 'au.asn.ucc.matt.ltc.dropbear' (head c1db4398d56c56c6d06ae1e20c1e0d04dbb598ed)
to branch 'au.asn.ucc.matt.dropbear' (head d26d5eb2837f46b56a33fb0e7573aa0201abd4d5)
--HG--
extra : convert_revision : 7a0ae6de81402591a789486070007238169fafca
Diffstat (limited to 'libtomcrypt/src/prngs')
-rw-r--r-- | libtomcrypt/src/prngs/fortuna.c | 427 | ||||
-rw-r--r-- | libtomcrypt/src/prngs/rc4.c | 269 | ||||
-rw-r--r-- | libtomcrypt/src/prngs/rng_get_bytes.c | 148 | ||||
-rw-r--r-- | libtomcrypt/src/prngs/rng_make_prng.c | 69 | ||||
-rw-r--r-- | libtomcrypt/src/prngs/sober128.c | 500 | ||||
-rw-r--r-- | libtomcrypt/src/prngs/sober128tab.c | 162 | ||||
-rw-r--r-- | libtomcrypt/src/prngs/sprng.c | 136 | ||||
-rw-r--r-- | libtomcrypt/src/prngs/yarrow.c | 362 |
8 files changed, 2073 insertions, 0 deletions
diff --git a/libtomcrypt/src/prngs/fortuna.c b/libtomcrypt/src/prngs/fortuna.c new file mode 100644 index 0000000..159db52 --- /dev/null +++ b/libtomcrypt/src/prngs/fortuna.c @@ -0,0 +1,427 @@ +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtomcrypt.com + */ +#include "tomcrypt.h" + +/** + @file fortuna.c + Fortuna PRNG, Tom St Denis +*/ + +/* Implementation of Fortuna by Tom St Denis + +We deviate slightly here for reasons of simplicity [and to fit in the API]. First all "sources" +in the AddEntropy function are fixed to 0. Second since no reliable timer is provided +we reseed automatically when len(pool0) >= 64 or every FORTUNA_WD calls to the read function */ + +#ifdef FORTUNA + +/* requries SHA256 and AES */ +#if !(defined(RIJNDAEL) && defined(SHA256)) + #error FORTUNA requires SHA256 and RIJNDAEL (AES) +#endif + +#ifndef FORTUNA_POOLS + #warning FORTUNA_POOLS was not previously defined (old headers?) + #define FORTUNA_POOLS 32 +#endif + +#if FORTUNA_POOLS < 4 || FORTUNA_POOLS > 32 + #error FORTUNA_POOLS must be in [4..32] +#endif + +const struct ltc_prng_descriptor fortuna_desc = { + "fortuna", 1024, + &fortuna_start, + &fortuna_add_entropy, + &fortuna_ready, + &fortuna_read, + &fortuna_done, + &fortuna_export, + &fortuna_import, + &fortuna_test +}; + +/* update the IV */ +static void fortuna_update_iv(prng_state *prng) +{ + int x; + unsigned char *IV; + /* update IV */ + IV = prng->fortuna.IV; + for (x = 0; x < 16; x++) { + IV[x] = (IV[x] + 1) & 255; + if (IV[x] != 0) break; + } +} + +/* reseed the PRNG */ +static int fortuna_reseed(prng_state *prng) +{ + unsigned char tmp[MAXBLOCKSIZE]; + hash_state md; + int err, x; + + ++prng->fortuna.reset_cnt; + + /* new K == SHA256(K || s) where s == SHA256(P0) || SHA256(P1) ... */ + sha256_init(&md); + if ((err = sha256_process(&md, prng->fortuna.K, 32)) != CRYPT_OK) { + sha256_done(&md, tmp); + return err; + } + + for (x = 0; x < FORTUNA_POOLS; x++) { + if (x == 0 || ((prng->fortuna.reset_cnt >> (x-1)) & 1) == 0) { + /* terminate this hash */ + if ((err = sha256_done(&prng->fortuna.pool[x], tmp)) != CRYPT_OK) { + sha256_done(&md, tmp); + return err; + } + /* add it to the string */ + if ((err = sha256_process(&md, tmp, 32)) != CRYPT_OK) { + sha256_done(&md, tmp); + return err; + } + /* reset this pool */ + if ((err = sha256_init(&prng->fortuna.pool[x])) != CRYPT_OK) { + sha256_done(&md, tmp); + return err; + } + } else { + break; + } + } + + /* finish key */ + if ((err = sha256_done(&md, prng->fortuna.K)) != CRYPT_OK) { + return err; + } + if ((err = rijndael_setup(prng->fortuna.K, 32, 0, &prng->fortuna.skey)) != CRYPT_OK) { + return err; + } + fortuna_update_iv(prng); + + /* reset pool len */ + prng->fortuna.pool0_len = 0; + prng->fortuna.wd = 0; + + +#ifdef LTC_CLEAN_STACK + zeromem(&md, sizeof(md)); + zeromem(tmp, sizeof(tmp)); +#endif + + return CRYPT_OK; +} + +/** + Start the PRNG + @param prng [out] The PRNG state to initialize + @return CRYPT_OK if successful +*/ +int fortuna_start(prng_state *prng) +{ + int err, x, y; + unsigned char tmp[MAXBLOCKSIZE]; + + LTC_ARGCHK(prng != NULL); + + /* initialize the pools */ + for (x = 0; x < FORTUNA_POOLS; x++) { + if ((err = sha256_init(&prng->fortuna.pool[x])) != CRYPT_OK) { + for (y = 0; y < x; y++) { + sha256_done(&prng->fortuna.pool[y], tmp); + } + return err; + } + } + prng->fortuna.pool_idx = prng->fortuna.pool0_len = prng->fortuna.wd = 0; + prng->fortuna.reset_cnt = 0; + + /* reset bufs */ + zeromem(prng->fortuna.K, 32); + if ((err = rijndael_setup(prng->fortuna.K, 32, 0, &prng->fortuna.skey)) != CRYPT_OK) { + for (x = 0; x < FORTUNA_POOLS; x++) { + sha256_done(&prng->fortuna.pool[x], tmp); + } + return err; + } + zeromem(prng->fortuna.IV, 16); + + LTC_MUTEX_INIT(&prng->fortuna.prng_lock) + + return CRYPT_OK; +} + +/** + Add entropy to the PRNG state + @param in The data to add + @param inlen Length of the data to add + @param prng PRNG state to update + @return CRYPT_OK if successful +*/ +int fortuna_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng) +{ + unsigned char tmp[2]; + int err; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(prng != NULL); + + LTC_MUTEX_LOCK(&prng->fortuna.prng_lock); + + /* ensure inlen <= 32 */ + if (inlen > 32) { + LTC_MUTEX_UNLOCK(&prng->fortuna.prng_lock); + return CRYPT_INVALID_ARG; + } + + /* add s || length(in) || in to pool[pool_idx] */ + tmp[0] = 0; + tmp[1] = (unsigned char)inlen; + if ((err = sha256_process(&prng->fortuna.pool[prng->fortuna.pool_idx], tmp, 2)) != CRYPT_OK) { + LTC_MUTEX_UNLOCK(&prng->fortuna.prng_lock); + return err; + } + if ((err = sha256_process(&prng->fortuna.pool[prng->fortuna.pool_idx], in, inlen)) != CRYPT_OK) { + LTC_MUTEX_UNLOCK(&prng->fortuna.prng_lock); + return err; + } + if (prng->fortuna.pool_idx == 0) { + prng->fortuna.pool0_len += inlen; + } + if (++(prng->fortuna.pool_idx) == FORTUNA_POOLS) { + prng->fortuna.pool_idx = 0; + } + + LTC_MUTEX_UNLOCK(&prng->fortuna.prng_lock); + return CRYPT_OK; +} + +/** + Make the PRNG ready to read from + @param prng The PRNG to make active + @return CRYPT_OK if successful +*/ +int fortuna_ready(prng_state *prng) +{ + return fortuna_reseed(prng); +} + +/** + Read from the PRNG + @param out Destination + @param outlen Length of output + @param prng The active PRNG to read from + @return Number of octets read +*/ +unsigned long fortuna_read(unsigned char *out, unsigned long outlen, prng_state *prng) +{ + unsigned char tmp[16]; + int err; + unsigned long tlen; + + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(prng != NULL); + + LTC_MUTEX_LOCK(&prng->fortuna.prng_lock); + + /* do we have to reseed? */ + if (++prng->fortuna.wd == FORTUNA_WD || prng->fortuna.pool0_len >= 64) { + if ((err = fortuna_reseed(prng)) != CRYPT_OK) { + LTC_MUTEX_UNLOCK(&prng->fortuna.prng_lock); + return 0; + } + } + + /* now generate the blocks required */ + tlen = outlen; + + /* handle whole blocks without the extra XMEMCPY */ + while (outlen >= 16) { + /* encrypt the IV and store it */ + rijndael_ecb_encrypt(prng->fortuna.IV, out, &prng->fortuna.skey); + out += 16; + outlen -= 16; + fortuna_update_iv(prng); + } + + /* left over bytes? */ + if (outlen > 0) { + rijndael_ecb_encrypt(prng->fortuna.IV, tmp, &prng->fortuna.skey); + XMEMCPY(out, tmp, outlen); + fortuna_update_iv(prng); + } + + /* generate new key */ + rijndael_ecb_encrypt(prng->fortuna.IV, prng->fortuna.K , &prng->fortuna.skey); fortuna_update_iv(prng); + rijndael_ecb_encrypt(prng->fortuna.IV, prng->fortuna.K+16, &prng->fortuna.skey); fortuna_update_iv(prng); + if ((err = rijndael_setup(prng->fortuna.K, 32, 0, &prng->fortuna.skey)) != CRYPT_OK) { + LTC_MUTEX_UNLOCK(&prng->fortuna.prng_lock); + return 0; + } + +#ifdef LTC_CLEAN_STACK + zeromem(tmp, sizeof(tmp)); +#endif + LTC_MUTEX_UNLOCK(&prng->fortuna.prng_lock); + return tlen; +} + +/** + Terminate the PRNG + @param prng The PRNG to terminate + @return CRYPT_OK if successful +*/ +int fortuna_done(prng_state *prng) +{ + int err, x; + unsigned char tmp[32]; + + LTC_ARGCHK(prng != NULL); + LTC_MUTEX_LOCK(&prng->fortuna.prng_lock); + + /* terminate all the hashes */ + for (x = 0; x < FORTUNA_POOLS; x++) { + if ((err = sha256_done(&(prng->fortuna.pool[x]), tmp)) != CRYPT_OK) { + LTC_MUTEX_UNLOCK(&prng->fortuna.prng_lock); + return err; + } + } + /* call cipher done when we invent one ;-) */ + +#ifdef LTC_CLEAN_STACK + zeromem(tmp, sizeof(tmp)); +#endif + + LTC_MUTEX_UNLOCK(&prng->fortuna.prng_lock); + return CRYPT_OK; +} + +/** + Export the PRNG state + @param out [out] Destination + @param outlen [in/out] Max size and resulting size of the state + @param prng The PRNG to export + @return CRYPT_OK if successful +*/ +int fortuna_export(unsigned char *out, unsigned long *outlen, prng_state *prng) +{ + int x, err; + hash_state *md; + + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + LTC_ARGCHK(prng != NULL); + + LTC_MUTEX_LOCK(&prng->fortuna.prng_lock); + + /* we'll write bytes for s&g's */ + if (*outlen < 32*FORTUNA_POOLS) { + LTC_MUTEX_UNLOCK(&prng->fortuna.prng_lock); + *outlen = 32*FORTUNA_POOLS; + return CRYPT_BUFFER_OVERFLOW; + } + + md = XMALLOC(sizeof(hash_state)); + if (md == NULL) { + LTC_MUTEX_UNLOCK(&prng->fortuna.prng_lock); + return CRYPT_MEM; + } + + /* to emit the state we copy each pool, terminate it then hash it again so + * an attacker who sees the state can't determine the current state of the PRNG + */ + for (x = 0; x < FORTUNA_POOLS; x++) { + /* copy the PRNG */ + XMEMCPY(md, &(prng->fortuna.pool[x]), sizeof(*md)); + + /* terminate it */ + if ((err = sha256_done(md, out+x*32)) != CRYPT_OK) { + goto LBL_ERR; + } + + /* now hash it */ + if ((err = sha256_init(md)) != CRYPT_OK) { + goto LBL_ERR; + } + if ((err = sha256_process(md, out+x*32, 32)) != CRYPT_OK) { + goto LBL_ERR; + } + if ((err = sha256_done(md, out+x*32)) != CRYPT_OK) { + goto LBL_ERR; + } + } + *outlen = 32*FORTUNA_POOLS; + err = CRYPT_OK; + +LBL_ERR: +#ifdef LTC_CLEAN_STACK + zeromem(md, sizeof(*md)); +#endif + XFREE(md); + LTC_MUTEX_UNLOCK(&prng->fortuna.prng_lock); + return err; +} + +/** + Import a PRNG state + @param in The PRNG state + @param inlen Size of the state + @param prng The PRNG to import + @return CRYPT_OK if successful +*/ +int fortuna_import(const unsigned char *in, unsigned long inlen, prng_state *prng) +{ + int err, x; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(prng != NULL); + + if (inlen != 32*FORTUNA_POOLS) { + return CRYPT_INVALID_ARG; + } + + if ((err = fortuna_start(prng)) != CRYPT_OK) { + return err; + } + for (x = 0; x < FORTUNA_POOLS; x++) { + if ((err = fortuna_add_entropy(in+x*32, 32, prng)) != CRYPT_OK) { + return err; + } + } + return err; +} + +/** + PRNG self-test + @return CRYPT_OK if successful, CRYPT_NOP if self-testing has been disabled +*/ +int fortuna_test(void) +{ +#ifndef LTC_TEST + return CRYPT_NOP; +#else + int err; + + if ((err = sha256_test()) != CRYPT_OK) { + return err; + } + return rijndael_test(); +#endif +} + +#endif + + +/* $Source: /cvs/libtom/libtomcrypt/src/prngs/fortuna.c,v $ */ +/* $Revision: 1.12 $ */ +/* $Date: 2006/12/04 21:34:03 $ */ diff --git a/libtomcrypt/src/prngs/rc4.c b/libtomcrypt/src/prngs/rc4.c new file mode 100644 index 0000000..cf118ad --- /dev/null +++ b/libtomcrypt/src/prngs/rc4.c @@ -0,0 +1,269 @@ +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtomcrypt.com + */ +#include "tomcrypt.h" + +/** + @file rc4.c + RC4 PRNG, Tom St Denis +*/ + +#ifdef RC4 + +const struct ltc_prng_descriptor rc4_desc = +{ + "rc4", 32, + &rc4_start, + &rc4_add_entropy, + &rc4_ready, + &rc4_read, + &rc4_done, + &rc4_export, + &rc4_import, + &rc4_test +}; + +/** + Start the PRNG + @param prng [out] The PRNG state to initialize + @return CRYPT_OK if successful +*/ +int rc4_start(prng_state *prng) +{ + LTC_ARGCHK(prng != NULL); + + /* set keysize to zero */ + prng->rc4.x = 0; + + return CRYPT_OK; +} + +/** + Add entropy to the PRNG state + @param in The data to add + @param inlen Length of the data to add + @param prng PRNG state to update + @return CRYPT_OK if successful +*/ +int rc4_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng) +{ + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(prng != NULL); + + /* trim as required */ + if (prng->rc4.x + inlen > 256) { + if (prng->rc4.x == 256) { + /* I can't possibly accept another byte, ok maybe a mint wafer... */ + return CRYPT_OK; + } else { + /* only accept part of it */ + inlen = 256 - prng->rc4.x; + } + } + + while (inlen--) { + prng->rc4.buf[prng->rc4.x++] = *in++; + } + + return CRYPT_OK; + +} + +/** + Make the PRNG ready to read from + @param prng The PRNG to make active + @return CRYPT_OK if successful +*/ +int rc4_ready(prng_state *prng) +{ + unsigned char key[256], tmp, *s; + int keylen, x, y, j; + + LTC_ARGCHK(prng != NULL); + + /* extract the key */ + s = prng->rc4.buf; + XMEMCPY(key, s, 256); + keylen = prng->rc4.x; + + /* make RC4 perm and shuffle */ + for (x = 0; x < 256; x++) { + s[x] = x; + } + + for (j = x = y = 0; x < 256; x++) { + y = (y + prng->rc4.buf[x] + key[j++]) & 255; + if (j == keylen) { + j = 0; + } + tmp = s[x]; s[x] = s[y]; s[y] = tmp; + } + prng->rc4.x = 0; + prng->rc4.y = 0; + +#ifdef LTC_CLEAN_STACK + zeromem(key, sizeof(key)); +#endif + + return CRYPT_OK; +} + +/** + Read from the PRNG + @param out Destination + @param outlen Length of output + @param prng The active PRNG to read from + @return Number of octets read +*/ +unsigned long rc4_read(unsigned char *out, unsigned long outlen, prng_state *prng) +{ + unsigned char x, y, *s, tmp; + unsigned long n; + + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(prng != NULL); + +#ifdef LTC_VALGRIND + zeromem(out, outlen); +#endif + + n = outlen; + x = prng->rc4.x; + y = prng->rc4.y; + s = prng->rc4.buf; + while (outlen--) { + x = (x + 1) & 255; + y = (y + s[x]) & 255; + tmp = s[x]; s[x] = s[y]; s[y] = tmp; + tmp = (s[x] + s[y]) & 255; + *out++ ^= s[tmp]; + } + prng->rc4.x = x; + prng->rc4.y = y; + return n; +} + +/** + Terminate the PRNG + @param prng The PRNG to terminate + @return CRYPT_OK if successful +*/ +int rc4_done(prng_state *prng) +{ + LTC_ARGCHK(prng != NULL); + return CRYPT_OK; +} + +/** + Export the PRNG state + @param out [out] Destination + @param outlen [in/out] Max size and resulting size of the state + @param prng The PRNG to export + @return CRYPT_OK if successful +*/ +int rc4_export(unsigned char *out, unsigned long *outlen, prng_state *prng) +{ + LTC_ARGCHK(outlen != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(prng != NULL); + + if (*outlen < 32) { + *outlen = 32; + return CRYPT_BUFFER_OVERFLOW; + } + + if (rc4_read(out, 32, prng) != 32) { + return CRYPT_ERROR_READPRNG; + } + *outlen = 32; + + return CRYPT_OK; +} + +/** + Import a PRNG state + @param in The PRNG state + @param inlen Size of the state + @param prng The PRNG to import + @return CRYPT_OK if successful +*/ +int rc4_import(const unsigned char *in, unsigned long inlen, prng_state *prng) +{ + int err; + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(prng != NULL); + + if (inlen != 32) { + return CRYPT_INVALID_ARG; + } + + if ((err = rc4_start(prng)) != CRYPT_OK) { + return err; + } + return rc4_add_entropy(in, 32, prng); +} + +/** + PRNG self-test + @return CRYPT_OK if successful, CRYPT_NOP if self-testing has been disabled +*/ +int rc4_test(void) +{ +#if !defined(LTC_TEST) || defined(LTC_VALGRIND) + return CRYPT_NOP; +#else + static const struct { + unsigned char key[8], pt[8], ct[8]; + } tests[] = { +{ + { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef }, + { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef }, + { 0x75, 0xb7, 0x87, 0x80, 0x99, 0xe0, 0xc5, 0x96 } +} +}; + prng_state prng; + unsigned char dst[8]; + int err, x; + + for (x = 0; x < (int)(sizeof(tests)/sizeof(tests[0])); x++) { + if ((err = rc4_start(&prng)) != CRYPT_OK) { + return err; + } + if ((err = rc4_add_entropy(tests[x].key, 8, &prng)) != CRYPT_OK) { + return err; + } + if ((err = rc4_ready(&prng)) != CRYPT_OK) { + return err; + } + XMEMCPY(dst, tests[x].pt, 8); + if (rc4_read(dst, 8, &prng) != 8) { + return CRYPT_ERROR_READPRNG; + } + rc4_done(&prng); + if (XMEMCMP(dst, tests[x].ct, 8)) { +#if 0 + int y; + printf("\n\nRC4 failed, I got:\n"); + for (y = 0; y < 8; y++) printf("%02x ", dst[y]); + printf("\n"); +#endif + return CRYPT_FAIL_TESTVECTOR; + } + } + return CRYPT_OK; +#endif +} + +#endif + + +/* $Source: /cvs/libtom/libtomcrypt/src/prngs/rc4.c,v $ */ +/* $Revision: 1.9 $ */ +/* $Date: 2006/11/16 00:32:18 $ */ diff --git a/libtomcrypt/src/prngs/rng_get_bytes.c b/libtomcrypt/src/prngs/rng_get_bytes.c new file mode 100644 index 0000000..7d332b5 --- /dev/null +++ b/libtomcrypt/src/prngs/rng_get_bytes.c @@ -0,0 +1,148 @@ +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtomcrypt.com + */ +#include "tomcrypt.h" + +/** + @file rng_get_bytes.c + portable way to get secure random bits to feed a PRNG (Tom St Denis) +*/ + +#ifdef DEVRANDOM +/* on *NIX read /dev/random */ +static unsigned long rng_nix(unsigned char *buf, unsigned long len, + void (*callback)(void)) +{ +#ifdef LTC_NO_FILE + return 0; +#else + FILE *f; + unsigned long x; +#ifdef TRY_URANDOM_FIRST + f = fopen("/dev/urandom", "rb"); + if (f == NULL) +#endif /* TRY_URANDOM_FIRST */ + f = fopen("/dev/random", "rb"); + + if (f == NULL) { + return 0; + } + + /* disable buffering */ + if (setvbuf(f, NULL, _IONBF, 0) != 0) { + fclose(f); + return 0; + } + + x = (unsigned long)fread(buf, 1, (size_t)len, f); + fclose(f); + return x; +#endif /* LTC_NO_FILE */ +} + +#endif /* DEVRANDOM */ + +/* on ANSI C platforms with 100 < CLOCKS_PER_SEC < 10000 */ +#if defined(CLOCKS_PER_SEC) && !defined(WINCE) + +#define ANSI_RNG + +static unsigned long rng_ansic(unsigned char *buf, unsigned long len, + void (*callback)(void)) +{ + clock_t t1; + int l, acc, bits, a, b; + + if (XCLOCKS_PER_SEC < 100 || XCLOCKS_PER_SEC > 10000) { + return 0; + } + + l = len; + bits = 8; + acc = a = b = 0; + while (len--) { + if (callback != NULL) callback(); + while (bits--) { + do { + t1 = XCLOCK(); while (t1 == XCLOCK()) a ^= 1; + t1 = XCLOCK(); while (t1 == XCLOCK()) b ^= 1; + } while (a == b); + acc = (acc << 1) | a; + } + *buf++ = acc; + acc = 0; + bits = 8; + } + acc = bits = a = b = 0; + return l; +} + +#endif + +/* Try the Microsoft CSP */ +#if defined(WIN32) || defined(WINCE) +#define _WIN32_WINNT 0x0400 +#ifdef WINCE + #define UNDER_CE + #define ARM +#endif +#include <windows.h> +#include <wincrypt.h> + +static unsigned long rng_win32(unsigned char *buf, unsigned long len, + void (*callback)(void)) +{ + HCRYPTPROV hProv = 0; + if (!CryptAcquireContext(&hProv, NULL, MS_DEF_PROV, PROV_RSA_FULL, + (CRYPT_VERIFYCONTEXT | CRYPT_MACHINE_KEYSET)) && + !CryptAcquireContext (&hProv, NULL, MS_DEF_PROV, PROV_RSA_FULL, + CRYPT_VERIFYCONTEXT | CRYPT_MACHINE_KEYSET | CRYPT_NEWKEYSET)) + return 0; + + if (CryptGenRandom(hProv, len, buf) == TRUE) { + CryptReleaseContext(hProv, 0); + return len; + } else { + CryptReleaseContext(hProv, 0); + return 0; + } +} + +#endif /* WIN32 */ + +/** + Read the system RNG + @param out Destination + @param outlen Length desired (octets) + @param callback Pointer to void function to act as "callback" when RNG is slow. This can be NULL + @return Number of octets read +*/ +unsigned long rng_get_bytes(unsigned char *out, unsigned long outlen, + void (*callback)(void)) +{ + unsigned long x; + + LTC_ARGCHK(out != NULL); + +#if defined(DEVRANDOM) + x = rng_nix(out, outlen, callback); if (x != 0) { return x; } +#endif +#ifdef WIN32 + x = rng_win32(out, outlen, callback); if (x != 0) { return x; } +#endif +#ifdef ANSI_RNG + x = rng_ansic(out, outlen, callback); if (x != 0) { return x; } +#endif + return 0; +} + +/* $Source: /cvs/libtom/libtomcrypt/src/prngs/rng_get_bytes.c,v $ */ +/* $Revision: 1.5 $ */ +/* $Date: 2006/12/06 02:01:29 $ */ diff --git a/libtomcrypt/src/prngs/rng_make_prng.c b/libtomcrypt/src/prngs/rng_make_prng.c new file mode 100644 index 0000000..35631ab --- /dev/null +++ b/libtomcrypt/src/prngs/rng_make_prng.c @@ -0,0 +1,69 @@ +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtomcrypt.com + */ +#include "tomcrypt.h" + +/** + @file rng_make_prng.c + portable way to get secure random bits to feed a PRNG (Tom St Denis) +*/ + +/** + Create a PRNG from a RNG + @param bits Number of bits of entropy desired (64 ... 1024) + @param wprng Index of which PRNG to setup + @param prng [out] PRNG state to initialize + @param callback A pointer to a void function for when the RNG is slow, this can be NULL + @return CRYPT_OK if successful +*/ +int rng_make_prng(int bits, int wprng, prng_state *prng, + void (*callback)(void)) +{ + unsigned char buf[256]; + int err; + + LTC_ARGCHK(prng != NULL); + + /* check parameter */ + if ((err = prng_is_valid(wprng)) != CRYPT_OK) { + return err; + } + + if (bits < 64 || bits > 1024) { + return CRYPT_INVALID_PRNGSIZE; + } + + if ((err = prng_descriptor[wprng].start(prng)) != CRYPT_OK) { + return err; + } + + bits = ((bits/8)+((bits&7)!=0?1:0)) * 2; + if (rng_get_bytes(buf, (unsigned long)bits, callback) != (unsigned long)bits) { + return CRYPT_ERROR_READPRNG; + } + + if ((err = prng_descriptor[wprng].add_entropy(buf, (unsigned long)bits, prng)) != CRYPT_OK) { + return err; + } + + if ((err = prng_descriptor[wprng].ready(prng)) != CRYPT_OK) { + return err; + } + + #ifdef LTC_CLEAN_STACK + zeromem(buf, sizeof(buf)); + #endif + return CRYPT_OK; +} + + +/* $Source: /cvs/libtom/libtomcrypt/src/prngs/rng_make_prng.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/03/31 14:15:35 $ */ diff --git a/libtomcrypt/src/prngs/sober128.c b/libtomcrypt/src/prngs/sober128.c new file mode 100644 index 0000000..0361387 --- /dev/null +++ b/libtomcrypt/src/prngs/sober128.c @@ -0,0 +1,500 @@ +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtomcrypt.com + */ +#include "tomcrypt.h" + +/** + @file sober128.c + Implementation of SOBER-128 by Tom St Denis. + Based on s128fast.c reference code supplied by Greg Rose of QUALCOMM. +*/ + +#ifdef SOBER128 + +#include "sober128tab.c" + +const struct ltc_prng_descriptor sober128_desc = +{ + "sober128", 64, + &sober128_start, + &sober128_add_entropy, + &sober128_ready, + &sober128_read, + &sober128_done, + &sober128_export, + &sober128_import, + &sober128_test +}; + +/* don't change these... */ +#define N 17 +#define FOLD N /* how many iterations of folding to do */ +#define INITKONST 0x6996c53a /* value of KONST to use during key loading */ +#define KEYP 15 /* where to insert key words */ +#define FOLDP 4 /* where to insert non-linear feedback */ + +#define B(x,i) ((unsigned char)(((x) >> (8*i)) & 0xFF)) + +static ulong32 BYTE2WORD(unsigned char *b) +{ + ulong32 t; + LOAD32L(t, b); + return t; +} + +#define WORD2BYTE(w, b) STORE32L(b, w) + +static void XORWORD(ulong32 w, unsigned char *b) +{ + ulong32 t; + LOAD32L(t, b); + t ^= w; + STORE32L(t, b); +} + +/* give correct offset for the current position of the register, + * where logically R[0] is at position "zero". + */ +#define OFF(zero, i) (((zero)+(i)) % N) + +/* step the LFSR */ +/* After stepping, "zero" moves right one place */ +#define STEP(R,z) \ + R[OFF(z,0)] = R[OFF(z,15)] ^ R[OFF(z,4)] ^ (R[OFF(z,0)] << 8) ^ Multab[(R[OFF(z,0)] >> 24) & 0xFF]; + +static void cycle(ulong32 *R) +{ + ulong32 t; + int i; + + STEP(R,0); + t = R[0]; + for (i = 1; i < N; ++i) { + R[i-1] = R[i]; + } + R[N-1] = t; +} + +/* Return a non-linear function of some parts of the register. + */ +#define NLFUNC(c,z) \ +{ \ + t = c->R[OFF(z,0)] + c->R[OFF(z,16)]; \ + t ^= Sbox[(t >> 24) & 0xFF]; \ + t = RORc(t, 8); \ + t = ((t + c->R[OFF(z,1)]) ^ c->konst) + c->R[OFF(z,6)]; \ + t ^= Sbox[(t >> 24) & 0xFF]; \ + t = t + c->R[OFF(z,13)]; \ +} + +static ulong32 nltap(struct sober128_prng *c) +{ + ulong32 t; + NLFUNC(c, 0); + return t; +} + +/** + Start the PRNG + @param prng [out] The PRNG state to initialize + @return CRYPT_OK if successful +*/ +int sober128_start(prng_state *prng) +{ + int i; + struct sober128_prng *c; + + LTC_ARGCHK(prng != NULL); + + c = &(prng->sober128); + + /* Register initialised to Fibonacci numbers */ + c->R[0] = 1; + c->R[1] = 1; + for (i = 2; i < N; ++i) { + c->R[i] = c->R[i-1] + c->R[i-2]; + } + c->konst = INITKONST; + + /* next add_entropy will be the key */ + c->flag = 1; + c->set = 0; + + return CRYPT_OK; +} + +/* Save the current register state + */ +static void s128_savestate(struct sober128_prng *c) +{ + int i; + for (i = 0; i < N; ++i) { + c->initR[i] = c->R[i]; + } +} + +/* initialise to previously saved register state + */ +static void s128_reloadstate(struct sober128_prng *c) +{ + int i; + + for (i = 0; i < N; ++i) { + c->R[i] = c->initR[i]; + } +} + +/* Initialise "konst" + */ +static void s128_genkonst(struct sober128_prng *c) +{ + ulong32 newkonst; + + do { + cycle(c->R); + newkonst = nltap(c); + } while ((newkonst & 0xFF000000) == 0); + c->konst = newkonst; +} + +/* Load key material into the register + */ +#define ADDKEY(k) \ + c->R[KEYP] += (k); + +#define XORNL(nl) \ + c->R[FOLDP] ^= (nl); + +/* nonlinear diffusion of register for key */ +#define DROUND(z) STEP(c->R,z); NLFUNC(c,(z+1)); c->R[OFF((z+1),FOLDP)] ^= t; +static void s128_diffuse(struct sober128_prng *c) +{ + ulong32 t; + /* relies on FOLD == N == 17! */ + DROUND(0); + DROUND(1); + DROUND(2); + DROUND(3); + DROUND(4); + DROUND(5); + DROUND(6); + DROUND(7); + DROUND(8); + DROUND(9); + DROUND(10); + DROUND(11); + DROUND(12); + DROUND(13); + DROUND(14); + DROUND(15); + DROUND(16); +} + +/** + Add entropy to the PRNG state + @param in The data to add + @param inlen Length of the data to add + @param prng PRNG state to update + @return CRYPT_OK if successful +*/ +int sober128_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng) +{ + struct sober128_prng *c; + ulong32 i, k; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(prng != NULL); + c = &(prng->sober128); + + if (c->flag == 1) { + /* this is the first call to the add_entropy so this input is the key */ + /* inlen must be multiple of 4 bytes */ + if ((inlen & 3) != 0) { + return CRYPT_INVALID_KEYSIZE; + } + + for (i = 0; i < inlen; i += 4) { + k = BYTE2WORD((unsigned char *)&in[i]); + ADDKEY(k); + cycle(c->R); + XORNL(nltap(c)); + } + + /* also fold in the length of the key */ + ADDKEY(inlen); + + /* now diffuse */ + s128_diffuse(c); + + s128_genkonst(c); + s128_savestate(c); + c->nbuf = 0; + c->flag = 0; + c->set = 1; + } else { + /* ok we are adding an IV then... */ + s128_reloadstate(c); + + /* inlen must be multiple of 4 bytes */ + if ((inlen & 3) != 0) { + return CRYPT_INVALID_KEYSIZE; + } + + for (i = 0; i < inlen; i += 4) { + k = BYTE2WORD((unsigned char *)&in[i]); + ADDKEY(k); + cycle(c->R); + XORNL(nltap(c)); + } + + /* also fold in the length of the key */ + ADDKEY(inlen); + + /* now diffuse */ + s128_diffuse(c); + c->nbuf = 0; + } + + return CRYPT_OK; +} + +/** + Make the PRNG ready to read from + @param prng The PRNG to make active + @return CRYPT_OK if successful +*/ +int sober128_ready(prng_state *prng) +{ + return prng->sober128.set == 1 ? CRYPT_OK : CRYPT_ERROR; +} + +/* XOR pseudo-random bytes into buffer + */ +#define SROUND(z) STEP(c->R,z); NLFUNC(c,(z+1)); XORWORD(t, out+(z*4)); + +/** + Read from the PRNG + @param out Destination + @param outlen Length of output + @param prng The active PRNG to read from + @return Number of octets read +*/ +unsigned long sober128_read(unsigned char *out, unsigned long outlen, prng_state *prng) +{ + struct sober128_prng *c; + ulong32 t, tlen; + + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(prng != NULL); + +#ifdef LTC_VALGRIND + zeromem(out, outlen); +#endif + + c = &(prng->sober128); + t = 0; + tlen = outlen; + + /* handle any previously buffered bytes */ + while (c->nbuf != 0 && outlen != 0) { + *out++ ^= c->sbuf & 0xFF; + c->sbuf >>= 8; + c->nbuf -= 8; + --outlen; + } + +#ifndef LTC_SMALL_CODE + /* do lots at a time, if there's enough to do */ + while (outlen >= N*4) { + SROUND(0); + SROUND(1); + SROUND(2); + SROUND(3); + SROUND(4); + SROUND(5); + SROUND(6); + SROUND(7); + SROUND(8); + SROUND(9); + SROUND(10); + SROUND(11); + SROUND(12); + SROUND(13); + SROUND(14); + SROUND(15); + SROUND(16); + out += 4*N; + outlen -= 4*N; + } +#endif + + /* do small or odd size buffers the slow way */ + while (4 <= outlen) { + cycle(c->R); + t = nltap(c); + XORWORD(t, out); + out += 4; + outlen -= 4; + } + + /* handle any trailing bytes */ + if (outlen != 0) { + cycle(c->R); + c->sbuf = nltap(c); + c->nbuf = 32; + while (c->nbuf != 0 && outlen != 0) { + *out++ ^= c->sbuf & 0xFF; + c->sbuf >>= 8; + c->nbuf -= 8; + --outlen; + } + } + + return tlen; +} + +/** + Terminate the PRNG + @param prng The PRNG to terminate + @return CRYPT_OK if successful +*/ +int sober128_done(prng_state *prng) +{ + LTC_ARGCHK(prng != NULL); + return CRYPT_OK; +} + +/** + Export the PRNG state + @param out [out] Destination + @param outlen [in/out] Max size and resulting size of the state + @param prng The PRNG to export + @return CRYPT_OK if successful +*/ +int sober128_export(unsigned char *out, unsigned long *outlen, prng_state *prng) +{ + LTC_ARGCHK(outlen != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(prng != NULL); + + if (*outlen < 64) { + *outlen = 64; + return CRYPT_BUFFER_OVERFLOW; + } + + if (sober128_read(out, 64, prng) != 64) { + return CRYPT_ERROR_READPRNG; + } + *outlen = 64; + + return CRYPT_OK; +} + +/** + Import a PRNG state + @param in The PRNG state + @param inlen Size of the state + @param prng The PRNG to import + @return CRYPT_OK if successful +*/ +int sober128_import(const unsigned char *in, unsigned long inlen, prng_state *prng) +{ + int err; + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(prng != NULL); + + if (inlen != 64) { + return CRYPT_INVALID_ARG; + } + + if ((err = sober128_start(prng)) != CRYPT_OK) { + return err; + } + if ((err = sober128_add_entropy(in, 64, prng)) != CRYPT_OK) { + return err; + } + return sober128_ready(prng); +} + +/** + PRNG self-test + @return CRYPT_OK if successful, CRYPT_NOP if self-testing has been disabled +*/ +int sober128_test(void) +{ +#ifndef LTC_TEST + return CRYPT_NOP; +#else + static const struct { + int keylen, ivlen, len; + unsigned char key[16], iv[4], out[20]; + } tests[] = { + +{ + 16, 4, 20, + + /* key */ + { 0x74, 0x65, 0x73, 0x74, 0x20, 0x6b, 0x65, 0x79, + 0x20, 0x31, 0x32, 0x38, 0x62, 0x69, 0x74, 0x73 }, + + /* IV */ + { 0x00, 0x00, 0x00, 0x00 }, + + /* expected output */ + { 0x43, 0x50, 0x0c, 0xcf, 0x89, 0x91, 0x9f, 0x1d, + 0xaa, 0x37, 0x74, 0x95, 0xf4, 0xb4, 0x58, 0xc2, + 0x40, 0x37, 0x8b, 0xbb } +} + +}; + prng_state prng; + unsigned char dst[20]; + int err, x; + + for (x = 0; x < (int)(sizeof(tests)/sizeof(tests[0])); x++) { + if ((err = sober128_start(&prng)) != CRYPT_OK) { + return err; + } + if ((err = sober128_add_entropy(tests[x].key, tests[x].keylen, &prng)) != CRYPT_OK) { + return err; + } + /* add IV */ + if ((err = sober128_add_entropy(tests[x].iv, tests[x].ivlen, &prng)) != CRYPT_OK) { + return err; + } + + /* ready up */ + if ((err = sober128_ready(&prng)) != CRYPT_OK) { + return err; + } + XMEMSET(dst, 0, tests[x].len); + if (sober128_read(dst, tests[x].len, &prng) != (unsigned long)tests[x].len) { + return CRYPT_ERROR_READPRNG; + } + sober128_done(&prng); + if (XMEMCMP(dst, tests[x].out, tests[x].len)) { +#if 0 + printf("\n\nSOBER128 failed, I got:\n"); + for (y = 0; y < tests[x].len; y++) printf("%02x ", dst[y]); + printf("\n"); +#endif + return CRYPT_FAIL_TESTVECTOR; + } + } + return CRYPT_OK; +#endif +} + +#endif + + +/* $Source: /cvs/libtom/libtomcrypt/src/prngs/sober128.c,v $ */ +/* $Revision: 1.8 $ */ +/* $Date: 2006/11/05 00:11:36 $ */ diff --git a/libtomcrypt/src/prngs/sober128tab.c b/libtomcrypt/src/prngs/sober128tab.c new file mode 100644 index 0000000..b50c77b --- /dev/null +++ b/libtomcrypt/src/prngs/sober128tab.c @@ -0,0 +1,162 @@ +/** + @file sober128tab.c + SOBER-128 Tables +*/ +/* $Id: sober128tab.c,v 1.2 2005/05/05 14:35:59 tom Exp $ */ +/* @(#)TuringMultab.h 1.3 (QUALCOMM) 02/09/03 */ +/* Multiplication table for Turing using 0xD02B4367 */ +static const ulong32 Multab[256] = { + 0x00000000, 0xD02B4367, 0xED5686CE, 0x3D7DC5A9, + 0x97AC41D1, 0x478702B6, 0x7AFAC71F, 0xAAD18478, + 0x631582EF, 0xB33EC188, 0x8E430421, 0x5E684746, + 0xF4B9C33E, 0x24928059, 0x19EF45F0, 0xC9C40697, + 0xC62A4993, 0x16010AF4, 0x2B7CCF5D, 0xFB578C3A, + 0x51860842, 0x81AD4B25, 0xBCD08E8C, 0x6CFBCDEB, + 0xA53FCB7C, 0x7514881B, 0x48694DB2, 0x98420ED5, + 0x32938AAD, 0xE2B8C9CA, 0xDFC50C63, 0x0FEE4F04, + 0xC154926B, 0x117FD10C, 0x2C0214A5, 0xFC2957C2, + 0x56F8D3BA, 0x86D390DD, 0xBBAE5574, 0x6B851613, + 0xA2411084, 0x726A53E3, 0x4F17964A, 0x9F3CD52D, + 0x35ED5155, 0xE5C61232, 0xD8BBD79B, 0x089094FC, + 0x077EDBF8, 0xD755989F, 0xEA285D36, 0x3A031E51, + 0x90D29A29, 0x40F9D94E, 0x7D841CE7, 0xADAF5F80, + 0x646B5917, 0xB4401A70, 0x893DDFD9, 0x59169CBE, + 0xF3C718C6, 0x23EC5BA1, 0x1E919E08, 0xCEBADD6F, + 0xCFA869D6, 0x1F832AB1, 0x22FEEF18, 0xF2D5AC7F, + 0x58042807, 0x882F6B60, 0xB552AEC9, 0x6579EDAE, + 0xACBDEB39, 0x7C96A85E, 0x41EB6DF7, 0x91C02E90, + 0x3B11AAE8, 0xEB3AE98F, 0xD6472C26, 0x066C6F41, + 0x09822045, 0xD9A96322, 0xE4D4A68B, 0x34FFE5EC, + 0x9E2E6194, 0x4E0522F3, 0x7378E75A, 0xA353A43D, + 0x6A97A2AA, 0xBABCE1CD, 0x87C12464, 0x57EA6703, + 0xFD3BE37B, 0x2D10A01C, 0x106D65B5, 0xC04626D2, + 0x0EFCFBBD, 0xDED7B8DA, 0xE3AA7D73, 0x33813E14, + 0x9950BA6C, 0x497BF90B, 0x74063CA2, 0xA42D7FC5, + 0x6DE97952, 0xBDC23A35, 0x80BFFF9C, 0x5094BCFB, + 0xFA453883, 0x2A6E7BE4, 0x1713BE4D, 0xC738FD2A, + 0xC8D6B22E, 0x18FDF149, 0x258034E0, 0xF5AB7787, + 0x5F7AF3FF, 0x8F51B098, 0xB22C7531, 0x62073656, + 0xABC330C1, 0x7BE873A6, 0x4695B60F, 0x96BEF568, + 0x3C6F7110, 0xEC443277, 0xD139F7DE, 0x0112B4B9, + 0xD31DD2E1, 0x03369186, 0x3E4B542F, 0xEE601748, + 0x44B19330, 0x949AD057, 0xA9E715FE, 0x79CC5699, + 0xB008500E, 0x60231369, 0x5D5ED6C0, 0x8D7595A7, + 0x27A411DF, 0xF78F52B8, 0xCAF29711, 0x1AD9D476, + 0x15379B72, 0xC51CD815, 0xF8611DBC, 0x284A5EDB, + 0x829BDAA3, 0x52B099C4, 0x6FCD5C6D, 0xBFE61F0A, + 0x7622199D, 0xA6095AFA, 0x9B749F53, 0x4B5FDC34, + 0xE18E584C, 0x31A51B2B, 0x0CD8DE82, 0xDCF39DE5, + 0x1249408A, 0xC26203ED, 0xFF1FC644, 0x2F348523, + 0x85E5015B, 0x55CE423C, 0x68B38795, 0xB898C4F2, + 0x715CC265, 0xA1778102, 0x9C0A44AB, 0x4C2107CC, + 0xE6F083B4, 0x36DBC0D3, 0x0BA6057A, 0xDB8D461D, + 0xD4630919, 0x04484A7E, 0x39358FD7, 0xE91ECCB0, + 0x43CF48C8, 0x93E40BAF, 0xAE99CE06, 0x7EB28D61, + 0xB7768BF6, 0x675DC891, 0x5A200D38, 0x8A0B4E5F, + 0x20DACA27, 0xF0F18940, 0xCD8C4CE9, 0x1DA70F8E, + 0x1CB5BB37, 0xCC9EF850, 0xF1E33DF9, 0x21C87E9E, + 0x8B19FAE6, 0x5B32B981, 0x664F7C28, 0xB6643F4F, + 0x7FA039D8, 0xAF8B7ABF, 0x92F6BF16, 0x42DDFC71, + 0xE80C7809, 0x38273B6E, 0x055AFEC7, 0xD571BDA0, + 0xDA9FF2A4, 0x0AB4B1C3, 0x37C9746A, 0xE7E2370D, + 0x4D33B375, 0x9D18F012, 0xA06535BB, 0x704E76DC, + 0xB98A704B, 0x69A1332C, 0x54DCF685, 0x84F7B5E2, + 0x2E26319A, 0xFE0D72FD, 0xC370B754, 0x135BF433, + 0xDDE1295C, 0x0DCA6A3B, 0x30B7AF92, 0xE09CECF5, + 0x4A4D688D, 0x9A662BEA, 0xA71BEE43, 0x7730AD24, + 0xBEF4ABB3, 0x6EDFE8D4, 0x53A22D7D, 0x83896E1A, + 0x2958EA62, 0xF973A905, 0xC40E6CAC, 0x14252FCB, + 0x1BCB60CF, 0xCBE023A8, 0xF69DE601, 0x26B6A566, + 0x8C67211E, 0x5C4C6279, 0x6131A7D0, 0xB11AE4B7, + 0x78DEE220, 0xA8F5A147, 0x958864EE, 0x45A32789, + 0xEF72A3F1, 0x3F59E096, 0x0224253F, 0xD20F6658, +}; + +/* $Id: sober128tab.c,v 1.2 2005/05/05 14:35:59 tom Exp $ */ +/* Sbox for SOBER-128 */ +/* + * This is really the combination of two SBoxes; the least significant + * 24 bits comes from: + * 8->32 Sbox generated by Millan et. al. at Queensland University of + * Technology. See: E. Dawson, W. Millan, L. Burnett, G. Carter, + * "On the Design of 8*32 S-boxes". Unpublished report, by the + * Information Systems Research Centre, + * Queensland University of Technology, 1999. + * + * The most significant 8 bits are the Skipjack "F table", which can be + * found at http://csrc.nist.gov/CryptoToolkit/skipjack/skipjack.pdf . + * In this optimised table, though, the intent is to XOR the word from + * the table selected by the high byte with the input word. Thus, the + * high byte is actually the Skipjack F-table entry XORED with its + * table index. + */ +static const ulong32 Sbox[256] = { + 0xa3aa1887, 0xd65e435c, 0x0b65c042, 0x800e6ef4, + 0xfc57ee20, 0x4d84fed3, 0xf066c502, 0xf354e8ae, + 0xbb2ee9d9, 0x281f38d4, 0x1f829b5d, 0x735cdf3c, + 0x95864249, 0xbc2e3963, 0xa1f4429f, 0xf6432c35, + 0xf7f40325, 0x3cc0dd70, 0x5f973ded, 0x9902dc5e, + 0xda175b42, 0x590012bf, 0xdc94d78c, 0x39aab26b, + 0x4ac11b9a, 0x8c168146, 0xc3ea8ec5, 0x058ac28f, + 0x52ed5c0f, 0x25b4101c, 0x5a2db082, 0x370929e1, + 0x2a1843de, 0xfe8299fc, 0x202fbc4b, 0x833915dd, + 0x33a803fa, 0xd446b2de, 0x46233342, 0x4fcee7c3, + 0x3ad607ef, 0x9e97ebab, 0x507f859b, 0xe81f2e2f, + 0xc55b71da, 0xd7e2269a, 0x1339c3d1, 0x7ca56b36, + 0xa6c9def2, 0xb5c9fc5f, 0x5927b3a3, 0x89a56ddf, + 0xc625b510, 0x560f85a7, 0xace82e71, 0x2ecb8816, + 0x44951e2a, 0x97f5f6af, 0xdfcbc2b3, 0xce4ff55d, + 0xcb6b6214, 0x2b0b83e3, 0x549ea6f5, 0x9de041af, + 0x792f1f17, 0xf73b99ee, 0x39a65ec0, 0x4c7016c6, + 0x857709a4, 0xd6326e01, 0xc7b280d9, 0x5cfb1418, + 0xa6aff227, 0xfd548203, 0x506b9d96, 0xa117a8c0, + 0x9cd5bf6e, 0xdcee7888, 0x61fcfe64, 0xf7a193cd, + 0x050d0184, 0xe8ae4930, 0x88014f36, 0xd6a87088, + 0x6bad6c2a, 0x1422c678, 0xe9204de7, 0xb7c2e759, + 0x0200248e, 0x013b446b, 0xda0d9fc2, 0x0414a895, + 0x3a6cc3a1, 0x56fef170, 0x86c19155, 0xcf7b8a66, + 0x551b5e69, 0xb4a8623e, 0xa2bdfa35, 0xc4f068cc, + 0x573a6acd, 0x6355e936, 0x03602db9, 0x0edf13c1, + 0x2d0bb16d, 0x6980b83c, 0xfeb23763, 0x3dd8a911, + 0x01b6bc13, 0xf55579d7, 0xf55c2fa8, 0x19f4196e, + 0xe7db5476, 0x8d64a866, 0xc06e16ad, 0xb17fc515, + 0xc46feb3c, 0x8bc8a306, 0xad6799d9, 0x571a9133, + 0x992466dd, 0x92eb5dcd, 0xac118f50, 0x9fafb226, + 0xa1b9cef3, 0x3ab36189, 0x347a19b1, 0x62c73084, + 0xc27ded5c, 0x6c8bc58f, 0x1cdde421, 0xed1e47fb, + 0xcdcc715e, 0xb9c0ff99, 0x4b122f0f, 0xc4d25184, + 0xaf7a5e6c, 0x5bbf18bc, 0x8dd7c6e0, 0x5fb7e420, + 0x521f523f, 0x4ad9b8a2, 0xe9da1a6b, 0x97888c02, + 0x19d1e354, 0x5aba7d79, 0xa2cc7753, 0x8c2d9655, + 0x19829da1, 0x531590a7, 0x19c1c149, 0x3d537f1c, + 0x50779b69, 0xed71f2b7, 0x463c58fa, 0x52dc4418, + 0xc18c8c76, 0xc120d9f0, 0xafa80d4d, 0x3b74c473, + 0xd09410e9, 0x290e4211, 0xc3c8082b, 0x8f6b334a, + 0x3bf68ed2, 0xa843cc1b, 0x8d3c0ff3, 0x20e564a0, + 0xf8f55a4f, 0x2b40f8e7, 0xfea7f15f, 0xcf00fe21, + 0x8a6d37d6, 0xd0d506f1, 0xade00973, 0xefbbde36, + 0x84670fa8, 0xfa31ab9e, 0xaedab618, 0xc01f52f5, + 0x6558eb4f, 0x71b9e343, 0x4b8d77dd, 0x8cb93da6, + 0x740fd52d, 0x425412f8, 0xc5a63360, 0x10e53ad0, + 0x5a700f1c, 0x8324ed0b, 0xe53dc1ec, 0x1a366795, + 0x6d549d15, 0xc5ce46d7, 0xe17abe76, 0x5f48e0a0, + 0xd0f07c02, 0x941249b7, 0xe49ed6ba, 0x37a47f78, + 0xe1cfffbd, 0xb007ca84, 0xbb65f4da, 0xb59f35da, + 0x33d2aa44, 0x417452ac, 0xc0d674a7, 0x2d61a46a, + 0xdc63152a, 0x3e12b7aa, 0x6e615927, 0xa14fb118, + 0xa151758d, 0xba81687b, 0xe152f0b3, 0x764254ed, + 0x34c77271, 0x0a31acab, 0x54f94aec, 0xb9e994cd, + 0x574d9e81, 0x5b623730, 0xce8a21e8, 0x37917f0b, + 0xe8a9b5d6, 0x9697adf8, 0xf3d30431, 0x5dcac921, + 0x76b35d46, 0xaa430a36, 0xc2194022, 0x22bca65e, + 0xdaec70ba, 0xdfaea8cc, 0x777bae8b, 0x242924d5, + 0x1f098a5a, 0x4b396b81, 0x55de2522, 0x435c1cb8, + 0xaeb8fe1d, 0x9db3c697, 0x5b164f83, 0xe0c16376, + 0xa319224c, 0xd0203b35, 0x433ac0fe, 0x1466a19a, + 0x45f0b24f, 0x51fda998, 0xc0d52d71, 0xfa0896a8, + 0xf9e6053f, 0xa4b0d300, 0xd499cbcc, 0xb95e3d40, +}; + +/* $Source: /cvs/libtom/libtomcrypt/src/prngs/sober128tab.c,v $ */ +/* $Revision: 1.2 $ */ +/* $Date: 2005/05/05 14:35:59 $ */ diff --git a/libtomcrypt/src/prngs/sprng.c b/libtomcrypt/src/prngs/sprng.c new file mode 100644 index 0000000..190e33d --- /dev/null +++ b/libtomcrypt/src/prngs/sprng.c @@ -0,0 +1,136 @@ +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtomcrypt.com + */ +#include "tomcrypt.h" + +/** + @file sprng.c + Secure PRNG, Tom St Denis +*/ + +/* A secure PRNG using the RNG functions. Basically this is a + * wrapper that allows you to use a secure RNG as a PRNG + * in the various other functions. + */ + +#ifdef SPRNG + +const struct ltc_prng_descriptor sprng_desc = +{ + "sprng", 0, + &sprng_start, + &sprng_add_entropy, + &sprng_ready, + &sprng_read, + &sprng_done, + &sprng_export, + &sprng_import, + &sprng_test +}; + +/** + Start the PRNG + @param prng [out] The PRNG state to initialize + @return CRYPT_OK if successful +*/ +int sprng_start(prng_state *prng) +{ + return CRYPT_OK; +} + +/** + Add entropy to the PRNG state + @param in The data to add + @param inlen Length of the data to add + @param prng PRNG state to update + @return CRYPT_OK if successful +*/ +int sprng_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng) +{ + return CRYPT_OK; +} + +/** + Make the PRNG ready to read from + @param prng The PRNG to make active + @return CRYPT_OK if successful +*/ +int sprng_ready(prng_state *prng) +{ + return CRYPT_OK; +} + +/** + Read from the PRNG + @param out Destination + @param outlen Length of output + @param prng The active PRNG to read from + @return Number of octets read +*/ +unsigned long sprng_read(unsigned char *out, unsigned long outlen, prng_state *prng) +{ + LTC_ARGCHK(out != NULL); + return rng_get_bytes(out, outlen, NULL); +} + +/** + Terminate the PRNG + @param prng The PRNG to terminate + @return CRYPT_OK if successful +*/ +int sprng_done(prng_state *prng) +{ + return CRYPT_OK; +} + +/** + Export the PRNG state + @param out [out] Destination + @param outlen [in/out] Max size and resulting size of the state + @param prng The PRNG to export + @return CRYPT_OK if successful +*/ +int sprng_export(unsigned char *out, unsigned long *outlen, prng_state *prng) +{ + LTC_ARGCHK(outlen != NULL); + + *outlen = 0; + return CRYPT_OK; +} + +/** + Import a PRNG state + @param in The PRNG state + @param inlen Size of the state + @param prng The PRNG to import + @return CRYPT_OK if successful +*/ +int sprng_import(const unsigned char *in, unsigned long inlen, prng_state *prng) +{ + return CRYPT_OK; +} + +/** + PRNG self-test + @return CRYPT_OK if successful, CRYPT_NOP if self-testing has been disabled +*/ +int sprng_test(void) +{ + return CRYPT_OK; +} + +#endif + + + + +/* $Source: /cvs/libtom/libtomcrypt/src/prngs/sprng.c,v $ */ +/* $Revision: 1.4 $ */ +/* $Date: 2006/03/31 14:15:35 $ */ diff --git a/libtomcrypt/src/prngs/yarrow.c b/libtomcrypt/src/prngs/yarrow.c new file mode 100644 index 0000000..9fbd4f6 --- /dev/null +++ b/libtomcrypt/src/prngs/yarrow.c @@ -0,0 +1,362 @@ +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtomcrypt.com + */ +#include "tomcrypt.h" + +/** + @file yarrow.c + Yarrow PRNG, Tom St Denis +*/ + +#ifdef YARROW + +const struct ltc_prng_descriptor yarrow_desc = +{ + "yarrow", 64, + &yarrow_start, + &yarrow_add_entropy, + &yarrow_ready, + &yarrow_read, + &yarrow_done, + &yarrow_export, + &yarrow_import, + &yarrow_test +}; + +/** + Start the PRNG + @param prng [out] The PRNG state to initialize + @return CRYPT_OK if successful +*/ +int yarrow_start(prng_state *prng) +{ + int err; + + LTC_ARGCHK(prng != NULL); + + /* these are the default hash/cipher combo used */ +#ifdef RIJNDAEL +#if YARROW_AES==0 + prng->yarrow.cipher = register_cipher(&rijndael_enc_desc); +#elif YARROW_AES==1 + prng->yarrow.cipher = register_cipher(&aes_enc_desc); +#elif YARROW_AES==2 + prng->yarrow.cipher = register_cipher(&rijndael_desc); +#elif YARROW_AES==3 + prng->yarrow.cipher = register_cipher(&aes_desc); +#endif +#elif defined(BLOWFISH) + prng->yarrow.cipher = register_cipher(&blowfish_desc); +#elif defined(TWOFISH) + prng->yarrow.cipher = register_cipher(&twofish_desc); +#elif defined(RC6) + prng->yarrow.cipher = register_cipher(&rc6_desc); +#elif defined(RC5) + prng->yarrow.cipher = register_cipher(&rc5_desc); +#elif defined(SAFERP) + prng->yarrow.cipher = register_cipher(&saferp_desc); +#elif defined(RC2) + prng->yarrow.cipher = register_cipher(&rc2_desc); +#elif defined(NOEKEON) + prng->yarrow.cipher = register_cipher(&noekeon_desc); +#elif defined(ANUBIS) + prng->yarrow.cipher = register_cipher(&anubis_desc); +#elif defined(KSEED) + prng->yarrow.cipher = register_cipher(&kseed_desc); +#elif defined(KHAZAD) + prng->yarrow.cipher = register_cipher(&khazad_desc); +#elif defined(CAST5) + prng->yarrow.cipher = register_cipher(&cast5_desc); +#elif defined(XTEA) + prng->yarrow.cipher = register_cipher(&xtea_desc); +#elif defined(SAFER) + prng->yarrow.cipher = register_cipher(&safer_sk128_desc); +#elif defined(DES) + prng->yarrow.cipher = register_cipher(&des3_desc); +#else + #error YARROW needs at least one CIPHER +#endif + if ((err = cipher_is_valid(prng->yarrow.cipher)) != CRYPT_OK) { + return err; + } + +#ifdef SHA256 + prng->yarrow.hash = register_hash(&sha256_desc); +#elif defined(SHA512) + prng->yarrow.hash = register_hash(&sha512_desc); +#elif defined(TIGER) + prng->yarrow.hash = register_hash(&tiger_desc); +#elif defined(SHA1) + prng->yarrow.hash = register_hash(&sha1_desc); +#elif defined(RIPEMD320) + prng->yarrow.hash = register_hash(&rmd320_desc); +#elif defined(RIPEMD256) + prng->yarrow.hash = register_hash(&rmd256_desc); +#elif defined(RIPEMD160) + prng->yarrow.hash = register_hash(&rmd160_desc); +#elif defined(RIPEMD128) + prng->yarrow.hash = register_hash(&rmd128_desc); +#elif defined(MD5) + prng->yarrow.hash = register_hash(&md5_desc); +#elif defined(MD4) + prng->yarrow.hash = register_hash(&md4_desc); +#elif defined(MD2) + prng->yarrow.hash = register_hash(&md2_desc); +#elif defined(WHIRLPOOL) + prng->yarrow.hash = register_hash(&whirlpool_desc); +#else + #error YARROW needs at least one HASH +#endif + if ((err = hash_is_valid(prng->yarrow.hash)) != CRYPT_OK) { + return err; + } + + /* zero the memory used */ + zeromem(prng->yarrow.pool, sizeof(prng->yarrow.pool)); + LTC_MUTEX_INIT(&prng->yarrow.prng_lock) + + return CRYPT_OK; +} + +/** + Add entropy to the PRNG state + @param in The data to add + @param inlen Length of the data to add + @param prng PRNG state to update + @return CRYPT_OK if successful +*/ +int yarrow_add_entropy(const unsigned char *in, unsigned long inlen, prng_state *prng) +{ + hash_state md; + int err; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(prng != NULL); + + LTC_MUTEX_LOCK(&prng->yarrow.prng_lock); + + if ((err = hash_is_valid(prng->yarrow.hash)) != CRYPT_OK) { + LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock); + return err; + } + + /* start the hash */ + if ((err = hash_descriptor[prng->yarrow.hash].init(&md)) != CRYPT_OK) { + LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock); + return err; + } + + /* hash the current pool */ + if ((err = hash_descriptor[prng->yarrow.hash].process(&md, prng->yarrow.pool, + hash_descriptor[prng->yarrow.hash].hashsize)) != CRYPT_OK) { + LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock); + return err; + } + + /* add the new entropy */ + if ((err = hash_descriptor[prng->yarrow.hash].process(&md, in, inlen)) != CRYPT_OK) { + LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock); + return err; + } + + /* store result */ + if ((err = hash_descriptor[prng->yarrow.hash].done(&md, prng->yarrow.pool)) != CRYPT_OK) { + LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock); + return err; + } + + LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock); + return CRYPT_OK; +} + +/** + Make the PRNG ready to read from + @param prng The PRNG to make active + @return CRYPT_OK if successful +*/ +int yarrow_ready(prng_state *prng) +{ + int ks, err; + + LTC_ARGCHK(prng != NULL); + LTC_MUTEX_LOCK(&prng->yarrow.prng_lock); + + if ((err = hash_is_valid(prng->yarrow.hash)) != CRYPT_OK) { + LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock); + return err; + } + + if ((err = cipher_is_valid(prng->yarrow.cipher)) != CRYPT_OK) { + LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock); + return err; + } + + /* setup CTR mode using the "pool" as the key */ + ks = (int)hash_descriptor[prng->yarrow.hash].hashsize; + if ((err = cipher_descriptor[prng->yarrow.cipher].keysize(&ks)) != CRYPT_OK) { + LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock); + return err; + } + + if ((err = ctr_start(prng->yarrow.cipher, /* what cipher to use */ + prng->yarrow.pool, /* IV */ + prng->yarrow.pool, ks, /* KEY and key size */ + 0, /* number of rounds */ + CTR_COUNTER_LITTLE_ENDIAN, /* little endian counter */ + &prng->yarrow.ctr)) != CRYPT_OK) { + LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock); + return err; + } + LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock); + return CRYPT_OK; +} + +/** + Read from the PRNG + @param out Destination + @param outlen Length of output + @param prng The active PRNG to read from + @return Number of octets read +*/ +unsigned long yarrow_read(unsigned char *out, unsigned long outlen, prng_state *prng) +{ + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(prng != NULL); + + LTC_MUTEX_LOCK(&prng->yarrow.prng_lock); + + /* put out in predictable state first */ + zeromem(out, outlen); + + /* now randomize it */ + if (ctr_encrypt(out, out, outlen, &prng->yarrow.ctr) != CRYPT_OK) { + LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock); + return 0; + } + LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock); + return outlen; +} + +/** + Terminate the PRNG + @param prng The PRNG to terminate + @return CRYPT_OK if successful +*/ +int yarrow_done(prng_state *prng) +{ + int err; + LTC_ARGCHK(prng != NULL); + + LTC_MUTEX_LOCK(&prng->yarrow.prng_lock); + + /* call cipher done when we invent one ;-) */ + + /* we invented one */ + err = ctr_done(&prng->yarrow.ctr); + + LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock); + return err; +} + +/** + Export the PRNG state + @param out [out] Destination + @param outlen [in/out] Max size and resulting size of the state + @param prng The PRNG to export + @return CRYPT_OK if successful +*/ +int yarrow_export(unsigned char *out, unsigned long *outlen, prng_state *prng) +{ + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + LTC_ARGCHK(prng != NULL); + + LTC_MUTEX_LOCK(&prng->yarrow.prng_lock); + + /* we'll write 64 bytes for s&g's */ + if (*outlen < 64) { + LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock); + *outlen = 64; + return CRYPT_BUFFER_OVERFLOW; + } + + if (yarrow_read(out, 64, prng) != 64) { + LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock); + return CRYPT_ERROR_READPRNG; + } + *outlen = 64; + + return CRYPT_OK; +} + +/** + Import a PRNG state + @param in The PRNG state + @param inlen Size of the state + @param prng The PRNG to import + @return CRYPT_OK if successful +*/ +int yarrow_import(const unsigned char *in, unsigned long inlen, prng_state *prng) +{ + int err; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(prng != NULL); + + LTC_MUTEX_LOCK(&prng->yarrow.prng_lock); + + if (inlen != 64) { + LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock); + return CRYPT_INVALID_ARG; + } + + if ((err = yarrow_start(prng)) != CRYPT_OK) { + LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock); + return err; + } + err = yarrow_add_entropy(in, 64, prng); + LTC_MUTEX_UNLOCK(&prng->yarrow.prng_lock); + return err; +} + +/** + PRNG self-test + @return CRYPT_OK if successful, CRYPT_NOP if self-testing has been disabled +*/ +int yarrow_test(void) +{ +#ifndef LTC_TEST + return CRYPT_NOP; +#else + int err; + prng_state prng; + + if ((err = yarrow_start(&prng)) != CRYPT_OK) { + return err; + } + + /* now let's test the hash/cipher that was chosen */ + if ((err = cipher_descriptor[prng.yarrow.cipher].test()) != CRYPT_OK) { + return err; + } + if ((err = hash_descriptor[prng.yarrow.hash].test()) != CRYPT_OK) { + return err; + } + + return CRYPT_OK; +#endif +} + +#endif + + +/* $Source: /cvs/libtom/libtomcrypt/src/prngs/yarrow.c,v $ */ +/* $Revision: 1.10 $ */ +/* $Date: 2006/11/14 04:21:17 $ */ |