[svn] / ecrypt / trunk / submissions / polarbear / polar-bear.c  

svn: ecrypt/trunk/submissions/polarbear/polar-bear.c

File: [svn] / ecrypt / trunk / submissions / polarbear / polar-bear.c (download) (as text)
Revision: 156, Mon Jan 16 12:04:27 2006 UTC (7 years, 4 months ago) by cdecanni
File size: 10007 byte(s)
* corrected bug in macro call.
/* polar-bear.c */

/*
 * "Polar Bear" stream cipher implementaion.
 *
 * This code is provided "as is" with no warranty or support. Requires a
 * (slightly modified) Rijndael (see documentation).
 */

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include "ecrypt-sync.h"
#include "aes.h"
#include "aestab.c"
#include "aeskey.c"
#include "aescrypt.c"

/* ------------------------------------------------------------------------- */

/* Tables for multiplication in GF(2^16) */
static u32 TL00[256], TH00[256], TL01[256], TH01[256],
           TL10[256], TH10[256], TL11[256], TH11[256];

/* 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
};

/* ------------------------------------------------------------------------- */

/* Init of S-box on each message */
#define InitD8(tab) memcpy(tab, T8_init, 256)

/* Multiplication in GF(2^16) */
#define GF216MUL(TL, TH, x) (TL[x & 0xff] ^ TH[x >> 8]) 

/*
 * Multiplies v(y) in 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 the registers */
#define STEP_R0_TWO_STEPS {\
	temp0 = R0[0];\
	temp1 = R0[1];\
	R0[0] = R0[2];\
	R0[1] = R0[3];\
	R0[2] = R0[4];\
	R0[3] = R0[5];\
	R0[4] = R0[6];\
	R0[5] = GF216MUL(TL00, TH00, temp0) ^ GF216MUL(TL01, TH01, temp1);\
	R0[6] = GF216MUL(TL00, TH00, temp1) ^ GF216MUL(TL01, TH01, R0[0]);\
	}

#define STEP_R0_THREE_STEPS {\
	temp0 = R0[0];\
	R0[0] = R0[3];\
	R0[3] = R0[6];\
	R0[6] = GF216MUL(TL00, TH00, R0[2]) ^ GF216MUL(TL01, TH01, R0[0]);\
	temp1 = R0[1];\
	R0[1] = R0[4];\
	R0[4] = GF216MUL(TL00, TH00, temp0) ^ GF216MUL(TL01, TH01, temp1);\
	temp0 = R0[2];\
	R0[2] = R0[5];\
	R0[5] = GF216MUL(TL00, TH00, temp1) ^ GF216MUL(TL01, TH01, temp0);\
	}

#define STEP_R1_TWO_STEPS {\
	temp0 = R1[0];\
	temp1 = R1[1];\
	R1[0] = R1[2];\
	R1[1] = R1[3];\
	R1[2] = R1[4];\
	R1[3] = R1[5];\
	R1[4] = R1[6];\
	R1[5] = R1[7];\
	R1[6] = R1[8];\
	R1[7] = GF216MUL(TL10, TH10, temp0) ^ GF216MUL(TL11, TH11, R1[3]);\
	R1[8] = GF216MUL(TL10, TH10, temp1) ^ GF216MUL(TL11, TH11, R1[4]);\
	}

#define STEP_R1_THREE_STEPS {\
	temp0 = R1[0];\
	R1[0] = R1[3];\
	R1[3] = R1[6];\
	R1[6] = GF216MUL(TL10, TH10, temp0) ^ GF216MUL(TL11, TH11, R1[5]);\
	temp0 = R1[1];\
	R1[1] = R1[4];\
	R1[4] = R1[7];\
	R1[7] = GF216MUL(TL10, TH10, temp0) ^ GF216MUL(TL11, TH11, R1[3]);\
	temp0 = R1[2];\
	R1[2] = R1[5];\
	R1[5] = R1[8];\
	R1[8] = GF216MUL(TL10, TH10, temp0) ^ GF216MUL(TL11, TH11, R1[4]);\
	}

