changeset 502:43bbe17d6ba0

- Add Counter Mode support
author Matt Johnston <matt@ucc.asn.au>
date Mon, 29 Sep 2008 13:53:31 +0000
parents d58c478bd399
children 0cdbc95bb3d2
files algo.h common-algo.c common-kex.c common-session.c libtomcrypt/src/headers/tomcrypt_custom.h options.h packet.c session.h svr-authpubkeyoptions.c svr-chansession.c sysoptions.h
diffstat 11 files changed, 195 insertions(+), 116 deletions(-) [+]
line wrap: on
line diff
--- a/algo.h	Mon Sep 29 02:23:04 2008 +0000
+++ b/algo.h	Mon Sep 29 13:53:31 2008 +0000
@@ -29,13 +29,18 @@
 #include "includes.h"
 #include "buffer.h"
 
+#define DROPBEAR_MODE_UNUSED 0
+#define DROPBEAR_MODE_CBC 1
+#define DROPBEAR_MODE_CTR 2
+
 struct Algo_Type {
 
 	unsigned char *name; /* identifying name */
 	char val; /* a value for this cipher, or -1 for invalid */
-	void *data; /* algorithm specific data */
-	unsigned usable : 1; /* whether we can use this algorithm */
-
+	const void *data; /* algorithm specific data */
+	char usable; /* whether we can use this algorithm */
+	const void *mode; /* the mode, currently only used for ciphers,
+						 points to a 'struct dropbear_cipher_mode' */
 };
 
 typedef struct Algo_Type algo_type;
@@ -48,6 +53,7 @@
 extern algo_type sshcompress[];
 
 extern const struct dropbear_cipher dropbear_nocipher;
+extern const struct dropbear_cipher_mode dropbear_mode_none;
 extern const struct dropbear_hash dropbear_nohash;
 
 struct dropbear_cipher {
@@ -56,6 +62,16 @@
 	unsigned char blocksize;
 };
 
