1 /****************************************************************************
2 **
3 ** Copyright (C) 2017 The Qt Company Ltd.
4 ** Copyright (C) 2014 BlackBerry Limited. All rights reserved.
5 ** Copyright (C) 2014 Governikus GmbH & Co. KG.
6 ** Copyright (C) 2016 Richard J. Moore <rich@kde.org>
7 ** Contact: https://www.qt.io/licensing/
8 **
9 ** This file is part of the QtNetwork module of the Qt Toolkit.
10 **
11 ** $QT_BEGIN_LICENSE:LGPL$
12 ** Commercial License Usage
13 ** Licensees holding valid commercial Qt licenses may use this file in
14 ** accordance with the commercial license agreement provided with the
15 ** Software or, alternatively, in accordance with the terms contained in
16 ** a written agreement between you and The Qt Company. For licensing terms
17 ** and conditions see https://www.qt.io/terms-conditions. For further
18 ** information use the contact form at https://www.qt.io/contact-us.
19 **
20 ** GNU Lesser General Public License Usage
21 ** Alternatively, this file may be used under the terms of the GNU Lesser
22 ** General Public License version 3 as published by the Free Software
23 ** Foundation and appearing in the file LICENSE.LGPL3 included in the
24 ** packaging of this file. Please review the following information to
25 ** ensure the GNU Lesser General Public License version 3 requirements
26 ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
27 **
28 ** GNU General Public License Usage
29 ** Alternatively, this file may be used under the terms of the GNU
30 ** General Public License version 2.0 or (at your option) the GNU General
31 ** Public license version 3 or any later version approved by the KDE Free
32 ** Qt Foundation. The licenses are as published by the Free Software
33 ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
34 ** included in the packaging of this file. Please review the following
35 ** information to ensure the GNU General Public License requirements will
36 ** be met: https://www.gnu.org/licenses/gpl-2.0.html and
37 ** https://www.gnu.org/licenses/gpl-3.0.html.
38 **
39 ** $QT_END_LICENSE$
40 **
41 ****************************************************************************/
42 
43 #include <QtNetwork/qsslsocket.h>
44 #include <QtNetwork/qssldiffiehellmanparameters.h>
45 
46 #include "private/qssl_p.h"
47 #include "private/qsslsocket_p.h"
48 #include "private/qsslcontext_openssl_p.h"
49 #include "private/qsslsocket_openssl_p.h"
50 #include "private/qsslsocket_openssl_symbols_p.h"
51 #include "private/qssldiffiehellmanparameters_p.h"
52 
53 #include <vector>
54 
55 QT_BEGIN_NAMESPACE
56 
Q_GLOBAL_STATIC(bool,forceSecurityLevel)57 Q_GLOBAL_STATIC(bool, forceSecurityLevel)
58 
59 Q_NETWORK_EXPORT void qt_ForceTlsSecurityLevel()
60 {
61     *forceSecurityLevel() = true;
62 }
63 
64 // defined in qsslsocket_openssl.cpp:
65 extern int q_X509Callback(int ok, X509_STORE_CTX *ctx);
66 extern QString getErrorsFromOpenSsl();
67 
68 #if QT_CONFIG(dtls)
69 // defined in qdtls_openssl.cpp:
70 namespace dtlscallbacks
71 {
72 extern "C" int q_X509DtlsCallback(int ok, X509_STORE_CTX *ctx);
73 extern "C" int q_generate_cookie_callback(SSL *ssl, unsigned char *dst,
74                                           unsigned *cookieLength);
75 extern "C" int q_verify_cookie_callback(SSL *ssl, const unsigned char *cookie,
76                                         unsigned cookieLength);
77 }
78 #endif // dtls
79 
80 #ifdef TLS1_3_VERSION
81 extern "C" int q_ssl_sess_set_new_cb(SSL *context, SSL_SESSION *session);
82 #endif // TLS1_3_VERSION
83 
84 // Defined in qsslsocket.cpp
85 QList<QSslCipher> q_getDefaultDtlsCiphers();
86 
msgErrorSettingBackendConfig(const QString & why)87 static inline QString msgErrorSettingBackendConfig(const QString &why)
88 {
89     return QSslSocket::tr("Error when setting the OpenSSL configuration (%1)").arg(why);
90 }
91 
msgErrorSettingEllipticCurves(const QString & why)92 static inline QString msgErrorSettingEllipticCurves(const QString &why)
93 {
94     return QSslSocket::tr("Error when setting the elliptic curves (%1)").arg(why);
95 }
96 
QSslContext()97 QSslContext::QSslContext()
98     : ctx(nullptr),
99     pkey(nullptr),
100     session(nullptr),
101     m_sessionTicketLifeTimeHint(-1)
102 {
103 }
104 
~QSslContext()105 QSslContext::~QSslContext()
106 {
107     if (ctx)
108         // This will decrement the reference count by 1 and free the context eventually when possible
109         q_SSL_CTX_free(ctx);
110 
111     if (pkey)
112         q_EVP_PKEY_free(pkey);
113 
114     if (session)
115         q_SSL_SESSION_free(session);
116 }
117 
fromConfiguration(QSslSocket::SslMode mode,const QSslConfiguration & configuration,bool allowRootCertOnDemandLoading)118 QSslContext* QSslContext::fromConfiguration(QSslSocket::SslMode mode, const QSslConfiguration &configuration, bool allowRootCertOnDemandLoading)
119 {
120     QSslContext *sslContext = new QSslContext();
121     initSslContext(sslContext, mode, configuration, allowRootCertOnDemandLoading);
122     return sslContext;
123 }
124 
sharedFromConfiguration(QSslSocket::SslMode mode,const QSslConfiguration & configuration,bool allowRootCertOnDemandLoading)125 QSharedPointer<QSslContext> QSslContext::sharedFromConfiguration(QSslSocket::SslMode mode, const QSslConfiguration &configuration, bool allowRootCertOnDemandLoading)
126 {
127     QSharedPointer<QSslContext> sslContext = QSharedPointer<QSslContext>::create();
128     initSslContext(sslContext.data(), mode, configuration, allowRootCertOnDemandLoading);
129     return sslContext;
130 }
131 
132 #ifndef OPENSSL_NO_NEXTPROTONEG
133 
next_proto_cb(SSL *,unsigned char ** out,unsigned char * outlen,const unsigned char * in,unsigned int inlen,void * arg)134 static int next_proto_cb(SSL *, unsigned char **out, unsigned char *outlen,
135                          const unsigned char *in, unsigned int inlen, void *arg)
136 {
137     QSslContext::NPNContext *ctx = reinterpret_cast<QSslContext::NPNContext *>(arg);
138 
139     // comment out to debug:
140 //    QList<QByteArray> supportedVersions;
141 //    for (unsigned int i = 0; i < inlen; ) {
142 //        QByteArray version(reinterpret_cast<const char *>(&in[i+1]), in[i]);
143 //        supportedVersions << version;
144 //        i += in[i] + 1;
145 //    }
146 
147     int proto = q_SSL_select_next_proto(out, outlen, in, inlen, ctx->data, ctx->len);
148     switch (proto) {
149     case OPENSSL_NPN_UNSUPPORTED:
150         ctx->status = QSslConfiguration::NextProtocolNegotiationNone;
151         break;
152     case OPENSSL_NPN_NEGOTIATED:
153         ctx->status = QSslConfiguration::NextProtocolNegotiationNegotiated;
154         break;
155     case OPENSSL_NPN_NO_OVERLAP:
156         ctx->status = QSslConfiguration::NextProtocolNegotiationUnsupported;
157         break;
158     default:
159         qCWarning(lcSsl, "OpenSSL sent unknown NPN status");
160     }
161 
162     return SSL_TLSEXT_ERR_OK;
163 }
164 
npnContext() const165 QSslContext::NPNContext QSslContext::npnContext() const
166 {
167     return m_npnContext;
168 }
169 #endif // !OPENSSL_NO_NEXTPROTONEG
170 
171 
172 
173 // Needs to be deleted by caller
createSsl()174 SSL* QSslContext::createSsl()
175 {
176     SSL* ssl = q_SSL_new(ctx);
177     q_SSL_clear(ssl);
178 
179     if (!session && !sessionASN1().isEmpty()
180             && !sslConfiguration.testSslOption(QSsl::SslOptionDisableSessionPersistence)) {
181         const unsigned char *data = reinterpret_cast<const unsigned char *>(m_sessionASN1.constData());
182         session = q_d2i_SSL_SESSION(nullptr, &data, m_sessionASN1.size());
183         // 'session' has refcount 1 already, set by the function above
184     }
185 
186     if (session) {
187         // Try to resume the last session we cached
188         if (!q_SSL_set_session(ssl, session)) {
189             qCWarning(lcSsl, "could not set SSL session");
190             q_SSL_SESSION_free(session);
191             session = nullptr;
192         }
193     }
194 
195 #ifndef OPENSSL_NO_NEXTPROTONEG
196     QList<QByteArray> protocols = sslConfiguration.d->nextAllowedProtocols;
197     if (!protocols.isEmpty()) {
198         m_supportedNPNVersions.clear();
199         for (int a = 0; a < protocols.count(); ++a) {
200             if (protocols.at(a).size() > 255) {
201                 qCWarning(lcSsl) << "TLS NPN extension" << protocols.at(a)
202                                  << "is too long and will be ignored.";
203                 continue;
204             } else if (protocols.at(a).isEmpty()) {
205                 continue;
206             }
207             m_supportedNPNVersions.append(protocols.at(a).size()).append(protocols.at(a));
208         }
209         if (m_supportedNPNVersions.size()) {
210             m_npnContext.data = reinterpret_cast<unsigned char *>(m_supportedNPNVersions.data());
211             m_npnContext.len = m_supportedNPNVersions.count();
212             m_npnContext.status = QSslConfiguration::NextProtocolNegotiationNone;
213             // Callback's type has a parameter 'const unsigned char ** out'
214             // since it was introduced in 1.0.2. Internally, OpenSSL's own code
215             // (tests/examples) cast it to unsigned char * (since it's 'out').
216             // We just re-use our NPN callback and cast here:
217             typedef int (*alpn_callback_t) (SSL *, const unsigned char **, unsigned char *,
218                                             const unsigned char *, unsigned int, void *);
219             // With ALPN callback is for a server side only, for a client m_npnContext.status
220             // will stay in NextProtocolNegotiationNone.
221             q_SSL_CTX_set_alpn_select_cb(ctx, alpn_callback_t(next_proto_cb), &m_npnContext);
222             // Client:
223             q_SSL_set_alpn_protos(ssl, m_npnContext.data, m_npnContext.len);
224             // And in case our peer does not support ALPN, but supports NPN:
225             q_SSL_CTX_set_next_proto_select_cb(ctx, next_proto_cb, &m_npnContext);
226         }
227     }
228 #endif // !OPENSSL_NO_NEXTPROTONEG
229 
230     return ssl;
231 }
232 
233 // We cache exactly one session here
cacheSession(SSL * ssl)234 bool QSslContext::cacheSession(SSL* ssl)
235 {
236     // don't cache the same session again
237     if (session && session == q_SSL_get_session(ssl))
238         return true;
239 
240     // decrease refcount of currently stored session
241     // (this might happen if there are several concurrent handshakes in flight)
242     if (session)
243         q_SSL_SESSION_free(session);
244 
245     // cache the session the caller gave us and increase reference count
246     session = q_SSL_get1_session(ssl);
247 
248     if (session && !sslConfiguration.testSslOption(QSsl::SslOptionDisableSessionPersistence)) {
249         int sessionSize = q_i2d_SSL_SESSION(session, nullptr);
250         if (sessionSize > 0) {
251             m_sessionASN1.resize(sessionSize);
252             unsigned char *data = reinterpret_cast<unsigned char *>(m_sessionASN1.data());
253             if (!q_i2d_SSL_SESSION(session, &data))
254                 qCWarning(lcSsl, "could not store persistent version of SSL session");
255             m_sessionTicketLifeTimeHint = q_SSL_SESSION_get_ticket_lifetime_hint(session);
256         }
257     }
258 
259     return (session != nullptr);
260 }
261 
sessionASN1() const262 QByteArray QSslContext::sessionASN1() const
263 {
264     return m_sessionASN1;
265 }
266 
setSessionASN1(const QByteArray & session)267 void QSslContext::setSessionASN1(const QByteArray &session)
268 {
269     m_sessionASN1 = session;
270 }
271 
sessionTicketLifeTimeHint() const272 int QSslContext::sessionTicketLifeTimeHint() const
273 {
274     return m_sessionTicketLifeTimeHint;
275 }
276 
error() const277 QSslError::SslError QSslContext::error() const
278 {
279     return errorCode;
280 }
281 
errorString() const282 QString QSslContext::errorString() const
283 {
284     return errorStr;
285 }
286 
initSslContext(QSslContext * sslContext,QSslSocket::SslMode mode,const QSslConfiguration & configuration,bool allowRootCertOnDemandLoading)287 void QSslContext::initSslContext(QSslContext *sslContext, QSslSocket::SslMode mode,
288                                  const QSslConfiguration &configuration,
289                                  bool allowRootCertOnDemandLoading)
290 {
291     sslContext->sslConfiguration = configuration;
292     sslContext->errorCode = QSslError::NoError;
293 
294     bool client = (mode == QSslSocket::SslClientMode);
295 
296     bool reinitialized = false;
297     bool unsupportedProtocol = false;
298     bool isDtls = false;
299 init_context:
300     if (sslContext->sslConfiguration.protocol() == QSsl::SslV2) {
301         // SSL 2 is no longer supported, but chosen deliberately -> error
302         sslContext->ctx = nullptr;
303         unsupportedProtocol = true;
304     } else if (sslContext->sslConfiguration.protocol() == QSsl::SslV3) {
305         // SSL 3 is no longer supported, but chosen deliberately -> error
306         sslContext->ctx = nullptr;
307         unsupportedProtocol = true;
308     } else {
309         switch (sslContext->sslConfiguration.protocol()) {
310         case QSsl::DtlsV1_0:
311         case QSsl::DtlsV1_0OrLater:
312         case QSsl::DtlsV1_2:
313         case QSsl::DtlsV1_2OrLater:
314 #if QT_CONFIG(dtls)
315             isDtls = true;
316             sslContext->ctx = q_SSL_CTX_new(client ? q_DTLS_client_method() : q_DTLS_server_method());
317 #else // dtls
318             sslContext->ctx = nullptr;
319             unsupportedProtocol = true;
320             qCWarning(lcSsl, "DTLS protocol requested, but feature 'dtls' is disabled");
321 
322 #endif // dtls
323             break;
324         case QSsl::TlsV1_3:
325         case QSsl::TlsV1_3OrLater:
326 #if !defined(TLS1_3_VERSION)
327             qCWarning(lcSsl, "TLS 1.3 is not supported");
328             sslContext->ctx = nullptr;
329             unsupportedProtocol = true;
330             break;
331 #endif // TLS1_3_VERSION
332         default:
333             // The ssl options will actually control the supported methods
334             sslContext->ctx = q_SSL_CTX_new(client ? q_TLS_client_method() : q_TLS_server_method());
335         }
336     }
337 
338     if (!sslContext->ctx) {
339         // After stopping Flash 10 the SSL library loses its ciphers. Try re-adding them
340         // by re-initializing the library.
341         if (!reinitialized) {
342             reinitialized = true;
343             if (q_OPENSSL_init_ssl(0, nullptr) == 1)
344                 goto init_context;
345         }
346 
347         sslContext->errorStr = QSslSocket::tr("Error creating SSL context (%1)").arg(
348             unsupportedProtocol ? QSslSocket::tr("unsupported protocol") : QSslSocketBackendPrivate::getErrorsFromOpenSsl()
349         );
350         sslContext->errorCode = QSslError::UnspecifiedError;
351         return;
352     }
353 
354     // A nasty hacked OpenSSL using a level that will make our auto-tests fail:
355     if (q_SSL_CTX_get_security_level(sslContext->ctx) > 1 && *forceSecurityLevel())
356         q_SSL_CTX_set_security_level(sslContext->ctx, 1);
357 
358     const long anyVersion =
359 #if QT_CONFIG(dtls)
360                             isDtls ? DTLS_ANY_VERSION : TLS_ANY_VERSION;
361 #else
362                             TLS_ANY_VERSION;
363 #endif // dtls
364     long minVersion = anyVersion;
365     long maxVersion = anyVersion;
366 
367     switch (sslContext->sslConfiguration.protocol()) {
368     case QSsl::TlsV1_0:
369         minVersion = TLS1_VERSION;
370         maxVersion = TLS1_VERSION;
371         break;
372     case QSsl::TlsV1_1:
373         minVersion = TLS1_1_VERSION;
374         maxVersion = TLS1_1_VERSION;
375         break;
376     case QSsl::TlsV1_2:
377         minVersion = TLS1_2_VERSION;
378         maxVersion = TLS1_2_VERSION;
379         break;
380     case QSsl::TlsV1_3:
381 #ifdef TLS1_3_VERSION
382         minVersion = TLS1_3_VERSION;
383         maxVersion = TLS1_3_VERSION;
384 #else
385         // This protocol is not supported by OpenSSL 1.1 and we handle
386         // it as an error (see the code above).
387         Q_UNREACHABLE();
388 #endif // TLS1_3_VERSION
389         break;
390     // Ranges:
391     case QSsl::TlsV1SslV3:
392     case QSsl::AnyProtocol:
393     case QSsl::SecureProtocols:
394     case QSsl::TlsV1_0OrLater:
395         minVersion = TLS1_VERSION;
396         maxVersion = 0;
397         break;
398     case QSsl::TlsV1_1OrLater:
399         minVersion = TLS1_1_VERSION;
400         maxVersion = 0;
401         break;
402     case QSsl::TlsV1_2OrLater:
403         minVersion = TLS1_2_VERSION;
404         maxVersion = 0;
405         break;
406     case QSsl::DtlsV1_0:
407         minVersion = DTLS1_VERSION;
408         maxVersion = DTLS1_VERSION;
409         break;
410     case QSsl::DtlsV1_0OrLater:
411         minVersion = DTLS1_VERSION;
412         maxVersion = DTLS_MAX_VERSION;
413         break;
414     case QSsl::DtlsV1_2:
415         minVersion = DTLS1_2_VERSION;
416         maxVersion = DTLS1_2_VERSION;
417         break;
418     case QSsl::DtlsV1_2OrLater:
419         minVersion = DTLS1_2_VERSION;
420         maxVersion = DTLS_MAX_VERSION;
421         break;
422     case QSsl::TlsV1_3OrLater:
423 #ifdef TLS1_3_VERSION
424         minVersion = TLS1_3_VERSION;
425         maxVersion = 0;
426         break;
427 #else
428         // This protocol is not supported by OpenSSL 1.1 and we handle
429         // it as an error (see the code above).
430         Q_UNREACHABLE();
431         break;
432 #endif // TLS1_3_VERSION
433     case QSsl::SslV2:
434     case QSsl::SslV3:
435         // These protocols are not supported, and we handle
436         // them as an error (see the code above).
437         Q_UNREACHABLE();
438         break;
439     case QSsl::UnknownProtocol:
440         break;
441     }
442 
443     if (minVersion != anyVersion
444         && !q_SSL_CTX_set_min_proto_version(sslContext->ctx, minVersion)) {
445         sslContext->errorStr = QSslSocket::tr("Error while setting the minimal protocol version");
446         sslContext->errorCode = QSslError::UnspecifiedError;
447         return;
448     }
449 
450     if (maxVersion != anyVersion
451         && !q_SSL_CTX_set_max_proto_version(sslContext->ctx, maxVersion)) {
452         sslContext->errorStr = QSslSocket::tr("Error while setting the maximum protocol version");
453         sslContext->errorCode = QSslError::UnspecifiedError;
454         return;
455     }
456 
457     // Enable bug workarounds.
458     long options = QSslSocketBackendPrivate::setupOpenSslOptions(configuration.protocol(), configuration.d->sslOptions);
459     q_SSL_CTX_set_options(sslContext->ctx, options);
460 
461     // Tell OpenSSL to release memory early
462     // http://www.openssl.org/docs/ssl/SSL_CTX_set_mode.html
463     q_SSL_CTX_set_mode(sslContext->ctx, SSL_MODE_RELEASE_BUFFERS);
464 
465     auto filterCiphers = [](const QList<QSslCipher> &ciphers, bool selectTls13)
466     {
467         QByteArray cipherString;
468         bool first = true;
469 
470         for (const QSslCipher &cipher : qAsConst(ciphers)) {
471             const bool isTls13Cipher = cipher.protocol() == QSsl::TlsV1_3 || cipher.protocol() == QSsl::TlsV1_3OrLater;
472             if (selectTls13 != isTls13Cipher)
473                 continue;
474 
475             if (first)
476                 first = false;
477             else
478                 cipherString.append(':');
479             cipherString.append(cipher.name().toLatin1());
480         }
481         return cipherString;
482     };
483 
484     // Initialize ciphers
485     QList<QSslCipher> ciphers = sslContext->sslConfiguration.ciphers();
486     if (ciphers.isEmpty())
487         ciphers = isDtls ? q_getDefaultDtlsCiphers() : QSslSocketPrivate::defaultCiphers();
488 
489     const QByteArray preTls13Ciphers = filterCiphers(ciphers, false);
490 
491     if (preTls13Ciphers.size()) {
492         if (!q_SSL_CTX_set_cipher_list(sslContext->ctx, preTls13Ciphers.data())) {
493             sslContext->errorStr = QSslSocket::tr("Invalid or empty cipher list (%1)").arg(QSslSocketBackendPrivate::getErrorsFromOpenSsl());
494             sslContext->errorCode = QSslError::UnspecifiedError;
495             return;
496         }
497     }
498 
499     const QByteArray tls13Ciphers = filterCiphers(ciphers, true);
500 #ifdef TLS1_3_VERSION
501     if (tls13Ciphers.size()) {
502         if (!q_SSL_CTX_set_ciphersuites(sslContext->ctx, tls13Ciphers.data())) {
503             sslContext->errorStr = QSslSocket::tr("Invalid or empty cipher list (%1)").arg(QSslSocketBackendPrivate::getErrorsFromOpenSsl());
504             sslContext->errorCode = QSslError::UnspecifiedError;
505             return;
506         }
507     }
508 #endif // TLS1_3_VERSION
509     if (!preTls13Ciphers.size() && !tls13Ciphers.size()) {
510         sslContext->errorStr = QSslSocket::tr("Invalid or empty cipher list (%1)").arg(QStringLiteral(""));
511         sslContext->errorCode = QSslError::UnspecifiedError;
512         return;
513     }
514 
515     const QDateTime now = QDateTime::currentDateTimeUtc();
516 
517     // Add all our CAs to this store.
518     const auto caCertificates = sslContext->sslConfiguration.caCertificates();
519     for (const QSslCertificate &caCertificate : caCertificates) {
520         // From https://www.openssl.org/docs/ssl/SSL_CTX_load_verify_locations.html:
521         //
522         // If several CA certificates matching the name, key identifier, and
523         // serial number condition are available, only the first one will be
524         // examined. This may lead to unexpected results if the same CA
525         // certificate is available with different expiration dates. If a
526         // ``certificate expired'' verification error occurs, no other
527         // certificate will be searched. Make sure to not have expired
528         // certificates mixed with valid ones.
529         //
530         // See also: QSslSocketBackendPrivate::verify()
531         if (caCertificate.expiryDate() >= now) {
532             q_X509_STORE_add_cert(q_SSL_CTX_get_cert_store(sslContext->ctx), (X509 *)caCertificate.handle());
533         }
534     }
535 
536     if (QSslSocketPrivate::s_loadRootCertsOnDemand && allowRootCertOnDemandLoading) {
537         // tell OpenSSL the directories where to look up the root certs on demand
538         const QList<QByteArray> unixDirs = QSslSocketPrivate::unixRootCertDirectories();
539         int success = 1;
540 #if OPENSSL_VERSION_MAJOR < 3
541         for (const QByteArray &unixDir : unixDirs) {
542             if ((success = q_SSL_CTX_load_verify_locations(sslContext->ctx, nullptr, unixDir.constData())) != 1)
543                 break;
544         }
545 #else
546         for (const QByteArray &unixDir : unixDirs) {
547             if ((success = q_SSL_CTX_load_verify_dir(sslContext->ctx, unixDir.constData())) != 1)
548                 break;
549         }
550 #endif // OPENSSL_VERSION_MAJOR
551         if (success != 1) {
552             const auto qtErrors = QSslSocketBackendPrivate::getErrorsFromOpenSsl();
553             qCWarning(lcSsl) << "An error encountered while to set root certificates location:"
554                               << qtErrors;
555         }
556     }
557 
558     if (!sslContext->sslConfiguration.localCertificate().isNull()) {
559         // Require a private key as well.
560         if (sslContext->sslConfiguration.privateKey().isNull()) {
561             sslContext->errorStr = QSslSocket::tr("Cannot provide a certificate with no key, %1").arg(QSslSocketBackendPrivate::getErrorsFromOpenSsl());
562             sslContext->errorCode = QSslError::UnspecifiedError;
563             return;
564         }
565 
566         // Load certificate
567         if (!q_SSL_CTX_use_certificate(sslContext->ctx, (X509 *)sslContext->sslConfiguration.localCertificate().handle())) {
568             sslContext->errorStr = QSslSocket::tr("Error loading local certificate, %1").arg(QSslSocketBackendPrivate::getErrorsFromOpenSsl());
569             sslContext->errorCode = QSslError::UnspecifiedError;
570             return;
571         }
572 
573         if (configuration.d->privateKey.algorithm() == QSsl::Opaque) {
574             sslContext->pkey = reinterpret_cast<EVP_PKEY *>(configuration.d->privateKey.handle());
575         } else {
576             // Load private key
577             sslContext->pkey = q_EVP_PKEY_new();
578             // before we were using EVP_PKEY_assign_R* functions and did not use EVP_PKEY_free.
579             // this lead to a memory leak. Now we use the *_set1_* functions which do not
580             // take ownership of the RSA/DSA key instance because the QSslKey already has ownership.
581             if (configuration.d->privateKey.algorithm() == QSsl::Rsa)
582                 q_EVP_PKEY_set1_RSA(sslContext->pkey, reinterpret_cast<RSA *>(configuration.d->privateKey.handle()));
583             else if (configuration.d->privateKey.algorithm() == QSsl::Dsa)
584                 q_EVP_PKEY_set1_DSA(sslContext->pkey, reinterpret_cast<DSA *>(configuration.d->privateKey.handle()));
585 #ifndef OPENSSL_NO_EC
586             else if (configuration.d->privateKey.algorithm() == QSsl::Ec)
587                 q_EVP_PKEY_set1_EC_KEY(sslContext->pkey, reinterpret_cast<EC_KEY *>(configuration.d->privateKey.handle()));
588 #endif
589         }
590 
591         if (!q_SSL_CTX_use_PrivateKey(sslContext->ctx, sslContext->pkey)) {
592             sslContext->errorStr = QSslSocket::tr("Error loading private key, %1").arg(QSslSocketBackendPrivate::getErrorsFromOpenSsl());
593             sslContext->errorCode = QSslError::UnspecifiedError;
594             return;
595         }
596         if (configuration.d->privateKey.algorithm() == QSsl::Opaque)
597             sslContext->pkey = nullptr; // Don't free the private key, it belongs to QSslKey
598 
599         // Check if the certificate matches the private key.
600         if (!q_SSL_CTX_check_private_key(sslContext->ctx)) {
601             sslContext->errorStr = QSslSocket::tr("Private key does not certify public key, %1").arg(QSslSocketBackendPrivate::getErrorsFromOpenSsl());
602             sslContext->errorCode = QSslError::UnspecifiedError;
603             return;
604         }
605 
606         // If we have any intermediate certificates then we need to add them to our chain
607         bool first = true;
608         for (const QSslCertificate &cert : qAsConst(configuration.d->localCertificateChain)) {
609             if (first) {
610                 first = false;
611                 continue;
612             }
613             q_SSL_CTX_ctrl(sslContext->ctx, SSL_CTRL_EXTRA_CHAIN_CERT, 0,
614                            q_X509_dup(reinterpret_cast<X509 *>(cert.handle())));
615         }
616     }
617 
618     // Initialize peer verification, different callbacks, TLS/DTLS verification first
619     // (note, all these set_some_callback do not have return value):
620     if (sslContext->sslConfiguration.peerVerifyMode() == QSslSocket::VerifyNone) {
621         q_SSL_CTX_set_verify(sslContext->ctx, SSL_VERIFY_NONE, nullptr);
622     } else {
623         q_SSL_CTX_set_verify(sslContext->ctx, SSL_VERIFY_PEER,
624 #if QT_CONFIG(dtls)
625                              isDtls ? dtlscallbacks::q_X509DtlsCallback :
626 #endif // dtls
627                              q_X509Callback);
628     }
629 
630 #ifdef TLS1_3_VERSION
631     // NewSessionTicket callback:
632     if (mode == QSslSocket::SslClientMode && !isDtls) {
633         q_SSL_CTX_sess_set_new_cb(sslContext->ctx, q_ssl_sess_set_new_cb);
634         q_SSL_CTX_set_session_cache_mode(sslContext->ctx, SSL_SESS_CACHE_CLIENT);
635     }
636 
637 #endif // TLS1_3_VERSION
638 
639 #if QT_CONFIG(dtls)
640     // DTLS cookies:
641     if (mode == QSslSocket::SslServerMode && isDtls && configuration.dtlsCookieVerificationEnabled()) {
642         q_SSL_CTX_set_cookie_generate_cb(sslContext->ctx, dtlscallbacks::q_generate_cookie_callback);
643         q_SSL_CTX_set_cookie_verify_cb(sslContext->ctx, dtlscallbacks::q_verify_cookie_callback);
644     }
645 #endif // dtls
646 
647     // Set verification depth.
648     if (sslContext->sslConfiguration.peerVerifyDepth() != 0)
649         q_SSL_CTX_set_verify_depth(sslContext->ctx, sslContext->sslConfiguration.peerVerifyDepth());
650 
651     // set persisted session if the user set it
652     if (!configuration.sessionTicket().isEmpty())
653         sslContext->setSessionASN1(configuration.sessionTicket());
654 
655     // Set temp DH params
656     QSslDiffieHellmanParameters dhparams = configuration.diffieHellmanParameters();
657 
658     if (!dhparams.isValid()) {
659         sslContext->errorStr = QSslSocket::tr("Diffie-Hellman parameters are not valid");
660         sslContext->errorCode = QSslError::UnspecifiedError;
661         return;
662     }
663 
664     if (!dhparams.isEmpty()) {
665         const QByteArray &params = dhparams.d->derData;
666         const char *ptr = params.constData();
667         DH *dh = q_d2i_DHparams(nullptr, reinterpret_cast<const unsigned char **>(&ptr),
668                                 params.length());
669         if (dh == nullptr)
670             qFatal("q_d2i_DHparams failed to convert QSslDiffieHellmanParameters to DER form");
671         q_SSL_CTX_set_tmp_dh(sslContext->ctx, dh);
672         q_DH_free(dh);
673     }
674 
675 #ifndef OPENSSL_NO_PSK
676     if (!client)
677         q_SSL_CTX_use_psk_identity_hint(sslContext->ctx, sslContext->sslConfiguration.preSharedKeyIdentityHint().constData());
678 #endif // !OPENSSL_NO_PSK
679 
680     const QVector<QSslEllipticCurve> qcurves = sslContext->sslConfiguration.ellipticCurves();
681     if (!qcurves.isEmpty()) {
682 #ifdef OPENSSL_NO_EC
683         sslContext->errorStr = msgErrorSettingEllipticCurves(QSslSocket::tr("OpenSSL version with disabled elliptic curves"));
684         sslContext->errorCode = QSslError::UnspecifiedError;
685         return;
686 #else
687         // Set the curves to be used.
688         std::vector<int> curves;
689         curves.reserve(qcurves.size());
690         for (const auto &sslCurve : qcurves)
691             curves.push_back(sslCurve.id);
692         if (!q_SSL_CTX_ctrl(sslContext->ctx, SSL_CTRL_SET_CURVES, long(curves.size()), &curves[0])) {
693             sslContext->errorStr = msgErrorSettingEllipticCurves(QSslSocketBackendPrivate::getErrorsFromOpenSsl());
694             sslContext->errorCode = QSslError::UnspecifiedError;
695             return;
696         }
697 #endif
698     }
699 
700     applyBackendConfig(sslContext);
701 }
702 
703 #if QT_CONFIG(ocsp)
704 extern "C" int qt_OCSP_status_server_callback(SSL *ssl, void *); // Defined in qsslsocket_openssl.cpp.
705 #endif // ocsp
706 // static
applyBackendConfig(QSslContext * sslContext)707 void QSslContext::applyBackendConfig(QSslContext *sslContext)
708 {
709     const QMap<QByteArray, QVariant> &conf = sslContext->sslConfiguration.backendConfiguration();
710     if (conf.isEmpty())
711         return;
712 
713 #if QT_CONFIG(ocsp)
714     auto ocspResponsePos = conf.find("Qt-OCSP-response");
715     if (ocspResponsePos != conf.end()) {
716         // This is our private, undocumented configuration option, existing only for
717         // the purpose of testing OCSP status responses. We don't even check this
718         // callback was set. If no - the test must fail.
719         q_SSL_CTX_set_tlsext_status_cb(sslContext->ctx, qt_OCSP_status_server_callback);
720         if (conf.size() == 1)
721             return;
722     }
723 #endif // ocsp
724 
725     QSharedPointer<SSL_CONF_CTX> cctx(q_SSL_CONF_CTX_new(), &q_SSL_CONF_CTX_free);
726     if (cctx) {
727         q_SSL_CONF_CTX_set_ssl_ctx(cctx.data(), sslContext->ctx);
728         q_SSL_CONF_CTX_set_flags(cctx.data(), SSL_CONF_FLAG_FILE);
729 
730         for (auto i = conf.constBegin(); i != conf.constEnd(); ++i) {
731             if (i.key() == "Qt-OCSP-response") // This never goes to SSL_CONF_cmd().
732                 continue;
733 
734             if (!i.value().canConvert(QMetaType::QByteArray)) {
735                 sslContext->errorCode = QSslError::UnspecifiedError;
736                 sslContext->errorStr = msgErrorSettingBackendConfig(
737                 QSslSocket::tr("Expecting QByteArray for %1").arg(
738                                QString::fromUtf8(i.key())));
739                 return;
740             }
741 
742             const QByteArray &value = i.value().toByteArray();
743             const int result = q_SSL_CONF_cmd(cctx.data(), i.key().constData(), value.constData());
744             if (result == 2)
745                 continue;
746 
747             sslContext->errorCode = QSslError::UnspecifiedError;
748             switch (result) {
749             case 0:
750                 sslContext->errorStr = msgErrorSettingBackendConfig(
751                     QSslSocket::tr("An error occurred attempting to set %1 to %2").arg(
752                         QString::fromUtf8(i.key()), QString::fromUtf8(value)));
753                 return;
754             case 1:
755                 sslContext->errorStr = msgErrorSettingBackendConfig(
756                     QSslSocket::tr("Wrong value for %1 (%2)").arg(
757                         QString::fromUtf8(i.key()), QString::fromUtf8(value)));
758                 return;
759             default:
760                 sslContext->errorStr = msgErrorSettingBackendConfig(
761                     QSslSocket::tr("Unrecognized command %1 = %2").arg(
762                         QString::fromUtf8(i.key()), QString::fromUtf8(value)));
763                 return;
764             }
765         }
766 
767         if (q_SSL_CONF_CTX_finish(cctx.data()) == 0) {
768             sslContext->errorStr = msgErrorSettingBackendConfig(QSslSocket::tr("SSL_CONF_finish() failed"));
769             sslContext->errorCode = QSslError::UnspecifiedError;
770         }
771     } else {
772         sslContext->errorStr = msgErrorSettingBackendConfig(QSslSocket::tr("SSL_CONF_CTX_new() failed"));
773         sslContext->errorCode = QSslError::UnspecifiedError;
774     }
775 }
776 
777 QT_END_NAMESPACE
778