Encrypt in-place, avoid an extra malloc

--HG--
extra : convert_revision : 981e3e4b44e6fdc8537775518e898a33e76a38db
This commit is contained in:
Matt Johnston 2009-03-01 14:38:25 +00:00
parent 4b37932ba1
commit 8e72bbaa9d

View File

@ -36,7 +36,7 @@
#include "channel.h" #include "channel.h"
static void read_packet_init(); static void read_packet_init();
static void writemac(buffer * outputbuffer, buffer * clearwritebuf); static void make_mac(buffer * clearwritebuf, unsigned char *output_mac);
static int checkmac(buffer* hashbuf, buffer* readbuf); static int checkmac(buffer* hashbuf, buffer* readbuf);
#define ZLIB_COMPRESS_INCR 20 /* this is 12 bytes + 0.1% of 8000 bytes */ #define ZLIB_COMPRESS_INCR 20 /* this is 12 bytes + 0.1% of 8000 bytes */
@ -449,11 +449,12 @@ void maybe_flush_reply_queue() {
void encrypt_packet() { void encrypt_packet() {
unsigned char padlen; unsigned char padlen;
unsigned char blocksize, macsize; unsigned char blocksize, mac_size;
buffer * writebuf; /* the packet which will go on the wire */ buffer * writebuf; /* the packet which will go on the wire. This is
buffer * clearwritebuf; /* unencrypted, possibly compressed */ encrypted in-place. */
unsigned char type; unsigned char type;
unsigned int len; unsigned int len, encrypt_buf_size;
unsigned char mac_bytes[MAX_MAC_LEN];
type = ses.writepayload->data[0]; type = ses.writepayload->data[0];
TRACE(("enter encrypt_packet()")) TRACE(("enter encrypt_packet()"))
@ -468,33 +469,35 @@ void encrypt_packet() {
} }
blocksize = ses.keys->trans_algo_crypt->blocksize; blocksize = ses.keys->trans_algo_crypt->blocksize;
macsize = ses.keys->trans_algo_mac->hashsize; mac_size = ses.keys->trans_algo_mac->hashsize;
/* Encrypted packet len is payload+5, then worst case is if we are 3 away /* 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 * from a blocksize multiple. In which case we need to pad to the
* multiple, then add another blocksize (or MIN_PACKET_LEN) */ * multiple, then add another blocksize (or MIN_PACKET_LEN) */
len = (ses.writepayload->len+4+1) + MIN_PACKET_LEN + 3; encrypt_buf_size = (ses.writepayload->len+4+1) + MIN_PACKET_LEN + 3;
/* add space for the MAC at the end */
encrypt_buf_size += mac_size;
#ifndef DISABLE_ZLIB #ifndef DISABLE_ZLIB
len += ZLIB_COMPRESS_INCR; /* bit of a kludge, but we can't know len*/ encrypt_buf_size += ZLIB_COMPRESS_INCR; /* bit of a kludge, but we can't know len*/
#endif #endif
clearwritebuf = buf_new(len); writebuf = buf_new(encrypt_buf_size);
buf_setlen(clearwritebuf, PACKET_PAYLOAD_OFF); buf_setlen(writebuf, PACKET_PAYLOAD_OFF);
buf_setpos(clearwritebuf, PACKET_PAYLOAD_OFF); buf_setpos(writebuf, PACKET_PAYLOAD_OFF);
buf_setpos(ses.writepayload, 0); buf_setpos(ses.writepayload, 0);
#ifndef DISABLE_ZLIB #ifndef DISABLE_ZLIB
/* compression */ /* compression */
if (is_compress_trans()) { if (is_compress_trans()) {
buf_compress(clearwritebuf, ses.writepayload, ses.writepayload->len); buf_compress(writebuf, ses.writepayload, ses.writepayload->len);
} else } else
#endif #endif
{ {
memcpy(buf_getwriteptr(clearwritebuf, ses.writepayload->len), memcpy(buf_getwriteptr(writebuf, ses.writepayload->len),
buf_getptr(ses.writepayload, ses.writepayload->len), buf_getptr(ses.writepayload, ses.writepayload->len),
ses.writepayload->len); ses.writepayload->len);
buf_incrwritepos(clearwritebuf, ses.writepayload->len); buf_incrwritepos(writebuf, ses.writepayload->len);
} }
/* finished with payload */ /* finished with payload */
@ -503,52 +506,45 @@ void encrypt_packet() {
/* length of padding - packet length must be a multiple of blocksize, /* length of padding - packet length must be a multiple of blocksize,
* with a minimum of 4 bytes of padding */ * with a minimum of 4 bytes of padding */
padlen = blocksize - (clearwritebuf->len) % blocksize; padlen = blocksize - (writebuf->len) % blocksize;
if (padlen < 4) { if (padlen < 4) {
padlen += blocksize; padlen += blocksize;
} }
/* check for min packet length */ /* check for min packet length */
if (clearwritebuf->len + padlen < MIN_PACKET_LEN) { if (writebuf->len + padlen < MIN_PACKET_LEN) {
padlen += blocksize; padlen += blocksize;
} }
buf_setpos(clearwritebuf, 0); buf_setpos(writebuf, 0);
/* packet length excluding the packetlength uint32 */ /* packet length excluding the packetlength uint32 */
buf_putint(clearwritebuf, clearwritebuf->len + padlen - 4); buf_putint(writebuf, writebuf->len + padlen - 4);
/* padding len */ /* padding len */
buf_putbyte(clearwritebuf, padlen); buf_putbyte(writebuf, padlen);
/* actual padding */ /* actual padding */
buf_setpos(clearwritebuf, clearwritebuf->len); buf_setpos(writebuf, writebuf->len);
buf_incrlen(clearwritebuf, padlen); buf_incrlen(writebuf, padlen);
genrandom(buf_getptr(clearwritebuf, padlen), padlen); genrandom(buf_getptr(writebuf, padlen), padlen);
/* do the actual encryption */ make_mac(writebuf, mac_bytes);
buf_setpos(clearwritebuf, 0);
/* create a new writebuffer, this is freed when it has been put on the
* wire by writepacket() */
writebuf = buf_new(clearwritebuf->len + macsize);
/* encrypt it */ /* do the actual encryption, in-place */
len = clearwritebuf->len; 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(clearwritebuf, len), buf_getptr(writebuf, len),
buf_getwriteptr(writebuf, len), buf_getwriteptr(writebuf, len),
len, len,
&ses.keys->trans_cipher_state) != CRYPT_OK) { &ses.keys->trans_cipher_state) != CRYPT_OK) {
dropbear_exit("error encrypting"); dropbear_exit("error encrypting");
} }
buf_incrpos(clearwritebuf, len); buf_incrpos(writebuf, len);
buf_incrwritepos(writebuf, len);
/* now add a hmac and we're done */ /* stick the MAC on it */
writemac(writebuf, clearwritebuf); buf_putbytes(writebuf, mac_bytes, mac_size);
/* clearwritebuf is finished with */ /* enqueue the packet for sending. It will get freed after transmission. */
buf_free(clearwritebuf);
clearwritebuf = NULL;
/* enqueue the packet for sending */
buf_setpos(writebuf, 0); buf_setpos(writebuf, 0);
enqueue(&ses.writequeue, (void*)writebuf); enqueue(&ses.writequeue, (void*)writebuf);
@ -561,18 +557,15 @@ void encrypt_packet() {
/* Create the packet mac, and append H(seqno|clearbuf) to the output */ /* Create the packet mac, and append H(seqno|clearbuf) to the output */
static void writemac(buffer * outputbuffer, buffer * clearwritebuf) { /* output_mac must have ses.keys->trans_algo_mac->hashsize bytes. */
static void make_mac(buffer * clearwritebuf, unsigned char *output_mac) {
unsigned int macsize;
unsigned char seqbuf[4]; unsigned char seqbuf[4];
unsigned char tempbuf[MAX_MAC_LEN];
unsigned long bufsize; unsigned long bufsize;
hmac_state hmac; hmac_state hmac;
TRACE(("enter writemac")) TRACE(("enter writemac"))
macsize = ses.keys->trans_algo_mac->hashsize; if (ses.keys->trans_algo_mac->hashsize > 0) {
if (macsize > 0) {
/* calculate the mac */ /* calculate the mac */
if (hmac_init(&hmac, if (hmac_init(&hmac,
find_hash(ses.keys->trans_algo_mac->hashdesc->name), find_hash(ses.keys->trans_algo_mac->hashdesc->name),
@ -596,12 +589,10 @@ static void writemac(buffer * outputbuffer, buffer * clearwritebuf) {
dropbear_exit("HMAC error"); dropbear_exit("HMAC error");
} }
bufsize = sizeof(tempbuf); bufsize = MAX_MAC_LEN;
if (hmac_done(&hmac, tempbuf, &bufsize) if (hmac_done(&hmac, output_mac, &bufsize) != CRYPT_OK) {
!= CRYPT_OK) {
dropbear_exit("HMAC error"); dropbear_exit("HMAC error");
} }
buf_putbytes(outputbuffer, tempbuf, macsize);
} }
TRACE(("leave writemac")) TRACE(("leave writemac"))
} }