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