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