aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ConfigureChecks.cmake4
-rw-r--r--config.h.cmake3
-rw-r--r--include/libssh/crypto.h8
-rw-r--r--include/libssh/wrapper.h20
-rw-r--r--src/CMakeLists.txt1
-rw-r--r--src/kdf.c167
-rw-r--r--src/kex.c78
-rw-r--r--src/libcrypto.c140
-rw-r--r--src/libgcrypt.c63
-rw-r--r--src/libmbedcrypto.c69
-rw-r--r--tests/unittests/torture_session_keys.c2
11 files changed, 299 insertions, 256 deletions
diff --git a/ConfigureChecks.cmake b/ConfigureChecks.cmake
index 376ad7dd..643a0a4b 100644
--- a/ConfigureChecks.cmake
+++ b/ConfigureChecks.cmake
@@ -129,6 +129,10 @@ if (OPENSSL_FOUND)
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARY})
+ check_function_exists(EVP_KDF_CTX_new_id HAVE_OPENSSL_EVP_KDF_CTX_NEW_ID)
+
+ set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
+ set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARY})
check_function_exists(RAND_priv_bytes HAVE_OPENSSL_RAND_PRIV_BYTES)
check_function_exists(OPENSSL_ia32cap_loc HAVE_OPENSSL_IA32CAP_LOC)
diff --git a/config.h.cmake b/config.h.cmake
index 672241e4..918ad437 100644
--- a/config.h.cmake
+++ b/config.h.cmake
@@ -115,6 +115,9 @@
/* Define to 1 if you have the `EVP_CIPHER_CTX_new' function. */
#cmakedefine HAVE_OPENSSL_EVP_CIPHER_CTX_NEW 1
+/* Define to 1 if you have the `EVP_KDF_CTX_new_id' function. */
+#cmakedefine HAVE_OPENSSL_EVP_KDF_CTX_NEW_ID 1
+
/* Define to 1 if you have the `OPENSSL_ia32cap_loc' function. */
#cmakedefine HAVE_OPENSSL_IA32CAP_LOC 1
diff --git a/include/libssh/crypto.h b/include/libssh/crypto.h
index 2d2d4f7f..4cd0cecd 100644
--- a/include/libssh/crypto.h
+++ b/include/libssh/crypto.h
@@ -122,7 +122,7 @@ struct ssh_crypto_struct {
ssh_curve25519_pubkey curve25519_server_pubkey;
#endif
ssh_string dh_server_signature; /* information used by dh_handshake. */
- size_t digest_len; /* len of all the fields below */
+ size_t digest_len; /* len of the two fields below */
unsigned char *session_id;
unsigned char *secret_hash; /* Secret hash is same as session id until re-kex */
unsigned char *encryptIV;
@@ -148,7 +148,7 @@ struct ssh_crypto_struct {
struct ssh_kex_struct client_kex;
char *kex_methods[SSH_KEX_METHODS];
enum ssh_key_exchange_e kex_type;
- enum ssh_mac_e mac_type; /* Mac operations to use for key gen */
+ enum ssh_kdf_digest digest_type; /* Digest type for session keys derivation */
enum ssh_crypto_direction_e used; /* Is this crypto still used for either of directions? */
};
@@ -204,5 +204,9 @@ struct ssh_cipher_struct {
};
const struct ssh_cipher_struct *ssh_get_chacha20poly1305_cipher(void);
+int sshkdf_derive_key(struct ssh_crypto_struct *crypto,
+ unsigned char *key, size_t key_len,
+ int key_type, unsigned char *output,
+ size_t requested_len);
#endif /* _CRYPTO_H_ */
diff --git a/include/libssh/wrapper.h b/include/libssh/wrapper.h
index e4a0bba1..df415bb5 100644
--- a/include/libssh/wrapper.h
+++ b/include/libssh/wrapper.h
@@ -36,11 +36,11 @@ enum ssh_digest_e {
SSH_DIGEST_SHA512
};
-enum ssh_mac_e {
- SSH_MAC_SHA1=1,
- SSH_MAC_SHA256,
- SSH_MAC_SHA384,
- SSH_MAC_SHA512
+enum ssh_kdf_digest {
+ SSH_KDF_SHA1=1,
+ SSH_KDF_SHA256,
+ SSH_KDF_SHA384,
+ SSH_KDF_SHA512
};
enum ssh_hmac_e {
@@ -70,6 +70,7 @@ enum ssh_crypto_direction_e {
};
struct ssh_cipher_struct;
+struct ssh_crypto_struct;
typedef struct ssh_mac_ctx_struct *ssh_mac_ctx;
MD5CTX md5_init(void);
@@ -101,15 +102,16 @@ EVPCTX evp_init(int nid);
void evp_update(EVPCTX ctx, const void *data, unsigned long len);
void evp_final(EVPCTX ctx, unsigned char *md, unsigned int *mdlen);
-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);
size_t hmac_digest_len(enum ssh_hmac_e type);
+int ssh_kdf(struct ssh_crypto_struct *crypto,
+ unsigned char *key, size_t key_len,
+ int key_type, unsigned char *output,
+ size_t requested_len);
+
int crypt_set_algorithms_client(ssh_session session);
int crypt_set_algorithms_server(ssh_session session);
struct ssh_crypto_struct *crypto_new(void);
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 3261d42c..fdb53baf 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -130,6 +130,7 @@ set(libssh_SRCS
error.c
getpass.c
init.c
+ kdf.c
kex.c
known_hosts.c
knownhosts.c
diff --git a/src/kdf.c b/src/kdf.c
new file mode 100644
index 00000000..0e90e188
--- /dev/null
+++ b/src/kdf.c
@@ -0,0 +1,167 @@
+/*
+ * This file is part of the SSH Library
+ *
+ * Copyright (c) 2009 by Aris Adamantiadis
+ * Copyrihgt (c) 2018 Red Hat, Inc.
+ *
+ * This 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.
+ *
+ * This 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 this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "config.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+
+#include "libssh/priv.h"
+#include "libssh/crypto.h"
+#include "libssh/buffer.h"
+#include "libssh/session.h"
+#include "libssh/misc.h"
+#include "libssh/dh.h"
+#include "libssh/ssh2.h"
+#include "libssh/pki.h"
+#include "libssh/bignum.h"
+
+#include "libssh/string.h"
+
+
+/* The following implements the SSHKDF for crypto backend that
+ * do not have a native implementations */
+struct ssh_mac_ctx_struct {
+ enum ssh_kdf_digest digest_type;
+ union {
+ SHACTX sha1_ctx;
+ SHA256CTX sha256_ctx;
+ SHA384CTX sha384_ctx;
+ SHA512CTX sha512_ctx;
+ } ctx;
+};
+
+static ssh_mac_ctx ssh_mac_ctx_init(enum ssh_kdf_digest type)
+{
+ ssh_mac_ctx ctx = malloc(sizeof(struct ssh_mac_ctx_struct));
+ if (ctx == NULL) {
+ return NULL;
+ }
+
+ ctx->digest_type = type;
+ switch(type){
+ case SSH_KDF_SHA1:
+ ctx->ctx.sha1_ctx = sha1_init();
+ return ctx;
+ case SSH_KDF_SHA256:
+ ctx->ctx.sha256_ctx = sha256_init();
+ return ctx;
+ case SSH_KDF_SHA384:
+ ctx->ctx.sha384_ctx = sha384_init();
+ return ctx;
+ case SSH_KDF_SHA512:
+ ctx->ctx.sha512_ctx = sha512_init();
+ return ctx;
+ default:
+ SAFE_FREE(ctx);
+ return NULL;
+ }
+}
+
+static void ssh_mac_update(ssh_mac_ctx ctx, const void *data, size_t len)
+{
+ switch(ctx->digest_type){
+ case SSH_KDF_SHA1:
+ sha1_update(ctx->ctx.sha1_ctx, data, len);
+ break;
+ case SSH_KDF_SHA256:
+ sha256_update(ctx->ctx.sha256_ctx, data, len);
+ break;
+ case SSH_KDF_SHA384:
+ sha384_update(ctx->ctx.sha384_ctx, data, len);
+ break;
+ case SSH_KDF_SHA512:
+ sha512_update(ctx->ctx.sha512_ctx, data, len);
+ break;
+ }
+}
+
+static void ssh_mac_final(unsigned char *md, ssh_mac_ctx ctx)
+{
+ switch(ctx->digest_type){
+ case SSH_KDF_SHA1:
+ sha1_final(md,ctx->ctx.sha1_ctx);
+ break;
+ case SSH_KDF_SHA256:
+ sha256_final(md,ctx->ctx.sha256_ctx);
+ break;
+ case SSH_KDF_SHA384:
+ sha384_final(md,ctx->ctx.sha384_ctx);
+ break;
+ case SSH_KDF_SHA512:
+ sha512_final(md,ctx->ctx.sha512_ctx);
+ break;
+ }
+ SAFE_FREE(ctx);
+}
+
+int sshkdf_derive_key(struct ssh_crypto_struct *crypto,
+ unsigned char *key, size_t key_len,
+ int key_type, unsigned char *output,
+ size_t requested_len)
+{
+ /* Can't use VLAs with Visual Studio, so allocate the biggest
+ * digest buffer we can possibly need */
+ unsigned char digest[DIGEST_MAX_LEN];
+ size_t output_len = crypto->digest_len;
+ char letter = key_type;
+ ssh_mac_ctx ctx;
+
+ if (DIGEST_MAX_LEN < crypto->digest_len) {
+ return -1;
+ }
+
+ ctx = ssh_mac_ctx_init(crypto->digest_type);
+ if (ctx == NULL) {
+ return -1;
+ }
+
+ ssh_mac_update(ctx, key, key_len);
+ ssh_mac_update(ctx, crypto->secret_hash, crypto->digest_len);
+ ssh_mac_update(ctx, &letter, 1);
+ ssh_mac_update(ctx, crypto->session_id, crypto->digest_len);
+ ssh_mac_final(digest, ctx);
+
+ if (requested_len < output_len) {
+ output_len = requested_len;
+ }
+ memcpy(output, digest, output_len);
+
+ while (requested_len > output_len) {
+ ctx = ssh_mac_ctx_init(crypto->digest_type);
+ if (ctx == NULL) {
+ return -1;
+ }
+ ssh_mac_update(ctx, key, key_len);
+ ssh_mac_update(ctx, crypto->secret_hash, crypto->digest_len);
+ ssh_mac_update(ctx, output, output_len);
+ ssh_mac_final(digest, ctx);
+ if (requested_len < output_len + crypto->digest_len) {
+ memcpy(output + output_len, digest, requested_len - output_len);
+ } else {
+ memcpy(output + output_len, digest, crypto->digest_len);
+ }
+ output_len += crypto->digest_len;
+ }
+
+ return 0;
+}
diff --git a/src/kex.c b/src/kex.c
index 1aaa4154..750996b3 100644
--- a/src/kex.c
+++ b/src/kex.c
@@ -1196,7 +1196,7 @@ int ssh_make_sessionid(ssh_session session)
case SSH_KEX_DH_GEX_SHA1:
#endif /* WITH_GEX */
session->next_crypto->digest_len = SHA_DIGEST_LENGTH;
- session->next_crypto->mac_type = SSH_MAC_SHA1;
+ session->next_crypto->digest_type = SSH_KDF_SHA1;
session->next_crypto->secret_hash = malloc(session->next_crypto->digest_len);
if (session->next_crypto->secret_hash == NULL) {
ssh_set_error_oom(session);
@@ -1212,7 +1212,7 @@ int ssh_make_sessionid(ssh_session session)
case SSH_KEX_DH_GEX_SHA256:
#endif /* WITH_GEX */
session->next_crypto->digest_len = SHA256_DIGEST_LENGTH;
- session->next_crypto->mac_type = SSH_MAC_SHA256;
+ session->next_crypto->digest_type = SSH_KDF_SHA256;
session->next_crypto->secret_hash = malloc(session->next_crypto->digest_len);
if (session->next_crypto->secret_hash == NULL) {
ssh_set_error_oom(session);
@@ -1223,7 +1223,7 @@ int ssh_make_sessionid(ssh_session session)
break;
case SSH_KEX_ECDH_SHA2_NISTP384:
session->next_crypto->digest_len = SHA384_DIGEST_LENGTH;
- session->next_crypto->mac_type = SSH_MAC_SHA384;
+ session->next_crypto->digest_type = SSH_KDF_SHA384;
session->next_crypto->secret_hash = malloc(session->next_crypto->digest_len);
if (session->next_crypto->secret_hash == NULL) {
ssh_set_error_oom(session);
@@ -1236,7 +1236,7 @@ int ssh_make_sessionid(ssh_session session)
case SSH_KEX_DH_GROUP18_SHA512:
case SSH_KEX_ECDH_SHA2_NISTP521:
session->next_crypto->digest_len = SHA512_DIGEST_LENGTH;
- session->next_crypto->mac_type = SSH_MAC_SHA512;
+ session->next_crypto->digest_type = SSH_KDF_SHA512;
session->next_crypto->secret_hash = malloc(session->next_crypto->digest_len);
if (session->next_crypto->secret_hash == NULL) {
ssh_set_error_oom(session);
@@ -1346,60 +1346,18 @@ int ssh_hashbufin_add_cookie(ssh_session session, unsigned char *cookie)
return 0;
}
-static int generate_one_key(ssh_string k, struct ssh_crypto_struct *crypto,
- unsigned char *output, char letter,
- size_t requested_size)
-{
- ssh_mac_ctx ctx;
- size_t size = crypto->digest_len;
- unsigned char digest[size];
-
- ctx = ssh_mac_ctx_init(crypto->mac_type);
- if (ctx == NULL) {
- return -1;
- }
-
- ssh_mac_update(ctx, k, ssh_string_len(k) + 4);
- ssh_mac_update(ctx, crypto->secret_hash, crypto->digest_len);
- ssh_mac_update(ctx, &letter, 1);
- ssh_mac_update(ctx, crypto->session_id, crypto->digest_len);
- ssh_mac_final(digest, ctx);
-
- if (requested_size < size) {
- size = requested_size;
- }
- memcpy(output, digest, size);
-
- while (requested_size > size) {
- ctx = ssh_mac_ctx_init(crypto->mac_type);
- if (ctx == NULL) {
- return -1;
- }
- ssh_mac_update(ctx, k, ssh_string_len(k) + 4);
- ssh_mac_update(ctx, crypto->secret_hash, crypto->digest_len);
- ssh_mac_update(ctx, output, size);
- ssh_mac_final(digest, ctx);
- if (requested_size < size + crypto->digest_len) {
- memcpy(output+size, digest, requested_size - size);
- } else {
- memcpy(output+size, digest, crypto->digest_len);
- }
- size += crypto->digest_len;
- }
-
- return 0;
-}
-
int ssh_generate_session_keys(ssh_session session)
{
ssh_string k_string = NULL;
struct ssh_crypto_struct *crypto = session->next_crypto;
+ unsigned char *key = NULL;
unsigned char *IV_cli_to_srv = NULL;
unsigned char *IV_srv_to_cli = NULL;
unsigned char *enckey_cli_to_srv = NULL;
unsigned char *enckey_srv_to_cli = NULL;
unsigned char *intkey_cli_to_srv = NULL;
unsigned char *intkey_srv_to_cli = NULL;
+ size_t key_len = 0;
size_t IV_len = 0;
size_t enckey_cli_to_srv_len = 0;
size_t enckey_srv_to_cli_len = 0;
@@ -1412,6 +1370,10 @@ int ssh_generate_session_keys(ssh_session session)
ssh_set_error_oom(session);
goto error;
}
+ /* See RFC4251 Section 5 for the definition of mpint which is the
+ * encoding we need to use for key in the SSH KDF */
+ key = (unsigned char *)k_string;
+ key_len = ssh_string_len(k_string) + 4;
IV_len = crypto->digest_len;
if (session->client) {
@@ -1440,33 +1402,33 @@ int ssh_generate_session_keys(ssh_session session)
}
/* IV */
- rc = generate_one_key(k_string, crypto, IV_cli_to_srv, 'A', IV_len);
+ rc = ssh_kdf(crypto, key, key_len, 'A', IV_cli_to_srv, IV_len);
if (rc < 0) {
goto error;
}
- rc = generate_one_key(k_string, crypto, IV_srv_to_cli, 'B', IV_len);
+ rc = ssh_kdf(crypto, key, key_len, 'B', IV_srv_to_cli, IV_len);
if (rc < 0) {
goto error;
}
/* Encryption Key */
- rc = generate_one_key(k_string, crypto, enckey_cli_to_srv, 'C',
- enckey_cli_to_srv_len);
+ rc = ssh_kdf(crypto, key, key_len, 'C', enckey_cli_to_srv,
+ enckey_cli_to_srv_len);
if (rc < 0) {
goto error;
}
- rc = generate_one_key(k_string, crypto, enckey_srv_to_cli, 'D',
- enckey_srv_to_cli_len);
+ rc = ssh_kdf(crypto, key, key_len, 'D', enckey_srv_to_cli,
+ enckey_srv_to_cli_len);
if (rc < 0) {
goto error;
}
/* Integrity Key */
- rc = generate_one_key(k_string, crypto, intkey_cli_to_srv, 'E',
- intkey_cli_to_srv_len);
+ rc = ssh_kdf(crypto, key, key_len, 'E', intkey_cli_to_srv,
+ intkey_cli_to_srv_len);
if (rc < 0) {
goto error;
}
- rc = generate_one_key(k_string, crypto, intkey_srv_to_cli, 'F',
- intkey_srv_to_cli_len);
+ rc = ssh_kdf(crypto, key, key_len, 'F', intkey_srv_to_cli,
+ intkey_srv_to_cli_len);
if (rc < 0) {
goto error;
}
diff --git a/src/libcrypto.c b/src/libcrypto.c
index 3df6e0a9..a89adb3b 100644
--- a/src/libcrypto.c
+++ b/src/libcrypto.c
@@ -61,15 +61,11 @@
#include "libssh/crypto.h"
-struct ssh_mac_ctx_struct {
- enum ssh_mac_e mac_type;
- union {
- SHACTX sha1_ctx;
- SHA256CTX sha256_ctx;
- SHA384CTX sha384_ctx;
- SHA512CTX sha512_ctx;
- } ctx;
-};
+#ifdef HAVE_OPENSSL_EVP_KDF_CTX_NEW_ID
+#include <openssl/kdf.h>
+#endif
+
+#include "libssh/crypto.h"
static int libcrypto_initialized = 0;
@@ -344,70 +340,80 @@ void md5_final(unsigned char *md, MD5CTX c)
EVP_MD_CTX_destroy(c);
}
-ssh_mac_ctx ssh_mac_ctx_init(enum ssh_mac_e type){
- ssh_mac_ctx ctx = malloc(sizeof(struct ssh_mac_ctx_struct));
- if (ctx == NULL) {
+#ifdef HAVE_OPENSSL_EVP_KDF_CTX_NEW_ID
+static const EVP_MD *sshkdf_digest_to_md(enum ssh_kdf_digest digest_type)
+{
+ switch (digest_type) {
+ case SSH_KDF_SHA1:
+ return EVP_sha1();
+ case SSH_KDF_SHA256:
+ return EVP_sha256();
+ case SSH_KDF_SHA384:
+ return EVP_sha384();
+ case SSH_KDF_SHA512:
+ return EVP_sha512();
+ }
return NULL;
- }
-
- 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:
- ctx->ctx.sha384_ctx = sha384_init();
- return ctx;
- case SSH_MAC_SHA512:
- ctx->ctx.sha512_ctx = sha512_init();
- return ctx;
- 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:
- sha384_update(ctx->ctx.sha384_ctx, data, len);
- break;
- case SSH_MAC_SHA512:
- sha512_update(ctx->ctx.sha512_ctx, data, len);
- break;
- default:
- break;
- }
+int ssh_kdf(struct ssh_crypto_struct *crypto,
+ unsigned char *key, size_t key_len,
+ int key_type, unsigned char *output,
+ size_t requested_len)
+{
+ EVP_KDF_CTX *ctx = EVP_KDF_CTX_new_id(EVP_KDF_SSHKDF);
+ int rc;
+
+ if (ctx == NULL) {
+ return -1;
+ }
+
+ rc = EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_MD,
+ sshkdf_digest_to_md(crypto->digest_type));
+ if (rc != 1) {
+ goto out;
+ }
+ rc = EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_KEY, key, key_len);
+ if (rc != 1) {
+ goto out;
+ }
+ rc = EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_SSHKDF_XCGHASH,
+ crypto->secret_hash, crypto->digest_len);
+ if (rc != 1) {
+ goto out;
+ }
+ rc = EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_SSHKDF_TYPE, key_type);
+ if (rc != 1) {
+ goto out;
+ }
+ rc = EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_SSHKDF_SESSION_ID,
+ crypto->session_id, crypto->digest_len);
+ if (rc != 1) {
+ goto out;
+ }
+ rc = EVP_KDF_derive(ctx, output, requested_len);
+ if (rc != 1) {
+ goto out;
+ }
+
+out:
+ EVP_KDF_CTX_free(ctx);
+ if (rc < 0) {
+ return rc;
+ }
+ return 0;
}
-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:
- sha384_final(md,ctx->ctx.sha384_ctx);
- break;
- case SSH_MAC_SHA512:
- sha512_final(md,ctx->ctx.sha512_ctx);
- break;
- default:
- break;
- }
- SAFE_FREE(ctx);
+#else
+int ssh_kdf(struct ssh_crypto_struct *crypto,
+ unsigned char *key, size_t key_len,
+ int key_type, unsigned char *output,
+ size_t requested_len)
+{
+ return sshkdf_derive_key(crypto, key, key_len,
+ key_type, output, requested_len);
}
+#endif
HMACCTX hmac_init(const void *key, int len, enum ssh_hmac_e type) {
HMACCTX ctx = NULL;
diff --git a/src/libgcrypt.c b/src/libgcrypt.c
index 25f2eddf..cccc3b3f 100644
--- a/src/libgcrypt.c
+++ b/src/libgcrypt.c
@@ -36,11 +36,6 @@
#ifdef HAVE_LIBGCRYPT
#include <gcrypt.h>
-struct ssh_mac_ctx_struct {
- enum ssh_mac_e mac_type;
- gcry_md_hd_t ctx;
-};
-
static int libgcrypt_initialized = 0;
static int alloc_key(struct ssh_cipher_struct *cipher) {
@@ -220,57 +215,13 @@ void md5_final(unsigned char *md, MD5CTX c) {
gcry_md_close(c);
}
-ssh_mac_ctx ssh_mac_ctx_init(enum ssh_mac_e type){
- ssh_mac_ctx ctx = malloc(sizeof(struct ssh_mac_ctx_struct));
- if (ctx == NULL) {
- return NULL;
- }
-
- 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 = 0;
- switch(ctx->mac_type){
- case SSH_MAC_SHA1:
- len=SHA_DIGEST_LEN;
- break;
- case SSH_MAC_SHA256:
- len=SHA256_DIGEST_LEN;
- break;
- case SSH_MAC_SHA384:
- len=SHA384_DIGEST_LEN;
- break;
- case SSH_MAC_SHA512:
- len=SHA512_DIGEST_LEN;
- break;
- }
- gcry_md_final(ctx->ctx);
- memcpy(md, gcry_md_read(ctx->ctx, 0), len);
- gcry_md_close(ctx->ctx);
- SAFE_FREE(ctx);
+int ssh_kdf(struct ssh_crypto_struct *crypto,
+ unsigned char *key, size_t key_len,
+ int key_type, unsigned char *output,
+ size_t requested_len)
+{
+ return sshkdf_derive_key(crypto, key, key_len,
+ key_type, output, requested_len);
}
HMACCTX hmac_init(const void *key, int len, enum ssh_hmac_e type) {
diff --git a/src/libmbedcrypto.c b/src/libmbedcrypto.c
index 748b3abb..02adffc0 100644
--- a/src/libmbedcrypto.c
+++ b/src/libmbedcrypto.c
@@ -37,10 +37,6 @@
static mbedtls_entropy_context ssh_mbedtls_entropy;
static mbedtls_ctr_drbg_context ssh_mbedtls_ctr_drbg;
-struct ssh_mac_ctx_struct {
- enum ssh_mac_e mac_type;
- mbedtls_md_context_t ctx;
-};
static int libmbedcrypto_initialized = 0;
void ssh_reseed(void)
@@ -386,66 +382,13 @@ void md5_final(unsigned char *md, MD5CTX c)
SAFE_FREE(c);
}
-ssh_mac_ctx ssh_mac_ctx_init(enum ssh_mac_e type)
-{
- ssh_mac_ctx ctx = malloc(sizeof (struct ssh_mac_ctx_struct));
- const mbedtls_md_info_t *md_info;
- int rc;
- if (ctx == NULL) {
- return NULL;
- }
-
- ctx->mac_type=type;
- switch(type) {
- case SSH_MAC_SHA1:
- md_info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA1);
- break;
- case SSH_MAC_SHA256:
- md_info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA256);
- break;
- case SSH_MAC_SHA384:
- md_info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA384);
- break;
- case SSH_MAC_SHA512:
- md_info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA512);
- break;
- default:
- goto error;
- }
-
- if (md_info == NULL) {
- goto error;
- }
-
- mbedtls_md_init(&ctx->ctx);
-
- rc = mbedtls_md_setup(&ctx->ctx, md_info, 0);
- if (rc != 0) {
- goto error;
- }
-
- rc = mbedtls_md_starts(&ctx->ctx);
- if (rc != 0) {
- goto error;
- }
-
- return ctx;
-
-error:
- SAFE_FREE(ctx);
- return NULL;
-}
-
-void ssh_mac_update(ssh_mac_ctx ctx, const void *data, unsigned long len)
+int ssh_kdf(struct ssh_crypto_struct *crypto,
+ unsigned char *key, size_t key_len,
+ int key_type, unsigned char *output,
+ size_t requested_len)
{
- mbedtls_md_update(&ctx->ctx, data, len);
-}
-
-void ssh_mac_final(unsigned char *md, ssh_mac_ctx ctx)
-{
- mbedtls_md_finish(&ctx->ctx, md);
- mbedtls_md_free(&ctx->ctx);
- SAFE_FREE(ctx);
+ return sshkdf_derive_key(crypto, key, key_len,
+ key_type, output, requested_len);
}
HMACCTX hmac_init(const void *key, int len, enum ssh_hmac_e type)
diff --git a/tests/unittests/torture_session_keys.c b/tests/unittests/torture_session_keys.c
index 65d3711b..2a21e63b 100644
--- a/tests/unittests/torture_session_keys.c
+++ b/tests/unittests/torture_session_keys.c
@@ -55,7 +55,7 @@ struct ssh_crypto_struct test_crypto = {
.out_cipher = &fake_out_cipher,
.in_hmac = SSH_HMAC_SHA256,
.out_hmac = SSH_HMAC_SHA256,
- .mac_type = SSH_MAC_SHA256,
+ .digest_type = SSH_KDF_SHA256,
};
struct ssh_session_struct session = {