]> andersk Git - openssh.git/blobdiff - kexgex.c
- djm@cvs.openbsd.org 2010/01/30 02:54:53
[openssh.git] / kexgex.c
index 6e8be78b5527a894e89baca4345be4407768cb8b..b60ab5c53cc9f2227c7e7a795adf4ee29964177c 100644 (file)
--- a/kexgex.c
+++ b/kexgex.c
@@ -1,3 +1,4 @@
+/* $OpenBSD: kexgex.c,v 1.27 2006/08/03 03:34:42 deraadt Exp $ */
 /*
  * Copyright (c) 2000 Niels Provos.  All rights reserved.
  * Copyright (c) 2001 Markus Friedl.  All rights reserved.
  */
 
 #include "includes.h"
-RCSID("$OpenBSD: kexgex.c,v 1.2 2001/04/03 23:32:12 markus Exp $");
 
-#include <openssl/bn.h>
+#include <sys/types.h>
+
+#include <openssl/evp.h>
+#include <signal.h>
 
-#include "xmalloc.h"
 #include "buffer.h"
-#include "bufaux.h"
 #include "key.h"
+#include "cipher.h"
 #include "kex.h"
-#include "log.h"
-#include "packet.h"
-#include "dh.h"
 #include "ssh2.h"
-#include "compat.h"
 
-u_char *
+void
 kexgex_hash(
+    const EVP_MD *evp_md,
     char *client_version_string,
     char *server_version_string,
     char *ckexinit, int ckexinitlen,
     char *skexinit, int skexinitlen,
-    char *serverhostkeyblob, int sbloblen,
+    u_char *serverhostkeyblob, int sbloblen,
     int min, int wantbits, int max, BIGNUM *prime, BIGNUM *gen,
     BIGNUM *client_dh_pub,
     BIGNUM *server_dh_pub,
-    BIGNUM *shared_secret)
+    BIGNUM *shared_secret,
+    u_char **hash, u_int *hashlen)
 {
        Buffer b;
        static u_char digest[EVP_MAX_MD_SIZE];
-       EVP_MD *evp_md = EVP_sha1();
        EVP_MD_CTX md;
 
        buffer_init(&b);
-       buffer_put_string(&b, client_version_string, strlen(client_version_string));
-       buffer_put_string(&b, server_version_string, strlen(server_version_string));
+       buffer_put_cstring(&b, client_version_string);
+       buffer_put_cstring(&b, server_version_string);
 
        /* kexinit messages: fake header: len+SSH2_MSG_KEXINIT */
        buffer_put_int(&b, ckexinitlen+1);
@@ -69,7 +68,7 @@ kexgex_hash(
        buffer_append(&b, skexinit, skexinitlen);
 
        buffer_put_string(&b, serverhostkeyblob, sbloblen);
-       if (min == -1 || max == -1) 
+       if (min == -1 || max == -1)
                buffer_put_int(&b, wantbits);
        else {
                buffer_put_int(&b, min);
@@ -85,327 +84,15 @@ kexgex_hash(
 #ifdef DEBUG_KEXDH
        buffer_dump(&b);
 #endif
+
        EVP_DigestInit(&md, evp_md);
        EVP_DigestUpdate(&md, buffer_ptr(&b), buffer_len(&b));
        EVP_DigestFinal(&md, digest, NULL);
 
        buffer_free(&b);
-
-#ifdef DEBUG_KEXDH
-       dump_digest("hash", digest, evp_md->md_size);
-#endif
-       return digest;
-}
-
-/* client */
-
-void
-kexgex_client(Kex *kex)
-{
-       BIGNUM *dh_server_pub = NULL, *shared_secret = NULL;
-       BIGNUM *p = NULL, *g = NULL;
-       Key *server_host_key;
-       u_char *kbuf, *hash, *signature = NULL, *server_host_key_blob = NULL;
-       u_int klen, kout, slen, sbloblen;
-       int dlen, plen, min, max, nbits;
-       DH *dh;
-
-       nbits = dh_estimate(kex->we_need * 8);
-
-       if (datafellows & SSH_OLD_DHGEX) {
-               debug("SSH2_MSG_KEX_DH_GEX_REQUEST_OLD sent");
-
-               /* Old GEX request */
-               packet_start(SSH2_MSG_KEX_DH_GEX_REQUEST_OLD);
-               packet_put_int(nbits);
-               min = DH_GRP_MIN;
-               max = DH_GRP_MAX;
-       } else {
-               debug("SSH2_MSG_KEX_DH_GEX_REQUEST sent");
-
-               /* New GEX request */
-               min = DH_GRP_MIN;
-               max = DH_GRP_MAX;
-               packet_start(SSH2_MSG_KEX_DH_GEX_REQUEST);
-               packet_put_int(min);
-               packet_put_int(nbits);
-               packet_put_int(max);
-       }
-#ifdef DEBUG_KEXDH
-       fprintf(stderr, "\nmin = %d, nbits = %d, max = %d\n",
-           min, nbits, max);
-#endif
-       packet_send();
-
-       debug("expecting SSH2_MSG_KEX_DH_GEX_GROUP");
-       packet_read_expect(&plen, SSH2_MSG_KEX_DH_GEX_GROUP);
-
-       if ((p = BN_new()) == NULL)
-               fatal("BN_new");
-       packet_get_bignum2(p, &dlen);
-       if ((g = BN_new()) == NULL)
-               fatal("BN_new");
-       packet_get_bignum2(g, &dlen);
-       packet_done();
-
-       if (BN_num_bits(p) < min || BN_num_bits(p) > max)
-               fatal("DH_GEX group out of range: %d !< %d !< %d",
-                   min, BN_num_bits(p), max);
-
-       dh = dh_new_group(g, p);
-       dh_gen_key(dh, kex->we_need * 8);
-
+       *hash = digest;
+       *hashlen = EVP_MD_size(evp_md);
 #ifdef DEBUG_KEXDH
-       DHparams_print_fp(stderr, dh);
-       fprintf(stderr, "pub= ");
-       BN_print_fp(stderr, dh->pub_key);
-       fprintf(stderr, "\n");
+       dump_digest("hash", digest, *hashlen);
 #endif
-
-       debug("SSH2_MSG_KEX_DH_GEX_INIT sent");
-       /* generate and send 'e', client DH public key */
-       packet_start(SSH2_MSG_KEX_DH_GEX_INIT);
-       packet_put_bignum2(dh->pub_key);
-       packet_send();
-
-       debug("expecting SSH2_MSG_KEX_DH_GEX_REPLY");
-       packet_read_expect(&plen, SSH2_MSG_KEX_DH_GEX_REPLY);
-
-       /* key, cert */
-       server_host_key_blob = packet_get_string(&sbloblen);
-       server_host_key = key_from_blob(server_host_key_blob, sbloblen);
-       if (server_host_key == NULL)
-               fatal("cannot decode server_host_key_blob");
-
-       if (kex->check_host_key == NULL)
-               fatal("cannot check server_host_key");
-       kex->check_host_key(server_host_key);
-
-       /* DH paramter f, server public DH key */
-       dh_server_pub = BN_new();
-       if (dh_server_pub == NULL)
-               fatal("dh_server_pub == NULL");
-       packet_get_bignum2(dh_server_pub, &dlen);
-
-#ifdef DEBUG_KEXDH
-       fprintf(stderr, "dh_server_pub= ");
-       BN_print_fp(stderr, dh_server_pub);
-       fprintf(stderr, "\n");
-       debug("bits %d", BN_num_bits(dh_server_pub));
-#endif
-
-       /* signed H */
-       signature = packet_get_string(&slen);
-       packet_done();
-
-       if (!dh_pub_is_valid(dh, dh_server_pub))
-               packet_disconnect("bad server public DH value");
-
-       klen = DH_size(dh);
-       kbuf = xmalloc(klen);
-       kout = DH_compute_key(kbuf, dh_server_pub, dh);
-#ifdef DEBUG_KEXDH
-        dump_digest("shared secret", kbuf, kout);
-#endif
-       shared_secret = BN_new();
-       BN_bin2bn(kbuf, kout, shared_secret);
-       memset(kbuf, 0, klen);
-       xfree(kbuf);
-
-       if (datafellows & SSH_OLD_DHGEX)
-               min = max = -1;
-
-       /* calc and verify H */
-       hash = kexgex_hash(
-           kex->client_version_string,
-           kex->server_version_string,
-           buffer_ptr(&kex->my), buffer_len(&kex->my),
-           buffer_ptr(&kex->peer), buffer_len(&kex->peer),
-           server_host_key_blob, sbloblen,
-           min, nbits, max,
-           dh->p, dh->g,
-           dh->pub_key,
-           dh_server_pub,
-           shared_secret
-       );
-       xfree(server_host_key_blob);
-       BN_free(dh_server_pub);
-
-       if (key_verify(server_host_key, (u_char *)signature, slen, hash, 20) != 1)
-               fatal("key_verify failed for server_host_key");
-       key_free(server_host_key);
-       xfree(signature);
-
-       /* save session id */
-       if (kex->session_id == NULL) {
-               kex->session_id_len = 20;
-               kex->session_id = xmalloc(kex->session_id_len);
-               memcpy(kex->session_id, hash, kex->session_id_len);
-       }
-
-       kex_derive_keys(kex, hash, shared_secret);
-       BN_clear_free(shared_secret);
-
-       kex_send_newkeys();
-
-       /* have keys, free DH */
-       DH_free(dh);
-}
-
-/* server */
-
-void
-kexgex_server(Kex *kex)
-{
-       BIGNUM *shared_secret = NULL, *dh_client_pub = NULL;
-       Key *server_host_key;
-       DH *dh = dh;
-       u_char *kbuf, *hash, *signature = NULL, *server_host_key_blob = NULL;
-       u_int sbloblen, klen, kout;
-       int min = -1, max = -1, nbits = -1, type, plen, dlen, slen;
-
-       if (kex->load_host_key == NULL)
-               fatal("Cannot load hostkey");
-       server_host_key = kex->load_host_key(kex->hostkey_type);
-       if (server_host_key == NULL)
-               fatal("Unsupported hostkey type %d", kex->hostkey_type);
-
-       type = packet_read(&plen);
-       switch(type){
-       case SSH2_MSG_KEX_DH_GEX_REQUEST:
-               debug("SSH2_MSG_KEX_DH_GEX_REQUEST received");
-               min = packet_get_int();
-               nbits = packet_get_int();
-               max = packet_get_int();
-               min = MAX(DH_GRP_MIN, min);
-               max = MIN(DH_GRP_MAX, max);
-               break;
-       case SSH2_MSG_KEX_DH_GEX_REQUEST_OLD:
-               debug("SSH2_MSG_KEX_DH_GEX_REQUEST_OLD received");
-               nbits = packet_get_int();
-               min = DH_GRP_MIN;
-               max = DH_GRP_MAX;
-               /* unused for old GEX */
-               break;
-       default:
-               fatal("protocol error during kex, no DH_GEX_REQUEST");
-       }
-       packet_done();
-
-       if (max < min || nbits < min || max < nbits)
-               fatal("DH_GEX_REQUEST, bad parameters: %d !< %d !< %d",
-                   min, nbits, max);
-
-       dh = choose_dh(min, nbits, max);
-       if (dh == NULL)
-               packet_disconnect("Protocol error: no matching DH grp found");
-
-       debug("SSH2_MSG_KEX_DH_GEX_GROUP sent");
-       packet_start(SSH2_MSG_KEX_DH_GEX_GROUP);
-       packet_put_bignum2(dh->p);
-       packet_put_bignum2(dh->g);
-       packet_send();
-
-       /* flush */
-       packet_write_wait();
-
-       /* Compute our exchange value in parallel with the client */
-       dh_gen_key(dh, kex->we_need * 8);
-
-       debug("expecting SSH2_MSG_KEX_DH_GEX_INIT");
-       packet_read_expect(&plen, SSH2_MSG_KEX_DH_GEX_INIT);
-
-       /* key, cert */
-       dh_client_pub = BN_new();
-       if (dh_client_pub == NULL)
-               fatal("dh_client_pub == NULL");
-       packet_get_bignum2(dh_client_pub, &dlen);
-
-#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));
-#endif
-
-#ifdef DEBUG_KEXDH
-       DHparams_print_fp(stderr, dh);
-       fprintf(stderr, "pub= ");
-       BN_print_fp(stderr, dh->pub_key);
-       fprintf(stderr, "\n");
-#endif
-       if (!dh_pub_is_valid(dh, dh_client_pub))
-               packet_disconnect("bad client public DH value");
-
-       klen = DH_size(dh);
-       kbuf = xmalloc(klen);
-       kout = DH_compute_key(kbuf, dh_client_pub, dh);
-#ifdef DEBUG_KEXDH
-        dump_digest("shared secret", kbuf, kout);
-#endif
-       shared_secret = BN_new();
-       BN_bin2bn(kbuf, kout, shared_secret);
-       memset(kbuf, 0, klen);
-       xfree(kbuf);
-
-       key_to_blob(server_host_key, &server_host_key_blob, &sbloblen);
-
-       if (type == SSH2_MSG_KEX_DH_GEX_REQUEST_OLD)
-               min = max = -1;
-
-       /* calc H */                    /* XXX depends on 'kex' */
-       hash = kexgex_hash(
-           kex->client_version_string,
-           kex->server_version_string,
-           buffer_ptr(&kex->peer), buffer_len(&kex->peer),
-           buffer_ptr(&kex->my), buffer_len(&kex->my),
-           (char *)server_host_key_blob, sbloblen,
-           min, nbits, max,
-           dh->p, dh->g,
-           dh_client_pub,
-           dh->pub_key,
-           shared_secret
-       );
-       BN_free(dh_client_pub);
-
-       /* save session id := H */
-       /* XXX hashlen depends on KEX */
-       if (kex->session_id == NULL) {
-               kex->session_id_len = 20;
-               kex->session_id = xmalloc(kex->session_id_len);
-               memcpy(kex->session_id, hash, kex->session_id_len);
-       }
-
-       /* sign H */
-       /* XXX hashlen depends on KEX */
-       key_sign(server_host_key, &signature, &slen, hash, 20);
-
-       /* destroy_sensitive_data(); */
-
-       /* send server hostkey, DH pubkey 'f' and singed H */
-       debug("SSH2_MSG_KEX_DH_GEX_REPLY sent");
-       packet_start(SSH2_MSG_KEX_DH_GEX_REPLY);
-       packet_put_string((char *)server_host_key_blob, sbloblen);
-       packet_put_bignum2(dh->pub_key);        /* f */
-       packet_put_string((char *)signature, slen);
-       packet_send();
-       xfree(signature);
-       xfree(server_host_key_blob);
-
-       kex_derive_keys(kex, hash, shared_secret);
-       BN_clear_free(shared_secret);
-
-       kex_send_newkeys();
-
-       /* have keys, free DH */
-       DH_free(dh);
-}
-
-void
-kexgex(Kex *kex)
-{
-       if (kex->server)
-               kexgex_server(kex);
-       else
-               kexgex_client(kex);
 }
This page took 0.04234 seconds and 4 git commands to generate.