keyexchange.c 21.9 KB
Newer Older
Niels Möller's avatar
Niels Möller committed
1
/* keyexchange.c
Niels Möller's avatar
Niels Möller committed
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
 *
 * $Id$ */

/* lsh, an implementation of the ssh protocol
 *
 * Copyright (C) 1998 Niels Mller
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
J.H.M. Dassen's avatar
J.H.M. Dassen committed
21
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
Niels Möller's avatar
Niels Möller committed
22
23
 */

24
25
#include "keyexchange.h"

26
#include "abstract_io.h"
27
28
/* For filter_algorithms */
#include "algorithms.h"
29
#include "alist.h"
30
#include "command.h"
31
#include "connection.h"
32
#include "debug.h"
33
#include "disconnect.h"
34
#include "format.h"
Niels Möller's avatar
Niels Möller committed
35
#include "parse.h"
Niels Möller's avatar
Niels Möller committed
36
#include "publickey_crypto.h"
37
#include "ssh.h"
38
#include "werror.h"
39
#include "xalloc.h"
Niels Möller's avatar
Niels Möller committed
40

41
#include <string.h>
42
43
#include <assert.h>

44
#define GABA_DEFINE
45
#include "keyexchange.h.x"
46
#undef GABA_DEFINE
47
48
49

#include "keyexchange.c.x"

50
/* GABA:
51
52
53
54
55
56
   (class
     (name kexinit_handler)
     (super packet_handler)
     (vars
       (init object make_kexinit)

57
58
59
       ; Extra rgument for the KEYEXCHANGE_INIT call.
       (extra object lsh_object)
       
60
61
62
63
64
       ; Maps names to algorithms. It's dangerous to lookup random atoms
       ; in this table, as not all objects have the same type. This
       ; mapping is used only on atoms that have appeared in *both* the
       ; client's and the server's list of algorithms (of a certain
       ; type), and therefore the remote side can't screw things up.
65
       (algorithms object alist)))
66
*/
67

Niels Möller's avatar
Niels Möller committed
68
69
#define NLISTS 10

70
71
72
/* Arbitrary limit on list length */
#define KEXINIT_MAX_ALGORITMS 47

Niels Möller's avatar
Niels Möller committed
73
74
static struct kexinit *
parse_kexinit(struct lsh_string *packet)
Niels Möller's avatar
Niels Möller committed
75
{
76
  NEW(kexinit, res);
Niels Möller's avatar
Niels Möller committed
77
  struct simple_buffer buffer;
Niels Möller's avatar
Niels Möller committed
78
  unsigned msg_number;
Niels Möller's avatar
Niels Möller committed
79
80
  UINT32 reserved;
  
81
  struct int_list *lists[NLISTS];
Niels Möller's avatar
Niels Möller committed
82
83
84
85
86
87
  int i;
  
  simple_buffer_init(&buffer, packet->length, packet->data);

  if (!parse_uint8(&buffer, &msg_number)
      || (msg_number != SSH_MSG_KEXINIT) )
88
89
    {
      KILL(res);
Niels Möller's avatar
Niels Möller committed
90
      return NULL;
91
    }
Niels Möller's avatar
Niels Möller committed
92

93
  if (!parse_octets(&buffer, 16, res->cookie))
Niels Möller's avatar
Niels Möller committed
94
    {
95
      KILL(res);
Niels Möller's avatar
Niels Möller committed
96
97
98
99
100
      return NULL;
    }
  
  for (i = 0; i<NLISTS; i++)
    {
101
      if ( !(lists[i] = parse_atom_list(&buffer, KEXINIT_MAX_ALGORITMS)))
Niels Möller's avatar
Niels Möller committed
102
103
104
105
106
107
108
109
110
111
112
	break;
    }

  if ( (i<NLISTS)
       || !parse_boolean(&buffer, &res->first_kex_packet_follows)
       || !parse_uint32(&buffer, &reserved)
       || reserved || !parse_eod(&buffer) )
    {
      /* Bad format */
      int j;
      for (j = 0; j<i; j++)
113
114
	KILL(lists[i]);
      KILL(res);
Niels Möller's avatar
Niels Möller committed
115
116
117
      return NULL;
    }
  
118
  res->kex_algorithms = lists[0];
119
  res->server_hostkey_algorithms = lists[1];
Niels Möller's avatar
Niels Möller committed
120
121
122
123

  for (i=0; i<KEX_PARAMETERS; i++)
    res->parameters[i] = lists[2 + i];

124
125
  res->languages_client_to_server = lists[8];
  res->languages_server_to_client = lists[9];
Niels Möller's avatar
Niels Möller committed
126
127
128

  return res;
}
Niels Möller's avatar
Niels Möller committed
129

