Coverage Report

Created: 2026-05-31 06:50

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/qtbase/src/network/ssl/qtlsbackend_p.h
Line
Count
Source
1
// Copyright (C) 2021 The Qt Company Ltd.
2
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
// Qt-Security score:significant reason:default
4
5
#ifndef QTLSBACKEND_P_H
6
#define QTLSBACKEND_P_H
7
8
//
9
//  W A R N I N G
10
//  -------------
11
//
12
// This file is not part of the Qt API.  It exists purely as an
13
// implementation detail.  This header file may change from version to
14
// version without notice, or even be removed.
15
//
16
// We mean it.
17
//
18
19
#include <QtNetwork/private/qtnetworkglobal_p.h>
20
21
#include "qsslconfiguration.h"
22
#include "qsslerror.h"
23
#include "qssl_p.h"
24
25
#if QT_CONFIG(dtls)
26
#include "qdtls.h"
27
#endif
28
29
#include <QtNetwork/qsslcertificate.h>
30
#include <QtNetwork/qsslcipher.h>
31
#include <QtNetwork/qsslkey.h>
32
#include <QtNetwork/qssl.h>
33
34
#include <QtCore/qloggingcategory.h>
35
#include <QtCore/qnamespace.h>
36
#include <QtCore/qobject.h>
37
#include <QtCore/qstring.h>
38
#include <QtCore/qlist.h>
39
#include <QtCore/qmap.h>
40
41
#include <memory>
42
43
QT_BEGIN_NAMESPACE
44
45
class QSslPreSharedKeyAuthenticator;
46
class QSslSocketPrivate;
47
class QHostAddress;
48
class QSslContext;
49
50
class QSslSocket;
51
class QByteArray;
52
class QSslCipher;
53
class QUdpSocket;
54
class QIODevice;
55
class QSslError;
56
class QSslKey;
57
58
namespace QTlsPrivate {
59
60
class Q_NETWORK_EXPORT TlsKey {
61
public:
62
0
    TlsKey() = default;
63
    Q_DISABLE_COPY_MOVE(TlsKey)
64
65
    virtual ~TlsKey();
66
67
    using KeyType = QSsl::KeyType;
68
    using KeyAlgorithm = QSsl::KeyAlgorithm;
69
70
    virtual void decodeDer(KeyType type, KeyAlgorithm algorithm, const QByteArray &der,
71
                           const QByteArray &passPhrase, bool deepClear) = 0;
72
    virtual void decodePem(KeyType type, KeyAlgorithm algorithm, const QByteArray &pem,
73
                           const QByteArray &passPhrase, bool deepClear) = 0;
74
75
    virtual QByteArray toPem(const QByteArray &passPhrase) const = 0;
76
    virtual QByteArray derFromPem(const QByteArray &pem, QMap<QByteArray, QByteArray> *headers) const = 0;
77
    virtual QByteArray pemFromDer(const QByteArray &der, const QMap<QByteArray, QByteArray> &headers) const = 0;
78
79
    virtual void fromHandle(Qt::HANDLE handle, KeyType type) = 0;
80
    virtual Qt::HANDLE handle() const = 0;
81
82
    virtual bool isNull() const = 0;
83
    virtual KeyType type() const = 0;
84
    virtual KeyAlgorithm algorithm() const = 0;
85
    virtual int length() const = 0;
86
87
    virtual void clear(bool deepClear) = 0;
88
89
    virtual bool isPkcs8() const = 0;
90
91
    virtual QByteArray decrypt(Cipher cipher, const QByteArray &data,
92
                               const QByteArray &passPhrase, const QByteArray &iv) const = 0;
93
    virtual QByteArray encrypt(Cipher cipher, const QByteArray &data,
94
                               const QByteArray &key, const QByteArray &iv) const = 0;
95
96
    QByteArray pemHeader() const;
97
    QByteArray pemFooter() const;
98
};
99
100
class Q_NETWORK_EXPORT X509Certificate
101
{
102
public:
103
    virtual ~X509Certificate();
104
105
    virtual bool isEqual(const X509Certificate &other) const = 0;
106
    virtual bool isNull() const = 0;
107
    virtual bool isSelfSigned() const = 0;
108
    virtual QByteArray version() const = 0;
109
    virtual QByteArray serialNumber() const = 0;
110
    virtual QStringList issuerInfo(QSslCertificate::SubjectInfo subject) const = 0;
111
    virtual QStringList issuerInfo(const QByteArray &attribute) const = 0;
112
    virtual QStringList subjectInfo(QSslCertificate::SubjectInfo subject) const = 0;
113
    virtual QStringList subjectInfo(const QByteArray &attribute) const = 0;
114
115
    virtual QList<QByteArray> subjectInfoAttributes() const = 0;
116
    virtual QList<QByteArray> issuerInfoAttributes() const = 0;
117
    virtual QMultiMap<QSsl::AlternativeNameEntryType, QString> subjectAlternativeNames() const = 0;
118
    virtual QDateTime effectiveDate() const = 0;
119
    virtual QDateTime expiryDate() const = 0;
120
121
    virtual TlsKey *publicKey() const;
122
123
    // Extensions. Plugins do not expose internal representation
124
    // and cannot rely on QSslCertificate's internals. Thus,
125
    // we provide this information 'in pieces':
126
    virtual qsizetype numberOfExtensions() const = 0;
127
    virtual QString oidForExtension(qsizetype i) const = 0;
128
    virtual QString nameForExtension(qsizetype i) const = 0;
129
    virtual QVariant valueForExtension(qsizetype i) const = 0;
130
    virtual bool isExtensionCritical(qsizetype i) const = 0;
131
    virtual bool isExtensionSupported(qsizetype i) const = 0;
132
133
    virtual QByteArray toPem() const = 0;
134
    virtual QByteArray toDer() const = 0;
135
    virtual QString toText() const = 0;
136
137
    virtual Qt::HANDLE handle() const = 0;
138
139
    virtual size_t hash(size_t seed) const noexcept = 0;
140
};
141
142
// TLSTODO: consider making those into virtuals in QTlsBackend. After all, we ask the backend
143
// to return those pointers if the functionality is supported, but it's a bit odd to have
144
// this level of indirection. They are not parts of the classes above because ...
145
// you'd then have to ask backend to create a certificate to ... call those
146
// functions on a certificate.
147
using X509ChainVerifyPtr = QList<QSslError> (*)(const QList<QSslCertificate> &chain,
148
                                                const QString &hostName);
149
using X509PemReaderPtr = QList<QSslCertificate> (*)(const QByteArray &pem, int count);
150
using X509DerReaderPtr = X509PemReaderPtr;
151
using X509Pkcs12ReaderPtr = bool (*)(QIODevice *device, QSslKey *key, QSslCertificate *cert,
152
                                     QList<QSslCertificate> *caCertificates,
153
                                     const QByteArray &passPhrase);
154
155
#if QT_CONFIG(ssl)
156
// TLS over TCP. Handshake, encryption/decryption.
157
class Q_NETWORK_EXPORT TlsCryptograph : public QObject
158
{
159
public:
160
    virtual ~TlsCryptograph();
161
162
    virtual void init(QSslSocket *q, QSslSocketPrivate *d) = 0;
163
    virtual void checkSettingSslContext(std::shared_ptr<QSslContext> tlsContext);
164
    virtual std::shared_ptr<QSslContext> sslContext() const;
165
166
    virtual QList<QSslError> tlsErrors() const = 0;
167
168
    virtual void startClientEncryption() = 0;
169
    virtual void startServerEncryption() = 0;
170
    virtual void continueHandshake() = 0;
171
    virtual void enableHandshakeContinuation();
172
    virtual void disconnectFromHost() = 0;
173
    virtual void disconnected() = 0;
174
    virtual void cancelCAFetch();
175
    virtual QSslCipher sessionCipher() const = 0;
176
    virtual QSsl::SslProtocol sessionProtocol() const = 0;
177
178
    virtual void transmit() = 0;
179
    virtual bool hasUndecryptedData() const;
180
    virtual QList<QOcspResponse> ocsps() const;
181
182
    static bool isMatchingHostname(const QSslCertificate &cert, const QString &peerName);
183
184
    void setErrorAndEmit(QSslSocketPrivate *d, QAbstractSocket::SocketError errorCode,
185
                         const QString &errorDescription) const;
186
};
187
#else
188
class TlsCryptograph;
189
#endif // QT_CONFIG(ssl)
190
191
#if QT_CONFIG(dtls)
192
193
class Q_NETWORK_EXPORT DtlsBase
194
{
195
public:
196
    virtual ~DtlsBase();
197
198
    virtual void setDtlsError(QDtlsError code, const QString &description) = 0;
199
200
    virtual QDtlsError error() const = 0;
201
    virtual QString errorString() const = 0;
202
203
    virtual void clearDtlsError() = 0;
204
205
    virtual void setConfiguration(const QSslConfiguration &configuration) = 0;
206
    virtual QSslConfiguration configuration() const = 0;
207
208
    using GenParams = QDtlsClientVerifier::GeneratorParameters;
209
    virtual bool setCookieGeneratorParameters(const GenParams &params) = 0;
210
    virtual GenParams cookieGeneratorParameters() const = 0;
211
};
212
213
// DTLS cookie: generation and verification.
214
class Q_NETWORK_EXPORT DtlsCookieVerifier : virtual public DtlsBase
215
{
216
public:
217
    virtual bool verifyClient(QUdpSocket *socket, const QByteArray &dgram,
218
                              const QHostAddress &address, quint16 port) = 0;
219
    virtual QByteArray verifiedHello() const = 0;
220
};
221
222
// TLS over UDP. Handshake, encryption/decryption.
223
class Q_NETWORK_EXPORT DtlsCryptograph : virtual public DtlsBase
224
{
225
public:
226
227
    virtual QSslSocket::SslMode cryptographMode() const = 0;
228
    virtual void setPeer(const QHostAddress &addr, quint16 port, const QString &name) = 0;
229
    virtual QHostAddress peerAddress() const = 0;
230
    virtual quint16 peerPort() const = 0;
231
    virtual void setPeerVerificationName(const QString &name) = 0;
232
    virtual QString peerVerificationName() const = 0;
233
234
    virtual void setDtlsMtuHint(quint16 mtu) = 0;
235
    virtual quint16 dtlsMtuHint() const = 0;
236
237
    virtual QDtls::HandshakeState state() const = 0;
238
    virtual bool isConnectionEncrypted() const = 0;
239
240
    virtual bool startHandshake(QUdpSocket *socket, const QByteArray &dgram) = 0;
241
    virtual bool handleTimeout(QUdpSocket *socket) = 0;
242
    virtual bool continueHandshake(QUdpSocket *socket, const QByteArray &dgram) = 0;
243
    virtual bool resumeHandshake(QUdpSocket *socket) = 0;
244
    virtual void abortHandshake(QUdpSocket *socket) = 0;
245
    virtual void sendShutdownAlert(QUdpSocket *socket) = 0;
246
247
    virtual QList<QSslError> peerVerificationErrors() const = 0;
248
    virtual void ignoreVerificationErrors(const QList<QSslError> &errorsToIgnore) = 0;
249
250
    virtual QSslCipher dtlsSessionCipher() const = 0;
251
    virtual QSsl::SslProtocol dtlsSessionProtocol() const = 0;
252
253
    virtual qint64 writeDatagramEncrypted(QUdpSocket *socket, const QByteArray &dgram) = 0;
254
    virtual QByteArray decryptDatagram(QUdpSocket *socket, const QByteArray &dgram) = 0;
255
};
256
257
#else
258
259
class DtlsCookieVerifier;
260
class DtlsCryptograph;
261
262
#endif // QT_CONFIG(dtls)
263
264
} // namespace QTlsPrivate
265
266
// Factory, creating back-end specific implementations of
267
// different entities QSslSocket is using.
268
class Q_NETWORK_EXPORT QTlsBackend : public QObject
269
{
270
0
    Q_OBJECT
271
0
public:
272
0
    QTlsBackend();
273
0
    ~QTlsBackend() override;
274
0
275
0
    virtual bool isValid() const;
276
0
    virtual long tlsLibraryVersionNumber() const;
277
0
    virtual QString tlsLibraryVersionString() const;
278
0
    virtual long tlsLibraryBuildVersionNumber() const;
279
0
    virtual QString tlsLibraryBuildVersionString() const;
280
0
    virtual void ensureInitialized() const;
281
0
282
0
    virtual QString backendName() const = 0;
283
0
    virtual QList<QSsl::SslProtocol> supportedProtocols() const = 0;
284
0
    virtual QList<QSsl::SupportedFeature> supportedFeatures() const = 0;
285
0
    virtual QList<QSsl::ImplementedClass> implementedClasses() const = 0;
286
0
287
0
    // X509 and keys:
288
0
    virtual QTlsPrivate::TlsKey *createKey() const;
289
0
    virtual QTlsPrivate::X509Certificate *createCertificate() const;
290
0
291
0
    virtual QList<QSslCertificate> systemCaCertificates() const;
292
0
293
0
    // TLS and DTLS:
294
0
    virtual QTlsPrivate::TlsCryptograph *createTlsCryptograph() const;
295
0
    virtual QTlsPrivate::DtlsCryptograph *createDtlsCryptograph(class QDtls *qObject, int mode) const;
296
0
    virtual QTlsPrivate::DtlsCookieVerifier *createDtlsCookieVerifier() const;
297
0
298
0
    // TLSTODO - get rid of these function pointers, make them virtuals in
299
0
    // the backend itself. X509 machinery:
300
0
    virtual QTlsPrivate::X509ChainVerifyPtr X509Verifier() const;
301
0
    virtual QTlsPrivate::X509PemReaderPtr X509PemReader() const;
302
0
    virtual QTlsPrivate::X509DerReaderPtr X509DerReader() const;
303
0
    virtual QTlsPrivate::X509Pkcs12ReaderPtr X509Pkcs12Reader() const;
304
0
305
0
    // Elliptic curves:
306
0
    virtual QList<int> ellipticCurvesIds() const;
307
0
    virtual int curveIdFromShortName(const QString &name) const;
308
0
    virtual int curveIdFromLongName(const QString &name) const;
309
0
    virtual QString shortNameForId(int cid) const;
310
0
    virtual QString longNameForId(int cid) const;
311
0
    virtual bool isTlsNamedCurve(int cid) const;
312
0
313
0
    // Note: int and not QSslDiffieHellmanParameter::Error - because this class and
314
0
    // its enum are QT_CONFIG(ssl)-conditioned. But not QTlsBackend and
315
0
    // its virtual functions. DH decoding:
316
0
    virtual int dhParametersFromDer(const QByteArray &derData, QByteArray *data) const;
317
0
    virtual int dhParametersFromPem(const QByteArray &pemData, QByteArray *data) const;
318
0
319
0
    static QList<QString> availableBackendNames();
320
0
    static QString defaultBackendName();
321
0
    static QTlsBackend *findBackend(const QString &backendName);
322
0
    static QTlsBackend *activeOrAnyBackend();
323
0
324
0
    static QList<QSsl::SslProtocol> supportedProtocols(const QString &backendName);
325
0
    static QList<QSsl::SupportedFeature> supportedFeatures(const QString &backendName);
326
0
    static QList<QSsl::ImplementedClass> implementedClasses(const QString &backendName);
327
0
328
0
    // Built-in, this is what Qt provides out of the box (depending on OS):
329
0
    static constexpr const int nameIndexSchannel = 0;
330
0
    static constexpr const int nameIndexSecureTransport = 1;
331
0
    static constexpr const int nameIndexOpenSSL = 2;
332
0
    static constexpr const int nameIndexCertOnly = 3;
333
0
334
0
    static const QString builtinBackendNames[];
335
0
336
0
    template<class DynamicType, class TLSObject>
337
0
    static DynamicType *backend(const TLSObject &o)
338
0
    {
339
0
        return static_cast<DynamicType *>(o.d->backend.get());
340
0
    }
Unexecuted instantiation: QTlsPrivate::X509CertificateOpenSSL* QTlsBackend::backend<QTlsPrivate::X509CertificateOpenSSL, QSslCertificate>(QSslCertificate const&)
Unexecuted instantiation: QTlsPrivate::TlsKeyOpenSSL* QTlsBackend::backend<QTlsPrivate::TlsKeyOpenSSL, QSslKey>(QSslKey const&)
341
342
    static void resetBackend(QSslKey &key, QTlsPrivate::TlsKey *keyBackend);
343
344
    static void setupClientPskAuth(QSslPreSharedKeyAuthenticator *auth, const char *hint,
345
                                   int hintLength, unsigned maxIdentityLen, unsigned maxPskLen);
346
    static void setupServerPskAuth(QSslPreSharedKeyAuthenticator *auth, const char *identity,
347
                                   const QByteArray &identityHint, unsigned maxPskLen);
348
#if QT_CONFIG(ssl)
349
    static QSslCipher createCiphersuite(const QString &description, int bits, int supportedBits);
350
    static QSslCipher createCiphersuite(const QString &suiteName, QSsl::SslProtocol protocol,
351
                                        const QString &protocolString);
352
    static QSslCipher createCiphersuite(const QString &name, const QString &keyExchangeMethod,
353
                                        const QString &encryptionMethod,
354
                                        const QString &authenticationMethod,
355
                                        int bits, QSsl::SslProtocol protocol,
356
                                        const QString &protocolString);
357
358
    // Those statics are implemented using QSslSocketPrivate (which is not exported,
359
    // unlike QTlsBackend).
360
    static QList<QSslCipher> defaultCiphers();
361
    static QList<QSslCipher> defaultDtlsCiphers();
362
363
    static void setDefaultCiphers(const QList<QSslCipher> &ciphers);
364
    static void setDefaultDtlsCiphers(const QList<QSslCipher> &ciphers);
365
    static void setDefaultSupportedCiphers(const QList<QSslCipher> &ciphers);
366
367
    static void resetDefaultEllipticCurves();
368
369
    static void setDefaultCaCertificates(const QList<QSslCertificate> &certs);
370
371
    // Many thanks to people who designed QSslConfiguration with hidden
372
    // data-members, that sneakily set by some 'friend' classes, having
373
    // some twisted logic.
374
    static bool rootLoadingOnDemandAllowed(const QSslConfiguration &configuration);
375
    static void storePeerCertificate(QSslConfiguration &configuration, const QSslCertificate &peerCert);
376
    static void storePeerCertificateChain(QSslConfiguration &configuration,
377
                                          const QList<QSslCertificate> &peerCertificateChain);
378
    static void clearPeerCertificates(QSslConfiguration &configuration);
379
    // And those are even worse, this is where we don't have the original configuration,
380
    // and can have only a copy. So instead we go to d->privateConfiguration.someMember:
381
    static void clearPeerCertificates(QSslSocketPrivate *d);
382
    static void setPeerSessionShared(QSslSocketPrivate *d, bool shared);
383
    static void setSessionAsn1(QSslSocketPrivate *d, const QByteArray &asn1);
384
    static void setSessionLifetimeHint(QSslSocketPrivate *d, int hint);
385
    using AlpnNegotiationStatus = QSslConfiguration::NextProtocolNegotiationStatus;
386
    static void setAlpnStatus(QSslSocketPrivate *d, AlpnNegotiationStatus st);
387
    static void setNegotiatedProtocol(QSslSocketPrivate *d, const QByteArray &protocol);
388
    static void storePeerCertificate(QSslSocketPrivate *d, const QSslCertificate &peerCert);
389
    static void storePeerCertificateChain(QSslSocketPrivate *d, const QList<QSslCertificate> &peerChain);
390
    static void addTrustedRoot(QSslSocketPrivate *d, const QSslCertificate &rootCert);
391
    // The next one - is a "very important" feature! Kidding ...
392
    static void setEphemeralKey(QSslSocketPrivate *d, const QSslKey &key);
393
394
    virtual void forceAutotestSecurityLevel();
395
#endif // QT_CONFIG(ssl)
396
397
    Q_DISABLE_COPY_MOVE(QTlsBackend)
398
};
399
400
#define QTlsBackend_iid "org.qt-project.Qt.QTlsBackend"
401
Q_DECLARE_INTERFACE(QTlsBackend, QTlsBackend_iid);
Unexecuted instantiation: char const* qobject_interface_iid<QTlsBackend*>()
Unexecuted instantiation: QTlsBackend* qobject_cast<QTlsBackend*>(QObject*)
Unexecuted instantiation: QTlsBackend const* qobject_cast<QTlsBackend const*>(QObject const*)
402
403
QT_END_NAMESPACE
404
405
#endif // QTLSBACKEND_P_H