Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qtlsbackend_openssl.cpp
Go to the documentation of this file.
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
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
31QT_BEGIN_NAMESPACE
32
33using namespace Qt::StringLiterals;
34
35#if defined(Q_OS_WIN) || defined(Q_OS_MACOS)
36constexpr auto DefaultWarningLevel = QtCriticalMsg;
37#else
38constexpr auto DefaultWarningLevel = QtDebugMsg;
39#endif
40
41Q_LOGGING_CATEGORY(lcTlsBackend, "qt.tlsbackend.ossl", DefaultWarningLevel);
42
43static void q_loadCiphersForConnection(SSL *connection, QList<QSslCipher> &ciphers,
44 QList<QSslCipher> &defaultCiphers)
45{
46 Q_ASSERT(connection);
47
48 STACK_OF(SSL_CIPHER) *supportedCiphers = q_SSL_get_ciphers(connection);
49 for (int i = 0; i < q_sk_SSL_CIPHER_num(supportedCiphers); ++i) {
50 if (SSL_CIPHER *cipher = q_sk_SSL_CIPHER_value(supportedCiphers, i)) {
51 const auto ciph = QTlsBackendOpenSSL::qt_OpenSSL_cipher_to_QSslCipher(cipher);
52 if (!ciph.isNull()) {
53 // Unconditionally exclude ADH and AECDH ciphers since they offer no MITM protection
54 if (!ciph.name().toLower().startsWith("adh"_L1) &&
55 !ciph.name().toLower().startsWith("exp-adh"_L1) &&
56 !ciph.name().toLower().startsWith("aecdh"_L1)) {
57 ciphers << ciph;
58
59 if (ciph.usedBits() >= 128)
60 defaultCiphers << ciph;
61 }
62 }
63 }
64 }
65}
66
67int QTlsBackendOpenSSL::s_indexForSSLExtraData = -1;
68
69QString QTlsBackendOpenSSL::getErrorsFromOpenSsl()
70{
71 QString errorString;
72 char buf[256] = {}; // OpenSSL docs claim both 120 and 256; use the larger.
73 unsigned long errNum;
74 while ((errNum = q_ERR_get_error())) {
75 if (!errorString.isEmpty())
76 errorString.append(", "_L1);
77 q_ERR_error_string_n(errNum, buf, sizeof buf);
78 errorString.append(QLatin1StringView(buf)); // error is ascii according to man ERR_error_string
79 }
80 return errorString;
81}
82
83void QTlsBackendOpenSSL::logAndClearErrorQueue()
84{
85 const auto errors = getErrorsFromOpenSsl();
86 if (errors.size())
87 qCWarning(lcTlsBackend) << "Discarding errors:" << errors;
88}
89
90void QTlsBackendOpenSSL::clearErrorQueue()
91{
92 while (q_ERR_get_error())
93 ;
94}
95
96bool QTlsBackendOpenSSL::ensureLibraryLoaded()
97{
98 static bool libraryLoaded = []() {
100 return false;
101
102 // Initialize OpenSSL.
103 if (q_OPENSSL_init_ssl(0, nullptr) != 1)
104 return false;
105
106 if (q_OpenSSL_version_num() < 0x10101000L) {
107 qCWarning(lcTlsBackend, "QSslSocket: OpenSSL >= 1.1.1 is required; %s was found instead", q_OpenSSL_version(OPENSSL_VERSION));
108 return false;
109 }
110
113
114 s_indexForSSLExtraData = q_CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_SSL, 0L, nullptr, nullptr,
115 nullptr, nullptr);
116
117 // Initialize OpenSSL's random seed.
118 if (!q_RAND_status()) {
119 qWarning("Random number generator not seeded, disabling SSL support");
120 return false;
121 }
122
123 return true;
124 }();
125
126 return libraryLoaded;
127}
128
129QString QTlsBackendOpenSSL::backendName() const
130{
131 return builtinBackendNames[nameIndexOpenSSL];
132}
133
134bool QTlsBackendOpenSSL::isValid() const
135{
136 return ensureLibraryLoaded();
137}
138
139long QTlsBackendOpenSSL::tlsLibraryVersionNumber() const
140{
142}
143
144QString QTlsBackendOpenSSL::tlsLibraryVersionString() const
145{
146 const char *versionString = q_OpenSSL_version(OPENSSL_VERSION);
147 if (!versionString)
148 return QString();
149
150 return QString::fromLatin1(versionString);
151}
152
153long QTlsBackendOpenSSL::tlsLibraryBuildVersionNumber() const
154{
155 return OPENSSL_VERSION_NUMBER;
156}
157
158QString QTlsBackendOpenSSL::tlsLibraryBuildVersionString() const
159{
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 return QStringLiteral(OPENSSL_VERSION_TEXT);
164}
165
166void QTlsBackendOpenSSL::ensureInitialized() const
167{
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 ensureCiphersAndCertsLoaded();
175}
176
177void QTlsBackendOpenSSL::ensureCiphersAndCertsLoaded() const
178{
179 Q_CONSTINIT static bool initializationStarted = false;
180 Q_CONSTINIT static QAtomicInt initialized = Q_BASIC_ATOMIC_INITIALIZER(0);
181 Q_CONSTINIT static QRecursiveMutex initMutex;
182
183 if (initialized.loadAcquire())
184 return;
185
186 const QMutexLocker locker(&initMutex);
187
188 if (initializationStarted || initialized.loadAcquire())
189 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 initializationStarted = true;
195
196 auto guard = qScopeGuard([] { initialized.storeRelease(1); });
197
198 resetDefaultCiphers();
199 resetDefaultEllipticCurves();
200
201#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 const QList<QByteArray> dirs = QSslSocketPrivate::unixRootCertDirectories();
208 const QStringList symLinkFilter{
209 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 for (const auto &dir : dirs) {
211 QDirListing dirList(QString::fromLatin1(dir), symLinkFilter,
212 QDirListing::IteratorFlag::FilesOnly);
213 if (dirList.cbegin() != dirList.cend()) { // Not empty
214 QSslSocketPrivate::setRootCertOnDemandLoadingSupported(true);
215 break;
216 }
217 }
218#endif
219#endif // QT_CONFIG(library)
220 // if on-demand loading was not enabled, load the certs now
221 if (!QSslSocketPrivate::rootCertOnDemandLoadingSupported())
222 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}
232
233void QTlsBackendOpenSSL::resetDefaultCiphers()
234{
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 Q_ASSERT(myCtx);
240 SSL *mySsl = q_SSL_new(myCtx);
241 Q_ASSERT(mySsl);
242
243 QList<QSslCipher> ciphers;
244 QList<QSslCipher> defaultCiphers;
245
246 q_loadCiphersForConnection(mySsl, ciphers, defaultCiphers);
247
248 q_SSL_CTX_free(myCtx);
249 q_SSL_free(mySsl);
250
251 setDefaultSupportedCiphers(ciphers);
252 setDefaultCiphers(defaultCiphers);
253
254#if QT_CONFIG(dtls)
255 ciphers.clear();
256 defaultCiphers.clear();
257 myCtx = q_SSL_CTX_new(q_DTLS_client_method());
258 if (myCtx) {
259 mySsl = q_SSL_new(myCtx);
260 if (mySsl) {
261 q_loadCiphersForConnection(mySsl, ciphers, defaultCiphers);
262 setDefaultDtlsCiphers(defaultCiphers);
263 q_SSL_free(mySsl);
264 }
265 q_SSL_CTX_free(myCtx);
266 }
267#endif // dtls
268}
269
270QList<QSsl::SslProtocol> QTlsBackendOpenSSL::supportedProtocols() const
271{
272 QList<QSsl::SslProtocol> protocols;
273
274 protocols << QSsl::AnyProtocol;
275 protocols << QSsl::SecureProtocols;
276QT_WARNING_PUSH
277QT_WARNING_DISABLE_DEPRECATED
278 protocols << QSsl::TlsV1_0;
279 protocols << QSsl::TlsV1_0OrLater;
280 protocols << QSsl::TlsV1_1;
281 protocols << QSsl::TlsV1_1OrLater;
282QT_WARNING_POP
283 protocols << QSsl::TlsV1_2;
284 protocols << QSsl::TlsV1_2OrLater;
285
286#ifdef TLS1_3_VERSION
287 protocols << QSsl::TlsV1_3;
288 protocols << QSsl::TlsV1_3OrLater;
289#endif // TLS1_3_VERSION
290
291#if QT_CONFIG(dtls)
292QT_WARNING_PUSH
293QT_WARNING_DISABLE_DEPRECATED
294 protocols << QSsl::DtlsV1_0;
295 protocols << QSsl::DtlsV1_0OrLater;
296QT_WARNING_POP
297 protocols << QSsl::DtlsV1_2;
298 protocols << QSsl::DtlsV1_2OrLater;
299#endif // dtls
300
301 return protocols;
302}
303
304QList<QSsl::SupportedFeature> QTlsBackendOpenSSL::supportedFeatures() const
305{
306 QList<QSsl::SupportedFeature> features;
307
308 features << QSsl::SupportedFeature::CertificateVerification;
309
310#if !defined(OPENSSL_NO_TLSEXT)
311 features << QSsl::SupportedFeature::ClientSideAlpn;
312 features << QSsl::SupportedFeature::ServerSideAlpn;
313#endif // !OPENSSL_NO_TLSEXT
314
315 features << QSsl::SupportedFeature::Ocsp;
316 features << QSsl::SupportedFeature::Psk;
317 features << QSsl::SupportedFeature::SessionTicket;
318 features << QSsl::SupportedFeature::Alerts;
319
320 return features;
321}
322
323QList<QSsl::ImplementedClass> QTlsBackendOpenSSL::implementedClasses() const
324{
325 QList<QSsl::ImplementedClass> classes;
326
327 classes << QSsl::ImplementedClass::Key;
328 classes << QSsl::ImplementedClass::Certificate;
329 classes << QSsl::ImplementedClass::Socket;
330#if QT_CONFIG(dtls)
331 classes << QSsl::ImplementedClass::Dtls;
332 classes << QSsl::ImplementedClass::DtlsCookie;
333#endif
334 classes << QSsl::ImplementedClass::EllipticCurve;
335 classes << QSsl::ImplementedClass::DiffieHellman;
336
337 return classes;
338}
339
340QTlsPrivate::TlsKey *QTlsBackendOpenSSL::createKey() const
341{
342 return new QTlsPrivate::TlsKeyOpenSSL;
343}
344
345QTlsPrivate::X509Certificate *QTlsBackendOpenSSL::createCertificate() const
346{
347 return new QTlsPrivate::X509CertificateOpenSSL;
348}
349
350namespace QTlsPrivate {
351
352#ifdef Q_OS_ANDROID
354#endif
355
357
358#ifndef Q_OS_DARWIN
360{
361#ifdef QSSLSOCKET_DEBUG
362 QElapsedTimer timer;
363 timer.start();
364#endif
365 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 const QList<QByteArray> directories = QSslSocketPrivate::unixRootCertDirectories();
391 QSet<QString> certFiles = {
392 QStringLiteral("/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem"), // Red Hat 2013+
393 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 };
396
397 static const size_t extLen = strlen(".pem"); // or strlen(".crt")
398 auto hasMatchingExtension = [](const QString &fileName) {
399 if (size_t(fileName.size()) < extLen + 1)
400 return false;
401 auto ext = QStringView{fileName}.last(extLen);
402 return ext == ".pem"_L1 || ext == ".crt"_L1;
403 };
404
405 using F = QDirListing::IteratorFlag;
406 constexpr auto flags = F::FilesOnly | F::ResolveSymlinks; // Files and symlinks to files
407 for (const QByteArray &directory : directories) {
408 for (const auto &dirEntry : QDirListing(QFile::decodeName(directory), flags)) {
409 // use canonical path here to not load the same certificate twice if symlinked
410 if (hasMatchingExtension(dirEntry.fileName()))
411 certFiles.insert(dirEntry.canonicalFilePath());
412 }
413 }
414 for (const QString& file : std::as_const(certFiles))
415 systemCerts.append(QSslCertificate::fromFile(file, QSsl::Pem));
416 }
417#endif // platform
418#ifdef QSSLSOCKET_DEBUG
419 qCDebug(lcTlsBackend) << "systemCaCertificates retrieval time " << timer.elapsed() << "ms";
420 qCDebug(lcTlsBackend) << "imported " << systemCerts.count() << " certificates";
421#endif
422
423 return systemCerts;
424}
425#endif // !Q_OS_DARWIN
426} // namespace QTlsPrivate
427
428QList<QSslCertificate> QTlsBackendOpenSSL::systemCaCertificates() const
429{
430 return QTlsPrivate::systemCaCertificates();
431}
432
434{
435#if QT_CONFIG(dtls)
436 return new QDtlsClientVerifierOpenSSL;
437#else
438 qCWarning(lcTlsBackend, "Feature 'dtls' is disabled, cannot verify DTLS cookies");
439 return nullptr;
440#endif // QT_CONFIG(dtls)
441}
442
444{
446}
447
448QTlsPrivate::DtlsCryptograph *QTlsBackendOpenSSL::createDtlsCryptograph(QDtls *q, int mode) const
449{
450#if QT_CONFIG(dtls)
451 return new QDtlsPrivateOpenSSL(q, QSslSocket::SslMode(mode));
452#else
453 Q_UNUSED(q);
454 Q_UNUSED(mode);
455 qCWarning(lcTlsBackend, "Feature 'dtls' is disabled, cannot encrypt UDP datagrams");
456 return nullptr;
457#endif // QT_CONFIG(dtls)
458}
459
460QTlsPrivate::X509ChainVerifyPtr QTlsBackendOpenSSL::X509Verifier() const
461{
462 return QTlsPrivate::X509CertificateOpenSSL::verify;
463}
464
465QTlsPrivate::X509PemReaderPtr QTlsBackendOpenSSL::X509PemReader() const
466{
467 return QTlsPrivate::X509CertificateOpenSSL::certificatesFromPem;
468}
469
470QTlsPrivate::X509DerReaderPtr QTlsBackendOpenSSL::X509DerReader() const
471{
472 return QTlsPrivate::X509CertificateOpenSSL::certificatesFromDer;
473}
474
476{
477 return QTlsPrivate::X509CertificateOpenSSL::importPkcs12;
478}
479
480QList<int> QTlsBackendOpenSSL::ellipticCurvesIds() const
481{
482 QList<int> ids;
483
484#ifndef OPENSSL_NO_EC
485 const size_t curveCount = q_EC_get_builtin_curves(nullptr, 0);
486 QVarLengthArray<EC_builtin_curve> builtinCurves(static_cast<int>(curveCount));
487
488 if (q_EC_get_builtin_curves(builtinCurves.data(), curveCount) == curveCount) {
489 ids.reserve(curveCount);
490 for (const auto &ec : builtinCurves)
491 ids.push_back(ec.nid);
492 }
493#endif // OPENSSL_NO_EC
494
495 return ids;
496}
497
498 int QTlsBackendOpenSSL::curveIdFromShortName(const QString &name) const
499 {
500 int nid = 0;
501 if (name.isEmpty())
502 return nid;
503
504 ensureInitialized(); // TLSTODO: check if it's needed!
505#ifndef OPENSSL_NO_EC
506 const QByteArray curveNameLatin1 = name.toLatin1();
507 nid = q_OBJ_sn2nid(curveNameLatin1.data());
508
509 if (nid == 0)
510 nid = q_EC_curve_nist2nid(curveNameLatin1.data());
511#endif // !OPENSSL_NO_EC
512
513 return nid;
514 }
515
516 int QTlsBackendOpenSSL::curveIdFromLongName(const QString &name) const
517 {
518 int nid = 0;
519 if (name.isEmpty())
520 return nid;
521
523
524#ifndef OPENSSL_NO_EC
525 const QByteArray curveNameLatin1 = name.toLatin1();
526 nid = q_OBJ_ln2nid(curveNameLatin1.data());
527#endif
528
529 return nid;
530 }
531
532 QString QTlsBackendOpenSSL::shortNameForId(int id) const
533 {
534 QString result;
535
536#ifndef OPENSSL_NO_EC
537 if (id != 0)
538 result = QString::fromLatin1(q_OBJ_nid2sn(id));
539#endif
540
541 return result;
542 }
543
544QString QTlsBackendOpenSSL::longNameForId(int id) const
545{
546 QString result;
547
548#ifndef OPENSSL_NO_EC
549 if (id != 0)
550 result = QString::fromLatin1(q_OBJ_nid2ln(id));
551#endif
552
553 return result;
554}
555
556// NIDs of named curves allowed in TLS as per RFCs 4492 and 7027,
557// see also https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-8
558static const int tlsNamedCurveNIDs[] = {
559 // RFC 4492
560 NID_sect163k1,
561 NID_sect163r1,
562 NID_sect163r2,
563 NID_sect193r1,
564 NID_sect193r2,
565 NID_sect233k1,
566 NID_sect233r1,
567 NID_sect239k1,
568 NID_sect283k1,
569 NID_sect283r1,
570 NID_sect409k1,
571 NID_sect409r1,
572 NID_sect571k1,
573 NID_sect571r1,
574
575 NID_secp160k1,
576 NID_secp160r1,
577 NID_secp160r2,
578 NID_secp192k1,
579 NID_X9_62_prime192v1, // secp192r1
580 NID_secp224k1,
581 NID_secp224r1,
582 NID_secp256k1,
583 NID_X9_62_prime256v1, // secp256r1
584 NID_secp384r1,
585 NID_secp521r1,
586
587 // RFC 7027
588 NID_brainpoolP256r1,
589 NID_brainpoolP384r1,
590 NID_brainpoolP512r1
591};
592
594
595bool QTlsBackendOpenSSL::isTlsNamedCurve(int id) const
596{
597 const int *const tlsNamedCurveNIDsEnd = tlsNamedCurveNIDs + tlsNamedCurveNIDCount;
598 return std::find(tlsNamedCurveNIDs, tlsNamedCurveNIDsEnd, id) != tlsNamedCurveNIDsEnd;
599}
600
601QString QTlsBackendOpenSSL::msgErrorsDuringHandshake()
602{
603 return QSslSocket::tr("Error during SSL handshake: %1").arg(getErrorsFromOpenSsl());
604}
605
606QSslCipher QTlsBackendOpenSSL::qt_OpenSSL_cipher_to_QSslCipher(const SSL_CIPHER *cipher)
607{
608 Q_ASSERT(cipher);
609 char buf [256] = {};
610 const QString desc = QString::fromLatin1(q_SSL_CIPHER_description(cipher, buf, sizeof(buf)));
611 int supportedBits = 0;
612 const int bits = q_SSL_CIPHER_get_bits(cipher, &supportedBits);
613 return createCiphersuite(desc, bits, supportedBits);
614}
615
620
621QT_END_NAMESPACE
622
623#include "moc_qtlsbackend_openssl_p.cpp"
static void forceAutoTestSecurityLevel()
QTlsPrivate::X509DerReaderPtr X509DerReader() const override
QString tlsLibraryBuildVersionString() const override
QList< QSsl::SslProtocol > supportedProtocols() const override
QTlsPrivate::X509ChainVerifyPtr X509Verifier() const override
bool isTlsNamedCurve(int cid) const override
long tlsLibraryVersionNumber() const override
long tlsLibraryBuildVersionNumber() const override
QTlsPrivate::DtlsCryptograph * createDtlsCryptograph(QDtls *q, int mode) const override
static void logAndClearErrorQueue()
int curveIdFromShortName(const QString &name) const override
QTlsPrivate::X509PemReaderPtr X509PemReader() const override
int curveIdFromLongName(const QString &name) const override
bool isValid() const override
QList< int > ellipticCurvesIds() const override
QString shortNameForId(int cid) const override
QTlsPrivate::X509Certificate * createCertificate() const override
void forceAutotestSecurityLevel() override
QTlsPrivate::X509Pkcs12ReaderPtr X509Pkcs12Reader() const override
QString longNameForId(int cid) const override
QList< QSslCertificate > systemCaCertificates() const override
QList< QSsl::SupportedFeature > supportedFeatures() const override
QList< QSsl::ImplementedClass > implementedClasses() const override
QTlsPrivate::DtlsCookieVerifier * createDtlsCookieVerifier() const override
void ensureInitialized() const override
QTlsPrivate::TlsKey * createKey() const override
QTlsPrivate::TlsCryptograph * createTlsCryptograph() const override
QString backendName() const override
QString tlsLibraryVersionString() const override
Namespace containing onternal types that TLS backends implement.
QList< QSslCertificate > systemCaCertificates()
Q_LOGGING_CATEGORY(lcEventDispatcher, "qt.eventdispatcher")
void q_SSL_free(SSL *a)
void q_SSL_CTX_free(SSL_CTX *a)
const char * q_OpenSSL_version(int type)
bool q_resolveOpenSslSymbols()
#define q_SSL_load_error_strings()
unsigned long q_ERR_get_error()
void q_ERR_error_string_n(unsigned long e, char *buf, size_t len)
#define q_OpenSSL_add_all_algorithms()
int q_RAND_status()
SSL_CTX * q_SSL_CTX_new(const SSL_METHOD *a)
#define q_sk_SSL_CIPHER_num(st)
const SSL_METHOD * q_TLS_client_method()
SSL * q_SSL_new(SSL_CTX *a)
int q_SSL_CIPHER_get_bits(const SSL_CIPHER *a, int *b)
long q_OpenSSL_version_num()
int q_CRYPTO_get_ex_new_index(int class_index, long argl, void *argp, CRYPTO_EX_new *new_func, CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func)
#define q_sk_SSL_CIPHER_value(st, i)
int q_OPENSSL_init_ssl(uint64_t opts, const OPENSSL_INIT_SETTINGS *settings)
constexpr auto DefaultWarningLevel
const size_t tlsNamedCurveNIDCount
static const int tlsNamedCurveNIDs[]
static void q_loadCiphersForConnection(SSL *connection, QList< QSslCipher > &ciphers, QList< QSslCipher > &defaultCiphers)