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 if (d->plainTcpSocket()->isValid())
379 context.reset(
nullptr);
383 d->plainTcpSocket()->disconnectFromHost();
388 SSLCipherSuite cipher = 0;
389 if (context && SSLGetNegotiatedCipher(context, &cipher) == errSecSuccess)
390 return QSslCipher_from_SSLCipherSuite(cipher);
398 return QSsl::UnknownProtocol;
400 SSLProtocol protocol = kSSLProtocolUnknown;
401 const OSStatus err = SSLGetNegotiatedProtocolVersion(context, &protocol);
402 if (err != errSecSuccess) {
403 qCWarning(lcSecureTransport) <<
"SSLGetNegotiatedProtocolVersion failed:" << err;
404 return QSsl::UnknownProtocol;
409QT_WARNING_DISABLE_DEPRECATED
411 return QSsl::TlsV1_0;
413 return QSsl::TlsV1_1;
416 return QSsl::TlsV1_2;
418 return QSsl::TlsV1_3;
420 return QSsl::UnknownProtocol;
426 if (!initSslContext()) {
431 setErrorAndEmit(d, QAbstractSocket::SslInternalError, QStringLiteral(
"Unable to init SSL Context"));
440 if (!initSslContext()) {
444 setErrorAndEmit(d, QAbstractSocket::SslInternalError, QStringLiteral(
"Unable to init SSL Context"));
458 if (!context || shutdown)
461 if (!isHandshakeComplete())
464 auto &writeBuffer = d->tlsWriteBuffer();
465 if (isHandshakeComplete() && !writeBuffer.isEmpty()) {
466 qint64 totalBytesWritten = 0;
467 while (writeBuffer.nextDataBlockSize() > 0 && context) {
468 const size_t nextDataBlockSize = writeBuffer.nextDataBlockSize();
469 size_t writtenBytes = 0;
470 const OSStatus err = SSLWrite(context, writeBuffer.readPointer(), nextDataBlockSize, &writtenBytes);
471#ifdef QSSLSOCKET_DEBUG
472 qCDebug(lcSecureTransport) << d->plainTcpSocket() <<
"SSLWrite returned" << err;
474 if (err != errSecSuccess && err != errSSLWouldBlock) {
475 setErrorAndEmit(d, QAbstractSocket::SslInternalError,
476 QStringLiteral(
"SSLWrite failed: %1").arg(err));
481 writeBuffer.free(writtenBytes);
482 totalBytesWritten += writtenBytes;
485 if (writtenBytes < nextDataBlockSize)
489 if (totalBytesWritten > 0) {
491 auto &emittedBytesWritten = d->tlsEmittedBytesWritten();
492 if (!emittedBytesWritten) {
493 emittedBytesWritten =
true;
494 emit q->bytesWritten(totalBytesWritten);
495 emittedBytesWritten =
false;
497 emit q->channelBytesWritten(0, totalBytesWritten);
501 auto &buffer = d->tlsBuffer();
502 const auto readBufferMaxSize = d->maxReadBufferSize();
503 if (isHandshakeComplete()) {
504 QVarLengthArray<
char, 4096> data;
505 while (context && (!readBufferMaxSize || buffer.size() < readBufferMaxSize)) {
506 size_t readBytes = 0;
508 const OSStatus err = SSLRead(context, data.data(), data.size(), &readBytes);
509#ifdef QSSLSOCKET_DEBUG
510 qCDebug(lcSecureTransport) << d->plainTcpSocket() <<
"SSLRead returned" << err;
512 if (err == errSSLClosedGraceful) {
514 setErrorAndEmit(d, QAbstractSocket::RemoteHostClosedError,
515 QSslSocket::tr(
"The TLS/SSL connection has been closed"));
517 }
else if (err != errSecSuccess && err != errSSLWouldBlock) {
518 setErrorAndEmit(d, QAbstractSocket::SslInternalError,
519 QStringLiteral(
"SSLRead failed: %1").arg(err));
523 if (err == errSSLWouldBlock && renegotiating) {
529 buffer.append(data.constData(), readBytes);
530 if (
bool *readyReadEmittedPointer = d->readyReadPointer())
531 *readyReadEmittedPointer =
true;
533 emit q->channelReadyRead(0);
536 if (err == errSSLWouldBlock)
544 if (ciph.name() ==
"AES128-SHA"_L1)
545 return TLS_RSA_WITH_AES_128_CBC_SHA;
546 if (ciph.name() ==
"DHE-RSA-AES128-SHA"_L1)
547 return TLS_DHE_RSA_WITH_AES_128_CBC_SHA;
548 if (ciph.name() ==
"AES256-SHA"_L1)
549 return TLS_RSA_WITH_AES_256_CBC_SHA;
550 if (ciph.name() ==
"DHE-RSA-AES256-SHA"_L1)
551 return TLS_DHE_RSA_WITH_AES_256_CBC_SHA;
552 if (ciph.name() ==
"ECDH-ECDSA-NULL-SHA"_L1)
553 return TLS_ECDH_ECDSA_WITH_NULL_SHA;
554 if (ciph.name() ==
"ECDH-ECDSA-RC4-SHA"_L1)
555 return TLS_ECDH_ECDSA_WITH_RC4_128_SHA;
556 if (ciph.name() ==
"ECDH-ECDSA-DES-CBC3-SHA"_L1)
557 return TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA;
558 if (ciph.name() ==
"ECDH-ECDSA-AES128-SHA"_L1)
559 return TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA;
560 if (ciph.name() ==
"ECDH-ECDSA-AES256-SHA"_L1)
561 return TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA;
562 if (ciph.name() ==
"ECDH-ECDSA-RC4-SHA"_L1)
563 return TLS_ECDHE_ECDSA_WITH_RC4_128_SHA;
564 if (ciph.name() ==
"ECDH-ECDSA-DES-CBC3-SHA"_L1)
565 return TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA;
566 if (ciph.name() ==
"ECDH-ECDSA-AES128-SHA"_L1)
567 return TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA;
568 if (ciph.name() ==
"ECDH-ECDSA-AES256-SHA"_L1)
569 return TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA;
570 if (ciph.name() ==
"ECDH-RSA-NULL-SHA"_L1)
571 return TLS_ECDH_RSA_WITH_NULL_SHA;
572 if (ciph.name() ==
"ECDH-RSA-RC4-SHA"_L1)
573 return TLS_ECDH_RSA_WITH_RC4_128_SHA;
574 if (ciph.name() ==
"ECDH-RSA-DES-CBC3-SHA"_L1)
575 return TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA;
576 if (ciph.name() ==
"ECDH-RSA-AES128-SHA"_L1)
577 return TLS_ECDH_RSA_WITH_AES_128_CBC_SHA;
578 if (ciph.name() ==
"ECDH-RSA-AES256-SHA"_L1)
579 return TLS_ECDH_RSA_WITH_AES_256_CBC_SHA;
580 if (ciph.name() ==
"ECDH-RSA-RC4-SHA"_L1)
581 return TLS_ECDHE_RSA_WITH_RC4_128_SHA;
582 if (ciph.name() ==
"ECDH-RSA-DES-CBC3-SHA"_L1)
583 return TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA;
584 if (ciph.name() ==
"ECDH-RSA-AES128-SHA"_L1)
585 return TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA;
586 if (ciph.name() ==
"ECDH-RSA-AES256-SHA"_L1)
587 return TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA;
588 if (ciph.name() ==
"DES-CBC3-SHA"_L1)
589 return TLS_RSA_WITH_3DES_EDE_CBC_SHA;
590 if (ciph.name() ==
"AES128-SHA256"_L1)
591 return TLS_RSA_WITH_AES_128_CBC_SHA256;
592 if (ciph.name() ==
"AES256-SHA256"_L1)
593 return TLS_RSA_WITH_AES_256_CBC_SHA256;
594 if (ciph.name() ==
"DHE-RSA-DES-CBC3-SHA"_L1)
595 return TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA;
596 if (ciph.name() ==
"DHE-RSA-AES128-SHA256"_L1)
597 return TLS_DHE_RSA_WITH_AES_128_CBC_SHA256;
598 if (ciph.name() ==
"DHE-RSA-AES256-SHA256"_L1)
599 return TLS_DHE_RSA_WITH_AES_256_CBC_SHA256;
600 if (ciph.name() ==
"AES256-GCM-SHA384"_L1)
601 return TLS_RSA_WITH_AES_256_GCM_SHA384;
602 if (ciph.name() ==
"ECDHE-ECDSA-AES128-SHA256"_L1)
603 return TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256;
604 if (ciph.name() ==
"ECDHE-ECDSA-AES256-SHA384"_L1)
605 return TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384;
606 if (ciph.name() ==
"ECDH-ECDSA-AES128-SHA256"_L1)
607 return TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256;
608 if (ciph.name() ==
"ECDH-ECDSA-AES256-SHA384"_L1)
609 return TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384;
610 if (ciph.name() ==
"ECDHE-RSA-AES128-SHA256"_L1)
611 return TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256;
612 if (ciph.name() ==
"ECDHE-RSA-AES256-SHA384"_L1)
613 return TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384;
614 if (ciph.name() ==
"ECDHE-RSA-AES256-SHA384"_L1)
615 return TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256;
616 if (ciph.name() ==
"ECDHE-RSA-AES256-GCM-SHA384"_L1)
617 return TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384;
618 if (ciph.name() ==
"AES128-GCM-SHA256"_L1)
619 return TLS_AES_128_GCM_SHA256;
620 if (ciph.name() ==
"AES256-GCM-SHA384"_L1)
621 return TLS_AES_256_GCM_SHA384;
622 if (ciph.name() ==
"CHACHA20-POLY1305-SHA256"_L1)
623 return TLS_CHACHA20_POLY1305_SHA256;
624 if (ciph.name() ==
"AES128-CCM-SHA256"_L1)
625 return TLS_AES_128_CCM_SHA256;
626 if (ciph.name() ==
"AES128-CCM8-SHA256"_L1)
627 return TLS_AES_128_CCM_8_SHA256;
628 if (ciph.name() ==
"ECDHE-ECDSA-AES128-GCM-SHA256"_L1)
629 return TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256;
630 if (ciph.name() ==
"ECDHE-ECDSA-AES256-GCM-SHA384"_L1)
631 return TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384;
632 if (ciph.name() ==
"ECDH-ECDSA-AES128-GCM-SHA256"_L1)
633 return TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256;
634 if (ciph.name() ==
"ECDH-ECDSA-AES256-GCM-SHA384"_L1)
635 return TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384;
636 if (ciph.name() ==
"ECDHE-RSA-AES128-GCM-SHA256"_L1)
637 return TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256;
638 if (ciph.name() ==
"ECDH-RSA-AES128-GCM-SHA256"_L1)
639 return TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256;
640 if (ciph.name() ==
"ECDH-RSA-AES256-GCM-SHA384"_L1)
641 return TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384;
642 if (ciph.name() ==
"ECDHE-RSA-CHACHA20-POLY1305-SHA256"_L1)
643 return TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256;
644 if (ciph.name() ==
"ECDHE-ECDSA-CHACHA20-POLY1305-SHA256"_L1)
645 return TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256;
655 Q_ASSERT_X(!context, Q_FUNC_INFO,
"invalid socket state, context is not null");
656 auto *plainSocket = d->plainTcpSocket();
657 Q_ASSERT(plainSocket);
659 const auto mode = d->tlsMode();
661 context.reset(qt_createSecureTransportContext(mode));
663 setErrorAndEmit(d, QAbstractSocket::SslInternalError, QStringLiteral(
"SSLCreateContext failed"));
667 const OSStatus err = SSLSetIOFuncs(context,
668 reinterpret_cast<SSLReadFunc>(&TlsCryptographSecureTransport::ReadCallback),
669 reinterpret_cast<SSLWriteFunc>(&TlsCryptographSecureTransport::WriteCallback));
670 if (err != errSecSuccess) {
672 setErrorAndEmit(d, QAbstractSocket::SslInternalError,
673 QStringLiteral(
"SSLSetIOFuncs failed: %1").arg(err));
677 SSLSetConnection(context,
this);
679 const auto &configuration = q->sslConfiguration();
680 if (mode == QSslSocket::SslServerMode
681 && !configuration.localCertificateChain().isEmpty()) {
682 QString errorDescription;
683 QAbstractSocket::SocketError errorCode = QAbstractSocket::UnknownSocketError;
684 if (!setSessionCertificate(errorDescription, errorCode)) {
686 setErrorAndEmit(d, errorCode, errorDescription);
691 if (!setSessionProtocol()) {
693 setErrorAndEmit(d, QAbstractSocket::SslInternalError, QStringLiteral(
"Failed to set protocol version"));
697 const auto protocolNames = configuration.allowedNextProtocols();
698 QCFType<CFMutableArrayRef> cfNames(CFArrayCreateMutable(
nullptr, 0, &kCFTypeArrayCallBacks));
700 for (
const QByteArray &name : protocolNames) {
701 if (name.size() > 255) {
702 qCWarning(lcSecureTransport) <<
"TLS ALPN extension" << name
703 <<
"is too long and will be ignored.";
705 }
else if (name.isEmpty()) {
708 QCFString cfName(QString::fromLatin1(name).toCFString());
709 CFArrayAppendValue(cfNames, cfName);
712 if (CFArrayGetCount(cfNames)) {
716 if (SSLSetALPNProtocols(context, cfNames) != errSecSuccess)
717 qCWarning(lcSecureTransport) <<
"SSLSetALPNProtocols failed - too long protocol names?";
720 qCWarning(lcSecureTransport) <<
"failed to allocate ALPN names array";
723 if (mode == QSslSocket::SslClientMode) {
725 const auto verificationPeerName = d->verificationName();
726 QString tlsHostName(verificationPeerName.isEmpty() ? q->peerName() : verificationPeerName);
727 if (tlsHostName.isEmpty())
728 tlsHostName = d->tlsHostName();
730 const QByteArray ace(QUrl::toAce(tlsHostName));
731 SSLSetPeerDomainName(context, ace.data(), ace.size());
733 OSStatus err = SSLSetSessionOption(context, kSSLSessionOptionBreakOnServerAuth,
true);
734 if (err == errSecSuccess)
735 err = SSLSetSessionOption(context, kSSLSessionOptionBreakOnCertRequested,
true);
737 if (err != errSecSuccess) {
739 setErrorAndEmit(d, QSslSocket::SslInternalError,
740 QStringLiteral(
"SSLSetSessionOption failed: %1").arg(err));
745 if (configuration.peerVerifyMode() != QSslSocket::VerifyNone) {
747 OSStatus err = SSLSetClientSideAuthenticate(context, kTryAuthenticate);
748 if (err == errSecSuccess) {
751 err = SSLSetSessionOption(context, kSSLSessionOptionBreakOnClientAuth,
true);
754 if (err != errSecSuccess) {
756 setErrorAndEmit(d, QAbstractSocket::SslInternalError,
757 QStringLiteral(
"failed to set SSL context option in server mode: %1").arg(err));
761#if !defined(QT_PLATFORM_UIKIT)
763 SSLSetDiffieHellmanParams(context, dhparam,
sizeof(
dhparam));
766 if (configuration.ciphers().size() > 0) {
767 QVector<SSLCipherSuite> cfCiphers;
768 for (
const QSslCipher &cipher : configuration.ciphers()) {
769 if (
auto sslCipher = TlsCryptographSecureTransport::SSLCipherSuite_from_QSslCipher(cipher))
770 cfCiphers << sslCipher;
772 if (cfCiphers.size() == 0) {
773 qCWarning(lcSecureTransport) <<
"failed to add any of the requested ciphers from the configuration";
776 OSStatus err = SSLSetEnabledCiphers(context, cfCiphers.data(), cfCiphers.size());
777 if (err != errSecSuccess) {
778 qCWarning(lcSecureTransport) <<
"failed to set the ciphers from the configuration";
787 context.reset(
nullptr);
792 Q_ASSERT_X(context, Q_FUNC_INFO,
"invalid SSL context (null)");
795 const auto &configuration = q->sslConfiguration();
797#ifdef QSSLSOCKET_DEBUG
798 auto *plainSocket = d->plainTcpSocket();
801 QSslCertificate localCertificate;
803 if (!configuration.localCertificateChain().isEmpty())
804 localCertificate = configuration.localCertificateChain().at(0);
806 if (!localCertificate.isNull()) {
808 if (configuration.privateKey().isNull()) {
809 errorCode = QAbstractSocket::SslInvalidUserDataError;
810 errorDescription = QStringLiteral(
"Cannot provide a certificate with no key");
815 const QString passPhrase(QString::fromLatin1(
"foobar"));
816 QCFType<CFDataRef> pkcs12 = _q_makePkcs12(configuration.localCertificateChain(),
817 configuration.privateKey(), passPhrase).toCFData();
818 QCFType<CFStringRef> password = passPhrase.toCFString();
819 const void *keys[2] = { kSecImportExportPassphrase };
820 const void *values[2] = { password };
823#if QT_MACOS_IOS_PLATFORM_SDK_EQUAL_OR_ABOVE(150000
, 180000
)
829 if (
__builtin_available(macOS 15, *)) {
831 keys[1] = kSecImportToMemoryOnly;
832 values[1] = kCFBooleanTrue;
838 const int env = qEnvironmentVariableIntValue(
"QT_SSL_USE_TEMPORARY_KEYCHAIN", &envOk);
840 static const EphemeralSecKeychain temporaryKeychain;
841 if (temporaryKeychain.keychain) {
843 keys[1] = kSecImportExportKeychain;
844 values[1] = temporaryKeychain.keychain;
849 QCFType<CFDictionaryRef> options = CFDictionaryCreate(
nullptr, keys, values, nKeys,
851 QCFType<CFArrayRef> items;
852 OSStatus err = SecPKCS12Import(pkcs12, options, &items);
853 if (err != errSecSuccess) {
854#ifdef QSSLSOCKET_DEBUG
855 qCWarning(lcSecureTransport) << plainSocket
856 << QStringLiteral(
"SecPKCS12Import failed: %1").arg(err);
858 errorCode = QAbstractSocket::SslInvalidUserDataError;
859 errorDescription = QStringLiteral(
"SecPKCS12Import failed: %1").arg(err);
863 if (!CFArrayGetCount(items)) {
864#ifdef QSSLSOCKET_DEBUG
865 qCWarning(lcSecureTransport) << plainSocket <<
"SecPKCS12Import returned no items";
867 errorCode = QAbstractSocket::SslInvalidUserDataError;
868 errorDescription = QStringLiteral(
"SecPKCS12Import returned no items");
872 CFDictionaryRef import = (CFDictionaryRef)CFArrayGetValueAtIndex(items, 0);
873 SecIdentityRef identity = (SecIdentityRef)CFDictionaryGetValue(import, kSecImportItemIdentity);
875#ifdef QSSLSOCKET_DEBUG
876 qCWarning(lcSecureTransport) << plainSocket <<
"SecPKCS12Import returned no identity";
878 errorCode = QAbstractSocket::SslInvalidUserDataError;
879 errorDescription = QStringLiteral(
"SecPKCS12Import returned no identity");
883 QCFType<CFMutableArrayRef> certs = CFArrayCreateMutable(
nullptr, 0, &kCFTypeArrayCallBacks);
885 errorCode = QAbstractSocket::SslInternalError;
886 errorDescription = QStringLiteral(
"Failed to allocate certificates array");
890 CFArrayAppendValue(certs, identity);
892 CFArrayRef chain = (CFArrayRef)CFDictionaryGetValue(import, kSecImportItemCertChain);
894 for (CFIndex i = 1, e = CFArrayGetCount(chain); i < e; ++i)
895 CFArrayAppendValue(certs, CFArrayGetValueAtIndex(chain, i));
898 err = SSLSetCertificate(context, certs);
899 if (err != errSecSuccess) {
900#ifdef QSSLSOCKET_DEBUG
901 qCWarning(lcSecureTransport) << plainSocket
902 << QStringLiteral(
"Cannot set certificate and key: %1").arg(err);
904 errorCode = QAbstractSocket::SslInvalidUserDataError;
905 errorDescription = QStringLiteral(
"Cannot set certificate and key: %1").arg(err);
915 Q_ASSERT_X(context, Q_FUNC_INFO,
"invalid SSL context (null)");
922 const auto &configuration = q->sslConfiguration();
923 auto *plainSocket = d->plainTcpSocket();
924 switch (configuration.protocol()) {
926 case QSsl::TlsV1_3OrLater:
927 qCWarning(lcSecureTransport) << plainSocket <<
"SecureTransport does not support TLS 1.3";
932 OSStatus err = errSecSuccess;
935QT_WARNING_DISABLE_DEPRECATED
936 if (configuration.protocol() == QSsl::TlsV1_0) {
937 #ifdef QSSLSOCKET_DEBUG
938 qCDebug(lcSecureTransport) << plainSocket <<
"requesting : TLSv1.0";
940 err = SSLSetProtocolVersionMin(context, kTLSProtocol1);
941 if (err == errSecSuccess)
942 err = SSLSetProtocolVersionMax(context, kTLSProtocol1);
943 }
else if (configuration.protocol() == QSsl::TlsV1_1) {
944 #ifdef QSSLSOCKET_DEBUG
945 qCDebug(lcSecureTransport) << plainSocket <<
"requesting : TLSv1.1";
947 err = SSLSetProtocolVersionMin(context, kTLSProtocol11);
948 if (err == errSecSuccess)
949 err = SSLSetProtocolVersionMax(context, kTLSProtocol11);
951 }
else if (configuration.protocol() == QSsl::TlsV1_2) {
952 #ifdef QSSLSOCKET_DEBUG
953 qCDebug(lcSecureTransport) << plainSocket <<
"requesting : TLSv1.2";
955 err = SSLSetProtocolVersionMin(context, kTLSProtocol12);
956 if (err == errSecSuccess)
957 err = SSLSetProtocolVersionMax(context, kTLSProtocol12);
958 }
else if (configuration.protocol() == QSsl::AnyProtocol) {
959 #ifdef QSSLSOCKET_DEBUG
960 qCDebug(lcSecureTransport) << plainSocket <<
"requesting : any";
962 err = SSLSetProtocolVersionMin(context, kTLSProtocol1);
963 }
else if (configuration.protocol() == QSsl::SecureProtocols) {
964 #ifdef QSSLSOCKET_DEBUG
965 qCDebug(lcSecureTransport) << plainSocket <<
"requesting : TLSv1.2";
967 err = SSLSetProtocolVersionMin(context, kTLSProtocol12);
969QT_WARNING_DISABLE_DEPRECATED
970 }
else if (configuration.protocol() == QSsl::TlsV1_0OrLater) {
971 #ifdef QSSLSOCKET_DEBUG
972 qCDebug(lcSecureTransport) << plainSocket <<
"requesting : TLSv1 - TLSv1.2";
974 err = SSLSetProtocolVersionMin(context, kTLSProtocol1);
975 }
else if (configuration.protocol() == QSsl::TlsV1_1OrLater) {
976 #ifdef QSSLSOCKET_DEBUG
977 qCDebug(lcSecureTransport) << plainSocket <<
"requesting : TLSv1.1 - TLSv1.2";
979 err = SSLSetProtocolVersionMin(context, kTLSProtocol11);
981 }
else if (configuration.protocol() == QSsl::TlsV1_2OrLater) {
982 #ifdef QSSLSOCKET_DEBUG
983 qCDebug(lcSecureTransport) << plainSocket <<
"requesting : TLSv1.2";
985 err = SSLSetProtocolVersionMin(context, kTLSProtocol12);
987 #ifdef QSSLSOCKET_DEBUG
988 qCDebug(lcSecureTransport) << plainSocket <<
"no protocol version found in the configuration";
993 return err == errSecSuccess;
1000 const auto &configuration = q->sslConfiguration();
1001 const QSslSocket::PeerVerifyMode verifyMode = configuration.peerVerifyMode();
1002 return d->tlsMode() == QSslSocket::SslServerMode
1003 && (verifyMode == QSslSocket::QueryPeer
1004 || verifyMode == QSslSocket::AutoVerifyPeer
1005 || verifyMode == QSslSocket::VerifyNone);
1012 const auto &configuration = q->sslConfiguration();
1013 bool protocolOk =
false;
1014 if (configuration.protocol() == QSsl::AnyProtocol)
1016 else if (configuration.protocol() == QSsl::SecureProtocols)
1017 protocolOk = (sessionProtocol() >= QSsl::TlsV1_2);
1019QT_WARNING_DISABLE_DEPRECATED
1020 else if (configuration.protocol() == QSsl::TlsV1_0OrLater)
1021 protocolOk = (sessionProtocol() >= QSsl::TlsV1_0);
1022 else if (configuration.protocol() == QSsl::TlsV1_1OrLater)
1023 protocolOk = (sessionProtocol() >= QSsl::TlsV1_1);
1025 else if (configuration.protocol() == QSsl::TlsV1_2OrLater)
1026 protocolOk = (sessionProtocol() >= QSsl::TlsV1_2);
1027 else if (configuration.protocol() == QSsl::TlsV1_3OrLater)
1028 protocolOk = (sessionProtocol() >= QSsl::TlsV1_3OrLater);
1030 protocolOk = (sessionProtocol() == configuration.protocol());
1040 const auto mode = d->tlsMode();
1041 const QSslSocket::PeerVerifyMode verifyMode = q->peerVerifyMode();
1042 const bool canIgnoreVerify = canIgnoreTrustVerificationFailure();
1044 Q_ASSERT_X(context, Q_FUNC_INFO,
"invalid SSL context (null)");
1046 auto *plainSocket = d->plainTcpSocket();
1047 Q_ASSERT(plainSocket);
1049 QCFType<SecTrustRef> trust;
1050 OSStatus err = SSLCopyPeerTrust(context, &trust);
1052 if (err != errSecSuccess || !trust) {
1053 if (!canIgnoreVerify) {
1054 setErrorAndEmit(d, QAbstractSocket::SslHandshakeFailedError,
1055 QStringLiteral(
"Failed to obtain peer trust: %1").arg(err));
1056 plainSocket->disconnectFromHost();
1063 QList<QSslError> errors;
1071 SecTrustResultType res = kSecTrustResultInvalid;
1072 err = SecTrustEvaluate(trust, &res);
1073 if (err != errSecSuccess) {
1076 setErrorAndEmit(d, QAbstractSocket::SslHandshakeFailedError,
1077 QStringLiteral(
"SecTrustEvaluate failed: %1").arg(err));
1078 plainSocket->disconnectFromHost();
1082 QTlsBackend::clearPeerCertificates(d);
1084 QList<QSslCertificate> peerCertificateChain;
1085 const CFIndex certCount = SecTrustGetCertificateCount(trust);
1086 for (CFIndex i = 0; i < certCount; ++i) {
1087 SecCertificateRef cert = SecTrustGetCertificateAtIndex(trust, i);
1088 QCFType<CFDataRef> derData = SecCertificateCopyData(cert);
1089 peerCertificateChain << QSslCertificate(QByteArray::fromCFData(derData), QSsl::Der);
1091 QTlsBackend::storePeerCertificateChain(d, peerCertificateChain);
1093 if (peerCertificateChain.size())
1094 QTlsBackend::storePeerCertificate(d, peerCertificateChain.at(0));
1097 for (
const QSslCertificate &cert : std::as_const(peerCertificateChain)) {
1098 if (QSslCertificatePrivate::isBlacklisted(cert) && !canIgnoreVerify) {
1099 const QSslError error(QSslError::CertificateBlacklisted, cert);
1101 emit q->peerVerifyError(error);
1102 if (q->state() != QAbstractSocket::ConnectedState)
1107 const bool doVerifyPeer = verifyMode == QSslSocket::VerifyPeer
1108 || (verifyMode == QSslSocket::AutoVerifyPeer
1109 && d->tlsMode() == QSslSocket::SslClientMode);
1113 const auto &peerCertificate = q->peerCertificate();
1114 if (!peerCertificate.isNull()) {
1117 const QString verificationPeerName = d->verificationName();
1118 if (mode == QSslSocket::SslClientMode) {
1119 const QString peerName(verificationPeerName.isEmpty () ? q->peerName() : verificationPeerName);
1120 if (!isMatchingHostname(peerCertificate, peerName) && !canIgnoreVerify) {
1122 const QSslError error(QSslError::HostNameMismatch, peerCertificate);
1124 emit q->peerVerifyError(error);
1125 if (q->state() != QAbstractSocket::ConnectedState)
1132 if (doVerifyPeer && !canIgnoreVerify) {
1133 const QSslError error(QSslError::NoPeerCertificate);
1135 emit q->peerVerifyError(error);
1136 if (q->state() != QAbstractSocket::ConnectedState)
1142 QCFType<CFMutableArrayRef> certArray = CFArrayCreateMutable(
nullptr, 0, &kCFTypeArrayCallBacks);
1143 const auto &caCertificates = q->sslConfiguration().caCertificates();
1144 for (
const QSslCertificate &cert : caCertificates) {
1145 QCFType<CFDataRef> certData = cert.toDer().toCFData();
1146 if (QCFType<SecCertificateRef> secRef = SecCertificateCreateWithData(
nullptr, certData))
1147 CFArrayAppendValue(certArray, secRef);
1150 SecTrustSetAnchorCertificates(trust, certArray);
1171 bool anchorsFromConfigurationOnly =
false;
1174 if (QOperatingSystemVersion::current() >= QOperatingSystemVersion::MacOSSierra)
1175 anchorsFromConfigurationOnly =
true;
1178 SecTrustSetAnchorCertificatesOnly(trust, anchorsFromConfigurationOnly);
1180 SecTrustResultType trustResult = kSecTrustResultInvalid;
1181 SecTrustEvaluate(trust, &trustResult);
1182 switch (trustResult) {
1183 case kSecTrustResultUnspecified:
1184 case kSecTrustResultProceed:
1187 if (!canIgnoreVerify) {
1188 const QSslError error(QSslError::CertificateUntrusted, peerCertificate);
1190 emit q->peerVerifyError(error);
1195 if (!errors.isEmpty() && !canIgnoreVerify) {
1200 if (!checkSslErrors() || q->state() != QAbstractSocket::ConnectedState)
1210
1211
1214 if (sslErrors.isEmpty())
1220 emit q->sslErrors(sslErrors);
1221 const auto mode = d->tlsMode();
1222 const auto &configuration = q->sslConfiguration();
1223 const bool doVerifyPeer = configuration.peerVerifyMode() == QSslSocket::VerifyPeer
1224 || (configuration.peerVerifyMode() == QSslSocket::AutoVerifyPeer
1225 && mode == QSslSocket::SslClientMode);
1226 const bool doEmitSslError = !d->verifyErrorsHaveBeenIgnored();
1228 if (doVerifyPeer && doEmitSslError) {
1229 if (q->pauseMode() & QAbstractSocket::PauseOnSslErrors) {
1230 QSslSocketPrivate::pauseSocketNotifiers(q);
1233 setErrorAndEmit(d, QAbstractSocket::SslHandshakeFailedError,
1234 sslErrors.constFirst().errorString());
1235 Q_ASSERT(d->plainTcpSocket());
1236 d->plainTcpSocket()->disconnectFromHost();
1250 auto *plainSocket = d->plainTcpSocket();
1251 Q_ASSERT(plainSocket);
1252 const auto mode = d->tlsMode();
1254 OSStatus err = SSLHandshake(context);
1255#ifdef QSSLSOCKET_DEBUG
1256 qCDebug(lcSecureTransport) << plainSocket <<
"SSLHandhake returned" << err;
1259 if (err == errSSLWouldBlock) {
1262 }
else if (err == errSSLServerAuthCompleted) {
1269 return startHandshake();
1270 }
else if (err == errSSLClientCertRequested) {
1271 Q_ASSERT(mode == QSslSocket::SslClientMode);
1272 QString errorDescription;
1273 QAbstractSocket::SocketError errorCode = QAbstractSocket::UnknownSocketError;
1276 if (!setSessionCertificate(errorDescription, errorCode)) {
1277 setErrorAndEmit(d, errorCode, errorDescription);
1278 renegotiating =
false;
1283 return startHandshake();
1285 }
else if (err != errSecSuccess) {
1286 if (err == errSSLBadCert && canIgnoreTrustVerificationFailure()) {
1290 return startHandshake();
1293 renegotiating =
false;
1294 setErrorAndEmit(d, QAbstractSocket::SslHandshakeFailedError,
1295 QStringLiteral(
"SSLHandshake failed: %1").arg(err));
1296 plainSocket->disconnectFromHost();
1301 if (q->state() != QAbstractSocket::ConnectedState) {
1302 qCDebug(lcSecureTransport) <<
"connection aborted";
1303 renegotiating =
false;
1309 if (!verifySessionProtocol()) {
1310 setErrorAndEmit(d, QAbstractSocket::SslHandshakeFailedError, QStringLiteral(
"Protocol version mismatch"));
1311 plainSocket->disconnectFromHost();
1312 renegotiating =
false;
1316 if (verifyPeerTrust()) {
1318 renegotiating =
false;
1321 renegotiating =
false;
1329 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)