1 /*
2  * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License").
5  * You may not use this file except in compliance with the License.
6  * A copy of the License is located at
7  *
8  *  http://aws.amazon.com/apache2.0
9  *
10  * or in the "license" file accompanying this file. This file is distributed
11  * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
12  * express or implied. See the License for the specific language governing
13  * permissions and limitations under the License.
14  */
15 
16 #include <openssl/engine.h>
17 
18 #include <sys/types.h>
19 #include <sys/stat.h>
20 #include <sys/param.h>
21 #include <unistd.h>
22 #include <pthread.h>
23 #include <limits.h>
24 #include <fcntl.h>
25 #include <string.h>
26 #include <stdint.h>
27 #include <stdlib.h>
28 #include <errno.h>
29 #include <time.h>
30 
31 #include "s2n.h"
32 
33 #if defined(S2N_CPUID_AVAILABLE)
34 #include <cpuid.h>
35 #endif
36 
37 #include "stuffer/s2n_stuffer.h"
38 
39 #include "crypto/s2n_drbg.h"
40 
41 #include "error/s2n_errno.h"
42 
43 #include "utils/s2n_result.h"
44 #include "utils/s2n_safety.h"
45 #include "utils/s2n_random.h"
46 #include "utils/s2n_mem.h"
47 
48 #include <openssl/rand.h>
49 
50 #define ENTROPY_SOURCE "/dev/urandom"
51 
52 /* See https://en.wikipedia.org/wiki/CPUID */
53 #define RDRAND_ECX_FLAG     0x40000000
54 
55 /* One second in nanoseconds */
56 #define ONE_S  INT64_C(1000000000)
57 
58 /* Placeholder value for an uninitialized entropy file descriptor */
59 #define UNINITIALIZED_ENTROPY_FD -1
60 
61 static int entropy_fd = UNINITIALIZED_ENTROPY_FD;
62 
63 static __thread struct s2n_drbg per_thread_private_drbg = {0};
64 static __thread struct s2n_drbg per_thread_public_drbg = {0};
65 
66 static void *zeroed_when_forked_page;
67 static int zero = 0;
68 
69 static __thread void *zero_if_forked_ptr = &zero;
70 #define zero_if_forked (* (int *) zero_if_forked_ptr)
71 
72 static int s2n_rand_init_impl(void);
73 static int s2n_rand_cleanup_impl(void);
74 static int s2n_rand_urandom_impl(void *ptr, uint32_t size);
75 static int s2n_rand_rdrand_impl(void *ptr, uint32_t size);
76 
77 static s2n_rand_init_callback s2n_rand_init_cb = s2n_rand_init_impl;
78 static s2n_rand_cleanup_callback s2n_rand_cleanup_cb = s2n_rand_cleanup_impl;
79 static s2n_rand_seed_callback s2n_rand_seed_cb = s2n_rand_urandom_impl;
80 static s2n_rand_mix_callback s2n_rand_mix_cb = s2n_rand_urandom_impl;
81 
s2n_cpu_supports_rdrand()82 bool s2n_cpu_supports_rdrand() {
83 #if defined(S2N_CPUID_AVAILABLE)
84     uint32_t eax, ebx, ecx, edx;
85     if (!__get_cpuid(1, &eax, &ebx, &ecx, &edx)) {
86         return false;
87     }
88 
89     if (ecx & RDRAND_ECX_FLAG) {
90         return true;
91     }
92 #endif
93     return false;
94 }
95 
s2n_rand_set_callbacks(s2n_rand_init_callback rand_init_callback,s2n_rand_cleanup_callback rand_cleanup_callback,s2n_rand_seed_callback rand_seed_callback,s2n_rand_mix_callback rand_mix_callback)96 int s2n_rand_set_callbacks(s2n_rand_init_callback rand_init_callback,
97                              s2n_rand_cleanup_callback rand_cleanup_callback,
98                              s2n_rand_seed_callback rand_seed_callback,
99                              s2n_rand_mix_callback rand_mix_callback)
100 {
101     POSIX_ENSURE_REF(rand_init_callback);
102     POSIX_ENSURE_REF(rand_cleanup_callback);
103     POSIX_ENSURE_REF(rand_seed_callback);
104     POSIX_ENSURE_REF(rand_mix_callback);
105     s2n_rand_init_cb = rand_init_callback;
106     s2n_rand_cleanup_cb = rand_cleanup_callback;
107     s2n_rand_seed_cb = rand_seed_callback;
108     s2n_rand_mix_cb = rand_mix_callback;
109 
110     return S2N_SUCCESS;
111 }
112 
s2n_get_seed_entropy(struct s2n_blob * blob)113 S2N_RESULT s2n_get_seed_entropy(struct s2n_blob *blob)
114 {
115     RESULT_ENSURE_REF(blob);
116 
117     RESULT_GUARD_POSIX(s2n_rand_seed_cb(blob->data, blob->size));
118 
119     return S2N_RESULT_OK;
120 }
121 
s2n_get_mix_entropy(struct s2n_blob * blob)122 S2N_RESULT s2n_get_mix_entropy(struct s2n_blob *blob)
123 {
124     RESULT_ENSURE_REF(blob);
125 
126     RESULT_GUARD_POSIX(s2n_rand_mix_cb(blob->data, blob->size));
127 
128     return S2N_RESULT_OK;
129 }
130 
s2n_on_fork(void)131 void s2n_on_fork(void)
132 {
133     zero_if_forked = 0;
134 }
135 
s2n_defend_if_forked(void)136 static inline S2N_RESULT s2n_defend_if_forked(void)
137 {
138     uint8_t s2n_public_drbg[] = "s2n public drbg";
139     uint8_t s2n_private_drbg[] = "s2n private drbg";
140     struct s2n_blob public = {.data = s2n_public_drbg,.size = sizeof(s2n_public_drbg) };
141     struct s2n_blob private = {.data = s2n_private_drbg,.size = sizeof(s2n_private_drbg) };
142 
143     if (zero_if_forked == 0) {
144         /* Clean up the old drbg first */
145         RESULT_GUARD(s2n_rand_cleanup_thread());
146         /* Instantiate the new ones */
147         RESULT_GUARD_POSIX(s2n_drbg_instantiate(&per_thread_public_drbg, &public, S2N_AES_128_CTR_NO_DF_PR));
148         RESULT_GUARD_POSIX(s2n_drbg_instantiate(&per_thread_private_drbg, &private, S2N_AES_128_CTR_NO_DF_PR));
149         zero_if_forked_ptr = zeroed_when_forked_page;
150         zero_if_forked = 1;
151     }
152 
153     return S2N_RESULT_OK;
154 }
155 
s2n_get_public_random_data(struct s2n_blob * blob)156 S2N_RESULT s2n_get_public_random_data(struct s2n_blob *blob)
157 {
158     RESULT_GUARD(s2n_defend_if_forked());
159 
160     uint32_t offset = 0;
161     uint32_t remaining = blob->size;
162 
163     while(remaining) {
164         struct s2n_blob slice = { 0 };
165 
166         RESULT_GUARD_POSIX(s2n_blob_slice(blob, &slice, offset, MIN(remaining, S2N_DRBG_GENERATE_LIMIT)));;
167 
168         RESULT_GUARD_POSIX(s2n_drbg_generate(&per_thread_public_drbg, &slice));
169 
170         remaining -= slice.size;
171         offset += slice.size;
172     }
173 
174     return S2N_RESULT_OK;
175 }
176 
s2n_get_private_random_data(struct s2n_blob * blob)177 S2N_RESULT s2n_get_private_random_data(struct s2n_blob *blob)
178 {
179     RESULT_GUARD(s2n_defend_if_forked());
180 
181     uint32_t offset = 0;
182     uint32_t remaining = blob->size;
183 
184     while(remaining) {
185         struct s2n_blob slice = { 0 };
186 
187         RESULT_GUARD_POSIX(s2n_blob_slice(blob, &slice, offset, MIN(remaining, S2N_DRBG_GENERATE_LIMIT)));;
188 
189         RESULT_GUARD_POSIX(s2n_drbg_generate(&per_thread_private_drbg, &slice));
190 
191         remaining -= slice.size;
192         offset += slice.size;
193     }
194 
195     return S2N_RESULT_OK;
196 }
197 
s2n_get_public_random_bytes_used(uint64_t * bytes_used)198 S2N_RESULT s2n_get_public_random_bytes_used(uint64_t *bytes_used)
199 {
200     RESULT_GUARD_POSIX(s2n_drbg_bytes_used(&per_thread_public_drbg, bytes_used));
201     return S2N_RESULT_OK;
202 }
203 
s2n_get_private_random_bytes_used(uint64_t * bytes_used)204 S2N_RESULT s2n_get_private_random_bytes_used(uint64_t *bytes_used)
205 {
206     RESULT_GUARD_POSIX(s2n_drbg_bytes_used(&per_thread_private_drbg, bytes_used));
207     return S2N_RESULT_OK;
208 }
209 
s2n_rand_urandom_impl(void * ptr,uint32_t size)210 static int s2n_rand_urandom_impl(void *ptr, uint32_t size)
211 {
212     POSIX_ENSURE(entropy_fd != UNINITIALIZED_ENTROPY_FD, S2N_ERR_NOT_INITIALIZED);
213 
214     uint8_t *data = ptr;
215     uint32_t n = size;
216     struct timespec sleep_time = {.tv_sec = 0, .tv_nsec = 0 };
217     long backoff = 1;
218 
219     while (n) {
220         errno = 0;
221         int r = read(entropy_fd, data, n);
222         if (r <= 0) {
223             /*
224              * A non-blocking read() on /dev/urandom should "never" fail,
225              * except for EINTR. If it does, briefly pause and use
226              * exponential backoff to avoid creating a tight spinning loop.
227              *
228              * iteration          delay
229              * ---------    -----------------
230              *    1         10          nsec
231              *    2         100         nsec
232              *    3         1,000       nsec
233              *    4         10,000      nsec
234              *    5         100,000     nsec
235              *    6         1,000,000   nsec
236              *    7         10,000,000  nsec
237              *    8         99,999,999  nsec
238              *    9         99,999,999  nsec
239              *    ...
240              */
241             if (errno != EINTR) {
242                 backoff = MIN(backoff * 10, ONE_S - 1);
243                 sleep_time.tv_nsec = backoff;
244                 do {
245                     r = nanosleep(&sleep_time, &sleep_time);
246                 }
247                 while (r != 0);
248             }
249 
250             continue;
251         }
252 
253         data += r;
254         n -= r;
255     }
256 
257     return S2N_SUCCESS;
258 }
259 
260 /*
261  * Return a random number in the range [0, bound)
262  */
s2n_public_random(int64_t bound,uint64_t * output)263 S2N_RESULT s2n_public_random(int64_t bound, uint64_t *output)
264 {
265     uint64_t r;
266 
267     RESULT_ENSURE_GT(bound, 0);
268 
269     while (1) {
270         struct s2n_blob blob = {.data = (void *)&r, sizeof(r) };
271         RESULT_GUARD(s2n_get_public_random_data(&blob));
272 
273         /* Imagine an int was one byte and UINT_MAX was 256. If the
274          * caller asked for s2n_random(129, ...) we'd end up in
275          * trouble. Each number in the range 0...127 would be twice
276          * as likely as 128. That's because r == 0 % 129 -> 0, and
277          * r == 129 % 129 -> 0, but only r == 128 returns 128,
278          * r == 257 is out of range.
279          *
280          * To de-bias the dice, we discard values of r that are higher
281          * that the highest multiple of 'bound' an int can support. If
282          * bound is a uint, then in the worst case we discard 50% - 1 r's.
283          * But since 'bound' is an int and INT_MAX is <= UINT_MAX / 2,
284          * in the worst case we discard 25% - 1 r's.
285          */
286         if (r < (UINT64_MAX - (UINT64_MAX % bound))) {
287             *output = r % bound;
288             return S2N_RESULT_OK;
289         }
290     }
291 }
292 
293 #if S2N_LIBCRYPTO_SUPPORTS_CUSTOM_RAND
294 
s2n_openssl_compat_rand(unsigned char * buf,int num)295 int s2n_openssl_compat_rand(unsigned char *buf, int num)
296 {
297     struct s2n_blob out = {.data = buf,.size = num };
298 
299     if (s2n_result_is_error(s2n_get_private_random_data(&out))) {
300         return 0;
301     }
302     return 1;
303 }
304 
s2n_openssl_compat_status(void)305 int s2n_openssl_compat_status(void)
306 {
307     return 1;
308 }
309 
s2n_openssl_compat_init(ENGINE * unused)310 int s2n_openssl_compat_init(ENGINE * unused)
311 {
312     return 1;
313 }
314 
315 RAND_METHOD s2n_openssl_rand_method = {
316     .seed = NULL,
317     .bytes = s2n_openssl_compat_rand,
318     .cleanup = NULL,
319     .add = NULL,
320     .pseudorand = s2n_openssl_compat_rand,
321     .status = s2n_openssl_compat_status
322 };
323 #endif
324 
s2n_rand_init_impl(void)325 static int s2n_rand_init_impl(void)
326 {
327   OPEN:
328     entropy_fd = open(ENTROPY_SOURCE, O_RDONLY);
329     if (entropy_fd == S2N_FAILURE) {
330         if (errno == EINTR) {
331             goto OPEN;
332         }
333         POSIX_BAIL(S2N_ERR_OPEN_RANDOM);
334     }
335 
336     if (s2n_cpu_supports_rdrand()) {
337        s2n_rand_mix_cb = s2n_rand_rdrand_impl;
338     }
339 
340     return S2N_SUCCESS;
341 }
342 
s2n_rand_init(void)343 S2N_RESULT s2n_rand_init(void)
344 {
345     uint32_t pagesize;
346 
347     RESULT_GUARD_POSIX(s2n_rand_init_cb());
348 
349     pagesize = s2n_mem_get_page_size();
350 
351     /* We need a single-aligned page for our protected memory region */
352     RESULT_ENSURE(posix_memalign(&zeroed_when_forked_page, pagesize, pagesize) == S2N_SUCCESS, S2N_ERR_OPEN_RANDOM);
353     RESULT_ENSURE(zeroed_when_forked_page != NULL, S2N_ERR_OPEN_RANDOM);
354 
355     /* Initialized to zero to ensure that we seed our DRBGs */
356     zero_if_forked = 0;
357 
358     /* INHERIT_ZERO and WIPEONFORK reset a page to all-zeroes when a fork occurs */
359 #if defined(MAP_INHERIT_ZERO)
360     RESULT_ENSURE(minherit(zeroed_when_forked_page, pagesize, MAP_INHERIT_ZERO) != S2N_FAILURE, S2N_ERR_OPEN_RANDOM);
361 #endif
362 
363 #if defined(MADV_WIPEONFORK)
364     RESULT_ENSURE(madvise(zeroed_when_forked_page, pagesize, MADV_WIPEONFORK) == S2N_SUCCESS, S2N_ERR_OPEN_RANDOM);
365 #endif
366 
367     /* For defence in depth */
368     RESULT_ENSURE(pthread_atfork(NULL, NULL, s2n_on_fork) == S2N_SUCCESS, S2N_ERR_OPEN_RANDOM);
369 
370     /* Seed everything */
371     RESULT_GUARD(s2n_defend_if_forked());
372 
373 #if S2N_LIBCRYPTO_SUPPORTS_CUSTOM_RAND
374     /* Create an engine */
375     ENGINE *e = ENGINE_new();
376 
377     RESULT_ENSURE(e != NULL, S2N_ERR_OPEN_RANDOM);
378     RESULT_GUARD_OSSL(ENGINE_set_id(e, "s2n_rand"), S2N_ERR_OPEN_RANDOM);
379     RESULT_GUARD_OSSL(ENGINE_set_name(e, "s2n entropy generator"), S2N_ERR_OPEN_RANDOM);
380     RESULT_GUARD_OSSL(ENGINE_set_flags(e, ENGINE_FLAGS_NO_REGISTER_ALL), S2N_ERR_OPEN_RANDOM);
381     RESULT_GUARD_OSSL(ENGINE_set_init_function(e, s2n_openssl_compat_init), S2N_ERR_OPEN_RANDOM);
382     RESULT_GUARD_OSSL(ENGINE_set_RAND(e, &s2n_openssl_rand_method), S2N_ERR_OPEN_RANDOM);
383     RESULT_GUARD_OSSL(ENGINE_add(e), S2N_ERR_OPEN_RANDOM);
384     RESULT_GUARD_OSSL(ENGINE_free(e) , S2N_ERR_OPEN_RANDOM);
385 
386     /* Use that engine for rand() */
387     e = ENGINE_by_id("s2n_rand");
388     RESULT_ENSURE(e != NULL, S2N_ERR_OPEN_RANDOM);
389     RESULT_GUARD_OSSL(ENGINE_init(e), S2N_ERR_OPEN_RANDOM);
390     RESULT_GUARD_OSSL(ENGINE_set_default(e, ENGINE_METHOD_RAND), S2N_ERR_OPEN_RANDOM);
391     RESULT_GUARD_OSSL(ENGINE_free(e), S2N_ERR_OPEN_RANDOM);
392 #endif
393 
394     return S2N_RESULT_OK;
395 }
396 
s2n_rand_cleanup_impl(void)397 static int s2n_rand_cleanup_impl(void)
398 {
399     POSIX_ENSURE(entropy_fd != UNINITIALIZED_ENTROPY_FD, S2N_ERR_NOT_INITIALIZED);
400 
401     POSIX_GUARD(close(entropy_fd));
402     entropy_fd = UNINITIALIZED_ENTROPY_FD;
403 
404     return S2N_SUCCESS;
405 }
406 
s2n_rand_cleanup(void)407 S2N_RESULT s2n_rand_cleanup(void)
408 {
409     RESULT_GUARD_POSIX(s2n_rand_cleanup_cb());
410 
411 #if S2N_LIBCRYPTO_SUPPORTS_CUSTOM_RAND
412     /* Cleanup our rand ENGINE in libcrypto */
413     ENGINE *rand_engine = ENGINE_by_id("s2n_rand");
414     if (rand_engine) {
415         ENGINE_finish(rand_engine);
416         ENGINE_free(rand_engine);
417         ENGINE_cleanup();
418         RAND_set_rand_engine(NULL);
419         RAND_set_rand_method(NULL);
420     }
421 #endif
422 
423     s2n_rand_init_cb = s2n_rand_init_impl;
424     s2n_rand_cleanup_cb = s2n_rand_cleanup_impl;
425     s2n_rand_seed_cb = s2n_rand_urandom_impl;
426     s2n_rand_mix_cb = s2n_rand_urandom_impl;
427 
428     return S2N_RESULT_OK;
429 }
430 
s2n_rand_cleanup_thread(void)431 S2N_RESULT s2n_rand_cleanup_thread(void)
432 {
433     RESULT_GUARD_POSIX(s2n_drbg_wipe(&per_thread_private_drbg));
434     RESULT_GUARD_POSIX(s2n_drbg_wipe(&per_thread_public_drbg));
435 
436     return S2N_RESULT_OK;
437 }
438 
439 /*
440  * This must only be used for unit tests. Any real use is dangerous and will be overwritten in s2n_defend_if_forked if
441  * it is forked. This was added to support known answer tests that use OpenSSL and s2n_get_private_random_data directly.
442  */
s2n_set_private_drbg_for_test(struct s2n_drbg drbg)443 S2N_RESULT s2n_set_private_drbg_for_test(struct s2n_drbg drbg)
444 {
445     RESULT_ENSURE(s2n_in_unit_test(), S2N_ERR_NOT_IN_UNIT_TEST);
446     RESULT_GUARD_POSIX(s2n_drbg_wipe(&per_thread_private_drbg));
447 
448     per_thread_private_drbg = drbg;
449     return S2N_RESULT_OK;
450 }
451 
452 /*
453  * volatile is important to prevent the compiler from
454  * re-ordering or optimizing the use of RDRAND.
455  */
s2n_rand_rdrand_impl(void * data,uint32_t size)456 static int s2n_rand_rdrand_impl(void *data, uint32_t size)
457 {
458 #if defined(__x86_64__) || defined(__i386__)
459     struct s2n_blob out = { .data = data, .size = size };
460     int space_remaining = 0;
461     struct s2n_stuffer stuffer = {0};
462     union {
463         uint64_t u64;
464 #if defined(__i386__)
465         struct {
466             /* since we check first that we're on intel, we can safely assume little endian. */
467             uint32_t u_low;
468             uint32_t u_high;
469         } i386_fields;
470 #endif /* defined(__i386__) */
471         uint8_t u8[8];
472     } output;
473 
474     POSIX_GUARD(s2n_stuffer_init(&stuffer, &out));
475     while ((space_remaining = s2n_stuffer_space_remaining(&stuffer))) {
476         unsigned char success = 0;
477         output.u64 = 0;
478 
479         for (int tries = 0; tries < 10; tries++) {
480 #if defined(__i386__)
481             /* execute the rdrand instruction, store the result in a general purpose register (it's assigned to
482             * output.i386_fields.u_low). Check the carry bit, which will be set on success. Then clober the register and reset
483             * the carry bit. Due to needing to support an ancient assembler we use the opcode syntax.
484             * the %b1 is to force compilers to use c1 instead of ecx.
485             * Here's a description of how the opcode is encoded:
486             * 0x0fc7 (rdrand)
487             * 0xf0 (store the result in eax).
488             */
489             unsigned char success_high = 0, success_low = 0;
490             __asm__ __volatile__(".byte 0x0f, 0xc7, 0xf0;\n" "setc %b1;\n": "=a"(output.i386_fields.u_low), "=qm"(success_low)
491                                  :
492                                  :"cc");
493 
494             __asm__ __volatile__(".byte 0x0f, 0xc7, 0xf0;\n" "setc %b1;\n": "=a"(output.i386_fields.u_high), "=qm"(success_high)
495                                  :
496                                  :"cc");
497             /* cppcheck-suppress knownConditionTrueFalse */
498             success = success_high & success_low;
499 
500             /* Treat either all 1 or all 0 bits in either the high or low order
501              * bits as failure */
502             if (output.i386_fields.u_low == 0 ||
503                     output.i386_fields.u_low == UINT32_MAX ||
504                     output.i386_fields.u_high == 0 ||
505                     output.i386_fields.u_high == UINT32_MAX) {
506                 success = 0;
507             }
508 #else
509             /* execute the rdrand instruction, store the result in a general purpose register (it's assigned to
510             * output.u64). Check the carry bit, which will be set on success. Then clober the carry bit.
511             * Due to needing to support an ancient assembler we use the opcode syntax.
512             * the %b1 is to force compilers to use c1 instead of ecx.
513             * Here's a description of how the opcode is encoded:
514             * 0x48 (pick a 64-bit register it does more too, but that's all that matters there)
515             * 0x0fc7 (rdrand)
516             * 0xf0 (store the result in rax). */
517             __asm__ __volatile__(".byte 0x48, 0x0f, 0xc7, 0xf0;\n" "setc %b1;\n": "=a"(output.u64), "=qm"(success)
518             :
519             :"cc");
520 #endif /* defined(__i386__) */
521 
522             /* Some AMD CPUs will find that RDRAND "sticks" on all 1s but still reports success.
523              * Some other very old CPUs use all 0s as an error condition while still reporting success.
524              * If we encounter either of these suspicious values (a 1/2^63 chance) we'll treat them as
525              * a failure and generate a new value.
526              *
527              * In the future we could add CPUID checks to detect processors with these known bugs,
528              * however it does not appear worth it. The entropy loss is negligible and the
529              * corresponding likelihood that a healthy CPU generates either of these values is also
530              * negligible (1/2^63). Finally, adding processor specific logic would greatly
531              * increase the complexity and would cause us to "miss" any unknown processors with
532              * similar bugs. */
533             if (output.u64 == UINT64_MAX ||
534                 output.u64 == 0) {
535                 success = 0;
536             }
537 
538             if (success) {
539                 break;
540             }
541         }
542 
543         POSIX_ENSURE(success, S2N_ERR_RDRAND_FAILED);
544 
545         int data_to_fill = MIN(sizeof(output), space_remaining);
546 
547         POSIX_GUARD(s2n_stuffer_write_bytes(&stuffer, output.u8, data_to_fill));
548     }
549 
550     return S2N_SUCCESS;
551 #else
552     POSIX_BAIL(S2N_ERR_UNSUPPORTED_CPU);
553 #endif
554 }
555