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