Niels Möller's avatar
Niels Möller committed
130
131
struct lsh_string *
format_kex(struct kexinit *kex)
Niels Möller's avatar
Niels Möller committed
132
133
134
135
136
{
  return ssh_format("%c%ls%A%A%A%A%A%A%A%A%A%A%c%i",
		    SSH_MSG_KEXINIT,
		    16, kex->cookie,
		    kex->kex_algorithms,
137
		    kex->server_hostkey_algorithms,
Niels Möller's avatar
Niels Möller committed
138
139
140
141
142
143
		    kex->parameters[KEX_ENCRYPTION_CLIENT_TO_SERVER],
		    kex->parameters[KEX_ENCRYPTION_SERVER_TO_CLIENT],
		    kex->parameters[KEX_MAC_CLIENT_TO_SERVER],
		    kex->parameters[KEX_MAC_SERVER_TO_CLIENT],
		    kex->parameters[KEX_COMPRESSION_CLIENT_TO_SERVER],
		    kex->parameters[KEX_COMPRESSION_SERVER_TO_CLIENT],
Niels Möller's avatar
Niels Möller committed
144
145
146
147
148
		    kex->languages_client_to_server,
		    kex->languages_server_to_client,
		    kex->first_kex_packet_follows, 0);
}
  
Niels Möller's avatar
Niels Möller committed
149
void
150
initiate_keyexchange(struct ssh_connection *connection)
Niels Möller's avatar
Niels Möller committed
151
{
152
  struct lsh_string *s;
153
154
  int mode = connection->flags & CONNECTION_MODE;
  
155
156
  struct kexinit *kex = connection->kexinits[mode];

157
  assert(kex->first_kex_packet_follows == !!kex->first_kex_packet);
158
159
  assert(connection->kex_state == KEX_STATE_INIT);
	 
Niels Möller's avatar
Niels Möller committed
160
161
162
  s = format_kex(kex);

  /* Save value for later signing */
Niels Möller's avatar
Niels Möller committed
163
#if 0
164
  debug("initiate_keyexchange: Storing literal_kexinits[%i]\n", mode);
Niels Möller's avatar
Niels Möller committed
165
166
#endif
  
167
  connection->literal_kexinits[mode] = s; 
Niels Möller's avatar
Niels Möller committed
168

Niels Möller's avatar
Niels Möller committed
169
  C_WRITE(connection, lsh_string_dup(s));
170

Niels Möller's avatar
Niels Möller committed
171
172
173
174
  if (kex->first_kex_packet_follows)
    {
      s = kex->first_kex_packet;
      kex->first_kex_packet = NULL;
175

Niels Möller's avatar
Niels Möller committed
176
177
      C_WRITE(connection, s);
    }
Niels Möller's avatar
Niels Möller committed
178
179
}

180
static int
181
182
select_algorithm(struct int_list *client_list,
		 struct int_list *server_list)
Niels Möller's avatar
Niels Möller committed
183
184
{
  /* FIXME: This quadratic complexity algorithm should do as long as
185
   * the lists are short. To avoid DOS-attacks, there should probably
186
187
   * be some limit on the list lengths. */
  unsigned i, j;
Niels Möller's avatar
Niels Möller committed
188

189
  for(i = 0; i < LIST_LENGTH(client_list); i++)
Niels Möller's avatar
Niels Möller committed
190
    {
191
192
      int a = LIST(client_list)[i];
      if (!a)
Niels Möller's avatar
Niels Möller committed
193
194
	/* Unknown algorithm */
	continue;
195
196
197
      for(j = 0; j < LIST_LENGTH(server_list); j++)
	if (a == LIST(server_list)[j])
	  return a;
Niels Möller's avatar
Niels Möller committed
198
199
200
201
202
    }

  return 0;
}

203
204
void
disconnect_kex_failed(struct ssh_connection *connection, const char *msg)
Niels Möller's avatar
Niels Möller committed
205
{
Niels Möller's avatar
Niels Möller committed
206
207
208
209
  EXCEPTION_RAISE
    (connection->e,
     make_protocol_exception(SSH_DISCONNECT_KEY_EXCHANGE_FAILED,
			     msg));
Niels Möller's avatar
Niels Möller committed
210
211
}

