1 /* test random number generator APIs */
2 
3 /*
4  * Copyright (c) 2016 Intel Corporation
5  *
6  * SPDX-License-Identifier: Apache-2.0
7  */
8 
9 /*
10  * This tests the following random number routines:
11  * void z_early_rand_get(uint8_t *buf, size_t length)
12  * uint32_t sys_rand32_get(void);
13  */
14 
15 
16 #include <zephyr/ztest.h>
17 #include <kernel_internal.h>
18 #include <zephyr/random/random.h>
19 
20 #define N_VALUES 10
21 
22 
23 /**
24  *
25  * @brief Regression test's entry point
26  *
27  */
28 
ZTEST(rng_common,test_rand32)29 ZTEST(rng_common, test_rand32)
30 {
31 	uint32_t gen, last_gen, tmp;
32 	int rnd_cnt;
33 	int equal_count = 0;
34 	uint32_t buf[N_VALUES];
35 	int err;
36 
37 	/* Test early boot random number generation function */
38 	/* Cover the case, where argument "length" is < size of "size_t" */
39 	z_early_rand_get((uint8_t *)&tmp, (size_t)1);
40 	z_early_rand_get((uint8_t *)&last_gen, sizeof(last_gen));
41 	z_early_rand_get((uint8_t *)&gen, sizeof(gen));
42 	zassert_true(last_gen != gen && last_gen != tmp && tmp != gen,
43 			"z_early_rand_get failed");
44 
45 	/*
46 	 * Test subsequently calls sys_rand32_get(), checking
47 	 * that two values are not equal.
48 	 */
49 	printk("Generating random numbers\n");
50 	last_gen = sys_rand32_get();
51 	/*
52 	 * Get several subsequent numbers as fast as possible.
53 	 * Based on review comments in
54 	 * https://github.com/zephyrproject-rtos/zephyr/pull/5066
55 	 * If minimum half of the numbers generated were the same
56 	 * as the previously generated one, then test fails, this
57 	 * should catch a buggy sys_rand32_get() function.
58 	 */
59 	for (rnd_cnt = 0; rnd_cnt < (N_VALUES - 1); rnd_cnt++) {
60 		gen = sys_rand32_get();
61 		if (gen == last_gen) {
62 			equal_count++;
63 		}
64 		last_gen = gen;
65 	}
66 
67 	if (equal_count > N_VALUES / 2) {
68 		zassert_false((equal_count > N_VALUES / 2),
69 		"random numbers returned same value with high probability");
70 	}
71 
72 	printk("Generating bulk fill random numbers\n");
73 	memset(buf, 0, sizeof(buf));
74 	sys_rand_get((uint8_t *)(&buf[0]), sizeof(buf));
75 
76 	for (rnd_cnt = 0; rnd_cnt < (N_VALUES - 1); rnd_cnt++) {
77 		gen = buf[rnd_cnt];
78 		if (gen == last_gen) {
79 			equal_count++;
80 		}
81 		last_gen = gen;
82 	}
83 
84 	if (equal_count > N_VALUES / 2) {
85 		zassert_false((equal_count > N_VALUES / 2),
86 		"random numbers returned same value with high probability");
87 	}
88 
89 #if defined(CONFIG_CSPRNG_ENABLED)
90 
91 	printk("Generating bulk fill cryptographically secure random numbers\n");
92 
93 	memset(buf, 0, sizeof(buf));
94 
95 	err = sys_csrand_get(buf, sizeof(buf));
96 
97 	zassert_true(err == 0, "sys_csrand_get returned an error");
98 
99 	for (rnd_cnt = 0; rnd_cnt < (N_VALUES - 1); rnd_cnt++) {
100 		gen = buf[rnd_cnt];
101 		if (gen == last_gen) {
102 			equal_count++;
103 		}
104 		last_gen = gen;
105 	}
106 
107 	if (equal_count > N_VALUES / 2) {
108 		zassert_false((equal_count > N_VALUES / 2),
109 		"random numbers returned same value with high probability");
110 	}
111 
112 #else
113 
114 	printk("Cryptographically secure implementation not enabled\n");
115 	printk("Ensure sys_csrand_get passes for library usage\n");
116 
117 	err = sys_csrand_get(buf, sizeof(buf));
118 
119 	zassert_true(err == 0, "sys_csrand_get returned an error");
120 
121 #endif /* CONFIG_CSPRNG_ENABLED */
122 }
123 
124 ZTEST_SUITE(rng_common, NULL, NULL, NULL, NULL, NULL);
125