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); 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); 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 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