Home | History | Annotate | Download | only in Cipher
      1 /** @file
      2   AES Wrapper Implementation over OpenSSL.
      3 
      4 Copyright (c) 2010 - 2012, Intel Corporation. All rights reserved.<BR>
      5 This program and the accompanying materials
      6 are licensed and made available under the terms and conditions of the BSD License
      7 which accompanies this distribution.  The full text of the license may be found at
      8 http://opensource.org/licenses/bsd-license.php
      9 
     10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     12 
     13 **/
     14 
     15 #include "InternalCryptLib.h"
     16 #include <openssl/aes.h>
     17 
     18 /**
     19   Retrieves the size, in bytes, of the context buffer required for AES operations.
     20 
     21   @return  The size, in bytes, of the context buffer required for AES operations.
     22 
     23 **/
     24 UINTN
     25 EFIAPI
     26 AesGetContextSize (
     27   VOID
     28   )
     29 {
     30   //
     31   // AES uses different key contexts for encryption and decryption, so here memory
     32   // for 2 copies of AES_KEY is allocated.
     33   //
     34   return (UINTN) (2 * sizeof (AES_KEY));
     35 }
     36 
     37 /**
     38   Initializes user-supplied memory as AES context for subsequent use.
     39 
     40   This function initializes user-supplied memory pointed by AesContext as AES context.
     41   In addition, it sets up all AES key materials for subsequent encryption and decryption
     42   operations.
     43   There are 3 options for key length, 128 bits, 192 bits, and 256 bits.
     44 
     45   If AesContext is NULL, then return FALSE.
     46   If Key is NULL, then return FALSE.
     47   If KeyLength is not valid, then return FALSE.
     48 
     49   @param[out]  AesContext  Pointer to AES context being initialized.
     50   @param[in]   Key         Pointer to the user-supplied AES key.
     51   @param[in]   KeyLength   Length of AES key in bits.
     52 
     53   @retval TRUE   AES context initialization succeeded.
     54   @retval FALSE  AES context initialization failed.
     55 
     56 **/
     57 BOOLEAN
     58 EFIAPI
     59 AesInit (
     60   OUT  VOID         *AesContext,
     61   IN   CONST UINT8  *Key,
     62   IN   UINTN        KeyLength
     63   )
     64 {
     65   AES_KEY  *AesKey;
     66 
     67   //
     68   // Check input parameters.
     69   //
     70   if (AesContext == NULL || Key == NULL || (KeyLength != 128 && KeyLength != 192 && KeyLength != 256)) {
     71     return FALSE;
     72   }
     73 
     74   //
     75   // Initialize AES encryption & decryption key schedule.
     76   //
     77   AesKey = (AES_KEY *) AesContext;
     78   if (AES_set_encrypt_key (Key, (UINT32) KeyLength, AesKey) != 0) {
     79     return FALSE;
     80   }
     81   if (AES_set_decrypt_key (Key, (UINT32) KeyLength, AesKey + 1) != 0) {
     82     return FALSE;
     83   }
     84   return TRUE;
     85 }
     86 
     87 /**
     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 **/
    111 BOOLEAN
    112 EFIAPI
    113 AesEcbEncrypt (
    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 **/
    168 BOOLEAN
    169 EFIAPI
    170 AesEcbDecrypt (
    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 **/
    228 BOOLEAN
    229 EFIAPI
    230 AesCbcEncrypt (
    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 **/
    290 BOOLEAN
    291 EFIAPI
    292 AesCbcDecrypt (
    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