Coverage Report

Created: 2025-10-10 06:20

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/dropbear/src/common-kex.c
Line
Count
Source
1
/*
2
 * Dropbear SSH
3
 * 
4
 * Copyright (c) 2002-2004 Matt Johnston
5
 * Portions Copyright (c) 2004 by Mihnea Stoenescu
6
 * All rights reserved.
7
 * 
8
 * Permission is hereby granted, free of charge, to any person obtaining a copy
9
 * of this software and associated documentation files (the "Software"), to deal
10
 * in the Software without restriction, including without limitation the rights
11
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12
 * copies of the Software, and to permit persons to whom the Software is
13
 * furnished to do so, subject to the following conditions:
14
 * 
15
 * The above copyright notice and this permission notice shall be included in
16
 * all copies or substantial portions of the Software.
17
 * 
18
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24
 * SOFTWARE. */
25
26
#include "includes.h"
27
#include "dbutil.h"
28
#include "algo.h"
29
#include "buffer.h"
30
#include "session.h"
31
#include "kex.h"
32
#include "ssh.h"
33
#include "packet.h"
34
#include "bignum.h"
35
#include "dbrandom.h"
36
#include "runopts.h"
37
38
static void kexinitialise(void);
39
static void gen_new_keys(void);
40
#ifndef DISABLE_ZLIB
41
static void gen_new_zstream_recv(void);
42
static void gen_new_zstream_trans(void);
43
#endif
44
static void read_kex_algos(void);
45
/* helper function for gen_new_keys */
46
static void hashkeys(unsigned char *out, unsigned int outlen, 
47
    const hash_state * hs, const unsigned char X);
