Coverage Report

Created: 2026-02-26 07:48

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/qtbase/src/plugins/tls/openssl/qtlsbackend_openssl.cpp
Line
Count
Source
1
// Copyright (C) 2021 The Qt Company Ltd.
2
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
// Qt-Security score:significant reason:default
4
5
#include "qsslsocket_openssl_symbols_p.h"
6
#include "qtlsbackend_openssl_p.h"
7
#include "qtlskey_openssl_p.h"
8
#include "qx509_openssl_p.h"
9
#include "qtls_openssl_p.h"
10
11
#if QT_CONFIG(dtls)
12
#include "qdtls_openssl_p.h"
13
#endif // QT_CONFIG(dtls)
14
15
#include <QtNetwork/private/qsslcipher_p.h>
16
17
#include <QtNetwork/qsslcipher.h>
18
#include <QtNetwork/qssl.h>
19
20
#include <QtCore/qdir.h>
21
#include <QtCore/qdirlisting.h>
22
#include <QtCore/qlist.h>
23
#include <QtCore/qmutex.h>
24
#include <QtCore/qscopeguard.h>
25
#include <QtCore/qset.h>
26
27
#include "qopenssl_p.h"
28
29
#include <algorithm>
30
31
QT_BEGIN_NAMESPACE
32
33
using namespace Qt::StringLiterals;
34
35
#if defined(Q_OS_WIN) || defined(Q_OS_MACOS)
36
constexpr auto DefaultWarningLevel = QtCriticalMsg;
37
#else
38
constexpr auto DefaultWarningLevel = QtDebugMsg;
39
#endif
40
41
Q_LOGGING_CATEGORY(lcTlsBackend, "qt.tlsbackend.ossl", DefaultWarningLevel);
42
43
static void q_loadCiphersForConnection(SSL *connection, QList<QSslCipher> &ciphers,
44
                                       QList<QSslCipher> &defaultCiphers)
45
0
{
46
0
    Q_ASSERT(connection);
47
48
0
    STACK_OF(SSL_CIPHER) *supportedCiphers = q_SSL_get_ciphers(connection);
49
0
    for (int i = 0; i < q_sk_SSL_CIPHER_num(supportedCiphers); ++i) {
50
0
        if (SSL_CIPHER *cipher = q_sk_SSL_CIPHER_value(supportedCiphers, i)) {
51
0
            const auto ciph = QTlsBackendOpenSSL::qt_OpenSSL_cipher_to_QSslCipher(cipher);
52
0
            if (!ciph.isNull()) {
53
                // Unconditionally exclude ADH and AECDH ciphers since they offer no MITM protection
54
0
                if (!ciph.name().toLower().startsWith("adh"_L1) &&
55
0
                    !ciph.name().toLower().startsWith("exp-adh"_L1) &&
56
0
                    !ciph.name().toLower().startsWith("aecdh"_L1)) {
57
0
                    ciphers << ciph;
58
59
0
                    if (ciph.usedBits() >= 128)
60
0
                        defaultCiphers << ciph;
61
0
                }
62
0
            }
63
0
        }
64
0
    }
65
0
}
66
67
int QTlsBackendOpenSSL::s_indexForSSLExtraData = -1;
68
69
QString QTlsBackendOpenSSL::getErrorsFromOpenSsl()
70
0
{
71
0
    QString errorString;
72
0
    char buf[256] = {}; // OpenSSL docs claim both 120 and 256; use the larger.
73
0
    unsigned long errNum;
74
0
    while ((errNum = q_ERR_get_error())) {
75
0
        if (!errorString.isEmpty())
76
0
            errorString.append(", "_L1);
77
0
        q_ERR_error_string_n(errNum, buf, sizeof buf);
78
0
        errorString.append(QLatin1StringView(buf)); // error is ascii according to man ERR_error_string
79
0
    }
80
0
    return errorString;
81
0
}
82
83
void QTlsBackendOpenSSL::logAndClearErrorQueue()
84
0
{
85
0
    const auto errors = getErrorsFromOpenSsl();
86
0
    if (errors.size())
87
0
        qCWarning(lcTlsBackend) << "Discarding errors:" << errors;
88
0
}
89
90
void QTlsBackendOpenSSL::clearErrorQueue()
91
0
{
92
0
    while (q_ERR_get_error())
93
0
        ;
94
0
}
95
96
bool QTlsBackendOpenSSL::ensureLibraryLoaded()
97
0
{
98
0
    static bool libraryLoaded = []() {
99
0
        if (!q_resolveOpenSslSymbols())
100
0
            return false;
101
102
        // Initialize OpenSSL.
103
0
        if (q_OPENSSL_init_ssl(0, nullptr) != 1)
104
0
            return false;
105
106
0
        if (q_OpenSSL_version_num() < 0x10101000L) {
107
0
            qCWarning(lcTlsBackend, "QSslSocket: OpenSSL >= 1.1.1 is required; %s was found instead", q_OpenSSL_version(OPENSSL_VERSION));
108
0
            return false;
109
0
        }
110
111
0
        q_SSL_load_error_strings();
112
0
        q_OpenSSL_add_all_algorithms();
113
114
0
        s_indexForSSLExtraData = q_CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_SSL, 0L, nullptr, nullptr,
115
0
                                                           nullptr, nullptr);
116
117
        // Initialize OpenSSL's random seed.
118
0
        if (!q_RAND_status()) {
119
0
            qWarning("Random number generator not seeded, disabling SSL support");
120
0
            return false;
121
0
        }
122
123
0
        return true;
124
0
    }();
