1 /* Copyright 1998 by the Massachusetts Institute of Technology.
2 * Copyright (C) 2007-2013 by Daniel Stenberg
3 *
4 * Permission to use, copy, modify, and distribute this
5 * software and its documentation for any purpose and without
6 * fee is hereby granted, provided that the above copyright
7 * notice appear in all copies and that both that copyright
8 * notice and this permission notice appear in supporting
9 * documentation, and that the name of M.I.T. not be used in
10 * advertising or publicity pertaining to distribution of the
11 * software without specific, written prior permission.
12 * M.I.T. makes no representations about the suitability of
13 * this software for any purpose. It is provided "as is"
14 * without express or implied warranty.
15 */
16
17 #include "ares_setup.h"
18 #include "ares.h"
19 #include "ares_private.h"
20 #include "ares_nowarn.h"
21 #include <stdlib.h>
22
23 typedef enum {
24 ARES_RAND_OS = 1, /* OS-provided such as RtlGenRandom or arc4random */
25 ARES_RAND_FILE = 2, /* OS file-backed random number generator */
26 ARES_RAND_RC4 = 3 /* Internal RC4 based PRNG */
27 } ares_rand_backend;
28
29 typedef struct ares_rand_rc4
30 {
31 unsigned char S[256];
32 size_t i;
33 size_t j;
34 } ares_rand_rc4;
35
36 struct ares_rand_state
37 {
38 ares_rand_backend type;
39 union {
40 FILE *rand_file;
41 ares_rand_rc4 rc4;
42 } state;
43 };
44
45
46 /* Define RtlGenRandom = SystemFunction036. This is in advapi32.dll. There is
47 * no need to dynamically load this, other software used widely does not.
48 * http://blogs.msdn.com/michael_howard/archive/2005/01/14/353379.aspx
49 * https://docs.microsoft.com/en-us/windows/win32/api/ntsecapi/nf-ntsecapi-rtlgenrandom
50 */
51 #ifdef _WIN32
52 BOOLEAN WINAPI SystemFunction036(PVOID RandomBuffer, ULONG RandomBufferLength);
53 # ifndef RtlGenRandom
54 # define RtlGenRandom(a,b) SystemFunction036(a,b)
55 # endif
56 #endif
57
58
59 #define ARES_RC4_KEY_LEN 32 /* 256 bits */
60
61 #ifdef _MSC_VER
62 typedef unsigned __int64 cares_u64;
63 #else
64 typedef unsigned long long cares_u64;
65 #endif
66
ares_u32_from_ptr(void * addr)67 static unsigned int ares_u32_from_ptr(void *addr)
68 {
69 if (sizeof(void *) == 8) {
70 return (unsigned int)((((cares_u64)addr >> 32) & 0xFFFFFFFF) | ((cares_u64)addr & 0xFFFFFFFF));
71 }
72 return (unsigned int)((size_t)addr & 0xFFFFFFFF);
73 }
74
75
76 /* initialize an rc4 key as the last possible fallback. */
ares_rc4_generate_key(ares_rand_rc4 * rc4_state,unsigned char * key,size_t key_len)77 static void ares_rc4_generate_key(ares_rand_rc4 *rc4_state, unsigned char *key, size_t key_len)
78 {
79 size_t i;
80 size_t len = 0;
81 unsigned int data;
82 struct timeval tv;
83
84 if (key_len != ARES_RC4_KEY_LEN)
85 return;
86
87 /* Randomness is hard to come by. Maybe the system randomizes heap and stack addresses.
88 * Maybe the current timestamp give us some randomness.
89 * Use rc4_state (heap), &i (stack), and ares__tvnow()
90 */
91 data = ares_u32_from_ptr(rc4_state);
92 memcpy(key + len, &data, sizeof(data));
93 len += sizeof(data);
94
95 data = ares_u32_from_ptr(&i);
96 memcpy(key + len, &data, sizeof(data));
97 len += sizeof(data);
98
99 tv = ares__tvnow();
100 data = (unsigned int)((tv.tv_sec | tv.tv_usec) & 0xFFFFFFFF);
101 memcpy(key + len, &data, sizeof(data));
102 len += sizeof(data);
103
104 srand(ares_u32_from_ptr(rc4_state) | ares_u32_from_ptr(&i) | (unsigned int)((tv.tv_sec | tv.tv_usec) & 0xFFFFFFFF));
105
106 for (i=len; i<key_len; i++) {
107 key[i]=(unsigned char)(rand() % 256); /* LCOV_EXCL_LINE */
108 }
109 }
110
111
ares_rc4_init(ares_rand_rc4 * rc4_state)112 static void ares_rc4_init(ares_rand_rc4 *rc4_state)
113 {
114 unsigned char key[ARES_RC4_KEY_LEN];
115 size_t i;
116 size_t j;
117
118 ares_rc4_generate_key(rc4_state, key, sizeof(key));
119
120 for (i = 0; i < sizeof(rc4_state->S); i++) {
121 rc4_state->S[i] = i & 0xFF;
122 }
123
124 for(i = 0, j = 0; i < 256; i++) {
125 j = (j + rc4_state->S[i] + key[i % sizeof(key)]) % 256;
126 ARES_SWAP_BYTE(&rc4_state->S[i], &rc4_state->S[j]);
127 }
128
129 rc4_state->i = 0;
130 rc4_state->j = 0;
131 }
132
133 /* Just outputs the key schedule, no need to XOR with any data since we have none */
ares_rc4_prng(ares_rand_rc4 * rc4_state,unsigned char * buf,size_t len)134 static void ares_rc4_prng(ares_rand_rc4 *rc4_state, unsigned char *buf, size_t len)
135 {
136 unsigned char *S = rc4_state->S;
137 size_t i = rc4_state->i;
138 size_t j = rc4_state->j;
139 size_t cnt;
140
141 for (cnt=0; cnt<len; cnt++) {
142 i = (i + 1) % 256;
143 j = (j + S[i]) % 256;
144
145 ARES_SWAP_BYTE(&S[i], &S[j]);
146 buf[cnt] = S[(S[i] + S[j]) % 256];
147 }
148
149 rc4_state->i = i;
150 rc4_state->j = j;
151 }
152
153
ares__init_rand_engine(ares_rand_state * state)154 static int ares__init_rand_engine(ares_rand_state *state)
155 {
156 memset(state, 0, sizeof(*state));
157
158 #if defined(HAVE_ARC4RANDOM_BUF) || defined(_WIN32)
159 state->type = ARES_RAND_OS;
160 return 1;
161 #elif defined(CARES_RANDOM_FILE)
162 state->type = ARES_RAND_FILE;
163 state->state.rand_file = fopen(CARES_RANDOM_FILE, "rb");
164 if (state->state.rand_file) {
165 setvbuf(state->state.rand_file, NULL, _IONBF, 0);
166 return 1;
167 }
168 /* Fall-Thru on failure to RC4 */
169 #endif
170
171 state->type = ARES_RAND_RC4;
172 ares_rc4_init(&state->state.rc4);
173
174 /* Currently cannot fail */
175 return 1;
176 }
177
178
ares__init_rand_state()179 ares_rand_state *ares__init_rand_state()
180 {
181 ares_rand_state *state = NULL;
182
183 state = ares_malloc(sizeof(*state));
184 if (!state)
185 return NULL;
186
187 if (!ares__init_rand_engine(state)) {
188 ares_free(state);
189 return NULL;
190 }
191
192 return state;
193 }
194
195
ares__clear_rand_state(ares_rand_state * state)196 static void ares__clear_rand_state(ares_rand_state *state)
197 {
198 if (!state)
199 return;
200
201 switch (state->type) {
202 case ARES_RAND_OS:
203 break;
204 case ARES_RAND_FILE:
205 fclose(state->state.rand_file);
206 break;
207 case ARES_RAND_RC4:
208 break;
209 }
210 }
211
212
ares__reinit_rand(ares_rand_state * state)213 static void ares__reinit_rand(ares_rand_state *state)
214 {
215 ares__clear_rand_state(state);
216 ares__init_rand_engine(state);
217 }
218
219
ares__destroy_rand_state(ares_rand_state * state)220 void ares__destroy_rand_state(ares_rand_state *state)
221 {
222 if (!state)
223 return;
224
225 ares__clear_rand_state(state);
226 ares_free(state);
227 }
228
229
ares__rand_bytes(ares_rand_state * state,unsigned char * buf,size_t len)230 static void ares__rand_bytes(ares_rand_state *state, unsigned char *buf, size_t len)
231 {
232
233 while (1) {
234 size_t bytes_read = 0;
235
236 switch (state->type) {
237 case ARES_RAND_OS:
238 #ifdef _WIN32
239 RtlGenRandom(buf, len);
240 return;
241 #elif defined(HAVE_ARC4RANDOM_BUF)
242 arc4random_buf(buf, len);
243 return;
244 #else
245 /* Shouldn't be possible to be here */
246 break;
247 #endif
248
249 case ARES_RAND_FILE:
250 while (1) {
251 size_t rv = fread(buf + bytes_read, 1, len - bytes_read, state->state.rand_file);
252 if (rv == 0)
253 break; /* critical error, will reinit rand state */
254
255 bytes_read += rv;
256 if (bytes_read == len)
257 return;
258 }
259 break;
260
261 case ARES_RAND_RC4:
262 ares_rc4_prng(&state->state.rc4, buf, len);
263 return;
264 }
265
266 /* If we didn't return before we got here, that means we had a critical rand
267 * failure and need to reinitialized */
268 ares__reinit_rand(state);
269 }
270 }
271
ares__generate_new_id(ares_rand_state * state)272 unsigned short ares__generate_new_id(ares_rand_state *state)
273 {
274 unsigned short r=0;
275
276 ares__rand_bytes(state, (unsigned char *)&r, sizeof(r));
277 return r;
278 }
279
280