• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt/router/samba-3.5.8/source4/heimdal/lib/hcrypto/
1/*
2 * Copyright (c) 2006 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 <stdio.h>
37#include <stdlib.h>
38#include <rand.h>
39#include <heim_threads.h>
40
41#include <roken.h>
42
43#include "randi.h"
44
45static int random_fd = -1;
46static HEIMDAL_MUTEX random_mutex = HEIMDAL_MUTEX_INITIALIZER;
47
48/*
49 * Unix /dev/random
50 */
51
52static int
53get_device_fd(int flags)
54{
55    static const char *rnd_devices[] = {
56	"/dev/urandom",
57	"/dev/random",
58	"/dev/srandom",
59	"/dev/arandom",
60	NULL
61    };
62    const char **p;
63
64    for(p = rnd_devices; *p; p++) {
65	int fd = open(*p, flags | O_NDELAY);
66	if(fd >= 0) {
67	    rk_cloexec(fd);
68	    return fd;
69	}
70    }
71    return -1;
72}
73
74static void
75unix_seed(const void *indata, int size)
76{
77    int fd;
78
79    if (size <= 0)
80	return;
81
82    fd = get_device_fd(O_WRONLY);
83    if (fd < 0)
84	return;
85
86    write(fd, indata, size);
87    close(fd);
88
89}
90
91
92static int
93unix_bytes(unsigned char *outdata, int size)
94{
95    ssize_t count;
96    int once = 0;
97
98    if (size <= 0)
99	return 0;
100
101    HEIMDAL_MUTEX_lock(&random_mutex);
102    if (random_fd == -1) {
103    retry:
104	random_fd = get_device_fd(O_RDONLY);
105	if (random_fd < 0) {
106	    HEIMDAL_MUTEX_unlock(&random_mutex);
107	    return 0;
108	}
109    }
110
111    while (size > 0) {
112	HEIMDAL_MUTEX_unlock(&random_mutex);
113	count = read (random_fd, outdata, size);
114	HEIMDAL_MUTEX_lock(&random_mutex);
115	if (random_fd < 0) {
116	    if (errno == EINTR)
117		continue;
118	    else if (errno == EBADF && once++ == 0) {
119		close(random_fd);
120		random_fd = -1;
121		goto retry;
122	    }
123	    return 0;
124	} else if (count <= 0) {
125	    HEIMDAL_MUTEX_unlock(&random_mutex);
126	    return 0;
127	}
128	outdata += count;
129	size -= count;
130    }
131    HEIMDAL_MUTEX_unlock(&random_mutex);
132
133    return 1;
134}
135
136static void
137unix_cleanup(void)
138{
139}
140
141static void
142unix_add(const void *indata, int size, double entropi)
143{
144    unix_seed(indata, size);
145}
146
147static int
148unix_pseudorand(unsigned char *outdata, int size)
149{
150    return unix_bytes(outdata, size);
151}
152
153static int
154unix_status(void)
155{
156    int fd;
157
158    fd = get_device_fd(O_RDONLY);
159    if (fd < 0)
160	return 0;
161    close(fd);
162
163    return 1;
164}
165
166const RAND_METHOD hc_rand_unix_method = {
167    unix_seed,
168    unix_bytes,
169    unix_cleanup,
170    unix_add,
171    unix_pseudorand,
172    unix_status
173};
174
175const RAND_METHOD *
176RAND_unix_method(void)
177{
178    return &hc_rand_unix_method;
179}
180