1 /*
2 * Copyright (c) 2017 Intel Corporation
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <zephyr/sys/atomic.h>
8 #include <zephyr/kernel.h>
9 #include <zephyr/drivers/entropy.h>
10 #include <string.h>
11
12 static const struct device *const entropy_dev =
13 DEVICE_DT_GET(DT_CHOSEN(zephyr_entropy));
14
15 #if defined(CONFIG_ENTROPY_DEVICE_RANDOM_GENERATOR)
z_impl_sys_rand32_get(void)16 uint32_t z_impl_sys_rand32_get(void)
17 {
18 uint32_t random_num;
19 int ret;
20
21 __ASSERT(device_is_ready(entropy_dev), "Entropy device %s not ready",
22 entropy_dev->name);
23
24 ret = entropy_get_entropy(entropy_dev, (uint8_t *)&random_num,
25 sizeof(random_num));
26 if (unlikely(ret < 0)) {
27 /* Use system timer in case the entropy device couldn't deliver
28 * 32-bit of data. There's not much that can be done in this
29 * situation. An __ASSERT() isn't used here as the HWRNG might
30 * still be gathering entropy during early boot situations.
31 */
32
33 random_num = k_cycle_get_32();
34 }
35
36 return random_num;
37 }
38 #endif /* CONFIG_ENTROPY_DEVICE_RANDOM_GENERATOR */
39
rand_get(uint8_t * dst,size_t outlen,bool csrand)40 static int rand_get(uint8_t *dst, size_t outlen, bool csrand)
41 {
42 uint32_t random_num;
43 int ret;
44
45 __ASSERT(device_is_ready(entropy_dev), "Entropy device %s not ready",
46 entropy_dev->name);
47
48 ret = entropy_get_entropy(entropy_dev, dst, outlen);
49
50 if (unlikely(ret < 0)) {
51 /* Don't try to fill the buffer in case of
52 * cryptographically secure random numbers, just
53 * propagate the driver error.
54 */
55 if (csrand) {
56 return ret;
57 }
58
59 /* Use system timer in case the entropy device couldn't deliver
60 * 32-bit of data. There's not much that can be done in this
61 * situation. An __ASSERT() isn't used here as the HWRNG might
62 * still be gathering entropy during early boot situations.
63 */
64
65 uint32_t len = 0;
66 uint32_t blocksize = 4;
67
68 while (len < outlen) {
69 size_t copylen = outlen - len;
70
71 if (copylen > blocksize) {
72 copylen = blocksize;
73 }
74
75 random_num = k_cycle_get_32();
76 (void)memcpy(&(dst[len]), &random_num, copylen);
77 len += copylen;
78 }
79 }
80
81 return 0;
82 }
83
84 #if defined(CONFIG_ENTROPY_DEVICE_RANDOM_GENERATOR)
z_impl_sys_rand_get(void * dst,size_t outlen)85 void z_impl_sys_rand_get(void *dst, size_t outlen)
86 {
87 rand_get(dst, outlen, false);
88 }
89 #endif /* CONFIG_ENTROPY_DEVICE_RANDOM_GENERATOR */
90
91 #if defined(CONFIG_HARDWARE_DEVICE_CS_GENERATOR)
92
z_impl_sys_csrand_get(void * dst,size_t outlen)93 int z_impl_sys_csrand_get(void *dst, size_t outlen)
94 {
95 if (rand_get(dst, outlen, true) != 0) {
96 /* Is it the only error it should return ? entropy_sam
97 * can return -ETIMEDOUT for example
98 */
99 return -EIO;
100 }
101
102 return 0;
103 }
104
105 #endif /* CONFIG_HARDWARE_DEVICE_CS_GENERATOR */
106