[Chinese-commits] [fqterm] 09/16: add aes-ctr cipher support

Boyuan Yang hosiet-guest at moszumanska.debian.org
Sun Dec 18 15:36:26 UTC 2016


This is an automated email from the git hooks/post-receive script.

hosiet-guest pushed a commit to branch master
in repository fqterm.

commit 50d144a7305c6f454a8f8f1a10ac7234eac2ceeb
Author: Iru Cai <mytbk920423 at gmail.com>
Date:   Tue Nov 8 11:40:32 2016 +0800

    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(-)

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

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/chinese/fqterm.git



More information about the Chinese-commits mailing list