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