|
1 /* crypto/rand/rand_egd.c */ |
|
2 /* Written by Ulf Moeller and Lutz Jaenicke for the OpenSSL project. */ |
|
3 /* ==================================================================== |
|
4 * Copyright (c) 1998-2000 The OpenSSL Project. All rights reserved. |
|
5 * |
|
6 * Redistribution and use in source and binary forms, with or without |
|
7 * modification, are permitted provided that the following conditions |
|
8 * are met: |
|
9 * |
|
10 * 1. Redistributions of source code must retain the above copyright |
|
11 * notice, this list of conditions and the following disclaimer. |
|
12 * |
|
13 * 2. Redistributions in binary form must reproduce the above copyright |
|
14 * notice, this list of conditions and the following disclaimer in |
|
15 * the documentation and/or other materials provided with the |
|
16 * distribution. |
|
17 * |
|
18 * 3. All advertising materials mentioning features or use of this |
|
19 * software must display the following acknowledgment: |
|
20 * "This product includes software developed by the OpenSSL Project |
|
21 * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" |
|
22 * |
|
23 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to |
|
24 * endorse or promote products derived from this software without |
|
25 * prior written permission. For written permission, please contact |
|
26 * openssl-core@openssl.org. |
|
27 * |
|
28 * 5. Products derived from this software may not be called "OpenSSL" |
|
29 * nor may "OpenSSL" appear in their names without prior written |
|
30 * permission of the OpenSSL Project. |
|
31 * |
|
32 * 6. Redistributions of any form whatsoever must retain the following |
|
33 * acknowledgment: |
|
34 * "This product includes software developed by the OpenSSL Project |
|
35 * for use in the OpenSSL Toolkit (http://www.openssl.org/)" |
|
36 * |
|
37 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY |
|
38 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
|
39 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
|
40 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR |
|
41 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
|
42 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
|
43 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
|
44 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
|
45 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, |
|
46 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
|
47 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED |
|
48 * OF THE POSSIBILITY OF SUCH DAMAGE. |
|
49 * ==================================================================== |
|
50 * |
|
51 * This product includes cryptographic software written by Eric Young |
|
52 * (eay@cryptsoft.com). This product includes software written by Tim |
|
53 * Hudson (tjh@cryptsoft.com). |
|
54 * |
|
55 */ |
|
56 /* |
|
57 © Portions copyright (c) 2006 Nokia Corporation. All rights reserved. |
|
58 */ |
|
59 #include <openssl/e_os2.h> |
|
60 #include <openssl/rand.h> |
|
61 #include <openssl/buffer.h> |
|
62 |
|
63 /* |
|
64 * Query the EGD <URL: http://www.lothar.com/tech/crypto/>. |
|
65 * |
|
66 * This module supplies three routines: |
|
67 * |
|
68 * RAND_query_egd_bytes(path, buf, bytes) |
|
69 * will actually query "bytes" bytes of entropy form the egd-socket located |
|
70 * at path and will write them to buf (if supplied) or will directly feed |
|
71 * it to RAND_seed() if buf==NULL. |
|
72 * The number of bytes is not limited by the maximum chunk size of EGD, |
|
73 * which is 255 bytes. If more than 255 bytes are wanted, several chunks |
|
74 * of entropy bytes are requested. The connection is left open until the |
|
75 * query is competed. |
|
76 * RAND_query_egd_bytes() returns with |
|
77 * -1 if an error occured during connection or communication. |
|
78 * num the number of bytes read from the EGD socket. This number is either |
|
79 * the number of bytes requested or smaller, if the EGD pool is |
|
80 * drained and the daemon signals that the pool is empty. |
|
81 * This routine does not touch any RAND_status(). This is necessary, since |
|
82 * PRNG functions may call it during initialization. |
|
83 * |
|
84 * RAND_egd_bytes(path, bytes) will query "bytes" bytes and have them |
|
85 * used to seed the PRNG. |
|
86 * RAND_egd_bytes() is a wrapper for RAND_query_egd_bytes() with buf=NULL. |
|
87 * Unlike RAND_query_egd_bytes(), RAND_status() is used to test the |
|
88 * seed status so that the return value can reflect the seed state: |
|
89 * -1 if an error occured during connection or communication _or_ |
|
90 * if the PRNG has still not received the required seeding. |
|
91 * num the number of bytes read from the EGD socket. This number is either |
|
92 * the number of bytes requested or smaller, if the EGD pool is |
|
93 * drained and the daemon signals that the pool is empty. |
|
94 * |
|
95 * RAND_egd(path) will query 255 bytes and use the bytes retreived to seed |
|
96 * the PRNG. |
|
97 * RAND_egd() is a wrapper for RAND_egd_bytes() with numbytes=255. |
|
98 */ |
|
99 /* |
|
100 © Portions copyright (c) 2006 Nokia Corporation. All rights reserved. |
|
101 */ |
|
102 |
|
103 #if defined(SYMBIAN)||defined(OPENSSL_SYS_WIN32) || defined(OPENSSL_SYS_VMS) || defined(OPENSSL_SYS_MSDOS) || defined(OPENSSL_SYS_VXWORKS) || defined(OPENSSL_SYS_NETWARE) || defined(OPENSSL_SYS_VOS) |
|
104 EXPORT_C int RAND_query_egd_bytes(const char *path, unsigned char *buf, int bytes) |
|
105 { |
|
106 return(-1); |
|
107 } |
|
108 EXPORT_C int RAND_egd(const char *path) |
|
109 { |
|
110 return(-1); |
|
111 } |
|
112 |
|
113 EXPORT_C int RAND_egd_bytes(const char *path,int bytes) |
|
114 { |
|
115 return(-1); |
|
116 } |
|
117 |
|
118 #else |
|
119 #include <openssl/opensslconf.h> |
|
120 #include OPENSSL_UNISTD |
|
121 #include <sys/types.h> |
|
122 #include <sys/socket.h> |
|
123 #ifndef NO_SYS_UN_H |
|
124 # ifdef OPENSSL_SYS_VXWORKS |
|
125 # include <streams/un.h> |
|
126 # else |
|
127 # include <sys/un.h> |
|
128 # endif |
|
129 #else |
|
130 struct sockaddr_un { |
|
131 short sun_family; /* AF_UNIX */ |
|
132 char sun_path[108]; /* path name (gag) */ |
|
133 }; |
|
134 #endif /* NO_SYS_UN_H */ |
|
135 #include <string.h> |
|
136 #include <errno.h> |
|
137 |
|
138 #ifndef offsetof |
|
139 # define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) |
|
140 #endif |
|
141 |
|
142 int RAND_query_egd_bytes(const char *path, unsigned char *buf, int bytes) |
|
143 { |
|
144 int ret = 0; |
|
145 struct sockaddr_un addr; |
|
146 int len, num, numbytes; |
|
147 int fd = -1; |
|
148 int success; |
|
149 unsigned char egdbuf[2], tempbuf[255], *retrievebuf; |
|
150 |
|
151 memset(&addr, 0, sizeof(addr)); |
|
152 addr.sun_family = AF_UNIX; |
|
153 if (strlen(path) >= sizeof(addr.sun_path)) |
|
154 return (-1); |
|
155 BUF_strlcpy(addr.sun_path,path,sizeof addr.sun_path); |
|
156 len = offsetof(struct sockaddr_un, sun_path) + strlen(path); |
|
157 fd = socket(AF_UNIX, SOCK_STREAM, 0); |
|
158 if (fd == -1) return (-1); |
|
159 success = 0; |
|
160 while (!success) |
|
161 { |
|
162 if (connect(fd, (struct sockaddr *)&addr, len) == 0) |
|
163 success = 1; |
|
164 else |
|
165 { |
|
166 switch (errno) |
|
167 { |
|
168 #ifdef EINTR |
|
169 case EINTR: |
|
170 #endif |
|
171 #ifdef EAGAIN |
|
172 case EAGAIN: |
|
173 #endif |
|
174 #ifdef EINPROGRESS |
|
175 case EINPROGRESS: |
|
176 #endif |
|
177 #ifdef EALREADY |
|
178 case EALREADY: |
|
179 #endif |
|
180 /* No error, try again */ |
|
181 break; |
|
182 #ifdef EISCONN |
|
183 case EISCONN: |
|
184 success = 1; |
|
185 break; |
|
186 #endif |
|
187 default: |
|
188 goto err; /* failure */ |
|
189 } |
|
190 } |
|
191 } |
|
192 |
|
193 while(bytes > 0) |
|
194 { |
|
195 egdbuf[0] = 1; |
|
196 egdbuf[1] = bytes < 255 ? bytes : 255; |
|
197 numbytes = 0; |
|
198 while (numbytes != 2) |
|
199 { |
|
200 num = write(fd, egdbuf + numbytes, 2 - numbytes); |
|
201 if (num >= 0) |
|
202 numbytes += num; |
|
203 else |
|
204 { |
|
205 switch (errno) |
|
206 { |
|
207 #ifdef EINTR |
|
208 case EINTR: |
|
209 #endif |
|
210 #ifdef EAGAIN |
|
211 case EAGAIN: |
|
212 #endif |
|
213 /* No error, try again */ |
|
214 break; |
|
215 default: |
|
216 ret = -1; |
|
217 goto err; /* failure */ |
|
218 } |
|
219 } |
|
220 } |
|
221 numbytes = 0; |
|
222 while (numbytes != 1) |
|
223 { |
|
224 num = read(fd, egdbuf, 1); |
|
225 if (num == 0) |
|
226 goto err; /* descriptor closed */ |
|
227 else if (num > 0) |
|
228 numbytes += num; |
|
229 else |
|
230 { |
|
231 switch (errno) |
|
232 { |
|
233 #ifdef EINTR |
|
234 case EINTR: |
|
235 #endif |
|
236 #ifdef EAGAIN |
|
237 case EAGAIN: |
|
238 #endif |
|
239 /* No error, try again */ |
|
240 break; |
|
241 default: |
|
242 ret = -1; |
|
243 goto err; /* failure */ |
|
244 } |
|
245 } |
|
246 } |
|
247 if(egdbuf[0] == 0) |
|
248 goto err; |
|
249 if (buf) |
|
250 retrievebuf = buf + ret; |
|
251 else |
|
252 retrievebuf = tempbuf; |
|
253 numbytes = 0; |
|
254 while (numbytes != egdbuf[0]) |
|
255 { |
|
256 num = read(fd, retrievebuf + numbytes, egdbuf[0] - numbytes); |
|
257 if (num == 0) |
|
258 goto err; /* descriptor closed */ |
|
259 else if (num > 0) |
|
260 numbytes += num; |
|
261 else |
|
262 { |
|
263 switch (errno) |
|
264 { |
|
265 #ifdef EINTR |
|
266 case EINTR: |
|
267 #endif |
|
268 #ifdef EAGAIN |
|
269 case EAGAIN: |
|
270 #endif |
|
271 /* No error, try again */ |
|
272 break; |
|
273 default: |
|
274 ret = -1; |
|
275 goto err; /* failure */ |
|
276 } |
|
277 } |
|
278 } |
|
279 ret += egdbuf[0]; |
|
280 bytes -= egdbuf[0]; |
|
281 if (!buf) |
|
282 RAND_seed(tempbuf, egdbuf[0]); |
|
283 } |
|
284 err: |
|
285 if (fd != -1) close(fd); |
|
286 return(ret); |
|
287 } |
|
288 |
|
289 |
|
290 int RAND_egd_bytes(const char *path, int bytes) |
|
291 { |
|
292 int num, ret = 0; |
|
293 |
|
294 num = RAND_query_egd_bytes(path, NULL, bytes); |
|
295 if (num < 1) goto err; |
|
296 if (RAND_status() == 1) |
|
297 ret = num; |
|
298 err: |
|
299 return(ret); |
|
300 } |
|
301 |
|
302 |
|
303 int RAND_egd(const char *path) |
|
304 { |
|
305 return (RAND_egd_bytes(path, 255)); |
|
306 } |
|
307 |
|
308 |
|
309 #endif |