From 92c88c20fe34add9876e9d4e89813ea285f1bbac Mon Sep 17 00:00:00 2001 From: Iru Cai Date: Fri, 4 Nov 2016 17:43:04 +0800 Subject: Use ssh_diffie-hellman, the new SSH diffie hellman code And add diffie-hellman-group14-sha1 support --- src/protocol/CMakeLists.txt | 2 + src/protocol/internal/fqterm_ssh2_kex.cpp | 55 +++++--------- src/protocol/internal/fqterm_ssh2_kex.h | 6 +- src/protocol/internal/ssh_diffie-hellman.c | 115 +++++++++++++++++++++++++++++ src/protocol/internal/ssh_diffie-hellman.h | 33 +++++++++ 5 files changed, 173 insertions(+), 38 deletions(-) create mode 100644 src/protocol/internal/ssh_diffie-hellman.c create mode 100644 src/protocol/internal/ssh_diffie-hellman.h diff --git a/src/protocol/CMakeLists.txt b/src/protocol/CMakeLists.txt index 498d351..84fddf4 100644 --- a/src/protocol/CMakeLists.txt +++ b/src/protocol/CMakeLists.txt @@ -15,6 +15,8 @@ set(export_SRCS set(internal_SRCS internal/ssh_pubkey_crypto.h internal/ssh_pubkey_crypto.c + internal/ssh_diffie-hellman.h + internal/ssh_diffie-hellman.c internal/crc32.h internal/fqterm_serialization.h internal/fqterm_ssh_auth.h diff --git a/src/protocol/internal/fqterm_ssh2_kex.cpp b/src/protocol/internal/fqterm_ssh2_kex.cpp index 3a8b75a..137a41e 100644 --- a/src/protocol/internal/fqterm_ssh2_kex.cpp +++ b/src/protocol/internal/fqterm_ssh2_kex.cpp @@ -33,27 +33,6 @@ namespace FQTerm { -static const int g = 2; -static const int q = 128; -static const unsigned char p[q]={ - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34, - 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, - 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, - 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, - 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, - 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, - 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37, - 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, - 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, - 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, - 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED, - 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, - 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6, - 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE6, 0x53, 0x81, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF -}; - FQTermSSH2Kex::FQTermSSH2Kex(const char *V_C, const char *V_S) : FQTermSSHKex(V_C, V_S) { is_first_kex_ = true; @@ -66,16 +45,11 @@ FQTermSSH2Kex::FQTermSSH2Kex(const char *V_C, const char *V_S) bn_x_ = BN_new(); bn_e_ = BN_new(); - bn_g_ = BN_new(); - bn_p_ = BN_new(); ctx_ = BN_CTX_new(); bn_K_ = BN_new(); bn_f_ = BN_new(); - BN_set_word(bn_g_, g); - BN_bin2bn(p, q, bn_p_); - session_id_ = NULL; } @@ -85,8 +59,7 @@ FQTermSSH2Kex::~FQTermSSH2Kex() { BN_clear_free(bn_x_); BN_clear_free(bn_e_); - BN_clear_free(bn_g_); - BN_clear_free(bn_p_); + ssh_dh_free(dh); BN_CTX_free(ctx_); BN_clear_free(bn_K_); @@ -151,8 +124,20 @@ void FQTermSSH2Kex::negotiateAlgorithms() { // 1. Parse server kex init packet packet_receiver_->getRawData((char*)cookie_, 16); + // select KEX algorithm + size_t kl_len = packet_receiver_->getInt(); + char kex_algos[kl_len+1]; + packet_receiver_->getRawData(kex_algos, kl_len); + kex_algos[kl_len] = '\0'; + NEW_DH dh = search_dh(kex_algos); + if (dh==NULL) { + emit kexError(tr("No matching KEX algorithms!")); + return; + } + this->dh = dh(); + std::vector name_lists; - for (int i = 0; i < 10; ++i) { + for (int i = 1; i < 10; ++i) { int name_lists_len = packet_receiver_->getInt(); if (name_lists_len > 0) { name_lists.resize(name_lists_len); @@ -171,7 +156,7 @@ void FQTermSSH2Kex::negotiateAlgorithms() { // 2. compose a kex init packet. packet_sender_->startPacket(SSH2_MSG_KEXINIT); packet_sender_->putRawData((const char*)cookie_, 16); // FIXME: generate new cookie_; - packet_sender_->putString("diffie-hellman-group1-sha1"); + packet_sender_->putString(all_dh_list); packet_sender_->putString("ssh-rsa"); packet_sender_->putString("3des-cbc"); packet_sender_->putString("3des-cbc"); @@ -196,8 +181,8 @@ void FQTermSSH2Kex::negotiateAlgorithms() { } void FQTermSSH2Kex::exchangeKey() { - BN_rand(bn_x_, q, 0, -1); - BN_mod_exp(bn_e_, bn_g_, bn_x_, bn_p_, ctx_); + BN_pseudo_rand_range(bn_x_, dh->p); + BN_mod_exp(bn_e_, dh->g, bn_x_, dh->p, ctx_); packet_sender_->startPacket(SSH2_MSG_KEXDH_INIT); packet_sender_->putBN2(bn_e_); @@ -222,7 +207,7 @@ bool FQTermSSH2Kex::verifyKey() { int s_len = -1; unsigned char *s = (unsigned char *)packet_receiver_->getString(&s_len); - BN_mod_exp(bn_K_, bn_f_, bn_x_, bn_p_, ctx_); + BN_mod_exp(bn_K_, bn_f_, bn_x_, dh->p, ctx_); FQTermSSHBuffer *buffer = packet_sender_->output_buffer_; @@ -236,11 +221,11 @@ bool FQTermSSH2Kex::verifyKey() { buffer->putSSH2BN(bn_f_); buffer->putSSH2BN(bn_K_); - SHA1(buffer->data(), buffer->len(), H_); + dh->hash(buffer->data(), buffer->len(), H_); // Start verify unsigned char s_H[SHA_DIGEST_LENGTH]; - SHA1(H_, SHA_DIGEST_LENGTH, s_H); + SHA1(H_, dh->hashlen, s_H); // Ignore the first 15 bytes of the signature of H sent from server: // algorithm_name_length[4], algorithm_name[7]("ssh-rsa") and signature_length[4]. diff --git a/src/protocol/internal/fqterm_ssh2_kex.h b/src/protocol/internal/fqterm_ssh2_kex.h index 23beba2..59e3330 100644 --- a/src/protocol/internal/fqterm_ssh2_kex.h +++ b/src/protocol/internal/fqterm_ssh2_kex.h @@ -24,6 +24,7 @@ #include #include "fqterm_ssh_kex.h" +#include "ssh_diffie-hellman.h" namespace FQTerm { @@ -55,16 +56,15 @@ private: int I_S_len_; char *I_S_; + SSH_DH *dh; BIGNUM *bn_x_; BIGNUM *bn_e_; - BIGNUM *bn_g_; - BIGNUM *bn_p_; BN_CTX *ctx_; BIGNUM *bn_K_; BIGNUM *bn_f_; - unsigned char H_[SHA_DIGEST_LENGTH]; + unsigned char H_[SHA512_DIGEST_LENGTH]; unsigned char *session_id_; diff --git a/src/protocol/internal/ssh_diffie-hellman.c b/src/protocol/internal/ssh_diffie-hellman.c new file mode 100644 index 0000000..1866b2f --- /dev/null +++ b/src/protocol/internal/ssh_diffie-hellman.c @@ -0,0 +1,115 @@ +#include "ssh_diffie-hellman.h" +#include "ssh_crypto_common.h" +#include + +static const int g = 2; + +static const unsigned char prime_group1[]={ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34, + 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, + 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, + 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, + 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, + 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, + 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37, + 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, + 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, + 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, + 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED, + 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, + 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6, + 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE6, 0x53, 0x81, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF +}; + +static const unsigned char prime_group14[] = { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34, + 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, + 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, + 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, + 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, + 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, + 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37, + 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, + 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, + 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, + 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED, + 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, + 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6, + 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D, + 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, + 0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A, + 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F, + 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, + 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB, + 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, + 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, + 0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C, + 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B, + 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, + 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F, + 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9, + 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, + 0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5, + 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10, + 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAC, 0xAA, 0x68, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF +}; + +void +ssh_dh_free(SSH_DH *dh) +{ + BN_free(dh->g); + BN_free(dh->p); + free(dh); +} + +SSH_DH * +ssh_dh_group1_sha1(void) +{ + SSH_DH *dh = (SSH_DH*)malloc(sizeof(SSH_DH)); + dh->g = BN_new(); + dh->p = BN_new(); + dh->hash = SHA1; + dh->hashlen = SHA_DIGEST_LENGTH; + BN_set_word(dh->g, g); + BN_bin2bn(prime_group1, 128, dh->p); + return dh; +} + +SSH_DH * +ssh_dh_group14_sha1(void) +{ + SSH_DH *dh = (SSH_DH*)malloc(sizeof(SSH_DH)); + dh->g = BN_new(); + dh->p = BN_new(); + dh->hash = SHA1; + dh->hashlen = SHA_DIGEST_LENGTH; + BN_set_word(dh->g, g); + BN_bin2bn(prime_group14, 256, dh->p); + return dh; +} + +struct +{ + const char *name; + NEW_DH f; +} all_dh[] = { + { "diffie-hellman-group14-sha1", ssh_dh_group14_sha1 }, + { "diffie-hellman-group1-sha1", ssh_dh_group1_sha1 }, + { NULL, NULL } +}; + +NEW_DH +search_dh(const char *s) +{ + int i = search_name((name_sp)all_dh, s); + if (i!=-1) + return all_dh[i].f; + else + return NULL; +} + +const char all_dh_list[] = "diffie-hellman-group14-sha1,diffie-hellman-group1-sha1"; diff --git a/src/protocol/internal/ssh_diffie-hellman.h b/src/protocol/internal/ssh_diffie-hellman.h new file mode 100644 index 0000000..5468fdb --- /dev/null +++ b/src/protocol/internal/ssh_diffie-hellman.h @@ -0,0 +1,33 @@ +#ifndef SSH_DH_H +#define SSH_DH_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + + typedef unsigned char* (*hash_t)(const unsigned char *, size_t, unsigned char *); + + typedef struct ssh_diffie_hellman + { + BIGNUM *g; // generator + BIGNUM *p; // prime + hash_t hash; // can be SHA1 or SHA256 + size_t hashlen; + } SSH_DH; + + void ssh_dh_free(SSH_DH*); + SSH_DH *ssh_dh_group1_sha1(void); + SSH_DH *ssh_dh_group14_sha1(void); + + typedef SSH_DH*(*NEW_DH)(void); + extern const char all_dh_list[]; + NEW_DH search_dh(const char *s); + +#ifdef __cplusplus +} +#endif + +#endif -- cgit v1.2.3