/* ------------------------------------------------------------------------- */

/* Initiates tables for GF(2^16) arithmetic */
void ECRYPT_init(void)
{
	u16 ALOG[65536], DLOG[65536];
	u16 g;
	int i;

	for (i = 0; i <= 0xffff; i++)
	{
		DLOG[i] = ALOG[i] = 0;
	}

	g = 1;
	DLOG[g] = 0;
	ALOG[0] = g;

	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 = 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];
	}
}


/*
 * 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.  */ 
{
	if (keysize != 128)
	{
		fprintf(stderr,"Key size not implemented\n");
		exit(1);
	}

	if (ivsize > 240)
	{
		fprintf(stderr,"Illegal IV size\n");
		exit(1);
	}
	else
	{
		ctx->ivsize = ivsize;
	}

	aes_enc_key(key, keysize/8, &ctx->ks);
}


/* 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;
	int n_iv = ctx->ivsize / 8;
	u32 *R0 = ctx->R0, *R1 = ctx->R1;
	u8 pt[32], ct[32];
	u16 *ct16 = (u16*)ct;
	InitD8(ctx->D8);
	ctx->shift  = 0;

	/* Pad IV with 0x80 and zeroes */
	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;
	}

	/* Five rounds Rijndael */
	aes_enc_blk(pt, ct, &ctx->ks);

	/* Initialize R0 and R1 */
	for (j = 0; j < 7; j++)
	{
	  R0[j] = U8TO16_LITTLE(ct16);
	  ct16++;
	}

	for (j = 0; j < 9; j++) {
	  R1[j] = U8TO16_LITTLE(ct16);
	  ct16++;
	}
}


void ECRYPT_process_bytes(int action,		/* 0 = encrypt; 1 = decrypt; */
                          ECRYPT_ctx* ctx, 
                          const u8* input, 
                          u8* output, 
                          u32 msglen)		/* Message length in bytes. */ 
{
	u32 alpha0, alpha1, alpha2, alpha3, beta0, beta1, beta2, beta3;
	u32 temp0, temp1, b;
	u32 *R0 = ctx->R0, *R1 = ctx->R1;
	u32 *S = &ctx->shift;
	u8 *D8 = ctx->D8;
	u32 *in = (u32*)input;
	u32 *out = (u32*)output;

	while (msglen)
	{
		/* Step R0 two or three steps*/
		if (*S & 0x4000)
		{
			STEP_R0_THREE_STEPS;
		}
		else
		{
			STEP_R0_TWO_STEPS;
		}

		/* Calculate alphas and betas */
		alpha0 = R0[6] >> 8;
		alpha1 = R0[6] & 0xff;
		alpha2 = R0[5] >> 8;
		alpha3 = R0[5] & 0xff;

		beta1 = D8[alpha1];
		beta3 = D8[alpha3];
		beta0 = D8[alpha0];
		beta2 = D8[alpha2];

		/* Swap(D8[alpha0], D8[alpha2]) */
		D8[alpha2] = beta0;
		D8[alpha0] = beta2;
		b = (beta2 << 8);
		b ^= (beta0 << 24);

		/* Swap(D8[alpha1], D8[alpha3]) */
		temp0 = D8[alpha3];
		D8[alpha3] = D8[alpha1];
		D8[alpha1] = temp0;
		b ^= beta3;
		b ^= (beta1 << 16);

		/* Step R1 two or three steps*/
		if (*S & 0x8000)
		{
			STEP_R1_THREE_STEPS;
		}
		else
		{
			STEP_R1_TWO_STEPS;
		}

		/* Calculate alphas and betas */
		alpha2 = R1[7] >> 8;
		alpha3 = R1[7] & 0xff;
		alpha0 = R1[8] >> 8;
		alpha1 = R1[8] & 0xff;

		beta1 = D8[alpha1];
		beta3 = D8[alpha3];
		beta0 = D8[alpha0];
		beta2 = D8[alpha2];

		/* Swap(D8[alpha0], D8[alpha2]) */
		D8[alpha0] = beta2;
		D8[alpha2] = beta0;

		/* Swap(D8[alpha1], D8[alpha3]) */
		temp0 = D8[alpha1];
		D8[alpha1] = D8[alpha3];
		D8[alpha3] = temp0;

		/* Calculate gamma1 and update R0[5] */
		temp0 = beta3 | (beta2 << 8);
		R0[5] += temp0;
		R0[5] &= 0xffff;
		b ^= temp0;
		
		/* Calculate gamma0 and update S */
		temp1 = beta1 | (beta0 << 8);
		*S += temp1;
		b ^= (temp1 << 16);

		/* Output 32 bits */
		*(out++) = *(in++) ^ U32TO32_LITTLE(b);
		msglen -= 4;
	}
}
	
