File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / curl / lib / rand.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Jun 3 10:01:15 2020 UTC (5 years ago) by misho
Branches: curl, MAIN
CVS tags: v7_70_0p4, HEAD
curl

    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>