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