diff options
author | Colin Watson <cjwatson@debian.org> | 2019-10-09 22:59:48 +0100 |
---|---|---|
committer | Colin Watson <cjwatson@debian.org> | 2019-10-09 23:39:39 +0100 |
commit | 767ee84d3465b6d244a9108de5c167a9ab866df9 (patch) | |
tree | 69b14ef6a62d7f133298a21d2ad6046f130b7801 /kex.c | |
parent | ddeaf9ee7d5c6612b88f1c4a83fc6fbccb93bf60 (diff) | |
parent | efef12825b9582c1710da3b7e50135870963d4f4 (diff) |
New upstream release (8.1p1)
Diffstat (limited to 'kex.c')
-rw-r--r-- | kex.c | 107 |
1 files changed, 80 insertions, 27 deletions
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: kex.c,v 1.150 2019/01/21 12:08:13 djm Exp $ */ | 1 | /* $OpenBSD: kex.c,v 1.155 2019/10/08 22:40:39 dtucker Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. | 3 | * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. |
4 | * | 4 | * |
@@ -116,7 +116,7 @@ static const struct kexalg kexalgs[] = { | |||
116 | { KEX_SNTRUP4591761X25519_SHA512, KEX_KEM_SNTRUP4591761X25519_SHA512, 0, | 116 | { KEX_SNTRUP4591761X25519_SHA512, KEX_KEM_SNTRUP4591761X25519_SHA512, 0, |
117 | SSH_DIGEST_SHA512 }, | 117 | SSH_DIGEST_SHA512 }, |
118 | #endif /* HAVE_EVP_SHA256 || !WITH_OPENSSL */ | 118 | #endif /* HAVE_EVP_SHA256 || !WITH_OPENSSL */ |
119 | { NULL, -1, -1, -1}, | 119 | { NULL, 0, -1, -1}, |
120 | }; | 120 | }; |
121 | static const struct kexalg gss_kexalgs[] = { | 121 | static const struct kexalg gss_kexalgs[] = { |
122 | #ifdef GSSAPI | 122 | #ifdef GSSAPI |
@@ -129,7 +129,7 @@ static const struct kexalg gss_kexalgs[] = { | |||
129 | NID_X9_62_prime256v1, SSH_DIGEST_SHA256 }, | 129 | NID_X9_62_prime256v1, SSH_DIGEST_SHA256 }, |
130 | { KEX_GSS_C25519_SHA256_ID, KEX_GSS_C25519_SHA256, 0, SSH_DIGEST_SHA256 }, | 130 | { KEX_GSS_C25519_SHA256_ID, KEX_GSS_C25519_SHA256, 0, SSH_DIGEST_SHA256 }, |
131 | #endif | 131 | #endif |
132 | { NULL, -1, -1, -1 }, | 132 | { NULL, 0, -1, -1 }, |
133 | }; | 133 | }; |
134 | 134 | ||
135 | static char * | 135 | static char * |
@@ -247,8 +247,9 @@ kex_names_cat(const char *a, const char *b) | |||
247 | /* | 247 | /* |
248 | * Assemble a list of algorithms from a default list and a string from a | 248 | * Assemble a list of algorithms from a default list and a string from a |
249 | * configuration file. The user-provided string may begin with '+' to | 249 | * configuration file. The user-provided string may begin with '+' to |
250 | * indicate that it should be appended to the default or '-' that the | 250 | * indicate that it should be appended to the default, '-' that the |
251 | * specified names should be removed. | 251 | * specified names should be removed, or '^' that they should be placed |
252 | * at the head. | ||
252 | */ | 253 | */ |
253 | int | 254 | int |
254 | kex_assemble_names(char **listp, const char *def, const char *all) | 255 | kex_assemble_names(char **listp, const char *def, const char *all) |
@@ -257,7 +258,10 @@ kex_assemble_names(char **listp, const char *def, const char *all) | |||
257 | char *list = NULL, *ret = NULL, *matching = NULL, *opatterns = NULL; | 258 | char *list = NULL, *ret = NULL, *matching = NULL, *opatterns = NULL; |
258 | int r = SSH_ERR_INTERNAL_ERROR; | 259 | int r = SSH_ERR_INTERNAL_ERROR; |
259 | 260 | ||
260 | if (listp == NULL || *listp == NULL || **listp == '\0') { | 261 | if (listp == NULL || def == NULL || all == NULL) |
262 | return SSH_ERR_INVALID_ARGUMENT; | ||
263 | |||
264 | if (*listp == NULL || **listp == '\0') { | ||
261 | if ((*listp = strdup(def)) == NULL) | 265 | if ((*listp = strdup(def)) == NULL) |
262 | return SSH_ERR_ALLOC_FAIL; | 266 | return SSH_ERR_ALLOC_FAIL; |
263 | return 0; | 267 | return 0; |
@@ -282,6 +286,14 @@ kex_assemble_names(char **listp, const char *def, const char *all) | |||
282 | free(list); | 286 | free(list); |
283 | /* filtering has already been done */ | 287 | /* filtering has already been done */ |
284 | return 0; | 288 | return 0; |
289 | } else if (*list == '^') { | ||
290 | /* Place names at head of default list */ | ||
291 | if ((tmp = kex_names_cat(list + 1, def)) == NULL) { | ||
292 | r = SSH_ERR_ALLOC_FAIL; | ||
293 | goto fail; | ||
294 | } | ||
295 | free(list); | ||
296 | list = tmp; | ||
285 | } else { | 297 | } else { |
286 | /* Explicit list, overrides default - just use "list" as is */ | 298 | /* Explicit list, overrides default - just use "list" as is */ |
287 | } | 299 | } |
@@ -402,18 +414,25 @@ kex_buf2prop(struct sshbuf *raw, int *first_kex_follows, char ***propp) | |||
402 | r = SSH_ERR_ALLOC_FAIL; | 414 | r = SSH_ERR_ALLOC_FAIL; |
403 | goto out; | 415 | goto out; |
404 | } | 416 | } |
405 | if ((r = sshbuf_consume(b, KEX_COOKIE_LEN)) != 0) /* skip cookie */ | 417 | if ((r = sshbuf_consume(b, KEX_COOKIE_LEN)) != 0) { /* skip cookie */ |
418 | error("%s: consume cookie: %s", __func__, ssh_err(r)); | ||
406 | goto out; | 419 | goto out; |
420 | } | ||
407 | /* extract kex init proposal strings */ | 421 | /* extract kex init proposal strings */ |
408 | for (i = 0; i < PROPOSAL_MAX; i++) { | 422 | for (i = 0; i < PROPOSAL_MAX; i++) { |
409 | if ((r = sshbuf_get_cstring(b, &(proposal[i]), NULL)) != 0) | 423 | if ((r = sshbuf_get_cstring(b, &(proposal[i]), NULL)) != 0) { |
424 | error("%s: parse proposal %u: %s", __func__, | ||
425 | i, ssh_err(r)); | ||
410 | goto out; | 426 | goto out; |
427 | } | ||
411 | debug2("%s: %s", proposal_names[i], proposal[i]); | 428 | debug2("%s: %s", proposal_names[i], proposal[i]); |
412 | } | 429 | } |
413 | /* first kex follows / reserved */ | 430 | /* first kex follows / reserved */ |
414 | if ((r = sshbuf_get_u8(b, &v)) != 0 || /* first_kex_follows */ | 431 | if ((r = sshbuf_get_u8(b, &v)) != 0 || /* first_kex_follows */ |
415 | (r = sshbuf_get_u32(b, &i)) != 0) /* reserved */ | 432 | (r = sshbuf_get_u32(b, &i)) != 0) { /* reserved */ |
433 | error("%s: parse: %s", __func__, ssh_err(r)); | ||
416 | goto out; | 434 | goto out; |
435 | } | ||
417 | if (first_kex_follows != NULL) | 436 | if (first_kex_follows != NULL) |
418 | *first_kex_follows = v; | 437 | *first_kex_follows = v; |
419 | debug2("first_kex_follows %d ", v); | 438 | debug2("first_kex_follows %d ", v); |
@@ -466,6 +485,7 @@ kex_send_ext_info(struct ssh *ssh) | |||
466 | int r; | 485 | int r; |
467 | char *algs; | 486 | char *algs; |
468 | 487 | ||
488 | debug("Sending SSH2_MSG_EXT_INFO"); | ||
469 | if ((algs = sshkey_alg_list(0, 1, 1, ',')) == NULL) | 489 | if ((algs = sshkey_alg_list(0, 1, 1, ',')) == NULL) |
470 | return SSH_ERR_ALLOC_FAIL; | 490 | return SSH_ERR_ALLOC_FAIL; |
471 | /* XXX filter algs list by allowed pubkey/hostbased types */ | 491 | /* XXX filter algs list by allowed pubkey/hostbased types */ |
@@ -473,8 +493,10 @@ kex_send_ext_info(struct ssh *ssh) | |||
473 | (r = sshpkt_put_u32(ssh, 1)) != 0 || | 493 | (r = sshpkt_put_u32(ssh, 1)) != 0 || |
474 | (r = sshpkt_put_cstring(ssh, "server-sig-algs")) != 0 || | 494 | (r = sshpkt_put_cstring(ssh, "server-sig-algs")) != 0 || |
475 | (r = sshpkt_put_cstring(ssh, algs)) != 0 || | 495 | (r = sshpkt_put_cstring(ssh, algs)) != 0 || |
476 | (r = sshpkt_send(ssh)) != 0) | 496 | (r = sshpkt_send(ssh)) != 0) { |
497 | error("%s: compose: %s", __func__, ssh_err(r)); | ||
477 | goto out; | 498 | goto out; |
499 | } | ||
478 | /* success */ | 500 | /* success */ |
479 | r = 0; | 501 | r = 0; |
480 | out: | 502 | out: |
@@ -492,11 +514,11 @@ kex_send_newkeys(struct ssh *ssh) | |||
492 | (r = sshpkt_send(ssh)) != 0) | 514 | (r = sshpkt_send(ssh)) != 0) |
493 | return r; | 515 | return r; |
494 | debug("SSH2_MSG_NEWKEYS sent"); | 516 | debug("SSH2_MSG_NEWKEYS sent"); |
495 | debug("expecting SSH2_MSG_NEWKEYS"); | ||
496 | ssh_dispatch_set(ssh, SSH2_MSG_NEWKEYS, &kex_input_newkeys); | 517 | ssh_dispatch_set(ssh, SSH2_MSG_NEWKEYS, &kex_input_newkeys); |
497 | if (ssh->kex->ext_info_c) | 518 | if (ssh->kex->ext_info_c && (ssh->kex->flags & KEX_INITIAL) != 0) |
498 | if ((r = kex_send_ext_info(ssh)) != 0) | 519 | if ((r = kex_send_ext_info(ssh)) != 0) |
499 | return r; | 520 | return r; |
521 | debug("expecting SSH2_MSG_NEWKEYS"); | ||
500 | return 0; | 522 | return 0; |
501 | } | 523 | } |
502 | 524 | ||
@@ -568,23 +590,32 @@ kex_send_kexinit(struct ssh *ssh) | |||
568 | struct kex *kex = ssh->kex; | 590 | struct kex *kex = ssh->kex; |
569 | int r; | 591 | int r; |
570 | 592 | ||
571 | if (kex == NULL) | 593 | if (kex == NULL) { |
594 | error("%s: no hex", __func__); | ||
572 | return SSH_ERR_INTERNAL_ERROR; | 595 | return SSH_ERR_INTERNAL_ERROR; |
596 | } | ||
573 | if (kex->flags & KEX_INIT_SENT) | 597 | if (kex->flags & KEX_INIT_SENT) |
574 | return 0; | 598 | return 0; |
575 | kex->done = 0; | 599 | kex->done = 0; |
576 | 600 | ||
577 | /* generate a random cookie */ | 601 | /* generate a random cookie */ |
578 | if (sshbuf_len(kex->my) < KEX_COOKIE_LEN) | 602 | if (sshbuf_len(kex->my) < KEX_COOKIE_LEN) { |
603 | error("%s: bad kex length: %zu < %d", __func__, | ||
604 | sshbuf_len(kex->my), KEX_COOKIE_LEN); | ||
579 | return SSH_ERR_INVALID_FORMAT; | 605 | return SSH_ERR_INVALID_FORMAT; |
580 | if ((cookie = sshbuf_mutable_ptr(kex->my)) == NULL) | 606 | } |
607 | if ((cookie = sshbuf_mutable_ptr(kex->my)) == NULL) { | ||
608 | error("%s: buffer error", __func__); | ||
581 | return SSH_ERR_INTERNAL_ERROR; | 609 | return SSH_ERR_INTERNAL_ERROR; |
610 | } | ||
582 | arc4random_buf(cookie, KEX_COOKIE_LEN); | 611 | arc4random_buf(cookie, KEX_COOKIE_LEN); |
583 | 612 | ||
584 | if ((r = sshpkt_start(ssh, SSH2_MSG_KEXINIT)) != 0 || | 613 | if ((r = sshpkt_start(ssh, SSH2_MSG_KEXINIT)) != 0 || |
585 | (r = sshpkt_putb(ssh, kex->my)) != 0 || | 614 | (r = sshpkt_putb(ssh, kex->my)) != 0 || |
586 | (r = sshpkt_send(ssh)) != 0) | 615 | (r = sshpkt_send(ssh)) != 0) { |
616 | error("%s: compose reply: %s", __func__, ssh_err(r)); | ||
587 | return r; | 617 | return r; |
618 | } | ||
588 | debug("SSH2_MSG_KEXINIT sent"); | 619 | debug("SSH2_MSG_KEXINIT sent"); |
589 | kex->flags |= KEX_INIT_SENT; | 620 | kex->flags |= KEX_INIT_SENT; |
590 | return 0; | 621 | return 0; |
@@ -601,21 +632,28 @@ kex_input_kexinit(int type, u_int32_t seq, struct ssh *ssh) | |||
601 | int r; | 632 | int r; |
602 | 633 | ||
603 | debug("SSH2_MSG_KEXINIT received"); | 634 | debug("SSH2_MSG_KEXINIT received"); |
604 | if (kex == NULL) | 635 | if (kex == NULL) { |
605 | return SSH_ERR_INVALID_ARGUMENT; | 636 | error("%s: no hex", __func__); |
606 | 637 | return SSH_ERR_INTERNAL_ERROR; | |
638 | } | ||
607 | ssh_dispatch_set(ssh, SSH2_MSG_KEXINIT, NULL); | 639 | ssh_dispatch_set(ssh, SSH2_MSG_KEXINIT, NULL); |
608 | ptr = sshpkt_ptr(ssh, &dlen); | 640 | ptr = sshpkt_ptr(ssh, &dlen); |
609 | if ((r = sshbuf_put(kex->peer, ptr, dlen)) != 0) | 641 | if ((r = sshbuf_put(kex->peer, ptr, dlen)) != 0) |
610 | return r; | 642 | return r; |
611 | 643 | ||
612 | /* discard packet */ | 644 | /* discard packet */ |
613 | for (i = 0; i < KEX_COOKIE_LEN; i++) | 645 | for (i = 0; i < KEX_COOKIE_LEN; i++) { |
614 | if ((r = sshpkt_get_u8(ssh, NULL)) != 0) | 646 | if ((r = sshpkt_get_u8(ssh, NULL)) != 0) { |
647 | error("%s: discard cookie: %s", __func__, ssh_err(r)); | ||
615 | return r; | 648 | return r; |
616 | for (i = 0; i < PROPOSAL_MAX; i++) | 649 | } |
617 | if ((r = sshpkt_get_string(ssh, NULL, NULL)) != 0) | 650 | } |
651 | for (i = 0; i < PROPOSAL_MAX; i++) { | ||
652 | if ((r = sshpkt_get_string(ssh, NULL, NULL)) != 0) { | ||
653 | error("%s: discard proposal: %s", __func__, ssh_err(r)); | ||
618 | return r; | 654 | return r; |
655 | } | ||
656 | } | ||
619 | /* | 657 | /* |
620 | * XXX RFC4253 sec 7: "each side MAY guess" - currently no supported | 658 | * XXX RFC4253 sec 7: "each side MAY guess" - currently no supported |
621 | * KEX method has the server move first, but a server might be using | 659 | * KEX method has the server move first, but a server might be using |
@@ -640,6 +678,7 @@ kex_input_kexinit(int type, u_int32_t seq, struct ssh *ssh) | |||
640 | if (kex->kex_type < KEX_MAX && kex->kex[kex->kex_type] != NULL) | 678 | if (kex->kex_type < KEX_MAX && kex->kex[kex->kex_type] != NULL) |
641 | return (kex->kex[kex->kex_type])(ssh); | 679 | return (kex->kex[kex->kex_type])(ssh); |
642 | 680 | ||
681 | error("%s: unknown kex type %u", __func__, kex->kex_type); | ||
643 | return SSH_ERR_INTERNAL_ERROR; | 682 | return SSH_ERR_INTERNAL_ERROR; |
644 | } | 683 | } |
645 | 684 | ||
@@ -778,6 +817,7 @@ choose_enc(struct sshenc *enc, char *client, char *server) | |||
778 | if (name == NULL) | 817 | if (name == NULL) |
779 | return SSH_ERR_NO_CIPHER_ALG_MATCH; | 818 | return SSH_ERR_NO_CIPHER_ALG_MATCH; |
780 | if ((enc->cipher = cipher_by_name(name)) == NULL) { | 819 | if ((enc->cipher = cipher_by_name(name)) == NULL) { |
820 | error("%s: unsupported cipher %s", __func__, name); | ||
781 | free(name); | 821 | free(name); |
782 | return SSH_ERR_INTERNAL_ERROR; | 822 | return SSH_ERR_INTERNAL_ERROR; |
783 | } | 823 | } |
@@ -799,6 +839,7 @@ choose_mac(struct ssh *ssh, struct sshmac *mac, char *client, char *server) | |||
799 | if (name == NULL) | 839 | if (name == NULL) |
800 | return SSH_ERR_NO_MAC_ALG_MATCH; | 840 | return SSH_ERR_NO_MAC_ALG_MATCH; |
801 | if (mac_setup(mac, name) < 0) { | 841 | if (mac_setup(mac, name) < 0) { |
842 | error("%s: unsupported MAC %s", __func__, name); | ||
802 | free(name); | 843 | free(name); |
803 | return SSH_ERR_INTERNAL_ERROR; | 844 | return SSH_ERR_INTERNAL_ERROR; |
804 | } | 845 | } |
@@ -822,6 +863,7 @@ choose_comp(struct sshcomp *comp, char *client, char *server) | |||
822 | } else if (strcmp(name, "none") == 0) { | 863 | } else if (strcmp(name, "none") == 0) { |
823 | comp->type = COMP_NONE; | 864 | comp->type = COMP_NONE; |
824 | } else { | 865 | } else { |
866 | error("%s: unsupported compression scheme %s", __func__, name); | ||
825 | free(name); | 867 | free(name); |
826 | return SSH_ERR_INTERNAL_ERROR; | 868 | return SSH_ERR_INTERNAL_ERROR; |
827 | } | 869 | } |
@@ -839,8 +881,10 @@ choose_kex(struct kex *k, char *client, char *server) | |||
839 | debug("kex: algorithm: %s", k->name ? k->name : "(no match)"); | 881 | debug("kex: algorithm: %s", k->name ? k->name : "(no match)"); |
840 | if (k->name == NULL) | 882 | if (k->name == NULL) |
841 | return SSH_ERR_NO_KEX_ALG_MATCH; | 883 | return SSH_ERR_NO_KEX_ALG_MATCH; |
842 | if ((kexalg = kex_alg_by_name(k->name)) == NULL) | 884 | if ((kexalg = kex_alg_by_name(k->name)) == NULL) { |
885 | error("%s: unsupported KEX method %s", __func__, k->name); | ||
843 | return SSH_ERR_INTERNAL_ERROR; | 886 | return SSH_ERR_INTERNAL_ERROR; |
887 | } | ||
844 | k->kex_type = kexalg->type; | 888 | k->kex_type = kexalg->type; |
845 | k->hash_alg = kexalg->hash_alg; | 889 | k->hash_alg = kexalg->hash_alg; |
846 | k->ec_nid = kexalg->ec_nid; | 890 | k->ec_nid = kexalg->ec_nid; |
@@ -857,8 +901,11 @@ choose_hostkeyalg(struct kex *k, char *client, char *server) | |||
857 | if (k->hostkey_alg == NULL) | 901 | if (k->hostkey_alg == NULL) |
858 | return SSH_ERR_NO_HOSTKEY_ALG_MATCH; | 902 | return SSH_ERR_NO_HOSTKEY_ALG_MATCH; |
859 | k->hostkey_type = sshkey_type_from_name(k->hostkey_alg); | 903 | k->hostkey_type = sshkey_type_from_name(k->hostkey_alg); |
860 | if (k->hostkey_type == KEY_UNSPEC) | 904 | if (k->hostkey_type == KEY_UNSPEC) { |
905 | error("%s: unsupported hostkey algorithm %s", __func__, | ||
906 | k->hostkey_alg); | ||
861 | return SSH_ERR_INTERNAL_ERROR; | 907 | return SSH_ERR_INTERNAL_ERROR; |
908 | } | ||
862 | k->hostkey_nid = sshkey_ecdsa_nid_from_name(k->hostkey_alg); | 909 | k->hostkey_nid = sshkey_ecdsa_nid_from_name(k->hostkey_alg); |
863 | return 0; | 910 | return 0; |
864 | } | 911 | } |
@@ -1027,6 +1074,7 @@ derive_key(struct ssh *ssh, int id, u_int need, u_char *hash, u_int hashlen, | |||
1027 | kex->session_id_len) != 0 || | 1074 | kex->session_id_len) != 0 || |
1028 | ssh_digest_final(hashctx, digest, mdsz) != 0) { | 1075 | ssh_digest_final(hashctx, digest, mdsz) != 0) { |
1029 | r = SSH_ERR_LIBCRYPTO_ERROR; | 1076 | r = SSH_ERR_LIBCRYPTO_ERROR; |
1077 | error("%s: KEX hash failed", __func__); | ||
1030 | goto out; | 1078 | goto out; |
1031 | } | 1079 | } |
1032 | ssh_digest_free(hashctx); | 1080 | ssh_digest_free(hashctx); |
@@ -1043,6 +1091,7 @@ derive_key(struct ssh *ssh, int id, u_int need, u_char *hash, u_int hashlen, | |||
1043 | ssh_digest_update(hashctx, hash, hashlen) != 0 || | 1091 | ssh_digest_update(hashctx, hash, hashlen) != 0 || |
1044 | ssh_digest_update(hashctx, digest, have) != 0 || | 1092 | ssh_digest_update(hashctx, digest, have) != 0 || |
1045 | ssh_digest_final(hashctx, digest + have, mdsz) != 0) { | 1093 | ssh_digest_final(hashctx, digest + have, mdsz) != 0) { |
1094 | error("%s: KDF failed", __func__); | ||
1046 | r = SSH_ERR_LIBCRYPTO_ERROR; | 1095 | r = SSH_ERR_LIBCRYPTO_ERROR; |
1047 | goto out; | 1096 | goto out; |
1048 | } | 1097 | } |
@@ -1106,8 +1155,10 @@ kex_load_hostkey(struct ssh *ssh, struct sshkey **prvp, struct sshkey **pubp) | |||
1106 | *pubp = NULL; | 1155 | *pubp = NULL; |
1107 | *prvp = NULL; | 1156 | *prvp = NULL; |
1108 | if (kex->load_host_public_key == NULL || | 1157 | if (kex->load_host_public_key == NULL || |
1109 | kex->load_host_private_key == NULL) | 1158 | kex->load_host_private_key == NULL) { |
1159 | error("%s: missing hostkey loader", __func__); | ||
1110 | return SSH_ERR_INVALID_ARGUMENT; | 1160 | return SSH_ERR_INVALID_ARGUMENT; |
1161 | } | ||
1111 | *pubp = kex->load_host_public_key(kex->hostkey_type, | 1162 | *pubp = kex->load_host_public_key(kex->hostkey_type, |
1112 | kex->hostkey_nid, ssh); | 1163 | kex->hostkey_nid, ssh); |
1113 | *prvp = kex->load_host_private_key(kex->hostkey_type, | 1164 | *prvp = kex->load_host_private_key(kex->hostkey_type, |
@@ -1122,8 +1173,10 @@ kex_verify_host_key(struct ssh *ssh, struct sshkey *server_host_key) | |||
1122 | { | 1173 | { |
1123 | struct kex *kex = ssh->kex; | 1174 | struct kex *kex = ssh->kex; |
1124 | 1175 | ||
1125 | if (kex->verify_host_key == NULL) | 1176 | if (kex->verify_host_key == NULL) { |
1177 | error("%s: missing hostkey verifier", __func__); | ||
1126 | return SSH_ERR_INVALID_ARGUMENT; | 1178 | return SSH_ERR_INVALID_ARGUMENT; |
1179 | } | ||
1127 | if (server_host_key->type != kex->hostkey_type || | 1180 | if (server_host_key->type != kex->hostkey_type || |
1128 | (kex->hostkey_type == KEY_ECDSA && | 1181 | (kex->hostkey_type == KEY_ECDSA && |
1129 | server_host_key->ecdsa_nid != kex->hostkey_nid)) | 1182 | server_host_key->ecdsa_nid != kex->hostkey_nid)) |