]>
Commit | Line | Data |
---|---|---|
1 | /********************************************************************* | |
2 | * Filename: aes.c | |
3 | * Author: Brad Conte (brad AT bradconte.com) | |
4 | * Copyright: | |
5 | * Disclaimer: This code is presented "as is" without any guarantees. | |
6 | * Details: This code is the implementation of the AES algorithm and | |
7 | the CTR, CBC, and CCM modes of operation it can be used in. | |
8 | AES is, specified by the NIST in in publication FIPS PUB 197, | |
9 | availible at: | |
10 | * http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf . | |
11 | The CBC and CTR modes of operation are specified by | |
12 | NIST SP 800-38 A, available at: | |
13 | * http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf . | |
14 | The CCM mode of operation is specified by NIST SP80-38 C, available at: | |
15 | * http://csrc.nist.gov/publications/nistpubs/800-38C/SP800-38C_updated-July20_2007.pdf | |
16 | *********************************************************************/ | |
17 | ||
18 | /*************************** HEADER FILES ***************************/ | |
19 | #include <stdlib.h> | |
20 | #include <memory.h> | |
21 | #include "aes.h" | |
22 | ||
23 | #include <stdio.h> | |
24 | ||
25 | /****************************** MACROS ******************************/ | |
26 | // The least significant byte of the word is rotated to the end. | |
27 | #define KE_ROTWORD(x) (((x) << 8) | ((x) >> 24)) | |
28 | ||
29 | #define TRUE 1 | |
30 | #define FALSE 0 | |
31 | ||
32 | /**************************** DATA TYPES ****************************/ | |
33 | #define AES_128_ROUNDS 10 | |
34 | #define AES_192_ROUNDS 12 | |
35 | #define AES_256_ROUNDS 14 | |
36 | ||
37 | /*********************** FUNCTION DECLARATIONS **********************/ | |
38 | void ccm_prepare_first_ctr_blk(BYTE counter[], const BYTE nonce[], int nonce_len, int payload_len_store_size); | |
39 | void ccm_prepare_first_format_blk(BYTE buf[], int assoc_len, int payload_len, int payload_len_store_size, int mac_len, const BYTE nonce[], int nonce_len); | |
40 | void ccm_format_assoc_data(BYTE buf[], int *end_of_buf, const BYTE assoc[], int assoc_len); | |
41 | void ccm_format_payload_data(BYTE buf[], int *end_of_buf, const BYTE payload[], int payload_len); | |
42 | ||
43 | /**************************** VARIABLES *****************************/ | |
44 | // This is the specified AES SBox. To look up a substitution value, put the first | |
45 | // nibble in the first index (row) and the second nibble in the second index (column). | |
46 | static const BYTE aes_sbox[16][16] = { | |
47 | {0x63,0x7C,0x77,0x7B,0xF2,0x6B,0x6F,0xC5,0x30,0x01,0x67,0x2B,0xFE,0xD7,0xAB,0x76}, | |
48 | {0xCA,0x82,0xC9,0x7D,0xFA,0x59,0x47,0xF0,0xAD,0xD4,0xA2,0xAF,0x9C,0xA4,0x72,0xC0}, | |
49 | {0xB7,0xFD,0x93,0x26,0x36,0x3F,0xF7,0xCC,0x34,0xA5,0xE5,0xF1,0x71,0xD8,0x31,0x15}, | |
50 | {0x04,0xC7,0x23,0xC3,0x18,0x96,0x05,0x9A,0x07,0x12,0x80,0xE2,0xEB,0x27,0xB2,0x75}, | |
51 | {0x09,0x83,0x2C,0x1A,0x1B,0x6E,0x5A,0xA0,0x52,0x3B,0xD6,0xB3,0x29,0xE3,0x2F,0x84}, | |
52 | {0x53,0xD1,0x00,0xED,0x20,0xFC,0xB1,0x5B,0x6A,0xCB,0xBE,0x39,0x4A,0x4C,0x58,0xCF}, | |
53 | {0xD0,0xEF,0xAA,0xFB,0x43,0x4D,0x33,0x85,0x45,0xF9,0x02,0x7F,0x50,0x3C,0x9F,0xA8}, | |
54 | {0x51,0xA3,0x40,0x8F,0x92,0x9D,0x38,0xF5,0xBC,0xB6,0xDA,0x21,0x10,0xFF,0xF3,0xD2}, | |
55 | {0xCD,0x0C,0x13,0xEC,0x5F,0x97,0x44,0x17,0xC4,0xA7,0x7E,0x3D,0x64,0x5D,0x19,0x73}, | |
56 | {0x60,0x81,0x4F,0xDC,0x22,0x2A,0x90,0x88,0x46,0xEE,0xB8,0x14,0xDE,0x5E,0x0B,0xDB}, | |
57 | {0xE0,0x32,0x3A,0x0A,0x49,0x06,0x24,0x5C,0xC2,0xD3,0xAC,0x62,0x91,0x95,0xE4,0x79}, | |
58 | {0xE7,0xC8,0x37,0x6D,0x8D,0xD5,0x4E,0xA9,0x6C,0x56,0xF4,0xEA,0x65,0x7A,0xAE,0x08}, | |
59 | {0xBA,0x78,0x25,0x2E,0x1C,0xA6,0xB4,0xC6,0xE8,0xDD,0x74,0x1F,0x4B,0xBD,0x8B,0x8A}, | |
60 | {0x70,0x3E,0xB5,0x66,0x48,0x03,0xF6,0x0E,0x61,0x35,0x57,0xB9,0x86,0xC1,0x1D,0x9E}, | |
61 | {0xE1,0xF8,0x98,0x11,0x69,0xD9,0x8E,0x94,0x9B,0x1E,0x87,0xE9,0xCE,0x55,0x28,0xDF}, | |
62 | {0x8C,0xA1,0x89,0x0D,0xBF,0xE6,0x42,0x68,0x41,0x99,0x2D,0x0F,0xB0,0x54,0xBB,0x16} | |
63 | }; | |
64 | ||
65 | static const BYTE aes_invsbox[16][16] = { | |
66 | {0x52,0x09,0x6A,0xD5,0x30,0x36,0xA5,0x38,0xBF,0x40,0xA3,0x9E,0x81,0xF3,0xD7,0xFB}, | |
67 | {0x7C,0xE3,0x39,0x82,0x9B,0x2F,0xFF,0x87,0x34,0x8E,0x43,0x44,0xC4,0xDE,0xE9,0xCB}, | |
68 | {0x54,0x7B,0x94,0x32,0xA6,0xC2,0x23,0x3D,0xEE,0x4C,0x95,0x0B,0x42,0xFA,0xC3,0x4E}, | |
69 | {0x08,0x2E,0xA1,0x66,0x28,0xD9,0x24,0xB2,0x76,0x5B,0xA2,0x49,0x6D,0x8B,0xD1,0x25}, | |
70 | {0x72,0xF8,0xF6,0x64,0x86,0x68,0x98,0x16,0xD4,0xA4,0x5C,0xCC,0x5D,0x65,0xB6,0x92}, | |
71 | {0x6C,0x70,0x48,0x50,0xFD,0xED,0xB9,0xDA,0x5E,0x15,0x46,0x57,0xA7,0x8D,0x9D,0x84}, | |
72 | {0x90,0xD8,0xAB,0x00,0x8C,0xBC,0xD3,0x0A,0xF7,0xE4,0x58,0x05,0xB8,0xB3,0x45,0x06}, | |
73 | {0xD0,0x2C,0x1E,0x8F,0xCA,0x3F,0x0F,0x02,0xC1,0xAF,0xBD,0x03,0x01,0x13,0x8A,0x6B}, | |
74 | {0x3A,0x91,0x11,0x41,0x4F,0x67,0xDC,0xEA,0x97,0xF2,0xCF,0xCE,0xF0,0xB4,0xE6,0x73}, | |
75 | {0x96,0xAC,0x74,0x22,0xE7,0xAD,0x35,0x85,0xE2,0xF9,0x37,0xE8,0x1C,0x75,0xDF,0x6E}, | |
76 | {0x47,0xF1,0x1A,0x71,0x1D,0x29,0xC5,0x89,0x6F,0xB7,0x62,0x0E,0xAA,0x18,0xBE,0x1B}, | |
77 | {0xFC,0x56,0x3E,0x4B,0xC6,0xD2,0x79,0x20,0x9A,0xDB,0xC0,0xFE,0x78,0xCD,0x5A,0xF4}, | |
78 | {0x1F,0xDD,0xA8,0x33,0x88,0x07,0xC7,0x31,0xB1,0x12,0x10,0x59,0x27,0x80,0xEC,0x5F}, | |
79 | {0x60,0x51,0x7F,0xA9,0x19,0xB5,0x4A,0x0D,0x2D,0xE5,0x7A,0x9F,0x93,0xC9,0x9C,0xEF}, | |
80 | {0xA0,0xE0,0x3B,0x4D,0xAE,0x2A,0xF5,0xB0,0xC8,0xEB,0xBB,0x3C,0x83,0x53,0x99,0x61}, | |
81 | {0x17,0x2B,0x04,0x7E,0xBA,0x77,0xD6,0x26,0xE1,0x69,0x14,0x63,0x55,0x21,0x0C,0x7D} | |
82 | }; | |
83 | ||
84 | // This table stores pre-calculated values for all possible GF(2^8) calculations.This | |
85 | // table is only used by the (Inv)MixColumns steps. | |
86 | // USAGE: The second index (column) is the coefficient of multiplication. Only 7 different | |
87 | // coefficients are used: 0x01, 0x02, 0x03, 0x09, 0x0b, 0x0d, 0x0e, but multiplication by | |
88 | // 1 is negligible leaving only 6 coefficients. Each column of the table is devoted to one | |
89 | // of these coefficients, in the ascending order of value, from values 0x00 to 0xFF. | |
90 | static const BYTE gf_mul[256][6] = { | |
91 | {0x00,0x00,0x00,0x00,0x00,0x00},{0x02,0x03,0x09,0x0b,0x0d,0x0e}, | |
92 | {0x04,0x06,0x12,0x16,0x1a,0x1c},{0x06,0x05,0x1b,0x1d,0x17,0x12}, | |
93 | {0x08,0x0c,0x24,0x2c,0x34,0x38},{0x0a,0x0f,0x2d,0x27,0x39,0x36}, | |
94 | {0x0c,0x0a,0x36,0x3a,0x2e,0x24},{0x0e,0x09,0x3f,0x31,0x23,0x2a}, | |
95 | {0x10,0x18,0x48,0x58,0x68,0x70},{0x12,0x1b,0x41,0x53,0x65,0x7e}, | |
96 | {0x14,0x1e,0x5a,0x4e,0x72,0x6c},{0x16,0x1d,0x53,0x45,0x7f,0x62}, | |
97 | {0x18,0x14,0x6c,0x74,0x5c,0x48},{0x1a,0x17,0x65,0x7f,0x51,0x46}, | |
98 | {0x1c,0x12,0x7e,0x62,0x46,0x54},{0x1e,0x11,0x77,0x69,0x4b,0x5a}, | |
99 | {0x20,0x30,0x90,0xb0,0xd0,0xe0},{0x22,0x33,0x99,0xbb,0xdd,0xee}, | |
100 | {0x24,0x36,0x82,0xa6,0xca,0xfc},{0x26,0x35,0x8b,0xad,0xc7,0xf2}, | |
101 | {0x28,0x3c,0xb4,0x9c,0xe4,0xd8},{0x2a,0x3f,0xbd,0x97,0xe9,0xd6}, | |
102 | {0x2c,0x3a,0xa6,0x8a,0xfe,0xc4},{0x2e,0x39,0xaf,0x81,0xf3,0xca}, | |
103 | {0x30,0x28,0xd8,0xe8,0xb8,0x90},{0x32,0x2b,0xd1,0xe3,0xb5,0x9e}, | |
104 | {0x34,0x2e,0xca,0xfe,0xa2,0x8c},{0x36,0x2d,0xc3,0xf5,0xaf,0x82}, | |
105 | {0x38,0x24,0xfc,0xc4,0x8c,0xa8},{0x3a,0x27,0xf5,0xcf,0x81,0xa6}, | |
106 | {0x3c,0x22,0xee,0xd2,0x96,0xb4},{0x3e,0x21,0xe7,0xd9,0x9b,0xba}, | |
107 | {0x40,0x60,0x3b,0x7b,0xbb,0xdb},{0x42,0x63,0x32,0x70,0xb6,0xd5}, | |
108 | {0x44,0x66,0x29,0x6d,0xa1,0xc7},{0x46,0x65,0x20,0x66,0xac,0xc9}, | |
109 | {0x48,0x6c,0x1f,0x57,0x8f,0xe3},{0x4a,0x6f,0x16,0x5c,0x82,0xed}, | |
110 | {0x4c,0x6a,0x0d,0x41,0x95,0xff},{0x4e,0x69,0x04,0x4a,0x98,0xf1}, | |
111 | {0x50,0x78,0x73,0x23,0xd3,0xab},{0x52,0x7b,0x7a,0x28,0xde,0xa5}, | |
112 | {0x54,0x7e,0x61,0x35,0xc9,0xb7},{0x56,0x7d,0x68,0x3e,0xc4,0xb9}, | |
113 | {0x58,0x74,0x57,0x0f,0xe7,0x93},{0x5a,0x77,0x5e,0x04,0xea,0x9d}, | |
114 | {0x5c,0x72,0x45,0x19,0xfd,0x8f},{0x5e,0x71,0x4c,0x12,0xf0,0x81}, | |
115 | {0x60,0x50,0xab,0xcb,0x6b,0x3b},{0x62,0x53,0xa2,0xc0,0x66,0x35}, | |
116 | {0x64,0x56,0xb9,0xdd,0x71,0x27},{0x66,0x55,0xb0,0xd6,0x7c,0x29}, | |
117 | {0x68,0x5c,0x8f,0xe7,0x5f,0x03},{0x6a,0x5f,0x86,0xec,0x52,0x0d}, | |
118 | {0x6c,0x5a,0x9d,0xf1,0x45,0x1f},{0x6e,0x59,0x94,0xfa,0x48,0x11}, | |
119 | {0x70,0x48,0xe3,0x93,0x03,0x4b},{0x72,0x4b,0xea,0x98,0x0e,0x45}, | |
120 | {0x74,0x4e,0xf1,0x85,0x19,0x57},{0x76,0x4d,0xf8,0x8e,0x14,0x59}, | |
121 | {0x78,0x44,0xc7,0xbf,0x37,0x73},{0x7a,0x47,0xce,0xb4,0x3a,0x7d}, | |
122 | {0x7c,0x42,0xd5,0xa9,0x2d,0x6f},{0x7e,0x41,0xdc,0xa2,0x20,0x61}, | |
123 | {0x80,0xc0,0x76,0xf6,0x6d,0xad},{0x82,0xc3,0x7f,0xfd,0x60,0xa3}, | |
124 | {0x84,0xc6,0x64,0xe0,0x77,0xb1},{0x86,0xc5,0x6d,0xeb,0x7a,0xbf}, | |
125 | {0x88,0xcc,0x52,0xda,0x59,0x95},{0x8a,0xcf,0x5b,0xd1,0x54,0x9b}, | |
126 | {0x8c,0xca,0x40,0xcc,0x43,0x89},{0x8e,0xc9,0x49,0xc7,0x4e,0x87}, | |
127 | {0x90,0xd8,0x3e,0xae,0x05,0xdd},{0x92,0xdb,0x37,0xa5,0x08,0xd3}, | |
128 | {0x94,0xde,0x2c,0xb8,0x1f,0xc1},{0x96,0xdd,0x25,0xb3,0x12,0xcf}, | |
129 | {0x98,0xd4,0x1a,0x82,0x31,0xe5},{0x9a,0xd7,0x13,0x89,0x3c,0xeb}, | |
130 | {0x9c,0xd2,0x08,0x94,0x2b,0xf9},{0x9e,0xd1,0x01,0x9f,0x26,0xf7}, | |
131 | {0xa0,0xf0,0xe6,0x46,0xbd,0x4d},{0xa2,0xf3,0xef,0x4d,0xb0,0x43}, | |
132 | {0xa4,0xf6,0xf4,0x50,0xa7,0x51},{0xa6,0xf5,0xfd,0x5b,0xaa,0x5f}, | |
133 | {0xa8,0xfc,0xc2,0x6a,0x89,0x75},{0xaa,0xff,0xcb,0x61,0x84,0x7b}, | |
134 | {0xac,0xfa,0xd0,0x7c,0x93,0x69},{0xae,0xf9,0xd9,0x77,0x9e,0x67}, | |
135 | {0xb0,0xe8,0xae,0x1e,0xd5,0x3d},{0xb2,0xeb,0xa7,0x15,0xd8,0x33}, | |
136 | {0xb4,0xee,0xbc,0x08,0xcf,0x21},{0xb6,0xed,0xb5,0x03,0xc2,0x2f}, | |
137 | {0xb8,0xe4,0x8a,0x32,0xe1,0x05},{0xba,0xe7,0x83,0x39,0xec,0x0b}, | |
138 | {0xbc,0xe2,0x98,0x24,0xfb,0x19},{0xbe,0xe1,0x91,0x2f,0xf6,0x17}, | |
139 | {0xc0,0xa0,0x4d,0x8d,0xd6,0x76},{0xc2,0xa3,0x44,0x86,0xdb,0x78}, | |
140 | {0xc4,0xa6,0x5f,0x9b,0xcc,0x6a},{0xc6,0xa5,0x56,0x90,0xc1,0x64}, | |
141 | {0xc8,0xac,0x69,0xa1,0xe2,0x4e},{0xca,0xaf,0x60,0xaa,0xef,0x40}, | |
142 | {0xcc,0xaa,0x7b,0xb7,0xf8,0x52},{0xce,0xa9,0x72,0xbc,0xf5,0x5c}, | |
143 | {0xd0,0xb8,0x05,0xd5,0xbe,0x06},{0xd2,0xbb,0x0c,0xde,0xb3,0x08}, | |
144 | {0xd4,0xbe,0x17,0xc3,0xa4,0x1a},{0xd6,0xbd,0x1e,0xc8,0xa9,0x14}, | |
145 | {0xd8,0xb4,0x21,0xf9,0x8a,0x3e},{0xda,0xb7,0x28,0xf2,0x87,0x30}, | |
146 | {0xdc,0xb2,0x33,0xef,0x90,0x22},{0xde,0xb1,0x3a,0xe4,0x9d,0x2c}, | |
147 | {0xe0,0x90,0xdd,0x3d,0x06,0x96},{0xe2,0x93,0xd4,0x36,0x0b,0x98}, | |
148 | {0xe4,0x96,0xcf,0x2b,0x1c,0x8a},{0xe6,0x95,0xc6,0x20,0x11,0x84}, | |
149 | {0xe8,0x9c,0xf9,0x11,0x32,0xae},{0xea,0x9f,0xf0,0x1a,0x3f,0xa0}, | |
150 | {0xec,0x9a,0xeb,0x07,0x28,0xb2},{0xee,0x99,0xe2,0x0c,0x25,0xbc}, | |
151 | {0xf0,0x88,0x95,0x65,0x6e,0xe6},{0xf2,0x8b,0x9c,0x6e,0x63,0xe8}, | |
152 | {0xf4,0x8e,0x87,0x73,0x74,0xfa},{0xf6,0x8d,0x8e,0x78,0x79,0xf4}, | |
153 | {0xf8,0x84,0xb1,0x49,0x5a,0xde},{0xfa,0x87,0xb8,0x42,0x57,0xd0}, | |
154 | {0xfc,0x82,0xa3,0x5f,0x40,0xc2},{0xfe,0x81,0xaa,0x54,0x4d,0xcc}, | |
155 | {0x1b,0x9b,0xec,0xf7,0xda,0x41},{0x19,0x98,0xe5,0xfc,0xd7,0x4f}, | |
156 | {0x1f,0x9d,0xfe,0xe1,0xc0,0x5d},{0x1d,0x9e,0xf7,0xea,0xcd,0x53}, | |
157 | {0x13,0x97,0xc8,0xdb,0xee,0x79},{0x11,0x94,0xc1,0xd0,0xe3,0x77}, | |
158 | {0x17,0x91,0xda,0xcd,0xf4,0x65},{0x15,0x92,0xd3,0xc6,0xf9,0x6b}, | |
159 | {0x0b,0x83,0xa4,0xaf,0xb2,0x31},{0x09,0x80,0xad,0xa4,0xbf,0x3f}, | |
160 | {0x0f,0x85,0xb6,0xb9,0xa8,0x2d},{0x0d,0x86,0xbf,0xb2,0xa5,0x23}, | |
161 | {0x03,0x8f,0x80,0x83,0x86,0x09},{0x01,0x8c,0x89,0x88,0x8b,0x07}, | |
162 | {0x07,0x89,0x92,0x95,0x9c,0x15},{0x05,0x8a,0x9b,0x9e,0x91,0x1b}, | |
163 | {0x3b,0xab,0x7c,0x47,0x0a,0xa1},{0x39,0xa8,0x75,0x4c,0x07,0xaf}, | |
164 | {0x3f,0xad,0x6e,0x51,0x10,0xbd},{0x3d,0xae,0x67,0x5a,0x1d,0xb3}, | |
165 | {0x33,0xa7,0x58,0x6b,0x3e,0x99},{0x31,0xa4,0x51,0x60,0x33,0x97}, | |
166 | {0x37,0xa1,0x4a,0x7d,0x24,0x85},{0x35,0xa2,0x43,0x76,0x29,0x8b}, | |
167 | {0x2b,0xb3,0x34,0x1f,0x62,0xd1},{0x29,0xb0,0x3d,0x14,0x6f,0xdf}, | |
168 | {0x2f,0xb5,0x26,0x09,0x78,0xcd},{0x2d,0xb6,0x2f,0x02,0x75,0xc3}, | |
169 | {0x23,0xbf,0x10,0x33,0x56,0xe9},{0x21,0xbc,0x19,0x38,0x5b,0xe7}, | |
170 | {0x27,0xb9,0x02,0x25,0x4c,0xf5},{0x25,0xba,0x0b,0x2e,0x41,0xfb}, | |
171 | {0x5b,0xfb,0xd7,0x8c,0x61,0x9a},{0x59,0xf8,0xde,0x87,0x6c,0x94}, | |
172 | {0x5f,0xfd,0xc5,0x9a,0x7b,0x86},{0x5d,0xfe,0xcc,0x91,0x76,0x88}, | |
173 | {0x53,0xf7,0xf3,0xa0,0x55,0xa2},{0x51,0xf4,0xfa,0xab,0x58,0xac}, | |
174 | {0x57,0xf1,0xe1,0xb6,0x4f,0xbe},{0x55,0xf2,0xe8,0xbd,0x42,0xb0}, | |
175 | {0x4b,0xe3,0x9f,0xd4,0x09,0xea},{0x49,0xe0,0x96,0xdf,0x04,0xe4}, | |
176 | {0x4f,0xe5,0x8d,0xc2,0x13,0xf6},{0x4d,0xe6,0x84,0xc9,0x1e,0xf8}, | |
177 | {0x43,0xef,0xbb,0xf8,0x3d,0xd2},{0x41,0xec,0xb2,0xf3,0x30,0xdc}, | |
178 | {0x47,0xe9,0xa9,0xee,0x27,0xce},{0x45,0xea,0xa0,0xe5,0x2a,0xc0}, | |
179 | {0x7b,0xcb,0x47,0x3c,0xb1,0x7a},{0x79,0xc8,0x4e,0x37,0xbc,0x74}, | |
180 | {0x7f,0xcd,0x55,0x2a,0xab,0x66},{0x7d,0xce,0x5c,0x21,0xa6,0x68}, | |
181 | {0x73,0xc7,0x63,0x10,0x85,0x42},{0x71,0xc4,0x6a,0x1b,0x88,0x4c}, | |
182 | {0x77,0xc1,0x71,0x06,0x9f,0x5e},{0x75,0xc2,0x78,0x0d,0x92,0x50}, | |
183 | {0x6b,0xd3,0x0f,0x64,0xd9,0x0a},{0x69,0xd0,0x06,0x6f,0xd4,0x04}, | |
184 | {0x6f,0xd5,0x1d,0x72,0xc3,0x16},{0x6d,0xd6,0x14,0x79,0xce,0x18}, | |
185 | {0x63,0xdf,0x2b,0x48,0xed,0x32},{0x61,0xdc,0x22,0x43,0xe0,0x3c}, | |
186 | {0x67,0xd9,0x39,0x5e,0xf7,0x2e},{0x65,0xda,0x30,0x55,0xfa,0x20}, | |
187 | {0x9b,0x5b,0x9a,0x01,0xb7,0xec},{0x99,0x58,0x93,0x0a,0xba,0xe2}, | |
188 | {0x9f,0x5d,0x88,0x17,0xad,0xf0},{0x9d,0x5e,0x81,0x1c,0xa0,0xfe}, | |
189 | {0x93,0x57,0xbe,0x2d,0x83,0xd4},{0x91,0x54,0xb7,0x26,0x8e,0xda}, | |
190 | {0x97,0x51,0xac,0x3b,0x99,0xc8},{0x95,0x52,0xa5,0x30,0x94,0xc6}, | |
191 | {0x8b,0x43,0xd2,0x59,0xdf,0x9c},{0x89,0x40,0xdb,0x52,0xd2,0x92}, | |
192 | {0x8f,0x45,0xc0,0x4f,0xc5,0x80},{0x8d,0x46,0xc9,0x44,0xc8,0x8e}, | |
193 | {0x83,0x4f,0xf6,0x75,0xeb,0xa4},{0x81,0x4c,0xff,0x7e,0xe6,0xaa}, | |
194 | {0x87,0x49,0xe4,0x63,0xf1,0xb8},{0x85,0x4a,0xed,0x68,0xfc,0xb6}, | |
195 | {0xbb,0x6b,0x0a,0xb1,0x67,0x0c},{0xb9,0x68,0x03,0xba,0x6a,0x02}, | |
196 | {0xbf,0x6d,0x18,0xa7,0x7d,0x10},{0xbd,0x6e,0x11,0xac,0x70,0x1e}, | |
197 | {0xb3,0x67,0x2e,0x9d,0x53,0x34},{0xb1,0x64,0x27,0x96,0x5e,0x3a}, | |
198 | {0xb7,0x61,0x3c,0x8b,0x49,0x28},{0xb5,0x62,0x35,0x80,0x44,0x26}, | |
199 | {0xab,0x73,0x42,0xe9,0x0f,0x7c},{0xa9,0x70,0x4b,0xe2,0x02,0x72}, | |
200 | {0xaf,0x75,0x50,0xff,0x15,0x60},{0xad,0x76,0x59,0xf4,0x18,0x6e}, | |
201 | {0xa3,0x7f,0x66,0xc5,0x3b,0x44},{0xa1,0x7c,0x6f,0xce,0x36,0x4a}, | |
202 | {0xa7,0x79,0x74,0xd3,0x21,0x58},{0xa5,0x7a,0x7d,0xd8,0x2c,0x56}, | |
203 | {0xdb,0x3b,0xa1,0x7a,0x0c,0x37},{0xd9,0x38,0xa8,0x71,0x01,0x39}, | |
204 | {0xdf,0x3d,0xb3,0x6c,0x16,0x2b},{0xdd,0x3e,0xba,0x67,0x1b,0x25}, | |
205 | {0xd3,0x37,0x85,0x56,0x38,0x0f},{0xd1,0x34,0x8c,0x5d,0x35,0x01}, | |
206 | {0xd7,0x31,0x97,0x40,0x22,0x13},{0xd5,0x32,0x9e,0x4b,0x2f,0x1d}, | |
207 | {0xcb,0x23,0xe9,0x22,0x64,0x47},{0xc9,0x20,0xe0,0x29,0x69,0x49}, | |
208 | {0xcf,0x25,0xfb,0x34,0x7e,0x5b},{0xcd,0x26,0xf2,0x3f,0x73,0x55}, | |
209 | {0xc3,0x2f,0xcd,0x0e,0x50,0x7f},{0xc1,0x2c,0xc4,0x05,0x5d,0x71}, | |
210 | {0xc7,0x29,0xdf,0x18,0x4a,0x63},{0xc5,0x2a,0xd6,0x13,0x47,0x6d}, | |
211 | {0xfb,0x0b,0x31,0xca,0xdc,0xd7},{0xf9,0x08,0x38,0xc1,0xd1,0xd9}, | |
212 | {0xff,0x0d,0x23,0xdc,0xc6,0xcb},{0xfd,0x0e,0x2a,0xd7,0xcb,0xc5}, | |
213 | {0xf3,0x07,0x15,0xe6,0xe8,0xef},{0xf1,0x04,0x1c,0xed,0xe5,0xe1}, | |
214 | {0xf7,0x01,0x07,0xf0,0xf2,0xf3},{0xf5,0x02,0x0e,0xfb,0xff,0xfd}, | |
215 | {0xeb,0x13,0x79,0x92,0xb4,0xa7},{0xe9,0x10,0x70,0x99,0xb9,0xa9}, | |
216 | {0xef,0x15,0x6b,0x84,0xae,0xbb},{0xed,0x16,0x62,0x8f,0xa3,0xb5}, | |
217 | {0xe3,0x1f,0x5d,0xbe,0x80,0x9f},{0xe1,0x1c,0x54,0xb5,0x8d,0x91}, | |
218 | {0xe7,0x19,0x4f,0xa8,0x9a,0x83},{0xe5,0x1a,0x46,0xa3,0x97,0x8d} | |
219 | }; | |
220 | ||
221 | /*********************** FUNCTION DEFINITIONS ***********************/ | |
222 | // XORs the in and out buffers, storing the result in out. Length is in bytes. | |
223 | void xor_buf(const BYTE in[], BYTE out[], size_t len) | |
224 | { | |
225 | size_t idx; | |
226 | ||
227 | for (idx = 0; idx < len; idx++) | |
228 | out[idx] ^= in[idx]; | |
229 | } | |
230 | ||
231 | /******************* | |
232 | * AES - CBC | |
233 | *******************/ | |
234 | int aes_encrypt_cbc(const BYTE in[], size_t in_len, BYTE out[], const WORD key[], int keysize, const BYTE iv[]) | |
235 | { | |
236 | BYTE buf_in[AES_BLOCK_SIZE], buf_out[AES_BLOCK_SIZE], iv_buf[AES_BLOCK_SIZE]; | |
237 | int blocks, idx; | |
238 | ||
239 | if (in_len % AES_BLOCK_SIZE != 0) | |
240 | return(FALSE); | |
241 | ||
242 | blocks = in_len / AES_BLOCK_SIZE; | |
243 | ||
244 | memcpy(iv_buf, iv, AES_BLOCK_SIZE); | |
245 | ||
246 | for (idx = 0; idx < blocks; idx++) { | |
247 | memcpy(buf_in, &in[idx * AES_BLOCK_SIZE], AES_BLOCK_SIZE); | |
248 | xor_buf(iv_buf, buf_in, AES_BLOCK_SIZE); | |
249 | aes_encrypt(buf_in, buf_out, key, keysize); | |
250 | memcpy(&out[idx * AES_BLOCK_SIZE], buf_out, AES_BLOCK_SIZE); | |
251 | memcpy(iv_buf, buf_out, AES_BLOCK_SIZE); | |
252 | } | |
253 | ||
254 | return(TRUE); | |
255 | } | |
256 | ||
257 | int aes_encrypt_cbc_mac(const BYTE in[], size_t in_len, BYTE out[], const WORD key[], int keysize, const BYTE iv[]) | |
258 | { | |
259 | BYTE buf_in[AES_BLOCK_SIZE], buf_out[AES_BLOCK_SIZE], iv_buf[AES_BLOCK_SIZE]; | |
260 | int blocks, idx; | |
261 | ||
262 | if (in_len % AES_BLOCK_SIZE != 0) | |
263 | return(FALSE); | |
264 | ||
265 | blocks = in_len / AES_BLOCK_SIZE; | |
266 | ||
267 | memcpy(iv_buf, iv, AES_BLOCK_SIZE); | |
268 | ||
269 | for (idx = 0; idx < blocks; idx++) { | |
270 | memcpy(buf_in, &in[idx * AES_BLOCK_SIZE], AES_BLOCK_SIZE); | |
271 | xor_buf(iv_buf, buf_in, AES_BLOCK_SIZE); | |
272 | aes_encrypt(buf_in, buf_out, key, keysize); | |
273 | memcpy(iv_buf, buf_out, AES_BLOCK_SIZE); | |
274 | // Do not output all encrypted blocks. | |
275 | } | |
276 | ||
277 | memcpy(out, buf_out, AES_BLOCK_SIZE); // Only output the last block. | |
278 | ||
279 | return(TRUE); | |
280 | } | |
281 | ||
282 | int aes_decrypt_cbc(const BYTE in[], size_t in_len, BYTE out[], const WORD key[], int keysize, const BYTE iv[]) | |
283 | { | |
284 | BYTE buf_in[AES_BLOCK_SIZE], buf_out[AES_BLOCK_SIZE], iv_buf[AES_BLOCK_SIZE]; | |
285 | int blocks, idx; | |
286 | ||
287 | if (in_len % AES_BLOCK_SIZE != 0) | |
288 | return(FALSE); | |
289 | ||
290 | blocks = in_len / AES_BLOCK_SIZE; | |
291 | ||
292 | memcpy(iv_buf, iv, AES_BLOCK_SIZE); | |
293 | ||
294 | for (idx = 0; idx < blocks; idx++) { | |
295 | memcpy(buf_in, &in[idx * AES_BLOCK_SIZE], AES_BLOCK_SIZE); | |
296 | aes_decrypt(buf_in, buf_out, key, keysize); | |
297 | xor_buf(iv_buf, buf_out, AES_BLOCK_SIZE); | |
298 | memcpy(&out[idx * AES_BLOCK_SIZE], buf_out, AES_BLOCK_SIZE); | |
299 | memcpy(iv_buf, buf_in, AES_BLOCK_SIZE); | |
300 | } | |
301 | ||
302 | return(TRUE); | |
303 | } | |
304 | ||
305 | /******************* | |
306 | * AES - CTR | |
307 | *******************/ | |
308 | void increment_iv(BYTE iv[], int counter_size) | |
309 | { | |
310 | int idx; | |
311 | ||
312 | // Use counter_size bytes at the end of the IV as the big-endian integer to increment. | |
313 | for (idx = AES_BLOCK_SIZE - 1; idx >= AES_BLOCK_SIZE - counter_size; idx--) { | |
314 | iv[idx]++; | |
315 | if (iv[idx] != 0 || idx == AES_BLOCK_SIZE - counter_size) | |
316 | break; | |
317 | } | |
318 | } | |
319 | ||
320 | // Performs the encryption in-place, the input and output buffers may be the same. | |
321 | // Input may be an arbitrary length (in bytes). | |
322 | void aes_encrypt_ctr(const BYTE in[], size_t in_len, BYTE out[], const WORD key[], int keysize, const BYTE iv[]) | |
323 | { | |
324 | size_t idx = 0, last_block_length; | |
325 | BYTE iv_buf[AES_BLOCK_SIZE], out_buf[AES_BLOCK_SIZE]; | |
326 | ||
327 | if (in != out) | |
328 | memcpy(out, in, in_len); | |
329 | ||
330 | memcpy(iv_buf, iv, AES_BLOCK_SIZE); | |
331 | last_block_length = in_len - AES_BLOCK_SIZE; | |
332 | ||
333 | if (in_len > AES_BLOCK_SIZE) { | |
334 | for (idx = 0; idx < last_block_length; idx += AES_BLOCK_SIZE) { | |
335 | aes_encrypt(iv_buf, out_buf, key, keysize); | |
336 | xor_buf(out_buf, &out[idx], AES_BLOCK_SIZE); | |
337 | increment_iv(iv_buf, AES_BLOCK_SIZE); | |
338 | } | |
339 | } | |
340 | ||
341 | aes_encrypt(iv_buf, out_buf, key, keysize); | |
342 | xor_buf(out_buf, &out[idx], in_len - idx); // Use the Most Significant bytes. | |
343 | } | |
344 | ||
345 | void aes_decrypt_ctr(const BYTE in[], size_t in_len, BYTE out[], const WORD key[], int keysize, const BYTE iv[]) | |
346 | { | |
347 | // CTR encryption is its own inverse function. | |
348 | aes_encrypt_ctr(in, in_len, out, key, keysize, iv); | |
349 | } | |
350 | ||
351 | /******************* | |
352 | * AES - CCM | |
353 | *******************/ | |
354 | // out_len = payload_len + assoc_len | |
355 | int aes_encrypt_ccm(const BYTE payload[], WORD payload_len, const BYTE assoc[], unsigned short assoc_len, | |
356 | const BYTE nonce[], unsigned short nonce_len, BYTE out[], WORD *out_len, | |
357 | WORD mac_len, const BYTE key_str[], int keysize) | |
358 | { | |
359 | BYTE temp_iv[AES_BLOCK_SIZE], counter[AES_BLOCK_SIZE], mac[16], *buf; | |
360 | int end_of_buf, payload_len_store_size; | |
361 | WORD key[60]; | |
362 | ||
363 | if (mac_len != 4 && mac_len != 6 && mac_len != 8 && mac_len != 10 && | |
364 | mac_len != 12 && mac_len != 14 && mac_len != 16) | |
365 | return(FALSE); | |
366 | ||
367 | if (nonce_len < 7 || nonce_len > 13) | |
368 | return(FALSE); | |
369 | ||
370 | if (assoc_len > 32768 /* = 2^15 */) | |
371 | return(FALSE); | |
372 | ||
373 | buf = (BYTE*)malloc(payload_len + assoc_len + 48 /*Round both payload and associated data up a block size and add an extra block.*/); | |
374 | if (! buf) | |
375 | return(FALSE); | |
376 | ||
377 | // Prepare the key for usage. | |
378 | aes_key_setup(key_str, key, keysize); | |
379 | ||
380 | // Format the first block of the formatted data. | |
381 | payload_len_store_size = AES_BLOCK_SIZE - 1 - nonce_len; | |
382 | ccm_prepare_first_format_blk(buf, assoc_len, payload_len, payload_len_store_size, mac_len, nonce, nonce_len); | |
383 | end_of_buf = AES_BLOCK_SIZE; | |
384 | ||
385 | // Format the Associated Data, aka, assoc[]. | |
386 | ccm_format_assoc_data(buf, &end_of_buf, assoc, assoc_len); | |
387 | ||
388 | // Format the Payload, aka payload[]. | |
389 | ccm_format_payload_data(buf, &end_of_buf, payload, payload_len); | |
390 | ||
391 | // Create the first counter block. | |
392 | ccm_prepare_first_ctr_blk(counter, nonce, nonce_len, payload_len_store_size); | |
393 | ||
394 | // Perform the CBC operation with an IV of zeros on the formatted buffer to calculate the MAC. | |
395 | memset(temp_iv, 0, AES_BLOCK_SIZE); | |
396 | aes_encrypt_cbc_mac(buf, end_of_buf, mac, key, keysize, temp_iv); | |
397 | ||
398 | // Copy the Payload and MAC to the output buffer. | |
399 | memcpy(out, payload, payload_len); | |
400 | memcpy(&out[payload_len], mac, mac_len); | |
401 | ||
402 | // Encrypt the Payload with CTR mode with a counter starting at 1. | |
403 | memcpy(temp_iv, counter, AES_BLOCK_SIZE); | |
404 | increment_iv(temp_iv, AES_BLOCK_SIZE - 1 - mac_len); // Last argument is the byte size of the counting portion of the counter block. /*BUG?*/ | |
405 | aes_encrypt_ctr(out, payload_len, out, key, keysize, temp_iv); | |
406 | ||
407 | // Encrypt the MAC with CTR mode with a counter starting at 0. | |
408 | aes_encrypt_ctr(&out[payload_len], mac_len, &out[payload_len], key, keysize, counter); | |
409 | ||
410 | free(buf); | |
411 | *out_len = payload_len + mac_len; | |
412 | ||
413 | return(TRUE); | |
414 | } | |
415 | ||
416 | // plaintext_len = ciphertext_len - mac_len | |
417 | // Needs a flag for whether the MAC matches. | |
418 | int aes_decrypt_ccm(const BYTE ciphertext[], WORD ciphertext_len, const BYTE assoc[], unsigned short assoc_len, | |
419 | const BYTE nonce[], unsigned short nonce_len, BYTE plaintext[], WORD *plaintext_len, | |
420 | WORD mac_len, int *mac_auth, const BYTE key_str[], int keysize) | |
421 | { | |
422 | BYTE temp_iv[AES_BLOCK_SIZE], counter[AES_BLOCK_SIZE], mac[16], mac_buf[16], *buf; | |
423 | int end_of_buf, plaintext_len_store_size; | |
424 | WORD key[60]; | |
425 | ||
426 | if (ciphertext_len <= mac_len) | |
427 | return(FALSE); | |
428 | ||
429 | buf = (BYTE*)malloc(assoc_len + ciphertext_len /*ciphertext_len = plaintext_len + mac_len*/ + 48); | |
430 | if (! buf) | |
431 | return(FALSE); | |
432 | ||
433 | // Prepare the key for usage. | |
434 | aes_key_setup(key_str, key, keysize); | |
435 | ||
436 | // Copy the plaintext and MAC to the output buffers. | |
437 | *plaintext_len = ciphertext_len - mac_len; | |
438 | plaintext_len_store_size = AES_BLOCK_SIZE - 1 - nonce_len; | |
439 | memcpy(plaintext, ciphertext, *plaintext_len); | |
440 | memcpy(mac, &ciphertext[*plaintext_len], mac_len); | |
441 | ||
442 | // Prepare the first counter block for use in decryption. | |
443 | ccm_prepare_first_ctr_blk(counter, nonce, nonce_len, plaintext_len_store_size); | |
444 | ||
445 | // Decrypt the Payload with CTR mode with a counter starting at 1. | |
446 | memcpy(temp_iv, counter, AES_BLOCK_SIZE); | |
447 | increment_iv(temp_iv, AES_BLOCK_SIZE - 1 - mac_len); // (AES_BLOCK_SIZE - 1 - mac_len) is the byte size of the counting portion of the counter block. | |
448 | aes_decrypt_ctr(plaintext, *plaintext_len, plaintext, key, keysize, temp_iv); | |
449 | ||
450 | // Setting mac_auth to NULL disables the authentication check. | |
451 | if (mac_auth != NULL) { | |
452 | // Decrypt the MAC with CTR mode with a counter starting at 0. | |
453 | aes_decrypt_ctr(mac, mac_len, mac, key, keysize, counter); | |
454 | ||
455 | // Format the first block of the formatted data. | |
456 | plaintext_len_store_size = AES_BLOCK_SIZE - 1 - nonce_len; | |
457 | ccm_prepare_first_format_blk(buf, assoc_len, *plaintext_len, plaintext_len_store_size, mac_len, nonce, nonce_len); | |
458 | end_of_buf = AES_BLOCK_SIZE; | |
459 | ||
460 | // Format the Associated Data into the authentication buffer. | |
461 | ccm_format_assoc_data(buf, &end_of_buf, assoc, assoc_len); | |
462 | ||
463 | // Format the Payload into the authentication buffer. | |
464 | ccm_format_payload_data(buf, &end_of_buf, plaintext, *plaintext_len); | |
465 | ||
466 | // Perform the CBC operation with an IV of zeros on the formatted buffer to calculate the MAC. | |
467 | memset(temp_iv, 0, AES_BLOCK_SIZE); | |
468 | aes_encrypt_cbc_mac(buf, end_of_buf, mac_buf, key, keysize, temp_iv); | |
469 | ||
470 | // Compare the calculated MAC against the MAC embedded in the ciphertext to see if they are the same. | |
471 | if (! memcmp(mac, mac_buf, mac_len)) { | |
472 | *mac_auth = TRUE; | |
473 | } | |
474 | else { | |
475 | *mac_auth = FALSE; | |
476 | memset(plaintext, 0, *plaintext_len); | |
477 | } | |
478 | } | |
479 | ||
480 | free(buf); | |
481 | ||
482 | return(TRUE); | |
483 | } | |
484 | ||
485 | // Creates the first counter block. First byte is flags, then the nonce, then the incremented part. | |
486 | void ccm_prepare_first_ctr_blk(BYTE counter[], const BYTE nonce[], int nonce_len, int payload_len_store_size) | |
487 | { | |
488 | memset(counter, 0, AES_BLOCK_SIZE); | |
489 | counter[0] = (payload_len_store_size - 1) & 0x07; | |
490 | memcpy(&counter[1], nonce, nonce_len); | |
491 | } | |
492 | ||
493 | void ccm_prepare_first_format_blk(BYTE buf[], int assoc_len, int payload_len, int payload_len_store_size, int mac_len, const BYTE nonce[], int nonce_len) | |
494 | { | |
495 | // Set the flags for the first byte of the first block. | |
496 | buf[0] = ((((mac_len - 2) / 2) & 0x07) << 3) | ((payload_len_store_size - 1) & 0x07); | |
497 | if (assoc_len > 0) | |
498 | buf[0] += 0x40; | |
499 | // Format the rest of the first block, storing the nonce and the size of the payload. | |
500 | memcpy(&buf[1], nonce, nonce_len); | |
501 | memset(&buf[1 + nonce_len], 0, AES_BLOCK_SIZE - 1 - nonce_len); | |
502 | buf[15] = payload_len & 0x000000FF; | |
503 | buf[14] = (payload_len >> 8) & 0x000000FF; | |
504 | } | |
505 | ||
506 | void ccm_format_assoc_data(BYTE buf[], int *end_of_buf, const BYTE assoc[], int assoc_len) | |
507 | { | |
508 | int pad; | |
509 | ||
510 | buf[*end_of_buf + 1] = assoc_len & 0x00FF; | |
511 | buf[*end_of_buf] = (assoc_len >> 8) & 0x00FF; | |
512 | *end_of_buf += 2; | |
513 | memcpy(&buf[*end_of_buf], assoc, assoc_len); | |
514 | *end_of_buf += assoc_len; | |
515 | pad = AES_BLOCK_SIZE - (*end_of_buf % AES_BLOCK_SIZE); /*BUG?*/ | |
516 | memset(&buf[*end_of_buf], 0, pad); | |
517 | *end_of_buf += pad; | |
518 | } | |
519 | ||
520 | void ccm_format_payload_data(BYTE buf[], int *end_of_buf, const BYTE payload[], int payload_len) | |
521 | { | |
522 | int pad; | |
523 | ||
524 | memcpy(&buf[*end_of_buf], payload, payload_len); | |
525 | *end_of_buf += payload_len; | |
526 | pad = *end_of_buf % AES_BLOCK_SIZE; | |
527 | if (pad != 0) | |
528 | pad = AES_BLOCK_SIZE - pad; | |
529 | memset(&buf[*end_of_buf], 0, pad); | |
530 | *end_of_buf += pad; | |
531 | } | |
532 | ||
533 | /******************* | |
534 | * AES | |
535 | *******************/ | |
536 | ///////////////// | |
537 | // KEY EXPANSION | |
538 | ///////////////// | |
539 | ||
540 | // Substitutes a word using the AES S-Box. | |
541 | WORD SubWord(WORD word) | |
542 | { | |
543 | unsigned int result; | |
544 | ||
545 | result = (int)aes_sbox[(word >> 4) & 0x0000000F][word & 0x0000000F]; | |
546 | result += (int)aes_sbox[(word >> 12) & 0x0000000F][(word >> 8) & 0x0000000F] << 8; | |
547 | result += (int)aes_sbox[(word >> 20) & 0x0000000F][(word >> 16) & 0x0000000F] << 16; | |
548 | result += (int)aes_sbox[(word >> 28) & 0x0000000F][(word >> 24) & 0x0000000F] << 24; | |
549 | return(result); | |
550 | } | |
551 | ||
552 | // Performs the action of generating the keys that will be used in every round of | |
553 | // encryption. "key" is the user-supplied input key, "w" is the output key schedule, | |
554 | // "keysize" is the length in bits of "key", must be 128, 192, or 256. | |
555 | void aes_key_setup(const BYTE key[], WORD w[], int keysize) | |
556 | { | |
557 | int Nb=4,Nr,Nk,idx; | |
558 | WORD temp,Rcon[]={0x01000000,0x02000000,0x04000000,0x08000000,0x10000000,0x20000000, | |
559 | 0x40000000,0x80000000,0x1b000000,0x36000000,0x6c000000,0xd8000000, | |
560 | 0xab000000,0x4d000000,0x9a000000}; | |
561 | ||
562 | switch (keysize) { | |
563 | case 128: Nr = 10; Nk = 4; break; | |
564 | case 192: Nr = 12; Nk = 6; break; | |
565 | case 256: Nr = 14; Nk = 8; break; | |
566 | default: return; | |
567 | } | |
568 | ||
569 | for (idx=0; idx < Nk; ++idx) { | |
570 | w[idx] = ((key[4 * idx]) << 24) | ((key[4 * idx + 1]) << 16) | | |
571 | ((key[4 * idx + 2]) << 8) | ((key[4 * idx + 3])); | |
572 | } | |
573 | ||
574 | for (idx = Nk; idx < Nb * (Nr+1); ++idx) { | |
575 | temp = w[idx - 1]; | |
576 | if ((idx % Nk) == 0) | |
577 | temp = SubWord(KE_ROTWORD(temp)) ^ Rcon[(idx-1)/Nk]; | |
578 | else if (Nk > 6 && (idx % Nk) == 4) | |
579 | temp = SubWord(temp); | |
580 | w[idx] = w[idx-Nk] ^ temp; | |
581 | } | |
582 | } | |
583 | ||
584 | ///////////////// | |
585 | // ADD ROUND KEY | |
586 | ///////////////// | |
587 | ||
588 | // Performs the AddRoundKey step. Each round has its own pre-generated 16-byte key in the | |
589 | // form of 4 integers (the "w" array). Each integer is XOR'd by one column of the state. | |
590 | // Also performs the job of InvAddRoundKey(); since the function is a simple XOR process, | |
591 | // it is its own inverse. | |
592 | void AddRoundKey(BYTE state[][4], const WORD w[]) | |
593 | { | |
594 | BYTE subkey[4]; | |
595 | ||
596 | // memcpy(subkey,&w[idx],4); // Not accurate for big endian machines | |
597 | // Subkey 1 | |
598 | subkey[0] = w[0] >> 24; | |
599 | subkey[1] = w[0] >> 16; | |
600 | subkey[2] = w[0] >> 8; | |
601 | subkey[3] = w[0]; | |
602 | state[0][0] ^= subkey[0]; | |
603 | state[1][0] ^= subkey[1]; | |
604 | state[2][0] ^= subkey[2]; | |
605 | state[3][0] ^= subkey[3]; | |
606 | // Subkey 2 | |
607 | subkey[0] = w[1] >> 24; | |
608 | subkey[1] = w[1] >> 16; | |
609 | subkey[2] = w[1] >> 8; | |
610 | subkey[3] = w[1]; | |
611 | state[0][1] ^= subkey[0]; | |
612 | state[1][1] ^= subkey[1]; | |
613 | state[2][1] ^= subkey[2]; | |
614 | state[3][1] ^= subkey[3]; | |
615 | // Subkey 3 | |
616 | subkey[0] = w[2] >> 24; | |
617 | subkey[1] = w[2] >> 16; | |
618 | subkey[2] = w[2] >> 8; | |
619 | subkey[3] = w[2]; | |
620 | state[0][2] ^= subkey[0]; | |
621 | state[1][2] ^= subkey[1]; | |
622 | state[2][2] ^= subkey[2]; | |
623 | state[3][2] ^= subkey[3]; | |
624 | // Subkey 4 | |
625 | subkey[0] = w[3] >> 24; | |
626 | subkey[1] = w[3] >> 16; | |
627 | subkey[2] = w[3] >> 8; | |
628 | subkey[3] = w[3]; | |
629 | state[0][3] ^= subkey[0]; | |
630 | state[1][3] ^= subkey[1]; | |
631 | state[2][3] ^= subkey[2]; | |
632 | state[3][3] ^= subkey[3]; | |
633 | } | |
634 | ||
635 | ///////////////// | |
636 | // (Inv)SubBytes | |
637 | ///////////////// | |
638 | ||
639 | // Performs the SubBytes step. All bytes in the state are substituted with a | |
640 | // pre-calculated value from a lookup table. | |
641 | void SubBytes(BYTE state[][4]) | |
642 | { | |
643 | state[0][0] = aes_sbox[state[0][0] >> 4][state[0][0] & 0x0F]; | |
644 | state[0][1] = aes_sbox[state[0][1] >> 4][state[0][1] & 0x0F]; | |
645 | state[0][2] = aes_sbox[state[0][2] >> 4][state[0][2] & 0x0F]; | |
646 | state[0][3] = aes_sbox[state[0][3] >> 4][state[0][3] & 0x0F]; | |
647 | state[1][0] = aes_sbox[state[1][0] >> 4][state[1][0] & 0x0F]; | |
648 | state[1][1] = aes_sbox[state[1][1] >> 4][state[1][1] & 0x0F]; | |
649 | state[1][2] = aes_sbox[state[1][2] >> 4][state[1][2] & 0x0F]; | |
650 | state[1][3] = aes_sbox[state[1][3] >> 4][state[1][3] & 0x0F]; | |
651 | state[2][0] = aes_sbox[state[2][0] >> 4][state[2][0] & 0x0F]; | |
652 | state[2][1] = aes_sbox[state[2][1] >> 4][state[2][1] & 0x0F]; | |
653 | state[2][2] = aes_sbox[state[2][2] >> 4][state[2][2] & 0x0F]; | |
654 | state[2][3] = aes_sbox[state[2][3] >> 4][state[2][3] & 0x0F]; | |
655 | state[3][0] = aes_sbox[state[3][0] >> 4][state[3][0] & 0x0F]; | |
656 | state[3][1] = aes_sbox[state[3][1] >> 4][state[3][1] & 0x0F]; | |
657 | state[3][2] = aes_sbox[state[3][2] >> 4][state[3][2] & 0x0F]; | |
658 | state[3][3] = aes_sbox[state[3][3] >> 4][state[3][3] & 0x0F]; | |
659 | } | |
660 | ||
661 | void InvSubBytes(BYTE state[][4]) | |
662 | { | |
663 | state[0][0] = aes_invsbox[state[0][0] >> 4][state[0][0] & 0x0F]; | |
664 | state[0][1] = aes_invsbox[state[0][1] >> 4][state[0][1] & 0x0F]; | |
665 | state[0][2] = aes_invsbox[state[0][2] >> 4][state[0][2] & 0x0F]; | |
666 | state[0][3] = aes_invsbox[state[0][3] >> 4][state[0][3] & 0x0F]; | |
667 | state[1][0] = aes_invsbox[state[1][0] >> 4][state[1][0] & 0x0F]; | |
668 | state[1][1] = aes_invsbox[state[1][1] >> 4][state[1][1] & 0x0F]; | |
669 | state[1][2] = aes_invsbox[state[1][2] >> 4][state[1][2] & 0x0F]; | |
670 | state[1][3] = aes_invsbox[state[1][3] >> 4][state[1][3] & 0x0F]; | |
671 | state[2][0] = aes_invsbox[state[2][0] >> 4][state[2][0] & 0x0F]; | |
672 | state[2][1] = aes_invsbox[state[2][1] >> 4][state[2][1] & 0x0F]; | |
673 | state[2][2] = aes_invsbox[state[2][2] >> 4][state[2][2] & 0x0F]; | |
674 | state[2][3] = aes_invsbox[state[2][3] >> 4][state[2][3] & 0x0F]; | |
675 | state[3][0] = aes_invsbox[state[3][0] >> 4][state[3][0] & 0x0F]; | |
676 | state[3][1] = aes_invsbox[state[3][1] >> 4][state[3][1] & 0x0F]; | |
677 | state[3][2] = aes_invsbox[state[3][2] >> 4][state[3][2] & 0x0F]; | |
678 | state[3][3] = aes_invsbox[state[3][3] >> 4][state[3][3] & 0x0F]; | |
679 | } | |
680 | ||
681 | ///////////////// | |
682 | // (Inv)ShiftRows | |
683 | ///////////////// | |
684 | ||
685 | // Performs the ShiftRows step. All rows are shifted cylindrically to the left. | |
686 | void ShiftRows(BYTE state[][4]) | |
687 | { | |
688 | int t; | |
689 | ||
690 | // Shift left by 1 | |
691 | t = state[1][0]; | |
692 | state[1][0] = state[1][1]; | |
693 | state[1][1] = state[1][2]; | |
694 | state[1][2] = state[1][3]; | |
695 | state[1][3] = t; | |
696 | // Shift left by 2 | |
697 | t = state[2][0]; | |
698 | state[2][0] = state[2][2]; | |
699 | state[2][2] = t; | |
700 | t = state[2][1]; | |
701 | state[2][1] = state[2][3]; | |
702 | state[2][3] = t; | |
703 | // Shift left by 3 | |
704 | t = state[3][0]; | |
705 | state[3][0] = state[3][3]; | |
706 | state[3][3] = state[3][2]; | |
707 | state[3][2] = state[3][1]; | |
708 | state[3][1] = t; | |
709 | } | |
710 | ||
711 | // All rows are shifted cylindrically to the right. | |
712 | void InvShiftRows(BYTE state[][4]) | |
713 | { | |
714 | int t; | |
715 | ||
716 | // Shift right by 1 | |
717 | t = state[1][3]; | |
718 | state[1][3] = state[1][2]; | |
719 | state[1][2] = state[1][1]; | |
720 | state[1][1] = state[1][0]; | |
721 | state[1][0] = t; | |
722 | // Shift right by 2 | |
723 | t = state[2][3]; | |
724 | state[2][3] = state[2][1]; | |
725 | state[2][1] = t; | |
726 | t = state[2][2]; | |
727 | state[2][2] = state[2][0]; | |
728 | state[2][0] = t; | |
729 | // Shift right by 3 | |
730 | t = state[3][3]; | |
731 | state[3][3] = state[3][0]; | |
732 | state[3][0] = state[3][1]; | |
733 | state[3][1] = state[3][2]; | |
734 | state[3][2] = t; | |
735 | } | |
736 | ||
737 | ///////////////// | |
738 | // (Inv)MixColumns | |
739 | ///////////////// | |
740 | ||
741 | // Performs the MixColums step. The state is multiplied by itself using matrix | |
742 | // multiplication in a Galios Field 2^8. All multiplication is pre-computed in a table. | |
743 | // Addition is equivilent to XOR. (Must always make a copy of the column as the original | |
744 | // values will be destoyed.) | |
745 | void MixColumns(BYTE state[][4]) | |
746 | { | |
747 | BYTE col[4]; | |
748 | ||
749 | // Column 1 | |
750 | col[0] = state[0][0]; | |
751 | col[1] = state[1][0]; | |
752 | col[2] = state[2][0]; | |
753 | col[3] = state[3][0]; | |
754 | state[0][0] = gf_mul[col[0]][0]; | |
755 | state[0][0] ^= gf_mul[col[1]][1]; | |
756 | state[0][0] ^= col[2]; | |
757 | state[0][0] ^= col[3]; | |
758 | state[1][0] = col[0]; | |
759 | state[1][0] ^= gf_mul[col[1]][0]; | |
760 | state[1][0] ^= gf_mul[col[2]][1]; | |
761 | state[1][0] ^= col[3]; | |
762 | state[2][0] = col[0]; | |
763 | state[2][0] ^= col[1]; | |
764 | state[2][0] ^= gf_mul[col[2]][0]; | |
765 | state[2][0] ^= gf_mul[col[3]][1]; | |
766 | state[3][0] = gf_mul[col[0]][1]; | |
767 | state[3][0] ^= col[1]; | |
768 | state[3][0] ^= col[2]; | |
769 | state[3][0] ^= gf_mul[col[3]][0]; | |
770 | // Column 2 | |
771 | col[0] = state[0][1]; | |
772 | col[1] = state[1][1]; | |
773 | col[2] = state[2][1]; | |
774 | col[3] = state[3][1]; | |
775 | state[0][1] = gf_mul[col[0]][0]; | |
776 | state[0][1] ^= gf_mul[col[1]][1]; | |
777 | state[0][1] ^= col[2]; | |
778 | state[0][1] ^= col[3]; | |
779 | state[1][1] = col[0]; | |
780 | state[1][1] ^= gf_mul[col[1]][0]; | |
781 | state[1][1] ^= gf_mul[col[2]][1]; | |
782 | state[1][1] ^= col[3]; | |
783 | state[2][1] = col[0]; | |
784 | state[2][1] ^= col[1]; | |
785 | state[2][1] ^= gf_mul[col[2]][0]; | |
786 | state[2][1] ^= gf_mul[col[3]][1]; | |
787 | state[3][1] = gf_mul[col[0]][1]; | |
788 | state[3][1] ^= col[1]; | |
789 | state[3][1] ^= col[2]; | |
790 | state[3][1] ^= gf_mul[col[3]][0]; | |
791 | // Column 3 | |
792 | col[0] = state[0][2]; | |
793 | col[1] = state[1][2]; | |
794 | col[2] = state[2][2]; | |
795 | col[3] = state[3][2]; | |
796 | state[0][2] = gf_mul[col[0]][0]; | |
797 | state[0][2] ^= gf_mul[col[1]][1]; | |
798 | state[0][2] ^= col[2]; | |
799 | state[0][2] ^= col[3]; | |
800 | state[1][2] = col[0]; | |
801 | state[1][2] ^= gf_mul[col[1]][0]; | |
802 | state[1][2] ^= gf_mul[col[2]][1]; | |
803 | state[1][2] ^= col[3]; | |
804 | state[2][2] = col[0]; | |
805 | state[2][2] ^= col[1]; | |
806 | state[2][2] ^= gf_mul[col[2]][0]; | |
807 | state[2][2] ^= gf_mul[col[3]][1]; | |
808 | state[3][2] = gf_mul[col[0]][1]; | |
809 | state[3][2] ^= col[1]; | |
810 | state[3][2] ^= col[2]; | |
811 | state[3][2] ^= gf_mul[col[3]][0]; | |
812 | // Column 4 | |
813 | col[0] = state[0][3]; | |
814 | col[1] = state[1][3]; | |
815 | col[2] = state[2][3]; | |
816 | col[3] = state[3][3]; | |
817 | state[0][3] = gf_mul[col[0]][0]; | |
818 | state[0][3] ^= gf_mul[col[1]][1]; | |
819 | state[0][3] ^= col[2]; | |
820 | state[0][3] ^= col[3]; | |
821 | state[1][3] = col[0]; | |
822 | state[1][3] ^= gf_mul[col[1]][0]; | |
823 | state[1][3] ^= gf_mul[col[2]][1]; | |
824 | state[1][3] ^= col[3]; | |
825 | state[2][3] = col[0]; | |
826 | state[2][3] ^= col[1]; | |
827 | state[2][3] ^= gf_mul[col[2]][0]; | |
828 | state[2][3] ^= gf_mul[col[3]][1]; | |
829 | state[3][3] = gf_mul[col[0]][1]; | |
830 | state[3][3] ^= col[1]; | |
831 | state[3][3] ^= col[2]; | |
832 | state[3][3] ^= gf_mul[col[3]][0]; | |
833 | } | |
834 | ||
835 | void InvMixColumns(BYTE state[][4]) | |
836 | { | |
837 | BYTE col[4]; | |
838 | ||
839 | // Column 1 | |
840 | col[0] = state[0][0]; | |
841 | col[1] = state[1][0]; | |
842 | col[2] = state[2][0]; | |
843 | col[3] = state[3][0]; | |
844 | state[0][0] = gf_mul[col[0]][5]; | |
845 | state[0][0] ^= gf_mul[col[1]][3]; | |
846 | state[0][0] ^= gf_mul[col[2]][4]; | |
847 | state[0][0] ^= gf_mul[col[3]][2]; | |
848 | state[1][0] = gf_mul[col[0]][2]; | |
849 | state[1][0] ^= gf_mul[col[1]][5]; | |
850 | state[1][0] ^= gf_mul[col[2]][3]; | |
851 | state[1][0] ^= gf_mul[col[3]][4]; | |
852 | state[2][0] = gf_mul[col[0]][4]; | |
853 | state[2][0] ^= gf_mul[col[1]][2]; | |
854 | state[2][0] ^= gf_mul[col[2]][5]; | |
855 | state[2][0] ^= gf_mul[col[3]][3]; | |
856 | state[3][0] = gf_mul[col[0]][3]; | |
857 | state[3][0] ^= gf_mul[col[1]][4]; | |
858 | state[3][0] ^= gf_mul[col[2]][2]; | |
859 | state[3][0] ^= gf_mul[col[3]][5]; | |
860 | // Column 2 | |
861 | col[0] = state[0][1]; | |
862 | col[1] = state[1][1]; | |
863 | col[2] = state[2][1]; | |
864 | col[3] = state[3][1]; | |
865 | state[0][1] = gf_mul[col[0]][5]; | |
866 | state[0][1] ^= gf_mul[col[1]][3]; | |
867 | state[0][1] ^= gf_mul[col[2]][4]; | |
868 | state[0][1] ^= gf_mul[col[3]][2]; | |
869 | state[1][1] = gf_mul[col[0]][2]; | |
870 | state[1][1] ^= gf_mul[col[1]][5]; | |
871 | state[1][1] ^= gf_mul[col[2]][3]; | |
872 | state[1][1] ^= gf_mul[col[3]][4]; | |
873 | state[2][1] = gf_mul[col[0]][4]; | |
874 | state[2][1] ^= gf_mul[col[1]][2]; | |
875 | state[2][1] ^= gf_mul[col[2]][5]; | |
876 | state[2][1] ^= gf_mul[col[3]][3]; | |
877 | state[3][1] = gf_mul[col[0]][3]; | |
878 | state[3][1] ^= gf_mul[col[1]][4]; | |
879 | state[3][1] ^= gf_mul[col[2]][2]; | |
880 | state[3][1] ^= gf_mul[col[3]][5]; | |
881 | // Column 3 | |
882 | col[0] = state[0][2]; | |
883 | col[1] = state[1][2]; | |
884 | col[2] = state[2][2]; | |
885 | col[3] = state[3][2]; | |
886 | state[0][2] = gf_mul[col[0]][5]; | |
887 | state[0][2] ^= gf_mul[col[1]][3]; | |
888 | state[0][2] ^= gf_mul[col[2]][4]; | |
889 | state[0][2] ^= gf_mul[col[3]][2]; | |
890 | state[1][2] = gf_mul[col[0]][2]; | |
891 | state[1][2] ^= gf_mul[col[1]][5]; | |
892 | state[1][2] ^= gf_mul[col[2]][3]; | |
893 | state[1][2] ^= gf_mul[col[3]][4]; | |
894 | state[2][2] = gf_mul[col[0]][4]; | |
895 | state[2][2] ^= gf_mul[col[1]][2]; | |
896 | state[2][2] ^= gf_mul[col[2]][5]; | |
897 | state[2][2] ^= gf_mul[col[3]][3]; | |
898 | state[3][2] = gf_mul[col[0]][3]; | |
899 | state[3][2] ^= gf_mul[col[1]][4]; | |
900 | state[3][2] ^= gf_mul[col[2]][2]; | |
901 | state[3][2] ^= gf_mul[col[3]][5]; | |
902 | // Column 4 | |
903 | col[0] = state[0][3]; | |
904 | col[1] = state[1][3]; | |
905 | col[2] = state[2][3]; | |
906 | col[3] = state[3][3]; | |
907 | state[0][3] = gf_mul[col[0]][5]; | |
908 | state[0][3] ^= gf_mul[col[1]][3]; | |
909 | state[0][3] ^= gf_mul[col[2]][4]; | |
910 | state[0][3] ^= gf_mul[col[3]][2]; | |
911 | state[1][3] = gf_mul[col[0]][2]; | |
912 | state[1][3] ^= gf_mul[col[1]][5]; | |
913 | state[1][3] ^= gf_mul[col[2]][3]; | |
914 | state[1][3] ^= gf_mul[col[3]][4]; | |
915 | state[2][3] = gf_mul[col[0]][4]; | |
916 | state[2][3] ^= gf_mul[col[1]][2]; | |
917 | state[2][3] ^= gf_mul[col[2]][5]; | |
918 | state[2][3] ^= gf_mul[col[3]][3]; | |
919 | state[3][3] = gf_mul[col[0]][3]; | |
920 | state[3][3] ^= gf_mul[col[1]][4]; | |
921 | state[3][3] ^= gf_mul[col[2]][2]; | |
922 | state[3][3] ^= gf_mul[col[3]][5]; | |
923 | } | |
924 | ||
925 | ///////////////// | |
926 | // (En/De)Crypt | |
927 | ///////////////// | |
928 | ||
929 | void aes_encrypt(const BYTE in[], BYTE out[], const WORD key[], int keysize) | |
930 | { | |
931 | BYTE state[4][4]; | |
932 | ||
933 | // Copy input array (should be 16 bytes long) to a matrix (sequential bytes are ordered | |
934 | // by row, not col) called "state" for processing. | |
935 | // *** Implementation note: The official AES documentation references the state by | |
936 | // column, then row. Accessing an element in C requires row then column. Thus, all state | |
937 | // references in AES must have the column and row indexes reversed for C implementation. | |
938 | state[0][0] = in[0]; | |
939 | state[1][0] = in[1]; | |
940 | state[2][0] = in[2]; | |
941 | state[3][0] = in[3]; | |
942 | state[0][1] = in[4]; | |
943 | state[1][1] = in[5]; | |
944 | state[2][1] = in[6]; | |
945 | state[3][1] = in[7]; | |
946 | state[0][2] = in[8]; | |
947 | state[1][2] = in[9]; | |
948 | state[2][2] = in[10]; | |
949 | state[3][2] = in[11]; | |
950 | state[0][3] = in[12]; | |
951 | state[1][3] = in[13]; | |
952 | state[2][3] = in[14]; | |
953 | state[3][3] = in[15]; | |
954 | ||
955 | // Perform the necessary number of rounds. The round key is added first. | |
956 | // The last round does not perform the MixColumns step. | |
957 | AddRoundKey(state,&key[0]); | |
958 | SubBytes(state); ShiftRows(state); MixColumns(state); AddRoundKey(state,&key[4]); | |
959 | SubBytes(state); ShiftRows(state); MixColumns(state); AddRoundKey(state,&key[8]); | |
960 | SubBytes(state); ShiftRows(state); MixColumns(state); AddRoundKey(state,&key[12]); | |
961 | SubBytes(state); ShiftRows(state); MixColumns(state); AddRoundKey(state,&key[16]); | |
962 | SubBytes(state); ShiftRows(state); MixColumns(state); AddRoundKey(state,&key[20]); | |
963 | SubBytes(state); ShiftRows(state); MixColumns(state); AddRoundKey(state,&key[24]); | |
964 | SubBytes(state); ShiftRows(state); MixColumns(state); AddRoundKey(state,&key[28]); | |
965 | SubBytes(state); ShiftRows(state); MixColumns(state); AddRoundKey(state,&key[32]); | |
966 | SubBytes(state); ShiftRows(state); MixColumns(state); AddRoundKey(state,&key[36]); | |
967 | if (keysize != 128) { | |
968 | SubBytes(state); ShiftRows(state); MixColumns(state); AddRoundKey(state,&key[40]); | |
969 | SubBytes(state); ShiftRows(state); MixColumns(state); AddRoundKey(state,&key[44]); | |
970 | if (keysize != 192) { | |
971 | SubBytes(state); ShiftRows(state); MixColumns(state); AddRoundKey(state,&key[48]); | |
972 | SubBytes(state); ShiftRows(state); MixColumns(state); AddRoundKey(state,&key[52]); | |
973 | SubBytes(state); ShiftRows(state); AddRoundKey(state,&key[56]); | |
974 | } | |
975 | else { | |
976 | SubBytes(state); ShiftRows(state); AddRoundKey(state,&key[48]); | |
977 | } | |
978 | } | |
979 | else { | |
980 | SubBytes(state); ShiftRows(state); AddRoundKey(state,&key[40]); | |
981 | } | |
982 | ||
983 | // Copy the state to the output array. | |
984 | out[0] = state[0][0]; | |
985 | out[1] = state[1][0]; | |
986 | out[2] = state[2][0]; | |
987 | out[3] = state[3][0]; | |
988 | out[4] = state[0][1]; | |
989 | out[5] = state[1][1]; | |
990 | out[6] = state[2][1]; | |
991 | out[7] = state[3][1]; | |
992 | out[8] = state[0][2]; | |
993 | out[9] = state[1][2]; | |
994 | out[10] = state[2][2]; | |
995 | out[11] = state[3][2]; | |
996 | out[12] = state[0][3]; | |
997 | out[13] = state[1][3]; | |
998 | out[14] = state[2][3]; | |
999 | out[15] = state[3][3]; | |
1000 | } | |
1001 | ||
1002 | void aes_decrypt(const BYTE in[], BYTE out[], const WORD key[], int keysize) | |
1003 | { | |
1004 | BYTE state[4][4]; | |
1005 | ||
1006 | // Copy the input to the state. | |
1007 | state[0][0] = in[0]; | |
1008 | state[1][0] = in[1]; | |
1009 | state[2][0] = in[2]; | |
1010 | state[3][0] = in[3]; | |
1011 | state[0][1] = in[4]; | |
1012 | state[1][1] = in[5]; | |
1013 | state[2][1] = in[6]; | |
1014 | state[3][1] = in[7]; | |
1015 | state[0][2] = in[8]; | |
1016 | state[1][2] = in[9]; | |
1017 | state[2][2] = in[10]; | |
1018 | state[3][2] = in[11]; | |
1019 | state[0][3] = in[12]; | |
1020 | state[1][3] = in[13]; | |
1021 | state[2][3] = in[14]; | |
1022 | state[3][3] = in[15]; | |
1023 | ||
1024 | // Perform the necessary number of rounds. The round key is added first. | |
1025 | // The last round does not perform the MixColumns step. | |
1026 | if (keysize > 128) { | |
1027 | if (keysize > 192) { | |
1028 | AddRoundKey(state,&key[56]); | |
1029 | InvShiftRows(state);InvSubBytes(state);AddRoundKey(state,&key[52]);InvMixColumns(state); | |
1030 | InvShiftRows(state);InvSubBytes(state);AddRoundKey(state,&key[48]);InvMixColumns(state); | |
1031 | } | |
1032 | else { | |
1033 | AddRoundKey(state,&key[48]); | |
1034 | } | |
1035 | InvShiftRows(state);InvSubBytes(state);AddRoundKey(state,&key[44]);InvMixColumns(state); | |
1036 | InvShiftRows(state);InvSubBytes(state);AddRoundKey(state,&key[40]);InvMixColumns(state); | |
1037 | } | |
1038 | else { | |
1039 | AddRoundKey(state,&key[40]); | |
1040 | } | |
1041 | InvShiftRows(state);InvSubBytes(state);AddRoundKey(state,&key[36]);InvMixColumns(state); | |
1042 | InvShiftRows(state);InvSubBytes(state);AddRoundKey(state,&key[32]);InvMixColumns(state); | |
1043 | InvShiftRows(state);InvSubBytes(state);AddRoundKey(state,&key[28]);InvMixColumns(state); | |
1044 | InvShiftRows(state);InvSubBytes(state);AddRoundKey(state,&key[24]);InvMixColumns(state); | |
1045 | InvShiftRows(state);InvSubBytes(state);AddRoundKey(state,&key[20]);InvMixColumns(state); | |
1046 | InvShiftRows(state);InvSubBytes(state);AddRoundKey(state,&key[16]);InvMixColumns(state); | |
1047 | InvShiftRows(state);InvSubBytes(state);AddRoundKey(state,&key[12]);InvMixColumns(state); | |
1048 | InvShiftRows(state);InvSubBytes(state);AddRoundKey(state,&key[8]);InvMixColumns(state); | |
1049 | InvShiftRows(state);InvSubBytes(state);AddRoundKey(state,&key[4]);InvMixColumns(state); | |
1050 | InvShiftRows(state);InvSubBytes(state);AddRoundKey(state,&key[0]); | |
1051 | ||
1052 | // Copy the state to the output array. | |
1053 | out[0] = state[0][0]; | |
1054 | out[1] = state[1][0]; | |
1055 | out[2] = state[2][0]; | |
1056 | out[3] = state[3][0]; | |
1057 | out[4] = state[0][1]; | |
1058 | out[5] = state[1][1]; | |
1059 | out[6] = state[2][1]; | |
1060 | out[7] = state[3][1]; | |
1061 | out[8] = state[0][2]; | |
1062 | out[9] = state[1][2]; | |
1063 | out[10] = state[2][2]; | |
1064 | out[11] = state[3][2]; | |
1065 | out[12] = state[0][3]; | |
1066 | out[13] = state[1][3]; | |
1067 | out[14] = state[2][3]; | |
1068 | out[15] = state[3][3]; | |
1069 | } | |
1070 | ||
1071 | /******************* | |
1072 | ** AES DEBUGGING FUNCTIONS | |
1073 | *******************/ | |
1074 | /* | |
1075 | // This prints the "state" grid as a linear hex string. | |
1076 | void print_state(BYTE state[][4]) | |
1077 | { | |
1078 | int idx,idx2; | |
1079 | ||
1080 | for (idx=0; idx < 4; idx++) | |
1081 | for (idx2=0; idx2 < 4; idx2++) | |
1082 | printf("%02x",state[idx2][idx]); | |
1083 | printf("\n"); | |
1084 | } | |
1085 | ||
1086 | // This prints the key (4 consecutive ints) used for a given round as a linear hex string. | |
1087 | void print_rnd_key(WORD key[]) | |
1088 | { | |
1089 | int idx; | |
1090 | ||
1091 | for (idx=0; idx < 4; idx++) | |
1092 | printf("%08x",key[idx]); | |
1093 | printf("\n"); | |
1094 | } | |
1095 | */ |