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