]> git.proxmox.com Git - mirror_edk2.git/blame - CryptoPkg/Library/BaseCryptLib/Cipher/CryptAes.c
Update CryptoPkg for new ciphers (HMAC, Block Cipher, etc) supports.
[mirror_edk2.git] / CryptoPkg / Library / BaseCryptLib / Cipher / CryptAes.c
CommitLineData
a8c44645 1/** @file\r
2 AES Wrapper Implementation over OpenSSL.\r
3\r
4Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>\r
5This program and the accompanying materials\r
6are licensed and made available under the terms and conditions of the BSD License\r
7which accompanies this distribution. The full text of the license may be found at\r
8http://opensource.org/licenses/bsd-license.php\r
9\r
10THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12\r
13**/\r
14\r
15#include "InternalCryptLib.h"\r
16#include <openssl/aes.h>\r
17\r
18/**\r
19 Retrieves the size, in bytes, of the context buffer required for AES operations.\r
20\r
21 @return The size, in bytes, of the context buffer required for AES operations.\r
22\r
23**/\r
24UINTN\r
25EFIAPI\r
26AesGetContextSize (\r
27 VOID\r
28 )\r
29{\r
30 //\r
31 // AES uses different key contexts for encryption and decryption, so here memory\r
32 // for 2 copies of AES_KEY is allocated.\r
33 //\r
34 return (UINTN) (2 * sizeof (AES_KEY));\r
35}\r
36\r
37/**\r
38 Initializes user-supplied memory as AES context for subsequent use.\r
39\r
40 This function initializes user-supplied memory pointed by AesContext as AES context.\r
41 In addtion, it sets up all AES key materials for subsequent encryption and decryption\r
42 operations.\r
43 There are 3 options for key length, 128 bits, 192 bits, and 256 bits.\r
44\r
45 If AesContext is NULL, then ASSERT().\r
46 If Key is NULL, then ASSERT().\r
47 If KeyLength is not valid, then ASSERT().\r
48\r
49 @param[out] AesContext Pointer to AES context being initialized.\r
50 @param[in] Key Pointer to the user-supplied AES key.\r
51 @param[in] KeyLength Length of AES key in bits.\r
52\r
53 @retval TRUE AES context initialization succeeded.\r
54 @retval FALSE AES context initialization failed.\r
55\r
56**/\r
57BOOLEAN\r
58EFIAPI\r
59AesInit (\r
60 OUT VOID *AesContext,\r
61 IN CONST UINT8 *Key,\r
62 IN UINTN KeyLength\r
63 )\r
64{\r
65 AES_KEY *AesKey;\r
66\r
67 ASSERT (AesContext != NULL);\r
68 //\r
69 // AES Key Checking\r
70 //\r
71 ASSERT (Key != NULL);\r
72 ASSERT ((KeyLength == 128) || (KeyLength == 192) || (KeyLength == 256));\r
73\r
74 //\r
75 // Initialize AES encryption & decryption key schedule.\r
76 //\r
77 AesKey = (AES_KEY *) AesContext;\r
78 if (AES_set_encrypt_key (Key, (UINT32) KeyLength, AesKey) != 0) {\r
79 return FALSE;\r
80 }\r
81 if (AES_set_decrypt_key (Key, (UINT32) KeyLength, AesKey + 1) != 0) {\r
82 return FALSE;\r
83 }\r
84 return TRUE;\r
85}\r
86\r
87/**\r
88 Performs AES encryption on a data buffer of the specified size in ECB mode.\r
89\r
90 This function performs AES encryption on data buffer pointed by Input, of specified\r
91 size of InputSize, in ECB mode.\r
92 InputSize must be multiple of block size (16 bytes). This function does not perform\r
93 padding. Caller must perform padding, if necessary, to ensure valid input data size.\r
94 AesContext should be already correctly initialized by AesInit(). Behavior with\r
95 invalid AES context is undefined.\r
96\r
97 If AesContext is NULL, then ASSERT().\r
98 If Input is NULL, then ASSERT().\r
99 If InputSize is not multiple of block size (16 bytes), then ASSERT().\r
100 If Output is NULL, then ASSERT().\r
101\r
102 @param[in] AesContext Pointer to the AES context.\r
103 @param[in] Input Pointer to the buffer containing the data to be encrypted.\r
104 @param[in] InputSize Size of the Input buffer in bytes.\r
105 @param[out] Output Pointer to a buffer that receives the AES encryption output.\r
106\r
107 @retval TRUE AES encryption succeeded.\r
108 @retval FALSE AES encryption failed.\r
109\r
110**/\r
111BOOLEAN\r
112EFIAPI\r
113AesEcbEncrypt (\r
114 IN VOID *AesContext,\r
115 IN CONST UINT8 *Input,\r
116 IN UINTN InputSize,\r
117 OUT UINT8 *Output\r
118 )\r
119{\r
120 AES_KEY *AesKey;\r
121 \r
122 ASSERT (AesContext != NULL);\r
123 ASSERT (Input != NULL);\r
124 ASSERT ((InputSize % AES_BLOCK_SIZE) == 0);\r
125 ASSERT (Output != NULL);\r
126\r
127 AesKey = (AES_KEY *) AesContext;\r
128\r
129 //\r
130 // Perform AES data encryption with ECB mode (block-by-block)\r
131 //\r
132 while (InputSize > 0) {\r
133 AES_ecb_encrypt (Input, Output, AesKey, AES_ENCRYPT);\r
134 Input += AES_BLOCK_SIZE;\r
135 Output += AES_BLOCK_SIZE;\r
136 InputSize -= AES_BLOCK_SIZE;\r
137 }\r
138\r
139 return TRUE;\r
140}\r
141\r
142/**\r
143 Performs AES decryption on a data buffer of the specified size in ECB mode.\r
144\r
145 This function performs AES decryption on data buffer pointed by Input, of specified\r
146 size of InputSize, in ECB mode.\r
147 InputSize must be multiple of block size (16 bytes). This function does not perform\r
148 padding. Caller must perform padding, if necessary, to ensure valid input data size.\r
149 AesContext should be already correctly initialized by AesInit(). Behavior with\r
150 invalid AES context is undefined.\r
151\r
152 If AesContext is NULL, then ASSERT().\r
153 If Input is NULL, then ASSERT().\r
154 If InputSize is not multiple of block size (16 bytes), then ASSERT().\r
155 If Output is NULL, then ASSERT().\r
156\r
157 @param[in] AesContext Pointer to the AES context.\r
158 @param[in] Input Pointer to the buffer containing the data to be decrypted.\r
159 @param[in] InputSize Size of the Input buffer in bytes.\r
160 @param[out] Output Pointer to a buffer that receives the AES decryption output.\r
161\r
162 @retval TRUE AES decryption succeeded.\r
163 @retval FALSE AES decryption failed.\r
164\r
165**/\r
166BOOLEAN\r
167EFIAPI\r
168AesEcbDecrypt (\r
169 IN VOID *AesContext,\r
170 IN CONST UINT8 *Input,\r
171 IN UINTN InputSize,\r
172 OUT UINT8 *Output\r
173 )\r
174{\r
175 AES_KEY *AesKey;\r
176 \r
177 ASSERT (AesContext != NULL);\r
178 ASSERT (Input != NULL);\r
179 ASSERT ((InputSize % AES_BLOCK_SIZE) == 0);\r
180 ASSERT (Output != NULL);\r
181\r
182 AesKey = (AES_KEY *) AesContext;\r
183\r
184 //\r
185 // Perform AES data decryption with ECB mode (block-by-block)\r
186 //\r
187 while (InputSize > 0) {\r
188 AES_ecb_encrypt (Input, Output, AesKey + 1, AES_DECRYPT);\r
189 Input += AES_BLOCK_SIZE;\r
190 Output += AES_BLOCK_SIZE;\r
191 InputSize -= AES_BLOCK_SIZE;\r
192 }\r
193\r
194 return TRUE;\r
195}\r
196\r
197/**\r
198 Performs AES encryption on a data buffer of the specified size in CBC mode.\r
199\r
200 This function performs AES encryption on data buffer pointed by Input, of specified\r
201 size of InputSize, in CBC mode.\r
202 InputSize must be multiple of block size (16 bytes). This function does not perform\r
203 padding. Caller must perform padding, if necessary, to ensure valid input data size.\r
204 Initialization vector should be one block size (16 bytes).\r
205 AesContext should be already correctly initialized by AesInit(). Behavior with\r
206 invalid AES context is undefined.\r
207\r
208 If AesContext is NULL, then ASSERT().\r
209 If Input is NULL, then ASSERT().\r
210 If InputSize is not multiple of block size (16 bytes), then ASSERT().\r
211 If Ivec is NULL, then ASSERT().\r
212 If Output is NULL, then ASSERT().\r
213\r
214 @param[in] AesContext Pointer to the AES context.\r
215 @param[in] Input Pointer to the buffer containing the data to be encrypted.\r
216 @param[in] InputSize Size of the Input buffer in bytes.\r
217 @param[in] Ivec Pointer to initialization vector.\r
218 @param[out] Output Pointer to a buffer that receives the AES encryption output.\r
219\r
220 @retval TRUE AES encryption succeeded.\r
221 @retval FALSE AES encryption failed.\r
222\r
223**/\r
224BOOLEAN\r
225EFIAPI\r
226AesCbcEncrypt (\r
227 IN VOID *AesContext,\r
228 IN CONST UINT8 *Input,\r
229 IN UINTN InputSize,\r
230 IN CONST UINT8 *Ivec,\r
231 OUT UINT8 *Output\r
232 )\r
233{\r
234 AES_KEY *AesKey;\r
235 UINT8 IvecBuffer[AES_BLOCK_SIZE];\r
236\r
237 ASSERT (AesContext != NULL);\r
238 ASSERT (Input != NULL);\r
239 ASSERT ((InputSize % AES_BLOCK_SIZE) == 0);\r
240 ASSERT (Ivec != NULL);\r
241 ASSERT (Output != NULL);\r
242\r
243 AesKey = (AES_KEY *) AesContext;\r
244 CopyMem (IvecBuffer, Ivec, AES_BLOCK_SIZE);\r
245\r
246 //\r
247 // Perform AES data encryption with CBC mode\r
248 //\r
249 AES_cbc_encrypt (Input, Output, (UINT32) InputSize, AesKey, IvecBuffer, AES_ENCRYPT);\r
250\r
251 return TRUE;\r
252}\r
253\r
254/**\r
255 Performs AES decryption on a data buffer of the specified size in CBC mode.\r
256\r
257 This function performs AES decryption on data buffer pointed by Input, of specified\r
258 size of InputSize, in CBC mode.\r
259 InputSize must be multiple of block size (16 bytes). This function does not perform\r
260 padding. Caller must perform padding, if necessary, to ensure valid input data size.\r
261 Initialization vector should be one block size (16 bytes).\r
262 AesContext should be already correctly initialized by AesInit(). Behavior with\r
263 invalid AES context is undefined.\r
264\r
265 If AesContext is NULL, then ASSERT().\r
266 If Input is NULL, then ASSERT().\r
267 If InputSize is not multiple of block size (16 bytes), then ASSERT().\r
268 If Ivec is NULL, then ASSERT().\r
269 If Output is NULL, then ASSERT().\r
270\r
271 @param[in] AesContext Pointer to the AES context.\r
272 @param[in] Input Pointer to the buffer containing the data to be encrypted.\r
273 @param[in] InputSize Size of the Input buffer in bytes.\r
274 @param[in] Ivec Pointer to initialization vector.\r
275 @param[out] Output Pointer to a buffer that receives the AES encryption output.\r
276\r
277 @retval TRUE AES decryption succeeded.\r
278 @retval FALSE AES decryption failed.\r
279\r
280**/\r
281BOOLEAN\r
282EFIAPI\r
283AesCbcDecrypt (\r
284 IN VOID *AesContext,\r
285 IN CONST UINT8 *Input,\r
286 IN UINTN InputSize,\r
287 IN CONST UINT8 *Ivec,\r
288 OUT UINT8 *Output\r
289 )\r
290{\r
291 AES_KEY *AesKey;\r
292 UINT8 IvecBuffer[AES_BLOCK_SIZE];\r
293 \r
294 ASSERT (AesContext != NULL);\r
295 ASSERT (Input != NULL);\r
296 ASSERT ((InputSize % AES_BLOCK_SIZE) == 0);\r
297 ASSERT (Ivec != NULL);\r
298 ASSERT (Output != NULL);\r
299\r
300 AesKey = (AES_KEY *) AesContext;\r
301 CopyMem (IvecBuffer, Ivec, AES_BLOCK_SIZE);\r
302\r
303 //\r
304 // Perform AES data decryption with CBC mode\r
305 //\r
306 AES_cbc_encrypt (Input, Output, (UINT32) InputSize, AesKey + 1, IvecBuffer, AES_DECRYPT);\r
307\r
308 return TRUE;\r
309}\r