1 /*
2 * Client side of key exchange for the SSH-2 transport protocol (RFC 4253).
3 */
4
5 #include <assert.h>
6
7 #include "putty.h"
8 #include "ssh.h"
9 #include "sshbpp.h"
10 #include "sshppl.h"
11 #include "sshcr.h"
12 #include "storage.h"
13 #include "ssh2transport.h"
14 #include "mpint.h"
15
16 /*
17 * Another copy of the symbol defined in mpunsafe.c. See the comment
18 * there.
19 */
20 const int deliberate_symbol_clash = 12345;
21
ssh2kex_coroutine(struct ssh2_transport_state * s,bool * aborted)22 void ssh2kex_coroutine(struct ssh2_transport_state *s, bool *aborted)
23 {
24 PacketProtocolLayer *ppl = &s->ppl; /* for ppl_logevent */
25 PktIn *pktin;
26 PktOut *pktout;
27
28 crBegin(s->crStateKex);
29
30 if (s->kex_alg->main_type == KEXTYPE_DH) {
31 /*
32 * Work out the number of bits of key we will need from the
33 * key exchange. We start with the maximum key length of
34 * either cipher...
35 */
36 {
37 int csbits, scbits;
38
39 csbits = s->out.cipher ? s->out.cipher->real_keybits : 0;
40 scbits = s->in.cipher ? s->in.cipher->real_keybits : 0;
41 s->nbits = (csbits > scbits ? csbits : scbits);
42 }
43 /* The keys only have hlen-bit entropy, since they're based on
44 * a hash. So cap the key size at hlen bits. */
45 if (s->nbits > s->kex_alg->hash->hlen * 8)
46 s->nbits = s->kex_alg->hash->hlen * 8;
47
48 /*
49 * If we're doing Diffie-Hellman group exchange, start by
50 * requesting a group.
51 */
52 if (dh_is_gex(s->kex_alg)) {
53 ppl_logevent("Doing Diffie-Hellman group exchange");
54 s->ppl.bpp->pls->kctx = SSH2_PKTCTX_DHGEX;
55 /*
56 * Work out how big a DH group we will need to allow that
57 * much data.
58 */
59 s->pbits = 512 << ((s->nbits - 1) / 64);
60 if (s->pbits < DH_MIN_SIZE)
61 s->pbits = DH_MIN_SIZE;
62 if (s->pbits > DH_MAX_SIZE)
63 s->pbits = DH_MAX_SIZE;
64 if ((s->ppl.remote_bugs & BUG_SSH2_OLDGEX)) {
65 pktout = ssh_bpp_new_pktout(
66 s->ppl.bpp, SSH2_MSG_KEX_DH_GEX_REQUEST_OLD);
67 put_uint32(pktout, s->pbits);
68 } else {
69 pktout = ssh_bpp_new_pktout(
70 s->ppl.bpp, SSH2_MSG_KEX_DH_GEX_REQUEST);
71 put_uint32(pktout, DH_MIN_SIZE);
72 put_uint32(pktout, s->pbits);
73 put_uint32(pktout, DH_MAX_SIZE);
74 }
75 pq_push(s->ppl.out_pq, pktout);
76
77 crMaybeWaitUntilV((pktin = ssh2_transport_pop(s)) != NULL);
78 if (pktin->type != SSH2_MSG_KEX_DH_GEX_GROUP) {
79 ssh_proto_error(s->ppl.ssh, "Received unexpected packet when "
80 "expecting Diffie-Hellman group, type %d (%s)",
81 pktin->type,
82 ssh2_pkt_type(s->ppl.bpp->pls->kctx,
83 s->ppl.bpp->pls->actx,
84 pktin->type));
85 *aborted = true;
86 return;
87 }
88 s->p = get_mp_ssh2(pktin);
89 s->g = get_mp_ssh2(pktin);
90 if (get_err(pktin)) {
91 ssh_proto_error(s->ppl.ssh,
92 "Unable to parse Diffie-Hellman group packet");
93 *aborted = true;
94 return;
95 }
96 s->dh_ctx = dh_setup_gex(s->p, s->g);
97 s->kex_init_value = SSH2_MSG_KEX_DH_GEX_INIT;
98 s->kex_reply_value = SSH2_MSG_KEX_DH_GEX_REPLY;
99
100 ppl_logevent("Doing Diffie-Hellman key exchange using %d-bit "
101 "modulus and hash %s with a server-supplied group",
102 dh_modulus_bit_size(s->dh_ctx),
103 ssh_hash_alg(s->exhash)->text_name);
104 } else {
105 s->ppl.bpp->pls->kctx = SSH2_PKTCTX_DHGROUP;
106 s->dh_ctx = dh_setup_group(s->kex_alg);
107 s->kex_init_value = SSH2_MSG_KEXDH_INIT;
108 s->kex_reply_value = SSH2_MSG_KEXDH_REPLY;
109
110 ppl_logevent("Doing Diffie-Hellman key exchange using %d-bit "
111 "modulus and hash %s with standard group \"%s\"",
112 dh_modulus_bit_size(s->dh_ctx),
113 ssh_hash_alg(s->exhash)->text_name,
114 s->kex_alg->groupname);
115 }
116
117 /*
118 * Now generate and send e for Diffie-Hellman.
119 */
120 seat_set_busy_status(s->ppl.seat, BUSY_CPU);
121 s->e = dh_create_e(s->dh_ctx, s->nbits * 2);
122 pktout = ssh_bpp_new_pktout(s->ppl.bpp, s->kex_init_value);
123 put_mp_ssh2(pktout, s->e);
124 pq_push(s->ppl.out_pq, pktout);
125
126 seat_set_busy_status(s->ppl.seat, BUSY_WAITING);
127 crMaybeWaitUntilV((pktin = ssh2_transport_pop(s)) != NULL);
128 if (pktin->type != s->kex_reply_value) {
129 ssh_proto_error(s->ppl.ssh, "Received unexpected packet when "
130 "expecting Diffie-Hellman reply, type %d (%s)",
131 pktin->type,
132 ssh2_pkt_type(s->ppl.bpp->pls->kctx,
133 s->ppl.bpp->pls->actx,
134 pktin->type));
135 *aborted = true;
136 return;
137 }
138 seat_set_busy_status(s->ppl.seat, BUSY_CPU);
139 s->hostkeydata = get_string(pktin);
140 s->hkey = ssh_key_new_pub(s->hostkey_alg, s->hostkeydata);
141 s->f = get_mp_ssh2(pktin);
142 s->sigdata = get_string(pktin);
143 if (get_err(pktin)) {
144 ssh_proto_error(s->ppl.ssh,
145 "Unable to parse Diffie-Hellman reply packet");
146 *aborted = true;
147 return;
148 }
149
150 {
151 const char *err = dh_validate_f(s->dh_ctx, s->f);
152 if (err) {
153 ssh_proto_error(s->ppl.ssh, "Diffie-Hellman reply failed "
154 "validation: %s", err);
155 *aborted = true;
156 return;
157 }
158 }
159 s->K = dh_find_K(s->dh_ctx, s->f);
160
161 /* We assume everything from now on will be quick, and it might
162 * involve user interaction. */
163 seat_set_busy_status(s->ppl.seat, BUSY_NOT);
164
165 put_stringpl(s->exhash, s->hostkeydata);
166 if (dh_is_gex(s->kex_alg)) {
167 if (!(s->ppl.remote_bugs & BUG_SSH2_OLDGEX))
168 put_uint32(s->exhash, DH_MIN_SIZE);
169 put_uint32(s->exhash, s->pbits);
170 if (!(s->ppl.remote_bugs & BUG_SSH2_OLDGEX))
171 put_uint32(s->exhash, DH_MAX_SIZE);
172 put_mp_ssh2(s->exhash, s->p);
173 put_mp_ssh2(s->exhash, s->g);
174 }
175 put_mp_ssh2(s->exhash, s->e);
176 put_mp_ssh2(s->exhash, s->f);
177
178 dh_cleanup(s->dh_ctx);
179 s->dh_ctx = NULL;
180 mp_free(s->f); s->f = NULL;
181 if (dh_is_gex(s->kex_alg)) {
182 mp_free(s->g); s->g = NULL;
183 mp_free(s->p); s->p = NULL;
184 }
185 } else if (s->kex_alg->main_type == KEXTYPE_ECDH) {
186
187 ppl_logevent("Doing ECDH key exchange with curve %s and hash %s",
188 ssh_ecdhkex_curve_textname(s->kex_alg),
189 ssh_hash_alg(s->exhash)->text_name);
190 s->ppl.bpp->pls->kctx = SSH2_PKTCTX_ECDHKEX;
191
192 s->ecdh_key = ssh_ecdhkex_newkey(s->kex_alg);
193 if (!s->ecdh_key) {
194 ssh_sw_abort(s->ppl.ssh, "Unable to generate key for ECDH");
195 *aborted = true;
196 return;
197 }
198
199 pktout = ssh_bpp_new_pktout(s->ppl.bpp, SSH2_MSG_KEX_ECDH_INIT);
200 {
201 strbuf *pubpoint = strbuf_new();
202 ssh_ecdhkex_getpublic(s->ecdh_key, BinarySink_UPCAST(pubpoint));
203 put_stringsb(pktout, pubpoint);
204 }
205
206 pq_push(s->ppl.out_pq, pktout);
207
208 crMaybeWaitUntilV((pktin = ssh2_transport_pop(s)) != NULL);
209 if (pktin->type != SSH2_MSG_KEX_ECDH_REPLY) {
210 ssh_proto_error(s->ppl.ssh, "Received unexpected packet when "
211 "expecting ECDH reply, type %d (%s)", pktin->type,
212 ssh2_pkt_type(s->ppl.bpp->pls->kctx,
213 s->ppl.bpp->pls->actx,
214 pktin->type));
215 *aborted = true;
216 return;
217 }
218
219 s->hostkeydata = get_string(pktin);
220 put_stringpl(s->exhash, s->hostkeydata);
221 s->hkey = ssh_key_new_pub(s->hostkey_alg, s->hostkeydata);
222
223 {
224 strbuf *pubpoint = strbuf_new();
225 ssh_ecdhkex_getpublic(s->ecdh_key, BinarySink_UPCAST(pubpoint));
226 put_string(s->exhash, pubpoint->u, pubpoint->len);
227 strbuf_free(pubpoint);
228 }
229
230 {
231 ptrlen keydata = get_string(pktin);
232 put_stringpl(s->exhash, keydata);
233 s->K = ssh_ecdhkex_getkey(s->ecdh_key, keydata);
234 if (!get_err(pktin) && !s->K) {
235 ssh_proto_error(s->ppl.ssh, "Received invalid elliptic curve "
236 "point in ECDH reply");
237 *aborted = true;
238 return;
239 }
240 }
241
242 s->sigdata = get_string(pktin);
243 if (get_err(pktin)) {
244 ssh_proto_error(s->ppl.ssh, "Unable to parse ECDH reply packet");
245 *aborted = true;
246 return;
247 }
248
249 ssh_ecdhkex_freekey(s->ecdh_key);
250 s->ecdh_key = NULL;
251 #ifndef NO_GSSAPI
252 } else if (s->kex_alg->main_type == KEXTYPE_GSS) {
253 ptrlen data;
254
255 s->ppl.bpp->pls->kctx = SSH2_PKTCTX_GSSKEX;
256 s->init_token_sent = false;
257 s->complete_rcvd = false;
258 s->hkey = NULL;
259 s->keystr = NULL;
260
261 /*
262 * Work out the number of bits of key we will need from the
263 * key exchange. We start with the maximum key length of
264 * either cipher...
265 *
266 * This is rote from the KEXTYPE_DH section above.
267 */
268 {
269 int csbits, scbits;
270
271 csbits = s->out.cipher->real_keybits;
272 scbits = s->in.cipher->real_keybits;
273 s->nbits = (csbits > scbits ? csbits : scbits);
274 }
275 /* The keys only have hlen-bit entropy, since they're based on
276 * a hash. So cap the key size at hlen bits. */
277 if (s->nbits > s->kex_alg->hash->hlen * 8)
278 s->nbits = s->kex_alg->hash->hlen * 8;
279
280 if (dh_is_gex(s->kex_alg)) {
281 /*
282 * Work out how big a DH group we will need to allow that
283 * much data.
284 */
285 s->pbits = 512 << ((s->nbits - 1) / 64);
286 ppl_logevent("Doing GSSAPI (with Kerberos V5) Diffie-Hellman "
287 "group exchange, with minimum %d bits", s->pbits);
288 pktout = ssh_bpp_new_pktout(s->ppl.bpp, SSH2_MSG_KEXGSS_GROUPREQ);
289 put_uint32(pktout, s->pbits); /* min */
290 put_uint32(pktout, s->pbits); /* preferred */
291 put_uint32(pktout, s->pbits * 2); /* max */
292 pq_push(s->ppl.out_pq, pktout);
293
294 crMaybeWaitUntilV(
295 (pktin = ssh2_transport_pop(s)) != NULL);
296 if (pktin->type != SSH2_MSG_KEXGSS_GROUP) {
297 ssh_proto_error(s->ppl.ssh, "Received unexpected packet when "
298 "expecting Diffie-Hellman group, type %d (%s)",
299 pktin->type,
300 ssh2_pkt_type(s->ppl.bpp->pls->kctx,
301 s->ppl.bpp->pls->actx,
302 pktin->type));
303 *aborted = true;
304 return;
305 }
306 s->p = get_mp_ssh2(pktin);
307 s->g = get_mp_ssh2(pktin);
308 if (get_err(pktin)) {
309 ssh_proto_error(s->ppl.ssh,
310 "Unable to parse Diffie-Hellman group packet");
311 *aborted = true;
312 return;
313 }
314 s->dh_ctx = dh_setup_gex(s->p, s->g);
315 } else {
316 s->dh_ctx = dh_setup_group(s->kex_alg);
317 ppl_logevent("Using GSSAPI (with Kerberos V5) Diffie-Hellman with"
318 " standard group \"%s\"", s->kex_alg->groupname);
319 }
320
321 ppl_logevent("Doing GSSAPI (with Kerberos V5) Diffie-Hellman key "
322 "exchange with hash %s", ssh_hash_alg(s->exhash)->text_name);
323 /* Now generate e for Diffie-Hellman. */
324 seat_set_busy_status(s->ppl.seat, BUSY_CPU);
325 s->e = dh_create_e(s->dh_ctx, s->nbits * 2);
326
327 if (s->shgss->lib->gsslogmsg)
328 ppl_logevent("%s", s->shgss->lib->gsslogmsg);
329
330 /* initial tokens are empty */
331 SSH_GSS_CLEAR_BUF(&s->gss_rcvtok);
332 SSH_GSS_CLEAR_BUF(&s->gss_sndtok);
333 SSH_GSS_CLEAR_BUF(&s->mic);
334 s->gss_stat = s->shgss->lib->acquire_cred(
335 s->shgss->lib, &s->shgss->ctx, &s->gss_cred_expiry);
336 if (s->gss_stat != SSH_GSS_OK) {
337 ssh_sw_abort(s->ppl.ssh,
338 "GSSAPI key exchange failed to initialise");
339 *aborted = true;
340 return;
341 }
342
343 /* now enter the loop */
344 assert(s->shgss->srv_name);
345 do {
346 /*
347 * When acquire_cred yields no useful expiration, go with the
348 * service ticket expiration.
349 */
350 s->gss_stat = s->shgss->lib->init_sec_context(
351 s->shgss->lib, &s->shgss->ctx, s->shgss->srv_name,
352 s->gss_delegate, &s->gss_rcvtok, &s->gss_sndtok,
353 (s->gss_cred_expiry == GSS_NO_EXPIRATION ?
354 &s->gss_cred_expiry : NULL), NULL);
355 SSH_GSS_CLEAR_BUF(&s->gss_rcvtok);
356
357 if (s->gss_stat == SSH_GSS_S_COMPLETE && s->complete_rcvd)
358 break; /* MIC is verified after the loop */
359
360 if (s->gss_stat != SSH_GSS_S_COMPLETE &&
361 s->gss_stat != SSH_GSS_S_CONTINUE_NEEDED) {
362 if (s->shgss->lib->display_status(
363 s->shgss->lib, s->shgss->ctx,
364 &s->gss_buf) == SSH_GSS_OK) {
365 char *err = s->gss_buf.value;
366 ssh_sw_abort(s->ppl.ssh,
367 "GSSAPI key exchange failed to initialise "
368 "context: %s", err);
369 sfree(err);
370 *aborted = true;
371 return;
372 }
373 }
374 assert(s->gss_stat == SSH_GSS_S_COMPLETE ||
375 s->gss_stat == SSH_GSS_S_CONTINUE_NEEDED);
376
377 if (!s->init_token_sent) {
378 s->init_token_sent = true;
379 pktout = ssh_bpp_new_pktout(s->ppl.bpp,
380 SSH2_MSG_KEXGSS_INIT);
381 if (s->gss_sndtok.length == 0) {
382 ssh_sw_abort(s->ppl.ssh, "GSSAPI key exchange failed: "
383 "no initial context token");
384 *aborted = true;
385 return;
386 }
387 put_string(pktout,
388 s->gss_sndtok.value, s->gss_sndtok.length);
389 put_mp_ssh2(pktout, s->e);
390 pq_push(s->ppl.out_pq, pktout);
391 s->shgss->lib->free_tok(s->shgss->lib, &s->gss_sndtok);
392 ppl_logevent("GSSAPI key exchange initialised");
393 } else if (s->gss_sndtok.length != 0) {
394 pktout = ssh_bpp_new_pktout(
395 s->ppl.bpp, SSH2_MSG_KEXGSS_CONTINUE);
396 put_string(pktout,
397 s->gss_sndtok.value, s->gss_sndtok.length);
398 pq_push(s->ppl.out_pq, pktout);
399 s->shgss->lib->free_tok(s->shgss->lib, &s->gss_sndtok);
400 }
401
402 if (s->gss_stat == SSH_GSS_S_COMPLETE && s->complete_rcvd)
403 break;
404
405 wait_for_gss_token:
406 crMaybeWaitUntilV(
407 (pktin = ssh2_transport_pop(s)) != NULL);
408 switch (pktin->type) {
409 case SSH2_MSG_KEXGSS_CONTINUE:
410 data = get_string(pktin);
411 s->gss_rcvtok.value = (char *)data.ptr;
412 s->gss_rcvtok.length = data.len;
413 continue;
414 case SSH2_MSG_KEXGSS_COMPLETE:
415 s->complete_rcvd = true;
416 s->f = get_mp_ssh2(pktin);
417 data = get_string(pktin);
418 s->mic.value = (char *)data.ptr;
419 s->mic.length = data.len;
420 /* If there's a final token we loop to consume it */
421 if (get_bool(pktin)) {
422 data = get_string(pktin);
423 s->gss_rcvtok.value = (char *)data.ptr;
424 s->gss_rcvtok.length = data.len;
425 continue;
426 }
427 break;
428 case SSH2_MSG_KEXGSS_HOSTKEY:
429 s->hostkeydata = get_string(pktin);
430 if (s->hostkey_alg) {
431 s->hkey = ssh_key_new_pub(s->hostkey_alg,
432 s->hostkeydata);
433 put_stringpl(s->exhash, s->hostkeydata);
434 }
435 /*
436 * Can't loop as we have no token to pass to
437 * init_sec_context.
438 */
439 goto wait_for_gss_token;
440 case SSH2_MSG_KEXGSS_ERROR:
441 /*
442 * We have no use for the server's major and minor
443 * status. The minor status is really only
444 * meaningful to the server, and with luck the major
445 * status means something to us (but not really all
446 * that much). The string is more meaningful, and
447 * hopefully the server sends any error tokens, as
448 * that will produce the most useful information for
449 * us.
450 */
451 get_uint32(pktin); /* server's major status */
452 get_uint32(pktin); /* server's minor status */
453 data = get_string(pktin);
454 ppl_logevent("GSSAPI key exchange failed; "
455 "server's message: %.*s", PTRLEN_PRINTF(data));
456 /* Language tag, but we have no use for it */
457 get_string(pktin);
458 /*
459 * Wait for an error token, if there is one, or the
460 * server's disconnect. The error token, if there
461 * is one, must follow the SSH2_MSG_KEXGSS_ERROR
462 * message, per the RFC.
463 */
464 goto wait_for_gss_token;
465 default:
466 ssh_proto_error(s->ppl.ssh, "Received unexpected packet "
467 "during GSSAPI key exchange, type %d (%s)",
468 pktin->type,
469 ssh2_pkt_type(s->ppl.bpp->pls->kctx,
470 s->ppl.bpp->pls->actx,
471 pktin->type));
472 *aborted = true;
473 return;
474 }
475 } while (s->gss_rcvtok.length ||
476 s->gss_stat == SSH_GSS_S_CONTINUE_NEEDED ||
477 !s->complete_rcvd);
478
479 {
480 const char *err = dh_validate_f(s->dh_ctx, s->f);
481 if (err) {
482 ssh_proto_error(s->ppl.ssh, "GSSAPI reply failed "
483 "validation: %s", err);
484 *aborted = true;
485 return;
486 }
487 }
488 s->K = dh_find_K(s->dh_ctx, s->f);
489
490 /* We assume everything from now on will be quick, and it might
491 * involve user interaction. */
492 seat_set_busy_status(s->ppl.seat, BUSY_NOT);
493
494 if (!s->hkey)
495 put_stringz(s->exhash, "");
496 if (dh_is_gex(s->kex_alg)) {
497 /* min, preferred, max */
498 put_uint32(s->exhash, s->pbits);
499 put_uint32(s->exhash, s->pbits);
500 put_uint32(s->exhash, s->pbits * 2);
501
502 put_mp_ssh2(s->exhash, s->p);
503 put_mp_ssh2(s->exhash, s->g);
504 }
505 put_mp_ssh2(s->exhash, s->e);
506 put_mp_ssh2(s->exhash, s->f);
507
508 /*
509 * MIC verification is done below, after we compute the hash
510 * used as the MIC input.
511 */
512
513 dh_cleanup(s->dh_ctx);
514 s->dh_ctx = NULL;
515 mp_free(s->f); s->f = NULL;
516 if (dh_is_gex(s->kex_alg)) {
517 mp_free(s->g); s->g = NULL;
518 mp_free(s->p); s->p = NULL;
519 }
520 #endif
521 } else {
522 ptrlen rsakeydata;
523
524 assert(s->kex_alg->main_type == KEXTYPE_RSA);
525 ppl_logevent("Doing RSA key exchange with hash %s",
526 ssh_hash_alg(s->exhash)->text_name);
527 s->ppl.bpp->pls->kctx = SSH2_PKTCTX_RSAKEX;
528 /*
529 * RSA key exchange. First expect a KEXRSA_PUBKEY packet
530 * from the server.
531 */
532 crMaybeWaitUntilV((pktin = ssh2_transport_pop(s)) != NULL);
533 if (pktin->type != SSH2_MSG_KEXRSA_PUBKEY) {
534 ssh_proto_error(s->ppl.ssh, "Received unexpected packet when "
535 "expecting RSA public key, type %d (%s)",
536 pktin->type,
537 ssh2_pkt_type(s->ppl.bpp->pls->kctx,
538 s->ppl.bpp->pls->actx,
539 pktin->type));
540 *aborted = true;
541 return;
542 }
543
544 s->hostkeydata = get_string(pktin);
545 put_stringpl(s->exhash, s->hostkeydata);
546 s->hkey = ssh_key_new_pub(s->hostkey_alg, s->hostkeydata);
547
548 rsakeydata = get_string(pktin);
549
550 s->rsa_kex_key = ssh_rsakex_newkey(rsakeydata);
551 if (!s->rsa_kex_key) {
552 ssh_proto_error(s->ppl.ssh,
553 "Unable to parse RSA public key packet");
554 *aborted = true;
555 return;
556 }
557 s->rsa_kex_key_needs_freeing = true;
558
559 put_stringpl(s->exhash, rsakeydata);
560
561 /*
562 * Next, set up a shared secret K, of precisely KLEN -
563 * 2*HLEN - 49 bits, where KLEN is the bit length of the
564 * RSA key modulus and HLEN is the bit length of the hash
565 * we're using.
566 */
567 {
568 int klen = ssh_rsakex_klen(s->rsa_kex_key);
569
570 const struct ssh_rsa_kex_extra *extra =
571 (const struct ssh_rsa_kex_extra *)s->kex_alg->extra;
572 if (klen < extra->minklen) {
573 ssh_proto_error(s->ppl.ssh, "Server sent %d-bit RSA key, "
574 "less than the minimum size %d for %s "
575 "key exchange", klen, extra->minklen,
576 s->kex_alg->name);
577 *aborted = true;
578 return;
579 }
580
581 int nbits = klen - (2*s->kex_alg->hash->hlen*8 + 49);
582 assert(nbits > 0);
583
584 strbuf *buf, *outstr;
585
586 mp_int *tmp = mp_random_bits(nbits - 1);
587 s->K = mp_power_2(nbits - 1);
588 mp_add_into(s->K, s->K, tmp);
589 mp_free(tmp);
590
591 /*
592 * Encode this as an mpint.
593 */
594 buf = strbuf_new_nm();
595 put_mp_ssh2(buf, s->K);
596
597 /*
598 * Encrypt it with the given RSA key.
599 */
600 outstr = ssh_rsakex_encrypt(s->rsa_kex_key, s->kex_alg->hash,
601 ptrlen_from_strbuf(buf));
602
603 /*
604 * And send it off in a return packet.
605 */
606 pktout = ssh_bpp_new_pktout(s->ppl.bpp, SSH2_MSG_KEXRSA_SECRET);
607 put_stringpl(pktout, ptrlen_from_strbuf(outstr));
608 pq_push(s->ppl.out_pq, pktout);
609
610 put_stringsb(s->exhash, outstr); /* frees outstr */
611
612 strbuf_free(buf);
613 }
614
615 ssh_rsakex_freekey(s->rsa_kex_key);
616 s->rsa_kex_key = NULL;
617 s->rsa_kex_key_needs_freeing = false;
618
619 crMaybeWaitUntilV((pktin = ssh2_transport_pop(s)) != NULL);
620 if (pktin->type != SSH2_MSG_KEXRSA_DONE) {
621 ssh_proto_error(s->ppl.ssh, "Received unexpected packet when "
622 "expecting RSA kex signature, type %d (%s)",
623 pktin->type,
624 ssh2_pkt_type(s->ppl.bpp->pls->kctx,
625 s->ppl.bpp->pls->actx,
626 pktin->type));
627 *aborted = true;
628 return;
629 }
630
631 s->sigdata = get_string(pktin);
632 if (get_err(pktin)) {
633 ssh_proto_error(s->ppl.ssh, "Unable to parse RSA kex signature");
634 *aborted = true;
635 return;
636 }
637 }
638
639 ssh2transport_finalise_exhash(s);
640
641 #ifndef NO_GSSAPI
642 if (s->kex_alg->main_type == KEXTYPE_GSS) {
643 Ssh_gss_buf gss_buf;
644 SSH_GSS_CLEAR_BUF(&s->gss_buf);
645
646 gss_buf.value = s->exchange_hash;
647 gss_buf.length = s->kex_alg->hash->hlen;
648 s->gss_stat = s->shgss->lib->verify_mic(
649 s->shgss->lib, s->shgss->ctx, &gss_buf, &s->mic);
650 if (s->gss_stat != SSH_GSS_OK) {
651 if (s->shgss->lib->display_status(
652 s->shgss->lib, s->shgss->ctx, &s->gss_buf) == SSH_GSS_OK) {
653 char *err = s->gss_buf.value;
654 ssh_sw_abort(s->ppl.ssh, "GSSAPI key exchange MIC was "
655 "not valid: %s", err);
656 sfree(err);
657 } else {
658 ssh_sw_abort(s->ppl.ssh, "GSSAPI key exchange MIC was "
659 "not valid");
660 }
661 *aborted = true;
662 return;
663 }
664
665 s->gss_kex_used = true;
666
667 /*-
668 * If this the first KEX, save the GSS context for "gssapi-keyex"
669 * authentication.
670 *
671 * http://tools.ietf.org/html/rfc4462#section-4
672 *
673 * This method may be used only if the initial key exchange was
674 * performed using a GSS-API-based key exchange method defined in
675 * accordance with Section 2. The GSS-API context used with this
676 * method is always that established during an initial GSS-API-based
677 * key exchange. Any context established during key exchange for the
678 * purpose of rekeying MUST NOT be used with this method.
679 */
680 if (s->got_session_id) {
681 s->shgss->lib->release_cred(s->shgss->lib, &s->shgss->ctx);
682 }
683 ppl_logevent("GSSAPI Key Exchange complete!");
684 }
685 #endif
686
687 s->dh_ctx = NULL;
688
689 /* In GSS keyex there's no hostkey signature to verify */
690 if (s->kex_alg->main_type != KEXTYPE_GSS) {
691 if (!s->hkey) {
692 ssh_proto_error(s->ppl.ssh, "Server's host key is invalid");
693 *aborted = true;
694 return;
695 }
696
697 if (!ssh_key_verify(
698 s->hkey, s->sigdata,
699 make_ptrlen(s->exchange_hash, s->kex_alg->hash->hlen))) {
700 #ifndef FUZZING
701 ssh_proto_error(s->ppl.ssh, "Signature from server's host key "
702 "is invalid");
703 *aborted = true;
704 return;
705 #endif
706 }
707 }
708
709 s->keystr = (s->hkey ? ssh_key_cache_str(s->hkey) : NULL);
710 #ifndef NO_GSSAPI
711 if (s->gss_kex_used) {
712 /*
713 * In a GSS-based session, check the host key (if any) against
714 * the transient host key cache.
715 */
716 if (s->kex_alg->main_type == KEXTYPE_GSS) {
717
718 /*
719 * We've just done a GSS key exchange. If it gave us a
720 * host key, store it.
721 */
722 if (s->hkey) {
723 char *fingerprint = ssh2_fingerprint(
724 s->hkey, SSH_FPTYPE_DEFAULT);
725 ppl_logevent("GSS kex provided fallback host key:");
726 ppl_logevent("%s", fingerprint);
727 sfree(fingerprint);
728
729 ssh_transient_hostkey_cache_add(s->thc, s->hkey);
730 } else if (!ssh_transient_hostkey_cache_non_empty(s->thc)) {
731 /*
732 * But if it didn't, then we currently have no
733 * fallback host key to use in subsequent non-GSS
734 * rekeys. So we should immediately trigger a non-GSS
735 * rekey of our own, to set one up, before the session
736 * keys have been used for anything else.
737 *
738 * This is similar to the cross-certification done at
739 * user request in the permanent host key cache, but
740 * here we do it automatically, once, at session
741 * startup, and only add the key to the transient
742 * cache.
743 */
744 if (s->hostkey_alg) {
745 s->need_gss_transient_hostkey = true;
746 } else {
747 /*
748 * If we negotiated the "null" host key algorithm
749 * in the key exchange, that's an indication that
750 * no host key at all is available from the server
751 * (both because we listed "null" last, and
752 * because RFC 4462 section 5 says that a server
753 * MUST NOT offer "null" as a host key algorithm
754 * unless that is the only algorithm it provides
755 * at all).
756 *
757 * In that case we actually _can't_ perform a
758 * non-GSSAPI key exchange, so it's pointless to
759 * attempt one proactively. This is also likely to
760 * cause trouble later if a rekey is required at a
761 * moment whne GSS credentials are not available,
762 * but someone setting up a server in this
763 * configuration presumably accepts that as a
764 * consequence.
765 */
766 if (!s->warned_about_no_gss_transient_hostkey) {
767 ppl_logevent("No fallback host key available");
768 s->warned_about_no_gss_transient_hostkey = true;
769 }
770 }
771 }
772 } else {
773 /*
774 * We've just done a fallback key exchange, so make
775 * sure the host key it used is in the cache of keys
776 * we previously received in GSS kexes.
777 *
778 * An exception is if this was the non-GSS key exchange we
779 * triggered on purpose to populate the transient cache.
780 */
781 assert(s->hkey); /* only KEXTYPE_GSS lets this be null */
782 char *fingerprint = ssh2_fingerprint(s->hkey, SSH_FPTYPE_DEFAULT);
783
784 if (s->need_gss_transient_hostkey) {
785 ppl_logevent("Post-GSS rekey provided fallback host key:");
786 ppl_logevent("%s", fingerprint);
787 ssh_transient_hostkey_cache_add(s->thc, s->hkey);
788 s->need_gss_transient_hostkey = false;
789 } else if (!ssh_transient_hostkey_cache_verify(s->thc, s->hkey)) {
790 ppl_logevent("Non-GSS rekey after initial GSS kex "
791 "used host key:");
792 ppl_logevent("%s", fingerprint);
793 sfree(fingerprint);
794 ssh_sw_abort(s->ppl.ssh, "Server's host key did not match any "
795 "used in previous GSS kex");
796 *aborted = true;
797 return;
798 }
799
800 sfree(fingerprint);
801 }
802 } else
803 #endif /* NO_GSSAPI */
804 if (!s->got_session_id) {
805 /*
806 * Make a note of any other host key formats that are available.
807 */
808 {
809 int i, j, nkeys = 0;
810 char *list = NULL;
811 for (i = 0; i < lenof(ssh2_hostkey_algs); i++) {
812 if (ssh2_hostkey_algs[i].alg == s->hostkey_alg)
813 continue;
814
815 for (j = 0; j < s->n_uncert_hostkeys; j++)
816 if (s->uncert_hostkeys[j] == i)
817 break;
818
819 if (j < s->n_uncert_hostkeys) {
820 char *newlist;
821 if (list)
822 newlist = dupprintf(
823 "%s/%s", list,
824 ssh2_hostkey_algs[i].alg->ssh_id);
825 else
826 newlist = dupprintf(
827 "%s", ssh2_hostkey_algs[i].alg->ssh_id);
828 sfree(list);
829 list = newlist;
830 nkeys++;
831 }
832 }
833 if (list) {
834 ppl_logevent("Server also has %s host key%s, but we "
835 "don't know %s", list,
836 nkeys > 1 ? "s" : "",
837 nkeys > 1 ? "any of them" : "it");
838 sfree(list);
839 }
840 }
841
842 /*
843 * Authenticate remote host: verify host key. (We've already
844 * checked the signature of the exchange hash.)
845 */
846 char **fingerprints = ssh2_all_fingerprints(s->hkey);
847 FingerprintType fptype_default =
848 ssh2_pick_default_fingerprint(fingerprints);
849 ppl_logevent("Host key fingerprint is:");
850 ppl_logevent("%s", fingerprints[fptype_default]);
851 /* First check against manually configured host keys. */
852 s->dlgret = verify_ssh_manual_host_key(
853 s->conf, fingerprints, s->hkey);
854 if (s->dlgret == 0) { /* did not match */
855 ssh2_free_all_fingerprints(fingerprints);
856 ssh_sw_abort(s->ppl.ssh, "Host key did not appear in manually "
857 "configured list");
858 *aborted = true;
859 return;
860 } else if (s->dlgret < 0) { /* none configured; use standard handling */
861 ssh2_userkey uk = { .key = s->hkey, .comment = NULL };
862 char *keydisp = ssh2_pubkey_openssh_str(&uk);
863 s->dlgret = seat_verify_ssh_host_key(
864 s->ppl.seat, s->savedhost, s->savedport,
865 ssh_key_cache_id(s->hkey), s->keystr, keydisp,
866 fingerprints, ssh2_transport_dialog_callback, s);
867 sfree(keydisp);
868 ssh2_free_all_fingerprints(fingerprints);
869 #ifdef FUZZING
870 s->dlgret = 1;
871 #endif
872 crMaybeWaitUntilV(s->dlgret >= 0);
873 if (s->dlgret == 0) {
874 ssh_user_close(s->ppl.ssh,
875 "User aborted at host key verification");
876 *aborted = true;
877 return;
878 }
879 }
880
881 /*
882 * Save this host key, to check against the one presented in
883 * subsequent rekeys.
884 */
885 s->hostkey_str = s->keystr;
886 s->keystr = NULL;
887 } else if (s->cross_certifying) {
888 assert(s->hkey);
889 assert(ssh_key_alg(s->hkey) == s->cross_certifying);
890
891 char *fingerprint = ssh2_fingerprint(s->hkey, SSH_FPTYPE_DEFAULT);
892 ppl_logevent("Storing additional host key for this host:");
893 ppl_logevent("%s", fingerprint);
894 sfree(fingerprint);
895
896 store_host_key(s->savedhost, s->savedport,
897 ssh_key_cache_id(s->hkey), s->keystr);
898 /*
899 * Don't forget to store the new key as the one we'll be
900 * re-checking in future normal rekeys.
901 */
902 s->hostkey_str = s->keystr;
903 s->keystr = NULL;
904 } else {
905 /*
906 * In a rekey, we never present an interactive host key
907 * verification request to the user. Instead, we simply
908 * enforce that the key we're seeing this time is identical to
909 * the one we saw before.
910 */
911 assert(s->keystr); /* filled in by prior key exchange */
912 if (strcmp(s->hostkey_str, s->keystr)) {
913 #ifndef FUZZING
914 ssh_sw_abort(s->ppl.ssh,
915 "Host key was different in repeat key exchange");
916 *aborted = true;
917 return;
918 #endif
919 }
920 }
921
922 sfree(s->keystr);
923 s->keystr = NULL;
924 if (s->hkey) {
925 ssh_key_free(s->hkey);
926 s->hkey = NULL;
927 }
928
929 crFinishV;
930 }
931