From 2d674f007b41d3237e0039b00a4150ddcbbb056c Mon Sep 17 00:00:00 2001
From: Dirkjan Bussink <d.bussink@gmail.com>
Date: Fri, 8 Feb 2019 19:44:36 +0000
Subject: [PATCH 4/6] Add flag for tracking EtM HMACs

This adds a flag to the type structures to track if we use a
Encrypt-then-MAC cipher instead of Encrypt-and-MAC. EtM is a more secure
hashing mechanism.

Reviewed-by: Jon Simons <jon@jonsimons.org>
Signed-off-by: Jon Simons <jon@jonsimons.org>
---
 include/libssh/crypto.h  |  1 +
 include/libssh/wrapper.h |  3 ++-
 src/session.c            |  4 ++--
 src/wrapper.c            | 26 ++++++++++++++++----------
 4 files changed, 21 insertions(+), 13 deletions(-)

diff --git a/include/libssh/crypto.h b/include/libssh/crypto.h
index 4cd76ddb..74e8ecd1 100644
--- a/include/libssh/crypto.h
+++ b/include/libssh/crypto.h
@@ -133,6 +133,7 @@ struct ssh_crypto_struct {
     unsigned char hmacbuf[DIGEST_MAX_LEN];
     struct ssh_cipher_struct *in_cipher, *out_cipher; /* the cipher structures/objects */
     enum ssh_hmac_e in_hmac, out_hmac; /* the MAC algorithms used */
+    int in_hmac_etm, out_hmac_etm; /* Whether EtM mode is used or not */
 
     ssh_key server_pubkey;
     int do_compress_out; /* idem */
diff --git a/include/libssh/wrapper.h b/include/libssh/wrapper.h
index 3a33c34f..8195d4bf 100644
--- a/include/libssh/wrapper.h
+++ b/include/libssh/wrapper.h
@@ -59,6 +59,7 @@ enum ssh_des_e {
 struct ssh_hmac_struct {
   const char* name;
   enum ssh_hmac_e hmac_type;
+  int etm;
 };
 
 enum ssh_crypto_direction_e {
@@ -120,6 +121,6 @@ void ssh_crypto_finalize(void);
 void ssh_cipher_clear(struct ssh_cipher_struct *cipher);
 struct ssh_hmac_struct *ssh_get_hmactab(void);
 struct ssh_cipher_struct *ssh_get_ciphertab(void);
-const char *ssh_hmac_type_to_string(enum ssh_hmac_e hmac_type);
+const char *ssh_hmac_type_to_string(enum ssh_hmac_e hmac_type, int etm);
 
 #endif /* WRAPPER_H_ */
diff --git a/src/session.c b/src/session.c
index 3b151bf7..d4600861 100644
--- a/src/session.c
+++ b/src/session.c
@@ -419,7 +419,7 @@ const char* ssh_get_cipher_out(ssh_session session) {
 const char* ssh_get_hmac_in(ssh_session session) {
     if ((session != NULL) &&
         (session->current_crypto != NULL)) {
-        return ssh_hmac_type_to_string(session->current_crypto->in_hmac);
+        return ssh_hmac_type_to_string(session->current_crypto->in_hmac, session->current_crypto->in_hmac_etm);
     }
     return NULL;
 }
@@ -434,7 +434,7 @@ const char* ssh_get_hmac_in(ssh_session session) {
 const char* ssh_get_hmac_out(ssh_session session) {
     if ((session != NULL) &&
         (session->current_crypto != NULL)) {
-        return ssh_hmac_type_to_string(session->current_crypto->out_hmac);
+        return ssh_hmac_type_to_string(session->current_crypto->out_hmac, session->current_crypto->out_hmac_etm);
     }
     return NULL;
 }
diff --git a/src/wrapper.c b/src/wrapper.c
index 79603455..f068e5b9 100644
--- a/src/wrapper.c
+++ b/src/wrapper.c
@@ -56,14 +56,14 @@
 #include "libssh/curve25519.h"
 
 static struct ssh_hmac_struct ssh_hmac_tab[] = {
-  { "hmac-sha1",     SSH_HMAC_SHA1 },
-  { "hmac-sha2-256", SSH_HMAC_SHA256 },
-  { "hmac-sha2-384", SSH_HMAC_SHA384 },
-  { "hmac-sha2-512", SSH_HMAC_SHA512 },
-  { "hmac-md5",      SSH_HMAC_MD5 },
-  { "aead-poly1305", SSH_HMAC_AEAD_POLY1305 },
-  { "aead-gcm",      SSH_HMAC_AEAD_GCM },
-  { NULL,            0}
+  { "hmac-sha1",     SSH_HMAC_SHA1,          0 },
+  { "hmac-sha2-256", SSH_HMAC_SHA256,        0 },
+  { "hmac-sha2-384", SSH_HMAC_SHA384,        0 },
+  { "hmac-sha2-512", SSH_HMAC_SHA512,        0 },
+  { "hmac-md5",      SSH_HMAC_MD5,           0 },
+  { "aead-poly1305", SSH_HMAC_AEAD_POLY1305, 0 },
+  { "aead-gcm",      SSH_HMAC_AEAD_GCM,      0 },
+  { NULL,            0,                      0 }
 };
 
 struct ssh_hmac_struct *ssh_get_hmactab(void) {
@@ -91,11 +91,13 @@ size_t hmac_digest_len(enum ssh_hmac_e type) {
   }
 }
 
-const char *ssh_hmac_type_to_string(enum ssh_hmac_e hmac_type)
+const char *ssh_hmac_type_to_string(enum ssh_hmac_e hmac_type, int etm)
 {
   int i = 0;
   struct ssh_hmac_struct *ssh_hmactab = ssh_get_hmactab();
-  while (ssh_hmactab[i].name && (ssh_hmactab[i].hmac_type != hmac_type)) {
+  while (ssh_hmactab[i].name &&
+         ((ssh_hmactab[i].hmac_type != hmac_type) ||
+          (ssh_hmactab[i].etm != etm))) {
     i++;
   }
   return ssh_hmactab[i].name;
@@ -296,6 +298,7 @@ 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;
+    session->next_crypto->out_hmac_etm = ssh_hmactab[i].etm;
 
     /* in */
     wanted = session->next_crypto->kex_methods[SSH_CRYPT_S_C];
@@ -349,6 +352,7 @@ static int crypt_set_algorithms2(ssh_session session)
     SSH_LOG(SSH_LOG_PACKET, "Set HMAC input algorithm to %s", wanted);
 
     session->next_crypto->in_hmac = ssh_hmactab[i].hmac_type;
+    session->next_crypto->in_hmac_etm = ssh_hmactab[i].etm;
 
     /* compression */
     cmp = strcmp(session->next_crypto->kex_methods[SSH_COMP_C_S], "zlib");
@@ -446,6 +450,7 @@ 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;
+    session->next_crypto->out_hmac_etm = ssh_hmactab[i].etm;
 
     /* in */
     method = session->next_crypto->kex_methods[SSH_CRYPT_C_S];
@@ -498,6 +503,7 @@ int crypt_set_algorithms_server(ssh_session session){
     SSH_LOG(SSH_LOG_PACKET, "Set HMAC input algorithm to %s", method);
 
     session->next_crypto->in_hmac = ssh_hmactab[i].hmac_type;
+    session->next_crypto->in_hmac_etm = ssh_hmactab[i].etm;
 
     /* compression */
     method = session->next_crypto->kex_methods[SSH_COMP_C_S];
-- 
2.11.0

