summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatt Johnston <matt@ucc.asn.au>2009-03-01 16:15:57 +0000
committerMatt Johnston <matt@ucc.asn.au>2009-03-01 16:15:57 +0000
commitbb6826febca9e61998d5a65a44ec27a77de2f2d4 (patch)
treedb341584ccdfc37492f4d74d2ba6c7fd79579149
parentdaae0ec37b94205651ed1565fc71498555f2e098 (diff)
downloaddropbear-bb6826febca9e61998d5a65a44ec27a77de2f2d4.tar.gz
- Get rid of decryptreadbuf, just decrypt in-place with readbuf
- Share make_mac function for both packet creation and validation - Split recv/trans parts of key_context into their own structures
-rw-r--r--common-kex.c114
-rw-r--r--common-session.c21
-rw-r--r--packet.c198
-rw-r--r--packet.h2
-rw-r--r--session.h51
5 files changed, 175 insertions, 211 deletions
diff --git a/common-kex.c b/common-kex.c
index c62516c..052324b 100644
--- a/common-kex.c
+++ b/common-kex.c
@@ -272,8 +272,8 @@ void gen_new_keys() {
recv_IV = S2C_IV;
trans_key = C2S_key;
recv_key = S2C_key;
- C2S_keysize = ses.newkeys->trans_algo_crypt->keysize;
- S2C_keysize = ses.newkeys->recv_algo_crypt->keysize;
+ C2S_keysize = ses.newkeys->trans.algo_crypt->keysize;
+ S2C_keysize = ses.newkeys->recv.algo_crypt->keysize;
mactransletter = 'E';
macrecvletter = 'F';
} else {
@@ -281,8 +281,8 @@ void gen_new_keys() {
recv_IV = C2S_IV;
trans_key = S2C_key;
recv_key = C2S_key;
- C2S_keysize = ses.newkeys->recv_algo_crypt->keysize;
- S2C_keysize = ses.newkeys->trans_algo_crypt->keysize;
+ C2S_keysize = ses.newkeys->recv.algo_crypt->keysize;
+ S2C_keysize = ses.newkeys->trans.algo_crypt->keysize;
mactransletter = 'F';
macrecvletter = 'E';
}
@@ -292,31 +292,33 @@ void gen_new_keys() {
hashkeys(C2S_key, C2S_keysize, &hs, 'C');
hashkeys(S2C_key, S2C_keysize, &hs, 'D');
- recv_cipher = find_cipher(ses.newkeys->recv_algo_crypt->cipherdesc->name);
+ recv_cipher = find_cipher(ses.newkeys->recv.algo_crypt->cipherdesc->name);
if (recv_cipher < 0)
dropbear_exit("crypto error");
- if (ses.newkeys->recv_crypt_mode->start(recv_cipher,
+ if (ses.newkeys->recv.crypt_mode->start(recv_cipher,
recv_IV, recv_key,
- ses.newkeys->recv_algo_crypt->keysize, 0,
- &ses.newkeys->recv_cipher_state) != CRYPT_OK) {
+ ses.newkeys->recv.algo_crypt->keysize, 0,
+ &ses.newkeys->recv.cipher_state) != CRYPT_OK) {
dropbear_exit("crypto error");
}
- trans_cipher = find_cipher(ses.newkeys->trans_algo_crypt->cipherdesc->name);
+ trans_cipher = find_cipher(ses.newkeys->trans.algo_crypt->cipherdesc->name);
if (trans_cipher < 0)
dropbear_exit("crypto error");
- if (ses.newkeys->trans_crypt_mode->start(trans_cipher,
+ if (ses.newkeys->trans.crypt_mode->start(trans_cipher,
trans_IV, trans_key,
- ses.newkeys->trans_algo_crypt->keysize, 0,
- &ses.newkeys->trans_cipher_state) != CRYPT_OK) {
+ ses.newkeys->trans.algo_crypt->keysize, 0,
+ &ses.newkeys->trans.cipher_state) != CRYPT_OK) {
dropbear_exit("crypto error");
}
/* MAC keys */
- hashkeys(ses.newkeys->transmackey,
- ses.newkeys->trans_algo_mac->keysize, &hs, mactransletter);
- hashkeys(ses.newkeys->recvmackey,
- ses.newkeys->recv_algo_mac->keysize, &hs, macrecvletter);
+ hashkeys(ses.newkeys->trans.mackey,
+ ses.newkeys->trans.algo_mac->keysize, &hs, mactransletter);
+ hashkeys(ses.newkeys->recv.mackey,
+ ses.newkeys->recv.algo_mac->keysize, &hs, macrecvletter);
+ ses.newkeys->trans.hash_index = find_hash(ses.newkeys->trans.algo_mac->hashdesc->name),
+ ses.newkeys->recv.hash_index = find_hash(ses.newkeys->recv.algo_mac->hashdesc->name),
#ifndef DISABLE_ZLIB
gen_new_zstreams();
@@ -334,15 +336,15 @@ void gen_new_keys() {
#ifndef DISABLE_ZLIB
int is_compress_trans() {
- return ses.keys->trans_algo_comp == DROPBEAR_COMP_ZLIB
+ return ses.keys->trans.algo_comp == DROPBEAR_COMP_ZLIB
|| (ses.authstate.authdone
- && ses.keys->trans_algo_comp == DROPBEAR_COMP_ZLIB_DELAY);
+ && ses.keys->trans.algo_comp == DROPBEAR_COMP_ZLIB_DELAY);
}
int is_compress_recv() {
- return ses.keys->recv_algo_comp == DROPBEAR_COMP_ZLIB
+ return ses.keys->recv.algo_comp == DROPBEAR_COMP_ZLIB
|| (ses.authstate.authdone
- && ses.keys->recv_algo_comp == DROPBEAR_COMP_ZLIB_DELAY);
+ && ses.keys->recv.algo_comp == DROPBEAR_COMP_ZLIB_DELAY);
}
/* Set up new zlib compression streams, close the old ones. Only
@@ -350,47 +352,47 @@ int is_compress_recv() {
static void gen_new_zstreams() {
/* create new zstreams */
- if (ses.newkeys->recv_algo_comp == DROPBEAR_COMP_ZLIB
- || ses.newkeys->recv_algo_comp == DROPBEAR_COMP_ZLIB_DELAY) {
- ses.newkeys->recv_zstream = (z_streamp)m_malloc(sizeof(z_stream));
- ses.newkeys->recv_zstream->zalloc = Z_NULL;
- ses.newkeys->recv_zstream->zfree = Z_NULL;
+ if (ses.newkeys->recv.algo_comp == DROPBEAR_COMP_ZLIB
+ || ses.newkeys->recv.algo_comp == DROPBEAR_COMP_ZLIB_DELAY) {
+ ses.newkeys->recv.zstream = (z_streamp)m_malloc(sizeof(z_stream));
+ ses.newkeys->recv.zstream->zalloc = Z_NULL;
+ ses.newkeys->recv.zstream->zfree = Z_NULL;
- if (inflateInit(ses.newkeys->recv_zstream) != Z_OK) {
+ if (inflateInit(ses.newkeys->recv.zstream) != Z_OK) {
dropbear_exit("zlib error");
}
} else {
- ses.newkeys->recv_zstream = NULL;
+ ses.newkeys->recv.zstream = NULL;
}
- if (ses.newkeys->trans_algo_comp == DROPBEAR_COMP_ZLIB
- || ses.newkeys->trans_algo_comp == DROPBEAR_COMP_ZLIB_DELAY) {
- ses.newkeys->trans_zstream = (z_streamp)m_malloc(sizeof(z_stream));
- ses.newkeys->trans_zstream->zalloc = Z_NULL;
- ses.newkeys->trans_zstream->zfree = Z_NULL;
+ if (ses.newkeys->trans.algo_comp == DROPBEAR_COMP_ZLIB
+ || ses.newkeys->trans.algo_comp == DROPBEAR_COMP_ZLIB_DELAY) {
+ ses.newkeys->trans.zstream = (z_streamp)m_malloc(sizeof(z_stream));
+ ses.newkeys->trans.zstream->zalloc = Z_NULL;
+ ses.newkeys->trans.zstream->zfree = Z_NULL;
- if (deflateInit(ses.newkeys->trans_zstream, Z_DEFAULT_COMPRESSION)
+ if (deflateInit(ses.newkeys->trans.zstream, Z_DEFAULT_COMPRESSION)
!= Z_OK) {
dropbear_exit("zlib error");
}
} else {
- ses.newkeys->trans_zstream = NULL;
+ ses.newkeys->trans.zstream = NULL;
}
/* clean up old keys */
- if (ses.keys->recv_zstream != NULL) {
- if (inflateEnd(ses.keys->recv_zstream) == Z_STREAM_ERROR) {
+ if (ses.keys->recv.zstream != NULL) {
+ if (inflateEnd(ses.keys->recv.zstream) == Z_STREAM_ERROR) {
/* Z_DATA_ERROR is ok, just means that stream isn't ended */
dropbear_exit("crypto error");
}
- m_free(ses.keys->recv_zstream);
+ m_free(ses.keys->recv.zstream);
}
- if (ses.keys->trans_zstream != NULL) {
- if (deflateEnd(ses.keys->trans_zstream) == Z_STREAM_ERROR) {
+ if (ses.keys->trans.zstream != NULL) {
+ if (deflateEnd(ses.keys->trans.zstream) == Z_STREAM_ERROR) {
/* Z_DATA_ERROR is ok, just means that stream isn't ended */
dropbear_exit("crypto error");
}
- m_free(ses.keys->trans_zstream);
+ m_free(ses.keys->trans.zstream);
}
}
#endif /* DISABLE_ZLIB */
@@ -698,36 +700,36 @@ static void read_kex_algos() {
/* Handle the asymmetry */
if (IS_DROPBEAR_CLIENT) {
- ses.newkeys->recv_algo_crypt =
+ ses.newkeys->recv.algo_crypt =
(struct dropbear_cipher*)s2c_cipher_algo->data;
- ses.newkeys->trans_algo_crypt =
+ ses.newkeys->trans.algo_crypt =
(struct dropbear_cipher*)c2s_cipher_algo->data;
- ses.newkeys->recv_crypt_mode =
+ ses.newkeys->recv.crypt_mode =
(struct dropbear_cipher_mode*)s2c_cipher_algo->mode;
- ses.newkeys->trans_crypt_mode =
+ ses.newkeys->trans.crypt_mode =
(struct dropbear_cipher_mode*)c2s_cipher_algo->mode;
- ses.newkeys->recv_algo_mac =
+ ses.newkeys->recv.algo_mac =
(struct dropbear_hash*)s2c_hash_algo->data;
- ses.newkeys->trans_algo_mac =
+ ses.newkeys->trans.algo_mac =
(struct dropbear_hash*)c2s_hash_algo->data;
- ses.newkeys->recv_algo_comp = s2c_comp_algo->val;
- ses.newkeys->trans_algo_comp = c2s_comp_algo->val;
+ ses.newkeys->recv.algo_comp = s2c_comp_algo->val;
+ ses.newkeys->trans.algo_comp = c2s_comp_algo->val;
} else {
/* SERVER */
- ses.newkeys->recv_algo_crypt =
+ ses.newkeys->recv.algo_crypt =
(struct dropbear_cipher*)c2s_cipher_algo->data;
- ses.newkeys->trans_algo_crypt =
+ ses.newkeys->trans.algo_crypt =
(struct dropbear_cipher*)s2c_cipher_algo->data;
- ses.newkeys->recv_crypt_mode =
+ ses.newkeys->recv.crypt_mode =
(struct dropbear_cipher_mode*)c2s_cipher_algo->mode;
- ses.newkeys->trans_crypt_mode =
+ ses.newkeys->trans.crypt_mode =
(struct dropbear_cipher_mode*)s2c_cipher_algo->mode;
- ses.newkeys->recv_algo_mac =
+ ses.newkeys->recv.algo_mac =
(struct dropbear_hash*)c2s_hash_algo->data;
- ses.newkeys->trans_algo_mac =
+ ses.newkeys->trans.algo_mac =
(struct dropbear_hash*)s2c_hash_algo->data;
- ses.newkeys->recv_algo_comp = c2s_comp_algo->val;
- ses.newkeys->trans_algo_comp = s2c_comp_algo->val;
+ ses.newkeys->recv.algo_comp = c2s_comp_algo->val;
+ ses.newkeys->trans.algo_comp = s2c_comp_algo->val;
}
/* reserved for future extensions */
diff --git a/common-session.c b/common-session.c
index b48d210..3663534 100644
--- a/common-session.c
+++ b/common-session.c
@@ -78,7 +78,6 @@ void common_session_init(int sock_in, int sock_out, char* remotehost) {
ses.transseq = 0;
ses.readbuf = NULL;
- ses.decryptreadbuf = NULL;
ses.payload = NULL;
ses.recvseq = 0;
@@ -95,22 +94,22 @@ void common_session_init(int sock_in, int sock_out, char* remotehost) {
/* set all the algos to none */
ses.keys = (struct key_context*)m_malloc(sizeof(struct key_context));
ses.newkeys = NULL;
- ses.keys->recv_algo_crypt = &dropbear_nocipher;
- ses.keys->trans_algo_crypt = &dropbear_nocipher;
- ses.keys->recv_crypt_mode = &dropbear_mode_none;
- ses.keys->trans_crypt_mode = &dropbear_mode_none;
+ ses.keys->recv.algo_crypt = &dropbear_nocipher;
+ ses.keys->trans.algo_crypt = &dropbear_nocipher;
+ ses.keys->recv.crypt_mode = &dropbear_mode_none;
+ ses.keys->trans.crypt_mode = &dropbear_mode_none;
- ses.keys->recv_algo_mac = &dropbear_nohash;
- ses.keys->trans_algo_mac = &dropbear_nohash;
+ ses.keys->recv.algo_mac = &dropbear_nohash;
+ ses.keys->trans.algo_mac = &dropbear_nohash;
ses.keys->algo_kex = -1;
ses.keys->algo_hostkey = -1;
- ses.keys->recv_algo_comp = DROPBEAR_COMP_NONE;
- ses.keys->trans_algo_comp = DROPBEAR_COMP_NONE;
+ ses.keys->recv.algo_comp = DROPBEAR_COMP_NONE;
+ ses.keys->trans.algo_comp = DROPBEAR_COMP_NONE;
#ifndef DISABLE_ZLIB
- ses.keys->recv_zstream = NULL;
- ses.keys->trans_zstream = NULL;
+ ses.keys->recv.zstream = NULL;
+ ses.keys->trans.zstream = NULL;
#endif
/* key exchange buffers */
diff --git a/packet.c b/packet.c
index 683525d..6a294f4 100644
--- a/packet.c
+++ b/packet.c
@@ -35,9 +35,11 @@
#include "auth.h"
#include "channel.h"
-static void read_packet_init();
-static void make_mac(buffer * clearwritebuf, unsigned char *output_mac);
-static int checkmac(buffer* hashbuf, buffer* readbuf);
+static int read_packet_init();
+static void make_mac(unsigned int seqno, const struct key_context_directional * key_state,
+ buffer * clear_buf, unsigned int clear_len,
+ unsigned char *output_mac);
+static int checkmac();
#define ZLIB_COMPRESS_INCR 20 /* this is 12 bytes + 0.1% of 8000 bytes */
#define ZLIB_DECOMPRESS_INCR 100
@@ -102,18 +104,18 @@ void read_packet() {
unsigned char blocksize;
TRACE(("enter read_packet"))
- blocksize = ses.keys->recv_algo_crypt->blocksize;
+ blocksize = ses.keys->recv.algo_crypt->blocksize;
if (ses.readbuf == NULL || ses.readbuf->len < blocksize) {
+ int ret;
/* In the first blocksize of a packet */
/* Read the first blocksize of the packet, so we can decrypt it and
* find the length of the whole packet */
- read_packet_init();
+ ret = read_packet_init();
- /* If we don't have the length of decryptreadbuf, we didn't read
- * a whole blocksize and should exit */
- if (ses.decryptreadbuf->len == 0) {
+ if (ret == DROPBEAR_FAILURE) {
+ /* didn't read enough to determine the length */
TRACE(("leave read_packet: packetinit done"))
return;
}
@@ -121,7 +123,6 @@ void read_packet() {
/* Attempt to read the remainder of the packet, note that there
* mightn't be any available (EAGAIN) */
- dropbear_assert(ses.readbuf != NULL);
maxlen = ses.readbuf->len - ses.readbuf->pos;
len = read(ses.sock_in, buf_getptr(ses.readbuf, maxlen), maxlen);
@@ -151,7 +152,9 @@ void read_packet() {
/* Function used to read the initial portion of a packet, and determine the
* length. Only called during the first BLOCKSIZE of a packet. */
-static void read_packet_init() {
+/* Returns DROPBEAR_SUCCESS if the length is determined,
+ * DROPBEAR_FAILURE otherwise */
+static int read_packet_init() {
unsigned int maxlen;
int len;
@@ -159,14 +162,12 @@ static void read_packet_init() {
unsigned char macsize;
- blocksize = ses.keys->recv_algo_crypt->blocksize;
- macsize = ses.keys->recv_algo_mac->hashsize;
+ blocksize = ses.keys->recv.algo_crypt->blocksize;
+ macsize = ses.keys->recv.algo_mac->hashsize;
if (ses.readbuf == NULL) {
/* start of a new packet */
ses.readbuf = buf_new(INIT_READBUF);
- dropbear_assert(ses.decryptreadbuf == NULL);
- ses.decryptreadbuf = buf_new(blocksize);
}
maxlen = blocksize - ses.readbuf->pos;
@@ -180,7 +181,7 @@ static void read_packet_init() {
if (len < 0) {
if (errno == EINTR) {
TRACE(("leave read_packet_init: EINTR"))
- return;
+ return DROPBEAR_FAILURE;
}
dropbear_exit("error reading: %s", strerror(errno));
}
@@ -189,22 +190,22 @@ static void read_packet_init() {
if ((unsigned int)len != maxlen) {
/* don't have enough bytes to determine length, get next time */
- return;
+ return DROPBEAR_FAILURE;
}
/* now we have the first block, need to get packet length, so we decrypt
* the first block (only need first 4 bytes) */
buf_setpos(ses.readbuf, 0);
- if (ses.keys->recv_crypt_mode->decrypt(buf_getptr(ses.readbuf, blocksize),
- buf_getwriteptr(ses.decryptreadbuf,blocksize),
+ if (ses.keys->recv.crypt_mode->decrypt(buf_getptr(ses.readbuf, blocksize),
+ buf_getwriteptr(ses.readbuf, blocksize),
blocksize,
- &ses.keys->recv_cipher_state) != CRYPT_OK) {
+ &ses.keys->recv.cipher_state) != CRYPT_OK) {
dropbear_exit("error decrypting");
}
- buf_setlen(ses.decryptreadbuf, blocksize);
- len = buf_getint(ses.decryptreadbuf) + 4 + macsize;
+ len = buf_getint(ses.readbuf) + 4 + macsize;
+
+ TRACE(("packet size is %d, block %d mac %d", len, blocksize, macsize))
- buf_setpos(ses.readbuf, blocksize);
/* check packet length */
if ((len > RECV_MAX_PACKET_LEN) ||
@@ -213,9 +214,12 @@ static void read_packet_init() {
dropbear_exit("bad packet size %d", len);
}
- buf_resize(ses.readbuf, len);
+ if (len > ses.readbuf->size) {
+ buf_resize(ses.readbuf, len);
+ }
buf_setlen(ses.readbuf, len);
-
+ buf_setpos(ses.readbuf, blocksize);
+ return DROPBEAR_SUCCESS;
}
/* handle the received packet */
@@ -227,68 +231,60 @@ void decrypt_packet() {
unsigned int len;
TRACE(("enter decrypt_packet"))
- blocksize = ses.keys->recv_algo_crypt->blocksize;
- macsize = ses.keys->recv_algo_mac->hashsize;
+ blocksize = ses.keys->recv.algo_crypt->blocksize;
+ macsize = ses.keys->recv.algo_mac->hashsize;
ses.kexstate.datarecv += ses.readbuf->len;
/* we've already decrypted the first blocksize in read_packet_init */
buf_setpos(ses.readbuf, blocksize);
- buf_resize(ses.decryptreadbuf, ses.readbuf->len - macsize);
- buf_setlen(ses.decryptreadbuf, ses.decryptreadbuf->size);
- buf_setpos(ses.decryptreadbuf, blocksize);
-
- /* decrypt it */
+ /* decrypt it in-place */
len = ses.readbuf->len - macsize - ses.readbuf->pos;
- if (ses.keys->recv_crypt_mode->decrypt(
+ if (ses.keys->recv.crypt_mode->decrypt(
buf_getptr(ses.readbuf, len),
- buf_getwriteptr(ses.decryptreadbuf, len),
+ buf_getwriteptr(ses.readbuf, len),
len,
- &ses.keys->recv_cipher_state) != CRYPT_OK) {
+ &ses.keys->recv.cipher_state) != CRYPT_OK) {
dropbear_exit("error decrypting");
}
buf_incrpos(ses.readbuf, len);
- buf_incrwritepos(ses.decryptreadbuf, len);
+
+ printhex("readbuf decrypted", ses.readbuf->data, ses.readbuf->len);
/* check the hmac */
- buf_setpos(ses.readbuf, ses.readbuf->len - macsize);
- if (checkmac(ses.readbuf, ses.decryptreadbuf) != DROPBEAR_SUCCESS) {
+ if (checkmac() != DROPBEAR_SUCCESS) {
dropbear_exit("Integrity error");
}
- /* readbuf no longer required */
- buf_free(ses.readbuf);
- ses.readbuf = NULL;
-
/* get padding length */
- buf_setpos(ses.decryptreadbuf, PACKET_PADDING_OFF);
- padlen = buf_getbyte(ses.decryptreadbuf);
+ buf_setpos(ses.readbuf, PACKET_PADDING_OFF);
+ padlen = buf_getbyte(ses.readbuf);
/* payload length */
/* - 4 - 1 is for LEN and PADLEN values */
- len = ses.decryptreadbuf->len - padlen - 4 - 1;
+ len = ses.readbuf->len - padlen - 4 - 1;
if ((len > RECV_MAX_PAYLOAD_LEN) || (len < 1)) {
dropbear_exit("bad packet size");
}
- buf_setpos(ses.decryptreadbuf, PACKET_PAYLOAD_OFF);
+ buf_setpos(ses.readbuf, PACKET_PAYLOAD_OFF);
#ifndef DISABLE_ZLIB
if (is_compress_recv()) {
/* decompress */
- ses.payload = buf_decompress(ses.decryptreadbuf, len);
+ ses.payload = buf_decompress(ses.readbuf, len);
} else
#endif
{
/* copy payload */
ses.payload = buf_new(len);
- memcpy(ses.payload->data, buf_getptr(ses.decryptreadbuf, len), len);
+ memcpy(ses.payload->data, buf_getptr(ses.readbuf, len), len);
buf_incrlen(ses.payload, len);
}
- buf_free(ses.decryptreadbuf);
- ses.decryptreadbuf = NULL;
+ buf_free(ses.readbuf);
+ ses.readbuf = NULL;
buf_setpos(ses.payload, 0);
ses.recvseq++;
@@ -296,49 +292,22 @@ void decrypt_packet() {
TRACE(("leave decrypt_packet"))
}
-/* Checks the mac in hashbuf, for the data in readbuf.
+/* Checks the mac at the end of a decrypted readbuf.
* Returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE */
-static int checkmac(buffer* macbuf, buffer* sourcebuf) {
+static int checkmac() {
- unsigned int macsize;
- hmac_state hmac;
- unsigned char tempbuf[MAX_MAC_LEN];
- unsigned long bufsize;
- unsigned int len;
-
- macsize = ses.keys->recv_algo_mac->hashsize;
- if (macsize == 0) {
- return DROPBEAR_SUCCESS;
- }
-
- /* calculate the mac */
- if (hmac_init(&hmac,
- find_hash(ses.keys->recv_algo_mac->hashdesc->name),
- ses.keys->recvmackey,
- ses.keys->recv_algo_mac->keysize)
- != CRYPT_OK) {
- dropbear_exit("HMAC error");
- }
+ unsigned char mac_bytes[MAX_MAC_LEN];
+ unsigned int mac_size, contents_len;
- /* sequence number */
- STORE32H(ses.recvseq, tempbuf);
- if (hmac_process(&hmac, tempbuf, 4) != CRYPT_OK) {
- dropbear_exit("HMAC error");
- }
+ mac_size = ses.keys->trans.algo_mac->hashsize;
+ contents_len = ses.readbuf->len - mac_size;
- buf_setpos(sourcebuf, 0);
- len = sourcebuf->len;
- if (hmac_process(&hmac, buf_getptr(sourcebuf, len), len) != CRYPT_OK) {
- dropbear_exit("HMAC error");
- }
-
- bufsize = sizeof(tempbuf);
- if (hmac_done(&hmac, tempbuf, &bufsize) != CRYPT_OK) {
- dropbear_exit("HMAC error");
- }
+ buf_setpos(ses.readbuf, 0);
+ make_mac(ses.recvseq, &ses.keys->recv, ses.readbuf, contents_len, mac_bytes);
/* compare the hash */
- if (memcmp(tempbuf, buf_getptr(macbuf, macsize), macsize) != 0) {
+ buf_setpos(ses.readbuf, contents_len);
+ if (memcmp(mac_bytes, buf_getptr(ses.readbuf, mac_size), mac_size) != 0) {
return DROPBEAR_FAILURE;
} else {
return DROPBEAR_SUCCESS;
@@ -353,7 +322,7 @@ static buffer* buf_decompress(buffer* buf, unsigned int len) {
buffer * ret;
z_streamp zstream;
- zstream = ses.keys->recv_zstream;
+ zstream = ses.keys->recv.zstream;
ret = buf_new(len);
zstream->avail_in = len;
@@ -468,8 +437,8 @@ void encrypt_packet() {
return;
}
- blocksize = ses.keys->trans_algo_crypt->blocksize;
- mac_size = ses.keys->trans_algo_mac->hashsize;
+ blocksize = ses.keys->trans.algo_crypt->blocksize;
+ mac_size = ses.keys->trans.algo_mac->hashsize;
/* Encrypted packet len is payload+5, then worst case is if we are 3 away
* from a blocksize multiple. In which case we need to pad to the
@@ -526,17 +495,17 @@ void encrypt_packet() {
buf_incrlen(writebuf, padlen);
genrandom(buf_getptr(writebuf, padlen), padlen);
- make_mac(writebuf, mac_bytes);
+ make_mac(ses.transseq, &ses.keys->trans, writebuf, writebuf->len, mac_bytes);
/* do the actual encryption, in-place */
buf_setpos(writebuf, 0);
/* encrypt it in-place*/
len = writebuf->len;
- if (ses.keys->trans_crypt_mode->encrypt(
+ if (ses.keys->trans.crypt_mode->encrypt(
buf_getptr(writebuf, len),
buf_getwriteptr(writebuf, len),
len,
- &ses.keys->trans_cipher_state) != CRYPT_OK) {
+ &ses.keys->trans.cipher_state) != CRYPT_OK) {
dropbear_exit("error encrypting");
}
buf_incrpos(writebuf, len);
@@ -557,35 +526,36 @@ void encrypt_packet() {
/* Create the packet mac, and append H(seqno|clearbuf) to the output */
-/* output_mac must have ses.keys->trans_algo_mac->hashsize bytes. */
-static void make_mac(buffer * clearwritebuf, unsigned char *output_mac) {
+/* output_mac must have ses.keys->trans.algo_mac->hashsize bytes. */
+static void make_mac(unsigned int seqno, const struct key_context_directional * key_state,
+ buffer * clear_buf, unsigned int clear_len,
+ unsigned char *output_mac) {
unsigned char seqbuf[4];
unsigned long bufsize;
hmac_state hmac;
TRACE(("enter writemac"))
- if (ses.keys->trans_algo_mac->hashsize > 0) {
+ if (key_state->algo_mac->hashsize > 0) {
/* calculate the mac */
if (hmac_init(&hmac,
- find_hash(ses.keys->trans_algo_mac->hashdesc->name),
- ses.keys->transmackey,
- ses.keys->trans_algo_mac->keysize) != CRYPT_OK) {
+ key_state->hash_index,
+ key_state->mackey,
+ key_state->algo_mac->keysize) != CRYPT_OK) {
dropbear_exit("HMAC error");
}
/* sequence number */
- STORE32H(ses.transseq, seqbuf);
+ STORE32H(seqno, seqbuf);
if (hmac_process(&hmac, seqbuf, 4) != CRYPT_OK) {
dropbear_exit("HMAC error");
}
/* the actual contents */
- buf_setpos(clearwritebuf, 0);
+ buf_setpos(clear_buf, 0);
if (hmac_process(&hmac,
- buf_getptr(clearwritebuf,
- clearwritebuf->len),
- clearwritebuf->len) != CRYPT_OK) {
+ buf_getptr(clear_buf, clear_len),
+ clear_len) != CRYPT_OK) {
dropbear_exit("HMAC error");
}
@@ -609,29 +579,29 @@ static void buf_compress(buffer * dest, buffer * src, unsigned int len) {
while (1) {
- ses.keys->trans_zstream->avail_in = endpos - src->pos;
- ses.keys->trans_zstream->next_in =
- buf_getptr(src, ses.keys->trans_zstream->avail_in);
+ ses.keys->trans.zstream->avail_in = endpos - src->pos;
+ ses.keys->trans.zstream->next_in =
+ buf_getptr(src, ses.keys->trans.zstream->avail_in);
- ses.keys->trans_zstream->avail_out = dest->size - dest->pos;
- ses.keys->trans_zstream->next_out =
- buf_getwriteptr(dest, ses.keys->trans_zstream->avail_out);
+ ses.keys->trans.zstream->avail_out = dest->size - dest->pos;
+ ses.keys->trans.zstream->next_out =
+ buf_getwriteptr(dest, ses.keys->trans.zstream->avail_out);
- result = deflate(ses.keys->trans_zstream, Z_SYNC_FLUSH);
+ result = deflate(ses.keys->trans.zstream, Z_SYNC_FLUSH);
- buf_setpos(src, endpos - ses.keys->trans_zstream->avail_in);
- buf_setlen(dest, dest->size - ses.keys->trans_zstream->avail_out);
+ buf_setpos(src, endpos - ses.keys->trans.zstream->avail_in);
+ buf_setlen(dest, dest->size - ses.keys->trans.zstream->avail_out);
buf_setpos(dest, dest->len);
if (result != Z_OK) {
dropbear_exit("zlib error");
}
- if (ses.keys->trans_zstream->avail_in == 0) {
+ if (ses.keys->trans.zstream->avail_in == 0) {
break;
}
- dropbear_assert(ses.keys->trans_zstream->avail_out == 0);
+ dropbear_assert(ses.keys->trans.zstream->avail_out == 0);
/* the buffer has been filled, we must extend. This only happens in
* unusual circumstances where the data grows in size after deflate(),
diff --git a/packet.h b/packet.h
index 8fadeb3..4645b14 100644
--- a/packet.h
+++ b/packet.h
@@ -44,6 +44,6 @@ typedef struct PacketType {
#define PACKET_PADDING_OFF 4
#define PACKET_PAYLOAD_OFF 5
-#define INIT_READBUF 200
+#define INIT_READBUF 128
#endif /* _PACKET_H_ */
diff --git a/session.h b/session.h
index 1106db4..5a4569e 100644
--- a/session.h
+++ b/session.h
@@ -60,42 +60,36 @@ void cli_session(int sock_in, int sock_out, char *remotehost);
void cli_session_cleanup();
void cleantext(unsigned char* dirtytext);
-struct key_context {
-
- const struct dropbear_cipher *recv_algo_crypt; /* NULL for none */
- const struct dropbear_cipher *trans_algo_crypt; /* NULL for none */
- const struct dropbear_cipher_mode *recv_crypt_mode;
- const struct dropbear_cipher_mode *trans_crypt_mode;
- const struct dropbear_hash *recv_algo_mac; /* NULL for none */
- const struct dropbear_hash *trans_algo_mac; /* NULL for none */
- char algo_kex;
- char algo_hostkey;
-
- char recv_algo_comp; /* compression */
- char trans_algo_comp;
- int allow_compress; /* whether compression has started (useful in
- zlib@openssh.com delayed compression case) */
+/* crypto parameters that are stored individually for transmit and receive */
+struct key_context_directional {
+ const struct dropbear_cipher *algo_crypt; /* NULL for none */
+ const struct dropbear_cipher_mode *crypt_mode;
+ const struct dropbear_hash *algo_mac; /* NULL for none */
+ int hash_index; /* lookup for libtomcrypt */
+ char algo_comp; /* compression */
#ifndef DISABLE_ZLIB
- z_streamp recv_zstream;
- z_streamp trans_zstream;
+ z_streamp zstream;
#endif
-
/* actual keys */
union {
symmetric_CBC cbc;
#ifdef DROPBEAR_ENABLE_CTR_MODE
symmetric_CTR ctr;
#endif
- } recv_cipher_state;
- union {
- symmetric_CBC cbc;
-#ifdef DROPBEAR_ENABLE_CTR_MODE
- symmetric_CTR ctr;
-#endif
- } trans_cipher_state;
- unsigned char recvmackey[MAX_MAC_KEY];
- unsigned char transmackey[MAX_MAC_KEY];
+ } cipher_state;
+ unsigned char mackey[MAX_MAC_KEY];
+};
+
+struct key_context {
+
+ struct key_context_directional recv;
+ struct key_context_directional trans;
+ char algo_kex;
+ char algo_hostkey;
+
+ int allow_compress; /* whether compression has started (useful in
+ zlib@openssh.com delayed compression case) */
};
struct packetlist;
@@ -128,8 +122,7 @@ struct sshsession {
throughout the code, as handlers fill out this
buffer with the packet to send. */
struct Queue writequeue; /* A queue of encrypted packets to send */
- buffer *readbuf; /* Encrypted */
- buffer *decryptreadbuf; /* Post-decryption */
+ buffer *readbuf; /* From the wire, decrypted in-place */
buffer *payload; /* Post-decompression, the actual SSH packet */
unsigned int transseq, recvseq; /* Sequence IDs */