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