pocoproject / poco

The POCO C++ Libraries are powerful cross-platform C++ libraries for building network- and internet-based applications that run on desktop, server, mobile, IoT, and embedded systems.
https://pocoproject.org
Other
8.43k stars 2.17k forks source link

Crypto Exception: Failed to load OpenSSL legacy provider when initializing SSL #4024

Closed jorialand closed 1 year ago

jorialand commented 1 year ago

Hello everyone!

I am stucked with the following issue, when I try to initialize the SSL functionality using Poco's Crypto Poco::Crypto::initializeCrypto();. The issue is that in the machine where I perform the build, it works fine, but in other machines, a Poco::Exception is thrown Crypto Exception: Failed to load OpenSSL legacy provider.

My development environment is the following:

#include <iostream>
//#include <Poco/Net/NetSSL.h>
#include <Poco/Crypto/Crypto.h>
#include <Poco/Exception.h>
#include <string>

int main()
{
    try
    {
        std::cout << "Initializing Poco Ssl." << std::endl;

        Poco::Crypto::initializeCrypto();
        //Poco::Net::initializeSSL();
    }
    catch (const Poco::Exception & e)
    {
        std::cout << "Exception initializing Poco Ssl library." << std::endl;
        std::cout << e.displayText() << std::endl;
    }

    std::string sTmp;
    std::getline(std::cin, sTmp);
}

C:\workcopy\vcpkg>vcpkg list

brotli:x64-windows 1.0.9#5 a generic-purpose lossless compression algorithm... bzip2:x64-windows 1.0.8#4 bzip2 is a freely available, patent free, high-q... bzip2:x64-windows-static 1.0.8#4 bzip2 is a freely available, patent free, high-q... bzip2[tool]:x64-windows Builds bzip2 executable bzip2[tool]:x64-windows-static Builds bzip2 executable curl:x64-windows 8.0.1 A library for transferring data with URLs curl[non-http]:x64-windows Enables protocols beyond HTTP/HTTPS/HTTP2 curl[schannel]:x64-windows SSL support (Secure Channel) curl[ssl]:x64-windows Default SSL backend curl[sspi]:x64-windows SSPI support egl-registry:x64-windows 2022-09-20 the EGL API and Extension Registry expat:x64-windows 2.5.0#3 XML parser library written in C expat:x64-windows-static 2.5.0#3 XML parser library written in C freetype:x64-windows 2.12.1#3 A library to render fonts. freetype[brotli]:x64-windows Support decompression of WOFF2 streams freetype[bzip2]:x64-windows Support bzip2 compressed fonts. freetype[png]:x64-windows Support PNG compressed OpenType embedded bitmaps. freetype[zlib]:x64-windows Use zlib instead of internal library for DEFLATE ftgl:x64-windows 2022-05-18#1 FTGL is a free open source library to enable dev... libpng:x64-windows 1.6.39#1 libpng is a library implementing an interface fo... opengl-registry:x64-windows 2022-09-29#1 the API and Extension registries for the OpenGL ... opengl:x64-windows 2022-12-04#3 Open Graphics Library (OpenGL)[3][4][5] is a cro... openssl:x64-windows 3.1.0#2 OpenSSL is an open source project that provides ... openssl:x64-windows-static 3.1.0#2 OpenSSL is an open source project that provides ... pcre2:x64-windows 10.40#1 Regular Expression pattern matching using the sa... pcre2:x64-windows-static 10.40#1 Regular Expression pattern matching using the sa... poco:x64-windows 1.12.4#4 Modern, powerful open source C++ class libraries... poco:x64-windows-static 1.12.4#4 Modern, powerful open source C++ class libraries... poco[crypto]:x64-windows Crypto support poco[crypto]:x64-windows-static Crypto support poco[netssl]:x64-windows NetSSL support for POCO poco[netssl]:x64-windows-static NetSSL support for POCO sentry-native:x64-windows 0.6.1 Sentry SDK for C, C++ and native applications. sentry-native[backend]:x64-windows Enables the platform-specific backend. sentry-native[transport]:x64-windows Enables the platform-specific network transport. vcpkg-cmake-config:x64-windows 2022-02-06#1 vcpkg-cmake-get-vars:x64-windows 2023-03-02 vcpkg-cmake:x64-windows 2022-12-22 zlib:x64-windows 1.2.13 A compression library zlib:x64-windows-static 1.2.13 A compression library

