11 martin 1.3 // Permission is hereby granted, free of charge, to any person obtaining a
12 // copy of this software and associated documentation files (the "Software"),
13 // to deal in the Software without restriction, including without limitation
14 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
15 // and/or sell copies of the Software, and to permit persons to whom the
16 // Software is furnished to do so, subject to the following conditions:
|
23 martin 1.3 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
24 // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
25 // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
26 // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
27 // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
30 kumpf 1.2 */
31
32 #include "Random.h"
33 #include <stdlib.h>
34 #include <sys/types.h>
35 #include <sys/stat.h>
36 #include <sys/time.h>
37 #include <fcntl.h>
38 #include <unistd.h>
39 #include <errno.h>
40
41 /*
42 **==============================================================================
43 **
44 ** FillRandomBytes1()
45 **
46 ** Fills *data* with *size* random bytes using the high-quality random
47 ** number generator device (/dev/urandom).
48 **
49 **==============================================================================
50 */
51 kumpf 1.2
52 static int _fillRandomBytes1(unsigned char* data, size_t size)
53 {
54 size_t numErrors = 0;
55 const size_t MAX_ERRORS_TOLERATED = 20;
56
57 int fd = open("/dev/urandom", O_RDONLY | O_NONBLOCK);
58
59 if (fd < 0)
60 return -1;
61
62 while (size)
63 {
64 ssize_t n = read(fd, data, size);
65
66 if (n < 1)
67 {
68 if (++numErrors == MAX_ERRORS_TOLERATED)
69 break;
70
71 if (errno == EAGAIN)
72 kumpf 1.2 continue;
73
74 break;
75 }
76
77 size -= n;
78 data += n;
79 }
80
81 close(fd);
82 return size == 0 ? 0 : -1;
83 }
84
85 /*
86 **==============================================================================
87 **
88 ** FillRandomBytes2()
89 **
90 ** Fills *data* with *size* random bytes using the standard rand() function.
91 ** Note: this function uses srand(), which is generally not considered
92 ** "random" enough for security purposes but it is only used if
93 kumpf 1.2 ** FillRandomBytes1() fails.
94 **
95 **==============================================================================
96 */
97
98 static void _fillRandomBytes2(unsigned char* data, size_t size)
99 {
100 struct timeval tv;
101
102 /* Seed the random number generator. */
103
104 gettimeofday(&tv, 0);
105
106 /* Flawfinder: ignore */
107 srand(tv.tv_usec);
108
109 /* Fill data with random bytes. */
110
111 while (size--)
112 *data++ = rand();
113 }
114 kumpf 1.2
115 /*
116 **==============================================================================
117 **
118 ** FillRandomBytes()
119 **
120 **==============================================================================
121 */
122
123 void FillRandomBytes(unsigned char* data, size_t size)
124 {
125 if (_fillRandomBytes1(data, size) != 0)
126 _fillRandomBytes2(data, size);
127 }
128
129 /*
130 **==============================================================================
131 **
132 ** RandBytesToHexASCII()
133 **
134 ** Converts the bytes given by *data* to a hexidecimal sequence of ASCII
135 kumpf 1.2 ** characters. The *ascii* parameter must be twice size plus one (for the
136 ** null terminator).
137 **
138 **==============================================================================
139 */
140
141 void RandBytesToHexASCII(
142 const unsigned char* data,
143 size_t size,
144 char* ascii)
145 {
146 static char _hexDigits[] =
147 {
148 '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'
149 };
150 size_t i;
151 size_t j = 0;
152
153 for (i = 0; i < size; i++)
154 {
155 unsigned char hi = data[i] >> 4;
156 kumpf 1.2 unsigned char lo = 0x0F & data[i];
157 ascii[j++] = _hexDigits[hi];
158 ascii[j++] = _hexDigits[lo];
159 }
160
161 ascii[j] = '\0';
162 }
|