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