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