1 /*
2 * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License").
5 * You may not use this file except in compliance with the License.
6 * A copy of the License is located at
7 *
8 * http://aws.amazon.com/apache2.0
9 *
10 * or in the "license" file accompanying this file. This file is distributed
11 * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
12 * express or implied. See the License for the specific language governing
13 * permissions and limitations under the License.
14 */
15
16 #include "s2n_test.h"
17
18 #include <sys/wait.h>
19 #include <pthread.h>
20 #include <s2n.h>
21
22 #include "utils/s2n_random.h"
23
24 extern bool s2n_cpu_supports_rdrand();
25
26 static uint8_t thread_data[2][100];
27
thread_safety_tester(void * slot)28 void *thread_safety_tester(void *slot)
29 {
30 intptr_t slotnum = (intptr_t) slot;
31 struct s2n_blob blob = {.data = thread_data[slotnum], .size = 100 };
32
33 EXPECT_OK(s2n_get_public_random_data(&blob));
34
35 EXPECT_OK(s2n_rand_cleanup_thread());
36
37 return NULL;
38 }
39
process_safety_tester(int write_fd)40 void process_safety_tester(int write_fd)
41 {
42 uint8_t pad[100];
43
44 struct s2n_blob blob = {.data = pad, .size = 100 };
45 EXPECT_OK(s2n_get_public_random_data(&blob));
46
47 /* Write the data we got to our pipe */
48 if (write(write_fd, pad, 100) != 100) {
49 _exit(100);
50 }
51
52 /* Close the pipe and exit */
53 close(write_fd);
54 _exit(0);
55 }
56
init(void)57 static int init(void) {
58 return S2N_SUCCESS;
59 }
60
cleanup(void)61 static int cleanup(void) {
62 return S2N_SUCCESS;
63 }
64
entropy(void * ptr,uint32_t size)65 static int entropy(void *ptr, uint32_t size) {
66 return S2N_SUCCESS;
67 }
68
main(int argc,char ** argv)69 int main(int argc, char **argv)
70 {
71 uint8_t bits[8] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 };
72 uint8_t bit_set_run[8];
73 int p[2], status;
74 pid_t pid;
75 uint8_t data[5120];
76 uint8_t child_data[100];
77 struct s2n_blob blob = {.data = data };
78
79 pthread_t threads[2];
80
81 BEGIN_TEST();
82 EXPECT_SUCCESS(s2n_disable_tls13());
83
84 /* Verify that randomness callbacks can't be set to NULL */
85 EXPECT_FAILURE(s2n_rand_set_callbacks(NULL, cleanup, entropy, entropy));
86 EXPECT_FAILURE(s2n_rand_set_callbacks(init, NULL, entropy, entropy));
87 EXPECT_FAILURE(s2n_rand_set_callbacks(init, cleanup, NULL, entropy));
88 EXPECT_FAILURE(s2n_rand_set_callbacks(init, cleanup, entropy, NULL));
89
90 /* Get one byte of data, to make sure the pool is (almost) full */
91 blob.size = 1;
92 EXPECT_OK(s2n_get_public_random_data(&blob));
93
94 /* Create two threads and have them each grab 100 bytes */
95 EXPECT_SUCCESS(pthread_create(&threads[0], NULL, thread_safety_tester, (void *)0));
96 EXPECT_SUCCESS(pthread_create(&threads[1], NULL, thread_safety_tester, (void *)1));
97
98 /* Wait for those threads to finish */
99 EXPECT_SUCCESS(pthread_join(threads[0], NULL));
100 EXPECT_SUCCESS(pthread_join(threads[1], NULL));
101
102 /* Confirm that their data differs from each other */
103 EXPECT_NOT_EQUAL(memcmp(thread_data[0], thread_data[1], 100), 0);
104
105 /* Confirm that their data differs from the parent thread */
106 blob.size = 100;
107 EXPECT_OK(s2n_get_public_random_data(&blob));
108 EXPECT_NOT_EQUAL(memcmp(thread_data[0], data, 100), 0);
109 EXPECT_NOT_EQUAL(memcmp(thread_data[1], data, 100), 0);
110
111 /* Create a pipe */
112 EXPECT_SUCCESS(pipe(p));
113
114 /* Create a child process */
115 pid = fork();
116 if (pid == 0) {
117 /* This is the child process, close the read end of the pipe */
118 EXPECT_SUCCESS(close(p[0]));
119 process_safety_tester(p[1]);
120 }
121
122 /* This is the parent process, close the write end of the pipe */
123 EXPECT_SUCCESS(close(p[1]));
124
125 /* Read the child's data from the pipe */
126 EXPECT_EQUAL(read(p[0], child_data, 100), 100);
127
128 /* Get 100 bytes here in the parent process */
129 blob.size = 100;
130 EXPECT_OK(s2n_get_public_random_data(&blob));
131
132 /* Confirm they differ */
133 EXPECT_NOT_EQUAL(memcmp(child_data, data, 100), 0);
134
135 /* Clean up */
136 EXPECT_EQUAL(waitpid(pid, &status, 0), pid);
137 EXPECT_EQUAL(status, 0);
138 EXPECT_SUCCESS(close(p[0]));
139
140 /* Get two sets of data in the same process/thread, and confirm that they
141 * differ
142 */
143 blob.data = child_data;
144 EXPECT_OK(s2n_get_public_random_data(&blob));
145 blob.data = data;
146 EXPECT_OK(s2n_get_public_random_data(&blob));
147 EXPECT_NOT_EQUAL(memcmp(child_data, data, 100), 0);
148
149 /* Try to fetch a volume of randomly generated data, every size between 1 and 5120
150 * bytes.
151 */
152 int trailing_zeros[8];
153
154 memset(trailing_zeros, 0, sizeof(trailing_zeros));
155 for (int i = 0; i < 5120; i++) {
156 blob.size = i;
157 EXPECT_OK(s2n_get_public_random_data(&blob));
158
159 if (i >= 64) {
160 /* Set the run counts to 0 */
161 memset(bit_set_run, 0, 8);
162
163 /* Apply 8 monobit tests to the data. Basically, we're
164 * looking for successive runs where a given bit is set.
165 * If a run exists with any particular bit 64 times in
166 * a row, then the data doesn't look randomly generated.
167 */
168 for (int j = 0; j < i; j++) {
169 for (int k = 0; k < 8; k++) {
170 if (data[j] & bits[k]) {
171 bit_set_run[k]++;
172
173 if (j >= 64) {
174 EXPECT_TRUE(bit_set_run[k] < 64);
175 }
176 } else {
177 bit_set_run[k] = 0;
178 }
179 }
180 }
181 }
182 /* A common mistake in array filling leaves the last bytes zero
183 * depending on the length.
184 */
185 int remainder = i % 8;
186 int non_zero_found = 0;
187 for (int t = i - remainder; t < i; t++) {
188 non_zero_found |= data[t];
189 }
190 if (!non_zero_found) {
191 trailing_zeros[remainder]++;
192 }
193 }
194 for (int t = 1; t < 8; t++) {
195 EXPECT_TRUE(trailing_zeros[t] < 5120 / 16);
196 }
197
198 memset(trailing_zeros, 0, sizeof(trailing_zeros));
199 for (int i = 0; i < 5120; i++) {
200 blob.size = i;
201 EXPECT_OK(s2n_get_private_random_data(&blob));
202
203 if (i >= 64) {
204 /* Set the run counts to 0 */
205 memset(bit_set_run, 0, 8);
206
207 /* Apply 8 monobit tests to the data. Basically, we're
208 * looking for successive runs where a given bit is set.
209 * If a run exists with any particular bit 64 times in
210 * a row, then the data doesn't look randomly generated.
211 */
212 for (int j = 0; j < i; j++) {
213 for (int k = 0; k < 8; k++) {
214 if (data[j] & bits[k]) {
215 bit_set_run[k]++;
216
217 if (j >= 64) {
218 EXPECT_TRUE(bit_set_run[k] < 64);
219 }
220 } else {
221 bit_set_run[k] = 0;
222 }
223 }
224 }
225 }
226 /* A common mistake in array filling leaves the last bytes zero
227 * depending on the length.
228 */
229 int remainder = i % 8;
230 int non_zero_found = 0;
231 for (int t = i - remainder; t < i; t++) {
232 non_zero_found |= data[t];
233 }
234 if (!non_zero_found) {
235 trailing_zeros[remainder]++;
236 }
237 }
238 for (int t = 1; t < 8; t++) {
239 EXPECT_TRUE(trailing_zeros[t] < 5120 / 16);
240 }
241
242 memset(trailing_zeros, 0, sizeof(trailing_zeros));
243 for (int i = 0; i < 5120; i++) {
244 blob.size = i;
245 EXPECT_OK(s2n_get_public_random_data(&blob));
246
247 if (i >= 64) {
248 /* Set the run counts to 0 */
249 memset(bit_set_run, 0, 8);
250
251 /* Apply 8 monobit tests to the data. Basically, we're
252 * looking for successive runs where a given bit is set.
253 * If a run exists with any particular bit 64 times in
254 * a row, then the data doesn't look randomly generated.
255 */
256 for (int j = 0; j < i; j++) {
257 for (int k = 0; k < 8; k++) {
258 if (data[j] & bits[k]) {
259 bit_set_run[k]++;
260
261 if (j >= 64) {
262 EXPECT_TRUE(bit_set_run[k] < 64);
263 }
264 } else {
265 bit_set_run[k] = 0;
266 }
267 }
268 }
269 }
270 /* A common mistake in array filling leaves the last bytes zero
271 * depending on the length.
272 */
273 int remainder = i % 8;
274 int non_zero_found = 0;
275 for (int t = i - remainder; t < i; t++) {
276 non_zero_found |= data[t];
277 }
278 if (!non_zero_found) {
279 trailing_zeros[remainder]++;
280 }
281 }
282 for (int t = 1; t < 8; t++) {
283 EXPECT_TRUE(trailing_zeros[t] < 5120 / 16);
284 }
285
286 if (s2n_cpu_supports_rdrand()) {
287 memset(trailing_zeros, 0, sizeof(trailing_zeros));
288 for (int i = 0; i < 5120; i++) {
289 blob.size = i;
290 EXPECT_OK(s2n_get_public_random_data(&blob));
291
292 if (i >= 64) {
293 /* Set the run counts to 0 */
294 memset(bit_set_run, 0, 8);
295
296 /* Apply 8 monobit tests to the data. Basically, we're
297 * looking for successive runs where a given bit is set.
298 * If a run exists with any particular bit 64 times in
299 * a row, then the data doesn't look randomly generated.
300 */
301 for (int j = 0; j < i; j++) {
302 for (int k = 0; k < 8; k++) {
303 if (data[j] & bits[k]) {
304 bit_set_run[k]++;
305
306 if (j >= 64) {
307 EXPECT_TRUE(bit_set_run[k] < 64);
308 }
309 } else {
310 bit_set_run[k] = 0;
311 }
312 }
313 }
314 }
315 /* A common mistake in array filling leaves the last bytes zero
316 * depending on the length
317 */
318 int remainder = i % 8;
319 int non_zero_found = 0;
320 for (int t = i - remainder; t < i; t++) {
321 non_zero_found |= data[t];
322 }
323 if (!non_zero_found) {
324 trailing_zeros[remainder]++;
325 }
326 }
327 for (int t = 1; t < 8; t++) {
328 EXPECT_TRUE(trailing_zeros[t] < 5120 / 16);
329 }
330 }
331
332 END_TEST();
333 }
334