keyexchange.c 23.1 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 Möller
 *
 * 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 "format.h"
Niels Möller's avatar
Niels Möller committed
34
#include "parse.h"
Niels Möller's avatar
Niels Möller committed
35
#include "publickey_crypto.h"
36
#include "ssh.h"
37
#include "werror.h"
38
#include "xalloc.h"
Niels Möller's avatar
Niels Möller committed
39

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

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

#include "keyexchange.c.x"

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

56
57
58
       ; Extra rgument for the KEYEXCHANGE_INIT call.
       (extra object lsh_object)
       
59
60
61
62
63
       ; 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.
64
       (algorithms object alist)))
65
*/
66

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

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

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

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

92
  if (!parse_octets(&buffer, 16, res->cookie))
Niels Möller's avatar
Niels Möller committed
93
    {
94
      KILL(res);
Niels Möller's avatar
Niels Möller committed
95
96
97
98
99
      return NULL;
    }
  
  for (i = 0; i<NLISTS; i++)
    {
100
      if ( !(lists[i] = parse_atom_list(&buffer, KEXINIT_MAX_ALGORITMS)))
Niels Möller's avatar
Niels Möller committed
101
102
103
104
105
106
107
108
109
110
111
	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++)
112
113
	KILL(lists[i]);
      KILL(res);
Niels Möller's avatar
Niels Möller committed
114
115
116
      return NULL;
    }
  
117
  res->kex_algorithms = lists[0];
118
  res->server_hostkey_algorithms = lists[1];
Niels Möller's avatar
Niels Möller committed
119
120
121
122

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

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

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

Niels Möller's avatar
Niels Möller committed
129
130
struct lsh_string *
format_kex(struct kexinit *kex)
Niels Möller's avatar
Niels Möller committed
131
132
133
134
135
{
  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,
136
		    kex->server_hostkey_algorithms,
Niels Möller's avatar
Niels Möller committed
137
138
139
140
141
142
		    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
143
144
145
146
147
		    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
148
void
149
send_kexinit(struct ssh_connection *connection)
Niels Möller's avatar
Niels Möller committed
150
{
151
  struct lsh_string *s;
152
  int mode = connection->flags & CONNECTION_MODE;
153

154
155
  struct kexinit *kex = connection->kexinits[mode];
  
156
  assert(kex->first_kex_packet_follows == !!kex->first_kex_packet);
Niels Möller's avatar
Niels Möller committed
157
  assert(connection->read_kex_state == KEX_STATE_INIT);
158
159
160
161

  /* First, disable any key reexchange timer */
  if (connection->key_expire)
    KILL_RESOURCE(connection->key_expire);
Niels Möller's avatar
Niels Möller committed
162
  
Niels Möller's avatar
Niels Möller committed
163
164
165
  s = format_kex(kex);

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

Niels Möller's avatar
Niels Möller committed
173
  C_WRITE_NOW(connection, lsh_string_dup(s));
174

175
176
  /* NOTE: This feature isn't fully implemented, as we won't tell
   * the selected key exchange method if the guess was "right". */
Niels Möller's avatar
Niels Möller committed
177
178
179
180
  if (kex->first_kex_packet_follows)
    {
      s = kex->first_kex_packet;
      kex->first_kex_packet = NULL;
181

Niels Möller's avatar
Niels Möller committed
182
      C_WRITE_NOW(connection, s);
Niels Möller's avatar
Niels Möller committed
183
    }
Niels Möller's avatar
Niels Möller committed
184
185
}

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

195
  for(i = 0; i < LIST_LENGTH(client_list); i++)
Niels Möller's avatar
Niels Möller committed
196
    {
197
198
      int a = LIST(client_list)[i];
      if (!a)
Niels Möller's avatar
Niels Möller committed
199
200
	/* Unknown algorithm */
	continue;
201
202
203
      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
204
205
206
207
208
    }

  return 0;
}

209
210
void
disconnect_kex_failed(struct ssh_connection *connection, const char *msg)
Niels Möller's avatar
Niels Möller committed
211
{
Niels Möller's avatar
Niels Möller committed
212
213
214
215
  EXCEPTION_RAISE
    (connection->e,
     make_protocol_exception(SSH_DISCONNECT_KEY_EXCHANGE_FAILED,
			     msg));
Niels Möller's avatar
Niels Möller committed
216
217
}

