diff options
author | Iru Cai <mytbk920423@gmail.com> | 2018-06-04 10:54:34 +0800 |
---|---|---|
committer | Iru Cai <mytbk920423@gmail.com> | 2018-06-06 21:24:00 +0800 |
commit | 94d81c6a60a85ad216ee494678bd2965bfd6ffb5 (patch) | |
tree | d3521ee6fbf4b4ef074b2ee2b9591d3f9a38b58f /src/protocol/internal/ssh_diffie-hellman.c | |
parent | 5ced18152ee31c1d469e7ec3a1e09b5ff0ae3814 (diff) | |
download | fqterm-94d81c6a60a85ad216ee494678bd2965bfd6ffb5.tar.xz |
curve25519 ECDH
Diffstat (limited to 'src/protocol/internal/ssh_diffie-hellman.c')
-rw-r--r-- | src/protocol/internal/ssh_diffie-hellman.c | 57 |
1 files changed, 57 insertions, 0 deletions
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 <stdlib.h> +#include <openssl/rand.h> 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"; |