| /** @file | |
| TDES Wrapper Implementation over OpenSSL. | |
| Copyright (c) 2010 - 2015, Intel Corporation. All rights reserved.<BR> | |
| This program and the accompanying materials | |
| are licensed and made available under the terms and conditions of the BSD License | |
| which accompanies this distribution. The full text of the license may be found at | |
| http://opensource.org/licenses/bsd-license.php | |
| THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, | |
| WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. | |
| **/ | |
| #include "InternalCryptLib.h" | |
| #include <openssl/des.h> | |
| /** | |
| Retrieves the size, in bytes, of the context buffer required for TDES operations. | |
| @return The size, in bytes, of the context buffer required for TDES operations. | |
| **/ | |
| UINTN | |
| EFIAPI | |
| TdesGetContextSize ( | |
| VOID | |
| ) | |
| { | |
| // | |
| // Memory for 3 copies of DES_key_schedule is allocated, for K1, K2 and K3 each. | |
| // | |
| return (UINTN) (3 * sizeof (DES_key_schedule)); | |
| } | |
| /** | |
| Initializes user-supplied memory as TDES context for subsequent use. | |
| This function initializes user-supplied memory pointed by TdesContext as TDES context. | |
| In addition, it sets up all TDES key materials for subsequent encryption and decryption | |
| operations. | |
| There are 3 key options as follows: | |
| KeyLength = 64, Keying option 1: K1 == K2 == K3 (Backward compatibility with DES) | |
| KeyLength = 128, Keying option 2: K1 != K2 and K3 = K1 (Less Security) | |
| KeyLength = 192 Keying option 3: K1 != K2 != K3 (Strongest) | |
| If TdesContext is NULL, then return FALSE. | |
| If Key is NULL, then return FALSE. | |
| If KeyLength is not valid, then return FALSE. | |
| @param[out] TdesContext Pointer to TDES context being initialized. | |
| @param[in] Key Pointer to the user-supplied TDES key. | |
| @param[in] KeyLength Length of TDES key in bits. | |
| @retval TRUE TDES context initialization succeeded. | |
| @retval FALSE TDES context initialization failed. | |
| **/ | |
| BOOLEAN | |
| EFIAPI | |
| TdesInit ( | |
| OUT VOID *TdesContext, | |
| IN CONST UINT8 *Key, | |
| IN UINTN KeyLength | |
| ) | |
| { | |
| DES_key_schedule *KeySchedule; | |
| // | |
| // Check input parameters. | |
| // | |
| if (TdesContext == NULL || Key == NULL || (KeyLength != 64 && KeyLength != 128 && KeyLength != 192)) { | |
| return FALSE; | |
| } | |
| KeySchedule = (DES_key_schedule *) TdesContext; | |
| // | |
| // If input Key is a weak key, return error. | |
| // | |
| if (DES_is_weak_key ((const_DES_cblock *) Key) == 1) { | |
| return FALSE; | |
| } | |
| DES_set_key_unchecked ((const_DES_cblock *) Key, KeySchedule); | |
| if (KeyLength == 64) { | |
| CopyMem (KeySchedule + 1, KeySchedule, sizeof (DES_key_schedule)); | |
| CopyMem (KeySchedule + 2, KeySchedule, sizeof (DES_key_schedule)); | |
| return TRUE; | |
| } | |
| if (DES_is_weak_key ((const_DES_cblock *) (Key + 8)) == 1) { | |
| return FALSE; | |
| } | |
| DES_set_key_unchecked ((const_DES_cblock *) (Key + 8), KeySchedule + 1); | |
| if (KeyLength == 128) { | |
| CopyMem (KeySchedule + 2, KeySchedule, sizeof (DES_key_schedule)); | |
| return TRUE; | |
| } | |
| if (DES_is_weak_key ((const_DES_cblock *) (Key + 16)) == 1) { | |
| return FALSE; | |
| } | |
| DES_set_key_unchecked ((const_DES_cblock *) (Key + 16), KeySchedule + 2); | |
| return TRUE; | |
| } | |
| /** | |
| Performs TDES encryption on a data buffer of the specified size in ECB mode. | |
| This function performs TDES encryption on data buffer pointed by Input, of specified | |
| size of InputSize, in ECB mode. | |
| InputSize must be multiple of block size (8 bytes). This function does not perform | |
| padding. Caller must perform padding, if necessary, to ensure valid input data size. | |
| TdesContext should be already correctly initialized by TdesInit(). Behavior with | |
| invalid TDES context is undefined. | |
| If TdesContext is NULL, then return FALSE. | |
| If Input is NULL, then return FALSE. | |
| If InputSize is not multiple of block size (8 bytes), then return FALSE. | |
| If Output is NULL, then return FALSE. | |
| @param[in] TdesContext Pointer to the TDES context. | |
| @param[in] Input Pointer to the buffer containing the data to be encrypted. | |
| @param[in] InputSize Size of the Input buffer in bytes. | |
| @param[out] Output Pointer to a buffer that receives the TDES encryption output. | |
| @retval TRUE TDES encryption succeeded. | |
| @retval FALSE TDES encryption failed. | |
| **/ | |
| BOOLEAN | |
| EFIAPI | |
| TdesEcbEncrypt ( | |
| IN VOID *TdesContext, | |
| IN CONST UINT8 *Input, | |
| IN UINTN InputSize, | |
| OUT UINT8 *Output | |
| ) | |
| { | |
| DES_key_schedule *KeySchedule; | |
| // | |
| // Check input parameters. | |
| // | |
| if (TdesContext == NULL || Input == NULL || (InputSize % TDES_BLOCK_SIZE) != 0 || Output == NULL) { | |
| return FALSE; | |
| } | |
| KeySchedule = (DES_key_schedule *) TdesContext; | |
| while (InputSize > 0) { | |
| DES_ecb3_encrypt ( | |
| (const_DES_cblock *) Input, | |
| (DES_cblock *) Output, | |
| KeySchedule, | |
| KeySchedule + 1, | |
| KeySchedule + 2, | |
| DES_ENCRYPT | |
| ); | |
| Input += TDES_BLOCK_SIZE; | |
| Output += TDES_BLOCK_SIZE; | |
| InputSize -= TDES_BLOCK_SIZE; | |
| } | |
| return TRUE; | |
| } | |
| /** | |
| Performs TDES decryption on a data buffer of the specified size in ECB mode. | |
| This function performs TDES decryption on data buffer pointed by Input, of specified | |
| size of InputSize, in ECB mode. | |
| InputSize must be multiple of block size (8 bytes). This function does not perform | |
| padding. Caller must perform padding, if necessary, to ensure valid input data size. | |
| TdesContext should be already correctly initialized by TdesInit(). Behavior with | |
| invalid TDES context is undefined. | |
| If TdesContext is NULL, then return FALSE. | |
| If Input is NULL, then return FALSE. | |
| If InputSize is not multiple of block size (8 bytes), then return FALSE. | |
| If Output is NULL, then return FALSE. | |
| @param[in] TdesContext Pointer to the TDES context. | |
| @param[in] Input Pointer to the buffer containing the data to be decrypted. | |
| @param[in] InputSize Size of the Input buffer in bytes. | |
| @param[out] Output Pointer to a buffer that receives the TDES decryption output. | |
| @retval TRUE TDES decryption succeeded. | |
| @retval FALSE TDES decryption failed. | |
| **/ | |
| BOOLEAN | |
| EFIAPI | |
| TdesEcbDecrypt ( | |
| IN VOID *TdesContext, | |
| IN CONST UINT8 *Input, | |
| IN UINTN InputSize, | |
| OUT UINT8 *Output | |
| ) | |
| { | |
| DES_key_schedule *KeySchedule; | |
| // | |
| // Check input parameters. | |
| // | |
| if (TdesContext == NULL || Input == NULL || (InputSize % TDES_BLOCK_SIZE) != 0 || Output == NULL) { | |
| return FALSE; | |
| } | |
| KeySchedule = (DES_key_schedule *) TdesContext; | |
| while (InputSize > 0) { | |
| DES_ecb3_encrypt ( | |
| (const_DES_cblock *) Input, | |
| (DES_cblock *) Output, | |
| KeySchedule, | |
| KeySchedule + 1, | |
| KeySchedule + 2, | |
| DES_DECRYPT | |
| ); | |
| Input += TDES_BLOCK_SIZE; | |
| Output += TDES_BLOCK_SIZE; | |
| InputSize -= TDES_BLOCK_SIZE; | |
| } | |
| return TRUE; | |
| } | |
| /** | |
| Performs TDES encryption on a data buffer of the specified size in CBC mode. | |
| This function performs TDES encryption on data buffer pointed by Input, of specified | |
| size of InputSize, in CBC mode. | |
| InputSize must be multiple of block size (8 bytes). This function does not perform | |
| padding. Caller must perform padding, if necessary, to ensure valid input data size. | |
| Initialization vector should be one block size (8 bytes). | |
| TdesContext should be already correctly initialized by TdesInit(). Behavior with | |
| invalid TDES context is undefined. | |
| If TdesContext is NULL, then return FALSE. | |
| If Input is NULL, then return FALSE. | |
| If InputSize is not multiple of block size (8 bytes), then return FALSE. | |
| If Ivec is NULL, then return FALSE. | |
| If Output is NULL, then return FALSE. | |
| @param[in] TdesContext Pointer to the TDES context. | |
| @param[in] Input Pointer to the buffer containing the data to be encrypted. | |
| @param[in] InputSize Size of the Input buffer in bytes. | |
| @param[in] Ivec Pointer to initialization vector. | |
| @param[out] Output Pointer to a buffer that receives the TDES encryption output. | |
| @retval TRUE TDES encryption succeeded. | |
| @retval FALSE TDES encryption failed. | |
| **/ | |
| BOOLEAN | |
| EFIAPI | |
| TdesCbcEncrypt ( | |
| IN VOID *TdesContext, | |
| IN CONST UINT8 *Input, | |
| IN UINTN InputSize, | |
| IN CONST UINT8 *Ivec, | |
| OUT UINT8 *Output | |
| ) | |
| { | |
| DES_key_schedule *KeySchedule; | |
| UINT8 IvecBuffer[TDES_BLOCK_SIZE]; | |
| // | |
| // Check input parameters. | |
| // | |
| if (TdesContext == NULL || Input == NULL || (InputSize % TDES_BLOCK_SIZE) != 0) { | |
| return FALSE; | |
| } | |
| if (Ivec == NULL || Output == NULL || InputSize > INT_MAX) { | |
| return FALSE; | |
| } | |
| KeySchedule = (DES_key_schedule *) TdesContext; | |
| CopyMem (IvecBuffer, Ivec, TDES_BLOCK_SIZE); | |
| DES_ede3_cbc_encrypt ( | |
| Input, | |
| Output, | |
| (UINT32) InputSize, | |
| KeySchedule, | |
| KeySchedule + 1, | |
| KeySchedule + 2, | |
| (DES_cblock *) IvecBuffer, | |
| DES_ENCRYPT | |
| ); | |
| return TRUE; | |
| } | |
| /** | |
| Performs TDES decryption on a data buffer of the specified size in CBC mode. | |
| This function performs TDES decryption on data buffer pointed by Input, of specified | |
| size of InputSize, in CBC mode. | |
| InputSize must be multiple of block size (8 bytes). This function does not perform | |
| padding. Caller must perform padding, if necessary, to ensure valid input data size. | |
| Initialization vector should be one block size (8 bytes). | |
| TdesContext should be already correctly initialized by TdesInit(). Behavior with | |
| invalid TDES context is undefined. | |
| If TdesContext is NULL, then return FALSE. | |
| If Input is NULL, then return FALSE. | |
| If InputSize is not multiple of block size (8 bytes), then return FALSE. | |
| If Ivec is NULL, then return FALSE. | |
| If Output is NULL, then return FALSE. | |
| @param[in] TdesContext Pointer to the TDES context. | |
| @param[in] Input Pointer to the buffer containing the data to be encrypted. | |
| @param[in] InputSize Size of the Input buffer in bytes. | |
| @param[in] Ivec Pointer to initialization vector. | |
| @param[out] Output Pointer to a buffer that receives the TDES encryption output. | |
| @retval TRUE TDES decryption succeeded. | |
| @retval FALSE TDES decryption failed. | |
| **/ | |
| BOOLEAN | |
| EFIAPI | |
| TdesCbcDecrypt ( | |
| IN VOID *TdesContext, | |
| IN CONST UINT8 *Input, | |
| IN UINTN InputSize, | |
| IN CONST UINT8 *Ivec, | |
| OUT UINT8 *Output | |
| ) | |
| { | |
| DES_key_schedule *KeySchedule; | |
| UINT8 IvecBuffer[TDES_BLOCK_SIZE]; | |
| // | |
| // Check input parameters. | |
| // | |
| if (TdesContext == NULL || Input == NULL || (InputSize % TDES_BLOCK_SIZE) != 0) { | |
| return FALSE; | |
| } | |
| if (Ivec == NULL || Output == NULL || InputSize > INT_MAX) { | |
| return FALSE; | |
| } | |
| KeySchedule = (DES_key_schedule *) TdesContext; | |
| CopyMem (IvecBuffer, Ivec, TDES_BLOCK_SIZE); | |
| DES_ede3_cbc_encrypt ( | |
| Input, | |
| Output, | |
| (UINT32) InputSize, | |
| KeySchedule, | |
| KeySchedule + 1, | |
| KeySchedule + 2, | |
| (DES_cblock *) IvecBuffer, | |
| DES_DECRYPT | |
| ); | |
| return TRUE; | |
| } | |