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

[PATCH 4/4] chachapoly: add chachapoly structures with compilation conditions (chacha20-poly1305@xxxxxxxxxxx support)


From 78b054eae890e36a556d1ed46df73b5f15f5df69 Mon Sep 17 00:00:00 2001
From: Meng Tan <mtan@xxxxxxxxxx>
Date: Mon, 18 Sep 2017 11:34:50 +0200
Subject: [PATCH 4/4] chachapoly: add chachapoly structures with compilation
 conditions (chacha20-poly1305@xxxxxxxxxxx support)

Signed-off-by: Meng Tan <mtan@xxxxxxxxxx>
---
 include/libssh/crypto.h  |  7 +++++
 include/libssh/wrapper.h |  4 +++
 src/kex.c                | 14 ++++++---
 src/libcrypto.c          | 72 ++++++++++++++++++++++++++++++++++++++++++++++
 src/libgcrypt.c          | 74 ++++++++++++++++++++++++++++++++++++++++++++++++
 src/packet_crypt.c       | 13 +++++++++
 6 files changed, 180 insertions(+), 4 deletions(-)

diff --git a/include/libssh/crypto.h b/include/libssh/crypto.h
index 0cdf96b..0465f21 100644
--- a/include/libssh/crypto.h
+++ b/include/libssh/crypto.h
@@ -32,6 +32,10 @@
 #endif
 #include "libssh/wrapper.h"
 
+#ifdef WITH_CHACHAPOLY
+#include "libssh/chachapoly.h"
+#endif
+
 #ifdef cbc_encrypt
 #undef cbc_encrypt
 #endif
