/*\
 *  Scalable Trivium C Source Code v0.5
 *  Copyright (c) 2005-2008 by Sean O'Neil
 *  Released to the public domain by Sean O'Neil in March 2008.
 *  Warning: The code may contain bugs.
 *  No warranties of any kind.
\*/

// Configurable parameters:

#define NLFSRS				3	// Only 3 is supported in this version, 3 for the original Trivium
#define PARALLELISE			64	// It will be parallelisable up to this many times, 64 for the original Trivium
#define PRIMEA				29	// Smallest prime (any prime greater than PARALLELISE/NLFSRS+1), 29 for the original Trivium
#define PRIMEB				31	// Second prime (greater than PRIMEA), 31 for the original Trivium
#define PRIMEC				37	// Third prime (greater than PRIMEB), 37 for the original Trivium

#define MUL(a,b)			(~((a)&(b)))	// NAND as recommended by Sean O'Neil
//#define MUL(a,b)			((a)&(b))		// AND as in the original Trivium (watch out for the 3-round loops!)

/*\

// nTrivium-128:

#define NLFSRS				3
#define PARALLELISE			128
#define PRIMEA				53
#define PRIMEB				59
#define PRIMEC				61
#define MUL(a,b)			(~((a)&(b)))	// NAND

// Parallelisable 128 times, 128-bit security, 516-bit state
// Should be sealed for 4096 rounds (32*128)
// Can safely produce up to 128 bits of output every 512 rounds
// Has not been analysed yet (March 2008)

\*/

/*\

// nTrivium-80:

#define NLFSRS				3
#define PARALLELISE			64
#define PRIMEA				31
#define PRIMEB				37
#define PRIMEC				41
#define MUL(a,b)			(~((a)&(b)))	// NAND

// Parallelisable 64 times, 80-bit security, 324-bit state (only 12.5% larger than the original Trivium)
// Should be sealed for 2304 rounds (36*64) (2 times more than recommended by the Trivium authors)
// Can safely produce up to 64 bits of output every 256 rounds (4 times slower than recommended by the Trivium authors)
// Has not been analysed yet (March 2008)

\*/

// 3*NLFSR structure:

#define A					(PRIMEB)*NLFSRS			// odd
#define B					(PRIMEA-1)*NLFSRS		// even
#define C					(PRIMEC)*NLFSRS			// odd
#define D					((PARALLELISE+NLFSRS-1)/NLFSRS)	// nearest allowed neighbour
#define BITS				(A+B+C)					// Total size of the state
#define S1					((D  )*NLFSRS)			// even/odd
#define S2					((D+1)*NLFSRS)			// odd/even
#define S3					((D  )*NLFSRS)			// even/odd
#define S4					((D+1)*NLFSRS)			// odd/even
#define S5					((D+NLFSRS+1)*NLFSRS)	// even/odd
#define S6					((D+NLFSRS*2+1)*NLFSRS)	// odd/even

#if ((D >= PRIMEA) || (S2 >= B) || (S5 >= B))
	*** ERROR: PRIME A IS TOO SMALL!!! ***
#endif

#if ((D >= PRIMEB) || (S1 >= A) || (S4 >= A))
	*** ERROR: PRIME B IS TOO SMALL!!! ***
#endif

#if ((D >= PRIMEC) || (S3 >= C) || (S6 >= C))
	*** ERROR: PRIME C IS TOO SMALL!!! ***
#endif

#define TAP00				(S1-1)
#define TAP01				(A+S2-1)
#define TAP02				(A+B+S3-1)
#define TAP03				(A-1)
#define TAP04				(A+B-1)
#define TAP05				(A+B+C-1)
#define TAP06				(A+S5-1)
#define TAP07				(A+B+S6-1)
#define TAP08				(S4-1)
#define TAP09				(A-3)
#define TAP10				(A+B-3)
#define TAP11				(A+B+C-3)
#define TAP12				(A-2)
#define TAP13				(A+B-2)
#define TAP14				(A+B+C-2)
#define TAP15				(A)
#define TAP16				(A+B)
#define TAP17				(0)

// Security parameters as recommended by Sean O'Neil:

#define MAX_SECURITY		((BITS-PARALLELISE)/3)									// A not-wild-at-all safe guess.
#define INIT_ROUNDS			(BITS*(24/(NLFSRS*NLFSRS)+6)/PARALLELISE*PARALLELISE)	// Sealing iterations before the first output for the NAND variant. Add 50% for the AND variant.
#define ROUNDS_PER_BIT		(12/(NLFSRS*NLFSRS)+3)									// Iterate for PARALLELISE*(ROUNDS_PER_BIT-1) rounds, then output one bit on every round for PARALLELISE rounds. Add 50% for the AND variant.

// Example bitslice implementation

unsigned long scalable_trivium_round (unsigned long * const s)
{
	unsigned long	i, a, b, c, x;
	
	a = s[TAP00] ^ s[TAP03];
	b = s[TAP01] ^ s[TAP04];
	c = s[TAP02] ^ s[TAP05];
	
	x = a ^ b ^ c;
	
	a ^= s[TAP06] ^ MUL (s[TAP09], s[TAP12]);
	b ^= s[TAP07] ^ MUL (s[TAP10], s[TAP13]);
	c ^= s[TAP08] ^ MUL (s[TAP11], s[TAP14]);
	
	for (i = BITS-1; i; i--) s[i] = s[i-1];
	
	s[TAP15] = a;
	s[TAP16] = b;
	s[TAP17] = c;
	
	return x;
}

int main (void)
{
	unsigned long	s[BITS];
	
	return scalable_trivium_round (s);
}
