]> git.proxmox.com Git - mirror_edk2.git/blame - SecurityPkg/RandomNumberGenerator/RngDxe/AesCore.c
Fix coding style problem in RngDxe driver.
[mirror_edk2.git] / SecurityPkg / RandomNumberGenerator / RngDxe / AesCore.c
CommitLineData
3aa8dc6c
LQ
1/** @file\r
2 Core Primitive Implementation of the Advanced Encryption Standard (AES) algorithm.\r
3 Refer to FIPS PUB 197 ("Advanced Encryption Standard (AES)") for detailed algorithm \r
4 description of AES. \r
5\r
6Copyright (c) 2013, Intel Corporation. All rights reserved.<BR>\r
7This program and the accompanying materials\r
8are licensed and made available under the terms and conditions of the BSD License\r
9which accompanies this distribution. The full text of the license may be found at\r
10http://opensource.org/licenses/bsd-license.php\r
11\r
12THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
13WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
14\r
15**/\r
16\r
17#include "AesCore.h"\r
18\r
19//\r
20// Number of columns (32-bit words) comprising the State.\r
21// AES_NB is a constant (value = 4) for NIST FIPS-197.\r
22//\r
23#define AES_NB 4\r
24\r
25//\r
b6023fb1
LQ
26// Pre-computed AES Forward Table: AesForwardTable[t] = AES_SBOX[t].[02, 01, 01, 03]\r
27// AES_SBOX (AES S-box) is defined in sec 5.1.1 of FIPS PUB 197.\r
3aa8dc6c
LQ
28// This is to speed up execution of the cipher by combining SubBytes and\r
29// ShiftRows with MixColumns steps and transforming them into table lookups.\r
30//\r
b6023fb1 31GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT32 AesForwardTable[] = {\r
3aa8dc6c
LQ
32 0xc66363a5, 0xf87c7c84, 0xee777799, 0xf67b7b8d, 0xfff2f20d, 0xd66b6bbd, \r
33 0xde6f6fb1, 0x91c5c554, 0x60303050, 0x02010103, 0xce6767a9, 0x562b2b7d,\r
34 0xe7fefe19, 0xb5d7d762, 0x4dababe6, 0xec76769a, 0x8fcaca45, 0x1f82829d, \r
35 0x89c9c940, 0xfa7d7d87, 0xeffafa15, 0xb25959eb, 0x8e4747c9, 0xfbf0f00b,\r
36 0x41adadec, 0xb3d4d467, 0x5fa2a2fd, 0x45afafea, 0x239c9cbf, 0x53a4a4f7, \r
37 0xe4727296, 0x9bc0c05b, 0x75b7b7c2, 0xe1fdfd1c, 0x3d9393ae, 0x4c26266a,\r
38 0x6c36365a, 0x7e3f3f41, 0xf5f7f702, 0x83cccc4f, 0x6834345c, 0x51a5a5f4, \r
39 0xd1e5e534, 0xf9f1f108, 0xe2717193, 0xabd8d873, 0x62313153, 0x2a15153f,\r
40 0x0804040c, 0x95c7c752, 0x46232365, 0x9dc3c35e, 0x30181828, 0x379696a1, \r
41 0x0a05050f, 0x2f9a9ab5, 0x0e070709, 0x24121236, 0x1b80809b, 0xdfe2e23d,\r
42 0xcdebeb26, 0x4e272769, 0x7fb2b2cd, 0xea75759f, 0x1209091b, 0x1d83839e, \r
43 0x582c2c74, 0x341a1a2e, 0x361b1b2d, 0xdc6e6eb2, 0xb45a5aee, 0x5ba0a0fb,\r
44 0xa45252f6, 0x763b3b4d, 0xb7d6d661, 0x7db3b3ce, 0x5229297b, 0xdde3e33e, \r
45 0x5e2f2f71, 0x13848497, 0xa65353f5, 0xb9d1d168, 0x00000000, 0xc1eded2c,\r
46 0x40202060, 0xe3fcfc1f, 0x79b1b1c8, 0xb65b5bed, 0xd46a6abe, 0x8dcbcb46, \r
47 0x67bebed9, 0x7239394b, 0x944a4ade, 0x984c4cd4, 0xb05858e8, 0x85cfcf4a,\r
48 0xbbd0d06b, 0xc5efef2a, 0x4faaaae5, 0xedfbfb16, 0x864343c5, 0x9a4d4dd7, \r
49 0x66333355, 0x11858594, 0x8a4545cf, 0xe9f9f910, 0x04020206, 0xfe7f7f81,\r
50 0xa05050f0, 0x783c3c44, 0x259f9fba, 0x4ba8a8e3, 0xa25151f3, 0x5da3a3fe, \r
51 0x804040c0, 0x058f8f8a, 0x3f9292ad, 0x219d9dbc, 0x70383848, 0xf1f5f504,\r
52 0x63bcbcdf, 0x77b6b6c1, 0xafdada75, 0x42212163, 0x20101030, 0xe5ffff1a, \r
53 0xfdf3f30e, 0xbfd2d26d, 0x81cdcd4c, 0x180c0c14, 0x26131335, 0xc3ecec2f,\r
54 0xbe5f5fe1, 0x359797a2, 0x884444cc, 0x2e171739, 0x93c4c457, 0x55a7a7f2, \r
55 0xfc7e7e82, 0x7a3d3d47, 0xc86464ac, 0xba5d5de7, 0x3219192b, 0xe6737395,\r
56 0xc06060a0, 0x19818198, 0x9e4f4fd1, 0xa3dcdc7f, 0x44222266, 0x542a2a7e, \r
57 0x3b9090ab, 0x0b888883, 0x8c4646ca, 0xc7eeee29, 0x6bb8b8d3, 0x2814143c,\r
58 0xa7dede79, 0xbc5e5ee2, 0x160b0b1d, 0xaddbdb76, 0xdbe0e03b, 0x64323256, \r
59 0x743a3a4e, 0x140a0a1e, 0x924949db, 0x0c06060a, 0x4824246c, 0xb85c5ce4,\r
60 0x9fc2c25d, 0xbdd3d36e, 0x43acacef, 0xc46262a6, 0x399191a8, 0x319595a4, \r
61 0xd3e4e437, 0xf279798b, 0xd5e7e732, 0x8bc8c843, 0x6e373759, 0xda6d6db7,\r
62 0x018d8d8c, 0xb1d5d564, 0x9c4e4ed2, 0x49a9a9e0, 0xd86c6cb4, 0xac5656fa, \r
63 0xf3f4f407, 0xcfeaea25, 0xca6565af, 0xf47a7a8e, 0x47aeaee9, 0x10080818,\r
64 0x6fbabad5, 0xf0787888, 0x4a25256f, 0x5c2e2e72, 0x381c1c24, 0x57a6a6f1, \r
65 0x73b4b4c7, 0x97c6c651, 0xcbe8e823, 0xa1dddd7c, 0xe874749c, 0x3e1f1f21,\r
66 0x964b4bdd, 0x61bdbddc, 0x0d8b8b86, 0x0f8a8a85, 0xe0707090, 0x7c3e3e42, \r
67 0x71b5b5c4, 0xcc6666aa, 0x904848d8, 0x06030305, 0xf7f6f601, 0x1c0e0e12,\r
68 0xc26161a3, 0x6a35355f, 0xae5757f9, 0x69b9b9d0, 0x17868691, 0x99c1c158, \r
69 0x3a1d1d27, 0x279e9eb9, 0xd9e1e138, 0xebf8f813, 0x2b9898b3, 0x22111133,\r
70 0xd26969bb, 0xa9d9d970, 0x078e8e89, 0x339494a7, 0x2d9b9bb6, 0x3c1e1e22, \r
71 0x15878792, 0xc9e9e920, 0x87cece49, 0xaa5555ff, 0x50282878, 0xa5dfdf7a,\r
72 0x038c8c8f, 0x59a1a1f8, 0x09898980, 0x1a0d0d17, 0x65bfbfda, 0xd7e6e631, \r
73 0x844242c6, 0xd06868b8, 0x824141c3, 0x299999b0, 0x5a2d2d77, 0x1e0f0f11,\r
74 0x7bb0b0cb, 0xa85454fc, 0x6dbbbbd6, 0x2c16163a\r
75};\r
76\r
3aa8dc6c
LQ
77//\r
78// Round constant word array used in AES key expansion.\r
79//\r
80GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT32 Rcon[] = {\r
81 0x01000000, 0x02000000, 0x04000000, 0x08000000, 0x10000000,\r
82 0x20000000, 0x40000000, 0x80000000, 0x1B000000, 0x36000000\r
83};\r
84\r
85//\r
86// Rotates x right n bits (circular right shift operation)\r
87//\r
88#define ROTATE_RIGHT32(x, n) (((x) >> (n)) | ((x) << (32-(n))))\r
89\r
90//\r
91// Loading & Storing 32-bit words in big-endian format: y[3..0] --> x; x --> y[3..0];\r
92//\r
93#define LOAD32H(x, y) { x = ((UINT32)((y)[0] & 0xFF) << 24) | ((UINT32)((y)[1] & 0xFF) << 16) | \\r
94 ((UINT32)((y)[2] & 0xFF) << 8) | ((UINT32)((y)[3] & 0xFF)); }\r
95#define STORE32H(x, y) { (y)[0] = (UINT8)(((x) >> 24) & 0xFF); (y)[1] = (UINT8)(((x) >> 16) & 0xFF); \\r
96 (y)[2] = (UINT8)(((x) >> 8) & 0xFF); (y)[3] = (UINT8)((x) & 0xFF); }\r
97\r
98//\r
b6023fb1 99// Wrap macros for AES forward tables lookups\r
3aa8dc6c 100//\r
b6023fb1
LQ
101#define AES_FT0(x) AesForwardTable[x]\r
102#define AES_FT1(x) ROTATE_RIGHT32(AesForwardTable[x], 8)\r
103#define AES_FT2(x) ROTATE_RIGHT32(AesForwardTable[x], 16)\r
104#define AES_FT3(x) ROTATE_RIGHT32(AesForwardTable[x], 24)\r
3aa8dc6c
LQ
105\r
106///\r
107/// AES Key Schedule which is expanded from symmetric key [Size 60 = 4 * ((Max AES Round, 14) + 1)].\r
108///\r
109typedef struct {\r
110 UINTN Nk; // Number of Cipher Key (in 32-bit words);\r
b6023fb1
LQ
111 UINT32 EncKey[60]; // Expanded AES encryption key\r
112 UINT32 DecKey[60]; // Expanded AES decryption key (Not used here)\r
3aa8dc6c
LQ
113} AES_KEY;\r
114\r
115/**\r
116 AES Key Expansion. \r
117 This function expands the cipher key into encryption schedule.\r
118\r
119 @param[in] Key AES symmetric key buffer.\r
120 @param[in] KeyLenInBits Key length in bits (128, 192, or 256).\r
121 @param[out] AesKey Expanded AES Key schedule for encryption.\r
122\r
123 @retval EFI_SUCCESS AES key expansion succeeded.\r
124 @retval EFI_INVALID_PARAMETER Unsupported key length.\r
125\r
126**/\r
127EFI_STATUS\r
128EFIAPI\r
129AesExpandKey (\r
130 IN UINT8 *Key,\r
131 IN UINTN KeyLenInBits,\r
132 OUT AES_KEY *AesKey\r
133 )\r
134{\r
b6023fb1
LQ
135 UINTN Nk;\r
136 UINTN Nr;\r
137 UINTN Nw;\r
138 UINTN Index1;\r
139 UINTN Index2;\r
140 UINTN Index3;\r
3aa8dc6c
LQ
141 UINT32 *Ek;\r
142 UINT32 Temp;\r
143\r
144 //\r
145 // Nk - Number of 32-bit words comprising the cipher key. (Nk = 4, 6 or 8)\r
146 // Nr - Number of rounds. (Nr = 10, 12, or 14), which is dependent on the key size.\r
147 //\r
148 Nk = KeyLenInBits >> 5;\r
149 if (Nk != 4 && Nk != 6 && Nk != 8) {\r
150 return EFI_INVALID_PARAMETER;\r
151 }\r
152 Nr = Nk + 6;\r
b6023fb1 153 Nw = AES_NB * (Nr + 1); // Key Expansion generates a total of Nb * (Nr + 1) words\r
3aa8dc6c
LQ
154 AesKey->Nk = Nk;\r
155\r
156 //\r
157 // Load initial symmetric AES key;\r
158 // Note that AES was designed on big-endian systems.\r
159 //\r
b6023fb1
LQ
160 Ek = AesKey->EncKey;\r
161 for (Index1 = Index2 = 0; Index1 < Nk; Index1++, Index2 += 4) {\r
162 LOAD32H (Ek[Index1], Key + Index2);\r
3aa8dc6c
LQ
163 }\r
164 \r
165 //\r
166 // Initialize the encryption key scheduler\r
167 //\r
b6023fb1
LQ
168 for (Index2 = Nk, Index3 = 0; Index2 < Nw; Index2 += Nk, Index3++) {\r
169 Temp = Ek[Index2 - 1];\r
170 Ek[Index2] = Ek[Index2 - Nk] ^ (AES_FT2((Temp >> 16) & 0xFF) & 0xFF000000) ^\r
171 (AES_FT3((Temp >> 8) & 0xFF) & 0x00FF0000) ^\r
172 (AES_FT0((Temp) & 0xFF) & 0x0000FF00) ^\r
173 (AES_FT1((Temp >> 24) & 0xFF) & 0x000000FF) ^\r
174 Rcon[Index3];\r
3aa8dc6c
LQ
175 if (Nk <= 6) {\r
176 //\r
177 // If AES Cipher Key is 128 or 192 bits\r
178 //\r
b6023fb1
LQ
179 for (Index1 = 1; Index1 < Nk && (Index1 + Index2) < Nw; Index1++) {\r
180 Ek [Index1 + Index2] = Ek [Index1 + Index2 - Nk] ^ Ek[Index1 + Index2 - 1];\r
3aa8dc6c
LQ
181 }\r
182 } else {\r
183 //\r
184 // Different routine for key expansion If Cipher Key is 256 bits, \r
185 //\r
b6023fb1
LQ
186 for (Index1 = 1; Index1 < 4 && (Index1 + Index2) < Nw; Index1++) {\r
187 Ek [Index1 + Index2] = Ek[Index1 + Index2 - Nk] ^ Ek[Index1 + Index2 - 1];\r
3aa8dc6c 188 }\r
b6023fb1
LQ
189 if (Index2 + 4 < Nw) {\r
190 Temp = Ek[Index2 + 3];\r
191 Ek[Index2 + 4] = Ek[Index2 + 4 - Nk] ^ (AES_FT2((Temp >> 24) & 0xFF) & 0xFF000000) ^\r
192 (AES_FT3((Temp >> 16) & 0xFF) & 0x00FF0000) ^\r
193 (AES_FT0((Temp >> 8) & 0xFF) & 0x0000FF00) ^\r
194 (AES_FT1((Temp) & 0xFF) & 0x000000FF);\r
3aa8dc6c
LQ
195 }\r
196 \r
b6023fb1
LQ
197 for (Index1 = 5; Index1 < Nk && (Index1 + Index2) < Nw; Index1++) {\r
198 Ek[Index1 + Index2] = Ek[Index1 + Index2 - Nk] ^ Ek[Index1 + Index2 - 1];\r
3aa8dc6c
LQ
199 }\r
200 }\r
201 }\r
202\r
203 return EFI_SUCCESS;\r
204}\r
205\r
206/**\r
207 Encrypts one single block data (128 bits) with AES algorithm.\r
208\r
209 @param[in] Key AES symmetric key buffer.\r
210 @param[in] InData One block of input plaintext to be encrypted.\r
211 @param[out] OutData Encrypted output ciphertext.\r
212\r
213 @retval EFI_SUCCESS AES Block Encryption succeeded.\r
214 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.\r
215\r
216**/\r
217EFI_STATUS\r
218EFIAPI\r
219AesEncrypt (\r
220 IN UINT8 *Key,\r
221 IN UINT8 *InData,\r
222 OUT UINT8 *OutData\r
223 )\r
224{\r
225 AES_KEY AesKey;\r
226 UINTN Nr;\r
b6023fb1
LQ
227 UINT32 *Ek;\r
228 UINT32 State[4];\r
229 UINT32 TempState[4];\r
230 UINT32 *StateX;\r
231 UINT32 *StateY;\r
232 UINT32 *Temp;\r
233 UINTN Index;\r
234 UINTN NbIndex;\r
235 UINTN Round;\r
3aa8dc6c
LQ
236\r
237 if ((Key == NULL) || (InData == NULL) || (OutData == NULL)) {\r
238 return EFI_INVALID_PARAMETER;\r
239 }\r
240\r
241 //\r
242 // Expands AES Key for encryption.\r
243 //\r
244 AesExpandKey (Key, 128, &AesKey);\r
245\r
246 Nr = AesKey.Nk + 6;\r
b6023fb1 247 Ek = AesKey.EncKey;\r
3aa8dc6c
LQ
248\r
249 //\r
250 // Initialize the cipher State array with the initial round key\r
251 //\r
252 for (Index = 0; Index < AES_NB; Index++) {\r
b6023fb1
LQ
253 LOAD32H (State[Index], InData + 4 * Index);\r
254 State[Index] ^= Ek[Index];\r
3aa8dc6c
LQ
255 }\r
256\r
b6023fb1
LQ
257 NbIndex = AES_NB;\r
258 StateX = State;\r
259 StateY = TempState;\r
260\r
3aa8dc6c
LQ
261 //\r
262 // AES Cipher transformation rounds (Nr - 1 rounds), in which SubBytes(), \r
263 // ShiftRows() and MixColumns() operations were combined by a sequence of \r
264 // table lookups to speed up the execution.\r
265 //\r
266 for (Round = 1; Round < Nr; Round++) {\r
b6023fb1
LQ
267 StateY[0] = AES_FT0 ((StateX[0] >> 24) ) ^ AES_FT1 ((StateX[1] >> 16) & 0xFF) ^\r
268 AES_FT2 ((StateX[2] >> 8) & 0xFF) ^ AES_FT3 ((StateX[3] ) & 0xFF) ^ Ek[NbIndex];\r
269 StateY[1] = AES_FT0 ((StateX[1] >> 24) ) ^ AES_FT1 ((StateX[2] >> 16) & 0xFF) ^\r
270 AES_FT2 ((StateX[3] >> 8) & 0xFF) ^ AES_FT3 ((StateX[0] ) & 0xFF) ^ Ek[NbIndex + 1];\r
271 StateY[2] = AES_FT0 ((StateX[2] >> 24) ) ^ AES_FT1 ((StateX[3] >> 16) & 0xFF) ^\r
272 AES_FT2 ((StateX[0] >> 8) & 0xFF) ^ AES_FT3 ((StateX[1] ) & 0xFF) ^ Ek[NbIndex + 2];\r
273 StateY[3] = AES_FT0 ((StateX[3] >> 24) ) ^ AES_FT1 ((StateX[0] >> 16) & 0xFF) ^\r
274 AES_FT2 ((StateX[1] >> 8) & 0xFF) ^ AES_FT3 ((StateX[2] ) & 0xFF) ^ Ek[NbIndex + 3];\r
275\r
276 NbIndex += 4;\r
277 Temp = StateX; StateX = StateY; StateY = Temp;\r
3aa8dc6c
LQ
278 }\r
279\r
280 //\r
281 // Apply the final round, which does not include MixColumns() transformation\r
282 //\r
b6023fb1
LQ
283 StateY[0] = (AES_FT2 ((StateX[0] >> 24) ) & 0xFF000000) ^ (AES_FT3 ((StateX[1] >> 16) & 0xFF) & 0x00FF0000) ^\r
284 (AES_FT0 ((StateX[2] >> 8) & 0xFF) & 0x0000FF00) ^ (AES_FT1 ((StateX[3] ) & 0xFF) & 0x000000FF) ^\r
285 Ek[NbIndex];\r
286 StateY[1] = (AES_FT2 ((StateX[1] >> 24) ) & 0xFF000000) ^ (AES_FT3 ((StateX[2] >> 16) & 0xFF) & 0x00FF0000) ^\r
287 (AES_FT0 ((StateX[3] >> 8) & 0xFF) & 0x0000FF00) ^ (AES_FT1 ((StateX[0] ) & 0xFF) & 0x000000FF) ^\r
288 Ek[NbIndex + 1];\r
289 StateY[2] = (AES_FT2 ((StateX[2] >> 24) ) & 0xFF000000) ^ (AES_FT3 ((StateX[3] >> 16) & 0xFF) & 0x00FF0000) ^\r
290 (AES_FT0 ((StateX[0] >> 8) & 0xFF) & 0x0000FF00) ^ (AES_FT1 ((StateX[1] ) & 0xFF) & 0x000000FF) ^\r
291 Ek[NbIndex + 2];\r
292 StateY[3] = (AES_FT2 ((StateX[3] >> 24) ) & 0xFF000000) ^ (AES_FT3 ((StateX[0] >> 16) & 0xFF) & 0x00FF0000) ^\r
293 (AES_FT0 ((StateX[1] >> 8) & 0xFF) & 0x0000FF00) ^ (AES_FT1 ((StateX[2] ) & 0xFF) & 0x000000FF) ^\r
294 Ek[NbIndex + 3];\r
3aa8dc6c
LQ
295\r
296 //\r
297 // Output the transformed result;\r
298 //\r
299 for (Index = 0; Index < AES_NB; Index++) {\r
b6023fb1 300 STORE32H (StateY[Index], OutData + 4 * Index);\r
3aa8dc6c
LQ
301 }\r
302\r
303 return EFI_SUCCESS;\r
304}