Home | History | Annotate | Download | only in Cipher
      1 /** @file
      2   TDES Wrapper Implementation over OpenSSL.
      3 
      4 Copyright (c) 2010 - 2015, 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/des.h>
     17 
     18 /**
     19   Retrieves the size, in bytes, of the context buffer required for TDES operations.
     20 
     21   @return  The size, in bytes, of the context buffer required for TDES operations.
     22 
     23 **/
     24 UINTN
     25 EFIAPI
     26 TdesGetContextSize (
     27   VOID
     28   )
     29 {
     30   //
     31   // Memory for 3 copies of DES_key_schedule is allocated, for K1, K2 and K3 each.
     32   //
     33   return (UINTN) (3 * sizeof (DES_key_schedule));
     34 }
     35 
     36 /**
     37   Initializes user-supplied memory as TDES context for subsequent use.
     38 
     39   This function initializes user-supplied memory pointed by TdesContext as TDES context.
     40   In addition, it sets up all TDES key materials for subsequent encryption and decryption
     41   operations.
     42   There are 3 key options as follows:
     43   KeyLength = 64,  Keying option 1: K1 == K2 == K3 (Backward compatibility with DES)
     44   KeyLength = 128, Keying option 2: K1 != K2 and K3 = K1 (Less Security)
     45   KeyLength = 192  Keying option 3: K1 != K2 != K3 (Strongest)
     46 
     47   If TdesContext is NULL, then return FALSE.
     48   If Key is NULL, then return FALSE.
     49   If KeyLength is not valid, then return FALSE.
     50 
     51   @param[out]  TdesContext  Pointer to TDES context being initialized.
     52   @param[in]   Key          Pointer to the user-supplied TDES key.
     53   @param[in]   KeyLength    Length of TDES key in bits.
     54 
     55   @retval TRUE   TDES context initialization succeeded.
     56   @retval FALSE  TDES context initialization failed.
     57 
     58 **/
     59 BOOLEAN
     60 EFIAPI
     61 TdesInit (
     62   OUT  VOID         *TdesContext,
     63   IN   CONST UINT8  *Key,
     64   IN   UINTN        KeyLength
     65   )
     66 {
     67   DES_key_schedule  *KeySchedule;
     68 
     69   //
     70   // Check input parameters.
     71   //
     72   if (TdesContext == NULL || Key == NULL || (KeyLength != 64 && KeyLength != 128 && KeyLength != 192)) {
     73     return FALSE;
     74   }
     75 
     76   KeySchedule = (DES_key_schedule *) TdesContext;
     77 
     78   //
     79   // If input Key is a weak key, return error.
     80   //
     81   if (DES_is_weak_key ((const_DES_cblock *) Key) == 1) {
     82     return FALSE;
     83   }
     84 
     85   DES_set_key_unchecked ((const_DES_cblock *) Key, KeySchedule);
     86 
     87   if (KeyLength == 64) {
     88     CopyMem (KeySchedule + 1, KeySchedule, sizeof (DES_key_schedule));
     89     CopyMem (KeySchedule + 2, KeySchedule, sizeof (DES_key_schedule));
     90     return TRUE;
     91   }
     92 
     93   if (DES_is_weak_key ((const_DES_cblock *) (Key + 8)) == 1) {
     94     return FALSE;
     95   }
     96 
     97   DES_set_key_unchecked ((const_DES_cblock *) (Key + 8), KeySchedule + 1);
     98 
     99   if (KeyLength == 128) {
    100     CopyMem (KeySchedule + 2, KeySchedule, sizeof (DES_key_schedule));
    101     return TRUE;
    102   }
    103 
    104   if (DES_is_weak_key ((const_DES_cblock *) (Key + 16)) == 1) {
    105     return FALSE;
    106   }
    107 
    108   DES_set_key_unchecked ((const_DES_cblock *) (Key + 16), KeySchedule + 2);
    109 
    110   return TRUE;
    111 }
    112 
    113 /**
    114   Performs TDES encryption on a data buffer of the specified size in ECB mode.
    115 
    116   This function performs TDES encryption on data buffer pointed by Input, of specified
    117   size of InputSize, in ECB mode.
    118   InputSize must be multiple of block size (8 bytes). This function does not perform
    119   padding. Caller must perform padding, if necessary, to ensure valid input data size.
    120   TdesContext should be already correctly initialized by TdesInit(). Behavior with
    121   invalid TDES context is undefined.
    122 
    123   If TdesContext is NULL, then return FALSE.
    124   If Input is NULL, then return FALSE.
    125   If InputSize is not multiple of block size (8 bytes), then return FALSE.
    126   If Output is NULL, then return FALSE.
    127 
    128   @param[in]   TdesContext  Pointer to the TDES context.
    129   @param[in]   Input        Pointer to the buffer containing the data to be encrypted.
    130   @param[in]   InputSize    Size of the Input buffer in bytes.
    131   @param[out]  Output       Pointer to a buffer that receives the TDES encryption output.
    132 
    133   @retval TRUE   TDES encryption succeeded.
    134   @retval FALSE  TDES encryption failed.
    135 
    136 **/
    137 BOOLEAN
    138 EFIAPI
    139 TdesEcbEncrypt (
    140   IN   VOID         *TdesContext,
    141   IN   CONST UINT8  *Input,
    142   IN   UINTN        InputSize,
    143   OUT  UINT8        *Output
    144   )
    145 {
    146   DES_key_schedule  *KeySchedule;
    147 
    148   //
    149   // Check input parameters.
    150   //
    151   if (TdesContext == NULL || Input == NULL || (InputSize % TDES_BLOCK_SIZE) != 0 || Output == NULL) {
    152     return FALSE;
    153   }
    154 
    155   KeySchedule = (DES_key_schedule *) TdesContext;
    156 
    157   while (InputSize > 0) {
    158     DES_ecb3_encrypt (
    159       (const_DES_cblock *) Input,
    160       (DES_cblock *) Output,
    161       KeySchedule,
    162       KeySchedule + 1,
    163       KeySchedule + 2,
    164       DES_ENCRYPT
    165       );
    166     Input     += TDES_BLOCK_SIZE;
    167     Output    += TDES_BLOCK_SIZE;
    168     InputSize -= TDES_BLOCK_SIZE;
    169   }
    170 
    171   return TRUE;
    172 }
    173 
    174 /**
    175   Performs TDES decryption on a data buffer of the specified size in ECB mode.
    176 
    177   This function performs TDES decryption on data buffer pointed by Input, of specified
    178   size of InputSize, in ECB mode.
    179   InputSize must be multiple of block size (8 bytes). This function does not perform
    180   padding. Caller must perform padding, if necessary, to ensure valid input data size.
    181   TdesContext should be already correctly initialized by TdesInit(). Behavior with
    182   invalid TDES context is undefined.
    183 
    184   If TdesContext is NULL, then return FALSE.
    185   If Input is NULL, then return FALSE.
    186   If InputSize is not multiple of block size (8 bytes), then return FALSE.
    187   If Output is NULL, then return FALSE.
    188 
    189   @param[in]   TdesContext  Pointer to the TDES context.
    190   @param[in]   Input        Pointer to the buffer containing the data to be decrypted.
    191   @param[in]   InputSize    Size of the Input buffer in bytes.
    192   @param[out]  Output       Pointer to a buffer that receives the TDES decryption output.
    193 
    194   @retval TRUE   TDES decryption succeeded.
    195   @retval FALSE  TDES decryption failed.
    196 
    197 **/
    198 BOOLEAN
    199 EFIAPI
    200 TdesEcbDecrypt (
    201   IN   VOID         *TdesContext,
    202   IN   CONST UINT8  *Input,
    203   IN   UINTN        InputSize,
    204   OUT  UINT8        *Output
    205   )
    206 {
    207   DES_key_schedule  *KeySchedule;
    208 
    209   //
    210   // Check input parameters.
    211   //
    212   if (TdesContext == NULL || Input == NULL || (InputSize % TDES_BLOCK_SIZE) != 0 || Output == NULL) {
    213     return FALSE;
    214   }
    215 
    216   KeySchedule = (DES_key_schedule *) TdesContext;
    217 
    218   while (InputSize > 0) {
    219     DES_ecb3_encrypt (
    220       (const_DES_cblock *) Input,
    221       (DES_cblock *) Output,
    222       KeySchedule,
    223       KeySchedule + 1,
    224       KeySchedule + 2,
    225       DES_DECRYPT
    226       );
    227     Input     += TDES_BLOCK_SIZE;
    228     Output    += TDES_BLOCK_SIZE;
    229     InputSize -= TDES_BLOCK_SIZE;
    230   }
    231 
    232   return TRUE;
    233 }
    234 
    235 /**
    236   Performs TDES encryption on a data buffer of the specified size in CBC mode.
    237 
    238   This function performs TDES encryption on data buffer pointed by Input, of specified
    239   size of InputSize, in CBC mode.
    240   InputSize must be multiple of block size (8 bytes). This function does not perform
    241   padding. Caller must perform padding, if necessary, to ensure valid input data size.
    242   Initialization vector should be one block size (8 bytes).
    243   TdesContext should be already correctly initialized by TdesInit(). Behavior with
    244   invalid TDES context is undefined.
    245 
    246   If TdesContext is NULL, then return FALSE.
    247   If Input is NULL, then return FALSE.
    248   If InputSize is not multiple of block size (8 bytes), then return FALSE.
    249   If Ivec is NULL, then return FALSE.
    250   If Output is NULL, then return FALSE.
    251 
    252   @param[in]   TdesContext  Pointer to the TDES context.
    253   @param[in]   Input        Pointer to the buffer containing the data to be encrypted.
    254   @param[in]   InputSize    Size of the Input buffer in bytes.
    255   @param[in]   Ivec         Pointer to initialization vector.
    256   @param[out]  Output       Pointer to a buffer that receives the TDES encryption output.
    257 
    258   @retval TRUE   TDES encryption succeeded.
    259   @retval FALSE  TDES encryption failed.
    260 
    261 **/
    262 BOOLEAN
    263 EFIAPI
    264 TdesCbcEncrypt (
    265   IN   VOID         *TdesContext,
    266   IN   CONST UINT8  *Input,
    267   IN   UINTN        InputSize,
    268   IN   CONST UINT8  *Ivec,
    269   OUT  UINT8        *Output
    270   )
    271 {
    272   DES_key_schedule  *KeySchedule;
    273   UINT8             IvecBuffer[TDES_BLOCK_SIZE];
    274 
    275   //
    276   // Check input parameters.
    277   //
    278   if (TdesContext == NULL || Input == NULL || (InputSize % TDES_BLOCK_SIZE) != 0) {
    279     return FALSE;
    280   }
    281 
    282   if (Ivec == NULL || Output == NULL || InputSize > INT_MAX) {
    283     return FALSE;
    284   }
    285 
    286   KeySchedule = (DES_key_schedule *) TdesContext;
    287   CopyMem (IvecBuffer, Ivec, TDES_BLOCK_SIZE);
    288 
    289   DES_ede3_cbc_encrypt (
    290     Input,
    291     Output,
    292     (UINT32) InputSize,
    293     KeySchedule,
    294     KeySchedule + 1,
    295     KeySchedule + 2,
    296     (DES_cblock *) IvecBuffer,
    297     DES_ENCRYPT
    298     );
    299 
    300   return TRUE;
    301 }
    302 
    303 /**
    304   Performs TDES decryption on a data buffer of the specified size in CBC mode.
    305 
    306   This function performs TDES decryption on data buffer pointed by Input, of specified
    307   size of InputSize, in CBC mode.
    308   InputSize must be multiple of block size (8 bytes). This function does not perform
    309   padding. Caller must perform padding, if necessary, to ensure valid input data size.
    310   Initialization vector should be one block size (8 bytes).
    311   TdesContext should be already correctly initialized by TdesInit(). Behavior with
    312   invalid TDES context is undefined.
    313 
    314   If TdesContext is NULL, then return FALSE.
    315   If Input is NULL, then return FALSE.
    316   If InputSize is not multiple of block size (8 bytes), then return FALSE.
    317   If Ivec is NULL, then return FALSE.
    318   If Output is NULL, then return FALSE.
    319 
    320   @param[in]   TdesContext  Pointer to the TDES context.
    321   @param[in]   Input        Pointer to the buffer containing the data to be encrypted.
    322   @param[in]   InputSize    Size of the Input buffer in bytes.
    323   @param[in]   Ivec         Pointer to initialization vector.
    324   @param[out]  Output       Pointer to a buffer that receives the TDES encryption output.
    325 
    326   @retval TRUE   TDES decryption succeeded.
    327   @retval FALSE  TDES decryption failed.
    328 
    329 **/
    330 BOOLEAN
    331 EFIAPI
    332 TdesCbcDecrypt (
    333   IN   VOID         *TdesContext,
    334   IN   CONST UINT8  *Input,
    335   IN   UINTN        InputSize,
    336   IN   CONST UINT8  *Ivec,
    337   OUT  UINT8        *Output
    338   )
    339 {
    340   DES_key_schedule  *KeySchedule;
    341   UINT8             IvecBuffer[TDES_BLOCK_SIZE];
    342 
    343   //
    344   // Check input parameters.
    345   //
    346   if (TdesContext == NULL || Input == NULL || (InputSize % TDES_BLOCK_SIZE) != 0) {
    347     return FALSE;
    348   }
    349 
    350   if (Ivec == NULL || Output == NULL || InputSize > INT_MAX) {
    351     return FALSE;
    352   }
    353 
    354   KeySchedule = (DES_key_schedule *) TdesContext;
    355   CopyMem (IvecBuffer, Ivec, TDES_BLOCK_SIZE);
    356 
    357   DES_ede3_cbc_encrypt (
    358     Input,
    359     Output,
    360     (UINT32) InputSize,
    361     KeySchedule,
    362     KeySchedule + 1,
    363     KeySchedule + 2,
    364     (DES_cblock *) IvecBuffer,
    365     DES_DECRYPT
    366     );
    367 
    368   return TRUE;
    369 }
    370 
    371