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 Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
14 rights reserved.
15
16 License to copy and use this software is granted provided that it
17 is identified as the ""RSA Data Security, Inc. MD5 Message-Digest
18 Algorithm"" in all material mentioning or referencing this software
19 or this function.
20
21 License is also granted to make and use derivative works provided
22 that such works are identified as ""derived from the RSA Data
23 Security, Inc. MD5 Message-Digest Algorithm"" in all material
24 mentioning or referencing the derived work.
25
26 RSA Data Security, Inc. makes no representations concerning either
27 the merchantability of this software or the suitability of this
28 software for any particular purpose. It is provided ""as is""
29 without express or implied warranty of any kind.
30
31 These notices must be retained in any copies of any part of this
32 documentation and/or software.
33 */
34 /**************************************************************************/
35
36
37 /**************************************************************************/
38 /**************************************************************************/
39 /** */
40 /** NetX Crypto Component */
41 /** */
42 /** MD5 Digest Algorithm (MD5) */
43 /** */
44 /**************************************************************************/
45 /**************************************************************************/
46
47 #include "nx_crypto_md5.h"
48
49
50 /* Define macros for the MD5 transform function. */
51
52 /* Define the MD5 basic F, G, H and I functions. */
53
54 #define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
55 #define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
56 #define H(x, y, z) ((x) ^ (y) ^ (z))
57 #define I(x, y, z) ((y) ^ ((x) | (~z)))
58
59
60 /* Define the MD5 left shift circular function. */
61
62 #define LEFT_SHIFT_CIRCULAR(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
63
64
65 /* Define the MD5 complex FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4. */
66
67 #define FF(a, b, c, d, x, s, ac) { \
68 (a) += F((b), (c), (d)) + (x) + (ULONG)(ac); \
69 (a) = LEFT_SHIFT_CIRCULAR((a), (s)); \
70 (a) += (b); \
71 }
72 #define GG(a, b, c, d, x, s, ac) { \
73 (a) += G((b), (c), (d)) + (x) + (ULONG)(ac); \
74 (a) = LEFT_SHIFT_CIRCULAR((a), (s)); \
75 (a) += (b); \
76 }
77 #define HH(a, b, c, d, x, s, ac) { \
78 (a) += H((b), (c), (d)) + (x) + (ULONG)(ac); \
79 (a) = LEFT_SHIFT_CIRCULAR((a), (s)); \
80 (a) += (b); \
81 }
82 #define II(a, b, c, d, x, s, ac) { \
83 (a) += I((b), (c), (d)) + (x) + (ULONG)(ac); \
84 (a) = LEFT_SHIFT_CIRCULAR((a), (s)); \
85 (a) += (b); \
86 }
87
88
89 /* Define the padding array. This is used to pad the message such that its length is
90 64 bits shy of being a multiple of 512 bits long. */
91
92 const UCHAR _nx_crypto_md5_padding[64] = {0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
93
94
95 /**************************************************************************/
96 /* */
97 /* FUNCTION RELEASE */
98 /* */
99 /* _nx_crypto_md5_initialize PORTABLE C */
100 /* 6.1 */
101 /* AUTHOR */
102 /* */
103 /* Timothy Stapko, Microsoft Corporation */
104 /* */
105 /* DESCRIPTION */
106 /* */
107 /* This function initializes the MD5 context. It must be called prior */
108 /* to creating the MD5 digest. */
109 /* */
110 /* INPUT */
111 /* */
112 /* context MD5 context pointer */
113 /* algorithm Algorithm type */
114 /* */
115 /* OUTPUT */
116 /* */
117 /* status Completion status */
118 /* */
119 /* CALLS */
120 /* */
121 /* None */
122 /* */
123 /* CALLED BY */
124 /* */
125 /* _nx_crypto_method_md5_operation Handle MD5 operation */
126 /* */
127 /* RELEASE HISTORY */
128 /* */
129 /* DATE NAME DESCRIPTION */
130 /* */
131 /* 05-19-2020 Timothy Stapko Initial Version 6.0 */
132 /* 09-30-2020 Timothy Stapko Modified comment(s), */
133 /* updated constants, */
134 /* resulting in version 6.1 */
135 /* */
136 /**************************************************************************/
_nx_crypto_md5_initialize(NX_CRYPTO_MD5 * context,UINT algorithm)137 NX_CRYPTO_KEEP UINT _nx_crypto_md5_initialize(NX_CRYPTO_MD5 *context, UINT algorithm)
138 {
139 NX_CRYPTO_PARAMETER_NOT_USED(algorithm);
140
141 /* Determine if the context is non-null. */
142 if (context == NX_CRYPTO_NULL)
143 {
144 return(NX_CRYPTO_PTR_ERROR);
145 }
146
147 /* First, clear the bit count for this context. */
148 context -> nx_md5_bit_count[0] = 0; /* Clear the lower 32-bits of the count */
149 context -> nx_md5_bit_count[1] = 0; /* Clear the upper 32-bits of the count */
150
151 /* Finally, setup the context states. */
152 context -> nx_md5_states[0] = 0x67452301UL; /* Setup state A */
153 context -> nx_md5_states[1] = 0xEFCDAB89UL; /* Setup state B */
154 context -> nx_md5_states[2] = 0x98BADCFEUL; /* Setup state C */
155 context -> nx_md5_states[3] = 0x10325476UL; /* Setup state D */
156
157 /* Return success. */
158 return(NX_CRYPTO_SUCCESS);
159 }
160
161
162 /**************************************************************************/
163 /* */
164 /* FUNCTION RELEASE */
165 /* */
166 /* _nx_crypto_md5_update PORTABLE C */
167 /* 6.1 */
168 /* AUTHOR */
169 /* */
170 /* Timothy Stapko, Microsoft Corporation */
171 /* */
172 /* DESCRIPTION */
173 /* */
174 /* This function updates the digest calculation with new input from */
175 /* the caller. */
176 /* */
177 /* INPUT */
178 /* */
179 /* context MD5 context pointer */
180 /* input_ptr Pointer to byte(s) of input */
181 /* input_length Length of bytes of input */
182 /* */
183 /* OUTPUT */
184 /* */
185 /* status Completion status */
186 /* */
187 /* CALLS */
188 /* */
189 /* _nx_crypto_md5_process_buffer Process complete buffer, */
190 /* which is 64-bytes in size */
191 /* */
192 /* CALLED BY */
193 /* */
194 /* _nx_crypto_md5_digest_calculate Perform calculation of the */
195 /* MD5 digest */
196 /* _nx_crypto_method_md5_operation Handle MD5 operation */
197 /* */
198 /* RELEASE HISTORY */
199 /* */
200 /* DATE NAME DESCRIPTION */
201 /* */
202 /* 05-19-2020 Timothy Stapko Initial Version 6.0 */
203 /* 09-30-2020 Timothy Stapko Modified comment(s), */
204 /* verified memcpy use cases, */
205 /* resulting in version 6.1 */
206 /* */
207 /**************************************************************************/
_nx_crypto_md5_update(NX_CRYPTO_MD5 * context,UCHAR * input_ptr,UINT input_length)208 NX_CRYPTO_KEEP UINT _nx_crypto_md5_update(NX_CRYPTO_MD5 *context, UCHAR *input_ptr, UINT input_length)
209 {
210
211 ULONG current_bytes;
212 ULONG needed_fill_bytes;
213
214
215 /* Determine if the context is non-null. */
216 if (context == NX_CRYPTO_NULL)
217 {
218 return(NX_CRYPTO_PTR_ERROR);
219 }
220
221 /* Determine if there is a length. */
222 if (input_length == 0)
223 {
224 return(NX_CRYPTO_SUCCESS);
225 }
226
227 /* Calculate the current byte count mod 64. Note the reason for the
228 shift by 3 is to account for the 8 bits per byte. */
229 current_bytes = (context -> nx_md5_bit_count[0] >> 3) & 0x3F;
230
231 /* Calculate the current number of bytes needed to be filled. */
232 needed_fill_bytes = 64 - current_bytes;
233
234 /* Update the total bit count based on the input length. */
235 context -> nx_md5_bit_count[0] += (input_length << 3);
236
237 /* Determine if there is roll-over of the bit count into the MSW. */
238 if (context -> nx_md5_bit_count[0] < (input_length << 3))
239 {
240 /* Yes, increment the MSW of the bit count. */
241 context -> nx_md5_bit_count[1]++;
242 }
243
244 /* Update upper total bit count word. */
245 context -> nx_md5_bit_count[1] += (input_length >> 29);
246
247 /* Check for a partial buffer that needs to be transformed. */
248 if ((current_bytes) && (input_length >= needed_fill_bytes))
249 {
250 /* Yes, we can complete the buffer and transform it. */
251
252 /* Copy the appropriate portion of the input buffer into the internal
253 buffer of the context. */
254 NX_CRYPTO_MEMCPY((void *)&(context -> nx_md5_buffer[current_bytes]), (void *)input_ptr, needed_fill_bytes); /* Use case of memcpy is verified. */
255
256 /* Process the 64-byte (512 bit) buffer. */
257 _nx_crypto_md5_process_buffer(context, context -> nx_md5_buffer);
258
259 /* Adjust the pointers and length accordingly. */
260 input_length = input_length - needed_fill_bytes;
261 input_ptr = input_ptr + needed_fill_bytes;
262
263 /* Clear the remaining bits, since the buffer was processed. */
264 current_bytes = 0;
265 }
266
267 /* Process any and all whole blocks of input. */
268 while (input_length >= 64)
269 {
270
271 /* Process this 64-byte (512 bit) buffer. */
272 _nx_crypto_md5_process_buffer(context, input_ptr);
273
274 /* Adjust the pointers and length accordingly. */
275 input_length = input_length - 64;
276 input_ptr = input_ptr + 64;
277 }
278
279 /* Determine if there is anything left. */
280 if (input_length)
281 {
282
283 /* Save the remaining bytes in the internal buffer after any remaining bytes
284 that it is processed later. */
285 NX_CRYPTO_MEMCPY((void *)&(context -> nx_md5_buffer[current_bytes]), (void *)input_ptr, input_length); /* Use case of memcpy is verified. */
286 }
287
288 /* Return success. */
289 return(NX_CRYPTO_SUCCESS);
290 }
291
292
293 /**************************************************************************/
294 /* */
295 /* FUNCTION RELEASE */
296 /* */
297 /* _nx_crypto_md5_digest_calculate PORTABLE C */
298 /* 6.1 */
299 /* AUTHOR */
300 /* */
301 /* Timothy Stapko, Microsoft Corporation */
302 /* */
303 /* DESCRIPTION */
304 /* */
305 /* This function finishes calculation of the MD5 digest. It is called */
306 /* where there is no further input needed for the digest. The resulting*/
307 /* 16-byte (128-bit) MD5 digest is returned to the caller. */
308 /* */
309 /* INPUT */
310 /* */
311 /* context MD5 context pointer */
312 /* digest 16-byte (128-bit) digest */
313 /* */
314 /* OUTPUT */
315 /* */
316 /* status Completion status */
317 /* algorithm Algorithm type */
318 /* */
319 /* CALLS */
320 /* */
321 /* _nx_crypto_md5_update Update the digest with padding*/
322 /* and length of digest */
323 /* */
324 /* CALLED BY */
325 /* */
326 /* _nx_crypto_method_md5_operation Handle MD5 operation */
327 /* */
328 /* RELEASE HISTORY */
329 /* */
330 /* DATE NAME DESCRIPTION */
331 /* */
332 /* 05-19-2020 Timothy Stapko Initial Version 6.0 */
333 /* 09-30-2020 Timothy Stapko Modified comment(s), */
334 /* updated constants, */
335 /* resulting in version 6.1 */
336 /* */
337 /**************************************************************************/
_nx_crypto_md5_digest_calculate(NX_CRYPTO_MD5 * context,UCHAR digest[16],UINT algorithm)338 NX_CRYPTO_KEEP UINT _nx_crypto_md5_digest_calculate(NX_CRYPTO_MD5 *context, UCHAR digest[16], UINT algorithm)
339 {
340
341 UCHAR bit_count_string[8];
342 ULONG current_byte_count;
343 ULONG padding_bytes;
344
345 NX_CRYPTO_PARAMETER_NOT_USED(algorithm);
346
347 /* Move the lower portion of the bit count into the array. */
348 bit_count_string[0] = (UCHAR)context -> nx_md5_bit_count[0];
349 bit_count_string[1] = (UCHAR)(context -> nx_md5_bit_count[0] >> 8);
350 bit_count_string[2] = (UCHAR)(context -> nx_md5_bit_count[0] >> 16);
351 bit_count_string[3] = (UCHAR)(context -> nx_md5_bit_count[0] >> 24);
352 bit_count_string[4] = (UCHAR)context -> nx_md5_bit_count[1];
353 bit_count_string[5] = (UCHAR)(context -> nx_md5_bit_count[1] >> 8);
354 bit_count_string[6] = (UCHAR)(context -> nx_md5_bit_count[1] >> 16);
355 bit_count_string[7] = (UCHAR)(context -> nx_md5_bit_count[1] >> 24);
356
357 /* Calculate the current byte count. */
358 current_byte_count = (context -> nx_md5_bit_count[0] >> 3) & 0x3F;
359
360 /* Calculate the padding bytes needed. */
361 padding_bytes = (current_byte_count < 56) ? (56 - current_byte_count) : (120 - current_byte_count);
362
363 /* Add any padding required. */
364 _nx_crypto_md5_update(context, (UCHAR*)_nx_crypto_md5_padding, padding_bytes);
365
366 /* Add the in the length. */
367 _nx_crypto_md5_update(context, bit_count_string, 8);
368
369 /* Now store the digest in the caller specified destination. */
370 digest[0] = (UCHAR)context -> nx_md5_states[0];
371 digest[1] = (UCHAR)(context -> nx_md5_states[0] >> 8);
372 digest[2] = (UCHAR)(context -> nx_md5_states[0] >> 16);
373 digest[3] = (UCHAR)(context -> nx_md5_states[0] >> 24);
374 digest[4] = (UCHAR)context -> nx_md5_states[1];
375 digest[5] = (UCHAR)(context -> nx_md5_states[1] >> 8);
376 digest[6] = (UCHAR)(context -> nx_md5_states[1] >> 16);
377 digest[7] = (UCHAR)(context -> nx_md5_states[1] >> 24);
378 digest[8] = (UCHAR)context -> nx_md5_states[2];
379 digest[9] = (UCHAR)(context -> nx_md5_states[2] >> 8);
380 digest[10] = (UCHAR)(context -> nx_md5_states[2] >> 16);
381 digest[11] = (UCHAR)(context -> nx_md5_states[2] >> 24);
382 digest[12] = (UCHAR)context -> nx_md5_states[3];
383 digest[13] = (UCHAR)(context -> nx_md5_states[3] >> 8);
384 digest[14] = (UCHAR)(context -> nx_md5_states[3] >> 16);
385 digest[15] = (UCHAR)(context -> nx_md5_states[3] >> 24);
386
387 #ifdef NX_SECURE_KEY_CLEAR
388 NX_CRYPTO_MEMSET(bit_count_string, 0, sizeof(bit_count_string));
389 #endif /* NX_SECURE_KEY_CLEAR */
390
391 /* Return successful completion. */
392 return(NX_CRYPTO_SUCCESS);
393 }
394
395
396 /**************************************************************************/
397 /* */
398 /* FUNCTION RELEASE */
399 /* */
400 /* _nx_crypto_md5_process_buffer PORTABLE C */
401 /* 6.1 */
402 /* AUTHOR */
403 /* */
404 /* Timothy Stapko, Microsoft Corporation */
405 /* */
406 /* DESCRIPTION */
407 /* */
408 /* This function actually uses the MD5 algorithm to process a 64-byte */
409 /* (512 bit) buffer. */
410 /* */
411 /* INPUT */
412 /* */
413 /* context MD5 context pointer */
414 /* buffer 64-byte buffer */
415 /* */
416 /* OUTPUT */
417 /* */
418 /* None */
419 /* */
420 /* CALLS */
421 /* */
422 /* None */
423 /* */
424 /* CALLED BY */
425 /* */
426 /* _nx_crypto_md5_update Update the digest with padding*/
427 /* and length of digest */
428 /* */
429 /* RELEASE HISTORY */
430 /* */
431 /* DATE NAME DESCRIPTION */
432 /* */
433 /* 05-19-2020 Timothy Stapko Initial Version 6.0 */
434 /* 09-30-2020 Timothy Stapko Modified comment(s), */
435 /* resulting in version 6.1 */
436 /* */
437 /**************************************************************************/
_nx_crypto_md5_process_buffer(NX_CRYPTO_MD5 * context,UCHAR buffer[64])438 NX_CRYPTO_KEEP VOID _nx_crypto_md5_process_buffer(NX_CRYPTO_MD5 *context, UCHAR buffer[64])
439 {
440
441 UINT i, j;
442 ULONG a, b, c, d;
443 ULONG x[16];
444
445
446 /* Initialize the state variables. */
447 a = context -> nx_md5_states[0];
448 b = context -> nx_md5_states[1];
449 c = context -> nx_md5_states[2];
450 d = context -> nx_md5_states[3];
451
452 /* Now, setup the x array of ULONGs for fast processing. */
453 j = 0;
454 for (i = 0; i < 16; i++)
455 {
456
457 /* Convert 4 bytes into one 32-bit word. */
458 x[i] = ((ULONG)buffer[j]) | (((ULONG)buffer[j + 1]) << 8) | (((ULONG)buffer[j + 2]) << 16) | (((ULONG)buffer[j + 3]) << 24);
459
460 /* Move to next position in source array. */
461 j = j + 4;
462 }
463
464 /* Process Round 1 of MD5 calculation. */
465 FF(a, b, c, d, x[0], 7, 0xd76aa478UL);
466 FF(d, a, b, c, x[1], 12, 0xe8c7b756UL);
467 FF(c, d, a, b, x[2], 17, 0x242070dbUL);
468 FF(b, c, d, a, x[3], 22, 0xc1bdceeeUL);
469 FF(a, b, c, d, x[4], 7, 0xf57c0fafUL);
470 FF(d, a, b, c, x[5], 12, 0x4787c62aUL);
471 FF(c, d, a, b, x[6], 17, 0xa8304613UL);
472 FF(b, c, d, a, x[7], 22, 0xfd469501UL);
473 FF(a, b, c, d, x[8], 7, 0x698098d8UL);
474 FF(d, a, b, c, x[9], 12, 0x8b44f7afUL);
475 FF(c, d, a, b, x[10], 17, 0xffff5bb1UL);
476 FF(b, c, d, a, x[11], 22, 0x895cd7beUL);
477 FF(a, b, c, d, x[12], 7, 0x6b901122UL);
478 FF(d, a, b, c, x[13], 12, 0xfd987193UL);
479 FF(c, d, a, b, x[14], 17, 0xa679438eUL);
480 FF(b, c, d, a, x[15], 22, 0x49b40821UL);
481
482 /* Process Round 2 of MD5 calculation. */
483 GG(a, b, c, d, x[1], 5, 0xf61e2562UL);
484 GG(d, a, b, c, x[6], 9, 0xc040b340UL);
485 GG(c, d, a, b, x[11], 14, 0x265e5a51UL);
486 GG(b, c, d, a, x[0], 20, 0xe9b6c7aaUL);
487 GG(a, b, c, d, x[5], 5, 0xd62f105dUL);
488 GG(d, a, b, c, x[10], 9, 0x02441453UL);
489 GG(c, d, a, b, x[15], 14, 0xd8a1e681UL);
490 GG(b, c, d, a, x[4], 20, 0xe7d3fbc8UL);
491 GG(a, b, c, d, x[9], 5, 0x21e1cde6UL);
492 GG(d, a, b, c, x[14], 9, 0xc33707d6UL);
493 GG(c, d, a, b, x[3], 14, 0xf4d50d87UL);
494 GG(b, c, d, a, x[8], 20, 0x455a14edUL);
495 GG(a, b, c, d, x[13], 5, 0xa9e3e905UL);
496 GG(d, a, b, c, x[2], 9, 0xfcefa3f8UL);
497 GG(c, d, a, b, x[7], 14, 0x676f02d9UL);
498 GG(b, c, d, a, x[12], 20, 0x8d2a4c8aUL);
499
500 /* Process Round 3 of MD5 calculation. */
501 HH(a, b, c, d, x[5], 4, 0xfffa3942UL);
502 HH(d, a, b, c, x[8], 11, 0x8771f681UL);
503 HH(c, d, a, b, x[11], 16, 0x6d9d6122UL);
504 HH(b, c, d, a, x[14], 23, 0xfde5380cUL);
505 HH(a, b, c, d, x[1], 4, 0xa4beea44UL);
506 HH(d, a, b, c, x[4], 11, 0x4bdecfa9UL);
507 HH(c, d, a, b, x[7], 16, 0xf6bb4b60UL);
508 HH(b, c, d, a, x[10], 23, 0xbebfbc70UL);
509 HH(a, b, c, d, x[13], 4, 0x289b7ec6UL);
510 HH(d, a, b, c, x[0], 11, 0xeaa127faUL);
511 HH(c, d, a, b, x[3], 16, 0xd4ef3085UL);
512 HH(b, c, d, a, x[6], 23, 0x04881d05UL);
513 HH(a, b, c, d, x[9], 4, 0xd9d4d039UL);
514 HH(d, a, b, c, x[12], 11, 0xe6db99e5UL);
515 HH(c, d, a, b, x[15], 16, 0x1fa27cf8UL);
516 HH(b, c, d, a, x[2], 23, 0xc4ac5665UL);
517
518 /* Process Round 4 of MD5 calculation. */
519 II(a, b, c, d, x[0], 6, 0xf4292244UL);
520 II(d, a, b, c, x[7], 10, 0x432aff97UL);
521 II(c, d, a, b, x[14], 15, 0xab9423a7UL);
522 II(b, c, d, a, x[5], 21, 0xfc93a039UL);
523 II(a, b, c, d, x[12], 6, 0x655b59c3UL);
524 II(d, a, b, c, x[3], 10, 0x8f0ccc92UL);
525 II(c, d, a, b, x[10], 15, 0xffeff47dUL);
526 II(b, c, d, a, x[1], 21, 0x85845dd1UL);
527 II(a, b, c, d, x[8], 6, 0x6fa87e4fUL);
528 II(d, a, b, c, x[15], 10, 0xfe2ce6e0UL);
529 II(c, d, a, b, x[6], 15, 0xa3014314UL);
530 II(b, c, d, a, x[13], 21, 0x4e0811a1UL);
531 II(a, b, c, d, x[4], 6, 0xf7537e82UL);
532 II(d, a, b, c, x[11], 10, 0xbd3af235UL);
533 II(c, d, a, b, x[2], 15, 0x2ad7d2bbUL);
534 II(b, c, d, a, x[9], 21, 0xeb86d391UL);
535
536 /* Save the resulting in this MD5 context. */
537 context -> nx_md5_states[0] += a;
538 context -> nx_md5_states[1] += b;
539 context -> nx_md5_states[2] += c;
540 context -> nx_md5_states[3] += d;
541
542 #ifdef NX_SECURE_KEY_CLEAR
543 a = 0; b = 0; c = 0; d = 0;
544 NX_CRYPTO_MEMSET(x, 0, sizeof(x));
545 #endif /* NX_SECURE_KEY_CLEAR */
546 }
547
548
549 /**************************************************************************/
550 /* */
551 /* FUNCTION RELEASE */
552 /* */
553 /* _nx_crypto_method_md5_init PORTABLE C */
554 /* 6.1 */
555 /* AUTHOR */
556 /* */
557 /* Timothy Stapko, Microsoft Corporation */
558 /* */
559 /* DESCRIPTION */
560 /* */
561 /* This function is the common crypto method init callback for */
562 /* Microsoft supported MD5 cryptographic algorithm. */
563 /* */
564 /* INPUT */
565 /* */
566 /* method Pointer to crypto method */
567 /* key Pointer to key */
568 /* key_size_in_bits Length of key size in bits */
569 /* handler Returned crypto handler */
570 /* crypto_metadata Metadata area */
571 /* crypto_metadata_size Size of the metadata area */
572 /* */
573 /* OUTPUT */
574 /* */
575 /* status Completion status */
576 /* */
577 /* CALLS */
578 /* */
579 /* None */
580 /* */
581 /* CALLED BY */
582 /* */
583 /* Application Code */
584 /* */
585 /* RELEASE HISTORY */
586 /* */
587 /* DATE NAME DESCRIPTION */
588 /* */
589 /* 05-19-2020 Timothy Stapko Initial Version 6.0 */
590 /* 09-30-2020 Timothy Stapko Modified comment(s), */
591 /* resulting in version 6.1 */
592 /* */
593 /**************************************************************************/
_nx_crypto_method_md5_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)594 NX_CRYPTO_KEEP UINT _nx_crypto_method_md5_init(struct NX_CRYPTO_METHOD_STRUCT *method,
595 UCHAR *key, NX_CRYPTO_KEY_SIZE key_size_in_bits,
596 VOID **handle,
597 VOID *crypto_metadata,
598 ULONG crypto_metadata_size)
599 {
600
601 NX_CRYPTO_PARAMETER_NOT_USED(key);
602 NX_CRYPTO_PARAMETER_NOT_USED(key_size_in_bits);
603 NX_CRYPTO_PARAMETER_NOT_USED(handle);
604
605 NX_CRYPTO_STATE_CHECK
606
607 if (method == NX_CRYPTO_NULL)
608 {
609 return(NX_CRYPTO_PTR_ERROR);
610 }
611
612 if (crypto_metadata == NX_CRYPTO_NULL)
613 {
614
615 /* metadata is not passed by IPsec. */
616 #ifndef NX_IPSEC_ENABLE
617 return(NX_CRYPTO_PTR_ERROR);
618 #endif
619 }
620 else if (((((ULONG)crypto_metadata) & 0x3) != 0) || (crypto_metadata_size < sizeof(NX_CRYPTO_MD5)))
621 {
622 return(NX_CRYPTO_PTR_ERROR);
623 }
624
625 return(NX_CRYPTO_SUCCESS);
626 }
627
628
629 /**************************************************************************/
630 /* */
631 /* FUNCTION RELEASE */
632 /* */
633 /* _nx_crypto_method_md5_cleanup PORTABLE C */
634 /* 6.1 */
635 /* AUTHOR */
636 /* */
637 /* Timothy Stapko, Microsoft Corporation */
638 /* */
639 /* DESCRIPTION */
640 /* */
641 /* This function cleans up the crypto metadata. */
642 /* */
643 /* INPUT */
644 /* */
645 /* crypto_metadata Crypto metadata */
646 /* */
647 /* OUTPUT */
648 /* */
649 /* status Completion status */
650 /* */
651 /* CALLS */
652 /* */
653 /* NX_CRYPTO_MEMSET Set the memory */
654 /* */
655 /* CALLED BY */
656 /* */
657 /* Application Code */
658 /* */
659 /* RELEASE HISTORY */
660 /* */
661 /* DATE NAME DESCRIPTION */
662 /* */
663 /* 05-19-2020 Timothy Stapko Initial Version 6.0 */
664 /* 09-30-2020 Timothy Stapko Modified comment(s), */
665 /* resulting in version 6.1 */
666 /* */
667 /**************************************************************************/
_nx_crypto_method_md5_cleanup(VOID * crypto_metadata)668 NX_CRYPTO_KEEP UINT _nx_crypto_method_md5_cleanup(VOID *crypto_metadata)
669 {
670
671 NX_CRYPTO_STATE_CHECK
672
673 #ifdef NX_SECURE_KEY_CLEAR
674 if (!crypto_metadata)
675 return (NX_CRYPTO_SUCCESS);
676
677 /* Clean up the crypto metadata. */
678 NX_CRYPTO_MEMSET(crypto_metadata, 0, sizeof(NX_CRYPTO_MD5));
679 #else
680 NX_CRYPTO_PARAMETER_NOT_USED(crypto_metadata);
681 #endif/* NX_SECURE_KEY_CLEAR */
682
683 return(NX_CRYPTO_SUCCESS);
684 }
685
686
687 /**************************************************************************/
688 /* */
689 /* FUNCTION RELEASE */
690 /* */
691 /* _nx_crypto_method_md5_operation PORTABLE C */
692 /* 6.3.0 */
693 /* AUTHOR */
694 /* */
695 /* Timothy Stapko, Microsoft Corporation */
696 /* */
697 /* DESCRIPTION */
698 /* */
699 /* This function encrypts and decrypts a message using */
700 /* the MD5 algorithm. */
701 /* */
702 /* INPUT */
703 /* */
704 /* op MD5 operation */
705 /* handle Crypto handle */
706 /* method Cryption Method Object */
707 /* key Encryption Key */
708 /* key_size_in_bits Key size in bits */
709 /* input Input data */
710 /* input_length_in_byte Input data size */
711 /* iv_ptr Initial vector */
712 /* output Output buffer */
713 /* output_length_in_byte Output buffer size */
714 /* crypto_metadata Metadata area */
715 /* crypto_metadata_size Metadata area size */
716 /* packet_ptr Pointer to packet */
717 /* nx_crypto_hw_process_callback Callback function pointer */
718 /* */
719 /* OUTPUT */
720 /* */
721 /* status Completion status */
722 /* */
723 /* CALLS */
724 /* */
725 /* _nx_crypto_md5_initialize Initialize the MD5 context */
726 /* _nx_crypto_md5_update Update the digest with padding*/
727 /* and length of digest */
728 /* _nx_crypto_md5_digest_calculate Perform calculation of the */
729 /* MD5 digest */
730 /* */
731 /* CALLED BY */
732 /* */
733 /* Application Code */
734 /* */
735 /* RELEASE HISTORY */
736 /* */
737 /* DATE NAME DESCRIPTION */
738 /* */
739 /* 05-19-2020 Timothy Stapko Initial Version 6.0 */
740 /* 09-30-2020 Timothy Stapko Modified comment(s), */
741 /* resulting in version 6.1 */
742 /* 10-31-2023 Yanwu Cai Modified comment(s), */
743 /* resulting in version 6.3.0 */
744 /* */
745 /**************************************************************************/
_nx_crypto_method_md5_operation(UINT op,VOID * handle,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))746 NX_CRYPTO_KEEP UINT _nx_crypto_method_md5_operation(UINT op, /* Encrypt, Decrypt, Authenticate */
747 VOID *handle, /* Crypto handler */
748 struct NX_CRYPTO_METHOD_STRUCT *method,
749 UCHAR *key,
750 NX_CRYPTO_KEY_SIZE key_size_in_bits,
751 UCHAR *input,
752 ULONG input_length_in_byte,
753 UCHAR *iv_ptr,
754 UCHAR *output,
755 ULONG output_length_in_byte,
756 VOID *crypto_metadata,
757 ULONG crypto_metadata_size,
758 VOID *packet_ptr,
759 VOID (*nx_crypto_hw_process_callback)(VOID *packet_ptr, UINT status))
760 {
761 NX_CRYPTO_MD5 *ctx = (NX_CRYPTO_MD5 *)crypto_metadata;
762 #ifdef NX_IPSEC_ENABLE
763 NX_CRYPTO_MD5 metadata;
764 #endif
765
766 NX_CRYPTO_PARAMETER_NOT_USED(handle);
767 NX_CRYPTO_PARAMETER_NOT_USED(key);
768 NX_CRYPTO_PARAMETER_NOT_USED(key_size_in_bits);
769 NX_CRYPTO_PARAMETER_NOT_USED(iv_ptr);
770 NX_CRYPTO_PARAMETER_NOT_USED(packet_ptr);
771 NX_CRYPTO_PARAMETER_NOT_USED(nx_crypto_hw_process_callback);
772
773 NX_CRYPTO_STATE_CHECK
774
775 if (method == NX_CRYPTO_NULL)
776 {
777 return(NX_CRYPTO_PTR_ERROR);
778 }
779
780 /* Verify the metadata address is 4-byte aligned. */
781 if (crypto_metadata == NX_CRYPTO_NULL)
782 {
783 #ifdef NX_IPSEC_ENABLE
784 /* metadata is not passed by IPsec. */
785 ctx = &metadata;
786 #else
787 return(NX_CRYPTO_PTR_ERROR);
788 #endif
789 }
790 else if (((((ULONG)crypto_metadata) & 0x3) != 0) || (crypto_metadata_size < sizeof(NX_CRYPTO_MD5)))
791 {
792 return(NX_CRYPTO_PTR_ERROR);
793 }
794
795 switch (op)
796 {
797 case NX_CRYPTO_HASH_INITIALIZE:
798 _nx_crypto_md5_initialize(ctx, method -> nx_crypto_algorithm);
799 break;
800
801 case NX_CRYPTO_HASH_UPDATE:
802 _nx_crypto_md5_update(ctx, input, input_length_in_byte);
803 break;
804
805 case NX_CRYPTO_HASH_CALCULATE:
806 if(output_length_in_byte < 16)
807 return(NX_CRYPTO_INVALID_BUFFER_SIZE);
808 _nx_crypto_md5_digest_calculate(ctx, output, method -> nx_crypto_algorithm);
809 break;
810
811 default:
812 if(output_length_in_byte < 16)
813 return(NX_CRYPTO_INVALID_BUFFER_SIZE);
814 _nx_crypto_md5_initialize(ctx, method -> nx_crypto_algorithm);
815 _nx_crypto_md5_update(ctx, input, input_length_in_byte);
816 _nx_crypto_md5_digest_calculate(ctx, output, method -> nx_crypto_algorithm);
817 #if defined(NX_SECURE_KEY_CLEAR) && defined(NX_IPSEC_ENABLE)
818 if (crypto_metadata == NX_CRYPTO_NULL)
819 {
820 memset(ctx, 0, sizeof(NX_CRYPTO_MD5));
821 }
822 #endif
823 break;
824 }
825
826 return NX_CRYPTO_SUCCESS;
827 }
828
829