我有一个使用 OpenSsl 1.1.1t 的大型 C++ 项目,现在我正在调整它以使用 OpenSsl 3.0.8。
为了解决加载旧 pfx 文件的一些问题,我需要加载旧提供程序。
以下代码在我的本地计算机(Win10)上成功:
OpenSslProviderHandler::OpenSslProviderHandler(IReporting* reporter, OSSL_LIB_CTX* ctx)
{
OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CONFIG, nullptr);
m_defaultProvider = OSSL_PROVIDER_load(ctx, "default");
if (m_defaultProvider == nullptr)
{
reporter->reportCritical(makeSslError(), "Failed to load the default provider");
}
m_legacyProvider = OSSL_PROVIDER_load(ctx, "legacy");
if (m_legacyProvider == nullptr)
{
reporter->reportCritical(makeSslError(), "Failed to load the legacy provider");
}
}
没有记录任何内容。
在测试机器(Win10、Jenkins)上,相同的测试失败。在日志中我可以看到这个严重错误报告:
Failed to load the legacy provider. could not load the shared library (DSO support routines) [asio.ssl:310378599]
然后尝试从 pfx 文件加载私钥失败:“不支持(数字信封例程)[asio.ssl:50856204]”。
在我的本地计算机上,我检查了上面显示的代码是否加载了一些新的 dll,但是执行此代码之前和之后加载的 dll 列表是相同的。
OpenSsl 是由以下脚本构建的:
perl Configure debug-VC-WIN64A no-asm enable-static-engine no-shared no-tests no-nod-module --prefix="%cd%\%INSTALL_PREFIX%" --openssldir="%cd%\x64\Debug" -FS || exit /b 1
perl -i.bak -pe "s/^\s*@\s*$/ @\$(ECHO\)\n/g" makefile || exit /b 1
nmake -k all || exit /b 1
nmake install_sw install_ssldirs || exit /b 1
~~这是我的程序在本地计算机上运行时加载的 dll 列表:~~ 抱歉,这个列表不正确,我误用了“资源监视器”来获取进程加载的库列表。当我注意到我发现legacy.dll已加载时
ADVAPI32.dll 10.0.19041.3693 C:\WINDOWS\System32\ADVAPI32.dll
bcrypt.dll 10.0.19041.3636 C:\WINDOWS\System32\bcrypt.dll
combase.dll 10.0.19041.3636 C:\WINDOWS\System32\combase.dll
CRYPT32.dll 10.0.19041.3636 C:\WINDOWS\System32\CRYPT32.dll
CRYPTBASE.DLL 10.0.19041.3636 C:\WINDOWS\SYSTEM32\CRYPTBASE.DLL
dbgeng.dll 10.0.19041.3636 C:\WINDOWS\SYSTEM32\dbgeng.dll
dbghelp.dll 10.0.19041.3636 C:\WINDOWS\SYSTEM32\dbghelp.dll
dbgmodel.dll 10.0.19041.3636 C:\WINDOWS\SYSTEM32\dbgmodel.dll
DPAPI.DLL 10.0.19041.3636 C:\WINDOWS\SYSTEM32\DPAPI.DLL
GDI32.dll 10.0.19041.3636 C:\WINDOWS\System32\GDI32.dll
gdi32full.dll 10.0.19041.3636 C:\WINDOWS\System32\gdi32full.dll
IMM32.DLL 10.0.19041.3636 C:\WINDOWS\System32\IMM32.DLL
KERNEL32.DLL 10.0.19041.3636 C:\WINDOWS\System32\KERNEL32.DLL
KERNELBASE.dll 10.0.19041.3636 C:\WINDOWS\System32\KERNELBASE.dll
MPR.dll 10.0.19041.3636 C:\WINDOWS\SYSTEM32\MPR.dll
msi.dll 5.0.19041.3636 C:\WINDOWS\SYSTEM32\msi.dll
msvcp_win.dll 10.0.19041.3636 C:\WINDOWS\System32\msvcp_win.dll
msvcrt.dll 7.0.19041.3636 C:\WINDOWS\System32\msvcrt.dll
MSWSOCK.dll 10.0.19041.3636 C:\WINDOWS\SYSTEM32\MSWSOCK.dll
NETAPI32.dll 10.0.19041.3636 C:\WINDOWS\SYSTEM32\NETAPI32.dll
ntdll.dll 10.0.19041.3636 C:\WINDOWS\SYSTEM32\ntdll.dll
ODBC32.dll 10.0.19041.3636 C:\WINDOWS\SYSTEM32\ODBC32.dll
ole32.dll 10.0.19041.3636 C:\WINDOWS\System32\ole32.dll
OLEAUT32.dll 10.0.19041.3636 C:\WINDOWS\System32\OLEAUT32.dll
RPCRT4.dll 10.0.19041.3636 C:\WINDOWS\System32\RPCRT4.dll
sechost.dll 10.0.19041.3636 C:\WINDOWS\System32\sechost.dll
SHELL32.dll 10.0.19041.3636 C:\WINDOWS\System32\SHELL32.dll
SRVCLI.DLL 10.0.19041.3636 C:\WINDOWS\SYSTEM32\SRVCLI.DLL
ucrtbase.dll 10.0.19041.3636 C:\WINDOWS\System32\ucrtbase.dll
USER32.dll 10.0.19041.3636 C:\WINDOWS\System32\USER32.dll
USERENV.dll 10.0.19041.3636 C:\WINDOWS\SYSTEM32\USERENV.dll
VERSION.dll 10.0.19041.3636 C:\WINDOWS\SYSTEM32\VERSION.dll
win32u.dll 10.0.19041.3636 C:\WINDOWS\System32\win32u.dll
WLDAP32.dll 10.0.19041.3636 C:\WINDOWS\System32\WLDAP32.dll
WS2_32.dll 10.0.19041.3636 C:\WINDOWS\System32\WS2_32.dll
XmlLite.dll 10.0.19041.3636 C:\WINDOWS\SYSTEM32\XmlLite.dll
好的,我发现问题了。问题是共享库隐藏在构建 OpenSsl 的地方。正好在路径
<build prefix>\lib\ossl-modules\legacy.dll
。
在我的本地计算机上它正在工作,因为测试是在构建产品的同一台计算机上运行的。
在 Jenkins 上它失败了,因为测试是在测试机器上运行的(多个配置),并且我的产品从构建机器(docker)复制到测试机器(具有所需软件的虚拟机)。复制的内容未覆盖 OpenSsl 构建位置。
现在很长一段时间以来,我一直在寻找如何使遗留提供程序成为 OpenSsl 库的一部分,结果发现您只需向
Configure
步骤添加一个参数:no-module
,整个问题就已经解决了:
perl Configure debug-VC-WIN64A no-asm enable-static-engine no-shared no-tests no-nod-module no-module --prefix="%cd%\%INSTALL_PREFIX%" --openssldir="%cd%\x64\Debug" -FS || exit /b 1
免责声明:
no-nod-module
参数只是我公司某种OpenSsl fork的结果(细节并不重要)。