keyexchange.c 12.6 KB
Newer Older
Niels Möller's avatar
Niels Möller committed
1
2
/* keyexchange.c
 *
Niels Möller's avatar
Niels Möller committed
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
 *
 *
 * $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
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
Niels Möller's avatar
Niels Möller committed
24
25
 */

26
27
#include "keyexchange.h"

28
#include "abstract_io.h"
29
#include "alist.h"
30
#include "connection.h"
31
#include "disconnect.h"
32
#include "format.h"
Niels Möller's avatar
Niels Möller committed
33
#include "parse.h"
Niels Möller's avatar
Niels Möller committed
34
#include "publickey_crypto.h"
35
#include "ssh.h"
36
#include "werror.h"
37
#include "xalloc.h"
Niels Möller's avatar
Niels Möller committed
38

39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
struct handle_kexinit
{
  struct packet_handler super;
  int type;
  
  struct make_kexinit *init;
  
  /* 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. */

  struct alist *algorithms;
};

Niels Möller's avatar
Niels Möller committed
55
56
#define NLISTS 10

57
static struct kexinit *parse_kexinit(struct lsh_string *packet)
Niels Möller's avatar
Niels Möller committed
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
{
  struct kexinit *res;
  struct simple_buffer buffer;
  struct simple_buffer sub_buffer;
  UINT8 msg_number;
  UINT32 reserved;
  
  int *lists[NLISTS];
  int i;
  
  simple_buffer_init(&buffer, packet->length, packet->data);

  if (!parse_uint8(&buffer, &msg_number)
      || (msg_number != SSH_MSG_KEXINIT) )
    return 0;

74
  res = xalloc(sizeof(struct kexinit));
Niels Möller's avatar
Niels Möller committed
75

76
  if (!parse_octets(&buffer, 16, res->cookie))
Niels Möller's avatar
Niels Möller committed
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
    {
      lsh_free(res);
      return NULL;
    }
  
  for (i = 0; i<NLISTS; i++)
    {
      if (!parse_sub_buffer(&buffer, &sub_buffer)
	  || ! (lists[i] = parse_atom_list(&sub_buffer)))
	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++)
	lsh_free(lists[i]);
      lsh_free(res);
      return NULL;
    }
  
102
  res->kex_algorithms = lists[0];
103
  res->server_hostkey_algorithms = lists[1];
Niels Möller's avatar
Niels Möller committed
104
105
106
107

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

108
109
  res->languages_client_to_server = lists[8];
  res->languages_server_to_client = lists[9];
Niels Möller's avatar
Niels Möller committed
110
111
112

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

Niels Möller's avatar
Niels Möller committed
114
115
116
117
118
119
struct lsh_string *format_kex(struct kexinit *kex)
{
  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,
120
		    kex->server_hostkey_algorithms,
Niels Möller's avatar
Niels Möller committed
121
122
123
124
125
126
		    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
127
128
129
130
131
132
133
		    kex->languages_client_to_server,
		    kex->languages_server_to_client,
		    kex->first_kex_packet_follows, 0);
}
  

int initiate_keyexchange(struct ssh_connection *connection,
134
			 int type,
Niels Möller's avatar
Niels Möller committed
135
136
137
138
			 struct kexinit *kex,
			 struct lsh_string *first_packet)
{
  int res;
139
  struct lsh_string *s;
Niels Möller's avatar
Niels Möller committed
140
141
  
  kex->first_kex_packet_follows = !!first_packet;
142
  connection->kexinits[type] = kex;
Niels Möller's avatar
Niels Möller committed
143

Niels Möller's avatar
Niels Möller committed
144
145
146
  s = format_kex(kex);

  /* Save value for later signing */
147
  connection->literal_kexinits[type] = s; 
Niels Möller's avatar
Niels Möller committed
148
149
150

  res = A_WRITE(connection->write, lsh_string_dup(s));
  
Niels Möller's avatar
Niels Möller committed
151
  if (!LSH_PROBLEMP(res) && first_packet)
Niels Möller's avatar
Niels Möller committed
152
153
154
155
156
    return A_WRITE(connection->write, first_packet);
  else
    return res;
}

