crypto: introduce .setEngine(engine, [flags])

This commit is contained in:
Fedor Indutny 2013-12-14 15:28:07 +04:00
parent a40b463674
commit 92b6417098
6 changed files with 168 additions and 2 deletions

View File

@ -928,7 +928,15 @@
'-lgdi32.lib',
'-luser32.lib',
]
}
},
'defines': [
'DSO_WIN32',
],
}, {
'defines': [
'DSO_DLFCN',
'HAVE_DLFCN_H'
],
}],
['target_arch=="arm"', {
'sources': ['openssl/crypto/armcap.c'],
@ -1028,7 +1036,14 @@
'-luser32.lib',
],
},
}]
}],
[ 'OS in "linux android"', {
'link_settings': {
'libraries': [
'-ldl',
],
},
}],
]
}
],

View File

@ -12,6 +12,30 @@ It also offers a set of wrappers for OpenSSL's hash, hmac, cipher,
decipher, sign and verify methods.
## crypto.setEngine(engine, [flags])
Load and set engine for some/all OpenSSL functions (selected by flags).
`engine` could be either an id or a path to the to the engine's shared library.
`flags` is optional and has `ENGINE_METHOD_ALL` value by default. It could take
one of or mix of following flags (defined in `constants` module):
* `ENGINE_METHOD_RSA`
* `ENGINE_METHOD_DSA`
* `ENGINE_METHOD_DH`
* `ENGINE_METHOD_RAND`
* `ENGINE_METHOD_ECDH`
* `ENGINE_METHOD_ECDSA`
* `ENGINE_METHOD_CIPHERS`
* `ENGINE_METHOD_DIGESTS`
* `ENGINE_METHOD_STORE`
* `ENGINE_METHOD_PKEY_METH`
* `ENGINE_METHOD_PKEY_ASN1_METH`
* `ENGINE_METHOD_ALL`
* `ENGINE_METHOD_NONE`
## crypto.getCiphers()
Returns an array with the names of the supported ciphers.

View File

@ -35,6 +35,7 @@ try {
throw new Error('node.js not compiled with openssl crypto support.');
}
var constants = require('constants');
var stream = require('stream');
var util = require('util');
@ -621,6 +622,21 @@ Certificate.prototype.exportChallenge = function(object, encoding) {
};
exports.setEngine = function setEngine(id, flags) {
if (!util.isString(id))
throw new TypeError('id should be a string');
if (flags && !util.isNumber(flags))
throw new TypeError('flags should be a number, if present');
flags = flags >>> 0;
// Use provided engine for everything by default
if (flags === 0)
flags = constants.ENGINE_METHOD_ALL;
return binding.setEngine(id, flags);
};
exports.randomBytes = randomBytes;
exports.pseudoRandomBytes = pseudoRandomBytes;

View File

