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
diff --git a/src/libgcrypt.h b/src/libgcrypt.h
index f9da52b..e2eb4d2 100644
--- a/src/libgcrypt.h
+++ b/src/libgcrypt.h
@@ -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
@@ -95,6 +97,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, (unsigned char *) data, datalen)
#define libssh2_hmac_final(ctx, data) \
diff --git a/src/mac.c b/src/mac.c
index 786a953..5ec26eb 100644
--- a/src/mac.c
+++ b/src/mac.c
@@ -96,6 +96,97 @@
+#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
*/
@@ -294,6 +385,12 @@
#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
diff --git a/src/openssl.h b/src/openssl.h
index a571309..4c3fe89 100644
--- a/src/openssl.h
+++ b/src/openssl.h
@@ -76,6 +76,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
@@ -138,6 +141,10 @@
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)
diff --git a/src/transport.c b/src/transport.c
index 5b3d66d..8725da0 100644
--- a/src/transport.c
+++ b/src/transport.c
@@ -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 '.'
diff --git a/src/wincng.h b/src/wincng.h
index 429192c..0381247 100644
--- a/src/wincng.h
+++ b/src/wincng.h
@@ -51,6 +51,8 @@
#define LIBSSH2_MD5 1
#define LIBSSH2_HMAC_RIPEMD 0
+#define LIBSSH2_HMAC_SHA256 0
+#define LIBSSH2_HMAC_SHA512 0
#define LIBSSH2_AES 1
#define LIBSSH2_AES_CTR 0
@@ -158,6 +160,10 @@
MD5_DIGEST_LENGTH, key, keylen)
#define libssh2_hmac_ripemd160_init(ctx, key, keylen)
/* not implemented */
+#define libssh2_hmac_sha256_init(ctx, key, keylen)
+ /* not implemented */
+#define libssh2_hmac_sha512_init(ctx, key, keylen)
+ /* not implemented */
#define libssh2_hmac_update(ctx, data, datalen) \
_libssh2_wincng_hash_update(&ctx, (unsigned char *) data, datalen)
#define libssh2_hmac_final(ctx, hash) \