// advanced encryption standard
// author: karl malbrain, malbrain@yahoo.com
/*
This work, including the source code, documentation
and related data, is placed into the public domain.

The orginal author is Karl Malbrain.

THIS SOFTWARE IS PROVIDED AS-IS WITHOUT WARRANTY
OF ANY KIND, NOT EVEN THE IMPLIED WARRANTY OF
MERCHANTABILITY. THE AUTHOR OF THIS SOFTWARE,
ASSUMES _NO_ RESPONSIBILITY FOR ANY CONSEQUENCE
RESULTING FROM THE USE, MODIFICATION, OR
REDISTRIBUTION OF THIS SOFTWARE.
*/
#ifndef __AES_H__
#define __AES_H__

typedef unsigned char uchar;
#include <string.h>
#include <memory.h>
namespace AES
{
	// AES only supports Nb=4
	#define Nb 4			// number of columns in the state & expanded key

	#define Nk 4			// number of columns in a key
	#define Nr 10			// number of rounds in encryption

	extern const uchar Sbox[256];

	extern const uchar InvSbox[256];

	// combined Xtimes2[Sbox[]]
	extern const uchar Xtime2Sbox[256];
	// combined Xtimes3[Sbox[]]
	extern const uchar Xtime3Sbox[256];
	// modular multiplication tables
	// based on:

	// Xtime2[x] = (x & 0x80 ? 0x1b : 0) ^ (x + x)
	// Xtime3[x] = x^Xtime2[x];

	extern const uchar Xtime2[256];
	extern const uchar Xtime9[256];
	extern const uchar XtimeB[256];
	extern const uchar XtimeD[256];
	extern const uchar XtimeE[256];
	// exchanges columns in each of 4 rows
	// row0 - unchanged, row1- shifted left 1,// row2 - shifted left 2 and row3 - shifted left 3
	extern const void ShiftRows (uchar *state);

	// restores columns in each of 4 rows
	// row0 - unchanged, row1- shifted right 1,
	// row2 - shifted right 2 and row3 - shifted right 3
	extern const void InvShiftRows (uchar *state);

	// recombine and mix each row in a column
	extern const void MixSubColumns (uchar *state);

	// restore and un-mix each row in a column
	extern const void InvMixSubColumns (uchar *state);

	// encrypt/decrypt columns of the key
	// n.b. you can replace this with
	// byte-wise xor if you wish.

	extern const void AddRoundKey (unsigned *state, unsigned *key);

	extern const uchar Rcon[11];

	// produce Nb bytes for each round
	extern const void ExpandKey (uchar *key, uchar *expkey);

	// encrypt one 128 bit block
	extern const void Encrypt (uchar *in, uchar *expkey, uchar *out);

	extern const void Decrypt (uchar *in, uchar *expkey, uchar *out);
}
#endif