1#ifndef _RIJNDAEL_H_
2#define _RIJNDAEL_H_
3
4//
5// File : rijndael.h
6// Creation date : Sun Nov 5 2000 03:21:05 CEST
7// Author : Szymon Stefanek (stefanek@tin.it)
8//
9// Another implementation of the Rijndael cipher.
10// This is intended to be an easily usable library file.
11// This code is public domain.
12// Based on the Vincent Rijmen and K.U.Leuven implementation 2.4.
13//
14
15//
16// Original Copyright notice:
17//
18//    rijndael-alg-fst.c   v2.4   April '2000
19//    rijndael-alg-fst.h
20//    rijndael-api-fst.c
21//    rijndael-api-fst.h
22//
23//    Optimised ANSI C code
24//
25//    authors: v1.0: Antoon Bosselaers
26//             v2.0: Vincent Rijmen, K.U.Leuven
27//             v2.3: Paulo Barreto
28//             v2.4: Vincent Rijmen, K.U.Leuven
29//
30//    This code is placed in the public domain.
31//
32
33//
34// This implementation works on 128 , 192 , 256 bit keys
35// and on 128 bit blocks
36//
37
38//
39// Example of usage:
40//
41//  // Input data
42//  unsigned char key[32];                       // The key
43//  initializeYour256BitKey();                   // Obviously initialized with sth
44//  const unsigned char * plainText = getYourPlainText(); // Your plain text
45//  int plainTextLen = strlen(plainText);        // Plain text length
46//
47//  // Encrypting
48//  Rijndael rin;
49//  unsigned char output[plainTextLen + 16];
50//
51//  rin.init(Rijndael::CBC,Rijndael::Encrypt,key,Rijndael::Key32Bytes);
52//  // It is a good idea to check the error code
53//  int len = rin.padEncrypt(plainText,len,output);
54//  if(len >= 0)useYourEncryptedText();
55//  else encryptError(len);
56//
57//  // Decrypting: we can reuse the same object
58//  unsigned char output2[len];
59//  rin.init(Rijndael::CBC,Rijndael::Decrypt,key,Rijndael::Key32Bytes));
60//  len = rin.padDecrypt(output,len,output2);
61//  if(len >= 0)useYourDecryptedText();
62//  else decryptError(len);
63//
64
65#include "stdafx.h"
66
67#define _MAX_KEY_COLUMNS (256/32)
68#define _MAX_ROUNDS      14
69#define MAX_IV_SIZE      16
70
71// We assume that unsigned int is 32 bits long....
72//typedef unsigned char  uint8_t;
73//typedef unsigned int   uint32_t;
74//typedef unsigned short uint16_t;
75
76// Error codes
77#define RIJNDAEL_SUCCESS 0
78#define RIJNDAEL_UNSUPPORTED_MODE -1
79#define RIJNDAEL_UNSUPPORTED_DIRECTION -2
80#define RIJNDAEL_UNSUPPORTED_KEY_LENGTH -3
81#define RIJNDAEL_BAD_KEY -4
82#define RIJNDAEL_NOT_INITIALIZED -5
83#define RIJNDAEL_BAD_DIRECTION -6
84#define RIJNDAEL_CORRUPTED_DATA -7
85
86class Rijndael
87{
88public:
89	enum Direction { Encrypt , Decrypt };
90	enum Mode { ECB , CBC , CFB1 };
91	enum KeyLength { Key16Bytes , Key24Bytes , Key32Bytes };
92	//
93	// Creates a Rijndael cipher object
94	// You have to call init() before you can encrypt or decrypt stuff
95	//
96	Rijndael();
97	~Rijndael();
98protected:
99	// Internal stuff
100	enum State { Valid , Invalid };
101
102	State     m_state;
103	Mode      m_mode;
104	Direction m_direction;
105	uint8_t     m_initVector[MAX_IV_SIZE];
106	uint32_t    m_uRounds;
107	uint8_t     m_expandedKey[_MAX_ROUNDS+1][4][4];
108public:
109	//////////////////////////////////////////////////////////////////////////////////////////
110	// API
111	//////////////////////////////////////////////////////////////////////////////////////////
112
113	// init(): Initializes the crypt session
114	// Returns RIJNDAEL_SUCCESS or an error code
115	// mode      : Rijndael::ECB, Rijndael::CBC or Rijndael::CFB1
116	//             You have to use the same mode for encrypting and decrypting
117	// dir       : Rijndael::Encrypt or Rijndael::Decrypt
118	//             A cipher instance works only in one direction
119	//             (Well , it could be easily modified to work in both
120	//             directions with a single init() call, but it looks
121	//             useless to me...anyway , it is a matter of generating
122	//             two expanded keys)
123	// key       : array of unsigned octets , it can be 16 , 24 or 32 bytes long
124	//             this CAN be binary data (it is not expected to be null terminated)
125	// keyLen    : Rijndael::Key16Bytes , Rijndael::Key24Bytes or Rijndael::Key32Bytes
126	// initVector: initialization vector, you will usually use 0 here
127	int init(Mode mode,Direction dir,const uint8_t *key,KeyLength keyLen,uint8_t * initVector = 0);
128	// Encrypts the input array (can be binary data)
129	// The input array length must be a multiple of 16 bytes, the remaining part
130	// is DISCARDED.
131	// so it actually encrypts inputLen / 128 blocks of input and puts it in outBuffer
132	// Input len is in BITS!
133	// outBuffer must be at least inputLen / 8 bytes long.
134	// Returns the encrypted buffer length in BITS or an error code < 0 in case of error
135	int blockEncrypt(const uint8_t *input, int inputLen, uint8_t *outBuffer);
136	// Encrypts the input array (can be binary data)
137	// The input array can be any length , it is automatically padded on a 16 byte boundary.
138	// Input len is in BYTES!
139	// outBuffer must be at least (inputLen + 16) bytes long
140	// Returns the encrypted buffer length in BYTES or an error code < 0 in case of error
141	int padEncrypt(const uint8_t *input, int inputOctets, uint8_t *outBuffer);
142	// Decrypts the input vector
143	// Input len is in BITS!
144	// outBuffer must be at least inputLen / 8 bytes long
145	// Returns the decrypted buffer length in BITS and an error code < 0 in case of error
146	int blockDecrypt(const uint8_t *input, int inputLen, uint8_t *outBuffer);
147	// Decrypts the input vector
148	// Input len is in BYTES!
149	// outBuffer must be at least inputLen bytes long
150	// Returns the decrypted buffer length in BYTES and an error code < 0 in case of error
151	int padDecrypt(const uint8_t *input, int inputOctets, uint8_t *outBuffer);
152protected:
153	void keySched(uint8_t key[_MAX_KEY_COLUMNS][4]);
154	void keyEncToDec();
155	void encrypt(const uint8_t a[16], uint8_t b[16]);
156	void decrypt(const uint8_t a[16], uint8_t b[16]);
157};
158
159#endif // _RIJNDAEL_H_
160