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