From 50d144a7305c6f454a8f8f1a10ac7234eac2ceeb Mon Sep 17 00:00:00 2001 From: Iru Cai Date: Tue, 8 Nov 2016 11:40:32 +0800 Subject: add aes-ctr cipher support --- src/protocol/CMakeLists.txt | 9 ++++--- src/protocol/internal/all_ciphers.c | 34 +++++++++++++++++++++++++++ src/protocol/internal/fqterm_ssh2_kex.cpp | 39 ++++++++++++++++++++++++++----- src/protocol/internal/ssh_cipher.h | 5 ++++ src/protocol/internal/ssh_crypto_common.c | 39 +++++++++++++++++++++++++++++++ src/protocol/internal/ssh_crypto_common.h | 20 ++++++++++++++++ 6 files changed, 137 insertions(+), 9 deletions(-) create mode 100644 src/protocol/internal/all_ciphers.c create mode 100644 src/protocol/internal/ssh_crypto_common.c create mode 100644 src/protocol/internal/ssh_crypto_common.h diff --git a/src/protocol/CMakeLists.txt b/src/protocol/CMakeLists.txt index 5803cb5..890a658 100644 --- a/src/protocol/CMakeLists.txt +++ b/src/protocol/CMakeLists.txt @@ -13,13 +13,16 @@ set(export_SRCS ) set(internal_SRCS + internal/ssh_crypto_common.h + internal/ssh_crypto_common.c + internal/ssh_cipher.h + internal/all_ciphers.c + internal/ssh_evp_cipher.c + internal/ssh_3des-ssh1.c internal/ssh_pubkey_crypto.h 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 diff --git a/src/protocol/internal/all_ciphers.c b/src/protocol/internal/all_ciphers.c new file mode 100644 index 0000000..3a524ee --- /dev/null +++ b/src/protocol/internal/all_ciphers.c @@ -0,0 +1,34 @@ +#include "ssh_crypto_common.h" +#include "ssh_cipher.h" +#include + +#define EVP_CIPHER_FUNC(name, evp, k, i, b) \ + static SSH_CIPHER* evp_##name(int e) { return new_ssh_cipher_evp(evp, k, i, b, e); } + +EVP_CIPHER_FUNC(aes256_ctr, EVP_aes_256_ctr, 32, 16, 16) +EVP_CIPHER_FUNC(aes192_ctr, EVP_aes_192_ctr, 24, 16, 16) +EVP_CIPHER_FUNC(aes128_ctr, EVP_aes_128_ctr, 16, 16, 16) +EVP_CIPHER_FUNC(3des_cbc, EVP_des_ede3_cbc, 24, 8, 8) + +struct +{ + const char *name; + NEW_CIPHER f; +} all_ciphers[] = { + { "aes256-ctr", evp_aes256_ctr }, + { "aes192-ctr", evp_aes192_ctr }, + { "aes128-ctr", evp_aes128_ctr }, + { "3des-cbc", evp_3des_cbc }, + { NULL, NULL } +}; + +NEW_CIPHER search_cipher(const char *s) +{ + int i = search_name((name_sp)all_ciphers, s); + if (i!=-1) + return all_ciphers[i].f; + else + return NULL; +} + +const char all_ciphers_list[] = "aes256-ctr,aes192-ctr,aes128-ctr,3des-cbc"; diff --git a/src/protocol/internal/fqterm_ssh2_kex.cpp b/src/protocol/internal/fqterm_ssh2_kex.cpp index e2fd784..59ec85e 100644 --- a/src/protocol/internal/fqterm_ssh2_kex.cpp +++ b/src/protocol/internal/fqterm_ssh2_kex.cpp @@ -137,8 +137,38 @@ void FQTermSSH2Kex::negotiateAlgorithms() { } this->dh = dh(); + // TODO: host key algorithms + size_t hk_algo_len = packet_receiver_->getInt(); + char hk_algo[hk_algo_len+1]; + packet_receiver_->getRawData(hk_algo, hk_algo_len); + hk_algo[hk_algo_len] = '\0'; + + // encryption algo c2s + size_t el_c2s_len = packet_receiver_->getInt(); + char el_c2s[el_c2s_len+1]; + packet_receiver_->getRawData(el_c2s, el_c2s_len); + el_c2s[el_c2s_len] = '\0'; + NEW_CIPHER c2s = search_cipher(el_c2s); + if (c2s==NULL) { + emit kexError(tr("No matching c2s cipher algorithms!")); + return; + } + packet_sender_->cipher = c2s(1); + + // encryption algo s2c + size_t el_s2c_len = packet_receiver_->getInt(); + char el_s2c[el_s2c_len+1]; + packet_receiver_->getRawData(el_s2c, el_s2c_len); + el_s2c[el_s2c_len] = '\0'; + NEW_CIPHER s2c = search_cipher(el_s2c); + if (s2c==NULL) { + emit kexError(tr("No matching s2c cipher algorithms!")); + return; + } + packet_receiver_->cipher = s2c(0); + std::vector name_lists; - for (int i = 1; i < 10; ++i) { + for (int i = 4; i < 10; ++i) { int name_lists_len = packet_receiver_->getInt(); if (name_lists_len > 0) { name_lists.resize(name_lists_len); @@ -159,8 +189,8 @@ void FQTermSSH2Kex::negotiateAlgorithms() { packet_sender_->putRawData((const char*)cookie_, 16); // FIXME: generate new cookie_; packet_sender_->putString(all_dh_list); packet_sender_->putString("ssh-rsa"); - packet_sender_->putString("3des-cbc"); - packet_sender_->putString("3des-cbc"); + packet_sender_->putString(all_ciphers_list); + packet_sender_->putString(all_ciphers_list); packet_sender_->putString("hmac-sha1"); packet_sender_->putString("hmac-sha1"); packet_sender_->putString("none"); @@ -297,9 +327,6 @@ bool FQTermSSH2Kex::changeKeyAlg() { memcpy(session_id_, H_, SHA_DIGEST_LENGTH); } - 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/ssh_cipher.h b/src/protocol/internal/ssh_cipher.h index ec51062..94b83ed 100644 --- a/src/protocol/internal/ssh_cipher.h +++ b/src/protocol/internal/ssh_cipher.h @@ -36,8 +36,13 @@ extern "C" { }; typedef const EVP_CIPHER*(*SSH_EVP)(void); + typedef SSH_CIPHER*(*NEW_CIPHER)(int); + 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); + /* all_ciphers.c */ + extern const char all_ciphers_list[]; + NEW_CIPHER search_cipher(const char *s); #ifdef __cplusplus } diff --git a/src/protocol/internal/ssh_crypto_common.c b/src/protocol/internal/ssh_crypto_common.c new file mode 100644 index 0000000..0c16d9d --- /dev/null +++ b/src/protocol/internal/ssh_crypto_common.c @@ -0,0 +1,39 @@ +#include "ssh_crypto_common.h" +#include + +/* We need the first algorithm in the client side, + so search l first +*/ + +int +search_name(name_list l, const char *s) +{ + size_t ns = 1; + size_t i,j; + const char *p; + + if (*s=='\0') + return -1; + + for (p=s; *p; p++) { + if (*p==',') ns++; + } + const char *start[ns], *end[ns]; + + p = s; + for (i=0; i