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