1 /***************************************************************************
2  * Copyright (c) 2024 Microsoft Corporation
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the MIT License which is available at
6  * https://opensource.org/licenses/MIT.
7  *
8  * SPDX-License-Identifier: MIT
9  **************************************************************************/
10 
11 
12 /**************************************************************************/
13 /**************************************************************************/
14 /**                                                                       */
15 /** NetX Crypto Component                                                 */
16 /**                                                                       */
17 /**   SHA-256 Digest Algorithm (SHA2)                                     */
18 /**                                                                       */
19 /**************************************************************************/
20 /**************************************************************************/
21 
22 #include "nx_crypto_sha2.h"
23 
24 /* Constants used in the SHA-256 digest calculation. */
25 const ULONG _sha2_round_constants[64] =
26 {
27     0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
28     0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
29     0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
30     0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
31     0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
32     0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
33     0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
34     0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
35 };
36 
37 
38 /* Define the SHA2 logic functions.  */
39 #define CH_FUNC(x, y, z)           (((x) & (y)) ^ ((~(x)) & (z)))
40 #define MAJ_FUNC(x, y, z)          (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)))
41 
42 #define RIGHT_SHIFT_CIRCULAR(x, n) (((x) >> (n)) | ((x) << (32 - (n))))
43 #define LARGE_SIGMA_0(x)           (RIGHT_SHIFT_CIRCULAR((x),  2) ^ RIGHT_SHIFT_CIRCULAR((x), 13) ^ RIGHT_SHIFT_CIRCULAR((x), 22))
44 #define LARGE_SIGMA_1(x)           (RIGHT_SHIFT_CIRCULAR((x),  6) ^ RIGHT_SHIFT_CIRCULAR((x), 11) ^ RIGHT_SHIFT_CIRCULAR((x), 25))
45 #define SMALL_SIGMA_0(x)           (RIGHT_SHIFT_CIRCULAR((x),  7) ^ RIGHT_SHIFT_CIRCULAR((x), 18) ^ ((x) >> 3))
46 #define SMALL_SIGMA_1(x)           (RIGHT_SHIFT_CIRCULAR((x), 17) ^ RIGHT_SHIFT_CIRCULAR((x), 19) ^ ((x) >> 10))
47 
48 #define W0(t) ((((ULONG)buffer[(t) * 4]) << 24) | (((ULONG)buffer[((t) * 4) + 1]) << 16) | (((ULONG)buffer[((t) * 4) + 2]) << 8) | ((ULONG)buffer[((t) * 4) + 3]))
49 #define W16(t) (SMALL_SIGMA_1(w[(t) - 2]) + w[(t) - 7] + SMALL_SIGMA_0(w[(t) - 15]) + w[(t) - 16])
50 
51 /* Define the padding array.  This is used to pad the message such that its length is
52    64 bits shy of being a multiple of 512 bits long.  */
53 const UCHAR   _nx_crypto_sha256_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};
54 
55 
56 /**************************************************************************/
57 /*                                                                        */
58 /*  FUNCTION                                               RELEASE        */
59 /*                                                                        */
60 /*    _nx_crypto_sha256_initialize                        PORTABLE C      */
61 /*                                                           6.1          */
62 /*                                                                        */
63 /*  AUTHOR                                                                */
64 /*                                                                        */
65 /*    Timothy Stapko, Microsoft Corporation                               */
66 /*                                                                        */
67 /*  DESCRIPTION                                                           */
68 /*                                                                        */
69 /*    This function initializes the SHA256 context. It must be called     */
70 /*    prior to creating a SHA256 digest.                                  */
71 /*                                                                        */
72 /*  INPUT                                                                 */
73 /*                                                                        */
74 /*    context                               SHA256 context pointer        */
75 /*                                                                        */
76 /*  OUTPUT                                                                */
77 /*                                                                        */
78 /*    status                                Completion status             */
79 /*                                                                        */
80 /*  CALLS                                                                 */
81 /*                                                                        */
82 /*    None                                                                */
83 /*                                                                        */
84 /*  CALLED BY                                                             */
85 /*                                                                        */
86 /*    _nx_crypto_method_sha256_operation    Handle SHA256 operation       */
87 /*                                                                        */
88 /*  RELEASE HISTORY                                                       */
89 /*                                                                        */
90 /*    DATE              NAME                      DESCRIPTION             */
91 /*                                                                        */
92 /*  05-19-2020     Timothy Stapko           Initial Version 6.0           */
93 /*  09-30-2020     Timothy Stapko           Modified comment(s),          */
94 /*                                            resulting in version 6.1    */
95 /*                                                                        */
96 /**************************************************************************/
_nx_crypto_sha256_initialize(NX_CRYPTO_SHA256 * context,UINT algorithm)97 NX_CRYPTO_KEEP UINT  _nx_crypto_sha256_initialize(NX_CRYPTO_SHA256 *context, UINT algorithm )
98 {
99     /* Determine if the context is non-null.  */
100     if (context == NX_CRYPTO_NULL)
101     {
102         return(NX_CRYPTO_PTR_ERROR);
103     }
104 
105     /* First, clear the bit count for this context.  */
106     context -> nx_sha256_bit_count[0] =  0;                   /* Clear the lower 32-bits of the count.*/
107     context -> nx_sha256_bit_count[1] =  0;                   /* Clear the upper 32-bits of the count.*/
108 
109     if ((algorithm == NX_CRYPTO_AUTHENTICATION_HMAC_SHA2_256) ||
110         (algorithm == NX_CRYPTO_HASH_SHA256))
111     {
112 
113         /* Initialize SHA-256 state. */
114         context -> nx_sha256_states[0] = 0x6a09e667; /* A H0 */
115         context -> nx_sha256_states[1] = 0xbb67ae85; /* B H1 */
116         context -> nx_sha256_states[2] = 0x3c6ef372; /* C H2 */
117         context -> nx_sha256_states[3] = 0xa54ff53a; /* D H3 */
118         context -> nx_sha256_states[4] = 0x510e527f; /* E H4 */
119         context -> nx_sha256_states[5] = 0x9b05688c; /* F H5 */
120         context -> nx_sha256_states[6] = 0x1f83d9ab; /* G H6 */
121         context -> nx_sha256_states[7] = 0x5be0cd19; /* H H7 */
122     }
123     else
124     {
125 
126         /* Initialize SHA-224 state. */
127         context -> nx_sha256_states[0] = 0xc1059ed8; /* A H0 */
128         context -> nx_sha256_states[1] = 0x367cd507; /* B H1 */
129         context -> nx_sha256_states[2] = 0x3070dd17; /* C H2 */
130         context -> nx_sha256_states[3] = 0xf70e5939; /* D H3 */
131         context -> nx_sha256_states[4] = 0xffc00b31; /* E H4 */
132         context -> nx_sha256_states[5] = 0x68581511; /* F H5 */
133         context -> nx_sha256_states[6] = 0x64f98fa7; /* G H6 */
134         context -> nx_sha256_states[7] = 0xbefa4fa4; /* H H7 */
135     }
136 
137     /* Return success.  */
138     return(NX_CRYPTO_SUCCESS);
139 }
140 
141 
142 /**************************************************************************/
143 /*                                                                        */
144 /*  FUNCTION                                               RELEASE        */
145 /*                                                                        */
146 /*    _nx_crypto_sha256_update                            PORTABLE C      */
147 /*                                                           6.1          */
148 /*                                                                        */
149 /*  AUTHOR                                                                */
150 /*                                                                        */
151 /*    Timothy Stapko, Microsoft Corporation                               */
152 /*                                                                        */
153 /*  DESCRIPTION                                                           */
154 /*                                                                        */
155 /*    This function updates the SHA256 digest with new input from the     */
156 /*    caller.                                                             */
157 /*                                                                        */
158 /*  INPUT                                                                 */
159 /*                                                                        */
160 /*    context                               SHA256 context pointer        */
161 /*    input_ptr                             Pointer to input data         */
162 /*    input_length                          Number of bytes in input      */
163 /*                                                                        */
164 /*  OUTPUT                                                                */
165 /*                                                                        */
166 /*    status                                Completion status             */
167 /*                                                                        */
168 /*  CALLS                                                                 */
169 /*                                                                        */
170 /*    _nx_crypto_sha256_process_buffer      Process complete buffer       */
171 /*                                            using SHA256                */
172 /*                                                                        */
173 /*  CALLED BY                                                             */
174 /*                                                                        */
175 /*    _nx_crypto_sha256_digest_calculate   Calculate the SHA256 digest    */
176 /*    _nx_crypto_method_sha256_operation   Handle SHA256 operation        */
177 /*                                                                        */
178 /*  RELEASE HISTORY                                                       */
179 /*                                                                        */
180 /*    DATE              NAME                      DESCRIPTION             */
181 /*                                                                        */
182 /*  05-19-2020     Timothy Stapko           Initial Version 6.0           */
183 /*  09-30-2020     Timothy Stapko           Modified comment(s),          */
184 /*                                            verified memcpy use cases,  */
185 /*                                            resulting in version 6.1    */
186 /*                                                                        */
187 /**************************************************************************/
_nx_crypto_sha256_update(NX_CRYPTO_SHA256 * context,UCHAR * input_ptr,UINT input_length)188 NX_CRYPTO_KEEP UINT _nx_crypto_sha256_update(NX_CRYPTO_SHA256 *context, UCHAR *input_ptr, UINT input_length)
189 {
190 ULONG current_bytes;
191 ULONG needed_fill_bytes;
192 
193     /* Determine if the context is non-null.  */
194     if (context == NX_CRYPTO_NULL)
195     {
196         return(NX_CRYPTO_PTR_ERROR);
197     }
198 
199     /* Determine if there is a length.  */
200     if (input_length == 0)
201     {
202         return(NX_CRYPTO_SUCCESS);
203     }
204 
205     /* Calculate the current byte count mod 64. Note the reason for the
206        shift by 3 is to account for the 8 bits per byte.  */
207     current_bytes =  (context -> nx_sha256_bit_count[0] >> 3) & 0x3F;
208 
209     /* Calculate the current number of bytes needed to be filled.  */
210     needed_fill_bytes =  64 - current_bytes;
211 
212     /* Update the total bit count based on the input length.  */
213     context -> nx_sha256_bit_count[0] += (input_length << 3);
214 
215     /* Determine if there is roll-over of the bit count into the MSW.  */
216     if (context -> nx_sha256_bit_count[0] < (input_length << 3))
217     {
218 
219         /* Yes, increment the MSW of the bit count.  */
220         context -> nx_sha256_bit_count[1]++;
221     }
222 
223     /* Update upper total bit count word.  */
224     context -> nx_sha256_bit_count[1] +=  (input_length >> 29);
225 
226     /* Check for a partial buffer that needs to be transformed.  */
227     if ((current_bytes) && (input_length >= needed_fill_bytes))
228     {
229         /* Yes, we can complete the buffer and transform it.  */
230 
231         /* Copy the appropriate portion of the input buffer into the internal
232            buffer of the context.  */
233         NX_CRYPTO_MEMCPY((void *)&(context -> nx_sha256_buffer[current_bytes]), (void *)input_ptr, needed_fill_bytes); /* Use case of memcpy is verified. */
234 
235         /* Process the 64-byte (512 bit) buffer.  */
236         _nx_crypto_sha256_process_buffer(context, context -> nx_sha256_buffer);
237 
238         /* Adjust the pointers and length accordingly.  */
239         input_length =  input_length - needed_fill_bytes;
240         input_ptr =     input_ptr + needed_fill_bytes;
241 
242         /* Clear the remaining bits, since the buffer was processed.  */
243         current_bytes =  0;
244     }
245 
246     /* Process any and all whole blocks of input.  */
247     while (input_length >= 64)
248     {
249 
250         /* Process this 64-byte (512 bit) buffer.  */
251         _nx_crypto_sha256_process_buffer(context, input_ptr);
252 
253         /* Adjust the pointers and length accordingly.  */
254         input_length =  input_length - 64;
255         input_ptr =     input_ptr + 64;
256     }
257 
258     /* Determine if there is anything left.  */
259     if (input_length)
260     {
261         /* Save the remaining bytes in the internal buffer after any remaining bytes
262            so that it is processed later.  */
263         NX_CRYPTO_MEMCPY((void *)&(context -> nx_sha256_buffer[current_bytes]), (void *)input_ptr, input_length); /* Use case of memcpy is verified. */
264     }
265 
266     /* Return success.  */
267     return(NX_CRYPTO_SUCCESS);
268 }
269 
270 
271 /**************************************************************************/
272 /*                                                                        */
273 /*  FUNCTION                                               RELEASE        */
274 /*                                                                        */
275 /*    _nx_crypto_sha256_digest_calculate                  PORTABLE C      */
276 /*                                                           6.1.10       */
277 /*                                                                        */
278 /*  AUTHOR                                                                */
279 /*                                                                        */
280 /*    Timothy Stapko, Microsoft Corporation                               */
281 /*                                                                        */
282 /*  DESCRIPTION                                                           */
283 /*                                                                        */
284 /*    This function calculates the final SHA256 digest. It is called      */
285 /*    when there is no more input for the digest and returns the 32-byte  */
286 /*    (256-bit) SHA256 digest to the caller.                              */
287 /*                                                                        */
288 /*  INPUT                                                                 */
289 /*                                                                        */
290 /*    context                               SHA256 context pointer        */
291 /*    digest                                Pointer to return buffer      */
292 /*                                                                        */
293 /*  OUTPUT                                                                */
294 /*                                                                        */
295 /*    status                                Completion status             */
296 /*                                                                        */
297 /*  CALLS                                                                 */
298 /*                                                                        */
299 /*    _nx_crypto_sha256_update              Final update to the digest    */
300 /*                                            with padding and length     */
301 /*                                                                        */
302 /*  CALLED BY                                                             */
303 /*                                                                        */
304 /*    _nx_crypto_method_sha256_operation    Handle SHA256 operation       */
305 /*                                                                        */
306 /*  RELEASE HISTORY                                                       */
307 /*                                                                        */
308 /*    DATE              NAME                      DESCRIPTION             */
309 /*                                                                        */
310 /*  05-19-2020     Timothy Stapko           Initial Version 6.0           */
311 /*  09-30-2020     Timothy Stapko           Modified comment(s),          */
312 /*                                            resulting in version 6.1    */
313 /*  01-31-2022     Timothy Stapko           Modified comment(s),          */
314 /*                                            improved performance,       */
315 /*                                            resulting in version 6.1.10 */
316 /*                                                                        */
317 /**************************************************************************/
_nx_crypto_sha256_digest_calculate(NX_CRYPTO_SHA256 * context,UCHAR * digest,UINT algorithm)318 NX_CRYPTO_KEEP UINT _nx_crypto_sha256_digest_calculate(NX_CRYPTO_SHA256 *context, UCHAR *digest, UINT algorithm)
319 {
320 UINT bit_count_string[2];
321 ULONG current_byte_count;
322 ULONG padding_bytes;
323 
324 
325     /* Move the lower portion of the bit count into the array.  */
326     bit_count_string[0] = context -> nx_sha256_bit_count[1];
327     NX_CRYPTO_CHANGE_ULONG_ENDIAN(bit_count_string[0]);
328     bit_count_string[1] = context -> nx_sha256_bit_count[0];
329     NX_CRYPTO_CHANGE_ULONG_ENDIAN(bit_count_string[1]);
330 
331     /* Calculate the current byte count.  */
332     current_byte_count =  (context -> nx_sha256_bit_count[0] >> 3) & 0x3F;
333 
334     /* Calculate the padding bytes needed.  */
335     padding_bytes =  (current_byte_count < 56) ? (56 - current_byte_count) : (120 - current_byte_count);
336 
337     /* Add any padding required.  */
338     _nx_crypto_sha256_update(context, (UCHAR*)_nx_crypto_sha256_padding, padding_bytes);
339 
340     /* Add the in the length.  */
341     _nx_crypto_sha256_update(context, (UCHAR*)bit_count_string, 8);
342 
343     /* Now store the digest in the caller specified destination.  */
344     digest[0] =  (UCHAR)(context -> nx_sha256_states[0] >> 24);
345     digest[1] =  (UCHAR)(context -> nx_sha256_states[0] >> 16);
346     digest[2] =  (UCHAR)(context -> nx_sha256_states[0] >> 8);
347     digest[3] =  (UCHAR)(context -> nx_sha256_states[0]);
348     digest[4] =  (UCHAR)(context -> nx_sha256_states[1] >> 24);
349     digest[5] =  (UCHAR)(context -> nx_sha256_states[1] >> 16);
350     digest[6] =  (UCHAR)(context -> nx_sha256_states[1] >> 8);
351     digest[7] =  (UCHAR)(context -> nx_sha256_states[1]);
352     digest[8] =  (UCHAR)(context -> nx_sha256_states[2] >> 24);
353     digest[9] =  (UCHAR)(context -> nx_sha256_states[2] >> 16);
354     digest[10] =  (UCHAR)(context -> nx_sha256_states[2] >> 8);
355     digest[11] =  (UCHAR)(context -> nx_sha256_states[2]);
356     digest[12] =  (UCHAR)(context -> nx_sha256_states[3] >> 24);
357     digest[13] =  (UCHAR)(context -> nx_sha256_states[3] >> 16);
358     digest[14] =  (UCHAR)(context -> nx_sha256_states[3] >> 8);
359     digest[15] =  (UCHAR)(context -> nx_sha256_states[3]);
360     digest[16] =  (UCHAR)(context -> nx_sha256_states[4] >> 24);
361     digest[17] =  (UCHAR)(context -> nx_sha256_states[4] >> 16);
362     digest[18] =  (UCHAR)(context -> nx_sha256_states[4] >> 8);
363     digest[19] =  (UCHAR)(context -> nx_sha256_states[4]);
364     digest[20] =  (UCHAR)(context -> nx_sha256_states[5] >> 24);
365     digest[21] =  (UCHAR)(context -> nx_sha256_states[5] >> 16);
366     digest[22] =  (UCHAR)(context -> nx_sha256_states[5] >> 8);
367     digest[23] =  (UCHAR)(context -> nx_sha256_states[5]);
368     digest[24] =  (UCHAR)(context -> nx_sha256_states[6] >> 24);
369     digest[25] =  (UCHAR)(context -> nx_sha256_states[6] >> 16);
370     digest[26] =  (UCHAR)(context -> nx_sha256_states[6] >> 8);
371     digest[27] =  (UCHAR)(context -> nx_sha256_states[6]);
372     if ((algorithm == NX_CRYPTO_AUTHENTICATION_HMAC_SHA2_256) ||
373         (algorithm == NX_CRYPTO_HASH_SHA256))
374     {
375         digest[28] =  (UCHAR)(context -> nx_sha256_states[7] >> 24);
376         digest[29] =  (UCHAR)(context -> nx_sha256_states[7] >> 16);
377         digest[30] =  (UCHAR)(context -> nx_sha256_states[7] >> 8);
378         digest[31] =  (UCHAR)(context -> nx_sha256_states[7]);
379     }
380 
381 #ifdef NX_SECURE_KEY_CLEAR
382     NX_CRYPTO_MEMSET(bit_count_string, 0, sizeof(bit_count_string));
383 #endif /* NX_SECURE_KEY_CLEAR  */
384 
385     /* Return successful completion.  */
386     return(NX_CRYPTO_SUCCESS);
387 }
388 
389 
390 /**************************************************************************/
391 /*                                                                        */
392 /*  FUNCTION                                               RELEASE        */
393 /*                                                                        */
394 /*    _nx_crypto_sha256_process_buffer                    PORTABLE C      */
395 /*                                                           6.1.10       */
396 /*                                                                        */
397 /*  AUTHOR                                                                */
398 /*                                                                        */
399 /*    Timothy Stapko, Microsoft Corporation                               */
400 /*                                                                        */
401 /*  DESCRIPTION                                                           */
402 /*                                                                        */
403 /*    This function implements the SHA256 algorithm which works on        */
404 /*    64-byte (512-bit) blocks of data.                                   */
405 /*                                                                        */
406 /*  INPUT                                                                 */
407 /*                                                                        */
408 /*    context                               SHA256 context pointer        */
409 /*    buffer                                Pointer to 64-byte buffer     */
410 /*                                                                        */
411 /*  OUTPUT                                                                */
412 /*                                                                        */
413 /*    None                                                                */
414 /*                                                                        */
415 /*  CALLS                                                                 */
416 /*                                                                        */
417 /*    None                                                                */
418 /*                                                                        */
419 /*  CALLED BY                                                             */
420 /*                                                                        */
421 /*    _nx_crypto_sha256_update              Final update to the digest    */
422 /*                                            with padding and length     */
423 /*                                                                        */
424 /*  RELEASE HISTORY                                                       */
425 /*                                                                        */
426 /*    DATE              NAME                      DESCRIPTION             */
427 /*                                                                        */
428 /*  05-19-2020     Timothy Stapko           Initial Version 6.0           */
429 /*  09-30-2020     Timothy Stapko           Modified comment(s),          */
430 /*                                            resulting in version 6.1    */
431 /*  01-31-2022     Timothy Stapko           Modified comment(s),          */
432 /*                                            improved performance,       */
433 /*                                            resulting in version 6.1.10 */
434 /*                                                                        */
435 /**************************************************************************/
_nx_crypto_sha256_process_buffer(NX_CRYPTO_SHA256 * context,UCHAR buffer[64])436 NX_CRYPTO_KEEP VOID _nx_crypto_sha256_process_buffer(NX_CRYPTO_SHA256 *context, UCHAR buffer[64])
437 {
438 ULONG *w;
439 UINT   t;
440 ULONG  temp1, temp2;
441 ULONG  a, b, c, d, e, f, g, h;
442 
443 
444     /* Setup pointers to the word array.  */
445     w =  context -> nx_sha256_word_array;
446 
447     /* Initialize the state variables.  */
448     a =  context -> nx_sha256_states[0];
449     b =  context -> nx_sha256_states[1];
450     c =  context -> nx_sha256_states[2];
451     d =  context -> nx_sha256_states[3];
452     e =  context -> nx_sha256_states[4];
453     f =  context -> nx_sha256_states[5];
454     g =  context -> nx_sha256_states[6];
455     h =  context -> nx_sha256_states[7];
456 
457     /* Now, perform Round operations.  */
458     for (t = 0; t < 16; t += 8)
459     {
460 
461         /* Setup each entry.  */
462         w[t] =  W0(t);
463         temp1 = h + LARGE_SIGMA_1(e) + CH_FUNC(e, f, g) + _sha2_round_constants[t] + w[t];
464         temp2 = LARGE_SIGMA_0(a) + MAJ_FUNC(a, b, c);
465         d = d + temp1;
466         h = temp1 + temp2;
467 
468         w[t + 1] =  W0(t + 1);
469         temp1 = g + LARGE_SIGMA_1(d) + CH_FUNC(d, e, f) + _sha2_round_constants[t + 1] + w[t + 1];
470         temp2 = LARGE_SIGMA_0(h) + MAJ_FUNC(h, a, b);
471         c = c + temp1;
472         g = temp1 + temp2;
473 
474         w[t + 2] =  W0(t + 2);
475         temp1 = f + LARGE_SIGMA_1(c) + CH_FUNC(c, d, e) + _sha2_round_constants[t + 2] + w[t + 2];
476         temp2 = LARGE_SIGMA_0(g) + MAJ_FUNC(g, h, a);
477         b = b + temp1;
478         f = temp1 + temp2;
479 
480         w[t + 3] =  W0(t + 3);
481         temp1 = e + LARGE_SIGMA_1(b) + CH_FUNC(b, c, d) + _sha2_round_constants[t + 3] + w[t + 3];
482         temp2 = LARGE_SIGMA_0(f) + MAJ_FUNC(f, g, h);
483         a = a + temp1;
484         e = temp1 + temp2;
485 
486         w[t + 4] =  W0(t + 4);
487         temp1 = d + LARGE_SIGMA_1(a) + CH_FUNC(a, b, c) + _sha2_round_constants[t + 4] + w[t + 4];
488         temp2 = LARGE_SIGMA_0(e) + MAJ_FUNC(e, f, g);
489         h = h + temp1;
490         d = temp1 + temp2;
491 
492 
493         w[t + 5] =  W0(t + 5);
494         temp1 = c + LARGE_SIGMA_1(h) + CH_FUNC(h, a, b) + _sha2_round_constants[t + 5] + w[t + 5];
495         temp2 = LARGE_SIGMA_0(d) + MAJ_FUNC(d, e, f);
496         g = g + temp1;
497         c = temp1 + temp2;
498 
499         w[t + 6] =  W0(t + 6);
500         temp1 = b + LARGE_SIGMA_1(g) + CH_FUNC(g, h, a) + _sha2_round_constants[t + 6] + w[t + 6];
501         temp2 = LARGE_SIGMA_0(c) + MAJ_FUNC(c, d, e);
502         f = f + temp1;
503         b = temp1 + temp2;
504 
505         w[t + 7] =  W0(t + 7);
506         temp1 = a + LARGE_SIGMA_1(f) + CH_FUNC(f, g, h) + _sha2_round_constants[t + 7] + w[t + 7];
507         temp2 = LARGE_SIGMA_0(b) + MAJ_FUNC(b, c, d);
508         e = e + temp1;
509         a = temp1 + temp2;
510     }
511 
512     for (; t < 64; t += 8)
513     {
514 
515         /* Setup each entry.  */
516         w[t] =  W16(t);
517         temp1 = h + LARGE_SIGMA_1(e) + CH_FUNC(e, f, g) + _sha2_round_constants[t] + w[t];
518         temp2 = LARGE_SIGMA_0(a) + MAJ_FUNC(a, b, c);
519         d = d + temp1;
520         h = temp1 + temp2;
521 
522         w[t + 1] =  W16(t + 1);
523         temp1 = g + LARGE_SIGMA_1(d) + CH_FUNC(d, e, f) + _sha2_round_constants[t + 1] + w[t + 1];
524         temp2 = LARGE_SIGMA_0(h) + MAJ_FUNC(h, a, b);
525         c = c + temp1;
526         g = temp1 + temp2;
527 
528         w[t + 2] =  W16(t + 2);
529         temp1 = f + LARGE_SIGMA_1(c) + CH_FUNC(c, d, e) + _sha2_round_constants[t + 2] + w[t + 2];
530         temp2 = LARGE_SIGMA_0(g) + MAJ_FUNC(g, h, a);
531         b = b + temp1;
532         f = temp1 + temp2;
533 
534         w[t + 3] =  W16(t + 3);
535         temp1 = e + LARGE_SIGMA_1(b) + CH_FUNC(b, c, d) + _sha2_round_constants[t + 3] + w[t + 3];
536         temp2 = LARGE_SIGMA_0(f) + MAJ_FUNC(f, g, h);
537         a = a + temp1;
538         e = temp1 + temp2;
539 
540         w[t + 4] =  W16(t + 4);
541         temp1 = d + LARGE_SIGMA_1(a) + CH_FUNC(a, b, c) + _sha2_round_constants[t + 4] + w[t + 4];
542         temp2 = LARGE_SIGMA_0(e) + MAJ_FUNC(e, f, g);
543         h = h + temp1;
544         d = temp1 + temp2;
545 
546 
547         w[t + 5] =  W16(t + 5);
548         temp1 = c + LARGE_SIGMA_1(h) + CH_FUNC(h, a, b) + _sha2_round_constants[t + 5] + w[t + 5];
549         temp2 = LARGE_SIGMA_0(d) + MAJ_FUNC(d, e, f);
550         g = g + temp1;
551         c = temp1 + temp2;
552 
553         w[t + 6] =  W16(t + 6);
554         temp1 = b + LARGE_SIGMA_1(g) + CH_FUNC(g, h, a) + _sha2_round_constants[t + 6] + w[t + 6];
555         temp2 = LARGE_SIGMA_0(c) + MAJ_FUNC(c, d, e);
556         f = f + temp1;
557         b = temp1 + temp2;
558 
559         w[t + 7] =  W16(t + 7);
560         temp1 = a + LARGE_SIGMA_1(f) + CH_FUNC(f, g, h) + _sha2_round_constants[t + 7] + w[t + 7];
561         temp2 = LARGE_SIGMA_0(b) + MAJ_FUNC(b, c, d);
562         e = e + temp1;
563         a = temp1 + temp2;
564 
565     }
566 
567     /* Save the resulting in this SHA256 context.  */
568     context -> nx_sha256_states[0] +=  a;
569     context -> nx_sha256_states[1] +=  b;
570     context -> nx_sha256_states[2] +=  c;
571     context -> nx_sha256_states[3] +=  d;
572     context -> nx_sha256_states[4] +=  e;
573     context -> nx_sha256_states[5] +=  f;
574     context -> nx_sha256_states[6] +=  g;
575     context -> nx_sha256_states[7] +=  h;
576 
577 #ifdef NX_SECURE_KEY_CLEAR
578     a = 0; b = 0; c = 0; d = 0;
579     e = 0; f = 0; g = 0; h = 0;
580     temp1 = 0; temp2 = 0;
581 #endif /* NX_SECURE_KEY_CLEAR  */
582 }
583 
584 
585 /**************************************************************************/
586 /*                                                                        */
587 /*  FUNCTION                                               RELEASE        */
588 /*                                                                        */
589 /*    _nx_crypto_method_sha256_init                       PORTABLE C      */
590 /*                                                           6.3.0        */
591 /*  AUTHOR                                                                */
592 /*                                                                        */
593 /*    Timothy Stapko, Microsoft Corporation                               */
594 /*                                                                        */
595 /*  DESCRIPTION                                                           */
596 /*                                                                        */
597 /*    This function is the common crypto method init callback for         */
598 /*    Microsoft supported SHA256 cryptographic algorithm.                 */
599 /*                                                                        */
600 /*  INPUT                                                                 */
601 /*                                                                        */
602 /*    method                                Pointer to crypto method      */
603 /*    key                                   Pointer to key                */
604 /*    key_size_in_bits                      Length of key size in bits    */
605 /*    handler                               Returned crypto handler       */
606 /*    crypto_metadata                       Metadata area                 */
607 /*    crypto_metadata_size                  Size of the metadata area     */
608 /*                                                                        */
609 /*  OUTPUT                                                                */
610 /*                                                                        */
611 /*    status                                Completion status             */
612 /*                                                                        */
613 /*  CALLS                                                                 */
614 /*                                                                        */
615 /*    None                                                                */
616 /*                                                                        */
617 /*  CALLED BY                                                             */
618 /*                                                                        */
619 /*    Application Code                                                    */
620 /*                                                                        */
621 /*  RELEASE HISTORY                                                       */
622 /*                                                                        */
623 /*    DATE              NAME                      DESCRIPTION             */
624 /*                                                                        */
625 /*  05-19-2020     Timothy Stapko           Initial Version 6.0           */
626 /*  09-30-2020     Timothy Stapko           Modified comment(s),          */
627 /*                                            resulting in version 6.1    */
628 /*  10-31-2023     Yanwu Cai                Modified comment(s),          */
629 /*                                            resulting in version 6.3.0  */
630 /*                                                                        */
631 /**************************************************************************/
_nx_crypto_method_sha256_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)632 NX_CRYPTO_KEEP UINT  _nx_crypto_method_sha256_init(struct  NX_CRYPTO_METHOD_STRUCT *method,
633                                                    UCHAR *key, NX_CRYPTO_KEY_SIZE key_size_in_bits,
634                                                    VOID  **handle,
635                                                    VOID  *crypto_metadata,
636                                                    ULONG crypto_metadata_size)
637 {
638 
639     NX_CRYPTO_PARAMETER_NOT_USED(key);
640     NX_CRYPTO_PARAMETER_NOT_USED(key_size_in_bits);
641     NX_CRYPTO_PARAMETER_NOT_USED(handle);
642 
643     NX_CRYPTO_STATE_CHECK
644 
645     if ((method == NX_CRYPTO_NULL) || (crypto_metadata == NX_CRYPTO_NULL))
646     {
647         return(NX_CRYPTO_PTR_ERROR);
648     }
649 
650     /* Verify the metadata address is 4-byte aligned. */
651     if((((ULONG)crypto_metadata) & 0x3) != 0)
652     {
653         return(NX_CRYPTO_PTR_ERROR);
654     }
655 
656     if(crypto_metadata_size < sizeof(NX_CRYPTO_SHA256))
657     {
658         return(NX_CRYPTO_PTR_ERROR);
659     }
660 
661     return(NX_CRYPTO_SUCCESS);
662 }
663 
664 
665 /**************************************************************************/
666 /*                                                                        */
667 /*  FUNCTION                                               RELEASE        */
668 /*                                                                        */
669 /*    _nx_crypto_method_sha256_cleanup                    PORTABLE C      */
670 /*                                                           6.1          */
671 /*  AUTHOR                                                                */
672 /*                                                                        */
673 /*    Timothy Stapko, Microsoft Corporation                               */
674 /*                                                                        */
675 /*  DESCRIPTION                                                           */
676 /*                                                                        */
677 /*    This function cleans up the crypto metadata.                        */
678 /*                                                                        */
679 /*  INPUT                                                                 */
680 /*                                                                        */
681 /*    crypto_metadata                       Crypto metadata               */
682 /*                                                                        */
683 /*  OUTPUT                                                                */
684 /*                                                                        */
685 /*    status                                Completion status             */
686 /*                                                                        */
687 /*  CALLS                                                                 */
688 /*                                                                        */
689 /*    NX_CRYPTO_MEMSET                      Set the memory                */
690 /*                                                                        */
691 /*  CALLED BY                                                             */
692 /*                                                                        */
693 /*    Application Code                                                    */
694 /*                                                                        */
695 /*  RELEASE HISTORY                                                       */
696 /*                                                                        */
697 /*    DATE              NAME                      DESCRIPTION             */
698 /*                                                                        */
699 /*  05-19-2020     Timothy Stapko           Initial Version 6.0           */
700 /*  09-30-2020     Timothy Stapko           Modified comment(s),          */
701 /*                                            resulting in version 6.1    */
702 /*                                                                        */
703 /**************************************************************************/
_nx_crypto_method_sha256_cleanup(VOID * crypto_metadata)704 NX_CRYPTO_KEEP UINT  _nx_crypto_method_sha256_cleanup(VOID *crypto_metadata)
705 {
706 
707     NX_CRYPTO_STATE_CHECK
708 
709 #ifdef NX_SECURE_KEY_CLEAR
710     if (!crypto_metadata)
711         return (NX_CRYPTO_SUCCESS);
712 
713     /* Clean up the crypto metadata.  */
714     NX_CRYPTO_MEMSET(crypto_metadata, 0, sizeof(NX_CRYPTO_SHA256));
715 #else
716     NX_CRYPTO_PARAMETER_NOT_USED(crypto_metadata);
717 #endif/* NX_SECURE_KEY_CLEAR  */
718 
719     return(NX_CRYPTO_SUCCESS);
720 }
721 
722 
723 /**************************************************************************/
724 /*                                                                        */
725 /*  FUNCTION                                               RELEASE        */
726 /*                                                                        */
727 /*    _nx_crypto_method_sha256_operation                 PORTABLE C       */
728 /*                                                           6.3.0        */
729 /*  AUTHOR                                                                */
730 /*                                                                        */
731 /*    Timothy Stapko, Microsoft Corporation                               */
732 /*                                                                        */
733 /*  DESCRIPTION                                                           */
734 /*                                                                        */
735 /*    This function encrypts and decrypts a message using                 */
736 /*    the SHA256 algorithm.                                               */
737 /*                                                                        */
738 /*  INPUT                                                                 */
739 /*                                                                        */
740 /*    op                                    SHA256 operation              */
741 /*    handle                                Crypto handle                 */
742 /*    method                                Cryption Method Object        */
743 /*    key                                   Encryption Key                */
744 /*    key_size_in_bits                      Key size in bits              */
745 /*    input                                 Input data                    */
746 /*    input_length_in_byte                  Input data size               */
747 /*    iv_ptr                                Initial vector                */
748 /*    output                                Output buffer                 */
749 /*    output_length_in_byte                 Output buffer size            */
750 /*    crypto_metadata                       Metadata area                 */
751 /*    crypto_metadata_size                  Metadata area size            */
752 /*    packet_ptr                            Pointer to packet             */
753 /*    nx_crypto_hw_process_callback         Callback function pointer     */
754 /*                                                                        */
755 /*  OUTPUT                                                                */
756 /*                                                                        */
757 /*    status                                Completion status             */
758 /*                                                                        */
759 /*  CALLS                                                                 */
760 /*                                                                        */
761 /*    _nx_crypto_sha256_initialize          Initialize the SHA256 context */
762 /*    _nx_crypto_sha256_update              Update the digest with padding*/
763 /*                                            and length of digest        */
764 /*    _nx_crypto_sha256_digest_calculate    Calculate the SHA256 digest   */
765 /*                                                                        */
766 /*  CALLED BY                                                             */
767 /*                                                                        */
768 /*    Application Code                                                    */
769 /*                                                                        */
770 /*  RELEASE HISTORY                                                       */
771 /*                                                                        */
772 /*    DATE              NAME                      DESCRIPTION             */
773 /*                                                                        */
774 /*  05-19-2020     Timothy Stapko           Initial Version 6.0           */
775 /*  09-30-2020     Timothy Stapko           Modified comment(s),          */
776 /*                                            resulting in version 6.1    */
777 /*  10-31-2023     Yanwu Cai                Modified comment(s),          */
778 /*                                            resulting in version 6.3.0  */
779 /*                                                                        */
780 /**************************************************************************/
_nx_crypto_method_sha256_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))781 NX_CRYPTO_KEEP UINT  _nx_crypto_method_sha256_operation(UINT op,      /* Encrypt, Decrypt, Authenticate */
782                                                         VOID *handle, /* Crypto handler */
783                                                         struct NX_CRYPTO_METHOD_STRUCT *method,
784                                                         UCHAR *key,
785                                                         NX_CRYPTO_KEY_SIZE key_size_in_bits,
786                                                         UCHAR *input,
787                                                         ULONG input_length_in_byte,
788                                                         UCHAR *iv_ptr,
789                                                         UCHAR *output,
790                                                         ULONG output_length_in_byte,
791                                                         VOID *crypto_metadata,
792                                                         ULONG crypto_metadata_size,
793                                                         VOID *packet_ptr,
794                                                         VOID (*nx_crypto_hw_process_callback)(VOID *packet_ptr, UINT status))
795 {
796 NX_CRYPTO_SHA256 *ctx;
797 
798     NX_CRYPTO_PARAMETER_NOT_USED(handle);
799     NX_CRYPTO_PARAMETER_NOT_USED(key);
800     NX_CRYPTO_PARAMETER_NOT_USED(key_size_in_bits);
801     NX_CRYPTO_PARAMETER_NOT_USED(iv_ptr);
802     NX_CRYPTO_PARAMETER_NOT_USED(packet_ptr);
803     NX_CRYPTO_PARAMETER_NOT_USED(nx_crypto_hw_process_callback);
804 
805     NX_CRYPTO_STATE_CHECK
806 
807     if (method == NX_CRYPTO_NULL)
808     {
809         return(NX_CRYPTO_PTR_ERROR);
810     }
811 
812     /* Verify the metadata address is 4-byte aligned. */
813     if((crypto_metadata == NX_CRYPTO_NULL) || ((((ULONG)crypto_metadata) & 0x3) != 0))
814     {
815         return(NX_CRYPTO_PTR_ERROR);
816     }
817 
818     if(crypto_metadata_size < sizeof(NX_CRYPTO_SHA256))
819     {
820         return(NX_CRYPTO_PTR_ERROR);
821     }
822 
823     ctx = (NX_CRYPTO_SHA256 *)crypto_metadata;
824 
825     if ((method -> nx_crypto_algorithm != NX_CRYPTO_AUTHENTICATION_HMAC_SHA2_256) &&
826         (method -> nx_crypto_algorithm != NX_CRYPTO_HASH_SHA224) &&
827         (method -> nx_crypto_algorithm != NX_CRYPTO_HASH_SHA256))
828     {
829         /* Incorrect method. */
830         return(NX_CRYPTO_NOT_SUCCESSFUL);
831     }
832 
833     switch (op)
834     {
835     case NX_CRYPTO_HASH_INITIALIZE:
836         _nx_crypto_sha256_initialize((NX_CRYPTO_SHA256 *)crypto_metadata, method -> nx_crypto_algorithm);
837         break;
838 
839     case NX_CRYPTO_HASH_UPDATE:
840         _nx_crypto_sha256_update((NX_CRYPTO_SHA256 *)crypto_metadata, input, input_length_in_byte);
841         break;
842 
843     case NX_CRYPTO_HASH_CALCULATE:
844         if ((method -> nx_crypto_algorithm == NX_CRYPTO_AUTHENTICATION_HMAC_SHA2_256) ||
845             (method -> nx_crypto_algorithm == NX_CRYPTO_HASH_SHA256))
846         {
847             if(output_length_in_byte < 32)
848                 return(NX_CRYPTO_INVALID_BUFFER_SIZE);
849         }
850         else if(output_length_in_byte < 28)
851             return(NX_CRYPTO_INVALID_BUFFER_SIZE);
852         _nx_crypto_sha256_digest_calculate((NX_CRYPTO_SHA256 *)crypto_metadata, output,
853                                            method -> nx_crypto_algorithm);
854         break;
855 
856     default:
857         if ((method -> nx_crypto_algorithm == NX_CRYPTO_AUTHENTICATION_HMAC_SHA2_256) ||
858             (method -> nx_crypto_algorithm == NX_CRYPTO_HASH_SHA256))
859         {
860             if(output_length_in_byte < 32)
861                 return(NX_CRYPTO_INVALID_BUFFER_SIZE);
862         }
863         else if(output_length_in_byte < 28)
864             return(NX_CRYPTO_INVALID_BUFFER_SIZE);
865 
866         _nx_crypto_sha256_initialize(ctx, method -> nx_crypto_algorithm);
867         _nx_crypto_sha256_update(ctx, input, input_length_in_byte);
868         _nx_crypto_sha256_digest_calculate(ctx, output, method -> nx_crypto_algorithm);
869         break;
870     }
871 
872     return NX_CRYPTO_SUCCESS;
873 }
874 
875