added libtomcrypt-0.92

This commit is contained in:
Tom St Denis 2003-12-24 18:59:57 +00:00 committed by Steffen Jaeckel
parent 55d745af4f
commit 033cec5f75
66 changed files with 9123 additions and 1253 deletions

45
aes.c
View File

@ -47,7 +47,7 @@ const struct _cipher_descriptor aes_desc =
int rijndael_setup(const unsigned char *key, int keylen, int rounds, symmetric_key *skey)
{
int i = 0, j;
int i, j;
ulong32 temp, *rk, *rrk;
_ARGCHK(key != NULL);
@ -64,6 +64,7 @@ int rijndael_setup(const unsigned char *key, int keylen, int rounds, symmetric_k
skey->rijndael.Nr = 10 + ((keylen/8)-2)*2;
/* setup the forward key */
i = 0;
rk = skey->rijndael.eK;
LOAD32H(rk[0], key );
LOAD32H(rk[1], key + 4);
@ -83,7 +84,7 @@ int rijndael_setup(const unsigned char *key, int keylen, int rounds, symmetric_k
rk[6] = rk[2] ^ rk[5];
rk[7] = rk[3] ^ rk[6];
if (++i == 10) {
break;
break;
}
rk += 4;
}
@ -233,7 +234,11 @@ int rijndael_setup(const unsigned char *key, int keylen, int rounds, symmetric_k
return CRYPT_OK;
}
void rijndael_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey)
#ifdef CLEAN_STACK
static void _rijndael_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey)
#else
void rijndael_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey)
#endif
{
ulong32 s0, s1, s2, s3, t0, t1, t2, t3, *rk;
int Nr, r;
@ -259,8 +264,6 @@ void rijndael_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_
*/
r = Nr >> 1;
for (;;) {
/* Both of these blocks are equivalent except the top is more friendlier for x86 processors */
t0 =
Te0[byte(s0, 3)] ^
Te1[byte(s1, 2)] ^
@ -350,7 +353,20 @@ void rijndael_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_
STORE32H(s3, ct+12);
}
void rijndael_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey) {
#ifdef CLEAN_STACK
void rijndael_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey)
{
_rijndael_ecb_encrypt(pt, ct, skey);
burn_stack(sizeof(unsigned long)*8 + sizeof(unsigned long*) + sizeof(int)*2);
}
#endif
#ifdef CLEAN_STACK
static void _rijndael_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey)
#else
void rijndael_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey)
#endif
{
ulong32 s0, s1, s2, s3, t0, t1, t2, t3, *rk;
int Nr, r;
@ -467,6 +483,15 @@ void rijndael_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_
STORE32H(s3, pt+12);
}
#ifdef CLEAN_STACK
void rijndael_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey)
{
_rijndael_ecb_decrypt(ct, pt, skey);
burn_stack(sizeof(unsigned long)*8 + sizeof(unsigned long*) + sizeof(int)*2);
}
#endif
int rijndael_test(void)
{
#ifndef LTC_TEST
@ -508,7 +533,7 @@ int rijndael_test(void)
symmetric_key key;
unsigned char tmp[2][16];
int i;
int i, y;
for (i = 0; i < (int)(sizeof(tests)/sizeof(tests[0])); i++) {
zeromem(&key, sizeof(key));
@ -537,6 +562,12 @@ int rijndael_test(void)
#endif
return CRYPT_FAIL_TESTVECTOR;
}
/* now see if we can encrypt all zero bytes 1000 times, decrypt and come back where we started */
for (y = 0; y < 16; y++) tmp[0][y] = 0;
for (y = 0; y < 1000; y++) rijndael_ecb_encrypt(tmp[0], tmp[0], &key);
for (y = 0; y < 1000; y++) rijndael_ecb_decrypt(tmp[0], tmp[0], &key);
for (y = 0; y < 16; y++) if (tmp[0][y] != 0) return CRYPT_FAIL_TESTVECTOR;
}
return CRYPT_OK;
#endif

View File

@ -304,7 +304,10 @@ int blowfish_setup(const unsigned char *key, int keylen, int num_rounds,
for (x = y = 0; x < 18; x++) {
A = 0;
for (z = 0; z < 4; z++) {
A = (A << 8) | ((ulong32)key[y++ % keylen]);
A = (A << 8) | ((ulong32)key[y++] & 255);
if (y == (ulong32)keylen) {
y = 0;
}
}
skey->blowfish.K[x] = ORIG_P[x] ^ A;
}
@ -347,13 +350,6 @@ int blowfish_setup(const unsigned char *key, int keylen, int num_rounds,
return CRYPT_OK;
}
#if defined(__GNUC__)
#define S1 key->blowfish.S[0]
#define S2 key->blowfish.S[1]
#define S3 key->blowfish.S[2]
#define S4 key->blowfish.S[3]
#endif
#define F(x) ((S1[byte(x,3)] + S2[byte(x,2)]) ^ S3[byte(x,1)]) + S4[byte(x,0)]
#ifdef CLEAN_STACK
@ -364,20 +360,16 @@ void blowfish_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_
{
ulong32 L, R;
int r;
#if !defined(TWOFISH_SMALL) && !defined(__GNUC__)
ulong32 *S1, *S2, *S3, *S4;
#endif
ulong32 *S1, *S2, *S3, *S4;
_ARGCHK(pt != NULL);
_ARGCHK(ct != NULL);
_ARGCHK(key != NULL);
#if !defined(TWOFISH_SMALL) && !defined(__GNUC__)
S1 = key->blowfish.S[0];
S2 = key->blowfish.S[1];
S3 = key->blowfish.S[2];
S4 = key->blowfish.S[3];
#endif
/* load it */
LOAD32H(L, &pt[0]);
@ -416,20 +408,16 @@ void blowfish_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_
{
ulong32 L, R;
int r;
#if !defined(TWOFISH_SMALL) && !defined(__GNUC__)
ulong32 *S1, *S2, *S3, *S4;
#endif
ulong32 *S1, *S2, *S3, *S4;
_ARGCHK(pt != NULL);
_ARGCHK(ct != NULL);
_ARGCHK(key != NULL);
#if !defined(TWOFISH_SMALL) && !defined(__GNUC__)
S1 = key->blowfish.S[0];
S2 = key->blowfish.S[1];
S3 = key->blowfish.S[2];
S4 = key->blowfish.S[3];
#endif
/* load it */
LOAD32H(R, &ct[0]);
@ -487,8 +475,8 @@ int blowfish_test(void)
{ 0x7D, 0x85, 0x6F, 0x9A, 0x61, 0x30, 0x63, 0xF2}
}
};
unsigned char buf[2][8];
int x;
unsigned char tmp[2][8];
int x, y;
for (x = 0; x < (int)(sizeof(tests) / sizeof(tests[0])); x++) {
/* setup key */
@ -497,13 +485,19 @@ int blowfish_test(void)
}
/* encrypt and decrypt */
blowfish_ecb_encrypt(tests[x].pt, buf[0], &key);
blowfish_ecb_decrypt(buf[0], buf[1], &key);
blowfish_ecb_encrypt(tests[x].pt, tmp[0], &key);
blowfish_ecb_decrypt(tmp[0], tmp[1], &key);
/* compare */
if ((memcmp(buf[0], tests[x].ct, 8) != 0) || (memcmp(buf[1], tests[x].pt, 8) != 0)) {
if ((memcmp(tmp[0], tests[x].ct, 8) != 0) || (memcmp(tmp[1], tests[x].pt, 8) != 0)) {
return CRYPT_FAIL_TESTVECTOR;
}
/* now see if we can encrypt all zero bytes 1000 times, decrypt and come back where we started */
for (y = 0; y < 8; y++) tmp[0][y] = 0;
for (y = 0; y < 1000; y++) blowfish_ecb_encrypt(tmp[0], tmp[0], &key);
for (y = 0; y < 1000; y++) blowfish_ecb_decrypt(tmp[0], tmp[0], &key);
for (y = 0; y < 8; y++) if (tmp[0][y] != 0) return CRYPT_FAIL_TESTVECTOR;
}
return CRYPT_OK;
#endif

60
cast5.c
View File

@ -381,7 +381,11 @@ static const ulong32 S8[256] = {
#define GB(x, i) (((x[(15-i)>>2])>>(unsigned)(8*((15-i)&3)))&255)
#endif
#ifdef CLEAN_STACK
static int _cast5_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey)
#else
int cast5_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey)
#endif
{
ulong32 x[4], z[4];
unsigned char buf[16];
@ -431,7 +435,6 @@ int cast5_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_
skey->cast5.K[i++] = S5[GB(x, 0x5)] ^ S6[GB(x, 0x4)] ^ S7[GB(x, 0xa)] ^ S8[GB(x, 0xb)] ^ S8[GB(x, 0x7)];
/* second half */
z[3] = x[3] ^ S5[GB(x, 0xD)] ^ S6[GB(x, 0xF)] ^ S7[GB(x, 0xC)] ^ S8[GB(x, 0xE)] ^ S7[GB(x, 0x8)];
z[2] = x[1] ^ S5[GB(z, 0x0)] ^ S6[GB(z, 0x2)] ^ S7[GB(z, 0x1)] ^ S8[GB(z, 0x3)] ^ S8[GB(x, 0xA)];
z[1] = x[0] ^ S5[GB(z, 0x7)] ^ S6[GB(z, 0x6)] ^ S7[GB(z, 0x5)] ^ S8[GB(z, 0x4)] ^ S5[GB(x, 0x9)];
@ -462,6 +465,16 @@ int cast5_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_
return CRYPT_OK;
}
#ifdef CLEAN_STACK
int cast5_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey)
{
int z;
z = _cast5_setup(key, keylen, num_rounds, skey);
burn_stack(sizeof(ulong32)*8 + 16 + sizeof(int)*2);
return z;
}
#endif
#ifdef _MSC_VER
#define INLINE __inline
#else
@ -492,7 +505,11 @@ INLINE static ulong32 FIII(ulong32 R, ulong32 Km, ulong32 Kr)
return ((S1[byte(I, 3)] + S2[byte(I,2)]) ^ S3[byte(I,1)]) - S4[byte(I,0)];
}
#ifdef CLEAN_STACK
static void _cast5_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *key)
#else
void cast5_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *key)
#endif
{
ulong32 R, L;
@ -502,7 +519,6 @@ void cast5_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key
LOAD32H(L,&pt[0]);
LOAD32H(R,&pt[4]);
L ^= FI(R, key->cast5.K[0], key->cast5.K[16]);
R ^= FII(L, key->cast5.K[1], key->cast5.K[17]);
L ^= FIII(R, key->cast5.K[2], key->cast5.K[18]);
@ -525,7 +541,20 @@ void cast5_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key
STORE32H(L,&ct[4]);
}
#ifdef CLEAN_STACK
void cast5_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *key)
{
_cast5_ecb_encrypt(pt,ct,key);
burn_stack(sizeof(ulong32)*3);
}
#endif
#ifdef CLEAN_STACK
static void _cast5_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *key)
#else
void cast5_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *key)
#endif
{
ulong32 R, L;
@ -535,14 +564,12 @@ void cast5_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key
LOAD32H(R,&ct[0]);
LOAD32H(L,&ct[4]);
if (key->cast5.keylen > 10) {
R ^= FI(L, key->cast5.K[15], key->cast5.K[31]);
L ^= FIII(R, key->cast5.K[14], key->cast5.K[30]);
R ^= FII(L, key->cast5.K[13], key->cast5.K[29]);
L ^= FI(R, key->cast5.K[12], key->cast5.K[28]);
}
R ^= FIII(L, key->cast5.K[11], key->cast5.K[27]);
L ^= FII(R, key->cast5.K[10], key->cast5.K[26]);
R ^= FI(L, key->cast5.K[9], key->cast5.K[25]);
@ -555,11 +582,18 @@ void cast5_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key
L ^= FIII(R, key->cast5.K[2], key->cast5.K[18]);
R ^= FII(L, key->cast5.K[1], key->cast5.K[17]);
L ^= FI(R, key->cast5.K[0], key->cast5.K[16]);
STORE32H(L,&pt[0]);
STORE32H(R,&pt[4]);
}
#ifdef CLEAN_STACK
void cast5_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *key)
{
_cast5_ecb_decrypt(ct,pt,key);
burn_stack(sizeof(ulong32)*3);
}
#endif
int cast5_test(void)
{
#ifndef LTC_TEST
@ -587,19 +621,24 @@ int cast5_test(void)
{0x7A, 0xC8, 0x16, 0xD1, 0x6E, 0x9B, 0x30, 0x2E}
}
};
int i, err;
int i, y, err;
symmetric_key key;
unsigned char buf[8], buf2[8];
unsigned char tmp[2][8];
for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) {
if ((err = cast5_setup(tests[i].key, tests[i].keylen, 0, &key)) != CRYPT_OK) {
return err;
}
cast5_ecb_encrypt(tests[i].pt, buf, &key);
cast5_ecb_decrypt(buf, buf2, &key);
if ((memcmp(buf, tests[i].ct, 8) != 0) || (memcmp(buf2, tests[i].pt, 8) != 0)) {
cast5_ecb_encrypt(tests[i].pt, tmp[0], &key);
cast5_ecb_decrypt(tmp[0], tmp[1], &key);
if ((memcmp(tmp[0], tests[i].ct, 8) != 0) || (memcmp(tmp[1], tests[i].pt, 8) != 0)) {
return CRYPT_FAIL_TESTVECTOR;
}
/* now see if we can encrypt all zero bytes 1000 times, decrypt and come back where we started */
for (y = 0; y < 8; y++) tmp[0][y] = 0;
for (y = 0; y < 1000; y++) cast5_ecb_encrypt(tmp[0], tmp[0], &key);
for (y = 0; y < 1000; y++) cast5_ecb_decrypt(tmp[0], tmp[0], &key);
for (y = 0; y < 8; y++) if (tmp[0][y] != 0) return CRYPT_FAIL_TESTVECTOR;
}
return CRYPT_OK;
@ -618,4 +657,3 @@ int cast5_keysize(int *desired_keysize)
}
#endif

56
changes
View File

@ -1,3 +1,59 @@
Dec 24th, 2003
v0.92 -- Updated the config.pl script so the options have more details.
-- Updated demos/tv_gen to include RIPEMD hashes
-- Updated Twofish so when TWOFISH_ALL_TABLES is defined a pre-computed RS table
is included [speedup: slight, about 4k cycles on my Athlon].
-- Re-wrote the twofish large key generation [the four 8x32 key dependent tables]. Now about twice as fast.
With both optimizations [e.g. TWOFISH_ALL_TABLES defined] a 128-bit Twofish key can now be scheduled
in 26,000 cycles on my Athlon XP [as opposed to 49,000 before] when optimized for size.
-- config.pl has been updated so rmd128.o and rmd160.o are objects included in the build [oops]
-- Andrew Mann found a bug in rsa_exptmod() which wouldn't indicate if the wrong type of key was specified
(e.g. not PK_PRIVATE or PK_PUBLIC)
-- Fixed up demos/x86_prof so it sorts the output now :-)
-- The project is now powered by radioactive rubber pants.
-- Fixed dh_encrypt_key() so if you pass it a hash with a smaller output than the input key it
will return CRYPT_INVALID_HASH [to match what ecc_encrypt_key() will do]
-- Merge the store/encrypt key part of ecc_encrypt_key() as per dh_encrypt_key() [can you guess what I'm upto?]
-- Massive updates to the prime generation code. I use the LTM random prime functions [and provide a nice
interface between the LTC PRNG's and the LTM generic prng prototype]. I also use a variable number of tests
depending on the input size. This nicely speeds up most prime generation/testing within the library.
-- Added SHA-224 to the list of hashes.
-- Made HMAC test vectors constant and static [takes ROM space instead of RAM]
-- This release was brought to you by the letter P which stands for Patent Infringement.
-- Added generic HASH_PROCESS macro to mycrypt_hash.h which simplifies the hash "process" functions
I also optimized the compression functions of all but MD2 to not perform input copies when avoidable.
-- Removed the division from the Blowfish setup function [dropped 3k cycles on my Athlon]
-- Added stack cleaning to rijndael, cast5 so now all ciphers have CLEAN_STACK code.
-- Added Skipjack to the list of ciphers [made appropriate changes to demos/test.c, demos/tv_gen.c and
demos/x86_prof.c]
-- Added mechanical testing to cipher test vector routines. Now it encrypts 1000 times, then decrypts and
compares. Any fault (e.g. bug in code, compiler) in the routines is likely to show through. Doesn't
stress test the key gen though...
-- Matt Johnson found a bug in the blowfish.c apparently I was out of my mind and put twofish defines in there
The code now builds with any config. Thanks.
-- Added OMAC1 Message Authentication Code support to the library.
-- Re-prototyped the hash "process" and "done" to prevent buffer overflows [which don't seem easy to exploit].
Updated HMAC code to use them too. Hazaa!
-- Fixed bug in ECC code which wouldn't do an _ARGCHK on stat in ecc_verify_hash().
-- Fixed [temp fix] bug in all PK where the OUTPUT_BIGNUM macros would not trap errors on the to_unsigned_bin
conversion [now returns CRYPT_MEM, will fix it up better later]
-- Added DSA to the list of supported PK algorithms.
-- Fixed up various ciphers to &255 the input key bytes where required [e.g. where used to index a table] to prevent
problems on platforms where CHAR_BIT != 8
-- Merged in LibTomMath v0.28
-- Updated demos/x86_prof.c to use Yarrow during the key sched testing [was horribly slow on platforms with blockable
/dev/random].
-- Added OMAC/HMAC tests to demos/tv_gen and I now store the output of this in notes/
-- Fixed a bug in config.pl that wouldn't have TWOFISH_TABLES defined by default (too many commas on the line)
-- Fixed bug in hmac_done(). Apparently FIPS-198 [HMAC] specifies that the output can be truncated. My code
would not support that (does now just like the new OMAC code).
-- Removed "hashsize" from hmac_state as it wasn't being used.
-- Made demos/test.c stop if OMAC or HMAC tests fail (instead of just printing a failed message and keep going).
-- Updated notes/tech0003.txt to take into account the existence of Skipjack [also I fixed a few typos].
-- Slight changes to Noekeon, with SMALL_CODE undefined it uses a fully unrolled version. Dropped +10 cycles/byte
on my Athlon (35 cycles per byte or 410.4Mbit/sec at 1795Mhz)
-- Added _ARGCHK() calls to is_prime() for the two input pointers.
Sept 25th, 2003
v0.91 -- HMAC fix of 0.90 was incorrect for keys larger than the block size of the hash.
-- Added error CRYPT_FILE_NOTFOUND for the file [hmac/hash] routines.

View File

@ -34,12 +34,14 @@
"SAFER,Include Safer-64 block ciphers,y",
"RIJNDAEL,Include Rijndael (AES) block cipher,y",
"XTEA,Include XTEA block cipher,y",
"TWOFISH,Include Twofish block cipher,y",
"TWOFISH_SMALL,Include Use a low ram variant of Twofish,n",
"TWOFISH_TABLES,Include Use precomputed tables to speed up the low-ram variant,y",
"TWOFISH,Include Twofish block cipher (default: fast),y",
"TWOFISH_SMALL,Use a low ram variant of Twofish (slow cipher+keyschedule!),n",
"TWOFISH_TABLES,Use precomputed tables (fast cipher and faster keychedule but adds ~3.3KB to the size),y",
"TWOFISH_ALL_TABLES,Speed up the key schedule a little (adds ~8KB ontop of TWOFISH_TABLES to the size),n",
"DES,Include DES and 3DES block ciphers,y",
"CAST5,Include CAST5 (aka CAST-128) block cipher,y",
"NOEKEON,Include Noekeon block cipher,y",
"SKIPJACK,Include Skipjack block cipher,y",
"CFB,Include CFB block mode of operation,y",
"OFB,Include OFB block mode of operation,y",
@ -50,6 +52,7 @@
"SHA512,Include SHA512 one-way hash,y",
"SHA384,Include SHA384 one-way hash (requires SHA512),y",
"SHA256,Include SHA256 one-way hash,y",
"SHA224,Include SHA224 one-way hash (requires SHA256),y",
"TIGER,Include TIGER one-way hash,y",
"SHA1,Include SHA1 one-way hash,y",
"MD5,Include MD5 one-way hash,y",
@ -58,6 +61,7 @@
"RIPEMD128,Include RIPEMD-128 one-way hash,y",
"RIPEMD160,Include RIPEMD-160 one-way hash,y",
"HMAC,Include Hash based Message Authentication Support,y",
"OMAC,Include OMAC1 Message Authentication Support,y",
"BASE64,Include Base64 encoding support,y",
@ -68,6 +72,7 @@
"TRY_URANDOM_FIRST,Try /dev/urandom before /dev/random?,n",
"MRSA,Include RSA public key support,y",
"MDSA,Include DSA public key support,y",
"MDH,Include Diffie-Hellman (over Z/pZ) public key support,y",
"MECC,Include Eliptic Curve public key crypto support,y",
"KR,Include Keyring support (groups all three PK systems),n",
@ -146,10 +151,10 @@ for (@settings) {
# output objects
print OUT "\ndefault: library\n\n";
print OUT "OBJECTS = keyring.o gf.o mem.o sprng.o ecc.o base64.o dh.o rsa.o bits.o yarrow.o cfb.o ofb.o ecb.o ctr.o cbc.o hash.o tiger.o sha1.o md5.o md4.o md2.o sha256.o sha512.o xtea.o aes.o des.o safer_tab.o safer.o safer+.o rc4.o rc2.o rc6.o rc5.o cast5.o noekeon.o blowfish.o crypt.o mpi.o prime.o twofish.o packet.o hmac.o strings.o \n\n";
print OUT "OBJECTS = keyring.o gf.o mem.o sprng.o ecc.o base64.o dh.o rsa.o bits.o yarrow.o cfb.o ofb.o ecb.o ctr.o cbc.o hash.o tiger.o sha1.o md5.o md4.o md2.o sha256.o sha512.o xtea.o aes.o des.o safer_tab.o safer.o safer+.o rc4.o rc2.o rc6.o rc5.o cast5.o noekeon.o blowfish.o crypt.o mpi.o prime.o twofish.o packet.o hmac.o strings.o rmd128.o rmd160.o skipjack.o omac.o dsa.o\n\n";
# some depends
print OUT "rsa.o: rsa_sys.c\ndh.o: dh_sys.c\necc.o: ecc_sys.c\n\n";
print OUT "rsa.o: rsa_sys.c\ndh.o: dh_sys.c\necc.o: ecc_sys.c\naes.o: aes.c aes_tab.c\ntwofish.o: twofish.c twofish_tab.c\nsha512.o: sha384.c sha512.c\nsha256.o: sha256.c sha224.c\n\n";
# targets
print OUT "library: \$(OBJECTS)\n\t \$(AR) r libtomcrypt.a \$(OBJECTS)\n\t ranlib libtomcrypt.a\n\n";

21
crypt.c
View File

@ -110,10 +110,10 @@ struct _prng_descriptor prng_descriptor[TAB_SIZE] = {
void crypt_argchk(char *v, char *s, int d)
{
#ifdef SONY_PS2
printf("_ARGCHK '%s' failure on line %d of file %s\n",
printf("_ARGCHK '%s' failure on line %d of file %s\n",
v, d, s);
#else
fprintf(stderr, "_ARGCHK '%s' failure on line %d of file %s\n",
#else
fprintf(stderr, "_ARGCHK '%s' failure on line %d of file %s\n",
v, d, s);
#endif
(void)raise(SIGABRT);
@ -345,7 +345,7 @@ int prng_is_valid(int idx)
return CRYPT_OK;
}
const char *crypt_build_settings =
const char *crypt_build_settings =
"LibTomCrypt " SCRYPT "\n\n"
"Endianess: "
#if defined(ENDIAN_NEUTRAL)
@ -400,7 +400,7 @@ const char *crypt_build_settings =
" Twofish "
#if defined(TWOFISH_SMALL) && defined(TWOFISH_TABLES)
"(small, tables)\n"
#elif defined(TWOFISH_SMALL)
#elif defined(TWOFISH_SMALL)
"(small)\n"
#elif defined(TWOFISH_TABLES)
"(tables)\n"
@ -417,6 +417,9 @@ const char *crypt_build_settings =
#if defined(NOEKEON)
" Noekeon\n"
#endif
#if defined(SKIPJACK)
" Skipjack\n"
#endif
"\nHashes built-in:\n"
#if defined(SHA512)
@ -428,6 +431,9 @@ const char *crypt_build_settings =
#if defined(SHA256)
" SHA-256\n"
#endif
#if defined(SHA224)
" SHA-224\n"
#endif
#if defined(TIGER)
" TIGER\n"
#endif
@ -446,6 +452,9 @@ const char *crypt_build_settings =
#if defined(RIPEMD128)
" RIPEMD128\n"
#endif
#if defined(RIPEMD160)
" RIPEMD160\n"
#endif
"\nBlock Chaining Modes:\n"
#if defined(CFB)
@ -524,7 +533,7 @@ const char *crypt_build_settings =
#endif
#if defined(LTC_TEST)
" LTC_TEST "
#endif
#endif
"\n"
"\n\n\n"

View File

@ -29,6 +29,7 @@
\BOOKMARK [1][-]{section.4.2}{Hash Descriptors}{chapter.4}
\BOOKMARK [2][-]{subsection.4.2.1}{Notice}{section.4.2}
\BOOKMARK [1][-]{section.4.3}{Hash based Message Authenication Codes}{chapter.4}
\BOOKMARK [1][-]{section.4.4}{OMAC Support}{chapter.4}
\BOOKMARK [0][-]{chapter.5}{Pseudo-Random Number Generators}{}
\BOOKMARK [1][-]{section.5.1}{Core Functions}{chapter.5}
\BOOKMARK [2][-]{subsection.5.1.1}{Remarks}{section.5.1}
@ -53,24 +54,30 @@
\BOOKMARK [1][-]{section.8.2}{Core Functions}{chapter.8}
\BOOKMARK [1][-]{section.8.3}{ECC Packet}{chapter.8}
\BOOKMARK [1][-]{section.8.4}{ECC Keysizes}{chapter.8}
\BOOKMARK [0][-]{chapter.9}{Public Keyrings}{}
\BOOKMARK [0][-]{chapter.9}{Digital Signature Algorithm}{}
\BOOKMARK [1][-]{section.9.1}{Introduction}{chapter.9}
\BOOKMARK [1][-]{section.9.2}{The Keyring API}{chapter.9}
\BOOKMARK [0][-]{chapter.10}{GF\(2w\) Math Routines}{}
\BOOKMARK [0][-]{chapter.11}{Miscellaneous}{}
\BOOKMARK [1][-]{section.11.1}{Base64 Encoding and Decoding}{chapter.11}
\BOOKMARK [1][-]{section.11.2}{The Multiple Precision Integer Library \(MPI\)}{chapter.11}
\BOOKMARK [2][-]{subsection.11.2.1}{Binary Forms of ``mp\137int'' Variables}{section.11.2}
\BOOKMARK [2][-]{subsection.11.2.2}{Primality Testing}{section.11.2}
\BOOKMARK [0][-]{chapter.12}{Programming Guidelines}{}
\BOOKMARK [1][-]{section.12.1}{Secure Pseudo Random Number Generators}{chapter.12}
\BOOKMARK [1][-]{section.12.2}{Preventing Trivial Errors}{chapter.12}
\BOOKMARK [1][-]{section.12.3}{Registering Your Algorithms}{chapter.12}
\BOOKMARK [1][-]{section.12.4}{Key Sizes}{chapter.12}
\BOOKMARK [2][-]{subsection.12.4.1}{Symmetric Ciphers}{section.12.4}
\BOOKMARK [2][-]{subsection.12.4.2}{Assymetric Ciphers}{section.12.4}
\BOOKMARK [1][-]{section.12.5}{Thread Safety}{chapter.12}
\BOOKMARK [0][-]{chapter.13}{Configuring the Library}{}
\BOOKMARK [1][-]{section.13.1}{Introduction}{chapter.13}
\BOOKMARK [1][-]{section.13.2}{mycrypt\137cfg.h}{chapter.13}
\BOOKMARK [1][-]{section.13.3}{The Configure Script}{chapter.13}
\BOOKMARK [1][-]{section.9.2}{Key Generation}{chapter.9}
\BOOKMARK [1][-]{section.9.3}{Key Verification}{chapter.9}
\BOOKMARK [1][-]{section.9.4}{Signatures}{chapter.9}
\BOOKMARK [1][-]{section.9.5}{Import and Export}{chapter.9}
\BOOKMARK [0][-]{chapter.10}{Public Keyrings}{}
\BOOKMARK [1][-]{section.10.1}{Introduction}{chapter.10}
\BOOKMARK [1][-]{section.10.2}{The Keyring API}{chapter.10}
\BOOKMARK [0][-]{chapter.11}{GF\(2w\) Math Routines}{}
\BOOKMARK [0][-]{chapter.12}{Miscellaneous}{}
\BOOKMARK [1][-]{section.12.1}{Base64 Encoding and Decoding}{chapter.12}
\BOOKMARK [1][-]{section.12.2}{The Multiple Precision Integer Library \(MPI\)}{chapter.12}
\BOOKMARK [2][-]{subsection.12.2.1}{Binary Forms of ``mp\137int'' Variables}{section.12.2}
\BOOKMARK [2][-]{subsection.12.2.2}{Primality Testing}{section.12.2}
\BOOKMARK [0][-]{chapter.13}{Programming Guidelines}{}
\BOOKMARK [1][-]{section.13.1}{Secure Pseudo Random Number Generators}{chapter.13}
\BOOKMARK [1][-]{section.13.2}{Preventing Trivial Errors}{chapter.13}
\BOOKMARK [1][-]{section.13.3}{Registering Your Algorithms}{chapter.13}
\BOOKMARK [1][-]{section.13.4}{Key Sizes}{chapter.13}
\BOOKMARK [2][-]{subsection.13.4.1}{Symmetric Ciphers}{section.13.4}
\BOOKMARK [2][-]{subsection.13.4.2}{Assymetric Ciphers}{section.13.4}
\BOOKMARK [1][-]{section.13.5}{Thread Safety}{chapter.13}
\BOOKMARK [0][-]{chapter.14}{Configuring the Library}{}
\BOOKMARK [1][-]{section.14.1}{Introduction}{chapter.14}
\BOOKMARK [1][-]{section.14.2}{mycrypt\137cfg.h}{chapter.14}
\BOOKMARK [1][-]{section.14.3}{The Configure Script}{chapter.14}

BIN
crypt.pdf

Binary file not shown.

274
crypt.tex
View File

@ -1,4 +1,4 @@
\documentclass{book}
\documentclass[b5paper]{book}
\usepackage{hyperref}
\usepackage{makeidx}
\usepackage{amssymb}
@ -47,7 +47,7 @@
\def\gap{\vspace{0.5ex}}
\makeindex
\begin{document}
\title{A Tiny Crypto Library, \\ LibTomCrypt \\ Version 0.91}
\title{A Tiny Crypto Library, \\ LibTomCrypt \\ Version 0.92}
\author{Tom St Denis \\
Algonquin College \\
\\
@ -60,6 +60,19 @@ K2L 1C3 \\
Canada
}
\maketitle
This text and source code library are both hereby placed in the public domain. This book has been
formatted for B5 [176x250] paper using the \LaTeX{} {\em book} macro package.
\vspace{10cm}
\begin{flushright}Open Source. Open Academia. Open Minds.
\mbox{ }
Tom St Denis,
Ontario, Canada
\end{flushright}
\newpage
\tableofcontents
\chapter{Introduction}
@ -492,7 +505,7 @@ As of this release the current cipher\_descriptors elements are
\begin{small}
\begin{center}
\begin{tabular}{|c|c|c|c|c|c|}
\hline Name & Descriptor Name & Block Size (bytes) & Key Range (bytes) & Rounds \\
\hline Name & Descriptor Name & Block Size & Key Range & Rounds \\
\hline Blowfish & blowfish\_desc & 8 & 8 ... 56 & 16 \\
\hline X-Tea & xtea\_desc & 8 & 16 & 32 \\
\hline RC2 & rc2\_desc & 8 & 8 .. 128 & 16 \\
@ -509,6 +522,7 @@ As of this release the current cipher\_descriptors elements are
\hline 3DES (EDE mode) & des3\_desc & 8 & 21 & 16 \\
\hline CAST5 (CAST-128) & cast5\_desc & 8 & 5 .. 16 & 12, 16 \\
\hline Noekeon & noekeon\_desc & 16 & 16 & 16 \\
\hline Skipjack & skipjack\_desc & 8 & 10 & 32 \\
\hline
\end{tabular}
\end{center}
@ -783,7 +797,7 @@ void XXX_init(hash_state *md);
This simply sets up the hash to the default state governed by the specifications of the hash. To add data to the
message being hashed call:
\begin{verbatim}
void XXX_process(hash_state *md, const unsigned char *in, unsigned long len);
int XXX_process(hash_state *md, const unsigned char *in, unsigned long len);
\end{verbatim}
Essentially all hash messages are virtually infinitely\footnote{Most hashes are limited to $2^{64}$ bits or 2,305,843,009,213,693,952 bytes.} long message which
@ -801,7 +815,7 @@ md5_process(&md, "hello world", 11);
To finally get the message digest (the hash) call:
\begin{verbatim}
void XXX_done(hash_state *md,
int XXX_done(hash_state *md,
unsigned char *out);
\end{verbatim}
@ -848,8 +862,8 @@ struct _hash_descriptor {
unsigned long hashsize; /* digest output size in bytes */
unsigned long blocksize; /* the block size the hash uses */
void (*init) (hash_state *);
void (*process)(hash_state *, const unsigned char *, unsigned long);
void (*done) (hash_state *, unsigned char *);
int (*process)(hash_state *, const unsigned char *, unsigned long);
int (*done) (hash_state *, unsigned char *);
int (*test) (void);
};
\end{verbatim}
@ -966,6 +980,7 @@ The following hashes are provided as of this release:
\hline SHA-512 & sha512\_desc & 64 \\
\hline SHA-384 & sha384\_desc & 48 \\
\hline SHA-256 & sha256\_desc & 32 \\
\hline SHA-224 & sha224\_desc & 28 \\
\hline TIGER-192 & tiger\_desc & 24 \\
\hline SHA-1 & sha1\_desc & 20 \\
\hline RIPEMD-160 & rmd160\_desc & 20 \\
@ -1021,7 +1036,8 @@ int hmac_done(hmac_state *hmac, unsigned char *hashOut,
\end{verbatim}
``hmac'' is the HMAC state you are working with. ``hashOut'' is the array of octets where the HMAC code should be stored. You must
set ``outlen'' to the size of the destination buffer before calling this function. It is updated with the length of the HMAC code
produced (depending on which hash was picked)
produced (depending on which hash was picked). If ``outlen'' is less than the size of the message digest (and ultimately
the HMAC code) then the HMAC code is truncated as per FIPS-198 specifications (e.g. take the first ``outlen'' bytes).
There are two utility functions provided to make using HMACs easier todo. They accept the key and information about the
message (file pointer, address in memory) and produce the HMAC result in one shot. These are useful if you want to avoid
@ -1099,6 +1115,118 @@ int main(void)
\end{verbatim}
\end{small}
\section{OMAC Support}
OMAC\footnote{\url{http://crypt.cis.ibaraki.ac.jp/omac/omac.html}}, which stands for \textit{One-Key CBC MAC} is an
algorithm which produces a Message Authentication Code (MAC) using only a block cipher such as AES. From an API
standpoint the OMAC routines work much like the HMAC routines do. Instead in this case a cipher is used instead of a hash.
To start an OMAC state you call
\begin{verbatim}
int omac_init(omac_state *omac, int cipher,
const unsigned char *key, unsigned long keylen);
\end{verbatim}
The ``omac'' variable is the state for the OMAC algorithm. ``cipher'' is the index into the cipher\_descriptor table
of the cipher\footnote{The cipher must have a 64 or 128 bit block size. Such as CAST5, Blowfish, DES, AES, Twofish, etc.} you
wish to use. ``key'' and ``keylen'' are the keys used to authenticate the data.
To send data through the algorithm call
\begin{verbatim}
int omac_process(omac_state *state,
const unsigned char *buf, unsigned long len);
\end{verbatim}
This will send ``len'' bytes from ``buf'' through the active OMAC state ``state''. Returns \textbf{CRYPT\_OK} if the
function succeeds. When you are done with the message you can call
\begin{verbatim}
int omac_done(omac_state *state,
unsigned char *out, unsigned long *outlen);
\end{verbatim}
Which will terminate the OMAC and output the \textit{tag} (MAC) to ``out''. Note that unlike the HMAC and other code
``outlen'' can be smaller than the default MAC size (for instance AES would make a 16-byte tag). Part of the OMAC
specification states that the output may be truncated. So if you pass in $outlen = 5$ and use AES as your cipher than
the output MAC code will only be five bytes long. If ``outlen'' is larger than the default size it is set to the default
size to show how many bytes were actually used.
Similar to the HMAC code the file and memory functions are also provided. To OMAC a buffer of memory in one shot use the
following function.
\begin{verbatim}
int omac_memory(int cipher,
const unsigned char *key, unsigned long keylen,
const unsigned char *msg, unsigned long msglen,
unsigned char *out, unsigned long *outlen);
\end{verbatim}
This will compute the OMAC of ``msglen'' bytes of ``msg'' using the key ``key'' of length ``keylen'' bytes and the cipher
specified by the ``cipher'''th entry in the cipher\_descriptor table. It will store the MAC in ``out'' with the same
rules as omac\_done.
To OMAC a file use
\begin{verbatim}
int omac_file(int cipher,
const unsigned char *key, unsigned long keylen,
const char *filename,
unsigned char *out, unsigned long *outlen);
\end{verbatim}
Which will OMAC the entire contents of the file specified by ``filename'' using the key ``key'' of length ``keylen'' bytes
and the cipher specified by the ``cipher'''th entry in the cipher\_descriptor table. It will store the MAC in ``out'' with
the same rules as omac\_done.
To test if the OMAC code is working there is the following function:
\begin{verbatim}
int omac_test(void);
\end{verbatim}
Which returns {\bf CRYPT\_OK} if the code passes otherwise it returns an error code. Some example code for using the
OMAC system is given below.
\begin{small}
\begin{verbatim}
#include <mycrypt.h>
int main(void)
{
int idx, errno;
omac_state omac;
unsigned char key[16], dst[MAXBLOCKSIZE];
unsigned long dstlen;
/* register Rijndael */
if (register_cipher(&rijndael_desc) == -1) {
printf("Error registering Rijndael\n");
return -1;
}
/* get index of Rijndael in cipher descriptor table */
idx = find_cipher("rijndael");
/* we would make up our symmetric key in "key[]" here */
/* start the OMAC */
if ((errno = omac_init(&omac, idx, key, 16)) != CRYPT_OK) {
printf("Error setting up omac: %s\n", error_to_string(errno));
return -1;
}
/* process a few octets */
if((errno = omac_process(&omac, "hello", 5) != CRYPT_OK) {
printf("Error processing omac: %s\n", error_to_string(errno));
return -1;
}
/* get result (presumably to use it somehow...) */
dstlen = sizeof(dst);
if ((errno = omac_done(&omac, dst, &dstlen)) != CRYPT_OK) {
printf("Error finishing omac: %s\n", error_to_string(errno));
return -1;
}
printf("The omac is %lu bytes long\n", dstlen);
/* return */
return 0;
}
\end{verbatim}
\end{small}
\chapter{Pseudo-Random Number Generators}
\section{Core Functions}
@ -1397,6 +1525,10 @@ This loads the bignum from ``in'' as a big endian word in the format PKCS specif
in ``out'' and the size of the result in ``outlen''. ``which'' is set to {\bf PK\_PUBLIC} to use ``e''
(i.e. for encryption/verifying) and set to {\bf PK\_PRIVATE} to use ``d'' as the exponent (i.e. for decrypting/signing).
Note that this function does not perform padding on the input (as per PKCS). So if you send in ``0000001'' you will
get ``01'' back (when you do the opposite operation). Make sure you pad properly which usually involves setting the msb to
a non-zero value.
\section{Packet Routines}
To encrypt or decrypt a symmetric key using RSA the following functions are provided. The idea is that you make up
a random symmetric key and use that to encode your message. By RSA encrypting the symmetric key you can send it to a
@ -1819,6 +1951,132 @@ you have 160-bits of security (e.g. as if you signed with SHA-1).
The library will not warn you if you make this mistake so it is important to check yourself before using the
signatures.
\chapter{Digital Signature Algorithm}
\section{Introduction}
The Digital Signature Algorithm (or DSA) is a variant of the ElGamal Signature scheme which has been modified to
reduce the bandwidth of a signature. For example, to have ``80-bits of security'' with ElGamal you need a group of
order at least 1024-bits. With DSA you need a group of order at least 160-bits. By comparison the ElGamal signature
would require at least 256 bytes where as the DSA signature would require only at least 40 bytes.
The API for the DSA is essentially the same as the other PK algorithms. Except in the case of DSA no encryption or
decryption routines are provided.
\section{Key Generation}
To make a DSA key you must call the following function
\begin{verbatim}
int dsa_make_key(prng_state *prng, int wprng,
int group_size, int modulus_size,
dsa_key *key);
\end{verbatim}
The variable ``prng'' is an active PRNG state and ``wprng'' the index to the descriptor. ``group\_size'' and
``modulus\_size'' control the difficulty of forging a signature. Both parameters are in bytes. The larger the
``group\_size'' the more difficult a forgery becomes upto a limit. The value of $group\_size$ is limited by
$15 < group\_size < 1024$ and $modulus\_size - group\_size < 512$. Suggested values for the pairs are as follows.
\begin{center}
\begin{tabular}{|c|c|c|}
\hline \textbf{Bits of Security} & \textbf{group\_size} & \textbf{modulus\_size} \\
\hline 80 & 20 & 128 \\
\hline 120 & 30 & 256 \\
\hline 140 & 35 & 384 \\
\hline 160 & 40 & 512 \\
\hline
\end{tabular}
\end{center}
When you are finished with a DSA key you can call the following function to free the memory used.
\begin{verbatim}
void dsa_free(dsa_key *key);
\end{verbatim}
\section{Key Verification}
Each DSA key is composed of the following variables.
\begin{enumerate}
\item $q$ a small prime of magnitude $256^{group\_size}$.
\item $p = qr + 1$ a large prime of magnitude $256^{modulus\_size}$ where $r$ is a random even integer.
\item $g = h^r \mbox{ (mod }p\mbox{)}$ a generator of order $q$ modulo $p$. $h$ can be any non-trivial random
value. For this library they start at $h = 2$ and step until $g$ is not $1$.
\item $x$ a random secret (the secret key) in the range $1 < x < q$
\item $y = g^x \mbox{ (mod }p\mbox{)}$ the public key.
\end{enumerate}
A DSA key is considered valid if it passes all of the following tests.
\begin{enumerate}
\item $q$ must be prime.
\item $p$ must be prime.
\item $g$ cannot be one of $\lbrace -1, 0, 1 \rbrace$ (modulo $p$).
\item $g$ must be less than $p$.
\item $(p-1) \equiv 0 \mbox{ (mod }q\mbox{)}$.
\item $g^q \equiv 1 \mbox{ (mod }p\mbox{)}$.
\item $1 < y < p - 1$
\item $y^q \equiv 1 \mbox{ (mod }p\mbox{)}$.
\end{enumerate}
Tests one and two ensure that the values will at least form a field which is required for the signatures to
function. Tests three and four ensure that the generator $g$ is not set to a trivial value which would make signature
forgery easier. Test five ensures that $q$ divides the order of multiplicative sub-group of $\Z/p\Z$. Test six
ensures that the generator actually generates a prime order group. Tests seven and eight ensure that the public key
is within range and belongs to a group of prime order. Note that test eight does not prove that $g$ generated $y$ only
that $y$ belongs to a multiplicative sub-group of order $q$.
The following function will perform these tests.
\begin{verbatim}
int dsa_verify_key(dsa_key *key, int *stat);
\end{verbatim}
This will test ``key'' and store the result in ``stat''. If the result is $stat = 0$ the DSA key failed one of the tests
and should not be used at all. If the result is $stat = 1$ the DSA key is valid (as far as valid mathematics are concerned).
\section{Signatures}
To generate a DSA signature call the following function
\begin{verbatim}
int dsa_sign_hash(const unsigned char *in, unsigned long inlen,
unsigned char *out, unsigned long *outlen,
prng_state *prng, int wprng, dsa_key *key);
\end{verbatim}
Which will sign the data in ``in'' of length ``inlen'' bytes. The signature is stored in ``out'' and the size
of the signature in ``outlen''. If the signature is longer than the size you initially specify in ``outlen'' nothing
is stored and the function returns an error code. The DSA ``key'' must be of the \textbf{PK\_PRIVATE} persuasion.
To verify a hash created with that function use the following function
\begin{verbatim}
int dsa_verify_hash(const unsigned char *sig, unsigned long siglen,
const unsigned char *hash, unsigned long inlen,
int *stat, dsa_key *key);
\end{verbatim}
Which will verify the data in ``hash'' of length ``inlen'' against the signature stored in ``sig'' of length ``siglen''.
It will set ``stat'' to $1$ if the signature is valid, otherwise it sets ``stat'' to $0$.
\section{Import and Export}
To export a DSA key so that it can be transported use the following function
\begin{verbatim}
int dsa_export(unsigned char *out, unsigned long *outlen,
int type,
dsa_key *key);
\end{verbatim}
This will export the DSA ``key'' to the buffer ``out'' and set the length in ``outlen'' (which must have been previously
initialized to the maximum buffer size). The ``type`` variable may be either \textbf{PK\_PRIVATE} or \textbf{PK\_PUBLIC}
depending on whether you want to export a private or public copy of the DSA key.
To import an exported DSA key use the following function
\begin{verbatim}
int dsa_import(const unsigned char *in, unsigned long inlen,
dsa_key *key);
\end{verbatim}
This will import the DSA key from the buffer ``in'' of length ``inlen'' to the ``key''. If the process fails the function
will automatically free all of the heap allocated in the process (you don't have to call dsa\_free()).
\chapter{Public Keyrings}
\section{Introduction}
In order to simplify the usage of the public key algorithms a set of keyring routines have been developed. They let the

View File

@ -16,14 +16,14 @@ static const struct _cipher_descriptor *ciphers[] = {
&saferp_desc, &rijndael_desc,
&twofish_desc, &safer_k64_desc, &safer_sk64_desc,
&safer_k128_desc, &safer_sk128_desc, &rc2_desc,
&des_desc, &des3_desc, &cast5_desc, NULL
&des_desc, &des3_desc, &cast5_desc, &skipjack_desc, NULL
};
int usage(void)
int usage(char *name)
{
int x;
printf("Usage: ./crypt [-d](ecrypt) cipher infile outfile\nCiphers:\n");
printf("Usage: ./%s [-d](ecrypt) cipher infile outfile\nCiphers:\n", name);
for (x = 0; cipher_descriptor[x].name != NULL; x++) {
printf("%s\n",cipher_descriptor[x].name);
}
@ -73,7 +73,7 @@ int main(int argc, char *argv[])
register_algs();
if (argc < 4) {
return usage();
return usage(argv[0]);
}
if (!strcmp(argv[1], "-d")) {

View File

@ -76,4 +76,5 @@ void register_algs(void)
register_hash(&md2_desc);
register_hash(&rmd128_desc);
register_hash(&rmd160_desc);
register_hash(&sha224_desc);
}

View File

@ -932,7 +932,7 @@ dh_tests (void)
}
/* test encrypt_key */
dh_make_key (&prng, find_prng ("yarrow"), 96, &usera);
dh_make_key (&prng, find_prng ("yarrow"), 128, &usera);
for (x = 0; x < 16; x++)
buf[0][x] = x;
y = sizeof (buf[1]);
@ -1337,7 +1337,9 @@ register_all_algs (void)
#ifdef NOEKEON
register_cipher (&noekeon_desc);
#endif
#ifdef SKIPJACK
register_cipher (&skipjack_desc);
#endif
register_cipher (&null_desc);
#ifdef TIGER
@ -1358,6 +1360,9 @@ register_all_algs (void)
#ifdef SHA256
register_hash (&sha256_desc);
#endif
#ifdef SHA224
register_hash (&sha224_desc);
#endif
#ifdef SHA384
register_hash (&sha384_desc);
#endif
@ -1712,6 +1717,97 @@ test_errs (void)
}
void dsa_tests(void)
{
unsigned char msg[16], out[1024], out2[1024];
unsigned long x, y;
int err, stat1, stat2;
dsa_key key, key2;
/* make a random key */
if ((err = dsa_make_key(&prng, find_prng("yarrow"), 20, 128, &key)) != CRYPT_OK) {
printf("Error making DSA key: %s\n", error_to_string(err));
exit(-1);
}
printf("DSA Key Made\n");
/* verify it */
if ((err = dsa_verify_key(&key, &stat1)) != CRYPT_OK) {
printf("Error verifying DSA key: %s\n", error_to_string(err));
exit(-1);
}
printf("DSA key verification: %s\n", stat1 == 1 ? "passed" : "failed");
if (stat1 == 0) exit(-1);
/* sign the message */
x = sizeof(out);
if ((err = dsa_sign_hash(msg, sizeof(msg), out, &x, &prng, find_prng("yarrow"), &key)) != CRYPT_OK) {
printf("Error signing with DSA key: %s\n", error_to_string(err));
exit(-1);
}
printf("DSA 160/1024 signature is %lu bytes long\n", x);
/* verify it once */
if ((err = dsa_verify_hash(out, x, msg, sizeof(msg), &stat1, &key)) != CRYPT_OK) {
printf("Error verifying with DSA key 1: %s\n", error_to_string(err));
exit(-1);
}
/* Modify and verify again */
msg[0] ^= 1;
if ((err = dsa_verify_hash(out, x, msg, sizeof(msg), &stat2, &key)) != CRYPT_OK) {
printf("Error verifying with DSA key 2: %s\n", error_to_string(err));
exit(-1);
}
msg[0] ^= 1;
printf("DSA Verification: %d, %d, %s\n", stat1, stat2, (stat1 == 1 && stat2 == 0) ? "passed" : "failed");
if (!(stat1 == 1 && stat2 == 0)) exit(-1);
/* test exporting it */
x = sizeof(out2);
if ((err = dsa_export(out2, &x, PK_PRIVATE, &key)) != CRYPT_OK) {
printf("Error export PK_PRIVATE DSA key: %s\n", error_to_string(err));
exit(-1);
}
printf("Exported PK_PRIVATE DSA key in %lu bytes\n", x);
if ((err = dsa_import(out2, x, &key2)) != CRYPT_OK) {
printf("Error importing PK_PRIVATE DSA key: %s\n", error_to_string(err));
exit(-1);
}
/* verify a signature with it */
if ((err = dsa_verify_hash(out, x, msg, sizeof(msg), &stat1, &key2)) != CRYPT_OK) {
printf("Error verifying with DSA key 3: %s\n", error_to_string(err));
exit(-1);
}
printf("PRIVATE Import Test: %s\n", stat1 == 1 ? "passed" : "failed");
if (stat1 == 0) exit(-1);
dsa_free(&key2);
/* export as public now */
x = sizeof(out2);
if ((err = dsa_export(out2, &x, PK_PUBLIC, &key)) != CRYPT_OK) {
printf("Error export PK_PUBLIC DSA key: %s\n", error_to_string(err));
exit(-1);
}
printf("Exported PK_PUBLIC DSA key in %lu bytes\n", x);
if ((err = dsa_import(out2, x, &key2)) != CRYPT_OK) {
printf("Error importing PK_PUBLIC DSA key: %s\n", error_to_string(err));
exit(-1);
}
/* verify a signature with it */
if ((err = dsa_verify_hash(out, x, msg, sizeof(msg), &stat1, &key2)) != CRYPT_OK) {
printf("Error verifying with DSA key 4: %s\n", error_to_string(err));
exit(-1);
}
printf("PUBLIC Import Test: %s\n", stat1 == 1 ? "passed" : "failed");
if (stat1 == 0) exit(-1);
dsa_free(&key2);
dsa_free(&key);
}
int
main (void)
@ -1735,8 +1831,15 @@ main (void)
printf (crypt_build_settings);
test_errs ();
#ifdef HMAC
printf ("HMAC: %s\n", hmac_test () == CRYPT_OK ? "passed" : "failed");
if (hmac_test() != CRYPT_OK) exit(EXIT_FAILURE);
#endif
#ifdef HMAC
printf ("OMAC: %s\n", omac_test () == CRYPT_OK ? "passed" : "failed");
if (omac_test() != CRYPT_OK) exit(EXIT_FAILURE);
#endif
store_tests ();
@ -1755,11 +1858,13 @@ main (void)
#ifdef KR
kr_test ();
#endif
dsa_tests();
rsa_test ();
pad_test ();
ecc_tests ();
dh_tests ();
gf_tests ();
base64_test ();

View File

@ -42,6 +42,9 @@ void reg_algs(void)
#ifdef NOEKEON
register_cipher (&noekeon_desc);
#endif
#ifdef SKIPJACK
register_cipher (&skipjack_desc);
#endif
#ifdef TIGER
register_hash (&tiger_desc);
@ -58,6 +61,9 @@ void reg_algs(void)
#ifdef SHA1
register_hash (&sha1_desc);
#endif
#ifdef SHA224
register_hash (&sha224_desc);
#endif
#ifdef SHA256
register_hash (&sha256_desc);
#endif
@ -67,6 +73,12 @@ void reg_algs(void)
#ifdef SHA512
register_hash (&sha512_desc);
#endif
#ifdef RIPEMD128
register_hash (&rmd128_desc);
#endif
#ifdef RIPEMD160
register_hash (&rmd160_desc);
#endif
}
void hash_gen(void)
@ -83,7 +95,7 @@ void hash_gen(void)
for (y = 0; y <= (hash_descriptor[x].blocksize * 2); y++) {
for (z = 0; z < y; z++) {
buf[z] = (unsigned char)z;
buf[z] = (unsigned char)(z & 255);
}
outlen = sizeof(md);
hash_memory(x, buf, y, md, &outlen);
@ -108,7 +120,10 @@ void cipher_gen(void)
out = fopen("cipher_tv.txt", "w");
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\n");
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);
@ -133,13 +148,19 @@ void cipher_gen(void)
for (z = 0; (int)z < cipher_descriptor[x].block_length; z++) {
pt[z] = (unsigned char)z;
}
for (w = 0; w < 25; w++) {
for (w = 0; w < 50; w++) {
cipher_descriptor[x].ecb_encrypt(pt, pt, &skey);
fprintf(out, "%2lu: ", w);
for (z = 0; (int)z < cipher_descriptor[x].block_length; z++) {
fprintf(out, "%02X", pt[z]);
}
fprintf(out, "\n");
/* reschedule a new key */
for (z = 0; z < (unsigned long)kl; z++) {
key[z] = pt[z % cipher_descriptor[x].block_length];
}
cipher_descriptor[x].setup(key, kl, 0, &skey);
}
fprintf(out, "\n");
}
@ -147,13 +168,114 @@ void cipher_gen(void)
}
fclose(out);
}
void hmac_gen(void)
{
unsigned char key[MAXBLOCKSIZE], output[MAXBLOCKSIZE], input[MAXBLOCKSIZE*2+2];
int x, y, z, kl, err;
FILE *out;
unsigned long len;
out = fopen("hmac_tv.txt", "w");
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, "HMAC-%s\n", hash_descriptor[x].name);
/* initial key */
for (y = 0; y < (int)hash_descriptor[x].hashsize; y++) {
key[y] = (y&255);
}
for (y = 0; y <= (int)(hash_descriptor[x].blocksize * 2); y++) {
for (z = 0; z < y; z++) {
input[z] = (unsigned char)(z & 255);
}
len = sizeof(output);
if ((err = hmac_memory(x, key, hash_descriptor[x].hashsize, input, y, output, &len)) != CRYPT_OK) {
printf("Error hmacing: %s\n", error_to_string(err));
exit(EXIT_FAILURE);
}
fprintf(out, "%3d: ", y);
for (z = 0; z <(int) len; z++) {
fprintf(out, "%02X", output[z]);
}
fprintf(out, "\n");
/* forward the key */
memcpy(key, output, hash_descriptor[x].hashsize);
}
fprintf(out, "\n");
}
fclose(out);
}
void omac_gen(void)
{
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,
"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++) {
kl = cipher_descriptor[x].block_length;
/* skip ciphers which do not have 64 or 128 bit block sizes */
if (kl != 8 && kl != 16) continue;
if (cipher_descriptor[x].keysize(&kl) != CRYPT_OK) {
kl = cipher_descriptor[x].max_key_length;
}
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);
}
len = sizeof(output);
if ((err = omac_memory(x, key, kl, input, y, output, &len)) != CRYPT_OK) {
printf("Error omacing: %s\n", error_to_string(err));
exit(EXIT_FAILURE);
}
fprintf(out, "%3d: ", y);
for (z = 0; z <(int)len; z++) {
fprintf(out, "%02X", output[z]);
}
fprintf(out, "\n");
/* forward the key */
for (z = 0; z < kl; z++) {
key[z] = output[z % len];
}
}
fprintf(out, "\n");
}
fclose(out);
}
int main(void)
{
reg_algs();
hash_gen();
cipher_gen();
hmac_gen();
omac_gen();
return 0;
}

View File

@ -3,6 +3,51 @@
#define KTIMES 25
#define TIMES 100000
struct list {
int id;
unsigned long spd1, spd2, avg;
} results[100];
int no_results;
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;
}
void tally_results(int type)
{
int x;
// qsort the results
qsort(results, no_results, sizeof(struct list), &sorter);
printf("\n");
if (type == 0) {
for (x = 0; x < no_results; x++) {
printf("%-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: Encrypt at %5lu, Decrypt at %5lu\n", cipher_descriptor[results[x].id].name, results[x].spd1, results[x].spd2);
}
} else {
for (x = 0; x < no_results; x++) {
printf
("%-20s: Process at %5lu\n", hash_descriptor[results[x].id].name, results[x].spd1 / 1000);
}
}
}
/* RDTSC from Scott Duplichan */
static ulong64 rdtsc (void)
{
@ -35,6 +80,7 @@ static ulong64 rdtsc (void)
}
ulong64 timer, skew = 0;
prng_state prng;
void t_start(void)
{
@ -107,6 +153,9 @@ void reg_algs(void)
#ifdef NOEKEON
register_cipher (&noekeon_desc);
#endif
#ifdef SKIPJACK
register_cipher (&skipjack_desc);
#endif
#ifdef TIGER
register_hash (&tiger_desc);
@ -123,6 +172,9 @@ void reg_algs(void)
#ifdef SHA1
register_hash (&sha1_desc);
#endif
#ifdef SHA224
register_hash (&sha224_desc);
#endif
#ifdef SHA256
register_hash (&sha256_desc);
#endif
@ -139,6 +191,8 @@ void reg_algs(void)
register_hash (&rmd160_desc);
#endif
register_prng(&yarrow_desc);
rng_make_prng(128, find_prng("yarrow"), &prng, NULL);
}
int time_keysched(void)
@ -151,24 +205,28 @@ int time_keysched(void)
unsigned char key[MAXBLOCKSIZE];
printf ("\n\nKey Schedule Time Trials for the Symmetric Ciphers:\n(Times are cycles per key)\n");
for (x = 0; cipher_descriptor[x].name != NULL; x++) {
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++) {
rng_get_bytes(key, kl, NULL);
yarrow_read(key, kl, &prng);
t_start();
DO1(key);
t1 = t_read();
c1 = (t1 > c1) ? c1 : t1;
}
t1 = c1 - skew;
printf("%-20s: Schedule at %6lu\n", cipher_descriptor[x].name, (unsigned long)t1);
results[no_results].spd1 = results[no_results].avg = t1;
results[no_results++].id = x;
printf("."); fflush(stdout);
#undef DO1
}
tally_results(0);
return 0;
}
@ -183,6 +241,7 @@ int time_cipher(void)
printf ("\n\nECB Time Trials for the Symmetric Ciphers:\n");
no_results = 0;
for (x = 0; cipher_descriptor[x].name != NULL; x++) {
cipher_descriptor[x].setup (key, cipher_descriptor[x].min_key_length, 0,
&skey);
@ -220,13 +279,18 @@ int time_cipher(void)
c2 = (t2 > c2 ? c2 : t2);
}
a2 = c2 - c1 - skew;
printf
("%-20s: Encrypt at %7.3f, Decrypt at %7.3f\n", cipher_descriptor[x].name, a1/(double)cipher_descriptor[x].block_length, a2/(double)cipher_descriptor[x].block_length);
results[no_results].id = x;
results[no_results].spd1 = a1/cipher_descriptor[x].block_length;
results[no_results].spd2 = a2/cipher_descriptor[x].block_length;;
results[no_results].avg = (results[no_results].spd1 + results[no_results].spd2+1)/2;
++no_results;
printf("."); fflush(stdout);
#undef DO2
#undef DO1
}
tally_results(1);
return 0;
}
@ -236,11 +300,12 @@ int time_hash(void)
unsigned long x, y1, len;
ulong64 t1, t2, c1, c2;
hash_state md;
void (*func)(hash_state *, const unsigned char *, unsigned long);
int (*func)(hash_state *, const unsigned char *, unsigned long);
unsigned char pt[MAXBLOCKSIZE];
printf ("\n\nHASH Time Trials for:\n");
no_results = 0;
for (x = 0; hash_descriptor[x].name != NULL; x++) {
hash_descriptor[x].init(&md);
@ -262,13 +327,14 @@ int time_hash(void)
}
t1 = c2 - c1 - skew;
t1 = ((t1 * CONST64(1000))) / ((ulong64)hash_descriptor[x].blocksize);
printf
("%-20s: Process at %9.3f\n", hash_descriptor[x].name, t1 / 1000.0);
results[no_results].id = x;
results[no_results].spd1 = results[no_results].avg = t1;
++no_results;
printf("."); fflush(stdout);
#undef DO2
#undef DO1
}
tally_results(2);
return 0;
}

16
des.c
View File

@ -1713,8 +1713,8 @@ int des_test(void)
http://www.ecs.soton.ac.uk/~prw99r/ez438/vectors.txt
***/
};
int i;
unsigned char out[8];
int i, y;
unsigned char tmp[8];
symmetric_key des;
for(i=0; i < (int)(sizeof(cases)/sizeof(cases[0])); i++)
@ -1723,14 +1723,20 @@ int des_test(void)
return err;
}
if (cases[i].mode != 0) {
des_ecb_encrypt(cases[i].txt, out, &des);
des_ecb_encrypt(cases[i].txt, tmp, &des);
} else {
des_ecb_decrypt(cases[i].txt, out, &des);
des_ecb_decrypt(cases[i].txt, tmp, &des);
}
if (memcmp(cases[i].out, out, sizeof out) != 0) {
if (memcmp(cases[i].out, tmp, sizeof(tmp)) != 0) {
return CRYPT_FAIL_TESTVECTOR;
}
/* now see if we can encrypt all zero bytes 1000 times, decrypt and come back where we started */
for (y = 0; y < 8; y++) tmp[y] = 0;
for (y = 0; y < 1000; y++) des_ecb_encrypt(tmp, tmp, &des);
for (y = 0; y < 1000; y++) des_ecb_decrypt(tmp, tmp, &des);
for (y = 0; y < 8; y++) if (tmp[y] != 0) return CRYPT_FAIL_TESTVECTOR;
}
return CRYPT_OK;

51
dh.c
View File

@ -149,34 +149,34 @@ int dh_test(void)
mp_int p, g, tmp;
int x, res, primality;
if (mp_init_multi(&p, &g, &tmp, NULL) != MP_OKAY) { goto error; }
if ((res = mp_init_multi(&p, &g, &tmp, NULL)) != MP_OKAY) { goto error; }
for (x = 0; sets[x].size != 0; x++) {
#if 0
printf("dh_test():testing size %d-bits\n", sets[x].size * 8);
#endif
if (mp_read_radix(&g,(char *)sets[x].base, 64) != MP_OKAY) { goto error; }
if (mp_read_radix(&p,(char *)sets[x].prime, 64) != MP_OKAY) { goto error; }
if ((res = mp_read_radix(&g,(char *)sets[x].base, 64)) != MP_OKAY) { goto error; }
if ((res = mp_read_radix(&p,(char *)sets[x].prime, 64)) != MP_OKAY) { goto error; }
/* ensure p is prime */
if ((res = is_prime(&p, &primality)) != CRYPT_OK) { goto done; }
if ((res = is_prime(&p, &primality)) != CRYPT_OK) { goto done; }
if (primality == 0) {
res = CRYPT_FAIL_TESTVECTOR;
goto done;
}
if (mp_sub_d(&p, 1, &tmp) != MP_OKAY) { goto error; }
if (mp_div_2(&tmp, &tmp) != MP_OKAY) { goto error; }
if ((res = mp_sub_d(&p, 1, &tmp)) != MP_OKAY) { goto error; }
if ((res = mp_div_2(&tmp, &tmp)) != MP_OKAY) { goto error; }
/* ensure (p-1)/2 is prime */
if ((res = is_prime(&tmp, &primality)) != CRYPT_OK) { goto done; }
if ((res = is_prime(&tmp, &primality)) != CRYPT_OK) { goto done; }
if (primality == 0) {
res = CRYPT_FAIL_TESTVECTOR;
goto done;
}
/* now see if g^((p-1)/2) mod p is in fact 1 */
if (mp_exptmod(&g, &tmp, &p, &tmp) != MP_OKAY) { goto error; }
if ((res = mp_exptmod(&g, &tmp, &p, &tmp)) != MP_OKAY) { goto error; }
if (mp_cmp_d(&tmp, 1)) {
res = CRYPT_FAIL_TESTVECTOR;
goto done;
@ -185,7 +185,7 @@ int dh_test(void)
res = CRYPT_OK;
goto done;
error:
res = CRYPT_MEM;
res = mpi_to_ltc_error(res);
done:
mp_clear_multi(&tmp, &g, &p, NULL);
return res;
@ -247,25 +247,25 @@ int dh_make_key(prng_state *prng, int wprng, int keysize, dh_key *key)
}
/* init parameters */
if (mp_init_multi(&g, &p, &key->x, &key->y, NULL) != MP_OKAY) {
return CRYPT_MEM;
if ((res = mp_init_multi(&g, &p, &key->x, &key->y, NULL)) != MP_OKAY) {
return mpi_to_ltc_error(res);
}
if (mp_read_radix(&g, sets[key->idx].base, 64) != MP_OKAY) { goto error; }
if (mp_read_radix(&p, sets[key->idx].prime, 64) != MP_OKAY) { goto error; }
if ((res = mp_read_radix(&g, sets[key->idx].base, 64)) != MP_OKAY) { goto error; }
if ((res = mp_read_radix(&p, sets[key->idx].prime, 64)) != MP_OKAY) { goto error; }
/* load the x value */
if (mp_read_unsigned_bin(&key->x, buf, keysize) != MP_OKAY) { goto error; }
if (mp_exptmod(&g, &key->x, &p, &key->y) != MP_OKAY) { goto error; }
if ((res = mp_read_unsigned_bin(&key->x, buf, keysize)) != MP_OKAY) { goto error; }
if ((res = mp_exptmod(&g, &key->x, &p, &key->y)) != MP_OKAY) { goto error; }
key->type = PK_PRIVATE;
if (mp_shrink(&key->x) != MP_OKAY) { goto error; }
if (mp_shrink(&key->y) != MP_OKAY) { goto error; }
if ((res = mp_shrink(&key->x)) != MP_OKAY) { goto error; }
if ((res = mp_shrink(&key->y)) != MP_OKAY) { goto error; }
/* free up ram */
res = CRYPT_OK;
goto done2;
error:
res = CRYPT_MEM;
res = mpi_to_ltc_error(res);
mp_clear_multi(&key->x, &key->y, NULL);
done2:
mp_clear_multi(&p, &g, NULL);
@ -284,7 +284,7 @@ void dh_free(dh_key *key)
z = (unsigned long)mp_unsigned_bin_size(num); \
STORE32L(z, buf2+y); \
y += 4; \
(void)mp_to_unsigned_bin(num, buf2+y); \
if ((err = mp_to_unsigned_bin(num, buf2+y)) != MP_OKAY) { return mpi_to_ltc_error(err); } \
y += z; \
}
@ -306,13 +306,13 @@ void dh_free(dh_key *key)
} \
\
/* load it */ \
if (mp_read_unsigned_bin(num, (unsigned char *)in+y, (int)x) != MP_OKAY) {\
err = CRYPT_MEM; \
if ((err = mp_read_unsigned_bin(num, (unsigned char *)in+y, (int)x)) != MP_OKAY) {\
err = mpi_to_ltc_error(err); \
goto error; \
} \
y += x; \
if (mp_shrink(num) != MP_OKAY) { \
err = CRYPT_MEM; \
if ((err = mp_shrink(num)) != MP_OKAY) { \
err = mpi_to_ltc_error(err); \
goto error; \
} \
}
@ -322,6 +322,7 @@ int dh_export(unsigned char *out, unsigned long *outlen, int type, dh_key *key)
{
unsigned char buf2[1536];
unsigned long y, z;
int err;
_ARGCHK(out != NULL);
_ARGCHK(outlen != NULL);
@ -387,8 +388,8 @@ int dh_import(const unsigned char *in, unsigned long inlen, dh_key *key)
}
/* init */
if (mp_init_multi(&key->x, &key->y, NULL) != MP_OKAY) {
return CRYPT_MEM;
if ((err = mp_init_multi(&key->x, &key->y, NULL)) != MP_OKAY) {
return mpi_to_ltc_error(err);
}
/* advance past packet header */

View File

@ -23,7 +23,7 @@ int dh_encrypt_key(const unsigned char *inkey, unsigned long keylen,
}
if (keylen > hash_descriptor[hash].hashsize) {
return CRYPT_INVALID_ARG;
return CRYPT_INVALID_HASH;
}
/* make a random key and export the public copy */
@ -250,32 +250,32 @@ int dh_sign_hash(const unsigned char *in, unsigned long inlen,
}
/* init bignums */
if (mp_init_multi(&a, &b, &k, &m, &p, &g, &p1, &tmp, NULL) != MP_OKAY) {
return CRYPT_MEM;
if ((err = mp_init_multi(&a, &b, &k, &m, &p, &g, &p1, &tmp, NULL)) != MP_OKAY) {
return mpi_to_ltc_error(err);
}
/* load k and m */
if (mp_read_unsigned_bin(&m, (unsigned char *)in, inlen) != MP_OKAY) { goto error; }
if ((err = mp_read_unsigned_bin(&m, (unsigned char *)in, inlen)) != MP_OKAY) { goto error; }
#ifdef FAST_PK
if (mp_read_unsigned_bin(&k, buf, MIN(32,sets[key->idx].size)) != MP_OKAY) { goto error; }
if ((err = mp_read_unsigned_bin(&k, buf, MIN(32,sets[key->idx].size))) != MP_OKAY) { goto error; }
#else
if (mp_read_unsigned_bin(&k, buf, sets[key->idx].size) != MP_OKAY) { goto error; }
if ((err = mp_read_unsigned_bin(&k, buf, sets[key->idx].size)) != MP_OKAY) { goto error; }
#endif
/* load g, p and p1 */
if (mp_read_radix(&g, sets[key->idx].base, 64) != MP_OKAY) { goto error; }
if (mp_read_radix(&p, sets[key->idx].prime, 64) != MP_OKAY) { goto error; }
if (mp_sub_d(&p, 1, &p1) != MP_OKAY) { goto error; }
if (mp_div_2(&p1, &p1) != MP_OKAY) { goto error; } /* p1 = (p-1)/2 */
if ((err = mp_read_radix(&g, sets[key->idx].base, 64)) != MP_OKAY) { goto error; }
if ((err = mp_read_radix(&p, sets[key->idx].prime, 64)) != MP_OKAY) { goto error; }
if ((err = mp_sub_d(&p, 1, &p1)) != MP_OKAY) { goto error; }
if ((err = mp_div_2(&p1, &p1)) != MP_OKAY) { goto error; } /* p1 = (p-1)/2 */
/* now get a = g^k mod p */
if (mp_exptmod(&g, &k, &p, &a) != MP_OKAY) { goto error; }
if ((err = mp_exptmod(&g, &k, &p, &a)) != MP_OKAY) { goto error; }
/* now find M = xa + kb mod p1 or just b = (M - xa)/k mod p1 */
if (mp_invmod(&k, &p1, &k) != MP_OKAY) { goto error; } /* k = 1/k mod p1 */
if (mp_mulmod(&a, &key->x, &p1, &tmp) != MP_OKAY) { goto error; } /* tmp = xa */
if (mp_submod(&m, &tmp, &p1, &tmp) != MP_OKAY) { goto error; } /* tmp = M - xa */
if (mp_mulmod(&k, &tmp, &p1, &b) != MP_OKAY) { goto error; } /* b = (M - xa)/k */
if ((err = mp_invmod(&k, &p1, &k)) != MP_OKAY) { goto error; } /* k = 1/k mod p1 */
if ((err = mp_mulmod(&a, &key->x, &p1, &tmp)) != MP_OKAY) { goto error; } /* tmp = xa */
if ((err = mp_submod(&m, &tmp, &p1, &tmp)) != MP_OKAY) { goto error; } /* tmp = M - xa */
if ((err = mp_mulmod(&k, &tmp, &p1, &b)) != MP_OKAY) { goto error; } /* b = (M - xa)/k */
/* store header */
y = PACKET_SIZE;
@ -283,11 +283,13 @@ int dh_sign_hash(const unsigned char *in, unsigned long inlen,
/* now store them both (a,b) */
x = (unsigned long)mp_unsigned_bin_size(&a);
STORE32L(x, buf+y); y += 4;
mp_to_unsigned_bin(&a, buf+y); y += x;
if ((err = mp_to_unsigned_bin(&a, buf+y)) != MP_OKAY) { goto error; }
y += x;
x = (unsigned long)mp_unsigned_bin_size(&b);
STORE32L(x, buf+y); y += 4;
mp_to_unsigned_bin(&b, buf+y); y += x;
if ((err = mp_to_unsigned_bin(&b, buf+y)) != MP_OKAY) { goto error; }
y += x;
/* check if size too big */
if (*outlen < y) {
@ -308,7 +310,7 @@ int dh_sign_hash(const unsigned char *in, unsigned long inlen,
res = CRYPT_OK;
goto done;
error:
res = CRYPT_MEM;
res = mpi_to_ltc_error(err);
done:
mp_clear_multi(&tmp, &p1, &g, &p, &m, &k, &b, &a, NULL);
return res;
@ -346,8 +348,8 @@ int dh_verify_hash(const unsigned char *sig, unsigned long siglen,
y = PACKET_SIZE;
/* init all bignums */
if (mp_init_multi(&a, &p, &b, &g, &m, &tmp, NULL) != MP_OKAY) {
return CRYPT_MEM;
if ((err = mp_init_multi(&a, &p, &b, &g, &m, &tmp, NULL)) != MP_OKAY) {
return mpi_to_ltc_error(err);
}
/* load a and b */
@ -359,7 +361,7 @@ int dh_verify_hash(const unsigned char *sig, unsigned long siglen,
}
y += 4;
if (mp_read_unsigned_bin(&a, (unsigned char *)sig+y, x) != MP_OKAY) { goto error; }
if ((err = mp_read_unsigned_bin(&a, (unsigned char *)sig+y, x)) != MP_OKAY) { goto error; }
y += x;
LOAD32L(x, sig+y);
@ -369,23 +371,23 @@ int dh_verify_hash(const unsigned char *sig, unsigned long siglen,
siglen -= x;
}
y += 4;
if (mp_read_unsigned_bin(&b, (unsigned char *)sig+y, x) != MP_OKAY) { goto error; }
if ((err = mp_read_unsigned_bin(&b, (unsigned char *)sig+y, x)) != MP_OKAY) { goto error; }
y += x;
/* load p and g */
if (mp_read_radix(&p, sets[key->idx].prime, 64) != MP_OKAY) { goto error; }
if (mp_read_radix(&g, sets[key->idx].base, 64) != MP_OKAY) { goto error; }
if ((err = mp_read_radix(&p, sets[key->idx].prime, 64)) != MP_OKAY) { goto error; }
if ((err = mp_read_radix(&g, sets[key->idx].base, 64)) != MP_OKAY) { goto error; }
/* load m */
if (mp_read_unsigned_bin(&m, (unsigned char *)hash, hashlen) != MP_OKAY) { goto error; }
if ((err = mp_read_unsigned_bin(&m, (unsigned char *)hash, hashlen)) != MP_OKAY) { goto error; }
/* find g^m mod p */
if (mp_exptmod(&g, &m, &p, &m) != MP_OKAY) { goto error; } /* m = g^m mod p */
if ((err = mp_exptmod(&g, &m, &p, &m)) != MP_OKAY) { goto error; } /* m = g^m mod p */
/* find y^a * a^b */
if (mp_exptmod(&key->y, &a, &p, &tmp) != MP_OKAY) { goto error; } /* tmp = y^a mod p */
if (mp_exptmod(&a, &b, &p, &a) != MP_OKAY) { goto error; } /* a = a^b mod p */
if (mp_mulmod(&a, &tmp, &p, &a) != MP_OKAY) { goto error; } /* a = y^a * a^b mod p */
if ((err = mp_exptmod(&key->y, &a, &p, &tmp)) != MP_OKAY) { goto error; } /* tmp = y^a mod p */
if ((err = mp_exptmod(&a, &b, &p, &a)) != MP_OKAY) { goto error; } /* a = a^b mod p */
if ((err = mp_mulmod(&a, &tmp, &p, &a)) != MP_OKAY) { goto error; } /* a = y^a * a^b mod p */
/* y^a * a^b == g^m ??? */
if (mp_cmp(&a, &m) == 0) {
@ -396,7 +398,7 @@ int dh_verify_hash(const unsigned char *sig, unsigned long siglen,
res = CRYPT_OK;
goto done;
error:
res = CRYPT_MEM;
res = mpi_to_ltc_error(err);
done:
mp_clear_multi(&tmp, &m, &g, &p, &b, &a, NULL);
return res;

498
dsa.c Normal file
View File

@ -0,0 +1,498 @@
#include "mycrypt.h"
#ifdef MDSA
#define DRAW(x) { char __buf[1000]; mp_toradix(x, __buf, 16); printf("\n%s == %s\n", #x, __buf); }
int dsa_make_key(prng_state *prng, int wprng, int group_size, int modulus_size, dsa_key *key)
{
mp_int tmp, tmp2;
int err, res;
unsigned char buf[512];
_ARGCHK(prng != NULL);
_ARGCHK(key != NULL);
/* check prng */
if ((err = prng_is_valid(wprng)) != CRYPT_OK) {
return err;
}
/* check size */
if (group_size >= 1024 || group_size <= 15 ||
group_size >= modulus_size || (modulus_size - group_size) >= (int)sizeof(buf)) {
return CRYPT_INVALID_ARG;
}
/* init mp_ints */
if ((err = mp_init_multi(&tmp, &tmp2, &key->g, &key->q, &key->p, &key->x, &key->y, NULL)) != MP_OKAY) {
return mpi_to_ltc_error(err);
}
/* make our prime q */
if ((err = rand_prime(&key->q, group_size, prng, wprng)) != CRYPT_OK) { goto error2; }
/* double q */
if ((err = mp_mul_2(&key->q, &tmp)) != MP_OKAY) { goto error; }
/* now make a random string and multply it against q */
if (prng_descriptor[wprng].read(buf, modulus_size - group_size, prng) != (unsigned long)(modulus_size - group_size)) {
err = CRYPT_ERROR_READPRNG;
goto error2;
}
/* force magnitude */
buf[0] |= 0x80;
/* force even */
buf[modulus_size - group_size - 1] &= ~1;
if ((err = mp_read_unsigned_bin(&tmp2, buf, modulus_size - group_size)) != MP_OKAY) { goto error; }
if ((err = mp_mul(&key->q, &tmp2, &key->p)) != MP_OKAY) { goto error; }
if ((err = mp_add_d(&key->p, 1, &key->p)) != MP_OKAY) { goto error; }
/* now loop until p is prime */
for (;;) {
if ((err = is_prime(&key->p, &res)) != CRYPT_OK) { goto error2; }
if (res == MP_YES) break;
/* add 2q to p and 2 to tmp2 */
if ((err = mp_add(&tmp, &key->p, &key->p)) != MP_OKAY) { goto error; }
if ((err = mp_add_d(&tmp2, 2, &tmp2)) != MP_OKAY) { goto error; }
}
/* now p = (q * tmp2) + 1 is prime, find a value g for which g^tmp2 != 1 */
mp_set(&key->g, 1);
do {
if ((err = mp_add_d(&key->g, 1, &key->g)) != MP_OKAY) { goto error; }
if ((err = mp_exptmod(&key->g, &tmp2, &key->p, &tmp)) != MP_OKAY) { goto error; }
} while (mp_cmp_d(&tmp, 1) == MP_EQ);
/* at this point tmp generates a group of order q mod p */
mp_exch(&tmp, &key->g);
/* so now we have our DH structure, generator g, order q, modulus p
Now we need a random exponent [mod q] and it's power g^x mod p
*/
do {
if (prng_descriptor[wprng].read(buf, group_size, prng) != (unsigned long)group_size) {
err = CRYPT_ERROR_READPRNG;
goto error2;
}
if ((err = mp_read_unsigned_bin(&key->x, buf, group_size)) != MP_OKAY) { goto error; }
} while (mp_cmp_d(&key->x, 1) != MP_GT);
if ((err = mp_exptmod(&key->g, &key->x, &key->p, &key->y)) != MP_OKAY) { goto error; }
key->type = PK_PRIVATE;
key->qord = group_size;
/* shrink the ram required */
if ((err = mp_shrink(&key->g)) != MP_OKAY) { goto error; }
if ((err = mp_shrink(&key->p)) != MP_OKAY) { goto error; }
if ((err = mp_shrink(&key->q)) != MP_OKAY) { goto error; }
if ((err = mp_shrink(&key->x)) != MP_OKAY) { goto error; }
if ((err = mp_shrink(&key->y)) != MP_OKAY) { goto error; }
err = CRYPT_OK;
#ifdef CLEAN_STACK
zeromem(buf, sizeof(buf));
#endif
goto done;
error : err = mpi_to_ltc_error(err);
error2: mp_clear_multi(&key->g, &key->q, &key->p, &key->x, &key->y, NULL);
done : mp_clear_multi(&tmp, &tmp2, NULL);
return err;
}
void dsa_free(dsa_key *key)
{
_ARGCHK(key != NULL);
mp_clear_multi(&key->g, &key->q, &key->p, &key->x, &key->y, NULL);
}
int dsa_sign_hash(const unsigned char *in, unsigned long inlen,
unsigned char *out, unsigned long *outlen,
prng_state *prng, int wprng, dsa_key *key)
{
mp_int k, kinv, tmp, r, s;
unsigned char buf[512];
int err, y;
unsigned long len;
_ARGCHK(in != NULL);
_ARGCHK(out != NULL);
_ARGCHK(prng != NULL);
_ARGCHK(outlen != NULL);
_ARGCHK(key != NULL);
if ((err = prng_is_valid(wprng)) != CRYPT_OK) {
return err;
}
if (key->type != PK_PRIVATE) {
return CRYPT_PK_NOT_PRIVATE;
}
/* check group order size */
if (key->qord >= (int)sizeof(buf)) {
return CRYPT_INVALID_ARG;
}
/* Init our temps */
if ((err = mp_init_multi(&k, &kinv, &r, &s, &tmp, NULL)) != MP_OKAY) { goto error; }
retry:
/* gen random k */
if (prng_descriptor[wprng].read(buf, key->qord, prng) != (unsigned long)key->qord) {
err = CRYPT_ERROR_READPRNG;
goto done;
}
/* read k */
if ((err = mp_read_unsigned_bin(&k, buf, key->qord)) != MP_OKAY) { goto error; }
/* now find 1/k mod q */
if ((err = mp_invmod(&k, &key->q, &kinv)) != MP_OKAY) { goto error; }
/* now find r = g^k mod p mod q */
if ((err = mp_exptmod(&key->g, &k, &key->p, &r)) != MP_OKAY) { goto error; }
if ((err = mp_mod(&r, &key->q, &r)) != MP_OKAY) { goto error; }
if (mp_iszero(&r) == MP_YES) { goto retry; }
/* now find s = (in + xr)/k mod q */
if ((err = mp_read_unsigned_bin(&tmp, (unsigned char *)in, inlen)) != MP_OKAY) { goto error; }
if ((err = mp_mul(&key->x, &r, &s)) != MP_OKAY) { goto error; }
if ((err = mp_add(&s, &tmp, &s)) != MP_OKAY) { goto error; }
if ((err = mp_mulmod(&s, &kinv, &key->q, &s)) != MP_OKAY) { goto error; }
if (mp_iszero(&s) == MP_YES) { goto retry; }
/* now store em both */
/* first check that we have enough room */
if (*outlen < (unsigned long)(PACKET_SIZE + 4 + mp_unsigned_bin_size(&s) + mp_unsigned_bin_size(&r))) {
err = CRYPT_BUFFER_OVERFLOW;
goto done;
}
/* packet header */
packet_store_header(out, PACKET_SECT_DSA, PACKET_SUB_SIGNED);
y = PACKET_SIZE;
/* store length of r */
len = mp_unsigned_bin_size(&r);
out[y++] = (len>>8)&255;
out[y++] = (len & 255);
/* store r */
mp_to_unsigned_bin(&r, out+y);
y += len;
/* store length of s */
len = mp_unsigned_bin_size(&s);
out[y++] = (len>>8)&255;
out[y++] = (len & 255);
/* store s */
mp_to_unsigned_bin(&s, out+y);
y += len;
/* reset size */
*outlen = y;
err = CRYPT_OK;
goto done;
error : err = mpi_to_ltc_error(err);
done : mp_clear_multi(&k, &kinv, &r, &s, &tmp, NULL);
#ifdef CLEAN_STACK
zeromem(buf, sizeof(buf));
#endif
return err;
}
int dsa_verify_hash(const unsigned char *sig, unsigned long siglen,
const unsigned char *hash, unsigned long inlen,
int *stat, dsa_key *key)
{
mp_int r, s, w, v, u1, u2;
unsigned long x, y;
int err;
_ARGCHK(sig != NULL);
_ARGCHK(hash != NULL);
_ARGCHK(stat != NULL);
_ARGCHK(key != NULL);
/* default to invalid signature */
*stat = 0;
if (siglen < PACKET_SIZE+2+2) {
return CRYPT_INVALID_PACKET;
}
/* is the message format correct? */
if ((err = packet_valid_header((unsigned char *)sig, PACKET_SECT_DSA, PACKET_SUB_SIGNED)) != CRYPT_OK) {
return err;
}
/* skip over header */
y = PACKET_SIZE;
/* init our variables */
if ((err = mp_init_multi(&r, &s, &w, &v, &u1, &u2, NULL)) != MP_OKAY) {
return mpi_to_ltc_error(err);
}
/* read in r followed by s */
x = ((unsigned)sig[y]<<8)|((unsigned)sig[y+1]);
y += 2;
if (y + x > siglen) {
err = CRYPT_INVALID_PACKET;
goto done;
}
if ((err = mp_read_unsigned_bin(&r, (unsigned char *)sig+y, x)) != MP_OKAY) { goto error; }
y += x;
/* load s */
x = ((unsigned)sig[y]<<8)|((unsigned)sig[y+1]);
y += 2;
if (y + x > siglen) {
err = CRYPT_INVALID_PACKET;
goto done;
}
if ((err = mp_read_unsigned_bin(&s, (unsigned char *)sig+y, x)) != MP_OKAY) { goto error; }
/* w = 1/s mod q */
if ((err = mp_invmod(&s, &key->q, &w)) != MP_OKAY) { goto error; }
/* u1 = m * w mod q */
if ((err = mp_read_unsigned_bin(&u1, (unsigned char *)hash, inlen)) != MP_OKAY) { goto error; }
if ((err = mp_mulmod(&u1, &w, &key->q, &u1)) != MP_OKAY) { goto error; }
/* u2 = r*w mod q */
if ((err = mp_mulmod(&r, &w, &key->q, &u2)) != MP_OKAY) { goto error; }
/* v = g^u1 * y^u2 mod p mod q */
if ((err = mp_exptmod(&key->g, &u1, &key->p, &u1)) != MP_OKAY) { goto error; }
if ((err = mp_exptmod(&key->y, &u2, &key->p, &u2)) != MP_OKAY) { goto error; }
if ((err = mp_mulmod(&u1, &u2, &key->p, &v)) != MP_OKAY) { goto error; }
if ((err = mp_mod(&v, &key->q, &v)) != MP_OKAY) { goto error; }
/* if r = v then we're set */
if (mp_cmp(&r, &v) == MP_EQ) {
*stat = 1;
}
err = CRYPT_OK;
goto done;
error : err = mpi_to_ltc_error(err);
done : mp_clear_multi(&r, &s, &w, &v, &u1, &u2, NULL);
return err;
}
#define OUTPUT_BIGNUM(num, buf2, y, z) \
{ \
z = (unsigned long)mp_unsigned_bin_size(num); \
if ((y + 4 + z) > *outlen) { return CRYPT_BUFFER_OVERFLOW; } \
STORE32L(z, out+y); \
y += 4; \
if (mp_to_unsigned_bin(num, out+y) != MP_OKAY) { return CRYPT_MEM; } \
y += z; \
}
int dsa_export(unsigned char *out, unsigned long *outlen, int type, dsa_key *key)
{
unsigned long y, z;
_ARGCHK(out != NULL);
_ARGCHK(outlen != NULL);
_ARGCHK(key != NULL);
if (type == PK_PRIVATE && key->type != PK_PRIVATE) {
return CRYPT_PK_TYPE_MISMATCH;
}
if (type != PK_PUBLIC && type != PK_PRIVATE) {
return CRYPT_INVALID_ARG;
}
/* can we store the static header? */
if (*outlen < (PACKET_SIZE + 1 + 2)) {
return CRYPT_BUFFER_OVERFLOW;
}
/* store header */
packet_store_header(out, PACKET_SECT_DSA, PACKET_SUB_KEY);
y = PACKET_SIZE;
/* store g, p, q, qord */
out[y++] = type;
out[y++] = (key->qord>>8)&255;
out[y++] = key->qord & 255;
OUTPUT_BIGNUM(&key->g,out,y,z);
OUTPUT_BIGNUM(&key->p,out,y,z);
OUTPUT_BIGNUM(&key->q,out,y,z);
/* public exponent */
OUTPUT_BIGNUM(&key->y,out,y,z);
if (type == PK_PRIVATE) {
OUTPUT_BIGNUM(&key->x,out,y,z);
}
*outlen = y;
return CRYPT_OK;
}
#define INPUT_BIGNUM(num, in, x, y) \
{ \
/* load value */ \
if (y+4 > inlen) { \
err = CRYPT_INVALID_PACKET; \
goto error; \
} \
LOAD32L(x, in+y); \
y += 4; \
\
/* sanity check... */ \
if (y+x > inlen) { \
err = CRYPT_INVALID_PACKET; \
goto error; \
} \
\
/* load it */ \
if (mp_read_unsigned_bin(num, (unsigned char *)in+y, (int)x) != MP_OKAY) {\
err = CRYPT_MEM; \
goto error; \
} \
y += x; \
if (mp_shrink(num) != MP_OKAY) { \
err = CRYPT_MEM; \
goto error; \
} \
}
int dsa_import(const unsigned char *in, unsigned long inlen, dsa_key *key)
{
unsigned long x, y;
int err;
_ARGCHK(in != NULL);
_ARGCHK(key != NULL);
/* check length */
if ((1+2+PACKET_SIZE) > inlen) {
return CRYPT_INVALID_PACKET;
}
/* check type */
if ((err = packet_valid_header((unsigned char *)in, PACKET_SECT_DSA, PACKET_SUB_KEY)) != CRYPT_OK) {
return err;
}
y = PACKET_SIZE;
/* init key */
if (mp_init_multi(&key->p, &key->g, &key->q, &key->x, &key->y, NULL) != MP_OKAY) {
return CRYPT_MEM;
}
/* read type/qord */
key->type = in[y++];
key->qord = ((unsigned)in[y]<<8)|((unsigned)in[y+1]);
y += 2;
/* input publics */
INPUT_BIGNUM(&key->g,in,x,y);
INPUT_BIGNUM(&key->p,in,x,y);
INPUT_BIGNUM(&key->q,in,x,y);
INPUT_BIGNUM(&key->y,in,x,y);
if (key->type == PK_PRIVATE) {
INPUT_BIGNUM(&key->x,in,x,y);
}
return CRYPT_OK;
error:
mp_clear_multi(&key->p, &key->g, &key->q, &key->x, &key->y, NULL);
return err;
}
int dsa_verify_key(dsa_key *key, int *stat)
{
mp_int tmp, tmp2;
int res, err;
_ARGCHK(key != NULL);
_ARGCHK(stat != NULL);
*stat = 0;
/* first make sure key->q and key->p are prime */
if ((err = is_prime(&key->q, &res)) != CRYPT_OK) {
return err;
}
if (res == 0) {
return CRYPT_OK;
}
if ((err = is_prime(&key->p, &res)) != CRYPT_OK) {
return err;
}
if (res == 0) {
return CRYPT_OK;
}
/* now make sure that g is not -1, 0 or 1 and <p */
if (mp_cmp_d(&key->g, 0) == MP_EQ || mp_cmp_d(&key->g, 1) == MP_EQ) {
return CRYPT_OK;
}
if ((err = mp_init_multi(&tmp, &tmp2, NULL)) != MP_OKAY) { goto error; }
if ((err = mp_sub_d(&key->p, 1, &tmp)) != MP_OKAY) { goto error; }
if (mp_cmp(&tmp, &key->g) == MP_EQ || mp_cmp(&key->g, &key->p) != MP_LT) {
err = CRYPT_OK;
goto done;
}
/* 1 < y < p-1 */
if (!(mp_cmp_d(&key->y, 1) == MP_GT && mp_cmp(&key->y, &tmp) == MP_LT)) {
err = CRYPT_OK;
goto done;
}
/* now we have to make sure that g^q = 1, and that p-1/q gives 0 remainder */
if ((err = mp_div(&tmp, &key->q, &tmp, &tmp2)) != MP_OKAY) { goto error; }
if (mp_iszero(&tmp2) != MP_YES) {
err = CRYPT_OK;
goto done;
}
if ((err = mp_exptmod(&key->g, &key->q, &key->p, &tmp)) != MP_OKAY) { goto error; }
if (mp_cmp_d(&tmp, 1) != MP_EQ) {
err = CRYPT_OK;
goto done;
}
/* now we have to make sure that y^q = 1, this makes sure y \in g^x mod p */
if ((err = mp_exptmod(&key->y, &key->q, &key->p, &tmp)) != MP_OKAY) { goto error; }
if (mp_cmp_d(&tmp, 1) != MP_EQ) {
err = CRYPT_OK;
goto done;
}
/* at this point we are out of tests ;-( */
err = CRYPT_OK;
*stat = 1;
goto done;
error: err = mpi_to_ltc_error(err);
done : mp_clear_multi(&tmp, &tmp2, NULL);
return err;
}
#endif

98
ecc.c
View File

@ -250,39 +250,39 @@ static int dbl_point(ecc_point *P, ecc_point *R, mp_int *modulus, mp_int *mu)
mp_int s, tmp, tmpx;
int res;
if (mp_init_multi(&s, &tmp, &tmpx, NULL) != MP_OKAY) {
return CRYPT_MEM;
if ((res = mp_init_multi(&s, &tmp, &tmpx, NULL)) != MP_OKAY) {
return mpi_to_ltc_error(res);
}
/* s = (3Xp^2 + a) / (2Yp) */
if (mp_mul_2(&P->y, &tmp) != MP_OKAY) { goto error; } /* tmp = 2*y */
if (mp_invmod(&tmp, modulus, &tmp) != MP_OKAY) { goto error; } /* tmp = 1/tmp mod modulus */
if (mp_sqr(&P->x, &s) != MP_OKAY) { goto error; } /* s = x^2 */
if (mp_reduce(&s, modulus, mu) != MP_OKAY) { goto error; }
if (mp_mul_d(&s,(mp_digit)3, &s) != MP_OKAY) { goto error; } /* s = 3*(x^2) */
if (mp_sub_d(&s,(mp_digit)3, &s) != MP_OKAY) { goto error; } /* s = 3*(x^2) - 3 */
if ((res = mp_mul_2(&P->y, &tmp)) != MP_OKAY) { goto error; } /* tmp = 2*y */
if ((res = mp_invmod(&tmp, modulus, &tmp)) != MP_OKAY) { goto error; } /* tmp = 1/tmp mod modulus */
if ((res = mp_sqr(&P->x, &s)) != MP_OKAY) { goto error; } /* s = x^2 */
if ((res = mp_reduce(&s, modulus, mu)) != MP_OKAY) { goto error; }
if ((res = mp_mul_d(&s,(mp_digit)3, &s)) != MP_OKAY) { goto error; } /* s = 3*(x^2) */
if ((res = mp_sub_d(&s,(mp_digit)3, &s)) != MP_OKAY) { goto error; } /* s = 3*(x^2) - 3 */
if (mp_cmp_d(&s, 0) == MP_LT) { /* if s < 0 add modulus */
if (mp_add(&s, modulus, &s) != MP_OKAY) { goto error; }
if ((res = mp_add(&s, modulus, &s)) != MP_OKAY) { goto error; }
}
if (mp_mul(&s, &tmp, &s) != MP_OKAY) { goto error; } /* s = tmp * s mod modulus */
if (mp_reduce(&s, modulus, mu) != MP_OKAY) { goto error; }
if ((res = mp_mul(&s, &tmp, &s)) != MP_OKAY) { goto error; } /* s = tmp * s mod modulus */
if ((res = mp_reduce(&s, modulus, mu)) != MP_OKAY) { goto error; }
/* Xr = s^2 - 2Xp */
if (mp_sqr(&s, &tmpx) != MP_OKAY) { goto error; } /* tmpx = s^2 */
if (mp_reduce(&tmpx, modulus, mu) != MP_OKAY) { goto error; } /* tmpx = tmpx mod modulus */
if (mp_sub(&tmpx, &P->x, &tmpx) != MP_OKAY) { goto error; } /* tmpx = tmpx - x */
if (mp_submod(&tmpx, &P->x, modulus, &tmpx) != MP_OKAY) { goto error; } /* tmpx = tmpx - x mod modulus */
if ((res = mp_sqr(&s, &tmpx)) != MP_OKAY) { goto error; } /* tmpx = s^2 */
if ((res = mp_reduce(&tmpx, modulus, mu)) != MP_OKAY) { goto error; } /* tmpx = tmpx mod modulus */
if ((res = mp_sub(&tmpx, &P->x, &tmpx)) != MP_OKAY) { goto error; } /* tmpx = tmpx - x */
if ((res = mp_submod(&tmpx, &P->x, modulus, &tmpx)) != MP_OKAY) { goto error; } /* tmpx = tmpx - x mod modulus */
/* Yr = -Yp + s(Xp - Xr) */
if (mp_sub(&P->x, &tmpx, &tmp) != MP_OKAY) { goto error; } /* tmp = x - tmpx */
if (mp_mul(&tmp, &s, &tmp) != MP_OKAY) { goto error; } /* tmp = tmp * s */
if (mp_submod(&tmp, &P->y, modulus, &R->y) != MP_OKAY) { goto error; } /* y = tmp - y mod modulus */
if (mp_copy(&tmpx, &R->x) != MP_OKAY) { goto error; } /* x = tmpx */
if ((res = mp_sub(&P->x, &tmpx, &tmp)) != MP_OKAY) { goto error; } /* tmp = x - tmpx */
if ((res = mp_mul(&tmp, &s, &tmp)) != MP_OKAY) { goto error; } /* tmp = tmp * s */
if ((res = mp_submod(&tmp, &P->y, modulus, &R->y)) != MP_OKAY) { goto error; } /* y = tmp - y mod modulus */
if ((res = mp_copy(&tmpx, &R->x)) != MP_OKAY) { goto error; } /* x = tmpx */
res = CRYPT_OK;
goto done;
error:
res = CRYPT_MEM;
res = mpi_to_ltc_error(res);
done:
mp_clear_multi(&tmpx, &tmp, &s, NULL);
return res;
@ -294,14 +294,14 @@ static int add_point(ecc_point *P, ecc_point *Q, ecc_point *R, mp_int *modulus,
mp_int s, tmp, tmpx;
int res;
if (mp_init(&tmp) != MP_OKAY) {
return CRYPT_MEM;
if ((res = mp_init(&tmp)) != MP_OKAY) {
return mpi_to_ltc_error(res);
}
/* is P==Q or P==-Q? */
if (mp_neg(&Q->y, &tmp) != MP_OKAY || mp_mod(&tmp, modulus, &tmp) != MP_OKAY) {
if (((res = mp_neg(&Q->y, &tmp)) != MP_OKAY) || ((res = mp_mod(&tmp, modulus, &tmp)) != MP_OKAY)) {
mp_clear(&tmp);
return CRYPT_MEM;
return mpi_to_ltc_error(res);
}
if (mp_cmp(&P->x, &Q->x) == MP_EQ)
@ -310,40 +310,40 @@ static int add_point(ecc_point *P, ecc_point *Q, ecc_point *R, mp_int *modulus,
return dbl_point(P, R, modulus, mu);
}
if (mp_init_multi(&tmpx, &s, NULL) != MP_OKAY) {
if ((res = mp_init_multi(&tmpx, &s, NULL)) != MP_OKAY) {
mp_clear(&tmp);
return CRYPT_MEM;
return mpi_to_ltc_error(res);
}
/* get s = (Yp - Yq)/(Xp-Xq) mod p */
if (mp_sub(&P->x, &Q->x, &tmp) != MP_OKAY) { goto error; } /* tmp = Px - Qx mod modulus */
if ((res = mp_sub(&P->x, &Q->x, &tmp)) != MP_OKAY) { goto error; } /* tmp = Px - Qx mod modulus */
if (mp_cmp_d(&tmp, 0) == MP_LT) { /* if tmp<0 add modulus */
if (mp_add(&tmp, modulus, &tmp) != MP_OKAY) { goto error; }
if ((res = mp_add(&tmp, modulus, &tmp)) != MP_OKAY) { goto error; }
}
if (mp_invmod(&tmp, modulus, &tmp) != MP_OKAY) { goto error; } /* tmp = 1/tmp mod modulus */
if (mp_sub(&P->y, &Q->y, &s) != MP_OKAY) { goto error; } /* s = Py - Qy mod modulus */
if ((res = mp_invmod(&tmp, modulus, &tmp)) != MP_OKAY) { goto error; } /* tmp = 1/tmp mod modulus */
if ((res = mp_sub(&P->y, &Q->y, &s)) != MP_OKAY) { goto error; } /* s = Py - Qy mod modulus */
if (mp_cmp_d(&s, 0) == MP_LT) { /* if s<0 add modulus */
if (mp_add(&s, modulus, &s) != MP_OKAY) { goto error; }
if ((res = mp_add(&s, modulus, &s)) != MP_OKAY) { goto error; }
}
if (mp_mul(&s, &tmp, &s) != MP_OKAY) { goto error; } /* s = s * tmp mod modulus */
if (mp_reduce(&s, modulus, mu) != MP_OKAY) { goto error; }
if ((res = mp_mul(&s, &tmp, &s)) != MP_OKAY) { goto error; } /* s = s * tmp mod modulus */
if ((res = mp_reduce(&s, modulus, mu)) != MP_OKAY) { goto error; }
/* Xr = s^2 - Xp - Xq */
if (mp_sqr(&s, &tmp) != MP_OKAY) { goto error; } /* tmp = s^2 mod modulus */
if (mp_reduce(&tmp, modulus, mu) != MP_OKAY) { goto error; }
if (mp_sub(&tmp, &P->x, &tmp) != MP_OKAY) { goto error; } /* tmp = tmp - Px */
if (mp_sub(&tmp, &Q->x, &tmpx) != MP_OKAY) { goto error; } /* tmpx = tmp - Qx */
if ((res = mp_sqr(&s, &tmp)) != MP_OKAY) { goto error; } /* tmp = s^2 mod modulus */
if ((res = mp_reduce(&tmp, modulus, mu)) != MP_OKAY) { goto error; }
if ((res = mp_sub(&tmp, &P->x, &tmp)) != MP_OKAY) { goto error; } /* tmp = tmp - Px */
if ((res = mp_sub(&tmp, &Q->x, &tmpx)) != MP_OKAY) { goto error; } /* tmpx = tmp - Qx */
/* Yr = -Yp + s(Xp - Xr) */
if (mp_sub(&P->x, &tmpx, &tmp) != MP_OKAY) { goto error; } /* tmp = Px - tmpx */
if (mp_mul(&tmp, &s, &tmp) != MP_OKAY) { goto error; } /* tmp = tmp * s */
if (mp_submod(&tmp, &P->y, modulus, &R->y) != MP_OKAY) { goto error; } /* Ry = tmp - Py mod modulus */
if (mp_mod(&tmpx, modulus, &R->x) != MP_OKAY) { goto error; } /* Rx = tmpx mod modulus */
if ((res = mp_sub(&P->x, &tmpx, &tmp)) != MP_OKAY) { goto error; } /* tmp = Px - tmpx */
if ((res = mp_mul(&tmp, &s, &tmp)) != MP_OKAY) { goto error; } /* tmp = tmp * s */
if ((res = mp_submod(&tmp, &P->y, modulus, &R->y)) != MP_OKAY) { goto error; } /* Ry = tmp - Py mod modulus */
if ((res = mp_mod(&tmpx, modulus, &R->x)) != MP_OKAY) { goto error; } /* Rx = tmpx mod modulus */
res = CRYPT_OK;
goto done;
error:
res = CRYPT_MEM;
res = mpi_to_ltc_error(res);
done:
mp_clear_multi(&s, &tmpx, &tmp, NULL);
return res;
@ -362,12 +362,12 @@ static int ecc_mulmod(mp_int *k, ecc_point *G, ecc_point *R, mp_int *modulus)
int first, bitbuf, bitcpy, bitcnt, mode, digidx;
/* init barrett reduction */
if (mp_init(&mu) != MP_OKAY) {
return CRYPT_MEM;
if ((res = mp_init(&mu)) != MP_OKAY) {
return mpi_to_ltc_error(res);
}
if (mp_reduce_setup(&mu, modulus) != MP_OKAY) {
if ((res = mp_reduce_setup(&mu, modulus)) != MP_OKAY) {
mp_clear(&mu);
return CRYPT_MEM;
return mpi_to_ltc_error(res);
}
/* alloc ram for window temps */
@ -748,7 +748,7 @@ done:
z = (unsigned long)mp_unsigned_bin_size(num); \
STORE32L(z, buf2+y); \
y += 4; \
(void)mp_to_unsigned_bin(num, buf2+y); \
if (mp_to_unsigned_bin(num, buf2+y) != MP_OKAY) { return CRYPT_MEM; } \
y += z; \
}
@ -771,12 +771,12 @@ done:
\
/* load it */ \
if (mp_read_unsigned_bin(num, (unsigned char *)in+y, (int)x) != MP_OKAY) {\
err = CRYPT_MEM; \
err = CRYPT_MEM; \
goto error; \
} \
y += x; \
if (mp_shrink(num) != MP_OKAY) { \
err = CRYPT_MEM; \
err = CRYPT_MEM; \
goto error; \
} \
}

View File

@ -56,11 +56,6 @@ int ecc_encrypt_key(const unsigned char *inkey, unsigned long keylen,
return err;
}
/* Encrypt the key */
for (x = 0; x < keylen; x++) {
skey[x] ^= inkey[x];
}
/* output header */
y = PACKET_SIZE;
@ -78,9 +73,9 @@ int ecc_encrypt_key(const unsigned char *inkey, unsigned long keylen,
STORE32L(keylen, out+y);
y += 4;
/* Store the encrypted key */
/* Encrypt/Store the encrypted key */
for (x = 0; x < keylen; x++, y++) {
out[y] = skey[x];
out[y] = skey[x] ^ inkey[x];
}
/* store header */
@ -324,7 +319,7 @@ int ecc_verify_hash(const unsigned char *sig, unsigned long siglen,
_ARGCHK(sig != NULL);
_ARGCHK(hash != NULL);
_ARGCHK(hash != NULL);
_ARGCHK(stat != NULL);
_ARGCHK(key != NULL);
/* default to invalid signature */

5
hash.c
View File

@ -82,7 +82,10 @@ int hash_file(int hash, const char *fname, unsigned char *dst, unsigned long *ou
}
err = hash_filehandle(hash, in, dst, outlen);
(void)fclose(in);
if (fclose(in) != 0) {
return CRYPT_ERROR;
}
return err;
#endif
}

37
hmac.c
View File

@ -45,7 +45,7 @@ int hmac_init(hmac_state *hmac, int hash, const unsigned char *key, unsigned lon
hmac->hash = hash;
// (1) make sure we have a large enough key
hmac->hashsize = hashsize = hash_descriptor[hash].hashsize;
hashsize = hash_descriptor[hash].hashsize;
if(keylen > HMAC_BLOCKSIZE) {
z = (unsigned long)sizeof(hmac->key);
if ((err = hash_memory(hash, key, keylen, hmac->key, &z)) != CRYPT_OK) {
@ -82,8 +82,7 @@ int hmac_process(hmac_state *hmac, const unsigned char *buf, unsigned long len)
if ((err = hash_is_valid(hmac->hash)) != CRYPT_OK) {
return err;
}
hash_descriptor[hmac->hash].process(&hmac->md, buf, len);
return CRYPT_OK;
return hash_descriptor[hmac->hash].process(&hmac->md, buf, len);
}
int hmac_done(hmac_state *hmac, unsigned char *hashOut, unsigned long *outlen)
@ -101,15 +100,13 @@ int hmac_done(hmac_state *hmac, unsigned char *hashOut, unsigned long *outlen)
return err;
}
/* ensure the output size is valid */
/* get the hash message digest size */
hashsize = hash_descriptor[hash].hashsize;
if (*outlen < hashsize) {
return CRYPT_BUFFER_OVERFLOW;
}
*outlen = hashsize;
// Get the hash of the first HMAC vector plus the data
hash_descriptor[hash].done(&hmac->md, isha);
if ((err = hash_descriptor[hash].done(&hmac->md, isha)) != CRYPT_OK) {
return err;
}
// Create the second HMAC vector vector for step (3)
for(i=0; i < HMAC_BLOCKSIZE; i++) {
@ -120,12 +117,18 @@ int hmac_done(hmac_state *hmac, unsigned char *hashOut, unsigned long *outlen)
hash_descriptor[hash].init(&hmac->md);
hash_descriptor[hash].process(&hmac->md, buf, HMAC_BLOCKSIZE);
hash_descriptor[hash].process(&hmac->md, isha, hashsize);
hash_descriptor[hash].done(&hmac->md, hashOut);
hash_descriptor[hash].done(&hmac->md, buf);
// copy to output
for (i = 0; i < hashsize && i < *outlen; i++) {
hashOut[i] = buf[i];
}
*outlen = i;
#ifdef CLEAN_STACK
zeromem(isha, sizeof(buf));
zeromem(buf, sizeof(isha));
zeromem(hmac->key, sizeof(hmac->key));
zeromem(hmac, sizeof(*hmac));
#endif
return CRYPT_OK;
}
@ -193,12 +196,16 @@ int hmac_file(int hash, const char *fname, const unsigned char *key,
/* process the file contents */
do {
x = fread(buf, 1, sizeof(buf), in);
if ((err = hmac_process(&hmac, buf, (unsigned long)x)) != CRYPT_OK) {
(void)fclose(in);
if ((err = hmac_process(&hmac, buf, (unsigned long)x)) != CRYPT_OK) {
/* we don't trap this error since we're already returning an error! */
fclose(in);
return err;
}
} while (x == sizeof(buf));
(void)fclose(in);
if (fclose(in) != 0) {
return CRYPT_ERROR;
}
/* get final hmac */
if ((err = hmac_done(&hmac, dst, dstlen)) != CRYPT_OK) {
@ -235,7 +242,7 @@ int hmac_test(void)
unsigned char digest[MAXBLOCKSIZE];
int i;
struct hmac_test_case {
static const struct hmac_test_case {
int num;
char *algo;
unsigned char key[128];

View File

@ -9,16 +9,16 @@
# a build. This is easy to remedy though, for those that have problems.
# The version
VERSION=0.91
VERSION=0.92
#ch1-01-1
# Compiler and Linker Names
CC=gcc
LD=ld
#CC=gcc
#LD=ld
# Archiver [makes .a files]
AR=ar
ARFLAGS=r
#AR=ar
#ARFLAGS=r
#ch1-01-1
#ch1-01-3
@ -66,7 +66,7 @@ OBJECTS=keyring.o gf.o mem.o sprng.o ecc.o base64.o dh.o rsa.o \
bits.o yarrow.o cfb.o ofb.o ecb.o ctr.o cbc.o hash.o tiger.o sha1.o \
md5.o md4.o md2.o sha256.o sha512.o xtea.o aes.o des.o \
safer_tab.o safer.o safer+.o rc4.o rc2.o rc6.o rc5.o cast5.o noekeon.o blowfish.o crypt.o \
prime.o twofish.o packet.o hmac.o strings.o rmd128.o rmd160.o $(MPIOBJECT)
prime.o twofish.o packet.o hmac.o strings.o rmd128.o rmd160.o skipjack.o omac.o dsa.o $(MPIOBJECT)
TESTOBJECTS=demos/test.o
HASHOBJECTS=demos/hashsum.o
@ -94,7 +94,9 @@ rsa.o: rsa.c rsa_sys.c
ecc.o: ecc.c ecc_sys.c
dh.o: dh.c dh_sys.c
aes.o: aes.c aes_tab.c
twofish.o: twofish.c twofish_tab.c
sha512.o: sha512.c sha384.c
sha256.o: sha256.c sha224.c
#This rule makes the libtomcrypt library.
library: $(LIBNAME)
@ -140,7 +142,7 @@ install: library docs
clean:
rm -f $(OBJECTS) $(TESTOBJECTS) $(HASHOBJECTS) $(CRYPTOBJECTS) $(SMALLOBJECTS) $(LEFTOVERS) $(LIBNAME)
rm -f $(TEST) $(HASH) $(COMPRESSED) $(PROFS) $(PROF) $(TVS) $(TV)
rm -f *stackdump *.lib *.exe *.obj demos/*.obj demos/*.o *.bat hash_tv.txt cipher_tv.txt
rm -f *.a *.dll *stackdump *.lib *.exe *.obj demos/*.obj demos/*.o *.bat *.txt
#This builds the crypt.pdf file. Note that the rm -f *.pdf has been removed
#from the clean command! This is because most people would like to keep the

32
makefile.cygwin_dll Normal file
View File

@ -0,0 +1,32 @@
default: ltc_dll
# Compilation flags. Note the += does not write over the user's CFLAGS!
CFLAGS += -I./ -Wall -Wsign-compare -W -Wno-unused -Wshadow -Werror -mno-cygwin -DWIN32
# optimize for SPEED
#CFLAGS += -O3 -funroll-loops
#add -fomit-frame-pointer. v3.2 is buggy for certain platforms!
#CFLAGS += -fomit-frame-pointer
# optimize for SIZE
CFLAGS += -Os
#Leave MPI built-in or force developer to link against libtommath?
MPIOBJECT=mpi.o
OBJECTS=keyring.o gf.o mem.o sprng.o ecc.o base64.o dh.o rsa.o \
bits.o yarrow.o cfb.o ofb.o ecb.o ctr.o cbc.o hash.o tiger.o sha1.o \
md5.o md4.o md2.o sha256.o sha512.o xtea.o aes.o des.o \
safer_tab.o safer.o safer+.o rc4.o rc2.o rc6.o rc5.o cast5.o noekeon.o blowfish.o crypt.o \
prime.o twofish.o packet.o hmac.o strings.o rmd128.o rmd160.o skipjack.o omac.o dsa.o $(MPIOBJECT)
ltc_dll: $(OBJECTS) $(MPIOBJECT)
gcc -mno-cygwin -mdll -o libtomcrypt.dll -Wl,--out-implib=libtomcrypt.dll.a -Wl,--export-all-symbols *.o -ladvapi32
ranlib libtomcrypt.dll.a
test: ltc_dll
gcc $(CFLAGS) demos/test.c libtomcrypt.dll.a -Wl,--enable-auto-import -o test -s

View File

@ -10,7 +10,8 @@ OBJECTS=keyring.obj gf.obj mem.obj sprng.obj ecc.obj base64.obj dh.obj rsa.obj \
bits.obj yarrow.obj cfb.obj ofb.obj ecb.obj ctr.obj cbc.obj hash.obj tiger.obj sha1.obj \
md5.obj md4.obj md2.obj sha256.obj sha512.obj xtea.obj aes.obj des.obj \
safer_tab.obj safer.obj safer+.obj rc4.obj rc2.obj rc6.obj rc5.obj cast5.obj noekeon.obj \
blowfish.obj crypt.obj mpi.obj prime.obj twofish.obj packet.obj hmac.obj strings.obj rmd128.obj rmd160.obj
blowfish.obj crypt.obj mpi.obj prime.obj twofish.obj packet.obj hmac.obj strings.obj rmd128.obj rmd160.obj \
skipjack.obj omac.obj dsa.obj
library: $(OBJECTS)
lib /out:tomcrypt.lib $(OBJECTS)
@ -28,4 +29,4 @@ tv_gen: demos/tv_gen.c library
cl $(CFLAGS) demos/tv_gen.c tomcrypt.lib advapi32.lib
hashsum: demos/hashsum.c library
cl $(CFLAGS) demos/hashsum.c tomcrypt.lib advapi32.lib
cl $(CFLAGS) demos/hashsum.c tomcrypt.lib advapi32.lib

View File

@ -9,11 +9,15 @@ CFLAGS += -Os -Wall -Wsign-compare -W -Wno-unused -Werror -I./
default: library
OBJECTS = keyring.o gf.o mem.o sprng.o ecc.o base64.o dh.o rsa.o bits.o yarrow.o cfb.o ofb.o ecb.o ctr.o cbc.o hash.o tiger.o sha1.o md5.o md4.o md2.o sha256.o sha512.o xtea.o aes.o des.o safer_tab.o safer.o safer+.o rc4.o rc2.o rc6.o rc5.o cast5.o noekeon.o blowfish.o crypt.o mpi.o prime.o twofish.o packet.o hmac.o strings.o
OBJECTS = keyring.o gf.o mem.o sprng.o ecc.o base64.o dh.o rsa.o bits.o yarrow.o cfb.o ofb.o ecb.o ctr.o cbc.o hash.o tiger.o sha1.o md5.o md4.o md2.o sha256.o sha512.o xtea.o aes.o des.o safer_tab.o safer.o safer+.o rc4.o rc2.o rc6.o rc5.o cast5.o noekeon.o blowfish.o crypt.o mpi.o prime.o twofish.o packet.o hmac.o strings.o rmd128.o rmd160.o skipjack.o omac.o dsa.o
rsa.o: rsa_sys.c
dh.o: dh_sys.c
ecc.o: ecc_sys.c
aes.o: aes.c aes_tab.c
twofish.o: twofish.c twofish_tab.c
sha512.o: sha384.c sha512.c
sha256.o: sha256.c sha224.c
library: $(OBJECTS)
$(AR) r libtomcrypt.a $(OBJECTS)

18
md2.c
View File

@ -47,7 +47,7 @@ static void md2_update_chksum(hash_state *md)
/* caution, the RFC says its "C[j] = S[M[i*16+j] xor L]" but the reference source code [and test vectors] say
otherwise.
*/
L = (md->md2.chksum[j] ^= PI_SUBST[(int)(md->md2.buf[j] ^ L)]);
L = (md->md2.chksum[j] ^= PI_SUBST[(int)(md->md2.buf[j] ^ L)] & 255);
}
}
@ -67,7 +67,7 @@ static void md2_compress(hash_state *md)
/* do 18 rounds */
for (j = 0; j < 18; j++) {
for (k = 0; k < 48; k++) {
t = (md->md2.X[k] ^= PI_SUBST[(int)t]);
t = (md->md2.X[k] ^= PI_SUBST[(int)(t & 255)]);
}
t = (t + (unsigned char)j) & 255;
}
@ -84,11 +84,14 @@ void md2_init(hash_state *md)
md->md2.curlen = 0;
}
void md2_process(hash_state *md, const unsigned char *buf, unsigned long len)
int md2_process(hash_state *md, const unsigned char *buf, unsigned long len)
{
unsigned long n;
_ARGCHK(md != NULL);
_ARGCHK(buf != NULL);
if (md-> md2 .curlen > sizeof(md-> md2 .buf)) {
return CRYPT_INVALID_ARG;
}
while (len > 0) {
n = MIN(len, (16 - md->md2.curlen));
memcpy(md->md2.buf + md->md2.curlen, buf, (size_t)n);
@ -103,15 +106,21 @@ void md2_process(hash_state *md, const unsigned char *buf, unsigned long len)
md->md2.curlen = 0;
}
}
return CRYPT_OK;
}
void md2_done(hash_state * md, unsigned char *hash)
int md2_done(hash_state * md, unsigned char *hash)
{
unsigned long i, k;
_ARGCHK(md != NULL);
_ARGCHK(hash != NULL);
if (md->md2.curlen >= sizeof(md->md2.buf)) {
return CRYPT_INVALID_ARG;
}
/* pad the message */
k = 16 - md->md2.curlen;
for (i = md->md2.curlen; i < 16; i++) {
@ -132,6 +141,7 @@ void md2_done(hash_state * md, unsigned char *hash)
#ifdef CLEAN_STACK
zeromem(md, sizeof(hash_state));
#endif
return CRYPT_OK;
}
int md2_test(void)

50
md4.c
View File

@ -53,12 +53,12 @@ const struct _hash_descriptor md4_desc =
}
#ifdef CLEAN_STACK
static void _md4_compress(hash_state *md)
static void _md4_compress(hash_state *md, unsigned char *buf)
#else
static void md4_compress(hash_state *md)
static void md4_compress(hash_state *md, unsigned char *buf)
#endif
{
unsigned long x[16], a, b, c, d;
ulong32 x[16], a, b, c, d;
int i;
_ARGCHK(md != NULL);
@ -71,7 +71,7 @@ static void md4_compress(hash_state *md)
/* copy the state into 512-bits into W[0..15] */
for (i = 0; i < 16; i++) {
LOAD32L(x[i], md->md4.buf + (4*i));
LOAD32L(x[i], buf + (4*i));
}
/* Round 1 */
@ -137,10 +137,10 @@ static void md4_compress(hash_state *md)
}
#ifdef CLEAN_STACK
static void md4_compress(hash_state *md)
static void md4_compress(hash_state *md, unsigned char *buf)
{
_md4_compress(md);
burn_stack(sizeof(unsigned long) * 20 + sizeof(int));
_md4_compress(md, buf);
burn_stack(sizeof(ulong32) * 20 + sizeof(int));
}
#endif
@ -152,37 +152,22 @@ void md4_init(hash_state * md)
md->md4.state[2] = 0x98badcfeUL;
md->md4.state[3] = 0x10325476UL;
md->md4.length = 0;
md->md4.curlen = 0;
md->md4.curlen = 0;
}
void md4_process(hash_state * md, const unsigned char *buf, unsigned long len)
{
unsigned long n;
_ARGCHK(md != NULL);
_ARGCHK(buf != NULL);
while (len > 0) {
n = MIN(len, (64 - md->md4.curlen));
memcpy(md->md4.buf + md->md4.curlen, buf, (size_t)n);
md->md4.curlen += n;
buf += n;
len -= n;
HASH_PROCESS(md4_process, md4_compress, md4, 64)
/* is 64 bytes full? */
if (md->md4.curlen == 64) {
md4_compress(md);
md->md4.length += 512;
md->md4.curlen = 0;
}
}
}
void md4_done(hash_state * md, unsigned char *hash)
int md4_done(hash_state * md, unsigned char *hash)
{
int i;
_ARGCHK(md != NULL);
_ARGCHK(hash != NULL);
if (md->md4.curlen >= sizeof(md->md4.buf)) {
return CRYPT_INVALID_ARG;
}
/* increase the length of the message */
md->md4.length += md->md4.curlen * 8;
@ -197,7 +182,7 @@ void md4_done(hash_state * md, unsigned char *hash)
while (md->md4.curlen < 64) {
md->md4.buf[md->md4.curlen++] = (unsigned char)0;
}
md4_compress(md);
md4_compress(md, md->md4.buf);
md->md4.curlen = 0;
}
@ -208,7 +193,7 @@ void md4_done(hash_state * md, unsigned char *hash)
/* store length */
STORE64L(md->md4.length, md->md4.buf+56);
md4_compress(md);
md4_compress(md, md->md4.buf);
/* copy output */
for (i = 0; i < 4; i++) {
@ -216,7 +201,8 @@ void md4_done(hash_state * md, unsigned char *hash)
}
#ifdef CLEAN_STACK
zeromem(md, sizeof(hash_state));
#endif
#endif
return CRYPT_OK;
}
int md4_test(void)

47
md5.c
View File

@ -32,18 +32,18 @@ const struct _hash_descriptor md5_desc =
a = (a + I(b,c,d) + M + t); a = ROL(a, s) + b;
#ifdef CLEAN_STACK
static void _md5_compress(hash_state *md)
static void _md5_compress(hash_state *md, unsigned char *buf)
#else
static void md5_compress(hash_state *md)
static void md5_compress(hash_state *md, unsigned char *buf)
#endif
{
unsigned long i, W[16], a, b, c, d;
ulong32 i, W[16], a, b, c, d;
_ARGCHK(md != NULL);
/* copy the state into 512-bits into W[0..15] */
for (i = 0; i < 16; i++) {
LOAD32L(W[i], md->md5.buf + (4*i));
LOAD32L(W[i], buf + (4*i));
}
/* copy state */
@ -124,10 +124,10 @@ static void md5_compress(hash_state *md)
}
#ifdef CLEAN_STACK
static void md5_compress(hash_state *md)
static void md5_compress(hash_state *md, unsigned char *buf)
{
_md5_compress(md);
burn_stack(sizeof(unsigned long) * 21);
_md5_compress(md, buf);
burn_stack(sizeof(ulong32) * 21);
}
#endif
@ -142,34 +142,20 @@ void md5_init(hash_state * md)
md->md5.length = 0;
}
void md5_process(hash_state * md, const unsigned char *buf, unsigned long len)
{
unsigned long n;
_ARGCHK(md != NULL);
_ARGCHK(buf != NULL);
while (len > 0) {
n = MIN(len, (64 - md->md5.curlen));
memcpy(md->md5.buf + md->md5.curlen, buf, (size_t)n);
md->md5.curlen += n;
buf += n;
len -= n;
HASH_PROCESS(md5_process, md5_compress, md5, 64)
/* is 64 bytes full? */
if (md->md5.curlen == 64) {
md5_compress(md);
md->md5.length += 512;
md->md5.curlen = 0;
}
}
}
void md5_done(hash_state * md, unsigned char *hash)
int md5_done(hash_state * md, unsigned char *hash)
{
int i;
_ARGCHK(md != NULL);
_ARGCHK(hash != NULL);
if (md->md5.curlen >= sizeof(md->md5.buf)) {
return CRYPT_INVALID_ARG;
}
/* increase the length of the message */
md->md5.length += md->md5.curlen * 8;
@ -184,7 +170,7 @@ void md5_done(hash_state * md, unsigned char *hash)
while (md->md5.curlen < 64) {
md->md5.buf[md->md5.curlen++] = (unsigned char)0;
}
md5_compress(md);
md5_compress(md, md->md5.buf);
md->md5.curlen = 0;
}
@ -195,7 +181,7 @@ void md5_done(hash_state * md, unsigned char *hash)
/* store length */
STORE64L(md->md5.length, md->md5.buf+56);
md5_compress(md);
md5_compress(md, md->md5.buf);
/* copy output */
for (i = 0; i < 4; i++) {
@ -204,6 +190,7 @@ void md5_done(hash_state * md, unsigned char *hash)
#ifdef CLEAN_STACK
zeromem(md, sizeof(hash_state));
#endif
return CRYPT_OK;
}
int md5_test(void)

759
mpi.c

File diff suppressed because it is too large Load Diff

View File

@ -16,8 +16,8 @@ extern "C" {
#endif
/* version */
#define CRYPT 0x0091
#define SCRYPT "0.91"
#define CRYPT 0x0092
#define SCRYPT "0.92"
/* max size of either a cipher/hash block or symmetric key [largest of the two] */
#define MAXBLOCKSIZE 128

View File

@ -48,12 +48,6 @@ extern clock_t XCLOCK(void);
#define ENDIAN_NEUTRAL
#endif
#ifdef SHA384
#ifndef SHA512
#error The SHA384 hash requires SHA512 to be defined!
#endif
#endif
#ifdef YARROW
#ifndef CTR
#error YARROW requires CTR chaining mode to be defined!
@ -71,7 +65,7 @@ extern clock_t XCLOCK(void);
#define PACKET_SECT_RSA 0
#define PACKET_SECT_DH 1
#define PACKET_SECT_ECC 2
#define PACKET_SECT_DSA 4
#define PACKET_SECT_DSA 3
/* Subsection Tags for the first three sections */
#define PACKET_SUB_KEY 0

View File

@ -95,6 +95,12 @@ struct noekeon_key {
};
#endif
#ifdef SKIPJACK
struct skipjack_key {
unsigned char key[10];
};
#endif
typedef union Symmetric_key {
#ifdef DES
struct des_key des;
@ -133,6 +139,9 @@ typedef union Symmetric_key {
#ifdef NOEKEON
struct noekeon_key noekeon;
#endif
#ifdef SKIPJACK
struct skipjack_key skipjack;
#endif
} symmetric_key;
/* A block cipher ECB structure */
@ -312,6 +321,15 @@ extern int noekeon_keysize(int *desired_keysize);
extern const struct _cipher_descriptor noekeon_desc;
#endif
#ifdef SKIPJACK
extern int skipjack_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
extern void skipjack_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *key);
extern void skipjack_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *key);
extern int skipjack_test(void);
extern int skipjack_keysize(int *desired_keysize);
extern const struct _cipher_descriptor skipjack_desc;
#endif
#ifdef ECB
extern int ecb_start(int cipher, const unsigned char *key,
int keylen, int num_rounds, symmetric_ECB *ecb);

View File

@ -16,7 +16,6 @@
#define XCLOCK clock
#define XCLOCKS_PER_SEC CLOCKS_PER_SEC
#define SMALL_CODE
#define CLEAN_STACK
#define LTC_TEST
#define BLOWFISH
#define RC2
@ -31,6 +30,7 @@
#define DES
#define CAST5
#define NOEKEON
#define SKIPJACK
#define CFB
#define OFB
#define ECB
@ -39,6 +39,7 @@
#define SHA512
#define SHA384
#define SHA256
#define SHA224
#define TIGER
#define SHA1
#define MD5
@ -47,12 +48,14 @@
#define RIPEMD128
#define RIPEMD160
#define HMAC
#define OMAC
#define BASE64
#define YARROW
#define SPRNG
#define RC4
#define DEVRANDOM
#define MRSA
#define MDSA
#define MDH
#define MECC
#define DH768

View File

@ -10,7 +10,7 @@ struct sha512_state {
#ifdef SHA256
struct sha256_state {
ulong64 length;
unsigned long state[8], curlen;
ulong32 state[8], curlen;
unsigned char buf[64];
};
#endif
@ -18,7 +18,7 @@ struct sha256_state {
#ifdef SHA1
struct sha1_state {
ulong64 length;
unsigned long state[5], curlen;
ulong32 state[5], curlen;
unsigned char buf[64];
};
#endif
@ -26,7 +26,7 @@ struct sha1_state {
#ifdef MD5
struct md5_state {
ulong64 length;
unsigned long state[4], curlen;
ulong32 state[4], curlen;
unsigned char buf[64];
};
#endif
@ -34,7 +34,7 @@ struct md5_state {
#ifdef MD4
struct md4_state {
ulong64 length;
unsigned long state[4], curlen;
ulong32 state[4], curlen;
unsigned char buf[64];
};
#endif
@ -58,7 +58,7 @@ struct md2_state {
struct rmd128_state {
ulong64 length;
unsigned char buf[64];
unsigned long curlen, state[4];
ulong32 curlen, state[4];
};
#endif
@ -66,7 +66,7 @@ struct rmd128_state {
struct rmd160_state {
ulong64 length;
unsigned char buf[64];
unsigned long curlen, state[5];
ulong32 curlen, state[5];
};
#endif
@ -106,87 +106,101 @@ extern struct _hash_descriptor {
unsigned long hashsize; /* digest output size in bytes */
unsigned long blocksize; /* the block size the hash uses */
void (*init)(hash_state *);
void (*process)(hash_state *, const unsigned char *, unsigned long);
void (*done)(hash_state *, unsigned char *);
int (*process)(hash_state *, const unsigned char *, unsigned long);
int (*done)(hash_state *, unsigned char *);
int (*test)(void);
} hash_descriptor[];
#ifdef SHA512
extern void sha512_init(hash_state * md);
extern void sha512_process(hash_state * md, const unsigned char *buf, unsigned long len);
extern void sha512_done(hash_state * md, unsigned char *hash);
extern int sha512_process(hash_state * md, const unsigned char *buf, unsigned long len);
extern int sha512_done(hash_state * md, unsigned char *hash);
extern int sha512_test(void);
extern const struct _hash_descriptor sha512_desc;
#endif
#ifdef SHA384
#ifndef SHA512
#error SHA512 is required for SHA384
#endif
extern void sha384_init(hash_state * md);
extern void sha384_process(hash_state * md, const unsigned char *buf, unsigned long len);
extern void sha384_done(hash_state * md, unsigned char *hash);
#define sha384_process sha512_process
extern int sha384_done(hash_state * md, unsigned char *hash);
extern int sha384_test(void);
extern const struct _hash_descriptor sha384_desc;
#endif
#ifdef SHA256
extern void sha256_init(hash_state * md);
extern void sha256_process(hash_state * md, const unsigned char *buf, unsigned long len);
extern void sha256_done(hash_state * md, unsigned char *hash);
extern int sha256_process(hash_state * md, const unsigned char *buf, unsigned long len);
extern int sha256_done(hash_state * md, unsigned char *hash);
extern int sha256_test(void);
extern const struct _hash_descriptor sha256_desc;
#ifdef SHA224
#ifndef SHA256
#error SHA256 is required for SHA224
#endif
extern void sha224_init(hash_state * md);
#define sha224_process sha256_process
extern int sha224_done(hash_state * md, unsigned char *hash);
extern int sha224_test(void);
extern const struct _hash_descriptor sha224_desc;
#endif
#endif
#ifdef SHA1
extern void sha1_init(hash_state * md);
extern void sha1_process(hash_state * md, const unsigned char *buf, unsigned long len);
extern void sha1_done(hash_state * md, unsigned char *hash);
extern int sha1_process(hash_state * md, const unsigned char *buf, unsigned long len);
extern int sha1_done(hash_state * md, unsigned char *hash);
extern int sha1_test(void);
extern const struct _hash_descriptor sha1_desc;
#endif
#ifdef MD5
extern void md5_init(hash_state * md);
extern void md5_process(hash_state * md, const unsigned char *buf, unsigned long len);
extern void md5_done(hash_state * md, unsigned char *hash);
extern int md5_process(hash_state * md, const unsigned char *buf, unsigned long len);
extern int md5_done(hash_state * md, unsigned char *hash);
extern int md5_test(void);
extern const struct _hash_descriptor md5_desc;
#endif
#ifdef MD4
extern void md4_init(hash_state * md);
extern void md4_process(hash_state * md, const unsigned char *buf, unsigned long len);
extern void md4_done(hash_state * md, unsigned char *hash);
extern int md4_process(hash_state * md, const unsigned char *buf, unsigned long len);
extern int md4_done(hash_state * md, unsigned char *hash);
extern int md4_test(void);
extern const struct _hash_descriptor md4_desc;
#endif
#ifdef MD2
extern void md2_init(hash_state * md);
extern void md2_process(hash_state * md, const unsigned char *buf, unsigned long len);
extern void md2_done(hash_state * md, unsigned char *hash);
extern int md2_process(hash_state * md, const unsigned char *buf, unsigned long len);
extern int md2_done(hash_state * md, unsigned char *hash);
extern int md2_test(void);
extern const struct _hash_descriptor md2_desc;
#endif
#ifdef TIGER
extern void tiger_init(hash_state * md);
extern void tiger_process(hash_state * md, const unsigned char *buf, unsigned long len);
extern void tiger_done(hash_state * md, unsigned char *hash);
extern int tiger_process(hash_state * md, const unsigned char *buf, unsigned long len);
extern int tiger_done(hash_state * md, unsigned char *hash);
extern int tiger_test(void);
extern const struct _hash_descriptor tiger_desc;
#endif
#ifdef RIPEMD128
extern void rmd128_init(hash_state * md);
extern void rmd128_process(hash_state * md, const unsigned char *buf, unsigned long len);
extern void rmd128_done(hash_state * md, unsigned char *hash);
extern int rmd128_process(hash_state * md, const unsigned char *buf, unsigned long len);
extern int rmd128_done(hash_state * md, unsigned char *hash);
extern int rmd128_test(void);
extern const struct _hash_descriptor rmd128_desc;
#endif
#ifdef RIPEMD160
extern void rmd160_init(hash_state * md);
extern void rmd160_process(hash_state * md, const unsigned char *buf, unsigned long len);
extern void rmd160_done(hash_state * md, unsigned char *hash);
extern int rmd160_process(hash_state * md, const unsigned char *buf, unsigned long len);
extern int rmd160_done(hash_state * md, unsigned char *hash);
extern int rmd160_test(void);
extern const struct _hash_descriptor rmd160_desc;
#endif
@ -202,13 +216,44 @@ extern int hash_memory(int hash, const unsigned char *data, unsigned long len, u
extern int hash_filehandle(int hash, FILE *in, unsigned char *dst, unsigned long *outlen);
extern int hash_file(int hash, const char *fname, unsigned char *dst, unsigned long *outlen);
/* a simple macro for making hash "process" functions */
#define HASH_PROCESS(func_name, compress_name, state_var, block_size) \
int func_name (hash_state * md, const unsigned char *buf, unsigned long len) \
{ \
unsigned long n; \
_ARGCHK(md != NULL); \
_ARGCHK(buf != NULL); \
if (md-> state_var .curlen > sizeof(md-> state_var .buf)) { \
return CRYPT_INVALID_ARG; \
} \
while (len > 0) { \
if (md-> state_var .curlen == 0 && len >= block_size) { \
compress_name (md, (unsigned char *)buf); \
md-> state_var .length += block_size * 8; \
buf += block_size; \
len -= block_size; \
} else { \
n = MIN(len, (block_size - md-> state_var .curlen)); \
memcpy(md-> state_var .buf + md-> state_var.curlen, buf, (size_t)n); \
md-> state_var .curlen += n; \
buf += n; \
len -= n; \
if (md-> state_var .curlen == block_size) { \
compress_name (md, md-> state_var .buf); \
md-> state_var .length += 8*block_size; \
md-> state_var .curlen = 0; \
} \
} \
} \
return CRYPT_OK; \
}
#ifdef HMAC
typedef struct Hmac_state {
hash_state md;
int hash;
unsigned long hashsize; /* here for your reference */
hash_state hashstate;
unsigned char key[MAXBLOCKSIZE];
hash_state md;
int hash;
hash_state hashstate;
unsigned char key[MAXBLOCKSIZE];
} hmac_state;
extern int hmac_init(hmac_state *hmac, int hash, const unsigned char *key, unsigned long keylen);
@ -222,3 +267,27 @@ extern int hmac_file(int hash, const char *fname, const unsigned char *key,
unsigned long keylen,
unsigned char *dst, unsigned long *dstlen);
#endif
#ifdef OMAC
typedef struct {
int cipher_idx,
buflen,
blklen;
unsigned char block[MAXBLOCKSIZE],
prev[MAXBLOCKSIZE],
Lu[2][MAXBLOCKSIZE];
symmetric_key key;
} omac_state;
extern int omac_init(omac_state *omac, int cipher, const unsigned char *key, unsigned long keylen);
extern int omac_process(omac_state *state, const unsigned char *buf, unsigned long len);
extern int omac_done(omac_state *state, unsigned char *out, unsigned long *outlen);
extern int omac_memory(int cipher, const unsigned char *key, unsigned long keylen,
const unsigned char *msg, unsigned long msglen,
unsigned char *out, unsigned long *outlen);
extern int omac_file(int cipher, const unsigned char *key, unsigned long keylen,
const char *filename, unsigned char *out, unsigned long *outlen);
extern int omac_test(void);
#endif

View File

@ -11,8 +11,7 @@ extern int base64_decode(const unsigned char *in, unsigned long len,
extern void zeromem(void *dst, size_t len);
extern void burn_stack(unsigned long len);
/* ch1-01-1*/
extern const char *error_to_string(int err);
/* ch1-01-1*/
extern int mpi_to_ltc_error(int err);
extern const char *crypt_build_settings;

View File

@ -170,3 +170,29 @@ extern int ecc_verify_hash(const unsigned char *sig, unsigned long siglen,
const unsigned char *hash, unsigned long hashlen,
int *stat, ecc_key *key);
#endif
#ifdef MDSA
typedef struct {
int type, qord;
mp_int g, q, p, x, y;
} dsa_key;
extern int dsa_make_key(prng_state *prng, int wprng, int group_size, int modulus_size, dsa_key *key);
extern void dsa_free(dsa_key *key);
extern int dsa_sign_hash(const unsigned char *in, unsigned long inlen,
unsigned char *out, unsigned long *outlen,
prng_state *prng, int wprng, dsa_key *key);
extern int dsa_verify_hash(const unsigned char *sig, unsigned long siglen,
const unsigned char *hash, unsigned long inlen,
int *stat, dsa_key *key);
extern int dsa_import(const unsigned char *in, unsigned long inlen, dsa_key *key);
extern int dsa_export(unsigned char *out, unsigned long *outlen, int type, dsa_key *key);
extern int dsa_verify_key(dsa_key *key, int *stat);
#endif

141
noekeon.c
View File

@ -24,7 +24,7 @@ static const ulong32 RC[] = {
};
#define kTHETA(a, b, c, d) \
#define kTHETA(a, b, c, d) \
temp = a^c; temp = temp ^ ROL(temp, 8) ^ ROR(temp, 8); \
b ^= temp; d ^= temp; \
temp = b^d; temp = temp ^ ROL(temp, 8) ^ ROR(temp, 8); \
@ -32,11 +32,9 @@ static const ulong32 RC[] = {
#define THETA(k, a, b, c, d) \
temp = a^c; temp = temp ^ ROL(temp, 8) ^ ROR(temp, 8); \
b ^= temp; d ^= temp; \
a ^= k[0]; b ^= k[1]; \
c ^= k[2]; d ^= k[3]; \
b ^= temp ^ k[1]; d ^= temp ^ k[3]; \
temp = b^d; temp = temp ^ ROL(temp, 8) ^ ROR(temp, 8); \
a ^= temp; c ^= temp;
a ^= temp ^ k[0]; c ^= temp ^ k[2];
#define GAMMA(a, b, c, d) \
b ^= ~(d|c); \
@ -89,7 +87,9 @@ void noekeon_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_k
#endif
{
ulong32 a,b,c,d,temp;
#ifdef SMALL_CODE
int r;
#endif
_ARGCHK(key != NULL);
_ARGCHK(pt != NULL);
@ -98,17 +98,32 @@ void noekeon_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_k
LOAD32L(a,&pt[0]); LOAD32L(b,&pt[4]);
LOAD32L(c,&pt[8]); LOAD32L(d,&pt[12]);
#define ROUND(i) \
a ^= RC[r+i]; \
#ifdef SMALL_CODE
#define ROUND \
a ^= RC[r]; \
THETA(key->noekeon.K, a,b,c,d); \
PI1(a,b,c,d); \
GAMMA(a,b,c,d); \
PI2(a,b,c,d);
for (r = 0; r < 16; r += 2) {
ROUND(0);
ROUND(1);
for (r = 0; r < 16; ++r) {
ROUND;
}
#else
#define ROUND(i) \
a ^= RC[i]; \
THETA(key->noekeon.K, a,b,c,d); \
PI1(a,b,c,d); \
GAMMA(a,b,c,d); \
PI2(a,b,c,d);
ROUND( 0); ROUND( 1); ROUND( 2); ROUND( 3);
ROUND( 4); ROUND( 5); ROUND( 6); ROUND( 7);
ROUND( 8); ROUND( 9); ROUND(10); ROUND(11);
ROUND(12); ROUND(13); ROUND(14); ROUND(15);
#endif
#undef ROUND
@ -134,7 +149,9 @@ void noekeon_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_k
#endif
{
ulong32 a,b,c,d, temp;
#ifdef SMALL_CODE
int r;
#endif
_ARGCHK(key != NULL);
_ARGCHK(pt != NULL);
@ -143,18 +160,35 @@ void noekeon_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_k
LOAD32L(a,&ct[0]); LOAD32L(b,&ct[4]);
LOAD32L(c,&ct[8]); LOAD32L(d,&ct[12]);
#define ROUND(i) \
#ifdef SMALL_CODE
#define ROUND \
THETA(key->noekeon.dK, a,b,c,d); \
a ^= RC[r-i]; \
a ^= RC[r]; \
PI1(a,b,c,d); \
GAMMA(a,b,c,d); \
PI2(a,b,c,d);
for (r = 16; r > 0; r -= 2) {
ROUND(0);
ROUND(1);
for (r = 16; r > 0; --r) {
ROUND;
}
#else
#define ROUND(i) \
THETA(key->noekeon.dK, a,b,c,d); \
a ^= RC[i]; \
PI1(a,b,c,d); \
GAMMA(a,b,c,d); \
PI2(a,b,c,d);
ROUND(16); ROUND(15); ROUND(14); ROUND(13);
ROUND(12); ROUND(11); ROUND(10); ROUND( 9);
ROUND( 8); ROUND( 7); ROUND( 6); ROUND( 5);
ROUND( 4); ROUND( 3); ROUND( 2); ROUND( 1);
#endif
#undef ROUND
@ -176,31 +210,58 @@ int noekeon_test(void)
{
#ifndef LTC_TEST
return CRYPT_NOP;
#else
static const unsigned char
key[] =
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 },
pt[] =
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 },
ct[] =
{ 0x57, 0x9a, 0x6c, 0xe8, 0x91, 0x16, 0x52, 0x53,
0x32, 0x00, 0xca, 0x0a, 0x17, 0x5d, 0x28, 0x0e };
unsigned char tmp[2][16];
int err;
symmetric_key skey;
if ((err = noekeon_setup(key, 16, 0, &skey)) != CRYPT_OK) {
return err;
#else
static const struct {
int keylen;
unsigned char key[16], pt[16], ct[16];
} tests[] = {
{
16,
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 },
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 },
{ 0x57, 0x9a, 0x6c, 0xe8, 0x91, 0x16, 0x52, 0x53,
0x32, 0x00, 0xca, 0x0a, 0x17, 0x5d, 0x28, 0x0e }
}
noekeon_ecb_encrypt(pt, tmp[0], &skey);
noekeon_ecb_decrypt(tmp[0], tmp[1], &skey);
if (memcmp(tmp[0], ct, 16) != 0 || memcmp(tmp[1], pt, 16) != 0) {
return CRYPT_FAIL_TESTVECTOR;
}
return CRYPT_OK;
};
symmetric_key key;
unsigned char tmp[2][16];
int err, i, y;
for (i = 0; i < (int)(sizeof(tests)/sizeof(tests[0])); i++) {
zeromem(&key, sizeof(key));
if ((err = noekeon_setup(tests[i].key, tests[i].keylen, 0, &key)) != CRYPT_OK) {
return err;
}
noekeon_ecb_encrypt(tests[i].pt, tmp[0], &key);
noekeon_ecb_decrypt(tmp[0], tmp[1], &key);
if (memcmp(tmp[0], tests[i].ct, 16) || memcmp(tmp[1], tests[i].pt, 16)) {
#if 0
printf("\n\nTest %d failed\n", i);
if (memcmp(tmp[0], tests[i].ct, 16)) {
printf("CT: ");
for (i = 0; i < 16; i++) {
printf("%02x ", tmp[0][i]);
}
printf("\n");
} else {
printf("PT: ");
for (i = 0; i < 16; i++) {
printf("%02x ", tmp[1][i]);
}
printf("\n");
}
#endif
return CRYPT_FAIL_TESTVECTOR;
}
/* now see if we can encrypt all zero bytes 1000 times, decrypt and come back where we started */
for (y = 0; y < 16; y++) tmp[0][y] = 0;
for (y = 0; y < 1000; y++) noekeon_ecb_encrypt(tmp[0], tmp[0], &key);
for (y = 0; y < 1000; y++) noekeon_ecb_decrypt(tmp[0], tmp[0], &key);
for (y = 0; y < 16; y++) if (tmp[0][y] != 0) return CRYPT_FAIL_TESTVECTOR;
}
return CRYPT_OK;
#endif
}

1755
notes/cipher_tv.txt Normal file

File diff suppressed because it is too large Load Diff

1605
notes/hash_tv.txt Normal file

File diff suppressed because it is too large Load Diff

1605
notes/hmac_tv.txt Normal file

File diff suppressed because it is too large Load Diff

407
notes/omac_tv.txt Normal file
View File

@ -0,0 +1,407 @@
OMAC Tests. In these tests messages of N bytes long (00,01,02,...,NN-1) are OMAC'ed. The initial key is
of the same format (length specified per cipher). The OMAC key in step N+1 is the OMAC output of
step N (repeated as required to fill the array).
OMAC-aes (16 byte key)
0: 97DD6E5A882CBD564C39AE7D1C5A31AA
1: F69346EEB9A76553172FC20E9DB18C63
2: 996B17202E2EDEBD63F414DD5E84F3AF
3: D00D7DA967A2873589A7496503B3DBAB
4: B43C24C0A82DAA12D328395C2ABD7CAE
5: 9B902B6663B5FEDC6F9DCE74B35B91F2
6: 06A9678C65D7CE225E082ECA31788335
7: 7D67866CDB313DF65DED113DB02D6362
8: 259E28CF3E578AC47A21A77BA9EA8261
9: 32F23C8F93EA301C6D3FE0840CA8DB4B
10: C2B06388AD6F8C43D19FE4F6A8ED21AE
11: FA8622485DB2F62F84FF46E532A1A141
12: F312D9B2E6272578F406B66C79F30A0E
13: 7A5DE06B2BFB75ADA665E96F680AC098
14: C3B00380F0BD8E2F5C9DD9945E0F36EE
15: DDD87974A5FB2E7A4514241E94526B5B
16: AD24FC47A0FEA84C54696DE997A94F4B
17: 7538713D8AA2AE3726307EFF087BBF5E
18: 7619A52B4C34A98440812F5F28F8DC4F
19: 7E797B8846554888622CC5E400B2FA44
20: 61E8DD3E09145F5657DB4B8F7BD2D7D8
21: FDAE2A3FE60DDF1871C2613A293AB6F1
22: A186D6EFD10DFFD2C088480B0A784185
23: 3119D337865618CDA55C06FB992427CF
24: 413E3EAD7E3F169A37C49F9CA92E235E
25: 37A55AF22373B9A1E2F8368B2FB992CA
26: 4941F604C40EEEE1A16CFE073C12D1FE
27: 3E8F4A0876BF12A2DCA87157F15DC884
28: 5DFAE292D8EEB13D8FE5725E5D169742
29: 59160455E0C0B35D950BA67C77F9FB05
30: 5AC0D736A06A7DD146B137ADEE78EE06
31: 0CA1178F28B953045EE76E2E760036CA
32: 025616215F870D1EF838AD1D2AE0C649
OMAC-blowfish (8 byte key)
0: 2CFB5DE451FFE8CC
1: A5AC339DB44D020C
2: A3CE0CF62249444D
3: 3076B7129CE3F6A1
4: 9E091A637DDF70E3
5: 275199AB20A5F09C
6: CDEDA8D16A401E62
7: FC980516CF5C9E30
8: 659D0B31D21B622B
9: 8306847B5E72E018
10: 7AD029BBF1D2919F
11: 133181425C6808C9
12: FC5AC60E367F413A
13: E0DF8BCCF0AD01D9
14: AC5015398FA64A85
15: 1F068F22AFFECEE1
16: 8E6831D5370678EF
OMAC-xtea (16 byte key)
0: 4A0B6160602E6C69
1: 1B797D5E14237F21
2: 938300C83B99D0AC
3: F989B99B3DE563C6
4: F65DEA2A6AD45D1E
5: 1DB329F0239E162E
6: C0C148C4EE8B4E1F
7: D82B387D5DFFE1FB
8: 1D027A4493898DF2
9: 196369F6B0AF971A
10: 2A37A2655191D10A
11: BD514BE32718EB4A
12: B4DBC978F8EE74ED
13: 8ACCAD35C3D436AE
14: 73ABDC1956630C9B
15: 73410D3D169373CE
16: 23D797B3C7919374
OMAC-rc5 (8 byte key)
0: E374E40562C3CB23
1: B46D83F69233E236
2: 7CB72B1D335F04B0
3: 94457CBC97B31328
4: 543D0EDFCDCD7C76
5: 5164EFA8412EAA5D
6: 13CA0717EF95F9A7
7: 2AA49A7AA7719700
8: C9E7C56125C3D90F
9: 2BE3E15FE58648AA
10: 77D0B90372D6D0FD
11: 17408F62ECD62F57
12: 7864EFFA59DC059B
13: 3212E76E25E5DEA8
14: E2424C083CDE5A6A
15: DE86FFDBDA65D138
16: 85482C24D61B8950
OMAC-rc6 (16 byte key)
0: E103BD8BA47B7C1C010E1561712E6722
1: E51AEECFED3AF40443B3A1C011407736
2: FA6506C5ABE03381B045D28D1D828966
3: FAC4237FFE7772E2299D3D983BB130DD
4: 3A7E24D41121A5D4F96FCECF0C2A4A10
5: AA44291E5500C1C8E1A14CB56E4F979A
6: 4B8FDA6DA6B3266E39111F403C31754E
7: 4DF5F1A1C8EBC7F56D0D12EEB63FF585
8: 46A6DDE419355EDE14D31045FCA1BA35
9: 71756D4D3DF59578B7F93FD4B5C08187
10: ADA292A19F8636A03A8BC58C26D65B0D
11: 703190DAF17F8D08A67A11FDF0C2A622
12: D2B94CAD1AFC5CD012575964D1425BE6
13: 45FD0069FCA6F72E23E4DB41AA543091
14: 36F652600F5C9F226721400A7199E2BA
15: E8CC6389ECF8EF1DBB90A0FD051B7570
16: 8125446B975DBDA742A903340D6B96C7
17: 00B55E4399EB930E592F507F896BF3DC
18: 33E58F42A47C9543A851D6CA9324FEE0
19: 9F28FDEA3EC7F515128F5D0C0EB684C5
20: AC1DAF6C01AA28BCC0A819189FA949D7
21: D0532B5F54A179444D052A4D2AD6E4F9
22: 58B80A66549404C7B9F64D5AE3F798AB
23: D0D6D586477F92311DDF667E0749D338
24: 0DFC0FAA67FF114398CE94D0688AE146
25: E163B8C00CF5CC9FA23ACACD62B53D64
26: ACE9270456AF9BD388BA72E98825CFE8
27: 4302EED9BAA19C7A296585E23A066A44
28: B3EEABEFAB25C7478419265564715387
29: 9F0630ADE9C74AB2981D63F3B69E85BF
30: 1215A9446A275CCE2714F94F3C213BB7
31: AF43D7F748DE0E3458DB970BAC37E98D
32: BF871AC9E892CE0DCD7C8C7ADDD854C6
OMAC-safer+ (16 byte key)
0: A2C8C7FEA5529D01C3FF4E9359EF74F4
1: EAB87021118FF24FE79B69ABCCB14A8F
2: 789566F467BAA68F4CC3C4B61901D6D4
3: 369F41EEAF7D628F9E0D77BE43BFC1D2
4: DC46A20E1F36F45006ED5B43BEC20DA6
5: 8F150CE34F57BBA2E6CE3431B78E4ACD
6: 61CD154478BE20F33B26CD8FC58091A5
7: 4E6DAA575CF28F1F48B256262B7D558C
8: D21FA4F1859571DB91E92767C5487AA2
9: E3D009DC7E71FBBB030B8FF0B544A2C9
10: 094C236EA48ABF7DBAE5A88AA3DE07D7
11: 00C401996F8224359566660AC1CEDAA1
12: D580EC60F712558D875F01643D96653F
13: 8482298027C7B4D5969787A1DB1B1F2F
14: AB726AE3DA95CB242E63EF876A4BC446
15: D668ED4919003F5E45590663FAED41DA
16: E4CFFD7E0E7B176867C386001849FD6F
17: 37B3C6DEFC5573879006D15F982A397C
18: 0AB8847EE6A41A0E960080EF0D1BF1C5
19: 2C94FCA2A685F276A65ED286AE12FD9F
20: 23383032032D7B5165A31ECA156DBD23
21: E1EECFB3D671DF694FFB05AE4305AD4C
22: A0F6CA99B96CD1EDD04C52828C8A4D74
23: 12D6B7053417AF3E407EFD6EE1CC38FE
24: A566D1C39AE7A1A0A77D5A1F56C5FAAB
25: 81C9FAECEAEA326140AFCD569668F669
26: 6A00BF1D0DC893868378E4347CB4A1B9
27: 98842956DBE7AFB1BF49C46497BD54C7
28: 88EFCD5A1644B75BB0B3F5DD338849CE
29: 77EC62C278C61163B1BEC595A11F047A
30: 147424E817DC69413CC657E0CB292F7F
31: A2946CBB910743EF62D8A3C7391B9B9B
32: 00EEDA55520B8A5B88B76487E80EB6E1
OMAC-twofish (16 byte key)
0: 0158EB365FCCFDD94EBA6BE42B6659C4
1: 17DA580917D147D10CB73DB6800B0E59
2: 3F185CC15EF3328D3E075665308C07C8
3: 5712A97ACC9D08FE9D2087D0CA16B0AD
4: 90425A8CC1C026DDD896FC2131AF654B
5: 30A43D4FEAE71F5396308C16DA081B4A
6: 6839FEF605704D49F1A379A9E9595E6F
7: 56A8F06DFEE543971B351B07430E2026
8: 36DD0E4B55C5314F9F2753D7EB6F0849
9: 8E319249A3CD456460F410F518F8CEDB
10: 463978BE2A063C22E71DC71520723517
11: 1B735E45FD3DF636E0A6104D4A2E9CB8
12: 628A82213148AD9791153D5AAFBDDFDC
13: 21AFDF08A36ADB6659B656C8EA0800E5
14: E5C3E58803DDBE174E0D4C2B8171AEF0
15: FC6981F2B4359BA05988D61822C0FA88
16: 7B03498FAFB04A6542248852225F9DAE
17: 9B173E91E59A940186E57BB867B8307B
18: 470BF2EE614C8423AA3FDF323F1C103E
19: 6E664AFDFD8306547BBEDA036D267B79
20: F61AEC1144C3DD646169E16073700AC6
21: AE503B139707AFA494F7F2DE933EE81A
22: A0A8BDD4ED0DCAE4A8E1DCEE56368FF0
23: 460B8207930DA434AE6AFECC305D9A26
24: 7F03F8C7BA5365CC65F7864A42693BC8
25: 31448849D6190484192F29A221700011
26: BDA941019C75551D858F70FB1362EB23
27: 2880CB3E62447AE8EACA76C17971BB18
28: FC8D710FA3990B56357E61C2A302EB84
29: 793CD15348D7DFF301C47BC6E6235E22
30: 6FB0CE69A15A3B6A933324A480077D35
31: C24FCA5DD4AE0DF2BFF17364D17D6743
32: DC6738080478AF9AF7CA833295031E06
OMAC-safer-k64 (8 byte key)
0: 726FE2DD40A43924
1: 2A138B65EB352621
2: 9588A1B53E29616C
3: C025DEFDE1A59850
4: 73D062F1B6D8E003
5: 944598A2FC8A2D76
6: B176C25D8CAFFC98
7: 14F05014DE6A090A
8: A7B9847B2CE22D0F
9: FCD71310CBAA3A62
10: BFF00CE5D4A20331
11: BEE12A2171333ED5
12: 333FD849BEB4A64A
13: D048EC7E93B90435
14: F04960356689CFEF
15: 9E63D9744BF1B61A
16: 7C744982F32F8889
OMAC-safer-sk64 (8 byte key)
0: E96711BA37D53743
1: 7DCFF26A03509FE1
2: 0A20EF19C8EE9BF2
3: FE2883748A6963CF
4: 557060195B820A18
5: 771A7931FBBE5C0F
6: 6BDBCE5F96CF91D8
7: F3B924CCE8724595
8: EC7191286D83C2C3
9: 94F55B19BB7A8AC1
10: 2189F4F2B06A8CA4
11: 99853DAEBCA33A46
12: 66EAC37A033802D7
13: 845D7AA866F8A8AD
14: 33A874DFECAC22AC
15: 63DD9F7A7F3683DF
16: EAC277D951676C44
OMAC-safer-k128 (16 byte key)
0: 8037B89AF193F129
1: FF2314E87BA6AFE1
2: C3243DF896B61D85
3: 0F61C715CE821AB8
4: EBFDC6A9CFD2F5A4
5: AB6497D7AF2C7FFF
6: C920CEEB7C1819C2
7: 3E186951B545A7E5
8: 5EA36A93C94AF4AC
9: 6A2C59FAE33709BE
10: BF1BAFAF9FC39C19
11: 69EB6EF046677B7C
12: CDDCEE6B20453094
13: A3833BD3FED6895C
14: B6C05E51F01E049B
15: 90A2D0EAB739D39B
16: 07BF607A161D0A66
OMAC-safer-sk128 (16 byte key)
0: 5E8B137A3946A557
1: 0228FA66B13F3C7E
2: A6F9BBAFF050DCDD
3: F75880F684A796CE
4: E0AEFB8E32040EBD
5: 9F65D658B86D310F
6: 3FA52804FB46CCAA
7: 2F6D12D199FCD2FB
8: CB56AF60AFB4D2BB
9: 8E6F0FF6FDD262FD
10: 490245BE3CCCEDE2
11: EFD319AE46C73005
12: 43E00E545C848995
13: 10444B41ECA15EBE
14: 521775C389D5BE71
15: 9B683EF8B097FEBA
16: 3C5D746EED09530A
OMAC-rc2 (8 byte key)
0: F001FE9BBC3A97B0
1: 8F8DC9C952897FBD
2: EC82EAD195AAC38C
3: 53DD52269B19E9A4
4: 9B86F64BF72A0647
5: 664A88A29F2898C6
6: AFEC3F71C1415666
7: 9BA1F2C1A2E765F9
8: 402A12120908B436
9: 03ECCD4C6AF44144
10: E8CA3529B5D9D6FC
11: 951EE10779CC585D
12: B9083CA88E7E819B
13: AFFB9E884DACC5B7
14: E942E8BC241343D6
15: 9B190489091344FB
16: 9330A9E05554A15A
OMAC-des (8 byte key)
0: C9085E99D74DF01D
1: FAC84F0EFBEF8630
2: C37C5FECE671CF16
3: 45B2CBEE8701A5B1
4: 53665E1F024EB001
5: 357123CEDFC9FF61
6: BD2CFD33FB1F832B
7: 1AAA9D8C9120BDBF
8: EB9F589AE9D4E78F
9: C8F9D2ACE691922D
10: 81ED6F3611DDC0FD
11: 2965ABEAC46839EE
12: 2208B1E095F7AE2E
13: C0414FE41800113E
14: 653A24119CF43D97
15: 7FB7CE0862958B37
16: 55097816B10C549B
OMAC-3des (24 byte key)
0: 7F07A9EA8ECEDF9E
1: 4E2A652EB5FBF5F8
2: 4F84E3779ACCB9F5
3: 7134AB3463115DC6
4: 82327BE8EA2D7E0B
5: 24950B9C14D87CD9
6: B25A097BB7E0E18A
7: ED51BAE55ED925E7
8: 56B79E7644556975
9: A65BD98E4D4E31E2
10: 11145BB51514482D
11: 397486787E676BA6
12: BD1F6DEBAF6D9AEF
13: 5CC3921F7DB815CF
14: B0C0E60DA5F727F3
15: F8637AEEFF10F470
16: 0EA19531D42706EA
OMAC-cast5 (8 byte key)
0: 7413DCDB9F0C3100
1: 423799EDF1472B79
2: 03856F0CB4F11606
3: F152AE6360813DE0
4: 853998BD980AD146
5: AE6C3D667DB8B414
6: B5A4986A34BDE20F
7: E5ABE5B979798942
8: BEE8DFED4555F405
9: 6B5339E952AF61BE
10: 5E867CF34D9C1149
11: F9C55CB3BC655E08
12: EA09A2929AC7D915
13: CE8EB0E4370E1933
14: 749A424B2AA91B98
15: 8DDA93C2B814D5D1
16: E8B0B219D4CB699B
OMAC-noekeon (16 byte key)
0: 897F93D42DF43E4FDACB0E19A27D0CF5
1: 3FAB4FD1A374C36E80D0535ADA81583A
2: 209F1B04BD823B068BC19CEF40B875DB
3: E8FC96A2D8EB9BDA9E8A4EA8F6FE611A
4: 35DE59C345C4AF97924187A6EA73F556
5: 59793AB3D84D614D8AEE6E233B3DE755
6: 64DCB7E74485DF98F4DC70B14DD26107
7: 42E87ABB43E4504DB362B59A9BBC28DC
8: 98EC0C30C1AFBF4BC9A2DF421AC446E4
9: 8B3B59B481B7AFDB6BC593E2BB2A80B2
10: 0F60392A9518682015F43B8109E3A773
11: A99BEC6BB467B5949EC4819B8FB47874
12: 8E15ED270998CD1D7226B2BB9B5A8BC8
13: B4D637277DE68E507DD95E6EC495B364
14: DCCF001FA3A9AB5C58213CEB90B341E7
15: 508C01FDA50B06DDC1AF9CD78F0FD2C7
16: 3DB78001DE8115BE9E0B884AE4243926
17: 165951DF3F7D28AD6A2FE56DC32A0F60
18: 155944AEA14A6E08283421E8F19FE6F3
19: 151BEE5BC94004DFD407A0EFE51F8D9A
20: 081C3192C00D7BACB147FDDA5C460A4A
21: BEEB181DB90F5B3B1DD5BCFFC87C66DE
22: D83B9F8AFD912D8424C85AB0FBDD4751
23: A3BAF0E00DEBFB9C3A7B65A5AFCEE670
24: D03695C35C7D36C05FD26ADBF070E559
25: 5BFAA49199ABCE1CFBA626D30FA6AB0F
26: 9C3601196AD328AADBE62C730ECCC888
27: 75D79E48C5797963EBAF466BC0E1639E
28: 968DF7D963E6D023EC8421C7B2787E7B
29: 5E315EB6B6E583E7D8CF78A3A81D28C9
30: 322E00FC522FA7B41A6564E37F3D9DDC
31: AAB04CB0B25A7A7951C75592BA7CB360
32: CD5B1ED284EDCD493EFE133ECEA0F822
OMAC-skipjack (10 byte key)
0: 84EDFA769040603C
1: 7DA58A4CBD642627
2: 118F60115CFC8229
3: A7F7346D34DB2F0E
4: 35615CCD526CD57F
5: DE471601A3660844
6: 15FCCE6D6D883D1F
7: C6F694861233151B
8: 3B762B397F16E807
9: 976C6AB59FB3AB12
10: 6810791F2C595961
11: 7FA3478286917F17
12: 73DEE44A51C6B610
13: 89EE8B253B1ACE81
14: CDF2586A56C8A0B5
15: ED91F98DA98F42C4
16: D8D0FA5CE96B08BF

View File

@ -12,28 +12,29 @@ and no heap.
To save space all of the symmetric key scheduled keys are stored in a union called "symmetric_key". This means the
size of a symmetric_key is the size of the largest scheduled key. By removing the ciphers you don't use from
the build you can minimize the size of this structure. For instance, by removing both Twofish and Blowfish the
size reduces to 528 bytes from the 4,256 bytes it would have been (on a 32-bit platform). Or if you remove
Blowfish and use Twofish with TWOFISH_SMALL defined its still 528 bytes. Even at its largest the structure is only
size reduces to 768 bytes from the 4,256 bytes it would have been (on a 32-bit platform). Or if you remove
Blowfish and use Twofish with TWOFISH_SMALL defined its still 768 bytes. Even at its largest the structure is only
4KB which is normally not a problem for any platform.
Cipher Name | Size of scheduled key (bytes) |
------------+-------------------------------|
Twofish | 4,256 |
Blowfish | 4,168 |
RC5 | 204 |
RC6 | 176 |
3DES | 768 |
SAFER+ | 532 |
Serpent | 528 |
Rijndael | 516 |
RC5 | 204 |
XTEA | 256 |
Twofish | 4,256 |
Twofish [*] | 193 |
SAFER [#] | 217 |
RC2 | 256 |
DES | 256 |
3DES | 768 |
SAFER [#] | 217 |
Twofish [*] | 193 |
RC6 | 176 |
CAST5 | 132 |
Noekeon | 32 |
Skipjack | 10 |
------------+-------------------------------/
Memory used per cipher on a 32-bit platform.
@ -43,4 +44,9 @@ Memory used per cipher on a 32-bit platform.
Noekeon is a fairly fast cipher and uses very little memory. Ideally in low-ram platforms all other ciphers should be
left undefined and Noekeon should remain. While Noekeon is generally considered a secure block cipher (it is insecure
as a hash) CAST5 is perhaps a "runner-up" choice. CAST5 has been around longer (it is also known as CAST-128) and is
fairly fast as well.
fairly fast as well.
You can easily accomplish this via the "config.pl" script. Simply answer "n" to all of the ciphers except the one you want
and then rebuild the library. [or you can hand edit mycrypt_custom.h]

244
omac.c Normal file
View File

@ -0,0 +1,244 @@
/* OMAC1 Support by Tom St Denis (for 64 and 128 bit block ciphers only) */
#include "mycrypt.h"
#ifdef OMAC
int omac_init(omac_state *omac, int cipher, const unsigned char *key, unsigned long keylen)
{
int err, x, y, mask, msb, len;
_ARGCHK(omac != NULL);
_ARGCHK(key != NULL);
/* schedule the key */
if ((err = cipher_is_valid(cipher)) != CRYPT_OK) {
return err;
}
if ((err = cipher_descriptor[cipher].setup(key, keylen, 0, &omac->key)) != CRYPT_OK) {
return err;
}
/* ok now we need Lu and Lu^2 [calc one from the other] */
/* first calc L which is Ek(0) */
zeromem(omac->Lu[0], cipher_descriptor[cipher].block_length);
cipher_descriptor[cipher].ecb_encrypt(omac->Lu[0], omac->Lu[0], &omac->key);
/* now setup the system */
switch (cipher_descriptor[cipher].block_length) {
case 8: mask = 0x1B;
len = 8;
break;
case 16: mask = 0x87;
len = 16;
break;
default: return CRYPT_INVALID_ARG;
}
/* now do the mults, whoopy! */
for (x = 0; x < 2; x++) {
/* if msb(L * u^(x+1)) = 0 then just shift, otherwise shift and xor constant mask */
msb = omac->Lu[x][0] >> 7;
/* shift left */
for (y = 0; y < (len - 1); y++) {
omac->Lu[x][y] = ((omac->Lu[x][y] << 1) | (omac->Lu[x][y+1] >> 7)) & 255;
}
omac->Lu[x][len - 1] = ((omac->Lu[x][len - 1] << 1) ^ (msb ? mask : 0)) & 255;
/* copy up as require */
if (x == 0) {
memcpy(omac->Lu[1], omac->Lu[0], sizeof(omac->Lu[0]));
}
}
/* setup state */
omac->cipher_idx = cipher;
omac->buflen = 0;
omac->blklen = len;
zeromem(omac->prev, sizeof(omac->prev));
zeromem(omac->block, sizeof(omac->block));
return CRYPT_OK;
}
int omac_process(omac_state *state, const unsigned char *buf, unsigned long len)
{
int err, n, x;
_ARGCHK(state != NULL);
_ARGCHK(buf != NULL);
if ((err = cipher_is_valid(state->cipher_idx)) != CRYPT_OK) {
return err;
}
if ((state->buflen > (int)sizeof(state->block)) || (state->buflen < 0) ||
(state->blklen > (int)sizeof(state->block)) || (state->buflen > state->blklen)) {
return CRYPT_INVALID_ARG;
}
while (len != 0) {
/* ok if the block is full we xor in prev, encrypt and replace prev */
if (state->buflen == state->blklen) {
for (x = 0; x < state->blklen; x++) {
state->block[x] ^= state->prev[x];
}
cipher_descriptor[state->cipher_idx].ecb_encrypt(state->block, state->prev, &state->key);
state->buflen = 0;
}
/* add bytes */
n = MIN(len, (unsigned long)(state->blklen - state->buflen));
memcpy(state->block + state->buflen, buf, n);
state->buflen += n;
len -= n;
buf += n;
}
return CRYPT_OK;
}
int omac_done(omac_state *state, unsigned char *out, unsigned long *outlen)
{
int err, mode, x;
_ARGCHK(state != NULL);
_ARGCHK(out != NULL);
if ((err = cipher_is_valid(state->cipher_idx)) != CRYPT_OK) {
return err;
}
if ((state->buflen > (int)sizeof(state->block)) || (state->buflen < 0) ||
(state->blklen > (int)sizeof(state->block)) || (state->buflen > state->blklen)) {
return CRYPT_INVALID_ARG;
}
/* figure out mode */
if (state->buflen != state->blklen) {
/* add the 0x80 byte */
state->block[state->buflen++] = 0x80;
/* pad with 0x00 */
while (state->buflen < state->blklen) {
state->block[state->buflen++] = 0x00;
}
mode = 1;
} else {
mode = 0;
}
/* now xor prev + Lu[mode] */
for (x = 0; x < state->blklen; x++) {
state->block[x] ^= state->prev[x] ^ state->Lu[mode][x];
}
/* encrypt it */
cipher_descriptor[state->cipher_idx].ecb_encrypt(state->block, state->block, &state->key);
/* output it */
for (x = 0; x < state->blklen && (unsigned long)x < *outlen; x++) {
out[x] = state->block[x];
}
*outlen = x;
#ifdef CLEAN_STACK
zeromem(state, sizeof(*state));
#endif
return CRYPT_OK;
}
int omac_memory(int cipher, const unsigned char *key, unsigned long keylen,
const unsigned char *msg, unsigned long msglen,
unsigned char *out, unsigned long *outlen)
{
int err;
omac_state omac;
if ((err = omac_init(&omac, cipher, key, keylen)) != CRYPT_OK) {
return err;
}
if ((err = omac_process(&omac, msg, msglen)) != CRYPT_OK) {
return err;
}
if ((err = omac_done(&omac, out, outlen)) != CRYPT_OK) {
return err;
}
return CRYPT_OK;
}
int omac_file(int cipher, const unsigned char *key, unsigned long keylen,
const char *filename, unsigned char *out, unsigned long *outlen)
{
#ifdef NO_FILE
return CRYPT_NOP;
#else
int err, x;
omac_state omac;
FILE *in;
unsigned char buf[512];
in = fopen(filename, "rb");
if (in == NULL) {
return CRYPT_FILE_NOTFOUND;
}
if ((err = omac_init(&omac, cipher, key, keylen)) != CRYPT_OK) {
fclose(in);
return err;
}
do {
x = fread(buf, 1, sizeof(buf), in);
if ((err = omac_process(&omac, buf, x)) != CRYPT_OK) {
fclose(in);
return err;
}
} while (x == sizeof(buf));
fclose(in);
if ((err = omac_done(&omac, out, outlen)) != CRYPT_OK) {
return err;
}
return CRYPT_OK;
#endif
}
int omac_test(void)
{
#if !defined(LTC_TEST)
return CRYPT_NOP;
#else
static const unsigned char key[] = { 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c };
static const unsigned char pt[] = { 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96,
0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c,
0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,
0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11 };
static const unsigned char tag[] = { 0xdf, 0xa6, 0x67, 0x47, 0xde, 0x9a, 0xe6, 0x30,
0x30, 0xca, 0x32, 0x61, 0x14, 0x97, 0xc8, 0x27 };
unsigned char out[16];
int err, idx;
unsigned long len;
/* AES can be under rijndael or aes... try to find it */
if ((idx = find_cipher("aes")) == -1) {
if ((idx = find_cipher("rijndael")) == -1) {
return CRYPT_NOP;
}
}
len = sizeof(out);
if ((err = omac_memory(idx, key, 16, pt, 40, out, &len)) != CRYPT_OK) {
return err;
}
if (memcmp(out, tag, 16) != 0) {
return CRYPT_FAIL_TESTVECTOR;
}
return CRYPT_OK;
#endif
}
#endif

72
prime.c
View File

@ -2,75 +2,67 @@
#ifdef MPI
struct rng_data {
prng_state *prng;
int wprng;
};
#define UPPER_LIMIT PRIME_SIZE
/* figures out if a number is prime (MR test) */
int is_prime(mp_int *N, int *result)
{
int err;
if ((err = mp_prime_is_prime(N, 8, result)) != MP_OKAY) {
return CRYPT_MEM;
_ARGCHK(N != NULL);
_ARGCHK(result != NULL);
if ((err = mp_prime_is_prime(N, mp_prime_rabin_miller_trials(mp_count_bits(N)), result)) != MP_OKAY) {
return mpi_to_ltc_error(err);
}
return CRYPT_OK;
}
static int rand_prime_helper(unsigned char *dst, int len, void *dat)
{
return (int)prng_descriptor[((struct rng_data *)dat)->wprng].read(dst, len, ((struct rng_data *)dat)->prng);
}
int rand_prime(mp_int *N, long len, prng_state *prng, int wprng)
{
unsigned char buf[260];
int err, step, ormask;
struct rng_data rng;
int type, err;
_ARGCHK(N != NULL);
/* pass a negative size if you want a prime congruent to 3 mod 4 */
if (len < 0) {
step = 1;
ormask = 3;
len = -len;
} else {
step = 0;
ormask = 1;
}
/* allow sizes between 2 and 256 bytes for a prime size */
if (len < 2 || len > 256) {
return CRYPT_INVALID_PRIME_SIZE;
}
/* valid PRNG? */
/* valid PRNG? Better be! */
if ((err = prng_is_valid(wprng)) != CRYPT_OK) {
return err;
}
/* read the prng */
if (prng_descriptor[wprng].read(buf+2, (unsigned long)len, prng) != (unsigned long)len) {
return CRYPT_ERROR_READPRNG;
/* setup our callback data, then world domination! */
rng.prng = prng;
rng.wprng = wprng;
/* get type */
if (len < 0) {
type = 1;
len = -len;
} else {
type = 0;
}
/* set sign byte to zero */
buf[0] = (unsigned char)0;
/* Set the top byte to 0x01 which makes the number a len*8 bit number */
buf[1] = (unsigned char)0x01;
/* set the LSB to the desired settings
* (1 for any prime, 3 for primes congruent to 3 mod 4)
/* New prime generation makes the code even more cryptoish-insane. Do you know what this means!!!
-- Gir: Yeah, oh wait, er, no.
*/
buf[len+1] |= (unsigned char)ormask;
/* read the number in */
if (mp_read_raw(N, buf, 2+len) != MP_OKAY) {
return CRYPT_MEM;
if ((err = mp_prime_random(N, mp_prime_rabin_miller_trials(len*8), len, type, rand_prime_helper, &rng)) != MP_OKAY) {
return mpi_to_ltc_error(err);
}
/* Find the next prime after N */
if (mp_prime_next_prime(N, 8, step) != MP_OKAY) {
return CRYPT_MEM;
}
#ifdef CLEAN_STACK
zeromem(buf, sizeof(buf));
#endif
return CRYPT_OK;
}

20
rc2.c
View File

@ -71,7 +71,7 @@ int rc2_setup(const unsigned char *key, int keylen, int rounds, symmetric_key *s
}
for (i = 0; i < keylen; i++) {
tmp[i] = key[i];
tmp[i] = key[i] & 255;
}
/* Phase 1: Expand input key to 128 bytes */
@ -261,22 +261,28 @@ int rc2_test(void)
{ 0x22, 0x69, 0x55, 0x2a, 0xb0, 0xf8, 0x5c, 0xa6 }
}
};
int x, err;
int x, y, err;
symmetric_key skey;
unsigned char buf[2][8];
unsigned char tmp[2][8];
for (x = 0; x < (int)(sizeof(tests) / sizeof(tests[0])); x++) {
zeromem(buf, sizeof(buf));
zeromem(tmp, sizeof(tmp));
if ((err = rc2_setup(tests[x].key, tests[x].keylen, 0, &skey)) != CRYPT_OK) {
return err;
}
rc2_ecb_encrypt(tests[x].pt, buf[0], &skey);
rc2_ecb_decrypt(buf[0], buf[1], &skey);
rc2_ecb_encrypt(tests[x].pt, tmp[0], &skey);
rc2_ecb_decrypt(tmp[0], tmp[1], &skey);
if (memcmp(buf[0], tests[x].ct, 8) != 0 || memcmp(buf[1], tests[x].pt, 8) != 0) {
if (memcmp(tmp[0], tests[x].ct, 8) != 0 || memcmp(tmp[1], tests[x].pt, 8) != 0) {
return CRYPT_FAIL_TESTVECTOR;
}
/* now see if we can encrypt all zero bytes 1000 times, decrypt and come back where we started */
for (y = 0; y < 8; y++) tmp[0][y] = 0;
for (y = 0; y < 1000; y++) rc2_ecb_encrypt(tmp[0], tmp[0], &skey);
for (y = 0; y < 1000; y++) rc2_ecb_decrypt(tmp[0], tmp[0], &skey);
for (y = 0; y < 8; y++) if (tmp[0][y] != 0) return CRYPT_FAIL_TESTVECTOR;
}
return CRYPT_OK;
#endif

18
rc5.c
View File

@ -69,7 +69,7 @@ int rc5_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_ke
/* setup the S array */
t = (ulong32)(2 * (num_rounds + 1));
memcpy(S, stab, t * sizeof(stab[0]));
memcpy(S, stab, t * sizeof(*S));
/* mix buffer */
s = 3 * MAX(t, j);
@ -211,8 +211,8 @@ int rc5_test(void)
{ 0x65, 0xc1, 0x78, 0xb2, 0x84, 0xd1, 0x97, 0xcc }
}
};
unsigned char buf[2][8];
int x, err;
unsigned char tmp[2][8];
int x, y, err;
symmetric_key key;
for (x = 0; x < (int)(sizeof(tests) / sizeof(tests[0])); x++) {
@ -222,13 +222,19 @@ int rc5_test(void)
}
/* encrypt and decrypt */
rc5_ecb_encrypt(tests[x].pt, buf[0], &key);
rc5_ecb_decrypt(buf[0], buf[1], &key);
rc5_ecb_encrypt(tests[x].pt, tmp[0], &key);
rc5_ecb_decrypt(tmp[0], tmp[1], &key);
/* compare */
if (memcmp(buf[0], tests[x].ct, 8) != 0 || memcmp(buf[1], tests[x].pt, 8) != 0) {
if (memcmp(tmp[0], tests[x].ct, 8) != 0 || memcmp(tmp[1], tests[x].pt, 8) != 0) {
return CRYPT_FAIL_TESTVECTOR;
}
/* now see if we can encrypt all zero bytes 1000 times, decrypt and come back where we started */
for (y = 0; y < 8; y++) tmp[0][y] = 0;
for (y = 0; y < 1000; y++) rc5_ecb_encrypt(tmp[0], tmp[0], &key);
for (y = 0; y < 1000; y++) rc5_ecb_decrypt(tmp[0], tmp[0], &key);
for (y = 0; y < 8; y++) if (tmp[0][y] != 0) return CRYPT_FAIL_TESTVECTOR;
}
return CRYPT_OK;
#endif

16
rc6.c
View File

@ -224,8 +224,8 @@ int rc6_test(void)
0x20, 0xad, 0x16, 0xa1, 0x67, 0x4e, 0x5d, 0x48 }
}
};
unsigned char buf[2][16];
int x, err;
unsigned char tmp[2][16];
int x, y, err;
symmetric_key key;
for (x = 0; x < (int)(sizeof(tests) / sizeof(tests[0])); x++) {
@ -235,13 +235,19 @@ int rc6_test(void)
}
/* encrypt and decrypt */
rc6_ecb_encrypt(tests[x].pt, buf[0], &key);
rc6_ecb_decrypt(buf[0], buf[1], &key);
rc6_ecb_encrypt(tests[x].pt, tmp[0], &key);
rc6_ecb_decrypt(tmp[0], tmp[1], &key);
/* compare */
if (memcmp(buf[0], tests[x].ct, 16) || memcmp(buf[1], tests[x].pt, 16)) {
if (memcmp(tmp[0], tests[x].ct, 16) || memcmp(tmp[1], tests[x].pt, 16)) {
return CRYPT_FAIL_TESTVECTOR;
}
/* now see if we can encrypt all zero bytes 1000 times, decrypt and come back where we started */
for (y = 0; y < 16; y++) tmp[0][y] = 0;
for (y = 0; y < 1000; y++) rc6_ecb_encrypt(tmp[0], tmp[0], &key);
for (y = 0; y < 1000; y++) rc6_ecb_decrypt(tmp[0], tmp[0], &key);
for (y = 0; y < 16; y++) if (tmp[0][y] != 0) return CRYPT_FAIL_TESTVECTOR;
}
return CRYPT_OK;
#endif

View File

@ -59,17 +59,17 @@ const struct _hash_descriptor rmd128_desc =
(a) = ROL((a), (s));
#ifdef CLEAN_STACK
static void _rmd128_compress(hash_state *md)
static void _rmd128_compress(hash_state *md, unsigned char *buf)
#else
static void rmd128_compress(hash_state *md)
static void rmd128_compress(hash_state *md, unsigned char *buf)
#endif
{
unsigned long aa,bb,cc,dd,aaa,bbb,ccc,ddd,X[16];
ulong32 aa,bb,cc,dd,aaa,bbb,ccc,ddd,X[16];
int i;
/* load words X */
for (i = 0; i < 16; i++){
LOAD32L(X[i], md->rmd128.buf + (4 * i));
LOAD32L(X[i], buf + (4 * i));
}
/* load state */
@ -231,10 +231,10 @@ static void rmd128_compress(hash_state *md)
}
#ifdef CLEAN_STACK
static void rmd128_compress(hash_state *md)
static void rmd128_compress(hash_state *md, unsigned char *buf)
{
_rmd128_compress(md);
burn_stack(sizeof(unsigned long) * 24 + sizeof(int));
_rmd128_compress(md, buf);
burn_stack(sizeof(ulong32) * 24 + sizeof(int));
}
#endif
@ -249,34 +249,20 @@ void rmd128_init(hash_state * md)
md->rmd128.length = 0;
}
void rmd128_process(hash_state * md, const unsigned char *buf, unsigned long len)
{
unsigned long n;
_ARGCHK(md != NULL);
_ARGCHK(buf != NULL);
while (len > 0) {
n = MIN(len, (64 - md->rmd128.curlen));
memcpy(md->rmd128.buf + md->rmd128.curlen, buf, (size_t)n);
md->rmd128.curlen += n;
buf += n;
len -= n;
HASH_PROCESS(rmd128_process, rmd128_compress, rmd128, 64)
/* is 64 bytes full? */
if (md->rmd128.curlen == 64) {
rmd128_compress(md);
md->rmd128.length += 512;
md->rmd128.curlen = 0;
}
}
}
void rmd128_done(hash_state * md, unsigned char *hash)
int rmd128_done(hash_state * md, unsigned char *hash)
{
int i;
_ARGCHK(md != NULL);
_ARGCHK(hash != NULL);
if (md->rmd128.curlen >= sizeof(md->rmd128.buf)) {
return CRYPT_INVALID_ARG;
}
/* increase the length of the message */
md->rmd128.length += md->rmd128.curlen * 8;
@ -291,7 +277,7 @@ void rmd128_done(hash_state * md, unsigned char *hash)
while (md->rmd128.curlen < 64) {
md->rmd128.buf[md->rmd128.curlen++] = (unsigned char)0;
}
rmd128_compress(md);
rmd128_compress(md, md->rmd128.buf);
md->rmd128.curlen = 0;
}
@ -302,7 +288,7 @@ void rmd128_done(hash_state * md, unsigned char *hash)
/* store length */
STORE64L(md->rmd128.length, md->rmd128.buf+56);
rmd128_compress(md);
rmd128_compress(md, md->rmd128.buf);
/* copy output */
for (i = 0; i < 4; i++) {
@ -311,6 +297,7 @@ void rmd128_done(hash_state * md, unsigned char *hash)
#ifdef CLEAN_STACK
zeromem(md, sizeof(hash_state));
#endif
return CRYPT_OK;
}
int rmd128_test(void)

View File

@ -79,17 +79,17 @@ const struct _hash_descriptor rmd160_desc =
#ifdef CLEAN_STACK
static void _rmd160_compress(hash_state *md)
static void _rmd160_compress(hash_state *md, unsigned char *buf)
#else
static void rmd160_compress(hash_state *md)
static void rmd160_compress(hash_state *md, unsigned char *buf)
#endif
{
unsigned long aa,bb,cc,dd,ee,aaa,bbb,ccc,ddd,eee,X[16];
ulong32 aa,bb,cc,dd,ee,aaa,bbb,ccc,ddd,eee,X[16];
int i;
/* load words X */
for (i = 0; i < 16; i++){
LOAD32L(X[i], md->rmd160.buf + (4 * i));
LOAD32L(X[i], buf + (4 * i));
}
/* load state */
@ -289,10 +289,10 @@ static void rmd160_compress(hash_state *md)
}
#ifdef CLEAN_STACK
static void rmd160_compress(hash_state *md)
static void rmd160_compress(hash_state *md, unsigned char *buf)
{
_rmd160_compress(md);
burn_stack(sizeof(unsigned long) * 26 + sizeof(int));
_rmd160_compress(md, buf);
burn_stack(sizeof(ulong32) * 26 + sizeof(int));
}
#endif
@ -308,34 +308,20 @@ void rmd160_init(hash_state * md)
md->rmd160.length = 0;
}
void rmd160_process(hash_state * md, const unsigned char *buf, unsigned long len)
{
unsigned long n;
_ARGCHK(md != NULL);
_ARGCHK(buf != NULL);
while (len > 0) {
n = MIN(len, (64 - md->rmd160.curlen));
memcpy(md->rmd160.buf + md->rmd160.curlen, buf, (size_t)n);
md->rmd160.curlen += n;
buf += n;
len -= n;
HASH_PROCESS(rmd160_process, rmd160_compress, rmd160, 64)
/* is 64 bytes full? */
if (md->rmd160.curlen == 64) {
rmd160_compress(md);
md->rmd160.length += 512;
md->rmd160.curlen = 0;
}
}
}
void rmd160_done(hash_state * md, unsigned char *hash)
int rmd160_done(hash_state * md, unsigned char *hash)
{
int i;
_ARGCHK(md != NULL);
_ARGCHK(hash != NULL);
if (md->rmd160.curlen >= sizeof(md->rmd160.buf)) {
return CRYPT_INVALID_ARG;
}
/* increase the length of the message */
md->rmd160.length += md->rmd160.curlen * 8;
@ -350,7 +336,7 @@ void rmd160_done(hash_state * md, unsigned char *hash)
while (md->rmd160.curlen < 64) {
md->rmd160.buf[md->rmd160.curlen++] = (unsigned char)0;
}
rmd160_compress(md);
rmd160_compress(md, md->rmd160.buf);
md->rmd160.curlen = 0;
}
@ -361,7 +347,7 @@ void rmd160_done(hash_state * md, unsigned char *hash)
/* store length */
STORE64L(md->rmd160.length, md->rmd160.buf+56);
rmd160_compress(md);
rmd160_compress(md, md->rmd160.buf);
/* copy output */
for (i = 0; i < 5; i++) {
@ -370,6 +356,7 @@ void rmd160_done(hash_state * md, unsigned char *hash)
#ifdef CLEAN_STACK
zeromem(md, sizeof(hash_state));
#endif
return CRYPT_OK;
}
int rmd160_test(void)

17
rsa.c
View File

@ -122,9 +122,14 @@ int rsa_exptmod(const unsigned char *in, unsigned long inlen,
return CRYPT_PK_NOT_PRIVATE;
}
/* must be a private or public operation */
if (which != PK_PRIVATE && which != PK_PUBLIC) {
return CRYPT_PK_INVALID_TYPE;
}
/* init and copy into tmp */
if (mp_init_multi(&tmp, &tmpa, &tmpb, NULL) != MP_OKAY) { goto error; }
if (mp_read_unsigned_bin(&tmp, (unsigned char *)in, (int)inlen) != MP_OKAY) { goto error; }
if (mp_init_multi(&tmp, &tmpa, &tmpb, NULL) != MP_OKAY) { goto error; }
if (mp_read_unsigned_bin(&tmp, (unsigned char *)in, (int)inlen) != MP_OKAY) { goto error; }
/* sanity check on the input */
if (mp_cmp(&key->N, &tmp) == MP_LT) {
@ -277,8 +282,9 @@ int rsa_signdepad(const unsigned char *in, unsigned long inlen,
return CRYPT_INVALID_PACKET;
}
}
for (x = 0; x < inlen/3; x++)
for (x = 0; x < inlen/3; x++) {
out[x] = in[x+(inlen/3)];
}
*outlen = inlen/3;
return CRYPT_OK;
}
@ -295,8 +301,9 @@ int rsa_depad(const unsigned char *in, unsigned long inlen,
if (*outlen < inlen/3) {
return CRYPT_BUFFER_OVERFLOW;
}
for (x = 0; x < inlen/3; x++)
for (x = 0; x < inlen/3; x++) {
out[x] = in[x+(inlen/3)];
}
*outlen = inlen/3;
return CRYPT_OK;
}
@ -306,7 +313,7 @@ int rsa_depad(const unsigned char *in, unsigned long inlen,
z = (unsigned long)mp_unsigned_bin_size(num); \
STORE32L(z, buf2+y); \
y += 4; \
(void)mp_to_unsigned_bin(num, buf2+y); \
if (mp_to_unsigned_bin(num, buf2+y) != MP_OKAY) { return CRYPT_MEM; } \
y += z; \
}

View File

@ -1,3 +1,4 @@
/* SAFER+ Implementation by Tom St Denis */
#include "mycrypt.h"
#ifdef SAFERP
@ -450,21 +451,27 @@ int saferp_test(void)
}
};
unsigned char buf[2][16];
unsigned char tmp[2][16];
symmetric_key skey;
int err, i;
int err, i, y;
for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) {
if ((err = saferp_setup(tests[i].key, tests[i].keylen, 0, &skey)) != CRYPT_OK) {
return err;
}
saferp_ecb_encrypt(tests[i].pt, buf[0], &skey);
saferp_ecb_decrypt(buf[0], buf[1], &skey);
saferp_ecb_encrypt(tests[i].pt, tmp[0], &skey);
saferp_ecb_decrypt(tmp[0], tmp[1], &skey);
/* compare */
if (memcmp(buf[0], tests[i].ct, 16) || memcmp(buf[1], tests[i].pt, 16)) {
if (memcmp(tmp[0], tests[i].ct, 16) || memcmp(tmp[1], tests[i].pt, 16)) {
return CRYPT_FAIL_TESTVECTOR;
}
/* now see if we can encrypt all zero bytes 1000 times, decrypt and come back where we started */
for (y = 0; y < 16; y++) tmp[0][y] = 0;
for (y = 0; y < 1000; y++) saferp_ecb_encrypt(tmp[0], tmp[0], &skey);
for (y = 0; y < 1000; y++) saferp_ecb_decrypt(tmp[0], tmp[0], &skey);
for (y = 0; y < 16; y++) if (tmp[0][y] != 0) return CRYPT_FAIL_TESTVECTOR;
}
return CRYPT_OK;

16
safer.c
View File

@ -393,7 +393,7 @@ int safer_sk64_test(void)
symmetric_key skey;
unsigned char buf[2][8];
int err;
int err, y;
/* test SK64 */
if ((err = safer_sk64_setup(sk64_key, 8, 6, &skey)) != CRYPT_OK) {
@ -407,6 +407,12 @@ int safer_sk64_test(void)
return CRYPT_FAIL_TESTVECTOR;
}
/* now see if we can encrypt all zero bytes 1000 times, decrypt and come back where we started */
for (y = 0; y < 8; y++) buf[0][y] = 0;
for (y = 0; y < 1000; y++) safer_ecb_encrypt(buf[0], buf[0], &skey);
for (y = 0; y < 1000; y++) safer_ecb_decrypt(buf[0], buf[0], &skey);
for (y = 0; y < 8; y++) if (buf[0][y] != 0) return CRYPT_FAIL_TESTVECTOR;
return CRYPT_OK;
#endif
}
@ -423,7 +429,7 @@ int safer_sk128_test(void)
symmetric_key skey;
unsigned char buf[2][8];
int err;
int err, y;
/* test SK128 */
if ((err = safer_sk128_setup(sk128_key, 16, 0, &skey)) != CRYPT_OK) {
@ -435,6 +441,12 @@ int safer_sk128_test(void)
if (memcmp(buf[0], sk128_ct, 8) != 0 || memcmp(buf[1], sk128_pt, 8) != 0) {
return CRYPT_FAIL_TESTVECTOR;
}
/* now see if we can encrypt all zero bytes 1000 times, decrypt and come back where we started */
for (y = 0; y < 8; y++) buf[0][y] = 0;
for (y = 0; y < 1000; y++) safer_ecb_encrypt(buf[0], buf[0], &skey);
for (y = 0; y < 1000; y++) safer_ecb_decrypt(buf[0], buf[0], &skey);
for (y = 0; y < 8; y++) if (buf[0][y] != 0) return CRYPT_FAIL_TESTVECTOR;
return CRYPT_OK;
#endif
}

53
sha1.c
View File

@ -20,18 +20,18 @@ const struct _hash_descriptor sha1_desc =
#define F3(x,y,z) (x ^ y ^ z)
#ifdef CLEAN_STACK
static void _sha1_compress(hash_state *md)
static void _sha1_compress(hash_state *md, unsigned char *buf)
#else
static void sha1_compress(hash_state *md)
static void sha1_compress(hash_state *md, unsigned char *buf)
#endif
{
unsigned long a,b,c,d,e,W[80],i;
ulong32 a,b,c,d,e,W[80],i;
_ARGCHK(md != NULL);
/* copy the state into 512-bits into W[0..15] */
for (i = 0; i < 16; i++) {
LOAD32H(W[i], md->sha1.buf + (4*i));
LOAD32H(W[i], buf + (4*i));
}
/* copy state */
@ -62,7 +62,7 @@ static void sha1_compress(hash_state *md)
}
/* round two */
for (i = 20; i < 40; ) {
for (; i < 40; ) {
FF1(a,b,c,d,e,i++);
FF1(e,a,b,c,d,i++);
FF1(d,e,a,b,c,i++);
@ -71,7 +71,7 @@ static void sha1_compress(hash_state *md)
}
/* round three */
for (i = 40; i < 60; ) {
for (; i < 60; ) {
FF2(a,b,c,d,e,i++);
FF2(e,a,b,c,d,i++);
FF2(d,e,a,b,c,i++);
@ -80,7 +80,7 @@ static void sha1_compress(hash_state *md)
}
/* round four */
for (i = 60; i < 80; ) {
for (; i < 80; ) {
FF3(a,b,c,d,e,i++);
FF3(e,a,b,c,d,i++);
FF3(d,e,a,b,c,i++);
@ -102,10 +102,10 @@ static void sha1_compress(hash_state *md)
}
#ifdef CLEAN_STACK
static void sha1_compress(hash_state *md)
static void sha1_compress(hash_state *md, unsigned char *buf)
{
_sha1_compress(md);
burn_stack(sizeof(unsigned long) * 87);
_sha1_compress(md, buf);
burn_stack(sizeof(ulong32) * 87);
}
#endif
@ -121,35 +121,19 @@ void sha1_init(hash_state * md)
md->sha1.length = 0;
}
void sha1_process(hash_state * md, const unsigned char *buf, unsigned long len)
{
unsigned long n;
_ARGCHK(md != NULL);
_ARGCHK(buf != NULL);
HASH_PROCESS(sha1_process, sha1_compress, sha1, 64)
while (len > 0) {
n = MIN(len, (64 - md->sha1.curlen));
memcpy(md->sha1.buf + md->sha1.curlen, buf, (size_t)n);
md->sha1.curlen += n;
buf += n;
len -= n;
/* is 64 bytes full? */
if (md->sha1.curlen == 64) {
sha1_compress(md);
md->sha1.length += 512;
md->sha1.curlen = 0;
}
}
}
void sha1_done(hash_state * md, unsigned char *hash)
int sha1_done(hash_state * md, unsigned char *hash)
{
int i;
_ARGCHK(md != NULL);
_ARGCHK(hash != NULL);
if (md->sha1.curlen >= sizeof(md->sha1.buf)) {
return CRYPT_INVALID_ARG;
}
/* increase the length of the message */
md->sha1.length += md->sha1.curlen * 8;
@ -164,7 +148,7 @@ void sha1_done(hash_state * md, unsigned char *hash)
while (md->sha1.curlen < 64) {
md->sha1.buf[md->sha1.curlen++] = (unsigned char)0;
}
sha1_compress(md);
sha1_compress(md, md->sha1.buf);
md->sha1.curlen = 0;
}
@ -175,7 +159,7 @@ void sha1_done(hash_state * md, unsigned char *hash)
/* store length */
STORE64H(md->sha1.length, md->sha1.buf+56);
sha1_compress(md);
sha1_compress(md, md->sha1.buf);
/* copy output */
for (i = 0; i < 5; i++) {
@ -184,6 +168,7 @@ void sha1_done(hash_state * md, unsigned char *hash)
#ifdef CLEAN_STACK
zeromem(md, sizeof(hash_state));
#endif
return CRYPT_OK;
}
int sha1_test(void)

82
sha224.c Normal file
View File

@ -0,0 +1,82 @@
/* SHA-224 new NIST standard based off of SHA-256 truncated to 224 bits */
const struct _hash_descriptor sha224_desc =
{
"sha224",
10,
28,
64,
&sha224_init,
&sha256_process,
&sha224_done,
&sha224_test
};
/* init the sha256 er... sha224 state ;-) */
void sha224_init(hash_state * md)
{
_ARGCHK(md != NULL);
md->sha256.curlen = 0;
md->sha256.length = 0;
md->sha256.state[0] = 0xc1059ed8UL;
md->sha256.state[1] = 0x367cd507UL;
md->sha256.state[2] = 0x3070dd17UL;
md->sha256.state[3] = 0xf70e5939UL;
md->sha256.state[4] = 0xffc00b31UL;
md->sha256.state[5] = 0x68581511UL;
md->sha256.state[6] = 0x64f98fa7UL;
md->sha256.state[7] = 0xbefa4fa4UL;
}
int sha224_done(hash_state * md, unsigned char *hash)
{
unsigned char buf[32];
int err;
err = sha256_done(md, buf);
memcpy(hash, buf, 28);
#ifdef CLEAN_STACK
zeromem(buf, sizeof(buf));
#endif
return err;
}
int sha224_test(void)
{
#ifndef LTC_TEST
return CRYPT_NOP;
#else
static const struct {
char *msg;
unsigned char hash[28];
} tests[] = {
{ "abc",
{ 0x23, 0x09, 0x7d, 0x22, 0x34, 0x05, 0xd8,
0x22, 0x86, 0x42, 0xa4, 0x77, 0xbd, 0xa2,
0x55, 0xb3, 0x2a, 0xad, 0xbc, 0xe4, 0xbd,
0xa0, 0xb3, 0xf7, 0xe3, 0x6c, 0x9d, 0xa7 }
},
{ "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
{ 0x75, 0x38, 0x8b, 0x16, 0x51, 0x27, 0x76,
0xcc, 0x5d, 0xba, 0x5d, 0xa1, 0xfd, 0x89,
0x01, 0x50, 0xb0, 0xc6, 0x45, 0x5c, 0xb4,
0xf5, 0x8b, 0x19, 0x52, 0x52, 0x25, 0x25 }
},
};
int i;
unsigned char tmp[28];
hash_state md;
for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) {
sha224_init(&md);
sha224_process(&md, (unsigned char*)tests[i].msg, (unsigned long)strlen(tests[i].msg));
sha224_done(&md, tmp);
if (memcmp(tmp, tests[i].hash, 28) != 0) {
return CRYPT_FAIL_TESTVECTOR;
}
}
return CRYPT_OK;
#endif
}

View File

@ -43,12 +43,12 @@ static const unsigned long K[64] = {
/* compress 512-bits */
#ifdef CLEAN_STACK
static void _sha256_compress(hash_state * md)
static void _sha256_compress(hash_state * md, unsigned char *buf)
#else
static void sha256_compress(hash_state * md)
static void sha256_compress(hash_state * md, unsigned char *buf)
#endif
{
unsigned long S[8], W[64], t0, t1;
ulong32 S[8], W[64], t0, t1;
int i;
_ARGCHK(md != NULL);
@ -60,7 +60,7 @@ static void sha256_compress(hash_state * md)
/* copy the state into 512-bits into W[0..15] */
for (i = 0; i < 16; i++) {
LOAD32H(W[i], md->sha256.buf + (4*i));
LOAD32H(W[i], buf + (4*i));
}
/* fill W[16..63] */
@ -70,18 +70,22 @@ static void sha256_compress(hash_state * md)
/* Compress */
#ifdef SMALL_CODE
for (i = 0; i < 64; i++) {
t0 = S[7] + Sigma1(S[4]) + Ch(S[4], S[5], S[6]) + K[i] + W[i];
t1 = Sigma0(S[0]) + Maj(S[0], S[1], S[2]);
S[7] = S[6];
S[6] = S[5];
S[5] = S[4];
S[4] = S[3] + t0;
S[3] = S[2];
S[2] = S[1];
S[1] = S[0];
S[0] = t0 + t1;
}
#define RND(a,b,c,d,e,f,g,h,i) \
t0 = h + Sigma1(e) + Ch(e, f, g) + K[i] + W[i]; \
t1 = Sigma0(a) + Maj(a, b, c); \
d += t0; \
h = t0 + t1;
for (i = 0; i < 64; i += 8) {
RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],i+0);
RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],i+1);
RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],i+2);
RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],i+3);
RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],i+4);
RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],i+5);
RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],i+6);
RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],i+7);
}
#else
#define RND(a,b,c,d,e,f,g,h,i,ki) \
t0 = h + Sigma1(e) + Ch(e, f, g) + ki + W[i]; \
@ -166,10 +170,10 @@ static void sha256_compress(hash_state * md)
}
#ifdef CLEAN_STACK
static void sha256_compress(hash_state * md)
static void sha256_compress(hash_state * md, unsigned char *buf)
{
_sha256_compress(md);
burn_stack(sizeof(unsigned long) * 74);
_sha256_compress(md, buf);
burn_stack(sizeof(ulong32) * 74);
}
#endif
@ -190,35 +194,20 @@ void sha256_init(hash_state * md)
md->sha256.state[7] = 0x5BE0CD19UL;
}
void sha256_process(hash_state * md, const unsigned char *buf, unsigned long len)
{
unsigned long n;
_ARGCHK(md != NULL);
_ARGCHK(buf != NULL);
HASH_PROCESS(sha256_process, sha256_compress, sha256, 64)
while (len > 0) {
n = MIN(len, (64 - md->sha256.curlen));
memcpy(md->sha256.buf + md->sha256.curlen, buf, (size_t)n);
md->sha256.curlen += n;
buf += n;
len -= n;
/* is 64 bytes full? */
if (md->sha256.curlen == 64) {
sha256_compress(md);
md->sha256.length += 512;
md->sha256.curlen = 0;
}
}
}
void sha256_done(hash_state * md, unsigned char *hash)
int sha256_done(hash_state * md, unsigned char *hash)
{
int i;
_ARGCHK(md != NULL);
_ARGCHK(hash != NULL);
if (md->sha256.curlen >= sizeof(md->sha256.buf)) {
return CRYPT_INVALID_ARG;
}
/* increase the length of the message */
md->sha256.length += md->sha256.curlen * 8;
@ -233,7 +222,7 @@ void sha256_done(hash_state * md, unsigned char *hash)
while (md->sha256.curlen < 64) {
md->sha256.buf[md->sha256.curlen++] = (unsigned char)0;
}
sha256_compress(md);
sha256_compress(md, md->sha256.buf);
md->sha256.curlen = 0;
}
@ -244,7 +233,7 @@ void sha256_done(hash_state * md, unsigned char *hash)
/* store length */
STORE64H(md->sha256.length, md->sha256.buf+56);
sha256_compress(md);
sha256_compress(md, md->sha256.buf);
/* copy output */
for (i = 0; i < 8; i++) {
@ -253,6 +242,7 @@ void sha256_done(hash_state * md, unsigned char *hash)
#ifdef CLEAN_STACK
zeromem(md, sizeof(hash_state));
#endif
return CRYPT_OK;
}
int sha256_test(void)
@ -261,7 +251,7 @@ int sha256_test(void)
return CRYPT_NOP;
#else
static const struct {
char *msg;
char *msg;
unsigned char hash[32];
} tests[] = {
{ "abc",
@ -294,6 +284,10 @@ int sha256_test(void)
#endif
}
#ifdef SHA224
#include "sha224.c"
#endif
#endif

View File

@ -7,7 +7,7 @@ const struct _hash_descriptor sha384_desc =
48,
128,
&sha384_init,
&sha384_process,
&sha512_process,
&sha384_done,
&sha384_test
};
@ -28,25 +28,23 @@ void sha384_init(hash_state * md)
md->sha512.state[7] = CONST64(0x47b5481dbefa4fa4);
}
void sha384_process(hash_state * md, const unsigned char *buf, unsigned long len)
{
_ARGCHK(md != NULL);
_ARGCHK(buf != NULL);
sha512_process(md, buf, len);
}
void sha384_done(hash_state * md, unsigned char *hash)
int sha384_done(hash_state * md, unsigned char *hash)
{
unsigned char buf[64];
_ARGCHK(md != NULL);
_ARGCHK(hash != NULL);
if (md->sha512.curlen >= sizeof(md->sha512.buf)) {
return CRYPT_INVALID_ARG;
}
sha512_done(md, buf);
memcpy(hash, buf, 48);
#ifdef CLEAN_STACK
zeromem(buf, sizeof(buf));
#endif
return CRYPT_OK;
}
int sha384_test(void)

View File

@ -70,9 +70,9 @@ CONST64(0x5fcb6fab3ad6faec), CONST64(0x6c44198c4a475817)
/* compress 1024-bits */
#ifdef CLEAN_STACK
static void _sha512_compress(hash_state * md)
static void _sha512_compress(hash_state * md, unsigned char *buf)
#else
static void sha512_compress(hash_state * md)
static void sha512_compress(hash_state * md, unsigned char *buf)
#endif
{
ulong64 S[8], W[80], t0, t1;
@ -81,12 +81,13 @@ static void sha512_compress(hash_state * md)
_ARGCHK(md != NULL);
/* copy state into S */
for (i = 0; i < 8; i++)
for (i = 0; i < 8; i++) {
S[i] = md->sha512.state[i];
}
/* copy the state into 1024-bits into W[0..15] */
for (i = 0; i < 16; i++) {
LOAD64H(W[i], md->sha512.buf + (8*i));
LOAD64H(W[i], buf + (8*i));
}
/* fill W[16..79] */
@ -136,9 +137,9 @@ static void sha512_compress(hash_state * md)
/* compress 1024-bits */
#ifdef CLEAN_STACK
static void sha512_compress(hash_state * md)
static void sha512_compress(hash_state * md, unsigned char *buf)
{
_sha512_compress(md);
_sha512_compress(md, buf);
burn_stack(sizeof(ulong64) * 90 + sizeof(int));
}
#endif
@ -160,34 +161,19 @@ void sha512_init(hash_state * md)
md->sha512.state[7] = CONST64(0x5be0cd19137e2179);
}
void sha512_process(hash_state * md, const unsigned char *buf, unsigned long len)
{
unsigned long n;
_ARGCHK(md != NULL);
_ARGCHK(buf != NULL);
while (len > 0) {
n = MIN(len, (128 - md->sha512.curlen));
memcpy(md->sha512.buf + md->sha512.curlen, buf, (size_t)n);
md->sha512.curlen += n;
buf += n;
len -= n;
HASH_PROCESS(sha512_process, sha512_compress, sha512, 128)
/* is 128 bytes full? */
if (md->sha512.curlen == 128) {
sha512_compress(md);
md->sha512.length += 1024;
md->sha512.curlen = 0;
}
}
}
void sha512_done(hash_state * md, unsigned char *hash)
int sha512_done(hash_state * md, unsigned char *hash)
{
int i;
_ARGCHK(md != NULL);
_ARGCHK(hash != NULL);
if (md->sha512.curlen >= sizeof(md->sha512.buf)) {
return CRYPT_INVALID_ARG;
}
/* increase the length of the message */
md->sha512.length += md->sha512.curlen * CONST64(8);
@ -202,7 +188,7 @@ void sha512_done(hash_state * md, unsigned char *hash)
while (md->sha512.curlen < 128) {
md->sha512.buf[md->sha512.curlen++] = (unsigned char)0;
}
sha512_compress(md);
sha512_compress(md, md->sha512.buf);
md->sha512.curlen = 0;
}
@ -216,7 +202,7 @@ void sha512_done(hash_state * md, unsigned char *hash)
/* store length */
STORE64H(md->sha512.length, md->sha512.buf+120);
sha512_compress(md);
sha512_compress(md, md->sha512.buf);
/* copy output */
for (i = 0; i < 8; i++) {
@ -225,6 +211,7 @@ void sha512_done(hash_state * md, unsigned char *hash)
#ifdef CLEAN_STACK
zeromem(md, sizeof(hash_state));
#endif
return CRYPT_OK;
}
int sha512_test(void)

279
skipjack.c Normal file
View File

@ -0,0 +1,279 @@
/* Skipjack Implementation by Tom St Denis */
#include "mycrypt.h"
#ifdef SKIPJACK
const struct _cipher_descriptor skipjack_desc =
{
"skipjack",
17,
10, 10, 8, 32,
&skipjack_setup,
&skipjack_ecb_encrypt,
&skipjack_ecb_decrypt,
&skipjack_test,
&skipjack_keysize
};
static const unsigned char sbox[256] = {
0xa3,0xd7,0x09,0x83,0xf8,0x48,0xf6,0xf4,0xb3,0x21,0x15,0x78,0x99,0xb1,0xaf,0xf9,
0xe7,0x2d,0x4d,0x8a,0xce,0x4c,0xca,0x2e,0x52,0x95,0xd9,0x1e,0x4e,0x38,0x44,0x28,
0x0a,0xdf,0x02,0xa0,0x17,0xf1,0x60,0x68,0x12,0xb7,0x7a,0xc3,0xe9,0xfa,0x3d,0x53,
0x96,0x84,0x6b,0xba,0xf2,0x63,0x9a,0x19,0x7c,0xae,0xe5,0xf5,0xf7,0x16,0x6a,0xa2,
0x39,0xb6,0x7b,0x0f,0xc1,0x93,0x81,0x1b,0xee,0xb4,0x1a,0xea,0xd0,0x91,0x2f,0xb8,
0x55,0xb9,0xda,0x85,0x3f,0x41,0xbf,0xe0,0x5a,0x58,0x80,0x5f,0x66,0x0b,0xd8,0x90,
0x35,0xd5,0xc0,0xa7,0x33,0x06,0x65,0x69,0x45,0x00,0x94,0x56,0x6d,0x98,0x9b,0x76,
0x97,0xfc,0xb2,0xc2,0xb0,0xfe,0xdb,0x20,0xe1,0xeb,0xd6,0xe4,0xdd,0x47,0x4a,0x1d,
0x42,0xed,0x9e,0x6e,0x49,0x3c,0xcd,0x43,0x27,0xd2,0x07,0xd4,0xde,0xc7,0x67,0x18,
0x89,0xcb,0x30,0x1f,0x8d,0xc6,0x8f,0xaa,0xc8,0x74,0xdc,0xc9,0x5d,0x5c,0x31,0xa4,
0x70,0x88,0x61,0x2c,0x9f,0x0d,0x2b,0x87,0x50,0x82,0x54,0x64,0x26,0x7d,0x03,0x40,
0x34,0x4b,0x1c,0x73,0xd1,0xc4,0xfd,0x3b,0xcc,0xfb,0x7f,0xab,0xe6,0x3e,0x5b,0xa5,
0xad,0x04,0x23,0x9c,0x14,0x51,0x22,0xf0,0x29,0x79,0x71,0x7e,0xff,0x8c,0x0e,0xe2,
0x0c,0xef,0xbc,0x72,0x75,0x6f,0x37,0xa1,0xec,0xd3,0x8e,0x62,0x8b,0x86,0x10,0xe8,
0x08,0x77,0x11,0xbe,0x92,0x4f,0x24,0xc5,0x32,0x36,0x9d,0xcf,0xf3,0xa6,0xbb,0xac,
0x5e,0x6c,0xa9,0x13,0x57,0x25,0xb5,0xe3,0xbd,0xa8,0x3a,0x01,0x05,0x59,0x2a,0x46
};
/* simple x + 1 (mod 10) in one step. */
static const int keystep[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
/* simple x - 1 (mod 10) in one step */
static const int ikeystep[] = { 9, 0, 1, 2, 3, 4, 5, 6, 7, 8 };
int skipjack_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey)
{
int x;
_ARGCHK(key != NULL);
_ARGCHK(skey != NULL);
if (keylen != 10) {
return CRYPT_INVALID_KEYSIZE;
}
if (num_rounds != 32 && num_rounds != 0) {
return CRYPT_INVALID_ROUNDS;
}
/* make sure the key is in range for platforms where CHAR_BIT != 8 */
for (x = 0; x < 10; x++) {
skey->skipjack.key[x] = key[x] & 255;
}
return CRYPT_OK;
}
#define RULE_A \
tmp = g_func(w1, &kp, key->skipjack.key); \
w1 = tmp ^ w4 ^ x; \
w4 = w3; w3 = w2; \
w2 = tmp;
#define RULE_B \
tmp = g_func(w1, &kp, key->skipjack.key); \
tmp1 = w4; w4 = w3; \
w3 = w1 ^ w2 ^ x; \
w1 = tmp1; w2 = tmp;
#define RULE_A1 \
tmp = w1 ^ w2 ^ x; \
w1 = ig_func(w2, &kp, key->skipjack.key); \
w2 = w3; w3 = w4; w4 = tmp;
#define RULE_B1 \
tmp = ig_func(w2, &kp, key->skipjack.key); \
w2 = tmp ^ w3 ^ x; \
w3 = w4; w4 = w1; w1 = tmp;
static unsigned g_func(unsigned w, int *kp, unsigned char *key)
{
unsigned char g1,g2;
g1 = (w >> 8) & 255; g2 = w & 255;
g1 ^= sbox[g2^key[*kp]]; *kp = keystep[*kp];
g2 ^= sbox[g1^key[*kp]]; *kp = keystep[*kp];
g1 ^= sbox[g2^key[*kp]]; *kp = keystep[*kp];
g2 ^= sbox[g1^key[*kp]]; *kp = keystep[*kp];
return ((unsigned)g1<<8)|(unsigned)g2;
}
static unsigned ig_func(unsigned w, int *kp, unsigned char *key)
{
unsigned char g1,g2;
g1 = (w >> 8) & 255; g2 = w & 255;
*kp = ikeystep[*kp]; g2 ^= sbox[g1^key[*kp]];
*kp = ikeystep[*kp]; g1 ^= sbox[g2^key[*kp]];
*kp = ikeystep[*kp]; g2 ^= sbox[g1^key[*kp]];
*kp = ikeystep[*kp]; g1 ^= sbox[g2^key[*kp]];
return ((unsigned)g1<<8)|(unsigned)g2;
}
#ifdef CLEAN_STACK
static void _skipjack_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *key)
#else
void skipjack_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *key)
#endif
{
unsigned w1,w2,w3,w4,tmp,tmp1;
int x, kp;
_ARGCHK(pt != NULL);
_ARGCHK(ct != NULL);
_ARGCHK(key != NULL);
/* load block */
w1 = ((unsigned)pt[0]<<8)|pt[1];
w2 = ((unsigned)pt[2]<<8)|pt[3];
w3 = ((unsigned)pt[4]<<8)|pt[5];
w4 = ((unsigned)pt[6]<<8)|pt[7];
/* 8 rounds of RULE A */
for (x = 1, kp = 0; x < 9; x++) {
RULE_A;
}
/* 8 rounds of RULE B */
for (; x < 17; x++) {
RULE_B;
}
/* 8 rounds of RULE A */
for (; x < 25; x++) {
RULE_A;
}
/* 8 rounds of RULE B */
for (; x < 33; x++) {
RULE_B;
}
/* store block */
ct[0] = (w1>>8)&255; ct[1] = w1&255;
ct[2] = (w2>>8)&255; ct[3] = w2&255;
ct[4] = (w3>>8)&255; ct[5] = w3&255;
ct[6] = (w4>>8)&255; ct[7] = w4&255;
}
#ifdef CLEAN_STACK
void skipjack_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *key)
{
_skipjack_ecb_encrypt(pt, ct, key);
burn_stack(sizeof(unsigned) * 8 + sizeof(int) * 2);
}
#endif
#ifdef CLEAN_STACK
static void _skipjack_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *key)
#else
void skipjack_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *key)
#endif
{
unsigned w1,w2,w3,w4,tmp;
int x, kp;
_ARGCHK(pt != NULL);
_ARGCHK(ct != NULL);
_ARGCHK(key != NULL);
/* load block */
w1 = ((unsigned)ct[0]<<8)|ct[1];
w2 = ((unsigned)ct[2]<<8)|ct[3];
w3 = ((unsigned)ct[4]<<8)|ct[5];
w4 = ((unsigned)ct[6]<<8)|ct[7];
/* 8 rounds of RULE B^-1
Note the value "kp = 8" comes from "kp = (32 * 4) mod 10" where 32*4 is 128 which mod 10 is 8
*/
for (x = 32, kp = 8; x > 24; x--) {
RULE_B1;
}
/* 8 rounds of RULE A^-1 */
for (; x > 16; x--) {
RULE_A1;
}
/* 8 rounds of RULE B^-1 */
for (; x > 8; x--) {
RULE_B1;
}
/* 8 rounds of RULE A^-1 */
for (; x > 0; x--) {
RULE_A1;
}
/* store block */
pt[0] = (w1>>8)&255; pt[1] = w1&255;
pt[2] = (w2>>8)&255; pt[3] = w2&255;
pt[4] = (w3>>8)&255; pt[5] = w3&255;
pt[6] = (w4>>8)&255; pt[7] = w4&255;
}
#ifdef CLEAN_STACK
void skipjack_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *key)
{
_skipjack_ecb_decrypt(ct, pt, key);
burn_stack(sizeof(unsigned) * 7 + sizeof(int) * 2);
}
#endif
int skipjack_test(void)
{
#ifndef LTC_TEST
return CRYPT_NOP;
#else
static const struct {
unsigned char key[10], pt[8], ct[8];
} tests[] = {
{
{ 0x00, 0x99, 0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11 },
{ 0x33, 0x22, 0x11, 0x00, 0xdd, 0xcc, 0xbb, 0xaa },
{ 0x25, 0x87, 0xca, 0xe2, 0x7a, 0x12, 0xd3, 0x00 }
}
};
unsigned char buf[2][8];
int x, y, err;
symmetric_key key;
for (x = 0; x < (int)(sizeof(tests) / sizeof(tests[0])); x++) {
/* setup key */
if ((err = skipjack_setup(tests[x].key, 10, 0, &key)) != CRYPT_OK) {
return err;
}
/* encrypt and decrypt */
skipjack_ecb_encrypt(tests[x].pt, buf[0], &key);
skipjack_ecb_decrypt(buf[0], buf[1], &key);
/* compare */
if (memcmp(buf[0], tests[x].ct, 8) != 0 || memcmp(buf[1], tests[x].pt, 8) != 0) {
return CRYPT_FAIL_TESTVECTOR;
}
/* now see if we can encrypt all zero bytes 1000 times, decrypt and come back where we started */
for (y = 0; y < 8; y++) buf[0][y] = 0;
for (y = 0; y < 1000; y++) skipjack_ecb_encrypt(buf[0], buf[0], &key);
for (y = 0; y < 1000; y++) skipjack_ecb_decrypt(buf[0], buf[0], &key);
for (y = 0; y < 8; y++) if (buf[0][y] != 0) return CRYPT_FAIL_TESTVECTOR;
}
return CRYPT_OK;
#endif
}
int skipjack_keysize(int *desired_keysize)
{
_ARGCHK(desired_keysize != NULL);
if (*desired_keysize < 10) {
return CRYPT_INVALID_KEYSIZE;
} else if (*desired_keysize > 10) {
*desired_keysize = 10;
}
return CRYPT_OK;
}
#endif

View File

@ -39,6 +39,14 @@ static const char *err_2_str[] =
};
static const struct {
int mpi_code, ltc_code;
} mpi_to_ltc_codes[] = {
{ MP_OKAY , CRYPT_OK},
{ MP_MEM , CRYPT_MEM},
{ MP_VAL , CRYPT_INVALID_ARG},
};
const char *error_to_string(int err)
{
if (err < 0 || err >= (int)(sizeof(err_2_str)/sizeof(err_2_str[0]))) {
@ -48,3 +56,17 @@ const char *error_to_string(int err)
}
}
/* convert a MPI error to a LTC error (Possibly the most powerful function ever! Oh wait... no) */
int mpi_to_ltc_error(int err)
{
int x;
for (x = 0; x < (int)(sizeof(mpi_to_ltc_codes)/sizeof(mpi_to_ltc_codes[0])); x++) {
if (err == mpi_to_ltc_codes[x].mpi_code) {
return mpi_to_ltc_codes[x].ltc_code;
}
}
return CRYPT_ERROR;
}

43
tiger.c
View File

@ -587,9 +587,9 @@ static void key_schedule(ulong64 *x) {
}
#ifdef CLEAN_STACK
static void _tiger_compress(hash_state *md)
static void _tiger_compress(hash_state *md, unsigned char *buf)
#else
static void tiger_compress(hash_state *md)
static void tiger_compress(hash_state *md, unsigned char *buf)
#endif
{
ulong64 a, b, c, x[8];
@ -599,7 +599,7 @@ static void tiger_compress(hash_state *md)
/* load words */
for (i = 0; i < 8; i++) {
LOAD64L(x[i],&md->tiger.buf[8*i]);
LOAD64L(x[i],&buf[8*i]);
}
a = md->tiger.state[0];
b = md->tiger.state[1];
@ -618,9 +618,9 @@ static void tiger_compress(hash_state *md)
}
#ifdef CLEAN_STACK
static void tiger_compress(hash_state *md)
static void tiger_compress(hash_state *md, unsigned char *buf)
{
_tiger_compress(md);
_tiger_compress(md, buf);
burn_stack(sizeof(ulong64) * 11 + sizeof(unsigned long));
}
#endif
@ -635,32 +635,17 @@ void tiger_init(hash_state *md)
md->tiger.length = 0;
}
void tiger_process(hash_state * md, const unsigned char *buf, unsigned long len)
{
unsigned long n;
_ARGCHK(md != NULL);
_ARGCHK(buf != NULL);
while (len > 0) {
n = MIN(len, (64 - md->tiger.curlen));
memcpy(md->tiger.buf + md->tiger.curlen, buf, (size_t)n);
md->tiger.curlen += n;
buf += n;
len -= n;
HASH_PROCESS(tiger_process, tiger_compress, tiger, 64)
/* is 64 bytes full? */
if (md->tiger.curlen == 64) {
tiger_compress(md);
md->tiger.length += 512; /* add the number of bits not bytes */
md->tiger.curlen = 0;
}
}
}
void tiger_done(hash_state * md, unsigned char *hash)
int tiger_done(hash_state * md, unsigned char *hash)
{
_ARGCHK(md != NULL);
_ARGCHK(hash != NULL);
if (md->tiger.curlen >= sizeof(md->tiger.buf)) {
return CRYPT_INVALID_ARG;
}
/* increase the length of the message */
md->tiger.length += md->tiger.curlen * 8;
@ -674,7 +659,7 @@ void tiger_done(hash_state * md, unsigned char *hash)
while (md->tiger.curlen < 64) {
md->tiger.buf[md->tiger.curlen++] = (unsigned char)0;
}
tiger_compress(md);
tiger_compress(md, md->tiger.buf);
md->tiger.curlen = 0;
}
@ -685,7 +670,7 @@ void tiger_done(hash_state * md, unsigned char *hash)
/* store length */
STORE64L(md->tiger.length, md->tiger.buf+56);
tiger_compress(md);
tiger_compress(md, md->tiger.buf);
/* copy output */
STORE64L(md->tiger.state[0], &hash[0]);
@ -694,6 +679,8 @@ void tiger_done(hash_state * md, unsigned char *hash)
#ifdef CLEAN_STACK
zeromem(md, sizeof(hash_state));
#endif
return CRYPT_OK;
}
int tiger_test(void)

View File

@ -91,6 +91,24 @@ extern "C" {
#endif
#endif
/* define heap macros */
#ifndef CRYPT
/* default to libc stuff */
#ifndef XMALLOC
#define XMALLOC malloc
#define XFREE free
#define XREALLOC realloc
#define XCALLOC calloc
#endif
/* prototypes for our heap functions */
extern void *XMALLOC(size_t n);
extern void *REALLOC(void *p, size_t n);
extern void *XCALLOC(size_t n, size_t s);
extern void XFREE(void *p);
#endif
/* otherwise the bits per digit is calculated automatically from the size of a mp_digit */
#ifndef DIGIT_BIT
#define DIGIT_BIT ((int)((CHAR_BIT * sizeof(mp_digit) - 1))) /* bits per digit */
@ -113,6 +131,9 @@ extern "C" {
#define MP_VAL -3 /* invalid input */
#define MP_RANGE MP_VAL
#define MP_YES 1 /* yes response */
#define MP_NO 0 /* no response */
typedef int mp_err;
/* you'll have to tune these... */
@ -130,11 +151,16 @@ extern int KARATSUBA_MUL_CUTOFF,
/* size of comba arrays, should be at least 2 * 2**(BITS_PER_WORD - BITS_PER_DIGIT*2) */
#define MP_WARRAY (1 << (sizeof(mp_word) * CHAR_BIT - 2 * DIGIT_BIT + 1))
/* the infamous mp_int structure */
typedef struct {
int used, alloc, sign;
mp_digit *dp;
} mp_int;
/* callback for mp_prime_random, should fill dst with random bytes and return how many read [upto len] */
typedef int ltm_prime_callback(unsigned char *dst, int len, void *dat);
#define USED(m) ((m)->used)
#define DIGIT(m,k) ((m)->dp[(k)])
#define SIGN(m) ((m)->sign)
@ -168,9 +194,9 @@ int mp_grow(mp_int *a, int size);
int mp_init_size(mp_int *a, int size);
/* ---> Basic Manipulations <--- */
#define mp_iszero(a) (((a)->used == 0) ? 1 : 0)
#define mp_iseven(a) (((a)->used > 0 && (((a)->dp[0] & 1) == 0)) ? 1 : 0)
#define mp_isodd(a) (((a)->used > 0 && (((a)->dp[0] & 1) == 1)) ? 1 : 0)
#define mp_iszero(a) (((a)->used == 0) ? MP_YES : MP_NO)
#define mp_iseven(a) (((a)->used > 0 && (((a)->dp[0] & 1) == 0)) ? MP_YES : MP_NO)
#define mp_isodd(a) (((a)->used > 0 && (((a)->dp[0] & 1) == 1)) ? MP_YES : MP_NO)
/* set to zero */
void mp_zero(mp_int *a);
@ -179,7 +205,7 @@ void mp_zero(mp_int *a);
void mp_set(mp_int *a, mp_digit b);
/* set a 32-bit const */
int mp_set_int(mp_int *a, unsigned int b);
int mp_set_int(mp_int *a, unsigned long b);
/* copy, b = a */
int mp_copy(mp_int *a, mp_int *b);
@ -219,6 +245,8 @@ int mp_2expt(mp_int *a, int b);
/* Counts the number of lsbs which are zero before the first zero bit */
int mp_cnt_lsb(mp_int *a);
/* I Love Earth! */
/* makes a pseudo-random int of a given size */
int mp_rand(mp_int *a, int digits);
@ -392,6 +420,11 @@ int mp_prime_fermat(mp_int *a, mp_int *b, int *result);
*/
int mp_prime_miller_rabin(mp_int *a, mp_int *b, int *result);
/* This gives [for a given bit size] the number of trials required
* such that Miller-Rabin gives a prob of failure lower than 2^-96
*/
int mp_prime_rabin_miller_trials(int size);
/* performs t rounds of Miller-Rabin on "a" using the first
* t prime bases. Also performs an initial sieve of trial
* division. Determines if "a" is prime with probability
@ -408,6 +441,18 @@ int mp_prime_is_prime(mp_int *a, int t, int *result);
*/
int mp_prime_next_prime(mp_int *a, int t, int bbs_style);
/* makes a truly random prime of a given size (bytes),
* call with bbs = 1 if you want it to be congruent to 3 mod 4
*
* You have to supply a callback which fills in a buffer with random bytes. "dat" is a parameter you can
* have passed to the callback (e.g. a state or something). This function doesn't use "dat" itself
* so it can be NULL
*
* The prime generated will be larger than 2^(8*size).
*/
int mp_prime_random(mp_int *a, int t, int size, int bbs, ltm_prime_callback cb, void *dat);
/* ---> radix conversion <--- */
int mp_count_bits(mp_int *a);
@ -464,5 +509,5 @@ extern const char *mp_s_rmap;
}
#endif
#endif /* ?BN_H_ */
#endif

325
twofish.c
View File

@ -3,6 +3,13 @@
#ifdef TWOFISH
/* first TWOFISH_ALL_TABLES must ensure TWOFISH_TABLES is defined */
#ifdef TWOFISH_ALL_TABLES
#ifndef TWOFISH_TABLES
#define TWOFISH_TABLES
#endif
#endif
const struct _cipher_descriptor twofish_desc =
{
"twofish",
@ -44,213 +51,21 @@ static const unsigned char qord[4][5] = {
};
#ifdef TWOFISH_TABLES
static const unsigned char SBOX[2][256] = {
{
0xa9, 0x67, 0xb3, 0xe8, 0x04, 0xfd, 0xa3, 0x76, 0x9a, 0x92,
0x80, 0x78, 0xe4, 0xdd, 0xd1, 0x38, 0x0d, 0xc6, 0x35, 0x98,
0x18, 0xf7, 0xec, 0x6c, 0x43, 0x75, 0x37, 0x26, 0xfa, 0x13,
0x94, 0x48, 0xf2, 0xd0, 0x8b, 0x30, 0x84, 0x54, 0xdf, 0x23,
0x19, 0x5b, 0x3d, 0x59, 0xf3, 0xae, 0xa2, 0x82, 0x63, 0x01,
0x83, 0x2e, 0xd9, 0x51, 0x9b, 0x7c, 0xa6, 0xeb, 0xa5, 0xbe,
0x16, 0x0c, 0xe3, 0x61, 0xc0, 0x8c, 0x3a, 0xf5, 0x73, 0x2c,
0x25, 0x0b, 0xbb, 0x4e, 0x89, 0x6b, 0x53, 0x6a, 0xb4, 0xf1,
0xe1, 0xe6, 0xbd, 0x45, 0xe2, 0xf4, 0xb6, 0x66, 0xcc, 0x95,
0x03, 0x56, 0xd4, 0x1c, 0x1e, 0xd7, 0xfb, 0xc3, 0x8e, 0xb5,
0xe9, 0xcf, 0xbf, 0xba, 0xea, 0x77, 0x39, 0xaf, 0x33, 0xc9,
0x62, 0x71, 0x81, 0x79, 0x09, 0xad, 0x24, 0xcd, 0xf9, 0xd8,
0xe5, 0xc5, 0xb9, 0x4d, 0x44, 0x08, 0x86, 0xe7, 0xa1, 0x1d,
0xaa, 0xed, 0x06, 0x70, 0xb2, 0xd2, 0x41, 0x7b, 0xa0, 0x11,
0x31, 0xc2, 0x27, 0x90, 0x20, 0xf6, 0x60, 0xff, 0x96, 0x5c,
0xb1, 0xab, 0x9e, 0x9c, 0x52, 0x1b, 0x5f, 0x93, 0x0a, 0xef,
0x91, 0x85, 0x49, 0xee, 0x2d, 0x4f, 0x8f, 0x3b, 0x47, 0x87,
0x6d, 0x46, 0xd6, 0x3e, 0x69, 0x64, 0x2a, 0xce, 0xcb, 0x2f,
0xfc, 0x97, 0x05, 0x7a, 0xac, 0x7f, 0xd5, 0x1a, 0x4b, 0x0e,
0xa7, 0x5a, 0x28, 0x14, 0x3f, 0x29, 0x88, 0x3c, 0x4c, 0x02,
0xb8, 0xda, 0xb0, 0x17, 0x55, 0x1f, 0x8a, 0x7d, 0x57, 0xc7,
0x8d, 0x74, 0xb7, 0xc4, 0x9f, 0x72, 0x7e, 0x15, 0x22, 0x12,
0x58, 0x07, 0x99, 0x34, 0x6e, 0x50, 0xde, 0x68, 0x65, 0xbc,
0xdb, 0xf8, 0xc8, 0xa8, 0x2b, 0x40, 0xdc, 0xfe, 0x32, 0xa4,
0xca, 0x10, 0x21, 0xf0, 0xd3, 0x5d, 0x0f, 0x00, 0x6f, 0x9d,
0x36, 0x42, 0x4a, 0x5e, 0xc1, 0xe0},
{
0x75, 0xf3, 0xc6, 0xf4, 0xdb, 0x7b, 0xfb, 0xc8, 0x4a, 0xd3,
0xe6, 0x6b, 0x45, 0x7d, 0xe8, 0x4b, 0xd6, 0x32, 0xd8, 0xfd,
0x37, 0x71, 0xf1, 0xe1, 0x30, 0x0f, 0xf8, 0x1b, 0x87, 0xfa,
0x06, 0x3f, 0x5e, 0xba, 0xae, 0x5b, 0x8a, 0x00, 0xbc, 0x9d,
0x6d, 0xc1, 0xb1, 0x0e, 0x80, 0x5d, 0xd2, 0xd5, 0xa0, 0x84,
0x07, 0x14, 0xb5, 0x90, 0x2c, 0xa3, 0xb2, 0x73, 0x4c, 0x54,
0x92, 0x74, 0x36, 0x51, 0x38, 0xb0, 0xbd, 0x5a, 0xfc, 0x60,
0x62, 0x96, 0x6c, 0x42, 0xf7, 0x10, 0x7c, 0x28, 0x27, 0x8c,
0x13, 0x95, 0x9c, 0xc7, 0x24, 0x46, 0x3b, 0x70, 0xca, 0xe3,
0x85, 0xcb, 0x11, 0xd0, 0x93, 0xb8, 0xa6, 0x83, 0x20, 0xff,
0x9f, 0x77, 0xc3, 0xcc, 0x03, 0x6f, 0x08, 0xbf, 0x40, 0xe7,
0x2b, 0xe2, 0x79, 0x0c, 0xaa, 0x82, 0x41, 0x3a, 0xea, 0xb9,
0xe4, 0x9a, 0xa4, 0x97, 0x7e, 0xda, 0x7a, 0x17, 0x66, 0x94,
0xa1, 0x1d, 0x3d, 0xf0, 0xde, 0xb3, 0x0b, 0x72, 0xa7, 0x1c,
0xef, 0xd1, 0x53, 0x3e, 0x8f, 0x33, 0x26, 0x5f, 0xec, 0x76,
0x2a, 0x49, 0x81, 0x88, 0xee, 0x21, 0xc4, 0x1a, 0xeb, 0xd9,
0xc5, 0x39, 0x99, 0xcd, 0xad, 0x31, 0x8b, 0x01, 0x18, 0x23,
0xdd, 0x1f, 0x4e, 0x2d, 0xf9, 0x48, 0x4f, 0xf2, 0x65, 0x8e,
0x78, 0x5c, 0x58, 0x19, 0x8d, 0xe5, 0x98, 0x57, 0x67, 0x7f,
0x05, 0x64, 0xaf, 0x63, 0xb6, 0xfe, 0xf5, 0xb7, 0x3c, 0xa5,
0xce, 0xe9, 0x68, 0x44, 0xe0, 0x4d, 0x43, 0x69, 0x29, 0x2e,
0xac, 0x15, 0x59, 0xa8, 0x0a, 0x9e, 0x6e, 0x47, 0xdf, 0x34,
0x35, 0x6a, 0xcf, 0xdc, 0x22, 0xc9, 0xc0, 0x9b, 0x89, 0xd4,
0xed, 0xab, 0x12, 0xa2, 0x0d, 0x52, 0xbb, 0x02, 0x2f, 0xa9,
0xd7, 0x61, 0x1e, 0xb4, 0x50, 0x04, 0xf6, 0xc2, 0x16, 0x25,
0x86, 0x56, 0x55, 0x09, 0xbe, 0x91}
};
static const ulong32 mds_tab[4][256] = {
{
0x00000000UL, 0xefef5b01UL, 0xb7b7b602UL, 0x5858ed03UL, 0x07070504UL, 0xe8e85e05UL, 0xb0b0b306UL, 0x5f5fe807UL,
0x0e0e0a08UL, 0xe1e15109UL, 0xb9b9bc0aUL, 0x5656e70bUL, 0x09090f0cUL, 0xe6e6540dUL, 0xbebeb90eUL, 0x5151e20fUL,
0x1c1c1410UL, 0xf3f34f11UL, 0xababa212UL, 0x4444f913UL, 0x1b1b1114UL, 0xf4f44a15UL, 0xacaca716UL, 0x4343fc17UL,
0x12121e18UL, 0xfdfd4519UL, 0xa5a5a81aUL, 0x4a4af31bUL, 0x15151b1cUL, 0xfafa401dUL, 0xa2a2ad1eUL, 0x4d4df61fUL,
0x38382820UL, 0xd7d77321UL, 0x8f8f9e22UL, 0x6060c523UL, 0x3f3f2d24UL, 0xd0d07625UL, 0x88889b26UL, 0x6767c027UL,
0x36362228UL, 0xd9d97929UL, 0x8181942aUL, 0x6e6ecf2bUL, 0x3131272cUL, 0xdede7c2dUL, 0x8686912eUL, 0x6969ca2fUL,
0x24243c30UL, 0xcbcb6731UL, 0x93938a32UL, 0x7c7cd133UL, 0x23233934UL, 0xcccc6235UL, 0x94948f36UL, 0x7b7bd437UL,
0x2a2a3638UL, 0xc5c56d39UL, 0x9d9d803aUL, 0x7272db3bUL, 0x2d2d333cUL, 0xc2c2683dUL, 0x9a9a853eUL, 0x7575de3fUL,
0x70705040UL, 0x9f9f0b41UL, 0xc7c7e642UL, 0x2828bd43UL, 0x77775544UL, 0x98980e45UL, 0xc0c0e346UL, 0x2f2fb847UL,
0x7e7e5a48UL, 0x91910149UL, 0xc9c9ec4aUL, 0x2626b74bUL, 0x79795f4cUL, 0x9696044dUL, 0xcecee94eUL, 0x2121b24fUL,
0x6c6c4450UL, 0x83831f51UL, 0xdbdbf252UL, 0x3434a953UL, 0x6b6b4154UL, 0x84841a55UL, 0xdcdcf756UL, 0x3333ac57UL,
0x62624e58UL, 0x8d8d1559UL, 0xd5d5f85aUL, 0x3a3aa35bUL, 0x65654b5cUL, 0x8a8a105dUL, 0xd2d2fd5eUL, 0x3d3da65fUL,
0x48487860UL, 0xa7a72361UL, 0xffffce62UL, 0x10109563UL, 0x4f4f7d64UL, 0xa0a02665UL, 0xf8f8cb66UL, 0x17179067UL,
0x46467268UL, 0xa9a92969UL, 0xf1f1c46aUL, 0x1e1e9f6bUL, 0x4141776cUL, 0xaeae2c6dUL, 0xf6f6c16eUL, 0x19199a6fUL,
0x54546c70UL, 0xbbbb3771UL, 0xe3e3da72UL, 0x0c0c8173UL, 0x53536974UL, 0xbcbc3275UL, 0xe4e4df76UL, 0x0b0b8477UL,
0x5a5a6678UL, 0xb5b53d79UL, 0xededd07aUL, 0x02028b7bUL, 0x5d5d637cUL, 0xb2b2387dUL, 0xeaead57eUL, 0x05058e7fUL,
0xe0e0a080UL, 0x0f0ffb81UL, 0x57571682UL, 0xb8b84d83UL, 0xe7e7a584UL, 0x0808fe85UL, 0x50501386UL, 0xbfbf4887UL,
0xeeeeaa88UL, 0x0101f189UL, 0x59591c8aUL, 0xb6b6478bUL, 0xe9e9af8cUL, 0x0606f48dUL, 0x5e5e198eUL, 0xb1b1428fUL,
0xfcfcb490UL, 0x1313ef91UL, 0x4b4b0292UL, 0xa4a45993UL, 0xfbfbb194UL, 0x1414ea95UL, 0x4c4c0796UL, 0xa3a35c97UL,
0xf2f2be98UL, 0x1d1de599UL, 0x4545089aUL, 0xaaaa539bUL, 0xf5f5bb9cUL, 0x1a1ae09dUL, 0x42420d9eUL, 0xadad569fUL,
0xd8d888a0UL, 0x3737d3a1UL, 0x6f6f3ea2UL, 0x808065a3UL, 0xdfdf8da4UL, 0x3030d6a5UL, 0x68683ba6UL, 0x878760a7UL,
0xd6d682a8UL, 0x3939d9a9UL, 0x616134aaUL, 0x8e8e6fabUL, 0xd1d187acUL, 0x3e3edcadUL, 0x666631aeUL, 0x89896aafUL,
0xc4c49cb0UL, 0x2b2bc7b1UL, 0x73732ab2UL, 0x9c9c71b3UL, 0xc3c399b4UL, 0x2c2cc2b5UL, 0x74742fb6UL, 0x9b9b74b7UL,
0xcaca96b8UL, 0x2525cdb9UL, 0x7d7d20baUL, 0x92927bbbUL, 0xcdcd93bcUL, 0x2222c8bdUL, 0x7a7a25beUL, 0x95957ebfUL,
0x9090f0c0UL, 0x7f7fabc1UL, 0x272746c2UL, 0xc8c81dc3UL, 0x9797f5c4UL, 0x7878aec5UL, 0x202043c6UL, 0xcfcf18c7UL,
0x9e9efac8UL, 0x7171a1c9UL, 0x29294ccaUL, 0xc6c617cbUL, 0x9999ffccUL, 0x7676a4cdUL, 0x2e2e49ceUL, 0xc1c112cfUL,
0x8c8ce4d0UL, 0x6363bfd1UL, 0x3b3b52d2UL, 0xd4d409d3UL, 0x8b8be1d4UL, 0x6464bad5UL, 0x3c3c57d6UL, 0xd3d30cd7UL,
0x8282eed8UL, 0x6d6db5d9UL, 0x353558daUL, 0xdada03dbUL, 0x8585ebdcUL, 0x6a6ab0ddUL, 0x32325ddeUL, 0xdddd06dfUL,
0xa8a8d8e0UL, 0x474783e1UL, 0x1f1f6ee2UL, 0xf0f035e3UL, 0xafafdde4UL, 0x404086e5UL, 0x18186be6UL, 0xf7f730e7UL,
0xa6a6d2e8UL, 0x494989e9UL, 0x111164eaUL, 0xfefe3febUL, 0xa1a1d7ecUL, 0x4e4e8cedUL, 0x161661eeUL, 0xf9f93aefUL,
0xb4b4ccf0UL, 0x5b5b97f1UL, 0x03037af2UL, 0xecec21f3UL, 0xb3b3c9f4UL, 0x5c5c92f5UL, 0x04047ff6UL, 0xebeb24f7UL,
0xbabac6f8UL, 0x55559df9UL, 0x0d0d70faUL, 0xe2e22bfbUL, 0xbdbdc3fcUL, 0x525298fdUL, 0x0a0a75feUL, 0xe5e52effUL
},
{
0x00000000UL, 0x015befefUL, 0x02b6b7b7UL, 0x03ed5858UL, 0x04050707UL, 0x055ee8e8UL, 0x06b3b0b0UL, 0x07e85f5fUL,
0x080a0e0eUL, 0x0951e1e1UL, 0x0abcb9b9UL, 0x0be75656UL, 0x0c0f0909UL, 0x0d54e6e6UL, 0x0eb9bebeUL, 0x0fe25151UL,
0x10141c1cUL, 0x114ff3f3UL, 0x12a2ababUL, 0x13f94444UL, 0x14111b1bUL, 0x154af4f4UL, 0x16a7acacUL, 0x17fc4343UL,
0x181e1212UL, 0x1945fdfdUL, 0x1aa8a5a5UL, 0x1bf34a4aUL, 0x1c1b1515UL, 0x1d40fafaUL, 0x1eada2a2UL, 0x1ff64d4dUL,
0x20283838UL, 0x2173d7d7UL, 0x229e8f8fUL, 0x23c56060UL, 0x242d3f3fUL, 0x2576d0d0UL, 0x269b8888UL, 0x27c06767UL,
0x28223636UL, 0x2979d9d9UL, 0x2a948181UL, 0x2bcf6e6eUL, 0x2c273131UL, 0x2d7cdedeUL, 0x2e918686UL, 0x2fca6969UL,
0x303c2424UL, 0x3167cbcbUL, 0x328a9393UL, 0x33d17c7cUL, 0x34392323UL, 0x3562ccccUL, 0x368f9494UL, 0x37d47b7bUL,
0x38362a2aUL, 0x396dc5c5UL, 0x3a809d9dUL, 0x3bdb7272UL, 0x3c332d2dUL, 0x3d68c2c2UL, 0x3e859a9aUL, 0x3fde7575UL,
0x40507070UL, 0x410b9f9fUL, 0x42e6c7c7UL, 0x43bd2828UL, 0x44557777UL, 0x450e9898UL, 0x46e3c0c0UL, 0x47b82f2fUL,
0x485a7e7eUL, 0x49019191UL, 0x4aecc9c9UL, 0x4bb72626UL, 0x4c5f7979UL, 0x4d049696UL, 0x4ee9ceceUL, 0x4fb22121UL,
0x50446c6cUL, 0x511f8383UL, 0x52f2dbdbUL, 0x53a93434UL, 0x54416b6bUL, 0x551a8484UL, 0x56f7dcdcUL, 0x57ac3333UL,
0x584e6262UL, 0x59158d8dUL, 0x5af8d5d5UL, 0x5ba33a3aUL, 0x5c4b6565UL, 0x5d108a8aUL, 0x5efdd2d2UL, 0x5fa63d3dUL,
0x60784848UL, 0x6123a7a7UL, 0x62ceffffUL, 0x63951010UL, 0x647d4f4fUL, 0x6526a0a0UL, 0x66cbf8f8UL, 0x67901717UL,
0x68724646UL, 0x6929a9a9UL, 0x6ac4f1f1UL, 0x6b9f1e1eUL, 0x6c774141UL, 0x6d2caeaeUL, 0x6ec1f6f6UL, 0x6f9a1919UL,
0x706c5454UL, 0x7137bbbbUL, 0x72dae3e3UL, 0x73810c0cUL, 0x74695353UL, 0x7532bcbcUL, 0x76dfe4e4UL, 0x77840b0bUL,
0x78665a5aUL, 0x793db5b5UL, 0x7ad0ededUL, 0x7b8b0202UL, 0x7c635d5dUL, 0x7d38b2b2UL, 0x7ed5eaeaUL, 0x7f8e0505UL,
0x80a0e0e0UL, 0x81fb0f0fUL, 0x82165757UL, 0x834db8b8UL, 0x84a5e7e7UL, 0x85fe0808UL, 0x86135050UL, 0x8748bfbfUL,
0x88aaeeeeUL, 0x89f10101UL, 0x8a1c5959UL, 0x8b47b6b6UL, 0x8cafe9e9UL, 0x8df40606UL, 0x8e195e5eUL, 0x8f42b1b1UL,
0x90b4fcfcUL, 0x91ef1313UL, 0x92024b4bUL, 0x9359a4a4UL, 0x94b1fbfbUL, 0x95ea1414UL, 0x96074c4cUL, 0x975ca3a3UL,
0x98bef2f2UL, 0x99e51d1dUL, 0x9a084545UL, 0x9b53aaaaUL, 0x9cbbf5f5UL, 0x9de01a1aUL, 0x9e0d4242UL, 0x9f56adadUL,
0xa088d8d8UL, 0xa1d33737UL, 0xa23e6f6fUL, 0xa3658080UL, 0xa48ddfdfUL, 0xa5d63030UL, 0xa63b6868UL, 0xa7608787UL,
0xa882d6d6UL, 0xa9d93939UL, 0xaa346161UL, 0xab6f8e8eUL, 0xac87d1d1UL, 0xaddc3e3eUL, 0xae316666UL, 0xaf6a8989UL,
0xb09cc4c4UL, 0xb1c72b2bUL, 0xb22a7373UL, 0xb3719c9cUL, 0xb499c3c3UL, 0xb5c22c2cUL, 0xb62f7474UL, 0xb7749b9bUL,
0xb896cacaUL, 0xb9cd2525UL, 0xba207d7dUL, 0xbb7b9292UL, 0xbc93cdcdUL, 0xbdc82222UL, 0xbe257a7aUL, 0xbf7e9595UL,
0xc0f09090UL, 0xc1ab7f7fUL, 0xc2462727UL, 0xc31dc8c8UL, 0xc4f59797UL, 0xc5ae7878UL, 0xc6432020UL, 0xc718cfcfUL,
0xc8fa9e9eUL, 0xc9a17171UL, 0xca4c2929UL, 0xcb17c6c6UL, 0xccff9999UL, 0xcda47676UL, 0xce492e2eUL, 0xcf12c1c1UL,
0xd0e48c8cUL, 0xd1bf6363UL, 0xd2523b3bUL, 0xd309d4d4UL, 0xd4e18b8bUL, 0xd5ba6464UL, 0xd6573c3cUL, 0xd70cd3d3UL,
0xd8ee8282UL, 0xd9b56d6dUL, 0xda583535UL, 0xdb03dadaUL, 0xdceb8585UL, 0xddb06a6aUL, 0xde5d3232UL, 0xdf06ddddUL,
0xe0d8a8a8UL, 0xe1834747UL, 0xe26e1f1fUL, 0xe335f0f0UL, 0xe4ddafafUL, 0xe5864040UL, 0xe66b1818UL, 0xe730f7f7UL,
0xe8d2a6a6UL, 0xe9894949UL, 0xea641111UL, 0xeb3ffefeUL, 0xecd7a1a1UL, 0xed8c4e4eUL, 0xee611616UL, 0xef3af9f9UL,
0xf0ccb4b4UL, 0xf1975b5bUL, 0xf27a0303UL, 0xf321ececUL, 0xf4c9b3b3UL, 0xf5925c5cUL, 0xf67f0404UL, 0xf724ebebUL,
0xf8c6babaUL, 0xf99d5555UL, 0xfa700d0dUL, 0xfb2be2e2UL, 0xfcc3bdbdUL, 0xfd985252UL, 0xfe750a0aUL, 0xff2ee5e5UL
},
{
0x00000000UL, 0xef01ef5bUL, 0xb702b7b6UL, 0x580358edUL, 0x07040705UL, 0xe805e85eUL, 0xb006b0b3UL, 0x5f075fe8UL,
0x0e080e0aUL, 0xe109e151UL, 0xb90ab9bcUL, 0x560b56e7UL, 0x090c090fUL, 0xe60de654UL, 0xbe0ebeb9UL, 0x510f51e2UL,
0x1c101c14UL, 0xf311f34fUL, 0xab12aba2UL, 0x441344f9UL, 0x1b141b11UL, 0xf415f44aUL, 0xac16aca7UL, 0x431743fcUL,
0x1218121eUL, 0xfd19fd45UL, 0xa51aa5a8UL, 0x4a1b4af3UL, 0x151c151bUL, 0xfa1dfa40UL, 0xa21ea2adUL, 0x4d1f4df6UL,
0x38203828UL, 0xd721d773UL, 0x8f228f9eUL, 0x602360c5UL, 0x3f243f2dUL, 0xd025d076UL, 0x8826889bUL, 0x672767c0UL,
0x36283622UL, 0xd929d979UL, 0x812a8194UL, 0x6e2b6ecfUL, 0x312c3127UL, 0xde2dde7cUL, 0x862e8691UL, 0x692f69caUL,
0x2430243cUL, 0xcb31cb67UL, 0x9332938aUL, 0x7c337cd1UL, 0x23342339UL, 0xcc35cc62UL, 0x9436948fUL, 0x7b377bd4UL,
0x2a382a36UL, 0xc539c56dUL, 0x9d3a9d80UL, 0x723b72dbUL, 0x2d3c2d33UL, 0xc23dc268UL, 0x9a3e9a85UL, 0x753f75deUL,
0x70407050UL, 0x9f419f0bUL, 0xc742c7e6UL, 0x284328bdUL, 0x77447755UL, 0x9845980eUL, 0xc046c0e3UL, 0x2f472fb8UL,
0x7e487e5aUL, 0x91499101UL, 0xc94ac9ecUL, 0x264b26b7UL, 0x794c795fUL, 0x964d9604UL, 0xce4ecee9UL, 0x214f21b2UL,
0x6c506c44UL, 0x8351831fUL, 0xdb52dbf2UL, 0x345334a9UL, 0x6b546b41UL, 0x8455841aUL, 0xdc56dcf7UL, 0x335733acUL,
0x6258624eUL, 0x8d598d15UL, 0xd55ad5f8UL, 0x3a5b3aa3UL, 0x655c654bUL, 0x8a5d8a10UL, 0xd25ed2fdUL, 0x3d5f3da6UL,
0x48604878UL, 0xa761a723UL, 0xff62ffceUL, 0x10631095UL, 0x4f644f7dUL, 0xa065a026UL, 0xf866f8cbUL, 0x17671790UL,
0x46684672UL, 0xa969a929UL, 0xf16af1c4UL, 0x1e6b1e9fUL, 0x416c4177UL, 0xae6dae2cUL, 0xf66ef6c1UL, 0x196f199aUL,
0x5470546cUL, 0xbb71bb37UL, 0xe372e3daUL, 0x0c730c81UL, 0x53745369UL, 0xbc75bc32UL, 0xe476e4dfUL, 0x0b770b84UL,
0x5a785a66UL, 0xb579b53dUL, 0xed7aedd0UL, 0x027b028bUL, 0x5d7c5d63UL, 0xb27db238UL, 0xea7eead5UL, 0x057f058eUL,
0xe080e0a0UL, 0x0f810ffbUL, 0x57825716UL, 0xb883b84dUL, 0xe784e7a5UL, 0x088508feUL, 0x50865013UL, 0xbf87bf48UL,
0xee88eeaaUL, 0x018901f1UL, 0x598a591cUL, 0xb68bb647UL, 0xe98ce9afUL, 0x068d06f4UL, 0x5e8e5e19UL, 0xb18fb142UL,
0xfc90fcb4UL, 0x139113efUL, 0x4b924b02UL, 0xa493a459UL, 0xfb94fbb1UL, 0x149514eaUL, 0x4c964c07UL, 0xa397a35cUL,
0xf298f2beUL, 0x1d991de5UL, 0x459a4508UL, 0xaa9baa53UL, 0xf59cf5bbUL, 0x1a9d1ae0UL, 0x429e420dUL, 0xad9fad56UL,
0xd8a0d888UL, 0x37a137d3UL, 0x6fa26f3eUL, 0x80a38065UL, 0xdfa4df8dUL, 0x30a530d6UL, 0x68a6683bUL, 0x87a78760UL,
0xd6a8d682UL, 0x39a939d9UL, 0x61aa6134UL, 0x8eab8e6fUL, 0xd1acd187UL, 0x3ead3edcUL, 0x66ae6631UL, 0x89af896aUL,
0xc4b0c49cUL, 0x2bb12bc7UL, 0x73b2732aUL, 0x9cb39c71UL, 0xc3b4c399UL, 0x2cb52cc2UL, 0x74b6742fUL, 0x9bb79b74UL,
0xcab8ca96UL, 0x25b925cdUL, 0x7dba7d20UL, 0x92bb927bUL, 0xcdbccd93UL, 0x22bd22c8UL, 0x7abe7a25UL, 0x95bf957eUL,
0x90c090f0UL, 0x7fc17fabUL, 0x27c22746UL, 0xc8c3c81dUL, 0x97c497f5UL, 0x78c578aeUL, 0x20c62043UL, 0xcfc7cf18UL,
0x9ec89efaUL, 0x71c971a1UL, 0x29ca294cUL, 0xc6cbc617UL, 0x99cc99ffUL, 0x76cd76a4UL, 0x2ece2e49UL, 0xc1cfc112UL,
0x8cd08ce4UL, 0x63d163bfUL, 0x3bd23b52UL, 0xd4d3d409UL, 0x8bd48be1UL, 0x64d564baUL, 0x3cd63c57UL, 0xd3d7d30cUL,
0x82d882eeUL, 0x6dd96db5UL, 0x35da3558UL, 0xdadbda03UL, 0x85dc85ebUL, 0x6add6ab0UL, 0x32de325dUL, 0xdddfdd06UL,
0xa8e0a8d8UL, 0x47e14783UL, 0x1fe21f6eUL, 0xf0e3f035UL, 0xafe4afddUL, 0x40e54086UL, 0x18e6186bUL, 0xf7e7f730UL,
0xa6e8a6d2UL, 0x49e94989UL, 0x11ea1164UL, 0xfeebfe3fUL, 0xa1eca1d7UL, 0x4eed4e8cUL, 0x16ee1661UL, 0xf9eff93aUL,
0xb4f0b4ccUL, 0x5bf15b97UL, 0x03f2037aUL, 0xecf3ec21UL, 0xb3f4b3c9UL, 0x5cf55c92UL, 0x04f6047fUL, 0xebf7eb24UL,
0xbaf8bac6UL, 0x55f9559dUL, 0x0dfa0d70UL, 0xe2fbe22bUL, 0xbdfcbdc3UL, 0x52fd5298UL, 0x0afe0a75UL, 0xe5ffe52eUL
},
{
0x00000000UL, 0x5bef015bUL, 0xb6b702b6UL, 0xed5803edUL, 0x05070405UL, 0x5ee8055eUL, 0xb3b006b3UL, 0xe85f07e8UL,
0x0a0e080aUL, 0x51e10951UL, 0xbcb90abcUL, 0xe7560be7UL, 0x0f090c0fUL, 0x54e60d54UL, 0xb9be0eb9UL, 0xe2510fe2UL,
0x141c1014UL, 0x4ff3114fUL, 0xa2ab12a2UL, 0xf94413f9UL, 0x111b1411UL, 0x4af4154aUL, 0xa7ac16a7UL, 0xfc4317fcUL,
0x1e12181eUL, 0x45fd1945UL, 0xa8a51aa8UL, 0xf34a1bf3UL, 0x1b151c1bUL, 0x40fa1d40UL, 0xada21eadUL, 0xf64d1ff6UL,
0x28382028UL, 0x73d72173UL, 0x9e8f229eUL, 0xc56023c5UL, 0x2d3f242dUL, 0x76d02576UL, 0x9b88269bUL, 0xc06727c0UL,
0x22362822UL, 0x79d92979UL, 0x94812a94UL, 0xcf6e2bcfUL, 0x27312c27UL, 0x7cde2d7cUL, 0x91862e91UL, 0xca692fcaUL,
0x3c24303cUL, 0x67cb3167UL, 0x8a93328aUL, 0xd17c33d1UL, 0x39233439UL, 0x62cc3562UL, 0x8f94368fUL, 0xd47b37d4UL,
0x362a3836UL, 0x6dc5396dUL, 0x809d3a80UL, 0xdb723bdbUL, 0x332d3c33UL, 0x68c23d68UL, 0x859a3e85UL, 0xde753fdeUL,
0x50704050UL, 0x0b9f410bUL, 0xe6c742e6UL, 0xbd2843bdUL, 0x55774455UL, 0x0e98450eUL, 0xe3c046e3UL, 0xb82f47b8UL,
0x5a7e485aUL, 0x01914901UL, 0xecc94aecUL, 0xb7264bb7UL, 0x5f794c5fUL, 0x04964d04UL, 0xe9ce4ee9UL, 0xb2214fb2UL,
0x446c5044UL, 0x1f83511fUL, 0xf2db52f2UL, 0xa93453a9UL, 0x416b5441UL, 0x1a84551aUL, 0xf7dc56f7UL, 0xac3357acUL,
0x4e62584eUL, 0x158d5915UL, 0xf8d55af8UL, 0xa33a5ba3UL, 0x4b655c4bUL, 0x108a5d10UL, 0xfdd25efdUL, 0xa63d5fa6UL,
0x78486078UL, 0x23a76123UL, 0xceff62ceUL, 0x95106395UL, 0x7d4f647dUL, 0x26a06526UL, 0xcbf866cbUL, 0x90176790UL,
0x72466872UL, 0x29a96929UL, 0xc4f16ac4UL, 0x9f1e6b9fUL, 0x77416c77UL, 0x2cae6d2cUL, 0xc1f66ec1UL, 0x9a196f9aUL,
0x6c54706cUL, 0x37bb7137UL, 0xdae372daUL, 0x810c7381UL, 0x69537469UL, 0x32bc7532UL, 0xdfe476dfUL, 0x840b7784UL,
0x665a7866UL, 0x3db5793dUL, 0xd0ed7ad0UL, 0x8b027b8bUL, 0x635d7c63UL, 0x38b27d38UL, 0xd5ea7ed5UL, 0x8e057f8eUL,
0xa0e080a0UL, 0xfb0f81fbUL, 0x16578216UL, 0x4db8834dUL, 0xa5e784a5UL, 0xfe0885feUL, 0x13508613UL, 0x48bf8748UL,
0xaaee88aaUL, 0xf10189f1UL, 0x1c598a1cUL, 0x47b68b47UL, 0xafe98cafUL, 0xf4068df4UL, 0x195e8e19UL, 0x42b18f42UL,
0xb4fc90b4UL, 0xef1391efUL, 0x024b9202UL, 0x59a49359UL, 0xb1fb94b1UL, 0xea1495eaUL, 0x074c9607UL, 0x5ca3975cUL,
0xbef298beUL, 0xe51d99e5UL, 0x08459a08UL, 0x53aa9b53UL, 0xbbf59cbbUL, 0xe01a9de0UL, 0x0d429e0dUL, 0x56ad9f56UL,
0x88d8a088UL, 0xd337a1d3UL, 0x3e6fa23eUL, 0x6580a365UL, 0x8ddfa48dUL, 0xd630a5d6UL, 0x3b68a63bUL, 0x6087a760UL,
0x82d6a882UL, 0xd939a9d9UL, 0x3461aa34UL, 0x6f8eab6fUL, 0x87d1ac87UL, 0xdc3eaddcUL, 0x3166ae31UL, 0x6a89af6aUL,
0x9cc4b09cUL, 0xc72bb1c7UL, 0x2a73b22aUL, 0x719cb371UL, 0x99c3b499UL, 0xc22cb5c2UL, 0x2f74b62fUL, 0x749bb774UL,
0x96cab896UL, 0xcd25b9cdUL, 0x207dba20UL, 0x7b92bb7bUL, 0x93cdbc93UL, 0xc822bdc8UL, 0x257abe25UL, 0x7e95bf7eUL,
0xf090c0f0UL, 0xab7fc1abUL, 0x4627c246UL, 0x1dc8c31dUL, 0xf597c4f5UL, 0xae78c5aeUL, 0x4320c643UL, 0x18cfc718UL,
0xfa9ec8faUL, 0xa171c9a1UL, 0x4c29ca4cUL, 0x17c6cb17UL, 0xff99ccffUL, 0xa476cda4UL, 0x492ece49UL, 0x12c1cf12UL,
0xe48cd0e4UL, 0xbf63d1bfUL, 0x523bd252UL, 0x09d4d309UL, 0xe18bd4e1UL, 0xba64d5baUL, 0x573cd657UL, 0x0cd3d70cUL,
0xee82d8eeUL, 0xb56dd9b5UL, 0x5835da58UL, 0x03dadb03UL, 0xeb85dcebUL, 0xb06addb0UL, 0x5d32de5dUL, 0x06dddf06UL,
0xd8a8e0d8UL, 0x8347e183UL, 0x6e1fe26eUL, 0x35f0e335UL, 0xddafe4ddUL, 0x8640e586UL, 0x6b18e66bUL, 0x30f7e730UL,
0xd2a6e8d2UL, 0x8949e989UL, 0x6411ea64UL, 0x3ffeeb3fUL, 0xd7a1ecd7UL, 0x8c4eed8cUL, 0x6116ee61UL, 0x3af9ef3aUL,
0xccb4f0ccUL, 0x975bf197UL, 0x7a03f27aUL, 0x21ecf321UL, 0xc9b3f4c9UL, 0x925cf592UL, 0x7f04f67fUL, 0x24ebf724UL,
0xc6baf8c6UL, 0x9d55f99dUL, 0x700dfa70UL, 0x2be2fb2bUL, 0xc3bdfcc3UL, 0x9852fd98UL, 0x750afe75UL, 0x2ee5ff2eUL
}};
#include "twofish_tab.c"
#define sbox(i, x) ((ulong32)SBOX[i][(x)&255])
#else
/* The Q-box tables */
static const unsigned char qbox[2][4][16] = {
static const unsigned char qbox[2][4][16] = {
{
{ 0x8, 0x1, 0x7, 0xD, 0x6, 0xF, 0x3, 0x2, 0x0, 0xB, 0x5, 0x9, 0xE, 0xC, 0xA, 0x4 },
{ 0xE, 0XC, 0XB, 0X8, 0X1, 0X2, 0X3, 0X5, 0XF, 0X4, 0XA, 0X6, 0X7, 0X0, 0X9, 0XD },
{ 0XB, 0XA, 0X5, 0XE, 0X6, 0XD, 0X9, 0X0, 0XC, 0X8, 0XF, 0X3, 0X2, 0X4, 0X7, 0X1 },
{ 0XD, 0X7, 0XF, 0X4, 0X1, 0X2, 0X6, 0XE, 0X9, 0XB, 0X3, 0X0, 0X8, 0X5, 0XC, 0XA }
},
},
{
{ 0X2, 0X8, 0XB, 0XD, 0XF, 0X7, 0X6, 0XE, 0X3, 0X1, 0X9, 0X4, 0X0, 0XA, 0XC, 0X5 },
{ 0X1, 0XE, 0X2, 0XB, 0X4, 0XC, 0X3, 0X7, 0X6, 0XD, 0XA, 0X5, 0XF, 0X9, 0X0, 0X8 },
@ -314,11 +129,11 @@ static ulong32 sbox(int i, ulong32 x)
/* computes ab mod p */
static ulong32 gf_mult(ulong32 a, ulong32 b, ulong32 p)
{
ulong32 result = 0, B[2], P[2];
ulong32 result, B[2], P[2];
P[1] = p;
B[1] = b;
P[0] = B[0] = 0;
result = P[0] = B[0] = 0;
/* unrolled branchless GF multiplier */
result ^= B[a&1]; a >>= 1; B[1] = P[B[1]>>7] ^ (B[1] << 1);
@ -369,7 +184,7 @@ static ulong32 mds_column_mult(unsigned char in, int col)
return 0;
}
#else /* TWOFISH_TABLES */
#else /* !TWOFISH_TABLES */
#define mds_column_mult(x, i) mds_tab[i][x]
@ -386,25 +201,40 @@ static void mds_mult(const unsigned char *in, unsigned char *out)
STORE32L(tmp, out);
}
#ifdef TWOFISH_ALL_TABLES
/* computes [y0 y1 y2 y3] = RS . [x0 x1 x2 x3 x4 x5 x6 x7] */
static void rs_mult(const unsigned char *in, unsigned char *out)
{
ulong32 tmp;
tmp = rs_tab0[in[0]] ^ rs_tab1[in[1]] ^ rs_tab2[in[2]] ^ rs_tab3[in[3]] ^
rs_tab4[in[4]] ^ rs_tab5[in[5]] ^ rs_tab6[in[6]] ^ rs_tab7[in[7]];
STORE32L(tmp, out);
}
#else /* !TWOFISH_ALL_TABLES */
/* computes [y0 y1 y2 y3] = RS . [x0 x1 x2 x3 x4 x5 x6 x7] */
static void rs_mult(const unsigned char *in, unsigned char *out)
{
int x, y;
for (x = 0; x < 4; x++) {
out[x] = 0;
for (y = 0; y < 8; y++)
for (y = 0; y < 8; y++) {
out[x] ^= gf_mult(in[y], RS[x][y], RS_POLY);
}
}
}
#endif
/* computes h(x) */
static void h_func(const unsigned char *in, unsigned char *out, unsigned char *M, int k, int offset)
{
int x;
unsigned char y[4];
for (x = 0; x < 4; x++)
for (x = 0; x < 4; x++) {
y[x] = in[x];
}
switch (k) {
case 4:
y[0] = (unsigned char)(sbox(1, (ulong32)y[0]) ^ M[4 * (6 + offset) + 0]);
@ -493,11 +323,9 @@ int twofish_setup(const unsigned char *key, int keylen, int num_rounds, symmetri
#endif
{
#ifndef TWOFISH_SMALL
ulong32 g;
int z, i;
unsigned char S[4*4];
unsigned char S[4*4], tmpx0, tmpx1;
#endif
int k, x, y, start;
int k, x, y;
unsigned char tmp[4], tmp2[4], M[8*4];
ulong32 A, B;
@ -517,29 +345,34 @@ int twofish_setup(const unsigned char *key, int keylen, int num_rounds, symmetri
k = keylen / 8;
/* copy the key into M */
for (x = 0; x < keylen; x++)
M[x] = key[x];
for (x = 0; x < keylen; x++) {
M[x] = key[x] & 255;
}
/* create the S[..] words */
#ifndef TWOFISH_SMALL
for (x = 0; x < k; x++)
for (x = 0; x < k; x++) {
rs_mult(M+(x*8), S+(x*4));
}
#else
for (x = 0; x < k; x++)
for (x = 0; x < k; x++) {
rs_mult(M+(x*8), skey->twofish.S+(x*4));
}
#endif
/* make subkeys */
for (x = 0; x < 20; x++) {
/* A = h(p * 2x, Me) */
for (y = 0; y < 4; y++)
for (y = 0; y < 4; y++) {
tmp[y] = x+x;
}
h_func(tmp, tmp2, M, k, 0);
LOAD32L(A, tmp2);
/* B = ROL(h(p * (2x + 1), Mo), 8) */
for (y = 0; y < 4; y++)
for (y = 0; y < 4; y++) {
tmp[y] = (unsigned char)(x+x+1);
}
h_func(tmp, tmp2, M, k, 1);
LOAD32L(B, tmp2);
B = ROL(B, 8);
@ -551,37 +384,44 @@ int twofish_setup(const unsigned char *key, int keylen, int num_rounds, symmetri
skey->twofish.K[x+x+1] = ROL(B + B + A, 9);
}
/* where to start in the sbox layers */
switch (k) {
case 4 : start = 0; break;
case 3 : start = 1; break;
default: start = 2; break;
}
#ifndef TWOFISH_SMALL
/* make the sboxes (large ram variant) */
for (y = 0; y < 4; y++) {
for (x = 0; x < 256; x++) {
z = start;
/* do unkeyed substitution */
g = sbox((int)qord[y][z++], x);
/* first subkey */
i = 0;
/* do key mixing+sbox until z==5 */
while (z != 5) {
g = sbox((int)qord[y][z++], g ^ S[4*i++ + y]);
}
/* multiply g by a column of the MDS */
skey->twofish.S[y][x] = mds_column_mult((unsigned char)g, y);
}
if (k == 2) {
for (x = 0; x < 256; x++) {
tmpx0 = sbox(0, x);
tmpx1 = sbox(1, x);
skey->twofish.S[0][x] = mds_column_mult(sbox(1, (sbox(0, tmpx0 ^ S[0]) ^ S[4])),0);
skey->twofish.S[1][x] = mds_column_mult(sbox(0, (sbox(0, tmpx1 ^ S[1]) ^ S[5])),1);
skey->twofish.S[2][x] = mds_column_mult(sbox(1, (sbox(1, tmpx0 ^ S[2]) ^ S[6])),2);
skey->twofish.S[3][x] = mds_column_mult(sbox(0, (sbox(1, tmpx1 ^ S[3]) ^ S[7])),3);
}
} else if (k == 3) {
for (x = 0; x < 256; x++) {
tmpx0 = sbox(0, x);
tmpx1 = sbox(1, x);
skey->twofish.S[0][x] = mds_column_mult(sbox(1, (sbox(0, sbox(0, tmpx1 ^ S[0]) ^ S[4]) ^ S[8])),0);
skey->twofish.S[1][x] = mds_column_mult(sbox(0, (sbox(0, sbox(1, tmpx1 ^ S[1]) ^ S[5]) ^ S[9])),1);
skey->twofish.S[2][x] = mds_column_mult(sbox(1, (sbox(1, sbox(0, tmpx0 ^ S[2]) ^ S[6]) ^ S[10])),2);
skey->twofish.S[3][x] = mds_column_mult(sbox(0, (sbox(1, sbox(1, tmpx0 ^ S[3]) ^ S[7]) ^ S[11])),3);
}
} else {
for (x = 0; x < 256; x++) {
tmpx0 = sbox(0, x);
tmpx1 = sbox(1, x);
skey->twofish.S[0][x] = mds_column_mult(sbox(1, (sbox(0, sbox(0, sbox(1, tmpx1 ^ S[0]) ^ S[4]) ^ S[8]) ^ S[12])),0);
skey->twofish.S[1][x] = mds_column_mult(sbox(0, (sbox(0, sbox(1, sbox(1, tmpx0 ^ S[1]) ^ S[5]) ^ S[9]) ^ S[13])),1);
skey->twofish.S[2][x] = mds_column_mult(sbox(1, (sbox(1, sbox(0, sbox(0, tmpx0 ^ S[2]) ^ S[6]) ^ S[10]) ^ S[14])),2);
skey->twofish.S[3][x] = mds_column_mult(sbox(0, (sbox(1, sbox(1, sbox(0, tmpx1 ^ S[3]) ^ S[7]) ^ S[11]) ^ S[15])),3);
}
}
#else
/* where to start in the sbox layers */
/* small ram variant */
skey->twofish.start = start;
switch (k) {
case 4 : skey->twofish.start = 0; break;
case 3 : skey->twofish.start = 1; break;
default: skey->twofish.start = 2; break;
}
#endif
return CRYPT_OK;
}
@ -639,7 +479,7 @@ void twofish_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_k
a = ROR(a ^ (t1 + t2 + k[0]), 1);
b = ROL(b, 1) ^ (t2 + t2 + t1 + k[1]);
k += 2;
}
}
/* output with "undo last swap" */
ta = c ^ key->twofish.K[4];
@ -768,7 +608,7 @@ int twofish_test(void)
symmetric_key key;
unsigned char tmp[2][16];
int err, i;
int err, i, y;
for (i = 0; i < (int)(sizeof(tests)/sizeof(tests[0])); i++) {
if ((err = twofish_setup(tests[i].key, tests[i].keylen, 0, &key)) != CRYPT_OK) {
@ -779,6 +619,11 @@ int twofish_test(void)
if (memcmp(tmp[0], tests[i].ct, 16) != 0 || memcmp(tmp[1], tests[i].pt, 16) != 0) {
return CRYPT_FAIL_TESTVECTOR;
}
/* now see if we can encrypt all zero bytes 1000 times, decrypt and come back where we started */
for (y = 0; y < 16; y++) tmp[0][y] = 0;
for (y = 0; y < 1000; y++) twofish_ecb_encrypt(tmp[0], tmp[0], &key);
for (y = 0; y < 1000; y++) twofish_ecb_decrypt(tmp[0], tmp[0], &key);
for (y = 0; y < 16; y++) if (tmp[0][y] != 0) return CRYPT_FAIL_TESTVECTOR;
}
return CRYPT_OK;
#endif

477
twofish_tab.c Normal file
View File

@ -0,0 +1,477 @@
#ifdef TWOFISH_TABLES
/* pre generated 8x8 tables from the four 4x4s */
static const unsigned char SBOX[2][256] = {
{
0xa9, 0x67, 0xb3, 0xe8, 0x04, 0xfd, 0xa3, 0x76, 0x9a, 0x92,
0x80, 0x78, 0xe4, 0xdd, 0xd1, 0x38, 0x0d, 0xc6, 0x35, 0x98,
0x18, 0xf7, 0xec, 0x6c, 0x43, 0x75, 0x37, 0x26, 0xfa, 0x13,
0x94, 0x48, 0xf2, 0xd0, 0x8b, 0x30, 0x84, 0x54, 0xdf, 0x23,
0x19, 0x5b, 0x3d, 0x59, 0xf3, 0xae, 0xa2, 0x82, 0x63, 0x01,
0x83, 0x2e, 0xd9, 0x51, 0x9b, 0x7c, 0xa6, 0xeb, 0xa5, 0xbe,
0x16, 0x0c, 0xe3, 0x61, 0xc0, 0x8c, 0x3a, 0xf5, 0x73, 0x2c,
0x25, 0x0b, 0xbb, 0x4e, 0x89, 0x6b, 0x53, 0x6a, 0xb4, 0xf1,
0xe1, 0xe6, 0xbd, 0x45, 0xe2, 0xf4, 0xb6, 0x66, 0xcc, 0x95,
0x03, 0x56, 0xd4, 0x1c, 0x1e, 0xd7, 0xfb, 0xc3, 0x8e, 0xb5,
0xe9, 0xcf, 0xbf, 0xba, 0xea, 0x77, 0x39, 0xaf, 0x33, 0xc9,
0x62, 0x71, 0x81, 0x79, 0x09, 0xad, 0x24, 0xcd, 0xf9, 0xd8,
0xe5, 0xc5, 0xb9, 0x4d, 0x44, 0x08, 0x86, 0xe7, 0xa1, 0x1d,
0xaa, 0xed, 0x06, 0x70, 0xb2, 0xd2, 0x41, 0x7b, 0xa0, 0x11,
0x31, 0xc2, 0x27, 0x90, 0x20, 0xf6, 0x60, 0xff, 0x96, 0x5c,
0xb1, 0xab, 0x9e, 0x9c, 0x52, 0x1b, 0x5f, 0x93, 0x0a, 0xef,
0x91, 0x85, 0x49, 0xee, 0x2d, 0x4f, 0x8f, 0x3b, 0x47, 0x87,
0x6d, 0x46, 0xd6, 0x3e, 0x69, 0x64, 0x2a, 0xce, 0xcb, 0x2f,
0xfc, 0x97, 0x05, 0x7a, 0xac, 0x7f, 0xd5, 0x1a, 0x4b, 0x0e,
0xa7, 0x5a, 0x28, 0x14, 0x3f, 0x29, 0x88, 0x3c, 0x4c, 0x02,
0xb8, 0xda, 0xb0, 0x17, 0x55, 0x1f, 0x8a, 0x7d, 0x57, 0xc7,
0x8d, 0x74, 0xb7, 0xc4, 0x9f, 0x72, 0x7e, 0x15, 0x22, 0x12,
0x58, 0x07, 0x99, 0x34, 0x6e, 0x50, 0xde, 0x68, 0x65, 0xbc,
0xdb, 0xf8, 0xc8, 0xa8, 0x2b, 0x40, 0xdc, 0xfe, 0x32, 0xa4,
0xca, 0x10, 0x21, 0xf0, 0xd3, 0x5d, 0x0f, 0x00, 0x6f, 0x9d,
0x36, 0x42, 0x4a, 0x5e, 0xc1, 0xe0},
{
0x75, 0xf3, 0xc6, 0xf4, 0xdb, 0x7b, 0xfb, 0xc8, 0x4a, 0xd3,
0xe6, 0x6b, 0x45, 0x7d, 0xe8, 0x4b, 0xd6, 0x32, 0xd8, 0xfd,
0x37, 0x71, 0xf1, 0xe1, 0x30, 0x0f, 0xf8, 0x1b, 0x87, 0xfa,
0x06, 0x3f, 0x5e, 0xba, 0xae, 0x5b, 0x8a, 0x00, 0xbc, 0x9d,
0x6d, 0xc1, 0xb1, 0x0e, 0x80, 0x5d, 0xd2, 0xd5, 0xa0, 0x84,
0x07, 0x14, 0xb5, 0x90, 0x2c, 0xa3, 0xb2, 0x73, 0x4c, 0x54,
0x92, 0x74, 0x36, 0x51, 0x38, 0xb0, 0xbd, 0x5a, 0xfc, 0x60,
0x62, 0x96, 0x6c, 0x42, 0xf7, 0x10, 0x7c, 0x28, 0x27, 0x8c,
0x13, 0x95, 0x9c, 0xc7, 0x24, 0x46, 0x3b, 0x70, 0xca, 0xe3,
0x85, 0xcb, 0x11, 0xd0, 0x93, 0xb8, 0xa6, 0x83, 0x20, 0xff,
0x9f, 0x77, 0xc3, 0xcc, 0x03, 0x6f, 0x08, 0xbf, 0x40, 0xe7,
0x2b, 0xe2, 0x79, 0x0c, 0xaa, 0x82, 0x41, 0x3a, 0xea, 0xb9,
0xe4, 0x9a, 0xa4, 0x97, 0x7e, 0xda, 0x7a, 0x17, 0x66, 0x94,
0xa1, 0x1d, 0x3d, 0xf0, 0xde, 0xb3, 0x0b, 0x72, 0xa7, 0x1c,
0xef, 0xd1, 0x53, 0x3e, 0x8f, 0x33, 0x26, 0x5f, 0xec, 0x76,
0x2a, 0x49, 0x81, 0x88, 0xee, 0x21, 0xc4, 0x1a, 0xeb, 0xd9,
0xc5, 0x39, 0x99, 0xcd, 0xad, 0x31, 0x8b, 0x01, 0x18, 0x23,
0xdd, 0x1f, 0x4e, 0x2d, 0xf9, 0x48, 0x4f, 0xf2, 0x65, 0x8e,
0x78, 0x5c, 0x58, 0x19, 0x8d, 0xe5, 0x98, 0x57, 0x67, 0x7f,
0x05, 0x64, 0xaf, 0x63, 0xb6, 0xfe, 0xf5, 0xb7, 0x3c, 0xa5,
0xce, 0xe9, 0x68, 0x44, 0xe0, 0x4d, 0x43, 0x69, 0x29, 0x2e,
0xac, 0x15, 0x59, 0xa8, 0x0a, 0x9e, 0x6e, 0x47, 0xdf, 0x34,
0x35, 0x6a, 0xcf, 0xdc, 0x22, 0xc9, 0xc0, 0x9b, 0x89, 0xd4,
0xed, 0xab, 0x12, 0xa2, 0x0d, 0x52, 0xbb, 0x02, 0x2f, 0xa9,
0xd7, 0x61, 0x1e, 0xb4, 0x50, 0x04, 0xf6, 0xc2, 0x16, 0x25,
0x86, 0x56, 0x55, 0x09, 0xbe, 0x91}
};
/* the 4x4 MDS in a nicer format */
static const ulong32 mds_tab[4][256] = {
{
0x00000000UL, 0xefef5b01UL, 0xb7b7b602UL, 0x5858ed03UL, 0x07070504UL, 0xe8e85e05UL, 0xb0b0b306UL, 0x5f5fe807UL,
0x0e0e0a08UL, 0xe1e15109UL, 0xb9b9bc0aUL, 0x5656e70bUL, 0x09090f0cUL, 0xe6e6540dUL, 0xbebeb90eUL, 0x5151e20fUL,
0x1c1c1410UL, 0xf3f34f11UL, 0xababa212UL, 0x4444f913UL, 0x1b1b1114UL, 0xf4f44a15UL, 0xacaca716UL, 0x4343fc17UL,
0x12121e18UL, 0xfdfd4519UL, 0xa5a5a81aUL, 0x4a4af31bUL, 0x15151b1cUL, 0xfafa401dUL, 0xa2a2ad1eUL, 0x4d4df61fUL,
0x38382820UL, 0xd7d77321UL, 0x8f8f9e22UL, 0x6060c523UL, 0x3f3f2d24UL, 0xd0d07625UL, 0x88889b26UL, 0x6767c027UL,
0x36362228UL, 0xd9d97929UL, 0x8181942aUL, 0x6e6ecf2bUL, 0x3131272cUL, 0xdede7c2dUL, 0x8686912eUL, 0x6969ca2fUL,
0x24243c30UL, 0xcbcb6731UL, 0x93938a32UL, 0x7c7cd133UL, 0x23233934UL, 0xcccc6235UL, 0x94948f36UL, 0x7b7bd437UL,
0x2a2a3638UL, 0xc5c56d39UL, 0x9d9d803aUL, 0x7272db3bUL, 0x2d2d333cUL, 0xc2c2683dUL, 0x9a9a853eUL, 0x7575de3fUL,
0x70705040UL, 0x9f9f0b41UL, 0xc7c7e642UL, 0x2828bd43UL, 0x77775544UL, 0x98980e45UL, 0xc0c0e346UL, 0x2f2fb847UL,
0x7e7e5a48UL, 0x91910149UL, 0xc9c9ec4aUL, 0x2626b74bUL, 0x79795f4cUL, 0x9696044dUL, 0xcecee94eUL, 0x2121b24fUL,
0x6c6c4450UL, 0x83831f51UL, 0xdbdbf252UL, 0x3434a953UL, 0x6b6b4154UL, 0x84841a55UL, 0xdcdcf756UL, 0x3333ac57UL,
0x62624e58UL, 0x8d8d1559UL, 0xd5d5f85aUL, 0x3a3aa35bUL, 0x65654b5cUL, 0x8a8a105dUL, 0xd2d2fd5eUL, 0x3d3da65fUL,
0x48487860UL, 0xa7a72361UL, 0xffffce62UL, 0x10109563UL, 0x4f4f7d64UL, 0xa0a02665UL, 0xf8f8cb66UL, 0x17179067UL,
0x46467268UL, 0xa9a92969UL, 0xf1f1c46aUL, 0x1e1e9f6bUL, 0x4141776cUL, 0xaeae2c6dUL, 0xf6f6c16eUL, 0x19199a6fUL,
0x54546c70UL, 0xbbbb3771UL, 0xe3e3da72UL, 0x0c0c8173UL, 0x53536974UL, 0xbcbc3275UL, 0xe4e4df76UL, 0x0b0b8477UL,
0x5a5a6678UL, 0xb5b53d79UL, 0xededd07aUL, 0x02028b7bUL, 0x5d5d637cUL, 0xb2b2387dUL, 0xeaead57eUL, 0x05058e7fUL,
0xe0e0a080UL, 0x0f0ffb81UL, 0x57571682UL, 0xb8b84d83UL, 0xe7e7a584UL, 0x0808fe85UL, 0x50501386UL, 0xbfbf4887UL,
0xeeeeaa88UL, 0x0101f189UL, 0x59591c8aUL, 0xb6b6478bUL, 0xe9e9af8cUL, 0x0606f48dUL, 0x5e5e198eUL, 0xb1b1428fUL,
0xfcfcb490UL, 0x1313ef91UL, 0x4b4b0292UL, 0xa4a45993UL, 0xfbfbb194UL, 0x1414ea95UL, 0x4c4c0796UL, 0xa3a35c97UL,
0xf2f2be98UL, 0x1d1de599UL, 0x4545089aUL, 0xaaaa539bUL, 0xf5f5bb9cUL, 0x1a1ae09dUL, 0x42420d9eUL, 0xadad569fUL,
0xd8d888a0UL, 0x3737d3a1UL, 0x6f6f3ea2UL, 0x808065a3UL, 0xdfdf8da4UL, 0x3030d6a5UL, 0x68683ba6UL, 0x878760a7UL,
0xd6d682a8UL, 0x3939d9a9UL, 0x616134aaUL, 0x8e8e6fabUL, 0xd1d187acUL, 0x3e3edcadUL, 0x666631aeUL, 0x89896aafUL,
0xc4c49cb0UL, 0x2b2bc7b1UL, 0x73732ab2UL, 0x9c9c71b3UL, 0xc3c399b4UL, 0x2c2cc2b5UL, 0x74742fb6UL, 0x9b9b74b7UL,
0xcaca96b8UL, 0x2525cdb9UL, 0x7d7d20baUL, 0x92927bbbUL, 0xcdcd93bcUL, 0x2222c8bdUL, 0x7a7a25beUL, 0x95957ebfUL,
0x9090f0c0UL, 0x7f7fabc1UL, 0x272746c2UL, 0xc8c81dc3UL, 0x9797f5c4UL, 0x7878aec5UL, 0x202043c6UL, 0xcfcf18c7UL,
0x9e9efac8UL, 0x7171a1c9UL, 0x29294ccaUL, 0xc6c617cbUL, 0x9999ffccUL, 0x7676a4cdUL, 0x2e2e49ceUL, 0xc1c112cfUL,
0x8c8ce4d0UL, 0x6363bfd1UL, 0x3b3b52d2UL, 0xd4d409d3UL, 0x8b8be1d4UL, 0x6464bad5UL, 0x3c3c57d6UL, 0xd3d30cd7UL,
0x8282eed8UL, 0x6d6db5d9UL, 0x353558daUL, 0xdada03dbUL, 0x8585ebdcUL, 0x6a6ab0ddUL, 0x32325ddeUL, 0xdddd06dfUL,
0xa8a8d8e0UL, 0x474783e1UL, 0x1f1f6ee2UL, 0xf0f035e3UL, 0xafafdde4UL, 0x404086e5UL, 0x18186be6UL, 0xf7f730e7UL,
0xa6a6d2e8UL, 0x494989e9UL, 0x111164eaUL, 0xfefe3febUL, 0xa1a1d7ecUL, 0x4e4e8cedUL, 0x161661eeUL, 0xf9f93aefUL,
0xb4b4ccf0UL, 0x5b5b97f1UL, 0x03037af2UL, 0xecec21f3UL, 0xb3b3c9f4UL, 0x5c5c92f5UL, 0x04047ff6UL, 0xebeb24f7UL,
0xbabac6f8UL, 0x55559df9UL, 0x0d0d70faUL, 0xe2e22bfbUL, 0xbdbdc3fcUL, 0x525298fdUL, 0x0a0a75feUL, 0xe5e52effUL
},
{
0x00000000UL, 0x015befefUL, 0x02b6b7b7UL, 0x03ed5858UL, 0x04050707UL, 0x055ee8e8UL, 0x06b3b0b0UL, 0x07e85f5fUL,
0x080a0e0eUL, 0x0951e1e1UL, 0x0abcb9b9UL, 0x0be75656UL, 0x0c0f0909UL, 0x0d54e6e6UL, 0x0eb9bebeUL, 0x0fe25151UL,
0x10141c1cUL, 0x114ff3f3UL, 0x12a2ababUL, 0x13f94444UL, 0x14111b1bUL, 0x154af4f4UL, 0x16a7acacUL, 0x17fc4343UL,
0x181e1212UL, 0x1945fdfdUL, 0x1aa8a5a5UL, 0x1bf34a4aUL, 0x1c1b1515UL, 0x1d40fafaUL, 0x1eada2a2UL, 0x1ff64d4dUL,
0x20283838UL, 0x2173d7d7UL, 0x229e8f8fUL, 0x23c56060UL, 0x242d3f3fUL, 0x2576d0d0UL, 0x269b8888UL, 0x27c06767UL,
0x28223636UL, 0x2979d9d9UL, 0x2a948181UL, 0x2bcf6e6eUL, 0x2c273131UL, 0x2d7cdedeUL, 0x2e918686UL, 0x2fca6969UL,
0x303c2424UL, 0x3167cbcbUL, 0x328a9393UL, 0x33d17c7cUL, 0x34392323UL, 0x3562ccccUL, 0x368f9494UL, 0x37d47b7bUL,
0x38362a2aUL, 0x396dc5c5UL, 0x3a809d9dUL, 0x3bdb7272UL, 0x3c332d2dUL, 0x3d68c2c2UL, 0x3e859a9aUL, 0x3fde7575UL,
0x40507070UL, 0x410b9f9fUL, 0x42e6c7c7UL, 0x43bd2828UL, 0x44557777UL, 0x450e9898UL, 0x46e3c0c0UL, 0x47b82f2fUL,
0x485a7e7eUL, 0x49019191UL, 0x4aecc9c9UL, 0x4bb72626UL, 0x4c5f7979UL, 0x4d049696UL, 0x4ee9ceceUL, 0x4fb22121UL,
0x50446c6cUL, 0x511f8383UL, 0x52f2dbdbUL, 0x53a93434UL, 0x54416b6bUL, 0x551a8484UL, 0x56f7dcdcUL, 0x57ac3333UL,
0x584e6262UL, 0x59158d8dUL, 0x5af8d5d5UL, 0x5ba33a3aUL, 0x5c4b6565UL, 0x5d108a8aUL, 0x5efdd2d2UL, 0x5fa63d3dUL,
0x60784848UL, 0x6123a7a7UL, 0x62ceffffUL, 0x63951010UL, 0x647d4f4fUL, 0x6526a0a0UL, 0x66cbf8f8UL, 0x67901717UL,
0x68724646UL, 0x6929a9a9UL, 0x6ac4f1f1UL, 0x6b9f1e1eUL, 0x6c774141UL, 0x6d2caeaeUL, 0x6ec1f6f6UL, 0x6f9a1919UL,
0x706c5454UL, 0x7137bbbbUL, 0x72dae3e3UL, 0x73810c0cUL, 0x74695353UL, 0x7532bcbcUL, 0x76dfe4e4UL, 0x77840b0bUL,
0x78665a5aUL, 0x793db5b5UL, 0x7ad0ededUL, 0x7b8b0202UL, 0x7c635d5dUL, 0x7d38b2b2UL, 0x7ed5eaeaUL, 0x7f8e0505UL,
0x80a0e0e0UL, 0x81fb0f0fUL, 0x82165757UL, 0x834db8b8UL, 0x84a5e7e7UL, 0x85fe0808UL, 0x86135050UL, 0x8748bfbfUL,
0x88aaeeeeUL, 0x89f10101UL, 0x8a1c5959UL, 0x8b47b6b6UL, 0x8cafe9e9UL, 0x8df40606UL, 0x8e195e5eUL, 0x8f42b1b1UL,
0x90b4fcfcUL, 0x91ef1313UL, 0x92024b4bUL, 0x9359a4a4UL, 0x94b1fbfbUL, 0x95ea1414UL, 0x96074c4cUL, 0x975ca3a3UL,
0x98bef2f2UL, 0x99e51d1dUL, 0x9a084545UL, 0x9b53aaaaUL, 0x9cbbf5f5UL, 0x9de01a1aUL, 0x9e0d4242UL, 0x9f56adadUL,
0xa088d8d8UL, 0xa1d33737UL, 0xa23e6f6fUL, 0xa3658080UL, 0xa48ddfdfUL, 0xa5d63030UL, 0xa63b6868UL, 0xa7608787UL,
0xa882d6d6UL, 0xa9d93939UL, 0xaa346161UL, 0xab6f8e8eUL, 0xac87d1d1UL, 0xaddc3e3eUL, 0xae316666UL, 0xaf6a8989UL,
0xb09cc4c4UL, 0xb1c72b2bUL, 0xb22a7373UL, 0xb3719c9cUL, 0xb499c3c3UL, 0xb5c22c2cUL, 0xb62f7474UL, 0xb7749b9bUL,
0xb896cacaUL, 0xb9cd2525UL, 0xba207d7dUL, 0xbb7b9292UL, 0xbc93cdcdUL, 0xbdc82222UL, 0xbe257a7aUL, 0xbf7e9595UL,
0xc0f09090UL, 0xc1ab7f7fUL, 0xc2462727UL, 0xc31dc8c8UL, 0xc4f59797UL, 0xc5ae7878UL, 0xc6432020UL, 0xc718cfcfUL,
0xc8fa9e9eUL, 0xc9a17171UL, 0xca4c2929UL, 0xcb17c6c6UL, 0xccff9999UL, 0xcda47676UL, 0xce492e2eUL, 0xcf12c1c1UL,
0xd0e48c8cUL, 0xd1bf6363UL, 0xd2523b3bUL, 0xd309d4d4UL, 0xd4e18b8bUL, 0xd5ba6464UL, 0xd6573c3cUL, 0xd70cd3d3UL,
0xd8ee8282UL, 0xd9b56d6dUL, 0xda583535UL, 0xdb03dadaUL, 0xdceb8585UL, 0xddb06a6aUL, 0xde5d3232UL, 0xdf06ddddUL,
0xe0d8a8a8UL, 0xe1834747UL, 0xe26e1f1fUL, 0xe335f0f0UL, 0xe4ddafafUL, 0xe5864040UL, 0xe66b1818UL, 0xe730f7f7UL,
0xe8d2a6a6UL, 0xe9894949UL, 0xea641111UL, 0xeb3ffefeUL, 0xecd7a1a1UL, 0xed8c4e4eUL, 0xee611616UL, 0xef3af9f9UL,
0xf0ccb4b4UL, 0xf1975b5bUL, 0xf27a0303UL, 0xf321ececUL, 0xf4c9b3b3UL, 0xf5925c5cUL, 0xf67f0404UL, 0xf724ebebUL,
0xf8c6babaUL, 0xf99d5555UL, 0xfa700d0dUL, 0xfb2be2e2UL, 0xfcc3bdbdUL, 0xfd985252UL, 0xfe750a0aUL, 0xff2ee5e5UL
},
{
0x00000000UL, 0xef01ef5bUL, 0xb702b7b6UL, 0x580358edUL, 0x07040705UL, 0xe805e85eUL, 0xb006b0b3UL, 0x5f075fe8UL,
0x0e080e0aUL, 0xe109e151UL, 0xb90ab9bcUL, 0x560b56e7UL, 0x090c090fUL, 0xe60de654UL, 0xbe0ebeb9UL, 0x510f51e2UL,
0x1c101c14UL, 0xf311f34fUL, 0xab12aba2UL, 0x441344f9UL, 0x1b141b11UL, 0xf415f44aUL, 0xac16aca7UL, 0x431743fcUL,
0x1218121eUL, 0xfd19fd45UL, 0xa51aa5a8UL, 0x4a1b4af3UL, 0x151c151bUL, 0xfa1dfa40UL, 0xa21ea2adUL, 0x4d1f4df6UL,
0x38203828UL, 0xd721d773UL, 0x8f228f9eUL, 0x602360c5UL, 0x3f243f2dUL, 0xd025d076UL, 0x8826889bUL, 0x672767c0UL,
0x36283622UL, 0xd929d979UL, 0x812a8194UL, 0x6e2b6ecfUL, 0x312c3127UL, 0xde2dde7cUL, 0x862e8691UL, 0x692f69caUL,
0x2430243cUL, 0xcb31cb67UL, 0x9332938aUL, 0x7c337cd1UL, 0x23342339UL, 0xcc35cc62UL, 0x9436948fUL, 0x7b377bd4UL,
0x2a382a36UL, 0xc539c56dUL, 0x9d3a9d80UL, 0x723b72dbUL, 0x2d3c2d33UL, 0xc23dc268UL, 0x9a3e9a85UL, 0x753f75deUL,
0x70407050UL, 0x9f419f0bUL, 0xc742c7e6UL, 0x284328bdUL, 0x77447755UL, 0x9845980eUL, 0xc046c0e3UL, 0x2f472fb8UL,
0x7e487e5aUL, 0x91499101UL, 0xc94ac9ecUL, 0x264b26b7UL, 0x794c795fUL, 0x964d9604UL, 0xce4ecee9UL, 0x214f21b2UL,
0x6c506c44UL, 0x8351831fUL, 0xdb52dbf2UL, 0x345334a9UL, 0x6b546b41UL, 0x8455841aUL, 0xdc56dcf7UL, 0x335733acUL,
0x6258624eUL, 0x8d598d15UL, 0xd55ad5f8UL, 0x3a5b3aa3UL, 0x655c654bUL, 0x8a5d8a10UL, 0xd25ed2fdUL, 0x3d5f3da6UL,
0x48604878UL, 0xa761a723UL, 0xff62ffceUL, 0x10631095UL, 0x4f644f7dUL, 0xa065a026UL, 0xf866f8cbUL, 0x17671790UL,
0x46684672UL, 0xa969a929UL, 0xf16af1c4UL, 0x1e6b1e9fUL, 0x416c4177UL, 0xae6dae2cUL, 0xf66ef6c1UL, 0x196f199aUL,
0x5470546cUL, 0xbb71bb37UL, 0xe372e3daUL, 0x0c730c81UL, 0x53745369UL, 0xbc75bc32UL, 0xe476e4dfUL, 0x0b770b84UL,
0x5a785a66UL, 0xb579b53dUL, 0xed7aedd0UL, 0x027b028bUL, 0x5d7c5d63UL, 0xb27db238UL, 0xea7eead5UL, 0x057f058eUL,
0xe080e0a0UL, 0x0f810ffbUL, 0x57825716UL, 0xb883b84dUL, 0xe784e7a5UL, 0x088508feUL, 0x50865013UL, 0xbf87bf48UL,
0xee88eeaaUL, 0x018901f1UL, 0x598a591cUL, 0xb68bb647UL, 0xe98ce9afUL, 0x068d06f4UL, 0x5e8e5e19UL, 0xb18fb142UL,
0xfc90fcb4UL, 0x139113efUL, 0x4b924b02UL, 0xa493a459UL, 0xfb94fbb1UL, 0x149514eaUL, 0x4c964c07UL, 0xa397a35cUL,
0xf298f2beUL, 0x1d991de5UL, 0x459a4508UL, 0xaa9baa53UL, 0xf59cf5bbUL, 0x1a9d1ae0UL, 0x429e420dUL, 0xad9fad56UL,
0xd8a0d888UL, 0x37a137d3UL, 0x6fa26f3eUL, 0x80a38065UL, 0xdfa4df8dUL, 0x30a530d6UL, 0x68a6683bUL, 0x87a78760UL,
0xd6a8d682UL, 0x39a939d9UL, 0x61aa6134UL, 0x8eab8e6fUL, 0xd1acd187UL, 0x3ead3edcUL, 0x66ae6631UL, 0x89af896aUL,
0xc4b0c49cUL, 0x2bb12bc7UL, 0x73b2732aUL, 0x9cb39c71UL, 0xc3b4c399UL, 0x2cb52cc2UL, 0x74b6742fUL, 0x9bb79b74UL,
0xcab8ca96UL, 0x25b925cdUL, 0x7dba7d20UL, 0x92bb927bUL, 0xcdbccd93UL, 0x22bd22c8UL, 0x7abe7a25UL, 0x95bf957eUL,
0x90c090f0UL, 0x7fc17fabUL, 0x27c22746UL, 0xc8c3c81dUL, 0x97c497f5UL, 0x78c578aeUL, 0x20c62043UL, 0xcfc7cf18UL,
0x9ec89efaUL, 0x71c971a1UL, 0x29ca294cUL, 0xc6cbc617UL, 0x99cc99ffUL, 0x76cd76a4UL, 0x2ece2e49UL, 0xc1cfc112UL,
0x8cd08ce4UL, 0x63d163bfUL, 0x3bd23b52UL, 0xd4d3d409UL, 0x8bd48be1UL, 0x64d564baUL, 0x3cd63c57UL, 0xd3d7d30cUL,
0x82d882eeUL, 0x6dd96db5UL, 0x35da3558UL, 0xdadbda03UL, 0x85dc85ebUL, 0x6add6ab0UL, 0x32de325dUL, 0xdddfdd06UL,
0xa8e0a8d8UL, 0x47e14783UL, 0x1fe21f6eUL, 0xf0e3f035UL, 0xafe4afddUL, 0x40e54086UL, 0x18e6186bUL, 0xf7e7f730UL,
0xa6e8a6d2UL, 0x49e94989UL, 0x11ea1164UL, 0xfeebfe3fUL, 0xa1eca1d7UL, 0x4eed4e8cUL, 0x16ee1661UL, 0xf9eff93aUL,
0xb4f0b4ccUL, 0x5bf15b97UL, 0x03f2037aUL, 0xecf3ec21UL, 0xb3f4b3c9UL, 0x5cf55c92UL, 0x04f6047fUL, 0xebf7eb24UL,
0xbaf8bac6UL, 0x55f9559dUL, 0x0dfa0d70UL, 0xe2fbe22bUL, 0xbdfcbdc3UL, 0x52fd5298UL, 0x0afe0a75UL, 0xe5ffe52eUL
},
{
0x00000000UL, 0x5bef015bUL, 0xb6b702b6UL, 0xed5803edUL, 0x05070405UL, 0x5ee8055eUL, 0xb3b006b3UL, 0xe85f07e8UL,
0x0a0e080aUL, 0x51e10951UL, 0xbcb90abcUL, 0xe7560be7UL, 0x0f090c0fUL, 0x54e60d54UL, 0xb9be0eb9UL, 0xe2510fe2UL,
0x141c1014UL, 0x4ff3114fUL, 0xa2ab12a2UL, 0xf94413f9UL, 0x111b1411UL, 0x4af4154aUL, 0xa7ac16a7UL, 0xfc4317fcUL,
0x1e12181eUL, 0x45fd1945UL, 0xa8a51aa8UL, 0xf34a1bf3UL, 0x1b151c1bUL, 0x40fa1d40UL, 0xada21eadUL, 0xf64d1ff6UL,
0x28382028UL, 0x73d72173UL, 0x9e8f229eUL, 0xc56023c5UL, 0x2d3f242dUL, 0x76d02576UL, 0x9b88269bUL, 0xc06727c0UL,
0x22362822UL, 0x79d92979UL, 0x94812a94UL, 0xcf6e2bcfUL, 0x27312c27UL, 0x7cde2d7cUL, 0x91862e91UL, 0xca692fcaUL,
0x3c24303cUL, 0x67cb3167UL, 0x8a93328aUL, 0xd17c33d1UL, 0x39233439UL, 0x62cc3562UL, 0x8f94368fUL, 0xd47b37d4UL,
0x362a3836UL, 0x6dc5396dUL, 0x809d3a80UL, 0xdb723bdbUL, 0x332d3c33UL, 0x68c23d68UL, 0x859a3e85UL, 0xde753fdeUL,
0x50704050UL, 0x0b9f410bUL, 0xe6c742e6UL, 0xbd2843bdUL, 0x55774455UL, 0x0e98450eUL, 0xe3c046e3UL, 0xb82f47b8UL,
0x5a7e485aUL, 0x01914901UL, 0xecc94aecUL, 0xb7264bb7UL, 0x5f794c5fUL, 0x04964d04UL, 0xe9ce4ee9UL, 0xb2214fb2UL,
0x446c5044UL, 0x1f83511fUL, 0xf2db52f2UL, 0xa93453a9UL, 0x416b5441UL, 0x1a84551aUL, 0xf7dc56f7UL, 0xac3357acUL,
0x4e62584eUL, 0x158d5915UL, 0xf8d55af8UL, 0xa33a5ba3UL, 0x4b655c4bUL, 0x108a5d10UL, 0xfdd25efdUL, 0xa63d5fa6UL,
0x78486078UL, 0x23a76123UL, 0xceff62ceUL, 0x95106395UL, 0x7d4f647dUL, 0x26a06526UL, 0xcbf866cbUL, 0x90176790UL,
0x72466872UL, 0x29a96929UL, 0xc4f16ac4UL, 0x9f1e6b9fUL, 0x77416c77UL, 0x2cae6d2cUL, 0xc1f66ec1UL, 0x9a196f9aUL,
0x6c54706cUL, 0x37bb7137UL, 0xdae372daUL, 0x810c7381UL, 0x69537469UL, 0x32bc7532UL, 0xdfe476dfUL, 0x840b7784UL,
0x665a7866UL, 0x3db5793dUL, 0xd0ed7ad0UL, 0x8b027b8bUL, 0x635d7c63UL, 0x38b27d38UL, 0xd5ea7ed5UL, 0x8e057f8eUL,
0xa0e080a0UL, 0xfb0f81fbUL, 0x16578216UL, 0x4db8834dUL, 0xa5e784a5UL, 0xfe0885feUL, 0x13508613UL, 0x48bf8748UL,
0xaaee88aaUL, 0xf10189f1UL, 0x1c598a1cUL, 0x47b68b47UL, 0xafe98cafUL, 0xf4068df4UL, 0x195e8e19UL, 0x42b18f42UL,
0xb4fc90b4UL, 0xef1391efUL, 0x024b9202UL, 0x59a49359UL, 0xb1fb94b1UL, 0xea1495eaUL, 0x074c9607UL, 0x5ca3975cUL,
0xbef298beUL, 0xe51d99e5UL, 0x08459a08UL, 0x53aa9b53UL, 0xbbf59cbbUL, 0xe01a9de0UL, 0x0d429e0dUL, 0x56ad9f56UL,
0x88d8a088UL, 0xd337a1d3UL, 0x3e6fa23eUL, 0x6580a365UL, 0x8ddfa48dUL, 0xd630a5d6UL, 0x3b68a63bUL, 0x6087a760UL,
0x82d6a882UL, 0xd939a9d9UL, 0x3461aa34UL, 0x6f8eab6fUL, 0x87d1ac87UL, 0xdc3eaddcUL, 0x3166ae31UL, 0x6a89af6aUL,
0x9cc4b09cUL, 0xc72bb1c7UL, 0x2a73b22aUL, 0x719cb371UL, 0x99c3b499UL, 0xc22cb5c2UL, 0x2f74b62fUL, 0x749bb774UL,
0x96cab896UL, 0xcd25b9cdUL, 0x207dba20UL, 0x7b92bb7bUL, 0x93cdbc93UL, 0xc822bdc8UL, 0x257abe25UL, 0x7e95bf7eUL,
0xf090c0f0UL, 0xab7fc1abUL, 0x4627c246UL, 0x1dc8c31dUL, 0xf597c4f5UL, 0xae78c5aeUL, 0x4320c643UL, 0x18cfc718UL,
0xfa9ec8faUL, 0xa171c9a1UL, 0x4c29ca4cUL, 0x17c6cb17UL, 0xff99ccffUL, 0xa476cda4UL, 0x492ece49UL, 0x12c1cf12UL,
0xe48cd0e4UL, 0xbf63d1bfUL, 0x523bd252UL, 0x09d4d309UL, 0xe18bd4e1UL, 0xba64d5baUL, 0x573cd657UL, 0x0cd3d70cUL,
0xee82d8eeUL, 0xb56dd9b5UL, 0x5835da58UL, 0x03dadb03UL, 0xeb85dcebUL, 0xb06addb0UL, 0x5d32de5dUL, 0x06dddf06UL,
0xd8a8e0d8UL, 0x8347e183UL, 0x6e1fe26eUL, 0x35f0e335UL, 0xddafe4ddUL, 0x8640e586UL, 0x6b18e66bUL, 0x30f7e730UL,
0xd2a6e8d2UL, 0x8949e989UL, 0x6411ea64UL, 0x3ffeeb3fUL, 0xd7a1ecd7UL, 0x8c4eed8cUL, 0x6116ee61UL, 0x3af9ef3aUL,
0xccb4f0ccUL, 0x975bf197UL, 0x7a03f27aUL, 0x21ecf321UL, 0xc9b3f4c9UL, 0x925cf592UL, 0x7f04f67fUL, 0x24ebf724UL,
0xc6baf8c6UL, 0x9d55f99dUL, 0x700dfa70UL, 0x2be2fb2bUL, 0xc3bdfcc3UL, 0x9852fd98UL, 0x750afe75UL, 0x2ee5ff2eUL
}};
#ifdef TWOFISH_ALL_TABLES
/* the 4x8 RS transform */
static const ulong32 rs_tab0[256] = {
0x00000000LU, 0xa402a401LU, 0x05040502LU, 0xa106a103LU, 0x0a080a04LU, 0xae0aae05LU, 0x0f0c0f06LU, 0xab0eab07LU,
0x14101408LU, 0xb012b009LU, 0x1114110aLU, 0xb516b50bLU, 0x1e181e0cLU, 0xba1aba0dLU, 0x1b1c1b0eLU, 0xbf1ebf0fLU,
0x28202810LU, 0x8c228c11LU, 0x2d242d12LU, 0x89268913LU, 0x22282214LU, 0x862a8615LU, 0x272c2716LU, 0x832e8317LU,
0x3c303c18LU, 0x98329819LU, 0x3934391aLU, 0x9d369d1bLU, 0x3638361cLU, 0x923a921dLU, 0x333c331eLU, 0x973e971fLU,
0x50405020LU, 0xf442f421LU, 0x55445522LU, 0xf146f123LU, 0x5a485a24LU, 0xfe4afe25LU, 0x5f4c5f26LU, 0xfb4efb27LU,
0x44504428LU, 0xe052e029LU, 0x4154412aLU, 0xe556e52bLU, 0x4e584e2cLU, 0xea5aea2dLU, 0x4b5c4b2eLU, 0xef5eef2fLU,
0x78607830LU, 0xdc62dc31LU, 0x7d647d32LU, 0xd966d933LU, 0x72687234LU, 0xd66ad635LU, 0x776c7736LU, 0xd36ed337LU,
0x6c706c38LU, 0xc872c839LU, 0x6974693aLU, 0xcd76cd3bLU, 0x6678663cLU, 0xc27ac23dLU, 0x637c633eLU, 0xc77ec73fLU,
0xa080a040LU, 0x04820441LU, 0xa584a542LU, 0x01860143LU, 0xaa88aa44LU, 0x0e8a0e45LU, 0xaf8caf46LU, 0x0b8e0b47LU,
0xb490b448LU, 0x10921049LU, 0xb194b14aLU, 0x1596154bLU, 0xbe98be4cLU, 0x1a9a1a4dLU, 0xbb9cbb4eLU, 0x1f9e1f4fLU,
0x88a08850LU, 0x2ca22c51LU, 0x8da48d52LU, 0x29a62953LU, 0x82a88254LU, 0x26aa2655LU, 0x87ac8756LU, 0x23ae2357LU,
0x9cb09c58LU, 0x38b23859LU, 0x99b4995aLU, 0x3db63d5bLU, 0x96b8965cLU, 0x32ba325dLU, 0x93bc935eLU, 0x37be375fLU,
0xf0c0f060LU, 0x54c25461LU, 0xf5c4f562LU, 0x51c65163LU, 0xfac8fa64LU, 0x5eca5e65LU, 0xffccff66LU, 0x5bce5b67LU,
0xe4d0e468LU, 0x40d24069LU, 0xe1d4e16aLU, 0x45d6456bLU, 0xeed8ee6cLU, 0x4ada4a6dLU, 0xebdceb6eLU, 0x4fde4f6fLU,
0xd8e0d870LU, 0x7ce27c71LU, 0xdde4dd72LU, 0x79e67973LU, 0xd2e8d274LU, 0x76ea7675LU, 0xd7ecd776LU, 0x73ee7377LU,
0xccf0cc78LU, 0x68f26879LU, 0xc9f4c97aLU, 0x6df66d7bLU, 0xc6f8c67cLU, 0x62fa627dLU, 0xc3fcc37eLU, 0x67fe677fLU,
0x0d4d0d80LU, 0xa94fa981LU, 0x08490882LU, 0xac4bac83LU, 0x07450784LU, 0xa347a385LU, 0x02410286LU, 0xa643a687LU,
0x195d1988LU, 0xbd5fbd89LU, 0x1c591c8aLU, 0xb85bb88bLU, 0x1355138cLU, 0xb757b78dLU, 0x1651168eLU, 0xb253b28fLU,
0x256d2590LU, 0x816f8191LU, 0x20692092LU, 0x846b8493LU, 0x2f652f94LU, 0x8b678b95LU, 0x2a612a96LU, 0x8e638e97LU,
0x317d3198LU, 0x957f9599LU, 0x3479349aLU, 0x907b909bLU, 0x3b753b9cLU, 0x9f779f9dLU, 0x3e713e9eLU, 0x9a739a9fLU,
0x5d0d5da0LU, 0xf90ff9a1LU, 0x580958a2LU, 0xfc0bfca3LU, 0x570557a4LU, 0xf307f3a5LU, 0x520152a6LU, 0xf603f6a7LU,
0x491d49a8LU, 0xed1feda9LU, 0x4c194caaLU, 0xe81be8abLU, 0x431543acLU, 0xe717e7adLU, 0x461146aeLU, 0xe213e2afLU,
0x752d75b0LU, 0xd12fd1b1LU, 0x702970b2LU, 0xd42bd4b3LU, 0x7f257fb4LU, 0xdb27dbb5LU, 0x7a217ab6LU, 0xde23deb7LU,
0x613d61b8LU, 0xc53fc5b9LU, 0x643964baLU, 0xc03bc0bbLU, 0x6b356bbcLU, 0xcf37cfbdLU, 0x6e316ebeLU, 0xca33cabfLU,
0xadcdadc0LU, 0x09cf09c1LU, 0xa8c9a8c2LU, 0x0ccb0cc3LU, 0xa7c5a7c4LU, 0x03c703c5LU, 0xa2c1a2c6LU, 0x06c306c7LU,
0xb9ddb9c8LU, 0x1ddf1dc9LU, 0xbcd9bccaLU, 0x18db18cbLU, 0xb3d5b3ccLU, 0x17d717cdLU, 0xb6d1b6ceLU, 0x12d312cfLU,
0x85ed85d0LU, 0x21ef21d1LU, 0x80e980d2LU, 0x24eb24d3LU, 0x8fe58fd4LU, 0x2be72bd5LU, 0x8ae18ad6LU, 0x2ee32ed7LU,
0x91fd91d8LU, 0x35ff35d9LU, 0x94f994daLU, 0x30fb30dbLU, 0x9bf59bdcLU, 0x3ff73fddLU, 0x9ef19edeLU, 0x3af33adfLU,
0xfd8dfde0LU, 0x598f59e1LU, 0xf889f8e2LU, 0x5c8b5ce3LU, 0xf785f7e4LU, 0x538753e5LU, 0xf281f2e6LU, 0x568356e7LU,
0xe99de9e8LU, 0x4d9f4de9LU, 0xec99eceaLU, 0x489b48ebLU, 0xe395e3ecLU, 0x479747edLU, 0xe691e6eeLU, 0x429342efLU,
0xd5add5f0LU, 0x71af71f1LU, 0xd0a9d0f2LU, 0x74ab74f3LU, 0xdfa5dff4LU, 0x7ba77bf5LU, 0xdaa1daf6LU, 0x7ea37ef7LU,
0xc1bdc1f8LU, 0x65bf65f9LU, 0xc4b9c4faLU, 0x60bb60fbLU, 0xcbb5cbfcLU, 0x6fb76ffdLU, 0xceb1cefeLU, 0x6ab36affLU };
static const ulong32 rs_tab1[256] = {
0x00000000LU, 0x55a156a4LU, 0xaa0fac05LU, 0xffaefaa1LU, 0x191e150aLU, 0x4cbf43aeLU, 0xb311b90fLU, 0xe6b0efabLU,
0x323c2a14LU, 0x679d7cb0LU, 0x98338611LU, 0xcd92d0b5LU, 0x2b223f1eLU, 0x7e8369baLU, 0x812d931bLU, 0xd48cc5bfLU,
0x64785428LU, 0x31d9028cLU, 0xce77f82dLU, 0x9bd6ae89LU, 0x7d664122LU, 0x28c71786LU, 0xd769ed27LU, 0x82c8bb83LU,
0x56447e3cLU, 0x03e52898LU, 0xfc4bd239LU, 0xa9ea849dLU, 0x4f5a6b36LU, 0x1afb3d92LU, 0xe555c733LU, 0xb0f49197LU,
0xc8f0a850LU, 0x9d51fef4LU, 0x62ff0455LU, 0x375e52f1LU, 0xd1eebd5aLU, 0x844febfeLU, 0x7be1115fLU, 0x2e4047fbLU,
0xfacc8244LU, 0xaf6dd4e0LU, 0x50c32e41LU, 0x056278e5LU, 0xe3d2974eLU, 0xb673c1eaLU, 0x49dd3b4bLU, 0x1c7c6defLU,
0xac88fc78LU, 0xf929aadcLU, 0x0687507dLU, 0x532606d9LU, 0xb596e972LU, 0xe037bfd6LU, 0x1f994577LU, 0x4a3813d3LU,
0x9eb4d66cLU, 0xcb1580c8LU, 0x34bb7a69LU, 0x611a2ccdLU, 0x87aac366LU, 0xd20b95c2LU, 0x2da56f63LU, 0x780439c7LU,
0xddad1da0LU, 0x880c4b04LU, 0x77a2b1a5LU, 0x2203e701LU, 0xc4b308aaLU, 0x91125e0eLU, 0x6ebca4afLU, 0x3b1df20bLU,
0xef9137b4LU, 0xba306110LU, 0x459e9bb1LU, 0x103fcd15LU, 0xf68f22beLU, 0xa32e741aLU, 0x5c808ebbLU, 0x0921d81fLU,
0xb9d54988LU, 0xec741f2cLU, 0x13dae58dLU, 0x467bb329LU, 0xa0cb5c82LU, 0xf56a0a26LU, 0x0ac4f087LU, 0x5f65a623LU,
0x8be9639cLU, 0xde483538LU, 0x21e6cf99LU, 0x7447993dLU, 0x92f77696LU, 0xc7562032LU, 0x38f8da93LU, 0x6d598c37LU,
0x155db5f0LU, 0x40fce354LU, 0xbf5219f5LU, 0xeaf34f51LU, 0x0c43a0faLU, 0x59e2f65eLU, 0xa64c0cffLU, 0xf3ed5a5bLU,
0x27619fe4LU, 0x72c0c940LU, 0x8d6e33e1LU, 0xd8cf6545LU, 0x3e7f8aeeLU, 0x6bdedc4aLU, 0x947026ebLU, 0xc1d1704fLU,
0x7125e1d8LU, 0x2484b77cLU, 0xdb2a4dddLU, 0x8e8b1b79LU, 0x683bf4d2LU, 0x3d9aa276LU, 0xc23458d7LU, 0x97950e73LU,
0x4319cbccLU, 0x16b89d68LU, 0xe91667c9LU, 0xbcb7316dLU, 0x5a07dec6LU, 0x0fa68862LU, 0xf00872c3LU, 0xa5a92467LU,
0xf7173a0dLU, 0xa2b66ca9LU, 0x5d189608LU, 0x08b9c0acLU, 0xee092f07LU, 0xbba879a3LU, 0x44068302LU, 0x11a7d5a6LU,
0xc52b1019LU, 0x908a46bdLU, 0x6f24bc1cLU, 0x3a85eab8LU, 0xdc350513LU, 0x899453b7LU, 0x763aa916LU, 0x239bffb2LU,
0x936f6e25LU, 0xc6ce3881LU, 0x3960c220LU, 0x6cc19484LU, 0x8a717b2fLU, 0xdfd02d8bLU, 0x207ed72aLU, 0x75df818eLU,
0xa1534431LU, 0xf4f21295LU, 0x0b5ce834LU, 0x5efdbe90LU, 0xb84d513bLU, 0xedec079fLU, 0x1242fd3eLU, 0x47e3ab9aLU,
0x3fe7925dLU, 0x6a46c4f9LU, 0x95e83e58LU, 0xc04968fcLU, 0x26f98757LU, 0x7358d1f3LU, 0x8cf62b52LU, 0xd9577df6LU,
0x0ddbb849LU, 0x587aeeedLU, 0xa7d4144cLU, 0xf27542e8LU, 0x14c5ad43LU, 0x4164fbe7LU, 0xbeca0146LU, 0xeb6b57e2LU,
0x5b9fc675LU, 0x0e3e90d1LU, 0xf1906a70LU, 0xa4313cd4LU, 0x4281d37fLU, 0x172085dbLU, 0xe88e7f7aLU, 0xbd2f29deLU,
0x69a3ec61LU, 0x3c02bac5LU, 0xc3ac4064LU, 0x960d16c0LU, 0x70bdf96bLU, 0x251cafcfLU, 0xdab2556eLU, 0x8f1303caLU,
0x2aba27adLU, 0x7f1b7109LU, 0x80b58ba8LU, 0xd514dd0cLU, 0x33a432a7LU, 0x66056403LU, 0x99ab9ea2LU, 0xcc0ac806LU,
0x18860db9LU, 0x4d275b1dLU, 0xb289a1bcLU, 0xe728f718LU, 0x019818b3LU, 0x54394e17LU, 0xab97b4b6LU, 0xfe36e212LU,
0x4ec27385LU, 0x1b632521LU, 0xe4cddf80LU, 0xb16c8924LU, 0x57dc668fLU, 0x027d302bLU, 0xfdd3ca8aLU, 0xa8729c2eLU,
0x7cfe5991LU, 0x295f0f35LU, 0xd6f1f594LU, 0x8350a330LU, 0x65e04c9bLU, 0x30411a3fLU, 0xcfefe09eLU, 0x9a4eb63aLU,
0xe24a8ffdLU, 0xb7ebd959LU, 0x484523f8LU, 0x1de4755cLU, 0xfb549af7LU, 0xaef5cc53LU, 0x515b36f2LU, 0x04fa6056LU,
0xd076a5e9LU, 0x85d7f34dLU, 0x7a7909ecLU, 0x2fd85f48LU, 0xc968b0e3LU, 0x9cc9e647LU, 0x63671ce6LU, 0x36c64a42LU,
0x8632dbd5LU, 0xd3938d71LU, 0x2c3d77d0LU, 0x799c2174LU, 0x9f2ccedfLU, 0xca8d987bLU, 0x352362daLU, 0x6082347eLU,
0xb40ef1c1LU, 0xe1afa765LU, 0x1e015dc4LU, 0x4ba00b60LU, 0xad10e4cbLU, 0xf8b1b26fLU, 0x071f48ceLU, 0x52be1e6aLU };
static const ulong32 rs_tab2[256] = {
0x00000000LU, 0x87fc8255LU, 0x43b549aaLU, 0xc449cbffLU, 0x86279219LU, 0x01db104cLU, 0xc592dbb3LU, 0x426e59e6LU,
0x414e6932LU, 0xc6b2eb67LU, 0x02fb2098LU, 0x8507a2cdLU, 0xc769fb2bLU, 0x4095797eLU, 0x84dcb281LU, 0x032030d4LU,
0x829cd264LU, 0x05605031LU, 0xc1299bceLU, 0x46d5199bLU, 0x04bb407dLU, 0x8347c228LU, 0x470e09d7LU, 0xc0f28b82LU,
0xc3d2bb56LU, 0x442e3903LU, 0x8067f2fcLU, 0x079b70a9LU, 0x45f5294fLU, 0xc209ab1aLU, 0x064060e5LU, 0x81bce2b0LU,
0x4975e9c8LU, 0xce896b9dLU, 0x0ac0a062LU, 0x8d3c2237LU, 0xcf527bd1LU, 0x48aef984LU, 0x8ce7327bLU, 0x0b1bb02eLU,
0x083b80faLU, 0x8fc702afLU, 0x4b8ec950LU, 0xcc724b05LU, 0x8e1c12e3LU, 0x09e090b6LU, 0xcda95b49LU, 0x4a55d91cLU,
0xcbe93bacLU, 0x4c15b9f9LU, 0x885c7206LU, 0x0fa0f053LU, 0x4dcea9b5LU, 0xca322be0LU, 0x0e7be01fLU, 0x8987624aLU,
0x8aa7529eLU, 0x0d5bd0cbLU, 0xc9121b34LU, 0x4eee9961LU, 0x0c80c087LU, 0x8b7c42d2LU, 0x4f35892dLU, 0xc8c90b78LU,
0x92ea9fddLU, 0x15161d88LU, 0xd15fd677LU, 0x56a35422LU, 0x14cd0dc4LU, 0x93318f91LU, 0x5778446eLU, 0xd084c63bLU,
0xd3a4f6efLU, 0x545874baLU, 0x9011bf45LU, 0x17ed3d10LU, 0x558364f6LU, 0xd27fe6a3LU, 0x16362d5cLU, 0x91caaf09LU,
0x10764db9LU, 0x978acfecLU, 0x53c30413LU, 0xd43f8646LU, 0x9651dfa0LU, 0x11ad5df5LU, 0xd5e4960aLU, 0x5218145fLU,
0x5138248bLU, 0xd6c4a6deLU, 0x128d6d21LU, 0x9571ef74LU, 0xd71fb692LU, 0x50e334c7LU, 0x94aaff38LU, 0x13567d6dLU,
0xdb9f7615LU, 0x5c63f440LU, 0x982a3fbfLU, 0x1fd6bdeaLU, 0x5db8e40cLU, 0xda446659LU, 0x1e0dada6LU, 0x99f12ff3LU,
0x9ad11f27LU, 0x1d2d9d72LU, 0xd964568dLU, 0x5e98d4d8LU, 0x1cf68d3eLU, 0x9b0a0f6bLU, 0x5f43c494LU, 0xd8bf46c1LU,
0x5903a471LU, 0xdeff2624LU, 0x1ab6eddbLU, 0x9d4a6f8eLU, 0xdf243668LU, 0x58d8b43dLU, 0x9c917fc2LU, 0x1b6dfd97LU,
0x184dcd43LU, 0x9fb14f16LU, 0x5bf884e9LU, 0xdc0406bcLU, 0x9e6a5f5aLU, 0x1996dd0fLU, 0xdddf16f0LU, 0x5a2394a5LU,
0x699973f7LU, 0xee65f1a2LU, 0x2a2c3a5dLU, 0xadd0b808LU, 0xefbee1eeLU, 0x684263bbLU, 0xac0ba844LU, 0x2bf72a11LU,
0x28d71ac5LU, 0xaf2b9890LU, 0x6b62536fLU, 0xec9ed13aLU, 0xaef088dcLU, 0x290c0a89LU, 0xed45c176LU, 0x6ab94323LU,
0xeb05a193LU, 0x6cf923c6LU, 0xa8b0e839LU, 0x2f4c6a6cLU, 0x6d22338aLU, 0xeadeb1dfLU, 0x2e977a20LU, 0xa96bf875LU,
0xaa4bc8a1LU, 0x2db74af4LU, 0xe9fe810bLU, 0x6e02035eLU, 0x2c6c5ab8LU, 0xab90d8edLU, 0x6fd91312LU, 0xe8259147LU,
0x20ec9a3fLU, 0xa710186aLU, 0x6359d395LU, 0xe4a551c0LU, 0xa6cb0826LU, 0x21378a73LU, 0xe57e418cLU, 0x6282c3d9LU,
0x61a2f30dLU, 0xe65e7158LU, 0x2217baa7LU, 0xa5eb38f2LU, 0xe7856114LU, 0x6079e341LU, 0xa43028beLU, 0x23ccaaebLU,
0xa270485bLU, 0x258cca0eLU, 0xe1c501f1LU, 0x663983a4LU, 0x2457da42LU, 0xa3ab5817LU, 0x67e293e8LU, 0xe01e11bdLU,
0xe33e2169LU, 0x64c2a33cLU, 0xa08b68c3LU, 0x2777ea96LU, 0x6519b370LU, 0xe2e53125LU, 0x26acfadaLU, 0xa150788fLU,
0xfb73ec2aLU, 0x7c8f6e7fLU, 0xb8c6a580LU, 0x3f3a27d5LU, 0x7d547e33LU, 0xfaa8fc66LU, 0x3ee13799LU, 0xb91db5ccLU,
0xba3d8518LU, 0x3dc1074dLU, 0xf988ccb2LU, 0x7e744ee7LU, 0x3c1a1701LU, 0xbbe69554LU, 0x7faf5eabLU, 0xf853dcfeLU,
0x79ef3e4eLU, 0xfe13bc1bLU, 0x3a5a77e4LU, 0xbda6f5b1LU, 0xffc8ac57LU, 0x78342e02LU, 0xbc7de5fdLU, 0x3b8167a8LU,
0x38a1577cLU, 0xbf5dd529LU, 0x7b141ed6LU, 0xfce89c83LU, 0xbe86c565LU, 0x397a4730LU, 0xfd338ccfLU, 0x7acf0e9aLU,
0xb20605e2LU, 0x35fa87b7LU, 0xf1b34c48LU, 0x764fce1dLU, 0x342197fbLU, 0xb3dd15aeLU, 0x7794de51LU, 0xf0685c04LU,
0xf3486cd0LU, 0x74b4ee85LU, 0xb0fd257aLU, 0x3701a72fLU, 0x756ffec9LU, 0xf2937c9cLU, 0x36dab763LU, 0xb1263536LU,
0x309ad786LU, 0xb76655d3LU, 0x732f9e2cLU, 0xf4d31c79LU, 0xb6bd459fLU, 0x3141c7caLU, 0xf5080c35LU, 0x72f48e60LU,
0x71d4beb4LU, 0xf6283ce1LU, 0x3261f71eLU, 0xb59d754bLU, 0xf7f32cadLU, 0x700faef8LU, 0xb4466507LU, 0x33bae752LU };
static const ulong32 rs_tab3[256] = {
0x00000000LU, 0x5ac1f387LU, 0xb4cfab43LU, 0xee0e58c4LU, 0x25d31b86LU, 0x7f12e801LU, 0x911cb0c5LU, 0xcbdd4342LU,
0x4aeb3641LU, 0x102ac5c6LU, 0xfe249d02LU, 0xa4e56e85LU, 0x6f382dc7LU, 0x35f9de40LU, 0xdbf78684LU, 0x81367503LU,
0x949b6c82LU, 0xce5a9f05LU, 0x2054c7c1LU, 0x7a953446LU, 0xb1487704LU, 0xeb898483LU, 0x0587dc47LU, 0x5f462fc0LU,
0xde705ac3LU, 0x84b1a944LU, 0x6abff180LU, 0x307e0207LU, 0xfba34145LU, 0xa162b2c2LU, 0x4f6cea06LU, 0x15ad1981LU,
0x657bd849LU, 0x3fba2bceLU, 0xd1b4730aLU, 0x8b75808dLU, 0x40a8c3cfLU, 0x1a693048LU, 0xf467688cLU, 0xaea69b0bLU,
0x2f90ee08LU, 0x75511d8fLU, 0x9b5f454bLU, 0xc19eb6ccLU, 0x0a43f58eLU, 0x50820609LU, 0xbe8c5ecdLU, 0xe44dad4aLU,
0xf1e0b4cbLU, 0xab21474cLU, 0x452f1f88LU, 0x1feeec0fLU, 0xd433af4dLU, 0x8ef25ccaLU, 0x60fc040eLU, 0x3a3df789LU,
0xbb0b828aLU, 0xe1ca710dLU, 0x0fc429c9LU, 0x5505da4eLU, 0x9ed8990cLU, 0xc4196a8bLU, 0x2a17324fLU, 0x70d6c1c8LU,
0xcaf6fd92LU, 0x90370e15LU, 0x7e3956d1LU, 0x24f8a556LU, 0xef25e614LU, 0xb5e41593LU, 0x5bea4d57LU, 0x012bbed0LU,
0x801dcbd3LU, 0xdadc3854LU, 0x34d26090LU, 0x6e139317LU, 0xa5ced055LU, 0xff0f23d2LU, 0x11017b16LU, 0x4bc08891LU,
0x5e6d9110LU, 0x04ac6297LU, 0xeaa23a53LU, 0xb063c9d4LU, 0x7bbe8a96LU, 0x217f7911LU, 0xcf7121d5LU, 0x95b0d252LU,
0x1486a751LU, 0x4e4754d6LU, 0xa0490c12LU, 0xfa88ff95LU, 0x3155bcd7LU, 0x6b944f50LU, 0x859a1794LU, 0xdf5be413LU,
0xaf8d25dbLU, 0xf54cd65cLU, 0x1b428e98LU, 0x41837d1fLU, 0x8a5e3e5dLU, 0xd09fcddaLU, 0x3e91951eLU, 0x64506699LU,
0xe566139aLU, 0xbfa7e01dLU, 0x51a9b8d9LU, 0x0b684b5eLU, 0xc0b5081cLU, 0x9a74fb9bLU, 0x747aa35fLU, 0x2ebb50d8LU,
0x3b164959LU, 0x61d7badeLU, 0x8fd9e21aLU, 0xd518119dLU, 0x1ec552dfLU, 0x4404a158LU, 0xaa0af99cLU, 0xf0cb0a1bLU,
0x71fd7f18LU, 0x2b3c8c9fLU, 0xc532d45bLU, 0x9ff327dcLU, 0x542e649eLU, 0x0eef9719LU, 0xe0e1cfddLU, 0xba203c5aLU,
0xd9a1b769LU, 0x836044eeLU, 0x6d6e1c2aLU, 0x37afefadLU, 0xfc72acefLU, 0xa6b35f68LU, 0x48bd07acLU, 0x127cf42bLU,
0x934a8128LU, 0xc98b72afLU, 0x27852a6bLU, 0x7d44d9ecLU, 0xb6999aaeLU, 0xec586929LU, 0x025631edLU, 0x5897c26aLU,
0x4d3adbebLU, 0x17fb286cLU, 0xf9f570a8LU, 0xa334832fLU, 0x68e9c06dLU, 0x322833eaLU, 0xdc266b2eLU, 0x86e798a9LU,
0x07d1edaaLU, 0x5d101e2dLU, 0xb31e46e9LU, 0xe9dfb56eLU, 0x2202f62cLU, 0x78c305abLU, 0x96cd5d6fLU, 0xcc0caee8LU,
0xbcda6f20LU, 0xe61b9ca7LU, 0x0815c463LU, 0x52d437e4LU, 0x990974a6LU, 0xc3c88721LU, 0x2dc6dfe5LU, 0x77072c62LU,
0xf6315961LU, 0xacf0aae6LU, 0x42fef222LU, 0x183f01a5LU, 0xd3e242e7LU, 0x8923b160LU, 0x672de9a4LU, 0x3dec1a23LU,
0x284103a2LU, 0x7280f025LU, 0x9c8ea8e1LU, 0xc64f5b66LU, 0x0d921824LU, 0x5753eba3LU, 0xb95db367LU, 0xe39c40e0LU,
0x62aa35e3LU, 0x386bc664LU, 0xd6659ea0LU, 0x8ca46d27LU, 0x47792e65LU, 0x1db8dde2LU, 0xf3b68526LU, 0xa97776a1LU,
0x13574afbLU, 0x4996b97cLU, 0xa798e1b8LU, 0xfd59123fLU, 0x3684517dLU, 0x6c45a2faLU, 0x824bfa3eLU, 0xd88a09b9LU,
0x59bc7cbaLU, 0x037d8f3dLU, 0xed73d7f9LU, 0xb7b2247eLU, 0x7c6f673cLU, 0x26ae94bbLU, 0xc8a0cc7fLU, 0x92613ff8LU,
0x87cc2679LU, 0xdd0dd5feLU, 0x33038d3aLU, 0x69c27ebdLU, 0xa21f3dffLU, 0xf8dece78LU, 0x16d096bcLU, 0x4c11653bLU,
0xcd271038LU, 0x97e6e3bfLU, 0x79e8bb7bLU, 0x232948fcLU, 0xe8f40bbeLU, 0xb235f839LU, 0x5c3ba0fdLU, 0x06fa537aLU,
0x762c92b2LU, 0x2ced6135LU, 0xc2e339f1LU, 0x9822ca76LU, 0x53ff8934LU, 0x093e7ab3LU, 0xe7302277LU, 0xbdf1d1f0LU,
0x3cc7a4f3LU, 0x66065774LU, 0x88080fb0LU, 0xd2c9fc37LU, 0x1914bf75LU, 0x43d54cf2LU, 0xaddb1436LU, 0xf71ae7b1LU,
0xe2b7fe30LU, 0xb8760db7LU, 0x56785573LU, 0x0cb9a6f4LU, 0xc764e5b6LU, 0x9da51631LU, 0x73ab4ef5LU, 0x296abd72LU,
0xa85cc871LU, 0xf29d3bf6LU, 0x1c936332LU, 0x465290b5LU, 0x8d8fd3f7LU, 0xd74e2070LU, 0x394078b4LU, 0x63818b33LU };
static const ulong32 rs_tab4[256] = {
0x00000000LU, 0x58471e5aLU, 0xb08e3cb4LU, 0xe8c922eeLU, 0x2d517825LU, 0x7516667fLU, 0x9ddf4491LU, 0xc5985acbLU,
0x5aa2f04aLU, 0x02e5ee10LU, 0xea2cccfeLU, 0xb26bd2a4LU, 0x77f3886fLU, 0x2fb49635LU, 0xc77db4dbLU, 0x9f3aaa81LU,
0xb409ad94LU, 0xec4eb3ceLU, 0x04879120LU, 0x5cc08f7aLU, 0x9958d5b1LU, 0xc11fcbebLU, 0x29d6e905LU, 0x7191f75fLU,
0xeeab5ddeLU, 0xb6ec4384LU, 0x5e25616aLU, 0x06627f30LU, 0xc3fa25fbLU, 0x9bbd3ba1LU, 0x7374194fLU, 0x2b330715LU,
0x25121765LU, 0x7d55093fLU, 0x959c2bd1LU, 0xcddb358bLU, 0x08436f40LU, 0x5004711aLU, 0xb8cd53f4LU, 0xe08a4daeLU,
0x7fb0e72fLU, 0x27f7f975LU, 0xcf3edb9bLU, 0x9779c5c1LU, 0x52e19f0aLU, 0x0aa68150LU, 0xe26fa3beLU, 0xba28bde4LU,
0x911bbaf1LU, 0xc95ca4abLU, 0x21958645LU, 0x79d2981fLU, 0xbc4ac2d4LU, 0xe40ddc8eLU, 0x0cc4fe60LU, 0x5483e03aLU,
0xcbb94abbLU, 0x93fe54e1LU, 0x7b37760fLU, 0x23706855LU, 0xe6e8329eLU, 0xbeaf2cc4LU, 0x56660e2aLU, 0x0e211070LU,
0x4a242ecaLU, 0x12633090LU, 0xfaaa127eLU, 0xa2ed0c24LU, 0x677556efLU, 0x3f3248b5LU, 0xd7fb6a5bLU, 0x8fbc7401LU,
0x1086de80LU, 0x48c1c0daLU, 0xa008e234LU, 0xf84ffc6eLU, 0x3dd7a6a5LU, 0x6590b8ffLU, 0x8d599a11LU, 0xd51e844bLU,
0xfe2d835eLU, 0xa66a9d04LU, 0x4ea3bfeaLU, 0x16e4a1b0LU, 0xd37cfb7bLU, 0x8b3be521LU, 0x63f2c7cfLU, 0x3bb5d995LU,
0xa48f7314LU, 0xfcc86d4eLU, 0x14014fa0LU, 0x4c4651faLU, 0x89de0b31LU, 0xd199156bLU, 0x39503785LU, 0x611729dfLU,
0x6f3639afLU, 0x377127f5LU, 0xdfb8051bLU, 0x87ff1b41LU, 0x4267418aLU, 0x1a205fd0LU, 0xf2e97d3eLU, 0xaaae6364LU,
0x3594c9e5LU, 0x6dd3d7bfLU, 0x851af551LU, 0xdd5deb0bLU, 0x18c5b1c0LU, 0x4082af9aLU, 0xa84b8d74LU, 0xf00c932eLU,
0xdb3f943bLU, 0x83788a61LU, 0x6bb1a88fLU, 0x33f6b6d5LU, 0xf66eec1eLU, 0xae29f244LU, 0x46e0d0aaLU, 0x1ea7cef0LU,
0x819d6471LU, 0xd9da7a2bLU, 0x311358c5LU, 0x6954469fLU, 0xaccc1c54LU, 0xf48b020eLU, 0x1c4220e0LU, 0x44053ebaLU,
0x94485cd9LU, 0xcc0f4283LU, 0x24c6606dLU, 0x7c817e37LU, 0xb91924fcLU, 0xe15e3aa6LU, 0x09971848LU, 0x51d00612LU,
0xceeaac93LU, 0x96adb2c9LU, 0x7e649027LU, 0x26238e7dLU, 0xe3bbd4b6LU, 0xbbfccaecLU, 0x5335e802LU, 0x0b72f658LU,
0x2041f14dLU, 0x7806ef17LU, 0x90cfcdf9LU, 0xc888d3a3LU, 0x0d108968LU, 0x55579732LU, 0xbd9eb5dcLU, 0xe5d9ab86LU,
0x7ae30107LU, 0x22a41f5dLU, 0xca6d3db3LU, 0x922a23e9LU, 0x57b27922LU, 0x0ff56778LU, 0xe73c4596LU, 0xbf7b5bccLU,
0xb15a4bbcLU, 0xe91d55e6LU, 0x01d47708LU, 0x59936952LU, 0x9c0b3399LU, 0xc44c2dc3LU, 0x2c850f2dLU, 0x74c21177LU,
0xebf8bbf6LU, 0xb3bfa5acLU, 0x5b768742LU, 0x03319918LU, 0xc6a9c3d3LU, 0x9eeedd89LU, 0x7627ff67LU, 0x2e60e13dLU,
0x0553e628LU, 0x5d14f872LU, 0xb5ddda9cLU, 0xed9ac4c6LU, 0x28029e0dLU, 0x70458057LU, 0x988ca2b9LU, 0xc0cbbce3LU,
0x5ff11662LU, 0x07b60838LU, 0xef7f2ad6LU, 0xb738348cLU, 0x72a06e47LU, 0x2ae7701dLU, 0xc22e52f3LU, 0x9a694ca9LU,
0xde6c7213LU, 0x862b6c49LU, 0x6ee24ea7LU, 0x36a550fdLU, 0xf33d0a36LU, 0xab7a146cLU, 0x43b33682LU, 0x1bf428d8LU,
0x84ce8259LU, 0xdc899c03LU, 0x3440beedLU, 0x6c07a0b7LU, 0xa99ffa7cLU, 0xf1d8e426LU, 0x1911c6c8LU, 0x4156d892LU,
0x6a65df87LU, 0x3222c1ddLU, 0xdaebe333LU, 0x82acfd69LU, 0x4734a7a2LU, 0x1f73b9f8LU, 0xf7ba9b16LU, 0xaffd854cLU,
0x30c72fcdLU, 0x68803197LU, 0x80491379LU, 0xd80e0d23LU, 0x1d9657e8LU, 0x45d149b2LU, 0xad186b5cLU, 0xf55f7506LU,
0xfb7e6576LU, 0xa3397b2cLU, 0x4bf059c2LU, 0x13b74798LU, 0xd62f1d53LU, 0x8e680309LU, 0x66a121e7LU, 0x3ee63fbdLU,
0xa1dc953cLU, 0xf99b8b66LU, 0x1152a988LU, 0x4915b7d2LU, 0x8c8ded19LU, 0xd4caf343LU, 0x3c03d1adLU, 0x6444cff7LU,
0x4f77c8e2LU, 0x1730d6b8LU, 0xfff9f456LU, 0xa7beea0cLU, 0x6226b0c7LU, 0x3a61ae9dLU, 0xd2a88c73LU, 0x8aef9229LU,
0x15d538a8LU, 0x4d9226f2LU, 0xa55b041cLU, 0xfd1c1a46LU, 0x3884408dLU, 0x60c35ed7LU, 0x880a7c39LU, 0xd04d6263LU };
static const ulong32 rs_tab5[256] = {
0x00000000LU, 0xdbaec658LU, 0xfb11c1b0LU, 0x20bf07e8LU, 0xbb22cf2dLU, 0x608c0975LU, 0x40330e9dLU, 0x9b9dc8c5LU,
0x3b44d35aLU, 0xe0ea1502LU, 0xc05512eaLU, 0x1bfbd4b2LU, 0x80661c77LU, 0x5bc8da2fLU, 0x7b77ddc7LU, 0xa0d91b9fLU,
0x7688ebb4LU, 0xad262decLU, 0x8d992a04LU, 0x5637ec5cLU, 0xcdaa2499LU, 0x1604e2c1LU, 0x36bbe529LU, 0xed152371LU,
0x4dcc38eeLU, 0x9662feb6LU, 0xb6ddf95eLU, 0x6d733f06LU, 0xf6eef7c3LU, 0x2d40319bLU, 0x0dff3673LU, 0xd651f02bLU,
0xec5d9b25LU, 0x37f35d7dLU, 0x174c5a95LU, 0xcce29ccdLU, 0x577f5408LU, 0x8cd19250LU, 0xac6e95b8LU, 0x77c053e0LU,
0xd719487fLU, 0x0cb78e27LU, 0x2c0889cfLU, 0xf7a64f97LU, 0x6c3b8752LU, 0xb795410aLU, 0x972a46e2LU, 0x4c8480baLU,
0x9ad57091LU, 0x417bb6c9LU, 0x61c4b121LU, 0xba6a7779LU, 0x21f7bfbcLU, 0xfa5979e4LU, 0xdae67e0cLU, 0x0148b854LU,
0xa191a3cbLU, 0x7a3f6593LU, 0x5a80627bLU, 0x812ea423LU, 0x1ab36ce6LU, 0xc11daabeLU, 0xe1a2ad56LU, 0x3a0c6b0eLU,
0x95ba7b4aLU, 0x4e14bd12LU, 0x6eabbafaLU, 0xb5057ca2LU, 0x2e98b467LU, 0xf536723fLU, 0xd58975d7LU, 0x0e27b38fLU,
0xaefea810LU, 0x75506e48LU, 0x55ef69a0LU, 0x8e41aff8LU, 0x15dc673dLU, 0xce72a165LU, 0xeecda68dLU, 0x356360d5LU,
0xe33290feLU, 0x389c56a6LU, 0x1823514eLU, 0xc38d9716LU, 0x58105fd3LU, 0x83be998bLU, 0xa3019e63LU, 0x78af583bLU,
0xd87643a4LU, 0x03d885fcLU, 0x23678214LU, 0xf8c9444cLU, 0x63548c89LU, 0xb8fa4ad1LU, 0x98454d39LU, 0x43eb8b61LU,
0x79e7e06fLU, 0xa2492637LU, 0x82f621dfLU, 0x5958e787LU, 0xc2c52f42LU, 0x196be91aLU, 0x39d4eef2LU, 0xe27a28aaLU,
0x42a33335LU, 0x990df56dLU, 0xb9b2f285LU, 0x621c34ddLU, 0xf981fc18LU, 0x222f3a40LU, 0x02903da8LU, 0xd93efbf0LU,
0x0f6f0bdbLU, 0xd4c1cd83LU, 0xf47eca6bLU, 0x2fd00c33LU, 0xb44dc4f6LU, 0x6fe302aeLU, 0x4f5c0546LU, 0x94f2c31eLU,
0x342bd881LU, 0xef851ed9LU, 0xcf3a1931LU, 0x1494df69LU, 0x8f0917acLU, 0x54a7d1f4LU, 0x7418d61cLU, 0xafb61044LU,
0x6739f694LU, 0xbc9730ccLU, 0x9c283724LU, 0x4786f17cLU, 0xdc1b39b9LU, 0x07b5ffe1LU, 0x270af809LU, 0xfca43e51LU,
0x5c7d25ceLU, 0x87d3e396LU, 0xa76ce47eLU, 0x7cc22226LU, 0xe75feae3LU, 0x3cf12cbbLU, 0x1c4e2b53LU, 0xc7e0ed0bLU,
0x11b11d20LU, 0xca1fdb78LU, 0xeaa0dc90LU, 0x310e1ac8LU, 0xaa93d20dLU, 0x713d1455LU, 0x518213bdLU, 0x8a2cd5e5LU,
0x2af5ce7aLU, 0xf15b0822LU, 0xd1e40fcaLU, 0x0a4ac992LU, 0x91d70157LU, 0x4a79c70fLU, 0x6ac6c0e7LU, 0xb16806bfLU,
0x8b646db1LU, 0x50caabe9LU, 0x7075ac01LU, 0xabdb6a59LU, 0x3046a29cLU, 0xebe864c4LU, 0xcb57632cLU, 0x10f9a574LU,
0xb020beebLU, 0x6b8e78b3LU, 0x4b317f5bLU, 0x909fb903LU, 0x0b0271c6LU, 0xd0acb79eLU, 0xf013b076LU, 0x2bbd762eLU,
0xfdec8605LU, 0x2642405dLU, 0x06fd47b5LU, 0xdd5381edLU, 0x46ce4928LU, 0x9d608f70LU, 0xbddf8898LU, 0x66714ec0LU,
0xc6a8555fLU, 0x1d069307LU, 0x3db994efLU, 0xe61752b7LU, 0x7d8a9a72LU, 0xa6245c2aLU, 0x869b5bc2LU, 0x5d359d9aLU,
0xf2838ddeLU, 0x292d4b86LU, 0x09924c6eLU, 0xd23c8a36LU, 0x49a142f3LU, 0x920f84abLU, 0xb2b08343LU, 0x691e451bLU,
0xc9c75e84LU, 0x126998dcLU, 0x32d69f34LU, 0xe978596cLU, 0x72e591a9LU, 0xa94b57f1LU, 0x89f45019LU, 0x525a9641LU,
0x840b666aLU, 0x5fa5a032LU, 0x7f1aa7daLU, 0xa4b46182LU, 0x3f29a947LU, 0xe4876f1fLU, 0xc43868f7LU, 0x1f96aeafLU,
0xbf4fb530LU, 0x64e17368LU, 0x445e7480LU, 0x9ff0b2d8LU, 0x046d7a1dLU, 0xdfc3bc45LU, 0xff7cbbadLU, 0x24d27df5LU,
0x1ede16fbLU, 0xc570d0a3LU, 0xe5cfd74bLU, 0x3e611113LU, 0xa5fcd9d6LU, 0x7e521f8eLU, 0x5eed1866LU, 0x8543de3eLU,
0x259ac5a1LU, 0xfe3403f9LU, 0xde8b0411LU, 0x0525c249LU, 0x9eb80a8cLU, 0x4516ccd4LU, 0x65a9cb3cLU, 0xbe070d64LU,
0x6856fd4fLU, 0xb3f83b17LU, 0x93473cffLU, 0x48e9faa7LU, 0xd3743262LU, 0x08daf43aLU, 0x2865f3d2LU, 0xf3cb358aLU,
0x53122e15LU, 0x88bce84dLU, 0xa803efa5LU, 0x73ad29fdLU, 0xe830e138LU, 0x339e2760LU, 0x13212088LU, 0xc88fe6d0LU };
static const ulong32 rs_tab6[256] = {
0x00000000LU, 0x9e3d68dbLU, 0x717ad0fbLU, 0xef47b820LU, 0xe2f4edbbLU, 0x7cc98560LU, 0x938e3d40LU, 0x0db3559bLU,
0x89a5973bLU, 0x1798ffe0LU, 0xf8df47c0LU, 0x66e22f1bLU, 0x6b517a80LU, 0xf56c125bLU, 0x1a2baa7bLU, 0x8416c2a0LU,
0x5f076376LU, 0xc13a0badLU, 0x2e7db38dLU, 0xb040db56LU, 0xbdf38ecdLU, 0x23cee616LU, 0xcc895e36LU, 0x52b436edLU,
0xd6a2f44dLU, 0x489f9c96LU, 0xa7d824b6LU, 0x39e54c6dLU, 0x345619f6LU, 0xaa6b712dLU, 0x452cc90dLU, 0xdb11a1d6LU,
0xbe0ec6ecLU, 0x2033ae37LU, 0xcf741617LU, 0x51497eccLU, 0x5cfa2b57LU, 0xc2c7438cLU, 0x2d80fbacLU, 0xb3bd9377LU,
0x37ab51d7LU, 0xa996390cLU, 0x46d1812cLU, 0xd8ece9f7LU, 0xd55fbc6cLU, 0x4b62d4b7LU, 0xa4256c97LU, 0x3a18044cLU,
0xe109a59aLU, 0x7f34cd41LU, 0x90737561LU, 0x0e4e1dbaLU, 0x03fd4821LU, 0x9dc020faLU, 0x728798daLU, 0xecbaf001LU,
0x68ac32a1LU, 0xf6915a7aLU, 0x19d6e25aLU, 0x87eb8a81LU, 0x8a58df1aLU, 0x1465b7c1LU, 0xfb220fe1LU, 0x651f673aLU,
0x311cc195LU, 0xaf21a94eLU, 0x4066116eLU, 0xde5b79b5LU, 0xd3e82c2eLU, 0x4dd544f5LU, 0xa292fcd5LU, 0x3caf940eLU,
0xb8b956aeLU, 0x26843e75LU, 0xc9c38655LU, 0x57feee8eLU, 0x5a4dbb15LU, 0xc470d3ceLU, 0x2b376beeLU, 0xb50a0335LU,
0x6e1ba2e3LU, 0xf026ca38LU, 0x1f617218LU, 0x815c1ac3LU, 0x8cef4f58LU, 0x12d22783LU, 0xfd959fa3LU, 0x63a8f778LU,
0xe7be35d8LU, 0x79835d03LU, 0x96c4e523LU, 0x08f98df8LU, 0x054ad863LU, 0x9b77b0b8LU, 0x74300898LU, 0xea0d6043LU,
0x8f120779LU, 0x112f6fa2LU, 0xfe68d782LU, 0x6055bf59LU, 0x6de6eac2LU, 0xf3db8219LU, 0x1c9c3a39LU, 0x82a152e2LU,
0x06b79042LU, 0x988af899LU, 0x77cd40b9LU, 0xe9f02862LU, 0xe4437df9LU, 0x7a7e1522LU, 0x9539ad02LU, 0x0b04c5d9LU,
0xd015640fLU, 0x4e280cd4LU, 0xa16fb4f4LU, 0x3f52dc2fLU, 0x32e189b4LU, 0xacdce16fLU, 0x439b594fLU, 0xdda63194LU,
0x59b0f334LU, 0xc78d9befLU, 0x28ca23cfLU, 0xb6f74b14LU, 0xbb441e8fLU, 0x25797654LU, 0xca3ece74LU, 0x5403a6afLU,
0x6238cf67LU, 0xfc05a7bcLU, 0x13421f9cLU, 0x8d7f7747LU, 0x80cc22dcLU, 0x1ef14a07LU, 0xf1b6f227LU, 0x6f8b9afcLU,
0xeb9d585cLU, 0x75a03087LU, 0x9ae788a7LU, 0x04dae07cLU, 0x0969b5e7LU, 0x9754dd3cLU, 0x7813651cLU, 0xe62e0dc7LU,
0x3d3fac11LU, 0xa302c4caLU, 0x4c457ceaLU, 0xd2781431LU, 0xdfcb41aaLU, 0x41f62971LU, 0xaeb19151LU, 0x308cf98aLU,
0xb49a3b2aLU, 0x2aa753f1LU, 0xc5e0ebd1LU, 0x5bdd830aLU, 0x566ed691LU, 0xc853be4aLU, 0x2714066aLU, 0xb9296eb1LU,
0xdc36098bLU, 0x420b6150LU, 0xad4cd970LU, 0x3371b1abLU, 0x3ec2e430LU, 0xa0ff8cebLU, 0x4fb834cbLU, 0xd1855c10LU,
0x55939eb0LU, 0xcbaef66bLU, 0x24e94e4bLU, 0xbad42690LU, 0xb767730bLU, 0x295a1bd0LU, 0xc61da3f0LU, 0x5820cb2bLU,
0x83316afdLU, 0x1d0c0226LU, 0xf24bba06LU, 0x6c76d2ddLU, 0x61c58746LU, 0xfff8ef9dLU, 0x10bf57bdLU, 0x8e823f66LU,
0x0a94fdc6LU, 0x94a9951dLU, 0x7bee2d3dLU, 0xe5d345e6LU, 0xe860107dLU, 0x765d78a6LU, 0x991ac086LU, 0x0727a85dLU,
0x53240ef2LU, 0xcd196629LU, 0x225ede09LU, 0xbc63b6d2LU, 0xb1d0e349LU, 0x2fed8b92LU, 0xc0aa33b2LU, 0x5e975b69LU,
0xda8199c9LU, 0x44bcf112LU, 0xabfb4932LU, 0x35c621e9LU, 0x38757472LU, 0xa6481ca9LU, 0x490fa489LU, 0xd732cc52LU,
0x0c236d84LU, 0x921e055fLU, 0x7d59bd7fLU, 0xe364d5a4LU, 0xeed7803fLU, 0x70eae8e4LU, 0x9fad50c4LU, 0x0190381fLU,
0x8586fabfLU, 0x1bbb9264LU, 0xf4fc2a44LU, 0x6ac1429fLU, 0x67721704LU, 0xf94f7fdfLU, 0x1608c7ffLU, 0x8835af24LU,
0xed2ac81eLU, 0x7317a0c5LU, 0x9c5018e5LU, 0x026d703eLU, 0x0fde25a5LU, 0x91e34d7eLU, 0x7ea4f55eLU, 0xe0999d85LU,
0x648f5f25LU, 0xfab237feLU, 0x15f58fdeLU, 0x8bc8e705LU, 0x867bb29eLU, 0x1846da45LU, 0xf7016265LU, 0x693c0abeLU,
0xb22dab68LU, 0x2c10c3b3LU, 0xc3577b93LU, 0x5d6a1348LU, 0x50d946d3LU, 0xcee42e08LU, 0x21a39628LU, 0xbf9efef3LU,
0x3b883c53LU, 0xa5b55488LU, 0x4af2eca8LU, 0xd4cf8473LU, 0xd97cd1e8LU, 0x4741b933LU, 0xa8060113LU, 0x363b69c8LU };
static const ulong32 rs_tab7[256] = {
0x00000000LU, 0x0319e59eLU, 0x06328771LU, 0x052b62efLU, 0x0c6443e2LU, 0x0f7da67cLU, 0x0a56c493LU, 0x094f210dLU,
0x18c88689LU, 0x1bd16317LU, 0x1efa01f8LU, 0x1de3e466LU, 0x14acc56bLU, 0x17b520f5LU, 0x129e421aLU, 0x1187a784LU,
0x30dd415fLU, 0x33c4a4c1LU, 0x36efc62eLU, 0x35f623b0LU, 0x3cb902bdLU, 0x3fa0e723LU, 0x3a8b85ccLU, 0x39926052LU,
0x2815c7d6LU, 0x2b0c2248LU, 0x2e2740a7LU, 0x2d3ea539LU, 0x24718434LU, 0x276861aaLU, 0x22430345LU, 0x215ae6dbLU,
0x60f782beLU, 0x63ee6720LU, 0x66c505cfLU, 0x65dce051LU, 0x6c93c15cLU, 0x6f8a24c2LU, 0x6aa1462dLU, 0x69b8a3b3LU,
0x783f0437LU, 0x7b26e1a9LU, 0x7e0d8346LU, 0x7d1466d8LU, 0x745b47d5LU, 0x7742a24bLU, 0x7269c0a4LU, 0x7170253aLU,
0x502ac3e1LU, 0x5333267fLU, 0x56184490LU, 0x5501a10eLU, 0x5c4e8003LU, 0x5f57659dLU, 0x5a7c0772LU, 0x5965e2ecLU,
0x48e24568LU, 0x4bfba0f6LU, 0x4ed0c219LU, 0x4dc92787LU, 0x4486068aLU, 0x479fe314LU, 0x42b481fbLU, 0x41ad6465LU,
0xc0a34931LU, 0xc3baacafLU, 0xc691ce40LU, 0xc5882bdeLU, 0xccc70ad3LU, 0xcfdeef4dLU, 0xcaf58da2LU, 0xc9ec683cLU,
0xd86bcfb8LU, 0xdb722a26LU, 0xde5948c9LU, 0xdd40ad57LU, 0xd40f8c5aLU, 0xd71669c4LU, 0xd23d0b2bLU, 0xd124eeb5LU,
0xf07e086eLU, 0xf367edf0LU, 0xf64c8f1fLU, 0xf5556a81LU, 0xfc1a4b8cLU, 0xff03ae12LU, 0xfa28ccfdLU, 0xf9312963LU,
0xe8b68ee7LU, 0xebaf6b79LU, 0xee840996LU, 0xed9dec08LU, 0xe4d2cd05LU, 0xe7cb289bLU, 0xe2e04a74LU, 0xe1f9afeaLU,
0xa054cb8fLU, 0xa34d2e11LU, 0xa6664cfeLU, 0xa57fa960LU, 0xac30886dLU, 0xaf296df3LU, 0xaa020f1cLU, 0xa91bea82LU,
0xb89c4d06LU, 0xbb85a898LU, 0xbeaeca77LU, 0xbdb72fe9LU, 0xb4f80ee4LU, 0xb7e1eb7aLU, 0xb2ca8995LU, 0xb1d36c0bLU,
0x90898ad0LU, 0x93906f4eLU, 0x96bb0da1LU, 0x95a2e83fLU, 0x9cedc932LU, 0x9ff42cacLU, 0x9adf4e43LU, 0x99c6abddLU,
0x88410c59LU, 0x8b58e9c7LU, 0x8e738b28LU, 0x8d6a6eb6LU, 0x84254fbbLU, 0x873caa25LU, 0x8217c8caLU, 0x810e2d54LU,
0xcd0b9262LU, 0xce1277fcLU, 0xcb391513LU, 0xc820f08dLU, 0xc16fd180LU, 0xc276341eLU, 0xc75d56f1LU, 0xc444b36fLU,
0xd5c314ebLU, 0xd6daf175LU, 0xd3f1939aLU, 0xd0e87604LU, 0xd9a75709LU, 0xdabeb297LU, 0xdf95d078LU, 0xdc8c35e6LU,
0xfdd6d33dLU, 0xfecf36a3LU, 0xfbe4544cLU, 0xf8fdb1d2LU, 0xf1b290dfLU, 0xf2ab7541LU, 0xf78017aeLU, 0xf499f230LU,
0xe51e55b4LU, 0xe607b02aLU, 0xe32cd2c5LU, 0xe035375bLU, 0xe97a1656LU, 0xea63f3c8LU, 0xef489127LU, 0xec5174b9LU,
0xadfc10dcLU, 0xaee5f542LU, 0xabce97adLU, 0xa8d77233LU, 0xa198533eLU, 0xa281b6a0LU, 0xa7aad44fLU, 0xa4b331d1LU,
0xb5349655LU, 0xb62d73cbLU, 0xb3061124LU, 0xb01ff4baLU, 0xb950d5b7LU, 0xba493029LU, 0xbf6252c6LU, 0xbc7bb758LU,
0x9d215183LU, 0x9e38b41dLU, 0x9b13d6f2LU, 0x980a336cLU, 0x91451261LU, 0x925cf7ffLU, 0x97779510LU, 0x946e708eLU,
0x85e9d70aLU, 0x86f03294LU, 0x83db507bLU, 0x80c2b5e5LU, 0x898d94e8LU, 0x8a947176LU, 0x8fbf1399LU, 0x8ca6f607LU,
0x0da8db53LU, 0x0eb13ecdLU, 0x0b9a5c22LU, 0x0883b9bcLU, 0x01cc98b1LU, 0x02d57d2fLU, 0x07fe1fc0LU, 0x04e7fa5eLU,
0x15605ddaLU, 0x1679b844LU, 0x1352daabLU, 0x104b3f35LU, 0x19041e38LU, 0x1a1dfba6LU, 0x1f369949LU, 0x1c2f7cd7LU,
0x3d759a0cLU, 0x3e6c7f92LU, 0x3b471d7dLU, 0x385ef8e3LU, 0x3111d9eeLU, 0x32083c70LU, 0x37235e9fLU, 0x343abb01LU,
0x25bd1c85LU, 0x26a4f91bLU, 0x238f9bf4LU, 0x20967e6aLU, 0x29d95f67LU, 0x2ac0baf9LU, 0x2febd816LU, 0x2cf23d88LU,
0x6d5f59edLU, 0x6e46bc73LU, 0x6b6dde9cLU, 0x68743b02LU, 0x613b1a0fLU, 0x6222ff91LU, 0x67099d7eLU, 0x641078e0LU,
0x7597df64LU, 0x768e3afaLU, 0x73a55815LU, 0x70bcbd8bLU, 0x79f39c86LU, 0x7aea7918LU, 0x7fc11bf7LU, 0x7cd8fe69LU,
0x5d8218b2LU, 0x5e9bfd2cLU, 0x5bb09fc3LU, 0x58a97a5dLU, 0x51e65b50LU, 0x52ffbeceLU, 0x57d4dc21LU, 0x54cd39bfLU,
0x454a9e3bLU, 0x46537ba5LU, 0x4378194aLU, 0x4061fcd4LU, 0x492eddd9LU, 0x4a373847LU, 0x4f1c5aa8LU, 0x4c05bf36LU };
#endif /* TWOFISH_ALL_TABLES */
#endif

8
xtea.c
View File

@ -119,7 +119,7 @@ int xtea_test(void)
{ 0x75, 0xd7, 0xc5, 0xbf, 0xcf, 0x58, 0xc9, 0x3f };
unsigned char tmp[2][8];
symmetric_key skey;
int err;
int err, y;
if ((err = xtea_setup(key, 16, 0, &skey)) != CRYPT_OK) {
return err;
@ -131,6 +131,12 @@ int xtea_test(void)
return CRYPT_FAIL_TESTVECTOR;
}
/* now see if we can encrypt all zero bytes 1000 times, decrypt and come back where we started */
for (y = 0; y < 8; y++) tmp[0][y] = 0;
for (y = 0; y < 1000; y++) xtea_ecb_encrypt(tmp[0], tmp[0], &skey);
for (y = 0; y < 1000; y++) xtea_ecb_decrypt(tmp[0], tmp[0], &skey);
for (y = 0; y < 8; y++) if (tmp[0][y] != 0) return CRYPT_FAIL_TESTVECTOR;
return CRYPT_OK;
#endif
}

View File

@ -20,24 +20,26 @@ int yarrow_start(prng_state *prng)
/* these are the default hash/cipher combo used */
#ifdef RIJNDAEL
prng->yarrow.cipher = register_cipher(&rijndael_desc);
#elif defined(NOEKEON)
prng->yarrow.cipher = register_cipher(&noekeon_desc);
#elif defined(BLOWFISH)
prng->yarrow.cipher = register_cipher(&blowfish_desc);
#elif defined(TWOFISH)
prng->yarrow.cipher = register_cipher(&twofish_desc);
#elif defined(CAST5)
prng->yarrow.cipher = register_cipher(&cast5_desc);
#elif defined(SAFER)
prng->yarrow.cipher = register_cipher(&saferp_desc);
#elif defined(RC5)
prng->yarrow.cipher = register_cipher(&rc5_desc);
#elif defined(RC6)
prng->yarrow.cipher = register_cipher(&rc6_desc);
#elif defined(XTEA)
prng->yarrow.cipher = register_cipher(&xtea_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(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);
#elif
@ -51,12 +53,14 @@ int yarrow_start(prng_state *prng)
prng->yarrow.hash = register_hash(&sha256_desc);
#elif defined(SHA512)
prng->yarrow.hash = register_hash(&sha512_desc);
#elif defined(SHA384)
prng->yarrow.hash = register_hash(&sha384_desc);
#elif defined(SHA1)
prng->yarrow.hash = register_hash(&sha1_desc);
#elif defined(TIGER)
prng->yarrow.hash = register_hash(&tiger_desc);
#elif defined(SHA1)
prng->yarrow.hash = register_hash(&sha1_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)