Skip to content
This repository has been archived by the owner on Apr 22, 2023. It is now read-only.

EntropySource not seeded properly #7338

Closed
mvuksano opened this issue Mar 22, 2014 · 20 comments
Closed

EntropySource not seeded properly #7338

mvuksano opened this issue Mar 22, 2014 · 20 comments

Comments

@mvuksano
Copy link

When using EntropySource PRNG is not seeded properly. It looks like V8 is seeding with bytes of randomness while OpenSSL PRNG requires 32 bytes. http://git.openssl.org/gitweb/?p=openssl.git;a=blob;f=crypto/rand/rand_lcl.h;h=6696b8057bbe71d532d17bb12ca95afe07ae4f8d;hb=refs/heads/master#l115

@indutny
Copy link
Member

indutny commented Mar 22, 2014

Hello!

Thanks for shedding a light on this! Could you please describe a problem with a bit more details?

From what I have just seen:

  1. v8 reads only 64bits of seed
  2. v8 won't even call this function if /dev/urandom is available in system.

@mvuksano
Copy link
Author

Hi,

Thanks for your prompt reply. We started seeing the problem in angular.dart
project. There are multiple people who had this issue (
https://groups.google.com/forum/m/#!msg/angular-dart/hYY8WN_5OQc/jFBcLN4DvMEJ).
I decided to dig a bit more and figure out what's really wrong.

  1. Yes, I understand that. I was thinking of opening an issue there but I
    guess it's better if you guys chase that one as it's really effecting the
    embedder of the EntropySource.
  2. I don't think that's the case. If you look at RandomNumberGenerator
    implementation in V8 (
    https://code.google.com/p/v8/source/browse/trunk/src/utils/random-number-generator.cc#52)
    you will notice that entropy_source is the first case that is handled. If
    it is set, it will be used for seeding, function exits at line 66 before it
    ever gets a chance to get u /dev/urandom

Let me know if there's anything else I can help you with.

On Sat, Mar 22, 2014 at 10:25 PM, Fedor Indutny notifications@github.hscsec.cnwrote:

Hello!

Thanks for shedding a light on this! Could you please describe a problem
with a bit more details?

From what I have just seen:

  1. v8 reads only 64bits of seed
  2. v8 won't even call this function if /dev/urandom is available in
    system.


Reply to this email directly or view it on GitHubhttps://github.com//issues/7338#issuecomment-38348966
.

@indutny
Copy link
Member

indutny commented Mar 22, 2014

I'm not sure what is the problem you are reporting. Is it about that PRNG error that you are seeing? Or is it about size of the seed that v8 is using?

@mvuksano
Copy link
Author

Yes, that's related to PRNG. The problem seems to be that v8 seeds the PRNG
with not enough bits which in turn causes the PRNG error. I believe to fix
this error v8 needs to use larger seed.

On Sat, Mar 22, 2014 at 10:55 PM, Fedor Indutny notifications@github.hscsec.cnwrote:

I'm not sure what is the problem you are reporting. Is it about that PRNG
error that you are seeing? Or is it about size of the seed that v8 is using?


Reply to this email directly or view it on GitHubhttps://github.com//issues/7338#issuecomment-38349531
.

@indutny
Copy link
Member

indutny commented Mar 22, 2014

v8 does not seed PRNG, the openssl seeds it itself. And this error may happen, if the system's /dev/random has not enough entropy itself.

@mvuksano
Copy link
Author

Yeah, you're right. The title of pull request
https://github.com/joyent/node/pull/6253/files mislead me to believe the
call was made to RAND_seed method, but it's actually made to RAND_bytes.

On Sat, Mar 22, 2014 at 11:28 PM, Fedor Indutny notifications@github.hscsec.cnwrote:

v8 does not seed PRNG, the openssl seeds it itself. And this error may
happen, if the system's /dev/random has not enough entropy itself.


Reply to this email directly or view it on GitHubhttps://github.com//issues/7338#issuecomment-38350201
.

@mvuksano
Copy link
Author

The weird thing is that this problem never happened until I updated my node
a few days ago. After that, I get the problem every single time.

I tried downgrading my node to a version before the patch mentioned above
and everything works fine. No issues. As soon as I upgraded again, I
started seeing the same issue.

On Sun, Mar 23, 2014 at 12:03 AM, Marko Vuksanovic <
markovuksanovic@gmail.com> wrote:

Yeah, you're right. The title of pull request
https://github.com/joyent/node/pull/6253/files mislead me to believe the
call was made to RAND_seed method, but it's actually made to RAND_bytes.

On Sat, Mar 22, 2014 at 11:28 PM, Fedor Indutny notifications@github.hscsec.cnwrote:

v8 does not seed PRNG, the openssl seeds it itself. And this error may
happen, if the system's /dev/random has not enough entropy itself.


Reply to this email directly or view it on GitHubhttps://github.com//issues/7338#issuecomment-38350201
.

@indutny
Copy link
Member

indutny commented Mar 22, 2014

Which version are you referring to?

@mvuksano
Copy link
Author

Actually, it's not the version, it's something else causing this problem. I
just realised that if I don't run node long enough (~15mins or so) it
eventually manages to get random bytes but then every subsequent run fails.
I'll just need to place some logging into RAND_poll, RAND_seed and
RAND_bytes and figure out what's happening. Somethings weird here and it
never used to happen up until a few days ago when I did the upgrade. After
I downgraded (v0.10.13) today (I assume I didn't run node long enough) the
first run was fine, then when I upgraded it failed immediately. I
downgraded again and it kept failing. After about another 15 mins I got one
successful run, but all the following runs were a failures.

I actually don't believe (not any more) that this is related to node. It
sounds more like some black magic...

On Sun, Mar 23, 2014 at 12:32 AM, Fedor Indutny notifications@github.hscsec.cnwrote:

Which version are you referring to?


Reply to this email directly or view it on GitHubhttps://github.com//issues/7338#issuecomment-38351514
.

@mvuksano
Copy link
Author

I also checked my /dev/random and /dev/urandom and they seem to work fine...

On Sun, Mar 23, 2014 at 1:13 AM, Marko Vuksanovic <markovuksanovic@gmail.com

wrote:

Actually, it's not the version, it's something else causing this problem.
I just realised that if I don't run node long enough (~15mins or so) it
eventually manages to get random bytes but then every subsequent run fails.
I'll just need to place some logging into RAND_poll, RAND_seed and
RAND_bytes and figure out what's happening. Somethings weird here and it
never used to happen up until a few days ago when I did the upgrade. After
I downgraded (v0.10.13) today (I assume I didn't run node long enough) the
first run was fine, then when I upgraded it failed immediately. I
downgraded again and it kept failing. After about another 15 mins I got one
successful run, but all the following runs were a failures.

I actually don't believe (not any more) that this is related to node. It
sounds more like some black magic...

On Sun, Mar 23, 2014 at 12:32 AM, Fedor Indutny notifications@github.hscsec.cnwrote:

Which version are you referring to?


Reply to this email directly or view it on GitHubhttps://github.com//issues/7338#issuecomment-38351514
.

@mvuksano
Copy link
Author

It might be worth mentioning the system I'm running on:

uname -a > 13.1.0 Darwin Kernel Version 13.1.0: Thu Jan 16 19:40:37 PST
2014; root:xnu-2422.90.20~2/RELEASE_X86_64 x86_64

On Sun, Mar 23, 2014 at 1:18 AM, Marko Vuksanovic <markovuksanovic@gmail.com

wrote:

I also checked my /dev/random and /dev/urandom and they seem to work
fine...

On Sun, Mar 23, 2014 at 1:13 AM, Marko Vuksanovic <
markovuksanovic@gmail.com> wrote:

Actually, it's not the version, it's something else causing this problem.
I just realised that if I don't run node long enough (~15mins or so) it
eventually manages to get random bytes but then every subsequent run fails.
I'll just need to place some logging into RAND_poll, RAND_seed and
RAND_bytes and figure out what's happening. Somethings weird here and it
never used to happen up until a few days ago when I did the upgrade. After
I downgraded (v0.10.13) today (I assume I didn't run node long enough) the
first run was fine, then when I upgraded it failed immediately. I
downgraded again and it kept failing. After about another 15 mins I got one
successful run, but all the following runs were a failures.

I actually don't believe (not any more) that this is related to node. It
sounds more like some black magic...

On Sun, Mar 23, 2014 at 12:32 AM, Fedor Indutny <notifications@github.com

wrote:

Which version are you referring to?


Reply to this email directly or view it on GitHubhttps://github.com//issues/7338#issuecomment-38351514
.

@mvuksano
Copy link
Author

I tried doing some small nodejs program to check if entropy was ok:

var c = require('crypto');
for(var i =0; i < 10000: i++) {
console.log(c.randomBytes(12).toString('UTF-8'))
}

This ran just fine. As soon as I run the angular.dart tests (using karma
and nodejs) I get the error with PRNG not seeded when a call to radnomBytes
is made... This just adds more to the mystery....

On Sun, Mar 23, 2014 at 1:41 AM, Marko Vuksanovic <markovuksanovic@gmail.com

wrote:

It might be worth mentioning the system I'm running on:

uname -a > 13.1.0 Darwin Kernel Version 13.1.0: Thu Jan 16 19:40:37 PST
2014; root:xnu-2422.90.20~2/RELEASE_X86_64 x86_64

On Sun, Mar 23, 2014 at 1:18 AM, Marko Vuksanovic <
markovuksanovic@gmail.com> wrote:

I also checked my /dev/random and /dev/urandom and they seem to work
fine...

On Sun, Mar 23, 2014 at 1:13 AM, Marko Vuksanovic <
markovuksanovic@gmail.com> wrote:

Actually, it's not the version, it's something else causing this
problem. I just realised that if I don't run node long enough (~15mins or
so) it eventually manages to get random bytes but then every subsequent run
fails. I'll just need to place some logging into RAND_poll, RAND_seed and
RAND_bytes and figure out what's happening. Somethings weird here and it
never used to happen up until a few days ago when I did the upgrade. After
I downgraded (v0.10.13) today (I assume I didn't run node long enough) the
first run was fine, then when I upgraded it failed immediately. I
downgraded again and it kept failing. After about another 15 mins I got one
successful run, but all the following runs were a failures.

I actually don't believe (not any more) that this is related to node. It
sounds more like some black magic...

On Sun, Mar 23, 2014 at 12:32 AM, Fedor Indutny <
notifications@github.com> wrote:

Which version are you referring to?


Reply to this email directly or view it on GitHubhttps://github.com//issues/7338#issuecomment-38351514
.

@bnoordhuis
Copy link
Member

It's possible that #6253 is not enough by itself and that node needs to call RAND_poll() at least once during start-up. Does this patch help?

diff --git a/src/node_crypto.cc b/src/node_crypto.cc
index a2b487a..2fbb8d1 100644
--- a/src/node_crypto.cc
+++ b/src/node_crypto.cc
@@ -217,6 +217,7 @@ void ThrowCryptoTypeError(Environment* env, unsigned long err) {


 bool EntropySource(unsigned char* buffer, size_t length) {
+  RAND_poll();
   // 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.

EDIT: When I say "not enough by itself", what I mean is that it's conceivable that another in-process actor consumes the entropy before node gets a chance to pass it on to V8.

@mvuksano
Copy link
Author

@bnoordhuis that could work although I won't be able to verify today. I was also wondering if it makes sense to call RAND_seed instead of RAND_poll?

@bnoordhuis
Copy link
Member

RAND_seed() is only useful if you have random data to seed the PRNG with. I don't think we have that anywhere unless you count the stack. Seems like a risky proposition, that early after start-up. (EDIT: Or in general; the contents of the stack is often highly predictable.)

@mvuksano
Copy link
Author

@bnoordhuis Thanks for the explanation. One other thing that might be worth mentioning, is that I never see the error if I get pseudoRandomBytes instead of randomBytes. Not sure if that piece of information can reveal anything useful about this issue...

@mvuksano mvuksano reopened this Mar 23, 2014
@indutny
Copy link
Member

indutny commented Mar 23, 2014

@markovuksanovic this is expected, those two functions are the same, but the latter one doesn't check if it's entropy pool is seeded properly.

@mvuksano
Copy link
Author

@indutny @bnoordhuis Adding RAND_poll seems to have solved the problem. I'll try to use this custom built version and see if the problem occurs again. I'll update here in a day or two to let you know, but for now it seems that the problem is gone.

@mvuksano
Copy link
Author

@indutny @bnoordhuis Have been using this for a day now and no issues so far...

@indutny
Copy link
Member

indutny commented Mar 25, 2014

Great! @bnoordhuis mind submitting a PR for this?

bnoordhuis added a commit to bnoordhuis/node that referenced this issue Mar 25, 2014
Ensure that OpenSSL has enough entropy (at least 256 bits) for its PRNG.

The entropy pool starts out empty and needs to fill up before the PRNG
can be used securely.

OpenSSL normally fills the pool automatically but not when someone
starts generating random numbers before the pool is full: in that case
OpenSSL keeps lowering the entropy estimate to thwart attackers trying
to guess the initial state of the PRNG.

When that happens, we wait until enough entropy is available, something
that normally should never take longer than a few milliseconds.

Fixes nodejs#7338.
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants