Coverage Report

Created: 2025-08-09 07:10

/src/dropbear/src/packet.c
Line
Count
Source (jump to first uncovered line)
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
0
#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
0
void write_packet() {
59
60
0
  ssize_t written;
61
0
#if defined(HAVE_WRITEV) && (defined(IOV_MAX) || defined(UIO_MAXIOV))
62
  /* 50 is somewhat arbitrary */
63
0
  unsigned int iov_count = 50;
64
0
  struct iovec iov[50];
65
#else
66
  int len;
67
  buffer* writebuf;
68
#endif
69
  
70
0
  TRACE2(("enter write_packet"))
71
0
  dropbear_assert(!isempty(&ses.writequeue));
72
73
0
#if defined(HAVE_WRITEV) && (defined(IOV_MAX) || defined(UIO_MAXIOV))
74
75
0
  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
0
#if DROPBEAR_FUZZ
80
0
  if (fuzz.fuzzing) {
81
    /* pretend to write one packet at a time */
82
    /* TODO(fuzz): randomise amount written based on the fuzz input */
83
0
    written = iov[0].iov_len;
84
0
  }
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
0
  packet_queue_consume(&ses.writequeue, written);
100
0
  ses.writequeue_len -= written;
101
102
0
  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
0
  TRACE2(("leave write_packet"))
145
0
}
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
0
void read_packet() {
151
152
0
  int len;
153
0
  unsigned int maxlen;
154
0
  unsigned char blocksize;
155
156
0
  TRACE2(("enter read_packet"))
157
0
  blocksize = ses.keys->recv.algo_crypt->blocksize;
158
  
159
0
  if (ses.readbuf == NULL || ses.readbuf->len < blocksize) {
160
0
    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
0
    ret = read_packet_init();
166
167
0
    if (ret == DROPBEAR_FAILURE) {
168
      /* didn't read enough to determine the length */
169
0
      TRACE2(("leave read_packet: packetinit done"))
170
0
      return;
171
0
    }
172
0
  }
173
174
  /* Attempt to read the remainder of the packet, note that there
175
   * mightn't be any available (EAGAIN) */
176
0
  maxlen = ses.readbuf->len - ses.readbuf->pos;
177
0
  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
0
    len = 0;
182
0
  } else {
183
0
    len = read(ses.sock_in, buf_getptr(ses.readbuf, maxlen), maxlen);
184
185
0
    if (len == 0) {
186
0
      ses.remoteclosed();
187
0
    }
188
189
0
    if (len < 0) {
190
0
      if (errno == EINTR || errno == EAGAIN) {
191
0
        TRACE2(("leave read_packet: EINTR or EAGAIN"))
192
0
        return;
193
0
      } else {
194
0
        dropbear_exit("Error reading: %s", strerror(errno));
195
0
      }
196
0
    }
197
198
0
    buf_incrpos(ses.readbuf, len);
199
0
  }
200
201
0
  if ((unsigned int)len == maxlen) {
202
    /* The whole packet has been read */
203
0
    decrypt_packet();
204
    /* The main select() loop process_packet() to
205
     * handle the packet contents... */
206
0
  }
207
0
  TRACE2(("leave read_packet"))
