Dynamically loading the engine(s)¶
The solution includes projects for building both the BCrypt EVP and NCrypt STORE engines as dynamically loadable libraries. This may not always be the preferred mode of operation, depending on the requirements. For leveraging the engine(s) with the OpenSSL commands, dynamic loading is more convenient and does not require any rebuilding of the openssl
binary.
Engine loading mechanisms¶
The dynamically loadable versions of the engine libraries are called engine-bcrypt.dll
and engine-ncrypt.dll
. They can be provided to the OpenSSL libraries via several mechanisms.
Through settings in the OpenSSL configuration file, pointed to through the
OPENSSL_CONF
environment variable or otherwise located in its default location which depends on the OpenSSL installationThrough OpenSSL function calls in code
As command line parameter to OpenSSL commands
Note that the library’s .dll
suffix does not need to be provided. The OpenSSL functions will add that by themselves where needed.
When using the OpenSSL commands, and mostly when using the OpenSSL API directly as well, the OpenSSL functions will search in specific locations to locate the requested engine libraries. This behavior can be modified via different control commands and different engine-related function calls, but typically the following locations will be searched:
The path in the
OPENSSL_ENGINES
environment variable, if it is setThe
engines-1_1
directory under the OpenSSLlib
directory, ifOPENSSL_ENGINES
is not setThe directories found in the
PATH
variableThe working directory
Any path-prefix to the requested engine name will be added when attempting to load it. The option to build the engines as static libraries is currently not provided by any of the Visual Studio projects.
The man page for config - OpenSSL CONF library configuration files contains a section Engine Configuration Module that describes additional mechanisms to dynamically load engines, through configuration as opposed to code.
Verifying the loading with the engine command¶
To verify whether OpenSSL can find and load an engine, the engine command can be leveraged. Keeping in mind the mechanisms for locating the engines outlined above, verifying that the BCrypt engine is available for dynamic loading happens like this:
>openssl engine dynamic -pre SO_PATH:engine-bcrypt -pre LOAD
(dynamic) Dynamic engine loading support
[Success]: SO_PATH:engine-bcrypt
[Success]: LOAD
Loaded: (engine-bcrypt) CryptoAPI: Next Gen (CNG) BCrypt EVP Engine
More functional examples of using the engines with other OpenSSL commands are given in section OpenSSL commands with the engine(s).
Example engine loading code¶
Example code of how to load them can be found in the Test::SetUpTestCase
methods of the BCrypt and NCrypt functional tests, in test_bcrypt.cpp
and test_ncrypt.cpp
. Without checking the return code values (for the sake of brevity):
static const char *ENGINE_NAME = "engine-bcrypt";
ENGINE *e = ENGINE_by_id("dynamic");
ENGINE_ctrl_cmd_string(e, "SO_PATH", ENGINE_NAME, 0);
ENGINE_ctrl_cmd_string(e, "LOAD", NULL, 0);
ENGINE_init(e);
ENGINE_add(e);
// Make the engine's implementations the default implementations
ENGINE_set_default(e, ENGINE_METHOD_ALL));
// Engine's structural refcount has been upped by ENGINE_by_id, lower it
ENGINE_free(e);
For more details on OpenSSL functions to create, manipulate, and use cryptographic modules in the form of ENGINE objects, see the ENGINE interface OpenSSL man page.