dropbear: add ed25519 and chacha20-poly1305
- add Ed25519 support (backport): * DROPBEAR_ED25519 option for ssh-ed25519, * disabled by default - add Chacha20-Poly1305 support (backport): * DROPBEAR_CHACHA20POLY1305 for chacha20-poly1305@openssh.com, * enabled by default - update feature costs in binary size Signed-off-by: Vladislav Grishenko <themiron@mail.ru>
This commit is contained in:
		 Vladislav Grishenko
					Vladislav Grishenko
				
			
				
					committed by
					
						 Hans Dedecker
						Hans Dedecker
					
				
			
			
				
	
			
			
			 Hans Dedecker
						Hans Dedecker
					
				
			
						parent
						
							02f08056bc
						
					
				
				
					commit
					f166cf9ca0
				
			| @@ -8,7 +8,7 @@ config DROPBEAR_CURVE25519 | |||||||
| 		This enables the following key exchange algorithm: | 		This enables the following key exchange algorithm: | ||||||
| 		  curve25519-sha256@libssh.org | 		  curve25519-sha256@libssh.org | ||||||
|  |  | ||||||
| 		Increases binary size by about 8 kB uncompressed (MIPS). | 		Increases binary size by about 4 kB (MIPS). | ||||||
|  |  | ||||||
| config DROPBEAR_ECC | config DROPBEAR_ECC | ||||||
| 	bool "Elliptic curve cryptography (ECC)" | 	bool "Elliptic curve cryptography (ECC)" | ||||||
| @@ -49,6 +49,24 @@ config DROPBEAR_ECC_FULL | |||||||
|  |  | ||||||
| 		Increases binary size by about 4 kB (MIPS). | 		Increases binary size by about 4 kB (MIPS). | ||||||
|  |  | ||||||
|  | config DROPBEAR_ED25519 | ||||||
|  | 	bool "Ed25519 support" | ||||||
|  | 	default n | ||||||
|  | 	help | ||||||
|  | 		This enables the following public key algorithm: | ||||||
|  | 		  ssh-ed25519 | ||||||
|  |  | ||||||
|  | 		Increases binary size by about 12 kB (MIPS). | ||||||
|  |  | ||||||
|  | config DROPBEAR_CHACHA20POLY1305 | ||||||
|  | 	bool "Chacha20-Poly1305 support" | ||||||
|  | 	default y | ||||||
|  | 	help | ||||||
|  | 		This enables the following authenticated encryption cipher: | ||||||
|  | 		  chacha20-poly1305@openssh.com | ||||||
|  |  | ||||||
|  | 		Increases binary size by about 4 kB (MIPS). | ||||||
|  |  | ||||||
| config DROPBEAR_ZLIB | config DROPBEAR_ZLIB | ||||||
| 	bool "Enable compression" | 	bool "Enable compression" | ||||||
| 	default n | 	default n | ||||||
|   | |||||||
| @@ -9,7 +9,7 @@ include $(TOPDIR)/rules.mk | |||||||
|  |  | ||||||
| PKG_NAME:=dropbear | PKG_NAME:=dropbear | ||||||
| PKG_VERSION:=2019.78 | PKG_VERSION:=2019.78 | ||||||
| PKG_RELEASE:=4 | PKG_RELEASE:=5 | ||||||
|  |  | ||||||
| PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2 | PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2 | ||||||
| PKG_SOURCE_URL:= \ | PKG_SOURCE_URL:= \ | ||||||
| @@ -29,6 +29,7 @@ PKG_FIXUP:=autoreconf | |||||||
| PKG_CONFIG_DEPENDS:= \ | PKG_CONFIG_DEPENDS:= \ | ||||||
| 	CONFIG_TARGET_INIT_PATH CONFIG_DROPBEAR_ECC CONFIG_DROPBEAR_ECC_FULL \ | 	CONFIG_TARGET_INIT_PATH CONFIG_DROPBEAR_ECC CONFIG_DROPBEAR_ECC_FULL \ | ||||||
| 	CONFIG_DROPBEAR_CURVE25519 CONFIG_DROPBEAR_ZLIB \ | 	CONFIG_DROPBEAR_CURVE25519 CONFIG_DROPBEAR_ZLIB \ | ||||||
|  | 	CONFIG_DROPBEAR_ED25519 CONFIG_DROPBEAR_CHACHA20POLY1305 \ | ||||||
| 	CONFIG_DROPBEAR_UTMP CONFIG_DROPBEAR_PUTUTLINE \ | 	CONFIG_DROPBEAR_UTMP CONFIG_DROPBEAR_PUTUTLINE \ | ||||||
| 	CONFIG_DROPBEAR_DBCLIENT | 	CONFIG_DROPBEAR_DBCLIENT | ||||||
|  |  | ||||||
| @@ -63,6 +64,7 @@ define Package/dropbear/description | |||||||
| endef | endef | ||||||
|  |  | ||||||
| define Package/dropbear/conffiles | define Package/dropbear/conffiles | ||||||
|  | $(if $(CONFIG_DROPBEAR_ED25519),/etc/dropbear/dropbear_ed25519_host_key) | ||||||
| $(if $(CONFIG_DROPBEAR_ECC),/etc/dropbear/dropbear_ecdsa_host_key) | $(if $(CONFIG_DROPBEAR_ECC),/etc/dropbear/dropbear_ecdsa_host_key) | ||||||
| /etc/dropbear/dropbear_rsa_host_key | /etc/dropbear/dropbear_rsa_host_key | ||||||
| /etc/config/dropbear | /etc/config/dropbear | ||||||
| @@ -110,6 +112,12 @@ define Build/Configure | |||||||
| 			$(PKG_BUILD_DIR)/localoptions.h; \ | 			$(PKG_BUILD_DIR)/localoptions.h; \ | ||||||
| 	done | 	done | ||||||
|  |  | ||||||
|  | 	echo '#define DROPBEAR_ED25519 $(if $(CONFIG_DROPBEAR_ED25519),1,0)' >> \ | ||||||
|  | 		$(PKG_BUILD_DIR)/localoptions.h | ||||||
|  |  | ||||||
|  | 	echo '#define DROPBEAR_CHACHA20POLY1305 $(if $(CONFIG_DROPBEAR_CHACHA20POLY1305),1,0)' >> \ | ||||||
|  | 		$(PKG_BUILD_DIR)/localoptions.h | ||||||
|  |  | ||||||
| 	# remove protocol idented software version number | 	# remove protocol idented software version number | ||||||
| 	$(ESED) 's,^(#define LOCAL_IDENT) .*$$$$,\1 "SSH-2.0-dropbear",g' \ | 	$(ESED) 's,^(#define LOCAL_IDENT) .*$$$$,\1 "SSH-2.0-dropbear",g' \ | ||||||
| 		$(PKG_BUILD_DIR)/sysoptions.h | 		$(PKG_BUILD_DIR)/sysoptions.h | ||||||
| @@ -160,6 +168,7 @@ define Package/dropbear/install | |||||||
| 	$(INSTALL_DIR) $(1)/etc/dropbear | 	$(INSTALL_DIR) $(1)/etc/dropbear | ||||||
| 	$(INSTALL_DIR) $(1)/lib/preinit | 	$(INSTALL_DIR) $(1)/lib/preinit | ||||||
| 	$(INSTALL_DATA) ./files/dropbear.failsafe $(1)/lib/preinit/99_10_failsafe_dropbear | 	$(INSTALL_DATA) ./files/dropbear.failsafe $(1)/lib/preinit/99_10_failsafe_dropbear | ||||||
|  | 	$(if $(CONFIG_DROPBEAR_ED25519),touch $(1)/etc/dropbear/dropbear_ed25519_host_key) | ||||||
| 	$(if $(CONFIG_DROPBEAR_ECC),touch $(1)/etc/dropbear/dropbear_ecdsa_host_key) | 	$(if $(CONFIG_DROPBEAR_ECC),touch $(1)/etc/dropbear/dropbear_ecdsa_host_key) | ||||||
| 	touch $(1)/etc/dropbear/dropbear_rsa_host_key | 	touch $(1)/etc/dropbear/dropbear_rsa_host_key | ||||||
| endef | endef | ||||||
|   | |||||||
| @@ -66,7 +66,7 @@ hk_generate_as_needed() | |||||||
| 	kdir='/etc/dropbear' | 	kdir='/etc/dropbear' | ||||||
|  |  | ||||||
| 	kgen='' | 	kgen='' | ||||||
| 	for ktype in ecdsa rsa; do | 	for ktype in ed25519 ecdsa rsa; do | ||||||
| 		hk_verify "${kdir}/dropbear_${ktype}_host_key" && continue | 		hk_verify "${kdir}/dropbear_${ktype}_host_key" && continue | ||||||
|  |  | ||||||
| 		kgen="${kgen} ${ktype}" | 		kgen="${kgen} ${ktype}" | ||||||
|   | |||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -0,0 +1,693 @@ | |||||||
|  | From 3cdf9ec918b37c17e12b33e4c244944d1ee836ca Mon Sep 17 00:00:00 2001 | ||||||
|  | From: Vladislav Grishenko <themiron@mail.ru> | ||||||
|  | Date: Mon, 6 Apr 2020 23:28:09 +0500 | ||||||
|  | Subject: [PATCH] Add Chacha20-Poly1305 authenticated encryption | ||||||
|  |  | ||||||
|  | * Add general AEAD approach. | ||||||
|  | * Add chacha20-poly1305@openssh.com algo using LibTomCrypt chacha and | ||||||
|  |   poly1305 routines. | ||||||
|  |  | ||||||
|  | Chacha20-Poly1305 is generally faster than AES256 on CPU w/o dedicated | ||||||
|  | AES instructions, having the same key size. | ||||||
|  | Compiling in will add ~5,5kB to binary size on x86-64. | ||||||
|  | --- | ||||||
|  |  Makefile.in                                 |   2 +- | ||||||
|  |  algo.h                                      |   8 ++ | ||||||
|  |  chachapoly.c                                | 148 ++++++++++++++++++++ | ||||||
|  |  chachapoly.h                                |  44 ++++++ | ||||||
|  |  common-algo.c                               |  11 +- | ||||||
|  |  common-kex.c                                |  44 ++++-- | ||||||
|  |  default_options.h                           |   6 + | ||||||
|  |  libtomcrypt/src/headers/tomcrypt_dropbear.h |   4 + | ||||||
|  |  packet.c                                    | 145 +++++++++++++------ | ||||||
|  |  session.h                                   |   4 + | ||||||
|  |  sysoptions.h                                |   8 +- | ||||||
|  |  11 files changed, 368 insertions(+), 56 deletions(-) | ||||||
|  |  create mode 100644 chachapoly.c | ||||||
|  |  create mode 100644 chachapoly.h | ||||||
|  |  | ||||||
|  | diff --git a/Makefile.in b/Makefile.in | ||||||
|  | index aaf7b3b..3437cb2 100644 | ||||||
|  | --- a/Makefile.in | ||||||
|  | +++ b/Makefile.in | ||||||
|  | @@ -53,7 +53,7 @@ CLIOBJS=cli-main.o cli-auth.o cli-authpasswd.o cli-kex.o \ | ||||||
|  |  CLISVROBJS=common-session.o packet.o common-algo.o common-kex.o \ | ||||||
|  |  			common-channel.o common-chansession.o termcodes.o loginrec.o \ | ||||||
|  |  			tcp-accept.o listener.o process-packet.o dh_groups.o \ | ||||||
|  | -			common-runopts.o circbuffer.o list.o netio.o | ||||||
|  | +			common-runopts.o circbuffer.o list.o netio.o chachapoly.o | ||||||
|  |   | ||||||
|  |  KEYOBJS=dropbearkey.o | ||||||
|  |   | ||||||
|  | diff --git a/algo.h b/algo.h | ||||||
|  | index b12fb94..efd0d73 100644 | ||||||
|  | --- a/algo.h | ||||||
|  | +++ b/algo.h | ||||||
|  | @@ -72,6 +72,14 @@ struct dropbear_cipher_mode { | ||||||
|  |  			unsigned long len, void *cipher_state); | ||||||
|  |  	int (*decrypt)(const unsigned char *ct, unsigned char *pt,  | ||||||
|  |  			unsigned long len, void *cipher_state); | ||||||
|  | +	int (*aead_crypt)(unsigned int seq, | ||||||
|  | +			const unsigned char *in, unsigned char *out, | ||||||
|  | +			unsigned long len, unsigned long taglen, | ||||||
|  | +			void *cipher_state, int direction); | ||||||
|  | +	int (*aead_getlength)(unsigned int seq, | ||||||
|  | +			const unsigned char *in, unsigned int *outlen, | ||||||
|  | +			unsigned long len, void *cipher_state); | ||||||
|  | +	const struct dropbear_hash *aead_mac; | ||||||
|  |  }; | ||||||
|  |   | ||||||
|  |  struct dropbear_hash { | ||||||
|  | diff --git a/chachapoly.c b/chachapoly.c | ||||||
|  | new file mode 100644 | ||||||
|  | index 0000000..8fb06c5 | ||||||
|  | --- /dev/null | ||||||
|  | +++ b/chachapoly.c | ||||||
|  | @@ -0,0 +1,148 @@ | ||||||
|  | +/* | ||||||
|  | + * Dropbear SSH | ||||||
|  | + *  | ||||||
|  | + * Copyright (c) 2002,2003 Matt Johnston | ||||||
|  | + * Copyright (c) 2020 by Vladislav Grishenko | ||||||
|  | + * All rights reserved. | ||||||
|  | + *  | ||||||
|  | + * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||||
|  | + * of this software and associated documentation files (the "Software"), to deal | ||||||
|  | + * in the Software without restriction, including without limitation the rights | ||||||
|  | + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||||
|  | + * copies of the Software, and to permit persons to whom the Software is | ||||||
|  | + * furnished to do so, subject to the following conditions: | ||||||
|  | + *  | ||||||
|  | + * The above copyright notice and this permission notice shall be included in | ||||||
|  | + * all copies or substantial portions of the Software. | ||||||
|  | + *  | ||||||
|  | + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||||
|  | + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||||
|  | + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||||
|  | + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||||
|  | + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||||
|  | + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||||||
|  | + * SOFTWARE. */ | ||||||
|  | + | ||||||
|  | +#include "includes.h" | ||||||
|  | +#include "algo.h" | ||||||
|  | +#include "dbutil.h" | ||||||
|  | +#include "chachapoly.h" | ||||||
|  | + | ||||||
|  | +#if DROPBEAR_CHACHA20POLY1305 | ||||||
|  | + | ||||||
|  | +#define CHACHA20_KEY_LEN 32 | ||||||
|  | +#define CHACHA20_BLOCKSIZE 8 | ||||||
|  | +#define POLY1305_KEY_LEN 32 | ||||||
|  | +#define POLY1305_TAG_LEN 16 | ||||||
|  | + | ||||||
|  | +static const struct ltc_cipher_descriptor dummy = {.name = NULL}; | ||||||
|  | + | ||||||
|  | +static const struct dropbear_hash dropbear_chachapoly_mac = | ||||||
|  | +	{NULL, POLY1305_KEY_LEN, POLY1305_TAG_LEN}; | ||||||
|  | + | ||||||
|  | +const struct dropbear_cipher dropbear_chachapoly = | ||||||
|  | +	{&dummy, CHACHA20_KEY_LEN*2, CHACHA20_BLOCKSIZE}; | ||||||
|  | + | ||||||
|  | +static int dropbear_chachapoly_start(int UNUSED(cipher), const unsigned char* UNUSED(IV), | ||||||
|  | +			const unsigned char *key, int keylen, | ||||||
|  | +			int UNUSED(num_rounds), dropbear_chachapoly_state *state) { | ||||||
|  | +	int err; | ||||||
|  | + | ||||||
|  | +	TRACE2(("enter dropbear_chachapoly_start")) | ||||||
|  | + | ||||||
|  | +	if (keylen != CHACHA20_KEY_LEN*2) { | ||||||
|  | +		return CRYPT_ERROR; | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	if ((err = chacha_setup(&state->chacha, key, | ||||||
|  | +				CHACHA20_KEY_LEN, 20)) != CRYPT_OK) { | ||||||
|  | +		return err; | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	if ((err = chacha_setup(&state->header, key + CHACHA20_KEY_LEN, | ||||||
|  | +				CHACHA20_KEY_LEN, 20) != CRYPT_OK)) { | ||||||
|  | +		return err; | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	TRACE2(("leave dropbear_chachapoly_start")) | ||||||
|  | +	return CRYPT_OK; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static int dropbear_chachapoly_crypt(unsigned int seq, | ||||||
|  | +			const unsigned char *in, unsigned char *out, | ||||||
|  | +			unsigned long len, unsigned long taglen, | ||||||
|  | +			dropbear_chachapoly_state *state, int direction) { | ||||||
|  | +	poly1305_state poly; | ||||||
|  | +	unsigned char seqbuf[8], key[POLY1305_KEY_LEN], tag[POLY1305_TAG_LEN]; | ||||||
|  | +	int err; | ||||||
|  | + | ||||||
|  | +	TRACE2(("enter dropbear_chachapoly_crypt")) | ||||||
|  | + | ||||||
|  | +	if (len < 4 || taglen != POLY1305_TAG_LEN) { | ||||||
|  | +		return CRYPT_ERROR; | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	STORE64H((uint64_t)seq, seqbuf); | ||||||
|  | +	chacha_ivctr64(&state->chacha, seqbuf, sizeof(seqbuf), 0); | ||||||
|  | +	if ((err = chacha_keystream(&state->chacha, key, sizeof(key))) != CRYPT_OK) { | ||||||
|  | +		return err; | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	poly1305_init(&poly, key, sizeof(key)); | ||||||
|  | +	if (direction == LTC_DECRYPT) { | ||||||
|  | +		poly1305_process(&poly, in, len); | ||||||
|  | +		poly1305_done(&poly, tag, &taglen); | ||||||
|  | +		if (constant_time_memcmp(in + len, tag, taglen) != 0) { | ||||||
|  | +			return CRYPT_ERROR; | ||||||
|  | +		} | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	chacha_ivctr64(&state->header, seqbuf, sizeof(seqbuf), 0); | ||||||
|  | +	if ((err = chacha_crypt(&state->header, in, 4, out)) != CRYPT_OK) { | ||||||
|  | +		return err; | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	chacha_ivctr64(&state->chacha, seqbuf, sizeof(seqbuf), 1); | ||||||
|  | +	if ((err = chacha_crypt(&state->chacha, in + 4, len - 4, out + 4)) != CRYPT_OK) { | ||||||
|  | +		return err; | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	if (direction == LTC_ENCRYPT) { | ||||||
|  | +		poly1305_process(&poly, out, len); | ||||||
|  | +		poly1305_done(&poly, out + len, &taglen); | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	TRACE2(("leave dropbear_chachapoly_crypt")) | ||||||
|  | +	return CRYPT_OK; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static int dropbear_chachapoly_getlength(unsigned int seq, | ||||||
|  | +			const unsigned char *in, unsigned int *outlen, | ||||||
|  | +			unsigned long len, dropbear_chachapoly_state *state) { | ||||||
|  | +	unsigned char seqbuf[8], buf[4]; | ||||||
|  | +	int err; | ||||||
|  | + | ||||||
|  | +	TRACE2(("enter dropbear_chachapoly_getlength")) | ||||||
|  | + | ||||||
|  | +	if (len < sizeof(buf)) { | ||||||
|  | +		return CRYPT_ERROR; | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	STORE64H((uint64_t)seq, seqbuf); | ||||||
|  | +	chacha_ivctr64(&state->header, seqbuf, sizeof(seqbuf), 0); | ||||||
|  | +	if ((err = chacha_crypt(&state->header, in, sizeof(buf), buf)) != CRYPT_OK) { | ||||||
|  | +		return err; | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	LOAD32H(*outlen, buf); | ||||||
|  | + | ||||||
|  | +	TRACE2(("leave dropbear_chachapoly_getlength")) | ||||||
|  | +	return CRYPT_OK; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +const struct dropbear_cipher_mode dropbear_mode_chachapoly = | ||||||
|  | +	{(void *)dropbear_chachapoly_start, NULL, NULL, | ||||||
|  | +	 (void *)dropbear_chachapoly_crypt, | ||||||
|  | +	 (void *)dropbear_chachapoly_getlength, &dropbear_chachapoly_mac}; | ||||||
|  | + | ||||||
|  | +#endif /* DROPBEAR_CHACHA20POLY1305 */ | ||||||
|  | diff --git a/chachapoly.h b/chachapoly.h | ||||||
|  | new file mode 100644 | ||||||
|  | index 0000000..5a7c5b2 | ||||||
|  | --- /dev/null | ||||||
|  | +++ b/chachapoly.h | ||||||
|  | @@ -0,0 +1,44 @@ | ||||||
|  | +/* | ||||||
|  | + * Dropbear SSH | ||||||
|  | + *  | ||||||
|  | + * Copyright (c) 2002,2003 Matt Johnston | ||||||
|  | + * Copyright (c) 2020 by Vladislav Grishenko | ||||||
|  | + * All rights reserved. | ||||||
|  | + *  | ||||||
|  | + * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||||
|  | + * of this software and associated documentation files (the "Software"), to deal | ||||||
|  | + * in the Software without restriction, including without limitation the rights | ||||||
|  | + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||||
|  | + * copies of the Software, and to permit persons to whom the Software is | ||||||
|  | + * furnished to do so, subject to the following conditions: | ||||||
|  | + *  | ||||||
|  | + * The above copyright notice and this permission notice shall be included in | ||||||
|  | + * all copies or substantial portions of the Software. | ||||||
|  | + *  | ||||||
|  | + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||||
|  | + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||||
|  | + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||||
|  | + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||||
|  | + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||||
|  | + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||||||
|  | + * SOFTWARE. */ | ||||||
|  | + | ||||||
|  | +#ifndef DROPBEAR_DROPBEAR_CHACHAPOLY_H_ | ||||||
|  | +#define DROPBEAR_DROPBEAR_CHACHAPOLY_H_ | ||||||
|  | + | ||||||
|  | +#include "includes.h" | ||||||
|  | +#include "algo.h" | ||||||
|  | + | ||||||
|  | +#if DROPBEAR_CHACHA20POLY1305 | ||||||
|  | + | ||||||
|  | +typedef struct { | ||||||
|  | +	chacha_state chacha; | ||||||
|  | +	chacha_state header; | ||||||
|  | +} dropbear_chachapoly_state; | ||||||
|  | + | ||||||
|  | +extern const struct dropbear_cipher dropbear_chachapoly; | ||||||
|  | +extern const struct dropbear_cipher_mode dropbear_mode_chachapoly; | ||||||
|  | + | ||||||
|  | +#endif /* DROPBEAR_CHACHA20POLY1305 */ | ||||||
|  | + | ||||||
|  | +#endif /* DROPBEAR_DROPBEAR_CHACHAPOLY_H_ */ | ||||||
|  | diff --git a/common-algo.c b/common-algo.c | ||||||
|  | index 558aad2..1436456 100644 | ||||||
|  | --- a/common-algo.c | ||||||
|  | +++ b/common-algo.c | ||||||
|  | @@ -30,6 +30,7 @@ | ||||||
|  |  #include "dh_groups.h" | ||||||
|  |  #include "ltc_prng.h" | ||||||
|  |  #include "ecc.h" | ||||||
|  | +#include "chachapoly.h" | ||||||
|  |   | ||||||
|  |  /* 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*/ | ||||||
|  | @@ -86,11 +87,11 @@ const struct dropbear_cipher dropbear_nocipher = | ||||||
|  |   * about the symmetric_CBC vs symmetric_CTR cipher_state pointer */ | ||||||
|  |  #if DROPBEAR_ENABLE_CBC_MODE | ||||||
|  |  const struct dropbear_cipher_mode dropbear_mode_cbc = | ||||||
|  | -	{(void*)cbc_start, (void*)cbc_encrypt, (void*)cbc_decrypt}; | ||||||
|  | +	{(void*)cbc_start, (void*)cbc_encrypt, (void*)cbc_decrypt, NULL, NULL, NULL}; | ||||||
|  |  #endif /* DROPBEAR_ENABLE_CBC_MODE */ | ||||||
|  |   | ||||||
|  |  const struct dropbear_cipher_mode dropbear_mode_none = | ||||||
|  | -	{void_start, void_cipher, void_cipher}; | ||||||
|  | +	{void_start, void_cipher, void_cipher, NULL, NULL, NULL}; | ||||||
|  |   | ||||||
|  |  #if DROPBEAR_ENABLE_CTR_MODE | ||||||
|  |  /* a wrapper to make ctr_start and cbc_start look the same */ | ||||||
|  | @@ -101,7 +102,7 @@ static int dropbear_big_endian_ctr_start(int cipher, | ||||||
|  |  	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}; | ||||||
|  | +	{(void*)dropbear_big_endian_ctr_start, (void*)ctr_encrypt, (void*)ctr_decrypt, NULL, NULL, NULL}; | ||||||
|  |  #endif /* DROPBEAR_ENABLE_CTR_MODE */ | ||||||
|  |   | ||||||
|  |  /* Mapping of ssh hashes to libtomcrypt hashes, including keysize etc. | ||||||
|  | @@ -137,6 +138,10 @@ const struct dropbear_hash dropbear_nohash = | ||||||
|  |   * that is also supported by the server will get used. */ | ||||||
|  |   | ||||||
|  |  algo_type sshciphers[] = { | ||||||
|  | +#if DROPBEAR_CHACHA20POLY1305 | ||||||
|  | +	{"chacha20-poly1305@openssh.com", 0, &dropbear_chachapoly, 1, &dropbear_mode_chachapoly}, | ||||||
|  | +#endif | ||||||
|  | + | ||||||
|  |  #if DROPBEAR_ENABLE_CTR_MODE | ||||||
|  |  #if DROPBEAR_AES128 | ||||||
|  |  	{"aes128-ctr", 0, &dropbear_aes128, 1, &dropbear_mode_ctr}, | ||||||
|  | diff --git a/common-kex.c b/common-kex.c | ||||||
|  | index 16b7e27..5e2923f 100644 | ||||||
|  | --- a/common-kex.c | ||||||
|  | +++ b/common-kex.c | ||||||
|  | @@ -329,9 +329,12 @@ static void gen_new_keys() { | ||||||
|  |  	hashkeys(S2C_key, sizeof(S2C_key), &hs, 'D'); | ||||||
|  |   | ||||||
|  |  	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"); | ||||||
|  | +		int recv_cipher = -1; | ||||||
|  | +		if (ses.newkeys->recv.algo_crypt->cipherdesc->name != NULL) { | ||||||
|  | +			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,  | ||||||
|  | @@ -341,9 +344,12 @@ static void gen_new_keys() { | ||||||
|  |  	} | ||||||
|  |   | ||||||
|  |  	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"); | ||||||
|  | +		int trans_cipher = -1; | ||||||
|  | +		if (ses.newkeys->trans.algo_crypt->cipherdesc->name != NULL) { | ||||||
|  | +			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,  | ||||||
|  | @@ -868,19 +874,29 @@ static void read_kex_algos() { | ||||||
|  |   | ||||||
|  |  	/* mac_algorithms_client_to_server */ | ||||||
|  |  	c2s_hash_algo = buf_match_algo(ses.payload, sshhashes, NULL, NULL); | ||||||
|  | +#if DROPBEAR_AEAD_MODE | ||||||
|  | +	if (((struct dropbear_cipher_mode*)c2s_cipher_algo->mode)->aead_crypt != NULL) { | ||||||
|  | +		c2s_hash_algo = NULL; | ||||||
|  | +	} else | ||||||
|  | +#endif | ||||||
|  |  	if (c2s_hash_algo == NULL) { | ||||||
|  |  		erralgo = "mac c->s"; | ||||||
|  |  		goto error; | ||||||
|  |  	} | ||||||
|  | -	TRACE(("hash c2s is  %s", c2s_hash_algo->name)) | ||||||
|  | +	TRACE(("hash c2s is  %s", c2s_hash_algo ? c2s_hash_algo->name : "<implicit>")) | ||||||
|  |   | ||||||
|  |  	/* mac_algorithms_server_to_client */ | ||||||
|  |  	s2c_hash_algo = buf_match_algo(ses.payload, sshhashes, NULL, NULL); | ||||||
|  | +#if DROPBEAR_AEAD_MODE | ||||||
|  | +	if (((struct dropbear_cipher_mode*)s2c_cipher_algo->mode)->aead_crypt != NULL) { | ||||||
|  | +		s2c_hash_algo = NULL; | ||||||
|  | +	} else | ||||||
|  | +#endif | ||||||
|  |  	if (s2c_hash_algo == NULL) { | ||||||
|  |  		erralgo = "mac s->c"; | ||||||
|  |  		goto error; | ||||||
|  |  	} | ||||||
|  | -	TRACE(("hash s2c is  %s", s2c_hash_algo->name)) | ||||||
|  | +	TRACE(("hash s2c is  %s", s2c_hash_algo ? s2c_hash_algo->name : "<implicit>")) | ||||||
|  |   | ||||||
|  |  	/* compression_algorithms_client_to_server */ | ||||||
|  |  	c2s_comp_algo = buf_match_algo(ses.payload, ses.compress_algos, NULL, NULL); | ||||||
|  | @@ -925,8 +941,14 @@ static void read_kex_algos() { | ||||||
|  |  		ses.newkeys->trans.crypt_mode = | ||||||
|  |  			(struct dropbear_cipher_mode*)c2s_cipher_algo->mode; | ||||||
|  |  		ses.newkeys->recv.algo_mac =  | ||||||
|  | +#if DROPBEAR_AEAD_MODE | ||||||
|  | +			s2c_hash_algo == NULL ? ses.newkeys->recv.crypt_mode->aead_mac : | ||||||
|  | +#endif | ||||||
|  |  			(struct dropbear_hash*)s2c_hash_algo->data; | ||||||
|  |  		ses.newkeys->trans.algo_mac =  | ||||||
|  | +#if DROPBEAR_AEAD_MODE | ||||||
|  | +			c2s_hash_algo == NULL ? ses.newkeys->trans.crypt_mode->aead_mac : | ||||||
|  | +#endif | ||||||
|  |  			(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; | ||||||
|  | @@ -941,8 +963,14 @@ static void read_kex_algos() { | ||||||
|  |  		ses.newkeys->trans.crypt_mode = | ||||||
|  |  			(struct dropbear_cipher_mode*)s2c_cipher_algo->mode; | ||||||
|  |  		ses.newkeys->recv.algo_mac =  | ||||||
|  | +#if DROPBEAR_AEAD_MODE | ||||||
|  | +			c2s_hash_algo == NULL ? ses.newkeys->recv.crypt_mode->aead_mac : | ||||||
|  | +#endif | ||||||
|  |  			(struct dropbear_hash*)c2s_hash_algo->data; | ||||||
|  |  		ses.newkeys->trans.algo_mac =  | ||||||
|  | +#if DROPBEAR_AEAD_MODE | ||||||
|  | +			s2c_hash_algo == NULL ? ses.newkeys->trans.crypt_mode->aead_mac : | ||||||
|  | +#endif | ||||||
|  |  			(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; | ||||||
|  | diff --git a/default_options.h b/default_options.h | ||||||
|  | index bafbb07..1a2ab10 100644 | ||||||
|  | --- a/default_options.h | ||||||
|  | +++ b/default_options.h | ||||||
|  | @@ -99,6 +99,12 @@ IMPORTANT: Some options will require "make clean" after changes */ | ||||||
|  |   * and forwards compatibility */ | ||||||
|  |  #define DROPBEAR_ENABLE_CTR_MODE 1 | ||||||
|  |   | ||||||
|  | +/* Enable Chacha20-Poly1305 authenticated encryption mode. This is | ||||||
|  | + * generally faster than AES256 on CPU w/o dedicated AES instructions, | ||||||
|  | + * having the same key size. | ||||||
|  | + * Compiling in will add ~5,5kB to binary size on x86-64 */ | ||||||
|  | +#define DROPBEAR_CHACHA20POLY1305 1 | ||||||
|  | + | ||||||
|  |  /* Message integrity. sha2-256 is recommended as a default,  | ||||||
|  |     sha1 for compatibility */ | ||||||
|  |  #define DROPBEAR_SHA1_HMAC 1 | ||||||
|  | diff --git a/libtomcrypt/src/headers/tomcrypt_dropbear.h b/libtomcrypt/src/headers/tomcrypt_dropbear.h | ||||||
|  | index b0ce45b..59960e5 100644 | ||||||
|  | --- a/libtomcrypt/src/headers/tomcrypt_dropbear.h | ||||||
|  | +++ b/libtomcrypt/src/headers/tomcrypt_dropbear.h | ||||||
|  | @@ -35,6 +35,10 @@ | ||||||
|  |  #define LTC_CTR_MODE | ||||||
|  |  #endif | ||||||
|  |   | ||||||
|  | +#if DROPBEAR_CHACHA20POLY1305 | ||||||
|  | +#define LTC_CHACHA | ||||||
|  | +#define LTC_POLY1305 | ||||||
|  | +#endif | ||||||
|  |   | ||||||
|  |  #if DROPBEAR_SHA512 | ||||||
|  |  #define LTC_SHA512 | ||||||
|  | diff --git a/packet.c b/packet.c | ||||||
|  | index 9fda0d6..0454726 100644 | ||||||
|  | --- a/packet.c | ||||||
|  | +++ b/packet.c | ||||||
|  | @@ -215,7 +215,7 @@ static int read_packet_init() { | ||||||
|  |   | ||||||
|  |  	unsigned int maxlen; | ||||||
|  |  	int slen; | ||||||
|  | -	unsigned int len; | ||||||
|  | +	unsigned int len, plen; | ||||||
|  |  	unsigned int blocksize; | ||||||
|  |  	unsigned int macsize; | ||||||
|  |   | ||||||
|  | @@ -254,21 +254,35 @@ static int read_packet_init() { | ||||||
|  |  	/* 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.readbuf, blocksize), | ||||||
|  | -				blocksize, | ||||||
|  | -				&ses.keys->recv.cipher_state) != CRYPT_OK) { | ||||||
|  | -		dropbear_exit("Error decrypting"); | ||||||
|  | +#if DROPBEAR_AEAD_MODE | ||||||
|  | +	if (ses.keys->recv.crypt_mode->aead_crypt) { | ||||||
|  | +		if (ses.keys->recv.crypt_mode->aead_getlength(ses.recvseq, | ||||||
|  | +					buf_getptr(ses.readbuf, blocksize), &plen, | ||||||
|  | +					blocksize, | ||||||
|  | +					&ses.keys->recv.cipher_state) != CRYPT_OK) { | ||||||
|  | +			dropbear_exit("Error decrypting"); | ||||||
|  | +		} | ||||||
|  | +		len = plen + 4 + macsize; | ||||||
|  | +	} else | ||||||
|  | +#endif | ||||||
|  | +	{ | ||||||
|  | +		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) { | ||||||
|  | +			dropbear_exit("Error decrypting"); | ||||||
|  | +		} | ||||||
|  | +		plen = buf_getint(ses.readbuf) + 4; | ||||||
|  | +		len = plen + macsize; | ||||||
|  |  	} | ||||||
|  | -	len = buf_getint(ses.readbuf) + 4 + macsize; | ||||||
|  |   | ||||||
|  |  	TRACE2(("packet size is %u, block %u mac %u", len, blocksize, macsize)) | ||||||
|  |   | ||||||
|  |   | ||||||
|  |  	/* check packet length */ | ||||||
|  |  	if ((len > RECV_MAX_PACKET_LEN) || | ||||||
|  | -		(len < MIN_PACKET_LEN + macsize) || | ||||||
|  | -		((len - macsize) % blocksize != 0)) { | ||||||
|  | +		(plen < blocksize) || | ||||||
|  | +		(plen % blocksize != 0)) { | ||||||
|  |  		dropbear_exit("Integrity error (bad packet size %u)", len); | ||||||
|  |  	} | ||||||
|  |   | ||||||
|  | @@ -294,23 +308,42 @@ void decrypt_packet() { | ||||||
|  |   | ||||||
|  |  	ses.kexstate.datarecv += ses.readbuf->len; | ||||||
|  |   | ||||||
|  | -	/* we've already decrypted the first blocksize in read_packet_init */ | ||||||
|  | -	buf_setpos(ses.readbuf, blocksize); | ||||||
|  | - | ||||||
|  | -	/* decrypt it in-place */ | ||||||
|  | -	len = ses.readbuf->len - macsize - ses.readbuf->pos; | ||||||
|  | -	if (ses.keys->recv.crypt_mode->decrypt( | ||||||
|  | -				buf_getptr(ses.readbuf, len),  | ||||||
|  | -				buf_getwriteptr(ses.readbuf, len), | ||||||
|  | -				len, | ||||||
|  | -				&ses.keys->recv.cipher_state) != CRYPT_OK) { | ||||||
|  | -		dropbear_exit("Error decrypting"); | ||||||
|  | -	} | ||||||
|  | -	buf_incrpos(ses.readbuf, len); | ||||||
|  | +#if DROPBEAR_AEAD_MODE | ||||||
|  | +	if (ses.keys->recv.crypt_mode->aead_crypt) { | ||||||
|  | +		/* first blocksize is not decrypted yet */ | ||||||
|  | +		buf_setpos(ses.readbuf, 0); | ||||||
|  | + | ||||||
|  | +		/* decrypt it in-place */ | ||||||
|  | +		len = ses.readbuf->len - macsize - ses.readbuf->pos; | ||||||
|  | +		if (ses.keys->recv.crypt_mode->aead_crypt(ses.recvseq, | ||||||
|  | +					buf_getptr(ses.readbuf, len + macsize), | ||||||
|  | +					buf_getwriteptr(ses.readbuf, len), | ||||||
|  | +					len, macsize, | ||||||
|  | +					&ses.keys->recv.cipher_state, LTC_DECRYPT) != CRYPT_OK) { | ||||||
|  | +			dropbear_exit("Error decrypting"); | ||||||
|  | +		} | ||||||
|  | +		buf_incrpos(ses.readbuf, len); | ||||||
|  | +	} else | ||||||
|  | +#endif | ||||||
|  | +	{ | ||||||
|  | +		/* we've already decrypted the first blocksize in read_packet_init */ | ||||||
|  | +		buf_setpos(ses.readbuf, blocksize); | ||||||
|  | + | ||||||
|  | +		/* decrypt it in-place */ | ||||||
|  | +		len = ses.readbuf->len - macsize - ses.readbuf->pos; | ||||||
|  | +		if (ses.keys->recv.crypt_mode->decrypt( | ||||||
|  | +					buf_getptr(ses.readbuf, len),  | ||||||
|  | +					buf_getwriteptr(ses.readbuf, len), | ||||||
|  | +					len, | ||||||
|  | +					&ses.keys->recv.cipher_state) != CRYPT_OK) { | ||||||
|  | +			dropbear_exit("Error decrypting"); | ||||||
|  | +		} | ||||||
|  | +		buf_incrpos(ses.readbuf, len); | ||||||
|  |   | ||||||
|  | -	/* check the hmac */ | ||||||
|  | -	if (checkmac() != DROPBEAR_SUCCESS) { | ||||||
|  | -		dropbear_exit("Integrity error"); | ||||||
|  | +		/* check the hmac */ | ||||||
|  | +		if (checkmac() != DROPBEAR_SUCCESS) { | ||||||
|  | +			dropbear_exit("Integrity error"); | ||||||
|  | +		} | ||||||
|  |  	} | ||||||
|  |   | ||||||
|  |  	/* get padding length */ | ||||||
|  | @@ -557,9 +590,16 @@ void encrypt_packet() { | ||||||
|  |  	buf_setpos(ses.writepayload, 0); | ||||||
|  |  	buf_setlen(ses.writepayload, 0); | ||||||
|  |   | ||||||
|  | -	/* length of padding - packet length must be a multiple of blocksize, | ||||||
|  | -	 * with a minimum of 4 bytes of padding */ | ||||||
|  | -	padlen = blocksize - (writebuf->len) % blocksize; | ||||||
|  | +	/* length of padding - packet length excluding the packetlength uint32 | ||||||
|  | +	 * field in aead mode must be a multiple of blocksize, with a minimum of | ||||||
|  | +	 * 4 bytes of padding */ | ||||||
|  | +	len = writebuf->len; | ||||||
|  | +#if DROPBEAR_AEAD_MODE | ||||||
|  | +	if (ses.keys->trans.crypt_mode->aead_crypt) { | ||||||
|  | +		len -= 4; | ||||||
|  | +	} | ||||||
|  | +#endif | ||||||
|  | +	padlen = blocksize - len % blocksize; | ||||||
|  |  	if (padlen < 4) { | ||||||
|  |  		padlen += blocksize; | ||||||
|  |  	} | ||||||
|  | @@ -579,23 +619,42 @@ void encrypt_packet() { | ||||||
|  |  	buf_incrlen(writebuf, padlen); | ||||||
|  |  	genrandom(buf_getptr(writebuf, padlen), padlen); | ||||||
|  |   | ||||||
|  | -	make_mac(ses.transseq, &ses.keys->trans, writebuf, writebuf->len, mac_bytes); | ||||||
|  | +#if DROPBEAR_AEAD_MODE | ||||||
|  | +	if (ses.keys->trans.crypt_mode->aead_crypt) { | ||||||
|  | +		/* do the actual encryption, in-place */ | ||||||
|  | +		buf_setpos(writebuf, 0); | ||||||
|  | +		/* encrypt it in-place*/ | ||||||
|  | +		len = writebuf->len; | ||||||
|  | +		buf_incrlen(writebuf, mac_size); | ||||||
|  | +		if (ses.keys->trans.crypt_mode->aead_crypt(ses.transseq, | ||||||
|  | +					buf_getptr(writebuf, len), | ||||||
|  | +					buf_getwriteptr(writebuf, len + mac_size), | ||||||
|  | +					len, mac_size, | ||||||
|  | +					&ses.keys->trans.cipher_state, LTC_ENCRYPT) != CRYPT_OK) { | ||||||
|  | +			dropbear_exit("Error encrypting"); | ||||||
|  | +		} | ||||||
|  | +		buf_incrpos(writebuf, len + mac_size); | ||||||
|  | +	} else | ||||||
|  | +#endif | ||||||
|  | +	{ | ||||||
|  | +		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( | ||||||
|  | +					buf_getptr(writebuf, len), | ||||||
|  | +					buf_getwriteptr(writebuf, len), | ||||||
|  | +					len, | ||||||
|  | +					&ses.keys->trans.cipher_state) != CRYPT_OK) { | ||||||
|  | +			dropbear_exit("Error encrypting"); | ||||||
|  | +		} | ||||||
|  | +		buf_incrpos(writebuf, len); | ||||||
|  |   | ||||||
|  | -	/* do the actual encryption, in-place */ | ||||||
|  | -	buf_setpos(writebuf, 0); | ||||||
|  | -	/* encrypt it in-place*/ | ||||||
|  | -	len = writebuf->len; | ||||||
|  | -	if (ses.keys->trans.crypt_mode->encrypt( | ||||||
|  | -				buf_getptr(writebuf, len), | ||||||
|  | -				buf_getwriteptr(writebuf, len), | ||||||
|  | -				len, | ||||||
|  | -				&ses.keys->trans.cipher_state) != CRYPT_OK) { | ||||||
|  | -		dropbear_exit("Error encrypting"); | ||||||
|  | +		/* stick the MAC on it */ | ||||||
|  | +		buf_putbytes(writebuf, mac_bytes, mac_size); | ||||||
|  |  	} | ||||||
|  | -	buf_incrpos(writebuf, len); | ||||||
|  | - | ||||||
|  | -	/* stick the MAC on it */ | ||||||
|  | -	buf_putbytes(writebuf, mac_bytes, mac_size); | ||||||
|  |   | ||||||
|  |  	/* Update counts */ | ||||||
|  |  	ses.kexstate.datatrans += writebuf->len; | ||||||
|  | diff --git a/session.h b/session.h | ||||||
|  | index e436882..a8f8914 100644 | ||||||
|  | --- a/session.h | ||||||
|  | +++ b/session.h | ||||||
|  | @@ -41,6 +41,7 @@ | ||||||
|  |  #include "chansession.h" | ||||||
|  |  #include "dbutil.h" | ||||||
|  |  #include "netio.h" | ||||||
|  | +#include "chachapoly.h" | ||||||
|  |   | ||||||
|  |  void common_session_init(int sock_in, int sock_out); | ||||||
|  |  void session_loop(void(*loophandler)(void)) ATTRIB_NORETURN; | ||||||
|  | @@ -80,6 +81,9 @@ struct key_context_directional { | ||||||
|  |  		symmetric_CBC cbc; | ||||||
|  |  #if DROPBEAR_ENABLE_CTR_MODE | ||||||
|  |  		symmetric_CTR ctr; | ||||||
|  | +#endif | ||||||
|  | +#if DROPBEAR_CHACHA20POLY1305 | ||||||
|  | +		dropbear_chachapoly_state chachapoly; | ||||||
|  |  #endif | ||||||
|  |  	} cipher_state; | ||||||
|  |  	unsigned char mackey[MAX_MAC_LEN]; | ||||||
|  | diff --git a/sysoptions.h b/sysoptions.h | ||||||
|  | index 2c27caf..2432779 100644 | ||||||
|  | --- a/sysoptions.h | ||||||
|  | +++ b/sysoptions.h | ||||||
|  | @@ -92,7 +92,11 @@ | ||||||
|  |  #define MD5_HASH_SIZE 16 | ||||||
|  |  #define MAX_HASH_SIZE 64 /* sha512 */ | ||||||
|  |   | ||||||
|  | +#if DROPBEAR_CHACHA20POLY1305 | ||||||
|  | +#define MAX_KEY_LEN 64 /* 2 x 256 bits for chacha20 */ | ||||||
|  | +#else | ||||||
|  |  #define MAX_KEY_LEN 32 /* 256 bits for aes256 etc */ | ||||||
|  | +#endif | ||||||
|  |  #define MAX_IV_LEN 20 /* must be same as max blocksize,  */ | ||||||
|  |   | ||||||
|  |  #if DROPBEAR_SHA2_512_HMAC | ||||||
|  | @@ -207,6 +211,8 @@ If you test it please contact the Dropbear author */ | ||||||
|  |   | ||||||
|  |  #define DROPBEAR_TWOFISH ((DROPBEAR_TWOFISH256) || (DROPBEAR_TWOFISH128)) | ||||||
|  |   | ||||||
|  | +#define DROPBEAR_AEAD_MODE ((DROPBEAR_CHACHA20POLY1305)) | ||||||
|  | + | ||||||
|  |  #define DROPBEAR_CLI_ANYTCPFWD ((DROPBEAR_CLI_REMOTETCPFWD) || (DROPBEAR_CLI_LOCALTCPFWD)) | ||||||
|  |   | ||||||
|  |  #define DROPBEAR_TCP_ACCEPT ((DROPBEAR_CLI_LOCALTCPFWD) || (DROPBEAR_SVR_REMOTETCPFWD)) | ||||||
|  | @@ -249,7 +255,7 @@ If you test it please contact the Dropbear author */ | ||||||
|  |  #endif | ||||||
|  |   | ||||||
|  |  #if !(DROPBEAR_AES128 || DROPBEAR_3DES || DROPBEAR_AES256 || DROPBEAR_BLOWFISH \ | ||||||
|  | -      || DROPBEAR_TWOFISH256 || DROPBEAR_TWOFISH128) | ||||||
|  | +      || DROPBEAR_TWOFISH256 || DROPBEAR_TWOFISH128 || DROPBEAR_CHACHA20POLY1305) | ||||||
|  |  	#error "At least one encryption algorithm must be enabled. AES128 is recommended." | ||||||
|  |  #endif | ||||||
|  |   | ||||||
|  | --  | ||||||
|  | 2.17.1 | ||||||
|  |  | ||||||
		Reference in New Issue
	
	Block a user