AusweisApp2/patches/qt-Make-server-side-signatu...

262 lines
11 KiB
Diff

From b0404383ab573d7550a6564405bb9b1316ff193a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Sebastian=20L=C3=B6sch?= <Sebastian.Loesch@governikus.de>
Date: Thu, 21 Apr 2016 09:19:19 +0200
Subject: [PATCH] Make server side signature algorithms configurable
Signature algorithms are used during the TLS handshake phase to protect
transferred security parameters, e.g the message ServerKeyExchange.
This patch enables the configuration of allowed algorithms used by the
server side.
Change-Id: Ia178efd4778b91863fcc919bf50219115b300d77
---
src/network/ssl/qsslconfiguration.cpp | 42 ++++++++++++++++++++++++
src/network/ssl/qsslconfiguration.h | 8 ++++-
src/network/ssl/qsslconfiguration_p.h | 5 +++
src/network/ssl/qsslcontext_openssl.cpp | 45 ++++++++++++++++++++++++++
src/network/ssl/qsslcontext_openssl_p.h | 1 +
src/network/ssl/qsslsocket.cpp | 2 ++
src/network/ssl/qsslsocket_openssl_symbols_p.h | 5 +++
7 files changed, 107 insertions(+), 1 deletion(-)
diff --git x/qtbase/src/network/ssl/qsslconfiguration.cpp y/qtbase/src/network/ssl/qsslconfiguration.cpp
index 75a880f115..37f99feef1 100644
--- x/qtbase/src/network/ssl/qsslconfiguration.cpp
+++ y/qtbase/src/network/ssl/qsslconfiguration.cpp
@@ -221,6 +221,7 @@ bool QSslConfiguration::operator==(const QSslConfiguration &other) const
d->peerVerifyMode == other.d->peerVerifyMode &&
d->peerVerifyDepth == other.d->peerVerifyDepth &&
d->allowRootCertOnDemandLoading == other.d->allowRootCertOnDemandLoading &&
+ d->signatureAndHashAlgorithms == other.d->signatureAndHashAlgorithms &&
d->sslOptions == other.d->sslOptions &&
d->sslSession == other.d->sslSession &&
d->sslSessionTicketLifeTimeHint == other.d->sslSessionTicketLifeTimeHint &&
@@ -263,6 +264,7 @@ bool QSslConfiguration::isNull() const
d->privateKey.isNull() &&
d->peerCertificate.isNull() &&
d->peerCertificateChain.count() == 0 &&
+ d->signatureAndHashAlgorithms.isEmpty() &&
d->sslOptions == QSslConfigurationPrivate::defaultSslOptions &&
d->sslSession.isNull() &&
d->sslSessionTicketLifeTimeHint == -1 &&
@@ -869,6 +871,46 @@ void QSslConfiguration::setDiffieHellmanParameters(const QSslDiffieHellmanParame
d->dhParams = dhparams;
}
+/*!
+ \since 5.9
+
+ Returns the connection's current list of supported signature
+ algorithms if enabled. Enable it by calling
+ setSignatureAndHashAlgorithms().
+
+ \sa setSignatureAndHashAlgorithms()
+ */
+QVector<QPair<QSsl::KeyAlgorithm, QCryptographicHash::Algorithm> > QSslConfiguration::signatureAndHashAlgorithms() const
+{
+ return d->signatureAndHashAlgorithms;
+}
+
+/*!
+ \since 5.9
+
+ Sets the list of signature algorithms to be used for the current
+ connection. The algorithms are expected to be ordered by descending
+ preference (i.e., the first algorithm is the most preferred one).
+ Notice that this restricts the list of supported ciphers (e.g.
+ configuring the signature algorithm RSA+SHA1 will restrict the ciphers
+ to RSA ciphers).
+
+ When configuring the client side this are the algorithms set in the
+ Signature Algorithms TLS extension, see RFC 5246 for details. Although
+ this extension will be ignored for TLS protocol versions prior 1.2
+ this still restricts the supported ciphers as mentioned above.
+
+ By default, the handshake phase can choose any of the algorithms
+ supported by this system's SSL libraries, which may vary from
+ system to system.
+
+ \sa signatureAndHashAlgorithms()
+ */
+void QSslConfiguration::setSignatureAndHashAlgorithms(const QVector<QPair<QSsl::KeyAlgorithm, QCryptographicHash::Algorithm> > &algorithms)
+{
+ d->signatureAndHashAlgorithms = algorithms;
+}
+
/*!
\since 5.3
diff --git x/qtbase/src/network/ssl/qsslconfiguration.h y/qtbase/src/network/ssl/qsslconfiguration.h
index 1c57bebd65..4d3e5129d5 100644
--- x/qtbase/src/network/ssl/qsslconfiguration.h
+++ y/qtbase/src/network/ssl/qsslconfiguration.h
@@ -56,10 +56,13 @@
#ifndef QSSLCONFIGURATION_H
#define QSSLCONFIGURATION_H
-#include <QtNetwork/qtnetworkglobal.h>
+#include <QtCore/qcryptographichash.h>
+#include <QtCore/qpair.h>
#include <QtCore/qshareddata.h>
+#include <QtCore/qvector.h>
#include <QtNetwork/qsslsocket.h>
#include <QtNetwork/qssl.h>
+#include <QtNetwork/qtnetworkglobal.h>
#ifndef QT_NO_SSL
@@ -149,6 +152,9 @@ public:
QSslDiffieHellmanParameters diffieHellmanParameters() const;
void setDiffieHellmanParameters(const QSslDiffieHellmanParameters &dhparams);
+ QVector<QPair<QSsl::KeyAlgorithm, QCryptographicHash::Algorithm> > signatureAndHashAlgorithms() const;
+ void setSignatureAndHashAlgorithms(const QVector<QPair<QSsl::KeyAlgorithm, QCryptographicHash::Algorithm> > &algorithms);
+
static QSslConfiguration defaultConfiguration();
static void setDefaultConfiguration(const QSslConfiguration &configuration);
diff --git x/qtbase/src/network/ssl/qsslconfiguration_p.h y/qtbase/src/network/ssl/qsslconfiguration_p.h
index 6adf2c9b54..7be253973b 100644
--- x/qtbase/src/network/ssl/qsslconfiguration_p.h
+++ y/qtbase/src/network/ssl/qsslconfiguration_p.h
@@ -75,6 +75,9 @@
#include "qsslkey.h"
#include "qsslellipticcurve.h"
#include "qssldiffiehellmanparameters.h"
+#include <QtCore/qcryptographichash.h>
+#include <QtCore/qpair.h>
+#include <QtCore/qvector.h>
QT_BEGIN_NAMESPACE
@@ -123,6 +126,8 @@ public:
QSslDiffieHellmanParameters dhParams;
+ QVector<QPair<QSsl::KeyAlgorithm, QCryptographicHash::Algorithm> > signatureAndHashAlgorithms;
+
QByteArray sslSession;
int sslSessionTicketLifeTimeHint;
diff --git x/qtbase/src/network/ssl/qsslcontext_openssl.cpp y/qtbase/src/network/ssl/qsslcontext_openssl.cpp
index c92d8fc3f8..29df53abc0 100644
--- x/qtbase/src/network/ssl/qsslcontext_openssl.cpp
+++ y/qtbase/src/network/ssl/qsslcontext_openssl.cpp
@@ -42,6 +42,7 @@
#include <QtNetwork/qsslsocket.h>
#include <QtNetwork/qssldiffiehellmanparameters.h>
+#include <QtCore/qmetaobject.h>
#include <QtCore/qmutex.h>
#include "private/qssl_p.h"
@@ -78,6 +79,11 @@ QSslContext::~QSslContext()
q_SSL_SESSION_free(session);
}
+static inline QString msgErrorSettingSignatureAlgorithms(const QString &why)
+{
+ return QSslSocket::tr("Error when setting the signature algorithms (%1)").arg(why);
+}
+
static inline QString msgErrorSettingEllipticCurves(const QString &why)
{
return QSslSocket::tr("Error when setting the elliptic curves (%1)").arg(why);
@@ -371,6 +377,45 @@ init_context:
sslContext->errorCode = QSslError::UnspecifiedError;
}
}
+
+ const auto& sigAndHashAlgorithms = sslContext->sslConfiguration.signatureAndHashAlgorithms();
+ if (!sigAndHashAlgorithms.isEmpty()) {
+#if OPENSSL_VERSION_NUMBER >= 0x10002000L
+ if (q_SSLeay() >= 0x10002000L) {
+ QMetaEnum hashMetaEnum = QMetaEnum::fromType<QCryptographicHash::Algorithm>();
+ QByteArrayList algorithmList;
+ for (int i=0; i < sigAndHashAlgorithms.size(); ++i) {
+ QByteArray sig;
+ switch (sigAndHashAlgorithms[i].first) {
+ case QSsl::KeyAlgorithm::Rsa:
+ sig = QByteArrayLiteral("RSA");
+ break;
+ case QSsl::KeyAlgorithm::Dsa:
+ sig = QByteArrayLiteral("DSA");
+ break;
+ case QSsl::KeyAlgorithm::Ec:
+ sig = QByteArrayLiteral("ECDSA");
+ break;
+ case QSsl::KeyAlgorithm::Opaque:
+ qCWarning(lcSsl, "Invalid value KeyAlgorithm::Opaque will be ignored");
+ continue;
+ }
+ QByteArray hash = QByteArray(hashMetaEnum.valueToKey(sigAndHashAlgorithms[i].second)).toUpper();
+ algorithmList += sig + QByteArrayLiteral("+") + hash;
+ }
+ QByteArray algorithms = algorithmList.join(':');
+ if (!q_SSL_CTX_set1_sigalgs_list(sslContext->ctx, algorithms.data())) {
+ sslContext->errorStr = msgErrorSettingSignatureAlgorithms(QSslSocketBackendPrivate::getErrorsFromOpenSsl());
+ sslContext->errorCode = QSslError::UnspecifiedError;
+ }
+ } else
+#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L
+ {
+ // specific algorithms requested, but not possible to set -> error
+ sslContext->errorStr = msgErrorSettingSignatureAlgorithms(QSslSocket::tr("OpenSSL version too old, need at least v1.0.2"));
+ sslContext->errorCode = QSslError::UnspecifiedError;
+ }
+ }
}
QSslContext* QSslContext::fromConfiguration(QSslSocket::SslMode mode, const QSslConfiguration &configuration, bool allowRootCertOnDemandLoading)
diff --git x/qtbase/src/network/ssl/qsslcontext_openssl_p.h y/qtbase/src/network/ssl/qsslcontext_openssl_p.h
index 06a31af5e5..c8c8e1941b 100644
--- x/qtbase/src/network/ssl/qsslcontext_openssl_p.h
+++ y/qtbase/src/network/ssl/qsslcontext_openssl_p.h
@@ -54,6 +54,7 @@
//
#include <QtNetwork/private/qtnetworkglobal_p.h>
+#include <QtCore/qobjectdefs.h>
#include <QtCore/qvariant.h>
#include <QtNetwork/qsslcertificate.h>
#include <QtNetwork/qsslconfiguration.h>
diff --git x/qtbase/src/network/ssl/qsslsocket.cpp y/qtbase/src/network/ssl/qsslsocket.cpp
index 8eba5db9fe..c0aa8b9bdf 100644
--- x/qtbase/src/network/ssl/qsslsocket.cpp
+++ y/qtbase/src/network/ssl/qsslsocket.cpp
@@ -922,6 +922,7 @@ void QSslSocket::setSslConfiguration(const QSslConfiguration &configuration)
d->configuration.peerVerifyDepth = configuration.peerVerifyDepth();
d->configuration.peerVerifyMode = configuration.peerVerifyMode();
d->configuration.protocol = configuration.protocol();
+ d->configuration.signatureAndHashAlgorithms = configuration.signatureAndHashAlgorithms();
d->configuration.sslOptions = configuration.d->sslOptions;
d->configuration.sslSession = configuration.sessionTicket();
d->configuration.sslSessionTicketLifeTimeHint = configuration.sessionTicketLifeTimeHint();
@@ -2249,6 +2250,7 @@ void QSslConfigurationPrivate::deepCopyDefaultConfiguration(QSslConfigurationPri
ptr->peerVerifyDepth = global->peerVerifyDepth;
ptr->sslOptions = global->sslOptions;
ptr->ellipticCurves = global->ellipticCurves;
+ ptr->signatureAndHashAlgorithms = global->signatureAndHashAlgorithms;
}
/*!
diff --git x/qtbase/src/network/ssl/qsslsocket_openssl_symbols_p.h y/qtbase/src/network/ssl/qsslsocket_openssl_symbols_p.h
index b35a895d38..d4cd493c45 100644
--- x/qtbase/src/network/ssl/qsslsocket_openssl_symbols_p.h
+++ y/qtbase/src/network/ssl/qsslsocket_openssl_symbols_p.h
@@ -517,6 +517,11 @@ int q_EC_curve_nist2nid(const char *name);
#define q_SSL_get_server_tmp_key(ssl, key) q_SSL_ctrl((ssl), SSL_CTRL_GET_SERVER_TMP_KEY, 0, (char *)key)
#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L
+// Signature algorithm extension
+#if OPENSSL_VERSION_NUMBER >= 0x10002000L
+#define q_SSL_CTX_set1_sigalgs_list(ctx, s) q_SSL_CTX_ctrl((ctx), SSL_CTRL_SET_SIGALGS_LIST, 0, (char *)s)
+#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L
+
// PKCS#12 support
int q_PKCS12_parse(PKCS12 *p12, const char *pass, EVP_PKEY **pkey, X509 **cert, STACK_OF(X509) **ca);
PKCS12 *q_d2i_PKCS12_bio(BIO *bio, PKCS12 **pkcs12);
--
2.15.0