Coverage Report

Created: 2025-11-13 06:08

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/dropbear/src/packet.c
Line
Count
Source
1
/*
2
 * Dropbear - a SSH2 server
3
 * 
4
 * Copyright (c) 2002,2003 Matt Johnston
5
 * All rights reserved.
6
 * 
7
 * Permission is hereby granted, free of charge, to any person obtaining a copy
8
 * of this software and associated documentation files (the "Software"), to deal
9
 * in the Software without restriction, including without limitation the rights
10
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
 * copies of the Software, and to permit persons to whom the Software is
12
 * furnished to do so, subject to the following conditions:
13
 * 
14
 * The above copyright notice and this permission notice shall be included in
15
 * all copies or substantial portions of the Software.
16
 * 
17
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23
 * SOFTWARE. */
24
25
#include "includes.h"
26
#include "packet.h"
27
#include "session.h"
28
#include "dbutil.h"
29
#include "ssh.h"
30
#include "algo.h"
31
#include "buffer.h"
32
#include "kex.h"
33
#include "dbrandom.h"
34
#include "service.h"
35
#include "auth.h"
36
#include "channel.h"
37
#include "netio.h"
38
#include "runopts.h"
39
40
static int read_packet_init(void);
41
static void make_mac(unsigned int seqno, const struct key_context_directional * key_state,
42
    buffer * clear_buf, unsigned int clear_len, 
43
    unsigned char *output_mac);
44
static int checkmac(void);
45
46
/* For exact details see http://www.zlib.net/zlib_tech.html
47
 * 5 bytes per 16kB block, plus 6 bytes for the stream.
48
 * We might allocate 5 unnecessary bytes here if it's an
49
 * exact multiple. */
50
58.1k
#define ZLIB_COMPRESS_EXPANSION (((RECV_MAX_PAYLOAD_LEN/16384)+1)*5 + 6)
51
#define ZLIB_DECOMPRESS_INCR 1024
52
#ifndef DISABLE_ZLIB
53
static buffer* buf_decompress(const buffer* buf, unsigned int len);
54
static void buf_compress(buffer * dest, buffer * src, unsigned int len);
55
#endif
56
57
/* non-blocking function writing out a current encrypted packet */
58
288k
void write_packet() {
59
60
288k
  ssize_t written;
61
288k
#if defined(HAVE_WRITEV) && (defined(IOV_MAX) || defined(UIO_MAXIOV))
62
  /* 50 is somewhat arbitrary */
63
288k
  unsigned int iov_count = 50;
64
288k
  struct iovec iov[50];
65
#else
66
  int len;
67
  buffer* writebuf;
68
#endif
69
  
70
288k
  TRACE2(("enter write_packet"))
71
288k
  dropbear_assert(!isempty(&ses.writequeue));
72
73
288k
#if defined(HAVE_WRITEV) && (defined(IOV_MAX) || defined(UIO_MAXIOV))
74
75
288k
  packet_queue_to_iovec(&ses.writequeue, iov, &iov_count);
76
  /* This may return EAGAIN. The main loop sometimes
77
  calls write_packet() without bothering to test with select() since
78
  it's likely to be necessary */
79
288k
#if DROPBEAR_FUZZ
80
288k
  if (fuzz.fuzzing) {
81
    /* pretend to write one packet at a time */
82
    /* TODO(fuzz): randomise amount written based on the fuzz input */
83
288k
    written = iov[0].iov_len;
84
288k
  }
85
0
  else
86
0
#endif
87
0
  {
88
0
  written = writev(ses.sock_out, iov, iov_count);
89
0
  if (written < 0) {
90
0
    if (errno == EINTR || errno == EAGAIN) {
91
0
      TRACE2(("leave write_packet: EINTR"))
92
0
      return;
93
0
    } else {
94
0
      dropbear_exit("Error writing: %s", strerror(errno));
95
0
    }
96
0
  }
97
0
  }
98
99
288k
  packet_queue_consume(&ses.writequeue, written);
100
288k
  ses.writequeue_len -= written;
101
102
288k
  if (written == 0) {
103
0
    ses.remoteclosed();
104
0
  }
105
106
#else /* No writev () */
107
#if DROPBEAR_FUZZ
108
  _Static_assert(0, "No fuzzing code for no-writev writes");
109
#endif
110
  /* Get the next buffer in the queue of encrypted packets to write*/
111
  writebuf = (buffer*)examine(&ses.writequeue);
112
113
  len = writebuf->len - writebuf->pos;
114
  dropbear_assert(len > 0);
115
  /* Try to write as much as possible */
116
  written = write(ses.sock_out, buf_getptr(writebuf, len), len);
117
118
  if (written < 0) {
119
    if (errno == EINTR || errno == EAGAIN) {
120
      TRACE2(("leave writepacket: EINTR"))
121
      return;
122
    } else {
123
      dropbear_exit("Error writing: %s", strerror(errno));
124
    }
125
  } 
126
127
  if (written == 0) {
128
    ses.remoteclosed();
129
  }
130
131
  ses.writequeue_len -= written;
132
133
  if (written == len) {
134
    /* We've finished with the packet, free it */
135
    dequeue(&ses.writequeue);
136
    buf_free(writebuf);
137
    writebuf = NULL;
138
  } else {
139
    /* More packet left to write, leave it in the queue for later */
140
    buf_incrpos(writebuf, written);
141
  }
142
#endif /* writev */
143
144
288k
  TRACE2(("leave write_packet"))
145
288k
}
146
147
/* Non-blocking function reading available portion of a packet into the
148
 * ses's buffer, decrypting the length if encrypted, decrypting the
149
 * full portion if possible */
