Update CryptoPkg for new ciphers (HMAC, Block Cipher, etc) supports.
[mirror_edk2.git] / CryptoPkg / Library / BaseCryptLib / Cipher / CryptAes.c
1 /** @file\r
2   AES Wrapper Implementation over OpenSSL.\r
3 \r
4 Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>\r
5 This program and the accompanying materials\r
6 are licensed and made available under the terms and conditions of the BSD License\r
7 which accompanies this distribution.  The full text of the license may be found at\r
8 http://opensource.org/licenses/bsd-license.php\r
9 \r
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11 WITHOUT 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
24 UINTN\r
25 EFIAPI\r
26 AesGetContextSize (\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
57 BOOLEAN\r
58 EFIAPI\r
59 AesInit (\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
111 BOOLEAN\r
112 EFIAPI\r
113 AesEcbEncrypt (\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
166 BOOLEAN\r
167 EFIAPI\r
168 AesEcbDecrypt (\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
224 BOOLEAN\r
225 EFIAPI\r
226 AesCbcEncrypt (\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
281 BOOLEAN\r
282 EFIAPI\r
283 AesCbcDecrypt (\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