48
49
50
/* Send our list of algorithms we can use */
51
11.7k
void send_msg_kexinit() {
52
53
11.7k
  CHECKCLEARTOWRITE();
54
11.7k
  buf_putbyte(ses.writepayload, SSH_MSG_KEXINIT);
55
56
  /* cookie */
57
11.7k
  genrandom(buf_getwriteptr(ses.writepayload, 16), 16);
58
11.7k
  buf_incrwritepos(ses.writepayload, 16);
59
60
  /* kex algos */
61
11.7k
  buf_put_algolist(ses.writepayload, sshkex);
62
63
  /* server_host_key_algorithms */
64
11.7k
  buf_put_algolist(ses.writepayload, sigalgs);
65
66
  /* encryption_algorithms_client_to_server */
67
11.7k
  buf_put_algolist(ses.writepayload, sshciphers);
68
69
  /* encryption_algorithms_server_to_client */
70
11.7k
  buf_put_algolist(ses.writepayload, sshciphers);
71
72
  /* mac_algorithms_client_to_server */
73
11.7k
  buf_put_algolist(ses.writepayload, sshhashes);
74
75
  /* mac_algorithms_server_to_client */
76
11.7k
  buf_put_algolist(ses.writepayload, sshhashes);
77
78
79
  /* compression_algorithms_client_to_server */
80
11.7k
  buf_put_algolist(ses.writepayload, ses.compress_algos_c2s);
81
82
  /* compression_algorithms_server_to_client */
83
11.7k
  buf_put_algolist(ses.writepayload, ses.compress_algos_s2c);
84
85
  /* languages_client_to_server */
86
11.7k
  buf_putstring(ses.writepayload, "", 0);
87
88
  /* languages_server_to_client */
89
11.7k
  buf_putstring(ses.writepayload, "", 0);
90
91
  /* first_kex_packet_follows */
92
11.7k
  buf_putbyte(ses.writepayload, (ses.send_kex_first_guess != NULL));
93
94
  /* reserved unit32 */
95
11.7k
  buf_putint(ses.writepayload, 0);
96
97
  /* set up transmitted kex packet buffer for hashing. 
98
   * This is freed after the end of the kex */
99
11.7k
  ses.transkexinit = buf_newcopy(ses.writepayload);
100
101
11.7k
  encrypt_packet();
102
11.7k
  ses.dataallowed = 0; /* don't send other packets during kex */
103
104
11.7k
  ses.kexstate.sentkexinit = 1;
105
106
11.7k
  ses.newkeys = (struct key_context*)m_malloc(sizeof(struct key_context));
107
108
11.7k
  if (ses.send_kex_first_guess) {
109
0
    ses.newkeys->algo_kex = first_usable_algo(sshkex)->data;
110
0
    ses.newkeys->algo_signature = first_usable_algo(sigalgs)->val;
111
0
    ses.newkeys->algo_hostkey = signkey_type_from_signature(ses.newkeys->algo_signature);
112
0
    ses.send_kex_first_guess();
113
0
  }
114
115
11.7k
  TRACE(("DATAALLOWED=0"))
116
11.7k
  TRACE(("-> KEXINIT"))
117
118
11.7k
}
119
120
19.9k
static void switch_keys() {
121
19.9k
  TRACE2(("enter switch_keys"))
122
19.9k
  if (!(ses.kexstate.sentkexinit && ses.kexstate.recvkexinit)) {
123
8
    dropbear_exit("Unexpected newkeys message");
124
8
  }
125
126
19.9k
  if (!ses.keys) {
127
0
    ses.keys = m_malloc(sizeof(*ses.newkeys));
128
0
  }
129
19.9k
  if (ses.kexstate.recvnewkeys && ses.newkeys->recv.valid) {
130
9.77k
    TRACE(("switch_keys recv"))
131
#ifndef DISABLE_ZLIB
132
    gen_new_zstream_recv();
133
#endif
134
9.77k
    ses.keys->recv = ses.newkeys->recv;
135
9.77k
    m_burn(&ses.newkeys->recv, sizeof(ses.newkeys->recv));
136
9.77k
    ses.newkeys->recv.valid = 0;
137
9.77k
  }
138
19.9k
  if (ses.kexstate.sentnewkeys && ses.newkeys->trans.valid) {
139
10.1k
    TRACE(("switch_keys trans"))
140
#ifndef DISABLE_ZLIB
141
    gen_new_zstream_trans();
142
#endif
143
10.1k
    ses.keys->trans = ses.newkeys->trans;
144
10.1k
    m_burn(&ses.newkeys->trans, sizeof(ses.newkeys->trans));
145
10.1k
    ses.newkeys->trans.valid = 0;
146
10.1k
  }
147
19.9k
  if (ses.kexstate.sentnewkeys && ses.kexstate.recvnewkeys)
148
9.77k
  {
149
9.77k
    TRACE(("switch_keys done"))
150
9.77k
    ses.keys->algo_kex = ses.newkeys->algo_kex;
151
9.77k
    ses.keys->algo_hostkey = ses.newkeys->algo_hostkey;
152
9.77k
    ses.keys->algo_signature = ses.newkeys->algo_signature;
153
9.77k
    ses.keys->allow_compress = 0;
154
9.77k
    m_free(ses.newkeys);
155
9.77k
    ses.newkeys = NULL;
156
9.77k
    kexinitialise();
157
9.77k
  }
158
19.9k
  TRACE2(("leave switch_keys"))
159
19.9k
}
160
161
/* Bring new keys into use after a key exchange, and let the client know*/
162
10.1k
void send_msg_newkeys() {
163
164
10.1k
  TRACE(("enter send_msg_newkeys"))
165
166
  /* generate the kexinit request */
167
10.1k
  CHECKCLEARTOWRITE();
168
10.1k
  buf_putbyte(ses.writepayload, SSH_MSG_NEWKEYS);
169
10.1k
  encrypt_packet();
170
171
  
172
  /* set up our state */
173
10.1k
  ses.kexstate.sentnewkeys = 1;
174
10.1k
  if (ses.kexstate.donefirstkex) {
175
8.48k
    ses.kexstate.donesecondkex = 1;
176
8.48k
  }
177
10.1k
  ses.kexstate.donefirstkex = 1;
178
10.1k
  ses.dataallowed = 1; /* we can send other packets again now */
179
10.1k
  gen_new_keys();
180
10.1k
  switch_keys();
181
182
10.1k
  if (ses.kexstate.strict_kex) {
183
1.33k
    ses.transseq = 0;
184
1.33k
  }
185
186
10.1k
  TRACE(("leave send_msg_newkeys"))
187
10.1k
}
188
189
/* Bring the new keys into use after a key exchange */
190
9.78k
void recv_msg_newkeys() {
191
192
9.78k
  TRACE(("enter recv_msg_newkeys"))
193
194
9.78k
  ses.kexstate.recvnewkeys = 1;
195
9.78k
  switch_keys();
196
197
9.78k
  if (ses.kexstate.strict_kex) {
198
1.32k
    ses.recvseq = 0;
199
1.32k
  }
200
9.78k
  ses.kexstate.recvfirstnewkeys = 1;
201
202
9.78k
  TRACE(("leave recv_msg_newkeys"))
203
9.78k
}
204
205
3.01k
static void kex_setup_compress(void) {
206
3.01k
#ifdef DISABLE_ZLIB
207
3.01k
  ses.compress_algos_c2s = ssh_nocompress;
208
3.01k
  ses.compress_algos_s2c = ssh_nocompress;
209
#else
210
211
  if (!opts.allow_compress) {
212
    ses.compress_algos_c2s = ssh_nocompress;
213
    ses.compress_algos_s2c = ssh_nocompress;
214
    return;
215
  }
216
217
  if (IS_DROPBEAR_CLIENT) {
218
    /* TODO: should c2s in dbclient be disabled?
219
     * Current Dropbear server disables it. Disabling it also
220
     * lets DROPBEAR_CLI_IMMEDIATE_AUTH work (see comment there) */
221
    ses.compress_algos_c2s = ssh_compress;
222
    ses.compress_algos_s2c = ssh_compress;
223
  } else {
224
    ses.compress_algos_c2s = ssh_nocompress;
225
    ses.compress_algos_s2c = ssh_compress;
226
  }
227
#endif
228
3.01k
}
229
230
/* Set up the kex for the first time */
231
3.01k
void kexfirstinitialise() {
232
3.01k
  kex_setup_compress();
233
3.01k
  kexinitialise();
234
3.01k
}
235
236
/* Reset the kex state, ready for a new negotiation */
237
12.7k
static void kexinitialise() {
238
239
12.7k
  TRACE(("kexinitialise()"))
240
241
  /* sent/recv'd MSG_KEXINIT */
242
12.7k
  ses.kexstate.sentkexinit = 0;
243
12.7k
  ses.kexstate.recvkexinit = 0;
244
245
  /* sent/recv'd MSG_NEWKEYS */
246
12.7k
  ses.kexstate.recvnewkeys = 0;
247
12.7k
  ses.kexstate.sentnewkeys = 0;
248
249
  /* first_packet_follows */
250
12.7k
  ses.kexstate.them_firstfollows = 0;
251
252
12.7k
  ses.kexstate.datatrans = 0;
253
12.7k
  ses.kexstate.datarecv = 0;
254
255
12.7k
  ses.kexstate.our_first_follows_matches = 0;
256
257
12.7k
  ses.kexstate.lastkextime = monotonic_now();
258
259
12.7k
}
260
261
/* Helper function for gen_new_keys, creates a hash. It makes a copy of the
262
 * already initialised hash_state hs, which should already have processed
263
 * the dh_K and hash, since these are common. X is the letter 'A', 'B' etc.
264
 * out must have at least min(hash_size, outlen) bytes allocated.
265
 *
266
 * See Section 7.2 of rfc4253 (ssh transport) for details */
