PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
pg_strong_random.c
Go to the documentation of this file.
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 random_from_file(char *filename, void *buf, size_t len)
48 {
49  int f;
50  char *p = buf;
51  ssize_t res;
52 
53  f = open(filename, O_RDONLY, 0);
54  if (f == -1)
55  return false;
56 
57  while (len)
58  {
59  res = read(f, p, len);
60  if (res <= 0)
61  {
62  if (errno == EINTR)
63  continue; /* interrupted by signal, just retry */
64 
65  close(f);
66  return false;
67  }
68 
69  p += res;
70  len -= res;
71  }
72 
73  close(f);
74  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 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  if (random_from_file("/dev/urandom", buf, len))
142  return true;
143  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 }
bool pg_strong_random(void *buf, size_t len)
static char * buf
Definition: pg_test_fsync.c:66
#define EINTR
Definition: win32.h:285
#define NULL
Definition: c.h:229
static char * filename
Definition: pg_dumpall.c:90
#define close(a)
Definition: win32.h:12
#define read(a, b, c)
Definition: win32.h:13