|  | /* | 
|  | * Copyright (c) 2017 Intel Corporation | 
|  | * | 
|  | * SPDX-License-Identifier: Apache-2.0 | 
|  | */ | 
|  |  | 
|  | #include <zephyr/sys/atomic.h> | 
|  | #include <zephyr/kernel.h> | 
|  | #include <zephyr/drivers/entropy.h> | 
|  | #include <string.h> | 
|  |  | 
|  | static const struct device *const entropy_dev = | 
|  | DEVICE_DT_GET(DT_CHOSEN(zephyr_entropy)); | 
|  |  | 
|  | static int rand_get(uint8_t *dst, size_t outlen, bool csrand) | 
|  | { | 
|  | uint32_t random_num; | 
|  | int ret; | 
|  |  | 
|  | __ASSERT(device_is_ready(entropy_dev), "Entropy device %s not ready", | 
|  | entropy_dev->name); | 
|  |  | 
|  | ret = entropy_get_entropy(entropy_dev, dst, outlen); | 
|  |  | 
|  | if (unlikely(ret < 0)) { | 
|  | /* Don't try to fill the buffer in case of | 
|  | * cryptographically secure random numbers, just | 
|  | * propagate the driver error. | 
|  | */ | 
|  | if (csrand) { | 
|  | return ret; | 
|  | } | 
|  |  | 
|  | /* Use system timer in case the entropy device couldn't deliver | 
|  | * 32-bit of data.  There's not much that can be done in this | 
|  | * situation.  An __ASSERT() isn't used here as the HWRNG might | 
|  | * still be gathering entropy during early boot situations. | 
|  | */ | 
|  |  | 
|  | uint32_t len = 0; | 
|  | uint32_t blocksize = 4; | 
|  |  | 
|  | while (len < outlen) { | 
|  | size_t copylen = outlen - len; | 
|  |  | 
|  | if (copylen > blocksize) { | 
|  | copylen = blocksize; | 
|  | } | 
|  |  | 
|  | random_num = k_cycle_get_32(); | 
|  | (void)memcpy(&(dst[len]), &random_num, copylen); | 
|  | len += copylen; | 
|  | } | 
|  | } | 
|  |  | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | #if defined(CONFIG_ENTROPY_DEVICE_RANDOM_GENERATOR) | 
|  | void z_impl_sys_rand_get(void *dst, size_t outlen) | 
|  | { | 
|  | rand_get(dst, outlen, false); | 
|  | } | 
|  | #endif /* CONFIG_ENTROPY_DEVICE_RANDOM_GENERATOR */ | 
|  |  | 
|  | #if defined(CONFIG_HARDWARE_DEVICE_CS_GENERATOR) | 
|  |  | 
|  | int z_impl_sys_csrand_get(void *dst, size_t outlen) | 
|  | { | 
|  | if (rand_get(dst, outlen, true) != 0) { | 
|  | /* Is it the only error it should return ? entropy_sam | 
|  | * can return -ETIMEDOUT for example | 
|  | */ | 
|  | return -EIO; | 
|  | } | 
|  |  | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | #endif /* CONFIG_HARDWARE_DEVICE_CS_GENERATOR */ |