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