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) The Internet Society (2001). All Rights Reserved.
15
16 This document and translations of it may be copied and furnished to
17 others, and derivative works that comment on or otherwise explain it
18 or assist in its implementation may be prepared, copied, published
19 and distributed, in whole or in part, without restriction of any
20 kind, provided that the above copyright notice and this paragraph are
21 included on all such copies and derivative works. However, this
22 document itself may not be modified in any way, such as by removing
23 the copyright notice or references to the Internet Society or other
24 Internet organizations, except as needed for the purpose of
25 developing Internet standards in which case the procedures for
26 copyrights defined in the Internet Standards process must be
27 followed, or as required to translate it into languages other than
28 English.
29
30 The limited permissions granted above are perpetual and will not be
31 revoked by the Internet Society or its successors or assigns.
32
33 This document and the information contained herein is provided on an
34 ""AS IS"" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
35 TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
36 BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
37 HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
38 MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
39 */
40 /**************************************************************************/
41
42
43 /**************************************************************************/
44 /**************************************************************************/
45 /** */
46 /** NetX Component */
47 /** */
48 /** SHA1 Digest Algorithm (SHA1) */
49 /** */
50 /**************************************************************************/
51 /**************************************************************************/
52
53 #include "nx_api.h"
54 #include "nx_sha1.h"
55
56 /* Define macros for the SHA1 transform function. */
57
58 /* Define the SHA1 basic F1, F2, F3, and F4 functions. */
59
60 #define F1(x, y, z) (((x) & (y)) | ((~x) & (z)))
61 #define F2(x, y, z) ((x) ^ (y) ^ (z))
62 #define F3(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z)))
63 #define F4(x, y, z) ((x) ^ (y) ^ (z))
64
65
66 /* Define the SHA1 left shift circular function. */
67
68 #define LEFT_SHIFT_CIRCULAR(x, n) (((x) << (n)) | ((x) >> (32-(n))))
69
70
71 /* Define the padding array. This is used to pad the message such that its length is
72 64 bits shy of being a multiple of 512 bits long. */
73
74 static UCHAR _nx_sha1_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};
75
76
77 /**************************************************************************/
78 /* */
79 /* FUNCTION RELEASE */
80 /* */
81 /* _nx_sha1_initialize PORTABLE C */
82 /* 6.1 */
83 /* AUTHOR */
84 /* */
85 /* Yuxin Zhou, Microsoft Corporation */
86 /* */
87 /* DESCRIPTION */
88 /* */
89 /* This function initializes the SHA1 context. It must be called prior */
90 /* to creating the SHA1 digest. */
91 /* */
92 /* INPUT */
93 /* */
94 /* context SHA1 context pointer */
95 /* */
96 /* OUTPUT */
97 /* */
98 /* status Completion status */
99 /* */
100 /* CALLS */
101 /* */
102 /* None */
103 /* */
104 /* CALLED BY */
105 /* */
106 /* NetX Applications */
107 /* */
108 /* RELEASE HISTORY */
109 /* */
110 /* DATE NAME DESCRIPTION */
111 /* */
112 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
113 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
114 /* resulting in version 6.1 */
115 /* */
116 /**************************************************************************/
_nx_sha1_initialize(NX_SHA1 * context)117 UINT _nx_sha1_initialize(NX_SHA1 *context)
118 {
119
120 /* Determine if the context is non-null. */
121 if (context == NX_NULL)
122 return(NX_PTR_ERROR);
123
124 /* First, clear the bit count for this context. */
125 context -> nx_sha1_bit_count[0] = 0; /* Clear the lower 32-bits of the count */
126 context -> nx_sha1_bit_count[1] = 0; /* Clear the upper 32-bits of the count */
127
128 /* Finally, setup the context states. */
129 context -> nx_sha1_states[0] = 0x67452301UL; /* Setup state A */
130 context -> nx_sha1_states[1] = 0xEFCDAB89UL; /* Setup state B */
131 context -> nx_sha1_states[2] = 0x98BADCFEUL; /* Setup state C */
132 context -> nx_sha1_states[3] = 0x10325476UL; /* Setup state D */
133 context -> nx_sha1_states[4] = 0xC3D2E1F0UL; /* Setup state E */
134
135 /* Return success. */
136 return(NX_SUCCESS);
137 }
138
139
140 /**************************************************************************/
141 /* */
142 /* FUNCTION RELEASE */
143 /* */
144 /* _nx_sha1_update PORTABLE C */
145 /* 6.1 */
146 /* AUTHOR */
147 /* */
148 /* Yuxin Zhou, Microsoft Corporation */
149 /* */
150 /* DESCRIPTION */
151 /* */
152 /* This function updates the digest calculation with new input from */
153 /* the caller. */
154 /* */
155 /* INPUT */
156 /* */
157 /* context SHA1 context pointer */
158 /* input_ptr Pointer to byte(s) of input */
159 /* input_length Length of bytes of input */
160 /* */
161 /* OUTPUT */
162 /* */
163 /* status Completion status */
164 /* */
165 /* CALLS */
166 /* */
167 /* _nx_sha1_process_buffer Process complete buffer, */
168 /* which is 64-bytes in size */
169 /* */
170 /* CALLED BY */
171 /* */
172 /* NetX Applications */
173 /* */
174 /* RELEASE HISTORY */
175 /* */
176 /* DATE NAME DESCRIPTION */
177 /* */
178 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
179 /* 09-30-2020 Yuxin Zhou Modified comment(s), and */
180 /* verified memcpy use cases, */
181 /* resulting in version 6.1 */
182 /* */
183 /**************************************************************************/
_nx_sha1_update(NX_SHA1 * context,UCHAR * input_ptr,UINT input_length)184 UINT _nx_sha1_update(NX_SHA1 *context, UCHAR *input_ptr, UINT input_length)
185 {
186
187 ULONG current_bytes;
188 ULONG needed_fill_bytes;
189
190
191 /* Determine if the context is non-null. */
192 if (context == NX_NULL)
193 return(NX_PTR_ERROR);
194
195 /* Determine if there is a length. */
196 if (input_length == 0)
197 return(NX_SUCCESS);
198
199 /* Calculate the current byte count mod 64. Note the reason for the
200 shift by 3 is to account for the 8 bits per byte. */
201 current_bytes = (context -> nx_sha1_bit_count[0] >> 3) & 0x3F;
202
203 /* Calculate the current number of bytes needed to be filled. */
204 needed_fill_bytes = 64 - current_bytes;
205
206 /* Update the total bit count based on the input length. */
207 context -> nx_sha1_bit_count[0] += (input_length << 3);
208
209 /* Determine if there is roll-over of the bit count into the MSW. */
210 if (context -> nx_sha1_bit_count[0] < (input_length << 3))
211 {
212
213 /* Yes, increment the MSW of the bit count. */
214 context -> nx_sha1_bit_count[1]++;
215 }
216
217 /* Update upper total bit count word. */
218 context -> nx_sha1_bit_count[1] += (input_length >> 29);
219
220 /* Check for a partial buffer that needs to be transformed. */
221 if ((current_bytes) && (input_length >= needed_fill_bytes))
222 {
223
224 /* Yes, we can complete the buffer and transform it. */
225
226 /* Copy the appropriate portion of the input buffer into the internal
227 buffer of the context. */
228 memcpy((void *) &(context -> nx_sha1_buffer[current_bytes]), (void *) input_ptr, needed_fill_bytes); /* Use case of memcpy is verified. */
229
230 /* Process the 64-byte (512 bit) buffer. */
231 _nx_sha1_process_buffer(context, context -> nx_sha1_buffer);
232
233 /* Adjust the pointers and length accordingly. */
234 input_length = input_length - needed_fill_bytes;
235 input_ptr = input_ptr + needed_fill_bytes;
236
237 /* Clear the remaining bits, since the buffer was processed. */
238 current_bytes = 0;
239 }
240
241 /* Process any and all whole blocks of input. */
242 while (input_length >= 64)
243 {
244
245 /* Process this 64-byte (512 bit) buffer. */
246 _nx_sha1_process_buffer(context, input_ptr);
247
248 /* Adjust the pointers and length accordingly. */
249 input_length = input_length - 64;
250 input_ptr = input_ptr + 64;
251 }
252
253 /* Determine if there is anything left. */
254 if (input_length)
255 {
256
257 /* Save the remaining bytes in the internal buffer after any remaining bytes
258 that it is processed later. */
259 memcpy((void *) &(context -> nx_sha1_buffer[current_bytes]), (void *) input_ptr, input_length); /* Use case of memcpy is verified. */
260 }
261
262 /* Return success. */
263 return(NX_SUCCESS);
264 }
265
266
267 /**************************************************************************/
268 /* */
269 /* FUNCTION RELEASE */
270 /* */
271 /* _nx_sha1_digest_calculate PORTABLE C */
272 /* 6.1 */
273 /* AUTHOR */
274 /* */
275 /* Yuxin Zhou, Microsoft Corporation */
276 /* */
277 /* DESCRIPTION */
278 /* */
279 /* This function finishes calculation of the SHA1 digest. It is called */
280 /* where there is no further input needed for the digest. The resulting*/
281 /* 20-byte (160-bit) SHA1 digest is returned to the caller. */
282 /* */
283 /* INPUT */
284 /* */
285 /* context SHA1 context pointer */
286 /* digest Pointer to return digest in */
287 /* */
288 /* OUTPUT */
289 /* */
290 /* status Completion status */
291 /* */
292 /* CALLS */
293 /* */
294 /* _nx_sha1_update Update the digest with padding*/
295 /* and length of digest */
296 /* */
297 /* CALLED BY */
298 /* */
299 /* NetX Applications */
300 /* */
301 /* RELEASE HISTORY */
302 /* */
303 /* DATE NAME DESCRIPTION */
304 /* */
305 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
306 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
307 /* resulting in version 6.1 */
308 /* */
309 /**************************************************************************/
_nx_sha1_digest_calculate(NX_SHA1 * context,UCHAR digest[20])310 UINT _nx_sha1_digest_calculate(NX_SHA1 *context, UCHAR digest[20])
311 {
312
313 UCHAR bit_count_string[8];
314 ULONG current_byte_count;
315 ULONG padding_bytes;
316
317
318 /* Move the lower portion of the bit count into the array. */
319 bit_count_string[0] = (UCHAR) (context -> nx_sha1_bit_count[1] >> 24);
320 bit_count_string[1] = (UCHAR) (context -> nx_sha1_bit_count[1] >> 16);
321 bit_count_string[2] = (UCHAR) (context -> nx_sha1_bit_count[1] >> 8);
322 bit_count_string[3] = (UCHAR) (context -> nx_sha1_bit_count[1]);
323 bit_count_string[4] = (UCHAR) (context -> nx_sha1_bit_count[0] >> 24);
324 bit_count_string[5] = (UCHAR) (context -> nx_sha1_bit_count[0] >> 16);
325 bit_count_string[6] = (UCHAR) (context -> nx_sha1_bit_count[0] >> 8);
326 bit_count_string[7] = (UCHAR) (context -> nx_sha1_bit_count[0]);
327
328 /* Calculate the current byte count. */
329 current_byte_count = (context -> nx_sha1_bit_count[0] >> 3) & 0x3F;
330
331 /* Calculate the padding bytes needed. */
332 padding_bytes = (current_byte_count < 56) ? (56 - current_byte_count) : (120 - current_byte_count);
333
334 /* Add any padding required. */
335 _nx_sha1_update(context, _nx_sha1_padding, padding_bytes);
336
337 /* Add the in the length. */
338 _nx_sha1_update(context, bit_count_string, 8);
339
340 /* Now store the digest in the caller specified destination. */
341 digest[ 0] = (UCHAR) (context -> nx_sha1_states[0] >> 24);
342 digest[ 1] = (UCHAR) (context -> nx_sha1_states[0] >> 16);
343 digest[ 2] = (UCHAR) (context -> nx_sha1_states[0] >> 8);
344 digest[ 3] = (UCHAR) (context -> nx_sha1_states[0]);
345 digest[ 4] = (UCHAR) (context -> nx_sha1_states[1] >> 24);
346 digest[ 5] = (UCHAR) (context -> nx_sha1_states[1] >> 16);
347 digest[ 6] = (UCHAR) (context -> nx_sha1_states[1] >> 8);
348 digest[ 7] = (UCHAR) (context -> nx_sha1_states[1]);
349 digest[ 8] = (UCHAR) (context -> nx_sha1_states[2] >> 24);
350 digest[ 9] = (UCHAR) (context -> nx_sha1_states[2] >> 16);
351 digest[10] = (UCHAR) (context -> nx_sha1_states[2] >> 8);
352 digest[11] = (UCHAR) (context -> nx_sha1_states[2]);
353 digest[12] = (UCHAR) (context -> nx_sha1_states[3] >> 24);
354 digest[13] = (UCHAR) (context -> nx_sha1_states[3] >> 16);
355 digest[14] = (UCHAR) (context -> nx_sha1_states[3] >> 8);
356 digest[15] = (UCHAR) (context -> nx_sha1_states[3]);
357 digest[16] = (UCHAR) (context -> nx_sha1_states[4] >> 24);
358 digest[17] = (UCHAR) (context -> nx_sha1_states[4] >> 16);
359 digest[18] = (UCHAR) (context -> nx_sha1_states[4] >> 8);
360 digest[19] = (UCHAR) (context -> nx_sha1_states[4]);
361
362 /* Return successful completion. */
363 return(NX_SUCCESS);
364 }
365
366
367 /**************************************************************************/
368 /* */
369 /* FUNCTION RELEASE */
370 /* */
371 /* _nx_sha1_process_buffer PORTABLE C */
372 /* 6.1 */
373 /* AUTHOR */
374 /* */
375 /* Yuxin Zhou, Microsoft Corporation */
376 /* */
377 /* DESCRIPTION */
378 /* */
379 /* This function actually uses the SHA1 algorithm to process a 64-byte */
380 /* (512 bit) buffer. */
381 /* */
382 /* INPUT */
383 /* */
384 /* context SHA1 context pointer */
385 /* buffer Pointer to 64-byte buffer */
386 /* */
387 /* OUTPUT */
388 /* */
389 /* status Completion status */
390 /* */
391 /* CALLS */
392 /* */
393 /* None */
394 /* */
395 /* CALLED BY */
396 /* */
397 /* NetX Applications */
398 /* */
399 /* RELEASE HISTORY */
400 /* */
401 /* DATE NAME DESCRIPTION */
402 /* */
403 /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
404 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
405 /* resulting in version 6.1 */
406 /* */
407 /**************************************************************************/
_nx_sha1_process_buffer(NX_SHA1 * context,UCHAR buffer[64])408 VOID _nx_sha1_process_buffer(NX_SHA1 *context, UCHAR buffer[64])
409 {
410
411 ULONG *w;
412 UINT t;
413 ULONG temp;
414 ULONG a, b, c, d, e;
415
416
417 /* Setup pointers to the word array. */
418 w = context -> nx_sha1_word_array;
419
420 /* Initialize the first 16 words of the word array, taking care of the
421 endian issues at the same time. */
422 for (t = 0; t < 16; t++)
423 {
424
425 /* Setup each entry. */
426 w[t] = (((ULONG) buffer[t * 4]) << 24) | (((ULONG) buffer[(t * 4) + 1]) << 16) | (((ULONG) buffer[(t * 4) + 2]) << 8) | ((ULONG) buffer[(t * 4) + 3]);
427 }
428
429 /* Setup the remaining entries of the word array. */
430 for (t = 16; t < 80; t++)
431 {
432
433 /* Setup each entry. */
434 w[t] = LEFT_SHIFT_CIRCULAR((w[t-3] ^ w[t-8] ^ w[t-14] ^ w[t-16]), 1);
435 }
436
437 /* Initialize the state variables. */
438 a = context -> nx_sha1_states[0];
439 b = context -> nx_sha1_states[1];
440 c = context -> nx_sha1_states[2];
441 d = context -> nx_sha1_states[3];
442 e = context -> nx_sha1_states[4];
443
444 /* Now, perform Round 1 operations. */
445 for (t = 0; t < 20; t++)
446 {
447
448 /* Compute round 1 (t = 0 through t = 19). */
449 temp = LEFT_SHIFT_CIRCULAR(a, 5) + F1(b, c, d) + e + w[t] + 0x5A827999UL;
450 e = d;
451 d = c;
452 c = LEFT_SHIFT_CIRCULAR(b, 30);
453 b = a;
454 a = temp;
455 }
456
457 /* Now, perform Round 2 operations. */
458 for (t = 20; t < 40; t++)
459 {
460
461 /* Compute round 2 (t = 20 through t = 39). */
462 temp = LEFT_SHIFT_CIRCULAR(a, 5) + F2(b, c, d) + e + w[t] + 0x6ED9EBA1UL;
463 e = d;
464 d = c;
465 c = LEFT_SHIFT_CIRCULAR(b, 30);
466 b = a;
467 a = temp;
468 }
469
470 /* Now, perform Round 3 operations. */
471 for (t = 40; t < 60; t++)
472 {
473
474 /* Compute round 3 (t = 40 through t = 59). */
475 temp = LEFT_SHIFT_CIRCULAR(a, 5) + F3(b, c, d) + e + w[t] + 0x8F1BBCDCUL;
476 e = d;
477 d = c;
478 c = LEFT_SHIFT_CIRCULAR(b, 30);
479 b = a;
480 a = temp;
481 }
482
483 /* Finally, perform Round 4 operations. */
484 for (t = 60; t < 80; t++)
485 {
486
487 /* Compute round 4 (t = 60 through t = 79). */
488 temp = LEFT_SHIFT_CIRCULAR(a, 5) + F4(b, c, d) + e + w[t] + 0xCA62C1D6UL;
489 e = d;
490 d = c;
491 c = LEFT_SHIFT_CIRCULAR(b, 30);
492 b = a;
493 a = temp;
494 }
495
496 /* Save the resulting in this SHA1 context. */
497 context -> nx_sha1_states[0] += a;
498 context -> nx_sha1_states[1] += b;
499 context -> nx_sha1_states[2] += c;
500 context -> nx_sha1_states[3] += d;
501 context -> nx_sha1_states[4] += e;
502 }
503
504