150
310k
void read_packet() {
151
152
310k
  int len;
153
310k
  unsigned int maxlen;
154
310k
  unsigned char blocksize;
155
156
310k
  TRACE2(("enter read_packet"))
157
310k
  blocksize = ses.keys->recv.algo_crypt->blocksize;
158
  
159
310k
  if (ses.readbuf == NULL || ses.readbuf->len < blocksize) {
160
171k
    int ret;
161
    /* In the first blocksize of a packet */
162
163
    /* Read the first blocksize of the packet, so we can decrypt it and
164
     * find the length of the whole packet */
165
171k
    ret = read_packet_init();
166
167
171k
    if (ret == DROPBEAR_FAILURE) {
168
      /* didn't read enough to determine the length */
169
111k
      TRACE2(("leave read_packet: packetinit done"))
170
111k
      return;
171
111k
    }
172
171k
  }
173
174
  /* Attempt to read the remainder of the packet, note that there
175
   * mightn't be any available (EAGAIN) */
176
198k
  maxlen = ses.readbuf->len - ses.readbuf->pos;
177
198k
  if (maxlen == 0) {
178
    /* Occurs when the packet is only a single block long and has all
179
     * been read in read_packet_init().  Usually means that MAC is disabled
180
     */
181
9.08k
    len = 0;
182
189k
  } else {
183
189k
    len = read(ses.sock_in, buf_getptr(ses.readbuf, maxlen), maxlen);
184
185
189k
    if (len == 0) {
186
150
      ses.remoteclosed();
187
150
    }
188
189
189k
    if (len < 0) {
190
221
      if (errno == EINTR || errno == EAGAIN) {
191
220
        TRACE2(("leave read_packet: EINTR or EAGAIN"))
192
220
        return;
193
220
      } else {
194
1
        dropbear_exit("Error reading: %s", strerror(errno));
195
1
      }
196
221
    }
197
198
189k
    buf_incrpos(ses.readbuf, len);
199
189k
  }
200
201
198k
  if ((unsigned int)len == maxlen) {
202
    /* The whole packet has been read */
203
58.1k
    decrypt_packet();
204
    /* The main select() loop process_packet() to
205
     * handle the packet contents... */
206
58.1k
  }
207
198k
  TRACE2(("leave read_packet"))
208
198k
}
209
210
/* Function used to read the initial portion of a packet, and determine the
211
 * length. Only called during the first BLOCKSIZE of a packet. */
212
/* Returns DROPBEAR_SUCCESS if the length is determined, 
213
 * DROPBEAR_FAILURE otherwise */
