diff options
Diffstat (limited to 'src/libcrypto.c')
-rw-r--r-- | src/libcrypto.c | 140 |
1 files changed, 73 insertions, 67 deletions
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; |