1 /*************************************************************************** 2 * _ _ ____ _ 3 * Project ___| | | | _ \| | 4 * / __| | | | |_) | | 5 * | (__| |_| | _ <| |___ 6 * \___|\___/|_| \_\_____| 7 * 8 * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al. 9 * 10 * This software is licensed as described in the file COPYING, which 11 * you should have received as part of this distribution. The terms 12 * are also available at https://curl.haxx.se/docs/copyright.html. 13 * 14 * You may opt to use, copy, modify, merge, publish, distribute and/or sell 15 * copies of the Software, and permit persons to whom the Software is 16 * furnished to do so, under the terms of the COPYING file. 17 * 18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 19 * KIND, either express or implied. 20 * 21 ***************************************************************************/ 22 23 #include "curl_setup.h" 24 25 #ifdef HAVE_FCNTL_H 26 #include <fcntl.h> 27 #endif 28 29 #include <curl/curl.h> 30 #include "vtls/vtls.h" 31 #include "sendf.h" 32 #include "rand.h" 33 34 /* The last 3 #include files should be in this order */ 35 #include "curl_printf.h" 36 #include "curl_memory.h" 37 #include "memdebug.h" 38 39 static CURLcode randit(struct Curl_easy *data, unsigned int *rnd) 40 { 41 unsigned int r; 42 CURLcode result = CURLE_OK; 43 static unsigned int randseed; 44 static bool seeded = FALSE; 45 46 #ifdef CURLDEBUG 47 char *force_entropy = getenv("CURL_ENTROPY"); 48 if(force_entropy) { 49 if(!seeded) { 50 unsigned int seed = 0; 51 size_t elen = strlen(force_entropy); 52 size_t clen = sizeof(seed); 53 size_t min = elen < clen ? elen : clen; 54 memcpy((char *)&seed, force_entropy, min); 55 randseed = ntohl(seed); 56 seeded = TRUE; 57 } 58 else 59 randseed++; 60 *rnd = randseed; 61 return CURLE_OK; 62 } 63 #endif 64 65 /* data may be NULL! */ 66 result = Curl_ssl_random(data, (unsigned char *)rnd, sizeof(*rnd)); 67 if(result != CURLE_NOT_BUILT_IN) 68 /* only if there is no random function in the TLS backend do the non crypto 69 version, otherwise return result */ 70 return result; 71 72 /* ---- non-cryptographic version following ---- */ 73 74 #ifdef RANDOM_FILE 75 if(!seeded) { 76 /* if there's a random file to read a seed from, use it */ 77 int fd = open(RANDOM_FILE, O_RDONLY); 78 if(fd > -1) { 79 /* read random data into the randseed variable */ 80 ssize_t nread = read(fd, &randseed, sizeof(randseed)); 81 if(nread == sizeof(randseed)) 82 seeded = TRUE; 83 close(fd); 84 } 85 } 86 #endif 87 88 if(!seeded) { 89 struct curltime now = Curl_now(); 90 infof(data, "WARNING: Using weak random seed\n"); 91 randseed += (unsigned int)now.tv_usec + (unsigned int)now.tv_sec; 92 randseed = randseed * 1103515245 + 12345; 93 randseed = randseed * 1103515245 + 12345; 94 randseed = randseed * 1103515245 + 12345; 95 seeded = TRUE; 96 } 97 98 /* Return an unsigned 32-bit pseudo-random number. */ 99 r = randseed = randseed * 1103515245 + 12345; 100 *rnd = (r << 16) | ((r >> 16) & 0xFFFF); 101 return CURLE_OK; 102 } 103 104 /* 105 * Curl_rand() stores 'num' number of random unsigned integers in the buffer 106 * 'rndptr' points to. 107 * 108 * If libcurl is built without TLS support or with a TLS backend that lacks a 109 * proper random API (Gskit, PolarSSL or mbedTLS), this function will use 110 * "weak" random. 111 * 112 * When built *with* TLS support and a backend that offers strong random, it 113 * will return error if it cannot provide strong random values. 114 * 115 * NOTE: 'data' may be passed in as NULL when coming from external API without 116 * easy handle! 117 * 118 */ 119 120 CURLcode Curl_rand(struct Curl_easy *data, unsigned char *rnd, size_t num) 121 { 122 CURLcode result = CURLE_BAD_FUNCTION_ARGUMENT; 123 124 DEBUGASSERT(num > 0); 125 126 while(num) { 127 unsigned int r; 128 size_t left = num < sizeof(unsigned int) ? num : sizeof(unsigned int); 129 130 result = randit(data, &r); 131 if(result) 132 return result; 133 134 while(left) { 135 *rnd++ = (unsigned char)(r & 0xFF); 136 r >>= 8; 137 --num; 138 --left; 139 } 140 } 141 142 return result; 143 } 144 145 /* 146 * Curl_rand_hex() fills the 'rnd' buffer with a given 'num' size with random 147 * hexadecimal digits PLUS a zero terminating byte. It must be an odd number 148 * size. 149 */ 150 151 CURLcode Curl_rand_hex(struct Curl_easy *data, unsigned char *rnd, 152 size_t num) 153 { 154 CURLcode result = CURLE_BAD_FUNCTION_ARGUMENT; 155 const char *hex = "0123456789abcdef"; 156 unsigned char buffer[128]; 157 unsigned char *bufp = buffer; 158 DEBUGASSERT(num > 1); 159 160 #ifdef __clang_analyzer__ 161 /* This silences a scan-build warning about accesssing this buffer with 162 uninitialized memory. */ 163 memset(buffer, 0, sizeof(buffer)); 164 #endif 165 166 if((num/2 >= sizeof(buffer)) || !(num&1)) 167 /* make sure it fits in the local buffer and that it is an odd number! */ 168 return CURLE_BAD_FUNCTION_ARGUMENT; 169 170 num--; /* save one for zero termination */ 171 172 result = Curl_rand(data, buffer, num/2); 173 if(result) 174 return result; 175 176 while(num) { 177 *rnd++ = hex[(*bufp & 0xF0)>>4]; 178 *rnd++ = hex[*bufp & 0x0F]; 179 bufp++; 180 num -= 2; 181 } 182 *rnd = 0; 183 184 return result; 185 } 186