157
static int select_algorithm(int *server_list, int *client_list)
Niels Möller's avatar
Niels Möller committed
158
159
160
161
162
163
164
165
166
167
168
{
  /* FIXME: This quadratic complexity algorithm should do as long as
   * the lists are short. */
  int i, j;

  for(i = 0; client_list[i] >= 0; i++)
    {
      if (!client_list[i])
	/* Unknown algorithm */
	continue;
      for(j = 0; server_list[j] > 0; j++)
169
	if (client_list[i] == server_list[j])
Niels Möller's avatar
Niels Möller committed
170
171
172
173
174
175
	  return client_list[i];
    }

  return 0;
}

176
int disconnect_kex_failed(struct ssh_connection *connection, char *msg)
Niels Möller's avatar
Niels Möller committed
177
178
{
  return A_WRITE(connection->write,
179
180
		 format_disconnect(SSH_DISCONNECT_KEY_EXCHANGE_FAILED,
				   msg));
Niels Möller's avatar
Niels Möller committed
181
182
}

183
static int do_handle_kexinit(struct packet_handler *c,
Niels Möller's avatar
Niels Möller committed
184
185
186
			     struct ssh_connection *connection,
			     struct lsh_string *packet)
{
187
  struct handle_kexinit *closure = (struct handle_kexinit *) c;
Niels Möller's avatar
Niels Möller committed
188
189
190
191
192
193
194
195
196
  struct kexinit *msg = parse_kexinit(packet);

  int kex_algorithm;
  int hostkey_algorithm;

  int parameters[KEX_PARAMETERS];
  void **algorithms;

  int i;
197
198
199

  MDEBUG(closure);
  MDEBUG(msg);
Niels Möller's avatar
Niels Möller committed
200
201
202
203
  
  if (!msg)
    return 0;

Niels Möller's avatar
Niels Möller committed
204
  /* Save value for later signing */
205
  connection->literal_kexinits[!closure->type] = packet;
Niels Möller's avatar
Niels Möller committed
206
  
207
  connection->kexinits[!closure->type] = msg;
Niels Möller's avatar
Niels Möller committed
208
209
  
  /* Have we sent a kexinit message? */
210
  if (!connection->kexinits[closure->type])
Niels Möller's avatar
Niels Möller committed
211
212
    {
      int res;
Niels Möller's avatar
Niels Möller committed
213
      struct lsh_string *packet;
214
      struct kexinit *sent = MAKE_KEXINIT(closure->init);
215
      connection->kexinits[closure->type] = sent;
Niels Möller's avatar
Niels Möller committed
216
      packet = format_kex(sent);
217
      connection->literal_kexinits[closure->type] = lsh_string_dup(packet); 
Niels Möller's avatar
Niels Möller committed
218
219
      
      res = A_WRITE(connection->write, packet);
Niels Möller's avatar
Niels Möller committed
220
      if (LSH_PROBLEMP(res))
Niels Möller's avatar
Niels Möller committed
221
222
223
224
225
226
	return res;
    }

  /* Select key exchange algorithms */

  if (connection->kexinits[0]->kex_algorithms[0]
227
      == connection->kexinits[1]->kex_algorithms[0])
Niels Möller's avatar
Niels Möller committed
228
229
    {
      /* Use this algorithm */
230
      kex_algorithm = connection->kexinits[0]->kex_algorithms[0];
Niels Möller's avatar
Niels Möller committed
231
232
233
234
235
236
    }
  else
    {
      if (msg->first_kex_packet_follows)
	{
	  /* Wrong guess */
237
	  connection->kex_state = KEX_STATE_IGNORE;
Niels Möller's avatar
Niels Möller committed
238
239
240
241
	}
      /* FIXME: Ignores that some keyechange algorithms require
       * certain features of the host key algorithms. */
      
242
243
244
      kex_algorithm
	= select_algorithm(connection->kexinits[0]->kex_algorithms,
			   connection->kexinits[1]->kex_algorithms);
245

Niels Möller's avatar
Niels Möller committed
246
247
      if  (!kex_algorithm)
	{
248
249
	  disconnect_kex_failed(connection,
				"No common key exchange method.\r\n");
250
	  
Niels Möller's avatar
Niels Möller committed
251
	  return LSH_FAIL | LSH_CLOSE;
Niels Möller's avatar
Niels Möller committed
252
	}
253
254
255
256
257
258
259
260
261
    }
  hostkey_algorithm
    = select_algorithm(connection->kexinits[0]->server_hostkey_algorithms,
		       connection->kexinits[1]->server_hostkey_algorithms);
  
