1d9e397b599b13d642138480a28c14db7a136bf0Adam Langley/* Copyright (c) 2014, Google Inc.
2d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *
3d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * Permission to use, copy, modify, and/or distribute this software for any
4d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * purpose with or without fee is hereby granted, provided that the above
5d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * copyright notice and this permission notice appear in all copies.
6d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *
7d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
10d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
12d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
13d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
14d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
15d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <openssl/rand.h>
16d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
1753b272a2813a0b11f107d77100ff8805ada8fbd2Adam Langley#include <limits.h>
18e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley#include <string.h>
19e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley
20e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley#include <openssl/mem.h>
21e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley
22e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley#include "internal.h"
23e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley#include "../internal.h"
24e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley
25e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley
26e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley/* It's assumed that the operating system always has an unfailing source of
27e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley * entropy which is accessed via |CRYPTO_sysrand|. (If the operating system
28e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley * entropy source fails, it's up to |CRYPTO_sysrand| to abort the process—we
29e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley * don't try to handle it.)
30e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley *
31e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley * In addition, the hardware may provide a low-latency RNG. Intel's rdrand
32e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley * instruction is the canonical example of this. When a hardware RNG is
33e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley * available we don't need to worry about an RNG failure arising from fork()ing
34e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley * the process or moving a VM, so we can keep thread-local RNG state and XOR
35e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley * the hardware entropy in.
36e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley *
37e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley * (We assume that the OS entropy is safe from fork()ing and VM duplication.
38e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley * This might be a bit of a leap of faith, esp on Windows, but there's nothing
39e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley * that we can do about it.) */
40e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley
41e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley/* rand_thread_state contains the per-thread state for the RNG. This is only
42e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley * used if the system has support for a hardware RNG. */
43e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langleystruct rand_thread_state {
44e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  uint8_t key[32];
45e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  uint64_t calls_used;
46e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  size_t bytes_used;
47e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  uint8_t partial_block[64];
48e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  unsigned partial_block_used;
49e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley};
50e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley
51e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley/* kMaxCallsPerRefresh is the maximum number of |RAND_bytes| calls that we'll
52e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley * serve before reading a new key from the operating system. This only applies
53e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley * if we have a hardware RNG. */
54e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langleystatic const unsigned kMaxCallsPerRefresh = 1024;
55e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley
56e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley/* kMaxBytesPerRefresh is the maximum number of bytes that we'll return from
57e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley * |RAND_bytes| before reading a new key from the operating system. This only
58e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley * applies if we have a hardware RNG. */
59e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langleystatic const uint64_t kMaxBytesPerRefresh = 1024 * 1024;
60e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley
61e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley/* rand_thread_state_free frees a |rand_thread_state|. This is called when a
62e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley * thread exits. */
63e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langleystatic void rand_thread_state_free(void *state) {
64e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  if (state == NULL) {
65e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    return;
66e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  }
67e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley
68e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  OPENSSL_cleanse(state, sizeof(struct rand_thread_state));
69e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  OPENSSL_free(state);
70e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley}
71e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley
72e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langleyextern void CRYPTO_chacha_20(uint8_t *out, const uint8_t *in, size_t in_len,
73e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley                             const uint8_t key[32], const uint8_t nonce[8],
74e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley                             size_t counter);
75e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley
76e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langleyint RAND_bytes(uint8_t *buf, size_t len) {
77e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  if (len == 0) {
78e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    return 1;
79e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  }
80e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley
81e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  if (!CRYPTO_have_hwrand()) {
82e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    /* Without a hardware RNG to save us from address-space duplication, the OS
83e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley     * entropy is used directly. */
84e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    CRYPTO_sysrand(buf, len);
85e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    return 1;
86e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  }
87e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley
88e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  struct rand_thread_state *state =
89e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley      CRYPTO_get_thread_local(OPENSSL_THREAD_LOCAL_RAND);
90e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  if (state == NULL) {
91e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    state = OPENSSL_malloc(sizeof(struct rand_thread_state));
92e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    if (state == NULL ||
93e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley        !CRYPTO_set_thread_local(OPENSSL_THREAD_LOCAL_RAND, state,
94e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley                                 rand_thread_state_free)) {
95e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley      CRYPTO_sysrand(buf, len);
96e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley      return 1;
97e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    }
98e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley
9953b272a2813a0b11f107d77100ff8805ada8fbd2Adam Langley    memset(state->partial_block, 0, sizeof(state->partial_block));
100e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    state->calls_used = kMaxCallsPerRefresh;
101e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  }
102e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley
103e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  if (state->calls_used >= kMaxCallsPerRefresh ||
104e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley      state->bytes_used >= kMaxBytesPerRefresh) {
105e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    CRYPTO_sysrand(state->key, sizeof(state->key));
106e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    state->calls_used = 0;
107e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    state->bytes_used = 0;
108e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    state->partial_block_used = sizeof(state->partial_block);
109e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  }
110e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley
111e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  CRYPTO_hwrand(buf, len);
112e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley
113e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  if (len >= sizeof(state->partial_block)) {
114e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    size_t remaining = len;
115e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    while (remaining > 0) {
116e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley      // kMaxBytesPerCall is only 2GB, while ChaCha can handle 256GB. But this
117e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley      // is sufficient and easier on 32-bit.
118e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley      static const size_t kMaxBytesPerCall = 0x80000000;
119e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley      size_t todo = remaining;
120e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley      if (todo > kMaxBytesPerCall) {
121e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley        todo = kMaxBytesPerCall;
122e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley      }
123e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley      CRYPTO_chacha_20(buf, buf, todo, state->key,
124e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley                       (uint8_t *)&state->calls_used, 0);
125e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley      buf += todo;
126e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley      remaining -= todo;
127e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley      state->calls_used++;
128e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    }
129e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  } else {
130e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    if (sizeof(state->partial_block) - state->partial_block_used < len) {
131e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley      CRYPTO_chacha_20(state->partial_block, state->partial_block,
132e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley                       sizeof(state->partial_block), state->key,
133e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley                       (uint8_t *)&state->calls_used, 0);
134e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley      state->partial_block_used = 0;
135e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    }
136e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley
137e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    unsigned i;
138e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    for (i = 0; i < len; i++) {
139e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley      buf[i] ^= state->partial_block[state->partial_block_used++];
140e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    }
141e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley    state->calls_used++;
142e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  }
143e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  state->bytes_used += len;
144e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley
145e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley  return 1;
146e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley}
147d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
148d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyint RAND_pseudo_bytes(uint8_t *buf, size_t len) {
149d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  return RAND_bytes(buf, len);
150d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
151d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
152d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyvoid RAND_seed(const void *buf, int num) {}
153d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
15453b272a2813a0b11f107d77100ff8805ada8fbd2Adam Langleyint RAND_load_file(const char *path, long num) {
15553b272a2813a0b11f107d77100ff8805ada8fbd2Adam Langley  if (num < 0) {  /* read the "whole file" */
15653b272a2813a0b11f107d77100ff8805ada8fbd2Adam Langley    return 1;
15753b272a2813a0b11f107d77100ff8805ada8fbd2Adam Langley  } else if (num <= INT_MAX) {
15853b272a2813a0b11f107d77100ff8805ada8fbd2Adam Langley    return (int) num;
15953b272a2813a0b11f107d77100ff8805ada8fbd2Adam Langley  } else {
16053b272a2813a0b11f107d77100ff8805ada8fbd2Adam Langley    return INT_MAX;
16153b272a2813a0b11f107d77100ff8805ada8fbd2Adam Langley  }
16253b272a2813a0b11f107d77100ff8805ada8fbd2Adam Langley}
16353b272a2813a0b11f107d77100ff8805ada8fbd2Adam Langley
164d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyvoid RAND_add(const void *buf, int num, double entropy) {}
165d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
166d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyint RAND_poll(void) {
167d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  return 1;
168d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
169f7e890d94bfb2ecad87621eed301e1897b5a6aefAdam Langley
170f7e890d94bfb2ecad87621eed301e1897b5a6aefAdam Langleyint RAND_status(void) {
171f7e890d94bfb2ecad87621eed301e1897b5a6aefAdam Langley  return 1;
172f7e890d94bfb2ecad87621eed301e1897b5a6aefAdam Langley}
173