Merge remote-tracking branch 'origin/v0.10'
authorFedor Indutny <fedor.indutny@gmail.com>
Wed, 26 Mar 2014 07:42:57 +0000 (11:42 +0400)
committerFedor Indutny <fedor.indutny@gmail.com>
Wed, 26 Mar 2014 07:42:57 +0000 (11:42 +0400)
Conflicts:
src/node.cc
src/node_crypto.cc
src/node_crypto.h

1  2 
common.gypi
src/node_crypto.cc

diff --cc common.gypi
Simple merge
@@@ -216,7 -157,41 +216,41 @@@ void ThrowCryptoTypeError(Environment* 
  }
  
  
 -    assert(status >= 0);  // Cannot fail.
+ // 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.  Once the pool is filled, it never dries up again;
+ // its contents is stirred and reused when necessary.
+ //
+ // 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 will have to wait until enough entropy is available.
+ // That should normally never take longer than a few milliseconds.
+ //
+ // OpenSSL draws from /dev/random and /dev/urandom.  While /dev/random may
+ // block pending "true" randomness, /dev/urandom is a CSPRNG that doesn't
+ // block under normal circumstances.
+ //
+ // The only time when /dev/urandom may conceivably block is right after boot,
+ // when the whole system is still low on entropy.  That's not something we can
+ // do anything about.
+ inline void CheckEntropy() {
+   for (;;) {
+     int status = RAND_status();
++    CHECK_GE(status, 0);  // Cannot fail.
+     if (status != 0)
+       break;
+     if (RAND_poll() == 0)  // Give up, RAND_poll() not supported.
+       break;
+   }
+ }
  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.
@@@ -3966,11 -4028,14 +4000,14 @@@ void RandomBytesWork(uv_work_t* work_re
                                           work_req_);
    int r;
  
+   // Ensure that OpenSSL's PRNG is properly seeded.
+   CheckEntropy();
    if (pseudoRandom == true) {
 -    r = RAND_pseudo_bytes(reinterpret_cast<unsigned char*>(req->data_),
 -                          req->size_);
 +    r = RAND_pseudo_bytes(reinterpret_cast<unsigned char*>(req->data()),
 +                          req->size());
    } else {
 -    r = RAND_bytes(reinterpret_cast<unsigned char*>(req->data_), req->size_);
 +    r = RAND_bytes(reinterpret_cast<unsigned char*>(req->data()), req->size());
    }
  
    // RAND_bytes() returns 0 on error. RAND_pseudo_bytes() returns 0 when the