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