summaryrefslogtreecommitdiff
path: root/kex.c
diff options
context:
space:
mode:
authormarkus@openbsd.org <markus@openbsd.org>2015-01-19 20:16:15 +0000
committerDamien Miller <djm@mindrot.org>2015-01-20 09:19:39 +1100
commit57d10cbe861a235dd269c74fb2fe248469ecee9d (patch)
treec65deed24700490bd3b20300c4829d4d5466ff6d /kex.c
parent3fdc88a0def4f86aa88a5846ac079dc964c0546a (diff)
upstream commit
adapt kex to sshbuf and struct ssh; ok djm@
Diffstat (limited to 'kex.c')
-rw-r--r--kex.c575
1 files changed, 338 insertions, 237 deletions
diff --git a/kex.c b/kex.c
index 92ebaf732..9280dd3f4 100644
--- a/kex.c
+++ b/kex.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: kex.c,v 1.101 2015/01/19 20:07:45 markus Exp $ */ 1/* $OpenBSD: kex.c,v 1.102 2015/01/19 20:16:15 markus 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 *
@@ -37,20 +37,22 @@
37#include <openssl/crypto.h> 37#include <openssl/crypto.h>
38#endif 38#endif
39 39
40#include "xmalloc.h"
41#include "ssh2.h" 40#include "ssh2.h"
42#include "buffer.h"
43#include "packet.h" 41#include "packet.h"
44#include "compat.h" 42#include "compat.h"
45#include "cipher.h" 43#include "cipher.h"
46#include "key.h" 44#include "sshkey.h"
47#include "kex.h" 45#include "kex.h"
48#include "log.h" 46#include "log.h"
49#include "mac.h" 47#include "mac.h"
50#include "match.h" 48#include "match.h"
49#include "misc.h"
51#include "dispatch.h" 50#include "dispatch.h"
52#include "monitor.h" 51#include "monitor.h"
53#include "roaming.h" 52#include "roaming.h"
53
54#include "ssherr.h"
55#include "sshbuf.h"
54#include "digest.h" 56#include "digest.h"
55 57
56#if OPENSSL_VERSION_NUMBER >= 0x00907000L 58#if OPENSSL_VERSION_NUMBER >= 0x00907000L
@@ -62,12 +64,12 @@ extern const EVP_MD *evp_ssh_sha256(void);
62#endif 64#endif
63 65
64/* prototype */ 66/* prototype */
65static void kex_kexinit_finish(Kex *); 67static int kex_choose_conf(struct ssh *);
66static void kex_choose_conf(Kex *); 68static int kex_input_newkeys(int, u_int32_t, void *);
67 69
68struct kexalg { 70struct kexalg {
69 char *name; 71 char *name;
70 int type; 72 u_int type;
71 int ec_nid; 73 int ec_nid;
72 int hash_alg; 74 int hash_alg;
73}; 75};
@@ -99,7 +101,7 @@ static const struct kexalg kexalgs[] = {
99char * 101char *
100kex_alg_list(char sep) 102kex_alg_list(char sep)
101{ 103{
102 char *ret = NULL; 104 char *ret = NULL, *tmp;
103 size_t nlen, rlen = 0; 105 size_t nlen, rlen = 0;
104 const struct kexalg *k; 106 const struct kexalg *k;
105 107
@@ -107,7 +109,11 @@ kex_alg_list(char sep)
107 if (ret != NULL) 109 if (ret != NULL)
108 ret[rlen++] = sep; 110 ret[rlen++] = sep;
109 nlen = strlen(k->name); 111 nlen = strlen(k->name);
110 ret = xrealloc(ret, 1, rlen + nlen + 2); 112 if ((tmp = realloc(ret, rlen + nlen + 2)) == NULL) {
113 free(ret);
114 return NULL;
115 }
116 ret = tmp;
111 memcpy(ret + rlen, k->name, nlen + 1); 117 memcpy(ret + rlen, k->name, nlen + 1);
112 rlen += nlen; 118 rlen += nlen;
113 } 119 }
@@ -134,7 +140,8 @@ kex_names_valid(const char *names)
134 140
135 if (names == NULL || strcmp(names, "") == 0) 141 if (names == NULL || strcmp(names, "") == 0)
136 return 0; 142 return 0;
137 s = cp = xstrdup(names); 143 if ((s = cp = strdup(names)) == NULL)
144 return 0;
138 for ((p = strsep(&cp, ",")); p && *p != '\0'; 145 for ((p = strsep(&cp, ",")); p && *p != '\0';
139 (p = strsep(&cp, ","))) { 146 (p = strsep(&cp, ","))) {
140 if (kex_alg_by_name(p) == NULL) { 147 if (kex_alg_by_name(p) == NULL) {
@@ -149,56 +156,75 @@ kex_names_valid(const char *names)
149} 156}
150 157
151/* put algorithm proposal into buffer */ 158/* put algorithm proposal into buffer */
152static void 159int
153kex_prop2buf(Buffer *b, char *proposal[PROPOSAL_MAX]) 160kex_prop2buf(struct sshbuf *b, char *proposal[PROPOSAL_MAX])
154{ 161{
155 u_int i; 162 u_int i;
163 int r;
164
165 sshbuf_reset(b);
156 166
157 buffer_clear(b);
158 /* 167 /*
159 * add a dummy cookie, the cookie will be overwritten by 168 * add a dummy cookie, the cookie will be overwritten by
160 * kex_send_kexinit(), each time a kexinit is set 169 * kex_send_kexinit(), each time a kexinit is set
161 */ 170 */
162 for (i = 0; i < KEX_COOKIE_LEN; i++) 171 for (i = 0; i < KEX_COOKIE_LEN; i++) {
163 buffer_put_char(b, 0); 172 if ((r = sshbuf_put_u8(b, 0)) != 0)
164 for (i = 0; i < PROPOSAL_MAX; i++) 173 return r;
165 buffer_put_cstring(b, proposal[i]); 174 }
166 buffer_put_char(b, 0); /* first_kex_packet_follows */ 175 for (i = 0; i < PROPOSAL_MAX; i++) {
167 buffer_put_int(b, 0); /* uint32 reserved */ 176 if ((r = sshbuf_put_cstring(b, proposal[i])) != 0)
177 return r;
178 }
179 if ((r = sshbuf_put_u8(b, 0)) != 0 || /* first_kex_packet_follows */
180 (r = sshbuf_put_u32(b, 0)) != 0) /* uint32 reserved */
181 return r;
182 return 0;
168} 183}
169 184
170/* parse buffer and return algorithm proposal */ 185/* parse buffer and return algorithm proposal */
171static char ** 186int
172kex_buf2prop(Buffer *raw, int *first_kex_follows) 187kex_buf2prop(struct sshbuf *raw, int *first_kex_follows, char ***propp)
173{ 188{
174 Buffer b; 189 struct sshbuf *b = NULL;
190 u_char v;
175 u_int i; 191 u_int i;
176 char **proposal; 192 char **proposal = NULL;
177 193 int r;
178 proposal = xcalloc(PROPOSAL_MAX, sizeof(char *)); 194
179 195 *propp = NULL;
180 buffer_init(&b); 196 if ((proposal = calloc(PROPOSAL_MAX, sizeof(char *))) == NULL)
181 buffer_append(&b, buffer_ptr(raw), buffer_len(raw)); 197 return SSH_ERR_ALLOC_FAIL;
182 /* skip cookie */ 198 if ((b = sshbuf_fromb(raw)) == NULL) {
183 for (i = 0; i < KEX_COOKIE_LEN; i++) 199 r = SSH_ERR_ALLOC_FAIL;
184 buffer_get_char(&b); 200 goto out;
201 }
202 if ((r = sshbuf_consume(b, KEX_COOKIE_LEN)) != 0) /* skip cookie */
203 goto out;
185 /* extract kex init proposal strings */ 204 /* extract kex init proposal strings */
186 for (i = 0; i < PROPOSAL_MAX; i++) { 205 for (i = 0; i < PROPOSAL_MAX; i++) {
187 proposal[i] = buffer_get_cstring(&b,NULL); 206 if ((r = sshbuf_get_cstring(b, &(proposal[i]), NULL)) != 0)
207 goto out;
188 debug2("kex_parse_kexinit: %s", proposal[i]); 208 debug2("kex_parse_kexinit: %s", proposal[i]);
189 } 209 }
190 /* first kex follows / reserved */ 210 /* first kex follows / reserved */
191 i = buffer_get_char(&b); 211 if ((r = sshbuf_get_u8(b, &v)) != 0 ||
212 (r = sshbuf_get_u32(b, &i)) != 0)
213 goto out;
192 if (first_kex_follows != NULL) 214 if (first_kex_follows != NULL)
193 *first_kex_follows = i; 215 *first_kex_follows = i;
194 debug2("kex_parse_kexinit: first_kex_follows %d ", i); 216 debug2("kex_parse_kexinit: first_kex_follows %d ", v);
195 i = buffer_get_int(&b);
196 debug2("kex_parse_kexinit: reserved %u ", i); 217 debug2("kex_parse_kexinit: reserved %u ", i);
197 buffer_free(&b); 218 r = 0;
198 return proposal; 219 *propp = proposal;
220 out:
221 if (r != 0 && proposal != NULL)
222 kex_prop_free(proposal);
223 sshbuf_free(b);
224 return r;
199} 225}
200 226
201static void 227void
202kex_prop_free(char **proposal) 228kex_prop_free(char **proposal)
203{ 229{
204 u_int i; 230 u_int i;
@@ -217,91 +243,103 @@ kex_protocol_error(int type, u_int32_t seq, void *ctxt)
217} 243}
218 244
219static void 245static void
220kex_reset_dispatch(void) 246kex_reset_dispatch(struct ssh *ssh)
221{ 247{
222 dispatch_range(SSH2_MSG_TRANSPORT_MIN, 248 ssh_dispatch_range(ssh, SSH2_MSG_TRANSPORT_MIN,
223 SSH2_MSG_TRANSPORT_MAX, &kex_protocol_error); 249 SSH2_MSG_TRANSPORT_MAX, &kex_protocol_error);
224 dispatch_set(SSH2_MSG_KEXINIT, &kex_input_kexinit); 250 ssh_dispatch_set(ssh, SSH2_MSG_KEXINIT, &kex_input_kexinit);
225} 251}
226 252
227void 253int
228kex_finish(Kex *kex) 254kex_send_newkeys(struct ssh *ssh)
229{ 255{
230 kex_reset_dispatch(); 256 int r;
231 257
232 packet_start(SSH2_MSG_NEWKEYS); 258 kex_reset_dispatch(ssh);
233 packet_send(); 259 if ((r = sshpkt_start(ssh, SSH2_MSG_NEWKEYS)) != 0 ||
234 /* packet_write_wait(); */ 260 (r = sshpkt_send(ssh)) != 0)
261 return r;
235 debug("SSH2_MSG_NEWKEYS sent"); 262 debug("SSH2_MSG_NEWKEYS sent");
236
237 debug("expecting SSH2_MSG_NEWKEYS"); 263 debug("expecting SSH2_MSG_NEWKEYS");
238 packet_read_expect(SSH2_MSG_NEWKEYS); 264 ssh_dispatch_set(ssh, SSH2_MSG_NEWKEYS, &kex_input_newkeys);
239 packet_check_eom(); 265 return 0;
240 debug("SSH2_MSG_NEWKEYS received"); 266}
267
268static int
269kex_input_newkeys(int type, u_int32_t seq, void *ctxt)
270{
271 struct ssh *ssh = ctxt;
272 struct kex *kex = ssh->kex;
273 int r;
241 274
275 debug("SSH2_MSG_NEWKEYS received");
276 ssh_dispatch_set(ssh, SSH2_MSG_NEWKEYS, &kex_protocol_error);
277 if ((r = sshpkt_get_end(ssh)) != 0)
278 return r;
242 kex->done = 1; 279 kex->done = 1;
243 buffer_clear(kex->peer); 280 sshbuf_reset(kex->peer);
244 /* buffer_clear(kex->my); */ 281 /* sshbuf_reset(kex->my); */
245 kex->flags &= ~KEX_INIT_SENT; 282 kex->flags &= ~KEX_INIT_SENT;
246 free(kex->name); 283 free(kex->name);
247 kex->name = NULL; 284 kex->name = NULL;
285 return 0;
248} 286}
249 287
250void 288int
251kex_send_kexinit(Kex *kex) 289kex_send_kexinit(struct ssh *ssh)
252{ 290{
253 u_int32_t rnd = 0;
254 u_char *cookie; 291 u_char *cookie;
255 u_int i; 292 struct kex *kex = ssh->kex;
293 int r;
256 294
257 if (kex == NULL) { 295 if (kex == NULL)
258 error("kex_send_kexinit: no kex, cannot rekey"); 296 return SSH_ERR_INTERNAL_ERROR;
259 return; 297 if (kex->flags & KEX_INIT_SENT)
260 } 298 return 0;
261 if (kex->flags & KEX_INIT_SENT) {
262 debug("KEX_INIT_SENT");
263 return;
264 }
265 kex->done = 0; 299 kex->done = 0;
266 300
267 /* generate a random cookie */ 301 /* generate a random cookie */
268 if (buffer_len(kex->my) < KEX_COOKIE_LEN) 302 if (sshbuf_len(kex->my) < KEX_COOKIE_LEN)
269 fatal("kex_send_kexinit: kex proposal too short"); 303 return SSH_ERR_INVALID_FORMAT;
270 cookie = buffer_ptr(kex->my); 304 if ((cookie = sshbuf_mutable_ptr(kex->my)) == NULL)
271 for (i = 0; i < KEX_COOKIE_LEN; i++) { 305 return SSH_ERR_INTERNAL_ERROR;
272 if (i % 4 == 0) 306 arc4random_buf(cookie, KEX_COOKIE_LEN);
273 rnd = arc4random(); 307
274 cookie[i] = rnd; 308 if ((r = sshpkt_start(ssh, SSH2_MSG_KEXINIT)) != 0 ||
275 rnd >>= 8; 309 (r = sshpkt_putb(ssh, kex->my)) != 0 ||
276 } 310 (r = sshpkt_send(ssh)) != 0)
277 packet_start(SSH2_MSG_KEXINIT); 311 return r;
278 packet_put_raw(buffer_ptr(kex->my), buffer_len(kex->my));
279 packet_send();
280 debug("SSH2_MSG_KEXINIT sent"); 312 debug("SSH2_MSG_KEXINIT sent");
281 kex->flags |= KEX_INIT_SENT; 313 kex->flags |= KEX_INIT_SENT;
314 return 0;
282} 315}
283 316
284/* ARGSUSED */ 317/* ARGSUSED */
285int 318int
286kex_input_kexinit(int type, u_int32_t seq, void *ctxt) 319kex_input_kexinit(int type, u_int32_t seq, void *ctxt)
287{ 320{
288 const char *ptr; 321 struct ssh *ssh = ctxt;
322 struct kex *kex = ssh->kex;
323 const u_char *ptr;
289 u_int i; 324 u_int i;
290 size_t dlen; 325 size_t dlen;
291 Kex *kex = (Kex *)ctxt; 326 int r;
292 327
293 debug("SSH2_MSG_KEXINIT received"); 328 debug("SSH2_MSG_KEXINIT received");
294 if (kex == NULL) 329 if (kex == NULL)
295 fatal("kex_input_kexinit: no kex, cannot rekey"); 330 return SSH_ERR_INVALID_ARGUMENT;
296 331
297 ptr = packet_get_raw(&dlen); 332 ptr = sshpkt_ptr(ssh, &dlen);
298 buffer_append(kex->peer, ptr, dlen); 333 if ((r = sshbuf_put(kex->peer, ptr, dlen)) != 0)
334 return r;
299 335
300 /* discard packet */ 336 /* discard packet */
301 for (i = 0; i < KEX_COOKIE_LEN; i++) 337 for (i = 0; i < KEX_COOKIE_LEN; i++)
302 packet_get_char(); 338 if ((r = sshpkt_get_u8(ssh, NULL)) != 0)
339 return r;
303 for (i = 0; i < PROPOSAL_MAX; i++) 340 for (i = 0; i < PROPOSAL_MAX; i++)
304 free(packet_get_string(NULL)); 341 if ((r = sshpkt_get_string(ssh, NULL, NULL)) != 0)
342 return r;
305 /* 343 /*
306 * XXX RFC4253 sec 7: "each side MAY guess" - currently no supported 344 * XXX RFC4253 sec 7: "each side MAY guess" - currently no supported
307 * KEX method has the server move first, but a server might be using 345 * KEX method has the server move first, but a server might be using
@@ -312,12 +350,47 @@ kex_input_kexinit(int type, u_int32_t seq, void *ctxt)
312 * for cases where the server *doesn't* go first. I guess we should 350 * for cases where the server *doesn't* go first. I guess we should
313 * ignore it when it is set for these cases, which is what we do now. 351 * ignore it when it is set for these cases, which is what we do now.
314 */ 352 */
315 (void) packet_get_char(); /* first_kex_follows */ 353 if ((r = sshpkt_get_u8(ssh, NULL)) != 0 || /* first_kex_follows */
316 (void) packet_get_int(); /* reserved */ 354 (r = sshpkt_get_u32(ssh, NULL)) != 0 || /* reserved */
317 packet_check_eom(); 355 (r = sshpkt_get_end(ssh)) != 0)
356 return r;
318 357
319 kex_kexinit_finish(kex); 358 if (!(kex->flags & KEX_INIT_SENT))
320 return 0; 359 if ((r = kex_send_kexinit(ssh)) != 0)
360 return r;
361 if ((r = kex_choose_conf(ssh)) != 0)
362 return r;
363
364 if (kex->kex_type < KEX_MAX && kex->kex[kex->kex_type] != NULL)
365 return (kex->kex[kex->kex_type])(ssh);
366
367 return SSH_ERR_INTERNAL_ERROR;
368}
369
370int
371kex_new(struct ssh *ssh, char *proposal[PROPOSAL_MAX], struct kex **kexp)
372{
373 struct kex *kex;
374 int r;
375
376 *kexp = NULL;
377 if ((kex = calloc(1, sizeof(*kex))) == NULL)
378 return SSH_ERR_ALLOC_FAIL;
379 if ((kex->peer = sshbuf_new()) == NULL ||
380 (kex->my = sshbuf_new()) == NULL) {
381 r = SSH_ERR_ALLOC_FAIL;
382 goto out;
383 }
384 if ((r = kex_prop2buf(kex->my, proposal)) != 0)
385 goto out;
386 kex->done = 0;
387 kex_reset_dispatch(ssh);
388 r = 0;
389 *kexp = kex;
390 out:
391 if (r != 0)
392 kex_free(kex);
393 return r;
321} 394}
322 395
323void 396void
@@ -351,51 +424,53 @@ kex_free_newkeys(struct newkeys *newkeys)
351 free(newkeys); 424 free(newkeys);
352} 425}
353 426
354Kex * 427void
355kex_setup(char *proposal[PROPOSAL_MAX]) 428kex_free(struct kex *kex)
356{ 429{
357 struct kex *kex; 430 u_int mode;
358 431
359 if ((kex = calloc(1, sizeof(*kex))) == NULL) 432#ifdef WITH_OPENSSL
360 fatal("%s: calloc", __func__); 433 if (kex->dh)
361 if ((kex->peer = sshbuf_new()) == NULL || 434 DH_free(kex->dh);
362 (kex->my = sshbuf_new()) == NULL) { 435 if (kex->ec_client_key)
363 fatal("%s: sshbuf_new", __func__); 436 EC_KEY_free(kex->ec_client_key);
437#endif
438 for (mode = 0; mode < MODE_MAX; mode++) {
439 kex_free_newkeys(kex->newkeys[mode]);
440 kex->newkeys[mode] = NULL;
364 } 441 }
365 kex_prop2buf(kex->my, proposal); 442 sshbuf_free(kex->peer);
366 kex->done = 0; 443 sshbuf_free(kex->my);
367 444 free(kex->session_id);
368 kex_send_kexinit(kex); /* we start */ 445 free(kex->client_version_string);
369 kex_reset_dispatch(); 446 free(kex->server_version_string);
370 447 free(kex);
371 return kex;
372} 448}
373 449
374static void 450int
375kex_kexinit_finish(Kex *kex) 451kex_setup(struct ssh *ssh, char *proposal[PROPOSAL_MAX])
376{ 452{
377 if (!(kex->flags & KEX_INIT_SENT)) 453 int r;
378 kex_send_kexinit(kex); 454
379 455 if ((r = kex_new(ssh, proposal, &ssh->kex)) != 0)
380 kex_choose_conf(kex); 456 return r;
381 457 if ((r = kex_send_kexinit(ssh)) != 0) { /* we start */
382 if (kex->kex_type >= 0 && kex->kex_type < KEX_MAX && 458 kex_free(ssh->kex);
383 kex->kex[kex->kex_type] != NULL) { 459 ssh->kex = NULL;
384 (kex->kex[kex->kex_type])(kex); 460 return r;
385 } else {
386 fatal("Unsupported key exchange %d", kex->kex_type);
387 } 461 }
462 return 0;
388} 463}
389 464
390static void 465static int
391choose_enc(Enc *enc, char *client, char *server) 466choose_enc(struct sshenc *enc, char *client, char *server)
392{ 467{
393 char *name = match_list(client, server, NULL); 468 char *name = match_list(client, server, NULL);
469
394 if (name == NULL) 470 if (name == NULL)
395 fatal("no matching cipher found: client %s server %s", 471 return SSH_ERR_NO_CIPHER_ALG_MATCH;
396 client, server);
397 if ((enc->cipher = cipher_by_name(name)) == NULL) 472 if ((enc->cipher = cipher_by_name(name)) == NULL)
398 fatal("matching cipher is not supported: %s", name); 473 return SSH_ERR_INTERNAL_ERROR;
399 enc->name = name; 474 enc->name = name;
400 enc->enabled = 0; 475 enc->enabled = 0;
401 enc->iv = NULL; 476 enc->iv = NULL;
@@ -403,31 +478,34 @@ choose_enc(Enc *enc, char *client, char *server)
403 enc->key = NULL; 478 enc->key = NULL;
404 enc->key_len = cipher_keylen(enc->cipher); 479 enc->key_len = cipher_keylen(enc->cipher);
405 enc->block_size = cipher_blocksize(enc->cipher); 480 enc->block_size = cipher_blocksize(enc->cipher);
481 return 0;
406} 482}
407 483
408static void 484static int
409choose_mac(Mac *mac, char *client, char *server) 485choose_mac(struct ssh *ssh, struct sshmac *mac, char *client, char *server)
410{ 486{
411 char *name = match_list(client, server, NULL); 487 char *name = match_list(client, server, NULL);
488
412 if (name == NULL) 489 if (name == NULL)
413 fatal("no matching mac found: client %s server %s", 490 return SSH_ERR_NO_MAC_ALG_MATCH;
414 client, server);
415 if (mac_setup(mac, name) < 0) 491 if (mac_setup(mac, name) < 0)
416 fatal("unsupported mac %s", name); 492 return SSH_ERR_INTERNAL_ERROR;
417 /* truncate the key */ 493 /* truncate the key */
418 if (datafellows & SSH_BUG_HMAC) 494 if (ssh->compat & SSH_BUG_HMAC)
419 mac->key_len = 16; 495 mac->key_len = 16;
420 mac->name = name; 496 mac->name = name;
421 mac->key = NULL; 497 mac->key = NULL;
422 mac->enabled = 0; 498 mac->enabled = 0;
499 return 0;
423} 500}
424 501
425static void 502static int
426choose_comp(Comp *comp, char *client, char *server) 503choose_comp(struct sshcomp *comp, char *client, char *server)
427{ 504{
428 char *name = match_list(client, server, NULL); 505 char *name = match_list(client, server, NULL);
506
429 if (name == NULL) 507 if (name == NULL)
430 fatal("no matching comp found: client %s server %s", client, server); 508 return SSH_ERR_NO_COMPRESS_ALG_MATCH;
431 if (strcmp(name, "zlib@openssh.com") == 0) { 509 if (strcmp(name, "zlib@openssh.com") == 0) {
432 comp->type = COMP_DELAYED; 510 comp->type = COMP_DELAYED;
433 } else if (strcmp(name, "zlib") == 0) { 511 } else if (strcmp(name, "zlib") == 0) {
@@ -435,36 +513,41 @@ choose_comp(Comp *comp, char *client, char *server)
435 } else if (strcmp(name, "none") == 0) { 513 } else if (strcmp(name, "none") == 0) {
436 comp->type = COMP_NONE; 514 comp->type = COMP_NONE;
437 } else { 515 } else {
438 fatal("unsupported comp %s", name); 516 return SSH_ERR_INTERNAL_ERROR;
439 } 517 }
440 comp->name = name; 518 comp->name = name;
519 return 0;
441} 520}
442 521
443static void 522static int
444choose_kex(Kex *k, char *client, char *server) 523choose_kex(struct kex *k, char *client, char *server)
445{ 524{
446 const struct kexalg *kexalg; 525 const struct kexalg *kexalg;
447 526
448 k->name = match_list(client, server, NULL); 527 k->name = match_list(client, server, NULL);
528
449 if (k->name == NULL) 529 if (k->name == NULL)
450 fatal("Unable to negotiate a key exchange method"); 530 return SSH_ERR_NO_KEX_ALG_MATCH;
451 if ((kexalg = kex_alg_by_name(k->name)) == NULL) 531 if ((kexalg = kex_alg_by_name(k->name)) == NULL)
452 fatal("unsupported kex alg %s", k->name); 532 return SSH_ERR_INTERNAL_ERROR;
453 k->kex_type = kexalg->type; 533 k->kex_type = kexalg->type;
454 k->hash_alg = kexalg->hash_alg; 534 k->hash_alg = kexalg->hash_alg;
455 k->ec_nid = kexalg->ec_nid; 535 k->ec_nid = kexalg->ec_nid;
536 return 0;
456} 537}
457 538
458static void 539static int
459choose_hostkeyalg(Kex *k, char *client, char *server) 540choose_hostkeyalg(struct kex *k, char *client, char *server)
460{ 541{
461 char *hostkeyalg = match_list(client, server, NULL); 542 char *hostkeyalg = match_list(client, server, NULL);
543
462 if (hostkeyalg == NULL) 544 if (hostkeyalg == NULL)
463 fatal("no hostkey alg"); 545 return SSH_ERR_NO_HOSTKEY_ALG_MATCH;
464 k->hostkey_type = key_type_from_name(hostkeyalg); 546 k->hostkey_type = sshkey_type_from_name(hostkeyalg);
465 if (k->hostkey_type == KEY_UNSPEC) 547 if (k->hostkey_type == KEY_UNSPEC)
466 fatal("bad hostkey alg '%s'", hostkeyalg); 548 return SSH_ERR_INTERNAL_ERROR;
467 free(hostkeyalg); 549 free(hostkeyalg);
550 return 0;
468} 551}
469 552
470static int 553static int
@@ -491,18 +574,20 @@ proposals_match(char *my[PROPOSAL_MAX], char *peer[PROPOSAL_MAX])
491 return (1); 574 return (1);
492} 575}
493 576
494static void 577static int
495kex_choose_conf(Kex *kex) 578kex_choose_conf(struct ssh *ssh)
496{ 579{
497 Newkeys *newkeys; 580 struct kex *kex = ssh->kex;
498 char **my, **peer; 581 struct newkeys *newkeys;
582 char **my = NULL, **peer = NULL;
499 char **cprop, **sprop; 583 char **cprop, **sprop;
500 int nenc, nmac, ncomp; 584 int nenc, nmac, ncomp;
501 u_int mode, ctos, need, dh_need, authlen; 585 u_int mode, ctos, need, dh_need, authlen;
502 int first_kex_follows, type; 586 int r, first_kex_follows;
503 587
504 my = kex_buf2prop(kex->my, NULL); 588 if ((r = kex_buf2prop(kex->my, NULL, &my)) != 0 ||
505 peer = kex_buf2prop(kex->peer, &first_kex_follows); 589 (r = kex_buf2prop(kex->peer, &first_kex_follows, &peer)) != 0)
590 goto out;
506 591
507 if (kex->server) { 592 if (kex->server) {
508 cprop=peer; 593 cprop=peer;
@@ -514,8 +599,9 @@ kex_choose_conf(Kex *kex)
514 599
515 /* Check whether server offers roaming */ 600 /* Check whether server offers roaming */
516 if (!kex->server) { 601 if (!kex->server) {
517 char *roaming; 602 char *roaming = match_list(KEX_RESUME,
518 roaming = match_list(KEX_RESUME, peer[PROPOSAL_KEX_ALGS], NULL); 603 peer[PROPOSAL_KEX_ALGS], NULL);
604
519 if (roaming) { 605 if (roaming) {
520 kex->roaming = 1; 606 kex->roaming = 1;
521 free(roaming); 607 free(roaming);
@@ -524,28 +610,39 @@ kex_choose_conf(Kex *kex)
524 610
525 /* Algorithm Negotiation */ 611 /* Algorithm Negotiation */
526 for (mode = 0; mode < MODE_MAX; mode++) { 612 for (mode = 0; mode < MODE_MAX; mode++) {
527 newkeys = xcalloc(1, sizeof(*newkeys)); 613 if ((newkeys = calloc(1, sizeof(*newkeys))) == NULL) {
614 r = SSH_ERR_ALLOC_FAIL;
615 goto out;
616 }
528 kex->newkeys[mode] = newkeys; 617 kex->newkeys[mode] = newkeys;
529 ctos = (!kex->server && mode == MODE_OUT) || 618 ctos = (!kex->server && mode == MODE_OUT) ||
530 (kex->server && mode == MODE_IN); 619 (kex->server && mode == MODE_IN);
531 nenc = ctos ? PROPOSAL_ENC_ALGS_CTOS : PROPOSAL_ENC_ALGS_STOC; 620 nenc = ctos ? PROPOSAL_ENC_ALGS_CTOS : PROPOSAL_ENC_ALGS_STOC;
532 nmac = ctos ? PROPOSAL_MAC_ALGS_CTOS : PROPOSAL_MAC_ALGS_STOC; 621 nmac = ctos ? PROPOSAL_MAC_ALGS_CTOS : PROPOSAL_MAC_ALGS_STOC;
533 ncomp = ctos ? PROPOSAL_COMP_ALGS_CTOS : PROPOSAL_COMP_ALGS_STOC; 622 ncomp = ctos ? PROPOSAL_COMP_ALGS_CTOS : PROPOSAL_COMP_ALGS_STOC;
534 choose_enc(&newkeys->enc, cprop[nenc], sprop[nenc]); 623 if ((r = choose_enc(&newkeys->enc, cprop[nenc],
535 /* ignore mac for authenticated encryption */ 624 sprop[nenc])) != 0)
625 goto out;
536 authlen = cipher_authlen(newkeys->enc.cipher); 626 authlen = cipher_authlen(newkeys->enc.cipher);
537 if (authlen == 0) 627 /* ignore mac for authenticated encryption */
538 choose_mac(&newkeys->mac, cprop[nmac], sprop[nmac]); 628 if (authlen == 0 &&
539 choose_comp(&newkeys->comp, cprop[ncomp], sprop[ncomp]); 629 (r = choose_mac(ssh, &newkeys->mac, cprop[nmac],
630 sprop[nmac])) != 0)
631 goto out;
632 if ((r = choose_comp(&newkeys->comp, cprop[ncomp],
633 sprop[ncomp])) != 0)
634 goto out;
540 debug("kex: %s %s %s %s", 635 debug("kex: %s %s %s %s",
541 ctos ? "client->server" : "server->client", 636 ctos ? "client->server" : "server->client",
542 newkeys->enc.name, 637 newkeys->enc.name,
543 authlen == 0 ? newkeys->mac.name : "<implicit>", 638 authlen == 0 ? newkeys->mac.name : "<implicit>",
544 newkeys->comp.name); 639 newkeys->comp.name);
545 } 640 }
546 choose_kex(kex, cprop[PROPOSAL_KEX_ALGS], sprop[PROPOSAL_KEX_ALGS]); 641 if ((r = choose_kex(kex, cprop[PROPOSAL_KEX_ALGS],
547 choose_hostkeyalg(kex, cprop[PROPOSAL_SERVER_HOST_KEY_ALGS], 642 sprop[PROPOSAL_KEX_ALGS])) != 0 ||
548 sprop[PROPOSAL_SERVER_HOST_KEY_ALGS]); 643 (r = choose_hostkeyalg(kex, cprop[PROPOSAL_SERVER_HOST_KEY_ALGS],
644 sprop[PROPOSAL_SERVER_HOST_KEY_ALGS])) != 0)
645 goto out;
549 need = dh_need = 0; 646 need = dh_need = 0;
550 for (mode = 0; mode < MODE_MAX; mode++) { 647 for (mode = 0; mode < MODE_MAX; mode++) {
551 newkeys = kex->newkeys[mode]; 648 newkeys = kex->newkeys[mode];
@@ -564,45 +661,47 @@ kex_choose_conf(Kex *kex)
564 661
565 /* ignore the next message if the proposals do not match */ 662 /* ignore the next message if the proposals do not match */
566 if (first_kex_follows && !proposals_match(my, peer) && 663 if (first_kex_follows && !proposals_match(my, peer) &&
567 !(datafellows & SSH_BUG_FIRSTKEX)) { 664 !(ssh->compat & SSH_BUG_FIRSTKEX))
568 type = packet_read(); 665 ssh->dispatch_skip_packets = 1;
569 debug2("skipping next packet (type %u)", type); 666 r = 0;
570 } 667 out:
571
572 kex_prop_free(my); 668 kex_prop_free(my);
573 kex_prop_free(peer); 669 kex_prop_free(peer);
670 return r;
574} 671}
575 672
576static u_char * 673static int
577derive_key(Kex *kex, int id, u_int need, u_char *hash, u_int hashlen, 674derive_key(struct ssh *ssh, int id, u_int need, u_char *hash, u_int hashlen,
578 const u_char *shared_secret, u_int slen) 675 const struct sshbuf *shared_secret, u_char **keyp)
579{ 676{
580 Buffer b; 677 struct kex *kex = ssh->kex;
581 struct ssh_digest_ctx *hashctx; 678 struct ssh_digest_ctx *hashctx = NULL;
582 char c = id; 679 char c = id;
583 u_int have; 680 u_int have;
584 size_t mdsz; 681 size_t mdsz;
585 u_char *digest; 682 u_char *digest;
683 int r;
586 684
587 if ((mdsz = ssh_digest_bytes(kex->hash_alg)) == 0) 685 if ((mdsz = ssh_digest_bytes(kex->hash_alg)) == 0)
588 fatal("bad kex md size %zu", mdsz); 686 return SSH_ERR_INVALID_ARGUMENT;
589 digest = xmalloc(roundup(need, mdsz)); 687 if ((digest = calloc(1, roundup(need, mdsz))) == NULL) {
590 688 r = SSH_ERR_ALLOC_FAIL;
591 buffer_init(&b); 689 goto out;
592 buffer_append(&b, shared_secret, slen); 690 }
593 691
594 /* K1 = HASH(K || H || "A" || session_id) */ 692 /* K1 = HASH(K || H || "A" || session_id) */
595 if ((hashctx = ssh_digest_start(kex->hash_alg)) == NULL) 693 if ((hashctx = ssh_digest_start(kex->hash_alg)) == NULL ||
596 fatal("%s: ssh_digest_start failed", __func__); 694 ssh_digest_update_buffer(hashctx, shared_secret) != 0 ||
597 if (ssh_digest_update_buffer(hashctx, &b) != 0 ||
598 ssh_digest_update(hashctx, hash, hashlen) != 0 || 695 ssh_digest_update(hashctx, hash, hashlen) != 0 ||
599 ssh_digest_update(hashctx, &c, 1) != 0 || 696 ssh_digest_update(hashctx, &c, 1) != 0 ||
600 ssh_digest_update(hashctx, kex->session_id, 697 ssh_digest_update(hashctx, kex->session_id,
601 kex->session_id_len) != 0) 698 kex->session_id_len) != 0 ||
602 fatal("%s: ssh_digest_update failed", __func__); 699 ssh_digest_final(hashctx, digest, mdsz) != 0) {
603 if (ssh_digest_final(hashctx, digest, mdsz) != 0) 700 r = SSH_ERR_LIBCRYPTO_ERROR;
604 fatal("%s: ssh_digest_final failed", __func__); 701 goto out;
702 }
605 ssh_digest_free(hashctx); 703 ssh_digest_free(hashctx);
704 hashctx = NULL;
606 705
607 /* 706 /*
608 * expand key: 707 * expand key:
@@ -610,38 +709,49 @@ derive_key(Kex *kex, int id, u_int need, u_char *hash, u_int hashlen,
610 * Key = K1 || K2 || ... || Kn 709 * Key = K1 || K2 || ... || Kn
611 */ 710 */
612 for (have = mdsz; need > have; have += mdsz) { 711 for (have = mdsz; need > have; have += mdsz) {
613 if ((hashctx = ssh_digest_start(kex->hash_alg)) == NULL) 712 if ((hashctx = ssh_digest_start(kex->hash_alg)) == NULL ||
614 fatal("%s: ssh_digest_start failed", __func__); 713 ssh_digest_update_buffer(hashctx, shared_secret) != 0 ||
615 if (ssh_digest_update_buffer(hashctx, &b) != 0 ||
616 ssh_digest_update(hashctx, hash, hashlen) != 0 || 714 ssh_digest_update(hashctx, hash, hashlen) != 0 ||
617 ssh_digest_update(hashctx, digest, have) != 0) 715 ssh_digest_update(hashctx, digest, have) != 0 ||
618 fatal("%s: ssh_digest_update failed", __func__); 716 ssh_digest_final(hashctx, digest + have, mdsz) != 0) {
619 if (ssh_digest_final(hashctx, digest + have, mdsz) != 0) 717 r = SSH_ERR_LIBCRYPTO_ERROR;
620 fatal("%s: ssh_digest_final failed", __func__); 718 goto out;
719 }
621 ssh_digest_free(hashctx); 720 ssh_digest_free(hashctx);
721 hashctx = NULL;
622 } 722 }
623 buffer_free(&b);
624#ifdef DEBUG_KEX 723#ifdef DEBUG_KEX
625 fprintf(stderr, "key '%c'== ", c); 724 fprintf(stderr, "key '%c'== ", c);
626 dump_digest("key", digest, need); 725 dump_digest("key", digest, need);
627#endif 726#endif
628 return digest; 727 *keyp = digest;
728 digest = NULL;
729 r = 0;
730 out:
731 if (digest)
732 free(digest);
733 ssh_digest_free(hashctx);
734 return r;
629} 735}
630 736
631#define NKEYS 6 737#define NKEYS 6
632void 738int
633kex_derive_keys(Kex *kex, u_char *hash, u_int hashlen, 739kex_derive_keys(struct ssh *ssh, u_char *hash, u_int hashlen,
634 const u_char *shared_secret, u_int slen) 740 const struct sshbuf *shared_secret)
635{ 741{
742 struct kex *kex = ssh->kex;
636 u_char *keys[NKEYS]; 743 u_char *keys[NKEYS];
637 u_int i, mode, ctos; 744 u_int i, j, mode, ctos;
745 int r;
638 746
639 for (i = 0; i < NKEYS; i++) { 747 for (i = 0; i < NKEYS; i++) {
640 keys[i] = derive_key(kex, 'A'+i, kex->we_need, hash, hashlen, 748 if ((r = derive_key(ssh, 'A'+i, kex->we_need, hash, hashlen,
641 shared_secret, slen); 749 shared_secret, &keys[i])) != 0) {
750 for (j = 0; j < i; j++)
751 free(keys[j]);
752 return r;
753 }
642 } 754 }
643
644 debug2("kex_derive_keys");
645 for (mode = 0; mode < MODE_MAX; mode++) { 755 for (mode = 0; mode < MODE_MAX; mode++) {
646 ctos = (!kex->server && mode == MODE_OUT) || 756 ctos = (!kex->server && mode == MODE_OUT) ||
647 (kex->server && mode == MODE_IN); 757 (kex->server && mode == MODE_IN);
@@ -649,54 +759,54 @@ kex_derive_keys(Kex *kex, u_char *hash, u_int hashlen,
649 kex->newkeys[mode]->enc.key = keys[ctos ? 2 : 3]; 759 kex->newkeys[mode]->enc.key = keys[ctos ? 2 : 3];
650 kex->newkeys[mode]->mac.key = keys[ctos ? 4 : 5]; 760 kex->newkeys[mode]->mac.key = keys[ctos ? 4 : 5];
651 } 761 }
762 return 0;
652} 763}
653 764
654#ifdef WITH_OPENSSL 765#ifdef WITH_OPENSSL
655void 766int
656kex_derive_keys_bn(Kex *kex, u_char *hash, u_int hashlen, const BIGNUM *secret) 767kex_derive_keys_bn(struct ssh *ssh, u_char *hash, u_int hashlen,
768 const BIGNUM *secret)
657{ 769{
658 Buffer shared_secret; 770 struct sshbuf *shared_secret;
659 771 int r;
660 buffer_init(&shared_secret); 772
661 buffer_put_bignum2(&shared_secret, secret); 773 if ((shared_secret = sshbuf_new()) == NULL)
662 kex_derive_keys(kex, hash, hashlen, 774 return SSH_ERR_ALLOC_FAIL;
663 buffer_ptr(&shared_secret), buffer_len(&shared_secret)); 775 if ((r = sshbuf_put_bignum2(shared_secret, secret)) == 0)
664 buffer_free(&shared_secret); 776 r = kex_derive_keys(ssh, hash, hashlen, shared_secret);
777 sshbuf_free(shared_secret);
778 return r;
665} 779}
666#endif 780#endif
667 781
668#ifdef WITH_SSH1 782#ifdef WITH_SSH1
669void 783int
670derive_ssh1_session_id(BIGNUM *host_modulus, BIGNUM *server_modulus, 784derive_ssh1_session_id(BIGNUM *host_modulus, BIGNUM *server_modulus,
671 u_int8_t cookie[8], u_int8_t id[16]) 785 u_int8_t cookie[8], u_int8_t id[16])
672{ 786{
673 u_int8_t nbuf[2048], obuf[SSH_DIGEST_MAX_LENGTH]; 787 u_int8_t nbuf[2048], obuf[SSH_DIGEST_MAX_LENGTH];
674 int len; 788 struct ssh_digest_ctx *hashctx = NULL;
675 struct ssh_digest_ctx *hashctx; 789 size_t len;
676 790 int r;
677 if ((hashctx = ssh_digest_start(SSH_DIGEST_MD5)) == NULL)
678 fatal("%s: ssh_digest_start", __func__);
679 791
680 len = BN_num_bytes(host_modulus); 792 len = BN_num_bytes(host_modulus);
681 if (len < (512 / 8) || (u_int)len > sizeof(nbuf)) 793 if (len < (512 / 8) || (u_int)len > sizeof(nbuf))
682 fatal("%s: bad host modulus (len %d)", __func__, len); 794 return SSH_ERR_KEY_BITS_MISMATCH;
683 BN_bn2bin(host_modulus, nbuf); 795 if (BN_bn2bin(host_modulus, nbuf) <= 0 ||
684 if (ssh_digest_update(hashctx, nbuf, len) != 0) 796 (hashctx = ssh_digest_start(SSH_DIGEST_MD5)) == NULL ||
685 fatal("%s: ssh_digest_update failed", __func__); 797 ssh_digest_update(hashctx, nbuf, len) != 0 ||
686 798 ssh_digest_update(hashctx, cookie, 8) != 0 ||
687 len = BN_num_bytes(server_modulus); 799 ssh_digest_final(hashctx, obuf, sizeof(obuf)) != 0) {
688 if (len < (512 / 8) || (u_int)len > sizeof(nbuf)) 800 r = SSH_ERR_LIBCRYPTO_ERROR;
689 fatal("%s: bad server modulus (len %d)", __func__, len); 801 goto out;
690 BN_bn2bin(server_modulus, nbuf); 802 }
691 if (ssh_digest_update(hashctx, nbuf, len) != 0 ||
692 ssh_digest_update(hashctx, cookie, 8) != 0)
693 fatal("%s: ssh_digest_update failed", __func__);
694 if (ssh_digest_final(hashctx, obuf, sizeof(obuf)) != 0)
695 fatal("%s: ssh_digest_final failed", __func__);
696 memcpy(id, obuf, ssh_digest_bytes(SSH_DIGEST_MD5)); 803 memcpy(id, obuf, ssh_digest_bytes(SSH_DIGEST_MD5));
697 804 r = 0;
805 out:
806 ssh_digest_free(hashctx);
698 explicit_bzero(nbuf, sizeof(nbuf)); 807 explicit_bzero(nbuf, sizeof(nbuf));
699 explicit_bzero(obuf, sizeof(obuf)); 808 explicit_bzero(obuf, sizeof(obuf));
809 return r;
700} 810}
701#endif 811#endif
702 812
@@ -704,16 +814,7 @@ derive_ssh1_session_id(BIGNUM *host_modulus, BIGNUM *server_modulus,
704void 814void
705dump_digest(char *msg, u_char *digest, int len) 815dump_digest(char *msg, u_char *digest, int len)
706{ 816{
707 int i;
708
709 fprintf(stderr, "%s\n", msg); 817 fprintf(stderr, "%s\n", msg);
710 for (i = 0; i < len; i++) { 818 sshbuf_dump_data(digest, len, stderr);
711 fprintf(stderr, "%02x", digest[i]);
712 if (i%32 == 31)
713 fprintf(stderr, "\n");
714 else if (i%8 == 7)
715 fprintf(stderr, " ");
716 }
717 fprintf(stderr, "\n");
718} 819}
719#endif 820#endif