Niels Möller's avatar
Niels Möller committed
218
219
220
221
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
222
{
223
  CAST(kexinit_handler, closure, c);
224
  
Niels Möller's avatar
Niels Möller committed
225
226
  int kex_algorithm_atom;
  int hostkey_algorithm_atom;
Niels Möller's avatar
Niels Möller committed
227
228

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

231
  int mode = connection->flags & CONNECTION_MODE;
232
  struct kexinit *msg = parse_kexinit(packet);
233

Niels Möller's avatar
Niels Möller committed
234
  int i;
235

236
237
  verbose("Received KEXINIT message. Key exchange initated.\n");
  
Niels Möller's avatar
Niels Möller committed
238
  if (connection->read_kex_state != KEX_STATE_INIT)
239
240
241
242
243
    {
      PROTOCOL_ERROR(connection->e, "Unexpected KEXINIT message.");
      return;
    }      
  
Niels Möller's avatar
Niels Möller committed
244
  if (!msg)
Niels Möller's avatar
Niels Möller committed
245
    {
246
      disconnect_kex_failed(connection, "Invalid KEXINIT message.");
Niels Möller's avatar
Niels Möller committed
247
248
      return;
    }
Niels Möller's avatar
Niels Möller committed
249

250
251
252
253
254
255
256
  if (!LIST_LENGTH(msg->kex_algorithms))
    {
      disconnect_kex_failed(connection, "No keyexchange method.");
      return;
    }
    
    
Niels Möller's avatar
Niels Möller committed
257
  /* Save value for later signing */
Niels Möller's avatar
Niels Möller committed
258
259
260
#if 0
  debug("do_handle_kexinit: Storing literal_kexinits[%i]\n", !mode);
#endif
261
  connection->literal_kexinits[!mode] = lsh_string_dup(packet);
Niels Möller's avatar
Niels Möller committed
262
  
263
  connection->kexinits[!mode] = msg;
Niels Möller's avatar
Niels Möller committed
264
  
265
  /* Have we sent a kexinit message already? */
266
  if (!connection->kexinits[mode])
Niels Möller's avatar
Niels Möller committed
267
    {
268
269
270
      connection->kexinits[mode] = MAKE_KEXINIT(closure->init);
      send_kexinit(connection);
#if 0
Niels Möller's avatar
Niels Möller committed
271
      struct lsh_string *packet;
272
      struct kexinit *sent = MAKE_KEXINIT(closure->init);
273
      connection->kexinits[mode] = sent;
Niels Möller's avatar
Niels Möller committed
274
      packet = format_kex(sent);
Niels Möller's avatar
Niels Möller committed
275
276
277
#if 0
      debug("do_handle_kexinit: Storing literal_kexinits[%i]\n", mode);
#endif
278
      connection->literal_kexinits[mode] = lsh_string_dup(packet); 
Niels Möller's avatar
Niels Möller committed
279
      
Niels Möller's avatar
Niels Möller committed
280
281
      connection_send_kex_start(connection);
      C_WRITE_NOW(connection, packet);
282
#endif
Niels Möller's avatar
Niels Möller committed
283
284
285
286
    }

  /* Select key exchange algorithms */

Niels Möller's avatar
Niels Möller committed
287
  /* FIXME: Look at the hostkey algorithm as well. */
288
289
  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
290
291
    {
      /* Use this algorithm */
292
293
294
      kex_algorithm_atom
	= LIST(connection->kexinits[CONNECTION_CLIENT]->kex_algorithms)[0];

Niels Möller's avatar
Niels Möller committed
295
      connection->read_kex_state = KEX_STATE_IN_PROGRESS;
Niels Möller's avatar
Niels Möller committed
296
297
298
299
300
301
    }
  else
    {
      if (msg->first_kex_packet_follows)
	{
	  /* Wrong guess */
Niels Möller's avatar
Niels Möller committed
302
	  connection->read_kex_state = KEX_STATE_IGNORE;
Niels Möller's avatar
Niels Möller committed
303
	}
304
305

      /* FIXME: Ignores that some keyexchange algorithms require
Niels Möller's avatar
Niels Möller committed
306
307
       * certain features of the host key algorithms. */
      
Niels Möller's avatar
Niels Möller committed
308
      kex_algorithm_atom
309
310
	= select_algorithm(connection->kexinits[CONNECTION_CLIENT]->kex_algorithms,
			   connection->kexinits[CONNECTION_SERVER]->kex_algorithms);
311

312
      /* FIXME: This is actually ok for SRP. */
Niels Möller's avatar
Niels Möller committed
313
      if  (!kex_algorithm_atom)
Niels Möller's avatar
Niels Möller committed
314
	{
315
316
	  disconnect_kex_failed(connection,
				"No common key exchange method.\r\n");
Niels Möller's avatar
Niels Möller committed
317
	  return;
Niels Möller's avatar
Niels Möller committed
318
	}
319
    }
320
  
Niels Möller's avatar
Niels Möller committed
321
  hostkey_algorithm_atom
322
323
    = select_algorithm(connection->kexinits[CONNECTION_CLIENT]->server_hostkey_algorithms,
		       connection->kexinits[CONNECTION_SERVER]->server_hostkey_algorithms);
324

325
326
327
328
329
  if (!hostkey_algorithm_atom)
    {
      disconnect_kex_failed(connection, "No common hostkey algorithm.\r\n");
      return;
    }
330
331
332
333
334

  verbose("Selected keyexchange algorithm: %a\n"
	  "  with hostkey algorithm:       %a\n",
	  kex_algorithm_atom, hostkey_algorithm_atom);
    
335
336
337
  for(i = 0; i<KEX_PARAMETERS; i++)
    {
      parameters[i]
338
339
	= select_algorithm(connection->kexinits[CONNECTION_CLIENT]->parameters[i],
			   connection->kexinits[CONNECTION_SERVER]->parameters[i]);
340
341
342
      
      if (!parameters[i])
	{
343
	  disconnect_kex_failed(connection, "Algorithm negotiation failed.");
Niels Möller's avatar
Niels Möller committed
344
	  return;
Niels Möller's avatar
Niels Möller committed
345
	}
346
    }
347
348
349
350
351
352
353
354

  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]);