125
126
0
    return libraryLoaded;
127
0
}
128
129
QString QTlsBackendOpenSSL::backendName() const
130
0
{
131
0
    return builtinBackendNames[nameIndexOpenSSL];
132
0
}
133
134
bool QTlsBackendOpenSSL::isValid() const
135
0
{
136
0
    return ensureLibraryLoaded();
137
0
}
138
139
long QTlsBackendOpenSSL::tlsLibraryVersionNumber() const
140
0
{
141
0
    return q_OpenSSL_version_num();
142
0
}
143
144
QString QTlsBackendOpenSSL::tlsLibraryVersionString() const
145
0
{
146
0
    const char *versionString = q_OpenSSL_version(OPENSSL_VERSION);
147
0
    if (!versionString)
148
0
        return QString();
149
150
0
    return QString::fromLatin1(versionString);
151
0
}
152
153
long QTlsBackendOpenSSL::tlsLibraryBuildVersionNumber() const
154
0
{
155
0
    return OPENSSL_VERSION_NUMBER;
156
0
}
157
158
QString QTlsBackendOpenSSL::tlsLibraryBuildVersionString() const
159
0
{
160
    // Using QStringLiteral to store the version string as unicode and
161
    // avoid false positives from Google searching the playstore for old
162
    // SSL versions. See QTBUG-46265
163
0
    return QStringLiteral(OPENSSL_VERSION_TEXT);
164
0
}
165
166
void QTlsBackendOpenSSL::ensureInitialized() const
167
0
{
168
    // Old qsslsocket_openssl calls supportsSsl() (which means
169
    // library found and symbols resolved, this already assured
170
    // by the fact we end up in this function (isValid() returned
171
    // true for the backend, see its code). The qsslsocket_openssl
172
    // proceedes with loading certificate, ciphers and elliptic
173
    // curves.
174
0
    ensureCiphersAndCertsLoaded();
175
0
}
176
177
void QTlsBackendOpenSSL::ensureCiphersAndCertsLoaded() const
178
0
{
179
0
    Q_CONSTINIT static bool initializationStarted = false;
180
0
    Q_CONSTINIT static QAtomicInt initialized = Q_BASIC_ATOMIC_INITIALIZER(0);
181
0
    Q_CONSTINIT static QRecursiveMutex initMutex;
182
183
0
    if (initialized.loadAcquire())
184
0
        return;
185
186
0
    const QMutexLocker locker(&initMutex);
187
188
0
    if (initializationStarted || initialized.loadAcquire())
189
0
        return;
190
191
    // Indicate that the initialization has already started in the current
192
    // thread in case of recursive calls. The atomic variable cannot be used
193
    // for this because it is checked without holding the init mutex.
194
0
    initializationStarted = true;
195
196
0
    auto guard = qScopeGuard([] { initialized.storeRelease(1); });
197
198
0
    resetDefaultCiphers();
199
0
    resetDefaultEllipticCurves();
200
201
0
#if QT_CONFIG(library)
202
    //load symbols needed to receive certificates from system store
203
#if defined(Q_OS_QNX)
204
    QSslSocketPrivate::setRootCertOnDemandLoadingSupported(true);
205
#elif defined(Q_OS_UNIX) && !defined(Q_OS_DARWIN)
206
    // check whether we can enable on-demand root-cert loading (i.e. check whether the sym links are there)
207
0
    const QList<QByteArray> dirs = QSslSocketPrivate::unixRootCertDirectories();
208
0
    const QStringList symLinkFilter{
209
0
        u"[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f].[0-9]"_s};
210
0
    for (const auto &dir : dirs) {
211
0
        QDirListing dirList(QString::fromLatin1(dir), symLinkFilter,
212
0
                            QDirListing::IteratorFlag::FilesOnly);
213
0
        if (dirList.cbegin() != dirList.cend()) { // Not empty
214
0
            QSslSocketPrivate::setRootCertOnDemandLoadingSupported(true);
215
0
            break;
216
0
        }
217
0
    }
218
0
#endif
219
0
#endif // QT_CONFIG(library)
220
    // if on-demand loading was not enabled, load the certs now
221
0
    if (!QSslSocketPrivate::rootCertOnDemandLoadingSupported())
222
0
        setDefaultCaCertificates(systemCaCertificates());
223
#ifdef Q_OS_WIN
224
    //Enabled for fetching additional root certs from windows update on windows.
225
    //This flag is set false by setDefaultCaCertificates() indicating the app uses
226
    //its own cert bundle rather than the system one.
227
    //Same logic that disables the unix on demand cert loading.
228
    //Unlike unix, we do preload the certificates from the cert store.
229
    QSslSocketPrivate::setRootCertOnDemandLoadingSupported(true);
230
#endif
231
0
}
232
233
void QTlsBackendOpenSSL::resetDefaultCiphers()
234
0
{
235
0
    SSL_CTX *myCtx = q_SSL_CTX_new(q_TLS_client_method());
236
    // Note, we assert, not just silently return/bail out early:
237
    // this should never happen and problems with OpenSSL's initialization
238
    // must be caught before this (see supportsSsl()).
239
0
    Q_ASSERT(myCtx);
240
0
    SSL *mySsl = q_SSL_new(myCtx);
241
0
    Q_ASSERT(mySsl);
242
243
0
    QList<QSslCipher> ciphers;
244
0
    QList<QSslCipher> defaultCiphers;
245
246
0
    q_loadCiphersForConnection(mySsl, ciphers, defaultCiphers);
247
248
0
    q_SSL_CTX_free(myCtx);
249
0
    q_SSL_free(mySsl);
250
251
0
    setDefaultSupportedCiphers(ciphers);
252
0
    setDefaultCiphers(defaultCiphers);
253
254
0
#if QT_CONFIG(dtls)
255
0
    ciphers.clear();
256
0
    defaultCiphers.clear();
257
0
    myCtx = q_SSL_CTX_new(q_DTLS_client_method());
258
0
    if (myCtx) {
259
0
        mySsl = q_SSL_new(myCtx);
260
0
        if (mySsl) {
261
0
            q_loadCiphersForConnection(mySsl, ciphers, defaultCiphers);
262
0
            setDefaultDtlsCiphers(defaultCiphers);
263
0
            q_SSL_free(mySsl);
264
0
        }
265
0
        q_SSL_CTX_free(myCtx);
266
0
    }
267
0
#endif // dtls
268
0
}
269
270
QList<QSsl::SslProtocol> QTlsBackendOpenSSL::supportedProtocols() const
271
0
{
272
0
    QList<QSsl::SslProtocol> protocols;
273
274
0
    protocols << QSsl::AnyProtocol;
275
0
    protocols << QSsl::SecureProtocols;
276
0
QT_WARNING_PUSH
277
0
QT_WARNING_DISABLE_DEPRECATED
278
0
    protocols << QSsl::TlsV1_0;
279
0
    protocols << QSsl::TlsV1_0OrLater;
280
0
    protocols << QSsl::TlsV1_1;
281
0
    protocols << QSsl::TlsV1_1OrLater;
282
0
QT_WARNING_POP
283
0
    protocols << QSsl::TlsV1_2;
284
0
    protocols << QSsl::TlsV1_2OrLater;
285
286
0
#ifdef TLS1_3_VERSION
287
0
    protocols << QSsl::TlsV1_3;
288
0
    protocols << QSsl::TlsV1_3OrLater;
289
0
#endif // TLS1_3_VERSION
290
291
0
#if QT_CONFIG(dtls)
292
0
QT_WARNING_PUSH
293
0
QT_WARNING_DISABLE_DEPRECATED
294
0
    protocols << QSsl::DtlsV1_0;
295
0
    protocols << QSsl::DtlsV1_0OrLater;
296
0
QT_WARNING_POP
297
0
    protocols << QSsl::DtlsV1_2;
298
0
    protocols << QSsl::DtlsV1_2OrLater;
299
0
#endif // dtls
300
301
0
    return protocols;
302
0
}
303
304
QList<QSsl::SupportedFeature> QTlsBackendOpenSSL::supportedFeatures() const
305
0
{
306
0
    QList<QSsl::SupportedFeature> features;
307
308
0
    features << QSsl::SupportedFeature::CertificateVerification;
309
310
0
#if !defined(OPENSSL_NO_TLSEXT)
311
0
    features << QSsl::SupportedFeature::ClientSideAlpn;
312
0
    features << QSsl::SupportedFeature::ServerSideAlpn;
313
0
#endif // !OPENSSL_NO_TLSEXT
314
315
0
    features << QSsl::SupportedFeature::Ocsp;
316
0
    features << QSsl::SupportedFeature::Psk;
317
0
    features << QSsl::SupportedFeature::SessionTicket;
318
0
    features << QSsl::SupportedFeature::Alerts;
319
320
0
    return features;
321
0
}
322
323
QList<QSsl::ImplementedClass> QTlsBackendOpenSSL::implementedClasses() const
324
0
{
325
0
    QList<QSsl::ImplementedClass> classes;
326
327
0
    classes << QSsl::ImplementedClass::Key;
328
0
    classes << QSsl::ImplementedClass::Certificate;
329
0
    classes << QSsl::ImplementedClass::Socket;
330
0
#if QT_CONFIG(dtls)
331
0
    classes << QSsl::ImplementedClass::Dtls;
332
0
    classes << QSsl::ImplementedClass::DtlsCookie;
333
0
#endif
334
0
    classes << QSsl::ImplementedClass::EllipticCurve;
335
0
    classes << QSsl::ImplementedClass::DiffieHellman;
336
337
0
    return classes;
338
0
}
339
340
QTlsPrivate::TlsKey *QTlsBackendOpenSSL::createKey() const
341
0
{
342
0
    return new QTlsPrivate::TlsKeyOpenSSL;
343
0
}
344
345
QTlsPrivate::X509Certificate *QTlsBackendOpenSSL::createCertificate() const
346
0
{
347
0
    return new QTlsPrivate::X509CertificateOpenSSL;
348
0
}
349
350
namespace QTlsPrivate {
351
352
#ifdef Q_OS_ANDROID
353
QList<QByteArray> fetchSslCertificateData();
354
#endif
355
356
QList<QSslCertificate> systemCaCertificates();
357
358
#ifndef Q_OS_DARWIN
359
QList<QSslCertificate> systemCaCertificates()
360
0
{
361
#ifdef QSSLSOCKET_DEBUG
362
    QElapsedTimer timer;
363
    timer.start();
364
#endif
365
0
    QList<QSslCertificate> systemCerts;
366
#if defined(Q_OS_WIN)
367
    HCERTSTORE hSystemStore;
368
    hSystemStore =
369
            CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
370
                          CERT_STORE_READONLY_FLAG | CERT_SYSTEM_STORE_CURRENT_USER, L"ROOT");
371
    if (hSystemStore) {
372
        PCCERT_CONTEXT pc = nullptr;
373
        while (1) {
374
            pc = CertFindCertificateInStore(hSystemStore, X509_ASN_ENCODING, 0, CERT_FIND_ANY, nullptr, pc);
375
            if (!pc)
376
                break;
377
            QByteArray der(reinterpret_cast<const char *>(pc->pbCertEncoded),
378
                            static_cast<int>(pc->cbCertEncoded));
379
            QSslCertificate cert(der, QSsl::Der);
380
            systemCerts.append(cert);
381
        }
382
        CertCloseStore(hSystemStore, 0);
383
    }
384
#elif defined(Q_OS_ANDROID)
385
    const QList<QByteArray> certData = fetchSslCertificateData();
386
    for (auto certDatum : certData)
387
        systemCerts.append(QSslCertificate::fromData(certDatum, QSsl::Der));
388
#elif defined(Q_OS_UNIX)
389
    {
390
0
        const QList<QByteArray> directories = QSslSocketPrivate::unixRootCertDirectories();
391
0
        QSet<QString> certFiles = {
392
0
            QStringLiteral("/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem"), // Red Hat 2013+
393
0
            QStringLiteral("/etc/pki/tls/certs/ca-bundle.crt"), // Red Hat older, Mandriva
394
            QStringLiteral("/usr/local/share/certs/ca-root-nss.crt") // FreeBSD's ca_root_nss
395
0
        };
396
397
0
        static const size_t extLen = strlen(".pem"); // or strlen(".crt")
398
0
        auto hasMatchingExtension = [](const QString &fileName) {
399
0
            if (size_t(fileName.size()) < extLen + 1)
400
0
                return false;
401
0
            auto ext = QStringView{fileName}.last(extLen);
402
0
            return ext == ".pem"_L1 || ext == ".crt"_L1;
403
0
        };
404
405
0
        using F = QDirListing::IteratorFlag;
406
0
        constexpr auto flags = F::FilesOnly | F::ResolveSymlinks; // Files and symlinks to files
407
0
        for (const QByteArray &directory : directories) {
408
0
            for (const auto &dirEntry : QDirListing(QFile::decodeName(directory), flags)) {
409
                // use canonical path here to not load the same certificate twice if symlinked
410
0
                if (hasMatchingExtension(dirEntry.fileName())) {
411
0
                    QString canonicalPath = dirEntry.canonicalFilePath();
412
                    // skip broken symlinks to not end up adding "" to the list which will then
413
                    // just be rejected by `QSslCertificate::fromFile`
414
0
                    if (!canonicalPath.isEmpty())
415
0
                        certFiles.insert(canonicalPath);
416
0
                }
417
0
            }
418
0
        }
419
0
        for (const QString& file : std::as_const(certFiles))
420
0
            systemCerts.append(QSslCertificate::fromFile(file, QSsl::Pem));
421
0
    }
422
0
#endif // platform
423
#ifdef QSSLSOCKET_DEBUG
424
    qCDebug(lcTlsBackend) << "systemCaCertificates retrieval time " << timer.elapsed() << "ms";
425
    qCDebug(lcTlsBackend) << "imported " << systemCerts.count() << " certificates";
426
#endif
427
428
0
    return systemCerts;
429
0
}
430
#endif // !Q_OS_DARWIN
431
} // namespace QTlsPrivate
432
433
QList<QSslCertificate> QTlsBackendOpenSSL::systemCaCertificates() const
434
0
{
435
0
    return QTlsPrivate::systemCaCertificates();
436
0
}
437
438
QTlsPrivate::DtlsCookieVerifier *QTlsBackendOpenSSL::createDtlsCookieVerifier() const
439
0
{
440
0
#if QT_CONFIG(dtls)
441
0
    return new QDtlsClientVerifierOpenSSL;
442
#else
443
    qCWarning(lcTlsBackend, "Feature 'dtls' is disabled, cannot verify DTLS cookies");
444
    return nullptr;
445
#endif // QT_CONFIG(dtls)
446
0
}
447
448
QTlsPrivate::TlsCryptograph *QTlsBackendOpenSSL::createTlsCryptograph() const
449
0
{
450
0
    return new QTlsPrivate::TlsCryptographOpenSSL;
451
0
}
452
453
QTlsPrivate::DtlsCryptograph *QTlsBackendOpenSSL::createDtlsCryptograph(QDtls *q, int mode) const
454
0
{
455
0
#if QT_CONFIG(dtls)
456
0
    return new QDtlsPrivateOpenSSL(q, QSslSocket::SslMode(mode));
457
#else
458
    Q_UNUSED(q);
459
    Q_UNUSED(mode);
460
    qCWarning(lcTlsBackend, "Feature 'dtls' is disabled, cannot encrypt UDP datagrams");
461
    return nullptr;
462
#endif // QT_CONFIG(dtls)
463
0
}
464
465
QTlsPrivate::X509ChainVerifyPtr QTlsBackendOpenSSL::X509Verifier() const
466
0
{
467
0
    return QTlsPrivate::X509CertificateOpenSSL::verify;
468
0
}
469
470
QTlsPrivate::X509PemReaderPtr QTlsBackendOpenSSL::X509PemReader() const
471
0
{
472
0
    return QTlsPrivate::X509CertificateOpenSSL::certificatesFromPem;
473
0
}
474
475
QTlsPrivate::X509DerReaderPtr QTlsBackendOpenSSL::X509DerReader() const
476
0
{
477
0
    return QTlsPrivate::X509CertificateOpenSSL::certificatesFromDer;
478
0
}
479
480
QTlsPrivate::X509Pkcs12ReaderPtr QTlsBackendOpenSSL::X509Pkcs12Reader() const
481
0
{
482
0
    return QTlsPrivate::X509CertificateOpenSSL::importPkcs12;
483
0
}
484
485
QList<int> QTlsBackendOpenSSL::ellipticCurvesIds() const
486
0
{
487
0
    QList<int> ids;
488
489
0
#ifndef OPENSSL_NO_EC
490
0
    const size_t curveCount = q_EC_get_builtin_curves(nullptr, 0);
491
0
    QVarLengthArray<EC_builtin_curve> builtinCurves(static_cast<int>(curveCount));
492
493
0
    if (q_EC_get_builtin_curves(builtinCurves.data(), curveCount) == curveCount) {
494
0
        ids.reserve(curveCount);
495
0
        for (const auto &ec : builtinCurves)
496
0
            ids.push_back(ec.nid);
497
0
    }
498
0
#endif // OPENSSL_NO_EC
499
500
0
    return ids;
501
0
}
502
503
 int QTlsBackendOpenSSL::curveIdFromShortName(const QString &name) const
