aboutsummaryrefslogtreecommitdiffstats
path: root/src/libs/ssh/sshkeyexchange.cpp
diff options
context:
space:
mode:
authorChristian Kandeler <[email protected]>2015-06-23 12:53:30 +0200
committerChristian Kandeler <[email protected]>2015-06-24 10:34:31 +0000
commitf8a8c6cac3f7e1955025e72dde451e00c10a1077 (patch)
tree23e4271cd7ab80a81bc1762f93a5df58b02d3381 /src/libs/ssh/sshkeyexchange.cpp
parent3c1b1496d43d41e6a628b14abe0172f34a866151 (diff)
SSH: Do not tie key exchange methods to specific host key algorithms.
Contrary to what I believed, all key exchange methods are compatible with all types of host key (at least for everything we support). Task-number: QTCREATORBUG-14621 Change-Id: Iacae3d36170b9841cceb3705780a64aeb15e10b9 Reviewed-by: Benjamin Zeller <[email protected]> Reviewed-by: Christian Kandeler <[email protected]>
Diffstat (limited to 'src/libs/ssh/sshkeyexchange.cpp')
-rw-r--r--src/libs/ssh/sshkeyexchange.cpp44
1 files changed, 13 insertions, 31 deletions
diff --git a/src/libs/ssh/sshkeyexchange.cpp b/src/libs/ssh/sshkeyexchange.cpp
index c553ecc8b22..62071e4fc70 100644
--- a/src/libs/ssh/sshkeyexchange.cpp
+++ b/src/libs/ssh/sshkeyexchange.cpp
@@ -30,6 +30,7 @@
#include "sshkeyexchange_p.h"
+#include "ssh_global.h"
#include "sshbotanconversions_p.h"
#include "sshcapabilities_p.h"
#include "sshsendfacility_p.h"
@@ -115,28 +116,8 @@ bool SshKeyExchange::sendDhInitPacket(const SshIncomingPacket &serverKexInit)
m_kexAlgoName = SshCapabilities::findBestMatch(SshCapabilities::KeyExchangeMethods,
kexInitParams.keyAlgorithms.names);
- const QList<QByteArray> &commonHostKeyAlgos
- = SshCapabilities::commonCapabilities(SshCapabilities::PublicKeyAlgorithms,
- kexInitParams.serverHostKeyAlgorithms.names);
- const bool ecdh = m_kexAlgoName.startsWith(SshCapabilities::EcdhKexNamePrefix);
- foreach (const QByteArray &possibleHostKeyAlgo, commonHostKeyAlgos) {
- if (ecdh && possibleHostKeyAlgo == SshCapabilities::PubKeyEcdsa) {
- m_serverHostKeyAlgo = possibleHostKeyAlgo;
- break;
- }
- if (!ecdh && (possibleHostKeyAlgo == SshCapabilities::PubKeyDss
- || possibleHostKeyAlgo == SshCapabilities::PubKeyRsa)) {
- m_serverHostKeyAlgo = possibleHostKeyAlgo;
- break;
- }
- }
- if (m_serverHostKeyAlgo.isEmpty()) {
- throw SshServerException(SSH_DISCONNECT_KEY_EXCHANGE_FAILED,
- "Invalid combination of key exchange and host key algorithms.",
- QCoreApplication::translate("SshConnection",
- "No matching host key algorithm available for key exchange algorithm \"%1\".")
- .arg(QString::fromLatin1(m_kexAlgoName)));
- }
+ m_serverHostKeyAlgo = SshCapabilities::findBestMatch(SshCapabilities::PublicKeyAlgorithms,
+ kexInitParams.serverHostKeyAlgorithms.names);
determineHashingAlgorithm(kexInitParams, true);
determineHashingAlgorithm(kexInitParams, false);
@@ -152,7 +133,7 @@ bool SshKeyExchange::sendDhInitPacket(const SshIncomingPacket &serverKexInit)
kexInitParams.compressionAlgorithmsServerToClient.names);
AutoSeeded_RNG rng;
- if (ecdh) {
+ if (m_kexAlgoName.startsWith(SshCapabilities::EcdhKexNamePrefix)) {
m_ecdhKey.reset(new ECDH_PrivateKey(rng, EC_Group(botanKeyExchangeAlgoName(m_kexAlgoName))));
m_sendFacility.sendKeyEcdhInitPacket(convertByteArray(m_ecdhKey->public_value()));
} else {
@@ -169,7 +150,7 @@ void SshKeyExchange::sendNewKeysPacket(const SshIncomingPacket &dhReply,
{
const SshKeyExchangeReply &reply
- = dhReply.extractKeyExchangeReply(m_serverHostKeyAlgo);
+ = dhReply.extractKeyExchangeReply(m_kexAlgoName, m_serverHostKeyAlgo);
if (m_dhKey && (reply.f <= 0 || reply.f >= m_dhKey->group_p())) {
throw SSH_SERVER_EXCEPTION(SSH_DISCONNECT_KEY_EXCHANGE_FAILED,
"Server sent invalid f.");
@@ -187,6 +168,7 @@ void SshKeyExchange::sendNewKeysPacket(const SshIncomingPacket &dhReply,
DH_KA_Operation dhOp(*m_dhKey);
SecureVector<byte> encodedF = BigInt::encode(reply.f);
encodedK = dhOp.agree(encodedF, encodedF.size());
+ m_dhKey.reset(nullptr);
} else {
Q_ASSERT(m_ecdhKey);
concatenatedData // Q_C.
@@ -194,7 +176,9 @@ void SshKeyExchange::sendNewKeysPacket(const SshIncomingPacket &dhReply,
concatenatedData += AbstractSshPacket::encodeString(reply.q_s);
ECDH_KA_Operation ecdhOp(*m_ecdhKey);
encodedK = ecdhOp.agree(convertByteArray(reply.q_s), reply.q_s.count());
+ m_ecdhKey.reset(nullptr);
}
+
const BigInt k = BigInt::decode(encodedK);
m_k = AbstractSshPacket::encodeMpInt(k); // Roundtrip, as Botan encodes BigInts somewhat differently.
concatenatedData += m_k;
@@ -228,13 +212,13 @@ void SshKeyExchange::sendNewKeysPacket(const SshIncomingPacket &dhReply,
RSA_PublicKey * const rsaKey
= new RSA_PublicKey(reply.parameters.at(1), reply.parameters.at(0));
sigKey.reset(rsaKey);
- } else if (m_serverHostKeyAlgo == SshCapabilities::PubKeyEcdsa) {
+ } else {
+ QSSH_ASSERT_AND_RETURN(m_serverHostKeyAlgo == SshCapabilities::PubKeyEcdsa);
+ const EC_Group domain("secp256r1");
const PointGFp point = OS2ECP(convertByteArray(reply.q), reply.q.count(),
- m_ecdhKey->domain().get_curve());
- ECDSA_PublicKey * const ecdsaKey = new ECDSA_PublicKey(m_ecdhKey->domain(), point);
+ domain.get_curve());
+ ECDSA_PublicKey * const ecdsaKey = new ECDSA_PublicKey(domain, point);
sigKey.reset(ecdsaKey);
- } else {
- Q_ASSERT(!"Impossible: Neither DSS nor RSA nor ECDSA!");
}
const byte * const botanH = convertByteArray(m_h);
@@ -248,8 +232,6 @@ void SshKeyExchange::sendNewKeysPacket(const SshIncomingPacket &dhReply,
checkHostKey(reply.k_s);
m_sendFacility.sendNewKeysPacket();
- m_dhKey.reset(nullptr);
- m_ecdhKey.reset(nullptr);
}
QByteArray SshKeyExchange::hashAlgoForKexAlgo() const