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