Record session ID, host key and sig at intital KEX
authordjm <djm@openbsd.org>
Sun, 19 Dec 2021 22:08:06 +0000 (22:08 +0000)
committerdjm <djm@openbsd.org>
Sun, 19 Dec 2021 22:08:06 +0000 (22:08 +0000)
These will be used later for agent session ID / hostkey binding

ok markus@

usr.bin/ssh/kex.c
usr.bin/ssh/kex.h
usr.bin/ssh/kexgen.c
usr.bin/ssh/kexgexc.c
usr.bin/ssh/kexgexs.c

index d663466..3f9c185 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: kex.c,v 1.168 2021/04/03 06:18:40 djm Exp $ */
+/* $OpenBSD: kex.c,v 1.169 2021/12/19 22:08:06 djm Exp $ */
 /*
  * Copyright (c) 2000, 2001 Markus Friedl.  All rights reserved.
  *
@@ -682,6 +682,8 @@ kex_free(struct kex *kex)
        sshbuf_free(kex->server_version);
        sshbuf_free(kex->client_pub);
        sshbuf_free(kex->session_id);
+       sshbuf_free(kex->initial_sig);
+       sshkey_free(kex->initial_hostkey);
        free(kex->failed_choice);
        free(kex->hostkey_alg);
        free(kex->name);
index 212fd35..b7967da 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: kex.h,v 1.114 2021/01/31 22:55:29 djm Exp $ */
+/* $OpenBSD: kex.h,v 1.115 2021/12/19 22:08:06 djm Exp $ */
 
 /*
  * Copyright (c) 2000, 2001 Markus Friedl.  All rights reserved.
@@ -123,6 +123,7 @@ struct newkeys {
 };
 
 struct ssh;
+struct sshbuf;
 
 struct kex {
        struct newkeys  *newkeys[MODE_MAX];
@@ -141,6 +142,8 @@ struct kex {
        struct sshbuf *client_version;
        struct sshbuf *server_version;
        struct sshbuf *session_id;
+       struct sshbuf *initial_sig;
+       struct sshkey *initial_hostkey;
        sig_atomic_t done;
        u_int   flags;
        int     hash_alg;
index 12d8bab..e7534f5 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: kexgen.c,v 1.7 2021/04/03 06:18:40 djm Exp $ */
+/* $OpenBSD: kexgen.c,v 1.8 2021/12/19 22:08:06 djm Exp $ */
 /*
  * Copyright (c) 2019 Markus Friedl.  All rights reserved.
  *
@@ -215,8 +215,26 @@ input_kex_gen_reply(int type, u_int32_t seq, struct ssh *ssh)
            kex->hostkey_alg, ssh->compat, NULL)) != 0)
                goto out;
 
-       if ((r = kex_derive_keys(ssh, hash, hashlen, shared_secret)) == 0)
-               r = kex_send_newkeys(ssh);
+       if ((r = kex_derive_keys(ssh, hash, hashlen, shared_secret)) != 0 ||
+           (r = kex_send_newkeys(ssh)) != 0)
+               goto out;
+
+       /* save initial signature and hostkey */
+       if ((kex->flags & KEX_INITIAL) != 0) {
+               if (kex->initial_hostkey != NULL || kex->initial_sig != NULL) {
+                       r = SSH_ERR_INTERNAL_ERROR;
+                       goto out;
+               }
+               if ((kex->initial_sig = sshbuf_new()) == NULL) {
+                       r = SSH_ERR_ALLOC_FAIL;
+                       goto out;
+               }
+               if ((r = sshbuf_put(kex->initial_sig, signature, slen)) != 0)
+                       goto out;
+               kex->initial_hostkey = server_host_key;
+               server_host_key = NULL;
+       }
+       /* success */
 out:
        explicit_bzero(hash, sizeof(hash));
        explicit_bzero(kex->c25519_client_key, sizeof(kex->c25519_client_key));
