rand: treat fake entropy the same regardless of endianness

When the random seed is purposely made predictable for testing purposes
by using the CURL_ENTROPY environment variable, process that data in an
endian agnostic way so the the initial random seed is the same
regardless of endianness.

- Change Curl_rand to write to a char array instead of int array.

- Add Curl_rand_hex to write random hex characters to a buffer.

Fixes #1315
Closes #1468

Co-authored-by: Daniel Stenberg
Reported-by: Michael Kaufmann
This commit is contained in:
Jay Satiro 2017-05-08 23:23:28 +02:00 committed by Daniel Stenberg
parent 9e9509e46a
commit 1cafede9f2
5 changed files with 87 additions and 54 deletions

View File

@ -48,7 +48,7 @@ static char *Curl_basename(char *path);
#endif
static size_t readfromfile(struct Form *form, char *buffer, size_t size);
static char *formboundary(struct Curl_easy *data);
static CURLcode formboundary(struct Curl_easy *data, char *buffer, size_t len);
/* What kind of Content-Type to use on un-specified files with unrecognized
extensions. */
@ -1159,20 +1159,19 @@ CURLcode Curl_getformdata(struct Curl_easy *data,
struct FormData *firstform;
struct curl_httppost *file;
CURLcode result = CURLE_OK;
curl_off_t size = 0; /* support potentially ENORMOUS formposts */
char *boundary;
char *fileboundary = NULL;
char fileboundary[42];
struct curl_slist *curList;
char boundary[42];
*finalform = NULL; /* default form is empty */
if(!post)
return result; /* no input => no output! */
boundary = formboundary(data);
if(!boundary)
return CURLE_OUT_OF_MEMORY;
result = formboundary(data, boundary, sizeof(boundary));
if(result)
return result;
/* Make the first line of the output */
result = AddFormDataf(&form, NULL,
@ -1182,7 +1181,6 @@ CURLcode Curl_getformdata(struct Curl_easy *data,
boundary);
if(result) {
free(boundary);
return result;
}
/* we DO NOT include that line in the total size of the POST, since it'll be
@ -1225,10 +1223,8 @@ CURLcode Curl_getformdata(struct Curl_easy *data,
/* If used, this is a link to more file names, we must then do
the magic to include several files with the same field name */
free(fileboundary);
fileboundary = formboundary(data);
if(!fileboundary) {
result = CURLE_OUT_OF_MEMORY;
result = formboundary(data, fileboundary, sizeof(fileboundary));
if(result) {
break;
}
@ -1379,16 +1375,10 @@ CURLcode Curl_getformdata(struct Curl_easy *data,
if(result) {
Curl_formclean(&firstform);
free(fileboundary);
free(boundary);
return result;
}
*sizep = size;
free(fileboundary);
free(boundary);
*finalform = firstform;
return result;
@ -1562,16 +1552,17 @@ char *Curl_formpostheader(void *formp, size_t *len)
* formboundary() creates a suitable boundary string and returns an allocated
* one.
*/
static char *formboundary(struct Curl_easy *data)
static CURLcode formboundary(struct Curl_easy *data,
char *buffer, size_t buflen)
{
/* 24 dashes and 16 hexadecimal digits makes 64 bit (18446744073709551615)
combinations */
unsigned int rnd[2];
CURLcode result = Curl_rand(data, &rnd[0], 2);
if(result)
return NULL;
DEBUGASSERT(buflen >= 41);
return aprintf("------------------------%08x%08x", rnd[0], rnd[1]);
memset(buffer, '-', 24);
Curl_rand_hex(data, (unsigned char *)&buffer[24], 17);
return CURLE_OK;
}
#else /* CURL_DISABLE_HTTP */

View File

@ -47,10 +47,12 @@ static CURLcode randit(struct Curl_easy *data, unsigned int *rnd)
char *force_entropy = getenv("CURL_ENTROPY");
if(force_entropy) {
if(!seeded) {
unsigned int seed = 0;
size_t elen = strlen(force_entropy);
size_t clen = sizeof(randseed);
size_t clen = sizeof(seed);
size_t min = elen < clen ? elen : clen;
memcpy((char *)&randseed, force_entropy, min);
memcpy((char *)&seed, force_entropy, min);
randseed = ntohl(seed);
seeded = TRUE;
}
else
@ -115,18 +117,63 @@ static CURLcode randit(struct Curl_easy *data, unsigned int *rnd)
*
*/
CURLcode Curl_rand(struct Curl_easy *data, unsigned int *rndptr,
unsigned int num)
CURLcode Curl_rand(struct Curl_easy *data, unsigned char *rnd, size_t num)
{
CURLcode result = CURLE_BAD_FUNCTION_ARGUMENT;
unsigned int i;
assert(num > 0);
for(i = 0; i < num; i++) {
result = randit(data, rndptr++);
while(num) {
unsigned int r;
size_t left = num < sizeof(unsigned int) ? num : sizeof(unsigned int);
result = randit(data, &r);
if(result)
return result;
while(left) {
*rnd++ = (unsigned char)(r & 0xFF);
r >>= 8;
--num;
--left;
}
}
return result;
}
/*
* Curl_rand_hex() fills the 'rnd' buffer with a given 'num' size with random
* hexadecimal digits PLUS a zero terminating byte. It must be an odd number
* size.
*/
CURLcode Curl_rand_hex(struct Curl_easy *data, unsigned char *rnd,
size_t num)
{
CURLcode result = CURLE_BAD_FUNCTION_ARGUMENT;
const char *hex = "0123456789abcdef";
unsigned char buffer[128];
unsigned char *bufp = buffer;
DEBUGASSERT(num > 1);
if((num/2 >= sizeof(buffer)) || !(num&1))
/* make sure it fits in the local buffer and that it is an odd number! */
return CURLE_BAD_FUNCTION_ARGUMENT;
num--; /* save one for zero termination */
result = Curl_rand(data, buffer, num/2);
if(result)
return result;
while(num) {
*rnd++ = hex[(*bufp & 0xF0)>>4];
*rnd++ = hex[*bufp & 0x0F];
bufp++;
num -= 2;
}
*rnd = 0;
return result;
}

View File

@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@ -23,7 +23,7 @@
***************************************************************************/
/*
* Curl_rand() stores 'num' number of random unsigned integers in the buffer
* Curl_rand() stores 'num' number of random unsigned characters in the buffer
* 'rnd' points to.
*
* If libcurl is built without TLS support or with a TLS backend that lacks a
@ -37,7 +37,11 @@
* easy handle!
*
*/
CURLcode Curl_rand(struct Curl_easy *data, unsigned int *rnd,
unsigned int num);
CURLcode Curl_rand(struct Curl_easy *data, unsigned char *rnd, size_t num);
/* Same as above but outputs only random lowercase hex characters.
Does NOT terminate.*/
CURLcode Curl_rand_hex(struct Curl_easy *data, unsigned char *rnd,
size_t num);
#endif /* HEADER_CURL_RAND_H */

View File

@ -360,7 +360,6 @@ CURLcode Curl_auth_create_digest_md5_message(struct Curl_easy *data,
char qop_options[64];
int qop_values;
char cnonce[33];
unsigned int entropy[4];
char nonceCount[] = "00000001";
char method[] = "AUTHENTICATE";
char qop[] = DIGEST_QOP_VALUE_STRING_AUTH;
@ -387,15 +386,11 @@ CURLcode Curl_auth_create_digest_md5_message(struct Curl_easy *data,
if(!(qop_values & DIGEST_QOP_VALUE_AUTH))
return CURLE_BAD_CONTENT_ENCODING;
/* Generate 16 bytes of random data */
result = Curl_rand(data, &entropy[0], 4);
/* Generate 32 random hex chars, 32 bytes + 1 zero termination */
result = Curl_rand_hex(data, (unsigned char *)cnonce, sizeof(cnonce));
if(result)
return result;
/* Convert the random data into a 32 byte hex string */
snprintf(cnonce, sizeof(cnonce), "%08x%08x%08x%08x",
entropy[0], entropy[1], entropy[2], entropy[3]);
/* So far so good, now calculate A1 and H(A1) according to RFC 2831 */
ctxt = Curl_MD5_init(Curl_DIGEST_MD5);
if(!ctxt)
@ -684,12 +679,10 @@ CURLcode Curl_auth_create_digest_http_message(struct Curl_easy *data,
digest->nc = 1;
if(!digest->cnonce) {
unsigned int rnd[4];
result = Curl_rand(data, &rnd[0], 4);
result = Curl_rand_hex(data, (unsigned char *)cnoncebuf,
sizeof(cnoncebuf));
if(result)
return result;
snprintf(cnoncebuf, sizeof(cnoncebuf), "%08x%08x%08x%08x",
rnd[0], rnd[1], rnd[2], rnd[3]);
result = Curl_base64_encode(data, cnoncebuf, strlen(cnoncebuf),
&cnonce, &cnonce_sz);

View File

@ -555,10 +555,10 @@ CURLcode Curl_auth_create_ntlm_type3_message(struct Curl_easy *data,
#if defined(USE_NTRESPONSES) && defined(USE_NTLM_V2)
if(ntlm->target_info_len) {
unsigned char ntbuffer[0x18];
unsigned int entropy[2];
unsigned char entropy[8];
unsigned char ntlmv2hash[0x18];
result = Curl_rand(data, &entropy[0], 2);
result = Curl_rand(data, entropy, 8);
if(result)
return result;
@ -572,15 +572,13 @@ CURLcode Curl_auth_create_ntlm_type3_message(struct Curl_easy *data,
return result;
/* LMv2 response */
result = Curl_ntlm_core_mk_lmv2_resp(ntlmv2hash,
(unsigned char *)&entropy[0],
result = Curl_ntlm_core_mk_lmv2_resp(ntlmv2hash, entropy,
&ntlm->nonce[0], lmresp);
if(result)
return result;
/* NTLMv2 response */
result = Curl_ntlm_core_mk_ntlmv2_resp(ntlmv2hash,
(unsigned char *)&entropy[0],
result = Curl_ntlm_core_mk_ntlmv2_resp(ntlmv2hash, entropy,
ntlm, &ntlmv2resp, &ntresplen);
if(result)
return result;
@ -596,10 +594,10 @@ CURLcode Curl_auth_create_ntlm_type3_message(struct Curl_easy *data,
unsigned char ntbuffer[0x18];
unsigned char tmp[0x18];
unsigned char md5sum[MD5_DIGEST_LENGTH];
unsigned int entropy[2];
unsigned char entropy[8];
/* Need to create 8 bytes random data */
result = Curl_rand(data, &entropy[0], 2);
result = Curl_rand(data, entropy, 8);
if(result)
return result;