diff options
Diffstat (limited to 'package/network/services/dropbear/patches/021-backport-chacha20-poly1305-support.patch')
-rw-r--r-- | package/network/services/dropbear/patches/021-backport-chacha20-poly1305-support.patch | 693 |
1 files changed, 0 insertions, 693 deletions
diff --git a/package/network/services/dropbear/patches/021-backport-chacha20-poly1305-support.patch b/package/network/services/dropbear/patches/021-backport-chacha20-poly1305-support.patch deleted file mode 100644 index 2120b4593e..0000000000 --- a/package/network/services/dropbear/patches/021-backport-chacha20-poly1305-support.patch +++ /dev/null @@ -1,693 +0,0 @@ -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 - |