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