From b5b60313ca4ac245173a57f170bd4c5344d48288 Mon Sep 17 00:00:00 2001 From: Darshan Sen Date: Sat, 16 Oct 2021 14:46:48 +0530 Subject: [PATCH] test: test `crypto.setEngine()` using an actual engine Signed-off-by: Darshan Sen --- node.gyp | 26 ++++++++ test/fixtures/test_crypto_engine.c | 29 +++++++++ test/parallel/test-crypto-engine.js | 98 ++++++++++++++++++----------- 3 files changed, 116 insertions(+), 37 deletions(-) create mode 100644 test/fixtures/test_crypto_engine.c diff --git a/node.gyp b/node.gyp index 39496fd0507718..da53d0ad3c9635 100644 --- a/node.gyp +++ b/node.gyp @@ -1467,5 +1467,31 @@ }, ] }], # end aix section + ['node_use_openssl=="true"', { + 'targets': [ + { + 'target_name': 'test_crypto_engine', + 'type': 'shared_library', + 'dependencies': ['deps/openssl/openssl.gyp:openssl'], + 'include_dirs': ['deps/openssl/openssl/include'], + 'sources': ['test/fixtures/test_crypto_engine.c'], + 'conditions': [ + ['OS=="mac"', { + 'xcode_settings': { + 'OTHER_CFLAGS': ['-Wno-deprecated-declarations'], + }, + }], + ['OS in "freebsd openbsd netbsd solaris android" or \ + (OS=="linux" and target_arch!="ia32")', { + 'cflags': [ + '-Wno-deprecated-declarations', + '-fPIC', + ], + 'ldflags': ['-fPIC'], + }], + ], + }, # test_crypto_engine + ], # end targets + }], # end node_use_openssl section ], # end conditions block } diff --git a/test/fixtures/test_crypto_engine.c b/test/fixtures/test_crypto_engine.c new file mode 100644 index 00000000000000..9e9fa6da52459e --- /dev/null +++ b/test/fixtures/test_crypto_engine.c @@ -0,0 +1,29 @@ +// Refs: https://www.openssl.org/blog/blog/2015/10/08/engine-building-lesson-1-a-minimum-useless-engine/ + +#include + +#include + +static const char *engine_id = "silly"; +static const char *engine_name = "A silly engine for demonstration purposes"; + +static int bind(ENGINE *e, const char *id) +{ + int ret = 0; + + if (!ENGINE_set_id(e, engine_id)) { + fprintf(stderr, "ENGINE_set_id failed\n"); + goto end; + } + if (!ENGINE_set_name(e, engine_name)) { + printf("ENGINE_set_name failed\n"); + goto end; + } + + ret = 1; + end: + return ret; +} + +IMPLEMENT_DYNAMIC_BIND_FN(bind) +IMPLEMENT_DYNAMIC_CHECK_FN() diff --git a/test/parallel/test-crypto-engine.js b/test/parallel/test-crypto-engine.js index 8b33285b454eef..ce3a405de7190d 100644 --- a/test/parallel/test-crypto-engine.js +++ b/test/parallel/test-crypto-engine.js @@ -1,43 +1,67 @@ 'use strict'; const common = require('../common'); +if (!common.hasCrypto) common.skip('missing crypto'); -if (!common.hasCrypto) - common.skip('missing crypto'); +// This tests crypto.setEngine(). const assert = require('assert'); const crypto = require('crypto'); -const invalidEngineName = 'xxx'; - -assert.throws( - () => crypto.setEngine(true), - { - code: 'ERR_INVALID_ARG_TYPE', - name: 'TypeError', - message: 'The "id" argument must be of type string. Received type boolean' + - ' (true)' - }); - -assert.throws( - () => crypto.setEngine('/path/to/engine', 'notANumber'), - { - code: 'ERR_INVALID_ARG_TYPE', - name: 'TypeError', - message: 'The "flags" argument must be of type number. Received type' + - " string ('notANumber')" - }); - -assert.throws( - () => crypto.setEngine(invalidEngineName), - { - code: 'ERR_CRYPTO_ENGINE_UNKNOWN', - name: 'Error', - message: `Engine "${invalidEngineName}" was not found` - }); - -assert.throws( - () => crypto.setEngine(invalidEngineName, crypto.constants.ENGINE_METHOD_RSA), - { - code: 'ERR_CRYPTO_ENGINE_UNKNOWN', - name: 'Error', - message: `Engine "${invalidEngineName}" was not found` - }); +const fs = require('fs'); +const path = require('path'); + +assert.throws(() => crypto.setEngine(true), /ERR_INVALID_ARG_TYPE/); +assert.throws(() => crypto.setEngine('/path/to/engine', 'notANumber'), + /ERR_INVALID_ARG_TYPE/); + +{ + const invalidEngineName = 'xxx'; + assert.throws(() => crypto.setEngine(invalidEngineName), + /ERR_CRYPTO_ENGINE_UNKNOWN/); + assert.throws(() => crypto.setEngine(invalidEngineName, + crypto.constants.ENGINE_METHOD_RSA), + /ERR_CRYPTO_ENGINE_UNKNOWN/); +} + +crypto.setEngine('dynamic'); +crypto.setEngine('dynamic'); + +crypto.setEngine('dynamic', crypto.constants.ENGINE_METHOD_RSA); +crypto.setEngine('dynamic', crypto.constants.ENGINE_METHOD_RSA); + +{ + const engineName = 'test_crypto_engine'; + let engineLib; + if (common.isWindows) engineLib = `${engineName}.dll`; + else if (common.isAIX) engineLib = `lib${engineName}.a`; + else if (common.isOSX) engineLib = `lib${engineName}.dylib`; + else engineLib = `lib${engineName}.so`; + const execDir = path.dirname(process.execPath); + const enginePath = path.join(execDir, engineLib); + const engineId = path.parse(engineLib).name; + + try { + fs.accessSync(enginePath); + } catch (err) { + console.log(`${execDir}:`); + fs.readdirSync(execDir).forEach((file) => console.log(` ${file}`)); + throw err; + } + + crypto.setEngine(enginePath); + crypto.setEngine(enginePath); + + crypto.setEngine(enginePath, crypto.constants.ENGINE_METHOD_RSA); + crypto.setEngine(enginePath, crypto.constants.ENGINE_METHOD_RSA); + + try { + process.env.OPENSSL_ENGINES = execDir; + + crypto.setEngine(engineId); + crypto.setEngine(engineId); + + crypto.setEngine(engineId, crypto.constants.ENGINE_METHOD_RSA); + crypto.setEngine(engineId, crypto.constants.ENGINE_METHOD_RSA); + } finally { + process.env.OPENSSL_ENGINES = undefined; + } +}