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 45 static uint8_t buf[65536]; 46 static uint8_t zero24[24]; 47 48 static void 49 alarm_handler(int signo) 50 { 51 52 fprintf(stderr, "timeout\n"); 53 } 54 55 static void 56 install_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 76 ATF_TC(getrandom_default); 77 ATF_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 } 82 ATF_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 102 ATF_TC(getrandom_nonblock); 103 ATF_TC_HEAD(getrandom_nonblock, tc) 104 { 105 atf_tc_set_md_var(tc, "descr", "getrandom(..., GRND_NONBLOCK)"); 106 } 107 ATF_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 124 ATF_TC(getrandom_insecure); 125 ATF_TC_HEAD(getrandom_insecure, tc) 126 { 127 atf_tc_set_md_var(tc, "descr", "getrandom(..., GRND_INSECURE)"); 128 } 129 ATF_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 143 ATF_TC(getrandom_insecure_nonblock); 144 ATF_TC_HEAD(getrandom_insecure_nonblock, tc) 145 { 146 atf_tc_set_md_var(tc, "descr", 147 "getrandom(..., GRND_INSECURE|GRND_NONBLOCK)"); 148 } 149 ATF_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 163 ATF_TC(getrandom_random); 164 ATF_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 } 169 ATF_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 191 ATF_TC(getrandom_random_nonblock); 192 ATF_TC_HEAD(getrandom_random_nonblock, tc) 193 { 194 atf_tc_set_md_var(tc, "descr", 195 "getrandom(..., GRND_RANDOM|GRND_NONBLOCK)"); 196 } 197 ATF_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 216 ATF_TC(getrandom_random_insecure); 217 ATF_TC_HEAD(getrandom_random_insecure, tc) 218 { 219 atf_tc_set_md_var(tc, "descr", 220 "getrandom(..., GRND_RANDOM|GRND_INSECURE)"); 221 } 222 ATF_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 232 ATF_TC(getrandom_random_insecure_nonblock); 233 ATF_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 } 238 ATF_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 249 ATF_TC(getrandom_invalid); 250 ATF_TC_HEAD(getrandom_invalid, tc) 251 { 252 atf_tc_set_md_var(tc, "descr", "getrandom(..., <invalid>)"); 253 } 254 ATF_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 266 ATF_TC(getrandom_fault); 267 ATF_TC_HEAD(getrandom_fault, tc) 268 { 269 atf_tc_set_md_var(tc, "descr", "getrandom(NULL, ...)"); 270 } 271 ATF_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 281 ATF_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