xref: /illumos-gate/usr/src/uts/common/io/random.c (revision f808c858fa61e7769218966759510a8b1190dfcf)
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 2006 Sun Microsystems, Inc.  All rights reserved.
22  * Use is subject to license terms.
23  */
24 
25 #pragma ident	"%Z%%M%	%I%	%E% SMI"
26 
27 /*
28  * Random number generator pseudo-driver
29  *
30  * This is a lightweight driver which calls in to the Kernel Cryptographic
31  * Framework to do the real work. Kernel modules should NOT depend on this
32  * driver for /dev/random kernel API.
33  *
34  * Applications may ask for 2 types of random bits:
35  * . High quality random by reading from /dev/random. The output is extracted
36  *   only when a minimum amount of entropy is available.
37  * . Pseudo-random, by reading from /dev/urandom, that can be generated any
38  *   time.
39  */
40 
41 #include <sys/types.h>
42 #include <sys/errno.h>
43 #include <sys/stat.h>
44 
45 #include <sys/file.h>
46 #include <sys/open.h>
47 #include <sys/poll.h>
48 #include <sys/uio.h>
49 #include <sys/cred.h>
50 #include <sys/modctl.h>
51 #include <sys/conf.h>
52 #include <sys/ddi.h>
53 #include <sys/sunddi.h>
54 #include <sys/random.h>
55 #include <sys/crypto/impl.h>
56 
57 #define	DEVRANDOM		0
58 #define	DEVURANDOM		1
59 
60 #define	HASHSIZE		20	/* Assuming a SHA1 hash algorithm */
61 #define	WRITEBUFSIZE		512	/* Size of buffer for write request */
62 #define	MAXRETBYTES		1040	/* Max bytes returned per read. */
63 					/* Must be a multiple of HASHSIZE */
64 static dev_info_t *rnd_dip;
65 
66 static int rnd_open(dev_t *, int, int, cred_t *);
67 static int rnd_close(dev_t, int, int, cred_t *);
68 static int rnd_read(dev_t, struct uio *, cred_t *);
69 static int rnd_write(dev_t, struct uio *, cred_t *);
70 static int rnd_chpoll(dev_t, short, int, short *, struct pollhead **);
71 static int rnd_attach(dev_info_t *, ddi_attach_cmd_t);
72 static int rnd_detach(dev_info_t *, ddi_detach_cmd_t);
73 static int rnd_getinfo(dev_info_t *, ddi_info_cmd_t, void *, void **);
74 
75 /* DDI declarations */
76 static struct cb_ops rnd_cb_ops = {
77 	rnd_open,		/* open */
78 	rnd_close,		/* close */
79 	nodev,			/* strategy */
80 	nodev,			/* print */
81 	nodev,			/* dump */
82 	rnd_read,		/* read */
83 	rnd_write,		/* write */
84 	nodev,			/* ioctl */
85 	nodev,			/* devmap */
86 	nodev,			/* mmap */
87 	nodev,			/* segmap */
88 	rnd_chpoll,		/* chpoll */
89 	ddi_prop_op,		/* prop_op */
90 	NULL,			/* streamtab  */
91 	(D_NEW | D_MP), 	/* cb_flag */
92 	CB_REV,			/* cb_rev */
93 	nodev,			/* aread */
94 	nodev			/* awrite */
95 };
96 
97 static struct dev_ops rnd_ops = {
98 	DEVO_REV,		/* devo_rev, */
99 	0,			/* refcnt  */
100 	rnd_getinfo,		/* get_dev_info */
101 	nulldev,		/* identify */
102 	nulldev,		/* probe */
103 	rnd_attach,		/* attach */
104 	rnd_detach,		/* detach */
105 	nodev,			/* reset */
106 	&rnd_cb_ops,		/* driver operations */
107 	NULL,			/* bus operations */
108 	NULL			/* power */
109 };
110 
111 /* Modlinkage */
112 static struct modldrv modldrv = {
113 	&mod_driverops,
114 	"random number device v%I%",
115 	&rnd_ops
116 };
117 
118 static struct modlinkage modlinkage = {	MODREV_1, { &modldrv, NULL } };
119 
120 
121 /* DDI glue */
122 
123 int
124 _init(void)
125 {
126 	return (mod_install(&modlinkage));
127 }
128 
129 int
130 _fini(void)
131 {
132 	return (mod_remove(&modlinkage));
133 }
134 
135 int
136 _info(struct modinfo *modinfop)
137 {
138 	return (mod_info(&modlinkage, modinfop));
139 }
140 
141 static int
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
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
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
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
220 rnd_close(dev_t dev, int flag, int otyp, cred_t *credp)
221 {
222 	return (0);
223 }
224 
225 /*ARGSUSED2*/
226 static int
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), B_TRUE);
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 (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
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 /*
311  * poll(2) is supported as follows:
312  * . Only POLLIN, POLLOUT, and POLLRDNORM events are valid.
313  * . POLLOUT always succeeds.
314  * . POLLIN and POLLRDNORM from /dev/urandom always succeeds.
315  * . POLLIN and POLLRDNORM from /dev/random will block until a
316  *   minimum amount of entropy is available.
317  */
318 static int
319 rnd_chpoll(dev_t dev, short events, int anyyet, short *reventsp,
320 	struct pollhead **phpp)
321 {
322 	switch (getminor(dev)) {
323 	case DEVURANDOM:
324 		*reventsp = events & (POLLOUT | POLLIN | POLLRDNORM);
325 
326 		/* We're being polled for non-supported events */
327 		if (*reventsp == 0 && !anyyet)
328 			return (EINVAL);
329 
330 		break;
331 	case DEVRANDOM:
332 		*reventsp = events & POLLOUT;
333 
334 		/* Either POLLOUT only or unsupported event */
335 		if ((events & (POLLIN | POLLRDNORM)) == 0) {
336 			if (*reventsp == 0 && !anyyet)
337 				return (EINVAL);
338 			break;
339 		}
340 
341 		kcf_rnd_chpoll(anyyet, reventsp, phpp);
342 		break;
343 	default:
344 		return (ENXIO);
345 	}
346 
347 	return (0);
348 }
349