[svn] / ecrypt / trunk / submissions / cryptmt / v2 / cryptmt.c  

svn: ecrypt/trunk/submissions/cryptmt/v2/cryptmt.c

File: [svn] / ecrypt / trunk / submissions / cryptmt / v2 / cryptmt.c (download) (as text)
Revision: 158, Thu Feb 23 20:59:48 2006 UTC (8 years, 4 months ago) by cdecanni
File size: 11146 byte(s)
* imported CryptMT-v2.
/* CryptMT Stream Cipher, Relying PMT */
/* By Hagita-Matsumoto-Nishimura-Saito */
/* PMT included */
/* 2005/12/22 */

#include <stdio.h>
#include <string.h>

#include "ecrypt-config.h"
#include "ecrypt-machine.h"
#include "ecrypt-portable.h"

#include "ecrypt-sync.h"


/**********Start of PMT ************/
/* Period parameters */
#define N 623
#define M 609
#define R 7 /* grot1 */
#define S 3 /* gs3 */

/* prototypes */
static void genrand_bytes_first(ECRYPT_ctx * ctx, u8 cipher[], const u8 plain[],
				u32 len);
static void genrand_bytes(ECRYPT_ctx * ctx, u8 cipher[], const u8 plain[], 
			  u32 len);
static void genrand_keystream_bytes_first(ECRYPT_ctx * ctx, u8 cipher[],
					  u32 len);
static void genrand_keystream_bytes(ECRYPT_ctx * ctx, u8 cipher[], u32 len);
static void genrand_block_first(ECRYPT_ctx * ctx, u8 cipher[], 
				const u8 plain[]);
static void genrand_block(ECRYPT_ctx * ctx, u8 cipher[], const u8 plain[]);
static void genrand_keystream_block_first(ECRYPT_ctx * ctx, u8 cipher[]);
static void genrand_keystream_block(ECRYPT_ctx * ctx, u8 cipher[]);
static void array_fill(u32 to_fill[], s32 gen_length, s32 init_length);
static void array_fill_withkey(u32 to_fill[], s32 gen_length, s32 init_length,
			u32 key_extended[]);

static void genrand_bytes_first(ECRYPT_ctx * ctx, u8 cipher[], const u8 plain[],
			  u32 len)
{
    u32 accum;
    int kk;
    u32 *to_fill, *key_extended;
    u32 x, y, lung;
    s32 j3, s;
	
    s = ctx->ivsize;
    to_fill = ctx->booter_state + 2*s;
    key_extended = ctx->key_extended + 2*s;
    
    accum = ctx->accum;
    j3 = s;
    lung = to_fill[1] | 1;
    for (kk=0; len>0; kk++, len--) {
	y = to_fill[j3-2];
	y ^= key_extended[kk];
	x = to_fill[kk];
	to_fill[kk] ^= y;
	lung *= (y | 1);
	x ^= lung;
	to_fill[j3++] ^= (x ^ (~x >> 16)) + (y << 1); /* reading key */
	
	accum *= to_fill[kk] | 0x1;
	cipher[kk] = plain[kk] ^ (u8)(accum >> 24);
    }
    /* ctx->f = 1; */
}

static void genrand_bytes(ECRYPT_ctx * ctx, u8 cipher[], const u8 plain[],
			  u32 len)
{
    u32 accum;
    int kk;
    u32 y;
    u32 *pmt;

    pmt = ctx->pmt;
    accum = ctx->accum;
    y = pmt[N];
    for (kk = 0; (kk < N - M) && (len > 0); kk++, len--) {
	y ^= pmt[kk] << R;
	y ^= pmt[kk+M];
	pmt[kk] ^= y ^ (y >> S);
	accum *= pmt[kk] | 0x1;
	cipher[kk] = plain[kk] ^ (u8)(accum >> 24);
    }
    if (len <= 0) {
	/* pmt[N] = y; */
	/* ctx->accum = accum; */
	return;
    }
    for (; (kk < N) && (len > 0); kk++, len--) {
	y ^= pmt[kk] << R;
	y ^= pmt[kk+M-N];
	pmt[kk] ^= y ^ (y >> S);
	
	accum *= pmt[kk] | 0x1;
	cipher[kk] = plain[kk] ^ (u8)(accum >> 24);
    }
    /* pmt[N] = y; */
    /* ctx->accum = accum; */
}