267
static void hashkeys(unsigned char *out, unsigned int outlen, 
268
45.6k
    const hash_state * hs, const unsigned char X) {
269
270
45.6k
  const struct ltc_hash_descriptor *hash_desc = ses.newkeys->algo_kex->hash_desc;
271
45.6k
  hash_state hs2;
272
45.6k
  unsigned int offset;
273
45.6k
  unsigned char tmpout[MAX_HASH_SIZE];
274
275
45.6k
  memcpy(&hs2, hs, sizeof(hash_state));
276
45.6k
  hash_desc->process(&hs2, &X, 1);
277
45.6k
  hash_desc->process(&hs2, ses.session_id->data, ses.session_id->len);
278
45.6k
  hash_desc->done(&hs2, tmpout);
279
45.6k
  memcpy(out, tmpout, MIN(hash_desc->hashsize, outlen));
280
45.6k
  for (offset = hash_desc->hashsize; 
281
64.2k
      offset < outlen; 
282
45.6k
      offset += hash_desc->hashsize)
283
18.6k
  {
284
    /* need to extend */
285
18.6k
    memcpy(&hs2, hs, sizeof(hash_state));
286
18.6k
    hash_desc->process(&hs2, out, offset);
287
18.6k
    hash_desc->done(&hs2, tmpout);
288
18.6k
    memcpy(&out[offset], tmpout, MIN(outlen - offset, hash_desc->hashsize));
289
18.6k
  }
290
45.6k
  m_burn(&hs2, sizeof(hash_state));
291
45.6k
}
292
293
/* Generate the actual encryption/integrity keys, using the results of the
294
 * key exchange, as specified in section 7.2 of the transport rfc 4253.
295
 * This occurs after the DH key-exchange.
296
 *
297
 * ses.newkeys is the new set of keys which are generated, these are only
298
 * taken into use after both sides have sent a newkeys message */
