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