• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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