static void genrand_keystream_bytes_first(ECRYPT_ctx * ctx, u8 cipher[], 
					  u32 len)
{
    u32 y, accum;
    int kk;
    
    u32 *to_fill, *key_extended;
    u32 x, lung;
    s32 j3, s;
    
    s = ctx->ivsize;
    to_fill = ctx->booter_state + 2*s;
    key_extended = ctx->key_extended + 2*s;

    accum = ctx->accum;
    j3 = s;
    lung = to_fill[1] | 1;
    for (kk=0; len>0; kk++, len--) {
	y = to_fill[j3-2];
	y ^= key_extended[kk];
	x = to_fill[kk];
	to_fill[kk] ^= y;
	lung *= (y | 1);
	x ^= lung;
	to_fill[j3++] ^= (x ^ (~x >> 16)) + (y << 1); /* reading key */
	
	accum *= to_fill[kk] | 0x1;
	*cipher++ = (u8)(accum >> 24);
    }
}

static void genrand_keystream_bytes(ECRYPT_ctx * ctx, u8 cipher[], u32 len)
{
    u32 y, accum;
    u32 *pmt;
    int kk;
    
    pmt = ctx->pmt;
    accum = ctx->accum;
    y = pmt[N];
    for (kk = 0; (kk < N - M) && (len > 0); kk++, len--) {
	y ^= pmt[kk] << R;
	y ^= pmt[kk+M];
	pmt[kk] ^= y ^ (y >> S);
	  
	accum *= pmt[kk] | 0x1;
	cipher[kk] = (u8)(accum >> 24);
    }
    if (len <= 0) {
	/* pmt[N] = y; */
	/* ctx->accum = accum; */
	return;
    }
    for (; (kk < N) && (len > 0); kk++, len--) {
	y ^= pmt[kk] << R;
	y ^= pmt[kk+M-N];
	pmt[kk] ^= y ^ (y >> S);
	accum *= pmt[kk] | 0x1;
	cipher[kk] = (u8)(accum >> 24);
    }
    /* pmt[N] = y; */
    /* ctx->accum = accum; */
}

static void genrand_block_first(ECRYPT_ctx * ctx, u8 cipher[], 
				const u8 plain[])
{
    u32 y, accum;
    int kk;
    u32 *to_fill, *key_extended;
    u32 x, lung;
    s32 j3, s;
	
    s = ctx->ivsize;
    to_fill = ctx->booter_state + 2*s;
    key_extended = ctx->key_extended + 2*s;
    
    accum = ctx->accum;
    j3 = s;
    lung = to_fill[1] | 1;
    for (kk=0; kk<N; kk++) {
	y = to_fill[j3-2];
	y ^= key_extended[kk];
	x = to_fill[kk];
	to_fill[kk] ^= y;
	lung *= (y | 1);
	x ^= lung;
	to_fill[j3++] ^= (x ^ (~x >> 16))  + (y << 1); /* reading key */
	
	accum *= to_fill[kk] | 0x1;
	cipher[kk] = plain[kk] ^ (u8)(accum >> 24);
    }
    ctx->pmt = to_fill;
    ctx->pmt[N] = U32C(0x4d484e53);
    ctx->accum = accum;
}

static void genrand_block(ECRYPT_ctx * ctx, u8 cipher[], const u8 plain[])
{
    u32 y, accum;
    u32 *pmt;
    int kk;

    pmt = ctx->pmt;
    accum = ctx->accum;
    y = pmt[N];
    for (kk=0; kk<(N-M); kk++) {
	y ^= pmt[kk] << R;
	y ^= pmt[kk+M];
	pmt[kk] ^= y ^ (y >> S);
	
	accum *= pmt[kk] | 0x1;
	cipher[kk] = plain[kk] ^ (u8)(accum >> 24);
    }
    for (; kk < N ; kk++) {
	y ^= pmt[kk] << R;
	y ^= pmt[kk+M-N];
	pmt[kk] ^= y ^ (y >> S);
	
	accum *= pmt[kk] | 0x1;
	cipher[kk] = plain[kk] ^ (u8)(accum >> 24);
    }
    pmt[N] = y;
    ctx->accum = accum;
}

