Mercurial > pihelp
comparison aes.c @ 10:439b7aaaec9e
Get aes from avr231 appnote instead
author | Matt Johnston <matt@ucc.asn.au> |
---|---|
date | Wed, 12 Jun 2013 22:57:44 +0800 |
parents | 87c8d0a11906 |
children |
comparison
equal
deleted
inserted
replaced
9:3aa92c7f379c | 10:439b7aaaec9e |
---|---|
1 // advanced encryption standard | 1 #include "aes.h" |
2 // Original author: Karl Malbrain, [email protected] | 2 //#include "loader.h" |
3 // Ported to Atmel AVR by: Jiri Pittner, [email protected] | |
4 // | 3 // |
5 /* | 4 #define KEY_COUNT 1 |
6 This work, including the source code, documentation | 5 |
7 and related data, is placed into the public domain. | 6 #if KEY_COUNT > 0 |
8 | 7 |
9 The original author is Karl Malbrain. | 8 //#include "aeskeys.inc" |
10 | 9 |
11 THIS SOFTWARE IS PROVIDED AS-IS WITHOUT WARRANTY | 10 |
12 OF ANY KIND, NOT EVEN THE IMPLIED WARRANTY OF | 11 |
13 MERCHANTABILITY. THE AUTHOR OF THIS SOFTWARE, | 12 |
14 ASSUMES _NO_ RESPONSIBILITY FOR ANY CONSEQUENCE | 13 typedef unsigned char byte; |
15 RESULTING FROM THE USE, MODIFICATION, OR | 14 |
16 REDISTRIBUTION OF THIS SOFTWARE. | 15 |
17 */ | 16 |
18 | 17 #define BPOLY 0x1b //!< Lower 8 bits of (x^8+x^4+x^3+x+1), ie. (x^4+x^3+x+1). |
19 #include <stdlib.h> | 18 #define BLOCKSIZE 16 //!< Block size in number of bytes. |
20 #include <string.h> | 19 |
21 | 20 |
22 #include <avr/pgmspace.h> //tables have to reside in flash memory | 21 |
23 | 22 #if KEY_COUNT == 1 |
24 | 23 #define KEYBITS 128 //!< Use AES128. |
25 // AES only supports Nb=4 | 24 #elif KEY_COUNT == 2 |
26 #define Nb 4 // number of columns in the state & expanded key | 25 #define KEYBITS 192 //!< Use AES196. |
27 | 26 #elif KEY_COUNT == 3 |
28 #define Nk 4 // number of columns in a key | 27 #define KEYBITS 256 //!< Use AES256. |
29 #define Nr 10 // number of rounds in encryption | 28 #else |
30 | 29 #error Use 1, 2 or 3 keys! |
31 #define Sbox(i) (pgm_read_byte(&P_Sbox[i])) | 30 #endif |
32 const unsigned char P_Sbox[256] __attribute__ ((__progmem__)) = { // forward s-box | 31 |
33 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, | 32 #if KEYBITS == 128 |
34 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, | 33 #define ROUNDS 10 //!< Number of rounds. |
35 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, | 34 #define KEYLENGTH 16 //!< Key length in number of bytes. |
36 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, | 35 #elif KEYBITS == 192 |
37 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, | 36 #define ROUNDS 12 //!< Number of rounds. |
38 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, | 37 #define KEYLENGTH 24 //!< // Key length in number of bytes. |
39 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, | 38 #elif KEYBITS == 256 |
40 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, | 39 #define ROUNDS 14 //!< Number of rounds. |
41 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, | 40 #define KEYLENGTH 32 //!< Key length in number of bytes. |
42 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, | 41 #else |
43 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, | 42 #error Key must be 128, 192 or 256 bits! |
44 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, | 43 #endif |
45 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, | 44 |
46 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, | 45 #define EXPANDED_KEY_SIZE (BLOCKSIZE * (ROUNDS+1)) //!< 176, 208 or 240 bytes. |
47 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, | 46 |
48 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16}; | 47 |
49 | 48 |
50 #define InvSbox(i) (pgm_read_byte(&P_InvSbox[i])) | 49 byte block1[ 256 ]; //!< Workspace 1. |
51 const unsigned char P_InvSbox[256] __attribute__ ((__progmem__)) = { // inverse s-box | 50 byte block2[ 256 ]; //!< Worksapce 2. |
52 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb, | 51 |
53 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, | 52 |
54 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e, | 53 |
55 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25, | 54 byte * powTbl; //!< Final location of exponentiation lookup table. |
56 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92, | 55 byte * logTbl; //!< Final location of logarithm lookup table. |
57 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84, | 56 byte * sBox; //!< Final location of s-box. |
58 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06, | 57 byte * sBoxInv; //!< Final location of inverse s-box. |
59 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b, | 58 byte * expandedKey; //!< Final location of expanded key. |
60 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73, | 59 |
61 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e, | 60 |
62 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b, | 61 |
63 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4, | 62 void CalcPowLog( byte * powTbl, byte * logTbl ) |
64 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f, | 63 { |
65 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef, | 64 byte i = 0; |
66 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61, | 65 byte t = 1; |
67 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d}; | 66 |
68 | 67 do { |
69 // combined Xtimes2[Sbox[]] | 68 // Use 0x03 as root for exponentiation and logarithms. |
70 #define Xtime2Sbox(i) (pgm_read_byte(&P_Xtime2Sbox[i])) | 69 powTbl[i] = t; |
71 const unsigned char P_Xtime2Sbox[256] __attribute__ ((__progmem__)) = { | 70 logTbl[t] = i; |
72 0xc6, 0xf8, 0xee, 0xf6, 0xff, 0xd6, 0xde, 0x91, 0x60, 0x02, 0xce, 0x56, 0xe7, 0xb5, 0x4d, 0xec, | 71 i++; |
73 0x8f, 0x1f, 0x89, 0xfa, 0xef, 0xb2, 0x8e, 0xfb, 0x41, 0xb3, 0x5f, 0x45, 0x23, 0x53, 0xe4, 0x9b, | 72 |
74 0x75, 0xe1, 0x3d, 0x4c, 0x6c, 0x7e, 0xf5, 0x83, 0x68, 0x51, 0xd1, 0xf9, 0xe2, 0xab, 0x62, 0x2a, | 73 // Muliply t by 3 in GF(2^8). |
75 0x08, 0x95, 0x46, 0x9d, 0x30, 0x37, 0x0a, 0x2f, 0x0e, 0x24, 0x1b, 0xdf, 0xcd, 0x4e, 0x7f, 0xea, | 74 t ^= (t << 1) ^ (t & 0x80 ? BPOLY : 0); |
76 0x12, 0x1d, 0x58, 0x34, 0x36, 0xdc, 0xb4, 0x5b, 0xa4, 0x76, 0xb7, 0x7d, 0x52, 0xdd, 0x5e, 0x13, | 75 } while( t != 1 ); // Cyclic properties ensure that i < 255. |
77 0xa6, 0xb9, 0x00, 0xc1, 0x40, 0xe3, 0x79, 0xb6, 0xd4, 0x8d, 0x67, 0x72, 0x94, 0x98, 0xb0, 0x85, | 76 |
78 0xbb, 0xc5, 0x4f, 0xed, 0x86, 0x9a, 0x66, 0x11, 0x8a, 0xe9, 0x04, 0xfe, 0xa0, 0x78, 0x25, 0x4b, | 77 powTbl[255] = powTbl[0]; // 255 = '-0', 254 = -1, etc. |
79 0xa2, 0x5d, 0x80, 0x05, 0x3f, 0x21, 0x70, 0xf1, 0x63, 0x77, 0xaf, 0x42, 0x20, 0xe5, 0xfd, 0xbf, | 78 } |
80 0x81, 0x18, 0x26, 0xc3, 0xbe, 0x35, 0x88, 0x2e, 0x93, 0x55, 0xfc, 0x7a, 0xc8, 0xba, 0x32, 0xe6, | 79 |
81 0xc0, 0x19, 0x9e, 0xa3, 0x44, 0x54, 0x3b, 0x0b, 0x8c, 0xc7, 0x6b, 0x28, 0xa7, 0xbc, 0x16, 0xad, | 80 |
82 0xdb, 0x64, 0x74, 0x14, 0x92, 0x0c, 0x48, 0xb8, 0x9f, 0xbd, 0x43, 0xc4, 0x39, 0x31, 0xd3, 0xf2, | 81 |
83 0xd5, 0x8b, 0x6e, 0xda, 0x01, 0xb1, 0x9c, 0x49, 0xd8, 0xac, 0xf3, 0xcf, 0xca, 0xf4, 0x47, 0x10, | 82 void CalcSBox( byte * sBox ) |
84 0x6f, 0xf0, 0x4a, 0x5c, 0x38, 0x57, 0x73, 0x97, 0xcb, 0xa1, 0xe8, 0x3e, 0x96, 0x61, 0x0d, 0x0f, | 83 { |
85 0xe0, 0x7c, 0x71, 0xcc, 0x90, 0x06, 0xf7, 0x1c, 0xc2, 0x6a, 0xae, 0x69, 0x17, 0x99, 0x3a, 0x27, | 84 byte i, rot; |
86 0xd9, 0xeb, 0x2b, 0x22, 0xd2, 0xa9, 0x07, 0x33, 0x2d, 0x3c, 0x15, 0xc9, 0x87, 0xaa, 0x50, 0xa5, | 85 byte temp; |
87 0x03, 0x59, 0x09, 0x1a, 0x65, 0xd7, 0x84, 0xd0, 0x82, 0x29, 0x5a, 0x1e, 0x7b, 0xa8, 0x6d, 0x2c | 86 byte result; |
88 }; | 87 |
89 | 88 // Fill all entries of sBox[]. |
90 // combined Xtimes3[Sbox[]] | 89 i = 0; |
91 #define Xtime3Sbox(i) (pgm_read_byte(&P_Xtime3Sbox[i])) | 90 do { |
92 const unsigned char P_Xtime3Sbox[256] __attribute__ ((__progmem__)) = { | 91 // Inverse in GF(2^8). |
93 0xa5, 0x84, 0x99, 0x8d, 0x0d, 0xbd, 0xb1, 0x54, 0x50, 0x03, 0xa9, 0x7d, 0x19, 0x62, 0xe6, 0x9a, | 92 if( i > 0 ) { |
94 0x45, 0x9d, 0x40, 0x87, 0x15, 0xeb, 0xc9, 0x0b, 0xec, 0x67, 0xfd, 0xea, 0xbf, 0xf7, 0x96, 0x5b, | 93 temp = powTbl[ 255 - logTbl[i] ]; |
95 0xc2, 0x1c, 0xae, 0x6a, 0x5a, 0x41, 0x02, 0x4f, 0x5c, 0xf4, 0x34, 0x08, 0x93, 0x73, 0x53, 0x3f, | 94 } else { |
96 0x0c, 0x52, 0x65, 0x5e, 0x28, 0xa1, 0x0f, 0xb5, 0x09, 0x36, 0x9b, 0x3d, 0x26, 0x69, 0xcd, 0x9f, | 95 temp = 0; |
97 0x1b, 0x9e, 0x74, 0x2e, 0x2d, 0xb2, 0xee, 0xfb, 0xf6, 0x4d, 0x61, 0xce, 0x7b, 0x3e, 0x71, 0x97, | |
98 0xf5, 0x68, 0x00, 0x2c, 0x60, 0x1f, 0xc8, 0xed, 0xbe, 0x46, 0xd9, 0x4b, 0xde, 0xd4, 0xe8, 0x4a, | |
99 0x6b, 0x2a, 0xe5, 0x16, 0xc5, 0xd7, 0x55, 0x94, 0xcf, 0x10, 0x06, 0x81, 0xf0, 0x44, 0xba, 0xe3, | |
100 0xf3, 0xfe, 0xc0, 0x8a, 0xad, 0xbc, 0x48, 0x04, 0xdf, 0xc1, 0x75, 0x63, 0x30, 0x1a, 0x0e, 0x6d, | |
101 0x4c, 0x14, 0x35, 0x2f, 0xe1, 0xa2, 0xcc, 0x39, 0x57, 0xf2, 0x82, 0x47, 0xac, 0xe7, 0x2b, 0x95, | |
102 0xa0, 0x98, 0xd1, 0x7f, 0x66, 0x7e, 0xab, 0x83, 0xca, 0x29, 0xd3, 0x3c, 0x79, 0xe2, 0x1d, 0x76, | |
103 0x3b, 0x56, 0x4e, 0x1e, 0xdb, 0x0a, 0x6c, 0xe4, 0x5d, 0x6e, 0xef, 0xa6, 0xa8, 0xa4, 0x37, 0x8b, | |
104 0x32, 0x43, 0x59, 0xb7, 0x8c, 0x64, 0xd2, 0xe0, 0xb4, 0xfa, 0x07, 0x25, 0xaf, 0x8e, 0xe9, 0x18, | |
105 0xd5, 0x88, 0x6f, 0x72, 0x24, 0xf1, 0xc7, 0x51, 0x23, 0x7c, 0x9c, 0x21, 0xdd, 0xdc, 0x86, 0x85, | |
106 0x90, 0x42, 0xc4, 0xaa, 0xd8, 0x05, 0x01, 0x12, 0xa3, 0x5f, 0xf9, 0xd0, 0x91, 0x58, 0x27, 0xb9, | |
107 0x38, 0x13, 0xb3, 0x33, 0xbb, 0x70, 0x89, 0xa7, 0xb6, 0x22, 0x92, 0x20, 0x49, 0xff, 0x78, 0x7a, | |
108 0x8f, 0xf8, 0x80, 0x17, 0xda, 0x31, 0xc6, 0xb8, 0xc3, 0xb0, 0x77, 0x11, 0xcb, 0xfc, 0xd6, 0x3a | |
109 }; | |
110 | |
111 // modular multiplication tables | |
112 // based on: | |
113 | |
114 // Xtime2[x] = (x & 0x80 ? 0x1b : 0) ^ (x + x) | |
115 // Xtime3[x] = x^Xtime2[x]; | |
116 | |
117 #define Xtime2(i) (pgm_read_byte(&P_Xtime2[i])) | |
118 const unsigned char P_Xtime2[256] __attribute__ ((__progmem__)) = { | |
119 0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e, 0x10, 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e, | |
120 0x20, 0x22, 0x24, 0x26, 0x28, 0x2a, 0x2c, 0x2e, 0x30, 0x32, 0x34, 0x36, 0x38, 0x3a, 0x3c, 0x3e, | |
121 0x40, 0x42, 0x44, 0x46, 0x48, 0x4a, 0x4c, 0x4e, 0x50, 0x52, 0x54, 0x56, 0x58, 0x5a, 0x5c, 0x5e, | |
122 0x60, 0x62, 0x64, 0x66, 0x68, 0x6a, 0x6c, 0x6e, 0x70, 0x72, 0x74, 0x76, 0x78, 0x7a, 0x7c, 0x7e, | |
123 0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8c, 0x8e, 0x90, 0x92, 0x94, 0x96, 0x98, 0x9a, 0x9c, 0x9e, | |
124 0xa0, 0xa2, 0xa4, 0xa6, 0xa8, 0xaa, 0xac, 0xae, 0xb0, 0xb2, 0xb4, 0xb6, 0xb8, 0xba, 0xbc, 0xbe, | |
125 0xc0, 0xc2, 0xc4, 0xc6, 0xc8, 0xca, 0xcc, 0xce, 0xd0, 0xd2, 0xd4, 0xd6, 0xd8, 0xda, 0xdc, 0xde, | |
126 0xe0, 0xe2, 0xe4, 0xe6, 0xe8, 0xea, 0xec, 0xee, 0xf0, 0xf2, 0xf4, 0xf6, 0xf8, 0xfa, 0xfc, 0xfe, | |
127 0x1b, 0x19, 0x1f, 0x1d, 0x13, 0x11, 0x17, 0x15, 0x0b, 0x09, 0x0f, 0x0d, 0x03, 0x01, 0x07, 0x05, | |
128 0x3b, 0x39, 0x3f, 0x3d, 0x33, 0x31, 0x37, 0x35, 0x2b, 0x29, 0x2f, 0x2d, 0x23, 0x21, 0x27, 0x25, | |
129 0x5b, 0x59, 0x5f, 0x5d, 0x53, 0x51, 0x57, 0x55, 0x4b, 0x49, 0x4f, 0x4d, 0x43, 0x41, 0x47, 0x45, | |
130 0x7b, 0x79, 0x7f, 0x7d, 0x73, 0x71, 0x77, 0x75, 0x6b, 0x69, 0x6f, 0x6d, 0x63, 0x61, 0x67, 0x65, | |
131 0x9b, 0x99, 0x9f, 0x9d, 0x93, 0x91, 0x97, 0x95, 0x8b, 0x89, 0x8f, 0x8d, 0x83, 0x81, 0x87, 0x85, | |
132 0xbb, 0xb9, 0xbf, 0xbd, 0xb3, 0xb1, 0xb7, 0xb5, 0xab, 0xa9, 0xaf, 0xad, 0xa3, 0xa1, 0xa7, 0xa5, | |
133 0xdb, 0xd9, 0xdf, 0xdd, 0xd3, 0xd1, 0xd7, 0xd5, 0xcb, 0xc9, 0xcf, 0xcd, 0xc3, 0xc1, 0xc7, 0xc5, | |
134 0xfb, 0xf9, 0xff, 0xfd, 0xf3, 0xf1, 0xf7, 0xf5, 0xeb, 0xe9, 0xef, 0xed, 0xe3, 0xe1, 0xe7, 0xe5}; | |
135 | |
136 #define Xtime9(i) (pgm_read_byte(&P_Xtime9[i])) | |
137 const unsigned char P_Xtime9[256] __attribute__ ((__progmem__)) = { | |
138 0x00, 0x09, 0x12, 0x1b, 0x24, 0x2d, 0x36, 0x3f, 0x48, 0x41, 0x5a, 0x53, 0x6c, 0x65, 0x7e, 0x77, | |
139 0x90, 0x99, 0x82, 0x8b, 0xb4, 0xbd, 0xa6, 0xaf, 0xd8, 0xd1, 0xca, 0xc3, 0xfc, 0xf5, 0xee, 0xe7, | |
140 0x3b, 0x32, 0x29, 0x20, 0x1f, 0x16, 0x0d, 0x04, 0x73, 0x7a, 0x61, 0x68, 0x57, 0x5e, 0x45, 0x4c, | |
141 0xab, 0xa2, 0xb9, 0xb0, 0x8f, 0x86, 0x9d, 0x94, 0xe3, 0xea, 0xf1, 0xf8, 0xc7, 0xce, 0xd5, 0xdc, | |
142 0x76, 0x7f, 0x64, 0x6d, 0x52, 0x5b, 0x40, 0x49, 0x3e, 0x37, 0x2c, 0x25, 0x1a, 0x13, 0x08, 0x01, | |
143 0xe6, 0xef, 0xf4, 0xfd, 0xc2, 0xcb, 0xd0, 0xd9, 0xae, 0xa7, 0xbc, 0xb5, 0x8a, 0x83, 0x98, 0x91, | |
144 0x4d, 0x44, 0x5f, 0x56, 0x69, 0x60, 0x7b, 0x72, 0x05, 0x0c, 0x17, 0x1e, 0x21, 0x28, 0x33, 0x3a, | |
145 0xdd, 0xd4, 0xcf, 0xc6, 0xf9, 0xf0, 0xeb, 0xe2, 0x95, 0x9c, 0x87, 0x8e, 0xb1, 0xb8, 0xa3, 0xaa, | |
146 0xec, 0xe5, 0xfe, 0xf7, 0xc8, 0xc1, 0xda, 0xd3, 0xa4, 0xad, 0xb6, 0xbf, 0x80, 0x89, 0x92, 0x9b, | |
147 0x7c, 0x75, 0x6e, 0x67, 0x58, 0x51, 0x4a, 0x43, 0x34, 0x3d, 0x26, 0x2f, 0x10, 0x19, 0x02, 0x0b, | |
148 0xd7, 0xde, 0xc5, 0xcc, 0xf3, 0xfa, 0xe1, 0xe8, 0x9f, 0x96, 0x8d, 0x84, 0xbb, 0xb2, 0xa9, 0xa0, | |
149 0x47, 0x4e, 0x55, 0x5c, 0x63, 0x6a, 0x71, 0x78, 0x0f, 0x06, 0x1d, 0x14, 0x2b, 0x22, 0x39, 0x30, | |
150 0x9a, 0x93, 0x88, 0x81, 0xbe, 0xb7, 0xac, 0xa5, 0xd2, 0xdb, 0xc0, 0xc9, 0xf6, 0xff, 0xe4, 0xed, | |
151 0x0a, 0x03, 0x18, 0x11, 0x2e, 0x27, 0x3c, 0x35, 0x42, 0x4b, 0x50, 0x59, 0x66, 0x6f, 0x74, 0x7d, | |
152 0xa1, 0xa8, 0xb3, 0xba, 0x85, 0x8c, 0x97, 0x9e, 0xe9, 0xe0, 0xfb, 0xf2, 0xcd, 0xc4, 0xdf, 0xd6, | |
153 0x31, 0x38, 0x23, 0x2a, 0x15, 0x1c, 0x07, 0x0e, 0x79, 0x70, 0x6b, 0x62, 0x5d, 0x54, 0x4f, 0x46}; | |
154 | |
155 #define XtimeB(i) (pgm_read_byte(&P_XtimeB[i])) | |
156 const unsigned char P_XtimeB[256] __attribute__ ((__progmem__)) = { | |
157 0x00, 0x0b, 0x16, 0x1d, 0x2c, 0x27, 0x3a, 0x31, 0x58, 0x53, 0x4e, 0x45, 0x74, 0x7f, 0x62, 0x69, | |
158 0xb0, 0xbb, 0xa6, 0xad, 0x9c, 0x97, 0x8a, 0x81, 0xe8, 0xe3, 0xfe, 0xf5, 0xc4, 0xcf, 0xd2, 0xd9, | |
159 0x7b, 0x70, 0x6d, 0x66, 0x57, 0x5c, 0x41, 0x4a, 0x23, 0x28, 0x35, 0x3e, 0x0f, 0x04, 0x19, 0x12, | |
160 0xcb, 0xc0, 0xdd, 0xd6, 0xe7, 0xec, 0xf1, 0xfa, 0x93, 0x98, 0x85, 0x8e, 0xbf, 0xb4, 0xa9, 0xa2, | |
161 0xf6, 0xfd, 0xe0, 0xeb, 0xda, 0xd1, 0xcc, 0xc7, 0xae, 0xa5, 0xb8, 0xb3, 0x82, 0x89, 0x94, 0x9f, | |
162 0x46, 0x4d, 0x50, 0x5b, 0x6a, 0x61, 0x7c, 0x77, 0x1e, 0x15, 0x08, 0x03, 0x32, 0x39, 0x24, 0x2f, | |
163 0x8d, 0x86, 0x9b, 0x90, 0xa1, 0xaa, 0xb7, 0xbc, 0xd5, 0xde, 0xc3, 0xc8, 0xf9, 0xf2, 0xef, 0xe4, | |
164 0x3d, 0x36, 0x2b, 0x20, 0x11, 0x1a, 0x07, 0x0c, 0x65, 0x6e, 0x73, 0x78, 0x49, 0x42, 0x5f, 0x54, | |
165 0xf7, 0xfc, 0xe1, 0xea, 0xdb, 0xd0, 0xcd, 0xc6, 0xaf, 0xa4, 0xb9, 0xb2, 0x83, 0x88, 0x95, 0x9e, | |
166 0x47, 0x4c, 0x51, 0x5a, 0x6b, 0x60, 0x7d, 0x76, 0x1f, 0x14, 0x09, 0x02, 0x33, 0x38, 0x25, 0x2e, | |
167 0x8c, 0x87, 0x9a, 0x91, 0xa0, 0xab, 0xb6, 0xbd, 0xd4, 0xdf, 0xc2, 0xc9, 0xf8, 0xf3, 0xee, 0xe5, | |
168 0x3c, 0x37, 0x2a, 0x21, 0x10, 0x1b, 0x06, 0x0d, 0x64, 0x6f, 0x72, 0x79, 0x48, 0x43, 0x5e, 0x55, | |
169 0x01, 0x0a, 0x17, 0x1c, 0x2d, 0x26, 0x3b, 0x30, 0x59, 0x52, 0x4f, 0x44, 0x75, 0x7e, 0x63, 0x68, | |
170 0xb1, 0xba, 0xa7, 0xac, 0x9d, 0x96, 0x8b, 0x80, 0xe9, 0xe2, 0xff, 0xf4, 0xc5, 0xce, 0xd3, 0xd8, | |
171 0x7a, 0x71, 0x6c, 0x67, 0x56, 0x5d, 0x40, 0x4b, 0x22, 0x29, 0x34, 0x3f, 0x0e, 0x05, 0x18, 0x13, | |
172 0xca, 0xc1, 0xdc, 0xd7, 0xe6, 0xed, 0xf0, 0xfb, 0x92, 0x99, 0x84, 0x8f, 0xbe, 0xb5, 0xa8, 0xa3}; | |
173 | |
174 #define XtimeD(i) (pgm_read_byte(&P_XtimeD[i])) | |
175 const unsigned char P_XtimeD[256] __attribute__ ((__progmem__)) = { | |
176 0x00, 0x0d, 0x1a, 0x17, 0x34, 0x39, 0x2e, 0x23, 0x68, 0x65, 0x72, 0x7f, 0x5c, 0x51, 0x46, 0x4b, | |
177 0xd0, 0xdd, 0xca, 0xc7, 0xe4, 0xe9, 0xfe, 0xf3, 0xb8, 0xb5, 0xa2, 0xaf, 0x8c, 0x81, 0x96, 0x9b, | |
178 0xbb, 0xb6, 0xa1, 0xac, 0x8f, 0x82, 0x95, 0x98, 0xd3, 0xde, 0xc9, 0xc4, 0xe7, 0xea, 0xfd, 0xf0, | |
179 0x6b, 0x66, 0x71, 0x7c, 0x5f, 0x52, 0x45, 0x48, 0x03, 0x0e, 0x19, 0x14, 0x37, 0x3a, 0x2d, 0x20, | |
180 0x6d, 0x60, 0x77, 0x7a, 0x59, 0x54, 0x43, 0x4e, 0x05, 0x08, 0x1f, 0x12, 0x31, 0x3c, 0x2b, 0x26, | |
181 0xbd, 0xb0, 0xa7, 0xaa, 0x89, 0x84, 0x93, 0x9e, 0xd5, 0xd8, 0xcf, 0xc2, 0xe1, 0xec, 0xfb, 0xf6, | |
182 0xd6, 0xdb, 0xcc, 0xc1, 0xe2, 0xef, 0xf8, 0xf5, 0xbe, 0xb3, 0xa4, 0xa9, 0x8a, 0x87, 0x90, 0x9d, | |
183 0x06, 0x0b, 0x1c, 0x11, 0x32, 0x3f, 0x28, 0x25, 0x6e, 0x63, 0x74, 0x79, 0x5a, 0x57, 0x40, 0x4d, | |
184 0xda, 0xd7, 0xc0, 0xcd, 0xee, 0xe3, 0xf4, 0xf9, 0xb2, 0xbf, 0xa8, 0xa5, 0x86, 0x8b, 0x9c, 0x91, | |
185 0x0a, 0x07, 0x10, 0x1d, 0x3e, 0x33, 0x24, 0x29, 0x62, 0x6f, 0x78, 0x75, 0x56, 0x5b, 0x4c, 0x41, | |
186 0x61, 0x6c, 0x7b, 0x76, 0x55, 0x58, 0x4f, 0x42, 0x09, 0x04, 0x13, 0x1e, 0x3d, 0x30, 0x27, 0x2a, | |
187 0xb1, 0xbc, 0xab, 0xa6, 0x85, 0x88, 0x9f, 0x92, 0xd9, 0xd4, 0xc3, 0xce, 0xed, 0xe0, 0xf7, 0xfa, | |
188 0xb7, 0xba, 0xad, 0xa0, 0x83, 0x8e, 0x99, 0x94, 0xdf, 0xd2, 0xc5, 0xc8, 0xeb, 0xe6, 0xf1, 0xfc, | |
189 0x67, 0x6a, 0x7d, 0x70, 0x53, 0x5e, 0x49, 0x44, 0x0f, 0x02, 0x15, 0x18, 0x3b, 0x36, 0x21, 0x2c, | |
190 0x0c, 0x01, 0x16, 0x1b, 0x38, 0x35, 0x22, 0x2f, 0x64, 0x69, 0x7e, 0x73, 0x50, 0x5d, 0x4a, 0x47, | |
191 0xdc, 0xd1, 0xc6, 0xcb, 0xe8, 0xe5, 0xf2, 0xff, 0xb4, 0xb9, 0xae, 0xa3, 0x80, 0x8d, 0x9a, 0x97}; | |
192 | |
193 #define XtimeE(i) (pgm_read_byte(&P_XtimeE[i])) | |
194 const unsigned char P_XtimeE[256] __attribute__ ((__progmem__)) = { | |
195 0x00, 0x0e, 0x1c, 0x12, 0x38, 0x36, 0x24, 0x2a, 0x70, 0x7e, 0x6c, 0x62, 0x48, 0x46, 0x54, 0x5a, | |
196 0xe0, 0xee, 0xfc, 0xf2, 0xd8, 0xd6, 0xc4, 0xca, 0x90, 0x9e, 0x8c, 0x82, 0xa8, 0xa6, 0xb4, 0xba, | |
197 0xdb, 0xd5, 0xc7, 0xc9, 0xe3, 0xed, 0xff, 0xf1, 0xab, 0xa5, 0xb7, 0xb9, 0x93, 0x9d, 0x8f, 0x81, | |
198 0x3b, 0x35, 0x27, 0x29, 0x03, 0x0d, 0x1f, 0x11, 0x4b, 0x45, 0x57, 0x59, 0x73, 0x7d, 0x6f, 0x61, | |
199 0xad, 0xa3, 0xb1, 0xbf, 0x95, 0x9b, 0x89, 0x87, 0xdd, 0xd3, 0xc1, 0xcf, 0xe5, 0xeb, 0xf9, 0xf7, | |
200 0x4d, 0x43, 0x51, 0x5f, 0x75, 0x7b, 0x69, 0x67, 0x3d, 0x33, 0x21, 0x2f, 0x05, 0x0b, 0x19, 0x17, | |
201 0x76, 0x78, 0x6a, 0x64, 0x4e, 0x40, 0x52, 0x5c, 0x06, 0x08, 0x1a, 0x14, 0x3e, 0x30, 0x22, 0x2c, | |
202 0x96, 0x98, 0x8a, 0x84, 0xae, 0xa0, 0xb2, 0xbc, 0xe6, 0xe8, 0xfa, 0xf4, 0xde, 0xd0, 0xc2, 0xcc, | |
203 0x41, 0x4f, 0x5d, 0x53, 0x79, 0x77, 0x65, 0x6b, 0x31, 0x3f, 0x2d, 0x23, 0x09, 0x07, 0x15, 0x1b, | |
204 0xa1, 0xaf, 0xbd, 0xb3, 0x99, 0x97, 0x85, 0x8b, 0xd1, 0xdf, 0xcd, 0xc3, 0xe9, 0xe7, 0xf5, 0xfb, | |
205 0x9a, 0x94, 0x86, 0x88, 0xa2, 0xac, 0xbe, 0xb0, 0xea, 0xe4, 0xf6, 0xf8, 0xd2, 0xdc, 0xce, 0xc0, | |
206 0x7a, 0x74, 0x66, 0x68, 0x42, 0x4c, 0x5e, 0x50, 0x0a, 0x04, 0x16, 0x18, 0x32, 0x3c, 0x2e, 0x20, | |
207 0xec, 0xe2, 0xf0, 0xfe, 0xd4, 0xda, 0xc8, 0xc6, 0x9c, 0x92, 0x80, 0x8e, 0xa4, 0xaa, 0xb8, 0xb6, | |
208 0x0c, 0x02, 0x10, 0x1e, 0x34, 0x3a, 0x28, 0x26, 0x7c, 0x72, 0x60, 0x6e, 0x44, 0x4a, 0x58, 0x56, | |
209 0x37, 0x39, 0x2b, 0x25, 0x0f, 0x01, 0x13, 0x1d, 0x47, 0x49, 0x5b, 0x55, 0x7f, 0x71, 0x63, 0x6d, | |
210 0xd7, 0xd9, 0xcb, 0xc5, 0xef, 0xe1, 0xf3, 0xfd, 0xa7, 0xa9, 0xbb, 0xb5, 0x9f, 0x91, 0x83, 0x8d}; | |
211 | |
212 // exchanges columns in each of 4 rows | |
213 // row0 - unchanged, row1- shifted left 1, | |
214 // row2 - shifted left 2 and row3 - shifted left 3 | |
215 void ShiftRows (unsigned char *state) | |
216 { | |
217 unsigned char tmp; | |
218 | |
219 // just substitute row 0 | |
220 state[0] = Sbox(state[0]), state[4] = Sbox(state[4]); | |
221 state[8] = Sbox(state[8]), state[12] = Sbox(state[12]); | |
222 | |
223 // rotate row 1 | |
224 tmp = Sbox(state[1]), state[1] = Sbox(state[5]); | |
225 state[5] = Sbox(state[9]), state[9] = Sbox(state[13]), state[13] = tmp; | |
226 | |
227 // rotate row 2 | |
228 tmp = Sbox(state[2]), state[2] = Sbox(state[10]), state[10] = tmp; | |
229 tmp = Sbox(state[6]), state[6] = Sbox(state[14]), state[14] = tmp; | |
230 | |
231 // rotate row 3 | |
232 tmp = Sbox(state[15]), state[15] = Sbox(state[11]); | |
233 state[11] = Sbox(state[7]), state[7] = Sbox(state[3]), state[3] = tmp; | |
234 } | |
235 | |
236 // restores columns in each of 4 rows | |
237 // row0 - unchanged, row1- shifted right 1, | |
238 // row2 - shifted right 2 and row3 - shifted right 3 | |
239 void InvShiftRows (unsigned char *state) | |
240 { | |
241 unsigned char tmp; | |
242 | |
243 // restore row 0 | |
244 state[0] = InvSbox(state[0]), state[4] = InvSbox(state[4]); | |
245 state[8] = InvSbox(state[8]), state[12] = InvSbox(state[12]); | |
246 | |
247 // restore row 1 | |
248 tmp = InvSbox(state[13]), state[13] = InvSbox(state[9]); | |
249 state[9] = InvSbox(state[5]), state[5] = InvSbox(state[1]), state[1] = tmp; | |
250 | |
251 // restore row 2 | |
252 tmp = InvSbox(state[2]), state[2] = InvSbox(state[10]), state[10] = tmp; | |
253 tmp = InvSbox(state[6]), state[6] = InvSbox(state[14]), state[14] = tmp; | |
254 | |
255 // restore row 3 | |
256 tmp = InvSbox(state[3]), state[3] = InvSbox(state[7]); | |
257 state[7] = InvSbox(state[11]), state[11] = InvSbox(state[15]), state[15] = tmp; | |
258 } | |
259 | |
260 // recombine and mix each row in a column | |
261 void MixSubColumns (unsigned char *state) | |
262 { | |
263 unsigned char tmp[4 * Nb]; | |
264 | |
265 // mixing column 0 | |
266 tmp[0] = Xtime2Sbox(state[0]) ^ Xtime3Sbox(state[5]) ^ Sbox(state[10]) ^ Sbox(state[15]); | |
267 tmp[1] = Sbox(state[0]) ^ Xtime2Sbox(state[5]) ^ Xtime3Sbox(state[10]) ^ Sbox(state[15]); | |
268 tmp[2] = Sbox(state[0]) ^ Sbox(state[5]) ^ Xtime2Sbox(state[10]) ^ Xtime3Sbox(state[15]); | |
269 tmp[3] = Xtime3Sbox(state[0]) ^ Sbox(state[5]) ^ Sbox(state[10]) ^ Xtime2Sbox(state[15]); | |
270 | |
271 // mixing column 1 | |
272 tmp[4] = Xtime2Sbox(state[4]) ^ Xtime3Sbox(state[9]) ^ Sbox(state[14]) ^ Sbox(state[3]); | |
273 tmp[5] = Sbox(state[4]) ^ Xtime2Sbox(state[9]) ^ Xtime3Sbox(state[14]) ^ Sbox(state[3]); | |
274 tmp[6] = Sbox(state[4]) ^ Sbox(state[9]) ^ Xtime2Sbox(state[14]) ^ Xtime3Sbox(state[3]); | |
275 tmp[7] = Xtime3Sbox(state[4]) ^ Sbox(state[9]) ^ Sbox(state[14]) ^ Xtime2Sbox(state[3]); | |
276 | |
277 // mixing column 2 | |
278 tmp[8] = Xtime2Sbox(state[8]) ^ Xtime3Sbox(state[13]) ^ Sbox(state[2]) ^ Sbox(state[7]); | |
279 tmp[9] = Sbox(state[8]) ^ Xtime2Sbox(state[13]) ^ Xtime3Sbox(state[2]) ^ Sbox(state[7]); | |
280 tmp[10] = Sbox(state[8]) ^ Sbox(state[13]) ^ Xtime2Sbox(state[2]) ^ Xtime3Sbox(state[7]); | |
281 tmp[11] = Xtime3Sbox(state[8]) ^ Sbox(state[13]) ^ Sbox(state[2]) ^ Xtime2Sbox(state[7]); | |
282 | |
283 // mixing column 3 | |
284 tmp[12] = Xtime2Sbox(state[12]) ^ Xtime3Sbox(state[1]) ^ Sbox(state[6]) ^ Sbox(state[11]); | |
285 tmp[13] = Sbox(state[12]) ^ Xtime2Sbox(state[1]) ^ Xtime3Sbox(state[6]) ^ Sbox(state[11]); | |
286 tmp[14] = Sbox(state[12]) ^ Sbox(state[1]) ^ Xtime2Sbox(state[6]) ^ Xtime3Sbox(state[11]); | |
287 tmp[15] = Xtime3Sbox(state[12]) ^ Sbox(state[1]) ^ Sbox(state[6]) ^ Xtime2Sbox(state[11]); | |
288 | |
289 memcpy (state, tmp, sizeof(tmp)); | |
290 } | |
291 | |
292 // restore and un-mix each row in a column | |
293 void InvMixSubColumns (unsigned char *state) | |
294 { | |
295 unsigned char tmp[4 * Nb]; | |
296 int i; | |
297 | |
298 // restore column 0 | |
299 tmp[0] = XtimeE(state[0]) ^ XtimeB(state[1]) ^ XtimeD(state[2]) ^ Xtime9(state[3]); | |
300 tmp[5] = Xtime9(state[0]) ^ XtimeE(state[1]) ^ XtimeB(state[2]) ^ XtimeD(state[3]); | |
301 tmp[10] = XtimeD(state[0]) ^ Xtime9(state[1]) ^ XtimeE(state[2]) ^ XtimeB(state[3]); | |
302 tmp[15] = XtimeB(state[0]) ^ XtimeD(state[1]) ^ Xtime9(state[2]) ^ XtimeE(state[3]); | |
303 | |
304 // restore column 1 | |
305 tmp[4] = XtimeE(state[4]) ^ XtimeB(state[5]) ^ XtimeD(state[6]) ^ Xtime9(state[7]); | |
306 tmp[9] = Xtime9(state[4]) ^ XtimeE(state[5]) ^ XtimeB(state[6]) ^ XtimeD(state[7]); | |
307 tmp[14] = XtimeD(state[4]) ^ Xtime9(state[5]) ^ XtimeE(state[6]) ^ XtimeB(state[7]); | |
308 tmp[3] = XtimeB(state[4]) ^ XtimeD(state[5]) ^ Xtime9(state[6]) ^ XtimeE(state[7]); | |
309 | |
310 // restore column 2 | |
311 tmp[8] = XtimeE(state[8]) ^ XtimeB(state[9]) ^ XtimeD(state[10]) ^ Xtime9(state[11]); | |
312 tmp[13] = Xtime9(state[8]) ^ XtimeE(state[9]) ^ XtimeB(state[10]) ^ XtimeD(state[11]); | |
313 tmp[2] = XtimeD(state[8]) ^ Xtime9(state[9]) ^ XtimeE(state[10]) ^ XtimeB(state[11]); | |
314 tmp[7] = XtimeB(state[8]) ^ XtimeD(state[9]) ^ Xtime9(state[10]) ^ XtimeE(state[11]); | |
315 | |
316 // restore column 3 | |
317 tmp[12] = XtimeE(state[12]) ^ XtimeB(state[13]) ^ XtimeD(state[14]) ^ Xtime9(state[15]); | |
318 tmp[1] = Xtime9(state[12]) ^ XtimeE(state[13]) ^ XtimeB(state[14]) ^ XtimeD(state[15]); | |
319 tmp[6] = XtimeD(state[12]) ^ Xtime9(state[13]) ^ XtimeE(state[14]) ^ XtimeB(state[15]); | |
320 tmp[11] = XtimeB(state[12]) ^ XtimeD(state[13]) ^ Xtime9(state[14]) ^ XtimeE(state[15]); | |
321 | |
322 for( i=0; i < 4 * Nb; i++ ) | |
323 state[i] = InvSbox(tmp[i]); | |
324 } | |
325 | |
326 // encrypt/decrypt columns of the key | |
327 // n.b. you can replace this with | |
328 // byte-wise xor if you wish. | |
329 | |
330 void AddRoundKey (unsigned *state, unsigned *key) | |
331 { | |
332 int idx; | |
333 | |
334 for( idx = 0; idx < 4; idx++ ) | |
335 state[idx] ^= key[idx]; | |
336 } | |
337 | |
338 unsigned char Rcon[11] = { | |
339 0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36}; | |
340 | |
341 // produce Nb bytes for each round | |
342 void ExpandKey (unsigned char *key, unsigned char *expkey) | |
343 { | |
344 unsigned char tmp0, tmp1, tmp2, tmp3, tmp4; | |
345 unsigned idx; | |
346 | |
347 memcpy (expkey, key, Nk * 4); | |
348 | |
349 for( idx = Nk; idx < Nb * (Nr + 1); idx++ ) { | |
350 tmp0 = expkey[4*idx - 4]; | |
351 tmp1 = expkey[4*idx - 3]; | |
352 tmp2 = expkey[4*idx - 2]; | |
353 tmp3 = expkey[4*idx - 1]; | |
354 if( !(idx % Nk) ) { | |
355 tmp4 = tmp3; | |
356 tmp3 = Sbox(tmp0); | |
357 tmp0 = Sbox(tmp1) ^ Rcon[idx/Nk]; | |
358 tmp1 = Sbox(tmp2); | |
359 tmp2 = Sbox(tmp4); | |
360 } else if( Nk > 6 && idx % Nk == 4 ) { | |
361 tmp0 = Sbox(tmp0); | |
362 tmp1 = Sbox(tmp1); | |
363 tmp2 = Sbox(tmp2); | |
364 tmp3 = Sbox(tmp3); | |
365 } | 96 } |
366 | 97 |
367 expkey[4*idx+0] = expkey[4*idx - 4*Nk + 0] ^ tmp0; | 98 // Affine transformation in GF(2). |
368 expkey[4*idx+1] = expkey[4*idx - 4*Nk + 1] ^ tmp1; | 99 result = temp ^ 0x63; // Start with adding a vector in GF(2). |
369 expkey[4*idx+2] = expkey[4*idx - 4*Nk + 2] ^ tmp2; | 100 for( rot = 0; rot < 4; rot++ ) { |
370 expkey[4*idx+3] = expkey[4*idx - 4*Nk + 3] ^ tmp3; | 101 // Rotate left. |
371 } | 102 temp = (temp<<1) | (temp>>7); |
372 } | 103 |
373 | 104 // Add rotated byte in GF(2). |
374 // encrypt one 128 bit block | 105 result ^= temp; |
375 void Encrypt (unsigned char *in, unsigned char *expkey, unsigned char *out) | 106 } |
376 { | 107 |
377 unsigned char state[Nb * 4]; | 108 // Put result in table. |
378 unsigned round; | 109 sBox[i] = result; |
379 | 110 } while( ++i != 0 ); |
380 memcpy (state, in, Nb * 4); | 111 } |
381 AddRoundKey ((unsigned *)state, (unsigned *)expkey); | 112 |
382 | 113 |
383 for( round = 1; round < Nr + 1; round++ ) { | 114 |
384 if( round < Nr ) | 115 void CalcSBoxInv( byte * sBox, byte * sBoxInv ) |
385 MixSubColumns (state); | 116 { |
386 else | 117 byte i = 0; |
387 ShiftRows (state); | 118 byte j = 0; |
388 | 119 |
389 AddRoundKey ((unsigned *)state, (unsigned *)expkey + round * Nb); | 120 // Iterate through all elements in sBoxInv using i. |
390 } | 121 do { |
391 | 122 // Search through sBox using j. |
392 memcpy (out, state, sizeof(state)); | 123 do { |
393 } | 124 // Check if current j is the inverse of current i. |
394 | 125 if( sBox[ j ] == i ) { |
395 void Decrypt (unsigned char *in, unsigned char *expkey, unsigned char *out) | 126 // If so, set sBoxInc and indicate search finished. |
396 { | 127 sBoxInv[ i ] = j; |
397 unsigned char state[Nb * 4]; | 128 j = 255; |
398 unsigned round; | 129 } |
399 | 130 } while( ++j != 0 ); |
400 memcpy (state, in, sizeof(state)); | 131 } while( ++i != 0 ); |
401 | 132 } |
402 AddRoundKey ((unsigned *)state, (unsigned *)expkey + Nr * Nb); | 133 |
403 InvShiftRows(state); | 134 |
404 | 135 |
405 for( round = Nr; round--; ) | 136 void CycleLeft( byte * row ) |
137 { | |
138 // Cycle 4 bytes in an array left once. | |
139 byte temp = row[0]; | |
140 row[0] = row[1]; | |
141 row[1] = row[2]; | |
142 row[2] = row[3]; | |
143 row[3] = temp; | |
144 } | |
145 | |
146 | |
147 | |
148 void InvMixColumn( byte * column ) | |
149 { | |
150 byte result0, result1, result2, result3; | |
151 byte column0, column1, column2, column3; | |
152 byte xor; | |
153 | |
154 // This generates more effective code, at least | |
155 // with the IAR C compiler. | |
156 column0 = column[0]; | |
157 column1 = column[1]; | |
158 column2 = column[2]; | |
159 column3 = column[3]; | |
160 | |
161 // Partial sums (modular addition using XOR). | |
162 result0 = column1 ^ column2 ^ column3; | |
163 result1 = column0 ^ column2 ^ column3; | |
164 result2 = column0 ^ column1 ^ column3; | |
165 result3 = column0 ^ column1 ^ column2; | |
166 | |
167 // Multiply column bytes by 2 modulo BPOLY. | |
168 // This operation is done the following way to ensure cycle count | |
169 // independent from data contents. Take care when changing this code. | |
170 xor = 0; | |
171 if (column0 & 0x80) { | |
172 xor = BPOLY; | |
173 } | |
174 column0 <<= 1; | |
175 column0 ^= xor; | |
176 | |
177 xor = 0; | |
178 if (column1 & 0x80) { | |
179 xor = BPOLY; | |
180 } | |
181 column1 <<= 1; | |
182 column1 ^= xor; | |
183 | |
184 xor = 0; | |
185 if (column2 & 0x80) { | |
186 xor = BPOLY; | |
187 } | |
188 column2 <<= 1; | |
189 column2 ^= xor; | |
190 | |
191 xor = 0; | |
192 if (column3 & 0x80) { | |
193 xor = BPOLY; | |
194 } | |
195 column3 <<= 1; | |
196 column3 ^= xor; | |
197 | |
198 // More partial sums. | |
199 result0 ^= column0 ^ column1; | |
200 result1 ^= column1 ^ column2; | |
201 result2 ^= column2 ^ column3; | |
202 result3 ^= column0 ^ column3; | |
203 | |
204 // Multiply column bytes by 2 modulo BPOLY. | |
205 // This operation is done the following way to ensure cycle count | |
206 // independent from data contents. Take care when changing this code. | |
207 xor = 0; | |
208 if (column0 & 0x80) { | |
209 xor = BPOLY; | |
210 } | |
211 column0 <<= 1; | |
212 column0 ^= xor; | |
213 | |
214 xor = 0; | |
215 if (column1 & 0x80) { | |
216 xor = BPOLY; | |
217 } | |
218 column1 <<= 1; | |
219 column1 ^= xor; | |
220 | |
221 xor = 0; | |
222 if (column2 & 0x80) { | |
223 xor = BPOLY; | |
224 } | |
225 column2 <<= 1; | |
226 column2 ^= xor; | |
227 | |
228 xor = 0; | |
229 if (column3 & 0x80) { | |
230 xor = BPOLY; | |
231 } | |
232 column3 <<= 1; | |
233 column3 ^= xor; | |
234 | |
235 // More partial sums. | |
236 result0 ^= column0 ^ column2; | |
237 result1 ^= column1 ^ column3; | |
238 result2 ^= column0 ^ column2; | |
239 result3 ^= column1 ^ column3; | |
240 | |
241 // Multiply column bytes by 2 modulo BPOLY. | |
242 // This operation is done the following way to ensure cycle count | |
243 // independent from data contents. Take care when changing this code. | |
244 xor = 0; | |
245 if (column0 & 0x80) { | |
246 xor = BPOLY; | |
247 } | |
248 column0 <<= 1; | |
249 column0 ^= xor; | |
250 | |
251 xor = 0; | |
252 if (column1 & 0x80) { | |
253 xor = BPOLY; | |
254 } | |
255 column1 <<= 1; | |
256 column1 ^= xor; | |
257 | |
258 xor = 0; | |
259 if (column2 & 0x80) { | |
260 xor = BPOLY; | |
261 } | |
262 column2 <<= 1; | |
263 column2 ^= xor; | |
264 | |
265 xor = 0; | |
266 if (column3 & 0x80) { | |
267 xor = BPOLY; | |
268 } | |
269 column3 <<= 1; | |
270 column3 ^= xor; | |
271 | |
272 // Final partial sum. | |
273 column0 ^= column1 ^ column2 ^ column3; | |
274 | |
275 // Final sums stored into original column bytes. | |
276 column[0] = result0 ^ column0; | |
277 column[1] = result1 ^ column0; | |
278 column[2] = result2 ^ column0; | |
279 column[3] = result3 ^ column0; | |
280 } | |
281 | |
282 | |
283 | |
284 void SubBytes( byte * bytes, byte count ) | |
285 { | |
286 do { | |
287 *bytes = sBox[ *bytes ]; // Substitute every byte in state. | |
288 bytes++; | |
289 } while( --count ); | |
290 } | |
291 | |
292 | |
293 | |
294 void InvSubBytesAndXOR( byte * bytes, byte * key, byte count ) | |
295 { | |
296 do { | |
297 // *bytes = sBoxInv[ *bytes ] ^ *key; // Inverse substitute every byte in state and add key. | |
298 *bytes = block2[ *bytes ] ^ *key; // Use block2 directly. Increases speed. | |
299 bytes++; | |
300 key++; | |
301 } while( --count ); | |
302 } | |
303 | |
304 | |
305 | |
306 void InvShiftRows( byte * state ) | |
307 { | |
308 byte temp; | |
309 | |
310 // Note: State is arranged column by column. | |
311 | |
312 // Cycle second row right one time. | |
313 temp = state[ 1 + 3*4 ]; | |
314 state[ 1 + 3*4 ] = state[ 1 + 2*4 ]; | |
315 state[ 1 + 2*4 ] = state[ 1 + 1*4 ]; | |
316 state[ 1 + 1*4 ] = state[ 1 + 0*4 ]; | |
317 state[ 1 + 0*4 ] = temp; | |
318 | |
319 // Cycle third row right two times. | |
320 temp = state[ 2 + 0*4 ]; | |
321 state[ 2 + 0*4 ] = state[ 2 + 2*4 ]; | |
322 state[ 2 + 2*4 ] = temp; | |
323 temp = state[ 2 + 1*4 ]; | |
324 state[ 2 + 1*4 ] = state[ 2 + 3*4 ]; | |
325 state[ 2 + 3*4 ] = temp; | |
326 | |
327 // Cycle fourth row right three times, ie. left once. | |
328 temp = state[ 3 + 0*4 ]; | |
329 state[ 3 + 0*4 ] = state[ 3 + 1*4 ]; | |
330 state[ 3 + 1*4 ] = state[ 3 + 2*4 ]; | |
331 state[ 3 + 2*4 ] = state[ 3 + 3*4 ]; | |
332 state[ 3 + 3*4 ] = temp; | |
333 } | |
334 | |
335 | |
336 | |
337 void InvMixColumns( byte * state ) | |
338 { | |
339 InvMixColumn( state + 0*4 ); | |
340 InvMixColumn( state + 1*4 ); | |
341 InvMixColumn( state + 2*4 ); | |
342 InvMixColumn( state + 3*4 ); | |
343 } | |
344 | |
345 | |
346 | |
347 void XORBytes( byte * bytes1, byte * bytes2, byte count ) | |
348 { | |
349 do { | |
350 *bytes1 ^= *bytes2; // Add in GF(2), ie. XOR. | |
351 bytes1++; | |
352 bytes2++; | |
353 } while( --count ); | |
354 } | |
355 | |
356 | |
357 | |
358 void CopyBytes( byte * to, byte * from, byte count ) | |
359 { | |
360 do { | |
361 *to = *from; | |
362 to++; | |
363 from++; | |
364 } while( --count ); | |
365 } | |
366 | |
367 | |
368 | |
369 void KeyExpansion( byte * key, byte * expandedKey ) | |
370 { | |
371 byte temp[4]; | |
372 byte i; | |
373 byte Rcon[4] = { 0x01, 0x00, 0x00, 0x00 }; // Round constant. | |
374 | |
375 #if 0 | |
376 // matt | |
377 unsigned char BOOTFLASH * key = kTable; | |
378 #endif | |
379 | |
380 // Copy key to start of expanded key. | |
381 i = KEYLENGTH; | |
382 do { | |
383 *expandedKey = *key; | |
384 expandedKey++; | |
385 key++; | |
386 } while( --i ); | |
387 | |
388 // Prepare last 4 bytes of key in temp. | |
389 expandedKey -= 4; | |
390 temp[0] = *(expandedKey++); | |
391 temp[1] = *(expandedKey++); | |
392 temp[2] = *(expandedKey++); | |
393 temp[3] = *(expandedKey++); | |
394 | |
395 // Expand key. | |
396 i = KEYLENGTH; | |
397 while( i < BLOCKSIZE*(ROUNDS+1) ) { | |
398 // Are we at the start of a multiple of the key size? | |
399 if( (i % KEYLENGTH) == 0 ) { | |
400 CycleLeft( temp ); // Cycle left once. | |
401 SubBytes( temp, 4 ); // Substitute each byte. | |
402 XORBytes( temp, Rcon, 4 ); // Add constant in GF(2). | |
403 *Rcon = (*Rcon << 1) ^ (*Rcon & 0x80 ? BPOLY : 0); | |
404 } | |
405 | |
406 // Keysize larger than 24 bytes, ie. larger that 192 bits? | |
407 #if KEYLENGTH > 24 | |
408 // Are we right past a block size? | |
409 else if( (i % KEYLENGTH) == BLOCKSIZE ) { | |
410 SubBytes( temp, 4 ); // Substitute each byte. | |
411 } | |
412 #endif | |
413 | |
414 // Add bytes in GF(2) one KEYLENGTH away. | |
415 XORBytes( temp, expandedKey - KEYLENGTH, 4 ); | |
416 | |
417 // Copy result to current 4 bytes. | |
418 *(expandedKey++) = temp[ 0 ]; | |
419 *(expandedKey++) = temp[ 1 ]; | |
420 *(expandedKey++) = temp[ 2 ]; | |
421 *(expandedKey++) = temp[ 3 ]; | |
422 | |
423 i += 4; // Next 4 bytes. | |
424 } | |
425 } | |
426 | |
427 | |
428 | |
429 void InvCipher( byte * block, byte * expandedKey ) | |
430 { | |
431 byte round = ROUNDS-1; | |
432 expandedKey += BLOCKSIZE * ROUNDS; | |
433 | |
434 XORBytes( block, expandedKey, 16 ); | |
435 expandedKey -= BLOCKSIZE; | |
436 | |
437 do { | |
438 InvShiftRows( block ); | |
439 InvSubBytesAndXOR( block, expandedKey, 16 ); | |
440 expandedKey -= BLOCKSIZE; | |
441 InvMixColumns( block ); | |
442 } while( --round ); | |
443 | |
444 InvShiftRows( block ); | |
445 InvSubBytesAndXOR( block, expandedKey, 16 ); | |
446 } | |
447 | |
448 | |
449 | |
450 void aesInit( unsigned char *key, unsigned char * tempbuf ) | |
451 { | |
452 powTbl = block1; | |
453 logTbl = block2; | |
454 CalcPowLog( powTbl, logTbl ); | |
455 | |
456 sBox = tempbuf; | |
457 CalcSBox( sBox ); | |
458 | |
459 expandedKey = block1; | |
460 KeyExpansion( key, expandedKey ); | |
461 | |
462 sBoxInv = block2; // Must be block2. | |
463 CalcSBoxInv( sBox, sBoxInv ); | |
464 } | |
465 | |
466 | |
467 | |
468 void aesDecrypt( unsigned char * buffer, unsigned char * chainBlock ) | |
469 { | |
470 byte temp[ BLOCKSIZE ]; | |
471 | |
472 CopyBytes( temp, buffer, BLOCKSIZE ); | |
473 InvCipher( buffer, expandedKey ); | |
474 if (chainBlock) | |
406 { | 475 { |
407 AddRoundKey ((unsigned *)state, (unsigned *)expkey + round * Nb); | 476 XORBytes( buffer, chainBlock, BLOCKSIZE ); |
408 if( round ) | 477 CopyBytes( chainBlock, temp, BLOCKSIZE ); |
409 InvMixSubColumns (state); | 478 } |
410 } | 479 } |
411 | 480 |
412 memcpy (out, state, sizeof(state)); | |
413 } | |
414 | |
415 | |
416 #if 0 | |
417 | |
418 /*avr specific routines*/ | |
419 #include "backward.h" | |
420 #include <avr/io.h> | |
421 #include <avr/pgmspace.h> | |
422 #include <avr/eeprom.h> | |
423 #include <avr/interrupt.h> | |
424 #include <avr/sleep.h> | |
425 | |
426 | |
427 | |
428 #if defined(at90s2313) || defined(at90s8535) | |
429 #else | |
430 #define ATmega | |
431 #endif | 481 #endif |
432 | |
433 #ifdef ATmega | |
434 #define USR UCSRA | |
435 #endif | |
436 | |
437 | |
438 | |
439 void printP (PGM_P string){ | |
440 char c; | |
441 c=pgm_read_byte(string); | |
442 while (c) { | |
443 loop_until_bit_is_set(USR, UDRE); | |
444 UDR = c; | |
445 c=pgm_read_byte(++string); | |
446 } | |
447 return; | |
448 } | |
449 | |
450 | |
451 | |
452 void print (const char *string){ | |
453 while (*string) { | |
454 loop_until_bit_is_set(USR, UDRE); | |
455 UDR = *string++; | |
456 } | |
457 return; | |
458 } | |
459 | |
460 void scan(char *string){ | |
461 char c; | |
462 do { | |
463 do { | |
464 loop_until_bit_is_set(USR, RXC); | |
465 c =UDR; | |
466 } while bit_is_set(USR, FE); | |
467 *string++ = c; | |
468 //echo the character | |
469 loop_until_bit_is_set(USR, UDRE); | |
470 UDR = c; | |
471 } while ( c != '\r' ); | |
472 loop_until_bit_is_set(USR, UDRE); | |
473 UDR = '\n'; | |
474 string[-1]=0; | |
475 } | |
476 | |
477 | |
478 //UART initialize | |
479 #ifdef ATmega | |
480 #define UCR UCSRB | |
481 #define UART_INIT(baud) { \ | |
482 UBRRH=0; \ | |
483 UBRRL= (XTAL/baud+15)/16-1; \ | |
484 UCSRB=(1<<TXEN)|(1<<RXEN); \ | |
485 UCSRC=(1<<URSEL)|(1<<UCSZ0)|(1<<UCSZ1)|(1<<USBS); } | |
486 #else | |
487 #define UART_INIT(baud) { \ | |
488 UBRR = (XTAL/baud+15)/16-1; \ | |
489 sbi(UCR, TXEN); \ | |
490 sbi(UCR, RXEN); \ | |
491 } | |
492 #endif | |
493 | |
494 #define itoa10(N,S) itoa(N,S,10) | |
495 #define itoa16(N,S) itoa(N,S,16) | |
496 | |
497 | |
498 //DEMO | |
499 | |
500 unsigned char sampleout[16]; | |
501 | |
502 | |
503 unsigned char samplekey[] = {0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, | |
504 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c}; | |
505 | |
506 unsigned char samplein[] = {0x32, 0x43, 0xf6, 0xa8, 0x88, 0x5a, 0x30, 0x8d, 0x31, | |
507 0x31, 0x98, 0xa2, 0xe0, 0x37, 0x07, 0x34}; | |
508 | |
509 #define BAUD 115200 | |
510 | |
511 int main(void) | |
512 { | |
513 UART_INIT(BAUD); | |
514 | |
515 unsigned char expkey[4 * Nb * (Nr + 1)]; | |
516 unsigned char i; | |
517 char c[8]; | |
518 | |
519 printP(PSTR("Original: ")); | |
520 for( i = 0; i < 16; i++ ) {itoa16(samplein[i],c);print(c); print(" ");} | |
521 printP(PSTR("\n")); | |
522 | |
523 ExpandKey (samplekey, expkey); | |
524 Encrypt (samplein, expkey, sampleout); | |
525 | |
526 printP(PSTR("Encrypted: ")); | |
527 for( i = 0; i < 16; i++ ) {itoa16(sampleout[i],c);print(c); print(" ");} | |
528 printP(PSTR("\n")); | |
529 | |
530 Decrypt (sampleout, expkey, samplein); | |
531 | |
532 printP(PSTR("Decrypted: ")); | |
533 | |
534 for( i = 0; i < 16; i++ ) {itoa16(samplein[i],c);print(c); print(" ");} | |
535 printP(PSTR("\n")); | |
536 } | |
537 | |
538 | |
539 #endif |