112855Sgabeblack@google.com#include <systemc.h>
212855Sgabeblack@google.com
312855Sgabeblack@google.com#define USE_TABLE 1
412855Sgabeblack@google.com
512855Sgabeblack@google.com#if DEBUG
612855Sgabeblack@google.comvoid
712855Sgabeblack@google.comDump_R(char *s, sc_uint<8> X[4][4])
812855Sgabeblack@google.com{
912855Sgabeblack@google.com	printf("%s R\n", s);
1012855Sgabeblack@google.com	for(int i = 0; i < 4; i++){
1112855Sgabeblack@google.com		printf("|");
1212855Sgabeblack@google.com		for(int j = 0; j < 4; j++){
1312855Sgabeblack@google.com			printf("%02x|", (int)X[i][j]);
1412855Sgabeblack@google.com		}
1512855Sgabeblack@google.com		printf("\n");
1612855Sgabeblack@google.com	}
1712855Sgabeblack@google.com}
1812855Sgabeblack@google.com
1912855Sgabeblack@google.comvoid
2012855Sgabeblack@google.comDump_rk(char *s, sc_uint<8> X[11][4][4])
2112855Sgabeblack@google.com{
2212855Sgabeblack@google.com	printf("%s rk\n", s);
2312855Sgabeblack@google.com	for(int i = 0; i < 11; i++){
2412855Sgabeblack@google.com		printf("%2d: ", (int)i);
2512855Sgabeblack@google.com		for(int j = 0; j < 4; j++){
2612855Sgabeblack@google.com			printf("|");
2712855Sgabeblack@google.com			for(int k = 0; k < 4; k++){
2812855Sgabeblack@google.com				printf("%02x|", (int)X[i][j][k]);
2912855Sgabeblack@google.com			}
3012855Sgabeblack@google.com			printf("   ");
3112855Sgabeblack@google.com		}
3212855Sgabeblack@google.com		printf("\n");
3312855Sgabeblack@google.com	}
3412855Sgabeblack@google.com}
3512855Sgabeblack@google.com#endif
3612855Sgabeblack@google.com
3712855Sgabeblack@google.comSC_MODULE(AES_Base)
3812855Sgabeblack@google.com{
3912855Sgabeblack@google.com	SC_CTOR(AES_Base) {}
4012855Sgabeblack@google.com
4112855Sgabeblack@google.com	void AddRoundKey(sc_uint<8> a[4][4], const sc_uint<8> rk[4][4]);
4212855Sgabeblack@google.com	sc_uint<8> S_Table(sc_uint<8> a);
4312855Sgabeblack@google.com	void SchedKey(sc_uint<8> k[4][4], sc_uint<8> W[11][4][4]);
4412855Sgabeblack@google.com};
4512855Sgabeblack@google.com
4612855Sgabeblack@google.comsc_uint<8>
4712855Sgabeblack@google.comAES_Base::S_Table(sc_uint<8> a)
4812855Sgabeblack@google.com{
4912855Sgabeblack@google.com	sc_uint<8> t;
5012855Sgabeblack@google.com#if USE_TABLE
5112855Sgabeblack@google.com	{
5212855Sgabeblack@google.com	static sc_uint<8> S[256] = {
5312855Sgabeblack@google.com 		99, 124, 119, 123, 242, 107, 111, 197,
5412855Sgabeblack@google.com		48,   1, 103,  43, 254, 215, 171, 118,
5512855Sgabeblack@google.com		202, 130, 201, 125, 250,  89,  71, 240,
5612855Sgabeblack@google.com		173, 212, 162, 175, 156, 164, 114, 192,
5712855Sgabeblack@google.com		183, 253, 147,  38,  54,  63, 247, 204,
5812855Sgabeblack@google.com		52, 165, 229, 241, 113, 216,  49,  21,
5912855Sgabeblack@google.com  		4, 199,  35, 195,  24, 150,   5, 154,
6012855Sgabeblack@google.com		7,  18, 128, 226, 235,  39, 178, 117,
6112855Sgabeblack@google.com  		9, 131,  44,  26,  27, 110,  90, 160,
6212855Sgabeblack@google.com		82,  59, 214, 179,  41, 227,  47, 132,
6312855Sgabeblack@google.com 		83, 209,   0, 237,  32, 252, 177,  91,
6412855Sgabeblack@google.com		106, 203, 190,  57,  74,  76,  88, 207,
6512855Sgabeblack@google.com		208, 239, 170, 251,  67,  77,  51, 133,
6612855Sgabeblack@google.com		69, 249,   2, 127,  80,  60, 159, 168,
6712855Sgabeblack@google.com 		81, 163,  64, 143, 146, 157,  56, 245,
6812855Sgabeblack@google.com		188, 182, 218,  33,  16, 255, 243, 210,
6912855Sgabeblack@google.com		205,  12,  19, 236,  95, 151,  68,  23,
7012855Sgabeblack@google.com		196, 167, 126,  61, 100,  93,  25, 115,
7112855Sgabeblack@google.com 		96, 129,  79, 220,  34,  42, 144, 136,
7212855Sgabeblack@google.com		70, 238, 184,  20, 222,  94,  11, 219,
7312855Sgabeblack@google.com		224,  50,  58,  10,  73,   6,  36,  92,
7412855Sgabeblack@google.com		194, 211, 172,  98, 145, 149, 228, 121,
7512855Sgabeblack@google.com		231, 200,  55, 109, 141, 213,  78, 169,
7612855Sgabeblack@google.com		108,  86, 244, 234, 101, 122, 174,   8,
7712855Sgabeblack@google.com		186, 120,  37,  46,  28, 166, 180, 198,
7812855Sgabeblack@google.com		232, 221, 116,  31,  75, 189, 139, 138,
7912855Sgabeblack@google.com		112,  62, 181, 102,  72,   3, 246,  14,
8012855Sgabeblack@google.com		97,  53,  87, 185, 134, 193,  29, 158,
8112855Sgabeblack@google.com		225, 248, 152,  17, 105, 217, 142, 148,
8212855Sgabeblack@google.com		155,  30, 135, 233, 206,  85,  40, 223,
8312855Sgabeblack@google.com		140, 161, 137,  13, 191, 230,  66, 104,
8412855Sgabeblack@google.com		65, 153,  45,  15, 176,  84, 187,  22,
8512855Sgabeblack@google.com	};
8612855Sgabeblack@google.com	t = S[a];
8712855Sgabeblack@google.com	}
8812855Sgabeblack@google.com#else
8912855Sgabeblack@google.com#define E(A,B) case A: t = B; break
9012855Sgabeblack@google.com	switch(a){
9112855Sgabeblack@google.com	E(  0, 99); E(  1,124); E(  2,119); E(  3,123); E(  4,242); E(  5,107);
9212855Sgabeblack@google.com	E(  6,111); E(  7,197); E(  8, 48); E(  9,  1); E( 10,103); E( 11, 43);
9312855Sgabeblack@google.com	E( 12,254); E( 13,215); E( 14,171); E( 15,118); E( 16,202); E( 17,130);
9412855Sgabeblack@google.com	E( 18,201); E( 19,125); E( 20,250); E( 21, 89); E( 22, 71); E( 23,240);
9512855Sgabeblack@google.com	E( 24,173); E( 25,212); E( 26,162); E( 27,175); E( 28,156); E( 29,164);
9612855Sgabeblack@google.com	E( 30,114); E( 31,192); E( 32,183); E( 33,253); E( 34,147); E( 35, 38);
9712855Sgabeblack@google.com	E( 36, 54); E( 37, 63); E( 38,247); E( 39,204); E( 40, 52); E( 41,165);
9812855Sgabeblack@google.com	E( 42,229); E( 43,241); E( 44,113); E( 45,216); E( 46, 49); E( 47, 21);
9912855Sgabeblack@google.com	E( 48,  4); E( 49,199); E( 50, 35); E( 51,195); E( 52, 24); E( 53,150);
10012855Sgabeblack@google.com	E( 54,  5); E( 55,154); E( 56,  7); E( 57, 18); E( 58,128); E( 59,226);
10112855Sgabeblack@google.com	E( 60,235); E( 61, 39); E( 62,178); E( 63,117); E( 64,  9); E( 65,131);
10212855Sgabeblack@google.com	E( 66, 44); E( 67, 26); E( 68, 27); E( 69,110); E( 70, 90); E( 71,160);
10312855Sgabeblack@google.com	E( 72, 82); E( 73, 59); E( 74,214); E( 75,179); E( 76, 41); E( 77,227);
10412855Sgabeblack@google.com	E( 78, 47); E( 79,132); E( 80, 83); E( 81,209); E( 82,  0); E( 83,237);
10512855Sgabeblack@google.com	E( 84, 32); E( 85,252); E( 86,177); E( 87, 91); E( 88,106); E( 89,203);
10612855Sgabeblack@google.com	E( 90,190); E( 91, 57); E( 92, 74); E( 93, 76); E( 94, 88); E( 95,207);
10712855Sgabeblack@google.com	E( 96,208); E( 97,239); E( 98,170); E( 99,251); E(100, 67); E(101, 77);
10812855Sgabeblack@google.com	E(102, 51); E(103,133); E(104, 69); E(105,249); E(106,  2); E(107,127);
10912855Sgabeblack@google.com	E(108, 80); E(109, 60); E(110,159); E(111,168); E(112, 81); E(113,163);
11012855Sgabeblack@google.com	E(114, 64); E(115,143); E(116,146); E(117,157); E(118, 56); E(119,245);
11112855Sgabeblack@google.com	E(120,188); E(121,182); E(122,218); E(123, 33); E(124, 16); E(125,255);
11212855Sgabeblack@google.com	E(126,243); E(127,210); E(128,205); E(129, 12); E(130, 19); E(131,236);
11312855Sgabeblack@google.com	E(132, 95); E(133,151); E(134, 68); E(135, 23); E(136,196); E(137,167);
11412855Sgabeblack@google.com	E(138,126); E(139, 61); E(140,100); E(141, 93); E(142, 25); E(143,115);
11512855Sgabeblack@google.com	E(144, 96); E(145,129); E(146, 79); E(147,220); E(148, 34); E(149, 42);
11612855Sgabeblack@google.com	E(150,144); E(151,136); E(152, 70); E(153,238); E(154,184); E(155, 20);
11712855Sgabeblack@google.com	E(156,222); E(157, 94); E(158, 11); E(159,219); E(160,224); E(161, 50);
11812855Sgabeblack@google.com	E(162, 58); E(163, 10); E(164, 73); E(165,  6); E(166, 36); E(167, 92);
11912855Sgabeblack@google.com	E(168,194); E(169,211); E(170,172); E(171, 98); E(172,145); E(173,149);
12012855Sgabeblack@google.com	E(174,228); E(175,121); E(176,231); E(177,200); E(178, 55); E(179,109);
12112855Sgabeblack@google.com	E(180,141); E(181,213); E(182, 78); E(183,169); E(184,108); E(185, 86);
12212855Sgabeblack@google.com	E(186,244); E(187,234); E(188,101); E(189,122); E(190,174); E(191,  8);
12312855Sgabeblack@google.com	E(192,186); E(193,120); E(194, 37); E(195, 46); E(196, 28); E(197,166);
12412855Sgabeblack@google.com	E(198,180); E(199,198); E(200,232); E(201,221); E(202,116); E(203, 31);
12512855Sgabeblack@google.com	E(204, 75); E(205,189); E(206,139); E(207,138); E(208,112); E(209, 62);
12612855Sgabeblack@google.com	E(210,181); E(211,102); E(212, 72); E(213,  3); E(214,246); E(215, 14);
12712855Sgabeblack@google.com	E(216, 97); E(217, 53); E(218, 87); E(219,185); E(220,134); E(221,193);
12812855Sgabeblack@google.com	E(222, 29); E(223,158); E(224,225); E(225,248); E(226,152); E(227, 17);
12912855Sgabeblack@google.com	E(228,105); E(229,217); E(230,142); E(231,148); E(232,155); E(233, 30);
13012855Sgabeblack@google.com	E(234,135); E(235,233); E(236,206); E(237, 85); E(238, 40); E(239,223);
13112855Sgabeblack@google.com	E(240,140); E(241,161); E(242,137); E(243, 13); E(244,191); E(245,230);
13212855Sgabeblack@google.com	E(246, 66); E(247,104); E(248, 65); E(249,153); E(250, 45); E(251, 15);
13312855Sgabeblack@google.com	E(252,176); E(253, 84); E(254,187); E(255, 22);
13412855Sgabeblack@google.com	}
13512855Sgabeblack@google.com#undef E
13612855Sgabeblack@google.com#endif
13712855Sgabeblack@google.com	return(t);
13812855Sgabeblack@google.com}
13912855Sgabeblack@google.com
14012855Sgabeblack@google.com
14112855Sgabeblack@google.comvoid
14212855Sgabeblack@google.comAES_Base::AddRoundKey(sc_uint<8> a[4][4], const sc_uint<8> rk[4][4])
14312855Sgabeblack@google.com{
14412855Sgabeblack@google.com	for( sc_uint<3> i = 0; i < 4; i++){
14512855Sgabeblack@google.com		for( sc_uint<3> j = 0; j < 4; j++){
14612855Sgabeblack@google.com			a[i][j] = a[i][j] ^ rk[i][j];
14712855Sgabeblack@google.com		}
14812855Sgabeblack@google.com	}
14912855Sgabeblack@google.com}
15012855Sgabeblack@google.com
15112855Sgabeblack@google.comvoid
15212855Sgabeblack@google.comAES_Base::SchedKey(sc_uint<8> k[4][4], sc_uint<8> W[11][4][4])
15312855Sgabeblack@google.com{
15412855Sgabeblack@google.com	sc_uint<3> i, j;
15512855Sgabeblack@google.com	sc_uint<8> tk[4][4];
15612855Sgabeblack@google.com	sc_uint<8> tt;
15712855Sgabeblack@google.com	sc_uint<4> t;
15812855Sgabeblack@google.com
15912855Sgabeblack@google.com	for(j = 0; j < 4; j++){
16012855Sgabeblack@google.com		for(i = 0; i < 4; i++){
16112855Sgabeblack@google.com			tk[i][j] = k[i][j];
16212855Sgabeblack@google.com		}
16312855Sgabeblack@google.com	}
16412855Sgabeblack@google.com
16512855Sgabeblack@google.com	for(j = 0; j < 4; j++){
16612855Sgabeblack@google.com		for(i = 0; i < 4; i++){
16712855Sgabeblack@google.com			W[0][i][j] = tk[i][j];
16812855Sgabeblack@google.com		}
16912855Sgabeblack@google.com	}
17012855Sgabeblack@google.com
17112855Sgabeblack@google.com	for( t = 1; t < 11; t++){
17212855Sgabeblack@google.com		for(i = 0; i < 4; i++){
17312855Sgabeblack@google.com			tk[i][0] ^= S_Table(tk[(i+1)&3][3]);
17412855Sgabeblack@google.com		}
17512855Sgabeblack@google.com
17612855Sgabeblack@google.com#if USE_TABLE
17712855Sgabeblack@google.com		{ static sc_uint<8> rcon[11] = {
17812855Sgabeblack@google.com			0x0, /* dummy entry to lineup with t's value */
17912855Sgabeblack@google.com  			0x01,
18012855Sgabeblack@google.com			0x02,
18112855Sgabeblack@google.com			0x04,
18212855Sgabeblack@google.com			0x08,
18312855Sgabeblack@google.com  			0x10,
18412855Sgabeblack@google.com			0x20,
18512855Sgabeblack@google.com			0x40,
18612855Sgabeblack@google.com			0x80,
18712855Sgabeblack@google.com  			0x1b,
18812855Sgabeblack@google.com			0x36
18912855Sgabeblack@google.com		};
19012855Sgabeblack@google.com		tt = rcon[t];
19112855Sgabeblack@google.com		}
19212855Sgabeblack@google.com#else
19312855Sgabeblack@google.com		switch(t){
19412855Sgabeblack@google.com  		case  1: tt = 0x01; break; /* 0000 0001 */
19512855Sgabeblack@google.com		case  2: tt = 0x02; break; /* 0000 0010 */
19612855Sgabeblack@google.com		case  3: tt = 0x04; break; /* 0000 0100 */
19712855Sgabeblack@google.com		case  4: tt = 0x08; break; /* 0000 1000 */
19812855Sgabeblack@google.com  		case  5: tt = 0x10; break; /* 0001 0000 */
19912855Sgabeblack@google.com		case  6: tt = 0x20; break; /* 0010 0000 */
20012855Sgabeblack@google.com		case  7: tt = 0x40; break; /* 0100 0000 */
20112855Sgabeblack@google.com		case  8: tt = 0x80; break; /* 1000 0000 */
20212855Sgabeblack@google.com  		case  9: tt = 0x1b; break; /* 0001 1011 */
20312855Sgabeblack@google.com		case 10: tt = 0x36; break; /* 0011 0110 */
20412855Sgabeblack@google.com		}
20512855Sgabeblack@google.com#endif
20612855Sgabeblack@google.com
20712855Sgabeblack@google.com		tk[0][0] ^= tt;
20812855Sgabeblack@google.com
20912855Sgabeblack@google.com		for(j = 1; j < 4; j++){
21012855Sgabeblack@google.com			for(i = 0; i < 4; i++){
21112855Sgabeblack@google.com				tk[i][j] ^= tk[i][j-1];
21212855Sgabeblack@google.com			}
21312855Sgabeblack@google.com		}
21412855Sgabeblack@google.com
21512855Sgabeblack@google.com		for(j = 0; j < 4; j++){
21612855Sgabeblack@google.com			for(i = 0; i < 4; i++){
21712855Sgabeblack@google.com				W[t][i][j] = tk[i][j];
21812855Sgabeblack@google.com			}
21912855Sgabeblack@google.com		}
22012855Sgabeblack@google.com	}
22112855Sgabeblack@google.com}
22212855Sgabeblack@google.com
22312855Sgabeblack@google.comclass AES_Decrypt : public AES_Base {
22412855Sgabeblack@google.compublic:
22512855Sgabeblack@google.com	SC_HAS_PROCESS(AES_Decrypt);
22612855Sgabeblack@google.com	AES_Decrypt(sc_module_name name,
22712855Sgabeblack@google.com		sc_clock& pCLK,
22812855Sgabeblack@google.com		sc_signal<bool>& pRST_X,
22912855Sgabeblack@google.com		sc_signal<bool>& pIn_req,
23012855Sgabeblack@google.com		sc_signal<bool>& pIn_ack,
23112855Sgabeblack@google.com		sc_signal<bool>& pIn_cmd,
23212855Sgabeblack@google.com		sc_signal<sc_biguint<128> >& pIn_wire,
23312855Sgabeblack@google.com		sc_signal<bool>& pOut_req,
23412855Sgabeblack@google.com		sc_signal<bool>& pOut_ack,
23512855Sgabeblack@google.com		sc_signal<sc_biguint<128> >& pOut_wire
23612855Sgabeblack@google.com	) : AES_Base(name)
23712855Sgabeblack@google.com	{
23812855Sgabeblack@google.com	    CLK(pCLK); RST_X(pRST_X);
23912855Sgabeblack@google.com	    In_req(pIn_req); In_ack(pIn_ack); In_cmd(pIn_cmd); In_wire(pIn_wire);
24012855Sgabeblack@google.com	    Out_req(pOut_req); Out_ack(pOut_ack); Out_wire(pOut_wire);
24112855Sgabeblack@google.com		SC_CTHREAD(MainThread, this->CLK.pos());
24212855Sgabeblack@google.com		reset_signal_is(RST_X,false);
24312855Sgabeblack@google.com	}
24412855Sgabeblack@google.com
24512855Sgabeblack@google.com	sc_in_clk CLK;
24612855Sgabeblack@google.com	sc_in<bool> RST_X;
24712855Sgabeblack@google.com
24812855Sgabeblack@google.com	sc_in<sc_biguint<128> >  In_wire;
24912855Sgabeblack@google.com	sc_out<bool>	      In_req;
25012855Sgabeblack@google.com	sc_in<bool>	      In_ack;
25112855Sgabeblack@google.com	sc_in<bool>	      In_cmd;
25212855Sgabeblack@google.com
25312855Sgabeblack@google.com	sc_out<sc_biguint<128> > Out_wire;
25412855Sgabeblack@google.com	sc_in<bool>	      Out_req;
25512855Sgabeblack@google.com	sc_out<bool>	      Out_ack;
25612855Sgabeblack@google.com
25712855Sgabeblack@google.com#define LOAD_KEY 0
25812855Sgabeblack@google.com#define DECRYPT 1
25912855Sgabeblack@google.com	sc_uint<1> cmd;
26012855Sgabeblack@google.com
26112855Sgabeblack@google.com	sc_uint<8> rk[11][4][4];
26212855Sgabeblack@google.com	sc_uint<8> R[4][4];
26312855Sgabeblack@google.com
26412855Sgabeblack@google.com	void MainThread(void);
26512855Sgabeblack@google.com	void Reset(void);
26612855Sgabeblack@google.com
26712855Sgabeblack@google.com	void Input(void);
26812855Sgabeblack@google.com	void Output(void);
26912855Sgabeblack@google.com
27012855Sgabeblack@google.com	void Decrypt(void);
27112855Sgabeblack@google.com
27212855Sgabeblack@google.com	void InvMixColumns(sc_uint<8> a[4][4]);
27312855Sgabeblack@google.com	void ShiftRows_Right_Rotate(sc_uint<8> a[4][4]);
27412855Sgabeblack@google.com	void Substitution_Si(sc_uint<8> a[4][4]);
27512855Sgabeblack@google.com	sc_uint<8> Si_Table(sc_uint<8> a);
27612855Sgabeblack@google.com
27712855Sgabeblack@google.com	sc_uint<8> dmul9(const sc_uint<8> B);
27812855Sgabeblack@google.com	sc_uint<8> dmulb(const sc_uint<8> B);
27912855Sgabeblack@google.com	sc_uint<8> dmuld(const sc_uint<8> B);
28012855Sgabeblack@google.com	sc_uint<8> dmule(const sc_uint<8> B);
28112855Sgabeblack@google.com};
28212855Sgabeblack@google.com
28312855Sgabeblack@google.comvoid
28412855Sgabeblack@google.comAES_Decrypt::Reset(void)
28512855Sgabeblack@google.com{
28612855Sgabeblack@google.com	In_req = false;
28712855Sgabeblack@google.com	Out_ack = false;
28812855Sgabeblack@google.com}
28912855Sgabeblack@google.com
29012855Sgabeblack@google.comvoid
29112855Sgabeblack@google.comAES_Decrypt::Input(void)
29212855Sgabeblack@google.com{
29312855Sgabeblack@google.com	sc_uint<8> t;
29412855Sgabeblack@google.com	sc_biguint<128> t_In_wire;
29512855Sgabeblack@google.com
29612855Sgabeblack@google.com	(void)wait();
29712855Sgabeblack@google.com	In_req = true;
29812855Sgabeblack@google.com
29912855Sgabeblack@google.com	do { wait(); } while(!In_ack);
30012855Sgabeblack@google.com
30112855Sgabeblack@google.com	cmd = In_cmd;
30212855Sgabeblack@google.com	t_In_wire = In_wire.read();
30312855Sgabeblack@google.com
30412855Sgabeblack@google.com	/*
30512855Sgabeblack@google.com	 * no matter whether it's a decrypt
30612855Sgabeblack@google.com	 * or a key_schedule, get the input pins
30712855Sgabeblack@google.com	 * into R[][].
30812855Sgabeblack@google.com	 */
30912855Sgabeblack@google.com	for(int i = 0; i < 4; i++){
31012855Sgabeblack@google.com		for(int j = 0; j < 4; j++){
31112855Sgabeblack@google.com			for( int k = 0; k < 8; k++){
31212855Sgabeblack@google.com				t[k] = t_In_wire[(i*4+j)*8+k];
31312855Sgabeblack@google.com			}
31412855Sgabeblack@google.com			R[i][j] = t;
31512855Sgabeblack@google.com		}
31612855Sgabeblack@google.com	}
31712855Sgabeblack@google.com
31812855Sgabeblack@google.com	In_req = false;
31912855Sgabeblack@google.com
32012855Sgabeblack@google.com	//Dump_R("AES_Descrypt::Input R", R);
32112855Sgabeblack@google.com}
32212855Sgabeblack@google.com
32312855Sgabeblack@google.comvoid
32412855Sgabeblack@google.comAES_Decrypt::Output(void)
32512855Sgabeblack@google.com{
32612855Sgabeblack@google.com	sc_uint<8> t;
32712855Sgabeblack@google.com	sc_biguint<128> t_Out_wire;
32812855Sgabeblack@google.com
32912855Sgabeblack@google.com	do { (void)wait(); } while(!Out_req);
33012855Sgabeblack@google.com
33112855Sgabeblack@google.com	/*
33212855Sgabeblack@google.com	 * if it's a decrypt, drive R[][] onto output pins
33312855Sgabeblack@google.com	 */
33412855Sgabeblack@google.com	if( cmd == DECRYPT){
33512855Sgabeblack@google.com		for(int i = 0; i < 4; i++){
33612855Sgabeblack@google.com			for(int j = 0; j < 4; j++){
33712855Sgabeblack@google.com				t = R[i][j];
33812855Sgabeblack@google.com				for( int k = 0; k < 8; k++){
33912855Sgabeblack@google.com					t_Out_wire[(i*4+j)*8+k] = t[k];
34012855Sgabeblack@google.com				}
34112855Sgabeblack@google.com			}
34212855Sgabeblack@google.com		}
34312855Sgabeblack@google.com		Out_wire.write(t_Out_wire);
34412855Sgabeblack@google.com
34512855Sgabeblack@google.com		//Dump_R("AES_Descrypt::Output R", R);
34612855Sgabeblack@google.com	}
34712855Sgabeblack@google.com
34812855Sgabeblack@google.com	Out_ack = true;
34912855Sgabeblack@google.com	(void)wait();
35012855Sgabeblack@google.com	Out_ack = false;
35112855Sgabeblack@google.com
35212855Sgabeblack@google.com}
35312855Sgabeblack@google.com
35412855Sgabeblack@google.comvoid
35512855Sgabeblack@google.comAES_Decrypt::MainThread(void)
35612855Sgabeblack@google.com{
35712855Sgabeblack@google.com	(void)Reset();
35812855Sgabeblack@google.com
35912855Sgabeblack@google.com	{
36012855Sgabeblack@google.com	while(!RST_X)
36112855Sgabeblack@google.com		(void)wait();
36212855Sgabeblack@google.com	}
36312855Sgabeblack@google.com
36412855Sgabeblack@google.com	for(;;){
36512855Sgabeblack@google.com		(void)Input();
36612855Sgabeblack@google.com
36712855Sgabeblack@google.com		if( cmd == LOAD_KEY ){
36812855Sgabeblack@google.com			/*
36912855Sgabeblack@google.com			 * take R[][] and expand
37012855Sgabeblack@google.com			 * it into rk[][][]
37112855Sgabeblack@google.com			 */
37212855Sgabeblack@google.com			(void)SchedKey(R, rk);
37312855Sgabeblack@google.com			(void)wait(3);
37412855Sgabeblack@google.com
37512855Sgabeblack@google.com			//Dump_rk("AES_Descrypt::MainThread rk", rk);
37612855Sgabeblack@google.com		} else {
37712855Sgabeblack@google.com			/*
37812855Sgabeblack@google.com			 * take R[][] and rk[][][]
37912855Sgabeblack@google.com			 * and decrypt the data inplace
38012855Sgabeblack@google.com			 * into R[][]
38112855Sgabeblack@google.com			 */
38212855Sgabeblack@google.com			(void)Decrypt();
38312855Sgabeblack@google.com			(void)wait(12);
38412855Sgabeblack@google.com			(void)Output();
38512855Sgabeblack@google.com		}
38612855Sgabeblack@google.com
38712855Sgabeblack@google.com	}
38812855Sgabeblack@google.com}
38912855Sgabeblack@google.com
39012855Sgabeblack@google.comvoid
39112855Sgabeblack@google.comAES_Decrypt::Decrypt(void)
39212855Sgabeblack@google.com{
39312855Sgabeblack@google.com	(void)AddRoundKey(R,rk[10]);
39412855Sgabeblack@google.com	//Dump_R("10: AES_Decrypt::AddRoundKey", R);
39512855Sgabeblack@google.com
39612855Sgabeblack@google.com	(void)Substitution_Si(R);
39712855Sgabeblack@google.com	//printf("%d: ", 10); Dump_R("AES_Decrypt::Substitution_Si", R);
39812855Sgabeblack@google.com
39912855Sgabeblack@google.com	(void)ShiftRows_Right_Rotate(R);
40012855Sgabeblack@google.com	//printf("%d: ", 10); Dump_R("AES_Decrypt::ShiftRows_Right_Rotate", R);
40112855Sgabeblack@google.com
40212855Sgabeblack@google.com	for(sc_uint<4> i = 9; i > 0; i--){
40312855Sgabeblack@google.com		(void)AddRoundKey(R, rk[i]);
40412855Sgabeblack@google.com		//printf("%d: ", (int)i); Dump_R("AES_Decrypt::AddRoundKey", R);
40512855Sgabeblack@google.com
40612855Sgabeblack@google.com		(void)InvMixColumns(R);
40712855Sgabeblack@google.com		//printf("%d: ", (int)i); Dump_R("AES_Decrypt::InvMixColums", R);
40812855Sgabeblack@google.com
40912855Sgabeblack@google.com		(void)Substitution_Si(R);
41012855Sgabeblack@google.com		//printf("%d: ", (int)i); Dump_R("AES_Decrypt::Substitution_Si", R);
41112855Sgabeblack@google.com
41212855Sgabeblack@google.com		(void)ShiftRows_Right_Rotate(R);
41312855Sgabeblack@google.com		//printf("%d: ", (int)i); Dump_R("AES_Decrypt::ShiftRows_Right_Rotate", R);
41412855Sgabeblack@google.com	}
41512855Sgabeblack@google.com
41612855Sgabeblack@google.com	(void)AddRoundKey(R, rk[0]);
41712855Sgabeblack@google.com	//Dump_R("0: AES_Decrypt::AddRoundKey", R);
41812855Sgabeblack@google.com}
41912855Sgabeblack@google.com
42012855Sgabeblack@google.comsc_uint<8>
42112855Sgabeblack@google.comAES_Decrypt::Si_Table(sc_uint<8> a)
42212855Sgabeblack@google.com{
42312855Sgabeblack@google.com	sc_uint<8> t;
42412855Sgabeblack@google.com#if USE_TABLE
42512855Sgabeblack@google.com	{
42612855Sgabeblack@google.com	static sc_uint<8> Si[256] = {
42712855Sgabeblack@google.com 		82,   9, 106, 213,  48,  54, 165,  56,
42812855Sgabeblack@google.com		191,  64, 163, 158, 129, 243, 215, 251,
42912855Sgabeblack@google.com		124, 227,  57, 130, 155,  47, 255, 135,
43012855Sgabeblack@google.com		52, 142,  67,	68, 196, 222, 233, 203,
43112855Sgabeblack@google.com 		84, 123, 148,	50, 166, 194,  35,  61,
43212855Sgabeblack@google.com		238,  76, 149,	11,  66, 250, 195,  78,
43312855Sgabeblack@google.com  		8,  46, 161, 102,  40, 217,  36, 178,
43412855Sgabeblack@google.com		118,  91, 162,	73, 109, 139, 209,  37,
43512855Sgabeblack@google.com		114, 248, 246, 100, 134, 104, 152,  22,
43612855Sgabeblack@google.com		212, 164,  92, 204,  93, 101, 182, 146,
43712855Sgabeblack@google.com		108, 112,  72,	80, 253, 237, 185, 218,
43812855Sgabeblack@google.com		94,  21,  70,	87, 167, 141, 157, 132,
43912855Sgabeblack@google.com		144, 216, 171,	 0, 140, 188, 211,  10,
44012855Sgabeblack@google.com		247, 228,  88,	 5, 184, 179,  69,   6,
44112855Sgabeblack@google.com		208,  44,  30, 143, 202,  63,  15,   2,
44212855Sgabeblack@google.com		193, 175, 189,	 3,   1,  19, 138, 107,
44312855Sgabeblack@google.com 		58, 145,  17,	65,  79, 103, 220, 234,
44412855Sgabeblack@google.com		151, 242, 207, 206, 240, 180, 230, 115,
44512855Sgabeblack@google.com		150, 172, 116,	34, 231, 173,  53, 133,
44612855Sgabeblack@google.com		226, 249,  55, 232,  28, 117, 223, 110,
44712855Sgabeblack@google.com 		71, 241,  26, 113,  29,  41, 197, 137,
44812855Sgabeblack@google.com		111, 183,  98,	14, 170,  24, 190,  27,
44912855Sgabeblack@google.com		252,  86,  62,	75, 198, 210, 121,  32,
45012855Sgabeblack@google.com		154, 219, 192, 254, 120, 205,  90, 244,
45112855Sgabeblack@google.com 		31, 221, 168,	51, 136,   7, 199,  49,
45212855Sgabeblack@google.com		177,  18,  16,	89,  39, 128, 236,  95,
45312855Sgabeblack@google.com 		96,  81, 127, 169,  25, 181,  74,  13,
45412855Sgabeblack@google.com		45, 229, 122, 159, 147, 201, 156, 239,
45512855Sgabeblack@google.com		160, 224,  59,	77, 174,  42, 245, 176,
45612855Sgabeblack@google.com		200, 235, 187,	60, 131,  83, 153,  97,
45712855Sgabeblack@google.com 		23,  43,   4, 126, 186, 119, 214,  38,
45812855Sgabeblack@google.com		225, 105,  20,	99,  85,  33,  12, 125,
45912855Sgabeblack@google.com	};
46012855Sgabeblack@google.com	t = Si[a];
46112855Sgabeblack@google.com	}
46212855Sgabeblack@google.com#else
46312855Sgabeblack@google.com#define E(A,B) case A: t = B; break
46412855Sgabeblack@google.com	switch(a){
46512855Sgabeblack@google.com	E(  0, 82); E(  1,  9); E(  2,106); E(  3,213); E(  4, 48); E(  5, 54);
46612855Sgabeblack@google.com	E(  6,165); E(  7, 56); E(  8,191); E(  9, 64); E( 10,163); E( 11,158);
46712855Sgabeblack@google.com	E( 12,129); E( 13,243); E( 14,215); E( 15,251); E( 16,124); E( 17,227);
46812855Sgabeblack@google.com	E( 18, 57); E( 19,130); E( 20,155); E( 21, 47); E( 22,255); E( 23,135);
46912855Sgabeblack@google.com	E( 24, 52); E( 25,142); E( 26, 67); E( 27, 68); E( 28,196); E( 29,222);
47012855Sgabeblack@google.com	E( 30,233); E( 31,203); E( 32, 84); E( 33,123); E( 34,148); E( 35, 50);
47112855Sgabeblack@google.com	E( 36,166); E( 37,194); E( 38, 35); E( 39, 61); E( 40,238); E( 41, 76);
47212855Sgabeblack@google.com	E( 42,149); E( 43, 11); E( 44, 66); E( 45,250); E( 46,195); E( 47, 78);
47312855Sgabeblack@google.com	E( 48,  8); E( 49, 46); E( 50,161); E( 51,102); E( 52, 40); E( 53,217);
47412855Sgabeblack@google.com	E( 54, 36); E( 55,178); E( 56,118); E( 57, 91); E( 58,162); E( 59, 73);
47512855Sgabeblack@google.com	E( 60,109); E( 61,139); E( 62,209); E( 63, 37); E( 64,114); E( 65,248);
47612855Sgabeblack@google.com	E( 66,246); E( 67,100); E( 68,134); E( 69,104); E( 70,152); E( 71, 22);
47712855Sgabeblack@google.com	E( 72,212); E( 73,164); E( 74, 92); E( 75,204); E( 76, 93); E( 77,101);
47812855Sgabeblack@google.com	E( 78,182); E( 79,146); E( 80,108); E( 81,112); E( 82, 72); E( 83, 80);
47912855Sgabeblack@google.com	E( 84,253); E( 85,237); E( 86,185); E( 87,218); E( 88, 94); E( 89, 21);
48012855Sgabeblack@google.com	E( 90, 70); E( 91, 87); E( 92,167); E( 93,141); E( 94,157); E( 95,132);
48112855Sgabeblack@google.com	E( 96,144); E( 97,216); E( 98,171); E( 99,  0); E(100,140); E(101,188);
48212855Sgabeblack@google.com	E(102,211); E(103, 10); E(104,247); E(105,228); E(106, 88); E(107,  5);
48312855Sgabeblack@google.com	E(108,184); E(109,179); E(110, 69); E(111,  6); E(112,208); E(113, 44);
48412855Sgabeblack@google.com	E(114, 30); E(115,143); E(116,202); E(117, 63); E(118, 15); E(119,  2);
48512855Sgabeblack@google.com	E(120,193); E(121,175); E(122,189); E(123,  3); E(124,  1); E(125, 19);
48612855Sgabeblack@google.com	E(126,138); E(127,107); E(128, 58); E(129,145); E(130, 17); E(131, 65);
48712855Sgabeblack@google.com	E(132, 79); E(133,103); E(134,220); E(135,234); E(136,151); E(137,242);
48812855Sgabeblack@google.com	E(138,207); E(139,206); E(140,240); E(141,180); E(142,230); E(143,115);
48912855Sgabeblack@google.com	E(144,150); E(145,172); E(146,116); E(147, 34); E(148,231); E(149,173);
49012855Sgabeblack@google.com	E(150, 53); E(151,133); E(152,226); E(153,249); E(154, 55); E(155,232);
49112855Sgabeblack@google.com	E(156, 28); E(157,117); E(158,223); E(159,110); E(160, 71); E(161,241);
49212855Sgabeblack@google.com	E(162, 26); E(163,113); E(164, 29); E(165, 41); E(166,197); E(167,137);
49312855Sgabeblack@google.com	E(168,111); E(169,183); E(170, 98); E(171, 14); E(172,170); E(173, 24);
49412855Sgabeblack@google.com	E(174,190); E(175, 27); E(176,252); E(177, 86); E(178, 62); E(179, 75);
49512855Sgabeblack@google.com	E(180,198); E(181,210); E(182,121); E(183, 32); E(184,154); E(185,219);
49612855Sgabeblack@google.com	E(186,192); E(187,254); E(188,120); E(189,205); E(190, 90); E(191,244);
49712855Sgabeblack@google.com	E(192, 31); E(193,221); E(194,168); E(195, 51); E(196,136); E(197,  7);
49812855Sgabeblack@google.com	E(198,199); E(199, 49); E(200,177); E(201, 18); E(202, 16); E(203, 89);
49912855Sgabeblack@google.com	E(204, 39); E(205,128); E(206,236); E(207, 95); E(208, 96); E(209, 81);
50012855Sgabeblack@google.com	E(210,127); E(211,169); E(212, 25); E(213,181); E(214, 74); E(215, 13);
50112855Sgabeblack@google.com	E(216, 45); E(217,229); E(218,122); E(219,159); E(220,147); E(221,201);
50212855Sgabeblack@google.com	E(222,156); E(223,239); E(224,160); E(225,224); E(226, 59); E(227, 77);
50312855Sgabeblack@google.com	E(228,174); E(229, 42); E(230,245); E(231,176); E(232,200); E(233,235);
50412855Sgabeblack@google.com	E(234,187); E(235, 60); E(236,131); E(237, 83); E(238,153); E(239, 97);
50512855Sgabeblack@google.com	E(240, 23); E(241, 43); E(242,  4); E(243,126); E(244,186); E(245,119);
50612855Sgabeblack@google.com	E(246,214); E(247, 38); E(248,225); E(249,105); E(250, 20); E(251, 99);
50712855Sgabeblack@google.com	E(252, 85); E(253, 33); E(254, 12); E(255,125);
50812855Sgabeblack@google.com	}
50912855Sgabeblack@google.com#undef E
51012855Sgabeblack@google.com#endif
51112855Sgabeblack@google.com	return(t);
51212855Sgabeblack@google.com}
51312855Sgabeblack@google.comvoid
51412855Sgabeblack@google.comAES_Decrypt::Substitution_Si(sc_uint<8> a[4][4])
51512855Sgabeblack@google.com{
51612855Sgabeblack@google.com	for(sc_uint<3> j = 0; j < 4; j++){
51712855Sgabeblack@google.com		for( sc_uint<3> i = 0; i < 4; i++){
51812855Sgabeblack@google.com			a[i][j] = Si_Table(a[i][j]);
51912855Sgabeblack@google.com		}
52012855Sgabeblack@google.com	}
52112855Sgabeblack@google.com}
52212855Sgabeblack@google.com
52312855Sgabeblack@google.com/*
52412855Sgabeblack@google.com * this routine does a rotate right
52512855Sgabeblack@google.com * on each row.  the first is rotated 0,
52612855Sgabeblack@google.com * ie, nothing is done.   the second row
52712855Sgabeblack@google.com * is roatated by 1, the third row by 2
52812855Sgabeblack@google.com * and the finally row by 3.
52912855Sgabeblack@google.com * ie:
53012855Sgabeblack@google.com *
53112855Sgabeblack@google.com *	row0	row1	row2	row3
53212855Sgabeblack@google.com *      0123    0123    0123    0123
53312855Sgabeblack@google.com *	||||    ||||    ||||    ||||
53412855Sgabeblack@google.com *	0123    3012    2301    1230
53512855Sgabeblack@google.com *
53612855Sgabeblack@google.com * this is equivalent to ShiftRows(1,...)
53712855Sgabeblack@google.com * code in the reference C code.   it
53812855Sgabeblack@google.com * has been expanded to get rid of the
53912855Sgabeblack@google.com * shifts[][][] array used at run time.
54012855Sgabeblack@google.com */
54112855Sgabeblack@google.comvoid
54212855Sgabeblack@google.comAES_Decrypt::ShiftRows_Right_Rotate(sc_uint<8> a[4][4])
54312855Sgabeblack@google.com{
54412855Sgabeblack@google.com	sc_uint<8> t;
54512855Sgabeblack@google.com
54612855Sgabeblack@google.com	t = a[1][3];
54712855Sgabeblack@google.com	a[1][3] = a[1][2];
54812855Sgabeblack@google.com	a[1][2] = a[1][1];
54912855Sgabeblack@google.com	a[1][1] = a[1][0];
55012855Sgabeblack@google.com	a[1][0] = t;
55112855Sgabeblack@google.com
55212855Sgabeblack@google.com	t = a[2][0];
55312855Sgabeblack@google.com	a[2][0] = a[2][2];
55412855Sgabeblack@google.com	a[2][2] = t;
55512855Sgabeblack@google.com	t = a[2][1];
55612855Sgabeblack@google.com	a[2][1] = a[2][3];
55712855Sgabeblack@google.com	a[2][3] = t;
55812855Sgabeblack@google.com
55912855Sgabeblack@google.com	t = a[3][0];
56012855Sgabeblack@google.com	a[3][0] = a[3][1];
56112855Sgabeblack@google.com	a[3][1] = a[3][2];
56212855Sgabeblack@google.com	a[3][2] = a[3][3];
56312855Sgabeblack@google.com	a[3][3] = t;
56412855Sgabeblack@google.com
56512855Sgabeblack@google.com}
56612855Sgabeblack@google.com
56712855Sgabeblack@google.comvoid
56812855Sgabeblack@google.comAES_Decrypt::InvMixColumns(sc_uint<8> a[4][4])
56912855Sgabeblack@google.com{
57012855Sgabeblack@google.com	sc_uint<8> t[4][4];
57112855Sgabeblack@google.com
57212855Sgabeblack@google.com	for(sc_uint<3> j = 0; j < 4; j++){
57312855Sgabeblack@google.com		for( sc_uint<3> i = 0; i < 4; i++){
57412855Sgabeblack@google.com			t[i][j] = dmule(a[i][j])
57512855Sgabeblack@google.com			          ^ dmulb(a[(i + 1) & 3][j])
57612855Sgabeblack@google.com			          ^ dmuld(a[(i + 2) & 3][j])
57712855Sgabeblack@google.com			          ^ dmul9(a[(i + 3) & 3][j]);
57812855Sgabeblack@google.com		}
57912855Sgabeblack@google.com	}
58012855Sgabeblack@google.com
58112855Sgabeblack@google.com	for(sc_uint<3> j = 0; j < 4; j++){
58212855Sgabeblack@google.com		for( sc_uint<3> i = 0; i < 4; i++){
58312855Sgabeblack@google.com			a[i][j] = t[i][j];
58412855Sgabeblack@google.com		}
58512855Sgabeblack@google.com	}
58612855Sgabeblack@google.com}
58712855Sgabeblack@google.com
58812855Sgabeblack@google.comsc_uint<8>
58912855Sgabeblack@google.comAES_Decrypt::dmul9(const sc_uint<8> B)
59012855Sgabeblack@google.com{
59112855Sgabeblack@google.com	sc_uint<8> O;
59212855Sgabeblack@google.com
59312855Sgabeblack@google.com	O[0] = B[5]          ^B[0];
59412855Sgabeblack@google.com	O[1] = B[5]^B[6]     ^B[1];
59512855Sgabeblack@google.com	O[2] = B[6]^B[7]     ^B[2];
59612855Sgabeblack@google.com	O[3] = B[0]^B[7]^B[5]^B[3];
59712855Sgabeblack@google.com	O[4] = B[1]^B[6]^B[5]^B[4];
59812855Sgabeblack@google.com	O[5] = B[7]^B[2]^B[6]^B[5];
59912855Sgabeblack@google.com	O[6] = B[7]^B[3]     ^B[6];
60012855Sgabeblack@google.com	O[7] = B[4]          ^B[7];
60112855Sgabeblack@google.com
60212855Sgabeblack@google.com	return(O);
60312855Sgabeblack@google.com}
60412855Sgabeblack@google.com
60512855Sgabeblack@google.comsc_uint<8>
60612855Sgabeblack@google.comAES_Decrypt::dmulb(const sc_uint<8> B)
60712855Sgabeblack@google.com{
60812855Sgabeblack@google.com	sc_uint<8> O;
60912855Sgabeblack@google.com
61012855Sgabeblack@google.com	O[0] = B[5]           ^B[7]      ^B[0];
61112855Sgabeblack@google.com	O[1] = B[5]^B[6]      ^B[0]^B[7] ^B[1];
61212855Sgabeblack@google.com	O[2] = B[6]^B[7]      ^B[1]      ^B[2];
61312855Sgabeblack@google.com	O[3] = B[0]^B[5]      ^B[2]      ^B[3];
61412855Sgabeblack@google.com	O[4] = B[1]^B[6]^B[5] ^B[3]^B[7] ^B[4];
61512855Sgabeblack@google.com	O[5] = B[7]^B[2]^B[6] ^B[4]      ^B[5];
61612855Sgabeblack@google.com	O[6] = B[7]^B[3]      ^B[5]      ^B[6];
61712855Sgabeblack@google.com	O[7] = B[4]           ^B[6]      ^B[7];
61812855Sgabeblack@google.com
61912855Sgabeblack@google.com	return(O);
62012855Sgabeblack@google.com}
62112855Sgabeblack@google.com
62212855Sgabeblack@google.comsc_uint<8>
62312855Sgabeblack@google.comAES_Decrypt::dmuld(const sc_uint<8> B)
62412855Sgabeblack@google.com{
62512855Sgabeblack@google.com	sc_uint<8> O;
62612855Sgabeblack@google.com
62712855Sgabeblack@google.com	O[0] = B[5]           ^B[6]      ^B[0];
62812855Sgabeblack@google.com	O[1] = B[5]           ^B[7]      ^B[1];
62912855Sgabeblack@google.com	O[2] = B[6]           ^B[0]      ^B[2];
63012855Sgabeblack@google.com	O[3] = B[0]^B[7]^B[5] ^B[1]^B[6] ^B[3];
63112855Sgabeblack@google.com	O[4] = B[1]^B[5]      ^B[2]^B[7] ^B[4];
63212855Sgabeblack@google.com	O[5] = B[2]^B[6]      ^B[3]      ^B[5];
63312855Sgabeblack@google.com	O[6] = B[7]^B[3]      ^B[4]      ^B[6];
63412855Sgabeblack@google.com	O[7] = B[4]           ^B[5]      ^B[7];
63512855Sgabeblack@google.com
63612855Sgabeblack@google.com	return(O);
63712855Sgabeblack@google.com}
63812855Sgabeblack@google.com
63912855Sgabeblack@google.comsc_uint<8>
64012855Sgabeblack@google.comAES_Decrypt::dmule(const sc_uint<8> B)
64112855Sgabeblack@google.com{
64212855Sgabeblack@google.com	sc_uint<8> O;
64312855Sgabeblack@google.com
64412855Sgabeblack@google.com	O[0] = B[5]           ^B[6]      ^B[7];
64512855Sgabeblack@google.com	O[1] = B[5]           ^B[7]      ^B[0]^B[7];
64612855Sgabeblack@google.com	O[2] = B[6]           ^B[0]      ^B[1];
64712855Sgabeblack@google.com	O[3] = B[0]^B[7]^B[5] ^B[1]^B[6] ^B[2]^B[7];
64812855Sgabeblack@google.com	O[4] = B[1]^B[5]      ^B[2]^B[7] ^B[3]^B[7];
64912855Sgabeblack@google.com	O[5] = B[2]^B[6]      ^B[3]      ^B[4];
65012855Sgabeblack@google.com	O[6] = B[7]^B[3]      ^B[4]      ^B[5];
65112855Sgabeblack@google.com	O[7] = B[4]           ^B[5]      ^B[6];
65212855Sgabeblack@google.com
65312855Sgabeblack@google.com	return(O);
65412855Sgabeblack@google.com}
65512855Sgabeblack@google.com
65612855Sgabeblack@google.comclass AES_Encrypt : public AES_Base {
65712855Sgabeblack@google.compublic:
65812855Sgabeblack@google.com	SC_HAS_PROCESS(AES_Encrypt);
65912855Sgabeblack@google.com	AES_Encrypt(sc_module_name name,
66012855Sgabeblack@google.com		    sc_clock& pCLK,
66112855Sgabeblack@google.com		    sc_signal<bool>& pRST_X,
66212855Sgabeblack@google.com		    sc_signal<bool>& pIn_req,
66312855Sgabeblack@google.com		    sc_signal<bool>& pIn_ack,
66412855Sgabeblack@google.com		    sc_signal<bool>& pIn_cmd,
66512855Sgabeblack@google.com		    sc_signal<sc_biguint<128> >& pIn_wire,
66612855Sgabeblack@google.com		    sc_signal<bool>& pOut_req,
66712855Sgabeblack@google.com		    sc_signal<bool>& pOut_ack,
66812855Sgabeblack@google.com		    sc_signal<sc_biguint<128> >& pOut_wire
66912855Sgabeblack@google.com	) : AES_Base(name)
67012855Sgabeblack@google.com	{
67112855Sgabeblack@google.com	    CLK(pCLK); RST_X(pRST_X);
67212855Sgabeblack@google.com	    In_req(pIn_req); In_ack(pIn_ack); In_cmd(pIn_cmd); In_wire(pIn_wire);
67312855Sgabeblack@google.com	    Out_req(pOut_req); Out_ack(pOut_ack); Out_wire(pOut_wire);
67412855Sgabeblack@google.com		SC_CTHREAD(MainThread, this->CLK.pos());
67512855Sgabeblack@google.com		reset_signal_is(RST_X,false);
67612855Sgabeblack@google.com	}
67712855Sgabeblack@google.com
67812855Sgabeblack@google.com	sc_in_clk CLK;
67912855Sgabeblack@google.com	sc_in<bool> RST_X;
68012855Sgabeblack@google.com
68112855Sgabeblack@google.com	sc_in<sc_biguint<128> >  In_wire;
68212855Sgabeblack@google.com	sc_out<bool>	      In_req;
68312855Sgabeblack@google.com	sc_in<bool>	      In_ack;
68412855Sgabeblack@google.com	sc_in<bool>	      In_cmd;
68512855Sgabeblack@google.com
68612855Sgabeblack@google.com	sc_out<sc_biguint<128> > Out_wire;
68712855Sgabeblack@google.com	sc_in<bool>	      Out_req;
68812855Sgabeblack@google.com	sc_out<bool>	      Out_ack;
68912855Sgabeblack@google.com
69012855Sgabeblack@google.com#define LOAD_KEY 0
69112855Sgabeblack@google.com#define ENCRYPT 1
69212855Sgabeblack@google.com	sc_uint<1> cmd;
69312855Sgabeblack@google.com	sc_uint<8> rk[11][4][4];
69412855Sgabeblack@google.com	sc_uint<8> R[4][4];
69512855Sgabeblack@google.com
69612855Sgabeblack@google.com	void MainThread(void);
69712855Sgabeblack@google.com	void Reset(void);
69812855Sgabeblack@google.com
69912855Sgabeblack@google.com	void Input(void);
70012855Sgabeblack@google.com	void Output(void);
70112855Sgabeblack@google.com
70212855Sgabeblack@google.com	void Encrypt(void);
70312855Sgabeblack@google.com
70412855Sgabeblack@google.com	void MixColumns(sc_uint<8> a[4][4]);
70512855Sgabeblack@google.com	void ShiftRows_Left_Rotate(sc_uint<8> a[4][4]);
70612855Sgabeblack@google.com	void Substitution_S(sc_uint<8> a[4][4]);
70712855Sgabeblack@google.com
70812855Sgabeblack@google.com	sc_uint<8> dmul2(const sc_uint<8> B);
70912855Sgabeblack@google.com	sc_uint<8> dmul3(const sc_uint<8> B);
71012855Sgabeblack@google.com};
71112855Sgabeblack@google.com
71212855Sgabeblack@google.com
71312855Sgabeblack@google.comvoid
71412855Sgabeblack@google.comAES_Encrypt::Reset(void)
71512855Sgabeblack@google.com{
71612855Sgabeblack@google.com	In_req = false;
71712855Sgabeblack@google.com	Out_ack = false;
71812855Sgabeblack@google.com}
71912855Sgabeblack@google.com
72012855Sgabeblack@google.comvoid
72112855Sgabeblack@google.comAES_Encrypt::Input(void)
72212855Sgabeblack@google.com{
72312855Sgabeblack@google.com	sc_biguint<128> t_In_wire;
72412855Sgabeblack@google.com	sc_uint<8> t;
72512855Sgabeblack@google.com
72612855Sgabeblack@google.com	(void)wait();
72712855Sgabeblack@google.com	In_req = true;
72812855Sgabeblack@google.com
72912855Sgabeblack@google.com	do { wait(); } while(!In_ack);
73012855Sgabeblack@google.com
73112855Sgabeblack@google.com	cmd = In_cmd;
73212855Sgabeblack@google.com	t_In_wire = In_wire.read();
73312855Sgabeblack@google.com
73412855Sgabeblack@google.com	/*
73512855Sgabeblack@google.com	 * no matter whether it's a decrypt
73612855Sgabeblack@google.com	 * or a key_schedule, get the input pins
73712855Sgabeblack@google.com	 * into R[][].
73812855Sgabeblack@google.com	 */
73912855Sgabeblack@google.com	for(int i = 0; i < 4; i++){
74012855Sgabeblack@google.com		for(int j = 0; j < 4; j++){
74112855Sgabeblack@google.com			for( int k = 0; k < 8; k++){
74212855Sgabeblack@google.com				t[k] = t_In_wire[(i*4+j)*8+k];
74312855Sgabeblack@google.com			}
74412855Sgabeblack@google.com			R[i][j] = t;
74512855Sgabeblack@google.com		}
74612855Sgabeblack@google.com	}
74712855Sgabeblack@google.com
74812855Sgabeblack@google.com	In_req = false;
74912855Sgabeblack@google.com
75012855Sgabeblack@google.com	//Dump_R("AES_Encrypt::Input R", R);
75112855Sgabeblack@google.com}
75212855Sgabeblack@google.com
75312855Sgabeblack@google.comvoid
75412855Sgabeblack@google.comAES_Encrypt::Output(void)
75512855Sgabeblack@google.com{
75612855Sgabeblack@google.com	sc_biguint<128> t_Out_wire;
75712855Sgabeblack@google.com	sc_uint<8> t;
75812855Sgabeblack@google.com
75912855Sgabeblack@google.com	do { (void)wait(); } while(!Out_req);
76012855Sgabeblack@google.com
76112855Sgabeblack@google.com	/*
76212855Sgabeblack@google.com	 * if it's a encrypt, drive R[][] onto output pins
76312855Sgabeblack@google.com	 */
76412855Sgabeblack@google.com	if( cmd == ENCRYPT){
76512855Sgabeblack@google.com		for(int i = 0; i < 4; i++){
76612855Sgabeblack@google.com			for(int j = 0; j < 4; j++){
76712855Sgabeblack@google.com				t = R[i][j];
76812855Sgabeblack@google.com				for( int k = 0; k < 8; k++){
76912855Sgabeblack@google.com					t_Out_wire[(i*4+j)*8+k] = t[k];
77012855Sgabeblack@google.com				}
77112855Sgabeblack@google.com			}
77212855Sgabeblack@google.com		}
77312855Sgabeblack@google.com
77412855Sgabeblack@google.com		(void)Out_wire.write(t_Out_wire);
77512855Sgabeblack@google.com
77612855Sgabeblack@google.com		//Dump_R("AES_Encrypt::Output R", R);
77712855Sgabeblack@google.com	}
77812855Sgabeblack@google.com
77912855Sgabeblack@google.com	Out_ack = true;
78012855Sgabeblack@google.com	wait();
78112855Sgabeblack@google.com	Out_ack = false;
78212855Sgabeblack@google.com
78312855Sgabeblack@google.com}
78412855Sgabeblack@google.com
78512855Sgabeblack@google.comvoid
78612855Sgabeblack@google.comAES_Encrypt::MainThread(void)
78712855Sgabeblack@google.com{
78812855Sgabeblack@google.com	(void)Reset();
78912855Sgabeblack@google.com
79012855Sgabeblack@google.com	{
79112855Sgabeblack@google.com	while(!RST_X)
79212855Sgabeblack@google.com		(void)wait();
79312855Sgabeblack@google.com	}
79412855Sgabeblack@google.com
79512855Sgabeblack@google.com	for(;;){
79612855Sgabeblack@google.com		(void)Input();
79712855Sgabeblack@google.com
79812855Sgabeblack@google.com		if( cmd == LOAD_KEY){
79912855Sgabeblack@google.com			/*
80012855Sgabeblack@google.com			 * take R[][] and expand
80112855Sgabeblack@google.com			 * it into rk[][][]
80212855Sgabeblack@google.com			 */
80312855Sgabeblack@google.com			(void)SchedKey(R, rk);
80412855Sgabeblack@google.com			(void)wait(3);
80512855Sgabeblack@google.com			//Dump_rk("AES_Encrypt::MainThread rk", rk);
80612855Sgabeblack@google.com		} else {
80712855Sgabeblack@google.com			/*
80812855Sgabeblack@google.com			 * take R[][] and rk[][][]
80912855Sgabeblack@google.com			 * and encrypt the data inplace
81012855Sgabeblack@google.com			 * into R[][]
81112855Sgabeblack@google.com			 */
81212855Sgabeblack@google.com			(void)Encrypt();
81312855Sgabeblack@google.com			(void)wait(12);
81412855Sgabeblack@google.com			(void)Output();
81512855Sgabeblack@google.com		}
81612855Sgabeblack@google.com	}
81712855Sgabeblack@google.com}
81812855Sgabeblack@google.com
81912855Sgabeblack@google.comvoid
82012855Sgabeblack@google.comAES_Encrypt::Encrypt(void)
82112855Sgabeblack@google.com{
82212855Sgabeblack@google.com	(void)AddRoundKey(R, rk[0]);
82312855Sgabeblack@google.com	//Dump_R("0: AES_Encrypt::AddRoundKey", R);
82412855Sgabeblack@google.com
82512855Sgabeblack@google.com	for(sc_uint<4> i = 1; i < 10; i++){
82612855Sgabeblack@google.com		(void)Substitution_S(R);
82712855Sgabeblack@google.com		//printf("%d: ", (int)i); Dump_R("AES_Encrypt::Substitution_S", R);
82812855Sgabeblack@google.com
82912855Sgabeblack@google.com		(void)ShiftRows_Left_Rotate(R);
83012855Sgabeblack@google.com		//printf("%d: ", (int)i); Dump_R("AES_Encrypt::ShiftRows_Left_Rotate", R);
83112855Sgabeblack@google.com
83212855Sgabeblack@google.com		(void)MixColumns(R);
83312855Sgabeblack@google.com		//printf("%d: ", (int)i); Dump_R("AES_Encrypt::MixColums", R);
83412855Sgabeblack@google.com
83512855Sgabeblack@google.com		(void)AddRoundKey(R, rk[i]);
83612855Sgabeblack@google.com		//printf("%d: ", (int)i); Dump_R("AES_Encrypt::AddRoundKey", R);
83712855Sgabeblack@google.com	}
83812855Sgabeblack@google.com
83912855Sgabeblack@google.com	(void)Substitution_S(R);
84012855Sgabeblack@google.com	//printf("%d: ", 10); Dump_R("AES_Encrypt::Substitution_S", R);
84112855Sgabeblack@google.com
84212855Sgabeblack@google.com	(void)ShiftRows_Left_Rotate(R);
84312855Sgabeblack@google.com	//printf("%d: ", 10); Dump_R("AES_Encrypt::ShiftRows_Left_Rotate", R);
84412855Sgabeblack@google.com
84512855Sgabeblack@google.com	(void)AddRoundKey(R,rk[10]);
84612855Sgabeblack@google.com	//printf("%d: ", 10); Dump_R("AES_Encrypt::AddRoundKey", R);
84712855Sgabeblack@google.com}
84812855Sgabeblack@google.com
84912855Sgabeblack@google.com
85012855Sgabeblack@google.comvoid
85112855Sgabeblack@google.comAES_Encrypt::Substitution_S(sc_uint<8> a[4][4])
85212855Sgabeblack@google.com{
85312855Sgabeblack@google.com	for(sc_uint<3> j = 0; j < 4; j++){
85412855Sgabeblack@google.com		for( sc_uint<3> i = 0; i < 4; i++){
85512855Sgabeblack@google.com			a[i][j] = S_Table(a[i][j]);
85612855Sgabeblack@google.com		}
85712855Sgabeblack@google.com	}
85812855Sgabeblack@google.com}
85912855Sgabeblack@google.com
86012855Sgabeblack@google.com/*
86112855Sgabeblack@google.com * this routine does a rotate left
86212855Sgabeblack@google.com * on each row.  the first is rotated 0,
86312855Sgabeblack@google.com * ie, nothing is done.   the second row
86412855Sgabeblack@google.com * is roatated by 1, the third row by 2
86512855Sgabeblack@google.com * and the finally row by 3.
86612855Sgabeblack@google.com * ie:
86712855Sgabeblack@google.com *
86812855Sgabeblack@google.com *	row0	row1	row2	row3
86912855Sgabeblack@google.com *      0123    0123    0123    0123
87012855Sgabeblack@google.com *	||||    ||||    ||||    ||||
87112855Sgabeblack@google.com *	0123    1230    2301    3012
87212855Sgabeblack@google.com *
87312855Sgabeblack@google.com * this is equivalent to ShiftRows(0,...)
87412855Sgabeblack@google.com * code in the reference C code.   it
87512855Sgabeblack@google.com * has been expanded to get rid of the
87612855Sgabeblack@google.com * shifts[][][] array used at run time.
87712855Sgabeblack@google.com */
87812855Sgabeblack@google.comvoid
87912855Sgabeblack@google.comAES_Encrypt::ShiftRows_Left_Rotate(sc_uint<8> a[4][4])
88012855Sgabeblack@google.com{
88112855Sgabeblack@google.com	sc_uint<8> t;
88212855Sgabeblack@google.com
88312855Sgabeblack@google.com	t = a[1][0];
88412855Sgabeblack@google.com	a[1][0] = a[1][1];
88512855Sgabeblack@google.com	a[1][1] = a[1][2];
88612855Sgabeblack@google.com	a[1][2] = a[1][3];
88712855Sgabeblack@google.com	a[1][3] = t;
88812855Sgabeblack@google.com
88912855Sgabeblack@google.com	t = a[2][0];
89012855Sgabeblack@google.com	a[2][0] = a[2][2];
89112855Sgabeblack@google.com	a[2][2] = t;
89212855Sgabeblack@google.com	t = a[2][1];
89312855Sgabeblack@google.com	a[2][1] = a[2][3];
89412855Sgabeblack@google.com	a[2][3] = t;
89512855Sgabeblack@google.com
89612855Sgabeblack@google.com	t = a[3][3];
89712855Sgabeblack@google.com	a[3][3] = a[3][2];
89812855Sgabeblack@google.com	a[3][2] = a[3][1];
89912855Sgabeblack@google.com	a[3][1] = a[3][0];
90012855Sgabeblack@google.com	a[3][0] = t;
90112855Sgabeblack@google.com}
90212855Sgabeblack@google.com
90312855Sgabeblack@google.comvoid
90412855Sgabeblack@google.comAES_Encrypt::MixColumns(sc_uint<8> a[4][4])
90512855Sgabeblack@google.com{
90612855Sgabeblack@google.com	sc_uint<8> t[4][4];
90712855Sgabeblack@google.com
90812855Sgabeblack@google.com	for(sc_uint<3> j = 0; j < 4; j++){
90912855Sgabeblack@google.com		for( sc_uint<3> i = 0; i < 4; i++){
91012855Sgabeblack@google.com			t[i][j] = dmul2(a[i][j])
91112855Sgabeblack@google.com                                ^ dmul3(a[(i + 1) & 3][j])
91212855Sgabeblack@google.com                                ^ a[(i + 2) & 3][j]
91312855Sgabeblack@google.com                                ^ a[(i + 3) & 3][j];
91412855Sgabeblack@google.com
91512855Sgabeblack@google.com		}
91612855Sgabeblack@google.com	}
91712855Sgabeblack@google.com
91812855Sgabeblack@google.com	for(sc_uint<3> j = 0; j < 4; j++){
91912855Sgabeblack@google.com		for( sc_uint<3> i = 0; i < 4; i++){
92012855Sgabeblack@google.com			a[i][j] = t[i][j];
92112855Sgabeblack@google.com		}
92212855Sgabeblack@google.com	}
92312855Sgabeblack@google.com}
92412855Sgabeblack@google.com
92512855Sgabeblack@google.com
92612855Sgabeblack@google.com
92712855Sgabeblack@google.comsc_uint<8>
92812855Sgabeblack@google.comAES_Encrypt::dmul2(const sc_uint<8> B)
92912855Sgabeblack@google.com{
93012855Sgabeblack@google.com	sc_uint<8> O;
93112855Sgabeblack@google.com
93212855Sgabeblack@google.com	O[0] = B[7];
93312855Sgabeblack@google.com	O[1] = B[0]^B[7];
93412855Sgabeblack@google.com	O[2] = B[1];
93512855Sgabeblack@google.com	O[3] = B[2]^B[7];
93612855Sgabeblack@google.com	O[4] = B[3]^B[7];
93712855Sgabeblack@google.com	O[5] = B[4];
93812855Sgabeblack@google.com	O[6] = B[5];
93912855Sgabeblack@google.com	O[7] = B[6];
94012855Sgabeblack@google.com
94112855Sgabeblack@google.com	return(O);
94212855Sgabeblack@google.com}
94312855Sgabeblack@google.com
94412855Sgabeblack@google.comsc_uint<8>
94512855Sgabeblack@google.comAES_Encrypt::dmul3(const sc_uint<8> B)
94612855Sgabeblack@google.com{
94712855Sgabeblack@google.com	sc_uint<8> O;
94812855Sgabeblack@google.com
94912855Sgabeblack@google.com	O[0] = B[7]     ^B[0];
95012855Sgabeblack@google.com	O[1] = B[0]^B[7]^B[1];
95112855Sgabeblack@google.com	O[2] = B[1]     ^B[2];
95212855Sgabeblack@google.com	O[3] = B[2]^B[7]^B[3];
95312855Sgabeblack@google.com	O[4] = B[3]^B[7]^B[4];
95412855Sgabeblack@google.com	O[5] = B[4]     ^B[5];
95512855Sgabeblack@google.com	O[6] = B[5]     ^B[6];
95612855Sgabeblack@google.com	O[7] = B[6]     ^B[7];
95712855Sgabeblack@google.com
95812855Sgabeblack@google.com	return(O);
95912855Sgabeblack@google.com}
96012855Sgabeblack@google.com
96112855Sgabeblack@google.com#define TESTBENCH 1
96212855Sgabeblack@google.com#if TESTBENCH
96312855Sgabeblack@google.com
96412855Sgabeblack@google.comsc_biguint<128>
96512855Sgabeblack@google.comstr2biguint(char *s)
96612855Sgabeblack@google.com{
96712855Sgabeblack@google.com	static sc_biguint<128> a;
96812855Sgabeblack@google.com	char str[16];
96912855Sgabeblack@google.com	int i, c;
97012855Sgabeblack@google.com
97112855Sgabeblack@google.com	for(i = 0; i < 16 && *s != '\0'; i++, s++)
97212855Sgabeblack@google.com		str[i] = *s;
97312855Sgabeblack@google.com
97412855Sgabeblack@google.com	while( i < 16)
97512855Sgabeblack@google.com		str[i++] = ' ';
97612855Sgabeblack@google.com
97712855Sgabeblack@google.com	for(i = 0; i < 16; i++){
97812855Sgabeblack@google.com		c = str[i];
97912855Sgabeblack@google.com		a[(i*8)+0] = (c&1);
98012855Sgabeblack@google.com		a[(i*8)+1] = ((c>>1)&1);
98112855Sgabeblack@google.com		a[(i*8)+2] = ((c>>2)&1);
98212855Sgabeblack@google.com		a[(i*8)+3] = ((c>>3)&1);
98312855Sgabeblack@google.com		a[(i*8)+4] = ((c>>4)&1);
98412855Sgabeblack@google.com		a[(i*8)+5] = ((c>>5)&1);
98512855Sgabeblack@google.com		a[(i*8)+6] = ((c>>6)&1);
98612855Sgabeblack@google.com		a[(i*8)+7] = ((c>>7)&1);
98712855Sgabeblack@google.com	}
98812855Sgabeblack@google.com
98912855Sgabeblack@google.com	return(a);
99012855Sgabeblack@google.com}
99112855Sgabeblack@google.com
99212855Sgabeblack@google.comchar *
99312855Sgabeblack@google.combiguint2str(sc_biguint<128> a)
99412855Sgabeblack@google.com{
99512855Sgabeblack@google.com	static char str[17];
99612855Sgabeblack@google.com	int i;
99712855Sgabeblack@google.com	char c;
99812855Sgabeblack@google.com
99912855Sgabeblack@google.com	str[16] = '\0';
100012855Sgabeblack@google.com
100112855Sgabeblack@google.com	for( i = 0; i < 128; i += 8){
100212855Sgabeblack@google.com		c = 0;
100312855Sgabeblack@google.com		c |= a[i+0] ? 1 : 0;
100412855Sgabeblack@google.com		c |= a[i+1] ? 1<<1 : 0;
100512855Sgabeblack@google.com		c |= a[i+2] ? 1<<2 : 0;
100612855Sgabeblack@google.com		c |= a[i+3] ? 1<<3 : 0;
100712855Sgabeblack@google.com		c |= a[i+4] ? 1<<4 : 0;
100812855Sgabeblack@google.com		c |= a[i+5] ? 1<<5 : 0;
100912855Sgabeblack@google.com		c |= a[i+6] ? 1<<6 : 0;
101012855Sgabeblack@google.com		c |= a[i+7] ? 1<<7 : 0;
101112855Sgabeblack@google.com		str[i/8] = c;
101212855Sgabeblack@google.com
101312855Sgabeblack@google.com	}
101412855Sgabeblack@google.com
101512855Sgabeblack@google.com	return(&str[0]);
101612855Sgabeblack@google.com}
101712855Sgabeblack@google.com
101812855Sgabeblack@google.comsc_biguint<128>
101912855Sgabeblack@google.commakekey(char *keyMaterial)
102012855Sgabeblack@google.com{
102112855Sgabeblack@google.com	int i, j, t, k;
102212855Sgabeblack@google.com	sc_uint<8> R[4][4];
102312855Sgabeblack@google.com	sc_uint<8> tt;
102412855Sgabeblack@google.com	sc_biguint<128> key;
102512855Sgabeblack@google.com
102612855Sgabeblack@google.com	for(i = 0; i < 128/8; i++) {
102712855Sgabeblack@google.com		t = keyMaterial[2*i];
102812855Sgabeblack@google.com		if ((t >= '0') && (t <= '9')) j = (t - '0') << 4;
102912855Sgabeblack@google.com		else if ((t >= 'a') && (t <= 'f')) j = (t - 'a' + 10) << 4;
103012855Sgabeblack@google.com		else if ((t >= 'A') && (t <= 'F')) j = (t - 'A' + 10) << 4;
103112855Sgabeblack@google.com		else abort();
103212855Sgabeblack@google.com
103312855Sgabeblack@google.com		t = keyMaterial[2*i+1];
103412855Sgabeblack@google.com		if ((t >= '0') && (t <= '9')) j ^= (t - '0');
103512855Sgabeblack@google.com		else if ((t >= 'a') && (t <= 'f')) j ^= (t - 'a' + 10);
103612855Sgabeblack@google.com		else if ((t >= 'A') && (t <= 'F')) j ^= (t - 'A' + 10);
103712855Sgabeblack@google.com		else abort();
103812855Sgabeblack@google.com
103912855Sgabeblack@google.com		R[i % 4][i / 4] = j;
104012855Sgabeblack@google.com	}
104112855Sgabeblack@google.com
104212855Sgabeblack@google.com	for(i = 0; i < 4; i++){
104312855Sgabeblack@google.com		for(j = 0; j < 4; j++){
104412855Sgabeblack@google.com			tt = R[i][j];
104512855Sgabeblack@google.com			for(k = 0; k < 8; k++){
104612855Sgabeblack@google.com				key[(i*4+j)*8+k] = tt[k];
104712855Sgabeblack@google.com			}
104812855Sgabeblack@google.com		}
104912855Sgabeblack@google.com	}
105012855Sgabeblack@google.com	return(key);
105112855Sgabeblack@google.com}
105212855Sgabeblack@google.com
105312855Sgabeblack@google.com
105412855Sgabeblack@google.comint
105512855Sgabeblack@google.comsc_main(int argc, char *argv[])
105612855Sgabeblack@google.com{
105712855Sgabeblack@google.com	sc_clock clock;
105812855Sgabeblack@google.com	sc_signal<bool> reset;
105912855Sgabeblack@google.com	sc_signal<bool> D_In_req;
106012855Sgabeblack@google.com	sc_signal<bool> D_In_ack;
106112855Sgabeblack@google.com	sc_signal<bool> D_In_cmd;
106212855Sgabeblack@google.com	sc_signal<bool> D_Out_req;
106312855Sgabeblack@google.com	sc_signal<bool> D_Out_ack;
106412855Sgabeblack@google.com	sc_signal<sc_biguint<128> > D_In_wire;
106512855Sgabeblack@google.com	sc_signal<sc_biguint<128> > D_Out_wire;
106612855Sgabeblack@google.com	sc_signal<bool> E_In_req;
106712855Sgabeblack@google.com	sc_signal<bool> E_In_ack;
106812855Sgabeblack@google.com	sc_signal<bool> E_In_cmd;
106912855Sgabeblack@google.com	sc_signal<bool> E_Out_req;
107012855Sgabeblack@google.com	sc_signal<bool> E_Out_ack;
107112855Sgabeblack@google.com	sc_signal<sc_biguint<128> > E_In_wire;
107212855Sgabeblack@google.com	sc_signal<sc_biguint<128> > E_Out_wire;
107312855Sgabeblack@google.com	sc_biguint<128> key;
107412855Sgabeblack@google.com	sc_biguint<128> t;
107512855Sgabeblack@google.com	char *s;
107612855Sgabeblack@google.com	char key_string[33] = "deadbeef0123456776543210beefdead";
107712855Sgabeblack@google.com	char in[17] = "abcdefghijklmnop";
107812855Sgabeblack@google.com	char *out;
107912855Sgabeblack@google.com	bool err;
108012855Sgabeblack@google.com	int i;
108112855Sgabeblack@google.com
108212855Sgabeblack@google.com	AES_Encrypt E("AES_Encrypt",
108312855Sgabeblack@google.com		clock,
108412855Sgabeblack@google.com		reset,
108512855Sgabeblack@google.com		E_In_req,
108612855Sgabeblack@google.com		E_In_ack,
108712855Sgabeblack@google.com		E_In_cmd,
108812855Sgabeblack@google.com		E_In_wire,
108912855Sgabeblack@google.com		E_Out_req,
109012855Sgabeblack@google.com		E_Out_ack,
109112855Sgabeblack@google.com		E_Out_wire);
109212855Sgabeblack@google.com
109312855Sgabeblack@google.com	AES_Decrypt D("AES_Decrypt",
109412855Sgabeblack@google.com		clock,
109512855Sgabeblack@google.com		reset,
109612855Sgabeblack@google.com		D_In_req,
109712855Sgabeblack@google.com		D_In_ack,
109812855Sgabeblack@google.com		D_In_cmd,
109912855Sgabeblack@google.com		D_In_wire,
110012855Sgabeblack@google.com		D_Out_req,
110112855Sgabeblack@google.com		D_Out_ack,
110212855Sgabeblack@google.com		D_Out_wire);
110312855Sgabeblack@google.com
110412855Sgabeblack@google.com
110512855Sgabeblack@google.com	key = makekey(key_string);
110612855Sgabeblack@google.com
110712855Sgabeblack@google.com	reset = 0;
110812855Sgabeblack@google.com	sc_start(2, SC_NS);
110912855Sgabeblack@google.com	reset = 1;
111012855Sgabeblack@google.com	sc_start(2, SC_NS);
111112855Sgabeblack@google.com
111212855Sgabeblack@google.com	while( !E_In_req) sc_start(1, SC_NS);
111312855Sgabeblack@google.com	E_In_cmd = LOAD_KEY;
111412855Sgabeblack@google.com	E_In_ack = 1;
111512855Sgabeblack@google.com	E_In_wire = key;
111612855Sgabeblack@google.com	do { sc_start(1, SC_NS); E_In_ack = 0; } while( !E_In_req);
111712855Sgabeblack@google.com
111812855Sgabeblack@google.com	while( !D_In_req) sc_start(1, SC_NS);
111912855Sgabeblack@google.com	D_In_cmd = LOAD_KEY;
112012855Sgabeblack@google.com	D_In_ack = 1;
112112855Sgabeblack@google.com	D_In_wire = key;
112212855Sgabeblack@google.com	do { sc_start(1, SC_NS); D_In_ack = 0; } while( !D_In_req);
112312855Sgabeblack@google.com
112412855Sgabeblack@google.com
112512855Sgabeblack@google.com	while( !E_In_req) sc_start(1, SC_NS);
112612855Sgabeblack@google.com	E_Out_req = 1;
112712855Sgabeblack@google.com	E_In_cmd = ENCRYPT;
112812855Sgabeblack@google.com	E_In_ack = 1;
112912855Sgabeblack@google.com	E_In_wire = str2biguint((char*)"abcdefghijklmnop");
113012855Sgabeblack@google.com	do { sc_start(1, SC_NS); E_In_ack = 0; } while(!E_Out_ack);
113112855Sgabeblack@google.com	E_Out_req = 0;
113212855Sgabeblack@google.com	sc_start(1, SC_NS);
113312855Sgabeblack@google.com
113412855Sgabeblack@google.com	while( !D_In_req) sc_start(1, SC_NS);
113512855Sgabeblack@google.com	D_Out_req = 1;
113612855Sgabeblack@google.com	D_In_cmd = DECRYPT;
113712855Sgabeblack@google.com	D_In_ack = 1;
113812855Sgabeblack@google.com	D_In_wire = E_Out_wire;
113912855Sgabeblack@google.com	do { sc_start(1, SC_NS); D_In_ack = 0; } while(!D_Out_ack);
114012855Sgabeblack@google.com	out = biguint2str(D_Out_wire);
114112855Sgabeblack@google.com	D_Out_req = 0;
114212855Sgabeblack@google.com	sc_start(1, SC_NS);
114312855Sgabeblack@google.com
114412855Sgabeblack@google.com	err = false;
114512855Sgabeblack@google.com	for(i = 0; i < 16; i++){
114612855Sgabeblack@google.com		if( in[i] != out[i]){
114712855Sgabeblack@google.com			err = true;
114812855Sgabeblack@google.com			break;
114912855Sgabeblack@google.com		}
115012855Sgabeblack@google.com	}
115112855Sgabeblack@google.com
115212855Sgabeblack@google.com	if( err){
115312855Sgabeblack@google.com		cout << "mismatch error at index " << i << endl;
115412855Sgabeblack@google.com		cout << "key:" << key_string << " in:" << in
115512855Sgabeblack@google.com                     << " out:" << out << endl;
115612855Sgabeblack@google.com	} else {
115712855Sgabeblack@google.com		cout << "program complete" << endl;
115812855Sgabeblack@google.com	}
115912855Sgabeblack@google.com
116012855Sgabeblack@google.com	return(0);
116112855Sgabeblack@google.com}
116212855Sgabeblack@google.com#endif
116312855Sgabeblack@google.com
116412855Sgabeblack@google.com
1165