Annotation of embedaddon/curl/lib/rand.c, revision 1.1.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>