1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 *
21 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
22 * Use is subject to license terms.
23 */
24
25
26 /*
27 * Random number generator pseudo-driver
28 *
29 * This is a lightweight driver which calls in to the Kernel Cryptographic
30 * Framework to do the real work. Kernel modules should NOT depend on this
31 * driver for /dev/random kernel API.
32 *
33 * Applications may ask for 2 types of random bits:
34 * . High quality random by reading from /dev/random. The output is extracted
35 * only when a minimum amount of entropy is available.
36 * . Pseudo-random, by reading from /dev/urandom, that can be generated any
37 * time.
38 */
39
40 #include <sys/types.h>
41 #include <sys/errno.h>
42 #include <sys/stat.h>
43
44 #include <sys/file.h>
45 #include <sys/open.h>
46 #include <sys/poll.h>
47 #include <sys/uio.h>
48 #include <sys/cred.h>
49 #include <sys/modctl.h>
50 #include <sys/conf.h>
51 #include <sys/ddi.h>
52 #include <sys/sunddi.h>
53 #include <sys/random.h>
54 #include <sys/crypto/impl.h>
55
56 #define DEVRANDOM 0
57 #define DEVURANDOM 1
58
59 #define HASHSIZE 20 /* Assuming a SHA1 hash algorithm */
60 #define WRITEBUFSIZE 512 /* Size of buffer for write request */
61 #define MAXRETBYTES 1040 /* Max bytes returned per read. */
62 /* Must be a multiple of HASHSIZE */
63 static dev_info_t *rnd_dip;
64
65 static int rnd_open(dev_t *, int, int, cred_t *);
66 static int rnd_close(dev_t, int, int, cred_t *);
67 static int rnd_read(dev_t, struct uio *, cred_t *);
68 static int rnd_write(dev_t, struct uio *, cred_t *);
69 static int rnd_chpoll(dev_t, short, int, short *, struct pollhead **);
70 static int rnd_attach(dev_info_t *, ddi_attach_cmd_t);
71 static int rnd_detach(dev_info_t *, ddi_detach_cmd_t);
72 static int rnd_getinfo(dev_info_t *, ddi_info_cmd_t, void *, void **);
73
74 /* DDI declarations */
75 static struct cb_ops rnd_cb_ops = {
76 rnd_open, /* open */
77 rnd_close, /* close */
78 nodev, /* strategy */
79 nodev, /* print */
80 nodev, /* dump */
81 rnd_read, /* read */
82 rnd_write, /* write */
83 nodev, /* ioctl */
84 nodev, /* devmap */
85 nodev, /* mmap */
86 nodev, /* segmap */
87 rnd_chpoll, /* chpoll */
88 ddi_prop_op, /* prop_op */
89 NULL, /* streamtab */
90 (D_NEW | D_MP), /* cb_flag */
91 CB_REV, /* cb_rev */
92 nodev, /* aread */
93 nodev /* awrite */
94 };
95
96 static struct dev_ops rnd_ops = {
97 DEVO_REV, /* devo_rev, */
98 0, /* refcnt */
99 rnd_getinfo, /* get_dev_info */
100 nulldev, /* identify */
101 nulldev, /* probe */
102 rnd_attach, /* attach */
103 rnd_detach, /* detach */
104 nodev, /* reset */
105 &rnd_cb_ops, /* driver operations */
106 NULL, /* bus operations */
107 NULL, /* power */
108 ddi_quiesce_not_needed, /* quiesce */
109 };
110
111 /* Modlinkage */
112 static struct modldrv modldrv = {
113 &mod_driverops,
114 "random number device",
115 &rnd_ops
116 };
117
118 static struct modlinkage modlinkage = { MODREV_1, { &modldrv, NULL } };
119
120
121 /* DDI glue */
122
123 int
_init(void)124 _init(void)
125 {
126 return (mod_install(&modlinkage));
127 }
128
129 int
_fini(void)130 _fini(void)
131 {
132 return (mod_remove(&modlinkage));
133 }
134
135 int
_info(struct modinfo * modinfop)136 _info(struct modinfo *modinfop)
137 {
138 return (mod_info(&modlinkage, modinfop));
139 }
140
141 static int
rnd_attach(dev_info_t * dip,ddi_attach_cmd_t cmd)142 rnd_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
143 {
144 if (cmd != DDI_ATTACH)
145 return (DDI_FAILURE);
146
147 if (ddi_create_minor_node(dip, "random", S_IFCHR, DEVRANDOM,
148 DDI_PSEUDO, 0) == DDI_FAILURE) {
149 ddi_remove_minor_node(dip, NULL);
150 return (DDI_FAILURE);
151 }
152 if (ddi_create_minor_node(dip, "urandom", S_IFCHR, DEVURANDOM,
153 DDI_PSEUDO, 0) == DDI_FAILURE) {
154 ddi_remove_minor_node(dip, NULL);
155 return (DDI_FAILURE);
156 }
157
158 rnd_dip = dip;
159
160 return (DDI_SUCCESS);
161 }
162
163 static int
rnd_detach(dev_info_t * dip,ddi_detach_cmd_t cmd)164 rnd_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
165 {
166 if (cmd != DDI_DETACH)
167 return (DDI_FAILURE);
168
169 rnd_dip = NULL;
170 ddi_remove_minor_node(dip, NULL);
171
172 return (DDI_SUCCESS);
173 }
174
175 /*ARGSUSED*/
176 static int
rnd_getinfo(dev_info_t * dip,ddi_info_cmd_t infocmd,void * arg,void ** result)177 rnd_getinfo(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result)
178 {
179 int error;
180
181 switch (infocmd) {
182 case DDI_INFO_DEVT2DEVINFO:
183 *result = rnd_dip;
184 error = DDI_SUCCESS;
185 break;
186 case DDI_INFO_DEVT2INSTANCE:
187 *result = (void *)0;
188 error = DDI_SUCCESS;
189 break;
190 default:
191 error = DDI_FAILURE;
192 }
193 return (error);
194 }
195
196 /*ARGSUSED3*/
197 static int
rnd_open(dev_t * devp,int flag,int otyp,cred_t * credp)198 rnd_open(dev_t *devp, int flag, int otyp, cred_t *credp)
199 {
200 switch (getminor(*devp)) {
201 case DEVRANDOM:
202 if (!kcf_rngprov_check())
203 return (ENXIO);
204 break;
205 case DEVURANDOM:
206 break;
207 default:
208 return (ENXIO);
209 }
210 if (otyp != OTYP_CHR)
211 return (EINVAL);
212
213 if (flag & FEXCL)
214 return (EINVAL);
215 return (0);
216 }
217
218 /*ARGSUSED*/
219 static int
rnd_close(dev_t dev,int flag,int otyp,cred_t * credp)220 rnd_close(dev_t dev, int flag, int otyp, cred_t *credp)
221 {
222 return (0);
223 }
224
225 /*ARGSUSED2*/
226 static int
rnd_read(dev_t dev,struct uio * uiop,cred_t * credp)227 rnd_read(dev_t dev, struct uio *uiop, cred_t *credp)
228 {
229 size_t len;
230 minor_t devno;
231 int error = 0;
232 int nbytes = 0;
233 uint8_t random_bytes[2 * HASHSIZE];
234
235 devno = getminor(dev);
236
237 while (error == 0 && uiop->uio_resid > 0) {
238 len = min(sizeof (random_bytes), uiop->uio_resid);
239 switch (devno) {
240 case DEVRANDOM:
241 error = kcf_rnd_get_bytes(random_bytes, len,
242 uiop->uio_fmode & (FNDELAY|FNONBLOCK));
243 break;
244 case DEVURANDOM:
245 error = kcf_rnd_get_pseudo_bytes(random_bytes, len);
246 break;
247 default:
248 return (ENXIO);
249 }
250
251 if (error == 0) {
252 /*
253 * /dev/[u]random is not a seekable device. To prevent
254 * uio offset from growing and eventually exceeding
255 * the maximum, reset the offset here for every call.
256 */
257 uiop->uio_loffset = 0;
258 error = uiomove(random_bytes, len, UIO_READ, uiop);
259
260 nbytes += len;
261
262 if (devno == DEVRANDOM && nbytes >= MAXRETBYTES)
263 break;
264
265 } else if ((error == EAGAIN) && (nbytes > 0)) {
266 error = 0;
267 break;
268 }
269 }
270 return (error);
271 }
272
273 /*ARGSUSED*/
274 static int
rnd_write(dev_t dev,struct uio * uiop,cred_t * credp)275 rnd_write(dev_t dev, struct uio *uiop, cred_t *credp)
276 {
277 int error;
278 uint8_t buf[WRITEBUFSIZE];
279 size_t bytes;
280 minor_t devno;
281
282 devno = getminor(dev);
283
284 while (uiop->uio_resid > 0) {
285 bytes = min(sizeof (buf), uiop->uio_resid);
286
287 /* See comments in rnd_read() */
288 uiop->uio_loffset = 0;
289 if ((error = uiomove(buf, bytes, UIO_WRITE, uiop)) != 0)
290 return (error);
291
292 switch (devno) {
293 case DEVRANDOM:
294 if ((error = random_add_entropy(buf, bytes, 0)) != 0)
295 return (error);
296 break;
297 case DEVURANDOM:
298 if ((error = random_add_pseudo_entropy(buf, bytes,
299 0)) != 0)
300 return (error);
301 break;
302 default:
303 return (ENXIO);
304 }
305 }
306
307 return (0);
308 }
309
310 static struct pollhead urnd_pollhd;
311
312 /*
313 * poll(2) is supported as follows:
314 * . Only POLLIN, POLLOUT, and POLLRDNORM events are supported.
315 * . POLLOUT always succeeds.
316 * . POLLIN and POLLRDNORM from /dev/urandom always succeeds.
317 * . POLLIN and POLLRDNORM from /dev/random will block until a
318 * minimum amount of entropy is available.
319 */
320 static int
rnd_chpoll(dev_t dev,short events,int anyyet,short * reventsp,struct pollhead ** phpp)321 rnd_chpoll(dev_t dev, short events, int anyyet, short *reventsp,
322 struct pollhead **phpp)
323 {
324 switch (getminor(dev)) {
325 case DEVURANDOM:
326 *reventsp = events & (POLLOUT | POLLIN | POLLRDNORM);
327
328 /*
329 * A non NULL pollhead pointer should be returned in case
330 * user polls for 0 events.
331 */
332 if (*reventsp == 0 && !anyyet)
333 *phpp = &urnd_pollhd;
334
335 break;
336 case DEVRANDOM:
337 kcf_rnd_chpoll(events, anyyet, reventsp, phpp);
338 break;
339 default:
340 return (ENXIO);
341 }
342
343 return (0);
344 }
345