1

What am I trying to achieve?

I need to create a portable (all-in-one) application, with SSL support.

What is the problem?

So the core problem I am facing is getting SSL support included into my binary/portable app.

A MCVE of the app is simple:

Project .pro file

QT -= gui
QT += network

CONFIG += c++11 console
CONFIG -= app_bundle

SOURCES += \
        main.cpp

INSTALLS += target

Project main.cpp

#include <QCoreApplication>
#include <QSslSocket>

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    qDebug() << "Is SSL Enabled? " << QSslSocket::supportsSsl();
    qDebug() << "SSL Library Build Version (Qt compiled against): " << QSslSocket::sslLibraryBuildVersionString();
    qDebug() << "SSL Library Version String (available locally): " << QSslSocket::sslLibraryVersionString();

    return a.exec();
}

  • Output on my DEV machine:

    Is SSL Enabled?  true
    SSL Library Build Version (Qt compiled against):  "OpenSSL 1.1.1d  10 Sep 2019"
    SSL Library Version String (available locally):  "OpenSSL 1.1.1d  10 Sep 2019"

Info of Dev Machine

    C:\Users\cybex>echo %PATH%
    C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Strawberry\c\bin;C:\Strawberry\perl\site\bin;C:\Strawberry\perl\bin

    C:\Users\cybex>openssl
    WARNING: can't open config file: /z/extlib/_openssl_/ssl/openssl.cnf
    OpenSSL> version
    OpenSSL 1.0.2g  1 Mar 2016

  • Running the same binary on a fresh Windows 10 x86 machine results in:

    Is SSL Enabled?  false
    SSL Library Build Version (Qt compiled against):  "OpenSSL 1.1.1d  10 Sep 2019"
    SSL Library Version String (available locally):  ""

Info of Test Machine (Completely fresh install - Windows 10 x86)

    C:\Users\cybex>echo %PATH%
    C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\
    C:\Users\cybex>openssl
    'openssl' is not recognized as an internal or external command,
    operable program or batch file.

  • Running the same binary on a fresh Windows 7 x64 machine results in:

    Is SSL Enabled?  false
    SSL Library Build Version (Qt compiled against):  "OpenSSL 1.1.1d  10 Sep 2019"
    SSL Library Version String (available locally):  ""

Info of Test Machine (Windows 7 x64 laptop with drivers installed)

    C:\Users\Home>echo %PATH%
    C:\Program Files (x86)\OpenSSL\libs;C:\Program Files (x86)\Intel\iCLS Client\;C:\Program Files\Intel\iCLS Client\;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Program Files (x86)\Intel\OpenCL SDK\2.0\bin\x86;C:\Program Files (x86)\Intel\OpenCL SDK\2.0\bin\x64;C:\Program Files\Intel\WiFi\bin\;C:\Program Files\Common Files\Intel\WirelessCommon\;C:\Program Files\Intel\Intel(R) Management Engine Components\DAL;C:\Program Files\Intel\Intel(R) Management Engine Components\IPT;C:\Program Files (x86)\Intel\Intel(R) Management Engine Components\DAL;C:\Program Files (x86)\Intel\Intel(R) Management Engine Components\IPT;C:\Program Files (x86)\Intel\OpenCL SDK\2.0\bin\x86;C:\Program Files (x86)\Intel\OpenCL SDK\2.0\bin\x64;C:\Program Files (x86)\OpenSSL\libs;C:\Program Files\Intel\WiFi\bin\;C:\Program Files\Common Files\Intel\WirelessCommon\
    C:\Users\Home>openssl
    'openssl' is not recognized as an internal or external command, operable program or batch file.

By look at the above results, I conclude that installing OpenSSL solves the problem. Good, but I want need to have it included in my portable app.

In achieving this, I am required to

  1. Compile Qt statically with OpenSSL support

I have done this with the help of this script adapted from ps1 powershell script found here on Qt's wiki. I made additions for:

  • OpenSSL home $OPENSSL_HOME

  • number of threads $threads, and

  • architecture type $arch to be used.

The configuration is as follows:

cmd /C "configure.bat -static -debug-and-release -platform win32-g++ -prefix $QtDir `
        -qt-zlib -qt-pcre -qt-libpng -qt-libjpeg -qt-freetype -opengl desktop -sql-sqlite -ssl -openssl -I $($OPENSSL_HOME)\include -L$($OPENSSL_HOME)\lib\MinGW`
        -opensource -confirm-license `
        -make libs -nomake tools -nomake examples -nomake tests -v"
cmd /C "mingw32-make -k -j$($threads)"

Note 1:

I am using -openssl and not -openssl-linked. I have tried several variations of builing Qt with both -openssl and -openssl-linked. -openssl-linked could never successfully build, see this post I made as to the reason why.

Note 2:

The only successful static Qt compilation I had working was with -ssl -openssl configuration flags enabled

OpenSSL installation is at

`$OPENSSL_HOME = "C:\OpenSSL-Win32"` 

where I am using the MinGW libraries, found in