355
  
356
  algorithms = alloc_object_list(KEX_PARAMETERS);
357
358
  
  for (i = 0; i<KEX_PARAMETERS; i++)
359
    LIST(algorithms)[i] = ALIST_GET(closure->algorithms, parameters[i]);
Niels Möller's avatar
Niels Möller committed
360
361
362
363

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

Niels Möller's avatar
Niels Möller committed
365
366
367
    KEYEXCHANGE_INIT( kex_algorithm,
		      connection,
		      hostkey_algorithm_atom,
368
		      closure->extra, /* hostkey_algorithm, */
Niels Möller's avatar
Niels Möller committed
369
370
		      algorithms);
  }
371
}
Niels Möller's avatar
Niels Möller committed
372

373
struct packet_handler *
374
make_kexinit_handler(struct make_kexinit *init,
375
376
		     struct lsh_object *extra,
		     struct alist *algorithms)
377
{
378
  NEW(kexinit_handler, self);
Niels Möller's avatar
Niels Möller committed
379

380
  self->super.handler = do_handle_kexinit;
381

382
  self->init = init;
383
  self->extra = extra;
384
  self->algorithms = algorithms;
385
  
386
  return &self->super;
Niels Möller's avatar
Niels Möller committed
387
388
}

389
390
#define IV_TYPE(t) ((t) + 4)

Niels Möller's avatar
Niels Möller committed
391
392
393
394
395
static struct lsh_string *
kex_make_key(struct hash_instance *secret,
	     UINT32 key_length,
	     int type,
	     struct lsh_string *session_id)
