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.
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.
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]
21 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
22 * Use is subject to license terms.
24 * Copyright 2016 Joyent, Inc.
29 * Random number generator pseudo-driver
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.
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
42 #include <sys/types.h>
43 #include <sys/errno.h>
51 #include <sys/modctl.h>
54 #include <sys/sunddi.h>
55 #include <sys/random.h>
56 #include <sys/crypto/impl.h>
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
;
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 **);
76 /* DDI declarations */
77 static struct cb_ops rnd_cb_ops
= {
79 rnd_close
, /* close */
84 rnd_write
, /* write */
89 rnd_chpoll
, /* chpoll */
90 ddi_prop_op
, /* prop_op */
92 (D_NEW
| D_MP
), /* cb_flag */
98 static struct dev_ops rnd_ops
= {
99 DEVO_REV
, /* devo_rev, */
101 rnd_getinfo
, /* get_dev_info */
102 nulldev
, /* identify */
104 rnd_attach
, /* attach */
105 rnd_detach
, /* detach */
107 &rnd_cb_ops
, /* driver operations */
108 NULL
, /* bus operations */
110 ddi_quiesce_not_needed
, /* quiesce */
114 static struct modldrv modldrv
= {
116 "random number device",
120 static struct modlinkage modlinkage
= { MODREV_1
, { &modldrv
, NULL
} };
128 return (mod_install(&modlinkage
));
134 return (mod_remove(&modlinkage
));
138 _info(struct modinfo
*modinfop
)
140 return (mod_info(&modlinkage
, modinfop
));
144 rnd_attach(dev_info_t
*dip
, ddi_attach_cmd_t cmd
)
146 if (cmd
!= DDI_ATTACH
)
147 return (DDI_FAILURE
);
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
);
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
);
162 return (DDI_SUCCESS
);
166 rnd_detach(dev_info_t
*dip
, ddi_detach_cmd_t cmd
)
168 if (cmd
!= DDI_DETACH
)
169 return (DDI_FAILURE
);
172 ddi_remove_minor_node(dip
, NULL
);
174 return (DDI_SUCCESS
);
179 rnd_getinfo(dev_info_t
*dip
, ddi_info_cmd_t infocmd
, void *arg
, void **result
)
184 case DDI_INFO_DEVT2DEVINFO
:
188 case DDI_INFO_DEVT2INSTANCE
:
200 rnd_open(dev_t
*devp
, int flag
, int otyp
, cred_t
*credp
)
202 switch (getminor(*devp
)) {
204 if (!kcf_rngprov_check())
212 if (otyp
!= OTYP_CHR
)
222 rnd_close(dev_t dev
, int flag
, int otyp
, cred_t
*credp
)
229 rnd_read(dev_t dev
, struct uio
*uiop
, cred_t
*credp
)
235 uint8_t random_bytes
[2 * HASHSIZE
];
237 devno
= getminor(dev
);
239 while (error
== 0 && uiop
->uio_resid
> 0) {
240 len
= min(sizeof (random_bytes
), uiop
->uio_resid
);
243 error
= kcf_rnd_get_bytes(random_bytes
, len
,
244 uiop
->uio_fmode
& (FNDELAY
|FNONBLOCK
));
247 error
= kcf_rnd_get_pseudo_bytes(random_bytes
, len
);
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.
259 uiop
->uio_loffset
= 0;
260 error
= uiomove(random_bytes
, len
, UIO_READ
, uiop
);
264 if (devno
== DEVRANDOM
&& nbytes
>= MAXRETBYTES
)
267 } else if ((error
== EAGAIN
) && (nbytes
> 0)) {
277 rnd_write(dev_t dev
, struct uio
*uiop
, cred_t
*credp
)
280 uint8_t buf
[WRITEBUFSIZE
];
284 devno
= getminor(dev
);
286 while (uiop
->uio_resid
> 0) {
287 bytes
= min(sizeof (buf
), uiop
->uio_resid
);
289 /* See comments in rnd_read() */
290 uiop
->uio_loffset
= 0;
291 if ((error
= uiomove(buf
, bytes
, UIO_WRITE
, uiop
)) != 0)
294 if (crgetzone(credp
) != global_zone
)
299 if ((error
= random_add_entropy(buf
, bytes
, 0)) != 0)
303 if ((error
= random_add_pseudo_entropy(buf
, bytes
,
315 static struct pollhead urnd_pollhd
;
318 * poll(2) is supported as follows:
319 * . Only POLLIN, POLLOUT, and POLLRDNORM events are supported.
320 * . POLLOUT always succeeds.
321 * . POLLIN and POLLRDNORM from /dev/urandom always succeeds.
322 * . POLLIN and POLLRDNORM from /dev/random will block until a
323 * minimum amount of entropy is available.
326 rnd_chpoll(dev_t dev
, short events
, int anyyet
, short *reventsp
,
327 struct pollhead
**phpp
)
329 switch (getminor(dev
)) {
331 *reventsp
= events
& (POLLOUT
| POLLIN
| POLLRDNORM
);
334 * A non NULL pollhead pointer should be returned in case
335 * user polls for 0 events.
337 if (*reventsp
== 0 && !anyyet
)
338 *phpp
= &urnd_pollhd
;
342 kcf_rnd_chpoll(events
, anyyet
, reventsp
, phpp
);