• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src/router/samba-3.5.8/source4/heimdal/lib/hcrypto/
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}
261