changeset 710:91dd8328a3ff

Merge "none" cipher/MAC branch. Also adds sha256 and sha512
author Matt Johnston <matt@ucc.asn.au>
date Wed, 20 Mar 2013 22:41:07 +0800
parents abd99ecd7ec2 (current diff) 983a817f8e41 (diff)
children f4232b65b316
files options.h sysoptions.h
diffstat 8 files changed, 159 insertions(+), 38 deletions(-) [+]
line wrap: on
line diff
--- a/cli-auth.c	Wed Mar 20 22:31:07 2013 +0800
+++ b/cli-auth.c	Wed Mar 20 22:41:07 2013 +0800
@@ -257,7 +257,9 @@
 #endif
 
 #ifdef ENABLE_CLI_INTERACT_AUTH
-	if (!finished && ses.authstate.authtypes & AUTH_TYPE_INTERACT) {
+	if (ses.keys->trans.algo_crypt->cipherdesc == NULL) {
+		fprintf(stderr, "Sorry, I won't let you use interactive auth unencrypted.\n");
+	} else if (!finished && ses.authstate.authtypes & AUTH_TYPE_INTERACT) {
 		if (cli_ses.auth_interact_failed) {
 			finished = 0;
 		} else {
@@ -269,7 +271,9 @@
 #endif
 
 #ifdef ENABLE_CLI_PASSWORD_AUTH
-	if (!finished && ses.authstate.authtypes & AUTH_TYPE_PASSWORD) {
+	if (ses.keys->trans.algo_crypt->cipherdesc == NULL) {
+		fprintf(stderr, "Sorry, I won't let you use password auth unencrypted.\n");
+	} else if (!finished && ses.authstate.authtypes & AUTH_TYPE_PASSWORD) {
 		cli_auth_password();
 		finished = 1;
 		cli_ses.lastauthtype = AUTH_TYPE_PASSWORD;
--- a/cli-session.c	Wed Mar 20 22:31:07 2013 +0800
+++ b/cli-session.c	Wed Mar 20 22:41:07 2013 +0800
@@ -133,6 +133,13 @@
 	cli_ses.lastprivkey = NULL;
 	cli_ses.lastauthtype = 0;
 
+#ifdef DROPBEAR_NONE_CIPHER
+	cli_ses.cipher_none_after_auth = get_algo_usable(sshciphers, "none");
+	set_algo_usable(sshciphers, "none", 0);
+#else
+	cli_ses.cipher_none_after_auth = 0;
+#endif
+
 	/* For printing "remote host closed" for the user */
 	ses.remoteclosed = cli_remoteclosed;
 	ses.buf_match_algo = cli_buf_match_algo;
@@ -207,6 +214,14 @@
 
 		case USERAUTH_SUCCESS_RCVD:
 
+#ifdef DROPBEAR_NONE_CIPHER
+			if (cli_ses.cipher_none_after_auth)
+			{
+				set_algo_usable(sshciphers, "none", 1);
+				send_msg_kexinit();
+			}
+#endif
+
 			if (cli_opts.backgrounded) {
 				int devnull;
 				/* keeping stdin open steals input from the terminal and
--- a/common-algo.c	Wed Mar 20 22:31:07 2013 +0800
+++ b/common-algo.c	Wed Mar 20 22:41:07 2013 +0800
@@ -106,6 +106,14 @@
 static const struct dropbear_hash dropbear_sha1_96 = 
 	{&sha1_desc, 20, 12};
 #endif
+#ifdef DROPBEAR_SHA2_256_HMAC
+static const struct dropbear_hash dropbear_sha2_256 = 
+	{&sha256_desc, 32, 32};
+#endif
+#ifdef DROPBEAR_SHA2_512_HMAC
+static const struct dropbear_hash dropbear_sha2_512 =
+	{&sha512_desc, 64, 64};
+#endif
 #ifdef DROPBEAR_MD5_HMAC
 static const struct dropbear_hash dropbear_md5 = 
 	{&md5_desc, 16, 16};
@@ -152,10 +160,19 @@
 #ifdef DROPBEAR_BLOWFISH
 	{"blowfish-cbc", 0, &dropbear_blowfish, 1, &dropbear_mode_cbc},
 #endif
+#ifdef DROPBEAR_NONE_CIPHER
+	{"none", 0, (void*)&dropbear_nocipher, 1, &dropbear_mode_none},
+#endif
 	{NULL, 0, NULL, 0, NULL}
 };
 
 algo_type sshhashes[] = {
+#ifdef DROPBEAR_SHA2_256_HMAC
+//	{"hmac-sha2-256", 0, &dropbear_sha2_256, 1, NULL},
+#endif
+#ifdef DROPBEAR_SHA2_512_HMAC
+//	{"hmac-sha2-512", 0, &dropbear_sha2_512, 1, NULL},
+#endif
 #ifdef DROPBEAR_SHA1_96_HMAC
 	{"hmac-sha1-96", 0, &dropbear_sha1_96, 1, NULL},
 #endif
@@ -163,7 +180,10 @@
 	{"hmac-sha1", 0, &dropbear_sha1, 1, NULL},
 #endif
 #ifdef DROPBEAR_MD5_HMAC
-	{"hmac-md5", 0, &dropbear_md5, 1, NULL},
+	{"hmac-md5", 0, (void*)&dropbear_md5, 1, NULL},
+#endif
+#ifdef DROPBEAR_NONE_INTEGRITY
+	{"none", 0, (void*)&dropbear_nohash, 1, NULL},
 #endif
 	{NULL, 0, NULL, 0, NULL}
 };
@@ -281,6 +301,38 @@
 	buf_free(algolist);
 }
 
+#ifdef DROPBEAR_NONE_CIPHER
+
+void
+set_algo_usable(algo_type algos[], const char * algo_name, int usable)
+{
+	algo_type *a;
+	for (a = algos; a->name != NULL; a++)
+	{
+		if (strcmp(a->name, algo_name) == 0)
+		{
+			a->usable = usable;
+			return;
+		}
+	}
+}
+
+int
+get_algo_usable(algo_type algos[], const char * algo_name)
+{
+	algo_type *a;
+	for (a = algos; a->name != NULL; a++)
+	{
+		if (strcmp(a->name, algo_name) == 0)
+		{
+			return a->usable;
+		}
+	}
+	return 0;
+}
+
+#endif // DROPBEAR_NONE_CIPHER
+
 #ifdef ENABLE_USER_ALGO_LIST
 
 char *
@@ -347,7 +399,8 @@
 		{
 			*c = '\0';
 			try_add_algo(last_name, algos, algo_desc, new_algos, &num_ret);
-			last_name = c++;
+			c++;
+			last_name = c;
 		}
 	}
 	try_add_algo(last_name, algos, algo_desc, new_algos, &num_ret);
--- a/common-kex.c	Wed Mar 20 22:31:07 2013 +0800
+++ b/common-kex.c	Wed Mar 20 22:41:07 2013 +0800
@@ -249,26 +249,28 @@
  * already initialised hash_state hs, which should already have processed
  * the dh_K and hash, since these are common. X is the letter 'A', 'B' etc.
  * out must have at least min(SHA1_HASH_SIZE, outlen) bytes allocated.
- * The output will only be expanded once, as we are assured that
- * outlen <= 2*SHA1_HASH_SIZE for all known hashes.
  *
  * See Section 7.2 of rfc4253 (ssh transport) for details */
 static void hashkeys(unsigned char *out, int outlen, 
 		const hash_state * hs, const unsigned char X) {
 
 	hash_state hs2;
-	unsigned char k2[SHA1_HASH_SIZE]; /* used to extending */
+	int offset;
 
 	memcpy(&hs2, hs, sizeof(hash_state));
 	sha1_process(&hs2, &X, 1);
 	sha1_process(&hs2, ses.session_id, SHA1_HASH_SIZE);
 	sha1_done(&hs2, out);
-	if (SHA1_HASH_SIZE < outlen) {
+	for (offset = SHA1_HASH_SIZE; 
+			offset < outlen; 
+			offset += SHA1_HASH_SIZE)
+	{
 		/* need to extend */
+		unsigned char k2[SHA1_HASH_SIZE];
 		memcpy(&hs2, hs, sizeof(hash_state));
-		sha1_process(&hs2, out, SHA1_HASH_SIZE);
+		sha1_process(&hs2, out, offset);
 		sha1_done(&hs2, k2);
-		memcpy(&out[SHA1_HASH_SIZE], k2, outlen - SHA1_HASH_SIZE);
+		memcpy(&out[offset], k2, MIN(outlen - offset, SHA1_HASH_SIZE));
 	}
 }
 
@@ -292,7 +294,6 @@
 	hash_state hs;
 	unsigned int C2S_keysize, S2C_keysize;
 	char mactransletter, macrecvletter; /* Client or server specific */
-	int recv_cipher = 0, trans_cipher = 0;
 
 	TRACE(("enter gen_new_keys"))
 	/* the dh_K and hash are the start of all hashes, we make use of that */
@@ -329,31 +330,39 @@
 	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);
-	if (recv_cipher < 0)
-	    dropbear_exit("Crypto error");
-	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) {
-		dropbear_exit("Crypto error");
+	if (ses.newkeys->recv.algo_crypt->cipherdesc != NULL) {
+		int 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, 
+				recv_IV, recv_key, 
+				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);
-	if (trans_cipher < 0)
-	    dropbear_exit("Crypto error");
-	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) {
-		dropbear_exit("Crypto error");
+	if (ses.newkeys->trans.algo_crypt->cipherdesc != NULL) {
+		int 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, 
+				trans_IV, trans_key, 
+				ses.newkeys->trans.algo_crypt->keysize, 0, 
+				&ses.newkeys->trans.cipher_state) != CRYPT_OK) {
+			dropbear_exit("Crypto error");
+		}
 	}
-	
+
 	/* MAC keys */
-	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);
+	if (ses.newkeys->trans.algo_mac->hashdesc != NULL) {
+		hashkeys(ses.newkeys->trans.mackey, 
+				ses.newkeys->trans.algo_mac->keysize, &hs, mactransletter);
+	}
+	if (ses.newkeys->recv.algo_mac->hashdesc != NULL) {
+		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),
 
--- a/libtomcrypt/src/headers/tomcrypt_custom.h	Wed Mar 20 22:31:07 2013 +0800
+++ b/libtomcrypt/src/headers/tomcrypt_custom.h	Wed Mar 20 22:41:07 2013 +0800
@@ -118,14 +118,18 @@
 #define LTC_CTR_MODE
 #endif
 
-#if defined(DROPBEAR_DSS) && defined(DSS_PROTOK)
-#define SHA512
+#define SHA1
+
+#ifdef DROPBEAR_MD5
+#define MD5
 #endif
 
-#define SHA1
+#ifdef DROPBEAR_SHA256
+#define SHA256
+#endif
 
-#ifdef DROPBEAR_MD5_HMAC
-#define MD5
+#ifdef DROPBEAR_SHA512
+#define SHA512
 #endif
 
 #define LTC_HMAC
--- a/options.h	Wed Mar 20 22:31:07 2013 +0800
+++ b/options.h	Wed Mar 20 22:41:07 2013 +0800
@@ -100,6 +100,12 @@
  * size and is recommended for most cases */
 #define DROPBEAR_ENABLE_CTR_MODE
 
+/* You can compile with no encryption if you want. In some circumstances
+ * this could be safe security-wise, though make sure you know what
+ * you're doing. Anyone can see everything that goes over the wire, so
+ * the only safe auth method is public key. */
+#define DROPBEAR_NONE_CIPHER
+
 /* Message Integrity - at least one required.
  * Protocol RFC requires sha1 and recommends sha1-96.
  * sha1-96 is of use for slow links as it has a smaller overhead.
@@ -112,11 +118,19 @@
  * These hashes are also used for public key fingerprints in logs.
  * If you disable MD5, Dropbear will fall back to SHA1 fingerprints,
  * which are not the standard form. */
-
 #define DROPBEAR_SHA1_HMAC
 #define DROPBEAR_SHA1_96_HMAC
+/*#define DROPBEAR_SHA2_256_HMAC*/
+/*#define DROPBEAR_SHA2_512_HMAC*/
 #define DROPBEAR_MD5_HMAC
 
+/* You can also disable integrity. Don't bother disabling this if you're
+ * still using a cipher, it's relatively cheap. If you disable this it's dead
+ * simple to run arbitrary commands on the remote host. Beware.
+ * Note again, for the client you will have to disable other hashes above
+ * to use this. */
+#define DROPBEAR_NONE_INTEGRITY
+
 /* Hostkey/public key algorithms - at least one required, these are used
  * for hostkey as well as for verifying signatures with pubkey auth.
  * Removing either of these won't save very much space.
--- a/session.h	Wed Mar 20 22:31:07 2013 +0800
+++ b/session.h	Wed Mar 20 22:41:07 2013 +0800
@@ -269,6 +269,9 @@
 	int interact_request_received; /* flag whether we've received an 
 									  info request from the server for
 									  interactive auth.*/
+
+	int cipher_none_after_auth; /* Set to 1 if the user requested "none"
+								   auth */
 #endif
 	sign_key *lastprivkey;
 
--- a/sysoptions.h	Wed Mar 20 22:31:07 2013 +0800
+++ b/sysoptions.h	Wed Mar 20 22:41:07 2013 +0800
@@ -90,7 +90,13 @@
 #define MAX_KEY_LEN 32 /* 256 bits for aes256 etc */
 #define MAX_IV_LEN 20 /* must be same as max blocksize, 
 						 and >= SHA1_HASH_SIZE */
+#if defined(DROPBEAR_SHA2_512_HMAC)
+#define MAX_MAC_KEY 64
+#elif defined(DROPBEAR_SHA2_256_HMAC)
+#define MAX_MAC_KEY 32
+#else
 #define MAX_MAC_KEY 20
+#endif
 
 #define MAX_NAME_LEN 64 /* maximum length of a protocol name, isn't
 						   explicitly specified for all protocols (just
@@ -144,6 +150,19 @@
 #define DROPBEAR_TWOFISH
 #endif
 
+#ifdef DROPBEAR_MD5_HMAC
+#define DROPBEAR_MD5
+#endif
+
+#ifdef DROPBEAR_SHA2_256_HMAC
+#define DROPBEAR_SHA256
+#endif
+
+#if (defined(DROPBEAR_DSS) && defined(DSS_PROTOK)) \
+	|| defined(DROPBEAR_SHA2_512_HMAC)
+#define DROPBEAR_SHA512
+#endif
+
 #ifndef ENABLE_X11FWD
 #define DISABLE_X11FWD
 #endif