summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIru Cai <mytbk920423@gmail.com>2016-11-08 11:40:32 +0800
committerIru Cai <mytbk920423@gmail.com>2016-11-08 15:17:38 +0800
commit50d144a7305c6f454a8f8f1a10ac7234eac2ceeb (patch)
tree4a5ccf4b14bed75689d97b01de47b77d2819fdbb
parent0a817b9fcb8e7a1bf5c4a910eb0de1a549b5ba9f (diff)
downloadfqterm-50d144a7305c6f454a8f8f1a10ac7234eac2ceeb.tar.xz
add aes-ctr cipher support
-rw-r--r--src/protocol/CMakeLists.txt9
-rw-r--r--src/protocol/internal/all_ciphers.c34
-rw-r--r--src/protocol/internal/fqterm_ssh2_kex.cpp39
-rw-r--r--src/protocol/internal/ssh_cipher.h5
-rw-r--r--src/protocol/internal/ssh_crypto_common.c39
-rw-r--r--src/protocol/internal/ssh_crypto_common.h20
6 files changed, 137 insertions, 9 deletions
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 <openssl/evp.h>
+
+#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<char> 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 <string.h>
+
+/* 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<ns; i++) {
+ start[i] = p;
+ end[i] = strchr(p, ',');
+ p = end[i]+1;
+ }
+ end[ns-1] = start[ns-1]+strlen(start[ns-1]);
+
+ for (i=0; l[i].name!=NULL; i++) {
+ size_t len = strlen(l[i].name);
+ for (j=0; j<ns; j++) {
+ if (start[j]+len==end[j] && strncmp(start[j],l[i].name,len)==0)
+ return i;
+ }
+ }
+ return -1;
+}
diff --git a/src/protocol/internal/ssh_crypto_common.h b/src/protocol/internal/ssh_crypto_common.h
new file mode 100644
index 0000000..c50029c
--- /dev/null
+++ b/src/protocol/internal/ssh_crypto_common.h
@@ -0,0 +1,20 @@
+#ifndef SSH_CRYPTO_COMMON_H
+#define SSH_CRYPTO_COMMON_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+ typedef struct
+ {
+ const char *name;
+ void *f;
+ } *name_sp, name_list[]; /* Do not write as *name_list!!! */
+
+ int search_name(name_list l, const char *s);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif