]> andersk Git - gssapi-openssh.git/blame - openssh/kex.c
http://www.psc.edu/networking/projects/hpn-ssh/openssh-5.1p1-hpn13v5.diff.gz committe...
[gssapi-openssh.git] / openssh / kex.c
CommitLineData
d4487008 1/* $OpenBSD: kex.c,v 1.79 2007/06/05 06:52:37 djm Exp $ */
3c0ef626 2/*
3 * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
18 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#include "includes.h"
9108f8d9 27
28#include <sys/param.h>
29
30#include <signal.h>
31#include <stdarg.h>
32#include <stdio.h>
33#include <stdlib.h>
34#include <string.h>
3c0ef626 35
36#include <openssl/crypto.h>
37
3c0ef626 38#include "xmalloc.h"
9108f8d9 39#include "ssh2.h"
3c0ef626 40#include "buffer.h"
3c0ef626 41#include "packet.h"
42#include "compat.h"
43#include "cipher.h"
3c0ef626 44#include "key.h"
9108f8d9 45#include "kex.h"
3c0ef626 46#include "log.h"
47#include "mac.h"
48#include "match.h"
49#include "dispatch.h"
700318f3 50#include "monitor.h"
c015d727 51#include "canohost.h"
3c0ef626 52
53#define KEX_COOKIE_LEN 16
54
9108f8d9 55#if OPENSSL_VERSION_NUMBER >= 0x00907000L
56# if defined(HAVE_EVP_SHA256)
57# define evp_ssh_sha256 EVP_sha256
58# else
59extern const EVP_MD *evp_ssh_sha256(void);
60# endif
61#endif
62
3c0ef626 63/* prototype */
64static void kex_kexinit_finish(Kex *);
65static void kex_choose_conf(Kex *);
66
67/* put algorithm proposal into buffer */
c015d727 68/* used in sshconnect.c as well as kex.c */
69void
3c0ef626 70kex_prop2buf(Buffer *b, char *proposal[PROPOSAL_MAX])
71{
665a873d 72 u_int i;
3c0ef626 73
74 buffer_clear(b);
700318f3 75 /*
76 * add a dummy cookie, the cookie will be overwritten by
77 * kex_send_kexinit(), each time a kexinit is set
78 */
79 for (i = 0; i < KEX_COOKIE_LEN; i++)
80 buffer_put_char(b, 0);
3c0ef626 81 for (i = 0; i < PROPOSAL_MAX; i++)
82 buffer_put_cstring(b, proposal[i]);
83 buffer_put_char(b, 0); /* first_kex_packet_follows */
84 buffer_put_int(b, 0); /* uint32 reserved */
85}
86
87/* parse buffer and return algorithm proposal */
88static char **
6a9b3198 89kex_buf2prop(Buffer *raw, int *first_kex_follows)
3c0ef626 90{
91 Buffer b;
d4487008 92 u_int i;
3c0ef626 93 char **proposal;
94
9108f8d9 95 proposal = xcalloc(PROPOSAL_MAX, sizeof(char *));
3c0ef626 96
97 buffer_init(&b);
98 buffer_append(&b, buffer_ptr(raw), buffer_len(raw));
99 /* skip cookie */
100 for (i = 0; i < KEX_COOKIE_LEN; i++)
101 buffer_get_char(&b);
102 /* extract kex init proposal strings */
103 for (i = 0; i < PROPOSAL_MAX; i++) {
104 proposal[i] = buffer_get_string(&b,NULL);
105 debug2("kex_parse_kexinit: %s", proposal[i]);
106 }
107 /* first kex follows / reserved */
108 i = buffer_get_char(&b);
6a9b3198 109 if (first_kex_follows != NULL)
110 *first_kex_follows = i;
3c0ef626 111 debug2("kex_parse_kexinit: first_kex_follows %d ", i);
112 i = buffer_get_int(&b);
d4487008 113 debug2("kex_parse_kexinit: reserved %u ", i);
3c0ef626 114 buffer_free(&b);
115 return proposal;
116}
117
118static void
119kex_prop_free(char **proposal)
120{
665a873d 121 u_int i;
3c0ef626 122
123 for (i = 0; i < PROPOSAL_MAX; i++)
124 xfree(proposal[i]);
125 xfree(proposal);
126}
127
d4487008 128/* ARGSUSED */
3c0ef626 129static void
e9a17296 130kex_protocol_error(int type, u_int32_t seq, void *ctxt)
3c0ef626 131{
e9a17296 132 error("Hm, kex protocol error: type %d seq %u", type, seq);
3c0ef626 133}
134
135static void
e9a17296 136kex_reset_dispatch(void)
3c0ef626 137{
e9a17296 138 dispatch_range(SSH2_MSG_TRANSPORT_MIN,
139 SSH2_MSG_TRANSPORT_MAX, &kex_protocol_error);
140 dispatch_set(SSH2_MSG_KEXINIT, &kex_input_kexinit);
3c0ef626 141}
142
143void
144kex_finish(Kex *kex)
145{
e9a17296 146 kex_reset_dispatch();
3c0ef626 147
148 packet_start(SSH2_MSG_NEWKEYS);
149 packet_send();
150 /* packet_write_wait(); */
151 debug("SSH2_MSG_NEWKEYS sent");
152
6a9b3198 153 debug("expecting SSH2_MSG_NEWKEYS");
e9a17296 154 packet_read_expect(SSH2_MSG_NEWKEYS);
155 packet_check_eom();
3c0ef626 156 debug("SSH2_MSG_NEWKEYS received");
157
158 kex->done = 1;
159 buffer_clear(&kex->peer);
160 /* buffer_clear(&kex->my); */
161 kex->flags &= ~KEX_INIT_SENT;
162 xfree(kex->name);
163 kex->name = NULL;
164}
165
166void
167kex_send_kexinit(Kex *kex)
168{
c9f39d2c 169 u_int32_t rnd = 0;
700318f3 170 u_char *cookie;
665a873d 171 u_int i;
700318f3 172
3c0ef626 173 if (kex == NULL) {
174 error("kex_send_kexinit: no kex, cannot rekey");
175 return;
176 }
177 if (kex->flags & KEX_INIT_SENT) {
178 debug("KEX_INIT_SENT");
179 return;
180 }
181 kex->done = 0;
700318f3 182
183 /* generate a random cookie */
184 if (buffer_len(&kex->my) < KEX_COOKIE_LEN)
185 fatal("kex_send_kexinit: kex proposal too short");
186 cookie = buffer_ptr(&kex->my);
187 for (i = 0; i < KEX_COOKIE_LEN; i++) {
188 if (i % 4 == 0)
c9f39d2c 189 rnd = arc4random();
190 cookie[i] = rnd;
191 rnd >>= 8;
700318f3 192 }
3c0ef626 193 packet_start(SSH2_MSG_KEXINIT);
194 packet_put_raw(buffer_ptr(&kex->my), buffer_len(&kex->my));
195 packet_send();
196 debug("SSH2_MSG_KEXINIT sent");
197 kex->flags |= KEX_INIT_SENT;
198}
199
d4487008 200/* ARGSUSED */
3c0ef626 201void
e9a17296 202kex_input_kexinit(int type, u_int32_t seq, void *ctxt)
3c0ef626 203{
204 char *ptr;
665a873d 205 u_int i, dlen;
3c0ef626 206 Kex *kex = (Kex *)ctxt;
207
208 debug("SSH2_MSG_KEXINIT received");
209 if (kex == NULL)
210 fatal("kex_input_kexinit: no kex, cannot rekey");
211
212 ptr = packet_get_raw(&dlen);
213 buffer_append(&kex->peer, ptr, dlen);
214
215 /* discard packet */
216 for (i = 0; i < KEX_COOKIE_LEN; i++)
217 packet_get_char();
218 for (i = 0; i < PROPOSAL_MAX; i++)
219 xfree(packet_get_string(NULL));
680cee3b 220 (void) packet_get_char();
221 (void) packet_get_int();
e9a17296 222 packet_check_eom();
3c0ef626 223
224 kex_kexinit_finish(kex);
225}
226
227Kex *
228kex_setup(char *proposal[PROPOSAL_MAX])
229{
230 Kex *kex;
231
9108f8d9 232 kex = xcalloc(1, sizeof(*kex));
3c0ef626 233 buffer_init(&kex->peer);
234 buffer_init(&kex->my);
235 kex_prop2buf(&kex->my, proposal);
236 kex->done = 0;
237
238 kex_send_kexinit(kex); /* we start */
e9a17296 239 kex_reset_dispatch();
3c0ef626 240
241 return kex;
242}
243
244static void
245kex_kexinit_finish(Kex *kex)
246{
247 if (!(kex->flags & KEX_INIT_SENT))
248 kex_send_kexinit(kex);
249
250 kex_choose_conf(kex);
251
6a9b3198 252 if (kex->kex_type >= 0 && kex->kex_type < KEX_MAX &&
253 kex->kex[kex->kex_type] != NULL) {
254 (kex->kex[kex->kex_type])(kex);
255 } else {
3c0ef626 256 fatal("Unsupported key exchange %d", kex->kex_type);
257 }
258}
259
260static void
261choose_enc(Enc *enc, char *client, char *server)
262{
263 char *name = match_list(client, server, NULL);
264 if (name == NULL)
d4487008 265 fatal("no matching cipher found: client %s server %s",
266 client, server);
e9a17296 267 if ((enc->cipher = cipher_by_name(name)) == NULL)
3c0ef626 268 fatal("matching cipher is not supported: %s", name);
269 enc->name = name;
270 enc->enabled = 0;
271 enc->iv = NULL;
272 enc->key = NULL;
e9a17296 273 enc->key_len = cipher_keylen(enc->cipher);
274 enc->block_size = cipher_blocksize(enc->cipher);
3c0ef626 275}
9108f8d9 276
3c0ef626 277static void
278choose_mac(Mac *mac, char *client, char *server)
279{
280 char *name = match_list(client, server, NULL);
281 if (name == NULL)
d4487008 282 fatal("no matching mac found: client %s server %s",
283 client, server);
284 if (mac_setup(mac, name) < 0)
3c0ef626 285 fatal("unsupported mac %s", name);
286 /* truncate the key */
287 if (datafellows & SSH_BUG_HMAC)
288 mac->key_len = 16;
289 mac->name = name;
290 mac->key = NULL;
291 mac->enabled = 0;
292}
9108f8d9 293
3c0ef626 294static void
295choose_comp(Comp *comp, char *client, char *server)
296{
297 char *name = match_list(client, server, NULL);
298 if (name == NULL)
299 fatal("no matching comp found: client %s server %s", client, server);
665a873d 300 if (strcmp(name, "zlib@openssh.com") == 0) {
301 comp->type = COMP_DELAYED;
302 } else if (strcmp(name, "zlib") == 0) {
303 comp->type = COMP_ZLIB;
3c0ef626 304 } else if (strcmp(name, "none") == 0) {
665a873d 305 comp->type = COMP_NONE;
3c0ef626 306 } else {
307 fatal("unsupported comp %s", name);
308 }
309 comp->name = name;
310}
9108f8d9 311
3c0ef626 312static void
313choose_kex(Kex *k, char *client, char *server)
314{
315 k->name = match_list(client, server, NULL);
316 if (k->name == NULL)
d4487008 317 fatal("Unable to negotiate a key exchange method");
3c0ef626 318 if (strcmp(k->name, KEX_DH1) == 0) {
6a9b3198 319 k->kex_type = KEX_DH_GRP1_SHA1;
2c06c99b 320 k->evp_md = EVP_sha1();
c9f39d2c 321 } else if (strcmp(k->name, KEX_DH14) == 0) {
322 k->kex_type = KEX_DH_GRP14_SHA1;
2c06c99b 323 k->evp_md = EVP_sha1();
324 } else if (strcmp(k->name, KEX_DHGEX_SHA1) == 0) {
6a9b3198 325 k->kex_type = KEX_DH_GEX_SHA1;
2c06c99b 326 k->evp_md = EVP_sha1();
9108f8d9 327#if OPENSSL_VERSION_NUMBER >= 0x00907000L
328 } else if (strcmp(k->name, KEX_DHGEX_SHA256) == 0) {
329 k->kex_type = KEX_DH_GEX_SHA256;
330 k->evp_md = evp_ssh_sha256();
331#endif
3c0ef626 332 } else
333 fatal("bad kex alg %s", k->name);
334}
2c06c99b 335
3c0ef626 336static void
337choose_hostkeyalg(Kex *k, char *client, char *server)
338{
339 char *hostkeyalg = match_list(client, server, NULL);
340 if (hostkeyalg == NULL)
341 fatal("no hostkey alg");
342 k->hostkey_type = key_type_from_name(hostkeyalg);
343 if (k->hostkey_type == KEY_UNSPEC)
344 fatal("bad hostkey alg '%s'", hostkeyalg);
345 xfree(hostkeyalg);
346}
347
cdd66111 348static int
6a9b3198 349proposals_match(char *my[PROPOSAL_MAX], char *peer[PROPOSAL_MAX])
350{
351 static int check[] = {
352 PROPOSAL_KEX_ALGS, PROPOSAL_SERVER_HOST_KEY_ALGS, -1
353 };
354 int *idx;
355 char *p;
356
357 for (idx = &check[0]; *idx != -1; idx++) {
358 if ((p = strchr(my[*idx], ',')) != NULL)
359 *p = '\0';
360 if ((p = strchr(peer[*idx], ',')) != NULL)
361 *p = '\0';
362 if (strcmp(my[*idx], peer[*idx]) != 0) {
363 debug2("proposal mismatch: my %s peer %s",
364 my[*idx], peer[*idx]);
365 return (0);
366 }
367 }
368 debug2("proposals match");
369 return (1);
370}
371
3c0ef626 372static void
373kex_choose_conf(Kex *kex)
374{
375 Newkeys *newkeys;
376 char **my, **peer;
377 char **cprop, **sprop;
378 int nenc, nmac, ncomp;
665a873d 379 u_int mode, ctos, need;
6a9b3198 380 int first_kex_follows, type;
c015d727 381 int log_flag = 0;
382
383 int auth_flag;
384
385 auth_flag = packet_authentication_state();
386
387 debug ("AUTH STATE IS %d", auth_flag);
3c0ef626 388
6a9b3198 389 my = kex_buf2prop(&kex->my, NULL);
390 peer = kex_buf2prop(&kex->peer, &first_kex_follows);
3c0ef626 391
392 if (kex->server) {
393 cprop=peer;
394 sprop=my;
395 } else {
396 cprop=my;
397 sprop=peer;
398 }
399
400 /* Algorithm Negotiation */
401 for (mode = 0; mode < MODE_MAX; mode++) {
9108f8d9 402 newkeys = xcalloc(1, sizeof(*newkeys));
3c0ef626 403 kex->newkeys[mode] = newkeys;
d4487008 404 ctos = (!kex->server && mode == MODE_OUT) ||
405 (kex->server && mode == MODE_IN);
3c0ef626 406 nenc = ctos ? PROPOSAL_ENC_ALGS_CTOS : PROPOSAL_ENC_ALGS_STOC;
407 nmac = ctos ? PROPOSAL_MAC_ALGS_CTOS : PROPOSAL_MAC_ALGS_STOC;
408 ncomp = ctos ? PROPOSAL_COMP_ALGS_CTOS : PROPOSAL_COMP_ALGS_STOC;
409 choose_enc (&newkeys->enc, cprop[nenc], sprop[nenc]);
410 choose_mac (&newkeys->mac, cprop[nmac], sprop[nmac]);
411 choose_comp(&newkeys->comp, cprop[ncomp], sprop[ncomp]);
c015d727 412 debug("REQUESTED ENC.NAME is '%s'", newkeys->enc.name);
413 if (strcmp(newkeys->enc.name, "none") == 0) {
414 debug("Requesting NONE. Authflag is %d", auth_flag);
415 if (auth_flag == 1) {
416 debug("None requested post authentication.");
417 } else {
418 fatal("Pre-authentication none cipher requests are not allowed.");
419 }
420 }
3c0ef626 421 debug("kex: %s %s %s %s",
422 ctos ? "client->server" : "server->client",
423 newkeys->enc.name,
424 newkeys->mac.name,
425 newkeys->comp.name);
c015d727 426 /* client starts withctos = 0 && log flag = 0 and no log*/
427 /* 2nd client pass ctos=1 and flag = 1 so no log*/
428 /* server starts with ctos =1 && log_flag = 0 so log */
429 /* 2nd sever pass ctos = 1 && log flag = 1 so no log*/
430 /* -cjr*/
431 if (ctos && !log_flag) {
432 logit("SSH: Server;Ltype: Kex;Remote: %s-%d;Enc: %s;MAC: %s;Comp: %s",
433 get_remote_ipaddr(),
434 get_remote_port(),
435 newkeys->enc.name,
436 newkeys->mac.name,
437 newkeys->comp.name);
438 }
439 log_flag = 1;
3c0ef626 440 }
441 choose_kex(kex, cprop[PROPOSAL_KEX_ALGS], sprop[PROPOSAL_KEX_ALGS]);
442 choose_hostkeyalg(kex, cprop[PROPOSAL_SERVER_HOST_KEY_ALGS],
443 sprop[PROPOSAL_SERVER_HOST_KEY_ALGS]);
444 need = 0;
445 for (mode = 0; mode < MODE_MAX; mode++) {
446 newkeys = kex->newkeys[mode];
e9a17296 447 if (need < newkeys->enc.key_len)
448 need = newkeys->enc.key_len;
449 if (need < newkeys->enc.block_size)
450 need = newkeys->enc.block_size;
3c0ef626 451 if (need < newkeys->mac.key_len)
452 need = newkeys->mac.key_len;
453 }
454 /* XXX need runden? */
455 kex->we_need = need;
456
6a9b3198 457 /* ignore the next message if the proposals do not match */
cdd66111 458 if (first_kex_follows && !proposals_match(my, peer) &&
665a873d 459 !(datafellows & SSH_BUG_FIRSTKEX)) {
6a9b3198 460 type = packet_read();
461 debug2("skipping next packet (type %u)", type);
462 }
463
3c0ef626 464 kex_prop_free(my);
465 kex_prop_free(peer);
466}
467
468static u_char *
2c06c99b 469derive_key(Kex *kex, int id, u_int need, u_char *hash, u_int hashlen,
470 BIGNUM *shared_secret)
3c0ef626 471{
472 Buffer b;
3c0ef626 473 EVP_MD_CTX md;
474 char c = id;
665a873d 475 u_int have;
2c06c99b 476 int mdsz;
665a873d 477 u_char *digest;
478
2c06c99b 479 if ((mdsz = EVP_MD_size(kex->evp_md)) <= 0)
480 fatal("bad kex md size %d", mdsz);
9108f8d9 481 digest = xmalloc(roundup(need, mdsz));
3c0ef626 482
483 buffer_init(&b);
484 buffer_put_bignum2(&b, shared_secret);
485
486 /* K1 = HASH(K || H || "A" || session_id) */
2c06c99b 487 EVP_DigestInit(&md, kex->evp_md);
3c0ef626 488 if (!(datafellows & SSH_BUG_DERIVEKEY))
489 EVP_DigestUpdate(&md, buffer_ptr(&b), buffer_len(&b));
2c06c99b 490 EVP_DigestUpdate(&md, hash, hashlen);
3c0ef626 491 EVP_DigestUpdate(&md, &c, 1);
492 EVP_DigestUpdate(&md, kex->session_id, kex->session_id_len);
493 EVP_DigestFinal(&md, digest, NULL);
494
495 /*
496 * expand key:
497 * Kn = HASH(K || H || K1 || K2 || ... || Kn-1)
498 * Key = K1 || K2 || ... || Kn
499 */
500 for (have = mdsz; need > have; have += mdsz) {
2c06c99b 501 EVP_DigestInit(&md, kex->evp_md);
3c0ef626 502 if (!(datafellows & SSH_BUG_DERIVEKEY))
503 EVP_DigestUpdate(&md, buffer_ptr(&b), buffer_len(&b));
2c06c99b 504 EVP_DigestUpdate(&md, hash, hashlen);
3c0ef626 505 EVP_DigestUpdate(&md, digest, have);
506 EVP_DigestFinal(&md, digest + have, NULL);
507 }
508 buffer_free(&b);
509#ifdef DEBUG_KEX
510 fprintf(stderr, "key '%c'== ", c);
511 dump_digest("key", digest, need);
512#endif
513 return digest;
514}
515
516Newkeys *current_keys[MODE_MAX];
517
518#define NKEYS 6
519void
2c06c99b 520kex_derive_keys(Kex *kex, u_char *hash, u_int hashlen, BIGNUM *shared_secret)
3c0ef626 521{
522 u_char *keys[NKEYS];
665a873d 523 u_int i, mode, ctos;
3c0ef626 524
2c06c99b 525 for (i = 0; i < NKEYS; i++) {
526 keys[i] = derive_key(kex, 'A'+i, kex->we_need, hash, hashlen,
527 shared_secret);
528 }
3c0ef626 529
6a9b3198 530 debug2("kex_derive_keys");
3c0ef626 531 for (mode = 0; mode < MODE_MAX; mode++) {
532 current_keys[mode] = kex->newkeys[mode];
533 kex->newkeys[mode] = NULL;
9108f8d9 534 ctos = (!kex->server && mode == MODE_OUT) ||
535 (kex->server && mode == MODE_IN);
3c0ef626 536 current_keys[mode]->enc.iv = keys[ctos ? 0 : 1];
537 current_keys[mode]->enc.key = keys[ctos ? 2 : 3];
538 current_keys[mode]->mac.key = keys[ctos ? 4 : 5];
539 }
540}
541
542Newkeys *
543kex_get_newkeys(int mode)
544{
545 Newkeys *ret;
546
547 ret = current_keys[mode];
548 current_keys[mode] = NULL;
549 return ret;
550}
551
c9f39d2c 552void
553derive_ssh1_session_id(BIGNUM *host_modulus, BIGNUM *server_modulus,
554 u_int8_t cookie[8], u_int8_t id[16])
555{
556 const EVP_MD *evp_md = EVP_md5();
557 EVP_MD_CTX md;
558 u_int8_t nbuf[2048], obuf[EVP_MAX_MD_SIZE];
559 int len;
560
561 EVP_DigestInit(&md, evp_md);
562
563 len = BN_num_bytes(host_modulus);
665a873d 564 if (len < (512 / 8) || (u_int)len > sizeof(nbuf))
c9f39d2c 565 fatal("%s: bad host modulus (len %d)", __func__, len);
566 BN_bn2bin(host_modulus, nbuf);
567 EVP_DigestUpdate(&md, nbuf, len);
568
569 len = BN_num_bytes(server_modulus);
665a873d 570 if (len < (512 / 8) || (u_int)len > sizeof(nbuf))
c9f39d2c 571 fatal("%s: bad server modulus (len %d)", __func__, len);
572 BN_bn2bin(server_modulus, nbuf);
573 EVP_DigestUpdate(&md, nbuf, len);
574
575 EVP_DigestUpdate(&md, cookie, 8);
576
577 EVP_DigestFinal(&md, obuf, NULL);
578 memcpy(id, obuf, 16);
579
580 memset(nbuf, 0, sizeof(nbuf));
581 memset(obuf, 0, sizeof(obuf));
582 memset(&md, 0, sizeof(md));
583}
584
3c0ef626 585#if defined(DEBUG_KEX) || defined(DEBUG_KEXDH)
586void
587dump_digest(char *msg, u_char *digest, int len)
588{
665a873d 589 u_int i;
3c0ef626 590
591 fprintf(stderr, "%s\n", msg);
799ae497 592 for (i = 0; i < len; i++) {
3c0ef626 593 fprintf(stderr, "%02x", digest[i]);
594 if (i%32 == 31)
595 fprintf(stderr, "\n");
596 else if (i%8 == 7)
597 fprintf(stderr, " ");
598 }
599 fprintf(stderr, "\n");
600}
601#endif
This page took 0.186864 seconds and 5 git commands to generate.