rand_test.cc
Go to the documentation of this file.
1 /* Copyright (c) 2018, 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 <stdio.h>
18 
19 #include <gtest/gtest.h>
20 
21 #include <openssl/cpu.h>
22 #include <openssl/span.h>
23 
24 #include "../fipsmodule/rand/fork_detect.h"
25 #include "../fipsmodule/rand/internal.h"
26 #include "../test/abi_test.h"
27 #include "../test/test_util.h"
28 
29 #if defined(OPENSSL_THREADS)
30 #include <array>
31 #include <thread>
32 #include <vector>
33 #endif
34 
35 #if !defined(OPENSSL_WINDOWS)
36 #include <errno.h>
37 #include <sys/types.h>
38 #include <sys/wait.h>
39 #include <unistd.h>
40 #endif
41 
42 
43 // These tests are, strictly speaking, flaky, but we use large enough buffers
44 // that the probability of failing when we should pass is negligible.
45 
46 TEST(RandTest, NotObviouslyBroken) {
47  static const uint8_t kZeros[256] = {0};
48 
49  uint8_t buf1[256], buf2[256];
50  RAND_bytes(buf1, sizeof(buf1));
51  RAND_bytes(buf2, sizeof(buf2));
52 
53  EXPECT_NE(Bytes(buf1), Bytes(buf2));
54  EXPECT_NE(Bytes(buf1), Bytes(kZeros));
55  EXPECT_NE(Bytes(buf2), Bytes(kZeros));
56 }
57 
58 #if !defined(OPENSSL_WINDOWS) && !defined(OPENSSL_IOS) && \
59  !defined(OPENSSL_FUCHSIA) && !defined(BORINGSSL_UNSAFE_DETERMINISTIC_MODE)
60 static bool ForkAndRand(bssl::Span<uint8_t> out) {
61  int pipefds[2];
62  if (pipe(pipefds) < 0) {
63  perror("pipe");
64  return false;
65  }
66 
67  // This is a multi-threaded process, but GTest does not run tests concurrently
68  // and there currently are no threads, so this should be safe.
69  pid_t child = fork();
70  if (child < 0) {
71  perror("fork");
72  close(pipefds[0]);
73  close(pipefds[1]);
74  return false;
75  }
76 
77  if (child == 0) {
78  // This is the child. Generate entropy and write it to the parent.
79  close(pipefds[0]);
80  RAND_bytes(out.data(), out.size());
81  while (!out.empty()) {
82  ssize_t ret = write(pipefds[1], out.data(), out.size());
83  if (ret < 0) {
84  if (errno == EINTR) {
85  continue;
86  }
87  perror("write");
88  _exit(1);
89  }
90  out = out.subspan(static_cast<size_t>(ret));
91  }
92  _exit(0);
93  }
94 
95  // This is the parent. Read the entropy from the child.
96  close(pipefds[1]);
97  while (!out.empty()) {
98  ssize_t ret = read(pipefds[0], out.data(), out.size());
99  if (ret <= 0) {
100  if (ret == 0) {
101  fprintf(stderr, "Unexpected EOF from child.\n");
102  } else {
103  if (errno == EINTR) {
104  continue;
105  }
106  perror("read");
107  }
108  close(pipefds[0]);
109  return false;
110  }
111  out = out.subspan(static_cast<size_t>(ret));
112  }
113  close(pipefds[0]);
114 
115  // Wait for the child to exit.
116  int status;
117  if (waitpid(child, &status, 0) < 0) {
118  perror("waitpid");
119  return false;
120  }
121  if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
122  fprintf(stderr, "Child did not exit cleanly.\n");
123  return false;
124  }
125 
126  return true;
127 }
128 
129 TEST(RandTest, Fork) {
130  static const uint8_t kZeros[16] = {0};
131 
132  // Draw a little entropy to initialize any internal PRNG buffering.
133  uint8_t byte;
134  RAND_bytes(&byte, 1);
135 
136  // Draw entropy in two child processes and the parent process. This test
137  // intentionally uses smaller buffers than the others, to minimize the chance
138  // of sneaking by with a large enough buffer that we've since reseeded from
139  // the OS.
140  uint8_t buf1[16], buf2[16], buf3[16];
141  ASSERT_TRUE(ForkAndRand(buf1));
143  RAND_bytes(buf3, sizeof(buf3));
144 
145  // All should be different.
146  EXPECT_NE(Bytes(buf1), Bytes(buf2));
147  EXPECT_NE(Bytes(buf2), Bytes(buf3));
148  EXPECT_NE(Bytes(buf1), Bytes(buf3));
149  EXPECT_NE(Bytes(buf1), Bytes(kZeros));
150  EXPECT_NE(Bytes(buf2), Bytes(kZeros));
151  EXPECT_NE(Bytes(buf3), Bytes(kZeros));
152 }
153 #endif // !OPENSSL_WINDOWS && !OPENSSL_IOS &&
154  // !OPENSSL_FUCHSIA && !BORINGSSL_UNSAFE_DETERMINISTIC_MODE
155 
156 #if defined(OPENSSL_THREADS)
157 static void RunConcurrentRands(size_t num_threads) {
158  static const uint8_t kZeros[256] = {0};
159 
160  std::vector<std::array<uint8_t, 256>> bufs(num_threads);
161  std::vector<std::thread> threads(num_threads);
162 
163  for (size_t i = 0; i < num_threads; i++) {
164  threads[i] =
165  std::thread([i, &bufs] { RAND_bytes(bufs[i].data(), bufs[i].size()); });
166  }
167  for (size_t i = 0; i < num_threads; i++) {
168  threads[i].join();
169  }
170 
171  for (size_t i = 0; i < num_threads; i++) {
172  EXPECT_NE(Bytes(bufs[i]), Bytes(kZeros));
173  for (size_t j = i + 1; j < num_threads; j++) {
174  EXPECT_NE(Bytes(bufs[i]), Bytes(bufs[j]));
175  }
176  }
177 }
178 
179 // Test that threads may concurrently draw entropy without tripping TSan.
180 TEST(RandTest, Threads) {
181  constexpr size_t kFewerThreads = 10;
182  constexpr size_t kMoreThreads = 20;
183 
184  // Draw entropy in parallel.
185  RunConcurrentRands(kFewerThreads);
186  // Draw entropy in parallel with higher concurrency than the previous maximum.
187  RunConcurrentRands(kMoreThreads);
188  // Draw entropy in parallel with lower concurrency than the previous maximum.
189  RunConcurrentRands(kFewerThreads);
190 }
191 #endif // OPENSSL_THREADS
192 
193 #if defined(OPENSSL_X86_64) && defined(SUPPORTS_ABI_TEST)
194 TEST(RandTest, RdrandABI) {
195  if (!have_rdrand()) {
196  fprintf(stderr, "rdrand not supported. Skipping.\n");
197  return;
198  }
199 
200  uint8_t buf[32];
207 }
208 #endif // OPENSSL_X86_64 && SUPPORTS_ABI_TEST
gen_build_yaml.out
dictionary out
Definition: src/benchmark/gen_build_yaml.py:24
RAND_bytes
#define RAND_bytes
Definition: boringssl_prefix_symbols.h:2060
Bytes
Definition: boringssl-with-bazel/src/crypto/test/test_util.h:38
absl::str_format_internal::LengthMod::j
@ j
write
#define write
Definition: test-fs.c:47
buf
voidpf void * buf
Definition: bloaty/third_party/zlib/contrib/minizip/ioapi.h:136
status
absl::Status status
Definition: rls.cc:251
uint8_t
unsigned char uint8_t
Definition: stdint-msvc2008.h:78
threads
static uv_thread_t * threads
Definition: threadpool.c:38
CRYPTO_rdrand_multiple8_buf
#define CRYPTO_rdrand_multiple8_buf
Definition: boringssl_prefix_symbols.h:1188
python_utils.port_server.stderr
stderr
Definition: port_server.py:51
CRYPTO_rdrand
#define CRYPTO_rdrand
Definition: boringssl_prefix_symbols.h:1187
ssize_t
intptr_t ssize_t
Definition: win.h:27
EXPECT_NE
#define EXPECT_NE(val1, val2)
Definition: bloaty/third_party/googletest/googletest/include/gtest/gtest.h:2028
close
#define close
Definition: test-fs.c:48
googletest-filter-unittest.child
child
Definition: bloaty/third_party/googletest/googletest/test/googletest-filter-unittest.py:62
data
char data[kBufferLength]
Definition: abseil-cpp/absl/strings/internal/str_format/float_conversion.cc:1006
TEST
TEST(RandTest, NotObviouslyBroken)
Definition: rand_test.cc:46
have_rdrand
OPENSSL_INLINE int have_rdrand(void)
Definition: third_party/boringssl-with-bazel/src/crypto/fipsmodule/rand/internal.h:169
bufs
static uv_buf_t bufs[5]
Definition: benchmark-udp-pummel.c:51
CHECK_ABI_SEH
#define CHECK_ABI_SEH(...)
Definition: abi_test.h:476
ares::byte
unsigned char byte
Definition: ares-test.h:33
read
int read(izstream &zs, T *x, Items items)
Definition: bloaty/third_party/zlib/contrib/iostream2/zstream.h:115
rand.h
ret
UniquePtr< SSL_SESSION > ret
Definition: ssl_x509.cc:1029
num_threads
static volatile int num_threads
Definition: benchmark-thread.c:30
ASSERT_TRUE
#define ASSERT_TRUE(condition)
Definition: bloaty/third_party/googletest/googletest/include/gtest/gtest.h:1973
ForkAndRand
static bool ForkAndRand(bssl::Span< uint8_t > out)
Definition: rand_test.cc:60
buf2
static char buf2[32]
Definition: test-fs.c:127
cpu.h
span.h
size
voidpf void uLong size
Definition: bloaty/third_party/zlib/contrib/minizip/ioapi.h:136
thread
static uv_thread_t thread
Definition: test-async-null-cb.c:29
errno.h
i
uint64_t i
Definition: abseil-cpp/absl/container/btree_benchmark.cc:230


grpc
Author(s):
autogenerated on Thu Mar 13 2025 03:00:59