1/* $NetBSD: t_getrandom.c,v 1.5 2023/08/03 03:18:12 rin Exp $ */ 2 3/*- 4 * Copyright (c) 2020 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Taylor R. Campbell. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32#include <sys/cdefs.h> 33__RCSID("$NetBSD: t_getrandom.c,v 1.5 2023/08/03 03:18:12 rin Exp $"); 34 35#include <sys/param.h> 36 37#include <sys/random.h> 38 39#include <atf-c.h> 40#include <errno.h> 41#include <signal.h> 42#include <stdio.h> 43#include <unistd.h> 44 45static uint8_t buf[65536]; 46static uint8_t zero24[24]; 47 48static void 49alarm_handler(int signo) 50{ 51 52 fprintf(stderr, "timeout\n"); 53} 54 55static void 56install_alarm_handler(void) 57{ 58 struct sigaction sa; 59 60 memset(&sa, 0, sizeof sa); 61 sa.sa_handler = alarm_handler; 62 sigfillset(&sa.sa_mask); 63 sa.sa_flags = 0; /* no SA_RESTART */ 64 65 ATF_CHECK_MSG(sigaction(SIGALRM, &sa, NULL) != -1, 66 "sigaction(SIGALRM): %s", strerror(errno)); 67} 68 69/* 70 * Probability of spurious failure is 1/2^192 for each of the memcmps. 71 * As long as there are fewer than 2^64 of them, the probability of 72 * spurious failure is at most 1/2^128, which is low enough that we 73 * don't care about it. 74 */ 75 76ATF_TC(getrandom_default); 77ATF_TC_HEAD(getrandom_default, tc) 78{ 79 atf_tc_set_md_var(tc, "descr", "getrandom(..., 0)"); 80 atf_tc_set_md_var(tc, "timeout", "2"); 81} 82ATF_TC_BODY(getrandom_default, tc) 83{ 84 ssize_t n; 85 86 /* default */ 87 install_alarm_handler(); 88 alarm(1); 89 memset(buf, 0, sizeof buf); 90 n = getrandom(buf, sizeof buf, 0); 91 if (n == -1) { 92 ATF_CHECK_EQ(errno, EINTR); 93 } else { 94 ATF_CHECK(n >= (ssize_t)MIN(256, sizeof buf)); 95 ATF_CHECK((size_t)n <= sizeof buf); 96 ATF_CHECK(memcmp(buf, zero24, 24) != 0); 97 ATF_CHECK(memcmp(buf + n - 24, zero24, 24) != 0); 98 } 99 alarm(0); 100} 101 102ATF_TC(getrandom_nonblock); 103ATF_TC_HEAD(getrandom_nonblock, tc) 104{ 105 atf_tc_set_md_var(tc, "descr", "getrandom(..., GRND_NONBLOCK)"); 106} 107ATF_TC_BODY(getrandom_nonblock, tc) 108{ 109 ssize_t n; 110 111 /* default, nonblocking */ 112 memset(buf, 0, sizeof buf); 113 n = getrandom(buf, sizeof buf, GRND_NONBLOCK); 114 if (n == -1) { 115 ATF_CHECK_EQ(errno, EAGAIN); 116 } else { 117 ATF_CHECK(n >= (ssize_t)MIN(256, sizeof buf)); 118 ATF_CHECK((size_t)n <= sizeof buf); 119 ATF_CHECK(memcmp(buf, zero24, 24) != 0); 120 ATF_CHECK(memcmp(buf + n - 24, zero24, 24) != 0); 121 } 122} 123 124ATF_TC(getrandom_insecure); 125ATF_TC_HEAD(getrandom_insecure, tc) 126{ 127 atf_tc_set_md_var(tc, "descr", "getrandom(..., GRND_INSECURE)"); 128} 129ATF_TC_BODY(getrandom_insecure, tc) 130{ 131 ssize_t n; 132 133 /* insecure */ 134 memset(buf, 0, sizeof buf); 135 n = getrandom(buf, sizeof buf, GRND_INSECURE); 136 ATF_CHECK(n != -1); 137 ATF_CHECK(n >= (ssize_t)MIN(256, sizeof buf)); 138 ATF_CHECK((size_t)n <= sizeof buf); 139 ATF_CHECK(memcmp(buf, zero24, 24) != 0); 140 ATF_CHECK(memcmp(buf + n - 24, zero24, 24) != 0); 141} 142 143ATF_TC(getrandom_insecure_nonblock); 144ATF_TC_HEAD(getrandom_insecure_nonblock, tc) 145{ 146 atf_tc_set_md_var(tc, "descr", 147 "getrandom(..., GRND_INSECURE|GRND_NONBLOCK)"); 148} 149ATF_TC_BODY(getrandom_insecure_nonblock, tc) 150{ 151 ssize_t n; 152 153 /* insecure, nonblocking -- same as mere insecure */ 154 memset(buf, 0, sizeof buf); 155 n = getrandom(buf, sizeof buf, GRND_INSECURE|GRND_NONBLOCK); 156 ATF_CHECK(n != -1); 157 ATF_CHECK(n >= (ssize_t)MIN(256, sizeof buf)); 158 ATF_CHECK((size_t)n <= sizeof buf); 159 ATF_CHECK(memcmp(buf, zero24, 24) != 0); 160 ATF_CHECK(memcmp(buf + n - 24, zero24, 24) != 0); 161} 162 163ATF_TC(getrandom_random); 164ATF_TC_HEAD(getrandom_random, tc) 165{ 166 atf_tc_set_md_var(tc, "descr", "getrandom(..., GRND_RANDOM)"); 167 atf_tc_set_md_var(tc, "timeout", "2"); 168} 169ATF_TC_BODY(getrandom_random, tc) 170{ 171 ssize_t n; 172 173 /* `random' (hokey) */ 174 install_alarm_handler(); 175 alarm(1); 176 memset(buf, 0, sizeof buf); 177 n = getrandom(buf, sizeof buf, GRND_RANDOM); 178 if (n == -1) { 179 ATF_CHECK_EQ(errno, EINTR); 180 } else { 181 ATF_CHECK(n != 0); 182 ATF_CHECK((size_t)n <= sizeof buf); 183 if ((size_t)n >= 24) { 184 ATF_CHECK(memcmp(buf, zero24, 24) != 0); 185 ATF_CHECK(memcmp(buf + n - 24, zero24, 24) != 0); 186 } 187 } 188 alarm(0); 189} 190 191ATF_TC(getrandom_random_nonblock); 192ATF_TC_HEAD(getrandom_random_nonblock, tc) 193{ 194 atf_tc_set_md_var(tc, "descr", 195 "getrandom(..., GRND_RANDOM|GRND_NONBLOCK)"); 196} 197ATF_TC_BODY(getrandom_random_nonblock, tc) 198{ 199 ssize_t n; 200 201 /* `random' (hokey), nonblocking */ 202 memset(buf, 0, sizeof buf); 203 n = getrandom(buf, sizeof buf, GRND_RANDOM|GRND_NONBLOCK); 204 if (n == -1) { 205 ATF_CHECK_EQ(errno, EAGAIN); 206 } else { 207 ATF_CHECK(n != 0); 208 ATF_CHECK((size_t)n <= sizeof buf); 209 if ((size_t)n >= 24) { 210 ATF_CHECK(memcmp(buf, zero24, 24) != 0); 211 ATF_CHECK(memcmp(buf + n - 24, zero24, 24) != 0); 212 } 213 } 214} 215 216ATF_TC(getrandom_random_insecure); 217ATF_TC_HEAD(getrandom_random_insecure, tc) 218{ 219 atf_tc_set_md_var(tc, "descr", 220 "getrandom(..., GRND_RANDOM|GRND_INSECURE)"); 221} 222ATF_TC_BODY(getrandom_random_insecure, tc) 223{ 224 ssize_t n; 225 226 /* random and insecure -- nonsensical */ 227 n = getrandom(buf, sizeof buf, GRND_RANDOM|GRND_INSECURE); 228 ATF_CHECK_EQ(n, -1); 229 ATF_CHECK_EQ(errno, EINVAL); 230} 231 232ATF_TC(getrandom_random_insecure_nonblock); 233ATF_TC_HEAD(getrandom_random_insecure_nonblock, tc) 234{ 235 atf_tc_set_md_var(tc, "descr", 236 "getrandom(..., GRND_RANDOM|GRND_INSECURE|GRND_NONBLOCK)"); 237} 238ATF_TC_BODY(getrandom_random_insecure_nonblock, tc) 239{ 240 ssize_t n; 241 242 /* random and insecure, nonblocking -- nonsensical */ 243 n = getrandom(buf, sizeof buf, 244 GRND_RANDOM|GRND_INSECURE|GRND_NONBLOCK); 245 ATF_CHECK_EQ(n, -1); 246 ATF_CHECK_EQ(errno, EINVAL); 247} 248 249ATF_TC(getrandom_invalid); 250ATF_TC_HEAD(getrandom_invalid, tc) 251{ 252 atf_tc_set_md_var(tc, "descr", "getrandom(..., <invalid>)"); 253} 254ATF_TC_BODY(getrandom_invalid, tc) 255{ 256 ssize_t n; 257 258 /* invalid flags */ 259 __CTASSERT(~(GRND_RANDOM|GRND_INSECURE|GRND_NONBLOCK)); 260 n = getrandom(buf, sizeof buf, 261 ~(GRND_RANDOM|GRND_INSECURE|GRND_NONBLOCK)); 262 ATF_CHECK_EQ(n, -1); 263 ATF_CHECK_EQ(errno, EINVAL); 264} 265 266ATF_TC(getrandom_fault); 267ATF_TC_HEAD(getrandom_fault, tc) 268{ 269 atf_tc_set_md_var(tc, "descr", "getrandom(NULL, ...)"); 270} 271ATF_TC_BODY(getrandom_fault, tc) 272{ 273 ssize_t n; 274 275 /* unmapped */ 276 n = getrandom(NULL, sizeof buf, GRND_INSECURE|GRND_NONBLOCK); 277 ATF_CHECK_EQ(n, -1); 278 ATF_CHECK_EQ(errno, EFAULT); 279} 280 281ATF_TP_ADD_TCS(tp) 282{ 283 284 ATF_TP_ADD_TC(tp, getrandom_default); 285 ATF_TP_ADD_TC(tp, getrandom_nonblock); 286 ATF_TP_ADD_TC(tp, getrandom_insecure); 287 ATF_TP_ADD_TC(tp, getrandom_insecure_nonblock); 288 ATF_TP_ADD_TC(tp, getrandom_random); 289 ATF_TP_ADD_TC(tp, getrandom_random_nonblock); 290 ATF_TP_ADD_TC(tp, getrandom_random_insecure); 291 ATF_TP_ADD_TC(tp, getrandom_random_insecure_nonblock); 292 ATF_TP_ADD_TC(tp, getrandom_invalid); 293 ATF_TP_ADD_TC(tp, getrandom_fault); 294 295 return atf_no_error(); 296} 297