#ifndef _MIR1_STREAM_CIPHER__
#define _MIR1_STREAM_CIPHER__

#include "ecrypt-portable.h"
#include "ecrypt-sync.h"

#ifndef _Mir1_DATASTRUCTURES_AND_TYPES_DEFINED
#define _Mir1_DATASTRUCTURES_AND_TYPES_DEFINED
/* ------------------------------------------------------------------------- */
/* Data Types used in coding */
/* ------------------------------------------------------------------------- */
typedef unsigned long long ull;  
typedef u32 ul;
typedef u8  uc;

union Int
{ struct _b
  { uc b0, b1, b2, b3, b4, b5, b6, b7;
  } b;     /* 8 -bit access */
  struct _w
  { ul w0, w1;
  } w;     /* 32-bit access */
  ull v;   /* 64-bit access */
};

/* ------------------------------------------------------------------------- */
/* Data structures */
/* ------------------------------------------------------------------------- */

typedef struct
{
  Int a, b, x0, x1, x2, x3;      /* Internal State */
  uc S[256];                     /* secret S-box   */

} ECRYPT_ctx;

#endif

/* ------------------------------------------------------------------------- */
/* Constants and global variables (tables) */
/* ------------------------------------------------------------------------- */

/* The typical Rijndael S-Box */

const uc SR[]={
0x63 ,0x7c ,0x77 ,0x7b ,0xf2 ,0x6b ,0x6f ,0xc5 ,0x30 ,0x01 ,0x67 ,0x2b,
0xfe ,0xd7 ,0xab ,0x76 ,0xca ,0x82 ,0xc9 ,0x7d ,0xfa ,0x59 ,0x47 ,0xf0,
0xad ,0xd4 ,0xa2 ,0xaf ,0x9c ,0xa4 ,0x72 ,0xc0 ,0xb7 ,0xfd ,0x93 ,0x26,
0x36 ,0x3f ,0xf7 ,0xcc ,0x34 ,0xa5 ,0xe5 ,0xf1 ,0x71 ,0xd8 ,0x31 ,0x15,
0x04 ,0xc7 ,0x23 ,0xc3 ,0x18 ,0x96 ,0x05 ,0x9a ,0x07 ,0x12 ,0x80 ,0xe2,
0xeb ,0x27 ,0xb2 ,0x75 ,0x09 ,0x83 ,0x2c ,0x1a ,0x1b ,0x6e ,0x5a ,0xa0,
0x52 ,0x3b ,0xd6 ,0xb3 ,0x29 ,0xe3 ,0x2f ,0x84 ,0x53 ,0xd1 ,0x00 ,0xed,
0x20 ,0xfc ,0xb1 ,0x5b ,0x6a ,0xcb ,0xbe ,0x39 ,0x4a ,0x4c ,0x58 ,0xcf,
0xd0 ,0xef ,0xaa ,0xfb ,0x43 ,0x4d ,0x33 ,0x85 ,0x45 ,0xf9 ,0x02 ,0x7f,
0x50 ,0x3c ,0x9f ,0xa8 ,0x51 ,0xa3 ,0x40 ,0x8f ,0x92 ,0x9d ,0x38 ,0xf5,
0xbc ,0xb6 ,0xda ,0x21 ,0x10 ,0xff ,0xf3 ,0xd2 ,0xcd ,0x0c ,0x13 ,0xec,
0x5f ,0x97 ,0x44 ,0x17 ,0xc4 ,0xa7 ,0x7e ,0x3d ,0x64 ,0x5d ,0x19 ,0x73,
0x60 ,0x81 ,0x4f ,0xdc ,0x22 ,0x2a ,0x90 ,0x88 ,0x46 ,0xee ,0xb8 ,0x14,
0xde ,0x5e ,0x0b ,0xdb ,0xe0 ,0x32 ,0x3a ,0x0a ,0x49 ,0x06 ,0x24 ,0x5c,
0xc2 ,0xd3 ,0xac ,0x62 ,0x91 ,0x95 ,0xe4 ,0x79 ,0xe7 ,0xc8 ,0x37 ,0x6d,
0x8d ,0xd5 ,0x4e ,0xa9 ,0x6c ,0x56 ,0xf4 ,0xea ,0x65 ,0x7a ,0xae ,0x08,
0xba ,0x78 ,0x25 ,0x2e ,0x1c ,0xa6 ,0xb4 ,0xc6 ,0xe8 ,0xdd ,0x74 ,0x1f,
0x4b ,0xbd ,0x8b ,0x8a ,0x70 ,0x3e ,0xb5 ,0x66 ,0x48 ,0x03 ,0xf6 ,0x0e,
0x61 ,0x35 ,0x57 ,0xb9 ,0x86 ,0xc1 ,0x1d ,0x9e ,0xe1 ,0xf8 ,0x98 ,0x11,
0x69 ,0xd9 ,0x8e ,0x94 ,0x9b ,0x1e ,0x87 ,0xe9 ,0xce ,0x55 ,0x28 ,0xdf,
0x8c ,0xa1 ,0x89 ,0x0d ,0xbf ,0xe6 ,0x42 ,0x68 ,0x41 ,0x99 ,0x2d ,0x0f,
0xb0 ,0x54 ,0xbb ,0x16 };


/* Several design constants */

const ull C0=0x1248842112488421I64; 
const ull C1=0x1248124812481248I64;
const ull C3=0x4812481248124812I64;

/* ------------------------------------------------------------------------- */
/* Internal State Update... Building Block */
/* ------------------------------------------------------------------------- */
#define Mir1_STATE_UPDATE                           \
     Int r0, r1, t0, t1, p0, p1, s, m0, m1, m2, m3; \
     t0.v  = p.x0.v << 1;                    \
     p1.v  = p.x3.v | C3;                    \
     p0.v  = p.x1.v | C1;                    \
     t1.v  = p.x2.v << 1;                    \
     m2.v  = p1.v * t0.v;                    \
     m3.v  = p0.v * t0.v;                    \
     m0.v  = p0.v * t1.v;                    \
     m1.v  = p1.v * t1.v;                    \
     r0.v  = p.x0.v & p.x1.v;                \
     p.a.b.b0 ^= p.S[p.b.b.b0];              \
     p.a.b.b1 ^= p.S[p.b.b.b1];              \
     r1.v      = r0.v & p.x2.v;              \
     p.a.b.b2 ^= p.S[p.b.b.b2];              \
     p.a.b.b3 ^= p.S[p.b.b.b3];              \
     s.v       = r1.v & p.x3.v;              \
     p.a.b.b4 ^= p.S[p.b.b.b4];              \
     p.a.b.b5 ^= p.S[p.b.b.b5];              \
     s.v       = (s.v + C0) ^ s.v;           \
     p.a.b.b6 ^= p.S[p.b.b.b6];              \
     p.a.b.b7 ^= p.S[p.b.b.b7];              \
     p.x3.v   += (s.v & r1.v)   + m3.v;      \
     p.x2.v   += (s.v & r0.v)   + m2.v;      \
     r0.v      = (p.b.v << 29);              \
     p.x1.v   += (s.v & p.x0.v) + m1.v;      \
     r0.v     |= (p.b.v >> 35);              \
     p.x0.v   +=  s.v           + m0.v;      \
     r0.v     += p.x1.w.w1;                  \
     r0.w.w1  += p.x3.w.w1;                  \
     p.b.w.w0  = p.a.w.w0 ^ p.x0.w.w1;       \
     p.b.w.w1  = p.a.w.w1 ^ p.x2.w.w1;       \
     p.a.v     = r0.v + p.b.v;


#endif


