version 1.33, 2019/01/21 10:00:23 |
version 1.34, 2019/01/21 10:03:37 |
|
|
input_kex_dh_init(int type, u_int32_t seq, struct ssh *ssh) |
input_kex_dh_init(int type, u_int32_t seq, struct ssh *ssh) |
{ |
{ |
struct kex *kex = ssh->kex; |
struct kex *kex = ssh->kex; |
BIGNUM *shared_secret = NULL, *dh_client_pub = NULL; |
BIGNUM *dh_client_pub = NULL; |
const BIGNUM *pub_key; |
const BIGNUM *pub_key; |
struct sshkey *server_host_public, *server_host_private; |
struct sshkey *server_host_public, *server_host_private; |
u_char *kbuf = NULL, *signature = NULL, *server_host_key_blob = NULL; |
struct sshbuf *shared_secret = NULL; |
|
u_char *signature = NULL, *server_host_key_blob = NULL; |
u_char hash[SSH_DIGEST_MAX_LENGTH]; |
u_char hash[SSH_DIGEST_MAX_LENGTH]; |
size_t sbloblen, slen; |
size_t sbloblen, slen; |
size_t klen = 0, hashlen; |
size_t hashlen; |
int kout, r; |
int r; |
|
|
if (kex->load_host_public_key == NULL || |
if (kex->load_host_public_key == NULL || |
kex->load_host_private_key == NULL) { |
kex->load_host_private_key == NULL) { |
|
|
if ((r = sshpkt_get_bignum2(ssh, &dh_client_pub)) != 0 || |
if ((r = sshpkt_get_bignum2(ssh, &dh_client_pub)) != 0 || |
(r = sshpkt_get_end(ssh)) != 0) |
(r = sshpkt_get_end(ssh)) != 0) |
goto out; |
goto out; |
DH_get0_key(kex->dh, &pub_key, NULL); |
if ((shared_secret = sshbuf_new()) == NULL) { |
|
|
#ifdef DEBUG_KEXDH |
|
fprintf(stderr, "dh_client_pub= "); |
|
BN_print_fp(stderr, dh_client_pub); |
|
fprintf(stderr, "\n"); |
|
debug("bits %d", BN_num_bits(dh_client_pub)); |
|
DHparams_print_fp(stderr, kex->dh); |
|
fprintf(stderr, "pub= "); |
|
BN_print_fp(stderr, pub_key); |
|
fprintf(stderr, "\n"); |
|
#endif |
|
if (!dh_pub_is_valid(kex->dh, dh_client_pub)) { |
|
sshpkt_disconnect(ssh, "bad client public DH value"); |
|
r = SSH_ERR_MESSAGE_INCOMPLETE; |
|
goto out; |
|
} |
|
|
|
klen = DH_size(kex->dh); |
|
if ((kbuf = malloc(klen)) == NULL || |
|
(shared_secret = BN_new()) == NULL) { |
|
r = SSH_ERR_ALLOC_FAIL; |
r = SSH_ERR_ALLOC_FAIL; |
goto out; |
goto out; |
} |
} |
if ((kout = DH_compute_key(kbuf, dh_client_pub, kex->dh)) < 0 || |
if ((r = kex_dh_compute_key(kex, dh_client_pub, shared_secret)) != 0) |
BN_bin2bn(kbuf, kout, shared_secret) == NULL) { |
|
r = SSH_ERR_LIBCRYPTO_ERROR; |
|
goto out; |
goto out; |
} |
|
#ifdef DEBUG_KEXDH |
|
dump_digest("shared secret", kbuf, kout); |
|
#endif |
|
if ((r = sshkey_to_blob(server_host_public, &server_host_key_blob, |
if ((r = sshkey_to_blob(server_host_public, &server_host_key_blob, |
&sbloblen)) != 0) |
&sbloblen)) != 0) |
goto out; |
goto out; |
/* calc H */ |
/* calc H */ |
|
DH_get0_key(kex->dh, &pub_key, NULL); |
hashlen = sizeof(hash); |
hashlen = sizeof(hash); |
if ((r = kex_dh_hash( |
if ((r = kex_dh_hash( |
kex->hash_alg, |
kex->hash_alg, |
|
|
server_host_key_blob, sbloblen, |
server_host_key_blob, sbloblen, |
dh_client_pub, |
dh_client_pub, |
pub_key, |
pub_key, |
shared_secret, |
sshbuf_ptr(shared_secret), sshbuf_len(shared_secret), |
hash, &hashlen)) != 0) |
hash, &hashlen)) != 0) |
goto out; |
goto out; |
|
|
|
|
&signature, &slen, hash, hashlen, kex->hostkey_alg)) < 0) |
&signature, &slen, hash, hashlen, kex->hostkey_alg)) < 0) |
goto out; |
goto out; |
|
|
/* destroy_sensitive_data(); */ |
|
|
|
/* send server hostkey, DH pubkey 'f' and signed H */ |
/* send server hostkey, DH pubkey 'f' and signed H */ |
if ((r = sshpkt_start(ssh, SSH2_MSG_KEXDH_REPLY)) != 0 || |
if ((r = sshpkt_start(ssh, SSH2_MSG_KEXDH_REPLY)) != 0 || |
(r = sshpkt_put_string(ssh, server_host_key_blob, sbloblen)) != 0 || |
(r = sshpkt_put_string(ssh, server_host_key_blob, sbloblen)) != 0 || |
|
|
(r = sshpkt_send(ssh)) != 0) |
(r = sshpkt_send(ssh)) != 0) |
goto out; |
goto out; |
|
|
if ((r = kex_derive_keys_bn(ssh, hash, hashlen, shared_secret)) == 0) |
if ((r = kex_derive_keys(ssh, hash, hashlen, shared_secret)) == 0) |
r = kex_send_newkeys(ssh); |
r = kex_send_newkeys(ssh); |
out: |
out: |
explicit_bzero(hash, sizeof(hash)); |
explicit_bzero(hash, sizeof(hash)); |
DH_free(kex->dh); |
DH_free(kex->dh); |
kex->dh = NULL; |
kex->dh = NULL; |
BN_clear_free(dh_client_pub); |
BN_clear_free(dh_client_pub); |
if (kbuf) { |
sshbuf_free(shared_secret); |
explicit_bzero(kbuf, klen); |
|
free(kbuf); |
|
} |
|
BN_clear_free(shared_secret); |
|
free(server_host_key_blob); |
free(server_host_key_blob); |
free(signature); |
free(signature); |
return r; |
return r; |