32
32
# include <errno.h>
33
33
# include <fcntl.h>
34
34
# include <unistd.h>
36
# define GENERIC_RANDOM_DEVICE "/dev/urandom"
37
39
#include "vmware.h"
38
40
#include "random.h"
40
#define ESX_RANDOM_DEVICE "/vmfs/devices/char/vmkdriver/urandom"
41
#define GENERIC_RANDOM_DEVICE "/dev/urandom"
45
45
*-----------------------------------------------------------------------------
49
49
* Generate 'size' bytes of cryptographically strong random bits in
50
* 'buffer'. Use this function when you need non-predictable random
51
* bits, typically in security applications. Use Random_Quick below
61
56
*-----------------------------------------------------------------------------
65
Random_Crypto(unsigned int size, // IN:
60
RandomBytesWin32(unsigned int size, // IN:
71
65
if (CryptAcquireContext(&csp, NULL, NULL, PROV_RSA_FULL,
72
66
CRYPT_VERIFYCONTEXT) == FALSE) {
73
Log("%s: CryptAcquireContext failed %d\n", __FUNCTION__,
78
70
if (CryptGenRandom(csp, size, buffer) == FALSE) {
79
71
CryptReleaseContext(csp, 0);
80
Log("%s: CryptGenRandom failed %d\n", __FUNCTION__, GetLastError());
85
75
if (CryptReleaseContext(csp, 0) == FALSE) {
86
Log("%s: CryptReleaseContext failed %d\n", __FUNCTION__,
95
* We use /dev/urandom and not /dev/random because it is good enough and
96
* because it cannot block. --hpreg
98
* Bug 352496: On ESX, /dev/urandom is proxied into COS, and hence is
99
* expensive. The VMkernel RNG is available through VMFS and is not
100
* proxied. So we use that instead.
103
#if defined(VMX86_SERVER)
105
* ESX: attempt to use the wonderful random device.
108
fd = open(ESX_RANDOM_DEVICE, O_RDONLY);
110
#if defined(VMX86_DEVEL)
112
* On developer builds, attempt to fall back to the generic random
113
* device, even if it is much slower. This has a nice side-effect -
114
* some things built for ESX will actually work in a Linux hosted
119
Log("%s: open of %s failed, attempting to use %s\n", __FUNCTION__,
120
ESX_RANDOM_DEVICE, GENERIC_RANDOM_DEVICE);
122
fd = open(GENERIC_RANDOM_DEVICE, O_RDONLY);
126
fd = open(GENERIC_RANDOM_DEVICE, O_RDONLY);
130
Log("%s: Failed to open random device: %d\n", __FUNCTION__, errno);
83
*-----------------------------------------------------------------------------
87
* Generate 'size' bytes of cryptographically strong random bits in
94
*-----------------------------------------------------------------------------
98
RandomBytesPosix(const char *name, // IN:
99
unsigned int size, // IN:
100
void *buffer) // OUT:
102
int fd = open(name, O_RDONLY);
135
108
/* Although /dev/urandom does not block, it can return short reads. */
136
110
while (size > 0) {
137
111
ssize_t bytesRead = read(fd, buffer, size);
139
if (bytesRead == 0 || (bytesRead == -1 && errno != EINTR)) {
113
if ((bytesRead == 0) || ((bytesRead == -1) && (errno != EINTR))) {
143
Log("%s: Short read: %d\n", __FUNCTION__, error);
147
119
if (bytesRead > 0) {
148
120
size -= bytesRead;
149
121
buffer = ((uint8 *) buffer) + bytesRead;
153
125
if (close(fd) == -1) {
154
Log("%s: Failed to close: %d\n", __FUNCTION__, errno);
135
*-----------------------------------------------------------------------------
139
* Generate 'size' bytes of cryptographically strong random bits in
140
* 'buffer'. Use this function when you need non-predictable random
141
* bits, typically in security applications, where the bits are generated
142
* external to the application.
144
* DO NOT USE THIS FUNCTION UNLESS YOU HAVE AN ABSOLUTE, EXPLICIT
145
* NEED FOR CRYPTOGRAPHICALLY VALID RANDOM NUMBERS.
154
*-----------------------------------------------------------------------------
158
Random_Crypto(unsigned int size, // IN:
159
void *buffer) // OUT:
162
return RandomBytesWin32(size, buffer);
165
* We use /dev/urandom and not /dev/random because it is good enough and
166
* because it cannot block. --hpreg
169
return RandomBytesPosix(GENERIC_RANDOM_DEVICE, size, buffer);