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
alarm_handler(int signo)49 alarm_handler(int signo)
50 {
51
52 fprintf(stderr, "timeout\n");
53 }
54
55 static void
install_alarm_handler(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);
ATF_TC_HEAD(getrandom_default,tc)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 }
ATF_TC_BODY(getrandom_default,tc)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);
ATF_TC_HEAD(getrandom_nonblock,tc)103 ATF_TC_HEAD(getrandom_nonblock, tc)
104 {
105 atf_tc_set_md_var(tc, "descr", "getrandom(..., GRND_NONBLOCK)");
106 }
ATF_TC_BODY(getrandom_nonblock,tc)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);
ATF_TC_HEAD(getrandom_insecure,tc)125 ATF_TC_HEAD(getrandom_insecure, tc)
126 {
127 atf_tc_set_md_var(tc, "descr", "getrandom(..., GRND_INSECURE)");
128 }
ATF_TC_BODY(getrandom_insecure,tc)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);
ATF_TC_HEAD(getrandom_insecure_nonblock,tc)144 ATF_TC_HEAD(getrandom_insecure_nonblock, tc)
145 {
146 atf_tc_set_md_var(tc, "descr",
147 "getrandom(..., GRND_INSECURE|GRND_NONBLOCK)");
148 }
ATF_TC_BODY(getrandom_insecure_nonblock,tc)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);
ATF_TC_HEAD(getrandom_random,tc)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 }
ATF_TC_BODY(getrandom_random,tc)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);
ATF_TC_HEAD(getrandom_random_nonblock,tc)192 ATF_TC_HEAD(getrandom_random_nonblock, tc)
193 {
194 atf_tc_set_md_var(tc, "descr",
195 "getrandom(..., GRND_RANDOM|GRND_NONBLOCK)");
196 }
ATF_TC_BODY(getrandom_random_nonblock,tc)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);
ATF_TC_HEAD(getrandom_random_insecure,tc)217 ATF_TC_HEAD(getrandom_random_insecure, tc)
218 {
219 atf_tc_set_md_var(tc, "descr",
220 "getrandom(..., GRND_RANDOM|GRND_INSECURE)");
221 }
ATF_TC_BODY(getrandom_random_insecure,tc)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);
ATF_TC_HEAD(getrandom_random_insecure_nonblock,tc)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 }
ATF_TC_BODY(getrandom_random_insecure_nonblock,tc)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);
ATF_TC_HEAD(getrandom_invalid,tc)250 ATF_TC_HEAD(getrandom_invalid, tc)
251 {
252 atf_tc_set_md_var(tc, "descr", "getrandom(..., <invalid>)");
253 }
ATF_TC_BODY(getrandom_invalid,tc)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);
ATF_TC_HEAD(getrandom_fault,tc)267 ATF_TC_HEAD(getrandom_fault, tc)
268 {
269 atf_tc_set_md_var(tc, "descr", "getrandom(NULL, ...)");
270 }
ATF_TC_BODY(getrandom_fault,tc)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
ATF_TP_ADD_TCS(tp)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