/* * Copyright (c) 2019, NXP * * SPDX-License-Identifier: Apache-2.0 */ #include #include #include #include #include #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 #elif defined(CONFIG_TINYCRYPT) #include #include #include #endif /* CONFIG_MBEDTLS */ static K_SEM_DEFINE(state_sem, 1, 1); static const struct device *entropy_dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_entropy)); 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_dev, (void *)buf, len); } #elif defined(CONFIG_TINYCRYPT) static TCCtrPrng_t ctr_ctx; #endif /* CONFIG_MBEDTLS */ static int ctr_drbg_initialize(void) { int ret; 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 return 0; } int z_impl_sys_csrand_get(void *dst, uint32_t outlen) { int ret; unsigned int key = irq_lock(); if (unlikely(!entropy_dev)) { 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; }