1 /*
2  * Copyright (c) 2019-2023, Texas Instruments Incorporated
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * *  Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  *
12  * *  Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * *  Neither the name of Texas Instruments Incorporated nor the names of
17  *    its contributors may be used to endorse or promote products derived
18  *    from this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
22  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
27  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
30  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32 
33 #include <stdint.h>
34 #include <stdbool.h>
35 #include <string.h>
36 
37 #include <ti/drivers/dpl/DebugP.h>
38 #include <ti/drivers/dpl/HwiP.h>
39 #include <ti/drivers/dpl/SwiP.h>
40 #include <ti/drivers/dpl/SemaphoreP.h>
41 
42 #include <ti/drivers/AESCTRDRBG.h>
43 #include <ti/drivers/aesctrdrbg/AESCTRDRBGXX.h>
44 #include <ti/drivers/AESCTR.h>
45 #include <ti/drivers/cryptoutils/cryptokey/CryptoKey.h>
46 #include <ti/drivers/cryptoutils/cryptokey/CryptoKeyPlaintext.h>
47 #include <ti/drivers/cryptoutils/utils/CryptoUtils.h>
48 
49 #include <ti/devices/DeviceFamily.h>
50 #include DeviceFamily_constructPath(driverlib/aes.h)
51 
52 #if (ENABLE_KEY_STORAGE == 1)
53     #include <ti/drivers/cryptoutils/cryptokey/CryptoKeyKeyStore_PSA.h>
54     #include <ti/drivers/cryptoutils/cryptokey/CryptoKeyKeyStore_PSA_helpers.h>
55     #include <ti/drivers/cryptoutils/cryptokey/CryptoKeyKeyStore_PSA_init.h>
56     #if (TFM_ENABLED == 1)
57         #include <ti/drivers/cryptoutils/cryptokey/CryptoKeyKeyStore_PSA_s.h>
58     #endif
59 #endif
60 
61 #if (DeviceFamily_PARENT == DeviceFamily_PARENT_CC23X0) || (DeviceFamily_PARENT == DeviceFamily_PARENT_CC27XX)
62     #include <ti/drivers/aesctr/AESCTRLPF3.h>
63 #else
64     #include <ti/drivers/aesctr/AESCTRCC26XX.h>
65 #endif
66 
67 /* Forward declarations */
68 static void AESCTRDRBGXX_addBigendCounter(uint8_t *counter, uint32_t increment);
69 static int_fast16_t AESCTRDRBGXX_updateState(AESCTRDRBG_Handle handle,
70                                              const void *additionalData,
71                                              size_t additionalDataLength);
72 static void AESCTRDRBG_uninstantiate(AESCTRDRBG_Handle handle);
73 
74 /* Static globals */
75 static bool isInitialized = false;
76 
77 #define CEIL(x, y) (1 + (((x)-1) / (y)))
78 
79 /*
80  *  ======== AESCTRDRBG_init ========
81  */
AESCTRDRBG_init(void)82 void AESCTRDRBG_init(void)
83 {
84     AESCTR_init();
85 
86     isInitialized = true;
87 }
88 
89 /*
90  *  ======== AESCTRDRBGXX_updateState ========
91  */
AESCTRDRBGXX_updateState(AESCTRDRBG_Handle handle,const void * additionalData,size_t additionalDataLength)92 static int_fast16_t AESCTRDRBGXX_updateState(AESCTRDRBG_Handle handle,
93                                              const void *additionalData,
94                                              size_t additionalDataLength)
95 {
96     AESCTRDRBGXX_Object *object;
97     AESCTR_Operation operation;
98     /*
99      * Buffer must be word aligned as some AESCTR implementations require
100      * word aligned I/O.
101      */
102     uint32_t buf32[(AESCTRDRBG_MAX_SEED_LENGTH + 3) / 4] = {0};
103 
104     object = handle->object;
105 
106     /*
107      * We need to increment the counter here since regular AESCTR
108      * only increments the counter after encrypting it while
109      * AESCTRDRBG increments the counter before encrypting it.
110      * We do not need to worry about the counter being 1 over afterwards
111      * as we will replace the global counter with part of the
112      * encrypted result.
113      */
114     AESCTRDRBGXX_addBigendCounter(object->counter, 1);
115 
116     /*
117      * Wrap the memcpy below in a zero-length check. Do not remove it!
118      * The explicit check is necessary for klocwork to stop emitting a critical
119      * warning. Theoretically, memcpy with a length argument of 0 should do
120      * nothing. However klocwork emits a warning that there is an out
121      * of bounds array access (underflow) on buf32 if this check is not in place.
122      */
123     if (additionalDataLength > 0)
124     {
125         /*
126          * Copy over any additional data and operate on buf32 in place. This way
127          * we can have the case where additionalDataLength < seedLength. This is
128          * useful in AESCTRDRBG_getBytes() to avoid allocating a spare empty
129          * buffer.
130          */
131         memcpy(buf32, additionalData, additionalDataLength);
132     }
133 
134     operation.key            = &object->key;
135     operation.input          = (uint8_t *)buf32;
136     operation.output         = (uint8_t *)buf32;
137     operation.initialCounter = object->counter;
138     operation.inputLength    = object->key.u.plaintext.keyLength + AESCTRDRBG_AES_BLOCK_SIZE_BYTES;
139 
140     if (AESCTR_oneStepEncrypt(object->ctrHandle, &operation) != AESCTR_STATUS_SUCCESS)
141     {
142         return AESCTRDRBG_STATUS_ERROR;
143     }
144 
145     /* Copy the left most keyLength bytes of the computed result */
146     memcpy(object->keyingMaterial, buf32, object->key.u.plaintext.keyLength);
147 
148     /*
149      * Copy new counter value as the right most 16 bytes of the computed result.
150      * The key length is always a word multiple number of bytes so we can divide
151      * by word size to determine the buf32 index.
152      */
153     memcpy(object->counter,
154            &buf32[object->key.u.plaintext.keyLength / sizeof(uint32_t)],
155            AESCTRDRBG_AES_BLOCK_SIZE_BYTES);
156 
157     /* Wipe the stack buffer */
158     memset(buf32, 0, object->seedLength);
159 
160     return AESCTRDRBG_STATUS_SUCCESS;
161 }
162 
163 /*
164  *  ======== AESCTRDRBGXX_addBigendCounter ========
165  */
AESCTRDRBGXX_addBigendCounter(uint8_t * counter,uint32_t increment)166 static void AESCTRDRBGXX_addBigendCounter(uint8_t *counter, uint32_t increment)
167 {
168     uint64_t *counter64 = (uint64_t *)counter;
169     uint64_t prior;
170 
171     /* Turn it into a little-endian counter */
172     CryptoUtils_reverseBufferBytewise(counter64, AESCTRDRBG_AES_BLOCK_SIZE_BYTES);
173 
174     prior = counter64[0];
175 
176     /* Increment as a 64-bit number */
177     counter64[0] += increment;
178 
179     /* Check if we wrapped and need to increment the upper 64 bits */
180     if (counter64[0] < prior)
181     {
182         counter64[1]++;
183     }
184 
185     /* Turn it back into a big-endian integer */
186     CryptoUtils_reverseBufferBytewise(counter64, AESCTRDRBG_AES_BLOCK_SIZE_BYTES);
187 }
188 
189 /*
190  *  ======== AESCTRDRBG_uninstantiate ========
191  *
192  *  Per the NIST Recommendation SP 800-90A Rev. 1 for DRBG, uninstantiate is the operation
193  *  of clearing the internal state {keyingMaterial, counter, reseedCounter} by writing
194  *  all 0's. Once uninstantiated, the DRBG instance shall not be used until it's
195  *  instantiated again with a fresh seed.
196  *
197  *  This implementation also sets the isInstantiated flag to false. This function
198  *  should be called if any of the AESCTR operations fail so that the DRBG instance
199  *  will never be usable when its internal state is potentially corrupt.
200  */
AESCTRDRBG_uninstantiate(AESCTRDRBG_Handle handle)201 static void AESCTRDRBG_uninstantiate(AESCTRDRBG_Handle handle)
202 {
203     AESCTRDRBGXX_Object *object;
204 
205     object = handle->object;
206 
207     object->isInstantiated = false;
208     memset(object->keyingMaterial, 0, object->key.u.plaintext.keyLength);
209     memset(object->counter, 0, AESCTRDRBG_AES_BLOCK_SIZE_BYTES);
210     object->reseedCounter = 0;
211 }
212 
213 /*
214  *  ======== AESCTRDRBG_construct ========
215  */
AESCTRDRBG_construct(AESCTRDRBG_Config * config,const AESCTRDRBG_Params * params)216 AESCTRDRBG_Handle AESCTRDRBG_construct(AESCTRDRBG_Config *config, const AESCTRDRBG_Params *params)
217 {
218     AESCTRDRBG_Handle handle = (AESCTRDRBG_Handle)config;
219     AESCTRDRBGXX_Object *object;
220     const AESCTRDRBGXX_HWAttrs *hwAttrs;
221     AESCTR_Params ctrParams;
222     uintptr_t key;
223     int_fast16_t status;
224 
225     /* There are no valid default params for this driver */
226     if (params == NULL)
227     {
228         return NULL;
229     }
230 
231     DebugP_assert(handle);
232     object  = handle->object;
233     hwAttrs = handle->hwAttrs;
234 
235     key = HwiP_disable();
236 
237     if (!isInitialized || object->isOpen)
238     {
239         HwiP_restore(key);
240         return NULL;
241     }
242 
243     object->isOpen = true;
244 
245     HwiP_restore(key);
246 
247     /*
248      * personalizationDataLength must be within
249      * [0, AESCTRDRBG_AES_BLOCK_SIZE_BYTES + KeyLength] bytes.
250      */
251     if (params->personalizationDataLength > params->keyLength + AESCTRDRBG_AES_BLOCK_SIZE_BYTES)
252     {
253         return NULL;
254     }
255 
256     /* Open the driver's AESCTR instance */
257     AESCTR_Params_init(&ctrParams);
258 #if (TFM_ENABLED == 0)
259     ctrParams.returnBehavior = (AESCTR_ReturnBehavior)(params->returnBehavior);
260 #else
261     /*
262      * For the secure-only implementation, AESCTRDRBG supports blocking or
263      * polling return behavior.  However, when TF-M is enabled, polling return
264      * behavior must be forced since drivers cannot block inside the TF-M.
265      */
266     ctrParams.returnBehavior = AESCTR_RETURN_BEHAVIOR_POLLING;
267 #endif
268 
269     /* Zero out the AESCTR object to ensure AESCTR_construct() will not fail */
270     memset(&object->aesctrObject, 0, sizeof(object->aesctrObject));
271     object->ctrConfig.object  = &object->aesctrObject;
272     object->ctrConfig.hwAttrs = &hwAttrs->aesctrHWAttrs;
273 
274     object->ctrHandle = AESCTR_construct(&object->ctrConfig, &ctrParams);
275 
276     if (object->ctrHandle == NULL)
277     {
278         object->isOpen = false;
279 
280         return NULL;
281     }
282 
283     /* Initialize CryptoKey for later use */
284     CryptoKeyPlaintext_initKey(&object->key, object->keyingMaterial, params->keyLength);
285 
286     /* Zero-out counter and keyingMaterial */
287     memset(object->counter, 0, AESCTRDRBG_AES_BLOCK_SIZE_BYTES);
288     memset(object->keyingMaterial, 0, params->keyLength);
289 
290     /* Store constants for later */
291     object->seedLength     = params->keyLength + AESCTRDRBG_AES_BLOCK_SIZE_BYTES;
292     object->reseedInterval = params->reseedInterval;
293 
294     /* Ideally this should be set only after instantiation is complete. However
295      * since this implementation uses the reseed function, this flag is set here
296      * to ensure it doesn't fail with AESCTRDRBG_STATUS_UNINSTANTIATED.
297      * Note that if reseed fails due to other reasons, the following call to
298      * uninstantiate will clear this flag.
299      */
300     object->isInstantiated = true;
301 
302     /* Reseed the instance to generate the initial (counter, keyingMaterial) pair */
303     status = AESCTRDRBG_reseed(handle, params->seed, params->personalizationData, params->personalizationDataLength);
304 
305     if (status != AESCTRDRBG_STATUS_SUCCESS)
306     {
307         AESCTR_close(object->ctrHandle);
308         AESCTRDRBG_uninstantiate(handle);
309         object->isOpen = false;
310 
311         return NULL;
312     }
313 
314     return handle;
315 }
316 
317 /*
318  *  ======== AESCTRDRBG_close ========
319  */
AESCTRDRBG_close(AESCTRDRBG_Handle handle)320 void AESCTRDRBG_close(AESCTRDRBG_Handle handle)
321 {
322     AESCTRDRBGXX_Object *object;
323 
324     DebugP_assert(handle);
325 
326     /* Get the pointer to the object and hwAttrs */
327     object = handle->object;
328 
329     AESCTR_close(object->ctrHandle);
330 
331     AESCTRDRBG_uninstantiate(handle);
332 
333     /* Mark the module as available */
334     object->isOpen = false;
335 }
336 
337 /*
338  *  ======== AESCTRDRBG_getBytes ========
339  */
AESCTRDRBG_getBytes(AESCTRDRBG_Handle handle,CryptoKey * randomBytes)340 int_fast16_t AESCTRDRBG_getBytes(AESCTRDRBG_Handle handle, CryptoKey *randomBytes)
341 {
342     return AESCTRDRBG_generateKey(handle, randomBytes);
343 }
344 
345 /*
346  *  ======== AESCTRDRBG_generateKey ========
347  */
AESCTRDRBG_generateKey(AESCTRDRBG_Handle handle,CryptoKey * randomKey)348 int_fast16_t AESCTRDRBG_generateKey(AESCTRDRBG_Handle handle, CryptoKey *randomKey)
349 {
350     int_fast16_t status = AESCTRDRBG_STATUS_ERROR;
351 #if (ENABLE_KEY_STORAGE == 1)
352     int_fast16_t keyStoreStatus = KEYSTORE_PSA_STATUS_GENERIC_ERROR;
353     uint8_t KeyStore_keyingMaterial[AESCTRDRBG_MAX_KEYSTORE_KEY_SIZE];
354     KeyStore_PSA_KeyAttributes attributes = KEYSTORE_PSA_KEY_ATTRIBUTES_INIT;
355     KeyStore_PSA_KeyAttributes *attributesPtr;
356 
357     attributesPtr = &attributes;
358 
359 #endif /* ENABLE_KEY_STORAGE */
360 
361     if (randomKey != NULL)
362     {
363         if (randomKey->encoding == CryptoKey_BLANK_PLAINTEXT)
364         {
365             status = AESCTRDRBG_getRandomBytes(handle,
366                                                randomKey->u.plaintext.keyMaterial,
367                                                randomKey->u.plaintext.keyLength);
368             if (status == AESCTRDRBG_STATUS_SUCCESS)
369             {
370                 randomKey->encoding = CryptoKey_PLAINTEXT;
371             }
372         }
373 #if (ENABLE_KEY_STORAGE == 1)
374         else if (randomKey->encoding == CryptoKey_BLANK_KEYSTORE)
375         {
376             if ((randomKey->u.keyStore.keyLength != 0) &&
377                 (randomKey->u.keyStore.keyLength <= AESCTRDRBG_MAX_KEYSTORE_KEY_SIZE))
378             {
379                 /* Copy keyAttributes from CryptoKey structure */
380     #if (TFM_ENABLED == 0)
381                 attributesPtr = (KeyStore_PSA_KeyAttributes *)randomKey->u.keyStore.keyAttributes;
382     #else
383                 keyStoreStatus = KeyStore_s_copyKeyAttributesFromClient((struct psa_client_key_attributes_s *)
384                                                                             randomKey->u.keyStore.keyAttributes,
385                                                                         KEYSTORE_PSA_DEFAULT_OWNER,
386                                                                         attributesPtr);
387     #endif
388                 status = AESCTRDRBG_getRandomBytes(handle, KeyStore_keyingMaterial, randomKey->u.keyStore.keyLength);
389 
390                 if (status == AESCTRDRBG_STATUS_SUCCESS)
391                 {
392                     keyStoreStatus = KeyStore_PSA_importKey(attributesPtr,
393                                                             KeyStore_keyingMaterial,
394                                                             randomKey->u.keyStore.keyLength,
395                                                             &attributesPtr->MBEDTLS_PRIVATE(core).MBEDTLS_PRIVATE(id));
396                     if (keyStoreStatus == KEYSTORE_PSA_STATUS_SUCCESS)
397                     {
398                         if (attributesPtr->MBEDTLS_PRIVATE(core).MBEDTLS_PRIVATE(lifetime) ==
399                             KEYSTORE_PSA_KEY_LIFETIME_VOLATILE)
400                         {
401                             /* Set the keyID of volatile keys provided by KeyStore driver in the cryptokey structure */
402                             KeyStore_PSA_initKey(randomKey,
403                                                  attributesPtr->MBEDTLS_PRIVATE(core).MBEDTLS_PRIVATE(id),
404                                                  randomKey->u.keyStore.keyLength,
405                                                  NULL);
406                         }
407                         else
408                         {
409                             /* Only update the KeyStore encoding for persistent keys */
410                             randomKey->encoding = CryptoKey_KEYSTORE;
411                         }
412                         status = AESCTRDRBG_STATUS_SUCCESS;
413                     }
414                     else
415                     {
416                         status = AESCTRDRBG_STATUS_KEYSTORE_ERROR;
417                     }
418                 }
419             }
420         }
421 #endif /* ENABLE_KEY_STORAGE */
422     }
423 
424     return status;
425 }
426 
427 /*
428  *  ======== AESCTRDRBG_getRandomBytes ========
429  */
AESCTRDRBG_getRandomBytes(AESCTRDRBG_Handle handle,void * randomBytes,size_t randomBytesSize)430 int_fast16_t AESCTRDRBG_getRandomBytes(AESCTRDRBG_Handle handle, void *randomBytes, size_t randomBytesSize)
431 {
432     AESCTRDRBGXX_Object *object;
433     AESCTR_Operation operation;
434     int_fast16_t status;
435     bool lockAcquired;
436     uint32_t lockAcquireTimeout;
437 
438     object = handle->object;
439 
440     if (object->isInstantiated == false)
441     {
442         return AESCTRDRBG_STATUS_UNINSTANTIATED;
443     }
444 
445     if (object->reseedCounter >= object->reseedInterval)
446     {
447         return AESCTRDRBG_STATUS_RESEED_REQUIRED;
448     }
449 
450     if (SwiP_inISR() || HwiP_inISR())
451     {
452         lockAcquireTimeout = SemaphoreP_NO_WAIT;
453     }
454     else
455     {
456         lockAcquireTimeout = SemaphoreP_WAIT_FOREVER;
457     }
458 
459     lockAcquired = AESCTR_acquireLock(object->ctrHandle, lockAcquireTimeout);
460     if (!lockAcquired)
461     {
462         return AESCTRDRBG_STATUS_RESOURCE_UNAVAILABLE;
463     }
464 
465     AESCTR_disableThreadSafety(object->ctrHandle);
466 
467     /* Set the keying material of the CryptoKey to 0.
468      * If we use AESCTR to encrypt a buffer full of zeros,
469      * the resultant output will be the bitstream of the
470      * encrypted counters. That is what is used as
471      * random bits by AESCTRDRBG.
472      * Zeroing out the keying material and performing
473      * the AESCTR encryption in place saves us from
474      * allocating a buffer of the right length full
475      * of zeros or repeatedly encrypting a 16-byte
476      * buffer full of zeros.
477      */
478     memset(randomBytes, 0, randomBytesSize);
479 
480     /* We need to increment the counter here since regular AESCTR
481      * only increments the counter after encrypting it while
482      * AESCTRDRBG increments the counter before encrypting it.
483      */
484     AESCTRDRBGXX_addBigendCounter(object->counter, 1);
485 
486     operation.key            = &object->key;
487     operation.input          = randomBytes;
488     operation.output         = randomBytes;
489     operation.initialCounter = object->counter;
490     operation.inputLength    = randomBytesSize;
491 
492     status = AESCTR_oneStepEncrypt(object->ctrHandle, &operation);
493 
494     if (status != AESCTR_STATUS_SUCCESS)
495     {
496         AESCTR_releaseLock(object->ctrHandle);
497 
498         if (status == AESCTR_STATUS_UNALIGNED_IO_NOT_SUPPORTED)
499         {
500             status = AESCTRDRBG_STATUS_UNALIGNED_IO_NOT_SUPPORTED;
501         }
502         else
503         {
504             AESCTRDRBG_uninstantiate(handle);
505             status = AESCTRDRBG_STATUS_UNINSTANTIATED;
506         }
507 
508         return status;
509     }
510 
511     /* Add the number of counter blocks we produced to the
512      * internal counter. We already incremented by one above
513      * so we increment by one less here.
514      */
515     AESCTRDRBGXX_addBigendCounter(object->counter, CEIL(randomBytesSize, AESCTRDRBG_AES_BLOCK_SIZE_BYTES) - 1);
516 
517     status = AESCTRDRBGXX_updateState(handle, NULL, 0);
518 
519     AESCTR_enableThreadSafety(object->ctrHandle);
520     AESCTR_releaseLock(object->ctrHandle);
521 
522     if (status != AESCTRDRBG_STATUS_SUCCESS)
523     {
524         AESCTRDRBG_uninstantiate(handle);
525         return AESCTRDRBG_STATUS_UNINSTANTIATED;
526     }
527 
528     object->reseedCounter += 1;
529 
530     return AESCTRDRBG_STATUS_SUCCESS;
531 }
532 
533 /*
534  *  ======== AESCTRDRBG_reseed ========
535  */
AESCTRDRBG_reseed(AESCTRDRBG_Handle handle,const void * seed,const void * additionalData,size_t additionalDataLength)536 int_fast16_t AESCTRDRBG_reseed(AESCTRDRBG_Handle handle,
537                                const void *seed,
538                                const void *additionalData,
539                                size_t additionalDataLength)
540 {
541     AESCTRDRBGXX_Object *object;
542     int_fast16_t status;
543     uint8_t tmp[AESCTRDRBG_MAX_SEED_LENGTH];
544     uint32_t i;
545     bool lockAcquired;
546     uint32_t lockAcquireTimeout;
547 
548     object = handle->object;
549 
550     if (object->isInstantiated == false)
551     {
552         return AESCTRDRBG_STATUS_UNINSTANTIATED;
553     }
554 
555     if (additionalDataLength > object->seedLength)
556     {
557         return AESCTRDRBG_STATUS_ERROR;
558     }
559 
560     if (SwiP_inISR() || HwiP_inISR())
561     {
562         lockAcquireTimeout = SemaphoreP_NO_WAIT;
563     }
564     else
565     {
566         lockAcquireTimeout = SemaphoreP_WAIT_FOREVER;
567     }
568 
569     lockAcquired = AESCTR_acquireLock(object->ctrHandle, lockAcquireTimeout);
570     if (!lockAcquired)
571     {
572         return AESCTRDRBG_STATUS_RESOURCE_UNAVAILABLE;
573     }
574 
575     AESCTR_disableThreadSafety(object->ctrHandle);
576 
577     /* Set temporary buffer as additionalData padded with zeros */
578     memset(tmp, 0, object->seedLength);
579     memcpy(tmp, additionalData, additionalDataLength);
580 
581     /* XOR-in the seed. It should always be a multiple of 32 bits */
582     for (i = 0; i < object->seedLength / sizeof(uint32_t); i++)
583     {
584         ((uint32_t *)tmp)[i] ^= ((uint32_t *)seed)[i];
585     }
586 
587     /* Use the combined seed to generate a new (counter, keyingMaterial) pair */
588     status = AESCTRDRBGXX_updateState(handle, tmp, object->seedLength);
589 
590     AESCTR_enableThreadSafety(object->ctrHandle);
591     AESCTR_releaseLock(object->ctrHandle);
592 
593     if (status != AESCTRDRBG_STATUS_SUCCESS)
594     {
595         AESCTRDRBG_uninstantiate(handle);
596         return AESCTRDRBG_STATUS_UNINSTANTIATED;
597     }
598 
599     object->reseedCounter = 1;
600 
601     return AESCTRDRBG_STATUS_SUCCESS;
602 }
603