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