@@ -144,6 +148,9 @@ struct ssh_cipher_struct {
     EVP_CIPHER_CTX *ctx;
 #endif
     unsigned int authlen; /* length of mac for authenticated ciphers */
+#ifdef WITH_CHACHAPOLY
+    struct chachapoly_ctx *chachapoly;
+#endif
     unsigned int keysize; /* bytes of key used. != keylen */
     /* sets the new key for immediate use */
     int (*set_encrypt_key)(struct ssh_cipher_struct *cipher, void *key, void *IV);
diff --git a/include/libssh/wrapper.h b/include/libssh/wrapper.h
index 09a9ee9..8569d5f 100644
--- a/include/libssh/wrapper.h
+++ b/include/libssh/wrapper.h
@@ -101,5 +101,9 @@ void ssh_reseed(void);
 void ssh_cipher_clear(struct ssh_cipher_struct *cipher);
 struct ssh_hmac_struct *ssh_get_hmactab(void);
 const char *ssh_hmac_type_to_string(enum ssh_hmac_e hmac_type);
+#ifdef WITH_CHACHAPOLY
+uint32_t chachapoly_getlength(struct ssh_cipher_struct *cipher, const void* in,
+                              unsigned long len, unsigned int seqnr);
+#endif
 
 #endif /* WRAPPER_H_ */
diff --git a/src/kex.c b/src/kex.c
index 21523fa..694a6bb 100644
--- a/src/kex.c
+++ b/src/kex.c
@@ -65,6 +65,12 @@
 # define DES_SUPPORTED "3des-cbc,des-cbc-ssh1"
 #endif /* HAVE_LIBCRYPTO */
 
+#ifdef WITH_CHACHAPOLY
+#define CHACHAPOLY "chacha20-poly1305@xxxxxxxxxxx,"
+#else
+#define CHACHAPOLY ""
+#endif
+
 #ifdef WITH_ZLIB
 #define ZLIB "none,zlib,zlib@xxxxxxxxxxx"
 #else
@@ -92,8 +98,8 @@
 static const char *default_methods[] = {
   KEY_EXCHANGE,
   HOSTKEYS,
-  AES BLOWFISH DES,
-  AES BLOWFISH DES,
+  AES CHACHAPOLY BLOWFISH DES,
+  AES CHACHAPOLY BLOWFISH DES,
   "hmac-sha2-256,hmac-sha2-512,hmac-sha1",
   "hmac-sha2-256,hmac-sha2-512,hmac-sha1",
   "none",
@@ -107,8 +113,8 @@ static const char *default_methods[] = {
 static const char *supported_methods[] = {
   KEY_EXCHANGE,
   HOSTKEYS,
-  AES BLOWFISH DES_SUPPORTED,
-  AES BLOWFISH DES_SUPPORTED,
+  AES CHACHAPOLY BLOWFISH DES_SUPPORTED,
+  AES CHACHAPOLY BLOWFISH DES_SUPPORTED,
   "hmac-sha2-256,hmac-sha2-512,hmac-sha1",
   "hmac-sha2-256,hmac-sha2-512,hmac-sha1",
   ZLIB,
diff --git a/src/libcrypto.c b/src/libcrypto.c
index 0c5bf92..22fac06 100644
--- a/src/libcrypto.c
+++ b/src/libcrypto.c
@@ -60,6 +60,10 @@
 
 #include "libssh/crypto.h"
 
+#ifdef WITH_CHACHAPOLY
+#include "libssh/chachapoly.h"
+#endif
+
 struct ssh_mac_ctx_struct {
   enum ssh_mac_e mac_type;
   union {
@@ -718,6 +722,60 @@ static void des_cleanup(struct ssh_cipher_struct *cipher){
 
 #endif /* HAS_DES */
 
+#ifdef WITH_CHACHAPOLY
+static int alloc_chachapoly(struct ssh_cipher_struct *cipher) {
+    cipher->chachapoly = malloc(sizeof(struct chachapoly_ctx));
+    if (cipher->chachapoly == NULL) {
+      return -1;
+    }
+
+    return 0;
+}
+
+static int chachapoly_set_key(struct ssh_cipher_struct *cipher, void *key,
+                              void *IV) {
+    (void)IV;
+    if (cipher->chachapoly == NULL) {
+        if (alloc_chachapoly(cipher) < 0) {
+            return -1;
+        }
+        if (chachapoly_init(cipher->chachapoly,key,cipher->keysize / 8) < 0) {
+            return -1;
+        }
+    }
+    return 0;
+}
+
+static int chachapoly_encrypt(struct ssh_cipher_struct *cipher, void *in, void *out,
+    unsigned long len, unsigned int seqnr) {
+    int res;
+    res = chachapoly_crypt(cipher->chachapoly, seqnr, out, in, len - 4, 4,
+                           cipher->authlen, 1);
+    return res;
+}
+
+static int chachapoly_decrypt(struct ssh_cipher_struct *cipher, void *in, void *out,
+    unsigned long len, unsigned int seqnr) {
+    int res;
+    res = chachapoly_crypt(cipher->chachapoly, seqnr, out, in, len - 4, 4,
+                           cipher->authlen, 0);
+    return res;
+}
+
+static void chachapoly_cleanup(struct ssh_cipher_struct *cipher) {
+    if (cipher->chachapoly != NULL) {
+        BURN_BUFFER(cipher->chachapoly, sizeof(struct chachapoly_ctx));
+        SAFE_FREE(cipher->chachapoly);
+    }
+}
+uint32_t chachapoly_getlength(struct ssh_cipher_struct *cipher, const void* in,
+                              unsigned long len, unsigned int seqnr) {
+    uint32_t plenp = 0;
+    chachapoly_get_length(cipher->chachapoly, &plenp, seqnr, in, len);
+    return plenp;
+}
+#endif /* WITH_CHACHAPOLY */
+
 /*
  * The table of supported ciphers
  */
@@ -890,6 +948,20 @@ static struct ssh_cipher_struct ssh_ciphertab[] = {
     .cleanup = des_cleanup
   },
 #endif /* HAS_DES */
+#ifdef WITH_CHACHAPOLY
+  {
+      .name = "chacha20-poly1305@xxxxxxxxxxx",
+      .blocksize = 8,
+      .ciphertype = SSH_CHACHAPOLY,
+      .authlen = 16,
+      .keysize = 512,
+      .set_encrypt_key = chachapoly_set_key,
+      .set_decrypt_key = chachapoly_set_key,
+      .encrypt = chachapoly_encrypt,
+      .decrypt = chachapoly_decrypt,
+      .cleanup = chachapoly_cleanup
+  },
+#endif
   {
     .name = NULL
   }
diff --git a/src/libgcrypt.c b/src/libgcrypt.c
index 22eaa00..aa7cdb1 100644
--- a/src/libgcrypt.c
+++ b/src/libgcrypt.c
@@ -33,6 +33,10 @@
 #ifdef HAVE_LIBGCRYPT
 #include <gcrypt.h>
 
+#ifdef WITH_CHACHAPOLY
+#include "libssh/chachapoly.h"
+#endif
+
 struct ssh_mac_ctx_struct {
   enum ssh_mac_e mac_type;
   gcry_md_hd_t ctx;
@@ -543,6 +547,60 @@ static int des3_1_decrypt(struct ssh_cipher_struct *cipher, void *in,
   return SSH_CRYPT_OK;
 }
 
+#ifdef WITH_CHACHAPOLY
+static int alloc_chachapoly(struct ssh_cipher_struct *cipher) {
+    cipher->chachapoly = malloc(sizeof(struct chachapoly_ctx));
+    if (cipher->chachapoly == NULL) {
+      return -1;
+    }
+
+    return 0;
+}
+
+static int chachapoly_set_key(struct ssh_cipher_struct *cipher, void *key,
+                              void *IV) {
+    (void)IV;
+    if (cipher->chachapoly == NULL) {
+        if (alloc_chachapoly(cipher) < 0) {
+            return -1;
+        }
+        if (chachapoly_init(cipher->chachapoly,key,cipher->keysize / 8) < 0) {
+            return -1;
+        }
+    }
+    return 0;
+}
+
+static int chachapoly_encrypt(struct ssh_cipher_struct *cipher, void *in, void *out,
+    unsigned long len, unsigned int seqnr) {
+    int res;
+    res = chachapoly_crypt(cipher->chachapoly, seqnr, out, in, len - 4, 4,
+                           cipher->authlen, 1);
+    return res;
+}
+
+static int chachapoly_decrypt(struct ssh_cipher_struct *cipher, void *in, void *out,
+    unsigned long len, unsigned int seqnr) {
+    int res;
+    res = chachapoly_crypt(cipher->chachapoly, seqnr, out, in, len - 4, 4,
+                           cipher->authlen, 0);
+    return res;
+}
+
+static void chachapoly_cleanup(struct ssh_cipher_struct *cipher) {
+    if (cipher->chachapoly != NULL) {
+        BURN_BUFFER(cipher->chachapoly, sizeof(struct chachapoly_ctx));
+        SAFE_FREE(cipher->chachapoly);
+    }
+}
+uint32_t chachapoly_getlength(struct ssh_cipher_struct *cipher, const void* in,
+                              unsigned long len, unsigned int seqnr) {
+    uint32_t plenp = 0;
+    chachapoly_get_length(cipher->chachapoly, &plenp, seqnr, in, len);
+    return plenp;
+}
+#endif /* WITH_CHACHAPOLY */
+
 /* the table of supported ciphers */
 static struct ssh_cipher_struct ssh_ciphertab[] = {
   {
@@ -665,6 +723,22 @@ static struct ssh_cipher_struct ssh_ciphertab[] = {
     .encrypt     = des1_1_encrypt,
     .decrypt     = des1_1_decrypt
   },
+#ifdef WITH_CHACHAPOLY
+  {
+    .name            = "chacha20-poly1305@xxxxxxxxxxx",
+    .blocksize       = 8,
+    .ciphertype      = SSH_CHACHAPOLY,
+    .keylen          = 64,
+    .key             = NULL,
+    .authlen         = 16,
+    .keysize         = 512,
+    .set_encrypt_key = chachapoly_set_key,
+    .set_decrypt_key = chachapoly_set_key,
+    .encrypt         = chachapoly_encrypt,
+    .decrypt         = chachapoly_decrypt,
+    .cleanup         = chachapoly_cleanup,
+  },
+#endif
   {
     .name            = NULL,
     .blocksize       = 0,
diff --git a/src/packet_crypt.c b/src/packet_crypt.c
index 6265844..592d9af 100644
--- a/src/packet_crypt.c
+++ b/src/packet_crypt.c
@@ -48,6 +48,19 @@ uint32_t ssh_packet_decrypt_len(ssh_session session, char *crypted){
   uint32_t decrypted;
 
   if (session->current_crypto) {
+#ifdef WITH_CHACHAPOLY
+      if (session->current_crypto->in_cipher->ciphertype == SSH_CHACHAPOLY) {
+          if (session->current_crypto->in_cipher->set_decrypt_key(
+                  session->current_crypto->in_cipher,
+                  session->current_crypto->decryptkey,
+                  session->current_crypto->decryptIV) < 0) {
+              return 0;
+          }
+          decrypted = chachapoly_getlength(session->current_crypto->in_cipher, crypted,
+                                           4, session->recv_seq);
+          return decrypted;
+      }
+#endif
     if (ssh_packet_decrypt(session, crypted,
           session->current_crypto->in_cipher->blocksize) < 0) {
       return 0;
-- 
2.1.4


Archive administrator: postmaster@lists.cynapses.org