214
171k
static int read_packet_init() {
215
216
171k
  unsigned int maxlen;
217
171k
  int slen;
218
171k
  unsigned int len, plen;
219
171k
  unsigned int blocksize;
220
171k
  unsigned int macsize;
221
222
223
171k
  blocksize = ses.keys->recv.algo_crypt->blocksize;
224
171k
  macsize = ses.keys->recv.algo_mac->hashsize;
225
226
171k
  if (ses.readbuf == NULL) {
227
    /* start of a new packet */
228
59.5k
    ses.readbuf = buf_new(INIT_READBUF);
229
59.5k
  }
230
231
171k
  maxlen = blocksize - ses.readbuf->pos;
232
      
233
  /* read the rest of the packet if possible */
234
171k
  slen = read(ses.sock_in, buf_getwriteptr(ses.readbuf, maxlen),
235
171k
      maxlen);
236
171k
  if (slen == 0) {
237
1.05k
    ses.remoteclosed();
238
1.05k
  }
239
171k
  if (slen < 0) {
240
171
    if (errno == EINTR || errno == EAGAIN) {
241
168
      TRACE2(("leave read_packet_init: EINTR"))
242
168
      return DROPBEAR_FAILURE;
243
168
    }
244
3
    dropbear_exit("Error reading: %s", strerror(errno));
245
171
  }
246
247
170k
  buf_incrwritepos(ses.readbuf, slen);
248
249
170k
  if ((unsigned int)slen != maxlen) {
250
    /* don't have enough bytes to determine length, get next time */
251
111k
    return DROPBEAR_FAILURE;
252
111k
  }
253
254
  /* now we have the first block, need to get packet length, so we decrypt
255
   * the first block (only need first 4 bytes) */
256
59.4k
  buf_setpos(ses.readbuf, 0);
257
59.4k
#if DROPBEAR_AEAD_MODE
258
59.4k
  if (ses.keys->recv.crypt_mode->aead_crypt) {
259
0
    if (ses.keys->recv.crypt_mode->aead_getlength(ses.recvseq,
260
0
          buf_getptr(ses.readbuf, blocksize), &plen,
261
0
          blocksize,
262
0
          &ses.keys->recv.cipher_state) != CRYPT_OK) {
263
0
      dropbear_exit("Error decrypting");
264
0
    }
265
0
    len = plen + 4 + macsize;
266
0
  } else
267
59.4k
#endif
268
59.4k
  {
269
59.4k
    if (ses.keys->recv.crypt_mode->decrypt(buf_getptr(ses.readbuf, blocksize), 
270
59.4k
          buf_getwriteptr(ses.readbuf, blocksize),
271
59.4k
          blocksize,
272
59.4k
          &ses.keys->recv.cipher_state) != CRYPT_OK) {
273
0
      dropbear_exit("Error decrypting");
274
0
    }
275
59.4k
    plen = buf_getint(ses.readbuf) + 4;
276
59.4k
    len = plen + macsize;
277
59.4k
  }
278
279
59.4k
  TRACE2(("packet size is %u, block %u mac %u", len, blocksize, macsize))
280
281
282
  /* check packet length */
283
59.4k
  if ((len > RECV_MAX_PACKET_LEN) ||
284
58.3k
    (plen < blocksize) ||
285
58.3k
    (plen % blocksize != 0)) {
286
97
    dropbear_exit("Integrity error (bad packet size %u)", len);
287
97
  }
288
289
59.4k
  if (len > ses.readbuf->size) {
290
9.30k
    ses.readbuf = buf_resize(ses.readbuf, len);   
291
9.30k
  }
292
59.4k
  buf_setlen(ses.readbuf, len);
293
59.4k
  buf_setpos(ses.readbuf, blocksize);
294
59.4k
  return DROPBEAR_SUCCESS;
295
59.4k
}
296
297
/* handle the received packet */
298
58.1k
void decrypt_packet() {
299
300
58.1k
  unsigned char blocksize;
301
58.1k
  unsigned char macsize;
302
58.1k
  unsigned int padlen;
303
58.1k
  unsigned int len;
304
305
58.1k
  TRACE2(("enter decrypt_packet"))
306
58.1k
  blocksize = ses.keys->recv.algo_crypt->blocksize;
307
58.1k
  macsize = ses.keys->recv.algo_mac->hashsize;
308
309
58.1k
  ses.kexstate.datarecv += ses.readbuf->len;
310
311
58.1k
#if DROPBEAR_AEAD_MODE
312
58.1k
  if (ses.keys->recv.crypt_mode->aead_crypt) {
313
    /* first blocksize is not decrypted yet */
314
0
    buf_setpos(ses.readbuf, 0);
315
316
    /* decrypt it in-place */
317
0
    len = ses.readbuf->len - macsize - ses.readbuf->pos;
318
0
    if (ses.keys->recv.crypt_mode->aead_crypt(ses.recvseq,
319
0
          buf_getptr(ses.readbuf, len + macsize),
320
0
          buf_getwriteptr(ses.readbuf, len),
321
0
          len, macsize,
322
0
          &ses.keys->recv.cipher_state, LTC_DECRYPT) != CRYPT_OK) {
323
0
      dropbear_exit("Error decrypting");
324
0
    }
325
0
    buf_incrpos(ses.readbuf, len);
326
0
  } else
327
58.1k
#endif
328
58.1k
  {
329
    /* we've already decrypted the first blocksize in read_packet_init */
330
58.1k
    buf_setpos(ses.readbuf, blocksize);
331
332
    /* decrypt it in-place */
333
58.1k
    len = ses.readbuf->len - macsize - ses.readbuf->pos;
334
58.1k
    if (ses.keys->recv.crypt_mode->decrypt(
335
58.1k
          buf_getptr(ses.readbuf, len), 
336
58.1k
          buf_getwriteptr(ses.readbuf, len),
337
58.1k
          len,
338
58.1k
          &ses.keys->recv.cipher_state) != CRYPT_OK) {
339
0
      dropbear_exit("Error decrypting");
340
0
    }
341
58.1k
    buf_incrpos(ses.readbuf, len);
342
343
    /* check the hmac */
344
58.1k
    if (checkmac() != DROPBEAR_SUCCESS) {
345
0
      dropbear_exit("Integrity error");
346
0
    }
347
348
58.1k
  }
349
  
350
58.1k
#if DROPBEAR_FUZZ
351
58.1k
  fuzz_dump(ses.readbuf->data, ses.readbuf->len);
352
58.1k
#endif
353
354
  /* get padding length */
355
58.1k
  buf_setpos(ses.readbuf, PACKET_PADDING_OFF);
356
58.1k
  padlen = buf_getbyte(ses.readbuf);
357
    
358
  /* payload length */
359
  /* - 4 - 1 is for LEN and PADLEN values */
360
58.1k
  len = ses.readbuf->len - padlen - 4 - 1 - macsize;
361
58.1k
  if ((len > RECV_MAX_PAYLOAD_LEN+ZLIB_COMPRESS_EXPANSION) || (len < 1)) {
362
3
    dropbear_exit("Bad packet size %u", len);
363
3
  }
364
365
58.1k
  buf_setpos(ses.readbuf, PACKET_PAYLOAD_OFF);
366
367
#ifndef DISABLE_ZLIB
368
  if (is_compress_recv()) {
369
    /* decompress */
370
    ses.payload = buf_decompress(ses.readbuf, len);
371
    buf_setpos(ses.payload, 0);
372
    ses.payload_beginning = 0;
373
    buf_free(ses.readbuf);
374
  } else 
375
#endif
376
58.1k
  {
377
58.1k
    ses.payload = ses.readbuf;
378
58.1k
    ses.payload_beginning = ses.payload->pos;
379
58.1k
    buf_setlen(ses.payload, ses.payload->pos + len);
380
58.1k
  }
381
58.1k
  ses.readbuf = NULL;
382
383
58.1k
  ses.recvseq++;
384
385
58.1k
  TRACE2(("leave decrypt_packet"))
386
58.1k
}
387
388
/* Checks the mac at the end of a decrypted readbuf.
389
 * Returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE */
390
58.1k
static int checkmac() {
391
392
58.1k
  unsigned char mac_bytes[MAX_MAC_LEN];
393
58.1k
  unsigned int mac_size, contents_len;
394
  
395
58.1k
  mac_size = ses.keys->recv.algo_mac->hashsize;
396
58.1k
  contents_len = ses.readbuf->len - mac_size;
397
398
58.1k
  buf_setpos(ses.readbuf, 0);
399
58.1k
  make_mac(ses.recvseq, &ses.keys->recv, ses.readbuf, contents_len, mac_bytes);
400
401
58.1k
#if DROPBEAR_FUZZ
402
58.1k
  if (fuzz.fuzzing) {
403
    /* fail 1 in 2000 times to test error path. */
404
58.1k
    unsigned int value = 0;
405
58.1k
    if (mac_size > sizeof(value)) {
406
0
      memcpy(&value, mac_bytes, sizeof(value));
407
0
    }
408
58.1k
    if (value % 2000 == 99) {
409
0
      return DROPBEAR_FAILURE;
410
0
    }
411
58.1k
    return DROPBEAR_SUCCESS;
412
58.1k
  }
413
0
#endif
414
415
  /* compare the hash */
416
0
  buf_setpos(ses.readbuf, contents_len);
417
0
  if (constant_time_memcmp(mac_bytes, buf_getptr(ses.readbuf, mac_size), mac_size) != 0) {
418
0
    return DROPBEAR_FAILURE;
419
0
  } else {
420
0
    return DROPBEAR_SUCCESS;
421
0
  }
422
0
}
423
424
#ifndef DISABLE_ZLIB
425
/* returns a pointer to a newly created buffer */
426
static buffer* buf_decompress(const buffer* buf, unsigned int len) {
427
428
  int result;
429
  buffer * ret;
430
  z_streamp zstream;
431
432
  zstream = ses.keys->recv.zstream;
433
  /* We use RECV_MAX_PAYLOAD_LEN+1 here to ensure that
434
     we can detect an oversized payload after inflate() */
435
  ret = buf_new(RECV_MAX_PAYLOAD_LEN+1);
436
437
  zstream->avail_in = len;
438
  zstream->next_in = buf_getptr(buf, len);
439
  zstream->avail_out = ret->size;
440
  zstream->next_out = ret->data;
441
442
  result = inflate(zstream, Z_SYNC_FLUSH);
443
  if (result != Z_OK) {
444
    dropbear_exit("zlib error");
445
  }
446
447
  buf_setlen(ret, ret->size - zstream->avail_out);
448
449
  if (zstream->avail_in > 0 || ret->len > RECV_MAX_PAYLOAD_LEN) {
450
    /* The remote side sent larger than a payload size
451
     * of uncompressed data.
452
     */
453
    dropbear_exit("bad packet, oversized decompressed");
454
  }
455
456
  /* Success. All input was consumed and avail_out > 0 */
457
  return ret;
458
459
}
460
#endif
461
462
463
/* returns 1 if the packet is a valid type during kex (see 7.1 of rfc4253) */
464
10.9k
static int packet_is_okay_kex(unsigned char type) {
465
10.9k
  if (type >= SSH_MSG_USERAUTH_REQUEST) {
466
1.15k
    return 0;
467
1.15k
  }
468
9.82k
  if (type == SSH_MSG_SERVICE_REQUEST || type == SSH_MSG_SERVICE_ACCEPT) {
469
0
    return 0;
470
0
  }
471
9.82k
  if (type == SSH_MSG_KEXINIT) {
472
    /* XXX should this die horribly if !dataallowed ?? */
473
0
    return 0;
474
0
  }
475
9.82k
  return 1;
476
9.82k
}
477
478
1.15k
static void enqueue_reply_packet() {
479
1.15k
  struct packetlist * new_item = NULL;
480
1.15k
  new_item = m_malloc(sizeof(struct packetlist));
481
1.15k
  new_item->next = NULL;
482
  
483
1.15k
  new_item->payload = buf_newcopy(ses.writepayload);
484
1.15k
  buf_setpos(ses.writepayload, 0);
485
1.15k
  buf_setlen(ses.writepayload, 0);
486
  
487
1.15k
  if (ses.reply_queue_tail) {
488
937
    ses.reply_queue_tail->next = new_item;
489
937
  } else {
490
218
    ses.reply_queue_head = new_item;
491
218
  }
492
1.15k
  ses.reply_queue_tail = new_item;
493
1.15k
}
494
495
537k
void maybe_flush_reply_queue() {
496
537k
  struct packetlist *tmp_item = NULL, *curr_item = NULL;
497
537k
  if (!ses.dataallowed)
498
62.8k
  {
499
62.8k
    TRACE(("maybe_empty_reply_queue - no data allowed"))
500
62.8k
    return;
501
62.8k
  }
502
    
503
475k
  for (curr_item = ses.reply_queue_head; curr_item; ) {
504
1.01k
    CHECKCLEARTOWRITE();
505
1.01k
    buf_putbytes(ses.writepayload,
506
1.01k
      curr_item->payload->data, curr_item->payload->len);
507
      
508
1.01k
    buf_free(curr_item->payload);
509
1.01k
    tmp_item = curr_item;
510
1.01k
    curr_item = curr_item->next;
511
1.01k
    m_free(tmp_item);
512
1.01k
    encrypt_packet();
513
1.01k
  }
514
474k
  ses.reply_queue_head = ses.reply_queue_tail = NULL;
515
474k
}
516
  
