svn: ecrypt/trunk/submissions/polarbear/polar-bear.c
File:
[svn] /
ecrypt /
trunk /
submissions /
polarbear / polar-bear.c
(
download)
(
as text)
Revision:
69,
Sun Aug 21 15:49:35 2005 UTC (7 years, 9 months ago) by
cdecanni
File size: 13836 byte(s)
* fixed endianness problems and a bug in the debugging code.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include "ecrypt-sync.h"
/* "Polar Bear" stream cipher implementaion */
/* This code is provided "as is" with no warranty or */
/* support. Requires a (slightly modified) Rijndael */
/* (see documentation and "readme.txt"). */
#include "aes.h"
#include "aestab.c"
#include "aeskey.c"
#include "aescrypt.c"
/* Define this flag to get debug printouts */
#undef CIPHER_DEBUG
#ifdef ECRYPT_API
#undef CIPHER_DEBUG
#endif
/* Multiplication in GF(2^16) */
#define GF216MUL(x,y) ALOG[(DLOG[(x)] + DLOG[(y)]) % 0xffff]
#define GF216MUL2(TL,TH,x) (TL[x & 0xff] ^ TH[x >> 8])
/* Multiplication in GF(2^16) by pre.computed DLOG */
#define GF216DMUL(d,x) ALOG[(DLOG[(x)] + d) % 0xffff]
/* Multiplies v(y), corresponding to a polynomial over GF(2^16),
by y where GF(2^16) is defined by
y^16 = y^8 + y^7 + y^5 + 1 = 0x1a1 */
#define YTIMES(v) (((v & 0x7fff) << 1) ^ (((v & 0x8000) >> 15)*0x1a1))
/* Steps LFSR R0 once */
/* Poly: 23787 x^7 + 35674 x^6 + 1 */
#define STEP_R0 {\
c = R0[0];\
R0[0] = R0[1];\
R0[1] = R0[2];\
R0[2] = R0[3];\
R0[3] = R0[4];\
R0[4] = R0[5];\
R0[5] = R0[6];\
R0[6] = GF216MUL2(TL00,TH00,c) ^ GF216MUL2(TL01,TH01,R0[0]);\
}
/* Steps LFSR R1 once */
/* Poly: 11362 x^9 + 26778 x^4 + 1 */
#define STEP_R1 {\
c = R1[0];\
R1[0] = R1[1];\
R1[1] = R1[2];\
R1[2] = R1[3];\
R1[3] = R1[4];\
R1[4] = R1[5];\
R1[5] = R1[6];\
R1[6] = R1[7];\
R1[7] = R1[8];\
R1[8] = GF216MUL2(TL10,TH10,c) ^ GF216MUL2(TL11,TH11,R1[4]);\
}
/* Init of S-box on each message */
#define InitD8(tab) memcpy(tab, T8_init, 256)
u16 T, ALOG[265536], DLOG[65536];
u16 TL00[256],TH00[256], TL01[256],TH01[256],
TL10[256],TH10[256], TL11[256],TH11[256];
char init_done = 0;
/* S-box, taken from AES */
static u8 T8_init[256] = {
99, 124, 119, 123, 242, 107, 111, 197, 48, 1, 103, 43, 254, 215, 171, 118,
202, 130, 201, 125, 250, 89, 71, 240, 173, 212, 162, 175, 156, 164, 114, 192,
183, 253, 147, 38, 54, 63, 247, 204, 52, 165, 229, 241, 113, 216, 49, 21,
4, 199, 35, 195, 24, 150, 5, 154, 7, 18, 128, 226, 235, 39, 178, 117,
9, 131, 44, 26, 27, 110, 90, 160, 82, 59, 214, 179, 41, 227, 47, 132,
83, 209, 0, 237, 32, 252, 177, 91, 106, 203, 190, 57, 74, 76, 88, 207,
208, 239, 170, 251, 67, 77, 51, 133, 69, 249, 2, 127, 80, 60, 159, 168,
81, 163, 64, 143, 146, 157, 56, 245, 188, 182, 218, 33, 16, 255, 243, 210,
205, 12, 19, 236, 95, 151, 68, 23, 196, 167, 126, 61, 100, 93, 25, 115,
96, 129, 79, 220, 34, 42, 144, 136, 70, 238, 184, 20, 222, 94, 11, 219,
224, 50, 58, 10, 73, 6, 36, 92, 194, 211, 172, 98, 145, 149, 228, 121,
231, 200, 55, 109, 141, 213, 78, 169, 108, 86, 244, 234, 101, 122, 174, 8,
186, 120, 37, 46, 28, 166, 180, 198, 232, 221, 116, 31, 75, 189, 139, 138,
112, 62, 181, 102, 72, 3, 246, 14, 97, 53, 87, 185, 134, 193, 29, 158,
225, 248, 152, 17, 105, 217, 142, 148, 155, 30, 135, 233, 206, 85, 40, 223,
140, 161, 137, 13, 191, 230, 66, 104, 65, 153, 45, 15, 176, 84, 187, 22
};
/* Initiates tables for GF(2^16) arithmetic */
void ECRYPT_init(void) {
u16 g;
int i;
#ifdef CIPHER_DEBUG
fprintf(stderr,"Builiding tables...\n");
#endif
if (!init_done) {
for (i = 0; i <= 0xffff; i++)
DLOG[i] = ALOG[i] = 0;
g = 1;
DLOG[g] = 0;
ALOG[0] = 1;
for (i = 1; i < 0xffff; i++) {
g = YTIMES(g); /* g = g*y; */
if (DLOG[g] || ALOG[i])
fprintf(stderr,"Table error, collision, i = %04x\n",i);
DLOG[g] = i;
ALOG[i] = g;
}
for (i = 1; i < 0xffff; i++)
if (!(DLOG[g] && ALOG[i]))
fprintf(stderr,"Table error, empty\n");
for (i = 0; i <= 0xff; i++) {
g = (DLOG[i] + DLOG[23787]) % 0xffff;
TL00[i] = ALOG[g];
TH00[i] = ALOG[(g + 8) % 0xffff];
g = (DLOG[i] + DLOG[35674]) % 0xffff;
TL01[i] = ALOG[g];
TH01[i] = ALOG[(g + 8) % 0xffff];
g = (DLOG[i] + DLOG[11362]) % 0xffff;
TL10[i] = ALOG[g];
TH10[i] = ALOG[(g + 8) % 0xffff];
g = (DLOG[i] + DLOG[26778]) % 0xffff;
TL11[i] = ALOG[g];
TH11[i] = ALOG[(g + 8) % 0xffff];
}
/* Poly: 11362 x^9 + 26778 x^4 + 1 */
/*
g = 23787;
gi = DLOG[g];
fprintf(stderr,"%04x: log = %04x,\n",g,gi);
g = 35674;
gi = DLOG[g];
fprintf(stderr,"%04x: log = %04x,\n",g,gi);
g = 11362;
gi = DLOG[g];
fprintf(stderr,"%04x: log = %04x,\n",g,gi);
g = 26778;
gi = DLOG[g];
fprintf(stderr,"%04x: log = %04x,\n",g,gi);
*/
init_done = 1;
}
}
/* Computes Polar Bear key schedule, done once per key */
/* memory is alloacted and a pointer is returned */
void ECRYPT_keysetup(
ECRYPT_ctx* ctx,
const u8* key,
u32 keysize, /* Key size in bits. */
u32 ivsize) /* IV size in bits. */
{
#ifdef CIPHER_DEBUG
int j;
#endif
if (keysize != 128) {
fprintf(stderr,"Key size not implemented\n");
exit(1);
}
if (!init_done)
ECRYPT_init();
#ifdef CIPHER_DEBUG
fprintf(stderr,"input key (len = %d): ",keysize);
for (j = 0; j < keysize/8; j++)
fprintf(stderr," %02x",key[j]);
fprintf(stderr,"\n");
#endif
ctx->ivsize = ivsize;
aes_enc_key(key, keysize/8, &ctx->ks);
#ifdef CIPHER_DEBUG
fprintf(stderr,"aes ctx:\n");
fprintf(stderr,"n_rounds %d\n",ctx->ks.n_rnd);
fprintf(stderr,"n_blk %d\n key schedule:\n",ctx->ks.n_blk);
for (j = 0; j < (6*32)/4; j++)
fprintf(stderr," %04x",ctx->ks.k_sch[j]);
fprintf(stderr,"\n");
fgetc(stdin);
#endif
}
/* Init of Polar Bear on each new message/IV */
/* the context, p, needs to have been allocated and the */
/* ks field of the context needs to point to the key */
/* schedule before calling */
void ECRYPT_ivsetup(
ECRYPT_ctx* ctx,
const u8* iv) {
int j, n_iv;
u16 IR[16], *R0 = ctx->R0, *R1 = ctx->R1;
u8 pt[32], ct[32];
if (ctx->ivsize > 248) {
fprintf(stderr,"Illegal IV size\n");
exit(1);
}
else
n_iv = ctx->ivsize/8;
#ifdef CIPHER_DEBUG
fprintf(stderr,"IV (len = %d): ",ctx->ivsize);
for (j = 0; j < n_iv; j++)
fprintf(stderr," %02x",iv[j]);
fprintf(stderr,"\n");
#endif
InitD8(ctx->D8);
/* IV schedule */
for (j = 0; j < n_iv; j++)
pt[j] = iv[j];
pt[n_iv] = 0x80;
for (j = n_iv+1; j < 32; j++)
pt[j] = 0;
#ifdef CIPHER_DEBUG
fprintf(stderr,"expanded IV:\n");
for (j = 0; j < 32; j++)
fprintf(stderr," %02x",pt[j]);
fprintf(stderr,"\n");
#endif
aes_enc_blk(pt, ct, &ctx->ks);
for (j = 0; j < 7; j++) {
R0[j] = IR[j] = U8TO16_LITTLE(ct + 2 * j);
R1[j] = IR[j + 7] = U8TO16_LITTLE(ct + 2 * (j + 7));
}
R1[7] = IR[14] = U8TO16_LITTLE(ct + 2 * 14);
R1[8] = IR[15] = U8TO16_LITTLE(ct + 2 * 15);
#ifdef CIPHER_DEBUG
fprintf(stderr,"R0 inital value (6..0): ");
for (j = 6; j >= 0; j--)
fprintf(stderr," %04x",ctx->R0[j]);
fprintf(stderr,"\n");
fprintf(stderr,"R1 initial value (8..0): ");
for (j = 8; j >= 0; j--)
fprintf(stderr," %04x",ctx->R1[j]);
fprintf(stderr,"\n");
fgetc(stdin);
#endif
ctx->shift = 0;
}
void ECRYPT_process_bytes(
int action, /* 0 = encrypt; 1 = decrypt; */
ECRYPT_ctx* ctx,
const u8* input,
u8* output,
u32 msglen) /* Message length in bytes. */
{
u8 alpha0, alpha1, alpha2, alpha3;
u8 beta00, beta01, beta02, beta03, beta10, beta11, beta12, beta13;
u16 c, gamma0, gamma1;
u16 *R0 = ctx->R0, *R1 = ctx->R1;
u8 *D8 = ctx->D8;
int j,i = 0;
while (i < msglen) {
STEP_R0;
STEP_R0;
STEP_R1;
STEP_R1;
#ifdef CIPHER_DEBUG
fprintf(stderr,"R0 stepped twice: ");
for (j = 6; j >= 0; j--)
fprintf(stderr," %04x",ctx->R0[j]);
fprintf(stderr,"\n");
fprintf(stderr,"R1 stepped twice: ");
for (j = 8; j >= 0; j--)
fprintf(stderr," %04x",ctx->R1[j]);
fprintf(stderr,"\n");
#endif
if (ctx->shift & 0x4000) {
STEP_R0;
#ifdef CIPHER_DEBUG
fprintf(stderr,"R0 stepped once more: ");
for (j = 6; j >= 0; j--)
fprintf(stderr," %04x",ctx->R0[j]);
fprintf(stderr,"\n");
#endif
}
if (ctx->shift & 0x8000) {
STEP_R1;
#ifdef CIPHER_DEBUG
fprintf(stderr,"R1 stepped once more: ");
for (j = 8; j >= 0; j--)
fprintf(stderr," %04x",ctx->R1[j]);
fprintf(stderr,"\n");
#endif
}
alpha3 = R0[5] & 0xff;
alpha2 = R0[5] >> 8;
alpha1 = R0[6] & 0xff;
alpha0 = R0[6] >> 8;
beta00 = D8[alpha0];
beta01 = D8[alpha1];
beta02 = D8[alpha2];
beta03 = D8[alpha3];
#ifdef CIPHER_DEBUG
fprintf(stderr,"alpha0 (0-3): %02x %02x %02x %02x \n",alpha0,alpha1,alpha2,alpha3);
fprintf(stderr,"beta0 (0-3): %02x %02x %02x %02x \n",beta00,beta01,beta02,beta03);
#endif
D8[alpha0] = beta02;
D8[alpha1] = beta00;
D8[alpha2] = beta03;
D8[alpha3] = beta01;
alpha3 = R1[7] & 0xff;
alpha2 = R1[7] >> 8;
alpha1 = R1[8] & 0xff;
alpha0 = R1[8] >> 8;
beta10 = D8[alpha0];
beta11 = D8[alpha1];
beta12 = D8[alpha2];
beta13 = D8[alpha3];
#ifdef CIPHER_DEBUG
fprintf(stderr,"alpha1 (0-3): %02x %02x %02x %02x \n",alpha0,alpha1,alpha2,alpha3);
fprintf(stderr,"beta1 (0-3): %02x %02x %02x %02x \n",beta10,beta11,beta12,beta13);
#endif
D8[alpha0] = beta12;
D8[alpha1] = beta10;
D8[alpha2] = beta13;
D8[alpha3] = beta11;
gamma0 = beta11 | (beta10 << 8);
gamma1 = beta13 | (beta12 << 8);
#ifdef CIPHER_DEBUG
fprintf(stderr,"gamma0, gamma1: %04x %04x \n",gamma0,gamma1);
#endif
ctx->shift = (gamma0 + ctx->shift) & 0xffff;
R0[5] = (gamma1 + R0[5]) & 0xffff;
j = msglen - i;
if (j >= 4) {
output[i] = input[i] ^ beta00 ^ beta10;
output[i+1] = input[i+1] ^ beta01 ^ beta11;
output[i+2] = input[i+2] ^ beta02 ^ beta12;
output[i+3] = input[i+3] ^ beta03 ^ beta13;
}
else {
output[i] = input[i] ^ beta00 ^ beta10;
if (j > 1)
output[i+1] = input[i+1] ^ beta01 ^ beta11;
if (j > 2)
output[i+2] = input[i+2] ^ beta02 ^ beta12;
}
#ifdef CIPHER_DEBUG
fprintf(stderr,"new shift: %04x \n",ctx->shift);
fprintf(stderr,"new R0[5]: %04x \n",ctx->R0[5]);
fprintf(stderr,"plaintext: %02x",input[i]);
if (j > 1)
fprintf(stderr," %02x",input[i+1]);
if (j > 2)
fprintf(stderr," %02x",input[i+2]);
if (j > 3)
fprintf(stderr," %02x",input[i+3]);
fprintf(stderr,"\n");
fprintf(stderr,"ciphertext: %02x",output[i]);
if (j > 1)
fprintf(stderr," %02x",output[i+1]);
if (j > 2)
fprintf(stderr," %02x",output[i+2]);
if (j > 3)
fprintf(stderr," %02x",output[i+3]);
fprintf(stderr,"\n");
fgetc(stdin);
#endif
i += 4;
}
}
void ECRYPT_keystream_bytes(
ECRYPT_ctx* ctx,
u8* keystream,
u32 length) {
u8 alpha0, alpha1, alpha2, alpha3;
u8 beta00, beta01, beta02, beta03, beta10, beta11, beta12, beta13;
u16 c, gamma0, gamma1;
u16 *R0 = ctx->R0, *R1 = ctx->R1;
u8 *D8 = ctx->D8;
int j,i = 0;
while (i < length) {
STEP_R0;
STEP_R0;
STEP_R1;
STEP_R1;
#ifdef CIPHER_DEBUG
fprintf(stderr,"R0 stepped twice: ");
for (j = 6; j >= 0; j--)
fprintf(stderr," %04x",ctx->R0[j]);
fprintf(stderr,"\n");
fprintf(stderr,"R1 stepped twice: ");
for (j = 8; j >= 0; j--)
fprintf(stderr," %04x",ctx->R1[j]);
fprintf(stderr,"\n");
#endif
if (ctx->shift & 0x4000) {
STEP_R0;
#ifdef CIPHER_DEBUG
fprintf(stderr,"R0 stepped once more: ");
for (j = 6; j >= 0; j--)
fprintf(stderr," %04x",ctx->R0[j]);
fprintf(stderr,"\n");
#endif
}
if (ctx->shift & 0x8000) {
STEP_R1;
#ifdef CIPHER_DEBUG
fprintf(stderr,"R1 stepped once more: ");
for (j = 8; j >= 0; j--)
fprintf(stderr," %04x",ctx->R1[j]);
fprintf(stderr,"\n");
#endif
}
alpha3 = R0[5] & 0xff;
alpha2 = R0[5] >> 8;
alpha1 = R0[6] & 0xff;
alpha0 = R0[6] >> 8;
beta00 = D8[alpha0];
beta01 = D8[alpha1];
beta02 = D8[alpha2];
beta03 = D8[alpha3];
#ifdef CIPHER_DEBUG
fprintf(stderr,"alpha0 (0-3): %02x %02x %02x %02x \n",alpha0,alpha1,alpha2,alpha3);
fprintf(stderr,"beta0 (0-3): %02x %02x %02x %02x \n",beta00,beta01,beta02,beta03);
#endif
D8[alpha0] = beta02;
D8[alpha1] = beta00;
D8[alpha2] = beta03;
D8[alpha3] = beta01;
alpha3 = R1[7] & 0xff;
alpha2 = R1[7] >> 8;
alpha1 = R1[8] & 0xff;
alpha0 = R1[8] >> 8;
beta10 = D8[alpha0];
beta11 = D8[alpha1];
beta12 = D8[alpha2];
beta13 = D8[alpha3];
#ifdef CIPHER_DEBUG
fprintf(stderr,"alpha1 (0-3): %02x %02x %02x %02x \n",alpha0,alpha1,alpha2,alpha3);
fprintf(stderr,"beta1 (0-3): %02x %02x %02x %02x \n",beta10,beta11,beta12,beta13);
#endif
D8[alpha0] = beta12;
D8[alpha1] = beta10;
D8[alpha2] = beta13;
D8[alpha3] = beta11;
gamma0 = beta11 | (beta10 << 8);
gamma1 = beta13 | (beta12 << 8);
#ifdef CIPHER_DEBUG
fprintf(stderr,"gamma0, gamma1: %04x %04x \n",gamma0,gamma1);
#endif
ctx->shift = (gamma0 + ctx->shift) & 0xffff;
R0[5] = (gamma1 + R0[5]) & 0xffff;
j = length - i;
if (j >= 4) {
keystream[i] = beta00 ^ beta10;
keystream[i+1] = beta01 ^ beta11;
keystream[i+2] = beta02 ^ beta12;
keystream[i+3] = beta03 ^ beta13;
}
else {
keystream[i] = beta00 ^ beta10;
if (j > 1)
keystream[i+1] = beta01 ^ beta11;
if (j > 2)
keystream[i+2] = beta02 ^ beta12;
}
#ifdef CIPHER_DEBUG
fprintf(stderr,"new shift: %04x \n",ctx->shift);
fprintf(stderr,"new R0[5]: %04x \n",ctx->R0[5]);
fprintf(stderr,"keystream: %02x",keystream[i]);
if (j > 1)
fprintf(stderr," %02x",keystream[i+1]);
if (j > 2)
fprintf(stderr," %02x",keystream[i+2]);
if (j > 3)
fprintf(stderr," %02x",keystream[i+3]);
fprintf(stderr,"\n");
fgetc(stdin);
#endif
i += 4;
}
}