summaryrefslogtreecommitdiff
path: root/kexgssc.c
diff options
context:
space:
mode:
Diffstat (limited to 'kexgssc.c')
-rw-r--r--kexgssc.c606
1 files changed, 606 insertions, 0 deletions
diff --git a/kexgssc.c b/kexgssc.c
new file mode 100644
index 000000000..f6e1405eb
--- /dev/null
+++ b/kexgssc.c
@@ -0,0 +1,606 @@
1/*
2 * Copyright (c) 2001-2009 Simon Wilkinson. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR
14 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
15 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
16 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
17 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
18 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
19 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
20 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
22 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23 */
24
25#include "includes.h"
26
27#if defined(GSSAPI) && defined(WITH_OPENSSL)
28
29#include "includes.h"
30
31#include <openssl/crypto.h>
32#include <openssl/bn.h>
33
34#include <string.h>
35
36#include "xmalloc.h"
37#include "sshbuf.h"
38#include "ssh2.h"
39#include "sshkey.h"
40#include "cipher.h"
41#include "kex.h"
42#include "log.h"
43#include "packet.h"
44#include "dh.h"
45#include "digest.h"
46#include "ssherr.h"
47
48#include "ssh-gss.h"
49
50int
51kexgss_client(struct ssh *ssh)
52{
53 struct kex *kex = ssh->kex;
54 gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER,
55 recv_tok = GSS_C_EMPTY_BUFFER,
56 gssbuf, msg_tok = GSS_C_EMPTY_BUFFER, *token_ptr;
57 Gssctxt *ctxt;
58 OM_uint32 maj_status, min_status, ret_flags;
59 struct sshbuf *server_blob = NULL;
60 struct sshbuf *shared_secret = NULL;
61 struct sshbuf *server_host_key_blob = NULL;
62 struct sshbuf *empty = NULL;
63 u_char *msg;
64 int type = 0;
65 int first = 1;
66 u_char hash[SSH_DIGEST_MAX_LENGTH];
67 size_t hashlen;
68 u_char c;
69 int r;
70
71 /* Initialise our GSSAPI world */
72 ssh_gssapi_build_ctx(&ctxt);
73 if (ssh_gssapi_id_kex(ctxt, kex->name, kex->kex_type)
74 == GSS_C_NO_OID)
75 fatal("Couldn't identify host exchange");
76
77 if (ssh_gssapi_import_name(ctxt, kex->gss_host))
78 fatal("Couldn't import hostname");
79
80 if (kex->gss_client &&
81 ssh_gssapi_client_identity(ctxt, kex->gss_client))
82 fatal("Couldn't acquire client credentials");
83
84 /* Step 1 */
85 switch (kex->kex_type) {
86 case KEX_GSS_GRP1_SHA1:
87 case KEX_GSS_GRP14_SHA1:
88 case KEX_GSS_GRP14_SHA256:
89 case KEX_GSS_GRP16_SHA512:
90 r = kex_dh_keypair(kex);
91 break;
92 case KEX_GSS_NISTP256_SHA256:
93 r = kex_ecdh_keypair(kex);
94 break;
95 case KEX_GSS_C25519_SHA256:
96 r = kex_c25519_keypair(kex);
97 break;
98 default:
99 fatal("%s: Unexpected KEX type %d", __func__, kex->kex_type);
100 }
101 if (r != 0)
102 return r;
103
104 token_ptr = GSS_C_NO_BUFFER;
105
106 do {
107 debug("Calling gss_init_sec_context");
108
109 maj_status = ssh_gssapi_init_ctx(ctxt,
110 kex->gss_deleg_creds, token_ptr, &send_tok,
111 &ret_flags);
112
113 if (GSS_ERROR(maj_status)) {
114 /* XXX Useles code: Missing send? */
115 if (send_tok.length != 0) {
116 if ((r = sshpkt_start(ssh,
117 SSH2_MSG_KEXGSS_CONTINUE)) != 0 ||
118 (r = sshpkt_put_string(ssh, send_tok.value,
119 send_tok.length)) != 0)
120 fatal("sshpkt failed: %s", ssh_err(r));
121 }
122 fatal("gss_init_context failed");
123 }
124
125 /* If we've got an old receive buffer get rid of it */
126 if (token_ptr != GSS_C_NO_BUFFER)
127 gss_release_buffer(&min_status, &recv_tok);
128
129 if (maj_status == GSS_S_COMPLETE) {
130 /* If mutual state flag is not true, kex fails */
131 if (!(ret_flags & GSS_C_MUTUAL_FLAG))
132 fatal("Mutual authentication failed");
133
134 /* If integ avail flag is not true kex fails */
135 if (!(ret_flags & GSS_C_INTEG_FLAG))
136 fatal("Integrity check failed");
137 }
138
139 /*
140 * If we have data to send, then the last message that we
141 * received cannot have been a 'complete'.
142 */
143 if (send_tok.length != 0) {
144 if (first) {
145 if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_INIT)) != 0 ||
146 (r = sshpkt_put_string(ssh, send_tok.value,
147 send_tok.length)) != 0 ||
148 (r = sshpkt_put_stringb(ssh, kex->client_pub)) != 0)
149 fatal("failed to construct packet: %s", ssh_err(r));
150 first = 0;
151 } else {
152 if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_CONTINUE)) != 0 ||
153 (r = sshpkt_put_string(ssh, send_tok.value,
154 send_tok.length)) != 0)
155 fatal("failed to construct packet: %s", ssh_err(r));
156 }
157 if ((r = sshpkt_send(ssh)) != 0)
158 fatal("failed to send packet: %s", ssh_err(r));
159 gss_release_buffer(&min_status, &send_tok);
160
161 /* If we've sent them data, they should reply */
162 do {
163 type = ssh_packet_read(ssh);
164 if (type == SSH2_MSG_KEXGSS_HOSTKEY) {
165 debug("Received KEXGSS_HOSTKEY");
166 if (server_host_key_blob)
167 fatal("Server host key received more than once");
168 if ((r = sshpkt_getb_froms(ssh, &server_host_key_blob)) != 0)
169 fatal("Failed to read server host key: %s", ssh_err(r));
170 }
171 } while (type == SSH2_MSG_KEXGSS_HOSTKEY);
172
173 switch (type) {
174 case SSH2_MSG_KEXGSS_CONTINUE:
175 debug("Received GSSAPI_CONTINUE");
176 if (maj_status == GSS_S_COMPLETE)
177 fatal("GSSAPI Continue received from server when complete");
178 if ((r = ssh_gssapi_sshpkt_get_buffer_desc(ssh,
179 &recv_tok)) != 0 ||
180 (r = sshpkt_get_end(ssh)) != 0)
181 fatal("Failed to read token: %s", ssh_err(r));
182 break;
183 case SSH2_MSG_KEXGSS_COMPLETE:
184 debug("Received GSSAPI_COMPLETE");
185 if (msg_tok.value != NULL)
186 fatal("Received GSSAPI_COMPLETE twice?");
187 if ((r = sshpkt_getb_froms(ssh, &server_blob)) != 0 ||
188 (r = ssh_gssapi_sshpkt_get_buffer_desc(ssh,
189 &msg_tok)) != 0)
190 fatal("Failed to read message: %s", ssh_err(r));
191
192 /* Is there a token included? */
193 if ((r = sshpkt_get_u8(ssh, &c)) != 0)
194 fatal("sshpkt failed: %s", ssh_err(r));
195 if (c) {
196 if ((r = ssh_gssapi_sshpkt_get_buffer_desc(
197 ssh, &recv_tok)) != 0)
198 fatal("Failed to read token: %s", ssh_err(r));
199 /* If we're already complete - protocol error */
200 if (maj_status == GSS_S_COMPLETE)
201 sshpkt_disconnect(ssh, "Protocol error: received token when complete");
202 } else {
203 /* No token included */
204 if (maj_status != GSS_S_COMPLETE)
205 sshpkt_disconnect(ssh, "Protocol error: did not receive final token");
206 }
207 if ((r = sshpkt_get_end(ssh)) != 0) {
208 fatal("Expecting end of packet.");
209 }
210 break;
211 case SSH2_MSG_KEXGSS_ERROR:
212 debug("Received Error");
213 if ((r = sshpkt_get_u32(ssh, &maj_status)) != 0 ||
214 (r = sshpkt_get_u32(ssh, &min_status)) != 0 ||
215 (r = sshpkt_get_string(ssh, &msg, NULL)) != 0 ||
216 (r = sshpkt_get_string(ssh, NULL, NULL)) != 0 || /* lang tag */
217 (r = sshpkt_get_end(ssh)) != 0)
218 fatal("sshpkt_get failed: %s", ssh_err(r));
219 fatal("GSSAPI Error: \n%.400s", msg);
220 default:
221 sshpkt_disconnect(ssh, "Protocol error: didn't expect packet type %d",
222 type);
223 }
224 token_ptr = &recv_tok;
225 } else {
226 /* No data, and not complete */
227 if (maj_status != GSS_S_COMPLETE)
228 fatal("Not complete, and no token output");
229 }
230 } while (maj_status & GSS_S_CONTINUE_NEEDED);
231
232 /*
233 * We _must_ have received a COMPLETE message in reply from the
234 * server, which will have set server_blob and msg_tok
235 */
236
237 if (type != SSH2_MSG_KEXGSS_COMPLETE)
238 fatal("Didn't receive a SSH2_MSG_KEXGSS_COMPLETE when I expected it");
239
240 /* compute shared secret */
241 switch (kex->kex_type) {
242 case KEX_GSS_GRP1_SHA1:
243 case KEX_GSS_GRP14_SHA1:
244 case KEX_GSS_GRP14_SHA256:
245 case KEX_GSS_GRP16_SHA512:
246 r = kex_dh_dec(kex, server_blob, &shared_secret);
247 break;
248 case KEX_GSS_C25519_SHA256:
249 if (sshbuf_ptr(server_blob)[sshbuf_len(server_blob)] & 0x80)
250 fatal("The received key has MSB of last octet set!");
251 r = kex_c25519_dec(kex, server_blob, &shared_secret);
252 break;
253 case KEX_GSS_NISTP256_SHA256:
254 if (sshbuf_len(server_blob) != 65)
255 fatal("The received NIST-P256 key did not match"
256 "expected length (expected 65, got %zu)", sshbuf_len(server_blob));
257
258 if (sshbuf_ptr(server_blob)[0] != POINT_CONVERSION_UNCOMPRESSED)
259 fatal("The received NIST-P256 key does not have first octet 0x04");
260
261 r = kex_ecdh_dec(kex, server_blob, &shared_secret);
262 break;
263 default:
264 r = SSH_ERR_INVALID_ARGUMENT;
265 break;
266 }
267 if (r != 0)
268 goto out;
269
270 if ((empty = sshbuf_new()) == NULL) {
271 r = SSH_ERR_ALLOC_FAIL;
272 goto out;
273 }
274
275 hashlen = sizeof(hash);
276 if ((r = kex_gen_hash(
277 kex->hash_alg,
278 kex->client_version,
279 kex->server_version,
280 kex->my,
281 kex->peer,
282 (server_host_key_blob ? server_host_key_blob : empty),
283 kex->client_pub,
284 server_blob,
285 shared_secret,
286 hash, &hashlen)) != 0)
287 fatal("%s: Unexpected KEX type %d", __func__, kex->kex_type);
288
289 gssbuf.value = hash;
290 gssbuf.length = hashlen;
291
292 /* Verify that the hash matches the MIC we just got. */
293 if (GSS_ERROR(ssh_gssapi_checkmic(ctxt, &gssbuf, &msg_tok)))
294 sshpkt_disconnect(ssh, "Hash's MIC didn't verify");
295
296 gss_release_buffer(&min_status, &msg_tok);
297
298 if (kex->gss_deleg_creds)
299 ssh_gssapi_credentials_updated(ctxt);
300
301 if (gss_kex_context == NULL)
302 gss_kex_context = ctxt;
303 else
304 ssh_gssapi_delete_ctx(&ctxt);
305
306 if ((r = kex_derive_keys(ssh, hash, hashlen, shared_secret)) == 0)
307 r = kex_send_newkeys(ssh);
308
309out:
310 explicit_bzero(hash, sizeof(hash));
311 explicit_bzero(kex->c25519_client_key, sizeof(kex->c25519_client_key));
312 sshbuf_free(empty);
313 sshbuf_free(server_host_key_blob);
314 sshbuf_free(server_blob);
315 sshbuf_free(shared_secret);
316 sshbuf_free(kex->client_pub);
317 kex->client_pub = NULL;
318 return r;
319}
320
321int
322kexgssgex_client(struct ssh *ssh)
323{
324 struct kex *kex = ssh->kex;
325 gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER,
326 recv_tok = GSS_C_EMPTY_BUFFER, gssbuf,
327 msg_tok = GSS_C_EMPTY_BUFFER, *token_ptr;
328 Gssctxt *ctxt;
329 OM_uint32 maj_status, min_status, ret_flags;
330 struct sshbuf *shared_secret = NULL;
331 BIGNUM *p = NULL;
332 BIGNUM *g = NULL;
333 struct sshbuf *buf = NULL;
334 struct sshbuf *server_host_key_blob = NULL;
335 struct sshbuf *server_blob = NULL;
336 BIGNUM *dh_server_pub = NULL;
337 u_char *msg;
338 int type = 0;
339 int first = 1;
340 u_char hash[SSH_DIGEST_MAX_LENGTH];
341 size_t hashlen;
342 const BIGNUM *pub_key, *dh_p, *dh_g;
343 int nbits = 0, min = DH_GRP_MIN, max = DH_GRP_MAX;
344 struct sshbuf *empty = NULL;
345 u_char c;
346 int r;
347
348 /* Initialise our GSSAPI world */
349 ssh_gssapi_build_ctx(&ctxt);
350 if (ssh_gssapi_id_kex(ctxt, kex->name, kex->kex_type)
351 == GSS_C_NO_OID)
352 fatal("Couldn't identify host exchange");
353
354 if (ssh_gssapi_import_name(ctxt, kex->gss_host))
355 fatal("Couldn't import hostname");
356
357 if (kex->gss_client &&
358 ssh_gssapi_client_identity(ctxt, kex->gss_client))
359 fatal("Couldn't acquire client credentials");
360
361 debug("Doing group exchange");
362 nbits = dh_estimate(kex->dh_need * 8);
363
364 kex->min = DH_GRP_MIN;
365 kex->max = DH_GRP_MAX;
366 kex->nbits = nbits;
367 if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_GROUPREQ)) != 0 ||
368 (r = sshpkt_put_u32(ssh, min)) != 0 ||
369 (r = sshpkt_put_u32(ssh, nbits)) != 0 ||
370 (r = sshpkt_put_u32(ssh, max)) != 0 ||
371 (r = sshpkt_send(ssh)) != 0)
372 fatal("Failed to construct a packet: %s", ssh_err(r));
373
374 if ((r = ssh_packet_read_expect(ssh, SSH2_MSG_KEXGSS_GROUP)) != 0)
375 fatal("Error: %s", ssh_err(r));
376
377 if ((r = sshpkt_get_bignum2(ssh, &p)) != 0 ||
378 (r = sshpkt_get_bignum2(ssh, &g)) != 0 ||
379 (r = sshpkt_get_end(ssh)) != 0)
380 fatal("shpkt_get_bignum2 failed: %s", ssh_err(r));
381
382 if (BN_num_bits(p) < min || BN_num_bits(p) > max)
383 fatal("GSSGRP_GEX group out of range: %d !< %d !< %d",
384 min, BN_num_bits(p), max);
385
386 if ((kex->dh = dh_new_group(g, p)) == NULL)
387 fatal("dn_new_group() failed");
388 p = g = NULL; /* belong to kex->dh now */
389
390 if ((r = dh_gen_key(kex->dh, kex->we_need * 8)) != 0)
391 goto out;
392 DH_get0_key(kex->dh, &pub_key, NULL);
393
394 token_ptr = GSS_C_NO_BUFFER;
395
396 do {
397 /* Step 2 - call GSS_Init_sec_context() */
398 debug("Calling gss_init_sec_context");
399
400 maj_status = ssh_gssapi_init_ctx(ctxt,
401 kex->gss_deleg_creds, token_ptr, &send_tok,
402 &ret_flags);
403
404 if (GSS_ERROR(maj_status)) {
405 /* XXX Useles code: Missing send? */
406 if (send_tok.length != 0) {
407 if ((r = sshpkt_start(ssh,
408 SSH2_MSG_KEXGSS_CONTINUE)) != 0 ||
409 (r = sshpkt_put_string(ssh, send_tok.value,
410 send_tok.length)) != 0)
411 fatal("sshpkt failed: %s", ssh_err(r));
412 }
413 fatal("gss_init_context failed");
414 }
415
416 /* If we've got an old receive buffer get rid of it */
417 if (token_ptr != GSS_C_NO_BUFFER)
418 gss_release_buffer(&min_status, &recv_tok);
419
420 if (maj_status == GSS_S_COMPLETE) {
421 /* If mutual state flag is not true, kex fails */
422 if (!(ret_flags & GSS_C_MUTUAL_FLAG))
423 fatal("Mutual authentication failed");
424
425 /* If integ avail flag is not true kex fails */
426 if (!(ret_flags & GSS_C_INTEG_FLAG))
427 fatal("Integrity check failed");
428 }
429
430 /*
431 * If we have data to send, then the last message that we
432 * received cannot have been a 'complete'.
433 */
434 if (send_tok.length != 0) {
435 if (first) {
436 if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_INIT)) != 0 ||
437 (r = sshpkt_put_string(ssh, send_tok.value,
438 send_tok.length)) != 0 ||
439 (r = sshpkt_put_bignum2(ssh, pub_key)) != 0)
440 fatal("sshpkt failed: %s", ssh_err(r));
441 first = 0;
442 } else {
443 if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_CONTINUE)) != 0 ||
444 (r = sshpkt_put_string(ssh,send_tok.value,
445 send_tok.length)) != 0)
446 fatal("sshpkt failed: %s", ssh_err(r));
447 }
448 if ((r = sshpkt_send(ssh)) != 0)
449 fatal("sshpkt_send failed: %s", ssh_err(r));
450 gss_release_buffer(&min_status, &send_tok);
451
452 /* If we've sent them data, they should reply */
453 do {
454 type = ssh_packet_read(ssh);
455 if (type == SSH2_MSG_KEXGSS_HOSTKEY) {
456 debug("Received KEXGSS_HOSTKEY");
457 if (server_host_key_blob)
458 fatal("Server host key received more than once");
459 if ((r = sshpkt_getb_froms(ssh, &server_host_key_blob)) != 0)
460 fatal("sshpkt failed: %s", ssh_err(r));
461 }
462 } while (type == SSH2_MSG_KEXGSS_HOSTKEY);
463
464 switch (type) {
465 case SSH2_MSG_KEXGSS_CONTINUE:
466 debug("Received GSSAPI_CONTINUE");
467 if (maj_status == GSS_S_COMPLETE)
468 fatal("GSSAPI Continue received from server when complete");
469 if ((r = ssh_gssapi_sshpkt_get_buffer_desc(ssh,
470 &recv_tok)) != 0 ||
471 (r = sshpkt_get_end(ssh)) != 0)
472 fatal("sshpkt failed: %s", ssh_err(r));
473 break;
474 case SSH2_MSG_KEXGSS_COMPLETE:
475 debug("Received GSSAPI_COMPLETE");
476 if (msg_tok.value != NULL)
477 fatal("Received GSSAPI_COMPLETE twice?");
478 if ((r = sshpkt_getb_froms(ssh, &server_blob)) != 0 ||
479 (r = ssh_gssapi_sshpkt_get_buffer_desc(ssh,
480 &msg_tok)) != 0)
481 fatal("sshpkt failed: %s", ssh_err(r));
482
483 /* Is there a token included? */
484 if ((r = sshpkt_get_u8(ssh, &c)) != 0)
485 fatal("sshpkt failed: %s", ssh_err(r));
486 if (c) {
487 if ((r = ssh_gssapi_sshpkt_get_buffer_desc(
488 ssh, &recv_tok)) != 0 ||
489 (r = sshpkt_get_end(ssh)) != 0)
490 fatal("sshpkt failed: %s", ssh_err(r));
491 /* If we're already complete - protocol error */
492 if (maj_status == GSS_S_COMPLETE)
493 sshpkt_disconnect(ssh, "Protocol error: received token when complete");
494 } else {
495 /* No token included */
496 if (maj_status != GSS_S_COMPLETE)
497 sshpkt_disconnect(ssh, "Protocol error: did not receive final token");
498 }
499 break;
500 case SSH2_MSG_KEXGSS_ERROR:
501 debug("Received Error");
502 if ((r = sshpkt_get_u32(ssh, &maj_status)) != 0 ||
503 (r = sshpkt_get_u32(ssh, &min_status)) != 0 ||
504 (r = sshpkt_get_string(ssh, &msg, NULL)) != 0 ||
505 (r = sshpkt_get_string(ssh, NULL, NULL)) != 0 || /* lang tag */
506 (r = sshpkt_get_end(ssh)) != 0)
507 fatal("sshpkt failed: %s", ssh_err(r));
508 fatal("GSSAPI Error: \n%.400s", msg);
509 default:
510 sshpkt_disconnect(ssh, "Protocol error: didn't expect packet type %d",
511 type);
512 }
513 token_ptr = &recv_tok;
514 } else {
515 /* No data, and not complete */
516 if (maj_status != GSS_S_COMPLETE)
517 fatal("Not complete, and no token output");
518 }
519 } while (maj_status & GSS_S_CONTINUE_NEEDED);
520
521 /*
522 * We _must_ have received a COMPLETE message in reply from the
523 * server, which will have set dh_server_pub and msg_tok
524 */
525
526 if (type != SSH2_MSG_KEXGSS_COMPLETE)
527 fatal("Didn't receive a SSH2_MSG_KEXGSS_COMPLETE when I expected it");
528
529 /* 7. C verifies that the key Q_S is valid */
530 /* 8. C computes shared secret */
531 if ((buf = sshbuf_new()) == NULL ||
532 (r = sshbuf_put_stringb(buf, server_blob)) != 0 ||
533 (r = sshbuf_get_bignum2(buf, &dh_server_pub)) != 0)
534 goto out;
535 sshbuf_free(buf);
536 buf = NULL;
537
538 if ((shared_secret = sshbuf_new()) == NULL) {
539 r = SSH_ERR_ALLOC_FAIL;
540 goto out;
541 }
542
543 if ((r = kex_dh_compute_key(kex, dh_server_pub, shared_secret)) != 0)
544 goto out;
545 if ((empty = sshbuf_new()) == NULL) {
546 r = SSH_ERR_ALLOC_FAIL;
547 goto out;
548 }
549
550 DH_get0_pqg(kex->dh, &dh_p, NULL, &dh_g);
551 hashlen = sizeof(hash);
552 if ((r = kexgex_hash(
553 kex->hash_alg,
554 kex->client_version,
555 kex->server_version,
556 kex->my,
557 kex->peer,
558 (server_host_key_blob ? server_host_key_blob : empty),
559 kex->min, kex->nbits, kex->max,
560 dh_p, dh_g,
561 pub_key,
562 dh_server_pub,
563 sshbuf_ptr(shared_secret), sshbuf_len(shared_secret),
564 hash, &hashlen)) != 0)
565 fatal("Failed to calculate hash: %s", ssh_err(r));
566
567 gssbuf.value = hash;
568 gssbuf.length = hashlen;
569
570 /* Verify that the hash matches the MIC we just got. */
571 if (GSS_ERROR(ssh_gssapi_checkmic(ctxt, &gssbuf, &msg_tok)))
572 sshpkt_disconnect(ssh, "Hash's MIC didn't verify");
573
574 gss_release_buffer(&min_status, &msg_tok);
575
576 /* save session id */
577 if (kex->session_id == NULL) {
578 kex->session_id_len = hashlen;
579 kex->session_id = xmalloc(kex->session_id_len);
580 memcpy(kex->session_id, hash, kex->session_id_len);
581 }
582
583 if (kex->gss_deleg_creds)
584 ssh_gssapi_credentials_updated(ctxt);
585
586 if (gss_kex_context == NULL)
587 gss_kex_context = ctxt;
588 else
589 ssh_gssapi_delete_ctx(&ctxt);
590
591 /* Finally derive the keys and send them */
592 if ((r = kex_derive_keys(ssh, hash, hashlen, shared_secret)) == 0)
593 r = kex_send_newkeys(ssh);
594out:
595 sshbuf_free(buf);
596 sshbuf_free(server_blob);
597 sshbuf_free(empty);
598 explicit_bzero(hash, sizeof(hash));
599 DH_free(kex->dh);
600 kex->dh = NULL;
601 BN_clear_free(dh_server_pub);
602 sshbuf_free(shared_secret);
603 sshbuf_free(server_host_key_blob);
604 return r;
605}
606#endif /* defined(GSSAPI) && defined(WITH_OPENSSL) */