Annotation of embedaddon/curl/lib/rand.c, revision 1.1
1.1 ! misho 1: /***************************************************************************
! 2: * _ _ ____ _
! 3: * Project ___| | | | _ \| |
! 4: * / __| | | | |_) | |
! 5: * | (__| |_| | _ <| |___
! 6: * \___|\___/|_| \_\_____|
! 7: *
! 8: * Copyright (C) 1998 - 2019, 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 or mbedTLS), this function will use "weak" random.
! 110: *
! 111: * When built *with* TLS support and a backend that offers strong random, it
! 112: * will return error if it cannot provide strong random values.
! 113: *
! 114: * NOTE: 'data' may be passed in as NULL when coming from external API without
! 115: * easy handle!
! 116: *
! 117: */
! 118:
! 119: CURLcode Curl_rand(struct Curl_easy *data, unsigned char *rnd, size_t num)
! 120: {
! 121: CURLcode result = CURLE_BAD_FUNCTION_ARGUMENT;
! 122:
! 123: DEBUGASSERT(num > 0);
! 124:
! 125: while(num) {
! 126: unsigned int r;
! 127: size_t left = num < sizeof(unsigned int) ? num : sizeof(unsigned int);
! 128:
! 129: result = randit(data, &r);
! 130: if(result)
! 131: return result;
! 132:
! 133: while(left) {
! 134: *rnd++ = (unsigned char)(r & 0xFF);
! 135: r >>= 8;
! 136: --num;
! 137: --left;
! 138: }
! 139: }
! 140:
! 141: return result;
! 142: }
! 143:
! 144: /*
! 145: * Curl_rand_hex() fills the 'rnd' buffer with a given 'num' size with random
! 146: * hexadecimal digits PLUS a zero terminating byte. It must be an odd number
! 147: * size.
! 148: */
! 149:
! 150: CURLcode Curl_rand_hex(struct Curl_easy *data, unsigned char *rnd,
! 151: size_t num)
! 152: {
! 153: CURLcode result = CURLE_BAD_FUNCTION_ARGUMENT;
! 154: const char *hex = "0123456789abcdef";
! 155: unsigned char buffer[128];
! 156: unsigned char *bufp = buffer;
! 157: DEBUGASSERT(num > 1);
! 158:
! 159: #ifdef __clang_analyzer__
! 160: /* This silences a scan-build warning about accessing this buffer with
! 161: uninitialized memory. */
! 162: memset(buffer, 0, sizeof(buffer));
! 163: #endif
! 164:
! 165: if((num/2 >= sizeof(buffer)) || !(num&1))
! 166: /* make sure it fits in the local buffer and that it is an odd number! */
! 167: return CURLE_BAD_FUNCTION_ARGUMENT;
! 168:
! 169: num--; /* save one for zero termination */
! 170:
! 171: result = Curl_rand(data, buffer, num/2);
! 172: if(result)
! 173: return result;
! 174:
! 175: while(num) {
! 176: /* clang-tidy warns on this line without this comment: */
! 177: /* NOLINTNEXTLINE(clang-analyzer-core.UndefinedBinaryOperatorResult) */
! 178: *rnd++ = hex[(*bufp & 0xF0)>>4];
! 179: *rnd++ = hex[*bufp & 0x0F];
! 180: bufp++;
! 181: num -= 2;
! 182: }
! 183: *rnd = 0;
! 184:
! 185: return result;
! 186: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>