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