xref: /freebsd/contrib/expat/lib/random_dev_urandom.c (revision e3935639d8d8b6556cad18e1c90e419a65f26b40)
1*e3935639SPhilip Paeps /*
2*e3935639SPhilip Paeps                             __  __            _
3*e3935639SPhilip Paeps                          ___\ \/ /_ __   __ _| |_
4*e3935639SPhilip Paeps                         / _ \\  /| '_ \ / _` | __|
5*e3935639SPhilip Paeps                        |  __//  \| |_) | (_| | |_
6*e3935639SPhilip Paeps                         \___/_/\_\ .__/ \__,_|\__|
7*e3935639SPhilip Paeps                                  |_| XML parser
8*e3935639SPhilip Paeps 
9*e3935639SPhilip Paeps    Copyright (c) 2017-2026 Sebastian Pipping <sebastian@pipping.org>
10*e3935639SPhilip Paeps    Copyright (c) 2026      Matthew Fernandez <matthew.fernandez@gmail.com>
11*e3935639SPhilip Paeps    Licensed under the MIT license:
12*e3935639SPhilip Paeps 
13*e3935639SPhilip Paeps    Permission is  hereby granted,  free of charge,  to any  person obtaining
14*e3935639SPhilip Paeps    a  copy  of  this  software   and  associated  documentation  files  (the
15*e3935639SPhilip Paeps    "Software"),  to  deal in  the  Software  without restriction,  including
16*e3935639SPhilip Paeps    without  limitation the  rights  to use,  copy,  modify, merge,  publish,
17*e3935639SPhilip Paeps    distribute, sublicense, and/or sell copies of the Software, and to permit
18*e3935639SPhilip Paeps    persons  to whom  the Software  is  furnished to  do so,  subject to  the
19*e3935639SPhilip Paeps    following conditions:
20*e3935639SPhilip Paeps 
21*e3935639SPhilip Paeps    The above copyright  notice and this permission notice  shall be included
22*e3935639SPhilip Paeps    in all copies or substantial portions of the Software.
23*e3935639SPhilip Paeps 
24*e3935639SPhilip Paeps    THE  SOFTWARE  IS  PROVIDED  "AS  IS",  WITHOUT  WARRANTY  OF  ANY  KIND,
25*e3935639SPhilip Paeps    EXPRESS  OR IMPLIED,  INCLUDING  BUT  NOT LIMITED  TO  THE WARRANTIES  OF
26*e3935639SPhilip Paeps    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
27*e3935639SPhilip Paeps    NO EVENT SHALL THE AUTHORS OR  COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
28*e3935639SPhilip Paeps    DAMAGES OR  OTHER LIABILITY, WHETHER  IN AN  ACTION OF CONTRACT,  TORT OR
29*e3935639SPhilip Paeps    OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
30*e3935639SPhilip Paeps    USE OR OTHER DEALINGS IN THE SOFTWARE.
31*e3935639SPhilip Paeps */
32*e3935639SPhilip Paeps 
33*e3935639SPhilip Paeps #include "random_dev_urandom.h"
34*e3935639SPhilip Paeps 
35*e3935639SPhilip Paeps #if ! defined(_POSIX_C_SOURCE)                                                 \
36*e3935639SPhilip Paeps     || (defined(_POSIX_C_SOURCE) && (_POSIX_C_SOURCE < 200809L))
37*e3935639SPhilip Paeps #  define _POSIX_C_SOURCE 200809L // for O_CLOEXEC
38*e3935639SPhilip Paeps #endif
39*e3935639SPhilip Paeps 
40*e3935639SPhilip Paeps #include <errno.h>
41*e3935639SPhilip Paeps #include <fcntl.h>  // open
42*e3935639SPhilip Paeps #include <unistd.h> // close
43*e3935639SPhilip Paeps 
44*e3935639SPhilip Paeps /* Extract entropy from /dev/urandom */
45*e3935639SPhilip Paeps bool
writeRandomBytes_dev_urandom(void * target,size_t count)46*e3935639SPhilip Paeps writeRandomBytes_dev_urandom(void *target, size_t count) {
47*e3935639SPhilip Paeps   int success = false; /* full count bytes written? */
48*e3935639SPhilip Paeps   size_t bytesWrittenTotal = 0;
49*e3935639SPhilip Paeps 
50*e3935639SPhilip Paeps   const int fd = open("/dev/urandom", O_RDONLY | O_CLOEXEC);
51*e3935639SPhilip Paeps   if (fd < 0) {
52*e3935639SPhilip Paeps     return 0;
53*e3935639SPhilip Paeps   }
54*e3935639SPhilip Paeps 
55*e3935639SPhilip Paeps   do {
56*e3935639SPhilip Paeps     void *const currentTarget = (void *)((char *)target + bytesWrittenTotal);
57*e3935639SPhilip Paeps     const size_t bytesToWrite = count - bytesWrittenTotal;
58*e3935639SPhilip Paeps 
59*e3935639SPhilip Paeps     errno = 0;
60*e3935639SPhilip Paeps 
61*e3935639SPhilip Paeps     const ssize_t bytesWrittenMore = read(fd, currentTarget, bytesToWrite);
62*e3935639SPhilip Paeps 
63*e3935639SPhilip Paeps     if (bytesWrittenMore > 0) {
64*e3935639SPhilip Paeps       bytesWrittenTotal += bytesWrittenMore;
65*e3935639SPhilip Paeps       if (bytesWrittenTotal >= count)
66*e3935639SPhilip Paeps         success = true;
67*e3935639SPhilip Paeps     }
68*e3935639SPhilip Paeps   } while (! success && (errno == EINTR));
69*e3935639SPhilip Paeps 
70*e3935639SPhilip Paeps   close(fd);
71*e3935639SPhilip Paeps   return success;
72*e3935639SPhilip Paeps }
73