1*2b5e567dSriastradh /* $NetBSD: t_getentropy.c,v 1.1 2022/05/31 13:42:59 riastradh Exp $ */
2*2b5e567dSriastradh
3*2b5e567dSriastradh /*-
4*2b5e567dSriastradh * Copyright (c) 2022 The NetBSD Foundation, Inc.
5*2b5e567dSriastradh * All rights reserved.
6*2b5e567dSriastradh *
7*2b5e567dSriastradh * Redistribution and use in source and binary forms, with or without
8*2b5e567dSriastradh * modification, are permitted provided that the following conditions
9*2b5e567dSriastradh * are met:
10*2b5e567dSriastradh * 1. Redistributions of source code must retain the above copyright
11*2b5e567dSriastradh * notice, this list of conditions and the following disclaimer.
12*2b5e567dSriastradh * 2. Redistributions in binary form must reproduce the above copyright
13*2b5e567dSriastradh * notice, this list of conditions and the following disclaimer in the
14*2b5e567dSriastradh * documentation and/or other materials provided with the distribution.
15*2b5e567dSriastradh *
16*2b5e567dSriastradh * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
17*2b5e567dSriastradh * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18*2b5e567dSriastradh * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19*2b5e567dSriastradh * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20*2b5e567dSriastradh * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21*2b5e567dSriastradh * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22*2b5e567dSriastradh * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23*2b5e567dSriastradh * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24*2b5e567dSriastradh * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25*2b5e567dSriastradh * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26*2b5e567dSriastradh * POSSIBILITY OF SUCH DAMAGE.
27*2b5e567dSriastradh */
28*2b5e567dSriastradh
29*2b5e567dSriastradh #include <sys/cdefs.h>
30*2b5e567dSriastradh __RCSID("$NetBSD: t_getentropy.c,v 1.1 2022/05/31 13:42:59 riastradh Exp $");
31*2b5e567dSriastradh
32*2b5e567dSriastradh #include <sys/mman.h>
33*2b5e567dSriastradh
34*2b5e567dSriastradh #include <atf-c.h>
35*2b5e567dSriastradh #include <errno.h>
36*2b5e567dSriastradh #include <limits.h>
37*2b5e567dSriastradh #include <stdint.h>
38*2b5e567dSriastradh #include <string.h>
39*2b5e567dSriastradh #include <unistd.h>
40*2b5e567dSriastradh
41*2b5e567dSriastradh static uint8_t buf[289];
42*2b5e567dSriastradh static uint8_t zero[sizeof(buf)];
43*2b5e567dSriastradh
44*2b5e567dSriastradh __CTASSERT(GETENTROPY_MAX == 256);
45*2b5e567dSriastradh
46*2b5e567dSriastradh ATF_TC(getentropy_0);
ATF_TC_HEAD(getentropy_0,tc)47*2b5e567dSriastradh ATF_TC_HEAD(getentropy_0, tc)
48*2b5e567dSriastradh {
49*2b5e567dSriastradh atf_tc_set_md_var(tc, "descr", "getentropy 0 bytes");
50*2b5e567dSriastradh atf_tc_set_md_var(tc, "timeout", "2");
51*2b5e567dSriastradh }
ATF_TC_BODY(getentropy_0,tc)52*2b5e567dSriastradh ATF_TC_BODY(getentropy_0, tc)
53*2b5e567dSriastradh {
54*2b5e567dSriastradh
55*2b5e567dSriastradh memset(buf, 0, sizeof(buf));
56*2b5e567dSriastradh if (getentropy(buf, 0) == -1)
57*2b5e567dSriastradh atf_tc_fail("getentropy: %d (%s)", errno, strerror(errno));
58*2b5e567dSriastradh ATF_CHECK(memcmp(buf, zero, sizeof(buf)) == 0);
59*2b5e567dSriastradh }
60*2b5e567dSriastradh
61*2b5e567dSriastradh ATF_TC(getentropy_32);
ATF_TC_HEAD(getentropy_32,tc)62*2b5e567dSriastradh ATF_TC_HEAD(getentropy_32, tc)
63*2b5e567dSriastradh {
64*2b5e567dSriastradh atf_tc_set_md_var(tc, "descr", "getentropy 32 bytes");
65*2b5e567dSriastradh atf_tc_set_md_var(tc, "timeout", "2");
66*2b5e567dSriastradh }
ATF_TC_BODY(getentropy_32,tc)67*2b5e567dSriastradh ATF_TC_BODY(getentropy_32, tc)
68*2b5e567dSriastradh {
69*2b5e567dSriastradh
70*2b5e567dSriastradh memset(buf, 0, sizeof(buf));
71*2b5e567dSriastradh if (getentropy(buf + 1, 32) == -1)
72*2b5e567dSriastradh atf_tc_fail("getentropy: %d (%s)", errno, strerror(errno));
73*2b5e567dSriastradh ATF_CHECK(buf[0] == 0);
74*2b5e567dSriastradh ATF_CHECK(memcmp(buf + 1, zero, 32) != 0);
75*2b5e567dSriastradh ATF_CHECK(memcmp(buf + 1 + 32, zero, sizeof(buf) - 1 - 32) == 0);
76*2b5e567dSriastradh }
77*2b5e567dSriastradh
78*2b5e567dSriastradh ATF_TC(getentropy_256);
ATF_TC_HEAD(getentropy_256,tc)79*2b5e567dSriastradh ATF_TC_HEAD(getentropy_256, tc)
80*2b5e567dSriastradh {
81*2b5e567dSriastradh atf_tc_set_md_var(tc, "descr", "getentropy 256 bytes");
82*2b5e567dSriastradh atf_tc_set_md_var(tc, "timeout", "2");
83*2b5e567dSriastradh }
ATF_TC_BODY(getentropy_256,tc)84*2b5e567dSriastradh ATF_TC_BODY(getentropy_256, tc)
85*2b5e567dSriastradh {
86*2b5e567dSriastradh
87*2b5e567dSriastradh memset(buf, 0, sizeof(buf));
88*2b5e567dSriastradh if (getentropy(buf + 1, 256) == -1)
89*2b5e567dSriastradh atf_tc_fail("getentropy: %d (%s)", errno, strerror(errno));
90*2b5e567dSriastradh ATF_CHECK(buf[0] == 0);
91*2b5e567dSriastradh ATF_CHECK(memcmp(buf + 1, zero, 256) != 0);
92*2b5e567dSriastradh ATF_CHECK(memcmp(buf + 1 + 256, zero, sizeof(buf) - 1 - 256) == 0);
93*2b5e567dSriastradh }
94*2b5e567dSriastradh
95*2b5e567dSriastradh ATF_TC(getentropy_257);
ATF_TC_HEAD(getentropy_257,tc)96*2b5e567dSriastradh ATF_TC_HEAD(getentropy_257, tc)
97*2b5e567dSriastradh {
98*2b5e567dSriastradh atf_tc_set_md_var(tc, "descr", "getentropy 257 bytes (beyond max)");
99*2b5e567dSriastradh atf_tc_set_md_var(tc, "timeout", "2");
100*2b5e567dSriastradh }
ATF_TC_BODY(getentropy_257,tc)101*2b5e567dSriastradh ATF_TC_BODY(getentropy_257, tc)
102*2b5e567dSriastradh {
103*2b5e567dSriastradh
104*2b5e567dSriastradh memset(buf, 0, sizeof(buf));
105*2b5e567dSriastradh ATF_CHECK_ERRNO(EINVAL, getentropy(buf, 257) == -1);
106*2b5e567dSriastradh ATF_CHECK(memcmp(buf, zero, sizeof(buf)) == 0);
107*2b5e567dSriastradh }
108*2b5e567dSriastradh
109*2b5e567dSriastradh ATF_TC(getentropy_null);
ATF_TC_HEAD(getentropy_null,tc)110*2b5e567dSriastradh ATF_TC_HEAD(getentropy_null, tc)
111*2b5e567dSriastradh {
112*2b5e567dSriastradh atf_tc_set_md_var(tc, "descr", "getentropy with null buffer");
113*2b5e567dSriastradh atf_tc_set_md_var(tc, "timeout", "2");
114*2b5e567dSriastradh }
ATF_TC_BODY(getentropy_null,tc)115*2b5e567dSriastradh ATF_TC_BODY(getentropy_null, tc)
116*2b5e567dSriastradh {
117*2b5e567dSriastradh
118*2b5e567dSriastradh ATF_CHECK_ERRNO(EFAULT, getentropy(NULL, 32) == -1);
119*2b5e567dSriastradh }
120*2b5e567dSriastradh
121*2b5e567dSriastradh ATF_TC(getentropy_nearnull);
ATF_TC_HEAD(getentropy_nearnull,tc)122*2b5e567dSriastradh ATF_TC_HEAD(getentropy_nearnull, tc)
123*2b5e567dSriastradh {
124*2b5e567dSriastradh atf_tc_set_md_var(tc, "descr", "getentropy with nearly null buffer");
125*2b5e567dSriastradh atf_tc_set_md_var(tc, "timeout", "2");
126*2b5e567dSriastradh }
ATF_TC_BODY(getentropy_nearnull,tc)127*2b5e567dSriastradh ATF_TC_BODY(getentropy_nearnull, tc)
128*2b5e567dSriastradh {
129*2b5e567dSriastradh
130*2b5e567dSriastradh ATF_CHECK_ERRNO(EFAULT, getentropy((char *)(uintptr_t)1, 32) == -1);
131*2b5e567dSriastradh }
132*2b5e567dSriastradh
133*2b5e567dSriastradh ATF_TC(getentropy_badaddr);
ATF_TC_HEAD(getentropy_badaddr,tc)134*2b5e567dSriastradh ATF_TC_HEAD(getentropy_badaddr, tc)
135*2b5e567dSriastradh {
136*2b5e567dSriastradh atf_tc_set_md_var(tc, "descr", "getentropy with bad address");
137*2b5e567dSriastradh atf_tc_set_md_var(tc, "timeout", "2");
138*2b5e567dSriastradh }
ATF_TC_BODY(getentropy_badaddr,tc)139*2b5e567dSriastradh ATF_TC_BODY(getentropy_badaddr, tc)
140*2b5e567dSriastradh {
141*2b5e567dSriastradh size_t pagesize = sysconf(_SC_PAGESIZE);
142*2b5e567dSriastradh char *p;
143*2b5e567dSriastradh
144*2b5e567dSriastradh /*
145*2b5e567dSriastradh * Allocate three consecutive pages and make the middle one
146*2b5e567dSriastradh * nonwritable.
147*2b5e567dSriastradh */
148*2b5e567dSriastradh p = mmap(NULL, 3*pagesize, PROT_READ|PROT_WRITE,
149*2b5e567dSriastradh MAP_ANON|MAP_PRIVATE, -1, 0);
150*2b5e567dSriastradh if (p == MAP_FAILED)
151*2b5e567dSriastradh atf_tc_fail("mmap: %d (%s)", errno, strerror(errno));
152*2b5e567dSriastradh if (mprotect(p + pagesize, pagesize, PROT_READ) == -1)
153*2b5e567dSriastradh atf_tc_fail("mprotect: %d (%s)", errno, strerror(errno));
154*2b5e567dSriastradh
155*2b5e567dSriastradh /* Verify that writing to the end of the first page works. */
156*2b5e567dSriastradh if (getentropy(p + pagesize - 25, 25) == -1)
157*2b5e567dSriastradh atf_tc_fail("getentropy 1: %d (%s)", errno, strerror(errno));
158*2b5e567dSriastradh ATF_CHECK(memcmp(p + pagesize - 25, zero, 25) != 0);
159*2b5e567dSriastradh
160*2b5e567dSriastradh /*
161*2b5e567dSriastradh * Verify that writes into the middle page, whether straddling
162*2b5e567dSriastradh * the surrounding pages or not, fail with EFAULT.
163*2b5e567dSriastradh */
164*2b5e567dSriastradh ATF_CHECK_ERRNO(EFAULT, getentropy(p + pagesize - 1, 2) == -1);
165*2b5e567dSriastradh ATF_CHECK_ERRNO(EFAULT, getentropy(p + pagesize, 32) == -1);
166*2b5e567dSriastradh ATF_CHECK_ERRNO(EFAULT, getentropy(p + 2*pagesize - 1, 2) == -1);
167*2b5e567dSriastradh
168*2b5e567dSriastradh /* Verify that writing to the start of the last page works. */
169*2b5e567dSriastradh if (getentropy(p + 2*pagesize, 25) == -1)
170*2b5e567dSriastradh atf_tc_fail("getentropy 2: %d (%s)", errno, strerror(errno));
171*2b5e567dSriastradh ATF_CHECK(memcmp(p + pagesize - 25, zero, 25) != 0);
172*2b5e567dSriastradh
173*2b5e567dSriastradh if (munmap(p, 3*pagesize) == -1)
174*2b5e567dSriastradh atf_tc_fail("munmap: %d (%s)", errno, strerror(errno));
175*2b5e567dSriastradh }
176*2b5e567dSriastradh
ATF_TP_ADD_TCS(tp)177*2b5e567dSriastradh ATF_TP_ADD_TCS(tp)
178*2b5e567dSriastradh {
179*2b5e567dSriastradh
180*2b5e567dSriastradh ATF_TP_ADD_TC(tp, getentropy_0);
181*2b5e567dSriastradh ATF_TP_ADD_TC(tp, getentropy_256);
182*2b5e567dSriastradh ATF_TP_ADD_TC(tp, getentropy_257);
183*2b5e567dSriastradh ATF_TP_ADD_TC(tp, getentropy_32);
184*2b5e567dSriastradh ATF_TP_ADD_TC(tp, getentropy_badaddr);
185*2b5e567dSriastradh ATF_TP_ADD_TC(tp, getentropy_nearnull);
186*2b5e567dSriastradh ATF_TP_ADD_TC(tp, getentropy_null);
187*2b5e567dSriastradh
188*2b5e567dSriastradh return atf_no_error();
189*2b5e567dSriastradh }
190