AnCH Framework  0.1
Another C++ Hack Framework
All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Pages
aes.hpp
1 /*
2  ANCH Framework: ANother C++ Hack is a C++ framework based on C++11 standard
3  Copyright (C) 2012 Vincent Lachenal
4 
5  This file is part of ANCH Framework.
6 
7  ANCH Framework is free software: you can redistribute it and/or modify
8  it under the terms of the GNU Lesser General Public License as published by
9  the Free Software Foundation, either version 3 of the License, or
10  (at your option) any later version.
11 
12  ANCH Framework is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  GNU Lesser General Public License for more details.
16 
17  You should have received a copy of the GNU Lesser General Public License
18  along with ANCH Framework. If not, see <http://www.gnu.org/licenses/>.
19 */
20 #ifndef _ANCH_CRYPTO_AES_H_
21 #define _ANCH_CRYPTO_AES_H_
22 
23 #include "crypto/cipher/blockCipher.hpp"
24 
25 #include <bitset>
26 #include <cstring>
27 
28 
29 namespace anch {
30  namespace crypto {
31 
33  extern const uint8_t ANCH_AES_CIPHER_SBOX[256];
34 
36  extern const uint8_t ANCH_AES_DECIPHER_SBOX[256];
37 
39  extern const uint32_t ANCH_AES_RCON[11];
40 
51  template<std::size_t K, std::size_t R>
52  class AES: public anch::crypto::BlockCipher<16> {
53  // Attributes +
54  private:
56  uint8_t _state[4][4];
57 
59  uint32_t _expKey[4*(R+1)];
60  // Attributes -
61 
62 
63  // Constructors +
64  public:
70  AES(const uint8_t key[4*K]): _state(), _expKey() {
71  expandKey(key);
72  }
73 
80  AES(const AES& other): _state(), _expKey() {
81  std::memcpy(_expKey, other._expKey, 4 * (R + 1) * sizeof(uint32_t));
82  }
83  // Constructors -
84 
85 
86  // Destructors +
90  virtual ~AES() {
91  // Nothing to do
92  }
93  // Destructors -
94 
95 
96  // Methods +
97  public:
104  void cipher(const std::array<uint8_t,16>& input, std::array<uint8_t,16>& output) {
105  std::memcpy(&_state, input.data(), 16);
106  unsigned int round = 0;
107 
108  // Initial round +
109  addRoundKey(round);
110  // Initial round -
111 
112  // Rounds +
113  for(round = 1 ; round < R ; ++round) {
114  cipherSubBytes();
115  cipherShiftRows();
116  cipherMixColumns();
117  addRoundKey(round);
118  }
119  // Rounds -
120 
121  // Final round +
122  cipherSubBytes();
123  cipherShiftRows();
124  addRoundKey(round);
125  // Final round -
126 
127  std::memcpy(output.data(), &_state, 16);
128  }
129 
136  void decipher(const std::array<uint8_t,16>& input, std::array<uint8_t,16>& output) {
137  std::memcpy(&_state, input.data(), 16);
138  unsigned int round = R;
139 
140  // Initial round +
141  addRoundKey(round);
142  decipherShiftRows();
143  decipherSubBytes();
144  // Initial round -
145 
146  // Rounds +
147  for(round = R - 1 ; round > 0 ; --round) {
148  addRoundKey(round);
149  decipherMixColumns();
150  decipherShiftRows();
151  decipherSubBytes();
152  }
153  // Rounds -
154 
155  // Final round +
156  addRoundKey(round);
157  // Final round -
158 
159  std::memcpy(output.data(), &_state, 16);
160  }
161 
162  private:
168  void expandKey(const uint8_t key[4*K]) {
169  std::memcpy(_expKey, key, 4*K);
170  for(std::size_t i = K ; i < 4*(R+1) ; ++i) {
171  uint32_t mod = i % K;
172  if(mod == 0) {
173  _expKey[i] = _expKey[i-K] ^ (subWord(rotateWord(_expKey[i-1])) ^ ANCH_AES_RCON[i/K]);
174  } else if(K > 6 && mod == 4) {
175  _expKey[i] = _expKey[i-K] ^ subWord(_expKey[i-1]);
176  } else {
177  _expKey[i] = _expKey[i-K] ^ _expKey[i-1];
178  }
179  }
180  }
181 
190  inline uint32_t subWord(const uint32_t& word) {
191  uint32_t res;
192  uint8_t* resBytes = reinterpret_cast<uint8_t*>(&res);
193  const uint8_t* const bytes = reinterpret_cast<const uint8_t* const>(&word);
194  resBytes[0] = ANCH_AES_CIPHER_SBOX[bytes[0]];
195  resBytes[1] = ANCH_AES_CIPHER_SBOX[bytes[1]];
196  resBytes[2] = ANCH_AES_CIPHER_SBOX[bytes[2]];
197  resBytes[3] = ANCH_AES_CIPHER_SBOX[bytes[3]];
198  return res;
199  }
200 
208  inline uint32_t rotateWord(const uint32_t& word) {
209  return ((word << 24) | (word >> 8));
210  }
211 
216  inline void cipherSubBytes() {
217  _state[0][0] = ANCH_AES_CIPHER_SBOX[_state[0][0]];
218  _state[0][1] = ANCH_AES_CIPHER_SBOX[_state[0][1]];
219  _state[0][2] = ANCH_AES_CIPHER_SBOX[_state[0][2]];
220  _state[0][3] = ANCH_AES_CIPHER_SBOX[_state[0][3]];
221  _state[1][0] = ANCH_AES_CIPHER_SBOX[_state[1][0]];
222  _state[1][1] = ANCH_AES_CIPHER_SBOX[_state[1][1]];
223  _state[1][2] = ANCH_AES_CIPHER_SBOX[_state[1][2]];
224  _state[1][3] = ANCH_AES_CIPHER_SBOX[_state[1][3]];
225  _state[2][0] = ANCH_AES_CIPHER_SBOX[_state[2][0]];
226  _state[2][1] = ANCH_AES_CIPHER_SBOX[_state[2][1]];
227  _state[2][2] = ANCH_AES_CIPHER_SBOX[_state[2][2]];
228  _state[2][3] = ANCH_AES_CIPHER_SBOX[_state[2][3]];
229  _state[3][0] = ANCH_AES_CIPHER_SBOX[_state[3][0]];
230  _state[3][1] = ANCH_AES_CIPHER_SBOX[_state[3][1]];
231  _state[3][2] = ANCH_AES_CIPHER_SBOX[_state[3][2]];
232  _state[3][3] = ANCH_AES_CIPHER_SBOX[_state[3][3]];
233  }
234 
239  inline void decipherSubBytes() {
240  _state[0][0] = ANCH_AES_DECIPHER_SBOX[_state[0][0]];
241  _state[0][1] = ANCH_AES_DECIPHER_SBOX[_state[0][1]];
242  _state[0][2] = ANCH_AES_DECIPHER_SBOX[_state[0][2]];
243  _state[0][3] = ANCH_AES_DECIPHER_SBOX[_state[0][3]];
244  _state[1][0] = ANCH_AES_DECIPHER_SBOX[_state[1][0]];
245  _state[1][1] = ANCH_AES_DECIPHER_SBOX[_state[1][1]];
246  _state[1][2] = ANCH_AES_DECIPHER_SBOX[_state[1][2]];
247  _state[1][3] = ANCH_AES_DECIPHER_SBOX[_state[1][3]];
248  _state[2][0] = ANCH_AES_DECIPHER_SBOX[_state[2][0]];
249  _state[2][1] = ANCH_AES_DECIPHER_SBOX[_state[2][1]];
250  _state[2][2] = ANCH_AES_DECIPHER_SBOX[_state[2][2]];
251  _state[2][3] = ANCH_AES_DECIPHER_SBOX[_state[2][3]];
252  _state[3][0] = ANCH_AES_DECIPHER_SBOX[_state[3][0]];
253  _state[3][1] = ANCH_AES_DECIPHER_SBOX[_state[3][1]];
254  _state[3][2] = ANCH_AES_DECIPHER_SBOX[_state[3][2]];
255  _state[3][3] = ANCH_AES_DECIPHER_SBOX[_state[3][3]];
256  }
257 
261  inline void cipherShiftRows() {
262  uint8_t tmp = _state[0][1];
263  _state[0][1] = _state[1][1];
264  _state[1][1] = _state[2][1];
265  _state[2][1] = _state[3][1];
266  _state[3][1] = tmp;
267  tmp = _state[1][2];
268  _state[1][2] = _state[3][2];
269  _state[3][2] = tmp;
270  tmp = _state[2][2];
271  _state[2][2] = _state[0][2];
272  _state[0][2] = tmp;
273  tmp = _state[3][3];
274  _state[3][3] = _state[2][3];
275  _state[2][3] = _state[1][3];
276  _state[1][3] = _state[0][3];
277  _state[0][3] = tmp;
278  }
279 
283  inline void decipherShiftRows() {
284  uint8_t tmp = _state[3][1];
285  _state[3][1] = _state[2][1];
286  _state[2][1] = _state[1][1];
287  _state[1][1] = _state[0][1];
288  _state[0][1] = tmp;
289  tmp = _state[1][2];
290  _state[1][2] = _state[3][2];
291  _state[3][2] = tmp;
292  tmp = _state[2][2];
293  _state[2][2] = _state[0][2];
294  _state[0][2] = tmp;
295  tmp = _state[0][3];
296  _state[0][3] = _state[1][3];
297  _state[1][3] = _state[2][3];
298  _state[2][3] = _state[3][3];
299  _state[3][3] = tmp;
300  }
301 
305  inline void cipherMixColumns() {
306  uint8_t state[4];
307 
308  state[0] = _state[0][0];
309  state[1] = _state[0][1];
310  state[2] = _state[0][2];
311  state[3] = _state[0][3];
312  _state[0][0] = ANCH_GALOIS_MULT2[state[0]] ^ ANCH_GALOIS_MULT3[state[1]] ^ state[2] ^ state[3];
313  _state[0][1] = state[0] ^ ANCH_GALOIS_MULT2[state[1]] ^ ANCH_GALOIS_MULT3[state[2]] ^ state[3];
314  _state[0][2] = state[0] ^ state[1] ^ ANCH_GALOIS_MULT2[state[2]] ^ ANCH_GALOIS_MULT3[state[3]];
315  _state[0][3] = ANCH_GALOIS_MULT3[state[0]] ^ state[1] ^ state[2] ^ ANCH_GALOIS_MULT2[state[3]];
316 
317  state[0] = _state[1][0];
318  state[1] = _state[1][1];
319  state[2] = _state[1][2];
320  state[3] = _state[1][3];
321  _state[1][0] = ANCH_GALOIS_MULT2[state[0]] ^ ANCH_GALOIS_MULT3[state[1]] ^ state[2] ^ state[3];
322  _state[1][1] = state[0] ^ ANCH_GALOIS_MULT2[state[1]] ^ ANCH_GALOIS_MULT3[state[2]] ^ state[3];
323  _state[1][2] = state[0] ^ state[1] ^ ANCH_GALOIS_MULT2[state[2]] ^ ANCH_GALOIS_MULT3[state[3]];
324  _state[1][3] = ANCH_GALOIS_MULT3[state[0]] ^ state[1] ^ state[2] ^ ANCH_GALOIS_MULT2[state[3]];
325 
326  state[0] = _state[2][0];
327  state[1] = _state[2][1];
328  state[2] = _state[2][2];
329  state[3] = _state[2][3];
330  _state[2][0] = ANCH_GALOIS_MULT2[state[0]] ^ ANCH_GALOIS_MULT3[state[1]] ^ state[2] ^ state[3];
331  _state[2][1] = state[0] ^ ANCH_GALOIS_MULT2[state[1]] ^ ANCH_GALOIS_MULT3[state[2]] ^ state[3];
332  _state[2][2] = state[0] ^ state[1] ^ ANCH_GALOIS_MULT2[state[2]] ^ ANCH_GALOIS_MULT3[state[3]];
333  _state[2][3] = ANCH_GALOIS_MULT3[state[0]] ^ state[1] ^ state[2] ^ ANCH_GALOIS_MULT2[state[3]];
334 
335  state[0] = _state[3][0];
336  state[1] = _state[3][1];
337  state[2] = _state[3][2];
338  state[3] = _state[3][3];
339  _state[3][0] = ANCH_GALOIS_MULT2[state[0]] ^ ANCH_GALOIS_MULT3[state[1]] ^ state[2] ^ state[3];
340  _state[3][1] = state[0] ^ ANCH_GALOIS_MULT2[state[1]] ^ ANCH_GALOIS_MULT3[state[2]] ^ state[3];
341  _state[3][2] = state[0] ^ state[1] ^ ANCH_GALOIS_MULT2[state[2]] ^ ANCH_GALOIS_MULT3[state[3]];
342  _state[3][3] = ANCH_GALOIS_MULT3[state[0]] ^ state[1] ^ state[2] ^ ANCH_GALOIS_MULT2[state[3]];
343  }
344 
348  inline void decipherMixColumns() {
349  uint8_t state[4];
350 
351  state[0] = _state[0][0];
352  state[1] = _state[0][1];
353  state[2] = _state[0][2];
354  state[3] = _state[0][3];
355  _state[0][0] = ANCH_GALOIS_MULT14[state[0]] ^ ANCH_GALOIS_MULT11[state[1]] ^ ANCH_GALOIS_MULT13[state[2]] ^ ANCH_GALOIS_MULT9[state[3]];
356  _state[0][1] = ANCH_GALOIS_MULT9[state[0]] ^ ANCH_GALOIS_MULT14[state[1]] ^ ANCH_GALOIS_MULT11[state[2]] ^ ANCH_GALOIS_MULT13[state[3]];
357  _state[0][2] = ANCH_GALOIS_MULT13[state[0]] ^ ANCH_GALOIS_MULT9[state[1]] ^ ANCH_GALOIS_MULT14[state[2]] ^ ANCH_GALOIS_MULT11[state[3]];
358  _state[0][3] = ANCH_GALOIS_MULT11[state[0]] ^ ANCH_GALOIS_MULT13[state[1]] ^ ANCH_GALOIS_MULT9[state[2]] ^ ANCH_GALOIS_MULT14[state[3]];
359 
360  state[0] = _state[1][0];
361  state[1] = _state[1][1];
362  state[2] = _state[1][2];
363  state[3] = _state[1][3];
364  _state[1][0] = ANCH_GALOIS_MULT14[state[0]] ^ ANCH_GALOIS_MULT11[state[1]] ^ ANCH_GALOIS_MULT13[state[2]] ^ ANCH_GALOIS_MULT9[state[3]];
365  _state[1][1] = ANCH_GALOIS_MULT9[state[0]] ^ ANCH_GALOIS_MULT14[state[1]] ^ ANCH_GALOIS_MULT11[state[2]] ^ ANCH_GALOIS_MULT13[state[3]];
366  _state[1][2] = ANCH_GALOIS_MULT13[state[0]] ^ ANCH_GALOIS_MULT9[state[1]] ^ ANCH_GALOIS_MULT14[state[2]] ^ ANCH_GALOIS_MULT11[state[3]];
367  _state[1][3] = ANCH_GALOIS_MULT11[state[0]] ^ ANCH_GALOIS_MULT13[state[1]] ^ ANCH_GALOIS_MULT9[state[2]] ^ ANCH_GALOIS_MULT14[state[3]];
368 
369  state[0] = _state[2][0];
370  state[1] = _state[2][1];
371  state[2] = _state[2][2];
372  state[3] = _state[2][3];
373  _state[2][0] = ANCH_GALOIS_MULT14[state[0]] ^ ANCH_GALOIS_MULT11[state[1]] ^ ANCH_GALOIS_MULT13[state[2]] ^ ANCH_GALOIS_MULT9[state[3]];
374  _state[2][1] = ANCH_GALOIS_MULT9[state[0]] ^ ANCH_GALOIS_MULT14[state[1]] ^ ANCH_GALOIS_MULT11[state[2]] ^ ANCH_GALOIS_MULT13[state[3]];
375  _state[2][2] = ANCH_GALOIS_MULT13[state[0]] ^ ANCH_GALOIS_MULT9[state[1]] ^ ANCH_GALOIS_MULT14[state[2]] ^ ANCH_GALOIS_MULT11[state[3]];
376  _state[2][3] = ANCH_GALOIS_MULT11[state[0]] ^ ANCH_GALOIS_MULT13[state[1]] ^ ANCH_GALOIS_MULT9[state[2]] ^ ANCH_GALOIS_MULT14[state[3]];
377 
378  state[0] = _state[3][0];
379  state[1] = _state[3][1];
380  state[2] = _state[3][2];
381  state[3] = _state[3][3];
382  _state[3][0] = ANCH_GALOIS_MULT14[state[0]] ^ ANCH_GALOIS_MULT11[state[1]] ^ ANCH_GALOIS_MULT13[state[2]] ^ ANCH_GALOIS_MULT9[state[3]];
383  _state[3][1] = ANCH_GALOIS_MULT9[state[0]] ^ ANCH_GALOIS_MULT14[state[1]] ^ ANCH_GALOIS_MULT11[state[2]] ^ ANCH_GALOIS_MULT13[state[3]];
384  _state[3][2] = ANCH_GALOIS_MULT13[state[0]] ^ ANCH_GALOIS_MULT9[state[1]] ^ ANCH_GALOIS_MULT14[state[2]] ^ ANCH_GALOIS_MULT11[state[3]];
385  _state[3][3] = ANCH_GALOIS_MULT11[state[0]] ^ ANCH_GALOIS_MULT13[state[1]] ^ ANCH_GALOIS_MULT9[state[2]] ^ ANCH_GALOIS_MULT14[state[3]];
386  }
387 
393  inline void addRoundKey(const uint32_t& round) {
394  uint32_t* key = _expKey + 4 * round;
395  uint32_t* state = reinterpret_cast<uint32_t*>(_state);
396  state[0] ^= key[0];
397  state[1] ^= key[1];
398  state[2] ^= key[2];
399  state[3] ^= key[3];
400  }
401  // Methods -
402 
403  };
404 
405  }
406 }
407 
408 #endif // _ANCH_CRYPTO_AES_H_
const uint8_t ANCH_GALOIS_MULT3[256]
Definition: blockCipher.cpp:49
const uint8_t ANCH_AES_CIPHER_SBOX[256]
Definition: aes.cpp:52
const uint32_t ANCH_AES_RCON[11]
Definition: aes.cpp:124
const uint8_t ANCH_GALOIS_MULT9[256]
Definition: blockCipher.cpp:69
Block cipher interface.
Definition: blockCipher.hpp:59
const uint8_t ANCH_AES_DECIPHER_SBOX[256]
Definition: aes.cpp:88
void decipher(const std::array< uint8_t, 16 > &input, std::array< uint8_t, 16 > &output)
Definition: aes.hpp:136
const uint8_t ANCH_GALOIS_MULT11[256]
Definition: blockCipher.cpp:89
AnCH framework base namespace.
Definition: base64.hpp:28
AES(const AES &other)
Definition: aes.hpp:80
const uint8_t ANCH_GALOIS_MULT2[256]
Definition: blockCipher.cpp:29
AES block cipher algorithm implementation.
Definition: aes.hpp:52
AES(const uint8_t key[4 *K])
Definition: aes.hpp:70
const uint8_t ANCH_GALOIS_MULT14[256]
Definition: blockCipher.cpp:129
const uint8_t ANCH_GALOIS_MULT13[256]
Definition: blockCipher.cpp:109
void cipher(const std::array< uint8_t, 16 > &input, std::array< uint8_t, 16 > &output)
Definition: aes.hpp:104
virtual ~AES()
Definition: aes.hpp:90