From a53cebba34e6cde2cd4cdc7daec593992cd47e21 Mon Sep 17 00:00:00 2001
From: "brian m. carlson" <sandals@crustytoothpaste.net>
Date: Sun, 6 Sep 2015 14:02:44 +0000
Subject: [PATCH] Add support for HMAC-SHA-256 and HMAC-SHA-512.

Implement support for these algorithms and wire them up to the libgcrypt
and OpenSSL backends.  Increase the maximum MAC buffer size to 64 bytes
to prevent buffer overflows.  Prefer HMAC-SHA-256 over HMAC-SHA-512, and
that over HMAC-SHA-1, as OpenSSH does.

Closes #40
---
 src/libgcrypt.h |  8 +++++
 src/mac.c       | 97 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/openssl.h   |  7 +++++
 src/transport.c |  2 +-
 src/wincng.h    |  6 ++++
 5 files changed, 119 insertions(+), 1 deletion(-)

Index: libssh2-1.4.3/src/libgcrypt.h
===================================================================
--- libssh2-1.4.3.orig/src/libgcrypt.h	2012-10-08 14:54:30.000000000 +0200
+++ libssh2-1.4.3/src/libgcrypt.h	2016-02-23 15:28:39.264493076 +0100
@@ -42,6 +42,8 @@
 #define LIBSSH2_MD5 1
 
 #define LIBSSH2_HMAC_RIPEMD 1
+#define LIBSSH2_HMAC_SHA256 1
+#define LIBSSH2_HMAC_SHA512 1
 
 #define LIBSSH2_AES 1
 #define LIBSSH2_AES_CTR 1
@@ -89,6 +91,12 @@
 #define libssh2_hmac_ripemd160_init(ctx, key, keylen) \
   gcry_md_open (ctx, GCRY_MD_RMD160, GCRY_MD_FLAG_HMAC), \
     gcry_md_setkey (*ctx, key, keylen)
+#define libssh2_hmac_sha256_init(ctx, key, keylen) \
+  gcry_md_open (ctx, GCRY_MD_SHA256, GCRY_MD_FLAG_HMAC), \
+    gcry_md_setkey (*ctx, key, keylen)
+#define libssh2_hmac_sha512_init(ctx, key, keylen) \
+  gcry_md_open (ctx, GCRY_MD_SHA512, GCRY_MD_FLAG_HMAC), \
+    gcry_md_setkey (*ctx, key, keylen)
 #define libssh2_hmac_update(ctx, data, datalen) \
   gcry_md_write (ctx, data, datalen)
 #define libssh2_hmac_final(ctx, data) \
