diff options
Diffstat (limited to 'entropy.c')
-rw-r--r-- | entropy.c | 99 |
1 files changed, 61 insertions, 38 deletions
@@ -35,7 +35,7 @@ | |||
35 | #include <openssl/rand.h> | 35 | #include <openssl/rand.h> |
36 | #include <openssl/sha.h> | 36 | #include <openssl/sha.h> |
37 | 37 | ||
38 | RCSID("$Id: entropy.c,v 1.14 2000/06/18 04:07:04 djm Exp $"); | 38 | RCSID("$Id: entropy.c,v 1.15 2000/06/26 03:01:33 djm Exp $"); |
39 | 39 | ||
40 | #ifndef offsetof | 40 | #ifndef offsetof |
41 | # define offsetof(type, member) ((size_t) &((type *)0)->member) | 41 | # define offsetof(type, member) ((size_t) &((type *)0)->member) |
@@ -66,64 +66,83 @@ RCSID("$Id: entropy.c,v 1.14 2000/06/18 04:07:04 djm Exp $"); | |||
66 | 66 | ||
67 | #ifdef EGD_SOCKET | 67 | #ifdef EGD_SOCKET |
68 | /* Collect entropy from EGD */ | 68 | /* Collect entropy from EGD */ |
69 | void get_random_bytes(unsigned char *buf, int len) | 69 | int get_random_bytes(unsigned char *buf, int len) |
70 | { | 70 | { |
71 | static int egd_socket = -1; | 71 | int fd; |
72 | int c; | 72 | char msg[2]; |
73 | char egd_message[2] = { 0x02, 0x00 }; | ||
74 | struct sockaddr_un addr; | 73 | struct sockaddr_un addr; |
75 | int addr_len; | 74 | int addr_len; |
76 | 75 | ||
77 | memset(&addr, '\0', sizeof(addr)); | 76 | /* Sanity checks */ |
78 | addr.sun_family = AF_UNIX; | ||
79 | |||
80 | /* FIXME: compile time check? */ | ||
81 | if (sizeof(EGD_SOCKET) > sizeof(addr.sun_path)) | 77 | if (sizeof(EGD_SOCKET) > sizeof(addr.sun_path)) |
82 | fatal("Random pool path is too long"); | 78 | fatal("Random pool path is too long"); |
83 | 79 | if (len > 255) | |
80 | fatal("Too many bytes to read from EGD"); | ||
81 | |||
82 | memset(&addr, '\0', sizeof(addr)); | ||
83 | addr.sun_family = AF_UNIX; | ||
84 | strlcpy(addr.sun_path, EGD_SOCKET, sizeof(addr.sun_path)); | 84 | strlcpy(addr.sun_path, EGD_SOCKET, sizeof(addr.sun_path)); |
85 | |||
86 | addr_len = offsetof(struct sockaddr_un, sun_path) + sizeof(EGD_SOCKET); | 85 | addr_len = offsetof(struct sockaddr_un, sun_path) + sizeof(EGD_SOCKET); |
87 | 86 | ||
88 | if (egd_socket == -1) { | 87 | fd = socket(AF_UNIX, SOCK_STREAM, 0); |
89 | egd_socket = socket(AF_UNIX, SOCK_STREAM, 0); | 88 | if (fd == -1) { |
90 | if (egd_socket == -1) | 89 | error("Couldn't create AF_UNIX socket: %s", strerror(errno)); |
91 | fatal("Couldn't create AF_UNIX socket: %s", strerror(errno)); | 90 | return(0); |
92 | if (connect(egd_socket, (struct sockaddr*)&addr, addr_len) == -1) | 91 | } |
93 | fatal("Couldn't connect to EGD socket \"%s\": %s", addr.sun_path, strerror(errno)); | 92 | |
94 | } | 93 | if (connect(fd, (struct sockaddr*)&addr, addr_len) == -1) { |
94 | error("Couldn't connect to EGD socket \"%s\": %s", | ||
95 | addr.sun_path, strerror(errno)); | ||
96 | close(fd); | ||
97 | return(0); | ||
98 | } | ||
95 | 99 | ||
96 | if (len > 255) | ||
97 | fatal("Too many bytes to read from EGD"); | ||
98 | |||
99 | /* Send blocking read request to EGD */ | 100 | /* Send blocking read request to EGD */ |
100 | egd_message[1] = len; | 101 | msg[0] = 0x02; |
102 | msg[1] = len; | ||
101 | 103 | ||
102 | c = atomicio(write, egd_socket, egd_message, sizeof(egd_message)); | 104 | if (atomicio(write, fd, msg, sizeof(msg)) != sizeof(msg)) { |
103 | if (c == -1) | 105 | error("Couldn't write to EGD socket \"%s\": %s", |
104 | fatal("Couldn't write to EGD socket \"%s\": %s", EGD_SOCKET, strerror(errno)); | 106 | EGD_SOCKET, strerror(errno)); |
107 | close(fd); | ||
108 | return(0); | ||
109 | } | ||
105 | 110 | ||
106 | c = atomicio(read, egd_socket, buf, len); | 111 | if (atomicio(read, fd, buf, len) != len) { |
107 | if (c <= 0) | 112 | error("Couldn't read from EGD socket \"%s\": %s", |
108 | fatal("Couldn't read from EGD socket \"%s\": %s", EGD_SOCKET, strerror(errno)); | 113 | EGD_SOCKET, strerror(errno)); |
114 | close(fd); | ||
115 | return(0); | ||
116 | } | ||
117 | |||
118 | close(fd); | ||
119 | |||
120 | return(1); | ||
109 | } | 121 | } |
110 | #else /* !EGD_SOCKET */ | 122 | #else /* !EGD_SOCKET */ |
111 | #ifdef RANDOM_POOL | 123 | #ifdef RANDOM_POOL |
112 | /* Collect entropy from /dev/urandom or pipe */ | 124 | /* Collect entropy from /dev/urandom or pipe */ |
113 | void get_random_bytes(unsigned char *buf, int len) | 125 | int get_random_bytes(unsigned char *buf, int len) |
114 | { | 126 | { |
115 | static int random_pool = -1; | 127 | int random_pool; |
116 | int c; | ||
117 | 128 | ||
129 | random_pool = open(RANDOM_POOL, O_RDONLY); | ||
118 | if (random_pool == -1) { | 130 | if (random_pool == -1) { |
119 | random_pool = open(RANDOM_POOL, O_RDONLY); | 131 | error("Couldn't open random pool \"%s\": %s", |
120 | if (random_pool == -1) | 132 | RANDOM_POOL, strerror(errno)); |
121 | fatal("Couldn't open random pool \"%s\": %s", RANDOM_POOL, strerror(errno)); | 133 | return(0); |
122 | } | 134 | } |
123 | 135 | ||
124 | c = atomicio(read, random_pool, buf, len); | 136 | if (atomicio(read, random_pool, buf, len) != len) { |
125 | if (c <= 0) | 137 | error("Couldn't read from random pool \"%s\": %s", |
126 | fatal("Couldn't read from random pool \"%s\": %s", RANDOM_POOL, strerror(errno)); | 138 | RANDOM_POOL, strerror(errno)); |
139 | close(random_pool); | ||
140 | return(0); | ||
141 | } | ||
142 | |||
143 | close(random_pool); | ||
144 | |||
145 | return(1); | ||
127 | } | 146 | } |
128 | #endif /* RANDOM_POOL */ | 147 | #endif /* RANDOM_POOL */ |
129 | #endif /* EGD_SOCKET */ | 148 | #endif /* EGD_SOCKET */ |
@@ -138,8 +157,12 @@ seed_rng(void) | |||
138 | char buf[32]; | 157 | char buf[32]; |
139 | 158 | ||
140 | debug("Seeding random number generator"); | 159 | debug("Seeding random number generator"); |
141 | get_random_bytes(buf, sizeof(buf)); | 160 | |
161 | if (!get_random_bytes(buf, sizeof(buf)) && !RAND_status()) | ||
162 | fatal("Entropy collection failed and entropy exhausted"); | ||
163 | |||
142 | RAND_add(buf, sizeof(buf), sizeof(buf)); | 164 | RAND_add(buf, sizeof(buf), sizeof(buf)); |
165 | |||
143 | memset(buf, '\0', sizeof(buf)); | 166 | memset(buf, '\0', sizeof(buf)); |
144 | } | 167 | } |
145 | 168 | ||