static void genrand_keystream_block_first(ECRYPT_ctx * ctx, u8 cipher[])
{
    u32 y, accum;
    int kk;
    u32 *to_fill, *key_extended;
    u32 x, lung;
    s32 j3, s;
	
    s = ctx->ivsize;
    to_fill = ctx->booter_state + 2*s;
    key_extended = ctx->key_extended + 2*s;

    accum = ctx->accum;
    j3 = s;
    lung = to_fill[1] | 1;
    for (kk=0; kk<N; kk++) {
	y = to_fill[j3-2];
	y ^= key_extended[kk];
	x = to_fill[kk];
	to_fill[kk] ^= y;
	lung *= (y | 1);
	x ^= lung;
	to_fill[j3++] ^= (x ^ (~x >> 16)) + (y << 1); /* reading key */

	accum *= to_fill[kk] | 0x1;
	cipher[kk] = (u8)(accum >> 24);
    }
    ctx->pmt = to_fill;
    ctx->pmt[N] = U32C(0x4d484e53);
    ctx->accum = accum;
}

static void genrand_keystream_block(ECRYPT_ctx * ctx, u8 cipher[])
{
    u32 y, accum;
    u32 *pmt;
    int kk;

    pmt = ctx->pmt;
    accum = ctx->accum;
    y = pmt[N];
    for (kk=0; kk<(N-M); kk++) {
	y ^= pmt[kk] << R;
	y ^= pmt[kk+M];
	pmt[kk] ^= y ^ (y >> S);

	accum *= pmt[kk] | 0x1;
	cipher[kk] = (u8)(accum >> 24);
    }
    for (; kk < N ; kk++) {
	y ^= pmt[kk] << R;
	y ^= pmt[kk+M-N];
	pmt[kk] ^= y ^ (y >> S);
	
	accum = pmt[kk] | 0x1;
	cipher[kk] = (u8)(accum >> 24);
    }
    pmt[N] = y;
    ctx->accum = accum;
}

/********* END of PMT **********/


void ECRYPT_init(void)
{
    /* do nothing */
}

static void array_fill(u32 to_fill[], s32 gen_length, s32 init_length) 
{
    s32 i, j2, j3;
    u32 lung;

    j2=init_length - 2;
    j3=init_length;
    lung = to_fill[1] | 1;
    for (i=0; i< gen_length; i++) {
	u32 x, y;
	y = to_fill[j2++];
	y ^= j2;
	x = to_fill[i];
	to_fill[i] ^= y;
	lung *= (y | 1);
	x ^= lung;
	to_fill[j3++] ^= (x ^ (~x >> 16)) + (y << 1); /* reading "key"*/
    }
}

/* Key size in bits. */
/* IV size in bits. */
void ECRYPT_keysetup(ECRYPT_ctx * ctx, const u8 * key, u32 keysize,
		     u32 ivsize)
{
    s32 i;
    u32 expander_state[2*N+4*(ECRYPT_MAXKEYSIZE/32)+2*(ECRYPT_MAXIVSIZE/32)];

    memset(expander_state, 0, sizeof(expander_state));
    memset(ctx, 0, sizeof(ctx));
    ctx->keysize = keysize / 32;
    ctx->ivsize = ivsize / 32;

    for (i = 0; i < ctx->keysize; i++) {
	expander_state[i] = U8TO32_LITTLE(key);
	key += 4;
    }
    
    array_fill(expander_state, 2*N + 4*(ivsize/32) + keysize/32, keysize/32);
    memcpy(ctx->key_extended, expander_state + 2*(keysize/32), 
	   sizeof(u32)*(2*N + 4*(ivsize/32)));
}

static void array_fill_withkey(u32 to_fill[], s32 gen_length, s32 init_length,
			u32 key_extended[]) 
{
    s32 i, j3;
    u32 lung;
    j3=init_length;
    lung = to_fill[1] | 1;
    for (i=0; i< gen_length; i++) {
	u32 x, y;
	y = to_fill[j3-2];
	y ^= key_extended[i];
	x = to_fill[i];
	to_fill[i] ^= y;
	lung *= (y | 1);
	x ^= lung;
	to_fill[j3++] ^= (x ^ (~x >> 16)) + (y << 1); /* reading "key"*/
    }
}

void ECRYPT_ivsetup(ECRYPT_ctx * ctx, const u8 * iv)
{
    s32 i, s;
 
    s = ctx->ivsize;
    for (i = 0; i < s; i++) {
	ctx->booter_state[i] = U8TO32_LITTLE(iv);
	iv += 4;
    }
    
    memcpy(ctx->booter_state + s, ctx->key_extended+N+2*s, sizeof(u32)*(N+2*s));
    array_fill_withkey(ctx->booter_state, 2*s, s, ctx->key_extended);
    ctx->accum = ctx->booter_state[s-1] | 1;
    ctx->f = 0;
}

