]>
Commit | Line | Data |
---|---|---|
0c1f3509 MG |
1 | #include <errno.h> |
2 | #include <fcntl.h> | |
3 | #include <limits.h> | |
4 | #include <stdint.h> | |
5 | #include <unistd.h> | |
6 | ||
7 | #include "warnp.h" | |
8 | ||
9 | #include "entropy.h" | |
10 | ||
11 | /** | |
12 | * XXX Portability | |
13 | * XXX We obtain random bytes from the operating system by opening | |
14 | * XXX /dev/urandom and reading them from that device; this works on | |
15 | * XXX modern UNIX-like operating systems but not on systems like | |
16 | * XXX win32 where there is no concept of /dev/urandom. | |
17 | */ | |
18 | ||
19 | /** | |
20 | * entropy_read(buf, buflen): | |
21 | * Fill the given buffer with random bytes provided by the operating system. | |
22 | */ | |
23 | int | |
24 | entropy_read(uint8_t * buf, size_t buflen) | |
25 | { | |
26 | int fd; | |
27 | ssize_t lenread; | |
28 | ||
29 | /* Sanity-check the buffer size. */ | |
30 | if (buflen > SSIZE_MAX) { | |
31 | warn0("Programmer error: " | |
32 | "Trying to read insane amount of random data: %zu", | |
33 | buflen); | |
34 | goto err0; | |
35 | } | |
36 | ||
37 | /* Open /dev/urandom. */ | |
38 | if ((fd = open("/dev/urandom", O_RDONLY)) == -1) { | |
39 | warnp("open(/dev/urandom)"); | |
40 | goto err0; | |
41 | } | |
42 | ||
43 | /* Read bytes until we have filled the buffer. */ | |
44 | while (buflen > 0) { | |
45 | if ((lenread = read(fd, buf, buflen)) == -1) { | |
46 | warnp("read(/dev/urandom)"); | |
47 | goto err1; | |
48 | } | |
49 | ||
50 | /* The random device should never EOF. */ | |
51 | if (lenread == 0) { | |
52 | warn0("EOF on /dev/urandom?"); | |
53 | goto err1; | |
54 | } | |
55 | ||
56 | /* We've filled a portion of the buffer. */ | |
57 | buf += (size_t)lenread; | |
58 | buflen -= (size_t)lenread; | |
59 | } | |
60 | ||
61 | /* Close the device. */ | |
62 | while (close(fd) == -1) { | |
63 | if (errno != EINTR) { | |
64 | warnp("close(/dev/urandom)"); | |
65 | goto err0; | |
66 | } | |
67 | } | |
68 | ||
69 | /* Success! */ | |
70 | return (0); | |
71 | ||
72 | err1: | |
73 | close(fd); | |
74 | err0: | |
75 | /* Failure! */ | |
76 | return (-1); | |
77 | } |