Thank you very much in advance.

micheleselea commented 1 year ago

try using this:

Poco::Crypto::OpenSSLInitializer openSSLInitializer;
try {
{
        Poco::Path cPath(getApplicationPath());
        cPath.makeDirectory();
        OSSL_PROVIDER_set_default_search_path(NULL, cPath.toString().c_str());
    }
        OSSL_PROVIDER* legacy = NULL;
    OSSL_PROVIDER* deflt = NULL;
    if ((legacy == nullptr) && (OSSL_PROVIDER_available(NULL, "legacy") == 0)) {
        legacy = OSSL_PROVIDER_try_load(NULL, "legacy", 1);
    }
    if (deflt == nullptr) {
        deflt = OSSL_PROVIDER_load(NULL, "default");
    }
}
catch (Poco::Exception& exc) {
}

when you end software you need

if (legacy != NULL) {
        OSSL_PROVIDER_unload(legacy);
        legacy = NULL;
    }
    if (deflt != NULL) {
        OSSL_PROVIDER_unload(deflt);
        deflt = NULL;
    }
jorialand commented 1 year ago

Hello @micheleselea!

Thank you for your suggestion, however, I get the same exception in first line, when I declare the openSSLInitializer.

Furthermore, I have discovered the problem is the application depends on the absolute path to \vcpkg\packages\openssl_x64-windows\bin\legacy.dll, because if i rename the legacy.dll file to _legacy.dll, it throws the same exception, even in the same machine where i perform the build.

I have even tried to manually copy legacy.dll to the same directory as the exectuable, and it doesn't work.

So, how could I configure the project to include this needed dll during the building process?

Thank you again.

micheleselea commented 1 year ago

Ah ok you are using DLL OpenSSL, so I think you have to put that dll in the executable folder

jorialand commented 1 year ago

That’s the problem! If i manually put the dll in executable folder, i still get the same exception.

micheleselea commented 1 year ago

did you try using OSSL_PROVIDER_set_default_search_path setting the correct DLL path? you need to use that before Poco::Crypto::OpenSSLInitializer openSSLInitializer;

jorialand commented 1 year ago

Hello @micheleselea ! Thank you again,

I tried the following and IT WORKED! 👯 👍 Thanks a lot.

BUT what last question. What is the default provider call for? I somehow remove it from your example code and it worked. Now the application consumes the legacy.dll from the executable's path, instead the one from the vcpkg directory, so I am able to distribute my app to others.

int main()
{
        try
        {
                std::cout << "Initializing OpenSsl provider." << std::endl;
            {
                Poco::Path cPath("C:\\workcopy\\PLAYGROUND\\PocoFailedLoadOpenSSL\\x64\\Release\\");
                cPath.makeDirectory();
                OSSL_PROVIDER_set_default_search_path(NULL, cPath.toString().c_str());
            }
            OSSL_PROVIDER* legacy = NULL;
            if ((legacy == nullptr) && (OSSL_PROVIDER_available(NULL, "legacy") == 0))
                legacy = OSSL_PROVIDER_try_load(NULL, "legacy", 1);
        }
        catch (Poco::Exception & e)
        {
            std::cout << "Exception initializing OpenSsl provider." << std::endl;
            std::cout << e.displayText() << std::endl;
        }
        try
        {
            std::cout << "Initializing Poco Ssl." << std::endl;
            Poco::Crypto::OpenSSLInitializer openSSLInitializer;
        }
        catch (const Poco::Exception & e)
        {
            std::cout << "Exception initializing Poco Ssl library." << std::endl;
            std::cout << e.displayText() << std::endl;
        }

    std::string sTmp;
    std::getline(std::cin, sTmp);
}
micheleselea commented 1 year ago

I do not understand what is the default provider, probably it's useless for you and for 99% of applications, I read month ago when I switch from Openssl 1.1.1 to 3.0 that was added legacy and default, but I do not remeber. Anyway good for your app