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