SSL problem on linux/windows



  • I've developed a QML-based application using a C++ component (with QNetwork and QNetworkAccessManager) to exchange data with PHP-based server over HTTP. I'm using the lastest Qt5.12.1 build. This application is supposed to work (and actually works fine) on macOS, iOS, windows and linux. Recently I moved to HTTPS with self-signed certificates. Server-side everything is fine, and I successfully tested some GET and POST using postman. I pushed all the required modifications on the client side, customizing QSslConfiguration (setCaCertificates, setLocalCertificate and setPrivateKey), setting QSsl::TlsV1_0OrLater as protocol and QSslSocket::VerifyNone as peer verify mode. Finally I'm setting this sslConfiguration on every QNetworkRequest. On MacOS (Mojave) everything is working fine: QSslSocket::supportsSsl() returns true and QSslSocket::sslLibraryVersionString() is referring to LibreSSL (which I think it's the default one on that OS).
    Instead I have a lot of problems on windows and linux. In both cases I receive a segfault with and invalid pointer as soon as I send a request, so I guess it's a runtime problem with libraries. Usually I develop on a ubuntu 16.04 machine, I installed the default openssl and libssl packages through apt-get. The above QSslSocket static methods confirm the availability of SSL, with the runtime version "OpenSSL 1.0.2g", while the current Qt version appears to link to "OpenSSL 1.0.2k-fips". I already tried to link exactly the same version (k instead of g) but nothing changed. Just before the segfault, this error is produced:

    Error loading private key, error:140C10F7:SSL routines:SSL_SET_PKEY:unknown certificate type"
    

    (I'm not 100% sure about the "Error loading private key" string since the original error is in Italian, so it's a translation).

    Can you give some hints about this problem? Reading online about similar problems, I saw that a build of Qt from sources with (static) linking of a specific version of SSL libraries is often advised, but I'd like to keep it as the last last chance, since it would be a quite annoying situation to keep updated...
    Thank you in advance.
    Daniele


  • Moderators

    @borghe said in SSL problem on linux/windows:

    Usually I develop on a ubuntu 16.04 machine, I installed the default openssl and libssl packages through apt-get

    you said you are using LibreSSL?

    Instead I have a lot of problems on windows and linux. In both cases I receive a segfault with and invalid pointer as soon as I send a request

    what is the corresponding stacktrace

    A little bit of code would be helpful here.
    How do you apply the certificate exactly?
    How did you create the certificate exactly?

    SSL_SET_PKEY:unknown certificate type soundslike either the certificate format is not supported or is wrongly formatted



  • I mean that on MacOS the default ssl library seems to be LibreSSL. On ubuntu I'm using regular openSSL

    The code I use to load certificates is the following:

    sslConfiguration = QSslConfiguration::defaultConfiguration(); // class member
    
        // CA certificates are replaced with own certificate
        QList<QSslCertificate> caCertificates = QSslCertificate::fromPath(":/ssl/ca-DFM.crt.pem",QSsl::Pem, QRegExp::Wildcard);
        if (caCertificates.size() != 0) {
            sslConfiguration.setCaCertificates(caCertificates);
        }
        else {
            qDebug() << "error loading ca-DFM.crt.pem";
        }
    
        // Client's private key
        QFile filekey(":/ssl/clientDFM.key.pem");
        if (filekey.open(QIODevice::ReadOnly)) {
            QSslKey key(&filekey);
            sslConfiguration.setPrivateKey(key);
        }
        else {
            qDebug() << "error loading clientDFM.key.pem";
        }
    
        // Client's certificate
        QFile filecrt(":/ssl/clientDFM.crt.pem");
        if (filecrt.open(QIODevice::ReadOnly)) {
            QSslCertificate crt(&filecrt);
            sslConfiguration.setLocalCertificate(crt);
        }
        else {
            qDebug() << "error loading clientDFM.key.pem";
        }
    
        sslConfiguration.setProtocol(QSsl::TlsV1_0OrLater);
        sslConfiguration.setPeerVerifyMode(QSslSocket::VerifyNone);
        sslConfiguration.setSslOption(QSsl::SslOptionDisableServerNameIndication, true);
    

    These files are located on a resource file within the project and no error is reported on loading.

    Every request is created as:

    QNetworkRequest networkRequest(serviceURL);
    networkRequest.setSslConfiguration(sslConfiguration);
    

    I use the following openssl commands to create certificates:

    // creation ca root
    openssl req -new -x509 -days 14600 -extensions v3_ca -keyout ca-DFM.key -out ca-DFM.crt
    // generation self signed client
    openssl genrsa -out clientDFM.key 2048
    openssl req -out clientDFM.csr -key clientDFM.key -new 
    openssl x509 -req -in clientDFM.csr -CA ca-DFM.crt -CAkey ca-DFM.key -CAcreateserial -out clientDFM.crt -days 14600
    // conversion
    openssl x509 -in ca-DFM.crt -out ca-DFM.crt.pem -outform PEM
    openssl x509 -in clientDFM.crt -out clientDFM.crt.pem -outform PEM
    openssl rsa -in clientDFM.key -out clientDFM.key.pem -outform PEM
    

    Finally this is the stacktrace I receive:

    *** Error in `/home/borghe/Personale/DFM/DFM_production_ssl/build-DFM-Desktop_Qt_5_12_1_GCC_64bit-Debug/DFM': free(): invalid pointer: 0x00007fffffffaef0 ***
    "Errore di caricamento della chiave privata, error:140C10F7:SSL routines:SSL_SET_PKEY:unknown certificate type"
    ======= Backtrace: =========
    /lib/x86_64-linux-gnu/libc.so.6(+0x777e5)[0x7ffff4cd17e5]
    /lib/x86_64-linux-gnu/libc.so.6(+0x8037a)[0x7ffff4cda37a]
    /lib/x86_64-linux-gnu/libc.so.6(cfree+0x4c)[0x7ffff4cde53c]
    /lib/x86_64-linux-gnu/libcrypto.so.1.0.0(CRYPTO_free+0x1d)[0x7fffdccd10cd]
    /home/borghe/Qt/5.12.1/gcc_64/lib/libQt5Network.so.5(+0x13922f)[0x7ffff639822f]
    /home/borghe/Qt/5.12.1/gcc_64/lib/libQt5Network.so.5(+0x1354de)[0x7ffff63944de]
    /home/borghe/Qt/5.12.1/gcc_64/lib/libQt5Network.so.5(+0x137742)[0x7ffff6396742]
    /home/borghe/Qt/5.12.1/gcc_64/lib/libQt5Network.so.5(_ZN10QSslSocket21startClientEncryptionEv+0x55)[0x7ffff6373da5]
    /home/borghe/Qt/5.12.1/gcc_64/lib/libQt5Network.so.5(+0x1158c8)[0x7ffff63748c8]
    QNetworkReply::UnknownNetworkError :  "Errore di caricamento della chiave privata, error:140C10F7:SSL routines:SSL_SET_PKEY:unknown certificate type"
    /home/borghe/Qt/5.12.1/gcc_64/lib/libQt5Network.so.5(+0x119039)[0x7ffff6378039]
    /home/borghe/Qt/5.12.1/gcc_64/lib/libQt5Core.so.5(_ZN11QMetaObject8activateEP7QObjectiiPPv+0x659)[0x7ffff5b638a9]
    /home/borghe/Qt/5.12.1/gcc_64/lib/libQt5Network.so.5(+0xe53f9)[0x7ffff63443f9]
    /home/borghe/Qt/5.12.1/gcc_64/lib/libQt5Network.so.5(+0xe80c8)[0x7ffff63470c8]
    /home/borghe/Qt/5.12.1/gcc_64/lib/libQt5Network.so.5(+0xf717d)[0x7ffff635617d]
    /home/borghe/Qt/5.12.1/gcc_64/lib/libQt5Core.so.5(_ZN16QCoreApplication15notifyInternal2EP7QObjectP6QEvent+0x108)[0x7ffff5b37e28]
    /home/borghe/Qt/5.12.1/gcc_64/lib/libQt5Core.so.5(+0x2cae28)[0x7ffff5b8fe28]
    /lib/x86_64-linux-gnu/libglib-2.0.so.0(g_main_context_dispatch+0x2a7)[0x7ffff125a197]
    /lib/x86_64-linux-gnu/libglib-2.0.so.0(+0x4a3f0)[0x7ffff125a3f0]
    /lib/x86_64-linux-gnu/libglib-2.0.so.0(g_main_context_iteration+0x2c)[0x7ffff125a49c]
    /home/borghe/Qt/5.12.1/gcc_64/lib/libQt5Core.so.5(_ZN20QEventDispatcherGlib13processEventsE6QFlagsIN10QEventLoop17ProcessEventsFlagEE+0x7b)[0x7ffff5b8f20b]
    /home/borghe/Qt/5.12.1/gcc_64/lib/libQt5Core.so.5(_ZN10QEventLoop4execE6QFlagsINS_17ProcessEventsFlagEE+0xea)[0x7ffff5b3678a]
    /home/borghe/Qt/5.12.1/gcc_64/lib/libQt5Core.so.5(_ZN7QThread4execEv+0x8c)[0x7ffff596987c]
    /home/borghe/Qt/5.12.1/gcc_64/lib/libQt5Core.so.5(+0xa5db3)[0x7ffff596adb3]
    /lib/x86_64-linux-gnu/libpthread.so.0(+0x76ba)[0x7ffff4a446ba]
    /lib/x86_64-linux-gnu/libc.so.6(clone+0x6d)[0x7ffff4d6141d]
    ======= Memory map: ========
    00400000-0077e000 r-xp 00000000 fd:00 4260823                            /home/borghe/Personale/DFM/DFM_production_ssl/build-DFM-Desktop_Qt_5_12_1_GCC_64bit-Debug/DFM
    0097e000-00980000 r--p 0037e000 fd:00 4260823                            /home/borghe/Personale/DFM/DFM_production_ssl/build-DFM-Desktop_Qt_5_12_1_GCC_64bit-Debug/DFM
    00980000-00982000 rw-p 00380000 fd:00 4260823                            /home/borghe/Personale/DFM/DFM_production_ssl/build-DFM-Desktop_Qt_5_12_1_GCC_64bit-Debug/DFM
    00982000-03370000 rw-p 00000000 00:00 0                                  [heap]
    
    etc...
    

    I know what that error sounds like, but if those certificates would be incorrect, they should also not work nor in postman or in MacOS app, which share the same codebase and the same certificate files.


  • Moderators

    @borghe
    i assume the problem might be that you run into the wrong constructors for

    QSslKey key(&filekey)
    QSslCertificate crt(&filecrt);

    try this instead:

    QSslKey key(&filekey, QSsl::Rsa, QSsl::Pem, QSsl::PrivateKey);
    QSslCertificate ca(&filecrt, QSsl::Pem);



  • Great! It works! I still can't understand why the same code works on MacOS without these chages, but that's fine anyway.
    Thank you very much! I owe you a beer.


  • Moderators

    @borghe said in SSL problem on linux/windows:

    I still can't understand why the same code works on MacOS without these chages

    i also can't answer this :)


  • Lifetime Qt Champion

    Hi,

    Not the same backend used. Unless you re-build Qt and force the use of OpenSSL. Qt on macOS uses Apple's SecureTransport framework. OpenSSL on that platform has been deprecated a long time ago.