aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAris Adamantiadis <aris@0xbadc0de.be>2011-06-13 13:46:34 +0200
committerAris Adamantiadis <aris@0xbadc0de.be>2011-06-13 13:46:34 +0200
commitc5a998f47afc0c79c4badfa5f6554ae51ad92e82 (patch)
tree4a0b2d03049833ae85ea7f837b010403dd357a3a
parent3b72bf08802a058cb663a40359ed0e006a1480ca (diff)
downloadlibssh-c5a998f47afc0c79c4badfa5f6554ae51ad92e82.tar.gz
libssh-c5a998f47afc0c79c4badfa5f6554ae51ad92e82.tar.xz
libssh-c5a998f47afc0c79c4badfa5f6554ae51ad92e82.zip
[crypto] initial support for ecdh-sha2-nistp256
Works with openssl Still requires work for libgcrypt and other modes
-rw-r--r--config.h.cmake4
-rw-r--r--include/libssh/crypto.h35
-rw-r--r--include/libssh/dh.h3
-rw-r--r--include/libssh/ecdh.h39
-rw-r--r--include/libssh/libcrypto.h5
-rw-r--r--include/libssh/libgcrypt.h7
-rw-r--r--include/libssh/session.h2
-rw-r--r--include/libssh/ssh2.h4
-rw-r--r--include/libssh/wrapper.h24
-rw-r--r--src/CMakeLists.txt1
-rw-r--r--src/client.c83
-rw-r--r--src/crypt.c4
-rw-r--r--src/dh.c249
-rw-r--r--src/ecdh.c167
-rw-r--r--src/kex.c18
-rw-r--r--src/known_hosts.c2
-rw-r--r--src/libcrypto.c86
-rw-r--r--src/libgcrypt.c63
18 files changed, 635 insertions, 161 deletions
diff --git a/config.h.cmake b/config.h.cmake
index e0ed57c3..f08c3801 100644
--- a/config.h.cmake
+++ b/config.h.cmake
@@ -35,6 +35,10 @@
/* Define to 1 if you have the <openssl/des.h> header file. */
#cmakedefine HAVE_OPENSSL_DES_H 1
+/* Define to 1 if you have the <openssl/ecdh.h> header file. */
+#cmakedefine HAVE_OPENSSL_ECDH_H 1
+
+
/* Define to 1 if you have the <pthread.h> header file. */
#cmakedefine HAVE_PTHREAD_H 1
diff --git a/include/libssh/crypto.h b/include/libssh/crypto.h
index 1c543f50..d5b95b9e 100644
--- a/include/libssh/crypto.h
+++ b/include/libssh/crypto.h
@@ -40,18 +40,31 @@
#undef cbc_decrypt
#endif
-struct ssh_crypto_struct {
- bignum e,f,x,k,y;
- unsigned char session_id[SHA_DIGEST_LEN];
-
- unsigned char encryptIV[SHA_DIGEST_LEN*2];
- unsigned char decryptIV[SHA_DIGEST_LEN*2];
+#ifdef HAVE_OPENSSL_ECDH_H
+#include <openssl/ecdh.h>
+#endif
- unsigned char decryptkey[SHA_DIGEST_LEN*2];
- unsigned char encryptkey[SHA_DIGEST_LEN*2];
+enum ssh_key_exchange_e {
+ /* diffie-hellman-group1-sha1 */
+ SSH_KEX_DH_GROUP1_SHA1=1,
+ /* ecdh-sha2-nistp256 */
+ SSH_KEX_ECDH_SHA2_NISTP256
+};
- unsigned char encryptMAC[SHA_DIGEST_LEN];
- unsigned char decryptMAC[SHA_DIGEST_LEN];
+struct ssh_crypto_struct {
+ bignum e,f,x,k,y;
+ EC_KEY *ecdh_privkey;
+ ssh_string ecdh_client_pubkey;
+ ssh_string ecdh_server_pubkey;
+ ssh_string dh_server_signature; /* information used by dh_handshake. */
+ size_t digest_len; /* len of all the fields below */
+ unsigned char *session_id;
+ unsigned char *encryptIV;
+ unsigned char *decryptIV;
+ unsigned char *decryptkey;
+ unsigned char *encryptkey;
+ unsigned char *encryptMAC;
+ unsigned char *decryptMAC;
unsigned char hmacbuf[EVP_MAX_MD_SIZE];
struct crypto_struct *in_cipher, *out_cipher; /* the cipher structures/objects */
ssh_string server_pubkey;
@@ -62,6 +75,8 @@ struct ssh_crypto_struct {
int delayed_compress_out;
void *compress_out_ctx; /* don't touch it */
void *compress_in_ctx; /* really, don't */
+ enum ssh_key_exchange_e kex_type;
+ enum ssh_mac_e mac_type; /* Mac operations to use for key gen */
};
struct crypto_struct {
diff --git a/include/libssh/dh.h b/include/libssh/dh.h
index ece7c019..d4cd0c2e 100644
--- a/include/libssh/dh.h
+++ b/include/libssh/dh.h
@@ -41,6 +41,9 @@ int dh_import_f(ssh_session session,ssh_string f_string);
int dh_import_e(ssh_session session, ssh_string e_string);
void dh_import_pubkey(ssh_session session,ssh_string pubkey_string);
int dh_build_k(ssh_session session);
+int ssh_client_dh_init(ssh_session session);
+int ssh_client_dh_reply(ssh_session session, ssh_buffer packet);
+
int make_sessionid(ssh_session session);
/* add data for the final cookie */
int hashbufin_add_cookie(ssh_session session, unsigned char *cookie);
diff --git a/include/libssh/ecdh.h b/include/libssh/ecdh.h
new file mode 100644
index 00000000..5cc208ce
--- /dev/null
+++ b/include/libssh/ecdh.h
@@ -0,0 +1,39 @@
+/*
+ * This file is part of the SSH Library
+ *
+ * Copyright (c) 2011 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.
+ */
+
+#ifndef ECDH_H_
+#define ECDH_H_
+
+#include "config.h"
+
+#ifdef HAVE_LIBCRYPTO
+#ifdef HAVE_OPENSSL_ECDH_H
+
+#define HAVE_ECDH
+
+#endif /* HAVE_OPENSSL_ECDH_H */
+#endif /* HAVE_LIBCRYPTO */
+
+int ssh_client_ecdh_init(ssh_session session);
+int ssh_client_ecdh_reply(ssh_session session, ssh_buffer packet);
+
+
+#endif /* ECDH_H_ */
diff --git a/include/libssh/libcrypto.h b/include/libssh/libcrypto.h
index 12dd2229..f1986602 100644
--- a/include/libssh/libcrypto.h
+++ b/include/libssh/libcrypto.h
@@ -32,6 +32,7 @@
#include <openssl/md5.h>
#include <openssl/hmac.h>
typedef SHA_CTX* SHACTX;
+typedef SHA256_CTX* SHA256CTX;
typedef MD5_CTX* MD5CTX;
typedef HMAC_CTX* HMACCTX;
@@ -67,6 +68,10 @@ typedef BN_CTX* bignum_CTX;
#define bignum_bn2bin(num,ptr) BN_bn2bin(num,ptr)
#define bignum_cmp(num1,num2) BN_cmp(num1,num2)
+SHA256CTX sha256_init(void);
+void sha256_update(SHA256CTX c, const void *data, unsigned long len);
+void sha256_final(unsigned char *md, SHA256CTX c);
+
struct crypto_struct *ssh_get_ciphertab(void);
#endif /* HAVE_LIBCRYPTO */
diff --git a/include/libssh/libgcrypt.h b/include/libssh/libgcrypt.h
index 0b1b16da..3afbcb49 100644
--- a/include/libssh/libgcrypt.h
+++ b/include/libssh/libgcrypt.h
@@ -30,8 +30,13 @@
typedef gcry_md_hd_t SHACTX;
typedef gcry_md_hd_t MD5CTX;
typedef gcry_md_hd_t HMACCTX;
-#define SHA_DIGEST_LEN 20
+#define SHA_DIGEST_LENGTH 20
+#define SHA_DIGEST_LEN SHA_DIGEST_LENGTH
#define MD5_DIGEST_LEN 16
+#define SHA256_DIGEST_LENGTH 32
+#define SHA384_DIGEST_LENGTH 48
+#define SHA512_DIGEST_LENGTH 64
+
#define EVP_MAX_MD_SIZE 36
typedef gcry_mpi_t bignum;
diff --git a/include/libssh/session.h b/include/libssh/session.h
index a31e6bfe..2d4b05bc 100644
--- a/include/libssh/session.h
+++ b/include/libssh/session.h
@@ -103,7 +103,7 @@ struct ssh_session_struct {
enum ssh_auth_service_state_e auth_service_state;
enum ssh_auth_state_e auth_state;
enum ssh_channel_request_state_e global_req_state;
- ssh_string dh_server_signature; /* information used by dh_handshake. */
+
KEX server_kex;
KEX client_kex;
ssh_buffer in_hashbuf;
diff --git a/include/libssh/ssh2.h b/include/libssh/ssh2.h
index bd89f4e1..f66dd2a9 100644
--- a/include/libssh/ssh2.h
+++ b/include/libssh/ssh2.h
@@ -13,6 +13,10 @@
#define SSH2_MSG_KEXDH_INIT 30
#define SSH2_MSG_KEXDH_REPLY 31
+#define SSH2_MSG_KEX_ECDH_INIT 30
+#define SSH2_MSG_KEX_ECDH_REPLY 31
+#define SSH2_MSG_ECMQV_INIT 30
+#define SSH2_MSG_ECMQV_REPLY 31
#define SSH2_MSG_KEX_DH_GEX_REQUEST_OLD 30
#define SSH2_MSG_KEX_DH_GEX_GROUP 31
diff --git a/include/libssh/wrapper.h b/include/libssh/wrapper.h
index 8c034970..7fe6f8ad 100644
--- a/include/libssh/wrapper.h
+++ b/include/libssh/wrapper.h
@@ -25,7 +25,21 @@
#include "config.h"
#include "libssh/libcrypto.h"
#include "libssh/libgcrypt.h"
+#include "libssh/crypto.h"
+enum ssh_mac_e {
+ SSH_MAC_SHA1=1,
+ SSH_MAC_SHA256,
+ SSH_MAC_SHA384,
+ SSH_MAC_SHA512
+};
+
+enum ssh_hmac_e {
+ SSH_HMAC_SHA1 = 1,
+ SSH_HMAC_MD5
+};
+
+typedef struct ssh_mac_ctx_struct *ssh_mac_ctx;
MD5CTX md5_init(void);
void md5_update(MD5CTX c, const void *data, unsigned long len);
void md5_final(unsigned char *md,MD5CTX c);
@@ -33,9 +47,13 @@ SHACTX sha1_init(void);
void sha1_update(SHACTX c, const void *data, unsigned long len);
void sha1_final(unsigned char *md,SHACTX c);
void sha1(unsigned char *digest,int len,unsigned char *hash);
-#define HMAC_SHA1 1
-#define HMAC_MD5 2
-HMACCTX hmac_init(const void *key,int len,int type);
+void sha256(unsigned char *digest, int len, unsigned char *hash);
+
+ssh_mac_ctx ssh_mac_ctx_init(enum ssh_mac_e type);
+void ssh_mac_update(ssh_mac_ctx ctx, const void *data, unsigned long len);
+void ssh_mac_final(unsigned char *md, ssh_mac_ctx ctx);
+
+HMACCTX hmac_init(const void *key,int len, enum ssh_hmac_e type);
void hmac_update(HMACCTX c, const void *data, unsigned long len);
void hmac_final(HMACCTX ctx,unsigned char *hashmacbuf,unsigned int *len);
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 64eebf0a..103b007a 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -85,6 +85,7 @@ set(libssh_SRCS
crc32.c
crypt.c
dh.c
+ ecdh.c
error.c
getpass.c
gzip.c
diff --git a/src/client.c b/src/client.c
index 7b2e4494..426dd2b3 100644
--- a/src/client.c
+++ b/src/client.c
@@ -36,6 +36,7 @@
#include "libssh/socket.h"
#include "libssh/session.h"
#include "libssh/dh.h"
+#include "libssh/ecdh.h"
#include "libssh/threads.h"
#include "libssh/misc.h"
@@ -176,12 +177,8 @@ end:
return err;
}
-
-
SSH_PACKET_CALLBACK(ssh_packet_dh_reply){
- ssh_string f = NULL;
- ssh_string pubkey = NULL;
- ssh_string signature = NULL;
+ int rc;
(void)type;
(void)user;
ssh_log(session,SSH_LOG_PROTOCOL,"Received SSH_KEXDH_REPLY");
@@ -191,48 +188,23 @@ SSH_PACKET_CALLBACK(ssh_packet_dh_reply){
session->session_state,session->dh_handshake_state);
goto error;
}
-
- pubkey = buffer_get_ssh_string(packet);
- if (pubkey == NULL){
- ssh_set_error(session,SSH_FATAL, "No public key in packet");
- goto error;
- }
- dh_import_pubkey(session, pubkey);
-
- f = buffer_get_ssh_string(packet);
- if (f == NULL) {
- ssh_set_error(session,SSH_FATAL, "No F number in packet");
- goto error;
- }
- if (dh_import_f(session, f) < 0) {
- ssh_set_error(session, SSH_FATAL, "Cannot import f number");
- goto error;
- }
- ssh_string_burn(f);
- ssh_string_free(f);
- f=NULL;
- signature = buffer_get_ssh_string(packet);
- if (signature == NULL) {
- ssh_set_error(session, SSH_FATAL, "No signature in packet");
- goto error;
- }
- session->dh_server_signature = signature;
- signature=NULL; /* ownership changed */
- if (dh_build_k(session) < 0) {
- ssh_set_error(session, SSH_FATAL, "Cannot build k number");
- goto error;
+ switch(session->next_crypto->kex_type){
+ case SSH_KEX_DH_GROUP1_SHA1:
+ rc=ssh_client_dh_reply(session, packet);
+ break;
+#ifdef HAVE_ECDH
+ case SSH_KEX_ECDH_SHA2_NISTP256:
+ rc = ssh_client_ecdh_reply(session, packet);
+ break;
+#endif
+ default:
+ ssh_set_error(session,SSH_FATAL,"Wrong kex type in ssh_packet_dh_reply");
+ goto error;
}
-
- /* Send the MSG_NEWKEYS */
- if (buffer_add_u8(session->out_buffer, SSH2_MSG_NEWKEYS) < 0) {
- goto error;
+ if(rc==SSH_OK) {
+ session->dh_handshake_state = DH_STATE_NEWKEYS_SENT;
+ return SSH_PACKET_USED;
}
-
- packet_send(session);
- ssh_log(session, SSH_LOG_PROTOCOL, "SSH_MSG_NEWKEYS sent");
-
- session->dh_handshake_state = DH_STATE_NEWKEYS_SENT;
- return SSH_PACKET_USED;
error:
session->session_state=SSH_SESSION_STATE_ERROR;
return SSH_PACKET_USED;
@@ -274,12 +246,12 @@ SSH_PACKET_CALLBACK(ssh_packet_newkeys){
}
/* Verify the host's signature. FIXME do it sooner */
- signature = session->dh_server_signature;
- session->dh_server_signature = NULL;
+ signature = session->next_crypto->dh_server_signature;
+ session->next_crypto->dh_server_signature = NULL;
if (signature_verify(session, signature)) {
goto error;
}
-
+ ssh_log(session,SSH_LOG_PROTOCOL,"Signature verified and valid");
/* forget it for now ... */
ssh_string_burn(signature);
ssh_string_free(signature);
@@ -325,7 +297,20 @@ static int dh_handshake(ssh_session session) {
switch (session->dh_handshake_state) {
case DH_STATE_INIT:
- rc = ssh_client_dh_init(session);
+ switch(session->next_crypto->kex_type){
+ case SSH_KEX_DH_GROUP1_SHA1:
+ rc = ssh_client_dh_init(session);
+ break;
+#ifdef HAVE_ECDH
+ case SSH_KEX_ECDH_SHA2_NISTP256:
+ rc = ssh_client_ecdh_init(session);
+ break;
+#endif
+ default:
+ rc=SSH_ERROR;
+ goto error;
+ }
+
if (rc == SSH_ERROR) {
goto error;
}
diff --git a/src/crypt.c b/src/crypt.c
index 363517e6..4c2e465c 100644
--- a/src/crypt.c
+++ b/src/crypt.c
@@ -136,7 +136,7 @@ unsigned char *packet_encrypt(ssh_session session, void *data, uint32_t len) {
#endif
if (session->version == 2) {
- ctx = hmac_init(session->current_crypto->encryptMAC,20,HMAC_SHA1);
+ ctx = hmac_init(session->current_crypto->encryptMAC,20,SSH_HMAC_SHA1);
if (ctx == NULL) {
SAFE_FREE(out);
return NULL;
@@ -190,7 +190,7 @@ int packet_hmac_verify(ssh_session session, ssh_buffer buffer,
unsigned int len;
uint32_t seq;
- ctx = hmac_init(session->current_crypto->decryptMAC, 20, HMAC_SHA1);
+ ctx = hmac_init(session->current_crypto->decryptMAC, 20, SSH_HMAC_SHA1);
if (ctx == NULL) {
return -1;
}
diff --git a/src/dh.c b/src/dh.c
index 8be99bf4..91e275ab 100644
--- a/src/dh.c
+++ b/src/dh.c
@@ -521,6 +521,56 @@ int ssh_client_dh_init(ssh_session session){
leave_function();
return SSH_ERROR;
}
+
+int ssh_client_dh_reply(ssh_session session, ssh_buffer packet){
+ ssh_string f = NULL;
+ ssh_string pubkey = NULL;
+ ssh_string signature = NULL;
+ int rc;
+ pubkey = buffer_get_ssh_string(packet);
+ if (pubkey == NULL){
+ ssh_set_error(session,SSH_FATAL, "No public key in packet");
+ goto error;
+ }
+ dh_import_pubkey(session, pubkey);
+
+ f = buffer_get_ssh_string(packet);
+ if (f == NULL) {
+ ssh_set_error(session,SSH_FATAL, "No F number in packet");
+ goto error;
+ }
+ if (dh_import_f(session, f) < 0) {
+ ssh_set_error(session, SSH_FATAL, "Cannot import f number");
+ goto error;
+ }
+ ssh_string_burn(f);
+ ssh_string_free(f);
+ f=NULL;
+ signature = buffer_get_ssh_string(packet);
+ if (signature == NULL) {
+ ssh_set_error(session, SSH_FATAL, "No signature in packet");
+ goto error;
+ }
+ session->next_crypto->dh_server_signature = signature;
+ signature=NULL; /* ownership changed */
+ if (dh_build_k(session) < 0) {
+ ssh_set_error(session, SSH_FATAL, "Cannot build k number");
+ goto error;
+ }
+
+ /* Send the MSG_NEWKEYS */
+ if (buffer_add_u8(session->out_buffer, SSH2_MSG_NEWKEYS) < 0) {
+ goto error;
+ }
+
+ rc=packet_send(session);
+ ssh_log(session, SSH_LOG_PROTOCOL, "SSH_MSG_NEWKEYS sent");
+ return rc;
+error:
+ return SSH_ERROR;
+}
+
+
/*
static void sha_add(ssh_string str,SHACTX ctx){
sha1_update(ctx,str,string_len(str)+4);
@@ -531,7 +581,6 @@ static void sha_add(ssh_string str,SHACTX ctx){
*/
int make_sessionid(ssh_session session) {
- SHACTX ctx;
ssh_string num = NULL;
ssh_string str = NULL;
ssh_buffer server_hash = NULL;
@@ -542,11 +591,6 @@ int make_sessionid(ssh_session session) {
enter_function();
- ctx = sha1_init();
- if (ctx == NULL) {
- return rc;
- }
-
buf = ssh_buffer_new();
if (buf == NULL) {
return rc;
@@ -614,29 +658,33 @@ int make_sessionid(ssh_session session) {
if (buffer_add_data(buf, session->next_crypto->server_pubkey, len) < 0) {
goto error;
}
+ if(session->next_crypto->kex_type == SSH_KEX_DH_GROUP1_SHA1){
+ num = make_bignum_string(session->next_crypto->e);
+ if (num == NULL) {
+ goto error;
+ }
- num = make_bignum_string(session->next_crypto->e);
- if (num == NULL) {
- goto error;
- }
+ len = ssh_string_len(num) + 4;
+ if (buffer_add_data(buf, num, len) < 0) {
+ goto error;
+ }
- len = ssh_string_len(num) + 4;
- if (buffer_add_data(buf, num, len) < 0) {
- goto error;
- }
+ ssh_string_free(num);
+ num = make_bignum_string(session->next_crypto->f);
+ if (num == NULL) {
+ goto error;
+ }
- ssh_string_free(num);
- num = make_bignum_string(session->next_crypto->f);
- if (num == NULL) {
- goto error;
- }
+ len = ssh_string_len(num) + 4;
+ if (buffer_add_data(buf, num, len) < 0) {
+ goto error;
+ }
- len = ssh_string_len(num) + 4;
- if (buffer_add_data(buf, num, len) < 0) {
- goto error;
+ ssh_string_free(num);
+ } else if (session->next_crypto->kex_type == SSH_KEX_ECDH_SHA2_NISTP256){
+ buffer_add_ssh_string(buf,session->next_crypto->ecdh_client_pubkey);
+ buffer_add_ssh_string(buf,session->next_crypto->ecdh_server_pubkey);
}
-
- ssh_string_free(num);
num = make_bignum_string(session->next_crypto->k);
if (num == NULL) {
goto error;
@@ -651,8 +699,31 @@ int make_sessionid(ssh_session session) {
ssh_print_hexa("hash buffer", ssh_buffer_get_begin(buf), ssh_buffer_get_len(buf));
#endif
- sha1_update(ctx, buffer_get_rest(buf), buffer_get_rest_len(buf));
- sha1_final(session->next_crypto->session_id, ctx);
+ switch(session->next_crypto->kex_type){
+ case SSH_KEX_DH_GROUP1_SHA1:
+ session->next_crypto->digest_len = SHA_DIGEST_LENGTH;
+ session->next_crypto->mac_type = SSH_MAC_SHA1;
+ session->next_crypto->session_id = malloc(session->next_crypto->digest_len);
+ if(session->next_crypto->session_id == NULL){
+ ssh_set_error_oom(session);
+ goto error;
+ }
+ sha1(buffer_get_rest(buf), buffer_get_rest_len(buf),
+ session->next_crypto->session_id);
+ break;
+ case SSH_KEX_ECDH_SHA2_NISTP256:
+ session->next_crypto->digest_len = SHA256_DIGEST_LENGTH;
+ session->next_crypto->mac_type = SSH_MAC_SHA256;
+ session->next_crypto->session_id = malloc(session->next_crypto->digest_len);
+ if(session->next_crypto->session_id == NULL){
+ ssh_set_error_oom(session);
+ goto error;
+ }
+ sha256(buffer_get_rest(buf), buffer_get_rest_len(buf),
+ session->next_crypto->session_id);
+ break;
+ }
+
#ifdef DEBUG_CRYPTO
printf("Session hash: ");
@@ -723,126 +794,134 @@ int hashbufin_add_cookie(ssh_session session, unsigned char *cookie) {
}
static int generate_one_key(ssh_string k,
- unsigned char session_id[SHA_DIGEST_LEN],
- unsigned char output[SHA_DIGEST_LEN],
- char letter) {
- SHACTX ctx = NULL;
+ struct ssh_crypto_struct *crypto, unsigned char *output, char letter) {
+ ssh_mac_ctx ctx;
+ ctx=ssh_mac_ctx_init(crypto->mac_type);
- ctx = sha1_init();
if (ctx == NULL) {
return -1;
}
- sha1_update(ctx, k, ssh_string_len(k) + 4);
- sha1_update(ctx, session_id, SHA_DIGEST_LEN);
- sha1_update(ctx, &letter, 1);
- sha1_update(ctx, session_id, SHA_DIGEST_LEN);
- sha1_final(output, ctx);
+ ssh_mac_update(ctx, k, ssh_string_len(k) + 4);
+ ssh_mac_update(ctx, crypto->session_id, crypto->digest_len);
+ ssh_mac_update(ctx, &letter, 1);
+ ssh_mac_update(ctx, crypto->session_id, crypto->digest_len);
+ ssh_mac_final(output, ctx);
return 0;
}
int generate_session_keys(ssh_session session) {
ssh_string k_string = NULL;
- SHACTX ctx = NULL;
+ ssh_mac_ctx ctx = NULL;
+ struct ssh_crypto_struct *crypto = session->next_crypto;
int rc = -1;
enter_function();
- k_string = make_bignum_string(session->next_crypto->k);
+ k_string = make_bignum_string(crypto->k);
if (k_string == NULL) {
+ ssh_set_error_oom(session);
+ goto error;
+ }
+
+ crypto->encryptIV = malloc(crypto->digest_len);
+ crypto->decryptIV = malloc(crypto->digest_len);
+ crypto->encryptkey = malloc(crypto->digest_len);
+ crypto->decryptkey = malloc(crypto->digest_len);
+ crypto->encryptMAC = malloc(crypto->digest_len);
+ crypto->decryptMAC = malloc(crypto->digest_len);
+ if(crypto->encryptIV == NULL || crypto->decryptIV == NULL ||
+ crypto->encryptkey == NULL || crypto->decryptkey == NULL ||
+ crypto->encryptMAC == NULL || crypto->decryptMAC == NULL){
+ ssh_set_error_oom(session);
goto error;
}
/* IV */
if (session->client) {
- if (generate_one_key(k_string, session->next_crypto->session_id,
- session->next_crypto->encryptIV, 'A') < 0) {
+ if (generate_one_key(k_string, crypto, crypto->encryptIV, 'A') < 0) {
goto error;
}
- if (generate_one_key(k_string, session->next_crypto->session_id,
- session->next_crypto->decryptIV, 'B') < 0) {
+ if (generate_one_key(k_string, crypto, crypto->decryptIV, 'B') < 0) {
goto error;
}
} else {
- if (generate_one_key(k_string, session->next_crypto->session_id,
- session->next_crypto->decryptIV, 'A') < 0) {
+ if (generate_one_key(k_string, crypto, crypto->decryptIV, 'A') < 0) {
goto error;
}
- if (generate_one_key(k_string, session->next_crypto->session_id,
- session->next_crypto->encryptIV, 'B') < 0) {
+ if (generate_one_key(k_string, crypto, crypto->encryptIV, 'B') < 0) {
goto error;
}
}
if (session->client) {
- if (generate_one_key(k_string, session->next_crypto->session_id,
- session->next_crypto->encryptkey, 'C') < 0) {
+ if (generate_one_key(k_string, crypto, crypto->encryptkey, 'C') < 0) {
goto error;
}
- if (generate_one_key(k_string, session->next_crypto->session_id,
- session->next_crypto->decryptkey, 'D') < 0) {
+ if (generate_one_key(k_string, crypto, crypto->decryptkey, 'D') < 0) {
goto error;
}
} else {
- if (generate_one_key(k_string, session->next_crypto->session_id,
- session->next_crypto->decryptkey, 'C') < 0) {
+ if (generate_one_key(k_string, crypto, crypto->decryptkey, 'C') < 0) {
goto error;
}
- if (generate_one_key(k_string, session->next_crypto->session_id,
- session->next_crypto->encryptkey, 'D') < 0) {
+ if (generate_one_key(k_string, crypto, crypto->encryptkey, 'D') < 0) {
goto error;
}
}
- /* some ciphers need more than 20 bytes of input key */
- /* XXX verify it's ok for server implementation */
- if (session->next_crypto->out_cipher->keysize > SHA_DIGEST_LEN * 8) {
- ctx = sha1_init();
+ /* some ciphers need more than DIGEST_LEN bytes of input key */
+ if (crypto->out_cipher->keysize > crypto->digest_len * 8) {
+ crypto->encryptkey = realloc(crypto->encryptkey, crypto->digest_len * 2);
+ if(crypto->encryptkey == NULL)
+ goto error;
+ ctx = ssh_mac_ctx_init(crypto->mac_type);
if (ctx == NULL) {
goto error;
}
- sha1_update(ctx, k_string, ssh_string_len(k_string) + 4);
- sha1_update(ctx, session->next_crypto->session_id, SHA_DIGEST_LEN);
- sha1_update(ctx, session->next_crypto->encryptkey, SHA_DIGEST_LEN);
- sha1_final(session->next_crypto->encryptkey + SHA_DIGEST_LEN, ctx);
+ ssh_mac_update(ctx, k_string, ssh_string_len(k_string) + 4);
+ ssh_mac_update(ctx, crypto->session_id,
+ crypto->digest_len);
+ ssh_mac_update(ctx, crypto->encryptkey, crypto->digest_len);
+ ssh_mac_final(crypto->encryptkey + crypto->digest_len, ctx);
}
- if (session->next_crypto->in_cipher->keysize > SHA_DIGEST_LEN * 8) {
- ctx = sha1_init();
- sha1_update(ctx, k_string, ssh_string_len(k_string) + 4);
- sha1_update(ctx, session->next_crypto->session_id, SHA_DIGEST_LEN);
- sha1_update(ctx, session->next_crypto->decryptkey, SHA_DIGEST_LEN);
- sha1_final(session->next_crypto->decryptkey + SHA_DIGEST_LEN, ctx);
+ if (crypto->in_cipher->keysize > crypto->digest_len * 8) {
+ crypto->decryptkey = realloc(crypto->decryptkey, crypto->digest_len *2);
+ if(crypto->decryptkey == NULL)
+ goto error;
+ ctx = ssh_mac_ctx_init(crypto->mac_type);
+ ssh_mac_update(ctx, k_string, ssh_string_len(k_string) + 4);
+ ssh_mac_update(ctx, crypto->session_id,
+ crypto->digest_len);
+ ssh_mac_update(ctx, crypto->decryptkey, crypto->digest_len);
+ ssh_mac_final(crypto->decryptkey + crypto->digest_len, ctx);
}
if(session->client) {
- if (generate_one_key(k_string, session->next_crypto->session_id,
- session->next_crypto->encryptMAC, 'E') < 0) {
+ if (generate_one_key(k_string, crypto, crypto->encryptMAC, 'E') < 0) {
goto error;
}
- if (generate_one_key(k_string, session->next_crypto->session_id,
- session->next_crypto->decryptMAC, 'F') < 0) {
+ if (generate_one_key(k_string, crypto, crypto->decryptMAC, 'F') < 0) {
goto error;
}
} else {
- if (generate_one_key(k_string, session->next_crypto->session_id,
- session->next_crypto->decryptMAC, 'E') < 0) {
+ if (generate_one_key(k_string, crypto, crypto->decryptMAC, 'E') < 0) {
goto error;
}
- if (generate_one_key(k_string, session->next_crypto->session_id,
- session->next_crypto->encryptMAC, 'F') < 0) {
+ if (generate_one_key(k_string, crypto, crypto->encryptMAC, 'F') < 0) {
goto error;
}
}
#ifdef DEBUG_CRYPTO
- ssh_print_hexa("Encrypt IV", session->next_crypto->encryptIV, SHA_DIGEST_LEN);
- ssh_print_hexa("Decrypt IV", session->next_crypto->decryptIV, SHA_DIGEST_LEN);
- ssh_print_hexa("Encryption key", session->next_crypto->encryptkey,
- session->next_crypto->out_cipher->keysize);
- ssh_print_hexa("Decryption key", session->next_crypto->decryptkey,
- session->next_crypto->in_cipher->keysize);
- ssh_print_hexa("Encryption MAC", session->next_crypto->encryptMAC, SHA_DIGEST_LEN);
- ssh_print_hexa("Decryption MAC", session->next_crypto->decryptMAC, 20);
+ ssh_print_hexa("Encrypt IV", crypto->encryptIV, SHA_DIGEST_LEN);
+ ssh_print_hexa("Decrypt IV", crypto->decryptIV, SHA_DIGEST_LEN);
+ ssh_print_hexa("Encryption key", crypto->encryptkey,
+ crypto->out_cipher->keysize);
+ ssh_print_hexa("Decryption key", crypto->decryptkey,
+ crypto->in_cipher->keysize);
+ ssh_print_hexa("Encryption MAC", crypto->encryptMAC, SHA_DIGEST_LEN);
+ ssh_print_hexa("Decryption MAC", crypto->decryptMAC, 20);
#endif
rc = 0;
@@ -1090,7 +1169,7 @@ int signature_verify(ssh_session session, ssh_string signature) {
"Going to verify a %s type signature", pubkey->type_c);
err = sig_verify(session,pubkey,sign,
- session->next_crypto->session_id,SHA_DIGEST_LEN);
+ session->next_crypto->session_id, session->next_crypto->digest_len);
signature_free(sign);
session->next_crypto->server_pubkey_type = pubkey->type_c;
publickey_free(pubkey);
diff --git a/src/ecdh.c b/src/ecdh.c
new file mode 100644
index 00000000..20840c8d
--- /dev/null
+++ b/src/ecdh.c
@@ -0,0 +1,167 @@
+/*
+ * This file is part of the SSH Library
+ *
+ * Copyright (c) 2011 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/session.h"
+#include "libssh/ecdh.h"
+#include "libssh/buffer.h"
+#include "libssh/ssh2.h"
+
+#ifdef HAVE_ECDH
+#include <openssl/ecdh.h>
+
+#define NISTP256 NID_X9_62_prime256v1
+#define NISTP384 NID_secp384r1
+#define NISTP521 NID_secp521r1
+
+/** @internal
+ * @brief Starts ecdh-sha2-nistp256 key exchange
+ */
+int ssh_client_ecdh_init(ssh_session session){
+ ssh_string e = NULL;
+ EC_KEY *key=NULL;
+ const EC_GROUP *group;
+ const EC_POINT *pubkey;
+ ssh_string client_pubkey;
+ int len;
+ int rc;
+ bignum_CTX ctx=BN_CTX_new();
+ enter_function();
+ if (buffer_add_u8(session->out_buffer, SSH2_MSG_KEX_ECDH_INIT) < 0) {
+ goto error;
+ }
+ key = EC_KEY_new_by_curve_name(NISTP256);
+ group = EC_KEY_get0_group(key);
+ EC_KEY_generate_key(key);
+ pubkey=EC_KEY_get0_public_key(key);
+ len = EC_POINT_point2oct(group,pubkey,POINT_CONVERSION_UNCOMPRESSED,
+ NULL,0,ctx);
+ client_pubkey=ssh_string_new(len);
+
+ EC_POINT_point2oct(group,pubkey,POINT_CONVERSION_UNCOMPRESSED,
+ ssh_string_data(client_pubkey),len,ctx);
+ buffer_add_ssh_string(session->out_buffer,client_pubkey);
+ BN_CTX_free(ctx);
+ session->next_crypto->ecdh_privkey = key;
+ session->next_crypto->ecdh_client_pubkey = client_pubkey;
+ rc = packet_send(session);
+ return rc;
+error:
+ if(e != NULL){
+ ssh_string_burn(e);
+ ssh_string_free(e);
+ }
+
+ leave_function();
+ return SSH_ERROR;
+}
+
+static void ecdh_import_pubkey(ssh_session session, ssh_string pubkey_string) {
+ session->next_crypto->server_pubkey = pubkey_string;
+}
+
+static int ecdh_build_k(ssh_session session) {
+ const EC_GROUP *group = EC_KEY_get0_group(session->next_crypto->ecdh_privkey);
+ EC_POINT *pubkey=EC_POINT_new(group);
+ void *buffer;
+ int len = (EC_GROUP_get_degree(group) + 7) / 8;
+#ifdef HAVE_LIBCRYPTO
+ bignum_CTX ctx = bignum_ctx_new();
+ if (ctx == NULL) {
+ return -1;
+ }
+#endif
+
+ session->next_crypto->k = bignum_new();
+ if (session->next_crypto->k == NULL) {
+#ifdef HAVE_LIBCRYPTO
+ bignum_ctx_free(ctx);
+#endif
+ return -1;
+ }
+
+ EC_POINT_oct2point(group,pubkey,ssh_string_data(session->next_crypto->ecdh_server_pubkey),
+ ssh_string_len(session->next_crypto->ecdh_server_pubkey),ctx);
+ buffer = malloc(len);
+ ECDH_compute_key(buffer,len,pubkey,session->next_crypto->ecdh_privkey,NULL);
+ BN_bin2bn(buffer,len,session->next_crypto->k);
+ free(buffer);
+
+#ifdef DEBUG_CRYPTO
+ ssh_print_hexa("Session server cookie", session->server_kex.cookie, 16);
+ ssh_print_hexa("Session client cookie", session->client_kex.cookie, 16);
+ ssh_print_bignum("Shared secret key", session->next_crypto->k);
+#endif
+
+#ifdef HAVE_LIBCRYPTO
+ bignum_ctx_free(ctx);
+#endif
+
+ return 0;
+}
+
+/** @internal
+ * @brief parses a SSH_MSG_KEX_ECDH_REPLY packet and sends back
+ * a SSH_MSG_NEWKEYS
+ */
+int ssh_client_ecdh_reply(ssh_session session, ssh_buffer packet){
+ ssh_string q_s_string = NULL;
+ ssh_string pubkey = NULL;
+ ssh_string signature = NULL;
+ int rc;
+ pubkey = buffer_get_ssh_string(packet);
+ if (pubkey == NULL){
+ ssh_set_error(session,SSH_FATAL, "No public key in packet");
+ goto error;
+ }
+ ecdh_import_pubkey(session, pubkey);
+
+ q_s_string = buffer_get_ssh_string(packet);
+ if (q_s_string == NULL) {
+ ssh_set_error(session,SSH_FATAL, "No Q_S ECC point in packet");
+ goto error;
+ }
+ session->next_crypto->ecdh_server_pubkey = q_s_string;
+ signature = buffer_get_ssh_string(packet);
+ if (signature == NULL) {
+ ssh_set_error(session, SSH_FATAL, "No signature in packet");
+ goto error;
+ }
+ session->next_crypto->dh_server_signature = signature;
+ signature=NULL; /* ownership changed */
+ if (ecdh_build_k(session) < 0) {
+ ssh_set_error(session, SSH_FATAL, "Cannot build k number");
+ goto error;
+ }
+
+ /* Send the MSG_NEWKEYS */
+ if (buffer_add_u8(session->out_buffer, SSH2_MSG_NEWKEYS) < 0) {
+ goto error;
+ }
+
+ rc=packet_send(session);
+ ssh_log(session, SSH_LOG_PROTOCOL, "SSH_MSG_NEWKEYS sent");
+ return rc;
+error:
+ return SSH_ERROR;
+}
+
+#endif /* HAVE_ECDH */
diff --git a/src/kex.c b/src/kex.c
index 2c7276b2..592ca092 100644
--- a/src/kex.c
+++ b/src/kex.c
@@ -42,6 +42,7 @@
#include "libssh/dh.h"
#include "libssh/kex.h"
#include "libssh/string.h"
+#include "libssh/ecdh.h"
#ifdef HAVE_LIBGCRYPT
#define BLOWFISH "blowfish-cbc,"
@@ -72,8 +73,14 @@
#define ZLIB "none"
#endif
+#ifdef HAVE_ECDH
+#define KEY_EXCHANGE "ecdh-sha2-nistp256,diffie-hellman-group1-sha1"
+#else
+#define KEY_EXCHANGE "diffie-hellman-group1-sha1"
+#endif
+
const char *default_methods[] = {
- "diffie-hellman-group1-sha1",
+ KEY_EXCHANGE,
"ssh-rsa,ssh-dss",
AES BLOWFISH DES,
AES BLOWFISH DES,
@@ -87,7 +94,7 @@ const char *default_methods[] = {
};
const char *supported_methods[] = {
- "diffie-hellman-group1-sha1",
+ KEY_EXCHANGE,
"ssh-rsa,ssh-dss",
AES BLOWFISH DES,
AES BLOWFISH DES,
@@ -370,7 +377,7 @@ int set_kex(ssh_session session){
ssh_get_random(client->cookie,16,0);
client->methods=malloc(10 * sizeof(char **));
if (client->methods == NULL) {
- ssh_set_error(session, SSH_FATAL, "No space left");
+ ssh_set_error_oom(session);
leave_function();
return -1;
}
@@ -394,6 +401,11 @@ int set_kex(ssh_session session){
}
}
}
+ if(strcmp(client->methods[SSH_KEX], "diffie-hellman-group1-sha1") == 0){
+ session->next_crypto->kex_type=SSH_KEX_DH_GROUP1_SHA1;
+ } else if(strcmp(client->methods[SSH_KEX], "ecdh-sha2-nistp256") == 0){
+ session->next_crypto->kex_type=SSH_KEX_ECDH_SHA2_NISTP256;
+ }
leave_function();
return 0;
}
diff --git a/src/known_hosts.c b/src/known_hosts.c
index 60241b7a..7c935a83 100644
--- a/src/known_hosts.c
+++ b/src/known_hosts.c
@@ -346,7 +346,7 @@ static int match_hashed_host(ssh_session session, const char *host,
return 0;
}
- mac = hmac_init(buffer_get_rest(salt), buffer_get_rest_len(salt), HMAC_SHA1);
+ mac = hmac_init(buffer_get_rest(salt), buffer_get_rest_len(salt), SSH_HMAC_SHA1);
if (mac == NULL) {
ssh_buffer_free(salt);
ssh_buffer_free(hash);
diff --git a/src/libcrypto.c b/src/libcrypto.c
index f43a91eb..ede0331b 100644
--- a/src/libcrypto.c
+++ b/src/libcrypto.c
@@ -57,6 +57,14 @@
#include "libssh/crypto.h"
+struct ssh_mac_ctx_struct {
+ enum ssh_mac_e mac_type;
+ union {
+ SHACTX sha1_ctx;
+ SHA256CTX sha256_ctx;
+ } ctx;
+};
+
static int alloc_key(struct crypto_struct *cipher) {
cipher->key = malloc(cipher->keylen);
if (cipher->key == NULL) {
@@ -89,6 +97,29 @@ void sha1(unsigned char *digest, int len, unsigned char *hash) {
SHA1(digest, len, hash);
}
+SHA256CTX sha256_init(void){
+ SHA256CTX c = malloc(sizeof(*c));
+ if (c == NULL) {
+ return NULL;
+ }
+ SHA256_Init(c);
+
+ return c;
+}
+
+void sha256_update(SHA256CTX c, const void *data, unsigned long len){
+ SHA256_Update(c,data,len);
+}
+
+void sha256_final(unsigned char *md, SHA256CTX c) {
+ SHA256_Final(md, c);
+ SAFE_FREE(c);
+}
+
+void sha256(unsigned char *digest, int len, unsigned char *hash) {
+ SHA256(digest, len, hash);
+}
+
MD5CTX md5_init(void) {
MD5CTX c = malloc(sizeof(*c));
if (c == NULL) {
@@ -109,7 +140,56 @@ void md5_final(unsigned char *md, MD5CTX c) {
SAFE_FREE(c);
}
-HMACCTX hmac_init(const void *key, int len, int type) {
+ssh_mac_ctx ssh_mac_ctx_init(enum ssh_mac_e type){
+ ssh_mac_ctx ctx=malloc(sizeof(struct ssh_mac_ctx_struct));
+ ctx->mac_type=type;
+ switch(type){
+ case SSH_MAC_SHA1:
+ ctx->ctx.sha1_ctx = sha1_init();
+ return ctx;
+ case SSH_MAC_SHA256:
+ ctx->ctx.sha256_ctx = sha256_init();
+ return ctx;
+ case SSH_MAC_SHA384:
+ case SSH_MAC_SHA512:
+ default:
+ SAFE_FREE(ctx);
+ return NULL;
+ }
+}
+
+void ssh_mac_update(ssh_mac_ctx ctx, const void *data, unsigned long len) {
+ switch(ctx->mac_type){
+ case SSH_MAC_SHA1:
+ sha1_update(ctx->ctx.sha1_ctx, data, len);
+ break;
+ case SSH_MAC_SHA256:
+ sha256_update(ctx->ctx.sha256_ctx, data, len);
+ break;
+ case SSH_MAC_SHA384:
+ case SSH_MAC_SHA512:
+ default:
+ break;
+ }
+}
+
+void ssh_mac_final(unsigned char *md, ssh_mac_ctx ctx) {
+ switch(ctx->mac_type){
+ case SSH_MAC_SHA1:
+ sha1_final(md,ctx->ctx.sha1_ctx);
+ break;
+ case SSH_MAC_SHA256:
+ sha256_final(md,ctx->ctx.sha256_ctx);
+ break;
+ case SSH_MAC_SHA384:
+ case SSH_MAC_SHA512:
+ default:
+ break;
+ }
+ SAFE_FREE(ctx);
+}
+
+HMACCTX hmac_init(const void *key, int len, enum ssh_hmac_e type) {
HMACCTX ctx = NULL;
ctx = malloc(sizeof(*ctx));
@@ -122,10 +202,10 @@ HMACCTX hmac_init(const void *key, int len, int type) {
#endif
switch(type) {
- case HMAC_SHA1:
+ case SSH_HMAC_SHA1:
HMAC_Init(ctx, key, len, EVP_sha1());
break;
- case HMAC_MD5:
+ case SSH_HMAC_MD5:
HMAC_Init(ctx, key, len, EVP_md5());
break;
default:
diff --git a/src/libgcrypt.c b/src/libgcrypt.c
index f8fe96f2..2e2695c8 100644
--- a/src/libgcrypt.c
+++ b/src/libgcrypt.c
@@ -31,6 +31,10 @@
#ifdef HAVE_LIBGCRYPT
#include <gcrypt.h>
+struct ssh_mac_ctx_struct {
+ enum ssh_mac_e mac_type;
+ gcry_md_hd_t ctx;
+};
static int alloc_key(struct crypto_struct *cipher) {
cipher->key = malloc(cipher->keylen);
@@ -62,6 +66,10 @@ void sha1(unsigned char *digest, int len, unsigned char *hash) {
gcry_md_hash_buffer(GCRY_MD_SHA1, hash, digest, len);
}
+void sha256(unsigned char *digest, int len, unsigned char *hash){
+ gcry_md_hash_buffer(GCRY_MD_SHA256, hash, digest, len);
+}
+
MD5CTX md5_init(void) {
MD5CTX c = NULL;
gcry_md_open(&c, GCRY_MD_MD5, 0);
@@ -79,14 +87,63 @@ void md5_final(unsigned char *md, MD5CTX c) {
gcry_md_close(c);
}
-HMACCTX hmac_init(const void *key, int len, int type) {
+ssh_mac_ctx ssh_mac_ctx_init(enum ssh_mac_e type){
+ ssh_mac_ctx ctx=malloc(sizeof(struct ssh_mac_ctx_struct));
+ ctx->mac_type=type;
+ switch(type){
+ case SSH_MAC_SHA1:
+ gcry_md_open(&ctx->ctx, GCRY_MD_SHA1, 0);
+ break;
+ case SSH_MAC_SHA256:
+ gcry_md_open(&ctx->ctx, GCRY_MD_SHA256, 0);
+ break;
+ case SSH_MAC_SHA384:
+ gcry_md_open(&ctx->ctx, GCRY_MD_SHA384, 0);
+ break;
+ case SSH_MAC_SHA512:
+ gcry_md_open(&ctx->ctx, GCRY_MD_SHA512, 0);
+ break;
+ default:
+ SAFE_FREE(ctx);
+ return NULL;
+ }
+ return ctx;
+}
+
+void ssh_mac_update(ssh_mac_ctx ctx, const void *data, unsigned long len) {
+ gcry_md_write(ctx->ctx,data,len);
+}
+
+void ssh_mac_final(unsigned char *md, ssh_mac_ctx ctx) {
+ size_t len;
+ switch(ctx->mac_type){
+ case SSH_MAC_SHA1:
+ len=SHA_DIGEST_LEN;
+ break;
+ case SSH_MAC_SHA256:
+ len=SHA256_DIGEST_LENGTH;
+ break;
+ case SSH_MAC_SHA384:
+ len=SHA384_DIGEST_LENGTH;
+ break;
+ case SSH_MAC_SHA512:
+ len=SHA512_DIGEST_LENGTH;
+ break;
+ }
+ gcry_md_final(ctx->ctx);
+ memcpy(md, gcry_md_read(ctx->ctx, 0), len);
+ gcry_md_close(ctx->ctx);
+ SAFE_FREE(ctx);
+}
+
+HMACCTX hmac_init(const void *key, int len, enum ssh_hmac_e type) {
HMACCTX c = NULL;
switch(type) {
- case HMAC_SHA1:
+ case SSH_HMAC_SHA1:
gcry_md_open(&c, GCRY_MD_SHA1, GCRY_MD_FLAG_HMAC);
break;
- case HMAC_MD5:
+ case SSH_HMAC_MD5:
gcry_md_open(&c, GCRY_MD_MD5, GCRY_MD_FLAG_HMAC);
break;
default: