ena.4: Add a missing space.
[dragonfly.git] / crypto / openssh / kex.c
blobd5d5a9dae996072e779597ccfa805b5e0bc8fc83
1 /* $OpenBSD: kex.c,v 1.134 2017/06/13 12:13:59 djm Exp $ */
2 /*
3 * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
18 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 #include "includes.h"
29 #include <signal.h>
30 #include <stdarg.h>
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
35 #ifdef WITH_OPENSSL
36 #include <openssl/crypto.h>
37 #include <openssl/dh.h>
38 #endif
40 #include "ssh2.h"
41 #include "packet.h"
42 #include "compat.h"
43 #include "cipher.h"
44 #include "sshkey.h"
45 #include "kex.h"
46 #include "log.h"
47 #include "mac.h"
48 #include "match.h"
49 #include "misc.h"
50 #include "dispatch.h"
51 #include "monitor.h"
53 #include "ssherr.h"
54 #include "sshbuf.h"
55 #include "digest.h"
57 /* prototype */
58 static int kex_choose_conf(struct ssh *);
59 static int kex_input_newkeys(int, u_int32_t, struct ssh *);
61 static const char *proposal_names[PROPOSAL_MAX] = {
62 "KEX algorithms",
63 "host key algorithms",
64 "ciphers ctos",
65 "ciphers stoc",
66 "MACs ctos",
67 "MACs stoc",
68 "compression ctos",
69 "compression stoc",
70 "languages ctos",
71 "languages stoc",
74 struct kexalg {
75 char *name;
76 u_int type;
77 int ec_nid;
78 int hash_alg;
80 static const struct kexalg kexalgs[] = {
81 #ifdef WITH_OPENSSL
82 { KEX_DH1, KEX_DH_GRP1_SHA1, 0, SSH_DIGEST_SHA1 },
83 { KEX_DH14_SHA1, KEX_DH_GRP14_SHA1, 0, SSH_DIGEST_SHA1 },
84 { KEX_DH14_SHA256, KEX_DH_GRP14_SHA256, 0, SSH_DIGEST_SHA256 },
85 { KEX_DH16_SHA512, KEX_DH_GRP16_SHA512, 0, SSH_DIGEST_SHA512 },
86 { KEX_DH18_SHA512, KEX_DH_GRP18_SHA512, 0, SSH_DIGEST_SHA512 },
87 { KEX_DHGEX_SHA1, KEX_DH_GEX_SHA1, 0, SSH_DIGEST_SHA1 },
88 #ifdef HAVE_EVP_SHA256
89 { KEX_DHGEX_SHA256, KEX_DH_GEX_SHA256, 0, SSH_DIGEST_SHA256 },
90 #endif /* HAVE_EVP_SHA256 */
91 #ifdef OPENSSL_HAS_ECC
92 { KEX_ECDH_SHA2_NISTP256, KEX_ECDH_SHA2,
93 NID_X9_62_prime256v1, SSH_DIGEST_SHA256 },
94 { KEX_ECDH_SHA2_NISTP384, KEX_ECDH_SHA2, NID_secp384r1,
95 SSH_DIGEST_SHA384 },
96 # ifdef OPENSSL_HAS_NISTP521
97 { KEX_ECDH_SHA2_NISTP521, KEX_ECDH_SHA2, NID_secp521r1,
98 SSH_DIGEST_SHA512 },
99 # endif /* OPENSSL_HAS_NISTP521 */
100 #endif /* OPENSSL_HAS_ECC */
101 #endif /* WITH_OPENSSL */
102 #if defined(HAVE_EVP_SHA256) || !defined(WITH_OPENSSL)
103 { KEX_CURVE25519_SHA256, KEX_C25519_SHA256, 0, SSH_DIGEST_SHA256 },
104 { KEX_CURVE25519_SHA256_OLD, KEX_C25519_SHA256, 0, SSH_DIGEST_SHA256 },
105 #endif /* HAVE_EVP_SHA256 || !WITH_OPENSSL */
106 { NULL, -1, -1, -1},
109 char *
110 kex_alg_list(char sep)
112 char *ret = NULL, *tmp;
113 size_t nlen, rlen = 0;
114 const struct kexalg *k;
116 for (k = kexalgs; k->name != NULL; k++) {
117 if (ret != NULL)
118 ret[rlen++] = sep;
119 nlen = strlen(k->name);
120 if ((tmp = realloc(ret, rlen + nlen + 2)) == NULL) {
121 free(ret);
122 return NULL;
124 ret = tmp;
125 memcpy(ret + rlen, k->name, nlen + 1);
126 rlen += nlen;
128 return ret;
131 static const struct kexalg *
132 kex_alg_by_name(const char *name)
134 const struct kexalg *k;
136 for (k = kexalgs; k->name != NULL; k++) {
137 if (strcmp(k->name, name) == 0)
138 return k;
140 return NULL;
143 /* Validate KEX method name list */
145 kex_names_valid(const char *names)
147 char *s, *cp, *p;
149 if (names == NULL || strcmp(names, "") == 0)
150 return 0;
151 if ((s = cp = strdup(names)) == NULL)
152 return 0;
153 for ((p = strsep(&cp, ",")); p && *p != '\0';
154 (p = strsep(&cp, ","))) {
155 if (kex_alg_by_name(p) == NULL) {
156 error("Unsupported KEX algorithm \"%.100s\"", p);
157 free(s);
158 return 0;
161 debug3("kex names ok: [%s]", names);
162 free(s);
163 return 1;
167 * Concatenate algorithm names, avoiding duplicates in the process.
168 * Caller must free returned string.
170 char *
171 kex_names_cat(const char *a, const char *b)
173 char *ret = NULL, *tmp = NULL, *cp, *p, *m;
174 size_t len;
176 if (a == NULL || *a == '\0')
177 return NULL;
178 if (b == NULL || *b == '\0')
179 return strdup(a);
180 if (strlen(b) > 1024*1024)
181 return NULL;
182 len = strlen(a) + strlen(b) + 2;
183 if ((tmp = cp = strdup(b)) == NULL ||
184 (ret = calloc(1, len)) == NULL) {
185 free(tmp);
186 return NULL;
188 strlcpy(ret, a, len);
189 for ((p = strsep(&cp, ",")); p && *p != '\0'; (p = strsep(&cp, ","))) {
190 if ((m = match_list(ret, p, NULL)) != NULL) {
191 free(m);
192 continue; /* Algorithm already present */
194 if (strlcat(ret, ",", len) >= len ||
195 strlcat(ret, p, len) >= len) {
196 free(tmp);
197 free(ret);
198 return NULL; /* Shouldn't happen */
201 free(tmp);
202 return ret;
206 * Assemble a list of algorithms from a default list and a string from a
207 * configuration file. The user-provided string may begin with '+' to
208 * indicate that it should be appended to the default or '-' that the
209 * specified names should be removed.
212 kex_assemble_names(const char *def, char **list)
214 char *ret;
216 if (list == NULL || *list == NULL || **list == '\0') {
217 *list = strdup(def);
218 return 0;
220 if (**list == '+') {
221 if ((ret = kex_names_cat(def, *list + 1)) == NULL)
222 return SSH_ERR_ALLOC_FAIL;
223 free(*list);
224 *list = ret;
225 } else if (**list == '-') {
226 if ((ret = match_filter_list(def, *list + 1)) == NULL)
227 return SSH_ERR_ALLOC_FAIL;
228 free(*list);
229 *list = ret;
232 return 0;
235 /* put algorithm proposal into buffer */
237 kex_prop2buf(struct sshbuf *b, char *proposal[PROPOSAL_MAX])
239 u_int i;
240 int r;
242 sshbuf_reset(b);
245 * add a dummy cookie, the cookie will be overwritten by
246 * kex_send_kexinit(), each time a kexinit is set
248 for (i = 0; i < KEX_COOKIE_LEN; i++) {
249 if ((r = sshbuf_put_u8(b, 0)) != 0)
250 return r;
252 for (i = 0; i < PROPOSAL_MAX; i++) {
253 if ((r = sshbuf_put_cstring(b, proposal[i])) != 0)
254 return r;
256 if ((r = sshbuf_put_u8(b, 0)) != 0 || /* first_kex_packet_follows */
257 (r = sshbuf_put_u32(b, 0)) != 0) /* uint32 reserved */
258 return r;
259 return 0;
262 /* parse buffer and return algorithm proposal */
264 kex_buf2prop(struct sshbuf *raw, int *first_kex_follows, char ***propp)
266 struct sshbuf *b = NULL;
267 u_char v;
268 u_int i;
269 char **proposal = NULL;
270 int r;
272 *propp = NULL;
273 if ((proposal = calloc(PROPOSAL_MAX, sizeof(char *))) == NULL)
274 return SSH_ERR_ALLOC_FAIL;
275 if ((b = sshbuf_fromb(raw)) == NULL) {
276 r = SSH_ERR_ALLOC_FAIL;
277 goto out;
279 if ((r = sshbuf_consume(b, KEX_COOKIE_LEN)) != 0) /* skip cookie */
280 goto out;
281 /* extract kex init proposal strings */
282 for (i = 0; i < PROPOSAL_MAX; i++) {
283 if ((r = sshbuf_get_cstring(b, &(proposal[i]), NULL)) != 0)
284 goto out;
285 debug2("%s: %s", proposal_names[i], proposal[i]);
287 /* first kex follows / reserved */
288 if ((r = sshbuf_get_u8(b, &v)) != 0 || /* first_kex_follows */
289 (r = sshbuf_get_u32(b, &i)) != 0) /* reserved */
290 goto out;
291 if (first_kex_follows != NULL)
292 *first_kex_follows = v;
293 debug2("first_kex_follows %d ", v);
294 debug2("reserved %u ", i);
295 r = 0;
296 *propp = proposal;
297 out:
298 if (r != 0 && proposal != NULL)
299 kex_prop_free(proposal);
300 sshbuf_free(b);
301 return r;
304 void
305 kex_prop_free(char **proposal)
307 u_int i;
309 if (proposal == NULL)
310 return;
311 for (i = 0; i < PROPOSAL_MAX; i++)
312 free(proposal[i]);
313 free(proposal);
316 /* ARGSUSED */
317 static int
318 kex_protocol_error(int type, u_int32_t seq, struct ssh *ssh)
320 int r;
322 error("kex protocol error: type %d seq %u", type, seq);
323 if ((r = sshpkt_start(ssh, SSH2_MSG_UNIMPLEMENTED)) != 0 ||
324 (r = sshpkt_put_u32(ssh, seq)) != 0 ||
325 (r = sshpkt_send(ssh)) != 0)
326 return r;
327 return 0;
330 static void
331 kex_reset_dispatch(struct ssh *ssh)
333 ssh_dispatch_range(ssh, SSH2_MSG_TRANSPORT_MIN,
334 SSH2_MSG_TRANSPORT_MAX, &kex_protocol_error);
337 static int
338 kex_send_ext_info(struct ssh *ssh)
340 int r;
341 char *algs;
343 if ((algs = sshkey_alg_list(0, 1, 1, ',')) == NULL)
344 return SSH_ERR_ALLOC_FAIL;
345 if ((r = sshpkt_start(ssh, SSH2_MSG_EXT_INFO)) != 0 ||
346 (r = sshpkt_put_u32(ssh, 1)) != 0 ||
347 (r = sshpkt_put_cstring(ssh, "server-sig-algs")) != 0 ||
348 (r = sshpkt_put_cstring(ssh, algs)) != 0 ||
349 (r = sshpkt_send(ssh)) != 0)
350 goto out;
351 /* success */
352 r = 0;
353 out:
354 free(algs);
355 return r;
359 kex_send_newkeys(struct ssh *ssh)
361 int r;
363 kex_reset_dispatch(ssh);
364 if ((r = sshpkt_start(ssh, SSH2_MSG_NEWKEYS)) != 0 ||
365 (r = sshpkt_send(ssh)) != 0)
366 return r;
367 debug("SSH2_MSG_NEWKEYS sent");
368 debug("expecting SSH2_MSG_NEWKEYS");
369 ssh_dispatch_set(ssh, SSH2_MSG_NEWKEYS, &kex_input_newkeys);
370 if (ssh->kex->ext_info_c)
371 if ((r = kex_send_ext_info(ssh)) != 0)
372 return r;
373 return 0;
377 kex_input_ext_info(int type, u_int32_t seq, struct ssh *ssh)
379 struct kex *kex = ssh->kex;
380 u_int32_t i, ninfo;
381 char *name, *found;
382 u_char *val;
383 size_t vlen;
384 int r;
386 debug("SSH2_MSG_EXT_INFO received");
387 ssh_dispatch_set(ssh, SSH2_MSG_EXT_INFO, &kex_protocol_error);
388 if ((r = sshpkt_get_u32(ssh, &ninfo)) != 0)
389 return r;
390 for (i = 0; i < ninfo; i++) {
391 if ((r = sshpkt_get_cstring(ssh, &name, NULL)) != 0)
392 return r;
393 if ((r = sshpkt_get_string(ssh, &val, &vlen)) != 0) {
394 free(name);
395 return r;
397 if (strcmp(name, "server-sig-algs") == 0) {
398 /* Ensure no \0 lurking in value */
399 if (memchr(val, '\0', vlen) != NULL) {
400 error("%s: nul byte in %s", __func__, name);
401 return SSH_ERR_INVALID_FORMAT;
403 debug("%s: %s=<%s>", __func__, name, val);
404 found = match_list("rsa-sha2-256", val, NULL);
405 if (found) {
406 kex->rsa_sha2 = 256;
407 free(found);
409 found = match_list("rsa-sha2-512", val, NULL);
410 if (found) {
411 kex->rsa_sha2 = 512;
412 free(found);
414 } else
415 debug("%s: %s (unrecognised)", __func__, name);
416 free(name);
417 free(val);
419 return sshpkt_get_end(ssh);
422 static int
423 kex_input_newkeys(int type, u_int32_t seq, struct ssh *ssh)
425 struct kex *kex = ssh->kex;
426 int r;
428 debug("SSH2_MSG_NEWKEYS received");
429 ssh_dispatch_set(ssh, SSH2_MSG_NEWKEYS, &kex_protocol_error);
430 ssh_dispatch_set(ssh, SSH2_MSG_KEXINIT, &kex_input_kexinit);
431 if ((r = sshpkt_get_end(ssh)) != 0)
432 return r;
433 if ((r = ssh_set_newkeys(ssh, MODE_IN)) != 0)
434 return r;
435 kex->done = 1;
436 sshbuf_reset(kex->peer);
437 /* sshbuf_reset(kex->my); */
438 kex->flags &= ~KEX_INIT_SENT;
439 free(kex->name);
440 kex->name = NULL;
441 return 0;
445 kex_send_kexinit(struct ssh *ssh)
447 u_char *cookie;
448 struct kex *kex = ssh->kex;
449 int r;
451 if (kex == NULL)
452 return SSH_ERR_INTERNAL_ERROR;
453 if (kex->flags & KEX_INIT_SENT)
454 return 0;
455 kex->done = 0;
457 /* generate a random cookie */
458 if (sshbuf_len(kex->my) < KEX_COOKIE_LEN)
459 return SSH_ERR_INVALID_FORMAT;
460 if ((cookie = sshbuf_mutable_ptr(kex->my)) == NULL)
461 return SSH_ERR_INTERNAL_ERROR;
462 arc4random_buf(cookie, KEX_COOKIE_LEN);
464 if ((r = sshpkt_start(ssh, SSH2_MSG_KEXINIT)) != 0 ||
465 (r = sshpkt_putb(ssh, kex->my)) != 0 ||
466 (r = sshpkt_send(ssh)) != 0)
467 return r;
468 debug("SSH2_MSG_KEXINIT sent");
469 kex->flags |= KEX_INIT_SENT;
470 return 0;
473 /* ARGSUSED */
475 kex_input_kexinit(int type, u_int32_t seq, struct ssh *ssh)
477 struct kex *kex = ssh->kex;
478 const u_char *ptr;
479 u_int i;
480 size_t dlen;
481 int r;
483 debug("SSH2_MSG_KEXINIT received");
484 if (kex == NULL)
485 return SSH_ERR_INVALID_ARGUMENT;
487 ssh_dispatch_set(ssh, SSH2_MSG_KEXINIT, NULL);
488 ptr = sshpkt_ptr(ssh, &dlen);
489 if ((r = sshbuf_put(kex->peer, ptr, dlen)) != 0)
490 return r;
492 /* discard packet */
493 for (i = 0; i < KEX_COOKIE_LEN; i++)
494 if ((r = sshpkt_get_u8(ssh, NULL)) != 0)
495 return r;
496 for (i = 0; i < PROPOSAL_MAX; i++)
497 if ((r = sshpkt_get_string(ssh, NULL, NULL)) != 0)
498 return r;
500 * XXX RFC4253 sec 7: "each side MAY guess" - currently no supported
501 * KEX method has the server move first, but a server might be using
502 * a custom method or one that we otherwise don't support. We should
503 * be prepared to remember first_kex_follows here so we can eat a
504 * packet later.
505 * XXX2 - RFC4253 is kind of ambiguous on what first_kex_follows means
506 * for cases where the server *doesn't* go first. I guess we should
507 * ignore it when it is set for these cases, which is what we do now.
509 if ((r = sshpkt_get_u8(ssh, NULL)) != 0 || /* first_kex_follows */
510 (r = sshpkt_get_u32(ssh, NULL)) != 0 || /* reserved */
511 (r = sshpkt_get_end(ssh)) != 0)
512 return r;
514 if (!(kex->flags & KEX_INIT_SENT))
515 if ((r = kex_send_kexinit(ssh)) != 0)
516 return r;
517 if ((r = kex_choose_conf(ssh)) != 0)
518 return r;
520 if (kex->kex_type < KEX_MAX && kex->kex[kex->kex_type] != NULL)
521 return (kex->kex[kex->kex_type])(ssh);
523 return SSH_ERR_INTERNAL_ERROR;
527 kex_new(struct ssh *ssh, char *proposal[PROPOSAL_MAX], struct kex **kexp)
529 struct kex *kex;
530 int r;
532 *kexp = NULL;
533 if ((kex = calloc(1, sizeof(*kex))) == NULL)
534 return SSH_ERR_ALLOC_FAIL;
535 if ((kex->peer = sshbuf_new()) == NULL ||
536 (kex->my = sshbuf_new()) == NULL) {
537 r = SSH_ERR_ALLOC_FAIL;
538 goto out;
540 if ((r = kex_prop2buf(kex->my, proposal)) != 0)
541 goto out;
542 kex->done = 0;
543 kex_reset_dispatch(ssh);
544 ssh_dispatch_set(ssh, SSH2_MSG_KEXINIT, &kex_input_kexinit);
545 r = 0;
546 *kexp = kex;
547 out:
548 if (r != 0)
549 kex_free(kex);
550 return r;
553 void
554 kex_free_newkeys(struct newkeys *newkeys)
556 if (newkeys == NULL)
557 return;
558 if (newkeys->enc.key) {
559 explicit_bzero(newkeys->enc.key, newkeys->enc.key_len);
560 free(newkeys->enc.key);
561 newkeys->enc.key = NULL;
563 if (newkeys->enc.iv) {
564 explicit_bzero(newkeys->enc.iv, newkeys->enc.iv_len);
565 free(newkeys->enc.iv);
566 newkeys->enc.iv = NULL;
568 free(newkeys->enc.name);
569 explicit_bzero(&newkeys->enc, sizeof(newkeys->enc));
570 free(newkeys->comp.name);
571 explicit_bzero(&newkeys->comp, sizeof(newkeys->comp));
572 mac_clear(&newkeys->mac);
573 if (newkeys->mac.key) {
574 explicit_bzero(newkeys->mac.key, newkeys->mac.key_len);
575 free(newkeys->mac.key);
576 newkeys->mac.key = NULL;
578 free(newkeys->mac.name);
579 explicit_bzero(&newkeys->mac, sizeof(newkeys->mac));
580 explicit_bzero(newkeys, sizeof(*newkeys));
581 free(newkeys);
584 void
585 kex_free(struct kex *kex)
587 u_int mode;
589 #ifdef WITH_OPENSSL
590 if (kex->dh)
591 DH_free(kex->dh);
592 #ifdef OPENSSL_HAS_ECC
593 if (kex->ec_client_key)
594 EC_KEY_free(kex->ec_client_key);
595 #endif /* OPENSSL_HAS_ECC */
596 #endif /* WITH_OPENSSL */
597 for (mode = 0; mode < MODE_MAX; mode++) {
598 kex_free_newkeys(kex->newkeys[mode]);
599 kex->newkeys[mode] = NULL;
601 sshbuf_free(kex->peer);
602 sshbuf_free(kex->my);
603 free(kex->session_id);
604 free(kex->client_version_string);
605 free(kex->server_version_string);
606 free(kex->failed_choice);
607 free(kex->hostkey_alg);
608 free(kex->name);
609 free(kex);
613 kex_setup(struct ssh *ssh, char *proposal[PROPOSAL_MAX])
615 int r;
617 if ((r = kex_new(ssh, proposal, &ssh->kex)) != 0)
618 return r;
619 if ((r = kex_send_kexinit(ssh)) != 0) { /* we start */
620 kex_free(ssh->kex);
621 ssh->kex = NULL;
622 return r;
624 return 0;
628 * Request key re-exchange, returns 0 on success or a ssherr.h error
629 * code otherwise. Must not be called if KEX is incomplete or in-progress.
632 kex_start_rekex(struct ssh *ssh)
634 if (ssh->kex == NULL) {
635 error("%s: no kex", __func__);
636 return SSH_ERR_INTERNAL_ERROR;
638 if (ssh->kex->done == 0) {
639 error("%s: requested twice", __func__);
640 return SSH_ERR_INTERNAL_ERROR;
642 ssh->kex->done = 0;
643 return kex_send_kexinit(ssh);
646 static int
647 choose_enc(struct sshenc *enc, char *client, char *server)
649 char *name = match_list(client, server, NULL);
651 if (name == NULL)
652 return SSH_ERR_NO_CIPHER_ALG_MATCH;
653 if ((enc->cipher = cipher_by_name(name)) == NULL) {
654 free(name);
655 return SSH_ERR_INTERNAL_ERROR;
657 enc->name = name;
658 enc->enabled = 0;
659 enc->iv = NULL;
660 enc->iv_len = cipher_ivlen(enc->cipher);
661 enc->key = NULL;
662 enc->key_len = cipher_keylen(enc->cipher);
663 enc->block_size = cipher_blocksize(enc->cipher);
664 return 0;
667 static int
668 choose_mac(struct ssh *ssh, struct sshmac *mac, char *client, char *server)
670 char *name = match_list(client, server, NULL);
672 if (name == NULL)
673 return SSH_ERR_NO_MAC_ALG_MATCH;
674 if (mac_setup(mac, name) < 0) {
675 free(name);
676 return SSH_ERR_INTERNAL_ERROR;
678 /* truncate the key */
679 if (ssh->compat & SSH_BUG_HMAC)
680 mac->key_len = 16;
681 mac->name = name;
682 mac->key = NULL;
683 mac->enabled = 0;
684 return 0;
687 static int
688 choose_comp(struct sshcomp *comp, char *client, char *server)
690 char *name = match_list(client, server, NULL);
692 if (name == NULL)
693 return SSH_ERR_NO_COMPRESS_ALG_MATCH;
694 if (strcmp(name, "zlib@openssh.com") == 0) {
695 comp->type = COMP_DELAYED;
696 } else if (strcmp(name, "zlib") == 0) {
697 comp->type = COMP_ZLIB;
698 } else if (strcmp(name, "none") == 0) {
699 comp->type = COMP_NONE;
700 } else {
701 free(name);
702 return SSH_ERR_INTERNAL_ERROR;
704 comp->name = name;
705 return 0;
708 static int
709 choose_kex(struct kex *k, char *client, char *server)
711 const struct kexalg *kexalg;
713 k->name = match_list(client, server, NULL);
715 debug("kex: algorithm: %s", k->name ? k->name : "(no match)");
716 if (k->name == NULL)
717 return SSH_ERR_NO_KEX_ALG_MATCH;
718 if ((kexalg = kex_alg_by_name(k->name)) == NULL)
719 return SSH_ERR_INTERNAL_ERROR;
720 k->kex_type = kexalg->type;
721 k->hash_alg = kexalg->hash_alg;
722 k->ec_nid = kexalg->ec_nid;
723 return 0;
726 static int
727 choose_hostkeyalg(struct kex *k, char *client, char *server)
729 k->hostkey_alg = match_list(client, server, NULL);
731 debug("kex: host key algorithm: %s",
732 k->hostkey_alg ? k->hostkey_alg : "(no match)");
733 if (k->hostkey_alg == NULL)
734 return SSH_ERR_NO_HOSTKEY_ALG_MATCH;
735 k->hostkey_type = sshkey_type_from_name(k->hostkey_alg);
736 if (k->hostkey_type == KEY_UNSPEC)
737 return SSH_ERR_INTERNAL_ERROR;
738 k->hostkey_nid = sshkey_ecdsa_nid_from_name(k->hostkey_alg);
739 return 0;
742 static int
743 proposals_match(char *my[PROPOSAL_MAX], char *peer[PROPOSAL_MAX])
745 static int check[] = {
746 PROPOSAL_KEX_ALGS, PROPOSAL_SERVER_HOST_KEY_ALGS, -1
748 int *idx;
749 char *p;
751 for (idx = &check[0]; *idx != -1; idx++) {
752 if ((p = strchr(my[*idx], ',')) != NULL)
753 *p = '\0';
754 if ((p = strchr(peer[*idx], ',')) != NULL)
755 *p = '\0';
756 if (strcmp(my[*idx], peer[*idx]) != 0) {
757 debug2("proposal mismatch: my %s peer %s",
758 my[*idx], peer[*idx]);
759 return (0);
762 debug2("proposals match");
763 return (1);
766 static int
767 kex_choose_conf(struct ssh *ssh)
769 struct kex *kex = ssh->kex;
770 struct newkeys *newkeys;
771 char **my = NULL, **peer = NULL;
772 char **cprop, **sprop;
773 int nenc, nmac, ncomp;
774 u_int mode, ctos, need, dh_need, authlen;
775 int r, first_kex_follows;
777 debug2("local %s KEXINIT proposal", kex->server ? "server" : "client");
778 if ((r = kex_buf2prop(kex->my, NULL, &my)) != 0)
779 goto out;
780 debug2("peer %s KEXINIT proposal", kex->server ? "client" : "server");
781 if ((r = kex_buf2prop(kex->peer, &first_kex_follows, &peer)) != 0)
782 goto out;
784 if (kex->server) {
785 cprop=peer;
786 sprop=my;
787 } else {
788 cprop=my;
789 sprop=peer;
792 /* Check whether client supports ext_info_c */
793 if (kex->server) {
794 char *ext;
796 ext = match_list("ext-info-c", peer[PROPOSAL_KEX_ALGS], NULL);
797 kex->ext_info_c = (ext != NULL);
798 free(ext);
801 /* Algorithm Negotiation */
802 if ((r = choose_kex(kex, cprop[PROPOSAL_KEX_ALGS],
803 sprop[PROPOSAL_KEX_ALGS])) != 0) {
804 kex->failed_choice = peer[PROPOSAL_KEX_ALGS];
805 peer[PROPOSAL_KEX_ALGS] = NULL;
806 goto out;
808 if ((r = choose_hostkeyalg(kex, cprop[PROPOSAL_SERVER_HOST_KEY_ALGS],
809 sprop[PROPOSAL_SERVER_HOST_KEY_ALGS])) != 0) {
810 kex->failed_choice = peer[PROPOSAL_SERVER_HOST_KEY_ALGS];
811 peer[PROPOSAL_SERVER_HOST_KEY_ALGS] = NULL;
812 goto out;
814 for (mode = 0; mode < MODE_MAX; mode++) {
815 if ((newkeys = calloc(1, sizeof(*newkeys))) == NULL) {
816 r = SSH_ERR_ALLOC_FAIL;
817 goto out;
819 kex->newkeys[mode] = newkeys;
820 ctos = (!kex->server && mode == MODE_OUT) ||
821 (kex->server && mode == MODE_IN);
822 nenc = ctos ? PROPOSAL_ENC_ALGS_CTOS : PROPOSAL_ENC_ALGS_STOC;
823 nmac = ctos ? PROPOSAL_MAC_ALGS_CTOS : PROPOSAL_MAC_ALGS_STOC;
824 ncomp = ctos ? PROPOSAL_COMP_ALGS_CTOS : PROPOSAL_COMP_ALGS_STOC;
825 if ((r = choose_enc(&newkeys->enc, cprop[nenc],
826 sprop[nenc])) != 0) {
827 kex->failed_choice = peer[nenc];
828 peer[nenc] = NULL;
829 goto out;
831 authlen = cipher_authlen(newkeys->enc.cipher);
832 /* ignore mac for authenticated encryption */
833 if (authlen == 0 &&
834 (r = choose_mac(ssh, &newkeys->mac, cprop[nmac],
835 sprop[nmac])) != 0) {
836 kex->failed_choice = peer[nmac];
837 peer[nmac] = NULL;
838 goto out;
840 if ((r = choose_comp(&newkeys->comp, cprop[ncomp],
841 sprop[ncomp])) != 0) {
842 kex->failed_choice = peer[ncomp];
843 peer[ncomp] = NULL;
844 goto out;
846 debug("kex: %s cipher: %s MAC: %s compression: %s",
847 ctos ? "client->server" : "server->client",
848 newkeys->enc.name,
849 authlen == 0 ? newkeys->mac.name : "<implicit>",
850 newkeys->comp.name);
852 need = dh_need = 0;
853 for (mode = 0; mode < MODE_MAX; mode++) {
854 newkeys = kex->newkeys[mode];
855 need = MAXIMUM(need, newkeys->enc.key_len);
856 need = MAXIMUM(need, newkeys->enc.block_size);
857 need = MAXIMUM(need, newkeys->enc.iv_len);
858 need = MAXIMUM(need, newkeys->mac.key_len);
859 dh_need = MAXIMUM(dh_need, cipher_seclen(newkeys->enc.cipher));
860 dh_need = MAXIMUM(dh_need, newkeys->enc.block_size);
861 dh_need = MAXIMUM(dh_need, newkeys->enc.iv_len);
862 dh_need = MAXIMUM(dh_need, newkeys->mac.key_len);
864 /* XXX need runden? */
865 kex->we_need = need;
866 kex->dh_need = dh_need;
868 /* ignore the next message if the proposals do not match */
869 if (first_kex_follows && !proposals_match(my, peer) &&
870 !(ssh->compat & SSH_BUG_FIRSTKEX))
871 ssh->dispatch_skip_packets = 1;
872 r = 0;
873 out:
874 kex_prop_free(my);
875 kex_prop_free(peer);
876 return r;
879 static int
880 derive_key(struct ssh *ssh, int id, u_int need, u_char *hash, u_int hashlen,
881 const struct sshbuf *shared_secret, u_char **keyp)
883 struct kex *kex = ssh->kex;
884 struct ssh_digest_ctx *hashctx = NULL;
885 char c = id;
886 u_int have;
887 size_t mdsz;
888 u_char *digest;
889 int r;
891 if ((mdsz = ssh_digest_bytes(kex->hash_alg)) == 0)
892 return SSH_ERR_INVALID_ARGUMENT;
893 if ((digest = calloc(1, ROUNDUP(need, mdsz))) == NULL) {
894 r = SSH_ERR_ALLOC_FAIL;
895 goto out;
898 /* K1 = HASH(K || H || "A" || session_id) */
899 if ((hashctx = ssh_digest_start(kex->hash_alg)) == NULL ||
900 ssh_digest_update_buffer(hashctx, shared_secret) != 0 ||
901 ssh_digest_update(hashctx, hash, hashlen) != 0 ||
902 ssh_digest_update(hashctx, &c, 1) != 0 ||
903 ssh_digest_update(hashctx, kex->session_id,
904 kex->session_id_len) != 0 ||
905 ssh_digest_final(hashctx, digest, mdsz) != 0) {
906 r = SSH_ERR_LIBCRYPTO_ERROR;
907 goto out;
909 ssh_digest_free(hashctx);
910 hashctx = NULL;
913 * expand key:
914 * Kn = HASH(K || H || K1 || K2 || ... || Kn-1)
915 * Key = K1 || K2 || ... || Kn
917 for (have = mdsz; need > have; have += mdsz) {
918 if ((hashctx = ssh_digest_start(kex->hash_alg)) == NULL ||
919 ssh_digest_update_buffer(hashctx, shared_secret) != 0 ||
920 ssh_digest_update(hashctx, hash, hashlen) != 0 ||
921 ssh_digest_update(hashctx, digest, have) != 0 ||
922 ssh_digest_final(hashctx, digest + have, mdsz) != 0) {
923 r = SSH_ERR_LIBCRYPTO_ERROR;
924 goto out;
926 ssh_digest_free(hashctx);
927 hashctx = NULL;
929 #ifdef DEBUG_KEX
930 fprintf(stderr, "key '%c'== ", c);
931 dump_digest("key", digest, need);
932 #endif
933 *keyp = digest;
934 digest = NULL;
935 r = 0;
936 out:
937 free(digest);
938 ssh_digest_free(hashctx);
939 return r;
942 #define NKEYS 6
944 kex_derive_keys(struct ssh *ssh, u_char *hash, u_int hashlen,
945 const struct sshbuf *shared_secret)
947 struct kex *kex = ssh->kex;
948 u_char *keys[NKEYS];
949 u_int i, j, mode, ctos;
950 int r;
952 for (i = 0; i < NKEYS; i++) {
953 if ((r = derive_key(ssh, 'A'+i, kex->we_need, hash, hashlen,
954 shared_secret, &keys[i])) != 0) {
955 for (j = 0; j < i; j++)
956 free(keys[j]);
957 return r;
960 for (mode = 0; mode < MODE_MAX; mode++) {
961 ctos = (!kex->server && mode == MODE_OUT) ||
962 (kex->server && mode == MODE_IN);
963 kex->newkeys[mode]->enc.iv = keys[ctos ? 0 : 1];
964 kex->newkeys[mode]->enc.key = keys[ctos ? 2 : 3];
965 kex->newkeys[mode]->mac.key = keys[ctos ? 4 : 5];
967 return 0;
970 #ifdef WITH_OPENSSL
972 kex_derive_keys_bn(struct ssh *ssh, u_char *hash, u_int hashlen,
973 const BIGNUM *secret)
975 struct sshbuf *shared_secret;
976 int r;
978 if ((shared_secret = sshbuf_new()) == NULL)
979 return SSH_ERR_ALLOC_FAIL;
980 if ((r = sshbuf_put_bignum2(shared_secret, secret)) == 0)
981 r = kex_derive_keys(ssh, hash, hashlen, shared_secret);
982 sshbuf_free(shared_secret);
983 return r;
985 #endif
988 #if defined(DEBUG_KEX) || defined(DEBUG_KEXDH) || defined(DEBUG_KEXECDH)
989 void
990 dump_digest(char *msg, u_char *digest, int len)
992 fprintf(stderr, "%s\n", msg);
993 sshbuf_dump_data(digest, len, stderr);
995 #endif