Niels Möller's avatar
Niels Möller committed
212
213
214
215
static void
do_handle_kexinit(struct packet_handler *c,
		  struct ssh_connection *connection,
		  struct lsh_string *packet)
Niels Möller's avatar
Niels Möller committed
216
{
217
  CAST(kexinit_handler, closure, c);
218
  
Niels Möller's avatar
Niels Möller committed
219
220
  int kex_algorithm_atom;
  int hostkey_algorithm_atom;
Niels Möller's avatar
Niels Möller committed
221
222

  int parameters[KEX_PARAMETERS];
223
  struct object_list *algorithms;
Niels Möller's avatar
Niels Möller committed
224

225
  int mode = connection->flags & CONNECTION_MODE;
226
  struct kexinit *msg = parse_kexinit(packet);
227
  
Niels Möller's avatar
Niels Möller committed
228
  int i;
229

230
231
232
233
234
235
  if (connection->kex_state != KEX_STATE_INIT)
    {
      PROTOCOL_ERROR(connection->e, "Unexpected KEXINIT message.");
      return;
    }      
  
Niels Möller's avatar
Niels Möller committed
236
  if (!msg)
Niels Möller's avatar
Niels Möller committed
237
    {
238
      disconnect_kex_failed(connection, "Invalid KEXINIT message.");
Niels Möller's avatar
Niels Möller committed
239
240
      return;
    }
Niels Möller's avatar
Niels Möller committed
241

242
243
244
245
246
247
248
  if (!LIST_LENGTH(msg->kex_algorithms))
    {
      disconnect_kex_failed(connection, "No keyexchange method.");
      return;
    }
    
    
Niels Möller's avatar
Niels Möller committed
249
  /* Save value for later signing */
Niels Möller's avatar
Niels Möller committed
250
251
252
#if 0
  debug("do_handle_kexinit: Storing literal_kexinits[%i]\n", !mode);
#endif
253
  connection->literal_kexinits[!mode] = packet;
Niels Möller's avatar
Niels Möller committed
254
  
255
  connection->kexinits[!mode] = msg;
Niels Möller's avatar
Niels Möller committed
256
  
257
  /* Have we sent a kexinit message already? */
258
  if (!connection->kexinits[mode])
Niels Möller's avatar
Niels Möller committed
259
    {
Niels Möller's avatar
Niels Möller committed
260
      struct lsh_string *packet;
261
      struct kexinit *sent = MAKE_KEXINIT(closure->init);
262
      connection->kexinits[mode] = sent;
Niels Möller's avatar
Niels Möller committed
263
      packet = format_kex(sent);
Niels Möller's avatar
Niels Möller committed
264
265
266
#if 0
      debug("do_handle_kexinit: Storing literal_kexinits[%i]\n", mode);
#endif
267
      connection->literal_kexinits[mode] = lsh_string_dup(packet); 
Niels Möller's avatar
Niels Möller committed
268
      
Niels Möller's avatar
Niels Möller committed
269
      C_WRITE(connection, packet);
Niels Möller's avatar
Niels Möller committed
270
271
272
273
    }

  /* Select key exchange algorithms */

Niels Möller's avatar
Niels Möller committed
274
  /* FIXME: Look at the hostkey algorithm as well. */
275
276
  if (LIST(connection->kexinits[CONNECTION_CLIENT]->kex_algorithms)[0]
      == LIST(connection->kexinits[CONNECTION_SERVER]->kex_algorithms)[0])
Niels Möller's avatar
Niels Möller committed
277
278
    {
      /* Use this algorithm */
279
280
281
      kex_algorithm_atom
	= LIST(connection->kexinits[CONNECTION_CLIENT]->kex_algorithms)[0];

282
      connection->kex_state = KEX_STATE_IN_PROGRESS;
Niels Möller's avatar
Niels Möller committed
283
284
285
286
287
288
    }
  else
    {
      if (msg->first_kex_packet_follows)
	{
	  /* Wrong guess */
289
	  connection->kex_state = KEX_STATE_IGNORE;
Niels Möller's avatar
Niels Möller committed
290
	}
291
292

      /* FIXME: Ignores that some keyexchange algorithms require
Niels Möller's avatar
Niels Möller committed
293
294
       * certain features of the host key algorithms. */
      
Niels Möller's avatar
Niels Möller committed
295
      kex_algorithm_atom
296
297
	= select_algorithm(connection->kexinits[CONNECTION_CLIENT]->kex_algorithms,
			   connection->kexinits[CONNECTION_SERVER]->kex_algorithms);
298

299
      /* FIXME: This is actually ok for SRP. */
Niels Möller's avatar
Niels Möller committed
300
      if  (!kex_algorithm_atom)
Niels Möller's avatar
Niels Möller committed
301
	{
302
303
	  disconnect_kex_failed(connection,
				"No common key exchange method.\r\n");
Niels Möller's avatar
Niels Möller committed
304
	  return;
Niels Möller's avatar
Niels Möller committed
305
	}
306
    }
307
  
Niels Möller's avatar
Niels Möller committed
308
  hostkey_algorithm_atom
309
310
    = select_algorithm(connection->kexinits[CONNECTION_CLIENT]->server_hostkey_algorithms,
		       connection->kexinits[CONNECTION_SERVER]->server_hostkey_algorithms);
311

312
313
314
315
316
  if (!hostkey_algorithm_atom)
    {
      disconnect_kex_failed(connection, "No common hostkey algorithm.\r\n");
      return;
    }
317
318
319
320
321

  verbose("Selected keyexchange algorithm: %a\n"
	  "  with hostkey algorithm:       %a\n",
	  kex_algorithm_atom, hostkey_algorithm_atom);
    
322
323
324
  for(i = 0; i<KEX_PARAMETERS; i++)
    {
      parameters[i]
325
326
	= select_algorithm(connection->kexinits[CONNECTION_CLIENT]->parameters[i],
			   connection->kexinits[CONNECTION_SERVER]->parameters[i]);
327
328
329
      
      if (!parameters[i])
	{
330
	  disconnect_kex_failed(connection, "Algorithm negotiation failed.");
Niels Möller's avatar
Niels Möller committed
331
	  return;
Niels Möller's avatar
Niels Möller committed
332
	}
333
    }
334
335
336
337
338
339
340
341

  verbose("Selected bulk algorithms: (client to server, server to client)\n"
	  "  Encryption:             (%a, %a)\n"
	  "  Message authentication: (%a, %a)\n"
	  "  Compression:            (%a, %a)\n",
	  parameters[0], parameters[1],
	  parameters[2], parameters[3], 
	  parameters[4], parameters[5]);
342
  
343
  algorithms = alloc_object_list(KEX_PARAMETERS);
344
345
  
  for (i = 0; i<KEX_PARAMETERS; i++)
346
    LIST(algorithms)[i] = ALIST_GET(closure->algorithms, parameters[i]);
Niels Möller's avatar
Niels Möller committed
347
348
349
350

  {
    CAST_SUBTYPE(keyexchange_algorithm, kex_algorithm,
		 ALIST_GET(closure->algorithms, kex_algorithm_atom));
351

Niels Möller's avatar
Niels Möller committed
352
353
354
    KEYEXCHANGE_INIT( kex_algorithm,
		      connection,
		      hostkey_algorithm_atom,
355
		      closure->extra, /* hostkey_algorithm, */
Niels Möller's avatar
Niels Möller committed
356
357
		      algorithms);
  }
358
}
Niels Möller's avatar
Niels Möller committed
359