@@ -330,8 +348,15 @@ input_kex_gen_init(int type, u_int32_t seq, struct ssh *ssh)
            (r = sshpkt_send(ssh)) != 0)
                goto out;
 
-       if ((r = kex_derive_keys(ssh, hash, hashlen, shared_secret)) == 0)
-               r = kex_send_newkeys(ssh);
+       if ((r = kex_derive_keys(ssh, hash, hashlen, shared_secret)) != 0 ||
+           (r = kex_send_newkeys(ssh)) != 0)
+               goto out;
+       /* retain copy of hostkey used at initial KEX */
+       if (kex->initial_hostkey == NULL &&
+           (r = sshkey_from_private(server_host_public,
+           &kex->initial_hostkey)) != 0)
+               goto out;
+       /* success */
 out:
        explicit_bzero(hash, sizeof(hash));
        sshbuf_free(server_host_key_blob);
index 75d843c..6a06d98 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: kexgexc.c,v 1.37 2021/01/31 22:55:29 djm Exp $ */
+/* $OpenBSD: kexgexc.c,v 1.38 2021/12/19 22:08:06 djm Exp $ */
 /*
  * Copyright (c) 2000 Niels Provos.  All rights reserved.
  * Copyright (c) 2001 Markus Friedl.  All rights reserved.
@@ -199,8 +199,26 @@ input_kex_dh_gex_reply(int type, u_int32_t seq, struct ssh *ssh)
            hashlen, kex->hostkey_alg, ssh->compat, NULL)) != 0)
                goto out;
 
-       if ((r = kex_derive_keys(ssh, hash, hashlen, shared_secret)) == 0)
-               r = kex_send_newkeys(ssh);
+       if ((r = kex_derive_keys(ssh, hash, hashlen, shared_secret)) != 0 ||
+           (r = kex_send_newkeys(ssh)) != 0)
+               goto out;
+
+       /* save initial signature and hostkey */
+       if ((kex->flags & KEX_INITIAL) != 0) {
+               if (kex->initial_hostkey != NULL || kex->initial_sig != NULL) {
+                       r = SSH_ERR_INTERNAL_ERROR;
+                       goto out;
+               }
+               if ((kex->initial_sig = sshbuf_new()) == NULL) {
+                       r = SSH_ERR_ALLOC_FAIL;
+                       goto out;
+               }
+               if ((r = sshbuf_put(kex->initial_sig, signature, slen)) != 0)
+                       goto out;
+               kex->initial_hostkey = server_host_key;
+               server_host_key = NULL;
+       }
+       /* success */
  out:
        explicit_bzero(hash, sizeof(hash));
        DH_free(kex->dh);
index 43c2410..aa86ea6 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: kexgexs.c,v 1.43 2021/01/31 22:55:29 djm Exp $ */
+/* $OpenBSD: kexgexs.c,v 1.44 2021/12/19 22:08:06 djm Exp $ */
 /*
  * Copyright (c) 2000 Niels Provos.  All rights reserved.
  * Copyright (c) 2001 Markus Friedl.  All rights reserved.
@@ -187,8 +187,16 @@ input_kex_dh_gex_init(int type, u_int32_t seq, struct ssh *ssh)
            (r = sshpkt_send(ssh)) != 0)
                goto out;
 
-       if ((r = kex_derive_keys(ssh, hash, hashlen, shared_secret)) == 0)
-               r = kex_send_newkeys(ssh);
+       if ((r = kex_derive_keys(ssh, hash, hashlen, shared_secret)) != 0 ||
+           (r = kex_send_newkeys(ssh)) != 0)
+               goto out;
+
+       /* retain copy of hostkey used at initial KEX */
+       if (kex->initial_hostkey == NULL &&
+           (r = sshkey_from_private(server_host_public,
+           &kex->initial_hostkey)) != 0)
+               goto out;
+       /* success */
  out:
        explicit_bzero(hash, sizeof(hash));
        DH_free(kex->dh);