1 /* Implementation of getentropy based on the getrandom system call.
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 #include <sysdep.h>
24 
25 /* Write LENGTH bytes of randomness starting at BUFFER.  Return 0 on
26    success and -1 on failure.  */
27 int
getentropy(void * buffer,size_t length)28 getentropy (void *buffer, size_t length)
29 {
30   /* The interface is documented to return EIO for buffer lengths
31      longer than 256 bytes.  */
32   if (length > 256)
33     {
34       __set_errno (EIO);
35       return -1;
36     }
37 
38   /* Try to fill the buffer completely.  Even with the 256 byte limit
39      above, we might still receive an EINTR error (when blocking
40      during boot).  */
41   void *end = buffer + length;
42   while (buffer < end)
43     {
44       /* NB: No cancellation point.  */
45       ssize_t bytes = INLINE_SYSCALL_CALL (getrandom, buffer, end - buffer, 0);
46       if (bytes < 0)
47         {
48           if (errno == EINTR)
49             /* Try again if interrupted by a signal.  */
50             continue;
51           else
52             return -1;
53         }
54       if (bytes == 0)
55         {
56           /* No more bytes available.  This should not happen under
57              normal circumstances.  */
58           __set_errno (EIO);
59           return -1;
60         }
61       /* Try again in case of a short read.  */
62       buffer += bytes;
63     }
64   return 0;
65 }
66