360
struct packet_handler *
361
make_kexinit_handler(struct make_kexinit *init,
362
363
		     struct lsh_object *extra,
		     struct alist *algorithms)
364
{
365
  NEW(kexinit_handler, self);
Niels Möller's avatar
Niels Möller committed
366

367
  self->super.handler = do_handle_kexinit;
368

369
  self->init = init;
370
  self->extra = extra;
371
  self->algorithms = algorithms;
372
  
373
  return &self->super;
Niels Möller's avatar
Niels Möller committed
374
375
}

376
377
#define IV_TYPE(t) ((t) + 4)

Niels Möller's avatar
Niels Möller committed
378
379
380
381
382
static struct lsh_string *
kex_make_key(struct hash_instance *secret,
	     UINT32 key_length,
	     int type,
	     struct lsh_string *session_id)
383
384
{
  /* Indexed by the KEX_* values */
Niels Möller's avatar
Niels Möller committed
385
  static const UINT8 tags[] = "CDEFAB";
386
387
388
389
390
391
392
  
  struct lsh_string *key;
  struct hash_instance *hash;
  UINT8 *digest;
  
  key = lsh_string_alloc(key_length);

393
  debug("\nConstructing session key of type %i\n", type);
394
  
395
396
397
398
  if (!key_length)
    return key;
  
  hash = HASH_COPY(secret);
399
  digest = alloca(hash->hash_size);
400

401
  HASH_UPDATE(hash, 1, tags + type); 
402
403
404
  HASH_UPDATE(hash, session_id->length, session_id->data);
  HASH_DIGEST(hash, digest);

405
  /* Is one digest large anough? */
406
407
  if (key_length <= hash->hash_size)
    memcpy(key->data, digest, key_length);
408
409
410
411
412
413
414
415
416

  else
    {
      unsigned left = key_length;
      UINT8 *dst = key->data;
      
      KILL(hash);
      hash = HASH_COPY(secret);
      
Niels Möller's avatar
Niels Möller committed
417
      for (;;)
418
419
420
421
422
423
424
425
426
	{
	  /* The n:th time we enter this loop, digest holds K_n (using
	   * the notation of section 5.2 of the ssh "transport"
	   * specification), and hash contains the hash state
	   * corresponding to
	   *
	   * H(secret | K_1 | ... | K_{n-1}) */

	  struct hash_instance *tmp;
427
	  
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
	  /* Append digest to the key data. */
	  memcpy(dst, digest, hash->hash_size);
	  dst += hash->hash_size;
	  left -= hash->hash_size;

	  /* And to the hash state */
	  HASH_UPDATE(hash, hash->hash_size, digest);

	  if (left <= hash->hash_size)
	    break;
	  
	  /* Get a new digest, without disturbing the hash object (as
	   * we'll need it again). We use another temporary hash for
	   * extracting the digest. */

	  tmp = HASH_COPY(hash);
	  HASH_DIGEST(tmp, digest);
	  KILL(tmp);
	}

      /* Get the final digest, and use some of it for the key. */
      HASH_DIGEST(hash, digest);
      memcpy(dst, digest, left);
    }
452
  KILL(hash);
453

454
455
456
  debug("Expanded key: %xs",
	key->length, key->data);

457
458
459
  return key;
}
  
