137074d96SEnji Cooper /*-
237074d96SEnji Cooper * Copyright (c) 2011 David Schultz
3*1730b5c7SRobert Clausecker * Copyright (c) 2024 Robert Clausecker <fuz@FreeBSD.org>
437074d96SEnji Cooper * All rights reserved.
537074d96SEnji Cooper *
637074d96SEnji Cooper * Redistribution and use in source and binary forms, with or without
737074d96SEnji Cooper * modification, are permitted provided that the following conditions
837074d96SEnji Cooper * are met:
937074d96SEnji Cooper * 1. Redistributions of source code must retain the above copyright
1037074d96SEnji Cooper * notice, this list of conditions and the following disclaimer.
1137074d96SEnji Cooper * 2. Redistributions in binary form must reproduce the above copyright
1237074d96SEnji Cooper * notice, this list of conditions and the following disclaimer in the
1337074d96SEnji Cooper * documentation and/or other materials provided with the distribution.
1437074d96SEnji Cooper *
1537074d96SEnji Cooper * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1637074d96SEnji Cooper * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1737074d96SEnji Cooper * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1837074d96SEnji Cooper * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1937074d96SEnji Cooper * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2037074d96SEnji Cooper * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2137074d96SEnji Cooper * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2237074d96SEnji Cooper * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2337074d96SEnji Cooper * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2437074d96SEnji Cooper * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2537074d96SEnji Cooper * SUCH DAMAGE.
2637074d96SEnji Cooper */
2737074d96SEnji Cooper
2837074d96SEnji Cooper #include <sys/types.h>
2937074d96SEnji Cooper #include <sys/mman.h>
3037074d96SEnji Cooper #include <sys/wait.h>
31233193f1SEnji Cooper #include <errno.h>
3237074d96SEnji Cooper #include <stdio.h>
33*1730b5c7SRobert Clausecker #include <stdint.h>
3437074d96SEnji Cooper #include <stdlib.h>
3537074d96SEnji Cooper #include <string.h>
3637074d96SEnji Cooper #include <unistd.h>
37233193f1SEnji Cooper
3837074d96SEnji Cooper #include <atf-c.h>
3937074d96SEnji Cooper
4037074d96SEnji Cooper /*
4137074d96SEnji Cooper * BUFSIZE is the number of bytes of rc4 output to compare. The probability
4237074d96SEnji Cooper * that this test fails spuriously is 2**(-BUFSIZE * 8).
4337074d96SEnji Cooper */
4437074d96SEnji Cooper #define BUFSIZE 8
4537074d96SEnji Cooper
4637074d96SEnji Cooper /*
4737074d96SEnji Cooper * Test whether arc4random_buf() returns the same sequence of bytes in both
4837074d96SEnji Cooper * parent and child processes. (Hint: It shouldn't.)
4937074d96SEnji Cooper */
5037074d96SEnji Cooper ATF_TC_WITHOUT_HEAD(test_arc4random);
ATF_TC_BODY(test_arc4random,tc)5137074d96SEnji Cooper ATF_TC_BODY(test_arc4random, tc)
5237074d96SEnji Cooper {
5337074d96SEnji Cooper struct shared_page {
5437074d96SEnji Cooper char parentbuf[BUFSIZE];
5537074d96SEnji Cooper char childbuf[BUFSIZE];
5637074d96SEnji Cooper } *page;
5737074d96SEnji Cooper pid_t pid;
5837074d96SEnji Cooper char c;
5937074d96SEnji Cooper
6037074d96SEnji Cooper page = mmap(NULL, sizeof(struct shared_page), PROT_READ | PROT_WRITE,
6137074d96SEnji Cooper MAP_ANON | MAP_SHARED, -1, 0);
62233193f1SEnji Cooper ATF_REQUIRE_MSG(page != MAP_FAILED, "mmap failed; errno=%d", errno);
6337074d96SEnji Cooper
6437074d96SEnji Cooper arc4random_buf(&c, 1);
6537074d96SEnji Cooper
6637074d96SEnji Cooper pid = fork();
6737074d96SEnji Cooper ATF_REQUIRE(0 <= pid);
6837074d96SEnji Cooper if (pid == 0) {
6937074d96SEnji Cooper /* child */
7037074d96SEnji Cooper arc4random_buf(page->childbuf, BUFSIZE);
7137074d96SEnji Cooper exit(0);
7237074d96SEnji Cooper } else {
7337074d96SEnji Cooper /* parent */
7437074d96SEnji Cooper int status;
7537074d96SEnji Cooper arc4random_buf(page->parentbuf, BUFSIZE);
7637074d96SEnji Cooper wait(&status);
7737074d96SEnji Cooper }
7837074d96SEnji Cooper ATF_CHECK_MSG(memcmp(page->parentbuf, page->childbuf, BUFSIZE) != 0,
7937074d96SEnji Cooper "sequences are the same");
8037074d96SEnji Cooper }
8137074d96SEnji Cooper
82*1730b5c7SRobert Clausecker /*
83*1730b5c7SRobert Clausecker * Test whether arc4random_uniform() returns a number below the given threshold.
84*1730b5c7SRobert Clausecker * Test with various thresholds.
85*1730b5c7SRobert Clausecker */
86*1730b5c7SRobert Clausecker ATF_TC_WITHOUT_HEAD(test_arc4random_uniform);
ATF_TC_BODY(test_arc4random_uniform,tc)87*1730b5c7SRobert Clausecker ATF_TC_BODY(test_arc4random_uniform, tc)
88*1730b5c7SRobert Clausecker {
89*1730b5c7SRobert Clausecker size_t i, j;
90*1730b5c7SRobert Clausecker static const uint32_t thresholds[] = {
91*1730b5c7SRobert Clausecker 1, 2, 3, 4, 5, 10, 100, 1000,
92*1730b5c7SRobert Clausecker INT32_MAX, (uint32_t)INT32_MAX + 1,
93*1730b5c7SRobert Clausecker UINT32_MAX - 1000000000, UINT32_MAX - 1000000, UINT32_MAX - 1, 0
94*1730b5c7SRobert Clausecker };
95*1730b5c7SRobert Clausecker
96*1730b5c7SRobert Clausecker for (i = 0; thresholds[i] != 0; i++)
97*1730b5c7SRobert Clausecker for (j = 0; j < 10000; j++)
98*1730b5c7SRobert Clausecker ATF_CHECK(arc4random_uniform(thresholds[i]) < thresholds[i]);
99*1730b5c7SRobert Clausecker
100*1730b5c7SRobert Clausecker /* for a threshold of zero, just check that we get zero every time */
101*1730b5c7SRobert Clausecker for (j = 0; j < 1000; j++)
102*1730b5c7SRobert Clausecker ATF_CHECK_EQ(0, arc4random_uniform(0));
103*1730b5c7SRobert Clausecker }
104*1730b5c7SRobert Clausecker
ATF_TP_ADD_TCS(tp)10537074d96SEnji Cooper ATF_TP_ADD_TCS(tp)
10637074d96SEnji Cooper {
10737074d96SEnji Cooper
10837074d96SEnji Cooper ATF_TP_ADD_TC(tp, test_arc4random);
109*1730b5c7SRobert Clausecker ATF_TP_ADD_TC(tp, test_arc4random_uniform);
11037074d96SEnji Cooper
11137074d96SEnji Cooper return (atf_no_error());
11237074d96SEnji Cooper }
113