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