×àñòü V
Èñõîäíûå êîäû
1. DES
2. LOKI91
3. IDEA
4. GOST
5. BLOWFISH
6. 3-WAY
7. RC5
8. À5
9. SEAL
DES
#define EN0 0 /* MODE == encrypt */ #define DE1 1 /* MODE == decrypt */
typedef struct {
unsigned long ek[32];
unsigned long dk[32]; } des_ctx;
extern void deskey(unsigned char *, short);
/* hexkey[8] MODE
* Sets the internal key register according to the hexadecimal
* key contained in the 8 bytes of hexkey, according to the DES,
* for encryption or decryption according to MODE. */
extern void usekey(unsigned long *);
/* cookedkey[32]
* Loads the internal key register with the data in cookedkey.
*/
extern void cpkey(unsigned long *);
/* cookedkey[32]
* Copies the contents of the internal key register into the storage
* located at &cookedkey[0]. */
extern void des(unsigned char *, unsigned char *);
/* from[8] to[8]
* Encrypts/Decrypts (according to the key currently loaded in the
* internal key register) one block of eight bytes at address 'from'
* into the block at address 'to'. They can be the same. */
static void scrunch(unsigned char *, unsigned long *); static void unscrun(unsigned long *, unsigned char *); static void desfunc(unsigned long *, unsigned long *); static void cookey(unsigned long *);
static unsigned long KnL[32] = { 0L }; static unsigned long KnR[32] = { 0L }; static unsigned long Kn3[32] = { 0L }; static 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 unsigned short bytebit[8] = {
0200, 0100, 040, 020, 010, 04, 02, 01 };
static 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 specified in the Standard (ANSI X3.92-1981). */
static 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 unsigned char totrot[16] = {
1,2,4,6,8,10,12,14,15,17,19,21,23,25,27,28 };
static 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 };
void deskey(key, edf) /* Thanks to James Gillogly & Phil Karn! */ unsigned char *key; short edf; {
register 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); return; }
static void cookey(raw1) register unsigned long *raw1; {
register unsigned long *cook, *raw0;
unsigned long dough[32];
register 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);
} usekey(dough); return; }
void cpkey(into)
register unsigned long *into;
{
register unsigned long *from, *endp;
from = KnL, endp = &KnL[32]; while( from < endp ) *into++ = *from++; return; }
void usekey(from)
register unsigned long *from;
{
register unsigned long *to, *endp;
to = KnL, endp = &KnL[32]; while( to < endp ) *to++ = *from++; return; }
void des(inblock, outblock) unsigned char *inblock, *outblock; {
unsigned long work[2];
scrunch(inblock, work); desfunc(work, KnL);
unscrun(work, outblock); return; }
static void scrunch(outof, into) register unsigned char *outof; register unsigned long *into; {
*into = (*outof++ & 0xffL) << 24;
*into |= (*outof++ & 0xffL) << 16;
*into |= (*outof++ & 0xffL) << 8;
*into++ |= (*outof++ & 0xffL);
*into = (*outof++ & 0xffL) << 24;
*into |= (*outof++ & 0xffL) << 16;
*into |= (*outof++ & 0xffL) << 8;
*into |= (*outof & 0xffL);
return; }
static void unscrun(outof, into) register unsigned long *outof; register unsigned char *into; {
*into++ = (*outof >> 24) & 0xffL;
*into++ = (*outof >> 16) & 0xffL;
*into++ = (*outof >> 8) & 0xffL;
*into++ = *outof++ & 0xffL;
*into++ = (*outof >> 24) & 0xffL;
*into++ = (*outof >> 16) & 0xffL;
*into++ = (*outof >> 8) & 0xffL;
*into = *outof & 0xffL;
return; }
static 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, 0x01010004L };
static 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, OxOOlOOOOOL, 0x80000020L,
0x00100020L, 0x80008020L, 0x80000020L, 0x00100020L,
0x00108000L, OxOOOOOOOOL, 0x80008000L, 0x00008020L,
0x80000000L, 0x80100020L, 0x80108020L, 0x00108000L };
static unsigned long SP3[64] = {
0x00000208L, 0x08020200L, OxOOOOOOOOL, 0x08020008L,
0x08000200L, OxOOOOOOOOL, 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, OxOOOOOOOOL,
0x00000200L, 0x00020008L, 0x08020208L, 0x08000200L,
0x08000008L, 0x00000200L, OxOOOOOOOOL, 0x08020008L,
0x08000208L, 0x00020000L, 0x08000000L, 0x08020208L,
0x00000008L, 0x00020208L, 0x00020200L, 0x08000008L,
0x08020000L, 0x08000208L, 0x00000208L, 0x08020000L,
0x00020208L, 0x00000008L, 0x08020008L, 0x00020200L };
static unsigned long SP4[64] = {
0x00802001L, 0x00002081L, 0x00002081L, 0x00000080L,
0x00802080L, 0x00800081L, 0x00800001L, 0x00002001L,
OxOOOOOOOOL, 0x00802000L, 0x00802000L, 0x00802081L,
0x00000081L, OxOOOOOOOOL, 0x00800080L, 0x00800001L,
OxOOOOOOOlL, 0x00002000L, 0x00800000L, 0x00802001L,
0x00000080L, 0x00800000L, 0x00002001L, 0x00002080L,
0x00800081L, OxOOOOOOOlL, 0x00002080L, 0x00800080L,
0x00002000L, 0x00802080L, 0x00802081L, 0x00000081L,
0x00800080L, 0x00800001L, 0x00802000L, 0x00802081L,
0x00000081L, OxOOOOOOOOL, OxOOOOOOOOL, 0x00802000L,
0x00002080L, 0x00800080L, 0x00800081L, OxOOOOOOOlL,
0x00802001L, 0x00002081L, 0x00002081L, 0x00000080L,
0x00802081L, 0x00000081L, OxOOOOOOOlL, 0x00002000L,
0x00800001L, 0x00002001L, 0x00802080L, 0x00800081L,
0x00002001L, 0x00002080L, 0x00800000L, 0x00802001L,
0x00000080L, 0x00800000L, 0x00002000L, 0x00802080L };
static unsigned long SP5[64] = {
OxOOOOOlOOL, 0x02080100L, 0x02080000L, 0x42000100L,
0x00080000L, OxOOOOOlOOL, 0x40000000L, 0x02080000L,
0x40080100L, 0x00080000L, 0x02000100L, 0x40080100L,
0x42000100L, 0x42080000L, 0x00080100L, 0x40000000L,
0x02000000L, 0x40080000L, 0x40080000L, OxOOOOOOOOL,
0x40000100L, 0x42080100L, 0x42080100L, 0x02000100L,
0x42080000L, 0x40000100L, OxOOOOOOOOL, 0x42000000L,
0x02080100L, 0x02000000L, 0x42000000L, 0x00080100L,
0x00080000L, 0x42000100L, OxOOOOOlOOL, 0x02000000L,
0x40000000L, 0x02080000L, 0x42000100L, 0x40080100L,
0x02000100L, 0x40000000L, 0x42080000L, 0x02080100L,
0x40080100L, OxOOOOOlOOL, 0x02000000L, 0x42080000L,
0x42080100L, 0x00080100L, 0x42000000L, 0x42080100L,
0x02080000L, OxOOOOOOOOL, 0x40080000L, 0x42000000L,
0x00080100L, 0x02000100L, 0x40000100L, 0x00080000L,
OxOOOOOOOOL, 0x40080000L, 0x02080100L, 0x40000100L };
static 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, 0x20004010L };
static 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, 0x00200002L };
static 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, 0x10041000L };
static void desfunc(block, keys) register unsigned long *block, *keys; {
register unsigned long fval, work, right, leftt;
register int round;
leftt = block[0]; right = block[1];
work = ((leftt » 4) ë right) & OxOfOfOfOfL;
right ë= work;
leftt ë= (work « 4);
work = ((leftt » 16) ë right) & OxOOOOffffL;
right ë= work;
leftt ë= (work « 16);
work = ((right » 2) ë leftt) & 0x33333333L;
leftt ë= work;
right ë= (work « 2);
work = ((right » 8) ë leftt) & OxOOffOOffL;
leftt ë= work;
right ë= (work « 8);
right = ((right « 1) | ((right » 31) & 1L)) & OxffffffffL;
work = (leftt ë right) & OxaaaaaaaaL;
leftt ë= work;
right ë= work;
leftt = ((leftt « 1) | ((leftt » 31) & 1L)) & OxffffffffL;
for( round = 0; round < 8; round++ ) {
work = (right «28) | (right » 4);
work ë= *keys++;
fval = SP7[ work & 0x3fL];
fval |= SP5[(work » 8) & 0x3fL];
fval |= SP3[(work » 16) & 0x3fL];
fval |= SPl[(work » 24) & 0x3fL];
work = right ë *keys++;
fval |= SP8[ work & 0x3fL];
fval |= SP6[(work » 8) & 0x3fL];
fval |= SP4[(work » 16) & 0x3fL];
fval |= SP2[(work » 24) & 0x3fL];
leftt ë= fval;
work = (leftt « 28) | (leftt » 4);
work ë= *keys++;
fval = SP7[ work & 0x3fL];
fval |= SP5[(work » 8) & 0x3fL];
fval |= SP3[(work » 16) & 0x3fL];
fval |= SPl[(work » 24) & 0x3fL];
work = leftt ë *keys++;
fval |= SP8[ work & 0x3fL];
fval |= SP6[(work » 8) & 0x3fL];
fval |= SP4[(work » 16) & 0x3fL];
fval |= SP2[(work » 24) & 0x3fL];
right ë= fval;
}
right = (right « 31) | (right » 1);
work = (leftt ë right) & OxaaaaaaaaL;
leftt ë= work;
right ë= work;
leftt = (leftt « 31) | (leftt » 1);
work = ((leftt » 8) ë right) & OxOOffOOffL;
right ë= work;
leftt ë= (work « 8);
work = ((leftt » 2) ë right) & 0x33333333L;
right ë= work;
leftt ë= (work « 2);
work = ((right » 16) ë leftt) & OxOOOOffffL;
leftt ë= work;
right ë= (work « 16);
work = ((right » 4) ë leftt) & OxOfOfOfOfL;
leftt ë= work;
right ë= (work « 4);
*block++ = right; *block = leftt; return; }
/* Validation sets: *
* Single-length key, single-length plaintext -
* Key : 0123 4567 89ab cdef
* Plain : 0123 4567 89ab cde7
* Cipher : c957 4425 6a5e d31d * **********************************************************************/
void des_key(des_ctx *dc, unsigned char *key){
deskey(key,EN0);
cpkey(dc->ek);
deskey(key,DE1);
cpkey(dc->dk); }
/* Encrypt several blocks in ECB mode. Caller is responsible for
short blocks. */ void des_enc(des_ctx *dc, unsigned char *data, int blocks){
unsigned long work[2];
int i;
unsigned char *cp;
cp = data; for(i=0;i<blocks;i++){
scrunch(cp,work);
desfunc(work,dc->ek);
unscrun(work,cp);
cp+=8; } }
void des_dec(des_ctx *dc, unsigned char *data, int blocks){ unsigned long work[2]; int i; unsigned char *cp;
cp = data; for(i=0;i<blocks;i++){
scrunch(cp,work);
desfunc(work,dc->dk);
unscrun(work,cp);
cp+=8; } }
void main(void){
des_ctx dc;
int i;
unsigned long data[10];
char *cp,key[8] = {0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef};
char x[8] = {0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xe7};
ñð = õ;
des_key(&dc,key);
des_enc(&dc,cp,1);
printf("Enc(0..7,0..7) = ");
for(i=0;i<8;i++) printf("%02x ", ((unsigned int) cp[i])&0x00ff);
printf("n");
des_dec(&dc,cp,1);
printf("Dec(above,0..7) = ");
for(i=0;i<8;i++) printf("%02x ",((unsigned int)cp[i])&0x00ff);
printf("n");
cp = (char *) data; for(i=0;i<10;i++)data[i]=i;
des_enc(&dc,cp,5); /* Enc 5 blocks. */
for(i=0;i<10;i+=2) printf("Block %01d = %08lx %08lx.n",
i/2,data[i],data[i+1]);
des_dec(&dc,cp,1); des_dec(&dc,cp+8,4);
for(i=0;i<10;i+=2) printf("Block %01d = %08lx %08lx.n",
i/2,data[i],data[i+1]);
}
L0KI91
#include <stdio.h>
#define LOKIBLK 8 /* No of bytes in a LOKI data-block
*/
#define ROUNDS 16 /* No of LOKI rounds
*/
typedef unsigned long Long; /* type specification for aligned LOKI blocks */
extern Long lokikey[2]; /* 64-bit key used by LOKI routines */ extern char *loki_lib_ver; /* String with version no. & copyright */
#ifdef __STDC__ /* declare prototypes for library
functions */
extern void enloki(char *b);
extern void deloki(char *b);
extern void setlokikey(char key[LOKIBLK]);
#else /* else just declare library functions extern
*/
extern void enloki(), deloki(), setlokikey();
#endif __STDC__
char P[32] = {
31, 23, 15, 7, 30, 22, 14, 6, 29, 21, 13, 5, 28, 20, 12, 4, 27, 19, 11, 3, 26, 18, 10, 2, 25, 17, 9, 1, 24, 16, 8, 0 };
typedef struct {
short gen; /* irreducible polynomial used in this field */
short exp; /* exponent used to generate this s function */
} sfn_desc;
sfn_desc sfn[] = {
{ /* 101110111 */ 375, 31}, { /* 101111011 */ 379, 31}, { /* 110000111 */ 391, 31}, { /* 110001011 */ 395, 31}, { /* 110001101 */ 397, 31}, { /* 110011111 */ 415, 31}, { /* 110100011 */ 419, 31}, { /* 110101001 */ 425, 31}, { /* 110110001 */ 433, 31}, { /* 110111101 */ 445, 31}, { /* 111000011 */ 451, 31}, { /* 111001111 */ 463, 31}, { /* 111010111 */ 471, 31}, { /* 111011101 */ 477, 31}, { /* 111100111 */ 487, 31}, { /* 111110011 */ 499, 31}, { 00, 00} };
typedef struct {
Long loki_subkeys[ROUNDS]; } loki_ctx;
static Long f(); /* declare LOKI function f */
static short s(); /* declare LOKI S-box fn s */
#define ROL12(b) b = ((b << 12) | (b >> 20)); #define ROL13(b) b = ((b << 13) | (b >> 19));
#ifdef LITTLE_ENDIAN
#define bswap(cb) {
register char c;
c = cb[0]; cb[0] = cb[3]; cb[3] = c;
c = cb[1]; cb[1] = cb[2]; cb[2] = c;
c = cb[4]; cb[4] = cb[7]; cb[7] = c;
c = cb[5]; cb[5] = cb[6]; cb[6] = c;
}
#endif
void
setlokikey(loki_ctx *c, char *key)
{
register i;
register Long KL, KR;
#ifdef LITTLE_ENDIAN
bswap(key); /* swap bytes round if little-endian */
#endif
KL = ((Long *)key)[0];
KR = ((Long *)key)[1];
for (i=0; i<ROUNDS; i+=4) { /* Generate the 16 subkeys */
c->loki_subkeys[i] = KL;
ROL12 (KL);
c->loki_subkeys[i+1] = KL;
ROL13 (KL);
c->loki_subkeys[i+2] = KR;
ROL12 (KR);
c->loki_subkeys[i+3] = KR;
ROL13 (KR); }
#ifdef LITTLE_ENDIAN
bswap(key); /* swap bytes back if little-endian */
#endif
}
void
enloki (loki_ctx *c, char *b)
{
register i;
register Long L, R; /* left & right data halves */
#ifdef LITTLE_ENDIAN
bswap(b); /* swap bytes round if little-endian */
#endif
L = ((Long *)b)[0]; R = ((Long *)b)[1];
for (i=0; i<ROUNDS; i+=2) { /* Encrypt with the 16 subkeys
*/
L ^= f (R, c->loki_subkeys[i]);
R ^= f (L, c->loki_subkeys[i+1]); }
((Long *)b)[0] = R; /* Y = swap(LR) */
((Long *)b)[1] = L;
#ifdef LITTLE_ENDIAN
bswap(b); /* swap bytes round if little-endian */
#endif }
void
deloki(loki_ctx *c, char *b)
{
register i;
register Long L, R; /* left & right data halves */
#ifdef LITTLE_ENDIAN
bswap(b); /* swap bytes round if little-endian */
#endif
L = ((Long *)b)[0]; /* LR = X XOR K */
R = ((Long *)b)[1];
for (i=ROUNDS; i>0; i-=2) { /* subkeys in reverse
order */
L ^= f(R, c->loki_subkeys[i-1]);
R ^= f(L, c->loki_subkeys[i-2]); }
((Long *)b)[0] = R; /* Y = LR XOR K */
((Long *)b)[1] = L; }
#define MASK12 0x0fff /* 12 bit mask for expansion E
*/
static Long
f(r, k)
register Long r; /* Data value R(i-1) */
Long k; /* Key K(i) */
{
Long a, b, c; /* 32 bit S-box output, & P output */
a = r ^ k; /* A = R(i-1) XOR K(i) */
/* want to use slow speed/small size version */
b = ((Long)s((a & MASK12)) ) | /* B = S(E(R(i-1))^K(i)) */
((Long)s(((a >> 8) & MASK12)) << 8) | ((Long)s(((a >> 16) & MASK12)) << 16) | ((Long)s((((a >> 24) | (a << 8)) & MASK12)) << 24);
perm32(&c, &b, P); /* C = P(S( E(R(i-1)) XOR K(i))) */
return(c); /* f returns the result C */
}
static short s(i)
register Long i; /* return S-box value for input i */
{
register short r, c, v, t;
short exp8(); /* exponentiation routine for GF(2^8) */
r = ((i>>8) & 0xc) | (i & 0x3); /* row value-top 2 &
bottom 2 */
c = (i>>2) & 0xff; /* column
value-middle 8 bits */
t = (c + ((r * 17) ^ 0xff)) & 0xff; /* base value for Sfn */
v = exp8(t, sfn[r].exp, sfn[r].gen); /* Sfn[r] = t ^ exp mod gen */
return(v); }
#define MSB 0x80000000L /* MSB of 32-bit word */
perm32(out, in , perm)
Long *out; /* Output 32-bit block to be permuted */
Long *in; /* Input 32-bit block after permutation */
char perm[32]; /* Permutation array */
{
Long mask = MSB; /* mask used to set bit in
output */
register int i, o, b; /* input bit no, output bit no, value */ register char *p = perm; /* ptr to permutation array */
*out = 0; /* clear output block */
for (o=0; o<32; o++) { /* For each output bit
position o */
i =(int)*p++; /* get input bit permuted to
output o */
b = (*in >> i) & 01; /* value of input bit i */
if (b) /* If the input bit i is set */
*out |= mask; /* OR in mask to
output i */
mask >>= 1; /* Shift mask to next
bit */ } }
#define SIZE 256 /* 256 elements in GF(2^8) */
short mult8(a, b, gen)
short a, b; /* operands for multiply */
short gen; /* irreducible polynomial generating Galois Field */
{
short product = 0; /* result of multiplication */
while(b != 0) { /* while multiplier is
non-zero */
if (b & 01)
product ^= a; /* add multiplicand if LSB of b set */
a <<= 1; /* shift multiplicand one place */
if (a >= SIZE)
a ^= gen; /* and modulo reduce if needed */
b >>= 1; /* shift multiplier one place */
}
return(product); }
short exp8(base, exponent, gen)
short base; /* base of exponentiation */
short exponent; /* exponent */
short gen; /* irreducible polynomial generating Galois Field */
{
short accum = base; /* superincreasing sequence of base */ short result = 1; /* result of exponentiation */
if (base == 0) /* if zero base specified then */
return(0); /* the result is "0" if base = 0 */
while (exponent != 0) { /* repeat while exponent non-zero */
if (( exponent & 0x0001) == 0x0001) /* multiply if
exp 1 */
result = mult8(result, accum, gen);
exponent >>= 1; /* shift exponent to next
digit */
accum = mult8(accum, accum, gen); /* & square */
}
return(result); }
void loki_key(loki_ctx *c, unsigned char *key){
setlokikey(c,key); }
void loki_enc(loki_ctx *c, unsigned char *data, int blocks){ unsigned char *cp; int i;
cp = data; for(i=0;i<blocks;i++){
enloki(c,cp);
cp+=8; } }
void loki_dec(loki_ctx *c, unsigned char *data, int blocks){ unsigned char *cp; int i;
cp = data; for(i=0;i<blocks;i++){
deloki(c,cp);
cp+=8; } }
void main(void){
loki_ctx lc;
unsigned long data[10];
unsigned char *cp;
unsigned char key[] = {0,1,2,3,4,5,6,7};
int i;
for(i=0;i<10;i++) data[i]=i;
loki_key(&lc,key);
cp = (char *)data;
loki_enc(&lc,cp,5);
for(i=0;i<10;i+=2) printf("Block %01d = %08lx %08lxn",
i/2,data[i],data[i+1]); loki_dec(&lc,cp,1); loki_dec(&lc,cp+8,4); for(i=0;i<10;i+=2) printf("Block %01d = %08lx %08lxn",
i/2,data[i],data[i+1]);
}
IDEA
typedef unsigned char boolean; /* values are TRUE or FALSE */
typedef unsigned char byte; /* values are 0-255 */
typedef byte *byteptr; /* pointer to byte */
typedef char *string;/* pointer to ASCII character string */
typedef unsigned short word16; /* values are 0-65535 */
typedef unsigned long word32; /* values are 0-4294967295 */
#ifndef TRUE
#define FALSE 0
#define TRUE (!FALSE)
#endif /* if TRUE not already defined */
#ifndef min /* if min macro not already defined */ #define min(a,b) ( (a)<(b) ? (a) : (b) ) #define max(a,b) ( (a)>(b) ? (a) : (b) ) #endif /* if min macro not already defined */
#define IDEAKEYSIZE 16 #define IDEABLOCKSIZE 8
#define IDEAROUNDS 8
#define IDEAKEYLEN (6*IDEAROUNDS+4)
typedef struct{
word16 ek[IDEAKEYLEN],dk[IDEAKEYLEN]; }idea_ctx;
/* End includes for IDEA.C */
#ifdef IDEA32 /* Use >16-bit temporaries */
#define low16(x) ((x) & 0xFFFF)
typedef unsigned int uint16;/* at LEAST 16 bits, maybe more */
#else
#define low16(x) (x) /* this is only ever applied to uint16's */
typedef word16 uint16;
#endif
#ifdef SMALL_CACHE
static uint16
mul(register uint16 a, register uint16 b)
{
register word32 p;
p = (word32)a * b; if (p) {
b = low16(p);
a = p>>16;
return (b - a) + (b < a); } else if (a) {
return 1-b; } else {
return 1-a; } } /* mul */ #endif /* SMALL_CACHE */
static uint16 mulInv(uint16 x) {
uint16 t0, t1;
uint16 q, y;
if (x <= 1)
return x; /* 0 and 1 are self-inverse */ t1 = 0x10001L / x; /* Since x >= 2, this fits into 16 bits */ y = 0x10001L % x; if (y == 1)
return low16(1-t1); t0 = 1; do {
q = x / y;
x = x % y;
t0 += q * t1;
if (x == 1)
return t0;
q = y / x;
y = y % x;
t1 += q * t0; } while (y != 1); return low16(1-t1); } /* mukInv */
static void
ideaExpandKey(byte const *userkey, word16 *EK)
{
int i,j;
for (j=0; j<8; j++) {
EK[j] = (userkey[0]<<8) + userkey[1];
userkey += 2; } for (i=0; j < IDEAKEYLEN; j++) {
i++;
EK[i+7] = EK[i & 7] << 9 | EK[i+1 & 7] >> 7;
EK += i & 8;
i &= 7; }
} /* ideaExpandKey */
static void
ideaInvertKey(word16 const *EK, word16 DK[IDEAKEYLEN])
{
int i;
uint16 t1, t2, t3;
word16 temp[IDEAKEYLEN];
word16 *p = temp + IDEAKEYLEN;
t1 = mulInv(*EK++);
t2 = -*EK++;
t3 = -*EK++;
*--p = mulInv(*EK++);
*--p = t3;
*--p = t2;
*--p = t1;
for (i = 0; i < IDEAROUNDS-1; i++) { t1 = *EK++; *--p = *EK++; *--p = t1;
t1 = mulInv(*EK++);
t2 = -*EK++;
t3 = -*EK++;
*--p = mulInv(*EK++);
*--p = t2;
*--p = t3;
*--p = t1; }
t1 = *EK++; *--p = *EK++; *--p = t1;
t1 = mulInv(*EK++);
t2 = -*EK++;
t3 = -*EK++;
*--p = mulInv(*EK++);
*--p = t3;
*--p = t2;
*--p = t1; /* Copy and destroy temp copy */
memcpy(DK, temp, sizeof(temp));
for(i=0;i<IDEAKEYLEN;i++)temp[i]=0; } /* ideaInvertKey */
#ifdef SMALL_CACHE
#define MUL(x,y) (x = mul(low16(x),y))
#else /* !SMALL_CACHE */
#ifdef AVOID_JUMPS
#define MUL(x,y) (x = low16(x-1), t16 = low16((y)-1),
t32 = (word32)x*t16 + x + t16 + 1, x = low16(t32), t16 = t32>>16, x = (x-t16) + (x<t16) ) #else /* !AVOID_JUMPS (default) */ #define MUL(x,y)
((t16 = (y)) ?
(x=low16(x)) ?
t32 = (word32)x*t16, x = low16(t32), t16 = t32>>16, x = (x-t16)+(x<t16)
:
(õ = l-tl6)
:
(x = 1-x)) #endif #endif
static void
ideaCipher(byte *inbuf, byte *outbuf, word16 *key)
{
register uint16 x1, x2, x3, x4, s2, s3;
word16 *in, *out; #ifndef SMALL_CACHE
register uint16 t16; /* Temporaries needed by MUL macro */
register word32 t32;
#endif
int r = IDEAROUNDS;
in = (wordl6 *)inbuf; xl = *in++; x2 = *in++; x3 = *in++; x4 = *in; #ifndef HIGHFIRST
xl = (xl »8) | (xl«8); x2 = (x2 »8) | (x2«8); x3 = (x3 »8) | (x3«8); x4 = (x4 »8) | (x4«8); #endif
do {
MUL(xl,*key++);
x2 += *key++;
x3 += *key++;
MUL(x4, *key++);
s3 = x3; õÇ ë= xl; MUL(x3, *key++); s2 = x2; x2 ë= x4; x2 += x3; MUL(x2, *key++); x3 += x2;
xl ë= õ2; õ4 ë= õÇ;
x2 ë= s3; õÇ ë= s2; } while (--r); MUL(xl, *key++); x3 += *key++; x2 += *key++; MUL(x4, *key);
out = (wordl6 *)outbuf; #ifdef HIGHFIRST
*out++ = xl;
*out++ = x3;
*out++ = x2;
*out = x4; #else /* 1HIGHFIRST */
*out++ = (xl »8) | (xl«8);
*out++ = (x3 »8) | (x3«8);
*out++ = (x2 »8) | (x2«8);
*out = (x4 »8) | (x4«8);
#endif
} /* ideaCipher */
void idea_key(idea_ctx *c, unsigned char *key){
ideaExpandKey(key,c->ek);
ideaInvertKey(c->ek,c->dk); }
void idea_enc(idea_ctx *c, unsigned char *data, int blocks){ int i; unsigned char *d = data;
for(i=0;i<blocks;i++){
ideaCipher(d,d,c->ek);
d+=8; } }
void idea_dec(idea_ctx *c, unsigned char *data, int blocks){ int i; unsigned char *d = data;
for(i=0;i<blocks;i++){
ideaCipher(d,d,c->dk);
d+=8; } }
#include <stdio.h>
#ifndef BLOCKS
#ifndef KBYTES
#define KBYTES 1024
#endif
#define BLOCKS (64*KBYTES)
#endif
int
main(void)
{ /* Test driver for IDEA cipher */
int i, j, k;
idea_ctx c;
byte userkey[16];
word16 EK[IDEAKEYLEN], DK[IDEAKEYLEN];
byte XX[8], YY[8], ZZ[8];
word32 long_block[10]; /* 5 blocks */
long l;
char *lbp;
/* Make a sample user key for testing... */ for(i=0; i<16; i++)
userkey[i] = i+1;
idea_key(&c,userkey);
/* Make a sample plaintext pattern for testing... */ for (k=0; k<8; k++) XX[k] = k;
idea_enc(&c,XX,1); /* encrypt */
lbp = (unsigned char *) long_block;
for(i=0;i<10;i++) long_block[i] = i;
idea_enc(&c,lbp,5);
for(i=0;i<10;i+=2) printf("Block %01d = %08lx %08lx.n",
i/2,long_block[i],long_block[i+1]);
idea_dec(&c,lbp,3); idea_dec(&c,lbp+24,2);
for(i=0;i<10;i+=2) printf("Block %01d = %08lx %08lx.n",
i/2,long_block[i],long_block[i+1]);
return 0; /* normal exit */ } /* main */
GOST
typedef unsigned long u4; typedef unsigned char byte;
typedef struct {
u4 k[8];
/* Constant s-boxes -- set up in gost_init(). */
char k87[256],k65[256],k43[256],k21[256]; } gost_ctx;
/* Note: encrypt and decrypt expect full blocks--padding blocks is
caller's responsibility. All bulk encryption is done in
ECB mode by these calls. Other modes may be added easily
enough. */
void gost_enc(gost_ctx *, u4 *, int);
void gost_dec(gost_ctx *, u4 *, int);
void gost_key(gost_ctx *, u4 *);
void gost_init(gost_ctx *);
void gost_destroy(gost_ctx *);
#ifdef __alpha /* Any other 64-bit machines? */
typedef unsigned int word32;
#else
typedef unsigned long word32;
#endif
kboxinit(gost_ctx *c) {
int i;
byte k8[16] = {14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6,
12, 5, 9, 0, 7 };
byte k7[16] = {15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2,
13, 12, 0, 5, 10 };
byte k6[16] = {10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12,
7, 11, 4, 2, 8 };
byte k5[16] = { 7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8,
5, 11, 12, 4, 15 };
byte k4[16] = { 2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3,
15, 13, 0, 14, 9 };
byte k3[16] = {12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3,
4, 14, 7, 5, 11 };
byte k2[16] = { 4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9,
7, 5, 10, 6, 1 };
byte kl[16] = {13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3,
14, 5, 0, 12, 7 };
for (i = 0; i < 256; i++) {
c->k87[i] = k8[i » 4] « 4 | k7[i & 15];
c->k65[i] = k6[i » 4] « 4 | k5[i & 15];
c->k43[i] = k4[i » 4] « 4 | k3[i & 15];
c->k21[i] = k2[i » 4] « 4 | kl[i & 15];
}
}
static word32 f(gost_ctx *c,word32 x) {
x = c->k87[x»24 & 255] « 24 | c->k65[x»16 & 255] « 16 | c->k43[x» 8 & 255] « 8 | c->k21[x & 255];
/* Rotate left 11 bits */ return x«ll | x» (32-11); }
void gostcrypt(gost_ctx *c, word32 *d){
register word32 nl, n2; /* As named in the GOST */
nl = d[0]; n2 = d[l];
/* Instead of swapping halves, swap names each round */ n2 ë= f(c,nl+c->k[0]); nl Ë= f(ñ,n2+c->k[1]); n2 ë= f(c,nl+c->k[2]); nl ë= f(ñ,n2+c->k[3]); n2 ë= f(c,nl+c->k[4]); nl ë= f(ñ,n2+c->k[5]); ï2 ë= f(c,nl+c->k[6]); nl ë= f(ñ,ï2+ñ->ê[7]);
ï2 ë= f(c,nl+c->k[0]); nl Ë= f(ñ,ï2+ñ->ê[1]);
ï2 ë= f(c,nl+c->k[2]); nl ë= f(ñ,ï2+ñ->ê[3]);
ï2 ë= f(c,nl+c->k[4]); nl ë= f(ñ,ï2+ ñ->ê[5]);
ï2 ë= f(c,nl+c->k[6]); nl ë= f(ñ,ï2+ñ->ê[7]);
ï2 ë= f(c,nl+c->k[0]); nl Ë= f(ñ,ï2+ñ->ê[1]);
ï2 ë= f(c,nl+c->k[2]); nl ë= f(ñ,ï2+ñ->ê[3]);
ï2 ë= f(c,nl+c->k[4]); nl ë= f(ñ,ï2+ñ->ê[5]);
ï2 ë= f(c,nl+c->k[6]); nl ë= f(ñ,ï2+ñ->ê[7]);
ï2 ë= f(c,nl+c->k[7]); nl ë= f(ñ,ï2+ñ->ê[6]);
ï2 ë= f(c,nl+c->k[5]); nl ë= f(ñ,ï2+ñ->ê[4]);
ï2 ë= f(c,nl+c->k[3]); nl ë= f(ñ,ï2+ñ->ê[2]);
ï2 ë= f(c,nl+c->k[l]); nl ë= f(ñ,ï2+ñ->ê[0]);
}
d[0] = n2; d[l] = nl;
void
gostdecrypt(gost_ctx *c, u4 *d){
register word32 nl, n2; /* As named in the GOST */
nl = d[0]; n2 = d[l];
n2 ë= f(c,nl+c->k[0]); nl Ë= f(ñ,n2+c->k[1]); n2 ë= f(c,nl+c->k[2]); nl ë= f(ñ,n2+c->k[3]); n2 ë= f(c,nl+c->k[4]); nl ë= f(ñ,n2+c->k[5]);
ï2 ë= f(c,nl+c->k[6]); nl ë= f(ñ,n2+c->k[7]);
}
ï2 ë= f(c,nl+c->k[7]); nl ë= f(ñ,ï2+ñ->ê[6]);
ï2 ë= f(c,nl+c->k[5]); nl ë= f(ñ,ï2+ñ->ê[4]);
ï2 ë= f(c,nl+c->k[3]); nl ë= f(ñ,ï2+ñ->ê[2]);
ï2 ë= f(c,nl+c->k[l]); nl ë= f(ñ,ï2+ñ->ê[0]);
ï2 ë= f(c,nl+c->k[7]); nl ë= f(ñ,ï2+ñ->ê[6]);
ï2 ë= f(c,nl+c->k[5]); nl ë= f(ñ,ï2+ñ->ê[4]);
ï2 ë= f(c,nl+c->k[3]); nl ë= f(ñ,ï2+ñ->ê[2]);
ï2 ë= f(c,nl+c->k[l]); nl ë= f(ñ,ï2+ñ->ê[0]);
ï2 ë= f(c,nl+c->k[7]); nl ë= f(ñ,ï2+ñ->ê[6]);
ï2 ë= f(c,nl+c->k[5]); nl ë= f(ñ,ï2+ñ->ê[4]);
ï2 ë= f(c,nl+c->k[3]); nl ë= f(ñ,ï2+ñ->ê[2]);
ï2 ë= f(c,nl+c->k[l]); nl ë= f(ñ,ï2+ñ->ê[0]);
d[0] = n2; d[l] = nl;
void gost_enc(gost_ctx *c, u4 *d, int blocks){ int i;
for(i=0;i<blocks;i++){
gostcrypt(c,d);
d+=2; } }
void gost_dec(gost_ctx *c, u4 *d, int blocks){ int i;
for(i=0;i<blocks;i++){
gostdecrypt(c,d);
d+=2; } }
void gost_key(gost_ctx *c, u4 *k){
int i;
for(i=0;i<8;i++) c->k[i]=k[i]; }
void gost_init(gost_ctx *c){
kboxinit(c); }
void gost_destroy(gost_ctx *c){
int i;
for(i=0;i<8;i++) c->k[i]=0; }
void main(void){
gost_ctx gc;
u4 k[8],data[10];
int i;
/* Initialize GOST context. */ gost_init(&gc);
/* Prepare key--a simple key should be OK, with this many rounds! */ for(i=0;i<8;i++) k[i] = i;
gost_key(&gc,k);
/* Try some test vectors. */
data[0] = 0; data[1] = 0;
gostcrypt(&gc,data);
printf("Enc of zero vector: %08lx %08lxn",data[0],data[1]);
gostcrypt(&gc,data);
printf("Enc of above: %08lx %08lxn",data[0],data[1]);
data[0] = 0xffffffff; data[1] = 0xffffffff;
gostcrypt(&gc,data);
printf("Enc of ones vector: %08lx %08lxn",data[0],data[1]);
gostcrypt(&gc,data);
printf("Enc of above: %08lx %08lxn",data[0],data[1]);
/* Does gost_dec() properly reverse gost_enc()? Do
we deal OK with single-block lengths passed in gost_dec()? Do we deal OK with different lengths passed in? */
/* Init data */ for(i=0;i<10;i++) data[i]=i;
/* Encrypt data as 5 blocks. */ gost_enc(&gc,data,5);
/* Display encrypted data. */
for(i=0;i<10;i+=2) printf("Block %02d = %08lx %08lxn",
i/2,data[i],data[i+1]);
/* Decrypt in different sized chunks. */
gost_dec(&gc,data,1);
gost_dec(&gc,data+2,4);
printf("n");
/* Display decrypted data. */
for(i=0;i<10;i+=2) printf("Block %02d = %08lx %08lxn",
i/2,data[i],data[i+1]);
gost_destroy(&gc);
WAY
#define STRT_E 0x0b0b /* round constant of first encryption round */
#define STRT_D 0xb1b1 /* round constant of first decryption round */
#define NMBR 11 /* number of rounds is 11 */
typedef unsigned long int word32 ;
/* the program only works correctly if long = 32bits */ typedef unsigned long u4; typedef unsigned char u1;
typedef struct {
u4 k[3],ki[3], ercon[NMBR+1],drcon[NMBR+1]; } twy_ctx;
/* Note: encrypt and decrypt expect full blocks--padding blocks is
caller's responsibility. All bulk encryption is done in
ECB mode by these calls. Other modes may be added easily
enough. */
/* destroy: Context. */
/* Scrub context of all sensitive data. */
void twy_destroy(twy_ctx *);
/* encrypt: Context, ptr to data block, # of blocks. */ void twy_enc(twy_ctx *, u4 *, int);
/* decrypt: Context, ptr to data block, # of blocks. */ void twy_dec(twy_ctx *, u4 *, int);
/* key: Context, ptr to key data. */ void twy_key(twy_ctx *, u4 *);
/* ACCODE --------------------------------------------------------- */
/* End of AC code prototypes and structures. */
/* ---------------------------------------------------------------- */
void mu(word32 *a) /* inverts the order of the bits of a */
{
int i ;
word32 b[3] ;
b[0] = b[1] = b[2] = 0 ; for( i=0 ; i<32 ; i++ )
{
b[0] <<= 1 ; b[1] <<= 1 ; b[2] <<= 1 ;
if(a[0]&1) b[2] |= 1 ;
if(a[1]&1) b[1] |= 1 ;
if(a[2]&l) b[0] |= 1 ;
a[0] »= 1 ; a[l] »= 1 ; a[2] »= 1 ;
}
a[0] = b[0] ; a[l] = b[l] ; a[2] = b[2] ; }
void gamma(word32 *a) /* the nonlinear step */
{
word32 b[3] ;
b[0] = a[0] ^ (a[1]|(~a[2])) ; b[1] = a[1] ^ (a[2]|(~a[0])) ; b[2] = a[2] ^ (a[0]|(~a[1])) ;
a[0] = b[0] ; a[1] = b[1] ; a[2] = b[2] ; }
void theta(word32 *a) /* the linear step */
{
word32 b[3];
b[0] = a[0] ë (à[0]»16) ë (à[1]«16) ë (à[1]»16) ë (à[2]«16) ë
(a[l]»24) ë (à[2]«8) ë (à[2]»8) ë (à[0]«24) ë
(a[2]»16) ë (à[0]«16) ë (à[2]»24) ë (à[0]«8)
b[l] = a[l] ë (à[1]»16) ë (à[2]«16) ë (à[2]»16) ë (à[0]«16) ë
(a[2]»24) ë (à[0]«8) ë (à[0]»8) ë (à[1]«24) ë
(a[0]»16) ë (à[1]«16) ë (à[0]»24) ë (à[1]«8)
b[2] = a[2] ë (à[2]»16) ë (à[0]«16) ë (à[0]»16) ë (à[1]«16) ë
(a[0]»24) ë (à[1]«8) ë (à[1]»8) ë (à[2]«24) ë
(a[l]»16) ë (à[2]«16) ë (à[1]»24) ë (à[2]«8)
a[0] = b[0] ; a[l] = b[l] ; a[2] = b[2] ; }
void pi_l(word32 *a)
{
a[0] = (a[0]»10) ë (à[0]«22);
a[2] = (a[2]«l) ë (à[2]»31);
}
void pi_2(word32 *a)
{
a[0] = (à[0]«1) ë (à[0]»31);
a[2] = (a[2]»10) ë (à[2]«22);
}
void rho(word32 *a) /* the round function */
{
theta(a) ;
pi_l(a) ;
gamma(a) ;
pi_2(a) ;
}
void rndcon_gen(word32 strt,word32 *rtab)
{ /* generates the round constants */
int i ;
for(i=0 ; i<=NMBR ; i++ )
{
rtab[i] = strt ; strt «= 1 ;
if( strt&OxlOOOO ) strt ë= OxllOll ; } }
/* Modified slightly to fit the caller's needs. */
void encrypt(twy_ctx *c, word32 *a)
{
char i ;
for( i=0 ; KNMBR ; i++ )
{
a[0] ë= ñ->ê[0] ë (c->ercon[i]«16) ;
a[l] ë= ñ->ê[1] ;
a[2] ë= ñ->ê[2] ë c->ercon[i] ;
rho(a) ;
} a[0] ë= ñ->ê[0] ë (c->ercon[NMBR]«16) ; a[l] ë= ñ->ê[1] ;
a[2] ë= ñ->ê[2] ë c->ercon[NMBR] ; theta(a) ; }
/* Modified slightly to meet caller's needs. */
void decrypt(twy_ctx *c, word32 *a)
{
char i ;
rau(a) ;
for( i=0 ; KNMBR ; i++ )
{
a[0] ë= c->ki[0] Ë (c->drcon[i]«16) ;
a[l] ë= c->ki[l] ;
a[2] ë= c->ki[2] ë c->drcon[i] ;
rho(a) ;
} a[0] ë= c->ki[0] Ë (c->drcon[NMBR]«16) ; a[l] ë= c->ki[l] ;
a[2] ë= c->ki[2] ë c->drcon[NMBR] ; theta(a) ; rau(a) ; }
void twy_key(twy_ctx *c, u4 *key){
c->ki[0] = c->k[0] = key[0];
c->ki[l] = c->k[l] = key[l];
c->ki[2] = c->k[2] = key[2];
theta(c->ki);
mu(c->ki);
rndcon_gen(STRT_E,c->ercon);
rndcon_gen(STRT_D,c->drcon);
}
/* Encrypt in ECB mode. */
void twy_enc(twy_ctx *c, u4 *data, int blkcnt){
u4 *d;
int i;
d = data; for(i=0;i<blkcnt;i++) {
encrypt(c,d); d +=3; } }
/* Decrypt in ECB mode. */
void twy_dec(twy_ctx *c, u4 *data, int blkcnt){
u4 *d;
int i;
d = data; for(i=0;i<blkcnt;i++){
decrypt(c,d);
d+=3; } }
/* Scrub sensitive values from memory before deallocating. */ void twy_destroy(twy_ctx *c){ int i;
for(i=0;i<3;i++) c->k[i] = c->ki[i] = 0; }
void printvec(char *chrs, word32 *d){
printf("%20s : %08lx %08lx %08lx n",chrs,d[2],d[1],d[0]); }
main()
{
twy_ctx gc;
word32 a[9],k[3];
int i;
/* Test vector 1. */
k[0]=k[1]=k[2]=0; a[0]=a[1]=a[2]=1; twy_key(&gc,k);
printf("**********n"); printvec("KEY = ",k); printvec("PLAIN = ",a); encrypt(&gc,a); printvec("CIPHER = ",a);
/* Test vector 2. */
k[0]=6;k[1]=5;k[2]=4; a[0]=3;a[1]=2;a[2]=1; twy_key(&gc,k);
printf("**********n"); printvec("KEY = ",k); printvec("PLAIN = ",a); encrypt(&gc,a); printvec("CIPHER = ",a);
/* Test vector 3. */
k[2]=0xbcdef012;k[1]=0x456789ab;k[0]=0xdef01234; a[2]=0x01234567;a[1]=0x9abcdef0;a[0]=0x23456789; twy_key(&gc,k);
printf("**********n"); printvec("KEY = ",k); printvec("PLAIN = ",a); encrypt(&gc,a); printvec("CIPHER = ",a);
/* Test vector 4. */
k[2]=0xcab920cd;k[1]=0xd6144138;k[0]=0xd2f05b5e; a[2]=0xad21ecf7;a[1]=0x83ae9dc4;a[0]=0x4059c76e; twy_key(&gc,k);
printf("**********n"); printvec("KEY = ",k); printvec("PLAIN = ",a); encrypt(&gc,a); printvec("CIPHER = ",a);
/* TEST VALUES
key : 00000000 00000000 00000000 plaintext : 00000001 00000001 00000001 ciphertext : ad21ecf7 83ae9dc4 4059c76e
key : 00000004 00000005 00000006 plaintext : 00000001 00000002 00000003 ciphertext : cab920cd d6144138 d2f05b5e
key : bcdef012 456789ab def01234 plaintext : 01234567 9abcdef0 23456789 ciphertext : 7cdb76b2 9cdddb6d 0aa55dbb
key : cab920cd d6144138 d2f05b5e plaintext : ad21ecf7 83ae9dc4 4059c76e ciphertext : 15b155ed 6b13f17c 478ea871
*/
/* Enc/dec test: */ for(i=0;i<9;i++) a[i]=i; twy_enc(&gc,a,3);
for(i=0;i<9;i+=3) printf("Block %01d encrypts to %08lx %08lx %08lxn",
i/3,a[i],a[i+1],a[i+2]);
twy_dec(&gc,a,2); twy_dec(&gc,a+6,1);
for(i=0;i<9;i+=3) printf("Block %01d decrypts to %08lx %08lx %08lxn",
i/3,a[i],a[i+1],a[i+2]); }
RC5
#include <stdio.h>
/* An RC5 context needs to know how many rounds it has, and its subkeys. */ typedef struct {
u4 *xk;
int nr; } rc5_ctx;
/* Where possible, these should be replaced with actual rotate instructions. For Turbo C++, this is done with _lrotl and _lrotr. */
#define ROTL32(X,C) (((X)<<(C))|((X)>>(32-(C)))) #define ROTR32(X,C) (((X)>>(C))|((X)<<(32-(C))))
/* Function prototypes for dealing with RC5 basic operations. */
void rc5_init(rc5_ctx *, int);
void rc5_destroy(rc5_ctx *);
void rc5_key(rc5_ctx *, u1 *, int);
void rc5_encrypt(rc5_ctx *, u4 *, int);
void rc5_decrypt(rc5_ctx *, u4 *, int);
/* Function implementations for RC5. */
/* Scrub out all sensitive values. */ void rc5_destroy(rc5_ctx *c){ int i;
for(i=0;i<(c->nr)*2+2;i++) c->xk[i]=0;
free(c->xk); }
/* Allocate memory for rc5 context's xk and such. */ void rc5_init(rc5_ctx *c, int rounds){
c->nr = rounds;
c->xk = (u4 *) malloc(4*(rounds*2+2)); }
void rc5_encrypt(rc5_ctx *c, u4 *data, int blocks){ u4 *d,*sk; int h,i,rc;
d = data;
sk = (c->xk)+2; for(h=0;h<blocks;h++){
d[0] += c->xk[0]; d[1] += c->xk[1]; for(i=0;i<c->nr*2;i+=2){ d[0] ^= d[1]; rc = d[1] & 31; d[0] = ROTL32(d[0],rc); d[0] += sk[i]; d[1] ^= d[0];
rc = d[0] & 31; d[1] = ROTL32(d[1],rc); d[1] += sk[i+1]; /*printf("Round %03d : %08lx %08lx sk= %08lx %08lxn",i/2,
d[0],d[1],sk[i],sk[i+1]);*/ } d+=2; }
}
void rc5_decrypt(rc5_ctx *c, u4 *data, int blocks){ u4 *d,*sk;
int h,i,rc;
d = data;
sk = (c->xk)+2; for(h=0;h<blocks;h++){
for(i=c->nr*2-2;i>=0;i-=2){ /*printf("Round %03d: %08lx %08lx sk: %08lx %08lxn", i/2,d[0],d[1],sk[i],sk[i+1]); */ d[1] -= sk[i+1]; rc = d[0] & 31; d[1] = ROTR32(d[1],rc); d[1] ^= d[0];
d[0] -= sk[i]; rc = d[1] & 31; d[0] = ROTR32(d[0],rc); d[0] ^= d[1]; }
d[0] -= c->xk[0]; d[1] -= c->xk[1]; d+=2; } }
void rc5_key(rc5_ctx *c, u1 *key, int keylen){ u4 *pk,A,B; /* padded key */ int xk_len, pk_len, i, num_steps,rc; u1 *cp;
xk_len = c->nr*2 + 2; pk_len = keylen/4; if((keylen%4)!=0) pk_len += 1;
pk = (u4 *) malloc(pk_len * 4); if(pk==NULL) {
printf("An error occurred!n");
exit(-1); }
/* Initialize pk -- this should work on Intel machines, anyway.... */ for(i=0;i<pk_len;i++) pk[i]=0; cp = (u1 *)pk; for(i=0;i<keylen;i++) cp[i]=key[i];
/* Initialize xk. */
c->xk[0] = 0xb7e15163; /* P32 */
for(i=1;i<xk_len;i++) c->xk[i] = c->xk[i-1] + 0x9e3779b9; /* Q32 */
/* TESTING */ A = B = 0; for(i=0;i<xk_len;i++) {
A = A + c->xk[i];
B = B ^ c->xk[i]; }
/* Expand key into xk. */
if(pk_len>xk_len) num_steps = 3*pk_len;else num_steps = 3*xk_len;
A = B = 0; for(i=0;i<num_steps;i++){
A = c->xk[i%xk_len] = ROTL32(c->xk[i%xk_len] + A + B,3);
rc = (A+B) & 31;
B = pk[i%pk_len] = ROTL32(pk[i%pk_len] + A + B,rc);
}
/* Clobber sensitive data before deallocating memory. */ for(i=0;i<pk_len;i++) pk[i] =0;
free(pk); }
void main(void){ rc5_ctx c; u4 data[8]; char key[] = "ABCDE"; int i;
printf(" ----------------------------------------------- n");
for(i=0;i<8;i++) data[i] = i; rc5_init(&c,10); /* 10 rounds */ rc5_key(&c,key,5);
rc5_encrypt(&c,data,4);
printf("Encryptions:n");
for(i=0;i<8;i+=2) printf("Block %01d = %08lx %08lxn",
i/2,data[i],data[i+1]); rc5_decrypt(&c,data,2); rc5_decrypt(&c,data+4,2); printf("Decryptions:n"); for(i=0;i<8;i+=2) printf("Block %01d = %08lx %08lxn",
i/2,data[i],data[i+1]);
}
À5
typedef struct {
unsigned long r1,r2,r3; } a5_ctx;
static int threshold(r1, r2, r3)
unsigned int r1;
unsigned int r2;
unsigned int r3;
{
int total;
total = (((r1 >> 9) & 0x1) == 1) + (((r2 >> 11) & 0x1) == 1) + (((r3 >> 11) & 0x1) == 1);
if (total > 1)
return (0); else
return (1); }
unsigned long clock_r1(ctl, r1)
int ctl;
unsigned long r1;
{
unsigned long feedback;
ctl ^= ((r1 >> 9) & 0x1);
if (ctl)
{
feedback = (r1 >> 18) ^ (r1 >> 17) ^ (r1 >> 16) ^ (r1 >> 13);
r1 = (r1 << 1) & 0x7ffff;
if (feedback & 0x01) r1 ^= 0x01; }
return (r1); }
unsigned long clock_r2(ctl, r2)
int ctl;
unsigned long r2;
{
unsigned long feedback;
ctl ^= ((r2 >> 11) & 0x1);
if (ctl)
{
feedback = (r2 >> 21) ^ (r2 >> 20) ^ (r2 >> 16) ^ (r2 >> 12);
r2 = (r2 << 1) & 0x3fffff;
if (feedback & 0x01) r2 ^= 0x01; }
return (r2); }
unsigned long clock_r3(ctl, r3)
int ctl;
unsigned long r3;
{
unsigned long feedback;
ctl ^= ((r3 >> 11) & 0x1);
if (ctl)
{
feedback = (r3 >> 22) ^ (r3 >> 21) ^ (r3 >> 18) ^ (r3 >> 17);
r3 = (r3 << 1) & 0x7fffff;
if (feedback & 0x01) r3 ^= 0x01; }
return (r3); }
int keystream(key, frame, alice, bob)
unsigned char *key; /* 64 bit session key */
unsigned long frame; /* 22 bit frame sequence number */
unsigned char *alice; /* 114 bit Alice to Bob key stream */
unsigned char *bob; /* 114 bit Bob to Alice key stream */
{
unsigned long r1; /* 19 bit shift register */
unsigned long r2; /* 22 bit shift register */
unsigned long r3; /* 23 bit shift register */
int i; /* counter for loops */
int clock_ctl; /* xored with clock enable on each shift register */
unsigned char *ptr; /* current position in keystream */
unsigned char byte; /* byte of keystream being assembled */
unsigned int bits; /* number of bits of keystream in byte */
unsigned int bit; /* bit output from keystream generator */
/* Initialise shift registers from session key */
r1 = (key[0] | (key[1] << 8) | (key[2] << 16) ) & 0x7ffff; r2 = ((key[2] >> 3) | (key[3] << 5) | (key[4] << 13) | (key[5] << 21)) & 0x3fffff;
r3 = ((key[5] >> 1) | (key[6] << 7) | (key[7] << 15) ) & 0x7fffff;
/* Merge frame sequence number into shift register state, by xor'ing it
* into the feedback path
*/
for (i=0;i<22;i++) {
clock_ctl = threshold(r1, r2, r2); r1 = clock_r1(clock_ctl, r1); r2 = clock_r2(clock_ctl, r2); r3 = clock_r3(clock_ctl, r3); if (frame & 1) {
r1 ^= 1; r2 ^= 1; r3 ^= 1; }
frame = frame >> 1; }
/* Run shift registers for 100 clock ticks to allow frame number to
* be diffused into all the bits of the shift registers
*/
for (i=0;i<100;i++) {
clock_ctl = threshold(r1, r2, r2);
r1 = clock_r1(clock_ctl, r1);
r2 = clock_r2(clock_ctl, r2);
r3 = clock_r3(clock_ctl, r3); }
/* Produce 114 bits of Alice->Bob key stream */
ptr = alice;
bits = 0;
byte = 0;
for (i=0;i<114;i++)
{
clock_ctl = threshold(r1, r2, r2);
r1 = clock_r1(clock_ctl, r1);
r2 = clock_r2(clock_ctl, r2);
r3 = clock_r3(clock_ctl, r3);
bit = ((r1 >> 18) ^ (r2 >> 21) ^ (r3 >> 22)) & 0x01;
byte = (byte << 1) | bit;
bits++;
if (bits == 8) {
*ptr = byte;
ptr++;
bits = 0;
byte = 0; } } if (bits)
*ptr = byte;
/* Run shift registers for another 100 bits to hide relationship between * Alice->Bob key stream and Bob->Alice key stream. */
for (i=0;i<100;i++) {
clock_ctl = threshold(r1, r2, r2);
r1 = clock_r1(clock_ctl, r1);
r2 = clock_r2(clock_ctl, r2);
r3 = clock_r3(clock_ctl, r3); }
/* Produce 114 bits of Bob->Alice key stream */
ptr = bob;
bits = 0;
byte = 0;
for (i=0;i<114;i++)
{
clock_ctl = threshold(r1, r2, r2);
r1 = clock_r1(clock_ctl, r1);
r2 = clock_r2(clock_ctl, r2);
r3 = clock_r3(clock_ctl, r3);
bit = ((r1 >> 18) ^ (r2 >> 21) ^ (r3 >> 22)) & 0x01;
byte = (byte << 1) | bit;
bits++;
if (bits == 8)
{
*ptr = byte;
ptr++;
bits = 0;
byte = 0; } } if (bits)
*ptr = byte;
return (0);
}
void a5_key(a5_ctx *c, char *k){
c->r1 = k[0]<<11|k[1]<<3 | k[2]>>5 ; /* 19 */
c->r2 = k[2]<<17|k[3]<<9 | k[4]<<1 | k[5]>>7; /* 22 */
c->r3 = k[5]<<15|k[6]<<8 | k[7] ; /* 23 */
}
/* Step one bit in A5, return 0 or 1 as output bit. */ int a5_step(a5_ctx *c){ int control;
control = threshold(c->r1,c->r2,c->r3); c->r1 = clock_r1(control,c->r1); c->r2 = clock_r2(control,c->r2); c->r3 = clock_r3(control,c->r3); return( (c->r1^c->r2^c->r3)&1); }
/* Encrypts a buffer of len bytes. */
void a5_encrypt(a5_ctx *c, char *data, int len){
int i,j;
char t;
for(i=0;i<len;i++){
for(j=0;j<8;j++) t = t<<1 | a5_step(c);
data[i]^=t; } }
void a5_decrypt(a5_ctx *c, char *data, int len){
a5_encrypt(c,data,len); }
void main(void){ a5_ctx c; char data[100];
char key[] = {1,2,3,4,5,6,7,8}; int i,flag;
for(i=0;i<100;i++) data[i] = i;
a5_key(&c,key); a5_encrypt(&c,data,100);
a5_key(&c,key);
a5_decrypt(&c,data,1);
a5_decrypt(&c,data+1,99);
flag = 0;
for(i=0;i<100;i++) if(data[i]!=i)flag = 1;
if(flag)printf("Decrypt failedn"); else printf("Decrypt succeededn"); }
SEAL
#undef SEAL_DEBUG
#define ALG_OK 0
#define ALG_NOTOK 1
#define WORDS_PER_SEAL_CALL 1024
typedef struct {
unsigned long t[520]; /* 512 rounded up to a multiple of 5 + 5*/ unsigned long s[265]; /* 256 rounded up to a multiple of 5 + 5*/ unsigned long r[20]; /* 16 rounded up to multiple of 5 */ unsigned long counter; /* 32-bit synch value. */ unsigned long ks_buf[WORDS_PER_SEAL_CALL]; int ks_pos; } seal_ctx;
#define R0T2(x) (((x) » 2) | ((x) « 30))
#define ROT9(x) (((x) » 9) | ((x) « 23))
#define ROT8(x) (((x) » 8) | ((x) « 24))
#define ROT16(x) (((x) » 16) | ((x) « 16))
#define ROT24(x) (((x) » 24) | ((x) « 8))
#define ROT27(x) (((x) » 27) | ((x) « 5))
#define WORD(cp) ((cp[0] << 24)|(cp[l] << 16)|(cp[2] << 8)|(cp[3]))
#define Fl(x, y, z) (((x) & (y)) | ((~(x)) & (z)))
tdefme F2(x, y, z) ((x) ë (ó) ë (z))
#define F3(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z)))
tdefme F4(x, y, z) ((x) ë (ó) ë (z))
int g(in, i, h) unsigned char *in; int i;
unsigned long *h; {
unsigned long hO; unsigned long hi; unsigned long h2; unsigned long h3; unsigned long h4; unsigned long a; unsigned long b; unsigned long c; unsigned long d; unsigned long e; unsigned char *kp; unsigned long w[80]; unsigned long temp;
kp = in;
hO = WORD(kp); kp += 4;
hi = WORD(kp); kp += 4;
h2 = WORD(kp); kp += 4;
h3 = WORD(kp); kp += 4;
h4 = WORD(kp); kp += 4;
w[0] = i;
for (i=l;i<16;i++)
w[i] = 0; for (i=16;i<80;i++)
w[i] = w[i-3]Aw[i-8]Aw[i-14]Aw[i-16];
a = hO;
b = hi;
ñ = h2;
d = h3;
e = h4;
for (i=0;i<20;i++) {
temp = ROT27(a) + Fl(b, c, d) + e + w[i] + 0x5a827999;
e = d;
d = c;
ñ = ROT2(b);
b = a;
a = temp; }
}
for (i=20;i<40;i++) {
temp = ROT27(a) + F2(b, c, d) + e + w[i] + 0x6ed9ebal;
e = d;
d = c;
ñ = R0T2(b);
b = a;
a = temp; }
for (i=40;i<60;i++) {
temp = ROT27(a) + F3(b, c, d) + e + w[i] + 0x8flbbcdc;
e = d;
d = c;
ñ = R0T2(b);
b = a;
a = temp; }
for (i=60;i<80;i++) {
temp = ROT27(a) + F4(b, c, d) + e + w[i] + 0xca62cld6;
e = d;
d = c;
ñ = R0T2(b);
b = a;
a = temp; }
h[0] = hO+a; h[l] = hl+b; h[2] = h2+c; h[3] = h3+d; h[4] = h4+e;
return (ALG_OK);
unsigned long gamma(a, i)
unsigned char *a;
int i;
{
unsigned long h[5];
(void) g(a, i/5, h); return h[i % 5]; }
int seal_init(seal_ctx *result, unsigned char *key)
{
int i;
unsigned long h[5];
for (i=0;i<510;i+=5)
g(key, i/5, &(result->t[i])); /* horrible special case for the end */ g(key, 510/5, h); for (i=510;i<512;i++)
result->t[i] = h[i-510]; /* 0x1000 mod 5 is +1, so have horrible special case for the start */ g(key, (-1+0x1000)/5, h); for (i=0;i<4;i++)
result->s[i] = h[i+1]; for (i=4;i<254;i+=5)
g(key, (i+0x1000)/5, &(result->s[i])); /* horrible special case for the end */ g(key, (254+0x1000)/5, h); for (i=254;i<256;i++)
result->s[i] = h[i-254]; /* 0x2000 mod 5 is +2, so have horrible special case at the start */ g(key, (-2+0x2000)/5, h); for (i=0;i<3;i++)
result->r[i] = h[i+2]; for (i=3;i<13;i+=5)
g(key, (i+0x2000)/5, &(result->r[i])); /* horrible special case for the end */ g(key, (13+0x2000)/5, h); for (i=13;i<16;i++)
result->r[i] = h[i-13]; return (ALG_OK); }
int seal(seal_ctx *key, unsigned long in, unsigned long *out)
{
int i;
int j;
int l;
unsigned long a;
unsigned long b;
unsigned long c;
unsigned long d;
unsigned short p;
unsigned short q;
unsigned long n1;
unsigned long n2;
unsigned long n3;
unsigned long n4;
unsigned long *wp;
wp = out;
for (l=0;l<4;l++) {
a = in ^ key->r[4*l];
b = ROT8(in) ^ key->r[4*l+1];
c = ROT16(in) ^ key->r[4*l+2];
d = ROT24(in) ^ key->r[4*l+3];
for (j=0;j<2;j++) {
p = a & 0x7fc;
b += key->t[p/4];
a = ROT9(a);
p = b & 0x7fc; c += key->t[p/4]; b = ROT9(b);
p = c & 0x7fc; d += key->t[p/4]; c = ROT9(c);
p = d & 0x7fc; a += key->t[p/4]; d = ROT9(d);
}
n1 = d; n2 = b; n3 = a; n4 = c;
p = a & 0x7fc; b += key->t[p/4]; a = ROT9(a);
p = b & 0x7fc; c += key->t[p/4]; b = ROT9(b);
p = c & 0x7fc; d += key->t[p/4]; c = ROT9(c);
p = d & 0x7fc; a += key->t[p/4]; d = ROT9(d);
/* This generates 64 32-bit words, or 256 bytes of keystream. */ for (i=0;i<64;i++) {
p = a & 0x7fc;
b += key->t[p/4];
a = ROT9(a);
b ^= a;
q = b & 0x7fc; c ^= key->t[q/4]; b = ROT9(b); c += b;
p = (p+c) & 0x7fc; d += key->t[p/4]; c = ROT9(c); d ^= c;
q = (q+d) & 0x7fc; a ^= key->t[q/4]; d = ROT9(d); a += d;
p = (p+a) & 0x7fc; b ^= key->t[p/4]; a = ROT9(a);
q = (q+b) & 0x7fc; c += key->t[q/4]; b = ROT9(b);
p = (p+c) & 0x7fc; d ^= key->t[p/4]; c = ROT9(c);
q = (q+d) & 0x7fc; a += key->t[q/4]; d = ROT9(d);
*wp = b + key->s[4*i];
wp++;
*wp = c ^ key->s[4*i+1];
wp++;
*wp = d + key->s[4*i+2];
wp++;
*wp = a ^ key->s[4*i+3];
wp++;
if (i & 1) {
a += n3;
c += n4; }
else {
a += n1;
c += n2; }
} }
return (ALG_OK); }
/* Added call to refill ks_buf and reset counter and ks_pos. */ void seal_refill_buffer(seal_ctx *c){
seal(c,c->counter,c->ks_buf);
c->counter++;
c->ks_pos = 0; }
void seal_key(seal_ctx *c, unsigned char *key){
seal_init(c,key);
c->counter = 0; /* By default, init to zero. */
c->ks_pos = WORDS_PER_SEAL_CALL;
/* Refill keystream buffer on next call. */ }
/* This encrypts the next w words with SEAL. */ void seal_encrypt(seal_ctx *c, unsigned long *data_ptr, int w){ int i;
for(i=0;i<w;i++){
if(c->ks_pos>=WORDS_PER_SEAL_CALL) seal_refill_buffer(c);
data_ptr[i]^=c->ks_buf[c->ks_pos];
c->ks_pos++; } }
void seal_decrypt(seal_ctx *c, unsigned long *data_ptr, int w) {
seal_encrypt(c,data_ptr,w); }
void seal_resynch(seal_ctx *c, unsigned long synch_word){
c->counter = synch_word;
c->ks_pos = WORDS_PER_SEAL_CALL; }
void main(void){
seal_ctx sc;
unsigned long buf[1000],t;
}
int i,flag;
unsigned char key[] =
{0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19};
printf("1n"); seal_key(&sc,key);
printf("2n");
for(i=0;i<1000;i++) buf[i]=0;
printf("3n");
seal_encrypt(&sc,buf,1000);
printf("4n");
t = 0;
for(i=0;i<1000;i++) t = t ^ buf[i];
printf("XOR of buf is %08lx.n",t);
seal_key(&sc,key);
seal_decrypt(&sc,buf,1);
seal_decrypt(&sc,buf+1,999);
flag = 0;
for(i=0;i<1000;i++) if(buf[i]!=0)flag=1;
if(flag) printf("Decrypt failed.n");
else printf("Decrypt succeeded.n");