1 /* Test of getting random bytes.
2    Copyright (C) 2020 Free Software Foundation, Inc.
3 
4    This program is free software: you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation; either version 3 of the License, or
7    (at your option) any later version.
8 
9    This program is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU General Public License for more details.
13 
14    You should have received a copy of the GNU General Public License
15    along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
16 
17 /* Written by Bruno Haible.  */
18 
19 #include <config.h>
20 
21 #include <sys/random.h>
22 
23 #include "signature.h"
24 SIGNATURE_CHECK (getrandom, ssize_t, (void *, size_t, unsigned int));
25 
26 #include <errno.h>
27 #include <string.h>
28 
29 #include "macros.h"
30 
31 int
main(void)32 main (void)
33 {
34   char buf1[8];
35   char buf2[8];
36   char large_buf[100000];
37   ssize_t ret;
38 
39   /* Check that different calls produce different results (with a high
40      probability).  */
41   ret = getrandom (buf1, sizeof (buf1), 0);
42   if (ret < 0)
43     ASSERT (errno == ENOSYS);
44   else
45     {
46       ret = getrandom (buf2, sizeof (buf2), 0);
47       if (ret < 0)
48         ASSERT (errno == ENOSYS);
49       else
50         {
51           /* It is very unlikely that two calls to getrandom produce the
52              same results.  */
53           ASSERT (memcmp (buf1, buf2, sizeof (buf1)) != 0);
54         }
55     }
56 
57   /* Likewise with the "truly random" number generator.  */
58   ret = getrandom (buf1, sizeof (buf1), GRND_RANDOM);
59   if (ret < 0)
60     ASSERT (errno == ENOSYS);
61   else
62     {
63       ret = getrandom (buf2, sizeof (buf2), GRND_RANDOM);
64       if (ret < 0)
65         ASSERT (errno == ENOSYS);
66       else
67         {
68           /* It is very unlikely that two calls to getrandom produce the
69              same results.  */
70           ASSERT (memcmp (buf1, buf2, sizeof (buf1)) != 0);
71         }
72     }
73 
74   /* Check that GRND_NONBLOCK works.  */
75   ret = getrandom (large_buf, sizeof (large_buf), GRND_RANDOM | GRND_NONBLOCK);
76   ASSERT (ret <= (ssize_t) sizeof (large_buf));
77   /* It is very unlikely that so many truly random bytes were ready.  */
78   if (ret < 0)
79     ASSERT (errno == ENOSYS || errno == EAGAIN
80             || errno == EINVAL /* Solaris */);
81   else
82     ASSERT (ret > 0);
83 
84   if (getrandom (buf1, 1, 0) < 1)
85     if (getrandom (buf1, 1, GRND_RANDOM) < 1)
86       {
87         fputs ("Skipping test: getrandom is ineffective\n", stderr);
88         return 77;
89       }
90 
91   return 0;
92 }
93