Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qtlsbackend_p.h
Go to the documentation of this file.
1// Copyright (C) 2021 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3// Qt-Security score:significant reason:default
4
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
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
43QT_BEGIN_NAMESPACE
44
45class QSslPreSharedKeyAuthenticator;
46class QSslSocketPrivate;
47class QHostAddress;
48class QSslContext;
49
50class QSslSocket;
51class QByteArray;
52class QSslCipher;
53class QUdpSocket;
54class QIODevice;
55class QSslError;
56class QSslKey;
57
58namespace QTlsPrivate {
59
60class Q_NETWORK_EXPORT TlsKey {
61public:
62 TlsKey() = default;
64
65 virtual ~TlsKey();
66
69
71 const QByteArray &passPhrase, bool deepClear) = 0;
73 const QByteArray &passPhrase, bool deepClear) = 0;
74
75 virtual QByteArray toPem(const QByteArray &passPhrase) 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
92 const QByteArray &passPhrase, const QByteArray &iv) const = 0;
94 const QByteArray &key, const QByteArray &iv) const = 0;
95
96 QByteArray pemHeader() const;
97 QByteArray pemFooter() const;
98};
99
100class Q_NETWORK_EXPORT X509Certificate
101{
102public:
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;
111 virtual QStringList issuerInfo(const QByteArray &attribute) const = 0;
113 virtual QStringList subjectInfo(const QByteArray &attribute) const = 0;
114
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;
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.
147using X509ChainVerifyPtr = QList<QSslError> (*)(const QList<QSslCertificate> &chain,
148 const QString &hostName);
149using X509PemReaderPtr = QList<QSslCertificate> (*)(const QByteArray &pem, int count);
150using X509DerReaderPtr = X509PemReaderPtr;
151using 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.
158{
159public:
160 virtual ~TlsCryptograph();
161
162 virtual void init(QSslSocket *q, QSslSocketPrivate *d) = 0;
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
185 const QString &errorDescription) const;
186};
187#else
188class TlsCryptograph;
189#endif // QT_CONFIG(ssl)
190
191#if QT_CONFIG(dtls)
192
194{
195public:
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
209 virtual bool setCookieGeneratorParameters(const GenParams &params) = 0;
210 virtual GenParams cookieGeneratorParameters() const = 0;
211};
212
213// DTLS cookie: generation and verification.
214class Q_NETWORK_EXPORT DtlsCookieVerifier : virtual public DtlsBase
215{
216public:
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.
223class Q_NETWORK_EXPORT DtlsCryptograph : virtual public DtlsBase
224{
225public:
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
255};
256
257#else
258
259class DtlsCookieVerifier;
260class 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.
268class Q_NETWORK_EXPORT QTlsBackend : public QObject
269{
270 Q_OBJECT
271public:
272 QTlsBackend();
273 ~QTlsBackend() override;
274
275 virtual bool isValid() const;
276 virtual long tlsLibraryVersionNumber() const;
277 virtual QString tlsLibraryVersionString() const;
278 virtual long tlsLibraryBuildVersionNumber() const;
279 virtual QString tlsLibraryBuildVersionString() const;
280 virtual void ensureInitialized() const;
281
282 virtual QString backendName() const = 0;
283 virtual QList<QSsl::SslProtocol> supportedProtocols() const = 0;
284 virtual QList<QSsl::SupportedFeature> supportedFeatures() const = 0;
285 virtual QList<QSsl::ImplementedClass> implementedClasses() const = 0;
286
287 // X509 and keys:
288 virtual QTlsPrivate::TlsKey *createKey() const;
289 virtual QTlsPrivate::X509Certificate *createCertificate() const;
290
291 virtual QList<QSslCertificate> systemCaCertificates() const;
292
293 // TLS and DTLS:
294 virtual QTlsPrivate::TlsCryptograph *createTlsCryptograph() const;
295 virtual QTlsPrivate::DtlsCryptograph *createDtlsCryptograph(class QDtls *qObject, int mode) const;
296 virtual QTlsPrivate::DtlsCookieVerifier *createDtlsCookieVerifier() const;
297
298 // TLSTODO - get rid of these function pointers, make them virtuals in
299 // the backend itself. X509 machinery:
300 virtual QTlsPrivate::X509ChainVerifyPtr X509Verifier() const;
301 virtual QTlsPrivate::X509PemReaderPtr X509PemReader() const;
302 virtual QTlsPrivate::X509DerReaderPtr X509DerReader() const;
303 virtual QTlsPrivate::X509Pkcs12ReaderPtr X509Pkcs12Reader() const;
304
305 // Elliptic curves:
306 virtual QList<int> ellipticCurvesIds() const;
307 virtual int curveIdFromShortName(const QString &name) const;
308 virtual int curveIdFromLongName(const QString &name) const;
309 virtual QString shortNameForId(int cid) const;
310 virtual QString longNameForId(int cid) const;
311 virtual bool isTlsNamedCurve(int cid) const;
312
313 // Note: int and not QSslDiffieHellmanParameter::Error - because this class and
314 // its enum are QT_CONFIG(ssl)-conditioned. But not QTlsBackend and
315 // its virtual functions. DH decoding:
316 virtual int dhParametersFromDer(const QByteArray &derData, QByteArray *data) const;
317 virtual int dhParametersFromPem(const QByteArray &pemData, QByteArray *data) const;
318
319 static QList<QString> availableBackendNames();
320 static QString defaultBackendName();
321 static QTlsBackend *findBackend(const QString &backendName);
322 static QTlsBackend *activeOrAnyBackend();
323
324 static QList<QSsl::SslProtocol> supportedProtocols(const QString &backendName);
325 static QList<QSsl::SupportedFeature> supportedFeatures(const QString &backendName);
326 static QList<QSsl::ImplementedClass> implementedClasses(const QString &backendName);
327
328 // Built-in, this is what Qt provides out of the box (depending on OS):
329 static constexpr const int nameIndexSchannel = 0;
330 static constexpr const int nameIndexSecureTransport = 1;
331 static constexpr const int nameIndexOpenSSL = 2;
332 static constexpr const int nameIndexCertOnly = 3;
333
334 static const QString builtinBackendNames[];
335
336 template<class DynamicType, class TLSObject>
337 static DynamicType *backend(const TLSObject &o)
338 {
339 return static_cast<DynamicType *>(o.d->backend.get());
340 }
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 addTustedRoot(QSslSocketPrivate *d, const QSslCertificate &rootCert);// TODO: "addTrusted..."
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"
402
403QT_END_NAMESPACE
404
405#endif // QTLSBACKEND_P_H
Definition qlist.h:81
This class represents Online Certificate Status Protocol response.
The QSslCertificate class provides a convenient API for an X509 certificate.
The QSslCipher class represents an SSL cryptographic cipher.
Definition qsslcipher.h:23
The QSslDiffieHellmanParameters class provides an interface for Diffie-Hellman parameters for servers...
Represents an elliptic curve for use by elliptic-curve cipher algorithms.
constexpr QSslEllipticCurve() noexcept
Constructs an invalid elliptic curve.
constexpr bool isValid() const noexcept
Returns true if this elliptic curve is a valid curve, false otherwise.
friend constexpr bool operator!=(QSslEllipticCurve lhs, QSslEllipticCurve rhs) noexcept
Q_NETWORK_EXPORT bool isTlsNamedCurve() const noexcept
Returns true if this elliptic curve is one of the named curves that can be used in the key exchange w...
friend constexpr bool operator==(QSslEllipticCurve lhs, QSslEllipticCurve rhs) noexcept
The QSslKey class provides an interface for private and public keys.
Definition qsslkey.h:24
Describes exported keying material derived from a TLS session.
QByteArray context() const noexcept
Returns the optional context value used for deriving the keying material.
QSslKeyingMaterial(const QByteArray &label, qsizetype size, const QByteArray &context=QByteArray()) noexcept
Constructs a QSslKeyingMaterial object with the given exporter label, output size,...
QByteArray label() const noexcept
Returns the exporter label used for deriving the keying material.
qsizetype size() const noexcept
The desired size of the keying material.
bool isValid() const noexcept
Returns true if this QSslKeyingMaterial object describes a valid exporter request.
QByteArray value() const noexcept
Returns the exported keying material.
friend bool comparesEqual(const QSslKeyingMaterial &lhs, const QSslKeyingMaterial &rhs) noexcept
The QSslPreSharedKeyAuthenticator class provides authentication data for pre shared keys (PSK) cipher...
The QSslSocket class provides an SSL encrypted socket for both clients and servers.
Definition qsslsocket.h:30
QTlsBackend is a factory class, providing implementations for the QSsl classes.
TlsKey is an abstract class, that allows a TLS plugin to provide an underlying implementation for the...
X509Certificate is an abstract class that allows a TLS backend to provide an implementation of the QS...
Combined button and popup list for selecting options.
Namespace containing onternal types that TLS backends implement.
bool(*)(QIODevice *device, QSslKey *key, QSslCertificate *cert, QList< QSslCertificate > *caCertificates, const QByteArray &passPhrase) X509Pkcs12ReaderPtr
Q_CORE_EXPORT QDebug operator<<(QDebug debug, QDir::Filters filters)
Definition qdir.cpp:2582
static QT_BEGIN_NAMESPACE QString msgUnsupportedMulticastAddress()
Definition qdtls.cpp:304
QT_REQUIRE_CONFIG(liburing)
Q_DECLARE_INTERFACE(QNetworkAccessBackendFactory, QNetworkAccessBackendFactory_iid)
QOcspRevocationReason
constexpr size_t qHash(QSslEllipticCurve curve, size_t seed=0) noexcept
Q_DECLARE_TYPEINFO(QSslEllipticCurve, Q_PRIMITIVE_TYPE)
size_t qHash(const QSslKeyingMaterial &material, size_t seed=0)
#define QTlsBackend_iid