From 94d81c6a60a85ad216ee494678bd2965bfd6ffb5 Mon Sep 17 00:00:00 2001 From: Iru Cai Date: Mon, 4 Jun 2018 10:54:34 +0800 Subject: curve25519 ECDH --- src/protocol/CMakeLists.txt | 2 ++ src/protocol/internal/ssh_diffie-hellman.c | 57 ++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+) diff --git a/src/protocol/CMakeLists.txt b/src/protocol/CMakeLists.txt index c4c9e0f..57cd0a8 100644 --- a/src/protocol/CMakeLists.txt +++ b/src/protocol/CMakeLists.txt @@ -29,6 +29,8 @@ set(internal_SRCS internal/ssh_diffie-hellman.c internal/crc32.c internal/ssh_packet.c + internal/curve25519/smult.c + internal/curve25519/base.c internal/fqterm_ssh_auth.h internal/fqterm_ssh_const.h internal/fqterm_ssh_kex.h diff --git a/src/protocol/internal/ssh_diffie-hellman.c b/src/protocol/internal/ssh_diffie-hellman.c index e413fad..ed1d6e8 100644 --- a/src/protocol/internal/ssh_diffie-hellman.c +++ b/src/protocol/internal/ssh_diffie-hellman.c @@ -1,7 +1,9 @@ #include "ssh_diffie-hellman.h" #include "ssh_session.h" #include "ssh_crypto_common.h" +#include "curve25519/crypto_scalarmult.h" #include +#include static const char DH_G16_SHA512[] = "diffie-hellman-group16-sha512"; static const char DH_G14_SHA256[] = "diffie-hellman-group14-sha256"; @@ -215,6 +217,38 @@ ssh_dh_group16_sha512(void) return dh; } +static void ecdh_compute(SSH_DH *dh) +{ + int i; + + /* FIXME: check return value and throw error */ + RAND_bytes(dh->priv.privkey, 32); + + dh->priv.privkey[0] &= 248; + dh->priv.privkey[31] &= 127; + dh->priv.privkey[31] |= 64; + + dh->e_len = 36; + dh->mpint_e = (unsigned char*)malloc(36); + dh->mpint_e[0] = dh->mpint_e[1] = dh->mpint_e[2] = 0; + dh->mpint_e[3] = 32; + crypto_scalarmult_base(dh->mpint_e + 4, dh->priv.privkey); +} + +static SSH_DH * +ssh_dh_curve25519_sha256(void) +{ + SSH_DH *dh = (SSH_DH*)malloc(sizeof(SSH_DH)); + dh->name = DH_CURVE25519_SHA256; + dh->digest = (evp_md_t) { + .mdctx = ssh_md_ctx_new(), + .md = EVP_sha256(), + .hashlen = SHA256_DIGEST_LENGTH + }; + ecdh_compute(dh); + return dh; +} + void ssh_dh_hash(SSH_DH *dh, const unsigned char *in, unsigned char *out, size_t n) { @@ -223,8 +257,28 @@ ssh_dh_hash(SSH_DH *dh, const unsigned char *in, unsigned char *out, size_t n) EVP_DigestFinal_ex(dh->digest.mdctx, out, NULL); } +static int ecdh_compute_secret(SSH_DH *dh, const unsigned char *f_bin, int f_len) +{ + unsigned char s[32]; + int i, j; + + if (f_len != 32) + return -1; + crypto_scalarmult(s, dh->priv.privkey, f_bin); + BIGNUM *bn_k = BN_new(); + BN_bin2bn(s, 32, bn_k); + dh->secret_len = BN_bn2mpi(bn_k, NULL); + dh->secret = (unsigned char*)malloc(dh->secret_len); + BN_bn2mpi(bn_k, dh->secret); + BN_clear_free(bn_k); + return 0; +} + int ssh_dh_compute_secret(SSH_DH *dh, const unsigned char *f_bin, int f_len) { + if (dh->name == DH_CURVE25519_SHA256) + return ecdh_compute_secret(dh, f_bin, f_len); + BIGNUM *bn_f = BN_new(); if (bn_f == NULL || BN_bin2bn(f_bin, f_len, bn_f) == NULL) return -1; @@ -233,6 +287,7 @@ int ssh_dh_compute_secret(SSH_DH *dh, const unsigned char *f_bin, int f_len) dh->secret_len = BN_bn2mpi(bn_k, NULL); dh->secret = (unsigned char*)malloc(dh->secret_len); BN_bn2mpi(bn_k, dh->secret); + BN_clear_free(bn_k); return 0; } @@ -243,6 +298,7 @@ struct const char *name; NEW_DH f; } all_dh[] = { + { DH_CURVE25519_SHA256, ssh_dh_curve25519_sha256 }, { DH_G16_SHA512, ssh_dh_group16_sha512 }, { DH_G14_SHA256, ssh_dh_group14_sha256 }, { DH_G14_SHA1, ssh_dh_group14_sha1 }, @@ -261,6 +317,7 @@ search_dh(const char *s) } const char all_dh_list[] = + "curve25519-sha256@libssh.org," "diffie-hellman-group16-sha512,diffie-hellman-group14-sha256," "diffie-hellman-group14-sha1,diffie-hellman-group1-sha1"; -- cgit v1.2.3