source: trunk/server/source4/heimdal/lib/hcrypto/rand-egd.c

Last change on this file was 414, checked in by Herwig Bauernfeind, 15 years ago

Samba 3.5.0: Initial import

File size: 5.0 KB
Line 
1/*
2 * Copyright (c) 2007 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
4 * 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 the
15 * documentation and/or other materials provided with the distribution.
16 *
17 * 3. Neither the name of the Institute nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#include <config.h>
35
36#include <sys/types.h>
37#ifdef HAVE_SYS_UN_H
38#include <sys/un.h>
39#endif
40
41#include <stdio.h>
42#include <stdlib.h>
43#ifdef HAVE_UNISTD_H
44#include <unistd.h>
45#endif
46#include <assert.h>
47
48#include <rand.h>
49#include <randi.h>
50
51#include <roken.h>
52
53static const char *egd_path = "/var/run/egd-pool";
54
55#define MAX_EGD_DATA 255
56
57static int
58connect_egd(const char *path)
59{
60 struct sockaddr_un addr;
61 int fd;
62
63 memset(&addr, 0, sizeof(addr));
64
65 if (strlen(path) > sizeof(addr.sun_path))
66 return -1;
67
68 addr.sun_family = AF_UNIX;
69 strlcpy(addr.sun_path, path, sizeof(addr.sun_path));
70
71 fd = socket(AF_UNIX, SOCK_STREAM, 0);
72 if (fd < 0)
73 return -1;
74
75 rk_cloexec(fd);
76
77 if (connect(fd, (struct sockaddr *)&addr, sizeof(addr)) != 0) {
78 close(fd);
79 return -1;
80 }
81
82 return fd;
83}
84
85static int
86get_entropy(int fd, void *data, size_t len)
87{
88 unsigned char msg[2];
89
90 assert(len <= MAX_EGD_DATA);
91
92 msg[0] = 0x02; /* read blocking data */
93 msg[1] = len; /* wanted length */
94
95 if (net_write(fd, msg, sizeof(msg)) != sizeof(msg))
96 return 0;
97
98 if (net_read(fd, data, len) != len)
99 return 0;
100
101 return 1;
102}
103
104static int
105put_entropy(int fd, const void *data, size_t len)
106{
107 unsigned char msg[4];
108
109 assert (len <= MAX_EGD_DATA);
110
111 msg[0] = 0x03; /* write data */
112 msg[1] = 0; /* dummy */
113 msg[2] = 0; /* entropy */
114 msg[3] = len; /* length */
115
116 if (net_write(fd, msg, sizeof(msg)) != sizeof(msg))
117 return 0;
118 if (net_write(fd, data, len) != len)
119 return 0;
120
121 return 1;
122}
123
124/*
125 *
126 */
127
128static void
129egd_seed(const void *indata, int size)
130{
131 size_t len;
132 int fd, ret = 1;
133
134 fd = connect_egd(egd_path);
135 if (fd < 0)
136 return;
137
138 while(size) {
139 len = size;
140 if (len > MAX_EGD_DATA)
141 len = MAX_EGD_DATA;
142 ret = put_entropy(fd, indata, len);
143 if (ret != 1)
144 break;
145 indata = ((unsigned char *)indata) + len;
146 size -= len;
147 }
148 close(fd);
149}
150
151static int
152get_bytes(const char *path, unsigned char *outdata, int size)
153{
154 size_t len;
155 int fd, ret = 1;
156
157 if (path == NULL)
158 path = egd_path;
159
160 fd = connect_egd(path);
161 if (fd < 0)
162 return 0;
163
164 while(size) {
165 len = size;
166 if (len > MAX_EGD_DATA)
167 len = MAX_EGD_DATA;
168 ret = get_entropy(fd, outdata, len);
169 if (ret != 1)
170 break;
171 outdata += len;
172 size -= len;
173 }
174 close(fd);
175
176 return ret;
177}
178
179static int
180egd_bytes(unsigned char *outdata, int size)
181{
182 return get_bytes(NULL, outdata, size);
183}
184
185static void
186egd_cleanup(void)
187{
188}
189
190static void
191egd_add(const void *indata, int size, double entropi)
192{
193 egd_seed(indata, size);
194}
195
196static int
197egd_pseudorand(unsigned char *outdata, int size)
198{
199 return get_bytes(NULL, outdata, size);
200}
201
202static int
203egd_status(void)
204{
205 int fd;
206 fd = connect_egd(egd_path);
207 if (fd < 0)
208 return 0;
209 close(fd);
210 return 1;
211}
212
213const RAND_METHOD hc_rand_egd_method = {
214 egd_seed,
215 egd_bytes,
216 egd_cleanup,
217 egd_add,
218 egd_pseudorand,
219 egd_status
220};
221
222const RAND_METHOD *
223RAND_egd_method(void)
224{
225 return &hc_rand_egd_method;
226}
227
228
229int
230RAND_egd(const char *filename)
231{
232 return RAND_egd_bytes(filename, 128);
233}
234
235int
236RAND_egd_bytes(const char *filename, int size)
237{
238 void *data;
239 int ret;
240
241 if (size <= 0)
242 return 0;
243
244 data = malloc(size);
245 if (data == NULL)
246 return 0;
247
248 ret = get_bytes(filename, data, size);
249 if (ret != 1) {
250 free(data);
251 return ret;
252 }
253
254 RAND_seed(data, size);
255
256 memset(data, 0, size);
257 free(data);
258
259 return 1;
260}
Note: See TracBrowser for help on using the repository browser.