kexgexc.c revision 162852
11590Srgrimes/* $OpenBSD: kexgexc.c,v 1.9 2006/08/03 03:34:42 deraadt Exp $ */ 21590Srgrimes/* 31590Srgrimes * Copyright (c) 2000 Niels Provos. All rights reserved. 41590Srgrimes * Copyright (c) 2001 Markus Friedl. All rights reserved. 51590Srgrimes * 61590Srgrimes * Redistribution and use in source and binary forms, with or without 71590Srgrimes * modification, are permitted provided that the following conditions 81590Srgrimes * are met: 91590Srgrimes * 1. Redistributions of source code must retain the above copyright 101590Srgrimes * notice, this list of conditions and the following disclaimer. 111590Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 121590Srgrimes * notice, this list of conditions and the following disclaimer in the 131590Srgrimes * documentation and/or other materials provided with the distribution. 141590Srgrimes * 151590Srgrimes * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 161590Srgrimes * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 171590Srgrimes * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 181590Srgrimes * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 191590Srgrimes * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 201590Srgrimes * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 211590Srgrimes * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 221590Srgrimes * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 231590Srgrimes * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 241590Srgrimes * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 251590Srgrimes */ 261590Srgrimes 271590Srgrimes#include "includes.h" 281590Srgrimes 291590Srgrimes#include <sys/types.h> 301590Srgrimes 3127751Scharnier#include <stdarg.h> 321590Srgrimes#include <stdio.h> 331590Srgrimes#include <string.h> 341590Srgrimes#include <signal.h> 351590Srgrimes 3694992Sbde#include "xmalloc.h" 371590Srgrimes#include "buffer.h" 3827751Scharnier#include "key.h" 3994992Sbde#include "cipher.h" 4027751Scharnier#include "kex.h" 411590Srgrimes#include "log.h" 4294504Scharnier#include "packet.h" 4394504Scharnier#include "dh.h" 4494504Scharnier#include "ssh2.h" 451590Srgrimes#include "compat.h" 461590Srgrimes 471590Srgrimesvoid 481590Srgrimeskexgex_client(Kex *kex) 491590Srgrimes{ 501590Srgrimes BIGNUM *dh_server_pub = NULL, *shared_secret = NULL; 511590Srgrimes BIGNUM *p = NULL, *g = NULL; 521590Srgrimes Key *server_host_key; 531590Srgrimes u_char *kbuf, *hash, *signature = NULL, *server_host_key_blob = NULL; 541590Srgrimes u_int klen, kout, slen, sbloblen, hashlen; 551590Srgrimes int min, max, nbits; 561590Srgrimes DH *dh; 571590Srgrimes 581590Srgrimes nbits = dh_estimate(kex->we_need * 8); 591590Srgrimes 601590Srgrimes if (datafellows & SSH_OLD_DHGEX) { 611590Srgrimes /* Old GEX request */ 621590Srgrimes packet_start(SSH2_MSG_KEX_DH_GEX_REQUEST_OLD); 631590Srgrimes packet_put_int(nbits); 641590Srgrimes min = DH_GRP_MIN; 651590Srgrimes max = DH_GRP_MAX; 661590Srgrimes 671590Srgrimes debug("SSH2_MSG_KEX_DH_GEX_REQUEST_OLD(%u) sent", nbits); 688382Srgrimes } else { 691590Srgrimes /* New GEX request */ 708382Srgrimes min = DH_GRP_MIN; 711590Srgrimes max = DH_GRP_MAX; 721590Srgrimes packet_start(SSH2_MSG_KEX_DH_GEX_REQUEST); 731590Srgrimes packet_put_int(min); 741590Srgrimes packet_put_int(nbits); 7518485Sbde packet_put_int(max); 7627751Scharnier 771590Srgrimes debug("SSH2_MSG_KEX_DH_GEX_REQUEST(%u<%u<%u) sent", 7837534Sghelmer min, nbits, max); 7912809Sache } 801590Srgrimes#ifdef DEBUG_KEXDH 811590Srgrimes fprintf(stderr, "\nmin = %d, nbits = %d, max = %d\n", 8227751Scharnier min, nbits, max); 836591Swollman#endif 841590Srgrimes packet_send(); 851590Srgrimes 861590Srgrimes debug("expecting SSH2_MSG_KEX_DH_GEX_GROUP"); 871590Srgrimes packet_read_expect(SSH2_MSG_KEX_DH_GEX_GROUP); 881590Srgrimes 891590Srgrimes if ((p = BN_new()) == NULL) 901590Srgrimes fatal("BN_new"); 911590Srgrimes packet_get_bignum2(p); 9212390Sache if ((g = BN_new()) == NULL) 931590Srgrimes fatal("BN_new"); 941590Srgrimes packet_get_bignum2(g); 951590Srgrimes packet_check_eom(); 961590Srgrimes 971590Srgrimes if (BN_num_bits(p) < min || BN_num_bits(p) > max) 981590Srgrimes fatal("DH_GEX group out of range: %d !< %d !< %d", 991590Srgrimes min, BN_num_bits(p), max); 1001590Srgrimes 1011590Srgrimes dh = dh_new_group(g, p); 1021590Srgrimes dh_gen_key(dh, kex->we_need * 8); 1031590Srgrimes 1041590Srgrimes#ifdef DEBUG_KEXDH 1051590Srgrimes DHparams_print_fp(stderr, dh); 1061590Srgrimes fprintf(stderr, "pub= "); 1071590Srgrimes BN_print_fp(stderr, dh->pub_key); 108241737Sed fprintf(stderr, "\n"); 109241737Sed#endif 110241737Sed 111241737Sed debug("SSH2_MSG_KEX_DH_GEX_INIT sent"); 112241737Sed /* generate and send 'e', client DH public key */ 113241737Sed packet_start(SSH2_MSG_KEX_DH_GEX_INIT); 114241737Sed packet_put_bignum2(dh->pub_key); 115241737Sed packet_send(); 116241737Sed 117241737Sed debug("expecting SSH2_MSG_KEX_DH_GEX_REPLY"); 118241737Sed packet_read_expect(SSH2_MSG_KEX_DH_GEX_REPLY); 119241737Sed 120241737Sed /* key, cert */ 121241737Sed server_host_key_blob = packet_get_string(&sbloblen); 122241737Sed server_host_key = key_from_blob(server_host_key_blob, sbloblen); 123241737Sed if (server_host_key == NULL) 124241737Sed fatal("cannot decode server_host_key_blob"); 125241737Sed if (server_host_key->type != kex->hostkey_type) 126241737Sed fatal("type mismatch for decoded server_host_key_blob"); 127241737Sed if (kex->verify_host_key == NULL) 128241737Sed fatal("cannot verify server_host_key"); 129241737Sed if (kex->verify_host_key(server_host_key) == -1) 130241737Sed fatal("server_host_key verification failed"); 131241737Sed 132241737Sed /* DH parameter f, server public DH key */ 133241737Sed if ((dh_server_pub = BN_new()) == NULL) 134241737Sed fatal("dh_server_pub == NULL"); 135241737Sed packet_get_bignum2(dh_server_pub); 136241737Sed 137241737Sed#ifdef DEBUG_KEXDH 1381590Srgrimes fprintf(stderr, "dh_server_pub= "); 1391590Srgrimes BN_print_fp(stderr, dh_server_pub); 140241737Sed fprintf(stderr, "\n"); 141241737Sed debug("bits %d", BN_num_bits(dh_server_pub)); 142241737Sed#endif 143241737Sed 144241737Sed /* signed H */ 145241737Sed signature = packet_get_string(&slen); 146241737Sed packet_check_eom(); 147241737Sed 148241737Sed if (!dh_pub_is_valid(dh, dh_server_pub)) 1491590Srgrimes packet_disconnect("bad server public DH value"); 150140389Sdelphij 151140389Sdelphij klen = DH_size(dh); 152140389Sdelphij kbuf = xmalloc(klen); 153140389Sdelphij kout = DH_compute_key(kbuf, dh_server_pub, dh); 154140389Sdelphij#ifdef DEBUG_KEXDH 155140389Sdelphij dump_digest("shared secret", kbuf, kout); 156140389Sdelphij#endif 157140389Sdelphij if ((shared_secret = BN_new()) == NULL) 158241737Sed fatal("kexgex_client: BN_new failed"); 15927751Scharnier BN_bin2bn(kbuf, kout, shared_secret); 16027751Scharnier memset(kbuf, 0, klen); 161102944Sdwmalone xfree(kbuf); 1621590Srgrimes 1631590Srgrimes if (datafellows & SSH_OLD_DHGEX) 1641590Srgrimes min = max = -1; 1651590Srgrimes 16612646Sdg /* calc and verify H */ 1671590Srgrimes kexgex_hash( 16837476Sjkh kex->evp_md, 1691590Srgrimes kex->client_version_string, 170173169Skevlo kex->server_version_string, 1711590Srgrimes buffer_ptr(&kex->my), buffer_len(&kex->my), 1721590Srgrimes buffer_ptr(&kex->peer), buffer_len(&kex->peer), 1731590Srgrimes server_host_key_blob, sbloblen, 1741590Srgrimes min, nbits, max, 17512809Sache dh->p, dh->g, 1761590Srgrimes dh->pub_key, 1771590Srgrimes dh_server_pub, 178241848Seadler shared_secret, 179241848Seadler &hash, &hashlen 1801590Srgrimes ); 1811590Srgrimes 1821590Srgrimes /* have keys, free DH */ 1831590Srgrimes DH_free(dh); 1841590Srgrimes xfree(server_host_key_blob); 1851590Srgrimes BN_clear_free(dh_server_pub); 1861590Srgrimes 1871590Srgrimes if (key_verify(server_host_key, signature, slen, hash, hashlen) != 1) 1881590Srgrimes fatal("key_verify failed for server_host_key"); 1891590Srgrimes key_free(server_host_key); 1901590Srgrimes xfree(signature); 1911590Srgrimes 1921590Srgrimes /* save session id */ 1931590Srgrimes if (kex->session_id == NULL) { 1941590Srgrimes kex->session_id_len = hashlen; 1951590Srgrimes kex->session_id = xmalloc(kex->session_id_len); 1961590Srgrimes memcpy(kex->session_id, hash, kex->session_id_len); 1971590Srgrimes } 1981590Srgrimes kex_derive_keys(kex, hash, hashlen, shared_secret); 1991590Srgrimes BN_clear_free(shared_secret); 20094504Scharnier 20194504Scharnier kex_finish(kex); 20294504Scharnier} 2031590Srgrimes