208
0
}
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
0
static int read_packet_init() {
215
216
0
  unsigned int maxlen;
217
0
  int slen;
218
0
  unsigned int len, plen;
219
0
  unsigned int blocksize;
220
0
  unsigned int macsize;
221
222
223
0
  blocksize = ses.keys->recv.algo_crypt->blocksize;
224
0
  macsize = ses.keys->recv.algo_mac->hashsize;
225
226
0
  if (ses.readbuf == NULL) {
227
    /* start of a new packet */
228
0
    ses.readbuf = buf_new(INIT_READBUF);
229
0
  }
230
231
0
  maxlen = blocksize - ses.readbuf->pos;
232
      
233
  /* read the rest of the packet if possible */
234
0
  slen = read(ses.sock_in, buf_getwriteptr(ses.readbuf, maxlen),
235
0
      maxlen);
236
0
  if (slen == 0) {
237
0
    ses.remoteclosed();
238
0
  }
239
0
  if (slen < 0) {
240
0
    if (errno == EINTR || errno == EAGAIN) {
241
0
      TRACE2(("leave read_packet_init: EINTR"))
242
0
      return DROPBEAR_FAILURE;
243
0
    }
244
0
    dropbear_exit("Error reading: %s", strerror(errno));
245
0
  }
246
247
0
  buf_incrwritepos(ses.readbuf, slen);
248
249
0
  if ((unsigned int)slen != maxlen) {
250
    /* don't have enough bytes to determine length, get next time */
251
0
    return DROPBEAR_FAILURE;
252
0
  }
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
0
  buf_setpos(ses.readbuf, 0);
257
0
#if DROPBEAR_AEAD_MODE
258
0
  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
0
#endif
268
0
  {
269
0
    if (ses.keys->recv.crypt_mode->decrypt(buf_getptr(ses.readbuf, blocksize), 
270
0
          buf_getwriteptr(ses.readbuf, blocksize),
271
0
          blocksize,
272
0
          &ses.keys->recv.cipher_state) != CRYPT_OK) {
273
0
      dropbear_exit("Error decrypting");
274
0
    }
275
0
    plen = buf_getint(ses.readbuf) + 4;
276
0
    len = plen + macsize;
277
0
  }
278
279
0
  TRACE2(("packet size is %u, block %u mac %u", len, blocksize, macsize))
280
281
282
  /* check packet length */
283
0
  if ((len > RECV_MAX_PACKET_LEN) ||
284
0
    (plen < blocksize) ||
285
0
    (plen % blocksize != 0)) {
286
0
    dropbear_exit("Integrity error (bad packet size %u)", len);
287
0
  }
288
289
0
  if (len > ses.readbuf->size) {
290
0
    ses.readbuf = buf_resize(ses.readbuf, len);   
291
0
  }
292
0
  buf_setlen(ses.readbuf, len);
293
0
  buf_setpos(ses.readbuf, blocksize);
294
0
  return DROPBEAR_SUCCESS;
295
0
}
296
297
/* handle the received packet */
298
0
void decrypt_packet() {
299
300
0
  unsigned char blocksize;
301
0
  unsigned char macsize;
302
0
  unsigned int padlen;
303
0
  unsigned int len;
304
305
0
  TRACE2(("enter decrypt_packet"))
306
0
  blocksize = ses.keys->recv.algo_crypt->blocksize;
307
0
  macsize = ses.keys->recv.algo_mac->hashsize;
308
309
0
  ses.kexstate.datarecv += ses.readbuf->len;
310
311
0
#if DROPBEAR_AEAD_MODE
312
0
  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
0
#endif
328
0
  {
329
    /* we've already decrypted the first blocksize in read_packet_init */
330
0
    buf_setpos(ses.readbuf, blocksize);
331
332
    /* decrypt it in-place */
333
0
    len = ses.readbuf->len - macsize - ses.readbuf->pos;
334
0
    if (ses.keys->recv.crypt_mode->decrypt(
335
0
          buf_getptr(ses.readbuf, len), 
336
0
          buf_getwriteptr(ses.readbuf, len),
337
0
          len,
338
0
          &ses.keys->recv.cipher_state) != CRYPT_OK) {
339
0
      dropbear_exit("Error decrypting");
340
0
    }
341
0
    buf_incrpos(ses.readbuf, len);
342
343
    /* check the hmac */
344
0
    if (checkmac() != DROPBEAR_SUCCESS) {
345
0
      dropbear_exit("Integrity error");
346
0
    }
347
348
0
  }
349
  
350
0
#if DROPBEAR_FUZZ
351
0
  fuzz_dump(ses.readbuf->data, ses.readbuf->len);
352
0
#endif
353
354
  /* get padding length */
355
0
  buf_setpos(ses.readbuf, PACKET_PADDING_OFF);
356
0
  padlen = buf_getbyte(ses.readbuf);
357
    
358
  /* payload length */
359
  /* - 4 - 1 is for LEN and PADLEN values */
360
0
  len = ses.readbuf->len - padlen - 4 - 1 - macsize;
361
0
  if ((len > RECV_MAX_PAYLOAD_LEN+ZLIB_COMPRESS_EXPANSION) || (len < 1)) {
362
0
    dropbear_exit("Bad packet size %u", len);
363
0
  }
364
365
0
  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
0
  {
377
0
    ses.payload = ses.readbuf;
378
0
    ses.payload_beginning = ses.payload->pos;
379
0
    buf_setlen(ses.payload, ses.payload->pos + len);
380
0
  }
381
0
  ses.readbuf = NULL;
382
383
0
  ses.recvseq++;
384
385
0
  TRACE2(("leave decrypt_packet"))
386
0
}
387
388
/* Checks the mac at the end of a decrypted readbuf.
389
 * Returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE */
390
0
static int checkmac() {
391
392
0
  unsigned char mac_bytes[MAX_MAC_LEN];
393
0
  unsigned int mac_size, contents_len;
394
  
395
0
  mac_size = ses.keys->recv.algo_mac->hashsize;
396
0
  contents_len = ses.readbuf->len - mac_size;
397
398
0
  buf_setpos(ses.readbuf, 0);
399
0
  make_mac(ses.recvseq, &ses.keys->recv, ses.readbuf, contents_len, mac_bytes);
400
401
0
#if DROPBEAR_FUZZ
402
0
  if (fuzz.fuzzing) {
403
    /* fail 1 in 2000 times to test error path. */
404
0
    unsigned int value = 0;
405
0
    if (mac_size > sizeof(value)) {
406
0
      memcpy(&value, mac_bytes, sizeof(value));
407
0
    }
408
0
    if (value % 2000 == 99) {
409
0
      return DROPBEAR_FAILURE;
410
0
    }
411
0
    return DROPBEAR_SUCCESS;
412
0
  }
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
0
static int packet_is_okay_kex(unsigned char type) {
465
0
  if (type >= SSH_MSG_USERAUTH_REQUEST) {
466
0
    return 0;
467
0
  }
468
0
  if (type == SSH_MSG_SERVICE_REQUEST || type == SSH_MSG_SERVICE_ACCEPT) {
469
0
    return 0;
470
0
  }
471
0
  if (type == SSH_MSG_KEXINIT) {
472
    /* XXX should this die horribly if !dataallowed ?? */
473
0
    return 0;
474
0
  }
475
0
  return 1;
476
0
}
477
478
0
static void enqueue_reply_packet() {
479
0
  struct packetlist * new_item = NULL;
480
0
  new_item = m_malloc(sizeof(struct packetlist));
481
0
  new_item->next = NULL;
482
  
483
0
  new_item->payload = buf_newcopy(ses.writepayload);
484
0
  buf_setpos(ses.writepayload, 0);
485
0
  buf_setlen(ses.writepayload, 0);
486
  
487
0
  if (ses.reply_queue_tail) {
488
0
    ses.reply_queue_tail->next = new_item;
489
0
  } else {
490
0
    ses.reply_queue_head = new_item;
491
0
  }
492
0
  ses.reply_queue_tail = new_item;
493
0
}
494
495
0
void maybe_flush_reply_queue() {
496
0
  struct packetlist *tmp_item = NULL, *curr_item = NULL;
497
0
  if (!ses.dataallowed)
498
0
  {
499
0
    TRACE(("maybe_empty_reply_queue - no data allowed"))
500
0
    return;
501
0
  }
502
    
503
0
  for (curr_item = ses.reply_queue_head; curr_item; ) {
504
0
    CHECKCLEARTOWRITE();
505
0
    buf_putbytes(ses.writepayload,
506
0
      curr_item->payload->data, curr_item->payload->len);
507
      
508
0
    buf_free(curr_item->payload);
509
0
    tmp_item = curr_item;
510
0
    curr_item = curr_item->next;
511
0
    m_free(tmp_item);
512
0
    encrypt_packet();
513
0
  }
514
0
  ses.reply_queue_head = ses.reply_queue_tail = NULL;
515
0
}
516
  
517
/* encrypt the writepayload, putting into writebuf, ready for write_packet()
518
 * to put on the wire */
519
0
void encrypt_packet() {
520
521
0
  unsigned char padlen;
522
0
  unsigned char blocksize, mac_size;
523
0
  buffer * writebuf; /* the packet which will go on the wire. This is 
524
                        encrypted in-place. */
525
0
  unsigned char packet_type;
526
0
  unsigned int len, encrypt_buf_size;
527
0
  unsigned char mac_bytes[MAX_MAC_LEN];
528
529
0
  time_t now;
530
  
531
0
  TRACE2(("enter encrypt_packet()"))
532
533
0
  buf_setpos(ses.writepayload, 0);
534
0
  packet_type = buf_getbyte(ses.writepayload);
535
0
  buf_setpos(ses.writepayload, 0);
536
537
0
  TRACE2(("encrypt_packet type is %d", packet_type))
538
  
539
0
  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
0
    enqueue_reply_packet();
544
0
    return;
545
0
  }
546
    
547
0
  blocksize = ses.keys->trans.algo_crypt->blocksize;
548
0
  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
0
  encrypt_buf_size = (ses.writepayload->len+4+1) 
554
0
    + MAX(MIN_PACKET_LEN, blocksize) + 3
555
  /* add space for the MAC at the end */
556
0
        + 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
0
        + 1;
564
565
0
  writebuf = buf_new(encrypt_buf_size);
566
0
  buf_setlen(writebuf, PACKET_PAYLOAD_OFF);
567
0
  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
0
  {
576
0
    memcpy(buf_getwriteptr(writebuf, ses.writepayload->len),
577
0
        buf_getptr(ses.writepayload, ses.writepayload->len),
578
0
        ses.writepayload->len);
579
0
    buf_incrwritepos(writebuf, ses.writepayload->len);
580
0
  }
581
582
  /* finished with payload */
583
0
  buf_setpos(ses.writepayload, 0);
584
0
  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
0
  len = writebuf->len;
590
0
#if DROPBEAR_AEAD_MODE
591
0
  if (ses.keys->trans.crypt_mode->aead_crypt) {
592
0
    len -= 4;
593
0
  }
594
0
#endif
595
0
  padlen = blocksize - len % blocksize;
596
0
  if (padlen < 4) {
597
0
    padlen += blocksize;
598
0
  }
599
  /* check for min packet length */
600
0
  if (writebuf->len + padlen < MIN_PACKET_LEN) {
601
0
    padlen += blocksize;
602
0
  }
603
604
0
  buf_setpos(writebuf, 0);
605
  /* packet length excluding the packetlength uint32 */
606
0
  buf_putint(writebuf, writebuf->len + padlen - 4);
607
608
  /* padding len */
609
0
  buf_putbyte(writebuf, padlen);
610
  /* actual padding */
611
0
  buf_setpos(writebuf, writebuf->len);
612
0
  buf_incrlen(writebuf, padlen);
613
0
  genrandom(buf_getptr(writebuf, padlen), padlen);
614
615
0
#if DROPBEAR_AEAD_MODE
616
0
  if (ses.keys->trans.crypt_mode->aead_crypt) {
617
    /* do the actual encryption, in-place */
618
0
    buf_setpos(writebuf, 0);
619
    /* encrypt it in-place*/
620
0
    len = writebuf->len;
621
0
    buf_incrlen(writebuf, mac_size);
622
0
    if (ses.keys->trans.crypt_mode->aead_crypt(ses.transseq,
623
0
          buf_getptr(writebuf, len),
624
0
          buf_getwriteptr(writebuf, len + mac_size),
625
0
          len, mac_size,
626
0
          &ses.keys->trans.cipher_state, LTC_ENCRYPT) != CRYPT_OK) {
627
0
      dropbear_exit("Error encrypting");
628
0
    }
629
0
    buf_incrpos(writebuf, len + mac_size);
630
0
  } else
631
0
#endif
632
0
  {
633
0
    make_mac(ses.transseq, &ses.keys->trans, writebuf, writebuf->len, mac_bytes);
634
635
    /* do the actual encryption, in-place */
636
0
    buf_setpos(writebuf, 0);
637
    /* encrypt it in-place*/
638
0
    len = writebuf->len;
639
0
    if (ses.keys->trans.crypt_mode->encrypt(
640
0
          buf_getptr(writebuf, len),
641
0
          buf_getwriteptr(writebuf, len),
642
0
          len,
643
0
          &ses.keys->trans.cipher_state) != CRYPT_OK) {
644
0
      dropbear_exit("Error encrypting");
645
0
    }
646
0
    buf_incrpos(writebuf, len);
647
648
    /* stick the MAC on it */
649
0
    buf_putbytes(writebuf, mac_bytes, mac_size);
650
0
  }
651
652
  /* Update counts */
653
0
  ses.kexstate.datatrans += writebuf->len;
654
655
0
  writebuf_enqueue(writebuf);
656
657
  /* Update counts */
658
0
  ses.transseq++;
659
660
0
  now = monotonic_now();
661
0
  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
0
  if (packet_type != SSH_MSG_REQUEST_FAILURE
666
0
    && packet_type != SSH_MSG_UNIMPLEMENTED
667
0
    && packet_type != SSH_MSG_IGNORE) {
668
0
    ses.last_packet_time_idle = now;
669
670
0
  }
671
672
0
  TRACE2(("leave encrypt_packet()"))
673
0
}
674
675
0
void writebuf_enqueue(buffer * writebuf) {
676
  /* enqueue the packet for sending. It will get freed after transmission. */
677
0
  buf_setpos(writebuf, 0);
678
0
  enqueue(&ses.writequeue, (void*)writebuf);
679
0
  ses.writequeue_len += writebuf->len;
680
0
}
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
0
    unsigned char *output_mac) {
688
0
  unsigned char seqbuf[4];
689
0
  unsigned long bufsize;
690
0
  hmac_state hmac;
691
692
0
  if (key_state->algo_mac->hashsize > 0) {
693
    /* calculate the mac */
694
0
    if (hmac_init(&hmac, 
695
0
          key_state->hash_index,
696
0
          key_state->mackey,
697
0
          key_state->algo_mac->keysize) != CRYPT_OK) {
698
0
      dropbear_exit("HMAC error");
699
0
    }
700
  
701
    /* sequence number */
702
0
    STORE32H(seqno, seqbuf);
703
0
    if (hmac_process(&hmac, seqbuf, 4) != CRYPT_OK) {
704
0
      dropbear_exit("HMAC error");
705
0
    }
706
  
707
    /* the actual contents */
708
0
    buf_setpos(clear_buf, 0);
709
0
    if (hmac_process(&hmac, 
710
0
          buf_getptr(clear_buf, clear_len),
711
0
          clear_len) != CRYPT_OK) {
712
0
      dropbear_exit("HMAC error");
713
0
    }
714
  
715
0
    bufsize = MAX_MAC_LEN;
716
0
    if (hmac_done(&hmac, output_mac, &bufsize) != CRYPT_OK) {
717
0
      dropbear_exit("HMAC error");
718
0
    }
719
0
  }
720
0
  TRACE2(("leave writemac"))
721
0
}
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