1323124Sdes/* $OpenBSD: kexdhs.c,v 1.24 2016/05/02 10:26:04 djm Exp $ */ 2113908Sdes/* 3113908Sdes * Copyright (c) 2001 Markus Friedl. All rights reserved. 4113908Sdes * 5113908Sdes * Redistribution and use in source and binary forms, with or without 6113908Sdes * modification, are permitted provided that the following conditions 7113908Sdes * are met: 8113908Sdes * 1. Redistributions of source code must retain the above copyright 9113908Sdes * notice, this list of conditions and the following disclaimer. 10113908Sdes * 2. Redistributions in binary form must reproduce the above copyright 11113908Sdes * notice, this list of conditions and the following disclaimer in the 12113908Sdes * documentation and/or other materials provided with the distribution. 13113908Sdes * 14113908Sdes * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15113908Sdes * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16113908Sdes * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17113908Sdes * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 18113908Sdes * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19113908Sdes * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20113908Sdes * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21113908Sdes * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22113908Sdes * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23113908Sdes * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24113908Sdes */ 25113908Sdes 26113908Sdes#include "includes.h" 27113908Sdes 28295367Sdes#ifdef WITH_OPENSSL 29295367Sdes 30162852Sdes#include <sys/types.h> 31162852Sdes 32162852Sdes#include <stdarg.h> 33162852Sdes#include <string.h> 34162852Sdes#include <signal.h> 35162852Sdes 36221420Sdes#include <openssl/dh.h> 37221420Sdes 38295367Sdes#include "sshkey.h" 39162852Sdes#include "cipher.h" 40295367Sdes#include "digest.h" 41113908Sdes#include "kex.h" 42113908Sdes#include "log.h" 43113908Sdes#include "packet.h" 44113908Sdes#include "dh.h" 45113908Sdes#include "ssh2.h" 46113908Sdes 47295367Sdes#include "dispatch.h" 48295367Sdes#include "compat.h" 49295367Sdes#include "ssherr.h" 50295367Sdes#include "sshbuf.h" 51295367Sdes 52295367Sdesstatic int input_kex_dh_init(int, u_int32_t, void *); 53295367Sdes 54295367Sdesint 55295367Sdeskexdh_server(struct ssh *ssh) 56113908Sdes{ 57295367Sdes struct kex *kex = ssh->kex; 58295367Sdes int r; 59113908Sdes 60113908Sdes /* generate server DH public key */ 61137015Sdes switch (kex->kex_type) { 62137015Sdes case KEX_DH_GRP1_SHA1: 63295367Sdes kex->dh = dh_new_group1(); 64137015Sdes break; 65137015Sdes case KEX_DH_GRP14_SHA1: 66323124Sdes case KEX_DH_GRP14_SHA256: 67295367Sdes kex->dh = dh_new_group14(); 68137015Sdes break; 69323124Sdes case KEX_DH_GRP16_SHA512: 70323124Sdes kex->dh = dh_new_group16(); 71323124Sdes break; 72323124Sdes case KEX_DH_GRP18_SHA512: 73323124Sdes kex->dh = dh_new_group18(); 74323124Sdes break; 75137015Sdes default: 76295367Sdes r = SSH_ERR_INVALID_ARGUMENT; 77295367Sdes goto out; 78137015Sdes } 79295367Sdes if (kex->dh == NULL) { 80295367Sdes r = SSH_ERR_ALLOC_FAIL; 81295367Sdes goto out; 82295367Sdes } 83295367Sdes if ((r = dh_gen_key(kex->dh, kex->we_need * 8)) != 0) 84295367Sdes goto out; 85113908Sdes 86113908Sdes debug("expecting SSH2_MSG_KEXDH_INIT"); 87295367Sdes ssh_dispatch_set(ssh, SSH2_MSG_KEXDH_INIT, &input_kex_dh_init); 88295367Sdes r = 0; 89295367Sdes out: 90295367Sdes return r; 91295367Sdes} 92113908Sdes 93295367Sdesint 94295367Sdesinput_kex_dh_init(int type, u_int32_t seq, void *ctxt) 95295367Sdes{ 96295367Sdes struct ssh *ssh = ctxt; 97295367Sdes struct kex *kex = ssh->kex; 98295367Sdes BIGNUM *shared_secret = NULL, *dh_client_pub = NULL; 99295367Sdes struct sshkey *server_host_public, *server_host_private; 100295367Sdes u_char *kbuf = NULL, *signature = NULL, *server_host_key_blob = NULL; 101295367Sdes u_char hash[SSH_DIGEST_MAX_LENGTH]; 102295367Sdes size_t sbloblen, slen; 103295367Sdes size_t klen = 0, hashlen; 104295367Sdes int kout, r; 105295367Sdes 106204917Sdes if (kex->load_host_public_key == NULL || 107295367Sdes kex->load_host_private_key == NULL) { 108295367Sdes r = SSH_ERR_INVALID_ARGUMENT; 109295367Sdes goto out; 110295367Sdes } 111295367Sdes server_host_public = kex->load_host_public_key(kex->hostkey_type, 112295367Sdes kex->hostkey_nid, ssh); 113295367Sdes server_host_private = kex->load_host_private_key(kex->hostkey_type, 114295367Sdes kex->hostkey_nid, ssh); 115295367Sdes if (server_host_public == NULL) { 116295367Sdes r = SSH_ERR_NO_HOSTKEY_LOADED; 117295367Sdes goto out; 118295367Sdes } 119113908Sdes 120113908Sdes /* key, cert */ 121295367Sdes if ((dh_client_pub = BN_new()) == NULL) { 122295367Sdes r = SSH_ERR_ALLOC_FAIL; 123295367Sdes goto out; 124295367Sdes } 125295367Sdes if ((r = sshpkt_get_bignum2(ssh, dh_client_pub)) != 0 || 126295367Sdes (r = sshpkt_get_end(ssh)) != 0) 127295367Sdes goto out; 128113908Sdes 129113908Sdes#ifdef DEBUG_KEXDH 130113908Sdes fprintf(stderr, "dh_client_pub= "); 131113908Sdes BN_print_fp(stderr, dh_client_pub); 132113908Sdes fprintf(stderr, "\n"); 133113908Sdes debug("bits %d", BN_num_bits(dh_client_pub)); 134113908Sdes#endif 135113908Sdes 136113908Sdes#ifdef DEBUG_KEXDH 137295367Sdes DHparams_print_fp(stderr, kex->dh); 138113908Sdes fprintf(stderr, "pub= "); 139295367Sdes BN_print_fp(stderr, kex->dh->pub_key); 140113908Sdes fprintf(stderr, "\n"); 141113908Sdes#endif 142295367Sdes if (!dh_pub_is_valid(kex->dh, dh_client_pub)) { 143295367Sdes sshpkt_disconnect(ssh, "bad client public DH value"); 144295367Sdes r = SSH_ERR_MESSAGE_INCOMPLETE; 145295367Sdes goto out; 146295367Sdes } 147113908Sdes 148295367Sdes klen = DH_size(kex->dh); 149295367Sdes if ((kbuf = malloc(klen)) == NULL || 150295367Sdes (shared_secret = BN_new()) == NULL) { 151295367Sdes r = SSH_ERR_ALLOC_FAIL; 152295367Sdes goto out; 153295367Sdes } 154295367Sdes if ((kout = DH_compute_key(kbuf, dh_client_pub, kex->dh)) < 0 || 155295367Sdes BN_bin2bn(kbuf, kout, shared_secret) == NULL) { 156295367Sdes r = SSH_ERR_LIBCRYPTO_ERROR; 157295367Sdes goto out; 158295367Sdes } 159113908Sdes#ifdef DEBUG_KEXDH 160113908Sdes dump_digest("shared secret", kbuf, kout); 161113908Sdes#endif 162295367Sdes if ((r = sshkey_to_blob(server_host_public, &server_host_key_blob, 163295367Sdes &sbloblen)) != 0) 164295367Sdes goto out; 165113908Sdes /* calc H */ 166295367Sdes hashlen = sizeof(hash); 167295367Sdes if ((r = kex_dh_hash( 168323124Sdes kex->hash_alg, 169113908Sdes kex->client_version_string, 170113908Sdes kex->server_version_string, 171295367Sdes sshbuf_ptr(kex->peer), sshbuf_len(kex->peer), 172295367Sdes sshbuf_ptr(kex->my), sshbuf_len(kex->my), 173113908Sdes server_host_key_blob, sbloblen, 174113908Sdes dh_client_pub, 175295367Sdes kex->dh->pub_key, 176157016Sdes shared_secret, 177295367Sdes hash, &hashlen)) != 0) 178295367Sdes goto out; 179113908Sdes 180113908Sdes /* save session id := H */ 181113908Sdes if (kex->session_id == NULL) { 182157016Sdes kex->session_id_len = hashlen; 183295367Sdes kex->session_id = malloc(kex->session_id_len); 184295367Sdes if (kex->session_id == NULL) { 185295367Sdes r = SSH_ERR_ALLOC_FAIL; 186295367Sdes goto out; 187295367Sdes } 188113908Sdes memcpy(kex->session_id, hash, kex->session_id_len); 189113908Sdes } 190113908Sdes 191113908Sdes /* sign H */ 192296781Sdes if ((r = kex->sign(server_host_private, server_host_public, &signature, 193296781Sdes &slen, hash, hashlen, kex->hostkey_alg, ssh->compat)) < 0) 194295367Sdes goto out; 195113908Sdes 196113908Sdes /* destroy_sensitive_data(); */ 197113908Sdes 198113908Sdes /* send server hostkey, DH pubkey 'f' and singed H */ 199295367Sdes if ((r = sshpkt_start(ssh, SSH2_MSG_KEXDH_REPLY)) != 0 || 200295367Sdes (r = sshpkt_put_string(ssh, server_host_key_blob, sbloblen)) != 0 || 201295367Sdes (r = sshpkt_put_bignum2(ssh, kex->dh->pub_key)) != 0 || /* f */ 202295367Sdes (r = sshpkt_put_string(ssh, signature, slen)) != 0 || 203295367Sdes (r = sshpkt_send(ssh)) != 0) 204295367Sdes goto out; 205113908Sdes 206295367Sdes if ((r = kex_derive_keys_bn(ssh, hash, hashlen, shared_secret)) == 0) 207295367Sdes r = kex_send_newkeys(ssh); 208295367Sdes out: 209295367Sdes explicit_bzero(hash, sizeof(hash)); 210295367Sdes DH_free(kex->dh); 211295367Sdes kex->dh = NULL; 212295367Sdes if (dh_client_pub) 213295367Sdes BN_clear_free(dh_client_pub); 214295367Sdes if (kbuf) { 215295367Sdes explicit_bzero(kbuf, klen); 216295367Sdes free(kbuf); 217295367Sdes } 218295367Sdes if (shared_secret) 219295367Sdes BN_clear_free(shared_secret); 220295367Sdes free(server_host_key_blob); 221255767Sdes free(signature); 222295367Sdes return r; 223113908Sdes} 224295367Sdes#endif /* WITH_OPENSSL */ 225