299
300
10.1k
static void gen_new_keys() {
301
302
10.1k
  unsigned char C2S_IV[MAX_IV_LEN];
303
10.1k
  unsigned char C2S_key[MAX_KEY_LEN];
304
10.1k
  unsigned char S2C_IV[MAX_IV_LEN];
305
10.1k
  unsigned char S2C_key[MAX_KEY_LEN];
306
  /* unsigned char key[MAX_KEY_LEN]; */
307
10.1k
  unsigned char *trans_IV, *trans_key, *recv_IV, *recv_key;
308
309
10.1k
  hash_state hs;
310
10.1k
  const struct ltc_hash_descriptor *hash_desc = ses.newkeys->algo_kex->hash_desc;
311
10.1k
  char mactransletter, macrecvletter; /* Client or server specific */
312
313
10.1k
  TRACE(("enter gen_new_keys"))
314
  /* the dh_K and hash are the start of all hashes, we make use of that */
315
316
10.1k
  hash_desc->init(&hs);
317
10.1k
  if (ses.dh_K) {
318
10.1k
    hash_process_mp(hash_desc, &hs, ses.dh_K);
319
10.1k
    mp_clear(ses.dh_K);
320
10.1k
    m_free(ses.dh_K);
321
10.1k
  }
322
10.1k
  if (ses.dh_K_bytes) {
323
0
      hash_desc->process(&hs, ses.dh_K_bytes->data, ses.dh_K_bytes->len);
324
0
    buf_burn_free(ses.dh_K_bytes);
325
0
    ses.dh_K_bytes = NULL;
326
0
  }
327
10.1k
  hash_desc->process(&hs, ses.hash->data, ses.hash->len);
328
10.1k
  buf_burn_free(ses.hash);
329
10.1k
  ses.hash = NULL;
330
331
10.1k
  if (IS_DROPBEAR_CLIENT) {
332
0
    trans_IV  = C2S_IV;
333
0
    recv_IV   = S2C_IV;
334
0
    trans_key = C2S_key;
335
0
    recv_key  = S2C_key;
336
0
    mactransletter = 'E';
337
0
    macrecvletter = 'F';
338
10.1k
  } else {
339
10.1k
    trans_IV  = S2C_IV;
340
10.1k
    recv_IV   = C2S_IV;
341
10.1k
    trans_key = S2C_key;
342
10.1k
    recv_key  = C2S_key;
343
10.1k
    mactransletter = 'F';
344
10.1k
    macrecvletter = 'E';
345
10.1k
  }
346
347
10.1k
  hashkeys(C2S_IV, sizeof(C2S_IV), &hs, 'A');
348
10.1k
  hashkeys(S2C_IV, sizeof(S2C_IV), &hs, 'B');
349
10.1k
  hashkeys(C2S_key, sizeof(C2S_key), &hs, 'C');
350
10.1k
  hashkeys(S2C_key, sizeof(S2C_key), &hs, 'D');
351
352
10.1k
  if (ses.newkeys->recv.algo_crypt->cipherdesc != NULL) {
353
10.1k
    int recv_cipher = -1;
354
10.1k
    if (ses.newkeys->recv.algo_crypt->cipherdesc->name != NULL) {
355
4.68k
      recv_cipher = find_cipher(ses.newkeys->recv.algo_crypt->cipherdesc->name);
356
4.68k
      if (recv_cipher < 0) {
357
0
        dropbear_exit("Crypto error");
358
0
      }
359
4.68k
    }
360
10.1k
    if (ses.newkeys->recv.crypt_mode->start(recv_cipher, 
361
10.1k
        recv_IV, recv_key, 
362
10.1k
        ses.newkeys->recv.algo_crypt->keysize, 0, 
363
10.1k
        &ses.newkeys->recv.cipher_state) != CRYPT_OK) {
364
0
      dropbear_exit("Crypto error");
365
0
    }
366
10.1k
  }
367
368
10.1k
  if (ses.newkeys->trans.algo_crypt->cipherdesc != NULL) {
369
10.1k
    int trans_cipher = -1;
370
10.1k
    if (ses.newkeys->trans.algo_crypt->cipherdesc->name != NULL) {
371
4.87k
      trans_cipher = find_cipher(ses.newkeys->trans.algo_crypt->cipherdesc->name);
372
4.87k
      if (trans_cipher < 0) {
373
0
        dropbear_exit("Crypto error");
374
0
      }
375
4.87k
    }
376
10.1k
    if (ses.newkeys->trans.crypt_mode->start(trans_cipher, 
377
10.1k
        trans_IV, trans_key, 
378
10.1k
        ses.newkeys->trans.algo_crypt->keysize, 0, 
379
10.1k
        &ses.newkeys->trans.cipher_state) != CRYPT_OK) {
380
0
      dropbear_exit("Crypto error");
381
0
    }
382
10.1k
  }
383
384
10.1k
  if (ses.newkeys->trans.algo_mac->hash_desc != NULL) {
385
4.87k
    hashkeys(ses.newkeys->trans.mackey, 
386
4.87k
        ses.newkeys->trans.algo_mac->keysize, &hs, mactransletter);
387
4.87k
    ses.newkeys->trans.hash_index = find_hash(ses.newkeys->trans.algo_mac->hash_desc->name);
388
4.87k
  }
389
390
10.1k
  if (ses.newkeys->recv.algo_mac->hash_desc != NULL) {
391
0
    hashkeys(ses.newkeys->recv.mackey, 
392
0
        ses.newkeys->recv.algo_mac->keysize, &hs, macrecvletter);
393
0
    ses.newkeys->recv.hash_index = find_hash(ses.newkeys->recv.algo_mac->hash_desc->name);
394
0
  }
395
396
  /* Ready to switch over */
397
10.1k
  ses.newkeys->trans.valid = 1;
398
10.1k
  ses.newkeys->recv.valid = 1;
399
400
10.1k
  m_burn(C2S_IV, sizeof(C2S_IV));
401
10.1k
  m_burn(C2S_key, sizeof(C2S_key));
402
10.1k
  m_burn(S2C_IV, sizeof(S2C_IV));
403
10.1k
  m_burn(S2C_key, sizeof(S2C_key));
404
10.1k
  m_burn(&hs, sizeof(hash_state));
405
406
10.1k
  TRACE(("leave gen_new_keys"))
407
10.1k
}
408
409
#ifndef DISABLE_ZLIB
410
411
int is_compress_trans() {
412
  return ses.keys->trans.algo_comp == DROPBEAR_COMP_ZLIB
413
    || (ses.authstate.authdone
414
      && ses.keys->trans.algo_comp == DROPBEAR_COMP_ZLIB_DELAY);
415
}
416
417
int is_compress_recv() {
418
  return ses.keys->recv.algo_comp == DROPBEAR_COMP_ZLIB
419
    || (ses.authstate.authdone
420
      && ses.keys->recv.algo_comp == DROPBEAR_COMP_ZLIB_DELAY);
421
}
422
423
static void* dropbear_zalloc(void* UNUSED(opaque), uInt items, uInt size) {
424
  return m_calloc(items, size);
425
}
426
427
static void dropbear_zfree(void* UNUSED(opaque), void* ptr) {
428
  m_free(ptr);
429
}
430
431
/* Set up new zlib compression streams, close the old ones. Only
432
 * called from gen_new_keys() */