504
0
 {
505
0
     int nid = 0;
506
0
     if (name.isEmpty())
507
0
         return nid;
508
509
0
     ensureInitialized(); // TLSTODO: check if it's needed!
510
0
#ifndef OPENSSL_NO_EC
511
0
     const QByteArray curveNameLatin1 = name.toLatin1();
512
0
     nid = q_OBJ_sn2nid(curveNameLatin1.data());
513
514
0
     if (nid == 0)
515
0
         nid = q_EC_curve_nist2nid(curveNameLatin1.data());
516
0
#endif // !OPENSSL_NO_EC
517
518
0
     return nid;
519
0
 }
520
521
 int QTlsBackendOpenSSL::curveIdFromLongName(const QString &name) const
522
0
 {
523
0
     int nid = 0;
524
0
     if (name.isEmpty())
525
0
         return nid;
526
527
0
     ensureInitialized();
528
529
0
#ifndef OPENSSL_NO_EC
530
0
     const QByteArray curveNameLatin1 = name.toLatin1();
531
0
     nid = q_OBJ_ln2nid(curveNameLatin1.data());
532
0
#endif
533
534
0
     return nid;
535
0
 }
536
537
 QString QTlsBackendOpenSSL::shortNameForId(int id) const
538
0
 {
539
0
     QString result;
540
541
0
#ifndef OPENSSL_NO_EC
542
0
     if (id != 0)
543
0
         result = QString::fromLatin1(q_OBJ_nid2sn(id));
544
0
#endif
545
546
0
     return result;
547
0
 }