Niels Möller's avatar
Niels Möller committed
460
461
462
463
464
struct crypto_instance *
kex_make_encrypt(struct hash_instance *secret,
		 struct object_list *algorithms,
		 int type,
		 struct lsh_string *session_id)
465
{
466
467
  CAST_SUBTYPE(crypto_algorithm, algorithm, LIST(algorithms)[type]);
    
468
  struct lsh_string *key;
469
  struct lsh_string *iv = NULL;
470
  struct crypto_instance *crypto;
471
472
473

  assert(LIST_LENGTH(algorithms) == KEX_PARAMETERS);

474
475
476
477
  if (!algorithm)
    return NULL;

  key = kex_make_key(secret, algorithm->key_size,
478
		     type, session_id);
479

480
481
482
483
484
485
  if (algorithm->iv_size)
    iv = kex_make_key(secret, algorithm->iv_size,
		      IV_TYPE(type), session_id);
  
  crypto = MAKE_ENCRYPT(algorithm, key->data,
			iv ? iv->data : NULL);
486
487

  lsh_string_free(key);
488
489
  lsh_string_free(iv);
  
490
  return crypto;
491
492
}

Niels Möller's avatar
Niels Möller committed
493
494
495
496
497
struct crypto_instance *
kex_make_decrypt(struct hash_instance *secret,
		 struct object_list *algorithms,
		 int type,
		 struct lsh_string *session_id)
498
{
499
500
  CAST_SUBTYPE(crypto_algorithm, algorithm, LIST(algorithms)[type]);

501
  struct lsh_string *key;
502
  struct lsh_string *iv = NULL;
503
  struct crypto_instance *crypto;
504
505
506

  assert(LIST_LENGTH(algorithms) == KEX_PARAMETERS);

507
508
509
510
  if (!algorithm)
    return NULL;
  
  key = kex_make_key(secret, algorithm->key_size,
511
		     type, session_id);
512

513
514
515
516
517
  if (algorithm->iv_size)
    iv = kex_make_key(secret, algorithm->iv_size,
		      IV_TYPE(type), session_id);
  
  crypto = MAKE_DECRYPT(algorithm, key->data, iv ? iv->data : NULL);
518
519

  lsh_string_free(key);
520
521
  lsh_string_free(iv);
  
522
  return crypto;
523
524
}