396
397
{
  /* Indexed by the KEX_* values */
Niels Möller's avatar
Niels Möller committed
398
  static const UINT8 tags[] = "CDEFAB";
399
400
401
402
403
404
405
  
  struct lsh_string *key;
  struct hash_instance *hash;
  UINT8 *digest;
  
  key = lsh_string_alloc(key_length);

406
  debug("\nConstructing session key of type %i\n", type);
407
  
408
409
410
  if (!key_length)
    return key;
  
411
412
  hash = hash_copy(secret);
  digest = alloca(HASH_SIZE(hash));
413

414
415
416
  hash_update(hash, 1, tags + type); 
  hash_update(hash, session_id->length, session_id->data);
  hash_digest(hash, digest);
417

418
  /* Is one digest large anough? */
419
  if (key_length <= HASH_SIZE(hash))
420
    memcpy(key->data, digest, key_length);
421
422
423
424
425
426
427

  else
    {
      unsigned left = key_length;
      UINT8 *dst = key->data;
      
      KILL(hash);
428
      hash = hash_copy(secret);
429
      
Niels Möller's avatar
Niels Möller committed
430
      for (;;)
431
432
433
434
435
436
437
438
439
	{
	  /* 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;
440
	  
441
	  /* Append digest to the key data. */
442
443
444
	  memcpy(dst, digest, HASH_SIZE(hash));
	  dst += HASH_SIZE(hash);
	  left -= HASH_SIZE(hash);
445
446

	  /* And to the hash state */
447
	  hash_update(hash, HASH_SIZE(hash), digest);
448

449
	  if (left <= HASH_SIZE(hash))
450
451
452
453
454
455
	    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. */

456
457
	  tmp = hash_copy(hash);
	  hash_digest(tmp, digest);
458
459
460
461
	  KILL(tmp);
	}

      /* Get the final digest, and use some of it for the key. */
462
      hash_digest(hash, digest);
463
464
      memcpy(dst, digest, left);
    }
465
  KILL(hash);
466

467
468
469
  debug("Expanded key: %xs",
	key->length, key->data);

470
471
472
  return key;
}
  
Niels Möller's avatar
Niels Möller committed
473
474
475
476
477
struct crypto_instance *
kex_make_encrypt(struct hash_instance *secret,
		 struct object_list *algorithms,
		 int type,
		 struct lsh_string *session_id)
478
{
479
480
  CAST_SUBTYPE(crypto_algorithm, algorithm, LIST(algorithms)[type]);
    
481
  struct lsh_string *key;
482
  struct lsh_string *iv = NULL;
483
  struct crypto_instance *crypto;
484
485
486

  assert(LIST_LENGTH(algorithms) == KEX_PARAMETERS);

487
488
489
490
  if (!algorithm)
    return NULL;

  key = kex_make_key(secret, algorithm->key_size,
491
		     type, session_id);
492

493
494
495
496
497
498
  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);
499
500

  lsh_string_free(key);
501
502
  lsh_string_free(iv);
  
503
  return crypto;
504
505
}

Niels Möller's avatar
Niels Möller committed
506
507
508
509
510
struct crypto_instance *
kex_make_decrypt(struct hash_instance *secret,
		 struct object_list *algorithms,
		 int type,
		 struct lsh_string *session_id)
511
{
512
513
  CAST_SUBTYPE(crypto_algorithm, algorithm, LIST(algorithms)[type]);

514
  struct lsh_string *key;
515
  struct lsh_string *iv = NULL;
516
  struct crypto_instance *crypto;
517
518
519

  assert(LIST_LENGTH(algorithms) == KEX_PARAMETERS);

520
521
522
523
  if (!algorithm)
    return NULL;
  
  key = kex_make_key(secret, algorithm->key_size,
524
		     type, session_id);
525

526
527
528
529
530
  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);
531
532

  lsh_string_free(key);
533
534
  lsh_string_free(iv);
  
535
  return crypto;
536
537
}

Niels Möller's avatar
Niels Möller committed
538
539
540
541
542
struct mac_instance *
kex_make_mac(struct hash_instance *secret,
	     struct object_list *algorithms,
	     int type,
	     struct lsh_string *session_id)
