|
|
@@ -46,8 +46,25 @@
|
|
|
|
|
|
#include "lib/log/util_bug.h"
|
|
|
|
|
|
+#ifdef HAVE_SYS_TYPES_H
|
|
|
+#include <sys/types.h>
|
|
|
+#endif
|
|
|
+#ifdef HAVE_UNISTD_H
|
|
|
+#include <unistd.h>
|
|
|
+#endif
|
|
|
+
|
|
|
#include <string.h>
|
|
|
|
|
|
+#ifdef NOINHERIT_CAN_FAIL
|
|
|
+#define CHECK_PID
|
|
|
+#endif
|
|
|
+
|
|
|
+#ifdef CHECK_PID
|
|
|
+#define PID_FIELD_LEN sizeof(pid_t)
|
|
|
+#else
|
|
|
+#define PID_FIELD_LEN 0
|
|
|
+#endif
|
|
|
+
|
|
|
/* Alias for CRYPTO_FAST_RNG_SEED_LEN to make our code shorter.
|
|
|
*/
|
|
|
#define SEED_LEN (CRYPTO_FAST_RNG_SEED_LEN)
|
|
|
@@ -59,7 +76,7 @@
|
|
|
/* The number of random bytes that we can yield to the user after each
|
|
|
* time we fill a crypto_fast_rng_t's buffer.
|
|
|
*/
|
|
|
-#define BUFLEN (MAPLEN - 2*sizeof(uint16_t) - SEED_LEN)
|
|
|
+#define BUFLEN (MAPLEN - 2*sizeof(uint16_t) - SEED_LEN - PID_FIELD_LEN)
|
|
|
|
|
|
/* The number of buffer refills after which we should fetch more
|
|
|
* entropy from crypto_strongest_rand().
|
|
|
@@ -82,6 +99,11 @@ struct crypto_fast_rng_t {
|
|
|
uint16_t n_till_reseed;
|
|
|
/** How many bytes are remaining in cbuf.bytes? */
|
|
|
uint16_t bytes_left;
|
|
|
+#ifdef CHECK_PID
|
|
|
+ /** Which process owns this fast_rng? If this value is zero, we do not
|
|
|
+ * need to test the owner. */
|
|
|
+ pid_t owner;
|
|
|
+#endif
|
|
|
struct cbuf {
|
|
|
/** The seed (key and IV) that we will use the next time that we refill
|
|
|
* cbuf. */
|
|
|
@@ -130,16 +152,32 @@ crypto_fast_rng_new(void)
|
|
|
crypto_fast_rng_t *
|
|
|
crypto_fast_rng_new_from_seed(const uint8_t *seed)
|
|
|
{
|
|
|
+ unsigned inherit = INHERIT_KEEP;
|
|
|
/* We try to allocate this object as securely as we can, to avoid
|
|
|
* having it get dumped, swapped, or shared after fork.
|
|
|
*/
|
|
|
crypto_fast_rng_t *result = tor_mmap_anonymous(sizeof(*result),
|
|
|
ANONMAP_PRIVATE | ANONMAP_NOINHERIT,
|
|
|
- NULL);
|
|
|
+ &inherit);
|
|
|
memcpy(result->buf.seed, seed, SEED_LEN);
|
|
|
/* Causes an immediate refill once the user asks for data. */
|
|
|
result->bytes_left = 0;
|
|
|
result->n_till_reseed = RESEED_AFTER;
|
|
|
+#ifdef CHECK_PID
|
|
|
+ if (inherit == INHERIT_KEEP) {
|
|
|
+ /* This value will neither be dropped nor zeroed after fork, so we need to
|
|
|
+ * check our pid to make sure we are not sharing it across a fork. This
|
|
|
+ * can be expensive if the pid value isn't cached, sadly.
|
|
|
+ */
|
|
|
+ result->owner = getpid();
|
|
|
+ }
|
|
|
+#elif defined(_WIN32)
|
|
|
+ /* Windows can't fork(), so there's no need to noinherit. */
|
|
|
+#else
|
|
|
+ /* We decided above that noinherit would always do _something_. Assert here
|
|
|
+ * that we were correct. */
|
|
|
+ tor_assert(inherit != INHERIT_KEEP);
|
|
|
+#endif
|
|
|
return result;
|
|
|
}
|
|
|
|
|
|
@@ -211,6 +249,27 @@ static void
|
|
|
crypto_fast_rng_getbytes_impl(crypto_fast_rng_t *rng, uint8_t *out,
|
|
|
const size_t n)
|
|
|
{
|
|
|
+#ifdef CHECK_PID
|
|
|
+ if (rng->owner) {
|
|
|
+ /* Note that we only need to do this check when we have owner set: that
|
|
|
+ * is, when our attempt to block inheriting failed, and the result was
|
|
|
+ * INHERIT_KEEP.
|
|
|
+ *
|
|
|
+ * If the result was INHERIT_DROP, then any attempt to access the rng
|
|
|
+ * memory after forking will crash.
|
|
|
+ *
|
|
|
+ * If the result was INHERIT_ZERO, then forking will set the bytes_left
|
|
|
+ * and n_till_reseed fields to zero. This function will call
|
|
|
+ * crypto_fast_rng_refill(), which will in turn reseed the PRNG.
|
|
|
+ *
|
|
|
+ * So we only need to do this test in the case when mmap_anonymous()
|
|
|
+ * returned INHERIT_KEEP. We avoid doing it needlessly, since getpid() is
|
|
|
+ * often a system call, and that can be slow.
|
|
|
+ */
|
|
|
+ tor_assert(rng->owner == getpid());
|
|
|
+ }
|
|
|
+#endif
|
|
|
+
|
|
|
size_t bytes_to_yield = n;
|
|
|
|
|
|
while (bytes_to_yield) {
|