548
549
QString QTlsBackendOpenSSL::longNameForId(int id) const
550
0
{
551
0
    QString result;
552
553
0
#ifndef OPENSSL_NO_EC
554
0
    if (id != 0)
555
0
        result = QString::fromLatin1(q_OBJ_nid2ln(id));
556
0
#endif
557
558
0
    return result;
559
0
}
560
561
// NIDs of named curves allowed in TLS as per RFCs 4492 and 7027,
562
// see also https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-8
563
static const int tlsNamedCurveNIDs[] = {
564
    // RFC 4492
565
    NID_sect163k1,
566
    NID_sect163r1,
567
    NID_sect163r2,
568
    NID_sect193r1,
569
    NID_sect193r2,
570
    NID_sect233k1,
571
    NID_sect233r1,
572
    NID_sect239k1,
573
    NID_sect283k1,
574
    NID_sect283r1,
575
    NID_sect409k1,
576
    NID_sect409r1,
577
    NID_sect571k1,
578
    NID_sect571r1,
579
580
    NID_secp160k1,
581
    NID_secp160r1,
582
    NID_secp160r2,
583
    NID_secp192k1,
584
    NID_X9_62_prime192v1, // secp192r1
585
    NID_secp224k1,
586
    NID_secp224r1,
587
    NID_secp256k1,
588
    NID_X9_62_prime256v1, // secp256r1
589
    NID_secp384r1,
590
    NID_secp521r1,
591
592
    // RFC 7027
593
    NID_brainpoolP256r1,
594
    NID_brainpoolP384r1,
595
    NID_brainpoolP512r1
596
};
597
598
const size_t tlsNamedCurveNIDCount = sizeof(tlsNamedCurveNIDs) / sizeof(tlsNamedCurveNIDs[0]);
599
600
bool QTlsBackendOpenSSL::isTlsNamedCurve(int id) const
601
0
{
602
0
    const int *const tlsNamedCurveNIDsEnd = tlsNamedCurveNIDs + tlsNamedCurveNIDCount;
603
0
    return std::find(tlsNamedCurveNIDs, tlsNamedCurveNIDsEnd, id) != tlsNamedCurveNIDsEnd;
604
0
}
605
606
QString QTlsBackendOpenSSL::msgErrorsDuringHandshake()
607
0
{
608
0
    return QSslSocket::tr("Error during SSL handshake: %1").arg(getErrorsFromOpenSsl());
609
0
}
610
611
QSslCipher QTlsBackendOpenSSL::qt_OpenSSL_cipher_to_QSslCipher(const SSL_CIPHER *cipher)
612
0
{
613
0
    Q_ASSERT(cipher);
614
0
    char buf [256] = {};
615
0
    const QString desc = QString::fromLatin1(q_SSL_CIPHER_description(cipher, buf, sizeof(buf)));
616
0
    int supportedBits = 0;
617
0
    const int bits = q_SSL_CIPHER_get_bits(cipher, &supportedBits);
618
0
    return createCiphersuite(desc, bits, supportedBits);
619
0
}
620
621
void QTlsBackendOpenSSL::forceAutotestSecurityLevel()
622
0
{
623
0
    QSslContext::forceAutoTestSecurityLevel();
624
0
}
625
626
QT_END_NAMESPACE
627
628
#include "moc_qtlsbackend_openssl_p.cpp"