VirtualBox

source: vbox/trunk/src/libs/curl-8.7.1/lib/rand.c@ 106542

最後變更 在這個檔案從106542是 104083,由 vboxsync 提交於 11 月 前

curl-8.7.1: Applied and adjusted our curl changes to 8.4.0. bugref:10639

  • 屬性 svn:eol-style 設為 native
檔案大小: 7.5 KB
 
1/***************************************************************************
2 * _ _ ____ _
3 * Project ___| | | | _ \| |
4 * / __| | | | |_) | |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
7 *
8 * Copyright (C) Daniel Stenberg, <[email protected]>, 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.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 * SPDX-License-Identifier: curl
22 *
23 ***************************************************************************/
24
25#include "curl_setup.h"
26
27#include <limits.h>
28
29#ifdef HAVE_FCNTL_H
30#include <fcntl.h>
31#endif
32#ifdef HAVE_ARPA_INET_H
33#include <arpa/inet.h>
34#endif
35
36#include <curl/curl.h>
37#include "urldata.h"
38#include "vtls/vtls.h"
39#include "sendf.h"
40#include "timeval.h"
41#include "rand.h"
42#include "escape.h"
43
44/* The last 3 #include files should be in this order */
45#include "curl_printf.h"
46#include "curl_memory.h"
47#include "memdebug.h"
48
49#ifdef _WIN32
50
51#if defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x600
52# define HAVE_WIN_BCRYPTGENRANDOM
53# include <bcrypt.h>
54# ifdef _MSC_VER
55# pragma comment(lib, "bcrypt.lib")
56# endif
57# ifndef BCRYPT_USE_SYSTEM_PREFERRED_RNG
58# define BCRYPT_USE_SYSTEM_PREFERRED_RNG 0x00000002
59# endif
60# ifndef STATUS_SUCCESS
61# define STATUS_SUCCESS ((NTSTATUS)0x00000000L)
62# endif
63#elif defined(USE_WIN32_CRYPTO)
64# include <wincrypt.h>
65# ifdef _MSC_VER
66# pragma comment(lib, "advapi32.lib")
67# endif
68#endif
69
70CURLcode Curl_win32_random(unsigned char *entropy, size_t length)
71{
72 memset(entropy, 0, length);
73
74#if defined(HAVE_WIN_BCRYPTGENRANDOM)
75 if(BCryptGenRandom(NULL, entropy, (ULONG)length,
76 BCRYPT_USE_SYSTEM_PREFERRED_RNG) != STATUS_SUCCESS)
77 return CURLE_FAILED_INIT;
78
79 return CURLE_OK;
80#elif defined(USE_WIN32_CRYPTO)
81 {
82 HCRYPTPROV hCryptProv = 0;
83
84 if(!CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL,
85 CRYPT_VERIFYCONTEXT | CRYPT_SILENT))
86 return CURLE_FAILED_INIT;
87
88 if(!CryptGenRandom(hCryptProv, (DWORD)length, entropy)) {
89 CryptReleaseContext(hCryptProv, 0UL);
90 return CURLE_FAILED_INIT;
91 }
92
93 CryptReleaseContext(hCryptProv, 0UL);
94 }
95 return CURLE_OK;
96#else
97 return CURLE_NOT_BUILT_IN;
98#endif
99}
100#endif
101
102static CURLcode randit(struct Curl_easy *data, unsigned int *rnd)
103{
104 CURLcode result = CURLE_OK;
105 static unsigned int randseed;
106 static bool seeded = FALSE;
107
108#ifdef CURLDEBUG
109 char *force_entropy = getenv("CURL_ENTROPY");
110 if(force_entropy) {
111 if(!seeded) {
112 unsigned int seed = 0;
113 size_t elen = strlen(force_entropy);
114 size_t clen = sizeof(seed);
115 size_t min = elen < clen ? elen : clen;
116 memcpy((char *)&seed, force_entropy, min);
117 randseed = ntohl(seed);
118 seeded = TRUE;
119 }
120 else
121 randseed++;
122 *rnd = randseed;
123 return CURLE_OK;
124 }
125#endif
126
127 /* data may be NULL! */
128 result = Curl_ssl_random(data, (unsigned char *)rnd, sizeof(*rnd));
129 if(result != CURLE_NOT_BUILT_IN)
130 /* only if there is no random function in the TLS backend do the non crypto
131 version, otherwise return result */
132 return result;
133
134 /* ---- non-cryptographic version following ---- */
135
136#ifdef _WIN32
137 if(!seeded) {
138 result = Curl_win32_random((unsigned char *)rnd, sizeof(*rnd));
139 if(result != CURLE_NOT_BUILT_IN)
140 return result;
141 }
142#endif
143
144#if defined(HAVE_ARC4RANDOM) && !defined(USE_OPENSSL)
145 if(!seeded) {
146 *rnd = (unsigned int)arc4random();
147 return CURLE_OK;
148 }
149#endif
150
151#if defined(RANDOM_FILE) && !defined(_WIN32)
152 if(!seeded) {
153 /* if there's a random file to read a seed from, use it */
154 int fd = open(RANDOM_FILE, O_RDONLY);
155 if(fd > -1) {
156 /* read random data into the randseed variable */
157 ssize_t nread = read(fd, &randseed, sizeof(randseed));
158 if(nread == sizeof(randseed))
159 seeded = TRUE;
160 close(fd);
161 }
162 }
163#endif
164
165 if(!seeded) {
166 struct curltime now = Curl_now();
167 infof(data, "WARNING: using weak random seed");
168 randseed += (unsigned int)now.tv_usec + (unsigned int)now.tv_sec;
169 randseed = randseed * 1103515245 + 12345;
170 randseed = randseed * 1103515245 + 12345;
171 randseed = randseed * 1103515245 + 12345;
172 seeded = TRUE;
173 }
174
175 {
176 unsigned int r;
177 /* Return an unsigned 32-bit pseudo-random number. */
178 r = randseed = randseed * 1103515245 + 12345;
179 *rnd = (r << 16) | ((r >> 16) & 0xFFFF);
180 }
181 return CURLE_OK;
182}
183
184/*
185 * Curl_rand() stores 'num' number of random unsigned characters in the buffer
186 * 'rnd' points to.
187 *
188 * If libcurl is built without TLS support or with a TLS backend that lacks a
189 * proper random API (rustls or mbedTLS), this function will use "weak"
190 * random.
191 *
192 * When built *with* TLS support and a backend that offers strong random, it
193 * will return error if it cannot provide strong random values.
194 *
195 * NOTE: 'data' may be passed in as NULL when coming from external API without
196 * easy handle!
197 *
198 */
199
200CURLcode Curl_rand(struct Curl_easy *data, unsigned char *rnd, size_t num)
201{
202 CURLcode result = CURLE_BAD_FUNCTION_ARGUMENT;
203
204 DEBUGASSERT(num);
205
206 while(num) {
207 unsigned int r;
208 size_t left = num < sizeof(unsigned int) ? num : sizeof(unsigned int);
209
210 result = randit(data, &r);
211 if(result)
212 return result;
213
214 while(left) {
215 *rnd++ = (unsigned char)(r & 0xFF);
216 r >>= 8;
217 --num;
218 --left;
219 }
220 }
221
222 return result;
223}
224
225/*
226 * Curl_rand_hex() fills the 'rnd' buffer with a given 'num' size with random
227 * hexadecimal digits PLUS a null-terminating byte. It must be an odd number
228 * size.
229 */
230
231CURLcode Curl_rand_hex(struct Curl_easy *data, unsigned char *rnd,
232 size_t num)
233{
234 CURLcode result = CURLE_BAD_FUNCTION_ARGUMENT;
235 unsigned char buffer[128];
236 DEBUGASSERT(num > 1);
237
238#ifdef __clang_analyzer__
239 /* This silences a scan-build warning about accessing this buffer with
240 uninitialized memory. */
241 memset(buffer, 0, sizeof(buffer));
242#endif
243
244 if((num/2 >= sizeof(buffer)) || !(num&1)) {
245 /* make sure it fits in the local buffer and that it is an odd number! */
246 DEBUGF(infof(data, "invalid buffer size with Curl_rand_hex"));
247 return CURLE_BAD_FUNCTION_ARGUMENT;
248 }
249
250 num--; /* save one for null-termination */
251
252 result = Curl_rand(data, buffer, num/2);
253 if(result)
254 return result;
255
256 Curl_hexencode(buffer, num/2, rnd, num + 1);
257 return result;
258}
259
260/*
261 * Curl_rand_alnum() fills the 'rnd' buffer with a given 'num' size with random
262 * alphanumerical chars PLUS a null-terminating byte.
263 */
264
265static const char alnum[] =
266 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
267
268CURLcode Curl_rand_alnum(struct Curl_easy *data, unsigned char *rnd,
269 size_t num)
270{
271 CURLcode result = CURLE_OK;
272 const int alnumspace = sizeof(alnum) - 1;
273 unsigned int r;
274 DEBUGASSERT(num > 1);
275
276 num--; /* save one for null-termination */
277
278 while(num) {
279 do {
280 result = randit(data, &r);
281 if(result)
282 return result;
283 } while(r >= (UINT_MAX - UINT_MAX % alnumspace));
284
285 *rnd++ = alnum[r % alnumspace];
286 num--;
287 }
288 *rnd = 0;
289
290 return result;
291}
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette