8#include <QtNetwork/qsslsocket.h>
9#include <QtNetwork/qssldiffiehellmanparameters.h>
17#include <QtNetwork/private/qssl_p.h>
18#include <QtNetwork/private/qsslsocket_p.h>
19#include <QtNetwork/private/qtlsbackend_p.h>
21#include <QtNetwork/private/qssldiffiehellmanparameters_p.h>
27Q_GLOBAL_STATIC(
bool, forceSecurityLevel)
40int q_ssl_sess_set_new_cb(SSL *context, SSL_SESSION *session);
47namespace dtlscallbacks
49int q_X509DtlsCallback(
int ok, X509_STORE_CTX *ctx);
50int q_generate_cookie_callback(SSL *ssl,
unsigned char *dst,
unsigned *cookieLength);
51int q_verify_cookie_callback(SSL *ssl,
const unsigned char *cookie,
unsigned cookieLength);
57 return QSslSocket::tr(
"Error when setting the OpenSSL configuration (%1)").arg(why);
62 return QSslSocket::tr(
"Error when setting the elliptic curves (%1)").arg(why);
65qssloptions
QSslContext::setupOpenSslOptions(QSsl::SslProtocol protocol, QSsl::SslOptions sslOptions)
70QT_WARNING_DISABLE_DEPRECATED
71 case QSsl::TlsV1_0OrLater:
72 options = SSL_OP_ALL | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3;
74 case QSsl::TlsV1_1OrLater:
75 options = SSL_OP_ALL | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1;
78 case QSsl::SecureProtocols:
79 case QSsl::TlsV1_2OrLater:
80 options = SSL_OP_ALL | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1;
82 case QSsl::TlsV1_3OrLater:
83 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;
90 if (sslOptions & QSsl::SslOptionDisableEmptyFragments)
91 options |= SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS;
93 options &= ~SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS;
95#ifdef SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION
97 if (sslOptions & QSsl::SslOptionDisableLegacyRenegotiation)
98 options &= ~SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION;
100 options |= SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION;
103#ifdef SSL_OP_NO_TICKET
104 if (sslOptions & QSsl::SslOptionDisableSessionTickets)
105 options |= SSL_OP_NO_TICKET;
107#ifdef SSL_OP_NO_COMPRESSION
108 if (sslOptions & QSsl::SslOptionDisableCompression)
109 options |= SSL_OP_NO_COMPRESSION;
112 if (!(sslOptions & QSsl::SslOptionDisableServerCipherPreference))
113 options |= SSL_OP_CIPHER_SERVER_PREFERENCE;
122 m_sessionTicketLifeTimeHint(-1)
139std::shared_ptr<QSslContext>
QSslContext::sharedFromConfiguration(QSslSocket::SslMode mode,
const QSslConfiguration &configuration,
bool allowRootCertOnDemandLoading)
142 std::shared_ptr<QSslContext> sslContext = std::make_shared<AccessToPrivateCtor>();
143 initSslContext(sslContext.get(), mode, configuration, allowRootCertOnDemandLoading);
147std::shared_ptr<QSslContext>
QSslContext::sharedFromPrivateConfiguration(QSslSocket::SslMode mode, QSslConfigurationPrivate *privConfiguration,
148 bool allowRootCertOnDemandLoading)
150 return sharedFromConfiguration(mode, privConfiguration, allowRootCertOnDemandLoading);
153#ifndef OPENSSL_NO_NEXTPROTONEG
156 const unsigned char *in,
unsigned int inlen,
void *arg)
170 case OPENSSL_NPN_UNSUPPORTED:
171 ctx->status = QSslConfiguration::NextProtocolNegotiationNone;
173 case OPENSSL_NPN_NEGOTIATED:
174 ctx->status = QSslConfiguration::NextProtocolNegotiationNegotiated;
176 case OPENSSL_NPN_NO_OVERLAP:
177 ctx->status = QSslConfiguration::NextProtocolNegotiationUnsupported;
180 qCWarning(lcTlsBackend,
"OpenSSL sent unknown NPN status");
183 return SSL_TLSEXT_ERR_OK;
200 if (!session && !sessionASN1().isEmpty()
201 && !sslConfiguration.testSslOption(QSsl::SslOptionDisableSessionPersistence)) {
202 const unsigned char *data =
reinterpret_cast<
const unsigned char *>(m_sessionASN1.constData());
203 session = q_d2i_SSL_SESSION(
nullptr, &data, m_sessionASN1.size());
210 qCWarning(lcTlsBackend,
"could not set SSL session");
216#ifndef OPENSSL_NO_NEXTPROTONEG
217 QList<QByteArray> protocols = sslConfiguration.d.constData()->nextAllowedProtocols;
218 if (!protocols.isEmpty()) {
219 m_supportedNPNVersions.clear();
220 for (
int a = 0; a < protocols.size(); ++a) {
221 if (protocols.at(a).size() > 255) {
222 qCWarning(lcTlsBackend) <<
"TLS NPN extension" << protocols.at(a)
223 <<
"is too long and will be ignored.";
225 }
else if (protocols.at(a).isEmpty()) {
228 m_supportedNPNVersions.append(protocols.at(a).size()).append(protocols.at(a));
230 if (m_supportedNPNVersions.size()) {
231 m_npnContext.data =
reinterpret_cast<
unsigned char *>(m_supportedNPNVersions.data());
232 m_npnContext.len = m_supportedNPNVersions.size();
233 m_npnContext.status = QSslConfiguration::NextProtocolNegotiationNone;
238 typedef int (*alpn_callback_t) (SSL *,
const unsigned char **,
unsigned char *,
239 const unsigned char *,
unsigned int,
void *);
242 q_SSL_CTX_set_alpn_select_cb(ctx, alpn_callback_t(next_proto_cb), &m_npnContext);
244 q_SSL_set_alpn_protos(ssl, m_npnContext.data, m_npnContext.len);
246 q_SSL_CTX_set_next_proto_select_cb(ctx, next_proto_cb, &m_npnContext);
269 if (session && !sslConfiguration.testSslOption(QSsl::SslOptionDisableSessionPersistence)) {
271 if (sessionSize > 0) {
272 m_sessionASN1.resize(sessionSize);
273 unsigned char *data =
reinterpret_cast<
unsigned char *>(m_sessionASN1.data());
275 qCWarning(lcTlsBackend,
"could not store persistent version of SSL session");
280 return (session !=
nullptr);
285 return m_sessionASN1;
290 m_sessionASN1 = session;
295 return m_sessionTicketLifeTimeHint;
300 *forceSecurityLevel() =
true;
314 const QSslConfiguration &configuration)
316 auto qtKey = QTlsBackend::backend<QTlsPrivate::TlsKeyOpenSSL>(configuration.d->privateKey);
318 sslContext->pkey = qtKey->genericKey;
319 Q_ASSERT(sslContext->pkey);
324 const QSslConfiguration &configuration,
325 bool allowRootCertOnDemandLoading)
327 sslContext->sslConfiguration = configuration;
328 sslContext->errorCode = QSslError::NoError;
330 bool client = (mode == QSslSocket::SslClientMode);
332 bool reinitialized =
false;
333 bool unsupportedProtocol =
false;
336 switch (sslContext->sslConfiguration.protocol()) {
338QT_WARNING_DISABLE_DEPRECATED
340 case QSsl::DtlsV1_0OrLater:
343 case QSsl::DtlsV1_2OrLater:
346 sslContext->ctx = q_SSL_CTX_new(client ? q_DTLS_client_method() : q_DTLS_server_method());
348 sslContext->ctx =
nullptr;
349 unsupportedProtocol =
true;
350 qCWarning(lcTlsBackend,
"DTLS protocol requested, but feature 'dtls' is disabled");
354 case QSsl::TlsV1_3OrLater:
355#if !defined(TLS1_3_VERSION
)
356 qCWarning(lcTlsBackend,
"TLS 1.3 is not supported");
357 sslContext->ctx =
nullptr;
358 unsupportedProtocol =
true;
366 if (!sslContext->ctx) {
369 if (!reinitialized) {
370 reinitialized =
true;
375 sslContext->errorStr = QSslSocket::tr(
"Error creating SSL context (%1)").arg(
376 unsupportedProtocol ? QSslSocket::tr(
"unsupported protocol") : QTlsBackendOpenSSL::getErrorsFromOpenSsl()
378 sslContext->errorCode = QSslError::UnspecifiedError;
386 const long anyVersion =
388 isDtls ? DTLS_ANY_VERSION : TLS_ANY_VERSION;
392 long minVersion = anyVersion;
393 long maxVersion = anyVersion;
395 switch (sslContext->sslConfiguration.protocol()) {
397QT_WARNING_DISABLE_DEPRECATED
399 minVersion = TLS1_VERSION;
400 maxVersion = TLS1_VERSION;
403 minVersion = TLS1_1_VERSION;
404 maxVersion = TLS1_1_VERSION;
408 minVersion = TLS1_2_VERSION;
409 maxVersion = TLS1_2_VERSION;
413 minVersion = TLS1_3_VERSION;
414 maxVersion = TLS1_3_VERSION;
422 case QSsl::AnyProtocol:
424QT_WARNING_DISABLE_DEPRECATED
425 case QSsl::TlsV1_0OrLater:
426 minVersion = TLS1_VERSION;
429 case QSsl::TlsV1_1OrLater:
430 minVersion = TLS1_1_VERSION;
434 case QSsl::SecureProtocols:
435 case QSsl::TlsV1_2OrLater:
436 minVersion = TLS1_2_VERSION;
440QT_WARNING_DISABLE_DEPRECATED
442 minVersion = DTLS1_VERSION;
443 maxVersion = DTLS1_VERSION;
445 case QSsl::DtlsV1_0OrLater:
446 minVersion = DTLS1_VERSION;
451 minVersion = DTLS1_2_VERSION;
452 maxVersion = DTLS1_2_VERSION;
454 case QSsl::DtlsV1_2OrLater:
455 minVersion = DTLS1_2_VERSION;
458 case QSsl::TlsV1_3OrLater:
460 minVersion = TLS1_3_VERSION;
469 case QSsl::UnknownProtocol:
473 if (minVersion != anyVersion
475 sslContext->errorStr = QSslSocket::tr(
"Error while setting the minimal protocol version");
476 sslContext->errorCode = QSslError::UnspecifiedError;
480 if (maxVersion != anyVersion
482 sslContext->errorStr = QSslSocket::tr(
"Error while setting the maximum protocol version");
483 sslContext->errorCode = QSslError::UnspecifiedError;
488 const qssloptions options = setupOpenSslOptions(configuration.protocol(), configuration.d->sslOptions);
495 auto filterCiphers = [](
const QList<QSslCipher> &ciphers,
bool selectTls13)
497 QByteArray cipherString;
499 for (
const QSslCipher &cipher : ciphers) {
500 const bool isTls13Cipher = cipher.protocol() == QSsl::TlsV1_3 || cipher.protocol() == QSsl::TlsV1_3OrLater;
501 if (selectTls13 != isTls13Cipher)
504 if (cipherString.size())
505 cipherString.append(
':');
506 cipherString.append(cipher.name().toLatin1());
512 QList<QSslCipher> ciphers = sslContext->sslConfiguration.ciphers();
513 if (ciphers.isEmpty())
514 ciphers = isDtls ? QTlsBackend::defaultDtlsCiphers() : QTlsBackend::defaultCiphers();
516 const QByteArray preTls13Ciphers = filterCiphers(ciphers,
false);
518 if (preTls13Ciphers.size()) {
519 if (!q_SSL_CTX_set_cipher_list(sslContext->ctx, preTls13Ciphers.data())) {
520 sslContext->errorStr = QSslSocket::tr(
"Invalid or empty cipher list (%1)").arg(QTlsBackendOpenSSL::getErrorsFromOpenSsl());
521 sslContext->errorCode = QSslError::UnspecifiedError;
526 const QByteArray tls13Ciphers = filterCiphers(ciphers,
true);
528 if (tls13Ciphers.size()) {
529 if (!q_SSL_CTX_set_ciphersuites(sslContext->ctx, tls13Ciphers.data())) {
530 sslContext->errorStr = QSslSocket::tr(
"Invalid or empty cipher list (%1)").arg(QTlsBackendOpenSSL::getErrorsFromOpenSsl());
531 sslContext->errorCode = QSslError::UnspecifiedError;
536 if (!preTls13Ciphers.size() && !tls13Ciphers.size()) {
537 sslContext->errorStr = QSslSocket::tr(
"Invalid or empty cipher list (%1)").arg(QStringLiteral(
""));
538 sslContext->errorCode = QSslError::UnspecifiedError;
542 const QDateTime now = QDateTime::currentDateTimeUtc();
545 const auto caCertificates = sslContext->sslConfiguration.caCertificates();
546 for (
const QSslCertificate &caCertificate : caCertificates) {
558 if (caCertificate.expiryDate() >= now) {
559 q_X509_STORE_add_cert(q_SSL_CTX_get_cert_store(sslContext->ctx), (X509 *)caCertificate.handle());
563 if (QSslSocketPrivate::rootCertOnDemandLoadingSupported() && allowRootCertOnDemandLoading) {
565 const QList<QByteArray> unixDirs = QSslSocketPrivate::unixRootCertDirectories();
567#if OPENSSL_VERSION_MAJOR
< 3
568 for (
const QByteArray &unixDir : unixDirs) {
569 if ((success = q_SSL_CTX_load_verify_locations(sslContext->ctx,
nullptr, unixDir.constData())) != 1)
573 for (
const QByteArray &unixDir : unixDirs) {
574 if ((success = q_SSL_CTX_load_verify_dir(sslContext->ctx, unixDir.constData())) != 1)
579 const auto qtErrors = QTlsBackendOpenSSL::getErrorsFromOpenSsl();
580 qCWarning(lcTlsBackend) <<
"An error encountered while to set root certificates location:"
585 if (!sslContext->sslConfiguration.localCertificate().isNull()) {
587 if (sslContext->sslConfiguration.privateKey().isNull()) {
588 sslContext->errorStr = QSslSocket::tr(
"Cannot provide a certificate with no key");
589 sslContext->errorCode = QSslError::UnspecifiedError;
595 sslContext->errorStr = QSslSocket::tr(
"Error loading local certificate, %1").arg(QTlsBackendOpenSSL::getErrorsFromOpenSsl());
596 sslContext->errorCode = QSslError::UnspecifiedError;
600 const auto algorithm = configuration.d->privateKey.algorithm();
601 bool useOpaqueHandle =
false;
603 if (algorithm == QSsl::Opaque)
604 useOpaqueHandle =
true;
605#if OPENSSL_VERSION_NUMBER
< 0x3050000fL
608 if (algorithm == QSsl::MlDsa)
609 useOpaqueHandle =
true;
612 if (useOpaqueHandle) {
613 sslContext->pkey =
reinterpret_cast<EVP_PKEY *>(configuration.d->privateKey.handle());
614#if OPENSSL_VERSION_NUMBER
>= 0x3050000fL
615 }
else if (algorithm == QSsl::MlDsa) {
616 setGenericPrivateKey(sslContext, configuration);
619#ifdef OPENSSL_NO_DEPRECATED_3_0
620 setGenericPrivateKey(sslContext, configuration);
627 if (algorithm == QSsl::Rsa)
629 else if (algorithm == QSsl::Dsa)
632 else if (algorithm == QSsl::Ec)
637 auto pkey = sslContext->pkey;
639 sslContext->pkey =
nullptr;
642 sslContext->errorStr = QSslSocket::tr(
"Error loading private key, %1").arg(QTlsBackendOpenSSL::getErrorsFromOpenSsl());
643 sslContext->errorCode = QSslError::UnspecifiedError;
649 sslContext->errorStr = QSslSocket::tr(
"Private key does not certify public key, %1").arg(QTlsBackendOpenSSL::getErrorsFromOpenSsl());
650 sslContext->errorCode = QSslError::UnspecifiedError;
656 for (
const QSslCertificate &cert : std::as_const(configuration.d->localCertificateChain)) {
661 q_SSL_CTX_ctrl(sslContext->ctx, SSL_CTRL_EXTRA_CHAIN_CERT, 0,
662 q_X509_dup(
reinterpret_cast<X509 *>(cert.handle())));
668 if (sslContext->sslConfiguration.peerVerifyMode() == QSslSocket::VerifyNone) {
671 auto verificationCallback =
673 isDtls ? dtlscallbacks::q_X509DtlsCallback :
677 if (!isDtls && configuration.handshakeMustInterruptOnError())
680 auto verificationMode = SSL_VERIFY_PEER;
681 if (!isDtls && sslContext->sslConfiguration.missingCertificateIsFatal())
682 verificationMode |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
689 if (mode == QSslSocket::SslClientMode && !isDtls) {
690 q_SSL_CTX_sess_set_new_cb(sslContext->ctx,
QTlsPrivate::q_ssl_sess_set_new_cb);
691 q_SSL_CTX_set_session_cache_mode(sslContext->ctx, SSL_SESS_CACHE_CLIENT);
698 if (mode == QSslSocket::SslServerMode && isDtls && configuration.dtlsCookieVerificationEnabled()) {
699 q_SSL_CTX_set_cookie_generate_cb(sslContext->ctx, dtlscallbacks::q_generate_cookie_callback);
700 q_SSL_CTX_set_cookie_verify_cb(sslContext->ctx, dtlscallbacks::q_verify_cookie_callback);
705 if (sslContext->sslConfiguration.peerVerifyDepth() != 0)
706 q_SSL_CTX_set_verify_depth(sslContext->ctx, sslContext->sslConfiguration.peerVerifyDepth());
709 if (!configuration.sessionTicket().isEmpty())
710 sslContext->setSessionASN1(configuration.sessionTicket());
713 QSslDiffieHellmanParameters dhparams = configuration.diffieHellmanParameters();
715 if (!dhparams.isValid()) {
716 sslContext->errorStr = QSslSocket::tr(
"Diffie-Hellman parameters are not valid");
717 sslContext->errorCode = QSslError::UnspecifiedError;
721 if (dhparams.isEmpty()) {
724#ifndef OPENSSL_NO_DEPRECATED_3_0
725 const QByteArray ¶ms = dhparams.d->derData;
726 const char *ptr = params.constData();
727 DH *dh = q_d2i_DHparams(
nullptr,
reinterpret_cast<
const unsigned char **>(&ptr),
730 qFatal(
"q_d2i_DHparams failed to convert QSslDiffieHellmanParameters to DER form");
734 qCWarning(lcTlsBackend,
"Diffie-Hellman parameters are not supported, because OpenSSL v3 was built with deprecated API removed");
738#ifndef OPENSSL_NO_PSK
740 q_SSL_CTX_use_psk_identity_hint(sslContext->ctx, sslContext->sslConfiguration.preSharedKeyIdentityHint().constData());
743 const auto qcurves = sslContext->sslConfiguration.ellipticCurves();
744 if (!qcurves.isEmpty()) {
746 sslContext->errorStr = msgErrorSettingEllipticCurves(QSslSocket::tr(
"OpenSSL version with disabled elliptic curves"));
747 sslContext->errorCode = QSslError::UnspecifiedError;
751 std::vector<
int> curves;
752 curves.reserve(qcurves.size());
753 for (
const auto &sslCurve : qcurves)
754 curves.push_back(sslCurve.id);
755 if (!q_SSL_CTX_ctrl(sslContext->ctx, SSL_CTRL_SET_CURVES,
long(curves.size()), &curves[0])) {
756 sslContext->errorStr = msgErrorSettingEllipticCurves(QTlsBackendOpenSSL::getErrorsFromOpenSsl());
757 sslContext->errorCode = QSslError::UnspecifiedError;
763 applyBackendConfig(sslContext);
768 const QMap<QByteArray, QVariant> &conf = sslContext->sslConfiguration.backendConfiguration();
773 auto ocspResponsePos = conf.find(
"Qt-OCSP-response");
774 if (ocspResponsePos != conf.end()) {
778 q_SSL_CTX_set_tlsext_status_cb(sslContext->ctx, QTlsPrivate::qt_OCSP_status_server_callback);
779 if (conf.size() == 1)
784 QSharedPointer<SSL_CONF_CTX> cctx(q_SSL_CONF_CTX_new(), &q_SSL_CONF_CTX_free);
786 q_SSL_CONF_CTX_set_ssl_ctx(cctx.data(), sslContext->ctx);
787 q_SSL_CONF_CTX_set_flags(cctx.data(), SSL_CONF_FLAG_FILE);
789 for (
auto i = conf.constBegin(); i != conf.constEnd(); ++i) {
790 if (i.key() ==
"Qt-OCSP-response")
793 if (!i.value().canConvert(QMetaType(QMetaType::QByteArray))) {
794 sslContext->errorCode = QSslError::UnspecifiedError;
795 sslContext->errorStr = msgErrorSettingBackendConfig(
796 QSslSocket::tr(
"Expecting QByteArray for %1").arg(i.key()));
800 const QByteArray &value = i.value().toByteArray();
801 const int result = q_SSL_CONF_cmd(cctx.data(), i.key().constData(), value.constData());
805 sslContext->errorCode = QSslError::UnspecifiedError;
808 sslContext->errorStr = msgErrorSettingBackendConfig(
809 QSslSocket::tr(
"An error occurred attempting to set %1 to %2")
810 .arg(i.key(), value));
813 sslContext->errorStr = msgErrorSettingBackendConfig(
814 QSslSocket::tr(
"Wrong value for %1 (%2)").arg(i.key(), value));
817 sslContext->errorStr = msgErrorSettingBackendConfig(
818 QSslSocket::tr(
"Unrecognized command %1 = %2").arg(i.key(), value));
823 if (q_SSL_CONF_CTX_finish(cctx.data()) == 0) {
824 sslContext->errorStr = msgErrorSettingBackendConfig(QSslSocket::tr(
"SSL_CONF_finish() failed"));
825 sslContext->errorCode = QSslError::UnspecifiedError;
828 sslContext->errorStr = msgErrorSettingBackendConfig(QSslSocket::tr(
"SSL_CONF_CTX_new() failed"));
829 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)
int q_EVP_PKEY_up_ref(EVP_PKEY *a)
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)