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 /** Deterministic Random Bit Generator (DRBG) */
19 /** */
20 /**************************************************************************/
21 /**************************************************************************/
22
23 #define NX_CRYPTO_SOURCE_CODE
24
25
26 /* Include necessary system files. */
27
28 #include "nx_crypto_drbg.h"
29
30 #ifdef NX_CRYPTO_DRBG_CTR_METADATA_SIZE
31 #include "nx_crypto_aes.h"
32 static UCHAR _nx_crypto_ctr_metadata[NX_CRYPTO_DRBG_CTR_METADATA_SIZE];
33 #endif
34
35 static NX_CRYPTO_DRBG _nx_crypto_drbg_ctx;
36
37 static const UCHAR zeroiv[16] = { 0 };
38 static const UCHAR _nx_crypto_drbg_df_key[] = {
39 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
40 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
41 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
42 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f
43 };
44
45 static UINT _nx_crypto_drbg_update(NX_CRYPTO_DRBG *drbg_ptr, UCHAR *provided_data);
46 static UINT _nx_crypto_drbg_block_cipher_df(NX_CRYPTO_DRBG *drbg_ptr, UINT input_len, UCHAR *output, UINT output_len);
47
48
49 /**************************************************************************/
50 /* */
51 /* FUNCTION RELEASE */
52 /* */
53 /* _nx_crypto_drbg_ctr_add_one PORTABLE C */
54 /* 6.1 */
55 /* AUTHOR */
56 /* */
57 /* Timothy Stapko, Microsoft Corporation */
58 /* */
59 /* DESCRIPTION */
60 /* */
61 /* This this a utility function incrementing a large integer by one. */
62 /* */
63 /* INPUT */
64 /* */
65 /* ctr Number to add one to. */
66 /* */
67 /* OUTPUT */
68 /* */
69 /* None */
70 /* */
71 /* CALLS */
72 /* */
73 /* None */
74 /* */
75 /* CALLED BY */
76 /* */
77 /* _nx_crypto_drbg_generate */
78 /* */
79 /* RELEASE HISTORY */
80 /* */
81 /* DATE NAME DESCRIPTION */
82 /* */
83 /* 05-19-2020 Timothy Stapko Initial Version 6.0 */
84 /* 09-30-2020 Timothy Stapko Modified comment(s), */
85 /* resulting in version 6.1 */
86 /* */
87 /**************************************************************************/
_nx_crypto_drbg_ctr_add_one(UCHAR * ctr)88 NX_CRYPTO_KEEP static VOID _nx_crypto_drbg_ctr_add_one(UCHAR *ctr)
89 {
90 USHORT result;
91 INT i;
92
93 /* Add one for last byte. */
94 result = (USHORT)(ctr[15] + 1);
95 ctr[15] = (UCHAR)(result & 0xFF);
96
97 /* Handle carry. */
98 for (i = 14; i >= 0; i--)
99 {
100 result = (USHORT)((result >> 8) + ctr[i]);
101 ctr[i] = (UCHAR)(result & 0xFF);
102 }
103 }
104
105 /**************************************************************************/
106 /* */
107 /* FUNCTION RELEASE */
108 /* */
109 /* _nx_crypto_drbg_update PORTABLE C */
110 /* 6.1 */
111 /* AUTHOR */
112 /* */
113 /* Timothy Stapko, Microsoft Corporation */
114 /* */
115 /* DESCRIPTION */
116 /* */
117 /* This isan internal function updates the DRBG with new data. */
118 /* */
119 /* INPUT */
120 /* */
121 /* drbg_ptr DRBG context */
122 /* */
123 /* OUTPUT */
124 /* */
125 /* status Completion status */
126 /* */
127 /* CALLS */
128 /* */
129 /* */
130 /* CALLED BY */
131 /* */
132 /* Application Code */
133 /* */
134 /* RELEASE HISTORY */
135 /* */
136 /* DATE NAME DESCRIPTION */
137 /* */
138 /* 05-19-2020 Timothy Stapko Initial Version 6.0 */
139 /* 09-30-2020 Timothy Stapko Modified comment(s), verified */
140 /* memcpy use cases, disabled */
141 /* unaligned access by default,*/
142 /* resulting in version 6.1 */
143 /* */
144 /**************************************************************************/
_nx_crypto_drbg_update(NX_CRYPTO_DRBG * drbg_ptr,UCHAR * provided_data)145 NX_CRYPTO_KEEP static UINT _nx_crypto_drbg_update(NX_CRYPTO_DRBG *drbg_ptr, UCHAR *provided_data)
146 {
147 NX_CRYPTO_METHOD *crypto_method;
148 UINT key_len;
149 UCHAR temp[NX_CRYPTO_DRBG_MAX_SEEDLEN];
150 UINT temp_len = 0;
151 UINT status = NX_CRYPTO_SUCCESS;
152 VOID *handler = NX_CRYPTO_NULL;
153
154 crypto_method = drbg_ptr -> nx_crypto_drbg_crypto_method;
155
156 /* Initialize crypto method with DRBG key. */
157 if (crypto_method -> nx_crypto_init)
158 {
159 status = crypto_method -> nx_crypto_init(crypto_method,
160 drbg_ptr -> nx_crypto_drbg_key,
161 crypto_method -> nx_crypto_key_size_in_bits,
162 &handler,
163 drbg_ptr -> nx_crypto_drbg_crypto_metadata,
164 crypto_method -> nx_crypto_metadata_area_size);
165 if (status)
166 {
167 return(status);
168 }
169 }
170
171 while (temp_len < drbg_ptr -> nx_crypto_drbg_seedlen)
172 {
173 /* V = (V+1) mod 2^blocklen */
174 _nx_crypto_drbg_ctr_add_one(drbg_ptr -> nx_crypto_drbg_v);
175
176 status = crypto_method -> nx_crypto_operation(NX_CRYPTO_ENCRYPT,
177 handler,
178 crypto_method,
179 NX_CRYPTO_NULL,
180 crypto_method -> nx_crypto_key_size_in_bits,
181 (UCHAR *)drbg_ptr -> nx_crypto_drbg_v,
182 NX_CRYPTO_DRBG_BLOCK_LENGTH_AES,
183 (UCHAR *)zeroiv,
184 &temp[temp_len],
185 NX_CRYPTO_DRBG_BLOCK_LENGTH_AES,
186 drbg_ptr -> nx_crypto_drbg_crypto_metadata,
187 crypto_method -> nx_crypto_metadata_area_size,
188 NX_CRYPTO_NULL, NX_CRYPTO_NULL);
189 if (status != NX_CRYPTO_SUCCESS)
190 {
191 return(status);
192 }
193
194 temp_len += NX_CRYPTO_DRBG_BLOCK_LENGTH_AES;
195
196 }
197
198 if (crypto_method -> nx_crypto_cleanup)
199 {
200 status = crypto_method -> nx_crypto_cleanup(drbg_ptr -> nx_crypto_drbg_crypto_metadata);
201 if(status != NX_CRYPTO_SUCCESS)
202 {
203 return(status);
204 }
205 }
206
207 if (provided_data != NX_CRYPTO_NULL)
208 {
209 /* temp = temp xor provided_data. */
210 #ifdef NX_CRYPTO_ENABLE_UNALIGNED_ACCESS
211 for (temp_len = 0; temp_len < (drbg_ptr -> nx_crypto_drbg_seedlen >> 2); temp_len++)
212 {
213 ((UINT*)temp)[temp_len] ^= ((UINT*)provided_data)[temp_len];
214 }
215 #else
216 for (temp_len = 0; temp_len < drbg_ptr -> nx_crypto_drbg_seedlen; temp_len++)
217 {
218 temp[temp_len] ^= provided_data[temp_len];
219 }
220 #endif
221 }
222
223 key_len = crypto_method -> nx_crypto_key_size_in_bits >> 3;
224
225 NX_CRYPTO_MEMCPY(drbg_ptr -> nx_crypto_drbg_key, temp, key_len); /* Use case of memcpy is verified. */
226 NX_CRYPTO_MEMCPY(drbg_ptr -> nx_crypto_drbg_v, &temp[key_len], NX_CRYPTO_DRBG_BLOCK_LENGTH_AES); /* Use case of memcpy is verified. */
227
228 #ifdef NX_SECURE_KEY_CLEAR
229 NX_CRYPTO_MEMSET(temp, 0, sizeof(temp));
230 #endif /* NX_SECURE_KEY_CLEAR */
231
232 return(status);
233 }
234
235
236 /**************************************************************************/
237 /* */
238 /* FUNCTION RELEASE */
239 /* */
240 /* _nx_crypto_drbg_instantiate PORTABLE C */
241 /* 6.1 */
242 /* AUTHOR */
243 /* */
244 /* Timothy Stapko, Microsoft Corporation */
245 /* */
246 /* DESCRIPTION */
247 /* */
248 /* This function instantiate a DRBG context. */
249 /* */
250 /* INPUT */
251 /* */
252 /* drbg_ptr DRBG context */
253 /* */
254 /* OUTPUT */
255 /* */
256 /* status Completion status */
257 /* */
258 /* CALLS */
259 /* */
260 /* */
261 /* CALLED BY */
262 /* */
263 /* Application Code */
264 /* */
265 /* RELEASE HISTORY */
266 /* */
267 /* DATE NAME DESCRIPTION */
268 /* */
269 /* 05-19-2020 Timothy Stapko Initial Version 6.0 */
270 /* 09-30-2020 Timothy Stapko Modified comment(s), verified */
271 /* memcpy use cases, disabled */
272 /* unaligned access by default,*/
273 /* resulting in version 6.1 */
274 /* */
275 /**************************************************************************/
_nx_crypto_drbg_instantiate(NX_CRYPTO_DRBG * drbg_ptr,UCHAR * nonce,UINT nonce_len,UCHAR * personalization_string,UINT personalization_string_len)276 NX_CRYPTO_KEEP UINT _nx_crypto_drbg_instantiate(NX_CRYPTO_DRBG *drbg_ptr,
277 UCHAR *nonce,
278 UINT nonce_len,
279 UCHAR *personalization_string,
280 UINT personalization_string_len)
281 {
282 UINT i;
283 UCHAR seed_material[NX_CRYPTO_DRBG_MAX_SEEDLEN];
284 UCHAR *df_input;
285 UINT status;
286 UINT entropy_len;
287
288 if (drbg_ptr -> nx_crypto_drbg_crypto_method == NX_CRYPTO_NULL)
289 {
290 return(NX_CRYPTO_PTR_ERROR);
291 }
292
293 drbg_ptr -> nx_crypto_drbg_seedlen = (UINT)(NX_CRYPTO_DRBG_BLOCK_LENGTH + (drbg_ptr -> nx_crypto_drbg_crypto_method -> nx_crypto_key_size_in_bits >> 3));
294
295 if (drbg_ptr -> nx_crypto_drbg_use_df)
296 {
297 entropy_len = drbg_ptr -> nx_crypto_drbg_security_strength;
298
299 if (entropy_len + nonce_len + personalization_string_len + NX_CRYPTO_DRBG_DF_INPUT_OFFSET >= NX_CRYPTO_DRBG_SEED_BUFFER_LEN)
300 {
301 return(NX_CRYPTO_SIZE_ERROR);
302 }
303
304 /* seed_material = entropy_input || nonce || personalization_string. */
305 df_input = drbg_ptr -> nx_crypto_drbg_buffer + NX_CRYPTO_DRBG_DF_INPUT_OFFSET;
306
307 status = drbg_ptr -> nx_crypto_drbg_get_entropy(df_input, &entropy_len, NX_CRYPTO_DRBG_MAX_ENTROPY_LEN);
308 if (status != NX_CRYPTO_SUCCESS)
309 {
310 return(status);
311 }
312
313 df_input += entropy_len;
314 NX_CRYPTO_MEMCPY(df_input, nonce, nonce_len); /* Use case of memcpy is verified. */
315 df_input += nonce_len;
316 NX_CRYPTO_MEMCPY(df_input, personalization_string, personalization_string_len); /* Use case of memcpy is verified. */
317
318 /* seed_material = Block_Cipher_df (seed_material, seedlen). */
319 _nx_crypto_drbg_block_cipher_df(drbg_ptr, entropy_len + nonce_len + personalization_string_len, seed_material, drbg_ptr -> nx_crypto_drbg_seedlen);
320 }
321 else
322 {
323 if (personalization_string_len > drbg_ptr -> nx_crypto_drbg_seedlen)
324 {
325 return(NX_CRYPTO_SIZE_ERROR);
326 }
327
328 if (personalization_string != NX_CRYPTO_NULL && personalization_string_len > 0)
329 {
330 NX_CRYPTO_MEMCPY(seed_material, personalization_string, personalization_string_len); /* Use case of memcpy is verified. */
331 }
332
333 /* Ensure that the length of the personalization_string is exactly seedlen bits. */
334 if (personalization_string_len < drbg_ptr -> nx_crypto_drbg_seedlen)
335 {
336 NX_CRYPTO_MEMSET(&seed_material[personalization_string_len], 0,
337 drbg_ptr -> nx_crypto_drbg_seedlen - personalization_string_len);
338 }
339
340 entropy_len = drbg_ptr -> nx_crypto_drbg_seedlen;
341 status = drbg_ptr -> nx_crypto_drbg_get_entropy(drbg_ptr -> nx_crypto_drbg_buffer, &entropy_len, drbg_ptr -> nx_crypto_drbg_seedlen);
342 if (status != NX_CRYPTO_SUCCESS)
343 {
344 return(status);
345 }
346
347 /* seed_material = entropy_input xor personalization_string. */
348 #ifdef NX_CRYPTO_ENABLE_UNALIGNED_ACCESS
349 for (i = 0; i < (drbg_ptr -> nx_crypto_drbg_seedlen >> 2); i++)
350 {
351 ((UINT*)seed_material)[i] ^= ((UINT*)drbg_ptr -> nx_crypto_drbg_buffer)[i];
352 }
353 #else
354 for (i = 0; i < drbg_ptr -> nx_crypto_drbg_seedlen; i++)
355 {
356 seed_material[i] ^= drbg_ptr -> nx_crypto_drbg_buffer[i];
357 }
358 #endif
359 }
360
361 NX_CRYPTO_MEMSET(drbg_ptr -> nx_crypto_drbg_key, 0, sizeof(drbg_ptr -> nx_crypto_drbg_key));
362 NX_CRYPTO_MEMSET(drbg_ptr -> nx_crypto_drbg_v, 0, sizeof(drbg_ptr -> nx_crypto_drbg_v));
363
364 _nx_crypto_drbg_update(drbg_ptr, seed_material);
365
366 drbg_ptr -> nx_crypto_drgb_reseed_counter = 1;
367
368 #ifdef NX_SECURE_KEY_CLEAR
369 NX_CRYPTO_MEMSET(seed_material, 0, sizeof(seed_material));
370 #endif /* NX_SECURE_KEY_CLEAR */
371
372 drbg_ptr -> nx_crypto_drbg_instantiated = 1;
373
374 return(NX_CRYPTO_SUCCESS);
375 }
376
377 /**************************************************************************/
378 /* */
379 /* FUNCTION RELEASE */
380 /* */
381 /* _nx_crypto_drbg_reseed PORTABLE C */
382 /* 6.1 */
383 /* AUTHOR */
384 /* */
385 /* Timothy Stapko, Microsoft Corporation */
386 /* */
387 /* DESCRIPTION */
388 /* */
389 /* This function reseed a DRBG context. */
390 /* */
391 /* INPUT */
392 /* */
393 /* drbg_ptr DRBG context */
394 /* */
395 /* OUTPUT */
396 /* */
397 /* status Completion status */
398 /* */
399 /* CALLS */
400 /* */
401 /* */
402 /* CALLED BY */
403 /* */
404 /* Application Code */
405 /* */
406 /* RELEASE HISTORY */
407 /* */
408 /* DATE NAME DESCRIPTION */
409 /* */
410 /* 05-19-2020 Timothy Stapko Initial Version 6.0 */
411 /* 09-30-2020 Timothy Stapko Modified comment(s), verified */
412 /* memcpy use cases, disabled */
413 /* unaligned access by default,*/
414 /* resulting in version 6.1 */
415 /* */
416 /**************************************************************************/
_nx_crypto_drbg_reseed(NX_CRYPTO_DRBG * drbg_ptr,UCHAR * additional_input,UINT additional_input_len)417 UINT _nx_crypto_drbg_reseed(NX_CRYPTO_DRBG *drbg_ptr,
418 UCHAR *additional_input,
419 UINT additional_input_len)
420 {
421 UINT i;
422 UCHAR seed_material[NX_CRYPTO_DRBG_MAX_SEEDLEN];
423 UCHAR *df_input;
424 UINT entropy_len;
425 UINT status;
426
427 if (!drbg_ptr -> nx_crypto_drbg_instantiated)
428 {
429 return(NX_CRYPTO_NO_INSTANCE);
430 }
431
432 if (drbg_ptr -> nx_crypto_drbg_use_df)
433 {
434 entropy_len = drbg_ptr -> nx_crypto_drbg_security_strength;
435
436 if (entropy_len + additional_input_len + NX_CRYPTO_DRBG_DF_INPUT_OFFSET >= NX_CRYPTO_DRBG_SEED_BUFFER_LEN)
437 {
438 return(NX_CRYPTO_SIZE_ERROR);
439 }
440
441 /* seed_material = entropy_input || additional_input. */
442 df_input = drbg_ptr -> nx_crypto_drbg_buffer + NX_CRYPTO_DRBG_DF_INPUT_OFFSET;
443
444 status = drbg_ptr -> nx_crypto_drbg_get_entropy(df_input, &entropy_len, NX_CRYPTO_DRBG_MAX_ENTROPY_LEN);
445 if (status != NX_CRYPTO_SUCCESS)
446 {
447 return(status);
448 }
449
450 df_input += entropy_len;
451 NX_CRYPTO_MEMCPY(df_input, additional_input, additional_input_len); /* Use case of memcpy is verified. */
452
453 /* seed_material = Block_Cipher_df (seed_material, seedlen). */
454 _nx_crypto_drbg_block_cipher_df(drbg_ptr, entropy_len + additional_input_len, seed_material, drbg_ptr -> nx_crypto_drbg_seedlen);
455 }
456 else
457 {
458 if (additional_input_len > drbg_ptr -> nx_crypto_drbg_seedlen)
459 {
460 return(NX_CRYPTO_SIZE_ERROR);
461 }
462
463 /* Ensure that the length of the additional_input is exactly seedlen bits. */
464 NX_CRYPTO_MEMCPY(seed_material, additional_input, additional_input_len); /* Use case of memcpy is verified. */
465 if (additional_input_len < drbg_ptr -> nx_crypto_drbg_seedlen)
466 {
467 NX_CRYPTO_MEMSET(&seed_material[additional_input_len], 0,
468 drbg_ptr -> nx_crypto_drbg_seedlen - additional_input_len);
469 }
470
471 entropy_len = drbg_ptr -> nx_crypto_drbg_seedlen;
472 status = drbg_ptr -> nx_crypto_drbg_get_entropy(drbg_ptr -> nx_crypto_drbg_buffer, &entropy_len, NX_CRYPTO_DRBG_MAX_ENTROPY_LEN);
473 if (status != NX_CRYPTO_SUCCESS)
474 {
475 return(status);
476 }
477
478 /* seed_material = entropy_input xor additional_input. */
479 #ifdef NX_CRYPTO_ENABLE_UNALIGNED_ACCESS
480 for (i = 0; i < (drbg_ptr -> nx_crypto_drbg_seedlen >> 2); i++)
481 {
482 ((UINT*)seed_material)[i] ^= ((UINT*)drbg_ptr -> nx_crypto_drbg_buffer)[i];
483 }
484 #else
485 for (i = 0; i < drbg_ptr -> nx_crypto_drbg_seedlen; i++)
486 {
487 seed_material[i] ^= drbg_ptr -> nx_crypto_drbg_buffer[i];
488 }
489 #endif
490 }
491
492 _nx_crypto_drbg_update(drbg_ptr, seed_material);
493
494 drbg_ptr -> nx_crypto_drgb_reseed_counter = 1;
495
496 #ifdef NX_SECURE_KEY_CLEAR
497 NX_CRYPTO_MEMSET(seed_material, 0, sizeof(seed_material));
498 #endif /* NX_SECURE_KEY_CLEAR */
499
500 return(NX_CRYPTO_SUCCESS);
501 }
502
503
504 /**************************************************************************/
505 /* */
506 /* FUNCTION RELEASE */
507 /* */
508 /* _nx_crypto_drbg_generate PORTABLE C */
509 /* 6.1 */
510 /* AUTHOR */
511 /* */
512 /* Timothy Stapko, Microsoft Corporation */
513 /* */
514 /* DESCRIPTION */
515 /* */
516 /* This function generates requested number of bits from DRBG. */
517 /* */
518 /* INPUT */
519 /* */
520 /* drbg_ptr DRBG context */
521 /* */
522 /* OUTPUT */
523 /* */
524 /* status Completion status */
525 /* */
526 /* CALLS */
527 /* */
528 /* */
529 /* CALLED BY */
530 /* */
531 /* Application Code */
532 /* */
533 /* RELEASE HISTORY */
534 /* */
535 /* DATE NAME DESCRIPTION */
536 /* */
537 /* 05-19-2020 Timothy Stapko Initial Version 6.0 */
538 /* 09-30-2020 Timothy Stapko Modified comment(s), */
539 /* verified memcpy use cases, */
540 /* resulting in version 6.1 */
541 /* */
542 /**************************************************************************/
_nx_crypto_drbg_generate(NX_CRYPTO_DRBG * drbg_ptr,UCHAR * output,UINT output_length_in_byte,UCHAR * additional_input,UINT additional_input_len)543 NX_CRYPTO_KEEP UINT _nx_crypto_drbg_generate(NX_CRYPTO_DRBG *drbg_ptr,
544 UCHAR *output, UINT output_length_in_byte,
545 UCHAR *additional_input,
546 UINT additional_input_len)
547 {
548 NX_CRYPTO_METHOD *crypto_method;
549 UCHAR addition[NX_CRYPTO_DRBG_MAX_SEEDLEN];
550 UCHAR temp[NX_CRYPTO_DRBG_BLOCK_LENGTH_AES];
551 UCHAR *out_ptr;
552 UINT temp_len = 0;
553 UINT status = NX_CRYPTO_SUCCESS;
554 VOID *handler = NX_CRYPTO_NULL;
555
556 if (!drbg_ptr -> nx_crypto_drbg_instantiated)
557 {
558 return(NX_CRYPTO_NO_INSTANCE);
559 }
560
561 if (drbg_ptr -> nx_crypto_drgb_reseed_counter > NX_CRYPTO_DRBG_MAX_SEED_LIFE || drbg_ptr -> nx_crypto_drbg_prediction_resistance)
562 {
563 status = _nx_crypto_drbg_reseed(drbg_ptr, additional_input, additional_input_len);
564 if (status != NX_CRYPTO_SUCCESS)
565 {
566 return(status);
567 }
568
569 additional_input_len = 0;
570 }
571
572 if (drbg_ptr -> nx_crypto_drbg_use_df)
573 {
574 if (additional_input_len + NX_CRYPTO_DRBG_DF_INPUT_OFFSET >= NX_CRYPTO_DRBG_SEED_BUFFER_LEN)
575 {
576 return(NX_CRYPTO_SIZE_ERROR);
577 }
578
579 if (additional_input_len > 0 && additional_input != NX_CRYPTO_NULL)
580 {
581 /* additional_input = Block_Cipher_df (additional_input, 256). */
582 NX_CRYPTO_MEMCPY(drbg_ptr -> nx_crypto_drbg_buffer + NX_CRYPTO_DRBG_DF_INPUT_OFFSET, additional_input, additional_input_len); /* Use case of memcpy is verified. */
583
584 _nx_crypto_drbg_block_cipher_df(drbg_ptr, additional_input_len, addition, drbg_ptr -> nx_crypto_drbg_seedlen);
585
586 _nx_crypto_drbg_update(drbg_ptr, addition);
587 }
588 }
589 else
590 {
591 if (additional_input_len > drbg_ptr -> nx_crypto_drbg_seedlen)
592 {
593 return(NX_CRYPTO_SIZE_ERROR);
594 }
595
596 if (additional_input_len == drbg_ptr -> nx_crypto_drbg_seedlen && additional_input != NX_CRYPTO_NULL)
597 {
598 _nx_crypto_drbg_update(drbg_ptr, additional_input);
599 }
600 else if (additional_input_len > 0 && additional_input != NX_CRYPTO_NULL)
601 {
602 /* Ensure that the length of the additional_input is exactly seedlen bits. */
603 NX_CRYPTO_MEMCPY(addition, additional_input, additional_input_len); /* Use case of memcpy is verified. */
604 if (additional_input_len < drbg_ptr -> nx_crypto_drbg_seedlen)
605 {
606 NX_CRYPTO_MEMSET(&addition[additional_input_len], 0,
607 drbg_ptr -> nx_crypto_drbg_seedlen - additional_input_len);
608 }
609 _nx_crypto_drbg_update(drbg_ptr, addition);
610 }
611 }
612
613 if (additional_input_len == 0)
614 {
615 additional_input = NX_CRYPTO_NULL;
616 }
617
618 crypto_method = drbg_ptr -> nx_crypto_drbg_crypto_method;
619
620 /* Initialize crypto method with DRBG key. */
621 if (crypto_method -> nx_crypto_init)
622 {
623 status = crypto_method -> nx_crypto_init(crypto_method,
624 drbg_ptr -> nx_crypto_drbg_key,
625 crypto_method -> nx_crypto_key_size_in_bits,
626 &handler,
627 drbg_ptr -> nx_crypto_drbg_crypto_metadata,
628 crypto_method -> nx_crypto_metadata_area_size);
629
630 if (status != NX_CRYPTO_SUCCESS)
631 {
632 return(status);
633 }
634 }
635
636 while (temp_len < output_length_in_byte)
637 {
638 /* V = (V+1) mod 2^blocklen */
639 _nx_crypto_drbg_ctr_add_one(drbg_ptr -> nx_crypto_drbg_v);
640
641 if (output_length_in_byte - temp_len < NX_CRYPTO_DRBG_BLOCK_LENGTH_AES)
642 {
643 out_ptr = temp;
644 }
645 else
646 {
647 out_ptr = &output[temp_len];
648 }
649
650 status = crypto_method -> nx_crypto_operation(NX_CRYPTO_ENCRYPT,
651 handler,
652 crypto_method,
653 NX_CRYPTO_NULL,
654 crypto_method -> nx_crypto_key_size_in_bits,
655 (UCHAR *)drbg_ptr -> nx_crypto_drbg_v,
656 NX_CRYPTO_DRBG_BLOCK_LENGTH_AES,
657 (UCHAR *)zeroiv,
658 out_ptr,
659 NX_CRYPTO_DRBG_BLOCK_LENGTH_AES,
660 drbg_ptr -> nx_crypto_drbg_crypto_metadata,
661 crypto_method -> nx_crypto_metadata_area_size,
662 NX_CRYPTO_NULL, NX_CRYPTO_NULL);
663 if (status != NX_CRYPTO_SUCCESS)
664 {
665 return(status);
666 }
667
668 if (output_length_in_byte - temp_len < NX_CRYPTO_DRBG_BLOCK_LENGTH_AES)
669 {
670 NX_CRYPTO_MEMCPY(&output[temp_len], temp, output_length_in_byte - temp_len); /* Use case of memcpy is verified. */
671 }
672
673 temp_len += NX_CRYPTO_DRBG_BLOCK_LENGTH_AES;
674 }
675
676 if (crypto_method -> nx_crypto_cleanup)
677 {
678 status = crypto_method -> nx_crypto_cleanup(drbg_ptr -> nx_crypto_drbg_crypto_metadata);
679 if(status != NX_CRYPTO_SUCCESS)
680 {
681 return(status);
682 }
683 }
684
685 if (additional_input_len > 0 && (drbg_ptr -> nx_crypto_drbg_use_df || additional_input_len != drbg_ptr -> nx_crypto_drbg_seedlen))
686 {
687 _nx_crypto_drbg_update(drbg_ptr, addition);
688 }
689 else
690 {
691 _nx_crypto_drbg_update(drbg_ptr, additional_input);
692 }
693
694 drbg_ptr -> nx_crypto_drgb_reseed_counter++;
695
696 #ifdef NX_SECURE_KEY_CLEAR
697 NX_CRYPTO_MEMSET(addition, 0, sizeof(addition));
698 NX_CRYPTO_MEMSET(temp, 0, sizeof(temp));
699 #endif /* NX_SECURE_KEY_CLEAR */
700
701 return(NX_CRYPTO_SUCCESS);
702 }
703
704 /**************************************************************************/
705 /* */
706 /* FUNCTION RELEASE */
707 /* */
708 /* _nx_crypto_drbg_block_cipher_df PORTABLE C */
709 /* 6.1 */
710 /* AUTHOR */
711 /* */
712 /* Timothy Stapko, Microsoft Corporation */
713 /* */
714 /* DESCRIPTION */
715 /* */
716 /* This function generates requested number of bits from DRBG. */
717 /* */
718 /* INPUT */
719 /* */
720 /* drbg_ptr DRBG context */
721 /* */
722 /* OUTPUT */
723 /* */
724 /* status Completion status */
725 /* */
726 /* CALLS */
727 /* */
728 /* */
729 /* CALLED BY */
730 /* */
731 /* Application Code */
732 /* */
733 /* RELEASE HISTORY */
734 /* */
735 /* DATE NAME DESCRIPTION */
736 /* */
737 /* 05-19-2020 Timothy Stapko Initial Version 6.0 */
738 /* 09-30-2020 Timothy Stapko Modified comment(s), */
739 /* verified memcpy use cases, */
740 /* and updated constants, */
741 /* resulting in version 6.1 */
742 /* */
743 /**************************************************************************/
_nx_crypto_drbg_block_cipher_df(NX_CRYPTO_DRBG * drbg_ptr,UINT input_len,UCHAR * output,UINT output_len)744 NX_CRYPTO_KEEP static UINT _nx_crypto_drbg_block_cipher_df(NX_CRYPTO_DRBG *drbg_ptr, UINT input_len,
745 UCHAR *output, UINT output_len)
746 {
747 NX_CRYPTO_METHOD *crypto_method;
748 UINT status = 0;
749 UCHAR temp[NX_CRYPTO_DRBG_MAX_SEEDLEN];
750 UINT temp_len;
751 UINT s_len;
752 UINT i, j;
753 UCHAR bcc_chain[NX_CRYPTO_DRBG_BLOCK_LENGTH];
754 UCHAR *iv;
755 UCHAR *s;
756 UCHAR *out_ptr;
757 VOID *handler = NX_CRYPTO_NULL;
758
759
760 crypto_method = drbg_ptr -> nx_crypto_drbg_crypto_method;
761
762 /* Initialize crypto method with DRBG key. */
763 if (crypto_method -> nx_crypto_init)
764 {
765 status = crypto_method -> nx_crypto_init(crypto_method,
766 (UCHAR *)_nx_crypto_drbg_df_key,
767 crypto_method -> nx_crypto_key_size_in_bits,
768 &handler,
769 drbg_ptr -> nx_crypto_drbg_crypto_metadata,
770 crypto_method -> nx_crypto_metadata_area_size);
771
772 if (status != NX_CRYPTO_SUCCESS)
773 {
774 return(status);
775 }
776 }
777
778 iv = drbg_ptr -> nx_crypto_drbg_buffer;
779 s = &iv[NX_CRYPTO_DRBG_BLOCK_LENGTH];
780 NX_CRYPTO_MEMSET(iv, 0, NX_CRYPTO_DRBG_BLOCK_LENGTH);
781 s[0] = (UCHAR)((input_len >> 24) & 0xff);
782 s[1] = (UCHAR)((input_len >> 16) & 0xff);
783 s[2] = (UCHAR)((input_len >> 8) & 0xff);
784 s[3] = (UCHAR)(input_len & 0xff);
785 s[4] = (UCHAR)((output_len >> 24) & 0xff);
786 s[5] = (UCHAR)((output_len >> 16) & 0xff);
787 s[6] = (UCHAR)((output_len >> 8) & 0xff);
788 s[7] = (UCHAR)(output_len & 0xff);
789 s[input_len + 8] = 0x80;
790 s_len = NX_CRYPTO_DRBG_BLOCK_LENGTH + input_len + 8 + 1;
791 if (s_len % NX_CRYPTO_DRBG_BLOCK_LENGTH != 0)
792 {
793 NX_CRYPTO_MEMSET(&iv[s_len], 0, NX_CRYPTO_DRBG_BLOCK_LENGTH - (s_len % NX_CRYPTO_DRBG_BLOCK_LENGTH));
794 s_len += NX_CRYPTO_DRBG_BLOCK_LENGTH - (s_len % NX_CRYPTO_DRBG_BLOCK_LENGTH);
795 }
796
797 temp_len = 0;
798 while (temp_len < drbg_ptr -> nx_crypto_drbg_seedlen)
799 {
800 NX_CRYPTO_MEMSET(bcc_chain, 0, sizeof(bcc_chain));
801
802 for (i = 0; i < s_len; i += NX_CRYPTO_DRBG_BLOCK_LENGTH)
803 {
804 for (j = 0; j < NX_CRYPTO_DRBG_BLOCK_LENGTH; j++)
805 {
806 bcc_chain[j] ^= iv[i + j];
807 }
808
809 status = crypto_method -> nx_crypto_operation(NX_CRYPTO_ENCRYPT,
810 handler,
811 crypto_method,
812 NX_CRYPTO_NULL,
813 crypto_method -> nx_crypto_key_size_in_bits,
814 bcc_chain,
815 NX_CRYPTO_DRBG_BLOCK_LENGTH,
816 (UCHAR *)zeroiv,
817 bcc_chain,
818 NX_CRYPTO_DRBG_BLOCK_LENGTH,
819 drbg_ptr -> nx_crypto_drbg_crypto_metadata,
820 crypto_method -> nx_crypto_metadata_area_size,
821 NX_CRYPTO_NULL, NX_CRYPTO_NULL);
822 if (status != NX_CRYPTO_SUCCESS)
823 {
824 return(status);
825 }
826
827 }
828
829 NX_CRYPTO_MEMCPY(&temp[temp_len], bcc_chain, NX_CRYPTO_DRBG_BLOCK_LENGTH); /* Use case of memcpy is verified. */
830 temp_len += NX_CRYPTO_DRBG_BLOCK_LENGTH;
831
832 iv[3]++;
833 }
834
835 if (crypto_method -> nx_crypto_cleanup)
836 {
837 status = crypto_method -> nx_crypto_cleanup(drbg_ptr -> nx_crypto_drbg_crypto_metadata);
838 if(status != NX_CRYPTO_SUCCESS)
839 {
840 return(status);
841 }
842 }
843
844 if (crypto_method -> nx_crypto_init)
845 {
846 status = crypto_method -> nx_crypto_init(crypto_method,
847 temp,
848 crypto_method -> nx_crypto_key_size_in_bits,
849 &handler,
850 drbg_ptr -> nx_crypto_drbg_crypto_metadata,
851 crypto_method -> nx_crypto_metadata_area_size);
852
853 if (status != NX_CRYPTO_SUCCESS)
854 {
855 return(status);
856 }
857 }
858
859 s = &temp[crypto_method -> nx_crypto_key_size_in_bits >> 3];
860
861 temp_len = 0;
862 while (temp_len < output_len)
863 {
864 if (output_len - temp_len < NX_CRYPTO_DRBG_BLOCK_LENGTH)
865 {
866 out_ptr = bcc_chain;
867 }
868 else
869 {
870 out_ptr = &output[temp_len];
871 }
872
873 status = crypto_method -> nx_crypto_operation(NX_CRYPTO_ENCRYPT,
874 handler,
875 crypto_method,
876 NX_CRYPTO_NULL,
877 crypto_method -> nx_crypto_key_size_in_bits,
878 s,
879 NX_CRYPTO_DRBG_BLOCK_LENGTH_AES,
880 (UCHAR *)zeroiv,
881 out_ptr,
882 NX_CRYPTO_DRBG_BLOCK_LENGTH_AES,
883 drbg_ptr -> nx_crypto_drbg_crypto_metadata,
884 crypto_method -> nx_crypto_metadata_area_size,
885 NX_CRYPTO_NULL, NX_CRYPTO_NULL);
886 if (status != NX_CRYPTO_SUCCESS)
887 {
888 return(status);
889 }
890
891 s = out_ptr;
892
893 if (output_len - temp_len < NX_CRYPTO_DRBG_BLOCK_LENGTH_AES)
894 {
895 NX_CRYPTO_MEMCPY(&output[temp_len], bcc_chain, output_len - temp_len); /* Use case of memcpy is verified. */
896 }
897
898 temp_len += NX_CRYPTO_DRBG_BLOCK_LENGTH;
899 }
900
901 if (crypto_method -> nx_crypto_cleanup)
902 {
903 status = crypto_method -> nx_crypto_cleanup(drbg_ptr -> nx_crypto_drbg_crypto_metadata);
904 if(status != NX_CRYPTO_SUCCESS)
905 {
906 return(status);
907 }
908 }
909
910 #ifdef NX_SECURE_KEY_CLEAR
911 NX_CRYPTO_MEMSET(temp, 0, sizeof(temp));
912 NX_CRYPTO_MEMSET(bcc_chain, 0, sizeof(bcc_chain));
913 #endif /* NX_SECURE_KEY_CLEAR */
914
915 return(status);
916 }
917
918
919 /**************************************************************************/
920 /* */
921 /* FUNCTION RELEASE */
922 /* */
923 /* _nx_crypto_method_drbg_init PORTABLE C */
924 /* 6.3.0 */
925 /* AUTHOR */
926 /* */
927 /* Timothy Stapko, Microsoft Corporation */
928 /* */
929 /* DESCRIPTION */
930 /* */
931 /* This function is the common crypto method init callback for */
932 /* Microsoft supported DRBG cryptographic algorithm. */
933 /* */
934 /* INPUT */
935 /* */
936 /* method Pointer to crypto method */
937 /* key Pointer to key */
938 /* key_size_in_bits Length of key size in bits */
939 /* handler Returned crypto handler */
940 /* crypto_metadata Metadata area */
941 /* crypto_metadata_size Size of the metadata area */
942 /* */
943 /* OUTPUT */
944 /* */
945 /* status Completion status */
946 /* */
947 /* CALLS */
948 /* */
949 /* None */
950 /* */
951 /* CALLED BY */
952 /* */
953 /* Application Code */
954 /* */
955 /* RELEASE HISTORY */
956 /* */
957 /* DATE NAME DESCRIPTION */
958 /* */
959 /* 05-19-2020 Timothy Stapko Initial Version 6.0 */
960 /* 09-30-2020 Timothy Stapko Modified comment(s), */
961 /* resulting in version 6.1 */
962 /* 10-31-2023 Yanwu Cai Modified comment(s), */
963 /* resulting in version 6.3.0 */
964 /* */
965 /**************************************************************************/
_nx_crypto_method_drbg_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)966 NX_CRYPTO_KEEP UINT _nx_crypto_method_drbg_init(struct NX_CRYPTO_METHOD_STRUCT *method,
967 UCHAR *key, NX_CRYPTO_KEY_SIZE key_size_in_bits,
968 VOID **handle,
969 VOID *crypto_metadata,
970 ULONG crypto_metadata_size)
971 {
972
973 NX_CRYPTO_PARAMETER_NOT_USED(key);
974 NX_CRYPTO_PARAMETER_NOT_USED(key_size_in_bits);
975 NX_CRYPTO_PARAMETER_NOT_USED(handle);
976
977 NX_CRYPTO_STATE_CHECK
978
979 if ((method == NX_CRYPTO_NULL) || (crypto_metadata == NX_CRYPTO_NULL))
980 {
981 return(NX_CRYPTO_PTR_ERROR);
982 }
983
984 /* Verify the metadata address is 4-byte aligned. */
985 if((((ULONG)crypto_metadata) & 0x3) != 0)
986 {
987 return(NX_CRYPTO_PTR_ERROR);
988 }
989
990 if(crypto_metadata_size < sizeof(NX_CRYPTO_DRBG))
991 {
992 return(NX_CRYPTO_PTR_ERROR);
993 }
994
995 return(NX_CRYPTO_SUCCESS);
996 }
997
998
999 /**************************************************************************/
1000 /* */
1001 /* FUNCTION RELEASE */
1002 /* */
1003 /* _nx_crypto_method_drbg_cleanup PORTABLE C */
1004 /* 6.1 */
1005 /* AUTHOR */
1006 /* */
1007 /* Timothy Stapko, Microsoft Corporation */
1008 /* */
1009 /* DESCRIPTION */
1010 /* */
1011 /* This function cleans up the crypto metadata. */
1012 /* */
1013 /* INPUT */
1014 /* */
1015 /* crypto_metadata Crypto metadata */
1016 /* */
1017 /* OUTPUT */
1018 /* */
1019 /* status Completion status */
1020 /* */
1021 /* CALLS */
1022 /* */
1023 /* NX_CRYPTO_MEMSET Set the memory */
1024 /* */
1025 /* CALLED BY */
1026 /* */
1027 /* Application Code */
1028 /* */
1029 /* RELEASE HISTORY */
1030 /* */
1031 /* DATE NAME DESCRIPTION */
1032 /* */
1033 /* 05-19-2020 Timothy Stapko Initial Version 6.0 */
1034 /* 09-30-2020 Timothy Stapko Modified comment(s), */
1035 /* resulting in version 6.1 */
1036 /* */
1037 /**************************************************************************/
_nx_crypto_method_drbg_cleanup(VOID * crypto_metadata)1038 NX_CRYPTO_KEEP UINT _nx_crypto_method_drbg_cleanup(VOID *crypto_metadata)
1039 {
1040
1041 NX_CRYPTO_STATE_CHECK
1042
1043 #ifdef NX_SECURE_KEY_CLEAR
1044 if (!crypto_metadata)
1045 return (NX_CRYPTO_SUCCESS);
1046
1047 /* Clean up the crypto metadata. */
1048 NX_CRYPTO_MEMSET(crypto_metadata, 0, sizeof(NX_CRYPTO_DRBG));
1049 #else
1050 NX_CRYPTO_PARAMETER_NOT_USED(crypto_metadata);
1051 #endif/* NX_SECURE_KEY_CLEAR */
1052
1053 return(NX_CRYPTO_SUCCESS);
1054 }
1055
1056
1057 /**************************************************************************/
1058 /* */
1059 /* FUNCTION RELEASE */
1060 /* */
1061 /* _nx_crypto_method_drbg_operation PORTABLE C */
1062 /* 6.3.0 */
1063 /* AUTHOR */
1064 /* */
1065 /* Timothy Stapko, Microsoft Corporation */
1066 /* */
1067 /* DESCRIPTION */
1068 /* */
1069 /* This function performs a DRBG operation. */
1070 /* */
1071 /* INPUT */
1072 /* */
1073 /* op DRBG operation */
1074 /* handle Crypto handle */
1075 /* method Cryption Method Object */
1076 /* key Encryption Key */
1077 /* key_size_in_bits Key size in bits */
1078 /* input Input data */
1079 /* input_length_in_byte Input data size */
1080 /* iv_ptr Initial vector */
1081 /* output Output buffer */
1082 /* output_length_in_byte Output buffer size */
1083 /* crypto_metadata Metadata area */
1084 /* crypto_metadata_size Metadata area size */
1085 /* packet_ptr Pointer to packet */
1086 /* nx_crypto_hw_process_callback Callback function pointer */
1087 /* */
1088 /* OUTPUT */
1089 /* */
1090 /* status Completion status */
1091 /* */
1092 /* CALLS */
1093 /* */
1094 /* */
1095 /* CALLED BY */
1096 /* */
1097 /* Application Code */
1098 /* */
1099 /* RELEASE HISTORY */
1100 /* */
1101 /* DATE NAME DESCRIPTION */
1102 /* */
1103 /* 05-19-2020 Timothy Stapko Initial Version 6.0 */
1104 /* 09-30-2020 Timothy Stapko Modified comment(s), */
1105 /* resulting in version 6.1 */
1106 /* 10-31-2023 Yanwu Cai Modified comment(s), */
1107 /* resulting in version 6.3.0 */
1108 /* */
1109 /**************************************************************************/
_nx_crypto_method_drbg_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 *,UINT))1110 NX_CRYPTO_KEEP UINT _nx_crypto_method_drbg_operation(UINT op,
1111 VOID *handle,
1112 struct NX_CRYPTO_METHOD_STRUCT *method,
1113 UCHAR *key, NX_CRYPTO_KEY_SIZE key_size_in_bits,
1114 UCHAR *input, ULONG input_length_in_byte,
1115 UCHAR *iv_ptr,
1116 UCHAR *output, ULONG output_length_in_byte,
1117 VOID *crypto_metadata, ULONG crypto_metadata_size,
1118 VOID *packet_ptr,
1119 VOID (*nx_crypto_hw_process_callback)(VOID *, UINT))
1120 {
1121 NX_CRYPTO_DRBG *drbg;
1122 UINT status = NX_CRYPTO_SUCCESS;
1123
1124 NX_CRYPTO_PARAMETER_NOT_USED(handle);
1125 NX_CRYPTO_PARAMETER_NOT_USED(iv_ptr);
1126 NX_CRYPTO_PARAMETER_NOT_USED(packet_ptr);
1127 NX_CRYPTO_PARAMETER_NOT_USED(nx_crypto_hw_process_callback);
1128
1129 NX_CRYPTO_STATE_CHECK
1130
1131 /* Verify the metadata address is 4-byte aligned. */
1132 if((method == NX_CRYPTO_NULL) || (crypto_metadata == NX_CRYPTO_NULL) || ((((ULONG)crypto_metadata) & 0x3) != 0))
1133 {
1134 return(NX_CRYPTO_PTR_ERROR);
1135 }
1136
1137 if(crypto_metadata_size < sizeof(NX_CRYPTO_DRBG))
1138 {
1139 return(NX_CRYPTO_PTR_ERROR);
1140 }
1141
1142 drbg = (NX_CRYPTO_DRBG *)crypto_metadata;
1143
1144 if (op == NX_CRYPTO_DRBG_OPTIONS_SET)
1145 {
1146
1147 drbg -> nx_crypto_drbg_security_strength = ((NX_CRYPTO_DRBG_OPTIONS *)input) -> security_strength;
1148 drbg -> nx_crypto_drbg_get_entropy = ((NX_CRYPTO_DRBG_OPTIONS *)input) -> entropy_input;
1149 drbg -> nx_crypto_drbg_use_df = ((NX_CRYPTO_DRBG_OPTIONS *)input) -> use_df;
1150 drbg -> nx_crypto_drbg_prediction_resistance = ((NX_CRYPTO_DRBG_OPTIONS *)input) -> prediction_resistance;
1151 drbg -> nx_crypto_drbg_crypto_method = ((NX_CRYPTO_DRBG_OPTIONS *)input) -> crypto_method;
1152 drbg -> nx_crypto_drbg_crypto_metadata = ((NX_CRYPTO_DRBG_OPTIONS *)input) -> crypto_metadata;
1153 drbg -> nx_crypto_drbg_instantiated = 0;
1154 }
1155 else if (op == NX_CRYPTO_DRBG_INSTANTIATE)
1156 {
1157 if (key == NX_CRYPTO_NULL)
1158 {
1159 return(NX_CRYPTO_PTR_ERROR);
1160 }
1161
1162 status = _nx_crypto_drbg_instantiate(drbg,
1163 key,
1164 key_size_in_bits >> 3,
1165 input,
1166 input_length_in_byte);
1167 }
1168 else if (op == NX_CRYPTO_DRBG_RESEED)
1169 {
1170 status = _nx_crypto_drbg_reseed(drbg, input, input_length_in_byte);
1171 }
1172 else if (op == NX_CRYPTO_DRBG_GENERATE)
1173 {
1174 status = _nx_crypto_drbg_generate(drbg,
1175 output,
1176 output_length_in_byte,
1177 input,
1178 input_length_in_byte);
1179 }
1180 else
1181 {
1182 status = NX_CRYPTO_NOT_SUCCESSFUL;
1183 }
1184
1185 return(status);
1186 }
1187
_nx_crypto_drbg_rnd_entropy_input(UCHAR * entropy,UINT * entropy_len,UINT entropy_max_len)1188 NX_CRYPTO_KEEP static UINT _nx_crypto_drbg_rnd_entropy_input(UCHAR *entropy, UINT *entropy_len,
1189 UINT entropy_max_len)
1190 {
1191 UINT bytes;
1192 UINT random_number;
1193
1194 NX_CRYPTO_PARAMETER_NOT_USED(entropy_max_len);
1195
1196 bytes = *entropy_len;
1197
1198 while (bytes > 3)
1199 {
1200 random_number = (UINT)NX_CRYPTO_RAND();
1201 entropy[0] = (UCHAR)(random_number & 0xFF);
1202 entropy[1] = (UCHAR)((random_number >> 8) & 0xFF);
1203 entropy[2] = (UCHAR)((random_number >> 16) & 0xFF);
1204 entropy[3] = (UCHAR)((random_number >> 24) & 0xFF);
1205 entropy += 4;
1206 bytes -= 4;
1207 }
1208
1209 if (bytes == 0)
1210 {
1211 return(NX_CRYPTO_SUCCESS);
1212 }
1213
1214 random_number = (UINT)NX_CRYPTO_RAND();
1215 while (bytes > 0)
1216 {
1217 entropy[0] = (UCHAR)(random_number & 0xFF);
1218 random_number = random_number >> 8;
1219 entropy++;
1220 bytes--;
1221 }
1222
1223 return(NX_CRYPTO_SUCCESS);
1224 }
1225
_nx_crypto_drbg_initialize()1226 NX_CRYPTO_KEEP static UINT _nx_crypto_drbg_initialize()
1227 {
1228 UINT status;
1229
1230 _nx_crypto_drbg_ctx.nx_crypto_drbg_get_entropy = NX_CRYPTO_DRBG_ENTROPY_INPUT_FUNC;
1231 _nx_crypto_drbg_ctx.nx_crypto_drbg_use_df = NX_CRYPTO_DRBG_USE_DF;
1232 _nx_crypto_drbg_ctx.nx_crypto_drbg_prediction_resistance = NX_CRYPTO_DRBG_PREDICTION_RESISTANCE;
1233 _nx_crypto_drbg_ctx.nx_crypto_drbg_crypto_method = NX_CRYPTO_DRBG_CTR_CRYPTO_METHOD;
1234 _nx_crypto_drbg_ctx.nx_crypto_drbg_crypto_metadata = NX_CRYPTO_DRBG_CTR_CRYPTO_METADATA;
1235 _nx_crypto_drbg_ctx.nx_crypto_drbg_security_strength = _nx_crypto_drbg_ctx.nx_crypto_drbg_crypto_method -> nx_crypto_key_size_in_bits >> 3;
1236
1237
1238 status = _nx_crypto_drbg_instantiate(&_nx_crypto_drbg_ctx,
1239 NX_CRYPTO_NULL,
1240 0,
1241 NX_CRYPTO_NULL,
1242 0);
1243 return(status);
1244 }
1245
_nx_crypto_drbg(UINT bits,UCHAR * result)1246 NX_CRYPTO_KEEP UINT _nx_crypto_drbg(UINT bits, UCHAR *result)
1247 {
1248 UINT bytes;
1249 UINT mask;
1250 UINT status;
1251
1252 bytes = (bits + 7) >> 3;
1253
1254 NX_CRYPTO_DRBG_MUTEX_GET;
1255
1256 if (!_nx_crypto_drbg_ctx.nx_crypto_drbg_instantiated)
1257 {
1258 _nx_crypto_drbg_initialize();
1259 }
1260
1261 status = _nx_crypto_drbg_generate(&_nx_crypto_drbg_ctx, result, bytes, NX_CRYPTO_NULL, 0);
1262 if (status)
1263 {
1264 return(status);
1265 }
1266
1267 NX_CRYPTO_DRBG_MUTEX_PUT;
1268
1269 /* Zero out extra bits generated. */
1270 bits = bits & 7;
1271 if (bits)
1272 {
1273 mask = (UINT)((1 << bits) - 1);
1274 result[0] = (UCHAR)(result[0] & mask);
1275 }
1276
1277 return(status);
1278 }
1279