/* Message length in bytes. */
void ECRYPT_encrypt_bytes(ECRYPT_ctx * ctx,
			  const u8 * plaintext,
			  u8 * ciphertext, u32 msglen)
{
    if (!ctx->f) {
	if (msglen >= ECRYPT_BLOCKLENGTH) {
	    	genrand_block_first(ctx, ciphertext, plaintext);
		ciphertext += ECRYPT_BLOCKLENGTH;
		plaintext += ECRYPT_BLOCKLENGTH;
		msglen -= ECRYPT_BLOCKLENGTH;
		ctx->f = 1;
	} else {
	    genrand_bytes_first(ctx, ciphertext, plaintext, msglen);
	    return;
	}
    }
    while (msglen >= ECRYPT_BLOCKLENGTH) {
	genrand_block(ctx, ciphertext, plaintext);
	ciphertext += ECRYPT_BLOCKLENGTH;
	plaintext += ECRYPT_BLOCKLENGTH;
	msglen -= ECRYPT_BLOCKLENGTH;
    }
    if (msglen != 0) {
	genrand_bytes(ctx, ciphertext, plaintext, msglen);
    }
}

/* Message length in bytes. */
void ECRYPT_decrypt_bytes(ECRYPT_ctx * ctx,
			  const u8 * ciphertext,
			  u8 * plaintext, u32 msglen)
{
    ECRYPT_encrypt_bytes(ctx, ciphertext, plaintext, msglen);
}

/* Message length in blocks. */
void ECRYPT_encrypt_blocks(ECRYPT_ctx * ctx,
			   const u8 * plaintext,
			   u8 * ciphertext, u32 blocks)
{
    s32 i;

    if (!ctx->f) {
	genrand_block_first(ctx, ciphertext, plaintext);
	ciphertext += ECRYPT_BLOCKLENGTH;
	plaintext += ECRYPT_BLOCKLENGTH;
	blocks--;
	ctx->f = 1;
    }
    for (i = 0; i < blocks; i++) {
	genrand_block(ctx, ciphertext, plaintext);
	ciphertext += ECRYPT_BLOCKLENGTH;
	plaintext += ECRYPT_BLOCKLENGTH;
    }
}

/* Message length in blocks. */
void ECRYPT_decrypt_blocks(ECRYPT_ctx * ctx,
			   const u8 * ciphertext,
			   u8 * plaintext, u32 blocks)
{
    ECRYPT_encrypt_blocks(ctx, ciphertext, plaintext, blocks);
}


/* keystream length in bytes */
void ECRYPT_keystream_bytes(ECRYPT_ctx * ctx, u8 * keystream, u32 msglen)
{
    if (!ctx->f) {
	if (msglen >= ECRYPT_BLOCKLENGTH) {
	    	genrand_keystream_block_first(ctx, keystream);
		keystream += ECRYPT_BLOCKLENGTH;
		msglen -= ECRYPT_BLOCKLENGTH;
		ctx->f = 1;
	} else {
	    genrand_keystream_bytes_first(ctx, keystream, msglen);
	    return;
	}
    }
    while (msglen >= ECRYPT_BLOCKLENGTH) {
	genrand_keystream_block(ctx, keystream);
	keystream += ECRYPT_BLOCKLENGTH;
	msglen -= ECRYPT_BLOCKLENGTH;
    }
    if (msglen != 0) {
	genrand_keystream_bytes(ctx, keystream, msglen);
    }
}

/* Keystream length in blocks. */
void ECRYPT_keystream_blocks(ECRYPT_ctx * ctx, u8 * keystream, u32 blocks)
{
    s32 i;

    if (!ctx->f) {
	genrand_keystream_block_first(ctx, keystream);
	keystream += ECRYPT_BLOCKLENGTH;
	blocks--;
	ctx->f = 1;
    }
    for (i = 0; i < blocks; i++) {
	genrand_keystream_block(ctx, keystream);
	keystream += ECRYPT_BLOCKLENGTH;
    }
}

eSTREAM Project

Powered by ViewCVS 1.0-dev
(Powered by Apache)

ViewCVS and CVS Help