Skip to content

Commit

Permalink
src: use V8 entropy source if RAND_bytes() != 1
Browse files Browse the repository at this point in the history
RAND_bytes() may return 0 to indicate an error, in which case the buffer
might not have been filled with random data at all. Instead of ignoring
this case, let V8 use its own entropy source. Historically, this used to
be a weak source of entropy, but V8 now implements a proper source even
on Windows. And even if V8's own entropy source turns out to be weak, it
does not matter much: V8's PRNG itself is not cryptographically secure,
so even if it is seeded from a cryptographically secure entropy source,
it does not produce cryptographically secure random numbers.

PR-URL: #44493
Reviewed-By: Rich Trott <rtrott@gmail.com>
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
Reviewed-By: Mohammed Keyvanzadeh <mohammadkeyvanzade94@gmail.com>
  • Loading branch information
tniessen authored Sep 4, 2022
1 parent 4236ef9 commit 7371d33
Show file tree
Hide file tree
Showing 3 changed files with 15 additions and 7 deletions.
14 changes: 10 additions & 4 deletions src/crypto/crypto_util.cc
Original file line number Diff line number Diff line change
Expand Up @@ -76,10 +76,16 @@ void CheckEntropy() {
bool EntropySource(unsigned char* buffer, size_t length) {
// Ensure that OpenSSL's PRNG is properly seeded.
CheckEntropy();
// RAND_bytes() can return 0 to indicate that the entropy data is not truly
// random. That's okay, it's still better than V8's stock source of entropy,
// which is /dev/urandom on UNIX platforms and the current time on Windows.
return RAND_bytes(buffer, length) != -1;
// If RAND_bytes() returns 0 or -1, the data might not be random at all. In
// that case, return false, which causes V8 to use its own entropy source. The
// quality of V8's entropy source depends on multiple factors and we should
// not assume that it is cryptographically secure (even though it often is).
// However, even if RAND_bytes() fails and V8 resorts to its potentially weak
// entropy source, it really does not matter much: V8 only uses the entropy
// source to seed its own PRNG, which itself is not cryptographically secure.
// In other words, even a cryptographically secure entropy source would not
// guarantee cryptographically secure random numbers in V8.
return RAND_bytes(buffer, length) == 1;
}

int PasswordCallback(char* buf, int size, int rwflag, void* u) {
Expand Down
2 changes: 1 addition & 1 deletion src/crypto/crypto_util.h
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ struct MarkPopErrorOnReturn {
void CheckEntropy();

// Generate length bytes of random data. If this returns false, the data
// may not be truly random but it's still generally good enough.
// might not be random at all and should not be used.
bool EntropySource(unsigned char* buffer, size_t length);

int PasswordCallback(char* buf, int size, int rwflag, void* u);
Expand Down
6 changes: 4 additions & 2 deletions src/node.cc
Original file line number Diff line number Diff line change
Expand Up @@ -980,8 +980,10 @@ std::unique_ptr<InitializationResult> InitializeOncePerProcess(
return result;
}

// V8 on Windows doesn't have a good source of entropy. Seed it from
// OpenSSL's pool.
// Seed V8's PRNG from OpenSSL's pool. This is recommended by V8 and a
// potentially better source of randomness than what V8 uses by default, but
// it does not guarantee that pseudo-random values produced by V8 will be
// cryptograhically secure.
V8::SetEntropySource(crypto::EntropySource);
#endif // HAVE_OPENSSL && !defined(OPENSSL_IS_BORINGSSL)
}
Expand Down

0 comments on commit 7371d33

Please sign in to comment.