1 /*        $NetBSD: t_arc4random.c,v 1.5 2025/03/09 18:11:55 riastradh Exp $     */
2 
3 /*-
4  * Copyright (c) 2024 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
17  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26  * POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 #define   _REENTRANT
30 
31 #include <sys/cdefs.h>
32 __RCSID("$NetBSD: t_arc4random.c,v 1.5 2025/03/09 18:11:55 riastradh Exp $");
33 
34 #include <sys/resource.h>
35 #include <sys/stat.h>
36 #include <sys/sysctl.h>
37 #include <sys/wait.h>
38 
39 #include <atf-c.h>
40 #include <err.h>
41 #include <fcntl.h>
42 #include <paths.h>
43 #include <stdio.h>
44 #include <string.h>
45 #include <unistd.h>
46 
47 #include "arc4random.h"
48 #include "reentrant.h"
49 #include "h_macros.h"
50 
51 /*
52  * iszero(buf, len)
53  *
54  *        True if len bytes at buf are all zero, false if any one of them
55  *        is nonzero.
56  */
57 static bool
iszero(const void * buf,size_t len)58 iszero(const void *buf, size_t len)
59 {
60           const unsigned char *p = buf;
61           size_t i;
62 
63           for (i = 0; i < len; i++) {
64                     if (p[i] != 0)
65                               return false;
66           }
67           return true;
68 }
69 
70 /*
71  * arc4random_prng()
72  *
73  *        Get a pointer to the current arc4random state, without updating
74  *        any of the state, not even lazy initialization.
75  */
76 static struct arc4random_prng *
arc4random_prng(void)77 arc4random_prng(void)
78 {
79           struct arc4random_prng *prng = NULL;
80 
81           /*
82            * If arc4random has been initialized and there is a thread key
83            * (i.e., libc was built with _REENTRANT), get the thread-local
84            * arc4random state if there is one.
85            */
86           if (arc4random_global.per_thread)
87                     prng = thr_getspecific(arc4random_global.thread_key);
88 
89           /*
90            * If we couldn't get the thread-local state, get the global
91            * state instead.
92            */
93           if (prng == NULL)
94                     prng = &arc4random_global.prng;
95 
96           return prng;
97 }
98 
99 /*
100  * arc4random_global_buf(buf, len)
101  *
102  *        Same as arc4random_buf, but force use of the global state.
103  *        Must happen before any other use of arc4random.
104  */
105 static void
arc4random_global_buf(void * buf,size_t len)106 arc4random_global_buf(void *buf, size_t len)
107 {
108           struct rlimit rlim, orlim;
109           struct arc4random_prng *prng;
110 
111           /*
112            * Save the address space limit.
113            */
114           RL(getrlimit(RLIMIT_AS, &orlim));
115           memcpy(&rlim, &orlim, sizeof(rlim));
116 
117           /*
118            * Get a sample while the address space limit is zero.  This
119            * should try, and fail, to allocate a thread-local arc4random
120            * state with mmap(2).
121            */
122           rlim.rlim_cur = 0;
123           RL(setrlimit(RLIMIT_AS, &rlim));
124           arc4random_buf(buf, len);
125           RL(setrlimit(RLIMIT_AS, &orlim));
126 
127           /*
128            * Restore the address space limit.
129            */
130           RL(setrlimit(RLIMIT_AS, &orlim));
131 
132           /*
133            * Verify the PRNG is the global one, not the thread-local one,
134            * and that it was initialized.
135            */
136           prng = arc4random_prng();
137           ATF_CHECK_EQ(prng, &arc4random_global.prng);
138           ATF_CHECK(!iszero(&prng->arc4_prng, sizeof(prng->arc4_prng)));
139           ATF_CHECK(prng->arc4_epoch != 0);
140 }
141 
142 /*
143  * arc4random_global_thread(cookie)
144  *
145  *        Start routine for a thread that just grabs an output from the
146  *        global state.
147  */
148 static void *
arc4random_global_thread(void * cookie)149 arc4random_global_thread(void *cookie)
150 {
151           unsigned char buf[32];
152 
153           arc4random_global_buf(buf, sizeof(buf));
154 
155           return NULL;
156 }
157 
158 ATF_TC(addrandom);
ATF_TC_HEAD(addrandom,tc)159 ATF_TC_HEAD(addrandom, tc)
160 {
161           atf_tc_set_md_var(tc, "descr",
162               "Test arc4random_addrandom updates the state");
163 }
ATF_TC_BODY(addrandom,tc)164 ATF_TC_BODY(addrandom, tc)
165 {
166           unsigned char buf[32], zero32[32] = {0};
167           struct arc4random_prng *prng, copy;
168 
169           /*
170            * Get a sample to start things off.
171            */
172           arc4random_buf(buf, sizeof(buf));
173           ATF_CHECK(!iszero(buf, sizeof(buf)));   /* Pr[fail] = 1/2^256 */
174 
175           /*
176            * By this point, the global state must be initialized -- if
177            * not, the process should have aborted.
178            */
179           ATF_CHECK(arc4random_global.initialized);
180 
181           /*
182            * Get the PRNG, global or local.  By this point, the PRNG
183            * state should be nonzero (with overwhelmingly high
184            * probability) and the epoch should also be nonzero.
185            */
186           prng = arc4random_prng();
187           ATF_CHECK(!iszero(&prng->arc4_prng, sizeof(prng->arc4_prng)));
188           ATF_CHECK(prng->arc4_epoch != 0);
189 
190           /*
191            * Save a copy and update the state with arc4random_addrandom.
192            */
193           copy = *prng;
194           arc4random_addrandom(zero32, sizeof(zero32));
195 
196           /*
197            * The state should have changed.  (The epoch may or may not.)
198            */
199           ATF_CHECK(memcmp(&prng->arc4_prng, &copy.arc4_prng,
200                     sizeof(copy.arc4_prng)) != 0);
201 
202           /*
203            * Save a copy and update the state with arc4random_stir.
204            */
205           copy = *prng;
206           arc4random_stir();
207 
208           /*
209            * The state should have changed.  (The epoch may or may not.)
210            */
211           ATF_CHECK(memcmp(&prng->arc4_prng, &copy.arc4_prng,
212                     sizeof(copy.arc4_prng)) != 0);
213 }
214 
215 ATF_TC(consolidate);
ATF_TC_HEAD(consolidate,tc)216 ATF_TC_HEAD(consolidate, tc)
217 {
218           atf_tc_set_md_var(tc, "descr",
219               "Test consolidating entropy resets the epoch");
220 }
ATF_TC_BODY(consolidate,tc)221 ATF_TC_BODY(consolidate, tc)
222 {
223           unsigned char buf[32];
224           struct arc4random_prng *local, *global = &arc4random_global.prng;
225           unsigned localepoch, globalepoch;
226           const int consolidate = 1;
227           pthread_t thread;
228 
229           /*
230            * Get a sample from the global state to make sure the global
231            * state is initialized.  Remember the epoch.
232            */
233           arc4random_global_buf(buf, sizeof(buf));
234           ATF_CHECK(!iszero(buf, sizeof(buf)));   /* Pr[fail] = 1/2^256 */
235           ATF_CHECK(!iszero(&global->arc4_prng, sizeof(global->arc4_prng)));
236           ATF_CHECK((globalepoch = global->arc4_epoch) != 0);
237 
238           /*
239            * Get a sample from the local state too to make sure the local
240            * state is initialized.  Remember the epoch.
241            */
242           arc4random_buf(buf, sizeof(buf));
243           ATF_CHECK(!iszero(buf, sizeof(buf)));   /* Pr[fail] = 1/2^256 */
244           local = arc4random_prng();
245           ATF_CHECK(!iszero(&local->arc4_prng, sizeof(local->arc4_prng)));
246           ATF_CHECK((localepoch = local->arc4_epoch) != 0);
247 
248           /*
249            * Trigger entropy consolidation.
250            */
251           RL(sysctlbyname("kern.entropy.consolidate", /*oldp*/NULL, /*oldlen*/0,
252                     &consolidate, sizeof(consolidate)));
253 
254           /*
255            * Verify the epoch cache isn't changed yet until we ask for
256            * more data.
257            */
258           ATF_CHECK_EQ_MSG(globalepoch, global->arc4_epoch,
259               "global epoch was %u, now %u", globalepoch, global->arc4_epoch);
260           ATF_CHECK_EQ_MSG(localepoch, local->arc4_epoch,
261               "local epoch was %u, now %u", localepoch, local->arc4_epoch);
262 
263           /*
264            * Request new output and verify the local epoch cache has
265            * changed.
266            */
267           arc4random_buf(buf, sizeof(buf));
268           ATF_CHECK(!iszero(buf, sizeof(buf)));   /* Pr[fail] = 1/2^256 */
269           ATF_CHECK_MSG(localepoch != local->arc4_epoch,
270               "local epoch unchanged from %u", localepoch);
271 
272           /*
273            * Create a new thread to grab output from the global state,
274            * wait for it to complete, and verify the global epoch cache
275            * has changed.  (Now that we have already used the local state
276            * in this thread, we can't use the global state any more.)
277            */
278           RZ(pthread_create(&thread, NULL, &arc4random_global_thread, NULL));
279           RZ(pthread_join(thread, NULL));
280           ATF_CHECK_MSG(globalepoch != global->arc4_epoch,
281               "global epoch unchanged from %u", globalepoch);
282 }
283 
284 ATF_TC(chroot);
ATF_TC_HEAD(chroot,tc)285 ATF_TC_HEAD(chroot, tc)
286 {
287           atf_tc_set_md_var(tc, "descr",
288               "Test arc4random in an empty chroot");
289           atf_tc_set_md_var(tc, "require.user", "root");
290 }
ATF_TC_BODY(chroot,tc)291 ATF_TC_BODY(chroot, tc)
292 {
293           pid_t pid;
294           int status;
295 
296           /*
297            * Create an empty chroot.
298            */
299           RL(mkdir("root", 0500));
300 
301           /*
302            * In a child process, enter the chroot and verify that we
303            * can't open /dev/urandom but we can use arc4random.
304            *
305            * (atf gets unhappy if we chroot in the same process, when it
306            * later tries to create a results file.)
307            */
308           RL(pid = fork());
309           if (pid == 0) {
310                     unsigned char buf[32] = {0};
311 
312                     if (chroot("root") == -1)
313                               err(1, "chroot");
314                     if (open(_PATH_URANDOM, O_RDONLY) != -1)
315                               errx(1, "open /dev/urandom must fail in empty chroot");
316                     if (errno != ENOENT) {
317                               err(1, "expected open to fail with %d=ENOENT, not %d",
318                                   ENOENT, errno);
319                     }
320                     arc4random_buf(buf, sizeof(buf));
321                     if (iszero(buf, sizeof(buf))) /* Pr[fail] = 1/2^256 */
322                               errx(1, "arc4random returned all-zero");
323                     if (arc4random_prng()->arc4_epoch == 0)
324                               errx(1, "arc4random failed to observe entropy epoch");
325                     _exit(0);
326           }
327 
328           /*
329            * Wait for the child process to finish.
330            */
331           RL(waitpid(pid, &status, 0));
332           ATF_CHECK_MSG(WIFEXITED(status) && WEXITSTATUS(status) == 0,
333               "child exited status 0x%x", status);
334 }
335 
336 ATF_TC(fdlimit);
ATF_TC_HEAD(fdlimit,tc)337 ATF_TC_HEAD(fdlimit, tc)
338 {
339           atf_tc_set_md_var(tc, "descr",
340               "Test arc4random works even if we have hit the fd limit");
341 }
ATF_TC_BODY(fdlimit,tc)342 ATF_TC_BODY(fdlimit, tc)
343 {
344           pid_t pid;
345           int status;
346 
347           /*
348            * In a child process, clamp down on the file descriptor
349            * resource limit and verify that we can't open /dev/urandom
350            * but we can use arc4random.
351            *
352            * (atf gets unhappy if we chroot in the same process, when it
353            * later tries to create a results file.)
354            */
355           RL(pid = fork());
356           if (pid == 0) {
357                     struct rlimit rlim = {.rlim_cur = 0, .rlim_max = 0};
358                     unsigned char buf[32] = {0};
359 
360                     if (setrlimit(RLIMIT_NOFILE, &rlim) == -1)
361                               err(1, "setrlimit(RLIMIT_NOFILE)");
362                     if (open(_PATH_URANDOM, O_RDONLY) != -1)
363                               errx(1, "open must fail with zero RLIMIT_NOFILE");
364                     if (errno != EMFILE) {
365                               err(1, "expected open to fail with %d=EMFILE, not %d",
366                                   EMFILE, errno);
367                     }
368                     arc4random_buf(buf, sizeof(buf));
369                     if (iszero(buf, sizeof(buf))) /* Pr[fail] = 1/2^256 */
370                               errx(1, "arc4random returned all-zero");
371                     if (arc4random_prng()->arc4_epoch == 0)
372                               errx(1, "arc4random failed to observe entropy epoch");
373                     _exit(0);
374           }
375 
376           /*
377            * Wait for the child process to finish.
378            */
379           RL(waitpid(pid, &status, 0));
380           ATF_CHECK_MSG(WIFEXITED(status) && WEXITSTATUS(status) == 0,
381               "child exited status 0x%x", status);
382 }
383 
384 ATF_TC(fork);
ATF_TC_HEAD(fork,tc)385 ATF_TC_HEAD(fork, tc)
386 {
387           atf_tc_set_md_var(tc, "descr",
388               "Test fork zeros the state and gets independent state");
389 }
ATF_TC_BODY(fork,tc)390 ATF_TC_BODY(fork, tc)
391 {
392           unsigned char buf[32];
393           struct arc4random_prng *local, *global = &arc4random_global.prng;
394           struct arc4random_prng childstate;
395           int fd[2];
396           pid_t child, pid;
397           ssize_t nread;
398           int status;
399 
400           /*
401            * Get a sample from the global state to make sure the global
402            * state is initialized.
403            */
404           arc4random_global_buf(buf, sizeof(buf));
405           ATF_CHECK(!iszero(buf, sizeof(buf)));   /* Pr[fail] = 1/2^256 */
406           ATF_CHECK(!iszero(&global->arc4_prng, sizeof(global->arc4_prng)));
407           ATF_CHECK(global->arc4_epoch != 0);
408 
409           /*
410            * Get a sample from the local state too to make sure the local
411            * state is initialized.
412            */
413           arc4random_buf(buf, sizeof(buf));
414           ATF_CHECK(!iszero(buf, sizeof(buf)));   /* Pr[fail] = 1/2^256 */
415           local = arc4random_prng();
416           ATF_CHECK(!iszero(&local->arc4_prng, sizeof(local->arc4_prng)));
417           ATF_CHECK(local->arc4_epoch != 0);
418 
419           /*
420            * Create a pipe to transfer the state from child to parent.
421            */
422           RL(pipe(fd));
423 
424           /*
425            * Fork a child.
426            */
427           RL(child = fork());
428           if (child == 0) {
429                     status = 0;
430 
431                     /*
432                      * Verify the states have been zero'd on fork.
433                      */
434                     if (!iszero(local, sizeof(*local))) {
435                               fprintf(stderr, "failed to zero local state\n");
436                               status = 1;
437                     }
438                     if (!iszero(global, sizeof(*global))) {
439                               fprintf(stderr, "failed to zero global state\n");
440                               status = 1;
441                     }
442 
443                     /*
444                      * Verify we generate nonzero output.
445                      */
446                     arc4random_buf(buf, sizeof(buf));
447                     if (iszero(buf, sizeof(buf))) {
448                               fprintf(stderr, "failed to generate nonzero output\n");
449                               status = 1;
450                     }
451 
452                     /*
453                      * Share the state to compare with parent.
454                      */
455                     if ((size_t)write(fd[1], local, sizeof(*local)) !=
456                         sizeof(*local)) {
457                               fprintf(stderr, "failed to share local state\n");
458                               status = 1;
459                     }
460                     _exit(status);
461           }
462 
463           /*
464            * Verify the global state has been zeroed as expected.  (This
465            * way it is never available to the child, even shortly after
466            * the fork syscall returns before the atfork handler is
467            * called.)
468            */
469           ATF_CHECK(iszero(global, sizeof(*global)));
470 
471           /*
472            * Read the state from the child.
473            */
474           RL(nread = read(fd[0], &childstate, sizeof(childstate)));
475           ATF_CHECK_EQ_MSG(nread, sizeof(childstate),
476               "nread=%zu sizeof(childstate)=%zu", nread, sizeof(childstate));
477 
478           /*
479            * Verify the child state is distinct.  (The global state has
480            * been zero'd so it's OK it if coincides.)  Check again after
481            * we grab another output.
482            */
483           ATF_CHECK(memcmp(local, &childstate, sizeof(*local)) != 0);
484           arc4random_buf(buf, sizeof(buf));
485           ATF_CHECK(!iszero(buf, sizeof(buf)));   /* Pr[fail] = 1/2^256 */
486           ATF_CHECK(memcmp(local, &childstate, sizeof(*local)) != 0);
487 
488           /*
489            * Wait for the child to complete and verify it passed.
490            */
491           RL(pid = waitpid(child, &status, 0));
492           ATF_CHECK_EQ_MSG(status, 0, "child exited with nonzero status=%d",
493               status);
494 }
495 
496 ATF_TC(global_aslimit);
ATF_TC_HEAD(global_aslimit,tc)497 ATF_TC_HEAD(global_aslimit, tc)
498 {
499           atf_tc_set_md_var(tc, "descr",
500               "Test the global state is used when address space limit is hit");
501 }
ATF_TC_BODY(global_aslimit,tc)502 ATF_TC_BODY(global_aslimit, tc)
503 {
504           unsigned char buf[32], buf1[32];
505 
506           /*
507            * Get a sample from the global state (and verify it was using
508            * the global state).
509            */
510           arc4random_global_buf(buf, sizeof(buf));
511 
512           /*
513            * Verify we got a sample.
514            */
515           ATF_CHECK(!iszero(buf, sizeof(buf)));   /* Pr[fail] = 1/2^256 */
516 
517           /*
518            * Get a sample from whatever state and make sure it wasn't
519            * repeated, which happens only with probability 1/2^256.
520            */
521           arc4random_buf(buf1, sizeof(buf1));
522           ATF_CHECK(!iszero(buf1, sizeof(buf1))); /* Pr[fail] = 1/2^256 */
523           ATF_CHECK(memcmp(buf, buf1, sizeof(buf)) != 0);
524 }
525 
526 ATF_TC(global_threadkeylimit);
ATF_TC_HEAD(global_threadkeylimit,tc)527 ATF_TC_HEAD(global_threadkeylimit, tc)
528 {
529           atf_tc_set_md_var(tc, "descr",
530               "Test the global state is used we run out of thread keys");
531 }
ATF_TC_BODY(global_threadkeylimit,tc)532 ATF_TC_BODY(global_threadkeylimit, tc)
533 {
534           unsigned char buf[32], buf1[32];
535 
536           /*
537            * Get a sample from the global state (and verify it was using
538            * the global state).
539            */
540           arc4random_global_buf(buf, sizeof(buf));
541 
542           /*
543            * Verify we got a sample.
544            */
545           ATF_CHECK(!iszero(buf, sizeof(buf)));   /* Pr[fail] = 1/2^256 */
546 
547           /*
548            * Artificially disable the per-thread state, make it an
549            * invalid thread key altogether, and clear the epoch.  Make
550            * sure we're using the global PRNG state now.
551            */
552           arc4random_global.per_thread = false;
553           memset(&arc4random_global.thread_key, 0x5a,
554               sizeof(arc4random_global.thread_key));
555           arc4random_global.prng.arc4_epoch = 0;
556           ATF_CHECK(arc4random_prng() == &arc4random_global.prng);
557 
558           /*
559            * Get a sample again and make sure it wasn't repeated, which
560            * happens only with probability 1/2^256.
561            */
562           arc4random_buf(buf1, sizeof(buf1));
563           ATF_CHECK(!iszero(buf1, sizeof(buf1))); /* Pr[fail] = 1/2^256 */
564           ATF_CHECK(memcmp(buf, buf1, sizeof(buf)) != 0);
565 
566           /*
567            * Verify this had the effect of updating the global epoch,
568            * meaning we used the global state and not the per-thread
569            * state.
570            */
571           ATF_CHECK(arc4random_global.prng.arc4_epoch != 0);
572 }
573 
574 ATF_TC(local);
ATF_TC_HEAD(local,tc)575 ATF_TC_HEAD(local, tc)
576 {
577           atf_tc_set_md_var(tc, "descr",
578               "Test arc4random uses thread-local state");
579           /* XXX skip if libc was built without _REENTRANT */
580 }
ATF_TC_BODY(local,tc)581 ATF_TC_BODY(local, tc)
582 {
583           unsigned char buf[32], buf1[32];
584           struct arc4random_prng *prng;
585 
586           /*
587            * Get a sample to start things off.
588            */
589           arc4random_buf(buf, sizeof(buf));
590           ATF_CHECK(!iszero(buf, sizeof(buf)));   /* Pr[fail] = 1/2^256 */
591 
592           /*
593            * Verify the arc4random state is _not_ the global state.
594            */
595           prng = arc4random_prng();
596           ATF_CHECK(prng != &arc4random_global.prng);
597           ATF_CHECK(!iszero(&prng->arc4_prng, sizeof(prng->arc4_prng)));
598           ATF_CHECK(prng->arc4_epoch != 0);
599 
600           /*
601            * Get another sample and make sure it wasn't repeated, which
602            * happens only with probability 1/2^256.
603            */
604           arc4random_buf(buf1, sizeof(buf1));
605           ATF_CHECK(!iszero(buf1, sizeof(buf1))); /* Pr[fail] = 1/2^256 */
606           ATF_CHECK(memcmp(buf, buf1, sizeof(buf)) != 0);
607 }
608 
609 ATF_TC(stackfallback);
ATF_TC_HEAD(stackfallback,tc)610 ATF_TC_HEAD(stackfallback, tc)
611 {
612           atf_tc_set_md_var(tc, "descr",
613               "Test arc4random with pthread_atfork and thr_keycreate failure");
614 }
ATF_TC_BODY(stackfallback,tc)615 ATF_TC_BODY(stackfallback, tc)
616 {
617           unsigned char buf[32], buf1[32];
618           struct arc4random_prng *local;
619 
620           /*
621            * Get a sample to start things off.  This makes the library
622            * gets initialized.
623            */
624           arc4random_buf(buf, sizeof(buf));
625           ATF_CHECK(!iszero(buf, sizeof(buf)));   /* Pr[fail] = 1/2^256 */
626 
627           /*
628            * Clear the arc4random global state, and the local state if it
629            * exists, and pretend pthread_atfork and thr_keycreate had
630            * both failed.
631            */
632           memset(&arc4random_global.prng, 0, sizeof(arc4random_global.prng));
633           if ((local = arc4random_prng()) != NULL)
634                     memset(local, 0, sizeof(*local));
635           arc4random_global.forksafe = false;
636           arc4random_global.per_thread = false;
637 
638           /*
639            * Make sure it still works to get a sample.
640            */
641           arc4random_buf(buf1, sizeof(buf1));
642           ATF_CHECK(!iszero(buf, sizeof(buf)));   /* Pr[fail] = 1/2^256 */
643           ATF_CHECK(memcmp(buf, buf1, sizeof(buf)) != 0);
644 
645           /*
646            * Make sure the global and local epochs did not change.
647            */
648           ATF_CHECK_EQ_MSG(arc4random_global.prng.arc4_epoch, 0,
649               "global epoch: %d", arc4random_global.prng.arc4_epoch);
650           if (local != NULL) {
651                     ATF_CHECK_EQ_MSG(local->arc4_epoch, 0,
652                         "local epoch: %d", local->arc4_epoch);
653           }
654 }
655 
ATF_TP_ADD_TCS(tp)656 ATF_TP_ADD_TCS(tp)
657 {
658 
659           ATF_TP_ADD_TC(tp, addrandom);
660           ATF_TP_ADD_TC(tp, chroot);
661           ATF_TP_ADD_TC(tp, consolidate);
662           ATF_TP_ADD_TC(tp, fdlimit);
663           ATF_TP_ADD_TC(tp, fork);
664           ATF_TP_ADD_TC(tp, global_aslimit);
665           ATF_TP_ADD_TC(tp, global_threadkeylimit);
666           ATF_TP_ADD_TC(tp, local);
667           ATF_TP_ADD_TC(tp, stackfallback);
668 
669           return atf_no_error();
670 }
671