+struct dropbear_cipher_mode {
+	int (*start)(int cipher, const unsigned char *IV, 
+			const unsigned char *key, 
+			int keylen, int num_rounds, void *cipher_state);
+	int (*encrypt)(const unsigned char *pt, unsigned char *ct, 
+			unsigned long len, void *cipher_state);
+	int (*decrypt)(const unsigned char *ct, unsigned char *pt, 
+			unsigned long len, void *cipher_state);
+};
+
 struct dropbear_hash {
 	const struct ltc_hash_descriptor *hashdesc;
 	unsigned long keysize;
--- a/common-algo.c	Mon Sep 29 02:23:04 2008 +0000
+++ b/common-algo.c	Mon Sep 29 13:53:31 2008 +0000
@@ -29,32 +29,44 @@
 /* This file (algo.c) organises the ciphers which can be used, and is used to
  * decide which ciphers/hashes/compression/signing to use during key exchange*/
 
+static int void_cipher(const unsigned char* in, unsigned char* out,
+		unsigned long len, void *cipher_state) {
+	memcpy(out, in, len);
+	return CRYPT_OK;
+}
+
+static int void_start(int cipher, const unsigned char *IV, 
+			const unsigned char *key, 
+			int keylen, int num_rounds, void *cipher_state) {
+	return CRYPT_OK;
+}
+
 /* Mappings for ciphers, parameters are
    {&cipher_desc, keysize, blocksize} */
 /* NOTE: if keysize > 2*SHA1_HASH_SIZE, code such as hashkeys()
    needs revisiting */
 
-#ifdef DROPBEAR_AES256_CBC
+#ifdef DROPBEAR_AES256
 static const struct dropbear_cipher dropbear_aes256 = 
 	{&aes_desc, 32, 16};
 #endif
-#ifdef DROPBEAR_AES128_CBC
+#ifdef DROPBEAR_AES128
 static const struct dropbear_cipher dropbear_aes128 = 
 	{&aes_desc, 16, 16};
 #endif
-#ifdef DROPBEAR_BLOWFISH_CBC
+#ifdef DROPBEAR_BLOWFISH
 static const struct dropbear_cipher dropbear_blowfish = 
 	{&blowfish_desc, 16, 8};
 #endif
-#ifdef DROPBEAR_TWOFISH256_CBC
+#ifdef DROPBEAR_TWOFISH256
 static const struct dropbear_cipher dropbear_twofish256 = 
 	{&twofish_desc, 32, 16};
 #endif
-#ifdef DROPBEAR_TWOFISH128_CBC
+#ifdef DROPBEAR_TWOFISH128
 static const struct dropbear_cipher dropbear_twofish128 = 
 	{&twofish_desc, 16, 16};
 #endif
-#ifdef DROPBEAR_3DES_CBC
+#ifdef DROPBEAR_3DES
 static const struct dropbear_cipher dropbear_3des = 
 	{&des3_desc, 24, 8};
 #endif
@@ -63,6 +75,24 @@
 const struct dropbear_cipher dropbear_nocipher =
 	{NULL, 16, 8}; 
 
+/* A few void* s are required to silence warnings
+ * about the symmetric_CBC vs symmetric_CTR cipher_state pointer */
+const struct dropbear_cipher_mode dropbear_mode_cbc =
+	{(void*)cbc_start, (void*)cbc_encrypt, (void*)cbc_decrypt};
+const struct dropbear_cipher_mode dropbear_mode_none =
+	{void_start, void_cipher, void_cipher};
+#ifdef DROPBEAR_ENABLE_CTR_MODE
+/* a wrapper to make ctr_start and cbc_start look the same */
+static int dropbear_big_endian_ctr_start(int cipher, 
+		const unsigned char *IV, 
+		const unsigned char *key, int keylen, 
+		int num_rounds, symmetric_CTR *ctr) {
+	return ctr_start(cipher, IV, key, keylen, num_rounds, CTR_COUNTER_BIG_ENDIAN, ctr);
+}
+const struct dropbear_cipher_mode dropbear_mode_ctr =
+	{(void*)dropbear_big_endian_ctr_start, (void*)ctr_encrypt, (void*)ctr_decrypt};
+#endif
+
 /* Mapping of ssh hashes to libtomcrypt hashes, including keysize etc.
    {&hash_desc, keysize, hashsize} */
 
@@ -83,66 +113,90 @@
 	{NULL, 16, 0}; /* used initially */
 	
 
-/* The following map ssh names to internal values */
+/* The following map ssh names to internal values.
+ * The ordering here is important for the client - the first mode
+ * that is also supported by the server will get used. */
 
 algo_type sshciphers[] = {
-#ifdef DROPBEAR_AES128_CBC
-	{"aes128-cbc", 0, (void*)&dropbear_aes128, 1},
+#ifdef DROPBEAR_ENABLE_CTR_MODE
+#ifdef DROPBEAR_AES128
+	{"aes128-ctr", 0, &dropbear_aes128, 1, &dropbear_mode_ctr},
+#endif
+#ifdef DROPBEAR_3DES
+	{"3des-ctr", 0, &dropbear_3des, 1, &dropbear_mode_ctr},
 #endif
-#ifdef DROPBEAR_3DES_CBC
-	{"3des-cbc", 0, (void*)&dropbear_3des, 1},
+#ifdef DROPBEAR_AES256
+	{"aes256-ctr", 0, &dropbear_aes256, 1, &dropbear_mode_ctr},
+#endif
+#ifdef DROPBEAR_TWOFISH256
+	{"twofish256-ctr", 0, &dropbear_twofish256, 1, &dropbear_mode_ctr},
 #endif
-#ifdef DROPBEAR_AES256_CBC
-	{"aes256-cbc", 0, (void*)&dropbear_aes256, 1},
+#ifdef DROPBEAR_TWOFISH128
+	{"twofish128-ctr", 0, &dropbear_twofish128, 1, &dropbear_mode_ctr},
+#endif
+#ifdef DROPBEAR_BLOWFISH
+	{"blowfish-ctr", 0, &dropbear_blowfish, 1, &dropbear_mode_ctr},
 #endif
-#ifdef DROPBEAR_TWOFISH256_CBC
-	{"twofish256-cbc", 0, (void*)&dropbear_twofish256, 1},
-	{"twofish-cbc", 0, (void*)&dropbear_twofish256, 1},
+#endif /* DROPBEAR_ENABLE_CTR_MODE */
+
+/* CBC modes are always enabled */
+#ifdef DROPBEAR_AES128
+	{"aes128-cbc", 0, &dropbear_aes128, 1, &dropbear_mode_cbc},
+#endif
+#ifdef DROPBEAR_3DES
+	{"3des-cbc", 0, &dropbear_3des, 1, &dropbear_mode_cbc},
+#endif
+#ifdef DROPBEAR_AES256
+	{"aes256-cbc", 0, &dropbear_aes256, 1, &dropbear_mode_cbc},
 #endif
-#ifdef DROPBEAR_TWOFISH128_CBC
-	{"twofish128-cbc", 0, (void*)&dropbear_twofish128, 1},
+#ifdef DROPBEAR_TWOFISH256
+	{"twofish256-cbc", 0, &dropbear_twofish256, 1, &dropbear_mode_cbc},
+	{"twofish-cbc", 0, &dropbear_twofish256, 1, &dropbear_mode_cbc},
 #endif
-#ifdef DROPBEAR_BLOWFISH_CBC
-	{"blowfish-cbc", 0, (void*)&dropbear_blowfish, 1},
+#ifdef DROPBEAR_TWOFISH128
+	{"twofish128-cbc", 0, &dropbear_twofish128, 1, &dropbear_mode_cbc},
 #endif
-	{NULL, 0, NULL, 0}
+#ifdef DROPBEAR_BLOWFISH
+	{"blowfish-cbc", 0, &dropbear_blowfish, 1, &dropbear_mode_cbc},
+#endif
+	{NULL, 0, NULL, 0, NULL}
 };
 
 algo_type sshhashes[] = {
 #ifdef DROPBEAR_SHA1_96_HMAC
-	{"hmac-sha1-96", 0, (void*)&dropbear_sha1_96, 1},
+	{"hmac-sha1-96", 0, &dropbear_sha1_96, 1, NULL},
 #endif
 #ifdef DROPBEAR_SHA1_HMAC
-	{"hmac-sha1", 0, (void*)&dropbear_sha1, 1},
+	{"hmac-sha1", 0, &dropbear_sha1, 1, NULL},
 #endif
 #ifdef DROPBEAR_MD5_HMAC
-	{"hmac-md5", 0, (void*)&dropbear_md5, 1},
+	{"hmac-md5", 0, &dropbear_md5, 1, NULL},
 #endif
-	{NULL, 0, NULL, 0}
+	{NULL, 0, NULL, 0, NULL}
 };
 
 algo_type sshcompress[] = {
 #ifndef DISABLE_ZLIB
-	{"zlib", DROPBEAR_COMP_ZLIB, NULL, 1},
-	{"[email protected]", DROPBEAR_COMP_ZLIB_DELAY, NULL, 1},
+	{"zlib", DROPBEAR_COMP_ZLIB, NULL, 1, NULL},
+	{"[email protected]nssh.com", DROPBEAR_COMP_ZLIB_DELAY, NULL, 1, NULL},
 #endif
-	{"none", DROPBEAR_COMP_NONE, NULL, 1},
-	{NULL, 0, NULL, 0}
+	{"none", DROPBEAR_COMP_NONE, NULL, 1, NULL},
+	{NULL, 0, NULL, 0, NULL}
 };
 
 algo_type sshhostkey[] = {
 #ifdef DROPBEAR_RSA
-	{"ssh-rsa", DROPBEAR_SIGNKEY_RSA, NULL, 1},
+	{"ssh-rsa", DROPBEAR_SIGNKEY_RSA, NULL, 1, NULL},
 #endif
 #ifdef DROPBEAR_DSS
-	{"ssh-dss", DROPBEAR_SIGNKEY_DSS, NULL, 1},
+	{"ssh-dss", DROPBEAR_SIGNKEY_DSS, NULL, 1, NULL},
 #endif
-	{NULL, 0, NULL, 0}
+	{NULL, 0, NULL, 0, NULL}
 };
 
 algo_type sshkex[] = {
-	{"diffie-hellman-group1-sha1", DROPBEAR_KEX_DH_GROUP1, NULL, 1},
-	{NULL, 0, NULL, 0}
+	{"diffie-hellman-group1-sha1", DROPBEAR_KEX_DH_GROUP1, NULL, 1, NULL},
+	{NULL, 0, NULL, 0, NULL}
 };
 
 
@@ -151,16 +205,16 @@
 void crypto_init() {
 
 	const struct ltc_cipher_descriptor *regciphers[] = {
-#ifdef DROPBEAR_AES_CBC
+#ifdef DROPBEAR_AES
 		&aes_desc,
 #endif
-#ifdef DROPBEAR_BLOWFISH_CBC
+#ifdef DROPBEAR_BLOWFISH
 		&blowfish_desc,
 #endif
-#ifdef DROPBEAR_TWOFISH_CBC
+#ifdef DROPBEAR_TWOFISH
 		&twofish_desc,
 #endif
-#ifdef DROPBEAR_3DES_CBC
+#ifdef DROPBEAR_3DES
 		&des3_desc,
 #endif
 		NULL
@@ -216,7 +270,7 @@
 	unsigned int donefirst = 0;
 	buffer *algolist = NULL;
 
-	algolist = buf_new(100);
+	algolist = buf_new(160);
 	for (i = 0; localalgos[i].name != NULL; i++) {
 		if (localalgos[i].usable) {
 			if (donefirst)
--- a/common-kex.c	Mon Sep 29 02:23:04 2008 +0000
+++ b/common-kex.c	Mon Sep 29 13:53:31 2008 +0000
@@ -295,19 +295,20 @@
 	recv_cipher = find_cipher(ses.newkeys->recv_algo_crypt->cipherdesc->name);
 	if (recv_cipher < 0)
 	    dropbear_exit("crypto error");
-		
-	if (cbc_start(recv_cipher, recv_IV, recv_key, 
+	if (ses.newkeys->recv_crypt_mode->start(recv_cipher, 
+			recv_IV, recv_key, 
 			ses.newkeys->recv_algo_crypt->keysize, 0, 
-			&ses.newkeys->recv_symmetric_struct) != CRYPT_OK) {
+			&ses.newkeys->recv_cipher_state) != CRYPT_OK) {
 		dropbear_exit("crypto error");
 	}
+
 	trans_cipher = find_cipher(ses.newkeys->trans_algo_crypt->cipherdesc->name);
 	if (trans_cipher < 0)
 	    dropbear_exit("crypto error");
-		
-	if (cbc_start(trans_cipher, trans_IV, trans_key, 
+	if (ses.newkeys->trans_crypt_mode->start(trans_cipher, 
+			trans_IV, trans_key, 
 			ses.newkeys->trans_algo_crypt->keysize, 0, 
-			&ses.newkeys->trans_symmetric_struct) != CRYPT_OK) {
+			&ses.newkeys->trans_cipher_state) != CRYPT_OK) {
 		dropbear_exit("crypto error");
 	}
 	
@@ -701,6 +702,10 @@
 			(struct dropbear_cipher*)s2c_cipher_algo->data;
 		ses.newkeys->trans_algo_crypt = 
 			(struct dropbear_cipher*)c2s_cipher_algo->data;
+		ses.newkeys->recv_crypt_mode = 
+			(struct dropbear_cipher_mode*)s2c_cipher_algo->mode;
+		ses.newkeys->trans_crypt_mode =
+			(struct dropbear_cipher_mode*)c2s_cipher_algo->mode;
 		ses.newkeys->recv_algo_mac = 
 			(struct dropbear_hash*)s2c_hash_algo->data;
 		ses.newkeys->trans_algo_mac = 
@@ -713,6 +718,10 @@
 			(struct dropbear_cipher*)c2s_cipher_algo->data;
 		ses.newkeys->trans_algo_crypt = 
 			(struct dropbear_cipher*)s2c_cipher_algo->data;
+		ses.newkeys->recv_crypt_mode =
+			(struct dropbear_cipher_mode*)c2s_cipher_algo->mode;
+		ses.newkeys->trans_crypt_mode =
+			(struct dropbear_cipher_mode*)s2c_cipher_algo->mode;
 		ses.newkeys->recv_algo_mac = 
 			(struct dropbear_hash*)c2s_hash_algo->data;
 		ses.newkeys->trans_algo_mac = 
--- a/common-session.c	Mon Sep 29 02:23:04 2008 +0000
+++ b/common-session.c	Mon Sep 29 13:53:31 2008 +0000
@@ -96,6 +96,8 @@
 	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_mac = &dropbear_nohash;
 	ses.keys->trans_algo_mac = &dropbear_nohash;
--- a/libtomcrypt/src/headers/tomcrypt_custom.h	Mon Sep 29 02:23:04 2008 +0000
+++ b/libtomcrypt/src/headers/tomcrypt_custom.h	Mon Sep 29 13:53:31 2008 +0000
@@ -90,15 +90,15 @@
 /* #define LTC_NO_BSWAP */
 
 
-#ifdef DROPBEAR_BLOWFISH_CBC
+#ifdef DROPBEAR_BLOWFISH
 #define BLOWFISH
 #endif
 
-#ifdef DROPBEAR_AES_CBC
+#ifdef DROPBEAR_AES
 #define RIJNDAEL
 #endif
 
-#ifdef DROPBEAR_TWOFISH_CBC
+#ifdef DROPBEAR_TWOFISH
 #define TWOFISH
 
 /* enabling just TWOFISH_SMALL will make the binary ~1kB smaller, turning on
@@ -108,12 +108,16 @@
 /*#define TWOFISH_TABLES*/
 #endif
 
-#ifdef DROPBEAR_3DES_CBC
+#ifdef DROPBEAR_3DES
 #define DES
 #endif
 
 #define LTC_CBC_MODE
 
+#ifdef DROPBEAR_ENABLE_CTR_MODE
+#define LTC_CTR_MODE
+#endif
+
 #if defined(DROPBEAR_DSS) && defined(DSS_PROTOK)
 #define SHA512
 #endif
--- a/options.h	Mon Sep 29 02:23:04 2008 +0000
+++ b/options.h	Mon Sep 29 13:53:31 2008 +0000
@@ -75,18 +75,22 @@
 
 
 /* Encryption - at least one required.
- * RFC Draft requires 3DES and recommends AES128 for interoperability.
+ * Protocol RFC requires 3DES and recommends AES128 for interoperability.
  * Including multiple keysize variants the same cipher 
  * (eg AES256 as well as AES128) will result in a minimal size increase.*/
-#define DROPBEAR_AES128_CBC
-#define DROPBEAR_3DES_CBC
-#define DROPBEAR_AES256_CBC
-#define DROPBEAR_BLOWFISH_CBC
-#define DROPBEAR_TWOFISH256_CBC
-#define DROPBEAR_TWOFISH128_CBC
+#define DROPBEAR_AES128
+#define DROPBEAR_3DES
+#define DROPBEAR_AES256
+#define DROPBEAR_BLOWFISH
+#define DROPBEAR_TWOFISH256
+#define DROPBEAR_TWOFISH128
+
+/* Enable "Counter Mode" for ciphers. This is more secure than normal
+ * CBC mode against certain attacks. TODO how much size does it add? */
+#define DROPBEAR_ENABLE_CTR_MODE
 
 /* Message Integrity - at least one required.
- * RFC Draft requires sha1 and recommends sha1-96.
+ * Protocol RFC requires sha1 and recommends sha1-96.
  * sha1-96 may be of use for slow links, as it has a smaller overhead.
  *
  * Note: there's no point disabling sha1 to save space, since it's used
@@ -142,7 +146,7 @@
 
 #define ENABLE_SVR_PASSWORD_AUTH
 /* PAM requires ./configure --enable-pam */
-/* #define ENABLE_SVR_PAM_AUTH */
+/*#define ENABLE_SVR_PAM_AUTH*/
 #define ENABLE_SVR_PUBKEY_AUTH
 
 /* Wether to ake public key options in authorized_keys file into account */
--- a/packet.c	Mon Sep 29 02:23:04 2008 +0000
+++ b/packet.c	Mon Sep 29 13:53:31 2008 +0000
@@ -194,19 +194,11 @@
 	/* 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_algo_crypt->cipherdesc == NULL) {
-		/* copy it */
-		memcpy(buf_getwriteptr(ses.decryptreadbuf, blocksize),
-				buf_getptr(ses.readbuf, blocksize),
-				blocksize);
-	} else {
-		/* decrypt it */
-		if (cbc_decrypt(buf_getptr(ses.readbuf, blocksize), 
-					buf_getwriteptr(ses.decryptreadbuf,blocksize),
-					blocksize,
-					&ses.keys->recv_symmetric_struct) != CRYPT_OK) {
-			dropbear_exit("error decrypting");
-		}
+	if (ses.keys->recv_crypt_mode->decrypt(buf_getptr(ses.readbuf, blocksize), 
+				buf_getwriteptr(ses.decryptreadbuf,blocksize),
+				blocksize,
+				&ses.keys->recv_cipher_state) != CRYPT_OK) {
+		dropbear_exit("error decrypting");
 	}
 	buf_setlen(ses.decryptreadbuf, blocksize);
 	len = buf_getint(ses.decryptreadbuf) + 4 + macsize;
@@ -246,24 +238,17 @@
 	buf_setlen(ses.decryptreadbuf, ses.decryptreadbuf->size);
 	buf_setpos(ses.decryptreadbuf, blocksize);
 
-	/* decrypt if encryption is set, memcpy otherwise */
-	if (ses.keys->recv_algo_crypt->cipherdesc == NULL) {
-		/* copy it */
-		len = ses.readbuf->len - macsize - blocksize;
-		memcpy(buf_getwriteptr(ses.decryptreadbuf, len),
-				buf_getptr(ses.readbuf, len), len);
-	} else {
-		/* decrypt */
-		while (ses.readbuf->pos < ses.readbuf->len - macsize) {
-			if (cbc_decrypt(buf_getptr(ses.readbuf, blocksize), 
-						buf_getwriteptr(ses.decryptreadbuf, blocksize),
-						blocksize,
-						&ses.keys->recv_symmetric_struct) != CRYPT_OK) {
-				dropbear_exit("error decrypting");
-			}
-			buf_incrpos(ses.readbuf, blocksize);
-			buf_incrwritepos(ses.decryptreadbuf, blocksize);
+	/* decrypt it */
+	while (ses.readbuf->pos < ses.readbuf->len - macsize) {
+		if (ses.keys->recv_crypt_mode->decrypt(
+					buf_getptr(ses.readbuf, blocksize), 
+					buf_getwriteptr(ses.decryptreadbuf, blocksize),
+					blocksize,
+					&ses.keys->recv_cipher_state) != CRYPT_OK) {
+			dropbear_exit("error decrypting");
 		}
+		buf_incrpos(ses.readbuf, blocksize);
+		buf_incrwritepos(ses.decryptreadbuf, blocksize);
 	}
 
 	/* check the hmac */
@@ -544,24 +529,17 @@
 	 * wire by writepacket() */
 	writebuf = buf_new(clearwritebuf->len + macsize);
 
-	if (ses.keys->trans_algo_crypt->cipherdesc == NULL) {
-		/* copy it */
-		memcpy(buf_getwriteptr(writebuf, clearwritebuf->len),
-				buf_getptr(clearwritebuf, clearwritebuf->len),
-				clearwritebuf->len);
-		buf_incrwritepos(writebuf, clearwritebuf->len);
-	} else {
-		/* encrypt it */
-		while (clearwritebuf->pos < clearwritebuf->len) {
-			if (cbc_encrypt(buf_getptr(clearwritebuf, blocksize),
-						buf_getwriteptr(writebuf, blocksize),
-						blocksize,
-						&ses.keys->trans_symmetric_struct) != CRYPT_OK) {
-				dropbear_exit("error encrypting");
-			}
-			buf_incrpos(clearwritebuf, blocksize);
-			buf_incrwritepos(writebuf, blocksize);
+	/* encrypt it */
+	while (clearwritebuf->pos < clearwritebuf->len) {
+		if (ses.keys->trans_crypt_mode->encrypt(
+					buf_getptr(clearwritebuf, blocksize),
+					buf_getwriteptr(writebuf, blocksize),
+					blocksize,
+					&ses.keys->trans_cipher_state) != CRYPT_OK) {
+			dropbear_exit("error encrypting");
 		}
+		buf_incrpos(clearwritebuf, blocksize);
+		buf_incrwritepos(writebuf, blocksize);
 	}
 
 	/* now add a hmac and we're done */
--- a/session.h	Mon Sep 29 02:23:04 2008 +0000
+++ b/session.h	Mon Sep 29 13:53:31 2008 +0000
@@ -64,6 +64,8 @@
 
 	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;
@@ -79,8 +81,18 @@
 #endif
 
 	/* actual keys */
-	symmetric_CBC recv_symmetric_struct;
-	symmetric_CBC trans_symmetric_struct;
+	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];
 
--- a/svr-authpubkeyoptions.c	Mon Sep 29 02:23:04 2008 +0000
+++ b/svr-authpubkeyoptions.c	Mon Sep 29 13:53:31 2008 +0000
@@ -105,7 +105,7 @@
 /* helper for svr_add_pubkey_options. returns DROPBEAR_SUCCESS if the option is matched,
    and increments the options_buf */
 static int match_option(buffer *options_buf, const char *opt_name) {
-	const int len = strlen(opt_name);
+	const unsigned int len = strlen(opt_name);
 	if (options_buf->len - options_buf->pos < len) {
 		return DROPBEAR_FAILURE;
 	}
--- a/svr-chansession.c	Mon Sep 29 02:23:04 2008 +0000
+++ b/svr-chansession.c	Mon Sep 29 13:53:31 2008 +0000
@@ -663,11 +663,11 @@
 	addchildpid(chansess, chansess->pid);
 
 	if (svr_ses.lastexit.exitpid != -1) {
+		unsigned int i;
 		TRACE(("parent side: lastexitpid is %d", svr_ses.lastexit.exitpid))
 		/* The child probably exited and the signal handler triggered
 		 * possibly before we got around to adding the childpid. So we fill
 		 * out its data manually */
-		int i;
 		for (i = 0; i < svr_ses.childpidsize; i++) {
 			if (svr_ses.childpids[i].pid == svr_ses.lastexit.exitpid) {
 				TRACE(("found match for lastexitpid"))
--- a/sysoptions.h	Mon Sep 29 02:23:04 2008 +0000
+++ b/sysoptions.h	Mon Sep 29 13:53:31 2008 +0000
@@ -134,12 +134,12 @@
 												accept for keyb-interactive
 												auth */
 
-#if defined(DROPBEAR_AES256_CBC) || defined(DROPBEAR_AES128_CBC)
-#define DROPBEAR_AES_CBC
+#if defined(DROPBEAR_AES256) || defined(DROPBEAR_AES128)
+#define DROPBEAR_AES
 #endif
 
-#if defined(DROPBEAR_TWOFISH256_CBC) || defined(DROPBEAR_TWOFISH128_CBC)
-#define DROPBEAR_TWOFISH_CBC
+#if defined(DROPBEAR_TWOFISH256) || defined(DROPBEAR_TWOFISH128)
+#define DROPBEAR_TWOFISH
 #endif
 
 #ifndef ENABLE_X11FWD