`$OPENSSL_HOME = "C:\OpenSSL-Win32\lib\MinGW",`

with the files

Directory: C:\OpenSSL-Win32\lib\MinGW

Mode                LastWriteTime         Length Name
----                -------------         ------ ----
-a----       2019/09/11     18:11        3347286 libcrypto.a
-a----       2019/09/11     18:10         109020 libcrypto.def
-a----       2019/09/11     18:11         385126 libssl.a
-a----       2019/09/11     18:10          14033 libssl.def
  1. Add link project .pro to OpenSSL libraries

I added the OpenSSL libraries to the .pro file (using the precompiled Qt built against OpenSSL 1.1.1d - shown above)

QT -= gui
QT += network

INCLUDEPATH += "C:\OpenSSL-Win32\include"
LIBS += -L"C:\OpenSSL-Win32\lib\MinGW\libssl.a"
LIBS += -L"C:\OpenSSL-Win32\lib\MinGW\libcrypto.a"

CONFIG += c++11 console
CONFIG -= app_bundle

SOURCES += \
        main.cpp

INSTALLS += target

Note 3

The binary size with and without the linked libraries above remains the same size

The LDD output of the binary (on my dev machine) with libraries added above is:

Start-Process -PassThru .\SSL-Test.exe | Get-Process -Module

   Size(K) ModuleName                                         FileName
   ------- ----------                                         --------
      6280 SSL-Test.exe                                       C:\Users\cybex\QtProjects\build-SSL-Test-Desktop_Qt_Op...
      1512 ntdll.dll                                          C:\Windows\SYSTEM32\ntdll.dll
       596 KERNEL32.DLL                                       C:\Windows\system32\KERNEL32.DLL
      1500 KERNELBASE.dll                                     C:\Windows\system32\KERNELBASE.dll

The LDD output of the binary (on my Windows 10 x86 test machine) with libraries added above is:

Start-Process -PassThru .\SSL-Test.exe | Get-Process -Module

   Size(K) ModuleName                                         FileName
   ------- ----------                                         --------
      6280 SSL-Test.exe                                       C:\Users\cybex\Desktop\SSL-Test.exe
      1512 ntdll.dll                                          C:\Windows\SYSTEM32\ntdll.dll
       596 KERNEL32.DLL                                       C:\Windows\system32\KERNEL32.DLL
      1500 KERNELBASE.dll                                     C:\Windows\system32\KERNELBASE.dll

Both SSL info outputs are the same

The output when requesting a SSL connection on Non-Dev machines are

QSslSocket::connectToHostEncrypted: TLS initialization failed

which is the result of the OpenSSL libary not being included.

So basically, adding a static OpenSSL library to the project file does not work or am I doing it incorrectly?