  for(i = 0; i<KEX_PARAMETERS; i++)
    {
      parameters[i]
	= select_algorithm(connection->kexinits[0]->parameters[i],
262
			   connection->kexinits[1]->parameters[i]);
263
264
265
266
      
      if (!parameters[i])
	{
	  disconnect_kex_failed(connection, "");
Niels Möller's avatar
Niels Möller committed
267
	  return LSH_FAIL | LSH_CLOSE;
Niels Möller's avatar
Niels Möller committed
268
	}
269
270
271
272
273
274
275
276
277
278
279
280
281
282
    }
  
  algorithms = xalloc(KEX_PARAMETERS*sizeof(void *));
  
  for (i = 0; i<KEX_PARAMETERS; i++)
    algorithms[i] = ALIST_GET(closure->algorithms, parameters[i]);
      
  return KEYEXCHANGE_INIT( (struct keyexchange_algorithm *)
			   ALIST_GET(closure->algorithms, kex_algorithm),
			   connection,
			   hostkey_algorithm,
			   ALIST_GET(closure->algorithms, hostkey_algorithm),
			   algorithms);
}
Niels Möller's avatar
Niels Möller committed
283

284
285
struct packet_handler *make_kexinit_handler(int type,
					    struct make_kexinit *init,
286
287
288
					    struct alist *algorithms)
{
  struct handle_kexinit *self = xalloc(sizeof(struct handle_kexinit));
Niels Möller's avatar
Niels Möller committed
289

290
  self->super.handler = do_handle_kexinit;
291
292

  self->type = type;
293
294
  self->init = init;
  self->algorithms = algorithms;
Niels Möller's avatar
Niels Möller committed
295

296
  return &self->super;
Niels Möller's avatar
Niels Möller committed
297
298
}

299
/* FIXME: THis function can't handle IV:s at all */
300
301
302
303
static struct lsh_string *kex_make_key(struct hash_instance *secret,
				       UINT32 key_length,
				       int type,
				       struct lsh_string *session_id)
304
305
{
  /* Indexed by the KEX_* values */
306
  static /* const */ char *tags = "CDEF";
307
308
309
310
311
312
313
  
  struct lsh_string *key;
  struct hash_instance *hash;
  UINT8 *digest;
  
  key = lsh_string_alloc(key_length);

314
315
  debug("Constructing session key of type %d\n", type);
  
316
317
318
319
  if (!key_length)
    return key;
  
  hash = HASH_COPY(secret);
320
  digest = alloca(hash->hash_size);
321

322
  HASH_UPDATE(hash, 1, tags + type); 
323
324
325
  HASH_UPDATE(hash, session_id->length, session_id->data);
  HASH_DIGEST(hash, digest);

326
  if (key_length > hash->hash_size)
327
    fatal("Not implemented\n");
328
329
330

  memcpy(key->data, digest, key_length);
  lsh_free(hash);
331
332

  debug_hex(key->length, key->data);
333
334
335
336
  return key;
}
  
struct crypto_instance *kex_make_encrypt(struct hash_instance *secret,
337
					 void **algorithms,
338
339
340
					 int type,
					 struct ssh_connection *connection)
{
341
342
343
344
345
346
347
348
  struct crypto_algorithm *algorithm = algorithms[type];
  struct lsh_string *key;
  struct crypto_instance *crypto;
  
  if (!algorithm)
    return NULL;

  key = kex_make_key(secret, algorithm->key_size,
349
350
351
					type, connection->session_id);
  /* FIXME: No IV. Note that for DES, instantiating the crypto can
   * fail, if the key happens to be weak. */
352
353

  crypto = MAKE_ENCRYPT(algorithm, key->data);
354
355

  lsh_string_free(key);
356
  return crypto;
357
358
359
}

struct crypto_instance *kex_make_decrypt(struct hash_instance *secret,
360
					 void **algorithms,
361
362
363
					 int type,
					 struct ssh_connection *connection)
{
364
365
366
367
368
369
370
371
372
  struct crypto_algorithm *algorithm = algorithms[type];
  struct lsh_string *key;
  struct crypto_instance *crypto;
  
  if (!algorithm)
    return NULL;
  
  key = kex_make_key(secret, algorithm->key_size,
		     type, connection->session_id);
373
374
  /* FIXME: No IV. Note that for DES, instantiating the crypto can
   * fail, if the key happens to be weak. */
375
376

