put back the 0.95 makefile which was inadvertently merged over

--HG--
branch : libtomcrypt
extra : convert_revision : a8432150cae4fe7441284bef582b002687ede6e0
This commit is contained in:
Matt Johnston
2004-05-31 18:21:40 +00:00
commit dad9dbb0bd
198 changed files with 49909 additions and 0 deletions

9
LICENSE Normal file
View File

@@ -0,0 +1,9 @@
LibTomCrypt is public domain. As should all quality software be.
All of the software was either written by or donated to Tom St Denis for the purposes
of this project. The only exception is the SAFER.C source which has no known
license status (assumed copyrighted) which is why SAFER,C is shipped as disabled.
Tom St Denis

38
PLAN Normal file
View File

@@ -0,0 +1,38 @@
The following functions are marked for removal and/or behavioural change by v1.00 of LibTomCrypt
1. RSA Support
rsa_pad, rsa_signpad, rsa_depad, rsa_signdepad, rsa_import, rsa_export
They will be replaced with PKCS #1 compliant OAEP/PSS padding function as early as v0.96
2. DSA Support
dsa_import, dsa_export
Will be replaced with suitable DSS [what is the standard?] compliant formats. Planned for v0.96
3. Key Ring Support
(all)
The entire API will be dropped as early as v0.96. It was just an experiment and nobody uses it anyways.
4. Test Harness
demos/test.c
The test harness is well overdue for a makeover. Planned for as early as v0.97
Put things in order...
v0.96 -- removed keyring.c and gf.c
-- removed LTC RSA padding
-- DSS support [whatever this entails]
-- Bug fixes/updates to the PKCS/DSS support, should be stable in this release
v0.97 -- Re-written test harness
-- More demos in the manual and demos/ directory
... future???

606
aes.c Normal file
View File

@@ -0,0 +1,606 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
*
* LibTomCrypt is a library that provides various cryptographic
* algorithms in a highly modular and flexible manner.
*
* The library is free for all purposes without any express
* guarantee it works.
*
* Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org
*/
/* AES implementation by Tom St Denis
*
* Derived from the Public Domain source code by
---
* rijndael-alg-fst.c
*
* @version 3.0 (December 2000)
*
* Optimised ANSI C code for the Rijndael cipher (now AES)
*
* @author Vincent Rijmen <vincent.rijmen@esat.kuleuven.ac.be>
* @author Antoon Bosselaers <antoon.bosselaers@esat.kuleuven.ac.be>
* @author Paulo Barreto <paulo.barreto@terra.com.br>
---
*/
#include "mycrypt.h"
#ifdef RIJNDAEL
const struct _cipher_descriptor rijndael_desc =
{
"rijndael",
6,
16, 32, 16, 10,
&rijndael_setup,
&rijndael_ecb_encrypt,
&rijndael_ecb_decrypt,
&rijndael_test,
&rijndael_keysize
};
const struct _cipher_descriptor aes_desc =
{
"aes",
6,
16, 32, 16, 10,
&rijndael_setup,
&rijndael_ecb_encrypt,
&rijndael_ecb_decrypt,
&rijndael_test,
&rijndael_keysize
};
#include "aes_tab.c"
int rijndael_setup(const unsigned char *key, int keylen, int rounds, symmetric_key *skey)
{
int i, j;
ulong32 temp, *rk, *rrk;
_ARGCHK(key != NULL);
_ARGCHK(skey != NULL);
if (keylen != 16 && keylen != 24 && keylen != 32) {
return CRYPT_INVALID_KEYSIZE;
}
if (rounds != 0 && rounds != (10 + ((keylen/8)-2)*2)) {
return CRYPT_INVALID_ROUNDS;
}
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);
LOAD32H(rk[2], key + 8);
LOAD32H(rk[3], key + 12);
if (keylen == 16) {
j = 44;
for (;;) {
temp = rk[3];
rk[4] = rk[0] ^
(Te4_3[byte(temp, 2)]) ^
(Te4_2[byte(temp, 1)]) ^
(Te4_1[byte(temp, 0)]) ^
(Te4_0[byte(temp, 3)]) ^
rcon[i];
rk[5] = rk[1] ^ rk[4];
rk[6] = rk[2] ^ rk[5];
rk[7] = rk[3] ^ rk[6];
if (++i == 10) {
break;
}
rk += 4;
}
} else if (keylen == 24) {
j = 52;
LOAD32H(rk[4], key + 16);
LOAD32H(rk[5], key + 20);
for (;;) {
#ifdef _MSC_VER
temp = skey->rijndael.eK[rk - skey->rijndael.eK + 5];
#else
temp = rk[5];
#endif
rk[ 6] = rk[ 0] ^
(Te4_3[byte(temp, 2)]) ^
(Te4_2[byte(temp, 1)]) ^
(Te4_1[byte(temp, 0)]) ^
(Te4_0[byte(temp, 3)]) ^
rcon[i];
rk[ 7] = rk[ 1] ^ rk[ 6];
rk[ 8] = rk[ 2] ^ rk[ 7];
rk[ 9] = rk[ 3] ^ rk[ 8];
if (++i == 8) {
break;
}
rk[10] = rk[ 4] ^ rk[ 9];
rk[11] = rk[ 5] ^ rk[10];
rk += 6;
}
} else if (keylen == 32) {
j = 60;
LOAD32H(rk[4], key + 16);
LOAD32H(rk[5], key + 20);
LOAD32H(rk[6], key + 24);
LOAD32H(rk[7], key + 28);
for (;;) {
#ifdef _MSC_VER
temp = skey->rijndael.eK[rk - skey->rijndael.eK + 7];
#else
temp = rk[7];
#endif
rk[ 8] = rk[ 0] ^
(Te4_3[byte(temp, 2)]) ^
(Te4_2[byte(temp, 1)]) ^
(Te4_1[byte(temp, 0)]) ^
(Te4_0[byte(temp, 3)]) ^
rcon[i];
rk[ 9] = rk[ 1] ^ rk[ 8];
rk[10] = rk[ 2] ^ rk[ 9];
rk[11] = rk[ 3] ^ rk[10];
if (++i == 7) {
break;
}
temp = rk[11];
rk[12] = rk[ 4] ^
(Te4_3[byte(temp, 3)]) ^
(Te4_2[byte(temp, 2)]) ^
(Te4_1[byte(temp, 1)]) ^
(Te4_0[byte(temp, 0)]);
rk[13] = rk[ 5] ^ rk[12];
rk[14] = rk[ 6] ^ rk[13];
rk[15] = rk[ 7] ^ rk[14];
rk += 8;
}
} else {
/* this can't happen */
j = 4;
}
/* setup the inverse key now */
rk = skey->rijndael.dK;
rrk = skey->rijndael.eK + j - 4;
/* apply the inverse MixColumn transform to all round keys but the first and the last: */
/* copy first */
*rk++ = *rrk++;
*rk++ = *rrk++;
*rk++ = *rrk++;
*rk = *rrk;
rk -= 3; rrk -= 3;
for (i = 1; i < skey->rijndael.Nr; i++) {
rrk -= 4;
rk += 4;
#ifdef SMALL_CODE
temp = rrk[0];
rk[0] =
Td0(255 & Te4[byte(temp, 3)]) ^
Td1(255 & Te4[byte(temp, 2)]) ^
Td2(255 & Te4[byte(temp, 1)]) ^
Td3(255 & Te4[byte(temp, 0)]);
temp = rrk[1];
rk[1] =
Td0(255 & Te4[byte(temp, 3)]) ^
Td1(255 & Te4[byte(temp, 2)]) ^
Td2(255 & Te4[byte(temp, 1)]) ^
Td3(255 & Te4[byte(temp, 0)]);
temp = rrk[2];
rk[2] =
Td0(255 & Te4[byte(temp, 3)]) ^
Td1(255 & Te4[byte(temp, 2)]) ^
Td2(255 & Te4[byte(temp, 1)]) ^
Td3(255 & Te4[byte(temp, 0)]);
temp = rrk[3];
rk[3] =
Td0(255 & Te4[byte(temp, 3)]) ^
Td1(255 & Te4[byte(temp, 2)]) ^
Td2(255 & Te4[byte(temp, 1)]) ^
Td3(255 & Te4[byte(temp, 0)]);
#else
temp = rrk[0];
rk[0] =
Tks0[byte(temp, 3)] ^
Tks1[byte(temp, 2)] ^
Tks2[byte(temp, 1)] ^
Tks3[byte(temp, 0)];
temp = rrk[1];
rk[1] =
Tks0[byte(temp, 3)] ^
Tks1[byte(temp, 2)] ^
Tks2[byte(temp, 1)] ^
Tks3[byte(temp, 0)];
temp = rrk[2];
rk[2] =
Tks0[byte(temp, 3)] ^
Tks1[byte(temp, 2)] ^
Tks2[byte(temp, 1)] ^
Tks3[byte(temp, 0)];
temp = rrk[3];
rk[3] =
Tks0[byte(temp, 3)] ^
Tks1[byte(temp, 2)] ^
Tks2[byte(temp, 1)] ^
Tks3[byte(temp, 0)];
#endif
}
/* copy last */
rrk -= 4;
rk += 4;
*rk++ = *rrk++;
*rk++ = *rrk++;
*rk++ = *rrk++;
*rk = *rrk;
return CRYPT_OK;
}
#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;
_ARGCHK(pt != NULL);
_ARGCHK(ct != NULL);
_ARGCHK(skey != NULL);
Nr = skey->rijndael.Nr;
rk = skey->rijndael.eK;
/*
* map byte array block to cipher state
* and add initial round key:
*/
LOAD32H(s0, pt ); s0 ^= rk[0];
LOAD32H(s1, pt + 4); s1 ^= rk[1];
LOAD32H(s2, pt + 8); s2 ^= rk[2];
LOAD32H(s3, pt + 12); s3 ^= rk[3];
/*
* Nr - 1 full rounds:
*/
r = Nr >> 1;
for (;;) {
t0 =
Te0(byte(s0, 3)) ^
Te1(byte(s1, 2)) ^
Te2(byte(s2, 1)) ^
Te3(byte(s3, 0)) ^
rk[4];
t1 =
Te0(byte(s1, 3)) ^
Te1(byte(s2, 2)) ^
Te2(byte(s3, 1)) ^
Te3(byte(s0, 0)) ^
rk[5];
t2 =
Te0(byte(s2, 3)) ^
Te1(byte(s3, 2)) ^
Te2(byte(s0, 1)) ^
Te3(byte(s1, 0)) ^
rk[6];
t3 =
Te0(byte(s3, 3)) ^
Te1(byte(s0, 2)) ^
Te2(byte(s1, 1)) ^
Te3(byte(s2, 0)) ^
rk[7];
rk += 8;
if (--r == 0) {
break;
}
s0 =
Te0(byte(t0, 3)) ^
Te1(byte(t1, 2)) ^
Te2(byte(t2, 1)) ^
Te3(byte(t3, 0)) ^
rk[0];
s1 =
Te0(byte(t1, 3)) ^
Te1(byte(t2, 2)) ^
Te2(byte(t3, 1)) ^
Te3(byte(t0, 0)) ^
rk[1];
s2 =
Te0(byte(t2, 3)) ^
Te1(byte(t3, 2)) ^
Te2(byte(t0, 1)) ^
Te3(byte(t1, 0)) ^
rk[2];
s3 =
Te0(byte(t3, 3)) ^
Te1(byte(t0, 2)) ^
Te2(byte(t1, 1)) ^
Te3(byte(t2, 0)) ^
rk[3];
}
/*
* apply last round and
* map cipher state to byte array block:
*/
s0 =
(Te4_3[(t0 >> 24) ]) ^
(Te4_2[(t1 >> 16) & 0xff]) ^
(Te4_1[(t2 >> 8) & 0xff]) ^
(Te4_0[(t3 ) & 0xff]) ^
rk[0];
STORE32H(s0, ct);
s1 =
(Te4_3[(t1 >> 24) ]) ^
(Te4_2[(t2 >> 16) & 0xff]) ^
(Te4_1[(t3 >> 8) & 0xff]) ^
(Te4_0[(t0 ) & 0xff]) ^
rk[1];
STORE32H(s1, ct+4);
s2 =
(Te4_3[(t2 >> 24) ]) ^
(Te4_2[(t3 >> 16) & 0xff]) ^
(Te4_1[(t0 >> 8) & 0xff]) ^
(Te4_0[(t1 ) & 0xff]) ^
rk[2];
STORE32H(s2, ct+8);
s3 =
(Te4_3[(t3 >> 24) ]) ^
(Te4_2[(t0 >> 16) & 0xff]) ^
(Te4_1[(t1 >> 8) & 0xff]) ^
(Te4_0[(t2 ) & 0xff]) ^
rk[3];
STORE32H(s3, ct+12);
}
#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;
_ARGCHK(pt != NULL);
_ARGCHK(ct != NULL);
_ARGCHK(skey != NULL);
Nr = skey->rijndael.Nr;
rk = skey->rijndael.dK;
/*
* map byte array block to cipher state
* and add initial round key:
*/
LOAD32H(s0, ct ); s0 ^= rk[0];
LOAD32H(s1, ct + 4); s1 ^= rk[1];
LOAD32H(s2, ct + 8); s2 ^= rk[2];
LOAD32H(s3, ct + 12); s3 ^= rk[3];
/*
* Nr - 1 full rounds:
*/
r = Nr >> 1;
for (;;) {
t0 =
Td0(byte(s0, 3)) ^
Td1(byte(s3, 2)) ^
Td2(byte(s2, 1)) ^
Td3(byte(s1, 0)) ^
rk[4];
t1 =
Td0(byte(s1, 3)) ^
Td1(byte(s0, 2)) ^
Td2(byte(s3, 1)) ^
Td3(byte(s2, 0)) ^
rk[5];
t2 =
Td0(byte(s2, 3)) ^
Td1(byte(s1, 2)) ^
Td2(byte(s0, 1)) ^
Td3(byte(s3, 0)) ^
rk[6];
t3 =
Td0(byte(s3, 3)) ^
Td1(byte(s2, 2)) ^
Td2(byte(s1, 1)) ^
Td3(byte(s0, 0)) ^
rk[7];
rk += 8;
if (--r == 0) {
break;
}
s0 =
Td0(byte(t0, 3)) ^
Td1(byte(t3, 2)) ^
Td2(byte(t2, 1)) ^
Td3(byte(t1, 0)) ^
rk[0];
s1 =
Td0(byte(t1, 3)) ^
Td1(byte(t0, 2)) ^
Td2(byte(t3, 1)) ^
Td3(byte(t2, 0)) ^
rk[1];
s2 =
Td0(byte(t2, 3)) ^
Td1(byte(t1, 2)) ^
Td2(byte(t0, 1)) ^
Td3(byte(t3, 0)) ^
rk[2];
s3 =
Td0(byte(t3, 3)) ^
Td1(byte(t2, 2)) ^
Td2(byte(t1, 1)) ^
Td3(byte(t0, 0)) ^
rk[3];
}
/*
* apply last round and
* map cipher state to byte array block:
*/
s0 =
(Td4[(t0 >> 24) ] & 0xff000000) ^
(Td4[(t3 >> 16) & 0xff] & 0x00ff0000) ^
(Td4[(t2 >> 8) & 0xff] & 0x0000ff00) ^
(Td4[(t1 ) & 0xff] & 0x000000ff) ^
rk[0];
STORE32H(s0, pt);
s1 =
(Td4[(t1 >> 24) ] & 0xff000000) ^
(Td4[(t0 >> 16) & 0xff] & 0x00ff0000) ^
(Td4[(t3 >> 8) & 0xff] & 0x0000ff00) ^
(Td4[(t2 ) & 0xff] & 0x000000ff) ^
rk[1];
STORE32H(s1, pt+4);
s2 =
(Td4[(t2 >> 24) ] & 0xff000000) ^
(Td4[(t1 >> 16) & 0xff] & 0x00ff0000) ^
(Td4[(t0 >> 8) & 0xff] & 0x0000ff00) ^
(Td4[(t3 ) & 0xff] & 0x000000ff) ^
rk[2];
STORE32H(s2, pt+8);
s3 =
(Td4[(t3 >> 24) ] & 0xff000000) ^
(Td4[(t2 >> 16) & 0xff] & 0x00ff0000) ^
(Td4[(t1 >> 8) & 0xff] & 0x0000ff00) ^
(Td4[(t0 ) & 0xff] & 0x000000ff) ^
rk[3];
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
return CRYPT_NOP;
#else
int err;
static const struct {
int keylen;
unsigned char key[32], pt[16], ct[16];
} tests[] = {
{ 16,
{ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
{ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff },
{ 0x69, 0xc4, 0xe0, 0xd8, 0x6a, 0x7b, 0x04, 0x30,
0xd8, 0xcd, 0xb7, 0x80, 0x70, 0xb4, 0xc5, 0x5a }
}, {
24,
{ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17 },
{ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff },
{ 0xdd, 0xa9, 0x7c, 0xa4, 0x86, 0x4c, 0xdf, 0xe0,
0x6e, 0xaf, 0x70, 0xa0, 0xec, 0x0d, 0x71, 0x91 }
}, {
32,
{ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f },
{ 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff },
{ 0x8e, 0xa2, 0xb7, 0xca, 0x51, 0x67, 0x45, 0xbf,
0xea, 0xfc, 0x49, 0x90, 0x4b, 0x49, 0x60, 0x89 }
}
};
symmetric_key key;
unsigned char tmp[2][16];
int i, y;
for (i = 0; i < (int)(sizeof(tests)/sizeof(tests[0])); i++) {
zeromem(&key, sizeof(key));
if ((err = rijndael_setup(tests[i].key, tests[i].keylen, 0, &key)) != CRYPT_OK) {
return err;
}
rijndael_ecb_encrypt(tests[i].pt, tmp[0], &key);
rijndael_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++) 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
}
int rijndael_keysize(int *desired_keysize)
{
_ARGCHK(desired_keysize != NULL);
if (*desired_keysize < 16)
return CRYPT_INVALID_KEYSIZE;
if (*desired_keysize < 24) {
*desired_keysize = 16;
return CRYPT_OK;
} else if (*desired_keysize < 32) {
*desired_keysize = 24;
return CRYPT_OK;
} else {
*desired_keysize = 32;
return CRYPT_OK;
}
}
#endif

1008
aes_tab.c Normal file

File diff suppressed because it is too large Load Diff

55
ampi.c Normal file
View File

@@ -0,0 +1,55 @@
/* Code submitted by Svante Seleborg, cleaned up by Tom St Denis */
#include "mycrypt.h"
#include <stdarg.h>
#ifdef MPI
mp_err mp_init_multi(mp_int *mp, ...)
{
mp_err res = MP_OKAY; /* Assume ok until proven otherwise */
int n = 0; /* Number of ok inits */
mp_int* cur_arg = mp;
va_list args;
va_start(args, mp); /* init args to next argument from caller */
while (cur_arg != NULL) {
if (mp_init(cur_arg) != MP_OKAY) {
/* Oops - error! Back-track and mp_clear what we already
succeeded in init-ing, then return error.
*/
va_list clean_args;
cur_arg = mp;
va_start(clean_args, mp);
while (n--) {
mp_clear(cur_arg);
cur_arg = va_arg(clean_args, mp_int*);
}
va_end(clean_args);
res = MP_MEM;
break;
}
n++;
cur_arg = va_arg(args, mp_int*);
}
va_end(args);
return res; /* Assumed ok, if error flagged above. */
}
/*
Clear all arguments given, ended by a NULL marker.
*/
void mp_clear_multi(mp_int *mp, ...)
{
mp_int* next_mp = mp;
va_list args;
va_start(args, mp);
while (next_mp != NULL) {
mp_clear(next_mp);
next_mp = va_arg(args, mp_int*);
}
va_end(args);
}
#endif

55
authors Normal file
View File

@@ -0,0 +1,55 @@
This is a list of people who have contributed [directly or indirectly] to the project
[in no partcular order]. If you have helped and your name is not here email me at
tomstdenis@yahoo.com.
1) Richard.van.de.Laarschot@ict.nl
Gave help porting the lib to MSVC particularly pointed out various warnings and errors.
2) Richard Heathfield
Gave a lot of help concerning valid C portable code.
3) Ajay K. Agrawal
Helped port the library to MSVC and spotted a few bugs and errors.
4) Brian Gladman
Wrote the AES and Serpent code used. Found a bug in the hash code for certain types of inputs.
5) Svante Seleborg
Submitted the "ampi.c" code as well as many suggestions on improving the readability of the source code.
6) Clay Culver
Submitted a fix for "rsa.c" which cleaned up some code. Submited some other fixes too. :-)
Clay has helped find bugs in various pieces of code including the registry functions, base64 routines
and the make process. He is also now the primary author of the libtomcrypt reference manual and has plan
at making a HTML version.
7) Jason Klapste
Submitted fixes to the yarrow, hash, make process and test code as well as other subtle bug fixes. The
yarrow code can now default to any cipher/hash that is left after you remove them from a build.
8) Dobes Vandermeer <dobes@smartt.com>
Submitted HMAC code that worked flawlessly out of the box... good job! Also submitted a MD4 routine.
Submitted some modified DES code that was merged into the code base [using the libtomcrypt API]
9) Wayne Scott (wscott@bitmover.com)
Submitted base64 that complies with the RFC standards. Submitted some ideas to improve the RSA key generation
as well.
10) Sky Schulz (sky@ogn.com)
Has submitted a set of ideas to improve the library and make it more attractive for professional users.
11) Mike Frysinger
Together with Clay came up with a more "unix friendly" makefile. Mike Frysinger has been keeping copies of
the library for the Gentoo linux distribution.

121
base64.c Normal file
View File

@@ -0,0 +1,121 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
*
* LibTomCrypt is a library that provides various cryptographic
* algorithms in a highly modular and flexible manner.
*
* The library is free for all purposes without any express
* guarantee it works.
*
* Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org
*/
/* compliant base64 code donated by Wayne Scott (wscott@bitmover.com) */
#include "mycrypt.h"
#ifdef BASE64
static const char *codes =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
static const unsigned char map[256] = {
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 62, 255, 255, 255, 63,
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 255, 255,
255, 254, 255, 255, 255, 0, 1, 2, 3, 4, 5, 6,
7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
19, 20, 21, 22, 23, 24, 25, 255, 255, 255, 255, 255,
255, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36,
37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
49, 50, 51, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255 };
int base64_encode(const unsigned char *in, unsigned long len,
unsigned char *out, unsigned long *outlen)
{
unsigned long i, len2, leven;
unsigned char *p;
_ARGCHK(in != NULL);
_ARGCHK(out != NULL);
_ARGCHK(outlen != NULL);
/* valid output size ? */
len2 = 4 * ((len + 2) / 3);
if (*outlen < len2 + 1) {
return CRYPT_BUFFER_OVERFLOW;
}
p = out;
leven = 3*(len / 3);
for (i = 0; i < leven; i += 3) {
*p++ = codes[(in[0] >> 2) & 0x3F];
*p++ = codes[(((in[0] & 3) << 4) + (in[1] >> 4)) & 0x3F];
*p++ = codes[(((in[1] & 0xf) << 2) + (in[2] >> 6)) & 0x3F];
*p++ = codes[in[2] & 0x3F];
in += 3;
}
/* Pad it if necessary... */
if (i < len) {
unsigned a = in[0];
unsigned b = (i+1 < len) ? in[1] : 0;
*p++ = codes[(a >> 2) & 0x3F];
*p++ = codes[(((a & 3) << 4) + (b >> 4)) & 0x3F];
*p++ = (i+1 < len) ? codes[(((b & 0xf) << 2)) & 0x3F] : '=';
*p++ = '=';
}
/* append a NULL byte */
*p = '\0';
/* return ok */
*outlen = p - out;
return CRYPT_OK;
}
int base64_decode(const unsigned char *in, unsigned long len,
unsigned char *out, unsigned long *outlen)
{
unsigned long t, x, y, z;
unsigned char c;
int g;
_ARGCHK(in != NULL);
_ARGCHK(out != NULL);
_ARGCHK(outlen != NULL);
g = 3;
for (x = y = z = t = 0; x < len; x++) {
c = map[in[x]&0xFF];
if (c == 255) continue;
if (c == 254) { c = 0; g--; }
t = (t<<6)|c;
if (++y == 4) {
if (z + g > *outlen) {
return CRYPT_BUFFER_OVERFLOW;
}
out[z++] = (unsigned char)((t>>16)&255);
if (g > 1) out[z++] = (unsigned char)((t>>8)&255);
if (g > 2) out[z++] = (unsigned char)(t&255);
y = t = 0;
}
}
if (y != 0) {
return CRYPT_INVALID_PACKET;
}
*outlen = z;
return CRYPT_OK;
}
#endif

541
blowfish.c Normal file
View File

@@ -0,0 +1,541 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
*
* LibTomCrypt is a library that provides various cryptographic
* algorithms in a highly modular and flexible manner.
*
* The library is free for all purposes without any express
* guarantee it works.
*
* Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org
*/
#include "mycrypt.h"
#ifdef BLOWFISH
const struct _cipher_descriptor blowfish_desc =
{
"blowfish",
0,
8, 56, 8, 16,
&blowfish_setup,
&blowfish_ecb_encrypt,
&blowfish_ecb_decrypt,
&blowfish_test,
&blowfish_keysize
};
static const ulong32 ORIG_P[16 + 2] = {
0x243F6A88UL, 0x85A308D3UL, 0x13198A2EUL, 0x03707344UL,
0xA4093822UL, 0x299F31D0UL, 0x082EFA98UL, 0xEC4E6C89UL,
0x452821E6UL, 0x38D01377UL, 0xBE5466CFUL, 0x34E90C6CUL,
0xC0AC29B7UL, 0xC97C50DDUL, 0x3F84D5B5UL, 0xB5470917UL,
0x9216D5D9UL, 0x8979FB1BUL
};
static const ulong32 ORIG_S[4][256] = {
{ 0xD1310BA6UL, 0x98DFB5ACUL, 0x2FFD72DBUL, 0xD01ADFB7UL,
0xB8E1AFEDUL, 0x6A267E96UL, 0xBA7C9045UL, 0xF12C7F99UL,
0x24A19947UL, 0xB3916CF7UL, 0x0801F2E2UL, 0x858EFC16UL,
0x636920D8UL, 0x71574E69UL, 0xA458FEA3UL, 0xF4933D7EUL,
0x0D95748FUL, 0x728EB658UL, 0x718BCD58UL, 0x82154AEEUL,
0x7B54A41DUL, 0xC25A59B5UL, 0x9C30D539UL, 0x2AF26013UL,
0xC5D1B023UL, 0x286085F0UL, 0xCA417918UL, 0xB8DB38EFUL,
0x8E79DCB0UL, 0x603A180EUL, 0x6C9E0E8BUL, 0xB01E8A3EUL,
0xD71577C1UL, 0xBD314B27UL, 0x78AF2FDAUL, 0x55605C60UL,
0xE65525F3UL, 0xAA55AB94UL, 0x57489862UL, 0x63E81440UL,
0x55CA396AUL, 0x2AAB10B6UL, 0xB4CC5C34UL, 0x1141E8CEUL,
0xA15486AFUL, 0x7C72E993UL, 0xB3EE1411UL, 0x636FBC2AUL,
0x2BA9C55DUL, 0x741831F6UL, 0xCE5C3E16UL, 0x9B87931EUL,
0xAFD6BA33UL, 0x6C24CF5CUL, 0x7A325381UL, 0x28958677UL,
0x3B8F4898UL, 0x6B4BB9AFUL, 0xC4BFE81BUL, 0x66282193UL,
0x61D809CCUL, 0xFB21A991UL, 0x487CAC60UL, 0x5DEC8032UL,
0xEF845D5DUL, 0xE98575B1UL, 0xDC262302UL, 0xEB651B88UL,
0x23893E81UL, 0xD396ACC5UL, 0x0F6D6FF3UL, 0x83F44239UL,
0x2E0B4482UL, 0xA4842004UL, 0x69C8F04AUL, 0x9E1F9B5EUL,
0x21C66842UL, 0xF6E96C9AUL, 0x670C9C61UL, 0xABD388F0UL,
0x6A51A0D2UL, 0xD8542F68UL, 0x960FA728UL, 0xAB5133A3UL,
0x6EEF0B6CUL, 0x137A3BE4UL, 0xBA3BF050UL, 0x7EFB2A98UL,
0xA1F1651DUL, 0x39AF0176UL, 0x66CA593EUL, 0x82430E88UL,
0x8CEE8619UL, 0x456F9FB4UL, 0x7D84A5C3UL, 0x3B8B5EBEUL,
0xE06F75D8UL, 0x85C12073UL, 0x401A449FUL, 0x56C16AA6UL,
0x4ED3AA62UL, 0x363F7706UL, 0x1BFEDF72UL, 0x429B023DUL,
0x37D0D724UL, 0xD00A1248UL, 0xDB0FEAD3UL, 0x49F1C09BUL,
0x075372C9UL, 0x80991B7BUL, 0x25D479D8UL, 0xF6E8DEF7UL,
0xE3FE501AUL, 0xB6794C3BUL, 0x976CE0BDUL, 0x04C006BAUL,
0xC1A94FB6UL, 0x409F60C4UL, 0x5E5C9EC2UL, 0x196A2463UL,
0x68FB6FAFUL, 0x3E6C53B5UL, 0x1339B2EBUL, 0x3B52EC6FUL,
0x6DFC511FUL, 0x9B30952CUL, 0xCC814544UL, 0xAF5EBD09UL,
0xBEE3D004UL, 0xDE334AFDUL, 0x660F2807UL, 0x192E4BB3UL,
0xC0CBA857UL, 0x45C8740FUL, 0xD20B5F39UL, 0xB9D3FBDBUL,
0x5579C0BDUL, 0x1A60320AUL, 0xD6A100C6UL, 0x402C7279UL,
0x679F25FEUL, 0xFB1FA3CCUL, 0x8EA5E9F8UL, 0xDB3222F8UL,
0x3C7516DFUL, 0xFD616B15UL, 0x2F501EC8UL, 0xAD0552ABUL,
0x323DB5FAUL, 0xFD238760UL, 0x53317B48UL, 0x3E00DF82UL,
0x9E5C57BBUL, 0xCA6F8CA0UL, 0x1A87562EUL, 0xDF1769DBUL,
0xD542A8F6UL, 0x287EFFC3UL, 0xAC6732C6UL, 0x8C4F5573UL,
0x695B27B0UL, 0xBBCA58C8UL, 0xE1FFA35DUL, 0xB8F011A0UL,
0x10FA3D98UL, 0xFD2183B8UL, 0x4AFCB56CUL, 0x2DD1D35BUL,
0x9A53E479UL, 0xB6F84565UL, 0xD28E49BCUL, 0x4BFB9790UL,
0xE1DDF2DAUL, 0xA4CB7E33UL, 0x62FB1341UL, 0xCEE4C6E8UL,
0xEF20CADAUL, 0x36774C01UL, 0xD07E9EFEUL, 0x2BF11FB4UL,
0x95DBDA4DUL, 0xAE909198UL, 0xEAAD8E71UL, 0x6B93D5A0UL,
0xD08ED1D0UL, 0xAFC725E0UL, 0x8E3C5B2FUL, 0x8E7594B7UL,
0x8FF6E2FBUL, 0xF2122B64UL, 0x8888B812UL, 0x900DF01CUL,
0x4FAD5EA0UL, 0x688FC31CUL, 0xD1CFF191UL, 0xB3A8C1ADUL,
0x2F2F2218UL, 0xBE0E1777UL, 0xEA752DFEUL, 0x8B021FA1UL,
0xE5A0CC0FUL, 0xB56F74E8UL, 0x18ACF3D6UL, 0xCE89E299UL,
0xB4A84FE0UL, 0xFD13E0B7UL, 0x7CC43B81UL, 0xD2ADA8D9UL,
0x165FA266UL, 0x80957705UL, 0x93CC7314UL, 0x211A1477UL,
0xE6AD2065UL, 0x77B5FA86UL, 0xC75442F5UL, 0xFB9D35CFUL,
0xEBCDAF0CUL, 0x7B3E89A0UL, 0xD6411BD3UL, 0xAE1E7E49UL,
0x00250E2DUL, 0x2071B35EUL, 0x226800BBUL, 0x57B8E0AFUL,
0x2464369BUL, 0xF009B91EUL, 0x5563911DUL, 0x59DFA6AAUL,
0x78C14389UL, 0xD95A537FUL, 0x207D5BA2UL, 0x02E5B9C5UL,
0x83260376UL, 0x6295CFA9UL, 0x11C81968UL, 0x4E734A41UL,
0xB3472DCAUL, 0x7B14A94AUL, 0x1B510052UL, 0x9A532915UL,
0xD60F573FUL, 0xBC9BC6E4UL, 0x2B60A476UL, 0x81E67400UL,
0x08BA6FB5UL, 0x571BE91FUL, 0xF296EC6BUL, 0x2A0DD915UL,
0xB6636521UL, 0xE7B9F9B6UL, 0xFF34052EUL, 0xC5855664UL,
0x53B02D5DUL, 0xA99F8FA1UL, 0x08BA4799UL, 0x6E85076AUL },
{ 0x4B7A70E9UL, 0xB5B32944UL, 0xDB75092EUL, 0xC4192623UL,
0xAD6EA6B0UL, 0x49A7DF7DUL, 0x9CEE60B8UL, 0x8FEDB266UL,
0xECAA8C71UL, 0x699A17FFUL, 0x5664526CUL, 0xC2B19EE1UL,
0x193602A5UL, 0x75094C29UL, 0xA0591340UL, 0xE4183A3EUL,
0x3F54989AUL, 0x5B429D65UL, 0x6B8FE4D6UL, 0x99F73FD6UL,
0xA1D29C07UL, 0xEFE830F5UL, 0x4D2D38E6UL, 0xF0255DC1UL,
0x4CDD2086UL, 0x8470EB26UL, 0x6382E9C6UL, 0x021ECC5EUL,
0x09686B3FUL, 0x3EBAEFC9UL, 0x3C971814UL, 0x6B6A70A1UL,
0x687F3584UL, 0x52A0E286UL, 0xB79C5305UL, 0xAA500737UL,
0x3E07841CUL, 0x7FDEAE5CUL, 0x8E7D44ECUL, 0x5716F2B8UL,
0xB03ADA37UL, 0xF0500C0DUL, 0xF01C1F04UL, 0x0200B3FFUL,
0xAE0CF51AUL, 0x3CB574B2UL, 0x25837A58UL, 0xDC0921BDUL,
0xD19113F9UL, 0x7CA92FF6UL, 0x94324773UL, 0x22F54701UL,
0x3AE5E581UL, 0x37C2DADCUL, 0xC8B57634UL, 0x9AF3DDA7UL,
0xA9446146UL, 0x0FD0030EUL, 0xECC8C73EUL, 0xA4751E41UL,
0xE238CD99UL, 0x3BEA0E2FUL, 0x3280BBA1UL, 0x183EB331UL,
0x4E548B38UL, 0x4F6DB908UL, 0x6F420D03UL, 0xF60A04BFUL,
0x2CB81290UL, 0x24977C79UL, 0x5679B072UL, 0xBCAF89AFUL,
0xDE9A771FUL, 0xD9930810UL, 0xB38BAE12UL, 0xDCCF3F2EUL,
0x5512721FUL, 0x2E6B7124UL, 0x501ADDE6UL, 0x9F84CD87UL,
0x7A584718UL, 0x7408DA17UL, 0xBC9F9ABCUL, 0xE94B7D8CUL,
0xEC7AEC3AUL, 0xDB851DFAUL, 0x63094366UL, 0xC464C3D2UL,
0xEF1C1847UL, 0x3215D908UL, 0xDD433B37UL, 0x24C2BA16UL,
0x12A14D43UL, 0x2A65C451UL, 0x50940002UL, 0x133AE4DDUL,
0x71DFF89EUL, 0x10314E55UL, 0x81AC77D6UL, 0x5F11199BUL,
0x043556F1UL, 0xD7A3C76BUL, 0x3C11183BUL, 0x5924A509UL,
0xF28FE6EDUL, 0x97F1FBFAUL, 0x9EBABF2CUL, 0x1E153C6EUL,
0x86E34570UL, 0xEAE96FB1UL, 0x860E5E0AUL, 0x5A3E2AB3UL,
0x771FE71CUL, 0x4E3D06FAUL, 0x2965DCB9UL, 0x99E71D0FUL,
0x803E89D6UL, 0x5266C825UL, 0x2E4CC978UL, 0x9C10B36AUL,
0xC6150EBAUL, 0x94E2EA78UL, 0xA5FC3C53UL, 0x1E0A2DF4UL,
0xF2F74EA7UL, 0x361D2B3DUL, 0x1939260FUL, 0x19C27960UL,
0x5223A708UL, 0xF71312B6UL, 0xEBADFE6EUL, 0xEAC31F66UL,
0xE3BC4595UL, 0xA67BC883UL, 0xB17F37D1UL, 0x018CFF28UL,
0xC332DDEFUL, 0xBE6C5AA5UL, 0x65582185UL, 0x68AB9802UL,
0xEECEA50FUL, 0xDB2F953BUL, 0x2AEF7DADUL, 0x5B6E2F84UL,
0x1521B628UL, 0x29076170UL, 0xECDD4775UL, 0x619F1510UL,
0x13CCA830UL, 0xEB61BD96UL, 0x0334FE1EUL, 0xAA0363CFUL,
0xB5735C90UL, 0x4C70A239UL, 0xD59E9E0BUL, 0xCBAADE14UL,
0xEECC86BCUL, 0x60622CA7UL, 0x9CAB5CABUL, 0xB2F3846EUL,
0x648B1EAFUL, 0x19BDF0CAUL, 0xA02369B9UL, 0x655ABB50UL,
0x40685A32UL, 0x3C2AB4B3UL, 0x319EE9D5UL, 0xC021B8F7UL,
0x9B540B19UL, 0x875FA099UL, 0x95F7997EUL, 0x623D7DA8UL,
0xF837889AUL, 0x97E32D77UL, 0x11ED935FUL, 0x16681281UL,
0x0E358829UL, 0xC7E61FD6UL, 0x96DEDFA1UL, 0x7858BA99UL,
0x57F584A5UL, 0x1B227263UL, 0x9B83C3FFUL, 0x1AC24696UL,
0xCDB30AEBUL, 0x532E3054UL, 0x8FD948E4UL, 0x6DBC3128UL,
0x58EBF2EFUL, 0x34C6FFEAUL, 0xFE28ED61UL, 0xEE7C3C73UL,
0x5D4A14D9UL, 0xE864B7E3UL, 0x42105D14UL, 0x203E13E0UL,
0x45EEE2B6UL, 0xA3AAABEAUL, 0xDB6C4F15UL, 0xFACB4FD0UL,
0xC742F442UL, 0xEF6ABBB5UL, 0x654F3B1DUL, 0x41CD2105UL,
0xD81E799EUL, 0x86854DC7UL, 0xE44B476AUL, 0x3D816250UL,
0xCF62A1F2UL, 0x5B8D2646UL, 0xFC8883A0UL, 0xC1C7B6A3UL,
0x7F1524C3UL, 0x69CB7492UL, 0x47848A0BUL, 0x5692B285UL,
0x095BBF00UL, 0xAD19489DUL, 0x1462B174UL, 0x23820E00UL,
0x58428D2AUL, 0x0C55F5EAUL, 0x1DADF43EUL, 0x233F7061UL,
0x3372F092UL, 0x8D937E41UL, 0xD65FECF1UL, 0x6C223BDBUL,
0x7CDE3759UL, 0xCBEE7460UL, 0x4085F2A7UL, 0xCE77326EUL,
0xA6078084UL, 0x19F8509EUL, 0xE8EFD855UL, 0x61D99735UL,
0xA969A7AAUL, 0xC50C06C2UL, 0x5A04ABFCUL, 0x800BCADCUL,
0x9E447A2EUL, 0xC3453484UL, 0xFDD56705UL, 0x0E1E9EC9UL,
0xDB73DBD3UL, 0x105588CDUL, 0x675FDA79UL, 0xE3674340UL,
0xC5C43465UL, 0x713E38D8UL, 0x3D28F89EUL, 0xF16DFF20UL,
0x153E21E7UL, 0x8FB03D4AUL, 0xE6E39F2BUL, 0xDB83ADF7UL },
{ 0xE93D5A68UL, 0x948140F7UL, 0xF64C261CUL, 0x94692934UL,
0x411520F7UL, 0x7602D4F7UL, 0xBCF46B2EUL, 0xD4A20068UL,
0xD4082471UL, 0x3320F46AUL, 0x43B7D4B7UL, 0x500061AFUL,
0x1E39F62EUL, 0x97244546UL, 0x14214F74UL, 0xBF8B8840UL,
0x4D95FC1DUL, 0x96B591AFUL, 0x70F4DDD3UL, 0x66A02F45UL,
0xBFBC09ECUL, 0x03BD9785UL, 0x7FAC6DD0UL, 0x31CB8504UL,
0x96EB27B3UL, 0x55FD3941UL, 0xDA2547E6UL, 0xABCA0A9AUL,
0x28507825UL, 0x530429F4UL, 0x0A2C86DAUL, 0xE9B66DFBUL,
0x68DC1462UL, 0xD7486900UL, 0x680EC0A4UL, 0x27A18DEEUL,
0x4F3FFEA2UL, 0xE887AD8CUL, 0xB58CE006UL, 0x7AF4D6B6UL,
0xAACE1E7CUL, 0xD3375FECUL, 0xCE78A399UL, 0x406B2A42UL,
0x20FE9E35UL, 0xD9F385B9UL, 0xEE39D7ABUL, 0x3B124E8BUL,
0x1DC9FAF7UL, 0x4B6D1856UL, 0x26A36631UL, 0xEAE397B2UL,
0x3A6EFA74UL, 0xDD5B4332UL, 0x6841E7F7UL, 0xCA7820FBUL,
0xFB0AF54EUL, 0xD8FEB397UL, 0x454056ACUL, 0xBA489527UL,
0x55533A3AUL, 0x20838D87UL, 0xFE6BA9B7UL, 0xD096954BUL,
0x55A867BCUL, 0xA1159A58UL, 0xCCA92963UL, 0x99E1DB33UL,
0xA62A4A56UL, 0x3F3125F9UL, 0x5EF47E1CUL, 0x9029317CUL,
0xFDF8E802UL, 0x04272F70UL, 0x80BB155CUL, 0x05282CE3UL,
0x95C11548UL, 0xE4C66D22UL, 0x48C1133FUL, 0xC70F86DCUL,
0x07F9C9EEUL, 0x41041F0FUL, 0x404779A4UL, 0x5D886E17UL,
0x325F51EBUL, 0xD59BC0D1UL, 0xF2BCC18FUL, 0x41113564UL,
0x257B7834UL, 0x602A9C60UL, 0xDFF8E8A3UL, 0x1F636C1BUL,
0x0E12B4C2UL, 0x02E1329EUL, 0xAF664FD1UL, 0xCAD18115UL,
0x6B2395E0UL, 0x333E92E1UL, 0x3B240B62UL, 0xEEBEB922UL,
0x85B2A20EUL, 0xE6BA0D99UL, 0xDE720C8CUL, 0x2DA2F728UL,
0xD0127845UL, 0x95B794FDUL, 0x647D0862UL, 0xE7CCF5F0UL,
0x5449A36FUL, 0x877D48FAUL, 0xC39DFD27UL, 0xF33E8D1EUL,
0x0A476341UL, 0x992EFF74UL, 0x3A6F6EABUL, 0xF4F8FD37UL,
0xA812DC60UL, 0xA1EBDDF8UL, 0x991BE14CUL, 0xDB6E6B0DUL,
0xC67B5510UL, 0x6D672C37UL, 0x2765D43BUL, 0xDCD0E804UL,
0xF1290DC7UL, 0xCC00FFA3UL, 0xB5390F92UL, 0x690FED0BUL,
0x667B9FFBUL, 0xCEDB7D9CUL, 0xA091CF0BUL, 0xD9155EA3UL,
0xBB132F88UL, 0x515BAD24UL, 0x7B9479BFUL, 0x763BD6EBUL,
0x37392EB3UL, 0xCC115979UL, 0x8026E297UL, 0xF42E312DUL,
0x6842ADA7UL, 0xC66A2B3BUL, 0x12754CCCUL, 0x782EF11CUL,
0x6A124237UL, 0xB79251E7UL, 0x06A1BBE6UL, 0x4BFB6350UL,
0x1A6B1018UL, 0x11CAEDFAUL, 0x3D25BDD8UL, 0xE2E1C3C9UL,
0x44421659UL, 0x0A121386UL, 0xD90CEC6EUL, 0xD5ABEA2AUL,
0x64AF674EUL, 0xDA86A85FUL, 0xBEBFE988UL, 0x64E4C3FEUL,
0x9DBC8057UL, 0xF0F7C086UL, 0x60787BF8UL, 0x6003604DUL,
0xD1FD8346UL, 0xF6381FB0UL, 0x7745AE04UL, 0xD736FCCCUL,
0x83426B33UL, 0xF01EAB71UL, 0xB0804187UL, 0x3C005E5FUL,
0x77A057BEUL, 0xBDE8AE24UL, 0x55464299UL, 0xBF582E61UL,
0x4E58F48FUL, 0xF2DDFDA2UL, 0xF474EF38UL, 0x8789BDC2UL,
0x5366F9C3UL, 0xC8B38E74UL, 0xB475F255UL, 0x46FCD9B9UL,
0x7AEB2661UL, 0x8B1DDF84UL, 0x846A0E79UL, 0x915F95E2UL,
0x466E598EUL, 0x20B45770UL, 0x8CD55591UL, 0xC902DE4CUL,
0xB90BACE1UL, 0xBB8205D0UL, 0x11A86248UL, 0x7574A99EUL,
0xB77F19B6UL, 0xE0A9DC09UL, 0x662D09A1UL, 0xC4324633UL,
0xE85A1F02UL, 0x09F0BE8CUL, 0x4A99A025UL, 0x1D6EFE10UL,
0x1AB93D1DUL, 0x0BA5A4DFUL, 0xA186F20FUL, 0x2868F169UL,
0xDCB7DA83UL, 0x573906FEUL, 0xA1E2CE9BUL, 0x4FCD7F52UL,
0x50115E01UL, 0xA70683FAUL, 0xA002B5C4UL, 0x0DE6D027UL,
0x9AF88C27UL, 0x773F8641UL, 0xC3604C06UL, 0x61A806B5UL,
0xF0177A28UL, 0xC0F586E0UL, 0x006058AAUL, 0x30DC7D62UL,
0x11E69ED7UL, 0x2338EA63UL, 0x53C2DD94UL, 0xC2C21634UL,
0xBBCBEE56UL, 0x90BCB6DEUL, 0xEBFC7DA1UL, 0xCE591D76UL,
0x6F05E409UL, 0x4B7C0188UL, 0x39720A3DUL, 0x7C927C24UL,
0x86E3725FUL, 0x724D9DB9UL, 0x1AC15BB4UL, 0xD39EB8FCUL,
0xED545578UL, 0x08FCA5B5UL, 0xD83D7CD3UL, 0x4DAD0FC4UL,
0x1E50EF5EUL, 0xB161E6F8UL, 0xA28514D9UL, 0x6C51133CUL,
0x6FD5C7E7UL, 0x56E14EC4UL, 0x362ABFCEUL, 0xDDC6C837UL,
0xD79A3234UL, 0x92638212UL, 0x670EFA8EUL, 0x406000E0UL },
{ 0x3A39CE37UL, 0xD3FAF5CFUL, 0xABC27737UL, 0x5AC52D1BUL,
0x5CB0679EUL, 0x4FA33742UL, 0xD3822740UL, 0x99BC9BBEUL,
0xD5118E9DUL, 0xBF0F7315UL, 0xD62D1C7EUL, 0xC700C47BUL,
0xB78C1B6BUL, 0x21A19045UL, 0xB26EB1BEUL, 0x6A366EB4UL,
0x5748AB2FUL, 0xBC946E79UL, 0xC6A376D2UL, 0x6549C2C8UL,
0x530FF8EEUL, 0x468DDE7DUL, 0xD5730A1DUL, 0x4CD04DC6UL,
0x2939BBDBUL, 0xA9BA4650UL, 0xAC9526E8UL, 0xBE5EE304UL,
0xA1FAD5F0UL, 0x6A2D519AUL, 0x63EF8CE2UL, 0x9A86EE22UL,
0xC089C2B8UL, 0x43242EF6UL, 0xA51E03AAUL, 0x9CF2D0A4UL,
0x83C061BAUL, 0x9BE96A4DUL, 0x8FE51550UL, 0xBA645BD6UL,
0x2826A2F9UL, 0xA73A3AE1UL, 0x4BA99586UL, 0xEF5562E9UL,
0xC72FEFD3UL, 0xF752F7DAUL, 0x3F046F69UL, 0x77FA0A59UL,
0x80E4A915UL, 0x87B08601UL, 0x9B09E6ADUL, 0x3B3EE593UL,
0xE990FD5AUL, 0x9E34D797UL, 0x2CF0B7D9UL, 0x022B8B51UL,
0x96D5AC3AUL, 0x017DA67DUL, 0xD1CF3ED6UL, 0x7C7D2D28UL,
0x1F9F25CFUL, 0xADF2B89BUL, 0x5AD6B472UL, 0x5A88F54CUL,
0xE029AC71UL, 0xE019A5E6UL, 0x47B0ACFDUL, 0xED93FA9BUL,
0xE8D3C48DUL, 0x283B57CCUL, 0xF8D56629UL, 0x79132E28UL,
0x785F0191UL, 0xED756055UL, 0xF7960E44UL, 0xE3D35E8CUL,
0x15056DD4UL, 0x88F46DBAUL, 0x03A16125UL, 0x0564F0BDUL,
0xC3EB9E15UL, 0x3C9057A2UL, 0x97271AECUL, 0xA93A072AUL,
0x1B3F6D9BUL, 0x1E6321F5UL, 0xF59C66FBUL, 0x26DCF319UL,
0x7533D928UL, 0xB155FDF5UL, 0x03563482UL, 0x8ABA3CBBUL,
0x28517711UL, 0xC20AD9F8UL, 0xABCC5167UL, 0xCCAD925FUL,
0x4DE81751UL, 0x3830DC8EUL, 0x379D5862UL, 0x9320F991UL,
0xEA7A90C2UL, 0xFB3E7BCEUL, 0x5121CE64UL, 0x774FBE32UL,
0xA8B6E37EUL, 0xC3293D46UL, 0x48DE5369UL, 0x6413E680UL,
0xA2AE0810UL, 0xDD6DB224UL, 0x69852DFDUL, 0x09072166UL,
0xB39A460AUL, 0x6445C0DDUL, 0x586CDECFUL, 0x1C20C8AEUL,
0x5BBEF7DDUL, 0x1B588D40UL, 0xCCD2017FUL, 0x6BB4E3BBUL,
0xDDA26A7EUL, 0x3A59FF45UL, 0x3E350A44UL, 0xBCB4CDD5UL,
0x72EACEA8UL, 0xFA6484BBUL, 0x8D6612AEUL, 0xBF3C6F47UL,
0xD29BE463UL, 0x542F5D9EUL, 0xAEC2771BUL, 0xF64E6370UL,
0x740E0D8DUL, 0xE75B1357UL, 0xF8721671UL, 0xAF537D5DUL,
0x4040CB08UL, 0x4EB4E2CCUL, 0x34D2466AUL, 0x0115AF84UL,
0xE1B00428UL, 0x95983A1DUL, 0x06B89FB4UL, 0xCE6EA048UL,
0x6F3F3B82UL, 0x3520AB82UL, 0x011A1D4BUL, 0x277227F8UL,
0x611560B1UL, 0xE7933FDCUL, 0xBB3A792BUL, 0x344525BDUL,
0xA08839E1UL, 0x51CE794BUL, 0x2F32C9B7UL, 0xA01FBAC9UL,
0xE01CC87EUL, 0xBCC7D1F6UL, 0xCF0111C3UL, 0xA1E8AAC7UL,
0x1A908749UL, 0xD44FBD9AUL, 0xD0DADECBUL, 0xD50ADA38UL,
0x0339C32AUL, 0xC6913667UL, 0x8DF9317CUL, 0xE0B12B4FUL,
0xF79E59B7UL, 0x43F5BB3AUL, 0xF2D519FFUL, 0x27D9459CUL,
0xBF97222CUL, 0x15E6FC2AUL, 0x0F91FC71UL, 0x9B941525UL,
0xFAE59361UL, 0xCEB69CEBUL, 0xC2A86459UL, 0x12BAA8D1UL,
0xB6C1075EUL, 0xE3056A0CUL, 0x10D25065UL, 0xCB03A442UL,
0xE0EC6E0EUL, 0x1698DB3BUL, 0x4C98A0BEUL, 0x3278E964UL,
0x9F1F9532UL, 0xE0D392DFUL, 0xD3A0342BUL, 0x8971F21EUL,
0x1B0A7441UL, 0x4BA3348CUL, 0xC5BE7120UL, 0xC37632D8UL,
0xDF359F8DUL, 0x9B992F2EUL, 0xE60B6F47UL, 0x0FE3F11DUL,
0xE54CDA54UL, 0x1EDAD891UL, 0xCE6279CFUL, 0xCD3E7E6FUL,
0x1618B166UL, 0xFD2C1D05UL, 0x848FD2C5UL, 0xF6FB2299UL,
0xF523F357UL, 0xA6327623UL, 0x93A83531UL, 0x56CCCD02UL,
0xACF08162UL, 0x5A75EBB5UL, 0x6E163697UL, 0x88D273CCUL,
0xDE966292UL, 0x81B949D0UL, 0x4C50901BUL, 0x71C65614UL,
0xE6C6C7BDUL, 0x327A140AUL, 0x45E1D006UL, 0xC3F27B9AUL,
0xC9AA53FDUL, 0x62A80F00UL, 0xBB25BFE2UL, 0x35BDD2F6UL,
0x71126905UL, 0xB2040222UL, 0xB6CBCF7CUL, 0xCD769C2BUL,
0x53113EC0UL, 0x1640E3D3UL, 0x38ABBD60UL, 0x2547ADF0UL,
0xBA38209CUL, 0xF746CE76UL, 0x77AFA1C5UL, 0x20756060UL,
0x85CBFE4EUL, 0x8AE88DD8UL, 0x7AAAF9B0UL, 0x4CF9AA7EUL,
0x1948C25CUL, 0x02FB8A8CUL, 0x01C36AE4UL, 0xD6EBE1F9UL,
0x90D4F869UL, 0xA65CDEA0UL, 0x3F09252DUL, 0xC208E69FUL,
0xB74E6132UL, 0xCE77E25BUL, 0x578FDFE3UL, 0x3AC372E6UL }
};
int blowfish_setup(const unsigned char *key, int keylen, int num_rounds,
symmetric_key *skey)
{
ulong32 x, y, z, A;
unsigned char B[8];
_ARGCHK(key != NULL);
_ARGCHK(skey != NULL);
/* check key length */
if (keylen < 8 || keylen > 56) {
return CRYPT_INVALID_KEYSIZE;
}
/* check rounds */
if (num_rounds != 0 && num_rounds != 16) {
return CRYPT_INVALID_ROUNDS;
}
/* load in key bytes (Supplied by David Hopwood) */
for (x = y = 0; x < 18; x++) {
A = 0;
for (z = 0; z < 4; z++) {
A = (A << 8) | ((ulong32)key[y++] & 255);
if (y == (ulong32)keylen) {
y = 0;
}
}
skey->blowfish.K[x] = ORIG_P[x] ^ A;
}
/* copy sboxes */
for (x = 0; x < 4; x++) {
for (y = 0; y < 256; y++) {
skey->blowfish.S[x][y] = ORIG_S[x][y];
}
}
/* encrypt K array */
for (x = 0; x < 8; x++) {
B[x] = 0;
}
for (x = 0; x < 18; x += 2) {
/* encrypt it */
blowfish_ecb_encrypt(B, B, skey);
/* copy it */
LOAD32H(skey->blowfish.K[x], &B[0]);
LOAD32H(skey->blowfish.K[x+1], &B[4]);
}
/* encrypt S array */
for (x = 0; x < 4; x++) {
for (y = 0; y < 256; y += 2) {
/* encrypt it */
blowfish_ecb_encrypt(B, B, skey);
/* copy it */
LOAD32H(skey->blowfish.S[x][y], &B[0]);
LOAD32H(skey->blowfish.S[x][y+1], &B[4]);
}
}
#ifdef CLEAN_STACK
zeromem(B, sizeof(B));
#endif
return CRYPT_OK;
}
#ifndef __GNUC__
#define F(x) ((S1[byte(x,3)] + S2[byte(x,2)]) ^ S3[byte(x,1)]) + S4[byte(x,0)]
#else
#define F(x) ((key->blowfish.S[0][byte(x,3)] + key->blowfish.S[1][byte(x,2)]) ^ key->blowfish.S[2][byte(x,1)]) + key->blowfish.S[3][byte(x,0)]
#endif
#ifdef CLEAN_STACK
static void _blowfish_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *key)
#else
void blowfish_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *key)
#endif
{
ulong32 L, R;
int r;
#ifndef __GNUC__
ulong32 *S1, *S2, *S3, *S4;
#endif
_ARGCHK(pt != NULL);
_ARGCHK(ct != NULL);
_ARGCHK(key != NULL);
#ifndef __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]);
LOAD32H(R, &pt[4]);
/* do 16 rounds */
for (r = 0; r < 16; ) {
L ^= key->blowfish.K[r++]; R ^= F(L);
R ^= key->blowfish.K[r++]; L ^= F(R);
L ^= key->blowfish.K[r++]; R ^= F(L);
R ^= key->blowfish.K[r++]; L ^= F(R);
}
/* last keying */
R ^= key->blowfish.K[17];
L ^= key->blowfish.K[16];
/* store */
STORE32H(R, &ct[0]);
STORE32H(L, &ct[4]);
}
#ifdef CLEAN_STACK
void blowfish_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *key)
{
_blowfish_ecb_encrypt(pt, ct, key);
burn_stack(sizeof(ulong32) * 2 + sizeof(int));
}
#endif
#ifdef CLEAN_STACK
static void _blowfish_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *key)
#else
void blowfish_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *key)
#endif
{
ulong32 L, R;
int r;
#ifndef __GNUC__
ulong32 *S1, *S2, *S3, *S4;
#endif
_ARGCHK(pt != NULL);
_ARGCHK(ct != NULL);
_ARGCHK(key != NULL);
#ifndef __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]);
LOAD32H(L, &ct[4]);
/* undo last keying */
R ^= key->blowfish.K[17];
L ^= key->blowfish.K[16];
/* do 16 rounds */
for (r = 15; r > 0; ) {
L ^= F(R); R ^= key->blowfish.K[r--];
R ^= F(L); L ^= key->blowfish.K[r--];
L ^= F(R); R ^= key->blowfish.K[r--];
R ^= F(L); L ^= key->blowfish.K[r--];
}
/* store */
STORE32H(L, &pt[0]);
STORE32H(R, &pt[4]);
}
#ifdef CLEAN_STACK
void blowfish_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *key)
{
_blowfish_ecb_decrypt(ct, pt, key);
burn_stack(sizeof(ulong32) * 2 + sizeof(int));
}
#endif
int blowfish_test(void)
{
#ifndef LTC_TEST
return CRYPT_NOP;
#else
int err;
symmetric_key key;
static const struct {
unsigned char key[8], pt[8], ct[8];
} tests[] = {
{
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
{ 0x4E, 0xF9, 0x97, 0x45, 0x61, 0x98, 0xDD, 0x78}
},
{
{ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
{ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
{ 0x51, 0x86, 0x6F, 0xD5, 0xB8, 0x5E, 0xCB, 0x8A}
},
{
{ 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
{ 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01},
{ 0x7D, 0x85, 0x6F, 0x9A, 0x61, 0x30, 0x63, 0xF2}
}
};
unsigned char tmp[2][8];
int x, y;
for (x = 0; x < (int)(sizeof(tests) / sizeof(tests[0])); x++) {
/* setup key */
if ((err = blowfish_setup(tests[x].key, 8, 16, &key)) != CRYPT_OK) {
return err;
}
/* encrypt and decrypt */
blowfish_ecb_encrypt(tests[x].pt, tmp[0], &key);
blowfish_ecb_decrypt(tmp[0], tmp[1], &key);
/* compare */
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
}
int blowfish_keysize(int *desired_keysize)
{
_ARGCHK(desired_keysize != NULL);
if (*desired_keysize < 8) {
return CRYPT_INVALID_KEYSIZE;
} else if (*desired_keysize > 56) {
*desired_keysize = 56;
}
return CRYPT_OK;
}
#endif

21
burn_stack.c Normal file
View File

@@ -0,0 +1,21 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
*
* LibTomCrypt is a library that provides various cryptographic
* algorithms in a highly modular and flexible manner.
*
* The library is free for all purposes without any express
* guarantee it works.
*
* Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org
*/
#include "mycrypt.h"
void burn_stack(unsigned long len)
{
unsigned char buf[32];
zeromem(buf, sizeof(buf));
if (len > (unsigned long)sizeof(buf))
burn_stack(len - sizeof(buf));
}

669
cast5.c Normal file
View File

@@ -0,0 +1,669 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
*
* LibTomCrypt is a library that provides various cryptographic
* algorithms in a highly modular and flexible manner.
*
* The library is free for all purposes without any express
* guarantee it works.
*
* Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org
*/
/* Implementation of CAST5 (RFC 2144) by Tom St Denis */
#include "mycrypt.h"
#ifdef CAST5
const struct _cipher_descriptor cast5_desc = {
"cast5",
15,
5, 16, 8, 16,
&cast5_setup,
&cast5_ecb_encrypt,
&cast5_ecb_decrypt,
&cast5_test,
&cast5_keysize
};
static const ulong32 S1[256] = {
0x30fb40d4UL, 0x9fa0ff0bUL, 0x6beccd2fUL, 0x3f258c7aUL, 0x1e213f2fUL, 0x9c004dd3UL,
0x6003e540UL, 0xcf9fc949UL, 0xbfd4af27UL, 0x88bbbdb5UL, 0xe2034090UL, 0x98d09675UL,
0x6e63a0e0UL, 0x15c361d2UL, 0xc2e7661dUL, 0x22d4ff8eUL, 0x28683b6fUL, 0xc07fd059UL,
0xff2379c8UL, 0x775f50e2UL, 0x43c340d3UL, 0xdf2f8656UL, 0x887ca41aUL, 0xa2d2bd2dUL,
0xa1c9e0d6UL, 0x346c4819UL, 0x61b76d87UL, 0x22540f2fUL, 0x2abe32e1UL, 0xaa54166bUL,
0x22568e3aUL, 0xa2d341d0UL, 0x66db40c8UL, 0xa784392fUL, 0x004dff2fUL, 0x2db9d2deUL,
0x97943facUL, 0x4a97c1d8UL, 0x527644b7UL, 0xb5f437a7UL, 0xb82cbaefUL, 0xd751d159UL,
0x6ff7f0edUL, 0x5a097a1fUL, 0x827b68d0UL, 0x90ecf52eUL, 0x22b0c054UL, 0xbc8e5935UL,
0x4b6d2f7fUL, 0x50bb64a2UL, 0xd2664910UL, 0xbee5812dUL, 0xb7332290UL, 0xe93b159fUL,
0xb48ee411UL, 0x4bff345dUL, 0xfd45c240UL, 0xad31973fUL, 0xc4f6d02eUL, 0x55fc8165UL,
0xd5b1caadUL, 0xa1ac2daeUL, 0xa2d4b76dUL, 0xc19b0c50UL, 0x882240f2UL, 0x0c6e4f38UL,
0xa4e4bfd7UL, 0x4f5ba272UL, 0x564c1d2fUL, 0xc59c5319UL, 0xb949e354UL, 0xb04669feUL,
0xb1b6ab8aUL, 0xc71358ddUL, 0x6385c545UL, 0x110f935dUL, 0x57538ad5UL, 0x6a390493UL,
0xe63d37e0UL, 0x2a54f6b3UL, 0x3a787d5fUL, 0x6276a0b5UL, 0x19a6fcdfUL, 0x7a42206aUL,
0x29f9d4d5UL, 0xf61b1891UL, 0xbb72275eUL, 0xaa508167UL, 0x38901091UL, 0xc6b505ebUL,
0x84c7cb8cUL, 0x2ad75a0fUL, 0x874a1427UL, 0xa2d1936bUL, 0x2ad286afUL, 0xaa56d291UL,
0xd7894360UL, 0x425c750dUL, 0x93b39e26UL, 0x187184c9UL, 0x6c00b32dUL, 0x73e2bb14UL,
0xa0bebc3cUL, 0x54623779UL, 0x64459eabUL, 0x3f328b82UL, 0x7718cf82UL, 0x59a2cea6UL,
0x04ee002eUL, 0x89fe78e6UL, 0x3fab0950UL, 0x325ff6c2UL, 0x81383f05UL, 0x6963c5c8UL,
0x76cb5ad6UL, 0xd49974c9UL, 0xca180dcfUL, 0x380782d5UL, 0xc7fa5cf6UL, 0x8ac31511UL,
0x35e79e13UL, 0x47da91d0UL, 0xf40f9086UL, 0xa7e2419eUL, 0x31366241UL, 0x051ef495UL,
0xaa573b04UL, 0x4a805d8dUL, 0x548300d0UL, 0x00322a3cUL, 0xbf64cddfUL, 0xba57a68eUL,
0x75c6372bUL, 0x50afd341UL, 0xa7c13275UL, 0x915a0bf5UL, 0x6b54bfabUL, 0x2b0b1426UL,
0xab4cc9d7UL, 0x449ccd82UL, 0xf7fbf265UL, 0xab85c5f3UL, 0x1b55db94UL, 0xaad4e324UL,
0xcfa4bd3fUL, 0x2deaa3e2UL, 0x9e204d02UL, 0xc8bd25acUL, 0xeadf55b3UL, 0xd5bd9e98UL,
0xe31231b2UL, 0x2ad5ad6cUL, 0x954329deUL, 0xadbe4528UL, 0xd8710f69UL, 0xaa51c90fUL,
0xaa786bf6UL, 0x22513f1eUL, 0xaa51a79bUL, 0x2ad344ccUL, 0x7b5a41f0UL, 0xd37cfbadUL,
0x1b069505UL, 0x41ece491UL, 0xb4c332e6UL, 0x032268d4UL, 0xc9600accUL, 0xce387e6dUL,
0xbf6bb16cUL, 0x6a70fb78UL, 0x0d03d9c9UL, 0xd4df39deUL, 0xe01063daUL, 0x4736f464UL,
0x5ad328d8UL, 0xb347cc96UL, 0x75bb0fc3UL, 0x98511bfbUL, 0x4ffbcc35UL, 0xb58bcf6aUL,
0xe11f0abcUL, 0xbfc5fe4aUL, 0xa70aec10UL, 0xac39570aUL, 0x3f04442fUL, 0x6188b153UL,
0xe0397a2eUL, 0x5727cb79UL, 0x9ceb418fUL, 0x1cacd68dUL, 0x2ad37c96UL, 0x0175cb9dUL,
0xc69dff09UL, 0xc75b65f0UL, 0xd9db40d8UL, 0xec0e7779UL, 0x4744ead4UL, 0xb11c3274UL,
0xdd24cb9eUL, 0x7e1c54bdUL, 0xf01144f9UL, 0xd2240eb1UL, 0x9675b3fdUL, 0xa3ac3755UL,
0xd47c27afUL, 0x51c85f4dUL, 0x56907596UL, 0xa5bb15e6UL, 0x580304f0UL, 0xca042cf1UL,
0x011a37eaUL, 0x8dbfaadbUL, 0x35ba3e4aUL, 0x3526ffa0UL, 0xc37b4d09UL, 0xbc306ed9UL,
0x98a52666UL, 0x5648f725UL, 0xff5e569dUL, 0x0ced63d0UL, 0x7c63b2cfUL, 0x700b45e1UL,
0xd5ea50f1UL, 0x85a92872UL, 0xaf1fbda7UL, 0xd4234870UL, 0xa7870bf3UL, 0x2d3b4d79UL,
0x42e04198UL, 0x0cd0ede7UL, 0x26470db8UL, 0xf881814cUL, 0x474d6ad7UL, 0x7c0c5e5cUL,
0xd1231959UL, 0x381b7298UL, 0xf5d2f4dbUL, 0xab838653UL, 0x6e2f1e23UL, 0x83719c9eUL,
0xbd91e046UL, 0x9a56456eUL, 0xdc39200cUL, 0x20c8c571UL, 0x962bda1cUL, 0xe1e696ffUL,
0xb141ab08UL, 0x7cca89b9UL, 0x1a69e783UL, 0x02cc4843UL, 0xa2f7c579UL, 0x429ef47dUL,
0x427b169cUL, 0x5ac9f049UL, 0xdd8f0f00UL, 0x5c8165bfUL};
static const ulong32 S2[256] = {
0x1f201094UL, 0xef0ba75bUL, 0x69e3cf7eUL, 0x393f4380UL, 0xfe61cf7aUL, 0xeec5207aUL,
0x55889c94UL, 0x72fc0651UL, 0xada7ef79UL, 0x4e1d7235UL, 0xd55a63ceUL, 0xde0436baUL,
0x99c430efUL, 0x5f0c0794UL, 0x18dcdb7dUL, 0xa1d6eff3UL, 0xa0b52f7bUL, 0x59e83605UL,
0xee15b094UL, 0xe9ffd909UL, 0xdc440086UL, 0xef944459UL, 0xba83ccb3UL, 0xe0c3cdfbUL,
0xd1da4181UL, 0x3b092ab1UL, 0xf997f1c1UL, 0xa5e6cf7bUL, 0x01420ddbUL, 0xe4e7ef5bUL,
0x25a1ff41UL, 0xe180f806UL, 0x1fc41080UL, 0x179bee7aUL, 0xd37ac6a9UL, 0xfe5830a4UL,
0x98de8b7fUL, 0x77e83f4eUL, 0x79929269UL, 0x24fa9f7bUL, 0xe113c85bUL, 0xacc40083UL,
0xd7503525UL, 0xf7ea615fUL, 0x62143154UL, 0x0d554b63UL, 0x5d681121UL, 0xc866c359UL,
0x3d63cf73UL, 0xcee234c0UL, 0xd4d87e87UL, 0x5c672b21UL, 0x071f6181UL, 0x39f7627fUL,
0x361e3084UL, 0xe4eb573bUL, 0x602f64a4UL, 0xd63acd9cUL, 0x1bbc4635UL, 0x9e81032dUL,
0x2701f50cUL, 0x99847ab4UL, 0xa0e3df79UL, 0xba6cf38cUL, 0x10843094UL, 0x2537a95eUL,
0xf46f6ffeUL, 0xa1ff3b1fUL, 0x208cfb6aUL, 0x8f458c74UL, 0xd9e0a227UL, 0x4ec73a34UL,
0xfc884f69UL, 0x3e4de8dfUL, 0xef0e0088UL, 0x3559648dUL, 0x8a45388cUL, 0x1d804366UL,
0x721d9bfdUL, 0xa58684bbUL, 0xe8256333UL, 0x844e8212UL, 0x128d8098UL, 0xfed33fb4UL,
0xce280ae1UL, 0x27e19ba5UL, 0xd5a6c252UL, 0xe49754bdUL, 0xc5d655ddUL, 0xeb667064UL,
0x77840b4dUL, 0xa1b6a801UL, 0x84db26a9UL, 0xe0b56714UL, 0x21f043b7UL, 0xe5d05860UL,
0x54f03084UL, 0x066ff472UL, 0xa31aa153UL, 0xdadc4755UL, 0xb5625dbfUL, 0x68561be6UL,
0x83ca6b94UL, 0x2d6ed23bUL, 0xeccf01dbUL, 0xa6d3d0baUL, 0xb6803d5cUL, 0xaf77a709UL,
0x33b4a34cUL, 0x397bc8d6UL, 0x5ee22b95UL, 0x5f0e5304UL, 0x81ed6f61UL, 0x20e74364UL,
0xb45e1378UL, 0xde18639bUL, 0x881ca122UL, 0xb96726d1UL, 0x8049a7e8UL, 0x22b7da7bUL,
0x5e552d25UL, 0x5272d237UL, 0x79d2951cUL, 0xc60d894cUL, 0x488cb402UL, 0x1ba4fe5bUL,
0xa4b09f6bUL, 0x1ca815cfUL, 0xa20c3005UL, 0x8871df63UL, 0xb9de2fcbUL, 0x0cc6c9e9UL,
0x0beeff53UL, 0xe3214517UL, 0xb4542835UL, 0x9f63293cUL, 0xee41e729UL, 0x6e1d2d7cUL,
0x50045286UL, 0x1e6685f3UL, 0xf33401c6UL, 0x30a22c95UL, 0x31a70850UL, 0x60930f13UL,
0x73f98417UL, 0xa1269859UL, 0xec645c44UL, 0x52c877a9UL, 0xcdff33a6UL, 0xa02b1741UL,
0x7cbad9a2UL, 0x2180036fUL, 0x50d99c08UL, 0xcb3f4861UL, 0xc26bd765UL, 0x64a3f6abUL,
0x80342676UL, 0x25a75e7bUL, 0xe4e6d1fcUL, 0x20c710e6UL, 0xcdf0b680UL, 0x17844d3bUL,
0x31eef84dUL, 0x7e0824e4UL, 0x2ccb49ebUL, 0x846a3baeUL, 0x8ff77888UL, 0xee5d60f6UL,
0x7af75673UL, 0x2fdd5cdbUL, 0xa11631c1UL, 0x30f66f43UL, 0xb3faec54UL, 0x157fd7faUL,
0xef8579ccUL, 0xd152de58UL, 0xdb2ffd5eUL, 0x8f32ce19UL, 0x306af97aUL, 0x02f03ef8UL,
0x99319ad5UL, 0xc242fa0fUL, 0xa7e3ebb0UL, 0xc68e4906UL, 0xb8da230cUL, 0x80823028UL,
0xdcdef3c8UL, 0xd35fb171UL, 0x088a1bc8UL, 0xbec0c560UL, 0x61a3c9e8UL, 0xbca8f54dUL,
0xc72feffaUL, 0x22822e99UL, 0x82c570b4UL, 0xd8d94e89UL, 0x8b1c34bcUL, 0x301e16e6UL,
0x273be979UL, 0xb0ffeaa6UL, 0x61d9b8c6UL, 0x00b24869UL, 0xb7ffce3fUL, 0x08dc283bUL,
0x43daf65aUL, 0xf7e19798UL, 0x7619b72fUL, 0x8f1c9ba4UL, 0xdc8637a0UL, 0x16a7d3b1UL,
0x9fc393b7UL, 0xa7136eebUL, 0xc6bcc63eUL, 0x1a513742UL, 0xef6828bcUL, 0x520365d6UL,
0x2d6a77abUL, 0x3527ed4bUL, 0x821fd216UL, 0x095c6e2eUL, 0xdb92f2fbUL, 0x5eea29cbUL,
0x145892f5UL, 0x91584f7fUL, 0x5483697bUL, 0x2667a8ccUL, 0x85196048UL, 0x8c4baceaUL,
0x833860d4UL, 0x0d23e0f9UL, 0x6c387e8aUL, 0x0ae6d249UL, 0xb284600cUL, 0xd835731dUL,
0xdcb1c647UL, 0xac4c56eaUL, 0x3ebd81b3UL, 0x230eabb0UL, 0x6438bc87UL, 0xf0b5b1faUL,
0x8f5ea2b3UL, 0xfc184642UL, 0x0a036b7aUL, 0x4fb089bdUL, 0x649da589UL, 0xa345415eUL,
0x5c038323UL, 0x3e5d3bb9UL, 0x43d79572UL, 0x7e6dd07cUL, 0x06dfdf1eUL, 0x6c6cc4efUL,
0x7160a539UL, 0x73bfbe70UL, 0x83877605UL, 0x4523ecf1UL};
static const ulong32 S3[256] = {
0x8defc240UL, 0x25fa5d9fUL, 0xeb903dbfUL, 0xe810c907UL, 0x47607fffUL, 0x369fe44bUL,
0x8c1fc644UL, 0xaececa90UL, 0xbeb1f9bfUL, 0xeefbcaeaUL, 0xe8cf1950UL, 0x51df07aeUL,
0x920e8806UL, 0xf0ad0548UL, 0xe13c8d83UL, 0x927010d5UL, 0x11107d9fUL, 0x07647db9UL,
0xb2e3e4d4UL, 0x3d4f285eUL, 0xb9afa820UL, 0xfade82e0UL, 0xa067268bUL, 0x8272792eUL,
0x553fb2c0UL, 0x489ae22bUL, 0xd4ef9794UL, 0x125e3fbcUL, 0x21fffceeUL, 0x825b1bfdUL,
0x9255c5edUL, 0x1257a240UL, 0x4e1a8302UL, 0xbae07fffUL, 0x528246e7UL, 0x8e57140eUL,
0x3373f7bfUL, 0x8c9f8188UL, 0xa6fc4ee8UL, 0xc982b5a5UL, 0xa8c01db7UL, 0x579fc264UL,
0x67094f31UL, 0xf2bd3f5fUL, 0x40fff7c1UL, 0x1fb78dfcUL, 0x8e6bd2c1UL, 0x437be59bUL,
0x99b03dbfUL, 0xb5dbc64bUL, 0x638dc0e6UL, 0x55819d99UL, 0xa197c81cUL, 0x4a012d6eUL,
0xc5884a28UL, 0xccc36f71UL, 0xb843c213UL, 0x6c0743f1UL, 0x8309893cUL, 0x0feddd5fUL,
0x2f7fe850UL, 0xd7c07f7eUL, 0x02507fbfUL, 0x5afb9a04UL, 0xa747d2d0UL, 0x1651192eUL,
0xaf70bf3eUL, 0x58c31380UL, 0x5f98302eUL, 0x727cc3c4UL, 0x0a0fb402UL, 0x0f7fef82UL,
0x8c96fdadUL, 0x5d2c2aaeUL, 0x8ee99a49UL, 0x50da88b8UL, 0x8427f4a0UL, 0x1eac5790UL,
0x796fb449UL, 0x8252dc15UL, 0xefbd7d9bUL, 0xa672597dUL, 0xada840d8UL, 0x45f54504UL,
0xfa5d7403UL, 0xe83ec305UL, 0x4f91751aUL, 0x925669c2UL, 0x23efe941UL, 0xa903f12eUL,
0x60270df2UL, 0x0276e4b6UL, 0x94fd6574UL, 0x927985b2UL, 0x8276dbcbUL, 0x02778176UL,
0xf8af918dUL, 0x4e48f79eUL, 0x8f616ddfUL, 0xe29d840eUL, 0x842f7d83UL, 0x340ce5c8UL,
0x96bbb682UL, 0x93b4b148UL, 0xef303cabUL, 0x984faf28UL, 0x779faf9bUL, 0x92dc560dUL,
0x224d1e20UL, 0x8437aa88UL, 0x7d29dc96UL, 0x2756d3dcUL, 0x8b907ceeUL, 0xb51fd240UL,
0xe7c07ce3UL, 0xe566b4a1UL, 0xc3e9615eUL, 0x3cf8209dUL, 0x6094d1e3UL, 0xcd9ca341UL,
0x5c76460eUL, 0x00ea983bUL, 0xd4d67881UL, 0xfd47572cUL, 0xf76cedd9UL, 0xbda8229cUL,
0x127dadaaUL, 0x438a074eUL, 0x1f97c090UL, 0x081bdb8aUL, 0x93a07ebeUL, 0xb938ca15UL,
0x97b03cffUL, 0x3dc2c0f8UL, 0x8d1ab2ecUL, 0x64380e51UL, 0x68cc7bfbUL, 0xd90f2788UL,
0x12490181UL, 0x5de5ffd4UL, 0xdd7ef86aUL, 0x76a2e214UL, 0xb9a40368UL, 0x925d958fUL,
0x4b39fffaUL, 0xba39aee9UL, 0xa4ffd30bUL, 0xfaf7933bUL, 0x6d498623UL, 0x193cbcfaUL,
0x27627545UL, 0x825cf47aUL, 0x61bd8ba0UL, 0xd11e42d1UL, 0xcead04f4UL, 0x127ea392UL,
0x10428db7UL, 0x8272a972UL, 0x9270c4a8UL, 0x127de50bUL, 0x285ba1c8UL, 0x3c62f44fUL,
0x35c0eaa5UL, 0xe805d231UL, 0x428929fbUL, 0xb4fcdf82UL, 0x4fb66a53UL, 0x0e7dc15bUL,
0x1f081fabUL, 0x108618aeUL, 0xfcfd086dUL, 0xf9ff2889UL, 0x694bcc11UL, 0x236a5caeUL,
0x12deca4dUL, 0x2c3f8cc5UL, 0xd2d02dfeUL, 0xf8ef5896UL, 0xe4cf52daUL, 0x95155b67UL,
0x494a488cUL, 0xb9b6a80cUL, 0x5c8f82bcUL, 0x89d36b45UL, 0x3a609437UL, 0xec00c9a9UL,
0x44715253UL, 0x0a874b49UL, 0xd773bc40UL, 0x7c34671cUL, 0x02717ef6UL, 0x4feb5536UL,
0xa2d02fffUL, 0xd2bf60c4UL, 0xd43f03c0UL, 0x50b4ef6dUL, 0x07478cd1UL, 0x006e1888UL,
0xa2e53f55UL, 0xb9e6d4bcUL, 0xa2048016UL, 0x97573833UL, 0xd7207d67UL, 0xde0f8f3dUL,
0x72f87b33UL, 0xabcc4f33UL, 0x7688c55dUL, 0x7b00a6b0UL, 0x947b0001UL, 0x570075d2UL,
0xf9bb88f8UL, 0x8942019eUL, 0x4264a5ffUL, 0x856302e0UL, 0x72dbd92bUL, 0xee971b69UL,
0x6ea22fdeUL, 0x5f08ae2bUL, 0xaf7a616dUL, 0xe5c98767UL, 0xcf1febd2UL, 0x61efc8c2UL,
0xf1ac2571UL, 0xcc8239c2UL, 0x67214cb8UL, 0xb1e583d1UL, 0xb7dc3e62UL, 0x7f10bdceUL,
0xf90a5c38UL, 0x0ff0443dUL, 0x606e6dc6UL, 0x60543a49UL, 0x5727c148UL, 0x2be98a1dUL,
0x8ab41738UL, 0x20e1be24UL, 0xaf96da0fUL, 0x68458425UL, 0x99833be5UL, 0x600d457dUL,
0x282f9350UL, 0x8334b362UL, 0xd91d1120UL, 0x2b6d8da0UL, 0x642b1e31UL, 0x9c305a00UL,
0x52bce688UL, 0x1b03588aUL, 0xf7baefd5UL, 0x4142ed9cUL, 0xa4315c11UL, 0x83323ec5UL,
0xdfef4636UL, 0xa133c501UL, 0xe9d3531cUL, 0xee353783UL};
static const ulong32 S4[256] = {
0x9db30420UL, 0x1fb6e9deUL, 0xa7be7befUL, 0xd273a298UL, 0x4a4f7bdbUL, 0x64ad8c57UL,
0x85510443UL, 0xfa020ed1UL, 0x7e287affUL, 0xe60fb663UL, 0x095f35a1UL, 0x79ebf120UL,
0xfd059d43UL, 0x6497b7b1UL, 0xf3641f63UL, 0x241e4adfUL, 0x28147f5fUL, 0x4fa2b8cdUL,
0xc9430040UL, 0x0cc32220UL, 0xfdd30b30UL, 0xc0a5374fUL, 0x1d2d00d9UL, 0x24147b15UL,
0xee4d111aUL, 0x0fca5167UL, 0x71ff904cUL, 0x2d195ffeUL, 0x1a05645fUL, 0x0c13fefeUL,
0x081b08caUL, 0x05170121UL, 0x80530100UL, 0xe83e5efeUL, 0xac9af4f8UL, 0x7fe72701UL,
0xd2b8ee5fUL, 0x06df4261UL, 0xbb9e9b8aUL, 0x7293ea25UL, 0xce84ffdfUL, 0xf5718801UL,
0x3dd64b04UL, 0xa26f263bUL, 0x7ed48400UL, 0x547eebe6UL, 0x446d4ca0UL, 0x6cf3d6f5UL,
0x2649abdfUL, 0xaea0c7f5UL, 0x36338cc1UL, 0x503f7e93UL, 0xd3772061UL, 0x11b638e1UL,
0x72500e03UL, 0xf80eb2bbUL, 0xabe0502eUL, 0xec8d77deUL, 0x57971e81UL, 0xe14f6746UL,
0xc9335400UL, 0x6920318fUL, 0x081dbb99UL, 0xffc304a5UL, 0x4d351805UL, 0x7f3d5ce3UL,
0xa6c866c6UL, 0x5d5bcca9UL, 0xdaec6feaUL, 0x9f926f91UL, 0x9f46222fUL, 0x3991467dUL,
0xa5bf6d8eUL, 0x1143c44fUL, 0x43958302UL, 0xd0214eebUL, 0x022083b8UL, 0x3fb6180cUL,
0x18f8931eUL, 0x281658e6UL, 0x26486e3eUL, 0x8bd78a70UL, 0x7477e4c1UL, 0xb506e07cUL,
0xf32d0a25UL, 0x79098b02UL, 0xe4eabb81UL, 0x28123b23UL, 0x69dead38UL, 0x1574ca16UL,
0xdf871b62UL, 0x211c40b7UL, 0xa51a9ef9UL, 0x0014377bUL, 0x041e8ac8UL, 0x09114003UL,
0xbd59e4d2UL, 0xe3d156d5UL, 0x4fe876d5UL, 0x2f91a340UL, 0x557be8deUL, 0x00eae4a7UL,
0x0ce5c2ecUL, 0x4db4bba6UL, 0xe756bdffUL, 0xdd3369acUL, 0xec17b035UL, 0x06572327UL,
0x99afc8b0UL, 0x56c8c391UL, 0x6b65811cUL, 0x5e146119UL, 0x6e85cb75UL, 0xbe07c002UL,
0xc2325577UL, 0x893ff4ecUL, 0x5bbfc92dUL, 0xd0ec3b25UL, 0xb7801ab7UL, 0x8d6d3b24UL,
0x20c763efUL, 0xc366a5fcUL, 0x9c382880UL, 0x0ace3205UL, 0xaac9548aUL, 0xeca1d7c7UL,
0x041afa32UL, 0x1d16625aUL, 0x6701902cUL, 0x9b757a54UL, 0x31d477f7UL, 0x9126b031UL,
0x36cc6fdbUL, 0xc70b8b46UL, 0xd9e66a48UL, 0x56e55a79UL, 0x026a4cebUL, 0x52437effUL,
0x2f8f76b4UL, 0x0df980a5UL, 0x8674cde3UL, 0xedda04ebUL, 0x17a9be04UL, 0x2c18f4dfUL,
0xb7747f9dUL, 0xab2af7b4UL, 0xefc34d20UL, 0x2e096b7cUL, 0x1741a254UL, 0xe5b6a035UL,
0x213d42f6UL, 0x2c1c7c26UL, 0x61c2f50fUL, 0x6552daf9UL, 0xd2c231f8UL, 0x25130f69UL,
0xd8167fa2UL, 0x0418f2c8UL, 0x001a96a6UL, 0x0d1526abUL, 0x63315c21UL, 0x5e0a72ecUL,
0x49bafefdUL, 0x187908d9UL, 0x8d0dbd86UL, 0x311170a7UL, 0x3e9b640cUL, 0xcc3e10d7UL,
0xd5cad3b6UL, 0x0caec388UL, 0xf73001e1UL, 0x6c728affUL, 0x71eae2a1UL, 0x1f9af36eUL,
0xcfcbd12fUL, 0xc1de8417UL, 0xac07be6bUL, 0xcb44a1d8UL, 0x8b9b0f56UL, 0x013988c3UL,
0xb1c52fcaUL, 0xb4be31cdUL, 0xd8782806UL, 0x12a3a4e2UL, 0x6f7de532UL, 0x58fd7eb6UL,
0xd01ee900UL, 0x24adffc2UL, 0xf4990fc5UL, 0x9711aac5UL, 0x001d7b95UL, 0x82e5e7d2UL,
0x109873f6UL, 0x00613096UL, 0xc32d9521UL, 0xada121ffUL, 0x29908415UL, 0x7fbb977fUL,
0xaf9eb3dbUL, 0x29c9ed2aUL, 0x5ce2a465UL, 0xa730f32cUL, 0xd0aa3fe8UL, 0x8a5cc091UL,
0xd49e2ce7UL, 0x0ce454a9UL, 0xd60acd86UL, 0x015f1919UL, 0x77079103UL, 0xdea03af6UL,
0x78a8565eUL, 0xdee356dfUL, 0x21f05cbeUL, 0x8b75e387UL, 0xb3c50651UL, 0xb8a5c3efUL,
0xd8eeb6d2UL, 0xe523be77UL, 0xc2154529UL, 0x2f69efdfUL, 0xafe67afbUL, 0xf470c4b2UL,
0xf3e0eb5bUL, 0xd6cc9876UL, 0x39e4460cUL, 0x1fda8538UL, 0x1987832fUL, 0xca007367UL,
0xa99144f8UL, 0x296b299eUL, 0x492fc295UL, 0x9266beabUL, 0xb5676e69UL, 0x9bd3dddaUL,
0xdf7e052fUL, 0xdb25701cUL, 0x1b5e51eeUL, 0xf65324e6UL, 0x6afce36cUL, 0x0316cc04UL,
0x8644213eUL, 0xb7dc59d0UL, 0x7965291fUL, 0xccd6fd43UL, 0x41823979UL, 0x932bcdf6UL,
0xb657c34dUL, 0x4edfd282UL, 0x7ae5290cUL, 0x3cb9536bUL, 0x851e20feUL, 0x9833557eUL,
0x13ecf0b0UL, 0xd3ffb372UL, 0x3f85c5c1UL, 0x0aef7ed2UL};
static const ulong32 S5[256] = {
0x7ec90c04UL, 0x2c6e74b9UL, 0x9b0e66dfUL, 0xa6337911UL, 0xb86a7fffUL, 0x1dd358f5UL,
0x44dd9d44UL, 0x1731167fUL, 0x08fbf1faUL, 0xe7f511ccUL, 0xd2051b00UL, 0x735aba00UL,
0x2ab722d8UL, 0x386381cbUL, 0xacf6243aUL, 0x69befd7aUL, 0xe6a2e77fUL, 0xf0c720cdUL,
0xc4494816UL, 0xccf5c180UL, 0x38851640UL, 0x15b0a848UL, 0xe68b18cbUL, 0x4caadeffUL,
0x5f480a01UL, 0x0412b2aaUL, 0x259814fcUL, 0x41d0efe2UL, 0x4e40b48dUL, 0x248eb6fbUL,
0x8dba1cfeUL, 0x41a99b02UL, 0x1a550a04UL, 0xba8f65cbUL, 0x7251f4e7UL, 0x95a51725UL,
0xc106ecd7UL, 0x97a5980aUL, 0xc539b9aaUL, 0x4d79fe6aUL, 0xf2f3f763UL, 0x68af8040UL,
0xed0c9e56UL, 0x11b4958bUL, 0xe1eb5a88UL, 0x8709e6b0UL, 0xd7e07156UL, 0x4e29fea7UL,
0x6366e52dUL, 0x02d1c000UL, 0xc4ac8e05UL, 0x9377f571UL, 0x0c05372aUL, 0x578535f2UL,
0x2261be02UL, 0xd642a0c9UL, 0xdf13a280UL, 0x74b55bd2UL, 0x682199c0UL, 0xd421e5ecUL,
0x53fb3ce8UL, 0xc8adedb3UL, 0x28a87fc9UL, 0x3d959981UL, 0x5c1ff900UL, 0xfe38d399UL,
0x0c4eff0bUL, 0x062407eaUL, 0xaa2f4fb1UL, 0x4fb96976UL, 0x90c79505UL, 0xb0a8a774UL,
0xef55a1ffUL, 0xe59ca2c2UL, 0xa6b62d27UL, 0xe66a4263UL, 0xdf65001fUL, 0x0ec50966UL,
0xdfdd55bcUL, 0x29de0655UL, 0x911e739aUL, 0x17af8975UL, 0x32c7911cUL, 0x89f89468UL,
0x0d01e980UL, 0x524755f4UL, 0x03b63cc9UL, 0x0cc844b2UL, 0xbcf3f0aaUL, 0x87ac36e9UL,
0xe53a7426UL, 0x01b3d82bUL, 0x1a9e7449UL, 0x64ee2d7eUL, 0xcddbb1daUL, 0x01c94910UL,
0xb868bf80UL, 0x0d26f3fdUL, 0x9342ede7UL, 0x04a5c284UL, 0x636737b6UL, 0x50f5b616UL,
0xf24766e3UL, 0x8eca36c1UL, 0x136e05dbUL, 0xfef18391UL, 0xfb887a37UL, 0xd6e7f7d4UL,
0xc7fb7dc9UL, 0x3063fcdfUL, 0xb6f589deUL, 0xec2941daUL, 0x26e46695UL, 0xb7566419UL,
0xf654efc5UL, 0xd08d58b7UL, 0x48925401UL, 0xc1bacb7fUL, 0xe5ff550fUL, 0xb6083049UL,
0x5bb5d0e8UL, 0x87d72e5aUL, 0xab6a6ee1UL, 0x223a66ceUL, 0xc62bf3cdUL, 0x9e0885f9UL,
0x68cb3e47UL, 0x086c010fUL, 0xa21de820UL, 0xd18b69deUL, 0xf3f65777UL, 0xfa02c3f6UL,
0x407edac3UL, 0xcbb3d550UL, 0x1793084dUL, 0xb0d70ebaUL, 0x0ab378d5UL, 0xd951fb0cUL,
0xded7da56UL, 0x4124bbe4UL, 0x94ca0b56UL, 0x0f5755d1UL, 0xe0e1e56eUL, 0x6184b5beUL,
0x580a249fUL, 0x94f74bc0UL, 0xe327888eUL, 0x9f7b5561UL, 0xc3dc0280UL, 0x05687715UL,
0x646c6bd7UL, 0x44904db3UL, 0x66b4f0a3UL, 0xc0f1648aUL, 0x697ed5afUL, 0x49e92ff6UL,
0x309e374fUL, 0x2cb6356aUL, 0x85808573UL, 0x4991f840UL, 0x76f0ae02UL, 0x083be84dUL,
0x28421c9aUL, 0x44489406UL, 0x736e4cb8UL, 0xc1092910UL, 0x8bc95fc6UL, 0x7d869cf4UL,
0x134f616fUL, 0x2e77118dUL, 0xb31b2be1UL, 0xaa90b472UL, 0x3ca5d717UL, 0x7d161bbaUL,
0x9cad9010UL, 0xaf462ba2UL, 0x9fe459d2UL, 0x45d34559UL, 0xd9f2da13UL, 0xdbc65487UL,
0xf3e4f94eUL, 0x176d486fUL, 0x097c13eaUL, 0x631da5c7UL, 0x445f7382UL, 0x175683f4UL,
0xcdc66a97UL, 0x70be0288UL, 0xb3cdcf72UL, 0x6e5dd2f3UL, 0x20936079UL, 0x459b80a5UL,
0xbe60e2dbUL, 0xa9c23101UL, 0xeba5315cUL, 0x224e42f2UL, 0x1c5c1572UL, 0xf6721b2cUL,
0x1ad2fff3UL, 0x8c25404eUL, 0x324ed72fUL, 0x4067b7fdUL, 0x0523138eUL, 0x5ca3bc78UL,
0xdc0fd66eUL, 0x75922283UL, 0x784d6b17UL, 0x58ebb16eUL, 0x44094f85UL, 0x3f481d87UL,
0xfcfeae7bUL, 0x77b5ff76UL, 0x8c2302bfUL, 0xaaf47556UL, 0x5f46b02aUL, 0x2b092801UL,
0x3d38f5f7UL, 0x0ca81f36UL, 0x52af4a8aUL, 0x66d5e7c0UL, 0xdf3b0874UL, 0x95055110UL,
0x1b5ad7a8UL, 0xf61ed5adUL, 0x6cf6e479UL, 0x20758184UL, 0xd0cefa65UL, 0x88f7be58UL,
0x4a046826UL, 0x0ff6f8f3UL, 0xa09c7f70UL, 0x5346aba0UL, 0x5ce96c28UL, 0xe176eda3UL,
0x6bac307fUL, 0x376829d2UL, 0x85360fa9UL, 0x17e3fe2aUL, 0x24b79767UL, 0xf5a96b20UL,
0xd6cd2595UL, 0x68ff1ebfUL, 0x7555442cUL, 0xf19f06beUL, 0xf9e0659aUL, 0xeeb9491dUL,
0x34010718UL, 0xbb30cab8UL, 0xe822fe15UL, 0x88570983UL, 0x750e6249UL, 0xda627e55UL,
0x5e76ffa8UL, 0xb1534546UL, 0x6d47de08UL, 0xefe9e7d4UL};
static const ulong32 S6[256] = {
0xf6fa8f9dUL, 0x2cac6ce1UL, 0x4ca34867UL, 0xe2337f7cUL, 0x95db08e7UL, 0x016843b4UL,
0xeced5cbcUL, 0x325553acUL, 0xbf9f0960UL, 0xdfa1e2edUL, 0x83f0579dUL, 0x63ed86b9UL,
0x1ab6a6b8UL, 0xde5ebe39UL, 0xf38ff732UL, 0x8989b138UL, 0x33f14961UL, 0xc01937bdUL,
0xf506c6daUL, 0xe4625e7eUL, 0xa308ea99UL, 0x4e23e33cUL, 0x79cbd7ccUL, 0x48a14367UL,
0xa3149619UL, 0xfec94bd5UL, 0xa114174aUL, 0xeaa01866UL, 0xa084db2dUL, 0x09a8486fUL,
0xa888614aUL, 0x2900af98UL, 0x01665991UL, 0xe1992863UL, 0xc8f30c60UL, 0x2e78ef3cUL,
0xd0d51932UL, 0xcf0fec14UL, 0xf7ca07d2UL, 0xd0a82072UL, 0xfd41197eUL, 0x9305a6b0UL,
0xe86be3daUL, 0x74bed3cdUL, 0x372da53cUL, 0x4c7f4448UL, 0xdab5d440UL, 0x6dba0ec3UL,
0x083919a7UL, 0x9fbaeed9UL, 0x49dbcfb0UL, 0x4e670c53UL, 0x5c3d9c01UL, 0x64bdb941UL,
0x2c0e636aUL, 0xba7dd9cdUL, 0xea6f7388UL, 0xe70bc762UL, 0x35f29adbUL, 0x5c4cdd8dUL,
0xf0d48d8cUL, 0xb88153e2UL, 0x08a19866UL, 0x1ae2eac8UL, 0x284caf89UL, 0xaa928223UL,
0x9334be53UL, 0x3b3a21bfUL, 0x16434be3UL, 0x9aea3906UL, 0xefe8c36eUL, 0xf890cdd9UL,
0x80226daeUL, 0xc340a4a3UL, 0xdf7e9c09UL, 0xa694a807UL, 0x5b7c5eccUL, 0x221db3a6UL,
0x9a69a02fUL, 0x68818a54UL, 0xceb2296fUL, 0x53c0843aUL, 0xfe893655UL, 0x25bfe68aUL,
0xb4628abcUL, 0xcf222ebfUL, 0x25ac6f48UL, 0xa9a99387UL, 0x53bddb65UL, 0xe76ffbe7UL,
0xe967fd78UL, 0x0ba93563UL, 0x8e342bc1UL, 0xe8a11be9UL, 0x4980740dUL, 0xc8087dfcUL,
0x8de4bf99UL, 0xa11101a0UL, 0x7fd37975UL, 0xda5a26c0UL, 0xe81f994fUL, 0x9528cd89UL,
0xfd339fedUL, 0xb87834bfUL, 0x5f04456dUL, 0x22258698UL, 0xc9c4c83bUL, 0x2dc156beUL,
0x4f628daaUL, 0x57f55ec5UL, 0xe2220abeUL, 0xd2916ebfUL, 0x4ec75b95UL, 0x24f2c3c0UL,
0x42d15d99UL, 0xcd0d7fa0UL, 0x7b6e27ffUL, 0xa8dc8af0UL, 0x7345c106UL, 0xf41e232fUL,
0x35162386UL, 0xe6ea8926UL, 0x3333b094UL, 0x157ec6f2UL, 0x372b74afUL, 0x692573e4UL,
0xe9a9d848UL, 0xf3160289UL, 0x3a62ef1dUL, 0xa787e238UL, 0xf3a5f676UL, 0x74364853UL,
0x20951063UL, 0x4576698dUL, 0xb6fad407UL, 0x592af950UL, 0x36f73523UL, 0x4cfb6e87UL,
0x7da4cec0UL, 0x6c152daaUL, 0xcb0396a8UL, 0xc50dfe5dUL, 0xfcd707abUL, 0x0921c42fUL,
0x89dff0bbUL, 0x5fe2be78UL, 0x448f4f33UL, 0x754613c9UL, 0x2b05d08dUL, 0x48b9d585UL,
0xdc049441UL, 0xc8098f9bUL, 0x7dede786UL, 0xc39a3373UL, 0x42410005UL, 0x6a091751UL,
0x0ef3c8a6UL, 0x890072d6UL, 0x28207682UL, 0xa9a9f7beUL, 0xbf32679dUL, 0xd45b5b75UL,
0xb353fd00UL, 0xcbb0e358UL, 0x830f220aUL, 0x1f8fb214UL, 0xd372cf08UL, 0xcc3c4a13UL,
0x8cf63166UL, 0x061c87beUL, 0x88c98f88UL, 0x6062e397UL, 0x47cf8e7aUL, 0xb6c85283UL,
0x3cc2acfbUL, 0x3fc06976UL, 0x4e8f0252UL, 0x64d8314dUL, 0xda3870e3UL, 0x1e665459UL,
0xc10908f0UL, 0x513021a5UL, 0x6c5b68b7UL, 0x822f8aa0UL, 0x3007cd3eUL, 0x74719eefUL,
0xdc872681UL, 0x073340d4UL, 0x7e432fd9UL, 0x0c5ec241UL, 0x8809286cUL, 0xf592d891UL,
0x08a930f6UL, 0x957ef305UL, 0xb7fbffbdUL, 0xc266e96fUL, 0x6fe4ac98UL, 0xb173ecc0UL,
0xbc60b42aUL, 0x953498daUL, 0xfba1ae12UL, 0x2d4bd736UL, 0x0f25faabUL, 0xa4f3fcebUL,
0xe2969123UL, 0x257f0c3dUL, 0x9348af49UL, 0x361400bcUL, 0xe8816f4aUL, 0x3814f200UL,
0xa3f94043UL, 0x9c7a54c2UL, 0xbc704f57UL, 0xda41e7f9UL, 0xc25ad33aUL, 0x54f4a084UL,
0xb17f5505UL, 0x59357cbeUL, 0xedbd15c8UL, 0x7f97c5abUL, 0xba5ac7b5UL, 0xb6f6deafUL,
0x3a479c3aUL, 0x5302da25UL, 0x653d7e6aUL, 0x54268d49UL, 0x51a477eaUL, 0x5017d55bUL,
0xd7d25d88UL, 0x44136c76UL, 0x0404a8c8UL, 0xb8e5a121UL, 0xb81a928aUL, 0x60ed5869UL,
0x97c55b96UL, 0xeaec991bUL, 0x29935913UL, 0x01fdb7f1UL, 0x088e8dfaUL, 0x9ab6f6f5UL,
0x3b4cbf9fUL, 0x4a5de3abUL, 0xe6051d35UL, 0xa0e1d855UL, 0xd36b4cf1UL, 0xf544edebUL,
0xb0e93524UL, 0xbebb8fbdUL, 0xa2d762cfUL, 0x49c92f54UL, 0x38b5f331UL, 0x7128a454UL,
0x48392905UL, 0xa65b1db8UL, 0x851c97bdUL, 0xd675cf2fUL};
static const ulong32 S7[256] = {
0x85e04019UL, 0x332bf567UL, 0x662dbfffUL, 0xcfc65693UL, 0x2a8d7f6fUL, 0xab9bc912UL,
0xde6008a1UL, 0x2028da1fUL, 0x0227bce7UL, 0x4d642916UL, 0x18fac300UL, 0x50f18b82UL,
0x2cb2cb11UL, 0xb232e75cUL, 0x4b3695f2UL, 0xb28707deUL, 0xa05fbcf6UL, 0xcd4181e9UL,
0xe150210cUL, 0xe24ef1bdUL, 0xb168c381UL, 0xfde4e789UL, 0x5c79b0d8UL, 0x1e8bfd43UL,
0x4d495001UL, 0x38be4341UL, 0x913cee1dUL, 0x92a79c3fUL, 0x089766beUL, 0xbaeeadf4UL,
0x1286becfUL, 0xb6eacb19UL, 0x2660c200UL, 0x7565bde4UL, 0x64241f7aUL, 0x8248dca9UL,
0xc3b3ad66UL, 0x28136086UL, 0x0bd8dfa8UL, 0x356d1cf2UL, 0x107789beUL, 0xb3b2e9ceUL,
0x0502aa8fUL, 0x0bc0351eUL, 0x166bf52aUL, 0xeb12ff82UL, 0xe3486911UL, 0xd34d7516UL,
0x4e7b3affUL, 0x5f43671bUL, 0x9cf6e037UL, 0x4981ac83UL, 0x334266ceUL, 0x8c9341b7UL,
0xd0d854c0UL, 0xcb3a6c88UL, 0x47bc2829UL, 0x4725ba37UL, 0xa66ad22bUL, 0x7ad61f1eUL,
0x0c5cbafaUL, 0x4437f107UL, 0xb6e79962UL, 0x42d2d816UL, 0x0a961288UL, 0xe1a5c06eUL,
0x13749e67UL, 0x72fc081aUL, 0xb1d139f7UL, 0xf9583745UL, 0xcf19df58UL, 0xbec3f756UL,
0xc06eba30UL, 0x07211b24UL, 0x45c28829UL, 0xc95e317fUL, 0xbc8ec511UL, 0x38bc46e9UL,
0xc6e6fa14UL, 0xbae8584aUL, 0xad4ebc46UL, 0x468f508bUL, 0x7829435fUL, 0xf124183bUL,
0x821dba9fUL, 0xaff60ff4UL, 0xea2c4e6dUL, 0x16e39264UL, 0x92544a8bUL, 0x009b4fc3UL,
0xaba68cedUL, 0x9ac96f78UL, 0x06a5b79aUL, 0xb2856e6eUL, 0x1aec3ca9UL, 0xbe838688UL,
0x0e0804e9UL, 0x55f1be56UL, 0xe7e5363bUL, 0xb3a1f25dUL, 0xf7debb85UL, 0x61fe033cUL,
0x16746233UL, 0x3c034c28UL, 0xda6d0c74UL, 0x79aac56cUL, 0x3ce4e1adUL, 0x51f0c802UL,
0x98f8f35aUL, 0x1626a49fUL, 0xeed82b29UL, 0x1d382fe3UL, 0x0c4fb99aUL, 0xbb325778UL,
0x3ec6d97bUL, 0x6e77a6a9UL, 0xcb658b5cUL, 0xd45230c7UL, 0x2bd1408bUL, 0x60c03eb7UL,
0xb9068d78UL, 0xa33754f4UL, 0xf430c87dUL, 0xc8a71302UL, 0xb96d8c32UL, 0xebd4e7beUL,
0xbe8b9d2dUL, 0x7979fb06UL, 0xe7225308UL, 0x8b75cf77UL, 0x11ef8da4UL, 0xe083c858UL,
0x8d6b786fUL, 0x5a6317a6UL, 0xfa5cf7a0UL, 0x5dda0033UL, 0xf28ebfb0UL, 0xf5b9c310UL,
0xa0eac280UL, 0x08b9767aUL, 0xa3d9d2b0UL, 0x79d34217UL, 0x021a718dUL, 0x9ac6336aUL,
0x2711fd60UL, 0x438050e3UL, 0x069908a8UL, 0x3d7fedc4UL, 0x826d2befUL, 0x4eeb8476UL,
0x488dcf25UL, 0x36c9d566UL, 0x28e74e41UL, 0xc2610acaUL, 0x3d49a9cfUL, 0xbae3b9dfUL,
0xb65f8de6UL, 0x92aeaf64UL, 0x3ac7d5e6UL, 0x9ea80509UL, 0xf22b017dUL, 0xa4173f70UL,
0xdd1e16c3UL, 0x15e0d7f9UL, 0x50b1b887UL, 0x2b9f4fd5UL, 0x625aba82UL, 0x6a017962UL,
0x2ec01b9cUL, 0x15488aa9UL, 0xd716e740UL, 0x40055a2cUL, 0x93d29a22UL, 0xe32dbf9aUL,
0x058745b9UL, 0x3453dc1eUL, 0xd699296eUL, 0x496cff6fUL, 0x1c9f4986UL, 0xdfe2ed07UL,
0xb87242d1UL, 0x19de7eaeUL, 0x053e561aUL, 0x15ad6f8cUL, 0x66626c1cUL, 0x7154c24cUL,
0xea082b2aUL, 0x93eb2939UL, 0x17dcb0f0UL, 0x58d4f2aeUL, 0x9ea294fbUL, 0x52cf564cUL,
0x9883fe66UL, 0x2ec40581UL, 0x763953c3UL, 0x01d6692eUL, 0xd3a0c108UL, 0xa1e7160eUL,
0xe4f2dfa6UL, 0x693ed285UL, 0x74904698UL, 0x4c2b0eddUL, 0x4f757656UL, 0x5d393378UL,
0xa132234fUL, 0x3d321c5dUL, 0xc3f5e194UL, 0x4b269301UL, 0xc79f022fUL, 0x3c997e7eUL,
0x5e4f9504UL, 0x3ffafbbdUL, 0x76f7ad0eUL, 0x296693f4UL, 0x3d1fce6fUL, 0xc61e45beUL,
0xd3b5ab34UL, 0xf72bf9b7UL, 0x1b0434c0UL, 0x4e72b567UL, 0x5592a33dUL, 0xb5229301UL,
0xcfd2a87fUL, 0x60aeb767UL, 0x1814386bUL, 0x30bcc33dUL, 0x38a0c07dUL, 0xfd1606f2UL,
0xc363519bUL, 0x589dd390UL, 0x5479f8e6UL, 0x1cb8d647UL, 0x97fd61a9UL, 0xea7759f4UL,
0x2d57539dUL, 0x569a58cfUL, 0xe84e63adUL, 0x462e1b78UL, 0x6580f87eUL, 0xf3817914UL,
0x91da55f4UL, 0x40a230f3UL, 0xd1988f35UL, 0xb6e318d2UL, 0x3ffa50bcUL, 0x3d40f021UL,
0xc3c0bdaeUL, 0x4958c24cUL, 0x518f36b2UL, 0x84b1d370UL, 0x0fedce83UL, 0x878ddadaUL,
0xf2a279c7UL, 0x94e01be8UL, 0x90716f4bUL, 0x954b8aa3UL};
static const ulong32 S8[256] = {
0xe216300dUL, 0xbbddfffcUL, 0xa7ebdabdUL, 0x35648095UL, 0x7789f8b7UL, 0xe6c1121bUL,
0x0e241600UL, 0x052ce8b5UL, 0x11a9cfb0UL, 0xe5952f11UL, 0xece7990aUL, 0x9386d174UL,
0x2a42931cUL, 0x76e38111UL, 0xb12def3aUL, 0x37ddddfcUL, 0xde9adeb1UL, 0x0a0cc32cUL,
0xbe197029UL, 0x84a00940UL, 0xbb243a0fUL, 0xb4d137cfUL, 0xb44e79f0UL, 0x049eedfdUL,
0x0b15a15dUL, 0x480d3168UL, 0x8bbbde5aUL, 0x669ded42UL, 0xc7ece831UL, 0x3f8f95e7UL,
0x72df191bUL, 0x7580330dUL, 0x94074251UL, 0x5c7dcdfaUL, 0xabbe6d63UL, 0xaa402164UL,
0xb301d40aUL, 0x02e7d1caUL, 0x53571daeUL, 0x7a3182a2UL, 0x12a8ddecUL, 0xfdaa335dUL,
0x176f43e8UL, 0x71fb46d4UL, 0x38129022UL, 0xce949ad4UL, 0xb84769adUL, 0x965bd862UL,
0x82f3d055UL, 0x66fb9767UL, 0x15b80b4eUL, 0x1d5b47a0UL, 0x4cfde06fUL, 0xc28ec4b8UL,
0x57e8726eUL, 0x647a78fcUL, 0x99865d44UL, 0x608bd593UL, 0x6c200e03UL, 0x39dc5ff6UL,
0x5d0b00a3UL, 0xae63aff2UL, 0x7e8bd632UL, 0x70108c0cUL, 0xbbd35049UL, 0x2998df04UL,
0x980cf42aUL, 0x9b6df491UL, 0x9e7edd53UL, 0x06918548UL, 0x58cb7e07UL, 0x3b74ef2eUL,
0x522fffb1UL, 0xd24708ccUL, 0x1c7e27cdUL, 0xa4eb215bUL, 0x3cf1d2e2UL, 0x19b47a38UL,
0x424f7618UL, 0x35856039UL, 0x9d17dee7UL, 0x27eb35e6UL, 0xc9aff67bUL, 0x36baf5b8UL,
0x09c467cdUL, 0xc18910b1UL, 0xe11dbf7bUL, 0x06cd1af8UL, 0x7170c608UL, 0x2d5e3354UL,
0xd4de495aUL, 0x64c6d006UL, 0xbcc0c62cUL, 0x3dd00db3UL, 0x708f8f34UL, 0x77d51b42UL,
0x264f620fUL, 0x24b8d2bfUL, 0x15c1b79eUL, 0x46a52564UL, 0xf8d7e54eUL, 0x3e378160UL,
0x7895cda5UL, 0x859c15a5UL, 0xe6459788UL, 0xc37bc75fUL, 0xdb07ba0cUL, 0x0676a3abUL,
0x7f229b1eUL, 0x31842e7bUL, 0x24259fd7UL, 0xf8bef472UL, 0x835ffcb8UL, 0x6df4c1f2UL,
0x96f5b195UL, 0xfd0af0fcUL, 0xb0fe134cUL, 0xe2506d3dUL, 0x4f9b12eaUL, 0xf215f225UL,
0xa223736fUL, 0x9fb4c428UL, 0x25d04979UL, 0x34c713f8UL, 0xc4618187UL, 0xea7a6e98UL,
0x7cd16efcUL, 0x1436876cUL, 0xf1544107UL, 0xbedeee14UL, 0x56e9af27UL, 0xa04aa441UL,
0x3cf7c899UL, 0x92ecbae6UL, 0xdd67016dUL, 0x151682ebUL, 0xa842eedfUL, 0xfdba60b4UL,
0xf1907b75UL, 0x20e3030fUL, 0x24d8c29eUL, 0xe139673bUL, 0xefa63fb8UL, 0x71873054UL,
0xb6f2cf3bUL, 0x9f326442UL, 0xcb15a4ccUL, 0xb01a4504UL, 0xf1e47d8dUL, 0x844a1be5UL,
0xbae7dfdcUL, 0x42cbda70UL, 0xcd7dae0aUL, 0x57e85b7aUL, 0xd53f5af6UL, 0x20cf4d8cUL,
0xcea4d428UL, 0x79d130a4UL, 0x3486ebfbUL, 0x33d3cddcUL, 0x77853b53UL, 0x37effcb5UL,
0xc5068778UL, 0xe580b3e6UL, 0x4e68b8f4UL, 0xc5c8b37eUL, 0x0d809ea2UL, 0x398feb7cUL,
0x132a4f94UL, 0x43b7950eUL, 0x2fee7d1cUL, 0x223613bdUL, 0xdd06caa2UL, 0x37df932bUL,
0xc4248289UL, 0xacf3ebc3UL, 0x5715f6b7UL, 0xef3478ddUL, 0xf267616fUL, 0xc148cbe4UL,
0x9052815eUL, 0x5e410fabUL, 0xb48a2465UL, 0x2eda7fa4UL, 0xe87b40e4UL, 0xe98ea084UL,
0x5889e9e1UL, 0xefd390fcUL, 0xdd07d35bUL, 0xdb485694UL, 0x38d7e5b2UL, 0x57720101UL,
0x730edebcUL, 0x5b643113UL, 0x94917e4fUL, 0x503c2fbaUL, 0x646f1282UL, 0x7523d24aUL,
0xe0779695UL, 0xf9c17a8fUL, 0x7a5b2121UL, 0xd187b896UL, 0x29263a4dUL, 0xba510cdfUL,
0x81f47c9fUL, 0xad1163edUL, 0xea7b5965UL, 0x1a00726eUL, 0x11403092UL, 0x00da6d77UL,
0x4a0cdd61UL, 0xad1f4603UL, 0x605bdfb0UL, 0x9eedc364UL, 0x22ebe6a8UL, 0xcee7d28aUL,
0xa0e736a0UL, 0x5564a6b9UL, 0x10853209UL, 0xc7eb8f37UL, 0x2de705caUL, 0x8951570fUL,
0xdf09822bUL, 0xbd691a6cUL, 0xaa12e4f2UL, 0x87451c0fUL, 0xe0f6a27aUL, 0x3ada4819UL,
0x4cf1764fUL, 0x0d771c2bUL, 0x67cdb156UL, 0x350d8384UL, 0x5938fa0fUL, 0x42399ef3UL,
0x36997b07UL, 0x0e84093dUL, 0x4aa93e61UL, 0x8360d87bUL, 0x1fa98b0cUL, 0x1149382cUL,
0xe97625a5UL, 0x0614d1b7UL, 0x0e25244bUL, 0x0c768347UL, 0x589e8d82UL, 0x0d2059d1UL,
0xa466bb1eUL, 0xf8da0a82UL, 0x04f19130UL, 0xba6e4ec0UL, 0x99265164UL, 0x1ee7230dUL,
0x50b2ad80UL, 0xeaee6801UL, 0x8db2a283UL, 0xea8bf59eUL};
/* returns the i'th byte of a variable */
#ifdef _MSC_VER
#define GB(x, i) ((unsigned char)((x[(15-i)>>2])>>(unsigned)(8*((15-i)&3))))
#else
#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];
int y, i;
_ARGCHK(key != NULL);
_ARGCHK(skey != NULL);
if (num_rounds != 12 && num_rounds != 16 && num_rounds != 0) {
return CRYPT_INVALID_ROUNDS;
}
if (num_rounds == 12 && keylen > 10) {
return CRYPT_INVALID_ROUNDS;
}
if (keylen < 5 || keylen > 16) {
return CRYPT_INVALID_KEYSIZE;
}
/* extend the key as required */
zeromem(buf, sizeof(buf));
memcpy(buf, key, (size_t)keylen);
/* load and start the awful looking network */
for (y = 0; y < 4; y++) {
LOAD32H(x[3-y],buf+4*y);
}
for (i = y = 0; y < 2; y++) {
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)];
z[0] = x[2] ^ S5[GB(z, 0xA)] ^ S6[GB(z, 0x9)] ^ S7[GB(z, 0xb)] ^ S8[GB(z, 0x8)] ^ S6[GB(x, 0xB)];
skey->cast5.K[i++] = S5[GB(z, 0x8)] ^ S6[GB(z, 0x9)] ^ S7[GB(z, 0x7)] ^ S8[GB(z, 0x6)] ^ S5[GB(z, 0x2)];
skey->cast5.K[i++] = S5[GB(z, 0xA)] ^ S6[GB(z, 0xB)] ^ S7[GB(z, 0x5)] ^ S8[GB(z, 0x4)] ^ S6[GB(z, 0x6)];
skey->cast5.K[i++] = S5[GB(z, 0xC)] ^ S6[GB(z, 0xd)] ^ S7[GB(z, 0x3)] ^ S8[GB(z, 0x2)] ^ S7[GB(z, 0x9)];
skey->cast5.K[i++] = S5[GB(z, 0xE)] ^ S6[GB(z, 0xF)] ^ S7[GB(z, 0x1)] ^ S8[GB(z, 0x0)] ^ S8[GB(z, 0xc)];
x[3] = z[1] ^ S5[GB(z, 0x5)] ^ S6[GB(z, 0x7)] ^ S7[GB(z, 0x4)] ^ S8[GB(z, 0x6)] ^ S7[GB(z, 0x0)];
x[2] = z[3] ^ S5[GB(x, 0x0)] ^ S6[GB(x, 0x2)] ^ S7[GB(x, 0x1)] ^ S8[GB(x, 0x3)] ^ S8[GB(z, 0x2)];
x[1] = z[2] ^ S5[GB(x, 0x7)] ^ S6[GB(x, 0x6)] ^ S7[GB(x, 0x5)] ^ S8[GB(x, 0x4)] ^ S5[GB(z, 0x1)];
x[0] = z[0] ^ S5[GB(x, 0xA)] ^ S6[GB(x, 0x9)] ^ S7[GB(x, 0xb)] ^ S8[GB(x, 0x8)] ^ S6[GB(z, 0x3)];
skey->cast5.K[i++] = S5[GB(x, 0x3)] ^ S6[GB(x, 0x2)] ^ S7[GB(x, 0xc)] ^ S8[GB(x, 0xd)] ^ S5[GB(x, 0x8)];
skey->cast5.K[i++] = S5[GB(x, 0x1)] ^ S6[GB(x, 0x0)] ^ S7[GB(x, 0xe)] ^ S8[GB(x, 0xf)] ^ S6[GB(x, 0xd)];
skey->cast5.K[i++] = S5[GB(x, 0x7)] ^ S6[GB(x, 0x6)] ^ S7[GB(x, 0x8)] ^ S8[GB(x, 0x9)] ^ S7[GB(x, 0x3)];
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)];
z[0] = x[2] ^ S5[GB(z, 0xA)] ^ S6[GB(z, 0x9)] ^ S7[GB(z, 0xb)] ^ S8[GB(z, 0x8)] ^ S6[GB(x, 0xB)];
skey->cast5.K[i++] = S5[GB(z, 0x3)] ^ S6[GB(z, 0x2)] ^ S7[GB(z, 0xc)] ^ S8[GB(z, 0xd)] ^ S5[GB(z, 0x9)];
skey->cast5.K[i++] = S5[GB(z, 0x1)] ^ S6[GB(z, 0x0)] ^ S7[GB(z, 0xe)] ^ S8[GB(z, 0xf)] ^ S6[GB(z, 0xc)];
skey->cast5.K[i++] = S5[GB(z, 0x7)] ^ S6[GB(z, 0x6)] ^ S7[GB(z, 0x8)] ^ S8[GB(z, 0x9)] ^ S7[GB(z, 0x2)];
skey->cast5.K[i++] = S5[GB(z, 0x5)] ^ S6[GB(z, 0x4)] ^ S7[GB(z, 0xa)] ^ S8[GB(z, 0xb)] ^ S8[GB(z, 0x6)];
x[3] = z[1] ^ S5[GB(z, 0x5)] ^ S6[GB(z, 0x7)] ^ S7[GB(z, 0x4)] ^ S8[GB(z, 0x6)] ^ S7[GB(z, 0x0)];
x[2] = z[3] ^ S5[GB(x, 0x0)] ^ S6[GB(x, 0x2)] ^ S7[GB(x, 0x1)] ^ S8[GB(x, 0x3)] ^ S8[GB(z, 0x2)];
x[1] = z[2] ^ S5[GB(x, 0x7)] ^ S6[GB(x, 0x6)] ^ S7[GB(x, 0x5)] ^ S8[GB(x, 0x4)] ^ S5[GB(z, 0x1)];
x[0] = z[0] ^ S5[GB(x, 0xA)] ^ S6[GB(x, 0x9)] ^ S7[GB(x, 0xb)] ^ S8[GB(x, 0x8)] ^ S6[GB(z, 0x3)];
skey->cast5.K[i++] = S5[GB(x, 0x8)] ^ S6[GB(x, 0x9)] ^ S7[GB(x, 0x7)] ^ S8[GB(x, 0x6)] ^ S5[GB(x, 0x3)];
skey->cast5.K[i++] = S5[GB(x, 0xa)] ^ S6[GB(x, 0xb)] ^ S7[GB(x, 0x5)] ^ S8[GB(x, 0x4)] ^ S6[GB(x, 0x7)];
skey->cast5.K[i++] = S5[GB(x, 0xc)] ^ S6[GB(x, 0xd)] ^ S7[GB(x, 0x3)] ^ S8[GB(x, 0x2)] ^ S7[GB(x, 0x8)];
skey->cast5.K[i++] = S5[GB(x, 0xe)] ^ S6[GB(x, 0xf)] ^ S7[GB(x, 0x1)] ^ S8[GB(x, 0x0)] ^ S8[GB(x, 0xd)];
}
skey->cast5.keylen = keylen;
#ifdef CLEAN_STACK
zeromem(buf, sizeof(buf));
zeromem(x, sizeof(x));
zeromem(z, sizeof(z));
#endif
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
#define INLINE
#endif
INLINE static ulong32 FI(ulong32 R, ulong32 Km, ulong32 Kr)
{
ulong32 I;
I = (Km + R);
I = ROL(I, Kr);
return ((S1[byte(I, 3)] ^ S2[byte(I,2)]) - S3[byte(I,1)]) + S4[byte(I,0)];
}
INLINE static ulong32 FII(ulong32 R, ulong32 Km, ulong32 Kr)
{
ulong32 I;
I = (Km ^ R);
I = ROL(I, Kr);
return ((S1[byte(I, 3)] - S2[byte(I,2)]) + S3[byte(I,1)]) ^ S4[byte(I,0)];
}
INLINE static ulong32 FIII(ulong32 R, ulong32 Km, ulong32 Kr)
{
ulong32 I;
I = (Km - R);
I = ROL(I, 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;
_ARGCHK(pt != NULL);
_ARGCHK(ct != NULL);
_ARGCHK(key != NULL);
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]);
R ^= FI(L, key->cast5.K[3], key->cast5.K[19]);
L ^= FII(R, key->cast5.K[4], key->cast5.K[20]);
R ^= FIII(L, key->cast5.K[5], key->cast5.K[21]);
L ^= FI(R, key->cast5.K[6], key->cast5.K[22]);
R ^= FII(L, key->cast5.K[7], key->cast5.K[23]);
L ^= FIII(R, key->cast5.K[8], key->cast5.K[24]);
R ^= FI(L, key->cast5.K[9], key->cast5.K[25]);
L ^= FII(R, key->cast5.K[10], key->cast5.K[26]);
R ^= FIII(L, key->cast5.K[11], key->cast5.K[27]);
if (key->cast5.keylen > 10) {
L ^= FI(R, key->cast5.K[12], key->cast5.K[28]);
R ^= FII(L, key->cast5.K[13], key->cast5.K[29]);
L ^= FIII(R, key->cast5.K[14], key->cast5.K[30]);
R ^= FI(L, key->cast5.K[15], key->cast5.K[31]);
}
STORE32H(R,&ct[0]);
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;
_ARGCHK(pt != NULL);
_ARGCHK(ct != NULL);
_ARGCHK(key != NULL);
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]);
L ^= FIII(R, key->cast5.K[8], key->cast5.K[24]);
R ^= FII(L, key->cast5.K[7], key->cast5.K[23]);
L ^= FI(R, key->cast5.K[6], key->cast5.K[22]);
R ^= FIII(L, key->cast5.K[5], key->cast5.K[21]);
L ^= FII(R, key->cast5.K[4], key->cast5.K[20]);
R ^= FI(L, key->cast5.K[3], key->cast5.K[19]);
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
return CRYPT_NOP;
#else
static const struct {
int keylen;
unsigned char key[16];
unsigned char pt[8];
unsigned char ct[8];
} tests[] = {
{ 16,
{0x01, 0x23, 0x45, 0x67, 0x12, 0x34, 0x56, 0x78, 0x23, 0x45, 0x67, 0x89, 0x34, 0x56, 0x78, 0x9A},
{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF},
{0x23, 0x8B, 0x4F, 0xE5, 0x84, 0x7E, 0x44, 0xB2}
},
{ 10,
{0x01, 0x23, 0x45, 0x67, 0x12, 0x34, 0x56, 0x78, 0x23, 0x45, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF},
{0xEB, 0x6A, 0x71, 0x1A, 0x2C, 0x02, 0x27, 0x1B},
},
{ 5,
{0x01, 0x23, 0x45, 0x67, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF},
{0x7A, 0xC8, 0x16, 0xD1, 0x6E, 0x9B, 0x30, 0x2E}
}
};
int i, y, err;
symmetric_key key;
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, 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;
#endif
}
int cast5_keysize(int *desired_keysize)
{
_ARGCHK(desired_keysize != NULL);
if (*desired_keysize < 5) {
return CRYPT_INVALID_KEYSIZE;
} else if (*desired_keysize > 16) {
*desired_keysize = 16;
}
return CRYPT_OK;
}
#endif

56
cbc_decrypt.c Normal file
View File

@@ -0,0 +1,56 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
*
* LibTomCrypt is a library that provides various cryptographic
* algorithms in a highly modular and flexible manner.
*
* The library is free for all purposes without any express
* guarantee it works.
*
* Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org
*/
#include "mycrypt.h"
#ifdef CBC
int cbc_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_CBC *cbc)
{
int x, err;
unsigned char tmp[MAXBLOCKSIZE], tmp2[MAXBLOCKSIZE];
_ARGCHK(pt != NULL);
_ARGCHK(ct != NULL);
_ARGCHK(cbc != NULL);
/* decrypt the block from ct into tmp */
if ((err = cipher_is_valid(cbc->cipher)) != CRYPT_OK) {
return err;
}
cipher_descriptor[cbc->cipher].ecb_decrypt(ct, tmp, &cbc->key);
/* is blocklen valid? */
if (cbc->blocklen < 0 || cbc->blocklen > (int)sizeof(cbc->IV)) {
return CRYPT_INVALID_ARG;
}
/* xor IV against the plaintext of the previous step */
for (x = 0; x < cbc->blocklen; x++) {
/* copy CT in case ct == pt */
tmp2[x] = ct[x];
/* actually decrypt the byte */
pt[x] = tmp[x] ^ cbc->IV[x];
}
/* replace IV with this current ciphertext */
for (x = 0; x < cbc->blocklen; x++) {
cbc->IV[x] = tmp2[x];
}
#ifdef CLEAN_STACK
zeromem(tmp, sizeof(tmp));
zeromem(tmp2, sizeof(tmp2));
#endif
return CRYPT_OK;
}
#endif

52
cbc_encrypt.c Normal file
View File

@@ -0,0 +1,52 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
*
* LibTomCrypt is a library that provides various cryptographic
* algorithms in a highly modular and flexible manner.
*
* The library is free for all purposes without any express
* guarantee it works.
*
* Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org
*/
#include "mycrypt.h"
#ifdef CBC
int cbc_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_CBC *cbc)
{
int x, err;
unsigned char tmp[MAXBLOCKSIZE];
_ARGCHK(pt != NULL);
_ARGCHK(ct != NULL);
_ARGCHK(cbc != NULL);
if ((err = cipher_is_valid(cbc->cipher)) != CRYPT_OK) {
return err;
}
/* is blocklen valid? */
if (cbc->blocklen < 0 || cbc->blocklen > (int)sizeof(cbc->IV)) {
return CRYPT_INVALID_ARG;
}
/* xor IV against plaintext */
for (x = 0; x < cbc->blocklen; x++) {
tmp[x] = pt[x] ^ cbc->IV[x];
}
/* encrypt */
cipher_descriptor[cbc->cipher].ecb_encrypt(tmp, ct, &cbc->key);
/* store IV [ciphertext] for a future block */
for (x = 0; x < cbc->blocklen; x++) {
cbc->IV[x] = ct[x];
}
#ifdef CLEAN_STACK
zeromem(tmp, sizeof(tmp));
#endif
return CRYPT_OK;
}
#endif

43
cbc_start.c Normal file
View File

@@ -0,0 +1,43 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
*
* LibTomCrypt is a library that provides various cryptographic
* algorithms in a highly modular and flexible manner.
*
* The library is free for all purposes without any express
* guarantee it works.
*
* Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org
*/
#include "mycrypt.h"
#ifdef CBC
int cbc_start(int cipher, const unsigned char *IV, const unsigned char *key,
int keylen, int num_rounds, symmetric_CBC *cbc)
{
int x, err;
_ARGCHK(IV != NULL);
_ARGCHK(key != NULL);
_ARGCHK(cbc != NULL);
/* bad param? */
if ((err = cipher_is_valid(cipher)) != CRYPT_OK) {
return err;
}
/* setup cipher */
if ((err = cipher_descriptor[cipher].setup(key, keylen, num_rounds, &cbc->key)) != CRYPT_OK) {
return err;
}
/* copy IV */
cbc->blocklen = cipher_descriptor[cipher].block_length;
cbc->cipher = cipher;
for (x = 0; x < cbc->blocklen; x++) {
cbc->IV[x] = IV[x];
}
return CRYPT_OK;
}
#endif

48
cfb_decrypt.c Normal file
View File

@@ -0,0 +1,48 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
*
* LibTomCrypt is a library that provides various cryptographic
* algorithms in a highly modular and flexible manner.
*
* The library is free for all purposes without any express
* guarantee it works.
*
* Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org
*/
#include "mycrypt.h"
#ifdef CFB
int cfb_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_CFB *cfb)
{
int err;
_ARGCHK(pt != NULL);
_ARGCHK(ct != NULL);
_ARGCHK(cfb != NULL);
if ((err = cipher_is_valid(cfb->cipher)) != CRYPT_OK) {
return err;
}
/* is blocklen/padlen valid? */
if (cfb->blocklen < 0 || cfb->blocklen > (int)sizeof(cfb->IV) ||
cfb->padlen < 0 || cfb->padlen > (int)sizeof(cfb->pad)) {
return CRYPT_INVALID_ARG;
}
while (len-- > 0) {
if (cfb->padlen == cfb->blocklen) {
cipher_descriptor[cfb->cipher].ecb_encrypt(cfb->pad, cfb->IV, &cfb->key);
cfb->padlen = 0;
}
cfb->pad[cfb->padlen] = *ct;
*pt = *ct ^ cfb->IV[cfb->padlen];
++pt;
++ct;
++cfb->padlen;
}
return CRYPT_OK;
}
#endif

46
cfb_encrypt.c Normal file
View File

@@ -0,0 +1,46 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
*
* LibTomCrypt is a library that provides various cryptographic
* algorithms in a highly modular and flexible manner.
*
* The library is free for all purposes without any express
* guarantee it works.
*
* Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org
*/
#include "mycrypt.h"
#ifdef CFB
int cfb_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_CFB *cfb)
{
int err;
_ARGCHK(pt != NULL);
_ARGCHK(ct != NULL);
_ARGCHK(cfb != NULL);
if ((err = cipher_is_valid(cfb->cipher)) != CRYPT_OK) {
return err;
}
/* is blocklen/padlen valid? */
if (cfb->blocklen < 0 || cfb->blocklen > (int)sizeof(cfb->IV) ||
cfb->padlen < 0 || cfb->padlen > (int)sizeof(cfb->pad)) {
return CRYPT_INVALID_ARG;
}
while (len-- > 0) {
if (cfb->padlen == cfb->blocklen) {
cipher_descriptor[cfb->cipher].ecb_encrypt(cfb->pad, cfb->IV, &cfb->key);
cfb->padlen = 0;
}
cfb->pad[cfb->padlen] = (*ct = *pt ^ cfb->IV[cfb->padlen]);
++pt;
++ct;
++cfb->padlen;
}
return CRYPT_OK;
}
#endif

47
cfb_start.c Normal file
View File

@@ -0,0 +1,47 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
*
* LibTomCrypt is a library that provides various cryptographic
* algorithms in a highly modular and flexible manner.
*
* The library is free for all purposes without any express
* guarantee it works.
*
* Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org
*/
#include "mycrypt.h"
#ifdef CFB
int cfb_start(int cipher, const unsigned char *IV, const unsigned char *key,
int keylen, int num_rounds, symmetric_CFB *cfb)
{
int x, err;
_ARGCHK(IV != NULL);
_ARGCHK(key != NULL);
_ARGCHK(cfb != NULL);
if ((err = cipher_is_valid(cipher)) != CRYPT_OK) {
return err;
}
/* copy data */
cfb->cipher = cipher;
cfb->blocklen = cipher_descriptor[cipher].block_length;
for (x = 0; x < cfb->blocklen; x++)
cfb->IV[x] = IV[x];
/* init the cipher */
if ((err = cipher_descriptor[cipher].setup(key, keylen, num_rounds, &cfb->key)) != CRYPT_OK) {
return err;
}
/* encrypt the IV */
cipher_descriptor[cfb->cipher].ecb_encrypt(cfb->IV, cfb->IV, &cfb->key);
cfb->padlen = 0;
return CRYPT_OK;
}
#endif

957
changes Normal file
View File

@@ -0,0 +1,957 @@
May 12th, 2004
v0.95 -- Optimized AES and WHIRLPOOL for SMALL_CODE by taking advantage of the fact
the transforms are circulant. AES dropped 5KB and WHIRLPOOL dropped 13KB
using the default build options on the x86.
-- Updated eax so the eax_done() would clear the state [like hmac,pmac,ocb] when
CLEAN_STACK has been defined.
-- added LTC_TEST support to rmd160
-- updates to mycrypt_pk.h
-- updated rand_prime() to faciliate making RSA composites
-- DSA/RSA now makes composites of the exact size desired.
-- Refactored quite a bit of the code, fewer functions per C file
-- cleaned up the makefiles to organize the objects logically
-- added ICC makefile along with "profiled" targets for both GNU and ICC compilers
-- Marked functions for removal before v1.00 see PLAN for more information
-- GCC 3.4.0 tested and seems to work
-- Added PKCS #5 support
-- Fixed typo in comment header of .C files ;-)
-- Added PKCS #1 OAEP and PSS support.
Feb 20th, 2004
v0.94 -- removed unused variables from ocb.c and fixed it to match known test vectors.
-- Added PMAC support, minor changes to OMAC/EAX code [I think....]
-- Teamed up with Brian Gladman. His code verifies against my vectors and my code
verifies against his test vectors. Hazaa for co-operation!
-- Various small changes (added missing ARGCHKs and cleaned up indentation)
-- Optimization to base64, removed unused variable "c"
-- Added base64 gen to demos/tv_gen.c
-- Fix to demos/x86_prof.c to correctly identify the i386 architecture... weird...
-- Fixed up all of the PK code by adding missing error checking, removed "res" variables,
shrunk some stack variables, removed non-required stack variables and added proper
error conversion from MPI to LTC codes. I also spotted a few "off by one" error
checking which could have been used to force the code to read past the end of
the buffer (in theory, haven't checked if it would work) by a few bytes.
-- Added checks to OUTPUT_BIGNUM so the *_export() functions cannot overflow the output and I
also modded it so it stores in the output provided to the function (that is not on
the local stack) which saves memory and time.
-- Made SAFER default to disabled for now (plans are to cleanhouse write an implementation later)
-- Added the 512-bit one-way hash WHIRLPOOL which clocks in at 138 cycles per byte on my
Athlon XP [for comparison, SHA-512 clocks in at 77 cycles per byte]. This code uses the
teams new sbox design (not the original NESSIE one).
Jan 25th, 2004
v0.93 -- [note: deleted v0.93 changes by accident... recreating from memory...]
-- Fix to RC2 to not deference pointer before ARGCHK
-- Fix to NOEKEON to match published test vectors as well as cleaned up the code a bit
-- Optimized Twofish [down to 28 cycles/byte on my box] and Blowfish
-- Fix to OMAC to test cipher block size first [prevents wasting any time]
-- Added more OMAC test vectors
-- Added EAX Encrypt+Authenticate support
-- Fix to DSA to check return of a few LTM functions I forgot [mp_to_unsigned_bin]
-- Added common headers to all C files
-- CTR mode supports big and little [default] endian counters now.
-- fix to find_cipher_any() so that it can handle a fragmented cipher_descriptor table.
-- added find_hash_any() akin to find_cipher_any().
-- Added EAX code to demos/tv_gen.c Hazaa!
-- Removed SONY defines and files from codebase.
-- Added OCB support [patents be damned] and to demos/tv_gen.c
-- Merge all of the INPUT/OUTPUT BIGNUM macros (less toc) into mycrypt_pk.h
-- Made appropriate changes to the debug string in crypt.c
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.
-- Added RIPEMD hashes to the hashsum demo.
-- Added hashsum demo to MSVC makefile.
-- Added RMD160 to the x86_prof demo [oops]
-- Merged in LibTomMath-0.27 with a patch to mp_shrink() that will be in LibTomMath-0.28
Fixes another potential memory leak.
Sept 7th, 2003
v0.90 -- new ROL/ROR for x86 GCC
-- Jochen Katz submitted a patch to the makefile to prevent "make" from making the .a library
when not required.
== By default the KR code is not enabled [it's only a demo anyways!]
-- changed the "buf" in ecc_make_key from 4KB to 128 bytes [since the largest key is 65 bytes]
-- hmac_done() now requires you pass it the size of the destination buffer to prevent
buffer overflows. (API CHANGE)
-- hmac/hash filebased routines now return CRYPT_NOP if NO_FILE is defined.
-- I've removed the primes from dh.c and replaced them with DR safe primes suitable for the default
configuration of LibTomMath. Check out these comparisons on a 1.3Ghz Athlon XP, optimized for size,
768-bit, 4 vs. 10
1024-bit, 8 vs. 18
1280-bit, 12 vs. 34
1536-bit, 20 vs. 56
1792-bit 28 vs. 88
2048-bit, 40 vs. 124
2560-bit, 71 vs. 234
3072-bit, 113 vs. 386
4096-bit, 283 vs. 916
Times are all in milliseconds for key generation. New primes times on the left. This makes the code binary
incompatible with previous releases. However, this addition is long overdue as LibTomMath has supported DR
reductions for quite some time.
-- Added RIPE-MD 128 and 160 to the list of supported hashes [10 in total].
-- The project has been released as public domain. TDCAL no longer applies.
July 15th, 2003
v0.89 -- Fix a bug in bits.c which would prevent it from building with msvc
-- Merged in LibTomMath v0.24 [and I used the alloc/free macros this time!]
-- Removed the LTC version of next_prime() and replaced it with a call to the
mp_prime_next_prime() from LibTomMath
-- reverted bits.c to the 0.86 copy since the new one doesn't build in MSVC
or cygwin.
Jul 10th, 2003
v0.88 -- Sped up CAST5 key schedule for MSVC
-- added "ulong32" which allows people on 64-bit platforms to force the 32-bit tables in
ciphers like blowfish and AES to be 32-bits. E.g. when unsigned long is 64-bits.
-- Optimized the SAFER-SK64, SAFER-SK128, SAFER+, RC5 and RC6 key schedule [big time!]
-- Optimized SHA-1 and SHA-256 quite a bit too.
-- Fixed up the makefile to use -fomit-frame-pointer more liberally
-- Added tv_gen program which makes test vectors for ciphers/hashes
-- Merged in LibTomMath v0.22
Jun 19th, 2003
v0.87 -- Many MSVC optimizations to the code base
-- Improved the AES and Twofish key schedule [faster, more constant time]
-- Tons of optimizations here and there.
Jun 15th, 2003
v0.86 -- Fixed up AES to workaround MSVC optimizer bug
-- Merged in fresh LTM base [based on v0.20] so there are no warnings with MSVC
-- Wrote x86_prof which will time the hashes and ciphers downto cycles per byte.
-- Fixed up demos/encrypt to remove serpent_desc from the list
-- Re-enabled MSVC optimizations w00t w00t
-- Replaced "errno" with "err" in all functions that had it so it wouldn't clash
with the global "errno"
-- Removed a set of unused variables from certain functions
-- Removed {#line 0 "..."} stuff from mpi.c to comply with ISO C :-)
Jun 11th, 2003
v0.85 -- Swapped in a new AES routine
-- Removed Serpent
-- Added TDCAL policy document
Jun 1st, 2003
v0.84 -- Removed a 4KB buffer from rsa_decrypt_key that wasn't being used no more
-- Fixed another potential buffer problem. Not an overflow but could cause the
PK import routines to read past the end of the buffer.
-- Optimized the ECC mulmod more by removing a if condition that will always be false
-- Optimized prime.c to not include a 2nd prime table, removed code from is_prime calls prime
test from LibTomMath now
-- Added LTC_TEST define which when defined will enable the test vector routines [see mycrypt_custom.h]
-- Removed ampi.o from the depends cuz it ain't no not working in *nix with it [routines are in mpi.c now].
Mar 29th, 2003
v0.83 -- Optimized the ecc_mulmod, it's faster and takes less heap/stack space
-- Fixed a free memory error in ecc_mulmod and del_point which would try to free NULL
-- Fixed two serious bugs in rsa_decrypt_key and rsa_verify_hash that would allow a trivialy
buffer overflow.
-- Fixed a bug in the hmac testing code if you don't register all the hashes it won't return
errors now.
Mar 15th, 2003
v0.82 -- Manual updated
-- Added MSVC makefile [back, actually its written from scratch to work with NMAKE]
-- Change to HMAC helper functions API to avoid buffer overflow [source changes]
-- the rsa_encrypt_key was supposed to reject key sizes out of bounds ...
same fix to the rsa_sign_hash
-- Added code to ensure that that chaining mode code (cfb/ofb/ctr/cbc) have valid
structures when being called. E.g. the indexes to the pad/ivs are not out of bounds
-- Cleaned up the DES code and simplified the core desfunc routine.
-- Simplified one of the boolean functions in MD4
Jan 16th, 2003
v0.81 -- Merged in new makefile from Clay Culver and Mike Frysinger
-- Sped up the ECC mulmod() routine by making the word size adapt to the input. Saves a whopping 9 point
operations on 521-bit keys now (translates to about 8ms on my Athlon XP). I also now use barrett reduction
as much as possible. This sped the routine up quite a bit.
-- Fixed a huge flaw in ecc_verify_hash() where it would return CRYPT_OK on error... Now fixed.
-- Fixed up config.pl by fixing an invalid query and the file is saved in non-windows [e.g. not CR/LF] format
(fix due to Mika Boström)
-- Merged in LibTomMath for kicks
-- Changed the build process so that by default "mycrypt_custom.h" is included and provided
The makefile doesn't include any build options anymore
-- Removed the PS2 and VC makefiles.
Dec 16th, 2002
v0.80 -- Found a change I made to the MPI that is questionable. Not quite a bug but definately not desired. Had todo
with the digit shifting. In v0.79 I simply truncated without zeroing. It didn't cause problems during my
testing but I fixed it up none the less.
-- Optimized s_mp_mul_dig() from MPI to do a minimal number of passes.
-- Fixed in rsa_exptmod() where I was getting the size of the result. Basically it accomplishes the same thing
but the fixed code is more readable.
-- Fixed slight bug in dh_sign_hash() where the random "k" value was 1 byte shorter than it should have been. I've
also made the #define FAST_PK speed up signatures as well. Essentially FAST_PK tells the DH sub-system to
limit any private exponent to 256-bits. Note that when FAST_PK is defined does not make the library
binary or source incompatible with a copy of the library with it undefined.
-- Removed the DSA code. If you want fast diffie-hellman just define FAST_PK :-)
-- Updated dh_sign_hash()/dh_verify_hash() to export "unsigned" bignums. Saves two bytes but is not binary
compatible with the previous release... sorry! I've performed the same fix to the ecc code as well.
-- Fixed up the PK code to remove all use of mp_toraw() and mp_read_raw() [get all the changes out of the way now]
-- Fixed a bug in the DH code where it missed trapping a few errors if they occurred.
-- Fixed a slight "its-not-a-bug-but-could-be-done-better" bug in the next_prime() function. Essentially it was
testing to ensure that in the loop that searches for the next candidate that the step never grows beyond
65000. Should have been testing for MP_DIGIT_MAX
-- Spruced up the config.pl script. It now makes a header file "mycrypt_custom.h" which can be included *before*
you include mycrypt.h. This allows you to add libtomcrypt to a project without completely changing your make
system around. Note that you should use the makefile it writes to at least build the library initially.
-- Used splint to check alot of the code out. Tons of minor fixes and explicit casts added.
-- Also made all the internal functions of MPI are now static to avoid poluting the namespace
-- **Notice**: There are no planned future releases for at least a month from the this release date.
Dec 14th, 2002
v0.79 -- Change to PK code [binary and source]. I made it so you have to pass the buffer size to the *_decrypt_key and
*_verify_hash functions. This prevents malformed packets from performing buffer overflows. I've also trimmed
the packet header size [by 4 bytes].
-- Made the test program halt on the first error it occurs. Also made it trap more errors than before.
-- Wrote the first chapter of my new book [DRAFT!], not in this package but check my website!
-- Included a perl script "config.pl" that will make "makefile.out" according to the users needs.
-- Added shell script to look for latest release
-- Merge DH and ECC key defines from mycrypt_cfg.h into the makefiles
-- updated the makefile to use BSD friendly archiving invokations
-- Changed the DH and ECC code to use base64 static key settings [e.g. the primes]. Dropped the code size by 3KB
and is ever-so-slightly faster than before.
-- added "mp_shrink" function to shrink the size of bignums. Specially useful for PK code :-)
-- Added new exptmod function that calculates a^b mod c with fewer multiplies then before [~20% for crypto
sized numbers]. Also added a "low mem" variant that doesn't use more than 20KB [upto 4096 bit nums] of
heap todo the calculation. Both are #define'able controlled
-- Added XREALLOC macro to provide realloc() functionality.
-- Added fix where in rsa_import() if you imported a public key or a non-optimized key it would free the mp_int's
not being used.
-- Fixed potential bug in the ECC code. Only would occur on platforms where char is not eight bits [which isn't
often!]
-- Fixed up the ECC point multiplication, its about 15% faster now
-- While I was at it [since the lib isn't binary backwards compatible anyways] I've fixed the PK export routines
so they export as "unsigned" types saving 1 byte per bignum outputted. Not a lot but heck why not.
Nov 28th, 2002
v0.78 -- Made the default ARGCHK macro a function call instead which reduced the code size from 264KB to 239KB.
-- Fixed a bug in the XTEA keysize function which called ARGCHK incorrectly.
-- Added Noekeon block cipher at 2,800 bytes of object code and 345Mbit/sec it is a welcome addition.
-- Made the KR code check if the other PK systems are included [provides error when building otherwise].
-- Made "aes" an alias for Rijndael via a pre-processor macro. Now you can use "aes_ecb_encrypt", etc... :-)
Thanks to Jean-Luc Cooke for the "buzzword conformance" suggestion.
-- Removed the old PK code entirely (e.g. rsa_sign, dh_encrypt). The *_sign_hash and *_encrypt_key functions
are all that is to remain.
-- **NOTE** Changed the PK *_import (including the keyring) routine to accept a "inlen" parameter. This fixes a
bug where improperly made key packets could result in reading passed the end of the buffer. This means
the code is no longer source compatible but still binary compatible.
-- Fixed a few other minor bugs in the PK import code while I was at it.
Nov 26th, 2002
v0.77 -- Updated the XTEA code to use pre-computed keys. With optimizations for speed it achieves 222Mbit/sec
compared to the 121Mbit/sec before. It is 288 bytes bigger than before.
-- Cleaned up some of the ciphers and hashes (coding style, cosmetic changes)
-- Optimized AES slightly for 256-bit keys [only one if statement now, still two for 192-bit keys]
-- Removed most test cases from Blowfish, left three of them there. Makes it smaller and faster to test.
-- Changed the primality routines around. I now use 8 rounds of Rabin-Miller, I use 256 primes in the sieve
step and the "rand_prime" function uses a modified sieve that avoids alot of un-needed bignum work.
-- Fixed a bug in the ECC/DH signatures where the keys "setting" value was not checked for validity. This means
that a invalid value could have caused segfaults, etc...
-- **NOTE** Changed the way the ECC/DH export/import functions work. They are source but not binary compatible
with v0.76. Essentially insteading of exporting the setting index like before I export the key size. Now
if you ever re-configure which key settings are supported the lib will still be able to make use of your
keys.
-- Optimized Blowfish by inlining the round function, unrolling it for four rounds then using a for loop for the
rest. It achieves a rate of 425Mbit/sec with the new code compared to 314Mbit/sec before. The new blowfish
object file is 7,813 bytes compared to 8,663 before and is 850 bytes smaller. So the code is both smaller and
faster!
-- Optimized Twofish as well by inlining the round function. Gets ~400Mbit/sec compared to 280Mbit/sec before
and the code is only 78 bytes larger than the previous copy.
-- Removed SMALL_PRIME_TAB build option. I use the smaller table always.
-- Fixed some mistakes concerning prime generation in the manual.
-- [Note: sizes/speeds are for GCC 3.2 on an x86 Athlon XP @ 1.53Ghz]
Nov 25th, 2002
v0.76 -- Updated makefiles a bit more, use "-Os" instead of "-O2" to optimize for size. Got the lib
downto 265KB using GCC 3.2 on my x86 box.
-- Updated the SAFER+, Twofish and Rijndael test vector routine to use the table driven design.
-- Updated all other test vector routines to return as soon as an error is found
-- fixed a bug in the test program where errors in the hash test routines would not be reported
correctly. I found this by temporarily changing one of the bytes of the test vectors. All the
hashes check out [the demos/test.c would still have reported an error, just the wrong one].
Nov 24th, 2002
v0.75 -- Fixed a flaw in hash_filehandle, it should ARGCHK that the filehandle is not NULL
-- Fixed a bug where in hash_file if the call to hash_filehandle failed the open file would
not be closed.
-- Added more strict rules to build process, starting to weed out "oh this works in GCC" style code
In the next release "-Wconversion" will be enabled which will deal with all implicit casts.
Nov 22nd, 2002 [later in the day]
v0.74 -- Wrote a small variant of SAFER+ which shaved 50KB off the size of the library on x86 platforms
-- Wrote a build option to remove the PK packet functions [keeps the encrypt_key/sign_hash functions]
-- Wrote a small variant of Rijndael (trimmed 13KB)
-- Trimmed the TIGER/192 hash function a bit
-- Overall the entire lib compiled is 295KB [down from 400KB before]
-- Fixed a few minor oversights in the MSVC makefile
Nov 22nd, 2002
v0.73 -- Fixed bug in RC4 code where it could only use 255 byte keys.
-- Fixed bug in yarrow code where it would allow cast5 or md2 to be used with it...
-- Removed the ecc compress/expand points from the global scope. Reduces namespace polution
-- Fixed bug where if you used the SPRNG you couldn't pass NULL as your prng_state which you should be
able todo since the SPRNG has no state...
-- Corrected some oversights in the manual and the examples...
-- By default the GF(2^W) math library is excluded from the build. The source is maintained because I wrote it
and like it :-). This way the built library is a tad smaller
-- the MSVC makefile will now build for a SPACE optimized library rather than TIME optimized.
Nov 21th, 2002
v0.72 -- Fixed bug in the prime testing. In the Miller-Rabin test I was raising the base to "N-1" not "r".
The math still worked out fine because in effect it was performing a Fermat test. Tested the new code and it
works properly
-- Fixed some of the code where it was still using the old error syntax
-- Sped up the RSA decrypt/sign routines
-- Optimized the ecc_shared_secret routine to not use so much stack
-- Fixed up the makefile to make releases where the version # is in the file name and directory it will unzip
to
Nov 19th, 2002
v0.71 -- HELP TOM. I need tuition for the January semester. Now I don't want to force donations [nor will I ever]
but I really need the help! See my website http://tom.iahu.ca/help_tom.html for more details. Please help
if you can!
--------------------------------------------------------------------------------------------------------------
-- Officially the library is no longer supported in GCC 3.2 in windows [cygwin].
In windows you can either use GCC 2.95.3 or try your luck with 3.2 It seems that
"-fomit-frame-pointer" is broken in the windows build [but not the linux x86 build???]
If you simply must use 3.2 then I suggest you limit the optimizations to simply "-O2"
-- Started new error handling API. Similar to the previous except there are more error codes than just
CRYPT_ERROR
-- Added my implementation of the MD2 hash function [despite the errors in the RFC I managed to get it right!]
-- Merged in more changes from Sky Schulz. I have to make mention here that he has been a tremendous help in
getting me motivated to make some much needed updates to the library!
-- Fixed one of the many mistakes in the manual as pointed out by Daniel Richards
-- Fixed a bug in the RC4 code [wasn't setting up the key correctly]
-- Added my implementation of the CAST5 [aka CAST-128] block cipher (conforms...)
-- Fixed numerous bugs in the PK code. Essentially I was "freeing" keys when the import failed. This is neither
required nor a good a idea [double free].
-- Tom needs a job.
-- Fixed up the test harness as requested by Sky Schulz. Also modifed the timing routines to run for X seconds
and count # of ops performed. This is more suitable than say encrypting 10 million blocks on a slow processor
where it could take minutes!
-- Modified test programs hashsum/encrypt to use the new algorithms and error handling syntax
-- Removed the PKCS code since it was incomplete. In the future I plan on writing a "add-on" library that
provides PKCS support...
-- updated the config system so the #defines are in the makefiles instead of mycrypt_cfg.h
-- Willing to work on an hourly basis for 15$ CDN per hour.
-- updated the test program to not test ciphers not included
-- updated the makefile to make "rsa_sys.c" a dependency of rsa.o [helps develop the code...]
-- fixed numerous failures to detect buffer overflows [minor] in the PK code.
-- fixed the safer [64-bit block version] test routines which didn't check the returns of the setup
function
-- check out my CV at http://tom.iahu.ca/cv.html
-- removed the GBA makefile and code from demos/test.c [not a particularly useful demo...]
-- merged in rudimentary [for testing] PS2 RNG from Sky Schulz
-- merged in PS2 timer code [only shell included due to NDA reasons...]
-- updated HMAC code to return errors where possible
-- Thanks go to Sky Schulz who bought me a RegCode for TextPad [the official editor of libtomcrypt]
Nov 12th, 2002
v0.70 -- Updated so you can swap out the default malloc/calloc/free routines at build time with others. (Sky Schulz)
-- Sky Schulz contributed some code towards autodetecting the PS2 in mycrypt_cfg.h
-- Added PS2 makefile contributed by Sky Schulz [see a pattern forming?]
-- Added ability to have no FILE I/O functions at all (see makefile), Sky Schulz....
-- Added support for substituting out the clock() function (Sky Schulz)
-- Fixed up makefile to include new headers in the HEADERS variable
-- Removed "coin.c" as its not really useful anyways
-- Removed many "debug" printfs that would show up on failures. Basically I wanted to ensure the only output
would be from the developer themselves.
-- Added "rc4.c" a RC4 implementation with a PRNG interface. Since RC4 isn't a block cipher it wouldn't work
too well as a block cipher.
-- Fixed ARGCHK macro usage when ARGTYPE=1 throughout the code
-- updated makefile to make subdirectory properly (Sku Schulz)
-- Started towards new API setup. Instead of checking for "== CRYPT_ERROR" you should check "!= CRYPT_OK"
In future releases functions will return things other than CRYPT_ERROR on error to give more useful
thread safe error reporting. The manual will be updated to reflect this. For this release all
errors are returned as CRYPT_ERROR (except as noted) but in future releases this will change.
-- Removed the zlib branch since its not really required anyways. Makes the package smaller
Nov 11th, 2002
v0.69 -- Added ARGCHK (see mycrypt_argchk.h) "arguement checking" to all functions that accept pointers
-- Note I forgot to change the CRYPT version tag in v0.68... fixed now.
Nov 8th, 2002
v0.68 -- Fixed flaw in kr_import/kr_export that wasted 4 bytes. Source but not binary compatible with v0.67
-- Fixed bug in kr_find_name that used memcmp to match strings. Uses strncmp now.
-- kr_clear now sets the pointer to NULL to facilate debugging [e.g. using the keyring after clearing]
-- static functions in _write/_read in keyring.c now check the return of ctr_encrypt/ctr_decrypt.
-- Updated blowfish/rc2/rc5/rc6 keysize() function to not reject keys larger than the biggest key the
respective ciphers can use.
-- Fixed a bug in hashsum demo that would report the hash for files that don't exist!
Oct 16th, 2002
v0.67 -- Moved the function prototypes into files mycrypt_*.h. To "install" the lib just copy all the
header files "*.h" from the base of this project into your global include path.
-- Made the OFB/CFB/CTR functions use "unsigned long" for the length instead of "int"
-- Added keyring support for the PK functions
-- ***API CHANGE*** changed the ecc_make_key and dh_make_key to act more like rsa_make_key. Basically
move the first argument to the next to last.
-- Fixed bug in dh_test() that wouldn't test the primality of the order of the sub-group
-- replaced the primes in the DH code with new ones that are larger than the size they are
associated with. That is a 1024-bit DH key will have a 1025-bit prime as the modulus
-- cleaned up all the PK code, changed a bit of the API around [not source compatible with v0.66]
-- major editing of the manual, started Docer program
-- added 160 and 224 bit key settings for ECC. This makes the DH and ECC binary wise incompatible with v0.66
-- Added an additional check for memory errors in is_prime() and cleaned up prime.c a bit
-- Removed ID_TAG from all files [meh, not a big fan...]
-- Removed unused variable from yarrow state and made AES/SHA256 the default cipher/hash combo
-- Fixed a bug in the Yarrow code that called prng_is_valid instead of cipher_is_valid from yarrow_start()
-- The ECB/CBC/OFB/CFB/CTR wrappers now check that the cipher is valid in the encrypt/decrypt calls
Returns int now instead of void.
Sept 24th, 2002
v0.66 -- Updated the /demos/test.c program to time the hashes correctly. Also it uses the yarrow PRNG for all of the
tests meaning its possible to run on RNG less platforms
-- Updated the /demos/hashsum.c program to hash from the standard input
-- Updated the RSA code to make keys a bit quicker [update by Wayne Scott] by not making both primes at the same
time.
-- Dan Kaminsky suggested some cleanups for the code and the MPI config
Code ships in unix LF format by default now too... will still build in MSVC and all... but if you want
to read the stuff you'll have to convert it
-- Changes to the manual to reflect new API [e.g. hash_memory/file have v0.65 prototypes]and some typos fixed
Sept 20th, 2002
v0.65 -- Wayne Scott (wscott@bitmover.com) made a few of suggestions to improve the library. Most
importantly he pointed out the math lib is not really required. He's also tested the lib on 18
different platforms. According to him with only a few troubles [lack of /dev/random, etc] the
library worked as it was supposed to. You can find the list at
http://www.bitkeeper.com/Products.BitKeeper.Platforms.html
-- Updated the hash_file and hash_memory functions to keep track of the size of the output
-- Wayne Scott updated the demos/test.c file to use the SPRNG less and Yarrow more
-- Modified the mycrypt_cfg.h to autodetect x86-32 machines
Sept 19th, 2002
v0.64 -- wrote makefile for the GBA device [and hacked the demos/test.c file to support it conditionally]
-- Fixed error in PK (e.g. ECC, RSA, DH) import functions where I was clobbering the packet error messages
-- fixed more typos in the manual
-- removed all unused variables from the core library (ignore the ID_TAG stuff)
-- added "const char *crypt_build_settings" string which is a build time constant that gives a listing
of all the build time options. Useful for debugging since you can send that to me and I will know what
exactly you had set for the mycrypt_cfg.h file.
-- Added control over endianess. Out of the box it defaults to endianess neutral but you can trivially
configure the library for your platform. Using this I boosted RC5 from 660Mbit/sec to 785Mbit/sec on my
Athlon box. See "mycrypt_cfg.h" for more information.
Sept 11th, 2002
v0.63 -- Made hashsum demo output like the original md5sum program
-- Made additions to the examples in the manual (fixed them up a bunch)
-- Merged in the base64 code from Wayne Scott (wscott@bitmover.com)
Aug 29th, 2002
v0.62 -- Added the CLEAN_STACK functionality to several of the hashes I forgot to update.
Aug 9th, 2002
v0.61 -- Fixed a bug in the DES code [oops I read something wrong].
Aug 8th, 2002
v0.60 -- Merged in DES code [and wrote 3DES-EDE code based on it] from Dobes V.
Aug 7th, 2002
v0.59 -- Fixed a "unsigned long long" bug that caused v0.58 not to build in MSVC.
-- Cleaned up a little in the makefile
-- added code that times the hash functions too in the test program
Aug 3rd, 2002
v0.58 -- Added more stack cleaning conditionals throughout the code.
-- corrected some CLEAR_STACK conditionals... should have been CLEAN_STACK
-- Simplified the RSA, DH and ECC encrypt() routines where they use CTR to encode the message
now they only make one call to ctr_encrypt()/ctr_decrypt().
Aug 2nd, 2002
v0.57 -- Fixed a few errors messages in the SAFER code to actually report the correct cipher name.
-- rsa_encrypt() uses the "keysize()" method of the cipher being used to more accurately pick a
key size. By default rsa_encrypt() will choose to use a 256-bit key but the cipher can turn that
down if required.
-- The rsa_exptmod() function will now more reliably detect invalid inputs (e.g. greater than the modulus).
-- The padding method for RSA is more clearly documented. Namely if you want to encrypt/sign something of length
N then your modulus must be of length 1+3N. So to sign a message with say SHA-384 [48 bytes] you need a
145 byte (1160 bits) modulus. This is all in the manual now.
-- Added build option CLEAN_STACK which will allow you to choose whether you want to clean the stack or not after every
cipher/hash call
-- Sped up the hash "process()" functions by not copying one byte at a time.
++ (added just after I uploaded...)
MD4 process() now handles input buffers > 64 bytes
Aug 1st, 2002
v0.56 -- Cleaned up the comments in the Blowfish code.
-- Oh yeah, in v0.55 I made all of the descriptor elements constant. I just forgot to mention it.
-- fixed a couple of places where descriptor indexes were tested wrong. Not a huge bug but now its harder
to mess up.
-- Added the SAFER [64-bit block] ciphers K64, SK64, K128 and SK128 to the library.
-- Added the RC2 block cipher to the library.
-- Changed the SAFER define for the SAFER+ cipher to SAFERP so that the new SAFER [64-bit] ciphers
can use them with less confusion.
July 29th, 2002
v0.55 -- My god stupid Blowfish has yet again been fixed. I swear I hate that cipher. Next bug in it and boom its out of the
library. Use AES or something else cuz I really hate Blowfish at this stage....
-- Partial PKCS support [hint DONT USE IT YET CUZ ITS UNTESTED!]
July 19th, 2002
v0.54 -- Blowfish now conforms to known test vectors. Silly bad coding tom!
-- RC5/RC6/Serpent all have more test vectors now [and they seemed to have been working before]
July 18th, 2002
v0.53 -- Added more test vectors to the blowfish code just for kicks [and they are const now too :-)]
-- added prng/hash/cipher is_valid functions and used them in all of the PK code so you can't enter the code
with an invalid index ever now.
-- Simplified the Yarrow code once again :-)
July 12th, 2002
v0.52 -- Fixed a bug in MD4 where the hash descriptor ID was the same as SHA-512. Now MD4 will work with
all the routines...
-- Fixed the comments in SHA-512 to be a bit more meaningful
-- In md4 I made the PADDING array const [again to store it in ROM]
-- in hash_file I switched the constant "512" to "sizeof(buf)" to be a bit safer
-- in SHA-1's test routine I fixed the string literal to say SHA-1 not sha1
-- Fixed a logical error in the CTR code which would make it skip the first IV value. This means
the CTR code from v0.52 will be incompatible [binary wise] with previous releases but it makes more
sense this way.
-- Added {} braces for as many if/for/blocks of code I could find. My rule is that every for/if/while/do block
must have {} braces around it.
-- made the rounds table in saferp_setup const [again for the ROM think about the ROM!]
-- fixed RC5 since it no longer requires rc5 to be registered in the lib. It used to since the descriptors used to
be part of the table...
-- the packet.c code now makes crypt_error literal string errors when an error occurs
-- cleaned up the SAFER+ key schedule to be a bit easier to read.
-- fixed a huge bug in Twofish with the TWOFISH_SMALL define. Because I clean the stack now I had
changed the "g_func()" to be called indirectly. I forgot to actually return the return of the Twofish
g_func() function which caused it not to work... [does now :-)]
July 11th, 2002
v0.51 -- Fixed a bug in SHA512/384 code for multi-block messages.
-- Added more test vectors to the SHA384/512 and TIGER hash functions
-- cleaned up the hash done routines to make more sense
July 10th, 2002
v0.50 -- Fixed yarrow.c so that the cipher/hash used would be registered. Also fixed
a bug where the SAFER+ name was "safer" but should have been "safer+".
-- Added an element to the hash descriptors that gives the size of a block [sent into the compressor]
-- Cleaned up the support for HMAC's
-- Cleaned up the test vector routines to make the test vector data const. This means on some platforms it will be
placed in ROM not RAM now.
-- Added MD4 code submited by Dobes Vandermeer (dobes@smartt.com)
-- Added "burn_stack" function [idea taken from another source of crypto code]. The idea is if a function has
alot of variables it will clean up better. Functions like the ecb serpent and twofish code will now have their
stacks cleaned and the rest of the code is getting much more straightforward.
-- Added a hashing demo by Daniel Richards (kyhwana@world-net.co.nz)
-- I (Tom) modified some of the test vector routines to use more vectors ala Dobes style.
For example, the MD5/SHA1 code now uses all of the test vectors from the RFC/FIPS spec.
-- Fixed the register/unregister functions to properly report errors in crypt_error
-- Correctly updated yarrow code to remove a few unused variables.
-- Updated manual to fix a few erroneous examples.
-- Added section on Hash based Message Authentication Codes (HMAC) to the manual
June 19th, 2002
v0.46 -- Added in HMAC code from Dobes Vandermeer (dobes@smartt.com)
June 8th, 2002
v0.45 -- Fixed bug in rc5.c where if you called rc5_setup() before registering RC5 it would cause
undefined behaviour.
-- Fixed mycrypt_cfg.h to eliminate the 224 bit ECC key.
-- made the "default" makefile target have depends on mycrypt.h and mycrypt_cfg.h
Apr 4th, 2002
v0.44 -- Fixed bug in ecc.c::new_point() where if the initial malloc fails it would not catch it.
Mar 22nd, 2002
v0.43 -- Changed the ZLIB code over to the 1.1.4 code base to avoid the "double free" bug.
-- Updated the GCC makefile not to use -O3 or -funroll-loops
-- Version tag in mycrypt.h has been updated :-)
Mar 10th, 2002
v0.42 -- The RNG code can now use /dev/urandom before trying /dev/random (J. Klapste)
Mar 3rd, 2002
v0.41 -- Added support to link and use ciphers at compile time. This can greatly reduce the code size!
-- Added a demo to show off how small an application can get... 46kb!
-- Disastry pointed out that Blowfish is supposed to be high endian.
-- Made registry code for the PRNGs as well [now the smallest useable link is 43kb]
Feb 11th, 2002
v0.40 -- RSA signatures use [and check for] fixed padding scheme.
-- I'm developing in Linux now :-)
-- No more warnings from GCC 2.96
Feb 5th, 2002
v0.39 -- Updated the XTEA code to work in accordance with the XTEA design
January 24th, 2002
v0.38 -- CFB and OFB modes can now handle blocks of variable size like the CTR code
-- Wrote a wrapper around the memory compress functions in Zlib that act like the functions
in the rest of my crypto lib
January 23rd, 2002
v0.37 -- Added support code so that if a hash size and key size for a cipher don't match up they will
use the next lower key supported. (mainly for the PK code). So you can now use SHA-1 with
Twofish, etc...
-- Added more options for Twofish. You can now tell it to use precomputed sboxes and MDS multiplications
This will speed up the TWOFISH_SMALL implementation by increasing the code size by 1024 bytes.
-- Fixed a bug in prime.c that would not use the correct table if you undefined SMALL_PRIME_TAB
-- Fixed all of the PK packet code to use the same header format [see packet.c]. This makes the PK code
binary wise incompatible with previous releases while the API has not changed at all.
January 22nd, 2002
v0.36 -- Corrections to the manual
-- Made a modification to Twofish which lets you build a "small ram" variant. It requires
about 190 bytes of ram for the key storage compared to the 4,200 bytes the normal
variant requires.
-- Reduced the stack space used in all of the PK routines.
January 19th, 2002
v0.35 -- If you removed the first hash or cipher from the library it wouldn't return an error if
you used an ID=0 [i.e blowfish or sha256] in any routine. Now it checks for that and will
return an error like it should
-- Merged in new routines from Clay Culver. These routines are for the PK code so you can easily
encode a symmetric key for multiple recipients.
-- Made the ecc and DH make_key() routines make secret keys of the same size as the keysize listed.
Originally I wanted to ensure that the keys were smaller than the order of the field used
However, the bias is so insignifcant using full sizes. For example, with a ECC-192 key the order
is about 2^191.99, so instead I rounded down and used a 184-bit secret key. Now I simply use a full 192-bit
key the code will work just the same except that some 192-bit keys will be duplicates which is not a big
deal since 1/2^192 is a very small bias!
-- Made the configuration a bit simpler and more exacting. You can for example now select which DH or ECC
key settings you wish to support without including the data for all other key settings. I put the #defines
in a new file called "mycrypt_cfg.h"
-- Configured "mpi-config.h" so its a bit more conservative with the memory required and code space used
-- Jason Klapste submitted bug fixes to the yarrow, hash and various other issues. The yarrow code will now
use what ever remaining hash/cipher combo is left [after you #undef them] at build time. He also suggested
a fix to remove unused structures from the symmetric_key and hash_state unions.
-- Made the CTR code handle variable length blocks better. It will buffer the encryption pad so you can
encrypt messages any size block at a time.
-- Simplified the yarrow code to take advantage of the new CTR code.
-- Added a 4096-bit DH key setting. That took me about 36 hours to find!
-- Changed the base64 routines to use a real base64 encoding scheme.
-- Added in DH and ECC "encrypt_key()" functions. They are still rather "beta"ish.
-- Added **Twofish** to the list of ciphers!
January 18th, 2002
v0.34 -- Added "sha512" to the list of hashes. Produces a 512-bit message digest. Note that with the current
padding with the rsa_sign() function you cannot use sha512 with a key less than 1536 bits for signatures.
-- Cleaned up the other hash functions to use the LOAD and STORE macros...
January 17th, 2002
v0.33 -- Made the lower limit on keysizes for RSA 1024 bits again because I realized that 768 bit keys wouldn't
work with the padding scheme and large symmetric keys.
-- Added information concerning the Zlib license to the manual
-- Added a 3072-bit key setting for the DH code.
-- Made the "find_xyz()" routines take "const char *" as per Clay Culver's suggestion.
-- Fixed an embarassing typo in the manual concerning the hashes. Thank's Clay for finding it!
-- Fixed rand_prime() so that it makes primes bigger than the setting you give. For example,
if you want a 1024-bit prime it would make a 1023-bit one. Now it ensures that the prime
it makes is always greater than 2^(8n) (n == bytes in prime). This doesn't have a huge
impact on security but I corrected it just the same.
-- Fixed the CTR routine to work on platforms where char != 8-bits
-- Fixed sha1/sha256/md5/blowfish to not assume "unsigned long == 32-bits", Basically any operation with carries
I "AND" with 0xFFFFFFFF. That forces only the lower 32-bits to have information in it. On x86 platforms
most compilers optimize out the AND operation since its a nop.
January 16th, 2002
v0.32 -- Made Rijndael's setup function fully static so it is thread safe
-- Svante Seleborg suggested a cosmetic style fixup for aes.c,
basically to remove some of the #defines to clean it up
-- Made the PK routines not export the ASCII version of the names of ciphers/hashes which makes
the PK message formats *incompatible* with previous releases.
-- Merge in Zlib :-)
January 15th, 2002
v0.31 -- The RSA routines can now use CRT to speed up decryption/signatures. The routines are backwards
compatible with previous releases.
-- Fixed another bug that Svante Seleborg found. Basically you could buffer-overrun the
rsa_exptmod() function itself if you're not careful. That's fixed now. Fixed another bug in
rsa_exptmod() where if it knows the buffer you passed is too small it wouldn't free all used
memory.
-- improved the readability of the PK import/export functions
-- Added a fix to RSA.C by Clay Culver
-- Changed the CONST64 macro for MSVC to use the "unsigned __int64" type, e.g. "ui64" instead of "i64".
January 14th, 2002
v0.30 -- Major change to the Yarrow PRNG code, fixed a bug that Eugene Starokoltsev found.
Basically if you added entropy to the pool in small increments it could in fact
cancel out. Now I hash the pool with the new data which is way smarter.
January 12th, 2002
v0.29 -- Added MPI code written by Svante Seleborg to the library. This will make the PK code much
easier to follow and debug. Actually I've already fixed a memory leak in dh_shared_secret().
-- Memory leaks found and correct in all three PK routines. The leaks would occur when a bignum
operation fails so it wouldn't normally turn up in the course of a program
-- Fixed bugs in dh_key_size and ecc_key_size which would return garbage for invalid key idx'es
January 11th, 2002
v0.28 -- Cleaned up some code so that it doesn't assume "char == 8bits". Mainly SAFER+ has been
changed.
-- ***HUGE*** changes in the PK code. I check all return values in the bignum code so if there
are errors [insufficient memory, etc..] it will be reported. This makes the code fairly more
robust and likely to catch any errors.
-- Updated the is_prime() function to use a new prototype [it can return errors now] and it also
does trial divisions against more primes before the Rabin Miller steps
-- Added OFB, CFB and ECB generic wrappers for the symmetric ciphers to round out the implementations.
-- Added Xtea to the list of ciphers, to the best of my ability I have verified this implementation.
I should note that there is not alot of concrete information about the cipher. "Ansi C" versions
I found did not address endianess and were not even portable!. This code is portable and to the
best of my knowledge implements the Xtea algorithm as per the [short] X-Tea paper.
-- Reformated the manual to include the **FULL** source code optimized to be pritable.
January 9th, 2002
v0.27 -- Changed the char constants to numerical values. It is backwards compatible and should work on
platforms where 'd' != 100 [for example].
-- Made a change to rand_prime() which takes the input length as a signed type so you can pass
a negative len to get a "3 mod 4" style prime... oops
-- changed the MSVC makefile to build with a warning level of three, no warnings!
January 8th, 2002
v0.26 -- updated SHA-256 to use ROR() for a rotate so 64-bit machines won't corrupt
the output
-- Changed #include <> to #include "" for local .h files as per Richard Heathfields' suggestions.
-- Fixed bug in MPI [well bug in MSVC] that compiled code incorrectly in mp_set_int()
I added a work around that catches the error and continues normally.
January 8th, 2002
v0.25 -- Added a stupid define so MSVC 6.00 can build the library.
-- Big thanks to sci.crypt and "Ajay K. Agrawal" for helping me port this to MSVC
January 7th, 2002
v0.24 -- Sped up Blowfish by unrolling and removing the swaps.
-- Made the code comply with more traditional ANSI C standards
Should compile with MSVC with less errors
-- moved the demos and documentation into their own directories
so you can easily build the library with other tool chains
by compiling the files in the root
-- converted functions with length of outputs to use
"unsigned long" so 16-bit platforms will like this library more.
January 5th, 2002
v0.23 -- Fixed a small error in the MPI config it should build fine anywhere.
January 4th, 2002
v0.22 -- faster gf_mul() code
-- gf_shl() and gf_shr() are safe on 64-bit platforms now
-- Fixed an error in the hashes that Brian Gladman found.
Basically if the message has exactly 56 bytes left to be
compressed I handled them incorrectly.
January 4th, 2002
v0.21 -- sped up the ECC code by removing redundant divisions in the
point add and double routines. I also extract the bits more
efficiently in "ecc_mulmod()" now.
-- sped up [and documented] the rand_prime() function. Now it just
makes a random integer and increments by two until a prime is found
This is faster since it doesn't require alot of calls to the PRNG and
it doesn't require loading huge integers over and over. rand_prime()
can also make primes congruent to 3 mod 4 [i.e for a blum integer]
-- added a gf_sqrt() function that finds square roots in a GF(2^w) field
-- fixed a bug in gf_div() that would return the wrong results if the divisor had a greator
divisor than the dividend.
January 4th, 2002
v0.20 -- Added the fixed MPI back in so RSA and DH are much faster again
v0.19 -- Updated the manual to reflect the fact that Brian Gladman wrote the AES and Serpent code.
-- DH, ECC and RSA signature/decryption functions check if the key is private
-- new DH signature/verification code works just like the RSA/ECC versions
January 3rd, 2002
v0.18 -- Added way more comments to each .C file
-- fixed a bug in cbc_decrypt(pt, ct, key) where pt == ct [i.e same buffer]
-- fixed RC5 so it reads the default rounds out of the cipher_descriptor table
-- cleaned up ecc_export()
-- Cleaned up dh_import() and ecc_import() which also perform more
error checking now
-- Fixed a serious flaw in rsa_import() with private keys.
January 2nd, 2002
v0.17 -- Fixed a bug in the random prime generator that fixes the wrong bits to one
-- ECC and DH code verify that the moduli and orders are in fact prime. That
slows down the test routines alot but what are you gonna do?
-- Fixed a huge bug in the mp_exptmod() function which incorrectly calculates g^x mod p for some
values of p. I replaced it with a slow function. Once the author of MPI fixes his faster routine
I will switch back.
January 1st, 2002 [whoa new year!]
v0.16 -- Improved GF division code that is faster.
-- documented the GF code
December 31st, 2001
v0.15 -- A 1792-bit and 2048-bit DH setting was added. Took me all night to
find a 1792 and 2048-bit strong prime but what the heck
-- Library now has polynomial-basis GF(2^w) routines I wrote myself. Can be used to perform
ECC over GF(2^w) later on....
-- Fixed a bug with the defines that allows it to build in windows
December 30th, 2001
v0.14 -- Fixed the xxx_encrypt() packet routines to make an IV of appropriate size
for the cipher used. It was defaulting to making a 256-bit IV...
-- base64_encode() now appends a NULL byte, um "duh" stupid mistake now fixed...
-- spell checked the manual again... :-)
December 30th, 2001
v0.13 -- Switching back to older copy of MPI since it works! arrg..
-- Added sign/verify functions for ECC
-- all signature verification routines default to invalid signatures.
-- Changed all calls to memset to zeromem. Fixed up some buffer problems
in other routines. All calls to zeromem let the compiler determine the size
of the data to wipe.
December 29th, 2001
v0.12 -- Imported a new version of MPI [the bignum library] that should
be a bit more stable [if you want to write your own bignum
routines with the library that is...]
-- Manual has way more info
-- hash_file() clears stack now [like it should]
-- The artificial cap on the hash input size of 2^32 bits has been
removed. Basically I was too lazy todo 64-bit math before
[don't ask why... I can't remember]. Anyways the hashes
support the size of 2^64 bits [if you ever use that many bits in a message
that's just wierd...]
-- The hashes now wipe the "hash_state" after the digest is computed. This helps
prevent the internal state of the hash being leaked accidently [i.e stack problems]
December 29th, 2001
v0.11 -- Made #define's so you can trim the library down by removing
ciphers, hashs, modes of operation, prngs, and even PK algorithms
For example, the library with rijndael+ctr+sha1+ECC is 91KB compared
to the 246kb the full library takes.
-- Added ECC packet routines for encrypt/decrypt/sign/verify much akin to
the RSA packet routines.
-- ECC now compresses the public key, a ECC-192 public key takes 33 bytes
for example....
December 28th, 2001
v0.10 -- going to restart the manual from scratch to make it more
clear and professional
-- Added ECC over Z/pZ. Basically provides as much as DH
except its faster since the numbers are smaller. For example,
A comparable 256-bit ECC key provides as much security as expected
from a DH key over 1024-bits.
-- Cleaned up the DH code to not export the symbol "sets[]"
-- Fixed a bug in the DH code that would not make the correct size
random string if you made the key short. For instance if you wanted
a 512-bit DH key it would make a 768-bit one but only make up 512-bits
for the exponent... now it makes the full 768 bits [or whatever the case
is]
-- Fixed another ***SERIOUS*** bug in the DH code that would default to 768-bit
keys by mistake.
December 25th, 2001
v0.09 -- Includes a demo program called file_crypt which shows off
how to use the library to make a command line tool which
allows the user to encode/decode a file with any
hash (on the passphrase) and cipher in CTR mode.
-- Switched everything to use typedef's now to clear up the code.
-- Added AES (128/192 and 256 bit key modes)
December 24th, 2001
v0.08 -- fixed a typo in the manual. MPI stores its bignums in
BIG endian not little.
-- Started adding a RNG to the library. Right now it tries
to open /dev/random and if that fails it uses either the
MS CSP or the clock drift RNG. It also allows callbacks
since the drift RNG is slow (about 3.5 bytes/sec)
-- the RNG can also automatically setup a PRNG as well now
v0.07 -- Added basic DH routines sufficient to
negotiate shared secrets
[see the manual for a complete example!]
-- Fixed rsa_import to detect when the input
could be corrupt.
-- added more to the manual.
December 22nd, 2001
v0.06 -- Fixed some formatting errors in
the hash functions [just source code cleaning]
-- Fixed a typo in the error message for sha256 :-)
-- Fixed an error in base64_encode() that
would fail to catch all buffer overruns
-- Test program times the RSA and symmetric cipher
routines for kicks...
-- Added the "const" modifier to alot of routines to
clear up the purpose of each function.
-- Changed the name of the library to "TomCrypt"
following a suggestion from a sci.crypt reader....
v0.05 -- Fixed the ROL/ROR macro to be safe on platforms
where unsigned long is not 32-bits
-- I have added a bit more to the documentation
manual "crypt.pdf" provided.
-- I have added a makefile for LCC-Win32. It should be
easy to port to other LCC platforms by changing a few lines.
-- Ran a spell checker over the manual.
-- Changed the header and library from "crypt" to "mycrypt" to not
clash with the *nix package "crypt".
v0.04 -- Fixed a bug in the RC5,RC6,Blowfish key schedules
where if the key was not a multiple of 4 bytes it would
not get loaded correctly.
December 21st, 2001
v0.03 -- Added Serpent to the list of ciphers.
v0.02 -- Changed RC5 to only allow 12 to 24 rounds
-- Added more to the manual.
v0.01 -- We will call this the first version.

232
crypt.c Normal file
View File

@@ -0,0 +1,232 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
*
* LibTomCrypt is a library that provides various cryptographic
* algorithms in a highly modular and flexible manner.
*
* The library is free for all purposes without any express
* guarantee it works.
*
* Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org
*/
#include "mycrypt.h"
/* Dropbear doesn't need these
const char *crypt_build_settings =
"LibTomCrypt " SCRYPT "\n\n"
"Endianess: "
#if defined(ENDIAN_NEUTRAL)
"neutral\n"
#elif defined(ENDIAN_LITTLE)
"little"
#if defined(ENDIAN_32BITWORD)
" (32-bit words)\n"
#else
" (64-bit words)\n"
#endif
#elif defined(ENDIAN_BIG)
"big"
#if defined(ENDIAN_32BITWORD)
" (32-bit words)\n"
#else
" (64-bit words)\n"
#endif
#endif
"Clean stack: "
#if defined(CLEAN_STACK)
"enabled\n"
#else
"disabled\n"
#endif
"Ciphers built-in:\n"
#if defined(BLOWFISH)
" Blowfish\n"
#endif
#if defined(RC2)
" RC2\n"
#endif
#if defined(RC5)
" RC5\n"
#endif
#if defined(RC6)
" RC6\n"
#endif
#if defined(SAFERP)
" Safer+\n"
#endif
#if defined(SAFER)
" Safer\n"
#endif
#if defined(RIJNDAEL)
" Rijndael\n"
#endif
#if defined(XTEA)
" XTEA\n"
#endif
#if defined(TWOFISH)
" Twofish "
#if defined(TWOFISH_SMALL) && defined(TWOFISH_TABLES)
"(small, tables)\n"
#elif defined(TWOFISH_SMALL)
"(small)\n"
#elif defined(TWOFISH_TABLES)
"(tables)\n"
#else
"\n"
#endif
#endif
#if defined(DES)
" DES\n"
#endif
#if defined(CAST5)
" CAST5\n"
#endif
#if defined(NOEKEON)
" Noekeon\n"
#endif
#if defined(SKIPJACK)
" Skipjack\n"
#endif
"\nHashes built-in:\n"
#if defined(SHA512)
" SHA-512\n"
#endif
#if defined(SHA384)
" SHA-384\n"
#endif
#if defined(SHA256)
" SHA-256\n"
#endif
#if defined(SHA224)
" SHA-224\n"
#endif
#if defined(TIGER)
" TIGER\n"
#endif
#if defined(SHA1)
" SHA1\n"
#endif
#if defined(MD5)
" MD5\n"
#endif
#if defined(MD4)
" MD4\n"
#endif
#if defined(MD2)
" MD2\n"
#endif
#if defined(RIPEMD128)
" RIPEMD128\n"
#endif
#if defined(RIPEMD160)
" RIPEMD160\n"
#endif
"\nBlock Chaining Modes:\n"
#if defined(CFB)
" CFB\n"
#endif
#if defined(OFB)
" OFB\n"
#endif
#if defined(ECB)
" ECB\n"
#endif
#if defined(CBC)
" CBC\n"
#endif
#if defined(CTR)
" CTR\n"
#endif
"\nPRNG:\n"
#if defined(YARROW)
" Yarrow\n"
#endif
#if defined(SPRNG)
" SPRNG\n"
#endif
#if defined(RC4)
" RC4\n"
#endif
"\nPK Algs:\n"
#if defined(MRSA)
" RSA\n"
#endif
#if defined(MDH)
" DH\n"
#endif
#if defined(MECC)
" ECC\n"
#endif
#if defined(MDSA)
" DSA\n"
#endif
#if defined(KR)
" KR\n"
#endif
"\nCompiler:\n"
#if defined(WIN32)
" WIN32 platform detected.\n"
#endif
#if defined(__CYGWIN__)
" CYGWIN Detected.\n"
#endif
#if defined(__DJGPP__)
" DJGPP Detected.\n"
#endif
#if defined(_MSC_VER)
" MSVC compiler detected.\n"
#endif
#if defined(__GNUC__)
" GCC compiler detected.\n"
#endif
#if defined(INTEL_CC)
" Intel C Compiler detected.\n"
#endif
"\nVarious others: "
#if defined(GF)
" GF "
#endif
#if defined(BASE64)
" BASE64 "
#endif
#if defined(MPI)
" MPI "
#endif
#if defined(HMAC)
" HMAC "
#endif
#if defined(OMAC)
" OMAC "
#endif
#if defined(PMAC)
" PMAC "
#endif
#if defined(EAX_MODE)
" EAX_MODE "
#endif
#if defined(OCB_MODE)
" OCB_MODE "
#endif
#if defined(TRY_UNRANDOM_FIRST)
" TRY_UNRANDOM_FIRST "
#endif
#if defined(LTC_TEST)
" LTC_TEST "
#endif
#if defined(PKCS_1)
" PKCS#1 "
#endif
#if defined(PKCS_5)
" PKCS#5 "
#endif
"\n"
"\n\n\n"
;
*/

88
crypt.out Normal file
View File

@@ -0,0 +1,88 @@
\BOOKMARK [0][-]{chapter.1}{Introduction}{}
\BOOKMARK [1][-]{section.1.1}{What is the LibTomCrypt?}{chapter.1}
\BOOKMARK [2][-]{subsection.1.1.1}{What the library IS for?}{section.1.1}
\BOOKMARK [2][-]{subsection.1.1.2}{What the library IS NOT for?}{section.1.1}
\BOOKMARK [1][-]{section.1.2}{Why did I write it?}{chapter.1}
\BOOKMARK [2][-]{subsection.1.2.1}{Modular}{section.1.2}
\BOOKMARK [1][-]{section.1.3}{License}{chapter.1}
\BOOKMARK [1][-]{section.1.4}{Patent Disclosure}{chapter.1}
\BOOKMARK [1][-]{section.1.5}{Building the library}{chapter.1}
\BOOKMARK [1][-]{section.1.6}{Building against the library}{chapter.1}
\BOOKMARK [1][-]{section.1.7}{Thanks}{chapter.1}
\BOOKMARK [0][-]{chapter.2}{The Application Programming Interface \(API\)}{}
\BOOKMARK [1][-]{section.2.1}{Introduction}{chapter.2}
\BOOKMARK [1][-]{section.2.2}{Macros}{chapter.2}
\BOOKMARK [1][-]{section.2.3}{Functions with Variable Length Output}{chapter.2}
\BOOKMARK [1][-]{section.2.4}{Functions that need a PRNG}{chapter.2}
\BOOKMARK [1][-]{section.2.5}{Functions that use Arrays of Octets}{chapter.2}
\BOOKMARK [0][-]{chapter.3}{Symmetric Block Ciphers}{}
\BOOKMARK [1][-]{section.3.1}{Core Functions}{chapter.3}
\BOOKMARK [1][-]{section.3.2}{Key Sizes and Number of Rounds}{chapter.3}
\BOOKMARK [1][-]{section.3.3}{The Cipher Descriptors}{chapter.3}
\BOOKMARK [2][-]{subsection.3.3.1}{Notes}{section.3.3}
\BOOKMARK [1][-]{section.3.4}{Symmetric Modes of Operations}{chapter.3}
\BOOKMARK [2][-]{subsection.3.4.1}{Background}{section.3.4}
\BOOKMARK [2][-]{subsection.3.4.2}{Choice of Mode}{section.3.4}
\BOOKMARK [2][-]{subsection.3.4.3}{Implementation}{section.3.4}
\BOOKMARK [1][-]{section.3.5}{Encrypt and Authenticate Modes}{chapter.3}
\BOOKMARK [2][-]{subsection.3.5.1}{EAX Mode}{section.3.5}
\BOOKMARK [2][-]{subsection.3.5.2}{OCB Mode}{section.3.5}
\BOOKMARK [0][-]{chapter.4}{One-Way Cryptographic Hash Functions}{}
\BOOKMARK [1][-]{section.4.1}{Core Functions}{chapter.4}
\BOOKMARK [1][-]{section.4.2}{Hash Descriptors}{chapter.4}
\BOOKMARK [2][-]{subsection.4.2.1}{Notice}{section.4.2}
\BOOKMARK [0][-]{chapter.5}{Message Authentication Codes}{}
\BOOKMARK [1][-]{section.5.1}{HMAC Protocol}{chapter.5}
\BOOKMARK [1][-]{section.5.2}{OMAC Support}{chapter.5}
\BOOKMARK [1][-]{section.5.3}{PMAC Support}{chapter.5}
\BOOKMARK [0][-]{chapter.6}{Pseudo-Random Number Generators}{}
\BOOKMARK [1][-]{section.6.1}{Core Functions}{chapter.6}
\BOOKMARK [2][-]{subsection.6.1.1}{Remarks}{section.6.1}
\BOOKMARK [2][-]{subsection.6.1.2}{Example}{section.6.1}
\BOOKMARK [1][-]{section.6.2}{PRNG Descriptors}{chapter.6}
\BOOKMARK [1][-]{section.6.3}{The Secure RNG}{chapter.6}
\BOOKMARK [2][-]{subsection.6.3.1}{The Secure PRNG Interface}{section.6.3}
\BOOKMARK [0][-]{chapter.7}{RSA Routines}{}
\BOOKMARK [1][-]{section.7.1}{Background}{chapter.7}
\BOOKMARK [1][-]{section.7.2}{Core Functions}{chapter.7}
\BOOKMARK [1][-]{section.7.3}{Packet Routines}{chapter.7}
\BOOKMARK [1][-]{section.7.4}{Remarks}{chapter.7}
\BOOKMARK [0][-]{chapter.8}{Diffie-Hellman Key Exchange}{}
\BOOKMARK [1][-]{section.8.1}{Background}{chapter.8}
\BOOKMARK [1][-]{section.8.2}{Core Functions}{chapter.8}
\BOOKMARK [2][-]{subsection.8.2.1}{Remarks on Usage}{section.8.2}
\BOOKMARK [2][-]{subsection.8.2.2}{Remarks on The Snippet}{section.8.2}
\BOOKMARK [1][-]{section.8.3}{Other Diffie-Hellman Functions}{chapter.8}
\BOOKMARK [1][-]{section.8.4}{DH Packet}{chapter.8}
\BOOKMARK [0][-]{chapter.9}{Elliptic Curve Cryptography}{}
\BOOKMARK [1][-]{section.9.1}{Background}{chapter.9}
\BOOKMARK [1][-]{section.9.2}{Core Functions}{chapter.9}
\BOOKMARK [1][-]{section.9.3}{ECC Packet}{chapter.9}
\BOOKMARK [1][-]{section.9.4}{ECC Keysizes}{chapter.9}
\BOOKMARK [0][-]{chapter.10}{Digital Signature Algorithm}{}
\BOOKMARK [1][-]{section.10.1}{Introduction}{chapter.10}
\BOOKMARK [1][-]{section.10.2}{Key Generation}{chapter.10}
\BOOKMARK [1][-]{section.10.3}{Key Verification}{chapter.10}
\BOOKMARK [1][-]{section.10.4}{Signatures}{chapter.10}
\BOOKMARK [1][-]{section.10.5}{Import and Export}{chapter.10}
\BOOKMARK [0][-]{chapter.11}{Public Keyrings}{}
\BOOKMARK [1][-]{section.11.1}{Introduction}{chapter.11}
\BOOKMARK [1][-]{section.11.2}{The Keyring API}{chapter.11}
\BOOKMARK [0][-]{chapter.12}{GF\(2w\) Math Routines}{}
\BOOKMARK [0][-]{chapter.13}{Miscellaneous}{}
\BOOKMARK [1][-]{section.13.1}{Base64 Encoding and Decoding}{chapter.13}
\BOOKMARK [1][-]{section.13.2}{The Multiple Precision Integer Library \(MPI\)}{chapter.13}
\BOOKMARK [2][-]{subsection.13.2.1}{Binary Forms of ``mp\137int'' Variables}{section.13.2}
\BOOKMARK [2][-]{subsection.13.2.2}{Primality Testing}{section.13.2}
\BOOKMARK [0][-]{chapter.14}{Programming Guidelines}{}
\BOOKMARK [1][-]{section.14.1}{Secure Pseudo Random Number Generators}{chapter.14}
\BOOKMARK [1][-]{section.14.2}{Preventing Trivial Errors}{chapter.14}
\BOOKMARK [1][-]{section.14.3}{Registering Your Algorithms}{chapter.14}
\BOOKMARK [1][-]{section.14.4}{Key Sizes}{chapter.14}
\BOOKMARK [2][-]{subsection.14.4.1}{Symmetric Ciphers}{section.14.4}
\BOOKMARK [2][-]{subsection.14.4.2}{Assymetric Ciphers}{section.14.4}
\BOOKMARK [1][-]{section.14.5}{Thread Safety}{chapter.14}
\BOOKMARK [0][-]{chapter.15}{Configuring the Library}{}
\BOOKMARK [1][-]{section.15.1}{Introduction}{chapter.15}
\BOOKMARK [1][-]{section.15.2}{mycrypt\137cfg.h}{chapter.15}
\BOOKMARK [1][-]{section.15.3}{The Configure Script}{chapter.15}

BIN
crypt.pdf Normal file

Binary file not shown.

3040
crypt.tex Normal file

File diff suppressed because it is too large Load Diff

21
crypt_argchk.c Normal file
View File

@@ -0,0 +1,21 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
*
* LibTomCrypt is a library that provides various cryptographic
* algorithms in a highly modular and flexible manner.
*
* The library is free for all purposes without any express
* guarantee it works.
*
* Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org
*/
#include "mycrypt.h"
#include <signal.h>
#if (ARGTYPE == 0)
void crypt_argchk(char *v, char *s, int d)
{
fprintf(stderr, "_ARGCHK '%s' failure on line %d of file %s\n",
v, d, s);
(void)raise(SIGABRT);
}
#endif

18
crypt_cipher_descriptor.c Normal file
View File

@@ -0,0 +1,18 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
*
* LibTomCrypt is a library that provides various cryptographic
* algorithms in a highly modular and flexible manner.
*
* The library is free for all purposes without any express
* guarantee it works.
*
* Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org
*/
#include "mycrypt.h"
struct _cipher_descriptor cipher_descriptor[TAB_SIZE] = {
{ NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL },
{ NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL },
{ NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL },
{ NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL } };

19
crypt_cipher_is_valid.c Normal file
View File

@@ -0,0 +1,19 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
*
* LibTomCrypt is a library that provides various cryptographic
* algorithms in a highly modular and flexible manner.
*
* The library is free for all purposes without any express
* guarantee it works.
*
* Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org
*/
#include "mycrypt.h"
int cipher_is_valid(int idx)
{
if (idx < 0 || idx >= TAB_SIZE || cipher_descriptor[idx].name == NULL) {
return CRYPT_INVALID_CIPHER;
}
return CRYPT_OK;
}

24
crypt_find_cipher.c Normal file
View File

@@ -0,0 +1,24 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
*
* LibTomCrypt is a library that provides various cryptographic
* algorithms in a highly modular and flexible manner.
*
* The library is free for all purposes without any express
* guarantee it works.
*
* Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org
*/
#include "mycrypt.h"
int find_cipher(const char *name)
{
int x;
_ARGCHK(name != NULL);
for (x = 0; x < TAB_SIZE; x++) {
if (cipher_descriptor[x].name != NULL && !strcmp(cipher_descriptor[x].name, name)) {
return x;
}
}
return -1;
}

32
crypt_find_cipher_any.c Normal file
View File

@@ -0,0 +1,32 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
*
* LibTomCrypt is a library that provides various cryptographic
* algorithms in a highly modular and flexible manner.
*
* The library is free for all purposes without any express
* guarantee it works.
*
* Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org
*/
#include "mycrypt.h"
/* idea from Wayne Scott */
int find_cipher_any(const char *name, int blocklen, int keylen)
{
int x;
_ARGCHK(name != NULL);
x = find_cipher(name);
if (x != -1) return x;
for (x = 0; x < TAB_SIZE; x++) {
if (cipher_descriptor[x].name == NULL) {
continue;
}
if (blocklen <= (int)cipher_descriptor[x].block_length && keylen <= (int)cipher_descriptor[x].max_key_length) {
return x;
}
}
return -1;
}

22
crypt_find_cipher_id.c Normal file
View File

@@ -0,0 +1,22 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
*
* LibTomCrypt is a library that provides various cryptographic
* algorithms in a highly modular and flexible manner.
*
* The library is free for all purposes without any express
* guarantee it works.
*
* Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org
*/
#include "mycrypt.h"
int find_cipher_id(unsigned char ID)
{
int x;
for (x = 0; x < TAB_SIZE; x++) {
if (cipher_descriptor[x].ID == ID) {
return (cipher_descriptor[x].name == NULL) ? -1 : x;
}
}
return -1;
}

23
crypt_find_hash.c Normal file
View File

@@ -0,0 +1,23 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
*
* LibTomCrypt is a library that provides various cryptographic
* algorithms in a highly modular and flexible manner.
*
* The library is free for all purposes without any express
* guarantee it works.
*
* Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org
*/
#include "mycrypt.h"
int find_hash(const char *name)
{
int x;
_ARGCHK(name != NULL);
for (x = 0; x < TAB_SIZE; x++) {
if (hash_descriptor[x].name != NULL && strcmp(hash_descriptor[x].name, name) == 0) {
return x;
}
}
return -1;
}

34
crypt_find_hash_any.c Normal file
View File

@@ -0,0 +1,34 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
*
* LibTomCrypt is a library that provides various cryptographic
* algorithms in a highly modular and flexible manner.
*
* The library is free for all purposes without any express
* guarantee it works.
*
* Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org
*/
#include "mycrypt.h"
/* return first hash with at least [amount over] digestlen bytes of output */
int find_hash_any(const char *name, int digestlen)
{
int x, y, z;
_ARGCHK(name != NULL);
x = find_hash(name);
if (x != -1) return x;
y = MAXBLOCKSIZE+1;
z = -1;
for (x = 0; x < TAB_SIZE; x++) {
if (hash_descriptor[x].name == NULL) {
continue;
}
if ((int)hash_descriptor[x].hashsize >= digestlen && (int)hash_descriptor[x].hashsize < y) {
z = x;
y = hash_descriptor[x].hashsize;
}
}
return z;
}

22
crypt_find_hash_id.c Normal file
View File

@@ -0,0 +1,22 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
*
* LibTomCrypt is a library that provides various cryptographic
* algorithms in a highly modular and flexible manner.
*
* The library is free for all purposes without any express
* guarantee it works.
*
* Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org
*/
#include "mycrypt.h"
int find_hash_id(unsigned char ID)
{
int x;
for (x = 0; x < TAB_SIZE; x++) {
if (hash_descriptor[x].ID == ID) {
return (hash_descriptor[x].name == NULL) ? -1 : x;
}
}
return -1;
}

24
crypt_find_prng.c Normal file
View File

@@ -0,0 +1,24 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
*
* LibTomCrypt is a library that provides various cryptographic
* algorithms in a highly modular and flexible manner.
*
* The library is free for all purposes without any express
* guarantee it works.
*
* Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org
*/
#include "mycrypt.h"
int find_prng(const char *name)
{
int x;
_ARGCHK(name != NULL);
for (x = 0; x < TAB_SIZE; x++) {
if ((prng_descriptor[x].name != NULL) && strcmp(prng_descriptor[x].name, name) == 0) {
return x;
}
}
return -1;
}

17
crypt_hash_descriptor.c Normal file
View File

@@ -0,0 +1,17 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
*
* LibTomCrypt is a library that provides various cryptographic
* algorithms in a highly modular and flexible manner.
*
* The library is free for all purposes without any express
* guarantee it works.
*
* Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org
*/
#include "mycrypt.h"
struct _hash_descriptor hash_descriptor[TAB_SIZE] = {
{ NULL, 0, 0, 0, NULL, NULL, NULL, NULL },
{ NULL, 0, 0, 0, NULL, NULL, NULL, NULL },
{ NULL, 0, 0, 0, NULL, NULL, NULL, NULL },
{ NULL, 0, 0, 0, NULL, NULL, NULL, NULL } };

19
crypt_hash_is_valid.c Normal file
View File

@@ -0,0 +1,19 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
*
* LibTomCrypt is a library that provides various cryptographic
* algorithms in a highly modular and flexible manner.
*
* The library is free for all purposes without any express
* guarantee it works.
*
* Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org
*/
#include "mycrypt.h"
int hash_is_valid(int idx)
{
if (idx < 0 || idx >= TAB_SIZE || hash_descriptor[idx].name == NULL) {
return CRYPT_INVALID_HASH;
}
return CRYPT_OK;
}

18
crypt_prng_descriptor.c Normal file
View File

@@ -0,0 +1,18 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
*
* LibTomCrypt is a library that provides various cryptographic
* algorithms in a highly modular and flexible manner.
*
* The library is free for all purposes without any express
* guarantee it works.
*
* Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org
*/
#include "mycrypt.h"
struct _prng_descriptor prng_descriptor[TAB_SIZE] = {
{ NULL, NULL, NULL, NULL, NULL },
{ NULL, NULL, NULL, NULL, NULL },
{ NULL, NULL, NULL, NULL, NULL },
{ NULL, NULL, NULL, NULL, NULL } };

19
crypt_prng_is_valid.c Normal file
View File

@@ -0,0 +1,19 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
*
* LibTomCrypt is a library that provides various cryptographic
* algorithms in a highly modular and flexible manner.
*
* The library is free for all purposes without any express
* guarantee it works.
*
* Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org
*/
#include "mycrypt.h"
int prng_is_valid(int idx)
{
if (idx < 0 || idx >= TAB_SIZE || prng_descriptor[idx].name == NULL) {
return CRYPT_INVALID_PRNG;
}
return CRYPT_OK;
}

36
crypt_register_cipher.c Normal file
View File

@@ -0,0 +1,36 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
*
* LibTomCrypt is a library that provides various cryptographic
* algorithms in a highly modular and flexible manner.
*
* The library is free for all purposes without any express
* guarantee it works.
*
* Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org
*/
#include "mycrypt.h"
int register_cipher(const struct _cipher_descriptor *cipher)
{
int x;
_ARGCHK(cipher != NULL);
/* is it already registered? */
for (x = 0; x < TAB_SIZE; x++) {
if (cipher_descriptor[x].name != NULL && cipher_descriptor[x].ID == cipher->ID) {
return x;
}
}
/* find a blank spot */
for (x = 0; x < TAB_SIZE; x++) {
if (cipher_descriptor[x].name == NULL) {
memcpy(&cipher_descriptor[x], cipher, sizeof(struct _cipher_descriptor));
return x;
}
}
/* no spot */
return -1;
}

36
crypt_register_hash.c Normal file
View File

@@ -0,0 +1,36 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
*
* LibTomCrypt is a library that provides various cryptographic
* algorithms in a highly modular and flexible manner.
*
* The library is free for all purposes without any express
* guarantee it works.
*
* Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org
*/
#include "mycrypt.h"
int register_hash(const struct _hash_descriptor *hash)
{
int x;
_ARGCHK(hash != NULL);
/* is it already registered? */
for (x = 0; x < TAB_SIZE; x++) {
if (memcmp(&hash_descriptor[x], hash, sizeof(struct _hash_descriptor)) == 0) {
return x;
}
}
/* find a blank spot */
for (x = 0; x < TAB_SIZE; x++) {
if (hash_descriptor[x].name == NULL) {
memcpy(&hash_descriptor[x], hash, sizeof(struct _hash_descriptor));
return x;
}
}
/* no spot */
return -1;
}

36
crypt_register_prng.c Normal file
View File

@@ -0,0 +1,36 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
*
* LibTomCrypt is a library that provides various cryptographic
* algorithms in a highly modular and flexible manner.
*
* The library is free for all purposes without any express
* guarantee it works.
*
* Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org
*/
#include "mycrypt.h"
int register_prng(const struct _prng_descriptor *prng)
{
int x;
_ARGCHK(prng != NULL);
/* is it already registered? */
for (x = 0; x < TAB_SIZE; x++) {
if (memcmp(&prng_descriptor[x], prng, sizeof(struct _prng_descriptor)) == 0) {
return x;
}
}
/* find a blank spot */
for (x = 0; x < TAB_SIZE; x++) {
if (prng_descriptor[x].name == NULL) {
memcpy(&prng_descriptor[x], prng, sizeof(struct _prng_descriptor));
return x;
}
}
/* no spot */
return -1;
}

28
crypt_unregister_cipher.c Normal file
View File

@@ -0,0 +1,28 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
*
* LibTomCrypt is a library that provides various cryptographic
* algorithms in a highly modular and flexible manner.
*
* The library is free for all purposes without any express
* guarantee it works.
*
* Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org
*/
#include "mycrypt.h"
int unregister_cipher(const struct _cipher_descriptor *cipher)
{
int x;
_ARGCHK(cipher != NULL);
/* is it already registered? */
for (x = 0; x < TAB_SIZE; x++) {
if (memcmp(&cipher_descriptor[x], cipher, sizeof(struct _cipher_descriptor)) == 0) {
cipher_descriptor[x].name = NULL;
cipher_descriptor[x].ID = 255;
return CRYPT_OK;
}
}
return CRYPT_ERROR;
}

27
crypt_unregister_hash.c Normal file
View File

@@ -0,0 +1,27 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
*
* LibTomCrypt is a library that provides various cryptographic
* algorithms in a highly modular and flexible manner.
*
* The library is free for all purposes without any express
* guarantee it works.
*
* Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org
*/
#include "mycrypt.h"
int unregister_hash(const struct _hash_descriptor *hash)
{
int x;
_ARGCHK(hash != NULL);
/* is it already registered? */
for (x = 0; x < TAB_SIZE; x++) {
if (memcmp(&hash_descriptor[x], hash, sizeof(struct _hash_descriptor)) == 0) {
hash_descriptor[x].name = NULL;
return CRYPT_OK;
}
}
return CRYPT_ERROR;
}

27
crypt_unregister_prng.c Normal file
View File

@@ -0,0 +1,27 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
*
* LibTomCrypt is a library that provides various cryptographic
* algorithms in a highly modular and flexible manner.
*
* The library is free for all purposes without any express
* guarantee it works.
*
* Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org
*/
#include "mycrypt.h"
int unregister_prng(const struct _prng_descriptor *prng)
{
int x;
_ARGCHK(prng != NULL);
/* is it already registered? */
for (x = 0; x < TAB_SIZE; x++) {
if (memcmp(&prng_descriptor[x], prng, sizeof(struct _prng_descriptor)) != 0) {
prng_descriptor[x].name = NULL;
return CRYPT_OK;
}
}
return CRYPT_ERROR;
}

25
ctr_decrypt.c Normal file
View File

@@ -0,0 +1,25 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
*
* LibTomCrypt is a library that provides various cryptographic
* algorithms in a highly modular and flexible manner.
*
* The library is free for all purposes without any express
* guarantee it works.
*
* Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org
*/
#include "mycrypt.h"
#ifdef CTR
int ctr_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_CTR *ctr)
{
_ARGCHK(pt != NULL);
_ARGCHK(ct != NULL);
_ARGCHK(ctr != NULL);
return ctr_encrypt(ct, pt, len, ctr);
}
#endif

64
ctr_encrypt.c Normal file
View File

@@ -0,0 +1,64 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
*
* LibTomCrypt is a library that provides various cryptographic
* algorithms in a highly modular and flexible manner.
*
* The library is free for all purposes without any express
* guarantee it works.
*
* Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org
*/
#include "mycrypt.h"
#ifdef CTR
int ctr_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_CTR *ctr)
{
int x, err;
_ARGCHK(pt != NULL);
_ARGCHK(ct != NULL);
_ARGCHK(ctr != NULL);
if ((err = cipher_is_valid(ctr->cipher)) != CRYPT_OK) {
return err;
}
/* is blocklen/padlen valid? */
if (ctr->blocklen < 0 || ctr->blocklen > (int)sizeof(ctr->ctr) ||
ctr->padlen < 0 || ctr->padlen > (int)sizeof(ctr->pad)) {
return CRYPT_INVALID_ARG;
}
while (len-- > 0) {
/* is the pad empty? */
if (ctr->padlen == ctr->blocklen) {
/* increment counter */
if (ctr->mode == 0) {
/* little-endian */
for (x = 0; x < ctr->blocklen; x++) {
ctr->ctr[x] = (ctr->ctr[x] + (unsigned char)1) & (unsigned char)255;
if (ctr->ctr[x] != (unsigned char)0) {
break;
}
}
} else {
/* big-endian */
for (x = ctr->blocklen-1; x >= 0; x--) {
ctr->ctr[x] = (ctr->ctr[x] + (unsigned char)1) & (unsigned char)255;
if (ctr->ctr[x] != (unsigned char)0) {
break;
}
}
}
/* encrypt it */
cipher_descriptor[ctr->cipher].ecb_encrypt(ctr->ctr, ctr->pad, &ctr->key);
ctr->padlen = 0;
}
*ct++ = *pt++ ^ ctr->pad[ctr->padlen++];
}
return CRYPT_OK;
}
#endif

46
ctr_start.c Normal file
View File

@@ -0,0 +1,46 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
*
* LibTomCrypt is a library that provides various cryptographic
* algorithms in a highly modular and flexible manner.
*
* The library is free for all purposes without any express
* guarantee it works.
*
* Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org
*/
#include "mycrypt.h"
#ifdef CTR
int ctr_start(int cipher, const unsigned char *count, const unsigned char *key, int keylen,
int num_rounds, symmetric_CTR *ctr)
{
int x, err;
_ARGCHK(count != NULL);
_ARGCHK(key != NULL);
_ARGCHK(ctr != NULL);
/* bad param? */
if ((err = cipher_is_valid(cipher)) != CRYPT_OK) {
return err;
}
/* setup cipher */
if ((err = cipher_descriptor[cipher].setup(key, keylen, num_rounds, &ctr->key)) != CRYPT_OK) {
return err;
}
/* copy ctr */
ctr->blocklen = cipher_descriptor[cipher].block_length;
ctr->cipher = cipher;
ctr->padlen = 0;
ctr->mode = 0;
for (x = 0; x < ctr->blocklen; x++) {
ctr->ctr[x] = count[x];
}
cipher_descriptor[ctr->cipher].ecb_encrypt(ctr->ctr, ctr->pad, &ctr->key);
return CRYPT_OK;
}
#endif

231
demos/encrypt.c Normal file
View File

@@ -0,0 +1,231 @@
/* encrypt V1.1 Fri Oct 18 04:28:03 NZDT 2002 */
/* File de/encryption, using libtomcrypt */
/* Written by Daniel Richards <kyhwana@world-net.co.nz> */
/* Help from Tom St Denis with various bits */
/* This code is public domain, no rights reserved. */
/* Encrypts by default, -d flag enables decryption */
/* ie: ./encrypt blowfish story.txt story.ct */
/* ./encrypt -d blowfish story.ct story.pt */
#include <mycrypt.h>
int errno;
int usage(char *name)
{
int x;
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);
}
exit(1);
}
void register_algs(void)
{
int x;
#ifdef RIJNDAEL
register_cipher (&aes_desc);
#endif
#ifdef BLOWFISH
register_cipher (&blowfish_desc);
#endif
#ifdef XTEA
register_cipher (&xtea_desc);
#endif
#ifdef RC5
register_cipher (&rc5_desc);
#endif
#ifdef RC6
register_cipher (&rc6_desc);
#endif
#ifdef SAFERP
register_cipher (&saferp_desc);
#endif
#ifdef TWOFISH
register_cipher (&twofish_desc);
#endif
#ifdef SAFER
register_cipher (&safer_k64_desc);
register_cipher (&safer_sk64_desc);
register_cipher (&safer_k128_desc);
register_cipher (&safer_sk128_desc);
#endif
#ifdef RC2
register_cipher (&rc2_desc);
#endif
#ifdef DES
register_cipher (&des_desc);
register_cipher (&des3_desc);
#endif
#ifdef CAST5
register_cipher (&cast5_desc);
#endif
#ifdef NOEKEON
register_cipher (&noekeon_desc);
#endif
#ifdef SKIPJACK
register_cipher (&skipjack_desc);
#endif
if (register_hash(&sha256_desc) == -1) {
printf("Error registering SHA256\n");
exit(-1);
}
if (register_prng(&yarrow_desc) == -1) {
printf("Error registering yarrow PRNG\n");
exit(-1);
}
if (register_prng(&sprng_desc) == -1) {
printf("Error registering sprng PRNG\n");
exit(-1);
}
}
int main(int argc, char *argv[])
{
unsigned char plaintext[512],ciphertext[512];
unsigned char tmpkey[512], key[MAXBLOCKSIZE], IV[MAXBLOCKSIZE];
unsigned char inbuf[512]; /* i/o block size */
unsigned long outlen, y, ivsize, x, decrypt;
symmetric_CTR ctr;
int cipher_idx, hash_idx, ks;
char *infile, *outfile, *cipher;
prng_state prng;
FILE *fdin, *fdout;
/* register algs, so they can be printed */
register_algs();
if (argc < 4) {
return usage(argv[0]);
}
if (!strcmp(argv[1], "-d")) {
decrypt = 1;
cipher = argv[2];
infile = argv[3];
outfile = argv[4];
} else {
decrypt = 0;
cipher = argv[1];
infile = argv[2];
outfile = argv[3];
}
/* file handles setup */
fdin = fopen(infile,"rb");
if (fdin == NULL) {
perror("Can't open input for reading");
exit(-1);
}
fdout = fopen(outfile,"wb");
if (fdout == NULL) {
perror("Can't open output for writing");
exit(-1);
}
cipher_idx = find_cipher(cipher);
if (cipher_idx == -1) {
printf("Invalid cipher entered on command line.\n");
exit(-1);
}
hash_idx = find_hash("sha256");
if (hash_idx == -1) {
printf("SHA256 not found...?\n");
exit(-1);
}
ivsize = cipher_descriptor[cipher_idx].block_length;
ks = hash_descriptor[hash_idx].hashsize;
if (cipher_descriptor[cipher_idx].keysize(&ks) != CRYPT_OK) {
printf("Invalid keysize???\n");
exit(-1);
}
printf("\nEnter key: ");
fgets((char *)tmpkey,sizeof(tmpkey), stdin);
outlen = sizeof(key);
if ((errno = hash_memory(hash_idx,tmpkey,strlen((char *)tmpkey),key,&outlen)) != CRYPT_OK) {
printf("Error hashing key: %s\n", error_to_string(errno));
exit(-1);
}
if (decrypt) {
/* Need to read in IV */
if (fread(IV,1,ivsize,fdin) != ivsize) {
printf("Error reading IV from input.\n");
exit(-1);
}
if ((errno = ctr_start(cipher_idx,IV,key,ks,0,&ctr)) != CRYPT_OK) {
printf("ctr_start error: %s\n",error_to_string(errno));
exit(-1);
}
/* IV done */
do {
y = fread(inbuf,1,sizeof(inbuf),fdin);
if ((errno = ctr_decrypt(inbuf,plaintext,y,&ctr)) != CRYPT_OK) {
printf("ctr_decrypt error: %s\n", error_to_string(errno));
exit(-1);
}
if (fwrite(plaintext,1,y,fdout) != y) {
printf("Error writing to file.\n");
exit(-1);
}
} while (y == sizeof(inbuf));
fclose(fdin);
fclose(fdout);
} else { /* encrypt */
/* Setup yarrow for random bytes for IV */
if ((errno = rng_make_prng(128, find_prng("yarrow"), &prng, NULL)) != CRYPT_OK) {
printf("Error setting up PRNG, %s\n", error_to_string(errno));
}
/* You can use rng_get_bytes on platforms that support it */
/* x = rng_get_bytes(IV,ivsize,NULL);*/
x = yarrow_read(IV,ivsize,&prng);
if (x != ivsize) {
printf("Error reading PRNG for IV required.\n");
exit(-1);
}
if (fwrite(IV,1,ivsize,fdout) != ivsize) {
printf("Error writing IV to output.\n");
exit(-1);
}
if ((errno = ctr_start(cipher_idx,IV,key,ks,0,&ctr)) != CRYPT_OK) {
printf("ctr_start error: %s\n",error_to_string(errno));
exit(-1);
}
do {
y = fread(inbuf,1,sizeof(inbuf),fdin);
if ((errno = ctr_encrypt(inbuf,ciphertext,y,&ctr)) != CRYPT_OK) {
printf("ctr_encrypt error: %s\n", error_to_string(errno));
exit(-1);
}
if (fwrite(ciphertext,1,y,fdout) != y) {
printf("Error writing to output.\n");
exit(-1);
}
} while (y == sizeof(inbuf));
fclose(fdout);
fclose(fdin);
}
return 0;
}

106
demos/hashsum.c Normal file
View File

@@ -0,0 +1,106 @@
/*
* Written by Daniel Richards <kyhwana@world-net.co.nz> 6/7/2002
* hash.c: This app uses libtomcrypt to hash either stdin or a file
* This file is Public Domain. No rights are reserved.
* Compile with 'gcc hashsum.c -o hashsum -ltomcrypt'
* This example isn't really big enough to warrent splitting into
* more functions ;)
*/
#include <mycrypt_custom.h>
int errno;
void register_algs();
int main(int argc, char **argv)
{
int idx, x, z;
unsigned long w;
unsigned char hash_buffer[MAXBLOCKSIZE];
hash_state md;
/* You need to register algorithms before using them */
register_algs();
if (argc < 2) {
printf("usage: ./hash algorithm file [file ...]\n");
printf("Algorithms:\n");
for (x = 0; hash_descriptor[x].name != NULL; x++) {
printf(" %s\n", hash_descriptor[x].name);
}
exit(EXIT_SUCCESS);
}
idx = find_hash(argv[1]);
if (idx == -1) {
fprintf(stderr, "\nInvalid hash specified on command line.\n");
return -1;
}
if (argc == 2) {
hash_descriptor[idx].init(&md);
do {
x = fread(hash_buffer, 1, sizeof(hash_buffer), stdin);
hash_descriptor[idx].process(&md, hash_buffer, x);
} while (x == sizeof(hash_buffer));
hash_descriptor[idx].done(&md, hash_buffer);
for (x = 0; x < (int)hash_descriptor[idx].hashsize; x++) {
printf("%02x",hash_buffer[x]);
}
printf(" (stdin)\n");
} else {
for (z = 2; z < argc; z++) {
w = sizeof(hash_buffer);
if ((errno = hash_file(idx,argv[z],hash_buffer,&w)) != CRYPT_OK) {
printf("File hash error: %s\n", error_to_string(errno));
} else {
for (x = 0; x < (int)hash_descriptor[idx].hashsize; x++) {
printf("%02x",hash_buffer[x]);
}
printf(" %s\n", argv[z]);
}
}
}
return EXIT_SUCCESS;
}
void register_algs(void)
{
#ifdef TIGER
register_hash (&tiger_desc);
#endif
#ifdef MD2
register_hash (&md2_desc);
#endif
#ifdef MD4
register_hash (&md4_desc);
#endif
#ifdef MD5
register_hash (&md5_desc);
#endif
#ifdef SHA1
register_hash (&sha1_desc);
#endif
#ifdef SHA224
register_hash (&sha224_desc);
#endif
#ifdef SHA256
register_hash (&sha256_desc);
#endif
#ifdef SHA384
register_hash (&sha384_desc);
#endif
#ifdef SHA512
register_hash (&sha512_desc);
#endif
#ifdef RIPEMD128
register_hash (&rmd128_desc);
#endif
#ifdef RIPEMD160
register_hash (&rmd160_desc);
#endif
#ifdef WHIRLPOOL
register_hash (&whirlpool_desc);
#endif
}

11
demos/small.c Normal file
View File

@@ -0,0 +1,11 @@
// small demo app that just includes a cipher/hash/prng
#include <mycrypt.h>
int main(void)
{
register_cipher(&rijndael_desc);
register_prng(&yarrow_desc);
register_hash(&sha256_desc);
return 0;
}

1982
demos/test.c Normal file

File diff suppressed because it is too large Load Diff

492
demos/tv_gen.c Normal file
View File

@@ -0,0 +1,492 @@
#include <mycrypt.h>
void reg_algs(void)
{
#ifdef RIJNDAEL
register_cipher (&aes_desc);
#endif
#ifdef BLOWFISH
register_cipher (&blowfish_desc);
#endif
#ifdef XTEA
register_cipher (&xtea_desc);
#endif
#ifdef RC5
register_cipher (&rc5_desc);
#endif
#ifdef RC6
register_cipher (&rc6_desc);
#endif
#ifdef SAFERP
register_cipher (&saferp_desc);
#endif
#ifdef TWOFISH
register_cipher (&twofish_desc);
#endif
#ifdef SAFER
register_cipher (&safer_k64_desc);
register_cipher (&safer_sk64_desc);
register_cipher (&safer_k128_desc);
register_cipher (&safer_sk128_desc);
#endif
#ifdef RC2
register_cipher (&rc2_desc);
#endif
#ifdef DES
register_cipher (&des_desc);
register_cipher (&des3_desc);
#endif
#ifdef CAST5
register_cipher (&cast5_desc);
#endif
#ifdef NOEKEON
register_cipher (&noekeon_desc);
#endif
#ifdef SKIPJACK
register_cipher (&skipjack_desc);
#endif
#ifdef TIGER
register_hash (&tiger_desc);
#endif
#ifdef MD2
register_hash (&md2_desc);
#endif
#ifdef MD4
register_hash (&md4_desc);
#endif
#ifdef MD5
register_hash (&md5_desc);
#endif
#ifdef SHA1
register_hash (&sha1_desc);
#endif
#ifdef SHA224
register_hash (&sha224_desc);
#endif
#ifdef SHA256
register_hash (&sha256_desc);
#endif
#ifdef SHA384
register_hash (&sha384_desc);
#endif
#ifdef SHA512
register_hash (&sha512_desc);
#endif
#ifdef RIPEMD128
register_hash (&rmd128_desc);
#endif
#ifdef RIPEMD160
register_hash (&rmd160_desc);
#endif
#ifdef WHIRLPOOL
register_hash (&whirlpool_desc);
#endif
}
void hash_gen(void)
{
unsigned char md[MAXBLOCKSIZE], buf[MAXBLOCKSIZE*2+2];
unsigned long outlen, x, y, z;
FILE *out;
out = fopen("hash_tv.txt", "w");
fprintf(out, "Hash Test Vectors:\n\nThese are the hashes of nn bytes '00 01 02 03 .. (nn-1)'\n\n");
for (x = 0; hash_descriptor[x].name != NULL; x++) {
fprintf(out, "Hash: %s\n", hash_descriptor[x].name);
for (y = 0; y <= (hash_descriptor[x].blocksize * 2); y++) {
for (z = 0; z < y; z++) {
buf[z] = (unsigned char)(z & 255);
}
outlen = sizeof(md);
hash_memory(x, buf, y, md, &outlen);
fprintf(out, "%3lu: ", y);
for (z = 0; z < outlen; z++) {
fprintf(out, "%02X", md[z]);
}
fprintf(out, "\n");
}
fprintf(out, "\n");
}
fclose(out);
}
void cipher_gen(void)
{
unsigned char key[MAXBLOCKSIZE], pt[MAXBLOCKSIZE];
unsigned long x, y, z, w;
int kl, lastkl;
FILE *out;
symmetric_key skey;
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"
"The output of step N is used as the key and plaintext for step N+1 (key bytes repeated as required to fill the key)\n\n");
for (x = 0; cipher_descriptor[x].name != NULL; x++) {
fprintf(out, "Cipher: %s\n", cipher_descriptor[x].name);
/* three modes, smallest, medium, large keys */
lastkl = 10000;
for (y = 0; y < 3; y++) {
switch (y) {
case 0: kl = cipher_descriptor[x].min_key_length; break;
case 1: kl = (cipher_descriptor[x].min_key_length + cipher_descriptor[x].max_key_length)/2; break;
case 2: kl = cipher_descriptor[x].max_key_length; break;
}
cipher_descriptor[x].keysize(&kl);
if (kl == lastkl) break;
lastkl = kl;
fprintf(out, "Key Size: %d bytes\n", kl);
for (z = 0; (int)z < kl; z++) {
key[z] = (unsigned char)z;
}
cipher_descriptor[x].setup(key, kl, 0, &skey);
for (z = 0; (int)z < cipher_descriptor[x].block_length; z++) {
pt[z] = (unsigned char)z;
}
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");
}
fprintf(out, "\n");
}
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);
}
void pmac_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("pmac_tv.txt", "w");
fprintf(out,
"PMAC 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, "PMAC-%s (%d byte key)\n", cipher_descriptor[x].name, kl);
/* initial key/block */
for (y = 0; y < kl; y++) {
key[y] = (y & 255);
}
for (y = 0; y <= (int)(cipher_descriptor[x].block_length*2); y++) {
for (z = 0; z < y; z++) {
input[z] = (unsigned char)(z & 255);
}
len = sizeof(output);
if ((err = pmac_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);
}
void eax_gen(void)
{
int err, kl, x, y1, z;
FILE *out;
unsigned char key[MAXBLOCKSIZE], nonce[MAXBLOCKSIZE*2], header[MAXBLOCKSIZE*2],
plaintext[MAXBLOCKSIZE*2], tag[MAXBLOCKSIZE];
unsigned long len;
out = fopen("eax_tv.txt", "w");
fprintf(out, "EAX Test Vectors. Uses the 00010203...NN-1 pattern for header/nonce/plaintext/key. The outputs\n"
"are of the form ciphertext,tag for a given NN. The key for step N>1 is the tag of the previous\n"
"step repeated sufficiently.\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, "EAX-%s (%d byte key)\n", cipher_descriptor[x].name, kl);
/* the key */
for (z = 0; z < kl; z++) {
key[z] = (z & 255);
}
for (y1 = 0; y1 <= (int)(cipher_descriptor[x].block_length*2); y1++){
for (z = 0; z < y1; z++) {
plaintext[z] = (unsigned char)(z & 255);
nonce[z] = (unsigned char)(z & 255);
header[z] = (unsigned char)(z & 255);
}
len = sizeof(tag);
if ((err = eax_encrypt_authenticate_memory(x, key, kl, nonce, y1, header, y1, plaintext, y1, plaintext, tag, &len)) != CRYPT_OK) {
printf("Error EAX'ing: %s\n", error_to_string(err));
exit(EXIT_FAILURE);
}
fprintf(out, "%3d: ", y1);
for (z = 0; z < y1; z++) {
fprintf(out, "%02X", plaintext[z]);
}
fprintf(out, ", ");
for (z = 0; z <(int)len; z++) {
fprintf(out, "%02X", tag[z]);
}
fprintf(out, "\n");
/* forward the key */
for (z = 0; z < kl; z++) {
key[z] = tag[z % len];
}
}
fprintf(out, "\n");
}
fclose(out);
}
void ocb_gen(void)
{
int err, kl, x, y1, z;
FILE *out;
unsigned char key[MAXBLOCKSIZE], nonce[MAXBLOCKSIZE*2],
plaintext[MAXBLOCKSIZE*2], tag[MAXBLOCKSIZE];
unsigned long len;
out = fopen("ocb_tv.txt", "w");
fprintf(out, "OCB Test Vectors. Uses the 00010203...NN-1 pattern for nonce/plaintext/key. The outputs\n"
"are of the form ciphertext,tag for a given NN. The key for step N>1 is the tag of the previous\n"
"step repeated sufficiently. The nonce is fixed throughout.\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, "OCB-%s (%d byte key)\n", cipher_descriptor[x].name, kl);
/* the key */
for (z = 0; z < kl; z++) {
key[z] = (z & 255);
}
/* fixed nonce */
for (z = 0; z < cipher_descriptor[x].block_length; z++) {
nonce[z] = z;
}
for (y1 = 0; y1 <= (int)(cipher_descriptor[x].block_length*2); y1++){
for (z = 0; z < y1; z++) {
plaintext[z] = (unsigned char)(z & 255);
}
len = sizeof(tag);
if ((err = ocb_encrypt_authenticate_memory(x, key, kl, nonce, plaintext, y1, plaintext, tag, &len)) != CRYPT_OK) {
printf("Error OCB'ing: %s\n", error_to_string(err));
exit(EXIT_FAILURE);
}
fprintf(out, "%3d: ", y1);
for (z = 0; z < y1; z++) {
fprintf(out, "%02X", plaintext[z]);
}
fprintf(out, ", ");
for (z = 0; z <(int)len; z++) {
fprintf(out, "%02X", tag[z]);
}
fprintf(out, "\n");
/* forward the key */
for (z = 0; z < kl; z++) {
key[z] = tag[z % len];
}
}
fprintf(out, "\n");
}
fclose(out);
}
void base64_gen(void)
{
FILE *out;
unsigned char dst[256], src[32];
unsigned long x, y, len;
out = fopen("base64_tv.txt", "w");
fprintf(out, "Base64 vectors. These are the base64 encodings of the strings 00,01,02...NN-1\n\n");
for (x = 0; x <= 32; x++) {
for (y = 0; y < x; y++) {
src[y] = y;
}
len = sizeof(dst);
base64_encode(src, x, dst, &len);
fprintf(out, "%2lu: %s\n", x, dst);
}
fclose(out);
}
int main(void)
{
reg_algs();
printf("Generating hash vectors..."); fflush(stdout); hash_gen(); printf("done\n");
printf("Generating cipher vectors..."); fflush(stdout); cipher_gen(); printf("done\n");
printf("Generating HMAC vectors..."); fflush(stdout); hmac_gen(); printf("done\n");
printf("Generating OMAC vectors..."); fflush(stdout); omac_gen(); printf("done\n");
printf("Generating PMAC vectors..."); fflush(stdout); pmac_gen(); printf("done\n");
printf("Generating EAX vectors..."); fflush(stdout); eax_gen(); printf("done\n");
printf("Generating OCB vectors..."); fflush(stdout); ocb_gen(); printf("done\n");
printf("Generating BASE64 vectors..."); fflush(stdout); base64_gen(); printf("done\n");
return 0;
}

358
demos/x86_prof.c Normal file
View File

@@ -0,0 +1,358 @@
#include <mycrypt.h>
#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)
{
#if defined __GNUC__
#ifdef __i386__
ulong64 a;
__asm__ __volatile__ ("rdtsc ":"=A" (a));
return a;
#else /* gcc-IA64 version */
unsigned long result;
__asm__ __volatile__("mov %0=ar.itc" : "=r"(result) :: "memory");
while (__builtin_expect ((int) result == -1, 0))
__asm__ __volatile__("mov %0=ar.itc" : "=r"(result) :: "memory");
return result;
#endif
// Microsoft and Intel Windows compilers
#elif defined _M_IX86
__asm rdtsc
#elif defined _M_AMD64
return __rdtsc ();
#elif defined _M_IA64
#if defined __INTEL_COMPILER
#include <ia64intrin.h>
#endif
return __getReg (3116);
#else
#error need rdtsc function for this build
#endif
}
ulong64 timer, skew = 0;
prng_state prng;
void t_start(void)
{
timer = rdtsc();
}
ulong64 t_read(void)
{
return rdtsc() - timer;
}
void init_timer(void)
{
ulong64 c1, c2, t1, t2, t3;
unsigned long y1;
c1 = c2 = (ulong64)-1;
for (y1 = 0; y1 < TIMES*100; y1++) {
t_start();
t1 = t_read();
t3 = t_read();
t2 = t_read() - t1;
c1 = (c1 > t1) ? t1 : c1;
c2 = (c2 > t2) ? t2 : c2;
}
skew = c2 - c1;
printf("Clock Skew: %lu\n", (unsigned long)skew);
}
void reg_algs(void)
{
#ifdef RIJNDAEL
register_cipher (&aes_desc);
#endif
#ifdef BLOWFISH
register_cipher (&blowfish_desc);
#endif
#ifdef XTEA
register_cipher (&xtea_desc);
#endif
#ifdef RC5
register_cipher (&rc5_desc);
#endif
#ifdef RC6
register_cipher (&rc6_desc);
#endif
#ifdef SAFERP
register_cipher (&saferp_desc);
#endif
#ifdef TWOFISH
register_cipher (&twofish_desc);
#endif
#ifdef SAFER
register_cipher (&safer_k64_desc);
register_cipher (&safer_sk64_desc);
register_cipher (&safer_k128_desc);
register_cipher (&safer_sk128_desc);
#endif
#ifdef RC2
register_cipher (&rc2_desc);
#endif
#ifdef DES
register_cipher (&des_desc);
register_cipher (&des3_desc);
#endif
#ifdef CAST5
register_cipher (&cast5_desc);
#endif
#ifdef NOEKEON
register_cipher (&noekeon_desc);
#endif
#ifdef SKIPJACK
register_cipher (&skipjack_desc);
#endif
#ifdef TIGER
register_hash (&tiger_desc);
#endif
#ifdef MD2
register_hash (&md2_desc);
#endif
#ifdef MD4
register_hash (&md4_desc);
#endif
#ifdef MD5
register_hash (&md5_desc);
#endif
#ifdef SHA1
register_hash (&sha1_desc);
#endif
#ifdef SHA224
register_hash (&sha224_desc);
#endif
#ifdef SHA256
register_hash (&sha256_desc);
#endif
#ifdef SHA384
register_hash (&sha384_desc);
#endif
#ifdef SHA512
register_hash (&sha512_desc);
#endif
#ifdef RIPEMD128
register_hash (&rmd128_desc);
#endif
#ifdef RIPEMD160
register_hash (&rmd160_desc);
#endif
#ifdef WHIRLPOOL
register_hash (&whirlpool_desc);
#endif
register_prng(&yarrow_desc);
rng_make_prng(128, find_prng("yarrow"), &prng, NULL);
}
int time_keysched(void)
{
unsigned long x, i, y1;
ulong64 t1, c1;
symmetric_key skey;
int kl;
int (*func) (const unsigned char *, int , int , symmetric_key *);
unsigned char key[MAXBLOCKSIZE];
printf ("\n\nKey Schedule Time Trials for the Symmetric Ciphers:\n(Times are cycles per key)\n");
no_results = 0;
for (x = 0; cipher_descriptor[x].name != NULL; x++) {
#define DO1(k) func(k, kl, 0, &skey);
func = cipher_descriptor[x].setup;
kl = cipher_descriptor[x].min_key_length;
c1 = (ulong64)-1;
for (y1 = 0; y1 < KTIMES; y1++) {
yarrow_read(key, kl, &prng);
t_start();
DO1(key);
t1 = t_read();
c1 = (t1 > c1) ? c1 : t1;
}
t1 = c1 - skew;
results[no_results].spd1 = results[no_results].avg = t1;
results[no_results++].id = x;
printf("."); fflush(stdout);
#undef DO1
}
tally_results(0);
return 0;
}
int time_cipher(void)
{
unsigned long x, y1;
ulong64 t1, t2, c1, c2, a1, a2;
symmetric_key skey;
void (*func) (const unsigned char *, unsigned char *, symmetric_key *);
unsigned char key[MAXBLOCKSIZE], pt[MAXBLOCKSIZE];
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);
#define DO1 func(pt,pt,&skey);
#define DO2 DO1 DO1
func = cipher_descriptor[x].ecb_encrypt;
c1 = c2 = (ulong64)-1;
for (y1 = 0; y1 < TIMES; y1++) {
t_start();
DO1;
t1 = t_read();
DO2;
t2 = t_read();
t2 -= t1;
c1 = (t1 > c1 ? c1 : t1);
c2 = (t2 > c2 ? c2 : t2);
}
a1 = c2 - c1 - skew;
func = cipher_descriptor[x].ecb_decrypt;
c1 = c2 = (ulong64)-1;
for (y1 = 0; y1 < TIMES; y1++) {
t_start();
DO1;
t1 = t_read();
DO2;
t2 = t_read();
t2 -= t1;
c1 = (t1 > c1 ? c1 : t1);
c2 = (t2 > c2 ? c2 : t2);
}
a2 = c2 - c1 - skew;
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;
}
int time_hash(void)
{
unsigned long x, y1, len;
ulong64 t1, t2, c1, c2;
hash_state md;
int (*func)(hash_state *, const unsigned char *, unsigned long);
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);
#define DO1 func(&md,pt,len);
#define DO2 DO1 DO1
func = hash_descriptor[x].process;
len = hash_descriptor[x].blocksize;
c1 = c2 = (ulong64)-1;
for (y1 = 0; y1 < TIMES; y1++) {
t_start();
DO1;
t1 = t_read();
DO2;
t2 = t_read() - t1;
c1 = (t1 > c1) ? c1 : t1;
c2 = (t2 > c2) ? c2 : t2;
}
t1 = c2 - c1 - skew;
t1 = ((t1 * CONST64(1000))) / ((ulong64)hash_descriptor[x].blocksize);
results[no_results].id = x;
results[no_results].spd1 = results[no_results].avg = t1;
++no_results;
printf("."); fflush(stdout);
#undef DO2
#undef DO1
}
tally_results(2);
return 0;
}
int main(void)
{
reg_algs();
printf("Timings for ciphers and hashes. Times are listed as cycles per byte processed.\n\n");
// init_timer();
time_cipher();
time_keysched();
time_hash();
return EXIT_SUCCESS;
}

1813
des.c Normal file

File diff suppressed because it is too large Load Diff

452
dh.c Normal file
View File

@@ -0,0 +1,452 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
*
* LibTomCrypt is a library that provides various cryptographic
* algorithms in a highly modular and flexible manner.
*
* The library is free for all purposes without any express
* guarantee it works.
*
* Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org
*/
#include "mycrypt.h"
#ifdef MDH
/* This holds the key settings. ***MUST*** be organized by size from smallest to largest. */
static const struct {
int size;
char *name, *base, *prime;
} sets[] = {
#ifdef DH768
{
96,
"DH-768",
"4",
"F///////////////////////////////////////////////////////////"
"////////////////////////////////////////////////////////////"
"//////m3wvV"
},
#endif
#ifdef DH1024
{
128,
"DH-1024",
"4",
"F///////////////////////////////////////////////////////////"
"////////////////////////////////////////////////////////////"
"////////////////////////////////////////////////m3C47"
},
#endif
#ifdef DH1280
{
160,
"DH-1280",
"4",
"F///////////////////////////////////////////////////////////"
"////////////////////////////////////////////////////////////"
"////////////////////////////////////////////////////////////"
"//////////////////////////////m4kSN"
},
#endif
#ifdef DH1536
{
192,
"DH-1536",
"4",
"F///////////////////////////////////////////////////////////"
"////////////////////////////////////////////////////////////"
"////////////////////////////////////////////////////////////"
"////////////////////////////////////////////////////////////"
"////////////m5uqd"
},
#endif
#ifdef DH1792
{
224,
"DH-1792",
"4",
"F///////////////////////////////////////////////////////////"
"////////////////////////////////////////////////////////////"
"////////////////////////////////////////////////////////////"
"////////////////////////////////////////////////////////////"
"//////////////////////////////////////////////////////mT/sd"
},
#endif
#ifdef DH2048
{
256,
"DH-2048",
"4",
"3///////////////////////////////////////////////////////////"
"////////////////////////////////////////////////////////////"
"////////////////////////////////////////////////////////////"
"////////////////////////////////////////////////////////////"
"////////////////////////////////////////////////////////////"
"/////////////////////////////////////////m8MPh"
},
#endif
#ifdef DH2560
{
320,
"DH-2560",
"4",
"3///////////////////////////////////////////////////////////"
"////////////////////////////////////////////////////////////"
"////////////////////////////////////////////////////////////"
"////////////////////////////////////////////////////////////"
"////////////////////////////////////////////////////////////"
"////////////////////////////////////////////////////////////"
"////////////////////////////////////////////////////////////"
"/////mKFpF"
},
#endif
#ifdef DH3072
{
384,
"DH-3072",
"4",
"3///////////////////////////////////////////////////////////"
"////////////////////////////////////////////////////////////"
"////////////////////////////////////////////////////////////"
"////////////////////////////////////////////////////////////"
"////////////////////////////////////////////////////////////"
"////////////////////////////////////////////////////////////"
"////////////////////////////////////////////////////////////"
"////////////////////////////////////////////////////////////"
"/////////////////////////////m32nN"
},
#endif
#ifdef DH4096
{
512,
"DH-4096",
"4",
"////////////////////////////////////////////////////////////"
"////////////////////////////////////////////////////////////"
"////////////////////////////////////////////////////////////"
"////////////////////////////////////////////////////////////"
"////////////////////////////////////////////////////////////"
"////////////////////////////////////////////////////////////"
"////////////////////////////////////////////////////////////"
"////////////////////////////////////////////////////////////"
"////////////////////////////////////////////////////////////"
"////////////////////////////////////////////////////////////"
"////////////////////////////////////////////////////////////"
"/////////////////////m8pOF"
},
#endif
{
0,
NULL,
NULL,
NULL
}
};
static int is_valid_idx(int n)
{
int x;
for (x = 0; sets[x].size; x++);
if ((n < 0) || (n >= x)) {
return 0;
}
return 1;
}
int dh_test(void)
{
mp_int p, g, tmp;
int x, err, primality;
if ((err = 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 ((err = mp_read_radix(&g,(char *)sets[x].base, 64)) != MP_OKAY) { goto error; }
if ((err = mp_read_radix(&p,(char *)sets[x].prime, 64)) != MP_OKAY) { goto error; }
/* ensure p is prime */
if ((err = is_prime(&p, &primality)) != CRYPT_OK) { goto done; }
if (primality == 0) {
err = CRYPT_FAIL_TESTVECTOR;
goto done;
}
if ((err = mp_sub_d(&p, 1, &tmp)) != MP_OKAY) { goto error; }
if ((err = mp_div_2(&tmp, &tmp)) != MP_OKAY) { goto error; }
/* ensure (p-1)/2 is prime */
if ((err = is_prime(&tmp, &primality)) != CRYPT_OK) { goto done; }
if (primality == 0) {
err = CRYPT_FAIL_TESTVECTOR;
goto done;
}
/* now see if g^((p-1)/2) mod p is in fact 1 */
if ((err = mp_exptmod(&g, &tmp, &p, &tmp)) != MP_OKAY) { goto error; }
if (mp_cmp_d(&tmp, 1)) {
err = CRYPT_FAIL_TESTVECTOR;
goto done;
}
}
err = CRYPT_OK;
goto done;
error:
err = mpi_to_ltc_error(err);
done:
mp_clear_multi(&tmp, &g, &p, NULL);
return err;
}
void dh_sizes(int *low, int *high)
{
int x;
_ARGCHK(low != NULL);
_ARGCHK(high != NULL);
*low = INT_MAX;
*high = 0;
for (x = 0; sets[x].size != 0; x++) {
if (*low > sets[x].size) *low = sets[x].size;
if (*high < sets[x].size) *high = sets[x].size;
}
}
int dh_get_size(dh_key *key)
{
_ARGCHK(key != NULL);
if (is_valid_idx(key->idx) == 1) {
return sets[key->idx].size;
} else {
return INT_MAX; /* large value that would cause dh_make_key() to fail */
}
}
int dh_make_key(prng_state *prng, int wprng, int keysize, dh_key *key)
{
unsigned char buf[512];
unsigned long x;
mp_int p, g;
int err;
_ARGCHK(key != NULL);
/* good prng? */
if ((err = prng_is_valid(wprng)) != CRYPT_OK) {
return err;
}
/* find key size */
for (x = 0; (keysize > sets[x].size) && (sets[x].size != 0); x++);
#ifdef FAST_PK
keysize = MIN(sets[x].size, 32);
#else
keysize = sets[x].size;
#endif
if (sets[x].size == 0) {
return CRYPT_INVALID_KEYSIZE;
}
key->idx = x;
/* make up random string */
if (prng_descriptor[wprng].read(buf, keysize, prng) != (unsigned long)keysize) {
return CRYPT_ERROR_READPRNG;
}
/* init parameters */
if ((err = mp_init_multi(&g, &p, &key->x, &key->y, NULL)) != MP_OKAY) {
return mpi_to_ltc_error(err);
}
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; }
/* load the x value */
if ((err = mp_read_unsigned_bin(&key->x, buf, keysize)) != MP_OKAY) { goto error; }
if ((err = mp_exptmod(&g, &key->x, &p, &key->y)) != MP_OKAY) { goto error; }
key->type = PK_PRIVATE;
if ((err = mp_shrink(&key->x)) != MP_OKAY) { goto error; }
if ((err = mp_shrink(&key->y)) != MP_OKAY) { goto error; }
/* free up ram */
err = CRYPT_OK;
goto done;
error:
err = mpi_to_ltc_error(err);
mp_clear_multi(&key->x, &key->y, NULL);
done:
mp_clear_multi(&p, &g, NULL);
zeromem(buf, sizeof(buf));
return err;
}
void dh_free(dh_key *key)
{
_ARGCHK(key != NULL);
mp_clear_multi(&key->x, &key->y, NULL);
}
int dh_export(unsigned char *out, unsigned long *outlen, int type, dh_key *key)
{
unsigned long y, z;
int err;
_ARGCHK(out != NULL);
_ARGCHK(outlen != NULL);
_ARGCHK(key != NULL);
/* can we store the static header? */
if (*outlen < (PACKET_SIZE + 2)) {
return CRYPT_BUFFER_OVERFLOW;
}
if (type == PK_PRIVATE && key->type != PK_PRIVATE) {
return CRYPT_PK_NOT_PRIVATE;
}
/* header */
y = PACKET_SIZE;
/* header */
out[y++] = type;
out[y++] = (unsigned char)(sets[key->idx].size / 8);
/* export y */
OUTPUT_BIGNUM(&key->y, out, y, z);
if (type == PK_PRIVATE) {
/* export x */
OUTPUT_BIGNUM(&key->x, out, y, z);
}
/* store header */
packet_store_header(out, PACKET_SECT_DH, PACKET_SUB_KEY);
/* store len */
*outlen = y;
return CRYPT_OK;
}
int dh_import(const unsigned char *in, unsigned long inlen, dh_key *key)
{
unsigned long x, y, s;
int err;
_ARGCHK(in != NULL);
_ARGCHK(key != NULL);
/* make sure valid length */
if ((2+PACKET_SIZE) > inlen) {
return CRYPT_INVALID_PACKET;
}
/* check type byte */
if ((err = packet_valid_header((unsigned char *)in, PACKET_SECT_DH, PACKET_SUB_KEY)) != CRYPT_OK) {
return err;
}
/* init */
if ((err = mp_init_multi(&key->x, &key->y, NULL)) != MP_OKAY) {
return mpi_to_ltc_error(err);
}
/* advance past packet header */
y = PACKET_SIZE;
/* key type, e.g. private, public */
key->type = (int)in[y++];
/* key size in bytes */
s = (unsigned long)in[y++] * 8;
for (x = 0; (s > (unsigned long)sets[x].size) && (sets[x].size != 0); x++);
if (sets[x].size == 0) {
err = CRYPT_INVALID_KEYSIZE;
goto error;
}
key->idx = (int)x;
/* type check both values */
if ((key->type != PK_PUBLIC) && (key->type != PK_PRIVATE)) {
err = CRYPT_PK_TYPE_MISMATCH;
goto error;
}
/* is the key idx valid? */
if (is_valid_idx(key->idx) != 1) {
err = CRYPT_PK_TYPE_MISMATCH;
goto error;
}
/* load public value g^x mod p*/
INPUT_BIGNUM(&key->y, in, x, y, inlen);
if (key->type == PK_PRIVATE) {
INPUT_BIGNUM(&key->x, in, x, y, inlen);
}
/* eliminate private key if public */
if (key->type == PK_PUBLIC) {
mp_clear(&key->x);
}
return CRYPT_OK;
error:
mp_clear_multi(&key->y, &key->x, NULL);
return err;
}
int dh_shared_secret(dh_key *private_key, dh_key *public_key,
unsigned char *out, unsigned long *outlen)
{
mp_int tmp, p;
unsigned long x;
int err;
_ARGCHK(private_key != NULL);
_ARGCHK(public_key != NULL);
_ARGCHK(out != NULL);
_ARGCHK(outlen != NULL);
/* types valid? */
if (private_key->type != PK_PRIVATE) {
return CRYPT_PK_NOT_PRIVATE;
}
/* same idx? */
if (private_key->idx != public_key->idx) {
return CRYPT_PK_TYPE_MISMATCH;
}
/* compute y^x mod p */
if ((err = mp_init_multi(&tmp, &p, NULL)) != MP_OKAY) {
return mpi_to_ltc_error(err);
}
if ((err = mp_read_radix(&p, (char *)sets[private_key->idx].prime, 64)) != MP_OKAY) { goto error; }
if ((err = mp_exptmod(&public_key->y, &private_key->x, &p, &tmp)) != MP_OKAY) { goto error; }
/* enough space for output? */
x = (unsigned long)mp_unsigned_bin_size(&tmp);
if (*outlen < x) {
err = CRYPT_BUFFER_OVERFLOW;
goto done;
}
if ((err = mp_to_unsigned_bin(&tmp, out)) != MP_OKAY) { goto error; }
*outlen = x;
err = CRYPT_OK;
goto done;
error:
err = mpi_to_ltc_error(err);
done:
mp_clear_multi(&p, &tmp, NULL);
return err;
}
#include "dh_sys.c"
#endif

399
dh_sys.c Normal file
View File

@@ -0,0 +1,399 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
*
* LibTomCrypt is a library that provides various cryptographic
* algorithms in a highly modular and flexible manner.
*
* The library is free for all purposes without any express
* guarantee it works.
*
* Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org
*/
int dh_encrypt_key(const unsigned char *inkey, unsigned long keylen,
unsigned char *out, unsigned long *len,
prng_state *prng, int wprng, int hash,
dh_key *key)
{
unsigned char pub_expt[768], dh_shared[768], skey[MAXBLOCKSIZE];
dh_key pubkey;
unsigned long x, y, z, hashsize, pubkeysize;
int err;
_ARGCHK(inkey != NULL);
_ARGCHK(out != NULL);
_ARGCHK(len != NULL);
_ARGCHK(key != NULL);
/* check that wprng/hash are not invalid */
if ((err = prng_is_valid(wprng)) != CRYPT_OK) {
return err;
}
if ((err = hash_is_valid(hash)) != CRYPT_OK) {
return err;
}
if (keylen > hash_descriptor[hash].hashsize) {
return CRYPT_INVALID_HASH;
}
/* make a random key and export the public copy */
if ((err = dh_make_key(prng, wprng, dh_get_size(key), &pubkey)) != CRYPT_OK) {
return err;
}
pubkeysize = sizeof(pub_expt);
if ((err = dh_export(pub_expt, &pubkeysize, PK_PUBLIC, &pubkey)) != CRYPT_OK) {
dh_free(&pubkey);
return err;
}
/* now check if the out buffer is big enough */
if (*len < (1 + 4 + 4 + PACKET_SIZE + pubkeysize + keylen)) {
dh_free(&pubkey);
return CRYPT_BUFFER_OVERFLOW;
}
/* make random key */
hashsize = hash_descriptor[hash].hashsize;
x = (unsigned long)sizeof(dh_shared);
if ((err = dh_shared_secret(&pubkey, key, dh_shared, &x)) != CRYPT_OK) {
dh_free(&pubkey);
return err;
}
dh_free(&pubkey);
z = sizeof(skey);
if ((err = hash_memory(hash, dh_shared, x, skey, &z)) != CRYPT_OK) {
return err;
}
/* store header */
packet_store_header(out, PACKET_SECT_DH, PACKET_SUB_ENC_KEY);
/* output header */
y = PACKET_SIZE;
/* size of hash name and the name itself */
out[y++] = hash_descriptor[hash].ID;
/* length of DH pubkey and the key itself */
STORE32L(pubkeysize, out+y);
y += 4;
for (x = 0; x < pubkeysize; x++, y++) {
out[y] = pub_expt[x];
}
/* Store the encrypted key */
STORE32L(keylen, out+y);
y += 4;
for (x = 0; x < keylen; x++, y++) {
out[y] = skey[x] ^ inkey[x];
}
*len = y;
#ifdef CLEAN_STACK
/* clean up */
zeromem(pub_expt, sizeof(pub_expt));
zeromem(dh_shared, sizeof(dh_shared));
zeromem(skey, sizeof(skey));
#endif
return CRYPT_OK;
}
int dh_decrypt_key(const unsigned char *in, unsigned long inlen,
unsigned char *outkey, unsigned long *keylen,
dh_key *key)
{
unsigned char shared_secret[768], skey[MAXBLOCKSIZE];
unsigned long x, y, z,hashsize, keysize;
int hash, err;
dh_key pubkey;
_ARGCHK(in != NULL);
_ARGCHK(outkey != NULL);
_ARGCHK(keylen != NULL);
_ARGCHK(key != NULL);
/* right key type? */
if (key->type != PK_PRIVATE) {
return CRYPT_PK_NOT_PRIVATE;
}
/* check if initial header should fit */
if (inlen < PACKET_SIZE+1+4+4) {
return CRYPT_INVALID_PACKET;
} else {
inlen -= PACKET_SIZE+1+4+4;
}
/* is header correct? */
if ((err = packet_valid_header((unsigned char *)in, PACKET_SECT_DH, PACKET_SUB_ENC_KEY)) != CRYPT_OK) {
return err;
}
/* now lets get the hash name */
y = PACKET_SIZE;
hash = find_hash_id(in[y++]);
if (hash == -1) {
return CRYPT_INVALID_HASH;
}
/* common values */
hashsize = hash_descriptor[hash].hashsize;
/* get public key */
LOAD32L(x, in+y);
/* now check if the imported key will fit */
if (inlen < x) {
return CRYPT_INVALID_PACKET;
} else {
inlen -= x;
}
y += 4;
if ((err = dh_import(in+y, x, &pubkey)) != CRYPT_OK) {
return err;
}
y += x;
/* make shared key */
x = (unsigned long)sizeof(shared_secret);
if ((err = dh_shared_secret(key, &pubkey, shared_secret, &x)) != CRYPT_OK) {
dh_free(&pubkey);
return err;
}
dh_free(&pubkey);
z = sizeof(skey);
if ((err = hash_memory(hash, shared_secret, x, skey, &z)) != CRYPT_OK) {
return err;
}
/* load in the encrypted key */
LOAD32L(keysize, in+y);
/* will the outkey fit as part of the input */
if (inlen < keysize) {
return CRYPT_INVALID_PACKET;
} else {
inlen -= keysize;
}
if (keysize > *keylen) {
err = CRYPT_BUFFER_OVERFLOW;
goto done;
}
y += 4;
*keylen = keysize;
for (x = 0; x < keysize; x++, y++) {
outkey[x] = skey[x] ^ in[y];
}
err = CRYPT_OK;
done:
#ifdef CLEAN_STACK
zeromem(shared_secret, sizeof(shared_secret));
zeromem(skey, sizeof(skey));
#endif
return err;
}
/* perform an ElGamal Signature of a hash
*
* The math works as follows. x is the private key, M is the message to sign
1. pick a random k
2. compute a = g^k mod p
3. compute b = (M - xa)/k mod p
4. Send (a,b)
Now to verify with y=g^x mod p, a and b
1. compute y^a * a^b = g^(xa) * g^(k*(M-xa)/k)
= g^(xa + (M - xa))
= g^M [all mod p]
2. Compare against g^M mod p [based on input hash].
3. If result of #2 == result of #1 then signature valid
*/
int dh_sign_hash(const unsigned char *in, unsigned long inlen,
unsigned char *out, unsigned long *outlen,
prng_state *prng, int wprng, dh_key *key)
{
mp_int a, b, k, m, g, p, p1, tmp;
unsigned char buf[520];
unsigned long x, y;
int err;
_ARGCHK(in != NULL);
_ARGCHK(out != NULL);
_ARGCHK(outlen != NULL);
_ARGCHK(key != NULL);
/* check parameters */
if (key->type != PK_PRIVATE) {
return CRYPT_PK_NOT_PRIVATE;
}
if ((err = prng_is_valid(wprng)) != CRYPT_OK) {
return err;
}
/* is the IDX valid ? */
if (is_valid_idx(key->idx) != 1) {
return CRYPT_PK_INVALID_TYPE;
}
/* make up a random value k,
* since the order of the group is prime
* we need not check if gcd(k, r) is 1
*/
if (prng_descriptor[wprng].read(buf, sets[key->idx].size, prng) !=
(unsigned long)(sets[key->idx].size)) {
return CRYPT_ERROR_READPRNG;
}
/* init bignums */
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 ((err = mp_read_unsigned_bin(&m, (unsigned char *)in, inlen)) != MP_OKAY) { goto error; }
#ifdef FAST_PK
if ((err = mp_read_unsigned_bin(&k, buf, MIN(32,sets[key->idx].size))) != MP_OKAY) { goto error; }
#else
if ((err = mp_read_unsigned_bin(&k, buf, sets[key->idx].size)) != MP_OKAY) { goto error; }
#endif
/* load g, p and p1 */
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 ((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 ((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 */
/* check for overflow */
if ((unsigned long)(PACKET_SIZE + 4 + 4 + mp_unsigned_bin_size(&a) + mp_unsigned_bin_size(&b)) > *outlen) {
err = CRYPT_BUFFER_OVERFLOW;
goto done;
}
/* store header */
y = PACKET_SIZE;
/* now store them both (a,b) */
x = (unsigned long)mp_unsigned_bin_size(&a);
STORE32L(x, out+y); y += 4;
if ((err = mp_to_unsigned_bin(&a, out+y)) != MP_OKAY) { goto error; }
y += x;
x = (unsigned long)mp_unsigned_bin_size(&b);
STORE32L(x, out+y); y += 4;
if ((err = mp_to_unsigned_bin(&b, out+y)) != MP_OKAY) { goto error; }
y += x;
/* check if size too big */
if (*outlen < y) {
err = CRYPT_BUFFER_OVERFLOW;
goto done;
}
/* store header */
packet_store_header(out, PACKET_SECT_DH, PACKET_SUB_SIGNED);
*outlen = y;
err = CRYPT_OK;
goto done;
error:
err = mpi_to_ltc_error(err);
done:
mp_clear_multi(&tmp, &p1, &g, &p, &m, &k, &b, &a, NULL);
return err;
}
/* verify the signature in sig of the given hash */
int dh_verify_hash(const unsigned char *sig, unsigned long siglen,
const unsigned char *hash, unsigned long hashlen,
int *stat, dh_key *key)
{
mp_int a, b, p, g, m, tmp;
unsigned long x, y;
int err;
_ARGCHK(sig != NULL);
_ARGCHK(hash != NULL);
_ARGCHK(stat != NULL);
_ARGCHK(key != NULL);
/* default to invalid */
*stat = 0;
/* check initial input length */
if (siglen < PACKET_SIZE+4+4) {
return CRYPT_INVALID_PACKET;
}
/* header ok? */
if ((err = packet_valid_header((unsigned char *)sig, PACKET_SECT_DH, PACKET_SUB_SIGNED)) != CRYPT_OK) {
return err;
}
/* get hash out of packet */
y = PACKET_SIZE;
/* init all bignums */
if ((err = mp_init_multi(&a, &p, &b, &g, &m, &tmp, NULL)) != MP_OKAY) {
return mpi_to_ltc_error(err);
}
/* load a and b */
INPUT_BIGNUM(&a, sig, x, y, siglen);
INPUT_BIGNUM(&b, sig, x, y, siglen);
/* load p and g */
if ((err = mp_read_radix(&p, sets[key->idx].prime, 64)) != MP_OKAY) { goto error1; }
if ((err = mp_read_radix(&g, sets[key->idx].base, 64)) != MP_OKAY) { goto error1; }
/* load m */
if ((err = mp_read_unsigned_bin(&m, (unsigned char *)hash, hashlen)) != MP_OKAY) { goto error1; }
/* find g^m mod p */
if ((err = mp_exptmod(&g, &m, &p, &m)) != MP_OKAY) { goto error1; } /* m = g^m mod p */
/* find y^a * a^b */
if ((err = mp_exptmod(&key->y, &a, &p, &tmp)) != MP_OKAY) { goto error1; } /* tmp = y^a mod p */
if ((err = mp_exptmod(&a, &b, &p, &a)) != MP_OKAY) { goto error1; } /* a = a^b mod p */
if ((err = mp_mulmod(&a, &tmp, &p, &a)) != MP_OKAY) { goto error1; } /* a = y^a * a^b mod p */
/* y^a * a^b == g^m ??? */
if (mp_cmp(&a, &m) == 0) {
*stat = 1;
}
/* clean up */
err = CRYPT_OK;
goto done;
error1:
err = mpi_to_ltc_error(err);
error:
done:
mp_clear_multi(&tmp, &m, &g, &p, &b, &a, NULL);
return err;
}

62
dsa_export.c Normal file
View File

@@ -0,0 +1,62 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
*
* LibTomCrypt is a library that provides various cryptographic
* algorithms in a highly modular and flexible manner.
*
* The library is free for all purposes without any express
* guarantee it works.
*
* Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org
*/
#include "mycrypt.h"
#ifdef MDSA
int dsa_export(unsigned char *out, unsigned long *outlen, int type, dsa_key *key)
{
unsigned long y, z;
int err;
_ARGCHK(out != NULL);
_ARGCHK(outlen != NULL);
_ARGCHK(key != NULL);
/* can we store the static header? */
if (*outlen < (PACKET_SIZE + 1 + 2)) {
return CRYPT_BUFFER_OVERFLOW;
}
if (type == PK_PRIVATE && key->type != PK_PRIVATE) {
return CRYPT_PK_TYPE_MISMATCH;
}
if (type != PK_PUBLIC && type != PK_PRIVATE) {
return CRYPT_INVALID_ARG;
}
/* 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;
}
#endif

21
dsa_free.c Normal file
View File

@@ -0,0 +1,21 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
*
* LibTomCrypt is a library that provides various cryptographic
* algorithms in a highly modular and flexible manner.
*
* The library is free for all purposes without any express
* guarantee it works.
*
* Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org
*/
#include "mycrypt.h"
#ifdef MDSA
void dsa_free(dsa_key *key)
{
_ARGCHK(key != NULL);
mp_clear_multi(&key->g, &key->q, &key->p, &key->x, &key->y, NULL);
}
#endif

59
dsa_import.c Normal file
View File

@@ -0,0 +1,59 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
*
* LibTomCrypt is a library that provides various cryptographic
* algorithms in a highly modular and flexible manner.
*
* The library is free for all purposes without any express
* guarantee it works.
*
* Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org
*/
#include "mycrypt.h"
#ifdef MDSA
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, inlen);
INPUT_BIGNUM(&key->p,in,x,y, inlen);
INPUT_BIGNUM(&key->q,in,x,y, inlen);
INPUT_BIGNUM(&key->y,in,x,y, inlen);
if (key->type == PK_PRIVATE) {
INPUT_BIGNUM(&key->x,in,x,y, inlen);
}
return CRYPT_OK;
error:
mp_clear_multi(&key->p, &key->g, &key->q, &key->x, &key->y, NULL);
return err;
}
#endif

117
dsa_make_key.c Normal file
View File

@@ -0,0 +1,117 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
*
* LibTomCrypt is a library that provides various cryptographic
* algorithms in a highly modular and flexible manner.
*
* The library is free for all purposes without any express
* guarantee it works.
*
* Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org
*/
#include "mycrypt.h"
#ifdef MDSA
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(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*8, 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+1, modulus_size - group_size, prng) != (unsigned long)(modulus_size - group_size)) {
err = CRYPT_ERROR_READPRNG;
goto error2;
}
/* force magnitude */
buf[0] = 1;
/* force even */
buf[modulus_size - group_size] &= ~1;
if ((err = mp_read_unsigned_bin(&tmp2, buf, modulus_size - group_size+1)) != 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;
}
#endif

125
dsa_sign_hash.c Normal file
View File

@@ -0,0 +1,125 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
*
* LibTomCrypt is a library that provides various cryptographic
* algorithms in a highly modular and flexible manner.
*
* The library is free for all purposes without any express
* guarantee it works.
*
* Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org
*/
#include "mycrypt.h"
#ifdef MDSA
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(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:
do {
/* 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; }
/* k > 1 ? */
if (mp_cmp_d(&k, 1) != MP_GT) { goto retry; }
/* test gcd */
if ((err = mp_gcd(&k, &key->q, &tmp)) != MP_OKAY) { goto error; }
} while (mp_cmp_d(&tmp, 1) != MP_EQ);
/* 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 */
if ((err = mp_to_unsigned_bin(&r, out+y)) != MP_OKAY) { goto error; }
y += len;
/* store length of s */
len = mp_unsigned_bin_size(&s);
out[y++] = (len>>8)&255;
out[y++] = len&255;
/* store s */
if ((err = mp_to_unsigned_bin(&s, out+y)) != MP_OKAY) { goto error; }
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;
}
#endif

97
dsa_verify_hash.c Normal file
View File

@@ -0,0 +1,97 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
*
* LibTomCrypt is a library that provides various cryptographic
* algorithms in a highly modular and flexible manner.
*
* The library is free for all purposes without any express
* guarantee it works.
*
* Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org
*/
#include "mycrypt.h"
#ifdef MDSA
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;
}
#endif

86
dsa_verify_key.c Normal file
View File

@@ -0,0 +1,86 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
*
* LibTomCrypt is a library that provides various cryptographic
* algorithms in a highly modular and flexible manner.
*
* The library is free for all purposes without any express
* guarantee it works.
*
* Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org
*/
#include "mycrypt.h"
#ifdef MDSA
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

25
eax_addheader.c Normal file
View File

@@ -0,0 +1,25 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
*
* LibTomCrypt is a library that provides various cryptographic
* algorithms in a highly modular and flexible manner.
*
* The library is free for all purposes without any express
* guarantee it works.
*
* Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org
*/
/* EAX Implementation by Tom St Denis */
#include "mycrypt.h"
#ifdef EAX_MODE
/* add header (metadata) to the stream */
int eax_addheader(eax_state *eax, const unsigned char *header, unsigned long length)
{
_ARGCHK(eax != NULL);
_ARGCHK(header != NULL);
return omac_process(&eax->headeromac, header, length);
}
#endif

34
eax_decrypt.c Normal file
View File

@@ -0,0 +1,34 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
*
* LibTomCrypt is a library that provides various cryptographic
* algorithms in a highly modular and flexible manner.
*
* The library is free for all purposes without any express
* guarantee it works.
*
* Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org
*/
/* EAX Implementation by Tom St Denis */
#include "mycrypt.h"
#ifdef EAX_MODE
int eax_decrypt(eax_state *eax, const unsigned char *ct, unsigned char *pt, unsigned long length)
{
int err;
_ARGCHK(eax != NULL);
_ARGCHK(pt != NULL);
_ARGCHK(ct != NULL);
/* omac ciphertext */
if ((err = omac_process(&eax->ctomac, ct, length)) != CRYPT_OK) {
return err;
}
/* decrypt */
return ctr_decrypt(ct, pt, length, &eax->ctr);
}
#endif

View File

@@ -0,0 +1,60 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
*
* LibTomCrypt is a library that provides various cryptographic
* algorithms in a highly modular and flexible manner.
*
* The library is free for all purposes without any express
* guarantee it works.
*
* Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org
*/
/* EAX Implementation by Tom St Denis */
#include "mycrypt.h"
#ifdef EAX_MODE
int eax_decrypt_verify_memory(int cipher,
const unsigned char *key, unsigned long keylen,
const unsigned char *nonce, unsigned long noncelen,
const unsigned char *header, unsigned long headerlen,
const unsigned char *ct, unsigned long ctlen,
unsigned char *pt,
unsigned char *tag, unsigned long taglen,
int *res)
{
int err;
eax_state eax;
unsigned char buf[MAXBLOCKSIZE];
unsigned long buflen;
_ARGCHK(res != NULL);
/* default to zero */
*res = 0;
if ((err = eax_init(&eax, cipher, key, keylen, nonce, noncelen, header, headerlen)) != CRYPT_OK) {
return err;
}
if ((err = eax_decrypt(&eax, ct, pt, ctlen)) != CRYPT_OK) {
return err;
}
buflen = MIN(sizeof(buf), taglen);
if ((err = eax_done(&eax, buf, &buflen)) != CRYPT_OK) {
return err;
}
/* compare tags */
if (buflen >= taglen && memcmp(buf, tag, taglen) == 0) {
*res = 1;
}
#ifdef CLEAN_STACK
zeromem(buf, sizeof(buf));
#endif
return CRYPT_OK;
}
#endif

56
eax_done.c Normal file
View File

@@ -0,0 +1,56 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
*
* LibTomCrypt is a library that provides various cryptographic
* algorithms in a highly modular and flexible manner.
*
* The library is free for all purposes without any express
* guarantee it works.
*
* Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org
*/
/* EAX Implementation by Tom St Denis */
#include "mycrypt.h"
#ifdef EAX_MODE
int eax_done(eax_state *eax, unsigned char *tag, unsigned long *taglen)
{
int err;
unsigned char headermac[MAXBLOCKSIZE], ctmac[MAXBLOCKSIZE];
unsigned long x, len;
_ARGCHK(eax != NULL);
_ARGCHK(tag != NULL);
_ARGCHK(taglen != NULL);
/* finish ctomac */
len = sizeof(ctmac);
if ((err = omac_done(&eax->ctomac, ctmac, &len)) != CRYPT_OK) {
return err;
}
/* finish headeromac */
/* note we specifically don't reset len so the two lens are minimal */
if ((err = omac_done(&eax->headeromac, headermac, &len)) != CRYPT_OK) {
return err;
}
/* compute N xor H xor C */
for (x = 0; x < len && x < *taglen; x++) {
tag[x] = eax->N[x] ^ headermac[x] ^ ctmac[x];
}
*taglen = x;
#ifdef CLEAN_STACK
zeromem(ctmac, sizeof(ctmac));
zeromem(headermac, sizeof(headermac));
zeromem(eax, sizeof(*eax));
#endif
return CRYPT_OK;
}
#endif

35
eax_encrypt.c Normal file
View File

@@ -0,0 +1,35 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
*
* LibTomCrypt is a library that provides various cryptographic
* algorithms in a highly modular and flexible manner.
*
* The library is free for all purposes without any express
* guarantee it works.
*
* Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org
*/
/* EAX Implementation by Tom St Denis */
#include "mycrypt.h"
#ifdef EAX_MODE
int eax_encrypt(eax_state *eax, const unsigned char *pt, unsigned char *ct, unsigned long length)
{
int err;
_ARGCHK(eax != NULL);
_ARGCHK(pt != NULL);
_ARGCHK(ct != NULL);
/* encrypt */
if ((err = ctr_encrypt(pt, ct, length, &eax->ctr)) != CRYPT_OK) {
return err;
}
/* omac ciphertext */
return omac_process(&eax->ctomac, ct, length);
}
#endif

View File

@@ -0,0 +1,43 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
*
* LibTomCrypt is a library that provides various cryptographic
* algorithms in a highly modular and flexible manner.
*
* The library is free for all purposes without any express
* guarantee it works.
*
* Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org
*/
/* EAX Implementation by Tom St Denis */
#include "mycrypt.h"
#ifdef EAX_MODE
int eax_encrypt_authenticate_memory(int cipher,
const unsigned char *key, unsigned long keylen,
const unsigned char *nonce, unsigned long noncelen,
const unsigned char *header, unsigned long headerlen,
const unsigned char *pt, unsigned long ptlen,
unsigned char *ct,
unsigned char *tag, unsigned long *taglen)
{
int err;
eax_state eax;
if ((err = eax_init(&eax, cipher, key, keylen, nonce, noncelen, header, headerlen)) != CRYPT_OK) {
return err;
}
if ((err = eax_encrypt(&eax, pt, ct, ptlen)) != CRYPT_OK) {
return err;
}
if ((err = eax_done(&eax, tag, taglen)) != CRYPT_OK) {
return err;
}
return CRYPT_OK;
}
#endif

106
eax_init.c Normal file
View File

@@ -0,0 +1,106 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
*
* LibTomCrypt is a library that provides various cryptographic
* algorithms in a highly modular and flexible manner.
*
* The library is free for all purposes without any express
* guarantee it works.
*
* Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org
*/
/* EAX Implementation by Tom St Denis */
#include "mycrypt.h"
#ifdef EAX_MODE
int eax_init(eax_state *eax, int cipher, const unsigned char *key, unsigned long keylen,
const unsigned char *nonce, unsigned long noncelen,
const unsigned char *header, unsigned long headerlen)
{
unsigned char buf[MAXBLOCKSIZE];
int err, blklen;
omac_state omac;
unsigned long len;
_ARGCHK(eax != NULL);
_ARGCHK(key != NULL);
_ARGCHK(nonce != NULL);
if (headerlen > 0) {
_ARGCHK(header != NULL);
}
if ((err = cipher_is_valid(cipher)) != CRYPT_OK) {
return err;
}
blklen = cipher_descriptor[cipher].block_length;
/* N = OMAC_0K(nonce) */
zeromem(buf, sizeof(buf));
if ((err = omac_init(&omac, cipher, key, keylen)) != CRYPT_OK) {
return err;
}
/* omac the [0]_n */
if ((err = omac_process(&omac, buf, blklen)) != CRYPT_OK) {
return err;
}
/* omac the nonce */
if ((err = omac_process(&omac, nonce, noncelen)) != CRYPT_OK) {
return err;
}
/* store result */
len = sizeof(eax->N);
if ((err = omac_done(&omac, eax->N, &len)) != CRYPT_OK) {
return err;
}
/* H = OMAC_1K(header) */
zeromem(buf, sizeof(buf));
buf[blklen - 1] = 1;
if ((err = omac_init(&eax->headeromac, cipher, key, keylen)) != CRYPT_OK) {
return err;
}
/* omac the [1]_n */
if ((err = omac_process(&eax->headeromac, buf, blklen)) != CRYPT_OK) {
return err;
}
/* omac the header */
if (headerlen != 0) {
if ((err = omac_process(&eax->headeromac, header, headerlen)) != CRYPT_OK) {
return err;
}
}
/* note we don't finish the headeromac, this allows us to add more header later */
/* setup the CTR mode */
if ((err = ctr_start(cipher, eax->N, key, keylen, 0, &eax->ctr)) != CRYPT_OK) {
return err;
}
/* use big-endian counter */
eax->ctr.mode = 1;
/* setup the OMAC for the ciphertext */
if ((err = omac_init(&eax->ctomac, cipher, key, keylen)) != CRYPT_OK) {
return err;
}
/* omac [2]_n */
zeromem(buf, sizeof(buf));
buf[blklen-1] = 2;
if ((err = omac_process(&eax->ctomac, buf, blklen)) != CRYPT_OK) {
return err;
}
#ifdef CLEAN_STACK
zeromem(buf, sizeof(buf));
zeromem(&omac, sizeof(omac));
#endif
return CRYPT_OK;
}
#endif

271
eax_test.c Normal file
View File

@@ -0,0 +1,271 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
*
* LibTomCrypt is a library that provides various cryptographic
* algorithms in a highly modular and flexible manner.
*
* The library is free for all purposes without any express
* guarantee it works.
*
* Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org
*/
/* EAX Implementation by Tom St Denis */
#include "mycrypt.h"
#ifdef EAX_MODE
int eax_test(void)
{
#ifndef LTC_TEST
return CRYPT_NOP;
#else
static const struct {
int keylen,
noncelen,
headerlen,
msglen;
unsigned char key[MAXBLOCKSIZE],
nonce[MAXBLOCKSIZE],
header[MAXBLOCKSIZE],
plaintext[MAXBLOCKSIZE],
ciphertext[MAXBLOCKSIZE],
tag[MAXBLOCKSIZE];
} tests[] = {
/* NULL message */
{
16, 0, 0, 0,
/* key */
{ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
/* nonce */
{ 0 },
/* header */
{ 0 },
/* plaintext */
{ 0 },
/* ciphertext */
{ 0 },
/* tag */
{ 0x9a, 0xd0, 0x7e, 0x7d, 0xbf, 0xf3, 0x01, 0xf5,
0x05, 0xde, 0x59, 0x6b, 0x96, 0x15, 0xdf, 0xff }
},
/* test with nonce */
{
16, 16, 0, 0,
/* key */
{ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
/* nonce */
{ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
/* header */
{ 0 },
/* plaintext */
{ 0 },
/* ciphertext */
{ 0 },
/* tag */
{ 0x1c, 0xe1, 0x0d, 0x3e, 0xff, 0xd4, 0xca, 0xdb,
0xe2, 0xe4, 0x4b, 0x58, 0xd6, 0x0a, 0xb9, 0xec }
},
/* test with header [no nonce] */
{
16, 0, 16, 0,
/* key */
{ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
/* nonce */
{ 0 },
/* header */
{ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
/* plaintext */
{ 0 },
/* ciphertext */
{ 0 },
/* tag */
{ 0x3a, 0x69, 0x8f, 0x7a, 0x27, 0x0e, 0x51, 0xb0,
0xf6, 0x5b, 0x3d, 0x3e, 0x47, 0x19, 0x3c, 0xff }
},
/* test with header + nonce + plaintext */
{
16, 16, 16, 32,
/* key */
{ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
/* nonce */
{ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
/* header */
{ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
/* plaintext */
{ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f },
/* ciphertext */
{ 0x29, 0xd8, 0x78, 0xd1, 0xa3, 0xbe, 0x85, 0x7b,
0x6f, 0xb8, 0xc8, 0xea, 0x59, 0x50, 0xa7, 0x78,
0x33, 0x1f, 0xbf, 0x2c, 0xcf, 0x33, 0x98, 0x6f,
0x35, 0xe8, 0xcf, 0x12, 0x1d, 0xcb, 0x30, 0xbc },
/* tag */
{ 0x4f, 0xbe, 0x03, 0x38, 0xbe, 0x1c, 0x8c, 0x7e,
0x1d, 0x7a, 0xe7, 0xe4, 0x5b, 0x92, 0xc5, 0x87 }
},
/* test with header + nonce + plaintext [not even sizes!] */
{
16, 15, 14, 29,
/* key */
{ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
/* nonce */
{ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e },
/* header */
{ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d },
/* plaintext */
{ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1a, 0x1b, 0x1c },
/* ciphertext */
{ 0xdd, 0x25, 0xc7, 0x54, 0xc5, 0xb1, 0x7c, 0x59,
0x28, 0xb6, 0x9b, 0x73, 0x15, 0x5f, 0x7b, 0xb8,
0x88, 0x8f, 0xaf, 0x37, 0x09, 0x1a, 0xd9, 0x2c,
0x8a, 0x24, 0xdb, 0x86, 0x8b },
/* tag */
{ 0x0d, 0x1a, 0x14, 0xe5, 0x22, 0x24, 0xff, 0xd2,
0x3a, 0x05, 0xfa, 0x02, 0xcd, 0xef, 0x52, 0xda }
},
/* Vectors from Brian Gladman */
{
16, 16, 8, 0,
/* key */
{ 0x23, 0x39, 0x52, 0xde, 0xe4, 0xd5, 0xed, 0x5f,
0x9b, 0x9c, 0x6d, 0x6f, 0xf8, 0x0f, 0xf4, 0x78 },
/* nonce */
{ 0x62, 0xec, 0x67, 0xf9, 0xc3, 0xa4, 0xa4, 0x07,
0xfc, 0xb2, 0xa8, 0xc4, 0x90, 0x31, 0xa8, 0xb3 },
/* header */
{ 0x6b, 0xfb, 0x91, 0x4f, 0xd0, 0x7e, 0xae, 0x6b },
/* PT */
{ 0x00 },
/* CT */
{ 0x00 },
/* tag */
{ 0xe0, 0x37, 0x83, 0x0e, 0x83, 0x89, 0xf2, 0x7b,
0x02, 0x5a, 0x2d, 0x65, 0x27, 0xe7, 0x9d, 0x01 }
},
{
16, 16, 8, 2,
/* key */
{ 0x91, 0x94, 0x5d, 0x3f, 0x4d, 0xcb, 0xee, 0x0b,
0xf4, 0x5e, 0xf5, 0x22, 0x55, 0xf0, 0x95, 0xa4 },
/* nonce */
{ 0xbe, 0xca, 0xf0, 0x43, 0xb0, 0xa2, 0x3d, 0x84,
0x31, 0x94, 0xba, 0x97, 0x2c, 0x66, 0xde, 0xbd },
/* header */
{ 0xfa, 0x3b, 0xfd, 0x48, 0x06, 0xeb, 0x53, 0xfa },
/* PT */
{ 0xf7, 0xfb },
/* CT */
{ 0x19, 0xdd },
/* tag */
{ 0x5c, 0x4c, 0x93, 0x31, 0x04, 0x9d, 0x0b, 0xda,
0xb0, 0x27, 0x74, 0x08, 0xf6, 0x79, 0x67, 0xe5 }
},
{
16, 16, 8, 5,
/* key */
{ 0x01, 0xf7, 0x4a, 0xd6, 0x40, 0x77, 0xf2, 0xe7,
0x04, 0xc0, 0xf6, 0x0a, 0xda, 0x3d, 0xd5, 0x23 },
/* nonce */
{ 0x70, 0xc3, 0xdb, 0x4f, 0x0d, 0x26, 0x36, 0x84,
0x00, 0xa1, 0x0e, 0xd0, 0x5d, 0x2b, 0xff, 0x5e },
/* header */
{ 0x23, 0x4a, 0x34, 0x63, 0xc1, 0x26, 0x4a, 0xc6 },
/* PT */
{ 0x1a, 0x47, 0xcb, 0x49, 0x33 },
/* CT */
{ 0xd8, 0x51, 0xd5, 0xba, 0xe0 },
/* Tag */
{ 0x3a, 0x59, 0xf2, 0x38, 0xa2, 0x3e, 0x39, 0x19,
0x9d, 0xc9, 0x26, 0x66, 0x26, 0xc4, 0x0f, 0x80 }
}
};
int err, x, idx, res;
unsigned long len;
unsigned char outct[MAXBLOCKSIZE], outtag[MAXBLOCKSIZE];
/* 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;
}
}
for (x = 0; x < (int)(sizeof(tests)/sizeof(tests[0])); x++) {
len = sizeof(outtag);
if ((err = eax_encrypt_authenticate_memory(idx, tests[x].key, tests[x].keylen,
tests[x].nonce, tests[x].noncelen, tests[x].header, tests[x].headerlen,
tests[x].plaintext, tests[x].msglen, outct, outtag, &len)) != CRYPT_OK) {
return err;
}
if (memcmp(outct, tests[x].ciphertext, tests[x].msglen) || memcmp(outtag, tests[x].tag, len)) {
#if 0
unsigned long y;
printf("\n\nFailure: \nCT:\n");
for (y = 0; y < (unsigned long)tests[x].msglen; ) {
printf("0x%02x", outct[y]);
if (y < (unsigned long)(tests[x].msglen-1)) printf(", ");
if (!(++y % 8)) printf("\n");
}
printf("\nTAG:\n");
for (y = 0; y < len; ) {
printf("0x%02x", outtag[y]);
if (y < len-1) printf(", ");
if (!(++y % 8)) printf("\n");
}
#endif
return CRYPT_FAIL_TESTVECTOR;
}
/* test decrypt */
if ((err = eax_decrypt_verify_memory(idx, tests[x].key, tests[x].keylen,
tests[x].nonce, tests[x].noncelen, tests[x].header, tests[x].headerlen,
outct, tests[x].msglen, outct, outtag, len, &res)) != CRYPT_OK) {
return err;
}
if ((res != 1) || memcmp(outct, tests[x].plaintext, tests[x].msglen)) {
#if 0
unsigned long y;
printf("\n\nFailure (res == %d): \nPT:\n", res);
for (y = 0; y < (unsigned long)tests[x].msglen; ) {
printf("0x%02x", outct[y]);
if (y < (unsigned long)(tests[x].msglen-1)) printf(", ");
if (!(++y % 8)) printf("\n");
}
printf("\n\n");
#endif
return CRYPT_FAIL_TESTVECTOR;
}
}
return CRYPT_OK;
#endif /* LTC_TEST */
}
#endif /* EAX_MODE */

31
ecb_decrypt.c Normal file
View File

@@ -0,0 +1,31 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
*
* LibTomCrypt is a library that provides various cryptographic
* algorithms in a highly modular and flexible manner.
*
* The library is free for all purposes without any express
* guarantee it works.
*
* Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org
*/
#include "mycrypt.h"
#ifdef ECB
int ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_ECB *ecb)
{
int err;
_ARGCHK(pt != NULL);
_ARGCHK(ct != NULL);
_ARGCHK(ecb != NULL);
if ((err = cipher_is_valid(ecb->cipher)) != CRYPT_OK) {
return err;
}
cipher_descriptor[ecb->cipher].ecb_decrypt(ct, pt, &ecb->key);
return CRYPT_OK;
}
#endif

29
ecb_encrypt.c Normal file
View File

@@ -0,0 +1,29 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
*
* LibTomCrypt is a library that provides various cryptographic
* algorithms in a highly modular and flexible manner.
*
* The library is free for all purposes without any express
* guarantee it works.
*
* Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org
*/
#include "mycrypt.h"
#ifdef ECB
int ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_ECB *ecb)
{
int err;
_ARGCHK(pt != NULL);
_ARGCHK(ct != NULL);
_ARGCHK(ecb != NULL);
if ((err = cipher_is_valid(ecb->cipher)) != CRYPT_OK) {
return err;
}
cipher_descriptor[ecb->cipher].ecb_encrypt(pt, ct, &ecb->key);
return CRYPT_OK;
}
#endif

29
ecb_start.c Normal file
View File

@@ -0,0 +1,29 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
*
* LibTomCrypt is a library that provides various cryptographic
* algorithms in a highly modular and flexible manner.
*
* The library is free for all purposes without any express
* guarantee it works.
*
* Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org
*/
#include "mycrypt.h"
#ifdef ECB
int ecb_start(int cipher, const unsigned char *key, int keylen, int num_rounds, symmetric_ECB *ecb)
{
int err;
_ARGCHK(key != NULL);
_ARGCHK(ecb != NULL);
if ((err = cipher_is_valid(cipher)) != CRYPT_OK) {
return err;
}
ecb->cipher = cipher;
ecb->blocklen = cipher_descriptor[cipher].block_length;
return cipher_descriptor[cipher].setup(key, keylen, num_rounds, &ecb->key);
}
#endif

937
ecc.c Normal file
View File

@@ -0,0 +1,937 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
*
* LibTomCrypt is a library that provides various cryptographic
* algorithms in a highly modular and flexible manner.
*
* The library is free for all purposes without any express
* guarantee it works.
*
* Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org
*/
/* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b
*
* All curves taken from NIST recommendation paper of July 1999
* Available at http://csrc.nist.gov/cryptval/dss.htm
*/
#include "mycrypt.h"
#ifdef MECC
/* This holds the key settings. ***MUST*** be organized by size from smallest to largest. */
static const struct {
int size;
char *name, *prime, *B, *order, *Gx, *Gy;
} sets[] = {
#ifdef ECC160
{
20,
"ECC-160",
/* prime */
"G00000000000000000000000007",
/* B */
"1oUV2vOaSlWbxr6",
/* order */
"G0000000000004sCQUtDxaqDUN5",
/* Gx */
"jpqOf1BHus6Yd/pyhyVpP",
/* Gy */
"D/wykuuIFfr+vPyx7kQEPu8MixO",
},
#endif
#ifdef ECC192
{
24,
"ECC-192",
/* prime */
"/////////////////////l//////////",
/* B */
"P2456UMSWESFf+chSYGmIVwutkp1Hhcn",
/* order */
"////////////////cTxuDXHhoR6qqYWn",
/* Gx */
"68se3h0maFPylo3hGw680FJ/2ls2/n0I",
/* Gy */
"1nahbV/8sdXZ417jQoJDrNFvTw4UUKWH"
},
#endif
#ifdef ECC224
{
28,
"ECC-224",
/* prime */
"400000000000000000000000000000000000BV",
/* B */
"21HkWGL2CxJIp",
/* order */
"4000000000000000000Kxnixk9t8MLzMiV264/",
/* Gx */
"jpqOf1BHus6Yd/pyhyVpP",
/* Gy */
"3FCtyo2yHA5SFjkCGbYxbOvNeChwS+j6wSIwck",
},
#endif
#ifdef ECC256
{
32,
"ECC-256",
/* Prime */
"F////y000010000000000000000////////////////",
/* B */
"5h6DTYgEfFdi+kzLNQOXhnb7GQmp5EmzZlEF3udqc1B",
/* Order */
"F////y00000//////////+yvlgjfnUUXFEvoiByOoLH",
/* Gx */
"6iNqVBXB497+BpcvMEaGF9t0ts1BUipeFIXEKNOcCAM",
/* Gy */
"4/ZGkB+6d+RZkVhIdmFdXOhpZDNQp5UpiksG6Wtlr7r"
},
#endif
#ifdef ECC384
{
48,
"ECC-384",
/* prime */
"//////////////////////////////////////////x/////00000000003/"
"////",
/* B */
"ip4lf+8+v+IOZWLhu/Wj6HWTd6x+WK4I0nG8Zr0JXrh6LZcDYYxHdIg5oEtJ"
"x2hl",
/* Order */
"////////////////////////////////nsDDWVGtBTzO6WsoIB2dUkpi6MhC"
"nIbp",
/* Gx and Gy */
"geVA8hwB1JUEiSSUyo2jT6uTEsABfvkOMVT1u89KAZXL0l9TlrKfR3fKNZXo"
"TWgt",
"DXVUIfOcB6zTdfY/afBSAVZq7RqecXHywTen4xNmkC0AOB7E7Nw1dNf37NoG"
"wWvV"
},
#endif
#ifdef ECC521
{
65,
"ECC-521",
/* prime */
"V///////////////////////////////////////////////////////////"
"///////////////////////////",
/* B */
"56LFhbXZXoQ7vAQ8Q2sXK3kejfoMvcp5VEuj8cHZl49uLOPEL7iVfDx5bB0l"
"JknlmSrSz+8FImqyUz57zHhK3y0",
/* Order */
"V//////////////////////////////////////////+b66XuE/BvPhVym1I"
"FS9fT0xjScuYPn7hhjljnwHE6G9",
/* Gx and Gy */
"CQ5ZWQt10JfpPu+osOZbRH2d6I1EGK/jI7uAAzWQqqzkg5BNdVlvrae/Xt19"
"wB/gDupIBF1XMf2c/b+VZ72vRrc",
"HWvAMfucZl015oANxGiVHlPcFL4ILURH6WNhxqN9pvcB9VkSfbUz2P0nL2v0"
"J+j1s4rF726edB2G8Y+b7QVqMPG",
},
#endif
{
0,
NULL, NULL, NULL, NULL, NULL, NULL
}
};
#if 0
/* you plug in a prime and B value and it finds a pseudo-random base point */
void ecc_find_base(void)
{
static char *prime = "26959946667150639794667015087019630673637144422540572481103610249951";
static char *order = "26959946667150639794667015087019637467111563745054605861463538557247";
static char *b = "9538957348957353489587";
mp_int pp, p, r, B, tmp1, tmp2, tx, ty, x, y;
char buf[4096];
int i;
mp_init_multi(&tx, &ty, &x, &y, &p, &pp, &r, &B, &tmp1, &tmp2, NULL);
mp_read_radix(&p, prime, 10);
mp_read_radix(&r, order, 10);
mp_read_radix(&B, b, 10);
/* get (p+1)/4 */
mp_add_d(&p, 1, &pp);
mp_div_2(&pp, &pp);
mp_div_2(&pp, &pp);
buf[0] = 0;
do {
printf("."); fflush(stdout);
/* make a random value of x */
for (i = 0; i < 16; i++) buf[i+1] = rand() & 255;
mp_read_raw(&x, buf, 17);
mp_copy(&x, &tx);
/* now compute x^3 - 3x + b */
mp_expt_d(&x, 3, &tmp1);
mp_mul_d(&x, 3, &tmp2);
mp_sub(&tmp1, &tmp2, &tmp1);
mp_add(&tmp1, &B, &tmp1);
mp_mod(&tmp1, &p, &tmp1);
/* now compute sqrt via x^((p+1)/4) */
mp_exptmod(&tmp1, &pp, &p, &tmp2);
mp_copy(&tmp2, &ty);
/* now square it */
mp_sqrmod(&tmp2, &p, &tmp2);
/* tmp2 should equal tmp1 */
} while (mp_cmp(&tmp1, &tmp2));
/* now output values in way that libtomcrypt wants */
mp_todecimal(&p, buf);
printf("\n\np==%s\n", buf);
mp_tohex(&B, buf);
printf("b==%s\n", buf);
mp_todecimal(&r, buf);
printf("r==%s\n", buf);
mp_tohex(&tx, buf);
printf("Gx==%s\n", buf);
mp_tohex(&ty, buf);
printf("Gy==%s\n", buf);
mp_clear_multi(&tx, &ty, &x, &y, &p, &pp, &r, &B, &tmp1, &tmp2, NULL);
}
#endif
static int is_valid_idx(int n)
{
int x;
for (x = 0; sets[x].size != 0; x++);
if ((n < 0) || (n >= x)) {
return 0;
}
return 1;
}
static ecc_point *new_point(void)
{
ecc_point *p;
p = XMALLOC(sizeof(ecc_point));
if (p == NULL) {
return NULL;
}
if (mp_init_multi(&p->x, &p->y, NULL) != MP_OKAY) {
XFREE(p);
return NULL;
}
return p;
}
static void del_point(ecc_point *p)
{
/* prevents free'ing null arguments */
if (p != NULL) {
mp_clear_multi(&p->x, &p->y, NULL);
XFREE(p);
}
}
/* double a point R = 2P, R can be P*/
static int dbl_point(ecc_point *P, ecc_point *R, mp_int *modulus, mp_int *mu)
{
mp_int s, tmp, tmpx;
int err;
if ((err = mp_init_multi(&s, &tmp, &tmpx, NULL)) != MP_OKAY) {
return mpi_to_ltc_error(err);
}
/* s = (3Xp^2 + a) / (2Yp) */
if ((err = mp_mul_2(&P->y, &tmp)) != MP_OKAY) { goto error; } /* tmp = 2*y */
if ((err = mp_invmod(&tmp, modulus, &tmp)) != MP_OKAY) { goto error; } /* tmp = 1/tmp mod modulus */
if ((err = mp_sqr(&P->x, &s)) != MP_OKAY) { goto error; } /* s = x^2 */
if ((err = mp_reduce(&s, modulus, mu)) != MP_OKAY) { goto error; }
if ((err = mp_mul_d(&s,(mp_digit)3, &s)) != MP_OKAY) { goto error; } /* s = 3*(x^2) */
if ((err = 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 ((err = mp_add(&s, modulus, &s)) != MP_OKAY) { goto error; }
}
if ((err = mp_mul(&s, &tmp, &s)) != MP_OKAY) { goto error; } /* s = tmp * s mod modulus */
if ((err = mp_reduce(&s, modulus, mu)) != MP_OKAY) { goto error; }
/* Xr = s^2 - 2Xp */
if ((err = mp_sqr(&s, &tmpx)) != MP_OKAY) { goto error; } /* tmpx = s^2 */
if ((err = mp_reduce(&tmpx, modulus, mu)) != MP_OKAY) { goto error; } /* tmpx = tmpx mod modulus */
if ((err = mp_sub(&tmpx, &P->x, &tmpx)) != MP_OKAY) { goto error; } /* tmpx = tmpx - x */
if ((err = mp_submod(&tmpx, &P->x, modulus, &tmpx)) != MP_OKAY) { goto error; } /* tmpx = tmpx - x mod modulus */
/* Yr = -Yp + s(Xp - Xr) */
if ((err = mp_sub(&P->x, &tmpx, &tmp)) != MP_OKAY) { goto error; } /* tmp = x - tmpx */
if ((err = mp_mul(&tmp, &s, &tmp)) != MP_OKAY) { goto error; } /* tmp = tmp * s */
if ((err = mp_submod(&tmp, &P->y, modulus, &R->y)) != MP_OKAY) { goto error; } /* y = tmp - y mod modulus */
if ((err = mp_copy(&tmpx, &R->x)) != MP_OKAY) { goto error; } /* x = tmpx */
err = CRYPT_OK;
goto done;
error:
err = mpi_to_ltc_error(err);
done:
mp_clear_multi(&tmpx, &tmp, &s, NULL);
return err;
}
/* add two different points over Z/pZ, R = P + Q, note R can equal either P or Q */
static int add_point(ecc_point *P, ecc_point *Q, ecc_point *R, mp_int *modulus, mp_int *mu)
{
mp_int s, tmp, tmpx;
int err;
if ((err = mp_init(&tmp)) != MP_OKAY) {
return mpi_to_ltc_error(err);
}
/* is P==Q or P==-Q? */
if (((err = mp_neg(&Q->y, &tmp)) != MP_OKAY) || ((err = mp_mod(&tmp, modulus, &tmp)) != MP_OKAY)) {
mp_clear(&tmp);
return mpi_to_ltc_error(err);
}
if (mp_cmp(&P->x, &Q->x) == MP_EQ)
if (mp_cmp(&P->y, &Q->y) == MP_EQ || mp_cmp(&P->y, &tmp) == MP_EQ) {
mp_clear(&tmp);
return dbl_point(P, R, modulus, mu);
}
if ((err = mp_init_multi(&tmpx, &s, NULL)) != MP_OKAY) {
mp_clear(&tmp);
return mpi_to_ltc_error(err);
}
/* get s = (Yp - Yq)/(Xp-Xq) mod p */
if ((err = 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 ((err = mp_add(&tmp, modulus, &tmp)) != MP_OKAY) { goto error; }
}
if ((err = mp_invmod(&tmp, modulus, &tmp)) != MP_OKAY) { goto error; } /* tmp = 1/tmp mod modulus */
if ((err = 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 ((err = mp_add(&s, modulus, &s)) != MP_OKAY) { goto error; }
}
if ((err = mp_mul(&s, &tmp, &s)) != MP_OKAY) { goto error; } /* s = s * tmp mod modulus */
if ((err = mp_reduce(&s, modulus, mu)) != MP_OKAY) { goto error; }
/* Xr = s^2 - Xp - Xq */
if ((err = mp_sqr(&s, &tmp)) != MP_OKAY) { goto error; } /* tmp = s^2 mod modulus */
if ((err = mp_reduce(&tmp, modulus, mu)) != MP_OKAY) { goto error; }
if ((err = mp_sub(&tmp, &P->x, &tmp)) != MP_OKAY) { goto error; } /* tmp = tmp - Px */
if ((err = mp_sub(&tmp, &Q->x, &tmpx)) != MP_OKAY) { goto error; } /* tmpx = tmp - Qx */
/* Yr = -Yp + s(Xp - Xr) */
if ((err = mp_sub(&P->x, &tmpx, &tmp)) != MP_OKAY) { goto error; } /* tmp = Px - tmpx */
if ((err = mp_mul(&tmp, &s, &tmp)) != MP_OKAY) { goto error; } /* tmp = tmp * s */
if ((err = mp_submod(&tmp, &P->y, modulus, &R->y)) != MP_OKAY) { goto error; } /* Ry = tmp - Py mod modulus */
if ((err = mp_mod(&tmpx, modulus, &R->x)) != MP_OKAY) { goto error; } /* Rx = tmpx mod modulus */
err = CRYPT_OK;
goto done;
error:
err = mpi_to_ltc_error(err);
done:
mp_clear_multi(&s, &tmpx, &tmp, NULL);
return err;
}
/* size of sliding window, don't change this! */
#define WINSIZE 4
/* perform R = kG where k == integer and G == ecc_point */
static int ecc_mulmod(mp_int *k, ecc_point *G, ecc_point *R, mp_int *modulus)
{
ecc_point *tG, *M[8];
int i, j, err;
mp_int mu;
mp_digit buf;
int first, bitbuf, bitcpy, bitcnt, mode, digidx;
/* init barrett reduction */
if ((err = mp_init(&mu)) != MP_OKAY) {
return mpi_to_ltc_error(err);
}
if ((err = mp_reduce_setup(&mu, modulus)) != MP_OKAY) {
mp_clear(&mu);
return mpi_to_ltc_error(err);
}
/* alloc ram for window temps */
for (i = 0; i < 8; i++) {
M[i] = new_point();
if (M[i] == NULL) {
for (j = 0; j < i; j++) {
del_point(M[j]);
}
mp_clear(&mu);
return CRYPT_MEM;
}
}
/* make a copy of G incase R==G */
tG = new_point();
if (tG == NULL) { err = CRYPT_MEM; goto done; }
/* tG = G */
if ((err = mp_copy(&G->x, &tG->x)) != MP_OKAY) { goto error; }
if ((err = mp_copy(&G->y, &tG->y)) != MP_OKAY) { goto error; }
/* calc the M tab, which holds kG for k==8..15 */
/* M[0] == 8G */
if ((err = dbl_point(G, M[0], modulus, &mu)) != CRYPT_OK) { goto done; }
if ((err = dbl_point(M[0], M[0], modulus, &mu)) != CRYPT_OK) { goto done; }
if ((err = dbl_point(M[0], M[0], modulus, &mu)) != CRYPT_OK) { goto done; }
/* now find (8+k)G for k=1..7 */
for (j = 9; j < 16; j++) {
if ((err = add_point(M[j-9], G, M[j-8], modulus, &mu)) != CRYPT_OK) { goto done; }
}
/* setup sliding window */
mode = 0;
bitcnt = 1;
buf = 0;
digidx = k->used - 1;
bitcpy = bitbuf = 0;
first = 1;
/* perform ops */
for (;;) {
/* grab next digit as required */
if (--bitcnt == 0) {
if (digidx == -1) {
break;
}
buf = k->dp[digidx--];
bitcnt = (int) DIGIT_BIT;
}
/* grab the next msb from the multiplicand */
i = (buf >> (DIGIT_BIT - 1)) & 1;
buf <<= 1;
/* skip leading zero bits */
if (mode == 0 && i == 0) {
continue;
}
/* if the bit is zero and mode == 1 then we double */
if (mode == 1 && i == 0) {
if ((err = dbl_point(R, R, modulus, &mu)) != CRYPT_OK) { goto done; }
continue;
}
/* else we add it to the window */
bitbuf |= (i << (WINSIZE - ++bitcpy));
mode = 2;
if (bitcpy == WINSIZE) {
/* if this is the first window we do a simple copy */
if (first == 1) {
/* R = kG [k = first window] */
if ((err = mp_copy(&M[bitbuf-8]->x, &R->x)) != MP_OKAY) { goto error; }
if ((err = mp_copy(&M[bitbuf-8]->y, &R->y)) != MP_OKAY) { goto error; }
first = 0;
} else {
/* normal window */
/* ok window is filled so double as required and add */
/* double first */
for (j = 0; j < WINSIZE; j++) {
if ((err = dbl_point(R, R, modulus, &mu)) != CRYPT_OK) { goto done; }
}
/* then add, bitbuf will be 8..15 [8..2^WINSIZE] guaranteed */
if ((err = add_point(R, M[bitbuf-8], R, modulus, &mu)) != CRYPT_OK) { goto done; }
}
/* empty window and reset */
bitcpy = bitbuf = 0;
mode = 1;
}
}
/* if bits remain then double/add */
if (mode == 2 && bitcpy > 0) {
/* double then add */
for (j = 0; j < bitcpy; j++) {
/* only double if we have had at least one add first */
if (first == 0) {
if ((err = dbl_point(R, R, modulus, &mu)) != CRYPT_OK) { goto done; }
}
bitbuf <<= 1;
if ((bitbuf & (1 << WINSIZE)) != 0) {
if (first == 1){
/* first add, so copy */
if ((err = mp_copy(&tG->x, &R->x)) != MP_OKAY) { goto error; }
if ((err = mp_copy(&tG->y, &R->y)) != MP_OKAY) { goto error; }
first = 0;
} else {
/* then add */
if ((err = add_point(R, tG, R, modulus, &mu)) != CRYPT_OK) { goto done; }
}
}
}
}
err = CRYPT_OK;
goto done;
error:
err = mpi_to_ltc_error(err);
done:
del_point(tG);
for (i = 0; i < 8; i++) {
del_point(M[i]);
}
mp_clear(&mu);
return err;
}
#undef WINSIZE
int ecc_test(void)
{
mp_int modulus, order;
ecc_point *G, *GG;
int i, err, primality;
if ((err = mp_init_multi(&modulus, &order, NULL)) != MP_OKAY) {
return mpi_to_ltc_error(err);
}
G = new_point();
GG = new_point();
if (G == NULL || GG == NULL) {
mp_clear_multi(&modulus, &order, NULL);
del_point(G);
del_point(GG);
return CRYPT_MEM;
}
for (i = 0; sets[i].size; i++) {
#if 0
printf("Testing %d\n", sets[i].size);
#endif
if ((err = mp_read_radix(&modulus, (char *)sets[i].prime, 64)) != MP_OKAY) { goto error; }
if ((err = mp_read_radix(&order, (char *)sets[i].order, 64)) != MP_OKAY) { goto error; }
/* is prime actually prime? */
if ((err = is_prime(&modulus, &primality)) != CRYPT_OK) { goto done; }
if (primality == 0) {
err = CRYPT_FAIL_TESTVECTOR;
goto done;
}
/* is order prime ? */
if ((err = is_prime(&order, &primality)) != CRYPT_OK) { goto done; }
if (primality == 0) {
err = CRYPT_FAIL_TESTVECTOR;
goto done;
}
if ((err = mp_read_radix(&G->x, (char *)sets[i].Gx, 64)) != MP_OKAY) { goto error; }
if ((err = mp_read_radix(&G->y, (char *)sets[i].Gy, 64)) != MP_OKAY) { goto error; }
/* then we should have G == (order + 1)G */
if ((err = mp_add_d(&order, 1, &order)) != MP_OKAY) { goto error; }
if ((err = ecc_mulmod(&order, G, GG, &modulus)) != CRYPT_OK) { goto done; }
if (mp_cmp(&G->x, &GG->x) != 0 || mp_cmp(&G->y, &GG->y) != 0) {
err = CRYPT_FAIL_TESTVECTOR;
goto done;
}
}
err = CRYPT_OK;
goto done;
error:
err = mpi_to_ltc_error(err);
done:
del_point(GG);
del_point(G);
mp_clear_multi(&order, &modulus, NULL);
return err;
}
void ecc_sizes(int *low, int *high)
{
int i;
_ARGCHK(low != NULL);
_ARGCHK(high != NULL);
*low = INT_MAX;
*high = 0;
for (i = 0; sets[i].size != 0; i++) {
if (sets[i].size < *low) {
*low = sets[i].size;
}
if (sets[i].size > *high) {
*high = sets[i].size;
}
}
}
int ecc_make_key(prng_state *prng, int wprng, int keysize, ecc_key *key)
{
int x, err;
ecc_point *base;
mp_int prime;
unsigned char buf[128];
_ARGCHK(key != NULL);
/* good prng? */
if ((err = prng_is_valid(wprng)) != CRYPT_OK) {
return err;
}
/* find key size */
for (x = 0; (keysize > sets[x].size) && (sets[x].size != 0); x++);
keysize = sets[x].size;
if (sets[x].size == 0) {
return CRYPT_INVALID_KEYSIZE;
}
key->idx = x;
/* make up random string */
if (prng_descriptor[wprng].read(buf, (unsigned long)keysize, prng) != (unsigned long)keysize) {
return CRYPT_ERROR_READPRNG;
}
/* setup the key variables */
if ((err = mp_init_multi(&key->pubkey.x, &key->pubkey.y, &key->k, &prime, NULL)) != MP_OKAY) {
return mpi_to_ltc_error(err);
}
base = new_point();
if (base == NULL) {
mp_clear_multi(&key->pubkey.x, &key->pubkey.y, &key->k, &prime, NULL);
return CRYPT_MEM;
}
/* read in the specs for this key */
if ((err = mp_read_radix(&prime, (char *)sets[key->idx].prime, 64)) != MP_OKAY) { goto error; }
if ((err = mp_read_radix(&base->x, (char *)sets[key->idx].Gx, 64)) != MP_OKAY) { goto error; }
if ((err = mp_read_radix(&base->y, (char *)sets[key->idx].Gy, 64)) != MP_OKAY) { goto error; }
if ((err = mp_read_unsigned_bin(&key->k, (unsigned char *)buf, keysize)) != MP_OKAY) { goto error; }
/* make the public key */
if ((err = ecc_mulmod(&key->k, base, &key->pubkey, &prime)) != CRYPT_OK) { goto done; }
key->type = PK_PRIVATE;
/* shrink key */
if ((err = mp_shrink(&key->k)) != MP_OKAY) { goto error; }
if ((err = mp_shrink(&key->pubkey.x)) != MP_OKAY) { goto error; }
if ((err = mp_shrink(&key->pubkey.y)) != MP_OKAY) { goto error; }
/* free up ram */
err = CRYPT_OK;
goto done;
error:
err = mpi_to_ltc_error(err);
done:
del_point(base);
mp_clear(&prime);
#ifdef CLEAN_STACK
zeromem(buf, sizeof(buf));
#endif
return err;
}
void ecc_free(ecc_key *key)
{
_ARGCHK(key != NULL);
mp_clear_multi(&key->pubkey.x, &key->pubkey.y, &key->k, NULL);
}
static int compress_y_point(ecc_point *pt, int idx, int *result)
{
mp_int tmp, tmp2, p;
int err;
_ARGCHK(pt != NULL);
_ARGCHK(result != NULL);
if ((err = mp_init_multi(&tmp, &tmp2, &p, NULL)) != MP_OKAY) {
return mpi_to_ltc_error(err);
}
/* get x^3 - 3x + b */
if ((err = mp_read_radix(&p, (char *)sets[idx].B, 64)) != MP_OKAY) { goto error; } /* p = B */
if ((err = mp_expt_d(&pt->x, 3, &tmp)) != MP_OKAY) { goto error; } /* tmp = pX^3 */
if ((err = mp_mul_d(&pt->x, 3, &tmp2)) != MP_OKAY) { goto error; } /* tmp2 = 3*pX^3 */
if ((err = mp_sub(&tmp, &tmp2, &tmp)) != MP_OKAY) { goto error; } /* tmp = tmp - tmp2 */
if ((err = mp_add(&tmp, &p, &tmp)) != MP_OKAY) { goto error; } /* tmp = tmp + p */
if ((err = mp_read_radix(&p, (char *)sets[idx].prime, 64)) != MP_OKAY) { goto error; } /* p = prime */
if ((err = mp_mod(&tmp, &p, &tmp)) != MP_OKAY) { goto error; } /* tmp = tmp mod p */
/* now find square root */
if ((err = mp_add_d(&p, 1, &tmp2)) != MP_OKAY) { goto error; } /* tmp2 = p + 1 */
if ((err = mp_div_2d(&tmp2, 2, &tmp2, NULL)) != MP_OKAY) { goto error; } /* tmp2 = (p+1)/4 */
if ((err = mp_exptmod(&tmp, &tmp2, &p, &tmp)) != MP_OKAY) { goto error; } /* tmp = (x^3 - 3x + b)^((p+1)/4) mod p */
/* if tmp equals the y point give a 0, otherwise 1 */
if (mp_cmp(&tmp, &pt->y) == 0) {
*result = 0;
} else {
*result = 1;
}
err = CRYPT_OK;
goto done;
error:
err = mpi_to_ltc_error(err);
done:
mp_clear_multi(&p, &tmp, &tmp2, NULL);
return err;
}
static int expand_y_point(ecc_point *pt, int idx, int result)
{
mp_int tmp, tmp2, p;
int err;
_ARGCHK(pt != NULL);
if ((err = mp_init_multi(&tmp, &tmp2, &p, NULL)) != MP_OKAY) {
return CRYPT_MEM;
}
/* get x^3 - 3x + b */
if ((err = mp_read_radix(&p, (char *)sets[idx].B, 64)) != MP_OKAY) { goto error; } /* p = B */
if ((err = mp_expt_d(&pt->x, 3, &tmp)) != MP_OKAY) { goto error; } /* tmp = pX^3 */
if ((err = mp_mul_d(&pt->x, 3, &tmp2)) != MP_OKAY) { goto error; } /* tmp2 = 3*pX^3 */
if ((err = mp_sub(&tmp, &tmp2, &tmp)) != MP_OKAY) { goto error; } /* tmp = tmp - tmp2 */
if ((err = mp_add(&tmp, &p, &tmp)) != MP_OKAY) { goto error; } /* tmp = tmp + p */
if ((err = mp_read_radix(&p, (char *)sets[idx].prime, 64)) != MP_OKAY) { goto error; } /* p = prime */
if ((err = mp_mod(&tmp, &p, &tmp)) != MP_OKAY) { goto error; } /* tmp = tmp mod p */
/* now find square root */
if ((err = mp_add_d(&p, 1, &tmp2)) != MP_OKAY) { goto error; } /* tmp2 = p + 1 */
if ((err = mp_div_2d(&tmp2, 2, &tmp2, NULL)) != MP_OKAY) { goto error; } /* tmp2 = (p+1)/4 */
if ((err = mp_exptmod(&tmp, &tmp2, &p, &tmp)) != MP_OKAY) { goto error; } /* tmp = (x^3 - 3x + b)^((p+1)/4) mod p */
/* if result==0, then y==tmp, otherwise y==p-tmp */
if (result == 0) {
if ((err = mp_copy(&tmp, &pt->y) != MP_OKAY)) { goto error; }
} else {
if ((err = mp_sub(&p, &tmp, &pt->y) != MP_OKAY)) { goto error; }
}
err = CRYPT_OK;
goto done;
error:
err = mpi_to_ltc_error(err);
done:
mp_clear_multi(&p, &tmp, &tmp2, NULL);
return err;
}
int ecc_export(unsigned char *out, unsigned long *outlen, int type, ecc_key *key)
{
unsigned long y, z;
int cp, err;
_ARGCHK(out != NULL);
_ARGCHK(outlen != NULL);
_ARGCHK(key != NULL);
/* can we store the static header? */
if (*outlen < (PACKET_SIZE + 3)) {
return CRYPT_BUFFER_OVERFLOW;
}
/* type valid? */
if (key->type != PK_PRIVATE && type == PK_PRIVATE) {
return CRYPT_PK_TYPE_MISMATCH;
}
/* output type and magic byte */
y = PACKET_SIZE;
out[y++] = (unsigned char)type;
out[y++] = (unsigned char)sets[key->idx].size;
/* output x coordinate */
OUTPUT_BIGNUM(&(key->pubkey.x), out, y, z);
/* compress y and output it */
if ((err = compress_y_point(&key->pubkey, key->idx, &cp)) != CRYPT_OK) {
return err;
}
out[y++] = (unsigned char)cp;
if (type == PK_PRIVATE) {
OUTPUT_BIGNUM(&key->k, out, y, z);
}
/* store header */
packet_store_header(out, PACKET_SECT_ECC, PACKET_SUB_KEY);
*outlen = y;
return CRYPT_OK;
}
int ecc_import(const unsigned char *in, unsigned long inlen, ecc_key *key)
{
unsigned long x, y, s;
int err;
_ARGCHK(in != NULL);
_ARGCHK(key != NULL);
/* check length */
if ((3+PACKET_SIZE) > inlen) {
return CRYPT_INVALID_PACKET;
}
/* check type */
if ((err = packet_valid_header((unsigned char *)in, PACKET_SECT_ECC, PACKET_SUB_KEY)) != CRYPT_OK) {
return err;
}
/* init key */
if (mp_init_multi(&key->pubkey.x, &key->pubkey.y, &key->k, NULL) != MP_OKAY) {
return CRYPT_MEM;
}
y = PACKET_SIZE;
key->type = (int)in[y++];
s = (unsigned long)in[y++];
for (x = 0; (s > (unsigned long)sets[x].size) && (sets[x].size != 0); x++);
if (sets[x].size == 0) {
err = CRYPT_INVALID_KEYSIZE;
goto error;
}
key->idx = (int)x;
/* type check both values */
if ((key->type != PK_PUBLIC) && (key->type != PK_PRIVATE)) {
err = CRYPT_INVALID_PACKET;
goto error;
}
/* is the key idx valid? */
if (is_valid_idx(key->idx) != 1) {
err = CRYPT_INVALID_PACKET;
goto error;
}
/* load x coordinate */
INPUT_BIGNUM(&key->pubkey.x, in, x, y, inlen);
/* load y */
x = (unsigned long)in[y++];
if ((err = expand_y_point(&key->pubkey, key->idx, (int)x)) != CRYPT_OK) {
goto error;
}
if (key->type == PK_PRIVATE) {
/* load private key */
INPUT_BIGNUM(&key->k, in, x, y, inlen);
}
/* eliminate private key if public */
if (key->type == PK_PUBLIC) {
mp_clear(&key->k);
}
return CRYPT_OK;
error:
mp_clear_multi(&key->pubkey.x, &key->pubkey.y, &key->k, NULL);
return err;
}
int ecc_shared_secret(ecc_key *private_key, ecc_key *public_key,
unsigned char *out, unsigned long *outlen)
{
unsigned long x, y;
ecc_point *result;
mp_int prime;
int err;
_ARGCHK(private_key != NULL);
_ARGCHK(public_key != NULL);
_ARGCHK(out != NULL);
_ARGCHK(outlen != NULL);
/* type valid? */
if (private_key->type != PK_PRIVATE) {
return CRYPT_PK_NOT_PRIVATE;
}
if (private_key->idx != public_key->idx) {
return CRYPT_PK_TYPE_MISMATCH;
}
/* make new point */
result = new_point();
if (result == NULL) {
return CRYPT_MEM;
}
if ((err = mp_init(&prime)) != MP_OKAY) {
del_point(result);
return mpi_to_ltc_error(err);
}
if ((err = mp_read_radix(&prime, (char *)sets[private_key->idx].prime, 64)) != MP_OKAY) { goto error; }
if ((err = ecc_mulmod(&private_key->k, &public_key->pubkey, result, &prime)) != CRYPT_OK) { goto done1; }
x = (unsigned long)mp_unsigned_bin_size(&result->x);
y = (unsigned long)mp_unsigned_bin_size(&result->y);
if (*outlen < (x+y)) {
err = CRYPT_BUFFER_OVERFLOW;
goto done1;
}
*outlen = x+y;
if ((err = mp_to_unsigned_bin(&result->x, out)) != MP_OKAY) { goto error; }
if ((err = mp_to_unsigned_bin(&result->y, out+x)) != MP_OKAY) { goto error; }
err = CRYPT_OK;
goto done1;
error:
err = mpi_to_ltc_error(err);
done1:
mp_clear(&prime);
del_point(result);
return err;
}
int ecc_get_size(ecc_key *key)
{
_ARGCHK(key != NULL);
if (is_valid_idx(key->idx))
return sets[key->idx].size;
else
return INT_MAX; /* large value known to cause it to fail when passed to ecc_make_key() */
}
#include "ecc_sys.c"
#endif

432
ecc_sys.c Normal file
View File

@@ -0,0 +1,432 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
*
* LibTomCrypt is a library that provides various cryptographic
* algorithms in a highly modular and flexible manner.
*
* The library is free for all purposes without any express
* guarantee it works.
*
* Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org
*/
int ecc_encrypt_key(const unsigned char *inkey, unsigned long keylen,
unsigned char *out, unsigned long *len,
prng_state *prng, int wprng, int hash,
ecc_key *key)
{
unsigned char pub_expt[256], ecc_shared[256], skey[MAXBLOCKSIZE];
ecc_key pubkey;
unsigned long x, y, z, hashsize, pubkeysize;
int err;
_ARGCHK(inkey != NULL);
_ARGCHK(out != NULL);
_ARGCHK(len != NULL);
_ARGCHK(key != NULL);
/* check that wprng/cipher/hash are not invalid */
if ((err = prng_is_valid(wprng)) != CRYPT_OK) {
return err;
}
if ((err = hash_is_valid(hash)) != CRYPT_OK) {
return err;
}
if (keylen > hash_descriptor[hash].hashsize) {
return CRYPT_INVALID_HASH;
}
/* make a random key and export the public copy */
if ((err = ecc_make_key(prng, wprng, ecc_get_size(key), &pubkey)) != CRYPT_OK) {
return err;
}
pubkeysize = (unsigned long)sizeof(pub_expt);
if ((err = ecc_export(pub_expt, &pubkeysize, PK_PUBLIC, &pubkey)) != CRYPT_OK) {
ecc_free(&pubkey);
return err;
}
/* now check if the out buffer is big enough */
if (*len < (9 + PACKET_SIZE + pubkeysize + hash_descriptor[hash].hashsize)) {
ecc_free(&pubkey);
return CRYPT_BUFFER_OVERFLOW;
}
/* make random key */
hashsize = hash_descriptor[hash].hashsize;
x = (unsigned long)sizeof(ecc_shared);
if ((err = ecc_shared_secret(&pubkey, key, ecc_shared, &x)) != CRYPT_OK) {
ecc_free(&pubkey);
return err;
}
ecc_free(&pubkey);
z = (unsigned long)sizeof(skey);
if ((err = hash_memory(hash, ecc_shared, x, skey, &z)) != CRYPT_OK) {
return err;
}
/* store header */
packet_store_header(out, PACKET_SECT_ECC, PACKET_SUB_ENC_KEY);
/* output header */
y = PACKET_SIZE;
/* size of hash name and the name itself */
out[y++] = hash_descriptor[hash].ID;
/* length of ECC pubkey and the key itself */
STORE32L(pubkeysize, out+y);
y += 4;
for (x = 0; x < pubkeysize; x++, y++) {
out[y] = pub_expt[x];
}
STORE32L(keylen, out+y);
y += 4;
/* Encrypt/Store the encrypted key */
for (x = 0; x < keylen; x++, y++) {
out[y] = skey[x] ^ inkey[x];
}
*len = y;
#ifdef CLEAN_STACK
/* clean up */
zeromem(pub_expt, sizeof(pub_expt));
zeromem(ecc_shared, sizeof(ecc_shared));
zeromem(skey, sizeof(skey));
#endif
return CRYPT_OK;
}
int ecc_decrypt_key(const unsigned char *in, unsigned long inlen,
unsigned char *outkey, unsigned long *keylen,
ecc_key *key)
{
unsigned char shared_secret[256], skey[MAXBLOCKSIZE];
unsigned long x, y, z, hashsize, keysize;
int hash, err;
ecc_key pubkey;
_ARGCHK(in != NULL);
_ARGCHK(outkey != NULL);
_ARGCHK(keylen != NULL);
_ARGCHK(key != NULL);
/* right key type? */
if (key->type != PK_PRIVATE) {
return CRYPT_PK_NOT_PRIVATE;
}
/* correct length ? */
if (inlen < PACKET_SIZE+1+4+4) {
return CRYPT_INVALID_PACKET;
} else {
inlen -= PACKET_SIZE+1+4+4;
}
/* is header correct? */
if ((err = packet_valid_header((unsigned char *)in, PACKET_SECT_ECC, PACKET_SUB_ENC_KEY)) != CRYPT_OK) {
return err;
}
/* now lets get the hash name */
y = PACKET_SIZE;
hash = find_hash_id(in[y++]);
if (hash == -1) {
return CRYPT_INVALID_HASH;
}
/* common values */
hashsize = hash_descriptor[hash].hashsize;
/* get public key */
LOAD32L(x, in+y);
if (inlen < x) {
return CRYPT_INVALID_PACKET;
} else {
inlen -= x;
}
y += 4;
if ((err = ecc_import(in+y, x, &pubkey)) != CRYPT_OK) {
return err;
}
y += x;
/* make shared key */
x = (unsigned long)sizeof(shared_secret);
if ((err = ecc_shared_secret(key, &pubkey, shared_secret, &x)) != CRYPT_OK) {
ecc_free(&pubkey);
return err;
}
ecc_free(&pubkey);
z = (unsigned long)sizeof(skey);
if ((err = hash_memory(hash, shared_secret, x, skey, &z)) != CRYPT_OK) {
return err;
}
LOAD32L(keysize, in+y);
if (inlen < keysize) {
return CRYPT_INVALID_PACKET;
} else {
inlen -= keysize;
}
y += 4;
if (*keylen < keysize) {
err = CRYPT_BUFFER_OVERFLOW;
goto done;
}
/* Decrypt the key */
for (x = 0; x < keysize; x++, y++) {
outkey[x] = skey[x] ^ in[y];
}
*keylen = keysize;
err = CRYPT_OK;
done:
#ifdef CLEAN_STACK
zeromem(shared_secret, sizeof(shared_secret));
zeromem(skey, sizeof(skey));
#endif
return err;
}
int ecc_sign_hash(const unsigned char *in, unsigned long inlen,
unsigned char *out, unsigned long *outlen,
prng_state *prng, int wprng, ecc_key *key)
{
ecc_key pubkey;
mp_int b, p;
unsigned char epubkey[256], er[256];
unsigned long x, y, pubkeysize, rsize;
int err;
_ARGCHK(in != NULL);
_ARGCHK(out != NULL);
_ARGCHK(outlen != NULL);
_ARGCHK(key != NULL);
/* is this a private key? */
if (key->type != PK_PRIVATE) {
return CRYPT_PK_NOT_PRIVATE;
}
/* is the IDX valid ? */
if (is_valid_idx(key->idx) != 1) {
return CRYPT_PK_INVALID_TYPE;
}
if ((err = prng_is_valid(wprng)) != CRYPT_OK) {
return err;
}
/* make up a key and export the public copy */
if ((err = ecc_make_key(prng, wprng, ecc_get_size(key), &pubkey)) != CRYPT_OK) {
return err;
}
pubkeysize = (unsigned long)sizeof(epubkey);
if ((err = ecc_export(epubkey, &pubkeysize, PK_PUBLIC, &pubkey)) != CRYPT_OK) {
ecc_free(&pubkey);
return err;
}
/* get the hash and load it as a bignum into 'b' */
/* init the bignums */
if ((err = mp_init_multi(&b, &p, NULL)) != MP_OKAY) {
ecc_free(&pubkey);
return mpi_to_ltc_error(err);
}
if ((err = mp_read_radix(&p, (char *)sets[key->idx].order, 64)) != MP_OKAY) { goto error; }
if ((err = mp_read_unsigned_bin(&b, (unsigned char *)in, (int)inlen)) != MP_OKAY) { goto error; }
/* find b = (m - x)/k */
if ((err = mp_invmod(&pubkey.k, &p, &pubkey.k)) != MP_OKAY) { goto error; } /* k = 1/k */
if ((err = mp_submod(&b, &key->k, &p, &b)) != MP_OKAY) { goto error; } /* b = m - x */
if ((err = mp_mulmod(&b, &pubkey.k, &p, &b)) != MP_OKAY) { goto error; } /* b = (m - x)/k */
/* export it */
rsize = (unsigned long)mp_unsigned_bin_size(&b);
if (rsize > (unsigned long)sizeof(er)) {
err = CRYPT_BUFFER_OVERFLOW;
goto error;
}
if ((err = mp_to_unsigned_bin(&b, er)) != MP_OKAY) { goto error; }
/* now lets check the outlen before we write */
if (*outlen < (12 + rsize + pubkeysize)) {
err = CRYPT_BUFFER_OVERFLOW;
goto done;
}
/* lets output */
y = PACKET_SIZE;
/* size of public key */
STORE32L(pubkeysize, out+y);
y += 4;
/* copy the public key */
for (x = 0; x < pubkeysize; x++, y++) {
out[y] = epubkey[x];
}
/* size of 'r' */
STORE32L(rsize, out+y);
y += 4;
/* copy r */
for (x = 0; x < rsize; x++, y++) {
out[y] = er[x];
}
/* store header */
packet_store_header(out, PACKET_SECT_ECC, PACKET_SUB_SIGNED);
/* clear memory */
*outlen = y;
err = CRYPT_OK;
goto done;
error:
err = mpi_to_ltc_error(err);
done:
mp_clear_multi(&b, &p, NULL);
ecc_free(&pubkey);
#ifdef CLEAN_STACK
zeromem(er, sizeof(er));
zeromem(epubkey, sizeof(epubkey));
#endif
return err;
}
/* verify that mG = (bA + Y)
*
* The signatures work by making up a fresh key "a" with a public key "A". Now we want to sign so the
* public key Y = xG can verify it.
*
* b = (m - x)/k, A is the public key embedded and Y is the users public key [who signed it]
* A = kG therefore bA == ((m-x)/k)kG == (m-x)G
*
* Adding Y = xG to the bA gives us (m-x)G + xG == mG
*
* The user given only xG, kG and b cannot determine k or x which means they can't find the private key.
*
*/
int ecc_verify_hash(const unsigned char *sig, unsigned long siglen,
const unsigned char *hash, unsigned long inlen,
int *stat, ecc_key *key)
{
ecc_point *mG;
ecc_key pubkey;
mp_int b, p, m, mu;
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+4+4) {
return CRYPT_INVALID_PACKET;
} else {
siglen -= PACKET_SIZE+4+4;
}
/* is the message format correct? */
if ((err = packet_valid_header((unsigned char *)sig, PACKET_SECT_ECC, PACKET_SUB_SIGNED)) != CRYPT_OK) {
return err;
}
/* get hash name */
y = PACKET_SIZE;
/* get size of public key */
LOAD32L(x, sig+y);
if (siglen < x) {
return CRYPT_INVALID_PACKET;
} else {
siglen -= x;
}
y += 4;
/* load the public key */
if ((err = ecc_import((unsigned char*)sig+y, x, &pubkey)) != CRYPT_OK) {
return err;
}
y += x;
/* load size of 'b' */
LOAD32L(x, sig+y);
if (siglen < x) {
return CRYPT_INVALID_PACKET;
} else {
siglen -= x;
}
y += 4;
/* init values */
if ((err = mp_init_multi(&b, &m, &p, &mu, NULL)) != MP_OKAY) {
ecc_free(&pubkey);
return mpi_to_ltc_error(err);
}
mG = new_point();
if (mG == NULL) {
mp_clear_multi(&b, &m, &p, &mu, NULL);
ecc_free(&pubkey);
return CRYPT_MEM;
}
/* load b */
if ((err = mp_read_unsigned_bin(&b, (unsigned char *)sig+y, (int)x)) != MP_OKAY) { goto error; }
y += x;
/* get m in binary a bignum */
if ((err = mp_read_unsigned_bin(&m, (unsigned char *)hash, (int)inlen)) != MP_OKAY) { goto error; }
/* load prime */
if ((err = mp_read_radix(&p, (char *)sets[key->idx].prime, 64)) != MP_OKAY) { goto error; }
/* calculate barrett stuff */
mp_set(&mu, 1);
mp_lshd(&mu, 2 * USED(&p));
if ((err = mp_div(&mu, &p, &mu, NULL)) != MP_OKAY) { goto error; }
/* get bA */
if ((err = ecc_mulmod(&b, &pubkey.pubkey, &pubkey.pubkey, &p)) != CRYPT_OK) { goto done; }
/* get bA + Y */
if ((err = add_point(&pubkey.pubkey, &key->pubkey, &pubkey.pubkey, &p, &mu)) != CRYPT_OK) { goto done; }
/* get mG */
if ((err = mp_read_radix(&mG->x, (char *)sets[key->idx].Gx, 64)) != MP_OKAY) { goto error; }
if ((err = mp_read_radix(&mG->y, (char *)sets[key->idx].Gy, 64)) != MP_OKAY) { goto error; }
if ((err = ecc_mulmod(&m, mG, mG, &p)) != CRYPT_OK) { goto done; }
/* compare mG to bA + Y */
if (mp_cmp(&mG->x, &pubkey.pubkey.x) == MP_EQ && mp_cmp(&mG->y, &pubkey.pubkey.y) == MP_EQ) {
*stat = 1;
}
/* clear up and return */
err = CRYPT_OK;
goto done;
error:
err = mpi_to_ltc_error(err);
done:
del_point(mG);
ecc_free(&pubkey);
mp_clear_multi(&p, &m, &b, &mu, NULL);
return err;
}

18
examples/ch1-01.c Normal file
View File

@@ -0,0 +1,18 @@
/*
* Name : ch1-01.c
* Purpose : Demonstration of a basic libtomcrypt program
* Author : Tom St Denis
*
* History : v0.79 Initial release
*/
/* ch1-01-1 */
/* Include the default headers and libtomcrypt headers */
#include <mycrypt.h>
int main(void)
{
return 0;
}
/* ch1-01-1 */

25
examples/ch1-02.c Normal file
View File

@@ -0,0 +1,25 @@
/*
* Name : ch1-02.c
* Purpose : Demonstration of error handling
* Author : Tom St Denis
*
* History : v0.79 Initial release
*/
/* ch1-01-1 */
#include <mycrypt.h>
int main(void)
{
int errno;
if ((errno = some_func(...)) != CRYPT_OK) {
printf("Error: %s\n", error_to_string(errno));
return EXIT_FAILURE;
}
return 0;
}
/*ch1-01-1 */

29
examples/ch1-03.c Normal file
View File

@@ -0,0 +1,29 @@
/*
* Name : ch1-03.c
* Purpose : Demonstration of variable length outputs
* Author : Tom St Denis
*
* History : v0.79 Initial release
*/
/* ch1-01-1 */
#include <mycrypt.h>
int main(void)
{
unsigned long length;
unsigned char buffer[512];
int errno;
length = sizeof(buffer);
if ((errno = some_func(..., buffer, &length)) != CRYPT_OK) {
printf("Error: %s\n", error_to_string(errno));
return EXIT_FAILURE;
}
printf("Size of output is %lu bytes\n", length);
return 0;
}
/* ch1-01-1 */

35
examples/ch2-01.c Normal file
View File

@@ -0,0 +1,35 @@
/*
* Name : ch2-01.c
* Purpose : Demonstration of reading the RNG
* Author : Tom St Denis
*
* History : v0.81 Initial release
*/
/* ch2-02-2 */
#include <mycrypt.h>
int main(void)
{
unsigned char buf[16];
unsigned long len;
int ix;
/* read the RNG */
len = rng_get_bytes(buf, sizeof(buf), NULL);
/* verify return */
if (len != sizeof(buf)) {
printf("Error: Only read %lu bytes.\n", len);
} else {
printf("Read %lu bytes\n", len);
for (ix = 0; ix < sizeof(buf); ix++) {
printf("%02x ", buf[ix]);
}
printf("\n");
}
return EXIT_SUCCESS;
}
/* ch2-02-2 */

305
gf.c Normal file
View File

@@ -0,0 +1,305 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
*
* LibTomCrypt is a library that provides various cryptographic
* algorithms in a highly modular and flexible manner.
*
* The library is free for all purposes without any express
* guarantee it works.
*
* Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org
*/
/* polynomial basis GF(2^w) routines */
#include "mycrypt.h"
#ifdef GF
#define FORLOOP for (i = 0; i < LSIZE; i++)
/* c = a + b */
void gf_add(gf_intp a, gf_intp b, gf_intp c)
{
int i;
FORLOOP c[i] = a[i]^b[i];
}
/* b = a */
void gf_copy(gf_intp a, gf_intp b)
{
int i;
FORLOOP b[i] = a[i];
}
/* a = 0 */
void gf_zero(gf_intp a)
{
int i;
FORLOOP a[i] = 0;
}
/* is a zero? */
int gf_iszero(gf_intp a)
{
int i;
FORLOOP if (a[i]) {
return 0;
}
return 1;
}
/* is a one? */
int gf_isone(gf_intp a)
{
int i;
for (i = 1; i < LSIZE; i++) {
if (a[i]) {
return 0;
}
}
return a[0] == 1;
}
/* b = a << 1*/
void gf_shl(gf_intp a, gf_intp b)
{
int i;
gf_int tmp;
gf_copy(a, tmp);
for (i = LSIZE-1; i > 0; i--)
b[i] = ((tmp[i]<<1)|((tmp[i-1]&0xFFFFFFFFUL)>>31))&0xFFFFFFFFUL;
b[0] = (tmp[0] << 1)&0xFFFFFFFFUL;
gf_zero(tmp);
}
/* b = a >> 1 */
void gf_shr(gf_intp a, gf_intp b)
{
int i;
gf_int tmp;
gf_copy(a, tmp);
for (i = 0; i < LSIZE-1; i++)
b[i] = (((tmp[i]&0xFFFFFFFFUL)>>1)|(tmp[i+1]<<31))&0xFFFFFFFFUL;
b[LSIZE-1] = (tmp[LSIZE-1]&0xFFFFFFFFUL)>>1;
gf_zero(tmp);
}
/* returns -1 if its zero, otherwise degree of a */
int gf_deg(gf_intp a)
{
int i, ii;
unsigned long t;
ii = -1;
for (i = LSIZE-1; i >= 0; i--)
if (a[i]) {
for (t = a[i], ii = 0; t; t >>= 1, ++ii);
break;
}
if (i == -1) i = 0;
return (i<<5)+ii;
}
/* c = ab */
void gf_mul(gf_intp a, gf_intp b, gf_intp c)
{
gf_int ta, tb;
int i, n;
gf_copy(a, ta);
gf_copy(b, tb);
gf_zero(c);
n = gf_deg(ta)+1;
for (i = 0; i < n; i++) {
if (ta[i>>5]&(1<<(i&31)))
gf_add(c, tb, c);
gf_shl(tb, tb);
}
gf_zero(ta);
gf_zero(tb);
}
/* q = a/b, r = a%b */
void gf_div(gf_intp a, gf_intp b, gf_intp q, gf_intp r)
{
gf_int ta, tb, shifts[LSIZE*32];
int i, magb, mag;
mag = gf_deg(a);
magb = gf_deg(b);
/* special cases */
if (magb > mag) {
gf_copy(a, r);
gf_zero(q);
return;
}
if (magb == -1) {
return;
}
/* copy locally */
gf_copy(a, ta);
gf_copy(b, tb);
gf_zero(q);
/* make shifted versions of "b" */
gf_copy(tb, shifts[0]);
for (i = 1; i <= (mag-magb); i++)
gf_shl(shifts[i-1], shifts[i]);
while (mag >= magb) {
i = (mag - magb);
q[i>>5] |= (1<<(i&31));
gf_add(ta, shifts[i], ta);
mag = gf_deg(ta);
}
gf_copy(ta, r);
gf_zero(ta);
gf_zero(tb);
zeromem(shifts, sizeof(shifts));
}
/* b = a mod m */
void gf_mod(gf_intp a, gf_intp m, gf_intp b)
{
gf_int tmp;
gf_div(a,m,tmp,b);
gf_zero(tmp);
}
/* c = ab (mod m) */
void gf_mulmod(gf_intp a, gf_intp b, gf_intp m, gf_intp c)
{
gf_int tmp;
gf_mul(a, b, tmp);
gf_mod(tmp, m, c);
gf_zero(tmp);
}
/* B = 1/A mod M */
void gf_invmod(gf_intp A, gf_intp M, gf_intp B)
{
gf_int m, n, p0, p1, p2, r, q, tmp;
/* put all variables in known setup state */
gf_zero(p0);
gf_zero(p2);
gf_copy(M, m);
gf_copy(A, n);
p0[0] = 1;
gf_div(m, n, p1, r);
gf_copy(p1, q);
/* loop until r == 0 */
while (!gf_iszero(r)) {
gf_copy(n, m);
gf_copy(r, n);
gf_div(m, n, q, r);
gf_mul(q, p1, tmp);
gf_add(tmp, p0, p2);
gf_copy(p1, p0);
gf_copy(p2, p1);
}
gf_copy(p0, B);
gf_zero(p0);
}
/* find a square root modulo a prime. Note the number of
* elements is 2^k - 1, so we must square k-2 times to get the
* square root..
*/
void gf_sqrt(gf_intp a, gf_intp M, gf_intp b)
{
int k;
k = gf_deg(M)-2;
gf_copy(a, b);
while (k--)
gf_mulmod(b, b, M, b);
}
/* c = gcd(A,B) */
void gf_gcd(gf_intp A, gf_intp B, gf_intp c)
{
gf_int a, b, r;
int n;
gf_add(A, B, r);
n = gf_deg(r);
if (gf_deg(A) > n) {
gf_copy(A, a);
gf_copy(B, b);
} else {
gf_copy(A, b);
gf_copy(B, a);
}
do {
gf_mod(a, b, r);
gf_copy(b, a);
gf_copy(r, b);
} while (!gf_iszero(r));
gf_copy(a, c);
gf_zero(a);
gf_zero(b);
}
/* returns non-zero if 'a' is irreducible */
int gf_is_prime(gf_intp a)
{
gf_int u, tmp;
int m, n;
gf_zero(u);
u[0] = 2; /* u(x) = x */
m = gf_deg(a);
for (n = 0; n < (m/2); n++) {
gf_mulmod(u, u, a, u); /* u(x) = u(x)^2 mod a(x) */
gf_copy(u, tmp);
tmp[0] ^= 2; /* tmp(x) = u(x) - x */
gf_gcd(tmp, a, tmp); /* tmp(x) = gcd(a(x), u(x) - x) */
if (!gf_isone(tmp)) {
return 0;
}
}
return 1;
}
/* returns bytes required to store a gf_int */
int gf_size(gf_intp a)
{
int n;
n = gf_deg(a);
if (n == -1) {
return 4;
}
n = n + (32 - (n&31));
return n/8;
}
/* store a gf_int */
void gf_toraw(gf_intp a, unsigned char *dst)
{
int x, n;
n = gf_size(a)/4;
for (x = 0; x < n; x++) {
STORE32L(a[x], dst);
dst += 4;
}
}
/* read a gf_int (len == in bytes) */
void gf_readraw(gf_intp a, unsigned char *str, int len)
{
int x;
gf_zero(a);
for (x = 0; x < len/4; x++) {
LOAD32L(a[x], str);
str += 4;
}
}
#endif

41
hash_file.c Normal file
View File

@@ -0,0 +1,41 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
*
* LibTomCrypt is a library that provides various cryptographic
* algorithms in a highly modular and flexible manner.
*
* The library is free for all purposes without any express
* guarantee it works.
*
* Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org
*/
#include "mycrypt.h"
int hash_file(int hash, const char *fname, unsigned char *dst, unsigned long *outlen)
{
#ifdef NO_FILE
return CRYPT_NOP;
#else
FILE *in;
int err;
_ARGCHK(fname != NULL);
_ARGCHK(dst != NULL);
_ARGCHK(outlen != NULL);
if ((err = hash_is_valid(hash)) != CRYPT_OK) {
return err;
}
in = fopen(fname, "rb");
if (in == NULL) {
return CRYPT_FILE_NOTFOUND;
}
err = hash_filehandle(hash, in, dst, outlen);
if (fclose(in) != 0) {
return CRYPT_ERROR;
}
return err;
#endif
}

49
hash_filehandle.c Normal file
View File

@@ -0,0 +1,49 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
*
* LibTomCrypt is a library that provides various cryptographic
* algorithms in a highly modular and flexible manner.
*
* The library is free for all purposes without any express
* guarantee it works.
*
* Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org
*/
#include "mycrypt.h"
int hash_filehandle(int hash, FILE *in, unsigned char *dst, unsigned long *outlen)
{
#ifdef NO_FILE
return CRYPT_NOP;
#else
hash_state md;
unsigned char buf[512];
size_t x;
int err;
_ARGCHK(dst != NULL);
_ARGCHK(outlen != NULL);
_ARGCHK(in != NULL);
if ((err = hash_is_valid(hash)) != CRYPT_OK) {
return err;
}
if (*outlen < hash_descriptor[hash].hashsize) {
return CRYPT_BUFFER_OVERFLOW;
}
*outlen = hash_descriptor[hash].hashsize;
hash_descriptor[hash].init(&md);
do {
x = fread(buf, 1, sizeof(buf), in);
hash_descriptor[hash].process(&md, buf, x);
} while (x == sizeof(buf));
hash_descriptor[hash].done(&md, dst);
#ifdef CLEAN_STACK
zeromem(buf, sizeof(buf));
#endif
return CRYPT_OK;
#endif
}

35
hash_memory.c Normal file
View File

@@ -0,0 +1,35 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
*
* LibTomCrypt is a library that provides various cryptographic
* algorithms in a highly modular and flexible manner.
*
* The library is free for all purposes without any express
* guarantee it works.
*
* Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org
*/
#include "mycrypt.h"
int hash_memory(int hash, const unsigned char *data, unsigned long len, unsigned char *dst, unsigned long *outlen)
{
hash_state md;
int err;
_ARGCHK(data != NULL);
_ARGCHK(dst != NULL);
_ARGCHK(outlen != NULL);
if ((err = hash_is_valid(hash)) != CRYPT_OK) {
return err;
}
if (*outlen < hash_descriptor[hash].hashsize) {
return CRYPT_BUFFER_OVERFLOW;
}
*outlen = hash_descriptor[hash].hashsize;
hash_descriptor[hash].init(&md);
hash_descriptor[hash].process(&md, data, len);
hash_descriptor[hash].done(&md, dst);
return CRYPT_OK;
}

84
hmac_done.c Normal file
View File

@@ -0,0 +1,84 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
*
* LibTomCrypt is a library that provides various cryptographic
* algorithms in a highly modular and flexible manner.
*
* The library is free for all purposes without any express
* guarantee it works.
*
* Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org
*/
/* Submited by Dobes Vandermeer (dobes@smartt.com) */
#include "mycrypt.h"
/*
(1) append zeros to the end of K to create a B byte string
(e.g., if K is of length 20 bytes and B=64, then K will be
appended with 44 zero bytes 0x00)
(2) XOR (bitwise exclusive-OR) the B byte string computed in step
(1) with ipad (ipad = the byte 0x36 repeated B times)
(3) append the stream of data 'text' to the B byte string resulting
from step (2)
(4) apply H to the stream generated in step (3)
(5) XOR (bitwise exclusive-OR) the B byte string computed in
step (1) with opad (opad = the byte 0x5C repeated B times.)
(6) append the H result from step (4) to the B byte string
resulting from step (5)
(7) apply H to the stream generated in step (6) and output
the result
*/
#ifdef HMAC
#define HMAC_BLOCKSIZE hash_descriptor[hash].blocksize
int hmac_done(hmac_state *hmac, unsigned char *hashOut, unsigned long *outlen)
{
unsigned char buf[MAXBLOCKSIZE];
unsigned char isha[MAXBLOCKSIZE];
unsigned long hashsize, i;
int hash, err;
_ARGCHK(hmac != NULL);
_ARGCHK(hashOut != NULL);
hash = hmac->hash;
if((err = hash_is_valid(hash)) != CRYPT_OK) {
return err;
}
/* get the hash message digest size */
hashsize = hash_descriptor[hash].hashsize;
// Get the hash of the first HMAC vector plus the data
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++) {
buf[i] = hmac->key[i] ^ 0x5C;
}
// Now calculate the "outer" hash for step (5), (6), and (7)
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, 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, sizeof(*hmac));
#endif
return CRYPT_OK;
}
#endif

96
hmac_file.c Normal file
View File

@@ -0,0 +1,96 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
*
* LibTomCrypt is a library that provides various cryptographic
* algorithms in a highly modular and flexible manner.
*
* The library is free for all purposes without any express
* guarantee it works.
*
* Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org
*/
/* Submited by Dobes Vandermeer (dobes@smartt.com) */
#include "mycrypt.h"
/*
(1) append zeros to the end of K to create a B byte string
(e.g., if K is of length 20 bytes and B=64, then K will be
appended with 44 zero bytes 0x00)
(2) XOR (bitwise exclusive-OR) the B byte string computed in step
(1) with ipad (ipad = the byte 0x36 repeated B times)
(3) append the stream of data 'text' to the B byte string resulting
from step (2)
(4) apply H to the stream generated in step (3)
(5) XOR (bitwise exclusive-OR) the B byte string computed in
step (1) with opad (opad = the byte 0x5C repeated B times.)
(6) append the H result from step (4) to the B byte string
resulting from step (5)
(7) apply H to the stream generated in step (6) and output
the result
*/
#ifdef HMAC
#define HMAC_BLOCKSIZE hash_descriptor[hash].blocksize
/* hmac_file added by Tom St Denis */
int hmac_file(int hash, const char *fname,
const unsigned char *key, unsigned long keylen,
unsigned char *dst, unsigned long *dstlen)
{
#ifdef NO_FILE
return CRYPT_NOP;
#else
hmac_state hmac;
FILE *in;
unsigned char buf[512];
size_t x;
int err;
_ARGCHK(fname != NULL);
_ARGCHK(key != NULL);
_ARGCHK(dst != NULL);
_ARGCHK(dstlen != NULL);
if((err = hash_is_valid(hash)) != CRYPT_OK) {
return err;
}
if ((err = hmac_init(&hmac, hash, key, keylen)) != CRYPT_OK) {
return err;
}
in = fopen(fname, "rb");
if (in == NULL) {
return CRYPT_FILE_NOTFOUND;
}
/* process the file contents */
do {
x = fread(buf, 1, sizeof(buf), 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));
if (fclose(in) != 0) {
return CRYPT_ERROR;
}
/* get final hmac */
if ((err = hmac_done(&hmac, dst, dstlen)) != CRYPT_OK) {
return err;
}
#ifdef CLEAN_STACK
/* clear memory */
zeromem(buf, sizeof(buf));
#endif
return CRYPT_OK;
#endif
}
#endif

87
hmac_init.c Normal file
View File

@@ -0,0 +1,87 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
*
* LibTomCrypt is a library that provides various cryptographic
* algorithms in a highly modular and flexible manner.
*
* The library is free for all purposes without any express
* guarantee it works.
*
* Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org
*/
/* Submited by Dobes Vandermeer (dobes@smartt.com) */
#include "mycrypt.h"
/*
(1) append zeros to the end of K to create a B byte string
(e.g., if K is of length 20 bytes and B=64, then K will be
appended with 44 zero bytes 0x00)
(2) XOR (bitwise exclusive-OR) the B byte string computed in step
(1) with ipad (ipad = the byte 0x36 repeated B times)
(3) append the stream of data 'text' to the B byte string resulting
from step (2)
(4) apply H to the stream generated in step (3)
(5) XOR (bitwise exclusive-OR) the B byte string computed in
step (1) with opad (opad = the byte 0x5C repeated B times.)
(6) append the H result from step (4) to the B byte string
resulting from step (5)
(7) apply H to the stream generated in step (6) and output
the result
*/
#ifdef HMAC
#define HMAC_BLOCKSIZE hash_descriptor[hash].blocksize
int hmac_init(hmac_state *hmac, int hash, const unsigned char *key, unsigned long keylen)
{
unsigned char buf[MAXBLOCKSIZE];
unsigned long hashsize;
unsigned long i, z;
int err;
_ARGCHK(hmac != NULL);
_ARGCHK(key != NULL);
if ((err = hash_is_valid(hash)) != CRYPT_OK) {
return err;
}
/* valid key length? */
if (keylen == 0) {
return CRYPT_INVALID_KEYSIZE;
}
hmac->hash = hash;
// (1) make sure we have a large enough key
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) {
return err;
}
if(hashsize < HMAC_BLOCKSIZE) {
zeromem((hmac->key) + hashsize, (size_t)(HMAC_BLOCKSIZE - hashsize));
}
keylen = hashsize;
} else {
memcpy(hmac->key, key, (size_t)keylen);
if(keylen < HMAC_BLOCKSIZE) {
zeromem((hmac->key) + keylen, (size_t)(HMAC_BLOCKSIZE - keylen));
}
}
// Create the initial vector for step (3)
for(i=0; i < HMAC_BLOCKSIZE; i++) {
buf[i] = hmac->key[i] ^ 0x36;
}
// Pre-pend that to the hash data
hash_descriptor[hash].init(&hmac->md);
hash_descriptor[hash].process(&hmac->md, buf, HMAC_BLOCKSIZE);
return CRYPT_OK;
}
#endif

67
hmac_memory.c Normal file
View File

@@ -0,0 +1,67 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
*
* LibTomCrypt is a library that provides various cryptographic
* algorithms in a highly modular and flexible manner.
*
* The library is free for all purposes without any express
* guarantee it works.
*
* Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org
*/
/* Submited by Dobes Vandermeer (dobes@smartt.com) */
#include "mycrypt.h"
/*
(1) append zeros to the end of K to create a B byte string
(e.g., if K is of length 20 bytes and B=64, then K will be
appended with 44 zero bytes 0x00)
(2) XOR (bitwise exclusive-OR) the B byte string computed in step
(1) with ipad (ipad = the byte 0x36 repeated B times)
(3) append the stream of data 'text' to the B byte string resulting
from step (2)
(4) apply H to the stream generated in step (3)
(5) XOR (bitwise exclusive-OR) the B byte string computed in
step (1) with opad (opad = the byte 0x5C repeated B times.)
(6) append the H result from step (4) to the B byte string
resulting from step (5)
(7) apply H to the stream generated in step (6) and output
the result
*/
#ifdef HMAC
#define HMAC_BLOCKSIZE hash_descriptor[hash].blocksize
int hmac_memory(int hash, const unsigned char *key, unsigned long keylen,
const unsigned char *data, unsigned long len,
unsigned char *dst, unsigned long *dstlen)
{
hmac_state hmac;
int err;
_ARGCHK(key != NULL);
_ARGCHK(data != NULL);
_ARGCHK(dst != NULL);
_ARGCHK(dstlen != NULL);
if((err = hash_is_valid(hash)) != CRYPT_OK) {
return err;
}
if ((err = hmac_init(&hmac, hash, key, keylen)) != CRYPT_OK) {
return err;
}
if ((err = hmac_process(&hmac, data, len)) != CRYPT_OK) {
return err;
}
if ((err = hmac_done(&hmac, dst, dstlen)) != CRYPT_OK) {
return err;
}
return CRYPT_OK;
}
#endif

48
hmac_process.c Normal file
View File

@@ -0,0 +1,48 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
*
* LibTomCrypt is a library that provides various cryptographic
* algorithms in a highly modular and flexible manner.
*
* The library is free for all purposes without any express
* guarantee it works.
*
* Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org
*/
/* Submited by Dobes Vandermeer (dobes@smartt.com) */
#include "mycrypt.h"
/*
(1) append zeros to the end of K to create a B byte string
(e.g., if K is of length 20 bytes and B=64, then K will be
appended with 44 zero bytes 0x00)
(2) XOR (bitwise exclusive-OR) the B byte string computed in step
(1) with ipad (ipad = the byte 0x36 repeated B times)
(3) append the stream of data 'text' to the B byte string resulting
from step (2)
(4) apply H to the stream generated in step (3)
(5) XOR (bitwise exclusive-OR) the B byte string computed in
step (1) with opad (opad = the byte 0x5C repeated B times.)
(6) append the H result from step (4) to the B byte string
resulting from step (5)
(7) apply H to the stream generated in step (6) and output
the result
*/
#ifdef HMAC
#define HMAC_BLOCKSIZE hash_descriptor[hash].blocksize
int hmac_process(hmac_state *hmac, const unsigned char *buf, unsigned long len)
{
int err;
_ARGCHK(hmac != NULL);
_ARGCHK(buf != NULL);
if ((err = hash_is_valid(hmac->hash)) != CRYPT_OK) {
return err;
}
return hash_descriptor[hmac->hash].process(&hmac->md, buf, len);
}
#endif

325
hmac_test.c Normal file
View File

@@ -0,0 +1,325 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
*
* LibTomCrypt is a library that provides various cryptographic
* algorithms in a highly modular and flexible manner.
*
* The library is free for all purposes without any express
* guarantee it works.
*
* Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org
*/
/* Submited by Dobes Vandermeer (dobes@smartt.com) */
#include "mycrypt.h"
/*
(1) append zeros to the end of K to create a B byte string
(e.g., if K is of length 20 bytes and B=64, then K will be
appended with 44 zero bytes 0x00)
(2) XOR (bitwise exclusive-OR) the B byte string computed in step
(1) with ipad (ipad = the byte 0x36 repeated B times)
(3) append the stream of data 'text' to the B byte string resulting
from step (2)
(4) apply H to the stream generated in step (3)
(5) XOR (bitwise exclusive-OR) the B byte string computed in
step (1) with opad (opad = the byte 0x5C repeated B times.)
(6) append the H result from step (4) to the B byte string
resulting from step (5)
(7) apply H to the stream generated in step (6) and output
the result
*/
#ifdef HMAC
#define HMAC_BLOCKSIZE hash_descriptor[hash].blocksize
/*
TEST CASES SOURCE:
Network Working Group P. Cheng
Request for Comments: 2202 IBM
Category: Informational R. Glenn
NIST
September 1997
Test Cases for HMAC-MD5 and HMAC-SHA-1
*/
int hmac_test(void)
{
#ifndef LTC_TEST
return CRYPT_NOP;
#else
unsigned char digest[MAXBLOCKSIZE];
int i;
static const struct hmac_test_case {
int num;
char *algo;
unsigned char key[128];
unsigned long keylen;
unsigned char data[128];
unsigned long datalen;
unsigned char digest[MAXBLOCKSIZE];
} cases[] = {
/*
3. Test Cases for HMAC-SHA-1
test_case = 1
key = 0x0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b
key_len = 20
data = "Hi Ther 20
digest = 0x4c1a03424b55e07fe7f27be1d58bb9324a9a5a04
digest-96 = 0x4c1a03424b55e07fe7f27be1
*/
{ 5, "sha1",
{0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
0x0c, 0x0c, 0x0c, 0x0c}, 20,
"Test With Truncation", 20,
{0x4c, 0x1a, 0x03, 0x42, 0x4b, 0x55, 0xe0, 0x7f, 0xe7, 0xf2,
0x7b, 0xe1, 0xd5, 0x8b, 0xb9, 0x32, 0x4a, 0x9a, 0x5a, 0x04} },
/*
test_case = 6
key = 0xaa repeated 80 times
key_len = 80
data = "Test Using Larger Than Block-Size Key - Hash Key First"
data_len = 54
digest = 0xaa4ae5e15272d00e95705637ce8a3b55ed402112
*/
{ 6, "sha1",
{0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa}, 80,
"Test Using Larger Than Block-Size Key - Hash Key First", 54,
{0xaa, 0x4a, 0xe5, 0xe1, 0x52, 0x72, 0xd0, 0x0e,
0x95, 0x70, 0x56, 0x37, 0xce, 0x8a, 0x3b, 0x55,
0xed, 0x40, 0x21, 0x12} },
/*
test_case = 7
key = 0xaa repeated 80 times
key_len = 80
data = "Test Using Larger Than Block-Size Key and Larger
Than One Block-Size Data"
data_len = 73
digest = 0xe8e99d0f45237d786d6bbaa7965c7808bbff1a91
*/
{ 7, "sha1",
{0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa}, 80,
"Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data", 73,
{0xe8, 0xe9, 0x9d, 0x0f, 0x45, 0x23, 0x7d, 0x78, 0x6d,
0x6b, 0xba, 0xa7, 0x96, 0x5c, 0x78, 0x08, 0xbb, 0xff, 0x1a, 0x91} },
/*
2. Test Cases for HMAC-MD5
test_case = 1
key = 0x0b 0b 0b 0b
0b 0b 0b 0b
0b 0b 0b 0b
0b 0b 0b 0b
key_len = 16
data = "Hi There"
data_len = 8
digest = 0x92 94 72 7a
36 38 bb 1c
13 f4 8e f8
15 8b fc 9d
*/
{ 1, "md5",
{0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b}, 16,
"Hi There", 8,
{0x92, 0x94, 0x72, 0x7a, 0x36, 0x38, 0xbb, 0x1c,
0x13, 0xf4, 0x8e, 0xf8, 0x15, 0x8b, 0xfc, 0x9d} },
/*
test_case = 2
key = "Jefe"
key_len = 4
data = "what do ya want for nothing?"
data_len = 28
digest = 0x750c783e6ab0b503eaa86e310a5db738
*/
{ 2, "md5",
"Jefe", 4,
"what do ya want for nothing?", 28,
{0x75, 0x0c, 0x78, 0x3e, 0x6a, 0xb0, 0xb5, 0x03,
0xea, 0xa8, 0x6e, 0x31, 0x0a, 0x5d, 0xb7, 0x38} },
/*
test_case = 3
key = 0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
key_len 16
data = 0xdd repeated 50 times
data_len = 50
digest = 0x56be34521d144c88dbb8c733f0e8b3f6
*/
{ 3, "md5",
{0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa}, 16,
{0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd}, 50,
{0x56, 0xbe, 0x34, 0x52, 0x1d, 0x14, 0x4c, 0x88,
0xdb, 0xb8, 0xc7, 0x33, 0xf0, 0xe8, 0xb3, 0xf6} },
/*
test_case = 4
key = 0x0102030405060708090a0b0c0d0e0f10111213141516171819
key_len 25
data = 0xcd repeated 50 times
data_len = 50
digest = 0x697eaf0aca3a3aea3a75164746ffaa79
*/
{ 4, "md5",
{0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a,
0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14,
0x15, 0x16, 0x17, 0x18, 0x19}, 25,
{0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd}, 50,
{0x69, 0x7e, 0xaf, 0x0a, 0xca, 0x3a, 0x3a, 0xea,
0x3a, 0x75, 0x16, 0x47, 0x46, 0xff, 0xaa, 0x79} },
/*
test_case = 5
key = 0x0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c
key_len = 16
data = "Test With Truncation"
data_len = 20
digest = 0x56461ef2342edc00f9bab995690efd4c
digest-96 0x56461ef2342edc00f9bab995
*/
{ 5, "md5",
{0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c}, 16,
"Test With Truncation", 20,
{0x56, 0x46, 0x1e, 0xf2, 0x34, 0x2e, 0xdc, 0x00,
0xf9, 0xba, 0xb9, 0x95, 0x69, 0x0e, 0xfd, 0x4c} },
/*
test_case = 6
key = 0xaa repeated 80 times
key_len = 80
data = "Test Using Larger Than Block-Size Key - Hash
Key First"
data_len = 54
digest = 0x6b1ab7fe4bd7bf8f0b62e6ce61b9d0cd
*/
{ 6, "md5",
{0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa}, 80,
"Test Using Larger Than Block-Size Key - Hash Key First", 54,
{0x6b, 0x1a, 0xb7, 0xfe, 0x4b, 0xd7, 0xbf, 0x8f,
0x0b, 0x62, 0xe6, 0xce, 0x61, 0xb9, 0xd0, 0xcd} },
/*
test_case = 7
key = 0xaa repeated 80 times
key_len = 80
data = "Test Using Larger Than Block-Size Key and Larger
Than One Block-Size Data"
data_len = 73
digest = 0x6f630fad67cda0ee1fb1f562db3aa53e
*/
{ 7, "md5",
{0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa}, 80,
"Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data", 73,
{0x6f, 0x63, 0x0f, 0xad, 0x67, 0xcd, 0xa0, 0xee,
0x1f, 0xb1, 0xf5, 0x62, 0xdb, 0x3a, 0xa5, 0x3e} }
};
unsigned long outlen;
int err;
int tested=0,failed=0;
for(i=0; i < (int)(sizeof(cases) / sizeof(cases[0])); i++) {
int hash = find_hash(cases[i].algo);
if (hash == -1) continue;
++tested;
outlen = sizeof(digest);
if((err = hmac_memory(hash, cases[i].key, cases[i].keylen, cases[i].data, cases[i].datalen, digest, &outlen)) != CRYPT_OK) {
#if 0
printf("HMAC-%s test #%d\n", cases[i].algo, cases[i].num);
#endif
return err;
}
if(memcmp(digest, cases[i].digest, (size_t)hash_descriptor[hash].hashsize) != 0) {
#if 0
unsigned int j;
printf("\nHMAC-%s test #%d:\n", cases[i].algo, cases[i].num);
printf( "Result: 0x");
for(j=0; j < hash_descriptor[hash].hashsize; j++) {
printf("%2x ", digest[j]);
}
printf("\nCorrect: 0x");
for(j=0; j < hash_descriptor[hash].hashsize; j++) {
printf("%2x ", cases[i].digest[j]);
}
printf("\n");
#endif
failed++;
//return CRYPT_ERROR;
} else {
/* printf("HMAC-%s test #%d: Passed\n", cases[i].algo, cases[i].num); */
}
}
if (failed != 0) {
return CRYPT_FAIL_TESTVECTOR;
} else if (tested == 0) {
return CRYPT_NOP;
} else {
return CRYPT_OK;
}
#endif
}
#endif

27
is_prime.c Normal file
View File

@@ -0,0 +1,27 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
*
* LibTomCrypt is a library that provides various cryptographic
* algorithms in a highly modular and flexible manner.
*
* The library is free for all purposes without any express
* guarantee it works.
*
* Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org
*/
#include "mycrypt.h"
#ifdef MPI
/* figures out if a number is prime (MR test) */
int is_prime(mp_int *N, int *result)
{
int err;
_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;
}
#endif

862
keyring.c Normal file
View File

@@ -0,0 +1,862 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
*
* LibTomCrypt is a library that provides various cryptographic
* algorithms in a highly modular and flexible manner.
*
* The library is free for all purposes without any express
* guarantee it works.
*
* Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org
*/
/* Provides keyring functionality for libtomcrypt, Tom St Denis */
#include <mycrypt.h>
#ifdef KR
static const unsigned char key_magic[4] = { 0x12, 0x34, 0x56, 0x78 };
static const unsigned char file_magic[4] = { 0x9A, 0xBC, 0xDE, 0xF0 };
static const unsigned char sign_magic[4] = { 0x87, 0x56, 0x43, 0x21 };
static const unsigned char enc_magic[4] = { 0x0F, 0xED, 0xCB, 0xA9 };
static const unsigned long crc_table[256] = {
0x00000000UL, 0x77073096UL, 0xee0e612cUL, 0x990951baUL, 0x076dc419UL,
0x706af48fUL, 0xe963a535UL, 0x9e6495a3UL, 0x0edb8832UL, 0x79dcb8a4UL,
0xe0d5e91eUL, 0x97d2d988UL, 0x09b64c2bUL, 0x7eb17cbdUL, 0xe7b82d07UL,
0x90bf1d91UL, 0x1db71064UL, 0x6ab020f2UL, 0xf3b97148UL, 0x84be41deUL,
0x1adad47dUL, 0x6ddde4ebUL, 0xf4d4b551UL, 0x83d385c7UL, 0x136c9856UL,
0x646ba8c0UL, 0xfd62f97aUL, 0x8a65c9ecUL, 0x14015c4fUL, 0x63066cd9UL,
0xfa0f3d63UL, 0x8d080df5UL, 0x3b6e20c8UL, 0x4c69105eUL, 0xd56041e4UL,
0xa2677172UL, 0x3c03e4d1UL, 0x4b04d447UL, 0xd20d85fdUL, 0xa50ab56bUL,
0x35b5a8faUL, 0x42b2986cUL, 0xdbbbc9d6UL, 0xacbcf940UL, 0x32d86ce3UL,
0x45df5c75UL, 0xdcd60dcfUL, 0xabd13d59UL, 0x26d930acUL, 0x51de003aUL,
0xc8d75180UL, 0xbfd06116UL, 0x21b4f4b5UL, 0x56b3c423UL, 0xcfba9599UL,
0xb8bda50fUL, 0x2802b89eUL, 0x5f058808UL, 0xc60cd9b2UL, 0xb10be924UL,
0x2f6f7c87UL, 0x58684c11UL, 0xc1611dabUL, 0xb6662d3dUL, 0x76dc4190UL,
0x01db7106UL, 0x98d220bcUL, 0xefd5102aUL, 0x71b18589UL, 0x06b6b51fUL,
0x9fbfe4a5UL, 0xe8b8d433UL, 0x7807c9a2UL, 0x0f00f934UL, 0x9609a88eUL,
0xe10e9818UL, 0x7f6a0dbbUL, 0x086d3d2dUL, 0x91646c97UL, 0xe6635c01UL,
0x6b6b51f4UL, 0x1c6c6162UL, 0x856530d8UL, 0xf262004eUL, 0x6c0695edUL,
0x1b01a57bUL, 0x8208f4c1UL, 0xf50fc457UL, 0x65b0d9c6UL, 0x12b7e950UL,
0x8bbeb8eaUL, 0xfcb9887cUL, 0x62dd1ddfUL, 0x15da2d49UL, 0x8cd37cf3UL,
0xfbd44c65UL, 0x4db26158UL, 0x3ab551ceUL, 0xa3bc0074UL, 0xd4bb30e2UL,
0x4adfa541UL, 0x3dd895d7UL, 0xa4d1c46dUL, 0xd3d6f4fbUL, 0x4369e96aUL,
0x346ed9fcUL, 0xad678846UL, 0xda60b8d0UL, 0x44042d73UL, 0x33031de5UL,
0xaa0a4c5fUL, 0xdd0d7cc9UL, 0x5005713cUL, 0x270241aaUL, 0xbe0b1010UL,
0xc90c2086UL, 0x5768b525UL, 0x206f85b3UL, 0xb966d409UL, 0xce61e49fUL,
0x5edef90eUL, 0x29d9c998UL, 0xb0d09822UL, 0xc7d7a8b4UL, 0x59b33d17UL,
0x2eb40d81UL, 0xb7bd5c3bUL, 0xc0ba6cadUL, 0xedb88320UL, 0x9abfb3b6UL,
0x03b6e20cUL, 0x74b1d29aUL, 0xead54739UL, 0x9dd277afUL, 0x04db2615UL,
0x73dc1683UL, 0xe3630b12UL, 0x94643b84UL, 0x0d6d6a3eUL, 0x7a6a5aa8UL,
0xe40ecf0bUL, 0x9309ff9dUL, 0x0a00ae27UL, 0x7d079eb1UL, 0xf00f9344UL,
0x8708a3d2UL, 0x1e01f268UL, 0x6906c2feUL, 0xf762575dUL, 0x806567cbUL,
0x196c3671UL, 0x6e6b06e7UL, 0xfed41b76UL, 0x89d32be0UL, 0x10da7a5aUL,
0x67dd4accUL, 0xf9b9df6fUL, 0x8ebeeff9UL, 0x17b7be43UL, 0x60b08ed5UL,
0xd6d6a3e8UL, 0xa1d1937eUL, 0x38d8c2c4UL, 0x4fdff252UL, 0xd1bb67f1UL,
0xa6bc5767UL, 0x3fb506ddUL, 0x48b2364bUL, 0xd80d2bdaUL, 0xaf0a1b4cUL,
0x36034af6UL, 0x41047a60UL, 0xdf60efc3UL, 0xa867df55UL, 0x316e8eefUL,
0x4669be79UL, 0xcb61b38cUL, 0xbc66831aUL, 0x256fd2a0UL, 0x5268e236UL,
0xcc0c7795UL, 0xbb0b4703UL, 0x220216b9UL, 0x5505262fUL, 0xc5ba3bbeUL,
0xb2bd0b28UL, 0x2bb45a92UL, 0x5cb36a04UL, 0xc2d7ffa7UL, 0xb5d0cf31UL,
0x2cd99e8bUL, 0x5bdeae1dUL, 0x9b64c2b0UL, 0xec63f226UL, 0x756aa39cUL,
0x026d930aUL, 0x9c0906a9UL, 0xeb0e363fUL, 0x72076785UL, 0x05005713UL,
0x95bf4a82UL, 0xe2b87a14UL, 0x7bb12baeUL, 0x0cb61b38UL, 0x92d28e9bUL,
0xe5d5be0dUL, 0x7cdcefb7UL, 0x0bdbdf21UL, 0x86d3d2d4UL, 0xf1d4e242UL,
0x68ddb3f8UL, 0x1fda836eUL, 0x81be16cdUL, 0xf6b9265bUL, 0x6fb077e1UL,
0x18b74777UL, 0x88085ae6UL, 0xff0f6a70UL, 0x66063bcaUL, 0x11010b5cUL,
0x8f659effUL, 0xf862ae69UL, 0x616bffd3UL, 0x166ccf45UL, 0xa00ae278UL,
0xd70dd2eeUL, 0x4e048354UL, 0x3903b3c2UL, 0xa7672661UL, 0xd06016f7UL,
0x4969474dUL, 0x3e6e77dbUL, 0xaed16a4aUL, 0xd9d65adcUL, 0x40df0b66UL,
0x37d83bf0UL, 0xa9bcae53UL, 0xdebb9ec5UL, 0x47b2cf7fUL, 0x30b5ffe9UL,
0xbdbdf21cUL, 0xcabac28aUL, 0x53b39330UL, 0x24b4a3a6UL, 0xbad03605UL,
0xcdd70693UL, 0x54de5729UL, 0x23d967bfUL, 0xb3667a2eUL, 0xc4614ab8UL,
0x5d681b02UL, 0x2a6f2b94UL, 0xb40bbe37UL, 0xc30c8ea1UL, 0x5a05df1bUL,
0x2d02ef8dUL
};
#define DO1(buf) crc = crc_table[(crc ^ (*buf++)) & 0xff] ^ (crc >> 8);
#define DO2(buf) DO1(buf); DO1(buf);
#define DO4(buf) DO2(buf); DO2(buf);
#define DO8(buf) DO4(buf); DO4(buf);
static unsigned long crc32 (unsigned long crc, const unsigned char *buf, unsigned long len)
{
//_ARGCHK(buf != NULL && len == 0);
crc = crc ^ 0xffffffffL;
while (len >= 8) {
DO8 (buf);
len -= 8;
}
if (len > 0) {
do {
DO1 (buf);
} while (--len > 0);
}
return crc ^ 0xffffffffUL;
}
int kr_init(pk_key **pk)
{
_ARGCHK(pk != NULL);
*pk = XCALLOC(1, sizeof(pk_key));
if (*pk == NULL) {
return CRYPT_MEM;
}
(*pk)->system = NON_KEY;
return CRYPT_OK;
}
unsigned long kr_crc(const unsigned char *name, const unsigned char *email, const unsigned char *description)
{
unsigned long crc;
_ARGCHK(name != NULL);
_ARGCHK(email != NULL);
_ARGCHK(description != NULL);
crc = crc32(0UL, NULL, 0UL);
crc = crc32(crc, name, (unsigned long)MIN(MAXLEN, strlen((char *)name)));
crc = crc32(crc, email, (unsigned long)MIN(MAXLEN, strlen((char *)email)));
return crc32(crc, description, (unsigned long)MIN(MAXLEN, strlen((char *)description)));
}
pk_key *kr_find(pk_key *pk, unsigned long ID)
{
_ARGCHK(pk != NULL);
while (pk != NULL) {
if (pk->system != NON_KEY && pk->ID == ID) {
return pk;
}
pk = pk->next;
}
return NULL;
}
pk_key *kr_find_name(pk_key *pk, const char *name)
{
_ARGCHK(pk != NULL);
_ARGCHK(name != NULL);
while (pk != NULL) {
if (pk->system != NON_KEY && strncmp((char *)pk->name, (char *)name, sizeof(pk->name)-1) == 0) {
return pk;
}
pk = pk->next;
}
return NULL;
}
int kr_add(pk_key *pk, int key_type, int sys, const unsigned char *name,
const unsigned char *email, const unsigned char *description, const _pk_key *key)
{
_ARGCHK(pk != NULL);
_ARGCHK(name != NULL);
_ARGCHK(email != NULL);
_ARGCHK(description != NULL);
_ARGCHK(key != NULL);
/* check parameters */
if (key_type != PK_PRIVATE && key_type != PK_PRIVATE_OPTIMIZED && key_type != PK_PUBLIC) {
return CRYPT_PK_INVALID_TYPE;
}
if (sys != RSA_KEY && sys != DH_KEY && sys != ECC_KEY) {
return CRYPT_PK_INVALID_SYSTEM;
}
/* see if its a dupe */
if (kr_find(pk, kr_crc(name, email, description)) != NULL) {
return CRYPT_PK_DUP;
}
/* find spot in key ring */
while (pk->system != NON_KEY) {
if (pk->next == NULL) {
return CRYPT_ERROR;
}
pk = pk->next;
}
/* now we have a spot make a next spot */
pk->next = XCALLOC(1, sizeof(pk_key));
if (pk->next == NULL) {
return CRYPT_MEM;
}
pk->next->system = NON_KEY;
/* now add this new data to this ring spot */
pk->key_type = key_type;
pk->system = sys;
strncpy((char *)pk->name, (char *)name, sizeof(pk->name)-1);
strncpy((char *)pk->email, (char *)email, sizeof(pk->email)-1);
strncpy((char *)pk->description, (char *)description, sizeof(pk->description)-1);
pk->ID = kr_crc(pk->name, pk->email, pk->description);
/* clear the memory area */
zeromem(&(pk->key), sizeof(pk->key));
/* copy the key */
switch (sys) {
case RSA_KEY:
memcpy(&(pk->key.rsa), &(key->rsa), sizeof(key->rsa));
break;
case DH_KEY:
memcpy(&(pk->key.dh), &(key->dh), sizeof(key->dh));
break;
case ECC_KEY:
memcpy(&(pk->key.ecc), &(key->ecc), sizeof(key->ecc));
break;
}
return CRYPT_OK;
}
int kr_del(pk_key **_pk, unsigned long ID)
{
pk_key *ppk, *pk;
_ARGCHK(_pk != NULL);
pk = *_pk;
ppk = NULL;
while (pk->system != NON_KEY && pk->ID != ID) {
ppk = pk;
pk = pk->next;
if (pk == NULL) {
return CRYPT_PK_NOT_FOUND;
}
}
switch (pk->system) {
case RSA_KEY:
rsa_free(&(pk->key.rsa));
break;
case DH_KEY:
dh_free(&(pk->key.dh));
break;
case ECC_KEY:
ecc_free(&(pk->key.ecc));
break;
}
if (ppk == NULL) { /* the first element matches the ID */
ppk = pk->next; /* get the 2nd element */
XFREE(pk); /* free the first */
*_pk = ppk; /* make the first element the second */
} else { /* (not) first element matches the ID */
ppk->next = pk->next; /* make the previous'es next point to the current next */
XFREE(pk); /* free the element */
}
return CRYPT_OK;
}
int kr_clear(pk_key **pk)
{
int err;
_ARGCHK(pk != NULL);
while ((*pk)->system != NON_KEY) {
if ((err = kr_del(pk, (*pk)->ID)) != CRYPT_OK) {
return err;
}
}
XFREE(*pk);
*pk = NULL;
return CRYPT_OK;
}
static unsigned long _write(unsigned char *buf, unsigned long len, FILE *f, symmetric_CTR *ctr)
{
#ifdef NO_FILE
return 0;
#else
_ARGCHK(buf != NULL);
_ARGCHK(f != NULL);
if (ctr != NULL) {
if (ctr_encrypt(buf, buf, len, ctr) != CRYPT_OK) {
return 0;
}
}
return (unsigned long)fwrite(buf, 1, (size_t)len, f);
#endif
}
static unsigned long _read(unsigned char *buf, unsigned long len, FILE *f, symmetric_CTR *ctr)
{
#ifdef NO_FILE
return 0;
#else
unsigned long y;
_ARGCHK(buf != NULL);
_ARGCHK(f != NULL);
y = (unsigned long)fread(buf, 1, (size_t)len, f);
if (ctr != NULL) {
if (ctr_decrypt(buf, buf, y, ctr) != CRYPT_OK) {
return 0;
}
}
return y;
#endif
}
int kr_export(pk_key *pk, unsigned long ID, int key_type, unsigned char *out, unsigned long *outlen)
{
unsigned char buf[8192], *obuf;
pk_key *ppk;
unsigned long len;
int err;
_ARGCHK(pk != NULL);
_ARGCHK(out != NULL);
_ARGCHK(outlen != NULL);
/* find the desired key */
ppk = kr_find(pk, ID);
if (ppk == NULL) {
return CRYPT_PK_NOT_FOUND;
}
if (ppk->key_type == PK_PUBLIC && key_type != PK_PUBLIC) {
return CRYPT_PK_NOT_PRIVATE;
}
/* this makes PK_PRIVATE an alias for PK_PRIVATE_OPTIMIZED type */
if (ppk->key_type == PK_PRIVATE_OPTIMIZED && key_type == PK_PRIVATE) {
key_type = PK_PRIVATE_OPTIMIZED;
}
/* now copy the header and various other details */
memcpy(buf, key_magic, 4); /* magic info */
buf[4] = key_type; /* key type */
buf[5] = ppk->system; /* system */
STORE32L(ppk->ID, buf+6); /* key ID */
memcpy(buf+10, ppk->name, MAXLEN); /* the name */
memcpy(buf+10+MAXLEN, ppk->email, MAXLEN); /* the email */
memcpy(buf+10+MAXLEN+MAXLEN, ppk->description, MAXLEN); /* the description */
/* export key */
len = sizeof(buf) - (6 + 4 + MAXLEN*3);
obuf = buf+6+4+MAXLEN*3;
switch (ppk->system) {
case RSA_KEY:
if ((err = rsa_export(obuf, &len, key_type, &(ppk->key.rsa))) != CRYPT_OK) {
return err;
}
break;
case DH_KEY:
if ((err = dh_export(obuf, &len, key_type, &(ppk->key.dh))) != CRYPT_OK) {
return err;
}
break;
case ECC_KEY:
if ((err = ecc_export(obuf, &len, key_type, &(ppk->key.ecc))) != CRYPT_OK) {
return err;
}
break;
}
/* get the entire length of the packet */
len += 6 + 4 + 3*MAXLEN;
if (*outlen < len) {
#ifdef CLEAN_STACK
zeromem(buf, sizeof(buf));
#endif
return CRYPT_BUFFER_OVERFLOW;
} else {
*outlen = len;
memcpy(out, buf, len);
#ifdef CLEAN_STACK
zeromem(buf, sizeof(buf));
#endif
return CRYPT_OK;
}
}
int kr_import(pk_key *pk, const unsigned char *in, unsigned long inlen)
{
_pk_key key;
int sys, key_type, err;
unsigned long ID;
_ARGCHK(pk != NULL);
_ARGCHK(in != NULL);
if (inlen < 10) {
return CRYPT_INVALID_PACKET;
}
if (memcmp(in, key_magic, 4) != 0) {
return CRYPT_INVALID_PACKET;
}
key_type = in[4]; /* get type */
sys = in[5]; /* get system */
LOAD32L(ID,in+6); /* the ID */
if (ID != kr_crc(in+10, in+10+MAXLEN, in+10+MAXLEN+MAXLEN)) {
return CRYPT_INVALID_PACKET;
}
zeromem(&key, sizeof(key));
/* size of remaining packet */
inlen -= 10 + 3*MAXLEN;
switch (sys) {
case RSA_KEY:
if ((err = rsa_import(in+10+3*MAXLEN, inlen, &(key.rsa))) != CRYPT_OK) {
return err;
}
break;
case DH_KEY:
if ((err = dh_import(in+10+3*MAXLEN, inlen, &(key.dh))) != CRYPT_OK) {
return err;
}
break;
case ECC_KEY:
if ((err = ecc_import(in+10+3*MAXLEN, inlen, &(key.ecc))) != CRYPT_OK) {
return err;
}
break;
}
return kr_add(pk, key_type, sys,
in+10, /* the name */
in+10+MAXLEN, /* email address */
in+10+MAXLEN+MAXLEN, /* description */
&key);
}
int kr_load(pk_key **pk, FILE *in, symmetric_CTR *ctr)
{
unsigned char buf[8192], blen[4];
unsigned long len;
int res, err;
_ARGCHK(pk != NULL);
_ARGCHK(in != NULL);
/* init keyring */
if ((err = kr_init(pk)) != CRYPT_OK) {
return err;
}
/* read in magic bytes */
if (_read(buf, 6, in, ctr) != 6) { goto done2; }
if (memcmp(buf, file_magic, 4) != 0) {
return CRYPT_INVALID_PACKET;
}
len = (unsigned long)buf[4] | ((unsigned long)buf[5] << 8);
if (len > CRYPT) {
return CRYPT_INVALID_PACKET;
}
/* while there are lengths to read... */
while (_read(blen, 4, in, ctr) == 4) {
/* get length */
LOAD32L(len, blen);
if (len > (unsigned long)sizeof(buf)) {
return CRYPT_INVALID_PACKET;
}
if (_read(buf, len, in, ctr) != len) { goto done2; }
if ((err = kr_import(*pk, buf, len)) != CRYPT_OK) {
return err;
}
}
res = CRYPT_OK;
goto done;
done2:
res = CRYPT_ERROR;
done:
#ifdef CLEAN_STACK
zeromem(buf, sizeof(buf));
#endif
return res;
}
int kr_save(pk_key *pk, FILE *out, symmetric_CTR *ctr)
{
unsigned char buf[8192], blen[4];
unsigned long len;
int res, err;
_ARGCHK(pk != NULL);
_ARGCHK(out != NULL);
/* write out magic bytes */
memcpy(buf, file_magic, 4);
buf[4] = (unsigned char)(CRYPT&255);
buf[5] = (unsigned char)((CRYPT>>8)&255);
if (_write(buf, 6, out, ctr) != 6) { goto done2; }
while (pk->system != NON_KEY) {
len = sizeof(buf);
if ((err = kr_export(pk, pk->ID, pk->key_type, buf, &len)) != CRYPT_OK) {
return err;
}
STORE32L(len, blen);
if (_write(blen, 4, out, ctr) != 4) { goto done2; }
if (_write(buf, len, out, ctr) != len) { goto done2; }
pk = pk->next;
}
res = CRYPT_OK;
goto done;
done2:
res = CRYPT_ERROR;
done:
#ifdef CLEAN_STACK
zeromem(buf, sizeof(buf));
#endif
return res;
}
int kr_make_key(pk_key *pk, prng_state *prng, int wprng,
int sys, int keysize, const unsigned char *name,
const unsigned char *email, const unsigned char *description)
{
_pk_key key;
int key_type, err;
_ARGCHK(pk != NULL);
_ARGCHK(name != NULL);
_ARGCHK(email != NULL);
_ARGCHK(description != NULL);
/* valid PRNG? */
if ((err = prng_is_valid(wprng)) != CRYPT_OK) {
return err;
}
/* make the key first */
zeromem(&key, sizeof(key));
switch (sys) {
case RSA_KEY:
if ((err = rsa_make_key(prng, wprng, keysize, 65537, &(key.rsa))) != CRYPT_OK) {
return err;
}
key_type = key.rsa.type;
break;
case DH_KEY:
if ((err = dh_make_key(prng, wprng, keysize, &(key.dh))) != CRYPT_OK) {
return err;
}
key_type = key.dh.type;
break;
case ECC_KEY:
if ((err = ecc_make_key(prng, wprng, keysize, &(key.ecc))) != CRYPT_OK) {
return err;
}
key_type = key.ecc.type;
break;
default:
return CRYPT_PK_INVALID_SYSTEM;
}
/* now add the key */
if ((err = kr_add(pk, key_type, sys, name, email, description, &key)) != CRYPT_OK) {
return err;
}
#ifdef CLEAN_STACK
zeromem(&key, sizeof(key));
#endif
return CRYPT_OK;
}
int kr_encrypt_key(pk_key *pk, unsigned long ID,
const unsigned char *in, unsigned long inlen,
unsigned char *out, unsigned long *outlen,
prng_state *prng, int wprng, int hash)
{
unsigned char buf[8192];
unsigned long len;
pk_key *kr;
int err;
_ARGCHK(pk != NULL);
_ARGCHK(in != NULL);
_ARGCHK(out != NULL);
_ARGCHK(outlen != NULL);
/* find the key */
kr = kr_find(pk, ID);
if (kr == NULL) {
return CRYPT_PK_NOT_FOUND;
}
/* store the header */
memcpy(buf, enc_magic, 4);
/* now store the ID */
STORE32L(kr->ID,buf+4);
/* now encrypt it */
len = sizeof(buf)-12;
switch (kr->system) {
case RSA_KEY:
if ((err = rsa_encrypt_key(in, inlen, buf+12, &len, prng, wprng, &(kr->key.rsa))) != CRYPT_OK) {
return err;
}
break;
case DH_KEY:
if ((err = dh_encrypt_key(in, inlen, buf+12, &len, prng, wprng, hash, &(kr->key.dh))) != CRYPT_OK) {
return err;
}
break;
case ECC_KEY:
if ((err = ecc_encrypt_key(in, inlen, buf+12, &len, prng, wprng, hash, &(kr->key.ecc))) != CRYPT_OK) {
return err;
}
break;
}
STORE32L(len,buf+8);
len += 12;
if (len > *outlen) {
#ifdef CLEAN_STACK
zeromem(buf, sizeof(buf));
#endif
return CRYPT_BUFFER_OVERFLOW;
} else {
memcpy(out, buf, len);
#ifdef CLEAN_STACK
zeromem(buf, sizeof(buf));
#endif
*outlen = len;
return CRYPT_OK;
}
}
int kr_decrypt_key(pk_key *pk, const unsigned char *in,
unsigned char *out, unsigned long *outlen)
{
unsigned char buf[8192];
unsigned long pklen, len, ID;
pk_key *kr;
int err;
_ARGCHK(pk != NULL);
_ARGCHK(in != NULL);
_ARGCHK(out != NULL);
_ARGCHK(outlen != NULL);
/* check magic header */
if (memcmp(in, enc_magic, 4)) {
return CRYPT_INVALID_PACKET;
}
/* now try to find key */
LOAD32L(ID,in+4);
kr = kr_find(pk, ID);
if (kr == NULL) {
return CRYPT_PK_NOT_FOUND;
}
/* is it public? */
if (kr->key_type == PK_PUBLIC) {
return CRYPT_PK_NOT_PRIVATE;
}
/* now try and decrypt it */
LOAD32L(pklen,in+8);
len = sizeof(buf);
switch (kr->system) {
case RSA_KEY:
if ((err = rsa_decrypt_key(in+12, pklen, buf, &len, &(kr->key.rsa))) != CRYPT_OK) {
return err;
}
break;
case DH_KEY:
if ((err = dh_decrypt_key(in+12, pklen, buf, &len, &(kr->key.dh))) != CRYPT_OK) {
return err;
}
break;
case ECC_KEY:
if ((err = ecc_decrypt_key(in+12, pklen, buf, &len, &(kr->key.ecc))) != CRYPT_OK) {
return err;
}
break;
}
if (len > *outlen) {
#ifdef CLEAN_STACK
zeromem(buf, sizeof(buf));
#endif
return CRYPT_BUFFER_OVERFLOW;
} else {
memcpy(out, buf, len);
#ifdef CLEAN_STACK
zeromem(buf, sizeof(buf));
#endif
*outlen = len;
return CRYPT_OK;
}
}
int kr_sign_hash(pk_key *pk, unsigned long ID,
const unsigned char *in, unsigned long inlen,
unsigned char *out, unsigned long *outlen,
prng_state *prng, int wprng)
{
unsigned char buf[8192];
unsigned long len;
pk_key *kr;
int err;
_ARGCHK(pk != NULL);
_ARGCHK(in != NULL);
_ARGCHK(out != NULL);
_ARGCHK(outlen != NULL);
/* find the key */
kr = kr_find(pk, ID);
if (kr == NULL) {
return CRYPT_PK_NOT_FOUND;
}
/* is it public? */
if (kr->key_type == PK_PUBLIC) {
return CRYPT_PK_NOT_PRIVATE;
}
/* store the header */
memcpy(buf, sign_magic, 4);
/* now store the ID */
STORE32L(kr->ID,buf+4);
/* now sign it */
len = sizeof(buf)-16;
switch (kr->system) {
case RSA_KEY:
if ((err = rsa_sign_hash(in, inlen, buf+16, &len, &(kr->key.rsa))) != CRYPT_OK) {
return err;
}
break;
case DH_KEY:
if ((err = dh_sign_hash(in, inlen, buf+16, &len, prng, wprng, &(kr->key.dh))) != CRYPT_OK) {
return err;
}
break;
case ECC_KEY:
if ((err = ecc_sign_hash(in, inlen, buf+16, &len, prng, wprng, &(kr->key.ecc))) != CRYPT_OK) {
return err;
}
break;
}
STORE32L(inlen,buf+8);
STORE32L(len,buf+12);
len += 16;
if (len > *outlen) {
#ifdef CLEAN_STACK
zeromem(buf, sizeof(buf));
#endif
return CRYPT_BUFFER_OVERFLOW;
} else {
memcpy(out, buf, len);
#ifdef CLEAN_STACK
zeromem(buf, sizeof(buf));
#endif
*outlen = len;
return CRYPT_OK;
}
}
int kr_verify_hash(pk_key *pk, const unsigned char *in, const unsigned char *hash,
unsigned long hashlen, int *stat)
{
unsigned long inlen, pklen, ID;
pk_key *kr;
int err;
_ARGCHK(pk != NULL);
_ARGCHK(in != NULL);
_ARGCHK(hash != NULL);
_ARGCHK(stat != NULL);
/* default to not match */
*stat = 0;
/* check magic header */
if (memcmp(in, sign_magic, 4)) {
return CRYPT_INVALID_PACKET;
}
/* now try to find key */
LOAD32L(ID,in+4);
kr = kr_find(pk, ID);
if (kr == NULL) {
return CRYPT_PK_NOT_FOUND;
}
/* now try and verify it */
LOAD32L(inlen,in+8); /* this is the length of the original inlen */
LOAD32L(pklen,in+12); /* size of the PK packet */
if (inlen != hashlen) { /* size doesn't match means the signature is invalid */
return CRYPT_OK;
}
switch (kr->system) {
case RSA_KEY:
if ((err = rsa_verify_hash(in+16, pklen, hash, stat, &(kr->key.rsa))) != CRYPT_OK) {
return err;
}
break;
case DH_KEY:
if ((err = dh_verify_hash(in+16, pklen, hash, inlen, stat, &(kr->key.dh))) != CRYPT_OK) {
return err;
}
break;
case ECC_KEY:
if ((err = ecc_verify_hash(in+16, pklen, hash, inlen, stat, &(kr->key.ecc))) != CRYPT_OK) {
return err;
}
break;
}
return CRYPT_OK;
}
int kr_fingerprint(pk_key *pk, unsigned long ID, int hash,
unsigned char *out, unsigned long *outlen)
{
unsigned char buf[8192];
unsigned long len;
int err;
_ARGCHK(pk != NULL);
_ARGCHK(out != NULL);
_ARGCHK(outlen != NULL);
/* valid hash? */
if ((err = hash_is_valid(hash)) != CRYPT_OK) {
return err;
}
len = (unsigned long)sizeof(buf);
if ((err = kr_export(pk, ID, PK_PUBLIC, buf, &len)) != CRYPT_OK) {
return err;
}
/* now hash it */
if ((err = hash_memory(hash, buf, len, out, outlen)) != CRYPT_OK) {
return err;
}
#ifdef CLEAN_STACK
zeromem(buf, sizeof(buf));
#endif
return CRYPT_OK;
}
#endif

254
makefile Normal file
View File

@@ -0,0 +1,254 @@
# MAKEFILE for linux GCC
#
# Tom St Denis
# Modified by Clay Culver
#
# NOTE: This should later be replaced by autoconf/automake scripts, but for
# the time being this is actually pretty clean. The only ugly part is
# handling CFLAGS so that the x86 specific optimizations don't break
# a build. This is easy to remedy though, for those that have problems.
# The version
VERSION=0.95
#ch1-01-1
# Compiler and Linker Names
#CC=gcc
#LD=ld
# Archiver [makes .a files]
#AR=ar
#ARFLAGS=r
#ch1-01-1
#ch1-01-3
# Compilation flags. Note the += does not write over the user's CFLAGS!
# The rest of the flags come from the parent Dropbear makefile
CFLAGS += -c -I./
# -Werror
# 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
# compile for DEBUGING
#CFLAGS += -g3
#ch1-01-3
#These flags control how the library gets built.
#Output filenames for various targets.
LIBNAME=libtomcrypt.a
TEST=test
HASH=hashsum
CRYPT=encrypt
SMALL=small
PROF=x86_prof
TV=tv_gen
#LIBPATH-The directory for libtomcrypt to be installed to.
#INCPATH-The directory to install the header files for libtomcrypt.
#DATAPATH-The directory to install the pdf docs.
DESTDIR=
LIBPATH=/usr/lib
INCPATH=/usr/include
DATAPATH=/usr/share/doc/libtomcrypt/pdf
#List of objects to compile.
#Leave MPI built-in or force developer to link against libtommath?
MPIOBJECT=mpi.o
OBJECTS=keyring.o gf.o base64.o \
\
crypt.o crypt_find_cipher.o crypt_find_hash_any.o \
crypt_hash_is_valid.o crypt_register_hash.o crypt_unregister_prng.o \
crypt_argchk.o crypt_find_cipher_any.o crypt_find_hash_id.o \
crypt_prng_descriptor.o crypt_register_prng.o crypt_cipher_descriptor.o \
crypt_find_cipher_id.o crypt_find_prng.o crypt_prng_is_valid.o \
crypt_unregister_cipher.o crypt_cipher_is_valid.o crypt_find_hash.o \
crypt_hash_descriptor.o crypt_register_cipher.o crypt_unregister_hash.o \
\
sprng.o yarrow.o rc4.o rng_get_bytes.o rng_make_prng.o \
\
rand_prime.o is_prime.o \
\
ecc.o dh.o \
\
rsa.o rsa_exptmod.o rsa_free.o rsa_make_key.o \
\
dsa_export.o dsa_free.o dsa_import.o dsa_make_key.o dsa_sign_hash.o dsa_verify_hash.o dsa_verify_key.o \
\
xtea.o aes.o des.o safer_tab.o safer.o saferp.o rc2.o \
rc6.o rc5.o cast5.o noekeon.o blowfish.o twofish.o skipjack.o \
\
md2.o md4.o md5.o sha1.o sha256.o sha512.o tiger.o whirl.o \
rmd128.o rmd160.o \
\
packet_store_header.o packet_valid_header.o \
\
eax_addheader.o eax_decrypt.o eax_decrypt_verify_memory.o eax_done.o eax_encrypt.o \
eax_encrypt_authenticate_memory.o eax_init.o eax_test.o \
\
ocb_decrypt.o ocb_decrypt_verify_memory.o ocb_done_decrypt.o ocb_done_encrypt.o \
ocb_encrypt.o ocb_encrypt_authenticate_memory.o ocb_init.o ocb_ntz.o \
ocb_shift_xor.o ocb_test.o s_ocb_done.o \
\
omac_done.o omac_file.o omac_init.o omac_memory.o omac_process.o omac_test.o \
\
pmac_done.o pmac_file.o pmac_init.o pmac_memory.o pmac_ntz.o pmac_process.o \
pmac_shift_xor.o pmac_test.o \
\
cbc_start.o cbc_encrypt.o cbc_decrypt.o \
cfb_start.o cfb_encrypt.o cfb_decrypt.o \
ofb_start.o ofb_encrypt.o ofb_decrypt.o \
ctr_start.o ctr_encrypt.o ctr_decrypt.o \
ecb_start.o ecb_encrypt.o ecb_decrypt.o \
\
hash_file.o hash_filehandle.o hash_memory.o \
\
hmac_done.o hmac_file.o hmac_init.o hmac_memory.o hmac_process.o hmac_test.o \
\
pkcs_1_mgf1.o pkcs_1_oaep_encode.o pkcs_1_oaep_decode.o \
pkcs_1_pss_encode.o pkcs_1_pss_decode.o pkcs_1_i2osp.o pkcs_1_os2ip.o \
\
pkcs_5_1.o pkcs_5_2.o \
\
burn_stack.o zeromem.o \
$(MPIOBJECT)
TESTOBJECTS=demos/test.o
HASHOBJECTS=demos/hashsum.o
CRYPTOBJECTS=demos/encrypt.o
SMALLOBJECTS=demos/small.o
PROFS=demos/x86_prof.o
TVS=demos/tv_gen.o
#Files left over from making the crypt.pdf.
LEFTOVERS=*.dvi *.log *.aux *.toc *.idx *.ilg *.ind
#Compressed filenames
COMPRESSED=crypt.tar.bz2 crypt.zip crypt.tar.gz
#Header files used by libtomcrypt.
HEADERS=tommath.h mycrypt_cfg.h mycrypt_gf.h mycrypt_kr.h \
mycrypt_misc.h mycrypt_prng.h mycrypt_cipher.h mycrypt_hash.h \
mycrypt_macros.h mycrypt_pk.h mycrypt.h mycrypt_argchk.h \
mycrypt_custom.h mycrypt_pkcs.h
#The default rule for make builds the libtomcrypt library.
default:library mycrypt.h mycrypt_cfg.h
#These are the rules to make certain object files.
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)
$(LIBNAME): $(OBJECTS)
$(AR) $(ARFLAGS) $@ $(OBJECTS)
#This rule makes the test program included with libtomcrypt
test: library $(TESTOBJECTS)
$(CC) $(TESTOBJECTS) $(LIBNAME) -o $(TEST) $(WARN)
#This rule makes the hash program included with libtomcrypt
hashsum: library $(HASHOBJECTS)
$(CC) $(HASHOBJECTS) $(LIBNAME) -o $(HASH) $(WARN)
#makes the crypt program
crypt: library $(CRYPTOBJECTS)
$(CC) $(CRYPTOBJECTS) $(LIBNAME) -o $(CRYPT) $(WARN)
#makes the small program
small: library $(SMALLOBJECTS)
$(CC) $(SMALLOBJECTS) $(LIBNAME) -o $(SMALL) $(WARN)
x86_prof: library $(PROFS)
$(CC) $(PROFS) $(LIBNAME) -o $(PROF)
tv_gen: library $(TVS)
$(CC) $(TVS) $(LIBNAME) -o $(TV)
#make a profiled library (takes a while!!!)
#
# This will build the library with profile generation
# then run the test demo and rebuild the library.
#
# So far I've seen improvements in the MP math
#
# This works with GCC v3.3.x [tested with 3.3.3]
profiled: $(TESTOBJECTS)
make CFLAGS="$(CFLAGS) -fprofile-arcs"
$(CC) $(TESTOBJECTS) $(LIBNAME) -o $(TEST)
./test
rm -f *.a *.o test demos/test.o
make CFLAGS="$(CFLAGS) -fbranch-probabilities"
#Profiling in GCC 3.4.x is a little diff.
#
#Tested with GCC v3.4.0
profiled34: $(TESTOBJECTS)
make CFLAGS="$(CFLAGS) -fprofile-generate"
$(CC) $(TESTOBJECTS) $(LIBNAME) -lgcov -o $(TEST)
./test
rm -f *.a *.o test demos/test.o
make CFLAGS="$(CFLAGS) -fprofile-use"
#This rule installs the library and the header files. This must be run
#as root in order to have a high enough permission to write to the correct
#directories and to set the owner and group to root.
install: library docs
install -d -g root -o root $(DESTDIR)$(LIBPATH)
install -d -g root -o root $(DESTDIR)$(INCPATH)
install -d -g root -o root $(DESTDIR)$(DATAPATH)
install -g root -o root $(LIBNAME) $(DESTDIR)$(LIBPATH)
install -g root -o root $(HEADERS) $(DESTDIR)$(INCPATH)
install -g root -o root crypt.pdf $(DESTDIR)$(DATAPATH)
#This rule cleans the source tree of all compiled code, not including the pdf
#documentation.
clean:
rm -f $(OBJECTS) $(TESTOBJECTS) $(HASHOBJECTS) $(CRYPTOBJECTS) $(SMALLOBJECTS) $(LEFTOVERS) $(LIBNAME)
rm -f $(TEST) $(HASH) $(COMPRESSED) $(PROFS) $(PROF) $(TVS) $(TV)
rm -f *.a *.dll *stackdump *.lib *.exe *.obj demos/*.obj demos/*.o *.bat *.txt *.il *.da demos/*.il demos/*.da *.dyn *.dpi \
*.gcda *.gcno demos/*.gcno demos/*.gcda *~
#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
#nice pre-compiled crypt.pdf that comes with libtomcrypt! We only need to
#delete it if we are rebuilding it.
docs: crypt.tex
rm -f crypt.pdf $(LEFTOVERS)
latex crypt > /dev/null
makeindex crypt > /dev/null
latex crypt > /dev/null
latex crypt > /dev/null
dvipdf crypt
rm -f $(LEFTOVERS)
#beta
beta: clean
cd .. ; rm -rf crypt* libtomcrypt-$(VERSION)-beta ; mkdir libtomcrypt-$(VERSION)-beta ; \
cp -R ./libtomcrypt/* ./libtomcrypt-$(VERSION)-beta/ ; tar -c libtomcrypt-$(VERSION)-beta/* > crypt-$(VERSION)-beta.tar ; \
bzip2 -9vv crypt-$(VERSION)-beta.tar ; zip -9 -r crypt-$(VERSION)-beta.zip libtomcrypt-$(VERSION)-beta/*
#zipup the project (take that!)
zipup: clean docs
cd .. ; rm -rf crypt* libtomcrypt-$(VERSION) ; mkdir libtomcrypt-$(VERSION) ; \
cp -R ./libtomcrypt/* ./libtomcrypt-$(VERSION)/ ; tar -c libtomcrypt-$(VERSION)/* > crypt-$(VERSION).tar ; \
bzip2 -9vv crypt-$(VERSION).tar ; zip -9 -r crypt-$(VERSION).zip libtomcrypt-$(VERSION)/*

84
makefile.cygwin_dll Normal file
View File

@@ -0,0 +1,84 @@
default: ltc_dll
# Compilation flags. Note the += does not write over the user's CFLAGS!
CFLAGS += -I./ -Wall -Wsign-compare -W -Wno-unused -Wshadow -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 strings.o base64.o \
\
crypt.o crypt_find_cipher.o crypt_find_hash_any.o \
crypt_hash_is_valid.o crypt_register_hash.o crypt_unregister_prng.o \
crypt_argchk.o crypt_find_cipher_any.o crypt_find_hash_id.o \
crypt_prng_descriptor.o crypt_register_prng.o crypt_cipher_descriptor.o \
crypt_find_cipher_id.o crypt_find_prng.o crypt_prng_is_valid.o \
crypt_unregister_cipher.o crypt_cipher_is_valid.o crypt_find_hash.o \
crypt_hash_descriptor.o crypt_register_cipher.o crypt_unregister_hash.o \
\
sprng.o yarrow.o rc4.o rng_get_bytes.o rng_make_prng.o \
\
rand_prime.o is_prime.o \
\
ecc.o dh.o \
\
rsa.o rsa_exptmod.o rsa_free.o rsa_make_key.o \
\
dsa_export.o dsa_free.o dsa_import.o dsa_make_key.o dsa_sign_hash.o dsa_verify_hash.o dsa_verify_key.o \
\
xtea.o aes.o des.o safer_tab.o safer.o saferp.o rc2.o \
rc6.o rc5.o cast5.o noekeon.o blowfish.o twofish.o skipjack.o \
\
md2.o md4.o md5.o sha1.o sha256.o sha512.o tiger.o whirl.o \
rmd128.o rmd160.o \
\
packet_store_header.o packet_valid_header.o \
\
eax_addheader.o eax_decrypt.o eax_decrypt_verify_memory.o eax_done.o eax_encrypt.o \
eax_encrypt_authenticate_memory.o eax_init.o eax_test.o \
\
ocb_decrypt.o ocb_decrypt_verify_memory.o ocb_done_decrypt.o ocb_done_encrypt.o \
ocb_encrypt.o ocb_encrypt_authenticate_memory.o ocb_init.o ocb_ntz.o \
ocb_shift_xor.o ocb_test.o s_ocb_done.o \
\
omac_done.o omac_file.o omac_init.o omac_memory.o omac_process.o omac_test.o \
\
pmac_done.o pmac_file.o pmac_init.o pmac_memory.o pmac_ntz.o pmac_process.o \
pmac_shift_xor.o pmac_test.o \
\
cbc_start.o cbc_encrypt.o cbc_decrypt.o \
cfb_start.o cfb_encrypt.o cfb_decrypt.o \
ofb_start.o ofb_encrypt.o ofb_decrypt.o \
ctr_start.o ctr_encrypt.o ctr_decrypt.o \
ecb_start.o ecb_encrypt.o ecb_decrypt.o \
\
hash_file.o hash_filehandle.o hash_memory.o \
\
hmac_done.o hmac_file.o hmac_init.o hmac_memory.o hmac_process.o hmac_test.o \
\
pkcs_1_mgf1.o pkcs_1_oaep_encode.o pkcs_1_oaep_decode.o \
pkcs_1_pss_encode.o pkcs_1_pss_decode.o pkcs_1_i2osp.o pkcs_1_os2ip.o \
\
pkcs_5_1.o pkcs_5_2.o \
\
burn_stack.o zeromem.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

213
makefile.icc Normal file
View File

@@ -0,0 +1,213 @@
# MAKEFILE for linux ICC (Intel C compiler)
#
# Tested with ICC v8....
#
# Be aware that ICC isn't quite as stable as GCC and several optimization switches
# seem to break the code (that GCC and MSVC compile just fine). In particular
# "-ip" and "-x*" seem to break the code (ROL/ROR macro problems). As the makefile
# is shipped the code will build and execute properly.
#
# Also note that ICC often makes code that is slower than GCC. This is probably due to
# a mix of not being able to use "-ip" and just having fewer optimization algos than GCC.
#
# Tom St Denis
#ch1-01-1
# Compiler and Linker Names
CC=icc
#LD=ld
# Archiver [makes .a files]
#AR=ar
#ARFLAGS=r
# Compilation flags. Note the += does not write over the user's CFLAGS!
CFLAGS += -c -I./ -DINTEL_CC
# optimize for SPEED
#
# -mcpu= can be pentium, pentiumpro (covers PII through PIII) or pentium4
# -ax? specifies make code specifically for ? but compatible with IA-32
# -x? specifies compile solely for ? [not specifically IA-32 compatible]
#
# where ? is
# K - PIII
# W - first P4 [Williamette]
# N - P4 Northwood
# P - P4 Prescott
# B - Blend of P4 and PM [mobile]
#
# Default to just generic max opts
CFLAGS += -O3 -xN -ip
# want to see stuff?
#CFLAGS += -opt_report
#These flags control how the library gets built.
#Output filenames for various targets.
LIBNAME=libtomcrypt.a
TEST=test
HASH=hashsum
CRYPT=encrypt
SMALL=small
PROF=x86_prof
TV=tv_gen
#LIBPATH-The directory for libtomcrypt to be installed to.
#INCPATH-The directory to install the header files for libtomcrypt.
#DATAPATH-The directory to install the pdf docs.
DESTDIR=
LIBPATH=/usr/lib
INCPATH=/usr/include
DATAPATH=/usr/share/doc/libtomcrypt/pdf
#List of objects to compile.
#Leave MPI built-in or force developer to link against libtommath?
MPIOBJECT=mpi.o
OBJECTS=keyring.o gf.o strings.o base64.o \
\
crypt.o crypt_find_cipher.o crypt_find_hash_any.o \
crypt_hash_is_valid.o crypt_register_hash.o crypt_unregister_prng.o \
crypt_argchk.o crypt_find_cipher_any.o crypt_find_hash_id.o \
crypt_prng_descriptor.o crypt_register_prng.o crypt_cipher_descriptor.o \
crypt_find_cipher_id.o crypt_find_prng.o crypt_prng_is_valid.o \
crypt_unregister_cipher.o crypt_cipher_is_valid.o crypt_find_hash.o \
crypt_hash_descriptor.o crypt_register_cipher.o crypt_unregister_hash.o \
\
sprng.o yarrow.o rc4.o rng_get_bytes.o rng_make_prng.o \
\
rand_prime.o is_prime.o \
\
ecc.o dh.o \
\
rsa.o rsa_exptmod.o rsa_free.o rsa_make_key.o \
\
dsa_export.o dsa_free.o dsa_import.o dsa_make_key.o dsa_sign_hash.o dsa_verify_hash.o dsa_verify_key.o \
\
xtea.o aes.o des.o safer_tab.o safer.o saferp.o rc2.o \
rc6.o rc5.o cast5.o noekeon.o blowfish.o twofish.o skipjack.o \
\
md2.o md4.o md5.o sha1.o sha256.o sha512.o tiger.o whirl.o \
rmd128.o rmd160.o \
\
packet_store_header.o packet_valid_header.o \
\
eax_addheader.o eax_decrypt.o eax_decrypt_verify_memory.o eax_done.o eax_encrypt.o \
eax_encrypt_authenticate_memory.o eax_init.o eax_test.o \
\
ocb_decrypt.o ocb_decrypt_verify_memory.o ocb_done_decrypt.o ocb_done_encrypt.o \
ocb_encrypt.o ocb_encrypt_authenticate_memory.o ocb_init.o ocb_ntz.o \
ocb_shift_xor.o ocb_test.o s_ocb_done.o \
\
omac_done.o omac_file.o omac_init.o omac_memory.o omac_process.o omac_test.o \
\
pmac_done.o pmac_file.o pmac_init.o pmac_memory.o pmac_ntz.o pmac_process.o \
pmac_shift_xor.o pmac_test.o \
\
cbc_start.o cbc_encrypt.o cbc_decrypt.o \
cfb_start.o cfb_encrypt.o cfb_decrypt.o \
ofb_start.o ofb_encrypt.o ofb_decrypt.o \
ctr_start.o ctr_encrypt.o ctr_decrypt.o \
ecb_start.o ecb_encrypt.o ecb_decrypt.o \
\
hash_file.o hash_filehandle.o hash_memory.o \
\
hmac_done.o hmac_file.o hmac_init.o hmac_memory.o hmac_process.o hmac_test.o \
\
pkcs_1_mgf1.o pkcs_1_oaep_encode.o pkcs_1_oaep_decode.o \
pkcs_1_pss_encode.o pkcs_1_pss_decode.o pkcs_1_i2osp.o pkcs_1_os2ip.o \
\
pkcs_5_1.o pkcs_5_2.o \
\
burn_stack.o zeromem.o \
$(MPIOBJECT)
TESTOBJECTS=demos/test.o
HASHOBJECTS=demos/hashsum.o
CRYPTOBJECTS=demos/encrypt.o
SMALLOBJECTS=demos/small.o
PROFS=demos/x86_prof.o
TVS=demos/tv_gen.o
#Files left over from making the crypt.pdf.
LEFTOVERS=*.dvi *.log *.aux *.toc *.idx *.ilg *.ind
#Compressed filenames
COMPRESSED=crypt.tar.bz2 crypt.zip crypt.tar.gz
#Header files used by libtomcrypt.
HEADERS=tommath.h mycrypt_cfg.h mycrypt_gf.h mycrypt_kr.h \
mycrypt_misc.h mycrypt_prng.h mycrypt_cipher.h mycrypt_hash.h \
mycrypt_macros.h mycrypt_pk.h mycrypt.h mycrypt_argchk.h mycrypt_custom.h
#The default rule for make builds the libtomcrypt library.
default:library mycrypt.h mycrypt_cfg.h
#These are the rules to make certain object files.
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)
$(LIBNAME): $(OBJECTS)
$(AR) $(ARFLAGS) $@ $(OBJECTS)
#This rule makes the test program included with libtomcrypt
test: library $(TESTOBJECTS)
$(CC) $(TESTOBJECTS) $(LIBNAME) -o $(TEST) $(WARN)
#This rule makes the hash program included with libtomcrypt
hashsum: library $(HASHOBJECTS)
$(CC) $(HASHOBJECTS) $(LIBNAME) -o $(HASH) $(WARN)
#makes the crypt program
crypt: library $(CRYPTOBJECTS)
$(CC) $(CRYPTOBJECTS) $(LIBNAME) -o $(CRYPT) $(WARN)
#makes the small program
small: library $(SMALLOBJECTS)
$(CC) $(SMALLOBJECTS) $(LIBNAME) -o $(SMALL) $(WARN)
x86_prof: library $(PROFS)
$(CC) $(PROFS) $(LIBNAME) -o $(PROF)
tv_gen: library $(TVS)
$(CC) $(TVS) $(LIBNAME) -o $(TV)
#make a profiled library (takes a while!!!)
#
# This will build the library with profile generation
# then run the test demo and rebuild the library.
#
# So far I've seen improvements in the MP math
profiled:
make -f makefile.icc CFLAGS="$(CFLAGS) -prof_gen" test
./test
rm -f *.a *.o test demos/test.o
make -f makefile.icc CFLAGS="$(CFLAGS) -prof_use"
#This rule installs the library and the header files. This must be run
#as root in order to have a high enough permission to write to the correct
#directories and to set the owner and group to root.
install: library
install -d -g root -o root $(DESTDIR)$(LIBPATH)
install -d -g root -o root $(DESTDIR)$(INCPATH)
install -g root -o root $(LIBNAME) $(DESTDIR)$(LIBPATH)
install -g root -o root $(HEADERS) $(DESTDIR)$(INCPATH)
#This rule cleans the source tree of all compiled code, not including the pdf
#documentation.
clean:
rm -f $(OBJECTS) $(TESTOBJECTS) $(HASHOBJECTS) $(CRYPTOBJECTS) $(SMALLOBJECTS) $(LEFTOVERS) $(LIBNAME)
rm -f $(TEST) $(HASH) $(COMPRESSED) $(PROFS) $(PROF) $(TVS) $(TV)
rm -f *.a *.dll *stackdump *.lib *.exe *.obj demos/*.obj demos/*.o *.bat *.txt *.il *.da demos/*.il demos/*.da *.dyn

86
makefile.msvc Normal file
View File

@@ -0,0 +1,86 @@
#MSVC Makefile [tested with MSVC 6.00 with SP5]
#
#Tom St Denis
CFLAGS = /I. /Ox /DWIN32 /W3
default: library
# leave this blank and link against libtommath if you want better link resolution
MPIOBJECT=mpi.obj
#List of objects to compile.
OBJECTS=keyring.obj gf.obj strings.obj base64.obj \
\
crypt.obj crypt_find_cipher.obj crypt_find_hash_any.obj \
crypt_hash_is_valid.obj crypt_register_hash.obj crypt_unregister_prng.obj \
crypt_argchk.obj crypt_find_cipher_any.obj crypt_find_hash_id.obj \
crypt_prng_descriptor.obj crypt_register_prng.obj crypt_cipher_descriptor.obj \
crypt_find_cipher_id.obj crypt_find_prng.obj crypt_prng_is_valid.obj \
crypt_unregister_cipher.obj crypt_cipher_is_valid.obj crypt_find_hash.obj \
crypt_hash_descriptor.obj crypt_register_cipher.obj crypt_unregister_hash.obj \
\
sprng.obj yarrow.obj rc4.obj rng_get_bytes.obj rng_make_prng.obj \
\
rand_prime.obj is_prime.obj \
\
ecc.obj dh.obj \
\
rsa.obj rsa_exptmod.obj rsa_free.obj rsa_make_key.obj \
\
dsa_export.obj dsa_free.obj dsa_import.obj dsa_make_key.obj dsa_sign_hash.obj dsa_verify_hash.obj dsa_verify_key.obj \
\
xtea.obj aes.obj des.obj safer_tab.obj safer.obj saferp.obj rc2.obj \
rc6.obj rc5.obj cast5.obj noekeon.obj blowfish.obj twofish.obj skipjack.obj \
\
md2.obj md4.obj md5.obj sha1.obj sha256.obj sha512.obj tiger.obj whirl.obj \
rmd128.obj rmd160.obj \
\
packet_store_header.obj packet_valid_header.obj \
\
eax_addheader.obj eax_decrypt.obj eax_decrypt_verify_memory.obj eax_done.obj eax_encrypt.obj \
eax_encrypt_authenticate_memory.obj eax_init.obj eax_test.obj \
\
ocb_decrypt.obj ocb_decrypt_verify_memory.obj ocb_done_decrypt.obj ocb_done_encrypt.obj \
ocb_encrypt.obj ocb_encrypt_authenticate_memory.obj ocb_init.obj ocb_ntz.obj \
ocb_shift_xor.obj ocb_test.obj s_ocb_done.obj \
\
omac_done.obj omac_file.obj omac_init.obj omac_memory.obj omac_process.obj omac_test.obj \
\
pmac_done.obj pmac_file.obj pmac_init.obj pmac_memory.obj pmac_ntz.obj pmac_process.obj \
pmac_shift_xor.obj pmac_test.obj \
\
cbc_start.obj cbc_encrypt.obj cbc_decrypt.obj \
cfb_start.obj cfb_encrypt.obj cfb_decrypt.obj \
ofb_start.obj ofb_encrypt.obj ofb_decrypt.obj \
ctr_start.obj ctr_encrypt.obj ctr_decrypt.obj \
ecb_start.obj ecb_encrypt.obj ecb_decrypt.obj \
\
hash_file.obj hash_filehandle.obj hash_memory.obj \
\
hmac_done.obj hmac_file.obj hmac_init.obj hmac_memory.obj hmac_process.obj hmac_test.obj \
\
pkcs_1_mgf1.obj pkcs_1_oaep_encode.obj pkcs_1_oaep_decode.obj \
pkcs_1_pss_encode.obj pkcs_1_pss_decode.obj pkcs_1_i2osp.obj pkcs_1_os2ip.obj \
\
pkcs_5_1.obj pkcs_5_2.obj \
\
burn_stack.obj zeromem.obj \
$(MPIOBJECT)
library: $(OBJECTS)
lib /out:tomcrypt.lib $(OBJECTS)
test.obj: demos/test.c
cl $(CFLAGS) /c demos/test.c
test: library test.obj
cl test.obj tomcrypt.lib advapi32.lib
x86_prof: demos/x86_prof.c library
cl $(CFLAGS) demos/x86_prof.c tomcrypt.lib advapi32.lib
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

214
md2.c Normal file
View File

@@ -0,0 +1,214 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
*
* LibTomCrypt is a library that provides various cryptographic
* algorithms in a highly modular and flexible manner.
*
* The library is free for all purposes without any express
* guarantee it works.
*
* Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org
*/
/* MD2 (RFC 1319) hash function implementation by Tom St Denis */
#include "mycrypt.h"
#ifdef MD2
const struct _hash_descriptor md2_desc =
{
"md2",
7,
16,
16,
&md2_init,
&md2_process,
&md2_done,
&md2_test
};
static const unsigned char PI_SUBST[256] = {
41, 46, 67, 201, 162, 216, 124, 1, 61, 54, 84, 161, 236, 240, 6,
19, 98, 167, 5, 243, 192, 199, 115, 140, 152, 147, 43, 217, 188,
76, 130, 202, 30, 155, 87, 60, 253, 212, 224, 22, 103, 66, 111, 24,
138, 23, 229, 18, 190, 78, 196, 214, 218, 158, 222, 73, 160, 251,
245, 142, 187, 47, 238, 122, 169, 104, 121, 145, 21, 178, 7, 63,
148, 194, 16, 137, 11, 34, 95, 33, 128, 127, 93, 154, 90, 144, 50,
39, 53, 62, 204, 231, 191, 247, 151, 3, 255, 25, 48, 179, 72, 165,
181, 209, 215, 94, 146, 42, 172, 86, 170, 198, 79, 184, 56, 210,
150, 164, 125, 182, 118, 252, 107, 226, 156, 116, 4, 241, 69, 157,
112, 89, 100, 113, 135, 32, 134, 91, 207, 101, 230, 45, 168, 2, 27,
96, 37, 173, 174, 176, 185, 246, 28, 70, 97, 105, 52, 64, 126, 15,
85, 71, 163, 35, 221, 81, 175, 58, 195, 92, 249, 206, 186, 197,
234, 38, 44, 83, 13, 110, 133, 40, 132, 9, 211, 223, 205, 244, 65,
129, 77, 82, 106, 220, 55, 200, 108, 193, 171, 250, 36, 225, 123,
8, 12, 189, 177, 74, 120, 136, 149, 139, 227, 99, 232, 109, 233,
203, 213, 254, 59, 0, 29, 57, 242, 239, 183, 14, 102, 88, 208, 228,
166, 119, 114, 248, 235, 117, 75, 10, 49, 68, 80, 180, 143, 237,
31, 26, 219, 153, 141, 51, 159, 17, 131, 20
};
/* adds 16 bytes to the checksum */
static void md2_update_chksum(hash_state *md)
{
int j;
unsigned char L;
L = md->md2.chksum[15];
for (j = 0; j < 16; j++) {
/* 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)] & 255);
}
}
static void md2_compress(hash_state *md)
{
int j, k;
unsigned char t;
/* copy block */
for (j = 0; j < 16; j++) {
md->md2.X[16+j] = md->md2.buf[j];
md->md2.X[32+j] = md->md2.X[j] ^ md->md2.X[16+j];
}
t = (unsigned char)0;
/* do 18 rounds */
for (j = 0; j < 18; j++) {
for (k = 0; k < 48; k++) {
t = (md->md2.X[k] ^= PI_SUBST[(int)(t & 255)]);
}
t = (t + (unsigned char)j) & 255;
}
}
void md2_init(hash_state *md)
{
_ARGCHK(md != NULL);
/* MD2 uses a zero'ed state... */
zeromem(md->md2.X, sizeof(md->md2.X));
zeromem(md->md2.chksum, sizeof(md->md2.chksum));
zeromem(md->md2.buf, sizeof(md->md2.buf));
md->md2.curlen = 0;
}
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);
md->md2.curlen += n;
buf += n;
len -= n;
/* is 16 bytes full? */
if (md->md2.curlen == 16) {
md2_compress(md);
md2_update_chksum(md);
md->md2.curlen = 0;
}
}
return CRYPT_OK;
}
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++) {
md->md2.buf[i] = (unsigned char)k;
}
/* hash and update */
md2_compress(md);
md2_update_chksum(md);
/* hash checksum */
memcpy(md->md2.buf, md->md2.chksum, 16);
md2_compress(md);
/* output is lower 16 bytes of X */
memcpy(hash, md->md2.X, 16);
#ifdef CLEAN_STACK
zeromem(md, sizeof(hash_state));
#endif
return CRYPT_OK;
}
int md2_test(void)
{
#ifndef LTC_TEST
return CRYPT_NOP;
#else
static const struct {
char *msg;
unsigned char md[16];
} tests[] = {
{ "",
{0x83,0x50,0xe5,0xa3,0xe2,0x4c,0x15,0x3d,
0xf2,0x27,0x5c,0x9f,0x80,0x69,0x27,0x73
}
},
{ "a",
{0x32,0xec,0x01,0xec,0x4a,0x6d,0xac,0x72,
0xc0,0xab,0x96,0xfb,0x34,0xc0,0xb5,0xd1
}
},
{ "message digest",
{0xab,0x4f,0x49,0x6b,0xfb,0x2a,0x53,0x0b,
0x21,0x9f,0xf3,0x30,0x31,0xfe,0x06,0xb0
}
},
{ "abcdefghijklmnopqrstuvwxyz",
{0x4e,0x8d,0xdf,0xf3,0x65,0x02,0x92,0xab,
0x5a,0x41,0x08,0xc3,0xaa,0x47,0x94,0x0b
}
},
{ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
{0xda,0x33,0xde,0xf2,0xa4,0x2d,0xf1,0x39,
0x75,0x35,0x28,0x46,0xc3,0x03,0x38,0xcd
}
},
{ "12345678901234567890123456789012345678901234567890123456789012345678901234567890",
{0xd5,0x97,0x6f,0x79,0xd8,0x3d,0x3a,0x0d,
0xc9,0x80,0x6c,0x3c,0x66,0xf3,0xef,0xd8
}
}
};
int i;
hash_state md;
unsigned char buf[16];
for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) {
md2_init(&md);
md2_process(&md, (unsigned char*)tests[i].msg, (unsigned long)strlen(tests[i].msg));
md2_done(&md, buf);
if (memcmp(buf, tests[i].md, 16) != 0) {
return CRYPT_FAIL_TESTVECTOR;
}
}
return CRYPT_OK;
#endif
}
#endif

266
md4.c Normal file
View File

@@ -0,0 +1,266 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
*
* LibTomCrypt is a library that provides various cryptographic
* algorithms in a highly modular and flexible manner.
*
* The library is free for all purposes without any express
* guarantee it works.
*
* Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org
*/
/* Submitted by Dobes Vandermeer (dobes@smartt.com) */
#include "mycrypt.h"
#ifdef MD4
const struct _hash_descriptor md4_desc =
{
"md4",
6,
16,
64,
&md4_init,
&md4_process,
&md4_done,
&md4_test
};
#define S11 3
#define S12 7
#define S13 11
#define S14 19
#define S21 3
#define S22 5
#define S23 9
#define S24 13
#define S31 3
#define S32 9
#define S33 11
#define S34 15
/* F, G and H are basic MD4 functions. */
#define F(x, y, z) (z ^ (x & (y ^ z)))
#define G(x, y, z) ((x & y) | (z & (x | y)))
#define H(x, y, z) ((x) ^ (y) ^ (z))
/* ROTATE_LEFT rotates x left n bits. */
#define ROTATE_LEFT(x, n) ROL(x, n)
/* FF, GG and HH are transformations for rounds 1, 2 and 3 */
/* Rotation is separate from addition to prevent recomputation */
#define FF(a, b, c, d, x, s) { \
(a) += F ((b), (c), (d)) + (x); \
(a) = ROTATE_LEFT ((a), (s)); \
}
#define GG(a, b, c, d, x, s) { \
(a) += G ((b), (c), (d)) + (x) + 0x5a827999UL; \
(a) = ROTATE_LEFT ((a), (s)); \
}
#define HH(a, b, c, d, x, s) { \
(a) += H ((b), (c), (d)) + (x) + 0x6ed9eba1UL; \
(a) = ROTATE_LEFT ((a), (s)); \
}
#ifdef CLEAN_STACK
static void _md4_compress(hash_state *md, unsigned char *buf)
#else
static void md4_compress(hash_state *md, unsigned char *buf)
#endif
{
ulong32 x[16], a, b, c, d;
int i;
/* copy state */
a = md->md4.state[0];
b = md->md4.state[1];
c = md->md4.state[2];
d = md->md4.state[3];
/* copy the state into 512-bits into W[0..15] */
for (i = 0; i < 16; i++) {
LOAD32L(x[i], buf + (4*i));
}
/* Round 1 */
FF (a, b, c, d, x[ 0], S11); /* 1 */
FF (d, a, b, c, x[ 1], S12); /* 2 */
FF (c, d, a, b, x[ 2], S13); /* 3 */
FF (b, c, d, a, x[ 3], S14); /* 4 */
FF (a, b, c, d, x[ 4], S11); /* 5 */
FF (d, a, b, c, x[ 5], S12); /* 6 */
FF (c, d, a, b, x[ 6], S13); /* 7 */
FF (b, c, d, a, x[ 7], S14); /* 8 */
FF (a, b, c, d, x[ 8], S11); /* 9 */
FF (d, a, b, c, x[ 9], S12); /* 10 */
FF (c, d, a, b, x[10], S13); /* 11 */
FF (b, c, d, a, x[11], S14); /* 12 */
FF (a, b, c, d, x[12], S11); /* 13 */
FF (d, a, b, c, x[13], S12); /* 14 */
FF (c, d, a, b, x[14], S13); /* 15 */
FF (b, c, d, a, x[15], S14); /* 16 */
/* Round 2 */
GG (a, b, c, d, x[ 0], S21); /* 17 */
GG (d, a, b, c, x[ 4], S22); /* 18 */
GG (c, d, a, b, x[ 8], S23); /* 19 */
GG (b, c, d, a, x[12], S24); /* 20 */
GG (a, b, c, d, x[ 1], S21); /* 21 */
GG (d, a, b, c, x[ 5], S22); /* 22 */
GG (c, d, a, b, x[ 9], S23); /* 23 */
GG (b, c, d, a, x[13], S24); /* 24 */
GG (a, b, c, d, x[ 2], S21); /* 25 */
GG (d, a, b, c, x[ 6], S22); /* 26 */
GG (c, d, a, b, x[10], S23); /* 27 */
GG (b, c, d, a, x[14], S24); /* 28 */
GG (a, b, c, d, x[ 3], S21); /* 29 */
GG (d, a, b, c, x[ 7], S22); /* 30 */
GG (c, d, a, b, x[11], S23); /* 31 */
GG (b, c, d, a, x[15], S24); /* 32 */
/* Round 3 */
HH (a, b, c, d, x[ 0], S31); /* 33 */
HH (d, a, b, c, x[ 8], S32); /* 34 */
HH (c, d, a, b, x[ 4], S33); /* 35 */
HH (b, c, d, a, x[12], S34); /* 36 */
HH (a, b, c, d, x[ 2], S31); /* 37 */
HH (d, a, b, c, x[10], S32); /* 38 */
HH (c, d, a, b, x[ 6], S33); /* 39 */
HH (b, c, d, a, x[14], S34); /* 40 */
HH (a, b, c, d, x[ 1], S31); /* 41 */
HH (d, a, b, c, x[ 9], S32); /* 42 */
HH (c, d, a, b, x[ 5], S33); /* 43 */
HH (b, c, d, a, x[13], S34); /* 44 */
HH (a, b, c, d, x[ 3], S31); /* 45 */
HH (d, a, b, c, x[11], S32); /* 46 */
HH (c, d, a, b, x[ 7], S33); /* 47 */
HH (b, c, d, a, x[15], S34); /* 48 */
/* Update our state */
md->md4.state[0] = md->md4.state[0] + a;
md->md4.state[1] = md->md4.state[1] + b;
md->md4.state[2] = md->md4.state[2] + c;
md->md4.state[3] = md->md4.state[3] + d;
}
#ifdef CLEAN_STACK
static void md4_compress(hash_state *md, unsigned char *buf)
{
_md4_compress(md, buf);
burn_stack(sizeof(ulong32) * 20 + sizeof(int));
}
#endif
void md4_init(hash_state * md)
{
_ARGCHK(md != NULL);
md->md4.state[0] = 0x67452301UL;
md->md4.state[1] = 0xefcdab89UL;
md->md4.state[2] = 0x98badcfeUL;
md->md4.state[3] = 0x10325476UL;
md->md4.length = 0;
md->md4.curlen = 0;
}
HASH_PROCESS(md4_process, md4_compress, md4, 64)
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;
/* append the '1' bit */
md->md4.buf[md->md4.curlen++] = (unsigned char)0x80;
/* if the length is currently above 56 bytes we append zeros
* then compress. Then we can fall back to padding zeros and length
* encoding like normal.
*/
if (md->md4.curlen > 56) {
while (md->md4.curlen < 64) {
md->md4.buf[md->md4.curlen++] = (unsigned char)0;
}
md4_compress(md, md->md4.buf);
md->md4.curlen = 0;
}
/* pad upto 56 bytes of zeroes */
while (md->md4.curlen < 56) {
md->md4.buf[md->md4.curlen++] = (unsigned char)0;
}
/* store length */
STORE64L(md->md4.length, md->md4.buf+56);
md4_compress(md, md->md4.buf);
/* copy output */
for (i = 0; i < 4; i++) {
STORE32L(md->md4.state[i], hash+(4*i));
}
#ifdef CLEAN_STACK
zeromem(md, sizeof(hash_state));
#endif
return CRYPT_OK;
}
int md4_test(void)
{
#ifndef LTC_TEST
return CRYPT_NOP;
#else
static const struct md4_test_case {
char *input;
unsigned char digest[16];
} cases[] = {
{ "",
{0x31, 0xd6, 0xcf, 0xe0, 0xd1, 0x6a, 0xe9, 0x31,
0xb7, 0x3c, 0x59, 0xd7, 0xe0, 0xc0, 0x89, 0xc0} },
{ "a",
{0xbd, 0xe5, 0x2c, 0xb3, 0x1d, 0xe3, 0x3e, 0x46,
0x24, 0x5e, 0x05, 0xfb, 0xdb, 0xd6, 0xfb, 0x24} },
{ "abc",
{0xa4, 0x48, 0x01, 0x7a, 0xaf, 0x21, 0xd8, 0x52,
0x5f, 0xc1, 0x0a, 0xe8, 0x7a, 0xa6, 0x72, 0x9d} },
{ "message digest",
{0xd9, 0x13, 0x0a, 0x81, 0x64, 0x54, 0x9f, 0xe8,
0x18, 0x87, 0x48, 0x06, 0xe1, 0xc7, 0x01, 0x4b} },
{ "abcdefghijklmnopqrstuvwxyz",
{0xd7, 0x9e, 0x1c, 0x30, 0x8a, 0xa5, 0xbb, 0xcd,
0xee, 0xa8, 0xed, 0x63, 0xdf, 0x41, 0x2d, 0xa9} },
{ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
{0x04, 0x3f, 0x85, 0x82, 0xf2, 0x41, 0xdb, 0x35,
0x1c, 0xe6, 0x27, 0xe1, 0x53, 0xe7, 0xf0, 0xe4} },
{ "12345678901234567890123456789012345678901234567890123456789012345678901234567890",
{0xe3, 0x3b, 0x4d, 0xdc, 0x9c, 0x38, 0xf2, 0x19,
0x9c, 0x3e, 0x7b, 0x16, 0x4f, 0xcc, 0x05, 0x36} },
};
int i;
hash_state md;
unsigned char digest[16];
for(i = 0; i < (int)(sizeof(cases) / sizeof(cases[0])); i++) {
md4_init(&md);
md4_process(&md, (unsigned char *)cases[i].input, (unsigned long)strlen(cases[i].input));
md4_done(&md, digest);
if (memcmp(digest, cases[i].digest, 16) != 0) {
return CRYPT_FAIL_TESTVECTOR;
}
}
return CRYPT_OK;
#endif
}
#endif

258
md5.c Normal file
View File

@@ -0,0 +1,258 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
*
* LibTomCrypt is a library that provides various cryptographic
* algorithms in a highly modular and flexible manner.
*
* The library is free for all purposes without any express
* guarantee it works.
*
* Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org
*/
/* MD5 hash function by Tom St Denis */
#include "mycrypt.h"
#ifdef MD5
const struct _hash_descriptor md5_desc =
{
"md5",
3,
16,
64,
&md5_init,
&md5_process,
&md5_done,
&md5_test
};
#define F(x,y,z) (z ^ (x & (y ^ z)))
#define G(x,y,z) (y ^ (z & (y ^ x)))
#define H(x,y,z) (x^y^z)
#define I(x,y,z) (y^(x|(~z)))
#define FF(a,b,c,d,M,s,t) \
a = (a + F(b,c,d) + M + t); a = ROL(a, s) + b;
#define GG(a,b,c,d,M,s,t) \
a = (a + G(b,c,d) + M + t); a = ROL(a, s) + b;
#define HH(a,b,c,d,M,s,t) \
a = (a + H(b,c,d) + M + t); a = ROL(a, s) + b;
#define II(a,b,c,d,M,s,t) \
a = (a + I(b,c,d) + M + t); a = ROL(a, s) + b;
#ifdef CLEAN_STACK
static void _md5_compress(hash_state *md, unsigned char *buf)
#else
static void md5_compress(hash_state *md, unsigned char *buf)
#endif
{
ulong32 i, W[16], a, b, c, d;
/* copy the state into 512-bits into W[0..15] */
for (i = 0; i < 16; i++) {
LOAD32L(W[i], buf + (4*i));
}
/* copy state */
a = md->md5.state[0];
b = md->md5.state[1];
c = md->md5.state[2];
d = md->md5.state[3];
FF(a,b,c,d,W[0],7,0xd76aa478UL)
FF(d,a,b,c,W[1],12,0xe8c7b756UL)
FF(c,d,a,b,W[2],17,0x242070dbUL)
FF(b,c,d,a,W[3],22,0xc1bdceeeUL)
FF(a,b,c,d,W[4],7,0xf57c0fafUL)
FF(d,a,b,c,W[5],12,0x4787c62aUL)
FF(c,d,a,b,W[6],17,0xa8304613UL)
FF(b,c,d,a,W[7],22,0xfd469501UL)
FF(a,b,c,d,W[8],7,0x698098d8UL)
FF(d,a,b,c,W[9],12,0x8b44f7afUL)
FF(c,d,a,b,W[10],17,0xffff5bb1UL)
FF(b,c,d,a,W[11],22,0x895cd7beUL)
FF(a,b,c,d,W[12],7,0x6b901122UL)
FF(d,a,b,c,W[13],12,0xfd987193UL)
FF(c,d,a,b,W[14],17,0xa679438eUL)
FF(b,c,d,a,W[15],22,0x49b40821UL)
GG(a,b,c,d,W[1],5,0xf61e2562UL)
GG(d,a,b,c,W[6],9,0xc040b340UL)
GG(c,d,a,b,W[11],14,0x265e5a51UL)
GG(b,c,d,a,W[0],20,0xe9b6c7aaUL)
GG(a,b,c,d,W[5],5,0xd62f105dUL)
GG(d,a,b,c,W[10],9,0x02441453UL)
GG(c,d,a,b,W[15],14,0xd8a1e681UL)
GG(b,c,d,a,W[4],20,0xe7d3fbc8UL)
GG(a,b,c,d,W[9],5,0x21e1cde6UL)
GG(d,a,b,c,W[14],9,0xc33707d6UL)
GG(c,d,a,b,W[3],14,0xf4d50d87UL)
GG(b,c,d,a,W[8],20,0x455a14edUL)
GG(a,b,c,d,W[13],5,0xa9e3e905UL)
GG(d,a,b,c,W[2],9,0xfcefa3f8UL)
GG(c,d,a,b,W[7],14,0x676f02d9UL)
GG(b,c,d,a,W[12],20,0x8d2a4c8aUL)
HH(a,b,c,d,W[5],4,0xfffa3942UL)
HH(d,a,b,c,W[8],11,0x8771f681UL)
HH(c,d,a,b,W[11],16,0x6d9d6122UL)
HH(b,c,d,a,W[14],23,0xfde5380cUL)
HH(a,b,c,d,W[1],4,0xa4beea44UL)
HH(d,a,b,c,W[4],11,0x4bdecfa9UL)
HH(c,d,a,b,W[7],16,0xf6bb4b60UL)
HH(b,c,d,a,W[10],23,0xbebfbc70UL)
HH(a,b,c,d,W[13],4,0x289b7ec6UL)
HH(d,a,b,c,W[0],11,0xeaa127faUL)
HH(c,d,a,b,W[3],16,0xd4ef3085UL)
HH(b,c,d,a,W[6],23,0x04881d05UL)
HH(a,b,c,d,W[9],4,0xd9d4d039UL)
HH(d,a,b,c,W[12],11,0xe6db99e5UL)
HH(c,d,a,b,W[15],16,0x1fa27cf8UL)
HH(b,c,d,a,W[2],23,0xc4ac5665UL)
II(a,b,c,d,W[0],6,0xf4292244UL)
II(d,a,b,c,W[7],10,0x432aff97UL)
II(c,d,a,b,W[14],15,0xab9423a7UL)
II(b,c,d,a,W[5],21,0xfc93a039UL)
II(a,b,c,d,W[12],6,0x655b59c3UL)
II(d,a,b,c,W[3],10,0x8f0ccc92UL)
II(c,d,a,b,W[10],15,0xffeff47dUL)
II(b,c,d,a,W[1],21,0x85845dd1UL)
II(a,b,c,d,W[8],6,0x6fa87e4fUL)
II(d,a,b,c,W[15],10,0xfe2ce6e0UL)
II(c,d,a,b,W[6],15,0xa3014314UL)
II(b,c,d,a,W[13],21,0x4e0811a1UL)
II(a,b,c,d,W[4],6,0xf7537e82UL)
II(d,a,b,c,W[11],10,0xbd3af235UL)
II(c,d,a,b,W[2],15,0x2ad7d2bbUL)
II(b,c,d,a,W[9],21,0xeb86d391UL)
md->md5.state[0] = md->md5.state[0] + a;
md->md5.state[1] = md->md5.state[1] + b;
md->md5.state[2] = md->md5.state[2] + c;
md->md5.state[3] = md->md5.state[3] + d;
}
#ifdef CLEAN_STACK
static void md5_compress(hash_state *md, unsigned char *buf)
{
_md5_compress(md, buf);
burn_stack(sizeof(ulong32) * 21);
}
#endif
void md5_init(hash_state * md)
{
_ARGCHK(md != NULL);
md->md5.state[0] = 0x67452301UL;
md->md5.state[1] = 0xefcdab89UL;
md->md5.state[2] = 0x98badcfeUL;
md->md5.state[3] = 0x10325476UL;
md->md5.curlen = 0;
md->md5.length = 0;
}
HASH_PROCESS(md5_process, md5_compress, md5, 64)
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;
/* append the '1' bit */
md->md5.buf[md->md5.curlen++] = (unsigned char)0x80;
/* if the length is currently above 56 bytes we append zeros
* then compress. Then we can fall back to padding zeros and length
* encoding like normal.
*/
if (md->md5.curlen > 56) {
while (md->md5.curlen < 64) {
md->md5.buf[md->md5.curlen++] = (unsigned char)0;
}
md5_compress(md, md->md5.buf);
md->md5.curlen = 0;
}
/* pad upto 56 bytes of zeroes */
while (md->md5.curlen < 56) {
md->md5.buf[md->md5.curlen++] = (unsigned char)0;
}
/* store length */
STORE64L(md->md5.length, md->md5.buf+56);
md5_compress(md, md->md5.buf);
/* copy output */
for (i = 0; i < 4; i++) {
STORE32L(md->md5.state[i], hash+(4*i));
}
#ifdef CLEAN_STACK
zeromem(md, sizeof(hash_state));
#endif
return CRYPT_OK;
}
int md5_test(void)
{
#ifndef LTC_TEST
return CRYPT_NOP;
#else
static const struct {
char *msg;
unsigned char hash[16];
} tests[] = {
{ "",
{ 0xd4, 0x1d, 0x8c, 0xd9, 0x8f, 0x00, 0xb2, 0x04,
0xe9, 0x80, 0x09, 0x98, 0xec, 0xf8, 0x42, 0x7e } },
{ "a",
{0x0c, 0xc1, 0x75, 0xb9, 0xc0, 0xf1, 0xb6, 0xa8,
0x31, 0xc3, 0x99, 0xe2, 0x69, 0x77, 0x26, 0x61 } },
{ "abc",
{ 0x90, 0x01, 0x50, 0x98, 0x3c, 0xd2, 0x4f, 0xb0,
0xd6, 0x96, 0x3f, 0x7d, 0x28, 0xe1, 0x7f, 0x72 } },
{ "message digest",
{ 0xf9, 0x6b, 0x69, 0x7d, 0x7c, 0xb7, 0x93, 0x8d,
0x52, 0x5a, 0x2f, 0x31, 0xaa, 0xf1, 0x61, 0xd0 } },
{ "abcdefghijklmnopqrstuvwxyz",
{ 0xc3, 0xfc, 0xd3, 0xd7, 0x61, 0x92, 0xe4, 0x00,
0x7d, 0xfb, 0x49, 0x6c, 0xca, 0x67, 0xe1, 0x3b } },
{ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
{ 0xd1, 0x74, 0xab, 0x98, 0xd2, 0x77, 0xd9, 0xf5,
0xa5, 0x61, 0x1c, 0x2c, 0x9f, 0x41, 0x9d, 0x9f } },
{ "12345678901234567890123456789012345678901234567890123456789012345678901234567890",
{ 0x57, 0xed, 0xf4, 0xa2, 0x2b, 0xe3, 0xc9, 0x55,
0xac, 0x49, 0xda, 0x2e, 0x21, 0x07, 0xb6, 0x7a } },
{ NULL, { 0 } }
};
int i;
unsigned char tmp[16];
hash_state md;
for (i = 0; tests[i].msg != NULL; i++) {
md5_init(&md);
md5_process(&md, (unsigned char *)tests[i].msg, (unsigned long)strlen(tests[i].msg));
md5_done(&md, tmp);
if (memcmp(tmp, tests[i].hash, 16) != 0) {
return CRYPT_FAIL_TESTVECTOR;
}
}
return CRYPT_OK;
#endif
}
#endif

8414
mpi.c Normal file

File diff suppressed because it is too large Load Diff

83
mycrypt.h Normal file
View File

@@ -0,0 +1,83 @@
#ifndef CRYPT_H_
#define CRYPT_H_
#include <assert.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <ctype.h>
#include <limits.h>
/* if there is a custom definition header file use it */
#include <mycrypt_custom.h>
#ifdef __cplusplus
extern "C" {
#endif
/* version */
#define CRYPT 0x0095
#define SCRYPT "0.95"
/* max size of either a cipher/hash block or symmetric key [largest of the two] */
#define MAXBLOCKSIZE 128
/* descriptor table size */
/* Dropbear change - this should be smaller, saves some size */
#define TAB_SIZE 4
/* error codes [will be expanded in future releases] */
enum {
CRYPT_OK=0, /* Result OK */
CRYPT_ERROR, /* Generic Error */
CRYPT_NOP, /* Not a failure but no operation was performed */
CRYPT_INVALID_KEYSIZE, /* Invalid key size given */
CRYPT_INVALID_ROUNDS, /* Invalid number of rounds */
CRYPT_FAIL_TESTVECTOR, /* Algorithm failed test vectors */
CRYPT_BUFFER_OVERFLOW, /* Not enough space for output */
CRYPT_INVALID_PACKET, /* Invalid input packet given */
CRYPT_INVALID_PRNGSIZE, /* Invalid number of bits for a PRNG */
CRYPT_ERROR_READPRNG, /* Could not read enough from PRNG */
CRYPT_INVALID_CIPHER, /* Invalid cipher specified */
CRYPT_INVALID_HASH, /* Invalid hash specified */
CRYPT_INVALID_PRNG, /* Invalid PRNG specified */
CRYPT_MEM, /* Out of memory */
CRYPT_PK_TYPE_MISMATCH, /* Not equivalent types of PK keys */
CRYPT_PK_NOT_PRIVATE, /* Requires a private PK key */
CRYPT_INVALID_ARG, /* Generic invalid argument */
CRYPT_FILE_NOTFOUND, /* File Not Found */
CRYPT_PK_INVALID_TYPE, /* Invalid type of PK key */
CRYPT_PK_INVALID_SYSTEM,/* Invalid PK system specified */
CRYPT_PK_DUP, /* Duplicate key already in key ring */
CRYPT_PK_NOT_FOUND, /* Key not found in keyring */
CRYPT_PK_INVALID_SIZE, /* Invalid size input for PK parameters */
CRYPT_INVALID_PRIME_SIZE/* Invalid size of prime requested */
};
#include <mycrypt_cfg.h>
#include <mycrypt_macros.h>
#include <mycrypt_cipher.h>
#include <mycrypt_hash.h>
#include <mycrypt_prng.h>
#include <mycrypt_pk.h>
#include <mycrypt_gf.h>
#include <mycrypt_misc.h>
#include <mycrypt_kr.h>
#include <mycrypt_argchk.h>
#include <mycrypt_pkcs.h>
#ifdef __cplusplus
}
#endif
#endif /* CRYPT_H_ */

24
mycrypt_argchk.h Normal file
View File

@@ -0,0 +1,24 @@
/* Defines the _ARGCHK macro used within the library */
/* ch1-01-1 */
/* ARGTYPE is defined in mycrypt_cfg.h */
#if ARGTYPE == 2 || defined(NDEBUG)
#define _ARGCHK(x)
#elif ARGTYPE == 0
#include <signal.h>
/* this is the default LibTomCrypt macro */
extern void crypt_argchk(char *v, char *s, int d);
#define _ARGCHK(x) if (!(x)) { crypt_argchk(#x, __FILE__, __LINE__); }
#elif ARGTYPE == 1
/* fatal type of error */
#define _ARGCHK(x) assert((x))
#endif
/* ch1-01-1 */

78
mycrypt_cfg.h Normal file
View File

@@ -0,0 +1,78 @@
/* This is the build config file.
*
* With this you can setup what to inlcude/exclude automatically during any build. Just comment
* out the line that #define's the word for the thing you want to remove. phew!
*/
#ifndef MYCRYPT_CFG_H
#define MYCRYPT_CFG_H
/* you can change how memory allocation works ... */
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);
/* change the clock function too */
extern clock_t XCLOCK(void);
/* ch1-01-1 */
/* type of argument checking, 0=default, 1=fatal and 2=none */
#define ARGTYPE 0
/* ch1-01-1 */
/* Controls endianess and size of registers. Leave uncommented to get platform neutral [slower] code */
/* detect x86-32 machines somewhat */
#if defined(INTEL_CC) || (defined(_MSC_VER) && defined(WIN32)) || (defined(__GNUC__) && (defined(__DJGPP__) || defined(__CYGWIN__) || defined(__MINGW32__) || defined(__i386__)))
#define ENDIAN_LITTLE
#define ENDIAN_32BITWORD
#endif
/* detects MIPS R5900 processors (PS2) */
#if (defined(__R5900) || defined(R5900) || defined(__R5900__)) && (defined(_mips) || defined(__mips__) || defined(mips))
#define ENDIAN_LITTLE
#define ENDIAN_64BITWORD
#endif
/* #define ENDIAN_LITTLE */
/* #define ENDIAN_BIG */
/* #define ENDIAN_32BITWORD */
/* #define ENDIAN_64BITWORD */
#if (defined(ENDIAN_BIG) || defined(ENDIAN_LITTLE)) && !(defined(ENDIAN_32BITWORD) || defined(ENDIAN_64BITWORD))
#error You must specify a word size as well as endianess in mycrypt_cfg.h
#endif
#if !(defined(ENDIAN_BIG) || defined(ENDIAN_LITTLE))
#define ENDIAN_NEUTRAL
#endif
#ifdef YARROW
#ifndef CTR
#error YARROW requires CTR chaining mode to be defined!
#endif
#endif
/* packet code */
#if defined(MRSA) || defined(MDH) || defined(MECC)
#define PACKET
/* size of a packet header in bytes */
#define PACKET_SIZE 4
/* Section tags */
#define PACKET_SECT_RSA 0
#define PACKET_SECT_DH 1
#define PACKET_SECT_ECC 2
#define PACKET_SECT_DSA 3
/* Subsection Tags for the first three sections */
#define PACKET_SUB_KEY 0
#define PACKET_SUB_ENCRYPTED 1
#define PACKET_SUB_SIGNED 2
#define PACKET_SUB_ENC_KEY 3
#endif
#endif /* MYCRYPT_CFG_H */

Some files were not shown because too many files have changed in this diff Show More