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 
27 static unsigned int seed = 0x5678;
28 
entropy_native_posix_get_entropy(const struct device * dev,uint8_t * buffer,uint16_t length)29 static int entropy_native_posix_get_entropy(const struct device *dev,
30 					    uint8_t *buffer,
31 					    uint16_t length)
32 {
33 	ARG_UNUSED(dev);
34 
35 	while (length) {
36 		/*
37 		 * Note that only 1 thread (Zephyr thread or HW models), runs at
38 		 * a time, therefore there is no need to use random_r()
39 		 */
40 		long value = nsi_host_random();
41 
42 		size_t to_copy = MIN(length, sizeof(long int));
43 
44 		memcpy(buffer, &value, to_copy);
45 		buffer += to_copy;
46 		length -= to_copy;
47 	}
48 
49 	return 0;
50 }
51 
entropy_native_posix_get_entropy_isr(const struct device * dev,uint8_t * buf,uint16_t len,uint32_t flags)52 static int entropy_native_posix_get_entropy_isr(const struct device *dev,
53 						uint8_t *buf,
54 						uint16_t len, uint32_t flags)
55 {
56 	ARG_UNUSED(flags);
57 
58 	/*
59 	 * entropy_native_posix_get_entropy() is also safe for ISRs
60 	 * and always produces data.
61 	 */
62 	entropy_native_posix_get_entropy(dev, buf, len);
63 
64 	return len;
65 }
66 
entropy_native_posix_init(const struct device * dev)67 static int entropy_native_posix_init(const struct device *dev)
68 {
69 	ARG_UNUSED(dev);
70 	nsi_host_srandom(seed);
71 	posix_print_warning("WARNING: "
72 			    "Using a test - not safe - entropy source\n");
73 	return 0;
74 }
75 
76 static const struct entropy_driver_api entropy_native_posix_api_funcs = {
77 	.get_entropy     = entropy_native_posix_get_entropy,
78 	.get_entropy_isr = entropy_native_posix_get_entropy_isr
79 };
80 
81 DEVICE_DT_INST_DEFINE(0,
82 		    entropy_native_posix_init, NULL,
83 		    NULL, NULL,
84 		    PRE_KERNEL_1, CONFIG_ENTROPY_INIT_PRIORITY,
85 		    &entropy_native_posix_api_funcs);
86 
add_fake_entropy_option(void)87 static void add_fake_entropy_option(void)
88 {
89 	static struct args_struct_t entropy_options[] = {
90 		/*
91 		 * Fields:
92 		 * manual, mandatory, switch,
93 		 * option_name, var_name ,type,
94 		 * destination, callback,
95 		 * description
96 		 */
97 		{false, false, false,
98 		"seed", "r_seed", 'u',
99 		(void *)&seed, NULL,
100 		"A 32-bit integer seed value for the entropy device, such as "
101 		"97229 (decimal), 0x17BCD (hex), or 0275715 (octal)"},
102 		ARG_TABLE_ENDMARKER
103 	};
104 
105 	native_add_command_line_opts(entropy_options);
106 }
107 
108 NATIVE_TASK(add_fake_entropy_option, PRE_BOOT_1, 10);
109