You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
159 lines
3.1 KiB
159 lines
3.1 KiB
/* |
|
* Copyright (c) 2019, NXP |
|
* |
|
* SPDX-License-Identifier: Apache-2.0 |
|
*/ |
|
|
|
#include <init.h> |
|
#include <device.h> |
|
#include <drivers/entropy.h> |
|
#include <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); |
|
|
|
static const struct device *entropy_driver; |
|
static const unsigned char drbg_seed[] = CONFIG_CS_CTR_DRBG_PERSONALIZATION; |
|
|
|
#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_driver, (void *)buf, len); |
|
} |
|
|
|
#elif defined(CONFIG_TINYCRYPT) |
|
|
|
static TCCtrPrng_t ctr_ctx; |
|
|
|
#endif /* CONFIG_MBEDTLS */ |
|
|
|
|
|
static int ctr_drbg_initialize(void) |
|
{ |
|
int ret; |
|
|
|
/* Only one entropy device exists, so this is safe even |
|
* if the whole operation isn't atomic. |
|
*/ |
|
entropy_driver = device_get_binding(DT_CHOSEN_ZEPHYR_ENTROPY_LABEL); |
|
if (!entropy_driver) { |
|
__ASSERT((entropy_driver != NULL), |
|
"Device driver for %s (DT_CHOSEN_ZEPHYR_ENTROPY_LABEL) not found. " |
|
"Check your build configuration!", |
|
DT_CHOSEN_ZEPHYR_ENTROPY_LABEL); |
|
return -EINVAL; |
|
} |
|
|
|
#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_driver, (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 |
|
|
|
return 0; |
|
} |
|
|
|
|
|
int z_impl_sys_csrand_get(void *dst, uint32_t outlen) |
|
{ |
|
int ret; |
|
unsigned int key = irq_lock(); |
|
|
|
if (unlikely(!entropy_driver)) { |
|
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_driver, |
|
(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; |
|
}
|
|
|