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