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 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 (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 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 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