Absolute File Name: | /home/opencoverage/opencoverage/guest-scripts/coreutils/src/gl/lib/randread.c |
Source code | Switch to Preprocessed file |
Line | Source | Count | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
1 | /* Generate buffers of random data. | - | ||||||||||||
2 | - | |||||||||||||
3 | Copyright (C) 2006-2018 Free Software Foundation, Inc. | - | ||||||||||||
4 | - | |||||||||||||
5 | This program is free software: you can redistribute it and/or modify | - | ||||||||||||
6 | it under the terms of the GNU General Public License as published by | - | ||||||||||||
7 | the Free Software Foundation, either version 3 of the License, or | - | ||||||||||||
8 | (at your option) any later version. | - | ||||||||||||
9 | - | |||||||||||||
10 | This program 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 | - | ||||||||||||
13 | GNU General Public License for more details. | - | ||||||||||||
14 | - | |||||||||||||
15 | You should have received a copy of the GNU General Public License | - | ||||||||||||
16 | along with this program. If not, see <https://www.gnu.org/licenses/>. */ | - | ||||||||||||
17 | - | |||||||||||||
18 | /* Written by Paul Eggert. */ | - | ||||||||||||
19 | - | |||||||||||||
20 | /* FIXME: Improve performance by adding support for the RDRAND machine | - | ||||||||||||
21 | instruction if available (e.g., Ivy Bridge processors). */ | - | ||||||||||||
22 | - | |||||||||||||
23 | #include <config.h> | - | ||||||||||||
24 | - | |||||||||||||
25 | #include "randread.h" | - | ||||||||||||
26 | - | |||||||||||||
27 | #include <errno.h> | - | ||||||||||||
28 | #include <error.h> | - | ||||||||||||
29 | #include <exitfail.h> | - | ||||||||||||
30 | #include <fcntl.h> | - | ||||||||||||
31 | #include <quote.h> | - | ||||||||||||
32 | #include <stdalign.h> | - | ||||||||||||
33 | #include <stdbool.h> | - | ||||||||||||
34 | #include <stdint.h> | - | ||||||||||||
35 | #include <stdio.h> | - | ||||||||||||
36 | #include <stdlib.h> | - | ||||||||||||
37 | #include <string.h> | - | ||||||||||||
38 | #include <sys/time.h> | - | ||||||||||||
39 | #include <unistd.h> | - | ||||||||||||
40 | - | |||||||||||||
41 | #include "gettext.h" | - | ||||||||||||
42 | #define _(msgid) gettext (msgid) | - | ||||||||||||
43 | - | |||||||||||||
44 | #include "rand-isaac.h" | - | ||||||||||||
45 | #include "stdio-safer.h" | - | ||||||||||||
46 | #include "unlocked-io.h" | - | ||||||||||||
47 | #include "xalloc.h" | - | ||||||||||||
48 | - | |||||||||||||
49 | #ifndef __attribute__ | - | ||||||||||||
50 | # if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 8) | - | ||||||||||||
51 | # define __attribute__(x) /* empty */ | - | ||||||||||||
52 | # endif | - | ||||||||||||
53 | #endif | - | ||||||||||||
54 | - | |||||||||||||
55 | #ifndef ATTRIBUTE_NORETURN | - | ||||||||||||
56 | # define ATTRIBUTE_NORETURN __attribute__ ((__noreturn__)) | - | ||||||||||||
57 | #endif | - | ||||||||||||
58 | - | |||||||||||||
59 | #ifndef MIN | - | ||||||||||||
60 | # define MIN(a, b) ((a) < (b) ? (a) : (b)) | - | ||||||||||||
61 | #endif | - | ||||||||||||
62 | - | |||||||||||||
63 | #if _STRING_ARCH_unaligned || _STRING_INLINE_unaligned | - | ||||||||||||
64 | # define ALIGNED_POINTER(ptr, type) true | - | ||||||||||||
65 | #else | - | ||||||||||||
66 | # define ALIGNED_POINTER(ptr, type) ((size_t) (ptr) % alignof (type) == 0) | - | ||||||||||||
67 | #endif | - | ||||||||||||
68 | - | |||||||||||||
69 | #ifndef NAME_OF_NONCE_DEVICE | - | ||||||||||||
70 | # define NAME_OF_NONCE_DEVICE "/dev/urandom" | - | ||||||||||||
71 | #endif | - | ||||||||||||
72 | - | |||||||||||||
73 | /* The maximum buffer size used for reads of random data. Using the | - | ||||||||||||
74 | value 2 * ISAAC_BYTES makes this the largest power of two that | - | ||||||||||||
75 | would not otherwise cause struct randread_source to grow. */ | - | ||||||||||||
76 | #define RANDREAD_BUFFER_SIZE (2 * ISAAC_BYTES) | - | ||||||||||||
77 | - | |||||||||||||
78 | /* A source of random data for generating random buffers. */ | - | ||||||||||||
79 | struct randread_source | - | ||||||||||||
80 | { | - | ||||||||||||
81 | /* Stream to read random bytes from. If null, the current | - | ||||||||||||
82 | implementation uses an internal PRNG (ISAAC). */ | - | ||||||||||||
83 | FILE *source; | - | ||||||||||||
84 | - | |||||||||||||
85 | /* Function to call, and its argument, if there is an input error or | - | ||||||||||||
86 | end of file when reading from the stream; errno is nonzero if | - | ||||||||||||
87 | there was an error. If this function returns, it should fix the | - | ||||||||||||
88 | problem before returning. The default handler assumes that | - | ||||||||||||
89 | handler_arg is the file name of the source. */ | - | ||||||||||||
90 | void (*handler) (void const *); | - | ||||||||||||
91 | void const *handler_arg; | - | ||||||||||||
92 | - | |||||||||||||
93 | /* The buffer for SOURCE. It's kept here to simplify storage | - | ||||||||||||
94 | allocation and to make it easier to clear out buffered random | - | ||||||||||||
95 | data. */ | - | ||||||||||||
96 | union | - | ||||||||||||
97 | { | - | ||||||||||||
98 | /* The stream buffer, if SOURCE is not null. */ | - | ||||||||||||
99 | char c[RANDREAD_BUFFER_SIZE]; | - | ||||||||||||
100 | - | |||||||||||||
101 | /* The buffered ISAAC pseudorandom buffer, if SOURCE is null. */ | - | ||||||||||||
102 | struct isaac | - | ||||||||||||
103 | { | - | ||||||||||||
104 | /* The number of bytes that are buffered at the end of data.b. */ | - | ||||||||||||
105 | size_t buffered; | - | ||||||||||||
106 | - | |||||||||||||
107 | /* State of the ISAAC generator. */ | - | ||||||||||||
108 | struct isaac_state state; | - | ||||||||||||
109 | - | |||||||||||||
110 | /* Up to a buffer's worth of pseudorandom data. */ | - | ||||||||||||
111 | union | - | ||||||||||||
112 | { | - | ||||||||||||
113 | isaac_word w[ISAAC_WORDS]; | - | ||||||||||||
114 | unsigned char b[ISAAC_BYTES]; | - | ||||||||||||
115 | } data; | - | ||||||||||||
116 | } isaac; | - | ||||||||||||
117 | } buf; | - | ||||||||||||
118 | }; | - | ||||||||||||
119 | - | |||||||||||||
120 | - | |||||||||||||
121 | /* The default error handler. */ | - | ||||||||||||
122 | - | |||||||||||||
123 | static void ATTRIBUTE_NORETURN | - | ||||||||||||
124 | randread_error (void const *file_name) | - | ||||||||||||
125 | { | - | ||||||||||||
126 | if (file_name)
| 0 | ||||||||||||
127 | error (exit_failure, errno, never executed: error (exit_failure, (*__errno_location ()) , (*__errno_location ()) == 0 ? dcgettext (((void *)0), "%s: end of file" , 5) : dcgettext (((void *)0), "%s: read error" , 5) , quote (file_name)); | 0 | ||||||||||||
128 | errno == 0 ? _("%s: end of file") : _("%s: read error"), never executed: error (exit_failure, (*__errno_location ()) , (*__errno_location ()) == 0 ? dcgettext (((void *)0), "%s: end of file" , 5) : dcgettext (((void *)0), "%s: read error" , 5) , quote (file_name)); | 0 | ||||||||||||
129 | quote (file_name)); never executed: error (exit_failure, (*__errno_location ()) , (*__errno_location ()) == 0 ? dcgettext (((void *)0), "%s: end of file" , 5) : dcgettext (((void *)0), "%s: read error" , 5) , quote (file_name)); | 0 | ||||||||||||
130 | abort (); never executed: abort (); | 0 | ||||||||||||
131 | } | - | ||||||||||||
132 | - | |||||||||||||
133 | /* Simply return a new randread_source object with the default error | - | ||||||||||||
134 | handler. */ | - | ||||||||||||
135 | - | |||||||||||||
136 | static struct randread_source * | - | ||||||||||||
137 | simple_new (FILE *source, void const *handler_arg) | - | ||||||||||||
138 | { | - | ||||||||||||
139 | struct randread_source *s = xmalloc (sizeof *s); | - | ||||||||||||
140 | s->source = source; | - | ||||||||||||
141 | s->handler = randread_error; | - | ||||||||||||
142 | s->handler_arg = handler_arg; | - | ||||||||||||
143 | return s; executed 655 times by 7 tests: return s; Executed by:
| 655 | ||||||||||||
144 | } | - | ||||||||||||
145 | - | |||||||||||||
146 | /* Put a nonce value into BUFFER, with size BUFSIZE, but do not get | - | ||||||||||||
147 | more than BYTES_BOUND bytes' worth of random information from any | - | ||||||||||||
148 | nonce device. */ | - | ||||||||||||
149 | - | |||||||||||||
150 | static void | - | ||||||||||||
151 | get_nonce (void *buffer, size_t bufsize, size_t bytes_bound) | - | ||||||||||||
152 | { | - | ||||||||||||
153 | char *buf = buffer; | - | ||||||||||||
154 | ssize_t seeded = 0; | - | ||||||||||||
155 | - | |||||||||||||
156 | /* Get some data from FD if available. */ | - | ||||||||||||
157 | int fd = open (NAME_OF_NONCE_DEVICE, O_RDONLY | O_BINARY); | - | ||||||||||||
158 | if (0 <= fd)
| 0-649 | ||||||||||||
159 | { | - | ||||||||||||
160 | seeded = read (fd, buf, MIN (bufsize, bytes_bound)); | - | ||||||||||||
161 | if (seeded < 0)
| 0-649 | ||||||||||||
162 | seeded = 0; never executed: seeded = 0; | 0 | ||||||||||||
163 | close (fd); | - | ||||||||||||
164 | } executed 649 times by 7 tests: end of block Executed by:
| 649 | ||||||||||||
165 | - | |||||||||||||
166 | /* If there's no nonce device, use a poor approximation | - | ||||||||||||
167 | by getting the time of day, etc. */ | - | ||||||||||||
168 | #define ISAAC_SEED(type, initialize_v) \ | - | ||||||||||||
169 | if (seeded < bufsize) \ | - | ||||||||||||
170 | { \ | - | ||||||||||||
171 | type v; \ | - | ||||||||||||
172 | size_t nbytes = MIN (sizeof v, bufsize - seeded); \ | - | ||||||||||||
173 | initialize_v; \ | - | ||||||||||||
174 | memcpy (buf + seeded, &v, nbytes); \ | - | ||||||||||||
175 | seeded += nbytes; \ | - | ||||||||||||
176 | } | - | ||||||||||||
177 | ISAAC_SEED (struct timeval, gettimeofday (&v, NULL)); executed 618 times by 6 tests: end of block Executed by:
| 0-618 | ||||||||||||
178 | ISAAC_SEED (pid_t, v = getpid ()); executed 618 times by 6 tests: end of block Executed by:
| 0-618 | ||||||||||||
179 | ISAAC_SEED (pid_t, v = getppid ()); executed 618 times by 6 tests: end of block Executed by:
| 0-618 | ||||||||||||
180 | ISAAC_SEED (uid_t, v = getuid ()); executed 618 times by 6 tests: end of block Executed by:
| 0-618 | ||||||||||||
181 | ISAAC_SEED (uid_t, v = getgid ()); executed 618 times by 6 tests: end of block Executed by:
| 0-618 | ||||||||||||
182 | - | |||||||||||||
183 | #ifdef lint | - | ||||||||||||
184 | /* Normally we like having the extra randomness from uninitialized | - | ||||||||||||
185 | parts of BUFFER. However, omit this randomness if we want to | - | ||||||||||||
186 | avoid false-positives from memory-checking debugging tools. */ | - | ||||||||||||
187 | memset (buf + seeded, 0, bufsize - seeded); | - | ||||||||||||
188 | #endif | - | ||||||||||||
189 | } executed 649 times by 7 tests: end of block Executed by:
| 649 | ||||||||||||
190 | - | |||||||||||||
191 | - | |||||||||||||
192 | /* Create and initialize a random data source from NAME, or use a | - | ||||||||||||
193 | reasonable default source if NAME is null. BYTES_BOUND is an upper | - | ||||||||||||
194 | bound on the number of bytes that will be needed. If zero, it is a | - | ||||||||||||
195 | hard bound; otherwise it is just an estimate. | - | ||||||||||||
196 | - | |||||||||||||
197 | If NAME is not null, NAME is saved for use as the argument of the | - | ||||||||||||
198 | default handler. Unless a non-default handler is used, NAME's | - | ||||||||||||
199 | lifetime should be at least that of the returned value. | - | ||||||||||||
200 | - | |||||||||||||
201 | Return NULL (setting errno) on failure. */ | - | ||||||||||||
202 | - | |||||||||||||
203 | struct randread_source * | - | ||||||||||||
204 | randread_new (char const *name, size_t bytes_bound) | - | ||||||||||||
205 | { | - | ||||||||||||
206 | if (bytes_bound == 0)
| 4-651 | ||||||||||||
207 | return simple_new (NULL, NULL); executed 4 times by 1 test: return simple_new ( ((void *)0) , ((void *)0) ); Executed by:
| 4 | ||||||||||||
208 | else | - | ||||||||||||
209 | { | - | ||||||||||||
210 | FILE *source = NULL; | - | ||||||||||||
211 | struct randread_source *s; | - | ||||||||||||
212 | - | |||||||||||||
213 | if (name)
| 2-649 | ||||||||||||
214 | if (! (source = fopen_safer (name, "rb")))
| 0-2 | ||||||||||||
215 | return NULL; never executed: return ((void *)0) ; | 0 | ||||||||||||
216 | - | |||||||||||||
217 | s = simple_new (source, name); | - | ||||||||||||
218 | - | |||||||||||||
219 | if (source)
| 2-649 | ||||||||||||
220 | setvbuf (source, s->buf.c, _IOFBF, MIN (sizeof s->buf.c, bytes_bound)); executed 2 times by 2 tests: setvbuf (source, s->buf.c, 0 , ((sizeof s->buf.c) < (bytes_bound) ? (sizeof s->buf.c) : (bytes_bound))); Executed by:
| 2 | ||||||||||||
221 | else | - | ||||||||||||
222 | { | - | ||||||||||||
223 | s->buf.isaac.buffered = 0; | - | ||||||||||||
224 | get_nonce (s->buf.isaac.state.m, sizeof s->buf.isaac.state.m, | - | ||||||||||||
225 | bytes_bound); | - | ||||||||||||
226 | isaac_seed (&s->buf.isaac.state); | - | ||||||||||||
227 | } executed 649 times by 7 tests: end of block Executed by:
| 649 | ||||||||||||
228 | - | |||||||||||||
229 | return s; executed 651 times by 7 tests: return s; Executed by:
| 651 | ||||||||||||
230 | } | - | ||||||||||||
231 | } | - | ||||||||||||
232 | - | |||||||||||||
233 | - | |||||||||||||
234 | /* Set S's handler and its argument. HANDLER (HANDLER_ARG) is called | - | ||||||||||||
235 | when there is a read error or end of file from the random data | - | ||||||||||||
236 | source; errno is nonzero if there was an error. If HANDLER | - | ||||||||||||
237 | returns, it should fix the problem before returning. The default | - | ||||||||||||
238 | handler assumes that handler_arg is the file name of the source; it | - | ||||||||||||
239 | does not return. */ | - | ||||||||||||
240 | - | |||||||||||||
241 | void | - | ||||||||||||
242 | randread_set_handler (struct randread_source *s, void (*handler) (void const *)) | - | ||||||||||||
243 | { | - | ||||||||||||
244 | s->handler = handler; | - | ||||||||||||
245 | } never executed: end of block | 0 | ||||||||||||
246 | - | |||||||||||||
247 | void | - | ||||||||||||
248 | randread_set_handler_arg (struct randread_source *s, void const *handler_arg) | - | ||||||||||||
249 | { | - | ||||||||||||
250 | s->handler_arg = handler_arg; | - | ||||||||||||
251 | } never executed: end of block | 0 | ||||||||||||
252 | - | |||||||||||||
253 | - | |||||||||||||
254 | /* Place SIZE random bytes into the buffer beginning at P, using | - | ||||||||||||
255 | the stream in S. */ | - | ||||||||||||
256 | - | |||||||||||||
257 | static void | - | ||||||||||||
258 | readsource (struct randread_source *s, unsigned char *p, size_t size) | - | ||||||||||||
259 | { | - | ||||||||||||
260 | while (true) | - | ||||||||||||
261 | { | - | ||||||||||||
262 | size_t inbytes = fread (p, sizeof *p, size, s->source); | - | ||||||||||||
263 | int fread_errno = errno; | - | ||||||||||||
264 | p += inbytes; | - | ||||||||||||
265 | size -= inbytes; | - | ||||||||||||
266 | if (size == 0)
| 0-18 | ||||||||||||
267 | break; executed 18 times by 2 tests: break; Executed by:
| 18 | ||||||||||||
268 | errno = (ferror (s->source) ? fread_errno : 0); | - | ||||||||||||
269 | s->handler (s->handler_arg); | - | ||||||||||||
270 | } never executed: end of block | 0 | ||||||||||||
271 | } executed 18 times by 2 tests: end of block Executed by:
| 18 | ||||||||||||
272 | - | |||||||||||||
273 | - | |||||||||||||
274 | /* Place SIZE pseudorandom bytes into the buffer beginning at P, using | - | ||||||||||||
275 | the buffered ISAAC generator in ISAAC. */ | - | ||||||||||||
276 | - | |||||||||||||
277 | static void | - | ||||||||||||
278 | readisaac (struct isaac *isaac, void *p, size_t size) | - | ||||||||||||
279 | { | - | ||||||||||||
280 | size_t inbytes = isaac->buffered; | - | ||||||||||||
281 | - | |||||||||||||
282 | while (true) | - | ||||||||||||
283 | { | - | ||||||||||||
284 | char *char_p = p; | - | ||||||||||||
285 | - | |||||||||||||
286 | if (size <= inbytes)
| 685-6236 | ||||||||||||
287 | { | - | ||||||||||||
288 | memcpy (p, isaac->data.b + ISAAC_BYTES - inbytes, size); | - | ||||||||||||
289 | isaac->buffered = inbytes - size; | - | ||||||||||||
290 | return; executed 6236 times by 7 tests: return; Executed by:
| 6236 | ||||||||||||
291 | } | - | ||||||||||||
292 | - | |||||||||||||
293 | memcpy (p, isaac->data.b + ISAAC_BYTES - inbytes, inbytes); | - | ||||||||||||
294 | p = char_p + inbytes; | - | ||||||||||||
295 | size -= inbytes; | - | ||||||||||||
296 | - | |||||||||||||
297 | /* If P is aligned, write to *P directly to avoid the overhead | - | ||||||||||||
298 | of copying from the buffer. */ | - | ||||||||||||
299 | if (ALIGNED_POINTER (p, isaac_word)) | - | ||||||||||||
300 | { | - | ||||||||||||
301 | isaac_word *wp = p; | - | ||||||||||||
302 | while (ISAAC_BYTES <= size)
| 669-1023 | ||||||||||||
303 | { | - | ||||||||||||
304 | isaac_refill (&isaac->state, wp); | - | ||||||||||||
305 | wp += ISAAC_WORDS; | - | ||||||||||||
306 | size -= ISAAC_BYTES; | - | ||||||||||||
307 | if (size == 0)
| 16-1007 | ||||||||||||
308 | { | - | ||||||||||||
309 | isaac->buffered = 0; | - | ||||||||||||
310 | return; executed 16 times by 1 test: return; Executed by:
| 16 | ||||||||||||
311 | } | - | ||||||||||||
312 | } executed 1007 times by 1 test: end of block Executed by:
| 1007 | ||||||||||||
313 | p = wp; | - | ||||||||||||
314 | } executed 669 times by 7 tests: end of block Executed by:
| 669 | ||||||||||||
315 | - | |||||||||||||
316 | isaac_refill (&isaac->state, isaac->data.w); | - | ||||||||||||
317 | inbytes = ISAAC_BYTES; | - | ||||||||||||
318 | } executed 669 times by 7 tests: end of block Executed by:
| 669 | ||||||||||||
319 | } never executed: end of block | 0 | ||||||||||||
320 | - | |||||||||||||
321 | - | |||||||||||||
322 | /* Consume random data from *S to generate a random buffer BUF of size | - | ||||||||||||
323 | SIZE. */ | - | ||||||||||||
324 | - | |||||||||||||
325 | void | - | ||||||||||||
326 | randread (struct randread_source *s, void *buf, size_t size) | - | ||||||||||||
327 | { | - | ||||||||||||
328 | if (s->source)
| 18-6252 | ||||||||||||
329 | readsource (s, buf, size); executed 18 times by 2 tests: readsource (s, buf, size); Executed by:
| 18 | ||||||||||||
330 | else | - | ||||||||||||
331 | readisaac (&s->buf.isaac, buf, size); executed 6252 times by 7 tests: readisaac (&s->buf.isaac, buf, size); Executed by:
| 6252 | ||||||||||||
332 | } | - | ||||||||||||
333 | - | |||||||||||||
334 | - | |||||||||||||
335 | /* Clear *S so that it no longer contains undelivered random data, and | - | ||||||||||||
336 | deallocate any system resources associated with *S. Return 0 if | - | ||||||||||||
337 | successful, a negative number (setting errno) if not (this is rare, | - | ||||||||||||
338 | but can occur in theory if there is an input error). */ | - | ||||||||||||
339 | - | |||||||||||||
340 | int | - | ||||||||||||
341 | randread_free (struct randread_source *s) | - | ||||||||||||
342 | { | - | ||||||||||||
343 | FILE *source = s->source; | - | ||||||||||||
344 | explicit_bzero (s, sizeof *s); | - | ||||||||||||
345 | free (s); | - | ||||||||||||
346 | return (source ? fclose (source) : 0); executed 635 times by 6 tests: return (source ? rpl_fclose (source) : 0); Executed by:
| 635 | ||||||||||||
347 | } | - | ||||||||||||
Source code | Switch to Preprocessed file |