]> git.proxmox.com Git - mirror_edk2.git/blame - SecurityPkg/RandomNumberGenerator/RngDxe/AesCore.c
SecurityPkg: Clean up source files
[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
b3548d32
LG
3 Refer to FIPS PUB 197 ("Advanced Encryption Standard (AES)") for detailed algorithm\r
4 description of AES.\r
3aa8dc6c 5\r
b3548d32 6Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.<BR>\r
3aa8dc6c
LQ
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
b3548d32 32 0xc66363a5, 0xf87c7c84, 0xee777799, 0xf67b7b8d, 0xfff2f20d, 0xd66b6bbd,\r
3aa8dc6c 33 0xde6f6fb1, 0x91c5c554, 0x60303050, 0x02010103, 0xce6767a9, 0x562b2b7d,\r
b3548d32 34 0xe7fefe19, 0xb5d7d762, 0x4dababe6, 0xec76769a, 0x8fcaca45, 0x1f82829d,\r
3aa8dc6c 35 0x89c9c940, 0xfa7d7d87, 0xeffafa15, 0xb25959eb, 0x8e4747c9, 0xfbf0f00b,\r
b3548d32 36 0x41adadec, 0xb3d4d467, 0x5fa2a2fd, 0x45afafea, 0x239c9cbf, 0x53a4a4f7,\r
3aa8dc6c 37 0xe4727296, 0x9bc0c05b, 0x75b7b7c2, 0xe1fdfd1c, 0x3d9393ae, 0x4c26266a,\r
b3548d32 38 0x6c36365a, 0x7e3f3f41, 0xf5f7f702, 0x83cccc4f, 0x6834345c, 0x51a5a5f4,\r
3aa8dc6c 39 0xd1e5e534, 0xf9f1f108, 0xe2717193, 0xabd8d873, 0x62313153, 0x2a15153f,\r
b3548d32 40 0x0804040c, 0x95c7c752, 0x46232365, 0x9dc3c35e, 0x30181828, 0x379696a1,\r
3aa8dc6c 41 0x0a05050f, 0x2f9a9ab5, 0x0e070709, 0x24121236, 0x1b80809b, 0xdfe2e23d,\r
b3548d32 42 0xcdebeb26, 0x4e272769, 0x7fb2b2cd, 0xea75759f, 0x1209091b, 0x1d83839e,\r
3aa8dc6c 43 0x582c2c74, 0x341a1a2e, 0x361b1b2d, 0xdc6e6eb2, 0xb45a5aee, 0x5ba0a0fb,\r
b3548d32 44 0xa45252f6, 0x763b3b4d, 0xb7d6d661, 0x7db3b3ce, 0x5229297b, 0xdde3e33e,\r
3aa8dc6c 45 0x5e2f2f71, 0x13848497, 0xa65353f5, 0xb9d1d168, 0x00000000, 0xc1eded2c,\r
b3548d32 46 0x40202060, 0xe3fcfc1f, 0x79b1b1c8, 0xb65b5bed, 0xd46a6abe, 0x8dcbcb46,\r
3aa8dc6c 47 0x67bebed9, 0x7239394b, 0x944a4ade, 0x984c4cd4, 0xb05858e8, 0x85cfcf4a,\r
b3548d32 48 0xbbd0d06b, 0xc5efef2a, 0x4faaaae5, 0xedfbfb16, 0x864343c5, 0x9a4d4dd7,\r
3aa8dc6c 49 0x66333355, 0x11858594, 0x8a4545cf, 0xe9f9f910, 0x04020206, 0xfe7f7f81,\r
b3548d32 50 0xa05050f0, 0x783c3c44, 0x259f9fba, 0x4ba8a8e3, 0xa25151f3, 0x5da3a3fe,\r
3aa8dc6c 51 0x804040c0, 0x058f8f8a, 0x3f9292ad, 0x219d9dbc, 0x70383848, 0xf1f5f504,\r
b3548d32 52 0x63bcbcdf, 0x77b6b6c1, 0xafdada75, 0x42212163, 0x20101030, 0xe5ffff1a,\r
3aa8dc6c 53 0xfdf3f30e, 0xbfd2d26d, 0x81cdcd4c, 0x180c0c14, 0x26131335, 0xc3ecec2f,\r
b3548d32 54 0xbe5f5fe1, 0x359797a2, 0x884444cc, 0x2e171739, 0x93c4c457, 0x55a7a7f2,\r
3aa8dc6c 55 0xfc7e7e82, 0x7a3d3d47, 0xc86464ac, 0xba5d5de7, 0x3219192b, 0xe6737395,\r
b3548d32 56 0xc06060a0, 0x19818198, 0x9e4f4fd1, 0xa3dcdc7f, 0x44222266, 0x542a2a7e,\r
3aa8dc6c 57 0x3b9090ab, 0x0b888883, 0x8c4646ca, 0xc7eeee29, 0x6bb8b8d3, 0x2814143c,\r
b3548d32 58 0xa7dede79, 0xbc5e5ee2, 0x160b0b1d, 0xaddbdb76, 0xdbe0e03b, 0x64323256,\r
3aa8dc6c 59 0x743a3a4e, 0x140a0a1e, 0x924949db, 0x0c06060a, 0x4824246c, 0xb85c5ce4,\r
b3548d32 60 0x9fc2c25d, 0xbdd3d36e, 0x43acacef, 0xc46262a6, 0x399191a8, 0x319595a4,\r
3aa8dc6c 61 0xd3e4e437, 0xf279798b, 0xd5e7e732, 0x8bc8c843, 0x6e373759, 0xda6d6db7,\r
b3548d32 62 0x018d8d8c, 0xb1d5d564, 0x9c4e4ed2, 0x49a9a9e0, 0xd86c6cb4, 0xac5656fa,\r
3aa8dc6c 63 0xf3f4f407, 0xcfeaea25, 0xca6565af, 0xf47a7a8e, 0x47aeaee9, 0x10080818,\r
b3548d32 64 0x6fbabad5, 0xf0787888, 0x4a25256f, 0x5c2e2e72, 0x381c1c24, 0x57a6a6f1,\r
3aa8dc6c 65 0x73b4b4c7, 0x97c6c651, 0xcbe8e823, 0xa1dddd7c, 0xe874749c, 0x3e1f1f21,\r
b3548d32 66 0x964b4bdd, 0x61bdbddc, 0x0d8b8b86, 0x0f8a8a85, 0xe0707090, 0x7c3e3e42,\r
3aa8dc6c 67 0x71b5b5c4, 0xcc6666aa, 0x904848d8, 0x06030305, 0xf7f6f601, 0x1c0e0e12,\r
b3548d32 68 0xc26161a3, 0x6a35355f, 0xae5757f9, 0x69b9b9d0, 0x17868691, 0x99c1c158,\r
3aa8dc6c 69 0x3a1d1d27, 0x279e9eb9, 0xd9e1e138, 0xebf8f813, 0x2b9898b3, 0x22111133,\r
b3548d32 70 0xd26969bb, 0xa9d9d970, 0x078e8e89, 0x339494a7, 0x2d9b9bb6, 0x3c1e1e22,\r
3aa8dc6c 71 0x15878792, 0xc9e9e920, 0x87cece49, 0xaa5555ff, 0x50282878, 0xa5dfdf7a,\r
b3548d32 72 0x038c8c8f, 0x59a1a1f8, 0x09898980, 0x1a0d0d17, 0x65bfbfda, 0xd7e6e631,\r
3aa8dc6c
LQ
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
b3548d32 116 AES Key Expansion.\r
3aa8dc6c
LQ
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 163 }\r
b3548d32 164\r
3aa8dc6c
LQ
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
b3548d32 184 // Different routine for key expansion If Cipher Key is 256 bits,\r
3aa8dc6c 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 195 }\r
b3548d32 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 261 //\r
b3548d32
LG
262 // AES Cipher transformation rounds (Nr - 1 rounds), in which SubBytes(),\r
263 // ShiftRows() and MixColumns() operations were combined by a sequence of\r
3aa8dc6c
LQ
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
b3548d32 304}\r