@ -34,6 +34,9 @@
#if HAVE_OPENSSL
# include <openssl/ssl.h>
# ifndef OPENSSL_NO_ENGINE
# include <openssl/engine.h>
# endif // !OPENSSL_NO_ENGINE
#endif
namespace node {
@ -875,6 +878,58 @@ void DefineOpenSSLConstants(Handle<Object> target) {
NODE_DEFINE_CONSTANT(target, SSL_OP_TLS_ROLLBACK_BUG);
#endif
# ifndef OPENSSL_NO_ENGINE
# ifdef ENGINE_METHOD_DSA
NODE_DEFINE_CONSTANT(target, ENGINE_METHOD_DSA);
# endif
# ifdef ENGINE_METHOD_DH
NODE_DEFINE_CONSTANT(target, ENGINE_METHOD_DH);
# endif
# ifdef ENGINE_METHOD_RAND
NODE_DEFINE_CONSTANT(target, ENGINE_METHOD_RAND);
# endif
# ifdef ENGINE_METHOD_ECDH
NODE_DEFINE_CONSTANT(target, ENGINE_METHOD_ECDH);
# endif
# ifdef ENGINE_METHOD_ECDSA
NODE_DEFINE_CONSTANT(target, ENGINE_METHOD_ECDSA);
# endif
# ifdef ENGINE_METHOD_CIPHERS
NODE_DEFINE_CONSTANT(target, ENGINE_METHOD_CIPHERS);
# endif
# ifdef ENGINE_METHOD_DIGESTS
NODE_DEFINE_CONSTANT(target, ENGINE_METHOD_DIGESTS);
# endif
# ifdef ENGINE_METHOD_STORE
NODE_DEFINE_CONSTANT(target, ENGINE_METHOD_STORE);
# endif
# ifdef ENGINE_METHOD_PKEY_METHS
NODE_DEFINE_CONSTANT(target, ENGINE_METHOD_PKEY_METHS);
# endif
# ifdef ENGINE_METHOD_PKEY_ASN1_METHS
NODE_DEFINE_CONSTANT(target, ENGINE_METHOD_PKEY_ASN1_METHS);
# endif
# ifdef ENGINE_METHOD_ALL
NODE_DEFINE_CONSTANT(target, ENGINE_METHOD_ALL);
# endif
# ifdef ENGINE_METHOD_NONE
NODE_DEFINE_CONSTANT(target, ENGINE_METHOD_NONE);
# endif
# endif // !OPENSSL_NO_ENGINE
#ifdef OPENSSL_NPN_NEGOTIATED
#define NPN_ENABLED 1
NODE_DEFINE_CONSTANT(target, NPN_ENABLED);

View File

@ -4069,9 +4069,56 @@ void InitCryptoOnce() {
sk_SSL_COMP_zero(comp_methods);
assert(sk_SSL_COMP_num(comp_methods) == 0);
#endif
#ifndef OPENSSL_NO_ENGINE
ERR_load_ENGINE_strings();
ENGINE_load_builtin_engines();
#endif // !OPENSSL_NO_ENGINE
}
#ifndef OPENSSL_NO_ENGINE
void SetEngine(const FunctionCallbackInfo<Value>& args) {
CHECK(args.Length() >= 2 && args[0]->IsString());
unsigned int flags = args[1]->Uint32Value();
ClearErrorOnReturn clear_error_on_return;
(void) &clear_error_on_return; // Silence compiler warning.
const String::Utf8Value engine_id(args[0]);
ENGINE* engine = ENGINE_by_id(*engine_id);
// Engine not found, try loading dynamically
if (engine == NULL) {
engine = ENGINE_by_id("dynamic");
if (engine != NULL) {
if (!ENGINE_ctrl_cmd_string(engine, "SO_PATH", *engine_id, 0) ||
!ENGINE_ctrl_cmd_string(engine, "LOAD", NULL, 0)) {
ENGINE_free(engine);
engine = NULL;
}
}
}
if (engine == NULL) {
int err = ERR_get_error();
if (err == 0) {
char tmp[1024];
snprintf(tmp, sizeof(tmp), "Engine \"%s\" was not found", *engine_id);
return ThrowError(tmp);
} else {
return ThrowCryptoError(err);
}
}
int r = ENGINE_set_default(engine, flags);
ENGINE_free(engine);
if (r == 0)
return ThrowCryptoError(ERR_get_error());
}
#endif // !OPENSSL_NO_ENGINE
// FIXME(bnoordhuis) Handle global init correctly.
void InitCrypto(Handle<Object> target,
Handle<Value> unused,
@ -4090,6 +4137,9 @@ void InitCrypto(Handle<Object> target,
Verify::Initialize(env, target);
Certificate::Initialize(target);
#ifndef OPENSSL_NO_ENGINE
NODE_SET_METHOD(target, "setEngine", SetEngine);
#endif // !OPENSSL_NO_ENGINE
NODE_SET_METHOD(target, "PBKDF2", PBKDF2);
NODE_SET_METHOD(target, "randomBytes", RandomBytes<false>);
NODE_SET_METHOD(target, "pseudoRandomBytes", RandomBytes<true>);

View File

@ -39,6 +39,9 @@
#include "v8.h"
#include <openssl/ssl.h>
#ifndef OPENSSL_NO_ENGINE
# include <openssl/engine.h>
#endif // !OPENSSL_NO_ENGINE
#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/pem.h>
@ -574,6 +577,9 @@ class Certificate : public AsyncWrap {
};
bool EntropySource(unsigned char* buffer, size_t length);
#ifndef OPENSSL_NO_ENGINE
void SetEngine(const v8::FunctionCallbackInfo<v8::Value>& args);
#endif // !OPENSSL_NO_ENGINE
void InitCrypto(v8::Handle<v8::Object> target);
} // namespace crypto