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/internal.h"
25 #include "../test/abi_test.h"
26 #include "../test/test_util.h"
27
28 #if defined(OPENSSL_THREADS)
29 #include <array>
30 #include <thread>
31 #include <vector>
32 #endif
33
34 #if !defined(OPENSSL_WINDOWS)
35 #include <errno.h>
36 #include <sys/types.h>
37 #include <sys/wait.h>
38 #include <unistd.h>
39 #endif
40
41
42 // These tests are, strictly speaking, flaky, but we use large enough buffers
43 // that the probability of failing when we should pass is negligible.
44
TEST(RandTest,NotObviouslyBroken)45 TEST(RandTest, NotObviouslyBroken) {
46 static const uint8_t kZeros[256] = {0};
47
48 uint8_t buf1[256], buf2[256];
49 RAND_bytes(buf1, sizeof(buf1));
50 RAND_bytes(buf2, sizeof(buf2));
51
52 EXPECT_NE(Bytes(buf1), Bytes(buf2));
53 EXPECT_NE(Bytes(buf1), Bytes(kZeros));
54 EXPECT_NE(Bytes(buf2), Bytes(kZeros));
55 }
56
57 #if !defined(OPENSSL_WINDOWS) && !defined(OPENSSL_IOS) && \
58 !defined(OPENSSL_FUCHSIA) && !defined(BORINGSSL_UNSAFE_DETERMINISTIC_MODE)
ForkAndRand(bssl::Span<uint8_t> out)59 static bool ForkAndRand(bssl::Span<uint8_t> out) {
60 int pipefds[2];
61 if (pipe(pipefds) < 0) {
62 perror("pipe");
63 return false;
64 }
65
66 // This is a multi-threaded process, but GTest does not run tests concurrently
67 // and there currently are no threads, so this should be safe.
68 pid_t child = fork();
69 if (child < 0) {
70 perror("fork");
71 close(pipefds[0]);
72 close(pipefds[1]);
73 return false;
74 }
75
76 if (child == 0) {
77 // This is the child. Generate entropy and write it to the parent.
78 close(pipefds[0]);
79 RAND_bytes(out.data(), out.size());
80 while (!out.empty()) {
81 ssize_t ret = write(pipefds[1], out.data(), out.size());
82 if (ret < 0) {
83 if (errno == EINTR) {
84 continue;
85 }
86 perror("write");
87 _exit(1);
88 }
89 out = out.subspan(static_cast<size_t>(ret));
90 }
91 _exit(0);
92 }
93
94 // This is the parent. Read the entropy from the child.
95 close(pipefds[1]);
96 while (!out.empty()) {
97 ssize_t ret = read(pipefds[0], out.data(), out.size());
98 if (ret <= 0) {
99 if (ret == 0) {
100 fprintf(stderr, "Unexpected EOF from child.\n");
101 } else {
102 if (errno == EINTR) {
103 continue;
104 }
105 perror("read");
106 }
107 close(pipefds[0]);
108 return false;
109 }
110 out = out.subspan(static_cast<size_t>(ret));
111 }
112 close(pipefds[0]);
113
114 // Wait for the child to exit.
115 int status;
116 if (waitpid(child, &status, 0) < 0) {
117 perror("waitpid");
118 return false;
119 }
120 if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
121 fprintf(stderr, "Child did not exit cleanly.\n");
122 return false;
123 }
124
125 return true;
126 }
127
TEST(RandTest,Fork)128 TEST(RandTest, Fork) {
129 static const uint8_t kZeros[16] = {0};
130
131 // Draw a little entropy to initialize any internal PRNG buffering.
132 uint8_t byte;
133 RAND_bytes(&byte, 1);
134
135 // Draw entropy in two child processes and the parent process. This test
136 // intentionally uses smaller buffers than the others, to minimize the chance
137 // of sneaking by with a large enough buffer that we've since reseeded from
138 // the OS.
139 uint8_t buf1[16], buf2[16], buf3[16];
140 ASSERT_TRUE(ForkAndRand(buf1));
141 ASSERT_TRUE(ForkAndRand(buf2));
142 RAND_bytes(buf3, sizeof(buf3));
143
144 // All should be different.
145 EXPECT_NE(Bytes(buf1), Bytes(buf2));
146 EXPECT_NE(Bytes(buf2), Bytes(buf3));
147 EXPECT_NE(Bytes(buf1), Bytes(buf3));
148 EXPECT_NE(Bytes(buf1), Bytes(kZeros));
149 EXPECT_NE(Bytes(buf2), Bytes(kZeros));
150 EXPECT_NE(Bytes(buf3), Bytes(kZeros));
151 }
152 #endif // !OPENSSL_WINDOWS && !OPENSSL_IOS &&
153 // !OPENSSL_FUCHSIA && !BORINGSSL_UNSAFE_DETERMINISTIC_MODE
154
155 #if defined(OPENSSL_THREADS)
RunConcurrentRands(size_t num_threads)156 static void RunConcurrentRands(size_t num_threads) {
157 static const uint8_t kZeros[256] = {0};
158
159 std::vector<std::array<uint8_t, 256>> bufs(num_threads);
160 std::vector<std::thread> threads(num_threads);
161
162 for (size_t i = 0; i < num_threads; i++) {
163 threads[i] =
164 std::thread([i, &bufs] { RAND_bytes(bufs[i].data(), bufs[i].size()); });
165 }
166 for (size_t i = 0; i < num_threads; i++) {
167 threads[i].join();
168 }
169
170 for (size_t i = 0; i < num_threads; i++) {
171 EXPECT_NE(Bytes(bufs[i]), Bytes(kZeros));
172 for (size_t j = i + 1; j < num_threads; j++) {
173 EXPECT_NE(Bytes(bufs[i]), Bytes(bufs[j]));
174 }
175 }
176 }
177
178 // Test that threads may concurrently draw entropy without tripping TSan.
TEST(RandTest,Threads)179 TEST(RandTest, Threads) {
180 constexpr size_t kFewerThreads = 10;
181 constexpr size_t kMoreThreads = 20;
182
183 // Draw entropy in parallel.
184 RunConcurrentRands(kFewerThreads);
185 // Draw entropy in parallel with higher concurrency than the previous maximum.
186 RunConcurrentRands(kMoreThreads);
187 // Draw entropy in parallel with lower concurrency than the previous maximum.
188 RunConcurrentRands(kFewerThreads);
189 }
190 #endif // OPENSSL_THREADS
191
192 #if defined(OPENSSL_X86_64) && defined(SUPPORTS_ABI_TEST)
TEST(RandTest,RdrandABI)193 TEST(RandTest, RdrandABI) {
194 if (!have_rdrand()) {
195 fprintf(stderr, "rdrand not supported. Skipping.\n");
196 return;
197 }
198
199 uint8_t buf[32];
200 CHECK_ABI_SEH(CRYPTO_rdrand, buf);
201 CHECK_ABI_SEH(CRYPTO_rdrand_multiple8_buf, nullptr, 0);
202 CHECK_ABI_SEH(CRYPTO_rdrand_multiple8_buf, buf, 8);
203 CHECK_ABI_SEH(CRYPTO_rdrand_multiple8_buf, buf, 16);
204 CHECK_ABI_SEH(CRYPTO_rdrand_multiple8_buf, buf, 24);
205 CHECK_ABI_SEH(CRYPTO_rdrand_multiple8_buf, buf, 32);
206 }
207 #endif // OPENSSL_X86_64 && SUPPORTS_ABI_TEST
208