160 lines
3.1 KiB
C
160 lines
3.1 KiB
C
/*
|
|
* 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;
|
|
}
|