| /* | 
 |  * Copyright (c) 2019, NXP | 
 |  * | 
 |  * SPDX-License-Identifier: Apache-2.0 | 
 |  */ | 
 |  | 
 | #include <zephyr/init.h> | 
 | #include <zephyr/device.h> | 
 | #include <zephyr/drivers/entropy.h> | 
 | #include <zephyr/kernel.h> | 
 | #include <string.h> | 
 |  | 
 | #if defined(CONFIG_MBEDTLS) | 
 | #if !defined(CONFIG_MBEDTLS_CFG_FILE) | 
 | #include "mbedtls/config.h" | 
 | #else | 
 | #include CONFIG_MBEDTLS_CFG_FILE | 
 | #endif /* CONFIG_MBEDTLS_CFG_FILE */ | 
 | #include <mbedtls/ctr_drbg.h> | 
 |  | 
 | #elif defined(CONFIG_TINYCRYPT) | 
 |  | 
 | #include <tinycrypt/ctr_prng.h> | 
 | #include <tinycrypt/aes.h> | 
 | #include <tinycrypt/constants.h> | 
 |  | 
 | #endif /* CONFIG_MBEDTLS */ | 
 |  | 
 | static K_SEM_DEFINE(state_sem, 1, 1); | 
 |  | 
 | /* | 
 |  * entropy_dev is initialized at runtime to allow first time initialization | 
 |  * of the ctr_drbg engine. | 
 |  */ | 
 | static const struct device *entropy_dev; | 
 | static const unsigned char drbg_seed[] = CONFIG_CS_CTR_DRBG_PERSONALIZATION; | 
 | static bool ctr_initialised; | 
 |  | 
 | #if defined(CONFIG_MBEDTLS) | 
 |  | 
 | static mbedtls_ctr_drbg_context ctr_ctx; | 
 |  | 
 | static int ctr_drbg_entropy_func(void *ctx, unsigned char *buf, size_t len) | 
 | { | 
 | 	return entropy_get_entropy(entropy_dev, (void *)buf, len); | 
 | } | 
 |  | 
 | #elif defined(CONFIG_TINYCRYPT) | 
 |  | 
 | static TCCtrPrng_t ctr_ctx; | 
 |  | 
 | #endif /* CONFIG_MBEDTLS */ | 
 |  | 
 |  | 
 | static int ctr_drbg_initialize(void) | 
 | { | 
 | 	int ret; | 
 |  | 
 | 	entropy_dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_entropy)); | 
 |  | 
 | 	if (!device_is_ready(entropy_dev)) { | 
 | 		__ASSERT(0, "Entropy device %s not ready", entropy_dev->name); | 
 | 		return -ENODEV; | 
 | 	} | 
 |  | 
 | #if defined(CONFIG_MBEDTLS) | 
 |  | 
 | 	mbedtls_ctr_drbg_init(&ctr_ctx); | 
 |  | 
 | 	ret = mbedtls_ctr_drbg_seed(&ctr_ctx, | 
 | 				    ctr_drbg_entropy_func, | 
 | 				    NULL, | 
 | 				    drbg_seed, | 
 | 				    sizeof(drbg_seed)); | 
 |  | 
 | 	if (ret != 0) { | 
 | 		mbedtls_ctr_drbg_free(&ctr_ctx); | 
 | 		return -EIO; | 
 | 	} | 
 |  | 
 | #elif defined(CONFIG_TINYCRYPT) | 
 |  | 
 | 	uint8_t entropy[TC_AES_KEY_SIZE + TC_AES_BLOCK_SIZE]; | 
 |  | 
 | 	ret = entropy_get_entropy(entropy_dev, (void *)&entropy, | 
 | 				  sizeof(entropy)); | 
 | 	if (ret != 0) { | 
 | 		return -EIO; | 
 | 	} | 
 |  | 
 | 	ret = tc_ctr_prng_init(&ctr_ctx, | 
 | 			       (uint8_t *)&entropy, | 
 | 			       sizeof(entropy), | 
 | 			       (uint8_t *)drbg_seed, | 
 | 			       sizeof(drbg_seed)); | 
 |  | 
 | 	if (ret == TC_CRYPTO_FAIL) { | 
 | 		return -EIO; | 
 | 	} | 
 |  | 
 | #endif | 
 | 	ctr_initialised = true; | 
 | 	return 0; | 
 | } | 
 |  | 
 |  | 
 | int z_impl_sys_csrand_get(void *dst, uint32_t outlen) | 
 | { | 
 | 	int ret; | 
 | 	unsigned int key = irq_lock(); | 
 |  | 
 | 	if (unlikely(!ctr_initialised)) { | 
 | 		ret = ctr_drbg_initialize(); | 
 | 		if (ret != 0) { | 
 | 			ret = -EIO; | 
 | 			goto end; | 
 | 		} | 
 | 	} | 
 |  | 
 | #if defined(CONFIG_MBEDTLS) | 
 |  | 
 | 	ret = mbedtls_ctr_drbg_random(&ctr_ctx, (unsigned char *)dst, outlen); | 
 |  | 
 | #elif defined(CONFIG_TINYCRYPT) | 
 |  | 
 | 	uint8_t entropy[TC_AES_KEY_SIZE + TC_AES_BLOCK_SIZE]; | 
 |  | 
 | 	ret = tc_ctr_prng_generate(&ctr_ctx, 0, 0, (uint8_t *)dst, outlen); | 
 |  | 
 | 	if (ret == TC_CRYPTO_SUCCESS) { | 
 | 		ret = 0; | 
 | 	} else if (ret == TC_CTR_PRNG_RESEED_REQ) { | 
 |  | 
 | 		ret = entropy_get_entropy(entropy_dev, | 
 | 				    (void *)&entropy, sizeof(entropy)); | 
 | 		if (ret != 0) { | 
 | 			ret = -EIO; | 
 | 			goto end; | 
 | 		} | 
 |  | 
 | 		ret = tc_ctr_prng_reseed(&ctr_ctx, | 
 | 					entropy, | 
 | 					sizeof(entropy), | 
 | 					drbg_seed, | 
 | 					sizeof(drbg_seed)); | 
 |  | 
 | 		ret = tc_ctr_prng_generate(&ctr_ctx, 0, 0, | 
 | 					   (uint8_t *)dst, outlen); | 
 |  | 
 | 		ret = (ret == TC_CRYPTO_SUCCESS) ? 0 : -EIO; | 
 | 	} else { | 
 | 		ret = -EIO; | 
 | 	} | 
 | #endif | 
 | end: | 
 | 	irq_unlock(key); | 
 |  | 
 | 	return ret; | 
 | } |