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 #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 */
write_packet()58 void write_packet() {
59 
60 	ssize_t written;
61 #if defined(HAVE_WRITEV) && (defined(IOV_MAX) || defined(UIO_MAXIOV))
62 	/* 50 is somewhat arbitrary */
63 	unsigned int iov_count = 50;
64 	struct iovec iov[50];
65 #else
66 	int len;
67 	buffer* writebuf;
68 #endif
69 
70 	TRACE2(("enter write_packet"))
71 	dropbear_assert(!isempty(&ses.writequeue));
72 
73 #if defined(HAVE_WRITEV) && (defined(IOV_MAX) || defined(UIO_MAXIOV))
74 
75 	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 #if DROPBEAR_FUZZ
80 	if (fuzz.fuzzing) {
81 		/* pretend to write one packet at a time */
82 		/* TODO(fuzz): randomise amount written based on the fuzz input */
83 		written = iov[0].iov_len;
84 	}
85 	else
86 #endif
87 	{
88 	written = writev(ses.sock_out, iov, iov_count);
89 	if (written < 0) {
90 		if (errno == EINTR || errno == EAGAIN) {
91 			TRACE2(("leave write_packet: EINTR"))
92 			return;
93 		} else {
94 			dropbear_exit("Error writing: %s", strerror(errno));
95 		}
96 	}
97 	}
98 
99 	packet_queue_consume(&ses.writequeue, written);
100 	ses.writequeue_len -= written;
101 
102 	if (written == 0) {
103 		ses.remoteclosed();
104 	}
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 	TRACE2(("leave write_packet"))
145 }
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 */
read_packet()150 void read_packet() {
151 
152 	int len;
153 	unsigned int maxlen;
154 	unsigned char blocksize;
155 
156 	TRACE2(("enter read_packet"))
157 	blocksize = ses.keys->recv.algo_crypt->blocksize;
158 
159 	if (ses.readbuf == NULL || ses.readbuf->len < blocksize) {
160 		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 		ret = read_packet_init();
166 
167 		if (ret == DROPBEAR_FAILURE) {
168 			/* didn't read enough to determine the length */
169 			TRACE2(("leave read_packet: packetinit done"))
170 			return;
171 		}
172 	}
173 
174 	/* Attempt to read the remainder of the packet, note that there
175 	 * mightn't be any available (EAGAIN) */
176 	maxlen = ses.readbuf->len - ses.readbuf->pos;
177 	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 		len = 0;
182 	} else {
183 		len = read(ses.sock_in, buf_getptr(ses.readbuf, maxlen), maxlen);
184 
185 		if (len == 0) {
186 			ses.remoteclosed();
187 		}
188 
189 		if (len < 0) {
190 			if (errno == EINTR || errno == EAGAIN) {
191 				TRACE2(("leave read_packet: EINTR or EAGAIN"))
192 				return;
193 			} else {
194 				dropbear_exit("Error reading: %s", strerror(errno));
195 			}
196 		}
197 
198 		buf_incrpos(ses.readbuf, len);
199 	}
200 
201 	if ((unsigned int)len == maxlen) {
202 		/* The whole packet has been read */
203 		decrypt_packet();
204 		/* The main select() loop process_packet() to
205 		 * handle the packet contents... */
206 	}
207 	TRACE2(("leave read_packet"))
208 }
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 */
read_packet_init()214 static int read_packet_init() {
215 
216 	unsigned int maxlen;
217 	int slen;
218 	unsigned int len, plen;
219 	unsigned int blocksize;
220 	unsigned int macsize;
221 
222 
223 	blocksize = ses.keys->recv.algo_crypt->blocksize;
224 	macsize = ses.keys->recv.algo_mac->hashsize;
225 
226 	if (ses.readbuf == NULL) {
227 		/* start of a new packet */
228 		ses.readbuf = buf_new(INIT_READBUF);
229 	}
230 
231 	maxlen = blocksize - ses.readbuf->pos;
232 
233 	/* read the rest of the packet if possible */
234 	slen = read(ses.sock_in, buf_getwriteptr(ses.readbuf, maxlen),
235 			maxlen);
236 	if (slen == 0) {
237 		ses.remoteclosed();
238 	}
239 	if (slen < 0) {
240 		if (errno == EINTR || errno == EAGAIN) {
241 			TRACE2(("leave read_packet_init: EINTR"))
242 			return DROPBEAR_FAILURE;
243 		}
244 		dropbear_exit("Error reading: %s", strerror(errno));
245 	}
246 
247 	buf_incrwritepos(ses.readbuf, slen);
248 
249 	if ((unsigned int)slen != maxlen) {
250 		/* don't have enough bytes to determine length, get next time */
251 		return DROPBEAR_FAILURE;
252 	}
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 	buf_setpos(ses.readbuf, 0);
257 #if DROPBEAR_AEAD_MODE
258 	if (ses.keys->recv.crypt_mode->aead_crypt) {
259 		if (ses.keys->recv.crypt_mode->aead_getlength(ses.recvseq,
260 					buf_getptr(ses.readbuf, blocksize), &plen,
261 					blocksize,
262 					&ses.keys->recv.cipher_state) != CRYPT_OK) {
263 			dropbear_exit("Error decrypting");
264 		}
265 		len = plen + 4 + macsize;
266 	} else
267 #endif
268 	{
269 		if (ses.keys->recv.crypt_mode->decrypt(buf_getptr(ses.readbuf, blocksize),
270 					buf_getwriteptr(ses.readbuf, blocksize),
271 					blocksize,
272 					&ses.keys->recv.cipher_state) != CRYPT_OK) {
273 			dropbear_exit("Error decrypting");
274 		}
275 		plen = buf_getint(ses.readbuf) + 4;
276 		len = plen + macsize;
277 	}
278 
279 	TRACE2(("packet size is %u, block %u mac %u", len, blocksize, macsize))
280 
281 
282 	/* check packet length */
283 	if ((len > RECV_MAX_PACKET_LEN) ||
284 		(plen < blocksize) ||
285 		(plen % blocksize != 0)) {
286 		dropbear_exit("Integrity error (bad packet size %u)", len);
287 	}
288 
289 	if (len > ses.readbuf->size) {
290 		ses.readbuf = buf_resize(ses.readbuf, len);
291 	}
292 	buf_setlen(ses.readbuf, len);
293 	buf_setpos(ses.readbuf, blocksize);
294 	return DROPBEAR_SUCCESS;
295 }
296 
297 /* handle the received packet */
decrypt_packet()298 void decrypt_packet() {
299 
300 	unsigned char blocksize;
301 	unsigned char macsize;
302 	unsigned int padlen;
303 	unsigned int len;
304 
305 	TRACE2(("enter decrypt_packet"))
306 	blocksize = ses.keys->recv.algo_crypt->blocksize;
307 	macsize = ses.keys->recv.algo_mac->hashsize;
308 
309 	ses.kexstate.datarecv += ses.readbuf->len;
310 
311 #if DROPBEAR_AEAD_MODE
312 	if (ses.keys->recv.crypt_mode->aead_crypt) {
313 		/* first blocksize is not decrypted yet */
314 		buf_setpos(ses.readbuf, 0);
315 
316 		/* decrypt it in-place */
317 		len = ses.readbuf->len - macsize - ses.readbuf->pos;
318 		if (ses.keys->recv.crypt_mode->aead_crypt(ses.recvseq,
319 					buf_getptr(ses.readbuf, len + macsize),
320 					buf_getwriteptr(ses.readbuf, len),
321 					len, macsize,
322 					&ses.keys->recv.cipher_state, LTC_DECRYPT) != CRYPT_OK) {
323 			dropbear_exit("Error decrypting");
324 		}
325 		buf_incrpos(ses.readbuf, len);
326 	} else
327 #endif
328 	{
329 		/* we've already decrypted the first blocksize in read_packet_init */
330 		buf_setpos(ses.readbuf, blocksize);
331 
332 		/* decrypt it in-place */
333 		len = ses.readbuf->len - macsize - ses.readbuf->pos;
334 		if (ses.keys->recv.crypt_mode->decrypt(
335 					buf_getptr(ses.readbuf, len),
336 					buf_getwriteptr(ses.readbuf, len),
337 					len,
338 					&ses.keys->recv.cipher_state) != CRYPT_OK) {
339 			dropbear_exit("Error decrypting");
340 		}
341 		buf_incrpos(ses.readbuf, len);
342 
343 		/* check the hmac */
344 		if (checkmac() != DROPBEAR_SUCCESS) {
345 			dropbear_exit("Integrity error");
346 		}
347 
348 	}
349 
350 #if DROPBEAR_FUZZ
351 	fuzz_dump(ses.readbuf->data, ses.readbuf->len);
352 #endif
353 
354 	/* get padding length */
355 	buf_setpos(ses.readbuf, PACKET_PADDING_OFF);
356 	padlen = buf_getbyte(ses.readbuf);
357 
358 	/* payload length */
359 	/* - 4 - 1 is for LEN and PADLEN values */
360 	len = ses.readbuf->len - padlen - 4 - 1 - macsize;
361 	if ((len > RECV_MAX_PAYLOAD_LEN+ZLIB_COMPRESS_EXPANSION) || (len < 1)) {
362 		dropbear_exit("Bad packet size %u", len);
363 	}
364 
365 	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 	{
377 		ses.payload = ses.readbuf;
378 		ses.payload_beginning = ses.payload->pos;
379 		buf_setlen(ses.payload, ses.payload->pos + len);
380 	}
381 	ses.readbuf = NULL;
382 
383 	ses.recvseq++;
384 
385 	TRACE2(("leave decrypt_packet"))
386 }
387 
388 /* Checks the mac at the end of a decrypted readbuf.
389  * Returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE */
checkmac()390 static int checkmac() {
391 
392 	unsigned char mac_bytes[MAX_MAC_LEN];
393 	unsigned int mac_size, contents_len;
394 
395 	mac_size = ses.keys->recv.algo_mac->hashsize;
396 	contents_len = ses.readbuf->len - mac_size;
397 
398 	buf_setpos(ses.readbuf, 0);
399 	make_mac(ses.recvseq, &ses.keys->recv, ses.readbuf, contents_len, mac_bytes);
400 
401 #if DROPBEAR_FUZZ
402 	if (fuzz.fuzzing) {
403 	 	/* fail 1 in 2000 times to test error path. */
404 		unsigned int value = 0;
405 		if (mac_size > sizeof(value)) {
406 			memcpy(&value, mac_bytes, sizeof(value));
407 		}
408 		if (value % 2000 == 99) {
409 			return DROPBEAR_FAILURE;
410 		}
411 		return DROPBEAR_SUCCESS;
412 	}
413 #endif
414 
415 	/* compare the hash */
416 	buf_setpos(ses.readbuf, contents_len);
417 	if (constant_time_memcmp(mac_bytes, buf_getptr(ses.readbuf, mac_size), mac_size) != 0) {
418 		return DROPBEAR_FAILURE;
419 	} else {
420 		return DROPBEAR_SUCCESS;
421 	}
422 }
423 
424 #ifndef DISABLE_ZLIB
425 /* returns a pointer to a newly created buffer */
buf_decompress(const buffer * buf,unsigned int len)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 	ret = buf_new(len);
434 
435 	zstream->avail_in = len;
436 	zstream->next_in = buf_getptr(buf, len);
437 
438 	/* decompress the payload, incrementally resizing the output buffer */
439 	while (1) {
440 
441 		zstream->avail_out = ret->size - ret->pos;
442 		zstream->next_out = buf_getwriteptr(ret, zstream->avail_out);
443 
444 		result = inflate(zstream, Z_SYNC_FLUSH);
445 
446 		buf_setlen(ret, ret->size - zstream->avail_out);
447 		buf_setpos(ret, ret->len);
448 
449 		if (result != Z_BUF_ERROR && result != Z_OK) {
450 			dropbear_exit("zlib error");
451 		}
452 
453 		if (zstream->avail_in == 0 &&
454 		   		(zstream->avail_out != 0 || result == Z_BUF_ERROR)) {
455 			/* we can only exit if avail_out hasn't all been used,
456 			 * and there's no remaining input */
457 			return ret;
458 		}
459 
460 		if (zstream->avail_out == 0) {
461 			int new_size = 0;
462 			if (ret->size >= RECV_MAX_PAYLOAD_LEN) {
463 				/* Already been increased as large as it can go,
464 				 * yet didn't finish up the decompression */
465 				dropbear_exit("bad packet, oversized decompressed");
466 			}
467 			new_size = MIN(RECV_MAX_PAYLOAD_LEN, ret->size + ZLIB_DECOMPRESS_INCR);
468 			ret = buf_resize(ret, new_size);
469 		}
470 	}
471 }
472 #endif
473 
474 
475 /* returns 1 if the packet is a valid type during kex (see 7.1 of rfc4253) */
packet_is_okay_kex(unsigned char type)476 static int packet_is_okay_kex(unsigned char type) {
477 	if (type >= SSH_MSG_USERAUTH_REQUEST) {
478 		return 0;
479 	}
480 	if (type == SSH_MSG_SERVICE_REQUEST || type == SSH_MSG_SERVICE_ACCEPT) {
481 		return 0;
482 	}
483 	if (type == SSH_MSG_KEXINIT) {
484 		/* XXX should this die horribly if !dataallowed ?? */
485 		return 0;
486 	}
487 	return 1;
488 }
489 
enqueue_reply_packet()490 static void enqueue_reply_packet() {
491 	struct packetlist * new_item = NULL;
492 	new_item = m_malloc(sizeof(struct packetlist));
493 	new_item->next = NULL;
494 
495 	new_item->payload = buf_newcopy(ses.writepayload);
496 	buf_setpos(ses.writepayload, 0);
497 	buf_setlen(ses.writepayload, 0);
498 
499 	if (ses.reply_queue_tail) {
500 		ses.reply_queue_tail->next = new_item;
501 	} else {
502 		ses.reply_queue_head = new_item;
503 	}
504 	ses.reply_queue_tail = new_item;
505 }
506 
maybe_flush_reply_queue()507 void maybe_flush_reply_queue() {
508 	struct packetlist *tmp_item = NULL, *curr_item = NULL;
509 	if (!ses.dataallowed)
510 	{
511 		TRACE(("maybe_empty_reply_queue - no data allowed"))
512 		return;
513 	}
514 
515 	for (curr_item = ses.reply_queue_head; curr_item; ) {
516 		CHECKCLEARTOWRITE();
517 		buf_putbytes(ses.writepayload,
518 			curr_item->payload->data, curr_item->payload->len);
519 
520 		buf_free(curr_item->payload);
521 		tmp_item = curr_item;
522 		curr_item = curr_item->next;
523 		m_free(tmp_item);
524 		encrypt_packet();
525 	}
526 	ses.reply_queue_head = ses.reply_queue_tail = NULL;
527 }
528 
529 /* encrypt the writepayload, putting into writebuf, ready for write_packet()
530  * to put on the wire */
encrypt_packet()531 void encrypt_packet() {
532 
533 	unsigned char padlen;
534 	unsigned char blocksize, mac_size;
535 	buffer * writebuf; /* the packet which will go on the wire. This is
536 	                      encrypted in-place. */
537 	unsigned char packet_type;
538 	unsigned int len, encrypt_buf_size;
539 	unsigned char mac_bytes[MAX_MAC_LEN];
540 
541 	time_t now;
542 
543 	TRACE2(("enter encrypt_packet()"))
544 
545 	buf_setpos(ses.writepayload, 0);
546 	packet_type = buf_getbyte(ses.writepayload);
547 	buf_setpos(ses.writepayload, 0);
548 
549 	TRACE2(("encrypt_packet type is %d", packet_type))
550 
551 	if ((!ses.dataallowed && !packet_is_okay_kex(packet_type))) {
552 		/* During key exchange only particular packets are allowed.
553 			Since this packet_type isn't OK we just enqueue it to send
554 			after the KEX, see maybe_flush_reply_queue */
555 		enqueue_reply_packet();
556 		return;
557 	}
558 
559 	blocksize = ses.keys->trans.algo_crypt->blocksize;
560 	mac_size = ses.keys->trans.algo_mac->hashsize;
561 
562 	/* Encrypted packet len is payload+5. We need to then make sure
563 	 * there is enough space for padding or MIN_PACKET_LEN.
564 	 * Add extra 3 since we need at least 4 bytes of padding */
565 	encrypt_buf_size = (ses.writepayload->len+4+1)
566 		+ MAX(MIN_PACKET_LEN, blocksize) + 3
567 	/* add space for the MAC at the end */
568 				+ mac_size
569 #ifndef DISABLE_ZLIB
570 	/* some extra in case 'compression' makes it larger */
571 				+ ZLIB_COMPRESS_EXPANSION
572 #endif
573 	/* and an extra cleartext (stripped before transmission) byte for the
574 	 * packet type */
575 				+ 1;
576 
577 	writebuf = buf_new(encrypt_buf_size);
578 	buf_setlen(writebuf, PACKET_PAYLOAD_OFF);
579 	buf_setpos(writebuf, PACKET_PAYLOAD_OFF);
580 
581 #ifndef DISABLE_ZLIB
582 	/* compression */
583 	if (is_compress_trans()) {
584 		buf_compress(writebuf, ses.writepayload, ses.writepayload->len);
585 	} else
586 #endif
587 	{
588 		memcpy(buf_getwriteptr(writebuf, ses.writepayload->len),
589 				buf_getptr(ses.writepayload, ses.writepayload->len),
590 				ses.writepayload->len);
591 		buf_incrwritepos(writebuf, ses.writepayload->len);
592 	}
593 
594 	/* finished with payload */
595 	buf_setpos(ses.writepayload, 0);
596 	buf_setlen(ses.writepayload, 0);
597 
598 	/* length of padding - packet length excluding the packetlength uint32
599 	 * field in aead mode must be a multiple of blocksize, with a minimum of
600 	 * 4 bytes of padding */
601 	len = writebuf->len;
602 #if DROPBEAR_AEAD_MODE
603 	if (ses.keys->trans.crypt_mode->aead_crypt) {
604 		len -= 4;
605 	}
606 #endif
607 	padlen = blocksize - len % blocksize;
608 	if (padlen < 4) {
609 		padlen += blocksize;
610 	}
611 	/* check for min packet length */
612 	if (writebuf->len + padlen < MIN_PACKET_LEN) {
613 		padlen += blocksize;
614 	}
615 
616 	buf_setpos(writebuf, 0);
617 	/* packet length excluding the packetlength uint32 */
618 	buf_putint(writebuf, writebuf->len + padlen - 4);
619 
620 	/* padding len */
621 	buf_putbyte(writebuf, padlen);
622 	/* actual padding */
623 	buf_setpos(writebuf, writebuf->len);
624 	buf_incrlen(writebuf, padlen);
625 	genrandom(buf_getptr(writebuf, padlen), padlen);
626 
627 #if DROPBEAR_AEAD_MODE
628 	if (ses.keys->trans.crypt_mode->aead_crypt) {
629 		/* do the actual encryption, in-place */
630 		buf_setpos(writebuf, 0);
631 		/* encrypt it in-place*/
632 		len = writebuf->len;
633 		buf_incrlen(writebuf, mac_size);
634 		if (ses.keys->trans.crypt_mode->aead_crypt(ses.transseq,
635 					buf_getptr(writebuf, len),
636 					buf_getwriteptr(writebuf, len + mac_size),
637 					len, mac_size,
638 					&ses.keys->trans.cipher_state, LTC_ENCRYPT) != CRYPT_OK) {
639 			dropbear_exit("Error encrypting");
640 		}
641 		buf_incrpos(writebuf, len + mac_size);
642 	} else
643 #endif
644 	{
645 		make_mac(ses.transseq, &ses.keys->trans, writebuf, writebuf->len, mac_bytes);
646 
647 		/* do the actual encryption, in-place */
648 		buf_setpos(writebuf, 0);
649 		/* encrypt it in-place*/
650 		len = writebuf->len;
651 		if (ses.keys->trans.crypt_mode->encrypt(
652 					buf_getptr(writebuf, len),
653 					buf_getwriteptr(writebuf, len),
654 					len,
655 					&ses.keys->trans.cipher_state) != CRYPT_OK) {
656 			dropbear_exit("Error encrypting");
657 		}
658 		buf_incrpos(writebuf, len);
659 
660 		/* stick the MAC on it */
661 		buf_putbytes(writebuf, mac_bytes, mac_size);
662 	}
663 
664 	/* Update counts */
665 	ses.kexstate.datatrans += writebuf->len;
666 
667 	writebuf_enqueue(writebuf);
668 
669 	/* Update counts */
670 	ses.transseq++;
671 
672 	now = monotonic_now();
673 	ses.last_packet_time_any_sent = now;
674 	/* idle timeout shouldn't be affected by responses to keepalives.
675 	send_msg_keepalive() itself also does tricks with
676 	ses.last_packet_idle_time - read that if modifying this code */
677 	if (packet_type != SSH_MSG_REQUEST_FAILURE
678 		&& packet_type != SSH_MSG_UNIMPLEMENTED
679 		&& packet_type != SSH_MSG_IGNORE) {
680 		ses.last_packet_time_idle = now;
681 
682 	}
683 
684 	TRACE2(("leave encrypt_packet()"))
685 }
686 
writebuf_enqueue(buffer * writebuf)687 void writebuf_enqueue(buffer * writebuf) {
688 	/* enqueue the packet for sending. It will get freed after transmission. */
689 	buf_setpos(writebuf, 0);
690 	enqueue(&ses.writequeue, (void*)writebuf);
691 	ses.writequeue_len += writebuf->len;
692 }
693 
694 
695 /* Create the packet mac, and append H(seqno|clearbuf) to the output */
696 /* output_mac must have ses.keys->trans.algo_mac->hashsize bytes. */
make_mac(unsigned int seqno,const struct key_context_directional * key_state,buffer * clear_buf,unsigned int clear_len,unsigned char * output_mac)697 static void make_mac(unsigned int seqno, const struct key_context_directional * key_state,
698 		buffer * clear_buf, unsigned int clear_len,
699 		unsigned char *output_mac) {
700 	unsigned char seqbuf[4];
701 	unsigned long bufsize;
702 	hmac_state hmac;
703 
704 	if (key_state->algo_mac->hashsize > 0) {
705 		/* calculate the mac */
706 		if (hmac_init(&hmac,
707 					key_state->hash_index,
708 					key_state->mackey,
709 					key_state->algo_mac->keysize) != CRYPT_OK) {
710 			dropbear_exit("HMAC error");
711 		}
712 
713 		/* sequence number */
714 		STORE32H(seqno, seqbuf);
715 		if (hmac_process(&hmac, seqbuf, 4) != CRYPT_OK) {
716 			dropbear_exit("HMAC error");
717 		}
718 
719 		/* the actual contents */
720 		buf_setpos(clear_buf, 0);
721 		if (hmac_process(&hmac,
722 					buf_getptr(clear_buf, clear_len),
723 					clear_len) != CRYPT_OK) {
724 			dropbear_exit("HMAC error");
725 		}
726 
727 		bufsize = MAX_MAC_LEN;
728 		if (hmac_done(&hmac, output_mac, &bufsize) != CRYPT_OK) {
729 			dropbear_exit("HMAC error");
730 		}
731 	}
732 	TRACE2(("leave writemac"))
733 }
734 
735 #ifndef DISABLE_ZLIB
736 /* compresses len bytes from src, outputting to dest (starting from the
737  * respective current positions. dest must have sufficient space,
738  * len+ZLIB_COMPRESS_EXPANSION */
buf_compress(buffer * dest,buffer * src,unsigned int len)739 static void buf_compress(buffer * dest, buffer * src, unsigned int len) {
740 
741 	unsigned int endpos = src->pos + len;
742 	int result;
743 
744 	TRACE2(("enter buf_compress"))
745 
746 	dropbear_assert(dest->size - dest->pos >= len+ZLIB_COMPRESS_EXPANSION);
747 
748 	ses.keys->trans.zstream->avail_in = endpos - src->pos;
749 	ses.keys->trans.zstream->next_in =
750 		buf_getptr(src, ses.keys->trans.zstream->avail_in);
751 
752 	ses.keys->trans.zstream->avail_out = dest->size - dest->pos;
753 	ses.keys->trans.zstream->next_out =
754 		buf_getwriteptr(dest, ses.keys->trans.zstream->avail_out);
755 
756 	result = deflate(ses.keys->trans.zstream, Z_SYNC_FLUSH);
757 
758 	buf_setpos(src, endpos - ses.keys->trans.zstream->avail_in);
759 	buf_setlen(dest, dest->size - ses.keys->trans.zstream->avail_out);
760 	buf_setpos(dest, dest->len);
761 
762 	if (result != Z_OK) {
763 		dropbear_exit("zlib error");
764 	}
765 
766 	/* fails if destination buffer wasn't large enough */
767 	dropbear_assert(ses.keys->trans.zstream->avail_in == 0);
768 	TRACE2(("leave buf_compress"))
769 }
770 #endif
771