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));
 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 }