1 /*
   2  * Copyright (c) 2000 Niels Provos.  All rights reserved.
   3  * Copyright (c) 2001 Markus Friedl.  All rights reserved.
   4  *
   5  * Redistribution and use in source and binary forms, with or without
   6  * modification, are permitted provided that the following conditions
   7  * are met:
   8  * 1. Redistributions of source code must retain the above copyright
   9  *    notice, this list of conditions and the following disclaimer.
  10  * 2. Redistributions in binary form must reproduce the above copyright
  11  *    notice, this list of conditions and the following disclaimer in the
  12  *    documentation and/or other materials provided with the distribution.
  13  *
  14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  15  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  16  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  17  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  18  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  19  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  20  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  21  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  23  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  24  */
  25 
  26 #include "includes.h"
  27 RCSID("$OpenBSD: kexgex.c,v 1.22 2002/03/24 17:27:03 stevesk Exp $");
  28 
  29 #pragma ident   "%Z%%M% %I%     %E% SMI"
  30 
  31 #include <openssl/opensslconf.h>
  32 #include <openssl/bn.h>
  33 
  34 #include "xmalloc.h"
  35 #include "buffer.h"
  36 #include "bufaux.h"
  37 #include "key.h"
  38 #include "kex.h"
  39 #include "log.h"
  40 #include "packet.h"
  41 #include "dh.h"
  42 #include "ssh2.h"
  43 #include "compat.h"
  44 
  45 void
  46 kexgex_client(Kex *kex)
  47 {
  48         BIGNUM *dh_server_pub = NULL, *shared_secret = NULL;
  49         BIGNUM *p = NULL, *g = NULL;
  50         Key *server_host_key;
  51         u_char *kbuf, *hash, *signature = NULL, *server_host_key_blob = NULL;
  52         u_int klen, kout, slen, sbloblen;
  53         int min, max, nbits;
  54         DH *dh;
  55 
  56         nbits = dh_estimate(kex->we_need * 8);
  57 
  58         if (datafellows & SSH_OLD_DHGEX) {
  59                 debug("SSH2_MSG_KEX_DH_GEX_REQUEST_OLD sent");
  60 
  61                 /* Old GEX request */
  62                 packet_start(SSH2_MSG_KEX_DH_GEX_REQUEST_OLD);
  63                 packet_put_int(nbits);
  64                 min = DH_GRP_MIN;
  65                 max = DH_GRP_MAX;
  66         } else {
  67                 debug("SSH2_MSG_KEX_DH_GEX_REQUEST sent");
  68 
  69                 /* New GEX request */
  70                 min = DH_GRP_MIN;
  71                 max = DH_GRP_MAX;
  72                 packet_start(SSH2_MSG_KEX_DH_GEX_REQUEST);
  73                 packet_put_int(min);
  74                 packet_put_int(nbits);
  75                 packet_put_int(max);
  76         }
  77 #ifdef DEBUG_KEXDH
  78         fprintf(stderr, "\nmin = %d, nbits = %d, max = %d\n",
  79             min, nbits, max);
  80 #endif
  81         packet_send();
  82 
  83         debug("expecting SSH2_MSG_KEX_DH_GEX_GROUP");
  84         packet_read_expect(SSH2_MSG_KEX_DH_GEX_GROUP);
  85 
  86         if ((p = BN_new()) == NULL)
  87                 fatal("BN_new");
  88         packet_get_bignum2(p);
  89         if ((g = BN_new()) == NULL)
  90                 fatal("BN_new");
  91         packet_get_bignum2(g);
  92         packet_check_eom();
  93 
  94         if (BN_num_bits(p) < min || BN_num_bits(p) > max)
  95                 fatal("DH_GEX group out of range: %d !< %d !< %d",
  96                     min, BN_num_bits(p), max);
  97 
  98         dh = dh_new_group(g, p);
  99         dh_gen_key(dh, kex->we_need * 8);
 100 
 101 #ifdef DEBUG_KEXDH
 102         DHparams_print_fp(stderr, dh);
 103         fprintf(stderr, "pub= ");
 104         BN_print_fp(stderr, dh->pub_key);
 105         fprintf(stderr, "\n");
 106 #endif
 107 
 108         debug("SSH2_MSG_KEX_DH_GEX_INIT sent");
 109         /* generate and send 'e', client DH public key */
 110         packet_start(SSH2_MSG_KEX_DH_GEX_INIT);
 111         packet_put_bignum2(dh->pub_key);
 112         packet_send();
 113 
 114         debug("expecting SSH2_MSG_KEX_DH_GEX_REPLY");
 115         packet_read_expect(SSH2_MSG_KEX_DH_GEX_REPLY);
 116 
 117         /* key, cert */
 118         server_host_key_blob = packet_get_string(&sbloblen);
 119         server_host_key = key_from_blob(server_host_key_blob, sbloblen);
 120         if (server_host_key == NULL)
 121                 fatal("cannot decode server_host_key_blob");
 122         if (server_host_key->type != kex->hostkey_type)
 123                 fatal("type mismatch for decoded server_host_key_blob");
 124         if (kex->verify_host_key == NULL)
 125                 fatal("cannot verify server_host_key");
 126         if (kex->verify_host_key(server_host_key) == -1)
 127                 fatal("server_host_key verification failed");
 128 
 129         /* DH paramter f, server public DH key */
 130         if ((dh_server_pub = BN_new()) == NULL)
 131                 fatal("dh_server_pub == NULL");
 132         packet_get_bignum2(dh_server_pub);
 133 
 134 #ifdef DEBUG_KEXDH
 135         fprintf(stderr, "dh_server_pub= ");
 136         BN_print_fp(stderr, dh_server_pub);
 137         fprintf(stderr, "\n");
 138         debug("bits %d", BN_num_bits(dh_server_pub));
 139 #endif
 140 
 141         /* signed H */
 142         signature = packet_get_string(&slen);
 143         packet_check_eom();
 144 
 145         if (!dh_pub_is_valid(dh, dh_server_pub))
 146                 packet_disconnect("bad server public DH value");
 147 
 148         klen = DH_size(dh);
 149         kbuf = xmalloc(klen);
 150         kout = DH_compute_key(kbuf, dh_server_pub, dh);
 151 #ifdef DEBUG_KEXDH
 152         dump_digest("shared secret", kbuf, kout);
 153 #endif
 154         if ((shared_secret = BN_new()) == NULL)
 155                 fatal("kexgex_client: BN_new failed");
 156         BN_bin2bn(kbuf, kout, shared_secret);
 157         memset(kbuf, 0, klen);
 158         xfree(kbuf);
 159 
 160         if (datafellows & SSH_OLD_DHGEX)
 161                 min = max = -1;
 162 
 163         /* calc and verify H */
 164         hash = kexgex_hash(
 165             kex->client_version_string,
 166             kex->server_version_string,
 167             buffer_ptr(&kex->my), buffer_len(&kex->my),
 168             buffer_ptr(&kex->peer), buffer_len(&kex->peer),
 169             server_host_key_blob, sbloblen,
 170             min, nbits, max,
 171             dh->p, dh->g,
 172             dh->pub_key,
 173             dh_server_pub,
 174             shared_secret
 175         );
 176         /* have keys, free DH */
 177         DH_free(dh);
 178         xfree(server_host_key_blob);
 179         BN_clear_free(dh_server_pub);
 180 
 181         if (key_verify(server_host_key, signature, slen, hash, 20) != 1)
 182                 fatal("key_verify failed for server_host_key");
 183         key_free(server_host_key);
 184         xfree(signature);
 185 
 186         /* save session id */
 187         if (kex->session_id == NULL) {
 188                 kex->session_id_len = 20;
 189                 kex->session_id = xmalloc(kex->session_id_len);
 190                 memcpy(kex->session_id, hash, kex->session_id_len);
 191         }
 192         kex_derive_keys(kex, hash, shared_secret);
 193         BN_clear_free(shared_secret);
 194 
 195         kex_finish(kex);
 196 }