diff options
author | Christian Kandeler <christian.kandeler@qt.io> | 2018-01-03 17:56:52 +0100 |
---|---|---|
committer | Christian Kandeler <christian.kandeler@qt.io> | 2018-08-10 09:23:42 +0000 |
commit | a44fe2e4f03fc18ce9c3d050f71fe369916259b8 (patch) | |
tree | e5f3211ced0bc7fc1628ff5e7a051007dfa18207 /src/libs/ssh | |
parent | 78c4cf9884770149fb9d69f923aa2169baa3f42a (diff) |
SSH: Use Botan2
Botan 1.10 will be completely unsupported by the end of this year, so we
now target API version 2 instead.
Also upgrade our bundled Botan to the latest version 2.7. We no longer
check in pre-processed files, but use the upstream sources directly
(with unneeded parts removed), employing Botan's own configure
script for building. This will make future upgrades much simpler. A
script to automate this process is also provided.
Task-number: QTCREATORBUG-18802
Task-number: QTCREATORBUG-8107
Change-Id: I5a5ea62cfd30d720b556217142e8b7e06bf49f7e
Reviewed-by: hjk <hjk@qt.io>
Reviewed-by: Eike Ziller <eike.ziller@qt.io>
Diffstat (limited to 'src/libs/ssh')
-rw-r--r-- | src/libs/ssh/ssh.pro | 14 | ||||
-rw-r--r-- | src/libs/ssh/ssh.qbs | 76 | ||||
-rw-r--r-- | src/libs/ssh/sshbotanconversions_p.h | 16 | ||||
-rw-r--r-- | src/libs/ssh/sshchannel.cpp | 2 | ||||
-rw-r--r-- | src/libs/ssh/sshconnection.cpp | 14 | ||||
-rw-r--r-- | src/libs/ssh/sshcryptofacility.cpp | 44 | ||||
-rw-r--r-- | src/libs/ssh/sshcryptofacility_p.h | 8 | ||||
-rw-r--r-- | src/libs/ssh/sshinit.cpp | 49 | ||||
-rw-r--r-- | src/libs/ssh/sshinit_p.h | 32 | ||||
-rw-r--r-- | src/libs/ssh/sshkeyexchange.cpp | 30 | ||||
-rw-r--r-- | src/libs/ssh/sshkeyexchange_p.h | 6 | ||||
-rw-r--r-- | src/libs/ssh/sshkeygenerator.cpp | 22 | ||||
-rw-r--r-- | src/libs/ssh/sshkeypasswordretriever.cpp | 8 | ||||
-rw-r--r-- | src/libs/ssh/sshkeypasswordretriever_p.h | 9 | ||||
-rw-r--r-- | src/libs/ssh/sshpacketparser_p.h | 2 | ||||
-rw-r--r-- | src/libs/ssh/sshremoteprocess.cpp | 2 |
16 files changed, 117 insertions, 217 deletions
diff --git a/src/libs/ssh/ssh.pro b/src/libs/ssh/ssh.pro index 499540ac72e..40efcaf96b5 100644 --- a/src/libs/ssh/ssh.pro +++ b/src/libs/ssh/ssh.pro @@ -27,7 +27,6 @@ SOURCES = $$PWD/sshsendfacility.cpp \ $$PWD/sshkeypasswordretriever.cpp \ $$PWD/sftpfilesystemmodel.cpp \ $$PWD/sshkeycreationdialog.cpp \ - $$PWD/sshinit.cpp \ $$PWD/sshdirecttcpiptunnel.cpp \ $$PWD/sshlogging.cpp \ $$PWD/sshhostkeydatabase.cpp \ @@ -69,7 +68,6 @@ HEADERS = $$PWD/sshsendfacility_p.h \ $$PWD/sshkeycreationdialog.h \ $$PWD/ssh_global.h \ $$PWD/sshdirecttcpiptunnel_p.h \ - $$PWD/sshinit_p.h \ $$PWD/sshdirecttcpiptunnel.h \ $$PWD/sshlogging_p.h \ $$PWD/sshhostkeydatabase.h \ @@ -84,4 +82,14 @@ FORMS = $$PWD/sshkeycreationdialog.ui RESOURCES += $$PWD/ssh.qrc -include(../3rdparty/botan/botan.pri) +include(../botan/botan.pri) +use_system_botan { + CONFIG += link_pkgconfig + PKGCONFIG += botan-2 +} else { + BOTAN_BUILD_DIR = $$OUT_PWD/../botan/$$BOTAN_BUILD_DIR + INCLUDEPATH += $$BOTAN_BUILD_DIR/build/include + LIBS += $$BOTAN_BUILD_DIR/$$BOTAN_FULL_NAME + win32: LIBS += -ladvapi32 -luser32 -lws2_32 +} +msvc:QMAKE_CXXFLAGS += /wd4250 diff --git a/src/libs/ssh/ssh.qbs b/src/libs/ssh/ssh.qbs index 3aa95a16d53..b635b7037f0 100644 --- a/src/libs/ssh/ssh.qbs +++ b/src/libs/ssh/ssh.qbs @@ -7,12 +7,18 @@ Project { QtcDevHeaders { } QtcLibrary { - cpp.defines: base.concat(["QTCSSH_LIBRARY"]).concat(botanDefines) + cpp.defines: base.concat("QTCSSH_LIBRARY") cpp.includePaths: botanIncludes cpp.dynamicLibraries: botanLibs cpp.enableExceptions: true + Properties { + condition: qbs.toolchain.contains("msvc") + cpp.cxxFlags: base.concat("/wd4250"); + } + Depends { name: "Qt"; submodules: ["widgets", "network" ] } + Depends { name: "Botan"; condition: !qtc.useSystemBotan } files: [ "sftpchannel.h", "sftpchannel_p.h", "sftpchannel.cpp", @@ -38,7 +44,6 @@ Project { "sshhostkeydatabase.cpp", "sshhostkeydatabase.h", "sshincomingpacket_p.h", "sshincomingpacket.cpp", - "sshinit_p.h", "sshinit.cpp", "sshkeycreationdialog.cpp", "sshkeycreationdialog.h", "sshkeycreationdialog.ui", "sshkeyexchange.cpp", "sshkeyexchange_p.h", "sshkeygenerator.cpp", "sshkeygenerator.h", @@ -54,21 +59,15 @@ Project { "sshsendfacility.cpp", "sshsendfacility_p.h", "sshtcpipforwardserver.cpp", "sshtcpipforwardserver.h", "sshtcpipforwardserver_p.h", "sshtcpiptunnel.cpp", "sshtcpiptunnel_p.h", - ].concat(botanFiles) + ] - property var useSystemBotan: Environment.getEnv("USE_SYSTEM_BOTAN") === "1" - property var botanIncludes: { - var result = ["../3rdparty"]; - if (useSystemBotan) - result.push("/usr/include/botan-1.10") - return result - } + property var botanIncludes: qtc.useSystemBotan ? ["/usr/include/botan-2"] : [] property var botanLibs: { var result = []; - if (useSystemBotan) - result.push("botan-1.10") + if (qtc.useSystemBotan) + result.push("botan-2") if (qbs.targetOS.contains("windows")) - result.push("advapi32", "user32") + result.push("advapi32", "user32", "ws2_32") else if (qbs.targetOS.contains("linux")) result.push("rt", "dl"); else if (qbs.targetOS.contains("macos")) @@ -77,57 +76,6 @@ Project { result.push("rt"); return result } - property var botanDefines: { - var result = []; - if (useSystemBotan) { - result.push("USE_SYSTEM_BOTAN") - } else { - result.push("BOTAN_DLL=") - if (qbs.toolchain.contains("msvc")) - result.push("BOTAN_BUILD_COMPILER_IS_MSVC", - "BOTAN_TARGET_OS_HAS_GMTIME_S", - "_SCL_SECURE_NO_WARNINGS") - if (qbs.toolchain.contains("gcc") || qbs.toolchain.contains("mingw")) - result.push("BOTAN_BUILD_COMPILER_IS_GCC") - if (qbs.targetOS.contains("linux")) - result.push("BOTAN_TARGET_OS_IS_LINUX", "BOTAN_TARGET_OS_HAS_CLOCK_GETTIME", - "BOTAN_TARGET_OS_HAS_DLOPEN", " BOTAN_TARGET_OS_HAS_GMTIME_R", - "BOTAN_TARGET_OS_HAS_POSIX_MLOCK", "BOTAN_HAS_DYNAMICALLY_LOADED_ENGINE", - "BOTAN_HAS_DYNAMIC_LOADER", "BOTAN_TARGET_OS_HAS_GETTIMEOFDAY", - "BOTAN_HAS_ALLOC_MMAP", "BOTAN_HAS_ENTROPY_SRC_DEV_RANDOM", - "BOTAN_HAS_ENTROPY_SRC_EGD", "BOTAN_HAS_ENTROPY_SRC_FTW", - "BOTAN_HAS_ENTROPY_SRC_UNIX", "BOTAN_HAS_MUTEX_PTHREAD", "BOTAN_HAS_PIPE_UNIXFD_IO") - if (qbs.targetOS.contains("macos")) - result.push("BOTAN_TARGET_OS_IS_DARWIN", "BOTAN_TARGET_OS_HAS_GETTIMEOFDAY", - "BOTAN_HAS_ALLOC_MMAP", "BOTAN_HAS_ENTROPY_SRC_DEV_RANDOM", - "BOTAN_HAS_ENTROPY_SRC_EGD", "BOTAN_HAS_ENTROPY_SRC_FTW", - "BOTAN_HAS_ENTROPY_SRC_UNIX", "BOTAN_HAS_MUTEX_PTHREAD", "BOTAN_HAS_PIPE_UNIXFD_IO") - if (qbs.targetOS.contains("windows")) - result.push("BOTAN_TARGET_OS_IS_WINDOWS", - "BOTAN_TARGET_OS_HAS_LOADLIBRARY", "BOTAN_TARGET_OS_HAS_WIN32_GET_SYSTEMTIME", - "BOTAN_TARGET_OS_HAS_WIN32_VIRTUAL_LOCK", "BOTAN_HAS_DYNAMICALLY_LOADED_ENGINE", - "BOTAN_HAS_DYNAMIC_LOADER", "BOTAN_HAS_ENTROPY_SRC_CAPI", - "BOTAN_HAS_ENTROPY_SRC_WIN32", "BOTAN_HAS_MUTEX_WIN32") - } - return result - } - property var botanFiles: { - var result = ["../3rdparty/botan/botan.h"]; - if (!useSystemBotan) - result.push("../3rdparty/botan/botan.cpp") - return result - } - - // For Botan. - Properties { - condition: qbs.toolchain.contains("mingw") - cpp.cxxFlags: base.concat([ - "-fpermissive", - "-finline-functions", - "-Wno-long-long" - ]) - } - cpp.cxxFlags: base Export { Depends { name: "Qt"; submodules: ["widgets", "network"] } diff --git a/src/libs/ssh/sshbotanconversions_p.h b/src/libs/ssh/sshbotanconversions_p.h index f54ca843a2c..335a02323c9 100644 --- a/src/libs/ssh/sshbotanconversions_p.h +++ b/src/libs/ssh/sshbotanconversions_p.h @@ -28,7 +28,8 @@ #include "sshcapabilities_p.h" #include "sshexception_p.h" -#include <botan/botan.h> +#include <botan/secmem.h> +#include <botan/types.h> namespace QSsh { namespace Internal { @@ -45,7 +46,12 @@ inline Botan::byte *convertByteArray(QByteArray &a) inline QByteArray convertByteArray(const Botan::SecureVector<Botan::byte> &v) { - return QByteArray(reinterpret_cast<const char *>(v.begin()), static_cast<int>(v.size())); + return QByteArray(reinterpret_cast<const char *>(&v.front()), static_cast<int>(v.size())); +} + +inline QByteArray convertByteArray(const std::vector<std::uint8_t> &v) +{ + return QByteArray(reinterpret_cast<const char *>(&v.front()), static_cast<int>(v.size())); } inline const char *botanKeyExchangeAlgoName(const QByteArray &rfcAlgoName) @@ -91,11 +97,11 @@ inline const char *botanEmsaAlgoName(const QByteArray &rfcAlgoName) if (rfcAlgoName == SshCapabilities::PubKeyRsa) return "EMSA3(SHA-1)"; if (rfcAlgoName == SshCapabilities::PubKeyEcdsa256) - return "EMSA1_BSI(SHA-256)"; + return "EMSA1(SHA-256)"; if (rfcAlgoName == SshCapabilities::PubKeyEcdsa384) - return "EMSA1_BSI(SHA-384)"; + return "EMSA1(SHA-384)"; if (rfcAlgoName == SshCapabilities::PubKeyEcdsa521) - return "EMSA1_BSI(SHA-512)"; + return "EMSA1(SHA-512)"; throw SshClientException(SshInternalError, SSH_TR("Unexpected host key algorithm \"%1\"") .arg(QString::fromLatin1(rfcAlgoName))); } diff --git a/src/libs/ssh/sshchannel.cpp b/src/libs/ssh/sshchannel.cpp index d48622b36f1..5a3d5e4d42f 100644 --- a/src/libs/ssh/sshchannel.cpp +++ b/src/libs/ssh/sshchannel.cpp @@ -29,8 +29,6 @@ #include "sshlogging_p.h" #include "sshsendfacility_p.h" -#include <botan/botan.h> - #include <QTimer> namespace QSsh { diff --git a/src/libs/ssh/sshconnection.cpp b/src/libs/ssh/sshconnection.cpp index e1f98da06dc..7981a65cb94 100644 --- a/src/libs/ssh/sshconnection.cpp +++ b/src/libs/ssh/sshconnection.cpp @@ -34,13 +34,10 @@ #include "sshdirecttcpiptunnel.h" #include "sshtcpipforwardserver.h" #include "sshexception_p.h" -#include "sshinit_p.h" #include "sshkeyexchange_p.h" #include "sshlogging_p.h" #include "sshremoteprocess.h" -#include <botan/botan.h> - #include <QFile> #include <QMutex> #include <QMutexLocker> @@ -94,7 +91,6 @@ bool operator!=(const SshConnectionParameters &p1, const SshConnectionParameters SshConnection::SshConnection(const SshConnectionParameters &serverInfo, QObject *parent) : QObject(parent) { - Internal::initSsh(); qRegisterMetaType<QSsh::SshError>("QSsh::SshError"); qRegisterMetaType<QSsh::SftpJobId>("QSsh::SftpJobId"); qRegisterMetaType<QSsh::SftpFileInfo>("QSsh::SftpFileInfo"); @@ -947,10 +943,12 @@ void SshConnectionPrivate::closeConnection(SshErrorCode sshError, disconnect(&m_timeoutTimer, 0, this, 0); m_keepAliveTimer.stop(); disconnect(&m_keepAliveTimer, 0, this, 0); - try { - m_channelManager->closeAllChannels(SshChannelManager::CloseAllAndReset); - m_sendFacility.sendDisconnectPacket(sshError, serverErrorString); - } catch (...) {} // Nothing sensible to be done here. + if (m_state != SocketConnected) { + try { + m_channelManager->closeAllChannels(SshChannelManager::CloseAllAndReset); + m_sendFacility.sendDisconnectPacket(sshError, serverErrorString); + } catch (...) {} // Nothing sensible to be done here. + } if (m_error != SshNoError) emit error(userError); if (m_state == ConnectionEstablished) diff --git a/src/libs/ssh/sshcryptofacility.cpp b/src/libs/ssh/sshcryptofacility.cpp index 7156fd801ad..83a2490caa7 100644 --- a/src/libs/ssh/sshcryptofacility.cpp +++ b/src/libs/ssh/sshcryptofacility.cpp @@ -33,7 +33,16 @@ #include "sshlogging_p.h" #include "sshpacket_p.h" -#include <botan/botan.h> +#include <botan/ber_dec.h> +#include <botan/ctr.h> +#include <botan/dsa.h> +#include <botan/ec_group.h> +#include <botan/ecdsa.h> +#include <botan/filters.h> +#include <botan/pkcs8.h> +#include <botan/point_gfp.h> +#include <botan/pubkey.h> +#include <botan/rsa.h> #include <QDebug> #include <QList> @@ -77,11 +86,9 @@ void SshAbstractCryptoFacility::recreateKeys(const SshKeyExchange &kex) if (m_sessionId.isEmpty()) m_sessionId = kex.h(); - Algorithm_Factory &af = global_state().algorithm_factory(); const QByteArray &rfcCryptAlgoName = cryptAlgoName(kex); - BlockCipher * const cipher - = af.prototype_block_cipher(botanCryptAlgoName(rfcCryptAlgoName))->clone(); - + std::unique_ptr<BlockCipher> cipher + = BlockCipher::create_or_throw(botanCryptAlgoName(rfcCryptAlgoName)); m_cipherBlockSize = static_cast<quint32>(cipher->block_size()); const QByteArray ivData = generateHash(kex, ivChar(), m_cipherBlockSize); const InitializationVector iv(convertByteArray(ivData), m_cipherBlockSize); @@ -90,15 +97,15 @@ void SshAbstractCryptoFacility::recreateKeys(const SshKeyExchange &kex) const QByteArray cryptKeyData = generateHash(kex, keyChar(), keySize); SymmetricKey cryptKey(convertByteArray(cryptKeyData), keySize); Keyed_Filter * const cipherMode - = makeCipherMode(cipher, getMode(rfcCryptAlgoName), iv, cryptKey); + = makeCipherMode(cipher.release(), getMode(rfcCryptAlgoName), iv, cryptKey); m_pipe.reset(new Pipe(cipherMode)); m_macLength = botanHMacKeyLen(hMacAlgoName(kex)); const QByteArray hMacKeyData = generateHash(kex, macChar(), macLength()); SymmetricKey hMacKey(convertByteArray(hMacKeyData), macLength()); - const HashFunction * const hMacProto - = af.prototype_hash_function(botanHMacAlgoName(hMacAlgoName(kex))); - m_hMac.reset(new HMAC(hMacProto->clone())); + std::unique_ptr<HashFunction> hashFunc + = HashFunction::create_or_throw(botanHMacAlgoName(hMacAlgoName(kex))); + m_hMac.reset(new HMAC(hashFunc.release())); m_hMac->set_key(hMacKey); } @@ -156,12 +163,12 @@ QByteArray SshAbstractCryptoFacility::generateHash(const SshKeyExchange &kex, = kex.hash()->process(convertByteArray(data), data.size()); while (key.size() < length) { SecureVector<byte> tmpKey; - tmpKey += SecureVector<byte>(convertByteArray(k), k.size()); - tmpKey += SecureVector<byte>(convertByteArray(h), h.size()); + tmpKey.insert(tmpKey.end(), k.cbegin(), k.cend()); + tmpKey.insert(tmpKey.end(), h.cbegin(), h.cend()); tmpKey += key; key += kex.hash()->process(tmpKey); } - return QByteArray(reinterpret_cast<const char *>(key.begin()), length); + return QByteArray(reinterpret_cast<const char *>(&key.front()), length); } void SshAbstractCryptoFacility::checkInvariant() const @@ -192,7 +199,7 @@ Keyed_Filter *SshEncryptionFacility::makeCipherMode(BlockCipher *cipher, Mode mo { switch (mode) { case CbcMode: - return new CBC_Encryption(cipher, new Null_Padding, key, iv); + return get_cipher(cipher->name() + "/CBC/NoPadding", key, iv, ENCRYPTION); case CtrMode: return makeCtrCipherMode(cipher, iv, key); } @@ -235,7 +242,7 @@ void SshEncryptionFacility::createAuthenticationKey(const QByteArray &privKeyFil if (ecdsaKey) { m_authPubKeyBlob += AbstractSshPacket::encodeString(m_authKeyAlgoName.mid(11)); // Without "ecdsa-sha2-" prefix. m_authPubKeyBlob += AbstractSshPacket::encodeString( - convertByteArray(EC2OSP(ecdsaKey->public_point(), PointGFp::UNCOMPRESSED))); + convertByteArray(ecdsaKey->public_point().encode(PointGFp::UNCOMPRESSED))); } else { foreach (const BigInt &b, pubKeyParams) m_authPubKeyBlob += AbstractSshPacket::encodeMpInt(b); @@ -249,7 +256,7 @@ bool SshEncryptionFacility::createAuthenticationKeyFromPKCS8(const QByteArray &p try { Pipe pipe; pipe.process_msg(convertByteArray(privKeyFileContents), privKeyFileContents.size()); - m_authKey.reset(PKCS8::load_key(pipe, m_rng, SshKeyPasswordRetriever())); + m_authKey.reset(PKCS8::load_key(pipe, m_rng, &get_passphrase)); if (auto * const dsaKey = dynamic_cast<DSA_PrivateKey *>(m_authKey.data())) { m_authKeyAlgoName = SshCapabilities::PubKeyDss; pubKeyParams << dsaKey->group_p() << dsaKey->group_q() @@ -338,8 +345,7 @@ bool SshEncryptionFacility::createAuthenticationKeyFromOpenSSL(const QByteArray } else if (m_authKeyAlgoName == SshCapabilities::PubKeyRsa) { BigInt p, q, e, d, n; sequence.decode(n).decode(e).decode(d).decode(p).decode(q); - RSA_PrivateKey * const rsaKey = new RSA_PrivateKey(m_rng, p, q, e, d, n); - m_authKey.reset(rsaKey); + m_authKey.reset(new RSA_PrivateKey(p, q, e, d, n)); pubKeyParams << e << n; allKeyParams << pubKeyParams << p << q << d; } else { @@ -374,7 +380,7 @@ QByteArray SshEncryptionFacility::authenticationKeySignature(const QByteArray &d { Q_ASSERT(m_authKey); - QScopedPointer<PK_Signer> signer(new PK_Signer(*m_authKey, + QScopedPointer<PK_Signer> signer(new PK_Signer(*m_authKey, m_rng, botanEmsaAlgoName(m_authKeyAlgoName))); QByteArray dataToSign = AbstractSshPacket::encodeString(sessionId()) + data; QByteArray signature @@ -417,7 +423,7 @@ Keyed_Filter *SshDecryptionFacility::makeCipherMode(BlockCipher *cipher, Mode mo { switch (mode) { case CbcMode: - return new CBC_Decryption(cipher, new Null_Padding, key, iv); + return get_cipher(cipher->name() + "/CBC/NoPadding", iv, key, DECRYPTION); case CtrMode: return makeCtrCipherMode(cipher, iv, key); } diff --git a/src/libs/ssh/sshcryptofacility_p.h b/src/libs/ssh/sshcryptofacility_p.h index 2f9b64c44c2..86df75764d8 100644 --- a/src/libs/ssh/sshcryptofacility_p.h +++ b/src/libs/ssh/sshcryptofacility_p.h @@ -25,7 +25,13 @@ #pragma once -#include <botan/botan.h> +#include <botan/auto_rng.h> +#include <botan/bigint.h> +#include <botan/block_cipher.h> +#include <botan/hmac.h> +#include <botan/key_filt.h> +#include <botan/pipe.h> +#include <botan/pk_keys.h> #include <QByteArray> #include <QScopedPointer> diff --git a/src/libs/ssh/sshinit.cpp b/src/libs/ssh/sshinit.cpp deleted file mode 100644 index a76724e5519..00000000000 --- a/src/libs/ssh/sshinit.cpp +++ /dev/null @@ -1,49 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of Qt Creator. -** -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -****************************************************************************/ - -#include "sshinit_p.h" - -#include <botan/botan.h> - -#include <QMutex> -#include <QMutexLocker> - -namespace QSsh { -namespace Internal { - -static bool initialized = false; -static QMutex initMutex; - -void initSsh() -{ - QMutexLocker locker(&initMutex); - if (!initialized) { - Botan::LibraryInitializer::initialize("thread_safe=true"); - initialized = true; - } -} - -} // namespace Internal -} // namespace QSsh diff --git a/src/libs/ssh/sshinit_p.h b/src/libs/ssh/sshinit_p.h deleted file mode 100644 index 8fb84e27b11..00000000000 --- a/src/libs/ssh/sshinit_p.h +++ /dev/null @@ -1,32 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of Qt Creator. -** -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -****************************************************************************/ - -namespace QSsh { -namespace Internal { - -void initSsh(); - -} // namespace Internal -} // namespace QSsh diff --git a/src/libs/ssh/sshkeyexchange.cpp b/src/libs/ssh/sshkeyexchange.cpp index f513454d456..3eb013f282a 100644 --- a/src/libs/ssh/sshkeyexchange.cpp +++ b/src/libs/ssh/sshkeyexchange.cpp @@ -33,7 +33,18 @@ #include "sshexception_p.h" #include "sshincomingpacket_p.h" -#include <botan/botan.h> +#include <botan/auto_rng.h> +#include <botan/dh.h> +#include <botan/dl_group.h> +#include <botan/dsa.h> +#include <botan/ec_group.h> +#include <botan/ecdh.h> +#include <botan/ecdsa.h> +#include <botan/lookup.h> +#include <botan/point_gfp.h> +#include <botan/pubkey.h> +#include <botan/rsa.h> +#include <botan/types.h> #include <string> @@ -148,12 +159,13 @@ void SshKeyExchange::sendNewKeysPacket(const SshIncomingPacket &dhReply, printData("K_S", reply.k_s); SecureVector<byte> encodedK; + Botan::AutoSeeded_RNG rng; if (m_dhKey) { concatenatedData += AbstractSshPacket::encodeMpInt(m_dhKey->get_y()); concatenatedData += AbstractSshPacket::encodeMpInt(reply.f); - DH_KA_Operation dhOp(*m_dhKey); - SecureVector<byte> encodedF = BigInt::encode(reply.f); - encodedK = dhOp.agree(encodedF, encodedF.size()); + Botan::PK_Key_Agreement dhOp(*m_dhKey, rng, "Raw"); + const std::vector<std::uint8_t> encodedF = BigInt::encode(reply.f); + encodedK = dhOp.derive_key(m_dhKey->group_p().bytes(), encodedF).bits_of(); printData("y", AbstractSshPacket::encodeMpInt(m_dhKey->get_y())); printData("f", AbstractSshPacket::encodeMpInt(reply.f)); m_dhKey.reset(nullptr); @@ -162,8 +174,9 @@ void SshKeyExchange::sendNewKeysPacket(const SshIncomingPacket &dhReply, concatenatedData // Q_C. += AbstractSshPacket::encodeString(convertByteArray(m_ecdhKey->public_value())); concatenatedData += AbstractSshPacket::encodeString(reply.q_s); - ECDH_KA_Operation ecdhOp(*m_ecdhKey); - encodedK = ecdhOp.agree(convertByteArray(reply.q_s), reply.q_s.count()); + Botan::PK_Key_Agreement ecdhOp(*m_ecdhKey, rng, "Raw"); + encodedK = ecdhOp.derive_key(m_ecdhKey->domain().get_p().bytes(), + convertByteArray(reply.q_s), reply.q_s.count()).bits_of(); m_ecdhKey.reset(nullptr); } @@ -173,7 +186,7 @@ void SshKeyExchange::sendNewKeysPacket(const SshIncomingPacket &dhReply, concatenatedData += m_k; printData("Concatenated data", concatenatedData); - m_hash.reset(get_hash(botanHMacAlgoName(hashAlgoForKexAlgo()))); + m_hash = HashFunction::create_or_throw(botanHMacAlgoName(hashAlgoForKexAlgo())); const SecureVector<byte> &hashResult = m_hash->process(convertByteArray(concatenatedData), concatenatedData.size()); m_h = convertByteArray(hashResult); @@ -193,8 +206,7 @@ void SshKeyExchange::sendNewKeysPacket(const SshIncomingPacket &dhReply, } else { QSSH_ASSERT_AND_RETURN(m_serverHostKeyAlgo.startsWith(SshCapabilities::PubKeyEcdsaPrefix)); const EC_Group domain(SshCapabilities::oid(m_serverHostKeyAlgo)); - const PointGFp point = OS2ECP(convertByteArray(reply.q), reply.q.count(), - domain.get_curve()); + const PointGFp point = domain.OS2ECP(convertByteArray(reply.q), reply.q.count()); ECDSA_PublicKey * const ecdsaKey = new ECDSA_PublicKey(domain, point); sigKey.reset(ecdsaKey); } diff --git a/src/libs/ssh/sshkeyexchange_p.h b/src/libs/ssh/sshkeyexchange_p.h index b56597b6df3..de5828292e2 100644 --- a/src/libs/ssh/sshkeyexchange_p.h +++ b/src/libs/ssh/sshkeyexchange_p.h @@ -30,6 +30,8 @@ #include <QByteArray> #include <QScopedPointer> +#include <memory> + namespace Botan { class DH_PrivateKey; class ECDH_PrivateKey; @@ -59,7 +61,7 @@ public: QByteArray k() const { return m_k; } QByteArray h() const { return m_h; } - Botan::HashFunction *hash() const { return m_hash.data(); } + Botan::HashFunction *hash() const { return m_hash.get(); } QByteArray encryptionAlgo() const { return m_encryptionAlgo; } QByteArray decryptionAlgo() const { return m_decryptionAlgo; } QByteArray hMacAlgoClientToServer() const { return m_c2sHMacAlgo; } @@ -84,7 +86,7 @@ private: QByteArray m_decryptionAlgo; QByteArray m_c2sHMacAlgo; QByteArray m_s2cHMacAlgo; - QScopedPointer<Botan::HashFunction> m_hash; + std::unique_ptr<Botan::HashFunction> m_hash; const SshConnectionParameters m_connParams; SshSendFacility &m_sendFacility; }; diff --git a/src/libs/ssh/sshkeygenerator.cpp b/src/libs/ssh/sshkeygenerator.cpp index eb85c1aa66f..38828ee97f4 100644 --- a/src/libs/ssh/sshkeygenerator.cpp +++ b/src/libs/ssh/sshkeygenerator.cpp @@ -27,11 +27,20 @@ #include "sshbotanconversions_p.h" #include "sshcapabilities_p.h" +#include "sshlogging_p.h" #include "ssh_global.h" -#include "sshinit_p.h" #include "sshpacket_p.h" -#include <botan/botan.h> +#include <botan/auto_rng.h> +#include <botan/der_enc.h> +#include <botan/dsa.h> +#include <botan/ecdsa.h> +#include <botan/numthry.h> +#include <botan/pem.h> +#include <botan/pipe.h> +#include <botan/pkcs8.h> +#include <botan/rsa.h> +#include <botan/x509_key.h> #include <QDateTime> #include <QInputDialog> @@ -45,7 +54,6 @@ using namespace Internal; SshKeyGenerator::SshKeyGenerator() : m_type(Rsa) { - initSsh(); } bool SshKeyGenerator::generateKeys(KeyType type, PrivateKeyFormat format, int keySize, @@ -116,8 +124,10 @@ void SshKeyGenerator::generatePkcs8KeyString(const KeyPtr &key, bool privateKey, } pipe.end_msg(); keyData->resize(static_cast<int>(pipe.remaining(pipe.message_count() - 1))); - pipe.read(convertByteArray(*keyData), keyData->size(), - pipe.message_count() - 1); + if (pipe.read(convertByteArray(*keyData), keyData->size(), pipe.message_count() - 1) + != std::size_t(keyData->size())) { + qCWarning(sshLog) << "short read from botan pipe"; + } } void SshKeyGenerator::generateOpenSslKeyStrings(const KeyPtr &key) @@ -146,7 +156,7 @@ void SshKeyGenerator::generateOpenSslPublicKeyString(const KeyPtr &key) } case Ecdsa: { const auto ecdsaKey = key.dynamicCast<ECDSA_PrivateKey>(); - q = convertByteArray(EC2OSP(ecdsaKey->public_point(), PointGFp::UNCOMPRESSED)); + q = convertByteArray(ecdsaKey->public_point().encode(PointGFp::UNCOMPRESSED)); keyId = SshCapabilities::ecdsaPubKeyAlgoForKeyWidth( static_cast<int>(ecdsaKey->private_value().bytes())); break; diff --git a/src/libs/ssh/sshkeypasswordretriever.cpp b/src/libs/ssh/sshkeypasswordretriever.cpp index 8f133623636..6631404a038 100644 --- a/src/libs/ssh/sshkeypasswordretriever.cpp +++ b/src/libs/ssh/sshkeypasswordretriever.cpp @@ -34,20 +34,16 @@ namespace QSsh { namespace Internal { -std::string SshKeyPasswordRetriever::get_passphrase(const std::string &, const std::string &, - UI_Result &result) const +std::string get_passphrase() { const bool hasGui = dynamic_cast<QApplication *>(QApplication::instance()); if (hasGui) { - bool ok; const QString &password = QInputDialog::getText(0, QCoreApplication::translate("QSsh::Ssh", "Password Required"), QCoreApplication::translate("QSsh::Ssh", "Please enter the password for your private key."), - QLineEdit::Password, QString(), &ok); - result = ok ? OK : CANCEL_ACTION; + QLineEdit::Password, QString()); return std::string(password.toLocal8Bit().data()); } else { - result = OK; std::string password; std::cout << "Please enter the password for your private key (set echo off beforehand!): " << std::flush; std::cin >> password; diff --git a/src/libs/ssh/sshkeypasswordretriever_p.h b/src/libs/ssh/sshkeypasswordretriever_p.h index 15301feb67b..7d7bc76e698 100644 --- a/src/libs/ssh/sshkeypasswordretriever_p.h +++ b/src/libs/ssh/sshkeypasswordretriever_p.h @@ -25,19 +25,12 @@ #pragma once -#include <botan/botan.h> - #include <string> namespace QSsh { namespace Internal { -class SshKeyPasswordRetriever : public Botan::User_Interface -{ -public: - std::string get_passphrase(const std::string &what, const std::string &source, - UI_Result &result) const; -}; +std::string get_passphrase(); } // namespace Internal } // namespace QSsh diff --git a/src/libs/ssh/sshpacketparser_p.h b/src/libs/ssh/sshpacketparser_p.h index b57f22f0846..db63f0a1b9c 100644 --- a/src/libs/ssh/sshpacketparser_p.h +++ b/src/libs/ssh/sshpacketparser_p.h @@ -25,7 +25,7 @@ #pragma once -#include <botan/botan.h> +#include <botan/bigint.h> #include <QByteArray> #include <QList> diff --git a/src/libs/ssh/sshremoteprocess.cpp b/src/libs/ssh/sshremoteprocess.cpp index 5a875d1f105..3b81e0409ce 100644 --- a/src/libs/ssh/sshremoteprocess.cpp +++ b/src/libs/ssh/sshremoteprocess.cpp @@ -31,8 +31,6 @@ #include "sshlogging_p.h" #include "sshsendfacility_p.h" -#include <botan/botan.h> - #include <QTimer> #include <cstring> |