CybeX
  • 2,060
  • 3
  • 48
  • 115
  • Are you sure that the server you are connecting with has a correctly configured ssl certificate? – m7913d Oct 01 '19 at 16:12
  • @m7913d yes. Those problems existed at the start of dev, but were resolved later. They are working fine now. I confirmed by opening firefox and requesting a file downloaded using the https link. No complaints – CybeX Oct 01 '19 at 16:24
  • Have you read this post: https://stackoverflow.com/questions/20843180/is-there-any-way-to-building-static-qt-with-static-openssl? – m7913d Oct 01 '19 at 16:27
  • @m7913d I attempted the `-openssl-linked`, but that ended up giving me another error, take a look https://forum.qt.io/topic/107364/static-compile-qt-5-13-1-with-openssl-1-1-1d-using-mingw-in-windows-10 – CybeX Oct 02 '19 at 07:39
  • What is the question? You want to connect from older openssl to the newest 1.1.1d? Connecting from PC with the same version *1.1.1d - works* - what does that mean? You want to be able to connect via all openssl versions? Perhaps, is the question elsewhere? – tukan Oct 15 '19 at 06:57
  • So this is the problem (rephrased). I need to create a self-contained distributed binary with SSL support. To do this, I need to statically compile Qt with SSL support to access `QSslSocket` libs, etc. In doing so, I have been able to compile it and run an app with SSL support, on my dev machine. When moving the same binary over to new machine with another version of OpenSsl installed, I get the `TLS initialization failed` issue in addition to `QSslSocket::sslLibraryVersionString()` returning `""`, but `QSslSocket::sslLibraryVersionString()` produces `OpenSSL 1.1.1d 10 Sep 2019`. Adding to q. – CybeX Oct 15 '19 at 07:06
  • @tukan see update – CybeX Oct 15 '19 at 07:13
  • I see now, that is much better. One more question. On the PC you are testing it you are getting both returns "" and returns OpenSSL 1.1.1d 10 Sep 2019 simultaneously? One more quesiton is: do you install the application or it is a "portable" one? – tukan Oct 15 '19 at 07:31
  • 1
    @tukan It is portable, a single exe. On my dev PC, I get `OpenSSL 1.1.1d 10 Sep 2019` for both `sslLibraryVersionString` and `sslLibraryBuildVersionString` and SSL support `true`, but on test machines, I get `sslLibraryVersionString` = `""` and `sslLibraryBuildVersionString` = `OpenSSL 1.1.1d 10 Sep 2019` and ssl support `false` – CybeX Oct 15 '19 at 08:07
  • It looks like you are having issues when you create the .exe, are you sure the openssl is included? What does `ldd your_file.exe` return? Do you have an compile output log? – tukan Oct 15 '19 at 14:34
  • @tukan stupid of me to forget this important point. I have also attempted this adding the lib to my project file (see update). This too, had no effect (also the executable size remained the same, with and without the addition of the lib) – CybeX Oct 15 '19 at 14:45
  • @tukan and thank you for taking the trouble to help! – CybeX Oct 15 '19 at 14:46
  • I see your edit but I don't see any `ldd` output. I'm looking for something like the following: https://pastebin.com/1VcBp98d . This is output from my portable *httrack*. If you do not have it please use dependecy walker, which can be downloaded from http://dependencywalker.com/. Try to find the openssl library there. Or directly powershell `Start-Process -PassThru C:\t\putty.exe | Get-Process -Module` – tukan Oct 15 '19 at 15:00
  • @tukan thanks for the help with `ldd`. Was trying to use MinGW's `ld.exe` but it didn't provide any output, nothing :|. In any case, I have updated with the dependencies for each library build (manual entry & Qt's library addition). It appears that no libssl or libcrypto is added...That is odd considering I have those libs added to my project file. I should then ask, should the OpenSSL I am using be in my path and/or the static libs (`*.a` files) also be in the path env variable? – CybeX Oct 15 '19 at 15:29
  • Hard to say because there where changes in the openssl 1.1.1d in the mingw path when building it. I recommend reading *Use Windows installation paths in the mingw builds (CVE-2019-1552)* - https://www.openssl.org/news/secadv/20190730.txt if that would help. It would help if I could try it out. – tukan Oct 15 '19 at 16:08
  • @tukan just out of interest sake, have you ever been able to build Qt statically and include OpenSSL into a all-in-one binary? – CybeX Oct 15 '19 at 16:24
  • Never needed it. – tukan Oct 15 '19 at 16:32
  • Anyways, I would love to help you and I think I can, but I need a mvce (https://stackoverflow.com/help/mcve) as it is hard to follow your question as you don't have any openssl library included. – tukan Oct 16 '19 at 07:33
  • @tukan I will rather post this as a new question, as I have gathered more info on what is causing the problem. Will comment the question link – CybeX Oct 16 '19 at 07:51
  • Well you can completely change your question here, if the information is not valid anymore. – tukan Oct 16 '19 at 08:11
  • @tukan I have updated the post, I hope it provides more info – CybeX Oct 16 '19 at 09:03

2 Answers2

0

OpenSSL Thread Local Storage is predicated by the "library loaded" per Qt source code. Then you need to make sure either the library statically linked with your executable OR accessible through the path.

if (!supportsSsl()) {
    qCWarning(lcSsl, "QSslSocket::connectToHostEncrypted: TLS initialization failed");
    d->setErrorAndEmit(QAbstractSocket::SslInternalError, tr("TLS initialization failed"));
    return;
}

and what about supportsSsl()?

/*!
    \internal

    Does the minimum amount of initialization to determine whether SSL
    is supported or not.
*/

bool QSslSocketPrivate::supportsSsl()
{
    return ensureLibraryLoaded();
}

But that "library loaded" is a bit "deeper" concept per Qt source code here:

bool QSslSocketPrivate::ensureLibraryLoaded()
{
    if (!q_resolveOpenSslSymbols())
        return false;

    const QMutexLocker locker(qt_opensslInitMutex);

    if (!s_libraryLoaded) {
        // Initialize OpenSSL.
        if (q_OPENSSL_init_ssl(0, nullptr) != 1)
            return false;
        q_SSL_load_error_strings();
        q_OpenSSL_add_all_algorithms();

        QSslSocketBackendPrivate::s_indexForSSLExtraData
            = q_CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_SSL, 0L, nullptr, nullptr,
                                        nullptr, nullptr);

        // Initialize OpenSSL's random seed.
        if (!q_RAND_status()) {
            qWarning("Random number generator not seeded, disabling SSL support");
            return false;
        }

        s_libraryLoaded = true;
    }
    return true;
}

As long as this is not a remote debug session, and the answer to this question matters you need to build Qt library in DEBUG mode with symbols (or get ready to use ones for the DEBUG build) and then simply put a breakpoint in this function and find the last detail preventing your Qt application from using OpenSSL.

The answer from the debugger should point to the reason of this "TLS initialization failed".

Alexander V
  • 8,351
  • 4
  • 38
  • 47
  • thanks for the suggestions, I will take a look at what it says and report back with an update to my question, alternatively a solution – CybeX Oct 16 '19 at 20:50
-1

I think you need to install an openSSL on your test machine, can do that from here https://code.google.com/archive/p/openssl-for-windows/downloads

Found in this topic

dejoma
  • 394
  • 1
  • 6
  • 18