Home | History | Annotate | Download | only in rand
      1 /* Copyright (c) 2014, Google Inc.
      2  *
      3  * Permission to use, copy, modify, and/or distribute this software for any
      4  * purpose with or without fee is hereby granted, provided that the above
      5  * copyright notice and this permission notice appear in all copies.
      6  *
      7  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
      8  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
      9  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
     10  * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
     11  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
     12  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
     13  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
     14 
     15 #include <openssl/rand.h>
     16 
     17 #include <assert.h>
     18 #include <limits.h>
     19 #include <string.h>
     20 
     21 #include <openssl/chacha.h>
     22 #include <openssl/cpu.h>
     23 #include <openssl/mem.h>
     24 
     25 #include "internal.h"
     26 #include "../internal.h"
     27 
     28 
     29 /* It's assumed that the operating system always has an unfailing source of
     30  * entropy which is accessed via |CRYPTO_sysrand|. (If the operating system
     31  * entropy source fails, it's up to |CRYPTO_sysrand| to abort the processwe
     32  * don't try to handle it.)
     33  *
     34  * In addition, the hardware may provide a low-latency RNG. Intel's rdrand
     35  * instruction is the canonical example of this. When a hardware RNG is
     36  * available we don't need to worry about an RNG failure arising from fork()ing
     37  * the process or moving a VM, so we can keep thread-local RNG state and XOR
     38  * the hardware entropy in.
     39  *
     40  * (We assume that the OS entropy is safe from fork()ing and VM duplication.
     41  * This might be a bit of a leap of faith, esp on Windows, but there's nothing
     42  * that we can do about it.) */
     43 
     44 /* rand_thread_state contains the per-thread state for the RNG. This is only
     45  * used if the system has support for a hardware RNG. */
     46 struct rand_thread_state {
     47   uint8_t key[32];
     48   uint64_t calls_used;
     49   size_t bytes_used;
     50   uint8_t partial_block[64];
     51   unsigned partial_block_used;
     52 };
     53 
     54 /* kMaxCallsPerRefresh is the maximum number of |RAND_bytes| calls that we'll
     55  * serve before reading a new key from the operating system. This only applies
     56  * if we have a hardware RNG. */
     57 static const unsigned kMaxCallsPerRefresh = 1024;
     58 
     59 /* kMaxBytesPerRefresh is the maximum number of bytes that we'll return from
     60  * |RAND_bytes| before reading a new key from the operating system. This only
     61  * applies if we have a hardware RNG. */
     62 static const uint64_t kMaxBytesPerRefresh = 1024 * 1024;
     63 
     64 /* rand_thread_state_free frees a |rand_thread_state|. This is called when a
     65  * thread exits. */
     66 static void rand_thread_state_free(void *state) {
     67   if (state == NULL) {
     68     return;
     69   }
     70 
     71   OPENSSL_cleanse(state, sizeof(struct rand_thread_state));
     72   OPENSSL_free(state);
     73 }
     74 
     75 #if defined(OPENSSL_X86_64) && !defined(OPENSSL_NO_ASM) && \
     76     !defined(BORINGSSL_UNSAFE_DETERMINISTIC_MODE)
     77 
     78 /* These functions are defined in asm/rdrand-x86_64.pl */
     79 extern int CRYPTO_rdrand(uint8_t out[8]);
     80 extern int CRYPTO_rdrand_multiple8_buf(uint8_t *buf, size_t len);
     81 
     82 static int have_rdrand(void) {
     83   return (OPENSSL_ia32cap_P[1] & (1u << 30)) != 0;
     84 }
     85 
     86 static int hwrand(uint8_t *buf, size_t len) {
     87   if (!have_rdrand()) {
     88     return 0;
     89   }
     90 
     91   const size_t len_multiple8 = len & ~7;
     92   if (!CRYPTO_rdrand_multiple8_buf(buf, len_multiple8)) {
     93     return 0;
     94   }
     95   len -= len_multiple8;
     96 
     97   if (len != 0) {
     98     assert(len < 8);
     99 
    100     uint8_t rand_buf[8];
    101     if (!CRYPTO_rdrand(rand_buf)) {
    102       return 0;
    103     }
    104     OPENSSL_memcpy(buf + len_multiple8, rand_buf, len);
    105   }
    106 
    107   return 1;
    108 }
    109 
    110 #else
    111 
    112 static int hwrand(uint8_t *buf, size_t len) {
    113   return 0;
    114 }
    115 
    116 #endif
    117 
    118 int RAND_bytes(uint8_t *buf, size_t len) {
    119   if (len == 0) {
    120     return 1;
    121   }
    122 
    123   if (!hwrand(buf, len)) {
    124     /* Without a hardware RNG to save us from address-space duplication, the OS
    125      * entropy is used directly. */
    126     CRYPTO_sysrand(buf, len);
    127     return 1;
    128   }
    129 
    130   struct rand_thread_state *state =
    131       CRYPTO_get_thread_local(OPENSSL_THREAD_LOCAL_RAND);
    132   if (state == NULL) {
    133     state = OPENSSL_malloc(sizeof(struct rand_thread_state));
    134     if (state == NULL ||
    135         !CRYPTO_set_thread_local(OPENSSL_THREAD_LOCAL_RAND, state,
    136                                  rand_thread_state_free)) {
    137       CRYPTO_sysrand(buf, len);
    138       return 1;
    139     }
    140 
    141     OPENSSL_memset(state->partial_block, 0, sizeof(state->partial_block));
    142     state->calls_used = kMaxCallsPerRefresh;
    143   }
    144 
    145   if (state->calls_used >= kMaxCallsPerRefresh ||
    146       state->bytes_used >= kMaxBytesPerRefresh) {
    147     CRYPTO_sysrand(state->key, sizeof(state->key));
    148     state->calls_used = 0;
    149     state->bytes_used = 0;
    150     state->partial_block_used = sizeof(state->partial_block);
    151   }
    152 
    153   if (len >= sizeof(state->partial_block)) {
    154     size_t remaining = len;
    155     while (remaining > 0) {
    156       /* kMaxBytesPerCall is only 2GB, while ChaCha can handle 256GB. But this
    157        * is sufficient and easier on 32-bit. */
    158       static const size_t kMaxBytesPerCall = 0x80000000;
    159       size_t todo = remaining;
    160       if (todo > kMaxBytesPerCall) {
    161         todo = kMaxBytesPerCall;
    162       }
    163       uint8_t nonce[12];
    164       OPENSSL_memset(nonce, 0, 4);
    165       OPENSSL_memcpy(nonce + 4, &state->calls_used, sizeof(state->calls_used));
    166       CRYPTO_chacha_20(buf, buf, todo, state->key, nonce, 0);
    167       buf += todo;
    168       remaining -= todo;
    169       state->calls_used++;
    170     }
    171   } else {
    172     if (sizeof(state->partial_block) - state->partial_block_used < len) {
    173       uint8_t nonce[12];
    174       OPENSSL_memset(nonce, 0, 4);
    175       OPENSSL_memcpy(nonce + 4, &state->calls_used, sizeof(state->calls_used));
    176       CRYPTO_chacha_20(state->partial_block, state->partial_block,
    177                        sizeof(state->partial_block), state->key, nonce, 0);
    178       state->partial_block_used = 0;
    179     }
    180 
    181     unsigned i;
    182     for (i = 0; i < len; i++) {
    183       buf[i] ^= state->partial_block[state->partial_block_used++];
    184     }
    185     state->calls_used++;
    186   }
    187   state->bytes_used += len;
    188 
    189   return 1;
    190 }
    191 
    192 int RAND_pseudo_bytes(uint8_t *buf, size_t len) {
    193   return RAND_bytes(buf, len);
    194 }
    195 
    196 void RAND_seed(const void *buf, int num) {
    197   /* OpenSSH calls |RAND_seed| before jailing on the assumption that any needed
    198    * file descriptors etc will be opened. */
    199   uint8_t unused;
    200   RAND_bytes(&unused, sizeof(unused));
    201 }
    202 
    203 int RAND_load_file(const char *path, long num) {
    204   if (num < 0) {  /* read the "whole file" */
    205     return 1;
    206   } else if (num <= INT_MAX) {
    207     return (int) num;
    208   } else {
    209     return INT_MAX;
    210   }
    211 }
    212 
    213 const char *RAND_file_name(char *buf, size_t num) { return NULL; }
    214 
    215 void RAND_add(const void *buf, int num, double entropy) {}
    216 
    217 int RAND_egd(const char *path) {
    218   return 255;
    219 }
    220 
    221 int RAND_poll(void) {
    222   return 1;
    223 }
    224 
    225 int RAND_status(void) {
    226   return 1;
    227 }
    228 
    229 static const struct rand_meth_st kSSLeayMethod = {
    230   RAND_seed,
    231   RAND_bytes,
    232   RAND_cleanup,
    233   RAND_add,
    234   RAND_pseudo_bytes,
    235   RAND_status,
    236 };
    237 
    238 RAND_METHOD *RAND_SSLeay(void) {
    239   return (RAND_METHOD*) &kSSLeayMethod;
    240 }
    241 
    242 void RAND_set_rand_method(const RAND_METHOD *method) {}
    243 
    244 void RAND_cleanup(void) {}
    245