/* * Copyright (c) 2017 Intel Corporation * * SPDX-License-Identifier: Apache-2.0 */ #include #include #include #include static struct device *entropy_driver; #if defined(CONFIG_ENTROPY_DEVICE_RANDOM_GENERATOR) u32_t sys_rand32_get(void) { struct device *dev = entropy_driver; u32_t random_num; int ret; if (unlikely(!dev)) { /* Only one entropy device exists, so this is safe even * if the whole operation isn't atomic. */ dev = device_get_binding(CONFIG_ENTROPY_NAME); __ASSERT((dev != NULL), "Device driver for %s (CONFIG_ENTROPY_NAME) not found. " "Check your build configuration!", CONFIG_ENTROPY_NAME); entropy_driver = dev; } ret = entropy_get_entropy(dev, (u8_t *)&random_num, sizeof(random_num)); if (unlikely(ret < 0)) { /* 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. */ random_num = k_cycle_get_32(); } return random_num; } #endif /* CONFIG_ENTROPY_DEVICE_RANDOM_GENERATOR */ static int rand_get(u8_t *dst, size_t outlen, bool csrand) { struct device *dev = entropy_driver; u32_t random_num; int ret; if (unlikely(!dev)) { /* Only one entropy device exists, so this is safe even * if the whole operation isn't atomic. */ dev = device_get_binding(CONFIG_ENTROPY_NAME); __ASSERT((dev != NULL), "Device driver for %s (CONFIG_ENTROPY_NAME) not found. " "Check your build configuration!", CONFIG_ENTROPY_NAME); entropy_driver = dev; } ret = entropy_get_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. */ u32_t len = 0; u32_t blocksize = 4; while (len < outlen) { random_num = k_cycle_get_32(); if ((outlen-len) < sizeof(random_num)) { blocksize = len; (void)memcpy(&(dst[random_num]), &random_num, blocksize); } else { *((u32_t *)&dst[len]) = random_num; } len += blocksize; } } return 0; } #if defined(CONFIG_ENTROPY_DEVICE_RANDOM_GENERATOR) void 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 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 */