433
static void gen_new_zstream_recv() {
434
435
  /* create new zstreams */
436
  if (ses.newkeys->recv.algo_comp == DROPBEAR_COMP_ZLIB
437
      || ses.newkeys->recv.algo_comp == DROPBEAR_COMP_ZLIB_DELAY) {
438
    ses.newkeys->recv.zstream = (z_streamp)m_malloc(sizeof(z_stream));
439
    ses.newkeys->recv.zstream->zalloc = dropbear_zalloc;
440
    ses.newkeys->recv.zstream->zfree = dropbear_zfree;
441
    
442
    if (inflateInit(ses.newkeys->recv.zstream) != Z_OK) {
443
      dropbear_exit("zlib error");
444
    }
445
  } else {
446
    ses.newkeys->recv.zstream = NULL;
447
  }
448
  /* clean up old keys */
449
  if (ses.keys->recv.zstream != NULL) {
450
    if (inflateEnd(ses.keys->recv.zstream) == Z_STREAM_ERROR) {
451
      /* Z_DATA_ERROR is ok, just means that stream isn't ended */
452
      dropbear_exit("Crypto error");
453
    }
454
    m_free(ses.keys->recv.zstream);
455
  }
456
}
457
458
static void gen_new_zstream_trans() {
459
460
  if (ses.newkeys->trans.algo_comp == DROPBEAR_COMP_ZLIB
461
      || ses.newkeys->trans.algo_comp == DROPBEAR_COMP_ZLIB_DELAY) {
462
    ses.newkeys->trans.zstream = (z_streamp)m_malloc(sizeof(z_stream));
463
    ses.newkeys->trans.zstream->zalloc = dropbear_zalloc;
464
    ses.newkeys->trans.zstream->zfree = dropbear_zfree;
465
  
466
    if (deflateInit2(ses.newkeys->trans.zstream, Z_DEFAULT_COMPRESSION,
467
          Z_DEFLATED, DROPBEAR_ZLIB_WINDOW_BITS, 
468
          DROPBEAR_ZLIB_MEM_LEVEL, Z_DEFAULT_STRATEGY)
469
        != Z_OK) {
470
      dropbear_exit("zlib error");
471
    }
472
  } else {
473
    ses.newkeys->trans.zstream = NULL;
474
  }
475
476
  if (ses.keys->trans.zstream != NULL) {
477
    if (deflateEnd(ses.keys->trans.zstream) == Z_STREAM_ERROR) {
478
      /* Z_DATA_ERROR is ok, just means that stream isn't ended */
479
      dropbear_exit("Crypto error");
480
    }
481
    m_free(ses.keys->trans.zstream);
482
  }
483
}
484
#endif /* DISABLE_ZLIB */
485
486
487
/* Executed upon receiving a kexinit message from the client to initiate
488
 * key exchange. If we haven't already done so, we send the list of our
489
 * preferred algorithms. The client's requested algorithms are processed,
490
 * and we calculate the first portion of the key-exchange-hash for used
491
 * later in the key exchange. No response is sent, as the client should
492
 * initiate the diffie-hellman key exchange */
