From 0a817b9fcb8e7a1bf5c4a910eb0de1a549b5ba9f Mon Sep 17 00:00:00 2001 From: Iru Cai Date: Sat, 5 Nov 2016 14:54:10 +0800 Subject: Implement ssh_cipher_t for symmetric ciphers in SSH * remove FQTermSSHCipher and FQTermSSH3DES, use ssh_cipher_t instead * implement EVP ciphers and 3DES-SSH1 --- src/protocol/CMakeLists.txt | 6 +- src/protocol/internal/fqterm_ssh1_packet.cpp | 24 ++-- src/protocol/internal/fqterm_ssh1_packet.h | 3 + src/protocol/internal/fqterm_ssh2_kex.cpp | 5 +- src/protocol/internal/fqterm_ssh2_packet.cpp | 50 ++------ src/protocol/internal/fqterm_ssh2_packet.h | 30 ++--- src/protocol/internal/fqterm_ssh_cipher.h | 58 --------- src/protocol/internal/fqterm_ssh_des.cpp | 180 --------------------------- src/protocol/internal/fqterm_ssh_des.h | 74 ----------- src/protocol/internal/fqterm_ssh_packet.cpp | 73 ++++------- src/protocol/internal/fqterm_ssh_packet.h | 18 ++- src/protocol/internal/ssh_3des-ssh1.c | 82 ++++++++++++ src/protocol/internal/ssh_cipher.h | 46 +++++++ src/protocol/internal/ssh_evp_cipher.c | 63 ++++++++++ 14 files changed, 275 insertions(+), 437 deletions(-) delete mode 100644 src/protocol/internal/fqterm_ssh_cipher.h delete mode 100644 src/protocol/internal/fqterm_ssh_des.cpp delete mode 100644 src/protocol/internal/fqterm_ssh_des.h create mode 100644 src/protocol/internal/ssh_3des-ssh1.c create mode 100644 src/protocol/internal/ssh_cipher.h create mode 100644 src/protocol/internal/ssh_evp_cipher.c diff --git a/src/protocol/CMakeLists.txt b/src/protocol/CMakeLists.txt index 84fddf4..5803cb5 100644 --- a/src/protocol/CMakeLists.txt +++ b/src/protocol/CMakeLists.txt @@ -17,13 +17,14 @@ set(internal_SRCS internal/ssh_pubkey_crypto.c internal/ssh_diffie-hellman.h internal/ssh_diffie-hellman.c + internal/ssh_cipher.h + internal/ssh_evp_cipher.c + internal/ssh_3des-ssh1.c internal/crc32.h internal/fqterm_serialization.h internal/fqterm_ssh_auth.h internal/fqterm_ssh_buffer.h - internal/fqterm_ssh_cipher.h internal/fqterm_ssh_const.h - internal/fqterm_ssh_des.h internal/fqterm_ssh_hash.h internal/fqterm_ssh_kex.h internal/fqterm_ssh2_kex.h @@ -37,7 +38,6 @@ set(internal_SRCS internal/crc32.cpp internal/fqterm_ssh_auth.cpp internal/fqterm_ssh_buffer.cpp - internal/fqterm_ssh_des.cpp internal/fqterm_ssh_kex.cpp internal/fqterm_ssh2_kex.cpp internal/fqterm_ssh_mac.cpp diff --git a/src/protocol/internal/fqterm_ssh1_packet.cpp b/src/protocol/internal/fqterm_ssh1_packet.cpp index ded7fe4..aab8f92 100644 --- a/src/protocol/internal/fqterm_ssh1_packet.cpp +++ b/src/protocol/internal/fqterm_ssh1_packet.cpp @@ -21,7 +21,6 @@ #include "fqterm_trace.h" #include "fqterm_ssh_buffer.h" #include "fqterm_ssh1_packet.h" -#include "fqterm_ssh_des.h" #include "fqterm_serialization.h" #include "crc32.h" @@ -43,6 +42,11 @@ namespace FQTerm { // //============================================================================== + FQTermSSH1PacketSender::FQTermSSH1PacketSender() + { + cipher = new_3des_ssh1(1); + } + void FQTermSSH1PacketSender::makePacket() { int len, padding, i; u_int32_t rand_val = 0; @@ -68,14 +72,20 @@ void FQTermSSH1PacketSender::makePacket() { output_buffer_->putInt(ssh_crc32(output_buffer_->data() + 4, output_buffer_->len() - 4)); if (is_encrypt_) { - cipher_->encrypt(output_buffer_->data() + 4, output_buffer_->data() + 4, output_buffer_->len() - 4); - } + cipher->crypt(cipher, output_buffer_->data() + 4, output_buffer_->data() + 4, output_buffer_->len() - 4); + } } //============================================================================== //FQTermSSH1PacketReceiver //============================================================================== + + FQTermSSH1PacketReceiver::FQTermSSH1PacketReceiver() + { + cipher = new_3des_ssh1(0); + } + void FQTermSSH1PacketReceiver::parseData(FQTermSSHBuffer *input) { u_int mycrc, gotcrc; u_char *buf = NULL; @@ -116,11 +126,11 @@ void FQTermSSH1PacketReceiver::parseData(FQTermSSHBuffer *input) { input->getRawData((char*)sourceData, total_len); if (is_decrypt_) { - cipher_->decrypt(sourceData, targetData, total_len); + cipher->crypt(cipher, sourceData, targetData, total_len); } else { - memcpy(targetData, sourceData, total_len); - } - + memcpy(targetData, sourceData, total_len); + } + buffer_->putRawData((char*)targetData, total_len); // Check the crc32. diff --git a/src/protocol/internal/fqterm_ssh1_packet.h b/src/protocol/internal/fqterm_ssh1_packet.h index a535635..8ea66c7 100644 --- a/src/protocol/internal/fqterm_ssh1_packet.h +++ b/src/protocol/internal/fqterm_ssh1_packet.h @@ -28,11 +28,14 @@ namespace FQTerm { class FQTermSSH1PacketSender: public FQTermSSHPacketSender { protected: virtual void makePacket(); +public: + FQTermSSH1PacketSender(); }; class FQTermSSH1PacketReceiver: public FQTermSSHPacketReceiver { public: virtual void parseData(FQTermSSHBuffer *input); + FQTermSSH1PacketReceiver(); }; } // namespace FQTerm diff --git a/src/protocol/internal/fqterm_ssh2_kex.cpp b/src/protocol/internal/fqterm_ssh2_kex.cpp index 137a41e..e2fd784 100644 --- a/src/protocol/internal/fqterm_ssh2_kex.cpp +++ b/src/protocol/internal/fqterm_ssh2_kex.cpp @@ -30,6 +30,7 @@ #include "fqterm_ssh_md5.h" #include "fqterm_trace.h" #include "ssh_pubkey_crypto.h" +#include "ssh_cipher.h" namespace FQTerm { @@ -296,8 +297,8 @@ bool FQTermSSH2Kex::changeKeyAlg() { memcpy(session_id_, H_, SHA_DIGEST_LENGTH); } - packet_sender_->setEncryptionType(SSH_CIPHER_3DES); - packet_receiver_->setEncryptionType(SSH_CIPHER_3DES); + packet_sender_->cipher = new_ssh_cipher_evp(EVP_des_ede3_cbc, 24, 8, 8, 1); + packet_receiver_->cipher = new_ssh_cipher_evp(EVP_des_ede3_cbc, 24, 8, 8, 0); packet_sender_->setMacType(FQTERM_SSH_HMAC_SHA1); packet_receiver_->setMacType(FQTERM_SSH_HMAC_SHA1); diff --git a/src/protocol/internal/fqterm_ssh2_packet.cpp b/src/protocol/internal/fqterm_ssh2_packet.cpp index d3094d3..aed8b48 100644 --- a/src/protocol/internal/fqterm_ssh2_packet.cpp +++ b/src/protocol/internal/fqterm_ssh2_packet.cpp @@ -21,7 +21,6 @@ #include "fqterm_trace.h" #include "fqterm_ssh_buffer.h" #include "fqterm_ssh2_packet.h" -#include "fqterm_ssh_des.h" #include "fqterm_serialization.h" #include "crc32.h" @@ -52,8 +51,8 @@ void FQTermSSH2PacketSender::makePacket() { int non_padding_len = 4 + 1 + buffer_->len(); int padding_block_len = 8; - if (is_encrypt_ && cipher_->blockSize() > padding_block_len) { - padding_block_len = cipher_->blockSize(); + if (is_encrypt_ && cipher->blkSize > padding_block_len) { + padding_block_len = cipher->blkSize; } int padding_len = padding_block_len - (non_padding_len % padding_block_len); @@ -128,7 +127,7 @@ void FQTermSSH2PacketSender::makePacket() { << len << " bytes:\n" << dumpHexString << std::string((const char *)data, len); - cipher_->encrypt(data, data, len); + FQ_VERIFY(cipher->crypt(cipher, data, data, len)==1); FQ_TRACE("ssh2packet", 9) << "An encrypted packet (without MAC) made:" << len << " bytes:\n" @@ -138,20 +137,6 @@ void FQTermSSH2PacketSender::makePacket() { ++sequence_no_; } -void FQTermSSH2PacketSender::setEncryptionType(int cipherType) { - cipher_type_ = cipherType; - - delete cipher_; - cipher_ = NULL; - - switch (cipher_type_) { - case SSH_CIPHER_3DES: - cipher_ = new FQTermSSH2TripleDESCBC; - break; - } -} - - //============================================================================== //FQTermSSH2PacketReceiver //============================================================================== @@ -162,8 +147,8 @@ void FQTermSSH2PacketReceiver::parseData(FQTermSSHBuffer *input) { while (input->len() > 0) { // 1. Check the ssh packet if (input->len() < 16 - || (is_decrypt_ && input->len() < cipher_->blockSize()) - || input->len() < last_expected_input_length_ + || (is_decrypt_ && input->len() < cipher->blkSize) + || input->len() < last_expected_input_length_ ) { FQ_TRACE("ssh2packet", 3) << "Got an incomplete packet. Wait for more data."; @@ -172,8 +157,8 @@ void FQTermSSH2PacketReceiver::parseData(FQTermSSHBuffer *input) { if (last_expected_input_length_ == 0) { if (is_decrypt_) { - // decrypte the first block to get the packet_length field. - cipher_->decrypt(input->data(), input->data(), cipher_->blockSize()); + // decrypte the first block to get the packet_length field. + FQ_VERIFY(cipher->crypt(cipher, input->data(), input->data(), cipher->blkSize)==1); } } else { // last_expected_input_length_ != 0 @@ -203,9 +188,9 @@ void FQTermSSH2PacketReceiver::parseData(FQTermSSHBuffer *input) { // 2. decrypte data. if (is_decrypt_) { // decrypte blocks left. - unsigned char *tmp = input->data() + cipher_->blockSize(); - int left_len = expected_input_len - cipher_->blockSize() - mac_->digestSize(); - cipher_->decrypt(tmp, tmp, left_len); + unsigned char *tmp = input->data() + cipher->blkSize; + int left_len = expected_input_len - cipher->blkSize - mac_->digestSize(); + FQ_VERIFY(cipher->crypt(cipher, tmp, tmp, left_len)==1); } // 3. check MAC @@ -226,7 +211,7 @@ void FQTermSSH2PacketReceiver::parseData(FQTermSSHBuffer *input) { packet_len = input->getInt(); std::vector data(packet_len); - + input->getRawData((char*)&data[0], packet_len); if (is_mac_) { input->consume(mac_->digestSize()); @@ -251,17 +236,4 @@ void FQTermSSH2PacketReceiver::parseData(FQTermSSHBuffer *input) { } } -void FQTermSSH2PacketReceiver::setEncryptionType(int cipherType) { - cipher_type_ = cipherType; - - delete cipher_; - cipher_ = NULL; - - switch (cipher_type_) { - case SSH_CIPHER_3DES: - cipher_ = new FQTermSSH2TripleDESCBC; - break; - } -} - } // namespace FQTerm diff --git a/src/protocol/internal/fqterm_ssh2_packet.h b/src/protocol/internal/fqterm_ssh2_packet.h index c460984..f2e6b0f 100644 --- a/src/protocol/internal/fqterm_ssh2_packet.h +++ b/src/protocol/internal/fqterm_ssh2_packet.h @@ -25,25 +25,21 @@ namespace FQTerm { -class FQTermSSH2PacketSender: public FQTermSSHPacketSender { - protected: - virtual void makePacket(); - - public: - virtual void setEncryptionType(int cipherType); +class FQTermSSH2PacketSender: public FQTermSSHPacketSender +{ +protected: + virtual void makePacket(); }; -class FQTermSSH2PacketReceiver: public FQTermSSHPacketReceiver { - private: - // greater than 0 if last time an incomplete ssh2 packet received. - int last_expected_input_length_; - public: - FQTermSSH2PacketReceiver() - : last_expected_input_length_(0) { - } - - virtual void parseData(FQTermSSHBuffer *input); - virtual void setEncryptionType(int cipherType); +class FQTermSSH2PacketReceiver: public FQTermSSHPacketReceiver +{ +private: + // greater than 0 if last time an incomplete ssh2 packet received. + int last_expected_input_length_; +public: +FQTermSSH2PacketReceiver() : last_expected_input_length_(0) { } + + virtual void parseData(FQTermSSHBuffer *input); }; } // namespace FQTerm diff --git a/src/protocol/internal/fqterm_ssh_cipher.h b/src/protocol/internal/fqterm_ssh_cipher.h deleted file mode 100644 index 13bc9f3..0000000 --- a/src/protocol/internal/fqterm_ssh_cipher.h +++ /dev/null @@ -1,58 +0,0 @@ -/*************************************************************************** - * fqterm, a terminal emulator for both BBS and *nix. * - * Copyright (C) 2008 fqterm development group. * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * - ***************************************************************************/ - -#ifndef FQTERM_SSH_CIPHER_H -#define FQTERM_SSH_CIPHER_H - -#include - -#include "fqterm_ssh_types.h" -#include "fqterm_ssh_const.h" - -namespace FQTerm { - -class FQTermSSHCipher { -protected: - const char *d_name; - -public: - FQTermSSHCipher() { - d_name = NULL; - } - - virtual ~FQTermSSHCipher(){} - - const char *name() const { - return d_name; - } - - virtual int blockSize() const = 0; - virtual int getKeySize() const = 0; - virtual int getIVSize() const = 0; - - virtual void setIV(const u_char *data) = 0; - virtual void setKey(const u_char *data) = 0; - virtual void encrypt(const u_char *source, u_char *dest, int len) = 0; - virtual void decrypt(const u_char *source, u_char *dest, int len) = 0; -}; - -} // namespace FQTerm - -#endif // FQTERM_SSH_CIPHER_H diff --git a/src/protocol/internal/fqterm_ssh_des.cpp b/src/protocol/internal/fqterm_ssh_des.cpp deleted file mode 100644 index ca6de16..0000000 --- a/src/protocol/internal/fqterm_ssh_des.cpp +++ /dev/null @@ -1,180 +0,0 @@ -/*************************************************************************** - * fqterm, a terminal emulator for both BBS and *nix. * - * Copyright (C) 2008 fqterm development group. * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * - ***************************************************************************/ - -#include -#include -#include -#include - -#include "fqterm_ssh_const.h" -#include "fqterm_ssh_des.h" -#include "fqterm_trace.h" - -namespace FQTerm { - -#define DES_ENCRYPT 1 -#define DES_DECRYPT 0 - -//============================================================================== -//FQTermSSH1DES3 -//============================================================================== - -FQTermSSH1DES3::FQTermSSH1DES3() { - d_name = "des3-cbc"; - - memset(d_IV1, 0, sizeof(d_IV1)); - memset(d_IV2, 0, sizeof(d_IV2)); - memset(d_IV3, 0, sizeof(d_IV3)); -} - -int FQTermSSH1DES3::blockSize() const { - return 8; -} - -void FQTermSSH1DES3::decrypt(const u_char *source, u_char *dest, int len) { - DES_ncbc_encrypt(source, dest, len, &d_key3, &d_IV3, DES_DECRYPT); - DES_ncbc_encrypt(dest, dest, len, &d_key2, &d_IV2, DES_ENCRYPT); - DES_ncbc_encrypt(dest, dest, len, &d_key1, &d_IV1, DES_DECRYPT); -} - -void FQTermSSH1DES3::encrypt(const u_char *source, u_char *dest, int len) { - DES_ncbc_encrypt(source, dest, len, &d_key1, &d_IV1, DES_ENCRYPT); - DES_ncbc_encrypt(dest, dest, len, &d_key2, &d_IV2, DES_DECRYPT); - DES_ncbc_encrypt(dest, dest, len, &d_key3, &d_IV3, DES_ENCRYPT); -} - -int FQTermSSH1DES3::getKeySize() const { - return 3*DES_KEY_SZ; -} - -int FQTermSSH1DES3::getIVSize() const { - return 0; -} - -void FQTermSSH1DES3::setIV(const u_char *data) { - memset(d_IV1, 0, sizeof(d_IV1)); - memset(d_IV2, 0, sizeof(d_IV2)); - memset(d_IV3, 0, sizeof(d_IV3)); -} - -void FQTermSSH1DES3::setKey(const u_char *data) { - DES_cblock key; - memset(key, 0, sizeof(key)); - memcpy(key, data, sizeof(key)); - DES_set_key(&key, &d_key1); - data += 8; - memset(key, 0, sizeof(key)); - memcpy(key, data, sizeof(key)); - DES_set_key(&key, &d_key2); - data += 8; - memset(key, 0, sizeof(key)); - memcpy(key, data, sizeof(key)); - DES_set_key(&key, &d_key3); -} - - -//================================================== -// TripleDES-CBC -//================================================== - -FQTermSSH2TripleDESCBC::FQTermSSH2TripleDESCBC() { - d_name = "des3-cbc"; - ctx_ = NULL; -} - -FQTermSSH2TripleDESCBC::~FQTermSSH2TripleDESCBC() { - if (ctx_ != NULL) { - EVP_CIPHER_CTX_cleanup(ctx_); - EVP_CIPHER_CTX_free(ctx_); - } -} - - -int FQTermSSH2TripleDESCBC::blockSize() const { - return 8; -} - -int FQTermSSH2TripleDESCBC::getKeySize() const { - return 24; -} - -int FQTermSSH2TripleDESCBC::getIVSize() const { - return 8; -} - -void FQTermSSH2TripleDESCBC::setIV(const u_char *data) { - memcpy(IV_, data, getIVSize()); -} - -void FQTermSSH2TripleDESCBC::setKey(const u_char *data) { - memcpy(key_, data, getKeySize()); -} - -void FQTermSSH2TripleDESCBC::encrypt(const u_char *source, u_char *dest, int len) { - FQ_TRACE("3DES_CBC", 9) << "Start encrypting"; - FQ_TRACE("3DES_CBC", 9) << "data len:" << len; - FQ_TRACE("3DES_CBC", 9) << "Source: \n" << dumpHexString << std::string((char *)source, len); - - int ret = 0; - if (ctx_ == NULL) { - // Lazy initialization. - ctx_ = EVP_CIPHER_CTX_new(); - EVP_CIPHER_CTX_init(ctx_); - ret = EVP_CipherInit(ctx_, EVP_des_ede3_cbc(), key_, IV_, 1); - FQ_VERIFY(ret == 1); - } - - ret = EVP_Cipher(ctx_, dest, source, len); - - FQ_VERIFY(ret == 1); - - FQ_TRACE("3DES_CBC", 9) << "Dest: \n" << dumpHexString << std::string((char *)dest, len); - - FQ_TRACE("3DES_CBC", 9) << "IV:\n" << dumpHexString << std::string((char *)IV_, getIVSize()); - FQ_TRACE("3DES_CBC", 9) << "key:\n" << dumpHexString << std::string((char *)key_, getKeySize()); - -} - -void FQTermSSH2TripleDESCBC::decrypt(const u_char *source, u_char *dest, int len) { - FQ_TRACE("3DES_CBC", 9) << "Start dencrypting"; - FQ_TRACE("3DES_CBC", 9) << "data len:" << len; - FQ_TRACE("3DES_CBC", 9) << "Source: \n" << dumpHexString << std::string((char *)source, len); - - int ret = 0; - if (ctx_ == NULL) { - // Lazy initialization. - ctx_ = EVP_CIPHER_CTX_new(); - EVP_CIPHER_CTX_init(ctx_); - ret = EVP_CipherInit(ctx_, EVP_des_ede3_cbc(), key_, IV_, 0); - FQ_VERIFY(ret == 1); - } - - ret = EVP_Cipher(ctx_, dest, source, len); - - FQ_VERIFY(ret == 1); - - FQ_TRACE("3DES_CBC", 9) << "Dest: \n" << dumpHexString << std::string((char *)dest, len); - - FQ_TRACE("3DES_CBC", 9) << "IV:\n" << dumpHexString << std::string((char *)IV_, getIVSize()); - FQ_TRACE("3DES_CBC", 9) << "key:\n" << dumpHexString << std::string((char *)key_, getKeySize()); -} - - -} // namespace FQTerm diff --git a/src/protocol/internal/fqterm_ssh_des.h b/src/protocol/internal/fqterm_ssh_des.h deleted file mode 100644 index ba153f2..0000000 --- a/src/protocol/internal/fqterm_ssh_des.h +++ /dev/null @@ -1,74 +0,0 @@ -/*************************************************************************** - * fqterm, a terminal emulator for both BBS and *nix. * - * Copyright (C) 2008 fqterm development group. * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * - ***************************************************************************/ - -#ifndef FQTERM_SSH_DES_H -#define FQTERM_SSH_DES_H - -#include -#include - -#include "fqterm_ssh_cipher.h" -#include "fqterm_ssh_types.h" - -namespace FQTerm { - -class FQTermSSH1DES3: public FQTermSSHCipher { - private: - DES_cblock d_IV1; - DES_cblock d_IV2; - DES_cblock d_IV3; - DES_key_schedule d_key1; - DES_key_schedule d_key2; - DES_key_schedule d_key3; - public: - FQTermSSH1DES3(); - - virtual int blockSize() const; - virtual int getKeySize() const; - virtual int getIVSize() const; - virtual void setIV(const u_char *data); - virtual void setKey(const u_char *data); - virtual void encrypt(const u_char *source, u_char *dest, int len); - virtual void decrypt(const u_char *source, u_char *dest, int len); -}; - -class FQTermSSH2TripleDESCBC: public FQTermSSHCipher { - private: - unsigned char IV_[8]; - unsigned char key_[24]; - - EVP_CIPHER_CTX *ctx_; - - public: - FQTermSSH2TripleDESCBC(); - ~FQTermSSH2TripleDESCBC(); - - virtual int blockSize() const; - virtual int getKeySize() const; - virtual int getIVSize() const; - virtual void setIV(const u_char *data); - virtual void setKey(const u_char *data); - virtual void encrypt(const u_char *source, u_char *dest, int len); - virtual void decrypt(const u_char *source, u_char *dest, int len); -}; - -} // namespace FQTerm - -#endif // FQTERM_SSH_DES_H diff --git a/src/protocol/internal/fqterm_ssh_packet.cpp b/src/protocol/internal/fqterm_ssh_packet.cpp index 9c4ff6c..402d1b8 100644 --- a/src/protocol/internal/fqterm_ssh_packet.cpp +++ b/src/protocol/internal/fqterm_ssh_packet.cpp @@ -21,7 +21,7 @@ #include "fqterm_trace.h" #include "fqterm_ssh_buffer.h" #include "fqterm_ssh_packet.h" -#include "fqterm_ssh_des.h" +#include "fqterm_ssh_const.h" #include "fqterm_serialization.h" #include "crc32.h" @@ -38,8 +38,7 @@ FQTermSSHPacketSender::FQTermSSHPacketSender() { is_encrypt_ = false; cipher_type_ = SSH_CIPHER_NONE; - cipher_ = NULL; - setEncryptionType(SSH_CIPHER_3DES); + cipher = NULL; is_mac_ = false; mac_type_ = FQTERM_SSH_MAC_NONE; @@ -51,11 +50,10 @@ FQTermSSHPacketSender::FQTermSSHPacketSender() { } FQTermSSHPacketSender::~FQTermSSHPacketSender() { - delete buffer_; - delete output_buffer_; - if (is_encrypt_) { - delete cipher_; - } + delete buffer_; + delete output_buffer_; + if (cipher) + cipher->cleanup(cipher); } void FQTermSSHPacketSender::putRawData(const char *data, int len) { @@ -92,23 +90,14 @@ void FQTermSSHPacketSender::write() { emit dataToWrite(); } -void FQTermSSHPacketSender::setEncryptionType(int cipherType) { - cipher_type_ = cipherType; - - delete cipher_; - cipher_ = NULL; - - switch (cipher_type_) { - case SSH_CIPHER_3DES: - cipher_ = new FQTermSSH1DES3; - break; - } -} - void FQTermSSHPacketSender::startEncryption(const u_char *key, const u_char *IV) { - is_encrypt_ = true; - cipher_->setIV(IV); - cipher_->setKey(key); + is_encrypt_ = true; + + if (cipher!=NULL) { + memcpy(cipher->IV, IV, cipher->IVSize); + memcpy(cipher->key, key, cipher->keySize); + cipher->init(cipher); + } } void FQTermSSHPacketSender::resetEncryption() { @@ -146,8 +135,7 @@ FQTermSSHPacketReceiver::FQTermSSHPacketReceiver() { is_decrypt_ = false; cipher_type_ = SSH_CIPHER_NONE; - cipher_ = NULL; - setEncryptionType(SSH_CIPHER_3DES); + cipher = NULL; is_mac_ = false; mac_type_ = FQTERM_SSH_MAC_NONE; @@ -158,11 +146,11 @@ FQTermSSHPacketReceiver::FQTermSSHPacketReceiver() { sequence_no_ = 0; } -FQTermSSHPacketReceiver::~FQTermSSHPacketReceiver() { - delete buffer_; - if (is_decrypt_) { - delete cipher_; - } +FQTermSSHPacketReceiver::~FQTermSSHPacketReceiver() +{ + delete buffer_; + if (cipher) + cipher->cleanup(cipher); } void FQTermSSHPacketReceiver::getRawData(char *data, int length) { @@ -193,23 +181,14 @@ void FQTermSSHPacketReceiver::consume(int len) { buffer_->consume(len); } -void FQTermSSHPacketReceiver::setEncryptionType(int cipherType) { - cipher_type_ = cipherType; - - delete cipher_; - cipher_ = NULL; - - switch (cipher_type_) { - case SSH_CIPHER_3DES: - cipher_ = new FQTermSSH1DES3; - break; - } -} - void FQTermSSHPacketReceiver::startEncryption(const u_char *key, const u_char *IV) { - is_decrypt_ = true; - cipher_->setIV(IV); - cipher_->setKey(key); + is_decrypt_ = true; + + if (cipher!=NULL) { + memcpy(cipher->IV, IV, cipher->IVSize); + memcpy(cipher->key, key, cipher->keySize); + cipher->init(cipher); + } } void FQTermSSHPacketReceiver::resetEncryption() { diff --git a/src/protocol/internal/fqterm_ssh_packet.h b/src/protocol/internal/fqterm_ssh_packet.h index ed5a488..705a11b 100644 --- a/src/protocol/internal/fqterm_ssh_packet.h +++ b/src/protocol/internal/fqterm_ssh_packet.h @@ -28,8 +28,8 @@ #include "fqterm_ssh_types.h" #include "fqterm_ssh_buffer.h" #include "fqterm_ssh_mac.h" -#include "fqterm_ssh_cipher.h" #include "fqterm_serialization.h" +#include "ssh_cipher.h" namespace FQTerm { @@ -38,10 +38,11 @@ class FQTermSSHPacketSender: public QObject { public: FQTermSSHBuffer *output_buffer_; FQTermSSHBuffer *buffer_; + ssh_cipher_t *cipher; FQTermSSHPacketSender(); virtual ~FQTermSSHPacketSender(); - + void startPacket(int pkt_type); void putByte(int data); void putInt(u_int data); @@ -51,12 +52,11 @@ class FQTermSSHPacketSender: public QObject { void putBN2(BIGNUM *bignum); void write(); - int getIVSize() const { return cipher_->getIVSize();} - int getKeySize() const { return cipher_->getKeySize();} + virtual int getIVSize() const { return cipher->IVSize;} + virtual int getKeySize() const { return cipher->keySize;} int getMacKeySize() const { return mac_->keySize();} public slots: - virtual void setEncryptionType(int cipherType); void startEncryption(const u_char *key, const u_char *IV = NULL); void resetEncryption(); @@ -72,7 +72,6 @@ class FQTermSSHPacketSender: public QObject { protected: bool is_encrypt_; int cipher_type_; - FQTermSSHCipher *cipher_; bool is_mac_; int mac_type_; @@ -89,6 +88,7 @@ class FQTermSSHPacketReceiver: public QObject { Q_OBJECT; public: FQTermSSHBuffer *buffer_; + ssh_cipher_t *cipher; FQTermSSHPacketReceiver(); virtual ~FQTermSSHPacketReceiver(); @@ -106,13 +106,12 @@ class FQTermSSHPacketReceiver: public QObject { void consume(int len); virtual int packetDataLen() const { return real_data_len_;} - int getIVSize() const { return cipher_->getIVSize();} - int getKeySize() const { return cipher_->getKeySize();} + virtual int getIVSize() const { return cipher->IVSize;} + virtual int getKeySize() const { return cipher->keySize;} int getMacKeySize() const { return mac_->keySize();} virtual void parseData(FQTermSSHBuffer *input) = 0; public slots: - virtual void setEncryptionType(int cipherType); void startEncryption(const u_char *key, const u_char *IV = NULL); void resetEncryption(); @@ -129,7 +128,6 @@ class FQTermSSHPacketReceiver: public QObject { protected: bool is_decrypt_; int cipher_type_; - FQTermSSHCipher *cipher_; bool is_mac_; int mac_type_; diff --git a/src/protocol/internal/ssh_3des-ssh1.c b/src/protocol/internal/ssh_3des-ssh1.c new file mode 100644 index 0000000..9f78298 --- /dev/null +++ b/src/protocol/internal/ssh_3des-ssh1.c @@ -0,0 +1,82 @@ +#include "ssh_cipher.h" +#include +#include + +struct ssh1_3des_priv +{ + DES_cblock d_IV1; + DES_cblock d_IV2; + DES_cblock d_IV3; + DES_key_schedule d_key1; + DES_key_schedule d_key2; + DES_key_schedule d_key3; +}; + +static int +init_3des(SSH_CIPHER* my) +{ + struct ssh1_3des_priv *priv = (struct ssh1_3des_priv*)my->priv; + const_DES_cblock *key = (const_DES_cblock*)my->key; + DES_set_key(key, &priv->d_key1); + DES_set_key(key+1, &priv->d_key2); + DES_set_key(key+2, &priv->d_key3); + memset(priv->d_IV1, 0, sizeof(DES_cblock)); + memset(priv->d_IV2, 0, sizeof(DES_cblock)); + memset(priv->d_IV3, 0, sizeof(DES_cblock)); + + return 1; +} + +static void +cleanup(SSH_CIPHER* my) +{ + if (my->key!=NULL) + free(my->key); + + if (my->priv!=NULL) + free(my->priv); + + free(my); +} + +static int +decrypt(SSH_CIPHER* my, const u_char *source, u_char *dest, size_t len) +{ + struct ssh1_3des_priv *priv = (struct ssh1_3des_priv*)my->priv; + DES_ncbc_encrypt(source, dest, len, &priv->d_key3, &priv->d_IV3, 0); + DES_ncbc_encrypt(dest, dest, len, &priv->d_key2, &priv->d_IV2, 1); + DES_ncbc_encrypt(dest, dest, len, &priv->d_key1, &priv->d_IV1, 0); + return 1; +} + +static int +encrypt(SSH_CIPHER* my, const u_char *source, u_char *dest, size_t len) +{ + struct ssh1_3des_priv *priv = (struct ssh1_3des_priv*)my->priv; + DES_ncbc_encrypt(source, dest, len, &priv->d_key1, &priv->d_IV1, 1); + DES_ncbc_encrypt(dest, dest, len, &priv->d_key2, &priv->d_IV2, 0); + DES_ncbc_encrypt(dest, dest, len, &priv->d_key3, &priv->d_IV3, 1); + return 1; +} + + +SSH_CIPHER* +new_3des_ssh1(int enc) +{ + SSH_CIPHER *cipher = (SSH_CIPHER*)malloc(sizeof(SSH_CIPHER)); + cipher->priv = malloc(sizeof(struct ssh1_3des_priv)); + cipher->blkSize = 8; + cipher->IVSize = 0; + cipher->keySize = 24; + cipher->IV = NULL; + cipher->key = (unsigned char*)malloc(24); + if (enc) + cipher->crypt = encrypt; + else + cipher->crypt = decrypt; + + cipher->init = init_3des; + cipher->cleanup = cleanup; + + return cipher; +} diff --git a/src/protocol/internal/ssh_cipher.h b/src/protocol/internal/ssh_cipher.h new file mode 100644 index 0000000..ec51062 --- /dev/null +++ b/src/protocol/internal/ssh_cipher.h @@ -0,0 +1,46 @@ +#ifndef SSH_CIPHER_H +#define SSH_CIPHER_H + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + + typedef struct ssh_cipher_t SSH_CIPHER; + typedef int (*crypt_t)(SSH_CIPHER*, const uint8_t*, uint8_t*, size_t); + typedef int (*init_t)(SSH_CIPHER*); + typedef void (*cleanup_t)(SSH_CIPHER*); + + struct ssh_cipher_t + { + /* + * priv is used for things like EVP_CIPHER_CTX and EVP_CIPHER + * + * We use only one crypt function for encrypt or decrypt. + * + * Before using the crypto function, IV and key must + * be set and then init function must be called + */ + unsigned char *IV; + unsigned char *key; + void *priv; + crypt_t crypt; + init_t init; + cleanup_t cleanup; + size_t blkSize; + size_t keySize; + size_t IVSize; + }; + + typedef const EVP_CIPHER*(*SSH_EVP)(void); + SSH_CIPHER* new_ssh_cipher_evp(SSH_EVP, size_t key, size_t iv, size_t blk, int enc); + SSH_CIPHER* new_3des_ssh1(int); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/protocol/internal/ssh_evp_cipher.c b/src/protocol/internal/ssh_evp_cipher.c new file mode 100644 index 0000000..29f8434 --- /dev/null +++ b/src/protocol/internal/ssh_evp_cipher.c @@ -0,0 +1,63 @@ +#include "ssh_cipher.h" + +struct evp_priv +{ + SSH_EVP evp; + EVP_CIPHER_CTX *ctx; + int enc; +}; + +static int +cipher_init(SSH_CIPHER* my) +{ + struct evp_priv *priv = (struct evp_priv*)my->priv; + priv->ctx = EVP_CIPHER_CTX_new(); + EVP_CIPHER_CTX_init(priv->ctx); + return EVP_CipherInit(priv->ctx, priv->evp(), my->key, my->IV, priv->enc); +} + +static int +do_crypt(SSH_CIPHER* my, const uint8_t* in, uint8_t* out, size_t l) +{ + return EVP_Cipher(((struct evp_priv*)my->priv)->ctx, out, in, l); +} + +static void +cleanup(SSH_CIPHER* my) +{ + if (my->IV!=NULL) + free(my->IV); + + if (my->key!=NULL) + free(my->key); + + if (my->priv!=NULL) { + struct evp_priv *priv = my->priv; + if (priv->ctx!=NULL) + EVP_CIPHER_CTX_free(priv->ctx); + + free(priv); + } + + free(my); +} + +SSH_CIPHER* +new_ssh_cipher_evp(SSH_EVP evp, size_t ks, size_t is, size_t bs, int enc) +{ + SSH_CIPHER *cipher = (SSH_CIPHER*)malloc(sizeof(SSH_CIPHER)); + cipher->priv = malloc(sizeof(struct evp_priv)); + struct evp_priv *priv = (struct evp_priv*)cipher->priv; + priv->evp = evp; + priv->enc = enc; + priv->ctx = NULL; + cipher->blkSize = bs; + cipher->keySize = ks; + cipher->IVSize = is; + cipher->key = (unsigned char*)malloc(ks); + cipher->IV = (unsigned char*)malloc(is); + cipher->init = cipher_init; + cipher->crypt = do_crypt; + cipher->cleanup = cleanup; + return cipher; +} -- cgit v1.2.3