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 (which is an implementation-specific |
893 | string), \a protocol and \a protocolString, e.g.: |
894 | \code |
895 | createCipher(QStringLiteral("schannel"), QSsl::TlsV1_2, "TLSv1.2"_L1); |
896 | \endcode |
897 | */ |
898 | QSslCipher QTlsBackend::createCipher(const QString &name, QSsl::SslProtocol protocol, |
899 | const QString &protocolString) |
900 | { |
901 | // Note the name 'createCipher' (not 'ciphersuite'): we don't provide |
902 | // information about Kx, Au, bits/supported etc. |
903 | QSslCipher cipher; |
904 | cipher.d->isNull = false; |
905 | cipher.d->name = name; |
906 | cipher.d->protocol = protocol; |
907 | cipher.d->protocolString = protocolString; |
908 | return cipher; |
909 | } |
910 | |
911 | /*! |
912 | \internal |
913 | Returns an implementation-specific list of ciphersuites that can be used by QSslSocket. |
914 | |
915 | \sa QSslConfiguration::defaultCiphers() |
916 | */ |
917 | QList<QSslCipher> QTlsBackend::defaultCiphers() |
918 | { |
919 | return QSslSocketPrivate::defaultCiphers(); |
920 | } |
921 | |
922 | /*! |
923 | \internal |
924 | Returns an implementation-specific list of ciphersuites that can be used by QDtls. |
925 | */ |
926 | QList<QSslCipher> QTlsBackend::defaultDtlsCiphers() |
927 | { |
928 | return QSslSocketPrivate::defaultDtlsCiphers(); |
929 | } |
930 | |
931 | /*! |
932 | \internal |
933 | Sets \a ciphers as defaults ciphers that QSslSocket can use. |
934 | |
935 | \sa defaultCiphers() |
936 | */ |
937 | void QTlsBackend::setDefaultCiphers(const QList<QSslCipher> &ciphers) |
938 | { |
939 | QSslSocketPrivate::setDefaultCiphers(ciphers); |
940 | } |
941 | |
942 | /*! |
943 | \internal |
944 | Sets \a ciphers as defaults ciphers that QDtls can use. |
945 | |
946 | \sa defaultDtlsCiphers() |
947 | */ |
948 | void QTlsBackend::setDefaultDtlsCiphers(const QList<QSslCipher> &ciphers) |
949 | { |
950 | QSslSocketPrivate::setDefaultDtlsCiphers(ciphers); |
951 | } |
952 | |
953 | /*! |
954 | \internal |
955 | Sets \a ciphers as a list of supported ciphers. |
956 | |
957 | \sa QSslConfiguration::supportedCiphers() |
958 | */ |
959 | void QTlsBackend::setDefaultSupportedCiphers(const QList<QSslCipher> &ciphers) |
960 | { |
961 | QSslSocketPrivate::setDefaultSupportedCiphers(ciphers); |
962 | } |
963 | |
964 | /*! |
965 | \internal |
966 | Sets the list of QSslEllipticCurve objects, that QSslConfiguration::supportedEllipticCurves() |
967 | returns, to ones that are supported by this backend. |
968 | */ |
969 | void QTlsBackend::resetDefaultEllipticCurves() |
970 | { |
971 | QSslSocketPrivate::resetDefaultEllipticCurves(); |
972 | } |
973 | |
974 | /*! |
975 | Sets \a certs as a list of certificates, that QSslConfiguration::caCertificates() |
976 | reports. |
977 | |
978 | \sa QSslConfiguration::defaultConfiguration(), QSslConfiguration::caCertificates() |
979 | */ |
980 | void QTlsBackend::setDefaultCaCertificates(const QList<QSslCertificate> &certs) |
981 | { |
982 | QSslSocketPrivate::setDefaultCaCertificates(certs); |
983 | } |
984 | |
985 | /*! |
986 | \internal |
987 | Returns true if \a configuration allows loading root certificates on demand. |
988 | */ |
989 | bool QTlsBackend::rootLoadingOnDemandAllowed(const QSslConfiguration &configuration) |
990 | { |
991 | return configuration.d->allowRootCertOnDemandLoading; |
992 | } |
993 | |
994 | /*! |
995 | \internal |
996 | Stores \a peerCert in the \a configuration. |
997 | */ |
998 | void QTlsBackend::storePeerCertificate(QSslConfiguration &configuration, |
999 | const QSslCertificate &peerCert) |
1000 | { |
1001 | configuration.d->peerCertificate = peerCert; |
1002 | } |
1003 | |
1004 | /*! |
1005 | \internal |
1006 | Stores \a peerChain in the \a configuration. |
1007 | */ |
1008 | void QTlsBackend::storePeerCertificateChain(QSslConfiguration &configuration, |
1009 | const QList<QSslCertificate> &peerChain) |
1010 | { |
1011 | configuration.d->peerCertificateChain = peerChain; |
1012 | } |
1013 | |
1014 | /*! |
1015 | \internal |
1016 | Clears the peer certificate chain in \a configuration. |
1017 | */ |
1018 | void QTlsBackend::clearPeerCertificates(QSslConfiguration &configuration) |
1019 | { |
1020 | configuration.d->peerCertificate.clear(); |
1021 | configuration.d->peerCertificateChain.clear(); |
1022 | } |
1023 | |
1024 | /*! |
1025 | \internal |
1026 | Clears the peer certificate chain in \a d. |
1027 | */ |
1028 | void QTlsBackend::clearPeerCertificates(QSslSocketPrivate *d) |
1029 | { |
1030 | Q_ASSERT(d); |
1031 | d->configuration.peerCertificate.clear(); |
1032 | d->configuration.peerCertificateChain.clear(); |
1033 | } |
1034 | |
1035 | /*! |
1036 | \internal |
1037 | Updates the configuration in \a d with \a shared value. |
1038 | */ |
1039 | void QTlsBackend::setPeerSessionShared(QSslSocketPrivate *d, bool shared) |
1040 | { |
1041 | Q_ASSERT(d); |
1042 | d->configuration.peerSessionShared = shared; |
1043 | } |
1044 | |
1045 | /*! |
1046 | \internal |
1047 | Sets TLS session in \a d to \a asn1. |
1048 | */ |
1049 | void QTlsBackend::setSessionAsn1(QSslSocketPrivate *d, const QByteArray &asn1) |
1050 | { |
1051 | Q_ASSERT(d); |
1052 | d->configuration.sslSession = asn1; |
1053 | } |
1054 | |
1055 | /*! |
1056 | \internal |
1057 | Sets TLS session lifetime hint in \a d to \a hint. |
1058 | */ |
1059 | void QTlsBackend::setSessionLifetimeHint(QSslSocketPrivate *d, int hint) |
1060 | { |
1061 | Q_ASSERT(d); |
1062 | d->configuration.sslSessionTicketLifeTimeHint = hint; |
1063 | } |
1064 | |
1065 | /*! |
1066 | \internal |
1067 | Sets application layer protocol negotiation status in \a d to \a st. |
1068 | */ |
1069 | void QTlsBackend::setAlpnStatus(QSslSocketPrivate *d, AlpnNegotiationStatus st) |
1070 | { |
1071 | Q_ASSERT(d); |
1072 | d->configuration.nextProtocolNegotiationStatus = st; |
1073 | } |
1074 | |
1075 | /*! |
1076 | \internal |
1077 | Sets \a protocol in \a d as a negotiated application layer protocol. |
1078 | */ |
1079 | void QTlsBackend::setNegotiatedProtocol(QSslSocketPrivate *d, const QByteArray &protocol) |
1080 | { |
1081 | Q_ASSERT(d); |
1082 | d->configuration.nextNegotiatedProtocol = protocol; |
1083 | } |
1084 | |
1085 | /*! |
1086 | \internal |
1087 | Stores \a peerCert in the TLS configuration of \a d. |
1088 | */ |
1089 | void QTlsBackend::storePeerCertificate(QSslSocketPrivate *d, const QSslCertificate &peerCert) |
1090 | { |
1091 | Q_ASSERT(d); |
1092 | d->configuration.peerCertificate = peerCert; |
1093 | } |
1094 | |
1095 | /*! |
1096 | \internal |
1097 | |
1098 | Stores \a peerChain in the TLS configuration of \a d. |
1099 | |
1100 | \note This is a helper function that TlsCryptograph and DtlsCryptograph |
1101 | call during a handshake. |
1102 | */ |
1103 | void QTlsBackend::storePeerCertificateChain(QSslSocketPrivate *d, |
1104 | const QList<QSslCertificate> &peerChain) |
1105 | { |
1106 | Q_ASSERT(d); |
1107 | d->configuration.peerCertificateChain = peerChain; |
1108 | } |
1109 | |
1110 | /*! |
1111 | \internal |
1112 | |
1113 | Adds \a rootCert to the list of trusted root certificates in \a d. |
1114 | |
1115 | \note In Qt 6.1 it's only used on Windows, during so called 'CA fetch'. |
1116 | */ |
1117 | void QTlsBackend::addTustedRoot(QSslSocketPrivate *d, const QSslCertificate &rootCert) |
1118 | { |
1119 | Q_ASSERT(d); |
1120 | if (!d->configuration.caCertificates.contains(t: rootCert)) |
1121 | d->configuration.caCertificates += rootCert; |
1122 | } |
1123 | |
1124 | /*! |
1125 | \internal |
1126 | |
1127 | Saves ephemeral \a key in \a d. |
1128 | |
1129 | \sa QSslConfiguration::ephemeralKey() |
1130 | */ |
1131 | void QTlsBackend::setEphemeralKey(QSslSocketPrivate *d, const QSslKey &key) |
1132 | { |
1133 | Q_ASSERT(d); |
1134 | d->configuration.ephemeralServerKey = key; |
1135 | } |
1136 | |
1137 | /*! |
1138 | \internal |
1139 | |
1140 | Implementation-specific. Sets the security level suitable for Qt's |
1141 | auto-tests. |
1142 | */ |
1143 | void QTlsBackend::forceAutotestSecurityLevel() |
1144 | { |
1145 | } |
1146 | |
1147 | #endif // QT_CONFIG(ssl) |
1148 | |
1149 | namespace QTlsPrivate { |
1150 | |
1151 | /*! |
1152 | \internal (Network-private) |
1153 | \namespace QTlsPrivate |
1154 | \brief Namespace containing onternal types that TLS backends implement. |
1155 | |
1156 | This namespace is private to Qt and the backends that implement its TLS support. |
1157 | */ |
1158 | |
1159 | /*! |
1160 | \class TlsKey |
1161 | \internal (Network-private) |
1162 | \brief TlsKey is an abstract class, that allows a TLS plugin to provide |
1163 | an underlying implementation for the class QSslKey. |
1164 | |
1165 | Most functions in the class TlsKey are pure virtual and thus have to be |
1166 | reimplemented by a TLS backend that supports QSslKey. In many cases an |
1167 | empty implementation as an overrider is sufficient, albeit with some |
1168 | of QSslKey's functionality missing. |
1169 | |
1170 | \sa QTlsBackend::createKey(), QTlsBackend::implementedClasses(), QSslKey |
1171 | */ |
1172 | |
1173 | /*! |
1174 | \fn void TlsKey::decodeDer(KeyType type, KeyAlgorithm algorithm, const QByteArray &der, const QByteArray &passPhrase, bool deepClear) |
1175 | \internal |
1176 | |
1177 | If a support of public and private keys in DER format is required, this function |
1178 | must be overridden and should initialize this key using the \a type, \a algorithm, \a der |
1179 | and \a passPhrase. If this key was initialized previously, \a deepClear |
1180 | has an implementation-specific meaning (e.g., if an implementation is using |
1181 | reference-counting and can share internally some data structures, a value \c true may |
1182 | trigger decrementing a reference counter on some implementation-specific object). |
1183 | |
1184 | \note An empty overrider is sufficient, but then reading keys in QSsl::Der format |
1185 | will not be supported. |
1186 | |
1187 | \sa isNull(), QSsl::KeyType, QSsl::EncodingFormat, QSsl::KeyAlgorithm |
1188 | */ |
1189 | |
1190 | /*! |
1191 | \fn void TlsKey::decodePem(KeyType type, KeyAlgorithm algorithm, const QByteArray &pem, const QByteArray &passPhrase, bool deepClear) |
1192 | \internal |
1193 | |
1194 | If a support of public and private keys in PEM format is required, this function must |
1195 | be overridden and should initialize this key using the \a type, \a algorithm, \a pem and |
1196 | \a passPhrase. If this key was initialized previously, \a deepClear has an |
1197 | implementation-specific meaning (e.g., in an implementation using reference-counting, |
1198 | a value \c true may trigger decrementing a reference counter on some implementation-specific |
1199 | object). |
1200 | |
1201 | \note An empty overrider is sufficient, but then reading keys in QSsl::Pem format |
1202 | will not be supported. |
1203 | |
1204 | \sa isNull(), QSsl::KeyType, QSsl::EncodingFormat, QSsl::KeyAlgorithm |
1205 | */ |
1206 | |
1207 | /*! |
1208 | \fn QByteArray TlsKey::toPem(const QByteArray &passPhrase) const |
1209 | \internal |
1210 | |
1211 | This function must be overridden, if converting a key to PEM format, potentially with |
1212 | encryption, is needed (e.g. to save a QSslKey into a file). If this key is |
1213 | private and \a passPhrase is not empty, the key's data is expected to be encrypted using |
1214 | some conventional encryption algorithm (e.g. DES or AES - the one that different tools |
1215 | or even the class QSslKey can understand later). |
1216 | |
1217 | \note If this particular functionality is not needed, an overrider returning an |
1218 | empty QByteArray is sufficient. |
1219 | |
1220 | \sa QSslKey::toPem() |
1221 | */ |
1222 | |
1223 | /*! |
1224 | \fn QByteArray TlsKey::derFromPem(const QByteArray &pem, QMap<QByteArray, QByteArray> *headers) const |
1225 | \internal |
1226 | |
1227 | Converts \a pem to DER format, using this key's type and algorithm. The parameter \a headers |
1228 | must be a valid, non-null pointer. When parsing \a pem, the headers found there will be saved |
1229 | into \a headers. |
1230 | |
1231 | \note An overrider returning an empty QByteArray is sufficient, if QSslKey::toDer() is not |
1232 | needed. |
1233 | |
1234 | \note This function is very implementation-specific. A backend, that already has this key's |
1235 | non-empty DER data, may simply return this data. |
1236 | |
1237 | \sa QSslKey::toDer() |
1238 | */ |
1239 | |
1240 | /*! |
1241 | \fn QByteArray TlsKey::pemFromDer(const QByteArray &der, const QMap<QByteArray, QByteArray> &headers) const |
1242 | \internal |
1243 | |
1244 | If overridden, this function is expected to convert \a der, using \a headers, to PEM format. |
1245 | |
1246 | \note This function is very implementation-specific. As of now (Qt 6.1), it is only required by |
1247 | Qt's own non-OpenSSL backends, that internally use DER and implement QSslKey::toPem() |
1248 | via pemFromDer(). |
1249 | */ |
1250 | |
1251 | /*! |
1252 | \fn void TlsKey::fromHandle(Qt::HANDLE handle, KeyType type) |
1253 | \internal |
1254 | |
1255 | Initializes this key using the \a handle and \a type, taking the ownership |
1256 | of the \a handle. |
1257 | |
1258 | \note The meaning of the \a handle is implementation-specific. |
1259 | |
1260 | \note If a TLS backend does not support such keys, it must provide an |
1261 | empty implementation. |
1262 | |
1263 | \sa handle(), QSslKey::QSslKey(), QSslKet::handle() |
1264 | */ |
1265 | |
1266 | /*! |
1267 | \fn TlsKey::handle() const |
1268 | \internal |
1269 | |
1270 | If a TLS backend supports opaque keys, returns a native handle that |
1271 | this key was initialized with. |
1272 | |
1273 | \sa fromHandle(), QSslKey::handle() |
1274 | */ |
1275 | |
1276 | /*! |
1277 | \fn bool TlsKey::isNull() const |
1278 | \internal |
1279 | |
1280 | Returns \c true if this is a null key, \c false otherwise. |
1281 | |
1282 | \note A null key corresponds to the default-constructed |
1283 | QSslKey or the one, that was cleared via QSslKey::clear(). |
1284 | |
1285 | \sa QSslKey::isNull() |
1286 | */ |
1287 | |
1288 | /*! |
1289 | \fn QSsl::KeyType TlsKey::type() const |
1290 | \internal |
1291 | |
1292 | Returns the type of this key (public or private). |
1293 | */ |
1294 | |
1295 | /*! |
1296 | \fn QSsl::KeyAlgorithm TlsKey::algorithm() const |
1297 | \internal |
1298 | |
1299 | Return this key's algorithm. |
1300 | */ |
1301 | |
1302 | /*! |
1303 | \fn int TlsKey::length() const |
1304 | \internal |
1305 | |
1306 | Returns the length of the key in bits, or -1 if the key is null. |
1307 | */ |
1308 | |
1309 | /*! |
1310 | \fn void TlsKey::clear(bool deep) |
1311 | \internal |
1312 | |
1313 | Clears the contents of this key, making it a null key. The meaning |
1314 | of \a deep is implementation-specific (e.g. if some internal objects |
1315 | representing a key can be shared using reference counting, \a deep equal |
1316 | to \c true would imply decrementing a reference count). |
1317 | |
1318 | \sa isNull() |
1319 | */ |
1320 | |
1321 | /*! |
1322 | \fn bool TlsKey::isPkcs8() const |
1323 | \internal |
1324 | |
1325 | This function is internally used only by Qt's own TLS plugins and affects |
1326 | the way PEM file is generated by TlsKey. It's sufficient to override it |
1327 | and return \c false in case a new TLS backend is not using Qt's plugin |
1328 | as a base. |
1329 | */ |
1330 | |
1331 | /*! |
1332 | \fn QByteArray TlsKey::decrypt(Cipher cipher, const QByteArray &data, const QByteArray &passPhrase, const QByteArray &iv) const |
1333 | \internal |
1334 | |
1335 | This function allows to decrypt \a data (for example, a private key read from a file), using |
1336 | \a passPhrase, initialization vector \a iv. \a cipher is describing a block cipher and its |
1337 | mode (for example, AES256 + CBC). decrypt() is needed to implement QSslKey's constructor. |
1338 | |
1339 | \note A TLS backend may provide an empty implementation, but as a result QSslKey will not be able |
1340 | to work with private encrypted keys. |
1341 | |
1342 | \sa QSslKey |
1343 | */ |
1344 | |
1345 | /*! |
1346 | \fn QByteArray TlsKey::encrypt(Cipher cipher, const QByteArray &data, const QByteArray &passPhrase, const QByteArray &iv) const |
1347 | \internal |
1348 | |
1349 | This function is needed to implement QSslKey::toPem() with encryption (for a private |
1350 | key). \a cipher names a block cipher to use to encrypt \a data, using |
1351 | \a passPhrase and initialization vector \a iv. |
1352 | |
1353 | \note An empty implementation is sufficient, but QSslKey::toPem() will fail for |
1354 | a private key and non-empty passphrase. |
1355 | |
1356 | \sa QSslKey |
1357 | */ |
1358 | |
1359 | /*! |
1360 | \internal |
1361 | |
1362 | Destroys this key. |
1363 | */ |
1364 | TlsKey::~TlsKey() = default; |
1365 | |
1366 | /*! |
1367 | \internal |
1368 | |
1369 | A convenience function that returns a string, corresponding to the |
1370 | key type or algorithm, which can be used as a header in a PEM file. |
1371 | */ |
1372 | QByteArray TlsKey::() const |
1373 | { |
1374 | if (type() == QSsl::PublicKey) |
1375 | return QByteArrayLiteral("-----BEGIN PUBLIC KEY-----" ); |
1376 | else if (algorithm() == QSsl::Rsa) |
1377 | return QByteArrayLiteral("-----BEGIN RSA PRIVATE KEY-----" ); |
1378 | else if (algorithm() == QSsl::Dsa) |
1379 | return QByteArrayLiteral("-----BEGIN DSA PRIVATE KEY-----" ); |
1380 | else if (algorithm() == QSsl::Ec) |
1381 | return QByteArrayLiteral("-----BEGIN EC PRIVATE KEY-----" ); |
1382 | else if (algorithm() == QSsl::Dh) |
1383 | return QByteArrayLiteral("-----BEGIN PRIVATE KEY-----" ); |
1384 | |
1385 | Q_UNREACHABLE_RETURN({}); |
1386 | } |
1387 | |
1388 | /*! |
1389 | \internal |
1390 | A convenience function that returns a string, corresponding to the |
1391 | key type or algorithm, which can be used as a footer in a PEM file. |
1392 | */ |
1393 | QByteArray TlsKey::() const |
1394 | { |
1395 | if (type() == QSsl::PublicKey) |
1396 | return QByteArrayLiteral("-----END PUBLIC KEY-----" ); |
1397 | else if (algorithm() == QSsl::Rsa) |
1398 | return QByteArrayLiteral("-----END RSA PRIVATE KEY-----" ); |
1399 | else if (algorithm() == QSsl::Dsa) |
1400 | return QByteArrayLiteral("-----END DSA PRIVATE KEY-----" ); |
1401 | else if (algorithm() == QSsl::Ec) |
1402 | return QByteArrayLiteral("-----END EC PRIVATE KEY-----" ); |
1403 | else if (algorithm() == QSsl::Dh) |
1404 | return QByteArrayLiteral("-----END PRIVATE KEY-----" ); |
1405 | |
1406 | Q_UNREACHABLE_RETURN({}); |
1407 | } |
1408 | |
1409 | /*! |
1410 | \class X509Certificate |
1411 | \internal (Network-private) |
1412 | \brief X509Certificate is an abstract class that allows a TLS backend to |
1413 | provide an implementation of the QSslCertificate class. |
1414 | |
1415 | This class provides an interface that must be reimplemented by a TLS plugin, |
1416 | that supports QSslCertificate. Most functions are pure virtual, and thus |
1417 | have to be overridden. For some of them, an empty overrider is acceptable, |
1418 | though a part of functionality in QSslCertificate will be missing. |
1419 | |
1420 | \sa QTlsBackend::createCertificate(), QTlsBackend::X509PemReader(), QTlsBackend::X509DerReader() |
1421 | */ |
1422 | |
1423 | /*! |
1424 | \fn bool X509Certificate::isEqual(const X509Certificate &other) const |
1425 | \internal |
1426 | |
1427 | This function is expected to return \c true if this certificate is the same as |
1428 | the \a other, \c false otherwise. Used by QSslCertificate's comparison operators. |
1429 | */ |
1430 | |
1431 | /*! |
1432 | \fn bool X509Certificate::isNull() const |
1433 | \internal |
1434 | |
1435 | Returns true if this certificate was default-constructed and not initialized yet. |
1436 | This function is called by QSslCertificate::isNull(). |
1437 | |
1438 | \sa QSslCertificate::isNull() |
1439 | */ |
1440 | |
1441 | /*! |
1442 | \fn bool X509Certificate::isSelfSigned() const |
1443 | \internal |
1444 | |
1445 | This function is needed to implement QSslCertificate::isSelfSigned() |
1446 | |
1447 | \sa QSslCertificate::isSelfSigned() |
1448 | */ |
1449 | |
1450 | /*! |
1451 | \fn QByteArray X509Certificate::version() const |
1452 | \internal |
1453 | |
1454 | Implements QSslCertificate::version(). |
1455 | |
1456 | \sa QSslCertificate::version() |
1457 | */ |
1458 | |
1459 | /*! |
1460 | \fn QByteArray X509Certificate::serialNumber() const |
1461 | \internal |
1462 | |
1463 | This function is expected to return the certificate's serial number string in |
1464 | hexadecimal format. |
1465 | |
1466 | \sa QSslCertificate::serialNumber() |
1467 | */ |
1468 | |
1469 | /*! |
1470 | \fn QStringList X509Certificate::issuerInfo(QSslCertificate::SubjectInfo subject) const |
1471 | \internal |
1472 | |
1473 | This function is expected to return the issuer information for the \a subject |
1474 | from the certificate, or an empty list if there is no information for subject |
1475 | in the certificate. There can be more than one entry of each type. |
1476 | |
1477 | \sa QSslCertificate::issuerInfo(). |
1478 | */ |
1479 | |
1480 | /*! |
1481 | \fn QStringList X509Certificate::issuerInfo(const QByteArray &attribute) const |
1482 | \internal |
1483 | |
1484 | This function is expected to return the issuer information for attribute from |
1485 | the certificate, or an empty list if there is no information for \a attribute |
1486 | in the certificate. There can be more than one entry for an attribute. |
1487 | |
1488 | \sa QSslCertificate::issuerInfo(). |
1489 | */ |
1490 | |
1491 | /*! |
1492 | \fn QStringList X509Certificate::subjectInfo(QSslCertificate::SubjectInfo subject) const |
1493 | \internal |
1494 | |
1495 | This function is expected to return the information for the \a subject, or an empty list |
1496 | if there is no information for subject in the certificate. There can be more than one |
1497 | entry of each type. |
1498 | |
1499 | \sa QSslCertificate::subjectInfo(). |
1500 | */ |
1501 | |
1502 | /*! |
1503 | \fn QStringList X509Certificate::subjectInfo(const QByteArray &attribute) const |
1504 | \internal |
1505 | |
1506 | This function is expected to return the subject information for \a attribute, or |
1507 | an empty list if there is no information for attribute in the certificate. |
1508 | There can be more than one entry for an attribute. |
1509 | |
1510 | \sa QSslCertificate::subjectInfo(). |
1511 | */ |
1512 | |
1513 | /*! |
1514 | \fn QList<QByteArray> X509Certificate::subjectInfoAttributes() const |
1515 | \internal |
1516 | |
1517 | This function is expected to return a list of the attributes that have values |
1518 | in the subject information of this certificate. The information associated |
1519 | with a given attribute can be accessed using the subjectInfo() method. Note |
1520 | that this list may include the OIDs for any elements that are not known by |
1521 | the TLS backend. |
1522 | |
1523 | \note This function is needed for QSslCertificate:::subjectInfoAttributes(). |
1524 | |
1525 | \sa subjectInfo() |
1526 | */ |
1527 | |
1528 | /*! |
1529 | \fn QList<QByteArray> X509Certificate::issuerInfoAttributes() const |
1530 | \internal |
1531 | |
1532 | This function is expected to return a list of the attributes that have |
1533 | values in the issuer information of this certificate. The information |
1534 | associated with a given attribute can be accessed using the issuerInfo() |
1535 | method. Note that this list may include the OIDs for any |
1536 | elements that are not known by the TLS backend. |
1537 | |
1538 | \note This function implements QSslCertificate::issuerInfoAttributes(). |
1539 | |
1540 | \sa issuerInfo() |
1541 | */ |
1542 | |
1543 | /*! |
1544 | \fn QMultiMap<QSsl::AlternativeNameEntryType, QString> X509Certificate::subjectAlternativeNames() const |
1545 | \internal |
1546 | |
1547 | This function is expected to return the list of alternative subject names for |
1548 | this certificate. The alternative names typically contain host names, optionally |
1549 | with wildcards, that are valid for this certificate. |
1550 | |
1551 | \sa subjectInfo() |
1552 | */ |
1553 | |
1554 | /*! |
1555 | \fn QDateTime X509Certificate::effectiveDate() const |
1556 | \internal |
1557 | |
1558 | This function is expected to return the date-time that the certificate |
1559 | becomes valid, or an empty QDateTime if this is a null certificate. |
1560 | |
1561 | \sa expiryDate() |
1562 | */ |
1563 | |
1564 | /*! |
1565 | \fn QDateTime X509Certificate::expiryDate() const |
1566 | \internal |
1567 | |
1568 | This function is expected to return the date-time that the certificate expires, |
1569 | or an empty QDateTime if this is a null certificate. |
1570 | |
1571 | \sa effectiveDate() |
1572 | */ |
1573 | |
1574 | /*! |
1575 | \fn qsizetype X509Certificate::numberOfExtensions() const |
1576 | \internal |
1577 | |
1578 | This function is expected to return the number of X509 extensions of |
1579 | this certificate. |
1580 | */ |
1581 | |
1582 | /*! |
1583 | \fn QString X509Certificate::oidForExtension(qsizetype i) const |
1584 | \internal |
1585 | |
1586 | This function is expected to return the ASN.1 OID for the extension |
1587 | with index \a i. |
1588 | |
1589 | \sa numberOfExtensions() |
1590 | */ |
1591 | |
1592 | /*! |
1593 | \fn QString X509Certificate::nameForExtension(qsizetype i) const |
1594 | \internal |
1595 | |
1596 | This function is expected to return the name for the extension |
1597 | with index \a i. If no name is known for the extension then the |
1598 | OID will be returned. |
1599 | |
1600 | \sa numberOfExtensions(), oidForExtension() |
1601 | */ |
1602 | |
1603 | /*! |
1604 | \fn QVariant X509Certificate::valueForExtension(qsizetype i) const |
1605 | \internal |
1606 | |
1607 | This function is expected to return the value of the extension |
1608 | with index \a i. The structure of the value returned depends on |
1609 | the extension type |
1610 | |
1611 | \sa numberOfExtensions() |
1612 | */ |
1613 | |
1614 | /*! |
1615 | \fn bool X509Certificate::isExtensionCritical(qsizetype i) const |
1616 | \internal |
1617 | |
1618 | This function is expected to return the criticality of the extension |
1619 | with index \a i. |
1620 | |
1621 | \sa numberOfExtensions() |
1622 | */ |
1623 | |
1624 | /*! |
1625 | \fn bool X509Certificate::isExtensionSupported(qsizetype i) const |
1626 | \internal |
1627 | |
1628 | This function is expected to return \c true if this extension is supported. |
1629 | In this case, supported simply means that the structure of the QVariant returned |
1630 | by the valueForExtension() accessor will remain unchanged between versions. |
1631 | |
1632 | \sa numberOfExtensions() |
1633 | */ |
1634 | |
1635 | /*! |
1636 | \fn QByteArray X509Certificate::toPem() const |
1637 | \internal |
1638 | |
1639 | This function is expected to return this certificate converted to a PEM (Base64) |
1640 | encoded representation. |
1641 | */ |
1642 | |
1643 | /*! |
1644 | \fn QByteArray X509Certificate::toDer() const |
1645 | \internal |
1646 | |
1647 | This function is expected to return this certificate converted to a DER (binary) |
1648 | encoded representation. |
1649 | */ |
1650 | |
1651 | /*! |
1652 | \fn QString X509Certificate::toText() const |
1653 | \internal |
1654 | |
1655 | This function is expected to return this certificate converted to a human-readable |
1656 | text representation. |
1657 | */ |
1658 | |
1659 | /*! |
1660 | \fn Qt::HANDLE X509Certificate::handle() const |
1661 | \internal |
1662 | |
1663 | This function is expected to return a pointer to the native certificate handle, |
1664 | if there is one, else nullptr. |
1665 | */ |
1666 | |
1667 | /*! |
1668 | \fn size_t X509Certificate::hash(size_t seed) const |
1669 | \internal |
1670 | |
1671 | This function is expected to return the hash value for this certificate, |
1672 | using \a seed to seed the calculation. |
1673 | */ |
1674 | |
1675 | /*! |
1676 | \internal |
1677 | |
1678 | Destroys this certificate. |
1679 | */ |
1680 | X509Certificate::~X509Certificate() = default; |
1681 | |
1682 | /*! |
1683 | \internal |
1684 | |
1685 | Returns the certificate subject's public key. |
1686 | */ |
1687 | TlsKey *X509Certificate::publicKey() const |
1688 | { |
1689 | return nullptr; |
1690 | } |
1691 | |
1692 | #if QT_CONFIG(ssl) |
1693 | |
1694 | /*! |
1695 | \class TlsCryptograph |
1696 | \internal (Network-private) |
1697 | \brief TlsCryptograph is an abstract class, that allows a TLS plugin to implement QSslSocket. |
1698 | |
1699 | This abstract base class provides an interface that must be reimplemented by a TLS plugin, |
1700 | that supports QSslSocket. A class, implementing TlsCryptograph's interface, is responsible |
1701 | for TLS handshake, reading and writing encryped application data; it is expected |
1702 | to work with QSslSocket and it's private implementation - QSslSocketPrivate. |
1703 | QSslSocketPrivate provides access to its read/write buffers, QTcpSocket it |
1704 | internally uses for connecting, reading and writing. QSslSocketPrivate |
1705 | can also be used for reporting errors and storing the certificates received |
1706 | during the handshake phase. |
1707 | |
1708 | \note Most of the functions in this class are pure virtual and have no actual implementation |
1709 | in the QtNetwork module. This documentation is mostly conceptual and only describes what those |
1710 | functions are expected to do, but not how they must be implemented. |
1711 | |
1712 | \sa QTlsBackend::createTlsCryptograph() |
1713 | */ |
1714 | |
1715 | /*! |
1716 | \fn void TlsCryptograph::init(QSslSocket *q, QSslSocketPrivate *d) |
1717 | \internal |
1718 | |
1719 | When initializing this TlsCryptograph, QSslSocket will pass a pointer to self and |
1720 | its d-object using this function. |
1721 | */ |
1722 | |
1723 | /*! |
1724 | \fn QList<QSslError> TlsCryptograph::tlsErrors() const |
1725 | \internal |
1726 | |
1727 | Returns a list of QSslError, describing errors encountered during |
1728 | the TLS handshake. |
1729 | |
1730 | \sa QSslSocket::sslHandshakeErrors() |
1731 | */ |
1732 | |
1733 | /*! |
1734 | \fn void TlsCryptograph::startClientEncryption() |
1735 | \internal |
1736 | |
1737 | A client-side QSslSocket calls this function after its internal TCP socket |
1738 | establishes a connection with a remote host, or from QSslSocket::startClientEncryption(). |
1739 | This TlsCryptograph is expected to initialize some implementation-specific TLS context, |
1740 | if needed, and then start the client side of the TLS handshake (for example, by calling |
1741 | transmit()), using TCP socket from QSslSocketPrivate. |
1742 | |
1743 | \sa init(), transmit(), QSslSocket::startClientEncryption(), QSslSocket::connectToHostEncrypted() |
1744 | */ |
1745 | |
1746 | /*! |
1747 | \fn void TlsCryptograph::startServerEncryption() |
1748 | \internal |
1749 | |
1750 | This function is called by QSslSocket::startServerEncryption(). The TlsCryptograph |
1751 | is expected to initialize some implementation-specific TLS context, if needed, |
1752 | and then try to read the ClientHello message and continue the TLS handshake |
1753 | (for example, by calling transmit()). |
1754 | |
1755 | \sa transmit(), QSslSocket::startServerEncryption() |
1756 | */ |
1757 | |
1758 | /*! |
1759 | \fn void TlsCryptograph::continueHandshake() |
1760 | \internal |
1761 | |
1762 | QSslSocket::resume() calls this function if its pause mode is QAbstractSocket::PauseOnSslErrors, |
1763 | and errors, found during the handshake, were ignored. If implemented, this function is expected |
1764 | to emit QSslSocket::encrypted(). |
1765 | |
1766 | \sa QAbstractSocket::pauseMode(), QSslSocket::sslHandshakeErrors(), QSslSocket::ignoreSslErrors(), QSslSocket::resume() |
1767 | */ |
1768 | |
1769 | /*! |
1770 | \fn void TlsCryptograph::disconnectFromHost() |
1771 | \internal |
1772 | |
1773 | This function is expected to call disconnectFromHost() on the TCP socket |
1774 | that can be obtained from QSslSocketPrivate. Any additional actions |
1775 | are implementation-specific (e.g., sending shutdown alert message). |
1776 | |
1777 | */ |
1778 | |
1779 | /*! |
1780 | \fn void TlsCryptograph::disconnected() |
1781 | \internal |
1782 | |
1783 | This function is called when the remote has disconnected. If there |
1784 | is data left to be read you may ignore the maxReadBufferSize restriction |
1785 | and read it all now. |
1786 | */ |
1787 | |
1788 | /*! |
1789 | \fn QSslCipher TlsCryptograph::sessionCipher() const |
1790 | \internal |
1791 | |
1792 | This function returns a QSslCipher object describing the ciphersuite negotiated |
1793 | during the handshake. |
1794 | */ |
1795 | |
1796 | /*! |
1797 | \fn QSsl::SslProtocol TlsCryptograph::sessionProtocol() const |
1798 | \internal |
1799 | |
1800 | This function returns the version of TLS (or DTLS) protocol negotiated during the handshake. |
1801 | */ |
1802 | |
1803 | /*! |
1804 | \fn void TlsCryptograph::transmit() |
1805 | \internal |
1806 | |
1807 | This function is responsible for reading and writing data. The meaning of these I/O |
1808 | operations depends on an implementation-specific TLS state machine. These read and write |
1809 | operations can be reading and writing parts of a TLS handshake (e.g. by calling handshake-specific |
1810 | functions), or reading and writing application data (if encrypted connection was already |
1811 | established). transmit() is expected to use the QSslSocket's TCP socket (accessible via |
1812 | QSslSocketPrivate) to read the incoming data and write the outgoing data. When in encrypted |
1813 | state, transmit() is also using QSslSocket's internal read and write buffers: the read buffer |
1814 | to fill with decrypted incoming data; the write buffer - for the data to encrypt and send. |
1815 | This TlsCryptograph can also use QSslSocketPrivate to check which TLS errors were ignored during |
1816 | the handshake. |
1817 | |
1818 | \note This function is responsible for emitting QSslSocket's signals, that occur during the |
1819 | handshake (e.g. QSslSocket::sslErrors() or QSslSocket::encrypted()), and also read/write signals, |
1820 | e.g. QSslSocket::bytesWritten() and QSslSocket::readyRead(). |
1821 | |
1822 | \sa init() |
1823 | */ |
1824 | |
1825 | /*! |
1826 | \internal |
1827 | |
1828 | Destroys this object. |
1829 | */ |
1830 | TlsCryptograph::~TlsCryptograph() = default; |
1831 | |
1832 | /*! |
1833 | \internal |
1834 | |
1835 | This function allows to share QSslContext between several QSslSocket objects. |
1836 | The default implementation does nothing. |
1837 | |
1838 | \note The definition of the class QSslContext is implementation-specific. |
1839 | |
1840 | \sa sslContext() |
1841 | */ |
1842 | void TlsCryptograph::checkSettingSslContext(std::shared_ptr<QSslContext> tlsContext) |
1843 | { |
1844 | Q_UNUSED(tlsContext); |
1845 | } |
1846 | |
1847 | /*! |
1848 | \internal |
1849 | |
1850 | Returns the context previously set by checkSettingSslContext() or \nullptr, |
1851 | if no context was set. The default implementation returns \nullptr. |
1852 | |
1853 | \sa checkSettingSslContext() |
1854 | */ |
1855 | std::shared_ptr<QSslContext> TlsCryptograph::sslContext() const |
1856 | { |
1857 | return {}; |
1858 | } |
1859 | |
1860 | /*! |
1861 | \internal |
1862 | |
1863 | If this TLS backend supports reporting errors before handshake is finished, |
1864 | e.g. from a verification callback function, enableHandshakeContinuation() |
1865 | allows this object to continue handshake. The default implementation does |
1866 | nothing. |
1867 | |
1868 | \sa QSslSocket::handshakeInterruptedOnError(), QSslConfiguration::setHandshakeMustInterruptOnError() |
1869 | */ |
1870 | void TlsCryptograph::enableHandshakeContinuation() |
1871 | { |
1872 | } |
1873 | |
1874 | /*! |
1875 | \internal |
1876 | |
1877 | Windows and OpenSSL-specific, only used internally by Qt's OpenSSL TLS backend. |
1878 | |
1879 | \note The default empty implementation is sufficient. |
1880 | */ |
1881 | void TlsCryptograph::cancelCAFetch() |
1882 | { |
1883 | } |
1884 | |
1885 | /*! |
1886 | \internal |
1887 | |
1888 | Windows and Schannel-specific, only used by Qt's Schannel TLS backend, in |
1889 | general, if a backend has its own buffer where it stores undecrypted data |
1890 | then it must report true if it contains any data through this function. |
1891 | |
1892 | \note The default empty implementation, returning \c false is sufficient. |
1893 | */ |
1894 | bool TlsCryptograph::hasUndecryptedData() const |
1895 | { |
1896 | return false; |
1897 | } |
1898 | |
1899 | /*! |
1900 | \internal |
1901 | |
1902 | Returns the list of OCSP (Online Certificate Status Protocol) responses, |
1903 | received during the handshake. The default implementation returns an empty |
1904 | list. |
1905 | */ |
1906 | QList<QOcspResponse> TlsCryptograph::ocsps() const |
1907 | { |
1908 | return {}; |
1909 | } |
1910 | |
1911 | /*! |
1912 | \internal |
1913 | |
1914 | A helper function that can be used during a handshake. Returns \c true if the \a peerName |
1915 | matches one of subject alternative names or common names found in the \a certificate. |
1916 | */ |
1917 | bool TlsCryptograph::isMatchingHostname(const QSslCertificate &certificate, const QString &peerName) |
1918 | { |
1919 | return QSslSocketPrivate::isMatchingHostname(cert: certificate, peerName); |
1920 | } |
1921 | |
1922 | /*! |
1923 | \internal |
1924 | Calls QAbstractSocketPrivate::setErrorAndEmit() for \a d, passing \a errorCode and |
1925 | \a errorDescription as parameters. |
1926 | */ |
1927 | void TlsCryptograph::setErrorAndEmit(QSslSocketPrivate *d, QAbstractSocket::SocketError errorCode, |
1928 | const QString &errorDescription) const |
1929 | { |
1930 | Q_ASSERT(d); |
1931 | d->setErrorAndEmit(errorCode, errorString: errorDescription); |
1932 | } |
1933 | |
1934 | #if QT_CONFIG(dtls) |
1935 | /*! |
1936 | \class DtlsBase |
1937 | \internal (Network-private) |
1938 | \brief DtlsBase is a base class for the classes DtlsCryptograph and DtlsCookieVerifier. |
1939 | |
1940 | DtlsBase is the base class for the classes DtlsCryptograph and DtlsCookieVerifier. It's |
1941 | an abstract class, an interface that these before-mentioned classes share. It allows to |
1942 | set, get and clear the last error that occurred, set and get cookie generation parameters, |
1943 | set and get QSslConfiguration. |
1944 | |
1945 | \note This class is not supposed to be inherited directly, it's only needed by DtlsCryptograph |
1946 | and DtlsCookieVerifier. |
1947 | |
1948 | \sa QDtls, QDtlsClientVerifier, DtlsCryptograph, DtlsCookieVerifier |
1949 | */ |
1950 | |
1951 | /*! |
1952 | \fn void DtlsBase::setDtlsError(QDtlsError code, const QString &description) |
1953 | \internal |
1954 | |
1955 | Sets the last error to \a code and its textual description to \a description. |
1956 | |
1957 | \sa QDtlsError, error(), errorString() |
1958 | */ |
1959 | |
1960 | /*! |
1961 | \fn QDtlsError DtlsBase::error() const |
1962 | \internal |
1963 | |
1964 | This function, when overridden, is expected to return the code for the last error that occurred. |
1965 | If no error occurred it should return QDtlsError::NoError. |
1966 | |
1967 | \sa QDtlsError, errorString(), setDtlsError() |
1968 | */ |
1969 | |
1970 | /*! |
1971 | \fn QDtlsError DtlsBase::errorString() const |
1972 | \internal |
1973 | |
1974 | This function, when overridden, is expected to return the textual description for the last error |
1975 | that occurred or an empty string if no error occurred. |
1976 | |
1977 | \sa QDtlsError, error(), setDtlsError() |
1978 | */ |
1979 | |
1980 | /*! |
1981 | \fn void DtlsBase::clearDtlsError() |
1982 | \internal |
1983 | |
1984 | This function is expected to set the error code for the last error to QDtlsError::NoError and |
1985 | its textual description to an empty string. |
1986 | |
1987 | \sa QDtlsError, setDtlsError(), error(), errorString() |
1988 | */ |
1989 | |
1990 | /*! |
1991 | \fn void DtlsBase::setConfiguration(const QSslConfiguration &configuration) |
1992 | \internal |
1993 | |
1994 | Sets a TLS configuration that an object of a class inheriting from DtlsCookieVerifier or |
1995 | DtlsCryptograph will use, to \a configuration. |
1996 | |
1997 | \sa configuration() |
1998 | */ |
1999 | |
2000 | /*! |
2001 | \fn QSslConfiguration DtlsBase::configuration() const |
2002 | \internal |
2003 | |
2004 | Returns TLS configuration this object is using (either set by setConfiguration() |
2005 | previously, or the default DTLS configuration). |
2006 | |
2007 | \sa setConfiguration(), QSslConfiguration::defaultDtlsConfiguration() |
2008 | */ |
2009 | |
2010 | /*! |
2011 | \fn bool DtlsBase::setCookieGeneratorParameters(const QDtlsClientVerifier::GeneratorParameters ¶ms) |
2012 | \internal |
2013 | |
2014 | Sets the DTLS cookie generation parameters that DtlsCookieVerifier or DtlsCryptograph will use to |
2015 | \a params. |
2016 | |
2017 | \note This function returns \c false if parameters were invalid - if the secret was empty. Otherwise, |
2018 | this function must return true. |
2019 | |
2020 | \sa QDtlsClientVerifier::GeneratorParameters, cookieGeneratorParameters() |
2021 | */ |
2022 | |
2023 | /*! |
2024 | \fn QDtlsClientVerifier::GeneratorParameters DtlsBase::cookieGeneratorParameters() const |
2025 | \internal |
2026 | |
2027 | Returns DTLS cookie generation parameters that were either previously set by setCookieGeneratorParameters(), |
2028 | or default parameters. |
2029 | |
2030 | \sa setCookieGeneratorParameters() |
2031 | */ |
2032 | |
2033 | /*! |
2034 | \internal |
2035 | |
2036 | Destroys this object. |
2037 | */ |
2038 | DtlsBase::~DtlsBase() = default; |
2039 | |
2040 | /*! |
2041 | \class DtlsCookieVerifier |
2042 | \internal (Network-private) |
2043 | \brief DtlsCookieVerifier is an interface that allows a TLS plugin to support the class QDtlsClientVerifier. |
2044 | |
2045 | DtlsCookieVerifier is an interface, an abstract class, that has to be implemented by |
2046 | a TLS plugin that supports DTLS cookie verification. |
2047 | |
2048 | \sa QDtlsClientVerifier |
2049 | */ |
2050 | |
2051 | /*! |
2052 | \fn bool DtlsCookieVerifier::verifyClient(QUdpSocket *socket, const QByteArray &dgram, const QHostAddress &address, quint16 port) |
2053 | \internal |
2054 | |
2055 | This function is expected to verify a ClientHello message, found in \a dgram, using \a address, |
2056 | \a port, and cookie generator parameters. The function returns \c true if such cookie was found |
2057 | and \c false otherwise. If no valid cookie was found in the \a dgram, this verifier should use |
2058 | \a socket to send a HelloVerifyRequest message, using \a address and \a port as the destination |
2059 | and a source material for cookie generation, see also |
2060 | \l {RFC 6347, section 4.2.1} |
2061 | |
2062 | \sa QDtlsClientVerifier |
2063 | */ |
2064 | |
2065 | /*! |
2066 | \fn QByteArray DtlsCookieVerifier::verifiedHello() const |
2067 | \internal |
2068 | |
2069 | Returns the last ClientHello message containing the DTLS cookie that this verifier was |
2070 | able to verify as correct, or an empty byte array. |
2071 | |
2072 | \sa verifyClient() |
2073 | */ |
2074 | |
2075 | /*! |
2076 | \class DtlsCryptograph |
2077 | \internal (Network-private) |
2078 | \brief DtlsCryptograph is an interface that allows a TLS plugin to implement the class QDtls. |
2079 | |
2080 | DtlsCryptograph is an abstract class; a TLS plugin can provide a class, inheriting from |
2081 | DtlsCryptograph and implementing its pure virtual functions, thus implementing the class |
2082 | QDtls and enabling DTLS over UDP. |
2083 | |
2084 | To write DTLS datagrams, a class, inheriting DtlsCryptograph, is expected to use |
2085 | QUdpSocket. In general, all reading is done externally, so DtlsCryptograph is |
2086 | expected to only write into QUdpSocket, check possible socket errors, change socket |
2087 | options if needed. |
2088 | |
2089 | \note All functions in this class are pure virtual and have no actual implementation |
2090 | in the QtNetwork module. This documentation is mostly conceptual and only describes |
2091 | what those functions are expected to do, but not how they must be implemented. |
2092 | |
2093 | \sa QDtls, QUdpSocket |
2094 | */ |
2095 | |
2096 | /*! |
2097 | \fn QSslSocket::SslMode DtlsCryptograph::cryptographMode() const |
2098 | \internal |
2099 | |
2100 | Returns the mode (client or server) this object operates in. |
2101 | |
2102 | \note This mode is set once when a new DtlsCryptograph is created |
2103 | by QTlsBackend and cannot change. |
2104 | |
2105 | \sa QTlsBackend::createDtlsCryptograph() |
2106 | */ |
2107 | |
2108 | /*! |
2109 | \fn void DtlsCryptograph::setPeer(const QHostAddress &addr, quint16 port, const QString &name) |
2110 | \internal |
2111 | |
2112 | Sets the remote peer's address to \a addr and remote port to \a port. \a name, |
2113 | if not empty, is to be used when validating the peer's certificate. |
2114 | |
2115 | \sa peerAddress(), peerPort(), peerVerificationName() |
2116 | */ |
2117 | |
2118 | /*! |
2119 | \fn QHostAddress DtlsCryptograph::peerAddress() const |
2120 | \internal |
2121 | |
2122 | Returns the remote peer's address previously set by setPeer() or, |
2123 | if no address was set, an empty address. |
2124 | |
2125 | \sa setPeer() |
2126 | */ |
2127 | |
2128 | /*! |
2129 | \fn quint16 DtlsCryptograph::peerPort() const |
2130 | \internal |
2131 | |
2132 | Returns the remote peer's port previously set by setPeer() or |
2133 | 0 if no port was set. |
2134 | |
2135 | \sa setPeer(), peerAddress() |
2136 | */ |
2137 | |
2138 | /*! |
2139 | \fn void DtlsCryptograph::setPeerVerificationName(const QString &name) |
2140 | \internal |
2141 | |
2142 | Sets the host name to use during certificate validation to \a name. |
2143 | |
2144 | \sa peerVerificationName(), setPeer() |
2145 | */ |
2146 | |
2147 | /*! |
2148 | \fn QString DtlsCryptograph::peerVerificationName() const |
2149 | \internal |
2150 | |
2151 | Returns the name that this object is using during the certificate validation, |
2152 | previously set by setPeer() or setPeerVerificationName(). Returns an empty string |
2153 | if no peer verification name was set. |
2154 | |
2155 | \sa setPeer(), setPeerVerificationName() |
2156 | */ |
2157 | |
2158 | /*! |
2159 | \fn void DtlsCryptograph::setDtlsMtuHint(quint16 mtu) |
2160 | \internal |
2161 | |
2162 | Sets the maximum transmission unit (MTU), if it is supported by a TLS implementation, to \a mtu. |
2163 | |
2164 | \sa dtlsMtuHint() |
2165 | */ |
2166 | |
2167 | /*! |
2168 | \fn quint16 DtlsCryptograph::dtlsMtuHint() const |
2169 | \internal |
2170 | |
2171 | Returns the value of the maximum transmission unit either previously set by setDtlsMtuHint(), |
2172 | or some implementation-specific value (guessed or somehow known to this DtlsCryptograph). |
2173 | |
2174 | \sa setDtlsMtuHint() |
2175 | */ |
2176 | |
2177 | /*! |
2178 | \fn QDtls::HandshakeState DtlsCryptograph::state() const |
2179 | \internal |
2180 | |
2181 | Returns the current handshake state for this DtlsCryptograph (not started, in progress, |
2182 | peer verification error found, complete). |
2183 | |
2184 | \sa isConnectionEncrypted(), startHandshake() |
2185 | */ |
2186 | |
2187 | /*! |
2188 | \fn bool DtlsCryptograph::isConnectionEncrypted() const |
2189 | \internal |
2190 | |
2191 | Returns \c true if this DtlsCryptograph has completed a handshake without validation |
2192 | errors (or these errors were ignored). Returns \c false otherwise. |
2193 | */ |
2194 | |
2195 | /*! |
2196 | \fn bool DtlsCryptograph::startHandshake(QUdpSocket *socket, const QByteArray &dgram) |
2197 | \internal |
2198 | |
2199 | This function is expected to initialize some implementation-specific context and to start a DTLS |
2200 | handshake, using \a socket to write datagrams (but not to read them). If this object is operating |
2201 | as a server, \a dgram is non-empty and contains the ClientHello message. This function returns |
2202 | \c true if no error occurred (and this DtlsCryptograph's state switching to |
2203 | QDtls::HandshakeState::HandshakeInProgress), \c false otherwise. |
2204 | |
2205 | \sa continueHandshake(), handleTimeout(), resumeHandshake(), abortHandshake(), state() |
2206 | */ |
2207 | |
2208 | /*! |
2209 | \fn bool DtlsCryptograph::handleTimeout(QUdpSocket *socket) |
2210 | \internal |
2211 | |
2212 | In case a timeout occurred during the handshake, allows to re-transmit the last message, |
2213 | using \a socket to write the datagram. Returns \c true if no error occurred, \c false otherwise. |
2214 | |
2215 | \sa QDtls::handshakeTimeout(), QDtls::handleTimeout() |
2216 | */ |
2217 | |
2218 | /*! |
2219 | \fn bool DtlsCryptograph::continueHandshake(QUdpSocket *socket, const QByteArray &dgram) |
2220 | \internal |
2221 | |
2222 | Continues the handshake, using \a socket to write datagrams (a handshake-specific message). |
2223 | \a dgram contains the peer's handshake-specific message. Returns \c false in case some error |
2224 | was encountered (this can include socket-related errors and errors found during the certificate |
2225 | validation). Returns \c true if the handshake was complete successfully, or is still in progress. |
2226 | |
2227 | This function, depending on the implementation-specific state machine, may leave the handshake |
2228 | state in QDtls::HandshakeState::HandshakeInProgress, or switch to QDtls::HandshakeState::HandshakeComplete |
2229 | or QDtls::HandshakeState::PeerVerificationFailed. |
2230 | |
2231 | This function may store the peer's certificate (or chain of certificates), extract and store |
2232 | the information about the negotiated session protocol and ciphersuite. |
2233 | |
2234 | \sa startHandshake() |
2235 | */ |
2236 | |
2237 | /*! |
2238 | \fn bool DtlsCryptograph::resumeHandshake(QUdpSocket *socket) |
2239 | \internal |
2240 | |
2241 | If peer validation errors were found duing the handshake, this function tries to |
2242 | continue and complete the handshake. If errors were ignored, the function switches |
2243 | this object's state to QDtls::HandshakeState::HandshakeComplete and returns \c true. |
2244 | |
2245 | \sa abortHandshake() |
2246 | */ |
2247 | |
2248 | /*! |
2249 | \fn void DtlsCryptograph::abortHandshake(QUdpSocket *socket) |
2250 | \internal |
2251 | |
2252 | Aborts the handshake if it's in progress or in the state QDtls::HandshakeState::PeerVerificationFailed. |
2253 | The use of \a socket is implementation-specific (for example, this DtlsCryptograph may send |
2254 | ShutdownAlert message). |
2255 | |
2256 | \sa resumeHandshake() |
2257 | */ |
2258 | |
2259 | /*! |
2260 | \fn void DtlsCryptograph::sendShutdownAlert(QUdpSocket *socket) |
2261 | \internal |
2262 | |
2263 | If the underlying TLS library provides the required functionality, this function |
2264 | may sent ShutdownAlert message using \a socket. |
2265 | */ |
2266 | |
2267 | /*! |
2268 | \fn QList<QSslError> DtlsCryptograph::peerVerificationErrors() const |
2269 | \internal |
2270 | |
2271 | Returns the list of errors that this object encountered during DTLS handshake |
2272 | and certificate validation. |
2273 | |
2274 | \sa ignoreVerificationErrors() |
2275 | */ |
2276 | |
2277 | /*! |
2278 | \fn void DtlsCryptograph::ignoreVerificationErrors(const QList<QSslError> &errorsToIgnore) |
2279 | \internal |
2280 | |
2281 | Tells this object to ignore errors from \a errorsToIgnore when they are found during |
2282 | DTLS handshake. |
2283 | |
2284 | \sa peerVerificationErrors() |
2285 | */ |
2286 | |
2287 | /*! |
2288 | \fn QSslCipher DtlsCryptograph::dtlsSessionCipher() const |
2289 | \internal |
2290 | |
2291 | If such information is available, returns the ciphersuite, negotiated during |
2292 | the handshake. |
2293 | |
2294 | \sa continueHandshake(), dtlsSessionProtocol() |
2295 | */ |
2296 | |
2297 | /*! |
2298 | \fn QSsl::SslProtocol DtlsCryptograph::dtlsSessionProtocol() const |
2299 | \internal |
2300 | |
2301 | Returns the version of the session protocol that was negotiated during the handshake or |
2302 | QSsl::UnknownProtocol if the handshake is incomplete or no information about the session |
2303 | protocol is available. |
2304 | |
2305 | \sa continueHandshake(), dtlsSessionCipher() |
2306 | */ |
2307 | |
2308 | /*! |
2309 | \fn qint64 DtlsCryptograph::writeDatagramEncrypted(QUdpSocket *socket, const QByteArray &dgram) |
2310 | \internal |
2311 | |
2312 | If this DtlsCryptograph is in the QDtls::HandshakeState::HandshakeComplete state, this function |
2313 | encrypts \a dgram and writes this encrypted data into \a socket. |
2314 | |
2315 | Returns the number of bytes (of \a dgram) written, or -1 in case of error. This function should |
2316 | set the error code and description if some error was encountered. |
2317 | |
2318 | \sa decryptDatagram() |
2319 | */ |
2320 | |
2321 | /*! |
2322 | \fn QByteArray DtlsCryptograph::decryptDatagram(QUdpSocket *socket, const QByteArray &dgram) |
2323 | \internal |
2324 | |
2325 | If this DtlsCryptograph is in the QDtls::HandshakeState::HandshakeComplete state, decrypts \a dgram. |
2326 | The use of \a socket is implementation-specific. This function should return an empty byte array |
2327 | and set the error code and description if some error was encountered. |
2328 | */ |
2329 | |
2330 | #endif // QT_CONFIG(dtls) |
2331 | #endif // QT_CONFIG(ssl) |
2332 | |
2333 | } // namespace QTlsPrivate |
2334 | |
2335 | #if QT_CONFIG(ssl) |
2336 | /*! |
2337 | \internal |
2338 | */ |
2339 | Q_NETWORK_EXPORT void qt_ForceTlsSecurityLevel() |
2340 | { |
2341 | if (auto *backend = QSslSocketPrivate::tlsBackendInUse()) |
2342 | backend->forceAutotestSecurityLevel(); |
2343 | } |
2344 | |
2345 | #endif // QT_CONFIG(ssl) |
2346 | |
2347 | QT_END_NAMESPACE |
2348 | |
2349 | #include "moc_qtlsbackend_p.cpp" |
2350 | |