xref: /netbsd-src/tests/lib/libc/sys/t_getrandom.c (revision 82d56013d7b633d116a93943de88e08335357a7c)
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