summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIru Cai <mytbk920423@gmail.com>2016-11-05 14:54:10 +0800
committerIru Cai <mytbk920423@gmail.com>2016-11-08 15:16:40 +0800
commit0a817b9fcb8e7a1bf5c4a910eb0de1a549b5ba9f (patch)
treef765c09f54e47f0d1e34afb5d09885579e946c76
parent92c88c20fe34add9876e9d4e89813ea285f1bbac (diff)
downloadfqterm-0a817b9fcb8e7a1bf5c4a910eb0de1a549b5ba9f.tar.xz
Implement ssh_cipher_t for symmetric ciphers in SSH
* remove FQTermSSHCipher and FQTermSSH3DES, use ssh_cipher_t instead * implement EVP ciphers and 3DES-SSH1
-rw-r--r--src/protocol/CMakeLists.txt6
-rw-r--r--src/protocol/internal/fqterm_ssh1_packet.cpp24
-rw-r--r--src/protocol/internal/fqterm_ssh1_packet.h3
-rw-r--r--src/protocol/internal/fqterm_ssh2_kex.cpp5
-rw-r--r--src/protocol/internal/fqterm_ssh2_packet.cpp50
-rw-r--r--src/protocol/internal/fqterm_ssh2_packet.h30
-rw-r--r--src/protocol/internal/fqterm_ssh_cipher.h58
-rw-r--r--src/protocol/internal/fqterm_ssh_des.cpp180
-rw-r--r--src/protocol/internal/fqterm_ssh_des.h74
-rw-r--r--src/protocol/internal/fqterm_ssh_packet.cpp73
-rw-r--r--src/protocol/internal/fqterm_ssh_packet.h18
-rw-r--r--src/protocol/internal/ssh_3des-ssh1.c82
-rw-r--r--src/protocol/internal/ssh_cipher.h46
-rw-r--r--src/protocol/internal/ssh_evp_cipher.c63
14 files changed, 275 insertions, 437 deletions
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<u_char> 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 <stdlib.h>
-
-#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 <memory.h>
-#include <openssl/des.h>
-#include <openssl/objects.h>
-#include <openssl/evp.h>
-
-#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 <openssl/ssl.h>
-#include <openssl/des.h>
-
-#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 <openssl/des.h>
+#include <string.h>
+
+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 <stdlib.h>
+#include <stdint.h>
+#include <openssl/evp.h>
+
+#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;
+}