added libtomcrypt-0.75

This commit is contained in:
Tom St Denis 2003-03-03 00:59:24 +00:00 committed by Steffen Jaeckel
commit a6a5fc648b
77 changed files with 28956 additions and 0 deletions

409
aes.c Normal file
View File

@ -0,0 +1,409 @@
/* This is an independent implementation of the encryption algorithm: */
/* */
/* RIJNDAEL by Joan Daemen and Vincent Rijmen */
/* */
/* which is a candidate algorithm in the Advanced Encryption Standard */
/* programme of the US National Institute of Standards and Technology. */
/* */
/* Copyright in this implementation is held by Dr B R Gladman but I */
/* hereby give permission for its free direct or derivative use subject */
/* to acknowledgment of its origin and compliance with any conditions */
/* that the originators of the algorithm place on its exploitation. */
/* */
/* Dr Brian Gladman (gladman@seven77.demon.co.uk) 14th January 1999 */
/* This code has been modified by Tom St Denis for libtomcrypt.a */
#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
};
#include "aes_tab.c"
#define byte(x, y) (((x)>>(8*(y)))&255)
#define f_rn(bo, bi, n, k) \
bo[n] = ft_tab[0][byte(bi[n],0)] ^ \
ft_tab[1][byte(bi[(n + 1) & 3],1)] ^ \
ft_tab[2][byte(bi[(n + 2) & 3],2)] ^ \
ft_tab[3][byte(bi[(n + 3) & 3],3)] ^ *(k + n)
#define i_rn(bo, bi, n, k) \
bo[n] = it_tab[0][byte(bi[n],0)] ^ \
it_tab[1][byte(bi[(n + 3) & 3],1)] ^ \
it_tab[2][byte(bi[(n + 2) & 3],2)] ^ \
it_tab[3][byte(bi[(n + 1) & 3],3)] ^ *(k + n)
#define ls_box(x) \
( fl_tab[0][byte(x, 0)] ^ \
fl_tab[1][byte(x, 1)] ^ \
fl_tab[2][byte(x, 2)] ^ \
fl_tab[3][byte(x, 3)] )
#define f_rl(bo, bi, n, k) \
bo[n] = fl_tab[0][byte(bi[n],0)] ^ \
fl_tab[1][byte(bi[(n + 1) & 3],1)] ^ \
fl_tab[2][byte(bi[(n + 2) & 3],2)] ^ \
fl_tab[3][byte(bi[(n + 3) & 3],3)] ^ *(k + n)
#define i_rl(bo, bi, n, k) \
bo[n] = il_tab[0][byte(bi[n],0)] ^ \
il_tab[1][byte(bi[(n + 3) & 3],1)] ^ \
il_tab[2][byte(bi[(n + 2) & 3],2)] ^ \
il_tab[3][byte(bi[(n + 1) & 3],3)] ^ *(k + n)
#define star_x(x) (((x) & 0x7f7f7f7fUL) << 1) ^ ((((x) & 0x80808080UL) >> 7) * 0x1bUL)
#define imix_col(y,x) \
u = star_x(x); \
v = star_x(u); \
w = star_x(v); \
t = w ^ (x); \
(y) = u ^ v ^ w; \
(y) ^= ROR(u ^ t, 8) ^ \
ROR(v ^ t, 16) ^ \
ROR(t,24)
#ifdef CLEAN_STACK
static int _rijndael_setup(const unsigned char *key, int keylen, int numrounds, symmetric_key *skey)
#else
int rijndael_setup(const unsigned char *key, int keylen, int numrounds, symmetric_key *skey)
#endif
{
unsigned long t, u, v, w, in_key[8];
int i, k_len;
/* check arguments */
_ARGCHK(key != NULL);
_ARGCHK(skey != NULL);
if (numrounds == 0)
numrounds = 10 + (2 * ((keylen/8)-2));
if (keylen != 16 && keylen != 24 && keylen != 32) {
return CRYPT_INVALID_KEYSIZE;
}
if (numrounds != (10 + (2 * ((keylen/8)-2)))) {
return CRYPT_INVALID_ROUNDS;
}
k_len = keylen / 4;
for (i = 0; i < k_len; i++) {
LOAD32L(in_key[i], key+(4*i));
}
skey->rijndael.k_len = k_len;
skey->rijndael.eK[0] = in_key[0]; skey->rijndael.eK[1] = in_key[1];
skey->rijndael.eK[2] = in_key[2]; skey->rijndael.eK[3] = in_key[3];
switch(k_len) {
case 4: t = skey->rijndael.eK[3];
for(i = 0; i < 10; ++i) {
t = ls_box(ROR(t, 8)) ^ rco_tab[i];
t ^= skey->rijndael.eK[4 * i]; skey->rijndael.eK[4 * i + 4] = t;
t ^= skey->rijndael.eK[4 * i + 1]; skey->rijndael.eK[4 * i + 5] = t;
t ^= skey->rijndael.eK[4 * i + 2]; skey->rijndael.eK[4 * i + 6] = t;
t ^= skey->rijndael.eK[4 * i + 3]; skey->rijndael.eK[4 * i + 7] = t;
}
break;
case 6: skey->rijndael.eK[4] = in_key[4];
t = skey->rijndael.eK[5] = in_key[5];
for(i = 0; i < 8; ++i) {
t = ls_box(ROR(t, 8)) ^ rco_tab[i];
t ^= skey->rijndael.eK[6 * i]; skey->rijndael.eK[6 * i + 6] = t;
t ^= skey->rijndael.eK[6 * i + 1]; skey->rijndael.eK[6 * i + 7] = t;
t ^= skey->rijndael.eK[6 * i + 2]; skey->rijndael.eK[6 * i + 8] = t;
t ^= skey->rijndael.eK[6 * i + 3]; skey->rijndael.eK[6 * i + 9] = t;
t ^= skey->rijndael.eK[6 * i + 4]; skey->rijndael.eK[6 * i + 10] = t;
t ^= skey->rijndael.eK[6 * i + 5]; skey->rijndael.eK[6 * i + 11] = t;
}
break;
case 8: skey->rijndael.eK[4] = in_key[4];
skey->rijndael.eK[5] = in_key[5];
skey->rijndael.eK[6] = in_key[6];
t = skey->rijndael.eK[7] = in_key[7];
for(i = 0; i < 7; ++i) {
t = ls_box(ROR(t, 8)) ^ rco_tab[i];
t ^= skey->rijndael.eK[8 * i]; skey->rijndael.eK[8 * i + 8] = t;
t ^= skey->rijndael.eK[8 * i + 1]; skey->rijndael.eK[8 * i + 9] = t;
t ^= skey->rijndael.eK[8 * i + 2]; skey->rijndael.eK[8 * i + 10] = t;
t ^= skey->rijndael.eK[8 * i + 3]; skey->rijndael.eK[8 * i + 11] = t;
t = skey->rijndael.eK[8 * i + 4] ^ ls_box(t); skey->rijndael.eK[8 * i + 12] = t;
t ^= skey->rijndael.eK[8 * i + 5]; skey->rijndael.eK[8 * i + 13] = t;
t ^= skey->rijndael.eK[8 * i + 6]; skey->rijndael.eK[8 * i + 14] = t;
t ^= skey->rijndael.eK[8 * i + 7]; skey->rijndael.eK[8 * i + 15] = t;
}
break;
}
skey->rijndael.dK[0] = skey->rijndael.eK[0];
skey->rijndael.dK[1] = skey->rijndael.eK[1];
skey->rijndael.dK[2] = skey->rijndael.eK[2];
skey->rijndael.dK[3] = skey->rijndael.eK[3];
for(i = 4; i < 4 * k_len + 24; ++i) {
imix_col(skey->rijndael.dK[i], skey->rijndael.eK[i]);
}
return CRYPT_OK;
};
#ifdef CLEAN_STACK
int rijndael_setup(const unsigned char *key, int keylen, int numrounds, symmetric_key *skey)
{
int x;
x = _rijndael_setup(key, keylen, numrounds, skey);
burn_stack(sizeof(unsigned long) * 12 + sizeof(int) * 2);
return x;
}
#endif
/* encrypt a block of text */
#define f_nround(bo, bi, k) \
f_rn(bo, bi, 0, k); \
f_rn(bo, bi, 1, k); \
f_rn(bo, bi, 2, k); \
f_rn(bo, bi, 3, k); \
k += 4
#define f_lround(bo, bi, k) \
f_rl(bo, bi, 0, k); \
f_rl(bo, bi, 1, k); \
f_rl(bo, bi, 2, k); \
f_rl(bo, bi, 3, k)
#ifdef RIJNDAEL_SMALL
static void _fnround(unsigned long *bo, unsigned long *bi, unsigned long *k)
{
f_nround(bo, bi, k);
}
static void _flround(unsigned long *bo, unsigned long *bi, unsigned long *k)
{
f_lround(bo, bi, k);
}
#undef f_nround
#define f_nround(bo, bi, k) { _fnround(bo, bi, k); k += 4; }
#undef f_lround
#define f_lround(bo, bi, k) _flround(bo, bi, k)
#endif
void rijndael_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey)
{
unsigned long b0[4], b1[4], *kp;
_ARGCHK(pt != NULL);
_ARGCHK(ct != NULL);
_ARGCHK(skey != NULL);
LOAD32L(b0[0], &pt[0]); LOAD32L(b0[1], &pt[4]);
LOAD32L(b0[2], &pt[8]); LOAD32L(b0[3], &pt[12]);
b0[0] ^= skey->rijndael.eK[0]; b0[1] ^= skey->rijndael.eK[1];
b0[2] ^= skey->rijndael.eK[2]; b0[3] ^= skey->rijndael.eK[3];
kp = skey->rijndael.eK + 4;
if(skey->rijndael.k_len > 6) {
f_nround(b1, b0, kp); f_nround(b0, b1, kp);
}
if(skey->rijndael.k_len > 4) {
f_nround(b1, b0, kp); f_nround(b0, b1, kp);
}
f_nround(b1, b0, kp); f_nround(b0, b1, kp);
f_nround(b1, b0, kp); f_nround(b0, b1, kp);
f_nround(b1, b0, kp); f_nround(b0, b1, kp);
f_nround(b1, b0, kp); f_nround(b0, b1, kp);
f_nround(b1, b0, kp); f_lround(b0, b1, kp);
STORE32L(b0[0], &ct[0]); STORE32L(b0[1], &ct[4]);
STORE32L(b0[2], &ct[8]); STORE32L(b0[3], &ct[12]);
#ifdef CLEAN_STACK
zeromem(b0, sizeof(b0));
zeromem(b1, sizeof(b1));
#endif
};
/* decrypt a block of text */
#define i_nround(bo, bi, k) \
i_rn(bo, bi, 0, k); \
i_rn(bo, bi, 1, k); \
i_rn(bo, bi, 2, k); \
i_rn(bo, bi, 3, k); \
k -= 4
#define i_lround(bo, bi, k) \
i_rl(bo, bi, 0, k); \
i_rl(bo, bi, 1, k); \
i_rl(bo, bi, 2, k); \
i_rl(bo, bi, 3, k)
#ifdef RIJNDAEL_SMALL
static void _inround(unsigned long *bo, unsigned long *bi, unsigned long *k)
{
i_nround(bo, bi, k);
}
static void _ilround(unsigned long *bo, unsigned long *bi, unsigned long *k)
{
i_lround(bo, bi, k);
}
#undef i_nround
#define i_nround(bo, bi, k) { _inround(bo, bi, k); k -= 4; }
#undef i_lround
#define i_lround(bo, bi, k) _ilround(bo, bi, k)
#endif
void rijndael_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey)
{
unsigned long b0[4], b1[4], *kp;
_ARGCHK(pt != NULL);
_ARGCHK(ct != NULL);
_ARGCHK(skey != NULL);
LOAD32L(b0[0], &ct[0]); LOAD32L(b0[1], &ct[4]);
LOAD32L(b0[2], &ct[8]); LOAD32L(b0[3], &ct[12]);
b0[0] ^= skey->rijndael.eK[4 * skey->rijndael.k_len + 24];
b0[1] ^= skey->rijndael.eK[4 * skey->rijndael.k_len + 25];
b0[2] ^= skey->rijndael.eK[4 * skey->rijndael.k_len + 26];
b0[3] ^= skey->rijndael.eK[4 * skey->rijndael.k_len + 27];
kp = skey->rijndael.dK + 4 * (skey->rijndael.k_len + 5);
if(skey->rijndael.k_len > 6) {
i_nround(b1, b0, kp); i_nround(b0, b1, kp);
}
if(skey->rijndael.k_len > 4) {
i_nround(b1, b0, kp); i_nround(b0, b1, kp);
}
i_nround(b1, b0, kp); i_nround(b0, b1, kp);
i_nround(b1, b0, kp); i_nround(b0, b1, kp);
i_nround(b1, b0, kp); i_nround(b0, b1, kp);
i_nround(b1, b0, kp); i_nround(b0, b1, kp);
i_nround(b1, b0, kp); i_lround(b0, b1, kp);
STORE32L(b0[0], &pt[0]); STORE32L(b0[1], &pt[4]);
STORE32L(b0[2], &pt[8]); STORE32L(b0[3], &pt[12]);
#ifdef CLEAN_STACK
zeromem(b0, sizeof(b0));
zeromem(b1, sizeof(b1));
#endif
};
int rijndael_test(void)
{
int errno;
static const unsigned char pt128[16] = {
0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff };
static const unsigned char key128[16] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f };
static const unsigned char ct128[16] = {
0x69, 0xc4, 0xe0, 0xd8, 0x6a, 0x7b, 0x04, 0x30,
0xd8, 0xcd, 0xb7, 0x80, 0x70, 0xb4, 0xc5, 0x5a };
static const unsigned char key192[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 };
static const unsigned char ct192[16] = {
0xdd, 0xa9, 0x7c, 0xa4, 0x86, 0x4c, 0xdf, 0xe0,
0x6e, 0xaf, 0x70, 0xa0, 0xec, 0x0d, 0x71, 0x91 };
static const unsigned char key256[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 };
static const unsigned char ct256[16] = {
0x8e, 0xa2, 0xb7, 0xca, 0x51, 0x67, 0x45, 0xbf,
0xea, 0xfc, 0x49, 0x90, 0x4b, 0x49, 0x60, 0x89 };
symmetric_key key;
unsigned char tmp[2][16];
if ((errno = rijndael_setup(key128, 16, 0, &key)) != CRYPT_OK) {
return errno;
}
rijndael_ecb_encrypt(pt128, tmp[0], &key);
rijndael_ecb_decrypt(tmp[0], tmp[1], &key);
if (memcmp(tmp[0], ct128, 16)) {
return CRYPT_FAIL_TESTVECTOR;
}
if (memcmp(tmp[1], pt128, 16)) {
return CRYPT_FAIL_TESTVECTOR;
}
if ((errno = rijndael_setup(key192, 24, 0, &key)) != CRYPT_OK) {
return errno;
}
rijndael_ecb_encrypt(pt128, tmp[0], &key);
rijndael_ecb_decrypt(tmp[0], tmp[1], &key);
if (memcmp(tmp[0], ct192, 16)) {
return CRYPT_FAIL_TESTVECTOR;
}
if (memcmp(tmp[1], pt128, 16)) {
return CRYPT_FAIL_TESTVECTOR;
}
if ((errno = rijndael_setup(key256, 32, 0, &key)) != CRYPT_OK) {
return errno;
}
rijndael_ecb_encrypt(pt128, tmp[0], &key);
rijndael_ecb_decrypt(tmp[0], tmp[1], &key);
if (memcmp(tmp[0], ct256, 16)) {
return CRYPT_FAIL_TESTVECTOR;
}
if (memcmp(tmp[1], pt128, 16)) {
return CRYPT_FAIL_TESTVECTOR;
}
return CRYPT_OK;
}
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

851
aes_tab.c Normal file
View File

@ -0,0 +1,851 @@
/* The precompute tables for AES */
static const unsigned long ft_tab[4][256] = {
{0xa56363c6UL, 0x847c7cf8UL, 0x997777eeUL, 0x8d7b7bf6UL, 0x0df2f2ffUL,
0xbd6b6bd6UL, 0xb16f6fdeUL, 0x54c5c591UL, 0x50303060UL, 0x03010102UL,
0xa96767ceUL, 0x7d2b2b56UL, 0x19fefee7UL, 0x62d7d7b5UL, 0xe6abab4dUL,
0x9a7676ecUL, 0x45caca8fUL, 0x9d82821fUL, 0x40c9c989UL, 0x877d7dfaUL,
0x15fafaefUL, 0xeb5959b2UL, 0xc947478eUL, 0x0bf0f0fbUL, 0xecadad41UL,
0x67d4d4b3UL, 0xfda2a25fUL, 0xeaafaf45UL, 0xbf9c9c23UL, 0xf7a4a453UL,
0x967272e4UL, 0x5bc0c09bUL, 0xc2b7b775UL, 0x1cfdfde1UL, 0xae93933dUL,
0x6a26264cUL, 0x5a36366cUL, 0x413f3f7eUL, 0x02f7f7f5UL, 0x4fcccc83UL,
0x5c343468UL, 0xf4a5a551UL, 0x34e5e5d1UL, 0x08f1f1f9UL, 0x937171e2UL,
0x73d8d8abUL, 0x53313162UL, 0x3f15152aUL, 0x0c040408UL, 0x52c7c795UL,
0x65232346UL, 0x5ec3c39dUL, 0x28181830UL, 0xa1969637UL, 0x0f05050aUL,
0xb59a9a2fUL, 0x0907070eUL, 0x36121224UL, 0x9b80801bUL, 0x3de2e2dfUL,
0x26ebebcdUL, 0x6927274eUL, 0xcdb2b27fUL, 0x9f7575eaUL, 0x1b090912UL,
0x9e83831dUL, 0x742c2c58UL, 0x2e1a1a34UL, 0x2d1b1b36UL, 0xb26e6edcUL,
0xee5a5ab4UL, 0xfba0a05bUL, 0xf65252a4UL, 0x4d3b3b76UL, 0x61d6d6b7UL,
0xceb3b37dUL, 0x7b292952UL, 0x3ee3e3ddUL, 0x712f2f5eUL, 0x97848413UL,
0xf55353a6UL, 0x68d1d1b9UL, 0x00000000UL, 0x2cededc1UL, 0x60202040UL,
0x1ffcfce3UL, 0xc8b1b179UL, 0xed5b5bb6UL, 0xbe6a6ad4UL, 0x46cbcb8dUL,
0xd9bebe67UL, 0x4b393972UL, 0xde4a4a94UL, 0xd44c4c98UL, 0xe85858b0UL,
0x4acfcf85UL, 0x6bd0d0bbUL, 0x2aefefc5UL, 0xe5aaaa4fUL, 0x16fbfbedUL,
0xc5434386UL, 0xd74d4d9aUL, 0x55333366UL, 0x94858511UL, 0xcf45458aUL,
0x10f9f9e9UL, 0x06020204UL, 0x817f7ffeUL, 0xf05050a0UL, 0x443c3c78UL,
0xba9f9f25UL, 0xe3a8a84bUL, 0xf35151a2UL, 0xfea3a35dUL, 0xc0404080UL,
0x8a8f8f05UL, 0xad92923fUL, 0xbc9d9d21UL, 0x48383870UL, 0x04f5f5f1UL,
0xdfbcbc63UL, 0xc1b6b677UL, 0x75dadaafUL, 0x63212142UL, 0x30101020UL,
0x1affffe5UL, 0x0ef3f3fdUL, 0x6dd2d2bfUL, 0x4ccdcd81UL, 0x140c0c18UL,
0x35131326UL, 0x2fececc3UL, 0xe15f5fbeUL, 0xa2979735UL, 0xcc444488UL,
0x3917172eUL, 0x57c4c493UL, 0xf2a7a755UL, 0x827e7efcUL, 0x473d3d7aUL,
0xac6464c8UL, 0xe75d5dbaUL, 0x2b191932UL, 0x957373e6UL, 0xa06060c0UL,
0x98818119UL, 0xd14f4f9eUL, 0x7fdcdca3UL, 0x66222244UL, 0x7e2a2a54UL,
0xab90903bUL, 0x8388880bUL, 0xca46468cUL, 0x29eeeec7UL, 0xd3b8b86bUL,
0x3c141428UL, 0x79dedea7UL, 0xe25e5ebcUL, 0x1d0b0b16UL, 0x76dbdbadUL,
0x3be0e0dbUL, 0x56323264UL, 0x4e3a3a74UL, 0x1e0a0a14UL, 0xdb494992UL,
0x0a06060cUL, 0x6c242448UL, 0xe45c5cb8UL, 0x5dc2c29fUL, 0x6ed3d3bdUL,
0xefacac43UL, 0xa66262c4UL, 0xa8919139UL, 0xa4959531UL, 0x37e4e4d3UL,
0x8b7979f2UL, 0x32e7e7d5UL, 0x43c8c88bUL, 0x5937376eUL, 0xb76d6ddaUL,
0x8c8d8d01UL, 0x64d5d5b1UL, 0xd24e4e9cUL, 0xe0a9a949UL, 0xb46c6cd8UL,
0xfa5656acUL, 0x07f4f4f3UL, 0x25eaeacfUL, 0xaf6565caUL, 0x8e7a7af4UL,
0xe9aeae47UL, 0x18080810UL, 0xd5baba6fUL, 0x887878f0UL, 0x6f25254aUL,
0x722e2e5cUL, 0x241c1c38UL, 0xf1a6a657UL, 0xc7b4b473UL, 0x51c6c697UL,
0x23e8e8cbUL, 0x7cdddda1UL, 0x9c7474e8UL, 0x211f1f3eUL, 0xdd4b4b96UL,
0xdcbdbd61UL, 0x868b8b0dUL, 0x858a8a0fUL, 0x907070e0UL, 0x423e3e7cUL,
0xc4b5b571UL, 0xaa6666ccUL, 0xd8484890UL, 0x05030306UL, 0x01f6f6f7UL,
0x120e0e1cUL, 0xa36161c2UL, 0x5f35356aUL, 0xf95757aeUL, 0xd0b9b969UL,
0x91868617UL, 0x58c1c199UL, 0x271d1d3aUL, 0xb99e9e27UL, 0x38e1e1d9UL,
0x13f8f8ebUL, 0xb398982bUL, 0x33111122UL, 0xbb6969d2UL, 0x70d9d9a9UL,
0x898e8e07UL, 0xa7949433UL, 0xb69b9b2dUL, 0x221e1e3cUL, 0x92878715UL,
0x20e9e9c9UL, 0x49cece87UL, 0xff5555aaUL, 0x78282850UL, 0x7adfdfa5UL,
0x8f8c8c03UL, 0xf8a1a159UL, 0x80898909UL, 0x170d0d1aUL, 0xdabfbf65UL,
0x31e6e6d7UL, 0xc6424284UL, 0xb86868d0UL, 0xc3414182UL, 0xb0999929UL,
0x772d2d5aUL, 0x110f0f1eUL, 0xcbb0b07bUL, 0xfc5454a8UL, 0xd6bbbb6dUL,
0x3a16162cUL},
{0x6363c6a5UL, 0x7c7cf884UL, 0x7777ee99UL, 0x7b7bf68dUL, 0xf2f2ff0dUL,
0x6b6bd6bdUL, 0x6f6fdeb1UL, 0xc5c59154UL, 0x30306050UL, 0x01010203UL,
0x6767cea9UL, 0x2b2b567dUL, 0xfefee719UL, 0xd7d7b562UL, 0xabab4de6UL,
0x7676ec9aUL, 0xcaca8f45UL, 0x82821f9dUL, 0xc9c98940UL, 0x7d7dfa87UL,
0xfafaef15UL, 0x5959b2ebUL, 0x47478ec9UL, 0xf0f0fb0bUL, 0xadad41ecUL,
0xd4d4b367UL, 0xa2a25ffdUL, 0xafaf45eaUL, 0x9c9c23bfUL, 0xa4a453f7UL,
0x7272e496UL, 0xc0c09b5bUL, 0xb7b775c2UL, 0xfdfde11cUL, 0x93933daeUL,
0x26264c6aUL, 0x36366c5aUL, 0x3f3f7e41UL, 0xf7f7f502UL, 0xcccc834fUL,
0x3434685cUL, 0xa5a551f4UL, 0xe5e5d134UL, 0xf1f1f908UL, 0x7171e293UL,
0xd8d8ab73UL, 0x31316253UL, 0x15152a3fUL, 0x0404080cUL, 0xc7c79552UL,
0x23234665UL, 0xc3c39d5eUL, 0x18183028UL, 0x969637a1UL, 0x05050a0fUL,
0x9a9a2fb5UL, 0x07070e09UL, 0x12122436UL, 0x80801b9bUL, 0xe2e2df3dUL,
0xebebcd26UL, 0x27274e69UL, 0xb2b27fcdUL, 0x7575ea9fUL, 0x0909121bUL,
0x83831d9eUL, 0x2c2c5874UL, 0x1a1a342eUL, 0x1b1b362dUL, 0x6e6edcb2UL,
0x5a5ab4eeUL, 0xa0a05bfbUL, 0x5252a4f6UL, 0x3b3b764dUL, 0xd6d6b761UL,
0xb3b37dceUL, 0x2929527bUL, 0xe3e3dd3eUL, 0x2f2f5e71UL, 0x84841397UL,
0x5353a6f5UL, 0xd1d1b968UL, 0x00000000UL, 0xededc12cUL, 0x20204060UL,
0xfcfce31fUL, 0xb1b179c8UL, 0x5b5bb6edUL, 0x6a6ad4beUL, 0xcbcb8d46UL,
0xbebe67d9UL, 0x3939724bUL, 0x4a4a94deUL, 0x4c4c98d4UL, 0x5858b0e8UL,
0xcfcf854aUL, 0xd0d0bb6bUL, 0xefefc52aUL, 0xaaaa4fe5UL, 0xfbfbed16UL,
0x434386c5UL, 0x4d4d9ad7UL, 0x33336655UL, 0x85851194UL, 0x45458acfUL,
0xf9f9e910UL, 0x02020406UL, 0x7f7ffe81UL, 0x5050a0f0UL, 0x3c3c7844UL,
0x9f9f25baUL, 0xa8a84be3UL, 0x5151a2f3UL, 0xa3a35dfeUL, 0x404080c0UL,
0x8f8f058aUL, 0x92923fadUL, 0x9d9d21bcUL, 0x38387048UL, 0xf5f5f104UL,
0xbcbc63dfUL, 0xb6b677c1UL, 0xdadaaf75UL, 0x21214263UL, 0x10102030UL,
0xffffe51aUL, 0xf3f3fd0eUL, 0xd2d2bf6dUL, 0xcdcd814cUL, 0x0c0c1814UL,
0x13132635UL, 0xececc32fUL, 0x5f5fbee1UL, 0x979735a2UL, 0x444488ccUL,
0x17172e39UL, 0xc4c49357UL, 0xa7a755f2UL, 0x7e7efc82UL, 0x3d3d7a47UL,
0x6464c8acUL, 0x5d5dbae7UL, 0x1919322bUL, 0x7373e695UL, 0x6060c0a0UL,
0x81811998UL, 0x4f4f9ed1UL, 0xdcdca37fUL, 0x22224466UL, 0x2a2a547eUL,
0x90903babUL, 0x88880b83UL, 0x46468ccaUL, 0xeeeec729UL, 0xb8b86bd3UL,
0x1414283cUL, 0xdedea779UL, 0x5e5ebce2UL, 0x0b0b161dUL, 0xdbdbad76UL,
0xe0e0db3bUL, 0x32326456UL, 0x3a3a744eUL, 0x0a0a141eUL, 0x494992dbUL,
0x06060c0aUL, 0x2424486cUL, 0x5c5cb8e4UL, 0xc2c29f5dUL, 0xd3d3bd6eUL,
0xacac43efUL, 0x6262c4a6UL, 0x919139a8UL, 0x959531a4UL, 0xe4e4d337UL,
0x7979f28bUL, 0xe7e7d532UL, 0xc8c88b43UL, 0x37376e59UL, 0x6d6ddab7UL,
0x8d8d018cUL, 0xd5d5b164UL, 0x4e4e9cd2UL, 0xa9a949e0UL, 0x6c6cd8b4UL,
0x5656acfaUL, 0xf4f4f307UL, 0xeaeacf25UL, 0x6565caafUL, 0x7a7af48eUL,
0xaeae47e9UL, 0x08081018UL, 0xbaba6fd5UL, 0x7878f088UL, 0x25254a6fUL,
0x2e2e5c72UL, 0x1c1c3824UL, 0xa6a657f1UL, 0xb4b473c7UL, 0xc6c69751UL,
0xe8e8cb23UL, 0xdddda17cUL, 0x7474e89cUL, 0x1f1f3e21UL, 0x4b4b96ddUL,
0xbdbd61dcUL, 0x8b8b0d86UL, 0x8a8a0f85UL, 0x7070e090UL, 0x3e3e7c42UL,
0xb5b571c4UL, 0x6666ccaaUL, 0x484890d8UL, 0x03030605UL, 0xf6f6f701UL,
0x0e0e1c12UL, 0x6161c2a3UL, 0x35356a5fUL, 0x5757aef9UL, 0xb9b969d0UL,
0x86861791UL, 0xc1c19958UL, 0x1d1d3a27UL, 0x9e9e27b9UL, 0xe1e1d938UL,
0xf8f8eb13UL, 0x98982bb3UL, 0x11112233UL, 0x6969d2bbUL, 0xd9d9a970UL,
0x8e8e0789UL, 0x949433a7UL, 0x9b9b2db6UL, 0x1e1e3c22UL, 0x87871592UL,
0xe9e9c920UL, 0xcece8749UL, 0x5555aaffUL, 0x28285078UL, 0xdfdfa57aUL,
0x8c8c038fUL, 0xa1a159f8UL, 0x89890980UL, 0x0d0d1a17UL, 0xbfbf65daUL,
0xe6e6d731UL, 0x424284c6UL, 0x6868d0b8UL, 0x414182c3UL, 0x999929b0UL,
0x2d2d5a77UL, 0x0f0f1e11UL, 0xb0b07bcbUL, 0x5454a8fcUL, 0xbbbb6dd6UL,
0x16162c3aUL},
{0x63c6a563UL, 0x7cf8847cUL, 0x77ee9977UL, 0x7bf68d7bUL, 0xf2ff0df2UL,
0x6bd6bd6bUL, 0x6fdeb16fUL, 0xc59154c5UL, 0x30605030UL, 0x01020301UL,
0x67cea967UL, 0x2b567d2bUL, 0xfee719feUL, 0xd7b562d7UL, 0xab4de6abUL,
0x76ec9a76UL, 0xca8f45caUL, 0x821f9d82UL, 0xc98940c9UL, 0x7dfa877dUL,
0xfaef15faUL, 0x59b2eb59UL, 0x478ec947UL, 0xf0fb0bf0UL, 0xad41ecadUL,
0xd4b367d4UL, 0xa25ffda2UL, 0xaf45eaafUL, 0x9c23bf9cUL, 0xa453f7a4UL,
0x72e49672UL, 0xc09b5bc0UL, 0xb775c2b7UL, 0xfde11cfdUL, 0x933dae93UL,
0x264c6a26UL, 0x366c5a36UL, 0x3f7e413fUL, 0xf7f502f7UL, 0xcc834fccUL,
0x34685c34UL, 0xa551f4a5UL, 0xe5d134e5UL, 0xf1f908f1UL, 0x71e29371UL,
0xd8ab73d8UL, 0x31625331UL, 0x152a3f15UL, 0x04080c04UL, 0xc79552c7UL,
0x23466523UL, 0xc39d5ec3UL, 0x18302818UL, 0x9637a196UL, 0x050a0f05UL,
0x9a2fb59aUL, 0x070e0907UL, 0x12243612UL, 0x801b9b80UL, 0xe2df3de2UL,
0xebcd26ebUL, 0x274e6927UL, 0xb27fcdb2UL, 0x75ea9f75UL, 0x09121b09UL,
0x831d9e83UL, 0x2c58742cUL, 0x1a342e1aUL, 0x1b362d1bUL, 0x6edcb26eUL,
0x5ab4ee5aUL, 0xa05bfba0UL, 0x52a4f652UL, 0x3b764d3bUL, 0xd6b761d6UL,
0xb37dceb3UL, 0x29527b29UL, 0xe3dd3ee3UL, 0x2f5e712fUL, 0x84139784UL,
0x53a6f553UL, 0xd1b968d1UL, 0x00000000UL, 0xedc12cedUL, 0x20406020UL,
0xfce31ffcUL, 0xb179c8b1UL, 0x5bb6ed5bUL, 0x6ad4be6aUL, 0xcb8d46cbUL,
0xbe67d9beUL, 0x39724b39UL, 0x4a94de4aUL, 0x4c98d44cUL, 0x58b0e858UL,
0xcf854acfUL, 0xd0bb6bd0UL, 0xefc52aefUL, 0xaa4fe5aaUL, 0xfbed16fbUL,
0x4386c543UL, 0x4d9ad74dUL, 0x33665533UL, 0x85119485UL, 0x458acf45UL,
0xf9e910f9UL, 0x02040602UL, 0x7ffe817fUL, 0x50a0f050UL, 0x3c78443cUL,
0x9f25ba9fUL, 0xa84be3a8UL, 0x51a2f351UL, 0xa35dfea3UL, 0x4080c040UL,
0x8f058a8fUL, 0x923fad92UL, 0x9d21bc9dUL, 0x38704838UL, 0xf5f104f5UL,
0xbc63dfbcUL, 0xb677c1b6UL, 0xdaaf75daUL, 0x21426321UL, 0x10203010UL,
0xffe51affUL, 0xf3fd0ef3UL, 0xd2bf6dd2UL, 0xcd814ccdUL, 0x0c18140cUL,
0x13263513UL, 0xecc32fecUL, 0x5fbee15fUL, 0x9735a297UL, 0x4488cc44UL,
0x172e3917UL, 0xc49357c4UL, 0xa755f2a7UL, 0x7efc827eUL, 0x3d7a473dUL,
0x64c8ac64UL, 0x5dbae75dUL, 0x19322b19UL, 0x73e69573UL, 0x60c0a060UL,
0x81199881UL, 0x4f9ed14fUL, 0xdca37fdcUL, 0x22446622UL, 0x2a547e2aUL,
0x903bab90UL, 0x880b8388UL, 0x468cca46UL, 0xeec729eeUL, 0xb86bd3b8UL,
0x14283c14UL, 0xdea779deUL, 0x5ebce25eUL, 0x0b161d0bUL, 0xdbad76dbUL,
0xe0db3be0UL, 0x32645632UL, 0x3a744e3aUL, 0x0a141e0aUL, 0x4992db49UL,
0x060c0a06UL, 0x24486c24UL, 0x5cb8e45cUL, 0xc29f5dc2UL, 0xd3bd6ed3UL,
0xac43efacUL, 0x62c4a662UL, 0x9139a891UL, 0x9531a495UL, 0xe4d337e4UL,
0x79f28b79UL, 0xe7d532e7UL, 0xc88b43c8UL, 0x376e5937UL, 0x6ddab76dUL,
0x8d018c8dUL, 0xd5b164d5UL, 0x4e9cd24eUL, 0xa949e0a9UL, 0x6cd8b46cUL,
0x56acfa56UL, 0xf4f307f4UL, 0xeacf25eaUL, 0x65caaf65UL, 0x7af48e7aUL,
0xae47e9aeUL, 0x08101808UL, 0xba6fd5baUL, 0x78f08878UL, 0x254a6f25UL,
0x2e5c722eUL, 0x1c38241cUL, 0xa657f1a6UL, 0xb473c7b4UL, 0xc69751c6UL,
0xe8cb23e8UL, 0xdda17cddUL, 0x74e89c74UL, 0x1f3e211fUL, 0x4b96dd4bUL,
0xbd61dcbdUL, 0x8b0d868bUL, 0x8a0f858aUL, 0x70e09070UL, 0x3e7c423eUL,
0xb571c4b5UL, 0x66ccaa66UL, 0x4890d848UL, 0x03060503UL, 0xf6f701f6UL,
0x0e1c120eUL, 0x61c2a361UL, 0x356a5f35UL, 0x57aef957UL, 0xb969d0b9UL,
0x86179186UL, 0xc19958c1UL, 0x1d3a271dUL, 0x9e27b99eUL, 0xe1d938e1UL,
0xf8eb13f8UL, 0x982bb398UL, 0x11223311UL, 0x69d2bb69UL, 0xd9a970d9UL,
0x8e07898eUL, 0x9433a794UL, 0x9b2db69bUL, 0x1e3c221eUL, 0x87159287UL,
0xe9c920e9UL, 0xce8749ceUL, 0x55aaff55UL, 0x28507828UL, 0xdfa57adfUL,
0x8c038f8cUL, 0xa159f8a1UL, 0x89098089UL, 0x0d1a170dUL, 0xbf65dabfUL,
0xe6d731e6UL, 0x4284c642UL, 0x68d0b868UL, 0x4182c341UL, 0x9929b099UL,
0x2d5a772dUL, 0x0f1e110fUL, 0xb07bcbb0UL, 0x54a8fc54UL, 0xbb6dd6bbUL,
0x162c3a16UL},
{0xc6a56363UL, 0xf8847c7cUL, 0xee997777UL, 0xf68d7b7bUL, 0xff0df2f2UL,
0xd6bd6b6bUL, 0xdeb16f6fUL, 0x9154c5c5UL, 0x60503030UL, 0x02030101UL,
0xcea96767UL, 0x567d2b2bUL, 0xe719fefeUL, 0xb562d7d7UL, 0x4de6ababUL,
0xec9a7676UL, 0x8f45cacaUL, 0x1f9d8282UL, 0x8940c9c9UL, 0xfa877d7dUL,
0xef15fafaUL, 0xb2eb5959UL, 0x8ec94747UL, 0xfb0bf0f0UL, 0x41ecadadUL,
0xb367d4d4UL, 0x5ffda2a2UL, 0x45eaafafUL, 0x23bf9c9cUL, 0x53f7a4a4UL,
0xe4967272UL, 0x9b5bc0c0UL, 0x75c2b7b7UL, 0xe11cfdfdUL, 0x3dae9393UL,
0x4c6a2626UL, 0x6c5a3636UL, 0x7e413f3fUL, 0xf502f7f7UL, 0x834fccccUL,
0x685c3434UL, 0x51f4a5a5UL, 0xd134e5e5UL, 0xf908f1f1UL, 0xe2937171UL,
0xab73d8d8UL, 0x62533131UL, 0x2a3f1515UL, 0x080c0404UL, 0x9552c7c7UL,
0x46652323UL, 0x9d5ec3c3UL, 0x30281818UL, 0x37a19696UL, 0x0a0f0505UL,
0x2fb59a9aUL, 0x0e090707UL, 0x24361212UL, 0x1b9b8080UL, 0xdf3de2e2UL,
0xcd26ebebUL, 0x4e692727UL, 0x7fcdb2b2UL, 0xea9f7575UL, 0x121b0909UL,
0x1d9e8383UL, 0x58742c2cUL, 0x342e1a1aUL, 0x362d1b1bUL, 0xdcb26e6eUL,
0xb4ee5a5aUL, 0x5bfba0a0UL, 0xa4f65252UL, 0x764d3b3bUL, 0xb761d6d6UL,
0x7dceb3b3UL, 0x527b2929UL, 0xdd3ee3e3UL, 0x5e712f2fUL, 0x13978484UL,
0xa6f55353UL, 0xb968d1d1UL, 0x00000000UL, 0xc12cededUL, 0x40602020UL,
0xe31ffcfcUL, 0x79c8b1b1UL, 0xb6ed5b5bUL, 0xd4be6a6aUL, 0x8d46cbcbUL,
0x67d9bebeUL, 0x724b3939UL, 0x94de4a4aUL, 0x98d44c4cUL, 0xb0e85858UL,
0x854acfcfUL, 0xbb6bd0d0UL, 0xc52aefefUL, 0x4fe5aaaaUL, 0xed16fbfbUL,
0x86c54343UL, 0x9ad74d4dUL, 0x66553333UL, 0x11948585UL, 0x8acf4545UL,
0xe910f9f9UL, 0x04060202UL, 0xfe817f7fUL, 0xa0f05050UL, 0x78443c3cUL,
0x25ba9f9fUL, 0x4be3a8a8UL, 0xa2f35151UL, 0x5dfea3a3UL, 0x80c04040UL,
0x058a8f8fUL, 0x3fad9292UL, 0x21bc9d9dUL, 0x70483838UL, 0xf104f5f5UL,
0x63dfbcbcUL, 0x77c1b6b6UL, 0xaf75dadaUL, 0x42632121UL, 0x20301010UL,
0xe51affffUL, 0xfd0ef3f3UL, 0xbf6dd2d2UL, 0x814ccdcdUL, 0x18140c0cUL,
0x26351313UL, 0xc32fececUL, 0xbee15f5fUL, 0x35a29797UL, 0x88cc4444UL,
0x2e391717UL, 0x9357c4c4UL, 0x55f2a7a7UL, 0xfc827e7eUL, 0x7a473d3dUL,
0xc8ac6464UL, 0xbae75d5dUL, 0x322b1919UL, 0xe6957373UL, 0xc0a06060UL,
0x19988181UL, 0x9ed14f4fUL, 0xa37fdcdcUL, 0x44662222UL, 0x547e2a2aUL,
0x3bab9090UL, 0x0b838888UL, 0x8cca4646UL, 0xc729eeeeUL, 0x6bd3b8b8UL,
0x283c1414UL, 0xa779dedeUL, 0xbce25e5eUL, 0x161d0b0bUL, 0xad76dbdbUL,
0xdb3be0e0UL, 0x64563232UL, 0x744e3a3aUL, 0x141e0a0aUL, 0x92db4949UL,
0x0c0a0606UL, 0x486c2424UL, 0xb8e45c5cUL, 0x9f5dc2c2UL, 0xbd6ed3d3UL,
0x43efacacUL, 0xc4a66262UL, 0x39a89191UL, 0x31a49595UL, 0xd337e4e4UL,
0xf28b7979UL, 0xd532e7e7UL, 0x8b43c8c8UL, 0x6e593737UL, 0xdab76d6dUL,
0x018c8d8dUL, 0xb164d5d5UL, 0x9cd24e4eUL, 0x49e0a9a9UL, 0xd8b46c6cUL,
0xacfa5656UL, 0xf307f4f4UL, 0xcf25eaeaUL, 0xcaaf6565UL, 0xf48e7a7aUL,
0x47e9aeaeUL, 0x10180808UL, 0x6fd5babaUL, 0xf0887878UL, 0x4a6f2525UL,
0x5c722e2eUL, 0x38241c1cUL, 0x57f1a6a6UL, 0x73c7b4b4UL, 0x9751c6c6UL,
0xcb23e8e8UL, 0xa17cddddUL, 0xe89c7474UL, 0x3e211f1fUL, 0x96dd4b4bUL,
0x61dcbdbdUL, 0x0d868b8bUL, 0x0f858a8aUL, 0xe0907070UL, 0x7c423e3eUL,
0x71c4b5b5UL, 0xccaa6666UL, 0x90d84848UL, 0x06050303UL, 0xf701f6f6UL,
0x1c120e0eUL, 0xc2a36161UL, 0x6a5f3535UL, 0xaef95757UL, 0x69d0b9b9UL,
0x17918686UL, 0x9958c1c1UL, 0x3a271d1dUL, 0x27b99e9eUL, 0xd938e1e1UL,
0xeb13f8f8UL, 0x2bb39898UL, 0x22331111UL, 0xd2bb6969UL, 0xa970d9d9UL,
0x07898e8eUL, 0x33a79494UL, 0x2db69b9bUL, 0x3c221e1eUL, 0x15928787UL,
0xc920e9e9UL, 0x8749ceceUL, 0xaaff5555UL, 0x50782828UL, 0xa57adfdfUL,
0x038f8c8cUL, 0x59f8a1a1UL, 0x09808989UL, 0x1a170d0dUL, 0x65dabfbfUL,
0xd731e6e6UL, 0x84c64242UL, 0xd0b86868UL, 0x82c34141UL, 0x29b09999UL,
0x5a772d2dUL, 0x1e110f0fUL, 0x7bcbb0b0UL, 0xa8fc5454UL, 0x6dd6bbbbUL,
0x2c3a1616UL}
};
static const unsigned long it_tab[4][256] = {
{0x50a7f451UL, 0x5365417eUL, 0xc3a4171aUL, 0x965e273aUL, 0xcb6bab3bUL,
0xf1459d1fUL, 0xab58faacUL, 0x9303e34bUL, 0x55fa3020UL, 0xf66d76adUL,
0x9176cc88UL, 0x254c02f5UL, 0xfcd7e54fUL, 0xd7cb2ac5UL, 0x80443526UL,
0x8fa362b5UL, 0x495ab1deUL, 0x671bba25UL, 0x980eea45UL, 0xe1c0fe5dUL,
0x02752fc3UL, 0x12f04c81UL, 0xa397468dUL, 0xc6f9d36bUL, 0xe75f8f03UL,
0x959c9215UL, 0xeb7a6dbfUL, 0xda595295UL, 0x2d83bed4UL, 0xd3217458UL,
0x2969e049UL, 0x44c8c98eUL, 0x6a89c275UL, 0x78798ef4UL, 0x6b3e5899UL,
0xdd71b927UL, 0xb64fe1beUL, 0x17ad88f0UL, 0x66ac20c9UL, 0xb43ace7dUL,
0x184adf63UL, 0x82311ae5UL, 0x60335197UL, 0x457f5362UL, 0xe07764b1UL,
0x84ae6bbbUL, 0x1ca081feUL, 0x942b08f9UL, 0x58684870UL, 0x19fd458fUL,
0x876cde94UL, 0xb7f87b52UL, 0x23d373abUL, 0xe2024b72UL, 0x578f1fe3UL,
0x2aab5566UL, 0x0728ebb2UL, 0x03c2b52fUL, 0x9a7bc586UL, 0xa50837d3UL,
0xf2872830UL, 0xb2a5bf23UL, 0xba6a0302UL, 0x5c8216edUL, 0x2b1ccf8aUL,
0x92b479a7UL, 0xf0f207f3UL, 0xa1e2694eUL, 0xcdf4da65UL, 0xd5be0506UL,
0x1f6234d1UL, 0x8afea6c4UL, 0x9d532e34UL, 0xa055f3a2UL, 0x32e18a05UL,
0x75ebf6a4UL, 0x39ec830bUL, 0xaaef6040UL, 0x069f715eUL, 0x51106ebdUL,
0xf98a213eUL, 0x3d06dd96UL, 0xae053eddUL, 0x46bde64dUL, 0xb58d5491UL,
0x055dc471UL, 0x6fd40604UL, 0xff155060UL, 0x24fb9819UL, 0x97e9bdd6UL,
0xcc434089UL, 0x779ed967UL, 0xbd42e8b0UL, 0x888b8907UL, 0x385b19e7UL,
0xdbeec879UL, 0x470a7ca1UL, 0xe90f427cUL, 0xc91e84f8UL, 0x00000000UL,
0x83868009UL, 0x48ed2b32UL, 0xac70111eUL, 0x4e725a6cUL, 0xfbff0efdUL,
0x5638850fUL, 0x1ed5ae3dUL, 0x27392d36UL, 0x64d90f0aUL, 0x21a65c68UL,
0xd1545b9bUL, 0x3a2e3624UL, 0xb1670a0cUL, 0x0fe75793UL, 0xd296eeb4UL,
0x9e919b1bUL, 0x4fc5c080UL, 0xa220dc61UL, 0x694b775aUL, 0x161a121cUL,
0x0aba93e2UL, 0xe52aa0c0UL, 0x43e0223cUL, 0x1d171b12UL, 0x0b0d090eUL,
0xadc78bf2UL, 0xb9a8b62dUL, 0xc8a91e14UL, 0x8519f157UL, 0x4c0775afUL,
0xbbdd99eeUL, 0xfd607fa3UL, 0x9f2601f7UL, 0xbcf5725cUL, 0xc53b6644UL,
0x347efb5bUL, 0x7629438bUL, 0xdcc623cbUL, 0x68fcedb6UL, 0x63f1e4b8UL,
0xcadc31d7UL, 0x10856342UL, 0x40229713UL, 0x2011c684UL, 0x7d244a85UL,
0xf83dbbd2UL, 0x1132f9aeUL, 0x6da129c7UL, 0x4b2f9e1dUL, 0xf330b2dcUL,
0xec52860dUL, 0xd0e3c177UL, 0x6c16b32bUL, 0x99b970a9UL, 0xfa489411UL,
0x2264e947UL, 0xc48cfca8UL, 0x1a3ff0a0UL, 0xd82c7d56UL, 0xef903322UL,
0xc74e4987UL, 0xc1d138d9UL, 0xfea2ca8cUL, 0x360bd498UL, 0xcf81f5a6UL,
0x28de7aa5UL, 0x268eb7daUL, 0xa4bfad3fUL, 0xe49d3a2cUL, 0x0d927850UL,
0x9bcc5f6aUL, 0x62467e54UL, 0xc2138df6UL, 0xe8b8d890UL, 0x5ef7392eUL,
0xf5afc382UL, 0xbe805d9fUL, 0x7c93d069UL, 0xa92dd56fUL, 0xb31225cfUL,
0x3b99acc8UL, 0xa77d1810UL, 0x6e639ce8UL, 0x7bbb3bdbUL, 0x097826cdUL,
0xf418596eUL, 0x01b79aecUL, 0xa89a4f83UL, 0x656e95e6UL, 0x7ee6ffaaUL,
0x08cfbc21UL, 0xe6e815efUL, 0xd99be7baUL, 0xce366f4aUL, 0xd4099feaUL,
0xd67cb029UL, 0xafb2a431UL, 0x31233f2aUL, 0x3094a5c6UL, 0xc066a235UL,
0x37bc4e74UL, 0xa6ca82fcUL, 0xb0d090e0UL, 0x15d8a733UL, 0x4a9804f1UL,
0xf7daec41UL, 0x0e50cd7fUL, 0x2ff69117UL, 0x8dd64d76UL, 0x4db0ef43UL,
0x544daaccUL, 0xdf0496e4UL, 0xe3b5d19eUL, 0x1b886a4cUL, 0xb81f2cc1UL,
0x7f516546UL, 0x04ea5e9dUL, 0x5d358c01UL, 0x737487faUL, 0x2e410bfbUL,
0x5a1d67b3UL, 0x52d2db92UL, 0x335610e9UL, 0x1347d66dUL, 0x8c61d79aUL,
0x7a0ca137UL, 0x8e14f859UL, 0x893c13ebUL, 0xee27a9ceUL, 0x35c961b7UL,
0xede51ce1UL, 0x3cb1477aUL, 0x59dfd29cUL, 0x3f73f255UL, 0x79ce1418UL,
0xbf37c773UL, 0xeacdf753UL, 0x5baafd5fUL, 0x146f3ddfUL, 0x86db4478UL,
0x81f3afcaUL, 0x3ec468b9UL, 0x2c342438UL, 0x5f40a3c2UL, 0x72c31d16UL,
0x0c25e2bcUL, 0x8b493c28UL, 0x41950dffUL, 0x7101a839UL, 0xdeb30c08UL,
0x9ce4b4d8UL, 0x90c15664UL, 0x6184cb7bUL, 0x70b632d5UL, 0x745c6c48UL,
0x4257b8d0UL},
{0xa7f45150UL, 0x65417e53UL, 0xa4171ac3UL, 0x5e273a96UL, 0x6bab3bcbUL,
0x459d1ff1UL, 0x58faacabUL, 0x03e34b93UL, 0xfa302055UL, 0x6d76adf6UL,
0x76cc8891UL, 0x4c02f525UL, 0xd7e54ffcUL, 0xcb2ac5d7UL, 0x44352680UL,
0xa362b58fUL, 0x5ab1de49UL, 0x1bba2567UL, 0x0eea4598UL, 0xc0fe5de1UL,
0x752fc302UL, 0xf04c8112UL, 0x97468da3UL, 0xf9d36bc6UL, 0x5f8f03e7UL,
0x9c921595UL, 0x7a6dbfebUL, 0x595295daUL, 0x83bed42dUL, 0x217458d3UL,
0x69e04929UL, 0xc8c98e44UL, 0x89c2756aUL, 0x798ef478UL, 0x3e58996bUL,
0x71b927ddUL, 0x4fe1beb6UL, 0xad88f017UL, 0xac20c966UL, 0x3ace7db4UL,
0x4adf6318UL, 0x311ae582UL, 0x33519760UL, 0x7f536245UL, 0x7764b1e0UL,
0xae6bbb84UL, 0xa081fe1cUL, 0x2b08f994UL, 0x68487058UL, 0xfd458f19UL,
0x6cde9487UL, 0xf87b52b7UL, 0xd373ab23UL, 0x024b72e2UL, 0x8f1fe357UL,
0xab55662aUL, 0x28ebb207UL, 0xc2b52f03UL, 0x7bc5869aUL, 0x0837d3a5UL,
0x872830f2UL, 0xa5bf23b2UL, 0x6a0302baUL, 0x8216ed5cUL, 0x1ccf8a2bUL,
0xb479a792UL, 0xf207f3f0UL, 0xe2694ea1UL, 0xf4da65cdUL, 0xbe0506d5UL,
0x6234d11fUL, 0xfea6c48aUL, 0x532e349dUL, 0x55f3a2a0UL, 0xe18a0532UL,
0xebf6a475UL, 0xec830b39UL, 0xef6040aaUL, 0x9f715e06UL, 0x106ebd51UL,
0x8a213ef9UL, 0x06dd963dUL, 0x053eddaeUL, 0xbde64d46UL, 0x8d5491b5UL,
0x5dc47105UL, 0xd406046fUL, 0x155060ffUL, 0xfb981924UL, 0xe9bdd697UL,
0x434089ccUL, 0x9ed96777UL, 0x42e8b0bdUL, 0x8b890788UL, 0x5b19e738UL,
0xeec879dbUL, 0x0a7ca147UL, 0x0f427ce9UL, 0x1e84f8c9UL, 0x00000000UL,
0x86800983UL, 0xed2b3248UL, 0x70111eacUL, 0x725a6c4eUL, 0xff0efdfbUL,
0x38850f56UL, 0xd5ae3d1eUL, 0x392d3627UL, 0xd90f0a64UL, 0xa65c6821UL,
0x545b9bd1UL, 0x2e36243aUL, 0x670a0cb1UL, 0xe757930fUL, 0x96eeb4d2UL,
0x919b1b9eUL, 0xc5c0804fUL, 0x20dc61a2UL, 0x4b775a69UL, 0x1a121c16UL,
0xba93e20aUL, 0x2aa0c0e5UL, 0xe0223c43UL, 0x171b121dUL, 0x0d090e0bUL,
0xc78bf2adUL, 0xa8b62db9UL, 0xa91e14c8UL, 0x19f15785UL, 0x0775af4cUL,
0xdd99eebbUL, 0x607fa3fdUL, 0x2601f79fUL, 0xf5725cbcUL, 0x3b6644c5UL,
0x7efb5b34UL, 0x29438b76UL, 0xc623cbdcUL, 0xfcedb668UL, 0xf1e4b863UL,
0xdc31d7caUL, 0x85634210UL, 0x22971340UL, 0x11c68420UL, 0x244a857dUL,
0x3dbbd2f8UL, 0x32f9ae11UL, 0xa129c76dUL, 0x2f9e1d4bUL, 0x30b2dcf3UL,
0x52860decUL, 0xe3c177d0UL, 0x16b32b6cUL, 0xb970a999UL, 0x489411faUL,
0x64e94722UL, 0x8cfca8c4UL, 0x3ff0a01aUL, 0x2c7d56d8UL, 0x903322efUL,
0x4e4987c7UL, 0xd138d9c1UL, 0xa2ca8cfeUL, 0x0bd49836UL, 0x81f5a6cfUL,
0xde7aa528UL, 0x8eb7da26UL, 0xbfad3fa4UL, 0x9d3a2ce4UL, 0x9278500dUL,
0xcc5f6a9bUL, 0x467e5462UL, 0x138df6c2UL, 0xb8d890e8UL, 0xf7392e5eUL,
0xafc382f5UL, 0x805d9fbeUL, 0x93d0697cUL, 0x2dd56fa9UL, 0x1225cfb3UL,
0x99acc83bUL, 0x7d1810a7UL, 0x639ce86eUL, 0xbb3bdb7bUL, 0x7826cd09UL,
0x18596ef4UL, 0xb79aec01UL, 0x9a4f83a8UL, 0x6e95e665UL, 0xe6ffaa7eUL,
0xcfbc2108UL, 0xe815efe6UL, 0x9be7bad9UL, 0x366f4aceUL, 0x099fead4UL,
0x7cb029d6UL, 0xb2a431afUL, 0x233f2a31UL, 0x94a5c630UL, 0x66a235c0UL,
0xbc4e7437UL, 0xca82fca6UL, 0xd090e0b0UL, 0xd8a73315UL, 0x9804f14aUL,
0xdaec41f7UL, 0x50cd7f0eUL, 0xf691172fUL, 0xd64d768dUL, 0xb0ef434dUL,
0x4daacc54UL, 0x0496e4dfUL, 0xb5d19ee3UL, 0x886a4c1bUL, 0x1f2cc1b8UL,
0x5165467fUL, 0xea5e9d04UL, 0x358c015dUL, 0x7487fa73UL, 0x410bfb2eUL,
0x1d67b35aUL, 0xd2db9252UL, 0x5610e933UL, 0x47d66d13UL, 0x61d79a8cUL,
0x0ca1377aUL, 0x14f8598eUL, 0x3c13eb89UL, 0x27a9ceeeUL, 0xc961b735UL,
0xe51ce1edUL, 0xb1477a3cUL, 0xdfd29c59UL, 0x73f2553fUL, 0xce141879UL,
0x37c773bfUL, 0xcdf753eaUL, 0xaafd5f5bUL, 0x6f3ddf14UL, 0xdb447886UL,
0xf3afca81UL, 0xc468b93eUL, 0x3424382cUL, 0x40a3c25fUL, 0xc31d1672UL,
0x25e2bc0cUL, 0x493c288bUL, 0x950dff41UL, 0x01a83971UL, 0xb30c08deUL,
0xe4b4d89cUL, 0xc1566490UL, 0x84cb7b61UL, 0xb632d570UL, 0x5c6c4874UL,
0x57b8d042UL},
{0xf45150a7UL, 0x417e5365UL, 0x171ac3a4UL, 0x273a965eUL, 0xab3bcb6bUL,
0x9d1ff145UL, 0xfaacab58UL, 0xe34b9303UL, 0x302055faUL, 0x76adf66dUL,
0xcc889176UL, 0x02f5254cUL, 0xe54ffcd7UL, 0x2ac5d7cbUL, 0x35268044UL,
0x62b58fa3UL, 0xb1de495aUL, 0xba25671bUL, 0xea45980eUL, 0xfe5de1c0UL,
0x2fc30275UL, 0x4c8112f0UL, 0x468da397UL, 0xd36bc6f9UL, 0x8f03e75fUL,
0x9215959cUL, 0x6dbfeb7aUL, 0x5295da59UL, 0xbed42d83UL, 0x7458d321UL,
0xe0492969UL, 0xc98e44c8UL, 0xc2756a89UL, 0x8ef47879UL, 0x58996b3eUL,
0xb927dd71UL, 0xe1beb64fUL, 0x88f017adUL, 0x20c966acUL, 0xce7db43aUL,
0xdf63184aUL, 0x1ae58231UL, 0x51976033UL, 0x5362457fUL, 0x64b1e077UL,
0x6bbb84aeUL, 0x81fe1ca0UL, 0x08f9942bUL, 0x48705868UL, 0x458f19fdUL,
0xde94876cUL, 0x7b52b7f8UL, 0x73ab23d3UL, 0x4b72e202UL, 0x1fe3578fUL,
0x55662aabUL, 0xebb20728UL, 0xb52f03c2UL, 0xc5869a7bUL, 0x37d3a508UL,
0x2830f287UL, 0xbf23b2a5UL, 0x0302ba6aUL, 0x16ed5c82UL, 0xcf8a2b1cUL,
0x79a792b4UL, 0x07f3f0f2UL, 0x694ea1e2UL, 0xda65cdf4UL, 0x0506d5beUL,
0x34d11f62UL, 0xa6c48afeUL, 0x2e349d53UL, 0xf3a2a055UL, 0x8a0532e1UL,
0xf6a475ebUL, 0x830b39ecUL, 0x6040aaefUL, 0x715e069fUL, 0x6ebd5110UL,
0x213ef98aUL, 0xdd963d06UL, 0x3eddae05UL, 0xe64d46bdUL, 0x5491b58dUL,
0xc471055dUL, 0x06046fd4UL, 0x5060ff15UL, 0x981924fbUL, 0xbdd697e9UL,
0x4089cc43UL, 0xd967779eUL, 0xe8b0bd42UL, 0x8907888bUL, 0x19e7385bUL,
0xc879dbeeUL, 0x7ca1470aUL, 0x427ce90fUL, 0x84f8c91eUL, 0x00000000UL,
0x80098386UL, 0x2b3248edUL, 0x111eac70UL, 0x5a6c4e72UL, 0x0efdfbffUL,
0x850f5638UL, 0xae3d1ed5UL, 0x2d362739UL, 0x0f0a64d9UL, 0x5c6821a6UL,
0x5b9bd154UL, 0x36243a2eUL, 0x0a0cb167UL, 0x57930fe7UL, 0xeeb4d296UL,
0x9b1b9e91UL, 0xc0804fc5UL, 0xdc61a220UL, 0x775a694bUL, 0x121c161aUL,
0x93e20abaUL, 0xa0c0e52aUL, 0x223c43e0UL, 0x1b121d17UL, 0x090e0b0dUL,
0x8bf2adc7UL, 0xb62db9a8UL, 0x1e14c8a9UL, 0xf1578519UL, 0x75af4c07UL,
0x99eebbddUL, 0x7fa3fd60UL, 0x01f79f26UL, 0x725cbcf5UL, 0x6644c53bUL,
0xfb5b347eUL, 0x438b7629UL, 0x23cbdcc6UL, 0xedb668fcUL, 0xe4b863f1UL,
0x31d7cadcUL, 0x63421085UL, 0x97134022UL, 0xc6842011UL, 0x4a857d24UL,
0xbbd2f83dUL, 0xf9ae1132UL, 0x29c76da1UL, 0x9e1d4b2fUL, 0xb2dcf330UL,
0x860dec52UL, 0xc177d0e3UL, 0xb32b6c16UL, 0x70a999b9UL, 0x9411fa48UL,
0xe9472264UL, 0xfca8c48cUL, 0xf0a01a3fUL, 0x7d56d82cUL, 0x3322ef90UL,
0x4987c74eUL, 0x38d9c1d1UL, 0xca8cfea2UL, 0xd498360bUL, 0xf5a6cf81UL,
0x7aa528deUL, 0xb7da268eUL, 0xad3fa4bfUL, 0x3a2ce49dUL, 0x78500d92UL,
0x5f6a9bccUL, 0x7e546246UL, 0x8df6c213UL, 0xd890e8b8UL, 0x392e5ef7UL,
0xc382f5afUL, 0x5d9fbe80UL, 0xd0697c93UL, 0xd56fa92dUL, 0x25cfb312UL,
0xacc83b99UL, 0x1810a77dUL, 0x9ce86e63UL, 0x3bdb7bbbUL, 0x26cd0978UL,
0x596ef418UL, 0x9aec01b7UL, 0x4f83a89aUL, 0x95e6656eUL, 0xffaa7ee6UL,
0xbc2108cfUL, 0x15efe6e8UL, 0xe7bad99bUL, 0x6f4ace36UL, 0x9fead409UL,
0xb029d67cUL, 0xa431afb2UL, 0x3f2a3123UL, 0xa5c63094UL, 0xa235c066UL,
0x4e7437bcUL, 0x82fca6caUL, 0x90e0b0d0UL, 0xa73315d8UL, 0x04f14a98UL,
0xec41f7daUL, 0xcd7f0e50UL, 0x91172ff6UL, 0x4d768dd6UL, 0xef434db0UL,
0xaacc544dUL, 0x96e4df04UL, 0xd19ee3b5UL, 0x6a4c1b88UL, 0x2cc1b81fUL,
0x65467f51UL, 0x5e9d04eaUL, 0x8c015d35UL, 0x87fa7374UL, 0x0bfb2e41UL,
0x67b35a1dUL, 0xdb9252d2UL, 0x10e93356UL, 0xd66d1347UL, 0xd79a8c61UL,
0xa1377a0cUL, 0xf8598e14UL, 0x13eb893cUL, 0xa9ceee27UL, 0x61b735c9UL,
0x1ce1ede5UL, 0x477a3cb1UL, 0xd29c59dfUL, 0xf2553f73UL, 0x141879ceUL,
0xc773bf37UL, 0xf753eacdUL, 0xfd5f5baaUL, 0x3ddf146fUL, 0x447886dbUL,
0xafca81f3UL, 0x68b93ec4UL, 0x24382c34UL, 0xa3c25f40UL, 0x1d1672c3UL,
0xe2bc0c25UL, 0x3c288b49UL, 0x0dff4195UL, 0xa8397101UL, 0x0c08deb3UL,
0xb4d89ce4UL, 0x566490c1UL, 0xcb7b6184UL, 0x32d570b6UL, 0x6c48745cUL,
0xb8d04257UL},
{0x5150a7f4UL, 0x7e536541UL, 0x1ac3a417UL, 0x3a965e27UL, 0x3bcb6babUL,
0x1ff1459dUL, 0xacab58faUL, 0x4b9303e3UL, 0x2055fa30UL, 0xadf66d76UL,
0x889176ccUL, 0xf5254c02UL, 0x4ffcd7e5UL, 0xc5d7cb2aUL, 0x26804435UL,
0xb58fa362UL, 0xde495ab1UL, 0x25671bbaUL, 0x45980eeaUL, 0x5de1c0feUL,
0xc302752fUL, 0x8112f04cUL, 0x8da39746UL, 0x6bc6f9d3UL, 0x03e75f8fUL,
0x15959c92UL, 0xbfeb7a6dUL, 0x95da5952UL, 0xd42d83beUL, 0x58d32174UL,
0x492969e0UL, 0x8e44c8c9UL, 0x756a89c2UL, 0xf478798eUL, 0x996b3e58UL,
0x27dd71b9UL, 0xbeb64fe1UL, 0xf017ad88UL, 0xc966ac20UL, 0x7db43aceUL,
0x63184adfUL, 0xe582311aUL, 0x97603351UL, 0x62457f53UL, 0xb1e07764UL,
0xbb84ae6bUL, 0xfe1ca081UL, 0xf9942b08UL, 0x70586848UL, 0x8f19fd45UL,
0x94876cdeUL, 0x52b7f87bUL, 0xab23d373UL, 0x72e2024bUL, 0xe3578f1fUL,
0x662aab55UL, 0xb20728ebUL, 0x2f03c2b5UL, 0x869a7bc5UL, 0xd3a50837UL,
0x30f28728UL, 0x23b2a5bfUL, 0x02ba6a03UL, 0xed5c8216UL, 0x8a2b1ccfUL,
0xa792b479UL, 0xf3f0f207UL, 0x4ea1e269UL, 0x65cdf4daUL, 0x06d5be05UL,
0xd11f6234UL, 0xc48afea6UL, 0x349d532eUL, 0xa2a055f3UL, 0x0532e18aUL,
0xa475ebf6UL, 0x0b39ec83UL, 0x40aaef60UL, 0x5e069f71UL, 0xbd51106eUL,
0x3ef98a21UL, 0x963d06ddUL, 0xddae053eUL, 0x4d46bde6UL, 0x91b58d54UL,
0x71055dc4UL, 0x046fd406UL, 0x60ff1550UL, 0x1924fb98UL, 0xd697e9bdUL,
0x89cc4340UL, 0x67779ed9UL, 0xb0bd42e8UL, 0x07888b89UL, 0xe7385b19UL,
0x79dbeec8UL, 0xa1470a7cUL, 0x7ce90f42UL, 0xf8c91e84UL, 0x00000000UL,
0x09838680UL, 0x3248ed2bUL, 0x1eac7011UL, 0x6c4e725aUL, 0xfdfbff0eUL,
0x0f563885UL, 0x3d1ed5aeUL, 0x3627392dUL, 0x0a64d90fUL, 0x6821a65cUL,
0x9bd1545bUL, 0x243a2e36UL, 0x0cb1670aUL, 0x930fe757UL, 0xb4d296eeUL,
0x1b9e919bUL, 0x804fc5c0UL, 0x61a220dcUL, 0x5a694b77UL, 0x1c161a12UL,
0xe20aba93UL, 0xc0e52aa0UL, 0x3c43e022UL, 0x121d171bUL, 0x0e0b0d09UL,
0xf2adc78bUL, 0x2db9a8b6UL, 0x14c8a91eUL, 0x578519f1UL, 0xaf4c0775UL,
0xeebbdd99UL, 0xa3fd607fUL, 0xf79f2601UL, 0x5cbcf572UL, 0x44c53b66UL,
0x5b347efbUL, 0x8b762943UL, 0xcbdcc623UL, 0xb668fcedUL, 0xb863f1e4UL,
0xd7cadc31UL, 0x42108563UL, 0x13402297UL, 0x842011c6UL, 0x857d244aUL,
0xd2f83dbbUL, 0xae1132f9UL, 0xc76da129UL, 0x1d4b2f9eUL, 0xdcf330b2UL,
0x0dec5286UL, 0x77d0e3c1UL, 0x2b6c16b3UL, 0xa999b970UL, 0x11fa4894UL,
0x472264e9UL, 0xa8c48cfcUL, 0xa01a3ff0UL, 0x56d82c7dUL, 0x22ef9033UL,
0x87c74e49UL, 0xd9c1d138UL, 0x8cfea2caUL, 0x98360bd4UL, 0xa6cf81f5UL,
0xa528de7aUL, 0xda268eb7UL, 0x3fa4bfadUL, 0x2ce49d3aUL, 0x500d9278UL,
0x6a9bcc5fUL, 0x5462467eUL, 0xf6c2138dUL, 0x90e8b8d8UL, 0x2e5ef739UL,
0x82f5afc3UL, 0x9fbe805dUL, 0x697c93d0UL, 0x6fa92dd5UL, 0xcfb31225UL,
0xc83b99acUL, 0x10a77d18UL, 0xe86e639cUL, 0xdb7bbb3bUL, 0xcd097826UL,
0x6ef41859UL, 0xec01b79aUL, 0x83a89a4fUL, 0xe6656e95UL, 0xaa7ee6ffUL,
0x2108cfbcUL, 0xefe6e815UL, 0xbad99be7UL, 0x4ace366fUL, 0xead4099fUL,
0x29d67cb0UL, 0x31afb2a4UL, 0x2a31233fUL, 0xc63094a5UL, 0x35c066a2UL,
0x7437bc4eUL, 0xfca6ca82UL, 0xe0b0d090UL, 0x3315d8a7UL, 0xf14a9804UL,
0x41f7daecUL, 0x7f0e50cdUL, 0x172ff691UL, 0x768dd64dUL, 0x434db0efUL,
0xcc544daaUL, 0xe4df0496UL, 0x9ee3b5d1UL, 0x4c1b886aUL, 0xc1b81f2cUL,
0x467f5165UL, 0x9d04ea5eUL, 0x015d358cUL, 0xfa737487UL, 0xfb2e410bUL,
0xb35a1d67UL, 0x9252d2dbUL, 0xe9335610UL, 0x6d1347d6UL, 0x9a8c61d7UL,
0x377a0ca1UL, 0x598e14f8UL, 0xeb893c13UL, 0xceee27a9UL, 0xb735c961UL,
0xe1ede51cUL, 0x7a3cb147UL, 0x9c59dfd2UL, 0x553f73f2UL, 0x1879ce14UL,
0x73bf37c7UL, 0x53eacdf7UL, 0x5f5baafdUL, 0xdf146f3dUL, 0x7886db44UL,
0xca81f3afUL, 0xb93ec468UL, 0x382c3424UL, 0xc25f40a3UL, 0x1672c31dUL,
0xbc0c25e2UL, 0x288b493cUL, 0xff41950dUL, 0x397101a8UL, 0x08deb30cUL,
0xd89ce4b4UL, 0x6490c156UL, 0x7b6184cbUL, 0xd570b632UL, 0x48745c6cUL,
0xd04257b8UL}
};
static const unsigned long fl_tab[4][256] = {
{0x00000063UL, 0x0000007cUL, 0x00000077UL, 0x0000007bUL, 0x000000f2UL,
0x0000006bUL, 0x0000006fUL, 0x000000c5UL, 0x00000030UL, 0x00000001UL,
0x00000067UL, 0x0000002bUL, 0x000000feUL, 0x000000d7UL, 0x000000abUL,
0x00000076UL, 0x000000caUL, 0x00000082UL, 0x000000c9UL, 0x0000007dUL,
0x000000faUL, 0x00000059UL, 0x00000047UL, 0x000000f0UL, 0x000000adUL,
0x000000d4UL, 0x000000a2UL, 0x000000afUL, 0x0000009cUL, 0x000000a4UL,
0x00000072UL, 0x000000c0UL, 0x000000b7UL, 0x000000fdUL, 0x00000093UL,
0x00000026UL, 0x00000036UL, 0x0000003fUL, 0x000000f7UL, 0x000000ccUL,
0x00000034UL, 0x000000a5UL, 0x000000e5UL, 0x000000f1UL, 0x00000071UL,
0x000000d8UL, 0x00000031UL, 0x00000015UL, 0x00000004UL, 0x000000c7UL,
0x00000023UL, 0x000000c3UL, 0x00000018UL, 0x00000096UL, 0x00000005UL,
0x0000009aUL, 0x00000007UL, 0x00000012UL, 0x00000080UL, 0x000000e2UL,
0x000000ebUL, 0x00000027UL, 0x000000b2UL, 0x00000075UL, 0x00000009UL,
0x00000083UL, 0x0000002cUL, 0x0000001aUL, 0x0000001bUL, 0x0000006eUL,
0x0000005aUL, 0x000000a0UL, 0x00000052UL, 0x0000003bUL, 0x000000d6UL,
0x000000b3UL, 0x00000029UL, 0x000000e3UL, 0x0000002fUL, 0x00000084UL,
0x00000053UL, 0x000000d1UL, 0x00000000UL, 0x000000edUL, 0x00000020UL,
0x000000fcUL, 0x000000b1UL, 0x0000005bUL, 0x0000006aUL, 0x000000cbUL,
0x000000beUL, 0x00000039UL, 0x0000004aUL, 0x0000004cUL, 0x00000058UL,
0x000000cfUL, 0x000000d0UL, 0x000000efUL, 0x000000aaUL, 0x000000fbUL,
0x00000043UL, 0x0000004dUL, 0x00000033UL, 0x00000085UL, 0x00000045UL,
0x000000f9UL, 0x00000002UL, 0x0000007fUL, 0x00000050UL, 0x0000003cUL,
0x0000009fUL, 0x000000a8UL, 0x00000051UL, 0x000000a3UL, 0x00000040UL,
0x0000008fUL, 0x00000092UL, 0x0000009dUL, 0x00000038UL, 0x000000f5UL,
0x000000bcUL, 0x000000b6UL, 0x000000daUL, 0x00000021UL, 0x00000010UL,
0x000000ffUL, 0x000000f3UL, 0x000000d2UL, 0x000000cdUL, 0x0000000cUL,
0x00000013UL, 0x000000ecUL, 0x0000005fUL, 0x00000097UL, 0x00000044UL,
0x00000017UL, 0x000000c4UL, 0x000000a7UL, 0x0000007eUL, 0x0000003dUL,
0x00000064UL, 0x0000005dUL, 0x00000019UL, 0x00000073UL, 0x00000060UL,
0x00000081UL, 0x0000004fUL, 0x000000dcUL, 0x00000022UL, 0x0000002aUL,
0x00000090UL, 0x00000088UL, 0x00000046UL, 0x000000eeUL, 0x000000b8UL,
0x00000014UL, 0x000000deUL, 0x0000005eUL, 0x0000000bUL, 0x000000dbUL,
0x000000e0UL, 0x00000032UL, 0x0000003aUL, 0x0000000aUL, 0x00000049UL,
0x00000006UL, 0x00000024UL, 0x0000005cUL, 0x000000c2UL, 0x000000d3UL,
0x000000acUL, 0x00000062UL, 0x00000091UL, 0x00000095UL, 0x000000e4UL,
0x00000079UL, 0x000000e7UL, 0x000000c8UL, 0x00000037UL, 0x0000006dUL,
0x0000008dUL, 0x000000d5UL, 0x0000004eUL, 0x000000a9UL, 0x0000006cUL,
0x00000056UL, 0x000000f4UL, 0x000000eaUL, 0x00000065UL, 0x0000007aUL,
0x000000aeUL, 0x00000008UL, 0x000000baUL, 0x00000078UL, 0x00000025UL,
0x0000002eUL, 0x0000001cUL, 0x000000a6UL, 0x000000b4UL, 0x000000c6UL,
0x000000e8UL, 0x000000ddUL, 0x00000074UL, 0x0000001fUL, 0x0000004bUL,
0x000000bdUL, 0x0000008bUL, 0x0000008aUL, 0x00000070UL, 0x0000003eUL,
0x000000b5UL, 0x00000066UL, 0x00000048UL, 0x00000003UL, 0x000000f6UL,
0x0000000eUL, 0x00000061UL, 0x00000035UL, 0x00000057UL, 0x000000b9UL,
0x00000086UL, 0x000000c1UL, 0x0000001dUL, 0x0000009eUL, 0x000000e1UL,
0x000000f8UL, 0x00000098UL, 0x00000011UL, 0x00000069UL, 0x000000d9UL,
0x0000008eUL, 0x00000094UL, 0x0000009bUL, 0x0000001eUL, 0x00000087UL,
0x000000e9UL, 0x000000ceUL, 0x00000055UL, 0x00000028UL, 0x000000dfUL,
0x0000008cUL, 0x000000a1UL, 0x00000089UL, 0x0000000dUL, 0x000000bfUL,
0x000000e6UL, 0x00000042UL, 0x00000068UL, 0x00000041UL, 0x00000099UL,
0x0000002dUL, 0x0000000fUL, 0x000000b0UL, 0x00000054UL, 0x000000bbUL,
0x00000016UL},
{0x00006300UL, 0x00007c00UL, 0x00007700UL, 0x00007b00UL, 0x0000f200UL,
0x00006b00UL, 0x00006f00UL, 0x0000c500UL, 0x00003000UL, 0x00000100UL,
0x00006700UL, 0x00002b00UL, 0x0000fe00UL, 0x0000d700UL, 0x0000ab00UL,
0x00007600UL, 0x0000ca00UL, 0x00008200UL, 0x0000c900UL, 0x00007d00UL,
0x0000fa00UL, 0x00005900UL, 0x00004700UL, 0x0000f000UL, 0x0000ad00UL,
0x0000d400UL, 0x0000a200UL, 0x0000af00UL, 0x00009c00UL, 0x0000a400UL,
0x00007200UL, 0x0000c000UL, 0x0000b700UL, 0x0000fd00UL, 0x00009300UL,
0x00002600UL, 0x00003600UL, 0x00003f00UL, 0x0000f700UL, 0x0000cc00UL,
0x00003400UL, 0x0000a500UL, 0x0000e500UL, 0x0000f100UL, 0x00007100UL,
0x0000d800UL, 0x00003100UL, 0x00001500UL, 0x00000400UL, 0x0000c700UL,
0x00002300UL, 0x0000c300UL, 0x00001800UL, 0x00009600UL, 0x00000500UL,
0x00009a00UL, 0x00000700UL, 0x00001200UL, 0x00008000UL, 0x0000e200UL,
0x0000eb00UL, 0x00002700UL, 0x0000b200UL, 0x00007500UL, 0x00000900UL,
0x00008300UL, 0x00002c00UL, 0x00001a00UL, 0x00001b00UL, 0x00006e00UL,
0x00005a00UL, 0x0000a000UL, 0x00005200UL, 0x00003b00UL, 0x0000d600UL,
0x0000b300UL, 0x00002900UL, 0x0000e300UL, 0x00002f00UL, 0x00008400UL,
0x00005300UL, 0x0000d100UL, 0x00000000UL, 0x0000ed00UL, 0x00002000UL,
0x0000fc00UL, 0x0000b100UL, 0x00005b00UL, 0x00006a00UL, 0x0000cb00UL,
0x0000be00UL, 0x00003900UL, 0x00004a00UL, 0x00004c00UL, 0x00005800UL,
0x0000cf00UL, 0x0000d000UL, 0x0000ef00UL, 0x0000aa00UL, 0x0000fb00UL,
0x00004300UL, 0x00004d00UL, 0x00003300UL, 0x00008500UL, 0x00004500UL,
0x0000f900UL, 0x00000200UL, 0x00007f00UL, 0x00005000UL, 0x00003c00UL,
0x00009f00UL, 0x0000a800UL, 0x00005100UL, 0x0000a300UL, 0x00004000UL,
0x00008f00UL, 0x00009200UL, 0x00009d00UL, 0x00003800UL, 0x0000f500UL,
0x0000bc00UL, 0x0000b600UL, 0x0000da00UL, 0x00002100UL, 0x00001000UL,
0x0000ff00UL, 0x0000f300UL, 0x0000d200UL, 0x0000cd00UL, 0x00000c00UL,
0x00001300UL, 0x0000ec00UL, 0x00005f00UL, 0x00009700UL, 0x00004400UL,
0x00001700UL, 0x0000c400UL, 0x0000a700UL, 0x00007e00UL, 0x00003d00UL,
0x00006400UL, 0x00005d00UL, 0x00001900UL, 0x00007300UL, 0x00006000UL,
0x00008100UL, 0x00004f00UL, 0x0000dc00UL, 0x00002200UL, 0x00002a00UL,
0x00009000UL, 0x00008800UL, 0x00004600UL, 0x0000ee00UL, 0x0000b800UL,
0x00001400UL, 0x0000de00UL, 0x00005e00UL, 0x00000b00UL, 0x0000db00UL,
0x0000e000UL, 0x00003200UL, 0x00003a00UL, 0x00000a00UL, 0x00004900UL,
0x00000600UL, 0x00002400UL, 0x00005c00UL, 0x0000c200UL, 0x0000d300UL,
0x0000ac00UL, 0x00006200UL, 0x00009100UL, 0x00009500UL, 0x0000e400UL,
0x00007900UL, 0x0000e700UL, 0x0000c800UL, 0x00003700UL, 0x00006d00UL,
0x00008d00UL, 0x0000d500UL, 0x00004e00UL, 0x0000a900UL, 0x00006c00UL,
0x00005600UL, 0x0000f400UL, 0x0000ea00UL, 0x00006500UL, 0x00007a00UL,
0x0000ae00UL, 0x00000800UL, 0x0000ba00UL, 0x00007800UL, 0x00002500UL,
0x00002e00UL, 0x00001c00UL, 0x0000a600UL, 0x0000b400UL, 0x0000c600UL,
0x0000e800UL, 0x0000dd00UL, 0x00007400UL, 0x00001f00UL, 0x00004b00UL,
0x0000bd00UL, 0x00008b00UL, 0x00008a00UL, 0x00007000UL, 0x00003e00UL,
0x0000b500UL, 0x00006600UL, 0x00004800UL, 0x00000300UL, 0x0000f600UL,
0x00000e00UL, 0x00006100UL, 0x00003500UL, 0x00005700UL, 0x0000b900UL,
0x00008600UL, 0x0000c100UL, 0x00001d00UL, 0x00009e00UL, 0x0000e100UL,
0x0000f800UL, 0x00009800UL, 0x00001100UL, 0x00006900UL, 0x0000d900UL,
0x00008e00UL, 0x00009400UL, 0x00009b00UL, 0x00001e00UL, 0x00008700UL,
0x0000e900UL, 0x0000ce00UL, 0x00005500UL, 0x00002800UL, 0x0000df00UL,
0x00008c00UL, 0x0000a100UL, 0x00008900UL, 0x00000d00UL, 0x0000bf00UL,
0x0000e600UL, 0x00004200UL, 0x00006800UL, 0x00004100UL, 0x00009900UL,
0x00002d00UL, 0x00000f00UL, 0x0000b000UL, 0x00005400UL, 0x0000bb00UL,
0x00001600UL},
{0x00630000UL, 0x007c0000UL, 0x00770000UL, 0x007b0000UL, 0x00f20000UL,
0x006b0000UL, 0x006f0000UL, 0x00c50000UL, 0x00300000UL, 0x00010000UL,
0x00670000UL, 0x002b0000UL, 0x00fe0000UL, 0x00d70000UL, 0x00ab0000UL,
0x00760000UL, 0x00ca0000UL, 0x00820000UL, 0x00c90000UL, 0x007d0000UL,
0x00fa0000UL, 0x00590000UL, 0x00470000UL, 0x00f00000UL, 0x00ad0000UL,
0x00d40000UL, 0x00a20000UL, 0x00af0000UL, 0x009c0000UL, 0x00a40000UL,
0x00720000UL, 0x00c00000UL, 0x00b70000UL, 0x00fd0000UL, 0x00930000UL,
0x00260000UL, 0x00360000UL, 0x003f0000UL, 0x00f70000UL, 0x00cc0000UL,
0x00340000UL, 0x00a50000UL, 0x00e50000UL, 0x00f10000UL, 0x00710000UL,
0x00d80000UL, 0x00310000UL, 0x00150000UL, 0x00040000UL, 0x00c70000UL,
0x00230000UL, 0x00c30000UL, 0x00180000UL, 0x00960000UL, 0x00050000UL,
0x009a0000UL, 0x00070000UL, 0x00120000UL, 0x00800000UL, 0x00e20000UL,
0x00eb0000UL, 0x00270000UL, 0x00b20000UL, 0x00750000UL, 0x00090000UL,
0x00830000UL, 0x002c0000UL, 0x001a0000UL, 0x001b0000UL, 0x006e0000UL,
0x005a0000UL, 0x00a00000UL, 0x00520000UL, 0x003b0000UL, 0x00d60000UL,
0x00b30000UL, 0x00290000UL, 0x00e30000UL, 0x002f0000UL, 0x00840000UL,
0x00530000UL, 0x00d10000UL, 0x00000000UL, 0x00ed0000UL, 0x00200000UL,
0x00fc0000UL, 0x00b10000UL, 0x005b0000UL, 0x006a0000UL, 0x00cb0000UL,
0x00be0000UL, 0x00390000UL, 0x004a0000UL, 0x004c0000UL, 0x00580000UL,
0x00cf0000UL, 0x00d00000UL, 0x00ef0000UL, 0x00aa0000UL, 0x00fb0000UL,
0x00430000UL, 0x004d0000UL, 0x00330000UL, 0x00850000UL, 0x00450000UL,
0x00f90000UL, 0x00020000UL, 0x007f0000UL, 0x00500000UL, 0x003c0000UL,
0x009f0000UL, 0x00a80000UL, 0x00510000UL, 0x00a30000UL, 0x00400000UL,
0x008f0000UL, 0x00920000UL, 0x009d0000UL, 0x00380000UL, 0x00f50000UL,
0x00bc0000UL, 0x00b60000UL, 0x00da0000UL, 0x00210000UL, 0x00100000UL,
0x00ff0000UL, 0x00f30000UL, 0x00d20000UL, 0x00cd0000UL, 0x000c0000UL,
0x00130000UL, 0x00ec0000UL, 0x005f0000UL, 0x00970000UL, 0x00440000UL,
0x00170000UL, 0x00c40000UL, 0x00a70000UL, 0x007e0000UL, 0x003d0000UL,
0x00640000UL, 0x005d0000UL, 0x00190000UL, 0x00730000UL, 0x00600000UL,
0x00810000UL, 0x004f0000UL, 0x00dc0000UL, 0x00220000UL, 0x002a0000UL,
0x00900000UL, 0x00880000UL, 0x00460000UL, 0x00ee0000UL, 0x00b80000UL,
0x00140000UL, 0x00de0000UL, 0x005e0000UL, 0x000b0000UL, 0x00db0000UL,
0x00e00000UL, 0x00320000UL, 0x003a0000UL, 0x000a0000UL, 0x00490000UL,
0x00060000UL, 0x00240000UL, 0x005c0000UL, 0x00c20000UL, 0x00d30000UL,
0x00ac0000UL, 0x00620000UL, 0x00910000UL, 0x00950000UL, 0x00e40000UL,
0x00790000UL, 0x00e70000UL, 0x00c80000UL, 0x00370000UL, 0x006d0000UL,
0x008d0000UL, 0x00d50000UL, 0x004e0000UL, 0x00a90000UL, 0x006c0000UL,
0x00560000UL, 0x00f40000UL, 0x00ea0000UL, 0x00650000UL, 0x007a0000UL,
0x00ae0000UL, 0x00080000UL, 0x00ba0000UL, 0x00780000UL, 0x00250000UL,
0x002e0000UL, 0x001c0000UL, 0x00a60000UL, 0x00b40000UL, 0x00c60000UL,
0x00e80000UL, 0x00dd0000UL, 0x00740000UL, 0x001f0000UL, 0x004b0000UL,
0x00bd0000UL, 0x008b0000UL, 0x008a0000UL, 0x00700000UL, 0x003e0000UL,
0x00b50000UL, 0x00660000UL, 0x00480000UL, 0x00030000UL, 0x00f60000UL,
0x000e0000UL, 0x00610000UL, 0x00350000UL, 0x00570000UL, 0x00b90000UL,
0x00860000UL, 0x00c10000UL, 0x001d0000UL, 0x009e0000UL, 0x00e10000UL,
0x00f80000UL, 0x00980000UL, 0x00110000UL, 0x00690000UL, 0x00d90000UL,
0x008e0000UL, 0x00940000UL, 0x009b0000UL, 0x001e0000UL, 0x00870000UL,
0x00e90000UL, 0x00ce0000UL, 0x00550000UL, 0x00280000UL, 0x00df0000UL,
0x008c0000UL, 0x00a10000UL, 0x00890000UL, 0x000d0000UL, 0x00bf0000UL,
0x00e60000UL, 0x00420000UL, 0x00680000UL, 0x00410000UL, 0x00990000UL,
0x002d0000UL, 0x000f0000UL, 0x00b00000UL, 0x00540000UL, 0x00bb0000UL,
0x00160000UL},
{0x63000000UL, 0x7c000000UL, 0x77000000UL, 0x7b000000UL, 0xf2000000UL,
0x6b000000UL, 0x6f000000UL, 0xc5000000UL, 0x30000000UL, 0x01000000UL,
0x67000000UL, 0x2b000000UL, 0xfe000000UL, 0xd7000000UL, 0xab000000UL,
0x76000000UL, 0xca000000UL, 0x82000000UL, 0xc9000000UL, 0x7d000000UL,
0xfa000000UL, 0x59000000UL, 0x47000000UL, 0xf0000000UL, 0xad000000UL,
0xd4000000UL, 0xa2000000UL, 0xaf000000UL, 0x9c000000UL, 0xa4000000UL,
0x72000000UL, 0xc0000000UL, 0xb7000000UL, 0xfd000000UL, 0x93000000UL,
0x26000000UL, 0x36000000UL, 0x3f000000UL, 0xf7000000UL, 0xcc000000UL,
0x34000000UL, 0xa5000000UL, 0xe5000000UL, 0xf1000000UL, 0x71000000UL,
0xd8000000UL, 0x31000000UL, 0x15000000UL, 0x04000000UL, 0xc7000000UL,
0x23000000UL, 0xc3000000UL, 0x18000000UL, 0x96000000UL, 0x05000000UL,
0x9a000000UL, 0x07000000UL, 0x12000000UL, 0x80000000UL, 0xe2000000UL,
0xeb000000UL, 0x27000000UL, 0xb2000000UL, 0x75000000UL, 0x09000000UL,
0x83000000UL, 0x2c000000UL, 0x1a000000UL, 0x1b000000UL, 0x6e000000UL,
0x5a000000UL, 0xa0000000UL, 0x52000000UL, 0x3b000000UL, 0xd6000000UL,
0xb3000000UL, 0x29000000UL, 0xe3000000UL, 0x2f000000UL, 0x84000000UL,
0x53000000UL, 0xd1000000UL, 0x00000000UL, 0xed000000UL, 0x20000000UL,
0xfc000000UL, 0xb1000000UL, 0x5b000000UL, 0x6a000000UL, 0xcb000000UL,
0xbe000000UL, 0x39000000UL, 0x4a000000UL, 0x4c000000UL, 0x58000000UL,
0xcf000000UL, 0xd0000000UL, 0xef000000UL, 0xaa000000UL, 0xfb000000UL,
0x43000000UL, 0x4d000000UL, 0x33000000UL, 0x85000000UL, 0x45000000UL,
0xf9000000UL, 0x02000000UL, 0x7f000000UL, 0x50000000UL, 0x3c000000UL,
0x9f000000UL, 0xa8000000UL, 0x51000000UL, 0xa3000000UL, 0x40000000UL,
0x8f000000UL, 0x92000000UL, 0x9d000000UL, 0x38000000UL, 0xf5000000UL,
0xbc000000UL, 0xb6000000UL, 0xda000000UL, 0x21000000UL, 0x10000000UL,
0xff000000UL, 0xf3000000UL, 0xd2000000UL, 0xcd000000UL, 0x0c000000UL,
0x13000000UL, 0xec000000UL, 0x5f000000UL, 0x97000000UL, 0x44000000UL,
0x17000000UL, 0xc4000000UL, 0xa7000000UL, 0x7e000000UL, 0x3d000000UL,
0x64000000UL, 0x5d000000UL, 0x19000000UL, 0x73000000UL, 0x60000000UL,
0x81000000UL, 0x4f000000UL, 0xdc000000UL, 0x22000000UL, 0x2a000000UL,
0x90000000UL, 0x88000000UL, 0x46000000UL, 0xee000000UL, 0xb8000000UL,
0x14000000UL, 0xde000000UL, 0x5e000000UL, 0x0b000000UL, 0xdb000000UL,
0xe0000000UL, 0x32000000UL, 0x3a000000UL, 0x0a000000UL, 0x49000000UL,
0x06000000UL, 0x24000000UL, 0x5c000000UL, 0xc2000000UL, 0xd3000000UL,
0xac000000UL, 0x62000000UL, 0x91000000UL, 0x95000000UL, 0xe4000000UL,
0x79000000UL, 0xe7000000UL, 0xc8000000UL, 0x37000000UL, 0x6d000000UL,
0x8d000000UL, 0xd5000000UL, 0x4e000000UL, 0xa9000000UL, 0x6c000000UL,
0x56000000UL, 0xf4000000UL, 0xea000000UL, 0x65000000UL, 0x7a000000UL,
0xae000000UL, 0x08000000UL, 0xba000000UL, 0x78000000UL, 0x25000000UL,
0x2e000000UL, 0x1c000000UL, 0xa6000000UL, 0xb4000000UL, 0xc6000000UL,
0xe8000000UL, 0xdd000000UL, 0x74000000UL, 0x1f000000UL, 0x4b000000UL,
0xbd000000UL, 0x8b000000UL, 0x8a000000UL, 0x70000000UL, 0x3e000000UL,
0xb5000000UL, 0x66000000UL, 0x48000000UL, 0x03000000UL, 0xf6000000UL,
0x0e000000UL, 0x61000000UL, 0x35000000UL, 0x57000000UL, 0xb9000000UL,
0x86000000UL, 0xc1000000UL, 0x1d000000UL, 0x9e000000UL, 0xe1000000UL,
0xf8000000UL, 0x98000000UL, 0x11000000UL, 0x69000000UL, 0xd9000000UL,
0x8e000000UL, 0x94000000UL, 0x9b000000UL, 0x1e000000UL, 0x87000000UL,
0xe9000000UL, 0xce000000UL, 0x55000000UL, 0x28000000UL, 0xdf000000UL,
0x8c000000UL, 0xa1000000UL, 0x89000000UL, 0x0d000000UL, 0xbf000000UL,
0xe6000000UL, 0x42000000UL, 0x68000000UL, 0x41000000UL, 0x99000000UL,
0x2d000000UL, 0x0f000000UL, 0xb0000000UL, 0x54000000UL, 0xbb000000UL,
0x16000000UL}
};
static const unsigned long il_tab[4][256] = {
{0x00000052UL, 0x00000009UL, 0x0000006aUL, 0x000000d5UL, 0x00000030UL,
0x00000036UL, 0x000000a5UL, 0x00000038UL, 0x000000bfUL, 0x00000040UL,
0x000000a3UL, 0x0000009eUL, 0x00000081UL, 0x000000f3UL, 0x000000d7UL,
0x000000fbUL, 0x0000007cUL, 0x000000e3UL, 0x00000039UL, 0x00000082UL,
0x0000009bUL, 0x0000002fUL, 0x000000ffUL, 0x00000087UL, 0x00000034UL,
0x0000008eUL, 0x00000043UL, 0x00000044UL, 0x000000c4UL, 0x000000deUL,
0x000000e9UL, 0x000000cbUL, 0x00000054UL, 0x0000007bUL, 0x00000094UL,
0x00000032UL, 0x000000a6UL, 0x000000c2UL, 0x00000023UL, 0x0000003dUL,
0x000000eeUL, 0x0000004cUL, 0x00000095UL, 0x0000000bUL, 0x00000042UL,
0x000000faUL, 0x000000c3UL, 0x0000004eUL, 0x00000008UL, 0x0000002eUL,
0x000000a1UL, 0x00000066UL, 0x00000028UL, 0x000000d9UL, 0x00000024UL,
0x000000b2UL, 0x00000076UL, 0x0000005bUL, 0x000000a2UL, 0x00000049UL,
0x0000006dUL, 0x0000008bUL, 0x000000d1UL, 0x00000025UL, 0x00000072UL,
0x000000f8UL, 0x000000f6UL, 0x00000064UL, 0x00000086UL, 0x00000068UL,
0x00000098UL, 0x00000016UL, 0x000000d4UL, 0x000000a4UL, 0x0000005cUL,
0x000000ccUL, 0x0000005dUL, 0x00000065UL, 0x000000b6UL, 0x00000092UL,
0x0000006cUL, 0x00000070UL, 0x00000048UL, 0x00000050UL, 0x000000fdUL,
0x000000edUL, 0x000000b9UL, 0x000000daUL, 0x0000005eUL, 0x00000015UL,
0x00000046UL, 0x00000057UL, 0x000000a7UL, 0x0000008dUL, 0x0000009dUL,
0x00000084UL, 0x00000090UL, 0x000000d8UL, 0x000000abUL, 0x00000000UL,
0x0000008cUL, 0x000000bcUL, 0x000000d3UL, 0x0000000aUL, 0x000000f7UL,
0x000000e4UL, 0x00000058UL, 0x00000005UL, 0x000000b8UL, 0x000000b3UL,
0x00000045UL, 0x00000006UL, 0x000000d0UL, 0x0000002cUL, 0x0000001eUL,
0x0000008fUL, 0x000000caUL, 0x0000003fUL, 0x0000000fUL, 0x00000002UL,
0x000000c1UL, 0x000000afUL, 0x000000bdUL, 0x00000003UL, 0x00000001UL,
0x00000013UL, 0x0000008aUL, 0x0000006bUL, 0x0000003aUL, 0x00000091UL,
0x00000011UL, 0x00000041UL, 0x0000004fUL, 0x00000067UL, 0x000000dcUL,
0x000000eaUL, 0x00000097UL, 0x000000f2UL, 0x000000cfUL, 0x000000ceUL,
0x000000f0UL, 0x000000b4UL, 0x000000e6UL, 0x00000073UL, 0x00000096UL,
0x000000acUL, 0x00000074UL, 0x00000022UL, 0x000000e7UL, 0x000000adUL,
0x00000035UL, 0x00000085UL, 0x000000e2UL, 0x000000f9UL, 0x00000037UL,
0x000000e8UL, 0x0000001cUL, 0x00000075UL, 0x000000dfUL, 0x0000006eUL,
0x00000047UL, 0x000000f1UL, 0x0000001aUL, 0x00000071UL, 0x0000001dUL,
0x00000029UL, 0x000000c5UL, 0x00000089UL, 0x0000006fUL, 0x000000b7UL,
0x00000062UL, 0x0000000eUL, 0x000000aaUL, 0x00000018UL, 0x000000beUL,
0x0000001bUL, 0x000000fcUL, 0x00000056UL, 0x0000003eUL, 0x0000004bUL,
0x000000c6UL, 0x000000d2UL, 0x00000079UL, 0x00000020UL, 0x0000009aUL,
0x000000dbUL, 0x000000c0UL, 0x000000feUL, 0x00000078UL, 0x000000cdUL,
0x0000005aUL, 0x000000f4UL, 0x0000001fUL, 0x000000ddUL, 0x000000a8UL,
0x00000033UL, 0x00000088UL, 0x00000007UL, 0x000000c7UL, 0x00000031UL,
0x000000b1UL, 0x00000012UL, 0x00000010UL, 0x00000059UL, 0x00000027UL,
0x00000080UL, 0x000000ecUL, 0x0000005fUL, 0x00000060UL, 0x00000051UL,
0x0000007fUL, 0x000000a9UL, 0x00000019UL, 0x000000b5UL, 0x0000004aUL,
0x0000000dUL, 0x0000002dUL, 0x000000e5UL, 0x0000007aUL, 0x0000009fUL,
0x00000093UL, 0x000000c9UL, 0x0000009cUL, 0x000000efUL, 0x000000a0UL,
0x000000e0UL, 0x0000003bUL, 0x0000004dUL, 0x000000aeUL, 0x0000002aUL,
0x000000f5UL, 0x000000b0UL, 0x000000c8UL, 0x000000ebUL, 0x000000bbUL,
0x0000003cUL, 0x00000083UL, 0x00000053UL, 0x00000099UL, 0x00000061UL,
0x00000017UL, 0x0000002bUL, 0x00000004UL, 0x0000007eUL, 0x000000baUL,
0x00000077UL, 0x000000d6UL, 0x00000026UL, 0x000000e1UL, 0x00000069UL,
0x00000014UL, 0x00000063UL, 0x00000055UL, 0x00000021UL, 0x0000000cUL,
0x0000007dUL},
{0x00005200UL, 0x00000900UL, 0x00006a00UL, 0x0000d500UL, 0x00003000UL,
0x00003600UL, 0x0000a500UL, 0x00003800UL, 0x0000bf00UL, 0x00004000UL,
0x0000a300UL, 0x00009e00UL, 0x00008100UL, 0x0000f300UL, 0x0000d700UL,
0x0000fb00UL, 0x00007c00UL, 0x0000e300UL, 0x00003900UL, 0x00008200UL,
0x00009b00UL, 0x00002f00UL, 0x0000ff00UL, 0x00008700UL, 0x00003400UL,
0x00008e00UL, 0x00004300UL, 0x00004400UL, 0x0000c400UL, 0x0000de00UL,
0x0000e900UL, 0x0000cb00UL, 0x00005400UL, 0x00007b00UL, 0x00009400UL,
0x00003200UL, 0x0000a600UL, 0x0000c200UL, 0x00002300UL, 0x00003d00UL,
0x0000ee00UL, 0x00004c00UL, 0x00009500UL, 0x00000b00UL, 0x00004200UL,
0x0000fa00UL, 0x0000c300UL, 0x00004e00UL, 0x00000800UL, 0x00002e00UL,
0x0000a100UL, 0x00006600UL, 0x00002800UL, 0x0000d900UL, 0x00002400UL,
0x0000b200UL, 0x00007600UL, 0x00005b00UL, 0x0000a200UL, 0x00004900UL,
0x00006d00UL, 0x00008b00UL, 0x0000d100UL, 0x00002500UL, 0x00007200UL,
0x0000f800UL, 0x0000f600UL, 0x00006400UL, 0x00008600UL, 0x00006800UL,
0x00009800UL, 0x00001600UL, 0x0000d400UL, 0x0000a400UL, 0x00005c00UL,
0x0000cc00UL, 0x00005d00UL, 0x00006500UL, 0x0000b600UL, 0x00009200UL,
0x00006c00UL, 0x00007000UL, 0x00004800UL, 0x00005000UL, 0x0000fd00UL,
0x0000ed00UL, 0x0000b900UL, 0x0000da00UL, 0x00005e00UL, 0x00001500UL,
0x00004600UL, 0x00005700UL, 0x0000a700UL, 0x00008d00UL, 0x00009d00UL,
0x00008400UL, 0x00009000UL, 0x0000d800UL, 0x0000ab00UL, 0x00000000UL,
0x00008c00UL, 0x0000bc00UL, 0x0000d300UL, 0x00000a00UL, 0x0000f700UL,
0x0000e400UL, 0x00005800UL, 0x00000500UL, 0x0000b800UL, 0x0000b300UL,
0x00004500UL, 0x00000600UL, 0x0000d000UL, 0x00002c00UL, 0x00001e00UL,
0x00008f00UL, 0x0000ca00UL, 0x00003f00UL, 0x00000f00UL, 0x00000200UL,
0x0000c100UL, 0x0000af00UL, 0x0000bd00UL, 0x00000300UL, 0x00000100UL,
0x00001300UL, 0x00008a00UL, 0x00006b00UL, 0x00003a00UL, 0x00009100UL,
0x00001100UL, 0x00004100UL, 0x00004f00UL, 0x00006700UL, 0x0000dc00UL,
0x0000ea00UL, 0x00009700UL, 0x0000f200UL, 0x0000cf00UL, 0x0000ce00UL,
0x0000f000UL, 0x0000b400UL, 0x0000e600UL, 0x00007300UL, 0x00009600UL,
0x0000ac00UL, 0x00007400UL, 0x00002200UL, 0x0000e700UL, 0x0000ad00UL,
0x00003500UL, 0x00008500UL, 0x0000e200UL, 0x0000f900UL, 0x00003700UL,
0x0000e800UL, 0x00001c00UL, 0x00007500UL, 0x0000df00UL, 0x00006e00UL,
0x00004700UL, 0x0000f100UL, 0x00001a00UL, 0x00007100UL, 0x00001d00UL,
0x00002900UL, 0x0000c500UL, 0x00008900UL, 0x00006f00UL, 0x0000b700UL,
0x00006200UL, 0x00000e00UL, 0x0000aa00UL, 0x00001800UL, 0x0000be00UL,
0x00001b00UL, 0x0000fc00UL, 0x00005600UL, 0x00003e00UL, 0x00004b00UL,
0x0000c600UL, 0x0000d200UL, 0x00007900UL, 0x00002000UL, 0x00009a00UL,
0x0000db00UL, 0x0000c000UL, 0x0000fe00UL, 0x00007800UL, 0x0000cd00UL,
0x00005a00UL, 0x0000f400UL, 0x00001f00UL, 0x0000dd00UL, 0x0000a800UL,
0x00003300UL, 0x00008800UL, 0x00000700UL, 0x0000c700UL, 0x00003100UL,
0x0000b100UL, 0x00001200UL, 0x00001000UL, 0x00005900UL, 0x00002700UL,
0x00008000UL, 0x0000ec00UL, 0x00005f00UL, 0x00006000UL, 0x00005100UL,
0x00007f00UL, 0x0000a900UL, 0x00001900UL, 0x0000b500UL, 0x00004a00UL,
0x00000d00UL, 0x00002d00UL, 0x0000e500UL, 0x00007a00UL, 0x00009f00UL,
0x00009300UL, 0x0000c900UL, 0x00009c00UL, 0x0000ef00UL, 0x0000a000UL,
0x0000e000UL, 0x00003b00UL, 0x00004d00UL, 0x0000ae00UL, 0x00002a00UL,
0x0000f500UL, 0x0000b000UL, 0x0000c800UL, 0x0000eb00UL, 0x0000bb00UL,
0x00003c00UL, 0x00008300UL, 0x00005300UL, 0x00009900UL, 0x00006100UL,
0x00001700UL, 0x00002b00UL, 0x00000400UL, 0x00007e00UL, 0x0000ba00UL,
0x00007700UL, 0x0000d600UL, 0x00002600UL, 0x0000e100UL, 0x00006900UL,
0x00001400UL, 0x00006300UL, 0x00005500UL, 0x00002100UL, 0x00000c00UL,
0x00007d00UL},
{0x00520000UL, 0x00090000UL, 0x006a0000UL, 0x00d50000UL, 0x00300000UL,
0x00360000UL, 0x00a50000UL, 0x00380000UL, 0x00bf0000UL, 0x00400000UL,
0x00a30000UL, 0x009e0000UL, 0x00810000UL, 0x00f30000UL, 0x00d70000UL,
0x00fb0000UL, 0x007c0000UL, 0x00e30000UL, 0x00390000UL, 0x00820000UL,
0x009b0000UL, 0x002f0000UL, 0x00ff0000UL, 0x00870000UL, 0x00340000UL,
0x008e0000UL, 0x00430000UL, 0x00440000UL, 0x00c40000UL, 0x00de0000UL,
0x00e90000UL, 0x00cb0000UL, 0x00540000UL, 0x007b0000UL, 0x00940000UL,
0x00320000UL, 0x00a60000UL, 0x00c20000UL, 0x00230000UL, 0x003d0000UL,
0x00ee0000UL, 0x004c0000UL, 0x00950000UL, 0x000b0000UL, 0x00420000UL,
0x00fa0000UL, 0x00c30000UL, 0x004e0000UL, 0x00080000UL, 0x002e0000UL,
0x00a10000UL, 0x00660000UL, 0x00280000UL, 0x00d90000UL, 0x00240000UL,
0x00b20000UL, 0x00760000UL, 0x005b0000UL, 0x00a20000UL, 0x00490000UL,
0x006d0000UL, 0x008b0000UL, 0x00d10000UL, 0x00250000UL, 0x00720000UL,
0x00f80000UL, 0x00f60000UL, 0x00640000UL, 0x00860000UL, 0x00680000UL,
0x00980000UL, 0x00160000UL, 0x00d40000UL, 0x00a40000UL, 0x005c0000UL,
0x00cc0000UL, 0x005d0000UL, 0x00650000UL, 0x00b60000UL, 0x00920000UL,
0x006c0000UL, 0x00700000UL, 0x00480000UL, 0x00500000UL, 0x00fd0000UL,
0x00ed0000UL, 0x00b90000UL, 0x00da0000UL, 0x005e0000UL, 0x00150000UL,
0x00460000UL, 0x00570000UL, 0x00a70000UL, 0x008d0000UL, 0x009d0000UL,
0x00840000UL, 0x00900000UL, 0x00d80000UL, 0x00ab0000UL, 0x00000000UL,
0x008c0000UL, 0x00bc0000UL, 0x00d30000UL, 0x000a0000UL, 0x00f70000UL,
0x00e40000UL, 0x00580000UL, 0x00050000UL, 0x00b80000UL, 0x00b30000UL,
0x00450000UL, 0x00060000UL, 0x00d00000UL, 0x002c0000UL, 0x001e0000UL,
0x008f0000UL, 0x00ca0000UL, 0x003f0000UL, 0x000f0000UL, 0x00020000UL,
0x00c10000UL, 0x00af0000UL, 0x00bd0000UL, 0x00030000UL, 0x00010000UL,
0x00130000UL, 0x008a0000UL, 0x006b0000UL, 0x003a0000UL, 0x00910000UL,
0x00110000UL, 0x00410000UL, 0x004f0000UL, 0x00670000UL, 0x00dc0000UL,
0x00ea0000UL, 0x00970000UL, 0x00f20000UL, 0x00cf0000UL, 0x00ce0000UL,
0x00f00000UL, 0x00b40000UL, 0x00e60000UL, 0x00730000UL, 0x00960000UL,
0x00ac0000UL, 0x00740000UL, 0x00220000UL, 0x00e70000UL, 0x00ad0000UL,
0x00350000UL, 0x00850000UL, 0x00e20000UL, 0x00f90000UL, 0x00370000UL,
0x00e80000UL, 0x001c0000UL, 0x00750000UL, 0x00df0000UL, 0x006e0000UL,
0x00470000UL, 0x00f10000UL, 0x001a0000UL, 0x00710000UL, 0x001d0000UL,
0x00290000UL, 0x00c50000UL, 0x00890000UL, 0x006f0000UL, 0x00b70000UL,
0x00620000UL, 0x000e0000UL, 0x00aa0000UL, 0x00180000UL, 0x00be0000UL,
0x001b0000UL, 0x00fc0000UL, 0x00560000UL, 0x003e0000UL, 0x004b0000UL,
0x00c60000UL, 0x00d20000UL, 0x00790000UL, 0x00200000UL, 0x009a0000UL,
0x00db0000UL, 0x00c00000UL, 0x00fe0000UL, 0x00780000UL, 0x00cd0000UL,
0x005a0000UL, 0x00f40000UL, 0x001f0000UL, 0x00dd0000UL, 0x00a80000UL,
0x00330000UL, 0x00880000UL, 0x00070000UL, 0x00c70000UL, 0x00310000UL,
0x00b10000UL, 0x00120000UL, 0x00100000UL, 0x00590000UL, 0x00270000UL,
0x00800000UL, 0x00ec0000UL, 0x005f0000UL, 0x00600000UL, 0x00510000UL,
0x007f0000UL, 0x00a90000UL, 0x00190000UL, 0x00b50000UL, 0x004a0000UL,
0x000d0000UL, 0x002d0000UL, 0x00e50000UL, 0x007a0000UL, 0x009f0000UL,
0x00930000UL, 0x00c90000UL, 0x009c0000UL, 0x00ef0000UL, 0x00a00000UL,
0x00e00000UL, 0x003b0000UL, 0x004d0000UL, 0x00ae0000UL, 0x002a0000UL,
0x00f50000UL, 0x00b00000UL, 0x00c80000UL, 0x00eb0000UL, 0x00bb0000UL,
0x003c0000UL, 0x00830000UL, 0x00530000UL, 0x00990000UL, 0x00610000UL,
0x00170000UL, 0x002b0000UL, 0x00040000UL, 0x007e0000UL, 0x00ba0000UL,
0x00770000UL, 0x00d60000UL, 0x00260000UL, 0x00e10000UL, 0x00690000UL,
0x00140000UL, 0x00630000UL, 0x00550000UL, 0x00210000UL, 0x000c0000UL,
0x007d0000UL},
{0x52000000UL, 0x09000000UL, 0x6a000000UL, 0xd5000000UL, 0x30000000UL,
0x36000000UL, 0xa5000000UL, 0x38000000UL, 0xbf000000UL, 0x40000000UL,
0xa3000000UL, 0x9e000000UL, 0x81000000UL, 0xf3000000UL, 0xd7000000UL,
0xfb000000UL, 0x7c000000UL, 0xe3000000UL, 0x39000000UL, 0x82000000UL,
0x9b000000UL, 0x2f000000UL, 0xff000000UL, 0x87000000UL, 0x34000000UL,
0x8e000000UL, 0x43000000UL, 0x44000000UL, 0xc4000000UL, 0xde000000UL,
0xe9000000UL, 0xcb000000UL, 0x54000000UL, 0x7b000000UL, 0x94000000UL,
0x32000000UL, 0xa6000000UL, 0xc2000000UL, 0x23000000UL, 0x3d000000UL,
0xee000000UL, 0x4c000000UL, 0x95000000UL, 0x0b000000UL, 0x42000000UL,
0xfa000000UL, 0xc3000000UL, 0x4e000000UL, 0x08000000UL, 0x2e000000UL,
0xa1000000UL, 0x66000000UL, 0x28000000UL, 0xd9000000UL, 0x24000000UL,
0xb2000000UL, 0x76000000UL, 0x5b000000UL, 0xa2000000UL, 0x49000000UL,
0x6d000000UL, 0x8b000000UL, 0xd1000000UL, 0x25000000UL, 0x72000000UL,
0xf8000000UL, 0xf6000000UL, 0x64000000UL, 0x86000000UL, 0x68000000UL,
0x98000000UL, 0x16000000UL, 0xd4000000UL, 0xa4000000UL, 0x5c000000UL,
0xcc000000UL, 0x5d000000UL, 0x65000000UL, 0xb6000000UL, 0x92000000UL,
0x6c000000UL, 0x70000000UL, 0x48000000UL, 0x50000000UL, 0xfd000000UL,
0xed000000UL, 0xb9000000UL, 0xda000000UL, 0x5e000000UL, 0x15000000UL,
0x46000000UL, 0x57000000UL, 0xa7000000UL, 0x8d000000UL, 0x9d000000UL,
0x84000000UL, 0x90000000UL, 0xd8000000UL, 0xab000000UL, 0x00000000UL,
0x8c000000UL, 0xbc000000UL, 0xd3000000UL, 0x0a000000UL, 0xf7000000UL,
0xe4000000UL, 0x58000000UL, 0x05000000UL, 0xb8000000UL, 0xb3000000UL,
0x45000000UL, 0x06000000UL, 0xd0000000UL, 0x2c000000UL, 0x1e000000UL,
0x8f000000UL, 0xca000000UL, 0x3f000000UL, 0x0f000000UL, 0x02000000UL,
0xc1000000UL, 0xaf000000UL, 0xbd000000UL, 0x03000000UL, 0x01000000UL,
0x13000000UL, 0x8a000000UL, 0x6b000000UL, 0x3a000000UL, 0x91000000UL,
0x11000000UL, 0x41000000UL, 0x4f000000UL, 0x67000000UL, 0xdc000000UL,
0xea000000UL, 0x97000000UL, 0xf2000000UL, 0xcf000000UL, 0xce000000UL,
0xf0000000UL, 0xb4000000UL, 0xe6000000UL, 0x73000000UL, 0x96000000UL,
0xac000000UL, 0x74000000UL, 0x22000000UL, 0xe7000000UL, 0xad000000UL,
0x35000000UL, 0x85000000UL, 0xe2000000UL, 0xf9000000UL, 0x37000000UL,
0xe8000000UL, 0x1c000000UL, 0x75000000UL, 0xdf000000UL, 0x6e000000UL,
0x47000000UL, 0xf1000000UL, 0x1a000000UL, 0x71000000UL, 0x1d000000UL,
0x29000000UL, 0xc5000000UL, 0x89000000UL, 0x6f000000UL, 0xb7000000UL,
0x62000000UL, 0x0e000000UL, 0xaa000000UL, 0x18000000UL, 0xbe000000UL,
0x1b000000UL, 0xfc000000UL, 0x56000000UL, 0x3e000000UL, 0x4b000000UL,
0xc6000000UL, 0xd2000000UL, 0x79000000UL, 0x20000000UL, 0x9a000000UL,
0xdb000000UL, 0xc0000000UL, 0xfe000000UL, 0x78000000UL, 0xcd000000UL,
0x5a000000UL, 0xf4000000UL, 0x1f000000UL, 0xdd000000UL, 0xa8000000UL,
0x33000000UL, 0x88000000UL, 0x07000000UL, 0xc7000000UL, 0x31000000UL,
0xb1000000UL, 0x12000000UL, 0x10000000UL, 0x59000000UL, 0x27000000UL,
0x80000000UL, 0xec000000UL, 0x5f000000UL, 0x60000000UL, 0x51000000UL,
0x7f000000UL, 0xa9000000UL, 0x19000000UL, 0xb5000000UL, 0x4a000000UL,
0x0d000000UL, 0x2d000000UL, 0xe5000000UL, 0x7a000000UL, 0x9f000000UL,
0x93000000UL, 0xc9000000UL, 0x9c000000UL, 0xef000000UL, 0xa0000000UL,
0xe0000000UL, 0x3b000000UL, 0x4d000000UL, 0xae000000UL, 0x2a000000UL,
0xf5000000UL, 0xb0000000UL, 0xc8000000UL, 0xeb000000UL, 0xbb000000UL,
0x3c000000UL, 0x83000000UL, 0x53000000UL, 0x99000000UL, 0x61000000UL,
0x17000000UL, 0x2b000000UL, 0x04000000UL, 0x7e000000UL, 0xba000000UL,
0x77000000UL, 0xd6000000UL, 0x26000000UL, 0xe1000000UL, 0x69000000UL,
0x14000000UL, 0x63000000UL, 0x55000000UL, 0x21000000UL, 0x0c000000UL,
0x7d000000UL}
};
static const unsigned long rco_tab[10] = {
0x00000001UL, 0x00000002UL, 0x00000004UL, 0x00000008UL, 0x00000010UL,
0x00000020UL, 0x00000040UL, 0x00000080UL, 0x0000001bUL, 0x00000036UL
};

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

48
authors Normal file
View File

@ -0,0 +1,48 @@
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.
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.
10) Sky Schulz (sky@ogn.com)
Has submitted a set of ideas to improve the library and make it more attractive for professional users.

111
base64.c Normal file
View File

@ -0,0 +1,111 @@
/* 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];
*p++ = codes[((in[0] & 3) << 4) + (in[1] >> 4)];
*p++ = codes[((in[1] & 0xf) << 2) + (in[2] >> 6)];
*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;
unsigned c = 0;
*p++ = codes[a >> 2];
*p++ = codes[((a & 3) << 4) + (b >> 4)];
*p++ = (i+1 < len) ? codes[((b & 0xf) << 2) + (c >> 6)] : '=';
*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 = 3;
_ARGCHK(in != NULL);
_ARGCHK(out != NULL);
_ARGCHK(outlen != NULL);
for (x = y = z = t = 0; x < len; x++) {
c = map[in[x]];
if (c == 255) continue;
if (c == 254) { c = 0; g--; }
t = (t<<6)|c;
if (++y == 4) {
if (z + g > *outlen) goto error;
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;
error:
return CRYPT_BUFFER_OVERFLOW;
}
#endif

193
bits.c Normal file
View File

@ -0,0 +1,193 @@
/* portable way to get secure random bits to feed a PRNG */
#include "mycrypt.h"
#ifdef DEVRANDOM
/* on *NIX read /dev/random */
static unsigned long rng_nix(unsigned char *buf, unsigned long len,
void (*callback)(void))
{
#ifdef NO_FILE
return 0;
#else
FILE *f;
int x;
#ifdef TRY_URANDOM_FIRST
f = fopen("/dev/urandom", "rb");
if (f == NULL)
#endif /* TRY_URANDOM_FIRST */
f = fopen("/dev/random", "rb");
if (f == NULL) {
return 0;
}
x = fread(buf, 1, len, f);
fclose(f);
return x;
#endif /* NO_FILE */
}
#endif /* DEVRANDOM */
#ifdef SONY_PS2
#include <eetypes.h>
#include <eeregs.h>
#define min(a,b) ((a) < (b) ? (a) : (b))
// Very simple/stupid MD5-based RNG that samples "entropy" from various PS2 control registers
static unsigned long rng_ps2(unsigned char *buf, unsigned long len,
void (*callback)(void))
{
static unsigned long lastx[2] = { 0xaab7cb4b2fd3b2b9, 0xcec58aff72afe49f }; // md5sum of bits.c
unsigned long j;
unsigned int samples[10]; // number of sample data sources
int l;
hash_state md;
for (j = 0; j < len; j += sizeof(lastx)) {
md5_init(&md);
samples[0] = *T2_COUNT;
samples[1] = *T3_COUNT;
samples[2] = *IPU_TOP;
samples[3] = *GIF_TAG0;
samples[4] = *GIF_TAG1;
samples[5] = *GIF_TAG2;
samples[6] = *VIF1_CODE;
samples[7] = *VIF0_CODE;
samples[8] = *D0_MADR;
samples[9] = *D1_MADR;
md5_process(&md, (unsigned char *)(&samples[0]), sizeof(samples));
// include previous round
md5_process(&md, (unsigned char *)(&lastx[0]), sizeof(lastx));
md5_done(&md, (unsigned char *)(&lastx[0]));
l = min(sizeof(lastx), len-j);
memcpy(buf+j, &lastx[0], l); //min(sizeof(lastx), len-j));
}
return len;
}
#endif /* SONY_PS2 */
/* on ANSI C platforms with 100 < CLOCKS_PER_SEC < 10000 */
#if !defined(SONY_PS2) && defined(CLOCKS_PER_SEC)
#define ANSI_RNG
static unsigned long rng_ansic(unsigned char *buf, unsigned long len,
void (*callback)(void))
{
clock_t t1;
int l, acc, bits, a, b;
if (XCLOCKS_PER_SEC < 100 || XCLOCKS_PER_SEC > 10000) {
return 0;
}
l = len;
bits = 8;
acc = a = b = 0;
while (len--) {
if (callback != NULL) callback();
while (bits--) {
do {
t1 = XCLOCK(); while (t1 == XCLOCK()) a ^= 1;
t1 = XCLOCK(); while (t1 == XCLOCK()) b ^= 1;
} while (a == b);
acc = (acc << 1) | a;
}
*buf++ = acc;
acc = 0;
bits = 8;
}
acc = bits = a = b = 0;
return l;
}
#endif
/* Try the Microsoft CSP */
#ifdef WIN32
#define _WIN32_WINNT 0x0400
#include <windows.h>
#include <wincrypt.h>
static unsigned long rng_win32(unsigned char *buf, unsigned long len,
void (*callback)(void))
{
HCRYPTPROV hProv = 0;
if (!CryptAcquireContext(&hProv, NULL, MS_DEF_PROV, PROV_RSA_FULL,
(CRYPT_VERIFYCONTEXT | CRYPT_MACHINE_KEYSET)) &&
!CryptAcquireContext (&hProv, NULL, MS_DEF_PROV, PROV_RSA_FULL,
CRYPT_VERIFYCONTEXT | CRYPT_MACHINE_KEYSET | CRYPT_NEWKEYSET))
return 0;
if (CryptGenRandom(hProv, len, buf) == TRUE) {
CryptReleaseContext(hProv, 0);
return len;
} else {
CryptReleaseContext(hProv, 0);
return 0;
}
}
#endif /* WIN32 */
unsigned long rng_get_bytes(unsigned char *buf, unsigned long len,
void (*callback)(void))
{
int x;
_ARGCHK(buf != NULL);
#ifdef SONY_PS2
x = rng_ps2(buf, len, callback); if (x) { return x; }
#elif defined(DEVRANDOM)
x = rng_nix(buf, len, callback); if (x) { return x; }
#endif
#ifdef WIN32
x = rng_win32(buf, len, callback); if (x) { return x; }
#endif
#ifdef ANSI_RNG
x = rng_ansic(buf, len, callback); if (x) { return x; }
#endif
return 0;
}
int rng_make_prng(int bits, int wprng, prng_state *prng,
void (*callback)(void))
{
unsigned char buf[256];
int errno;
_ARGCHK(prng != NULL);
/* check parameter */
if ((errno = prng_is_valid(wprng)) != CRYPT_OK) {
return errno;
}
if (bits < 64 || bits > 1024) {
return CRYPT_INVALID_PRNGSIZE;
}
if ((errno = prng_descriptor[wprng].start(prng)) != CRYPT_OK) {
return errno;
}
bits = ((bits/8)+(bits&7?1:0)) * 2;
if (rng_get_bytes(buf, bits, callback) != (unsigned long)bits) {
return CRYPT_ERROR_READPRNG;
}
if ((errno = prng_descriptor[wprng].add_entropy(buf, bits, prng)) != CRYPT_OK) {
return errno;
}
if ((errno = prng_descriptor[wprng].ready(prng)) != CRYPT_OK) {
return errno;
}
#ifdef CLEAN_STACK
zeromem(buf, sizeof(buf));
#endif
return CRYPT_OK;
}

691
blowfish.c Normal file
View File

@ -0,0 +1,691 @@
#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 unsigned long ORIG_P[16 + 2] = {
0x243F6A88UL, 0x85A308D3UL, 0x13198A2EUL, 0x03707344UL,
0xA4093822UL, 0x299F31D0UL, 0x082EFA98UL, 0xEC4E6C89UL,
0x452821E6UL, 0x38D01377UL, 0xBE5466CFUL, 0x34E90C6CUL,
0xC0AC29B7UL, 0xC97C50DDUL, 0x3F84D5B5UL, 0xB5470917UL,
0x9216D5D9UL, 0x8979FB1BUL
};
static const unsigned long 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 }
};
static unsigned long F(unsigned long x, symmetric_key *key)
{
return (((key->blowfish.S[0][(x>>24)&255] +
key->blowfish.S[1][(x>>16)&255]) ^
key->blowfish.S[2][(x>>8)&255]) +
key->blowfish.S[3][(x>>0)&255]);
}
int blowfish_setup(const unsigned char *key, int keylen, int num_rounds,
symmetric_key *skey)
{
unsigned long 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) | (unsigned long) key[y++ % keylen];
}
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 */
zeromem(B, 8);
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;
}
#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
{
unsigned long L, R;
_ARGCHK(pt != NULL);
_ARGCHK(ct != NULL);
_ARGCHK(key != NULL);
/* load it */
LOAD32H(L, &pt[0]);
LOAD32H(R, &pt[4]);
/* do 16 rounds */
L ^= key->blowfish.K[0]; R ^= F(L, key);
R ^= key->blowfish.K[1]; L ^= F(R, key);
L ^= key->blowfish.K[2]; R ^= F(L, key);
R ^= key->blowfish.K[3]; L ^= F(R, key);
L ^= key->blowfish.K[4]; R ^= F(L, key);
R ^= key->blowfish.K[5]; L ^= F(R, key);
L ^= key->blowfish.K[6]; R ^= F(L, key);
R ^= key->blowfish.K[7]; L ^= F(R, key);
L ^= key->blowfish.K[8]; R ^= F(L, key);
R ^= key->blowfish.K[9]; L ^= F(R, key);
L ^= key->blowfish.K[10]; R ^= F(L, key);
R ^= key->blowfish.K[11]; L ^= F(R, key);
L ^= key->blowfish.K[12]; R ^= F(L, key);
R ^= key->blowfish.K[13]; L ^= F(R, key);
L ^= key->blowfish.K[14]; R ^= F(L, key);
R ^= key->blowfish.K[15]; L ^= F(R, key);
/* 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(unsigned long) * 2);
}
#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
{
unsigned long L, R;
_ARGCHK(pt != NULL);
_ARGCHK(ct != NULL);
_ARGCHK(key != NULL);
/* 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 */
L ^= F(R, key); R ^= key->blowfish.K[15];
R ^= F(L, key); L ^= key->blowfish.K[14];
L ^= F(R, key); R ^= key->blowfish.K[13];
R ^= F(L, key); L ^= key->blowfish.K[12];
L ^= F(R, key); R ^= key->blowfish.K[11];
R ^= F(L, key); L ^= key->blowfish.K[10];
L ^= F(R, key); R ^= key->blowfish.K[9];
R ^= F(L, key); L ^= key->blowfish.K[8];
L ^= F(R, key); R ^= key->blowfish.K[7];
R ^= F(L, key); L ^= key->blowfish.K[6];
L ^= F(R, key); R ^= key->blowfish.K[5];
R ^= F(L, key); L ^= key->blowfish.K[4];
L ^= F(R, key); R ^= key->blowfish.K[3];
R ^= F(L, key); L ^= key->blowfish.K[2];
L ^= F(R, key); R ^= key->blowfish.K[1];
R ^= F(L, key); L ^= key->blowfish.K[0];
/* 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(unsigned long) * 2);
}
#endif
int blowfish_test(void)
{
int errno;
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}
},
{
{ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11},
{ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11},
{ 0x24, 0x66, 0xDD, 0x87, 0x8B, 0x96, 0x3C, 0x9D}
},
{
{ 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF},
{ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11},
{ 0x61, 0xF9, 0xC3, 0x80, 0x22, 0x81, 0xB0, 0x96}
},
{
{ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11},
{ 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF},
{ 0x7D, 0x0C, 0xC6, 0x30, 0xAF, 0xDA, 0x1E, 0xC7}
},
{
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
{ 0x4E, 0xF9, 0x97, 0x45, 0x61, 0x98, 0xDD, 0x78}
},
{
{ 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10},
{ 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF},
{ 0x0A, 0xCE, 0xAB, 0x0F, 0xC6, 0xA0, 0xA2, 0x8D}
},
{
{ 0x7C, 0xA1, 0x10, 0x45, 0x4A, 0x1A, 0x6E, 0x57},
{ 0x01, 0xA1, 0xD6, 0xD0, 0x39, 0x77, 0x67, 0x42},
{ 0x59, 0xC6, 0x82, 0x45, 0xEB, 0x05, 0x28, 0x2B}
},
{
{ 0x01, 0x31, 0xD9, 0x61, 0x9D, 0xC1, 0x37, 0x6E},
{ 0x5C, 0xD5, 0x4C, 0xA8, 0x3D, 0xEF, 0x57, 0xDA},
{ 0xB1, 0xB8, 0xCC, 0x0B, 0x25, 0x0F, 0x09, 0xA0}
},
{
{ 0x07, 0xA1, 0x13, 0x3E, 0x4A, 0x0B, 0x26, 0x86},
{ 0x02, 0x48, 0xD4, 0x38, 0x06, 0xF6, 0x71, 0x72},
{ 0x17, 0x30, 0xE5, 0x77, 0x8B, 0xEA, 0x1D, 0xA4}
},
{
{ 0x38, 0x49, 0x67, 0x4C, 0x26, 0x02, 0x31, 0x9E},
{ 0x51, 0x45, 0x4B, 0x58, 0x2D, 0xDF, 0x44, 0x0A},
{ 0xA2, 0x5E, 0x78, 0x56, 0xCF, 0x26, 0x51, 0xEB}
},
{
{ 0x04, 0xB9, 0x15, 0xBA, 0x43, 0xFE, 0xB5, 0xB6},
{ 0x42, 0xFD, 0x44, 0x30, 0x59, 0x57, 0x7F, 0xA2},
{ 0x35, 0x38, 0x82, 0xB1, 0x09, 0xCE, 0x8F, 0x1A}
},
{
{ 0x01, 0x13, 0xB9, 0x70, 0xFD, 0x34, 0xF2, 0xCE},
{ 0x05, 0x9B, 0x5E, 0x08, 0x51, 0xCF, 0x14, 0x3A},
{ 0x48, 0xF4, 0xD0, 0x88, 0x4C, 0x37, 0x99, 0x18}
},
{
{ 0x01, 0x70, 0xF1, 0x75, 0x46, 0x8F, 0xB5, 0xE6},
{ 0x07, 0x56, 0xD8, 0xE0, 0x77, 0x47, 0x61, 0xD2},
{ 0x43, 0x21, 0x93, 0xB7, 0x89, 0x51, 0xFC, 0x98}
},
{
{ 0x43, 0x29, 0x7F, 0xAD, 0x38, 0xE3, 0x73, 0xFE},
{ 0x76, 0x25, 0x14, 0xB8, 0x29, 0xBF, 0x48, 0x6A},
{ 0x13, 0xF0, 0x41, 0x54, 0xD6, 0x9D, 0x1A, 0xE5}
},
{
{ 0x07, 0xA7, 0x13, 0x70, 0x45, 0xDA, 0x2A, 0x16},
{ 0x3B, 0xDD, 0x11, 0x90, 0x49, 0x37, 0x28, 0x02},
{ 0x2E, 0xED, 0xDA, 0x93, 0xFF, 0xD3, 0x9C, 0x79}
},
{
{ 0x04, 0x68, 0x91, 0x04, 0xC2, 0xFD, 0x3B, 0x2F},
{ 0x26, 0x95, 0x5F, 0x68, 0x35, 0xAF, 0x60, 0x9A},
{ 0xD8, 0x87, 0xE0, 0x39, 0x3C, 0x2D, 0xA6, 0xE3}
},
{
{ 0x37, 0xD0, 0x6B, 0xB5, 0x16, 0xCB, 0x75, 0x46},
{ 0x16, 0x4D, 0x5E, 0x40, 0x4F, 0x27, 0x52, 0x32},
{ 0x5F, 0x99, 0xD0, 0x4F, 0x5B, 0x16, 0x39, 0x69}
},
{
{ 0x1F, 0x08, 0x26, 0x0D, 0x1A, 0xC2, 0x46, 0x5E},
{ 0x6B, 0x05, 0x6E, 0x18, 0x75, 0x9F, 0x5C, 0xCA},
{ 0x4A, 0x05, 0x7A, 0x3B, 0x24, 0xD3, 0x97, 0x7B}
},
{
{ 0x58, 0x40, 0x23, 0x64, 0x1A, 0xBA, 0x61, 0x76},
{ 0x00, 0x4B, 0xD6, 0xEF, 0x09, 0x17, 0x60, 0x62},
{ 0x45, 0x20, 0x31, 0xC1, 0xE4, 0xFA, 0xDA, 0x8E}
},
{
{ 0x02, 0x58, 0x16, 0x16, 0x46, 0x29, 0xB0, 0x07},
{ 0x48, 0x0D, 0x39, 0x00, 0x6E, 0xE7, 0x62, 0xF2},
{ 0x75, 0x55, 0xAE, 0x39, 0xF5, 0x9B, 0x87, 0xBD}
},
{
{ 0x49, 0x79, 0x3E, 0xBC, 0x79, 0xB3, 0x25, 0x8F},
{ 0x43, 0x75, 0x40, 0xC8, 0x69, 0x8F, 0x3C, 0xFA},
{ 0x53, 0xC5, 0x5F, 0x9C, 0xB4, 0x9F, 0xC0, 0x19}
},
{
{ 0x4F, 0xB0, 0x5E, 0x15, 0x15, 0xAB, 0x73, 0xA7},
{ 0x07, 0x2D, 0x43, 0xA0, 0x77, 0x07, 0x52, 0x92},
{ 0x7A, 0x8E, 0x7B, 0xFA, 0x93, 0x7E, 0x89, 0xA3}
},
{
{ 0x49, 0xE9, 0x5D, 0x6D, 0x4C, 0xA2, 0x29, 0xBF},
{ 0x02, 0xFE, 0x55, 0x77, 0x81, 0x17, 0xF1, 0x2A},
{ 0xCF, 0x9C, 0x5D, 0x7A, 0x49, 0x86, 0xAD, 0xB5}
},
{
{ 0x01, 0x83, 0x10, 0xDC, 0x40, 0x9B, 0x26, 0xD6},
{ 0x1D, 0x9D, 0x5C, 0x50, 0x18, 0xF7, 0x28, 0xC2},
{ 0xD1, 0xAB, 0xB2, 0x90, 0x65, 0x8B, 0xC7, 0x78}
},
{
{ 0x1C, 0x58, 0x7F, 0x1C, 0x13, 0x92, 0x4F, 0xEF},
{ 0x30, 0x55, 0x32, 0x28, 0x6D, 0x6F, 0x29, 0x5A},
{ 0x55, 0xCB, 0x37, 0x74, 0xD1, 0x3E, 0xF2, 0x01}
},
{
{ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01},
{ 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF},
{ 0xFA, 0x34, 0xEC, 0x48, 0x47, 0xB2, 0x68, 0xB2}
},
{
{ 0x1F, 0x1F, 0x1F, 0x1F, 0x0E, 0x0E, 0x0E, 0x0E},
{ 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF},
{ 0xA7, 0x90, 0x79, 0x51, 0x08, 0xEA, 0x3C, 0xAE}
},
{
{ 0xE0, 0xFE, 0xE0, 0xFE, 0xF1, 0xFE, 0xF1, 0xFE},
{ 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF},
{ 0xC3, 0x9E, 0x07, 0x2D, 0x9F, 0xAC, 0x63, 0x1D}
},
{
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
{ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
{ 0x01, 0x49, 0x33, 0xE0, 0xCD, 0xAF, 0xF6, 0xE4}
},
{
{ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
{ 0xF2, 0x1E, 0x9A, 0x77, 0xB7, 0x1C, 0x49, 0xBC}
},
{
{ 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF},
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
{ 0x24, 0x59, 0x46, 0x88, 0x57, 0x54, 0x36, 0x9A}
},
{
{ 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10},
{ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
{ 0x6B, 0x5C, 0x5A, 0x9C, 0x5D, 0x9E, 0x0A, 0x5A}
}
};
unsigned char buf[2][8];
int x, failed;
for (x = failed = 0; x < (int)(sizeof(tests) / sizeof(tests[0])); x++) {
/* setup key */
if ((errno = blowfish_setup(tests[x].key, 8, 16, &key)) != CRYPT_OK) {
return errno;
}
/* encrypt and decrypt */
blowfish_ecb_encrypt(tests[x].pt, buf[0], &key);
blowfish_ecb_decrypt(buf[0], buf[1], &key);
/* compare */
if (memcmp(buf[0], tests[x].ct, 8)) {
#if 0
int y;
printf("\nEncrypt test %d failed\n", x);
for (y = 0; y < 8; y++) printf("%02x ", buf[0][y]);
printf("\n");
#endif
failed = 1;
}
if (memcmp(buf[1], tests[x].pt, 8)) {
#if 0
int y;
printf("\nDecrypt test %d failed\n", x);
for (y = 0; y < 8; y++) printf("%02x ", buf[1][y]);
printf("\n");
#endif
failed = 1;
}
}
if (failed == 1) {
return CRYPT_FAIL_TESTVECTOR;
} else {
return CRYPT_OK;
}
}
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

622
cast5.c Normal file
View File

@ -0,0 +1,622 @@
/* 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 unsigned long S1[256] = {
0x30fb40d4, 0x9fa0ff0b, 0x6beccd2f, 0x3f258c7a, 0x1e213f2f, 0x9c004dd3,
0x6003e540, 0xcf9fc949, 0xbfd4af27, 0x88bbbdb5, 0xe2034090, 0x98d09675,
0x6e63a0e0, 0x15c361d2, 0xc2e7661d, 0x22d4ff8e, 0x28683b6f, 0xc07fd059,
0xff2379c8, 0x775f50e2, 0x43c340d3, 0xdf2f8656, 0x887ca41a, 0xa2d2bd2d,
0xa1c9e0d6, 0x346c4819, 0x61b76d87, 0x22540f2f, 0x2abe32e1, 0xaa54166b,
0x22568e3a, 0xa2d341d0, 0x66db40c8, 0xa784392f, 0x004dff2f, 0x2db9d2de,
0x97943fac, 0x4a97c1d8, 0x527644b7, 0xb5f437a7, 0xb82cbaef, 0xd751d159,
0x6ff7f0ed, 0x5a097a1f, 0x827b68d0, 0x90ecf52e, 0x22b0c054, 0xbc8e5935,
0x4b6d2f7f, 0x50bb64a2, 0xd2664910, 0xbee5812d, 0xb7332290, 0xe93b159f,
0xb48ee411, 0x4bff345d, 0xfd45c240, 0xad31973f, 0xc4f6d02e, 0x55fc8165,
0xd5b1caad, 0xa1ac2dae, 0xa2d4b76d, 0xc19b0c50, 0x882240f2, 0x0c6e4f38,
0xa4e4bfd7, 0x4f5ba272, 0x564c1d2f, 0xc59c5319, 0xb949e354, 0xb04669fe,
0xb1b6ab8a, 0xc71358dd, 0x6385c545, 0x110f935d, 0x57538ad5, 0x6a390493,
0xe63d37e0, 0x2a54f6b3, 0x3a787d5f, 0x6276a0b5, 0x19a6fcdf, 0x7a42206a,
0x29f9d4d5, 0xf61b1891, 0xbb72275e, 0xaa508167, 0x38901091, 0xc6b505eb,
0x84c7cb8c, 0x2ad75a0f, 0x874a1427, 0xa2d1936b, 0x2ad286af, 0xaa56d291,
0xd7894360, 0x425c750d, 0x93b39e26, 0x187184c9, 0x6c00b32d, 0x73e2bb14,
0xa0bebc3c, 0x54623779, 0x64459eab, 0x3f328b82, 0x7718cf82, 0x59a2cea6,
0x04ee002e, 0x89fe78e6, 0x3fab0950, 0x325ff6c2, 0x81383f05, 0x6963c5c8,
0x76cb5ad6, 0xd49974c9, 0xca180dcf, 0x380782d5, 0xc7fa5cf6, 0x8ac31511,
0x35e79e13, 0x47da91d0, 0xf40f9086, 0xa7e2419e, 0x31366241, 0x051ef495,
0xaa573b04, 0x4a805d8d, 0x548300d0, 0x00322a3c, 0xbf64cddf, 0xba57a68e,
0x75c6372b, 0x50afd341, 0xa7c13275, 0x915a0bf5, 0x6b54bfab, 0x2b0b1426,
0xab4cc9d7, 0x449ccd82, 0xf7fbf265, 0xab85c5f3, 0x1b55db94, 0xaad4e324,
0xcfa4bd3f, 0x2deaa3e2, 0x9e204d02, 0xc8bd25ac, 0xeadf55b3, 0xd5bd9e98,
0xe31231b2, 0x2ad5ad6c, 0x954329de, 0xadbe4528, 0xd8710f69, 0xaa51c90f,
0xaa786bf6, 0x22513f1e, 0xaa51a79b, 0x2ad344cc, 0x7b5a41f0, 0xd37cfbad,
0x1b069505, 0x41ece491, 0xb4c332e6, 0x032268d4, 0xc9600acc, 0xce387e6d,
0xbf6bb16c, 0x6a70fb78, 0x0d03d9c9, 0xd4df39de, 0xe01063da, 0x4736f464,
0x5ad328d8, 0xb347cc96, 0x75bb0fc3, 0x98511bfb, 0x4ffbcc35, 0xb58bcf6a,
0xe11f0abc, 0xbfc5fe4a, 0xa70aec10, 0xac39570a, 0x3f04442f, 0x6188b153,
0xe0397a2e, 0x5727cb79, 0x9ceb418f, 0x1cacd68d, 0x2ad37c96, 0x0175cb9d,
0xc69dff09, 0xc75b65f0, 0xd9db40d8, 0xec0e7779, 0x4744ead4, 0xb11c3274,
0xdd24cb9e, 0x7e1c54bd, 0xf01144f9, 0xd2240eb1, 0x9675b3fd, 0xa3ac3755,
0xd47c27af, 0x51c85f4d, 0x56907596, 0xa5bb15e6, 0x580304f0, 0xca042cf1,
0x011a37ea, 0x8dbfaadb, 0x35ba3e4a, 0x3526ffa0, 0xc37b4d09, 0xbc306ed9,
0x98a52666, 0x5648f725, 0xff5e569d, 0x0ced63d0, 0x7c63b2cf, 0x700b45e1,
0xd5ea50f1, 0x85a92872, 0xaf1fbda7, 0xd4234870, 0xa7870bf3, 0x2d3b4d79,
0x42e04198, 0x0cd0ede7, 0x26470db8, 0xf881814c, 0x474d6ad7, 0x7c0c5e5c,
0xd1231959, 0x381b7298, 0xf5d2f4db, 0xab838653, 0x6e2f1e23, 0x83719c9e,
0xbd91e046, 0x9a56456e, 0xdc39200c, 0x20c8c571, 0x962bda1c, 0xe1e696ff,
0xb141ab08, 0x7cca89b9, 0x1a69e783, 0x02cc4843, 0xa2f7c579, 0x429ef47d,
0x427b169c, 0x5ac9f049, 0xdd8f0f00, 0x5c8165bf};
static const unsigned long S2[256] = {
0x1f201094, 0xef0ba75b, 0x69e3cf7e, 0x393f4380, 0xfe61cf7a, 0xeec5207a,
0x55889c94, 0x72fc0651, 0xada7ef79, 0x4e1d7235, 0xd55a63ce, 0xde0436ba,
0x99c430ef, 0x5f0c0794, 0x18dcdb7d, 0xa1d6eff3, 0xa0b52f7b, 0x59e83605,
0xee15b094, 0xe9ffd909, 0xdc440086, 0xef944459, 0xba83ccb3, 0xe0c3cdfb,
0xd1da4181, 0x3b092ab1, 0xf997f1c1, 0xa5e6cf7b, 0x01420ddb, 0xe4e7ef5b,
0x25a1ff41, 0xe180f806, 0x1fc41080, 0x179bee7a, 0xd37ac6a9, 0xfe5830a4,
0x98de8b7f, 0x77e83f4e, 0x79929269, 0x24fa9f7b, 0xe113c85b, 0xacc40083,
0xd7503525, 0xf7ea615f, 0x62143154, 0x0d554b63, 0x5d681121, 0xc866c359,
0x3d63cf73, 0xcee234c0, 0xd4d87e87, 0x5c672b21, 0x071f6181, 0x39f7627f,
0x361e3084, 0xe4eb573b, 0x602f64a4, 0xd63acd9c, 0x1bbc4635, 0x9e81032d,
0x2701f50c, 0x99847ab4, 0xa0e3df79, 0xba6cf38c, 0x10843094, 0x2537a95e,
0xf46f6ffe, 0xa1ff3b1f, 0x208cfb6a, 0x8f458c74, 0xd9e0a227, 0x4ec73a34,
0xfc884f69, 0x3e4de8df, 0xef0e0088, 0x3559648d, 0x8a45388c, 0x1d804366,
0x721d9bfd, 0xa58684bb, 0xe8256333, 0x844e8212, 0x128d8098, 0xfed33fb4,
0xce280ae1, 0x27e19ba5, 0xd5a6c252, 0xe49754bd, 0xc5d655dd, 0xeb667064,
0x77840b4d, 0xa1b6a801, 0x84db26a9, 0xe0b56714, 0x21f043b7, 0xe5d05860,
0x54f03084, 0x066ff472, 0xa31aa153, 0xdadc4755, 0xb5625dbf, 0x68561be6,
0x83ca6b94, 0x2d6ed23b, 0xeccf01db, 0xa6d3d0ba, 0xb6803d5c, 0xaf77a709,
0x33b4a34c, 0x397bc8d6, 0x5ee22b95, 0x5f0e5304, 0x81ed6f61, 0x20e74364,
0xb45e1378, 0xde18639b, 0x881ca122, 0xb96726d1, 0x8049a7e8, 0x22b7da7b,
0x5e552d25, 0x5272d237, 0x79d2951c, 0xc60d894c, 0x488cb402, 0x1ba4fe5b,
0xa4b09f6b, 0x1ca815cf, 0xa20c3005, 0x8871df63, 0xb9de2fcb, 0x0cc6c9e9,
0x0beeff53, 0xe3214517, 0xb4542835, 0x9f63293c, 0xee41e729, 0x6e1d2d7c,
0x50045286, 0x1e6685f3, 0xf33401c6, 0x30a22c95, 0x31a70850, 0x60930f13,
0x73f98417, 0xa1269859, 0xec645c44, 0x52c877a9, 0xcdff33a6, 0xa02b1741,
0x7cbad9a2, 0x2180036f, 0x50d99c08, 0xcb3f4861, 0xc26bd765, 0x64a3f6ab,
0x80342676, 0x25a75e7b, 0xe4e6d1fc, 0x20c710e6, 0xcdf0b680, 0x17844d3b,
0x31eef84d, 0x7e0824e4, 0x2ccb49eb, 0x846a3bae, 0x8ff77888, 0xee5d60f6,
0x7af75673, 0x2fdd5cdb, 0xa11631c1, 0x30f66f43, 0xb3faec54, 0x157fd7fa,
0xef8579cc, 0xd152de58, 0xdb2ffd5e, 0x8f32ce19, 0x306af97a, 0x02f03ef8,
0x99319ad5, 0xc242fa0f, 0xa7e3ebb0, 0xc68e4906, 0xb8da230c, 0x80823028,
0xdcdef3c8, 0xd35fb171, 0x088a1bc8, 0xbec0c560, 0x61a3c9e8, 0xbca8f54d,
0xc72feffa, 0x22822e99, 0x82c570b4, 0xd8d94e89, 0x8b1c34bc, 0x301e16e6,
0x273be979, 0xb0ffeaa6, 0x61d9b8c6, 0x00b24869, 0xb7ffce3f, 0x08dc283b,
0x43daf65a, 0xf7e19798, 0x7619b72f, 0x8f1c9ba4, 0xdc8637a0, 0x16a7d3b1,
0x9fc393b7, 0xa7136eeb, 0xc6bcc63e, 0x1a513742, 0xef6828bc, 0x520365d6,
0x2d6a77ab, 0x3527ed4b, 0x821fd216, 0x095c6e2e, 0xdb92f2fb, 0x5eea29cb,
0x145892f5, 0x91584f7f, 0x5483697b, 0x2667a8cc, 0x85196048, 0x8c4bacea,
0x833860d4, 0x0d23e0f9, 0x6c387e8a, 0x0ae6d249, 0xb284600c, 0xd835731d,
0xdcb1c647, 0xac4c56ea, 0x3ebd81b3, 0x230eabb0, 0x6438bc87, 0xf0b5b1fa,
0x8f5ea2b3, 0xfc184642, 0x0a036b7a, 0x4fb089bd, 0x649da589, 0xa345415e,
0x5c038323, 0x3e5d3bb9, 0x43d79572, 0x7e6dd07c, 0x06dfdf1e, 0x6c6cc4ef,
0x7160a539, 0x73bfbe70, 0x83877605, 0x4523ecf1};
static const unsigned long S3[256] = {
0x8defc240, 0x25fa5d9f, 0xeb903dbf, 0xe810c907, 0x47607fff, 0x369fe44b,
0x8c1fc644, 0xaececa90, 0xbeb1f9bf, 0xeefbcaea, 0xe8cf1950, 0x51df07ae,
0x920e8806, 0xf0ad0548, 0xe13c8d83, 0x927010d5, 0x11107d9f, 0x07647db9,
0xb2e3e4d4, 0x3d4f285e, 0xb9afa820, 0xfade82e0, 0xa067268b, 0x8272792e,
0x553fb2c0, 0x489ae22b, 0xd4ef9794, 0x125e3fbc, 0x21fffcee, 0x825b1bfd,
0x9255c5ed, 0x1257a240, 0x4e1a8302, 0xbae07fff, 0x528246e7, 0x8e57140e,
0x3373f7bf, 0x8c9f8188, 0xa6fc4ee8, 0xc982b5a5, 0xa8c01db7, 0x579fc264,
0x67094f31, 0xf2bd3f5f, 0x40fff7c1, 0x1fb78dfc, 0x8e6bd2c1, 0x437be59b,
0x99b03dbf, 0xb5dbc64b, 0x638dc0e6, 0x55819d99, 0xa197c81c, 0x4a012d6e,
0xc5884a28, 0xccc36f71, 0xb843c213, 0x6c0743f1, 0x8309893c, 0x0feddd5f,
0x2f7fe850, 0xd7c07f7e, 0x02507fbf, 0x5afb9a04, 0xa747d2d0, 0x1651192e,
0xaf70bf3e, 0x58c31380, 0x5f98302e, 0x727cc3c4, 0x0a0fb402, 0x0f7fef82,
0x8c96fdad, 0x5d2c2aae, 0x8ee99a49, 0x50da88b8, 0x8427f4a0, 0x1eac5790,
0x796fb449, 0x8252dc15, 0xefbd7d9b, 0xa672597d, 0xada840d8, 0x45f54504,
0xfa5d7403, 0xe83ec305, 0x4f91751a, 0x925669c2, 0x23efe941, 0xa903f12e,
0x60270df2, 0x0276e4b6, 0x94fd6574, 0x927985b2, 0x8276dbcb, 0x02778176,
0xf8af918d, 0x4e48f79e, 0x8f616ddf, 0xe29d840e, 0x842f7d83, 0x340ce5c8,
0x96bbb682, 0x93b4b148, 0xef303cab, 0x984faf28, 0x779faf9b, 0x92dc560d,
0x224d1e20, 0x8437aa88, 0x7d29dc96, 0x2756d3dc, 0x8b907cee, 0xb51fd240,
0xe7c07ce3, 0xe566b4a1, 0xc3e9615e, 0x3cf8209d, 0x6094d1e3, 0xcd9ca341,
0x5c76460e, 0x00ea983b, 0xd4d67881, 0xfd47572c, 0xf76cedd9, 0xbda8229c,
0x127dadaa, 0x438a074e, 0x1f97c090, 0x081bdb8a, 0x93a07ebe, 0xb938ca15,
0x97b03cff, 0x3dc2c0f8, 0x8d1ab2ec, 0x64380e51, 0x68cc7bfb, 0xd90f2788,
0x12490181, 0x5de5ffd4, 0xdd7ef86a, 0x76a2e214, 0xb9a40368, 0x925d958f,
0x4b39fffa, 0xba39aee9, 0xa4ffd30b, 0xfaf7933b, 0x6d498623, 0x193cbcfa,
0x27627545, 0x825cf47a, 0x61bd8ba0, 0xd11e42d1, 0xcead04f4, 0x127ea392,
0x10428db7, 0x8272a972, 0x9270c4a8, 0x127de50b, 0x285ba1c8, 0x3c62f44f,
0x35c0eaa5, 0xe805d231, 0x428929fb, 0xb4fcdf82, 0x4fb66a53, 0x0e7dc15b,
0x1f081fab, 0x108618ae, 0xfcfd086d, 0xf9ff2889, 0x694bcc11, 0x236a5cae,
0x12deca4d, 0x2c3f8cc5, 0xd2d02dfe, 0xf8ef5896, 0xe4cf52da, 0x95155b67,
0x494a488c, 0xb9b6a80c, 0x5c8f82bc, 0x89d36b45, 0x3a609437, 0xec00c9a9,
0x44715253, 0x0a874b49, 0xd773bc40, 0x7c34671c, 0x02717ef6, 0x4feb5536,
0xa2d02fff, 0xd2bf60c4, 0xd43f03c0, 0x50b4ef6d, 0x07478cd1, 0x006e1888,
0xa2e53f55, 0xb9e6d4bc, 0xa2048016, 0x97573833, 0xd7207d67, 0xde0f8f3d,
0x72f87b33, 0xabcc4f33, 0x7688c55d, 0x7b00a6b0, 0x947b0001, 0x570075d2,
0xf9bb88f8, 0x8942019e, 0x4264a5ff, 0x856302e0, 0x72dbd92b, 0xee971b69,
0x6ea22fde, 0x5f08ae2b, 0xaf7a616d, 0xe5c98767, 0xcf1febd2, 0x61efc8c2,
0xf1ac2571, 0xcc8239c2, 0x67214cb8, 0xb1e583d1, 0xb7dc3e62, 0x7f10bdce,
0xf90a5c38, 0x0ff0443d, 0x606e6dc6, 0x60543a49, 0x5727c148, 0x2be98a1d,
0x8ab41738, 0x20e1be24, 0xaf96da0f, 0x68458425, 0x99833be5, 0x600d457d,
0x282f9350, 0x8334b362, 0xd91d1120, 0x2b6d8da0, 0x642b1e31, 0x9c305a00,
0x52bce688, 0x1b03588a, 0xf7baefd5, 0x4142ed9c, 0xa4315c11, 0x83323ec5,
0xdfef4636, 0xa133c501, 0xe9d3531c, 0xee353783};
static const unsigned long S4[256] = {
0x9db30420, 0x1fb6e9de, 0xa7be7bef, 0xd273a298, 0x4a4f7bdb, 0x64ad8c57,
0x85510443, 0xfa020ed1, 0x7e287aff, 0xe60fb663, 0x095f35a1, 0x79ebf120,
0xfd059d43, 0x6497b7b1, 0xf3641f63, 0x241e4adf, 0x28147f5f, 0x4fa2b8cd,
0xc9430040, 0x0cc32220, 0xfdd30b30, 0xc0a5374f, 0x1d2d00d9, 0x24147b15,
0xee4d111a, 0x0fca5167, 0x71ff904c, 0x2d195ffe, 0x1a05645f, 0x0c13fefe,
0x081b08ca, 0x05170121, 0x80530100, 0xe83e5efe, 0xac9af4f8, 0x7fe72701,
0xd2b8ee5f, 0x06df4261, 0xbb9e9b8a, 0x7293ea25, 0xce84ffdf, 0xf5718801,
0x3dd64b04, 0xa26f263b, 0x7ed48400, 0x547eebe6, 0x446d4ca0, 0x6cf3d6f5,
0x2649abdf, 0xaea0c7f5, 0x36338cc1, 0x503f7e93, 0xd3772061, 0x11b638e1,
0x72500e03, 0xf80eb2bb, 0xabe0502e, 0xec8d77de, 0x57971e81, 0xe14f6746,
0xc9335400, 0x6920318f, 0x081dbb99, 0xffc304a5, 0x4d351805, 0x7f3d5ce3,
0xa6c866c6, 0x5d5bcca9, 0xdaec6fea, 0x9f926f91, 0x9f46222f, 0x3991467d,
0xa5bf6d8e, 0x1143c44f, 0x43958302, 0xd0214eeb, 0x022083b8, 0x3fb6180c,
0x18f8931e, 0x281658e6, 0x26486e3e, 0x8bd78a70, 0x7477e4c1, 0xb506e07c,
0xf32d0a25, 0x79098b02, 0xe4eabb81, 0x28123b23, 0x69dead38, 0x1574ca16,
0xdf871b62, 0x211c40b7, 0xa51a9ef9, 0x0014377b, 0x041e8ac8, 0x09114003,
0xbd59e4d2, 0xe3d156d5, 0x4fe876d5, 0x2f91a340, 0x557be8de, 0x00eae4a7,
0x0ce5c2ec, 0x4db4bba6, 0xe756bdff, 0xdd3369ac, 0xec17b035, 0x06572327,
0x99afc8b0, 0x56c8c391, 0x6b65811c, 0x5e146119, 0x6e85cb75, 0xbe07c002,
0xc2325577, 0x893ff4ec, 0x5bbfc92d, 0xd0ec3b25, 0xb7801ab7, 0x8d6d3b24,
0x20c763ef, 0xc366a5fc, 0x9c382880, 0x0ace3205, 0xaac9548a, 0xeca1d7c7,
0x041afa32, 0x1d16625a, 0x6701902c, 0x9b757a54, 0x31d477f7, 0x9126b031,
0x36cc6fdb, 0xc70b8b46, 0xd9e66a48, 0x56e55a79, 0x026a4ceb, 0x52437eff,
0x2f8f76b4, 0x0df980a5, 0x8674cde3, 0xedda04eb, 0x17a9be04, 0x2c18f4df,
0xb7747f9d, 0xab2af7b4, 0xefc34d20, 0x2e096b7c, 0x1741a254, 0xe5b6a035,
0x213d42f6, 0x2c1c7c26, 0x61c2f50f, 0x6552daf9, 0xd2c231f8, 0x25130f69,
0xd8167fa2, 0x0418f2c8, 0x001a96a6, 0x0d1526ab, 0x63315c21, 0x5e0a72ec,
0x49bafefd, 0x187908d9, 0x8d0dbd86, 0x311170a7, 0x3e9b640c, 0xcc3e10d7,
0xd5cad3b6, 0x0caec388, 0xf73001e1, 0x6c728aff, 0x71eae2a1, 0x1f9af36e,
0xcfcbd12f, 0xc1de8417, 0xac07be6b, 0xcb44a1d8, 0x8b9b0f56, 0x013988c3,
0xb1c52fca, 0xb4be31cd, 0xd8782806, 0x12a3a4e2, 0x6f7de532, 0x58fd7eb6,
0xd01ee900, 0x24adffc2, 0xf4990fc5, 0x9711aac5, 0x001d7b95, 0x82e5e7d2,
0x109873f6, 0x00613096, 0xc32d9521, 0xada121ff, 0x29908415, 0x7fbb977f,
0xaf9eb3db, 0x29c9ed2a, 0x5ce2a465, 0xa730f32c, 0xd0aa3fe8, 0x8a5cc091,
0xd49e2ce7, 0x0ce454a9, 0xd60acd86, 0x015f1919, 0x77079103, 0xdea03af6,
0x78a8565e, 0xdee356df, 0x21f05cbe, 0x8b75e387, 0xb3c50651, 0xb8a5c3ef,
0xd8eeb6d2, 0xe523be77, 0xc2154529, 0x2f69efdf, 0xafe67afb, 0xf470c4b2,
0xf3e0eb5b, 0xd6cc9876, 0x39e4460c, 0x1fda8538, 0x1987832f, 0xca007367,
0xa99144f8, 0x296b299e, 0x492fc295, 0x9266beab, 0xb5676e69, 0x9bd3ddda,
0xdf7e052f, 0xdb25701c, 0x1b5e51ee, 0xf65324e6, 0x6afce36c, 0x0316cc04,
0x8644213e, 0xb7dc59d0, 0x7965291f, 0xccd6fd43, 0x41823979, 0x932bcdf6,
0xb657c34d, 0x4edfd282, 0x7ae5290c, 0x3cb9536b, 0x851e20fe, 0x9833557e,
0x13ecf0b0, 0xd3ffb372, 0x3f85c5c1, 0x0aef7ed2};
static const unsigned long S5[256] = {
0x7ec90c04, 0x2c6e74b9, 0x9b0e66df, 0xa6337911, 0xb86a7fff, 0x1dd358f5,
0x44dd9d44, 0x1731167f, 0x08fbf1fa, 0xe7f511cc, 0xd2051b00, 0x735aba00,
0x2ab722d8, 0x386381cb, 0xacf6243a, 0x69befd7a, 0xe6a2e77f, 0xf0c720cd,
0xc4494816, 0xccf5c180, 0x38851640, 0x15b0a848, 0xe68b18cb, 0x4caadeff,
0x5f480a01, 0x0412b2aa, 0x259814fc, 0x41d0efe2, 0x4e40b48d, 0x248eb6fb,
0x8dba1cfe, 0x41a99b02, 0x1a550a04, 0xba8f65cb, 0x7251f4e7, 0x95a51725,
0xc106ecd7, 0x97a5980a, 0xc539b9aa, 0x4d79fe6a, 0xf2f3f763, 0x68af8040,
0xed0c9e56, 0x11b4958b, 0xe1eb5a88, 0x8709e6b0, 0xd7e07156, 0x4e29fea7,
0x6366e52d, 0x02d1c000, 0xc4ac8e05, 0x9377f571, 0x0c05372a, 0x578535f2,
0x2261be02, 0xd642a0c9, 0xdf13a280, 0x74b55bd2, 0x682199c0, 0xd421e5ec,
0x53fb3ce8, 0xc8adedb3, 0x28a87fc9, 0x3d959981, 0x5c1ff900, 0xfe38d399,
0x0c4eff0b, 0x062407ea, 0xaa2f4fb1, 0x4fb96976, 0x90c79505, 0xb0a8a774,
0xef55a1ff, 0xe59ca2c2, 0xa6b62d27, 0xe66a4263, 0xdf65001f, 0x0ec50966,
0xdfdd55bc, 0x29de0655, 0x911e739a, 0x17af8975, 0x32c7911c, 0x89f89468,
0x0d01e980, 0x524755f4, 0x03b63cc9, 0x0cc844b2, 0xbcf3f0aa, 0x87ac36e9,
0xe53a7426, 0x01b3d82b, 0x1a9e7449, 0x64ee2d7e, 0xcddbb1da, 0x01c94910,
0xb868bf80, 0x0d26f3fd, 0x9342ede7, 0x04a5c284, 0x636737b6, 0x50f5b616,
0xf24766e3, 0x8eca36c1, 0x136e05db, 0xfef18391, 0xfb887a37, 0xd6e7f7d4,
0xc7fb7dc9, 0x3063fcdf, 0xb6f589de, 0xec2941da, 0x26e46695, 0xb7566419,
0xf654efc5, 0xd08d58b7, 0x48925401, 0xc1bacb7f, 0xe5ff550f, 0xb6083049,
0x5bb5d0e8, 0x87d72e5a, 0xab6a6ee1, 0x223a66ce, 0xc62bf3cd, 0x9e0885f9,
0x68cb3e47, 0x086c010f, 0xa21de820, 0xd18b69de, 0xf3f65777, 0xfa02c3f6,
0x407edac3, 0xcbb3d550, 0x1793084d, 0xb0d70eba, 0x0ab378d5, 0xd951fb0c,
0xded7da56, 0x4124bbe4, 0x94ca0b56, 0x0f5755d1, 0xe0e1e56e, 0x6184b5be,
0x580a249f, 0x94f74bc0, 0xe327888e, 0x9f7b5561, 0xc3dc0280, 0x05687715,
0x646c6bd7, 0x44904db3, 0x66b4f0a3, 0xc0f1648a, 0x697ed5af, 0x49e92ff6,
0x309e374f, 0x2cb6356a, 0x85808573, 0x4991f840, 0x76f0ae02, 0x083be84d,
0x28421c9a, 0x44489406, 0x736e4cb8, 0xc1092910, 0x8bc95fc6, 0x7d869cf4,
0x134f616f, 0x2e77118d, 0xb31b2be1, 0xaa90b472, 0x3ca5d717, 0x7d161bba,
0x9cad9010, 0xaf462ba2, 0x9fe459d2, 0x45d34559, 0xd9f2da13, 0xdbc65487,
0xf3e4f94e, 0x176d486f, 0x097c13ea, 0x631da5c7, 0x445f7382, 0x175683f4,
0xcdc66a97, 0x70be0288, 0xb3cdcf72, 0x6e5dd2f3, 0x20936079, 0x459b80a5,
0xbe60e2db, 0xa9c23101, 0xeba5315c, 0x224e42f2, 0x1c5c1572, 0xf6721b2c,
0x1ad2fff3, 0x8c25404e, 0x324ed72f, 0x4067b7fd, 0x0523138e, 0x5ca3bc78,
0xdc0fd66e, 0x75922283, 0x784d6b17, 0x58ebb16e, 0x44094f85, 0x3f481d87,
0xfcfeae7b, 0x77b5ff76, 0x8c2302bf, 0xaaf47556, 0x5f46b02a, 0x2b092801,
0x3d38f5f7, 0x0ca81f36, 0x52af4a8a, 0x66d5e7c0, 0xdf3b0874, 0x95055110,
0x1b5ad7a8, 0xf61ed5ad, 0x6cf6e479, 0x20758184, 0xd0cefa65, 0x88f7be58,
0x4a046826, 0x0ff6f8f3, 0xa09c7f70, 0x5346aba0, 0x5ce96c28, 0xe176eda3,
0x6bac307f, 0x376829d2, 0x85360fa9, 0x17e3fe2a, 0x24b79767, 0xf5a96b20,
0xd6cd2595, 0x68ff1ebf, 0x7555442c, 0xf19f06be, 0xf9e0659a, 0xeeb9491d,
0x34010718, 0xbb30cab8, 0xe822fe15, 0x88570983, 0x750e6249, 0xda627e55,
0x5e76ffa8, 0xb1534546, 0x6d47de08, 0xefe9e7d4};
static const unsigned long S6[256] = {
0xf6fa8f9d, 0x2cac6ce1, 0x4ca34867, 0xe2337f7c, 0x95db08e7, 0x016843b4,
0xeced5cbc, 0x325553ac, 0xbf9f0960, 0xdfa1e2ed, 0x83f0579d, 0x63ed86b9,
0x1ab6a6b8, 0xde5ebe39, 0xf38ff732, 0x8989b138, 0x33f14961, 0xc01937bd,
0xf506c6da, 0xe4625e7e, 0xa308ea99, 0x4e23e33c, 0x79cbd7cc, 0x48a14367,
0xa3149619, 0xfec94bd5, 0xa114174a, 0xeaa01866, 0xa084db2d, 0x09a8486f,
0xa888614a, 0x2900af98, 0x01665991, 0xe1992863, 0xc8f30c60, 0x2e78ef3c,
0xd0d51932, 0xcf0fec14, 0xf7ca07d2, 0xd0a82072, 0xfd41197e, 0x9305a6b0,
0xe86be3da, 0x74bed3cd, 0x372da53c, 0x4c7f4448, 0xdab5d440, 0x6dba0ec3,
0x083919a7, 0x9fbaeed9, 0x49dbcfb0, 0x4e670c53, 0x5c3d9c01, 0x64bdb941,
0x2c0e636a, 0xba7dd9cd, 0xea6f7388, 0xe70bc762, 0x35f29adb, 0x5c4cdd8d,
0xf0d48d8c, 0xb88153e2, 0x08a19866, 0x1ae2eac8, 0x284caf89, 0xaa928223,
0x9334be53, 0x3b3a21bf, 0x16434be3, 0x9aea3906, 0xefe8c36e, 0xf890cdd9,
0x80226dae, 0xc340a4a3, 0xdf7e9c09, 0xa694a807, 0x5b7c5ecc, 0x221db3a6,
0x9a69a02f, 0x68818a54, 0xceb2296f, 0x53c0843a, 0xfe893655, 0x25bfe68a,
0xb4628abc, 0xcf222ebf, 0x25ac6f48, 0xa9a99387, 0x53bddb65, 0xe76ffbe7,
0xe967fd78, 0x0ba93563, 0x8e342bc1, 0xe8a11be9, 0x4980740d, 0xc8087dfc,
0x8de4bf99, 0xa11101a0, 0x7fd37975, 0xda5a26c0, 0xe81f994f, 0x9528cd89,
0xfd339fed, 0xb87834bf, 0x5f04456d, 0x22258698, 0xc9c4c83b, 0x2dc156be,
0x4f628daa, 0x57f55ec5, 0xe2220abe, 0xd2916ebf, 0x4ec75b95, 0x24f2c3c0,
0x42d15d99, 0xcd0d7fa0, 0x7b6e27ff, 0xa8dc8af0, 0x7345c106, 0xf41e232f,
0x35162386, 0xe6ea8926, 0x3333b094, 0x157ec6f2, 0x372b74af, 0x692573e4,
0xe9a9d848, 0xf3160289, 0x3a62ef1d, 0xa787e238, 0xf3a5f676, 0x74364853,
0x20951063, 0x4576698d, 0xb6fad407, 0x592af950, 0x36f73523, 0x4cfb6e87,
0x7da4cec0, 0x6c152daa, 0xcb0396a8, 0xc50dfe5d, 0xfcd707ab, 0x0921c42f,
0x89dff0bb, 0x5fe2be78, 0x448f4f33, 0x754613c9, 0x2b05d08d, 0x48b9d585,
0xdc049441, 0xc8098f9b, 0x7dede786, 0xc39a3373, 0x42410005, 0x6a091751,
0x0ef3c8a6, 0x890072d6, 0x28207682, 0xa9a9f7be, 0xbf32679d, 0xd45b5b75,
0xb353fd00, 0xcbb0e358, 0x830f220a, 0x1f8fb214, 0xd372cf08, 0xcc3c4a13,
0x8cf63166, 0x061c87be, 0x88c98f88, 0x6062e397, 0x47cf8e7a, 0xb6c85283,
0x3cc2acfb, 0x3fc06976, 0x4e8f0252, 0x64d8314d, 0xda3870e3, 0x1e665459,
0xc10908f0, 0x513021a5, 0x6c5b68b7, 0x822f8aa0, 0x3007cd3e, 0x74719eef,
0xdc872681, 0x073340d4, 0x7e432fd9, 0x0c5ec241, 0x8809286c, 0xf592d891,
0x08a930f6, 0x957ef305, 0xb7fbffbd, 0xc266e96f, 0x6fe4ac98, 0xb173ecc0,
0xbc60b42a, 0x953498da, 0xfba1ae12, 0x2d4bd736, 0x0f25faab, 0xa4f3fceb,
0xe2969123, 0x257f0c3d, 0x9348af49, 0x361400bc, 0xe8816f4a, 0x3814f200,
0xa3f94043, 0x9c7a54c2, 0xbc704f57, 0xda41e7f9, 0xc25ad33a, 0x54f4a084,
0xb17f5505, 0x59357cbe, 0xedbd15c8, 0x7f97c5ab, 0xba5ac7b5, 0xb6f6deaf,
0x3a479c3a, 0x5302da25, 0x653d7e6a, 0x54268d49, 0x51a477ea, 0x5017d55b,
0xd7d25d88, 0x44136c76, 0x0404a8c8, 0xb8e5a121, 0xb81a928a, 0x60ed5869,
0x97c55b96, 0xeaec991b, 0x29935913, 0x01fdb7f1, 0x088e8dfa, 0x9ab6f6f5,
0x3b4cbf9f, 0x4a5de3ab, 0xe6051d35, 0xa0e1d855, 0xd36b4cf1, 0xf544edeb,
0xb0e93524, 0xbebb8fbd, 0xa2d762cf, 0x49c92f54, 0x38b5f331, 0x7128a454,
0x48392905, 0xa65b1db8, 0x851c97bd, 0xd675cf2f};
static const unsigned long S7[256] = {
0x85e04019, 0x332bf567, 0x662dbfff, 0xcfc65693, 0x2a8d7f6f, 0xab9bc912,
0xde6008a1, 0x2028da1f, 0x0227bce7, 0x4d642916, 0x18fac300, 0x50f18b82,
0x2cb2cb11, 0xb232e75c, 0x4b3695f2, 0xb28707de, 0xa05fbcf6, 0xcd4181e9,
0xe150210c, 0xe24ef1bd, 0xb168c381, 0xfde4e789, 0x5c79b0d8, 0x1e8bfd43,
0x4d495001, 0x38be4341, 0x913cee1d, 0x92a79c3f, 0x089766be, 0xbaeeadf4,
0x1286becf, 0xb6eacb19, 0x2660c200, 0x7565bde4, 0x64241f7a, 0x8248dca9,
0xc3b3ad66, 0x28136086, 0x0bd8dfa8, 0x356d1cf2, 0x107789be, 0xb3b2e9ce,
0x0502aa8f, 0x0bc0351e, 0x166bf52a, 0xeb12ff82, 0xe3486911, 0xd34d7516,
0x4e7b3aff, 0x5f43671b, 0x9cf6e037, 0x4981ac83, 0x334266ce, 0x8c9341b7,
0xd0d854c0, 0xcb3a6c88, 0x47bc2829, 0x4725ba37, 0xa66ad22b, 0x7ad61f1e,
0x0c5cbafa, 0x4437f107, 0xb6e79962, 0x42d2d816, 0x0a961288, 0xe1a5c06e,
0x13749e67, 0x72fc081a, 0xb1d139f7, 0xf9583745, 0xcf19df58, 0xbec3f756,
0xc06eba30, 0x07211b24, 0x45c28829, 0xc95e317f, 0xbc8ec511, 0x38bc46e9,
0xc6e6fa14, 0xbae8584a, 0xad4ebc46, 0x468f508b, 0x7829435f, 0xf124183b,
0x821dba9f, 0xaff60ff4, 0xea2c4e6d, 0x16e39264, 0x92544a8b, 0x009b4fc3,
0xaba68ced, 0x9ac96f78, 0x06a5b79a, 0xb2856e6e, 0x1aec3ca9, 0xbe838688,
0x0e0804e9, 0x55f1be56, 0xe7e5363b, 0xb3a1f25d, 0xf7debb85, 0x61fe033c,
0x16746233, 0x3c034c28, 0xda6d0c74, 0x79aac56c, 0x3ce4e1ad, 0x51f0c802,
0x98f8f35a, 0x1626a49f, 0xeed82b29, 0x1d382fe3, 0x0c4fb99a, 0xbb325778,
0x3ec6d97b, 0x6e77a6a9, 0xcb658b5c, 0xd45230c7, 0x2bd1408b, 0x60c03eb7,
0xb9068d78, 0xa33754f4, 0xf430c87d, 0xc8a71302, 0xb96d8c32, 0xebd4e7be,
0xbe8b9d2d, 0x7979fb06, 0xe7225308, 0x8b75cf77, 0x11ef8da4, 0xe083c858,
0x8d6b786f, 0x5a6317a6, 0xfa5cf7a0, 0x5dda0033, 0xf28ebfb0, 0xf5b9c310,
0xa0eac280, 0x08b9767a, 0xa3d9d2b0, 0x79d34217, 0x021a718d, 0x9ac6336a,
0x2711fd60, 0x438050e3, 0x069908a8, 0x3d7fedc4, 0x826d2bef, 0x4eeb8476,
0x488dcf25, 0x36c9d566, 0x28e74e41, 0xc2610aca, 0x3d49a9cf, 0xbae3b9df,
0xb65f8de6, 0x92aeaf64, 0x3ac7d5e6, 0x9ea80509, 0xf22b017d, 0xa4173f70,
0xdd1e16c3, 0x15e0d7f9, 0x50b1b887, 0x2b9f4fd5, 0x625aba82, 0x6a017962,
0x2ec01b9c, 0x15488aa9, 0xd716e740, 0x40055a2c, 0x93d29a22, 0xe32dbf9a,
0x058745b9, 0x3453dc1e, 0xd699296e, 0x496cff6f, 0x1c9f4986, 0xdfe2ed07,
0xb87242d1, 0x19de7eae, 0x053e561a, 0x15ad6f8c, 0x66626c1c, 0x7154c24c,
0xea082b2a, 0x93eb2939, 0x17dcb0f0, 0x58d4f2ae, 0x9ea294fb, 0x52cf564c,
0x9883fe66, 0x2ec40581, 0x763953c3, 0x01d6692e, 0xd3a0c108, 0xa1e7160e,
0xe4f2dfa6, 0x693ed285, 0x74904698, 0x4c2b0edd, 0x4f757656, 0x5d393378,
0xa132234f, 0x3d321c5d, 0xc3f5e194, 0x4b269301, 0xc79f022f, 0x3c997e7e,
0x5e4f9504, 0x3ffafbbd, 0x76f7ad0e, 0x296693f4, 0x3d1fce6f, 0xc61e45be,
0xd3b5ab34, 0xf72bf9b7, 0x1b0434c0, 0x4e72b567, 0x5592a33d, 0xb5229301,
0xcfd2a87f, 0x60aeb767, 0x1814386b, 0x30bcc33d, 0x38a0c07d, 0xfd1606f2,
0xc363519b, 0x589dd390, 0x5479f8e6, 0x1cb8d647, 0x97fd61a9, 0xea7759f4,
0x2d57539d, 0x569a58cf, 0xe84e63ad, 0x462e1b78, 0x6580f87e, 0xf3817914,
0x91da55f4, 0x40a230f3, 0xd1988f35, 0xb6e318d2, 0x3ffa50bc, 0x3d40f021,
0xc3c0bdae, 0x4958c24c, 0x518f36b2, 0x84b1d370, 0x0fedce83, 0x878ddada,
0xf2a279c7, 0x94e01be8, 0x90716f4b, 0x954b8aa3};
static const unsigned long S8[256] = {
0xe216300d, 0xbbddfffc, 0xa7ebdabd, 0x35648095, 0x7789f8b7, 0xe6c1121b,
0x0e241600, 0x052ce8b5, 0x11a9cfb0, 0xe5952f11, 0xece7990a, 0x9386d174,
0x2a42931c, 0x76e38111, 0xb12def3a, 0x37ddddfc, 0xde9adeb1, 0x0a0cc32c,
0xbe197029, 0x84a00940, 0xbb243a0f, 0xb4d137cf, 0xb44e79f0, 0x049eedfd,
0x0b15a15d, 0x480d3168, 0x8bbbde5a, 0x669ded42, 0xc7ece831, 0x3f8f95e7,
0x72df191b, 0x7580330d, 0x94074251, 0x5c7dcdfa, 0xabbe6d63, 0xaa402164,
0xb301d40a, 0x02e7d1ca, 0x53571dae, 0x7a3182a2, 0x12a8ddec, 0xfdaa335d,
0x176f43e8, 0x71fb46d4, 0x38129022, 0xce949ad4, 0xb84769ad, 0x965bd862,
0x82f3d055, 0x66fb9767, 0x15b80b4e, 0x1d5b47a0, 0x4cfde06f, 0xc28ec4b8,
0x57e8726e, 0x647a78fc, 0x99865d44, 0x608bd593, 0x6c200e03, 0x39dc5ff6,
0x5d0b00a3, 0xae63aff2, 0x7e8bd632, 0x70108c0c, 0xbbd35049, 0x2998df04,
0x980cf42a, 0x9b6df491, 0x9e7edd53, 0x06918548, 0x58cb7e07, 0x3b74ef2e,
0x522fffb1, 0xd24708cc, 0x1c7e27cd, 0xa4eb215b, 0x3cf1d2e2, 0x19b47a38,
0x424f7618, 0x35856039, 0x9d17dee7, 0x27eb35e6, 0xc9aff67b, 0x36baf5b8,
0x09c467cd, 0xc18910b1, 0xe11dbf7b, 0x06cd1af8, 0x7170c608, 0x2d5e3354,
0xd4de495a, 0x64c6d006, 0xbcc0c62c, 0x3dd00db3, 0x708f8f34, 0x77d51b42,
0x264f620f, 0x24b8d2bf, 0x15c1b79e, 0x46a52564, 0xf8d7e54e, 0x3e378160,
0x7895cda5, 0x859c15a5, 0xe6459788, 0xc37bc75f, 0xdb07ba0c, 0x0676a3ab,
0x7f229b1e, 0x31842e7b, 0x24259fd7, 0xf8bef472, 0x835ffcb8, 0x6df4c1f2,
0x96f5b195, 0xfd0af0fc, 0xb0fe134c, 0xe2506d3d, 0x4f9b12ea, 0xf215f225,
0xa223736f, 0x9fb4c428, 0x25d04979, 0x34c713f8, 0xc4618187, 0xea7a6e98,
0x7cd16efc, 0x1436876c, 0xf1544107, 0xbedeee14, 0x56e9af27, 0xa04aa441,
0x3cf7c899, 0x92ecbae6, 0xdd67016d, 0x151682eb, 0xa842eedf, 0xfdba60b4,
0xf1907b75, 0x20e3030f, 0x24d8c29e, 0xe139673b, 0xefa63fb8, 0x71873054,
0xb6f2cf3b, 0x9f326442, 0xcb15a4cc, 0xb01a4504, 0xf1e47d8d, 0x844a1be5,
0xbae7dfdc, 0x42cbda70, 0xcd7dae0a, 0x57e85b7a, 0xd53f5af6, 0x20cf4d8c,
0xcea4d428, 0x79d130a4, 0x3486ebfb, 0x33d3cddc, 0x77853b53, 0x37effcb5,
0xc5068778, 0xe580b3e6, 0x4e68b8f4, 0xc5c8b37e, 0x0d809ea2, 0x398feb7c,
0x132a4f94, 0x43b7950e, 0x2fee7d1c, 0x223613bd, 0xdd06caa2, 0x37df932b,
0xc4248289, 0xacf3ebc3, 0x5715f6b7, 0xef3478dd, 0xf267616f, 0xc148cbe4,
0x9052815e, 0x5e410fab, 0xb48a2465, 0x2eda7fa4, 0xe87b40e4, 0xe98ea084,
0x5889e9e1, 0xefd390fc, 0xdd07d35b, 0xdb485694, 0x38d7e5b2, 0x57720101,
0x730edebc, 0x5b643113, 0x94917e4f, 0x503c2fba, 0x646f1282, 0x7523d24a,
0xe0779695, 0xf9c17a8f, 0x7a5b2121, 0xd187b896, 0x29263a4d, 0xba510cdf,
0x81f47c9f, 0xad1163ed, 0xea7b5965, 0x1a00726e, 0x11403092, 0x00da6d77,
0x4a0cdd61, 0xad1f4603, 0x605bdfb0, 0x9eedc364, 0x22ebe6a8, 0xcee7d28a,
0xa0e736a0, 0x5564a6b9, 0x10853209, 0xc7eb8f37, 0x2de705ca, 0x8951570f,
0xdf09822b, 0xbd691a6c, 0xaa12e4f2, 0x87451c0f, 0xe0f6a27a, 0x3ada4819,
0x4cf1764f, 0x0d771c2b, 0x67cdb156, 0x350d8384, 0x5938fa0f, 0x42399ef3,
0x36997b07, 0x0e84093d, 0x4aa93e61, 0x8360d87b, 0x1fa98b0c, 0x1149382c,
0xe97625a5, 0x0614d1b7, 0x0e25244b, 0x0c768347, 0x589e8d82, 0x0d2059d1,
0xa466bb1e, 0xf8da0a82, 0x04f19130, 0xba6e4ec0, 0x99265164, 0x1ee7230d,
0x50b2ad80, 0xeaee6801, 0x8db2a283, 0xea8bf59e};
/* returns the i'th byte of a variable */
#define GB(x, i) (((x[(15-i)>>2])>>(8*((15-i)&3)))&255)
int cast5_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey)
{
unsigned long 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, 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;
}
static unsigned long FI(unsigned long R, unsigned long Km, unsigned long Kr)
{
unsigned long I;
I = (Km + R);
I = ROL(I, Kr);
return ((S1[(I>>24)&255] ^ S2[(I>>16)&255]) - S3[(I>>8)&255]) + S4[I&255];
}
static unsigned long FII(unsigned long R, unsigned long Km, unsigned long Kr)
{
unsigned long I;
I = (Km ^ R);
I = ROL(I, Kr);
return ((S1[(I>>24)&255] - S2[(I>>16)&255]) + S3[(I>>8)&255]) ^ S4[I&255];
}
static unsigned long FIII(unsigned long R, unsigned long Km, unsigned long Kr)
{
unsigned long I;
I = (Km - R);
I = ROL(I, Kr);
return ((S1[(I>>24)&255] + S2[(I>>16)&255]) ^ S3[(I>>8)&255]) - S4[I&255];
}
void cast5_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *key)
{
unsigned long 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]);
}
void cast5_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *key)
{
unsigned long 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]);
}
int cast5_test(void)
{
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},
{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF},
{0xEB, 0x6A, 0x71, 0x1A, 0x2C, 0x02, 0x27, 0x1B},
},
{ 5,
{0x01, 0x23, 0x45, 0x67, 0x12},
{0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF},
{0x7A, 0xC8, 0x16, 0xD1, 0x6E, 0x9B, 0x30, 0x2E}
}
};
int i, errno;
symmetric_key key;
unsigned char buf[8], buf2[8];
for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) {
if ((errno = cast5_setup(tests[i].key, tests[i].keylen, 0, &key)) != CRYPT_OK) {
return errno;
}
cast5_ecb_encrypt(tests[i].pt, buf, &key);
if (memcmp(buf, tests[i].ct, 8)) {
#if 0
int j;
printf("\n\n\nFailed encrypt test: %d\n", i);
for (j = 0; j < 8; j++) printf("%02x ", buf[j]);
printf("\n");
#endif
return CRYPT_FAIL_TESTVECTOR;
}
cast5_ecb_decrypt(buf, buf2, &key);
if (memcmp(buf2, tests[i].pt, 8)) {
#if 0
int j;
printf("\n\n\nFailed decrypt test: %d\n", i);
for (j = 0; j < 8; j++) printf("%02x ", buf2[j]);
printf("\n");
#endif
return CRYPT_FAIL_TESTVECTOR;
}
}
return CRYPT_OK;
}
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

101
cbc.c Normal file
View File

@ -0,0 +1,101 @@
#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, errno;
_ARGCHK(IV != NULL);
_ARGCHK(key != NULL);
_ARGCHK(cbc != NULL);
/* bad param? */
if ((errno = cipher_is_valid(cipher)) != CRYPT_OK) {
return errno;
}
/* setup cipher */
if ((errno = cipher_descriptor[cipher].setup(key, keylen, num_rounds, &cbc->key)) != CRYPT_OK) {
return errno;
}
/* 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;
}
int cbc_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_CBC *cbc)
{
int x, errno;
unsigned char tmp[MAXBLOCKSIZE];
_ARGCHK(pt != NULL);
_ARGCHK(ct != NULL);
_ARGCHK(cbc != NULL);
if ((errno = cipher_is_valid(cbc->cipher)) != CRYPT_OK) {
return errno;
}
/* 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;
}
int cbc_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_CBC *cbc)
{
int x, errno;
unsigned char tmp[MAXBLOCKSIZE], tmp2[MAXBLOCKSIZE];
_ARGCHK(pt != NULL);
_ARGCHK(ct != NULL);
_ARGCHK(cbc != NULL);
/* decrypt the block from ct into tmp */
if ((errno = cipher_is_valid(cbc->cipher)) != CRYPT_OK) {
return errno;
}
cipher_descriptor[cbc->cipher].ecb_decrypt(ct, tmp, &cbc->key);
/* 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

86
cfb.c Normal file
View File

@ -0,0 +1,86 @@
#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, errno;
_ARGCHK(IV != NULL);
_ARGCHK(key != NULL);
_ARGCHK(cfb != NULL);
if ((errno = cipher_is_valid(cipher)) != CRYPT_OK) {
return errno;
}
/* 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 ((errno = cipher_descriptor[cipher].setup(key, keylen, num_rounds, &cfb->key)) != CRYPT_OK) {
return errno;
}
/* encrypt the IV */
cipher_descriptor[cfb->cipher].ecb_encrypt(cfb->IV, cfb->IV, &cfb->key);
cfb->padlen = 0;
return CRYPT_OK;
}
int cfb_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_CFB *cfb)
{
int errno;
_ARGCHK(pt != NULL);
_ARGCHK(ct != NULL);
_ARGCHK(cfb != NULL);
if ((errno = cipher_is_valid(cfb->cipher)) != CRYPT_OK) {
return errno;
}
while (len--) {
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;
}
int cfb_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_CFB *cfb)
{
int errno;
_ARGCHK(pt != NULL);
_ARGCHK(ct != NULL);
_ARGCHK(cfb != NULL);
if ((errno = cipher_is_valid(cfb->cipher)) != CRYPT_OK) {
return errno;
}
while (len--) {
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

622
changes Normal file
View File

@ -0,0 +1,622 @@
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.

507
crypt.c Normal file
View File

@ -0,0 +1,507 @@
#include "mycrypt.h"
#include <signal.h>
struct _cipher_descriptor cipher_descriptor[32] = {
{ 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 },
{ 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 },
{ 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 },
{ 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 },
{ 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 },
{ 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 },
{ 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 },
{ 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 } };
struct _hash_descriptor hash_descriptor[32] = {
{ 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 },
{ 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 },
{ 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 },
{ 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 },
{ 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 },
{ 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 },
{ 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 },
{ 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 } };
struct _prng_descriptor prng_descriptor[32] = {
{ NULL, NULL, NULL, NULL, NULL },
{ NULL, NULL, NULL, NULL, NULL },
{ NULL, NULL, NULL, NULL, NULL },
{ NULL, NULL, NULL, NULL, NULL },
{ NULL, NULL, NULL, NULL, NULL },
{ NULL, NULL, NULL, NULL, NULL },
{ NULL, NULL, NULL, NULL, NULL },
{ NULL, NULL, NULL, NULL, NULL },
{ NULL, NULL, NULL, NULL, NULL },
{ NULL, NULL, NULL, NULL, NULL },
{ NULL, NULL, NULL, NULL, NULL },
{ NULL, NULL, NULL, NULL, NULL },
{ NULL, NULL, NULL, NULL, NULL },
{ NULL, NULL, NULL, NULL, NULL },
{ NULL, NULL, NULL, NULL, NULL },
{ NULL, NULL, NULL, NULL, NULL },
{ NULL, NULL, NULL, NULL, NULL },
{ NULL, NULL, NULL, NULL, NULL },
{ NULL, NULL, NULL, NULL, NULL },
{ NULL, NULL, NULL, NULL, NULL },
{ NULL, NULL, NULL, NULL, NULL },
{ NULL, NULL, NULL, NULL, NULL },
{ NULL, NULL, NULL, NULL, NULL },
{ NULL, NULL, NULL, NULL, NULL },
{ NULL, NULL, NULL, NULL, NULL },
{ NULL, NULL, NULL, NULL, NULL },
{ NULL, NULL, NULL, NULL, NULL },
{ NULL, NULL, NULL, NULL, NULL },
{ NULL, NULL, NULL, NULL, NULL },
{ NULL, NULL, NULL, NULL, NULL },
{ NULL, NULL, NULL, NULL, NULL },
{ NULL, NULL, NULL, NULL, NULL } };
int find_cipher(const char *name)
{
int x;
_ARGCHK(name != NULL);
for (x = 0; x < 32; x++) {
if (cipher_descriptor[x].name != NULL && !strcmp(cipher_descriptor[x].name, name)) {
return x;
}
}
return -1;
}
int find_hash(const char *name)
{
int x;
_ARGCHK(name != NULL);
for (x = 0; x < 32; x++) {
if (hash_descriptor[x].name != NULL && !strcmp(hash_descriptor[x].name, name)) {
return x;
}
}
return -1;
}
int find_prng(const char *name)
{
int x;
_ARGCHK(name != NULL);
for (x = 0; x < 32; x++) {
if ((prng_descriptor[x].name != NULL) && !strcmp(prng_descriptor[x].name, name)) {
return x;
}
}
return -1;
}
int find_cipher_id(unsigned char ID)
{
int x;
for (x = 0; x < 32; x++) {
if (cipher_descriptor[x].ID == ID) {
return (cipher_descriptor[x].name == NULL) ? -1 : x;
}
}
return -1;
}
int find_hash_id(unsigned char ID)
{
int x;
for (x = 0; x < 32; x++) {
if (hash_descriptor[x].ID == ID) {
return (hash_descriptor[x].name == NULL) ? -1 : x;
}
}
return -1;
}
/* 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; cipher_descriptor[x].name != NULL; x++) {
if (blocklen <= (int)cipher_descriptor[x].block_length && keylen <= (int)cipher_descriptor[x].max_key_length) {
return x;
}
}
return -1;
}
int register_cipher(const struct _cipher_descriptor *cipher)
{
int x;
_ARGCHK(cipher != NULL);
/* is it already registered? */
for (x = 0; x < 32; x++) {
if (!memcmp(&cipher_descriptor[x], cipher, sizeof(struct _cipher_descriptor))) {
return x;
}
}
/* find a blank spot */
for (x = 0; x < 32; x++) {
if (cipher_descriptor[x].name == NULL) {
memcpy(&cipher_descriptor[x], cipher, sizeof(struct _cipher_descriptor));
return x;
}
}
/* no spot */
return -1;
}
int unregister_cipher(const struct _cipher_descriptor *cipher)
{
int x;
_ARGCHK(cipher != NULL);
/* is it already registered? */
for (x = 0; x < 32; x++) {
if (!memcmp(&cipher_descriptor[x], cipher, sizeof(struct _cipher_descriptor))) {
cipher_descriptor[x].name = NULL;
return CRYPT_OK;
}
}
return CRYPT_ERROR;
}
int register_hash(const struct _hash_descriptor *hash)
{
int x;
_ARGCHK(hash != NULL);
/* is it already registered? */
for (x = 0; x < 32; x++) {
if (!memcmp(&hash_descriptor[x], hash, sizeof(struct _hash_descriptor))) {
return x;
}
}
/* find a blank spot */
for (x = 0; x < 32; x++) {
if (hash_descriptor[x].name == NULL) {
memcpy(&hash_descriptor[x], hash, sizeof(struct _hash_descriptor));
return x;
}
}
/* no spot */
return -1;
}
int unregister_hash(const struct _hash_descriptor *hash)
{
int x;
_ARGCHK(hash != NULL);
/* is it already registered? */
for (x = 0; x < 32; x++) {
if (!memcmp(&hash_descriptor[x], hash, sizeof(struct _hash_descriptor))) {
hash_descriptor[x].name = NULL;
return CRYPT_OK;
}
}
return CRYPT_ERROR;
}
int register_prng(const struct _prng_descriptor *prng)
{
int x;
_ARGCHK(prng != NULL);
/* is it already registered? */
for (x = 0; x < 32; x++) {
if (!memcmp(&prng_descriptor[x], prng, sizeof(struct _prng_descriptor))) {
return x;
}
}
/* find a blank spot */
for (x = 0; x < 32; x++) {
if (prng_descriptor[x].name == NULL) {
memcpy(&prng_descriptor[x], prng, sizeof(struct _prng_descriptor));
return x;
}
}
/* no spot */
return -1;
}
int unregister_prng(const struct _prng_descriptor *prng)
{
int x;
_ARGCHK(prng != NULL);
/* is it already registered? */
for (x = 0; x < 32; x++) {
if (!memcmp(&prng_descriptor[x], prng, sizeof(struct _prng_descriptor))) {
prng_descriptor[x].name = NULL;
return CRYPT_OK;
}
}
return CRYPT_ERROR;
}
int cipher_is_valid(int idx)
{
if (idx < 0 || idx > 32 || cipher_descriptor[idx].name == NULL) {
return CRYPT_INVALID_CIPHER;
}
return CRYPT_OK;
}
int hash_is_valid(int idx)
{
if (idx < 0 || idx > 32 || hash_descriptor[idx].name == NULL) {
return CRYPT_INVALID_HASH;
}
return CRYPT_OK;
}
int prng_is_valid(int idx)
{
if (idx < 0 || idx > 32 || prng_descriptor[idx].name == NULL) {
return CRYPT_INVALID_PRNG;
}
return CRYPT_OK;
}
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(SERPENT)
" Serpent\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
"\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(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
"\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
"\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
"\nVarious others: "
#if defined(GF)
" GF "
#endif
#if defined(BASE64)
" BASE64 "
#endif
#if defined(MPI)
" MPI "
#endif
#if defined(HMAC)
" HMAC "
#endif
#if defined(TRY_UNRANDOM_FIRST)
" TRY_UNRANDOM_FIRST "
#endif
#if defined(SMALL_PRIME_TAB)
" SMALL_PRIME_TAB "
#endif
"\n"
"\n\n\n"
;

BIN
crypt.pdf Normal file

Binary file not shown.

2412
crypt.tex Normal file

File diff suppressed because it is too large Load Diff

77
ctr.c Normal file
View File

@ -0,0 +1,77 @@
#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, errno;
_ARGCHK(count != NULL);
_ARGCHK(key != NULL);
_ARGCHK(ctr != NULL);
/* bad param? */
if ((errno = cipher_is_valid(cipher)) != CRYPT_OK) {
return errno;
}
/* setup cipher */
if ((errno = cipher_descriptor[cipher].setup(key, keylen, num_rounds, &ctr->key)) != CRYPT_OK) {
return errno;
}
/* copy ctr */
ctr->blocklen = cipher_descriptor[cipher].block_length;
ctr->cipher = cipher;
ctr->padlen = 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;
}
int ctr_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_CTR *ctr)
{
int x, errno;
_ARGCHK(pt != NULL);
_ARGCHK(ct != NULL);
_ARGCHK(ctr != NULL);
if ((errno = cipher_is_valid(ctr->cipher)) != CRYPT_OK) {
return errno;
}
while (len--) {
/* is the pad empty? */
if (ctr->padlen == ctr->blocklen) {
/* increment counter */
for (x = 0; x < ctr->blocklen; x++) {
ctr->ctr[x] = (ctr->ctr[x] + 1) & 255;
if (ctr->ctr[x] != 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;
}
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

202
demos/encrypt.c Normal file
View File

@ -0,0 +1,202 @@
/* 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;
static const struct _cipher_descriptor *ciphers[] = {
&blowfish_desc, &xtea_desc, &rc5_desc, &rc6_desc,
&saferp_desc, &serpent_desc, &rijndael_desc,
&twofish_desc, &safer_k64_desc, &safer_sk64_desc,
&safer_k128_desc, &safer_sk128_desc, &rc2_desc,
&des_desc, &des3_desc, &cast5_desc, NULL
};
int usage(void)
{
int x;
printf("Usage: ./crypt [-d](ecrypt) cipher infile outfile\nCiphers:\n");
for (x = 0; cipher_descriptor[x].name != NULL; x++) {
printf("%s\n",cipher_descriptor[x].name);
}
exit(1);
}
void register_algs(void)
{
int x;
for (x = 0; ciphers[x] != NULL; x++) {
if (register_cipher(ciphers[x]) == -1) {
printf("Error registering cipher\n");
exit(-1);
}
}
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();
}
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(tmpkey,sizeof(tmpkey), stdin);
outlen = sizeof(key);
if ((errno = hash_memory(hash_idx,tmpkey,strlen(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;
}

77
demos/hashsum.c Normal file
View File

@ -0,0 +1,77 @@
/*
* 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.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)
{
register_hash(&sha512_desc);
register_hash(&sha384_desc);
register_hash(&sha256_desc);
register_hash(&sha1_desc);
register_hash(&md5_desc);
register_hash(&md4_desc);
register_hash(&tiger_desc);
register_hash(&md2_desc);
}

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(&sha1_desc);
return 0;
}

1586
demos/test.c Normal file

File diff suppressed because it is too large Load Diff

7
demos/timer.c Normal file
View File

@ -0,0 +1,7 @@
/*
* The working version of this file can be found
* at the PlayStation(r)2 Developer Network website
* under the libtomcrypt project.
*/
#error Please download the implemented version of this file from the PlayStation(r)2 Developer Network website

51
demos/timer.h Normal file
View File

@ -0,0 +1,51 @@
#ifndef __TIMER_H__
#define __TIMER_H__
/****************************************************************************
*
* Copyright (c) 2000, Sony Computer Entertainment of America Inc.
* All rights reserved
* SCEA Confidential
*
* Document: TIMER.H
* Author: Ben Wiggins
* Date: 7/15/2002
* Header: Timer stuff
*
****************************************************************************/
/*============================================================================
= INTERFACE REQUIRED HEADERS
============================================================================*/
/*============================================================================
= INTERFACE DEFINITIONS / ENUMERATIONS / SIMPLE TYPEDEFS
============================================================================*/
/*============================================================================
= INTERFACE STRUCTURES / UTILITY CLASSES
============================================================================*/
/*============================================================================
= INTERFACE DATA DECLARATIONS
============================================================================*/
/*============================================================================
= INTERFACE FUNCTION PROTOTYPES
============================================================================*/
void TIMER_Init(void);
void TIMER_Shutdown(void);
double TIMER_GetTime(void);
#include <time.h>
#ifdef CLOCKS_PER_SEC
#undef CLOCKS_PER_SEC
#endif
#define CLOCKS_PER_SEC 576000
extern clock_t TIMER_clock(void);
/*============================================================================
= INTERFACE TRAILING HEADERS
============================================================================*/
/****************************************************************************
*
* END HEADER TIMER.H
*
****************************************************************************/
#endif // __TIMER_H__

728
des.c Normal file
View File

@ -0,0 +1,728 @@
/* DES code submitted by Dobes Vandermeer */
#include "mycrypt.h"
#ifdef DES
#define EN0 0
#define DE1 1
const struct _cipher_descriptor des_desc =
{
"des",
13,
8, 8, 8, 16,
&des_setup,
&des_ecb_encrypt,
&des_ecb_decrypt,
&des_test,
&des_keysize
};
const struct _cipher_descriptor des3_desc =
{
"3des",
14,
24, 24, 8, 16,
&des3_setup,
&des3_ecb_encrypt,
&des3_ecb_decrypt,
&des3_test,
&des3_keysize
};
static const unsigned char Df_Key[24] =
{
0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10,
0x89, 0xab, 0xcd, 0xef, 0x01, 0x23, 0x45, 0x67
};
static const unsigned short bytebit[8] =
{
0200, 0100, 040, 020, 010, 04, 02, 01
};
static const unsigned long bigbyte[24] =
{
0x800000L, 0x400000L, 0x200000L, 0x100000L,
0x80000L, 0x40000L, 0x20000L, 0x10000L,
0x8000L, 0x4000L, 0x2000L, 0x1000L,
0x800L, 0x400L, 0x200L, 0x100L,
0x80L, 0x40L, 0x20L, 0x10L,
0x8L, 0x4L, 0x2L, 0x1L
};
/* Use the key schedule specific in the standard (ANSI X3.92-1981) */
static const unsigned char pc1[56] = {
56, 48, 40, 32, 24, 16, 8, 0, 57, 49, 41, 33, 25, 17,
9, 1, 58, 50, 42, 34, 26, 18, 10, 2, 59, 51, 43, 35,
62, 54, 46, 38, 30, 22, 14, 6, 61, 53, 45, 37, 29, 21,
13, 5, 60, 52, 44, 36, 28, 20, 12, 4, 27, 19, 11, 3
};
static const unsigned char totrot[16] = {
1, 2, 4, 6,
8, 10, 12, 14,
15, 17, 19, 21,
23, 25, 27, 28
};
static const unsigned char pc2[48] = {
13, 16, 10, 23, 0, 4, 2, 27, 14, 5, 20, 9,
22, 18, 11, 3, 25, 7, 15, 6, 26, 19, 12, 1,
40, 51, 30, 36, 46, 54, 29, 39, 50, 44, 32, 47,
43, 48, 38, 55, 33, 52, 45, 41, 49, 35, 28, 31
};
static const unsigned long SP1[64] =
{
0x01010400L, 0x00000000L, 0x00010000L, 0x01010404L,
0x01010004L, 0x00010404L, 0x00000004L, 0x00010000L,
0x00000400L, 0x01010400L, 0x01010404L, 0x00000400L,
0x01000404L, 0x01010004L, 0x01000000L, 0x00000004L,
0x00000404L, 0x01000400L, 0x01000400L, 0x00010400L,
0x00010400L, 0x01010000L, 0x01010000L, 0x01000404L,
0x00010004L, 0x01000004L, 0x01000004L, 0x00010004L,
0x00000000L, 0x00000404L, 0x00010404L, 0x01000000L,
0x00010000L, 0x01010404L, 0x00000004L, 0x01010000L,
0x01010400L, 0x01000000L, 0x01000000L, 0x00000400L,
0x01010004L, 0x00010000L, 0x00010400L, 0x01000004L,
0x00000400L, 0x00000004L, 0x01000404L, 0x00010404L,
0x01010404L, 0x00010004L, 0x01010000L, 0x01000404L,
0x01000004L, 0x00000404L, 0x00010404L, 0x01010400L,
0x00000404L, 0x01000400L, 0x01000400L, 0x00000000L,
0x00010004L, 0x00010400L, 0x00000000L, 0x01010004
};
static const unsigned long SP2[64] =
{
0x80108020L, 0x80008000L, 0x00008000L, 0x00108020L,
0x00100000L, 0x00000020L, 0x80100020L, 0x80008020L,
0x80000020L, 0x80108020L, 0x80108000L, 0x80000000L,
0x80008000L, 0x00100000L, 0x00000020L, 0x80100020L,
0x00108000L, 0x00100020L, 0x80008020L, 0x00000000L,
0x80000000L, 0x00008000L, 0x00108020L, 0x80100000L,
0x00100020L, 0x80000020L, 0x00000000L, 0x00108000L,
0x00008020L, 0x80108000L, 0x80100000L, 0x00008020L,
0x00000000L, 0x00108020L, 0x80100020L, 0x00100000L,
0x80008020L, 0x80100000L, 0x80108000L, 0x00008000L,
0x80100000L, 0x80008000L, 0x00000020L, 0x80108020L,
0x00108020L, 0x00000020L, 0x00008000L, 0x80000000L,
0x00008020L, 0x80108000L, 0x00100000L, 0x80000020L,
0x00100020L, 0x80008020L, 0x80000020L, 0x00100020L,
0x00108000L, 0x00000000L, 0x80008000L, 0x00008020L,
0x80000000L, 0x80100020L, 0x80108020L, 0x00108000
};
static const unsigned long SP3[64] =
{
0x00000208L, 0x08020200L, 0x00000000L, 0x08020008L,
0x08000200L, 0x00000000L, 0x00020208L, 0x08000200L,
0x00020008L, 0x08000008L, 0x08000008L, 0x00020000L,
0x08020208L, 0x00020008L, 0x08020000L, 0x00000208L,
0x08000000L, 0x00000008L, 0x08020200L, 0x00000200L,
0x00020200L, 0x08020000L, 0x08020008L, 0x00020208L,
0x08000208L, 0x00020200L, 0x00020000L, 0x08000208L,
0x00000008L, 0x08020208L, 0x00000200L, 0x08000000L,
0x08020200L, 0x08000000L, 0x00020008L, 0x00000208L,
0x00020000L, 0x08020200L, 0x08000200L, 0x00000000L,
0x00000200L, 0x00020008L, 0x08020208L, 0x08000200L,
0x08000008L, 0x00000200L, 0x00000000L, 0x08020008L,
0x08000208L, 0x00020000L, 0x08000000L, 0x08020208L,
0x00000008L, 0x00020208L, 0x00020200L, 0x08000008L,
0x08020000L, 0x08000208L, 0x00000208L, 0x08020000L,
0x00020208L, 0x00000008L, 0x08020008L, 0x00020200
};
static const unsigned long SP4[64] =
{
0x00802001L, 0x00002081L, 0x00002081L, 0x00000080L,
0x00802080L, 0x00800081L, 0x00800001L, 0x00002001L,
0x00000000L, 0x00802000L, 0x00802000L, 0x00802081L,
0x00000081L, 0x00000000L, 0x00800080L, 0x00800001L,
0x00000001L, 0x00002000L, 0x00800000L, 0x00802001L,
0x00000080L, 0x00800000L, 0x00002001L, 0x00002080L,
0x00800081L, 0x00000001L, 0x00002080L, 0x00800080L,
0x00002000L, 0x00802080L, 0x00802081L, 0x00000081L,
0x00800080L, 0x00800001L, 0x00802000L, 0x00802081L,
0x00000081L, 0x00000000L, 0x00000000L, 0x00802000L,
0x00002080L, 0x00800080L, 0x00800081L, 0x00000001L,
0x00802001L, 0x00002081L, 0x00002081L, 0x00000080L,
0x00802081L, 0x00000081L, 0x00000001L, 0x00002000L,
0x00800001L, 0x00002001L, 0x00802080L, 0x00800081L,
0x00002001L, 0x00002080L, 0x00800000L, 0x00802001L,
0x00000080L, 0x00800000L, 0x00002000L, 0x00802080
};
static const unsigned long SP5[64] =
{
0x00000100L, 0x02080100L, 0x02080000L, 0x42000100L,
0x00080000L, 0x00000100L, 0x40000000L, 0x02080000L,
0x40080100L, 0x00080000L, 0x02000100L, 0x40080100L,
0x42000100L, 0x42080000L, 0x00080100L, 0x40000000L,
0x02000000L, 0x40080000L, 0x40080000L, 0x00000000L,
0x40000100L, 0x42080100L, 0x42080100L, 0x02000100L,
0x42080000L, 0x40000100L, 0x00000000L, 0x42000000L,
0x02080100L, 0x02000000L, 0x42000000L, 0x00080100L,
0x00080000L, 0x42000100L, 0x00000100L, 0x02000000L,
0x40000000L, 0x02080000L, 0x42000100L, 0x40080100L,
0x02000100L, 0x40000000L, 0x42080000L, 0x02080100L,
0x40080100L, 0x00000100L, 0x02000000L, 0x42080000L,
0x42080100L, 0x00080100L, 0x42000000L, 0x42080100L,
0x02080000L, 0x00000000L, 0x40080000L, 0x42000000L,
0x00080100L, 0x02000100L, 0x40000100L, 0x00080000L,
0x00000000L, 0x40080000L, 0x02080100L, 0x40000100
};
static const unsigned long SP6[64] =
{
0x20000010L, 0x20400000L, 0x00004000L, 0x20404010L,
0x20400000L, 0x00000010L, 0x20404010L, 0x00400000L,
0x20004000L, 0x00404010L, 0x00400000L, 0x20000010L,
0x00400010L, 0x20004000L, 0x20000000L, 0x00004010L,
0x00000000L, 0x00400010L, 0x20004010L, 0x00004000L,
0x00404000L, 0x20004010L, 0x00000010L, 0x20400010L,
0x20400010L, 0x00000000L, 0x00404010L, 0x20404000L,
0x00004010L, 0x00404000L, 0x20404000L, 0x20000000L,
0x20004000L, 0x00000010L, 0x20400010L, 0x00404000L,
0x20404010L, 0x00400000L, 0x00004010L, 0x20000010L,
0x00400000L, 0x20004000L, 0x20000000L, 0x00004010L,
0x20000010L, 0x20404010L, 0x00404000L, 0x20400000L,
0x00404010L, 0x20404000L, 0x00000000L, 0x20400010L,
0x00000010L, 0x00004000L, 0x20400000L, 0x00404010L,
0x00004000L, 0x00400010L, 0x20004010L, 0x00000000L,
0x20404000L, 0x20000000L, 0x00400010L, 0x20004010
};
static const unsigned long SP7[64] =
{
0x00200000L, 0x04200002L, 0x04000802L, 0x00000000L,
0x00000800L, 0x04000802L, 0x00200802L, 0x04200800L,
0x04200802L, 0x00200000L, 0x00000000L, 0x04000002L,
0x00000002L, 0x04000000L, 0x04200002L, 0x00000802L,
0x04000800L, 0x00200802L, 0x00200002L, 0x04000800L,
0x04000002L, 0x04200000L, 0x04200800L, 0x00200002L,
0x04200000L, 0x00000800L, 0x00000802L, 0x04200802L,
0x00200800L, 0x00000002L, 0x04000000L, 0x00200800L,
0x04000000L, 0x00200800L, 0x00200000L, 0x04000802L,
0x04000802L, 0x04200002L, 0x04200002L, 0x00000002L,
0x00200002L, 0x04000000L, 0x04000800L, 0x00200000L,
0x04200800L, 0x00000802L, 0x00200802L, 0x04200800L,
0x00000802L, 0x04000002L, 0x04200802L, 0x04200000L,
0x00200800L, 0x00000000L, 0x00000002L, 0x04200802L,
0x00000000L, 0x00200802L, 0x04200000L, 0x00000800L,
0x04000002L, 0x04000800L, 0x00000800L, 0x00200002
};
static const unsigned long SP8[64] =
{
0x10001040L, 0x00001000L, 0x00040000L, 0x10041040L,
0x10000000L, 0x10001040L, 0x00000040L, 0x10000000L,
0x00040040L, 0x10040000L, 0x10041040L, 0x00041000L,
0x10041000L, 0x00041040L, 0x00001000L, 0x00000040L,
0x10040000L, 0x10000040L, 0x10001000L, 0x00001040L,
0x00041000L, 0x00040040L, 0x10040040L, 0x10041000L,
0x00001040L, 0x00000000L, 0x00000000L, 0x10040040L,
0x10000040L, 0x10001000L, 0x00041040L, 0x00040000L,
0x00041040L, 0x00040000L, 0x10041000L, 0x00001000L,
0x00000040L, 0x10040040L, 0x00001000L, 0x00041040L,
0x10001000L, 0x00000040L, 0x10000040L, 0x10040000L,
0x10040040L, 0x10000000L, 0x00040000L, 0x10001040L,
0x00000000L, 0x10041040L, 0x00040040L, 0x10000040L,
0x10040000L, 0x10001000L, 0x10001040L, 0x00000000L,
0x10041040L, 0x00041000L, 0x00041000L, 0x00001040L,
0x00001040L, 0x00040040L, 0x10000000L, 0x10041000
};
static void cookey(const unsigned long *raw1, unsigned long *keyout);
#ifdef CLEAN_STACK
void _deskey(const unsigned char *key, short edf, unsigned long *keyout)
#else
void deskey(const unsigned char *key, short edf, unsigned long *keyout)
#endif
{
int i, j, l, m, n;
unsigned char pc1m[56], pcr[56];
unsigned long kn[32];
for(j=0; j < 56; j++)
{
l = pc1[j];
m = l & 07;
pc1m[j] = (key[l >> 3] & bytebit[m]) ? 1 : 0;
}
for(i=0; i < 16; i++)
{
if(edf == DE1) m = (15 - i) << 1;
else m = i << 1;
n = m + 1;
kn[m] = kn[n] = 0L;
for(j=0; j < 28; j++)
{
l = j + totrot[i];
if(l < 28) pcr[j] = pc1m[l];
else pcr[j] = pc1m[l - 28];
}
for(/*j = 28*/; j < 56; j++)
{
l = j + totrot[i];
if(l < 56) pcr[j] = pc1m[l];
else pcr[j] = pc1m[l - 28];
}
for(j=0; j < 24; j++)
{
if(pcr[pc2[j]]) kn[m] |= bigbyte[j];
if(pcr[pc2[j+24]]) kn[n] |= bigbyte[j];
}
}
cookey(kn, keyout);
}
#ifdef CLEAN_STACK
void deskey(const unsigned char *key, short edf, unsigned long *keyout)
{
_deskey(key, edf, keyout);
burn_stack(sizeof(int)*5 + sizeof(unsigned long)*32 + sizeof(unsigned char)*112);
}
#endif
#ifdef CLEAN_STACK
static void _cookey(const unsigned long *raw1, unsigned long *keyout)
#else
static void cookey(const unsigned long *raw1, unsigned long *keyout)
#endif
{
unsigned long *cook;
const unsigned long *raw0;
unsigned long dough[32];
int i;
cook = dough;
for(i=0; i < 16; i++, raw1++)
{
raw0 = raw1++;
*cook = (*raw0 & 0x00fc0000L) << 6;
*cook |= (*raw0 & 0x00000fc0L) << 10;
*cook |= (*raw1 & 0x00fc0000L) >> 10;
*cook++ |= (*raw1 & 0x00000fc0L) >> 6;
*cook = (*raw0 & 0x0003f000L) << 12;
*cook |= (*raw0 & 0x0000003fL) << 16;
*cook |= (*raw1 & 0x0003f000L) >> 4;
*cook++ |= (*raw1 & 0x0000003fL);
}
memcpy(keyout, dough, sizeof dough);
}
#ifdef CLEAN_STACK
static void cookey(const unsigned long *raw1, unsigned long *keyout)
{
_cookey(raw1, keyout);
burn_stack(sizeof(unsigned long *) * 2 + sizeof(unsigned long)*32 + sizeof(int));
}
#endif
#ifndef CLEAN_STACK
static void desfunc(unsigned long *block, const unsigned long *keys)
#else
static void _desfunc(unsigned long *block, const unsigned long *keys)
#endif
{
unsigned long fval, work, right, leftt;
int round;
leftt = block[0];
right = block[1];
work = ((leftt >> 4) ^ right) & 0x0f0f0f0fL;
right ^= work;
leftt ^= (work << 4);
work = ((leftt >> 16) ^ right) & 0x0000ffffL;
right ^= work;
leftt ^= (work << 16);
work = ((right >> 2) ^ leftt) & 0x33333333L;
leftt ^= work;
right ^= (work << 2);
work = ((right >> 8) ^ leftt) & 0x00ff00ffL;
leftt ^= work;
right ^= (work << 8);
right = ((right << 1) | ((right >> 31) & 1L)) & 0xFFFFFFFFL;
work = (leftt ^ right) & 0xaaaaaaaaL;
leftt ^= work;
right ^= work;
leftt = ((leftt << 1) | ((leftt >> 31) & 1L)) & 0xffffffffL;
for( round = 0; round < 8; round++)
{
work = ((right << 28) | (right >> 4)) ^ *keys++;
fval = SP7[ work & 0x3fL]
| SP5[(work >> 8) & 0x3fL]
| SP3[(work >> 16) & 0x3fL]
| SP1[(work >> 24) & 0x3fL];
work = right ^ *keys++;
fval |= SP8[ work & 0x3fL]
| SP6[(work >> 8) & 0x3fL]
| SP4[(work >> 16) & 0x3fL]
| SP2[(work >> 24) & 0x3fL];
leftt ^= fval;
work = ((leftt << 28) | (leftt >> 4)) ^ *keys++;
fval = SP7[ work & 0x3fL]
| SP5[(work >> 8) & 0x3fL]
| SP3[(work >> 16) & 0x3fL]
| SP1[(work >> 24) & 0x3fL];
work = leftt ^ *keys++;
fval |= SP8[ work & 0x3fL]
| SP6[(work >> 8) & 0x3fL]
| SP4[(work >> 16) & 0x3fL]
| SP2[(work >> 24) & 0x3fL];
right ^= fval;
}
right = (right << 31) | (right >> 1);
work = (leftt ^ right) & 0xaaaaaaaaL;
leftt ^= work;
right ^= work;
leftt = (leftt << 31) | (leftt >> 1);
work = ((leftt >> 8) ^ right) & 0x00ff00ffL;
right ^= work;
leftt ^= (work << 8);
// --
work = ((leftt >> 2) ^ right) & 0x33333333L;
right ^= work;
leftt ^= (work << 2);
work = ((right >> 16) ^ leftt) & 0x0000ffffL;
leftt ^= work;
right ^= (work << 16);
work = ((right >> 4) ^ leftt) & 0x0f0f0f0fL;
leftt ^= work;
right ^= (work << 4);
block[0] = right;
block[1] = leftt;
}
#ifdef CLEAN_STACK
static void desfunc(unsigned long *block, const unsigned long *keys)
{
_desfunc(block, keys);
burn_stack(sizeof(unsigned long) * 4 + sizeof(int));
}
#endif
int des_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey)
{
_ARGCHK(key != NULL);
_ARGCHK(skey != NULL);
if (num_rounds != 0 && num_rounds != 16) {
return CRYPT_INVALID_ROUNDS;
}
if (keylen != 8) {
return CRYPT_INVALID_KEYSIZE;
}
deskey(key, EN0, skey->des.ek);
deskey(key, DE1, skey->des.dk);
return CRYPT_OK;
}
int des3_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey)
{
_ARGCHK(key != NULL);
_ARGCHK(skey != NULL);
if( num_rounds != 0 && num_rounds != 16) {
return CRYPT_INVALID_ROUNDS;
}
if (keylen != 24) {
return CRYPT_INVALID_KEYSIZE;
}
deskey(key, EN0, skey->des3.ek[0]);
deskey(key+8, DE1, skey->des3.ek[1]);
deskey(key+16, EN0, skey->des3.ek[2]);
deskey(key, DE1, skey->des3.dk[2]);
deskey(key+8, EN0, skey->des3.dk[1]);
deskey(key+16, DE1, skey->des3.dk[0]);
return CRYPT_OK;
}
void des_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *key)
{
unsigned long work[2];
_ARGCHK(pt != NULL);
_ARGCHK(ct != NULL);
_ARGCHK(key != NULL);
LOAD32H(work[0], pt+0);
LOAD32H(work[1], pt+4);
desfunc(work, key->des.ek);
STORE32H(work[0],ct+0);
STORE32H(work[1],ct+4);
}
void des_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *key)
{
unsigned long work[2];
_ARGCHK(pt != NULL);
_ARGCHK(ct != NULL);
_ARGCHK(key != NULL);
LOAD32H(work[0], ct+0);
LOAD32H(work[1], ct+4);
desfunc(work, key->des.dk);
STORE32H(work[0],pt+0);
STORE32H(work[1],pt+4);
}
void des3_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *key)
{
unsigned long work[2];
_ARGCHK(pt != NULL);
_ARGCHK(ct != NULL);
_ARGCHK(key != NULL);
LOAD32H(work[0], pt+0);
LOAD32H(work[1], pt+4);
desfunc(work, key->des3.ek[0]);
desfunc(work, key->des3.ek[1]);
desfunc(work, key->des3.ek[2]);
STORE32H(work[0],ct+0);
STORE32H(work[1],ct+4);
}
void des3_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *key)
{
unsigned long work[2];
_ARGCHK(pt != NULL);
_ARGCHK(ct != NULL);
_ARGCHK(key != NULL);
LOAD32H(work[0], ct+0);
LOAD32H(work[1], ct+4);
desfunc(work, key->des3.dk[0]);
desfunc(work, key->des3.dk[1]);
desfunc(work, key->des3.dk[2]);
STORE32H(work[0],pt+0);
STORE32H(work[1],pt+4);
}
int des_test(void)
{
int errno;
static const struct des_test_case {
int num, mode; // mode 1 = encrypt
unsigned char key[8], txt[8], out[8];
} cases[] = {
{ 1, 1, { 0x10, 0x31, 0x6E, 0x02, 0x8C, 0x8F, 0x3B, 0x4A },
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
{ 0x82, 0xDC, 0xBA, 0xFB, 0xDE, 0xAB, 0x66, 0x02 } },
{ 2, 1, { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },
{ 0x95, 0xF8, 0xA5, 0xE5, 0xDD, 0x31, 0xD9, 0x00 },
{ 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
{ 3, 1, { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },
{ 0xDD, 0x7F, 0x12, 0x1C, 0xA5, 0x01, 0x56, 0x19 },
{ 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
{ 4, 1, { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },
{ 0x2E, 0x86, 0x53, 0x10, 0x4F, 0x38, 0x34, 0xEA },
{ 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
{ 5, 1, { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },
{ 0x4B, 0xD3, 0x88, 0xFF, 0x6C, 0xD8, 0x1D, 0x4F },
{ 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
{ 6, 1, { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },
{ 0x20, 0xB9, 0xE7, 0x67, 0xB2, 0xFB, 0x14, 0x56 },
{ 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
{ 7, 1, { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },
{ 0x55, 0x57, 0x93, 0x80, 0xD7, 0x71, 0x38, 0xEF },
{ 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
{ 8, 1, { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },
{ 0x6C, 0xC5, 0xDE, 0xFA, 0xAF, 0x04, 0x51, 0x2F },
{ 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
{ 9, 1, { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },
{ 0x0D, 0x9F, 0x27, 0x9B, 0xA5, 0xD8, 0x72, 0x60 },
{ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
{10, 1, { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },
{ 0xD9, 0x03, 0x1B, 0x02, 0x71, 0xBD, 0x5A, 0x0A },
{ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
{ 1, 0, { 0x10, 0x31, 0x6E, 0x02, 0x8C, 0x8F, 0x3B, 0x4A },
{ 0x82, 0xDC, 0xBA, 0xFB, 0xDE, 0xAB, 0x66, 0x02 },
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
{ 2, 0, { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },
{ 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
{ 0x95, 0xF8, 0xA5, 0xE5, 0xDD, 0x31, 0xD9, 0x00 } },
{ 3, 0, { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },
{ 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
{ 0xDD, 0x7F, 0x12, 0x1C, 0xA5, 0x01, 0x56, 0x19 } },
{ 4, 0, { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },
{ 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
{ 0x2E, 0x86, 0x53, 0x10, 0x4F, 0x38, 0x34, 0xEA } },
{ 5, 0, { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },
{ 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
{ 0x4B, 0xD3, 0x88, 0xFF, 0x6C, 0xD8, 0x1D, 0x4F } },
{ 6, 0, { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },
{ 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
{ 0x20, 0xB9, 0xE7, 0x67, 0xB2, 0xFB, 0x14, 0x56 } },
{ 7, 0, { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },
{ 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
{ 0x55, 0x57, 0x93, 0x80, 0xD7, 0x71, 0x38, 0xEF } },
{ 8, 0, { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },
{ 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
{ 0x6C, 0xC5, 0xDE, 0xFA, 0xAF, 0x04, 0x51, 0x2F } },
{ 9, 0, { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },
{ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
{ 0x0D, 0x9F, 0x27, 0x9B, 0xA5, 0xD8, 0x72, 0x60 } },
{10, 0, { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },
{ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
{ 0xD9, 0x03, 0x1B, 0x02, 0x71, 0xBD, 0x5A, 0x0A } }
/*** more test cases you could add if you are not convinced (the above test cases aren't really too good):
key plaintext ciphertext
0000000000000000 0000000000000000 8CA64DE9C1B123A7
FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF 7359B2163E4EDC58
3000000000000000 1000000000000001 958E6E627A05557B
1111111111111111 1111111111111111 F40379AB9E0EC533
0123456789ABCDEF 1111111111111111 17668DFC7292532D
1111111111111111 0123456789ABCDEF 8A5AE1F81AB8F2DD
0000000000000000 0000000000000000 8CA64DE9C1B123A7
FEDCBA9876543210 0123456789ABCDEF ED39D950FA74BCC4
7CA110454A1A6E57 01A1D6D039776742 690F5B0D9A26939B
0131D9619DC1376E 5CD54CA83DEF57DA 7A389D10354BD271
07A1133E4A0B2686 0248D43806F67172 868EBB51CAB4599A
3849674C2602319E 51454B582DDF440A 7178876E01F19B2A
04B915BA43FEB5B6 42FD443059577FA2 AF37FB421F8C4095
0113B970FD34F2CE 059B5E0851CF143A 86A560F10EC6D85B
0170F175468FB5E6 0756D8E0774761D2 0CD3DA020021DC09
43297FAD38E373FE 762514B829BF486A EA676B2CB7DB2B7A
07A7137045DA2A16 3BDD119049372802 DFD64A815CAF1A0F
04689104C2FD3B2F 26955F6835AF609A 5C513C9C4886C088
37D06BB516CB7546 164D5E404F275232 0A2AEEAE3FF4AB77
1F08260D1AC2465E 6B056E18759F5CCA EF1BF03E5DFA575A
584023641ABA6176 004BD6EF09176062 88BF0DB6D70DEE56
025816164629B007 480D39006EE762F2 A1F9915541020B56
49793EBC79B3258F 437540C8698F3CFA 6FBF1CAFCFFD0556
4FB05E1515AB73A7 072D43A077075292 2F22E49BAB7CA1AC
49E95D6D4CA229BF 02FE55778117F12A 5A6B612CC26CCE4A
018310DC409B26D6 1D9D5C5018F728C2 5F4C038ED12B2E41
1C587F1C13924FEF 305532286D6F295A 63FAC0D034D9F793
0101010101010101 0123456789ABCDEF 617B3A0CE8F07100
1F1F1F1F0E0E0E0E 0123456789ABCDEF DB958605F8C8C606
E0FEE0FEF1FEF1FE 0123456789ABCDEF EDBFD1C66C29CCC7
0000000000000000 FFFFFFFFFFFFFFFF 355550B2150E2451
FFFFFFFFFFFFFFFF 0000000000000000 CAAAAF4DEAF1DBAE
0123456789ABCDEF 0000000000000000 D5D44FF720683D0D
FEDCBA9876543210 FFFFFFFFFFFFFFFF 2A2BB008DF97C2F2
http://www.ecs.soton.ac.uk/~prw99r/ez438/vectors.txt
***/
};
int i, failed=0;
unsigned char out[8];
symmetric_key des;
for(i=0; i < (int)(sizeof(cases)/sizeof(cases[0])); i++)
{
if ((errno = des_setup(cases[i].key, 8, 0, &des)) != CRYPT_OK) {
return errno;
}
if (cases[i].mode) {
des_ecb_encrypt(cases[i].txt, out, &des);
} else {
des_ecb_decrypt(cases[i].txt, out, &des);
}
if (memcmp(cases[i].out, out, sizeof out) != 0) {
#if 0
int j;
printf("DES test #%d failed!\n", cases[i].num);
printf( "got: ");
for (j=0; j < (int)sizeof out; j++) {
printf("%02x ", out[j] & 0xff);
}
printf("\nwanted: ");
for(j=0; j < (int)sizeof out; j++) {
printf("%02x ", cases[i].out[j] & 0xff);
}
printf("\n");
#endif
failed++;
}
}
if(failed > 0) {
return CRYPT_FAIL_TESTVECTOR;
}
return CRYPT_OK;
}
int des3_test(void)
{
unsigned char key[24], pt[8], ct[8], tmp[8];
symmetric_key skey;
int x, errno;
if ((errno = des_test()) != CRYPT_OK) {
return errno;
}
for (x = 0; x < 8; x++) {
pt[x] = x;
}
for (x = 0; x < 24; x++) {
key[x] = x;
}
if ((errno = des3_setup(key, 24, 0, &skey)) != CRYPT_OK) {
return errno;
}
des3_ecb_encrypt(pt, ct, &skey);
des3_ecb_decrypt(ct, tmp, &skey);
if (memcmp(pt, tmp, 8)) {
return CRYPT_FAIL_TESTVECTOR;
}
return CRYPT_OK;
}
int des_keysize(int *desired_keysize)
{
_ARGCHK(desired_keysize != NULL);
if(*desired_keysize < 8) {
return CRYPT_INVALID_KEYSIZE;
}
*desired_keysize = 8;
return CRYPT_OK;
}
int des3_keysize(int *desired_keysize)
{
_ARGCHK(desired_keysize != NULL);
if(*desired_keysize < 24) {
return CRYPT_INVALID_KEYSIZE;
}
*desired_keysize = 24;
return CRYPT_OK;
}
#endif

489
dh.c Normal file
View File

@ -0,0 +1,489 @@
#include "mycrypt.h"
#ifdef MDH
static const struct {
int size;
char *name, *base, *prime;
} sets[] = {
#ifdef DH512
{
64,
"DH-512",
"3",
"1793360119486011337223707056216512835002732007217684422667328794587337075124"
"5439587792371960615073855669274087805055507977323024886880985062002853331424"
"203"
},
#endif
#ifdef DH768
{
96,
"DH-768",
"2",
"2893527720709661239493896562339544088620375736490408468011883030469939904368"
"0860923364582982212457078989335831907131881773994018526277492109945959747917"
"8279025394653904396221302707492255957231214118178743427870878320796645901947"
"9487"
},
#endif
#ifdef DH1024
{
128,
"DH-1024",
"2",
"3477431594398766260792527967974222231775354473882066076071816639030459075912"
"0194047822362172211817327089848758298713770865641434468581617942085516098634"
"0457973820182883508387588163122354089264395604796675278966117567294812714812"
"7968205965648764507160662831267200108590414847865290564578963676831229604111"
"36319"
},
#endif
#ifdef DH1280
{
160,
"DH-1280",
"2",
"2618298020488323341377089635550383393554460131909411928885489146533597039863"
"5379029297773089246854323581071445272213255646852180580463169755159411503866"
"4190218001872082125570169842848154404911652982668791288605239288293106162305"
"7236093554796242806887062958692596037823904832542385180840218330924392268465"
"0197244314233248991982159235832322194332167923655574170280697353556560854901"
"280047"
},
#endif
#ifdef DH1536
{
192,
"DH-1536",
"3",
"2992593690703251306835100868059076484222548092264611010748654597096560864537"
"1704684310938824733433085888971827086341295918925237859522548192211945291282"
"1170570153374563548621496076860061698150233114892317627457427359445435608693"
"5625000902194809114890745455404045166957722404567939575618007347432055137282"
"3291711752537781447636541738638119983678441628437171377508654097130147131310"
"9209393805685590941710151477648542896503595482724205166251069428524927527085"
"2602467"
},
#endif
#ifdef DH1792
{
224,
"DH-1792",
"2",
"3210090394251532205679207425273650879078185529033544241951292722086520015900"
"0402371844205168176419829949232601235193754977706171541009393172204470047690"
"6659627844880912479392592056697278305733615369406596661203184035142652643118"
"1379603333858737848321053048184938839622944591194935387992479717305577175500"
"2554620614907177847128950276247571809502831255425929468853285490357704941968"
"3407102520889651917659577334897408316217748346860775479727332331727022096550"
"7718799868459391361770854814013613619048768630587629568449528005570971478547"
"34960319"
},
#endif
#ifdef DH2048
{
256,
"DH-2048",
"2",
"4726642895635639316469736509812041897640060270607231273592407174543853221823"
"7979333351774907308168340693326687317443721193266215155735814510792148768576"
"4984911991227443513994894535335532038333186916782632419417062569961974604240"
"2901241901263467186228353234265630967717360250949841797609150915436003989316"
"5037637034737020327399910409885798185771003505320583967737293415979917317338"
"9858373857347474783642420203804168920566508414708692945275435973492502995396"
"8243060517332102902655554683247304860032703684578197028928889831788842751736"
"4945316709081173840186150794397479045034008257793436817683392375274635794835"
"245695887"
},
#endif
#ifdef DH2560
{
320,
"DH-2560",
"3",
"4364638085059577685748948703943497396233464406019459611612544400721432981520"
"4010567649104824811014627875285783993051576616744140702150122992472133564455"
"7342265864606569000117714935185566842453630868849121480179691838399545644365"
"5711067577313173717585579907818806913366955847993133136872874688941488237617"
"8558298254958618375680644901754262226787427510387748147553499120184991222267"
"0102069951687572917937634467778042874315463238062009202992087620963771759666"
"4482665328580794026699200252242206134194410697184828373996126449788399252071"
"0987084027819404215874884544513172913711709852902888677006373648742061314404"
"5836803985635654192482395882603511950547826439092832800532152534003936926017"
"6124466061356551464456206233957889787267447285030586700468858762515271223502"
"75750995227"
},
#endif
#ifdef DH3072
{
384,
"DH-3072",
"2",
"1142416747335183639807830604262436227795642944052113706188970261176634876069"
"2206243140413411077394583180726863277012016602279290144126785129569474909173"
"5847898223419867427192303319460727303195559844849117167970588759054009995043"
"0587724584911968750902323279027363746682105257685923245298206183100977078603"
"1785669030271542286603956118755585683996118896215213488875253101894663403069"
"6777459483058938495054342017637452328957807119724320113448575216910178963168"
"6140320644942133224365885545343578400651720289418164056243357539082138421096"
"0117518650374602256601091379644034244332285065935413233557998331562749140202"
"9658442193362989700115138825649355387042894469683222814519074873620465114612"
"2132979989735099337056069750580968643878203623537213701573130477907243026098"
"6460269894522159103008260495503005267165927542949439526272736586626709581721"
"0321895327263896436255906801057848442461527026701693042037830722750891947548"
"89511973916207"
},
#endif
#ifdef DH4096
{
512,
"DH-4096",
"3",
"1214855636816562637502584060163403830270705000634713483015101384881871978446"
"8012247985361554068958233050354675916325310675478909486951171720769542207270"
"7568804875102242119871203284889005635784597424656074834791863005085393369779"
"2254955890439720297560693579400297062396904306270145886830719309296352765295"
"7121830407731464190228751653827780070401099576097395898755908857011261979060"
"6362013395489321661267883850754077713843779770560245371955901763398648664952"
"3611975865005712371194067612263330335590526176087004421363598470302731349138"
"7732059014477046821815179040647356365184624522427916765417252923789255682968"
"5801015185232631677751193503753101741391050692192245066693320227848902452126"
"3798482237150056835746454842662048692127173834433089016107854491097456725016"
"3277096631997382384421648431471327891537255132571679155551620949708535844479"
"9312548860769600816980737473671129700747381225627224548940589847029717873802"
"9484459690836250560495461579533254473316340608217876781986188705928270735695"
"7528308255279638383554197625162460286802809880204019145518254873499903069763"
"0409310938445143881325121105159739212749146489879740678917545306796007200859"
"0614886532333015881171367104445044718144312416815712216611576221546455968770"
"801413440778423979"
},
#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, res, primality;
if (mp_init_multi(&p, &g, &tmp, NULL) != MP_OKAY) { goto error; }
for (x = 0; sets[x].size; x++) {
#if 0
printf("dh_test():testing size %d-bits\n", sets[x].size * 8);
#endif
/* see if g^((p-1)/2) == 1 mod p. */
if (mp_read_radix(&g, sets[x].base, 10) != MP_OKAY) { goto error; }
if (mp_read_radix(&p, sets[x].prime, 10) != MP_OKAY) { goto error; }
/* ensure p is prime */
if ((res = is_prime(&p, &primality)) != CRYPT_OK) { goto done; }
if (primality == 0) {
res = CRYPT_FAIL_TESTVECTOR;
goto done;
}
if (mp_sub_d(&p, 1, &tmp) != MP_OKAY) { goto error; }
if (mp_div_2(&tmp, &tmp) != MP_OKAY) { goto error; }
/* ensure (p-1)/2 is prime */
if ((res = is_prime(&tmp, &primality)) != CRYPT_OK) { goto done; }
if (primality == 0) {
res = CRYPT_FAIL_TESTVECTOR;
goto done;
}
/* now see if g^((p-1)/2) mod p is in fact 1 */
if (mp_exptmod(&g, &tmp, &p, &tmp) != MP_OKAY) { goto error; }
if (mp_cmp_d(&tmp, 1)) {
res = CRYPT_FAIL_TESTVECTOR;
goto done;
}
}
res = CRYPT_OK;
goto done;
error:
res = CRYPT_MEM;
done:
mp_clear_multi(&tmp, &g, &p, NULL);
return res;
}
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; 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))
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[768];
unsigned long x;
mp_int p, g;
int res, errno;
_ARGCHK(key != NULL);
/* good prng? */
if ((errno = prng_is_valid(wprng)) != CRYPT_OK) {
return errno;
}
/* find key size */
for (x = 0; (keysize > sets[x].size) && (sets[x].size); 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 */
buf[0] = 0;
if (prng_descriptor[wprng].read(buf+1, keysize, prng) != (unsigned long)keysize) {
return CRYPT_ERROR_READPRNG;
}
/* init parameters */
if (mp_init_multi(&g, &p, &key->x, &key->y, NULL) != MP_OKAY) {
return CRYPT_MEM;
}
if (mp_read_radix(&g, sets[x].base, 10) != MP_OKAY) { goto error2; }
if (mp_read_radix(&p, sets[x].prime, 10) != MP_OKAY) { goto error2; }
/* load the x value */
mp_read_raw(&key->x, buf, keysize+1);
if (mp_exptmod(&g, &key->x, &p, &key->y) != MP_OKAY) { goto error2; }
key->type = PK_PRIVATE;
/* free up ram */
res = CRYPT_OK;
goto done2;
error2:
res = CRYPT_MEM;
mp_clear_multi(&key->x, &key->y, NULL);
done2:
mp_clear_multi(&p, &g, NULL);
zeromem(buf, sizeof(buf));
return res;
}
void dh_free(dh_key *key)
{
_ARGCHK(key != NULL);
mp_clear_multi(&key->x, &key->y, NULL);
}
#define OUTPUT_BIGNUM(num, buf2, y, z) \
{ \
z = mp_raw_size(num); \
STORE32L(z, buf2+y); \
y += 4; \
mp_toraw(num, buf2+y); \
y += z; \
}
#define INPUT_BIGNUM(num, in, x, y) \
{ \
/* load value */ \
LOAD32L(x, in+y); \
y += 4; \
\
/* sanity check... */ \
if (x > 1024) { \
errno = CRYPT_ERROR; \
goto error; \
} \
\
/* load it */ \
if (mp_read_raw(num, (unsigned char *)in+y, x) != MP_OKAY) {\
return CRYPT_MEM; \
goto error; \
} \
y += x; \
}
int dh_export(unsigned char *out, unsigned long *outlen, int type, dh_key *key)
{
unsigned char buf2[1536];
unsigned long y, z;
_ARGCHK(out != NULL);
_ARGCHK(outlen != NULL);
_ARGCHK(key != NULL);
if (type == PK_PRIVATE && key->type != PK_PRIVATE) {
return CRYPT_PK_NOT_PRIVATE;
}
/* header */
y = PACKET_SIZE;
/* header */
buf2[y++] = type;
buf2[y++] = key->idx;
/* export y */
OUTPUT_BIGNUM(&key->y, buf2, y, z);
if (type == PK_PRIVATE) {
/* export x */
OUTPUT_BIGNUM(&key->x, buf2, y, z);
}
/* check for overflow */
if (*outlen < y) {
#ifdef CLEAN_STACK
zeromem(buf2, sizeof(buf2));
#endif
return CRYPT_BUFFER_OVERFLOW;
}
/* store header */
packet_store_header(buf2, PACKET_SECT_DH, PACKET_SUB_KEY, y);
/* output it */
*outlen = y;
memcpy(out, buf2, y);
/* clear mem */
zeromem(buf2, sizeof(buf2));
return CRYPT_OK;
}
int dh_import(const unsigned char *in, dh_key *key)
{
long x, y;
int errno;
_ARGCHK(in != NULL);
_ARGCHK(key != NULL);
/* check type byte */
if ((errno = packet_valid_header((unsigned char *)in, PACKET_SECT_DH, PACKET_SUB_KEY)) != CRYPT_OK) {
return errno;
}
/* init */
if (mp_init_multi(&key->x, &key->y, NULL) != MP_OKAY) {
return CRYPT_MEM;
}
y = PACKET_SIZE;
key->type = in[y++];
key->idx = in[y++];
/* type check both values */
if ((key->type != PK_PUBLIC) && (key->type != PK_PRIVATE)) {
errno = CRYPT_PK_TYPE_MISMATCH;
goto error;
}
/* is the key idx valid? */
if (!is_valid_idx(key->idx)) {
errno = CRYPT_PK_TYPE_MISMATCH;
goto error;
}
/* load public value g^x mod p*/
INPUT_BIGNUM(&key->y, in, x, y);
if (key->type == PK_PRIVATE) {
INPUT_BIGNUM(&key->x, in, x, y);
}
return CRYPT_OK;
error:
mp_clear_multi(&key->y, &key->x, NULL);
return errno;
}
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 res;
_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 (mp_init_multi(&tmp, &p, NULL) != MP_OKAY) {
return CRYPT_MEM;
}
if (mp_read_radix(&p, sets[private_key->idx].prime, 10) != MP_OKAY) { goto error; }
if (mp_exptmod(&public_key->y, &private_key->x, &p, &tmp) != MP_OKAY) { goto error; }
/* enough space for output? */
x = mp_raw_size(&tmp);
if (*outlen < x) {
res = CRYPT_BUFFER_OVERFLOW;
goto done;
}
mp_toraw(&tmp, out);
*outlen = x;
res = CRYPT_OK;
goto done;
error:
res = CRYPT_MEM;
done:
mp_clear_multi(&p, &tmp, NULL);
return res;
}
#include "dh_sys.c"
#endif

774
dh_sys.c Normal file
View File

@ -0,0 +1,774 @@
#ifdef PK_PACKET
int dh_encrypt(const unsigned char *in, unsigned long len,
unsigned char *out, unsigned long *outlen,
prng_state *prng, int wprng, int cipher, int hash,
dh_key *key)
{
unsigned char pub_expt[1536], dh_shared[1536], IV[MAXBLOCKSIZE], skey[MAXBLOCKSIZE];
dh_key pubkey;
unsigned long x, y, z, hashsize, blocksize, pubkeysize;
int keysize, errno;
symmetric_CTR ctr;
_ARGCHK(in != NULL);
_ARGCHK(out != NULL);
_ARGCHK(outlen != NULL);
_ARGCHK(key != NULL);
/* check that wprng/cipher/hash are not invalid */
if ((errno = prng_is_valid(wprng)) != CRYPT_OK) {
return errno;
}
if ((errno = hash_is_valid(hash)) != CRYPT_OK) {
return errno;
}
if ((errno = cipher_is_valid(cipher)) != CRYPT_OK) {
return errno;
}
/* make a random key and export the public copy */
if ((errno = dh_make_key(prng, wprng, dh_get_size(key), &pubkey)) != CRYPT_OK) {
return errno;
}
pubkeysize = sizeof(pub_expt);
if ((errno = dh_export(pub_expt, &pubkeysize, PK_PUBLIC, &pubkey)) != CRYPT_OK) {
dh_free(&pubkey);
return errno;
}
/* now check if the out buffer is big enough */
if (*outlen < (10 + PACKET_SIZE + pubkeysize + cipher_descriptor[cipher].block_length + len)) {
dh_free(&pubkey);
return CRYPT_BUFFER_OVERFLOW;
}
/* make random key */
blocksize = cipher_descriptor[cipher].block_length;
hashsize = hash_descriptor[hash].hashsize;
keysize = hashsize;
if ((errno = cipher_descriptor[cipher].keysize(&keysize)) != CRYPT_OK) {
dh_free(&pubkey);
return errno;
}
x = sizeof(dh_shared);
if ((errno = dh_shared_secret(&pubkey, key, dh_shared, &x)) != CRYPT_OK) {
dh_free(&pubkey);
return errno;
}
dh_free(&pubkey);
z = sizeof(skey);
if ((errno = hash_memory(hash, dh_shared, x, skey, &z)) != CRYPT_OK) {
return errno;
}
/* make up IV */
if (prng_descriptor[wprng].read(IV, cipher_descriptor[cipher].block_length, prng) !=
cipher_descriptor[cipher].block_length) {
return CRYPT_ERROR_READPRNG;
}
/* setup CTR mode */
if ((errno = ctr_start(cipher, IV, skey, keysize, 0, &ctr)) != CRYPT_OK) {
return errno;
}
/* output header */
y = PACKET_SIZE;
/* size of cipher name and the name itself */
out[y++] = cipher_descriptor[cipher].ID;
/* 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];
}
/* cipher IV */
for (x = 0; x < blocksize; x++, y++) {
out[y] = IV[x];
}
/* length of ciphertext */
STORE32L(len, out+y);
y += 4;
/* encrypt the message */
if ((errno = ctr_encrypt(in, out+y, len, &ctr)) != CRYPT_OK) {
return errno;
}
y += len;
/* store header */
packet_store_header(out, PACKET_SECT_DH, PACKET_SUB_ENCRYPTED, y);
#ifdef CLEAN_STACK
/* clean up */
zeromem(pub_expt, sizeof(pub_expt));
zeromem(dh_shared, sizeof(dh_shared));
zeromem(skey, sizeof(skey));
zeromem(IV, sizeof(IV));
zeromem(&ctr, sizeof(ctr));
#endif
*outlen = y;
return CRYPT_OK;
}
int dh_decrypt(const unsigned char *in, unsigned long len,
unsigned char *out, unsigned long *outlen,
dh_key *key)
{
unsigned char shared_secret[1536], skey[MAXBLOCKSIZE];
unsigned long x, y, z, res, hashsize, blocksize;
int hash, cipher, keysize, errno;
dh_key pubkey;
symmetric_CTR ctr;
_ARGCHK(in != NULL);
_ARGCHK(out != NULL);
_ARGCHK(outlen != NULL);
_ARGCHK(key != NULL);
/* right key type? */
if (key->type != PK_PRIVATE) {
return CRYPT_PK_NOT_PRIVATE;
}
/* is header correct? */
if ((errno = packet_valid_header((unsigned char *)in, PACKET_SECT_DH, PACKET_SUB_ENCRYPTED)) != CRYPT_OK) {
return errno;
}
/* now lets get the cipher name */
y = PACKET_SIZE;
cipher = find_cipher_id(in[y++]);
if (cipher == -1) {
return CRYPT_INVALID_CIPHER;
}
/* now lets get the hash name */
hash = find_hash_id(in[y++]);
if (hash == -1) {
return CRYPT_INVALID_HASH;
}
/* common values */
blocksize = cipher_descriptor[cipher].block_length;
hashsize = hash_descriptor[hash].hashsize;
keysize = hashsize;
if ((errno = cipher_descriptor[cipher].keysize(&keysize)) != CRYPT_OK) {
return errno;
}
/* get public key */
LOAD32L(x, in+y);
y += 4;
if ((errno = dh_import(in+y, &pubkey)) != CRYPT_OK) {
return errno;
}
y += x;
/* make shared key */
x = sizeof(shared_secret);
if ((errno = dh_shared_secret(key, &pubkey, shared_secret, &x)) != CRYPT_OK) {
dh_free(&pubkey);
return errno;
}
dh_free(&pubkey);
z = sizeof(skey);
if ((errno = hash_memory(hash, shared_secret, x, skey, &z)) != CRYPT_OK) {
return errno;
}
/* setup CTR mode */
if ((errno = ctr_start(cipher, in+y, skey, keysize, 0, &ctr)) != CRYPT_OK) {
res = errno;
goto done;
}
/* skip over the IV */
y += blocksize;
/* get length */
LOAD32L(len,in+y);
y += 4;
/* buffer overflow? */
if (len > *outlen) {
res = CRYPT_BUFFER_OVERFLOW;
goto done;
}
/* decrypt message */
if ((errno = ctr_decrypt(in+y, out, len, &ctr)) != CRYPT_OK) {
res = errno;
goto done;
}
*outlen = len;
res = CRYPT_OK;
done:
#ifdef CLEAN_STACK
zeromem(shared_secret, sizeof(shared_secret));
zeromem(skey, sizeof(skey));
zeromem(&ctr, sizeof(ctr));
#endif
return res;
}
int dh_sign(const unsigned char *in, unsigned long inlen,
unsigned char *out, unsigned long *outlen,
int hash, prng_state *prng, int wprng,
dh_key *key)
{
mp_int a, b, k, m, g, p, p1, tmp;
unsigned char buf[1536], md[MAXBLOCKSIZE];
unsigned long x, y, z;
int res, errno;
_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 ((errno = prng_is_valid(wprng)) != CRYPT_OK) {
return errno;
}
if ((errno = hash_is_valid(hash)) != CRYPT_OK) {
return errno;
}
/* hash the message */
z = sizeof(md) - 1;
md[0] = 0;
if ((errno = hash_memory(hash, in, inlen, md+1, &z)) != CRYPT_OK) {
return errno;
}
/* make up a random value k,
* since the order of the group is prime
* we need not check if gcd(k, r) is 1
*/
buf[0] = 0;
if (prng_descriptor[wprng].read(buf+1, sets[key->idx].size-1, prng) != (unsigned long)(sets[key->idx].size-1)) {
return CRYPT_ERROR_READPRNG;
}
/* init bignums */
if (mp_init_multi(&a, &b, &k, &m, &p, &g, &p1, &tmp, NULL) != MP_OKAY) {
return CRYPT_MEM;
}
/* load k and m */
if (mp_read_raw(&m, md, 1+hash_descriptor[hash].hashsize) != MP_OKAY) { goto error; }
if (mp_read_raw(&k, buf, sets[key->idx].size) != MP_OKAY) { goto error; }
/* load g, p and p1 */
if (mp_read_radix(&g, sets[key->idx].base, 10) != MP_OKAY) { goto error; }
if (mp_read_radix(&p, sets[key->idx].prime, 10) != MP_OKAY) { goto error; }
if (mp_sub_d(&p, 1, &p1) != MP_OKAY) { goto error; } /* p1 = p-1 */
if (mp_div_2(&p1, &p1) != MP_OKAY) { goto error; } /* p1 = (p-1)/2 */
/* now get a = g^k mod p */
if (mp_exptmod(&g, &k, &p, &a) != MP_OKAY) { goto error; } /* a = g^k mod p */
/* now find M = xa + kb mod p1 or just b = (M - xa)/k mod p1 */
if (mp_invmod(&k, &p1, &k) != MP_OKAY) { goto error; } /* k = 1/k mod p1 */
if (mp_mulmod(&a, &key->x, &p1, &tmp) != MP_OKAY) { goto error; } /* tmp = xa */
if (mp_submod(&m, &tmp, &p1, &tmp) != MP_OKAY) { goto error; } /* tmp = M - xa */
if (mp_mulmod(&k, &tmp, &p1, &b) != MP_OKAY) { goto error; } /* b = (M - xa)/k */
/* store header */
y = PACKET_SIZE;
/* store length and name of hash */
buf[y++] = hash_descriptor[hash].ID; /* store hash ID */
/* now store them both (a,b) */
x = mp_raw_size(&a); /* get raw size of a */
STORE32L(x, buf+y); y += 4; /* store size of a */
mp_toraw(&a, buf+y); y += x; /* store a itself */
x = mp_raw_size(&b); /* get raw size of b */
STORE32L(x, buf+y); y += 4; /* store size of b */
mp_toraw(&b, buf+y); y += x; /* store b itself */
/* check if size too big */
if (*outlen < y) { goto error; }
/* store header */
packet_store_header(buf, PACKET_SECT_DH, PACKET_SUB_SIGNED, y);
/* store it */
memcpy(out, buf, y);
*outlen = y;
#ifdef CLEAN_STACK
zeromem(md, sizeof(md));
zeromem(buf, sizeof(buf));
#endif
res = CRYPT_OK;
goto done;
error:
res = CRYPT_MEM;
done:
mp_clear_multi(&tmp, &p1, &g, &p, &m, &k, &b, &a, NULL);
return res;
}
int dh_verify(const unsigned char *sig, const unsigned char *msg,
unsigned long inlen, int *stat,
dh_key *key)
{
mp_int a, b, p, g, m, tmp;
unsigned char md[MAXBLOCKSIZE];
unsigned long x, y, z;
int hash, res, errno;
_ARGCHK(sig != NULL);
_ARGCHK(msg != NULL);
_ARGCHK(stat != NULL);
_ARGCHK(key != NULL);
/* default to invalid */
*stat = 0;
/* header ok? */
if ((errno = packet_valid_header((unsigned char *)sig, PACKET_SECT_DH, PACKET_SUB_SIGNED)) != CRYPT_OK) {
return errno;
}
/* get hash out of packet */
y = PACKET_SIZE;
hash = find_hash_id(sig[y++]);
if (hash == -1) {
return CRYPT_INVALID_HASH;
}
/* hash the message */
md[0] = 0;
z = sizeof(md) - 1;
if ((errno = hash_memory(hash, msg, inlen, md+1, &z)) != CRYPT_OK) {
return errno;
}
/* init all bignums */
if (mp_init_multi(&a, &p, &b, &g, &m, &tmp, NULL) != MP_OKAY) {
return CRYPT_MEM;
}
/* load a and b */
LOAD32L(x, sig+y);
y += 4;
if (mp_read_raw(&a, (unsigned char *)sig+y, x) != MP_OKAY) { goto error; }
y += x;
LOAD32L(x, sig+y);
y += 4;
if (mp_read_raw(&b, (unsigned char *)sig+y, x) != MP_OKAY) { goto error; }
y += x;
/* load p and g */
if (mp_read_radix(&p, sets[key->idx].prime, 10) != MP_OKAY) { goto error; }
if (mp_read_radix(&g, sets[key->idx].base, 10) != MP_OKAY) { goto error; }
/* load m */
if (mp_read_raw(&m, md, hash_descriptor[hash].hashsize + 1) != MP_OKAY) { goto error; }
/* find g^m mod p */
if (mp_exptmod(&g, &m, &p, &m) != MP_OKAY) { goto error; } /* m = g^m mod p */
/* find y^a * a^b */
if (mp_exptmod(&key->y, &a, &p, &tmp) != MP_OKAY) { goto error; } /* tmp = y^a mod p */
if (mp_exptmod(&a, &b, &p, &a) != MP_OKAY) { goto error; } /* a = a^b mod p */
if (mp_mulmod(&a, &tmp, &p, &a) != MP_OKAY) { goto error; } /* a = y^a * a^b mod p */
/* y^a * a^b == g^m ??? */
if (mp_cmp(&a, &m) == 0) {
*stat = 1;
}
/* clean up */
res = CRYPT_OK;
goto done;
error:
res = CRYPT_MEM;
done:
mp_clear_multi(&tmp, &m, &g, &p, &b, &a, NULL);
#ifdef CLEAN_STACK
zeromem(md, sizeof(md));
#endif
return res;
}
#endif
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[1536], dh_shared[1536], skey[MAXBLOCKSIZE];
dh_key pubkey;
unsigned long x, y, z, hashsize, pubkeysize;
int errno;
_ARGCHK(inkey != NULL);
_ARGCHK(out != NULL);
_ARGCHK(len != NULL);
_ARGCHK(key != NULL);
/* check that wprng/hash are not invalid */
if ((errno = prng_is_valid(wprng)) != CRYPT_OK) {
return errno;
}
if ((errno = hash_is_valid(hash)) != CRYPT_OK) {
return errno;
}
if (keylen > hash_descriptor[hash].hashsize) {
return CRYPT_INVALID_ARG;
}
/* make a random key and export the public copy */
if ((errno = dh_make_key(prng, wprng, dh_get_size(key), &pubkey)) != CRYPT_OK) {
return errno;
}
pubkeysize = sizeof(pub_expt);
if ((errno = dh_export(pub_expt, &pubkeysize, PK_PUBLIC, &pubkey)) != CRYPT_OK) {
dh_free(&pubkey);
return errno;
}
/* now check if the out buffer is big enough */
if (*len < (9 + PACKET_SIZE + pubkeysize + keylen)) {
dh_free(&pubkey);
return CRYPT_BUFFER_OVERFLOW;
}
/* make random key */
hashsize = hash_descriptor[hash].hashsize;
x = sizeof(dh_shared);
if ((errno = dh_shared_secret(&pubkey, key, dh_shared, &x)) != CRYPT_OK) {
dh_free(&pubkey);
return errno;
}
dh_free(&pubkey);
z = sizeof(skey);
if ((errno = hash_memory(hash, dh_shared, x, skey, &z)) != CRYPT_OK) {
return errno;
}
/* 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];
}
/* store header */
packet_store_header(out, PACKET_SECT_DH, PACKET_SUB_ENC_KEY, y);
#ifdef CLEAN_STACK
/* clean up */
zeromem(pub_expt, sizeof(pub_expt));
zeromem(dh_shared, sizeof(dh_shared));
zeromem(skey, sizeof(skey));
#endif
*len = y;
return CRYPT_OK;
}
int dh_decrypt_key(const unsigned char *in, unsigned char *outkey,
unsigned long *keylen, dh_key *key)
{
unsigned char shared_secret[1536], skey[MAXBLOCKSIZE];
unsigned long x, y, z, res, hashsize, keysize;
int hash, errno;
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;
}
/* is header correct? */
if ((errno = packet_valid_header((unsigned char *)in, PACKET_SECT_DH, PACKET_SUB_ENC_KEY)) != CRYPT_OK) {
return errno;
}
/* 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);
y += 4;
if ((errno = dh_import(in+y, &pubkey)) != CRYPT_OK) {
return errno;
}
y += x;
/* make shared key */
x = sizeof(shared_secret);
if ((errno = dh_shared_secret(key, &pubkey, shared_secret, &x)) != CRYPT_OK) {
dh_free(&pubkey);
return errno;
}
dh_free(&pubkey);
z = sizeof(skey);
if ((errno = hash_memory(hash, shared_secret, x, skey, &z)) != CRYPT_OK) {
return errno;
}
/* load in the encrypted key */
LOAD32L(keysize, in+y);
if (keysize > *keylen) {
res = CRYPT_BUFFER_OVERFLOW;
goto done;
}
y += 4;
*keylen = keysize;
for (x = 0; x < keysize; x++, y++) {
outkey[x] = skey[x] ^ in[y];
}
res = CRYPT_OK;
done:
#ifdef CLEAN_STACK
zeromem(shared_secret, sizeof(shared_secret));
zeromem(skey, sizeof(skey));
#endif
return res;
}
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[1536], md[MAXBLOCKSIZE];
unsigned long x, y;
int res, errno;
_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 ((errno = prng_is_valid(wprng)) != CRYPT_OK) {
return errno;
}
/* hash the message */
md[0] = 0;
memcpy(md+1, in, MIN(sizeof(md) - 1, inlen));
/* make up a random value k,
* since the order of the group is prime
* we need not check if gcd(k, r) is 1
*/
buf[0] = 0;
if (prng_descriptor[wprng].read(buf+1, sets[key->idx].size-1, prng) !=
(unsigned long)(sets[key->idx].size-1)) {
return CRYPT_ERROR_READPRNG;
}
/* init bignums */
if (mp_init_multi(&a, &b, &k, &m, &p, &g, &p1, &tmp, NULL) != MP_OKAY) {
return CRYPT_MEM;
}
/* load k and m */
if (mp_read_raw(&m, md, 1+MIN(sizeof(md) - 1, inlen)) != MP_OKAY) { goto error; }
if (mp_read_raw(&k, buf, sets[key->idx].size) != MP_OKAY) { goto error; }
/* load g, p and p1 */
if (mp_read_radix(&g, sets[key->idx].base, 10) != MP_OKAY) { goto error; }
if (mp_read_radix(&p, sets[key->idx].prime, 10) != MP_OKAY) { goto error; }
if (mp_sub_d(&p, 1, &p1) != MP_OKAY) { goto error; }
if (mp_div_2(&p1, &p1) != MP_OKAY) { goto error; } /* p1 = (p-1)/2 */
/* now get a = g^k mod p */
if (mp_exptmod(&g, &k, &p, &a) != MP_OKAY) { goto error; }
/* now find M = xa + kb mod p1 or just b = (M - xa)/k mod p1 */
if (mp_invmod(&k, &p1, &k) != MP_OKAY) { goto error; } /* k = 1/k mod p1 */
if (mp_mulmod(&a, &key->x, &p1, &tmp) != MP_OKAY) { goto error; } /* tmp = xa */
if (mp_submod(&m, &tmp, &p1, &tmp) != MP_OKAY) { goto error; } /* tmp = M - xa */
if (mp_mulmod(&k, &tmp, &p1, &b) != MP_OKAY) { goto error; } /* b = (M - xa)/k */
/* store header */
y = PACKET_SIZE;
/* now store them both (a,b) */
x = mp_raw_size(&a);
STORE32L(x, buf+y); y += 4;
mp_toraw(&a, buf+y); y += x;
x = mp_raw_size(&b);
STORE32L(x, buf+y); y += 4;
mp_toraw(&b, buf+y); y += x;
/* check if size too big */
if (*outlen < y) {
res = CRYPT_BUFFER_OVERFLOW;
goto done;
}
/* store header */
packet_store_header(buf, PACKET_SECT_DH, PACKET_SUB_SIGNED, y);
/* store it */
memcpy(out, buf, y);
*outlen = y;
#ifdef CLEAN_STACK
zeromem(md, sizeof(md));
zeromem(buf, sizeof(buf));
#endif
res = CRYPT_OK;
goto done;
error:
res = CRYPT_MEM;
done:
mp_clear_multi(&tmp, &p1, &g, &p, &m, &k, &b, &a, NULL);
return res;
}
int dh_verify_hash(const unsigned char *sig, const unsigned char *hash,
unsigned long inlen, int *stat,
dh_key *key)
{
mp_int a, b, p, g, m, tmp;
unsigned char md[MAXBLOCKSIZE];
unsigned long x, y;
int res, errno;
_ARGCHK(sig != NULL);
_ARGCHK(hash != NULL);
_ARGCHK(stat != NULL);
_ARGCHK(key != NULL);
/* default to invalid */
*stat = 0;
/* header ok? */
if ((errno = packet_valid_header((unsigned char *)sig, PACKET_SECT_DH, PACKET_SUB_SIGNED)) != CRYPT_OK) {
return errno;
}
/* get hash out of packet */
y = PACKET_SIZE;
/* hash the message */
md[0] = 0;
memcpy(md+1, hash, MIN(sizeof(md) - 1, inlen));
/* init all bignums */
if (mp_init_multi(&a, &p, &b, &g, &m, &tmp, NULL) != MP_OKAY) {
return CRYPT_MEM;
}
/* load a and b */
LOAD32L(x, sig+y);
y += 4;
if (mp_read_raw(&a, (unsigned char *)sig+y, x) != MP_OKAY) { goto error; }
y += x;
LOAD32L(x, sig+y);
y += 4;
if (mp_read_raw(&b, (unsigned char *)sig+y, x) != MP_OKAY) { goto error; }
y += x;
/* load p and g */
if (mp_read_radix(&p, sets[key->idx].prime, 10) != MP_OKAY) { goto error; }
if (mp_read_radix(&g, sets[key->idx].base, 10) != MP_OKAY) { goto error; }
/* load m */
if (mp_read_raw(&m, md, 1+MIN(sizeof(md)-1, inlen)) != MP_OKAY) { goto error; }
/* find g^m mod p */
if (mp_exptmod(&g, &m, &p, &m) != MP_OKAY) { goto error; } /* m = g^m mod p */
/* find y^a * a^b */
if (mp_exptmod(&key->y, &a, &p, &tmp) != MP_OKAY) { goto error; } /* tmp = y^a mod p */
if (mp_exptmod(&a, &b, &p, &a) != MP_OKAY) { goto error; } /* a = a^b mod p */
if (mp_mulmod(&a, &tmp, &p, &a) != MP_OKAY) { goto error; } /* a = y^a * a^b mod p */
/* y^a * a^b == g^m ??? */
if (mp_cmp(&a, &m) == 0) {
*stat = 1;
}
/* clean up */
res = CRYPT_OK;
goto done;
error:
res = CRYPT_MEM;
done:
mp_clear_multi(&tmp, &m, &g, &p, &b, &a, NULL);
#ifdef CLEAN_STACK
zeromem(md, sizeof(md));
#endif
return res;
}

49
ecb.c Normal file
View File

@ -0,0 +1,49 @@
#include "mycrypt.h"
#ifdef ECB
int ecb_start(int cipher, const unsigned char *key, int keylen, int num_rounds, symmetric_ECB *ecb)
{
int errno;
_ARGCHK(key != NULL);
_ARGCHK(ecb != NULL);
if ((errno = cipher_is_valid(cipher)) != CRYPT_OK) {
return errno;
}
ecb->cipher = cipher;
ecb->blocklen = cipher_descriptor[cipher].block_length;
return cipher_descriptor[cipher].setup(key, keylen, num_rounds, &ecb->key);
}
int ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_ECB *ecb)
{
int errno;
_ARGCHK(pt != NULL);
_ARGCHK(ct != NULL);
_ARGCHK(ecb != NULL);
if ((errno = cipher_is_valid(ecb->cipher)) != CRYPT_OK) {
return errno;
}
cipher_descriptor[ecb->cipher].ecb_encrypt(pt, ct, &ecb->key);
return CRYPT_OK;
}
int ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_ECB *ecb)
{
int errno;
_ARGCHK(pt != NULL);
_ARGCHK(ct != NULL);
_ARGCHK(ecb != NULL);
if ((errno = cipher_is_valid(ecb->cipher)) != CRYPT_OK) {
return errno;
}
cipher_descriptor[ecb->cipher].ecb_decrypt(ct, pt, &ecb->key);
return CRYPT_OK;
}
#endif

827
ecc.c Normal file
View File

@ -0,0 +1,827 @@
/* 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
static const struct {
int size;
char *name, *prime, *B, *order, *Gx, *Gy;
} sets[] = {
#ifdef ECC160
{
20,
"ECC-160",
/* prime */
"1461501637330902918203684832716283019655932542983",
/* B */
"1C9E7C2E5891CBE097BD46",
/* order */
"1461501637330902918203686297565868358251373258181",
/* Gx */
"2DCF462904B478D868A7FF3F2BF1FCD9",
/* Gy */
"DFFAF2EE3848FA75FB967CEC7B9A399E085ACED8",
},
#endif
#ifdef ECC192
{
24,
"ECC-192",
/* prime */
"6277101735386680763835789423207666416083908700390324961279",
/* B */
"64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1",
/* order */
"6277101735386680763835789423176059013767194773182842284081",
/* Gx */
"188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012",
/* Gy */
"07192b95ffc8da78631011ed6b24cdd573f977a11e794811"
},
#endif
#ifdef ECC224
{
28,
"ECC-224",
/* prime */
"26959946667150639794667015087019630673637144422540572481103610249951",
/* B */
"2051BA041508CED34B3",
/* order */
"26959946667150639794667015087019637467111563745054605861463538557247",
/* Gx */
"2DCF462904B478D868A7FF3F2BF1FCD9",
/* Gy */
"CF337F320BC44A15C3EDB8C4258BB958E57A0CAFA73EB46E9C4BA9AE",
},
#endif
#ifdef ECC256
{
32,
"ECC-256",
/* Prime */
"115792089210356248762697446949407573530086143415290314195533631308867097853951",
/* B */
"5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b",
/* Order */
"115792089210356248762697446949407573529996955224135760342422259061068512044369",
/* Gx */
"6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296",
/* Gy */
"4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5"
},
#endif
#ifdef ECC384
{
48,
"ECC-384",
/* prime */
"394020061963944792122790401001436138050797392704654466679482934042457217714968"
"70329047266088258938001861606973112319",
/* B */
"b3312fa7e23ee7e4988e056be3f82d19181d9c6efe8141120314088f5013875ac656398d8a2ed1"
"9d2a85c8edd3ec2aef",
/* Order */
"394020061963944792122790401001436138050797392704654466679469052796276593991132"
"63569398956308152294913554433653942643",
/* Gx and Gy */
"aa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a385502f25dbf5529"
"6c3a545e3872760ab7",
"3617de4a96262c6f5d9e98bf9292dc29f8f41dbd289a147ce9da3113b5f0b8c00a60b1ce1d7e81"
"9d7a431d7c90ea0e5f"
},
#endif
#ifdef ECC521
{
65,
"ECC-521",
/* prime */
"686479766013060971498190079908139321726943530014330540939446345918554318339765"
"6052122559640661454554977296311391480858037121987999716643812574028291115057151",
/* B */
"051953eb9618e1c9a1f929a21a0b68540eea2da725b99b315f3b8b489918ef109e156193951ec7"
"e937b1652c0bd3bb1bf073573df883d2c34f1ef451fd46b503f00",
/* Order */
"686479766013060971498190079908139321726943530014330540939446345918554318339765"
"5394245057746333217197532963996371363321113864768612440380340372808892707005449",
/* Gx and Gy */
"c6858e06b70404e9cd9e3ecb662395b4429c648139053fb521f828af606b4d3dbaa14b5e77efe7"
"5928fe1dc127a2ffa8de3348b3c1856a429bf97e7e31c2e5bd66",
"11839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e662c97ee72995ef"
"42640c550b9013fad0761353c7086a272c24088be94769fd16650",
},
#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; 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)
{
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 s, tmp, tmpx;
int res;
if (mp_init_multi(&s, &tmp, &tmpx, NULL) != MP_OKAY) {
return CRYPT_MEM;
}
/* s = (3Xp^2 + a) / (2Yp) */
if (mp_mul_2(&P->y, &tmp) != MP_OKAY) { goto error; } /* tmp = 2*y */
if (mp_invmod(&tmp, modulus, &tmp) != MP_OKAY) { goto error; } /* tmp = 1/tmp mod modulus */
if (mp_sqr(&P->x, &s) != MP_OKAY) { goto error; } /* s = x^2 */
if (mp_mul_d(&s, 3, &s) != MP_OKAY) { goto error; } /* s = 3*(x^2) */
if (mp_sub_d(&s, 3, &s) != MP_OKAY) { goto error; } /* s = 3*(x^2) - 3 */
if (mp_mulmod(&s, &tmp, modulus, &s) != MP_OKAY) { goto error; } /* s = tmp * s mod modulus */
/* Xr = s^2 - 2Xp */
if (mp_sqr(&s, &tmpx) != MP_OKAY) { goto error; } /* tmpx = s^2 */
if (mp_sub(&tmpx, &P->x, &tmpx) != MP_OKAY) { goto error; } /* tmpx = tmpx - x */
if (mp_submod(&tmpx, &P->x, modulus, &tmpx) != MP_OKAY) { goto error; } /* tmpx = tmpx - x mod modulus */
/* Yr = -Yp + s(Xp - Xr) */
if (mp_sub(&P->x, &tmpx, &tmp) != MP_OKAY) { goto error; } /* tmp = x - tmpx */
if (mp_mul(&tmp, &s, &tmp) != MP_OKAY) { goto error; } /* tmp = tmp * s */
if (mp_submod(&tmp, &P->y, modulus, &R->y) != MP_OKAY) { goto error; } /* y = tmp - y mod modulus */
if (mp_copy(&tmpx, &R->x) != MP_OKAY) { goto error; } /* x = tmpx */
res = CRYPT_OK;
goto done;
error:
res = CRYPT_MEM;
done:
mp_clear_multi(&tmpx, &tmp, &s, NULL);
return res;
}
/* 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 s, tmp, tmpx;
int res;
if (mp_init(&tmp) != MP_OKAY) {
return CRYPT_MEM;
}
/* is P==Q or P==-Q? */
mp_neg(&Q->y, &tmp);
mp_mod(&tmp, modulus, &tmp);
if (!mp_cmp(&P->x, &Q->x))
if (!mp_cmp(&P->y, &Q->y) || !mp_cmp(&P->y, &tmp)) {
mp_clear(&tmp);
return dbl_point(P, R, modulus);
}
if (mp_init_multi(&tmpx, &s, NULL) != MP_OKAY) {
mp_clear(&tmp);
return CRYPT_MEM;
}
/* get s = (Yp - Yq)/(Xp-Xq) mod p */
if (mp_submod(&P->x, &Q->x, modulus, &tmp) != MP_OKAY) { goto error; } /* tmp = Px - Qx mod modulus */
if (mp_invmod(&tmp, modulus, &tmp) != MP_OKAY) { goto error; } /* tmp = 1/tmp mod modulus */
if (mp_sub(&P->y, &Q->y, &s) != MP_OKAY) { goto error; } /* s = Py - Qy mod modulus */
if (mp_mulmod(&s, &tmp, modulus, &s) != MP_OKAY) { goto error; } /* s = s * tmp mod modulus */
/* Xr = s^2 - Xp - Xq */
if (mp_sqrmod(&s, modulus, &tmp) != MP_OKAY) { goto error; } /* tmp = s^2 mod modulus */
if (mp_sub(&tmp, &P->x, &tmp) != MP_OKAY) { goto error; } /* tmp = tmp - Px */
if (mp_sub(&tmp, &Q->x, &tmpx) != MP_OKAY) { goto error; } /* tmpx = tmp - Qx */
/* Yr = -Yp + s(Xp - Xr) */
if (mp_sub(&P->x, &tmpx, &tmp) != MP_OKAY) { goto error; } /* tmp = Px - tmpx */
if (mp_mul(&tmp, &s, &tmp) != MP_OKAY) { goto error; } /* tmp = tmp * s */
if (mp_submod(&tmp, &P->y, modulus, &R->y) != MP_OKAY) { goto error; } /* Ry = tmp - Py mod modulus */
if (mp_mod(&tmpx, modulus, &R->x) != MP_OKAY) { goto error; } /* Rx = tmpx mod modulus */
res = CRYPT_OK;
goto done;
error:
res = CRYPT_MEM;
done:
mp_clear_multi(&s, &tmpx, &tmp, NULL);
return res;
}
/* 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, int idx)
{
ecc_point *tG;
int i, j, z, first, res;
mp_digit d;
unsigned char bits[768];
/* get bits of k */
for (z = i = 0; z < (int)USED(k); z++) {
d = DIGIT(k, z);
#define DO1 bits[i++] = d&1; d >>= 1;
#define DO2 DO1 DO1
#define DO4 DO2 DO2
DO4; DO4; DO4; DO4
#undef DO4
#undef DO2
#undef DO1
}
/* make a copy of G incase R==G */
tG = new_point();
if (tG == NULL) {
return CRYPT_MEM;
}
/* tG = G */
if (mp_copy(&G->x, &tG->x) != MP_OKAY) { goto error; }
if (mp_copy(&G->y, &tG->y) != MP_OKAY) { goto error; }
/* set result to G, R = G */
if (mp_copy(&G->x, &R->x) != MP_OKAY) { goto error; }
if (mp_copy(&G->y, &R->y) != MP_OKAY) { goto error; }
first = 0;
/* now do dbl+add through all the bits */
for (j = i-1; j >= 0; j--) {
if (first) {
if (dbl_point(R, R, modulus) != CRYPT_OK) { goto error; }
}
if (bits[j] == 1) {
if (first) {
if (add_point(R, tG, R, modulus) != CRYPT_OK) { goto error; }
}
first = 1;
}
}
res = CRYPT_OK;
goto done;
error:
res = CRYPT_MEM;
done:
del_point(tG);
#ifdef CLEAN_STACK
zeromem(bits, sizeof(bits));
#endif
return res;
}
int ecc_test(void)
{
mp_int modulus, order;
ecc_point *G, *GG;
int i, res, primality;
if (mp_init_multi(&modulus, &order, NULL) != MP_OKAY) {
return CRYPT_MEM;
}
G = new_point();
if (G == NULL) {
mp_clear_multi(&modulus, &order, NULL);
return CRYPT_MEM;
}
GG = new_point();
if (GG == NULL) {
mp_clear_multi(&modulus, &order, NULL);
del_point(G);
return CRYPT_MEM;
}
for (i = 0; sets[i].size; i++) {
if (mp_read_radix(&modulus, (unsigned char *)sets[i].prime, 10) != MP_OKAY) { goto error; }
if (mp_read_radix(&order, (unsigned char *)sets[i].order, 10) != MP_OKAY) { goto error; }
/* is prime actually prime? */
if (is_prime(&modulus, &primality) != CRYPT_OK) { goto error; }
if (primality == 0) {
res = CRYPT_FAIL_TESTVECTOR;
goto done1;
}
/* is order prime ? */
if (is_prime(&order, &primality) != CRYPT_OK) { goto error; }
if (primality == 0) {
res = CRYPT_FAIL_TESTVECTOR;
goto done1;
}
if (mp_read_radix(&G->x, (unsigned char *)sets[i].Gx, 16) != MP_OKAY) { goto error; }
if (mp_read_radix(&G->y, (unsigned char *)sets[i].Gy, 16) != MP_OKAY) { goto error; }
/* then we should have G == (order + 1)G */
if (mp_add_d(&order, 1, &order) != MP_OKAY) { goto error; }
if (ecc_mulmod(&order, G, GG, &modulus, i) != CRYPT_OK) { goto error; }
if (mp_cmp(&G->x, &GG->x) || mp_cmp(&G->y, &GG->y)) {
res = CRYPT_FAIL_TESTVECTOR;
goto done1;
}
}
res = CRYPT_OK;
goto done1;
error:
res = CRYPT_MEM;
done1:
del_point(GG);
del_point(G);
mp_clear_multi(&order, &modulus, NULL);
return res;
}
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; 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, res, errno;
ecc_point *base;
mp_int prime;
unsigned char buf[4096];
_ARGCHK(key != NULL);
/* good prng? */
if ((errno = prng_is_valid(wprng)) != CRYPT_OK) {
return errno;
}
/* find key size */
for (x = 0; (keysize > sets[x].size) && (sets[x].size); x++);
keysize = sets[x].size;
if (sets[x].size == 0) {
return CRYPT_INVALID_KEYSIZE;
}
key->idx = x;
/* make up random string */
buf[0] = 0;
if (prng_descriptor[wprng].read(buf+1, keysize, prng) != (unsigned long)keysize) {
return CRYPT_ERROR_READPRNG;
}
/* setup the key variables */
if (mp_init_multi(&key->pubkey.x, &key->pubkey.y, &key->k, &prime, NULL) != MP_OKAY) {
return CRYPT_MEM;
}
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 (mp_read_radix(&prime, (unsigned char *)sets[x].prime, 10) != MP_OKAY) { goto error; }
if (mp_read_radix(&base->x, (unsigned char *)sets[x].Gx, 16) != MP_OKAY) { goto error; }
if (mp_read_radix(&base->y, (unsigned char *)sets[x].Gy, 16) != MP_OKAY) { goto error; }
if (mp_read_raw(&key->k, (unsigned char *)buf, keysize+1) != MP_OKAY) { goto error; }
/* make the public key */
if (ecc_mulmod(&key->k, base, &key->pubkey, &prime, x) != CRYPT_OK) { goto error; }
key->type = PK_PRIVATE;
/* free up ram */
res = CRYPT_OK;
goto done;
error:
res = CRYPT_MEM;
done:
del_point(base);
mp_clear(&prime);
#ifdef CLEAN_STACK
zeromem(buf, sizeof(buf));
#endif
return res;
}
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 res;
_ARGCHK(pt != NULL);
_ARGCHK(result != NULL);
if (mp_init_multi(&tmp, &tmp2, &p, NULL) != MP_OKAY) {
return CRYPT_MEM;
}
/* get x^3 - 3x + b */
if (mp_read_radix(&p, (unsigned char *)sets[idx].B, 16) != MP_OKAY) { goto error; } /* p = B */
if (mp_expt_d(&pt->x, 3, &tmp) != MP_OKAY) { goto error; } /* tmp = pX^3 */
if (mp_mul_d(&pt->x, 3, &tmp2) != MP_OKAY) { goto error; } /* tmp2 = 3*pX^3 */
if (mp_sub(&tmp, &tmp2, &tmp) != MP_OKAY) { goto error; } /* tmp = tmp - tmp2 */
if (mp_add(&tmp, &p, &tmp) != MP_OKAY) { goto error; } /* tmp = tmp + p */
if (mp_read_radix(&p, (unsigned char *)sets[idx].prime, 10) != MP_OKAY) { goto error; } /* p = prime */
if (mp_mod(&tmp, &p, &tmp) != MP_OKAY) { goto error; } /* tmp = tmp mod p */
/* now find square root */
if (mp_add_d(&p, 1, &tmp2) != MP_OKAY) { goto error; } /* tmp2 = p + 1 */
if (mp_div_2(&tmp2, &tmp2) != MP_OKAY) { goto error; } /* tmp2 = tmp2/2 */
if (mp_div_2(&tmp2, &tmp2) != MP_OKAY) { goto error; } /* tmp2 = (p+1)/4 */
if (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;
res = CRYPT_OK;
goto done;
error:
res = CRYPT_MEM;
done:
mp_clear_multi(&p, &tmp, &tmp2, NULL);
return res;
}
static int expand_y_point(ecc_point *pt, int idx, int result)
{
mp_int tmp, tmp2, p;
int res;
_ARGCHK(pt != NULL);
if (mp_init_multi(&tmp, &tmp2, &p, NULL) != MP_OKAY) {
return CRYPT_MEM;
}
/* get x^3 - 3x + b */
if (mp_read_radix(&p, (unsigned char *)sets[idx].B, 16) != MP_OKAY) { goto error; } /* p = B */
if (mp_expt_d(&pt->x, 3, &tmp) != MP_OKAY) { goto error; } /* tmp = pX^3 */
if (mp_mul_d(&pt->x, 3, &tmp2) != MP_OKAY) { goto error; } /* tmp2 = 3*pX^3 */
if (mp_sub(&tmp, &tmp2, &tmp) != MP_OKAY) { goto error; } /* tmp = tmp - tmp2 */
if (mp_add(&tmp, &p, &tmp) != MP_OKAY) { goto error; } /* tmp = tmp + p */
if (mp_read_radix(&p, (unsigned char *)sets[idx].prime, 10) != MP_OKAY) { goto error; } /* p = prime */
if (mp_mod(&tmp, &p, &tmp) != MP_OKAY) { goto error; } /* tmp = tmp mod p */
/* now find square root */
if (mp_add_d(&p, 1, &tmp2) != MP_OKAY) { goto error; } /* tmp2 = p + 1 */
if (mp_div_2(&tmp2, &tmp2) != MP_OKAY) { goto error; } /* tmp2 = tmp2/2 */
if (mp_div_2(&tmp2, &tmp2) != MP_OKAY) { goto error; } /* tmp2 = (p+1)/4 */
if (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 (mp_copy(&tmp, &pt->y) != MP_OKAY) { goto error; }
} else {
if (mp_sub(&p, &tmp, &pt->y) != MP_OKAY) { goto error; }
}
res = CRYPT_OK;
goto done;
error:
res = CRYPT_MEM;
done:
mp_clear_multi(&p, &tmp, &tmp2, NULL);
return res;
}
#define OUTPUT_BIGNUM(num, buf2, y, z) \
{ \
z = mp_raw_size(num); \
STORE32L(z, buf2+y); \
y += 4; \
mp_toraw(num, buf2+y); \
y += z; \
}
#define INPUT_BIGNUM(num, in, x, y) \
{ \
/* load value */ \
LOAD32L(x, in+y); \
y += 4; \
\
/* sanity check... */ \
if (x > 1024) { \
goto error; \
} \
\
/* load it */ \
if (mp_read_raw(num, (unsigned char *)in+y, x) != MP_OKAY) {\
goto error; \
} \
y += x; \
}
int ecc_export(unsigned char *out, unsigned long *outlen, int type, ecc_key *key)
{
unsigned long y, z;
int res, errno;
unsigned char buf2[512];
_ARGCHK(out != NULL);
_ARGCHK(outlen != NULL);
_ARGCHK(key != NULL);
/* type valid? */
if (key->type != PK_PRIVATE && type == PK_PRIVATE) {
return CRYPT_PK_TYPE_MISMATCH;
}
/* output type and magic byte */
y = PACKET_SIZE;
buf2[y++] = type;
buf2[y++] = key->idx;
/* output x coordinate */
OUTPUT_BIGNUM(&(key->pubkey.x), buf2, y, z);
/* compress y and output it */
if ((errno = compress_y_point(&key->pubkey, key->idx, &res)) != CRYPT_OK) {
return errno;
}
buf2[y++] = res;
if (type == PK_PRIVATE) {
OUTPUT_BIGNUM(&key->k, buf2, y, z);
}
/* check size */
if (*outlen < y) {
return CRYPT_BUFFER_OVERFLOW;
}
/* store header */
packet_store_header(buf2, PACKET_SECT_ECC, PACKET_SUB_KEY, y);
memcpy(out, buf2, y);
*outlen = y;
#ifdef CLEAN_STACK
zeromem(buf2, sizeof(buf2));
#endif
return CRYPT_OK;
}
int ecc_import(const unsigned char *in, ecc_key *key)
{
unsigned long x, y;
int res, errno;
_ARGCHK(in != NULL);
_ARGCHK(key != NULL);
/* check type */
if ((errno = packet_valid_header((unsigned char *)in, PACKET_SECT_ECC, PACKET_SUB_KEY)) != CRYPT_OK) {
return errno;
}
/* 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 = in[y++];
key->idx = in[y++];
/* type check both values */
if ((key->type != PK_PUBLIC) && (key->type != PK_PRIVATE)) {
res = CRYPT_INVALID_PACKET;
goto error2;
}
/* is the key idx valid? */
if (!is_valid_idx(key->idx)) {
res = CRYPT_INVALID_PACKET;
goto error2;
}
/* load x coordinate */
INPUT_BIGNUM(&key->pubkey.x, in, x, y);
/* load y */
x = in[y++];
if ((errno = expand_y_point(&key->pubkey, key->idx, x)) != CRYPT_OK) { res = errno; goto error2; }
if (key->type == PK_PRIVATE) {
/* load private key */
INPUT_BIGNUM(&key->k, in, x, y);
}
res = CRYPT_OK;
goto done;
error:
res = CRYPT_MEM;
error2:
mp_clear_multi(&key->pubkey.x, &key->pubkey.y, &key->k, NULL);
done:
return res;
}
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 res, errno;
_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 (mp_init(&prime) != MP_OKAY) {
del_point(result);
return CRYPT_MEM;
}
if (mp_read_radix(&prime, (unsigned char *)sets[private_key->idx].prime, 10) != MP_OKAY) { goto error; }
if ((errno = ecc_mulmod(&private_key->k, &public_key->pubkey, result, &prime, private_key->idx)) != CRYPT_OK) { res = errno; goto done1; }
x = mp_raw_size(&result->x);
y = mp_raw_size(&result->y);
if (*outlen < (x+y)) {
res = CRYPT_BUFFER_OVERFLOW;
goto done1;
}
*outlen = x+y;
mp_toraw(&result->x, out);
mp_toraw(&result->y, out+x);
res = CRYPT_OK;
goto done1;
error:
res = CRYPT_MEM;
done1:
mp_clear(&prime);
del_point(result);
return res;
}
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

862
ecc_sys.c Normal file
View File

@ -0,0 +1,862 @@
#ifdef PK_PACKET
int ecc_encrypt(const unsigned char *in, unsigned long len,
unsigned char *out, unsigned long *outlen,
prng_state *prng, int wprng, int cipher, int hash,
ecc_key *key)
{
unsigned char pub_expt[512], ecc_shared[256], IV[MAXBLOCKSIZE], skey[MAXBLOCKSIZE];
ecc_key pubkey;
unsigned long x, y, z, pubkeysize;
int keysize, blocksize, hashsize, errno;
symmetric_CTR ctr;
_ARGCHK(in != NULL);
_ARGCHK(out != NULL);
_ARGCHK(outlen != NULL);
_ARGCHK(key != NULL);
/* check that wprng/cipher/hash are not invalid */
if ((errno = prng_is_valid(wprng)) != CRYPT_OK) {
return errno;
}
if ((errno = cipher_is_valid(cipher)) != CRYPT_OK) {
return errno;
}
if ((errno = hash_is_valid(hash)) != CRYPT_OK) {
return errno;
}
/* make a random key and export the public copy */
if ((errno = ecc_make_key(prng, wprng, ecc_get_size(key), &pubkey)) != CRYPT_OK) {
return errno;
}
pubkeysize = sizeof(pub_expt);
if ((errno = ecc_export(pub_expt, &pubkeysize, PK_PUBLIC, &pubkey)) != CRYPT_OK) {
ecc_free(&pubkey);
return errno;
}
/* now check if the out buffer is big enough */
if (*outlen < (10 + PACKET_SIZE + pubkeysize +
cipher_descriptor[cipher].block_length + len)) {
ecc_free(&pubkey);
return CRYPT_BUFFER_OVERFLOW;
}
/* make random key */
blocksize = cipher_descriptor[cipher].block_length;
hashsize = hash_descriptor[hash].hashsize;
keysize = hashsize;
if ((errno = cipher_descriptor[cipher].keysize(&keysize)) != CRYPT_OK) {
ecc_free(&pubkey);
return errno;
}
x = sizeof(ecc_shared);
if ((errno = ecc_shared_secret(&pubkey, key, ecc_shared, &x)) != CRYPT_OK) {
ecc_free(&pubkey);
return errno;
}
ecc_free(&pubkey);
z = sizeof(skey);
if ((errno = hash_memory(hash, ecc_shared, x, skey, &z)) != CRYPT_OK) {
return errno;
}
/* make up IV */
if (prng_descriptor[wprng].read(IV, cipher_descriptor[cipher].block_length, prng) !=
(unsigned long)cipher_descriptor[cipher].block_length) {
return CRYPT_ERROR_READPRNG;
}
/* setup CTR mode */
if ((errno = ctr_start(cipher, IV, skey, keysize, 0, &ctr)) != CRYPT_OK) {
return errno;
}
/* output header */
y = PACKET_SIZE;
/* size of cipher name and the name itself */
out[y++] = cipher_descriptor[cipher].ID;
/* 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 < (unsigned)pubkeysize; x++, y++) {
out[y] = pub_expt[x];
}
/* cipher IV */
for (x = 0; x < (unsigned)blocksize; x++, y++) {
out[y] = IV[x];
}
/* length of ciphertext */
STORE32L(len, out+y);
y += 4;
/* encrypt the message */
if ((errno = ctr_encrypt(in, out+y, len, &ctr)) != CRYPT_OK) {
return errno;
}
y += len;
/* store header */
packet_store_header(out, PACKET_SECT_ECC, PACKET_SUB_ENCRYPTED, y);
#ifdef CLEAN_STACK
/* clean up */
zeromem(pub_expt, sizeof(pub_expt));
zeromem(ecc_shared, sizeof(ecc_shared));
zeromem(skey, sizeof(skey));
zeromem(IV, sizeof(IV));
zeromem(&ctr, sizeof(ctr));
#endif
*outlen = y;
return CRYPT_OK;
}
int ecc_decrypt(const unsigned char *in, unsigned long len,
unsigned char *out, unsigned long *outlen,
ecc_key *key)
{
unsigned char shared_secret[256], skey[MAXBLOCKSIZE];
unsigned long x, y, z, res, hashsize, blocksize;
int cipher, hash, keysize, errno;
ecc_key pubkey;
symmetric_CTR ctr;
_ARGCHK(in != NULL);
_ARGCHK(out != NULL);
_ARGCHK(outlen != NULL);
_ARGCHK(key != NULL);
/* right key type? */
if (key->type != PK_PRIVATE) {
return CRYPT_PK_NOT_PRIVATE;
}
/* is header correct? */
if ((errno = packet_valid_header((unsigned char *)in, PACKET_SECT_ECC, PACKET_SUB_ENCRYPTED)) != CRYPT_OK) {
return errno;
}
/* now lets get the cipher name */
y = PACKET_SIZE;
cipher = find_cipher_id(in[y++]);
if (cipher == -1) {
return CRYPT_INVALID_CIPHER;
}
/* now lets get the hash name */
hash = find_hash_id(in[y++]);
if (hash == -1) {
return CRYPT_INVALID_HASH;
}
/* common values */
blocksize = cipher_descriptor[cipher].block_length;
hashsize = hash_descriptor[hash].hashsize;
keysize = hashsize;
if ((errno = cipher_descriptor[cipher].keysize(&keysize)) != CRYPT_OK) {
return errno;
}
/* get public key */
LOAD32L(x, in+y);
y += 4;
if ((errno = ecc_import(in+y, &pubkey)) != CRYPT_OK) {
return errno;
}
y += x;
/* make shared key */
x = sizeof(shared_secret);
if ((errno = ecc_shared_secret(key, &pubkey, shared_secret, &x)) != CRYPT_OK) {
ecc_free(&pubkey);
return errno;
}
ecc_free(&pubkey);
z = sizeof(skey);
if ((errno = hash_memory(hash, shared_secret, x, skey, &z)) != CRYPT_OK) {
res = errno;
goto done;
}
/* setup CTR mode */
if ((errno = ctr_start(cipher, in+y, skey, keysize, 0, &ctr)) != CRYPT_OK) {
res = errno;
goto done;
}
y += blocksize;
/* get length */
LOAD32L(len,in+y);
y += 4;
/* buffer overflow? */
if (len > *outlen) {
res = CRYPT_BUFFER_OVERFLOW;
goto done;
}
/* decrypt message */
if ((errno = ctr_decrypt(in+y, out, len, &ctr)) != CRYPT_OK) {
res = errno;
goto done;
}
*outlen = len;
res = CRYPT_OK;
done:
#ifdef CLEAN_STACK
zeromem(shared_secret, sizeof(shared_secret));
zeromem(skey, sizeof(skey));
zeromem(&ctr, sizeof(ctr));
#endif
return res;
}
/* Signatures
*
* Signatures are performed using a slightly modified ElGamal protocol.
* In these notes uppercase letters are points and lowercase letters are
* scalars. The users private key is 'x' and public key is Y = xG.
* The order of the curve is 'r'.
*
*
* To sign a message 'm' the user does this
1. Makes up a random 'k' and finds kG [basically makes up a ecc_key], we will let A = kG
2. Finds b such that b = (m - x)/k mod r
3. Outputs (A, b) as the signature
To verify a user computes mG and compares that to (bA + Y). Note that (bA + Y) is equal to
= ((m - x)/k)(kG) + xG
= (m - x)G + xG
= mG
In theory, assuming the ECC Discrete Log is a hard problem an attacker
cannot find 'x' from (A, b). 'b' is perfectly decorrelated and reveals no
information. A reveals what kG is but not 'k' directly. Therefore,
assuming finding 'k' given kG is hard, finding 'x' from b is hard too.
*/
int ecc_sign(const unsigned char *in, unsigned long inlen,
unsigned char *out, unsigned long *outlen,
int hash, prng_state *prng, int wprng,
ecc_key *key)
{
ecc_key pubkey;
mp_int b, p;
unsigned char epubkey[256], er[256], md[MAXBLOCKSIZE];
unsigned long x, y, z, pubkeysize, rsize;
int res, errno;
_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;
}
if ((errno = prng_is_valid(wprng)) != CRYPT_OK) {
return errno;
}
if ((errno = hash_is_valid(hash)) != CRYPT_OK) {
return errno;
}
/* make up a key and export the public copy */
if ((errno = ecc_make_key(prng, wprng, ecc_get_size(key), &pubkey)) != CRYPT_OK) {
return errno;
}
pubkeysize = sizeof(epubkey);
if ((errno = ecc_export(epubkey, &pubkeysize, PK_PUBLIC, &pubkey)) != CRYPT_OK) {
ecc_free(&pubkey);
return errno;
}
/* get the hash and load it as a bignum into 'b' */
md[0] = 0;
z = sizeof(md)-1;
if ((errno = hash_memory(hash, in, inlen, md+1, &z)) != CRYPT_OK) {
ecc_free(&pubkey);
return errno;
}
/* init the bignums */
if (mp_init_multi(&b, &p, NULL) != MP_OKAY) {
ecc_free(&pubkey);
return CRYPT_MEM;
}
if (mp_read_radix(&p, sets[key->idx].order, 10) != MP_OKAY) { goto error; }
if (mp_read_raw(&b, md, 1+hash_descriptor[hash].hashsize) != MP_OKAY) { goto error; }
/* find b = (m - x)/k */
if (mp_invmod(&pubkey.k, &p, &pubkey.k) != MP_OKAY) { goto error; } /* k = 1/k */
if (mp_submod(&b, &key->k, &p, &b) != MP_OKAY) { goto error; } /* b = m - x */
if (mp_mulmod(&b, &pubkey.k, &p, &b) != MP_OKAY) { goto error; } /* b = (m - x)/k */
/* export it */
rsize = mp_raw_size(&b);
if (rsize > sizeof(er)) {
goto error;
}
mp_toraw(&b, er);
/* now lets check the outlen before we write */
if (*outlen < (9 + PACKET_SIZE + rsize + pubkeysize)) {
res = CRYPT_BUFFER_OVERFLOW;
goto done1;
}
/* lets output */
y = PACKET_SIZE;
/* length of hash name plus NULL */
out[y++] = hash_descriptor[hash].ID;
/* 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, y);
/* clear memory */
*outlen = y;
res = CRYPT_OK;
goto done1;
error:
res = CRYPT_MEM;
done1:
mp_clear_multi(&b, &p, NULL);
ecc_free(&pubkey);
#ifdef CLEAN_STACK
zeromem(er, sizeof(er));
zeromem(epubkey, sizeof(epubkey));
zeromem(md, sizeof(md));
#endif
return res;
}
/* verify that mG = (bA + Y) */
int ecc_verify(const unsigned char *sig, const unsigned char *msg,
unsigned long inlen, int *stat,
ecc_key *key)
{
ecc_point *mG;
ecc_key pubkey;
mp_int b, p, m;
unsigned long x, y, z;
int hash, res, errno;
unsigned char md[MAXBLOCKSIZE];
_ARGCHK(sig != NULL);
_ARGCHK(msg != NULL);
_ARGCHK(stat != NULL);
_ARGCHK(key != NULL);
/* default to invalid signature */
*stat = 0;
/* is the message format correct? */
if ((errno = packet_valid_header((unsigned char *)sig, PACKET_SECT_ECC, PACKET_SUB_SIGNED)) != CRYPT_OK) {
return errno;
}
/* get hash name */
y = PACKET_SIZE;
hash = find_hash_id(sig[y++]);
if (hash == -1) {
return CRYPT_INVALID_HASH;
}
/* get size of public key */
LOAD32L(x, sig+y);
y += 4;
/* load the public key */
if ((errno = ecc_import((unsigned char*)sig+y, &pubkey)) != CRYPT_OK) {
return errno;
}
y += x;
/* load size of 'b' */
LOAD32L(x, sig+y);
y += 4;
/* init values */
if (mp_init_multi(&b, &m, &p, NULL) != MP_OKAY) {
ecc_free(&pubkey);
return CRYPT_MEM;
}
mG = new_point();
if (mG == NULL) {
mp_clear_multi(&b, &m, &p, NULL);
ecc_free(&pubkey);
return CRYPT_MEM;
}
/* load b */
if (mp_read_raw(&b, (unsigned char *)sig+y, x) != MP_OKAY) { goto error; }
y += x;
/* get m in binary a bignum */
md[0] = 0;
z = sizeof(md)-1;
if ((errno = hash_memory(hash, msg, inlen, md+1, &z)) != CRYPT_OK) {
res = errno;
goto done1;
}
if (mp_read_raw(&m, md, hash_descriptor[hash].hashsize + 1) != MP_OKAY) { goto error; }
/* load prime */
if (mp_read_radix(&p, sets[key->idx].prime, 10) != MP_OKAY) { goto error; }
/* get bA */
if (ecc_mulmod(&b, &pubkey.pubkey, &pubkey.pubkey, &p, key->idx) != CRYPT_OK) { goto error; }
/* get bA + Y */
if (add_point(&pubkey.pubkey, &key->pubkey, &pubkey.pubkey, &p) != CRYPT_OK) { goto error; }
/* get mG */
if (mp_read_radix(&mG->x, sets[key->idx].Gx, 16) != MP_OKAY) { goto error; }
if (mp_read_radix(&mG->y, sets[key->idx].Gy, 16) != MP_OKAY) { goto error; }
if (ecc_mulmod(&m, mG, mG, &p, key->idx) != CRYPT_OK) { goto error; }
/* compare mG to bA + Y */
if (!mp_cmp(&mG->x, &pubkey.pubkey.x) && !mp_cmp(&mG->y, &pubkey.pubkey.y)) {
*stat = 1;
}
/* clear up and return */
res = CRYPT_OK;
goto done1;
error:
res = CRYPT_MEM;
done1:
del_point(mG);
ecc_free(&pubkey);
mp_clear_multi(&p, &m, &b, NULL);
#ifdef CLEAN_STACK
zeromem(md, sizeof(md));
#endif
return CRYPT_OK;
}
#endif
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 errno;
_ARGCHK(inkey != NULL);
_ARGCHK(out != NULL);
_ARGCHK(len != NULL);
_ARGCHK(key != NULL);
/* check that wprng/cipher/hash are not invalid */
if ((errno = prng_is_valid(wprng)) != CRYPT_OK) {
return errno;
}
if ((errno = hash_is_valid(hash)) != CRYPT_OK) {
return errno;
}
if (keylen > hash_descriptor[hash].hashsize) {
return CRYPT_INVALID_HASH;
}
/* make a random key and export the public copy */
if ((errno = ecc_make_key(prng, wprng, ecc_get_size(key), &pubkey)) != CRYPT_OK) {
return errno;
}
pubkeysize = sizeof(pub_expt);
if ((errno = ecc_export(pub_expt, &pubkeysize, PK_PUBLIC, &pubkey)) != CRYPT_OK) {
ecc_free(&pubkey);
return errno;
}
/* 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 = sizeof(ecc_shared);
if ((errno = ecc_shared_secret(&pubkey, key, ecc_shared, &x)) != CRYPT_OK) {
ecc_free(&pubkey);
return errno;
}
ecc_free(&pubkey);
z = sizeof(skey);
if ((errno = hash_memory(hash, ecc_shared, x, skey, &z)) != CRYPT_OK) {
return errno;
}
/* Encrypt the key */
for (x = 0; x < keylen; x++) {
skey[x] ^= inkey[x];
}
/* 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;
/* Store the encrypted key */
for (x = 0; x < keylen; x++, y++) {
out[y] = skey[x];
}
/* store header */
packet_store_header(out, PACKET_SECT_ECC, PACKET_SUB_ENC_KEY, y);
#ifdef CLEAN_STACK
/* clean up */
zeromem(pub_expt, sizeof(pub_expt));
zeromem(ecc_shared, sizeof(ecc_shared));
zeromem(skey, sizeof(skey));
#endif
*len = y;
return CRYPT_OK;
}
int ecc_decrypt_key(const unsigned char *in, unsigned char *outkey,
unsigned long *keylen, ecc_key *key)
{
unsigned char shared_secret[256], skey[MAXBLOCKSIZE];
unsigned long x, y, z, res, hashsize, keysize;
int hash, errno;
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;
}
/* is header correct? */
if ((errno = packet_valid_header((unsigned char *)in, PACKET_SECT_ECC, PACKET_SUB_ENC_KEY)) != CRYPT_OK) {
return errno;
}
/* 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);
y += 4;
if ((errno = ecc_import(in+y, &pubkey)) != CRYPT_OK) {
return errno;
}
y += x;
/* make shared key */
x = sizeof(shared_secret);
if ((errno = ecc_shared_secret(key, &pubkey, shared_secret, &x)) != CRYPT_OK) {
ecc_free(&pubkey);
return errno;
}
ecc_free(&pubkey);
z = sizeof(skey);
if ((errno = hash_memory(hash, shared_secret, x, skey, &z)) != CRYPT_OK) {
return errno;
}
LOAD32L(keysize, in+y);
y += 4;
if (*keylen < keysize) {
res = CRYPT_BUFFER_OVERFLOW;
goto done;
}
/* Decrypt the key */
for (x = 0; x < keysize; x++, y++) {
outkey[x] = skey[x] ^ in[y];
}
*keylen = keysize;
res = CRYPT_OK;
done:
#ifdef CLEAN_STACK
zeromem(shared_secret, sizeof(shared_secret));
zeromem(skey, sizeof(skey));
#endif
return res;
}
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], md[MAXBLOCKSIZE];
unsigned long x, y, pubkeysize, rsize;
int res, errno;
_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;
}
if ((errno = prng_is_valid(wprng)) != CRYPT_OK) {
return errno;
}
/* make up a key and export the public copy */
if ((errno = ecc_make_key(prng, wprng, ecc_get_size(key), &pubkey)) != CRYPT_OK) {
return errno;
}
pubkeysize = sizeof(epubkey);
if ((errno = ecc_export(epubkey, &pubkeysize, PK_PUBLIC, &pubkey)) != CRYPT_OK) {
ecc_free(&pubkey);
return errno;
}
/* get the hash and load it as a bignum into 'b' */
md[0] = 0;
memcpy(md+1, in, MIN(sizeof(md)-1,inlen));
/* init the bignums */
if (mp_init_multi(&b, &p, NULL) != MP_OKAY) {
ecc_free(&pubkey);
return CRYPT_MEM;
}
if (mp_read_radix(&p, (unsigned char *)sets[key->idx].order, 10) != MP_OKAY) { goto error; }
if (mp_read_raw(&b, md, 1+MIN(sizeof(md)-1,inlen)) != MP_OKAY) { goto error; }
/* find b = (m - x)/k */
if (mp_invmod(&pubkey.k, &p, &pubkey.k) != MP_OKAY) { goto error; } /* k = 1/k */
if (mp_submod(&b, &key->k, &p, &b) != MP_OKAY) { goto error; } /* b = m - x */
if (mp_mulmod(&b, &pubkey.k, &p, &b) != MP_OKAY) { goto error; } /* b = (m - x)/k */
/* export it */
rsize = mp_raw_size(&b);
if (rsize > sizeof(er)) {
goto error;
}
mp_toraw(&b, er);
/* now lets check the outlen before we write */
if (*outlen < (12 + rsize + pubkeysize)) {
res = CRYPT_BUFFER_OVERFLOW;
goto done1;
}
/* 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, y);
/* clear memory */
*outlen = y;
res = CRYPT_OK;
goto done1;
error:
res = CRYPT_MEM;
done1:
mp_clear_multi(&b, &p, NULL);
ecc_free(&pubkey);
#ifdef CLEAN_STACK
zeromem(er, sizeof(er));
zeromem(epubkey, sizeof(epubkey));
zeromem(md, sizeof(md));
#endif
return res;
}
/* verify that mG = (bA + Y) */
int ecc_verify_hash(const unsigned char *sig, const unsigned char *hash,
unsigned long inlen, int *stat,
ecc_key *key)
{
ecc_point *mG;
ecc_key pubkey;
mp_int b, p, m;
unsigned long x, y;
int res, errno;
unsigned char md[MAXBLOCKSIZE];
_ARGCHK(sig != NULL);
_ARGCHK(hash != NULL);
_ARGCHK(hash != NULL);
_ARGCHK(key != NULL);
/* default to invalid signature */
*stat = 0;
/* is the message format correct? */
if ((errno = packet_valid_header((unsigned char *)sig, PACKET_SECT_ECC, PACKET_SUB_SIGNED)) != CRYPT_OK) {
return errno;
}
/* get hash name */
y = PACKET_SIZE;
/* get size of public key */
LOAD32L(x, sig+y);
y += 4;
/* load the public key */
if ((errno = ecc_import((unsigned char*)sig+y, &pubkey)) != CRYPT_OK) {
return errno;
}
y += x;
/* load size of 'b' */
LOAD32L(x, sig+y);
y += 4;
/* init values */
if (mp_init_multi(&b, &m, &p, NULL) != MP_OKAY) {
ecc_free(&pubkey);
return CRYPT_MEM;
}
mG = new_point();
if (mG == NULL) {
mp_clear_multi(&b, &m, &p, NULL);
ecc_free(&pubkey);
return CRYPT_MEM;
}
/* load b */
if (mp_read_raw(&b, (unsigned char *)sig+y, x) != MP_OKAY) { goto error; }
y += x;
/* get m in binary a bignum */
md[0] = 0;
memcpy(md+1,hash,MIN(sizeof(md)-1,inlen));
if (mp_read_raw(&m, md, 1+MIN(sizeof(md)-1,inlen)) != MP_OKAY) { goto error; }
/* load prime */
if (mp_read_radix(&p, (unsigned char *)sets[key->idx].prime, 10) != MP_OKAY) { goto error; }
/* get bA */
if (ecc_mulmod(&b, &pubkey.pubkey, &pubkey.pubkey, &p, key->idx) != CRYPT_OK) { goto error; }
/* get bA + Y */
if (add_point(&pubkey.pubkey, &key->pubkey, &pubkey.pubkey, &p) != CRYPT_OK) { goto error; }
/* get mG */
if (mp_read_radix(&mG->x, (unsigned char *)sets[key->idx].Gx, 16) != MP_OKAY) { goto error; }
if (mp_read_radix(&mG->y, (unsigned char *)sets[key->idx].Gy, 16) != MP_OKAY) { goto error; }
if (ecc_mulmod(&m, mG, mG, &p, key->idx) != CRYPT_OK) { goto error; }
/* compare mG to bA + Y */
if (!mp_cmp(&mG->x, &pubkey.pubkey.x) && !mp_cmp(&mG->y, &pubkey.pubkey.y)) {
*stat = 1;
}
/* clear up and return */
res = CRYPT_OK;
goto done;
error:
res = CRYPT_ERROR;
done:
del_point(mG);
ecc_free(&pubkey);
mp_clear_multi(&p, &m, &b, NULL);
#ifdef CLEAN_STACK
zeromem(md, sizeof(md));
#endif
return CRYPT_OK;
}

295
gf.c Normal file
View File

@ -0,0 +1,295 @@
/* 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

93
hash.c Normal file
View File

@ -0,0 +1,93 @@
#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 errno;
_ARGCHK(data != NULL);
_ARGCHK(dst != NULL);
_ARGCHK(outlen != NULL);
if ((errno = hash_is_valid(hash)) != CRYPT_OK) {
return errno;
}
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;
}
int hash_filehandle(int hash, FILE *in, unsigned char *dst, unsigned long *outlen)
{
#ifdef NO_FILE
return CRYPT_ERROR;
#else
hash_state md;
unsigned char buf[512];
int x, errno;
_ARGCHK(dst != NULL);
_ARGCHK(outlen != NULL);
_ARGCHK(in != NULL);
if ((errno = hash_is_valid(hash)) != CRYPT_OK) {
return errno;
}
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
}
int hash_file(int hash, const char *fname, unsigned char *dst, unsigned long *outlen)
{
#ifdef NO_FILE
return CRYPT_ERROR;
#else
FILE *in;
int errno;
_ARGCHK(fname != NULL);
_ARGCHK(dst != NULL);
_ARGCHK(outlen != NULL);
if ((errno = hash_is_valid(hash)) != CRYPT_OK) {
return errno;
}
in = fopen(fname, "rb");
if (in == NULL) {
return CRYPT_INVALID_ARG;
}
if ((errno = hash_filehandle(hash, in, dst, outlen)) != CRYPT_OK) {
fclose(in);
return errno;
}
fclose(in);
return CRYPT_OK;
#endif
}

478
hmac.c Normal file
View File

@ -0,0 +1,478 @@
/* 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 errno;
_ARGCHK(hmac != NULL);
_ARGCHK(key != NULL);
if ((errno = hash_is_valid(hash)) != CRYPT_OK) {
return errno;
}
if(key == NULL || keylen == 0) {
return CRYPT_INVALID_KEYSIZE;
}
hmac->hash = hash;
// (1) make sure we have a large enough key
hmac->hashsize = hashsize = hash_descriptor[hash].hashsize;
if(keylen > HMAC_BLOCKSIZE) {
z = sizeof(hmac->key);
if ((errno = hash_memory(hash, key, keylen, hmac->key, &z)) != CRYPT_OK) {
return errno;
}
if(hashsize < HMAC_BLOCKSIZE) {
zeromem(hmac->key+hashsize, HMAC_BLOCKSIZE - hashsize);
}
} else {
memcpy(hmac->key, key, keylen);
if(keylen < HMAC_BLOCKSIZE) {
zeromem(hmac->key + keylen, HMAC_BLOCKSIZE - keylen);
}
}
// Create the initial vector for step (3)
for(i=0; i < keylen; i++) {
buf[i] = hmac->key[i] ^ 0x36;
}
for( ; i < HMAC_BLOCKSIZE; i++) {
buf[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;
}
int hmac_process(hmac_state *hmac, const unsigned char *buf, unsigned long len)
{
int errno;
_ARGCHK(hmac != NULL);
_ARGCHK(buf != NULL);
if ((errno = hash_is_valid(hmac->hash)) != CRYPT_OK) {
return errno;
}
hash_descriptor[hmac->hash].process(&hmac->md, buf, len);
return CRYPT_OK;
}
int hmac_done(hmac_state *hmac, unsigned char *hashOut)
{
unsigned char buf[MAXBLOCKSIZE];
unsigned char isha[MAXBLOCKSIZE];
unsigned long hashsize, i;
int hash, errno;
_ARGCHK(hmac != NULL);
_ARGCHK(hashOut != NULL);
hash = hmac->hash;
if((errno = hash_is_valid(hash)) != CRYPT_OK) {
return errno;
}
// Get the hash of the first HMAC vector plus the data
hash_descriptor[hash].done(&hmac->md, isha);
// Create the second HMAC vector vector for step (3)
hashsize = hash_descriptor[hash].hashsize;
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, hashOut);
#ifdef CLEAN_STACK
zeromem(hmac->key, sizeof(hmac->key));
#endif
return CRYPT_OK;
}
int hmac_memory(int hash, const unsigned char *key, unsigned long keylen,
const unsigned char *data, unsigned long len, unsigned char *dst)
{
hmac_state hmac;
int errno;
_ARGCHK(key != NULL);
_ARGCHK(data != NULL);
_ARGCHK(dst != NULL);
if ((errno = hmac_init(&hmac, hash, key, keylen)) != CRYPT_OK) {
return errno;
}
if ((errno = hmac_process(&hmac, data, len)) != CRYPT_OK) {
return errno;
}
if ((errno = hmac_done(&hmac, dst)) != CRYPT_OK) {
return errno;
}
return CRYPT_OK;
}
/* 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)
{
#ifdef NO_FILE
return CRYPT_ERROR;
#else
hmac_state hmac;
FILE *in;
unsigned char buf[512];
int x, errno;
_ARGCHK(fname != NULL);
_ARGCHK(key != NULL);
_ARGCHK(dst != NULL);
if ((errno = hmac_init(&hmac, hash, key, keylen)) != CRYPT_OK) {
return errno;
}
in = fopen(fname, "rb");
if (in == NULL) {
return CRYPT_INVALID_ARG;
}
/* process the file contents */
do {
x = fread(buf, 1, sizeof(buf), in);
if ((errno = hmac_process(&hmac, buf, x)) != CRYPT_OK) {
fclose(in);
return errno;
}
} while (x == sizeof(buf));
fclose(in);
/* get final hmac */
if ((errno = hmac_done(&hmac, dst)) != CRYPT_OK) {
return errno;
}
#ifdef CLEAN_STACK
/* clear memory */
zeromem(buf, sizeof(buf));
#endif
return CRYPT_OK;
#endif
}
/*
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)
{
unsigned char digest[MAXBLOCKSIZE];
int i;
struct hmac_test_case {
int num;
char *algo;
unsigned char key[128];
int keylen;
unsigned char data[128];
int 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} }
};
int errno;
int failed=0;
for(i=0; i < (int)(sizeof(cases) / sizeof(cases[0])); i++) {
int hash = find_hash(cases[i].algo);
if((errno = hmac_memory(hash, cases[i].key, cases[i].keylen, cases[i].data, cases[i].datalen, digest)) != CRYPT_OK) {
#if 0
printf("HMAC-%s test #%d\n", cases[i].algo, cases[i].num);
#endif
return errno;
}
if(memcmp(digest, cases[i].digest, 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) {
return CRYPT_FAIL_TESTVECTOR;
}
return CRYPT_OK;
}
#endif

840
keyring.c Normal file
View File

@ -0,0 +1,840 @@
/* 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] = {
0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
0x2d02ef8dL
};
#define DO1(buf) crc = crc_table[((int)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)
{
crc = crc ^ 0xffffffffL;
while (len >= 8)
{
DO8 (buf);
len -= 8;
}
if (len)
do
{
DO1 (buf);
}
while (--len);
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(0, NULL, 0);
crc = crc32(crc, name, MIN(MAXLEN, strlen((char *)name)));
crc = crc32(crc, email, MIN(MAXLEN, strlen((char *)email)));
return crc32(crc, description, 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)) {
return pk;
}
pk = pk->next;
}
return NULL;
}
int kr_add(pk_key *pk, int key_type, int system, 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 (system != RSA_KEY && system != DH_KEY && system != 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 = system;
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 (system) {
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 errno;
_ARGCHK(pk != NULL);
while ((*pk)->system != NON_KEY) {
if ((errno = kr_del(pk, (*pk)->ID)) != CRYPT_OK) {
return errno;
}
}
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 fwrite(buf, 1, 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 = fread(buf, 1, 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 errno;
_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 ((errno = rsa_export(obuf, &len, key_type, &(ppk->key.rsa))) != CRYPT_OK) {
return errno;
}
break;
case DH_KEY:
if ((errno = dh_export(obuf, &len, key_type, &(ppk->key.dh))) != CRYPT_OK) {
return errno;
}
break;
case ECC_KEY:
if ((errno = ecc_export(obuf, &len, key_type, &(ppk->key.ecc))) != CRYPT_OK) {
return errno;
}
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)
{
_pk_key key;
int system, key_type, errno;
unsigned long ID;
_ARGCHK(pk != NULL);
_ARGCHK(in != NULL);
if (memcmp(in, key_magic, 4)) {
return CRYPT_INVALID_PACKET;
}
key_type = in[4]; /* get type */
system = 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));
switch (system) {
case RSA_KEY:
if ((errno = rsa_import(in+10+3*MAXLEN, &(key.rsa))) != CRYPT_OK) {
return errno;
}
break;
case DH_KEY:
if ((errno = dh_import(in+10+3*MAXLEN, &(key.dh))) != CRYPT_OK) {
return errno;
}
break;
case ECC_KEY:
if ((errno = ecc_import(in+10+3*MAXLEN, &(key.ecc))) != CRYPT_OK) {
return errno;
}
break;
}
return kr_add(pk, key_type, system,
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, errno;
_ARGCHK(pk != NULL);
_ARGCHK(in != NULL);
/* init keyring */
if ((errno = kr_init(pk)) != CRYPT_OK) {
return errno;
}
/* read in magic bytes */
if (_read(buf, 6, in, ctr) != 6) { goto done2; }
if (memcmp(buf, file_magic, 4)) {
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 > sizeof(buf)) {
return CRYPT_INVALID_PACKET;
}
if (_read(buf, len, in, ctr) != len) { goto done2; }
if ((errno = kr_import(*pk, buf)) != CRYPT_OK) {
return errno;
}
}
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, errno;
_ARGCHK(pk != NULL);
_ARGCHK(out != NULL);
/* write out magic bytes */
memcpy(buf, file_magic, 4);
buf[4] = CRYPT&255;
buf[5] = (CRYPT>>8)&255;
if (_write(buf, 6, out, ctr) != 6) { goto done2; }
while (pk->system != NON_KEY) {
len = sizeof(buf);
if ((errno = kr_export(pk, pk->ID, pk->key_type, buf, &len)) != CRYPT_OK) {
return errno;
}
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 system, int keysize, const unsigned char *name,
const unsigned char *email, const unsigned char *description)
{
_pk_key key;
int key_type, errno;
_ARGCHK(pk != NULL);
_ARGCHK(name != NULL);
_ARGCHK(email != NULL);
_ARGCHK(description != NULL);
/* valid PRNG? */
if ((errno = prng_is_valid(wprng)) != CRYPT_OK) {
return errno;
}
/* make the key first */
zeromem(&key, sizeof(key));
switch (system) {
case RSA_KEY:
if ((errno = rsa_make_key(prng, wprng, keysize, 65537, &(key.rsa))) != CRYPT_OK) {
return errno;
}
key_type = key.rsa.type;
break;
case DH_KEY:
if ((errno = dh_make_key(prng, wprng, keysize, &(key.dh))) != CRYPT_OK) {
return errno;
}
key_type = key.dh.type;
break;
case ECC_KEY:
if ((errno = ecc_make_key(prng, wprng, keysize, &(key.ecc))) != CRYPT_OK) {
return errno;
}
key_type = key.ecc.type;
break;
default:
return CRYPT_PK_INVALID_SYSTEM;
}
/* now add the key */
if ((errno = kr_add(pk, key_type, system, name, email, description, &key)) != CRYPT_OK) {
return errno;
}
#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 errno;
_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)-8;
switch (kr->system) {
case RSA_KEY:
if ((errno = rsa_encrypt_key(in, inlen, buf+8, &len, prng, wprng, &(kr->key.rsa))) != CRYPT_OK) {
return errno;
}
break;
case DH_KEY:
if ((errno = dh_encrypt_key(in, inlen, buf+8, &len, prng, wprng, hash, &(kr->key.dh))) != CRYPT_OK) {
return errno;
}
break;
case ECC_KEY:
if ((errno = ecc_encrypt_key(in, inlen, buf+8, &len, prng, wprng, hash, &(kr->key.ecc))) != CRYPT_OK) {
return errno;
}
break;
}
len += 8;
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 len, ID;
pk_key *kr;
int errno;
_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 */
len = sizeof(buf);
switch (kr->system) {
case RSA_KEY:
if ((errno = rsa_decrypt_key(in+8, buf, &len, &(kr->key.rsa))) != CRYPT_OK) {
return errno;
}
break;
case DH_KEY:
if ((errno = dh_decrypt_key(in+8, buf, &len, &(kr->key.dh))) != CRYPT_OK) {
return errno;
}
break;
case ECC_KEY:
if ((errno = ecc_decrypt_key(in+8, buf, &len, &(kr->key.ecc))) != CRYPT_OK) {
return errno;
}
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 errno;
_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)-12;
switch (kr->system) {
case RSA_KEY:
if ((errno = rsa_sign_hash(in, inlen, buf+12, &len, &(kr->key.rsa))) != CRYPT_OK) {
return errno;
}
break;
case DH_KEY:
if ((errno = dh_sign_hash(in, inlen, buf+12, &len, prng, wprng, &(kr->key.dh))) != CRYPT_OK) {
return errno;
}
break;
case ECC_KEY:
if ((errno = ecc_sign_hash(in, inlen, buf+12, &len, prng, wprng, &(kr->key.ecc))) != CRYPT_OK) {
return errno;
}
break;
}
STORE32L(inlen,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_verify_hash(pk_key *pk, const unsigned char *in, const unsigned char *hash,
unsigned long hashlen, int *stat)
{
unsigned long inlen, ID;
pk_key *kr;
int errno;
_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 */
if (inlen != hashlen) { /* size doesn't match means the signature is invalid */
return CRYPT_OK;
}
switch (kr->system) {
case RSA_KEY:
if ((errno = rsa_verify_hash(in+12, hash, stat, &(kr->key.rsa))) != CRYPT_OK) {
return errno;
}
break;
case DH_KEY:
if ((errno = dh_verify_hash(in+12, hash, inlen, stat, &(kr->key.dh))) != CRYPT_OK) {
return errno;
}
break;
case ECC_KEY:
if ((errno = ecc_verify_hash(in+12, hash, inlen, stat, &(kr->key.ecc))) != CRYPT_OK) {
return errno;
}
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 errno;
_ARGCHK(pk != NULL);
_ARGCHK(out != NULL);
_ARGCHK(outlen != NULL);
/* valid hash? */
if ((errno = hash_is_valid(hash)) != CRYPT_OK) {
return errno;
}
len = sizeof(buf);
if ((errno = kr_export(pk, ID, PK_PUBLIC, buf, &len)) != CRYPT_OK) {
return errno;
}
/* now hash it */
if ((errno = hash_memory(hash, buf, len, out, outlen)) != CRYPT_OK) {
return errno;
}
#ifdef CLEAN_STACK
zeromem(buf, sizeof(buf));
#endif
return CRYPT_OK;
}
#endif

262
makefile Normal file
View File

@ -0,0 +1,262 @@
# 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.75
#Compiler and Linker Names
CC=gcc
LD=ld
#Archiver [makes .a files]
AR=ar
ARFLAGS=rs
#here you can set the malloc/calloc/free functions you want
XMALLOC=malloc
XCALLOC=calloc
XFREE=free
#you can redefine the clock
XCLOCK=clock
XCLOCKS_PER_SEC=CLOCKS_PER_SEC
#Compilation flags. Note the += does not write over the user's CFLAGS!
CFLAGS += -c -I./ -Wall -Wsign-compare -W -Wno-unused -Werror \
-DXMALLOC=$(XMALLOC) -DXCALLOC=$(XCALLOC) -DXFREE=$(XFREE) -DXCLOCK=$(XCLOCK) \
-DXCLOCKS_PER_SEC=$(XCLOCKS_PER_SEC)
#optimize for SPEED (comment out SIZE/DEBUG line as well)
#CFLAGS += -O3 -fomit-frame-pointer -funroll-loops
#optimize for SIZE (comment out SPEED/DEBUG line as well)
CFLAGS += -O2
#compile for DEBUGGING
#CFLAGS += -g3
#These flags control how the library gets built.
#no file support, when defined the library will not have any functions that can read/write files
#(comment out to have file support)
#CFLAGS += -DNO_FILE
#Support the UNIX /dev/random or /dev/urandom
CFLAGS += -DDEVRANDOM
# Use /dev/urandom first on devices where /dev/random is too slow */
#CFLAGS += -DTRY_URANDOM_FIRST
# Clean the stack after sensitive functions. Not always required...
# With this defined most of the ciphers and hashes will clean their stack area
# after usage with a (sometimes) huge penalty in speed. Normally this is not
# required if you simply lock your stack and wipe it when your program is done.
#
#CFLAGS += -DCLEAN_STACK
# What algorithms to include? comment out and rebuild to remove em
CFLAGS += -DBLOWFISH
CFLAGS += -DRC2
CFLAGS += -DRC5
CFLAGS += -DRC6
CFLAGS += -DSERPENT
CFLAGS += -DSAFERP
CFLAGS += -DSAFER
CFLAGS += -DRIJNDAEL
CFLAGS += -DXTEA
CFLAGS += -DTWOFISH
CFLAGS += -DDES
CFLAGS += -DCAST5
#You can also customize the Twofish code. All four combinations
#of the flags are possible but only three of them make sense.
#
#Both undefined: Very fast, requires ~4.2KB of ram per scheduled key
#Both defined : Slow, requires only ~100 bytes of ram per scheduled key
#
#If defined on their own
#_SMALL defined: Very Slow, small code only ~100 bytes of ram
#_TABLES defined: Very fast, not faster than if both were undefined. Code is ~1KB bigger
# faster keysetup though...
# Small Ram Variant of Twofish. For this you must have TWOFISH defined. This
# variant requires about 4kb less memory but is considerably slower. It is ideal
# when high throughput is less important than conserving memory. By default it is
# not defined which means the larger ram (about 4.2Kb used) variant is built.
#CFLAGS += -DTWOFISH_SMALL
# Tell Twofish to use precomputed tables. If you want to use the small table
# variant of Twofish you may want to turn this on. Essentially it tells Twofish to use
# precomputed S-boxes (Q0 and Q1) as well as precomputed GF multiplications [in the MDS].
# This speeds up the cipher somewhat.
#CFLAGS += -DTWOFISH_TABLES
#Small code variant of the SAFER+ cipher, uses same RAM but less code space
#With this defined the cipher is slower. On my x86 with GCC 3.2 it required 50KB less space
CFLAGS += -DSAFERP_SMALL
#Small Rijndael [saves 13KB on an x86]
#With this defined the cipher is slower (by 50Mbit/sec on an Athon XP)
CFLAGS += -DRIJNDAEL_SMALL
#Use fast PK routines. Basically this limits the size of the private key in the
#DH system to 256 bits. The group order remains unchanged so the best
#attacks are still GNFS (for DH upto 2560-bits)
#
#This will only speed up the key generation and encryption routines. It lowers the
#security so its by default not turned on. USE AT YOUR RISK!
#CFLAGS += -DFAST_PK
#Include the PK Packet functions (e.g. dh_encrypt)
#Does not affect the key/hash routines (e.g. ecc_sign_hash)
#CFLAGS += -DPK_PACKET
# Chaining modes
CFLAGS += -DCFB
CFLAGS += -DOFB
CFLAGS += -DECB
CFLAGS += -DCBC
CFLAGS += -DCTR
#One-way hashes
CFLAGS += -DSHA512
CFLAGS += -DSHA384
CFLAGS += -DSHA256
CFLAGS += -DTIGER
CFLAGS += -DSHA1
CFLAGS += -DMD5
CFLAGS += -DMD4
CFLAGS += -DMD2
# base64
CFLAGS += -DBASE64
# prngs
CFLAGS += -DYARROW
CFLAGS += -DSPRNG
CFLAGS += -DRC4
# PK code
CFLAGS += -DMRSA
CFLAGS += -DMDH
CFLAGS += -DMECC
CFLAGS += -DKR
# include GF math routines? (not currently used by anything internally)
#CFLAGS += -DGF
# include large integer math routines? (required by the PK code)
CFLAGS += -DMPI
# Use a small prime table? It greatly reduces the size of prime.c at a little impact
# in speed.
#
CFLAGS += -DSMALL_PRIME_TAB
# include HMAC support
CFLAGS += -DHMAC
#Output filenames for various targets.
LIBNAME=libtomcrypt.a
TEST=test
HASH=hashsum
CRYPT=encrypt
SMALL=small
#LIBPATH-The directory for libtomcrypt to be installed to.
#INCPATH-The directory to install the header files for libtomcrypt.
LIBPATH=/usr/lib
INCPATH=/usr/include
#List of objects to compile.
OBJECTS=keyring.o gf.o mem.o sprng.o ecc.o base64.o dh.o rsa.o \
bits.o yarrow.o cfb.o ofb.o ecb.o ctr.o cbc.o hash.o tiger.o sha1.o \
md5.o md4.o md2.o sha256.o sha512.o xtea.o aes.o serpent.o des.o \
safer_tab.o safer.o safer+.o rc4.o rc2.o rc6.o rc5.o cast5.o blowfish.o crypt.o \
ampi.o mpi.o prime.o twofish.o packet.o hmac.o strings.o
TESTOBJECTS=demos/test.o
HASHOBJECTS=demos/hashsum.o
CRYPTOBJECTS=demos/encrypt.o
SMALLOBJECTS=demos/small.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=mpi-types.h mpi-config.h mpi.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
#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
sha512.o: sha512.c sha384.c
#This rule makes the libtomcrypt library.
library: $(OBJECTS)
$(AR) $(ARFLAGS) $(LIBNAME) $(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)
#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 -g root -o root $(LIBNAME) $(LIBPATH)
install -g root -o root $(HEADERS) $(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)
rm -f *stackdump *.lib *.exe *.obj demos/*.obj zlib/*.obj *.bat
#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
rm -f $(LEFTOVERS)
latex crypt > /dev/null
makeindex crypt > /dev/null
pdflatex crypt > /dev/null
rm -f $(LEFTOVERS)
#zipup the project (take that!)
zipup: clean docs
chdir .. ; 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)/*

293
makefile.ps2 Normal file
View File

@ -0,0 +1,293 @@
# 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.
#Compiler and Linker Names
CC=ee-gcc
LD=ee-ld
# PlayStation(tm) 2 specifics
TOP = /usr/local/sce/ee
LIBDIR = $(TOP)/lib
INCDIR = $(TOP)/include/
COMMONDIR = $(TOP)/../common/include/
LCFILE = $(LIBDIR)/app.cmd
LDFLAGS = -DSONY_PS2 -DSONY_PS2_EE -Wl,-Map,$(@).map -mno-crt0 -L$(LIBDIR) -lm
AS = ee-gcc
ASFLAGS = -DSONY_PS2 -DSONY_PS2_EE -c -xassembler-with-cpp -Wa,-al
EXT = .elf
CFLAGS += -DSONY_PS2 -DSONY_PS2_EE -Wa,-al -Wno-unused -Werror \
-fno-common -fno-strict-aliasing -I$(INCDIR) -I$(COMMONDIR)
#Archiver [makes .a files]
AR=ee-ar
ARFLAGS=rs
#here you can set the malloc/calloc/free functions you want
XMALLOC=malloc
XCALLOC=calloc
XFREE=free
#you can redefine the clock
XCLOCK=TIMER_clock
XCLOCKS_PER_SEC=576000
#Compilation flags. Note the += does not write over the user's CFLAGS!
CFLAGS += -c -I./ -Wall -Wsign-compare -W -Wno-unused -Werror \
-DXMALLOC=$(XMALLOC) -DXCALLOC=$(XCALLOC) -DXFREE=$(XFREE) -DXCLOCK=$(XCLOCK) \
-DXCLOCKS_PER_SEC=$(XCLOCKS_PER_SEC)
#no file support, when defined the library will not have any functions that can read/write files
#(comment out to have file support)
CFLAGS += -DNO_FILE
#optimize for SPEED (comment out SIZE line as well)
#CFLAGS += -O3 -fomit-frame-pointer -funroll-loops
#optimize for SIZE (comment out SPEED line as well)
CFLAGS += -O2
#These flags control how the library gets built.
# Clean the stack after sensitive functions. Not always required...
# With this defined most of the ciphers and hashes will clean their stack area
# after usage with a (sometimes) huge penalty in speed. Normally this is not
# required if you simply lock your stack and wipe it when your program is done.
#
#CFLAGS += -DCLEAN_STACK
# What algorithms to include? comment out and rebuild to remove em
CFLAGS += -DBLOWFISH
CFLAGS += -DRC2
#CFLAGS += -DRC5
#CFLAGS += -DRC6
CFLAGS += -DSERPENT
CFLAGS += -DSAFERP
CFLAGS += -DSAFER
CFLAGS += -DRIJNDAEL
CFLAGS += -DXTEA
CFLAGS += -DTWOFISH
CFLAGS += -DDES
CFLAGS += -DCAST5
#You can also customize the Twofish code. All four combinations
#of the flags are possible but only three of them make sense.
#
#Both undefined: Very fast, requires ~4.2KB of ram per scheduled key
#Both defined : Slow, requires only ~100 bytes of ram per scheduled key
#
#If defined on their own
#_SMALL defined: Very Slow, small code only ~100 bytes of ram
#_TABLES defined: Very fast, not faster than if both were undefined. Code is ~1KB bigger
# faster keysetup though...
# Small Ram Variant of Twofish. For this you must have TWOFISH defined. This
# variant requires about 4kb less memory but is considerably slower. It is ideal
# when high throughput is less important than conserving memory. By default it is
# not defined which means the larger ram (about 4.2Kb used) variant is built.
# CFLAGS += -DTWOFISH_SMALL
# Tell Twofish to use precomputed tables. If you want to use the small table
# variant of Twofish you may want to turn this on. Essentially it tells Twofish to use
# precomputed S-boxes (Q0 and Q1) as well as precomputed GF multiplications [in the MDS].
# This speeds up the cipher somewhat.
# CFLAGS += -DTWOFISH_TABLES
#Small code variant of the SAFER+ cipher, uses same RAM but less code space
#With this defined the cipher is slower. On my x86 with GCC 3.2 it required 50KB less space
CFLAGS += -DSAFERP_SMALL
#Small Rijndael [saves 13KB on an x86]
#With this defined the cipher is slower (by 50Mbit/sec on an Athon XP)
CFLAGS += -DRIJNDAEL_SMALL
#Use fast PK routines. Basically this limits the size of the private key in the
#DH system to 256 bits. The group order remains unchanged so the best
#attacks are still GNFS (for DH upto 2560-bits)
#
#This will only speed up the key generation and encryption routines. It lowers the
#security so its by default not turned on. USE AT YOUR RISK!
#CFLAGS += -DFAST_PK
#Include the PK Packet functions (e.g. dh_encrypt)
#Does not affect the key/hash routines (e.g. ecc_sign_hash)
#CFLAGS += -DPK_PACKET
# Chaining modes
CFLAGS += -DCFB
CFLAGS += -DOFB
CFLAGS += -DECB
CFLAGS += -DCBC
CFLAGS += -DCTR
#One-way hashes
CFLAGS += -DSHA512
CFLAGS += -DSHA384
CFLAGS += -DSHA256
CFLAGS += -DTIGER
CFLAGS += -DSHA1
CFLAGS += -DMD5
CFLAGS += -DMD4
CFLAGS += -DMD2
# base64
CFLAGS += -DBASE64
# prngs
CFLAGS += -DYARROW
CFLAGS += -DSPRNG
CFLAGS += -DRC4
# PK code
CFLAGS += -DMRSA
CFLAGS += -DMDH
CFLAGS += -DMECC
CFLAGS += -DKR
# include GF math routines? (not currently used by anything internally)
#CFLAGS += -DGF
# include large integer math routines? (required by the PK code)
CFLAGS += -DMPI
# Use a small prime table? It greatly reduces the size of prime.c at a little impact
# in speed.
#
CFLAGS += -DSMALL_PRIME_TAB
# include HMAC support
CFLAGS += -DHMAC
# Have /dev/random or /dev/urandom?
#CFLAGS += -DDEVRANDOM
#Output filenames for various targets.
LIBNAME=libtomcrypt.a
TEST=test$(EXT)
HASH=hashsum$(EXT)
CRYPT=encrypt$(EXT)
SMALL=small$(EXT)
#LIBPATH-The directory for libtomcrypt to be installed to.
#INCPATH-The directory to install the header files for libtomcrypt.
LIBPATH=/usr/lib
INCPATH=/usr/include
#List of objects to compile.
OBJECTS=keyring.o gf.o mem.o sprng.o ecc.o base64.o dh.o rsa.o \
bits.o yarrow.o cfb.o ofb.o ecb.o ctr.o cbc.o hash.o tiger.o sha1.o \
md5.o md4.o md2.o sha256.o sha512.o xtea.o aes.o serpent.o des.o \
safer_tab.o safer.o safer+.o rc4.o rc2.o rc6.o rc5.o cast5.o blowfish.o crypt.o \
ampi.o mpi.o prime.o twofish.o packet.o hmac.o strings.o
# PlayStation(tm) 2 C run-time startup module
PS2CRT0=crt0.o
TESTOBJECTS=$(PS2CRT0) demos/test.o demos/timer.o
HASHOBJECTS=$(PS2CRT0) demos/hashsum.o
CRYPTOBJECTS=$(PS2CRT0) demos/encrypt.o
SMALLOBJECTS=$(PS2CRT0) demos/small.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=mpi-types.h mpi-config.h mpi.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
#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
sha512.o: sha512.c sha384.c
#This rule makes the libtomcrypt library.
library: $(OBJECTS)
$(AR) $(ARFLAGS) $(LIBNAME) $(OBJECTS)
#This rule makes the test program included with libtomcrypt
test: library $(TESTOBJECTS)
$(CC) -o $(TEST) -T $(LCFILE) $(LDFLAGS) $(TESTOBJECTS) $(LIBNAME)
#This rule makes the hash program included with libtomcrypt
hashsum: library $(HASHOBJECTS)
$(CC) -o $(HASH) -T $(LCFILE) $(LDFLAGS) $(HASHOBJECTS) $(LIBNAME)
#makes the crypt program
crypt: library $(CRYPTOBJECTS)
$(CC) -o $(CRYPT) -T $(LCFILE) $(LDFLAGS) $(CRYPTOBJECTS) $(LIBNAME)
#makes the small program
small: library $(SMALLOBJECTS)
$(CC) -o $(SMALL) -T $(LCFILE) $(LDFLAGS) $(SMALLOBJECTS) $(LIBNAME)
# makes the PlayStation(tm) 2 CRT 0 module
$(PS2CRT0): $(LIBDIR)/crt0.s
$(AS) $(ASFLAGS) $(TMPFLAGS) -o $@ $< > $*.lst
#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 -g root -o root $(LIBNAME) $(LIBPATH)
install -g root -o root $(HEADERS) $(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)
rm -f *stackdump *.lib *.exe *.obj demos/*.obj zlib/*.obj
rm -f *.o *.lst demos/*.o demos/*.lst
#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
rm -f $(LEFTOVERS)
latex crypt > /dev/null
makeindex crypt > /dev/null
pdflatex crypt > /dev/null
rm -f $(LEFTOVERS)
#This used to be the zipup target. I have split it into two seperate targets:
#bz and zip. bz builds a crypt.tar.bz2 package, while zip builds a crypt.zip
#package. I have removed the dos2unix commands, as this is a Linux makefile,
#and these should not be needed. I also made it output the target to the
#current directory instead of the root (/) directory. (Bad Tom!) We are
#almost assured write permission in the current directory, but not in the root
#directory. This means any user can now build a BZ image or a zip.
#NOTE: This removes all pre-built compressed archives during clean.
bz: clean docs
chdir .. ; rm -f crypt.tar.bz2 ; tar -c libtomcrypt/* > crypt.tar ; bzip2 -9v crypt.tar
zip: clean docs
chdir .. ; rm -f crypt.zip ; zip -9 -r crypt.zip libtomcrypt/*
#Makes a tar/gz archive of the library.
gz: clean docs
chdir .. ; rm -f crypt.tar.gz ; tar -c libtomcrypt/* > crypt.tar ; gzip -9v crypt.tar
#makes a tar/SZIP archive [slightly better than bzip2]
szip: clean docs
chdir .. ; rm -f crypt.tar.szp ; tar -c libtomcrypt/* > crypt.tar ; szip -b41o64v255 crypt.tar crypt.tar.szp
.c.o:
$(CC) $(CFLAGS) $(TMPFLAGS) -c $< -o $*.o > $*.lst

254
makefile.vc Normal file
View File

@ -0,0 +1,254 @@
# MAKEFILE for MSVC 6.0 SP5
#
# Tom St Denis, tomstdenis@yahoo.com
#
CC=cl
AR=lib
#here you can set the malloc/calloc/free functions you want
XMALLOC=malloc
XCALLOC=calloc
XFREE=free
#you can redefine the clock
XCLOCK=clock
XCLOCKS_PER_SEC=CLOCKS_PER_SEC
CFLAGS = /c /Ogisy1 /Gs /I. /W3 /DWIN32 /DXMALLOC=$(XMALLOC) /DXCALLOC=$(XCALLOC) /DXFREE=$(XFREE) /DXCLOCK=$(XCLOCK) /DXCLOCKS_PER_SEC=$(XCLOCKS_PER_SEC)
#These flags control how the library gets built.
#no file support, when defined the library will not have any functions that can read/write files
#(comment out to have file support)
#CFLAGS += /DNO_FILE
#Support the UNIX /dev/random or /dev/urandom
#CFLAGS += /DDEVRANDOM
# Use /dev/urandom first on devices where /dev/random is too slow */
#CFLAGS += /DTRY_URANDOM_FIRST
# Clean the stack after sensitive functions. Not always required...
# With this defined most of the ciphers and hashes will clean their stack area
# after usage with a (sometimes) huge penalty in speed. Normally this is not
# required if you simply lock your stack and wipe it when your program is done.
#
#CFLAGS += /DCLEAN_STACK
# What algorithms to include? comment out and rebuild to remove em
CFLAGS += /DBLOWFISH
CFLAGS += /DRC2
CFLAGS += /DRC5
CFLAGS += /DRC6
CFLAGS += /DSERPENT
CFLAGS += /DSAFERP
CFLAGS += /DSAFER
CFLAGS += /DRIJNDAEL
CFLAGS += /DXTEA
CFLAGS += /DTWOFISH
CFLAGS += /DDES
CFLAGS += /DCAST5
#You can also customize the Twofish code. All four combinations
#of the flags are possible but only three of them make sense.
#
#Both undefined: Very fast, requires ~4.2KB of ram per scheduled key
#Both defined : Slow, requires only ~100 bytes of ram per scheduled key
#
#If defined on their own
#_SMALL defined: Very Slow, small code only ~100 bytes of ram
#_TABLES defined: Very fast, not faster than if both were undefined. Code is ~1KB bigger
# faster keysetup though...
# Small Ram Variant of Twofish. For this you must have TWOFISH defined. This
# variant requires about 4kb less memory but is considerably slower. It is ideal
# when high throughput is less important than conserving memory. By default it is
# not defined which means the larger ram (about 4.2Kb used) variant is built.
# CFLAGS += /DTWOFISH_SMALL
# Tell Twofish to use precomputed tables. If you want to use the small table
# variant of Twofish you may want to turn this on. Essentially it tells Twofish to use
# precomputed S-boxes (Q0 and Q1) as well as precomputed GF multiplications [in the MDS].
# This speeds up the cipher somewhat.
# CFLAGS += /DTWOFISH_TABLES
#Small code variant of the SAFER+ cipher, uses same RAM but less code space
#With this defined the cipher is slower. On my x86 with GCC 3.2 it required 50KB less space
CFLAGS += /DSAFERP_SMALL
#Small Rijndael [saves 13KB on an x86]
#With this defined the cipher is slower (by 50Mbit/sec on an Athon XP)
CFLAGS += /DRIJNDAEL_SMALL
#Use fast PK routines. Basically this limits the size of the private key in the
#DH system to 256 bits. The group order remains unchanged so the best
#attacks are still GNFS (for DH upto 2560-bits)
#
#This will only speed up the key generation and encryption routines. It lowers the
#security so its by default not turned on. USE AT YOUR RISK!
#CFLAGS += /DFAST_PK
#Include the PK Packet functions (e.g. dh_encrypt)
#Does not affect the key/hash routines (e.g. ecc_sign_hash)
#CFLAGS += /DPK_PACKET
# Chaining modes
CFLAGS += /DCFB
CFLAGS += /DOFB
CFLAGS += /DECB
CFLAGS += /DCBC
CFLAGS += /DCTR
#One-way hashes
CFLAGS += /DSHA512
CFLAGS += /DSHA384
CFLAGS += /DSHA256
CFLAGS += /DTIGER
CFLAGS += /DSHA1
CFLAGS += /DMD5
CFLAGS += /DMD4
CFLAGS += /DMD2
# base64
CFLAGS += /DBASE64
# prngs
CFLAGS += /DYARROW
CFLAGS += /DSPRNG
CFLAGS += /DRC4
# PK code
CFLAGS += /DMRSA
CFLAGS += /DMDH
CFLAGS += /DMECC
CFLAGS += /DKR
# include GF math routines? (not currently used by anything internally)
#CFLAGS += /DGF
# include large integer math routines? (required by the PK code)
CFLAGS += /DMPI
# Use a small prime table? It greatly reduces the size of prime.c at a little impact
# in speed.
#
CFLAGS += /DSMALL_PRIME_TAB
# include HMAC support
CFLAGS += /DHMAC
default: tomcrypt.lib
keyring.obj: keyring.c
$(CC) $(CFLAGS) keyring.c
ampi.obj: ampi.c
$(CC) $(CFLAGS) ampi.c
mpi.obj: mpi.c
$(CC) $(CFLAGS) mpi.c
blowfish.obj: blowfish.c
$(CC) $(CFLAGS) blowfish.c
crypt.obj: crypt.c
$(CC) $(CFLAGS) crypt.c
sha512.obj: sha512.c sha384.c
$(CC) $(CFLAGS) sha512.c
sha256.obj: sha256.c
$(CC) $(CFLAGS) sha256.c
hash.obj: hash.c
$(CC) $(CFLAGS) hash.c
md5.obj: md5.c
$(CC) $(CFLAGS) md5.c
md4.obj: md4.c
$(CC) $(CFLAGS) md4.c
sha1.obj: sha1.c
$(CC) $(CFLAGS) sha1.c
cfb.obj: cfb.c
$(CC) $(CFLAGS) cfb.c
ofb.obj: ofb.c
$(CC) $(CFLAGS) ofb.c
ecb.obj: ecb.c
$(CC) $(CFLAGS) ecb.c
ctr.obj: ctr.c
$(CC) $(CFLAGS) ctr.c
prime.obj: prime.c
$(CC) $(CFLAGS) prime.c
base64.obj: base64.c
$(CC) $(CFLAGS) base64.c
sprng.obj: sprng.c
$(CC) $(CFLAGS) sprng.c
mem.obj: mem.c
$(CC) $(CFLAGS) mem.c
gf.obj: gf.c
$(CC) $(CFLAGS) gf.c
ecc.obj: ecc.c ecc_sys.c
$(CC) $(CFLAGS) ecc.c
yarrow.obj: yarrow.c
$(CC) $(CFLAGS) yarrow.c
bits.obj: bits.c
$(CC) $(CFLAGS) bits.c
rsa.obj: rsa.c
$(CC) $(CFLAGS) rsa.c
rc6.obj: rc6.c
$(CC) $(CFLAGS) rc6.c
des.obj: des.c
$(CC) $(CFLAGS) des.c
tiger.obj: tiger.c
$(CC) $(CFLAGS) tiger.c
dh.obj: dh.c dh_sys.c
$(CC) $(CFLAGS) dh.c
serpent.obj: serpent.c
$(CC) $(CFLAGS) serpent.c
aes.obj: aes.c aes_tab.c
$(CC) $(CFLAGS) aes.c
rc5.obj: rc5.c
$(CC) $(CFLAGS) rc5.c
rc2.obj: rc2.c
$(CC) $(CFLAGS) rc2.c
cbc.obj: cbc.c
$(CC) $(CFLAGS) cbc.c
safer+.obj: safer+.c
$(CC) $(CFLAGS) safer+.c
safer.obj: safer.c
$(CC) $(CFLAGS) safer.c
safer_tab.obj: safer_tab.c
$(CC) $(CFLAGS) safer_tab.c
xtea.obj: xtea.c
$(CC) $(CFLAGS) xtea.c
twofish.obj: twofish.c
$(CC) $(CFLAGS) twofish.c
packet.obj: packet.c
$(CC) $(CFLAGS) packet.c
pack.obj: pack.c
$(CC) $(CFLAGS) pack.c
hmac.obj: hmac.c
$(CC) $(CFLAGS) hmac.c
strings.obj: strings.c
$(CC) $(CFLAGS) strings.c
md2.obj: md2.c
$(CC) $(CFLAGS) md2.c
cast5.obj: cast5.c
$(CC) $(CFLAGS) cast5.c
demos/test.obj: demos/test.c
$(CC) $(CFLAGS) demos/test.c
demos/hashsum.obj: demos/hashsum.c
$(CC) $(CFLAGS) demos/hashsum.c
tomcrypt.lib: keyring.obj gf.obj mem.obj sprng.obj ecc.obj base64.obj dh.obj rsa.obj bits.obj hmac.obj \
yarrow.obj cfb.obj ofb.obj ecb.obj ctr.obj cbc.obj hash.obj tiger.obj sha1.obj md2.obj md5.obj md4.obj sha256.obj sha512.obj xtea.obj \
aes.obj serpent.obj safer_tab.obj safer.obj safer+.obj cast5.obj rc2.obj rc6.obj rc5.obj des.obj blowfish.obj crypt.obj ampi.obj \
strings.obj mpi.obj prime.obj twofish.obj packet.obj
$(AR) /out:tomcrypt.lib keyring.obj gf.obj mem.obj sprng.obj ecc.obj base64.obj dh.obj rsa.obj hmac.obj \
bits.obj yarrow.obj cfb.obj ofb.obj ecb.obj ctr.obj cbc.obj hash.obj tiger.obj sha1.obj md2.obj md5.obj md4.obj sha256.obj \
strings.obj sha512.obj xtea.obj aes.obj serpent.obj safer_tab.obj safer.obj safer+.obj cast5.obj rc2.obj rc6.obj rc5.obj des.obj \
blowfish.obj crypt.obj ampi.obj mpi.obj prime.obj twofish.obj packet.obj
test.exe: tomcrypt.lib demos/test.obj
link /OUT:test.exe test.obj tomcrypt.lib advapi32.lib
hashsum.exe: tomcrypt.lib demos/hashsum.obj
link /OUT:hashsum.exe hashsum.obj tomcrypt.lib advapi32.lib
clean:
rm -f demos/*.obj *.obj *.exe *.lib

203
md2.c Normal file
View File

@ -0,0 +1,203 @@
/* 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[md->md2.buf[j] ^ L]);
}
}
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 = 0;
/* do 18 rounds */
for (j = 0; j < 18; j++) {
for (k = 0; k < 48; k++) {
t = (md->md2.X[k] ^= PI_SUBST[t]);
}
t = (t + 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;
}
void md2_process(hash_state *md, const unsigned char *buf, unsigned long len)
{
unsigned long n;
_ARGCHK(md != NULL);
_ARGCHK(buf != NULL);
while (len) {
n = MIN(len, (16 - md->md2.curlen));
memcpy(md->md2.buf + md->md2.curlen, buf, 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;
}
}
}
void md2_done(hash_state * md, unsigned char *hash)
{
int i, k;
_ARGCHK(md != NULL);
_ARGCHK(hash != NULL);
/* pad the message */
k = 16 - md->md2.curlen;
for (i = md->md2.curlen; i < 16; i++) {
md->md2.buf[i] = 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
}
int md2_test(void)
{
static const struct {
unsigned 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, tests[i].msg, strlen(tests[i].msg));
md2_done(&md, buf);
if (memcmp(buf, tests[i].md, 16)) {
#if 0
int j;
printf("\n\nFailed test %d\n\n", i);
for (j = 0; j < 16; j++) {
printf("%02x ", buf[j]);
}
printf("\n");
printf("Should have been\n");
for (j = 0; j < 16; j++) {
printf("%02x ", tests[i].md[j]);
}
printf("\n");
#endif
return CRYPT_FAIL_TESTVECTOR;
}
}
return CRYPT_OK;
}
#endif

290
md4.c Normal file
View File

@ -0,0 +1,290 @@
/* 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) (((x) & (y)) | ((~x) & (z)))
#define G(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z)))
#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)
#else
static void md4_compress(hash_state *md)
#endif
{
unsigned long x[16], a, b, c, d;
int i;
_ARGCHK(md != NULL);
/* 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], md->md4.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)
{
_md4_compress(md);
burn_stack(sizeof(unsigned long) * 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;
}
void md4_process(hash_state * md, const unsigned char *buf, unsigned long len)
{
unsigned long n;
_ARGCHK(md != NULL);
_ARGCHK(buf != NULL);
while (len) {
n = MIN(len, (64 - md->md4.curlen));
memcpy(md->md4.buf + md->md4.curlen, buf, n);
md->md4.curlen += n;
buf += n;
len -= n;
/* is 64 bytes full? */
if (md->md4.curlen == 64) {
md4_compress(md);
md->md4.length += 512;
md->md4.curlen = 0;
}
}
}
void md4_done(hash_state * md, unsigned char *hash)
{
int i;
_ARGCHK(md != NULL);
_ARGCHK(hash != NULL);
/* increase the length of the message */
md->md4.length += md->md4.curlen * 8;
/* append the '1' bit */
md->md4.buf[md->md4.curlen++] = 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++] = 0;
}
md4_compress(md);
md->md4.curlen = 0;
}
/* pad upto 56 bytes of zeroes */
while (md->md4.curlen < 56) {
md->md4.buf[md->md4.curlen++] = 0;
}
/* store length */
STORE64L(md->md4.length, md->md4.buf+56);
md4_compress(md);
/* 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
}
int md4_test(void)
{
static const struct md4_test_case {
int num;
unsigned char input[128];
int inputlen;
unsigned char digest[16];
} cases[] = {
{ 1, "", 0,
{0x31, 0xd6, 0xcf, 0xe0, 0xd1, 0x6a, 0xe9, 0x31,
0xb7, 0x3c, 0x59, 0xd7, 0xe0, 0xc0, 0x89, 0xc0} },
{ 2, "a", 1,
{0xbd, 0xe5, 0x2c, 0xb3, 0x1d, 0xe3, 0x3e, 0x46,
0x24, 0x5e, 0x05, 0xfb, 0xdb, 0xd6, 0xfb, 0x24} },
{ 3, "abc", 3,
{0xa4, 0x48, 0x01, 0x7a, 0xaf, 0x21, 0xd8, 0x52,
0x5f, 0xc1, 0x0a, 0xe8, 0x7a, 0xa6, 0x72, 0x9d} },
{ 4, "message digest", 14,
{0xd9, 0x13, 0x0a, 0x81, 0x64, 0x54, 0x9f, 0xe8,
0x18, 0x87, 0x48, 0x06, 0xe1, 0xc7, 0x01, 0x4b} },
{ 5, "abcdefghijklmnopqrstuvwxyz", 26,
{0xd7, 0x9e, 0x1c, 0x30, 0x8a, 0xa5, 0xbb, 0xcd,
0xee, 0xa8, 0xed, 0x63, 0xdf, 0x41, 0x2d, 0xa9} },
{ 6, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", 62,
{0x04, 0x3f, 0x85, 0x82, 0xf2, 0x41, 0xdb, 0x35,
0x1c, 0xe6, 0x27, 0xe1, 0x53, 0xe7, 0xf0, 0xe4} },
{ 7, "12345678901234567890123456789012345678901234567890123456789012345678901234567890", 80,
{0xe3, 0x3b, 0x4d, 0xdc, 0x9c, 0x38, 0xf2, 0x19,
0x9c, 0x3e, 0x7b, 0x16, 0x4f, 0xcc, 0x05, 0x36} },
};
int i, failed;
hash_state md;
unsigned char digest[16];
failed = 0;
for(i = 0; i < (int)(sizeof(cases) / sizeof(cases[0])); i++) {
md4_init(&md);
md4_process(&md, cases[i].input, cases[i].inputlen);
md4_done(&md, digest);
if(memcmp(digest, cases[i].digest, 16) != 0) {
#if 0
int j;
printf("\nMD4 test #%d failed\n", cases[i].num);
printf( "Result: 0x");
for(j=0; j < 16; j++) {
printf("%2x", digest[j]);
}
printf("\nCorrect: 0x");
for(j=0; j < 16; j++) {
printf("%2x", cases[i].digest[j]);
}
printf("\n");
#endif
failed++;
} else {
/* printf("MD4 test #%d succeeded.\n", cases[i].num); */
}
}
if (failed) {
return CRYPT_FAIL_TESTVECTOR;
}
return CRYPT_OK;
}
#endif

268
md5.c Normal file
View File

@ -0,0 +1,268 @@
#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) ( (x&y)|((~x)&z) )
#define G(x,y,z) ( (x&z)|(y&(~z)) )
#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); a = (b + a);
#define GG(a,b,c,d,M,s,t) \
a = (a + G(b,c,d) + M + t); a = ROL(a, s); a = (b + a);
#define HH(a,b,c,d,M,s,t) \
a = (a + H(b,c,d) + M + t); a = ROL(a, s); a = (b + a);
#define II(a,b,c,d,M,s,t) \
a = (a + I(b,c,d) + M + t); a = ROL(a, s); a = (b + a);
#ifdef CLEAN_STACK
static void _md5_compress(hash_state *md)
#else
static void md5_compress(hash_state *md)
#endif
{
unsigned long i, W[16], a, b, c, d;
_ARGCHK(md != NULL);
/* copy the state into 512-bits into W[0..15] */
for (i = 0; i < 16; i++) {
LOAD32L(W[i], md->md5.buf + (4*i));
}
/* 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)
{
_md5_compress(md);
burn_stack(sizeof(unsigned long) * 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;
}
void md5_process(hash_state * md, const unsigned char *buf, unsigned long len)
{
unsigned long n;
_ARGCHK(md != NULL);
_ARGCHK(buf != NULL);
while (len) {
n = MIN(len, (64 - md->md5.curlen));
memcpy(md->md5.buf + md->md5.curlen, buf, n);
md->md5.curlen += n;
buf += n;
len -= n;
/* is 64 bytes full? */
if (md->md5.curlen == 64) {
md5_compress(md);
md->md5.length += 512;
md->md5.curlen = 0;
}
}
}
void md5_done(hash_state * md, unsigned char *hash)
{
int i;
_ARGCHK(md != NULL);
_ARGCHK(hash != NULL);
/* increase the length of the message */
md->md5.length += md->md5.curlen * 8;
/* append the '1' bit */
md->md5.buf[md->md5.curlen++] = 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++] = 0;
}
md5_compress(md);
md->md5.curlen = 0;
}
/* pad upto 56 bytes of zeroes */
while (md->md5.curlen < 56) {
md->md5.buf[md->md5.curlen++] = 0;
}
/* store length */
STORE64L(md->md5.length, md->md5.buf+56);
md5_compress(md);
/* 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
}
int md5_test(void)
{
static const struct {
unsigned 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 failed, i;
unsigned char tmp[16];
hash_state md;
for (failed = i = 0; tests[i].msg != NULL; i++) {
md5_init(&md);
md5_process(&md, tests[i].msg, strlen(tests[i].msg));
md5_done(&md, tmp);
if (memcmp(tmp, tests[i].hash, 16)) {
#if 0
int j;
printf("MD5 Test %d (len == %d) failed\nGot (as a result): ", i, strlen(tests[i].msg));
for (j = 0; j < 16; j++) {
printf("%02x ", tmp[j]);
}
printf("\n");
#endif
failed = 1;
}
}
if (failed == 1) {
return CRYPT_FAIL_TESTVECTOR;
} else {
return CRYPT_OK;
}
}
#endif

19
mem.c Normal file
View File

@ -0,0 +1,19 @@
#include "mycrypt.h"
void zeromem(void *dst, unsigned long len)
{
unsigned char *mem = (unsigned char *)dst;
_ARGCHK(dst != NULL);
while (len--)
*mem++ = 0;
}
void burn_stack(unsigned long len)
{
unsigned char buf[32];
zeromem(buf, sizeof(buf));
if (len > sizeof(buf))
burn_stack(len - sizeof(buf));
}

87
mpi-config.h Normal file
View File

@ -0,0 +1,87 @@
/* Default configuration for MPI library */
/* $ID$ */
#ifndef MPI_CONFIG_H_
#define MPI_CONFIG_H_
/*
For boolean options,
0 = no
1 = yes
Other options are documented individually.
*/
#ifndef MP_IOFUNC
#define MP_IOFUNC 1 /* include mp_print() ? */
#endif
#ifndef MP_MODARITH
#define MP_MODARITH 1 /* include modular arithmetic ? */
#endif
#ifndef MP_NUMTH
#define MP_NUMTH 1 /* include number theoretic functions? */
#endif
#ifndef MP_LOGTAB
#define MP_LOGTAB 1 /* use table of logs instead of log()? */
#endif
#ifndef MP_MEMSET
#define MP_MEMSET 1 /* use memset() to zero buffers? */
#endif
#ifndef MP_MEMCPY
#define MP_MEMCPY 1 /* use memcpy() to copy buffers? */
#endif
#ifndef MP_CRYPTO
#define MP_CRYPTO 1 /* erase memory on free? */
#endif
#ifndef MP_ARGCHK
/*
0 = no parameter checks
1 = runtime checks, continue execution and return an error to caller
2 = assertions; dump core on parameter errors
*/
#define MP_ARGCHK 1 /* how to check input arguments */
#endif
#ifndef MP_DEBUG
#define MP_DEBUG 0 /* print diagnostic output? */
#endif
#ifndef MP_DEFPREC
#define MP_DEFPREC 8 /* default precision, in digits */
#endif
#ifndef MP_MACRO
#define MP_MACRO 1 /* use macros for frequent calls? */
#endif
#ifndef MP_SQUARE
#define MP_SQUARE 1 /* use separate squaring code? */
#endif
#ifndef MP_PTAB_SIZE
/*
When building mpprime.c, we build in a table of small prime
values to use for primality testing. The more you include,
the more space they take up. See primes.c for the possible
values (currently 16, 32, 64, 128, 256, and 6542)
*/
#define MP_PTAB_SIZE 128 /* how many built-in primes? */
#endif
#ifndef MP_COMPAT_MACROS
#define MP_COMPAT_MACROS 1 /* define compatibility macros? */
#endif
#endif /* ifndef MPI_CONFIG_H_ */

16
mpi-types.h Normal file
View File

@ -0,0 +1,16 @@
/* Type definitions generated by 'types.pl' */
typedef char mp_sign;
typedef unsigned short mp_digit; /* 2 byte type */
typedef unsigned int mp_word; /* 4 byte type */
typedef unsigned int mp_size;
typedef int mp_err;
#define MP_DIGIT_BIT (CHAR_BIT*sizeof(mp_digit))
#define MP_DIGIT_MAX USHRT_MAX
#define MP_WORD_BIT (CHAR_BIT*sizeof(mp_word))
#define MP_WORD_MAX UINT_MAX
#define MP_DIGIT_SIZE 2
#define DIGIT_FMT "%04X"
#define RADIX (MP_DIGIT_MAX+1)

4009
mpi.c Normal file

File diff suppressed because it is too large Load Diff

225
mpi.h Normal file
View File

@ -0,0 +1,225 @@
/*
mpi.h
by Michael J. Fromberger <sting@linguist.dartmouth.edu>
Copyright (C) 1998 Michael J. Fromberger, All Rights Reserved
Arbitrary precision integer arithmetic library
$ID$
*/
#ifndef _H_MPI_
#define _H_MPI_
#include "mpi-config.h"
#define MP_LT -1
#define MP_EQ 0
#define MP_GT 1
#if MP_DEBUG
#undef MP_IOFUNC
#define MP_IOFUNC 1
#endif
#if MP_IOFUNC
#include <stdio.h>
#include <ctype.h>
#endif
#include <limits.h>
#define MP_NEG 1
#define MP_ZPOS 0
/* Included for compatibility... */
#define NEG MP_NEG
#define ZPOS MP_ZPOS
#define MP_OKAY 0 /* no error, all is well */
#define MP_YES 0 /* yes (boolean result) */
#define MP_NO -1 /* no (boolean result) */
#define MP_MEM -2 /* out of memory */
#define MP_RANGE -3 /* argument out of range */
#define MP_BADARG -4 /* invalid parameter */
#define MP_UNDEF -5 /* answer is undefined */
#define MP_LAST_CODE MP_UNDEF
#include "mpi-types.h"
/* Included for compatibility... */
#define DIGIT_BIT MP_DIGIT_BIT
#define DIGIT_MAX MP_DIGIT_MAX
/* Macros for accessing the mp_int internals */
#define SIGN(MP) ((MP)->sign)
#define USED(MP) ((MP)->used)
#define ALLOC(MP) ((MP)->alloc)
#define DIGITS(MP) ((MP)->dp)
#define DIGIT(MP,N) (MP)->dp[(N)]
#if MP_ARGCHK == 1
#define ARGCHK(X,Y) {if(!(X)){return (Y);}}
#elif MP_ARGCHK == 2
#include <assert.h>
#define ARGCHK(X,Y) assert(X)
#else
#define ARGCHK(X,Y) /* */
#endif
/* This defines the maximum I/O base (minimum is 2) */
#define MAX_RADIX 64
typedef struct {
mp_sign sign; /* sign of this quantity */
mp_size alloc; /* how many digits allocated */
mp_size used; /* how many digits used */
mp_digit *dp; /* the digits themselves */
} mp_int;
/*------------------------------------------------------------------------*/
/* Default precision */
unsigned int mp_get_prec(void);
void mp_set_prec(unsigned int prec);
/*------------------------------------------------------------------------*/
/* Memory management */
mp_err mp_init(mp_int *mp);
mp_err mp_init_array(mp_int mp[], int count);
mp_err mp_init_size(mp_int *mp, mp_size prec);
mp_err mp_init_copy(mp_int *mp, mp_int *from);
mp_err mp_copy(mp_int *from, mp_int *to);
void mp_exch(mp_int *mp1, mp_int *mp2);
void mp_clear(mp_int *mp);
void mp_clear_array(mp_int mp[], int count);
void mp_zero(mp_int *mp);
void mp_set(mp_int *mp, mp_digit d);
mp_err mp_set_int(mp_int *mp, long z);
/*------------------------------------------------------------------------*/
/* Single digit arithmetic */
mp_err mp_add_d(mp_int *a, mp_digit d, mp_int *b);
mp_err mp_sub_d(mp_int *a, mp_digit d, mp_int *b);
mp_err mp_mul_d(mp_int *a, mp_digit d, mp_int *b);
mp_err mp_mul_2(mp_int *a, mp_int *c);
mp_err mp_div_d(mp_int *a, mp_digit d, mp_int *q, mp_digit *r);
mp_err mp_div_2(mp_int *a, mp_int *c);
mp_err mp_expt_d(mp_int *a, mp_digit d, mp_int *c);
/*------------------------------------------------------------------------*/
/* Sign manipulations */
mp_err mp_abs(mp_int *a, mp_int *b);
mp_err mp_neg(mp_int *a, mp_int *b);
/*------------------------------------------------------------------------*/
/* Full arithmetic */
mp_err mp_add(mp_int *a, mp_int *b, mp_int *c);
mp_err mp_sub(mp_int *a, mp_int *b, mp_int *c);
mp_err mp_mul(mp_int *a, mp_int *b, mp_int *c);
mp_err mp_mul_2d(mp_int *a, mp_digit d, mp_int *c);
#if MP_SQUARE
mp_err mp_sqr(mp_int *a, mp_int *b);
#else
#define mp_sqr(a, b) mp_mul(a, a, b)
#endif
mp_err mp_div(mp_int *a, mp_int *b, mp_int *q, mp_int *r);
mp_err mp_div_2d(mp_int *a, mp_digit d, mp_int *q, mp_int *r);
mp_err mp_expt(mp_int *a, mp_int *b, mp_int *c);
mp_err mp_2expt(mp_int *a, mp_digit k);
mp_err mp_sqrt(mp_int *a, mp_int *b);
/*------------------------------------------------------------------------*/
/* Modular arithmetic */
#if MP_MODARITH
mp_err mp_mod(mp_int *a, mp_int *m, mp_int *c);
mp_err mp_mod_d(mp_int *a, mp_digit d, mp_digit *c);
mp_err mp_addmod(mp_int *a, mp_int *b, mp_int *m, mp_int *c);
mp_err mp_submod(mp_int *a, mp_int *b, mp_int *m, mp_int *c);
mp_err mp_mulmod(mp_int *a, mp_int *b, mp_int *m, mp_int *c);
#if MP_SQUARE
mp_err mp_sqrmod(mp_int *a, mp_int *m, mp_int *c);
#else
#define mp_sqrmod(a, m, c) mp_mulmod(a, a, m, c)
#endif
mp_err mp_exptmod(mp_int *a, mp_int *b, mp_int *m, mp_int *c);
mp_err mp_exptmod_d(mp_int *a, mp_digit d, mp_int *m, mp_int *c);
#endif /* MP_MODARITH */
/*------------------------------------------------------------------------*/
/* Comparisons */
int mp_cmp_z(mp_int *a);
int mp_cmp_d(mp_int *a, mp_digit d);
int mp_cmp(mp_int *a, mp_int *b);
int mp_cmp_mag(mp_int *a, mp_int *b);
int mp_cmp_int(mp_int *a, long z);
int mp_isodd(mp_int *a);
int mp_iseven(mp_int *a);
/*------------------------------------------------------------------------*/
/* Number theoretic */
#if MP_NUMTH
mp_err mp_gcd(mp_int *a, mp_int *b, mp_int *c);
mp_err mp_lcm(mp_int *a, mp_int *b, mp_int *c);
mp_err mp_xgcd(mp_int *a, mp_int *b, mp_int *g, mp_int *x, mp_int *y);
mp_err mp_invmod(mp_int *a, mp_int *m, mp_int *c);
#endif /* end MP_NUMTH */
/*------------------------------------------------------------------------*/
/* Input and output */
#if MP_IOFUNC
void mp_print(mp_int *mp, FILE *ofp);
#endif /* end MP_IOFUNC */
/*------------------------------------------------------------------------*/
/* Base conversion */
#define BITS 1
#define BYTES CHAR_BIT
mp_err mp_read_signed_bin(mp_int *mp, unsigned char *str, int len);
int mp_signed_bin_size(mp_int *mp);
mp_err mp_to_signed_bin(mp_int *mp, unsigned char *str);
mp_err mp_read_unsigned_bin(mp_int *mp, unsigned char *str, int len);
int mp_unsigned_bin_size(mp_int *mp);
mp_err mp_to_unsigned_bin(mp_int *mp, unsigned char *str);
int mp_count_bits(mp_int *mp);
#if MP_COMPAT_MACROS
#define mp_read_raw(mp, str, len) mp_read_signed_bin((mp), (str), (len))
#define mp_raw_size(mp) mp_signed_bin_size(mp)
#define mp_toraw(mp, str) mp_to_signed_bin((mp), (str))
#define mp_read_mag(mp, str, len) mp_read_unsigned_bin((mp), (str), (len))
#define mp_mag_size(mp) mp_unsigned_bin_size(mp)
#define mp_tomag(mp, str) mp_to_unsigned_bin((mp), (str))
#endif
mp_err mp_read_radix(mp_int *mp, unsigned char *str, int radix);
int mp_radix_size(mp_int *mp, int radix);
int mp_value_radix_size(int num, int qty, int radix);
mp_err mp_toradix(mp_int *mp, unsigned char *str, int radix);
int mp_char2value(char ch, int r);
#define mp_tobinary(M, S) mp_toradix((M), (S), 2)
#define mp_tooctal(M, S) mp_toradix((M), (S), 8)
#define mp_todecimal(M, S) mp_toradix((M), (S), 10)
#define mp_tohex(M, S) mp_toradix((M), (S), 16)
/*------------------------------------------------------------------------*/
/* Error strings */
const char *mp_strerror(mp_err ec);
#endif /* end _H_MPI_ */

75
mycrypt.h Normal file
View File

@ -0,0 +1,75 @@
#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>
#ifdef __cplusplus
extern "C" {
#endif
/* version */
#define CRYPT 0x0075
#define SCRYPT "0.75"
/* max size of either a cipher/hash block or symmetric key [largest of the two] */
#define MAXBLOCKSIZE 128
/* error codes [will be expanded in future releases] */
enum {
CRYPT_OK=0,
CRYPT_ERROR,
CRYPT_INVALID_KEYSIZE,
CRYPT_INVALID_ROUNDS,
CRYPT_FAIL_TESTVECTOR,
CRYPT_BUFFER_OVERFLOW,
CRYPT_INVALID_PACKET,
CRYPT_INVALID_PRNGSIZE,
CRYPT_ERROR_READPRNG,
CRYPT_INVALID_CIPHER,
CRYPT_INVALID_HASH,
CRYPT_INVALID_PRNG,
CRYPT_MEM,
CRYPT_PK_TYPE_MISMATCH,
CRYPT_PK_NOT_PRIVATE,
CRYPT_INVALID_ARG,
CRYPT_PK_INVALID_TYPE,
CRYPT_PK_INVALID_SYSTEM,
CRYPT_PK_DUP,
CRYPT_PK_NOT_FOUND,
CRYPT_PK_INVALID_SIZE,
CRYPT_INVALID_PRIME_SIZE
};
#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>
#ifdef __cplusplus
}
#endif
#endif /* CRYPT_H_ */

41
mycrypt_argchk.h Normal file
View File

@ -0,0 +1,41 @@
/* Defines the _ARGCHK macro used within the library */
/* ARGTYPE is defined in mycrypt_cfg.h */
#if ARGTYPE == 0
#include <signal.h>
/* this is the default LibTomCrypt macro
*
* On embedded platforms you can change the fprintf() to be a routine that would display a message
* somehow
*/
#ifndef SONY_PS2
#define _ARGCHK(x) \
if (!(x)) { \
fprintf(stderr, "_ARGCHK '%s' failure on line %d of file %s\n", #x, __LINE__, __FILE__); \
raise(SIGABRT); \
}
#else
#define _ARGCHK(x) \
if (!(x)) { \
printf("_ARGCHK '%s' failure on line %d of file %s\n", #x, __LINE__, __FILE__); \
raise(SIGABRT); \
}
#endif /* SONY_PS2 */
#elif ARGTYPE == 1
/* fatal type of error */
#define _ARGCHK(x) assert((x))
#elif ARGTYPE == 2
#define _ARGCHK(x)
#endif

122
mycrypt_cfg.h Normal file
View File

@ -0,0 +1,122 @@
/* 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 *XCALLOC(size_t n, size_t s);
extern void XFREE(void *p);
/* change the clock function too */
extern clock_t XCLOCK(void);
/* type of argument checking, 0=default, 1=fatal and 2=none */
#define ARGTYPE 0
/* Controls endianess and size of registers. Leave uncommented to get platform neutral [slower] code */
/* detect x86-32 machines somewhat */
#if (defined(_MSC_VER) && defined(WIN32)) || (defined(__GNUC__) && (defined(__DJGPP__) || defined(__CYGWIN__) || defined(__MINGW32__)))
#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 SHA384
#ifndef SHA512
#error The SHA384 hash requires SHA512 to be defined!
#endif
#endif
#ifdef YARROW
#ifndef CTR
#error YARROW Requires CTR mode
#endif
#endif
/* packet code */
#if defined(MRSA) || defined(MDH) || defined(MECC)
#define PACKET
/* size of a packet header in bytes */
#define PACKET_SIZE 8
/* Section tags */
#define PACKET_SECT_RSA 0
#define PACKET_SECT_DH 1
#define PACKET_SECT_ECC 2
/* 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
/* Diffie-Hellman key settings you can omit ones you don't want to save space */
#ifdef MDH
#define DH512
#define DH768
#define DH1024
#define DH1280
#define DH1536
#define DH1792
#define DH2048
#define DH2560
#define DH3072
#define DH4096
#endif /* MDH */
/* ECC Key settings */
#ifdef MECC
#define ECC160
#define ECC192
#define ECC224
#define ECC256
#define ECC384
#define ECC521
#endif /* MECC */
#ifdef MPI
#include "mpi.h"
#else
#ifdef MRSA
#error RSA requires the big int library
#endif
#ifdef MECC
#error ECC requires the big int library
#endif
#ifdef MDH
#error DH requires the big int library
#endif
#endif /* MPI */
#endif /* MYCRYPT_CFG_H */

349
mycrypt_cipher.h Normal file
View File

@ -0,0 +1,349 @@
/* ---- SYMMETRIC KEY STUFF -----
*
* We put each of the ciphers scheduled keys in their own structs then we put all of
* the key formats in one union. This makes the function prototypes easier to use.
*/
#ifdef BLOWFISH
struct blowfish_key {
unsigned long S[4][256];
unsigned long K[18];
};
#endif
#ifdef RC5
struct rc5_key {
int rounds;
unsigned long K[50];
};
#endif
#ifdef RC6
struct rc6_key {
unsigned long K[44];
};
#endif
#ifdef SAFERP
struct saferp_key {
unsigned char K[33][16];
long rounds;
};
#endif
#ifdef SERPENT
struct serpent_key {
unsigned long K[132];
};
#endif
#ifdef RIJNDAEL
struct rijndael_key {
unsigned long eK[64], dK[64], k_len;
};
#endif
#ifdef XTEA
struct xtea_key {
unsigned long K[4];
};
#endif
#ifdef TWOFISH
#ifndef TWOFISH_SMALL
struct twofish_key {
unsigned long S[4][256], K[40];
};
#else
struct twofish_key {
unsigned long K[40];
unsigned char S[32], start;
};
#endif
#endif
#ifdef SAFER
#define SAFER_K64_DEFAULT_NOF_ROUNDS 6
#define SAFER_K128_DEFAULT_NOF_ROUNDS 10
#define SAFER_SK64_DEFAULT_NOF_ROUNDS 8
#define SAFER_SK128_DEFAULT_NOF_ROUNDS 10
#define SAFER_MAX_NOF_ROUNDS 13
#define SAFER_BLOCK_LEN 8
#define SAFER_KEY_LEN (1 + SAFER_BLOCK_LEN * (1 + 2 * SAFER_MAX_NOF_ROUNDS))
typedef unsigned char safer_block_t[SAFER_BLOCK_LEN];
typedef unsigned char safer_key_t[SAFER_KEY_LEN];
struct safer_key { safer_key_t key; };
#endif
#ifdef RC2
struct rc2_key { unsigned xkey[64]; };
#endif
#ifdef DES
struct des_key {
unsigned long ek[32], dk[32];
};
struct des3_key {
unsigned long ek[3][32], dk[3][32];
};
#endif
#ifdef CAST5
struct cast5_key {
unsigned long K[32], keylen;
};
#endif
typedef union Symmetric_key {
#ifdef DES
struct des_key des;
struct des3_key des3;
#endif
#ifdef RC2
struct rc2_key rc2;
#endif
#ifdef SAFER
struct safer_key safer;
#endif
#ifdef TWOFISH
struct twofish_key twofish;
#endif
#ifdef BLOWFISH
struct blowfish_key blowfish;
#endif
#ifdef RC5
struct rc5_key rc5;
#endif
#ifdef RC6
struct rc6_key rc6;
#endif
#ifdef SAFERP
struct saferp_key saferp;
#endif
#ifdef SERPENT
struct serpent_key serpent;
#endif
#ifdef RIJNDAEL
struct rijndael_key rijndael;
#endif
#ifdef XTEA
struct xtea_key xtea;
#endif
#ifdef CAST5
struct cast5_key cast5;
#endif
} symmetric_key;
/* A block cipher ECB structure */
typedef struct {
int cipher, blocklen;
symmetric_key key;
} symmetric_ECB;
/* A block cipher CFB structure */
typedef struct {
int cipher, blocklen, padlen;
unsigned char IV[MAXBLOCKSIZE], pad[MAXBLOCKSIZE];
symmetric_key key;
} symmetric_CFB;
/* A block cipher OFB structure */
typedef struct {
int cipher, blocklen, padlen;
unsigned char IV[MAXBLOCKSIZE];
symmetric_key key;
} symmetric_OFB;
/* A block cipher CBC structure */
typedef struct Symmetric_CBC {
int cipher, blocklen;
unsigned char IV[MAXBLOCKSIZE];
symmetric_key key;
} symmetric_CBC;
/* A block cipher CTR structure */
typedef struct Symmetric_CTR {
int cipher, blocklen, padlen;
unsigned char ctr[MAXBLOCKSIZE], pad[MAXBLOCKSIZE];
symmetric_key key;
} symmetric_CTR;
/* cipher descriptor table, last entry has "name == NULL" to mark the end of table */
extern struct _cipher_descriptor {
char *name;
unsigned char ID;
unsigned long min_key_length, max_key_length, block_length, default_rounds;
int (*setup)(const unsigned char *key, int keylength, int num_rounds, symmetric_key *skey);
void (*ecb_encrypt)(const unsigned char *pt, unsigned char *ct, symmetric_key *key);
void (*ecb_decrypt)(const unsigned char *ct, unsigned char *pt, symmetric_key *key);
int (*test)(void);
int (*keysize)(int *desired_keysize);
} cipher_descriptor[];
#ifdef BLOWFISH
extern int blowfish_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
extern void blowfish_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *key);
extern void blowfish_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *key);
extern int blowfish_test(void);
extern int blowfish_keysize(int *desired_keysize);
extern const struct _cipher_descriptor blowfish_desc;
#endif
#ifdef RC5
extern int rc5_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
extern void rc5_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *key);
extern void rc5_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *key);
extern int rc5_test(void);
extern int rc5_keysize(int *desired_keysize);
extern const struct _cipher_descriptor rc5_desc;
#endif
#ifdef RC6
extern int rc6_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
extern void rc6_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *key);
extern void rc6_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *key);
extern int rc6_test(void);
extern int rc6_keysize(int *desired_keysize);
extern const struct _cipher_descriptor rc6_desc;
#endif
#ifdef RC2
extern int rc2_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
extern void rc2_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *key);
extern void rc2_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *key);
extern int rc2_test(void);
extern int rc2_keysize(int *desired_keysize);
extern const struct _cipher_descriptor rc2_desc;
#endif
#ifdef SAFERP
extern int saferp_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
extern void saferp_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *key);
extern void saferp_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *key);
extern int saferp_test(void);
extern int saferp_keysize(int *desired_keysize);
extern const struct _cipher_descriptor saferp_desc;
#endif
#ifdef SAFER
extern int safer_k64_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
extern int safer_sk64_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
extern int safer_k128_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
extern int safer_sk128_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
extern void safer_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *key);
extern void safer_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *key);
extern int safer_k64_test(void);
extern int safer_sk64_test(void);
extern int safer_sk128_test(void);
extern int safer_64_keysize(int *desired_keysize);
extern int safer_128_keysize(int *desired_keysize);
extern const struct _cipher_descriptor safer_k64_desc, safer_k128_desc, safer_sk64_desc, safer_sk128_desc;
#endif
#ifdef SERPENT
extern int serpent_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
extern void serpent_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *key);
extern void serpent_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *key);
extern int serpent_test(void);
extern int serpent_keysize(int *desired_keysize);
extern const struct _cipher_descriptor serpent_desc;
#endif
#ifdef RIJNDAEL
extern int rijndael_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
extern void rijndael_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *key);
extern void rijndael_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *key);
extern int rijndael_test(void);
extern int rijndael_keysize(int *desired_keysize);
extern const struct _cipher_descriptor rijndael_desc;
#endif
#ifdef XTEA
extern int xtea_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
extern void xtea_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *key);
extern void xtea_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *key);
extern int xtea_test(void);
extern int xtea_keysize(int *desired_keysize);
extern const struct _cipher_descriptor xtea_desc;
#endif
#ifdef TWOFISH
extern int twofish_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
extern void twofish_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *key);
extern void twofish_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *key);
extern int twofish_test(void);
extern int twofish_keysize(int *desired_keysize);
extern const struct _cipher_descriptor twofish_desc;
#endif
#ifdef DES
extern int des_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
extern void des_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *key);
extern void des_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *key);
extern int des_test(void);
extern int des_keysize(int *desired_keysize);
extern int des3_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
extern void des3_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *key);
extern void des3_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *key);
extern int des3_test(void);
extern int des3_keysize(int *desired_keysize);
extern const struct _cipher_descriptor des_desc, des3_desc;
#endif
#ifdef CAST5
extern int cast5_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
extern void cast5_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *key);
extern void cast5_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *key);
extern int cast5_test(void);
extern int cast5_keysize(int *desired_keysize);
extern const struct _cipher_descriptor cast5_desc;
#endif
#ifdef ECB
extern int ecb_start(int cipher, const unsigned char *key,
int keylen, int num_rounds, symmetric_ECB *ecb);
extern int ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_ECB *ecb);
extern int ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_ECB *ecb);
#endif
#ifdef CFB
extern int cfb_start(int cipher, const unsigned char *IV, const unsigned char *key,
int keylen, int num_rounds, symmetric_CFB *cfb);
extern int cfb_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_CFB *cfb);
extern int cfb_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_CFB *cfb);
#endif
#ifdef OFB
extern int ofb_start(int cipher, const unsigned char *IV, const unsigned char *key,
int keylen, int num_rounds, symmetric_OFB *ofb);
extern int ofb_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_OFB *ofb);
extern int ofb_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_OFB *ofb);
#endif
#ifdef CBC
extern int cbc_start(int cipher, const unsigned char *IV, const unsigned char *key,
int keylen, int num_rounds, symmetric_CBC *cbc);
extern int cbc_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_CBC *cbc);
extern int cbc_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_CBC *cbc);
#endif
#ifdef CTR
extern int ctr_start(int cipher, const unsigned char *IV, const unsigned char *key,
int keylen, int num_rounds, symmetric_CTR *ctr);
extern int ctr_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_CTR *ctr);
extern int ctr_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_CTR *ctr);
#endif
extern int find_cipher(const char *name);
extern int find_cipher_any(const char *name, int blocklen, int keylen);
extern int find_cipher_id(unsigned char ID);
extern int register_cipher(const struct _cipher_descriptor *cipher);
extern int unregister_cipher(const struct _cipher_descriptor *cipher);
extern int cipher_is_valid(int idx);

32
mycrypt_gf.h Normal file
View File

@ -0,0 +1,32 @@
/* ---- GF(2^w) polynomial basis ---- */
#ifdef GF
#define LSIZE 32 /* handle upto 1024-bit GF numbers */
typedef unsigned long gf_int[LSIZE];
typedef unsigned long *gf_intp;
extern void gf_copy(gf_intp a, gf_intp b);
extern void gf_zero(gf_intp a);
extern int gf_iszero(gf_intp a);
extern int gf_isone(gf_intp a);
extern int gf_deg(gf_intp a);
extern void gf_shl(gf_intp a, gf_intp b);
extern void gf_shr(gf_intp a, gf_intp b);
extern void gf_add(gf_intp a, gf_intp b, gf_intp c);
extern void gf_mul(gf_intp a, gf_intp b, gf_intp c);
extern void gf_div(gf_intp a, gf_intp b, gf_intp q, gf_intp r);
extern void gf_mod(gf_intp a, gf_intp m, gf_intp b);
extern void gf_mulmod(gf_intp a, gf_intp b, gf_intp m, gf_intp c);
extern void gf_invmod(gf_intp A, gf_intp M, gf_intp B);
extern void gf_sqrt(gf_intp a, gf_intp M, gf_intp b);
extern void gf_gcd(gf_intp A, gf_intp B, gf_intp c);
extern int gf_is_prime(gf_intp a);
extern int gf_size(gf_intp a);
extern void gf_toraw(gf_intp a, unsigned char *dst);
extern void gf_readraw(gf_intp a, unsigned char *str, int len);
#endif

184
mycrypt_hash.h Normal file
View File

@ -0,0 +1,184 @@
/* ---- HASH FUNCTIONS ---- */
#ifdef SHA512
struct sha512_state {
ulong64 length, state[8];
unsigned long curlen;
unsigned char buf[128];
};
#endif
#ifdef SHA256
struct sha256_state {
ulong64 length;
unsigned long state[8], curlen;
unsigned char buf[64];
};
#endif
#ifdef SHA1
struct sha1_state {
ulong64 length;
unsigned long state[5], curlen;
unsigned char buf[64];
};
#endif
#ifdef MD5
struct md5_state {
ulong64 length;
unsigned long state[4], curlen;
unsigned char buf[64];
};
#endif
#ifdef MD4
struct md4_state {
ulong64 length;
unsigned long state[4], curlen;
unsigned char buf[64];
};
#endif
#ifdef TIGER
struct tiger_state {
ulong64 state[3], length;
unsigned long curlen;
unsigned char buf[64];
};
#endif
#ifdef MD2
struct md2_state {
unsigned char chksum[16], X[48], buf[16];
unsigned long curlen;
};
#endif
typedef union Hash_state {
#ifdef SHA512
struct sha512_state sha512;
#endif
#ifdef SHA256
struct sha256_state sha256;
#endif
#ifdef SHA1
struct sha1_state sha1;
#endif
#ifdef MD5
struct md5_state md5;
#endif
#ifdef MD4
struct md4_state md4;
#endif
#ifdef MD2
struct md2_state md2;
#endif
#ifdef TIGER
struct tiger_state tiger;
#endif
} hash_state;
extern struct _hash_descriptor {
char *name;
unsigned char ID;
unsigned long hashsize; /* digest output size in bytes */
unsigned long blocksize; /* the block size the hash uses */
void (*init)(hash_state *);
void (*process)(hash_state *, const unsigned char *, unsigned long);
void (*done)(hash_state *, unsigned char *);
int (*test)(void);
} hash_descriptor[];
#ifdef SHA512
extern void sha512_init(hash_state * md);
extern void sha512_process(hash_state * md, const unsigned char *buf, unsigned long len);
extern void sha512_done(hash_state * md, unsigned char *hash);
extern int sha512_test(void);
extern const struct _hash_descriptor sha512_desc;
#endif
#ifdef SHA384
extern void sha384_init(hash_state * md);
extern void sha384_process(hash_state * md, const unsigned char *buf, unsigned long len);
extern void sha384_done(hash_state * md, unsigned char *hash);
extern int sha384_test(void);
extern const struct _hash_descriptor sha384_desc;
#endif
#ifdef SHA256
extern void sha256_init(hash_state * md);
extern void sha256_process(hash_state * md, const unsigned char *buf, unsigned long len);
extern void sha256_done(hash_state * md, unsigned char *hash);
extern int sha256_test(void);
extern const struct _hash_descriptor sha256_desc;
#endif
#ifdef SHA1
extern void sha1_init(hash_state * md);
extern void sha1_process(hash_state * md, const unsigned char *buf, unsigned long len);
extern void sha1_done(hash_state * md, unsigned char *hash);
extern int sha1_test(void);
extern const struct _hash_descriptor sha1_desc;
#endif
#ifdef MD5
extern void md5_init(hash_state * md);
extern void md5_process(hash_state * md, const unsigned char *buf, unsigned long len);
extern void md5_done(hash_state * md, unsigned char *hash);
extern int md5_test(void);
extern const struct _hash_descriptor md5_desc;
#endif
#ifdef MD4
extern void md4_init(hash_state * md);
extern void md4_process(hash_state * md, const unsigned char *buf, unsigned long len);
extern void md4_done(hash_state * md, unsigned char *hash);
extern int md4_test(void);
extern const struct _hash_descriptor md4_desc;
#endif
#ifdef MD2
extern void md2_init(hash_state * md);
extern void md2_process(hash_state * md, const unsigned char *buf, unsigned long len);
extern void md2_done(hash_state * md, unsigned char *hash);
extern int md2_test(void);
extern const struct _hash_descriptor md2_desc;
#endif
#ifdef TIGER
extern void tiger_init(hash_state * md);
extern void tiger_process(hash_state * md, const unsigned char *buf, unsigned long len);
extern void tiger_done(hash_state * md, unsigned char *hash);
extern int tiger_test(void);
extern const struct _hash_descriptor tiger_desc;
#endif
extern int find_hash(const char *name);
extern int find_hash_id(unsigned char ID);
extern int register_hash(const struct _hash_descriptor *hash);
extern int unregister_hash(const struct _hash_descriptor *hash);
extern int hash_is_valid(int idx);
extern int hash_memory(int hash, const unsigned char *data, unsigned long len, unsigned char *dst, unsigned long *outlen);
extern int hash_filehandle(int hash, FILE *in, unsigned char *dst, unsigned long *outlen);
extern int hash_file(int hash, const char *fname, unsigned char *dst, unsigned long *outlen);
#ifdef HMAC
typedef struct Hmac_state {
hash_state md;
int hash;
unsigned long hashsize; /* here for your reference */
hash_state hashstate;
unsigned char key[MAXBLOCKSIZE];
} hmac_state;
extern int hmac_init(hmac_state *hmac, int hash, const unsigned char *key, unsigned long keylen);
extern int hmac_process(hmac_state *hmac, const unsigned char *buf, unsigned long len);
extern int hmac_done(hmac_state *hmac, unsigned char *hash);
extern int hmac_test(void);
extern int hmac_memory(int hash, const unsigned char *key, unsigned long keylen,
const unsigned char *data, unsigned long len, unsigned char *dst);
extern int hmac_file(int hash, const char *fname, const unsigned char *key,
unsigned long keylen, unsigned char *dst);
#endif

77
mycrypt_kr.h Normal file
View File

@ -0,0 +1,77 @@
#ifdef KR
#define MAXLEN 256
enum {
NON_KEY=0,
RSA_KEY,
DH_KEY,
ECC_KEY
};
typedef union {
rsa_key rsa;
dh_key dh;
ecc_key ecc;
} _pk_key;
typedef struct Pk_key {
int key_type, /* PUBLIC, PRIVATE, PRIVATE_OPTIMIZED */
system; /* RSA, ECC or DH ? */
unsigned char
name[MAXLEN], /* various info's about this key */
email[MAXLEN],
description[MAXLEN];
unsigned long ID; /* CRC32 of the name/email/description together */
_pk_key key;
struct Pk_key *next; /* linked list chain */
} pk_key;
extern int kr_init(pk_key **pk);
extern unsigned long kr_crc(const unsigned char *name, const unsigned char *email, const unsigned char *description);
extern pk_key *kr_find(pk_key *pk, unsigned long ID);
extern pk_key *kr_find_name(pk_key *pk, const char *name);
extern int kr_add(pk_key *pk, int key_type, int system, const unsigned char *name,
const unsigned char *email, const unsigned char *description, const _pk_key *key);
extern int kr_del(pk_key **_pk, unsigned long ID);
extern int kr_clear(pk_key **pk);
extern int kr_make_key(pk_key *pk, prng_state *prng, int wprng,
int system, int keysize, const unsigned char *name,
const unsigned char *email, const unsigned char *description);
extern int kr_export(pk_key *pk, unsigned long ID, int key_type, unsigned char *out, unsigned long *outlen);
extern int kr_import(pk_key *pk, const unsigned char *in);
extern int kr_load(pk_key **pk, FILE *in, symmetric_CTR *ctr);
extern int kr_save(pk_key *pk, FILE *out, symmetric_CTR *ctr);
extern 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);
extern int kr_decrypt_key(pk_key *pk, const unsigned char *in,
unsigned char *out, unsigned long *outlen);
extern 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);
extern int kr_verify_hash(pk_key *pk, const unsigned char *in,
const unsigned char *hash, unsigned long hashlen,
int *stat);
extern int kr_fingerprint(pk_key *pk, unsigned long ID, int hash,
unsigned char *out, unsigned long *outlen);
#endif

200
mycrypt_macros.h Normal file
View File

@ -0,0 +1,200 @@
/* fix for MSVC ...evil! */
#ifdef _MSC_VER
#define CONST64(n) n ## ui64
typedef unsigned __int64 ulong64;
#else
#define CONST64(n) n ## ULL
typedef unsigned long long ulong64;
#endif
extern char *crypt_error;
/* ---- HELPER MACROS ---- */
#ifdef ENDIAN_NEUTRAL
#define STORE32L(x, y) \
{ (y)[3] = (unsigned char)(((x)>>24)&255); (y)[2] = (unsigned char)(((x)>>16)&255); \
(y)[1] = (unsigned char)(((x)>>8)&255); (y)[0] = (unsigned char)((x)&255); }
#define LOAD32L(x, y) \
{ x = ((unsigned long)((y)[3] & 255)<<24) | \
((unsigned long)((y)[2] & 255)<<16) | \
((unsigned long)((y)[1] & 255)<<8) | \
((unsigned long)((y)[0] & 255)); }
#define STORE64L(x, y) \
{ (y)[7] = (unsigned char)(((x)>>56)&255); (y)[6] = (unsigned char)(((x)>>48)&255); \
(y)[5] = (unsigned char)(((x)>>40)&255); (y)[4] = (unsigned char)(((x)>>32)&255); \
(y)[3] = (unsigned char)(((x)>>24)&255); (y)[2] = (unsigned char)(((x)>>16)&255); \
(y)[1] = (unsigned char)(((x)>>8)&255); (y)[0] = (unsigned char)((x)&255); }
#define LOAD64L(x, y) \
{ x = (((ulong64)((y)[7] & 255))<<56)|(((ulong64)((y)[6] & 255))<<48)| \
(((ulong64)((y)[5] & 255))<<40)|(((ulong64)((y)[4] & 255))<<32)| \
(((ulong64)((y)[3] & 255))<<24)|(((ulong64)((y)[2] & 255))<<16)| \
(((ulong64)((y)[1] & 255))<<8)|(((ulong64)((y)[0] & 255))); }
#define STORE32H(x, y) \
{ (y)[0] = (unsigned char)(((x)>>24)&255); (y)[1] = (unsigned char)(((x)>>16)&255); \
(y)[2] = (unsigned char)(((x)>>8)&255); (y)[3] = (unsigned char)((x)&255); }
#define LOAD32H(x, y) \
{ x = ((unsigned long)((y)[0] & 255)<<24) | \
((unsigned long)((y)[1] & 255)<<16) | \
((unsigned long)((y)[2] & 255)<<8) | \
((unsigned long)((y)[3] & 255)); }
#define STORE64H(x, y) \
{ (y)[0] = (unsigned char)(((x)>>56)&255); (y)[1] = (unsigned char)(((x)>>48)&255); \
(y)[2] = (unsigned char)(((x)>>40)&255); (y)[3] = (unsigned char)(((x)>>32)&255); \
(y)[4] = (unsigned char)(((x)>>24)&255); (y)[5] = (unsigned char)(((x)>>16)&255); \
(y)[6] = (unsigned char)(((x)>>8)&255); (y)[7] = (unsigned char)((x)&255); }
#define LOAD64H(x, y) \
{ x = (((ulong64)((y)[0] & 255))<<56)|(((ulong64)((y)[1] & 255))<<48) | \
(((ulong64)((y)[2] & 255))<<40)|(((ulong64)((y)[3] & 255))<<32) | \
(((ulong64)((y)[4] & 255))<<24)|(((ulong64)((y)[5] & 255))<<16) | \
(((ulong64)((y)[6] & 255))<<8)|(((ulong64)((y)[7] & 255))); }
#endif /* ENDIAN_NEUTRAL */
#ifdef ENDIAN_LITTLE
#define STORE32H(x, y) \
{ (y)[0] = (unsigned char)(((x)>>24)&255); (y)[1] = (unsigned char)(((x)>>16)&255); \
(y)[2] = (unsigned char)(((x)>>8)&255); (y)[3] = (unsigned char)((x)&255); }
#define LOAD32H(x, y) \
{ x = ((unsigned long)((y)[0] & 255)<<24) | \
((unsigned long)((y)[1] & 255)<<16) | \
((unsigned long)((y)[2] & 255)<<8) | \
((unsigned long)((y)[3] & 255)); }
#define STORE64H(x, y) \
{ (y)[0] = (unsigned char)(((x)>>56)&255); (y)[1] = (unsigned char)(((x)>>48)&255); \
(y)[2] = (unsigned char)(((x)>>40)&255); (y)[3] = (unsigned char)(((x)>>32)&255); \
(y)[4] = (unsigned char)(((x)>>24)&255); (y)[5] = (unsigned char)(((x)>>16)&255); \
(y)[6] = (unsigned char)(((x)>>8)&255); (y)[7] = (unsigned char)((x)&255); }
#define LOAD64H(x, y) \
{ x = (((ulong64)((y)[0] & 255))<<56)|(((ulong64)((y)[1] & 255))<<48) | \
(((ulong64)((y)[2] & 255))<<40)|(((ulong64)((y)[3] & 255))<<32) | \
(((ulong64)((y)[4] & 255))<<24)|(((ulong64)((y)[5] & 255))<<16) | \
(((ulong64)((y)[6] & 255))<<8)|(((ulong64)((y)[7] & 255))); }
#ifdef ENDIAN_32BITWORD
#define STORE32L(x, y) \
{ unsigned long t = (x); memcpy(y, &t, 4); }
#define LOAD32L(x, y) \
memcpy(&(x), y, 4);
#define STORE64L(x, y) \
{ (y)[7] = (unsigned char)(((x)>>56)&255); (y)[6] = (unsigned char)(((x)>>48)&255); \
(y)[5] = (unsigned char)(((x)>>40)&255); (y)[4] = (unsigned char)(((x)>>32)&255); \
(y)[3] = (unsigned char)(((x)>>24)&255); (y)[2] = (unsigned char)(((x)>>16)&255); \
(y)[1] = (unsigned char)(((x)>>8)&255); (y)[0] = (unsigned char)((x)&255); }
#define LOAD64L(x, y) \
{ x = (((ulong64)((y)[7] & 255))<<56)|(((ulong64)((y)[6] & 255))<<48)| \
(((ulong64)((y)[5] & 255))<<40)|(((ulong64)((y)[4] & 255))<<32)| \
(((ulong64)((y)[3] & 255))<<24)|(((ulong64)((y)[2] & 255))<<16)| \
(((ulong64)((y)[1] & 255))<<8)|(((ulong64)((y)[0] & 255))); }
#else /* 64-bit words then */
#define STORE32L(x, y) \
{ unsigned long t = (x); memcpy(y, &t, 4); }
#define LOAD32L(x, y) \
{ memcpy(&(x), y, 4); x &= 0xFFFFFFFF; }
#define STORE64L(x, y) \
{ ulong64 t = (x); memcpy(y, &t, 8); }
#define LOAD64L(x, y) \
{ memcpy(&(x), y, 8); }
#endif /* ENDIAN_64BITWORD */
#endif /* ENDIAN_LITTLE */
#ifdef ENDIAN_BIG
#define STORE32L(x, y) \
{ (y)[0] = (unsigned char)(((x)>>24)&255); (y)[1] = (unsigned char)(((x)>>16)&255); \
(y)[2] = (unsigned char)(((x)>>8)&255); (y)[3] = (unsigned char)((x)&255); }
#define LOAD32L(x, y) \
{ x = ((unsigned long)((y)[0] & 255)<<24) | \
((unsigned long)((y)[1] & 255)<<16) | \
((unsigned long)((y)[2] & 255)<<8) | \
((unsigned long)((y)[3] & 255)); }
#define STORE64L(x, y) \
{ (y)[0] = (unsigned char)(((x)>>56)&255); (y)[1] = (unsigned char)(((x)>>48)&255); \
(y)[2] = (unsigned char)(((x)>>40)&255); (y)[3] = (unsigned char)(((x)>>32)&255); \
(y)[4] = (unsigned char)(((x)>>24)&255); (y)[5] = (unsigned char)(((x)>>16)&255); \
(y)[6] = (unsigned char)(((x)>>8)&255); (y)[7] = (unsigned char)((x)&255); }
#define LOAD64L(x, y) \
{ x = (((ulong64)((y)[0] & 255))<<56)|(((ulong64)((y)[1] & 255))<<48) | \
(((ulong64)((y)[2] & 255))<<40)|(((ulong64)((y)[3] & 255))<<32) | \
(((ulong64)((y)[4] & 255))<<24)|(((ulong64)((y)[5] & 255))<<16) | \
(((ulong64)((y)[6] & 255))<<8)|(((ulong64)((y)[7] & 255))); }
#ifdef ENDIAN_32BITWORD
#define STORE32H(x, y) \
{ unsigned long t = (x); memcpy(y, &t, 4); }
#define LOAD32H(x, y) \
memcpy(&(x), y, 4);
#define STORE64H(x, y) \
{ (y)[7] = (unsigned char)(((x)>>56)&255); (y)[6] = (unsigned char)(((x)>>48)&255); \
(y)[5] = (unsigned char)(((x)>>40)&255); (y)[4] = (unsigned char)(((x)>>32)&255); \
(y)[3] = (unsigned char)(((x)>>24)&255); (y)[2] = (unsigned char)(((x)>>16)&255); \
(y)[1] = (unsigned char)(((x)>>8)&255); (y)[0] = (unsigned char)((x)&255); }
#define LOAD64H(x, y) \
{ x = (((ulong64)((y)[7] & 255))<<56)|(((ulong64)((y)[6] & 255))<<48)| \
(((ulong64)((y)[5] & 255))<<40)|(((ulong64)((y)[4] & 255))<<32)| \
(((ulong64)((y)[3] & 255))<<24)|(((ulong64)((y)[2] & 255))<<16)| \
(((ulong64)((y)[1] & 255))<<8)|(((ulong64)((y)[0] & 255))); }
#else /* 64-bit words then */
#define STORE32H(x, y) \
{ unsigned long t = (x); memcpy(y, &t, 4); }
#define LOAD32H(x, y) \
{ memcpy(&(x), y, 4); x &= 0xFFFFFFFF; }
#define STORE64H(x, y) \
{ ulong64 t = (x); memcpy(y, &t, 8); }
#define LOAD64H(x, y) \
{ memcpy(&(x), y, 8); }
#endif /* ENDIAN_64BITWORD */
#endif /* ENDIAN_BIG */
#define BSWAP(x) ( ((x>>24)&0x000000FFUL) | ((x<<24)&0xFF000000UL) | \
((x>>8)&0x0000FF00UL) | ((x<<8)&0x00FF0000UL) )
#define ROL(x, y) ( (((x)<<((y)&31)) | (((x)&0xFFFFFFFFUL)>>(32-((y)&31)))) & 0xFFFFFFFFUL)
#define ROR(x, y) ( ((((x)&0xFFFFFFFFUL)>>((y)&31)) | ((x)<<(32-((y)&31)))) & 0xFFFFFFFFUL)
#define ROL64(x, y) \
( (((x)<<((ulong64)(y)&63)) | \
(((x)&CONST64(0xFFFFFFFFFFFFFFFF))>>((ulong64)64-((y)&63)))) & CONST64(0xFFFFFFFFFFFFFFFF))
#define ROR64(x, y) \
( ((((x)&CONST64(0xFFFFFFFFFFFFFFFF))>>((ulong64)(y)&CONST64(63))) | \
((x)<<((ulong64)(64-((y)&CONST64(63)))))) & CONST64(0xFFFFFFFFFFFFFFFF))
#undef MAX
#undef MIN
#define MAX(x, y) ( ((x)>(y))?(x):(y) )
#define MIN(x, y) ( ((x)<(y))?(x):(y) )

16
mycrypt_misc.h Normal file
View File

@ -0,0 +1,16 @@
/* ---- BASE64 Routines ---- */
#ifdef BASE64
extern int base64_encode(const unsigned char *in, unsigned long len,
unsigned char *out, unsigned long *outlen);
extern int base64_decode(const unsigned char *in, unsigned long len,
unsigned char *out, unsigned long *outlen);
#endif
/* ---- MEM routines ---- */
extern void zeromem(void *dst, unsigned long len);
extern void burn_stack(unsigned long len);
extern const char *error_to_string(int errno);
extern const char *crypt_build_settings;

219
mycrypt_pk.h Normal file
View File

@ -0,0 +1,219 @@
/* ---- NUMBER THEORY ---- */
#ifdef MPI
extern int is_prime(mp_int *, int *);
extern int rand_prime(mp_int *N, long len, prng_state *prng, int wprng);
extern mp_err mp_init_multi(mp_int* mp, ...);
extern void mp_clear_multi(mp_int* mp, ...);
#endif
/* ---- PUBLIC KEY CRYPTO ---- */
#define PK_PRIVATE 0 /* PK private keys */
#define PK_PUBLIC 1 /* PK public keys */
#define PK_PRIVATE_OPTIMIZED 2 /* PK private key [rsa optimized] */
/* ---- PACKET ---- */
#ifdef PACKET
extern void packet_store_header(unsigned char *dst, int section, int subsection, unsigned long length);
extern int packet_valid_header(unsigned char *src, int section, int subsection);
#endif
/* ---- RSA ---- */
#ifdef MRSA
typedef struct Rsa_key {
int type;
mp_int e, d, N, qP, pQ, dP, dQ, p, q;
} rsa_key;
extern int rsa_make_key(prng_state *prng, int wprng, int size, long e, rsa_key *key);
extern int rsa_exptmod(const unsigned char *in, unsigned long inlen,
unsigned char *out, unsigned long *outlen, int which,
rsa_key *key);
extern int rsa_pad(const unsigned char *in, unsigned long inlen,
unsigned char *out, unsigned long *outlen,
int wprng, prng_state *prng);
extern int rsa_signpad(const unsigned char *in, unsigned long inlen,
unsigned char *out, unsigned long *outlen);
extern int rsa_depad(const unsigned char *in, unsigned long inlen,
unsigned char *out, unsigned long *outlen);
extern int rsa_signdepad(const unsigned char *in, unsigned long inlen,
unsigned char *out, unsigned long *outlen);
extern void rsa_free(rsa_key *key);
#ifdef PK_PACKET
extern int rsa_encrypt(const unsigned char *in, unsigned long len,
unsigned char *out, unsigned long *outlen,
prng_state *prng, int wprng, int cipher,
rsa_key *key);
extern int rsa_decrypt(const unsigned char *in, unsigned long len,
unsigned char *out, unsigned long *outlen,
rsa_key *key);
extern int rsa_sign(const unsigned char *in, unsigned long inlen,
unsigned char *out, unsigned long *outlen,
int hash, rsa_key *key);
extern int rsa_verify(const unsigned char *sig, const unsigned char *msg,
unsigned long inlen, int *stat,
rsa_key *key);
#endif
extern int rsa_encrypt_key(const unsigned char *inkey, unsigned long inlen,
unsigned char *outkey, unsigned long *outlen,
prng_state *prng, int wprng, rsa_key *key);
extern int rsa_decrypt_key(const unsigned char *in, unsigned char *outkey,
unsigned long *keylen, rsa_key *key);
extern int rsa_sign_hash(const unsigned char *in, unsigned long inlen,
unsigned char *out, unsigned long *outlen,
rsa_key *key);
extern int rsa_verify_hash(const unsigned char *sig, const unsigned char *hash,
int *stat, rsa_key *key);
extern int rsa_export(unsigned char *out, unsigned long *outlen, int type, rsa_key *key);
extern int rsa_import(const unsigned char *in, rsa_key *key);
#endif
/* ---- DH Routines ---- */
#ifdef MDH
typedef struct Dh_key {
int idx, type;
mp_int x, y;
} dh_key;
extern int dh_test(void);
extern void dh_sizes(int *low, int *high);
extern int dh_get_size(dh_key *key);
extern int dh_make_key(prng_state *prng, int wprng, int keysize, dh_key *key);
extern void dh_free(dh_key *key);
extern int dh_export(unsigned char *out, unsigned long *outlen, int type, dh_key *key);
extern int dh_import(const unsigned char *in, dh_key *key);
extern int dh_shared_secret(dh_key *private_key, dh_key *public_key,
unsigned char *out, unsigned long *outlen);
#ifdef PK_PACKET
extern int dh_encrypt(const unsigned char *in, unsigned long len,
unsigned char *out, unsigned long *outlen,
prng_state *prng, int wprng, int cipher, int hash,
dh_key *key);
extern int dh_decrypt(const unsigned char *in, unsigned long len,
unsigned char *out, unsigned long *outlen,
dh_key *key);
extern int dh_sign(const unsigned char *in, unsigned long inlen,
unsigned char *out, unsigned long *outlen, int hash,
prng_state *prng, int wprng,
dh_key *key);
extern int dh_verify(const unsigned char *sig, const unsigned char *msg,
unsigned long inlen, int *stat,
dh_key *key);
#endif
extern 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);
extern int dh_decrypt_key(const unsigned char *in, unsigned char *outkey,
unsigned long *keylen, dh_key *key);
extern 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);
extern int dh_verify_hash(const unsigned char *sig, const unsigned char *hash,
unsigned long inlen, int *stat,
dh_key *key);
#endif
/* ---- ECC Routines ---- */
#ifdef MECC
typedef struct {
mp_int x, y;
} ecc_point;
typedef struct {
int type, idx;
ecc_point pubkey;
mp_int k;
} ecc_key;
extern int ecc_test(void);
extern void ecc_sizes(int *low, int *high);
extern int ecc_get_size(ecc_key *key);
extern int ecc_make_key(prng_state *prng, int wprng, int keysize, ecc_key *key);
extern void ecc_free(ecc_key *key);
extern int ecc_export(unsigned char *out, unsigned long *outlen, int type, ecc_key *key);
extern int ecc_import(const unsigned char *in, ecc_key *key);
extern int ecc_shared_secret(ecc_key *private_key, ecc_key *public_key,
unsigned char *out, unsigned long *outlen);
#ifdef PK_PACKET
extern int ecc_encrypt(const unsigned char *in, unsigned long len,
unsigned char *out, unsigned long *outlen,
prng_state *prng, int wprng, int cipher, int hash,
ecc_key *key);
extern int ecc_decrypt(const unsigned char *in, unsigned long len,
unsigned char *out, unsigned long *outlen,
ecc_key *key);
extern int ecc_sign(const unsigned char *in, unsigned long inlen,
unsigned char *out, unsigned long *outlen, int hash,
prng_state *prng, int wprng,
ecc_key *key);
extern int ecc_verify(const unsigned char *sig, const unsigned char *msg,
unsigned long inlen, int *stat,
ecc_key *key);
#endif
extern 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);
extern int ecc_decrypt_key(const unsigned char *in, unsigned char *outkey,
unsigned long *keylen, ecc_key *key);
extern 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);
extern int ecc_verify_hash(const unsigned char *sig, const unsigned char *hash,
unsigned long inlen, int *stat,
ecc_key *key);
#endif

62
mycrypt_prng.h Normal file
View File

@ -0,0 +1,62 @@
/* ---- PRNG Stuff ---- */
struct yarrow_prng {
int cipher, hash;
unsigned char pool[MAXBLOCKSIZE];
symmetric_CTR ctr;
};
struct rc4_prng {
int x, y;
unsigned char buf[256];
};
typedef union Prng_state {
struct yarrow_prng yarrow;
struct rc4_prng rc4;
} prng_state;
extern struct _prng_descriptor {
char *name;
int (*start)(prng_state *);
int (*add_entropy)(const unsigned char *, unsigned long, prng_state *);
int (*ready)(prng_state *);
unsigned long (*read)(unsigned char *, unsigned long len, prng_state *);
} prng_descriptor[];
#ifdef YARROW
extern int yarrow_start(prng_state *prng);
extern int yarrow_add_entropy(const unsigned char *buf, unsigned long len, prng_state *prng);
extern int yarrow_ready(prng_state *prng);
extern unsigned long yarrow_read(unsigned char *buf, unsigned long len, prng_state *prng);
extern const struct _prng_descriptor yarrow_desc;
#endif
#ifdef RC4
extern int rc4_start(prng_state *prng);
extern int rc4_add_entropy(const unsigned char *buf, unsigned long len, prng_state *prng);
extern int rc4_ready(prng_state *prng);
extern unsigned long rc4_read(unsigned char *buf, unsigned long len, prng_state *prng);
extern const struct _prng_descriptor rc4_desc;
#endif
#ifdef SPRNG
extern int sprng_start(prng_state *prng);
extern int sprng_add_entropy(const unsigned char *buf, unsigned long len, prng_state *prng);
extern int sprng_ready(prng_state *prng);
extern unsigned long sprng_read(unsigned char *buf, unsigned long len, prng_state *prng);
extern const struct _prng_descriptor sprng_desc;
#endif
extern int find_prng(const char *name);
extern int register_prng(const struct _prng_descriptor *prng);
extern int unregister_prng(const struct _prng_descriptor *prng);
extern int prng_is_valid(int idx);
/* Slow RNG you **might** be able to use to seed a PRNG with. Be careful as this
* might not work on all platforms as planned
*/
extern unsigned long rng_get_bytes(unsigned char *buf, unsigned long len, void (*callback)(void));
extern int rng_make_prng(int bits, int wprng, prng_state *prng, void (*callback)(void));

73
notes/tech0001.txt Normal file
View File

@ -0,0 +1,73 @@
Tech Note 0001
How to Gather Entropy on Embedded Systems
Tom St Denis
Introduction
------------
This tech note explains a relatively simple way to gather entropy for a PRNG (Yarrow in this case) in embedded systems
where there are few sources of entropy or physical sources.
When trying to setup a secure random number generator a fresh source of random data (entropy) is required to ensure the
deterministic state of the PRNG is not known or predetermined with respect to an attacker.
At the very least the system requires one timer and one source of un-timed interrupts. by "un-timed" I mean interrupts
that do not occur at regular intervals [e.g. joypad/keypad input, network packets, etc...].
First we shall begin by taking an overview of how the Yarrow PRNG works within libtomcrypt. At the heart of all
PRNGs is the "prng_state" data type. This is a union of structures that hold the PRNG state for the various prngs. The
first thing we require is a state...
prng_state myPrng;
Next we must initialize the state once to get the ball rolling
if (yarrow_start(&myPrng) != CRYPT_OK) {
// error should never happen!
}
At this point the PRNG is ready to accept fresh entropy which is added with
int yarrow_add_entropy(const unsigned char *buf, unsigned long len, prng_state *prng)
This function is **NOT** thread safe which will come under consideration later. To add entropy to our PRNG we must
call this function with fresh data as its sampled. Lets say we have a timer counter called "uTimer" which is a 32-bit
long and say a 32-bit joyPad state called "uPad". An example interrupt handler would look like
void joypad_interrupt(...) {
unsigned char buf[8];
STORE32L(uTimer, buf);
STORE32L(uPad, buf+4)
if (yarrow_add_entropy(buf, 8, &myPrng) != CRYPT_OK) {
// this should never occur either unless you didn't call yarrow_start
}
// handle interrupt
}
In this snippet the timer count and state of the joypad are added together into the entropy pool. The timer is important
because with respect to the joypad it is a good source of entropy (on its own its not). For example, the probability of
the user pushing the up arrow is fairly high, but at a specific time is not.
This method doesn't gather alot of entropy and has to be used to for quite a while. One way to speed it up is to tap
multiple sources. If you have a network adapter and other sources of events (keyboard, mouse, etc...) trapping their
data is ideal as well. Its important to gather the timer along with the event data.
As mentioned the "yarrow_add_entropy()" function is not thread safe. If your system allows interrupt handlers to be
interrupted themselves then you could have trouble. One simple way is to detect when an interrupt is in progress and
simply not add entropy during the call (jump over the yarrow_add_entropy() call)
Once you feel that there has been enough entropy added to the pool then within a single thread you can call
int yarrow_ready(prng_state *prng)
Now the PRNG is ready to read via the
unsigned long yarrow_read(unsigned char *buf, unsigned long len, prng_state *prng)
It is a very good idea that once you call the yarrow_ready() function that you stop harvesting entropy in your interrupt
functions. This will free up alot of CPU time. Also one more final note. The yarrow_read() function is not thread
safe either. This means if you have multiple threads or processes that read from it you will have to add your own semaphores
around calls to it.

60
ofb.c Normal file
View File

@ -0,0 +1,60 @@
#include "mycrypt.h"
#ifdef OFB
int ofb_start(int cipher, const unsigned char *IV, const unsigned char *key,
int keylen, int num_rounds, symmetric_OFB *ofb)
{
int x, errno;
_ARGCHK(IV != NULL);
_ARGCHK(key != NULL);
_ARGCHK(ofb != NULL);
if ((errno = cipher_is_valid(cipher)) != CRYPT_OK) {
return errno;
}
/* copy details */
ofb->cipher = cipher;
ofb->blocklen = cipher_descriptor[cipher].block_length;
for (x = 0; x < ofb->blocklen; x++) {
ofb->IV[x] = IV[x];
}
/* init the cipher */
ofb->padlen = ofb->blocklen;
return cipher_descriptor[cipher].setup(key, keylen, num_rounds, &ofb->key);
}
int ofb_encrypt(const unsigned char *pt, unsigned char *ct, unsigned long len, symmetric_OFB *ofb)
{
int errno;
_ARGCHK(pt != NULL);
_ARGCHK(ct != NULL);
_ARGCHK(ofb != NULL);
if ((errno = cipher_is_valid(ofb->cipher)) != CRYPT_OK) {
return errno;
}
while (len--) {
if (ofb->padlen == ofb->blocklen) {
cipher_descriptor[ofb->cipher].ecb_encrypt(ofb->IV, ofb->IV, &ofb->key);
ofb->padlen = 0;
}
*ct++ = *pt++ ^ ofb->IV[ofb->padlen++];
}
return CRYPT_OK;
}
int ofb_decrypt(const unsigned char *ct, unsigned char *pt, unsigned long len, symmetric_OFB *ofb)
{
_ARGCHK(pt != NULL);
_ARGCHK(ct != NULL);
_ARGCHK(ofb != NULL);
return ofb_encrypt(ct, pt, len, ofb);
}
#endif

43
packet.c Normal file
View File

@ -0,0 +1,43 @@
#include "mycrypt.h"
#ifdef PACKET
void packet_store_header(unsigned char *dst, int section, int subsection, unsigned long length)
{
_ARGCHK(dst != NULL);
/* store version number */
dst[0] = CRYPT&255;
dst[1] = (CRYPT>>8)&255;
/* store section and subsection */
dst[2] = section & 255;
dst[3] = subsection & 255;
/* store length */
STORE32L(length, &dst[4]);
}
int packet_valid_header(unsigned char *src, int section, int subsection)
{
unsigned long ver;
_ARGCHK(src != NULL);
/* check version */
ver = ((unsigned long)src[0]) | ((unsigned long)src[1] << 8);
if (CRYPT < ver) {
return CRYPT_INVALID_PACKET;
}
/* check section and subsection */
if (section != src[2] || subsection != src[3]) {
return CRYPT_INVALID_PACKET;
}
return CRYPT_OK;
}
#endif

1008
prime.c Normal file

File diff suppressed because it is too large Load Diff

321
rc2.c Normal file
View File

@ -0,0 +1,321 @@
/**********************************************************************\
* To commemorate the 1996 RSA Data Security Conference, the following *
* code is released into the public domain by its author. Prost! *
* *
* This cipher uses 16-bit words and little-endian byte ordering. *
* I wonder which processor it was optimized for? *
* *
* Thanks to CodeView, SoftIce, and D86 for helping bring this code to *
* the public. *
\**********************************************************************/
#include <mycrypt.h>
#ifdef RC2
const struct _cipher_descriptor rc2_desc = {
"rc2",
12, 8, 128, 8, 16,
&rc2_setup,
&rc2_ecb_encrypt,
&rc2_ecb_decrypt,
&rc2_test,
&rc2_keysize
};
/**********************************************************************\
* Expand a variable-length user key (between 1 and 128 bytes) to a *
* 64-short working rc2 key, of at most "bits" effective key bits. *
* The effective key bits parameter looks like an export control hack. *
* For normal use, it should always be set to 1024. For convenience, *
* zero is accepted as an alias for 1024. *
\**********************************************************************/
/* 256-entry permutation table, probably derived somehow from pi */
static const unsigned char permute[256] = {
217,120,249,196, 25,221,181,237, 40,233,253,121, 74,160,216,157,
198,126, 55,131, 43,118, 83,142, 98, 76,100,136, 68,139,251,162,
23,154, 89,245,135,179, 79, 19, 97, 69,109,141, 9,129,125, 50,
189,143, 64,235,134,183,123, 11,240,149, 33, 34, 92,107, 78,130,
84,214,101,147,206, 96,178, 28,115, 86,192, 20,167,140,241,220,
18,117,202, 31, 59,190,228,209, 66, 61,212, 48,163, 60,182, 38,
111,191, 14,218, 70,105, 7, 87, 39,242, 29,155,188,148, 67, 3,
248, 17,199,246,144,239, 62,231, 6,195,213, 47,200,102, 30,215,
8,232,234,222,128, 82,238,247,132,170,114,172, 53, 77,106, 42,
150, 26,210,113, 90, 21, 73,116, 75,159,208, 94, 4, 24,164,236,
194,224, 65,110, 15, 81,203,204, 36,145,175, 80,161,244,112, 57,
153,124, 58,133, 35,184,180,122,252, 2, 54, 91, 37, 85,151, 49,
45, 93,250,152,227,138,146,174, 5,223, 41, 16,103,108,186,201,
211, 0,230,207,225,158,168, 44, 99, 22, 1, 63, 88,226,137,169,
13, 56, 52, 27,171, 51,255,176,187, 72, 12, 95,185,177,205, 46,
197,243,219, 71,229,165,156,119, 10,166, 32,104,254,127,193,173
};
int rc2_setup(const unsigned char *key, int keylen, int rounds, symmetric_key *skey)
{
unsigned *xkey = skey->rc2.xkey;
unsigned char tmp[128];
unsigned T8, TM;
int i, bits;
_ARGCHK(key != NULL);
_ARGCHK(skey != NULL);
if (keylen < 8 || keylen > 128) {
return CRYPT_INVALID_KEYSIZE;
}
if (rounds && rounds != 16) {
return CRYPT_INVALID_ROUNDS;
}
for (i = 0; i < keylen; i++) {
tmp[i] = key[i];
}
/* Phase 1: Expand input key to 128 bytes */
if (keylen < 128) {
for (i = keylen; i < 128; i++) {
tmp[i] = permute[(tmp[i - 1] + tmp[i - keylen]) & 255];
}
}
/* Phase 2 - reduce effective key size to "bits" */
bits = keylen*8;
T8 = (bits+7)>>3;
TM = (255 >> (7 & -bits));
tmp[128 - T8] = permute[tmp[128 - T8] & TM];
for (i = 127 - T8; i >= 0; i--) {
tmp[i] = permute[tmp[i + 1] ^ tmp[i + T8]];
}
/* Phase 3 - copy to xkey in little-endian order */
i = 63;
do {
xkey[i] = (unsigned)tmp[2*i] + ((unsigned)tmp[2*i+1] << 8);
} while (i--);
#ifdef CLEAN_STACK
zeromem(tmp, sizeof(tmp));
#endif
return CRYPT_OK;
}
/**********************************************************************\
* Encrypt an 8-byte block of plaintext using the given key. *
\**********************************************************************/
#ifdef CLEAN_STACK
static void _rc2_ecb_encrypt( const unsigned char *plain,
unsigned char *cipher,
symmetric_key *skey)
#else
void rc2_ecb_encrypt( const unsigned char *plain,
unsigned char *cipher,
symmetric_key *skey)
#endif
{
unsigned *xkey = skey->rc2.xkey;
unsigned x76, x54, x32, x10, i;
_ARGCHK(plain != NULL);
_ARGCHK(cipher != NULL);
_ARGCHK(skey != NULL);
x76 = ((unsigned)plain[7] << 8) + (unsigned)plain[6];
x54 = ((unsigned)plain[5] << 8) + (unsigned)plain[4];
x32 = ((unsigned)plain[3] << 8) + (unsigned)plain[2];
x10 = ((unsigned)plain[1] << 8) + (unsigned)plain[0];
for (i = 0; i < 16; i++) {
x10 = (x10 + (x32 & ~x76) + (x54 & x76) + xkey[4*i+0]) & 0xFFFF;
x10 = ((x10 << 1) | (x10 >> 15)) & 0xFFFF;
x32 = (x32 + (x54 & ~x10) + (x76 & x10) + xkey[4*i+1]) & 0xFFFF;
x32 = ((x32 << 2) | (x32 >> 14)) & 0xFFFF;
x54 = (x54 + (x76 & ~x32) + (x10 & x32) + xkey[4*i+2]) & 0xFFFF;
x54 = ((x54 << 3) | (x54 >> 13)) & 0xFFFF;
x76 = (x76 + (x10 & ~x54) + (x32 & x54) + xkey[4*i+3]) & 0xFFFF;
x76 = ((x76 << 5) | (x76 >> 11)) & 0xFFFF;
if (i == 4 || i == 10) {
x10 = (x10 + xkey[x76 & 63]) & 0xFFFF;
x32 = (x32 + xkey[x10 & 63]) & 0xFFFF;
x54 = (x54 + xkey[x32 & 63]) & 0xFFFF;
x76 = (x76 + xkey[x54 & 63]) & 0xFFFF;
}
}
cipher[0] = (unsigned char)x10;
cipher[1] = (unsigned char)(x10 >> 8);
cipher[2] = (unsigned char)x32;
cipher[3] = (unsigned char)(x32 >> 8);
cipher[4] = (unsigned char)x54;
cipher[5] = (unsigned char)(x54 >> 8);
cipher[6] = (unsigned char)x76;
cipher[7] = (unsigned char)(x76 >> 8);
}
#ifdef CLEAN_STACK
void rc2_ecb_encrypt( const unsigned char *plain,
unsigned char *cipher,
symmetric_key *skey)
{
_rc2_ecb_encrypt(plain, cipher, skey);
burn_stack(sizeof(unsigned *) + sizeof(unsigned) * 5);
}
#endif
/**********************************************************************\
* Decrypt an 8-byte block of ciphertext using the given key. *
\**********************************************************************/
#ifdef CLEAN_STACK
static void _rc2_ecb_decrypt( const unsigned char *cipher,
unsigned char *plain,
symmetric_key *skey)
#else
void rc2_ecb_decrypt( const unsigned char *cipher,
unsigned char *plain,
symmetric_key *skey)
#endif
{
unsigned x76, x54, x32, x10;
unsigned *xkey = skey->rc2.xkey;
int i;
_ARGCHK(plain != NULL);
_ARGCHK(cipher != NULL);
_ARGCHK(skey != NULL);
x76 = ((unsigned)cipher[7] << 8) + (unsigned)cipher[6];
x54 = ((unsigned)cipher[5] << 8) + (unsigned)cipher[4];
x32 = ((unsigned)cipher[3] << 8) + (unsigned)cipher[2];
x10 = ((unsigned)cipher[1] << 8) + (unsigned)cipher[0];
for (i = 15; i >= 0; i--) {
if (i == 4 || i == 10) {
x76 = (x76 - xkey[x54 & 63]) & 0xFFFF;
x54 = (x54 - xkey[x32 & 63]) & 0xFFFF;
x32 = (x32 - xkey[x10 & 63]) & 0xFFFF;
x10 = (x10 - xkey[x76 & 63]) & 0xFFFF;
}
x76 = ((x76 << 11) | (x76 >> 5)) & 0xFFFF;
x76 = (x76 - ((x10 & ~x54) + (x32 & x54) + xkey[4*i+3])) & 0xFFFF;
x54 = ((x54 << 13) | (x54 >> 3)) & 0xFFFF;
x54 = (x54 - ((x76 & ~x32) + (x10 & x32) + xkey[4*i+2])) & 0xFFFF;
x32 = ((x32 << 14) | (x32 >> 2)) & 0xFFFF;
x32 = (x32 - ((x54 & ~x10) + (x76 & x10) + xkey[4*i+1])) & 0xFFFF;
x10 = ((x10 << 15) | (x10 >> 1)) & 0xFFFF;
x10 = (x10 - ((x32 & ~x76) + (x54 & x76) + xkey[4*i+0])) & 0xFFFF;
}
plain[0] = (unsigned char)x10;
plain[1] = (unsigned char)(x10 >> 8);
plain[2] = (unsigned char)x32;
plain[3] = (unsigned char)(x32 >> 8);
plain[4] = (unsigned char)x54;
plain[5] = (unsigned char)(x54 >> 8);
plain[6] = (unsigned char)x76;
plain[7] = (unsigned char)(x76 >> 8);
}
#ifdef CLEAN_STACK
void rc2_ecb_decrypt( const unsigned char *cipher,
unsigned char *plain,
symmetric_key *skey)
{
_rc2_ecb_decrypt(cipher, plain, skey);
burn_stack(sizeof(unsigned *) + sizeof(unsigned) * 4 + sizeof(int));
}
#endif
int rc2_test(void)
{
static const struct {
int keylen;
unsigned char key[16], pt[8], ct[8];
} tests[] = {
{ 8,
{ 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
{ 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 },
{ 0x30, 0x64, 0x9e, 0xdf, 0x9b, 0xe7, 0xd2, 0xc2 }
},
{ 16,
{ 0x88, 0xbc, 0xa9, 0x0e, 0x90, 0x87, 0x5a, 0x7f,
0x0f, 0x79, 0xc3, 0x84, 0x62, 0x7b, 0xaf, 0xb2 },
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
{ 0x22, 0x69, 0x55, 0x2a, 0xb0, 0xf8, 0x5c, 0xa6 }
}
};
int x, failed, errno;
symmetric_key skey;
unsigned char buf[2][8];
failed = 0;
for (x = 0; x < (int)(sizeof(tests) / sizeof(tests[0])); x++) {
zeromem(buf, sizeof(buf));
if ((errno = rc2_setup(tests[x].key, tests[x].keylen, 0, &skey)) != CRYPT_OK) {
return errno;
}
rc2_ecb_encrypt(tests[x].pt, buf[0], &skey);
rc2_ecb_decrypt(buf[0], buf[1], &skey);
if (memcmp(buf[0], tests[x].ct, 8)) {
#if 0
int y;
printf("\nTest %d failed to encrypt\n", x);
for (y = 0; y < 8; y++) {
printf("%02x ", buf[0][y]);
}
printf("\n");
#endif
failed = 1;
}
if (memcmp(buf[1], tests[x].pt, 8)) {
#if 0
int y;
printf("\nTest %d failed to decrypt\n", x);
for (y = 0; y < 8; y++) {
printf("%02x ", buf[1][y]);
}
printf("\n");
#endif
failed = 1;
}
}
if (failed == 1) {
return CRYPT_FAIL_TESTVECTOR;
} else {
return CRYPT_OK;
}
}
int rc2_keysize(int *keysize)
{
_ARGCHK(keysize != NULL);
if (*keysize < 8) {
return CRYPT_INVALID_KEYSIZE;
} else if (*keysize > 128) {
*keysize = 128;
}
return CRYPT_OK;
}
#endif

97
rc4.c Normal file
View File

@ -0,0 +1,97 @@
#include "mycrypt.h"
#ifdef RC4
const struct _prng_descriptor rc4_desc =
{
"rc4",
&rc4_start,
&rc4_add_entropy,
&rc4_ready,
&rc4_read
};
int rc4_start(prng_state *prng)
{
_ARGCHK(prng != NULL);
/* set keysize to zero */
prng->rc4.x = 0;
return CRYPT_OK;
}
int rc4_add_entropy(const unsigned char *buf, unsigned long len, prng_state *prng)
{
_ARGCHK(buf != NULL);
_ARGCHK(prng != NULL);
if (prng->rc4.x + len > 256) {
return CRYPT_INVALID_KEYSIZE;
}
while (len--) {
prng->rc4.buf[prng->rc4.x++] = *buf++;
}
return CRYPT_OK;
}
int rc4_ready(prng_state *prng)
{
unsigned char key[256], tmp;
int keylen, x, y;
_ARGCHK(prng != NULL);
/* extract the key */
memcpy(key, prng->rc4.buf, 256);
keylen = prng->rc4.x;
/* make RC4 perm and shuffle */
for (x = 0; x < 256; x++) {
prng->rc4.buf[x] = x;
}
for (x = y = 0; x < 256; x++) {
y = (y + prng->rc4.buf[x] + key[x % keylen]) & 255;
tmp = prng->rc4.buf[x]; prng->rc4.buf[x] = prng->rc4.buf[y]; prng->rc4.buf[y] = tmp;
}
prng->rc4.x = x;
prng->rc4.y = y;
#ifdef CLEAN_STACK
zeromem(key, sizeof(key));
#endif
return CRYPT_OK;
}
unsigned long rc4_read(unsigned char *buf, unsigned long len, prng_state *prng)
{
int x, y;
unsigned char *s, tmp;
unsigned long n;
_ARGCHK(buf != NULL);
_ARGCHK(prng != NULL);
n = len;
x = prng->rc4.x;
y = prng->rc4.y;
s = prng->rc4.buf;
while (len--) {
x = (x + 1) & 255;
y = (y + s[x]) & 255;
tmp = s[x]; s[x] = s[y]; s[y] = tmp;
tmp = (s[x] + s[y]) & 255;
*buf++ ^= s[tmp];
}
prng->rc4.x = x;
prng->rc4.y = y;
return n;
}
#endif

234
rc5.c Normal file
View File

@ -0,0 +1,234 @@
#include "mycrypt.h"
#ifdef RC5
const struct _cipher_descriptor rc5_desc =
{
"rc5",
2,
8, 128, 8, 12,
&rc5_setup,
&rc5_ecb_encrypt,
&rc5_ecb_decrypt,
&rc5_test,
&rc5_keysize
};
#ifdef CLEAN_STACK
static int _rc5_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey)
#else
int rc5_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey)
#endif
{
unsigned long L[64], S[50], A, B, i, j, v, s, t, l;
_ARGCHK(skey != NULL);
_ARGCHK(key != NULL);
/* test parameters */
if (num_rounds == 0) {
num_rounds = rc5_desc.default_rounds;
}
if (num_rounds < 12 || num_rounds > 24) {
return CRYPT_INVALID_ROUNDS;
}
/* key must be between 64 and 1024 bits */
if (keylen < 8 || keylen > 128) {
return CRYPT_INVALID_KEYSIZE;
}
/* copy the key into the L array */
for (A = i = j = 0; i < (unsigned long)keylen; ) {
A = (A << 8) | ((unsigned long)(key[i++] & 255));
if (!(i & 3)) {
L[j++] = BSWAP(A);
A = 0;
}
}
if (keylen & 3) {
A <<= (8 * (4 - (keylen&3)));
L[j++] = BSWAP(A);
}
/* setup the S array */
t = 2 * (num_rounds + 1);
S[0] = 0xB7E15163UL;
for (i = 1; i < t; i++) S[i] = S[i - 1] + 0x9E3779B9UL;
/* mix buffer */
s = 3 * MAX(t, j);
l = j;
for (A = B = i = j = v = 0; v < s; v++) {
A = S[i] = ROL(S[i] + A + B, 3);
B = L[j] = ROL(L[j] + A + B, (A+B));
i = (i + 1) % t;
j = (j + 1) % l;
}
/* copy to key */
for (i = 0; i < t; i++) {
skey->rc5.K[i] = S[i];
}
skey->rc5.rounds = num_rounds;
return CRYPT_OK;
}
#ifdef CLEAN_STACK
int rc5_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey)
{
int x;
x = _rc5_setup(key, keylen, num_rounds, skey);
burn_stack(sizeof(unsigned long) * 122 + sizeof(int));
return x;
}
#endif
#ifdef CLEAN_STACK
static void _rc5_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *key)
#else
void rc5_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *key)
#endif
{
unsigned long A, B;
int r;
_ARGCHK(key != NULL);
_ARGCHK(pt != NULL);
_ARGCHK(ct != NULL);
LOAD32L(A, &pt[0]);
LOAD32L(B, &pt[4]);
A += key->rc5.K[0];
B += key->rc5.K[1];
for (r = 0; r < key->rc5.rounds; r++) {
A = ROL(A ^ B, B) + key->rc5.K[r+r+2];
B = ROL(B ^ A, A) + key->rc5.K[r+r+3];
}
STORE32L(A, &ct[0]);
STORE32L(B, &ct[4]);
}
#ifdef CLEAN_STACK
void rc5_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *key)
{
_rc5_ecb_encrypt(pt, ct, key);
burn_stack(sizeof(unsigned long) * 2 + sizeof(int));
}
#endif
#ifdef CLEAN_STACK
static void _rc5_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *key)
#else
void rc5_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *key)
#endif
{
unsigned long A, B;
int r;
_ARGCHK(key != NULL);
_ARGCHK(pt != NULL);
_ARGCHK(ct != NULL);
LOAD32L(A, &ct[0]);
LOAD32L(B, &ct[4]);
for (r = key->rc5.rounds - 1; r >= 0; r--) {
B = ROR(B - key->rc5.K[r+r+3], A) ^ A;
A = ROR(A - key->rc5.K[r+r+2], B) ^ B;
}
A -= key->rc5.K[0];
B -= key->rc5.K[1];
STORE32L(A, &pt[0]);
STORE32L(B, &pt[4]);
}
#ifdef CLEAN_STACK
void rc5_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *key)
{
_rc5_ecb_decrypt(ct, pt, key);
burn_stack(sizeof(unsigned long) * 2 + sizeof(int));
}
#endif
int rc5_test(void)
{
static const struct {
unsigned char key[16], pt[8], ct[8];
} tests[] = {
{
{ 0x91, 0x5f, 0x46, 0x19, 0xbe, 0x41, 0xb2, 0x51,
0x63, 0x55, 0xa5, 0x01, 0x10, 0xa9, 0xce, 0x91 },
{ 0x21, 0xa5, 0xdb, 0xee, 0x15, 0x4b, 0x8f, 0x6d },
{ 0xf7, 0xc0, 0x13, 0xac, 0x5b, 0x2b, 0x89, 0x52 }
},
{
{ 0x78, 0x33, 0x48, 0xe7, 0x5a, 0xeb, 0x0f, 0x2f,
0xd7, 0xb1, 0x69, 0xbb, 0x8d, 0xc1, 0x67, 0x87 },
{ 0xF7, 0xC0, 0x13, 0xAC, 0x5B, 0x2B, 0x89, 0x52 },
{ 0x2F, 0x42, 0xB3, 0xB7, 0x03, 0x69, 0xFC, 0x92 }
},
{
{ 0xDC, 0x49, 0xdb, 0x13, 0x75, 0xa5, 0x58, 0x4f,
0x64, 0x85, 0xb4, 0x13, 0xb5, 0xf1, 0x2b, 0xaf },
{ 0x2F, 0x42, 0xB3, 0xB7, 0x03, 0x69, 0xFC, 0x92 },
{ 0x65, 0xc1, 0x78, 0xb2, 0x84, 0xd1, 0x97, 0xcc }
}
};
unsigned char buf[2][8];
int x, failed, errno;
symmetric_key key;
for (x = failed = 0; x < (int)(sizeof(tests) / sizeof(tests[0])); x++) {
/* setup key */
if ((errno = rc5_setup(tests[x].key, 16, 12, &key)) != CRYPT_OK) {
return errno;
}
/* encrypt and decrypt */
rc5_ecb_encrypt(tests[x].pt, buf[0], &key);
rc5_ecb_decrypt(buf[0], buf[1], &key);
/* compare */
if (memcmp(buf[0], tests[x].ct, 8)) {
#if 0
int y;
printf("\nEncrypt test %d failed\n", x);
for (y = 0; y < 8; y++) printf("%02x ", buf[0][y]);
printf("\n");
#endif
failed = 1;
}
if (memcmp(buf[1], tests[x].pt, 8)) {
#if 0
int y;
printf("\nDecrypt test %d failed\n", x);
for (y = 0; y < 8; y++) printf("%02x ", buf[1][y]);
printf("\n");
#endif
failed = 1;
}
}
if (failed == 1) {
return CRYPT_FAIL_TESTVECTOR;
} else {
return CRYPT_OK;
}
}
int rc5_keysize(int *desired_keysize)
{
_ARGCHK(desired_keysize != NULL);
if (*desired_keysize < 8) {
return CRYPT_INVALID_KEYSIZE;
} else if (*desired_keysize > 128) {
*desired_keysize = 128;
}
return CRYPT_OK;
}
#endif

253
rc6.c Normal file
View File

@ -0,0 +1,253 @@
#include "mycrypt.h"
#ifdef RC6
const struct _cipher_descriptor rc6_desc =
{
"rc6",
3,
8, 128, 16, 20,
&rc6_setup,
&rc6_ecb_encrypt,
&rc6_ecb_decrypt,
&rc6_test,
&rc6_keysize
};
#ifdef CLEAN_STACK
static int _rc6_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey)
#else
int rc6_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey)
#endif
{
unsigned long L[64], S[50], A, B, i, j, v, s, t, l;
_ARGCHK(key != NULL);
_ARGCHK(skey != NULL);
/* test parameters */
if (num_rounds != 0 && num_rounds != 20) {
return CRYPT_INVALID_ROUNDS;
}
/* key must be between 64 and 1024 bits */
if (keylen < 8 || keylen > 128) {
return CRYPT_INVALID_KEYSIZE;
}
/* copy the key into the L array */
for (A = i = j = 0; i < (unsigned long)keylen; ) {
A = (A << 8) | ((unsigned long)(key[i++] & 255));
if (!(i & 3)) {
L[j++] = BSWAP(A);
A = 0;
}
}
/* handle odd sized keys */
if (keylen & 3) {
A <<= (8 * (4 - (keylen&3)));
L[j++] = BSWAP(A);
}
/* setup the S array */
t = 44; /* fixed at 20 rounds */
S[0] = 0xB7E15163UL;
for (i = 1; i < t; i++)
S[i] = S[i - 1] + 0x9E3779B9UL;
/* mix buffer */
s = 3 * MAX(t, j);
l = j;
for (A = B = i = j = v = 0; v < s; v++) {
A = S[i] = ROL(S[i] + A + B, 3);
B = L[j] = ROL(L[j] + A + B, (A+B));
i = (i + 1) % t;
j = (j + 1) % l;
}
/* copy to key */
for (i = 0; i < t; i++) {
skey->rc6.K[i] = S[i];
}
return CRYPT_OK;
}
#ifdef CLEAN_STACK
int rc6_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey)
{
int x;
x = _rc6_setup(key, keylen, num_rounds, skey);
burn_stack(sizeof(unsigned long) * 122);
return x;
}
#endif
#ifdef CLEAN_STACK
static void _rc6_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *key)
#else
void rc6_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *key)
#endif
{
unsigned long a,b,c,d,t,u;
int r;
_ARGCHK(key != NULL);
_ARGCHK(pt != NULL);
_ARGCHK(ct != NULL);
LOAD32L(a,&pt[0]);LOAD32L(b,&pt[4]);LOAD32L(c,&pt[8]);LOAD32L(d,&pt[12]);
b += key->rc6.K[0];
d += key->rc6.K[1];
for (r = 0; r < 20; r++) {
t = (b * (b + b + 1)); t = ROL(t, 5);
u = (d * (d + d + 1)); u = ROL(u, 5);
a = ROL(a^t,u) + key->rc6.K[r+r+2];
c = ROL(c^u,t) + key->rc6.K[r+r+3];
t = a; a = b; b = c; c = d; d = t;
}
a += key->rc6.K[42];
c += key->rc6.K[43];
STORE32L(a,&ct[0]);STORE32L(b,&ct[4]);STORE32L(c,&ct[8]);STORE32L(d,&ct[12]);
}
#ifdef CLEAN_STACK
void rc6_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *key)
{
_rc6_ecb_encrypt(pt, ct, key);
burn_stack(sizeof(unsigned long) * 6 + sizeof(int));
}
#endif
#ifdef CLEAN_STACK
static void _rc6_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *key)
#else
void rc6_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *key)
#endif
{
unsigned long a,b,c,d,t,u;
int r;
_ARGCHK(key != NULL);
_ARGCHK(pt != NULL);
_ARGCHK(ct != NULL);
LOAD32L(a,&ct[0]);LOAD32L(b,&ct[4]);LOAD32L(c,&ct[8]);LOAD32L(d,&ct[12]);
a -= key->rc6.K[42];
c -= key->rc6.K[43];
for (r = 19; r >= 0; r--) {
t = d; d = c; c = b; b = a; a = t;
t = (b * (b + b + 1)); t = ROL(t, 5);
u = (d * (d + d + 1)); u = ROL(u, 5);
c = ROR(c - key->rc6.K[r+r+3], t) ^ u;
a = ROR(a - key->rc6.K[r+r+2], u) ^ t;
}
b -= key->rc6.K[0];
d -= key->rc6.K[1];
STORE32L(a,&pt[0]);STORE32L(b,&pt[4]);STORE32L(c,&pt[8]);STORE32L(d,&pt[12]);
}
#ifdef CLEAN_STACK
void rc6_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *key)
{
_rc6_ecb_decrypt(ct, pt, key);
burn_stack(sizeof(unsigned long) * 6 + sizeof(int));
}
#endif
int rc6_test(void)
{
static const struct {
int keylen;
unsigned char key[32], pt[16], ct[16];
} tests[] = {
{
16,
{ 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
0x01, 0x12, 0x23, 0x34, 0x45, 0x56, 0x67, 0x78,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
{ 0x02, 0x13, 0x24, 0x35, 0x46, 0x57, 0x68, 0x79,
0x8a, 0x9b, 0xac, 0xbd, 0xce, 0xdf, 0xe0, 0xf1 },
{ 0x52, 0x4e, 0x19, 0x2f, 0x47, 0x15, 0xc6, 0x23,
0x1f, 0x51, 0xf6, 0x36, 0x7e, 0xa4, 0x3f, 0x18 }
},
{
24,
{ 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
0x01, 0x12, 0x23, 0x34, 0x45, 0x56, 0x67, 0x78,
0x89, 0x9a, 0xab, 0xbc, 0xcd, 0xde, 0xef, 0xf0,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
{ 0x02, 0x13, 0x24, 0x35, 0x46, 0x57, 0x68, 0x79,
0x8a, 0x9b, 0xac, 0xbd, 0xce, 0xdf, 0xe0, 0xf1 },
{ 0x68, 0x83, 0x29, 0xd0, 0x19, 0xe5, 0x05, 0x04,
0x1e, 0x52, 0xe9, 0x2a, 0xf9, 0x52, 0x91, 0xd4 }
},
{
32,
{ 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
0x01, 0x12, 0x23, 0x34, 0x45, 0x56, 0x67, 0x78,
0x89, 0x9a, 0xab, 0xbc, 0xcd, 0xde, 0xef, 0xf0,
0x10, 0x32, 0x54, 0x76, 0x98, 0xba, 0xdc, 0xfe },
{ 0x02, 0x13, 0x24, 0x35, 0x46, 0x57, 0x68, 0x79,
0x8a, 0x9b, 0xac, 0xbd, 0xce, 0xdf, 0xe0, 0xf1 },
{ 0xc8, 0x24, 0x18, 0x16, 0xf0, 0xd7, 0xe4, 0x89,
0x20, 0xad, 0x16, 0xa1, 0x67, 0x4e, 0x5d, 0x48 }
}
};
unsigned char buf[2][16];
int x, failed, errno;
symmetric_key key;
for (x = failed = 0; x < (int)(sizeof(tests) / sizeof(tests[0])); x++) {
/* setup key */
if ((errno = rc6_setup(tests[x].key, tests[x].keylen, 0, &key)) != CRYPT_OK) {
return errno;
}
/* encrypt and decrypt */
rc6_ecb_encrypt(tests[x].pt, buf[0], &key);
rc6_ecb_decrypt(buf[0], buf[1], &key);
/* compare */
if (memcmp(buf[0], tests[x].ct, 16)) {
#if 0
int y;
printf("\nEncrypt test %d failed\n", x);
for (y = 0; y < 16; y++) printf("%02x ", buf[0][y]);
printf("\n");
#endif
failed = 1;
}
if (memcmp(buf[1], tests[x].pt, 16)) {
#if 0
int y;
printf("\nDecrypt test %d failed\n", x);
for (y = 0; y < 16; y++) printf("%02x ", buf[1][y]);
printf("\n");
#endif
failed = 1;
}
}
if (failed == 1) {
return CRYPT_FAIL_TESTVECTOR;
} else {
return CRYPT_OK;
}
}
int rc6_keysize(int *desired_keysize)
{
_ARGCHK(desired_keysize != NULL);
if (*desired_keysize < 8) {
return CRYPT_INVALID_KEYSIZE;
} else if (*desired_keysize > 128) {
*desired_keysize = 128;
}
return CRYPT_OK;
}
#endif /*RC6*/

436
rsa.c Normal file
View File

@ -0,0 +1,436 @@
#include "mycrypt.h"
#ifdef MRSA
int rsa_make_key(prng_state *prng, int wprng, int size, long e, rsa_key *key)
{
mp_int p, q, tmp1, tmp2, tmp3;
int res, errno;
_ARGCHK(key != NULL);
if ((size < (1024/8)) || (size > (4096/8))) {
return CRYPT_INVALID_KEYSIZE;
}
if ((e < 3) || (!(e & 1))) {
return CRYPT_INVALID_ARG;
}
if ((errno = prng_is_valid(wprng)) != CRYPT_OK) {
return errno;
}
if (mp_init_multi(&p, &q, &tmp1, &tmp2, &tmp3, NULL) != MP_OKAY) {
return CRYPT_MEM;
}
/* make primes p and q (optimization provided by Wayne Scott) */
if (mp_set_int(&tmp3, e) != MP_OKAY) { goto error; } /* tmp3 = e */
/* make prime "p" */
do {
if (rand_prime(&p, size/2, prng, wprng) != CRYPT_OK) { res = CRYPT_ERROR; goto done; }
if (mp_sub_d(&p, 1, &tmp1) != MP_OKAY) { goto error; } /* tmp1 = p-1 */
if (mp_gcd(&tmp1, &tmp3, &tmp2) != MP_OKAY) { goto error; } /* tmp2 = gcd(p-1, e) */
} while (mp_cmp_d(&tmp2, 1) != 0);
/* make prime "q" */
do {
if (rand_prime(&q, size/2, prng, wprng) != CRYPT_OK) { res = CRYPT_ERROR; goto done; }
if (mp_sub_d(&q, 1, &tmp1) != MP_OKAY) { goto error; } /* tmp1 = q-1 */
if (mp_gcd(&tmp1, &tmp3, &tmp2) != MP_OKAY) { goto error; } /* tmp2 = gcd(q-1, e) */
} while (mp_cmp_d(&tmp2, 1) != 0);
/* tmp1 = lcm(p-1, q-1) */
if (mp_sub_d(&p, 1, &tmp2) != MP_OKAY) { goto error; } /* tmp2 = p-1 */
/* tmp1 = q-1 (previous do/while loop) */
if (mp_lcm(&tmp1, &tmp2, &tmp1) != MP_OKAY) { goto error; } /* tmp1 = lcm(p-1, q-1) */
/* make key */
if (mp_init_multi(&key->e, &key->d, &key->N, &key->dQ, &key->dP,
&key->qP, &key->pQ, &key->p, &key->q, NULL) != MP_OKAY) {
goto error;
}
mp_set_int(&key->e, e); /* key->e = e */
if (mp_invmod(&key->e, &tmp1, &key->d) != MP_OKAY) goto error2; /* key->d = 1/e mod lcm(p-1,q-1) */
if (mp_mul(&p, &q, &key->N) != MP_OKAY) goto error2; /* key->N = pq */
/* optimize for CRT now */
/* find d mod q-1 and d mod p-1 */
if (mp_sub_d(&p, 1, &tmp1) != MP_OKAY) { goto error2; } /* tmp1 = q-1 */
if (mp_sub_d(&q, 1, &tmp2) != MP_OKAY) { goto error2; } /* tmp2 = p-1 */
if (mp_mod(&key->d, &tmp1, &key->dP) != MP_OKAY) { goto error2; } /* dP = d mod p-1 */
if (mp_mod(&key->d, &tmp2, &key->dQ) != MP_OKAY) { goto error2; } /* dQ = d mod q-1 */
if (mp_invmod(&q, &p, &key->qP) != MP_OKAY) { goto error2; } /* qP = 1/q mod p */
if (mp_mulmod(&key->qP, &q, &key->N, &key->qP)) { goto error2; } /* qP = q * (1/q mod p) mod N */
if (mp_invmod(&p, &q, &key->pQ) != MP_OKAY) { goto error2; } /* pQ = 1/p mod q */
if (mp_mulmod(&key->pQ, &p, &key->N, &key->pQ)) { goto error2; } /* pQ = p * (1/p mod q) mod N */
if (mp_copy(&p, &key->p) != MP_OKAY) { goto error2; }
if (mp_copy(&q, &key->q) != MP_OKAY) { goto error2; }
res = CRYPT_OK;
key->type = PK_PRIVATE_OPTIMIZED;
goto done;
error2:
mp_clear_multi(&key->d, &key->e, &key->N, &key->dQ, &key->dP,
&key->qP, &key->pQ, &key->p, &key->q, NULL);
error:
res = CRYPT_MEM;
done:
mp_clear_multi(&tmp3, &tmp2, &tmp1, &p, &q, NULL);
return res;
}
void rsa_free(rsa_key *key)
{
_ARGCHK(key != NULL);
mp_clear_multi(&key->e, &key->d, &key->N, &key->dQ, &key->dP,
&key->qP, &key->pQ, &key->p, &key->q, NULL);
}
int rsa_exptmod(const unsigned char *in, unsigned long inlen,
unsigned char *out, unsigned long *outlen, int which,
rsa_key *key)
{
mp_int tmp, tmpa, tmpb;
unsigned long x;
int res;
_ARGCHK(in != NULL);
_ARGCHK(out != NULL);
_ARGCHK(outlen != NULL);
_ARGCHK(key != NULL);
if (which == PK_PRIVATE && (key->type != PK_PRIVATE && key->type != PK_PRIVATE_OPTIMIZED)) {
return CRYPT_PK_NOT_PRIVATE;
}
/* init and copy into tmp */
if (mp_init_multi(&tmp, &tmpa, &tmpb, NULL) != MP_OKAY) { goto error; }
if (mp_read_unsigned_bin(&tmp, (unsigned char *)in, inlen) != MP_OKAY) { goto error; }
/* sanity check on the input */
if (mp_cmp(&key->N, &tmp) == MP_LT) {
res = CRYPT_PK_INVALID_SIZE;
goto done;
}
/* are we using the private exponent and is the key optimized? */
if (which == PK_PRIVATE && key->type == PK_PRIVATE_OPTIMIZED) {
/* tmpa = tmp^dP mod p */
if (mp_exptmod(&tmp, &key->dP, &key->p, &tmpa) != MP_OKAY) { goto error; }
/* tmpb = tmp^dQ mod q */
if (mp_exptmod(&tmp, &key->dQ, &key->q, &tmpb) != MP_OKAY) { goto error; }
/* tmp = tmpa*qP + tmpb*pQ mod N */
if (mp_mul(&tmpa, &key->qP, &tmpa) != MP_OKAY) { goto error; }
if (mp_mul(&tmpb, &key->pQ, &tmpb) != MP_OKAY) { goto error; }
if (mp_addmod(&tmpa, &tmpb, &key->N, &tmp) != MP_OKAY) { goto error; }
} else {
/* exptmod it */
if (mp_exptmod(&tmp, which==PK_PRIVATE?&key->d:&key->e, &key->N, &tmp) != MP_OKAY) { goto error; }
}
/* read it back */
x = mp_raw_size(&tmp)-1;
if (x > *outlen) {
res = CRYPT_BUFFER_OVERFLOW;
goto done;
}
*outlen = x;
/* convert it */
mp_to_unsigned_bin(&tmp, out);
/* clean up and return */
res = CRYPT_OK;
goto done;
error:
res = CRYPT_MEM;
done:
mp_clear_multi(&tmp, &tmpa, &tmpb, NULL);
return res;
}
int rsa_signpad(const unsigned char *in, unsigned long inlen,
unsigned char *out, unsigned long *outlen)
{
unsigned long x, y;
_ARGCHK(in != NULL);
_ARGCHK(out != NULL);
_ARGCHK(outlen != NULL);
if (*outlen < (3 * inlen)) {
return CRYPT_BUFFER_OVERFLOW;
}
/* check inlen */
if ((inlen <= 0) || inlen > 512) {
return CRYPT_PK_INVALID_SIZE;
}
for (y = x = 0; x < inlen; x++)
out[y++] = 0xFF;
for (x = 0; x < inlen; x++)
out[y++] = in[x];
for (x = 0; x < inlen; x++)
out[y++] = 0xFF;
*outlen = 3 * inlen;
return CRYPT_OK;
}
int rsa_pad(const unsigned char *in, unsigned long inlen,
unsigned char *out, unsigned long *outlen,
int wprng, prng_state *prng)
{
unsigned char buf[2048];
unsigned long x;
int errno;
_ARGCHK(in != NULL);
_ARGCHK(out != NULL);
_ARGCHK(outlen != NULL);
/* is output big enough? */
if (*outlen < (3 * inlen)) {
return CRYPT_BUFFER_OVERFLOW;
}
/* get random padding required */
if ((errno = prng_is_valid(wprng)) != CRYPT_OK) {
return errno;
}
/* check inlen */
if ((inlen <= 0) || inlen > 512) {
return CRYPT_PK_INVALID_SIZE;
}
if (prng_descriptor[wprng].read(buf, inlen*2-2, prng) != (inlen*2 - 2)) {
return CRYPT_ERROR_READPRNG;
}
/* pad it like a sandwitch (sp?)
*
* Looks like 0xFF R1 M R2 0xFF
*
* Where R1/R2 are random and exactly equal to the length of M minus one byte.
*/
for (x = 0; x < inlen-1; x++) {
out[x+1] = buf[x];
}
for (x = 0; x < inlen; x++) {
out[x+inlen] = in[x];
}
for (x = 0; x < inlen-1; x++) {
out[x+inlen+inlen] = buf[x+inlen-1];
}
/* last and first bytes are 0xFF */
out[0] = 0xFF;
out[inlen+inlen+inlen-1] = 0xFF;
/* clear up and return */
#ifdef CLEAN_STACK
zeromem(buf, sizeof(buf));
#endif
*outlen = inlen*3;
return CRYPT_OK;
}
int rsa_signdepad(const unsigned char *in, unsigned long inlen,
unsigned char *out, unsigned long *outlen)
{
unsigned long x;
_ARGCHK(in != NULL);
_ARGCHK(out != NULL);
_ARGCHK(outlen != NULL);
if (*outlen < inlen/3) {
return CRYPT_BUFFER_OVERFLOW;
}
/* check padding bytes */
for (x = 0; x < inlen/3; x++) {
if (in[x] != 0xFF || in[x+(inlen/3)+(inlen/3)] != 0xFF) {
return CRYPT_INVALID_PACKET;
}
}
for (x = 0; x < inlen/3; x++)
out[x] = in[x+(inlen/3)];
*outlen = inlen/3;
return CRYPT_OK;
}
int rsa_depad(const unsigned char *in, unsigned long inlen,
unsigned char *out, unsigned long *outlen)
{
unsigned long x;
_ARGCHK(in != NULL);
_ARGCHK(out != NULL);
_ARGCHK(outlen != NULL);
if (*outlen < inlen/3) {
return CRYPT_BUFFER_OVERFLOW;
}
for (x = 0; x < inlen/3; x++)
out[x] = in[x+(inlen/3)];
*outlen = inlen/3;
return CRYPT_OK;
}
#define OUTPUT_BIGNUM(num, buf2, y, z) \
{ \
z = mp_raw_size(num); \
STORE32L(z, buf2+y); \
y += 4; \
mp_toraw(num, buf2+y); \
y += z; \
}
#define INPUT_BIGNUM(num, in, x, y) \
{ \
/* load value */ \
LOAD32L(x, in+y); \
y += 4; \
\
/* sanity check... */ \
if (x > 1024) { \
goto error2; \
} \
\
/* load it */ \
if (mp_read_raw(num, (unsigned char *)in+y, x) != MP_OKAY) {\
goto error2; \
} \
y += x; \
}
int rsa_export(unsigned char *out, unsigned long *outlen, int type, rsa_key *key)
{
unsigned char buf2[5120];
unsigned long y, z;
_ARGCHK(out != NULL);
_ARGCHK(outlen != NULL);
_ARGCHK(key != NULL);
/* type valid? */
if (!(key->type == PK_PRIVATE || key->type == PK_PRIVATE_OPTIMIZED) &&
(type == PK_PRIVATE || type == PK_PRIVATE_OPTIMIZED)) {
return CRYPT_PK_INVALID_TYPE;
}
/* start at offset y=PACKET_SIZE */
y = PACKET_SIZE;
/* output key type */
buf2[y++] = type;
/* output modulus */
OUTPUT_BIGNUM(&key->N, buf2, y, z);
/* output public key */
OUTPUT_BIGNUM(&key->e, buf2, y, z);
if (type == PK_PRIVATE || type == PK_PRIVATE_OPTIMIZED) {
OUTPUT_BIGNUM(&key->d, buf2, y, z);
}
if (type == PK_PRIVATE_OPTIMIZED) {
OUTPUT_BIGNUM(&key->dQ, buf2, y, z);
OUTPUT_BIGNUM(&key->dP, buf2, y, z);
OUTPUT_BIGNUM(&key->pQ, buf2, y, z);
OUTPUT_BIGNUM(&key->qP, buf2, y, z);
OUTPUT_BIGNUM(&key->p, buf2, y, z);
OUTPUT_BIGNUM(&key->q, buf2, y, z);
}
/* check size */
if (*outlen < y) {
return CRYPT_BUFFER_OVERFLOW;
}
/* store packet header */
packet_store_header(buf2, PACKET_SECT_RSA, PACKET_SUB_KEY, y);
/* copy to the user buffer */
memcpy(out, buf2, y);
*outlen = y;
/* clear stack and return */
#ifdef CLEAN_STACK
zeromem(buf2, sizeof(buf2));
#endif
return CRYPT_OK;
}
int rsa_import(const unsigned char *in, rsa_key *key)
{
unsigned long x, y;
int errno;
_ARGCHK(in != NULL);
_ARGCHK(key != NULL);
/* test packet header */
if ((errno = packet_valid_header((unsigned char *)in, PACKET_SECT_RSA, PACKET_SUB_KEY)) != CRYPT_OK) {
return errno;
}
/* init key */
if (mp_init_multi(&key->e, &key->d, &key->N, &key->dQ, &key->dP, &key->qP,
&key->pQ, &key->p, &key->q, NULL) != MP_OKAY) {
return CRYPT_MEM;
}
/* get key type */
y = PACKET_SIZE;
key->type = in[y++];
/* load the modulus */
INPUT_BIGNUM(&key->N, in, x, y);
/* load public exponent */
INPUT_BIGNUM(&key->e, in, x, y);
/* get private exponent */
if (key->type == PK_PRIVATE || key->type == PK_PRIVATE_OPTIMIZED) {
INPUT_BIGNUM(&key->d, in, x, y);
}
/* get CRT private data if required */
if (key->type == PK_PRIVATE_OPTIMIZED) {
INPUT_BIGNUM(&key->dQ, in, x, y);
INPUT_BIGNUM(&key->dP, in, x, y);
INPUT_BIGNUM(&key->pQ, in, x, y);
INPUT_BIGNUM(&key->qP, in, x, y);
INPUT_BIGNUM(&key->p, in, x, y);
INPUT_BIGNUM(&key->q, in, x, y);
}
return CRYPT_OK;
error2:
mp_clear_multi(&key->d, &key->e, &key->N, &key->dQ, &key->dP,
&key->pQ, &key->qP, &key->p, &key->q, NULL);
return CRYPT_MEM;
}
#include "rsa_sys.c"
#endif /* RSA */

584
rsa_sys.c Normal file
View File

@ -0,0 +1,584 @@
#ifdef PK_PACKET
int rsa_encrypt(const unsigned char *in, unsigned long len,
unsigned char *out, unsigned long *outlen,
prng_state *prng, int wprng, int cipher,
rsa_key *key)
{
unsigned char sym_IV[MAXBLOCKSIZE], sym_key[MAXBLOCKSIZE], rsa_in[4096], rsa_out[4096];
symmetric_CTR ctr;
unsigned long x, y, blklen, rsa_size;
int keylen, errno;;
_ARGCHK(in != NULL);
_ARGCHK(out != NULL);
_ARGCHK(outlen != NULL);
_ARGCHK(key != NULL);
/* are the parameters valid? */
if ((errno = prng_is_valid(wprng)) != CRYPT_OK) {
return errno;
}
if ((errno = cipher_is_valid(cipher)) != CRYPT_OK) {
return errno;
}
/* setup the CTR key */
keylen = 32; /* default to 256-bit keys */
if ((errno = cipher_descriptor[cipher].keysize(&keylen)) != CRYPT_OK) {
return errno;
}
blklen = cipher_descriptor[cipher].block_length;
if (prng_descriptor[wprng].read(sym_key, keylen, prng) != (unsigned long)keylen) {
return CRYPT_ERROR_READPRNG;
}
if (prng_descriptor[wprng].read(sym_IV, blklen, prng) != blklen) {
return CRYPT_ERROR_READPRNG;
}
/* setup CTR mode */
if ((errno = ctr_start(cipher, sym_IV, sym_key, keylen, 0, &ctr)) != CRYPT_OK) {
return errno;
}
/* rsa_pad the symmetric key */
y = sizeof(rsa_in);
if ((errno = rsa_pad(sym_key, keylen, rsa_in, &y, wprng, prng)) != CRYPT_OK) {
return errno;
}
/* rsa encrypt it */
rsa_size = sizeof(rsa_out);
if ((errno = rsa_exptmod(rsa_in, y, rsa_out, &rsa_size, PK_PUBLIC, key)) != CRYPT_OK) {
return errno;
}
/* check size */
if (*outlen < (PACKET_SIZE+9+rsa_size+blklen+len)) {
return CRYPT_BUFFER_OVERFLOW;
}
/* now lets make the header */
y = PACKET_SIZE;
out[y++] = cipher_descriptor[cipher].ID;
/* store the size of the RSA value */
STORE32L(rsa_size, (out+y));
y += 4;
/* store the rsa value */
for (x = 0; x < rsa_size; x++, y++) {
out[y] = rsa_out[x];
}
/* store the IV used */
for (x = 0; x < blklen; x++, y++) {
out[y] = sym_IV[x];
}
/* store the length */
STORE32L(len, (out+y));
y += 4;
/* encrypt the message */
if ((errno = ctr_encrypt(in, out+y, len, &ctr)) != CRYPT_OK) {
return errno;
}
y += len;
/* store the header */
packet_store_header(out, PACKET_SECT_RSA, PACKET_SUB_ENCRYPTED, y);
#ifdef CLEAN_STACK
/* clean up */
zeromem(sym_key, sizeof(sym_key));
zeromem(sym_IV, sizeof(sym_IV));
zeromem(&ctr, sizeof(ctr));
zeromem(rsa_in, sizeof(rsa_in));
zeromem(rsa_out, sizeof(rsa_out));
#endif
*outlen = y;
return CRYPT_OK;
}
int rsa_decrypt(const unsigned char *in, unsigned long len,
unsigned char *out, unsigned long *outlen,
rsa_key *key)
{
unsigned char sym_IV[MAXBLOCKSIZE], sym_key[MAXBLOCKSIZE], rsa_in[4096], rsa_out[4096];
symmetric_CTR ctr;
unsigned long x, y, z, keylen, blklen, rsa_size;
int cipher, errno;
_ARGCHK(in != NULL);
_ARGCHK(out != NULL);
_ARGCHK(outlen != NULL);
_ARGCHK(key != NULL);
/* right key type? */
if (key->type != PK_PRIVATE && key->type != PK_PRIVATE_OPTIMIZED) {
return CRYPT_PK_NOT_PRIVATE;
}
/* check the header */
if ((errno = packet_valid_header((unsigned char *)in, PACKET_SECT_RSA, PACKET_SUB_ENCRYPTED)) != CRYPT_OK) {
return errno;
}
/* grab cipher name */
y = PACKET_SIZE;
cipher = find_cipher_id(in[y++]);
if (cipher == -1) {
return CRYPT_INVALID_CIPHER;
}
keylen = MIN(cipher_descriptor[cipher].max_key_length, 32);
blklen = cipher_descriptor[cipher].block_length;
/* grab length of the rsa key */
LOAD32L(rsa_size, (in+y))
y += 4;
/* read it in */
for (x = 0; x < rsa_size; x++, y++) {
rsa_in[x] = in[y];
}
/* decrypt it */
x = sizeof(rsa_out);
if ((errno = rsa_exptmod(rsa_in, rsa_size, rsa_out, &x, PK_PRIVATE, key)) != CRYPT_OK) {
return errno;
}
/* depad it */
z = sizeof(sym_key);
if ((errno = rsa_depad(rsa_out, x, sym_key, &z)) != CRYPT_OK) {
return errno;
}
/* read the IV in */
for (x = 0; x < blklen; x++, y++) {
sym_IV[x] = in[y];
}
/* setup CTR mode */
if ((errno = ctr_start(cipher, sym_IV, sym_key, keylen, 0, &ctr)) != CRYPT_OK) {
return errno;
}
/* get len */
LOAD32L(len, (in+y));
y += 4;
/* check size */
if (*outlen < len) {
return CRYPT_BUFFER_OVERFLOW;
}
/* decrypt the message */
if ((errno = ctr_decrypt(in+y, out, len, &ctr)) != CRYPT_OK) {
return errno;
}
#ifdef CLEAN_STACK
/* clean up */
zeromem(sym_key, sizeof(sym_key));
zeromem(sym_IV, sizeof(sym_IV));
zeromem(&ctr, sizeof(ctr));
zeromem(rsa_in, sizeof(rsa_in));
zeromem(rsa_out, sizeof(rsa_out));
#endif
*outlen = len;
return CRYPT_OK;
}
/* Signature Message Format
offset | length | Contents
----------------------------------------------------------------------
0 | 1 | hash ID
1 | 4 | length of rsa_pad'ed signature
5 | p | the rsa_pad'ed signature
*/
int rsa_sign(const unsigned char *in, unsigned long inlen,
unsigned char *out, unsigned long *outlen,
int hash, rsa_key *key)
{
unsigned long hashlen, rsa_size, x, y, z;
unsigned char rsa_in[4096], rsa_out[4096];
int errno;
_ARGCHK(in != NULL);
_ARGCHK(out != NULL);
_ARGCHK(outlen != NULL);
_ARGCHK(key != NULL);
/* type of key? */
if (key->type != PK_PRIVATE && key->type != PK_PRIVATE_OPTIMIZED) {
return CRYPT_PK_NOT_PRIVATE;
}
/* are the parameters valid? */
if ((errno = hash_is_valid(hash)) != CRYPT_OK) {
return errno;
}
/* hash it */
hashlen = hash_descriptor[hash].hashsize;
z = sizeof(rsa_in);
if ((errno = hash_memory(hash, in, inlen, rsa_in, &z)) != CRYPT_OK) {
return errno;
}
/* pad it */
x = sizeof(rsa_in);
if ((errno = rsa_signpad(rsa_in, hashlen, rsa_out, &x)) != CRYPT_OK) {
return errno;
}
/* sign it */
rsa_size = sizeof(rsa_in);
if ((errno = rsa_exptmod(rsa_out, x, rsa_in, &rsa_size, PK_PRIVATE, key)) != CRYPT_OK) {
return errno;
}
/* check size */
if (*outlen < (PACKET_SIZE+4+rsa_size)) {
return CRYPT_BUFFER_OVERFLOW;
}
/* now lets output the message */
y = PACKET_SIZE;
out[y++] = hash_descriptor[hash].ID;
/* output the len */
STORE32L(rsa_size, (out+y));
y += 4;
/* store the signature */
for (x = 0; x < rsa_size; x++, y++) {
out[y] = rsa_in[x];
}
/* store header */
packet_store_header(out, PACKET_SECT_RSA, PACKET_SUB_SIGNED, y);
#ifdef CLEAN_STACK
/* clean up */
zeromem(rsa_in, sizeof(rsa_in));
zeromem(rsa_out, sizeof(rsa_out));
#endif
*outlen = y;
return CRYPT_OK;
}
int rsa_verify(const unsigned char *sig, const unsigned char *msg,
unsigned long inlen, int *stat,
rsa_key *key)
{
unsigned long hashlen, rsa_size, x, y, z, w;
int hash, errno;
unsigned char rsa_in[4096], rsa_out[4096];
_ARGCHK(sig != NULL);
_ARGCHK(msg != NULL);
_ARGCHK(stat != NULL);
_ARGCHK(key != NULL);
/* always be incorrect by default */
*stat = 0;
/* verify header */
if ((errno = packet_valid_header((unsigned char *)sig, PACKET_SECT_RSA, PACKET_SUB_SIGNED)) != CRYPT_OK) {
return errno;
}
/* grab hash name */
y = PACKET_SIZE;
hash = find_hash_id(sig[y++]);
if (hash == -1) {
return CRYPT_INVALID_HASH;
}
hashlen = hash_descriptor[hash].hashsize;
/* get the len */
LOAD32L(rsa_size, (sig+y));
y += 4;
/* load the signature */
for (x = 0; x < rsa_size; x++, y++) {
rsa_in[x] = sig[y];
}
/* exptmod it */
x = sizeof(rsa_in);
if ((errno = rsa_exptmod(rsa_in, rsa_size, rsa_out, &x, PK_PUBLIC, key)) != CRYPT_OK) {
return errno;
}
/* depad it */
z = sizeof(rsa_in);
if ((errno = rsa_signdepad(rsa_out, x, rsa_in, &z)) != CRYPT_OK) {
return errno;
}
/* check? */
w = sizeof(rsa_out);
if ((errno = hash_memory(hash, msg, inlen, rsa_out, &w)) != CRYPT_OK) {
return errno;
}
if ((z == hashlen) && (!memcmp(rsa_in, rsa_out, hashlen))) {
*stat = 1;
}
#ifdef CLEAN_STACK
zeromem(rsa_in, sizeof(rsa_in));
zeromem(rsa_out, sizeof(rsa_out));
#endif
return CRYPT_OK;
}
#endif
/* these are smaller routines written by Clay Culver. They do the same function as the rsa_encrypt/decrypt
* except that they are used to RSA encrypt/decrypt a single value and not a packet.
*/
int rsa_encrypt_key(const unsigned char *inkey, unsigned long inlen,
unsigned char *outkey, unsigned long *outlen,
prng_state *prng, int wprng, rsa_key *key)
{
unsigned char rsa_in[4096], rsa_out[4096];
unsigned long x, y, rsa_size;
int errno;
_ARGCHK(inkey != NULL);
_ARGCHK(outkey != NULL);
_ARGCHK(outlen != NULL);
_ARGCHK(key != NULL);
/* are the parameters valid? */
if ((errno = prng_is_valid(wprng)) != CRYPT_OK) {
return errno;
}
/* rsa_pad the symmetric key */
y = sizeof(rsa_in);
if ((errno = rsa_pad(inkey, inlen, rsa_in, &y, wprng, prng)) != CRYPT_OK) {
return CRYPT_ERROR;
}
/* rsa encrypt it */
rsa_size = sizeof(rsa_out);
if ((errno = rsa_exptmod(rsa_in, y, rsa_out, &rsa_size, PK_PUBLIC, key)) != CRYPT_OK) {
return CRYPT_ERROR;
}
/* check size */
if (*outlen < (PACKET_SIZE+4+rsa_size)) {
return CRYPT_BUFFER_OVERFLOW;
}
/* now lets make the header */
y = PACKET_SIZE;
/* store the size of the RSA value */
STORE32L(rsa_size, (outkey+y));
y += 4;
/* store the rsa value */
for (x = 0; x < rsa_size; x++, y++) {
outkey[y] = rsa_out[x];
}
/* store header */
packet_store_header(outkey, PACKET_SECT_RSA, PACKET_SUB_ENC_KEY, y);
#ifdef CLEAN_STACK
/* clean up */
zeromem(rsa_in, sizeof(rsa_in));
zeromem(rsa_out, sizeof(rsa_out));
#endif
*outlen = y;
return CRYPT_OK;
}
int rsa_decrypt_key(const unsigned char *in, unsigned char *outkey,
unsigned long *keylen, rsa_key *key)
{
unsigned char sym_key[MAXBLOCKSIZE], rsa_in[4096], rsa_out[4096];
unsigned long x, y, z, i, rsa_size;
int errno;
_ARGCHK(in != NULL);
_ARGCHK(outkey != NULL);
_ARGCHK(keylen != NULL);
_ARGCHK(key != NULL);
/* right key type? */
if (key->type != PK_PRIVATE && key->type != PK_PRIVATE_OPTIMIZED) {
return CRYPT_PK_NOT_PRIVATE;
}
/* check the header */
if ((errno = packet_valid_header((unsigned char *)in, PACKET_SECT_RSA, PACKET_SUB_ENC_KEY)) != CRYPT_OK) {
return errno;
}
/* grab length of the rsa key */
y = PACKET_SIZE;
LOAD32L(rsa_size, (in+y))
y += 4;
/* read it in */
for (x = 0; x < rsa_size; x++, y++) {
rsa_in[x] = in[y];
}
/* decrypt it */
x = sizeof(rsa_out);
if ((errno = rsa_exptmod(rsa_in, rsa_size, rsa_out, &x, PK_PRIVATE, key)) != CRYPT_OK)
return errno;
/* depad it */
z = sizeof(sym_key);
if ((errno = rsa_depad(rsa_out, x, sym_key, &z)) != CRYPT_OK) {
return errno;
}
/* check size */
if (*keylen < z) {
return CRYPT_BUFFER_OVERFLOW;
}
for (i = 0; i < z; i++) {
outkey[i] = sym_key[i];
}
#ifdef CLEAN_STACK
/* clean up */
zeromem(sym_key, sizeof(sym_key));
zeromem(rsa_in, sizeof(rsa_in));
zeromem(rsa_out, sizeof(rsa_out));
#endif
*keylen = z;
return CRYPT_OK;
}
int rsa_sign_hash(const unsigned char *in, unsigned long inlen,
unsigned char *out, unsigned long *outlen,
rsa_key *key)
{
unsigned long rsa_size, x, y;
unsigned char rsa_in[4096], rsa_out[4096];
int errno;
_ARGCHK(in != NULL);
_ARGCHK(out != NULL);
_ARGCHK(outlen != NULL);
_ARGCHK(key != NULL);
/* type of key? */
if (key->type != PK_PRIVATE && key->type != PK_PRIVATE_OPTIMIZED) {
return CRYPT_PK_NOT_PRIVATE;
}
/* pad it */
x = sizeof(rsa_out);
if ((errno = rsa_signpad(in, inlen, rsa_out, &x)) != CRYPT_OK) {
return errno;
}
/* sign it */
rsa_size = sizeof(rsa_in);
if ((errno = rsa_exptmod(rsa_out, x, rsa_in, &rsa_size, PK_PRIVATE, key)) != CRYPT_OK) {
return errno;
}
/* check size */
if (*outlen < (PACKET_SIZE+4+rsa_size)) {
return CRYPT_BUFFER_OVERFLOW;
}
/* now lets output the message */
y = PACKET_SIZE;
/* output the len */
STORE32L(rsa_size, (out+y));
y += 4;
/* store the signature */
for (x = 0; x < rsa_size; x++, y++) {
out[y] = rsa_in[x];
}
/* store header */
packet_store_header(out, PACKET_SECT_RSA, PACKET_SUB_SIGNED, y);
#ifdef CLEAN_STACK
/* clean up */
zeromem(rsa_in, sizeof(rsa_in));
zeromem(rsa_out, sizeof(rsa_out));
#endif
*outlen = y;
return CRYPT_OK;
}
int rsa_verify_hash(const unsigned char *sig, const unsigned char *md,
int *stat, rsa_key *key)
{
unsigned long rsa_size, x, y, z;
unsigned char rsa_in[4096], rsa_out[4096];
int errno;
_ARGCHK(sig != NULL);
_ARGCHK(md != NULL);
_ARGCHK(stat != NULL);
_ARGCHK(key != NULL);
/* always be incorrect by default */
*stat = 0;
/* verify header */
if ((errno = packet_valid_header((unsigned char *)sig, PACKET_SECT_RSA, PACKET_SUB_SIGNED)) != CRYPT_OK) {
return errno;
}
/* get the len */
y = PACKET_SIZE;
LOAD32L(rsa_size, (sig+y));
y += 4;
/* load the signature */
for (x = 0; x < rsa_size; x++, y++) {
rsa_in[x] = sig[y];
}
/* exptmod it */
x = sizeof(rsa_in);
if ((errno = rsa_exptmod(rsa_in, rsa_size, rsa_out, &x, PK_PUBLIC, key)) != CRYPT_OK) {
return errno;
}
/* depad it */
z = sizeof(rsa_in);
if ((errno = rsa_signdepad(rsa_out, x, rsa_in, &z)) != CRYPT_OK) {
return errno;
}
/* check? */
if (!memcmp(rsa_in, md, z)) {
*stat = 1;
}
#ifdef CLEAN_STACK
zeromem(rsa_in, sizeof(rsa_in));
zeromem(rsa_out, sizeof(rsa_out));
#endif
return CRYPT_OK;
}

506
safer+.c Normal file
View File

@ -0,0 +1,506 @@
#include "mycrypt.h"
#ifdef SAFERP
const struct _cipher_descriptor saferp_desc =
{
"safer+",
4,
16, 32, 16, 8,
&saferp_setup,
&saferp_ecb_encrypt,
&saferp_ecb_decrypt,
&saferp_test,
&saferp_keysize
};
/* ROUND(b,i)
*
* This is one forward key application. Note the basic form is
* key addition, substitution, key addition. The safer_ebox and safer_lbox
* are the exponentiation box and logarithm boxes respectively.
* The value of 'i' is the current round number which allows this
* function to be unrolled massively. Most of SAFER+'s speed
* comes from not having to compute indirect accesses into the
* array of 16 bytes b[0..15] which is the block of data
*/
extern const unsigned char safer_ebox[], safer_lbox[];
#define ROUND(b, i) \
b[0] = (safer_ebox[(b[0] ^ skey->saferp.K[i][0]) & 255] + skey->saferp.K[i+1][0]) & 255; \
b[1] = safer_lbox[(b[1] + skey->saferp.K[i][1]) & 255] ^ skey->saferp.K[i+1][1]; \
b[2] = safer_lbox[(b[2] + skey->saferp.K[i][2]) & 255] ^ skey->saferp.K[i+1][2]; \
b[3] = (safer_ebox[(b[3] ^ skey->saferp.K[i][3]) & 255] + skey->saferp.K[i+1][3]) & 255; \
b[4] = (safer_ebox[(b[4] ^ skey->saferp.K[i][4]) & 255] + skey->saferp.K[i+1][4]) & 255; \
b[5] = safer_lbox[(b[5] + skey->saferp.K[i][5]) & 255] ^ skey->saferp.K[i+1][5]; \
b[6] = safer_lbox[(b[6] + skey->saferp.K[i][6]) & 255] ^ skey->saferp.K[i+1][6]; \
b[7] = (safer_ebox[(b[7] ^ skey->saferp.K[i][7]) & 255] + skey->saferp.K[i+1][7]) & 255; \
b[8] = (safer_ebox[(b[8] ^ skey->saferp.K[i][8]) & 255] + skey->saferp.K[i+1][8]) & 255; \
b[9] = safer_lbox[(b[9] + skey->saferp.K[i][9]) & 255] ^ skey->saferp.K[i+1][9]; \
b[10] = safer_lbox[(b[10] + skey->saferp.K[i][10]) & 255] ^ skey->saferp.K[i+1][10]; \
b[11] = (safer_ebox[(b[11] ^ skey->saferp.K[i][11]) & 255] + skey->saferp.K[i+1][11]) & 255; \
b[12] = (safer_ebox[(b[12] ^ skey->saferp.K[i][12]) & 255] + skey->saferp.K[i+1][12]) & 255; \
b[13] = safer_lbox[(b[13] + skey->saferp.K[i][13]) & 255] ^ skey->saferp.K[i+1][13]; \
b[14] = safer_lbox[(b[14] + skey->saferp.K[i][14]) & 255] ^ skey->saferp.K[i+1][14]; \
b[15] = (safer_ebox[(b[15] ^ skey->saferp.K[i][15]) & 255] + skey->saferp.K[i+1][15]) & 255;
/* This is one inverse key application */
#define iROUND(b, i) \
b[0] = safer_lbox[(b[0] - skey->saferp.K[i+1][0]) & 255] ^ skey->saferp.K[i][0]; \
b[1] = (safer_ebox[(b[1] ^ skey->saferp.K[i+1][1]) & 255] - skey->saferp.K[i][1]) & 255; \
b[2] = (safer_ebox[(b[2] ^ skey->saferp.K[i+1][2]) & 255] - skey->saferp.K[i][2]) & 255; \
b[3] = safer_lbox[(b[3] - skey->saferp.K[i+1][3]) & 255] ^ skey->saferp.K[i][3]; \
b[4] = safer_lbox[(b[4] - skey->saferp.K[i+1][4]) & 255] ^ skey->saferp.K[i][4]; \
b[5] = (safer_ebox[(b[5] ^ skey->saferp.K[i+1][5]) & 255] - skey->saferp.K[i][5]) & 255; \
b[6] = (safer_ebox[(b[6] ^ skey->saferp.K[i+1][6]) & 255] - skey->saferp.K[i][6]) & 255; \
b[7] = safer_lbox[(b[7] - skey->saferp.K[i+1][7]) & 255] ^ skey->saferp.K[i][7]; \
b[8] = safer_lbox[(b[8] - skey->saferp.K[i+1][8]) & 255] ^ skey->saferp.K[i][8]; \
b[9] = (safer_ebox[(b[9] ^ skey->saferp.K[i+1][9]) & 255] - skey->saferp.K[i][9]) & 255; \
b[10] = (safer_ebox[(b[10] ^ skey->saferp.K[i+1][10]) & 255] - skey->saferp.K[i][10]) & 255; \
b[11] = safer_lbox[(b[11] - skey->saferp.K[i+1][11]) & 255] ^ skey->saferp.K[i][11]; \
b[12] = safer_lbox[(b[12] - skey->saferp.K[i+1][12]) & 255] ^ skey->saferp.K[i][12]; \
b[13] = (safer_ebox[(b[13] ^ skey->saferp.K[i+1][13]) & 255] - skey->saferp.K[i][13]) & 255; \
b[14] = (safer_ebox[(b[14] ^ skey->saferp.K[i+1][14]) & 255] - skey->saferp.K[i][14]) & 255; \
b[15] = safer_lbox[(b[15] - skey->saferp.K[i+1][15]) & 255] ^ skey->saferp.K[i][15];
/* This is a forward single layer PHT transform. */
#define PHT(b) \
b[0] = (b[0] + (b[1] = (b[0] + b[1]) & 255)) & 255; \
b[2] = (b[2] + (b[3] = (b[3] + b[2]) & 255)) & 255; \
b[4] = (b[4] + (b[5] = (b[5] + b[4]) & 255)) & 255; \
b[6] = (b[6] + (b[7] = (b[7] + b[6]) & 255)) & 255; \
b[8] = (b[8] + (b[9] = (b[9] + b[8]) & 255)) & 255; \
b[10] = (b[10] + (b[11] = (b[11] + b[10]) & 255)) & 255; \
b[12] = (b[12] + (b[13] = (b[13] + b[12]) & 255)) & 255; \
b[14] = (b[14] + (b[15] = (b[15] + b[14]) & 255)) & 255;
/* This is an inverse single layer PHT transform */
#define iPHT(b) \
b[15] = (b[15] - (b[14] = (b[14] - b[15]) & 255)) & 255; \
b[13] = (b[13] - (b[12] = (b[12] - b[13]) & 255)) & 255; \
b[11] = (b[11] - (b[10] = (b[10] - b[11]) & 255)) & 255; \
b[9] = (b[9] - (b[8] = (b[8] - b[9]) & 255)) & 255; \
b[7] = (b[7] - (b[6] = (b[6] - b[7]) & 255)) & 255; \
b[5] = (b[5] - (b[4] = (b[4] - b[5]) & 255)) & 255; \
b[3] = (b[3] - (b[2] = (b[2] - b[3]) & 255)) & 255; \
b[1] = (b[1] - (b[0] = (b[0] - b[1]) & 255)) & 255; \
/* This is the "Armenian" Shuffle. It takes the input from b and stores it in b2 */
#define SHUF(b, b2) \
b2[0] = b[8]; b2[1] = b[11]; b2[2] = b[12]; b2[3] = b[15]; \
b2[4] = b[2]; b2[5] = b[1]; b2[6] = b[6]; b2[7] = b[5]; \
b2[8] = b[10]; b2[9] = b[9]; b2[10] = b[14]; b2[11] = b[13]; \
b2[12] = b[0]; b2[13] = b[7]; b2[14] = b[4]; b2[15] = b[3];
/* This is the inverse shuffle. It takes from b and gives to b2 */
#define iSHUF(b, b2) \
b2[0] = b[12]; b2[1] = b[5]; b2[2] = b[4]; b2[3] = b[15]; \
b2[4] = b[14]; b2[5] = b[7]; b2[6] = b[6]; b2[7] = b[13]; \
b2[8] = b[0]; b2[9] = b[9]; b2[10] = b[8]; b2[11] = b[1]; \
b2[12] = b[2]; b2[13] = b[11]; b2[14] = b[10]; b2[15] = b[3];
/* The complete forward Linear Transform layer.
* Note that alternating usage of b and b2.
* Each round of LT starts in 'b' and ends in 'b2'.
*/
#define LT(b, b2) \
PHT(b); SHUF(b, b2); \
PHT(b2); SHUF(b2, b); \
PHT(b); SHUF(b, b2); \
PHT(b2);
/* This is the inverse linear transform layer. */
#define iLT(b, b2) \
iPHT(b); \
iSHUF(b, b2); iPHT(b2); \
iSHUF(b2, b); iPHT(b); \
iSHUF(b, b2); iPHT(b2);
#ifdef SAFERP_SMALL
static void _round(unsigned char *b, int i, symmetric_key *skey)
{
ROUND(b, i);
}
static void _iround(unsigned char *b, int i, symmetric_key *skey)
{
iROUND(b, i);
}
static void _lt(unsigned char *b, unsigned char *b2)
{
LT(b, b2);
}
static void _ilt(unsigned char *b, unsigned char *b2)
{
iLT(b, b2);
}
#undef ROUND
#define ROUND(b, i) _round(b, i, skey)
#undef iROUND
#define iROUND(b, i) _iround(b, i, skey)
#undef LT
#define LT(b, b2) _lt(b, b2)
#undef iLT
#define iLT(b, b2) _ilt(b, b2)
#endif
/* These are the 33, 128-bit bias words for the key schedule */
const unsigned char safer_bias[33][16] = {
{ 70, 151, 177, 186, 163, 183, 16, 10, 197, 55, 179, 201, 90, 40, 172, 100},
{ 236, 171, 170, 198, 103, 149, 88, 13, 248, 154, 246, 110, 102, 220, 5, 61},
{ 138, 195, 216, 137, 106, 233, 54, 73, 67, 191, 235, 212, 150, 155, 104, 160},
{ 93, 87, 146, 31, 213, 113, 92, 187, 34, 193, 190, 123, 188, 153, 99, 148},
{ 42, 97, 184, 52, 50, 25, 253, 251, 23, 64, 230, 81, 29, 65, 68, 143},
{ 221, 4, 128, 222, 231, 49, 214, 127, 1, 162, 247, 57, 218, 111, 35, 202},
{ 58, 208, 28, 209, 48, 62, 18, 161, 205, 15, 224, 168, 175, 130, 89, 44},
{ 125, 173, 178, 239, 194, 135, 206, 117, 6, 19, 2, 144, 79, 46, 114, 51},
{ 192, 141, 207, 169, 129, 226, 196, 39, 47, 108, 122, 159, 82, 225, 21, 56},
{ 252, 32, 66, 199, 8, 228, 9, 85, 94, 140, 20, 118, 96, 255, 223, 215},
{ 250, 11, 33, 0, 26, 249, 166, 185, 232, 158, 98, 76, 217, 145, 80, 210},
{ 24, 180, 7, 132, 234, 91, 164, 200, 14, 203, 72, 105, 75, 78, 156, 53},
{ 69, 77, 84, 229, 37, 60, 12, 74, 139, 63, 204, 167, 219, 107, 174, 244},
{ 45, 243, 124, 109, 157, 181, 38, 116, 242, 147, 83, 176, 240, 17, 237, 131},
{ 182, 3, 22, 115, 59, 30, 142, 112, 189, 134, 27, 71, 126, 36, 86, 241},
{ 136, 70, 151, 177, 186, 163, 183, 16, 10, 197, 55, 179, 201, 90, 40, 172},
{ 220, 134, 119, 215, 166, 17, 251, 244, 186, 146, 145, 100, 131, 241, 51, 239},
{ 44, 181, 178, 43, 136, 209, 153, 203, 140, 132, 29, 20, 129, 151, 113, 202},
{ 163, 139, 87, 60, 130, 196, 82, 92, 28, 232, 160, 4, 180, 133, 74, 246},
{ 84, 182, 223, 12, 26, 142, 222, 224, 57, 252, 32, 155, 36, 78, 169, 152},
{ 171, 242, 96, 208, 108, 234, 250, 199, 217, 0, 212, 31, 110, 67, 188, 236},
{ 137, 254, 122, 93, 73, 201, 50, 194, 249, 154, 248, 109, 22, 219, 89, 150},
{ 233, 205, 230, 70, 66, 143, 10, 193, 204, 185, 101, 176, 210, 198, 172, 30},
{ 98, 41, 46, 14, 116, 80, 2, 90, 195, 37, 123, 138, 42, 91, 240, 6},
{ 71, 111, 112, 157, 126, 16, 206, 18, 39, 213, 76, 79, 214, 121, 48, 104},
{ 117, 125, 228, 237, 128, 106, 144, 55, 162, 94, 118, 170, 197, 127, 61, 175},
{ 229, 25, 97, 253, 77, 124, 183, 11, 238, 173, 75, 34, 245, 231, 115, 35},
{ 200, 5, 225, 102, 221, 179, 88, 105, 99, 86, 15, 161, 49, 149, 23, 7},
{ 40, 1, 45, 226, 147, 190, 69, 21, 174, 120, 3, 135, 164, 184, 56, 207},
{ 8, 103, 9, 148, 235, 38, 168, 107, 189, 24, 52, 27, 187, 191, 114, 247},
{ 53, 72, 156, 81, 47, 59, 85, 227, 192, 159, 216, 211, 243, 141, 177, 255},
{ 62, 220, 134, 119, 215, 166, 17, 251, 244, 186, 146, 145, 100, 131, 241, 51}};
int saferp_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey)
{
unsigned x, y;
unsigned char t[33];
static const int rounds[3] = { 8, 12, 16 };
_ARGCHK(key != NULL);
_ARGCHK(skey != NULL);
/* check arguments */
if (keylen != 16 && keylen != 24 && keylen != 32) {
return CRYPT_INVALID_KEYSIZE;
}
/* Is the number of rounds valid? Either use zero for default or
* 8,12,16 rounds for 16,24,32 byte keys
*/
if (num_rounds != 0 && num_rounds != rounds[(keylen/8)-2]) {
return CRYPT_INVALID_ROUNDS;
}
/* 128 bit key version */
if (keylen == 16) {
/* copy key into t */
for (x = y = 0; x < 16; x++) {
t[x] = key[x];
y ^= key[x];
}
t[16] = y;
/* make round keys */
for (x = 0; x < 16; x++) {
skey->saferp.K[0][x] = t[x];
}
/* make the 16 other keys as a transformation of the first key */
for (x = 1; x < 17; x++) {
/* rotate 3 bits each */
for (y = 0; y < 17; y++) {
t[y] = ((t[y]<<3)|(t[y]>>5)) & 255;
}
/* select and add */
for (y = 0; y < 16; y++) {
skey->saferp.K[x][y] = (t[(x+y)%17] + safer_bias[x-1][y]) & 255;
}
}
skey->saferp.rounds = 8;
} else if (keylen == 24) {
/* copy key into t */
for (x = y = 0; x < 24; x++) {
t[x] = key[x];
y ^= key[x];
}
t[24] = y;
/* make round keys */
for (x = 0; x < 16; x++) {
skey->saferp.K[0][x] = t[x];
}
for (x = 1; x < 25; x++) {
/* rotate 3 bits each */
for (y = 0; y < 25; y++) {
t[y] = ((t[y]<<3)|(t[y]>>5)) & 255;
}
/* select and add */
for (y = 0; y < 16; y++) {
skey->saferp.K[x][y] = (t[(x+y)%25] + safer_bias[x-1][y]) & 255;
}
}
skey->saferp.rounds = 12;
} else {
/* copy key into t */
for (x = y = 0; x < 32; x++) {
t[x] = key[x];
y ^= key[x];
}
t[32] = y;
/* make round keys */
for (x = 0; x < 16; x++) {
skey->saferp.K[0][x] = t[x];
}
for (x = 1; x < 33; x++) {
/* rotate 3 bits each */
for (y = 0; y < 33; y++) {
t[y] = ((t[y]<<3)|(t[y]>>5)) & 255;
}
/* select and add */
for (y = 0; y < 16; y++) {
skey->saferp.K[x][y] = (t[(x+y)%33] + safer_bias[x-1][y]) & 255;
}
}
skey->saferp.rounds = 16;
}
#ifdef CLEAN_STACK
zeromem(t, sizeof(t));
#endif
return CRYPT_OK;
}
void saferp_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey)
{
unsigned char b[16];
int x;
_ARGCHK(pt != NULL);
_ARGCHK(ct != NULL);
_ARGCHK(skey != NULL);
/* do eight rounds */
for (x = 0; x < 16; x++) {
b[x] = pt[x];
}
ROUND(b, 0); LT(b, ct);
ROUND(ct, 2); LT(ct, b);
ROUND(b, 4); LT(b, ct);
ROUND(ct, 6); LT(ct, b);
ROUND(b, 8); LT(b, ct);
ROUND(ct, 10); LT(ct, b);
ROUND(b, 12); LT(b, ct);
ROUND(ct, 14); LT(ct, b);
/* 192-bit key? */
if (skey->saferp.rounds > 8) {
ROUND(b, 16); LT(b, ct);
ROUND(ct, 18); LT(ct, b);
ROUND(b, 20); LT(b, ct);
ROUND(ct, 22); LT(ct, b);
}
/* 256-bit key? */
if (skey->saferp.rounds > 12) {
ROUND(b, 24); LT(b, ct);
ROUND(ct, 26); LT(ct, b);
ROUND(b, 28); LT(b, ct);
ROUND(ct, 30); LT(ct, b);
}
ct[0] = b[0] ^ skey->saferp.K[skey->saferp.rounds*2][0];
ct[1] = (b[1] + skey->saferp.K[skey->saferp.rounds*2][1]) & 255;
ct[2] = (b[2] + skey->saferp.K[skey->saferp.rounds*2][2]) & 255;
ct[3] = b[3] ^ skey->saferp.K[skey->saferp.rounds*2][3];
ct[4] = b[4] ^ skey->saferp.K[skey->saferp.rounds*2][4];
ct[5] = (b[5] + skey->saferp.K[skey->saferp.rounds*2][5]) & 255;
ct[6] = (b[6] + skey->saferp.K[skey->saferp.rounds*2][6]) & 255;
ct[7] = b[7] ^ skey->saferp.K[skey->saferp.rounds*2][7];
ct[8] = b[8] ^ skey->saferp.K[skey->saferp.rounds*2][8];
ct[9] = (b[9] + skey->saferp.K[skey->saferp.rounds*2][9]) & 255;
ct[10] = (b[10] + skey->saferp.K[skey->saferp.rounds*2][10]) & 255;
ct[11] = b[11] ^ skey->saferp.K[skey->saferp.rounds*2][11];
ct[12] = b[12] ^ skey->saferp.K[skey->saferp.rounds*2][12];
ct[13] = (b[13] + skey->saferp.K[skey->saferp.rounds*2][13]) & 255;
ct[14] = (b[14] + skey->saferp.K[skey->saferp.rounds*2][14]) & 255;
ct[15] = b[15] ^ skey->saferp.K[skey->saferp.rounds*2][15];
#ifdef CLEAN_STACK
zeromem(b, sizeof(b));
#endif
}
void saferp_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey)
{
unsigned char b[16];
int x;
_ARGCHK(pt != NULL);
_ARGCHK(ct != NULL);
_ARGCHK(skey != NULL);
/* do eight rounds */
b[0] = ct[0] ^ skey->saferp.K[skey->saferp.rounds*2][0];
b[1] = (ct[1] - skey->saferp.K[skey->saferp.rounds*2][1]) & 255;
b[2] = (ct[2] - skey->saferp.K[skey->saferp.rounds*2][2]) & 255;
b[3] = ct[3] ^ skey->saferp.K[skey->saferp.rounds*2][3];
b[4] = ct[4] ^ skey->saferp.K[skey->saferp.rounds*2][4];
b[5] = (ct[5] - skey->saferp.K[skey->saferp.rounds*2][5]) & 255;
b[6] = (ct[6] - skey->saferp.K[skey->saferp.rounds*2][6]) & 255;
b[7] = ct[7] ^ skey->saferp.K[skey->saferp.rounds*2][7];
b[8] = ct[8] ^ skey->saferp.K[skey->saferp.rounds*2][8];
b[9] = (ct[9] - skey->saferp.K[skey->saferp.rounds*2][9]) & 255;
b[10] = (ct[10] - skey->saferp.K[skey->saferp.rounds*2][10]) & 255;
b[11] = ct[11] ^ skey->saferp.K[skey->saferp.rounds*2][11];
b[12] = ct[12] ^ skey->saferp.K[skey->saferp.rounds*2][12];
b[13] = (ct[13] - skey->saferp.K[skey->saferp.rounds*2][13]) & 255;
b[14] = (ct[14] - skey->saferp.K[skey->saferp.rounds*2][14]) & 255;
b[15] = ct[15] ^ skey->saferp.K[skey->saferp.rounds*2][15];
/* 256-bit key? */
if (skey->saferp.rounds > 12) {
iLT(b, pt); iROUND(pt, 30);
iLT(pt, b); iROUND(b, 28);
iLT(b, pt); iROUND(pt, 26);
iLT(pt, b); iROUND(b, 24);
}
/* 192-bit key? */
if (skey->saferp.rounds > 8) {
iLT(b, pt); iROUND(pt, 22);
iLT(pt, b); iROUND(b, 20);
iLT(b, pt); iROUND(pt, 18);
iLT(pt, b); iROUND(b, 16);
}
iLT(b, pt); iROUND(pt, 14);
iLT(pt, b); iROUND(b, 12);
iLT(b, pt); iROUND(pt,10);
iLT(pt, b); iROUND(b, 8);
iLT(b, pt); iROUND(pt,6);
iLT(pt, b); iROUND(b, 4);
iLT(b, pt); iROUND(pt,2);
iLT(pt, b); iROUND(b, 0);
for (x = 0; x < 16; x++) {
pt[x] = b[x];
}
#ifdef CLEAN_STACK
zeromem(b, sizeof(b));
#endif
}
int saferp_test(void)
{
static const unsigned char key128[16] =
{ 41, 35, 190, 132, 225, 108, 214, 174,
82, 144, 73, 241, 241, 187, 233, 235 };
static const unsigned char pt128[16] =
{ 179, 166, 219, 60, 135, 12, 62, 153,
36, 94, 13, 28, 6, 183, 71, 222 };
static const unsigned char ct128[16] =
{ 224, 31, 182, 10, 12, 255, 84, 70,
127, 13, 89, 249, 9, 57, 165, 220 };
static const unsigned char key192[24] =
{ 72, 211, 143, 117, 230, 217, 29, 42,
229, 192, 247, 43, 120, 129, 135, 68,
14, 95, 80, 0, 212, 97, 141, 190 };
static const unsigned char pt192[16] =
{ 123, 5, 21, 7, 59, 51, 130, 31,
24, 112, 146, 218, 100, 84, 206, 177 };
static const unsigned char ct192[16] =
{ 92, 136, 4, 63, 57, 95, 100, 0,
150, 130, 130, 16, 193, 111, 219, 133 };
static const unsigned char key256[32] =
{ 243, 168, 141, 254, 190, 242, 235, 113,
255, 160, 208, 59, 117, 6, 140, 126,
135, 120, 115, 77, 208, 190, 130, 190,
219, 194, 70, 65, 43, 140, 250, 48 };
static const unsigned char pt256[16] =
{ 127, 112, 240, 167, 84, 134, 50, 149,
170, 91, 104, 19, 11, 230, 252, 245 };
static const unsigned char ct256[16] =
{ 88, 11, 25, 36, 172, 229, 202, 213,
170, 65, 105, 153, 220, 104, 153, 138 };
unsigned char buf[2][16];
symmetric_key skey;
int errno;
/* test 128-bit key */
if ((errno = saferp_setup(key128, 16, 0, &skey)) != CRYPT_OK) {
return errno;
}
saferp_ecb_encrypt(pt128, buf[0], &skey);
saferp_ecb_decrypt(buf[0], buf[1], &skey);
/* compare */
if (memcmp(buf[0], &ct128, 16) || memcmp(buf[1], &pt128, 16)) {
return CRYPT_FAIL_TESTVECTOR;
}
/* test 192-bit key */
if ((errno = saferp_setup(key192, 24, 0, &skey)) != CRYPT_OK) {
return errno;
}
saferp_ecb_encrypt(pt192, buf[0], &skey);
saferp_ecb_decrypt(buf[0], buf[1], &skey);
/* compare */
if (memcmp(buf[0], &ct192, 16) || memcmp(buf[1], &pt192, 16)) {
return CRYPT_FAIL_TESTVECTOR;
}
/* test 256-bit key */
if ((errno = saferp_setup(key256, 32, 0, &skey)) != CRYPT_OK) {
return errno;
}
saferp_ecb_encrypt(pt256, buf[0], &skey);
saferp_ecb_decrypt(buf[0], buf[1], &skey);
/* compare */
if (memcmp(buf[0], &ct256, 16) || memcmp(buf[1], &pt256, 16)) {
return CRYPT_FAIL_TESTVECTOR;
}
return CRYPT_OK;
}
int saferp_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

421
safer.c Normal file
View File

@ -0,0 +1,421 @@
/*******************************************************************************
*
* FILE: safer.c
*
* DESCRIPTION: block-cipher algorithm SAFER (Secure And Fast Encryption
* Routine) in its four versions: SAFER K-64, SAFER K-128,
* SAFER SK-64 and SAFER SK-128.
*
* AUTHOR: Richard De Moliner (demoliner@isi.ee.ethz.ch)
* Signal and Information Processing Laboratory
* Swiss Federal Institute of Technology
* CH-8092 Zuerich, Switzerland
*
* DATE: September 9, 1995
*
* CHANGE HISTORY:
*
*******************************************************************************/
#include <mycrypt.h>
#ifdef SAFER
const struct _cipher_descriptor
safer_k64_desc = {
"safer-k64",
8, 8, 8, 8, SAFER_K64_DEFAULT_NOF_ROUNDS,
&safer_k64_setup,
&safer_ecb_encrypt,
&safer_ecb_decrypt,
&safer_k64_test,
&safer_64_keysize
},
safer_sk64_desc = {
"safer-sk64",
9, 8, 8, 8, SAFER_SK64_DEFAULT_NOF_ROUNDS,
&safer_sk64_setup,
&safer_ecb_encrypt,
&safer_ecb_decrypt,
&safer_sk64_test,
&safer_64_keysize
},
safer_k128_desc = {
"safer-k128",
10, 16, 16, 8, SAFER_K128_DEFAULT_NOF_ROUNDS,
&safer_k128_setup,
&safer_ecb_encrypt,
&safer_ecb_decrypt,
&safer_sk128_test,
&safer_128_keysize
},
safer_sk128_desc = {
"safer-sk128",
11, 16, 16, 8, SAFER_SK128_DEFAULT_NOF_ROUNDS,
&safer_sk128_setup,
&safer_ecb_encrypt,
&safer_ecb_decrypt,
&safer_sk128_test,
&safer_128_keysize
};
/******************* Constants ************************************************/
// #define TAB_LEN 256
/******************* Assertions ***********************************************/
/******************* Macros ***************************************************/
#define ROL8(x, n) ((unsigned char)((unsigned int)(x) << (n)\
|(unsigned int)((x) & 0xFF) >> (8 - (n))))
#define EXP(x) safer_ebox[(x) & 0xFF]
#define LOG(x) safer_lbox[(x) & 0xFF]
#define PHT(x, y) { y += x; x += y; }
#define IPHT(x, y) { x -= y; y -= x; }
/******************* Types ****************************************************/
extern const unsigned char safer_ebox[], safer_lbox[];
#ifdef CLEAN_STACK
static void _Safer_Expand_Userkey(const unsigned char *userkey_1,
const unsigned char *userkey_2,
unsigned int nof_rounds,
int strengthened,
safer_key_t key)
#else
static void Safer_Expand_Userkey(const unsigned char *userkey_1,
const unsigned char *userkey_2,
unsigned int nof_rounds,
int strengthened,
safer_key_t key)
#endif
{ unsigned int i, j;
unsigned char ka[SAFER_BLOCK_LEN + 1];
unsigned char kb[SAFER_BLOCK_LEN + 1];
if (SAFER_MAX_NOF_ROUNDS < nof_rounds)
nof_rounds = SAFER_MAX_NOF_ROUNDS;
*key++ = (unsigned char)nof_rounds;
ka[SAFER_BLOCK_LEN] = 0;
kb[SAFER_BLOCK_LEN] = 0;
for (j = 0; j < SAFER_BLOCK_LEN; j++)
{
ka[SAFER_BLOCK_LEN] ^= ka[j] = ROL8(userkey_1[j], 5);
kb[SAFER_BLOCK_LEN] ^= kb[j] = *key++ = userkey_2[j];
}
for (i = 1; i <= nof_rounds; i++)
{
for (j = 0; j < SAFER_BLOCK_LEN + 1; j++)
{
ka[j] = ROL8(ka[j], 6);
kb[j] = ROL8(kb[j], 6);
}
for (j = 0; j < SAFER_BLOCK_LEN; j++)
if (strengthened)
*key++ = (ka[(j + 2 * i - 1) % (SAFER_BLOCK_LEN + 1)]
+ safer_ebox[safer_ebox[18 * i + j + 1]]) & 0xFF;
else
*key++ = (ka[j] + safer_ebox[safer_ebox[18 * i + j + 1]]) & 0xFF;
for (j = 0; j < SAFER_BLOCK_LEN; j++)
if (strengthened)
*key++ = (kb[(j + 2 * i) % (SAFER_BLOCK_LEN + 1)]
+ safer_ebox[safer_ebox[18 * i + j + 10]]) & 0xFF;
else
*key++ = (kb[j] + safer_ebox[safer_ebox[18 * i + j + 10]]) & 0xFF;
}
#ifdef CLEAN_STACK
zeromem(ka, sizeof(ka));
zeromem(kb, sizeof(kb));
#endif
}
#ifdef CLEAN_STACK
static void Safer_Expand_Userkey(const unsigned char *userkey_1,
const unsigned char *userkey_2,
unsigned int nof_rounds,
int strengthened,
safer_key_t key)
{
_Safer_Expand_Userkey(userkey_1, userkey_2, nof_rounds, strengthened, key);
burn_stack(sizeof(unsigned char) * (2 * (SAFER_BLOCK_LEN + 1)) + sizeof(unsigned int)*2);
}
#endif
int safer_k64_setup(const unsigned char *key, int keylen, int numrounds, symmetric_key *skey)
{
_ARGCHK(key != NULL);
_ARGCHK(skey != NULL);
if (numrounds && (numrounds < 6 || numrounds > SAFER_MAX_NOF_ROUNDS)) {
return CRYPT_INVALID_ROUNDS;
}
if (keylen != 8) {
return CRYPT_INVALID_KEYSIZE;
}
Safer_Expand_Userkey(key, key, numrounds?numrounds:SAFER_K64_DEFAULT_NOF_ROUNDS, 0, skey->safer.key);
return CRYPT_OK;
}
int safer_sk64_setup(const unsigned char *key, int keylen, int numrounds, symmetric_key *skey)
{
_ARGCHK(key != NULL);
_ARGCHK(skey != NULL);
if (numrounds && (numrounds < 6 || numrounds > SAFER_MAX_NOF_ROUNDS)) {
return CRYPT_INVALID_ROUNDS;
}
if (keylen != 8) {
return CRYPT_INVALID_KEYSIZE;
}
Safer_Expand_Userkey(key, key, numrounds?numrounds:SAFER_SK64_DEFAULT_NOF_ROUNDS, 1, skey->safer.key);
return CRYPT_OK;
}
int safer_k128_setup(const unsigned char *key, int keylen, int numrounds, symmetric_key *skey)
{
_ARGCHK(key != NULL);
_ARGCHK(skey != NULL);
if (numrounds && (numrounds < 6 || numrounds > SAFER_MAX_NOF_ROUNDS)) {
return CRYPT_INVALID_ROUNDS;
}
if (keylen != 16) {
return CRYPT_INVALID_KEYSIZE;
}
Safer_Expand_Userkey(key, key+8, numrounds?numrounds:SAFER_K128_DEFAULT_NOF_ROUNDS, 0, skey->safer.key);
return CRYPT_OK;
}
int safer_sk128_setup(const unsigned char *key, int keylen, int numrounds, symmetric_key *skey)
{
_ARGCHK(key != NULL);
_ARGCHK(skey != NULL);
if (numrounds && (numrounds < 6 || numrounds > SAFER_MAX_NOF_ROUNDS)) {
return CRYPT_INVALID_ROUNDS;
}
if (keylen != 16) {
return CRYPT_INVALID_KEYSIZE;
}
Safer_Expand_Userkey(key, key+8, numrounds?numrounds:SAFER_SK128_DEFAULT_NOF_ROUNDS, 1, skey->safer.key);
return CRYPT_OK;
}
#ifdef CLEAN_STACK
static void _safer_ecb_encrypt(const unsigned char *block_in,
unsigned char *block_out,
symmetric_key *skey)
#else
void safer_ecb_encrypt(const unsigned char *block_in,
unsigned char *block_out,
symmetric_key *skey)
#endif
{ unsigned char a, b, c, d, e, f, g, h, t;
unsigned int round;
unsigned char *key;
_ARGCHK(block_in != NULL);
_ARGCHK(block_out != NULL);
_ARGCHK(skey != NULL);
key = skey->safer.key;
a = block_in[0]; b = block_in[1]; c = block_in[2]; d = block_in[3];
e = block_in[4]; f = block_in[5]; g = block_in[6]; h = block_in[7];
if (SAFER_MAX_NOF_ROUNDS < (round = *key)) round = SAFER_MAX_NOF_ROUNDS;
while(round--)
{
a ^= *++key; b += *++key; c += *++key; d ^= *++key;
e ^= *++key; f += *++key; g += *++key; h ^= *++key;
a = EXP(a) + *++key; b = LOG(b) ^ *++key;
c = LOG(c) ^ *++key; d = EXP(d) + *++key;
e = EXP(e) + *++key; f = LOG(f) ^ *++key;
g = LOG(g) ^ *++key; h = EXP(h) + *++key;
PHT(a, b); PHT(c, d); PHT(e, f); PHT(g, h);
PHT(a, c); PHT(e, g); PHT(b, d); PHT(f, h);
PHT(a, e); PHT(b, f); PHT(c, g); PHT(d, h);
t = b; b = e; e = c; c = t; t = d; d = f; f = g; g = t;
}
a ^= *++key; b += *++key; c += *++key; d ^= *++key;
e ^= *++key; f += *++key; g += *++key; h ^= *++key;
block_out[0] = a & 0xFF; block_out[1] = b & 0xFF;
block_out[2] = c & 0xFF; block_out[3] = d & 0xFF;
block_out[4] = e & 0xFF; block_out[5] = f & 0xFF;
block_out[6] = g & 0xFF; block_out[7] = h & 0xFF;
}
#ifdef CLEAN_STACK
void safer_ecb_encrypt(const unsigned char *block_in,
unsigned char *block_out,
symmetric_key *skey)
{
_safer_ecb_encrypt(block_in, block_out, skey);
burn_stack(sizeof(unsigned char) * 9 + sizeof(unsigned int) + sizeof(unsigned char *));
}
#endif
#ifdef CLEAN_STACK
static void _safer_ecb_decrypt(const unsigned char *block_in,
unsigned char *block_out,
symmetric_key *skey)
#else
void safer_ecb_decrypt(const unsigned char *block_in,
unsigned char *block_out,
symmetric_key *skey)
#endif
{ unsigned char a, b, c, d, e, f, g, h, t;
unsigned int round;
unsigned char *key;
_ARGCHK(block_in != NULL);
_ARGCHK(block_out != NULL);
_ARGCHK(skey != NULL);
key = skey->safer.key;
a = block_in[0]; b = block_in[1]; c = block_in[2]; d = block_in[3];
e = block_in[4]; f = block_in[5]; g = block_in[6]; h = block_in[7];
if (SAFER_MAX_NOF_ROUNDS < (round = *key)) round = SAFER_MAX_NOF_ROUNDS;
key += SAFER_BLOCK_LEN * (1 + 2 * round);
h ^= *key; g -= *--key; f -= *--key; e ^= *--key;
d ^= *--key; c -= *--key; b -= *--key; a ^= *--key;
while (round--)
{
t = e; e = b; b = c; c = t; t = f; f = d; d = g; g = t;
IPHT(a, e); IPHT(b, f); IPHT(c, g); IPHT(d, h);
IPHT(a, c); IPHT(e, g); IPHT(b, d); IPHT(f, h);
IPHT(a, b); IPHT(c, d); IPHT(e, f); IPHT(g, h);
h -= *--key; g ^= *--key; f ^= *--key; e -= *--key;
d -= *--key; c ^= *--key; b ^= *--key; a -= *--key;
h = LOG(h) ^ *--key; g = EXP(g) - *--key;
f = EXP(f) - *--key; e = LOG(e) ^ *--key;
d = LOG(d) ^ *--key; c = EXP(c) - *--key;
b = EXP(b) - *--key; a = LOG(a) ^ *--key;
}
block_out[0] = a & 0xFF; block_out[1] = b & 0xFF;
block_out[2] = c & 0xFF; block_out[3] = d & 0xFF;
block_out[4] = e & 0xFF; block_out[5] = f & 0xFF;
block_out[6] = g & 0xFF; block_out[7] = h & 0xFF;
}
#ifdef CLEAN_STACK
void safer_ecb_decrypt(const unsigned char *block_in,
unsigned char *block_out,
symmetric_key *skey)
{
_safer_ecb_decrypt(block_in, block_out, skey);
burn_stack(sizeof(unsigned char) * 9 + sizeof(unsigned int) + sizeof(unsigned char *));
}
#endif
int safer_64_keysize(int *keysize)
{
_ARGCHK(keysize != NULL);
if (*keysize < 8) {
return CRYPT_INVALID_KEYSIZE;
} else {
*keysize = 8;
return CRYPT_OK;
}
}
int safer_128_keysize(int *keysize)
{
_ARGCHK(keysize != NULL);
if (*keysize < 16) {
return CRYPT_INVALID_KEYSIZE;
} else {
*keysize = 16;
return CRYPT_OK;
}
}
int safer_k64_test(void)
{
static const unsigned char k64_pt[] = { 1, 2, 3, 4, 5, 6, 7, 8 },
k64_key[] = { 8, 7, 6, 5, 4, 3, 2, 1 },
k64_ct[] = { 200, 242, 156, 221, 135, 120, 62, 217 };
symmetric_key skey;
unsigned char buf[2][8];
int errno;
/* test K64 */
if ((errno = safer_k64_setup(k64_key, 8, 6, &skey)) != CRYPT_OK) {
return errno;
}
safer_ecb_encrypt(k64_pt, buf[0], &skey);
safer_ecb_decrypt(buf[0], buf[1], &skey);
if (memcmp(buf[0], k64_ct, 8) || memcmp(buf[1], k64_pt, 8)) {
return CRYPT_FAIL_TESTVECTOR;
}
return CRYPT_OK;
}
int safer_sk64_test(void)
{
static const unsigned char sk64_pt[] = { 1, 2, 3, 4, 5, 6, 7, 8 },
sk64_key[] = { 1, 2, 3, 4, 5, 6, 7, 8 },
sk64_ct[] = { 95, 206, 155, 162, 5, 132, 56, 199 };
symmetric_key skey;
unsigned char buf[2][8];
int errno;
/* test SK64 */
if ((errno = safer_sk64_setup(sk64_key, 8, 6, &skey)) != CRYPT_OK) {
return errno;
}
safer_ecb_encrypt(sk64_pt, buf[0], &skey);
safer_ecb_decrypt(buf[0], buf[1], &skey);
if (memcmp(buf[0], sk64_ct, 8) || memcmp(buf[1], sk64_pt, 8)) {
return CRYPT_FAIL_TESTVECTOR;
}
return CRYPT_OK;
}
int safer_sk128_test(void)
{
static const unsigned char sk128_pt[] = { 1, 2, 3, 4, 5, 6, 7, 8 },
sk128_key[] = { 1, 2, 3, 4, 5, 6, 7, 8,
0, 0, 0, 0, 0, 0, 0, 0 },
sk128_ct[] = { 255, 120, 17, 228, 179, 167, 46, 113 };
symmetric_key skey;
unsigned char buf[2][8];
int errno;
/* test SK128 */
if ((errno = safer_sk128_setup(sk128_key, 16, 0, &skey)) != CRYPT_OK) {
return errno;
}
safer_ecb_encrypt(sk128_pt, buf[0], &skey);
safer_ecb_decrypt(buf[0], buf[1], &skey);
if (memcmp(buf[0], sk128_ct, 8) || memcmp(buf[1], sk128_pt, 8)) {
return CRYPT_FAIL_TESTVECTOR;
}
return CRYPT_OK;
}
#endif

48
safer_tab.c Normal file
View File

@ -0,0 +1,48 @@
#include "mycrypt.h"
#if defined(SAFERP) || defined(SAFER)
/* This is the box defined by ebox[x] = 45^x mod 257.
* Its assumed that the value "256" corresponds to zero. */
const unsigned char safer_ebox[256] = {
1, 45, 226, 147, 190, 69, 21, 174, 120, 3, 135, 164, 184, 56, 207, 63,
8, 103, 9, 148, 235, 38, 168, 107, 189, 24, 52, 27, 187, 191, 114, 247,
64, 53, 72, 156, 81, 47, 59, 85, 227, 192, 159, 216, 211, 243, 141, 177,
255, 167, 62, 220, 134, 119, 215, 166, 17, 251, 244, 186, 146, 145, 100, 131,
241, 51, 239, 218, 44, 181, 178, 43, 136, 209, 153, 203, 140, 132, 29, 20,
129, 151, 113, 202, 95, 163, 139, 87, 60, 130, 196, 82, 92, 28, 232, 160,
4, 180, 133, 74, 246, 19, 84, 182, 223, 12, 26, 142, 222, 224, 57, 252,
32, 155, 36, 78, 169, 152, 158, 171, 242, 96, 208, 108, 234, 250, 199, 217,
0, 212, 31, 110, 67, 188, 236, 83, 137, 254, 122, 93, 73, 201, 50, 194,
249, 154, 248, 109, 22, 219, 89, 150, 68, 233, 205, 230, 70, 66, 143, 10,
193, 204, 185, 101, 176, 210, 198, 172, 30, 65, 98, 41, 46, 14, 116, 80,
2, 90, 195, 37, 123, 138, 42, 91, 240, 6, 13, 71, 111, 112, 157, 126,
16, 206, 18, 39, 213, 76, 79, 214, 121, 48, 104, 54, 117, 125, 228, 237,
128, 106, 144, 55, 162, 94, 118, 170, 197, 127, 61, 175, 165, 229, 25, 97,
253, 77, 124, 183, 11, 238, 173, 75, 34, 245, 231, 115, 35, 33, 200, 5,
225, 102, 221, 179, 88, 105, 99, 86, 15, 161, 49, 149, 23, 7, 58, 40
};
/* This is the inverse of ebox or the base 45 logarithm */
const unsigned char safer_lbox[256] = {
128, 0, 176, 9, 96, 239, 185, 253, 16, 18, 159, 228, 105, 186, 173, 248,
192, 56, 194, 101, 79, 6, 148, 252, 25, 222, 106, 27, 93, 78, 168, 130,
112, 237, 232, 236, 114, 179, 21, 195, 255, 171, 182, 71, 68, 1, 172, 37,
201, 250, 142, 65, 26, 33, 203, 211, 13, 110, 254, 38, 88, 218, 50, 15,
32, 169, 157, 132, 152, 5, 156, 187, 34, 140, 99, 231, 197, 225, 115, 198,
175, 36, 91, 135, 102, 39, 247, 87, 244, 150, 177, 183, 92, 139, 213, 84,
121, 223, 170, 246, 62, 163, 241, 17, 202, 245, 209, 23, 123, 147, 131, 188,
189, 82, 30, 235, 174, 204, 214, 53, 8, 200, 138, 180, 226, 205, 191, 217,
208, 80, 89, 63, 77, 98, 52, 10, 72, 136, 181, 86, 76, 46, 107, 158,
210, 61, 60, 3, 19, 251, 151, 81, 117, 74, 145, 113, 35, 190, 118, 42,
95, 249, 212, 85, 11, 220, 55, 49, 22, 116, 215, 119, 167, 230, 7, 219,
164, 47, 70, 243, 97, 69, 103, 227, 12, 162, 59, 28, 133, 24, 4, 29,
41, 160, 143, 178, 90, 216, 166, 126, 238, 141, 83, 75, 161, 154, 193, 14,
122, 73, 165, 44, 129, 196, 199, 54, 43, 127, 67, 149, 51, 242, 108, 104,
109, 240, 2, 40, 206, 221, 155, 234, 94, 153, 124, 20, 134, 207, 229, 66,
184, 64, 120, 45, 58, 233, 100, 31, 146, 144, 125, 57, 111, 224, 137, 48
};
#endif

719
serpent.c Normal file
View File

@ -0,0 +1,719 @@
#include "mycrypt.h"
#ifdef SERPENT
const struct _cipher_descriptor serpent_desc =
{
"serpent",
5,
16, 32, 16, 32,
&serpent_setup,
&serpent_ecb_encrypt,
&serpent_ecb_decrypt,
&serpent_test,
&serpent_keysize
};
/* These defines are derived from Brian Gladman's work. Contact him at gladman@seven77.demon.co.uk
*
* Available on the web at http://fp.gladman.plus.com/cryptography_technology/aes/index.htm
*/
#define sb0(a,b,c,d,e,f,g,h) \
t1 = a ^ d; \
t2 = a & d; \
t3 = c ^ t1; \
t6 = b & t1; \
t4 = b ^ t3; \
t10 = ~t3; \
h = t2 ^ t4; \
t7 = a ^ t6; \
t14 = ~t7; \
t8 = c | t7; \
t11 = t3 ^ t7; \
g = t4 ^ t8; \
t12 = h & t11; \
f = t10 ^ t12; \
e = t12 ^ t14
/* 15 terms */
#define ib0(a,b,c,d,e,f,g,h) \
t1 = ~a; \
t2 = a ^ b; \
t3 = t1 | t2; \
t4 = d ^ t3; \
t7 = d & t2; \
t5 = c ^ t4; \
t8 = t1 ^ t7; \
g = t2 ^ t5; \
t11 = a & t4; \
t9 = g & t8; \
t14 = t5 ^ t8; \
f = t4 ^ t9; \
t12 = t5 | f; \
h = t11 ^ t12; \
e = h ^ t14
/* 14 terms! */
#define sb1(a,b,c,d,e,f,g,h) \
t1 = ~a; \
t2 = b ^ t1; \
t3 = a | t2; \
t4 = d | t2; \
t5 = c ^ t3; \
g = d ^ t5; \
t7 = b ^ t4; \
t8 = t2 ^ g; \
t9 = t5 & t7; \
h = t8 ^ t9; \
t11 = t5 ^ t7; \
f = h ^ t11; \
t13 = t8 & t11; \
e = t5 ^ t13
/* 17 terms */
#define ib1(a,b,c,d,e,f,g,h) \
t1 = a ^ d; \
t2 = a & b; \
t3 = b ^ c; \
t4 = a ^ t3; \
t5 = b | d; \
t7 = c | t1; \
h = t4 ^ t5; \
t8 = b ^ t7; \
t11 = ~t2; \
t9 = t4 & t8; \
f = t1 ^ t9; \
t13 = t9 ^ t11; \
t12 = h & f; \
g = t12 ^ t13; \
t15 = a & d; \
t16 = c ^ t13; \
e = t15 ^ t16
/* 16 terms */
#define sb2(a,b,c,d,e,f,g,h) \
t1 = ~a; \
t2 = b ^ d; \
t3 = c & t1; \
t13 = d | t1; \
e = t2 ^ t3; \
t5 = c ^ t1; \
t6 = c ^ e; \
t7 = b & t6; \
t10 = e | t5; \
h = t5 ^ t7; \
t9 = d | t7; \
t11 = t9 & t10; \
t14 = t2 ^ h; \
g = a ^ t11; \
t15 = g ^ t13; \
f = t14 ^ t15
/* 16 terms */
#define ib2(a,b,c,d,e,f,g,h) \
t1 = b ^ d; \
t2 = ~t1; \
t3 = a ^ c; \
t4 = c ^ t1; \
t7 = a | t2; \
t5 = b & t4; \
t8 = d ^ t7; \
t11 = ~t4; \
e = t3 ^ t5; \
t9 = t3 | t8; \
t14 = d & t11; \
h = t1 ^ t9; \
t12 = e | h; \
f = t11 ^ t12; \
t15 = t3 ^ t12; \
g = t14 ^ t15
/* 17 terms */
#define sb3(a,b,c,d,e,f,g,h) \
t1 = a ^ c; \
t2 = d ^ t1; \
t3 = a & t2; \
t4 = d ^ t3; \
t5 = b & t4; \
g = t2 ^ t5; \
t7 = a | g; \
t8 = b | d; \
t11 = a | d; \
t9 = t4 & t7; \
f = t8 ^ t9; \
t12 = b ^ t11; \
t13 = g ^ t9; \
t15 = t3 ^ t8; \
h = t12 ^ t13; \
t16 = c & t15; \
e = t12 ^ t16
/* 16 term solution that performs less well than 17 term one
in my environment (PPro/PII)
#define sb3(a,b,c,d,e,f,g,h) \
t1 = a ^ b; \
t2 = a & c; \
t3 = a | d; \
t4 = c ^ d; \
t5 = t1 & t3; \
t6 = t2 | t5; \
g = t4 ^ t6; \
t8 = b ^ t3; \
t9 = t6 ^ t8; \
t10 = t4 & t9; \
e = t1 ^ t10; \
t12 = g & e; \
f = t9 ^ t12; \
t14 = b | d; \
t15 = t4 ^ t12; \
h = t14 ^ t15
*/
/* 17 terms */
#define ib3(a,b,c,d,e,f,g,h) \
t1 = b ^ c; \
t2 = b | c; \
t3 = a ^ c; \
t7 = a ^ d; \
t4 = t2 ^ t3; \
t5 = d | t4; \
t9 = t2 ^ t7; \
e = t1 ^ t5; \
t8 = t1 | t5; \
t11 = a & t4; \
g = t8 ^ t9; \
t12 = e | t9; \
f = t11 ^ t12; \
t14 = a & g; \
t15 = t2 ^ t14; \
t16 = e & t15; \
h = t4 ^ t16
/* 15 terms */
#define sb4(a,b,c,d,e,f,g,h) \
t1 = a ^ d; \
t2 = d & t1; \
t3 = c ^ t2; \
t4 = b | t3; \
h = t1 ^ t4; \
t6 = ~b; \
t7 = t1 | t6; \
e = t3 ^ t7; \
t9 = a & e; \
t10 = t1 ^ t6; \
t11 = t4 & t10; \
g = t9 ^ t11; \
t13 = a ^ t3; \
t14 = t10 & g; \
f = t13 ^ t14
/* 17 terms */
#define ib4(a,b,c,d,e,f,g,h) \
t1 = c ^ d; \
t2 = c | d; \
t3 = b ^ t2; \
t4 = a & t3; \
f = t1 ^ t4; \
t6 = a ^ d; \
t7 = b | d; \
t8 = t6 & t7; \
h = t3 ^ t8; \
t10 = ~a; \
t11 = c ^ h; \
t12 = t10 | t11;\
e = t3 ^ t12; \
t14 = c | t4; \
t15 = t7 ^ t14; \
t16 = h | t10; \
g = t15 ^ t16
/* 16 terms */
#define sb5(a,b,c,d,e,f,g,h) \
t1 = ~a; \
t2 = a ^ b; \
t3 = a ^ d; \
t4 = c ^ t1; \
t5 = t2 | t3; \
e = t4 ^ t5; \
t7 = d & e; \
t8 = t2 ^ e; \
t10 = t1 | e; \
f = t7 ^ t8; \
t11 = t2 | t7; \
t12 = t3 ^ t10; \
t14 = b ^ t7; \
g = t11 ^ t12; \
t15 = f & t12; \
h = t14 ^ t15
/* 16 terms */
#define ib5(a,b,c,d,e,f,g,h) \
t1 = ~c; \
t2 = b & t1; \
t3 = d ^ t2; \
t4 = a & t3; \
t5 = b ^ t1; \
h = t4 ^ t5; \
t7 = b | h; \
t8 = a & t7; \
f = t3 ^ t8; \
t10 = a | d; \
t11 = t1 ^ t7; \
e = t10 ^ t11; \
t13 = a ^ c; \
t14 = b & t10; \
t15 = t4 | t13; \
g = t14 ^ t15
/* 15 terms */
#define sb6(a,b,c,d,e,f,g,h) \
t1 = ~a; \
t2 = a ^ d; \
t3 = b ^ t2; \
t4 = t1 | t2; \
t5 = c ^ t4; \
f = b ^ t5; \
t13 = ~t5; \
t7 = t2 | f; \
t8 = d ^ t7; \
t9 = t5 & t8; \
g = t3 ^ t9; \
t11 = t5 ^ t8; \
e = g ^ t11; \
t14 = t3 & t11; \
h = t13 ^ t14
/* 15 terms */
#define ib6(a,b,c,d,e,f,g,h) \
t1 = ~a; \
t2 = a ^ b; \
t3 = c ^ t2; \
t4 = c | t1; \
t5 = d ^ t4; \
t13 = d & t1; \
f = t3 ^ t5; \
t7 = t3 & t5; \
t8 = t2 ^ t7; \
t9 = b | t8; \
h = t5 ^ t9; \
t11 = b | h; \
e = t8 ^ t11; \
t14 = t3 ^ t11; \
g = t13 ^ t14
/* 17 terms */
#define sb7(a,b,c,d,e,f,g,h) \
t1 = ~c; \
t2 = b ^ c; \
t3 = b | t1; \
t4 = d ^ t3; \
t5 = a & t4; \
t7 = a ^ d; \
h = t2 ^ t5; \
t8 = b ^ t5; \
t9 = t2 | t8; \
t11 = d & t3; \
f = t7 ^ t9; \
t12 = t5 ^ f; \
t15 = t1 | t4; \
t13 = h & t12; \
g = t11 ^ t13; \
t16 = t12 ^ g; \
e = t15 ^ t16
/* 17 terms */
#define ib7(a,b,c,d,e,f,g,h) \
t1 = a & b; \
t2 = a | b; \
t3 = c | t1; \
t4 = d & t2; \
h = t3 ^ t4; \
t6 = ~d; \
t7 = b ^ t4; \
t8 = h ^ t6; \
t11 = c ^ t7; \
t9 = t7 | t8; \
f = a ^ t9; \
t12 = d | f; \
e = t11 ^ t12; \
t14 = a & h; \
t15 = t3 ^ f; \
t16 = e ^ t14; \
g = t15 ^ t16
#define k_xor(r,a,b,c,d) \
a ^= skey->serpent.K[4 * (r) + 0]; \
b ^= skey->serpent.K[4 * (r) + 1]; \
c ^= skey->serpent.K[4 * (r) + 2]; \
d ^= skey->serpent.K[4 * (r) + 3]
#define k_set(r,a,b,c,d) \
a = lkey[4 * (r) + 8]; \
b = lkey[4 * (r) + 9]; \
c = lkey[4 * (r) + 10]; \
d = lkey[4 * (r) + 11]
#define k_get(r,a,b,c,d) \
skey->serpent.K[4 * (r) + 0] = a; \
skey->serpent.K[4 * (r) + 1] = b; \
skey->serpent.K[4 * (r) + 2] = c; \
skey->serpent.K[4 * (r) + 3] = d
/* the linear transformation and its inverse */
#define rot(a,b,c,d) \
a = ROL(a, 13); \
c = ROL(c, 3); \
d ^= c ^ (a << 3); \
b ^= a ^ c; \
d = ROL(d, 7); \
b = ROL(b, 1); \
a ^= b ^ d; \
c ^= d ^ (b << 7); \
a = ROL(a, 5); \
c = ROL(c, 22)
#define irot(a,b,c,d) \
c = ROR(c, 22); \
a = ROR(a, 5); \
c ^= d ^ (b << 7); \
a ^= b ^ d; \
d = ROR(d, 7); \
b = ROR(b, 1); \
d ^= c ^ (a << 3); \
b ^= a ^ c; \
c = ROR(c, 3); \
a = ROR(a, 13)
#ifdef CLEAN_STACK
static int _serpent_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey)
#else
int serpent_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey)
#endif
{
unsigned long lkey[140], t, a, b, c, d, e, f, g, h, x;
unsigned long t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14,t15,t16;
unsigned char buf[32];
_ARGCHK(key != NULL);
_ARGCHK(skey != NULL);
/* check rounds */
if (num_rounds != 0 && num_rounds != 32) {
return CRYPT_INVALID_ROUNDS;
}
/* check keylen */
if (keylen < 16 || keylen > 32) {
return CRYPT_INVALID_KEYSIZE;
}
/* copy key and expand to 32bytes as required */
for (x = 0; x < (unsigned long)keylen; x++) {
buf[x] = key[x];
}
if (x < 32) {
buf[x++] = 0x01;
while (x < 32) {
buf[x++] = 0;
}
}
/* copy key into 32-bit words */
for (x = 0; x < 8; x++) {
LOAD32L(lkey[x], &buf[x*4]);
}
/* expand using the LFSR to 140 words */
for (x = 0; x < 132; x++) {
t = lkey[x] ^ lkey[x+3] ^ lkey[x+5] ^ lkey[x+7] ^ x ^ 0x9E3779B9UL;
lkey[x + 8] = ROL(t, 11);
}
/* perform the substituions */
for (x = 0; x < 32; ) {
k_set( x,a,b,c,d);sb3(a,b,c,d,e,f,g,h);k_get( x,e,f,g,h); ++x;
k_set( x,a,b,c,d);sb2(a,b,c,d,e,f,g,h);k_get( x,e,f,g,h); ++x;
k_set( x,a,b,c,d);sb1(a,b,c,d,e,f,g,h);k_get( x,e,f,g,h); ++x;
k_set( x,a,b,c,d);sb0(a,b,c,d,e,f,g,h);k_get( x,e,f,g,h); ++x;
k_set( x,a,b,c,d);sb7(a,b,c,d,e,f,g,h);k_get( x,e,f,g,h); ++x;
k_set( x,a,b,c,d);sb6(a,b,c,d,e,f,g,h);k_get( x,e,f,g,h); ++x;
k_set( x,a,b,c,d);sb5(a,b,c,d,e,f,g,h);k_get( x,e,f,g,h); ++x;
k_set( x,a,b,c,d);sb4(a,b,c,d,e,f,g,h);k_get( x,e,f,g,h); ++x;
}
k_set(32,a,b,c,d);sb3(a,b,c,d,e,f,g,h);k_get(32,e,f,g,h);
return CRYPT_OK;
}
#ifdef CLEAN_STACK
int serpent_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey)
{
int x;
x = _serpent_setup(key, keylen, num_rounds, skey);
burn_stack(sizeof(unsigned long)*166 + sizeof(unsigned char)*32);
return x;
}
#endif
#ifdef CLEAN_STACK
static void _serpent_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey)
#else
void serpent_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey)
#endif
{
unsigned long a,b,c,d,e,f,g,h;
unsigned long t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14,t15,t16;
_ARGCHK(pt != NULL);
_ARGCHK(ct != NULL);
_ARGCHK(skey != NULL);
LOAD32L(a, &pt[0]);LOAD32L(b, &pt[4]);LOAD32L(c, &pt[8]);LOAD32L(d, &pt[12]);
k_xor( 0,a,b,c,d); sb0(a,b,c,d,e,f,g,h); rot(e,f,g,h);
k_xor( 1,e,f,g,h); sb1(e,f,g,h,a,b,c,d); rot(a,b,c,d);
k_xor( 2,a,b,c,d); sb2(a,b,c,d,e,f,g,h); rot(e,f,g,h);
k_xor( 3,e,f,g,h); sb3(e,f,g,h,a,b,c,d); rot(a,b,c,d);
k_xor( 4,a,b,c,d); sb4(a,b,c,d,e,f,g,h); rot(e,f,g,h);
k_xor( 5,e,f,g,h); sb5(e,f,g,h,a,b,c,d); rot(a,b,c,d);
k_xor( 6,a,b,c,d); sb6(a,b,c,d,e,f,g,h); rot(e,f,g,h);
k_xor( 7,e,f,g,h); sb7(e,f,g,h,a,b,c,d); rot(a,b,c,d);
k_xor( 8,a,b,c,d); sb0(a,b,c,d,e,f,g,h); rot(e,f,g,h);
k_xor( 9,e,f,g,h); sb1(e,f,g,h,a,b,c,d); rot(a,b,c,d);
k_xor(10,a,b,c,d); sb2(a,b,c,d,e,f,g,h); rot(e,f,g,h);
k_xor(11,e,f,g,h); sb3(e,f,g,h,a,b,c,d); rot(a,b,c,d);
k_xor(12,a,b,c,d); sb4(a,b,c,d,e,f,g,h); rot(e,f,g,h);
k_xor(13,e,f,g,h); sb5(e,f,g,h,a,b,c,d); rot(a,b,c,d);
k_xor(14,a,b,c,d); sb6(a,b,c,d,e,f,g,h); rot(e,f,g,h);
k_xor(15,e,f,g,h); sb7(e,f,g,h,a,b,c,d); rot(a,b,c,d);
k_xor(16,a,b,c,d); sb0(a,b,c,d,e,f,g,h); rot(e,f,g,h);
k_xor(17,e,f,g,h); sb1(e,f,g,h,a,b,c,d); rot(a,b,c,d);
k_xor(18,a,b,c,d); sb2(a,b,c,d,e,f,g,h); rot(e,f,g,h);
k_xor(19,e,f,g,h); sb3(e,f,g,h,a,b,c,d); rot(a,b,c,d);
k_xor(20,a,b,c,d); sb4(a,b,c,d,e,f,g,h); rot(e,f,g,h);
k_xor(21,e,f,g,h); sb5(e,f,g,h,a,b,c,d); rot(a,b,c,d);
k_xor(22,a,b,c,d); sb6(a,b,c,d,e,f,g,h); rot(e,f,g,h);
k_xor(23,e,f,g,h); sb7(e,f,g,h,a,b,c,d); rot(a,b,c,d);
k_xor(24,a,b,c,d); sb0(a,b,c,d,e,f,g,h); rot(e,f,g,h);
k_xor(25,e,f,g,h); sb1(e,f,g,h,a,b,c,d); rot(a,b,c,d);
k_xor(26,a,b,c,d); sb2(a,b,c,d,e,f,g,h); rot(e,f,g,h);
k_xor(27,e,f,g,h); sb3(e,f,g,h,a,b,c,d); rot(a,b,c,d);
k_xor(28,a,b,c,d); sb4(a,b,c,d,e,f,g,h); rot(e,f,g,h);
k_xor(29,e,f,g,h); sb5(e,f,g,h,a,b,c,d); rot(a,b,c,d);
k_xor(30,a,b,c,d); sb6(a,b,c,d,e,f,g,h); rot(e,f,g,h);
k_xor(31,e,f,g,h); sb7(e,f,g,h,a,b,c,d); k_xor(32,a,b,c,d);
STORE32L(a, &ct[0]);STORE32L(b, &ct[4]);STORE32L(c, &ct[8]);STORE32L(d, &ct[12]);
}
#ifdef CLEAN_STACK
void serpent_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey)
{
_serpent_ecb_encrypt(pt, ct, skey);
burn_stack(sizeof(unsigned long)*24);
}
#endif
#ifdef CLEAN_STACK
static void _serpent_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey)
#else
void serpent_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey)
#endif
{
unsigned long a,b,c,d,e,f,g,h;
unsigned long t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14,t15,t16;
_ARGCHK(pt != NULL);
_ARGCHK(ct != NULL);
_ARGCHK(skey != NULL);
LOAD32L(a, &ct[0]);LOAD32L(b, &ct[4]);LOAD32L(c, &ct[8]);LOAD32L(d, &ct[12]);
k_xor(32,a,b,c,d); ib7(a,b,c,d,e,f,g,h); k_xor(31,e,f,g,h);
irot(e,f,g,h); ib6(e,f,g,h,a,b,c,d); k_xor(30,a,b,c,d);
irot(a,b,c,d); ib5(a,b,c,d,e,f,g,h); k_xor(29,e,f,g,h);
irot(e,f,g,h); ib4(e,f,g,h,a,b,c,d); k_xor(28,a,b,c,d);
irot(a,b,c,d); ib3(a,b,c,d,e,f,g,h); k_xor(27,e,f,g,h);
irot(e,f,g,h); ib2(e,f,g,h,a,b,c,d); k_xor(26,a,b,c,d);
irot(a,b,c,d); ib1(a,b,c,d,e,f,g,h); k_xor(25,e,f,g,h);
irot(e,f,g,h); ib0(e,f,g,h,a,b,c,d); k_xor(24,a,b,c,d);
irot(a,b,c,d); ib7(a,b,c,d,e,f,g,h); k_xor(23,e,f,g,h);
irot(e,f,g,h); ib6(e,f,g,h,a,b,c,d); k_xor(22,a,b,c,d);
irot(a,b,c,d); ib5(a,b,c,d,e,f,g,h); k_xor(21,e,f,g,h);
irot(e,f,g,h); ib4(e,f,g,h,a,b,c,d); k_xor(20,a,b,c,d);
irot(a,b,c,d); ib3(a,b,c,d,e,f,g,h); k_xor(19,e,f,g,h);
irot(e,f,g,h); ib2(e,f,g,h,a,b,c,d); k_xor(18,a,b,c,d);
irot(a,b,c,d); ib1(a,b,c,d,e,f,g,h); k_xor(17,e,f,g,h);
irot(e,f,g,h); ib0(e,f,g,h,a,b,c,d); k_xor(16,a,b,c,d);
irot(a,b,c,d); ib7(a,b,c,d,e,f,g,h); k_xor(15,e,f,g,h);
irot(e,f,g,h); ib6(e,f,g,h,a,b,c,d); k_xor(14,a,b,c,d);
irot(a,b,c,d); ib5(a,b,c,d,e,f,g,h); k_xor(13,e,f,g,h);
irot(e,f,g,h); ib4(e,f,g,h,a,b,c,d); k_xor(12,a,b,c,d);
irot(a,b,c,d); ib3(a,b,c,d,e,f,g,h); k_xor(11,e,f,g,h);
irot(e,f,g,h); ib2(e,f,g,h,a,b,c,d); k_xor(10,a,b,c,d);
irot(a,b,c,d); ib1(a,b,c,d,e,f,g,h); k_xor( 9,e,f,g,h);
irot(e,f,g,h); ib0(e,f,g,h,a,b,c,d); k_xor( 8,a,b,c,d);
irot(a,b,c,d); ib7(a,b,c,d,e,f,g,h); k_xor( 7,e,f,g,h);
irot(e,f,g,h); ib6(e,f,g,h,a,b,c,d); k_xor( 6,a,b,c,d);
irot(a,b,c,d); ib5(a,b,c,d,e,f,g,h); k_xor( 5,e,f,g,h);
irot(e,f,g,h); ib4(e,f,g,h,a,b,c,d); k_xor( 4,a,b,c,d);
irot(a,b,c,d); ib3(a,b,c,d,e,f,g,h); k_xor( 3,e,f,g,h);
irot(e,f,g,h); ib2(e,f,g,h,a,b,c,d); k_xor( 2,a,b,c,d);
irot(a,b,c,d); ib1(a,b,c,d,e,f,g,h); k_xor( 1,e,f,g,h);
irot(e,f,g,h); ib0(e,f,g,h,a,b,c,d); k_xor( 0,a,b,c,d);
STORE32L(a, &pt[0]);STORE32L(b, &pt[4]);STORE32L(c, &pt[8]);STORE32L(d, &pt[12]);
}
#ifdef CLEAN_STACK
void serpent_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey)
{
_serpent_ecb_decrypt(ct, pt, skey);
burn_stack(sizeof(unsigned long)*24);
}
#endif
int serpent_test(void)
{
static const struct {
int keylen;
unsigned char key[32], pt[16], ct[16];
} tests[] = {
{
16,
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
{ 0xdd, 0xd2, 0x6b, 0x98, 0xa5, 0xff, 0xd8, 0x2c,
0x05, 0x34, 0x5a, 0x9d, 0xad, 0xbf, 0xaf, 0x49 }
},
{
16,
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80 },
{ 0x4a, 0xe9, 0xa2, 0x0b, 0x2b, 0x14, 0xa1, 0x02,
0x90, 0xcb, 0xb8, 0x20, 0xb7, 0xff, 0xb5, 0x10 }
},
{
24,
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08 },
{ 0xe1, 0x1b, 0x01, 0x52, 0x4e, 0xa1, 0xf4, 0x65,
0xa2, 0xa2, 0x00, 0x43, 0xeb, 0x9f, 0x7e, 0x8a }
},
{
32,
{ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
{ 0xe0, 0x88, 0x5d, 0x44, 0x60, 0x37, 0x34, 0x69,
0xd1, 0xfa, 0x6c, 0x36, 0xa6, 0xe1, 0xc5, 0x2f }
},
{
32,
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
{ 0x17, 0xc6, 0x25, 0x8e, 0x60, 0x09, 0xe2, 0x82,
0x66, 0x18, 0x69, 0xd5, 0x25, 0xf7, 0xd2, 0x04 }
},
{
32,
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
{ 0x9f, 0xe1, 0x43, 0x25, 0x0d, 0x00, 0xe2, 0x56,
0x96, 0xb0, 0x1e, 0x0a, 0x2e, 0xd0, 0x5d, 0xb3 }
}
};
unsigned char buf[2][16];
int x, failed, errno;
symmetric_key key;
for (x = failed = 0; x < (int)(sizeof(tests) / sizeof(tests[0])); x++) {
/* setup key */
if ((errno = serpent_setup(tests[x].key, tests[x].keylen, 0, &key))!= CRYPT_OK) {
return errno;
}
/* encrypt and decrypt */
serpent_ecb_encrypt(tests[x].pt, buf[0], &key);
serpent_ecb_decrypt(buf[0], buf[1], &key);
/* compare */
if (memcmp(buf[0], tests[x].ct, 16)) {
#if 0
int y;
printf("\nEncrypt test %d failed\n", x);
for (y = 0; y < 16; y++) printf("%02x ", buf[0][y]);
printf("\n");
#endif
failed = 1;
}
if (memcmp(buf[1], tests[x].pt, 16)) {
#if 0
int y;
printf("\nDecrypt test %d failed\n", x);
for (y = 0; y < 16; y++) printf("%02x ", buf[1][y]);
printf("\n");
#endif
failed = 1;
}
}
if (failed == 1) {
return CRYPT_FAIL_TESTVECTOR;
} else {
return CRYPT_OK;
}
}
int serpent_keysize(int *desired_keysize)
{
_ARGCHK(desired_keysize != NULL);
if (*desired_keysize < 16)
return CRYPT_INVALID_KEYSIZE;
if (*desired_keysize > 32)
*desired_keysize = 32;
return CRYPT_OK;
}
#endif

232
sha1.c Normal file
View File

@ -0,0 +1,232 @@
#include "mycrypt.h"
#ifdef SHA1
const struct _hash_descriptor sha1_desc =
{
"sha1",
2,
20,
64,
&sha1_init,
&sha1_process,
&sha1_done,
&sha1_test
};
#define F0(x,y,z) ( (x&y) | ((~x)&z) )
#define F1(x,y,z) (x ^ y ^ z)
#define F2(x,y,z) ((x & y) | (z & (x | y)))
#define F3(x,y,z) (x ^ y ^ z)
#ifdef CLEAN_STACK
static void _sha1_compress(hash_state *md)
#else
static void sha1_compress(hash_state *md)
#endif
{
unsigned long a,b,c,d,e,W[80],i,j;
_ARGCHK(md != NULL);
/* copy the state into 512-bits into W[0..15] */
for (i = 0; i < 16; i++) {
LOAD32H(W[i], md->sha1.buf + (4*i));
}
/* copy state */
a = md->sha1.state[0];
b = md->sha1.state[1];
c = md->sha1.state[2];
d = md->sha1.state[3];
e = md->sha1.state[4];
/* expand it */
for (i = 16; i < 80; i++) {
j = W[i-3] ^ W[i-8] ^ W[i-14] ^ W[i-16];
W[i] = ROL(j, 1);
}
/* compress */
/* round one */
for (i = 0; i < 20; i++) {
j = (ROL(a, 5) + F0(b,c,d) + e + W[i] + 0x5a827999UL);
e = d;
d = c;
c = ROL(b, 30);
b = a;
a = j;
}
/* round two */
for (i = 20; i < 40; i++) {
j = (ROL(a, 5) + F1(b,c,d) + e + W[i] + 0x6ed9eba1UL);
e = d;
d = c;
c = ROL(b, 30);
b = a;
a = j;
}
/* round three */
for (i = 40; i < 60; i++) {
j = (ROL(a, 5) + F2(b,c,d) + e + W[i] + 0x8f1bbcdcUL);
e = d;
d = c;
c = ROL(b, 30);
b = a;
a = j;
}
/* round four */
for (i = 60; i < 80; i++) {
j = (ROL(a, 5) + F3(b,c,d) + e + W[i] + 0xca62c1d6UL);
e = d;
d = c;
c = ROL(b, 30);
b = a;
a = j;
}
/* store */
md->sha1.state[0] = md->sha1.state[0] + a;
md->sha1.state[1] = md->sha1.state[1] + b;
md->sha1.state[2] = md->sha1.state[2] + c;
md->sha1.state[3] = md->sha1.state[3] + d;
md->sha1.state[4] = md->sha1.state[4] + e;
}
#ifdef CLEAN_STACK
static void sha1_compress(hash_state *md)
{
_sha1_compress(md);
burn_stack(sizeof(unsigned long) * 87);
}
#endif
void sha1_init(hash_state * md)
{
_ARGCHK(md != NULL);
md->sha1.state[0] = 0x67452301UL;
md->sha1.state[1] = 0xefcdab89UL;
md->sha1.state[2] = 0x98badcfeUL;
md->sha1.state[3] = 0x10325476UL;
md->sha1.state[4] = 0xc3d2e1f0UL;
md->sha1.curlen = 0;
md->sha1.length = 0;
}
void sha1_process(hash_state * md, const unsigned char *buf, unsigned long len)
{
unsigned long n;
_ARGCHK(md != NULL);
_ARGCHK(buf != NULL);
while (len) {
n = MIN(len, (64 - md->sha1.curlen));
memcpy(md->sha1.buf + md->sha1.curlen, buf, n);
md->sha1.curlen += n;
buf += n;
len -= n;
/* is 64 bytes full? */
if (md->sha1.curlen == 64) {
sha1_compress(md);
md->sha1.length += 512;
md->sha1.curlen = 0;
}
}
}
void sha1_done(hash_state * md, unsigned char *hash)
{
int i;
_ARGCHK(md != NULL);
_ARGCHK(hash != NULL);
/* increase the length of the message */
md->sha1.length += md->sha1.curlen * 8;
/* append the '1' bit */
md->sha1.buf[md->sha1.curlen++] = 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->sha1.curlen > 56) {
while (md->sha1.curlen < 64) {
md->sha1.buf[md->sha1.curlen++] = 0;
}
sha1_compress(md);
md->sha1.curlen = 0;
}
/* pad upto 56 bytes of zeroes */
while (md->sha1.curlen < 56) {
md->sha1.buf[md->sha1.curlen++] = 0;
}
/* store length */
STORE64H(md->sha1.length, md->sha1.buf+56);
sha1_compress(md);
/* copy output */
for (i = 0; i < 5; i++) {
STORE32H(md->sha1.state[i], hash+(4*i));
}
#ifdef CLEAN_STACK
zeromem(md, sizeof(hash_state));
#endif
}
int sha1_test(void)
{
static const struct {
unsigned char *msg;
unsigned char hash[20];
} tests[] = {
{ "abc",
{ 0xa9, 0x99, 0x3e, 0x36, 0x47, 0x06, 0x81, 0x6a,
0xba, 0x3e, 0x25, 0x71, 0x78, 0x50, 0xc2, 0x6c,
0x9c, 0xd0, 0xd8, 0x9d }
},
{ "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
{ 0x84, 0x98, 0x3E, 0x44, 0x1C, 0x3B, 0xD2, 0x6E,
0xBA, 0xAE, 0x4A, 0xA1, 0xF9, 0x51, 0x29, 0xE5,
0xE5, 0x46, 0x70, 0xF1 }
},
{ NULL, { 0 }}
};
int failed, i;
unsigned char tmp[20];
hash_state md;
for (failed = i = 0; tests[i].msg != NULL; i++) {
sha1_init(&md);
sha1_process(&md, tests[i].msg, strlen(tests[i].msg));
sha1_done(&md, tmp);
if (memcmp(tmp, tests[i].hash, 20)) {
#if 0
int j;
printf("\nSHA-1 Test %d failed\nGot (as a result): ", i);
for (j = 0; j < 20; j++) {
printf("%02x ", tmp[j]);
}
printf("\n");
#endif
failed = 1;
}
}
if (failed == 1) {
return CRYPT_FAIL_TESTVECTOR;
} else {
return CRYPT_OK;
}
}
#endif

229
sha256.c Normal file
View File

@ -0,0 +1,229 @@
#include "mycrypt.h"
#ifdef SHA256
const struct _hash_descriptor sha256_desc =
{
"sha256",
0,
32,
64,
&sha256_init,
&sha256_process,
&sha256_done,
&sha256_test
};
/* the K array */
static const unsigned long K[64] = {
0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL, 0x3956c25bUL,
0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL, 0xd807aa98UL, 0x12835b01UL,
0x243185beUL, 0x550c7dc3UL, 0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL,
0xc19bf174UL, 0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL,
0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL, 0x983e5152UL,
0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL, 0xc6e00bf3UL, 0xd5a79147UL,
0x06ca6351UL, 0x14292967UL, 0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL,
0x53380d13UL, 0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL,
0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL, 0xd192e819UL,
0xd6990624UL, 0xf40e3585UL, 0x106aa070UL, 0x19a4c116UL, 0x1e376c08UL,
0x2748774cUL, 0x34b0bcb5UL, 0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL,
0x682e6ff3UL, 0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL,
0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL
};
/* Various logical functions */
#define Ch(x,y,z) ((x & y) ^ (~x & z))
#define Maj(x,y,z) ((x & y) ^ (x & z) ^ (y & z))
#define S(x, n) ROR((x),(n))
#define R(x, n) (((x)&0xFFFFFFFFUL)>>(n))
#define Sigma0(x) (S(x, 2) ^ S(x, 13) ^ S(x, 22))
#define Sigma1(x) (S(x, 6) ^ S(x, 11) ^ S(x, 25))
#define Gamma0(x) (S(x, 7) ^ S(x, 18) ^ R(x, 3))
#define Gamma1(x) (S(x, 17) ^ S(x, 19) ^ R(x, 10))
/* compress 512-bits */
#ifdef CLEAN_STACK
static void _sha256_compress(hash_state * md)
#else
static void sha256_compress(hash_state * md)
#endif
{
unsigned long S[8], W[64], t0, t1;
int i;
_ARGCHK(md != NULL);
/* copy state into S */
for (i = 0; i < 8; i++)
S[i] = md->sha256.state[i];
/* copy the state into 512-bits into W[0..15] */
for (i = 0; i < 16; i++) {
LOAD32H(W[i], md->sha256.buf + (4*i));
}
/* fill W[16..63] */
for (i = 16; i < 64; i++)
W[i] = Gamma1(W[i - 2]) + W[i - 7] + Gamma0(W[i - 15]) + W[i - 16];
/* Compress */
for (i = 0; i < 64; i++) {
t0 = S[7] + Sigma1(S[4]) + Ch(S[4], S[5], S[6]) + K[i] + W[i];
t1 = Sigma0(S[0]) + Maj(S[0], S[1], S[2]);
S[7] = S[6];
S[6] = S[5];
S[5] = S[4];
S[4] = S[3] + t0;
S[3] = S[2];
S[2] = S[1];
S[1] = S[0];
S[0] = t0 + t1;
}
/* feedback */
for (i = 0; i < 8; i++) {
md->sha256.state[i] = md->sha256.state[i] + S[i];
}
}
#ifdef CLEAN_STACK
static void sha256_compress(hash_state * md)
{
_sha256_compress(md);
burn_stack(sizeof(unsigned long) * 74);
}
#endif
/* init the sha256 state */
void sha256_init(hash_state * md)
{
_ARGCHK(md != NULL);
md->sha256.curlen = 0;
md->sha256.length = 0;
md->sha256.state[0] = 0x6A09E667UL;
md->sha256.state[1] = 0xBB67AE85UL;
md->sha256.state[2] = 0x3C6EF372UL;
md->sha256.state[3] = 0xA54FF53AUL;
md->sha256.state[4] = 0x510E527FUL;
md->sha256.state[5] = 0x9B05688CUL;
md->sha256.state[6] = 0x1F83D9ABUL;
md->sha256.state[7] = 0x5BE0CD19UL;
}
void sha256_process(hash_state * md, const unsigned char *buf, unsigned long len)
{
unsigned long n;
_ARGCHK(md != NULL);
_ARGCHK(buf != NULL);
while (len) {
n = MIN(len, (64 - md->sha256.curlen));
memcpy(md->sha256.buf + md->sha256.curlen, buf, n);
md->sha256.curlen += n;
buf += n;
len -= n;
/* is 64 bytes full? */
if (md->sha256.curlen == 64) {
sha256_compress(md);
md->sha256.length += 512;
md->sha256.curlen = 0;
}
}
}
void sha256_done(hash_state * md, unsigned char *hash)
{
int i;
_ARGCHK(md != NULL);
_ARGCHK(hash != NULL);
/* increase the length of the message */
md->sha256.length += md->sha256.curlen * 8;
/* append the '1' bit */
md->sha256.buf[md->sha256.curlen++] = 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->sha256.curlen > 56) {
while (md->sha256.curlen < 64) {
md->sha256.buf[md->sha256.curlen++] = 0;
}
sha256_compress(md);
md->sha256.curlen = 0;
}
/* pad upto 56 bytes of zeroes */
while (md->sha256.curlen < 56) {
md->sha256.buf[md->sha256.curlen++] = 0;
}
/* store length */
STORE64H(md->sha256.length, md->sha256.buf+56);
sha256_compress(md);
/* copy output */
for (i = 0; i < 8; i++) {
STORE32H(md->sha256.state[i], hash+(4*i));
}
#ifdef CLEAN_STACK
zeromem(md, sizeof(hash_state));
#endif
}
int sha256_test(void)
{
static const struct {
unsigned char *msg;
unsigned char hash[32];
} tests[] = {
{ "abc",
{ 0xba, 0x78, 0x16, 0xbf, 0x8f, 0x01, 0xcf, 0xea,
0x41, 0x41, 0x40, 0xde, 0x5d, 0xae, 0x22, 0x23,
0xb0, 0x03, 0x61, 0xa3, 0x96, 0x17, 0x7a, 0x9c,
0xb4, 0x10, 0xff, 0x61, 0xf2, 0x00, 0x15, 0xad }
},
{ "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
{ 0x24, 0x8d, 0x6a, 0x61, 0xd2, 0x06, 0x38, 0xb8,
0xe5, 0xc0, 0x26, 0x93, 0x0c, 0x3e, 0x60, 0x39,
0xa3, 0x3c, 0xe4, 0x59, 0x64, 0xff, 0x21, 0x67,
0xf6, 0xec, 0xed, 0xd4, 0x19, 0xdb, 0x06, 0xc1 }
},
{ NULL, { 0 } }
};
int failed, i;
unsigned char tmp[32];
hash_state md;
for (failed = i = 0; tests[i].msg != NULL; i++) {
sha256_init(&md);
sha256_process(&md, tests[i].msg, strlen(tests[i].msg));
sha256_done(&md, tmp);
if (memcmp(tmp, tests[i].hash, 32)) {
#if 0
int j;
printf("\nSHA-256 Test %d failed\nGot (as a result): ", i);
for (j = 0; j < 32; j++) {
printf("%02x ", tmp[j]);
}
printf("\n");
#endif
failed = 1;
}
}
if (failed == 1) {
return CRYPT_FAIL_TESTVECTOR;
} else {
return CRYPT_OK;
}
}
#endif

107
sha384.c Normal file
View File

@ -0,0 +1,107 @@
/* included in sha512.c */
const struct _hash_descriptor sha384_desc =
{
"sha384",
4,
48,
128,
&sha384_init,
&sha384_process,
&sha384_done,
&sha384_test
};
void sha384_init(hash_state * md)
{
_ARGCHK(md != NULL);
md->sha512.curlen = 0;
md->sha512.length = 0;
md->sha512.state[0] = CONST64(0xcbbb9d5dc1059ed8);
md->sha512.state[1] = CONST64(0x629a292a367cd507);
md->sha512.state[2] = CONST64(0x9159015a3070dd17);
md->sha512.state[3] = CONST64(0x152fecd8f70e5939);
md->sha512.state[4] = CONST64(0x67332667ffc00b31);
md->sha512.state[5] = CONST64(0x8eb44a8768581511);
md->sha512.state[6] = CONST64(0xdb0c2e0d64f98fa7);
md->sha512.state[7] = CONST64(0x47b5481dbefa4fa4);
}
void sha384_process(hash_state * md, const unsigned char *buf, unsigned long len)
{
_ARGCHK(md != NULL);
_ARGCHK(buf != NULL);
sha512_process(md, buf, len);
}
void sha384_done(hash_state * md, unsigned char *hash)
{
unsigned char buf[64];
_ARGCHK(md != NULL);
_ARGCHK(hash != NULL);
sha512_done(md, buf);
memcpy(hash, buf, 48);
#ifdef CLEAN_STACK
zeromem(buf, sizeof(buf));
#endif
}
int sha384_test(void)
{
static const struct {
unsigned char *msg;
unsigned char hash[48];
} tests[] = {
{ "abc",
{ 0xcb, 0x00, 0x75, 0x3f, 0x45, 0xa3, 0x5e, 0x8b,
0xb5, 0xa0, 0x3d, 0x69, 0x9a, 0xc6, 0x50, 0x07,
0x27, 0x2c, 0x32, 0xab, 0x0e, 0xde, 0xd1, 0x63,
0x1a, 0x8b, 0x60, 0x5a, 0x43, 0xff, 0x5b, 0xed,
0x80, 0x86, 0x07, 0x2b, 0xa1, 0xe7, 0xcc, 0x23,
0x58, 0xba, 0xec, 0xa1, 0x34, 0xc8, 0x25, 0xa7 }
},
{ "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu",
{ 0x09, 0x33, 0x0c, 0x33, 0xf7, 0x11, 0x47, 0xe8,
0x3d, 0x19, 0x2f, 0xc7, 0x82, 0xcd, 0x1b, 0x47,
0x53, 0x11, 0x1b, 0x17, 0x3b, 0x3b, 0x05, 0xd2,
0x2f, 0xa0, 0x80, 0x86, 0xe3, 0xb0, 0xf7, 0x12,
0xfc, 0xc7, 0xc7, 0x1a, 0x55, 0x7e, 0x2d, 0xb9,
0x66, 0xc3, 0xe9, 0xfa, 0x91, 0x74, 0x60, 0x39 }
},
{ NULL, { 0 }}
};
int failed, i;
unsigned char tmp[48];
hash_state md;
for (failed = i = 0; tests[i].msg != NULL; i++) {
sha384_init(&md);
sha384_process(&md, tests[i].msg, strlen(tests[i].msg));
sha384_done(&md, tmp);
if (memcmp(tmp, tests[i].hash, 48)) {
#if 0
int j;
printf("\nSHA-384 Test %d failed\nGot (as a result): ", i);
for (j = 0; j < 48; j++) {
printf("%02x ", tmp[j]);
}
printf("\n");
#endif
failed = 1;
}
}
if (failed == 1) {
return CRYPT_FAIL_TESTVECTOR;
} else {
return CRYPT_OK;
}
}

272
sha512.c Normal file
View File

@ -0,0 +1,272 @@
#include "mycrypt.h"
#ifdef SHA512
const struct _hash_descriptor sha512_desc =
{
"sha512",
5,
64,
128,
&sha512_init,
&sha512_process,
&sha512_done,
&sha512_test
};
/* the K array */
static const ulong64 K[80] = {
CONST64(0x428a2f98d728ae22), CONST64(0x7137449123ef65cd),
CONST64(0xb5c0fbcfec4d3b2f), CONST64(0xe9b5dba58189dbbc),
CONST64(0x3956c25bf348b538), CONST64(0x59f111f1b605d019),
CONST64(0x923f82a4af194f9b), CONST64(0xab1c5ed5da6d8118),
CONST64(0xd807aa98a3030242), CONST64(0x12835b0145706fbe),
CONST64(0x243185be4ee4b28c), CONST64(0x550c7dc3d5ffb4e2),
CONST64(0x72be5d74f27b896f), CONST64(0x80deb1fe3b1696b1),
CONST64(0x9bdc06a725c71235), CONST64(0xc19bf174cf692694),
CONST64(0xe49b69c19ef14ad2), CONST64(0xefbe4786384f25e3),
CONST64(0x0fc19dc68b8cd5b5), CONST64(0x240ca1cc77ac9c65),
CONST64(0x2de92c6f592b0275), CONST64(0x4a7484aa6ea6e483),
CONST64(0x5cb0a9dcbd41fbd4), CONST64(0x76f988da831153b5),
CONST64(0x983e5152ee66dfab), CONST64(0xa831c66d2db43210),
CONST64(0xb00327c898fb213f), CONST64(0xbf597fc7beef0ee4),
CONST64(0xc6e00bf33da88fc2), CONST64(0xd5a79147930aa725),
CONST64(0x06ca6351e003826f), CONST64(0x142929670a0e6e70),
CONST64(0x27b70a8546d22ffc), CONST64(0x2e1b21385c26c926),
CONST64(0x4d2c6dfc5ac42aed), CONST64(0x53380d139d95b3df),
CONST64(0x650a73548baf63de), CONST64(0x766a0abb3c77b2a8),
CONST64(0x81c2c92e47edaee6), CONST64(0x92722c851482353b),
CONST64(0xa2bfe8a14cf10364), CONST64(0xa81a664bbc423001),
CONST64(0xc24b8b70d0f89791), CONST64(0xc76c51a30654be30),
CONST64(0xd192e819d6ef5218), CONST64(0xd69906245565a910),
CONST64(0xf40e35855771202a), CONST64(0x106aa07032bbd1b8),
CONST64(0x19a4c116b8d2d0c8), CONST64(0x1e376c085141ab53),
CONST64(0x2748774cdf8eeb99), CONST64(0x34b0bcb5e19b48a8),
CONST64(0x391c0cb3c5c95a63), CONST64(0x4ed8aa4ae3418acb),
CONST64(0x5b9cca4f7763e373), CONST64(0x682e6ff3d6b2b8a3),
CONST64(0x748f82ee5defb2fc), CONST64(0x78a5636f43172f60),
CONST64(0x84c87814a1f0ab72), CONST64(0x8cc702081a6439ec),
CONST64(0x90befffa23631e28), CONST64(0xa4506cebde82bde9),
CONST64(0xbef9a3f7b2c67915), CONST64(0xc67178f2e372532b),
CONST64(0xca273eceea26619c), CONST64(0xd186b8c721c0c207),
CONST64(0xeada7dd6cde0eb1e), CONST64(0xf57d4f7fee6ed178),
CONST64(0x06f067aa72176fba), CONST64(0x0a637dc5a2c898a6),
CONST64(0x113f9804bef90dae), CONST64(0x1b710b35131c471b),
CONST64(0x28db77f523047d84), CONST64(0x32caab7b40c72493),
CONST64(0x3c9ebe0a15c9bebc), CONST64(0x431d67c49c100d4c),
CONST64(0x4cc5d4becb3e42b6), CONST64(0x597f299cfc657e2a),
CONST64(0x5fcb6fab3ad6faec), CONST64(0x6c44198c4a475817)
};
/* Various logical functions */
#define Ch(x,y,z) ((x & y) ^ (~x & z))
#define Maj(x,y,z) ((x & y) ^ (x & z) ^ (y & z))
#define S(x, n) ROR64((x),(n))
#define R(x, n) (((x)&CONST64(0xFFFFFFFFFFFFFFFF))>>((ulong64)n))
#define Sigma0(x) (S(x, 28) ^ S(x, 34) ^ S(x, 39))
#define Sigma1(x) (S(x, 14) ^ S(x, 18) ^ S(x, 41))
#define Gamma0(x) (S(x, 1) ^ S(x, 8) ^ R(x, 7))
#define Gamma1(x) (S(x, 19) ^ S(x, 61) ^ R(x, 6))
/* compress 1024-bits */
#ifdef CLEAN_STACK
static void _sha512_compress(hash_state * md)
#else
static void sha512_compress(hash_state * md)
#endif
{
ulong64 S[8], W[80], t0, t1;
int i;
_ARGCHK(md != NULL);
/* copy state into S */
for (i = 0; i < 8; i++)
S[i] = md->sha512.state[i];
/* copy the state into 1024-bits into W[0..15] */
for (i = 0; i < 16; i++) {
LOAD64H(W[i], md->sha512.buf + (8*i));
}
/* fill W[16..79] */
for (i = 16; i < 80; i++)
W[i] = Gamma1(W[i - 2]) + W[i - 7] + Gamma0(W[i - 15]) + W[i - 16];
/* Compress */
for (i = 0; i < 80; i++) {
t0 = S[7] + Sigma1(S[4]) + Ch(S[4], S[5], S[6]) + K[i] + W[i];
t1 = Sigma0(S[0]) + Maj(S[0], S[1], S[2]);
S[7] = S[6];
S[6] = S[5];
S[5] = S[4];
S[4] = S[3] + t0;
S[3] = S[2];
S[2] = S[1];
S[1] = S[0];
S[0] = t0 + t1;
}
/* feedback */
for (i = 0; i < 8; i++) {
md->sha512.state[i] = md->sha512.state[i] + S[i];
}
}
/* compress 1024-bits */
#ifdef CLEAN_STACK
static void sha512_compress(hash_state * md)
{
_sha512_compress(md);
burn_stack(sizeof(ulong64) * 90 + sizeof(int));
}
#endif
/* init the sha512 state */
void sha512_init(hash_state * md)
{
_ARGCHK(md != NULL);
md->sha512.curlen = 0;
md->sha512.length = 0;
md->sha512.state[0] = CONST64(0x6a09e667f3bcc908);
md->sha512.state[1] = CONST64(0xbb67ae8584caa73b);
md->sha512.state[2] = CONST64(0x3c6ef372fe94f82b);
md->sha512.state[3] = CONST64(0xa54ff53a5f1d36f1);
md->sha512.state[4] = CONST64(0x510e527fade682d1);
md->sha512.state[5] = CONST64(0x9b05688c2b3e6c1f);
md->sha512.state[6] = CONST64(0x1f83d9abfb41bd6b);
md->sha512.state[7] = CONST64(0x5be0cd19137e2179);
}
void sha512_process(hash_state * md, const unsigned char *buf, unsigned long len)
{
unsigned long n;
_ARGCHK(md != NULL);
_ARGCHK(buf != NULL);
while (len) {
n = MIN(len, (128 - md->sha512.curlen));
memcpy(md->sha512.buf + md->sha512.curlen, buf, n);
md->sha512.curlen += n;
buf += n;
len -= n;
/* is 64 bytes full? */
if (md->sha512.curlen == 128) {
sha512_compress(md);
md->sha512.length += 1024;
md->sha512.curlen = 0;
}
}
}
void sha512_done(hash_state * md, unsigned char *hash)
{
int i;
_ARGCHK(md != NULL);
_ARGCHK(hash != NULL);
/* increase the length of the message */
md->sha512.length += md->sha512.curlen * CONST64(8);
/* append the '1' bit */
md->sha512.buf[md->sha512.curlen++] = 0x80;
/* if the length is currently above 112 bytes we append zeros
* then compress. Then we can fall back to padding zeros and length
* encoding like normal.
*/
if (md->sha512.curlen > 112) {
while (md->sha512.curlen < 128) {
md->sha512.buf[md->sha512.curlen++] = 0;
}
sha512_compress(md);
md->sha512.curlen = 0;
}
/* pad upto 120 bytes of zeroes
* note: that from 112 to 120 is the 64 MSB of the length. We assume that you won't hash
* > 2^64 bits of data... :-)
*/
while (md->sha512.curlen < 120) {
md->sha512.buf[md->sha512.curlen++] = 0;
}
/* store length */
STORE64H(md->sha512.length, md->sha512.buf+120);
sha512_compress(md);
/* copy output */
for (i = 0; i < 8; i++) {
STORE64H(md->sha512.state[i], hash+(8*i));
}
#ifdef CLEAN_STACK
zeromem(md, sizeof(hash_state));
#endif
}
int sha512_test(void)
{
static const struct {
unsigned char *msg;
unsigned char hash[64];
} tests[] = {
{ "abc",
{ 0xdd, 0xaf, 0x35, 0xa1, 0x93, 0x61, 0x7a, 0xba,
0xcc, 0x41, 0x73, 0x49, 0xae, 0x20, 0x41, 0x31,
0x12, 0xe6, 0xfa, 0x4e, 0x89, 0xa9, 0x7e, 0xa2,
0x0a, 0x9e, 0xee, 0xe6, 0x4b, 0x55, 0xd3, 0x9a,
0x21, 0x92, 0x99, 0x2a, 0x27, 0x4f, 0xc1, 0xa8,
0x36, 0xba, 0x3c, 0x23, 0xa3, 0xfe, 0xeb, 0xbd,
0x45, 0x4d, 0x44, 0x23, 0x64, 0x3c, 0xe8, 0x0e,
0x2a, 0x9a, 0xc9, 0x4f, 0xa5, 0x4c, 0xa4, 0x9f }
},
{ "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu",
{ 0x8e, 0x95, 0x9b, 0x75, 0xda, 0xe3, 0x13, 0xda,
0x8c, 0xf4, 0xf7, 0x28, 0x14, 0xfc, 0x14, 0x3f,
0x8f, 0x77, 0x79, 0xc6, 0xeb, 0x9f, 0x7f, 0xa1,
0x72, 0x99, 0xae, 0xad, 0xb6, 0x88, 0x90, 0x18,
0x50, 0x1d, 0x28, 0x9e, 0x49, 0x00, 0xf7, 0xe4,
0x33, 0x1b, 0x99, 0xde, 0xc4, 0xb5, 0x43, 0x3a,
0xc7, 0xd3, 0x29, 0xee, 0xb6, 0xdd, 0x26, 0x54,
0x5e, 0x96, 0xe5, 0x5b, 0x87, 0x4b, 0xe9, 0x09 }
},
{ NULL, { 0 }}
};
int failed, i;
unsigned char tmp[64];
hash_state md;
for (failed = i = 0; tests[i].msg != NULL; i++) {
sha512_init(&md);
sha512_process(&md, tests[i].msg, strlen(tests[i].msg));
sha512_done(&md, tmp);
if (memcmp(tmp, tests[i].hash, 64)) {
#if 0
int j;
printf("\nSHA-512 Test %d failed\nGot (as a result): ", i);
for (j = 0; j < 64; j++) {
printf("%02x ", tmp[j]);
}
printf("\n");
#endif
failed = 1;
}
}
if (failed == 1) {
return CRYPT_FAIL_TESTVECTOR;
} else {
return CRYPT_OK;
}
}
#ifdef SHA384
#include "sha384.c"
#endif
#endif

42
sprng.c Normal file
View File

@ -0,0 +1,42 @@
/* A secure PRNG using the RNG functions. Basically this is a
* wrapper that allows you to use a secure RNG as a PRNG
* in the various other functions.
*/
#include "mycrypt.h"
#ifdef SPRNG
const struct _prng_descriptor sprng_desc =
{
"sprng",
&sprng_start,
&sprng_add_entropy,
&sprng_ready,
&sprng_read
};
int sprng_start(prng_state *prng)
{
return CRYPT_OK;
}
int sprng_add_entropy(const unsigned char *buf, unsigned long len, prng_state *prng)
{
return CRYPT_OK;
}
int sprng_ready(prng_state *prng)
{
return CRYPT_OK;
}
unsigned long sprng_read(unsigned char *buf, unsigned long len, prng_state *prng)
{
_ARGCHK(buf != NULL);
return rng_get_bytes(buf, len, NULL);
}
#endif

47
strings.c Normal file
View File

@ -0,0 +1,47 @@
/* Future releases will make use of this */
#include "mycrypt.h"
static const char *err_2_str[] =
{
"CRYPT_OK",
"CRYPT_ERROR",
"Invalid keysize for block cipher.",
"Invalid number of rounds for block cipher.",
"Algorithm failed test vectors.",
"Buffer overflow.",
"Invalid input packet.",
"Invalid number of bits for a PRNG.",
"Error reading the PRNG.",
"Invalid cipher specified.",
"Invalid hash specified.",
"Invalid PRNG specified.",
"Out of memory.",
"Invalid PK key or key type specified for function.",
"A private PK key is required.",
"Invalid argument provided.",
"Invalid PK type.",
"Invalid PK system.",
"Duplicate PK key found on keyring.",
"Key not found in keyring.",
"Invalid sized parameter.",
"Invalid size for prime."
};
const char *error_to_string(int errno)
{
if (errno < 0 || errno > (int)(sizeof(err_2_str)/sizeof(err_2_str[0]))) {
return "Invalid error code.";
} else {
return err_2_str[errno];
}
}

775
tiger.c Normal file
View File

@ -0,0 +1,775 @@
#include "mycrypt.h"
#ifdef TIGER
const struct _hash_descriptor tiger_desc =
{
"tiger",
1,
24,
64,
&tiger_init,
&tiger_process,
&tiger_done,
&tiger_test
};
#define t1 (table)
#define t2 (table+256)
#define t3 (table+256*2)
#define t4 (table+256*3)
#define save_abc aa = a; bb = b; cc = c;
static const ulong64 table[4*256] = {
CONST64(0x02AAB17CF7E90C5E) /* 0 */, CONST64(0xAC424B03E243A8EC) /* 1 */,
CONST64(0x72CD5BE30DD5FCD3) /* 2 */, CONST64(0x6D019B93F6F97F3A) /* 3 */,
CONST64(0xCD9978FFD21F9193) /* 4 */, CONST64(0x7573A1C9708029E2) /* 5 */,
CONST64(0xB164326B922A83C3) /* 6 */, CONST64(0x46883EEE04915870) /* 7 */,
CONST64(0xEAACE3057103ECE6) /* 8 */, CONST64(0xC54169B808A3535C) /* 9 */,
CONST64(0x4CE754918DDEC47C) /* 10 */, CONST64(0x0AA2F4DFDC0DF40C) /* 11 */,
CONST64(0x10B76F18A74DBEFA) /* 12 */, CONST64(0xC6CCB6235AD1AB6A) /* 13 */,
CONST64(0x13726121572FE2FF) /* 14 */, CONST64(0x1A488C6F199D921E) /* 15 */,
CONST64(0x4BC9F9F4DA0007CA) /* 16 */, CONST64(0x26F5E6F6E85241C7) /* 17 */,
CONST64(0x859079DBEA5947B6) /* 18 */, CONST64(0x4F1885C5C99E8C92) /* 19 */,
CONST64(0xD78E761EA96F864B) /* 20 */, CONST64(0x8E36428C52B5C17D) /* 21 */,
CONST64(0x69CF6827373063C1) /* 22 */, CONST64(0xB607C93D9BB4C56E) /* 23 */,
CONST64(0x7D820E760E76B5EA) /* 24 */, CONST64(0x645C9CC6F07FDC42) /* 25 */,
CONST64(0xBF38A078243342E0) /* 26 */, CONST64(0x5F6B343C9D2E7D04) /* 27 */,
CONST64(0xF2C28AEB600B0EC6) /* 28 */, CONST64(0x6C0ED85F7254BCAC) /* 29 */,
CONST64(0x71592281A4DB4FE5) /* 30 */, CONST64(0x1967FA69CE0FED9F) /* 31 */,
CONST64(0xFD5293F8B96545DB) /* 32 */, CONST64(0xC879E9D7F2A7600B) /* 33 */,
CONST64(0x860248920193194E) /* 34 */, CONST64(0xA4F9533B2D9CC0B3) /* 35 */,
CONST64(0x9053836C15957613) /* 36 */, CONST64(0xDB6DCF8AFC357BF1) /* 37 */,
CONST64(0x18BEEA7A7A370F57) /* 38 */, CONST64(0x037117CA50B99066) /* 39 */,
CONST64(0x6AB30A9774424A35) /* 40 */, CONST64(0xF4E92F02E325249B) /* 41 */,
CONST64(0x7739DB07061CCAE1) /* 42 */, CONST64(0xD8F3B49CECA42A05) /* 43 */,
CONST64(0xBD56BE3F51382F73) /* 44 */, CONST64(0x45FAED5843B0BB28) /* 45 */,
CONST64(0x1C813D5C11BF1F83) /* 46 */, CONST64(0x8AF0E4B6D75FA169) /* 47 */,
CONST64(0x33EE18A487AD9999) /* 48 */, CONST64(0x3C26E8EAB1C94410) /* 49 */,
CONST64(0xB510102BC0A822F9) /* 50 */, CONST64(0x141EEF310CE6123B) /* 51 */,
CONST64(0xFC65B90059DDB154) /* 52 */, CONST64(0xE0158640C5E0E607) /* 53 */,
CONST64(0x884E079826C3A3CF) /* 54 */, CONST64(0x930D0D9523C535FD) /* 55 */,
CONST64(0x35638D754E9A2B00) /* 56 */, CONST64(0x4085FCCF40469DD5) /* 57 */,
CONST64(0xC4B17AD28BE23A4C) /* 58 */, CONST64(0xCAB2F0FC6A3E6A2E) /* 59 */,
CONST64(0x2860971A6B943FCD) /* 60 */, CONST64(0x3DDE6EE212E30446) /* 61 */,
CONST64(0x6222F32AE01765AE) /* 62 */, CONST64(0x5D550BB5478308FE) /* 63 */,
CONST64(0xA9EFA98DA0EDA22A) /* 64 */, CONST64(0xC351A71686C40DA7) /* 65 */,
CONST64(0x1105586D9C867C84) /* 66 */, CONST64(0xDCFFEE85FDA22853) /* 67 */,
CONST64(0xCCFBD0262C5EEF76) /* 68 */, CONST64(0xBAF294CB8990D201) /* 69 */,
CONST64(0xE69464F52AFAD975) /* 70 */, CONST64(0x94B013AFDF133E14) /* 71 */,
CONST64(0x06A7D1A32823C958) /* 72 */, CONST64(0x6F95FE5130F61119) /* 73 */,
CONST64(0xD92AB34E462C06C0) /* 74 */, CONST64(0xED7BDE33887C71D2) /* 75 */,
CONST64(0x79746D6E6518393E) /* 76 */, CONST64(0x5BA419385D713329) /* 77 */,
CONST64(0x7C1BA6B948A97564) /* 78 */, CONST64(0x31987C197BFDAC67) /* 79 */,
CONST64(0xDE6C23C44B053D02) /* 80 */, CONST64(0x581C49FED002D64D) /* 81 */,
CONST64(0xDD474D6338261571) /* 82 */, CONST64(0xAA4546C3E473D062) /* 83 */,
CONST64(0x928FCE349455F860) /* 84 */, CONST64(0x48161BBACAAB94D9) /* 85 */,
CONST64(0x63912430770E6F68) /* 86 */, CONST64(0x6EC8A5E602C6641C) /* 87 */,
CONST64(0x87282515337DDD2B) /* 88 */, CONST64(0x2CDA6B42034B701B) /* 89 */,
CONST64(0xB03D37C181CB096D) /* 90 */, CONST64(0xE108438266C71C6F) /* 91 */,
CONST64(0x2B3180C7EB51B255) /* 92 */, CONST64(0xDF92B82F96C08BBC) /* 93 */,
CONST64(0x5C68C8C0A632F3BA) /* 94 */, CONST64(0x5504CC861C3D0556) /* 95 */,
CONST64(0xABBFA4E55FB26B8F) /* 96 */, CONST64(0x41848B0AB3BACEB4) /* 97 */,
CONST64(0xB334A273AA445D32) /* 98 */, CONST64(0xBCA696F0A85AD881) /* 99 */,
CONST64(0x24F6EC65B528D56C) /* 100 */, CONST64(0x0CE1512E90F4524A) /* 101 */,
CONST64(0x4E9DD79D5506D35A) /* 102 */, CONST64(0x258905FAC6CE9779) /* 103 */,
CONST64(0x2019295B3E109B33) /* 104 */, CONST64(0xF8A9478B73A054CC) /* 105 */,
CONST64(0x2924F2F934417EB0) /* 106 */, CONST64(0x3993357D536D1BC4) /* 107 */,
CONST64(0x38A81AC21DB6FF8B) /* 108 */, CONST64(0x47C4FBF17D6016BF) /* 109 */,
CONST64(0x1E0FAADD7667E3F5) /* 110 */, CONST64(0x7ABCFF62938BEB96) /* 111 */,
CONST64(0xA78DAD948FC179C9) /* 112 */, CONST64(0x8F1F98B72911E50D) /* 113 */,
CONST64(0x61E48EAE27121A91) /* 114 */, CONST64(0x4D62F7AD31859808) /* 115 */,
CONST64(0xECEBA345EF5CEAEB) /* 116 */, CONST64(0xF5CEB25EBC9684CE) /* 117 */,
CONST64(0xF633E20CB7F76221) /* 118 */, CONST64(0xA32CDF06AB8293E4) /* 119 */,
CONST64(0x985A202CA5EE2CA4) /* 120 */, CONST64(0xCF0B8447CC8A8FB1) /* 121 */,
CONST64(0x9F765244979859A3) /* 122 */, CONST64(0xA8D516B1A1240017) /* 123 */,
CONST64(0x0BD7BA3EBB5DC726) /* 124 */, CONST64(0xE54BCA55B86ADB39) /* 125 */,
CONST64(0x1D7A3AFD6C478063) /* 126 */, CONST64(0x519EC608E7669EDD) /* 127 */,
CONST64(0x0E5715A2D149AA23) /* 128 */, CONST64(0x177D4571848FF194) /* 129 */,
CONST64(0xEEB55F3241014C22) /* 130 */, CONST64(0x0F5E5CA13A6E2EC2) /* 131 */,
CONST64(0x8029927B75F5C361) /* 132 */, CONST64(0xAD139FABC3D6E436) /* 133 */,
CONST64(0x0D5DF1A94CCF402F) /* 134 */, CONST64(0x3E8BD948BEA5DFC8) /* 135 */,
CONST64(0xA5A0D357BD3FF77E) /* 136 */, CONST64(0xA2D12E251F74F645) /* 137 */,
CONST64(0x66FD9E525E81A082) /* 138 */, CONST64(0x2E0C90CE7F687A49) /* 139 */,
CONST64(0xC2E8BCBEBA973BC5) /* 140 */, CONST64(0x000001BCE509745F) /* 141 */,
CONST64(0x423777BBE6DAB3D6) /* 142 */, CONST64(0xD1661C7EAEF06EB5) /* 143 */,
CONST64(0xA1781F354DAACFD8) /* 144 */, CONST64(0x2D11284A2B16AFFC) /* 145 */,
CONST64(0xF1FC4F67FA891D1F) /* 146 */, CONST64(0x73ECC25DCB920ADA) /* 147 */,
CONST64(0xAE610C22C2A12651) /* 148 */, CONST64(0x96E0A810D356B78A) /* 149 */,
CONST64(0x5A9A381F2FE7870F) /* 150 */, CONST64(0xD5AD62EDE94E5530) /* 151 */,
CONST64(0xD225E5E8368D1427) /* 152 */, CONST64(0x65977B70C7AF4631) /* 153 */,
CONST64(0x99F889B2DE39D74F) /* 154 */, CONST64(0x233F30BF54E1D143) /* 155 */,
CONST64(0x9A9675D3D9A63C97) /* 156 */, CONST64(0x5470554FF334F9A8) /* 157 */,
CONST64(0x166ACB744A4F5688) /* 158 */, CONST64(0x70C74CAAB2E4AEAD) /* 159 */,
CONST64(0xF0D091646F294D12) /* 160 */, CONST64(0x57B82A89684031D1) /* 161 */,
CONST64(0xEFD95A5A61BE0B6B) /* 162 */, CONST64(0x2FBD12E969F2F29A) /* 163 */,
CONST64(0x9BD37013FEFF9FE8) /* 164 */, CONST64(0x3F9B0404D6085A06) /* 165 */,
CONST64(0x4940C1F3166CFE15) /* 166 */, CONST64(0x09542C4DCDF3DEFB) /* 167 */,
CONST64(0xB4C5218385CD5CE3) /* 168 */, CONST64(0xC935B7DC4462A641) /* 169 */,
CONST64(0x3417F8A68ED3B63F) /* 170 */, CONST64(0xB80959295B215B40) /* 171 */,
CONST64(0xF99CDAEF3B8C8572) /* 172 */, CONST64(0x018C0614F8FCB95D) /* 173 */,
CONST64(0x1B14ACCD1A3ACDF3) /* 174 */, CONST64(0x84D471F200BB732D) /* 175 */,
CONST64(0xC1A3110E95E8DA16) /* 176 */, CONST64(0x430A7220BF1A82B8) /* 177 */,
CONST64(0xB77E090D39DF210E) /* 178 */, CONST64(0x5EF4BD9F3CD05E9D) /* 179 */,
CONST64(0x9D4FF6DA7E57A444) /* 180 */, CONST64(0xDA1D60E183D4A5F8) /* 181 */,
CONST64(0xB287C38417998E47) /* 182 */, CONST64(0xFE3EDC121BB31886) /* 183 */,
CONST64(0xC7FE3CCC980CCBEF) /* 184 */, CONST64(0xE46FB590189BFD03) /* 185 */,
CONST64(0x3732FD469A4C57DC) /* 186 */, CONST64(0x7EF700A07CF1AD65) /* 187 */,
CONST64(0x59C64468A31D8859) /* 188 */, CONST64(0x762FB0B4D45B61F6) /* 189 */,
CONST64(0x155BAED099047718) /* 190 */, CONST64(0x68755E4C3D50BAA6) /* 191 */,
CONST64(0xE9214E7F22D8B4DF) /* 192 */, CONST64(0x2ADDBF532EAC95F4) /* 193 */,
CONST64(0x32AE3909B4BD0109) /* 194 */, CONST64(0x834DF537B08E3450) /* 195 */,
CONST64(0xFA209DA84220728D) /* 196 */, CONST64(0x9E691D9B9EFE23F7) /* 197 */,
CONST64(0x0446D288C4AE8D7F) /* 198 */, CONST64(0x7B4CC524E169785B) /* 199 */,
CONST64(0x21D87F0135CA1385) /* 200 */, CONST64(0xCEBB400F137B8AA5) /* 201 */,
CONST64(0x272E2B66580796BE) /* 202 */, CONST64(0x3612264125C2B0DE) /* 203 */,
CONST64(0x057702BDAD1EFBB2) /* 204 */, CONST64(0xD4BABB8EACF84BE9) /* 205 */,
CONST64(0x91583139641BC67B) /* 206 */, CONST64(0x8BDC2DE08036E024) /* 207 */,
CONST64(0x603C8156F49F68ED) /* 208 */, CONST64(0xF7D236F7DBEF5111) /* 209 */,
CONST64(0x9727C4598AD21E80) /* 210 */, CONST64(0xA08A0896670A5FD7) /* 211 */,
CONST64(0xCB4A8F4309EBA9CB) /* 212 */, CONST64(0x81AF564B0F7036A1) /* 213 */,
CONST64(0xC0B99AA778199ABD) /* 214 */, CONST64(0x959F1EC83FC8E952) /* 215 */,
CONST64(0x8C505077794A81B9) /* 216 */, CONST64(0x3ACAAF8F056338F0) /* 217 */,
CONST64(0x07B43F50627A6778) /* 218 */, CONST64(0x4A44AB49F5ECCC77) /* 219 */,
CONST64(0x3BC3D6E4B679EE98) /* 220 */, CONST64(0x9CC0D4D1CF14108C) /* 221 */,
CONST64(0x4406C00B206BC8A0) /* 222 */, CONST64(0x82A18854C8D72D89) /* 223 */,
CONST64(0x67E366B35C3C432C) /* 224 */, CONST64(0xB923DD61102B37F2) /* 225 */,
CONST64(0x56AB2779D884271D) /* 226 */, CONST64(0xBE83E1B0FF1525AF) /* 227 */,
CONST64(0xFB7C65D4217E49A9) /* 228 */, CONST64(0x6BDBE0E76D48E7D4) /* 229 */,
CONST64(0x08DF828745D9179E) /* 230 */, CONST64(0x22EA6A9ADD53BD34) /* 231 */,
CONST64(0xE36E141C5622200A) /* 232 */, CONST64(0x7F805D1B8CB750EE) /* 233 */,
CONST64(0xAFE5C7A59F58E837) /* 234 */, CONST64(0xE27F996A4FB1C23C) /* 235 */,
CONST64(0xD3867DFB0775F0D0) /* 236 */, CONST64(0xD0E673DE6E88891A) /* 237 */,
CONST64(0x123AEB9EAFB86C25) /* 238 */, CONST64(0x30F1D5D5C145B895) /* 239 */,
CONST64(0xBB434A2DEE7269E7) /* 240 */, CONST64(0x78CB67ECF931FA38) /* 241 */,
CONST64(0xF33B0372323BBF9C) /* 242 */, CONST64(0x52D66336FB279C74) /* 243 */,
CONST64(0x505F33AC0AFB4EAA) /* 244 */, CONST64(0xE8A5CD99A2CCE187) /* 245 */,
CONST64(0x534974801E2D30BB) /* 246 */, CONST64(0x8D2D5711D5876D90) /* 247 */,
CONST64(0x1F1A412891BC038E) /* 248 */, CONST64(0xD6E2E71D82E56648) /* 249 */,
CONST64(0x74036C3A497732B7) /* 250 */, CONST64(0x89B67ED96361F5AB) /* 251 */,
CONST64(0xFFED95D8F1EA02A2) /* 252 */, CONST64(0xE72B3BD61464D43D) /* 253 */,
CONST64(0xA6300F170BDC4820) /* 254 */, CONST64(0xEBC18760ED78A77A) /* 255 */,
CONST64(0xE6A6BE5A05A12138) /* 256 */, CONST64(0xB5A122A5B4F87C98) /* 257 */,
CONST64(0x563C6089140B6990) /* 258 */, CONST64(0x4C46CB2E391F5DD5) /* 259 */,
CONST64(0xD932ADDBC9B79434) /* 260 */, CONST64(0x08EA70E42015AFF5) /* 261 */,
CONST64(0xD765A6673E478CF1) /* 262 */, CONST64(0xC4FB757EAB278D99) /* 263 */,
CONST64(0xDF11C6862D6E0692) /* 264 */, CONST64(0xDDEB84F10D7F3B16) /* 265 */,
CONST64(0x6F2EF604A665EA04) /* 266 */, CONST64(0x4A8E0F0FF0E0DFB3) /* 267 */,
CONST64(0xA5EDEEF83DBCBA51) /* 268 */, CONST64(0xFC4F0A2A0EA4371E) /* 269 */,
CONST64(0xE83E1DA85CB38429) /* 270 */, CONST64(0xDC8FF882BA1B1CE2) /* 271 */,
CONST64(0xCD45505E8353E80D) /* 272 */, CONST64(0x18D19A00D4DB0717) /* 273 */,
CONST64(0x34A0CFEDA5F38101) /* 274 */, CONST64(0x0BE77E518887CAF2) /* 275 */,
CONST64(0x1E341438B3C45136) /* 276 */, CONST64(0xE05797F49089CCF9) /* 277 */,
CONST64(0xFFD23F9DF2591D14) /* 278 */, CONST64(0x543DDA228595C5CD) /* 279 */,
CONST64(0x661F81FD99052A33) /* 280 */, CONST64(0x8736E641DB0F7B76) /* 281 */,
CONST64(0x15227725418E5307) /* 282 */, CONST64(0xE25F7F46162EB2FA) /* 283 */,
CONST64(0x48A8B2126C13D9FE) /* 284 */, CONST64(0xAFDC541792E76EEA) /* 285 */,
CONST64(0x03D912BFC6D1898F) /* 286 */, CONST64(0x31B1AAFA1B83F51B) /* 287 */,
CONST64(0xF1AC2796E42AB7D9) /* 288 */, CONST64(0x40A3A7D7FCD2EBAC) /* 289 */,
CONST64(0x1056136D0AFBBCC5) /* 290 */, CONST64(0x7889E1DD9A6D0C85) /* 291 */,
CONST64(0xD33525782A7974AA) /* 292 */, CONST64(0xA7E25D09078AC09B) /* 293 */,
CONST64(0xBD4138B3EAC6EDD0) /* 294 */, CONST64(0x920ABFBE71EB9E70) /* 295 */,
CONST64(0xA2A5D0F54FC2625C) /* 296 */, CONST64(0xC054E36B0B1290A3) /* 297 */,
CONST64(0xF6DD59FF62FE932B) /* 298 */, CONST64(0x3537354511A8AC7D) /* 299 */,
CONST64(0xCA845E9172FADCD4) /* 300 */, CONST64(0x84F82B60329D20DC) /* 301 */,
CONST64(0x79C62CE1CD672F18) /* 302 */, CONST64(0x8B09A2ADD124642C) /* 303 */,
CONST64(0xD0C1E96A19D9E726) /* 304 */, CONST64(0x5A786A9B4BA9500C) /* 305 */,
CONST64(0x0E020336634C43F3) /* 306 */, CONST64(0xC17B474AEB66D822) /* 307 */,
CONST64(0x6A731AE3EC9BAAC2) /* 308 */, CONST64(0x8226667AE0840258) /* 309 */,
CONST64(0x67D4567691CAECA5) /* 310 */, CONST64(0x1D94155C4875ADB5) /* 311 */,
CONST64(0x6D00FD985B813FDF) /* 312 */, CONST64(0x51286EFCB774CD06) /* 313 */,
CONST64(0x5E8834471FA744AF) /* 314 */, CONST64(0xF72CA0AEE761AE2E) /* 315 */,
CONST64(0xBE40E4CDAEE8E09A) /* 316 */, CONST64(0xE9970BBB5118F665) /* 317 */,
CONST64(0x726E4BEB33DF1964) /* 318 */, CONST64(0x703B000729199762) /* 319 */,
CONST64(0x4631D816F5EF30A7) /* 320 */, CONST64(0xB880B5B51504A6BE) /* 321 */,
CONST64(0x641793C37ED84B6C) /* 322 */, CONST64(0x7B21ED77F6E97D96) /* 323 */,
CONST64(0x776306312EF96B73) /* 324 */, CONST64(0xAE528948E86FF3F4) /* 325 */,
CONST64(0x53DBD7F286A3F8F8) /* 326 */, CONST64(0x16CADCE74CFC1063) /* 327 */,
CONST64(0x005C19BDFA52C6DD) /* 328 */, CONST64(0x68868F5D64D46AD3) /* 329 */,
CONST64(0x3A9D512CCF1E186A) /* 330 */, CONST64(0x367E62C2385660AE) /* 331 */,
CONST64(0xE359E7EA77DCB1D7) /* 332 */, CONST64(0x526C0773749ABE6E) /* 333 */,
CONST64(0x735AE5F9D09F734B) /* 334 */, CONST64(0x493FC7CC8A558BA8) /* 335 */,
CONST64(0xB0B9C1533041AB45) /* 336 */, CONST64(0x321958BA470A59BD) /* 337 */,
CONST64(0x852DB00B5F46C393) /* 338 */, CONST64(0x91209B2BD336B0E5) /* 339 */,
CONST64(0x6E604F7D659EF19F) /* 340 */, CONST64(0xB99A8AE2782CCB24) /* 341 */,
CONST64(0xCCF52AB6C814C4C7) /* 342 */, CONST64(0x4727D9AFBE11727B) /* 343 */,
CONST64(0x7E950D0C0121B34D) /* 344 */, CONST64(0x756F435670AD471F) /* 345 */,
CONST64(0xF5ADD442615A6849) /* 346 */, CONST64(0x4E87E09980B9957A) /* 347 */,
CONST64(0x2ACFA1DF50AEE355) /* 348 */, CONST64(0xD898263AFD2FD556) /* 349 */,
CONST64(0xC8F4924DD80C8FD6) /* 350 */, CONST64(0xCF99CA3D754A173A) /* 351 */,
CONST64(0xFE477BACAF91BF3C) /* 352 */, CONST64(0xED5371F6D690C12D) /* 353 */,
CONST64(0x831A5C285E687094) /* 354 */, CONST64(0xC5D3C90A3708A0A4) /* 355 */,
CONST64(0x0F7F903717D06580) /* 356 */, CONST64(0x19F9BB13B8FDF27F) /* 357 */,
CONST64(0xB1BD6F1B4D502843) /* 358 */, CONST64(0x1C761BA38FFF4012) /* 359 */,
CONST64(0x0D1530C4E2E21F3B) /* 360 */, CONST64(0x8943CE69A7372C8A) /* 361 */,
CONST64(0xE5184E11FEB5CE66) /* 362 */, CONST64(0x618BDB80BD736621) /* 363 */,
CONST64(0x7D29BAD68B574D0B) /* 364 */, CONST64(0x81BB613E25E6FE5B) /* 365 */,
CONST64(0x071C9C10BC07913F) /* 366 */, CONST64(0xC7BEEB7909AC2D97) /* 367 */,
CONST64(0xC3E58D353BC5D757) /* 368 */, CONST64(0xEB017892F38F61E8) /* 369 */,
CONST64(0xD4EFFB9C9B1CC21A) /* 370 */, CONST64(0x99727D26F494F7AB) /* 371 */,
CONST64(0xA3E063A2956B3E03) /* 372 */, CONST64(0x9D4A8B9A4AA09C30) /* 373 */,
CONST64(0x3F6AB7D500090FB4) /* 374 */, CONST64(0x9CC0F2A057268AC0) /* 375 */,
CONST64(0x3DEE9D2DEDBF42D1) /* 376 */, CONST64(0x330F49C87960A972) /* 377 */,
CONST64(0xC6B2720287421B41) /* 378 */, CONST64(0x0AC59EC07C00369C) /* 379 */,
CONST64(0xEF4EAC49CB353425) /* 380 */, CONST64(0xF450244EEF0129D8) /* 381 */,
CONST64(0x8ACC46E5CAF4DEB6) /* 382 */, CONST64(0x2FFEAB63989263F7) /* 383 */,
CONST64(0x8F7CB9FE5D7A4578) /* 384 */, CONST64(0x5BD8F7644E634635) /* 385 */,
CONST64(0x427A7315BF2DC900) /* 386 */, CONST64(0x17D0C4AA2125261C) /* 387 */,
CONST64(0x3992486C93518E50) /* 388 */, CONST64(0xB4CBFEE0A2D7D4C3) /* 389 */,
CONST64(0x7C75D6202C5DDD8D) /* 390 */, CONST64(0xDBC295D8E35B6C61) /* 391 */,
CONST64(0x60B369D302032B19) /* 392 */, CONST64(0xCE42685FDCE44132) /* 393 */,
CONST64(0x06F3DDB9DDF65610) /* 394 */, CONST64(0x8EA4D21DB5E148F0) /* 395 */,
CONST64(0x20B0FCE62FCD496F) /* 396 */, CONST64(0x2C1B912358B0EE31) /* 397 */,
CONST64(0xB28317B818F5A308) /* 398 */, CONST64(0xA89C1E189CA6D2CF) /* 399 */,
CONST64(0x0C6B18576AAADBC8) /* 400 */, CONST64(0xB65DEAA91299FAE3) /* 401 */,
CONST64(0xFB2B794B7F1027E7) /* 402 */, CONST64(0x04E4317F443B5BEB) /* 403 */,
CONST64(0x4B852D325939D0A6) /* 404 */, CONST64(0xD5AE6BEEFB207FFC) /* 405 */,
CONST64(0x309682B281C7D374) /* 406 */, CONST64(0xBAE309A194C3B475) /* 407 */,
CONST64(0x8CC3F97B13B49F05) /* 408 */, CONST64(0x98A9422FF8293967) /* 409 */,
CONST64(0x244B16B01076FF7C) /* 410 */, CONST64(0xF8BF571C663D67EE) /* 411 */,
CONST64(0x1F0D6758EEE30DA1) /* 412 */, CONST64(0xC9B611D97ADEB9B7) /* 413 */,
CONST64(0xB7AFD5887B6C57A2) /* 414 */, CONST64(0x6290AE846B984FE1) /* 415 */,
CONST64(0x94DF4CDEACC1A5FD) /* 416 */, CONST64(0x058A5BD1C5483AFF) /* 417 */,
CONST64(0x63166CC142BA3C37) /* 418 */, CONST64(0x8DB8526EB2F76F40) /* 419 */,
CONST64(0xE10880036F0D6D4E) /* 420 */, CONST64(0x9E0523C9971D311D) /* 421 */,
CONST64(0x45EC2824CC7CD691) /* 422 */, CONST64(0x575B8359E62382C9) /* 423 */,
CONST64(0xFA9E400DC4889995) /* 424 */, CONST64(0xD1823ECB45721568) /* 425 */,
CONST64(0xDAFD983B8206082F) /* 426 */, CONST64(0xAA7D29082386A8CB) /* 427 */,
CONST64(0x269FCD4403B87588) /* 428 */, CONST64(0x1B91F5F728BDD1E0) /* 429 */,
CONST64(0xE4669F39040201F6) /* 430 */, CONST64(0x7A1D7C218CF04ADE) /* 431 */,
CONST64(0x65623C29D79CE5CE) /* 432 */, CONST64(0x2368449096C00BB1) /* 433 */,
CONST64(0xAB9BF1879DA503BA) /* 434 */, CONST64(0xBC23ECB1A458058E) /* 435 */,
CONST64(0x9A58DF01BB401ECC) /* 436 */, CONST64(0xA070E868A85F143D) /* 437 */,
CONST64(0x4FF188307DF2239E) /* 438 */, CONST64(0x14D565B41A641183) /* 439 */,
CONST64(0xEE13337452701602) /* 440 */, CONST64(0x950E3DCF3F285E09) /* 441 */,
CONST64(0x59930254B9C80953) /* 442 */, CONST64(0x3BF299408930DA6D) /* 443 */,
CONST64(0xA955943F53691387) /* 444 */, CONST64(0xA15EDECAA9CB8784) /* 445 */,
CONST64(0x29142127352BE9A0) /* 446 */, CONST64(0x76F0371FFF4E7AFB) /* 447 */,
CONST64(0x0239F450274F2228) /* 448 */, CONST64(0xBB073AF01D5E868B) /* 449 */,
CONST64(0xBFC80571C10E96C1) /* 450 */, CONST64(0xD267088568222E23) /* 451 */,
CONST64(0x9671A3D48E80B5B0) /* 452 */, CONST64(0x55B5D38AE193BB81) /* 453 */,
CONST64(0x693AE2D0A18B04B8) /* 454 */, CONST64(0x5C48B4ECADD5335F) /* 455 */,
CONST64(0xFD743B194916A1CA) /* 456 */, CONST64(0x2577018134BE98C4) /* 457 */,
CONST64(0xE77987E83C54A4AD) /* 458 */, CONST64(0x28E11014DA33E1B9) /* 459 */,
CONST64(0x270CC59E226AA213) /* 460 */, CONST64(0x71495F756D1A5F60) /* 461 */,
CONST64(0x9BE853FB60AFEF77) /* 462 */, CONST64(0xADC786A7F7443DBF) /* 463 */,
CONST64(0x0904456173B29A82) /* 464 */, CONST64(0x58BC7A66C232BD5E) /* 465 */,
CONST64(0xF306558C673AC8B2) /* 466 */, CONST64(0x41F639C6B6C9772A) /* 467 */,
CONST64(0x216DEFE99FDA35DA) /* 468 */, CONST64(0x11640CC71C7BE615) /* 469 */,
CONST64(0x93C43694565C5527) /* 470 */, CONST64(0xEA038E6246777839) /* 471 */,
CONST64(0xF9ABF3CE5A3E2469) /* 472 */, CONST64(0x741E768D0FD312D2) /* 473 */,
CONST64(0x0144B883CED652C6) /* 474 */, CONST64(0xC20B5A5BA33F8552) /* 475 */,
CONST64(0x1AE69633C3435A9D) /* 476 */, CONST64(0x97A28CA4088CFDEC) /* 477 */,
CONST64(0x8824A43C1E96F420) /* 478 */, CONST64(0x37612FA66EEEA746) /* 479 */,
CONST64(0x6B4CB165F9CF0E5A) /* 480 */, CONST64(0x43AA1C06A0ABFB4A) /* 481 */,
CONST64(0x7F4DC26FF162796B) /* 482 */, CONST64(0x6CBACC8E54ED9B0F) /* 483 */,
CONST64(0xA6B7FFEFD2BB253E) /* 484 */, CONST64(0x2E25BC95B0A29D4F) /* 485 */,
CONST64(0x86D6A58BDEF1388C) /* 486 */, CONST64(0xDED74AC576B6F054) /* 487 */,
CONST64(0x8030BDBC2B45805D) /* 488 */, CONST64(0x3C81AF70E94D9289) /* 489 */,
CONST64(0x3EFF6DDA9E3100DB) /* 490 */, CONST64(0xB38DC39FDFCC8847) /* 491 */,
CONST64(0x123885528D17B87E) /* 492 */, CONST64(0xF2DA0ED240B1B642) /* 493 */,
CONST64(0x44CEFADCD54BF9A9) /* 494 */, CONST64(0x1312200E433C7EE6) /* 495 */,
CONST64(0x9FFCC84F3A78C748) /* 496 */, CONST64(0xF0CD1F72248576BB) /* 497 */,
CONST64(0xEC6974053638CFE4) /* 498 */, CONST64(0x2BA7B67C0CEC4E4C) /* 499 */,
CONST64(0xAC2F4DF3E5CE32ED) /* 500 */, CONST64(0xCB33D14326EA4C11) /* 501 */,
CONST64(0xA4E9044CC77E58BC) /* 502 */, CONST64(0x5F513293D934FCEF) /* 503 */,
CONST64(0x5DC9645506E55444) /* 504 */, CONST64(0x50DE418F317DE40A) /* 505 */,
CONST64(0x388CB31A69DDE259) /* 506 */, CONST64(0x2DB4A83455820A86) /* 507 */,
CONST64(0x9010A91E84711AE9) /* 508 */, CONST64(0x4DF7F0B7B1498371) /* 509 */,
CONST64(0xD62A2EABC0977179) /* 510 */, CONST64(0x22FAC097AA8D5C0E) /* 511 */,
CONST64(0xF49FCC2FF1DAF39B) /* 512 */, CONST64(0x487FD5C66FF29281) /* 513 */,
CONST64(0xE8A30667FCDCA83F) /* 514 */, CONST64(0x2C9B4BE3D2FCCE63) /* 515 */,
CONST64(0xDA3FF74B93FBBBC2) /* 516 */, CONST64(0x2FA165D2FE70BA66) /* 517 */,
CONST64(0xA103E279970E93D4) /* 518 */, CONST64(0xBECDEC77B0E45E71) /* 519 */,
CONST64(0xCFB41E723985E497) /* 520 */, CONST64(0xB70AAA025EF75017) /* 521 */,
CONST64(0xD42309F03840B8E0) /* 522 */, CONST64(0x8EFC1AD035898579) /* 523 */,
CONST64(0x96C6920BE2B2ABC5) /* 524 */, CONST64(0x66AF4163375A9172) /* 525 */,
CONST64(0x2174ABDCCA7127FB) /* 526 */, CONST64(0xB33CCEA64A72FF41) /* 527 */,
CONST64(0xF04A4933083066A5) /* 528 */, CONST64(0x8D970ACDD7289AF5) /* 529 */,
CONST64(0x8F96E8E031C8C25E) /* 530 */, CONST64(0xF3FEC02276875D47) /* 531 */,
CONST64(0xEC7BF310056190DD) /* 532 */, CONST64(0xF5ADB0AEBB0F1491) /* 533 */,
CONST64(0x9B50F8850FD58892) /* 534 */, CONST64(0x4975488358B74DE8) /* 535 */,
CONST64(0xA3354FF691531C61) /* 536 */, CONST64(0x0702BBE481D2C6EE) /* 537 */,
CONST64(0x89FB24057DEDED98) /* 538 */, CONST64(0xAC3075138596E902) /* 539 */,
CONST64(0x1D2D3580172772ED) /* 540 */, CONST64(0xEB738FC28E6BC30D) /* 541 */,
CONST64(0x5854EF8F63044326) /* 542 */, CONST64(0x9E5C52325ADD3BBE) /* 543 */,
CONST64(0x90AA53CF325C4623) /* 544 */, CONST64(0xC1D24D51349DD067) /* 545 */,
CONST64(0x2051CFEEA69EA624) /* 546 */, CONST64(0x13220F0A862E7E4F) /* 547 */,
CONST64(0xCE39399404E04864) /* 548 */, CONST64(0xD9C42CA47086FCB7) /* 549 */,
CONST64(0x685AD2238A03E7CC) /* 550 */, CONST64(0x066484B2AB2FF1DB) /* 551 */,
CONST64(0xFE9D5D70EFBF79EC) /* 552 */, CONST64(0x5B13B9DD9C481854) /* 553 */,
CONST64(0x15F0D475ED1509AD) /* 554 */, CONST64(0x0BEBCD060EC79851) /* 555 */,
CONST64(0xD58C6791183AB7F8) /* 556 */, CONST64(0xD1187C5052F3EEE4) /* 557 */,
CONST64(0xC95D1192E54E82FF) /* 558 */, CONST64(0x86EEA14CB9AC6CA2) /* 559 */,
CONST64(0x3485BEB153677D5D) /* 560 */, CONST64(0xDD191D781F8C492A) /* 561 */,
CONST64(0xF60866BAA784EBF9) /* 562 */, CONST64(0x518F643BA2D08C74) /* 563 */,
CONST64(0x8852E956E1087C22) /* 564 */, CONST64(0xA768CB8DC410AE8D) /* 565 */,
CONST64(0x38047726BFEC8E1A) /* 566 */, CONST64(0xA67738B4CD3B45AA) /* 567 */,
CONST64(0xAD16691CEC0DDE19) /* 568 */, CONST64(0xC6D4319380462E07) /* 569 */,
CONST64(0xC5A5876D0BA61938) /* 570 */, CONST64(0x16B9FA1FA58FD840) /* 571 */,
CONST64(0x188AB1173CA74F18) /* 572 */, CONST64(0xABDA2F98C99C021F) /* 573 */,
CONST64(0x3E0580AB134AE816) /* 574 */, CONST64(0x5F3B05B773645ABB) /* 575 */,
CONST64(0x2501A2BE5575F2F6) /* 576 */, CONST64(0x1B2F74004E7E8BA9) /* 577 */,
CONST64(0x1CD7580371E8D953) /* 578 */, CONST64(0x7F6ED89562764E30) /* 579 */,
CONST64(0xB15926FF596F003D) /* 580 */, CONST64(0x9F65293DA8C5D6B9) /* 581 */,
CONST64(0x6ECEF04DD690F84C) /* 582 */, CONST64(0x4782275FFF33AF88) /* 583 */,
CONST64(0xE41433083F820801) /* 584 */, CONST64(0xFD0DFE409A1AF9B5) /* 585 */,
CONST64(0x4325A3342CDB396B) /* 586 */, CONST64(0x8AE77E62B301B252) /* 587 */,
CONST64(0xC36F9E9F6655615A) /* 588 */, CONST64(0x85455A2D92D32C09) /* 589 */,
CONST64(0xF2C7DEA949477485) /* 590 */, CONST64(0x63CFB4C133A39EBA) /* 591 */,
CONST64(0x83B040CC6EBC5462) /* 592 */, CONST64(0x3B9454C8FDB326B0) /* 593 */,
CONST64(0x56F56A9E87FFD78C) /* 594 */, CONST64(0x2DC2940D99F42BC6) /* 595 */,
CONST64(0x98F7DF096B096E2D) /* 596 */, CONST64(0x19A6E01E3AD852BF) /* 597 */,
CONST64(0x42A99CCBDBD4B40B) /* 598 */, CONST64(0xA59998AF45E9C559) /* 599 */,
CONST64(0x366295E807D93186) /* 600 */, CONST64(0x6B48181BFAA1F773) /* 601 */,
CONST64(0x1FEC57E2157A0A1D) /* 602 */, CONST64(0x4667446AF6201AD5) /* 603 */,
CONST64(0xE615EBCACFB0F075) /* 604 */, CONST64(0xB8F31F4F68290778) /* 605 */,
CONST64(0x22713ED6CE22D11E) /* 606 */, CONST64(0x3057C1A72EC3C93B) /* 607 */,
CONST64(0xCB46ACC37C3F1F2F) /* 608 */, CONST64(0xDBB893FD02AAF50E) /* 609 */,
CONST64(0x331FD92E600B9FCF) /* 610 */, CONST64(0xA498F96148EA3AD6) /* 611 */,
CONST64(0xA8D8426E8B6A83EA) /* 612 */, CONST64(0xA089B274B7735CDC) /* 613 */,
CONST64(0x87F6B3731E524A11) /* 614 */, CONST64(0x118808E5CBC96749) /* 615 */,
CONST64(0x9906E4C7B19BD394) /* 616 */, CONST64(0xAFED7F7E9B24A20C) /* 617 */,
CONST64(0x6509EADEEB3644A7) /* 618 */, CONST64(0x6C1EF1D3E8EF0EDE) /* 619 */,
CONST64(0xB9C97D43E9798FB4) /* 620 */, CONST64(0xA2F2D784740C28A3) /* 621 */,
CONST64(0x7B8496476197566F) /* 622 */, CONST64(0x7A5BE3E6B65F069D) /* 623 */,
CONST64(0xF96330ED78BE6F10) /* 624 */, CONST64(0xEEE60DE77A076A15) /* 625 */,
CONST64(0x2B4BEE4AA08B9BD0) /* 626 */, CONST64(0x6A56A63EC7B8894E) /* 627 */,
CONST64(0x02121359BA34FEF4) /* 628 */, CONST64(0x4CBF99F8283703FC) /* 629 */,
CONST64(0x398071350CAF30C8) /* 630 */, CONST64(0xD0A77A89F017687A) /* 631 */,
CONST64(0xF1C1A9EB9E423569) /* 632 */, CONST64(0x8C7976282DEE8199) /* 633 */,
CONST64(0x5D1737A5DD1F7ABD) /* 634 */, CONST64(0x4F53433C09A9FA80) /* 635 */,
CONST64(0xFA8B0C53DF7CA1D9) /* 636 */, CONST64(0x3FD9DCBC886CCB77) /* 637 */,
CONST64(0xC040917CA91B4720) /* 638 */, CONST64(0x7DD00142F9D1DCDF) /* 639 */,
CONST64(0x8476FC1D4F387B58) /* 640 */, CONST64(0x23F8E7C5F3316503) /* 641 */,
CONST64(0x032A2244E7E37339) /* 642 */, CONST64(0x5C87A5D750F5A74B) /* 643 */,
CONST64(0x082B4CC43698992E) /* 644 */, CONST64(0xDF917BECB858F63C) /* 645 */,
CONST64(0x3270B8FC5BF86DDA) /* 646 */, CONST64(0x10AE72BB29B5DD76) /* 647 */,
CONST64(0x576AC94E7700362B) /* 648 */, CONST64(0x1AD112DAC61EFB8F) /* 649 */,
CONST64(0x691BC30EC5FAA427) /* 650 */, CONST64(0xFF246311CC327143) /* 651 */,
CONST64(0x3142368E30E53206) /* 652 */, CONST64(0x71380E31E02CA396) /* 653 */,
CONST64(0x958D5C960AAD76F1) /* 654 */, CONST64(0xF8D6F430C16DA536) /* 655 */,
CONST64(0xC8FFD13F1BE7E1D2) /* 656 */, CONST64(0x7578AE66004DDBE1) /* 657 */,
CONST64(0x05833F01067BE646) /* 658 */, CONST64(0xBB34B5AD3BFE586D) /* 659 */,
CONST64(0x095F34C9A12B97F0) /* 660 */, CONST64(0x247AB64525D60CA8) /* 661 */,
CONST64(0xDCDBC6F3017477D1) /* 662 */, CONST64(0x4A2E14D4DECAD24D) /* 663 */,
CONST64(0xBDB5E6D9BE0A1EEB) /* 664 */, CONST64(0x2A7E70F7794301AB) /* 665 */,
CONST64(0xDEF42D8A270540FD) /* 666 */, CONST64(0x01078EC0A34C22C1) /* 667 */,
CONST64(0xE5DE511AF4C16387) /* 668 */, CONST64(0x7EBB3A52BD9A330A) /* 669 */,
CONST64(0x77697857AA7D6435) /* 670 */, CONST64(0x004E831603AE4C32) /* 671 */,
CONST64(0xE7A21020AD78E312) /* 672 */, CONST64(0x9D41A70C6AB420F2) /* 673 */,
CONST64(0x28E06C18EA1141E6) /* 674 */, CONST64(0xD2B28CBD984F6B28) /* 675 */,
CONST64(0x26B75F6C446E9D83) /* 676 */, CONST64(0xBA47568C4D418D7F) /* 677 */,
CONST64(0xD80BADBFE6183D8E) /* 678 */, CONST64(0x0E206D7F5F166044) /* 679 */,
CONST64(0xE258A43911CBCA3E) /* 680 */, CONST64(0x723A1746B21DC0BC) /* 681 */,
CONST64(0xC7CAA854F5D7CDD3) /* 682 */, CONST64(0x7CAC32883D261D9C) /* 683 */,
CONST64(0x7690C26423BA942C) /* 684 */, CONST64(0x17E55524478042B8) /* 685 */,
CONST64(0xE0BE477656A2389F) /* 686 */, CONST64(0x4D289B5E67AB2DA0) /* 687 */,
CONST64(0x44862B9C8FBBFD31) /* 688 */, CONST64(0xB47CC8049D141365) /* 689 */,
CONST64(0x822C1B362B91C793) /* 690 */, CONST64(0x4EB14655FB13DFD8) /* 691 */,
CONST64(0x1ECBBA0714E2A97B) /* 692 */, CONST64(0x6143459D5CDE5F14) /* 693 */,
CONST64(0x53A8FBF1D5F0AC89) /* 694 */, CONST64(0x97EA04D81C5E5B00) /* 695 */,
CONST64(0x622181A8D4FDB3F3) /* 696 */, CONST64(0xE9BCD341572A1208) /* 697 */,
CONST64(0x1411258643CCE58A) /* 698 */, CONST64(0x9144C5FEA4C6E0A4) /* 699 */,
CONST64(0x0D33D06565CF620F) /* 700 */, CONST64(0x54A48D489F219CA1) /* 701 */,
CONST64(0xC43E5EAC6D63C821) /* 702 */, CONST64(0xA9728B3A72770DAF) /* 703 */,
CONST64(0xD7934E7B20DF87EF) /* 704 */, CONST64(0xE35503B61A3E86E5) /* 705 */,
CONST64(0xCAE321FBC819D504) /* 706 */, CONST64(0x129A50B3AC60BFA6) /* 707 */,
CONST64(0xCD5E68EA7E9FB6C3) /* 708 */, CONST64(0xB01C90199483B1C7) /* 709 */,
CONST64(0x3DE93CD5C295376C) /* 710 */, CONST64(0xAED52EDF2AB9AD13) /* 711 */,
CONST64(0x2E60F512C0A07884) /* 712 */, CONST64(0xBC3D86A3E36210C9) /* 713 */,
CONST64(0x35269D9B163951CE) /* 714 */, CONST64(0x0C7D6E2AD0CDB5FA) /* 715 */,
CONST64(0x59E86297D87F5733) /* 716 */, CONST64(0x298EF221898DB0E7) /* 717 */,
CONST64(0x55000029D1A5AA7E) /* 718 */, CONST64(0x8BC08AE1B5061B45) /* 719 */,
CONST64(0xC2C31C2B6C92703A) /* 720 */, CONST64(0x94CC596BAF25EF42) /* 721 */,
CONST64(0x0A1D73DB22540456) /* 722 */, CONST64(0x04B6A0F9D9C4179A) /* 723 */,
CONST64(0xEFFDAFA2AE3D3C60) /* 724 */, CONST64(0xF7C8075BB49496C4) /* 725 */,
CONST64(0x9CC5C7141D1CD4E3) /* 726 */, CONST64(0x78BD1638218E5534) /* 727 */,
CONST64(0xB2F11568F850246A) /* 728 */, CONST64(0xEDFABCFA9502BC29) /* 729 */,
CONST64(0x796CE5F2DA23051B) /* 730 */, CONST64(0xAAE128B0DC93537C) /* 731 */,
CONST64(0x3A493DA0EE4B29AE) /* 732 */, CONST64(0xB5DF6B2C416895D7) /* 733 */,
CONST64(0xFCABBD25122D7F37) /* 734 */, CONST64(0x70810B58105DC4B1) /* 735 */,
CONST64(0xE10FDD37F7882A90) /* 736 */, CONST64(0x524DCAB5518A3F5C) /* 737 */,
CONST64(0x3C9E85878451255B) /* 738 */, CONST64(0x4029828119BD34E2) /* 739 */,
CONST64(0x74A05B6F5D3CECCB) /* 740 */, CONST64(0xB610021542E13ECA) /* 741 */,
CONST64(0x0FF979D12F59E2AC) /* 742 */, CONST64(0x6037DA27E4F9CC50) /* 743 */,
CONST64(0x5E92975A0DF1847D) /* 744 */, CONST64(0xD66DE190D3E623FE) /* 745 */,
CONST64(0x5032D6B87B568048) /* 746 */, CONST64(0x9A36B7CE8235216E) /* 747 */,
CONST64(0x80272A7A24F64B4A) /* 748 */, CONST64(0x93EFED8B8C6916F7) /* 749 */,
CONST64(0x37DDBFF44CCE1555) /* 750 */, CONST64(0x4B95DB5D4B99BD25) /* 751 */,
CONST64(0x92D3FDA169812FC0) /* 752 */, CONST64(0xFB1A4A9A90660BB6) /* 753 */,
CONST64(0x730C196946A4B9B2) /* 754 */, CONST64(0x81E289AA7F49DA68) /* 755 */,
CONST64(0x64669A0F83B1A05F) /* 756 */, CONST64(0x27B3FF7D9644F48B) /* 757 */,
CONST64(0xCC6B615C8DB675B3) /* 758 */, CONST64(0x674F20B9BCEBBE95) /* 759 */,
CONST64(0x6F31238275655982) /* 760 */, CONST64(0x5AE488713E45CF05) /* 761 */,
CONST64(0xBF619F9954C21157) /* 762 */, CONST64(0xEABAC46040A8EAE9) /* 763 */,
CONST64(0x454C6FE9F2C0C1CD) /* 764 */, CONST64(0x419CF6496412691C) /* 765 */,
CONST64(0xD3DC3BEF265B0F70) /* 766 */, CONST64(0x6D0E60F5C3578A9E) /* 767 */,
CONST64(0x5B0E608526323C55) /* 768 */, CONST64(0x1A46C1A9FA1B59F5) /* 769 */,
CONST64(0xA9E245A17C4C8FFA) /* 770 */, CONST64(0x65CA5159DB2955D7) /* 771 */,
CONST64(0x05DB0A76CE35AFC2) /* 772 */, CONST64(0x81EAC77EA9113D45) /* 773 */,
CONST64(0x528EF88AB6AC0A0D) /* 774 */, CONST64(0xA09EA253597BE3FF) /* 775 */,
CONST64(0x430DDFB3AC48CD56) /* 776 */, CONST64(0xC4B3A67AF45CE46F) /* 777 */,
CONST64(0x4ECECFD8FBE2D05E) /* 778 */, CONST64(0x3EF56F10B39935F0) /* 779 */,
CONST64(0x0B22D6829CD619C6) /* 780 */, CONST64(0x17FD460A74DF2069) /* 781 */,
CONST64(0x6CF8CC8E8510ED40) /* 782 */, CONST64(0xD6C824BF3A6ECAA7) /* 783 */,
CONST64(0x61243D581A817049) /* 784 */, CONST64(0x048BACB6BBC163A2) /* 785 */,
CONST64(0xD9A38AC27D44CC32) /* 786 */, CONST64(0x7FDDFF5BAAF410AB) /* 787 */,
CONST64(0xAD6D495AA804824B) /* 788 */, CONST64(0xE1A6A74F2D8C9F94) /* 789 */,
CONST64(0xD4F7851235DEE8E3) /* 790 */, CONST64(0xFD4B7F886540D893) /* 791 */,
CONST64(0x247C20042AA4BFDA) /* 792 */, CONST64(0x096EA1C517D1327C) /* 793 */,
CONST64(0xD56966B4361A6685) /* 794 */, CONST64(0x277DA5C31221057D) /* 795 */,
CONST64(0x94D59893A43ACFF7) /* 796 */, CONST64(0x64F0C51CCDC02281) /* 797 */,
CONST64(0x3D33BCC4FF6189DB) /* 798 */, CONST64(0xE005CB184CE66AF1) /* 799 */,
CONST64(0xFF5CCD1D1DB99BEA) /* 800 */, CONST64(0xB0B854A7FE42980F) /* 801 */,
CONST64(0x7BD46A6A718D4B9F) /* 802 */, CONST64(0xD10FA8CC22A5FD8C) /* 803 */,
CONST64(0xD31484952BE4BD31) /* 804 */, CONST64(0xC7FA975FCB243847) /* 805 */,
CONST64(0x4886ED1E5846C407) /* 806 */, CONST64(0x28CDDB791EB70B04) /* 807 */,
CONST64(0xC2B00BE2F573417F) /* 808 */, CONST64(0x5C9590452180F877) /* 809 */,
CONST64(0x7A6BDDFFF370EB00) /* 810 */, CONST64(0xCE509E38D6D9D6A4) /* 811 */,
CONST64(0xEBEB0F00647FA702) /* 812 */, CONST64(0x1DCC06CF76606F06) /* 813 */,
CONST64(0xE4D9F28BA286FF0A) /* 814 */, CONST64(0xD85A305DC918C262) /* 815 */,
CONST64(0x475B1D8732225F54) /* 816 */, CONST64(0x2D4FB51668CCB5FE) /* 817 */,
CONST64(0xA679B9D9D72BBA20) /* 818 */, CONST64(0x53841C0D912D43A5) /* 819 */,
CONST64(0x3B7EAA48BF12A4E8) /* 820 */, CONST64(0x781E0E47F22F1DDF) /* 821 */,
CONST64(0xEFF20CE60AB50973) /* 822 */, CONST64(0x20D261D19DFFB742) /* 823 */,
CONST64(0x16A12B03062A2E39) /* 824 */, CONST64(0x1960EB2239650495) /* 825 */,
CONST64(0x251C16FED50EB8B8) /* 826 */, CONST64(0x9AC0C330F826016E) /* 827 */,
CONST64(0xED152665953E7671) /* 828 */, CONST64(0x02D63194A6369570) /* 829 */,
CONST64(0x5074F08394B1C987) /* 830 */, CONST64(0x70BA598C90B25CE1) /* 831 */,
CONST64(0x794A15810B9742F6) /* 832 */, CONST64(0x0D5925E9FCAF8C6C) /* 833 */,
CONST64(0x3067716CD868744E) /* 834 */, CONST64(0x910AB077E8D7731B) /* 835 */,
CONST64(0x6A61BBDB5AC42F61) /* 836 */, CONST64(0x93513EFBF0851567) /* 837 */,
CONST64(0xF494724B9E83E9D5) /* 838 */, CONST64(0xE887E1985C09648D) /* 839 */,
CONST64(0x34B1D3C675370CFD) /* 840 */, CONST64(0xDC35E433BC0D255D) /* 841 */,
CONST64(0xD0AAB84234131BE0) /* 842 */, CONST64(0x08042A50B48B7EAF) /* 843 */,
CONST64(0x9997C4EE44A3AB35) /* 844 */, CONST64(0x829A7B49201799D0) /* 845 */,
CONST64(0x263B8307B7C54441) /* 846 */, CONST64(0x752F95F4FD6A6CA6) /* 847 */,
CONST64(0x927217402C08C6E5) /* 848 */, CONST64(0x2A8AB754A795D9EE) /* 849 */,
CONST64(0xA442F7552F72943D) /* 850 */, CONST64(0x2C31334E19781208) /* 851 */,
CONST64(0x4FA98D7CEAEE6291) /* 852 */, CONST64(0x55C3862F665DB309) /* 853 */,
CONST64(0xBD0610175D53B1F3) /* 854 */, CONST64(0x46FE6CB840413F27) /* 855 */,
CONST64(0x3FE03792DF0CFA59) /* 856 */, CONST64(0xCFE700372EB85E8F) /* 857 */,
CONST64(0xA7BE29E7ADBCE118) /* 858 */, CONST64(0xE544EE5CDE8431DD) /* 859 */,
CONST64(0x8A781B1B41F1873E) /* 860 */, CONST64(0xA5C94C78A0D2F0E7) /* 861 */,
CONST64(0x39412E2877B60728) /* 862 */, CONST64(0xA1265EF3AFC9A62C) /* 863 */,
CONST64(0xBCC2770C6A2506C5) /* 864 */, CONST64(0x3AB66DD5DCE1CE12) /* 865 */,
CONST64(0xE65499D04A675B37) /* 866 */, CONST64(0x7D8F523481BFD216) /* 867 */,
CONST64(0x0F6F64FCEC15F389) /* 868 */, CONST64(0x74EFBE618B5B13C8) /* 869 */,
CONST64(0xACDC82B714273E1D) /* 870 */, CONST64(0xDD40BFE003199D17) /* 871 */,
CONST64(0x37E99257E7E061F8) /* 872 */, CONST64(0xFA52626904775AAA) /* 873 */,
CONST64(0x8BBBF63A463D56F9) /* 874 */, CONST64(0xF0013F1543A26E64) /* 875 */,
CONST64(0xA8307E9F879EC898) /* 876 */, CONST64(0xCC4C27A4150177CC) /* 877 */,
CONST64(0x1B432F2CCA1D3348) /* 878 */, CONST64(0xDE1D1F8F9F6FA013) /* 879 */,
CONST64(0x606602A047A7DDD6) /* 880 */, CONST64(0xD237AB64CC1CB2C7) /* 881 */,
CONST64(0x9B938E7225FCD1D3) /* 882 */, CONST64(0xEC4E03708E0FF476) /* 883 */,
CONST64(0xFEB2FBDA3D03C12D) /* 884 */, CONST64(0xAE0BCED2EE43889A) /* 885 */,
CONST64(0x22CB8923EBFB4F43) /* 886 */, CONST64(0x69360D013CF7396D) /* 887 */,
CONST64(0x855E3602D2D4E022) /* 888 */, CONST64(0x073805BAD01F784C) /* 889 */,
CONST64(0x33E17A133852F546) /* 890 */, CONST64(0xDF4874058AC7B638) /* 891 */,
CONST64(0xBA92B29C678AA14A) /* 892 */, CONST64(0x0CE89FC76CFAADCD) /* 893 */,
CONST64(0x5F9D4E0908339E34) /* 894 */, CONST64(0xF1AFE9291F5923B9) /* 895 */,
CONST64(0x6E3480F60F4A265F) /* 896 */, CONST64(0xEEBF3A2AB29B841C) /* 897 */,
CONST64(0xE21938A88F91B4AD) /* 898 */, CONST64(0x57DFEFF845C6D3C3) /* 899 */,
CONST64(0x2F006B0BF62CAAF2) /* 900 */, CONST64(0x62F479EF6F75EE78) /* 901 */,
CONST64(0x11A55AD41C8916A9) /* 902 */, CONST64(0xF229D29084FED453) /* 903 */,
CONST64(0x42F1C27B16B000E6) /* 904 */, CONST64(0x2B1F76749823C074) /* 905 */,
CONST64(0x4B76ECA3C2745360) /* 906 */, CONST64(0x8C98F463B91691BD) /* 907 */,
CONST64(0x14BCC93CF1ADE66A) /* 908 */, CONST64(0x8885213E6D458397) /* 909 */,
CONST64(0x8E177DF0274D4711) /* 910 */, CONST64(0xB49B73B5503F2951) /* 911 */,
CONST64(0x10168168C3F96B6B) /* 912 */, CONST64(0x0E3D963B63CAB0AE) /* 913 */,
CONST64(0x8DFC4B5655A1DB14) /* 914 */, CONST64(0xF789F1356E14DE5C) /* 915 */,
CONST64(0x683E68AF4E51DAC1) /* 916 */, CONST64(0xC9A84F9D8D4B0FD9) /* 917 */,
CONST64(0x3691E03F52A0F9D1) /* 918 */, CONST64(0x5ED86E46E1878E80) /* 919 */,
CONST64(0x3C711A0E99D07150) /* 920 */, CONST64(0x5A0865B20C4E9310) /* 921 */,
CONST64(0x56FBFC1FE4F0682E) /* 922 */, CONST64(0xEA8D5DE3105EDF9B) /* 923 */,
CONST64(0x71ABFDB12379187A) /* 924 */, CONST64(0x2EB99DE1BEE77B9C) /* 925 */,
CONST64(0x21ECC0EA33CF4523) /* 926 */, CONST64(0x59A4D7521805C7A1) /* 927 */,
CONST64(0x3896F5EB56AE7C72) /* 928 */, CONST64(0xAA638F3DB18F75DC) /* 929 */,
CONST64(0x9F39358DABE9808E) /* 930 */, CONST64(0xB7DEFA91C00B72AC) /* 931 */,
CONST64(0x6B5541FD62492D92) /* 932 */, CONST64(0x6DC6DEE8F92E4D5B) /* 933 */,
CONST64(0x353F57ABC4BEEA7E) /* 934 */, CONST64(0x735769D6DA5690CE) /* 935 */,
CONST64(0x0A234AA642391484) /* 936 */, CONST64(0xF6F9508028F80D9D) /* 937 */,
CONST64(0xB8E319A27AB3F215) /* 938 */, CONST64(0x31AD9C1151341A4D) /* 939 */,
CONST64(0x773C22A57BEF5805) /* 940 */, CONST64(0x45C7561A07968633) /* 941 */,
CONST64(0xF913DA9E249DBE36) /* 942 */, CONST64(0xDA652D9B78A64C68) /* 943 */,
CONST64(0x4C27A97F3BC334EF) /* 944 */, CONST64(0x76621220E66B17F4) /* 945 */,
CONST64(0x967743899ACD7D0B) /* 946 */, CONST64(0xF3EE5BCAE0ED6782) /* 947 */,
CONST64(0x409F753600C879FC) /* 948 */, CONST64(0x06D09A39B5926DB6) /* 949 */,
CONST64(0x6F83AEB0317AC588) /* 950 */, CONST64(0x01E6CA4A86381F21) /* 951 */,
CONST64(0x66FF3462D19F3025) /* 952 */, CONST64(0x72207C24DDFD3BFB) /* 953 */,
CONST64(0x4AF6B6D3E2ECE2EB) /* 954 */, CONST64(0x9C994DBEC7EA08DE) /* 955 */,
CONST64(0x49ACE597B09A8BC4) /* 956 */, CONST64(0xB38C4766CF0797BA) /* 957 */,
CONST64(0x131B9373C57C2A75) /* 958 */, CONST64(0xB1822CCE61931E58) /* 959 */,
CONST64(0x9D7555B909BA1C0C) /* 960 */, CONST64(0x127FAFDD937D11D2) /* 961 */,
CONST64(0x29DA3BADC66D92E4) /* 962 */, CONST64(0xA2C1D57154C2ECBC) /* 963 */,
CONST64(0x58C5134D82F6FE24) /* 964 */, CONST64(0x1C3AE3515B62274F) /* 965 */,
CONST64(0xE907C82E01CB8126) /* 966 */, CONST64(0xF8ED091913E37FCB) /* 967 */,
CONST64(0x3249D8F9C80046C9) /* 968 */, CONST64(0x80CF9BEDE388FB63) /* 969 */,
CONST64(0x1881539A116CF19E) /* 970 */, CONST64(0x5103F3F76BD52457) /* 971 */,
CONST64(0x15B7E6F5AE47F7A8) /* 972 */, CONST64(0xDBD7C6DED47E9CCF) /* 973 */,
CONST64(0x44E55C410228BB1A) /* 974 */, CONST64(0xB647D4255EDB4E99) /* 975 */,
CONST64(0x5D11882BB8AAFC30) /* 976 */, CONST64(0xF5098BBB29D3212A) /* 977 */,
CONST64(0x8FB5EA14E90296B3) /* 978 */, CONST64(0x677B942157DD025A) /* 979 */,
CONST64(0xFB58E7C0A390ACB5) /* 980 */, CONST64(0x89D3674C83BD4A01) /* 981 */,
CONST64(0x9E2DA4DF4BF3B93B) /* 982 */, CONST64(0xFCC41E328CAB4829) /* 983 */,
CONST64(0x03F38C96BA582C52) /* 984 */, CONST64(0xCAD1BDBD7FD85DB2) /* 985 */,
CONST64(0xBBB442C16082AE83) /* 986 */, CONST64(0xB95FE86BA5DA9AB0) /* 987 */,
CONST64(0xB22E04673771A93F) /* 988 */, CONST64(0x845358C9493152D8) /* 989 */,
CONST64(0xBE2A488697B4541E) /* 990 */, CONST64(0x95A2DC2DD38E6966) /* 991 */,
CONST64(0xC02C11AC923C852B) /* 992 */, CONST64(0x2388B1990DF2A87B) /* 993 */,
CONST64(0x7C8008FA1B4F37BE) /* 994 */, CONST64(0x1F70D0C84D54E503) /* 995 */,
CONST64(0x5490ADEC7ECE57D4) /* 996 */, CONST64(0x002B3C27D9063A3A) /* 997 */,
CONST64(0x7EAEA3848030A2BF) /* 998 */, CONST64(0xC602326DED2003C0) /* 999 */,
CONST64(0x83A7287D69A94086) /* 1000 */, CONST64(0xC57A5FCB30F57A8A) /* 1001 */,
CONST64(0xB56844E479EBE779) /* 1002 */, CONST64(0xA373B40F05DCBCE9) /* 1003 */,
CONST64(0xD71A786E88570EE2) /* 1004 */, CONST64(0x879CBACDBDE8F6A0) /* 1005 */,
CONST64(0x976AD1BCC164A32F) /* 1006 */, CONST64(0xAB21E25E9666D78B) /* 1007 */,
CONST64(0x901063AAE5E5C33C) /* 1008 */, CONST64(0x9818B34448698D90) /* 1009 */,
CONST64(0xE36487AE3E1E8ABB) /* 1010 */, CONST64(0xAFBDF931893BDCB4) /* 1011 */,
CONST64(0x6345A0DC5FBBD519) /* 1012 */, CONST64(0x8628FE269B9465CA) /* 1013 */,
CONST64(0x1E5D01603F9C51EC) /* 1014 */, CONST64(0x4DE44006A15049B7) /* 1015 */,
CONST64(0xBF6C70E5F776CBB1) /* 1016 */, CONST64(0x411218F2EF552BED) /* 1017 */,
CONST64(0xCB0C0708705A36A3) /* 1018 */, CONST64(0xE74D14754F986044) /* 1019 */,
CONST64(0xCD56D9430EA8280E) /* 1020 */, CONST64(0xC12591D7535F5065) /* 1021 */,
CONST64(0xC83223F1720AEF96) /* 1022 */, CONST64(0xC3A0396F7363A51F) /* 1023 */};
/* one round of the hash function */
static void round(ulong64 *a, ulong64 *b, ulong64 *c, ulong64 x, ulong64 mul)
{
*c ^= x;
*a -= t1[(*c)&255] ^ t2[((*c)>>16)&255] ^ t3[((*c)>>32)&255] ^ t4[((*c)>>48)&255];
*b += t4[((*c)>>8)&255] ^ t3[((*c)>>24)&255] ^ t2[((*c)>>40)&255] ^ t1[((*c)>>56)&255];
*b *= mul;
}
/* one complete pass */
static void pass(ulong64 *a, ulong64 *b, ulong64 *c, ulong64 *x, ulong64 mul)
{
round(a,b,c,x[0],mul);
round(b,c,a,x[1],mul);
round(c,a,b,x[2],mul);
round(a,b,c,x[3],mul);
round(b,c,a,x[4],mul);
round(c,a,b,x[5],mul);
round(a,b,c,x[6],mul);
round(b,c,a,x[7],mul);
}
/* The key mixing schedule */
static void key_schedule(ulong64 *x) {
x[0] -= x[7] ^ CONST64(0xA5A5A5A5A5A5A5A5);
x[1] ^= x[0];
x[2] += x[1];
x[3] -= x[2] ^ ((~x[1])<<19);
x[4] ^= x[3];
x[5] += x[4];
x[6] -= x[5] ^ ((~x[4])>>23);
x[7] ^= x[6];
x[0] += x[7];
x[1] -= x[0] ^ ((~x[7])<<19);
x[2] ^= x[1];
x[3] += x[2];
x[4] -= x[3] ^ ((~x[2])>>23);
x[5] ^= x[4];
x[6] += x[5];
x[7] -= x[6] ^ CONST64(0x0123456789ABCDEF);
}
#ifdef CLEAN_STACK
static void _tiger_compress(hash_state *md)
#else
static void tiger_compress(hash_state *md)
#endif
{
ulong64 a, b, c, x[8];
unsigned long i;
_ARGCHK(md != NULL);
/* load words */
for (i = 0; i < 8; i++) {
LOAD64L(x[i],&md->tiger.buf[8*i]);
}
a = md->tiger.state[0];
b = md->tiger.state[1];
c = md->tiger.state[2];
pass(&a,&b,&c,x,5);
key_schedule(x);
pass(&c,&a,&b,x,7);
key_schedule(x);
pass(&b,&c,&a,x,9);
/* store state */
md->tiger.state[0] = a ^ md->tiger.state[0];
md->tiger.state[1] = b - md->tiger.state[1];
md->tiger.state[2] = c + md->tiger.state[2];
}
#ifdef CLEAN_STACK
static void tiger_compress(hash_state *md)
{
_tiger_compress(md);
burn_stack(sizeof(ulong64) * 11 + sizeof(unsigned long));
}
#endif
void tiger_init(hash_state *md)
{
_ARGCHK(md != NULL);
md->tiger.state[0] = CONST64(0x0123456789ABCDEF);
md->tiger.state[1] = CONST64(0xFEDCBA9876543210);
md->tiger.state[2] = CONST64(0xF096A5B4C3B2E187);
md->tiger.curlen = 0;
md->tiger.length = 0;
}
void tiger_process(hash_state * md, const unsigned char *buf, unsigned long len)
{
unsigned long n;
_ARGCHK(md != NULL);
_ARGCHK(buf != NULL);
while (len) {
n = MIN(len, (64 - md->tiger.curlen));
memcpy(md->tiger.buf + md->tiger.curlen, buf, n);
md->tiger.curlen += n;
buf += n;
len -= n;
/* is 64 bytes full? */
if (md->tiger.curlen == 64) {
tiger_compress(md);
md->tiger.length += 512; /* add the number of bits not bytes */
md->tiger.curlen = 0;
}
}
}
void tiger_done(hash_state * md, unsigned char *hash)
{
_ARGCHK(md != NULL);
_ARGCHK(hash != NULL);
/* increase the length of the message */
md->tiger.length += md->tiger.curlen * 8;
/* append the '1' bit */
md->tiger.buf[md->tiger.curlen++] = 0x01;
/* 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->tiger.curlen > 56) {
while (md->tiger.curlen < 64) {
md->tiger.buf[md->tiger.curlen++] = 0;
}
tiger_compress(md);
md->tiger.curlen = 0;
}
/* pad upto 56 bytes of zeroes */
while (md->tiger.curlen < 56) {
md->tiger.buf[md->tiger.curlen++] = 0;
}
/* store length */
STORE64L(md->tiger.length, md->tiger.buf+56);
tiger_compress(md);
/* copy output */
STORE64L(md->tiger.state[0], &hash[0]);
STORE64L(md->tiger.state[1], &hash[8]);
STORE64L(md->tiger.state[2], &hash[16]);
#ifdef CLEAN_STACK
zeromem(md, sizeof(hash_state));
#endif
}
int tiger_test(void)
{
static const struct {
unsigned char *msg;
unsigned char hash[24];
} tests[] = {
{ "",
{ 0x32, 0x93, 0xac, 0x63, 0x0c, 0x13, 0xf0, 0x24,
0x5f, 0x92, 0xbb, 0xb1, 0x76, 0x6e, 0x16, 0x16,
0x7a, 0x4e, 0x58, 0x49, 0x2d, 0xde, 0x73, 0xf3 }
},
{ "abc",
{ 0x2a, 0xab, 0x14, 0x84, 0xe8, 0xc1, 0x58, 0xf2,
0xbf, 0xb8, 0xc5, 0xff, 0x41, 0xb5, 0x7a, 0x52,
0x51, 0x29, 0x13, 0x1c, 0x95, 0x7b, 0x5f, 0x93 }
},
{ "Tiger",
{ 0xdd, 0x00, 0x23, 0x07, 0x99, 0xf5, 0x00, 0x9f,
0xec, 0x6d, 0xeb, 0xc8, 0x38, 0xbb, 0x6a, 0x27,
0xdf, 0x2b, 0x9d, 0x6f, 0x11, 0x0c, 0x79, 0x37 }
},
{ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-",
{ 0xf7, 0x1c, 0x85, 0x83, 0x90, 0x2a, 0xfb, 0x87,
0x9e, 0xdf, 0xe6, 0x10, 0xf8, 0x2c, 0x0d, 0x47,
0x86, 0xa3, 0xa5, 0x34, 0x50, 0x44, 0x86, 0xb5 }
},
{ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-",
{ 0xc5, 0x40, 0x34, 0xe5, 0xb4, 0x3e, 0xb8, 0x00,
0x58, 0x48, 0xa7, 0xe0, 0xae, 0x6a, 0xac, 0x76,
0xe4, 0xff, 0x59, 0x0a, 0xe7, 0x15, 0xfd, 0x25 }
},
{ NULL, { 0 }}
};
int failed, i;
unsigned char tmp[24];
hash_state md;
for (failed = i = 0; tests[i].msg != NULL; i++) {
tiger_init(&md);
tiger_process(&md, tests[i].msg, strlen(tests[i].msg));
tiger_done(&md, tmp);
if (memcmp(tmp, tests[i].hash, 24)) {
#if 0
int j;
printf("\nTIGER-192 Test %d failed\nGot (as a result): ", i);
for (j = 0; j < 24; j++) {
printf("%02x ", tmp[j]);
}
printf("\n");
#endif
failed = 1;
}
}
if (failed == 1) {
return CRYPT_FAIL_TESTVECTOR;
} else {
return CRYPT_OK;
}
}
#endif
/*
Hash of "":
24F0130C63AC9332 16166E76B1BB925F F373DE2D49584E7A
Hash of "abc":
F258C1E88414AB2A 527AB541FFC5B8BF 935F7B951C132951
Hash of "Tiger":
9F00F599072300DD 276ABB38C8EB6DEC 37790C116F9D2BDF
Hash of "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-":
87FB2A9083851CF7 470D2CF810E6DF9E B586445034A5A386
Hash of "ABCDEFGHIJKLMNOPQRSTUVWXYZ=abcdefghijklmnopqrstuvwxyz+0123456789":
467DB80863EBCE48 8DF1CD1261655DE9 57896565975F9197
Hash of "Tiger - A Fast New Hash Function, by Ross Anderson and Eli Biham":
0C410A042968868A 1671DA5A3FD29A72 5EC1E457D3CDB303
Hash of "Tiger - A Fast New Hash Function, by Ross Anderson and Eli Biham, proceedings of Fast Software Encryption 3, Cambridge.":
EBF591D5AFA655CE 7F22894FF87F54AC 89C811B6B0DA3193
Hash of "Tiger - A Fast New Hash Function, by Ross Anderson and Eli Biham, proceedings of Fast Software Encryption 3, Cambridge, 1996.":
3D9AEB03D1BD1A63 57B2774DFD6D5B24 DD68151D503974FC
Hash of "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-":
00B83EB4E53440C5 76AC6AAEE0A74858 25FD15E70A59FFE4
*/

727
twofish.c Normal file
View File

@ -0,0 +1,727 @@
/* Implementation of Twofish by Tom St Denis */
#include "mycrypt.h"
#ifdef TWOFISH
const struct _cipher_descriptor twofish_desc =
{
"twofish",
7,
16, 32, 16, 16,
&twofish_setup,
&twofish_ecb_encrypt,
&twofish_ecb_decrypt,
&twofish_test,
&twofish_keysize
};
/* the two polynomials */
#define MDS_POLY 0x169
#define RS_POLY 0x14D
/* The 4x4 MDS Linear Transform */
static const unsigned char MDS[4][4] = {
{ 0x01, 0xEF, 0x5B, 0x5B },
{ 0x5B, 0xEF, 0xEF, 0x01 },
{ 0xEF, 0x5B, 0x01, 0xEF },
{ 0xEF, 0x01, 0xEF, 0x5B }
};
/* The 4x8 RS Linear Transform */
static const unsigned char RS[4][8] = {
{ 0x01, 0xA4, 0x55, 0x87, 0x5A, 0x58, 0xDB, 0x9E },
{ 0xA4, 0x56, 0x82, 0xF3, 0X1E, 0XC6, 0X68, 0XE5 },
{ 0X02, 0XA1, 0XFC, 0XC1, 0X47, 0XAE, 0X3D, 0X19 },
{ 0XA4, 0X55, 0X87, 0X5A, 0X58, 0XDB, 0X9E, 0X03 }
};
/* sbox usage orderings */
static const unsigned char qord[4][5] = {
{ 1, 1, 0, 0, 1 },
{ 0, 1, 1, 0, 0 },
{ 0, 0, 0, 1, 1 },
{ 1, 0, 1, 1, 0 }
};
#ifdef TWOFISH_TABLES
static const unsigned char SBOX[2][256] = {
{
0xa9, 0x67, 0xb3, 0xe8, 0x04, 0xfd, 0xa3, 0x76, 0x9a, 0x92,
0x80, 0x78, 0xe4, 0xdd, 0xd1, 0x38, 0x0d, 0xc6, 0x35, 0x98,
0x18, 0xf7, 0xec, 0x6c, 0x43, 0x75, 0x37, 0x26, 0xfa, 0x13,
0x94, 0x48, 0xf2, 0xd0, 0x8b, 0x30, 0x84, 0x54, 0xdf, 0x23,
0x19, 0x5b, 0x3d, 0x59, 0xf3, 0xae, 0xa2, 0x82, 0x63, 0x01,
0x83, 0x2e, 0xd9, 0x51, 0x9b, 0x7c, 0xa6, 0xeb, 0xa5, 0xbe,
0x16, 0x0c, 0xe3, 0x61, 0xc0, 0x8c, 0x3a, 0xf5, 0x73, 0x2c,
0x25, 0x0b, 0xbb, 0x4e, 0x89, 0x6b, 0x53, 0x6a, 0xb4, 0xf1,
0xe1, 0xe6, 0xbd, 0x45, 0xe2, 0xf4, 0xb6, 0x66, 0xcc, 0x95,
0x03, 0x56, 0xd4, 0x1c, 0x1e, 0xd7, 0xfb, 0xc3, 0x8e, 0xb5,
0xe9, 0xcf, 0xbf, 0xba, 0xea, 0x77, 0x39, 0xaf, 0x33, 0xc9,
0x62, 0x71, 0x81, 0x79, 0x09, 0xad, 0x24, 0xcd, 0xf9, 0xd8,
0xe5, 0xc5, 0xb9, 0x4d, 0x44, 0x08, 0x86, 0xe7, 0xa1, 0x1d,
0xaa, 0xed, 0x06, 0x70, 0xb2, 0xd2, 0x41, 0x7b, 0xa0, 0x11,
0x31, 0xc2, 0x27, 0x90, 0x20, 0xf6, 0x60, 0xff, 0x96, 0x5c,
0xb1, 0xab, 0x9e, 0x9c, 0x52, 0x1b, 0x5f, 0x93, 0x0a, 0xef,
0x91, 0x85, 0x49, 0xee, 0x2d, 0x4f, 0x8f, 0x3b, 0x47, 0x87,
0x6d, 0x46, 0xd6, 0x3e, 0x69, 0x64, 0x2a, 0xce, 0xcb, 0x2f,
0xfc, 0x97, 0x05, 0x7a, 0xac, 0x7f, 0xd5, 0x1a, 0x4b, 0x0e,
0xa7, 0x5a, 0x28, 0x14, 0x3f, 0x29, 0x88, 0x3c, 0x4c, 0x02,
0xb8, 0xda, 0xb0, 0x17, 0x55, 0x1f, 0x8a, 0x7d, 0x57, 0xc7,
0x8d, 0x74, 0xb7, 0xc4, 0x9f, 0x72, 0x7e, 0x15, 0x22, 0x12,
0x58, 0x07, 0x99, 0x34, 0x6e, 0x50, 0xde, 0x68, 0x65, 0xbc,
0xdb, 0xf8, 0xc8, 0xa8, 0x2b, 0x40, 0xdc, 0xfe, 0x32, 0xa4,
0xca, 0x10, 0x21, 0xf0, 0xd3, 0x5d, 0x0f, 0x00, 0x6f, 0x9d,
0x36, 0x42, 0x4a, 0x5e, 0xc1, 0xe0},
{
0x75, 0xf3, 0xc6, 0xf4, 0xdb, 0x7b, 0xfb, 0xc8, 0x4a, 0xd3,
0xe6, 0x6b, 0x45, 0x7d, 0xe8, 0x4b, 0xd6, 0x32, 0xd8, 0xfd,
0x37, 0x71, 0xf1, 0xe1, 0x30, 0x0f, 0xf8, 0x1b, 0x87, 0xfa,
0x06, 0x3f, 0x5e, 0xba, 0xae, 0x5b, 0x8a, 0x00, 0xbc, 0x9d,
0x6d, 0xc1, 0xb1, 0x0e, 0x80, 0x5d, 0xd2, 0xd5, 0xa0, 0x84,
0x07, 0x14, 0xb5, 0x90, 0x2c, 0xa3, 0xb2, 0x73, 0x4c, 0x54,
0x92, 0x74, 0x36, 0x51, 0x38, 0xb0, 0xbd, 0x5a, 0xfc, 0x60,
0x62, 0x96, 0x6c, 0x42, 0xf7, 0x10, 0x7c, 0x28, 0x27, 0x8c,
0x13, 0x95, 0x9c, 0xc7, 0x24, 0x46, 0x3b, 0x70, 0xca, 0xe3,
0x85, 0xcb, 0x11, 0xd0, 0x93, 0xb8, 0xa6, 0x83, 0x20, 0xff,
0x9f, 0x77, 0xc3, 0xcc, 0x03, 0x6f, 0x08, 0xbf, 0x40, 0xe7,
0x2b, 0xe2, 0x79, 0x0c, 0xaa, 0x82, 0x41, 0x3a, 0xea, 0xb9,
0xe4, 0x9a, 0xa4, 0x97, 0x7e, 0xda, 0x7a, 0x17, 0x66, 0x94,
0xa1, 0x1d, 0x3d, 0xf0, 0xde, 0xb3, 0x0b, 0x72, 0xa7, 0x1c,
0xef, 0xd1, 0x53, 0x3e, 0x8f, 0x33, 0x26, 0x5f, 0xec, 0x76,
0x2a, 0x49, 0x81, 0x88, 0xee, 0x21, 0xc4, 0x1a, 0xeb, 0xd9,
0xc5, 0x39, 0x99, 0xcd, 0xad, 0x31, 0x8b, 0x01, 0x18, 0x23,
0xdd, 0x1f, 0x4e, 0x2d, 0xf9, 0x48, 0x4f, 0xf2, 0x65, 0x8e,
0x78, 0x5c, 0x58, 0x19, 0x8d, 0xe5, 0x98, 0x57, 0x67, 0x7f,
0x05, 0x64, 0xaf, 0x63, 0xb6, 0xfe, 0xf5, 0xb7, 0x3c, 0xa5,
0xce, 0xe9, 0x68, 0x44, 0xe0, 0x4d, 0x43, 0x69, 0x29, 0x2e,
0xac, 0x15, 0x59, 0xa8, 0x0a, 0x9e, 0x6e, 0x47, 0xdf, 0x34,
0x35, 0x6a, 0xcf, 0xdc, 0x22, 0xc9, 0xc0, 0x9b, 0x89, 0xd4,
0xed, 0xab, 0x12, 0xa2, 0x0d, 0x52, 0xbb, 0x02, 0x2f, 0xa9,
0xd7, 0x61, 0x1e, 0xb4, 0x50, 0x04, 0xf6, 0xc2, 0x16, 0x25,
0x86, 0x56, 0x55, 0x09, 0xbe, 0x91}
};
static const unsigned char GF_EF[256] = {
0x00, 0xef, 0xb7, 0x58, 0x07, 0xe8, 0xb0, 0x5f, 0x0e, 0xe1,
0xb9, 0x56, 0x09, 0xe6, 0xbe, 0x51, 0x1c, 0xf3, 0xab, 0x44,
0x1b, 0xf4, 0xac, 0x43, 0x12, 0xfd, 0xa5, 0x4a, 0x15, 0xfa,
0xa2, 0x4d, 0x38, 0xd7, 0x8f, 0x60, 0x3f, 0xd0, 0x88, 0x67,
0x36, 0xd9, 0x81, 0x6e, 0x31, 0xde, 0x86, 0x69, 0x24, 0xcb,
0x93, 0x7c, 0x23, 0xcc, 0x94, 0x7b, 0x2a, 0xc5, 0x9d, 0x72,
0x2d, 0xc2, 0x9a, 0x75, 0x70, 0x9f, 0xc7, 0x28, 0x77, 0x98,
0xc0, 0x2f, 0x7e, 0x91, 0xc9, 0x26, 0x79, 0x96, 0xce, 0x21,
0x6c, 0x83, 0xdb, 0x34, 0x6b, 0x84, 0xdc, 0x33, 0x62, 0x8d,
0xd5, 0x3a, 0x65, 0x8a, 0xd2, 0x3d, 0x48, 0xa7, 0xff, 0x10,
0x4f, 0xa0, 0xf8, 0x17, 0x46, 0xa9, 0xf1, 0x1e, 0x41, 0xae,
0xf6, 0x19, 0x54, 0xbb, 0xe3, 0x0c, 0x53, 0xbc, 0xe4, 0x0b,
0x5a, 0xb5, 0xed, 0x02, 0x5d, 0xb2, 0xea, 0x05, 0xe0, 0x0f,
0x57, 0xb8, 0xe7, 0x08, 0x50, 0xbf, 0xee, 0x01, 0x59, 0xb6,
0xe9, 0x06, 0x5e, 0xb1, 0xfc, 0x13, 0x4b, 0xa4, 0xfb, 0x14,
0x4c, 0xa3, 0xf2, 0x1d, 0x45, 0xaa, 0xf5, 0x1a, 0x42, 0xad,
0xd8, 0x37, 0x6f, 0x80, 0xdf, 0x30, 0x68, 0x87, 0xd6, 0x39,
0x61, 0x8e, 0xd1, 0x3e, 0x66, 0x89, 0xc4, 0x2b, 0x73, 0x9c,
0xc3, 0x2c, 0x74, 0x9b, 0xca, 0x25, 0x7d, 0x92, 0xcd, 0x22,
0x7a, 0x95, 0x90, 0x7f, 0x27, 0xc8, 0x97, 0x78, 0x20, 0xcf,
0x9e, 0x71, 0x29, 0xc6, 0x99, 0x76, 0x2e, 0xc1, 0x8c, 0x63,
0x3b, 0xd4, 0x8b, 0x64, 0x3c, 0xd3, 0x82, 0x6d, 0x35, 0xda,
0x85, 0x6a, 0x32, 0xdd, 0xa8, 0x47, 0x1f, 0xf0, 0xaf, 0x40,
0x18, 0xf7, 0xa6, 0x49, 0x11, 0xfe, 0xa1, 0x4e, 0x16, 0xf9,
0xb4, 0x5b, 0x03, 0xec, 0xb3, 0x5c, 0x04, 0xeb, 0xba, 0x55,
0x0d, 0xe2, 0xbd, 0x52, 0x0a, 0xe5};
static const unsigned char GF_5B[256] = {
0x00, 0x5b, 0xb6, 0xed, 0x05, 0x5e, 0xb3, 0xe8, 0x0a, 0x51,
0xbc, 0xe7, 0x0f, 0x54, 0xb9, 0xe2, 0x14, 0x4f, 0xa2, 0xf9,
0x11, 0x4a, 0xa7, 0xfc, 0x1e, 0x45, 0xa8, 0xf3, 0x1b, 0x40,
0xad, 0xf6, 0x28, 0x73, 0x9e, 0xc5, 0x2d, 0x76, 0x9b, 0xc0,
0x22, 0x79, 0x94, 0xcf, 0x27, 0x7c, 0x91, 0xca, 0x3c, 0x67,
0x8a, 0xd1, 0x39, 0x62, 0x8f, 0xd4, 0x36, 0x6d, 0x80, 0xdb,
0x33, 0x68, 0x85, 0xde, 0x50, 0x0b, 0xe6, 0xbd, 0x55, 0x0e,
0xe3, 0xb8, 0x5a, 0x01, 0xec, 0xb7, 0x5f, 0x04, 0xe9, 0xb2,
0x44, 0x1f, 0xf2, 0xa9, 0x41, 0x1a, 0xf7, 0xac, 0x4e, 0x15,
0xf8, 0xa3, 0x4b, 0x10, 0xfd, 0xa6, 0x78, 0x23, 0xce, 0x95,
0x7d, 0x26, 0xcb, 0x90, 0x72, 0x29, 0xc4, 0x9f, 0x77, 0x2c,
0xc1, 0x9a, 0x6c, 0x37, 0xda, 0x81, 0x69, 0x32, 0xdf, 0x84,
0x66, 0x3d, 0xd0, 0x8b, 0x63, 0x38, 0xd5, 0x8e, 0xa0, 0xfb,
0x16, 0x4d, 0xa5, 0xfe, 0x13, 0x48, 0xaa, 0xf1, 0x1c, 0x47,
0xaf, 0xf4, 0x19, 0x42, 0xb4, 0xef, 0x02, 0x59, 0xb1, 0xea,
0x07, 0x5c, 0xbe, 0xe5, 0x08, 0x53, 0xbb, 0xe0, 0x0d, 0x56,
0x88, 0xd3, 0x3e, 0x65, 0x8d, 0xd6, 0x3b, 0x60, 0x82, 0xd9,
0x34, 0x6f, 0x87, 0xdc, 0x31, 0x6a, 0x9c, 0xc7, 0x2a, 0x71,
0x99, 0xc2, 0x2f, 0x74, 0x96, 0xcd, 0x20, 0x7b, 0x93, 0xc8,
0x25, 0x7e, 0xf0, 0xab, 0x46, 0x1d, 0xf5, 0xae, 0x43, 0x18,
0xfa, 0xa1, 0x4c, 0x17, 0xff, 0xa4, 0x49, 0x12, 0xe4, 0xbf,
0x52, 0x09, 0xe1, 0xba, 0x57, 0x0c, 0xee, 0xb5, 0x58, 0x03,
0xeb, 0xb0, 0x5d, 0x06, 0xd8, 0x83, 0x6e, 0x35, 0xdd, 0x86,
0x6b, 0x30, 0xd2, 0x89, 0x64, 0x3f, 0xd7, 0x8c, 0x61, 0x3a,
0xcc, 0x97, 0x7a, 0x21, 0xc9, 0x92, 0x7f, 0x24, 0xc6, 0x9d,
0x70, 0x2b, 0xc3, 0x98, 0x75, 0x2e};
#define sbox(i, x) ((unsigned long)SBOX[i][(x)&255])
#else
/* The Q-box tables */
static const unsigned char qbox[2][4][16] = {
{
{ 0x8, 0x1, 0x7, 0xD, 0x6, 0xF, 0x3, 0x2, 0x0, 0xB, 0x5, 0x9, 0xE, 0xC, 0xA, 0x4 },
{ 0xE, 0XC, 0XB, 0X8, 0X1, 0X2, 0X3, 0X5, 0XF, 0X4, 0XA, 0X6, 0X7, 0X0, 0X9, 0XD },
{ 0XB, 0XA, 0X5, 0XE, 0X6, 0XD, 0X9, 0X0, 0XC, 0X8, 0XF, 0X3, 0X2, 0X4, 0X7, 0X1 },
{ 0XD, 0X7, 0XF, 0X4, 0X1, 0X2, 0X6, 0XE, 0X9, 0XB, 0X3, 0X0, 0X8, 0X5, 0XC, 0XA }
},
{
{ 0X2, 0X8, 0XB, 0XD, 0XF, 0X7, 0X6, 0XE, 0X3, 0X1, 0X9, 0X4, 0X0, 0XA, 0XC, 0X5 },
{ 0X1, 0XE, 0X2, 0XB, 0X4, 0XC, 0X3, 0X7, 0X6, 0XD, 0XA, 0X5, 0XF, 0X9, 0X0, 0X8 },
{ 0X4, 0XC, 0X7, 0X5, 0X1, 0X6, 0X9, 0XA, 0X0, 0XE, 0XD, 0X8, 0X2, 0XB, 0X3, 0XF },
{ 0xB, 0X9, 0X5, 0X1, 0XC, 0X3, 0XD, 0XE, 0X6, 0X4, 0X7, 0XF, 0X2, 0X0, 0X8, 0XA }
}
};
/* computes S_i[x] */
#ifdef CLEAN_STACK
static unsigned long _sbox(int i, unsigned long x)
#else
unsigned long sbox(int i, unsigned long x)
#endif
{
unsigned char a0,b0,a1,b1,a2,b2,a3,b3,a4,b4,y;
/* a0,b0 = [x/16], x mod 16 */
a0 = (x>>4)&15;
b0 = (x)&15;
/* a1 = a0 ^ b0 */
a1 = a0 ^ b0;
/* b1 = a0 ^ ROR(b0, 1) ^ 8a0 */
b1 = (a0 ^ ((b0<<3)|(b0>>1)) ^ (a0<<3)) & 15;
/* a2,b2 = t0[a1], t1[b1] */
a2 = qbox[i][0][a1];
b2 = qbox[i][1][b1];
/* a3 = a2 ^ b2 */
a3 = a2 ^ b2;
/* b3 = a2 ^ ROR(b2, 1) ^ 8a2 */
b3 = (a2 ^ ((b2<<3)|(b2>>1)) ^ (a2<<3)) & 15;
/* a4,b4 = t2[a3], t3[b3] */
a4 = qbox[i][2][a3];
b4 = qbox[i][3][b3];
/* y = 16b4 + a4 */
y = (b4 << 4) + a4;
/* return result */
return (unsigned long)y;
}
#ifdef CLEAN_STACK
static unsigned long sbox(int i, unsigned long x)
{
unsigned long y;
y = _sbox(i, x);
burn_stack(sizeof(unsigned char) * 11);
return y;
}
#endif
#endif
/* computes ab mod p */
static unsigned long gf_mult(unsigned long a, unsigned long b, unsigned long p)
{
unsigned long result = 0;
while (a) {
if (a&1)
result ^= b;
a >>= 1;
b <<= 1;
if (b & 0x100)
b ^= p;
}
return result & 255;
}
/* Computes [y0 y1 y2 y3] = MDS . [x0 x1 x2 x3] */
static void mds_mult(const unsigned char *in, unsigned char *out)
{
int x, y;
unsigned char tmp[4];
for (x = 0; x < 4; x++) {
tmp[x] = 0;
for (y = 0; y < 4; y++)
tmp[x] ^= gf_mult(in[y], MDS[x][y], MDS_POLY);
}
for (x = 0; x < 4; x++)
out[x] = tmp[x];
zeromem(tmp, 4);
}
/* computes [y0 y1 y2 y3] = RS . [x0 x1 x2 x3 x4 x5 x6 x7] */
static void rs_mult(const unsigned char *in, unsigned char *out)
{
int x, y;
unsigned char tmp[4];
for (x = 0; x < 4; x++) {
tmp[x] = 0;
for (y = 0; y < 8; y++)
tmp[x] ^= gf_mult(in[y], RS[x][y], RS_POLY);
}
for (x = 0; x < 4; x++)
out[x] = tmp[x];
zeromem(tmp, 4);
}
/* computes [y0 y1 y2 y3] = MDS . [x0] */
#ifndef TWOFISH_TABLES
static unsigned long mds_column_mult(unsigned char in, int col)
{
return
(gf_mult(in, MDS[0][col], MDS_POLY) << 0) |
(gf_mult(in, MDS[1][col], MDS_POLY) << 8) |
(gf_mult(in, MDS[2][col], MDS_POLY) << 16) |
(gf_mult(in, MDS[3][col], MDS_POLY) << 24);
}
#else
static unsigned long mds_column_mult(unsigned char in, int col)
{
unsigned long x01, x5B, xEF;
x01 = in;
x5B = GF_5B[in];
xEF = GF_EF[in];
switch (col) {
case 0:
return (x01 << 0 ) |
(x5B << 8 ) |
(xEF << 16) |
(xEF << 24);
case 1:
return (xEF << 0 ) |
(xEF << 8 ) |
(x5B << 16) |
(x01 << 24);
case 2:
return (x5B << 0 ) |
(xEF << 8 ) |
(x01 << 16) |
(xEF << 24);
case 3:
return (x5B << 0 ) |
(x01 << 8 ) |
(xEF << 16) |
(x5B << 24);
}
/* avoid warnings, we'd never get here normally but just to calm compiler warnings... */
return 0;
}
#endif
/* computes h(x) */
static void h_func(const unsigned char *in, unsigned char *out, unsigned char *M, int k, int offset)
{
int x;
unsigned char y[4];
for (x = 0; x < 4; x++)
y[x] = in[x];
switch (k) {
case 4:
y[0] = sbox(1, y[0]) ^ M[4 * (6 + offset) + 0];
y[1] = sbox(0, y[1]) ^ M[4 * (6 + offset) + 1];
y[2] = sbox(0, y[2]) ^ M[4 * (6 + offset) + 2];
y[3] = sbox(1, y[3]) ^ M[4 * (6 + offset) + 3];
case 3:
y[0] = sbox(1, y[0]) ^ M[4 * (4 + offset) + 0];
y[1] = sbox(1, y[1]) ^ M[4 * (4 + offset) + 1];
y[2] = sbox(0, y[2]) ^ M[4 * (4 + offset) + 2];
y[3] = sbox(0, y[3]) ^ M[4 * (4 + offset) + 3];
case 2:
y[0] = sbox(1, sbox(0, sbox(0, y[0]) ^ M[4 * (2 + offset) + 0]) ^ M[4 * (0 + offset) + 0]);
y[1] = sbox(0, sbox(0, sbox(1, y[1]) ^ M[4 * (2 + offset) + 1]) ^ M[4 * (0 + offset) + 1]);
y[2] = sbox(1, sbox(1, sbox(0, y[2]) ^ M[4 * (2 + offset) + 2]) ^ M[4 * (0 + offset) + 2]);
y[3] = sbox(0, sbox(1, sbox(1, y[3]) ^ M[4 * (2 + offset) + 3]) ^ M[4 * (0 + offset) + 3]);
}
mds_mult(y, out);
}
#ifndef TWOFISH_SMALL
static unsigned long g_func(unsigned long x, symmetric_key *key)
{
return
key->twofish.S[0][(x>>0)&255] ^
key->twofish.S[1][(x>>8)&255] ^
key->twofish.S[2][(x>>16)&255] ^
key->twofish.S[3][(x>>24)&255];
}
#else
#ifdef CLEAN_STACK
static unsigned long _g_func(unsigned long x, symmetric_key *key)
#else
unsigned long g_func(unsigned long x, symmetric_key *key)
#endif
{
unsigned char g, i, y, z;
unsigned long res;
res = 0;
for (y = 0; y < 4; y++) {
z = key->twofish.start;
/* do unkeyed substitution */
g = sbox(qord[y][z++], (x >> (8*y)) & 255);
/* first subkey */
i = 0;
/* do key mixing+sbox until z==5 */
while (z != 5) {
g = g ^ key->twofish.S[4*i++ + y];
g = sbox(qord[y][z++], g);
}
/* multiply g by a column of the MDS */
res ^= mds_column_mult(g, y);
}
return res;
}
#ifdef CLEAN_STACK
static unsigned long g_func(unsigned long x, symmetric_key *key)
{
unsigned long y;
y = _g_func(x, key);
burn_stack(sizeof(unsigned char) * 4 + sizeof(unsigned long));
return y;
}
#endif
#endif
#ifdef CLEAN_STACK
static int _twofish_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey)
#else
int twofish_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey)
#endif
{
#ifndef TWOFISH_SMALL
int g, z, i;
unsigned char S[4*4];
#endif
int k, x, y, start;
unsigned char tmp[4], tmp2[4], M[8*4];
unsigned long A, B;
_ARGCHK(key != NULL);
_ARGCHK(skey != NULL);
/* invalid arguments? */
if (num_rounds != 16 && num_rounds != 0) {
return CRYPT_INVALID_ROUNDS;
}
if (keylen != 16 && keylen != 24 && keylen != 32) {
return CRYPT_INVALID_KEYSIZE;
}
/* k = keysize/64 [but since our keysize is in bytes...] */
k = keylen / 8;
/* copy the key into M */
for (x = 0; x < keylen; x++)
M[x] = key[x];
/* create the S[..] words */
#ifndef TWOFISH_SMALL
for (x = 0; x < k; x++)
rs_mult(M+(x*8), S+(x*4));
#else
for (x = 0; x < k; x++)
rs_mult(M+(x*8), skey->twofish.S+(x*4));
#endif
/* make subkeys */
for (x = 0; x < 20; x++) {
/* A = h(p * 2x, Me) */
for (y = 0; y < 4; y++)
tmp[y] = x+x;
h_func(tmp, tmp2, M, k, 0);
LOAD32L(A, tmp2);
/* B = ROL(h(p * (2x + 1), Mo), 8) */
for (y = 0; y < 4; y++)
tmp[y] = x+x+1;
h_func(tmp, tmp2, M, k, 1);
LOAD32L(B, tmp2);
B = ROL(B, 8);
/* K[2i] = A + B */
skey->twofish.K[x+x] = (A + B) & 0xFFFFFFFFUL;
/* K[2i+1] = (A + 2B) <<< 9 */
skey->twofish.K[x+x+1] = ROL(B + B + A, 9);
}
/* where to start in the sbox layers */
switch (k) {
case 4 : start = 0; break;
case 3 : start = 1; break;
default: start = 2; break;
}
#ifndef TWOFISH_SMALL
/* make the sboxes (large ram variant) */
for (y = 0; y < 4; y++) {
for (x = 0; x < 256; x++) {
z = start;
/* do unkeyed substitution */
g = sbox(qord[y][z++], x);
/* first subkey */
i = 0;
/* do key mixing+sbox until z==5 */
while (z != 5) {
g = g ^ S[4*i++ + y];
g = sbox(qord[y][z++], g);
}
/* multiply g by a column of the MDS */
skey->twofish.S[y][x] = mds_column_mult(g, y);
}
}
#else
/* small ram variant */
skey->twofish.start = start;
#endif
return CRYPT_OK;
}
#ifdef CLEAN_STACK
int twofish_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey)
{
int x;
x = _twofish_setup(key, keylen, num_rounds, skey);
burn_stack(sizeof(int) * 7 + sizeof(unsigned char) * 56 + sizeof(unsigned long) * 2);
return x;
}
#endif
#ifdef CLEAN_STACK
static void _twofish_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *key)
#else
void twofish_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *key)
#endif
{
unsigned long a,b,c,d,ta,tb,tc,td,t1,t2;
int r;
_ARGCHK(pt != NULL);
_ARGCHK(ct != NULL);
_ARGCHK(key != NULL);
LOAD32L(a,&pt[0]); LOAD32L(b,&pt[4]);
LOAD32L(c,&pt[8]); LOAD32L(d,&pt[12]);
a ^= key->twofish.K[0];
b ^= key->twofish.K[1];
c ^= key->twofish.K[2];
d ^= key->twofish.K[3];
for (r = 0; r < 16; r += 2) {
t1 = g_func(a, key);
t2 = g_func(ROL(b, 8), key);
t2 += (t1 += t2);
t1 += key->twofish.K[r+r+8];
t2 += key->twofish.K[r+r+9];
c ^= t1; c = ROR(c, 1);
d = ROL(d, 1) ^ t2;
t1 = g_func(c, key);
t2 = g_func(ROL(d, 8), key);
t2 += (t1 += t2);
t1 += key->twofish.K[r+r+10];
t2 += key->twofish.K[r+r+11];
a ^= t1; a = ROR(a, 1);
b = ROL(b, 1) ^ t2;
}
/* output with "undo last swap" */
ta = c ^ key->twofish.K[4];
tb = d ^ key->twofish.K[5];
tc = a ^ key->twofish.K[6];
td = b ^ key->twofish.K[7];
/* store output */
STORE32L(ta,&ct[0]); STORE32L(tb,&ct[4]);
STORE32L(tc,&ct[8]); STORE32L(td,&ct[12]);
}
#ifdef CLEAN_STACK
void twofish_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *key)
{
_twofish_ecb_encrypt(pt, ct, key);
burn_stack(sizeof(unsigned long) * 10 + sizeof(int));
}
#endif
#ifdef CLEAN_STACK
static void _twofish_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *key)
#else
void twofish_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *key)
#endif
{
unsigned long a,b,c,d,ta,tb,tc,td,t1,t2;
int r;
_ARGCHK(pt != NULL);
_ARGCHK(ct != NULL);
_ARGCHK(key != NULL);
/* load input */
LOAD32L(ta,&ct[0]); LOAD32L(tb,&ct[4]);
LOAD32L(tc,&ct[8]); LOAD32L(td,&ct[12]);
/* undo undo final swap */
a = tc ^ key->twofish.K[6];
b = td ^ key->twofish.K[7];
c = ta ^ key->twofish.K[4];
d = tb ^ key->twofish.K[5];
for (r = 14; r >= 0; r -= 2) {
t1 = g_func(c, key);
t2 = g_func(ROL(d, 8), key);
t2 += (t1 += t2);
t1 += key->twofish.K[r+r+10];
t2 += key->twofish.K[r+r+11];
a = ROL(a, 1) ^ t1;
b = b ^ t2; b = ROR(b, 1);
t1 = g_func(a, key);
t2 = g_func(ROL(b, 8), key);
t2 += (t1 += t2);
t1 += key->twofish.K[r+r+8];
t2 += key->twofish.K[r+r+9];
c = ROL(c, 1) ^ t1;
d = d ^ t2; d = ROR(d, 1);
}
/* pre-white */
a ^= key->twofish.K[0];
b ^= key->twofish.K[1];
c ^= key->twofish.K[2];
d ^= key->twofish.K[3];
/* store */
STORE32L(a, &pt[0]); STORE32L(b, &pt[4]);
STORE32L(c, &pt[8]); STORE32L(d, &pt[12]);
}
#ifdef CLEAN_STACK
void twofish_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *key)
{
_twofish_ecb_decrypt(ct, pt, key);
burn_stack(sizeof(unsigned long) * 10 + sizeof(int));
}
#endif
int twofish_test(void)
{
static const unsigned char key128[16] = {
0x9F, 0x58, 0x9F, 0x5C, 0xF6, 0x12, 0x2C, 0x32,
0xB6, 0xBF, 0xEC, 0x2F, 0x2A, 0xE8, 0xC3, 0x5A };
static const unsigned char pt128[16] = {
0xD4, 0x91, 0xDB, 0x16, 0xE7, 0xB1, 0xC3, 0x9E,
0x86, 0xCB, 0x08, 0x6B, 0x78, 0x9F, 0x54, 0x19 };
static const unsigned char ct128[16] = {
0x01, 0x9F, 0x98, 0x09, 0xDE, 0x17, 0x11, 0x85,
0x8F, 0xAA, 0xC3, 0xA3, 0xBA, 0x20, 0xFB, 0xC3 };
static const unsigned char key192[24] = {
0x88, 0xB2, 0xB2, 0x70, 0x6B, 0x10, 0x5E, 0x36,
0xB4, 0x46, 0xBB, 0x6D, 0x73, 0x1A, 0x1E, 0x88,
0xEF, 0xA7, 0x1F, 0x78, 0x89, 0x65, 0xBD, 0x44 };
static const unsigned char pt192[16] = {
0x39, 0xDA, 0x69, 0xD6, 0xBA, 0x49, 0x97, 0xD5,
0x85, 0xB6, 0xDC, 0x07, 0x3C, 0xA3, 0x41, 0xB2 };
static const unsigned char ct192[16] = {
0x18, 0x2B, 0x02, 0xD8, 0x14, 0x97, 0xEA, 0x45,
0xF9, 0xDA, 0xAC, 0xDC, 0x29, 0x19, 0x3A, 0x65 };
static const unsigned char key256[32] = {
0xD4, 0x3B, 0xB7, 0x55, 0x6E, 0xA3, 0x2E, 0x46,
0xF2, 0xA2, 0x82, 0xB7, 0xD4, 0x5B, 0x4E, 0x0D,
0x57, 0xFF, 0x73, 0x9D, 0x4D, 0xC9, 0x2C, 0x1B,
0xD7, 0xFC, 0x01, 0x70, 0x0C, 0xC8, 0x21, 0x6F };
static const unsigned char pt256[16] = {
0x90, 0xAF, 0xE9, 0x1B, 0xB2, 0x88, 0x54, 0x4F,
0x2C, 0x32, 0xDC, 0x23, 0x9B, 0x26, 0x35, 0xE6 };
static const unsigned char ct256[16] = {
0x6C, 0xB4, 0x56, 0x1C, 0x40, 0xBF, 0x0A, 0x97,
0x05, 0x93, 0x1C, 0xB6, 0xD4, 0x08, 0xE7, 0xFA };
symmetric_key key;
unsigned char tmp[2][16];
int errno;
if ((errno = twofish_setup(key128, 16, 0, &key)) != CRYPT_OK) {
return errno;
}
twofish_ecb_encrypt(pt128, tmp[0], &key);
twofish_ecb_decrypt(tmp[0], tmp[1], &key);
if (memcmp(tmp[0], ct128, 16) || memcmp(tmp[1], pt128, 16)) {
return CRYPT_FAIL_TESTVECTOR;
}
if ((errno = twofish_setup(key192, 24, 0, &key)) != CRYPT_OK) {
return errno;
}
twofish_ecb_encrypt(pt192, tmp[0], &key);
twofish_ecb_decrypt(tmp[0], tmp[1], &key);
if (memcmp(tmp[0], ct192, 16) || memcmp(tmp[1], pt192, 16)) {
return CRYPT_FAIL_TESTVECTOR;
}
if ((errno = twofish_setup(key256, 32, 0, &key)) != CRYPT_OK) {
return errno;
}
twofish_ecb_encrypt(pt256, tmp[0], &key);
twofish_ecb_decrypt(tmp[0], tmp[1], &key);
if (memcmp(tmp[0], ct256, 16) || memcmp(tmp[1], pt256, 16)) {
return CRYPT_FAIL_TESTVECTOR;
}
return CRYPT_OK;
}
int twofish_keysize(int *desired_keysize)
{
_ARGCHK(desired_keysize);
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

121
xtea.c Normal file
View File

@ -0,0 +1,121 @@
#include "mycrypt.h"
#ifdef XTEA
const struct _cipher_descriptor xtea_desc =
{
"xtea",
1,
16, 16, 8, 32,
&xtea_setup,
&xtea_ecb_encrypt,
&xtea_ecb_decrypt,
&xtea_test,
&xtea_keysize
};
int xtea_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey)
{
_ARGCHK(key != NULL);
_ARGCHK(skey != NULL);
/* check arguments */
if (keylen != 16) {
return CRYPT_INVALID_KEYSIZE;
}
if (num_rounds != 0 && num_rounds != 32) {
return CRYPT_INVALID_ROUNDS;
}
/* load key */
LOAD32L(skey->xtea.K[0], key+0);
LOAD32L(skey->xtea.K[1], key+4);
LOAD32L(skey->xtea.K[2], key+8);
LOAD32L(skey->xtea.K[3], key+12);
return CRYPT_OK;
}
void xtea_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *key)
{
unsigned long y, z, sum;
int r;
_ARGCHK(pt != NULL);
_ARGCHK(ct != NULL);
_ARGCHK(key != NULL);
LOAD32L(y, &pt[0]);
LOAD32L(z, &pt[4]);
sum = 0;
for (r = 0; r < 32; r++) {
y = (y + ((((z<<4)^(z>>5)) + z) ^ (sum + key->xtea.K[sum&3]))) & 0xFFFFFFFFUL;
sum = (sum + 0x9E3779B9UL) & 0xFFFFFFFFUL;
z = (z + ((((y<<4)^(y>>5)) + y) ^ (sum + key->xtea.K[(sum>>11)&3]))) & 0xFFFFFFFFUL;
}
STORE32L(y, &ct[0]);
STORE32L(z, &ct[4]);
}
void xtea_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *key)
{
unsigned long y, z, sum;
int r;
_ARGCHK(pt != NULL);
_ARGCHK(ct != NULL);
_ARGCHK(key != NULL);
LOAD32L(y, &ct[0]);
LOAD32L(z, &ct[4]);
sum = (32UL*0x9E3779B9UL)&0xFFFFFFFFUL;
for (r = 0; r < 32; r++) {
z = (z - ((((y<<4)^(y>>5)) + y) ^ (sum + key->xtea.K[(sum>>11)&3]))) & 0xFFFFFFFFUL;
sum = (sum - 0x9E3779B9UL) & 0xFFFFFFFFUL;
y = (y - ((((z<<4)^(z>>5)) + z) ^ (sum + key->xtea.K[sum&3]))) & 0xFFFFFFFFUL;
}
STORE32L(y, &pt[0]);
STORE32L(z, &pt[4]);
}
int xtea_test(void)
{
static const unsigned char key[16] =
{ 0x78, 0x56, 0x34, 0x12, 0xf0, 0xcd, 0xcb, 0x9a,
0x48, 0x37, 0x26, 0x15, 0xc0, 0xbf, 0xae, 0x9d };
static const unsigned char pt[8] =
{ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 };
static const unsigned char ct[8] =
{ 0x75, 0xd7, 0xc5, 0xbf, 0xcf, 0x58, 0xc9, 0x3f };
unsigned char tmp[2][8];
symmetric_key skey;
int errno;
if ((errno = xtea_setup(key, 16, 0, &skey)) != CRYPT_OK) {
return errno;
}
xtea_ecb_encrypt(pt, tmp[0], &skey);
xtea_ecb_decrypt(tmp[0], tmp[1], &skey);
if (memcmp(tmp[0], ct, 8) || memcmp(tmp[1], pt, 8)) {
return CRYPT_FAIL_TESTVECTOR;
}
return CRYPT_OK;
}
int xtea_keysize(int *desired_keysize)
{
_ARGCHK(desired_keysize);
if (*desired_keysize < 16) {
return CRYPT_INVALID_KEYSIZE;
}
*desired_keysize = 16;
return CRYPT_OK;
}
#endif

144
yarrow.c Normal file
View File

@ -0,0 +1,144 @@
#include "mycrypt.h"
#ifdef YARROW
const struct _prng_descriptor yarrow_desc =
{
"yarrow",
&yarrow_start,
&yarrow_add_entropy,
&yarrow_ready,
&yarrow_read
};
int yarrow_start(prng_state *prng)
{
int errno;
_ARGCHK(prng != NULL);
/* these are the default hash/cipher combo used */
#ifdef RIJNDAEL
prng->yarrow.cipher = register_cipher(&rijndael_desc);
#elif defined(BLOWFISH)
prng->yarrow.cipher = register_cipher(&blowfish_desc);
#elif defined(TWOFISH)
prng->yarrow.cipher = register_cipher(&twofish_desc);
#elif defined(CAST5)
prng->yarrow.cipher = register_cipher(&cast5_desc);
#elif defined(SERPENT)
prng->yarrow.cipher = register_cipher(&serpent_desc);
#elif defined(SAFER)
prng->yarrow.cipher = register_cipher(&saferp_desc);
#elif defined(RC5)
prng->yarrow.cipher = register_cipher(&rc5_desc);
#elif defined(RC6)
prng->yarrow.cipher = register_cipher(&rc6_desc);
#elif defined(XTEA)
prng->yarrow.cipher = register_cipher(&xtea_desc);
#elif defined(RC2)
prng->yarrow.cipher = register_cipher(&rc2_desc);
#elif defined(DES)
prng->yarrow.cipher = register_cipher(&des3_desc);
#elif
#error YARROW needs at least one CIPHER
#endif
if ((errno = cipher_is_valid(prng->yarrow.cipher)) != CRYPT_OK) {
return errno;
}
#ifdef SHA256
prng->yarrow.hash = register_hash(&sha256_desc);
#elif defined(SHA512)
prng->yarrow.hash = register_hash(&sha512_desc);
#elif defined(SHA384)
prng->yarrow.hash = register_hash(&sha384_desc);
#elif defined(SHA1)
prng->yarrow.hash = register_hash(&sha1_desc);
#elif defined(TIGER)
prng->yarrow.hash = register_hash(&tiger_desc);
#elif defined(MD5)
prng->yarrow.hash = register_hash(&md5_desc);
#elif defined(MD4)
prng->yarrow.hash = register_hash(&md4_desc);
#elif defined(MD2)
prng->yarrow.hash = register_hash(&md2_desc);
#else
#error YARROW needs at least one HASH
#endif
if ((errno = hash_is_valid(prng->yarrow.hash)) != CRYPT_OK) {
return errno;
}
/* zero the memory used */
zeromem(prng->yarrow.pool, sizeof(prng->yarrow.pool));
return CRYPT_OK;
}
int yarrow_add_entropy(const unsigned char *buf, unsigned long len, prng_state *prng)
{
hash_state md;
int errno;
_ARGCHK(buf != NULL);
_ARGCHK(prng != NULL);
if ((errno = hash_is_valid(prng->yarrow.hash)) != CRYPT_OK) {
return errno;
}
/* start the hash */
hash_descriptor[prng->yarrow.hash].init(&md);
/* hash the current pool */
hash_descriptor[prng->yarrow.hash].process(&md, prng->yarrow.pool, hash_descriptor[prng->yarrow.hash].hashsize);
/* add the new entropy */
hash_descriptor[prng->yarrow.hash].process(&md, buf, len);
/* store result */
hash_descriptor[prng->yarrow.hash].done(&md, prng->yarrow.pool);
return CRYPT_OK;
}
int yarrow_ready(prng_state *prng)
{
int ks, errno;
_ARGCHK(prng != NULL);
if ((errno = hash_is_valid(prng->yarrow.hash)) != CRYPT_OK) {
return errno;
}
if ((errno = cipher_is_valid(prng->yarrow.cipher)) != CRYPT_OK) {
return errno;
}
/* setup CTR mode using the "pool" as the key */
ks = hash_descriptor[prng->yarrow.hash].hashsize;
if ((errno = cipher_descriptor[prng->yarrow.cipher].keysize(&ks)) != CRYPT_OK) {
return errno;
}
if ((errno = ctr_start(prng->yarrow.cipher, prng->yarrow.pool, prng->yarrow.pool, ks, 0, &prng->yarrow.ctr)) != CRYPT_OK) {
return errno;
}
return CRYPT_OK;
}
unsigned long yarrow_read(unsigned char *buf, unsigned long len, prng_state *prng)
{
_ARGCHK(buf != NULL);
_ARGCHK(prng != NULL);
if (ctr_encrypt(buf, buf, len, &prng->yarrow.ctr) != CRYPT_OK) {
return 0;
}
return len;
}
#endif