Niels Möller's avatar
Niels Möller committed
525
526
527
528
529
struct mac_instance *
kex_make_mac(struct hash_instance *secret,
	     struct object_list *algorithms,
	     int type,
	     struct lsh_string *session_id)
530
{
Niels Möller's avatar
Niels Möller committed
531
  CAST_SUBTYPE(mac_algorithm, algorithm, LIST(algorithms)[type]);
532

533
534
535
  struct mac_instance *mac;
  struct lsh_string *key;

536
537
  assert(LIST_LENGTH(algorithms) == KEX_PARAMETERS);
  
538
539
  if (!algorithm)
    return NULL;
540

541
  key = kex_make_key(secret, algorithm->key_size,
542
		     type, session_id);
543

544
  mac = MAKE_MAC(algorithm, algorithm->key_size, key->data);
545
546
547
548
549

  lsh_string_free(key);
  return mac;
}

Niels Möller's avatar
Niels Möller committed
550
551
552
static struct compress_instance *
kex_make_deflate(struct object_list *algorithms,
		 int type)
553
554
555
556
557
558
{
  CAST_SUBTYPE(compress_algorithm, algorithm, LIST(algorithms)[type]);
  
  return algorithm ? MAKE_DEFLATE(algorithm) : NULL;
}

Niels Möller's avatar
Niels Möller committed
559
560
561
static struct compress_instance *
kex_make_inflate(struct object_list *algorithms,
		 int type)
562
563
564
565
566
567
{
  CAST_SUBTYPE(compress_algorithm, algorithm, LIST(algorithms)[type]);

  return algorithm ? MAKE_INFLATE(algorithm) : NULL;
}

568
/* GABA:
569
570
571
572
573
   (class
     (name newkeys_handler)
     (super packet_handler)
     (vars
       (crypto object crypto_instance)
574
575
       (mac object mac_instance)
       (compression object compress_instance)))
576
577
*/

Niels Möller's avatar
Niels Möller committed
578
579
580
581
static void
do_handle_newkeys(struct packet_handler *c,
		  struct ssh_connection *connection,
		  struct lsh_string *packet)
Niels Möller's avatar
Niels Möller committed
582
{
583
  CAST(newkeys_handler, closure, c);
584
  struct simple_buffer buffer;
Niels Möller's avatar
Niels Möller committed
585
  unsigned msg_number;
586
587
588
589
590
591
592
593
594

  simple_buffer_init(&buffer, packet->length, packet->data);

  if (parse_uint8(&buffer, &msg_number)
      && (msg_number == SSH_MSG_NEWKEYS)
      && (parse_eod(&buffer)))
    {
      connection->rec_crypto = closure->crypto;
      connection->rec_mac = closure->mac;
595
      connection->rec_compress = closure->compression;
596

597
598
      connection->kex_state = KEX_STATE_INIT;

599
600
601
      connection->kexinits[CONNECTION_CLIENT]
	= connection->kexinits[CONNECTION_SERVER] = NULL;

602
603
604
605
606
607
      lsh_string_free(connection->literal_kexinits[CONNECTION_CLIENT]);
      lsh_string_free(connection->literal_kexinits[CONNECTION_SERVER]);
      
      connection->literal_kexinits[CONNECTION_CLIENT]
	= connection->literal_kexinits[CONNECTION_SERVER] = NULL;

608
609
      connection->dispatch[SSH_MSG_NEWKEYS] = NULL;

610
      KILL(closure);
611
612
    }
  else
613
    PROTOCOL_ERROR(connection->e, "Invalid NEWKEYS message");
Niels Möller's avatar
Niels Möller committed
614
  lsh_string_free(packet);
615
616
}

Niels Möller's avatar
Niels Möller committed
617
struct packet_handler *
618
make_newkeys_handler(struct crypto_instance *crypto,
619
620
		     struct mac_instance *mac,
		     struct compress_instance *compression)
Niels Möller's avatar
Niels Möller committed
621
{
622
  NEW(newkeys_handler,self);
623
624
625
626

  self->super.handler = do_handle_newkeys;
  self->crypto = crypto;
  self->mac = mac;
627
  self->compression = compression;
Niels Möller's avatar
Niels Möller committed
628

629
630
  return &self->super;
}
631