  crypto = MAKE_DECRYPT(algorithm, key->data);
377
378

  lsh_string_free(key);
379
  return crypto;
380
381
382
}

struct mac_instance *kex_make_mac(struct hash_instance *secret,
383
				  void **algorithms,
384
385
386
				  int type,
				  struct ssh_connection *connection)
{
387
388
389
390
391
392
  struct mac_algorithm *algorithm = algorithms[type];
  struct mac_instance *mac;
  struct lsh_string *key;

  if (!algorithm)
    return NULL;
393

394
395
396
397
  key = kex_make_key(secret, algorithm->key_size,
		     type, connection->session_id);

  mac = MAKE_MAC(algorithm, key->data);
398
399
400
401
402

  lsh_string_free(key);
  return mac;
}

403
404
405
406
407
408
struct handle_newkeys
{
  struct packet_handler super;
  struct crypto_instance *crypto;
  struct mac_instance *mac;
};
409

Niels Möller's avatar
Niels Möller committed
410
411
412
413
static int do_handle_newkeys(struct packet_handler *c,
			     struct ssh_connection *connection,
			     struct lsh_string *packet)
{
414
415
416
417
  struct handle_newkeys *closure = (struct handle_newkeys *) c;
  struct simple_buffer buffer;
  UINT8 msg_number;

418
419
  MDEBUG(closure);
  
420
421
422
423
424
425
426
427
428
  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;

429
430
      connection->kex_state = KEX_STATE_INIT;

431
432
433
      connection->dispatch[SSH_MSG_NEWKEYS] = NULL;

      lsh_free(closure);
Niels Möller's avatar
Niels Möller committed
434
      return LSH_OK | LSH_GOON;
435
436
    }
  else
Niels Möller's avatar
Niels Möller committed
437
    return LSH_FAIL | LSH_DIE;
438
439
}

Niels Möller's avatar
Niels Möller committed
440
struct packet_handler *
441
442
make_newkeys_handler(struct crypto_instance *crypto,
		     struct mac_instance *mac)
Niels Möller's avatar
Niels Möller committed
443
{
444
445
446
447
448
  struct handle_newkeys *self = xalloc(sizeof(struct handle_newkeys));

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

450
451
  return &self->super;
}
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469

struct test_kexinit
{
  struct make_kexinit super;
  struct randomness *r;
};

static struct kexinit *do_make_kexinit(struct make_kexinit *c)
{
  struct test_kexinit *closure = (struct test_kexinit *) c;
  struct kexinit *res = xalloc(sizeof(struct kexinit));

  static int kex_algorithms[] = { ATOM_DIFFIE_HELLMAN_GROUP1_SHA1, 0 };
  static int server_hostkey_algorithms[] = { ATOM_SSH_DSS, 0 };
  static int crypto_algorithms[] = { ATOM_ARCFOUR, ATOM_NONE, 0 };
  static int mac_algorithms[] = { ATOM_HMAC_SHA1, 0 };
  static int compression_algorithms[] = { ATOM_NONE, 0 };
  static int languages[] = { 0 };
470
471

  MDEBUG(closure);
Niels Möller's avatar
Niels Möller committed
472
  
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
  RANDOM(closure->r, 16, res->cookie);
  res->kex_algorithms = kex_algorithms;
  res->server_hostkey_algorithms = server_hostkey_algorithms;
  res->parameters[KEX_ENCRYPTION_CLIENT_TO_SERVER] = crypto_algorithms;
  res->parameters[KEX_ENCRYPTION_SERVER_TO_CLIENT] = crypto_algorithms;
  res->parameters[KEX_MAC_CLIENT_TO_SERVER] = mac_algorithms;
  res->parameters[KEX_MAC_SERVER_TO_CLIENT] = mac_algorithms;
  res->parameters[KEX_COMPRESSION_CLIENT_TO_SERVER] = compression_algorithms;
  res->parameters[KEX_COMPRESSION_SERVER_TO_CLIENT] = compression_algorithms;
  res->languages_client_to_server = languages;
  res->languages_server_to_client = languages;
  res->first_kex_packet_follows = 0;

  return res;
}

struct make_kexinit *make_test_kexinit(struct randomness *r)
{
  struct test_kexinit *res = xalloc(sizeof(struct test_kexinit));

  res->super.make = do_make_kexinit;
  res->r = r;

  return &res->super;
}