543
{
Niels Möller's avatar
Niels Möller committed
544
  CAST_SUBTYPE(mac_algorithm, algorithm, LIST(algorithms)[type]);
545

546
547
548
  struct mac_instance *mac;
  struct lsh_string *key;

549
550
  assert(LIST_LENGTH(algorithms) == KEX_PARAMETERS);
  
551
552
  if (!algorithm)
    return NULL;
553

554
  key = kex_make_key(secret, algorithm->key_size,
555
		     type, session_id);
556

557
  mac = MAKE_MAC(algorithm, algorithm->key_size, key->data);
558
559
560
561
562

  lsh_string_free(key);
  return mac;
}

Niels Möller's avatar
Niels Möller committed
563
564
565
static struct compress_instance *
kex_make_deflate(struct object_list *algorithms,
		 int type)
566
567
568
569
570
571
{
  CAST_SUBTYPE(compress_algorithm, algorithm, LIST(algorithms)[type]);
  
  return algorithm ? MAKE_DEFLATE(algorithm) : NULL;
}

Niels Möller's avatar
Niels Möller committed
572
573
574
static struct compress_instance *
kex_make_inflate(struct object_list *algorithms,
		 int type)
575
576
577
578
579
580
{
  CAST_SUBTYPE(compress_algorithm, algorithm, LIST(algorithms)[type]);

  return algorithm ? MAKE_INFLATE(algorithm) : NULL;
}

581
/* GABA:
582
583
584
585
586
   (class
     (name newkeys_handler)
     (super packet_handler)
     (vars
       (crypto object crypto_instance)
587
588
       (mac object mac_instance)
       (compression object compress_instance)))
589
590
*/

Niels Möller's avatar
Niels Möller committed
591
592
593
594
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
595
{
596
  CAST(newkeys_handler, closure, c);
597
  struct simple_buffer buffer;
Niels Möller's avatar
Niels Möller committed
598
  unsigned msg_number;
599
600
601

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

602
603
  verbose("Received NEWKEYS. Key exchange finished.\n");
  
604
605
606
607
608
609
  if (parse_uint8(&buffer, &msg_number)
      && (msg_number == SSH_MSG_NEWKEYS)
      && (parse_eod(&buffer)))
    {
      connection->rec_crypto = closure->crypto;
      connection->rec_mac = closure->mac;
610
      connection->rec_compress = closure->compression;
611

Niels Möller's avatar
Niels Möller committed
612
      connection->read_kex_state = KEX_STATE_INIT;
613

614
615
616
      connection->kexinits[CONNECTION_CLIENT]
	= connection->kexinits[CONNECTION_SERVER] = NULL;

617
618
619
620
621
622
      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;

Niels Möller's avatar
Niels Möller committed
623
624
625
626
627
628
      /* Normally, packet entries in the dispatch table must never be
       * NULL, but SSH_MSG_NEWKEYS is handled specially by
       * connection.c:connection_handle_packet. So we could use NULL
       * here, but for uniformity we don't do that. */
      
      connection->dispatch[SSH_MSG_NEWKEYS] = &connection_fail_handler;
629

630
      KILL(closure);
631
632
    }
  else
633
    PROTOCOL_ERROR(connection->e, "Invalid NEWKEYS message");
634
635
}

Niels Möller's avatar
Niels Möller committed
636
struct packet_handler *
637
make_newkeys_handler(struct crypto_instance *crypto,
638
639
		     struct mac_instance *mac,
		     struct compress_instance *compression)
Niels Möller's avatar
Niels Möller committed
640
{
641
  NEW(newkeys_handler,self);
642
643
644
645

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

648
649
  return &self->super;
}
650

651
/* Uses the same algorithms for both directions */
652
/* GABA:
653
654
655
656
657
658
659
660
661
662
663
664
665
   (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)))
*/

666
static struct kexinit *
667
do_make_simple_kexinit(struct make_kexinit *c)
668
669
{
  CAST(simple_kexinit, closure, c);
670
671
672
673
674
675
676
677
678
679
680
681
682
  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]
683
    = closure->compression_algorithms;
684
  kex->parameters[KEX_COMPRESSION_SERVER_TO_CLIENT]
685
    = closure->compression_algorithms;
686
687
688
  kex->languages_client_to_server = closure->languages;
  kex->languages_server_to_client = closure->languages;
  kex->first_kex_packet_follows = 0;
689

690
691
692
  kex->first_kex_packet = NULL;

  return kex;
693
694
}

