summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorAnton Gerasimov <agerasimov@twilio.com>2019-08-05 12:03:23 +0200
committerRich Trott <rtrott@gmail.com>2019-09-27 15:50:56 -0700
commitc2ce8d05474c38c503b6ac57e94366421c960762 (patch)
treedef403dc2cec32e1e689023669b23a37f9c03b68 /test
parent3de5eae6dbe503485b95bdeb8bddbd67e4613d59 (diff)
downloadandroid-node-v8-c2ce8d05474c38c503b6ac57e94366421c960762.tar.gz
android-node-v8-c2ce8d05474c38c503b6ac57e94366421c960762.tar.bz2
android-node-v8-c2ce8d05474c38c503b6ac57e94366421c960762.zip
tls: add option for private keys for OpenSSL engines
Add `privateKeyIdentifier` and `privateKeyEngine` options to get private key from an OpenSSL engine in tls.createSecureContext(). PR-URL: https://github.com/nodejs/node/pull/28973 Reviewed-By: Rod Vagg <rod@vagg.org> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Sam Roberts <vieuxtech@gmail.com>
Diffstat (limited to 'test')
-rw-r--r--test/addons/openssl-key-engine/binding.gyp25
-rw-r--r--test/addons/openssl-key-engine/test.js62
-rw-r--r--test/addons/openssl-key-engine/testkeyengine.cc73
-rw-r--r--test/parallel/test-tls-keyengine-invalid-arg-type.js23
-rw-r--r--test/parallel/test-tls-keyengine-unsupported.js34
5 files changed, 217 insertions, 0 deletions
diff --git a/test/addons/openssl-key-engine/binding.gyp b/test/addons/openssl-key-engine/binding.gyp
new file mode 100644
index 0000000000..6f9a8c32c1
--- /dev/null
+++ b/test/addons/openssl-key-engine/binding.gyp
@@ -0,0 +1,25 @@
+{
+ 'targets': [
+ {
+ 'target_name': 'testkeyengine',
+ 'type': 'none',
+ 'includes': ['../common.gypi'],
+ 'conditions': [
+ ['OS=="mac" and '
+ 'node_use_openssl=="true" and '
+ 'node_shared=="false" and '
+ 'node_shared_openssl=="false"', {
+ 'type': 'shared_library',
+ 'sources': [ 'testkeyengine.cc' ],
+ 'product_extension': 'engine',
+ 'include_dirs': ['../../../deps/openssl/openssl/include'],
+ 'link_settings': {
+ 'libraries': [
+ '../../../../out/<(PRODUCT_DIR)/<(openssl_product)'
+ ]
+ },
+ }],
+ ]
+ }
+ ]
+}
diff --git a/test/addons/openssl-key-engine/test.js b/test/addons/openssl-key-engine/test.js
new file mode 100644
index 0000000000..5c93e62636
--- /dev/null
+++ b/test/addons/openssl-key-engine/test.js
@@ -0,0 +1,62 @@
+'use strict';
+const common = require('../../common');
+const fixture = require('../../common/fixtures');
+
+if (!common.hasCrypto)
+ common.skip('missing crypto');
+
+const fs = require('fs');
+const path = require('path');
+
+const engine = path.join(__dirname,
+ `/build/${common.buildType}/testkeyengine.engine`);
+
+if (!fs.existsSync(engine))
+ common.skip('no client cert engine');
+
+const assert = require('assert');
+const https = require('https');
+
+const agentKey = fs.readFileSync(fixture.path('/keys/agent1-key.pem'));
+const agentCert = fs.readFileSync(fixture.path('/keys/agent1-cert.pem'));
+const agentCa = fs.readFileSync(fixture.path('/keys/ca1-cert.pem'));
+
+const serverOptions = {
+ key: agentKey,
+ cert: agentCert,
+ ca: agentCa,
+ requestCert: true,
+ rejectUnauthorized: true
+};
+
+const server = https.createServer(serverOptions, common.mustCall((req, res) => {
+ res.writeHead(200);
+ res.end('hello world');
+})).listen(0, common.localhostIPv4, common.mustCall(() => {
+ const clientOptions = {
+ method: 'GET',
+ host: common.localhostIPv4,
+ port: server.address().port,
+ path: '/test',
+ privateKeyEngine: engine,
+ privateKeyIdentifier: 'dummykey',
+ cert: agentCert,
+ rejectUnauthorized: false, // Prevent failing on self-signed certificates
+ headers: {}
+ };
+
+ const req = https.request(clientOptions, common.mustCall(function(response) {
+ let body = '';
+ response.setEncoding('utf8');
+ response.on('data', function(chunk) {
+ body += chunk;
+ });
+
+ response.on('end', common.mustCall(function() {
+ assert.strictEqual(body, 'hello world');
+ server.close();
+ }));
+ }));
+
+ req.end();
+}));
diff --git a/test/addons/openssl-key-engine/testkeyengine.cc b/test/addons/openssl-key-engine/testkeyengine.cc
new file mode 100644
index 0000000000..78a4fc49a6
--- /dev/null
+++ b/test/addons/openssl-key-engine/testkeyengine.cc
@@ -0,0 +1,73 @@
+#include <assert.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <openssl/engine.h>
+#include <openssl/pem.h>
+
+#include <fstream>
+#include <iterator>
+#include <string>
+
+#ifndef ENGINE_CMD_BASE
+# error did not get engine.h
+#endif
+
+#define TEST_ENGINE_ID "testkeyengine"
+#define TEST_ENGINE_NAME "dummy test key engine"
+
+#define PRIVATE_KEY "test/fixtures/keys/agent1-key.pem"
+
+namespace {
+
+int EngineInit(ENGINE* engine) {
+ return 1;
+}
+
+int EngineFinish(ENGINE* engine) {
+ return 1;
+}
+
+int EngineDestroy(ENGINE* engine) {
+ return 1;
+}
+
+std::string LoadFile(const char* filename) {
+ std::ifstream file(filename);
+ return std::string(std::istreambuf_iterator<char>(file),
+ std::istreambuf_iterator<char>());
+}
+
+static EVP_PKEY* EngineLoadPrivkey(ENGINE* engine, const char* name,
+ UI_METHOD* ui_method, void* callback_data) {
+ if (strcmp(name, "dummykey") == 0) {
+ std::string key = LoadFile(PRIVATE_KEY);
+ BIO* bio = BIO_new_mem_buf(key.data(), key.size());
+ EVP_PKEY* ret = PEM_read_bio_PrivateKey(bio, nullptr, nullptr, nullptr);
+
+ BIO_vfree(bio);
+ if (ret != nullptr) {
+ return ret;
+ }
+ }
+
+ return nullptr;
+}
+
+int bind_fn(ENGINE* engine, const char* id) {
+ ENGINE_set_id(engine, TEST_ENGINE_ID);
+ ENGINE_set_name(engine, TEST_ENGINE_NAME);
+ ENGINE_set_init_function(engine, EngineInit);
+ ENGINE_set_finish_function(engine, EngineFinish);
+ ENGINE_set_destroy_function(engine, EngineDestroy);
+ ENGINE_set_load_privkey_function(engine, EngineLoadPrivkey);
+
+ return 1;
+}
+
+extern "C" {
+ IMPLEMENT_DYNAMIC_CHECK_FN();
+ IMPLEMENT_DYNAMIC_BIND_FN(bind_fn);
+}
+
+} // anonymous namespace
diff --git a/test/parallel/test-tls-keyengine-invalid-arg-type.js b/test/parallel/test-tls-keyengine-invalid-arg-type.js
new file mode 100644
index 0000000000..385841a654
--- /dev/null
+++ b/test/parallel/test-tls-keyengine-invalid-arg-type.js
@@ -0,0 +1,23 @@
+'use strict';
+const common = require('../common');
+
+if (!common.hasCrypto)
+ common.skip('missing crypto');
+
+const tls = require('tls');
+
+common.expectsError(
+ () => {
+ tls.createSecureContext({ privateKeyEngine: 0,
+ privateKeyIdentifier: 'key' });
+ },
+ { code: 'ERR_INVALID_ARG_TYPE',
+ message: / Received type number$/ });
+
+common.expectsError(
+ () => {
+ tls.createSecureContext({ privateKeyEngine: 'engine',
+ privateKeyIdentifier: 0 });
+ },
+ { code: 'ERR_INVALID_ARG_TYPE',
+ message: / Received type number$/ });
diff --git a/test/parallel/test-tls-keyengine-unsupported.js b/test/parallel/test-tls-keyengine-unsupported.js
new file mode 100644
index 0000000000..149fc4dc31
--- /dev/null
+++ b/test/parallel/test-tls-keyengine-unsupported.js
@@ -0,0 +1,34 @@
+// Flags: --expose-internals
+'use strict';
+const common = require('../common');
+
+if (!common.hasCrypto)
+ common.skip('missing crypto');
+
+// Monkey-patch SecureContext
+const { internalBinding } = require('internal/test/binding');
+const binding = internalBinding('crypto');
+const NativeSecureContext = binding.SecureContext;
+
+binding.SecureContext = function() {
+ const rv = new NativeSecureContext();
+ rv.setEngineKey = undefined;
+ return rv;
+};
+
+const tls = require('tls');
+
+{
+ common.expectsError(
+ () => {
+ tls.createSecureContext({
+ privateKeyEngine: 'engine',
+ privateKeyIdentifier: 'key'
+ });
+ },
+ {
+ code: 'ERR_CRYPTO_CUSTOM_ENGINE_NOT_SUPPORTED',
+ message: 'Custom engines not supported by this OpenSSL'
+ }
+ );
+}