1 /* Implementation of getentropy based on getrandom.
2    Copyright (C) 2016-2022 Free Software Foundation, Inc.
3    This file is part of the GNU C Library.
4 
5    The GNU C Library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Lesser General Public
7    License as published by the Free Software Foundation; either
8    version 2.1 of the License, or (at your option) any later version.
9 
10    The GNU C Library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Lesser General Public License for more details.
14 
15    You should have received a copy of the GNU Lesser General Public
16    License along with the GNU C Library; if not, see
17    <https://www.gnu.org/licenses/>.  */
18 
19 #include <sys/random.h>
20 #include <assert.h>
21 #include <errno.h>
22 #include <unistd.h>
23 
24 /* Write LENGTH bytes of randomness starting at BUFFER.  Return 0 on
25    success and -1 on failure.  */
26 int
getentropy(void * buffer,size_t length)27 getentropy (void *buffer, size_t length)
28 {
29   /* The interface is documented to return EIO for buffer lengths
30      longer than 256 bytes.  */
31   if (length > 256)
32     {
33       __set_errno (EIO);
34       return -1;
35     }
36 
37   /* Try to fill the buffer completely.  Even with the 256 byte limit
38      above, we might still receive an EINTR error (when blocking
39      during boot).  */
40   void *end = buffer + length;
41   while (buffer < end)
42     {
43       /* NB: No cancellation point.  */
44       ssize_t bytes = __getrandom (buffer, end - buffer, 0);
45       if (bytes < 0)
46         {
47           if (errno == EINTR)
48             /* Try again if interrupted by a signal.  */
49             continue;
50           else
51             return -1;
52         }
53       if (bytes == 0)
54         {
55           /* No more bytes available.  This should not happen under
56              normal circumstances.  */
57           __set_errno (EIO);
58           return -1;
59         }
60       /* Try again in case of a short read.  */
61       buffer += bytes;
62     }
63   return 0;
64 }
65