Niels Möller's avatar
Niels Möller committed
695
696
697
698
699
700
701
702
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)
703
704
705
{
  NEW(simple_kexinit, res);

706
707
  assert(r->quality == RANDOM_GOOD);
  
708
709
710
711
712
713
714
715
716
717
718
719
  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;
}

720

721
722
723
724
725
726
/* 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. */

727
728
729
730
731
732
DEFINE_COMMAND2(kexinit_filter)
     (struct command_2 *s UNUSED,
      struct lsh_object *a1,
      struct lsh_object *a2,
      struct command_continuation *c,
      struct exception_handler *e UNUSED)
733
{
734
735
  CAST(simple_kexinit, init, a1);
  CAST_SUBTYPE(alist, keys, a2);
736

737
738
  init->hostkey_algorithms
    = filter_algorithms(keys, init->hostkey_algorithms);
739

740
  if (!init->hostkey_algorithms)
741
742
    {
      werror("No hostkey algorithms advertised.\n");
743
      init->hostkey_algorithms = make_int_list(1, ATOM_NONE, -1);
744
    }
745

746
  assert(LIST_LENGTH(init->hostkey_algorithms));
747

748
  COMMAND_RETURN(c, init);
749
750
751
}


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

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

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

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

798
  connection->send_compress
799
800
    = kex_make_deflate(algorithms,
		       KEX_COMPRESSION_CLIENT_TO_SERVER ^ is_server);
801
  
802
803
804
  return 1;
}

805

806
807
808
/* 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. */
809
static struct hash_instance *
810
kex_build_secret(const struct hash_algorithm *H,
811
		 struct lsh_string *exchange_hash,
812
		 struct lsh_string *K)
813
{
814
815
816
  /* We include a length field for the key, but not for the exchange
   * hash. */
  
817
  struct hash_instance *hash = make_hash(H);
818
  struct lsh_string *s = ssh_format("%S%lS", K, exchange_hash);
819

820
  hash_update(hash, s->length, s->data);
821
  lsh_string_free(s);
822
823
824
825
  
  return hash;
}

826
/* NOTE: Consumes both the exchange_hash and K */
827
828
void
keyexchange_finish(struct ssh_connection *connection,
829
		   struct object_list *algorithms,
830
		   const struct hash_algorithm *H,
831
832
833
834
835
836
837
838
		   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. */

Niels Möller's avatar
Niels Möller committed
839
840
841
  assert(connection->send_kex_only);
  C_WRITE_NOW(connection, ssh_format("%c", SSH_MSG_NEWKEYS));
  
842
843
844
845
846
847
848
849
850
851
852
  /* 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);
  
853
  if (!install_keys(algorithms, connection, hash))
854
855
856
857
858
    {
      werror("Installing new keys failed. Hanging up.\n");
      KILL(hash);

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

860
861
862
863
864
      return;
    }

  KILL(hash);

Niels Möller's avatar
Niels Möller committed
865
866
867
868
869
  /* If any messages were queued during the key exchange, send them
   * now. */
  connection_send_kex_end(connection);
  
  connection->read_kex_state = KEX_STATE_NEWKEYS;
870

Niels Möller's avatar
Niels Möller committed
871
872
873
#if 0
  /* This message is rather pointless, and some implementations don't
   * handle it properly. */
874
875
876
877
#if DATAFELLOWS_WORKAROUNDS
  if (! (connection->peer_flags & PEER_SEND_NO_DEBUG))
#endif
    send_verbose(connection->write, "Key exchange successful!", 0);
Niels Möller's avatar
Niels Möller committed
878
#endif
879

880
881
  /* FIXME: This is the time for installing the key_expire timer. */
  
Niels Möller's avatar
Niels Möller committed
882
883
884
885
886
  /* FIXME: If we have stopped readin channel sources during the key
   * exchange, we must get them started again, perhaps by calling
   * CHANNEL_ADJUST(channel, 0) for all channels. Can we reuse the
   * connection->established hook for that? */
  
887
888
889
890
891
892
893
894
  if (connection->established)
    {
      struct command_continuation *c = connection->established;
      connection->established = NULL;
  
      COMMAND_RETURN(c, connection);
    }
}