493
11.1k
void recv_msg_kexinit() {
494
  
495
11.1k
  unsigned int kexhashbuf_len = 0;
496
11.1k
  unsigned int remote_ident_len = 0;
497
11.1k
  unsigned int local_ident_len = 0;
498
499
11.1k
  TRACE(("<- KEXINIT"))
500
11.1k
  TRACE(("enter recv_msg_kexinit"))
501
  
502
11.1k
  if (!ses.kexstate.sentkexinit) {
503
    /* we need to send a kex packet */
504
8.71k
    send_msg_kexinit();
505
8.71k
    TRACE(("continue recv_msg_kexinit: sent kexinit"))
506
8.71k
  }
507
508
  /* "Once a party has sent a SSH_MSG_KEXINIT message ...
509
  further SSH_MSG_KEXINIT messages MUST NOT be sent" */
510
11.1k
  if (ses.kexstate.recvkexinit) {
511
0
    dropbear_exit("Unexpected KEXINIT");
512
0
  }
513
514
  /* start the kex hash */
515
11.1k
  local_ident_len = strlen(LOCAL_IDENT);
516
11.1k
  remote_ident_len = strlen(ses.remoteident);
517
518
11.1k
  kexhashbuf_len = local_ident_len + remote_ident_len
519
11.1k
    + ses.transkexinit->len + ses.payload->len
520
11.1k
    + KEXHASHBUF_MAX_INTS;
521
522
11.1k
  ses.kexhashbuf = buf_new(kexhashbuf_len);
523
524
11.1k
  if (IS_DROPBEAR_CLIENT) {
525
526
    /* read the peer's choice of algos */
527
0
    read_kex_algos();
528
529
    /* V_C, the client's version string (CR and NL excluded) */
530
0
    buf_putstring(ses.kexhashbuf, LOCAL_IDENT, local_ident_len);
531
    /* V_S, the server's version string (CR and NL excluded) */
532
0
    buf_putstring(ses.kexhashbuf, ses.remoteident, remote_ident_len);
533
534
    /* I_C, the payload of the client's SSH_MSG_KEXINIT */
535
0
    buf_putstring(ses.kexhashbuf,
536
0
      (const char*)ses.transkexinit->data, ses.transkexinit->len);
537
    /* I_S, the payload of the server's SSH_MSG_KEXINIT */
538
0
    buf_setpos(ses.payload, ses.payload_beginning);
539
0
    buf_putstring(ses.kexhashbuf,
540
0
      (const char*)buf_getptr(ses.payload, ses.payload->len-ses.payload->pos),
541
0
      ses.payload->len-ses.payload->pos);
542
0
    ses.requirenext = SSH_MSG_KEXDH_REPLY;
543
11.1k
  } else {
544
    /* SERVER */
545
546
    /* read the peer's choice of algos */
547
11.1k
    read_kex_algos();
548
    /* V_C, the client's version string (CR and NL excluded) */
549
11.1k
    buf_putstring(ses.kexhashbuf, ses.remoteident, remote_ident_len);
550
    /* V_S, the server's version string (CR and NL excluded) */
551
11.1k
    buf_putstring(ses.kexhashbuf, LOCAL_IDENT, local_ident_len);
552
553
    /* I_C, the payload of the client's SSH_MSG_KEXINIT */
554
11.1k
    buf_setpos(ses.payload, ses.payload_beginning);
555
11.1k
    buf_putstring(ses.kexhashbuf, 
556
11.1k
      (const char*)buf_getptr(ses.payload, ses.payload->len-ses.payload->pos),
557
11.1k
      ses.payload->len-ses.payload->pos);
558
559
    /* I_S, the payload of the server's SSH_MSG_KEXINIT */
560
11.1k
    buf_putstring(ses.kexhashbuf,
561
11.1k
      (const char*)ses.transkexinit->data, ses.transkexinit->len);
562
563
11.1k
    ses.requirenext = SSH_MSG_KEXDH_INIT;
564
11.1k
  }
565
566
11.1k
  buf_free(ses.transkexinit);
567
11.1k
  ses.transkexinit = NULL;
568
  /* the rest of ses.kexhashbuf will be done after DH exchange */
569
570
11.1k
  ses.kexstate.recvkexinit = 1;
571
572
11.1k
  if (ses.kexstate.strict_kex && !ses.kexstate.donefirstkex && ses.recvseq != 1) {
573
8
    dropbear_exit("First packet wasn't kexinit");
574
8
  }
575
576
11.1k
  TRACE(("leave recv_msg_kexinit"))
577
11.1k
}
578
579
580
10.1k
void finish_kexhashbuf(void) {
581
10.1k
  hash_state hs;
582
10.1k
  const struct ltc_hash_descriptor *hash_desc = ses.newkeys->algo_kex->hash_desc;
583
584
10.1k
  hash_desc->init(&hs);
585
10.1k
  buf_setpos(ses.kexhashbuf, 0);
586
10.1k
  hash_desc->process(&hs, buf_getptr(ses.kexhashbuf, ses.kexhashbuf->len),
587
10.1k
      ses.kexhashbuf->len);
588
10.1k
  ses.hash = buf_new(hash_desc->hashsize);
589
10.1k
  hash_desc->done(&hs, buf_getwriteptr(ses.hash, hash_desc->hashsize));
590
10.1k
  buf_setlen(ses.hash, hash_desc->hashsize);
591
592
#if defined(DEBUG_KEXHASH) && DEBUG_TRACE
593
  if (!debug_trace) {
594
    printhex("kexhashbuf", ses.kexhashbuf->data, ses.kexhashbuf->len);
595
    printhex("kexhash", ses.hash->data, ses.hash->len);
596
  }
597
#endif
598
599
10.1k
  buf_burn_free(ses.kexhashbuf);
600
10.1k
  m_burn(&hs, sizeof(hash_state));
601
10.1k
  ses.kexhashbuf = NULL;
602
  
603
  /* first time around, we set the session_id to H */
604
10.1k
  if (ses.session_id == NULL) {
605
    /* create the session_id, this never needs freeing */
606
1.70k
    ses.session_id = buf_newcopy(ses.hash);
607
1.70k
  }
608
10.1k
}
609
610
/* read the other side's algo list. buf_match_algo is a callback to match
611
 * algos for the client or server. */
