[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Missing signed-off for pkg chacha20 patches


Hi Jon,

I'm currently working on chacha20 to merge Aris his work. There are two pkd 
patches from you which don't have a Signed-off-by tag from you.

Could you please give me the permission to add it or send the attached patch 
back with them?

Also, could you test this patchset?


Thanks,


	Andreas
From 22c4fbb136fa315cdcbae762a0488af310231517 Mon Sep 17 00:00:00 2001
From: Aris Adamantiadis <aris@xxxxxxxxxxxx>
Date: Wed, 28 Feb 2018 10:24:51 -0600
Subject: [PATCH 01/12] external: Add ChaCha and Poly1305 implementations from
 OpenSSH

Signed-off-by: Aris Adamantiadis <aris@xxxxxxxxxxxx>
Reviewed-by: Andreas Schneider <asn@xxxxxxxxx>
---
 ConfigureChecks.cmake     |   1 +
 config.h.cmake            |   3 +
 include/libssh/chacha.h   |  32 ++++++
 include/libssh/poly1305.h |  18 ++++
 src/CMakeLists.txt        |   2 +
 src/external/chacha.c     | 218 ++++++++++++++++++++++++++++++++++++++
 src/external/poly1305.c   | 156 +++++++++++++++++++++++++++
 7 files changed, 430 insertions(+)
 create mode 100644 include/libssh/chacha.h
 create mode 100644 include/libssh/poly1305.h
 create mode 100644 src/external/chacha.c
 create mode 100644 src/external/poly1305.c

diff --git a/ConfigureChecks.cmake b/ConfigureChecks.cmake
index 4f0ecf8a..2e1348f1 100644
--- a/ConfigureChecks.cmake
+++ b/ConfigureChecks.cmake
@@ -56,6 +56,7 @@ check_include_file(pty.h HAVE_PTY_H)
 check_include_file(utmp.h HAVE_UTMP_H)
 check_include_file(termios.h HAVE_TERMIOS_H)
 check_include_file(unistd.h HAVE_UNISTD_H)
+check_include_file(stdint.h HAVE_STDINT_H)
 check_include_file(util.h HAVE_UTIL_H)
 check_include_file(libutil.h HAVE_LIBUTIL_H)
 check_include_file(sys/time.h HAVE_SYS_TIME_H)
diff --git a/config.h.cmake b/config.h.cmake
index 50a50ed7..e8786b1e 100644
--- a/config.h.cmake
+++ b/config.h.cmake
@@ -50,6 +50,9 @@
 /* Define to 1 if you have the <unistd.h> header file. */
 #cmakedefine HAVE_UNISTD_H 1
 
+/* Define to 1 if you have the <stdint.h> header file. */
+#cmakedefine HAVE_STDINT_H 1
+
 /* Define to 1 if you have the <openssl/aes.h> header file. */
 #cmakedefine HAVE_OPENSSL_AES_H 1
 
diff --git a/include/libssh/chacha.h b/include/libssh/chacha.h
new file mode 100644
index 00000000..84ff66a2
--- /dev/null
+++ b/include/libssh/chacha.h
@@ -0,0 +1,32 @@
+/* $OpenBSD: chacha.h,v 1.3 2014/05/02 03:27:54 djm Exp $ */
+
+/*
+chacha-merged.c version 20080118
+D. J. Bernstein
+Public domain.
+*/
+
+#ifndef CHACHA_H
+#define CHACHA_H
+
+struct chacha_ctx {
+    uint32_t input[16];
+};
+
+#define CHACHA_MINKEYLEN  16
+#define CHACHA_NONCELEN   8
+#define CHACHA_CTRLEN     8
+#define CHACHA_STATELEN   (CHACHA_NONCELEN+CHACHA_CTRLEN)
+#define CHACHA_BLOCKLEN   64
+
+void chacha_keysetup(struct chacha_ctx *x, const uint8_t *k, uint32_t kbits)
+    __attribute__((__bounded__(__minbytes__, 2, CHACHA_MINKEYLEN)));
+void chacha_ivsetup(struct chacha_ctx *x, const uint8_t *iv, const uint8_t *ctr)
+    __attribute__((__bounded__(__minbytes__, 2, CHACHA_NONCELEN)))
+    __attribute__((__bounded__(__minbytes__, 3, CHACHA_CTRLEN)));
+void chacha_encrypt_bytes(struct chacha_ctx *x, const uint8_t *m,
+    uint8_t *c, uint32_t bytes)
+    __attribute__((__bounded__(__buffer__, 2, 4)))
+    __attribute__((__bounded__(__buffer__, 3, 4)));
+
+#endif    /* CHACHA_H */
diff --git a/include/libssh/poly1305.h b/include/libssh/poly1305.h
new file mode 100644
index 00000000..7126ecbf
--- /dev/null
+++ b/include/libssh/poly1305.h
@@ -0,0 +1,18 @@
+/*
+ * Public Domain poly1305 from Andrew Moon
+ * poly1305-donna-unrolled.c from https://github.com/floodyberry/poly1305-donna
+ */
+
+#ifndef POLY1305_H
+#define POLY1305_H
+
+#define POLY1305_KEYLEN    32
+#define POLY1305_TAGLEN    16
+
+void poly1305_auth(uint8_t out[POLY1305_TAGLEN], const uint8_t *m, size_t inlen,
+    const uint8_t key[POLY1305_KEYLEN])
+    __attribute__((__bounded__(__minbytes__, 1, POLY1305_TAGLEN)))
+    __attribute__((__bounded__(__buffer__, 2, 3)))
+    __attribute__((__bounded__(__minbytes__, 4, POLY1305_KEYLEN)));
+
+#endif	/* POLY1305_H */
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 7ecee06c..edbf3520 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -158,9 +158,11 @@ set(libssh_SRCS
   wrapper.c
   external/bcrypt_pbkdf.c
   external/blowfish.c
+  external/chacha.c
   external/ed25519.c
   external/fe25519.c
   external/ge25519.c
+  external/poly1305.c
   external/sc25519.c
 )
 
diff --git a/src/external/chacha.c b/src/external/chacha.c
new file mode 100644
index 00000000..062aafb8
--- /dev/null
+++ b/src/external/chacha.c
@@ -0,0 +1,218 @@
+/*
+chacha-merged.c version 20080118
+D. J. Bernstein
+Public domain.
+ */
+
+#include <stdint.h>
+#include <unistd.h>
+#include <sys/types.h>
+
+#include "libssh/chacha.h"
+
+typedef unsigned int uint32_t;
+
+typedef struct chacha_ctx chacha_ctx;
+
+#define U8C(v) (v##U)
+#define U32C(v) (v##U)
+
+#define U8V(v) ((uint8_t)(v) & U8C(0xFF))
+#define U32V(v) ((uint32_t)(v) & U32C(0xFFFFFFFF))
+
+#define ROTL32(v, n) \
+        (U32V((v) << (n)) | ((v) >> (32 - (n))))
+
+#define U8TO32_LITTLE(p) \
+        (((uint32_t)((p)[0])      ) | \
+         ((uint32_t)((p)[1]) <<  8) | \
+         ((uint32_t)((p)[2]) << 16) | \
+         ((uint32_t)((p)[3]) << 24))
+
+#define U32TO8_LITTLE(p, v) \
+        do { \
+            (p)[0] = U8V((v)      ); \
+            (p)[1] = U8V((v) >>  8); \
+            (p)[2] = U8V((v) >> 16); \
+            (p)[3] = U8V((v) >> 24); \
+        } while (0)
+
+#define ROTATE(v,c) (ROTL32(v,c))
+#define XOR(v,w) ((v) ^ (w))
+#define PLUS(v,w) (U32V((v) + (w)))
+#define PLUSONE(v) (PLUS((v),1))
+
+#define QUARTERROUND(a,b,c,d) \
+        a = PLUS(a,b); d = ROTATE(XOR(d,a),16); \
+        c = PLUS(c,d); b = ROTATE(XOR(b,c),12); \
+        a = PLUS(a,b); d = ROTATE(XOR(d,a), 8); \
+        c = PLUS(c,d); b = ROTATE(XOR(b,c), 7);
+
+static const char sigma[16] = "expand 32-byte k";
+static const char tau[16] = "expand 16-byte k";
+
+void
+chacha_keysetup(chacha_ctx *x,const uint8_t *k,uint32_t kbits)
+{
+    const char *constants;
+
+    x->input[4] = U8TO32_LITTLE(k + 0);
+    x->input[5] = U8TO32_LITTLE(k + 4);
+    x->input[6] = U8TO32_LITTLE(k + 8);
+    x->input[7] = U8TO32_LITTLE(k + 12);
+    if (kbits == 256) { /* recommended */
+        k += 16;
+        constants = sigma;
+    } else { /* kbits == 128 */
+        constants = tau;
+    }
+    x->input[8] = U8TO32_LITTLE(k + 0);
+    x->input[9] = U8TO32_LITTLE(k + 4);
+    x->input[10] = U8TO32_LITTLE(k + 8);
+    x->input[11] = U8TO32_LITTLE(k + 12);
+    x->input[0] = U8TO32_LITTLE(constants + 0);
+    x->input[1] = U8TO32_LITTLE(constants + 4);
+    x->input[2] = U8TO32_LITTLE(constants + 8);
+    x->input[3] = U8TO32_LITTLE(constants + 12);
+}
+
+void
+chacha_ivsetup(chacha_ctx *x, const uint8_t *iv, const uint8_t *counter)
+{
+    x->input[12] = counter == NULL ? 0 : U8TO32_LITTLE(counter + 0);
+    x->input[13] = counter == NULL ? 0 : U8TO32_LITTLE(counter + 4);
+    x->input[14] = U8TO32_LITTLE(iv + 0);
+    x->input[15] = U8TO32_LITTLE(iv + 4);
+}
+
+void
+chacha_encrypt_bytes(chacha_ctx *x,const uint8_t *m,uint8_t *c,uint32_t bytes)
+{
+    uint32_t x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15;
+    uint32_t j0, j1, j2, j3, j4, j5, j6, j7, j8, j9, j10, j11, j12, j13, j14, j15;
+    uint8_t *ctarget = NULL;
+    uint8_t tmp[64];
+    u_int i;
+
+    if (!bytes) return;
+
+    j0 = x->input[0];
+    j1 = x->input[1];
+    j2 = x->input[2];
+    j3 = x->input[3];
+    j4 = x->input[4];
+    j5 = x->input[5];
+    j6 = x->input[6];
+    j7 = x->input[7];
+    j8 = x->input[8];
+    j9 = x->input[9];
+    j10 = x->input[10];
+    j11 = x->input[11];
+    j12 = x->input[12];
+    j13 = x->input[13];
+    j14 = x->input[14];
+    j15 = x->input[15];
+
+    for (;;) {
+        if (bytes < 64) {
+            for (i = 0;i < bytes;++i) tmp[i] = m[i];
+            m = tmp;
+            ctarget = c;
+            c = tmp;
+        }
+        x0 = j0;
+        x1 = j1;
+        x2 = j2;
+        x3 = j3;
+        x4 = j4;
+        x5 = j5;
+        x6 = j6;
+        x7 = j7;
+        x8 = j8;
+        x9 = j9;
+        x10 = j10;
+        x11 = j11;
+        x12 = j12;
+        x13 = j13;
+        x14 = j14;
+        x15 = j15;
+        for (i = 20;i > 0;i -= 2) {
+            QUARTERROUND( x0, x4, x8,x12)
+                      QUARTERROUND( x1, x5, x9,x13)
+                      QUARTERROUND( x2, x6,x10,x14)
+                      QUARTERROUND( x3, x7,x11,x15)
+                      QUARTERROUND( x0, x5,x10,x15)
+                      QUARTERROUND( x1, x6,x11,x12)
+                      QUARTERROUND( x2, x7, x8,x13)
+                      QUARTERROUND( x3, x4, x9,x14)
+        }
+        x0 = PLUS(x0,j0);
+        x1 = PLUS(x1,j1);
+        x2 = PLUS(x2,j2);
+        x3 = PLUS(x3,j3);
+        x4 = PLUS(x4,j4);
+        x5 = PLUS(x5,j5);
+        x6 = PLUS(x6,j6);
+        x7 = PLUS(x7,j7);
+        x8 = PLUS(x8,j8);
+        x9 = PLUS(x9,j9);
+        x10 = PLUS(x10,j10);
+        x11 = PLUS(x11,j11);
+        x12 = PLUS(x12,j12);
+        x13 = PLUS(x13,j13);
+        x14 = PLUS(x14,j14);
+        x15 = PLUS(x15,j15);
+
+        x0 = XOR(x0,U8TO32_LITTLE(m + 0));
+        x1 = XOR(x1,U8TO32_LITTLE(m + 4));
+        x2 = XOR(x2,U8TO32_LITTLE(m + 8));
+        x3 = XOR(x3,U8TO32_LITTLE(m + 12));
+        x4 = XOR(x4,U8TO32_LITTLE(m + 16));
+        x5 = XOR(x5,U8TO32_LITTLE(m + 20));
+        x6 = XOR(x6,U8TO32_LITTLE(m + 24));
+        x7 = XOR(x7,U8TO32_LITTLE(m + 28));
+        x8 = XOR(x8,U8TO32_LITTLE(m + 32));
+        x9 = XOR(x9,U8TO32_LITTLE(m + 36));
+        x10 = XOR(x10,U8TO32_LITTLE(m + 40));
+        x11 = XOR(x11,U8TO32_LITTLE(m + 44));
+        x12 = XOR(x12,U8TO32_LITTLE(m + 48));
+        x13 = XOR(x13,U8TO32_LITTLE(m + 52));
+        x14 = XOR(x14,U8TO32_LITTLE(m + 56));
+        x15 = XOR(x15,U8TO32_LITTLE(m + 60));
+
+        j12 = PLUSONE(j12);
+        if (!j12) {
+            j13 = PLUSONE(j13);
+            /* stopping at 2^70 bytes per nonce is user's responsibility */
+        }
+
+        U32TO8_LITTLE(c + 0,x0);
+        U32TO8_LITTLE(c + 4,x1);
+        U32TO8_LITTLE(c + 8,x2);
+        U32TO8_LITTLE(c + 12,x3);
+        U32TO8_LITTLE(c + 16,x4);
+        U32TO8_LITTLE(c + 20,x5);
+        U32TO8_LITTLE(c + 24,x6);
+        U32TO8_LITTLE(c + 28,x7);
+        U32TO8_LITTLE(c + 32,x8);
+        U32TO8_LITTLE(c + 36,x9);
+        U32TO8_LITTLE(c + 40,x10);
+        U32TO8_LITTLE(c + 44,x11);
+        U32TO8_LITTLE(c + 48,x12);
+        U32TO8_LITTLE(c + 52,x13);
+        U32TO8_LITTLE(c + 56,x14);
+        U32TO8_LITTLE(c + 60,x15);
+
+        if (bytes <= 64) {
+            if (bytes < 64) {
+                for (i = 0;i < bytes;++i) ctarget[i] = c[i];
+            }
+            x->input[12] = j12;
+            x->input[13] = j13;
+            return;
+        }
+        bytes -= 64;
+        c += 64;
+        m += 64;
+    }
+}
diff --git a/src/external/poly1305.c b/src/external/poly1305.c
new file mode 100644
index 00000000..916dd625
--- /dev/null
+++ b/src/external/poly1305.c
@@ -0,0 +1,156 @@
+/*
+ * Public Domain poly1305 from Andrew Moon
+ * poly1305-donna-unrolled.c from https://github.com/floodyberry/poly1305-donna
+ */
+
+#include "config.h"
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include "libssh/poly1305.h"
+
+#define mul32x32_64(a,b) ((uint64_t)(a) * (b))
+
+#define U8TO32_LE(p) \
+    (((uint32_t)((p)[0])) | \
+     ((uint32_t)((p)[1]) <<  8) | \
+     ((uint32_t)((p)[2]) << 16) | \
+     ((uint32_t)((p)[3]) << 24))
+
+#define U32TO8_LE(p, v) \
+    do { \
+        (p)[0] = (uint8_t)((v)); \
+        (p)[1] = (uint8_t)((v) >>  8); \
+        (p)[2] = (uint8_t)((v) >> 16); \
+        (p)[3] = (uint8_t)((v) >> 24); \
+    } while (0)
+
+void
+poly1305_auth(unsigned char out[POLY1305_TAGLEN], const unsigned char *m, size_t inlen, const unsigned char key[POLY1305_KEYLEN]) {
+    uint32_t t0,t1,t2,t3;
+    uint32_t h0,h1,h2,h3,h4;
+    uint32_t r0,r1,r2,r3,r4;
+    uint32_t s1,s2,s3,s4;
+    uint32_t b, nb;
+    size_t j;
+    uint64_t t[5];
+    uint64_t f0,f1,f2,f3;
+    uint32_t g0,g1,g2,g3,g4;
+    uint64_t c;
+    unsigned char mp[16];
+
+    /* clamp key */
+    t0 = U8TO32_LE(key+0);
+    t1 = U8TO32_LE(key+4);
+    t2 = U8TO32_LE(key+8);
+    t3 = U8TO32_LE(key+12);
+
+    /* precompute multipliers */
+    r0 = t0 & 0x3ffffff; t0 >>= 26; t0 |= t1 << 6;
+    r1 = t0 & 0x3ffff03; t1 >>= 20; t1 |= t2 << 12;
+    r2 = t1 & 0x3ffc0ff; t2 >>= 14; t2 |= t3 << 18;
+    r3 = t2 & 0x3f03fff; t3 >>= 8;
+    r4 = t3 & 0x00fffff;
+
+    s1 = r1 * 5;
+    s2 = r2 * 5;
+    s3 = r3 * 5;
+    s4 = r4 * 5;
+
+    /* init state */
+    h0 = 0;
+    h1 = 0;
+    h2 = 0;
+    h3 = 0;
+    h4 = 0;
+
+    /* full blocks */
+    if (inlen < 16) goto poly1305_donna_atmost15bytes;
+poly1305_donna_16bytes:
+    m += 16;
+    inlen -= 16;
+
+    t0 = U8TO32_LE(m-16);
+    t1 = U8TO32_LE(m-12);
+    t2 = U8TO32_LE(m-8);
+    t3 = U8TO32_LE(m-4);
+
+    h0 += t0 & 0x3ffffff;
+    h1 += ((((uint64_t)t1 << 32) | t0) >> 26) & 0x3ffffff;
+    h2 += ((((uint64_t)t2 << 32) | t1) >> 20) & 0x3ffffff;
+    h3 += ((((uint64_t)t3 << 32) | t2) >> 14) & 0x3ffffff;
+    h4 += (t3 >> 8) | (1 << 24);
+
+
+poly1305_donna_mul:
+    t[0]  = mul32x32_64(h0,r0) + mul32x32_64(h1,s4) + mul32x32_64(h2,s3) + mul32x32_64(h3,s2) + mul32x32_64(h4,s1);
+    t[1]  = mul32x32_64(h0,r1) + mul32x32_64(h1,r0) + mul32x32_64(h2,s4) + mul32x32_64(h3,s3) + mul32x32_64(h4,s2);
+    t[2]  = mul32x32_64(h0,r2) + mul32x32_64(h1,r1) + mul32x32_64(h2,r0) + mul32x32_64(h3,s4) + mul32x32_64(h4,s3);
+    t[3]  = mul32x32_64(h0,r3) + mul32x32_64(h1,r2) + mul32x32_64(h2,r1) + mul32x32_64(h3,r0) + mul32x32_64(h4,s4);
+    t[4]  = mul32x32_64(h0,r4) + mul32x32_64(h1,r3) + mul32x32_64(h2,r2) + mul32x32_64(h3,r1) + mul32x32_64(h4,r0);
+
+                    h0 = (uint32_t)t[0] & 0x3ffffff; c =           (t[0] >> 26);
+    t[1] += c;      h1 = (uint32_t)t[1] & 0x3ffffff; b = (uint32_t)(t[1] >> 26);
+    t[2] += b;      h2 = (uint32_t)t[2] & 0x3ffffff; b = (uint32_t)(t[2] >> 26);
+    t[3] += b;      h3 = (uint32_t)t[3] & 0x3ffffff; b = (uint32_t)(t[3] >> 26);
+    t[4] += b;      h4 = (uint32_t)t[4] & 0x3ffffff; b = (uint32_t)(t[4] >> 26);
+    h0 += b * 5;
+
+    if (inlen >= 16) goto poly1305_donna_16bytes;
+
+    /* final bytes */
+poly1305_donna_atmost15bytes:
+    if (!inlen) goto poly1305_donna_finish;
+
+    for (j = 0; j < inlen; j++) mp[j] = m[j];
+    mp[j++] = 1;
+    for (; j < 16; j++)    mp[j] = 0;
+    inlen = 0;
+
+    t0 = U8TO32_LE(mp+0);
+    t1 = U8TO32_LE(mp+4);
+    t2 = U8TO32_LE(mp+8);
+    t3 = U8TO32_LE(mp+12);
+
+    h0 += t0 & 0x3ffffff;
+    h1 += ((((uint64_t)t1 << 32) | t0) >> 26) & 0x3ffffff;
+    h2 += ((((uint64_t)t2 << 32) | t1) >> 20) & 0x3ffffff;
+    h3 += ((((uint64_t)t3 << 32) | t2) >> 14) & 0x3ffffff;
+    h4 += (t3 >> 8);
+
+    goto poly1305_donna_mul;
+
+poly1305_donna_finish:
+                 b = h0 >> 26; h0 = h0 & 0x3ffffff;
+    h1 +=     b; b = h1 >> 26; h1 = h1 & 0x3ffffff;
+    h2 +=     b; b = h2 >> 26; h2 = h2 & 0x3ffffff;
+    h3 +=     b; b = h3 >> 26; h3 = h3 & 0x3ffffff;
+    h4 +=     b; b = h4 >> 26; h4 = h4 & 0x3ffffff;
+    h0 += b * 5; b = h0 >> 26; h0 = h0 & 0x3ffffff;
+    h1 +=     b;
+
+    g0 = h0 + 5; b = g0 >> 26; g0 &= 0x3ffffff;
+    g1 = h1 + b; b = g1 >> 26; g1 &= 0x3ffffff;
+    g2 = h2 + b; b = g2 >> 26; g2 &= 0x3ffffff;
+    g3 = h3 + b; b = g3 >> 26; g3 &= 0x3ffffff;
+    g4 = h4 + b - (1 << 26);
+
+    b = (g4 >> 31) - 1;
+    nb = ~b;
+    h0 = (h0 & nb) | (g0 & b);
+    h1 = (h1 & nb) | (g1 & b);
+    h2 = (h2 & nb) | (g2 & b);
+    h3 = (h3 & nb) | (g3 & b);
+    h4 = (h4 & nb) | (g4 & b);
+
+    f0 = ((h0      ) | (h1 << 26)) + (uint64_t)U8TO32_LE(&key[16]);
+    f1 = ((h1 >>  6) | (h2 << 20)) + (uint64_t)U8TO32_LE(&key[20]);
+    f2 = ((h2 >> 12) | (h3 << 14)) + (uint64_t)U8TO32_LE(&key[24]);
+    f3 = ((h3 >> 18) | (h4 <<  8)) + (uint64_t)U8TO32_LE(&key[28]);
+
+    U32TO8_LE(&out[ 0], f0); f1 += (f0 >> 32);
+    U32TO8_LE(&out[ 4], f1); f2 += (f1 >> 32);
+    U32TO8_LE(&out[ 8], f2); f3 += (f2 >> 32);
+    U32TO8_LE(&out[12], f3);
+}
-- 
2.17.1


From a48b7439a0807c1fc54e4dd69a8624481d394cf4 Mon Sep 17 00:00:00 2001
From: Aris Adamantiadis <aris@xxxxxxxxxxxx>
Date: Wed, 28 Feb 2018 10:24:52 -0600
Subject: [PATCH 02/12] cmake: detect "bounded" compiler attribute

Signed-off-by: Aris Adamantiadis <aris@xxxxxxxxxxxx>
Reviewed-by: Andreas Schneider <asn@xxxxxxxxxxxxxx>
---
 ConfigureChecks.cmake     |  5 +++++
 config.h.cmake            |  2 ++
 include/libssh/chacha.h   | 15 ++++++++++++---
 include/libssh/poly1305.h |  5 ++++-
 4 files changed, 23 insertions(+), 4 deletions(-)

diff --git a/ConfigureChecks.cmake b/ConfigureChecks.cmake
index 2e1348f1..fd8ff136 100644
--- a/ConfigureChecks.cmake
+++ b/ConfigureChecks.cmake
@@ -327,6 +327,11 @@ int main(void) {
 }" HAVE_COMPILER__FUNCTION__)
 
 
+check_c_source_compiles("
+void chacha_keysetup(struct chacha_ctx *x, const u_char *k, u_int kbits)
+    __attribute__((__bounded__(__minbytes__, 2, CHACHA_MINKEYLEN)));
+int main(void) { return 0; }" HAVE_GCC_BOUNDED_ATTRIBUTE)
+
 if (WITH_DEBUG_CRYPTO)
   set(DEBUG_CRYPTO 1)
 endif (WITH_DEBUG_CRYPTO)
diff --git a/config.h.cmake b/config.h.cmake
index e8786b1e..61d20acb 100644
--- a/config.h.cmake
+++ b/config.h.cmake
@@ -199,6 +199,8 @@
 #cmakedefine HAVE_COMPILER__FUNC__ 1
 #cmakedefine HAVE_COMPILER__FUNCTION__ 1
 
+#cmakedefine HAVE_GCC_BOUNDED_ATTRIBUTE 1
+
 /* Define to 1 if you want to enable GSSAPI */
 #cmakedefine WITH_GSSAPI 1
 
diff --git a/include/libssh/chacha.h b/include/libssh/chacha.h
index 84ff66a2..bac78c67 100644
--- a/include/libssh/chacha.h
+++ b/include/libssh/chacha.h
@@ -20,13 +20,22 @@ struct chacha_ctx {
 #define CHACHA_BLOCKLEN   64
 
 void chacha_keysetup(struct chacha_ctx *x, const uint8_t *k, uint32_t kbits)
-    __attribute__((__bounded__(__minbytes__, 2, CHACHA_MINKEYLEN)));
+#ifdef HAVE_GCC_BOUNDED_ATTRIBUTE
+    __attribute__((__bounded__(__minbytes__, 2, CHACHA_MINKEYLEN)))
+#endif
+    ;
 void chacha_ivsetup(struct chacha_ctx *x, const uint8_t *iv, const uint8_t *ctr)
+#ifdef HAVE_GCC_BOUNDED_ATTRIBUTE
     __attribute__((__bounded__(__minbytes__, 2, CHACHA_NONCELEN)))
-    __attribute__((__bounded__(__minbytes__, 3, CHACHA_CTRLEN)));
+    __attribute__((__bounded__(__minbytes__, 3, CHACHA_CTRLEN)))
+#endif
+    ;
 void chacha_encrypt_bytes(struct chacha_ctx *x, const uint8_t *m,
     uint8_t *c, uint32_t bytes)
+#ifdef HAVE_GCC_BOUNDED_ATTRIBUTE
     __attribute__((__bounded__(__buffer__, 2, 4)))
-    __attribute__((__bounded__(__buffer__, 3, 4)));
+    __attribute__((__bounded__(__buffer__, 3, 4)))
+#endif
+    ;
 
 #endif    /* CHACHA_H */
diff --git a/include/libssh/poly1305.h b/include/libssh/poly1305.h
index 7126ecbf..9174bd17 100644
--- a/include/libssh/poly1305.h
+++ b/include/libssh/poly1305.h
@@ -11,8 +11,11 @@
 
 void poly1305_auth(uint8_t out[POLY1305_TAGLEN], const uint8_t *m, size_t inlen,
     const uint8_t key[POLY1305_KEYLEN])
+#ifdef HAVE_GCC_BOUNDED_ATTRIBUTE
     __attribute__((__bounded__(__minbytes__, 1, POLY1305_TAGLEN)))
     __attribute__((__bounded__(__buffer__, 2, 3)))
-    __attribute__((__bounded__(__minbytes__, 4, POLY1305_KEYLEN)));
+    __attribute__((__bounded__(__minbytes__, 4, POLY1305_KEYLEN)))
+#endif
+    ;
 
 #endif	/* POLY1305_H */
-- 
2.17.1


From c4d6dbbbaa7172768247df79d5657255c7acf4e6 Mon Sep 17 00:00:00 2001
From: Aris Adamantiadis <aris@xxxxxxxxxxxx>
Date: Wed, 28 Feb 2018 10:24:53 -0600
Subject: [PATCH 03/12] chacha: packet encryption

Signed-off-by: Aris Adamantiadis <aris@xxxxxxxxxxxx>
---
 include/libssh/crypto.h    |   6 ++
 include/libssh/libcrypto.h |   1 +
 include/libssh/wrapper.h   |   3 +-
 src/CMakeLists.txt         |   1 +
 src/chachapoly.c           | 126 +++++++++++++++++++++++++++++++++++++
 src/dh.c                   |   3 +
 src/kex.c                  |   4 +-
 src/libcrypto.c            |  21 ++++++-
 src/packet.c               |  43 ++++++++-----
 src/packet_crypt.c         |  46 ++++++++------
 src/wrapper.c              |  96 ++++++++++++++++++++--------
 11 files changed, 288 insertions(+), 62 deletions(-)
 create mode 100644 src/chachapoly.c

diff --git a/include/libssh/crypto.h b/include/libssh/crypto.h
index fab39ed1..e6e5b8f6 100644
--- a/include/libssh/crypto.h
+++ b/include/libssh/crypto.h
@@ -128,10 +128,12 @@ struct ssh_cipher_struct {
     const char *name; /* ssh name of the algorithm */
     unsigned int blocksize; /* blocksize of the algo */
     enum ssh_cipher_e ciphertype;
+    uint32_t lenfield_blocksize; /* blocksize of the packet length field */
 #ifdef HAVE_LIBGCRYPT
     size_t keylen; /* length of the key structure */
     gcry_cipher_hd_t *key;
 #elif defined HAVE_LIBCRYPTO
+    size_t keylen; /* length of the key structure */
     struct ssh_3des_key_schedule *des3_key;
     struct ssh_aes_key_schedule *aes_key;
     const EVP_CIPHER *cipher;
@@ -141,7 +143,9 @@ struct ssh_cipher_struct {
     mbedtls_cipher_context_t decrypt_ctx;
     mbedtls_cipher_type_t type;
 #endif
+    struct chacha20_poly1305_keysched *chacha20_schedule;
     unsigned int keysize; /* bytes of key used. != keylen */
+    size_t tag_size; /* overhead required for tag */
     /* sets the new key for immediate use */
     int (*set_encrypt_key)(struct ssh_cipher_struct *cipher, void *key, void *IV);
     int (*set_decrypt_key)(struct ssh_cipher_struct *cipher, void *key, void *IV);
@@ -149,6 +153,8 @@ struct ssh_cipher_struct {
         unsigned long len);
     void (*decrypt)(struct ssh_cipher_struct *cipher, void *in, void *out,
         unsigned long len);
+    void (*aead_encrypt)(struct ssh_cipher_struct *cipher, void *in, void *out,
+        size_t len, uint8_t *mac, uint64_t seq);
     void (*cleanup)(struct ssh_cipher_struct *cipher);
 };
 
diff --git a/include/libssh/libcrypto.h b/include/libssh/libcrypto.h
index 6a08837a..4b8e5414 100644
--- a/include/libssh/libcrypto.h
+++ b/include/libssh/libcrypto.h
@@ -95,6 +95,7 @@ SHA512CTX sha512_init(void);
 void sha512_update(SHA512CTX c, const void *data, unsigned long len);
 void sha512_final(unsigned char *md, SHA512CTX c);
 
+void libcrypto_init(void);
 struct ssh_cipher_struct *ssh_get_ciphertab(void);
 
 #endif /* HAVE_LIBCRYPTO */
diff --git a/include/libssh/wrapper.h b/include/libssh/wrapper.h
index 6b6cf0b1..c23c9061 100644
--- a/include/libssh/wrapper.h
+++ b/include/libssh/wrapper.h
@@ -39,7 +39,8 @@ enum ssh_hmac_e {
   SSH_HMAC_SHA256,
   SSH_HMAC_SHA384,
   SSH_HMAC_SHA512,
-  SSH_HMAC_MD5
+  SSH_HMAC_MD5,
+  SSH_HMAC_AEAD_POLY1305
 };
 
 enum ssh_des_e {
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index edbf3520..90e44253 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -122,6 +122,7 @@ set(libssh_SRCS
   bignum.c
   buffer.c
   callbacks.c
+  chachapoly.c
   channels.c
   client.c
   config.c
diff --git a/src/chachapoly.c b/src/chachapoly.c
new file mode 100644
index 00000000..16032179
--- /dev/null
+++ b/src/chachapoly.c
@@ -0,0 +1,126 @@
+/*
+ * This file is part of the SSH Library
+ *
+ * Copyright (c) 2015 by Aris Adamantiadis
+ *
+ * The SSH Library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version.
+ *
+ * The SSH Library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with the SSH Library; see the file COPYING.  If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ * MA 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#include "libssh/libssh.h"
+#include "libssh/crypto.h"
+#include "libssh/chacha.h"
+#include "libssh/poly1305.h"
+#include "libssh/misc.h"
+
+/* size of the keys k1 and k2 as defined in specs */
+#define CHACHA20_KEYLEN 32
+struct chacha20_poly1305_keysched {
+    /* key used for encrypting the length field*/
+    struct chacha_ctx k1;
+    /* key used for encrypting the packets */
+    struct chacha_ctx k2;
+};
+
+#pragma pack(push, 1)
+struct ssh_packet_header {
+    uint32_t length;
+    uint8_t payload[];
+};
+#pragma pack(pop)
+
+const uint8_t zero_block_counter[8] = {0, 0, 0, 0, 0, 0, 0, 0};
+const uint8_t payload_block_counter[8] = {1, 0, 0, 0, 0, 0, 0, 0};
+
+static int chacha20_set_encrypt_key(struct ssh_cipher_struct *cipher,
+                                    void *key,
+                                    void *IV)
+{
+    struct chacha20_poly1305_keysched *sched;
+    uint8_t *u8key = key;
+    (void)IV;
+
+    if (cipher->chacha20_schedule == NULL) {
+        sched = malloc(sizeof *sched);
+        if (sched == NULL){
+            return -1;
+        }
+    } else {
+        sched = cipher->chacha20_schedule;
+    }
+
+    chacha_keysetup(&sched->k2, u8key, CHACHA20_KEYLEN * 8);
+    chacha_keysetup(&sched->k1, u8key + CHACHA20_KEYLEN, CHACHA20_KEYLEN * 8);
+    cipher->chacha20_schedule = sched;
+
+    return 0;
+}
+
+/**
+ * @internal
+ *
+ * @brief encrypts an outgoing packet with chacha20 and authenticate it
+ * with poly1305.
+ */
+static void chacha20_poly1305_aead_encrypt(struct ssh_cipher_struct *cipher,
+                                           void *in,
+                                           void *out,
+                                           size_t len,
+                                           uint8_t *tag,
+                                           uint64_t seq)
+{
+    struct ssh_packet_header *in_packet = in, *out_packet = out;
+    uint8_t poly1305_ctx[POLY1305_KEYLEN] = {0};
+    struct chacha20_poly1305_keysched *keys = cipher->chacha20_schedule;
+
+    seq = htonll(seq);
+    /* step 1, prepare the poly1305 key */
+    chacha_ivsetup(&keys->k2, (uint8_t *)&seq, zero_block_counter);
+    chacha_encrypt_bytes(&keys->k2,
+                         poly1305_ctx,
+                         poly1305_ctx,
+                         POLY1305_KEYLEN);
+
+    /* step 2, encrypt length field */
+    chacha_ivsetup(&keys->k1, (uint8_t *)&seq, zero_block_counter);
+    chacha_encrypt_bytes(&keys->k1,
+                         (uint8_t *)&in_packet->length,
+                         (uint8_t *)&out_packet->length,
+                         sizeof(uint32_t));
+
+    /* step 3, encrypt packet payload */
+    chacha_ivsetup(&keys->k2, (uint8_t *)&seq, payload_block_counter);
+    chacha_encrypt_bytes(&keys->k2,
+                         in_packet->payload,
+                         out_packet->payload,
+                         len - sizeof(uint32_t));
+
+    /* step 4, compute the MAC */
+    poly1305_auth(tag, (uint8_t *)out_packet, len, poly1305_ctx);
+}
+
+const struct ssh_cipher_struct chacha20poly1305_cipher = {
+    .name = "chacha20-poly1305@xxxxxxxxxxx",
+    .blocksize = 8,
+    .lenfield_blocksize = 4,
+    .keylen = sizeof(struct chacha20_poly1305_keysched),
+    .keysize = 512,
+    .tag_size = POLY1305_TAGLEN,
+    .set_encrypt_key = chacha20_set_encrypt_key,
+    .set_decrypt_key = chacha20_set_encrypt_key,
+    .aead_encrypt = chacha20_poly1305_aead_encrypt,
+};
diff --git a/src/dh.c b/src/dh.c
index d2ddfabd..d0ef05d1 100644
--- a/src/dh.c
+++ b/src/dh.c
@@ -68,6 +68,7 @@
 #include <openssl/rand.h>
 #include <openssl/evp.h>
 #include <openssl/err.h>
+#include "libssh/libcrypto.h"
 #endif
 
 static unsigned char p_group1_value[] = {
@@ -210,6 +211,8 @@ int ssh_crypto_init(void) {
     bignum_bin2bn(p_group14_value, P_GROUP14_LEN, p_group14);
 
     OpenSSL_add_all_algorithms();
+
+    libcrypto_init();
 #elif defined HAVE_LIBMBEDCRYPTO
     p_group1 = bignum_new();
     bignum_bin2bn(p_group1_value, P_GROUP1_LEN, p_group1);
diff --git a/src/kex.c b/src/kex.c
index b658ed44..20044c32 100644
--- a/src/kex.c
+++ b/src/kex.c
@@ -95,6 +95,8 @@
 #define ECDH ""
 #endif
 
+#define CHACHA20 "chacha20-poly1305@xxxxxxxxxxx,"
+
 #define KEY_EXCHANGE CURVE25519 ECDH "diffie-hellman-group14-sha1,diffie-hellman-group1-sha1"
 #define KEX_METHODS_SIZE 10
 
@@ -117,7 +119,7 @@ static const char *default_methods[] = {
 static const char *supported_methods[] = {
   KEY_EXCHANGE,
   HOSTKEYS,
-  AES BLOWFISH DES_SUPPORTED,
+  CHACHA20 AES BLOWFISH DES_SUPPORTED,
   AES BLOWFISH DES_SUPPORTED,
   "hmac-sha2-256,hmac-sha2-512,hmac-sha1",
   "hmac-sha2-256,hmac-sha2-512,hmac-sha1",
diff --git a/src/libcrypto.c b/src/libcrypto.c
index 66453666..982c9c84 100644
--- a/src/libcrypto.c
+++ b/src/libcrypto.c
@@ -60,6 +60,7 @@
 
 #include "libssh/crypto.h"
 
+extern const struct ssh_cipher_struct chacha20poly1305_cipher;
 struct ssh_mac_ctx_struct {
   enum ssh_mac_e mac_type;
   union {
@@ -860,11 +861,30 @@ static struct ssh_cipher_struct ssh_ciphertab[] = {
     .cleanup = des_cleanup
   },
 #endif /* HAS_DES */
+  {
+    .name = "chacha20-poly1305@xxxxxxxxxxx"
+  },
   {
     .name = NULL
   }
 };
 
+void libcrypto_init(void)
+{
+    size_t i;
+
+    for (i = 0; ssh_ciphertab[i].name != NULL; i++) {
+        int cmp;
+
+        cmp = strcmp(ssh_ciphertab[i].name, "chacha20-poly1305@xxxxxxxxxxx");
+        if (cmp == 0) {
+            memcpy(&ssh_ciphertab[i],
+                   &chacha20poly1305_cipher,
+                   sizeof(struct ssh_cipher_struct));
+            break;
+        }
+    }
+}
 
 struct ssh_cipher_struct *ssh_get_ciphertab(void)
 {
@@ -872,4 +892,3 @@ struct ssh_cipher_struct *ssh_get_ciphertab(void)
 }
 
 #endif /* LIBCRYPTO */
-
diff --git a/src/packet.c b/src/packet.c
index b66e3d22..f6fb6bff 100644
--- a/src/packet.c
+++ b/src/packet.c
@@ -555,6 +555,8 @@ static int ssh_packet_write(ssh_session session) {
 static int packet_send2(ssh_session session) {
   unsigned int blocksize = (session->current_crypto ?
       session->current_crypto->out_cipher->blocksize : 8);
+  unsigned int lenfield_blocksize = (session->current_crypto ?
+      session->current_crypto->out_cipher->lenfield_blocksize : 0);
   enum ssh_hmac_e hmac_type = (session->current_crypto ?
       session->current_crypto->out_hmac : session->next_crypto->out_hmac);
   uint32_t currentlen = ssh_buffer_get_len(session->out_buffer);
@@ -563,8 +565,7 @@ static int packet_send2(ssh_session session) {
   int rc = SSH_ERROR;
   uint32_t finallen,payloadsize,compsize;
   uint8_t padding;
-
-  uint8_t header[sizeof(padding) + sizeof(finallen)] = { 0 };
+  ssh_buffer header_buffer = ssh_buffer_new();
 
   payloadsize = currentlen;
 #ifdef WITH_ZLIB
@@ -578,20 +579,30 @@ static int packet_send2(ssh_session session) {
   }
 #endif /* WITH_ZLIB */
   compsize = currentlen;
-  padding = (blocksize - ((currentlen +5) % blocksize));
+  /* compressed payload + packet len (4) + padding len (1) */
+  /* totallen - lenfield_blocksize must be equal to 0 (mod blocksize) */
+  padding = (blocksize - ((blocksize - lenfield_blocksize + currentlen + 5) % blocksize));
   if(padding < 4) {
     padding += blocksize;
   }
 
-  if (session->current_crypto) {
+  if (session->current_crypto != NULL) {
     ssh_get_random(padstring, padding, 0);
   }
 
-  finallen = htonl(currentlen + padding + 1);
+  if (header_buffer == NULL){
+    ssh_set_error_oom(session);
+    goto error;
+  }
+  finallen = currentlen + padding + 1;
+  rc = ssh_buffer_pack(header_buffer, "db", finallen, padding);
+  if (rc == SSH_ERROR){
+    goto error;
+  }
 
-  memcpy(&header[0], &finallen, sizeof(finallen));
-  header[sizeof(finallen)] = padding;
-  rc = ssh_buffer_prepend_data(session->out_buffer, &header, sizeof(header));
+  rc = ssh_buffer_prepend_data(session->out_buffer,
+                               ssh_buffer_get(header_buffer),
+                               ssh_buffer_get_len(header_buffer));
   if (rc < 0) {
     goto error;
   }
@@ -600,10 +611,12 @@ static int packet_send2(ssh_session session) {
     goto error;
   }
 #ifdef WITH_PCAP
-  if(session->pcap_ctx){
-  	ssh_pcap_context_write(session->pcap_ctx,SSH_PCAP_DIR_OUT,
-  			ssh_buffer_get(session->out_buffer),ssh_buffer_get_len(session->out_buffer)
-  			,ssh_buffer_get_len(session->out_buffer));
+  if (session->pcap_ctx) {
+      ssh_pcap_context_write(session->pcap_ctx,
+                             SSH_PCAP_DIR_OUT,
+                             ssh_buffer_get(session->out_buffer),
+                             ssh_buffer_get_len(session->out_buffer),
+                             ssh_buffer_get_len(session->out_buffer));
   }
 #endif
   hmac = ssh_packet_encrypt(session, ssh_buffer_get(session->out_buffer),
@@ -624,12 +637,14 @@ static int packet_send2(ssh_session session) {
 
   SSH_LOG(SSH_LOG_PACKET,
           "packet: wrote [len=%d,padding=%hhd,comp=%d,payload=%d]",
-          ntohl(finallen), padding, compsize, payloadsize);
+          finallen, padding, compsize, payloadsize);
   if (ssh_buffer_reinit(session->out_buffer) < 0) {
     rc = SSH_ERROR;
   }
 error:
-
+  if (header_buffer != NULL) {
+      ssh_buffer_free(header_buffer);
+  }
   return rc; /* SSH_OK, AGAIN or ERROR */
 }
 
diff --git a/src/packet_crypt.c b/src/packet_crypt.c
index 7a30e661..5bcb6d65 100644
--- a/src/packet_crypt.c
+++ b/src/packet_crypt.c
@@ -93,7 +93,7 @@ unsigned char *ssh_packet_encrypt(ssh_session session, void *data, uint32_t len)
   if (!session->current_crypto) {
     return NULL; /* nothing to do here */
   }
-  if(len % session->current_crypto->in_cipher->blocksize != 0){
+  if((len - session->current_crypto->out_cipher->lenfield_blocksize) % session->current_crypto->out_cipher->blocksize != 0){
       ssh_set_error(session, SSH_FATAL, "Cryptographic functions must be set on at least one blocksize (received %d)",len);
       return NULL;
   }
@@ -106,26 +106,36 @@ unsigned char *ssh_packet_encrypt(ssh_session session, void *data, uint32_t len)
   seq = ntohl(session->send_seq);
   crypto = session->current_crypto->out_cipher;
 
-  if (session->version == 2) {
-    ctx = hmac_init(session->current_crypto->encryptMAC, hmac_digest_len(type), type);
-    if (ctx == NULL) {
-      SAFE_FREE(out);
-      return NULL;
-    }
-    hmac_update(ctx,(unsigned char *)&seq,sizeof(uint32_t));
-    hmac_update(ctx,data,len);
-    hmac_final(ctx,session->current_crypto->hmacbuf,&finallen);
+  if (crypto->aead_encrypt != NULL) {
+    crypto->aead_encrypt(crypto, data, out, len,
+            session->current_crypto->hmacbuf, session->send_seq);
+  } else {
+    if (session->version == 2) {
+      ctx = hmac_init(session->current_crypto->encryptMAC, hmac_digest_len(type), type);
+      if (ctx == NULL) {
+        SAFE_FREE(out);
+        return NULL;
+      }
+      hmac_update(ctx,(unsigned char *)&seq,sizeof(uint32_t));
+      hmac_update(ctx,data,len);
+      hmac_final(ctx,session->current_crypto->hmacbuf,&finallen);
+
+      if (crypto->set_encrypt_key(crypto, session->current_crypto->encryptkey,
+          session->current_crypto->encryptIV) < 0) {
+        SAFE_FREE(out);
+        return NULL;
+      }
+
 #ifdef DEBUG_CRYPTO
-    ssh_print_hexa("mac: ",data,hmac_digest_len(type));
-    if (finallen != hmac_digest_len(type)) {
-      printf("Final len is %d\n",finallen);
-    }
-    ssh_print_hexa("Packet hmac", session->current_crypto->hmacbuf, hmac_digest_len(type));
+      ssh_print_hexa("mac: ",data,hmac_digest_len(type));
+      if (finallen != hmac_digest_len(type)) {
+        printf("Final len is %d\n",finallen);
+      }
+      ssh_print_hexa("Packet hmac", session->current_crypto->hmacbuf, hmac_digest_len(type));
 #endif
-  }
-
+    }
   crypto->encrypt(crypto, data, out, len);
-
+  }
   memcpy(data, out, len);
   explicit_bzero(out, len);
   SAFE_FREE(out);
diff --git a/src/wrapper.c b/src/wrapper.c
index 16f93274..69484fff 100644
--- a/src/wrapper.c
+++ b/src/wrapper.c
@@ -47,6 +47,7 @@
 #include "libssh/crypto.h"
 #include "libssh/wrapper.h"
 #include "libssh/pki.h"
+#include "libssh/poly1305.h"
 
 static struct ssh_hmac_struct ssh_hmac_tab[] = {
   { "hmac-sha1",     SSH_HMAC_SHA1 },
@@ -54,6 +55,7 @@ static struct ssh_hmac_struct ssh_hmac_tab[] = {
   { "hmac-sha2-384", SSH_HMAC_SHA384 },
   { "hmac-sha2-512", SSH_HMAC_SHA512 },
   { "hmac-md5",      SSH_HMAC_MD5 },
+  { "aead-poly1305", SSH_HMAC_AEAD_POLY1305 },
   { NULL,            0}
 };
 
@@ -73,6 +75,8 @@ size_t hmac_digest_len(enum ssh_hmac_e type) {
       return SHA512_DIGEST_LEN;
     case SSH_HMAC_MD5:
       return MD5_DIGEST_LEN;
+    case SSH_HMAC_AEAD_POLY1305:
+      return POLY1305_TAGLEN;
     default:
       return 0;
   }
@@ -124,6 +128,9 @@ void ssh_cipher_clear(struct ssh_cipher_struct *cipher){
     if (cipher->cleanup != NULL) {
         cipher->cleanup(cipher);
     }
+    if (cipher->chacha20_schedule != NULL){
+        SAFE_FREE(cipher->chacha20_schedule);
+    }
 }
 
 static void cipher_free(struct ssh_cipher_struct *cipher) {
@@ -247,9 +254,14 @@ static int crypt_set_algorithms2(ssh_session session){
   }
   i = 0;
 
-  /* we must scan the kex entries to find hmac algorithms and set their appropriate structure */
-  /* out */
-  wanted = session->next_crypto->kex_methods[SSH_MAC_C_S];
+  if (session->next_crypto->out_cipher->aead_encrypt != NULL){
+      /* this cipher has integrated MAC */
+      wanted = "aead-poly1305";
+  } else {
+      /* we must scan the kex entries to find hmac algorithms and set their appropriate structure */
+      /* out */
+      wanted = session->next_crypto->kex_methods[SSH_MAC_C_S];
+  }
   while (ssh_hmactab[i].name && strcmp(wanted, ssh_hmactab[i].name)) {
     i++;
   }
@@ -357,7 +369,7 @@ int crypt_set_algorithms(ssh_session session, enum ssh_des_e des_type) {
 
 #ifdef WITH_SERVER
 int crypt_set_algorithms_server(ssh_session session){
-    char *method = NULL;
+    const char *method = NULL;
     int i = 0;
     struct ssh_cipher_struct *ssh_ciphertab=ssh_get_ciphertab();
     struct ssh_hmac_struct   *ssh_hmactab=ssh_get_hmactab();
@@ -372,9 +384,17 @@ int crypt_set_algorithms_server(ssh_session session){
      */
     /* out */
     method = session->next_crypto->kex_methods[SSH_CRYPT_S_C];
-    while(ssh_ciphertab[i].name && strcmp(method,ssh_ciphertab[i].name))
-        i++;
-    if(!ssh_ciphertab[i].name){
+
+    for (i = 0; ssh_ciphertab[i].name != NULL; i++) {
+        int cmp;
+
+        cmp = strcmp(method, ssh_ciphertab[i].name);
+        if (cmp == 0) {
+          break;
+        }
+    }
+
+    if (ssh_ciphertab[i].name == NULL) {
         ssh_set_error(session,SSH_FATAL,"crypt_set_algorithms_server : "
                 "no crypto algorithm function found for %s",method);
         return SSH_ERROR;
@@ -387,26 +407,16 @@ int crypt_set_algorithms_server(ssh_session session){
         return SSH_ERROR;
     }
     i=0;
-    /* in */
-    method = session->next_crypto->kex_methods[SSH_CRYPT_C_S];
-    while(ssh_ciphertab[i].name && strcmp(method,ssh_ciphertab[i].name))
-        i++;
-    if(!ssh_ciphertab[i].name){
-        ssh_set_error(session,SSH_FATAL,"Crypt_set_algorithms_server :"
-                "no crypto algorithm function found for %s",method);
-        return SSH_ERROR;
-    }
-    SSH_LOG(SSH_LOG_PACKET,"Set input algorithm %s",method);
-
-    session->next_crypto->in_cipher = cipher_new(i);
-    if (session->next_crypto->in_cipher == NULL) {
-        ssh_set_error_oom(session);
-        return SSH_ERROR;
+    if (session->next_crypto->out_cipher->aead_encrypt != NULL){
+        /* this cipher has integrated MAC */
+        method = "aead-poly1305";
+    } else {
+        /* we must scan the kex entries to find hmac algorithms and set their appropriate structure */
+        /* out */
+        method = session->next_crypto->kex_methods[SSH_MAC_S_C];
     }
-    i=0;
-
     /* HMAC algorithm selection */
-    method = session->next_crypto->kex_methods[SSH_MAC_S_C];
+
     while (ssh_hmactab[i].name && strcmp(method, ssh_hmactab[i].name)) {
       i++;
     }
@@ -420,11 +430,43 @@ int crypt_set_algorithms_server(ssh_session session){
     SSH_LOG(SSH_LOG_PACKET, "Set HMAC output algorithm to %s", method);
 
     session->next_crypto->out_hmac = ssh_hmactab[i].hmac_type;
+
+    /* in */
+    i=0;
+    method = session->next_crypto->kex_methods[SSH_CRYPT_C_S];
+
+    for (i = 0; ssh_ciphertab[i].name; i++) {
+      int cmp;
+
+      cmp = strcmp(method, ssh_ciphertab[i].name);
+      if (cmp == 0) {
+        break;
+      }
+    }
+
+    if (ssh_ciphertab[i].name == NULL) {
+        ssh_set_error(session,SSH_FATAL,"Crypt_set_algorithms_server :"
+                "no crypto algorithm function found for %s",method);
+        return SSH_ERROR;
+    }
+    SSH_LOG(SSH_LOG_PACKET,"Set input algorithm %s",method);
+
+    session->next_crypto->in_cipher = cipher_new(i);
+    if (session->next_crypto->in_cipher == NULL) {
+        ssh_set_error_oom(session);
+        return SSH_ERROR;
+    }
     i=0;
 
     method = session->next_crypto->kex_methods[SSH_MAC_C_S];
-    while (ssh_hmactab[i].name && strcmp(method, ssh_hmactab[i].name)) {
-      i++;
+
+    for (i = 0; ssh_hmactab[i].name != NULL; i++) {
+      int cmp;
+
+      cmp = strcmp(method, ssh_hmactab[i].name);
+      if (cmp == 0) {
+        break;
+      }
     }
 
     if (ssh_hmactab[i].name == NULL) {
-- 
2.17.1


From 7c1187961a0ef3e89d32d2c9c467dfa264a6933b Mon Sep 17 00:00:00 2001
From: Aris Adamantiadis <aris@xxxxxxxxxxxx>
Date: Wed, 28 Feb 2018 10:24:54 -0600
Subject: [PATCH 04/12] chacha: packet decryption

Signed-off-by: Aris Adamantiadis <aris@xxxxxxxxxxxx>
---
 include/libssh/crypto.h |   4 ++
 include/libssh/packet.h |   5 +-
 src/chachapoly.c        |  76 ++++++++++++++++++++++++
 src/kex.c               |   2 +-
 src/packet.c            | 110 +++++++++++++++++------------------
 src/packet_crypt.c      | 125 ++++++++++++++++++++++++++++++----------
 src/wrapper.c           |  58 ++++++++++++++-----
 7 files changed, 276 insertions(+), 104 deletions(-)

diff --git a/include/libssh/crypto.h b/include/libssh/crypto.h
index e6e5b8f6..495a9c4c 100644
--- a/include/libssh/crypto.h
+++ b/include/libssh/crypto.h
@@ -155,6 +155,10 @@ struct ssh_cipher_struct {
         unsigned long len);
     void (*aead_encrypt)(struct ssh_cipher_struct *cipher, void *in, void *out,
         size_t len, uint8_t *mac, uint64_t seq);
+    int (*aead_decrypt_length)(struct ssh_cipher_struct *cipher, void *in,
+        uint8_t *out, size_t len, uint64_t seq);
+    int (*aead_decrypt)(struct ssh_cipher_struct *cipher, void *complete_packet, uint8_t *out,
+        size_t encrypted_size, uint64_t seq);
     void (*cleanup)(struct ssh_cipher_struct *cipher);
 };
 
diff --git a/include/libssh/packet.h b/include/libssh/packet.h
index 3a84eb70..b10308f7 100644
--- a/include/libssh/packet.h
+++ b/include/libssh/packet.h
@@ -78,8 +78,9 @@ void ssh_packet_set_default_callbacks(ssh_session session);
 void ssh_packet_process(ssh_session session, uint8_t type);
 
 /* PACKET CRYPT */
-uint32_t ssh_packet_decrypt_len(ssh_session session, char *crypted);
-int ssh_packet_decrypt(ssh_session session, void *packet, unsigned int len);
+uint32_t ssh_packet_decrypt_len(ssh_session session, uint8_t *destination, uint8_t *source);
+int ssh_packet_decrypt(ssh_session session, uint8_t *destination, uint8_t *source,
+        size_t start, size_t encrypted_size);
 unsigned char *ssh_packet_encrypt(ssh_session session,
                                   void *packet,
                                   unsigned int len);
diff --git a/src/chachapoly.c b/src/chachapoly.c
index 16032179..f3319b62 100644
--- a/src/chachapoly.c
+++ b/src/chachapoly.c
@@ -109,8 +109,82 @@ static void chacha20_poly1305_aead_encrypt(struct ssh_cipher_struct *cipher,
                          out_packet->payload,
                          len - sizeof(uint32_t));
 
+    /* ssh_print_hexa("poly1305_ctx", poly1305_ctx, sizeof(poly1305_ctx)); */
     /* step 4, compute the MAC */
     poly1305_auth(tag, (uint8_t *)out_packet, len, poly1305_ctx);
+    /* ssh_print_hexa("poly1305 src", (uint8_t *)out_packet, len);
+    ssh_print_hexa("poly1305 tag", tag, POLY1305_TAGLEN); */
+}
+
+static int chacha20_poly1305_aead_decrypt_length(
+        struct ssh_cipher_struct *cipher,
+        void *in,
+        uint8_t *out,
+        size_t len,
+        uint64_t seq)
+{
+    struct chacha20_poly1305_keysched *keys = cipher->chacha20_schedule;
+
+    if (len < sizeof(uint32_t)) {
+        return SSH_ERROR;
+    }
+    seq = htonll(seq);
+
+    chacha_ivsetup(&keys->k1, (uint8_t *)&seq, zero_block_counter);
+    chacha_encrypt_bytes(&keys->k1,
+                         in,
+                         (uint8_t *)out,
+                         sizeof(uint32_t));
+    return SSH_OK;
+}
+
+static int chacha20_poly1305_aead_decrypt(struct ssh_cipher_struct *cipher,
+                                          void *complete_packet,
+                                          uint8_t *out,
+                                          size_t encrypted_size,
+                                          uint64_t seq)
+{
+    uint8_t poly1305_ctx[POLY1305_KEYLEN] = {0};
+    uint8_t tag[POLY1305_TAGLEN] = {0};
+    struct chacha20_poly1305_keysched *keys = cipher->chacha20_schedule;
+    uint8_t *mac = (uint8_t *)complete_packet + sizeof(uint32_t) + encrypted_size;
+    int cmp;
+
+    seq = htonll(seq);
+
+    ZERO_STRUCT(poly1305_ctx);
+    chacha_ivsetup(&keys->k2, (uint8_t *)&seq, zero_block_counter);
+    chacha_encrypt_bytes(&keys->k2,
+                         poly1305_ctx,
+                         poly1305_ctx,
+                         POLY1305_KEYLEN);
+#if 0
+    ssh_print_hexa("poly1305_ctx", poly1305_ctx, sizeof(poly1305_ctx));
+#endif
+
+    poly1305_auth(tag, (uint8_t *)complete_packet, encrypted_size +
+            sizeof(uint32_t), poly1305_ctx);
+#if 0
+    ssh_print_hexa("poly1305 src",
+                   (uint8_t*)complete_packet,
+                   encrypted_size + 4);
+    ssh_print_hexa("poly1305 tag", tag, POLY1305_TAGLEN);
+    ssh_print_hexa("received tag", mac, POLY1305_TAGLEN);
+#endif
+
+    cmp = memcmp(tag, mac, POLY1305_TAGLEN);
+    if(cmp != 0) {
+        /* mac error */
+        SSH_LOG(SSH_LOG_PACKET,"poly1305 verify error");
+        return SSH_ERROR;
+    }
+    chacha_ivsetup(&keys->k2, (uint8_t *)&seq, payload_block_counter);
+    chacha_encrypt_bytes(&keys->k2,
+                         (uint8_t *)complete_packet + sizeof(uint32_t),
+                         out,
+                         encrypted_size);
+
+    return SSH_OK;
 }
 
 const struct ssh_cipher_struct chacha20poly1305_cipher = {
@@ -123,4 +197,6 @@ const struct ssh_cipher_struct chacha20poly1305_cipher = {
     .set_encrypt_key = chacha20_set_encrypt_key,
     .set_decrypt_key = chacha20_set_encrypt_key,
     .aead_encrypt = chacha20_poly1305_aead_encrypt,
+    .aead_decrypt_length = chacha20_poly1305_aead_decrypt_length,
+    .aead_decrypt = chacha20_poly1305_aead_decrypt
 };
diff --git a/src/kex.c b/src/kex.c
index 20044c32..00f4e00f 100644
--- a/src/kex.c
+++ b/src/kex.c
@@ -120,7 +120,7 @@ static const char *supported_methods[] = {
   KEY_EXCHANGE,
   HOSTKEYS,
   CHACHA20 AES BLOWFISH DES_SUPPORTED,
-  AES BLOWFISH DES_SUPPORTED,
+  CHACHA20 AES BLOWFISH DES_SUPPORTED,
   "hmac-sha2-256,hmac-sha2-512,hmac-sha1",
   "hmac-sha2-256,hmac-sha2-512,hmac-sha1",
   ZLIB,
diff --git a/src/packet.c b/src/packet.c
index f6fb6bff..7d3c14b1 100644
--- a/src/packet.c
+++ b/src/packet.c
@@ -144,20 +144,26 @@ int ssh_packet_socket_callback(const void *data, size_t receivedlen, void *user)
     ssh_session session= (ssh_session) user;
     unsigned int blocksize = (session->current_crypto ?
                               session->current_crypto->in_cipher->blocksize : 8);
-    unsigned char mac[DIGEST_MAX_LEN] = {0};
-    char buffer[16] = {0};
+    unsigned int lenfield_blocksize = (session->current_crypto ?
+                                  session->current_crypto->in_cipher->lenfield_blocksize : 8);
     size_t current_macsize = 0;
-    const uint8_t *packet;
+    uint8_t *ptr = NULL;
     int to_be_read;
     int rc;
-    uint32_t len, compsize, payloadsize;
+    uint8_t *cleartext_packet = NULL;
+    uint8_t *packet_second_block = NULL;
+    uint8_t *mac = NULL;
+    size_t packet_remaining;
+    uint32_t packet_len, compsize, payloadsize;
     uint8_t padding;
     size_t processed = 0; /* number of byte processed from the callback */
 
     if(session->current_crypto != NULL) {
       current_macsize = hmac_digest_len(session->current_crypto->in_hmac);
     }
-
+    if (lenfield_blocksize == 0) {
+        lenfield_blocksize = blocksize;
+    }
     if (data == NULL) {
         goto error;
     }
@@ -178,7 +184,7 @@ int ssh_packet_socket_callback(const void *data, size_t receivedlen, void *user)
 #endif
     switch(session->packet_state) {
         case PACKET_STATE_INIT:
-            if (receivedlen < blocksize) {
+            if (receivedlen < lenfield_blocksize) {
                 /*
                  * We didn't receive enough data to read at least one
                  * block size, give up
@@ -187,7 +193,7 @@ int ssh_packet_socket_callback(const void *data, size_t receivedlen, void *user)
                 SSH_LOG(SSH_LOG_PACKET,
                         "Waiting for more data (%zu < %zu)",
                         receivedlen,
-                        blocksize);
+                        lenfield_blocksize);
 #endif
                 return 0;
             }
@@ -206,24 +212,21 @@ int ssh_packet_socket_callback(const void *data, size_t receivedlen, void *user)
                 }
             }
 
-            memcpy(buffer, data, blocksize);
-            processed += blocksize;
-            len = ssh_packet_decrypt_len(session, buffer);
-
-            rc = ssh_buffer_add_data(session->in_buffer, buffer, blocksize);
-            if (rc < 0) {
+            ptr = ssh_buffer_allocate(session->in_buffer, lenfield_blocksize);
+            if (ptr == NULL) {
                 goto error;
             }
+            processed += lenfield_blocksize;
+            packet_len = ssh_packet_decrypt_len(session, ptr, (uint8_t *)data);
 
-            if (len > MAX_PACKET_LEN) {
+            if (packet_len > MAX_PACKET_LEN) {
                 ssh_set_error(session,
                               SSH_FATAL,
                               "read_packet(): Packet len too high(%u %.4x)",
-                              len, len);
+                              packet_len, packet_len);
                 goto error;
             }
-
-            to_be_read = len - blocksize + sizeof(uint32_t);
+            to_be_read = packet_len - lenfield_blocksize + sizeof(uint32_t);
             if (to_be_read < 0) {
                 /* remote sshd sends invalid sizes? */
                 ssh_set_error(session,
@@ -233,59 +236,52 @@ int ssh_packet_socket_callback(const void *data, size_t receivedlen, void *user)
                 goto error;
             }
 
-            /* Saves the status of the current operations */
-            session->in_packet.len = len;
+            session->in_packet.len = packet_len;
             session->packet_state = PACKET_STATE_SIZEREAD;
             FALL_THROUGH;
         case PACKET_STATE_SIZEREAD:
-            len = session->in_packet.len;
-            to_be_read = len - blocksize + sizeof(uint32_t) + current_macsize;
+            packet_len = session->in_packet.len;
+            processed = lenfield_blocksize;
+            to_be_read = packet_len + sizeof(uint32_t) + current_macsize;
             /* if to_be_read is zero, the whole packet was blocksize bytes. */
             if (to_be_read != 0) {
-                if (receivedlen - processed < (unsigned int)to_be_read) {
+                if (receivedlen  < (unsigned int)to_be_read) {
                     /* give up, not enough data in buffer */
-                    SSH_LOG(SSH_LOG_PACKET,"packet: partial packet (read len) [len=%d]",len);
-                    return processed;
+                    SSH_LOG(SSH_LOG_PACKET,
+                            "packet: partial packet (read len) "
+                            "[len=%d, receivedlen=%d, to_be_read=%d]",
+                            packet_len,
+                            (int)receivedlen,
+                            to_be_read);
+                    return 0;
                 }
 
-                packet = ((uint8_t*)data) + processed;
-#if 0
-                ssh_socket_read(session->socket,
-                                packet,
-                                to_be_read - current_macsize);
-#endif
-
-                rc = ssh_buffer_add_data(session->in_buffer,
-                                     packet,
-                                     to_be_read - current_macsize);
-                if (rc < 0) {
-                    goto error;
-                }
-                processed += to_be_read - current_macsize;
+                packet_second_block = (uint8_t*)data + lenfield_blocksize;
+                processed = to_be_read - current_macsize;
             }
 
+            /* remaining encrypted bytes from the packet, MAC not included */
+            packet_remaining =
+                packet_len - (lenfield_blocksize - sizeof(uint32_t));
+            cleartext_packet = ssh_buffer_allocate(session->in_buffer,
+                                                   packet_remaining);
             if (session->current_crypto) {
                 /*
-                 * Decrypt the rest of the packet (blocksize bytes already
+                 * Decrypt the rest of the packet (lenfield_blocksize bytes already
                  * have been decrypted)
                  */
-                uint32_t buffer_len = ssh_buffer_get_len(session->in_buffer);
-
-                /* The following check avoids decrypting zero bytes */
-                if (buffer_len > blocksize) {
-                    uint8_t *payload = ((uint8_t*)ssh_buffer_get(session->in_buffer) + blocksize);
-                    uint32_t plen = buffer_len - blocksize;
-
-                    rc = ssh_packet_decrypt(session, payload, plen);
+                if (packet_remaining > 0) {
+                    rc = ssh_packet_decrypt(session,
+                                            cleartext_packet,
+                                            (uint8_t *)data,
+                                            lenfield_blocksize,
+                                            processed - lenfield_blocksize);
                     if (rc < 0) {
-                        ssh_set_error(session, SSH_FATAL, "Decrypt error");
+                        ssh_set_error(session, SSH_FATAL, "Decryption error");
                         goto error;
                     }
                 }
-
-                /* copy the last part from the incoming buffer */
-                packet = ((uint8_t *)data) + processed;
-                memcpy(mac, packet, current_macsize);
+                mac = packet_second_block + packet_remaining;
 
                 rc = ssh_packet_hmac_verify(session, session->in_buffer, mac, session->current_crypto->in_hmac);
                 if (rc < 0) {
@@ -293,6 +289,8 @@ int ssh_packet_socket_callback(const void *data, size_t receivedlen, void *user)
                     goto error;
                 }
                 processed += current_macsize;
+            } else {
+                memcpy(cleartext_packet, packet_second_block, packet_remaining);
             }
 
             /* skip the size field which has been processed before */
@@ -342,7 +340,7 @@ int ssh_packet_socket_callback(const void *data, size_t receivedlen, void *user)
             ssh_packet_parse_type(session);
             SSH_LOG(SSH_LOG_PACKET,
                     "packet: read type %hhd [len=%d,padding=%hhd,comp=%d,payload=%d]",
-                    session->in_packet.type, len, padding, compsize, payloadsize);
+                    session->in_packet.type, packet_len, padding, compsize, payloadsize);
 
             /* Execute callbacks */
             ssh_packet_process(session, session->in_packet.type);
@@ -353,9 +351,9 @@ int ssh_packet_socket_callback(const void *data, size_t receivedlen, void *user)
                         "Processing %" PRIdS " bytes left in socket buffer",
                         receivedlen-processed);
 
-                packet = ((uint8_t*)data) + processed;
+                ptr = ((uint8_t*)data) + processed;
 
-                rc = ssh_packet_socket_callback(packet, receivedlen - processed,user);
+                rc = ssh_packet_socket_callback(ptr, receivedlen - processed,user);
                 processed += rc;
             }
 
@@ -372,7 +370,7 @@ int ssh_packet_socket_callback(const void *data, size_t receivedlen, void *user)
 
 error:
     session->session_state= SSH_SESSION_STATE_ERROR;
-
+    SSH_LOG(SSH_LOG_PACKET,"Packet: processed %" PRIdS " bytes", processed);
     return processed;
 }
 
diff --git a/src/packet_crypt.c b/src/packet_crypt.c
index 5bcb6d65..fb09a225 100644
--- a/src/packet_crypt.c
+++ b/src/packet_crypt.c
@@ -44,40 +44,97 @@
 #include "libssh/crypto.h"
 #include "libssh/buffer.h"
 
-uint32_t ssh_packet_decrypt_len(ssh_session session, char *crypted){
-  uint32_t decrypted;
-
-  if (session->current_crypto) {
-    if (ssh_packet_decrypt(session, crypted,
-          session->current_crypto->in_cipher->blocksize) < 0) {
-      return 0;
+/** @internal
+ * @brief decrypt the packet length from a raw encrypted packet, and store the first decrypted
+ * blocksize.
+ * @returns native byte-ordered decrypted length of the upcoming packet
+ */
+uint32_t ssh_packet_decrypt_len(ssh_session session,
+                                uint8_t *destination,
+                                uint8_t *source)
+{
+    uint32_t decrypted;
+    int rc;
+
+    if (session->current_crypto != NULL) {
+        if (session->current_crypto->in_cipher->aead_decrypt_length != NULL) {
+            rc =
+              session->current_crypto->in_cipher->set_decrypt_key(
+                  session->current_crypto->in_cipher,
+                  session->current_crypto->decryptkey,
+                  session->current_crypto->decryptIV);
+            if (rc < 0) {
+                return (uint32_t)-1;
+            }
+            session->current_crypto->in_cipher->aead_decrypt_length(
+                    session->current_crypto->in_cipher, source, destination,
+                    session->current_crypto->in_cipher->lenfield_blocksize,
+                    session->recv_seq);
+        } else {
+            rc = ssh_packet_decrypt(
+                    session,
+                    destination,
+                    source,
+                    0,
+                    session->current_crypto->in_cipher->blocksize);
+            if (rc < 0) {
+                return 0;
+            }
+        }
+    } else {
+        memcpy(destination, source, 8);
     }
-  }
-  memcpy(&decrypted,crypted,sizeof(decrypted));
-  return ntohl(decrypted);
+    memcpy(&decrypted,destination,sizeof(decrypted));
+
+    return ntohl(decrypted);
 }
 
-int ssh_packet_decrypt(ssh_session session, void *data,uint32_t len) {
-  struct ssh_cipher_struct *crypto = session->current_crypto->in_cipher;
-  char *out = NULL;
+/** @internal
+ * @brief decrypts the content of an SSH packet.
+ * @param[source] source packet, including the encrypted length field
+ * @param[start] index in the packet that was not decrypted yet.
+ * @param[encrypted_size] size of the encrypted data to be decrypted after start.
+ */
+int ssh_packet_decrypt(ssh_session session,
+                       uint8_t *destination,
+                       uint8_t *source,
+                       size_t start,
+                       size_t encrypted_size)
+{
+    struct ssh_cipher_struct *crypto = session->current_crypto->in_cipher;
+    int rc;
+
+    if (encrypted_size <= 0) {
+        return SSH_ERROR;
+    }
 
-  assert(len);
+    if (encrypted_size % session->current_crypto->in_cipher->blocksize != 0) {
+        ssh_set_error(session,
+                      SSH_FATAL,
+                      "Cryptographic functions must be used on multiple of "
+                      "blocksize (received %" PRIdS ")",
+                      encrypted_size);
+        return SSH_ERROR;
+    }
 
-  if(len % session->current_crypto->in_cipher->blocksize != 0){
-    ssh_set_error(session, SSH_FATAL, "Cryptographic functions must be set on at least one blocksize (received %d)",len);
-    return SSH_ERROR;
-  }
-  out = malloc(len);
-  if (out == NULL) {
-    return -1;
-  }
+    rc = crypto->set_decrypt_key(crypto,
+                                 session->current_crypto->decryptkey,
+                                 session->current_crypto->decryptIV);
+    if (rc < 0) {
+        return -1;
+    }
 
-  crypto->decrypt(crypto,data,out,len);
+    if (crypto->aead_decrypt != NULL) {
+        return crypto->aead_decrypt(crypto,
+                                    source,
+                                    destination,
+                                    encrypted_size,
+                                    session->recv_seq);
+    } else {
+        crypto->decrypt(crypto, source + start, destination, encrypted_size);
+    }
 
-  memcpy(data,out,len);
-  explicit_bzero(out, len);
-  SAFE_FREE(out);
-  return 0;
+    return 0;
 }
 
 unsigned char *ssh_packet_encrypt(ssh_session session, void *data, uint32_t len) {
@@ -159,13 +216,21 @@ unsigned char *ssh_packet_encrypt(ssh_session session, void *data, uint32_t len)
  * @return              0 if hmac and mac are equal, < 0 if not or an error
  *                      occurred.
  */
-int ssh_packet_hmac_verify(ssh_session session, ssh_buffer buffer,
-    unsigned char *mac, enum ssh_hmac_e type) {
+int ssh_packet_hmac_verify(ssh_session session,
+                           ssh_buffer buffer,
+                           uint8_t *mac,
+                           enum ssh_hmac_e type)
+{
   unsigned char hmacbuf[DIGEST_MAX_LEN] = {0};
   HMACCTX ctx;
   unsigned int len;
   uint32_t seq;
 
+  /* AEAD type have no mac checking */
+  if (type == SSH_HMAC_AEAD_POLY1305) {
+      return SSH_OK;
+  }
+
   ctx = hmac_init(session->current_crypto->decryptMAC, hmac_digest_len(type), type);
   if (ctx == NULL) {
     return -1;
@@ -188,5 +253,3 @@ int ssh_packet_hmac_verify(ssh_session session, ssh_buffer buffer,
 
   return -1;
 }
-
-/* vim: set ts=2 sw=2 et cindent: */
diff --git a/src/wrapper.c b/src/wrapper.c
index 69484fff..77af522d 100644
--- a/src/wrapper.c
+++ b/src/wrapper.c
@@ -231,8 +231,13 @@ static int crypt_set_algorithms2(ssh_session session){
   int i = 0;
   struct ssh_cipher_struct *ssh_ciphertab=ssh_get_ciphertab();
   struct ssh_hmac_struct *ssh_hmactab=ssh_get_hmactab();
+  int cmp;
+
+  /*
+   * We must scan the kex entries to find crypto algorithms and set their
+   * appropriate structure.
+   */
 
-  /* we must scan the kex entries to find crypto algorithms and set their appropriate structure */
   /* out */
   wanted = session->next_crypto->kex_methods[SSH_CRYPT_C_S];
   while (ssh_ciphertab[i].name && strcmp(wanted, ssh_ciphertab[i].name)) {
@@ -258,12 +263,20 @@ static int crypt_set_algorithms2(ssh_session session){
       /* this cipher has integrated MAC */
       wanted = "aead-poly1305";
   } else {
-      /* we must scan the kex entries to find hmac algorithms and set their appropriate structure */
+      /*
+       * We must scan the kex entries to find hmac algorithms and set their
+       * appropriate structure.
+       */
+
       /* out */
       wanted = session->next_crypto->kex_methods[SSH_MAC_C_S];
   }
-  while (ssh_hmactab[i].name && strcmp(wanted, ssh_hmactab[i].name)) {
-    i++;
+
+  for (i = 0; ssh_hmactab[i].name != NULL; i++) {
+      cmp = strcmp(wanted, ssh_hmactab[i].name);
+      if (cmp == 0) {
+          break;
+      }
   }
 
   if (ssh_hmactab[i].name == NULL) {
@@ -275,12 +288,15 @@ static int crypt_set_algorithms2(ssh_session session){
   SSH_LOG(SSH_LOG_PACKET, "Set HMAC output algorithm to %s", wanted);
 
   session->next_crypto->out_hmac = ssh_hmactab[i].hmac_type;
-  i = 0;
 
   /* in */
   wanted = session->next_crypto->kex_methods[SSH_CRYPT_S_C];
-  while (ssh_ciphertab[i].name && strcmp(wanted, ssh_ciphertab[i].name)) {
-    i++;
+
+  for (i = 0; ssh_ciphertab[i].name != NULL; i++) {
+      cmp = strcmp(wanted, ssh_ciphertab[i].name);
+      if (cmp == 0) {
+        break;
+      }
   }
 
   if (ssh_ciphertab[i].name == NULL) {
@@ -296,12 +312,20 @@ static int crypt_set_algorithms2(ssh_session session){
       ssh_set_error_oom(session);
       return SSH_ERROR;
   }
-  i = 0;
 
-  /* we must scan the kex entries to find hmac algorithms and set their appropriate structure */
-  wanted = session->next_crypto->kex_methods[SSH_MAC_S_C];
-  while (ssh_hmactab[i].name && strcmp(wanted, ssh_hmactab[i].name)) {
-    i++;
+  if (session->next_crypto->in_cipher->aead_encrypt != NULL){
+      /* this cipher has integrated MAC */
+      wanted = "aead-poly1305";
+  } else {
+      /* we must scan the kex entries to find hmac algorithms and set their appropriate structure */
+      wanted = session->next_crypto->kex_methods[SSH_MAC_S_C];
+  }
+
+  for (i = 0; ssh_hmactab[i].name != NULL; i++) {
+      cmp = strcmp(wanted, ssh_hmactab[i].name);
+      if (cmp == 0) {
+          break;
+      }
   }
 
   if (ssh_hmactab[i].name == NULL) {
@@ -310,7 +334,7 @@ static int crypt_set_algorithms2(ssh_session session){
         wanted);
       return SSH_ERROR;
   }
-  SSH_LOG(SSH_LOG_PACKET, "Set HMAC output algorithm to %s", wanted);
+  SSH_LOG(SSH_LOG_PACKET, "Set HMAC input algorithm to %s", wanted);
 
   session->next_crypto->in_hmac = ssh_hmactab[i].hmac_type;
   i = 0;
@@ -458,7 +482,13 @@ int crypt_set_algorithms_server(ssh_session session){
     }
     i=0;
 
-    method = session->next_crypto->kex_methods[SSH_MAC_C_S];
+    if (session->next_crypto->in_cipher->aead_encrypt != NULL){
+        /* this cipher has integrated MAC */
+        method = "aead-poly1305";
+    } else {
+        /* we must scan the kex entries to find hmac algorithms and set their appropriate structure */
+        method = session->next_crypto->kex_methods[SSH_MAC_C_S];
+    }
 
     for (i = 0; ssh_hmactab[i].name != NULL; i++) {
       int cmp;
-- 
2.17.1


From e8659591e3f2c8a51ccb16261bc38fa172ef56da Mon Sep 17 00:00:00 2001
From: Aris Adamantiadis <aris@xxxxxxxxxxxx>
Date: Wed, 28 Feb 2018 10:24:55 -0600
Subject: [PATCH 05/12] libgcrypt: make it compatible with chacha20

Signed-off-by: Aris Adamantiadis <aris@xxxxxxxxxxxx>
---
 include/libssh/libgcrypt.h |  1 +
 src/dh.c                   |  1 +
 src/libgcrypt.c            | 21 +++++++++++++++++++++
 3 files changed, 23 insertions(+)

diff --git a/include/libssh/libgcrypt.h b/include/libssh/libgcrypt.h
index ec353910..307920d3 100644
--- a/include/libssh/libgcrypt.h
+++ b/include/libssh/libgcrypt.h
@@ -88,6 +88,7 @@ ssh_string ssh_sexp_extract_mpi(const gcry_sexp_t sexp,
 
 #endif /* HAVE_LIBGCRYPT */
 
+void libgcrypt_init(void);
 struct ssh_cipher_struct *ssh_get_ciphertab(void);
 
 #endif /* LIBGCRYPT_H_ */
diff --git a/src/dh.c b/src/dh.c
index d0ef05d1..a1b1ecfb 100644
--- a/src/dh.c
+++ b/src/dh.c
@@ -190,6 +190,7 @@ int ssh_crypto_init(void) {
       p_group1 = NULL;
       return -1;
     }
+    libgcrypt_init();
 
 #elif defined HAVE_LIBCRYPTO
     p_group1 = bignum_new();
diff --git a/src/libgcrypt.c b/src/libgcrypt.c
index d9dd5be6..b695b6bb 100644
--- a/src/libgcrypt.c
+++ b/src/libgcrypt.c
@@ -35,6 +35,8 @@
 #ifdef HAVE_LIBGCRYPT
 #include <gcrypt.h>
 
+extern const struct ssh_cipher_struct chacha20poly1305_cipher;
+
 struct ssh_mac_ctx_struct {
   enum ssh_mac_e mac_type;
   gcry_md_hd_t ctx;
@@ -637,6 +639,9 @@ static struct ssh_cipher_struct ssh_ciphertab[] = {
     .encrypt     = des1_1_encrypt,
     .decrypt     = des1_1_decrypt
   },
+  {
+    .name = "chacha20-poly1305@xxxxxxxxxxx"
+  },
   {
     .name            = NULL,
     .blocksize       = 0,
@@ -650,6 +655,22 @@ static struct ssh_cipher_struct ssh_ciphertab[] = {
   }
 };
 
+void libgcrypt_init(void)
+{
+    size_t i;
+
+    for (i = 0; ssh_ciphertab[i].name != NULL; i++) {
+        int cmp;
+        cmp = strcmp(ssh_ciphertab[i].name, "chacha20-poly1305@xxxxxxxxxxx");
+        if (cmp == 0) {
+            memcpy(&ssh_ciphertab[i],
+                   &chacha20poly1305_cipher,
+                   sizeof(struct ssh_cipher_struct));
+            break;
+        }
+    }
+}
+
 struct ssh_cipher_struct *ssh_get_ciphertab(void)
 {
   return ssh_ciphertab;
-- 
2.17.1


From c584a80d2941750d25917f696c5f8dd4154b7aa7 Mon Sep 17 00:00:00 2001
From: Aris Adamantiadis <aris@xxxxxxxxxxxx>
Date: Wed, 28 Feb 2018 10:24:56 -0600
Subject: [PATCH 06/12] tests: test for chacha20-poly1305@xxxxxxxxxxx

Signed-off-by: Aris Adamantiadis <aris@xxxxxxxxxxxx>
---
 tests/client/torture_algorithms.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/tests/client/torture_algorithms.c b/tests/client/torture_algorithms.c
index 76ea2cef..857ba190 100644
--- a/tests/client/torture_algorithms.c
+++ b/tests/client/torture_algorithms.c
@@ -261,6 +261,10 @@ static void torture_algorithms_blowfish_cbc_hmac_sha2_512(void **state) {
 }
 #endif
 
+static void torture_algorithms_chacha20_poly1305(void **state) {
+    test_algorithm(*state, NULL/*kex*/, "chacha20-poly1305@xxxxxxxxxxx", NULL);
+}
+
 static void torture_algorithms_zlib(void **state) {
     struct torture_state *s = *state;
     ssh_session session = s->ssh.session;
@@ -441,6 +445,9 @@ int torture_run_tests(void) {
                                         session_setup,
                                         session_teardown),
 #endif
+        cmocka_unit_test_setup_teardown(torture_algorithms_chacha20_poly1305,
+                                        session_setup,
+                                        session_teardown),
         cmocka_unit_test_setup_teardown(torture_algorithms_zlib,
                                         session_setup,
                                         session_teardown),
-- 
2.17.1


From 24b4f7e42e0aed2554e7ece79a727f43b9ee9c0d Mon Sep 17 00:00:00 2001
From: Aris Adamantiadis <aris@xxxxxxxxxxxx>
Date: Wed, 28 Feb 2018 10:24:57 -0600
Subject: [PATCH 07/12] tests: packet encryption unit testing

That code is really ugly, but it wasn't meant to be modular at all in the
first place.

Signed-off-by: Aris Adamantiadis <aris@xxxxxxxxxxxx>
---
 tests/unittests/CMakeLists.txt   |   1 +
 tests/unittests/torture_packet.c | 193 +++++++++++++++++++++++++++++++
 2 files changed, 194 insertions(+)
 create mode 100644 tests/unittests/torture_packet.c

diff --git a/tests/unittests/CMakeLists.txt b/tests/unittests/CMakeLists.txt
index ee8db1d2..0afe11b4 100644
--- a/tests/unittests/CMakeLists.txt
+++ b/tests/unittests/CMakeLists.txt
@@ -12,6 +12,7 @@ add_cmocka_test(torture_config torture_config.c ${TORTURE_LIBRARY})
 add_cmocka_test(torture_options torture_options.c ${TORTURE_LIBRARY})
 add_cmocka_test(torture_isipaddr torture_isipaddr.c ${TORTURE_LIBRARY})
 add_cmocka_test(torture_knownhosts_parsing torture_knownhosts_parsing.c ${TORTURE_LIBRARY})
+add_cmocka_test(torture_packet torture_packet.c ${TORTURE_LIBRARY})
 if (UNIX AND NOT WIN32)
     # requires ssh-keygen
     add_cmocka_test(torture_keyfiles torture_keyfiles.c ${TORTURE_LIBRARY})
diff --git a/tests/unittests/torture_packet.c b/tests/unittests/torture_packet.c
new file mode 100644
index 00000000..0e7d3f1e
--- /dev/null
+++ b/tests/unittests/torture_packet.c
@@ -0,0 +1,193 @@
+#include "config.h"
+
+#define LIBSSH_STATIC
+
+#include "torture.h"
+#include "libssh/libssh.h"
+#include "libssh/session.h"
+#include "libssh/crypto.h"
+#include "libssh/buffer.h"
+#include "libssh/socket.h"
+#include "libssh/callbacks.h"
+#include <sys/types.h>
+#include <sys/socket.h>
+#include "socket.c"
+
+uint8_t test_data[]="AThis is test data. Use it to check the validity of packet functions";
+uint8_t key[]="iekaeshoa7ooCie2shai8shahngee3ONsee3xoishooj0ojei6aeChieth1iraPh";
+uint8_t iv[]="eixaxughoomah4ui7Aew3ohxuolaifuu";
+uint8_t mac[]="thook2Jai0ahmahyae7ChuuruoPhee8Y";
+
+static uint8_t *copy_data(uint8_t *data, size_t len){
+    uint8_t *ret = malloc(len);
+    assert_non_null(ret);
+    memcpy(ret, data, len);
+    return ret;
+}
+
+static SSH_PACKET_CALLBACK(copy_packet_data){
+    uint8_t *response = user;
+    size_t len = ssh_buffer_get_len(packet);
+    (void)type;
+    (void)session;
+
+    if(len > 1024){
+        len = 1024;
+    }
+    ssh_buffer_get_data(packet, response, len);
+
+    return 0;
+}
+
+static void torture_packet(const char *cipher,
+        const char *mac_type, size_t payload_len) {
+
+    ssh_session session = ssh_new();
+    int verbosity = torture_libssh_verbosity();
+    struct ssh_crypto_struct *crypto;
+    int rc;
+    int sockets[2];
+    uint8_t buffer[1024];
+    uint8_t response[1024];
+    size_t encrypted_packet_len;
+    ssh_packet_callback callbacks[]={copy_packet_data};
+    struct ssh_packet_callbacks_struct cb = {
+            .start='A',
+            .n_callbacks=1,
+            .callbacks=callbacks,
+            .user=response
+    };
+
+    assert_non_null(session);
+    ssh_options_set(session, SSH_OPTIONS_LOG_VERBOSITY, &verbosity);
+    crypto = session->next_crypto;
+
+    rc = socketpair(AF_UNIX, SOCK_STREAM, 0, sockets);
+    assert_int_equal(rc, 0);
+
+    session->version = 2;
+    crypto->kex_methods[SSH_KEX] = strdup("curve25519-sha256@xxxxxxxxxx");
+    crypto->kex_methods[SSH_HOSTKEYS] = strdup("ssh-rsa");
+    crypto->kex_methods[SSH_CRYPT_C_S] = strdup(cipher);
+    crypto->kex_methods[SSH_CRYPT_S_C] = strdup(cipher);
+    crypto->kex_methods[SSH_MAC_C_S] = strdup(mac_type);
+    crypto->kex_methods[SSH_MAC_S_C] = strdup(mac_type);
+    crypto->kex_methods[SSH_COMP_C_S] = strdup("none");
+    crypto->kex_methods[SSH_COMP_S_C] = strdup("none");
+    crypto->kex_methods[SSH_LANG_C_S] = strdup("none");
+    crypto->kex_methods[SSH_LANG_S_C] = strdup("none");
+    rc = crypt_set_algorithms(session, 0);
+    assert_int_equal(rc, SSH_OK);
+    session->current_crypto = session->next_crypto;
+    session->next_crypto = crypto_new();
+    crypto->encryptkey = copy_data(key, sizeof(key));
+    crypto->decryptkey = copy_data(key, sizeof(key));
+    crypto->encryptIV = copy_data(iv, sizeof(iv));
+    crypto->decryptIV = copy_data(iv, sizeof(iv));
+    crypto->encryptMAC = copy_data(mac, sizeof(mac));
+    crypto->decryptMAC = copy_data(mac, sizeof(mac));
+
+    assert_non_null(session->out_buffer);
+    ssh_buffer_add_data(session->out_buffer, test_data, payload_len);
+    session->socket->fd_out = sockets[0];
+    session->socket->fd_in = -2;
+    session->socket->write_wontblock = 1;
+    rc = ssh_packet_send(session);
+    assert_int_equal(rc, SSH_OK);
+
+    rc = recv(sockets[1], buffer, sizeof(buffer), 0);
+    assert_true(rc > 0);
+    encrypted_packet_len = rc;
+    assert_in_range(encrypted_packet_len, payload_len + 4, payload_len + (32 * 3));
+    rc = send(sockets[0], buffer, encrypted_packet_len, 0);
+    assert_int_equal(rc, encrypted_packet_len);
+
+    ssh_packet_set_callbacks(session, &cb);
+    explicit_bzero(response, sizeof(response));
+    rc = ssh_packet_socket_callback(buffer, encrypted_packet_len, session);
+    assert_int_not_equal(rc, SSH_ERROR);
+    if(payload_len > 0){
+        assert_memory_equal(response, test_data+1, payload_len-1);
+    }
+    close(sockets[0]);
+    close(sockets[1]);
+    session->socket->fd_in = SSH_INVALID_SOCKET;
+    session->socket->fd_out = SSH_INVALID_SOCKET;
+    ssh_free(session);
+}
+
+static void torture_packet_aes128_ctr() {
+    int i;
+    for (i=1;i<256;++i){
+        torture_packet("aes128-ctr","hmac-sha1",i);
+    }
+}
+
+static void torture_packet_aes192_ctr(){
+    int i;
+    for (i=1;i<256;++i){
+        torture_packet("aes192-ctr","hmac-sha1",i);
+    }
+}
+
+static void torture_packet_aes256_ctr(){
+    int i;
+    for (i=1;i<256;++i){
+        torture_packet("aes256-ctr","hmac-sha1",i);
+    }
+}
+
+static void torture_packet_aes128_cbc() {
+    int i;
+    for (i=1;i<256;++i){
+        torture_packet("aes128-cbc","hmac-sha1",i);
+    }
+}
+
+static void torture_packet_aes192_cbc(){
+    int i;
+    for (i=1;i<256;++i){
+        torture_packet("aes192-cbc","hmac-sha1",i);
+    }
+}
+
+static void torture_packet_aes256_cbc(){
+    int i;
+    for (i=1;i<256;++i){
+        torture_packet("aes256-cbc","hmac-sha1",i);
+    }
+}
+
+static void torture_packet_3des_cbc(){
+    int i;
+    for (i=1;i<256;++i){
+        torture_packet("3des-cbc","hmac-sha1",i);
+    }
+}
+
+static void torture_packet_chacha20(){
+    int i;
+    for (i=1;i<256;++i){
+        torture_packet("chacha20-poly1305@xxxxxxxxxxx","none",i);
+    }
+}
+
+int torture_run_tests(void) {
+    int rc;
+    struct CMUnitTest tests[] = {
+        cmocka_unit_test(torture_packet_aes128_ctr),
+        cmocka_unit_test(torture_packet_aes192_ctr),
+        cmocka_unit_test(torture_packet_aes256_ctr),
+        cmocka_unit_test(torture_packet_aes128_cbc),
+        cmocka_unit_test(torture_packet_aes192_cbc),
+        cmocka_unit_test(torture_packet_aes256_cbc),
+        cmocka_unit_test(torture_packet_3des_cbc),
+        cmocka_unit_test(torture_packet_chacha20)
+    };
+
+    ssh_init();
+    torture_filter_tests(tests);
+    rc = cmocka_run_group_tests(tests, NULL, NULL);
+    ssh_finalize();
+    return rc;
+}
-- 
2.17.1


From a8d17d200f0e4c79676f599174f79a28f41f28d5 Mon Sep 17 00:00:00 2001
From: Aris Adamantiadis <aris@xxxxxxxxxxxx>
Date: Wed, 28 Feb 2018 10:24:58 -0600
Subject: [PATCH 08/12] tests: send more packets of various sizes

Signed-off-by: Aris Adamantiadis <aris@xxxxxxxxxxxx>
---
 tests/client/torture_algorithms.c | 19 ++++++++++++++++++-
 1 file changed, 18 insertions(+), 1 deletion(-)

diff --git a/tests/client/torture_algorithms.c b/tests/client/torture_algorithms.c
index 857ba190..edeb697d 100644
--- a/tests/client/torture_algorithms.c
+++ b/tests/client/torture_algorithms.c
@@ -26,6 +26,7 @@
 #include "torture.h"
 #include "libssh/libssh.h"
 #include "libssh/priv.h"
+#include "libssh/session.h"
 
 #include <errno.h>
 #include <sys/types.h>
@@ -49,7 +50,6 @@ static int session_setup(void **state) {
     int verbosity = torture_libssh_verbosity();
     struct passwd *pwd;
     int rc;
-
     pwd = getpwnam("bob");
     assert_non_null(pwd);
 
@@ -80,6 +80,15 @@ static void test_algorithm(ssh_session session,
                            const char *cipher,
                            const char *hmac) {
     int rc;
+    char data[256];
+    size_t len_to_test[] = {
+        1, 2, 3, 4, 5, 6, 7, 8, 10,
+        12, 15, 16, 20,
+        31, 32, 33,
+        63, 64, 65,
+        100, 127, 128
+    };
+    unsigned int i;
 
     int verbosity = torture_libssh_verbosity();
     ssh_options_set(session, SSH_OPTIONS_LOG_VERBOSITY, &verbosity);
@@ -106,6 +115,14 @@ static void test_algorithm(ssh_session session,
     rc = ssh_connect(session);
     assert_int_equal(rc, SSH_OK);
 
+    /* send ignore packets of all sizes */
+    memset(data, 0, sizeof(data));
+    for (i = 0; i < (sizeof(len_to_test) / sizeof(size_t)); i++) {
+        memset(data, 'A', len_to_test[i]);
+        ssh_send_ignore(session, data);
+        ssh_handle_packets(session, 50);
+    }
+
     rc = ssh_userauth_none(session, NULL);
     if (rc != SSH_OK) {
         rc = ssh_get_error_code(session);
-- 
2.17.1


From 2b7d948f2f70f870ba0592f3f088b30305e5622d Mon Sep 17 00:00:00 2001
From: Alberto Aguirre <albaguirre@xxxxxxxxx>
Date: Wed, 28 Feb 2018 10:25:02 -0600
Subject: [PATCH 09/12] packet_crypt: Avoid setting keys every time

Avoid setting keys on every packet decrypt or encrypt operation.

Signed-off-by: Alberto Aguirre <albaguirre@xxxxxxxxx>
---
 src/packet_crypt.c | 13 -------------
 1 file changed, 13 deletions(-)

diff --git a/src/packet_crypt.c b/src/packet_crypt.c
index fb09a225..68103afb 100644
--- a/src/packet_crypt.c
+++ b/src/packet_crypt.c
@@ -117,13 +117,6 @@ int ssh_packet_decrypt(ssh_session session,
         return SSH_ERROR;
     }
 
-    rc = crypto->set_decrypt_key(crypto,
-                                 session->current_crypto->decryptkey,
-                                 session->current_crypto->decryptIV);
-    if (rc < 0) {
-        return -1;
-    }
-
     if (crypto->aead_decrypt != NULL) {
         return crypto->aead_decrypt(crypto,
                                     source,
@@ -177,12 +170,6 @@ unsigned char *ssh_packet_encrypt(ssh_session session, void *data, uint32_t len)
       hmac_update(ctx,data,len);
       hmac_final(ctx,session->current_crypto->hmacbuf,&finallen);
 
-      if (crypto->set_encrypt_key(crypto, session->current_crypto->encryptkey,
-          session->current_crypto->encryptIV) < 0) {
-        SAFE_FREE(out);
-        return NULL;
-      }
-
 #ifdef DEBUG_CRYPTO
       ssh_print_hexa("mac: ",data,hmac_digest_len(type));
       if (finallen != hmac_digest_len(type)) {
-- 
2.17.1


From a6502beeed0518b5cb1358be109929465f3f3c6d Mon Sep 17 00:00:00 2001
From: Alberto Aguirre <albaguirre@xxxxxxxxx>
Date: Wed, 28 Feb 2018 10:25:04 -0600
Subject: [PATCH 10/12] torture_packet: Set encryption/decryption keys

Signed-off-by: Alberto Aguirre <albaguirre@xxxxxxxxx>
---
 tests/unittests/torture_packet.c | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/tests/unittests/torture_packet.c b/tests/unittests/torture_packet.c
index 0e7d3f1e..a01ea218 100644
--- a/tests/unittests/torture_packet.c
+++ b/tests/unittests/torture_packet.c
@@ -45,6 +45,8 @@ static void torture_packet(const char *cipher,
     ssh_session session = ssh_new();
     int verbosity = torture_libssh_verbosity();
     struct ssh_crypto_struct *crypto;
+    struct ssh_cipher_struct *in_cipher;
+    struct ssh_cipher_struct *out_cipher;
     int rc;
     int sockets[2];
     uint8_t buffer[1024];
@@ -87,6 +89,18 @@ static void torture_packet(const char *cipher,
     crypto->encryptMAC = copy_data(mac, sizeof(mac));
     crypto->decryptMAC = copy_data(mac, sizeof(mac));
 
+    in_cipher = session->current_crypto->in_cipher;
+    rc = in_cipher->set_decrypt_key(in_cipher,
+                                    session->current_crypto->decryptkey,
+                                    session->current_crypto->decryptIV);
+    assert_int_equal(rc, SSH_OK);
+
+    out_cipher = session->current_crypto->out_cipher;
+    rc = out_cipher->set_encrypt_key(out_cipher,
+                                     session->current_crypto->encryptkey,
+                                     session->current_crypto->encryptIV);
+    assert_int_equal(rc, SSH_OK);
+
     assert_non_null(session->out_buffer);
     ssh_buffer_add_data(session->out_buffer, test_data, payload_len);
     session->socket->fd_out = sockets[0];
-- 
2.17.1


From 5b0860449bae17b29babdcda04271340972007c3 Mon Sep 17 00:00:00 2001
From: Jon Simons <jon@xxxxxxxxxxxxx>
Date: Wed, 28 Feb 2018 10:24:59 -0600
Subject: [PATCH 11/12] pkd: add passes for chacha20-poly1305@xxxxxxxxxxx
 cipher

---
 tests/pkd/pkd_hello.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/tests/pkd/pkd_hello.c b/tests/pkd/pkd_hello.c
index e0c0cbf6..ace8d8e6 100644
--- a/tests/pkd/pkd_hello.c
+++ b/tests/pkd/pkd_hello.c
@@ -252,6 +252,7 @@ static int torture_pkd_setup_ecdsa_521(void **state) {
 #endif
 
 #ifdef HAVE_DSA
+#define CHACHA20 "chacha20-poly1305@xxxxxxxxxxx"
 #define PKDTESTS_CIPHER(f, client, ciphercmd) \
     /* Ciphers. */ \
     f(client, rsa_3des_cbc,            ciphercmd("3des-cbc"),      setup_rsa,        teardown) \
@@ -260,24 +261,28 @@ static int torture_pkd_setup_ecdsa_521(void **state) {
     f(client, rsa_aes256_cbc,          ciphercmd("aes256-cbc"),    setup_rsa,        teardown) \
     f(client, rsa_aes256_ctr,          ciphercmd("aes256-ctr"),    setup_rsa,        teardown) \
     f(client, rsa_blowfish_cbc,        ciphercmd("blowfish-cbc"),  setup_rsa,        teardown) \
+    f(client, rsa_chacha20,            ciphercmd(CHACHA20),        setup_rsa,        teardown) \
     f(client, dsa_3des_cbc,            ciphercmd("3des-cbc"),      setup_dsa,        teardown) \
     f(client, dsa_aes128_cbc,          ciphercmd("aes128-cbc"),    setup_dsa,        teardown) \
     f(client, dsa_aes128_ctr,          ciphercmd("aes128-ctr"),    setup_dsa,        teardown) \
     f(client, dsa_aes256_cbc,          ciphercmd("aes256-cbc"),    setup_dsa,        teardown) \
     f(client, dsa_aes256_ctr,          ciphercmd("aes256-ctr"),    setup_dsa,        teardown) \
     f(client, dsa_blowfish_cbc,        ciphercmd("blowfish-cbc"),  setup_dsa,        teardown) \
+    f(client, dsa_chacha20,            ciphercmd(CHACHA20),        setup_dsa,        teardown) \
     f(client, ecdsa_256_3des_cbc,      ciphercmd("3des-cbc"),      setup_ecdsa_256,  teardown) \
     f(client, ecdsa_256_aes128_cbc,    ciphercmd("aes128-cbc"),    setup_ecdsa_256,  teardown) \
     f(client, ecdsa_256_aes128_ctr,    ciphercmd("aes128-ctr"),    setup_ecdsa_256,  teardown) \
     f(client, ecdsa_256_aes256_cbc,    ciphercmd("aes256-cbc"),    setup_ecdsa_256,  teardown) \
     f(client, ecdsa_256_aes256_ctr,    ciphercmd("aes256-ctr"),    setup_ecdsa_256,  teardown) \
     f(client, ecdsa_256_blowfish_cbc,  ciphercmd("blowfish-cbc"),  setup_ecdsa_256,  teardown) \
+    f(client, ecdsa_256_chacha20,      ciphercmd(CHACHA20),        setup_ecdsa_256,  teardown) \
     f(client, ecdsa_384_3des_cbc,      ciphercmd("3des-cbc"),      setup_ecdsa_384,  teardown) \
     f(client, ecdsa_384_aes128_cbc,    ciphercmd("aes128-cbc"),    setup_ecdsa_384,  teardown) \
     f(client, ecdsa_384_aes128_ctr,    ciphercmd("aes128-ctr"),    setup_ecdsa_384,  teardown) \
     f(client, ecdsa_384_aes256_cbc,    ciphercmd("aes256-cbc"),    setup_ecdsa_384,  teardown) \
     f(client, ecdsa_384_aes256_ctr,    ciphercmd("aes256-ctr"),    setup_ecdsa_384,  teardown) \
     f(client, ecdsa_384_blowfish_cbc,  ciphercmd("blowfish-cbc"),  setup_ecdsa_384,  teardown) \
+    f(client, ecdsa_384_chacha20,      ciphercmd(CHACHA20),        setup_ecdsa_384,  teardown) \
     f(client, ecdsa_521_3des_cbc,      ciphercmd("3des-cbc"),      setup_ecdsa_521,  teardown) \
     f(client, ecdsa_521_aes128_cbc,    ciphercmd("aes128-cbc"),    setup_ecdsa_521,  teardown) \
     f(client, ecdsa_521_aes128_ctr,    ciphercmd("aes128-ctr"),    setup_ecdsa_521,  teardown) \
@@ -310,7 +315,7 @@ static int torture_pkd_setup_ecdsa_521(void **state) {
     f(client, ecdsa_521_aes128_ctr,    ciphercmd("aes128-ctr"),    setup_ecdsa_521,  teardown) \
     f(client, ecdsa_521_aes256_cbc,    ciphercmd("aes256-cbc"),    setup_ecdsa_521,  teardown) \
     f(client, ecdsa_521_aes256_ctr,    ciphercmd("aes256-ctr"),    setup_ecdsa_521,  teardown) \
-    f(client, ecdsa_521_blowfish_cbc,  ciphercmd("blowfish-cbc"),  setup_ecdsa_521,  teardown)
+    f(client, ecdsa_521_chacha20,      ciphercmd(CHACHA20),        setup_ecdsa_521,  teardown)
 #endif
 
 #ifdef HAVE_DSA
-- 
2.17.1


From 250d8132f34700d9eb9a67425bd0006343616182 Mon Sep 17 00:00:00 2001
From: Jon Simons <jon@xxxxxxxxxxxxx>
Date: Wed, 28 Feb 2018 10:25:00 -0600
Subject: [PATCH 12/12] pkd: move chacha20-poly1305@xxxxxxxxxxx tests to
 OPENSSHONLY section

Dropbear does not currently implement the 'chacha20-poly1305@xxxxxxxxxxx'
cipher, so move it into the OPENSSHONLY suite.
---
 tests/pkd/pkd_hello.c | 13 +++++++------
 1 file changed, 7 insertions(+), 6 deletions(-)

diff --git a/tests/pkd/pkd_hello.c b/tests/pkd/pkd_hello.c
index ace8d8e6..7fef0c2c 100644
--- a/tests/pkd/pkd_hello.c
+++ b/tests/pkd/pkd_hello.c
@@ -252,7 +252,6 @@ static int torture_pkd_setup_ecdsa_521(void **state) {
 #endif
 
 #ifdef HAVE_DSA
-#define CHACHA20 "chacha20-poly1305@xxxxxxxxxxx"
 #define PKDTESTS_CIPHER(f, client, ciphercmd) \
     /* Ciphers. */ \
     f(client, rsa_3des_cbc,            ciphercmd("3des-cbc"),      setup_rsa,        teardown) \
@@ -261,28 +260,24 @@ static int torture_pkd_setup_ecdsa_521(void **state) {
     f(client, rsa_aes256_cbc,          ciphercmd("aes256-cbc"),    setup_rsa,        teardown) \
     f(client, rsa_aes256_ctr,          ciphercmd("aes256-ctr"),    setup_rsa,        teardown) \
     f(client, rsa_blowfish_cbc,        ciphercmd("blowfish-cbc"),  setup_rsa,        teardown) \
-    f(client, rsa_chacha20,            ciphercmd(CHACHA20),        setup_rsa,        teardown) \
     f(client, dsa_3des_cbc,            ciphercmd("3des-cbc"),      setup_dsa,        teardown) \
     f(client, dsa_aes128_cbc,          ciphercmd("aes128-cbc"),    setup_dsa,        teardown) \
     f(client, dsa_aes128_ctr,          ciphercmd("aes128-ctr"),    setup_dsa,        teardown) \
     f(client, dsa_aes256_cbc,          ciphercmd("aes256-cbc"),    setup_dsa,        teardown) \
     f(client, dsa_aes256_ctr,          ciphercmd("aes256-ctr"),    setup_dsa,        teardown) \
     f(client, dsa_blowfish_cbc,        ciphercmd("blowfish-cbc"),  setup_dsa,        teardown) \
-    f(client, dsa_chacha20,            ciphercmd(CHACHA20),        setup_dsa,        teardown) \
     f(client, ecdsa_256_3des_cbc,      ciphercmd("3des-cbc"),      setup_ecdsa_256,  teardown) \
     f(client, ecdsa_256_aes128_cbc,    ciphercmd("aes128-cbc"),    setup_ecdsa_256,  teardown) \
     f(client, ecdsa_256_aes128_ctr,    ciphercmd("aes128-ctr"),    setup_ecdsa_256,  teardown) \
     f(client, ecdsa_256_aes256_cbc,    ciphercmd("aes256-cbc"),    setup_ecdsa_256,  teardown) \
     f(client, ecdsa_256_aes256_ctr,    ciphercmd("aes256-ctr"),    setup_ecdsa_256,  teardown) \
     f(client, ecdsa_256_blowfish_cbc,  ciphercmd("blowfish-cbc"),  setup_ecdsa_256,  teardown) \
-    f(client, ecdsa_256_chacha20,      ciphercmd(CHACHA20),        setup_ecdsa_256,  teardown) \
     f(client, ecdsa_384_3des_cbc,      ciphercmd("3des-cbc"),      setup_ecdsa_384,  teardown) \
     f(client, ecdsa_384_aes128_cbc,    ciphercmd("aes128-cbc"),    setup_ecdsa_384,  teardown) \
     f(client, ecdsa_384_aes128_ctr,    ciphercmd("aes128-ctr"),    setup_ecdsa_384,  teardown) \
     f(client, ecdsa_384_aes256_cbc,    ciphercmd("aes256-cbc"),    setup_ecdsa_384,  teardown) \
     f(client, ecdsa_384_aes256_ctr,    ciphercmd("aes256-ctr"),    setup_ecdsa_384,  teardown) \
     f(client, ecdsa_384_blowfish_cbc,  ciphercmd("blowfish-cbc"),  setup_ecdsa_384,  teardown) \
-    f(client, ecdsa_384_chacha20,      ciphercmd(CHACHA20),        setup_ecdsa_384,  teardown) \
     f(client, ecdsa_521_3des_cbc,      ciphercmd("3des-cbc"),      setup_ecdsa_521,  teardown) \
     f(client, ecdsa_521_aes128_cbc,    ciphercmd("aes128-cbc"),    setup_ecdsa_521,  teardown) \
     f(client, ecdsa_521_aes128_ctr,    ciphercmd("aes128-ctr"),    setup_ecdsa_521,  teardown) \
@@ -319,16 +314,21 @@ static int torture_pkd_setup_ecdsa_521(void **state) {
 #endif
 
 #ifdef HAVE_DSA
+#define CHACHA20 "chacha20-poly1305@xxxxxxxxxxx"
 #define PKDTESTS_CIPHER_OPENSSHONLY(f, client, ciphercmd) \
     /* Ciphers. */ \
     f(client, rsa_aes192_cbc,          ciphercmd("aes192-cbc"),    setup_rsa,        teardown) \
     f(client, rsa_aes192_ctr,          ciphercmd("aes192-ctr"),    setup_rsa,        teardown) \
+    f(client, rsa_chacha20,            ciphercmd(CHACHA20),        setup_rsa,        teardown) \
     f(client, dsa_aes192_cbc,          ciphercmd("aes192-cbc"),    setup_dsa,        teardown) \
     f(client, dsa_aes192_ctr,          ciphercmd("aes192-ctr"),    setup_dsa,        teardown) \
+    f(client, dsa_chacha20,            ciphercmd(CHACHA20),        setup_dsa,        teardown) \
     f(client, ecdsa_256_aes192_cbc,    ciphercmd("aes192-cbc"),    setup_ecdsa_256,  teardown) \
     f(client, ecdsa_256_aes192_ctr,    ciphercmd("aes192-ctr"),    setup_ecdsa_256,  teardown) \
+    f(client, ecdsa_256_chacha20,      ciphercmd(CHACHA20),        setup_ecdsa_256,  teardown) \
     f(client, ecdsa_384_aes192_cbc,    ciphercmd("aes192-cbc"),    setup_ecdsa_384,  teardown) \
     f(client, ecdsa_384_aes192_ctr,    ciphercmd("aes192-ctr"),    setup_ecdsa_384,  teardown) \
+    f(client, ecdsa_384_chacha20,      ciphercmd(CHACHA20),        setup_ecdsa_384,  teardown) \
     f(client, ecdsa_521_aes192_cbc,    ciphercmd("aes192-cbc"),    setup_ecdsa_521,  teardown) \
     f(client, ecdsa_521_aes192_ctr,    ciphercmd("aes192-ctr"),    setup_ecdsa_521,  teardown)
 #else
@@ -341,7 +341,8 @@ static int torture_pkd_setup_ecdsa_521(void **state) {
     f(client, ecdsa_384_aes192_cbc,    ciphercmd("aes192-cbc"),    setup_ecdsa_384,  teardown) \
     f(client, ecdsa_384_aes192_ctr,    ciphercmd("aes192-ctr"),    setup_ecdsa_384,  teardown) \
     f(client, ecdsa_521_aes192_cbc,    ciphercmd("aes192-cbc"),    setup_ecdsa_521,  teardown) \
-    f(client, ecdsa_521_aes192_ctr,    ciphercmd("aes192-ctr"),    setup_ecdsa_521,  teardown)
+    f(client, ecdsa_521_aes192_ctr,    ciphercmd("aes192-ctr"),    setup_ecdsa_521,  teardown) \
+    f(client, ecdsa_521_chacha20,      ciphercmd(CHACHA20),        setup_ecdsa_521,  teardown)
 #endif
 
 #ifdef HAVE_DSA
-- 
2.17.1


Follow-Ups:
Re: Missing signed-off for pkg chacha20 patchesJon Simons <jon@xxxxxxxxxxxxx>
Archive administrator: postmaster@lists.cynapses.org