632
/* Uses the same algorithms for both directions */
633
/* GABA:
634
635
636
637
638
639
640
641
642
643
644
645
646
   (class
     (name simple_kexinit)
     (super make_kexinit)
     (vars
       (r object randomness)
       (kex_algorithms object int_list)
       (hostkey_algorithms object int_list)
       (crypto_algorithms object int_list)
       (mac_algorithms object int_list)
       (compression_algorithms object int_list)
       (languages object int_list)))
*/

647
static struct kexinit *
648
do_make_simple_kexinit(struct make_kexinit *c)
649
650
{
  CAST(simple_kexinit, closure, c);
651
652
653
654
655
656
657
658
659
660
661
662
663
  NEW(kexinit, kex);

  RANDOM(closure->r, 16, kex->cookie);

  kex->kex_algorithms = closure->kex_algorithms;
  kex->server_hostkey_algorithms = closure->hostkey_algorithms;
  kex->parameters[KEX_ENCRYPTION_CLIENT_TO_SERVER]
    = closure->crypto_algorithms;
  kex->parameters[KEX_ENCRYPTION_SERVER_TO_CLIENT]
    = closure->crypto_algorithms;
  kex->parameters[KEX_MAC_CLIENT_TO_SERVER] = closure->mac_algorithms;
  kex->parameters[KEX_MAC_SERVER_TO_CLIENT] = closure->mac_algorithms;
  kex->parameters[KEX_COMPRESSION_CLIENT_TO_SERVER]
664
    = closure->compression_algorithms;
665
  kex->parameters[KEX_COMPRESSION_SERVER_TO_CLIENT]
666
    = closure->compression_algorithms;
667
668
669
  kex->languages_client_to_server = closure->languages;
  kex->languages_server_to_client = closure->languages;
  kex->first_kex_packet_follows = 0;
670

671
672
673
  kex->first_kex_packet = NULL;

  return kex;
674
675
}

Niels Möller's avatar
Niels Möller committed
676
677
678
679
680
681
682
683
struct make_kexinit *
make_simple_kexinit(struct randomness *r,
		    struct int_list *kex_algorithms,
		    struct int_list *hostkey_algorithms,
		    struct int_list *crypto_algorithms,
		    struct int_list *mac_algorithms,
		    struct int_list *compression_algorithms,
		    struct int_list *languages)
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
{
  NEW(simple_kexinit, res);

  res->super.make = do_make_simple_kexinit;
  res->r = r;
  res->kex_algorithms = kex_algorithms;
  res->hostkey_algorithms = hostkey_algorithms;
  res->crypto_algorithms = crypto_algorithms;
  res->mac_algorithms = mac_algorithms;
  res->compression_algorithms = compression_algorithms;
  res->languages = languages;

  return &res->super;
}

699

700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
/* FIXME: Move this to a separate file keyexchange_commands.c? */
/* (kexinit_filter simple_kexinit alist)
 *
 * Destructively modifies the simple_kexinit to include only hostkey
 * algorithms that have keys in alist. */

/* GABA:
   (class
     (name kexinit_filter_command)
     (super command)
     (vars
       (init object simple_kexinit)))
*/

static void
do_kexinit_filter(struct command *s,
		  struct lsh_object *x,
		  struct command_continuation *c,
		  struct exception_handler *e UNUSED)
{
  CAST(kexinit_filter_command, self, s);
  CAST_SUBTYPE(alist, keys, x);

Niels Möller's avatar
Niels Möller committed
723
724
  self->init->hostkey_algorithms
    = filter_algorithms(keys, self->init->hostkey_algorithms);
725

726
  if (!self->init->hostkey_algorithms)
727
728
729
730
    {
      werror("No hostkey algorithms advertised.\n");
      self->init->hostkey_algorithms = make_int_list(1, ATOM_NONE, -1);
    }
731
732
733

  assert(LIST_LENGTH(self->init->hostkey_algorithms));

734
735
736
  COMMAND_RETURN(c, self->init);
}

737
DEFINE_COMMAND_SIMPLE(kexinit_filter, a)
738
739
740
741
742
743
744
745
746
747
748
{
  CAST(simple_kexinit, init, a);
  NEW(kexinit_filter_command, self);

  self->super.call = do_kexinit_filter;
  self->init = init;

  return &self->super.super;
}