612
11.1k
static void read_kex_algos() {
613
614
  /* for asymmetry */
615
11.1k
  algo_type * c2s_hash_algo = NULL;
616
11.1k
  algo_type * s2c_hash_algo = NULL;
617
11.1k
  algo_type * c2s_cipher_algo = NULL;
618
11.1k
  algo_type * s2c_cipher_algo = NULL;
619
11.1k
  algo_type * c2s_comp_algo = NULL;
620
11.1k
  algo_type * s2c_comp_algo = NULL;
621
  /* the generic one */
622
11.1k
  algo_type * algo = NULL;
623
624
  /* which algo couldn't match */
625
11.1k
  char * erralgo = NULL;
626
627
11.1k
  int goodguess = 0;
628
11.1k
  int allgood = 1; /* we AND this with each goodguess and see if its still
629
            true after */
630
11.1k
  int kexguess2 = 0;
631
632
11.1k
  buf_incrpos(ses.payload, 16); /* start after the cookie */
633
634
11.1k
  memset(ses.newkeys, 0x0, sizeof(*ses.newkeys));
635
636
  /* kex_algorithms */
637
11.1k
#if DROPBEAR_KEXGUESS2
638
11.1k
  if (buf_has_algo(ses.payload, KEXGUESS2_ALGO_NAME) == DROPBEAR_SUCCESS) {
639
258
    kexguess2 = 1;
640
258
  }
641
11.1k
#endif
642
643
11.1k
#if DROPBEAR_EXT_INFO
644
  /* Determine if SSH_MSG_EXT_INFO messages should be sent.
645
  Should be done for the first key exchange. Only required on server side
646
    for server-sig-algs */
647
11.1k
  if (IS_DROPBEAR_SERVER) {
648
11.0k
    if (!ses.kexstate.donefirstkex) {
649
2.35k
      if (buf_has_algo(ses.payload, SSH_EXT_INFO_C) == DROPBEAR_SUCCESS) {
650
142
        ses.allow_ext_info = 1;
651
142
      }
652
2.35k
    }
653
11.0k
  }
654
11.1k
#endif
655
656
11.1k
  if (!ses.kexstate.donefirstkex) {
657
2.35k
    const char* strict_name;
658
2.35k
    if (IS_DROPBEAR_CLIENT) {
659
0
      strict_name = SSH_STRICT_KEX_S;
660
2.35k
    } else {
661
2.35k
      strict_name = SSH_STRICT_KEX_C;
662
2.35k
    }
663
2.35k
    if (buf_has_algo(ses.payload, strict_name) == DROPBEAR_SUCCESS) {
664
66
      ses.kexstate.strict_kex = 1;
665
66
    }
666
2.35k
  }
667
668
11.1k
  algo = buf_match_algo(ses.payload, sshkex, kexguess2, &goodguess);
669
11.1k
  allgood &= goodguess;
670
11.1k
  if (algo == NULL || algo->data == NULL) {
671
    /* kexguess2, ext-info-c, ext-info-s should not match negotiation */
672
224
    erralgo = "kex";
673
224
    goto error;
674
224
  }
675
10.9k
  TRACE(("kexguess2 %d", kexguess2))
676
10.9k
  DEBUG3(("kex algo %s", algo->name))
677
10.9k
  ses.newkeys->algo_kex = algo->data;
678
679
  /* server_host_key_algorithms */
680
10.9k
  algo = buf_match_algo(ses.payload, sigalgs, kexguess2, &goodguess);
681
10.9k
  allgood &= goodguess;
682
10.9k
  if (algo == NULL) {
683
8
    erralgo = "hostkey";
684
8
    goto error;
685
8
  }
686
10.9k
  DEBUG2(("hostkey algo %s", algo->name))
687
10.9k
  ses.newkeys->algo_signature = algo->val;
688
10.9k
  ses.newkeys->algo_hostkey = signkey_type_from_signature(ses.newkeys->algo_signature);
689
690
  /* encryption_algorithms_client_to_server */
691
10.9k
  c2s_cipher_algo = buf_match_algo(ses.payload, sshciphers, 0, NULL);
692
10.9k
  if (c2s_cipher_algo == NULL) {
693
19
    erralgo = "enc c->s";
694
19
    goto error;
695
19
  }
696
10.8k
  DEBUG2(("enc  c2s is %s", c2s_cipher_algo->name))
697
698
  /* encryption_algorithms_server_to_client */
699
10.8k
  s2c_cipher_algo = buf_match_algo(ses.payload, sshciphers, 0, NULL);
700
10.8k
  if (s2c_cipher_algo == NULL) {
701
10
    erralgo = "enc s->c";
702
10
    goto error;
703
10
  }
704
10.8k
  DEBUG2(("enc  s2c is %s", s2c_cipher_algo->name))
705
706
  /* mac_algorithms_client_to_server */
707
10.8k
  c2s_hash_algo = buf_match_algo(ses.payload, sshhashes, 0, NULL);
708
10.8k
#if DROPBEAR_AEAD_MODE
709
10.8k
  if (((struct dropbear_cipher_mode*)c2s_cipher_algo->mode)->aead_crypt != NULL) {
710
5.59k
    c2s_hash_algo = NULL;
711
5.59k
  } else
712
5.28k
#endif
713
5.28k
  if (c2s_hash_algo == NULL) {
714
1
    erralgo = "mac c->s";
715
1
    goto error;
716
1
  }
717
10.8k
  DEBUG2(("hmac c2s is %s", c2s_hash_algo ? c2s_hash_algo->name : "<implicit>"))
718
719
  /* mac_algorithms_server_to_client */
720
10.8k
  s2c_hash_algo = buf_match_algo(ses.payload, sshhashes, 0, NULL);
721
10.8k
#if DROPBEAR_AEAD_MODE
722
10.8k
  if (((struct dropbear_cipher_mode*)s2c_cipher_algo->mode)->aead_crypt != NULL) {
723
5.40k
    s2c_hash_algo = NULL;
724
5.40k
  } else
725
5.47k
#endif
726
5.47k
  if (s2c_hash_algo == NULL) {
727
8
    erralgo = "mac s->c";
728
8
    goto error;
729
8
  }
730
10.8k
  DEBUG2(("hmac s2c is %s", s2c_hash_algo ? s2c_hash_algo->name : "<implicit>"))
731
732
  /* compression_algorithms_client_to_server */
733
10.8k
  c2s_comp_algo = buf_match_algo(ses.payload, ses.compress_algos_c2s, 0, NULL);
734
10.8k
  if (c2s_comp_algo == NULL) {
735
9
    erralgo = "comp c->s";
736
9
    goto error;
737
9
  }
738
10.8k
  DEBUG2(("comp c2s is %s", c2s_comp_algo->name))
739
740
  /* compression_algorithms_server_to_client */
741
10.8k
  s2c_comp_algo = buf_match_algo(ses.payload, ses.compress_algos_s2c, 0, NULL);
742
10.8k
  if (s2c_comp_algo == NULL) {
743
3
    erralgo = "comp s->c";
744
3
    goto error;
745
3
  }
746
10.8k
  DEBUG2(("comp s2c is %s", s2c_comp_algo->name))
747
748
  /* languages_client_to_server */
749
10.8k
  buf_eatstring(ses.payload);
750
751
  /* languages_server_to_client */
752
10.8k
  buf_eatstring(ses.payload);
753
754
  /* their first_kex_packet_follows */
755
10.8k
  if (buf_getbool(ses.payload)) {
756
349
    TRACE(("them kex firstfollows. allgood %d", allgood))
757
349
    ses.kexstate.them_firstfollows = 1;
758
    /* if the guess wasn't good, we ignore the packet sent */
759
349
    if (!allgood) {
760
194
      ses.ignorenext = 1;
761
194
    }
762
349
  }
763
764
  /* Handle the asymmetry */
765
10.8k
  if (IS_DROPBEAR_CLIENT) {
766
0
    ses.newkeys->recv.algo_crypt = 
767
0
      (struct dropbear_cipher*)s2c_cipher_algo->data;
768
0
    ses.newkeys->trans.algo_crypt = 
769
0
      (struct dropbear_cipher*)c2s_cipher_algo->data;
770
0
    ses.newkeys->recv.crypt_mode = 
771
0
      (struct dropbear_cipher_mode*)s2c_cipher_algo->mode;
772
0
    ses.newkeys->trans.crypt_mode =
773
0
      (struct dropbear_cipher_mode*)c2s_cipher_algo->mode;
774
0
    ses.newkeys->recv.algo_mac = 
775
0
#if DROPBEAR_AEAD_MODE
776
0
      s2c_hash_algo == NULL ? ses.newkeys->recv.crypt_mode->aead_mac :
777
0
#endif
778
0
      (struct dropbear_hash*)s2c_hash_algo->data;
779
0
    ses.newkeys->trans.algo_mac = 
780
0
#if DROPBEAR_AEAD_MODE
781
0
      c2s_hash_algo == NULL ? ses.newkeys->trans.crypt_mode->aead_mac :
782
0
#endif
783
0
      (struct dropbear_hash*)c2s_hash_algo->data;
784
0
    ses.newkeys->recv.algo_comp = s2c_comp_algo->val;
785
0
    ses.newkeys->trans.algo_comp = c2s_comp_algo->val;
786
10.8k
  } else {
787
    /* SERVER */
788
10.8k
    ses.newkeys->recv.algo_crypt = 
789
10.8k
      (struct dropbear_cipher*)c2s_cipher_algo->data;
790
10.8k
    ses.newkeys->trans.algo_crypt = 
791
10.8k
      (struct dropbear_cipher*)s2c_cipher_algo->data;
792
10.8k
    ses.newkeys->recv.crypt_mode =
793
10.8k
      (struct dropbear_cipher_mode*)c2s_cipher_algo->mode;
794
10.8k
    ses.newkeys->trans.crypt_mode =
795
10.8k
      (struct dropbear_cipher_mode*)s2c_cipher_algo->mode;
796
10.8k
    ses.newkeys->recv.algo_mac = 
797
10.8k
#if DROPBEAR_AEAD_MODE
798
10.8k
      c2s_hash_algo == NULL ? ses.newkeys->recv.crypt_mode->aead_mac :
799
10.8k
#endif
800
10.8k
      (struct dropbear_hash*)c2s_hash_algo->data;
801
10.8k
    ses.newkeys->trans.algo_mac = 
802
10.8k
#if DROPBEAR_AEAD_MODE
803
10.8k
      s2c_hash_algo == NULL ? ses.newkeys->trans.crypt_mode->aead_mac :
804
10.8k
#endif
805
10.8k
      (struct dropbear_hash*)s2c_hash_algo->data;
806
10.8k
    ses.newkeys->recv.algo_comp = c2s_comp_algo->val;
807
10.8k
    ses.newkeys->trans.algo_comp = s2c_comp_algo->val;
808
10.8k
  }
809
810
10.8k
#if DROPBEAR_FUZZ
811
10.8k
  if (fuzz.fuzzing) {
812
10.5k
    fuzz_kex_fakealgos();
813
10.5k
  }
814
10.8k
#endif
815
816
  /* reserved for future extensions */
817
10.8k
  buf_getint(ses.payload);
818
819
10.8k
  if (ses.send_kex_first_guess && allgood) {
820
0
    TRACE(("our_first_follows_matches 1"))
821
0
    ses.kexstate.our_first_follows_matches = 1;
822
0
  }
823
10.8k
  return;
824
825
282
error:
826
282
  dropbear_exit("No matching algo %s", erralgo);
827
10.8k
}