summaryrefslogtreecommitdiff
path: root/kex.c
diff options
context:
space:
mode:
authorColin Watson <cjwatson@debian.org>2019-10-09 22:59:48 +0100
committerColin Watson <cjwatson@debian.org>2019-10-09 23:39:39 +0100
commit767ee84d3465b6d244a9108de5c167a9ab866df9 (patch)
tree69b14ef6a62d7f133298a21d2ad6046f130b7801 /kex.c
parentddeaf9ee7d5c6612b88f1c4a83fc6fbccb93bf60 (diff)
parentefef12825b9582c1710da3b7e50135870963d4f4 (diff)
New upstream release (8.1p1)
Diffstat (limited to 'kex.c')
-rw-r--r--kex.c107
1 files changed, 80 insertions, 27 deletions
diff --git a/kex.c b/kex.c
index bbb7a2340..f450bc2c7 100644
--- a/kex.c
+++ b/kex.c
@@ -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};
121static const struct kexalg gss_kexalgs[] = { 121static 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
135static char * 135static 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 */
253int 254int
254kex_assemble_names(char **listp, const char *def, const char *all) 255kex_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))