Niels Möller's avatar
Niels Möller committed
749
static int
750
751
752
install_keys(struct object_list *algorithms,
	     struct ssh_connection *connection,
	     struct hash_instance *secret)
753
754
755
{
  struct crypto_instance *rec;
  struct crypto_instance *send;
756
  int is_server = connection->flags & CONNECTION_SERVER;
757

758
759
760
761
  assert(LIST_LENGTH(algorithms) == KEX_PARAMETERS);
  
  rec = kex_make_decrypt(secret, algorithms,
			 KEX_ENCRYPTION_SERVER_TO_CLIENT ^ is_server,
762
763
764
765
766
			 connection->session_id);
  if (!rec)
    /* Weak or invalid key */
    return 0;

767
768
  send = kex_make_encrypt(secret, algorithms,
			  KEX_ENCRYPTION_CLIENT_TO_SERVER ^ is_server,
769
770
771
772
773
774
775
			  connection->session_id);
  if (!send)
    {
      KILL(rec);
      return 0;
    }
  
Niels Möller's avatar
Niels Möller committed
776
  /* Keys for receiving */
777
778
  connection->dispatch[SSH_MSG_NEWKEYS] = make_newkeys_handler
    (rec,
779
780
     kex_make_mac(secret, algorithms,
		  KEX_MAC_SERVER_TO_CLIENT ^ is_server,
781
		  connection->session_id),
782
783
     kex_make_inflate(algorithms,
		      KEX_COMPRESSION_SERVER_TO_CLIENT ^ is_server));
784
785
786
787
788
789
790

  /* Keys for sending */
  /* NOTE: The NEWKEYS-message should have been sent before this
   * is done. */
  connection->send_crypto = send;
  
  connection->send_mac 
791
792
    = kex_make_mac(secret, algorithms,
		   KEX_MAC_CLIENT_TO_SERVER ^ is_server,
793
		   connection->session_id);
794

795
  connection->send_compress
796
797
    = kex_make_deflate(algorithms,
		       KEX_COMPRESSION_CLIENT_TO_SERVER ^ is_server);
798
  
799
800
801
  return 1;
}

802

803
804
805
/* Returns a hash instance for generating various session keys. NOTE:
 * This mechanism changed in the transport-05 draft. Before this, the
 * exchange hash was not included at this point. */
806
static struct hash_instance *
807
808
kex_build_secret(struct hash_algorithm *H,
		 struct lsh_string *exchange_hash,
809
		 struct lsh_string *K)
810
{
811
812
813
  /* We include a length field for the key, but not for the exchange
   * hash. */
  
814
  struct hash_instance *hash = MAKE_HASH(H);
815
  struct lsh_string *s = ssh_format("%S%lS", K, exchange_hash);
816

817
818
  HASH_UPDATE(hash, s->length, s->data);
  lsh_string_free(s);
819
820
821
822
  
  return hash;
}

823
/* NOTE: Consumes both the exchange_hash and K */
824
825
void
keyexchange_finish(struct ssh_connection *connection,
826
		   struct object_list *algorithms,
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
		   struct hash_algorithm *H,
		   struct lsh_string *exchange_hash,
		   struct lsh_string *K)
{
  struct hash_instance *hash;
  
  /* Send a newkeys message, and install a handler for receiving the
   * newkeys message. */

  C_WRITE(connection, ssh_format("%c", SSH_MSG_NEWKEYS));

  /* A hash instance initialized with the key, to be used for key
   * generation */
  hash = kex_build_secret(H, exchange_hash, K);
  lsh_string_free(K);
  
  /* Record session id */
  if (!connection->session_id)
    connection->session_id = exchange_hash;
  else
    lsh_string_free(exchange_hash);
  
849
  if (!install_keys(algorithms, connection, hash))
850
851
852
853
854
    {
      werror("Installing new keys failed. Hanging up.\n");
      KILL(hash);

      PROTOCOL_ERROR(connection->e, "Refusing to use weak key.");
855

856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
      return;
    }

  KILL(hash);

  connection->kex_state = KEX_STATE_NEWKEYS;

#if DATAFELLOWS_WORKAROUNDS
  if (! (connection->peer_flags & PEER_SEND_NO_DEBUG))
#endif
    send_verbose(connection->write, "Key exchange successful!", 0);

  if (connection->established)
    {
      struct command_continuation *c = connection->established;
      connection->established = NULL;
  
      COMMAND_RETURN(c, connection);
    }
}