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 | |
4 | #include "qtlsbackend_p.h" |
5 | |
6 | #if QT_CONFIG(ssl) |
7 | #include "qsslpresharedkeyauthenticator_p.h" |
8 | #include "qsslpresharedkeyauthenticator.h" |
9 | #include "qsslsocket_p.h" |
10 | #include "qsslcipher_p.h" |
11 | #include "qsslkey_p.h" |
12 | #include "qsslkey.h" |
13 | #endif |
14 | |
15 | #include "qssl_p.h" |
16 | |
17 | #include <QtCore/private/qfactoryloader_p.h> |
18 | |
19 | #include "QtCore/qapplicationstatic.h" |
20 | #include <QtCore/qbytearray.h> |
21 | #include <QtCore/qmutex.h> |
22 | |
23 | #include <algorithm> |
24 | #include <vector> |
25 | |
26 | QT_BEGIN_NAMESPACE |
27 | |
28 | using namespace Qt::StringLiterals; |
29 | |
30 | Q_APPLICATION_STATIC(QFactoryLoader, qtlsbLoader, QTlsBackend_iid, |
31 | QStringLiteral("/tls")) |
32 | |
33 | namespace { |
34 | |
35 | class BackendCollection |
36 | { |
37 | public: |
38 | void addBackend(QTlsBackend *backend) |
39 | { |
40 | Q_ASSERT(backend); |
41 | Q_ASSERT(std::find(backends.begin(), backends.end(), backend) == backends.end()); |
42 | const QMutexLocker locker(&collectionMutex); |
43 | backends.push_back(x: backend); |
44 | } |
45 | |
46 | void removeBackend(QTlsBackend *backend) |
47 | { |
48 | Q_ASSERT(backend); |
49 | const QMutexLocker locker(&collectionMutex); |
50 | const auto it = std::find(first: backends.begin(), last: backends.end(), val: backend); |
51 | Q_ASSERT(it != backends.end()); |
52 | backends.erase(position: it); |
53 | } |
54 | |
55 | bool tryPopulateCollection() |
56 | { |
57 | if (!qtlsbLoader()) |
58 | return false; |
59 | |
60 | Q_CONSTINIT static QBasicMutex mutex; |
61 | const QMutexLocker locker(&mutex); |
62 | if (backends.size()) |
63 | return true; |
64 | |
65 | #if QT_CONFIG(library) |
66 | qtlsbLoader->update(); |
67 | #endif |
68 | int index = 0; |
69 | while (qtlsbLoader->instance(index)) |
70 | ++index; |
71 | |
72 | return true; |
73 | } |
74 | |
75 | QList<QString> backendNames() |
76 | { |
77 | QList<QString> names; |
78 | if (!tryPopulateCollection()) |
79 | return names; |
80 | |
81 | const QMutexLocker locker(&collectionMutex); |
82 | if (!backends.size()) |
83 | return names; |
84 | |
85 | names.reserve(asize: backends.size()); |
86 | for (const auto *backend : backends) { |
87 | if (backend->isValid()) |
88 | names.append(t: backend->backendName()); |
89 | } |
90 | |
91 | return names; |
92 | } |
93 | |
94 | QTlsBackend *backend(const QString &name) |
95 | { |
96 | if (!tryPopulateCollection()) |
97 | return nullptr; |
98 | |
99 | const QMutexLocker locker(&collectionMutex); |
100 | const auto it = std::find_if(first: backends.begin(), last: backends.end(), |
101 | pred: [&name](const auto *fct) {return fct->backendName() == name;}); |
102 | |
103 | return it == backends.end() ? nullptr : *it; |
104 | } |
105 | |
106 | private: |
107 | std::vector<QTlsBackend *> backends; |
108 | QMutex collectionMutex; |
109 | }; |
110 | |
111 | } // Unnamed namespace |
112 | |
113 | Q_GLOBAL_STATIC(BackendCollection, backends); |
114 | |
115 | /*! |
116 | \class QTlsBackend |
117 | \internal (Network-private) |
118 | \brief QTlsBackend is a factory class, providing implementations |
119 | for the QSsl classes. |
120 | |
121 | The purpose of QTlsBackend is to enable and simplify the addition |
122 | of new TLS backends to be used by QSslSocket and related classes. |
123 | Starting from Qt 6.1, these backends have plugin-based design (and |
124 | thus can co-exist simultaneously, unlike pre 6.1 times), although |
125 | any given run of a program can only use one of them. |
126 | |
127 | Inheriting from QTlsBackend and creating an object of such |
128 | a class adds a new backend into the list of available TLS backends. |
129 | |
130 | A new backend must provide a list of classes, features and protocols |
131 | it supports, and override the corresponding virtual functions that |
132 | create backend-specific implementations for these QSsl-classes. |
133 | |
134 | The base abstract class - QTlsBackend - provides, where possible, |
135 | default implementations of its virtual member functions. These |
136 | default implementations can be overridden by a derived backend |
137 | class, if needed. |
138 | |
139 | QTlsBackend also provides some auxiliary functions that a derived |
140 | backend class can use to interact with the internals of network-private classes. |
141 | |
142 | \sa QSslSocket::availableBackends(), supportedFeatures(), supportedProtocols(), implementedClasses() |
143 | */ |
144 | |
145 | /*! |
146 | \fn QString QTlsBackend::backendName() const |
147 | \internal |
148 | Returns the name of this backend. The name will be reported by QSslSocket::availableBackends(). |
149 | Example of backend names: "openssl", "schannel", "securetransport". |
150 | |
151 | \sa QSslSocket::availableBackends(), isValid() |
152 | */ |
153 | |
154 | const QString QTlsBackend::builtinBackendNames[] = { |
155 | QStringLiteral("schannel"), |
156 | QStringLiteral("securetransport"), |
157 | QStringLiteral("openssl"), |
158 | QStringLiteral("cert-only") |
159 | }; |
160 | |
161 | /*! |
162 | \internal |
163 | The default constructor, adds a new backend to the list of available backends. |
164 | |
165 | \sa ~QTlsBackend(), availableBackendNames(), QSslSocket::availableBackends() |
166 | */ |
167 | QTlsBackend::QTlsBackend() |
168 | { |
169 | if (backends()) |
170 | backends->addBackend(backend: this); |
171 | |
172 | if (QCoreApplication::instance()) { |
173 | connect(sender: QCoreApplication::instance(), signal: &QCoreApplication::destroyed, context: this, slot: [this] { |
174 | delete this; |
175 | }); |
176 | } |
177 | } |
178 | |
179 | /*! |
180 | \internal |
181 | Removes this backend from the list of available backends. |
182 | |
183 | \sa QTlsBackend(), availableBackendNames(), QSslSocket::availableBackends() |
184 | */ |
185 | QTlsBackend::~QTlsBackend() |
186 | { |
187 | if (backends()) |
188 | backends->removeBackend(backend: this); |
189 | } |
190 | |
191 | /*! |
192 | \internal |
193 | Returns \c true if this backend was initialised successfully. The default implementation |
194 | always returns \c true. |
195 | |
196 | \note This function must be overridden if a particular backend has a non-trivial initialization |
197 | that can fail. If reimplemented, returning \c false will exclude this backend from the list of |
198 | backends, reported as available by QSslSocket. |
199 | |
200 | \sa QSslSocket::availableBackends() |
201 | */ |
202 | |
203 | bool QTlsBackend::isValid() const |
204 | { |
205 | return true; |
206 | } |
207 | |
208 | /*! |
209 | \internal |
210 | Returns an implementations-specific integer value, representing the TLS library's |
211 | version, that is currently used by this backend (i.e. runtime library version). |
212 | The default implementation returns 0. |
213 | |
214 | \sa tlsLibraryBuildVersionNumber() |
215 | */ |
216 | long QTlsBackend::tlsLibraryVersionNumber() const |
217 | { |
218 | return 0; |
219 | } |
220 | |
221 | /*! |
222 | \internal |
223 | Returns an implementation-specific string, representing the TLS library's version, |
224 | that is currently used by this backend (i.e. runtime library version). The default |
225 | implementation returns an empty string. |
226 | |
227 | \sa tlsLibraryBuildVersionString() |
228 | */ |
229 | |
230 | QString QTlsBackend::tlsLibraryVersionString() const |
231 | { |
232 | return {}; |
233 | } |
234 | |
235 | /*! |
236 | \internal |
237 | Returns an implementation-specific integer value, representing the TLS library's |
238 | version that this backend was built against (i.e. compile-time library version). |
239 | The default implementation returns 0. |
240 | |
241 | \sa tlsLibraryVersionNumber() |
242 | */ |
243 | |
244 | long QTlsBackend::tlsLibraryBuildVersionNumber() const |
245 | { |
246 | return 0; |
247 | } |
248 | |
249 | /*! |
250 | \internal |
251 | Returns an implementation-specific string, representing the TLS library's version |
252 | that this backend was built against (i.e. compile-time version). The default |
253 | implementation returns an empty string. |
254 | |
255 | \sa tlsLibraryVersionString() |
256 | */ |
257 | QString QTlsBackend::tlsLibraryBuildVersionString() const |
258 | { |
259 | return {}; |
260 | } |
261 | |
262 | /*! |
263 | \internal |
264 | QSslSocket and related classes call this function to ensure that backend's internal |
265 | resources - e.g. CA certificates, or ciphersuites - were properly initialized. |
266 | */ |
267 | void QTlsBackend::ensureInitialized() const |
268 | { |
269 | } |
270 | |
271 | #define REPORT_MISSING_SUPPORT(message) \ |
272 | qCWarning(lcSsl) << "The backend" << backendName() << message |
273 | |
274 | /*! |
275 | \internal |
276 | If QSsl::ImplementedClass::Key is present in this backend's implementedClasses(), |
277 | the backend must reimplement this method to return a dynamically-allocated instance |
278 | of an implementation-specific type, inheriting from the class QTlsPrivate::TlsKey. |
279 | The default implementation of this function returns \nullptr. |
280 | |
281 | \sa QSslKey, implementedClasses(), QTlsPrivate::TlsKey |
282 | */ |
283 | QTlsPrivate::TlsKey *QTlsBackend::createKey() const |
284 | { |
285 | REPORT_MISSING_SUPPORT("does not support QSslKey"); |
286 | return nullptr; |
287 | } |
288 | |
289 | /*! |
290 | \internal |
291 | If QSsl::ImplementedClass::Certificate is present in this backend's implementedClasses(), |
292 | the backend must reimplement this method to return a dynamically-allocated instance of an |
293 | implementation-specific type, inheriting from the class QTlsPrivate::X509Certificate. |
294 | The default implementation of this function returns \nullptr. |
295 | |
296 | \sa QSslCertificate, QTlsPrivate::X509Certificate, implementedClasses() |
297 | */ |
298 | QTlsPrivate::X509Certificate *QTlsBackend::createCertificate() const |
299 | { |
300 | REPORT_MISSING_SUPPORT("does not support QSslCertificate"); |
301 | return nullptr; |
302 | } |
303 | |
304 | /*! |
305 | \internal |
306 | This function returns a list of system CA certificates - e.g. certificates, loaded |
307 | from a system store, if available. This function allows implementation of the class |
308 | QSslConfiguration. The default implementation of this function returns an empty list. |
309 | |
310 | \sa QSslCertificate, QSslConfiguration |
311 | */ |
312 | QList<QSslCertificate> QTlsBackend::systemCaCertificates() const |
313 | { |
314 | REPORT_MISSING_SUPPORT("does not provide system CA certificates"); |
315 | return {}; |
316 | } |
317 | |
318 | /*! |
319 | \internal |
320 | If QSsl::ImplementedClass::Socket is present in this backend's implementedClasses(), |
321 | the backend must reimplement this method to return a dynamically-allocated instance of an |
322 | implementation-specific type, inheriting from the class QTlsPrivate::TlsCryptograph. |
323 | The default implementation of this function returns \nullptr. |
324 | |
325 | \sa QSslSocket, QTlsPrivate::TlsCryptograph, implementedClasses() |
326 | */ |
327 | QTlsPrivate::TlsCryptograph *QTlsBackend::createTlsCryptograph() const |
328 | { |
329 | REPORT_MISSING_SUPPORT("does not support QSslSocket"); |
330 | return nullptr; |
331 | } |
332 | |
333 | /*! |
334 | \internal |
335 | If QSsl::ImplementedClass::Dtls is present in this backend's implementedClasses(), |
336 | the backend must reimplement this method to return a dynamically-allocated instance of an |
337 | implementation-specific type, inheriting from the class QTlsPrivate::DtlsCryptograph. |
338 | The default implementation of this function returns \nullptr. |
339 | |
340 | \sa QDtls, QTlsPrivate::DtlsCryptograph, implementedClasses() |
341 | */ |
342 | QTlsPrivate::DtlsCryptograph *QTlsBackend::createDtlsCryptograph(QDtls *qObject, int mode) const |
343 | { |
344 | Q_UNUSED(qObject); |
345 | Q_UNUSED(mode); |
346 | REPORT_MISSING_SUPPORT("does not support QDtls"); |
347 | return nullptr; |
348 | } |
349 | |
350 | /*! |
351 | \internal |
352 | If QSsl::ImplementedClass::DtlsCookie is present in this backend's implementedClasses(), |
353 | the backend must reimplement this method to return a dynamically-allocated instance of an |
354 | implementation-specific type, inheriting from the class QTlsPrivate::DtlsCookieVerifier. The |
355 | default implementation returns \nullptr. |
356 | |
357 | \sa QDtlsClientVerifier, QTlsPrivate::DtlsCookieVerifier, implementedClasses() |
358 | */ |
359 | QTlsPrivate::DtlsCookieVerifier *QTlsBackend::createDtlsCookieVerifier() const |
360 | { |
361 | REPORT_MISSING_SUPPORT("does not support DTLS cookies"); |
362 | return nullptr; |
363 | } |
364 | |
365 | /*! |
366 | \internal |
367 | If QSsl::SupportedFeature::CertificateVerification is present in this backend's |
368 | supportedFeatures(), the backend must reimplement this method to return a pointer |
369 | to a function, that checks a certificate (or a chain of certificates) against available |
370 | CA certificates. The default implementation returns \nullptr. |
371 | |
372 | \sa supportedFeatures(), QSslCertificate |
373 | */ |
374 | |
375 | QTlsPrivate::X509ChainVerifyPtr QTlsBackend::X509Verifier() const |
376 | { |
377 | REPORT_MISSING_SUPPORT("does not support (manual) certificate verification"); |
378 | return nullptr; |
379 | } |
380 | |
381 | /*! |
382 | \internal |
383 | Returns a pointer to function, that reads certificates in PEM format. The |
384 | default implementation returns \nullptr. |
385 | |
386 | \sa QSslCertificate |
387 | */ |
388 | QTlsPrivate::X509PemReaderPtr QTlsBackend::X509PemReader() const |
389 | { |
390 | REPORT_MISSING_SUPPORT("cannot read PEM format"); |
391 | return nullptr; |
392 | } |
393 | |
394 | /*! |
395 | \internal |
396 | Returns a pointer to function, that can read certificates in DER format. |
397 | The default implementation returns \nullptr. |
398 | |
399 | \sa QSslCertificate |
400 | */ |
401 | QTlsPrivate::X509DerReaderPtr QTlsBackend::X509DerReader() const |
402 | { |
403 | REPORT_MISSING_SUPPORT("cannot read DER format"); |
404 | return nullptr; |
405 | } |
406 | |
407 | /*! |
408 | \internal |
409 | Returns a pointer to function, that can read certificates in PKCS 12 format. |
410 | The default implementation returns \nullptr. |
411 | |
412 | \sa QSslCertificate |
413 | */ |
414 | QTlsPrivate::X509Pkcs12ReaderPtr QTlsBackend::X509Pkcs12Reader() const |
415 | { |
416 | REPORT_MISSING_SUPPORT("cannot read PKCS12 format"); |
417 | return nullptr; |
418 | } |
419 | |
420 | /*! |
421 | \internal |
422 | If QSsl::ImplementedClass::EllipticCurve is present in this backend's implementedClasses(), |
423 | and the backend provides information about supported curves, it must reimplement this |
424 | method to return a list of unique identifiers of the supported elliptic curves. The default |
425 | implementation returns an empty list. |
426 | |
427 | \note The meaning of a curve identifier is implementation-specific. |
428 | |
429 | \sa implemenedClasses(), QSslEllipticCurve |
430 | */ |
431 | QList<int> QTlsBackend::ellipticCurvesIds() const |
432 | { |
433 | REPORT_MISSING_SUPPORT("does not support QSslEllipticCurve"); |
434 | return {}; |
435 | } |
436 | |
437 | /*! |
438 | \internal |
439 | If this backend provides information about available elliptic curves, this |
440 | function should return a unique integer identifier for a curve named \a name, |
441 | which is a conventional short name for the curve. The default implementation |
442 | returns 0. |
443 | |
444 | \note The meaning of a curve identifier is implementation-specific. |
445 | |
446 | \sa QSslEllipticCurve::shortName() |
447 | */ |
448 | int QTlsBackend::curveIdFromShortName(const QString &name) const |
449 | { |
450 | Q_UNUSED(name); |
451 | REPORT_MISSING_SUPPORT("does not support QSslEllipticCurve"); |
452 | return 0; |
453 | } |
454 | |
455 | /*! |
456 | \internal |
457 | If this backend provides information about available elliptic curves, this |
458 | function should return a unique integer identifier for a curve named \a name, |
459 | which is a conventional long name for the curve. The default implementation |
460 | returns 0. |
461 | |
462 | \note The meaning of a curve identifier is implementation-specific. |
463 | |
464 | \sa QSslElliptiCurve::longName() |
465 | */ |
466 | int QTlsBackend::curveIdFromLongName(const QString &name) const |
467 | { |
468 | Q_UNUSED(name); |
469 | REPORT_MISSING_SUPPORT("does not support QSslEllipticCurve"); |
470 | return 0; |
471 | } |
472 | |
473 | /*! |
474 | \internal |
475 | If this backend provides information about available elliptic curves, |
476 | this function should return a conventional short name for a curve identified |
477 | by \a cid. The default implementation returns an empty string. |
478 | |
479 | \note The meaning of a curve identifier is implementation-specific. |
480 | |
481 | \sa ellipticCurvesIds(), QSslEllipticCurve::shortName() |
482 | */ |
483 | QString QTlsBackend::shortNameForId(int cid) const |
484 | { |
485 | Q_UNUSED(cid); |
486 | REPORT_MISSING_SUPPORT("does not support QSslEllipticCurve"); |
487 | return {}; |
488 | } |
489 | |
490 | /*! |
491 | \internal |
492 | If this backend provides information about available elliptic curves, |
493 | this function should return a conventional long name for a curve identified |
494 | by \a cid. The default implementation returns an empty string. |
495 | |
496 | \note The meaning of a curve identifier is implementation-specific. |
497 | |
498 | \sa ellipticCurvesIds(), QSslEllipticCurve::shortName() |
499 | */ |
500 | QString QTlsBackend::longNameForId(int cid) const |
501 | { |
502 | Q_UNUSED(cid); |
503 | REPORT_MISSING_SUPPORT("does not support QSslEllipticCurve"); |
504 | return {}; |
505 | } |
506 | |
507 | /*! |
508 | \internal |
509 | Returns true if the elliptic curve identified by \a cid is one of the named |
510 | curves, that can be used in the key exchange when using an elliptic curve |
511 | cipher with TLS; false otherwise. The default implementation returns false. |
512 | |
513 | \note The meaning of curve identifier is implementation-specific. |
514 | */ |
515 | bool QTlsBackend::isTlsNamedCurve(int cid) const |
516 | { |
517 | Q_UNUSED(cid); |
518 | REPORT_MISSING_SUPPORT("does not support QSslEllipticCurve"); |
519 | return false; |
520 | } |
521 | |
522 | /*! |
523 | \internal |
524 | If this backend supports the class QSslDiffieHellmanParameters, this function is |
525 | needed for construction of a QSslDiffieHellmanParameters from DER encoded data. |
526 | This function is expected to return a value that matches an enumerator in |
527 | QSslDiffieHellmanParameters::Error enumeration. The default implementation of this |
528 | function returns 0 (equals to QSslDiffieHellmanParameters::NoError). |
529 | |
530 | \sa QSslDiffieHellmanParameters, implementedClasses() |
531 | */ |
532 | int QTlsBackend::dhParametersFromDer(const QByteArray &derData, QByteArray *data) const |
533 | { |
534 | Q_UNUSED(derData); |
535 | Q_UNUSED(data); |
536 | REPORT_MISSING_SUPPORT("does not support QSslDiffieHellmanParameters in DER format"); |
537 | return {}; |
538 | } |
539 | |
540 | /*! |
541 | \internal |
542 | If this backend supports the class QSslDiffieHellmanParameters, this function is |
543 | is needed for construction of a QSslDiffieHellmanParameters from PEM encoded data. |
544 | This function is expected to return a value that matches an enumerator in |
545 | QSslDiffieHellmanParameters::Error enumeration. The default implementation of this |
546 | function returns 0 (equals to QSslDiffieHellmanParameters::NoError). |
547 | |
548 | \sa QSslDiffieHellmanParameters, implementedClasses() |
549 | */ |
550 | int QTlsBackend::dhParametersFromPem(const QByteArray &pemData, QByteArray *data) const |
551 | { |
552 | Q_UNUSED(pemData); |
553 | Q_UNUSED(data); |
554 | REPORT_MISSING_SUPPORT("does not support QSslDiffieHellmanParameters in PEM format"); |
555 | return {}; |
556 | } |
557 | |
558 | /*! |
559 | \internal |
560 | Returns a list of names of available backends. |
561 | |
562 | \note This list contains only properly initialized backends. |
563 | |
564 | \sa QTlsBackend(), isValid() |
565 | */ |
566 | QList<QString> QTlsBackend::availableBackendNames() |
567 | { |
568 | if (!backends()) |
569 | return {}; |
570 | |
571 | return backends->backendNames(); |
572 | } |
573 | |
574 | /*! |
575 | \internal |
576 | Returns the name of the backend that QSslSocket() would use by default. If no |
577 | backend was found, the function returns an empty string. |
578 | */ |
579 | QString QTlsBackend::defaultBackendName() |
580 | { |
581 | // We prefer OpenSSL as default: |
582 | const auto names = availableBackendNames(); |
583 | auto name = builtinBackendNames[nameIndexOpenSSL]; |
584 | if (names.contains(str: name)) |
585 | return name; |
586 | name = builtinBackendNames[nameIndexSchannel]; |
587 | if (names.contains(str: name)) |
588 | return name; |
589 | name = builtinBackendNames[nameIndexSecureTransport]; |
590 | if (names.contains(str: name)) |
591 | return name; |
592 | |
593 | const auto pos = std::find_if(first: names.begin(), last: names.end(), pred: [](const auto &name) { |
594 | return name != builtinBackendNames[nameIndexCertOnly]; |
595 | }); |
596 | |
597 | if (pos != names.end()) |
598 | return *pos; |
599 | |
600 | if (names.size()) |
601 | return names[0]; |
602 | |
603 | return {}; |
604 | } |
605 | |
606 | /*! |
607 | \internal |
608 | Returns a backend named \a backendName, if it exists. |
609 | Otherwise, it returns \nullptr. |
610 | |
611 | \sa backendName(), QSslSocket::availableBackends() |
612 | */ |
613 | QTlsBackend *QTlsBackend::findBackend(const QString &backendName) |
614 | { |
615 | if (!backends()) |
616 | return {}; |
617 | |
618 | if (auto *fct = backends->backend(name: backendName)) |
619 | return fct; |
620 | |
621 | qCWarning(lcSsl) << "Cannot create unknown backend named"<< backendName; |
622 | return nullptr; |
623 | } |
624 | |
625 | /*! |
626 | \internal |
627 | Returns the backend that QSslSocket is using. If Qt was built without TLS support, |
628 | this function returns a minimal backend that only supports QSslCertificate. |
629 | |
630 | \sa defaultBackend() |
631 | */ |
632 | QTlsBackend *QTlsBackend::activeOrAnyBackend() |
633 | { |
634 | #if QT_CONFIG(ssl) |
635 | return QSslSocketPrivate::tlsBackendInUse(); |
636 | #else |
637 | return findBackend(defaultBackendName()); |
638 | #endif // QT_CONFIG(ssl) |
639 | } |
640 | |
641 | /*! |
642 | \internal |
643 | Returns a list of TLS and DTLS protocol versions, that a backend named |
644 | \a backendName supports. |
645 | |
646 | \note This list is supposed to also include range-based versions, which |
647 | allows negotiation of protocols during the handshake, so that these versions |
648 | can be used when configuring QSslSocket (e.g. QSsl::TlsV1_2OrLater). |
649 | |
650 | \sa QSsl::SslProtocol |
651 | */ |
652 | QList<QSsl::SslProtocol> QTlsBackend::supportedProtocols(const QString &backendName) |
653 | { |
654 | if (!backends()) |
655 | return {}; |
656 | |
657 | if (const auto *fct = backends->backend(name: backendName)) |
658 | return fct->supportedProtocols(); |
659 | |
660 | return {}; |
661 | } |
662 | |
663 | /*! |
664 | \internal |
665 | Returns a list of features that a backend named \a backendName supports. E.g. |
666 | a backend may support PSK (pre-shared keys, defined as QSsl::SupportedFeature::Psk) |
667 | or ALPN (application layer protocol negotiation, identified by |
668 | QSsl::SupportedFeature::ClientSideAlpn or QSsl::SupportedFeature::ServerSideAlpn). |
669 | |
670 | \sa QSsl::SupportedFeature |
671 | */ |
672 | QList<QSsl::SupportedFeature> QTlsBackend::supportedFeatures(const QString &backendName) |
673 | { |
674 | if (!backends()) |
675 | return {}; |
676 | |
677 | if (const auto *fct = backends->backend(name: backendName)) |
678 | return fct->supportedFeatures(); |
679 | |
680 | return {}; |
681 | } |
682 | |
683 | /*! |
684 | \internal |
685 | Returns a list of classes that a backend named \a backendName supports. E.g. a backend |
686 | may implement QSslSocket (QSsl::ImplementedClass::Socket), and QDtls |
687 | (QSsl::ImplementedClass::Dtls). |
688 | |
689 | \sa QSsl::ImplementedClass |
690 | */ |
691 | QList<QSsl::ImplementedClass> QTlsBackend::implementedClasses(const QString &backendName) |
692 | { |
693 | if (!backends()) |
694 | return {}; |
695 | |
696 | if (const auto *fct = backends->backend(name: backendName)) |
697 | return fct->implementedClasses(); |
698 | |
699 | return {}; |
700 | } |
701 | |
702 | /*! |
703 | \internal |
704 | Auxiliary function. Initializes \a key to use \a keyBackend. |
705 | */ |
706 | void QTlsBackend::resetBackend(QSslKey &key, QTlsPrivate::TlsKey *keyBackend) |
707 | { |
708 | #if QT_CONFIG(ssl) |
709 | key.d->backend.reset(p: keyBackend); |
710 | #else |
711 | Q_UNUSED(key); |
712 | Q_UNUSED(keyBackend); |
713 | #endif // QT_CONFIG(ssl) |
714 | } |
715 | |
716 | /*! |
717 | \internal |
718 | Auxiliary function. Initializes client-side \a auth using the \a hint, \a hintLength, |
719 | \a maxIdentityLength and \a maxPskLen. |
720 | */ |
721 | void QTlsBackend::setupClientPskAuth(QSslPreSharedKeyAuthenticator *auth, const char *hint, |
722 | int hintLength, unsigned maxIdentityLen, unsigned maxPskLen) |
723 | { |
724 | Q_ASSERT(auth); |
725 | #if QT_CONFIG(ssl) |
726 | if (hint) |
727 | auth->d->identityHint = QByteArray::fromRawData(data: hint, size: hintLength); // it's NUL terminated, but do not include the NUL |
728 | |
729 | auth->d->maximumIdentityLength = int(maxIdentityLen) - 1; // needs to be NUL terminated |
730 | auth->d->maximumPreSharedKeyLength = int(maxPskLen); |
731 | #else |
732 | Q_UNUSED(auth); |
733 | Q_UNUSED(hint); |
734 | Q_UNUSED(hintLength); |
735 | Q_UNUSED(maxIdentityLen); |
736 | Q_UNUSED(maxPskLen); |
737 | #endif |
738 | } |
739 | |
740 | /*! |
741 | \internal |
742 | Auxiliary function. Initializes server-side \a auth using the \a identity, \a identityHint and |
743 | \a maxPskLen. |
744 | */ |
745 | void QTlsBackend::setupServerPskAuth(QSslPreSharedKeyAuthenticator *auth, const char *identity, |
746 | const QByteArray &identityHint, unsigned int maxPskLen) |
747 | { |
748 | #if QT_CONFIG(ssl) |
749 | Q_ASSERT(auth); |
750 | auth->d->identityHint = identityHint; |
751 | auth->d->identity = identity; |
752 | auth->d->maximumIdentityLength = 0; // user cannot set an identity |
753 | auth->d->maximumPreSharedKeyLength = int(maxPskLen); |
754 | #else |
755 | Q_UNUSED(auth); |
756 | Q_UNUSED(identity); |
757 | Q_UNUSED(identityHint); |
758 | Q_UNUSED(maxPskLen); |
759 | #endif |
760 | } |
761 | |
762 | #if QT_CONFIG(ssl) |
763 | /*! |
764 | \internal |
765 | Auxiliary function. Creates a new QSslCipher from \a descriptionOneLine, \a bits |
766 | and \a supportedBits. \a descriptionOneLine consists of several fields, separated by |
767 | whitespace. These include: cipher name, protocol version, key exchange method, |
768 | authentication method, encryption method, message digest (Mac). Example: |
769 | "ECDHE-RSA-AES256-GCM-SHA256 TLSv1.2 Kx=ECDH Au=RSA Enc=AESGCM(256) Mac=AEAD" |
770 | */ |
771 | QSslCipher QTlsBackend::createCiphersuite(const QString &descriptionOneLine, int bits, int supportedBits) |
772 | { |
773 | QSslCipher ciph; |
774 | |
775 | const auto descriptionList = QStringView{descriptionOneLine}.split(sep: u' ', behavior: Qt::SkipEmptyParts); |
776 | if (descriptionList.size() > 5) { |
777 | ciph.d->isNull = false; |
778 | ciph.d->name = descriptionList.at(i: 0).toString(); |
779 | |
780 | QStringView protoString = descriptionList.at(i: 1); |
781 | ciph.d->protocolString = protoString.toString(); |
782 | ciph.d->protocol = QSsl::UnknownProtocol; |
783 | QT_WARNING_PUSH |
784 | QT_WARNING_DISABLE_DEPRECATED |
785 | if (protoString.startsWith(s: u"TLSv1")) { |
786 | QStringView tail = protoString.sliced(pos: 5); |
787 | if (tail.startsWith(c: u'.')) { |
788 | tail = tail.sliced(pos: 1); |
789 | if (tail == u"3") |
790 | ciph.d->protocol = QSsl::TlsV1_3; |
791 | else if (tail == u"2") |
792 | ciph.d->protocol = QSsl::TlsV1_2; |
793 | else if (tail == u"1") |
794 | ciph.d->protocol = QSsl::TlsV1_1; |
795 | } else if (tail.isEmpty()) { |
796 | ciph.d->protocol = QSsl::TlsV1_0; |
797 | } |
798 | } |
799 | QT_WARNING_POP |
800 | |
801 | if (descriptionList.at(i: 2).startsWith(s: "Kx="_L1)) |
802 | ciph.d->keyExchangeMethod = descriptionList.at(i: 2).mid(pos: 3).toString(); |
803 | if (descriptionList.at(i: 3).startsWith(s: "Au="_L1)) |
804 | ciph.d->authenticationMethod = descriptionList.at(i: 3).mid(pos: 3).toString(); |
805 | if (descriptionList.at(i: 4).startsWith(s: "Enc="_L1)) |
806 | ciph.d->encryptionMethod = descriptionList.at(i: 4).mid(pos: 4).toString(); |
807 | ciph.d->exportable = (descriptionList.size() > 6 && descriptionList.at(i: 6) == "export"_L1); |
808 | |
809 | ciph.d->bits = bits; |
810 | ciph.d->supportedBits = supportedBits; |
811 | } |
812 | |
813 | return ciph; |
814 | } |
815 | |
816 | /*! |
817 | \internal |
818 | Auxiliary function. Creates a new QSslCipher from \a suiteName, \a protocol version and |
819 | \a protocolString. For example: |
820 | \code |
821 | createCiphersuite("ECDHE-RSA-AES256-GCM-SHA256"_L1, QSsl::TlsV1_2, "TLSv1.2"_L1); |
822 | \endcode |
823 | */ |
824 | QSslCipher QTlsBackend::createCiphersuite(const QString &suiteName, QSsl::SslProtocol protocol, |
825 | const QString &protocolString) |
826 | { |
827 | QSslCipher ciph; |
828 | |
829 | if (!suiteName.size()) |
830 | return ciph; |
831 | |
832 | ciph.d->isNull = false; |
833 | ciph.d->name = suiteName; |
834 | ciph.d->protocol = protocol; |
835 | ciph.d->protocolString = protocolString; |
836 | |
837 | const auto bits = QStringView{ciph.d->name}.split(sep: u'-'); |
838 | if (bits.size() >= 2) { |
839 | if (bits.size() == 2 || bits.size() == 3) |
840 | ciph.d->keyExchangeMethod = "RSA"_L1; |
841 | else if (bits.front() == "DH"_L1|| bits.front() == "DHE"_L1) |
842 | ciph.d->keyExchangeMethod = "DH"_L1; |
843 | else if (bits.front() == "ECDH"_L1|| bits.front() == "ECDHE"_L1) |
844 | ciph.d->keyExchangeMethod = "ECDH"_L1; |
845 | else |
846 | qCWarning(lcSsl) << "Unknown Kx"<< ciph.d->name; |
847 | |
848 | if (bits.size() == 2 || bits.size() == 3) |
849 | ciph.d->authenticationMethod = "RSA"_L1; |
850 | else if (ciph.d->name.contains(s: "-ECDSA-"_L1)) |
851 | ciph.d->authenticationMethod = "ECDSA"_L1; |
852 | else if (ciph.d->name.contains(s: "-RSA-"_L1)) |
853 | ciph.d->authenticationMethod = "RSA"_L1; |
854 | else |
855 | qCWarning(lcSsl) << "Unknown Au"<< ciph.d->name; |
856 | |
857 | if (ciph.d->name.contains(s: "RC4-"_L1)) { |
858 | ciph.d->encryptionMethod = "RC4(128)"_L1; |
859 | ciph.d->bits = 128; |
860 | ciph.d->supportedBits = 128; |
861 | } else if (ciph.d->name.contains(s: "DES-CBC3-"_L1)) { |
862 | ciph.d->encryptionMethod = "3DES(168)"_L1; |
863 | ciph.d->bits = 168; |
864 | ciph.d->supportedBits = 168; |
865 | } else if (ciph.d->name.contains(s: "AES128-"_L1)) { |
866 | ciph.d->encryptionMethod = "AES(128)"_L1; |
867 | ciph.d->bits = 128; |
868 | ciph.d->supportedBits = 128; |
869 | } else if (ciph.d->name.contains(s: "AES256-GCM"_L1)) { |
870 | ciph.d->encryptionMethod = "AESGCM(256)"_L1; |
871 | ciph.d->bits = 256; |
872 | ciph.d->supportedBits = 256; |
873 | } else if (ciph.d->name.contains(s: "AES256-"_L1)) { |
874 | ciph.d->encryptionMethod = "AES(256)"_L1; |
875 | ciph.d->bits = 256; |
876 | ciph.d->supportedBits = 256; |
877 | } else if (ciph.d->name.contains(s: "CHACHA20-"_L1)) { |
878 | ciph.d->encryptionMethod = "CHACHA20"_L1; |
879 | ciph.d->bits = 256; |
880 | ciph.d->supportedBits = 256; |
881 | } else if (ciph.d->name.contains(s: "NULL-"_L1)) { |
882 | ciph.d->encryptionMethod = "NULL"_L1; |
883 | } else { |
884 | qCWarning(lcSsl) << "Unknown Enc"<< ciph.d->name; |
885 | } |
886 | } |
887 | return ciph; |
888 | } |
889 | |
890 | /*! |
891 | \internal |
892 | Auxiliary function. Creates a new QSslCipher from \a name, \a keyExchangeMethod, \a encryptionMethod, |
893 | \a authenticationMethod, \a bits, \a protocol version and \a protocolString. |
894 | For example: |
895 | \code |
896 | createCiphersuite("ECDHE-RSA-AES256-GCM-SHA256"_L1, "ECDH"_L1, "AES"_L1, "RSA"_L1, 256, |
897 | QSsl::TlsV1_2, "TLSv1.2"_L1); |
898 | \endcode |
899 | */ |
900 | QSslCipher QTlsBackend::createCiphersuite(const QString &name, const QString &keyExchangeMethod, |
901 | const QString &encryptionMethod, |
902 | const QString &authenticationMethod, |
903 | int bits, QSsl::SslProtocol protocol, |
904 | const QString &protocolString) |
905 | { |
906 | QSslCipher cipher; |
907 | cipher.d->isNull = false; |
908 | cipher.d->name = name; |
909 | cipher.d->bits = bits; |
910 | cipher.d->supportedBits = bits; |
911 | cipher.d->keyExchangeMethod = keyExchangeMethod; |
912 | cipher.d->encryptionMethod = encryptionMethod; |
913 | cipher.d->authenticationMethod = authenticationMethod; |
914 | cipher.d->protocol = protocol; |
915 | cipher.d->protocolString = protocolString; |
916 | return cipher; |
917 | } |
918 | |
919 | /*! |
920 | \internal |
921 | Returns an implementation-specific list of ciphersuites that can be used by QSslSocket. |
922 | |
923 | \sa QSslConfiguration::defaultCiphers() |
924 | */ |
925 | QList<QSslCipher> QTlsBackend::defaultCiphers() |
926 | { |
927 | return QSslSocketPrivate::defaultCiphers(); |
928 | } |
929 | |
930 | /*! |
931 | \internal |
932 | Returns an implementation-specific list of ciphersuites that can be used by QDtls. |
933 | */ |
934 | QList<QSslCipher> QTlsBackend::defaultDtlsCiphers() |
935 | { |
936 | return QSslSocketPrivate::defaultDtlsCiphers(); |
937 | } |
938 | |
939 | /*! |
940 | \internal |
941 | Sets \a ciphers as defaults ciphers that QSslSocket can use. |
942 | |
943 | \sa defaultCiphers() |
944 | */ |
945 | void QTlsBackend::setDefaultCiphers(const QList<QSslCipher> &ciphers) |
946 | { |
947 | QSslSocketPrivate::setDefaultCiphers(ciphers); |
948 | } |
949 | |
950 | /*! |
951 | \internal |
952 | Sets \a ciphers as defaults ciphers that QDtls can use. |
953 | |
954 | \sa defaultDtlsCiphers() |
955 | */ |
956 | void QTlsBackend::setDefaultDtlsCiphers(const QList<QSslCipher> &ciphers) |
957 | { |
958 | QSslSocketPrivate::setDefaultDtlsCiphers(ciphers); |
959 | } |
960 | |
961 | /*! |
962 | \internal |
963 | Sets \a ciphers as a list of supported ciphers. |
964 | |
965 | \sa QSslConfiguration::supportedCiphers() |
966 | */ |
967 | void QTlsBackend::setDefaultSupportedCiphers(const QList<QSslCipher> &ciphers) |
968 | { |
969 | QSslSocketPrivate::setDefaultSupportedCiphers(ciphers); |
970 | } |
971 | |
972 | /*! |
973 | \internal |
974 | Sets the list of QSslEllipticCurve objects, that QSslConfiguration::supportedEllipticCurves() |
975 | returns, to ones that are supported by this backend. |
976 | */ |
977 | void QTlsBackend::resetDefaultEllipticCurves() |
978 | { |
979 | QSslSocketPrivate::resetDefaultEllipticCurves(); |
980 | } |
981 | |
982 | /*! |
983 | Sets \a certs as a list of certificates, that QSslConfiguration::caCertificates() |
984 | reports. |
985 | |
986 | \sa QSslConfiguration::defaultConfiguration(), QSslConfiguration::caCertificates() |
987 | */ |
988 | void QTlsBackend::setDefaultCaCertificates(const QList<QSslCertificate> &certs) |
989 | { |
990 | QSslSocketPrivate::setDefaultCaCertificates(certs); |
991 | } |
992 | |
993 | /*! |
994 | \internal |
995 | Returns true if \a configuration allows loading root certificates on demand. |
996 | */ |
997 | bool QTlsBackend::rootLoadingOnDemandAllowed(const QSslConfiguration &configuration) |
998 | { |
999 | return configuration.d->allowRootCertOnDemandLoading; |
1000 | } |
1001 | |
1002 | /*! |
1003 | \internal |
1004 | Stores \a peerCert in the \a configuration. |
1005 | */ |
1006 | void QTlsBackend::storePeerCertificate(QSslConfiguration &configuration, |
1007 | const QSslCertificate &peerCert) |
1008 | { |
1009 | configuration.d->peerCertificate = peerCert; |
1010 | } |
1011 | |
1012 | /*! |
1013 | \internal |
1014 | Stores \a peerChain in the \a configuration. |
1015 | */ |
1016 | void QTlsBackend::storePeerCertificateChain(QSslConfiguration &configuration, |
1017 | const QList<QSslCertificate> &peerChain) |
1018 | { |
1019 | configuration.d->peerCertificateChain = peerChain; |
1020 | } |
1021 | |
1022 | /*! |
1023 | \internal |
1024 | Clears the peer certificate chain in \a configuration. |
1025 | */ |
1026 | void QTlsBackend::clearPeerCertificates(QSslConfiguration &configuration) |
1027 | { |
1028 | configuration.d->peerCertificate.clear(); |
1029 | configuration.d->peerCertificateChain.clear(); |
1030 | } |
1031 | |
1032 | /*! |
1033 | \internal |
1034 | Clears the peer certificate chain in \a d. |
1035 | */ |
1036 | void QTlsBackend::clearPeerCertificates(QSslSocketPrivate *d) |
1037 | { |
1038 | Q_ASSERT(d); |
1039 | d->configuration.peerCertificate.clear(); |
1040 | d->configuration.peerCertificateChain.clear(); |
1041 | } |
1042 | |
1043 | /*! |
1044 | \internal |
1045 | Updates the configuration in \a d with \a shared value. |
1046 | */ |
1047 | void QTlsBackend::setPeerSessionShared(QSslSocketPrivate *d, bool shared) |
1048 | { |
1049 | Q_ASSERT(d); |
1050 | d->configuration.peerSessionShared = shared; |
1051 | } |
1052 | |
1053 | /*! |
1054 | \internal |
1055 | Sets TLS session in \a d to \a asn1. |
1056 | */ |
1057 | void QTlsBackend::setSessionAsn1(QSslSocketPrivate *d, const QByteArray &asn1) |
1058 | { |
1059 | Q_ASSERT(d); |
1060 | d->configuration.sslSession = asn1; |
1061 | } |
1062 | |
1063 | /*! |
1064 | \internal |
1065 | Sets TLS session lifetime hint in \a d to \a hint. |
1066 | */ |
1067 | void QTlsBackend::setSessionLifetimeHint(QSslSocketPrivate *d, int hint) |
1068 | { |
1069 | Q_ASSERT(d); |
1070 | d->configuration.sslSessionTicketLifeTimeHint = hint; |
1071 | } |
1072 | |
1073 | /*! |
1074 | \internal |
1075 | Sets application layer protocol negotiation status in \a d to \a st. |
1076 | */ |
1077 | void QTlsBackend::setAlpnStatus(QSslSocketPrivate *d, AlpnNegotiationStatus st) |
1078 | { |
1079 | Q_ASSERT(d); |
1080 | d->configuration.nextProtocolNegotiationStatus = st; |
1081 | } |
1082 | |
1083 | /*! |
1084 | \internal |
1085 | Sets \a protocol in \a d as a negotiated application layer protocol. |
1086 | */ |
1087 | void QTlsBackend::setNegotiatedProtocol(QSslSocketPrivate *d, const QByteArray &protocol) |
1088 | { |
1089 | Q_ASSERT(d); |
1090 | d->configuration.nextNegotiatedProtocol = protocol; |
1091 | } |
1092 | |
1093 | /*! |
1094 | \internal |
1095 | Stores \a peerCert in the TLS configuration of \a d. |
1096 | */ |
1097 | void QTlsBackend::storePeerCertificate(QSslSocketPrivate *d, const QSslCertificate &peerCert) |
1098 | { |
1099 | Q_ASSERT(d); |
1100 | d->configuration.peerCertificate = peerCert; |
1101 | } |
1102 | |
1103 | /*! |
1104 | \internal |
1105 | |
1106 | Stores \a peerChain in the TLS configuration of \a d. |
1107 | |
1108 | \note This is a helper function that TlsCryptograph and DtlsCryptograph |
1109 | call during a handshake. |
1110 | */ |
1111 | void QTlsBackend::storePeerCertificateChain(QSslSocketPrivate *d, |
1112 | const QList<QSslCertificate> &peerChain) |
1113 | { |
1114 | Q_ASSERT(d); |
1115 | d->configuration.peerCertificateChain = peerChain; |
1116 | } |
1117 | |
1118 | /*! |
1119 | \internal |
1120 | |
1121 | Adds \a rootCert to the list of trusted root certificates in \a d. |
1122 | |
1123 | \note In Qt 6.1 it's only used on Windows, during so called 'CA fetch'. |
1124 | */ |
1125 | void QTlsBackend::addTustedRoot(QSslSocketPrivate *d, const QSslCertificate &rootCert) |
1126 | { |
1127 | Q_ASSERT(d); |
1128 | if (!d->configuration.caCertificates.contains(t: rootCert)) |
1129 | d->configuration.caCertificates += rootCert; |
1130 | } |
1131 | |
1132 | /*! |
1133 | \internal |
1134 | |
1135 | Saves ephemeral \a key in \a d. |
1136 | |
1137 | \sa QSslConfiguration::ephemeralKey() |
1138 | */ |
1139 | void QTlsBackend::setEphemeralKey(QSslSocketPrivate *d, const QSslKey &key) |
1140 | { |
1141 | Q_ASSERT(d); |
1142 | d->configuration.ephemeralServerKey = key; |
1143 | } |
1144 | |
1145 | /*! |
1146 | \internal |
1147 | |
1148 | Implementation-specific. Sets the security level suitable for Qt's |
1149 | auto-tests. |
1150 | */ |
1151 | void QTlsBackend::forceAutotestSecurityLevel() |
1152 | { |
1153 | } |
1154 | |
1155 | #endif // QT_CONFIG(ssl) |
1156 | |
1157 | namespace QTlsPrivate { |
1158 | |
1159 | /*! |
1160 | \internal (Network-private) |
1161 | \namespace QTlsPrivate |
1162 | \brief Namespace containing onternal types that TLS backends implement. |
1163 | |
1164 | This namespace is private to Qt and the backends that implement its TLS support. |
1165 | */ |
1166 | |
1167 | /*! |
1168 | \class TlsKey |
1169 | \internal (Network-private) |
1170 | \brief TlsKey is an abstract class, that allows a TLS plugin to provide |
1171 | an underlying implementation for the class QSslKey. |
1172 | |
1173 | Most functions in the class TlsKey are pure virtual and thus have to be |
1174 | reimplemented by a TLS backend that supports QSslKey. In many cases an |
1175 | empty implementation as an overrider is sufficient, albeit with some |
1176 | of QSslKey's functionality missing. |
1177 | |
1178 | \sa QTlsBackend::createKey(), QTlsBackend::implementedClasses(), QSslKey |
1179 | */ |
1180 | |
1181 | /*! |
1182 | \fn void TlsKey::decodeDer(KeyType type, KeyAlgorithm algorithm, const QByteArray &der, const QByteArray &passPhrase, bool deepClear) |
1183 | \internal |
1184 | |
1185 | If a support of public and private keys in DER format is required, this function |
1186 | must be overridden and should initialize this key using the \a type, \a algorithm, \a der |
1187 | and \a passPhrase. If this key was initialized previously, \a deepClear |
1188 | has an implementation-specific meaning (e.g., if an implementation is using |
1189 | reference-counting and can share internally some data structures, a value \c true may |
1190 | trigger decrementing a reference counter on some implementation-specific object). |
1191 | |
1192 | \note An empty overrider is sufficient, but then reading keys in QSsl::Der format |
1193 | will not be supported. |
1194 | |
1195 | \sa isNull(), QSsl::KeyType, QSsl::EncodingFormat, QSsl::KeyAlgorithm |
1196 | */ |
1197 | |
1198 | /*! |
1199 | \fn void TlsKey::decodePem(KeyType type, KeyAlgorithm algorithm, const QByteArray &pem, const QByteArray &passPhrase, bool deepClear) |
1200 | \internal |
1201 | |
1202 | If a support of public and private keys in PEM format is required, this function must |
1203 | be overridden and should initialize this key using the \a type, \a algorithm, \a pem and |
1204 | \a passPhrase. If this key was initialized previously, \a deepClear has an |
1205 | implementation-specific meaning (e.g., in an implementation using reference-counting, |
1206 | a value \c true may trigger decrementing a reference counter on some implementation-specific |
1207 | object). |
1208 | |
1209 | \note An empty overrider is sufficient, but then reading keys in QSsl::Pem format |
1210 | will not be supported. |
1211 | |
1212 | \sa isNull(), QSsl::KeyType, QSsl::EncodingFormat, QSsl::KeyAlgorithm |
1213 | */ |
1214 | |
1215 | /*! |
1216 | \fn QByteArray TlsKey::toPem(const QByteArray &passPhrase) const |
1217 | \internal |
1218 | |
1219 | This function must be overridden, if converting a key to PEM format, potentially with |
1220 | encryption, is needed (e.g. to save a QSslKey into a file). If this key is |
1221 | private and \a passPhrase is not empty, the key's data is expected to be encrypted using |
1222 | some conventional encryption algorithm (e.g. DES or AES - the one that different tools |
1223 | or even the class QSslKey can understand later). |
1224 | |
1225 | \note If this particular functionality is not needed, an overrider returning an |
1226 | empty QByteArray is sufficient. |
1227 | |
1228 | \sa QSslKey::toPem() |
1229 | */ |
1230 | |
1231 | /*! |
1232 | \fn QByteArray TlsKey::derFromPem(const QByteArray &pem, QMap<QByteArray, QByteArray> *headers) const |
1233 | \internal |
1234 | |
1235 | Converts \a pem to DER format, using this key's type and algorithm. The parameter \a headers |
1236 | must be a valid, non-null pointer. When parsing \a pem, the headers found there will be saved |
1237 | into \a headers. |
1238 | |
1239 | \note An overrider returning an empty QByteArray is sufficient, if QSslKey::toDer() is not |
1240 | needed. |
1241 | |
1242 | \note This function is very implementation-specific. A backend, that already has this key's |
1243 | non-empty DER data, may simply return this data. |
1244 | |
1245 | \sa QSslKey::toDer() |
1246 | */ |
1247 | |
1248 | /*! |
1249 | \fn QByteArray TlsKey::pemFromDer(const QByteArray &der, const QMap<QByteArray, QByteArray> &headers) const |
1250 | \internal |
1251 | |
1252 | If overridden, this function is expected to convert \a der, using \a headers, to PEM format. |
1253 | |
1254 | \note This function is very implementation-specific. As of now (Qt 6.1), it is only required by |
1255 | Qt's own non-OpenSSL backends, that internally use DER and implement QSslKey::toPem() |
1256 | via pemFromDer(). |
1257 | */ |
1258 | |
1259 | /*! |
1260 | \fn void TlsKey::fromHandle(Qt::HANDLE handle, KeyType type) |
1261 | \internal |
1262 | |
1263 | Initializes this key using the \a handle and \a type, taking the ownership |
1264 | of the \a handle. |
1265 | |
1266 | \note The meaning of the \a handle is implementation-specific. |
1267 | |
1268 | \note If a TLS backend does not support such keys, it must provide an |
1269 | empty implementation. |
1270 | |
1271 | \sa handle(), QSslKey::QSslKey(), QSslKet::handle() |
1272 | */ |
1273 | |
1274 | /*! |
1275 | \fn TlsKey::handle() const |
1276 | \internal |
1277 | |
1278 | If a TLS backend supports opaque keys, returns a native handle that |
1279 | this key was initialized with. |
1280 | |
1281 | \sa fromHandle(), QSslKey::handle() |
1282 | */ |
1283 | |
1284 | /*! |
1285 | \fn bool TlsKey::isNull() const |
1286 | \internal |
1287 | |
1288 | Returns \c true if this is a null key, \c false otherwise. |
1289 | |
1290 | \note A null key corresponds to the default-constructed |
1291 | QSslKey or the one, that was cleared via QSslKey::clear(). |
1292 | |
1293 | \sa QSslKey::isNull() |
1294 | */ |
1295 | |
1296 | /*! |
1297 | \fn QSsl::KeyType TlsKey::type() const |
1298 | \internal |
1299 | |
1300 | Returns the type of this key (public or private). |
1301 | */ |
1302 | |
1303 | /*! |
1304 | \fn QSsl::KeyAlgorithm TlsKey::algorithm() const |
1305 | \internal |
1306 | |
1307 | Return this key's algorithm. |
1308 | */ |
1309 | |
1310 | /*! |
1311 | \fn int TlsKey::length() const |
1312 | \internal |
1313 | |
1314 | Returns the length of the key in bits, or -1 if the key is null. |
1315 | */ |
1316 | |
1317 | /*! |
1318 | \fn void TlsKey::clear(bool deep) |
1319 | \internal |
1320 | |
1321 | Clears the contents of this key, making it a null key. The meaning |
1322 | of \a deep is implementation-specific (e.g. if some internal objects |
1323 | representing a key can be shared using reference counting, \a deep equal |
1324 | to \c true would imply decrementing a reference count). |
1325 | |
1326 | \sa isNull() |
1327 | */ |
1328 | |
1329 | /*! |
1330 | \fn bool TlsKey::isPkcs8() const |
1331 | \internal |
1332 | |
1333 | This function is internally used only by Qt's own TLS plugins and affects |
1334 | the way PEM file is generated by TlsKey. It's sufficient to override it |
1335 | and return \c false in case a new TLS backend is not using Qt's plugin |
1336 | as a base. |
1337 | */ |
1338 | |
1339 | /*! |
1340 | \fn QByteArray TlsKey::decrypt(Cipher cipher, const QByteArray &data, const QByteArray &passPhrase, const QByteArray &iv) const |
1341 | \internal |
1342 | |
1343 | This function allows to decrypt \a data (for example, a private key read from a file), using |
1344 | \a passPhrase, initialization vector \a iv. \a cipher is describing a block cipher and its |
1345 | mode (for example, AES256 + CBC). decrypt() is needed to implement QSslKey's constructor. |
1346 | |
1347 | \note A TLS backend may provide an empty implementation, but as a result QSslKey will not be able |
1348 | to work with private encrypted keys. |
1349 | |
1350 | \sa QSslKey |
1351 | */ |
1352 | |
1353 | /*! |
1354 | \fn QByteArray TlsKey::encrypt(Cipher cipher, const QByteArray &data, const QByteArray &passPhrase, const QByteArray &iv) const |
1355 | \internal |
1356 | |
1357 | This function is needed to implement QSslKey::toPem() with encryption (for a private |
1358 | key). \a cipher names a block cipher to use to encrypt \a data, using |
1359 | \a passPhrase and initialization vector \a iv. |
1360 | |
1361 | \note An empty implementation is sufficient, but QSslKey::toPem() will fail for |
1362 | a private key and non-empty passphrase. |
1363 | |
1364 | \sa QSslKey |
1365 | */ |
1366 | |
1367 | /*! |
1368 | \internal |
1369 | |
1370 | Destroys this key. |
1371 | */ |
1372 | TlsKey::~TlsKey() = default; |
1373 | |
1374 | /*! |
1375 | \internal |
1376 | |
1377 | A convenience function that returns a string, corresponding to the |
1378 | key type or algorithm, which can be used as a header in a PEM file. |
1379 | */ |
1380 | QByteArray TlsKey::pemHeader() const |
1381 | { |
1382 | if (type() == QSsl::PublicKey) |
1383 | return QByteArrayLiteral("-----BEGIN PUBLIC KEY-----"); |
1384 | else if (algorithm() == QSsl::Rsa) |
1385 | return QByteArrayLiteral("-----BEGIN RSA PRIVATE KEY-----"); |
1386 | else if (algorithm() == QSsl::Dsa) |
1387 | return QByteArrayLiteral("-----BEGIN DSA PRIVATE KEY-----"); |
1388 | else if (algorithm() == QSsl::Ec) |
1389 | return QByteArrayLiteral("-----BEGIN EC PRIVATE KEY-----"); |
1390 | else if (algorithm() == QSsl::Dh) |
1391 | return QByteArrayLiteral("-----BEGIN PRIVATE KEY-----"); |
1392 | |
1393 | Q_UNREACHABLE_RETURN({}); |
1394 | } |
1395 | |
1396 | /*! |
1397 | \internal |
1398 | A convenience function that returns a string, corresponding to the |
1399 | key type or algorithm, which can be used as a footer in a PEM file. |
1400 | */ |
1401 | QByteArray TlsKey::pemFooter() const |
1402 | { |
1403 | if (type() == QSsl::PublicKey) |
1404 | return QByteArrayLiteral("-----END PUBLIC KEY-----"); |
1405 | else if (algorithm() == QSsl::Rsa) |
1406 | return QByteArrayLiteral("-----END RSA PRIVATE KEY-----"); |
1407 | else if (algorithm() == QSsl::Dsa) |
1408 | return QByteArrayLiteral("-----END DSA PRIVATE KEY-----"); |
1409 | else if (algorithm() == QSsl::Ec) |
1410 | return QByteArrayLiteral("-----END EC PRIVATE KEY-----"); |
1411 | else if (algorithm() == QSsl::Dh) |
1412 | return QByteArrayLiteral("-----END PRIVATE KEY-----"); |
1413 | |
1414 | Q_UNREACHABLE_RETURN({}); |
1415 | } |
1416 | |
1417 | /*! |
1418 | \class X509Certificate |
1419 | \internal (Network-private) |
1420 | \brief X509Certificate is an abstract class that allows a TLS backend to |
1421 | provide an implementation of the QSslCertificate class. |
1422 | |
1423 | This class provides an interface that must be reimplemented by a TLS plugin, |
1424 | that supports QSslCertificate. Most functions are pure virtual, and thus |
1425 | have to be overridden. For some of them, an empty overrider is acceptable, |
1426 | though a part of functionality in QSslCertificate will be missing. |
1427 | |
1428 | \sa QTlsBackend::createCertificate(), QTlsBackend::X509PemReader(), QTlsBackend::X509DerReader() |
1429 | */ |
1430 | |
1431 | /*! |
1432 | \fn bool X509Certificate::isEqual(const X509Certificate &other) const |
1433 | \internal |
1434 | |
1435 | This function is expected to return \c true if this certificate is the same as |
1436 | the \a other, \c false otherwise. Used by QSslCertificate's comparison operators. |
1437 | */ |
1438 | |
1439 | /*! |
1440 | \fn bool X509Certificate::isNull() const |
1441 | \internal |
1442 | |
1443 | Returns true if this certificate was default-constructed and not initialized yet. |
1444 | This function is called by QSslCertificate::isNull(). |
1445 | |
1446 | \sa QSslCertificate::isNull() |
1447 | */ |
1448 | |
1449 | /*! |
1450 | \fn bool X509Certificate::isSelfSigned() const |
1451 | \internal |
1452 | |
1453 | This function is needed to implement QSslCertificate::isSelfSigned() |
1454 | |
1455 | \sa QSslCertificate::isSelfSigned() |
1456 | */ |
1457 | |
1458 | /*! |
1459 | \fn QByteArray X509Certificate::version() const |
1460 | \internal |
1461 | |
1462 | Implements QSslCertificate::version(). |
1463 | |
1464 | \sa QSslCertificate::version() |
1465 | */ |
1466 | |
1467 | /*! |
1468 | \fn QByteArray X509Certificate::serialNumber() const |
1469 | \internal |
1470 | |
1471 | This function is expected to return the certificate's serial number string in |
1472 | hexadecimal format. |
1473 | |
1474 | \sa QSslCertificate::serialNumber() |
1475 | */ |
1476 | |
1477 | /*! |
1478 | \fn QStringList X509Certificate::issuerInfo(QSslCertificate::SubjectInfo subject) const |
1479 | \internal |
1480 | |
1481 | This function is expected to return the issuer information for the \a subject |
1482 | from the certificate, or an empty list if there is no information for subject |
1483 | in the certificate. There can be more than one entry of each type. |
1484 | |
1485 | \sa QSslCertificate::issuerInfo(). |
1486 | */ |
1487 | |
1488 | /*! |
1489 | \fn QStringList X509Certificate::issuerInfo(const QByteArray &attribute) const |
1490 | \internal |
1491 | |
1492 | This function is expected to return the issuer information for attribute from |
1493 | the certificate, or an empty list if there is no information for \a attribute |
1494 | in the certificate. There can be more than one entry for an attribute. |
1495 | |
1496 | \sa QSslCertificate::issuerInfo(). |
1497 | */ |
1498 | |
1499 | /*! |
1500 | \fn QStringList X509Certificate::subjectInfo(QSslCertificate::SubjectInfo subject) const |
1501 | \internal |
1502 | |
1503 | This function is expected to return the information for the \a subject, or an empty list |
1504 | if there is no information for subject in the certificate. There can be more than one |
1505 | entry of each type. |
1506 | |
1507 | \sa QSslCertificate::subjectInfo(). |
1508 | */ |
1509 | |
1510 | /*! |
1511 | \fn QStringList X509Certificate::subjectInfo(const QByteArray &attribute) const |
1512 | \internal |
1513 | |
1514 | This function is expected to return the subject information for \a attribute, or |
1515 | an empty list if there is no information for attribute in the certificate. |
1516 | There can be more than one entry for an attribute. |
1517 | |
1518 | \sa QSslCertificate::subjectInfo(). |
1519 | */ |
1520 | |
1521 | /*! |
1522 | \fn QList<QByteArray> X509Certificate::subjectInfoAttributes() const |
1523 | \internal |
1524 | |
1525 | This function is expected to return a list of the attributes that have values |
1526 | in the subject information of this certificate. The information associated |
1527 | with a given attribute can be accessed using the subjectInfo() method. Note |
1528 | that this list may include the OIDs for any elements that are not known by |
1529 | the TLS backend. |
1530 | |
1531 | \note This function is needed for QSslCertificate:::subjectInfoAttributes(). |
1532 | |
1533 | \sa subjectInfo() |
1534 | */ |
1535 | |
1536 | /*! |
1537 | \fn QList<QByteArray> X509Certificate::issuerInfoAttributes() const |
1538 | \internal |
1539 | |
1540 | This function is expected to return a list of the attributes that have |
1541 | values in the issuer information of this certificate. The information |
1542 | associated with a given attribute can be accessed using the issuerInfo() |
1543 | method. Note that this list may include the OIDs for any |
1544 | elements that are not known by the TLS backend. |
1545 | |
1546 | \note This function implements QSslCertificate::issuerInfoAttributes(). |
1547 | |
1548 | \sa issuerInfo() |
1549 | */ |
1550 | |
1551 | /*! |
1552 | \fn QMultiMap<QSsl::AlternativeNameEntryType, QString> X509Certificate::subjectAlternativeNames() const |
1553 | \internal |
1554 | |
1555 | This function is expected to return the list of alternative subject names for |
1556 | this certificate. The alternative names typically contain host names, optionally |
1557 | with wildcards, that are valid for this certificate. |
1558 | |
1559 | \sa subjectInfo() |
1560 | */ |
1561 | |
1562 | /*! |
1563 | \fn QDateTime X509Certificate::effectiveDate() const |
1564 | \internal |
1565 | |
1566 | This function is expected to return the date-time that the certificate |
1567 | becomes valid, or an empty QDateTime if this is a null certificate. |
1568 | |
1569 | \sa expiryDate() |
1570 | */ |
1571 | |
1572 | /*! |
1573 | \fn QDateTime X509Certificate::expiryDate() const |
1574 | \internal |
1575 | |
1576 | This function is expected to return the date-time that the certificate expires, |
1577 | or an empty QDateTime if this is a null certificate. |
1578 | |
1579 | \sa effectiveDate() |
1580 | */ |
1581 | |
1582 | /*! |
1583 | \fn qsizetype X509Certificate::numberOfExtensions() const |
1584 | \internal |
1585 | |
1586 | This function is expected to return the number of X509 extensions of |
1587 | this certificate. |
1588 | */ |
1589 | |
1590 | /*! |
1591 | \fn QString X509Certificate::oidForExtension(qsizetype i) const |
1592 | \internal |
1593 | |
1594 | This function is expected to return the ASN.1 OID for the extension |
1595 | with index \a i. |
1596 | |
1597 | \sa numberOfExtensions() |
1598 | */ |
1599 | |
1600 | /*! |
1601 | \fn QString X509Certificate::nameForExtension(qsizetype i) const |
1602 | \internal |
1603 | |
1604 | This function is expected to return the name for the extension |
1605 | with index \a i. If no name is known for the extension then the |
1606 | OID will be returned. |
1607 | |
1608 | \sa numberOfExtensions(), oidForExtension() |
1609 | */ |
1610 | |
1611 | /*! |
1612 | \fn QVariant X509Certificate::valueForExtension(qsizetype i) const |
1613 | \internal |
1614 | |
1615 | This function is expected to return the value of the extension |
1616 | with index \a i. The structure of the value returned depends on |
1617 | the extension type |
1618 | |
1619 | \sa numberOfExtensions() |
1620 | */ |
1621 | |
1622 | /*! |
1623 | \fn bool X509Certificate::isExtensionCritical(qsizetype i) const |
1624 | \internal |
1625 | |
1626 | This function is expected to return the criticality of the extension |
1627 | with index \a i. |
1628 | |
1629 | \sa numberOfExtensions() |
1630 | */ |
1631 | |
1632 | /*! |
1633 | \fn bool X509Certificate::isExtensionSupported(qsizetype i) const |
1634 | \internal |
1635 | |
1636 | This function is expected to return \c true if this extension is supported. |
1637 | In this case, supported simply means that the structure of the QVariant returned |
1638 | by the valueForExtension() accessor will remain unchanged between versions. |
1639 | |
1640 | \sa numberOfExtensions() |
1641 | */ |
1642 | |
1643 | /*! |
1644 | \fn QByteArray X509Certificate::toPem() const |
1645 | \internal |
1646 | |
1647 | This function is expected to return this certificate converted to a PEM (Base64) |
1648 | encoded representation. |
1649 | */ |
1650 | |
1651 | /*! |
1652 | \fn QByteArray X509Certificate::toDer() const |
1653 | \internal |
1654 | |
1655 | This function is expected to return this certificate converted to a DER (binary) |
1656 | encoded representation. |
1657 | */ |
1658 | |
1659 | /*! |
1660 | \fn QString X509Certificate::toText() const |
1661 | \internal |
1662 | |
1663 | This function is expected to return this certificate converted to a human-readable |
1664 | text representation. |
1665 | */ |
1666 | |
1667 | /*! |
1668 | \fn Qt::HANDLE X509Certificate::handle() const |
1669 | \internal |
1670 | |
1671 | This function is expected to return a pointer to the native certificate handle, |
1672 | if there is one, else nullptr. |
1673 | */ |
1674 | |
1675 | /*! |
1676 | \fn size_t X509Certificate::hash(size_t seed) const |
1677 | \internal |
1678 | |
1679 | This function is expected to return the hash value for this certificate, |
1680 | using \a seed to seed the calculation. |
1681 | */ |
1682 | |
1683 | /*! |
1684 | \internal |
1685 | |
1686 | Destroys this certificate. |
1687 | */ |
1688 | X509Certificate::~X509Certificate() = default; |
1689 | |
1690 | /*! |
1691 | \internal |
1692 | |
1693 | Returns the certificate subject's public key. |
1694 | */ |
1695 | TlsKey *X509Certificate::publicKey() const |
1696 | { |
1697 | return nullptr; |
1698 | } |
1699 | |
1700 | #if QT_CONFIG(ssl) |
1701 | |
1702 | /*! |
1703 | \class TlsCryptograph |
1704 | \internal (Network-private) |
1705 | \brief TlsCryptograph is an abstract class, that allows a TLS plugin to implement QSslSocket. |
1706 | |
1707 | This abstract base class provides an interface that must be reimplemented by a TLS plugin, |
1708 | that supports QSslSocket. A class, implementing TlsCryptograph's interface, is responsible |
1709 | for TLS handshake, reading and writing encryped application data; it is expected |
1710 | to work with QSslSocket and it's private implementation - QSslSocketPrivate. |
1711 | QSslSocketPrivate provides access to its read/write buffers, QTcpSocket it |
1712 | internally uses for connecting, reading and writing. QSslSocketPrivate |
1713 | can also be used for reporting errors and storing the certificates received |
1714 | during the handshake phase. |
1715 | |
1716 | \note Most of the functions in this class are pure virtual and have no actual implementation |
1717 | in the QtNetwork module. This documentation is mostly conceptual and only describes what those |
1718 | functions are expected to do, but not how they must be implemented. |
1719 | |
1720 | \sa QTlsBackend::createTlsCryptograph() |
1721 | */ |
1722 | |
1723 | /*! |
1724 | \fn void TlsCryptograph::init(QSslSocket *q, QSslSocketPrivate *d) |
1725 | \internal |
1726 | |
1727 | When initializing this TlsCryptograph, QSslSocket will pass a pointer to self and |
1728 | its d-object using this function. |
1729 | */ |
1730 | |
1731 | /*! |
1732 | \fn QList<QSslError> TlsCryptograph::tlsErrors() const |
1733 | \internal |
1734 | |
1735 | Returns a list of QSslError, describing errors encountered during |
1736 | the TLS handshake. |
1737 | |
1738 | \sa QSslSocket::sslHandshakeErrors() |
1739 | */ |
1740 | |
1741 | /*! |
1742 | \fn void TlsCryptograph::startClientEncryption() |
1743 | \internal |
1744 | |
1745 | A client-side QSslSocket calls this function after its internal TCP socket |
1746 | establishes a connection with a remote host, or from QSslSocket::startClientEncryption(). |
1747 | This TlsCryptograph is expected to initialize some implementation-specific TLS context, |
1748 | if needed, and then start the client side of the TLS handshake (for example, by calling |
1749 | transmit()), using TCP socket from QSslSocketPrivate. |
1750 | |
1751 | \sa init(), transmit(), QSslSocket::startClientEncryption(), QSslSocket::connectToHostEncrypted() |
1752 | */ |
1753 | |
1754 | /*! |
1755 | \fn void TlsCryptograph::startServerEncryption() |
1756 | \internal |
1757 | |
1758 | This function is called by QSslSocket::startServerEncryption(). The TlsCryptograph |
1759 | is expected to initialize some implementation-specific TLS context, if needed, |
1760 | and then try to read the ClientHello message and continue the TLS handshake |
1761 | (for example, by calling transmit()). |
1762 | |
1763 | \sa transmit(), QSslSocket::startServerEncryption() |
1764 | */ |
1765 | |
1766 | /*! |
1767 | \fn void TlsCryptograph::continueHandshake() |
1768 | \internal |
1769 | |
1770 | QSslSocket::resume() calls this function if its pause mode is QAbstractSocket::PauseOnSslErrors, |
1771 | and errors, found during the handshake, were ignored. If implemented, this function is expected |
1772 | to emit QSslSocket::encrypted(). |
1773 | |
1774 | \sa QAbstractSocket::pauseMode(), QSslSocket::sslHandshakeErrors(), QSslSocket::ignoreSslErrors(), QSslSocket::resume() |
1775 | */ |
1776 | |
1777 | /*! |
1778 | \fn void TlsCryptograph::disconnectFromHost() |
1779 | \internal |
1780 | |
1781 | This function is expected to call disconnectFromHost() on the TCP socket |
1782 | that can be obtained from QSslSocketPrivate. Any additional actions |
1783 | are implementation-specific (e.g., sending shutdown alert message). |
1784 | |
1785 | */ |
1786 | |
1787 | /*! |
1788 | \fn void TlsCryptograph::disconnected() |
1789 | \internal |
1790 | |
1791 | This function is called when the remote has disconnected. If there |
1792 | is data left to be read you may ignore the maxReadBufferSize restriction |
1793 | and read it all now. |
1794 | */ |
1795 | |
1796 | /*! |
1797 | \fn QSslCipher TlsCryptograph::sessionCipher() const |
1798 | \internal |
1799 | |
1800 | This function returns a QSslCipher object describing the ciphersuite negotiated |
1801 | during the handshake. |
1802 | */ |
1803 | |
1804 | /*! |
1805 | \fn QSsl::SslProtocol TlsCryptograph::sessionProtocol() const |
1806 | \internal |
1807 | |
1808 | This function returns the version of TLS (or DTLS) protocol negotiated during the handshake. |
1809 | */ |
1810 | |
1811 | /*! |
1812 | \fn void TlsCryptograph::transmit() |
1813 | \internal |
1814 | |
1815 | This function is responsible for reading and writing data. The meaning of these I/O |
1816 | operations depends on an implementation-specific TLS state machine. These read and write |
1817 | operations can be reading and writing parts of a TLS handshake (e.g. by calling handshake-specific |
1818 | functions), or reading and writing application data (if encrypted connection was already |
1819 | established). transmit() is expected to use the QSslSocket's TCP socket (accessible via |
1820 | QSslSocketPrivate) to read the incoming data and write the outgoing data. When in encrypted |
1821 | state, transmit() is also using QSslSocket's internal read and write buffers: the read buffer |
1822 | to fill with decrypted incoming data; the write buffer - for the data to encrypt and send. |
1823 | This TlsCryptograph can also use QSslSocketPrivate to check which TLS errors were ignored during |
1824 | the handshake. |
1825 | |
1826 | \note This function is responsible for emitting QSslSocket's signals, that occur during the |
1827 | handshake (e.g. QSslSocket::sslErrors() or QSslSocket::encrypted()), and also read/write signals, |
1828 | e.g. QSslSocket::bytesWritten() and QSslSocket::readyRead(). |
1829 | |
1830 | \sa init() |
1831 | */ |
1832 | |
1833 | /*! |
1834 | \internal |
1835 | |
1836 | Destroys this object. |
1837 | */ |
1838 | TlsCryptograph::~TlsCryptograph() = default; |
1839 | |
1840 | /*! |
1841 | \internal |
1842 | |
1843 | This function allows to share QSslContext between several QSslSocket objects. |
1844 | The default implementation does nothing. |
1845 | |
1846 | \note The definition of the class QSslContext is implementation-specific. |
1847 | |
1848 | \sa sslContext() |
1849 | */ |
1850 | void TlsCryptograph::checkSettingSslContext(std::shared_ptr<QSslContext> tlsContext) |
1851 | { |
1852 | Q_UNUSED(tlsContext); |
1853 | } |
1854 | |
1855 | /*! |
1856 | \internal |
1857 | |
1858 | Returns the context previously set by checkSettingSslContext() or \nullptr, |
1859 | if no context was set. The default implementation returns \nullptr. |
1860 | |
1861 | \sa checkSettingSslContext() |
1862 | */ |
1863 | std::shared_ptr<QSslContext> TlsCryptograph::sslContext() const |
1864 | { |
1865 | return {}; |
1866 | } |
1867 | |
1868 | /*! |
1869 | \internal |
1870 | |
1871 | If this TLS backend supports reporting errors before handshake is finished, |
1872 | e.g. from a verification callback function, enableHandshakeContinuation() |
1873 | allows this object to continue handshake. The default implementation does |
1874 | nothing. |
1875 | |
1876 | \sa QSslSocket::handshakeInterruptedOnError(), QSslConfiguration::setHandshakeMustInterruptOnError() |
1877 | */ |
1878 | void TlsCryptograph::enableHandshakeContinuation() |
1879 | { |
1880 | } |
1881 | |
1882 | /*! |
1883 | \internal |
1884 | |
1885 | Windows and OpenSSL-specific, only used internally by Qt's OpenSSL TLS backend. |
1886 | |
1887 | \note The default empty implementation is sufficient. |
1888 | */ |
1889 | void TlsCryptograph::cancelCAFetch() |
1890 | { |
1891 | } |
1892 | |
1893 | /*! |
1894 | \internal |
1895 | |
1896 | Windows and Schannel-specific, only used by Qt's Schannel TLS backend, in |
1897 | general, if a backend has its own buffer where it stores undecrypted data |
1898 | then it must report true if it contains any data through this function. |
1899 | |
1900 | \note The default empty implementation, returning \c false is sufficient. |
1901 | */ |
1902 | bool TlsCryptograph::hasUndecryptedData() const |
1903 | { |
1904 | return false; |
1905 | } |
1906 | |
1907 | /*! |
1908 | \internal |
1909 | |
1910 | Returns the list of OCSP (Online Certificate Status Protocol) responses, |
1911 | received during the handshake. The default implementation returns an empty |
1912 | list. |
1913 | */ |
1914 | QList<QOcspResponse> TlsCryptograph::ocsps() const |
1915 | { |
1916 | return {}; |
1917 | } |
1918 | |
1919 | /*! |
1920 | \internal |
1921 | |
1922 | A helper function that can be used during a handshake. Returns \c true if the \a peerName |
1923 | matches one of subject alternative names or common names found in the \a certificate. |
1924 | */ |
1925 | bool TlsCryptograph::isMatchingHostname(const QSslCertificate &certificate, const QString &peerName) |
1926 | { |
1927 | return QSslSocketPrivate::isMatchingHostname(cert: certificate, peerName); |
1928 | } |
1929 | |
1930 | /*! |
1931 | \internal |
1932 | Calls QAbstractSocketPrivate::setErrorAndEmit() for \a d, passing \a errorCode and |
1933 | \a errorDescription as parameters. |
1934 | */ |
1935 | void TlsCryptograph::setErrorAndEmit(QSslSocketPrivate *d, QAbstractSocket::SocketError errorCode, |
1936 | const QString &errorDescription) const |
1937 | { |
1938 | Q_ASSERT(d); |
1939 | d->setErrorAndEmit(errorCode, errorString: errorDescription); |
1940 | } |
1941 | |
1942 | #if QT_CONFIG(dtls) |
1943 | /*! |
1944 | \class DtlsBase |
1945 | \internal (Network-private) |
1946 | \brief DtlsBase is a base class for the classes DtlsCryptograph and DtlsCookieVerifier. |
1947 | |
1948 | DtlsBase is the base class for the classes DtlsCryptograph and DtlsCookieVerifier. It's |
1949 | an abstract class, an interface that these before-mentioned classes share. It allows to |
1950 | set, get and clear the last error that occurred, set and get cookie generation parameters, |
1951 | set and get QSslConfiguration. |
1952 | |
1953 | \note This class is not supposed to be inherited directly, it's only needed by DtlsCryptograph |
1954 | and DtlsCookieVerifier. |
1955 | |
1956 | \sa QDtls, QDtlsClientVerifier, DtlsCryptograph, DtlsCookieVerifier |
1957 | */ |
1958 | |
1959 | /*! |
1960 | \fn void DtlsBase::setDtlsError(QDtlsError code, const QString &description) |
1961 | \internal |
1962 | |
1963 | Sets the last error to \a code and its textual description to \a description. |
1964 | |
1965 | \sa QDtlsError, error(), errorString() |
1966 | */ |
1967 | |
1968 | /*! |
1969 | \fn QDtlsError DtlsBase::error() const |
1970 | \internal |
1971 | |
1972 | This function, when overridden, is expected to return the code for the last error that occurred. |
1973 | If no error occurred it should return QDtlsError::NoError. |
1974 | |
1975 | \sa QDtlsError, errorString(), setDtlsError() |
1976 | */ |
1977 | |
1978 | /*! |
1979 | \fn QDtlsError DtlsBase::errorString() const |
1980 | \internal |
1981 | |
1982 | This function, when overridden, is expected to return the textual description for the last error |
1983 | that occurred or an empty string if no error occurred. |
1984 | |
1985 | \sa QDtlsError, error(), setDtlsError() |
1986 | */ |
1987 | |
1988 | /*! |
1989 | \fn void DtlsBase::clearDtlsError() |
1990 | \internal |
1991 | |
1992 | This function is expected to set the error code for the last error to QDtlsError::NoError and |
1993 | its textual description to an empty string. |
1994 | |
1995 | \sa QDtlsError, setDtlsError(), error(), errorString() |
1996 | */ |
1997 | |
1998 | /*! |
1999 | \fn void DtlsBase::setConfiguration(const QSslConfiguration &configuration) |
2000 | \internal |
2001 | |
2002 | Sets a TLS configuration that an object of a class inheriting from DtlsCookieVerifier or |
2003 | DtlsCryptograph will use, to \a configuration. |
2004 | |
2005 | \sa configuration() |
2006 | */ |
2007 | |
2008 | /*! |
2009 | \fn QSslConfiguration DtlsBase::configuration() const |
2010 | \internal |
2011 | |
2012 | Returns TLS configuration this object is using (either set by setConfiguration() |
2013 | previously, or the default DTLS configuration). |
2014 | |
2015 | \sa setConfiguration(), QSslConfiguration::defaultDtlsConfiguration() |
2016 | */ |
2017 | |
2018 | /*! |
2019 | \fn bool DtlsBase::setCookieGeneratorParameters(const QDtlsClientVerifier::GeneratorParameters ¶ms) |
2020 | \internal |
2021 | |
2022 | Sets the DTLS cookie generation parameters that DtlsCookieVerifier or DtlsCryptograph will use to |
2023 | \a params. |
2024 | |
2025 | \note This function returns \c false if parameters were invalid - if the secret was empty. Otherwise, |
2026 | this function must return true. |
2027 | |
2028 | \sa QDtlsClientVerifier::GeneratorParameters, cookieGeneratorParameters() |
2029 | */ |
2030 | |
2031 | /*! |
2032 | \fn QDtlsClientVerifier::GeneratorParameters DtlsBase::cookieGeneratorParameters() const |
2033 | \internal |
2034 | |
2035 | Returns DTLS cookie generation parameters that were either previously set by setCookieGeneratorParameters(), |
2036 | or default parameters. |
2037 | |
2038 | \sa setCookieGeneratorParameters() |
2039 | */ |
2040 | |
2041 | /*! |
2042 | \internal |
2043 | |
2044 | Destroys this object. |
2045 | */ |
2046 | DtlsBase::~DtlsBase() = default; |
2047 | |
2048 | /*! |
2049 | \class DtlsCookieVerifier |
2050 | \internal (Network-private) |
2051 | \brief DtlsCookieVerifier is an interface that allows a TLS plugin to support the class QDtlsClientVerifier. |
2052 | |
2053 | DtlsCookieVerifier is an interface, an abstract class, that has to be implemented by |
2054 | a TLS plugin that supports DTLS cookie verification. |
2055 | |
2056 | \sa QDtlsClientVerifier |
2057 | */ |
2058 | |
2059 | /*! |
2060 | \fn bool DtlsCookieVerifier::verifyClient(QUdpSocket *socket, const QByteArray &dgram, const QHostAddress &address, quint16 port) |
2061 | \internal |
2062 | |
2063 | This function is expected to verify a ClientHello message, found in \a dgram, using \a address, |
2064 | \a port, and cookie generator parameters. The function returns \c true if such cookie was found |
2065 | and \c false otherwise. If no valid cookie was found in the \a dgram, this verifier should use |
2066 | \a socket to send a HelloVerifyRequest message, using \a address and \a port as the destination |
2067 | and a source material for cookie generation, see also |
2068 | \l {RFC 6347, section 4.2.1} |
2069 | |
2070 | \sa QDtlsClientVerifier |
2071 | */ |
2072 | |
2073 | /*! |
2074 | \fn QByteArray DtlsCookieVerifier::verifiedHello() const |
2075 | \internal |
2076 | |
2077 | Returns the last ClientHello message containing the DTLS cookie that this verifier was |
2078 | able to verify as correct, or an empty byte array. |
2079 | |
2080 | \sa verifyClient() |
2081 | */ |
2082 | |
2083 | /*! |
2084 | \class DtlsCryptograph |
2085 | \internal (Network-private) |
2086 | \brief DtlsCryptograph is an interface that allows a TLS plugin to implement the class QDtls. |
2087 | |
2088 | DtlsCryptograph is an abstract class; a TLS plugin can provide a class, inheriting from |
2089 | DtlsCryptograph and implementing its pure virtual functions, thus implementing the class |
2090 | QDtls and enabling DTLS over UDP. |
2091 | |
2092 | To write DTLS datagrams, a class, inheriting DtlsCryptograph, is expected to use |
2093 | QUdpSocket. In general, all reading is done externally, so DtlsCryptograph is |
2094 | expected to only write into QUdpSocket, check possible socket errors, change socket |
2095 | options if needed. |
2096 | |
2097 | \note All functions in this class are pure virtual and have no actual implementation |
2098 | in the QtNetwork module. This documentation is mostly conceptual and only describes |
2099 | what those functions are expected to do, but not how they must be implemented. |
2100 | |
2101 | \sa QDtls, QUdpSocket |
2102 | */ |
2103 | |
2104 | /*! |
2105 | \fn QSslSocket::SslMode DtlsCryptograph::cryptographMode() const |
2106 | \internal |
2107 | |
2108 | Returns the mode (client or server) this object operates in. |
2109 | |
2110 | \note This mode is set once when a new DtlsCryptograph is created |
2111 | by QTlsBackend and cannot change. |
2112 | |
2113 | \sa QTlsBackend::createDtlsCryptograph() |
2114 | */ |
2115 | |
2116 | /*! |
2117 | \fn void DtlsCryptograph::setPeer(const QHostAddress &addr, quint16 port, const QString &name) |
2118 | \internal |
2119 | |
2120 | Sets the remote peer's address to \a addr and remote port to \a port. \a name, |
2121 | if not empty, is to be used when validating the peer's certificate. |
2122 | |
2123 | \sa peerAddress(), peerPort(), peerVerificationName() |
2124 | */ |
2125 | |
2126 | /*! |
2127 | \fn QHostAddress DtlsCryptograph::peerAddress() const |
2128 | \internal |
2129 | |
2130 | Returns the remote peer's address previously set by setPeer() or, |
2131 | if no address was set, an empty address. |
2132 | |
2133 | \sa setPeer() |
2134 | */ |
2135 | |
2136 | /*! |
2137 | \fn quint16 DtlsCryptograph::peerPort() const |
2138 | \internal |
2139 | |
2140 | Returns the remote peer's port previously set by setPeer() or |
2141 | 0 if no port was set. |
2142 | |
2143 | \sa setPeer(), peerAddress() |
2144 | */ |
2145 | |
2146 | /*! |
2147 | \fn void DtlsCryptograph::setPeerVerificationName(const QString &name) |
2148 | \internal |
2149 | |
2150 | Sets the host name to use during certificate validation to \a name. |
2151 | |
2152 | \sa peerVerificationName(), setPeer() |
2153 | */ |
2154 | |
2155 | /*! |
2156 | \fn QString DtlsCryptograph::peerVerificationName() const |
2157 | \internal |
2158 | |
2159 | Returns the name that this object is using during the certificate validation, |
2160 | previously set by setPeer() or setPeerVerificationName(). Returns an empty string |
2161 | if no peer verification name was set. |
2162 | |
2163 | \sa setPeer(), setPeerVerificationName() |
2164 | */ |
2165 | |
2166 | /*! |
2167 | \fn void DtlsCryptograph::setDtlsMtuHint(quint16 mtu) |
2168 | \internal |
2169 | |
2170 | Sets the maximum transmission unit (MTU), if it is supported by a TLS implementation, to \a mtu. |
2171 | |
2172 | \sa dtlsMtuHint() |
2173 | */ |
2174 | |
2175 | /*! |
2176 | \fn quint16 DtlsCryptograph::dtlsMtuHint() const |
2177 | \internal |
2178 | |
2179 | Returns the value of the maximum transmission unit either previously set by setDtlsMtuHint(), |
2180 | or some implementation-specific value (guessed or somehow known to this DtlsCryptograph). |
2181 | |
2182 | \sa setDtlsMtuHint() |
2183 | */ |
2184 | |
2185 | /*! |
2186 | \fn QDtls::HandshakeState DtlsCryptograph::state() const |
2187 | \internal |
2188 | |
2189 | Returns the current handshake state for this DtlsCryptograph (not started, in progress, |
2190 | peer verification error found, complete). |
2191 | |
2192 | \sa isConnectionEncrypted(), startHandshake() |
2193 | */ |
2194 | |
2195 | /*! |
2196 | \fn bool DtlsCryptograph::isConnectionEncrypted() const |
2197 | \internal |
2198 | |
2199 | Returns \c true if this DtlsCryptograph has completed a handshake without validation |
2200 | errors (or these errors were ignored). Returns \c false otherwise. |
2201 | */ |
2202 | |
2203 | /*! |
2204 | \fn bool DtlsCryptograph::startHandshake(QUdpSocket *socket, const QByteArray &dgram) |
2205 | \internal |
2206 | |
2207 | This function is expected to initialize some implementation-specific context and to start a DTLS |
2208 | handshake, using \a socket to write datagrams (but not to read them). If this object is operating |
2209 | as a server, \a dgram is non-empty and contains the ClientHello message. This function returns |
2210 | \c true if no error occurred (and this DtlsCryptograph's state switching to |
2211 | QDtls::HandshakeState::HandshakeInProgress), \c false otherwise. |
2212 | |
2213 | \sa continueHandshake(), handleTimeout(), resumeHandshake(), abortHandshake(), state() |
2214 | */ |
2215 | |
2216 | /*! |
2217 | \fn bool DtlsCryptograph::handleTimeout(QUdpSocket *socket) |
2218 | \internal |
2219 | |
2220 | In case a timeout occurred during the handshake, allows to re-transmit the last message, |
2221 | using \a socket to write the datagram. Returns \c true if no error occurred, \c false otherwise. |
2222 | |
2223 | \sa QDtls::handshakeTimeout(), QDtls::handleTimeout() |
2224 | */ |
2225 | |
2226 | /*! |
2227 | \fn bool DtlsCryptograph::continueHandshake(QUdpSocket *socket, const QByteArray &dgram) |
2228 | \internal |
2229 | |
2230 | Continues the handshake, using \a socket to write datagrams (a handshake-specific message). |
2231 | \a dgram contains the peer's handshake-specific message. Returns \c false in case some error |
2232 | was encountered (this can include socket-related errors and errors found during the certificate |
2233 | validation). Returns \c true if the handshake was complete successfully, or is still in progress. |
2234 | |
2235 | This function, depending on the implementation-specific state machine, may leave the handshake |
2236 | state in QDtls::HandshakeState::HandshakeInProgress, or switch to QDtls::HandshakeState::HandshakeComplete |
2237 | or QDtls::HandshakeState::PeerVerificationFailed. |
2238 | |
2239 | This function may store the peer's certificate (or chain of certificates), extract and store |
2240 | the information about the negotiated session protocol and ciphersuite. |
2241 | |
2242 | \sa startHandshake() |
2243 | */ |
2244 | |
2245 | /*! |
2246 | \fn bool DtlsCryptograph::resumeHandshake(QUdpSocket *socket) |
2247 | \internal |
2248 | |
2249 | If peer validation errors were found duing the handshake, this function tries to |
2250 | continue and complete the handshake. If errors were ignored, the function switches |
2251 | this object's state to QDtls::HandshakeState::HandshakeComplete and returns \c true. |
2252 | |
2253 | \sa abortHandshake() |
2254 | */ |
2255 | |
2256 | /*! |
2257 | \fn void DtlsCryptograph::abortHandshake(QUdpSocket *socket) |
2258 | \internal |
2259 | |
2260 | Aborts the handshake if it's in progress or in the state QDtls::HandshakeState::PeerVerificationFailed. |
2261 | The use of \a socket is implementation-specific (for example, this DtlsCryptograph may send |
2262 | ShutdownAlert message). |
2263 | |
2264 | \sa resumeHandshake() |
2265 | */ |
2266 | |
2267 | /*! |
2268 | \fn void DtlsCryptograph::sendShutdownAlert(QUdpSocket *socket) |
2269 | \internal |
2270 | |
2271 | If the underlying TLS library provides the required functionality, this function |
2272 | may sent ShutdownAlert message using \a socket. |
2273 | */ |
2274 | |
2275 | /*! |
2276 | \fn QList<QSslError> DtlsCryptograph::peerVerificationErrors() const |
2277 | \internal |
2278 | |
2279 | Returns the list of errors that this object encountered during DTLS handshake |
2280 | and certificate validation. |
2281 | |
2282 | \sa ignoreVerificationErrors() |
2283 | */ |
2284 | |
2285 | /*! |
2286 | \fn void DtlsCryptograph::ignoreVerificationErrors(const QList<QSslError> &errorsToIgnore) |
2287 | \internal |
2288 | |
2289 | Tells this object to ignore errors from \a errorsToIgnore when they are found during |
2290 | DTLS handshake. |
2291 | |
2292 | \sa peerVerificationErrors() |
2293 | */ |
2294 | |
2295 | /*! |
2296 | \fn QSslCipher DtlsCryptograph::dtlsSessionCipher() const |
2297 | \internal |
2298 | |
2299 | If such information is available, returns the ciphersuite, negotiated during |
2300 | the handshake. |
2301 | |
2302 | \sa continueHandshake(), dtlsSessionProtocol() |
2303 | */ |
2304 | |
2305 | /*! |
2306 | \fn QSsl::SslProtocol DtlsCryptograph::dtlsSessionProtocol() const |
2307 | \internal |
2308 | |
2309 | Returns the version of the session protocol that was negotiated during the handshake or |
2310 | QSsl::UnknownProtocol if the handshake is incomplete or no information about the session |
2311 | protocol is available. |
2312 | |
2313 | \sa continueHandshake(), dtlsSessionCipher() |
2314 | */ |
2315 | |
2316 | /*! |
2317 | \fn qint64 DtlsCryptograph::writeDatagramEncrypted(QUdpSocket *socket, const QByteArray &dgram) |
2318 | \internal |
2319 | |
2320 | If this DtlsCryptograph is in the QDtls::HandshakeState::HandshakeComplete state, this function |
2321 | encrypts \a dgram and writes this encrypted data into \a socket. |
2322 | |
2323 | Returns the number of bytes (of \a dgram) written, or -1 in case of error. This function should |
2324 | set the error code and description if some error was encountered. |
2325 | |
2326 | \sa decryptDatagram() |
2327 | */ |
2328 | |
2329 | /*! |
2330 | \fn QByteArray DtlsCryptograph::decryptDatagram(QUdpSocket *socket, const QByteArray &dgram) |
2331 | \internal |
2332 | |
2333 | If this DtlsCryptograph is in the QDtls::HandshakeState::HandshakeComplete state, decrypts \a dgram. |
2334 | The use of \a socket is implementation-specific. This function should return an empty byte array |
2335 | and set the error code and description if some error was encountered. |
2336 | */ |
2337 | |
2338 | #endif // QT_CONFIG(dtls) |
2339 | #endif // QT_CONFIG(ssl) |
2340 | |
2341 | } // namespace QTlsPrivate |
2342 | |
2343 | #if QT_CONFIG(ssl) |
2344 | /*! |
2345 | \internal |
2346 | */ |
2347 | Q_NETWORK_EXPORT void qt_ForceTlsSecurityLevel() |
2348 | { |
2349 | if (auto *backend = QSslSocketPrivate::tlsBackendInUse()) |
2350 | backend->forceAutotestSecurityLevel(); |
2351 | } |
2352 | |
2353 | #endif // QT_CONFIG(ssl) |
2354 | |
2355 | QT_END_NAMESPACE |
2356 | |
2357 | #include "moc_qtlsbackend_p.cpp" |
2358 |
Definitions
- qtlsbLoader
- BackendCollection
- addBackend
- removeBackend
- tryPopulateCollection
- backendNames
- backend
- backends
- builtinBackendNames
- QTlsBackend
- ~QTlsBackend
- isValid
- tlsLibraryVersionNumber
- tlsLibraryVersionString
- tlsLibraryBuildVersionNumber
- tlsLibraryBuildVersionString
- ensureInitialized
- createKey
- createCertificate
- systemCaCertificates
- createTlsCryptograph
- createDtlsCryptograph
- createDtlsCookieVerifier
- X509Verifier
- X509PemReader
- X509DerReader
- X509Pkcs12Reader
- ellipticCurvesIds
- curveIdFromShortName
- curveIdFromLongName
- shortNameForId
- longNameForId
- isTlsNamedCurve
- dhParametersFromDer
- dhParametersFromPem
- availableBackendNames
- defaultBackendName
- findBackend
- activeOrAnyBackend
- supportedProtocols
- supportedFeatures
- implementedClasses
- resetBackend
- setupClientPskAuth
- setupServerPskAuth
- createCiphersuite
- createCiphersuite
- createCiphersuite
- defaultCiphers
- defaultDtlsCiphers
- setDefaultCiphers
- setDefaultDtlsCiphers
- setDefaultSupportedCiphers
- resetDefaultEllipticCurves
- setDefaultCaCertificates
- rootLoadingOnDemandAllowed
- storePeerCertificate
- storePeerCertificateChain
- clearPeerCertificates
- clearPeerCertificates
- setPeerSessionShared
- setSessionAsn1
- setSessionLifetimeHint
- setAlpnStatus
- setNegotiatedProtocol
- storePeerCertificate
- storePeerCertificateChain
- addTustedRoot
- setEphemeralKey
- forceAutotestSecurityLevel
- ~TlsKey
- pemHeader
- pemFooter
- ~X509Certificate
- publicKey
- ~TlsCryptograph
- checkSettingSslContext
- sslContext
- enableHandshakeContinuation
- cancelCAFetch
- hasUndecryptedData
- ocsps
- isMatchingHostname
- setErrorAndEmit
- ~DtlsBase
Start learning QML with our Intro Training
Find out more