Skip to content

Commit

Permalink
crypto: renamed addEntropy to addSystemEntropy, removed RAND_seed call
Browse files Browse the repository at this point in the history
The purpose of this patch is to allow Node applications to proactively
add additional entropy (provided by the OS) to OpenSSL's pool. This is
useful in environments where a running Node process can be cloned
(e.g. VM snapshotting or live migration), resulting in a chance of the
cloned process sharing an entropy pool with the original process.

The new AddSystemEntropy function calls RAND_poll, which will add
entropy using an OS-dependent method. Performance was evaluated at
about 140k ops/sec, but this will vary by OS and hardware.

The AddSystemEntropy function is bound to crypto.addSystemEntropy().

Usage:
var crypto = require('crypto');

// Add entropy from system-supplied source
crypto.addSystemEntropy();
  • Loading branch information
scovetta authored and Michael Scovetta committed Apr 2, 2016
1 parent d3f22a8 commit 7d749eb
Show file tree
Hide file tree
Showing 4 changed files with 17 additions and 31 deletions.
4 changes: 2 additions & 2 deletions doc/api/crypto.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -731,12 +731,12 @@ one of or mix of following flags (defined in `constants` module):
* `ENGINE_METHOD_ALL`
* `ENGINE_METHOD_NONE`

## crypto.addEntropy()
## crypto.addSystemEntropy()

Adds system-generated entropy to entropy pool. Usage:

// sync
crypto.addEntropy();
crypto.addSystemEntropy();

NOTE: This method calls the OpenSSL `RAND_poll` function, which in turn calls
an OS-specific implementation (e.g. `/dev/urandom`, `CryptGenRandom`).
Expand Down
4 changes: 2 additions & 2 deletions lib/crypto.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ try {
var getCiphers = binding.getCiphers;
var getHashes = binding.getHashes;
var getCurves = binding.getCurves;
var addEntropy = binding.addEntropy;
var addSystemEntropy = binding.addSystemEntropy;
} catch (e) {
throw new Error('Node.js is not compiled with openssl crypto support');
}
Expand Down Expand Up @@ -622,7 +622,7 @@ exports.randomBytes = exports.pseudoRandomBytes = randomBytes;

exports.rng = exports.prng = randomBytes;

exports.addEntropy = addEntropy;
exports.addSystemEntropy = addSystemEntropy;

exports.getCiphers = function() {
return filterDuplicates(getCiphers());
Expand Down
22 changes: 5 additions & 17 deletions src/node_crypto.cc
Original file line number Diff line number Diff line change
Expand Up @@ -5354,22 +5354,10 @@ void GetCurves(const FunctionCallbackInfo<Value>& args) {
}


void AddEntropy(const FunctionCallbackInfo<Value>& args) {
Environment* env = Environment::GetCurrent(args);

if (args.Length() == 0) {
// Delegate entropy generation to OpenSSL, which will add
// entropy from system sources.
RAND_poll();
return;
}
// Make sure we got a buffer from the user and use it to
// seed OpenSSL.
THROW_AND_RETURN_IF_NOT_BUFFER(args[0]);
Local<Object> buf_obj = args[0]->ToObject();
const void* buf = Buffer::Data(buf_obj);
size_t buf_length = Buffer::Length(buf_obj);
RAND_seed(buf, buf_length);
void AddSystemEntropy(const FunctionCallbackInfo<Value>& args) {
// Delegate entropy generation to OpenSSL, which will add
// entropy from system sources.
RAND_poll();
}


Expand Down Expand Up @@ -5667,7 +5655,7 @@ void InitCrypto(Local<Object> target,
env->SetMethod(target, "getCiphers", GetCiphers);
env->SetMethod(target, "getHashes", GetHashes);
env->SetMethod(target, "getCurves", GetCurves);
env->SetMethod(target, "addEntropy", AddEntropy);
env->SetMethod(target, "addSystemEntropy", AddSystemEntropy);
env->SetMethod(target, "publicEncrypt",
PublicKeyCipher::Cipher<PublicKeyCipher::kPublic,
EVP_PKEY_encrypt_init,
Expand Down
18 changes: 8 additions & 10 deletions test/parallel/test-crypto-random.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,16 +37,14 @@ process.setMaxListeners(256);
});
});

// crypto.addEntropy takes nothing or an ArrayBuffer
[-1,
undefined,
null,
false,
true,
{}, [], [1]
].forEach(function(value) {
assert.throws(function() { crypto.addEntropy(value); });
});
// Test to make sure addSystemEntropy returns in less than 10 ms.
(function() {
var start = process.hrtime();
crypto.addSystemEntropy();
var duration = process.hrtime(start);
duration = duration[0] * 1e9 + duration[1]; // convert to nanoseconds
assert.ok(duration < 10 * 1e6, 'addSystemEntropy responds in < 10ms');
})();

// assert that the callback is indeed called
function checkCall(cb, desc) {
Expand Down

0 comments on commit 7d749eb

Please sign in to comment.