10#include <QtNetwork/private/qssl_p.h>
12#include <QtNetwork/private/qsslcertificate_p.h>
13#include <QtNetwork/private/qsslcipher_p.h>
14#include <QtNetwork/private/qsslkey_p.h>
16#include <QtNetwork/qsslsocket.h>
18#include <QtCore/qmessageauthenticationcode.h>
19#include <QtCore/qoperatingsystemversion.h>
20#include <QtCore/qscopedvaluerollback.h>
21#include <QtCore/qcryptographichash.h>
22#include <QtCore/qsystemdetection.h>
23#include <QtCore/qdatastream.h>
24#include <QtCore/qsysinfo.h>
25#include <QtCore/qlist.h>
26#include <QtCore/qmutex.h>
27#include <QtCore/qdebug.h>
28#include <QtCore/quuid.h>
29#include <QtCore/qdir.h>
36#include <QtCore/private/qcore_mac_p.h>
39#include <CoreServices/CoreServices.h>
44using namespace Qt::StringLiterals;
48 const QString &passPhrase);
59
60
61
62
63
64
66struct EphemeralSecKeychain
68 EphemeralSecKeychain();
69 ~EphemeralSecKeychain();
71 SecKeychainRef keychain =
nullptr;
72 Q_DISABLE_COPY_MOVE(EphemeralSecKeychain)
75EphemeralSecKeychain::EphemeralSecKeychain()
77 const auto uuid = QUuid::createUuid();
79 qCWarning(lcSecureTransport) <<
"Failed to create a unique keychain name";
83 const QByteArray uuidAsByteArray = uuid.toByteArray();
84 Q_ASSERT(uuidAsByteArray.size() > 2);
85 Q_ASSERT(uuidAsByteArray.startsWith(
'{'));
86 Q_ASSERT(uuidAsByteArray.endsWith(
'}'));
87 const auto uuidAsString = QLatin1StringView(uuidAsByteArray.data(), uuidAsByteArray.size()).mid(1, uuidAsByteArray.size() - 2);
89 const QString keychainName
90 = QDir::tempPath() + QDir::separator() + uuidAsString +
".keychain"_L1;
98 QCFType<CFStringRef> cfName = keychainName.toCFString();
99 std::vector<
char> posixPath;
102 posixPath.resize(CFStringGetMaximumSizeOfFileSystemRepresentation(cfName));
103 const auto ok = CFStringGetFileSystemRepresentation(cfName, &posixPath[0],
104 CFIndex(posixPath.size()));
106 qCWarning(lcSecureTransport) <<
"Failed to create a unique keychain name from"
107 <<
"QDir::tempPath()";
111 std::vector<uint8_t> passUtf8(256);
112 if (SecRandomCopyBytes(kSecRandomDefault, passUtf8.size(), &passUtf8[0])) {
113 qCWarning(lcSecureTransport) <<
"SecRandomCopyBytes: failed to create a key";
117 const OSStatus status = SecKeychainCreate(&posixPath[0], passUtf8.size(),
118 &passUtf8[0], FALSE,
nullptr,
120 if (status != errSecSuccess || !keychain) {
121 qCWarning(lcSecureTransport) <<
"SecKeychainCreate: failed to create a custom keychain";
123 SecKeychainDelete(keychain);
130 SecKeychainSettings settings = {};
131 settings.version = SEC_KEYCHAIN_SETTINGS_VERS1;
134 settings.lockInterval = INT_MAX;
135 if (SecKeychainSetSettings(keychain, &settings) != errSecSuccess)
136 qCWarning(lcSecureTransport) <<
"SecKeychainSettings: failed to disable lock on sleep";
139#ifdef QSSLSOCKET_DEBUG
141 qCDebug(lcSecureTransport) <<
"Custom keychain with name" << keychainName <<
"was created"
147EphemeralSecKeychain::~EphemeralSecKeychain()
151 SecKeychainDelete(keychain);
158void qt_releaseSecureTransportContext(SSLContextRef context)
169 const bool isServer = mode == QSslSocket::SslServerMode;
170 const SSLProtocolSide side = isServer ? kSSLServerSide : kSSLClientSide;
172 SSLContextRef context = SSLCreateContext(
nullptr, side, kSSLStreamType);
174 qCWarning(lcSecureTransport) <<
"SSLCreateContext failed";
185 qt_releaseSecureTransportContext(context);
195 qt_releaseSecureTransportContext(context);
196 context = newContext;
199#if !defined(QT_PLATFORM_UIKIT)
201 "\x30\x82\x01\x08\x02\x82\x01\x01\x00\x97\xea\xd0\x46\xf7\xae\xa7\x76\x80"
202 "\x9c\x74\x56\x98\xd8\x56\x97\x2b\x20\x6c\x77\xe2\x82\xbb\xc8\x84\xbe\xe7"
203 "\x63\xaf\xcc\x30\xd0\x67\x97\x7d\x1b\xab\x59\x30\xa9\x13\x67\x21\xd7\xd4"
204 "\x0e\x46\xcf\xe5\x80\xdf\xc9\xb9\xba\x54\x9b\x46\x2f\x3b\x45\xfc\x2f\xaf"
205 "\xad\xc0\x17\x56\xdd\x52\x42\x57\x45\x70\x14\xe5\xbe\x67\xaa\xde\x69\x75"
206 "\x30\x0d\xf9\xa2\xc4\x63\x4d\x7a\x39\xef\x14\x62\x18\x33\x44\xa1\xf9\xc1"
207 "\x52\xd1\xb6\x72\x21\x98\xf8\xab\x16\x1b\x7b\x37\x65\xe3\xc5\x11\x00\xf6"
208 "\x36\x1f\xd8\x5f\xd8\x9f\x43\xa8\xce\x9d\xbf\x5e\xd6\x2d\xfa\x0a\xc2\x01"
209 "\x54\xc2\xd9\x81\x54\x55\xb5\x26\xf8\x88\x37\xf5\xfe\xe0\xef\x4a\x34\x81"
210 "\xdc\x5a\xb3\x71\x46\x27\xe3\xcd\x24\xf6\x1b\xf1\xe2\x0f\xc2\xa1\x39\x53"
211 "\x5b\xc5\x38\x46\x8e\x67\x4c\xd9\xdd\xe4\x37\x06\x03\x16\xf1\x1d\x7a\xba"
212 "\x2d\xc1\xe4\x03\x1a\x58\xe5\x29\x5a\x29\x06\x69\x61\x7a\xd8\xa9\x05\x9f"
213 "\xc1\xa2\x45\x9c\x17\xad\x52\x69\x33\xdc\x18\x8d\x15\xa6\x5e\xcd\x94\xf4"
214 "\x45\xbb\x9f\xc2\x7b\x85\x00\x61\xb0\x1a\xdc\x3c\x86\xaa\x9f\x5c\x04\xb3"
215 "\x90\x0b\x35\x64\xff\xd9\xe3\xac\xf2\xf2\xeb\x3a\x63\x02\x01\x02";
219 char *data, size_t *dataLength)
223 Q_ASSERT(dataLength);
226 QTcpSocket *plainSocket = socket->d->plainTcpSocket();
227 Q_ASSERT(plainSocket);
229 if (socket->isHandshakeComplete()) {
232 SSLSessionState currentState = kSSLConnected;
233 const OSStatus result = SSLGetSessionState(socket->context, ¤tState);
234 if (result != noErr) {
239 if (currentState == kSSLHandshake) {
243 socket->renegotiating =
true;
244 return errSSLWouldBlock;
248 const qint64 bytes = plainSocket->read(data, *dataLength);
249#ifdef QSSLSOCKET_DEBUG
250 qCDebug(lcSecureTransport) << plainSocket <<
"read" << bytes;
257 const OSStatus err = (size_t(bytes) < *dataLength) ? OSStatus(errSSLWouldBlock) : OSStatus(errSecSuccess);
264 const char *data, size_t *dataLength)
268 Q_ASSERT(dataLength);
271 QTcpSocket *plainSocket = socket->d->plainTcpSocket();
272 Q_ASSERT(plainSocket);
274 const qint64 bytes = plainSocket->write(data, *dataLength);
275#ifdef QSSLSOCKET_DEBUG
276 qCDebug(lcSecureTransport) << plainSocket <<
"write" << bytes;
283 const OSStatus err = (size_t(bytes) < *dataLength) ? OSStatus(errSSLWouldBlock) : OSStatus(errSecSuccess);
306 renegotiating =
false;
314 d->setEncrypted(
true);
315#ifdef QSSLSOCKET_DEBUG
316 qCDebug(lcSecureTransport) << d->plainTcpSocket() <<
"connection encrypted";
323 const auto &configuration = q->sslConfiguration();
324 const auto &requestedProtocols = configuration.allowedNextProtocols();
325 if (
const int requestedCount = requestedProtocols.size()) {
326 QTlsBackend::setAlpnStatus(d, QSslConfiguration::NextProtocolNegotiationNone);
327 QTlsBackend::setNegotiatedProtocol(d, {});
329 QCFType<CFArrayRef> cfArray;
330 const OSStatus result = SSLCopyALPNProtocols(context, &cfArray);
331 if (result == errSecSuccess && cfArray && CFArrayGetCount(cfArray)) {
332 const int size = CFArrayGetCount(cfArray);
333 QList<QString> peerProtocols(size);
334 for (
int i = 0; i < size; ++i)
335 peerProtocols[i] = QString::fromCFString((CFStringRef)CFArrayGetValueAtIndex(cfArray, i));
337 for (
int i = 0; i < requestedCount; ++i) {
338 const auto requestedName = QString::fromLatin1(requestedProtocols[i]);
339 for (
int j = 0; j < size; ++j) {
340 if (requestedName == peerProtocols[j]) {
341 QTlsBackend::setNegotiatedProtocol(d, requestedName.toLatin1());
342 QTlsBackend::setAlpnStatus(d, QSslConfiguration::NextProtocolNegotiationNegotiated);
346 if (configuration.nextProtocolNegotiationStatus() == QSslConfiguration::NextProtocolNegotiationNegotiated)
355 if (d->isAutoStartingHandshake() && d->isPendingClose()) {
356 d->setPendingClose(
false);
357 q->disconnectFromHost();
363 Q_ASSERT(d && d->plainTcpSocket());
364 d->setEncrypted(
false);
365 if (d->plainTcpSocket()->bytesAvailable() <= 0)
373 Q_ASSERT(d && d->plainTcpSocket());
377 context.reset(
nullptr);
381 d->plainTcpSocket()->disconnectFromHost();
386 SSLCipherSuite cipher = 0;
387 if (context && SSLGetNegotiatedCipher(context, &cipher) == errSecSuccess)
388 return QSslCipher_from_SSLCipherSuite(cipher);
396 return QSsl::UnknownProtocol;
398 SSLProtocol protocol = kSSLProtocolUnknown;
399 const OSStatus err = SSLGetNegotiatedProtocolVersion(context, &protocol);
400 if (err != errSecSuccess) {
401 qCWarning(lcSecureTransport) <<
"SSLGetNegotiatedProtocolVersion failed:" << err;
402 return QSsl::UnknownProtocol;
407QT_WARNING_DISABLE_DEPRECATED
409 return QSsl::TlsV1_0;
411 return QSsl::TlsV1_1;
414 return QSsl::TlsV1_2;
416 return QSsl::TlsV1_3;
418 return QSsl::UnknownProtocol;
424 if (!initSslContext()) {
429 setErrorAndEmit(d, QAbstractSocket::SslInternalError, QStringLiteral(
"Unable to init SSL Context"));
438 if (!initSslContext()) {
442 setErrorAndEmit(d, QAbstractSocket::SslInternalError, QStringLiteral(
"Unable to init SSL Context"));
456 if (!context || shutdown)
459 if (!isHandshakeComplete())
462 auto &writeBuffer = d->tlsWriteBuffer();
463 if (isHandshakeComplete() && !writeBuffer.isEmpty()) {
464 qint64 totalBytesWritten = 0;
465 while (writeBuffer.nextDataBlockSize() > 0 && context) {
466 const size_t nextDataBlockSize = writeBuffer.nextDataBlockSize();
467 size_t writtenBytes = 0;
468 const OSStatus err = SSLWrite(context, writeBuffer.readPointer(), nextDataBlockSize, &writtenBytes);
469#ifdef QSSLSOCKET_DEBUG
470 qCDebug(lcSecureTransport) << d->plainTcpSocket() <<
"SSLWrite returned" << err;
472 if (err != errSecSuccess && err != errSSLWouldBlock) {
473 setErrorAndEmit(d, QAbstractSocket::SslInternalError,
474 QStringLiteral(
"SSLWrite failed: %1").arg(err));
479 writeBuffer.free(writtenBytes);
480 totalBytesWritten += writtenBytes;
483 if (writtenBytes < nextDataBlockSize)
487 if (totalBytesWritten > 0) {
489 auto &emittedBytesWritten = d->tlsEmittedBytesWritten();
490 if (!emittedBytesWritten) {
491 emittedBytesWritten =
true;
492 emit q->bytesWritten(totalBytesWritten);
493 emittedBytesWritten =
false;
495 emit q->channelBytesWritten(0, totalBytesWritten);
499 auto &buffer = d->tlsBuffer();
500 const auto readBufferMaxSize = d->maxReadBufferSize();
501 if (isHandshakeComplete()) {
502 QVarLengthArray<
char, 4096> data;
503 while (context && (!readBufferMaxSize || buffer.size() < readBufferMaxSize)) {
504 size_t readBytes = 0;
506 const OSStatus err = SSLRead(context, data.data(), data.size(), &readBytes);
507#ifdef QSSLSOCKET_DEBUG
508 qCDebug(lcSecureTransport) << d->plainTcpSocket() <<
"SSLRead returned" << err;
510 if (err == errSSLClosedGraceful) {
512 setErrorAndEmit(d, QAbstractSocket::RemoteHostClosedError,
513 QSslSocket::tr(
"The TLS/SSL connection has been closed"));
515 }
else if (err != errSecSuccess && err != errSSLWouldBlock) {
516 setErrorAndEmit(d, QAbstractSocket::SslInternalError,
517 QStringLiteral(
"SSLRead failed: %1").arg(err));
521 if (err == errSSLWouldBlock && renegotiating) {
527 buffer.append(data.constData(), readBytes);
528 if (
bool *readyReadEmittedPointer = d->readyReadPointer())
529 *readyReadEmittedPointer =
true;
531 emit q->channelReadyRead(0);
534 if (err == errSSLWouldBlock)
542 if (ciph.name() ==
"AES128-SHA"_L1)
543 return TLS_RSA_WITH_AES_128_CBC_SHA;
544 if (ciph.name() ==
"DHE-RSA-AES128-SHA"_L1)
545 return TLS_DHE_RSA_WITH_AES_128_CBC_SHA;
546 if (ciph.name() ==
"AES256-SHA"_L1)
547 return TLS_RSA_WITH_AES_256_CBC_SHA;
548 if (ciph.name() ==
"DHE-RSA-AES256-SHA"_L1)
549 return TLS_DHE_RSA_WITH_AES_256_CBC_SHA;
550 if (ciph.name() ==
"ECDH-ECDSA-NULL-SHA"_L1)
551 return TLS_ECDH_ECDSA_WITH_NULL_SHA;
552 if (ciph.name() ==
"ECDH-ECDSA-RC4-SHA"_L1)
553 return TLS_ECDH_ECDSA_WITH_RC4_128_SHA;
554 if (ciph.name() ==
"ECDH-ECDSA-DES-CBC3-SHA"_L1)
555 return TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA;
556 if (ciph.name() ==
"ECDH-ECDSA-AES128-SHA"_L1)
557 return TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA;
558 if (ciph.name() ==
"ECDH-ECDSA-AES256-SHA"_L1)
559 return TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA;
560 if (ciph.name() ==
"ECDH-ECDSA-RC4-SHA"_L1)
561 return TLS_ECDHE_ECDSA_WITH_RC4_128_SHA;
562 if (ciph.name() ==
"ECDH-ECDSA-DES-CBC3-SHA"_L1)
563 return TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA;
564 if (ciph.name() ==
"ECDH-ECDSA-AES128-SHA"_L1)
565 return TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA;
566 if (ciph.name() ==
"ECDH-ECDSA-AES256-SHA"_L1)
567 return TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA;
568 if (ciph.name() ==
"ECDH-RSA-NULL-SHA"_L1)
569 return TLS_ECDH_RSA_WITH_NULL_SHA;
570 if (ciph.name() ==
"ECDH-RSA-RC4-SHA"_L1)
571 return TLS_ECDH_RSA_WITH_RC4_128_SHA;
572 if (ciph.name() ==
"ECDH-RSA-DES-CBC3-SHA"_L1)
573 return TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA;
574 if (ciph.name() ==
"ECDH-RSA-AES128-SHA"_L1)
575 return TLS_ECDH_RSA_WITH_AES_128_CBC_SHA;
576 if (ciph.name() ==
"ECDH-RSA-AES256-SHA"_L1)
577 return TLS_ECDH_RSA_WITH_AES_256_CBC_SHA;
578 if (ciph.name() ==
"ECDH-RSA-RC4-SHA"_L1)
579 return TLS_ECDHE_RSA_WITH_RC4_128_SHA;
580 if (ciph.name() ==
"ECDH-RSA-DES-CBC3-SHA"_L1)
581 return TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA;
582 if (ciph.name() ==
"ECDH-RSA-AES128-SHA"_L1)
583 return TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA;
584 if (ciph.name() ==
"ECDH-RSA-AES256-SHA"_L1)
585 return TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA;
586 if (ciph.name() ==
"DES-CBC3-SHA"_L1)
587 return TLS_RSA_WITH_3DES_EDE_CBC_SHA;
588 if (ciph.name() ==
"AES128-SHA256"_L1)
589 return TLS_RSA_WITH_AES_128_CBC_SHA256;
590 if (ciph.name() ==
"AES256-SHA256"_L1)
591 return TLS_RSA_WITH_AES_256_CBC_SHA256;
592 if (ciph.name() ==
"DHE-RSA-DES-CBC3-SHA"_L1)
593 return TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA;
594 if (ciph.name() ==
"DHE-RSA-AES128-SHA256"_L1)
595 return TLS_DHE_RSA_WITH_AES_128_CBC_SHA256;
596 if (ciph.name() ==
"DHE-RSA-AES256-SHA256"_L1)
597 return TLS_DHE_RSA_WITH_AES_256_CBC_SHA256;
598 if (ciph.name() ==
"AES256-GCM-SHA384"_L1)
599 return TLS_RSA_WITH_AES_256_GCM_SHA384;
600 if (ciph.name() ==
"ECDHE-ECDSA-AES128-SHA256"_L1)
601 return TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256;
602 if (ciph.name() ==
"ECDHE-ECDSA-AES256-SHA384"_L1)
603 return TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384;
604 if (ciph.name() ==
"ECDH-ECDSA-AES128-SHA256"_L1)
605 return TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256;
606 if (ciph.name() ==
"ECDH-ECDSA-AES256-SHA384"_L1)
607 return TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384;
608 if (ciph.name() ==
"ECDHE-RSA-AES128-SHA256"_L1)
609 return TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256;
610 if (ciph.name() ==
"ECDHE-RSA-AES256-SHA384"_L1)
611 return TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384;
612 if (ciph.name() ==
"ECDHE-RSA-AES256-SHA384"_L1)
613 return TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256;
614 if (ciph.name() ==
"ECDHE-RSA-AES256-GCM-SHA384"_L1)
615 return TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384;
616 if (ciph.name() ==
"AES128-GCM-SHA256"_L1)
617 return TLS_AES_128_GCM_SHA256;
618 if (ciph.name() ==
"AES256-GCM-SHA384"_L1)
619 return TLS_AES_256_GCM_SHA384;
620 if (ciph.name() ==
"CHACHA20-POLY1305-SHA256"_L1)
621 return TLS_CHACHA20_POLY1305_SHA256;
622 if (ciph.name() ==
"AES128-CCM-SHA256"_L1)
623 return TLS_AES_128_CCM_SHA256;
624 if (ciph.name() ==
"AES128-CCM8-SHA256"_L1)
625 return TLS_AES_128_CCM_8_SHA256;
626 if (ciph.name() ==
"ECDHE-ECDSA-AES128-GCM-SHA256"_L1)
627 return TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256;
628 if (ciph.name() ==
"ECDHE-ECDSA-AES256-GCM-SHA384"_L1)
629 return TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384;
630 if (ciph.name() ==
"ECDH-ECDSA-AES128-GCM-SHA256"_L1)
631 return TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256;
632 if (ciph.name() ==
"ECDH-ECDSA-AES256-GCM-SHA384"_L1)
633 return TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384;
634 if (ciph.name() ==
"ECDHE-RSA-AES128-GCM-SHA256"_L1)
635 return TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256;
636 if (ciph.name() ==
"ECDH-RSA-AES128-GCM-SHA256"_L1)
637 return TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256;
638 if (ciph.name() ==
"ECDH-RSA-AES256-GCM-SHA384"_L1)
639 return TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384;
640 if (ciph.name() ==
"ECDHE-RSA-CHACHA20-POLY1305-SHA256"_L1)
641 return TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256;
642 if (ciph.name() ==
"ECDHE-ECDSA-CHACHA20-POLY1305-SHA256"_L1)
643 return TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256;
653 Q_ASSERT_X(!context, Q_FUNC_INFO,
"invalid socket state, context is not null");
654 auto *plainSocket = d->plainTcpSocket();
655 Q_ASSERT(plainSocket);
657 const auto mode = d->tlsMode();
659 context.reset(qt_createSecureTransportContext(mode));
661 setErrorAndEmit(d, QAbstractSocket::SslInternalError, QStringLiteral(
"SSLCreateContext failed"));
665 const OSStatus err = SSLSetIOFuncs(context,
666 reinterpret_cast<SSLReadFunc>(&TlsCryptographSecureTransport::ReadCallback),
667 reinterpret_cast<SSLWriteFunc>(&TlsCryptographSecureTransport::WriteCallback));
668 if (err != errSecSuccess) {
670 setErrorAndEmit(d, QAbstractSocket::SslInternalError,
671 QStringLiteral(
"SSLSetIOFuncs failed: %1").arg(err));
675 SSLSetConnection(context,
this);
677 const auto &configuration = q->sslConfiguration();
678 if (mode == QSslSocket::SslServerMode
679 && !configuration.localCertificateChain().isEmpty()) {
680 QString errorDescription;
681 QAbstractSocket::SocketError errorCode = QAbstractSocket::UnknownSocketError;
682 if (!setSessionCertificate(errorDescription, errorCode)) {
684 setErrorAndEmit(d, errorCode, errorDescription);
689 if (!setSessionProtocol()) {
691 setErrorAndEmit(d, QAbstractSocket::SslInternalError, QStringLiteral(
"Failed to set protocol version"));
695 const auto protocolNames = configuration.allowedNextProtocols();
696 QCFType<CFMutableArrayRef> cfNames(CFArrayCreateMutable(
nullptr, 0, &kCFTypeArrayCallBacks));
698 for (
const QByteArray &name : protocolNames) {
699 if (name.size() > 255) {
700 qCWarning(lcSecureTransport) <<
"TLS ALPN extension" << name
701 <<
"is too long and will be ignored.";
703 }
else if (name.isEmpty()) {
706 QCFString cfName(QString::fromLatin1(name).toCFString());
707 CFArrayAppendValue(cfNames, cfName);
710 if (CFArrayGetCount(cfNames)) {
714 if (SSLSetALPNProtocols(context, cfNames) != errSecSuccess)
715 qCWarning(lcSecureTransport) <<
"SSLSetALPNProtocols failed - too long protocol names?";
718 qCWarning(lcSecureTransport) <<
"failed to allocate ALPN names array";
721 if (mode == QSslSocket::SslClientMode) {
723 const auto verificationPeerName = d->verificationName();
724 QString tlsHostName(verificationPeerName.isEmpty() ? q->peerName() : verificationPeerName);
725 if (tlsHostName.isEmpty())
726 tlsHostName = d->tlsHostName();
728 const QByteArray ace(QUrl::toAce(tlsHostName));
729 SSLSetPeerDomainName(context, ace.data(), ace.size());
731 OSStatus err = SSLSetSessionOption(context, kSSLSessionOptionBreakOnServerAuth,
true);
732 if (err == errSecSuccess)
733 err = SSLSetSessionOption(context, kSSLSessionOptionBreakOnCertRequested,
true);
735 if (err != errSecSuccess) {
737 setErrorAndEmit(d, QSslSocket::SslInternalError,
738 QStringLiteral(
"SSLSetSessionOption failed: %1").arg(err));
743 if (configuration.peerVerifyMode() != QSslSocket::VerifyNone) {
745 OSStatus err = SSLSetClientSideAuthenticate(context, kTryAuthenticate);
746 if (err == errSecSuccess) {
749 err = SSLSetSessionOption(context, kSSLSessionOptionBreakOnClientAuth,
true);
752 if (err != errSecSuccess) {
754 setErrorAndEmit(d, QAbstractSocket::SslInternalError,
755 QStringLiteral(
"failed to set SSL context option in server mode: %1").arg(err));
759#if !defined(QT_PLATFORM_UIKIT)
761 SSLSetDiffieHellmanParams(context, dhparam,
sizeof(dhparam));
764 if (configuration.ciphers().size() > 0) {
765 QVector<SSLCipherSuite> cfCiphers;
766 for (
const QSslCipher &cipher : configuration.ciphers()) {
767 if (
auto sslCipher = TlsCryptographSecureTransport::SSLCipherSuite_from_QSslCipher(cipher))
768 cfCiphers << sslCipher;
770 if (cfCiphers.size() == 0) {
771 qCWarning(lcSecureTransport) <<
"failed to add any of the requested ciphers from the configuration";
774 OSStatus err = SSLSetEnabledCiphers(context, cfCiphers.data(), cfCiphers.size());
775 if (err != errSecSuccess) {
776 qCWarning(lcSecureTransport) <<
"failed to set the ciphers from the configuration";
785 context.reset(
nullptr);
790 Q_ASSERT_X(context, Q_FUNC_INFO,
"invalid SSL context (null)");
793 const auto &configuration = q->sslConfiguration();
795#ifdef QSSLSOCKET_DEBUG
796 auto *plainSocket = d->plainTcpSocket();
799 QSslCertificate localCertificate;
801 if (!configuration.localCertificateChain().isEmpty())
802 localCertificate = configuration.localCertificateChain().at(0);
804 if (!localCertificate.isNull()) {
806 if (configuration.privateKey().isNull()) {
807 errorCode = QAbstractSocket::SslInvalidUserDataError;
808 errorDescription = QStringLiteral(
"Cannot provide a certificate with no key");
813 const QString passPhrase(QString::fromLatin1(
"foobar"));
814 QCFType<CFDataRef> pkcs12 = _q_makePkcs12(configuration.localCertificateChain(),
815 configuration.privateKey(), passPhrase).toCFData();
816 QCFType<CFStringRef> password = passPhrase.toCFString();
817 const void *keys[2] = { kSecImportExportPassphrase };
818 const void *values[2] = { password };
821#if QT_MACOS_IOS_PLATFORM_SDK_EQUAL_OR_ABOVE(150000
, 180000
)
827 if (
__builtin_available(macOS 15, *)) {
829 keys[1] = kSecImportToMemoryOnly;
830 values[1] = kCFBooleanTrue;
836 const int env = qEnvironmentVariableIntValue(
"QT_SSL_USE_TEMPORARY_KEYCHAIN", &envOk);
838 static const EphemeralSecKeychain temporaryKeychain;
839 if (temporaryKeychain.keychain) {
841 keys[1] = kSecImportExportKeychain;
842 values[1] = temporaryKeychain.keychain;
847 QCFType<CFDictionaryRef> options = CFDictionaryCreate(
nullptr, keys, values, nKeys,
849 QCFType<CFArrayRef> items;
850 OSStatus err = SecPKCS12Import(pkcs12, options, &items);
851 if (err != errSecSuccess) {
852#ifdef QSSLSOCKET_DEBUG
853 qCWarning(lcSecureTransport) << plainSocket
854 << QStringLiteral(
"SecPKCS12Import failed: %1").arg(err);
856 errorCode = QAbstractSocket::SslInvalidUserDataError;
857 errorDescription = QStringLiteral(
"SecPKCS12Import failed: %1").arg(err);
861 if (!CFArrayGetCount(items)) {
862#ifdef QSSLSOCKET_DEBUG
863 qCWarning(lcSecureTransport) << plainSocket <<
"SecPKCS12Import returned no items";
865 errorCode = QAbstractSocket::SslInvalidUserDataError;
866 errorDescription = QStringLiteral(
"SecPKCS12Import returned no items");
870 CFDictionaryRef import = (CFDictionaryRef)CFArrayGetValueAtIndex(items, 0);
871 SecIdentityRef identity = (SecIdentityRef)CFDictionaryGetValue(import, kSecImportItemIdentity);
873#ifdef QSSLSOCKET_DEBUG
874 qCWarning(lcSecureTransport) << plainSocket <<
"SecPKCS12Import returned no identity";
876 errorCode = QAbstractSocket::SslInvalidUserDataError;
877 errorDescription = QStringLiteral(
"SecPKCS12Import returned no identity");
881 QCFType<CFMutableArrayRef> certs = CFArrayCreateMutable(
nullptr, 0, &kCFTypeArrayCallBacks);
883 errorCode = QAbstractSocket::SslInternalError;
884 errorDescription = QStringLiteral(
"Failed to allocate certificates array");
888 CFArrayAppendValue(certs, identity);
890 CFArrayRef chain = (CFArrayRef)CFDictionaryGetValue(import, kSecImportItemCertChain);
892 for (CFIndex i = 1, e = CFArrayGetCount(chain); i < e; ++i)
893 CFArrayAppendValue(certs, CFArrayGetValueAtIndex(chain, i));
896 err = SSLSetCertificate(context, certs);
897 if (err != errSecSuccess) {
898#ifdef QSSLSOCKET_DEBUG
899 qCWarning(lcSecureTransport) << plainSocket
900 << QStringLiteral(
"Cannot set certificate and key: %1").arg(err);
902 errorCode = QAbstractSocket::SslInvalidUserDataError;
903 errorDescription = QStringLiteral(
"Cannot set certificate and key: %1").arg(err);
913 Q_ASSERT_X(context, Q_FUNC_INFO,
"invalid SSL context (null)");
920 const auto &configuration = q->sslConfiguration();
921 auto *plainSocket = d->plainTcpSocket();
922 switch (configuration.protocol()) {
924 case QSsl::TlsV1_3OrLater:
925 qCWarning(lcSecureTransport) << plainSocket <<
"SecureTransport does not support TLS 1.3";
930 OSStatus err = errSecSuccess;
933QT_WARNING_DISABLE_DEPRECATED
934 if (configuration.protocol() == QSsl::TlsV1_0) {
935 #ifdef QSSLSOCKET_DEBUG
936 qCDebug(lcSecureTransport) << plainSocket <<
"requesting : TLSv1.0";
938 err = SSLSetProtocolVersionMin(context, kTLSProtocol1);
939 if (err == errSecSuccess)
940 err = SSLSetProtocolVersionMax(context, kTLSProtocol1);
941 }
else if (configuration.protocol() == QSsl::TlsV1_1) {
942 #ifdef QSSLSOCKET_DEBUG
943 qCDebug(lcSecureTransport) << plainSocket <<
"requesting : TLSv1.1";
945 err = SSLSetProtocolVersionMin(context, kTLSProtocol11);
946 if (err == errSecSuccess)
947 err = SSLSetProtocolVersionMax(context, kTLSProtocol11);
949 }
else if (configuration.protocol() == QSsl::TlsV1_2) {
950 #ifdef QSSLSOCKET_DEBUG
951 qCDebug(lcSecureTransport) << plainSocket <<
"requesting : TLSv1.2";
953 err = SSLSetProtocolVersionMin(context, kTLSProtocol12);
954 if (err == errSecSuccess)
955 err = SSLSetProtocolVersionMax(context, kTLSProtocol12);
956 }
else if (configuration.protocol() == QSsl::AnyProtocol) {
957 #ifdef QSSLSOCKET_DEBUG
958 qCDebug(lcSecureTransport) << plainSocket <<
"requesting : any";
960 err = SSLSetProtocolVersionMin(context, kTLSProtocol1);
961 }
else if (configuration.protocol() == QSsl::SecureProtocols) {
962 #ifdef QSSLSOCKET_DEBUG
963 qCDebug(lcSecureTransport) << plainSocket <<
"requesting : TLSv1.2";
965 err = SSLSetProtocolVersionMin(context, kTLSProtocol12);
967QT_WARNING_DISABLE_DEPRECATED
968 }
else if (configuration.protocol() == QSsl::TlsV1_0OrLater) {
969 #ifdef QSSLSOCKET_DEBUG
970 qCDebug(lcSecureTransport) << plainSocket <<
"requesting : TLSv1 - TLSv1.2";
972 err = SSLSetProtocolVersionMin(context, kTLSProtocol1);
973 }
else if (configuration.protocol() == QSsl::TlsV1_1OrLater) {
974 #ifdef QSSLSOCKET_DEBUG
975 qCDebug(lcSecureTransport) << plainSocket <<
"requesting : TLSv1.1 - TLSv1.2";
977 err = SSLSetProtocolVersionMin(context, kTLSProtocol11);
979 }
else if (configuration.protocol() == QSsl::TlsV1_2OrLater) {
980 #ifdef QSSLSOCKET_DEBUG
981 qCDebug(lcSecureTransport) << plainSocket <<
"requesting : TLSv1.2";
983 err = SSLSetProtocolVersionMin(context, kTLSProtocol12);
985 #ifdef QSSLSOCKET_DEBUG
986 qCDebug(lcSecureTransport) << plainSocket <<
"no protocol version found in the configuration";
991 return err == errSecSuccess;
998 const auto &configuration = q->sslConfiguration();
999 const QSslSocket::PeerVerifyMode verifyMode = configuration.peerVerifyMode();
1000 return d->tlsMode() == QSslSocket::SslServerMode
1001 && (verifyMode == QSslSocket::QueryPeer
1002 || verifyMode == QSslSocket::AutoVerifyPeer
1003 || verifyMode == QSslSocket::VerifyNone);
1010 const auto &configuration = q->sslConfiguration();
1011 bool protocolOk =
false;
1012 if (configuration.protocol() == QSsl::AnyProtocol)
1014 else if (configuration.protocol() == QSsl::SecureProtocols)
1015 protocolOk = (sessionProtocol() >= QSsl::TlsV1_2);
1017QT_WARNING_DISABLE_DEPRECATED
1018 else if (configuration.protocol() == QSsl::TlsV1_0OrLater)
1019 protocolOk = (sessionProtocol() >= QSsl::TlsV1_0);
1020 else if (configuration.protocol() == QSsl::TlsV1_1OrLater)
1021 protocolOk = (sessionProtocol() >= QSsl::TlsV1_1);
1023 else if (configuration.protocol() == QSsl::TlsV1_2OrLater)
1024 protocolOk = (sessionProtocol() >= QSsl::TlsV1_2);
1025 else if (configuration.protocol() == QSsl::TlsV1_3OrLater)
1026 protocolOk = (sessionProtocol() >= QSsl::TlsV1_3OrLater);
1028 protocolOk = (sessionProtocol() == configuration.protocol());
1038 const auto mode = d->tlsMode();
1039 const QSslSocket::PeerVerifyMode verifyMode = q->peerVerifyMode();
1040 const bool canIgnoreVerify = canIgnoreTrustVerificationFailure();
1042 Q_ASSERT_X(context, Q_FUNC_INFO,
"invalid SSL context (null)");
1044 auto *plainSocket = d->plainTcpSocket();
1045 Q_ASSERT(plainSocket);
1047 QCFType<SecTrustRef> trust;
1048 OSStatus err = SSLCopyPeerTrust(context, &trust);
1050 if (err != errSecSuccess || !trust) {
1051 if (!canIgnoreVerify) {
1052 setErrorAndEmit(d, QAbstractSocket::SslHandshakeFailedError,
1053 QStringLiteral(
"Failed to obtain peer trust: %1").arg(err));
1054 plainSocket->disconnectFromHost();
1061 QList<QSslError> errors;
1069 SecTrustResultType res = kSecTrustResultInvalid;
1070 err = SecTrustEvaluate(trust, &res);
1071 if (err != errSecSuccess) {
1074 setErrorAndEmit(d, QAbstractSocket::SslHandshakeFailedError,
1075 QStringLiteral(
"SecTrustEvaluate failed: %1").arg(err));
1076 plainSocket->disconnectFromHost();
1080 QTlsBackend::clearPeerCertificates(d);
1082 QList<QSslCertificate> peerCertificateChain;
1083 const CFIndex certCount = SecTrustGetCertificateCount(trust);
1084 for (CFIndex i = 0; i < certCount; ++i) {
1085 SecCertificateRef cert = SecTrustGetCertificateAtIndex(trust, i);
1086 QCFType<CFDataRef> derData = SecCertificateCopyData(cert);
1087 peerCertificateChain << QSslCertificate(QByteArray::fromCFData(derData), QSsl::Der);
1089 QTlsBackend::storePeerCertificateChain(d, peerCertificateChain);
1091 if (peerCertificateChain.size())
1092 QTlsBackend::storePeerCertificate(d, peerCertificateChain.at(0));
1095 for (
const QSslCertificate &cert : std::as_const(peerCertificateChain)) {
1096 if (QSslCertificatePrivate::isBlacklisted(cert) && !canIgnoreVerify) {
1097 const QSslError error(QSslError::CertificateBlacklisted, cert);
1099 emit q->peerVerifyError(error);
1100 if (q->state() != QAbstractSocket::ConnectedState)
1105 const bool doVerifyPeer = verifyMode == QSslSocket::VerifyPeer
1106 || (verifyMode == QSslSocket::AutoVerifyPeer
1107 && d->tlsMode() == QSslSocket::SslClientMode);
1111 const auto &peerCertificate = q->peerCertificate();
1112 if (!peerCertificate.isNull()) {
1115 const QString verificationPeerName = d->verificationName();
1116 if (mode == QSslSocket::SslClientMode) {
1117 const QString peerName(verificationPeerName.isEmpty () ? q->peerName() : verificationPeerName);
1118 if (!isMatchingHostname(peerCertificate, peerName) && !canIgnoreVerify) {
1120 const QSslError error(QSslError::HostNameMismatch, peerCertificate);
1122 emit q->peerVerifyError(error);
1123 if (q->state() != QAbstractSocket::ConnectedState)
1130 if (doVerifyPeer && !canIgnoreVerify) {
1131 const QSslError error(QSslError::NoPeerCertificate);
1133 emit q->peerVerifyError(error);
1134 if (q->state() != QAbstractSocket::ConnectedState)
1140 QCFType<CFMutableArrayRef> certArray = CFArrayCreateMutable(
nullptr, 0, &kCFTypeArrayCallBacks);
1141 const auto &caCertificates = q->sslConfiguration().caCertificates();
1142 for (
const QSslCertificate &cert : caCertificates) {
1143 QCFType<CFDataRef> certData = cert.toDer().toCFData();
1144 if (QCFType<SecCertificateRef> secRef = SecCertificateCreateWithData(
nullptr, certData))
1145 CFArrayAppendValue(certArray, secRef);
1148 SecTrustSetAnchorCertificates(trust, certArray);
1169 bool anchorsFromConfigurationOnly =
false;
1172 if (QOperatingSystemVersion::current() >= QOperatingSystemVersion::MacOSSierra)
1173 anchorsFromConfigurationOnly =
true;
1176 SecTrustSetAnchorCertificatesOnly(trust, anchorsFromConfigurationOnly);
1178 SecTrustResultType trustResult = kSecTrustResultInvalid;
1179 SecTrustEvaluate(trust, &trustResult);
1180 switch (trustResult) {
1181 case kSecTrustResultUnspecified:
1182 case kSecTrustResultProceed:
1185 if (!canIgnoreVerify) {
1186 const QSslError error(QSslError::CertificateUntrusted, peerCertificate);
1188 emit q->peerVerifyError(error);
1193 if (!errors.isEmpty() && !canIgnoreVerify) {
1198 if (!checkSslErrors() || q->state() != QAbstractSocket::ConnectedState)
1208
1209
1212 if (sslErrors.isEmpty())
1218 emit q->sslErrors(sslErrors);
1219 const auto mode = d->tlsMode();
1220 const auto &configuration = q->sslConfiguration();
1221 const bool doVerifyPeer = configuration.peerVerifyMode() == QSslSocket::VerifyPeer
1222 || (configuration.peerVerifyMode() == QSslSocket::AutoVerifyPeer
1223 && mode == QSslSocket::SslClientMode);
1224 const bool doEmitSslError = !d->verifyErrorsHaveBeenIgnored();
1226 if (doVerifyPeer && doEmitSslError) {
1227 if (q->pauseMode() & QAbstractSocket::PauseOnSslErrors) {
1228 QSslSocketPrivate::pauseSocketNotifiers(q);
1231 setErrorAndEmit(d, QAbstractSocket::SslHandshakeFailedError,
1232 sslErrors.constFirst().errorString());
1233 Q_ASSERT(d->plainTcpSocket());
1234 d->plainTcpSocket()->disconnectFromHost();
1248 auto *plainSocket = d->plainTcpSocket();
1249 Q_ASSERT(plainSocket);
1250 const auto mode = d->tlsMode();
1252 OSStatus err = SSLHandshake(context);
1253#ifdef QSSLSOCKET_DEBUG
1254 qCDebug(lcSecureTransport) << plainSocket <<
"SSLHandhake returned" << err;
1257 if (err == errSSLWouldBlock) {
1260 }
else if (err == errSSLServerAuthCompleted) {
1267 return startHandshake();
1268 }
else if (err == errSSLClientCertRequested) {
1269 Q_ASSERT(mode == QSslSocket::SslClientMode);
1270 QString errorDescription;
1271 QAbstractSocket::SocketError errorCode = QAbstractSocket::UnknownSocketError;
1274 if (!setSessionCertificate(errorDescription, errorCode)) {
1275 setErrorAndEmit(d, errorCode, errorDescription);
1276 renegotiating =
false;
1281 return startHandshake();
1283 }
else if (err != errSecSuccess) {
1284 if (err == errSSLBadCert && canIgnoreTrustVerificationFailure()) {
1288 return startHandshake();
1291 renegotiating =
false;
1292 setErrorAndEmit(d, QAbstractSocket::SslHandshakeFailedError,
1293 QStringLiteral(
"SSLHandshake failed: %1").arg(err));
1294 plainSocket->disconnectFromHost();
1299 if (q->state() != QAbstractSocket::ConnectedState) {
1300 qCDebug(lcSecureTransport) <<
"connection aborted";
1301 renegotiating =
false;
1307 if (!verifySessionProtocol()) {
1308 setErrorAndEmit(d, QAbstractSocket::SslHandshakeFailedError, QStringLiteral(
"Protocol version mismatch"));
1309 plainSocket->disconnectFromHost();
1310 renegotiating =
false;
1314 if (verifyPeerTrust()) {
1316 renegotiating =
false;
1319 renegotiating =
false;
1327 return q->isEncrypted() && !renegotiating;
~QSecureTransportContext()
void reset(SSLContextRef newContext)
QSecureTransportContext(SSLContextRef context)
void disconnectFromHost() override
TlsCryptographSecureTransport()
void startClientEncryption() override
void continueHandshake() override
QSslCipher sessionCipher() const override
QList< QSslError > tlsErrors() const override
void init(QSslSocket *qObj, QSslSocketPrivate *dObj) override
QSsl::SslProtocol sessionProtocol() const override
void startServerEncryption() override
SSLCipherSuite SSLCipherSuite_from_QSslCipher(const QSslCipher &ciph)
~TlsCryptographSecureTransport() override
void disconnected() override
Namespace containing onternal types that TLS backends implement.
QSslCipher QSslCipher_from_SSLCipherSuite(SSLCipherSuite cipher)
static const uint8_t dhparam[]
SSLContextRef qt_createSecureTransportContext(QSslSocket::SslMode mode)
QByteArray _q_makePkcs12(const QList< QSslCertificate > &certs, const QSslKey &key, const QString &passPhrase)