Index: libssh2-1.4.3/src/mac.c
===================================================================
--- libssh2-1.4.3.orig/src/mac.c	2010-12-15 09:37:31.000000000 +0100
+++ libssh2-1.4.3/src/mac.c	2016-02-23 13:49:02.169231812 +0100
@@ -96,6 +96,97 @@ mac_method_common_dtor(LIBSSH2_SESSION *
 
 
 
+#if LIBSSH2_HMAC_SHA512
+/* mac_method_hmac_sha512_hash
+ * Calculate hash using full sha512 value
+ */
+static int
+mac_method_hmac_sha2_512_hash(LIBSSH2_SESSION * session,
+                          unsigned char *buf, uint32_t seqno,
+                          const unsigned char *packet,
+                          uint32_t packet_len,
+                          const unsigned char *addtl,
+                          uint32_t addtl_len, void **abstract)
+{
+    libssh2_hmac_ctx ctx;
+    unsigned char seqno_buf[4];
+    (void) session;
+
+    _libssh2_htonu32(seqno_buf, seqno);
+
+    libssh2_hmac_ctx_init(ctx);
+    libssh2_hmac_sha512_init(&ctx, *abstract, 64);
+    libssh2_hmac_update(ctx, seqno_buf, 4);
+    libssh2_hmac_update(ctx, packet, packet_len);
+    if (addtl && addtl_len) {
+        libssh2_hmac_update(ctx, addtl, addtl_len);
+    }
+    libssh2_hmac_final(ctx, buf);
+    libssh2_hmac_cleanup(&ctx);
+
+    return 0;
+}
+
+
+
+static const LIBSSH2_MAC_METHOD mac_method_hmac_sha2_512 = {
+    "hmac-sha2-512",
+    64,
+    64,
+    mac_method_common_init,
+    mac_method_hmac_sha2_512_hash,
+    mac_method_common_dtor,
+};
+#endif
+
+
+
+#if LIBSSH2_HMAC_SHA256
+/* mac_method_hmac_sha256_hash
+ * Calculate hash using full sha256 value
+ */
+static int
+mac_method_hmac_sha2_256_hash(LIBSSH2_SESSION * session,
+                          unsigned char *buf, uint32_t seqno,
+                          const unsigned char *packet,
+                          uint32_t packet_len,
+                          const unsigned char *addtl,
+                          uint32_t addtl_len, void **abstract)
+{
+    libssh2_hmac_ctx ctx;
+    unsigned char seqno_buf[4];
+    (void) session;
+
+    _libssh2_htonu32(seqno_buf, seqno);
+
+    libssh2_hmac_ctx_init(ctx);
+    libssh2_hmac_sha256_init(&ctx, *abstract, 32);
+    libssh2_hmac_update(ctx, seqno_buf, 4);
+    libssh2_hmac_update(ctx, packet, packet_len);
+    if (addtl && addtl_len) {
+        libssh2_hmac_update(ctx, addtl, addtl_len);
+    }
+    libssh2_hmac_final(ctx, buf);
+    libssh2_hmac_cleanup(&ctx);
+
+    return 0;
+}
+
+
+
+static const LIBSSH2_MAC_METHOD mac_method_hmac_sha2_256 = {
+    "hmac-sha2-256",
+    32,
+    32,
+    mac_method_common_init,
+    mac_method_hmac_sha2_256_hash,
+    mac_method_common_dtor,
+};
+#endif
+
+
+
+
 /* mac_method_hmac_sha1_hash
  * Calculate hash using full sha1 value
  */
@@ -291,6 +382,12 @@ static const LIBSSH2_MAC_METHOD mac_meth
 #endif /* LIBSSH2_HMAC_RIPEMD */
 
 static const LIBSSH2_MAC_METHOD *mac_methods[] = {
+#if LIBSSH2_HMAC_SHA256
+    &mac_method_hmac_sha2_256,
+#endif
+#if LIBSSH2_HMAC_SHA512
+    &mac_method_hmac_sha2_512,
+#endif
     &mac_method_hmac_sha1,
     &mac_method_hmac_sha1_96,
 #if LIBSSH2_MD5
Index: libssh2-1.4.3/src/openssl.h
===================================================================
--- libssh2-1.4.3.orig/src/openssl.h	2012-10-08 14:54:30.000000000 +0200
+++ libssh2-1.4.3/src/openssl.h	2016-02-23 15:29:38.014446452 +0100
@@ -72,6 +72,9 @@
 # define LIBSSH2_HMAC_RIPEMD 1
 #endif
 
+#define LIBSSH2_HMAC_SHA256 1
+#define LIBSSH2_HMAC_SHA512 1
+
 #if OPENSSL_VERSION_NUMBER >= 0x00907000L && !defined(OPENSSL_NO_AES)
 # define LIBSSH2_AES_CTR 1
 # define LIBSSH2_AES 1
@@ -122,12 +125,18 @@ void libssh2_sha1(const unsigned char *m
 void libssh2_md5(const unsigned char *message, unsigned long len, unsigned char *out);
 
 #define libssh2_hmac_ctx HMAC_CTX
+#define libssh2_hmac_ctx_init(ctx) \
+  HMAC_CTX_init(&ctx)
 #define libssh2_hmac_sha1_init(ctx, key, keylen) \
   HMAC_Init(ctx, key, keylen, EVP_sha1())
 #define libssh2_hmac_md5_init(ctx, key, keylen) \
   HMAC_Init(ctx, key, keylen, EVP_md5())
 #define libssh2_hmac_ripemd160_init(ctx, key, keylen) \
   HMAC_Init(ctx, key, keylen, EVP_ripemd160())
+#define libssh2_hmac_sha256_init(ctx, key, keylen) \
+  HMAC_Init(ctx, key, keylen, EVP_sha256())
+#define libssh2_hmac_sha512_init(ctx, key, keylen) \
+  HMAC_Init(ctx, key, keylen, EVP_sha512())
 #define libssh2_hmac_update(ctx, data, datalen) \
   HMAC_Update(&(ctx), data, datalen)
 #define libssh2_hmac_final(ctx, data) HMAC_Final(&(ctx), data, NULL)
Index: libssh2-1.4.3/src/transport.c
===================================================================
--- libssh2-1.4.3.orig/src/transport.c	2012-10-08 14:54:30.000000000 +0200
+++ libssh2-1.4.3/src/transport.c	2016-02-23 13:49:02.169231812 +0100
@@ -52,7 +52,7 @@
 #include "mac.h"
 
 #define MAX_BLOCKSIZE 32    /* MUST fit biggest crypto block size we use/get */
-#define MAX_MACSIZE 20      /* MUST fit biggest MAC length we support */
+#define MAX_MACSIZE 64      /* MUST fit biggest MAC length we support */
 
 #ifdef LIBSSH2DEBUG
 #define UNPRINTABLE_CHAR '.'
