From 66ccbcbb37f0f33a4be1abf69c668e90fd4a6eb3 Mon Sep 17 00:00:00 2001 From: Christian Kandeler <christian.kandeler@theqtcompany.com> Date: Fri, 22 May 2015 17:12:38 +0200 Subject: [PATCH] SSH: Minor refactorings in key exchange code. Change-Id: I107a61831ca7824c30dcc83b3a13f5765dd2da52 Reviewed-by: Joerg Bornemann <joerg.bornemann@theqtcompany.com> Reviewed-by: Christian Kandeler <christian.kandeler@theqtcompany.com> --- src/libs/ssh/sshcapabilities.cpp | 17 ++++++++++++++--- src/libs/ssh/sshcapabilities_p.h | 2 ++ src/libs/ssh/sshkeyexchange.cpp | 13 +++++++------ 3 files changed, 23 insertions(+), 9 deletions(-) diff --git a/src/libs/ssh/sshcapabilities.cpp b/src/libs/ssh/sshcapabilities.cpp index 1d70d73a60..6bad151fcd 100644 --- a/src/libs/ssh/sshcapabilities.cpp +++ b/src/libs/ssh/sshcapabilities.cpp @@ -89,14 +89,18 @@ const QList<QByteArray> SshCapabilities::CompressionAlgorithms const QByteArray SshCapabilities::SshConnectionService("ssh-connection"); -QByteArray SshCapabilities::findBestMatch(const QList<QByteArray> &myCapabilities, - const QList<QByteArray> &serverCapabilities) +QList<QByteArray> SshCapabilities::commonCapabilities(const QList<QByteArray> &myCapabilities, + const QList<QByteArray> &serverCapabilities) { + QList<QByteArray> capabilities; foreach (const QByteArray &myCapability, myCapabilities) { if (serverCapabilities.contains(myCapability)) - return myCapability; + capabilities << myCapability; } + if (!capabilities.isEmpty()) + return capabilities; + throw SshServerException(SSH_DISCONNECT_KEY_EXCHANGE_FAILED, "Server and client capabilities do not match.", QCoreApplication::translate("SshConnection", @@ -104,6 +108,13 @@ QByteArray SshCapabilities::findBestMatch(const QList<QByteArray> &myCapabilitie "Client list was: %1.\nServer list was %2.") .arg(QString::fromLocal8Bit(listAsByteArray(myCapabilities).data())) .arg(QString::fromLocal8Bit(listAsByteArray(serverCapabilities).data()))); + +} + +QByteArray SshCapabilities::findBestMatch(const QList<QByteArray> &myCapabilities, + const QList<QByteArray> &serverCapabilities) +{ + return commonCapabilities(myCapabilities, serverCapabilities).first(); } } // namespace Internal diff --git a/src/libs/ssh/sshcapabilities_p.h b/src/libs/ssh/sshcapabilities_p.h index d0295fccd0..1a82ae1ef2 100644 --- a/src/libs/ssh/sshcapabilities_p.h +++ b/src/libs/ssh/sshcapabilities_p.h @@ -65,6 +65,8 @@ public: static const QByteArray SshConnectionService; + static QList<QByteArray> commonCapabilities(const QList<QByteArray> &myCapabilities, + const QList<QByteArray> &serverCapabilities); static QByteArray findBestMatch(const QList<QByteArray> &myCapabilities, const QList<QByteArray> &serverCapabilities); }; diff --git a/src/libs/ssh/sshkeyexchange.cpp b/src/libs/ssh/sshkeyexchange.cpp index 12c2607648..1f90417c1f 100644 --- a/src/libs/ssh/sshkeyexchange.cpp +++ b/src/libs/ssh/sshkeyexchange.cpp @@ -162,8 +162,11 @@ void SshKeyExchange::sendNewKeysPacket(const SshIncomingPacket &dhReply, concatenatedData += reply.k_s; concatenatedData += AbstractSshPacket::encodeMpInt(m_dhKey->get_y()); concatenatedData += AbstractSshPacket::encodeMpInt(reply.f); - const BigInt k = power_mod(reply.f, m_dhKey->get_x(), m_dhKey->get_domain().get_p()); - m_k = AbstractSshPacket::encodeMpInt(k); + DH_KA_Operation dhOp(*m_dhKey); + SecureVector<byte> encodedF = BigInt::encode(reply.f); + SecureVector<byte> encodedK = dhOp.agree(encodedF, encodedF.size()); + const BigInt k = BigInt::decode(encodedK); + m_k = AbstractSshPacket::encodeMpInt(k); // Roundtrip, as Botan encodes BigInts somewhat differently. concatenatedData += m_k; m_hash.reset(get_hash(botanSha1Name())); @@ -186,26 +189,24 @@ void SshKeyExchange::sendNewKeysPacket(const SshIncomingPacket &dhReply, #endif // CREATOR_SSH_DEBUG QScopedPointer<Public_Key> sigKey; - QScopedPointer<PK_Verifier> verifier; if (m_serverHostKeyAlgo == SshCapabilities::PubKeyDss) { const DL_Group group(reply.parameters.at(0), reply.parameters.at(1), reply.parameters.at(2)); DSA_PublicKey * const dsaKey = new DSA_PublicKey(group, reply.parameters.at(3)); sigKey.reset(dsaKey); - verifier.reset(new PK_Verifier(*dsaKey, botanEmsaAlgoName(SshCapabilities::PubKeyDss))); } else if (m_serverHostKeyAlgo == SshCapabilities::PubKeyRsa) { RSA_PublicKey * const rsaKey = new RSA_PublicKey(reply.parameters.at(1), reply.parameters.at(0)); sigKey.reset(rsaKey); - verifier.reset(new PK_Verifier(*rsaKey, botanEmsaAlgoName(SshCapabilities::PubKeyRsa))); } else { Q_ASSERT(!"Impossible: Neither DSS nor RSA!"); } const byte * const botanH = convertByteArray(m_h); const Botan::byte * const botanSig = convertByteArray(reply.signatureBlob); - if (!verifier->verify_message(botanH, m_h.size(), botanSig, + PK_Verifier verifier(*sigKey, botanEmsaAlgoName(m_serverHostKeyAlgo)); + if (!verifier.verify_message(botanH, m_h.size(), botanSig, reply.signatureBlob.size())) { throw SSH_SERVER_EXCEPTION(SSH_DISCONNECT_KEY_EXCHANGE_FAILED, "Invalid signature in SSH_MSG_KEXDH_REPLY packet."); -- GitLab