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) 2017 Chanho Park <chanho61.park@samsung.com>
11*e3935639SPhilip Paeps Copyright (c) 2022 Sean McBride <sean@rogue-research.com>
12*e3935639SPhilip Paeps Copyright (c) 2026 Matthew Fernandez <matthew.fernandez@gmail.com>
13*e3935639SPhilip Paeps Licensed under the MIT license:
14*e3935639SPhilip Paeps
15*e3935639SPhilip Paeps Permission is hereby granted, free of charge, to any person obtaining
16*e3935639SPhilip Paeps a copy of this software and associated documentation files (the
17*e3935639SPhilip Paeps "Software"), to deal in the Software without restriction, including
18*e3935639SPhilip Paeps without limitation the rights to use, copy, modify, merge, publish,
19*e3935639SPhilip Paeps distribute, sublicense, and/or sell copies of the Software, and to permit
20*e3935639SPhilip Paeps persons to whom the Software is furnished to do so, subject to the
21*e3935639SPhilip Paeps following conditions:
22*e3935639SPhilip Paeps
23*e3935639SPhilip Paeps The above copyright notice and this permission notice shall be included
24*e3935639SPhilip Paeps in all copies or substantial portions of the Software.
25*e3935639SPhilip Paeps
26*e3935639SPhilip Paeps THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
27*e3935639SPhilip Paeps EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
28*e3935639SPhilip Paeps MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
29*e3935639SPhilip Paeps NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
30*e3935639SPhilip Paeps DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
31*e3935639SPhilip Paeps OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
32*e3935639SPhilip Paeps USE OR OTHER DEALINGS IN THE SOFTWARE.
33*e3935639SPhilip Paeps */
34*e3935639SPhilip Paeps
35*e3935639SPhilip Paeps #include "random_getrandom.h"
36*e3935639SPhilip Paeps
37*e3935639SPhilip Paeps #include "expat_config.h" // for HAVE_GETRANDOM, HAVE_SYSCALL_GETRANDOM
38*e3935639SPhilip Paeps
39*e3935639SPhilip Paeps #if defined(HAVE_GETRANDOM)
40*e3935639SPhilip Paeps # include <sys/random.h> /* getrandom */
41*e3935639SPhilip Paeps #endif
42*e3935639SPhilip Paeps
43*e3935639SPhilip Paeps #if defined(HAVE_SYSCALL_GETRANDOM)
44*e3935639SPhilip Paeps # if ! defined(_GNU_SOURCE)
45*e3935639SPhilip Paeps # define _GNU_SOURCE 1 /* syscall prototype */
46*e3935639SPhilip Paeps # endif
47*e3935639SPhilip Paeps # include <unistd.h> /* syscall */
48*e3935639SPhilip Paeps # include <sys/syscall.h> /* SYS_getrandom */
49*e3935639SPhilip Paeps #endif // defined(HAVE_SYSCALL_GETRANDOM)
50*e3935639SPhilip Paeps
51*e3935639SPhilip Paeps #if ! defined(GRND_NONBLOCK)
52*e3935639SPhilip Paeps # define GRND_NONBLOCK 0x0001
53*e3935639SPhilip Paeps #endif /* defined(GRND_NONBLOCK) */
54*e3935639SPhilip Paeps
55*e3935639SPhilip Paeps #include <assert.h>
56*e3935639SPhilip Paeps #include <errno.h>
57*e3935639SPhilip Paeps #include <limits.h> // for INT_MAX
58*e3935639SPhilip Paeps
59*e3935639SPhilip Paeps /* Obtain entropy on Linux 3.17+ */
60*e3935639SPhilip Paeps bool
writeRandomBytes_getrandom_nonblock(void * target,size_t count)61*e3935639SPhilip Paeps writeRandomBytes_getrandom_nonblock(void *target, size_t count) {
62*e3935639SPhilip Paeps int success = false; /* full count bytes written? */
63*e3935639SPhilip Paeps size_t bytesWrittenTotal = 0;
64*e3935639SPhilip Paeps const unsigned int getrandomFlags = GRND_NONBLOCK;
65*e3935639SPhilip Paeps
66*e3935639SPhilip Paeps do {
67*e3935639SPhilip Paeps void *const currentTarget = (void *)((char *)target + bytesWrittenTotal);
68*e3935639SPhilip Paeps const size_t bytesToWrite = count - bytesWrittenTotal;
69*e3935639SPhilip Paeps
70*e3935639SPhilip Paeps assert(bytesToWrite <= INT_MAX);
71*e3935639SPhilip Paeps
72*e3935639SPhilip Paeps errno = 0;
73*e3935639SPhilip Paeps
74*e3935639SPhilip Paeps const int bytesWrittenMore =
75*e3935639SPhilip Paeps #if defined(HAVE_GETRANDOM)
76*e3935639SPhilip Paeps (int)getrandom(currentTarget, bytesToWrite, getrandomFlags);
77*e3935639SPhilip Paeps #else
78*e3935639SPhilip Paeps (int)syscall(SYS_getrandom, currentTarget, bytesToWrite,
79*e3935639SPhilip Paeps getrandomFlags);
80*e3935639SPhilip Paeps #endif
81*e3935639SPhilip Paeps
82*e3935639SPhilip Paeps if (bytesWrittenMore > 0) {
83*e3935639SPhilip Paeps bytesWrittenTotal += bytesWrittenMore;
84*e3935639SPhilip Paeps if (bytesWrittenTotal >= count)
85*e3935639SPhilip Paeps success = true;
86*e3935639SPhilip Paeps }
87*e3935639SPhilip Paeps } while (! success && (errno == EINTR));
88*e3935639SPhilip Paeps
89*e3935639SPhilip Paeps return success;
90*e3935639SPhilip Paeps }
91