LCOV - code coverage report
Current view: top level - basic - random-util.c (source / functions) Hit Total Coverage
Test: systemd test coverage Lines: 11 36 30.6 %
Date: 2015-07-29 18:47:03 Functions: 2 3 66.7 %

          Line data    Source code
       1             : /***
       2             :   This file is part of systemd.
       3             : 
       4             :   Copyright 2010 Lennart Poettering
       5             : 
       6             :   systemd is free software; you can redistribute it and/or modify it
       7             :   under the terms of the GNU Lesser General Public License as published by
       8             :   the Free Software Foundation; either version 2.1 of the License, or
       9             :   (at your option) any later version.
      10             : 
      11             :   systemd is distributed in the hope that it will be useful, but
      12             :   WITHOUT ANY WARRANTY; without even the implied warranty of
      13             :   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
      14             :   Lesser General Public License for more details.
      15             : 
      16             :   You should have received a copy of the GNU Lesser General Public License
      17             :   along with systemd; If not, see <http://www.gnu.org/licenses/>.
      18             : ***/
      19             : 
      20             : #include <stdint.h>
      21             : #include <errno.h>
      22             : #include <sys/types.h>
      23             : #include <sys/stat.h>
      24             : #include <fcntl.h>
      25             : #include <time.h>
      26             : #ifdef HAVE_SYS_AUXV_H
      27             : #include <sys/auxv.h>
      28             : #endif
      29             : #include <linux/random.h>
      30             : 
      31             : #include "random-util.h"
      32             : #include "time-util.h"
      33             : #include "missing.h"
      34             : #include "util.h"
      35             : 
      36        1038 : int dev_urandom(void *p, size_t n) {
      37             :         static int have_syscall = -1;
      38             : 
      39        2076 :         _cleanup_close_ int fd = -1;
      40             :         int r;
      41             : 
      42             :         /* Gathers some randomness from the kernel. This call will
      43             :          * never block, and will always return some data from the
      44             :          * kernel, regardless if the random pool is fully initialized
      45             :          * or not. It thus makes no guarantee for the quality of the
      46             :          * returned entropy, but is good enough for or usual usecases
      47             :          * of seeding the hash functions for hashtable */
      48             : 
      49             :         /* Use the getrandom() syscall unless we know we don't have
      50             :          * it, or when the requested size is too large for it. */
      51        1038 :         if (have_syscall != 0 || (size_t) (int) n != n) {
      52        1038 :                 r = getrandom(p, n, GRND_NONBLOCK);
      53        1038 :                 if (r == (int) n) {
      54        1038 :                         have_syscall = true;
      55        1038 :                         return 0;
      56             :                 }
      57             : 
      58           0 :                 if (r < 0) {
      59           0 :                         if (errno == ENOSYS)
      60             :                                 /* we lack the syscall, continue with
      61             :                                  * reading from /dev/urandom */
      62           0 :                                 have_syscall = false;
      63           0 :                         else if (errno == EAGAIN)
      64             :                                 /* not enough entropy for now. Let's
      65             :                                  * remember to use the syscall the
      66             :                                  * next time, again, but also read
      67             :                                  * from /dev/urandom for now, which
      68             :                                  * doesn't care about the current
      69             :                                  * amount of entropy.  */
      70           0 :                                 have_syscall = true;
      71             :                         else
      72           0 :                                 return -errno;
      73             :                 } else
      74             :                         /* too short read? */
      75           0 :                         return -ENODATA;
      76             :         }
      77             : 
      78           0 :         fd = open("/dev/urandom", O_RDONLY|O_CLOEXEC|O_NOCTTY);
      79           0 :         if (fd < 0)
      80           0 :                 return errno == ENOENT ? -ENOSYS : -errno;
      81             : 
      82           0 :         return loop_read_exact(fd, p, n, true);
      83             : }
      84             : 
      85           0 : void initialize_srand(void) {
      86             :         static bool srand_called = false;
      87             :         unsigned x;
      88             : #ifdef HAVE_SYS_AUXV_H
      89             :         void *auxv;
      90             : #endif
      91             : 
      92           0 :         if (srand_called)
      93           0 :                 return;
      94             : 
      95           0 :         x = 0;
      96             : 
      97             : #ifdef HAVE_SYS_AUXV_H
      98             :         /* The kernel provides us with a bit of entropy in auxv, so
      99             :          * let's try to make use of that to seed the pseudo-random
     100             :          * generator. It's better than nothing... */
     101             : 
     102           0 :         auxv = (void*) getauxval(AT_RANDOM);
     103           0 :         if (auxv)
     104           0 :                 x ^= *(unsigned*) auxv;
     105             : #endif
     106             : 
     107           0 :         x ^= (unsigned) now(CLOCK_REALTIME);
     108           0 :         x ^= (unsigned) gettid();
     109             : 
     110           0 :         srand(x);
     111           0 :         srand_called = true;
     112             : }
     113             : 
     114        1011 : void random_bytes(void *p, size_t n) {
     115             :         uint8_t *q;
     116             :         int r;
     117             : 
     118        1011 :         r = dev_urandom(p, n);
     119        1011 :         if (r >= 0)
     120        1011 :                 return;
     121             : 
     122             :         /* If some idiot made /dev/urandom unavailable to us, he'll
     123             :          * get a PRNG instead. */
     124             : 
     125           0 :         initialize_srand();
     126             : 
     127           0 :         for (q = p; q < (uint8_t*) p + n; q ++)
     128           0 :                 *q = rand();
     129             : }

Generated by: LCOV version 1.11