7#include <QtNetwork/qsslsocket.h>
8#include <QtNetwork/qssldiffiehellmanparameters.h>
16#include <QtNetwork/private/qssl_p.h>
17#include <QtNetwork/private/qsslsocket_p.h>
18#include <QtNetwork/private/qtlsbackend_p.h>
20#include <QtNetwork/private/qssldiffiehellmanparameters_p.h>
26Q_GLOBAL_STATIC(
bool, forceSecurityLevel)
42namespace dtlscallbacks
44extern "C" int q_X509DtlsCallback(
int ok, X509_STORE_CTX *ctx);
45extern "C" int q_generate_cookie_callback(SSL *ssl,
unsigned char *dst,
46 unsigned *cookieLength);
47extern "C" int q_verify_cookie_callback(SSL *ssl,
const unsigned char *cookie,
48 unsigned cookieLength);
53extern "C" int q_ssl_sess_set_new_cb(SSL *context, SSL_SESSION *session);
58 return QSslSocket::tr(
"Error when setting the OpenSSL configuration (%1)").arg(why);
63 return QSslSocket::tr(
"Error when setting the elliptic curves (%1)").arg(why);
66qssloptions
QSslContext::setupOpenSslOptions(QSsl::SslProtocol protocol, QSsl::SslOptions sslOptions)
71QT_WARNING_DISABLE_DEPRECATED
72 case QSsl::TlsV1_0OrLater:
73 options = SSL_OP_ALL | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3;
75 case QSsl::TlsV1_1OrLater:
76 options = SSL_OP_ALL | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1;
79 case QSsl::SecureProtocols:
80 case QSsl::TlsV1_2OrLater:
81 options = SSL_OP_ALL | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1;
83 case QSsl::TlsV1_3OrLater:
84 options = SSL_OP_ALL | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1 | SSL_OP_NO_TLSv1_2;
91 if (sslOptions & QSsl::SslOptionDisableEmptyFragments)
92 options |= SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS;
94 options &= ~SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS;
96#ifdef SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION
98 if (sslOptions & QSsl::SslOptionDisableLegacyRenegotiation)
99 options &= ~SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION;
101 options |= SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION;
104#ifdef SSL_OP_NO_TICKET
105 if (sslOptions & QSsl::SslOptionDisableSessionTickets)
106 options |= SSL_OP_NO_TICKET;
108#ifdef SSL_OP_NO_COMPRESSION
109 if (sslOptions & QSsl::SslOptionDisableCompression)
110 options |= SSL_OP_NO_COMPRESSION;
113 if (!(sslOptions & QSsl::SslOptionDisableServerCipherPreference))
114 options |= SSL_OP_CIPHER_SERVER_PREFERENCE;
123 m_sessionTicketLifeTimeHint(-1)
140std::shared_ptr<QSslContext>
QSslContext::sharedFromConfiguration(QSslSocket::SslMode mode,
const QSslConfiguration &configuration,
bool allowRootCertOnDemandLoading)
143 std::shared_ptr<QSslContext> sslContext = std::make_shared<AccessToPrivateCtor>();
144 initSslContext(sslContext.get(), mode, configuration, allowRootCertOnDemandLoading);
148std::shared_ptr<QSslContext>
QSslContext::sharedFromPrivateConfiguration(QSslSocket::SslMode mode, QSslConfigurationPrivate *privConfiguration,
149 bool allowRootCertOnDemandLoading)
151 return sharedFromConfiguration(mode, privConfiguration, allowRootCertOnDemandLoading);
154#ifndef OPENSSL_NO_NEXTPROTONEG
157 const unsigned char *in,
unsigned int inlen,
void *arg)
171 case OPENSSL_NPN_UNSUPPORTED:
172 ctx->status = QSslConfiguration::NextProtocolNegotiationNone;
174 case OPENSSL_NPN_NEGOTIATED:
175 ctx->status = QSslConfiguration::NextProtocolNegotiationNegotiated;
177 case OPENSSL_NPN_NO_OVERLAP:
178 ctx->status = QSslConfiguration::NextProtocolNegotiationUnsupported;
181 qCWarning(lcTlsBackend,
"OpenSSL sent unknown NPN status");
184 return SSL_TLSEXT_ERR_OK;
201 if (!session && !sessionASN1().isEmpty()
202 && !sslConfiguration.testSslOption(QSsl::SslOptionDisableSessionPersistence)) {
203 const unsigned char *data =
reinterpret_cast<
const unsigned char *>(m_sessionASN1.constData());
204 session = q_d2i_SSL_SESSION(
nullptr, &data, m_sessionASN1.size());
211 qCWarning(lcTlsBackend,
"could not set SSL session");
217#ifndef OPENSSL_NO_NEXTPROTONEG
218 QList<QByteArray> protocols = sslConfiguration.d.constData()->nextAllowedProtocols;
219 if (!protocols.isEmpty()) {
220 m_supportedNPNVersions.clear();
221 for (
int a = 0; a < protocols.size(); ++a) {
222 if (protocols.at(a).size() > 255) {
223 qCWarning(lcTlsBackend) <<
"TLS NPN extension" << protocols.at(a)
224 <<
"is too long and will be ignored.";
226 }
else if (protocols.at(a).isEmpty()) {
229 m_supportedNPNVersions.append(protocols.at(a).size()).append(protocols.at(a));
231 if (m_supportedNPNVersions.size()) {
232 m_npnContext.data =
reinterpret_cast<
unsigned char *>(m_supportedNPNVersions.data());
233 m_npnContext.len = m_supportedNPNVersions.size();
234 m_npnContext.status = QSslConfiguration::NextProtocolNegotiationNone;
239 typedef int (*alpn_callback_t) (SSL *,
const unsigned char **,
unsigned char *,
240 const unsigned char *,
unsigned int,
void *);
243 q_SSL_CTX_set_alpn_select_cb(ctx, alpn_callback_t(next_proto_cb), &m_npnContext);
245 q_SSL_set_alpn_protos(ssl, m_npnContext.data, m_npnContext.len);
247 q_SSL_CTX_set_next_proto_select_cb(ctx, next_proto_cb, &m_npnContext);
270 if (session && !sslConfiguration.testSslOption(QSsl::SslOptionDisableSessionPersistence)) {
272 if (sessionSize > 0) {
273 m_sessionASN1.resize(sessionSize);
274 unsigned char *data =
reinterpret_cast<
unsigned char *>(m_sessionASN1.data());
276 qCWarning(lcTlsBackend,
"could not store persistent version of SSL session");
281 return (session !=
nullptr);
286 return m_sessionASN1;
291 m_sessionASN1 = session;
296 return m_sessionTicketLifeTimeHint;
301 *forceSecurityLevel() =
true;
315 const QSslConfiguration &configuration,
316 bool allowRootCertOnDemandLoading)
318 sslContext->sslConfiguration = configuration;
319 sslContext->errorCode = QSslError::NoError;
321 bool client = (mode == QSslSocket::SslClientMode);
323 bool reinitialized =
false;
324 bool unsupportedProtocol =
false;
327 switch (sslContext->sslConfiguration.protocol()) {
329QT_WARNING_DISABLE_DEPRECATED
331 case QSsl::DtlsV1_0OrLater:
334 case QSsl::DtlsV1_2OrLater:
337 sslContext->ctx = q_SSL_CTX_new(client ? q_DTLS_client_method() : q_DTLS_server_method());
339 sslContext->ctx =
nullptr;
340 unsupportedProtocol =
true;
341 qCWarning(lcTlsBackend,
"DTLS protocol requested, but feature 'dtls' is disabled");
345 case QSsl::TlsV1_3OrLater:
346#if !defined(TLS1_3_VERSION
)
347 qCWarning(lcTlsBackend,
"TLS 1.3 is not supported");
348 sslContext->ctx =
nullptr;
349 unsupportedProtocol =
true;
357 if (!sslContext->ctx) {
360 if (!reinitialized) {
361 reinitialized =
true;
366 sslContext->errorStr = QSslSocket::tr(
"Error creating SSL context (%1)").arg(
367 unsupportedProtocol ? QSslSocket::tr(
"unsupported protocol") : QTlsBackendOpenSSL::getErrorsFromOpenSsl()
369 sslContext->errorCode = QSslError::UnspecifiedError;
377 const long anyVersion =
379 isDtls ? DTLS_ANY_VERSION : TLS_ANY_VERSION;
383 long minVersion = anyVersion;
384 long maxVersion = anyVersion;
386 switch (sslContext->sslConfiguration.protocol()) {
388QT_WARNING_DISABLE_DEPRECATED
390 minVersion = TLS1_VERSION;
391 maxVersion = TLS1_VERSION;
394 minVersion = TLS1_1_VERSION;
395 maxVersion = TLS1_1_VERSION;
399 minVersion = TLS1_2_VERSION;
400 maxVersion = TLS1_2_VERSION;
404 minVersion = TLS1_3_VERSION;
405 maxVersion = TLS1_3_VERSION;
413 case QSsl::AnyProtocol:
415QT_WARNING_DISABLE_DEPRECATED
416 case QSsl::TlsV1_0OrLater:
417 minVersion = TLS1_VERSION;
420 case QSsl::TlsV1_1OrLater:
421 minVersion = TLS1_1_VERSION;
425 case QSsl::SecureProtocols:
426 case QSsl::TlsV1_2OrLater:
427 minVersion = TLS1_2_VERSION;
431QT_WARNING_DISABLE_DEPRECATED
433 minVersion = DTLS1_VERSION;
434 maxVersion = DTLS1_VERSION;
436 case QSsl::DtlsV1_0OrLater:
437 minVersion = DTLS1_VERSION;
442 minVersion = DTLS1_2_VERSION;
443 maxVersion = DTLS1_2_VERSION;
445 case QSsl::DtlsV1_2OrLater:
446 minVersion = DTLS1_2_VERSION;
449 case QSsl::TlsV1_3OrLater:
451 minVersion = TLS1_3_VERSION;
460 case QSsl::UnknownProtocol:
464 if (minVersion != anyVersion
466 sslContext->errorStr = QSslSocket::tr(
"Error while setting the minimal protocol version");
467 sslContext->errorCode = QSslError::UnspecifiedError;
471 if (maxVersion != anyVersion
473 sslContext->errorStr = QSslSocket::tr(
"Error while setting the maximum protocol version");
474 sslContext->errorCode = QSslError::UnspecifiedError;
479 const qssloptions options = setupOpenSslOptions(configuration.protocol(), configuration.d->sslOptions);
486 auto filterCiphers = [](
const QList<QSslCipher> &ciphers,
bool selectTls13)
488 QByteArray cipherString;
490 for (
const QSslCipher &cipher : ciphers) {
491 const bool isTls13Cipher = cipher.protocol() == QSsl::TlsV1_3 || cipher.protocol() == QSsl::TlsV1_3OrLater;
492 if (selectTls13 != isTls13Cipher)
495 if (cipherString.size())
496 cipherString.append(
':');
497 cipherString.append(cipher.name().toLatin1());
503 QList<QSslCipher> ciphers = sslContext->sslConfiguration.ciphers();
504 if (ciphers.isEmpty())
505 ciphers = isDtls ? QTlsBackend::defaultDtlsCiphers() : QTlsBackend::defaultCiphers();
507 const QByteArray preTls13Ciphers = filterCiphers(ciphers,
false);
509 if (preTls13Ciphers.size()) {
510 if (!q_SSL_CTX_set_cipher_list(sslContext->ctx, preTls13Ciphers.data())) {
511 sslContext->errorStr = QSslSocket::tr(
"Invalid or empty cipher list (%1)").arg(QTlsBackendOpenSSL::getErrorsFromOpenSsl());
512 sslContext->errorCode = QSslError::UnspecifiedError;
517 const QByteArray tls13Ciphers = filterCiphers(ciphers,
true);
519 if (tls13Ciphers.size()) {
520 if (!q_SSL_CTX_set_ciphersuites(sslContext->ctx, tls13Ciphers.data())) {
521 sslContext->errorStr = QSslSocket::tr(
"Invalid or empty cipher list (%1)").arg(QTlsBackendOpenSSL::getErrorsFromOpenSsl());
522 sslContext->errorCode = QSslError::UnspecifiedError;
527 if (!preTls13Ciphers.size() && !tls13Ciphers.size()) {
528 sslContext->errorStr = QSslSocket::tr(
"Invalid or empty cipher list (%1)").arg(QStringLiteral(
""));
529 sslContext->errorCode = QSslError::UnspecifiedError;
533 const QDateTime now = QDateTime::currentDateTimeUtc();
536 const auto caCertificates = sslContext->sslConfiguration.caCertificates();
537 for (
const QSslCertificate &caCertificate : caCertificates) {
549 if (caCertificate.expiryDate() >= now) {
550 q_X509_STORE_add_cert(q_SSL_CTX_get_cert_store(sslContext->ctx), (X509 *)caCertificate.handle());
554 if (QSslSocketPrivate::rootCertOnDemandLoadingSupported() && allowRootCertOnDemandLoading) {
556 const QList<QByteArray> unixDirs = QSslSocketPrivate::unixRootCertDirectories();
558#if OPENSSL_VERSION_MAJOR
< 3
559 for (
const QByteArray &unixDir : unixDirs) {
560 if ((success = q_SSL_CTX_load_verify_locations(sslContext->ctx,
nullptr, unixDir.constData())) != 1)
564 for (
const QByteArray &unixDir : unixDirs) {
565 if ((success = q_SSL_CTX_load_verify_dir(sslContext->ctx, unixDir.constData())) != 1)
570 const auto qtErrors = QTlsBackendOpenSSL::getErrorsFromOpenSsl();
571 qCWarning(lcTlsBackend) <<
"An error encountered while to set root certificates location:"
576 if (!sslContext->sslConfiguration.localCertificate().isNull()) {
578 if (sslContext->sslConfiguration.privateKey().isNull()) {
579 sslContext->errorStr = QSslSocket::tr(
"Cannot provide a certificate with no key");
580 sslContext->errorCode = QSslError::UnspecifiedError;
586 sslContext->errorStr = QSslSocket::tr(
"Error loading local certificate, %1").arg(QTlsBackendOpenSSL::getErrorsFromOpenSsl());
587 sslContext->errorCode = QSslError::UnspecifiedError;
591 if (configuration.d->privateKey.algorithm() == QSsl::Opaque) {
592 sslContext->pkey =
reinterpret_cast<EVP_PKEY *>(configuration.d->privateKey.handle());
594#ifdef OPENSSL_NO_DEPRECATED_3_0
595 auto qtKey = QTlsBackend::backend<QTlsPrivate::TlsKeyOpenSSL>(configuration.d->privateKey);
597 sslContext->pkey = qtKey->genericKey;
598 Q_ASSERT(sslContext->pkey);
599 q_EVP_PKEY_up_ref(sslContext->pkey);
606 if (configuration.d->privateKey.algorithm() == QSsl::Rsa)
608 else if (configuration.d->privateKey.algorithm() == QSsl::Dsa)
611 else if (configuration.d->privateKey.algorithm() == QSsl::Ec)
616 auto pkey = sslContext->pkey;
617 if (configuration.d->privateKey.algorithm() == QSsl::Opaque)
618 sslContext->pkey =
nullptr;
621 sslContext->errorStr = QSslSocket::tr(
"Error loading private key, %1").arg(QTlsBackendOpenSSL::getErrorsFromOpenSsl());
622 sslContext->errorCode = QSslError::UnspecifiedError;
628 sslContext->errorStr = QSslSocket::tr(
"Private key does not certify public key, %1").arg(QTlsBackendOpenSSL::getErrorsFromOpenSsl());
629 sslContext->errorCode = QSslError::UnspecifiedError;
635 for (
const QSslCertificate &cert : std::as_const(configuration.d->localCertificateChain)) {
640 q_SSL_CTX_ctrl(sslContext->ctx, SSL_CTRL_EXTRA_CHAIN_CERT, 0,
641 q_X509_dup(
reinterpret_cast<X509 *>(cert.handle())));
647 if (sslContext->sslConfiguration.peerVerifyMode() == QSslSocket::VerifyNone) {
650 auto verificationCallback =
652 isDtls ? dtlscallbacks::q_X509DtlsCallback :
656 if (!isDtls && configuration.handshakeMustInterruptOnError())
659 auto verificationMode = SSL_VERIFY_PEER;
660 if (!isDtls && sslContext->sslConfiguration.missingCertificateIsFatal())
661 verificationMode |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
668 if (mode == QSslSocket::SslClientMode && !isDtls) {
669 q_SSL_CTX_sess_set_new_cb(sslContext->ctx, q_ssl_sess_set_new_cb);
670 q_SSL_CTX_set_session_cache_mode(sslContext->ctx, SSL_SESS_CACHE_CLIENT);
677 if (mode == QSslSocket::SslServerMode && isDtls && configuration.dtlsCookieVerificationEnabled()) {
678 q_SSL_CTX_set_cookie_generate_cb(sslContext->ctx, dtlscallbacks::q_generate_cookie_callback);
679 q_SSL_CTX_set_cookie_verify_cb(sslContext->ctx, dtlscallbacks::q_verify_cookie_callback);
684 if (sslContext->sslConfiguration.peerVerifyDepth() != 0)
685 q_SSL_CTX_set_verify_depth(sslContext->ctx, sslContext->sslConfiguration.peerVerifyDepth());
688 if (!configuration.sessionTicket().isEmpty())
689 sslContext->setSessionASN1(configuration.sessionTicket());
692 QSslDiffieHellmanParameters dhparams = configuration.diffieHellmanParameters();
694 if (!dhparams.isValid()) {
695 sslContext->errorStr = QSslSocket::tr(
"Diffie-Hellman parameters are not valid");
696 sslContext->errorCode = QSslError::UnspecifiedError;
700 if (dhparams.isEmpty()) {
703#ifndef OPENSSL_NO_DEPRECATED_3_0
704 const QByteArray ¶ms = dhparams.d->derData;
705 const char *ptr = params.constData();
706 DH *dh = q_d2i_DHparams(
nullptr,
reinterpret_cast<
const unsigned char **>(&ptr),
709 qFatal(
"q_d2i_DHparams failed to convert QSslDiffieHellmanParameters to DER form");
713 qCWarning(lcTlsBackend,
"Diffie-Hellman parameters are not supported, because OpenSSL v3 was built with deprecated API removed");
717#ifndef OPENSSL_NO_PSK
719 q_SSL_CTX_use_psk_identity_hint(sslContext->ctx, sslContext->sslConfiguration.preSharedKeyIdentityHint().constData());
722 const auto qcurves = sslContext->sslConfiguration.ellipticCurves();
723 if (!qcurves.isEmpty()) {
725 sslContext->errorStr = msgErrorSettingEllipticCurves(QSslSocket::tr(
"OpenSSL version with disabled elliptic curves"));
726 sslContext->errorCode = QSslError::UnspecifiedError;
730 std::vector<
int> curves;
731 curves.reserve(qcurves.size());
732 for (
const auto &sslCurve : qcurves)
733 curves.push_back(sslCurve.id);
734 if (!q_SSL_CTX_ctrl(sslContext->ctx, SSL_CTRL_SET_CURVES,
long(curves.size()), &curves[0])) {
735 sslContext->errorStr = msgErrorSettingEllipticCurves(QTlsBackendOpenSSL::getErrorsFromOpenSsl());
736 sslContext->errorCode = QSslError::UnspecifiedError;
742 applyBackendConfig(sslContext);
747 const QMap<QByteArray, QVariant> &conf = sslContext->sslConfiguration.backendConfiguration();
752 auto ocspResponsePos = conf.find(
"Qt-OCSP-response");
753 if (ocspResponsePos != conf.end()) {
757 q_SSL_CTX_set_tlsext_status_cb(sslContext->ctx, QTlsPrivate::qt_OCSP_status_server_callback);
758 if (conf.size() == 1)
763 QSharedPointer<SSL_CONF_CTX> cctx(q_SSL_CONF_CTX_new(), &q_SSL_CONF_CTX_free);
765 q_SSL_CONF_CTX_set_ssl_ctx(cctx.data(), sslContext->ctx);
766 q_SSL_CONF_CTX_set_flags(cctx.data(), SSL_CONF_FLAG_FILE);
768 for (
auto i = conf.constBegin(); i != conf.constEnd(); ++i) {
769 if (i.key() ==
"Qt-OCSP-response")
772 if (!i.value().canConvert(QMetaType(QMetaType::QByteArray))) {
773 sslContext->errorCode = QSslError::UnspecifiedError;
774 sslContext->errorStr = msgErrorSettingBackendConfig(
775 QSslSocket::tr(
"Expecting QByteArray for %1").arg(i.key()));
779 const QByteArray &value = i.value().toByteArray();
780 const int result = q_SSL_CONF_cmd(cctx.data(), i.key().constData(), value.constData());
784 sslContext->errorCode = QSslError::UnspecifiedError;
787 sslContext->errorStr = msgErrorSettingBackendConfig(
788 QSslSocket::tr(
"An error occurred attempting to set %1 to %2")
789 .arg(i.key(), value));
792 sslContext->errorStr = msgErrorSettingBackendConfig(
793 QSslSocket::tr(
"Wrong value for %1 (%2)").arg(i.key(), value));
796 sslContext->errorStr = msgErrorSettingBackendConfig(
797 QSslSocket::tr(
"Unrecognized command %1 = %2").arg(i.key(), value));
802 if (q_SSL_CONF_CTX_finish(cctx.data()) == 0) {
803 sslContext->errorStr = msgErrorSettingBackendConfig(QSslSocket::tr(
"SSL_CONF_finish() failed"));
804 sslContext->errorCode = QSslError::UnspecifiedError;
807 sslContext->errorStr = msgErrorSettingBackendConfig(QSslSocket::tr(
"SSL_CONF_CTX_new() failed"));
808 sslContext->errorCode = QSslError::UnspecifiedError;
QByteArray sessionASN1() const
int sessionTicketLifeTimeHint() const
NPNContext npnContext() const
QString errorString() const
static void forceAutoTestSecurityLevel()
void setSessionASN1(const QByteArray &sessionASN1)
QSslError::SslError error() const
Namespace containing onternal types that TLS backends implement.
int q_X509Callback(int ok, X509_STORE_CTX *ctx)
int q_X509CallbackDirect(int ok, X509_STORE_CTX *ctx)
static int next_proto_cb(SSL *, unsigned char **out, unsigned char *outlen, const unsigned char *in, unsigned int inlen, void *arg)
static QString msgErrorSettingEllipticCurves(const QString &why)
static QString msgErrorSettingBackendConfig(const QString &why)
void q_SSL_CTX_free(SSL_CTX *a)
const SSL_METHOD * q_TLS_server_method()
int q_EVP_PKEY_set1_DSA(EVP_PKEY *a, DSA *b)
int q_SSL_CTX_get_security_level(const SSL_CTX *ctx)
void q_SSL_SESSION_free(SSL_SESSION *ses)
int q_SSL_set_session(SSL *to, SSL_SESSION *session)
int q_EVP_PKEY_set1_RSA(EVP_PKEY *a, RSA *b)
int q_SSL_select_next_proto(unsigned char **out, unsigned char *outlen, const unsigned char *in, unsigned int inlen, const unsigned char *client, unsigned int client_len)
int q_EVP_PKEY_set1_EC_KEY(EVP_PKEY *a, EC_KEY *b)
SSL_CTX * q_SSL_CTX_new(const SSL_METHOD *a)
int q_SSL_CTX_use_certificate(SSL_CTX *a, X509 *b)
EVP_PKEY * q_EVP_PKEY_new()
void q_EVP_PKEY_free(EVP_PKEY *a)
#define q_SSL_CTX_set_min_proto_version(ctx, version)
int q_SSL_CTX_check_private_key(const SSL_CTX *a)
unsigned long q_SSL_SESSION_get_ticket_lifetime_hint(const SSL_SESSION *session)
int q_i2d_SSL_SESSION(SSL_SESSION *in, unsigned char **pp)
SSL_SESSION * q_SSL_get_session(const SSL *ssl)
void q_SSL_CTX_set_security_level(SSL_CTX *ctx, int level)
const SSL_METHOD * q_TLS_client_method()
SSL * q_SSL_new(SSL_CTX *a)
#define q_SSL_CTX_set_tmp_dh(ctx, dh)
#define q_SSL_CTX_set_dh_auto(ctx, onoff)
SSL_SESSION * q_SSL_get1_session(SSL *ssl)
int q_SSL_CTX_use_PrivateKey(SSL_CTX *a, EVP_PKEY *b)
void q_SSL_CTX_set_verify(SSL_CTX *a, int b, int(*c)(int, X509_STORE_CTX *))
#define q_SSL_CTX_set_mode(ctx, op)
qssloptions q_SSL_CTX_set_options(SSL_CTX *ctx, qssloptions op)
int q_OPENSSL_init_ssl(uint64_t opts, const OPENSSL_INIT_SETTINGS *settings)
#define q_SSL_CTX_set_max_proto_version(ctx, version)