void ECRYPT_keystream_bytes(ECRYPT_ctx* ctx, u8* keystream, u32 length)
{
	u32 alpha0, alpha1, alpha2, alpha3, beta0, beta1, beta2, beta3;
	u32 temp0, temp1, b;
	u32 *R0 = ctx->R0, *R1 = ctx->R1;
	u32 *S = &ctx->shift;
	u8 *D8 = ctx->D8;
	u32 *ks = (u32*)keystream;

	while (length)
	{
		/* Step R0 two or three steps*/
		if (*S & 0x4000)
		{
			STEP_R0_THREE_STEPS;
		}
		else
		{
			STEP_R0_TWO_STEPS;
		}

		/* Calculate alphas and betas */
		alpha0 = R0[6] >> 8;
		alpha1 = R0[6] & 0xff;
		alpha2 = R0[5] >> 8;
		alpha3 = R0[5] & 0xff;

		beta1 = D8[alpha1];
		beta3 = D8[alpha3];
		beta0 = D8[alpha0];
		beta2 = D8[alpha2];

		/* Swap(D8[alpha0], D8[alpha2]) */
		D8[alpha2] = beta0;
		D8[alpha0] = beta2;
		b = (beta2 << 8);
		b ^= (beta0 << 24);

		/* Swap(D8[alpha1], D8[alpha3]) */
		temp0 = D8[alpha3];
		D8[alpha3] = D8[alpha1];
		D8[alpha1] = temp0;
		b ^= beta3;
		b ^= (beta1 << 16);

		/* Step R1 two or three steps*/
		if (*S & 0x8000)
		{
			STEP_R1_THREE_STEPS;
		}
		else
		{
			STEP_R1_TWO_STEPS;
		}

		/* Calculate alphas and betas */
		alpha2 = R1[7] >> 8;
		alpha3 = R1[7] & 0xff;
		alpha0 = R1[8] >> 8;
		alpha1 = R1[8] & 0xff;

		beta1 = D8[alpha1];
		beta3 = D8[alpha3];
		beta0 = D8[alpha0];
		beta2 = D8[alpha2];

		/* Swap(D8[alpha0], D8[alpha2]) */
		D8[alpha0] = beta2;
		D8[alpha2] = beta0;

		/* Swap(D8[alpha1], D8[alpha3]) */
		temp0 = D8[alpha3];
		D8[alpha3] = D8[alpha1];
		D8[alpha1] = temp0;

		/* Calculate gamma1 and update R0[5] */
		temp0 = beta3 | (beta2 << 8);
		R0[5] += temp0;
		R0[5] &= 0xffff;
		b ^= temp0;
		
		/* Calculate gamma0 and update S */
		temp1 = beta1 | (beta0 << 8);
		*S += temp1;
		b ^= (temp1 << 16);

		/* Output 32 bits */
		*(ks++) = U32TO32_LITTLE(b);
		length -= 4;
	}
}

eSTREAM Project

Powered by ViewCVS 1.0-dev
(Powered by Apache)

ViewCVS and CVS Help