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