Home | History | Annotate | Download | only in dropbear
      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 "random.h"
     34 #include "service.h"
     35 #include "auth.h"
     36 #include "channel.h"
     37 
     38 static void read_packet_init();
     39 static void writemac(buffer * outputbuffer, buffer * clearwritebuf);
     40 static int checkmac(buffer* hashbuf, buffer* readbuf);
     41 
     42 #define ZLIB_COMPRESS_INCR 20 /* this is 12 bytes + 0.1% of 8000 bytes */
     43 #define ZLIB_DECOMPRESS_INCR 100
     44 #ifndef DISABLE_ZLIB
     45 static buffer* buf_decompress(buffer* buf, unsigned int len);
     46 static void buf_compress(buffer * dest, buffer * src, unsigned int len);
     47 #endif
     48 
     49 /* non-blocking function writing out a current encrypted packet */
     50 void write_packet() {
     51 
     52 	int len, written;
     53 	buffer * writebuf = NULL;
     54 
     55 	TRACE(("enter write_packet"))
     56 	dropbear_assert(!isempty(&ses.writequeue));
     57 
     58 	/* Get the next buffer in the queue of encrypted packets to write*/
     59 	writebuf = (buffer*)examine(&ses.writequeue);
     60 
     61 	len = writebuf->len - writebuf->pos;
     62 	dropbear_assert(len > 0);
     63 	/* Try to write as much as possible */
     64 	written = write(ses.sock, buf_getptr(writebuf, len), len);
     65 
     66 	if (written < 0) {
     67 		if (errno == EINTR) {
     68 			TRACE(("leave writepacket: EINTR"))
     69 			return;
     70 		} else {
     71 			dropbear_exit("error writing");
     72 		}
     73 	}
     74 
     75 	if (written == 0) {
     76 		ses.remoteclosed();
     77 	}
     78 
     79 	if (written == len) {
     80 		/* We've finished with the packet, free it */
     81 		dequeue(&ses.writequeue);
     82 		buf_free(writebuf);
     83 		writebuf = NULL;
     84 	} else {
     85 		/* More packet left to write, leave it in the queue for later */
     86 		buf_incrpos(writebuf, written);
     87 	}
     88 
     89 	TRACE(("leave write_packet"))
     90 }
     91 
     92 /* Non-blocking function reading available portion of a packet into the
     93  * ses's buffer, decrypting the length if encrypted, decrypting the
     94  * full portion if possible */
     95 void read_packet() {
     96 
     97 	int len;
     98 	unsigned int maxlen;
     99 	unsigned char blocksize;
    100 
    101 	TRACE(("enter read_packet"))
    102 	blocksize = ses.keys->recv_algo_crypt->blocksize;
    103 
    104 	if (ses.readbuf == NULL || ses.readbuf->len < blocksize) {
    105 		/* In the first blocksize of a packet */
    106 
    107 		/* Read the first blocksize of the packet, so we can decrypt it and
    108 		 * find the length of the whole packet */
    109 		read_packet_init();
    110 
    111 		/* If we don't have the length of decryptreadbuf, we didn't read
    112 		 * a whole blocksize and should exit */
    113 		if (ses.decryptreadbuf->len == 0) {
    114 			TRACE(("leave read_packet: packetinit done"))
    115 			return;
    116 		}
    117 	}
    118 
    119 	/* Attempt to read the remainder of the packet, note that there
    120 	 * mightn't be any available (EAGAIN) */
    121 	dropbear_assert(ses.readbuf != NULL);
    122 	maxlen = ses.readbuf->len - ses.readbuf->pos;
    123 	len = read(ses.sock, buf_getptr(ses.readbuf, maxlen), maxlen);
    124 
    125 	if (len == 0) {
    126 		ses.remoteclosed();
    127 	}
    128 
    129 	if (len < 0) {
    130 		if (errno == EINTR || errno == EAGAIN) {
    131 			TRACE(("leave read_packet: EINTR or EAGAIN"))
    132 			return;
    133 		} else {
    134 			dropbear_exit("error reading: %s", strerror(errno));
    135 		}
    136 	}
    137 
    138 	buf_incrpos(ses.readbuf, len);
    139 
    140 	if ((unsigned int)len == maxlen) {
    141 		/* The whole packet has been read */
    142 		decrypt_packet();
    143 		/* The main select() loop process_packet() to
    144 		 * handle the packet contents... */
    145 	}
    146 	TRACE(("leave read_packet"))
    147 }
    148 
    149 /* Function used to read the initial portion of a packet, and determine the
    150  * length. Only called during the first BLOCKSIZE of a packet. */
    151 static void read_packet_init() {
    152 
    153 	unsigned int maxlen;
    154 	int len;
    155 	unsigned char blocksize;
    156 	unsigned char macsize;
    157 
    158 
    159 	blocksize = ses.keys->recv_algo_crypt->blocksize;
    160 	macsize = ses.keys->recv_algo_mac->hashsize;
    161 
    162 	if (ses.readbuf == NULL) {
    163 		/* start of a new packet */
    164 		ses.readbuf = buf_new(INIT_READBUF);
    165 		dropbear_assert(ses.decryptreadbuf == NULL);
    166 		ses.decryptreadbuf = buf_new(blocksize);
    167 	}
    168 
    169 	maxlen = blocksize - ses.readbuf->pos;
    170 
    171 	/* read the rest of the packet if possible */
    172 	len = read(ses.sock, buf_getwriteptr(ses.readbuf, maxlen),
    173 			maxlen);
    174 	if (len == 0) {
    175 		ses.remoteclosed();
    176 	}
    177 	if (len < 0) {
    178 		if (errno == EINTR) {
    179 			TRACE(("leave read_packet_init: EINTR"))
    180 			return;
    181 		}
    182 		dropbear_exit("error reading: %s", strerror(errno));
    183 	}
    184 
    185 	buf_incrwritepos(ses.readbuf, len);
    186 
    187 	if ((unsigned int)len != maxlen) {
    188 		/* don't have enough bytes to determine length, get next time */
    189 		return;
    190 	}
    191 
    192 	/* now we have the first block, need to get packet length, so we decrypt
    193 	 * the first block (only need first 4 bytes) */
    194 	buf_setpos(ses.readbuf, 0);
    195 	if (ses.keys->recv_algo_crypt->cipherdesc == NULL) {
    196 		/* copy it */
    197 		memcpy(buf_getwriteptr(ses.decryptreadbuf, blocksize),
    198 				buf_getptr(ses.readbuf, blocksize),
    199 				blocksize);
    200 	} else {
    201 		/* decrypt it */
    202 		if (cbc_decrypt(buf_getptr(ses.readbuf, blocksize),
    203 					buf_getwriteptr(ses.decryptreadbuf,blocksize),
    204 					blocksize,
    205 					&ses.keys->recv_symmetric_struct) != CRYPT_OK) {
    206 			dropbear_exit("error decrypting");
    207 		}
    208 	}
    209 	buf_setlen(ses.decryptreadbuf, blocksize);
    210 	len = buf_getint(ses.decryptreadbuf) + 4 + macsize;
    211 
    212 	buf_setpos(ses.readbuf, blocksize);
    213 
    214 	/* check packet length */
    215 	if ((len > MAX_PACKET_LEN) ||
    216 		(len < MIN_PACKET_LEN + macsize) ||
    217 		((len - macsize) % blocksize != 0)) {
    218 		dropbear_exit("bad packet size %d", len);
    219 	}
    220 
    221 	buf_resize(ses.readbuf, len);
    222 	buf_setlen(ses.readbuf, len);
    223 
    224 }
    225 
    226 /* handle the received packet */
    227 void decrypt_packet() {
    228 
    229 	unsigned char blocksize;
    230 	unsigned char macsize;
    231 	unsigned int padlen;
    232 	unsigned int len;
    233 
    234 	TRACE(("enter decrypt_packet"))
    235 	blocksize = ses.keys->recv_algo_crypt->blocksize;
    236 	macsize = ses.keys->recv_algo_mac->hashsize;
    237 
    238 	ses.kexstate.datarecv += ses.readbuf->len;
    239 
    240 	/* we've already decrypted the first blocksize in read_packet_init */
    241 	buf_setpos(ses.readbuf, blocksize);
    242 
    243 	buf_resize(ses.decryptreadbuf, ses.readbuf->len - macsize);
    244 	buf_setlen(ses.decryptreadbuf, ses.decryptreadbuf->size);
    245 	buf_setpos(ses.decryptreadbuf, blocksize);
    246 
    247 	/* decrypt if encryption is set, memcpy otherwise */
    248 	if (ses.keys->recv_algo_crypt->cipherdesc == NULL) {
    249 		/* copy it */
    250 		len = ses.readbuf->len - macsize - blocksize;
    251 		memcpy(buf_getwriteptr(ses.decryptreadbuf, len),
    252 				buf_getptr(ses.readbuf, len), len);
    253 	} else {
    254 		/* decrypt */
    255 		while (ses.readbuf->pos < ses.readbuf->len - macsize) {
    256 			if (cbc_decrypt(buf_getptr(ses.readbuf, blocksize),
    257 						buf_getwriteptr(ses.decryptreadbuf, blocksize),
    258 						blocksize,
    259 						&ses.keys->recv_symmetric_struct) != CRYPT_OK) {
    260 				dropbear_exit("error decrypting");
    261 			}
    262 			buf_incrpos(ses.readbuf, blocksize);
    263 			buf_incrwritepos(ses.decryptreadbuf, blocksize);
    264 		}
    265 	}
    266 
    267 	/* check the hmac */
    268 	buf_setpos(ses.readbuf, ses.readbuf->len - macsize);
    269 	if (checkmac(ses.readbuf, ses.decryptreadbuf) != DROPBEAR_SUCCESS) {
    270 		dropbear_exit("Integrity error");
    271 	}
    272 
    273 	/* readbuf no longer required */
    274 	buf_free(ses.readbuf);
    275 	ses.readbuf = NULL;
    276 
    277 	/* get padding length */
    278 	buf_setpos(ses.decryptreadbuf, PACKET_PADDING_OFF);
    279 	padlen = buf_getbyte(ses.decryptreadbuf);
    280 
    281 	/* payload length */
    282 	/* - 4 - 1 is for LEN and PADLEN values */
    283 	len = ses.decryptreadbuf->len - padlen - 4 - 1;
    284 	if ((len > MAX_PAYLOAD_LEN) || (len < 1)) {
    285 		dropbear_exit("bad packet size");
    286 	}
    287 
    288 	buf_setpos(ses.decryptreadbuf, PACKET_PAYLOAD_OFF);
    289 
    290 #ifndef DISABLE_ZLIB
    291 	if (ses.keys->recv_algo_comp == DROPBEAR_COMP_ZLIB) {
    292 		/* decompress */
    293 		ses.payload = buf_decompress(ses.decryptreadbuf, len);
    294 
    295 	} else
    296 #endif
    297 	{
    298 		/* copy payload */
    299 		ses.payload = buf_new(len);
    300 		memcpy(ses.payload->data, buf_getptr(ses.decryptreadbuf, len), len);
    301 		buf_incrlen(ses.payload, len);
    302 	}
    303 
    304 	buf_free(ses.decryptreadbuf);
    305 	ses.decryptreadbuf = NULL;
    306 	buf_setpos(ses.payload, 0);
    307 
    308 	ses.recvseq++;
    309 
    310 	TRACE(("leave decrypt_packet"))
    311 }
    312 
    313 /* Checks the mac in hashbuf, for the data in readbuf.
    314  * Returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE */
    315 static int checkmac(buffer* macbuf, buffer* sourcebuf) {
    316 
    317 	unsigned int macsize;
    318 	hmac_state hmac;
    319 	unsigned char tempbuf[MAX_MAC_LEN];
    320 	unsigned long bufsize;
    321 	unsigned int len;
    322 
    323 	macsize = ses.keys->recv_algo_mac->hashsize;
    324 	if (macsize == 0) {
    325 		return DROPBEAR_SUCCESS;
    326 	}
    327 
    328 	/* calculate the mac */
    329 	if (hmac_init(&hmac,
    330 				find_hash(ses.keys->recv_algo_mac->hashdesc->name),
    331 				ses.keys->recvmackey,
    332 				ses.keys->recv_algo_mac->keysize)
    333 				!= CRYPT_OK) {
    334 		dropbear_exit("HMAC error");
    335 	}
    336 
    337 	/* sequence number */
    338 	STORE32H(ses.recvseq, tempbuf);
    339 	if (hmac_process(&hmac, tempbuf, 4) != CRYPT_OK) {
    340 		dropbear_exit("HMAC error");
    341 	}
    342 
    343 	buf_setpos(sourcebuf, 0);
    344 	len = sourcebuf->len;
    345 	if (hmac_process(&hmac, buf_getptr(sourcebuf, len), len) != CRYPT_OK) {
    346 		dropbear_exit("HMAC error");
    347 	}
    348 
    349 	bufsize = sizeof(tempbuf);
    350 	if (hmac_done(&hmac, tempbuf, &bufsize) != CRYPT_OK) {
    351 		dropbear_exit("HMAC error");
    352 	}
    353 
    354 	/* compare the hash */
    355 	if (memcmp(tempbuf, buf_getptr(macbuf, macsize), macsize) != 0) {
    356 		return DROPBEAR_FAILURE;
    357 	} else {
    358 		return DROPBEAR_SUCCESS;
    359 	}
    360 }
    361 
    362 #ifndef DISABLE_ZLIB
    363 /* returns a pointer to a newly created buffer */
    364 static buffer* buf_decompress(buffer* buf, unsigned int len) {
    365 
    366 	int result;
    367 	buffer * ret;
    368 	z_streamp zstream;
    369 
    370 	zstream = ses.keys->recv_zstream;
    371 	ret = buf_new(len);
    372 
    373 	zstream->avail_in = len;
    374 	zstream->next_in = buf_getptr(buf, len);
    375 
    376 	/* decompress the payload, incrementally resizing the output buffer */
    377 	while (1) {
    378 
    379 		zstream->avail_out = ret->size - ret->pos;
    380 		zstream->next_out = buf_getwriteptr(ret, zstream->avail_out);
    381 
    382 		result = inflate(zstream, Z_SYNC_FLUSH);
    383 
    384 		buf_setlen(ret, ret->size - zstream->avail_out);
    385 		buf_setpos(ret, ret->len);
    386 
    387 		if (result != Z_BUF_ERROR && result != Z_OK) {
    388 			dropbear_exit("zlib error");
    389 		}
    390 
    391 		if (zstream->avail_in == 0 &&
    392 		   		(zstream->avail_out != 0 || result == Z_BUF_ERROR)) {
    393 			/* we can only exit if avail_out hasn't all been used,
    394 			 * and there's no remaining input */
    395 			return ret;
    396 		}
    397 
    398 		if (zstream->avail_out == 0) {
    399 			buf_resize(ret, ret->size + ZLIB_DECOMPRESS_INCR);
    400 		}
    401 	}
    402 }
    403 #endif
    404 
    405 
    406 
    407 
    408 /* encrypt the writepayload, putting into writebuf, ready for write_packet()
    409  * to put on the wire */
    410 void encrypt_packet() {
    411 
    412 	unsigned char padlen;
    413 	unsigned char blocksize, macsize;
    414 	buffer * writebuf; /* the packet which will go on the wire */
    415 	buffer * clearwritebuf; /* unencrypted, possibly compressed */
    416 
    417 	TRACE(("enter encrypt_packet()"))
    418 	TRACE(("encrypt_packet type is %d", ses.writepayload->data[0]))
    419 	blocksize = ses.keys->trans_algo_crypt->blocksize;
    420 	macsize = ses.keys->trans_algo_mac->hashsize;
    421 
    422 	/* Encrypted packet len is payload+5, then worst case is if we are 3 away
    423 	 * from a blocksize multiple. In which case we need to pad to the
    424 	 * multiple, then add another blocksize (or MIN_PACKET_LEN) */
    425 	clearwritebuf = buf_new((ses.writepayload->len+4+1) + MIN_PACKET_LEN + 3
    426 #ifndef DISABLE_ZLIB
    427 			+ ZLIB_COMPRESS_INCR /* bit of a kludge, but we can't know len*/
    428 #endif
    429 			);
    430 	buf_setlen(clearwritebuf, PACKET_PAYLOAD_OFF);
    431 	buf_setpos(clearwritebuf, PACKET_PAYLOAD_OFF);
    432 
    433 	buf_setpos(ses.writepayload, 0);
    434 
    435 #ifndef DISABLE_ZLIB
    436 	/* compression */
    437 	if (ses.keys->trans_algo_comp == DROPBEAR_COMP_ZLIB) {
    438 		buf_compress(clearwritebuf, ses.writepayload, ses.writepayload->len);
    439 	} else
    440 #endif
    441 	{
    442 		memcpy(buf_getwriteptr(clearwritebuf, ses.writepayload->len),
    443 				buf_getptr(ses.writepayload, ses.writepayload->len),
    444 				ses.writepayload->len);
    445 		buf_incrwritepos(clearwritebuf, ses.writepayload->len);
    446 	}
    447 
    448 	/* finished with payload */
    449 	buf_setpos(ses.writepayload, 0);
    450 	buf_setlen(ses.writepayload, 0);
    451 
    452 	/* length of padding - packet length must be a multiple of blocksize,
    453 	 * with a minimum of 4 bytes of padding */
    454 	padlen = blocksize - (clearwritebuf->len) % blocksize;
    455 	if (padlen < 4) {
    456 		padlen += blocksize;
    457 	}
    458 	/* check for min packet length */
    459 	if (clearwritebuf->len + padlen < MIN_PACKET_LEN) {
    460 		padlen += blocksize;
    461 	}
    462 
    463 	buf_setpos(clearwritebuf, 0);
    464 	/* packet length excluding the packetlength uint32 */
    465 	buf_putint(clearwritebuf, clearwritebuf->len + padlen - 4);
    466 
    467 	/* padding len */
    468 	buf_putbyte(clearwritebuf, padlen);
    469 	/* actual padding */
    470 	buf_setpos(clearwritebuf, clearwritebuf->len);
    471 	buf_incrlen(clearwritebuf, padlen);
    472 	genrandom(buf_getptr(clearwritebuf, padlen), padlen);
    473 
    474 	/* do the actual encryption */
    475 	buf_setpos(clearwritebuf, 0);
    476 	/* create a new writebuffer, this is freed when it has been put on the
    477 	 * wire by writepacket() */
    478 	writebuf = buf_new(clearwritebuf->len + macsize);
    479 
    480 	if (ses.keys->trans_algo_crypt->cipherdesc == NULL) {
    481 		/* copy it */
    482 		memcpy(buf_getwriteptr(writebuf, clearwritebuf->len),
    483 				buf_getptr(clearwritebuf, clearwritebuf->len),
    484 				clearwritebuf->len);
    485 		buf_incrwritepos(writebuf, clearwritebuf->len);
    486 	} else {
    487 		/* encrypt it */
    488 		while (clearwritebuf->pos < clearwritebuf->len) {
    489 			if (cbc_encrypt(buf_getptr(clearwritebuf, blocksize),
    490 						buf_getwriteptr(writebuf, blocksize),
    491 						blocksize,
    492 						&ses.keys->trans_symmetric_struct) != CRYPT_OK) {
    493 				dropbear_exit("error encrypting");
    494 			}
    495 			buf_incrpos(clearwritebuf, blocksize);
    496 			buf_incrwritepos(writebuf, blocksize);
    497 		}
    498 	}
    499 
    500 	/* now add a hmac and we're done */
    501 	writemac(writebuf, clearwritebuf);
    502 
    503 	/* clearwritebuf is finished with */
    504 	buf_free(clearwritebuf);
    505 	clearwritebuf = NULL;
    506 
    507 	/* enqueue the packet for sending */
    508 	buf_setpos(writebuf, 0);
    509 	enqueue(&ses.writequeue, (void*)writebuf);
    510 
    511 	/* Update counts */
    512 	ses.kexstate.datatrans += writebuf->len;
    513 	ses.transseq++;
    514 
    515 	TRACE(("leave encrypt_packet()"))
    516 }
    517 
    518 
    519 /* Create the packet mac, and append H(seqno|clearbuf) to the output */
    520 static void writemac(buffer * outputbuffer, buffer * clearwritebuf) {
    521 
    522 	unsigned int macsize;
    523 	unsigned char seqbuf[4];
    524 	unsigned char tempbuf[MAX_MAC_LEN];
    525 	unsigned long bufsize;
    526 	hmac_state hmac;
    527 
    528 	TRACE(("enter writemac"))
    529 
    530 	macsize = ses.keys->trans_algo_mac->hashsize;
    531 	if (macsize > 0) {
    532 		/* calculate the mac */
    533 		if (hmac_init(&hmac,
    534 					find_hash(ses.keys->trans_algo_mac->hashdesc->name),
    535 					ses.keys->transmackey,
    536 					ses.keys->trans_algo_mac->keysize) != CRYPT_OK) {
    537 			dropbear_exit("HMAC error");
    538 		}
    539 
    540 		/* sequence number */
    541 		STORE32H(ses.transseq, seqbuf);
    542 		if (hmac_process(&hmac, seqbuf, 4) != CRYPT_OK) {
    543 			dropbear_exit("HMAC error");
    544 		}
    545 
    546 		/* the actual contents */
    547 		buf_setpos(clearwritebuf, 0);
    548 		if (hmac_process(&hmac,
    549 					buf_getptr(clearwritebuf,
    550 						clearwritebuf->len),
    551 					clearwritebuf->len) != CRYPT_OK) {
    552 			dropbear_exit("HMAC error");
    553 		}
    554 
    555 		bufsize = sizeof(tempbuf);
    556 		if (hmac_done(&hmac, tempbuf, &bufsize)
    557 				!= CRYPT_OK) {
    558 			dropbear_exit("HMAC error");
    559 		}
    560 		buf_putbytes(outputbuffer, tempbuf, macsize);
    561 	}
    562 	TRACE(("leave writemac"))
    563 }
    564 
    565 #ifndef DISABLE_ZLIB
    566 /* compresses len bytes from src, outputting to dest (starting from the
    567  * respective current positions. */
    568 static void buf_compress(buffer * dest, buffer * src, unsigned int len) {
    569 
    570 	unsigned int endpos = src->pos + len;
    571 	int result;
    572 
    573 	TRACE(("enter buf_compress"))
    574 
    575 	while (1) {
    576 
    577 		ses.keys->trans_zstream->avail_in = endpos - src->pos;
    578 		ses.keys->trans_zstream->next_in =
    579 			buf_getptr(src, ses.keys->trans_zstream->avail_in);
    580 
    581 		ses.keys->trans_zstream->avail_out = dest->size - dest->pos;
    582 		ses.keys->trans_zstream->next_out =
    583 			buf_getwriteptr(dest, ses.keys->trans_zstream->avail_out);
    584 
    585 		result = deflate(ses.keys->trans_zstream, Z_SYNC_FLUSH);
    586 
    587 		buf_setpos(src, endpos - ses.keys->trans_zstream->avail_in);
    588 		buf_setlen(dest, dest->size - ses.keys->trans_zstream->avail_out);
    589 		buf_setpos(dest, dest->len);
    590 
    591 		if (result != Z_OK) {
    592 			dropbear_exit("zlib error");
    593 		}
    594 
    595 		if (ses.keys->trans_zstream->avail_in == 0) {
    596 			break;
    597 		}
    598 
    599 		dropbear_assert(ses.keys->trans_zstream->avail_out == 0);
    600 
    601 		/* the buffer has been filled, we must extend. This only happens in
    602 		 * unusual circumstances where the data grows in size after deflate(),
    603 		 * but it is possible */
    604 		buf_resize(dest, dest->size + ZLIB_COMPRESS_INCR);
    605 
    606 	}
    607 	TRACE(("leave buf_compress"))
    608 }
    609 #endif
    610