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