1 /* $NetBSD: t_getrandom.c,v 1.3 2020/08/25 01:37:38 riastradh 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.3 2020/08/25 01:37:38 riastradh Exp $"); 34 35 #include <sys/random.h> 36 37 #include <atf-c.h> 38 #include <errno.h> 39 #include <signal.h> 40 #include <stdio.h> 41 #include <unistd.h> 42 43 static uint8_t buf[65536]; 44 static uint8_t zero24[24]; 45 46 static void 47 alarm_handler(int signo) 48 { 49 50 fprintf(stderr, "timeout\n"); 51 } 52 53 static void 54 install_alarm_handler(void) 55 { 56 struct sigaction sa; 57 58 memset(&sa, 0, sizeof sa); 59 sa.sa_handler = alarm_handler; 60 sigfillset(&sa.sa_mask); 61 sa.sa_flags = 0; /* no SA_RESTART */ 62 63 ATF_CHECK_MSG(sigaction(SIGALRM, &sa, NULL) != -1, 64 "sigaction(SIGALRM): %s", strerror(errno)); 65 } 66 67 /* 68 * Probability of spurious failure is 1/2^192 for each of the memcmps. 69 * As long as there are fewer than 2^64 of them, the probability of 70 * spurious failure is at most 1/2^128, which is low enough that we 71 * don't care about it. 72 */ 73 74 ATF_TC(getrandom_default); 75 ATF_TC_HEAD(getrandom_default, tc) 76 { 77 atf_tc_set_md_var(tc, "descr", "getrandom(..., 0)"); 78 atf_tc_set_md_var(tc, "timeout", "2"); 79 } 80 ATF_TC_BODY(getrandom_default, tc) 81 { 82 ssize_t n; 83 84 /* default */ 85 install_alarm_handler(); 86 alarm(1); 87 memset(buf, 0, sizeof buf); 88 n = getrandom(buf, sizeof buf, 0); 89 if (n == -1) { 90 ATF_CHECK_EQ(errno, EINTR); 91 } else { 92 ATF_CHECK_EQ((size_t)n, sizeof buf); 93 ATF_CHECK(memcmp(buf, zero24, 24) != 0); 94 ATF_CHECK(memcmp(buf + sizeof buf - 24, zero24, 24) != 0); 95 } 96 alarm(0); 97 } 98 99 ATF_TC(getrandom_nonblock); 100 ATF_TC_HEAD(getrandom_nonblock, tc) 101 { 102 atf_tc_set_md_var(tc, "descr", "getrandom(..., GRND_NONBLOCK)"); 103 } 104 ATF_TC_BODY(getrandom_nonblock, tc) 105 { 106 ssize_t n; 107 108 /* default, nonblocking */ 109 memset(buf, 0, sizeof buf); 110 n = getrandom(buf, sizeof buf, GRND_NONBLOCK); 111 if (n == -1) { 112 ATF_CHECK_EQ(errno, EAGAIN); 113 } else { 114 ATF_CHECK_EQ((size_t)n, sizeof buf); 115 ATF_CHECK(memcmp(buf, zero24, 24) != 0); 116 ATF_CHECK(memcmp(buf + sizeof buf - 24, zero24, 24) != 0); 117 } 118 } 119 120 ATF_TC(getrandom_insecure); 121 ATF_TC_HEAD(getrandom_insecure, tc) 122 { 123 atf_tc_set_md_var(tc, "descr", "getrandom(..., GRND_INSECURE)"); 124 } 125 ATF_TC_BODY(getrandom_insecure, tc) 126 { 127 ssize_t n; 128 129 /* insecure */ 130 memset(buf, 0, sizeof buf); 131 n = getrandom(buf, sizeof buf, GRND_INSECURE); 132 ATF_CHECK(n != -1); 133 ATF_CHECK_EQ((size_t)n, sizeof buf); 134 ATF_CHECK(memcmp(buf, zero24, 24) != 0); 135 ATF_CHECK(memcmp(buf + sizeof buf - 24, zero24, 24) != 0); 136 } 137 138 ATF_TC(getrandom_insecure_nonblock); 139 ATF_TC_HEAD(getrandom_insecure_nonblock, tc) 140 { 141 atf_tc_set_md_var(tc, "descr", 142 "getrandom(..., GRND_INSECURE|GRND_NONBLOCK)"); 143 } 144 ATF_TC_BODY(getrandom_insecure_nonblock, tc) 145 { 146 ssize_t n; 147 148 /* insecure, nonblocking -- same as mere insecure */ 149 memset(buf, 0, sizeof buf); 150 n = getrandom(buf, sizeof buf, GRND_INSECURE|GRND_NONBLOCK); 151 ATF_CHECK(n != -1); 152 ATF_CHECK_EQ((size_t)n, sizeof buf); 153 ATF_CHECK(memcmp(buf, zero24, 24) != 0); 154 ATF_CHECK(memcmp(buf + sizeof buf - 24, zero24, 24) != 0); 155 } 156 157 ATF_TC(getrandom_random); 158 ATF_TC_HEAD(getrandom_random, tc) 159 { 160 atf_tc_set_md_var(tc, "descr", "getrandom(..., GRND_RANDOM)"); 161 atf_tc_set_md_var(tc, "timeout", "2"); 162 } 163 ATF_TC_BODY(getrandom_random, tc) 164 { 165 ssize_t n; 166 167 /* `random' (hokey) */ 168 install_alarm_handler(); 169 alarm(1); 170 memset(buf, 0, sizeof buf); 171 n = getrandom(buf, sizeof buf, GRND_RANDOM); 172 if (n == -1) { 173 ATF_CHECK_EQ(errno, EINTR); 174 } else { 175 ATF_CHECK(n != 0); 176 ATF_CHECK((size_t)n <= sizeof buf); 177 if ((size_t)n >= 24) { 178 ATF_CHECK(memcmp(buf, zero24, 24) != 0); 179 ATF_CHECK(memcmp(buf + n - 24, zero24, 24) != 0); 180 } 181 } 182 alarm(0); 183 } 184 185 ATF_TC(getrandom_random_nonblock); 186 ATF_TC_HEAD(getrandom_random_nonblock, tc) 187 { 188 atf_tc_set_md_var(tc, "descr", 189 "getrandom(..., GRND_RANDOM|GRND_NONBLOCK)"); 190 } 191 ATF_TC_BODY(getrandom_random_nonblock, tc) 192 { 193 ssize_t n; 194 195 /* `random' (hokey), nonblocking */ 196 memset(buf, 0, sizeof buf); 197 n = getrandom(buf, sizeof buf, GRND_RANDOM|GRND_NONBLOCK); 198 if (n == -1) { 199 ATF_CHECK_EQ(errno, EAGAIN); 200 } else { 201 ATF_CHECK(n != 0); 202 ATF_CHECK((size_t)n <= sizeof buf); 203 if ((size_t)n >= 24) { 204 ATF_CHECK(memcmp(buf, zero24, 24) != 0); 205 ATF_CHECK(memcmp(buf + n - 24, zero24, 24) != 0); 206 } 207 } 208 } 209 210 ATF_TC(getrandom_random_insecure); 211 ATF_TC_HEAD(getrandom_random_insecure, tc) 212 { 213 atf_tc_set_md_var(tc, "descr", 214 "getrandom(..., GRND_RANDOM|GRND_INSECURE)"); 215 } 216 ATF_TC_BODY(getrandom_random_insecure, tc) 217 { 218 ssize_t n; 219 220 /* random and insecure -- nonsensical */ 221 n = getrandom(buf, sizeof buf, GRND_RANDOM|GRND_INSECURE); 222 ATF_CHECK_EQ(n, -1); 223 ATF_CHECK_EQ(errno, EINVAL); 224 } 225 226 ATF_TC(getrandom_random_insecure_nonblock); 227 ATF_TC_HEAD(getrandom_random_insecure_nonblock, tc) 228 { 229 atf_tc_set_md_var(tc, "descr", 230 "getrandom(..., GRND_RANDOM|GRND_INSECURE|GRND_NONBLOCK)"); 231 } 232 ATF_TC_BODY(getrandom_random_insecure_nonblock, tc) 233 { 234 ssize_t n; 235 236 /* random and insecure, nonblocking -- nonsensical */ 237 n = getrandom(buf, sizeof buf, 238 GRND_RANDOM|GRND_INSECURE|GRND_NONBLOCK); 239 ATF_CHECK_EQ(n, -1); 240 ATF_CHECK_EQ(errno, EINVAL); 241 } 242 243 ATF_TC(getrandom_invalid); 244 ATF_TC_HEAD(getrandom_invalid, tc) 245 { 246 atf_tc_set_md_var(tc, "descr", "getrandom(..., <invalid>)"); 247 } 248 ATF_TC_BODY(getrandom_invalid, tc) 249 { 250 ssize_t n; 251 252 /* invalid flags */ 253 __CTASSERT(~(GRND_RANDOM|GRND_INSECURE|GRND_NONBLOCK)); 254 n = getrandom(buf, sizeof buf, 255 ~(GRND_RANDOM|GRND_INSECURE|GRND_NONBLOCK)); 256 ATF_CHECK_EQ(n, -1); 257 ATF_CHECK_EQ(errno, EINVAL); 258 } 259 260 ATF_TC(getrandom_fault); 261 ATF_TC_HEAD(getrandom_fault, tc) 262 { 263 atf_tc_set_md_var(tc, "descr", "getrandom(NULL, ...)"); 264 } 265 ATF_TC_BODY(getrandom_fault, tc) 266 { 267 ssize_t n; 268 269 /* unmapped */ 270 n = getrandom(NULL, sizeof buf, GRND_INSECURE|GRND_NONBLOCK); 271 ATF_CHECK_EQ(n, -1); 272 ATF_CHECK_EQ(errno, EFAULT); 273 } 274 275 ATF_TP_ADD_TCS(tp) 276 { 277 278 ATF_TP_ADD_TC(tp, getrandom_default); 279 ATF_TP_ADD_TC(tp, getrandom_nonblock); 280 ATF_TP_ADD_TC(tp, getrandom_insecure); 281 ATF_TP_ADD_TC(tp, getrandom_insecure_nonblock); 282 ATF_TP_ADD_TC(tp, getrandom_random); 283 ATF_TP_ADD_TC(tp, getrandom_random_nonblock); 284 ATF_TP_ADD_TC(tp, getrandom_random_insecure); 285 ATF_TP_ADD_TC(tp, getrandom_random_insecure_nonblock); 286 ATF_TP_ADD_TC(tp, getrandom_invalid); 287 ATF_TP_ADD_TC(tp, getrandom_fault); 288 289 return atf_no_error(); 290 } 291