517
/* encrypt the writepayload, putting into writebuf, ready for write_packet()
518
 * to put on the wire */
519
294k
void encrypt_packet() {
520
521
294k
  unsigned char padlen;
522
294k
  unsigned char blocksize, mac_size;
523
294k
  buffer * writebuf; /* the packet which will go on the wire. This is 
524
                        encrypted in-place. */
525
294k
  unsigned char packet_type;
526
294k
  unsigned int len, encrypt_buf_size;
527
294k
  unsigned char mac_bytes[MAX_MAC_LEN];
528
529
294k
  time_t now;
530
  
531
294k
  TRACE2(("enter encrypt_packet()"))
532
533
294k
  buf_setpos(ses.writepayload, 0);
534
294k
  packet_type = buf_getbyte(ses.writepayload);
535
294k
  buf_setpos(ses.writepayload, 0);
536
537
294k
  TRACE2(("encrypt_packet type is %d", packet_type))
538
  
539
294k
  if ((!ses.dataallowed && !packet_is_okay_kex(packet_type))) {
540
    /* During key exchange only particular packets are allowed.
541
      Since this packet_type isn't OK we just enqueue it to send 
542
      after the KEX, see maybe_flush_reply_queue */
543
1.15k
    enqueue_reply_packet();
544
1.15k
    return;
545
1.15k
  }
546
    
547
293k
  blocksize = ses.keys->trans.algo_crypt->blocksize;
548
293k
  mac_size = ses.keys->trans.algo_mac->hashsize;
549
550
  /* Encrypted packet len is payload+5. We need to then make sure
551
   * there is enough space for padding or MIN_PACKET_LEN. 
552
   * Add extra 3 since we need at least 4 bytes of padding */
553
293k
  encrypt_buf_size = (ses.writepayload->len+4+1) 
554
293k
    + MAX(MIN_PACKET_LEN, blocksize) + 3
555
  /* add space for the MAC at the end */
556
293k
        + mac_size
557
#ifndef DISABLE_ZLIB
558
  /* some extra in case 'compression' makes it larger */
559
        + ZLIB_COMPRESS_EXPANSION
560
#endif
561
  /* and an extra cleartext (stripped before transmission) byte for the
562
   * packet type */
563
293k
        + 1;
564
565
293k
  writebuf = buf_new(encrypt_buf_size);
566
293k
  buf_setlen(writebuf, PACKET_PAYLOAD_OFF);
567
293k
  buf_setpos(writebuf, PACKET_PAYLOAD_OFF);
568
569
#ifndef DISABLE_ZLIB
570
  /* compression */
571
  if (is_compress_trans()) {
572
    buf_compress(writebuf, ses.writepayload, ses.writepayload->len);
573
  } else
574
#endif
575
293k
  {
576
293k
    memcpy(buf_getwriteptr(writebuf, ses.writepayload->len),
577
293k
        buf_getptr(ses.writepayload, ses.writepayload->len),
578
293k
        ses.writepayload->len);
579
293k
    buf_incrwritepos(writebuf, ses.writepayload->len);
580
293k
  }
581
582
  /* finished with payload */
583
293k
  buf_setpos(ses.writepayload, 0);
584
293k
  buf_setlen(ses.writepayload, 0);
585
586
  /* length of padding - packet length excluding the packetlength uint32
587
   * field in aead mode must be a multiple of blocksize, with a minimum of
588
   * 4 bytes of padding */
589
293k
  len = writebuf->len;
590
293k
#if DROPBEAR_AEAD_MODE
591
293k
  if (ses.keys->trans.crypt_mode->aead_crypt) {
592
231k
    len -= 4;
593
231k
  }
594
293k
#endif
595
293k
  padlen = blocksize - len % blocksize;
596
293k
  if (padlen < 4) {
597
100k
    padlen += blocksize;
598
100k
  }
599
  /* check for min packet length */
600
293k
  if (writebuf->len + padlen < MIN_PACKET_LEN) {
601
4.00k
    padlen += blocksize;
602
4.00k
  }
603
604
293k
  buf_setpos(writebuf, 0);
605
  /* packet length excluding the packetlength uint32 */
606
293k
  buf_putint(writebuf, writebuf->len + padlen - 4);
607
608
  /* padding len */
609
293k
  buf_putbyte(writebuf, padlen);
610
  /* actual padding */
611
293k
  buf_setpos(writebuf, writebuf->len);
612
293k
  buf_incrlen(writebuf, padlen);
613
293k
  genrandom(buf_getptr(writebuf, padlen), padlen);
614
615
293k
#if DROPBEAR_AEAD_MODE
616
293k
  if (ses.keys->trans.crypt_mode->aead_crypt) {
617
    /* do the actual encryption, in-place */
618
231k
    buf_setpos(writebuf, 0);
619
    /* encrypt it in-place*/
620
231k
    len = writebuf->len;
621
231k
    buf_incrlen(writebuf, mac_size);
622
231k
    if (ses.keys->trans.crypt_mode->aead_crypt(ses.transseq,
623
231k
          buf_getptr(writebuf, len),
624
231k
          buf_getwriteptr(writebuf, len + mac_size),
625
231k
          len, mac_size,
626
231k
          &ses.keys->trans.cipher_state, LTC_ENCRYPT) != CRYPT_OK) {
627
0
      dropbear_exit("Error encrypting");
628
0
    }
629
231k
    buf_incrpos(writebuf, len + mac_size);
630
231k
  } else
631
61.0k
#endif
632
61.0k
  {
633
61.0k
    make_mac(ses.transseq, &ses.keys->trans, writebuf, writebuf->len, mac_bytes);
634
635
    /* do the actual encryption, in-place */
636
61.0k
    buf_setpos(writebuf, 0);
637
    /* encrypt it in-place*/
638
61.0k
    len = writebuf->len;
639
61.0k
    if (ses.keys->trans.crypt_mode->encrypt(
640
61.0k
          buf_getptr(writebuf, len),
641
61.0k
          buf_getwriteptr(writebuf, len),
642
61.0k
          len,
643
61.0k
          &ses.keys->trans.cipher_state) != CRYPT_OK) {
644
0
      dropbear_exit("Error encrypting");
645
0
    }
646
61.0k
    buf_incrpos(writebuf, len);
647
648
    /* stick the MAC on it */
649
61.0k
    buf_putbytes(writebuf, mac_bytes, mac_size);
650
61.0k
  }
651
652
  /* Update counts */
653
293k
  ses.kexstate.datatrans += writebuf->len;
654
655
293k
  writebuf_enqueue(writebuf);
656
657
  /* Update counts */
658
293k
  ses.transseq++;
659
660
293k
  now = monotonic_now();
661
293k
  ses.last_packet_time_any_sent = now;
662
  /* idle timeout shouldn't be affected by responses to keepalives.
663
  send_msg_keepalive() itself also does tricks with 
664
  ses.last_packet_idle_time - read that if modifying this code */
665
293k
  if (packet_type != SSH_MSG_REQUEST_FAILURE
666
291k
    && packet_type != SSH_MSG_UNIMPLEMENTED
667
288k
    && packet_type != SSH_MSG_IGNORE) {
668
288k
    ses.last_packet_time_idle = now;
669
670
288k
  }
671
672
293k
  TRACE2(("leave encrypt_packet()"))
673
293k
}
674
675
294k
void writebuf_enqueue(buffer * writebuf) {
676
  /* enqueue the packet for sending. It will get freed after transmission. */
677
294k
  buf_setpos(writebuf, 0);
678
294k
  enqueue(&ses.writequeue, (void*)writebuf);
679
294k
  ses.writequeue_len += writebuf->len;
680
294k
}
681
682
683
/* Create the packet mac, and append H(seqno|clearbuf) to the output */
684
/* output_mac must have ses.keys->trans.algo_mac->hashsize bytes. */
685
static void make_mac(unsigned int seqno, const struct key_context_directional * key_state,
686
    buffer * clear_buf, unsigned int clear_len, 
687
119k
    unsigned char *output_mac) {
688
119k
  unsigned char seqbuf[4];
689
119k
  unsigned long bufsize;
690
119k
  hmac_state hmac;
691
692
119k
  if (key_state->algo_mac->hashsize > 0) {
693
    /* calculate the mac */
694
56.1k
    if (hmac_init(&hmac, 
695
56.1k
          key_state->hash_index,
696
56.1k
          key_state->mackey,
697
56.1k
          key_state->algo_mac->keysize) != CRYPT_OK) {
698
0
      dropbear_exit("HMAC error");
699
0
    }
700
  
701
    /* sequence number */
702
56.1k
    STORE32H(seqno, seqbuf);
703
56.1k
    if (hmac_process(&hmac, seqbuf, 4) != CRYPT_OK) {
704
0
      dropbear_exit("HMAC error");
705
0
    }
706
  
707
    /* the actual contents */
708
56.1k
    buf_setpos(clear_buf, 0);
709
56.1k
    if (hmac_process(&hmac, 
710
56.1k
          buf_getptr(clear_buf, clear_len),
711
56.1k
          clear_len) != CRYPT_OK) {
712
0
      dropbear_exit("HMAC error");
713
0
    }
714
  
715
56.1k
    bufsize = MAX_MAC_LEN;
716
56.1k
    if (hmac_done(&hmac, output_mac, &bufsize) != CRYPT_OK) {
717
0
      dropbear_exit("HMAC error");
718
0
    }
719
56.1k
  }
720
119k
  TRACE2(("leave writemac"))
721
119k
}
722
723
#ifndef DISABLE_ZLIB
724
/* compresses len bytes from src, outputting to dest (starting from the
725
 * respective current positions. dest must have sufficient space,
726
 * len+ZLIB_COMPRESS_EXPANSION */
