1
0
mirror of https://github.com/clearml/dropbear synced 2025-04-26 00:49:39 +00:00

- 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

--HG--
extra : convert_revision : 043bc598c76ed43625987e6937e32238f7ed6240
This commit is contained in:
Matt Johnston 2009-03-01 16:15:57 +00:00
parent 8e72bbaa9d
commit ff763e4005
5 changed files with 175 additions and 211 deletions

View File

@ -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 */

View File

@ -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 */

198
packet.c
View File

@ -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(),

View File

@ -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_ */

View File

@ -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 */