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