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