1 /***************************************************************************
2 * Copyright (c) 2024 Microsoft Corporation
3 *
4 * This program and the accompanying materials are made available under the
5 * terms of the MIT License which is available at
6 * https://opensource.org/licenses/MIT.
7 *
8 * SPDX-License-Identifier: MIT
9 **************************************************************************/
10
11
12 /**************************************************************************/
13 /**************************************************************************/
14 /** */
15 /** NetX Crypto Component */
16 /** */
17 /** 3DES Encryption Standard (Triple DES) */
18 /** */
19 /**************************************************************************/
20 /**************************************************************************/
21
22 #include "nx_crypto_3des.h"
23
24
25 /**************************************************************************/
26 /* */
27 /* FUNCTION RELEASE */
28 /* */
29 /* _nx_crypto_3des_key_set PORTABLE C */
30 /* 6.1.11 */
31 /* AUTHOR */
32 /* */
33 /* Timothy Stapko, Microsoft Corporation */
34 /* */
35 /* DESCRIPTION */
36 /* */
37 /* This function sets up the encryption keys for the 3DES algorithm. */
38 /* It must be called before either _nx_crypto_3des_encrypt or */
39 /* _nx_crypto_3des_decrypt can be called. */
40 /* */
41 /* INPUT */
42 /* */
43 /* context 3DES context pointer */
44 /* key 24 bytes key */
45 /* */
46 /* OUTPUT */
47 /* */
48 /* status Completion status */
49 /* */
50 /* CALLS */
51 /* */
52 /* _nx_crypto_des_key_set Set the key for DES */
53 /* */
54 /* CALLED BY */
55 /* */
56 /* _nx_crypto_method_3des_init Init the method for 3DES */
57 /* */
58 /* RELEASE HISTORY */
59 /* */
60 /* DATE NAME DESCRIPTION */
61 /* */
62 /* 05-19-2020 Timothy Stapko Initial Version 6.0 */
63 /* 09-30-2020 Timothy Stapko Modified comment(s), */
64 /* resulting in version 6.1 */
65 /* 04-25-2022 Timothy Stapko Modified comments(s), added */
66 /* warning supression for */
67 /* obsolete DES/3DES, */
68 /* resulting in version 6.1.11 */
69 /* */
70 /**************************************************************************/
_nx_crypto_3des_key_set(NX_CRYPTO_3DES * context,UCHAR key[24])71 NX_CRYPTO_KEEP UINT _nx_crypto_3des_key_set(NX_CRYPTO_3DES *context, UCHAR key[24])
72 {
73
74 _nx_crypto_des_key_set(&context -> des_1, key); /* lgtm[cpp/weak-cryptographic-algorithm] */
75
76 _nx_crypto_des_key_set(&context -> des_2, key + 8); /* lgtm[cpp/weak-cryptographic-algorithm] */
77
78 _nx_crypto_des_key_set(&context -> des_3, key + 16); /* lgtm[cpp/weak-cryptographic-algorithm] */
79
80 return(NX_CRYPTO_SUCCESS);
81 }
82
83
84 /**************************************************************************/
85 /* */
86 /* FUNCTION RELEASE */
87 /* */
88 /* _nx_crypto_3des_encrypt PORTABLE C */
89 /* 6.1.11 */
90 /* AUTHOR */
91 /* */
92 /* Timothy Stapko, Microsoft Corporation */
93 /* */
94 /* DESCRIPTION */
95 /* */
96 /* This function uses the 3DES algorithm to encrypt 8-bytes (64-bits). */
97 /* The result is 8 encrypted bytes. Note that the caller must make */
98 /* sure the source and destination are 8-bytes in size! */
99 /* */
100 /* INPUT */
101 /* */
102 /* context 3DES context pointer */
103 /* source 8-byte source */
104 /* destination 8-byte destination */
105 /* length The length of output buffer */
106 /* */
107 /* OUTPUT */
108 /* */
109 /* status Completion status */
110 /* */
111 /* CALLS */
112 /* */
113 /* _nx_crypto_des_encrypt Perform DES mode encryption */
114 /* _nx_crypto_des_decrypt Perform DES mode decryption */
115 /* */
116 /* CALLED BY */
117 /* */
118 /* _nx_crypto_method_3des_operation Handle 3DES encrypt or decrypt*/
119 /* */
120 /* RELEASE HISTORY */
121 /* */
122 /* DATE NAME DESCRIPTION */
123 /* */
124 /* 05-19-2020 Timothy Stapko Initial Version 6.0 */
125 /* 09-30-2020 Timothy Stapko Modified comment(s), */
126 /* resulting in version 6.1 */
127 /* 04-25-2022 Timothy Stapko Modified comments(s), added */
128 /* warning supression for */
129 /* obsolete DES/3DES, */
130 /* resulting in version 6.1.11 */
131 /* */
132 /**************************************************************************/
_nx_crypto_3des_encrypt(NX_CRYPTO_3DES * context,UCHAR source[8],UCHAR destination[8],UINT length)133 NX_CRYPTO_KEEP UINT _nx_crypto_3des_encrypt(NX_CRYPTO_3DES *context, UCHAR source[8],
134 UCHAR destination[8], UINT length)
135 {
136
137 /* ciphertext = EK3(DK2(EK1(plaintext)))
138 I.e., DES encrypt with K1, DES decrypt with K2, then DES encrypt with K3. */
139 _nx_crypto_des_encrypt(&context -> des_1, source, destination, length); /* lgtm[cpp/weak-cryptographic-algorithm] */
140
141 _nx_crypto_des_decrypt(&context -> des_2, destination, destination, length); /* lgtm[cpp/weak-cryptographic-algorithm] */
142
143 _nx_crypto_des_encrypt(&context -> des_3, destination, destination, length); /* lgtm[cpp/weak-cryptographic-algorithm] */
144
145 /* Return successful completion. */
146 return(NX_CRYPTO_SUCCESS);
147 }
148
149
150 /**************************************************************************/
151 /* */
152 /* FUNCTION RELEASE */
153 /* */
154 /* _nx_crypto_3des_decrypt PORTABLE C */
155 /* 6.1.11 */
156 /* AUTHOR */
157 /* */
158 /* Timothy Stapko, Microsoft Corporation */
159 /* */
160 /* DESCRIPTION */
161 /* */
162 /* This function uses the 3DES algorithm to decrypt 8-bytes (64-bits). */
163 /* The result is 8 original source bytes. Note that the caller must */
164 /* make sure the source and destination are 8-bytes in size! */
165 /* */
166 /* INPUT */
167 /* */
168 /* context 3DES context pointer */
169 /* source 8-byte source */
170 /* destination 8-byte destination */
171 /* length The length of output buffer */
172 /* */
173 /* OUTPUT */
174 /* */
175 /* status Completion status */
176 /* */
177 /* CALLS */
178 /* */
179 /* _nx_crypto_des_encrypt Perform DES mode encryption */
180 /* _nx_crypto_des_decrypt Perform DES mode decryption */
181 /* */
182 /* CALLED BY */
183 /* */
184 /* _nx_crypto_method_3des_operation Handle 3DES encrypt or decrypt*/
185 /* */
186 /* RELEASE HISTORY */
187 /* */
188 /* DATE NAME DESCRIPTION */
189 /* */
190 /* 05-19-2020 Timothy Stapko Initial Version 6.0 */
191 /* 09-30-2020 Timothy Stapko Modified comment(s), */
192 /* resulting in version 6.1 */
193 /* 04-25-2022 Timothy Stapko Modified comments(s), added */
194 /* warning supression for */
195 /* obsolete DES/3DES, */
196 /* resulting in version 6.1.11 */
197 /* */
198 /**************************************************************************/
_nx_crypto_3des_decrypt(NX_CRYPTO_3DES * context,UCHAR source[8],UCHAR destination[8],UINT length)199 NX_CRYPTO_KEEP UINT _nx_crypto_3des_decrypt(NX_CRYPTO_3DES *context, UCHAR source[8],
200 UCHAR destination[8], UINT length)
201 {
202
203
204 /*
205 plaintext = DK1(EK2(DK3(ciphertext)))
206 I.e., decrypt with K3, encrypt with K2, then decrypt with K1.
207 */
208 _nx_crypto_des_decrypt(&context -> des_3, source, destination, length); /* lgtm[cpp/weak-cryptographic-algorithm] */
209
210 _nx_crypto_des_encrypt(&context -> des_2, destination, destination, length); /* lgtm[cpp/weak-cryptographic-algorithm] */
211
212 _nx_crypto_des_decrypt(&context -> des_1, destination, destination, length); /* lgtm[cpp/weak-cryptographic-algorithm] */
213
214
215 /* Return successful completion. */
216 return(NX_CRYPTO_SUCCESS);
217 }
218
219
220 /**************************************************************************/
221 /* */
222 /* FUNCTION RELEASE */
223 /* */
224 /* _nx_crypto_method_3des_init PORTABLE C */
225 /* 6.3.0 */
226 /* AUTHOR */
227 /* */
228 /* Timothy Stapko, Microsoft Corporation */
229 /* */
230 /* DESCRIPTION */
231 /* */
232 /* This function is the common crypto method init callback for */
233 /* Microsoft supported 3DES cryptographic algorithm. */
234 /* */
235 /* INPUT */
236 /* */
237 /* method Pointer to crypto method */
238 /* key Pointer to key */
239 /* key_size_in_bits Length of key size in bits */
240 /* handler Returned crypto handler */
241 /* crypto_metadata Metadata area */
242 /* crypto_metadata_size Size of the metadata area */
243 /* */
244 /* OUTPUT */
245 /* */
246 /* status Completion status */
247 /* */
248 /* CALLS */
249 /* */
250 /* _nx_crypto_3des_key_set Set the key for 3DES */
251 /* */
252 /* CALLED BY */
253 /* */
254 /* Application Code */
255 /* */
256 /* RELEASE HISTORY */
257 /* */
258 /* DATE NAME DESCRIPTION */
259 /* */
260 /* 05-19-2020 Timothy Stapko Initial Version 6.0 */
261 /* 09-30-2020 Timothy Stapko Modified comment(s), */
262 /* resulting in version 6.1 */
263 /* 04-25-2022 Timothy Stapko Modified comments(s), added */
264 /* warning supression for */
265 /* obsolete DES/3DES, */
266 /* resulting in version 6.1.11 */
267 /* 10-31-2023 Yanwu Cai Modified comment(s), */
268 /* resulting in version 6.3.0 */
269 /* */
270 /**************************************************************************/
_nx_crypto_method_3des_init(struct NX_CRYPTO_METHOD_STRUCT * method,UCHAR * key,NX_CRYPTO_KEY_SIZE key_size_in_bits,VOID ** handle,VOID * crypto_metadata,ULONG crypto_metadata_size)271 NX_CRYPTO_KEEP UINT _nx_crypto_method_3des_init(struct NX_CRYPTO_METHOD_STRUCT *method,
272 UCHAR *key, NX_CRYPTO_KEY_SIZE key_size_in_bits,
273 VOID **handle,
274 VOID *crypto_metadata,
275 ULONG crypto_metadata_size)
276 {
277 NX_CRYPTO_3DES *triple_des_context_ptr;
278
279 NX_CRYPTO_PARAMETER_NOT_USED(handle);
280
281 NX_CRYPTO_STATE_CHECK
282
283 /* Validate input parameters. */
284 if ((method == NX_CRYPTO_NULL) || (key == NX_CRYPTO_NULL) || (crypto_metadata == NX_CRYPTO_NULL))
285 {
286 return(NX_CRYPTO_PTR_ERROR);
287 }
288
289 /* Verify the metadata address is 4-byte aligned. */
290 if((((ULONG)crypto_metadata) & 0x3) != 0)
291 {
292 return(NX_CRYPTO_PTR_ERROR);
293 }
294
295 if(crypto_metadata_size < sizeof(NX_CRYPTO_3DES))
296 {
297 return(NX_CRYPTO_PTR_ERROR);
298 }
299
300
301 if (key_size_in_bits != NX_CRYPTO_3DES_KEY_LEN_IN_BITS) /* lgtm[cpp/weak-cryptographic-algorithm] */
302 {
303 return(NX_CRYPTO_UNSUPPORTED_KEY_SIZE);
304 }
305
306 triple_des_context_ptr = (NX_CRYPTO_3DES *)(crypto_metadata);
307
308
309 _nx_crypto_3des_key_set(triple_des_context_ptr, key); /* lgtm[cpp/weak-cryptographic-algorithm] */
310
311 return(NX_CRYPTO_SUCCESS);
312 }
313
314
315 /**************************************************************************/
316 /* */
317 /* FUNCTION RELEASE */
318 /* */
319 /* _nx_crypto_method_3des_cleanup PORTABLE C */
320 /* 6.1 */
321 /* AUTHOR */
322 /* */
323 /* Timothy Stapko, Microsoft Corporation */
324 /* */
325 /* DESCRIPTION */
326 /* */
327 /* This function cleans up the crypto metadata. */
328 /* */
329 /* INPUT */
330 /* */
331 /* crypto_metadata Crypto metadata */
332 /* */
333 /* OUTPUT */
334 /* */
335 /* status Completion status */
336 /* */
337 /* CALLS */
338 /* */
339 /* NX_CRYPTO_MEMSET Set the memory */
340 /* */
341 /* CALLED BY */
342 /* */
343 /* Application Code */
344 /* */
345 /* RELEASE HISTORY */
346 /* */
347 /* DATE NAME DESCRIPTION */
348 /* */
349 /* 05-19-2020 Timothy Stapko Initial Version 6.0 */
350 /* 09-30-2020 Timothy Stapko Modified comment(s), */
351 /* resulting in version 6.1 */
352 /* */
353 /**************************************************************************/
_nx_crypto_method_3des_cleanup(VOID * crypto_metadata)354 NX_CRYPTO_KEEP UINT _nx_crypto_method_3des_cleanup(VOID *crypto_metadata)
355 {
356
357 NX_CRYPTO_STATE_CHECK
358
359 #ifdef NX_SECURE_KEY_CLEAR
360 if (!crypto_metadata)
361 return (NX_CRYPTO_SUCCESS);
362
363 /* Clean up the crypto metadata. */
364 NX_CRYPTO_MEMSET(crypto_metadata, 0, sizeof(NX_CRYPTO_3DES));
365 #else
366 NX_CRYPTO_PARAMETER_NOT_USED(crypto_metadata);
367 #endif/* NX_SECURE_KEY_CLEAR */
368
369 return(NX_CRYPTO_SUCCESS);
370 }
371
372
373 /**************************************************************************/
374 /* */
375 /* FUNCTION RELEASE */
376 /* */
377 /* _nx_crypto_method_3des_operation PORTABLE C */
378 /* 6.3.0 */
379 /* AUTHOR */
380 /* */
381 /* Timothy Stapko, Microsoft Corporation */
382 /* */
383 /* DESCRIPTION */
384 /* */
385 /* This function handles 3des encrypt or decrypt operations. */
386 /* */
387 /* INPUT */
388 /* */
389 /* op Operation Type */
390 /* Encrypt, Decrypt, Authenticate*/
391 /* handler Pointer to crypto context */
392 /* method Pointer to crypto method */
393 /* key Pointer to key */
394 /* key_size_in_bits Length of key size in bits */
395 /* input Input Stream */
396 /* input_length_in_byte Input Stream Length */
397 /* iv_ptr Initialized Vector */
398 /* output Output Stream */
399 /* output_length_in_byte Output Stream Length */
400 /* crypto_metadata Metadata area */
401 /* crypto_metadata_size Size of the metadata area */
402 /* packet_ptr Pointer to packet */
403 /* nx_crypto_hw_process_callback Callback function pointer */
404 /* */
405 /* OUTPUT */
406 /* */
407 /* status Completion status */
408 /* */
409 /* CALLS */
410 /* */
411 /* _nx_crypto_cbc_encrypt Perform CBC mode encryption */
412 /* _nx_crypto_cbc_decrypt Perform CBC mode decryption */
413 /* */
414 /* CALLED BY */
415 /* */
416 /* Application Code */
417 /* */
418 /* RELEASE HISTORY */
419 /* */
420 /* DATE NAME DESCRIPTION */
421 /* */
422 /* 05-19-2020 Timothy Stapko Initial Version 6.0 */
423 /* 09-30-2020 Timothy Stapko Modified comment(s), */
424 /* resulting in version 6.1 */
425 /* 04-25-2022 Timothy Stapko Modified comments(s), added */
426 /* warning supression for */
427 /* obsolete DES/3DES, */
428 /* resulting in version 6.1.11 */
429 /* 10-31-2023 Yanwu Cai Modified comment(s), */
430 /* resulting in version 6.3.0 */
431 /* */
432 /**************************************************************************/
_nx_crypto_method_3des_operation(UINT op,VOID * handler,struct NX_CRYPTO_METHOD_STRUCT * method,UCHAR * key,NX_CRYPTO_KEY_SIZE key_size_in_bits,UCHAR * input,ULONG input_length_in_byte,UCHAR * iv_ptr,UCHAR * output,ULONG output_length_in_byte,VOID * crypto_metadata,ULONG crypto_metadata_size,VOID * packet_ptr,VOID (* nx_crypto_hw_process_callback)(VOID * packet_ptr,UINT status))433 NX_CRYPTO_KEEP UINT _nx_crypto_method_3des_operation(UINT op, /* Encrypt, Decrypt, Authenticate */
434 VOID *handler, /* Crypto handler */
435 struct NX_CRYPTO_METHOD_STRUCT *method,
436 UCHAR *key,
437 NX_CRYPTO_KEY_SIZE key_size_in_bits,
438 UCHAR *input,
439 ULONG input_length_in_byte,
440 UCHAR *iv_ptr,
441 UCHAR *output,
442 ULONG output_length_in_byte,
443 VOID *crypto_metadata,
444 ULONG crypto_metadata_size,
445 VOID *packet_ptr,
446 VOID (*nx_crypto_hw_process_callback)(VOID *packet_ptr, UINT status))
447 {
448 UINT status = NX_CRYPTO_NOT_SUCCESSFUL;
449 NX_CRYPTO_3DES *context;
450
451 NX_CRYPTO_PARAMETER_NOT_USED(handler);
452 NX_CRYPTO_PARAMETER_NOT_USED(key);
453 NX_CRYPTO_PARAMETER_NOT_USED(key_size_in_bits);
454 NX_CRYPTO_PARAMETER_NOT_USED(output_length_in_byte);
455 NX_CRYPTO_PARAMETER_NOT_USED(packet_ptr);
456 NX_CRYPTO_PARAMETER_NOT_USED(nx_crypto_hw_process_callback);
457
458 NX_CRYPTO_STATE_CHECK
459
460 if (op == NX_CRYPTO_AUTHENTICATE)
461 {
462 /* Incorrect Operation. */
463 return(NX_CRYPTO_NOT_SUCCESSFUL);
464 }
465
466 if ((method == NX_CRYPTO_NULL) || (crypto_metadata == NX_CRYPTO_NULL))
467 {
468 return(NX_CRYPTO_PTR_ERROR);
469 }
470
471 /* Verify the metadata address is 4-byte aligned. */
472 if((((ULONG)crypto_metadata) & 0x3) != 0)
473 {
474 return(NX_CRYPTO_PTR_ERROR);
475 }
476
477 if(crypto_metadata_size < sizeof(NX_CRYPTO_3DES))
478 {
479 return(NX_CRYPTO_PTR_ERROR);
480 }
481
482 if (method -> nx_crypto_algorithm != NX_CRYPTO_ENCRYPTION_3DES_CBC) /* lgtm[cpp/weak-cryptographic-algorithm] */
483 {
484 /* Incorrect method. */
485 return(NX_CRYPTO_INVALID_ALGORITHM);
486 }
487
488 context = (NX_CRYPTO_3DES *)crypto_metadata;
489
490 switch (op)
491 {
492 case NX_CRYPTO_DECRYPT:
493 {
494 status = _nx_crypto_cbc_decrypt_init(&(context -> nx_crypto_cbc_context),
495 iv_ptr, method -> nx_crypto_IV_size_in_bits >> 3);
496 if (status)
497 {
498 break;
499 }
500
501 status = _nx_crypto_cbc_decrypt(context, &(context -> nx_crypto_cbc_context),
502 (UINT (*)(VOID *, UCHAR *, UCHAR *, UINT))_nx_crypto_3des_decrypt,
503 input, output, input_length_in_byte,
504 (NX_CRYPTO_3DES_BLOCK_SIZE_IN_BITS >> 3)); /* lgtm[cpp/weak-cryptographic-algorithm] */
505 } break;
506
507 case NX_CRYPTO_ENCRYPT:
508 {
509 status = _nx_crypto_cbc_encrypt_init(&(context -> nx_crypto_cbc_context),
510 iv_ptr, method -> nx_crypto_IV_size_in_bits >> 3);
511 if (status)
512 {
513 break;
514 }
515
516 status = _nx_crypto_cbc_encrypt(context, &(context -> nx_crypto_cbc_context),
517 (UINT (*)(VOID *, UCHAR *, UCHAR *, UINT))_nx_crypto_3des_encrypt,
518 input, output, input_length_in_byte,
519 (NX_CRYPTO_3DES_BLOCK_SIZE_IN_BITS >> 3)); /* lgtm[cpp/weak-cryptographic-algorithm] */
520 } break;
521
522 case NX_CRYPTO_DECRYPT_INITIALIZE:
523 {
524 status = _nx_crypto_cbc_decrypt_init(&(context -> nx_crypto_cbc_context),
525 iv_ptr, method -> nx_crypto_IV_size_in_bits >> 3);
526 } break;
527
528 case NX_CRYPTO_ENCRYPT_INITIALIZE:
529 {
530 status = _nx_crypto_cbc_encrypt_init(&(context -> nx_crypto_cbc_context),
531 iv_ptr, method -> nx_crypto_IV_size_in_bits >> 3);
532 } break;
533
534 case NX_CRYPTO_DECRYPT_UPDATE:
535 {
536 status = _nx_crypto_cbc_decrypt(context, &(context -> nx_crypto_cbc_context),
537 (UINT (*)(VOID *, UCHAR *, UCHAR *, UINT))_nx_crypto_3des_decrypt,
538 input, output, input_length_in_byte,
539 (NX_CRYPTO_3DES_BLOCK_SIZE_IN_BITS >> 3)); /* lgtm[cpp/weak-cryptographic-algorithm] */
540 } break;
541
542 case NX_CRYPTO_ENCRYPT_UPDATE:
543 {
544 status = _nx_crypto_cbc_encrypt(context, &(context -> nx_crypto_cbc_context),
545 (UINT (*)(VOID *, UCHAR *, UCHAR *, UINT))_nx_crypto_3des_encrypt,
546 input, output, input_length_in_byte,
547 (NX_CRYPTO_3DES_BLOCK_SIZE_IN_BITS >> 3)); /* lgtm[cpp/weak-cryptographic-algorithm] */
548 } break;
549
550 case NX_CRYPTO_ENCRYPT_CALCULATE:
551 /* fallthrough */
552 case NX_CRYPTO_DECRYPT_CALCULATE:
553 {
554
555 /* Nothing to do. */
556 status = NX_CRYPTO_SUCCESS;
557 } break;
558
559 default:
560 {
561 status = NX_CRYPTO_INVALID_ALGORITHM;
562 } break;
563 }
564
565 return status;
566 }
567
568