727
static void buf_compress(buffer * dest, buffer * src, unsigned int len) {
728
729
  unsigned int endpos = src->pos + len;
730
  int result;
731
732
  TRACE2(("enter buf_compress"))
733
734
  dropbear_assert(dest->size - dest->pos >= len+ZLIB_COMPRESS_EXPANSION);
735
736
  ses.keys->trans.zstream->avail_in = endpos - src->pos;
737
  ses.keys->trans.zstream->next_in = 
738
    buf_getptr(src, ses.keys->trans.zstream->avail_in);
739
740
  ses.keys->trans.zstream->avail_out = dest->size - dest->pos;
741
  ses.keys->trans.zstream->next_out =
742
    buf_getwriteptr(dest, ses.keys->trans.zstream->avail_out);
743
744
  result = deflate(ses.keys->trans.zstream, Z_SYNC_FLUSH);
745
746
  buf_setpos(src, endpos - ses.keys->trans.zstream->avail_in);
747
  buf_setlen(dest, dest->size - ses.keys->trans.zstream->avail_out);
748
  buf_setpos(dest, dest->len);
749
750
  if (result != Z_OK) {
751
    dropbear_exit("zlib error");
752
  }
753
754
  /* fails if destination buffer wasn't large enough */
755
  dropbear_assert(ses.keys->trans.zstream->avail_in == 0);
756
  TRACE2(("leave buf_compress"))
757
}
758
#endif