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 <[email protected]>
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 <[email protected]>
Reviewed-by: Andreas Schneider <[email protected]>
---
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 <[email protected]>
Date: Wed, 28 Feb 2018 10:24:52 -0600
Subject: [PATCH 02/12] cmake: detect "bounded" compiler attribute
Signed-off-by: Aris Adamantiadis <[email protected]>
Reviewed-by: Andreas Schneider <[email protected]>
---
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 <[email protected]>
Date: Wed, 28 Feb 2018 10:24:53 -0600
Subject: [PATCH 03/12] chacha: packet encryption
Signed-off-by: Aris Adamantiadis <[email protected]>
---
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 = "[email protected]",
+ .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 "[email protected],"
+
#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 = "[email protected]"
+ },
{
.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, "[email protected]");
+ 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 <[email protected]>
Date: Wed, 28 Feb 2018 10:24:54 -0600
Subject: [PATCH 04/12] chacha: packet decryption
Signed-off-by: Aris Adamantiadis <[email protected]>
---
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 <[email protected]>
Date: Wed, 28 Feb 2018 10:24:55 -0600
Subject: [PATCH 05/12] libgcrypt: make it compatible with chacha20
Signed-off-by: Aris Adamantiadis <[email protected]>
---
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 = "[email protected]"
+ },
{
.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, "[email protected]");
+ 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 <[email protected]>
Date: Wed, 28 Feb 2018 10:24:56 -0600
Subject: [PATCH 06/12] tests: test for [email protected]
Signed-off-by: Aris Adamantiadis <[email protected]>
---
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*/, "[email protected]", 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 <[email protected]>
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 <[email protected]>
---
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("[email protected]");
+ 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("[email protected]","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 <[email protected]>
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 <[email protected]>
---
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 <[email protected]>
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 <[email protected]>
---
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 <[email protected]>
Date: Wed, 28 Feb 2018 10:25:04 -0600
Subject: [PATCH 10/12] torture_packet: Set encryption/decryption keys
Signed-off-by: Alberto Aguirre <[email protected]>
---
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 <[email protected]>
Date: Wed, 28 Feb 2018 10:24:59 -0600
Subject: [PATCH 11/12] pkd: add passes for [email protected]
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 "[email protected]"
#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 <[email protected]>
Date: Wed, 28 Feb 2018 10:25:00 -0600
Subject: [PATCH 12/12] pkd: move [email protected] tests to
OPENSSHONLY section
Dropbear does not currently implement the '[email protected]'
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 "[email protected]"
#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 "[email protected]"
#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