1 /*
2  * Copyright (c) 2018 Oticon A/S
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Pseudo-random entropy generator for the ARCH_POSIX architecture:
7  * Following the principle of reproducibility of the native_posix board
8  * this entropy device will always generate the same random sequence when
9  * initialized with the same seed
10  *
11  * This entropy source should only be used for testing.
12  */
13 
14 #define DT_DRV_COMPAT zephyr_native_posix_rng
15 
16 #include <zephyr/device.h>
17 #include <zephyr/drivers/entropy.h>
18 #include <zephyr/init.h>
19 #include <zephyr/sys/util.h>
20 #include <stdlib.h>
21 #include <string.h>
22 #include <zephyr/arch/posix/posix_trace.h>
23 #include "soc.h"
24 #include "cmdline.h" /* native_posix command line options header */
25 #include "nsi_host_trampolines.h"
26 #include "fake_entropy_native_bottom.h"
27 
28 static unsigned int seed = 0x5678;
29 static bool seed_random;
30 static bool seed_set;
31 
entropy_native_posix_get_entropy(const struct device * dev,uint8_t * buffer,uint16_t length)32 static int entropy_native_posix_get_entropy(const struct device *dev,
33 					    uint8_t *buffer,
34 					    uint16_t length)
35 {
36 	ARG_UNUSED(dev);
37 
38 	while (length) {
39 		/*
40 		 * Note that only 1 thread (Zephyr thread or HW models), runs at
41 		 * a time, therefore there is no need to use random_r()
42 		 */
43 		long value = nsi_host_random();
44 
45 		size_t to_copy = MIN(length, sizeof(long int));
46 
47 		memcpy(buffer, &value, to_copy);
48 		buffer += to_copy;
49 		length -= to_copy;
50 	}
51 
52 	return 0;
53 }
54 
entropy_native_posix_get_entropy_isr(const struct device * dev,uint8_t * buf,uint16_t len,uint32_t flags)55 static int entropy_native_posix_get_entropy_isr(const struct device *dev,
56 						uint8_t *buf,
57 						uint16_t len, uint32_t flags)
58 {
59 	ARG_UNUSED(flags);
60 
61 	/*
62 	 * entropy_native_posix_get_entropy() is also safe for ISRs
63 	 * and always produces data.
64 	 */
65 	entropy_native_posix_get_entropy(dev, buf, len);
66 
67 	return len;
68 }
69 
entropy_native_posix_init(const struct device * dev)70 static int entropy_native_posix_init(const struct device *dev)
71 {
72 	ARG_UNUSED(dev);
73 	if (seed_set || seed_random ||
74 	    IS_ENABLED(CONFIG_FAKE_ENTROPY_NATIVE_POSIX_SEED_BY_DEFAULT)) {
75 		entropy_native_seed(seed, seed_random);
76 	}
77 	posix_print_warning("WARNING: "
78 			    "Using a test - not safe - entropy source\n");
79 	return 0;
80 }
81 
82 static DEVICE_API(entropy, entropy_native_posix_api_funcs) = {
83 	.get_entropy     = entropy_native_posix_get_entropy,
84 	.get_entropy_isr = entropy_native_posix_get_entropy_isr
85 };
86 
87 DEVICE_DT_INST_DEFINE(0,
88 		    entropy_native_posix_init, NULL,
89 		    NULL, NULL,
90 		    PRE_KERNEL_1, CONFIG_ENTROPY_INIT_PRIORITY,
91 		    &entropy_native_posix_api_funcs);
92 
seed_was_set(char * argv,int offset)93 static void seed_was_set(char *argv, int offset)
94 {
95 	ARG_UNUSED(argv);
96 	ARG_UNUSED(offset);
97 	seed_set = true;
98 }
99 
add_fake_entropy_option(void)100 static void add_fake_entropy_option(void)
101 {
102 	static struct args_struct_t entropy_options[] = {
103 		{
104 			.option = "seed",
105 			.name = "r_seed",
106 			.type = 'u',
107 			.dest = (void *)&seed,
108 			.call_when_found = seed_was_set,
109 			.descript = "A 32-bit integer seed value for the entropy device, such as "
110 				    "97229 (decimal), 0x17BCD (hex), or 0275715 (octal)"
111 		},
112 		{
113 			.is_switch = true,
114 			.option = "seed-random",
115 			.type = 'b',
116 			.dest = (void *)&seed_random,
117 			.descript = "Seed the random generator from /dev/urandom. "
118 				    "Note your test may not be reproducible if you set this option"
119 		},
120 		ARG_TABLE_ENDMARKER
121 	};
122 
123 	native_add_command_line_opts(entropy_options);
124 }
125 
126 NATIVE_TASK(add_fake_entropy_option, PRE_BOOT_1, 10);
127