LCOV - code coverage report
Current view: top level - src/interfaces/libpq - pg_strong_random.c (source / functions) Hit Total Coverage
Test: PostgreSQL Lines: 0 20 0.0 %
Date: 2017-09-29 15:12:54 Functions: 0 2 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*-------------------------------------------------------------------------
       2             :  *
       3             :  * pg_strong_random.c
       4             :  *    generate a cryptographically secure random number
       5             :  *
       6             :  * Our definition of "strong" is that it's suitable for generating random
       7             :  * salts and query cancellation keys, during authentication.
       8             :  *
       9             :  * Copyright (c) 1996-2017, PostgreSQL Global Development Group
      10             :  *
      11             :  * IDENTIFICATION
      12             :  *    src/port/pg_strong_random.c
      13             :  *
      14             :  *-------------------------------------------------------------------------
      15             :  */
      16             : 
      17             : #ifndef FRONTEND
      18             : #include "postgres.h"
      19             : #else
      20             : #include "postgres_fe.h"
      21             : #endif
      22             : 
      23             : #include <fcntl.h>
      24             : #include <unistd.h>
      25             : #include <sys/time.h>
      26             : 
      27             : #ifdef USE_OPENSSL
      28             : #include <openssl/rand.h>
      29             : #endif
      30             : #ifdef WIN32
      31             : #include <wincrypt.h>
      32             : #endif
      33             : 
      34             : #ifdef WIN32
      35             : /*
      36             :  * Cache a global crypto provider that only gets freed when the process
      37             :  * exits, in case we need random numbers more than once.
      38             :  */
      39             : static HCRYPTPROV hProvider = 0;
      40             : #endif
      41             : 
      42             : #if defined(USE_DEV_URANDOM)
      43             : /*
      44             :  * Read (random) bytes from a file.
      45             :  */
      46             : static bool
      47           0 : random_from_file(char *filename, void *buf, size_t len)
      48             : {
      49             :     int         f;
      50           0 :     char       *p = buf;
      51             :     ssize_t     res;
      52             : 
      53           0 :     f = open(filename, O_RDONLY, 0);
      54           0 :     if (f == -1)
      55           0 :         return false;
      56             : 
      57           0 :     while (len)
      58             :     {
      59           0 :         res = read(f, p, len);
      60           0 :         if (res <= 0)
      61             :         {
      62           0 :             if (errno == EINTR)
      63           0 :                 continue;       /* interrupted by signal, just retry */
      64             : 
      65           0 :             close(f);
      66           0 :             return false;
      67             :         }
      68             : 
      69           0 :         p += res;
      70           0 :         len -= res;
      71             :     }
      72             : 
      73           0 :     close(f);
      74           0 :     return true;
      75             : }
      76             : #endif
      77             : 
      78             : /*
      79             :  * pg_strong_random
      80             :  *
      81             :  * Generate requested number of random bytes. The returned bytes are
      82             :  * cryptographically secure, suitable for use e.g. in authentication.
      83             :  *
      84             :  * We rely on system facilities for actually generating the numbers.
      85             :  * We support a number of sources:
      86             :  *
      87             :  * 1. OpenSSL's RAND_bytes()
      88             :  * 2. Windows' CryptGenRandom() function
      89             :  * 3. /dev/urandom
      90             :  *
      91             :  * The configure script will choose which one to use, and set
      92             :  * a USE_*_RANDOM flag accordingly.
      93             :  *
      94             :  * Returns true on success, and false if none of the sources
      95             :  * were available. NB: It is important to check the return value!
      96             :  * Proceeding with key generation when no random data was available
      97             :  * would lead to predictable keys and security issues.
      98             :  */
      99             : bool
     100           0 : pg_strong_random(void *buf, size_t len)
     101             : {
     102             :     /*
     103             :      * When built with OpenSSL, use OpenSSL's RAND_bytes function.
     104             :      */
     105             : #if defined(USE_OPENSSL_RANDOM)
     106             :     if (RAND_bytes(buf, len) == 1)
     107             :         return true;
     108             :     return false;
     109             : 
     110             :     /*
     111             :      * Windows has CryptoAPI for strong cryptographic numbers.
     112             :      */
     113             : #elif defined(USE_WIN32_RANDOM)
     114             :     if (hProvider == 0)
     115             :     {
     116             :         if (!CryptAcquireContext(&hProvider,
     117             :                                  NULL,
     118             :                                  MS_DEF_PROV,
     119             :                                  PROV_RSA_FULL,
     120             :                                  CRYPT_VERIFYCONTEXT | CRYPT_SILENT))
     121             :         {
     122             :             /*
     123             :              * On failure, set back to 0 in case the value was for some reason
     124             :              * modified.
     125             :              */
     126             :             hProvider = 0;
     127             :         }
     128             :     }
     129             :     /* Re-check in case we just retrieved the provider */
     130             :     if (hProvider != 0)
     131             :     {
     132             :         if (CryptGenRandom(hProvider, len, buf))
     133             :             return true;
     134             :     }
     135             :     return false;
     136             : 
     137             :     /*
     138             :      * Read /dev/urandom ourselves.
     139             :      */
     140             : #elif defined(USE_DEV_URANDOM)
     141           0 :     if (random_from_file("/dev/urandom", buf, len))
     142           0 :         return true;
     143           0 :     return false;
     144             : 
     145             : #else
     146             :     /* The autoconf script should not have allowed this */
     147             : #error no source of random numbers configured
     148             : #endif
     149             : }

Generated by: LCOV version 1.11