mirror of
https://git.libssh.org/projects/libssh.git
synced 2025-12-12 15:41:16 +03:00
Update HMAC function parameter type
New openssl API, libmbedtls, libgcrypt use size_t for HMAC len pameter. New helper functions were added in libcrypto.c to avoid code duplication. (the header pki.h is needed for this reason) Signed-off-by: Norbert Pocs <npocs@redhat.com> Reviewed-by: Jakub Jelen <jjelen@redhat.com> Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
This commit is contained in:
committed by
Andreas Schneider
parent
51c940adc9
commit
debd0ea4d3
@@ -80,7 +80,7 @@ int ssh_packet_decrypt(ssh_session session, uint8_t *destination, uint8_t *sourc
|
||||
size_t start, size_t encrypted_size);
|
||||
unsigned char *ssh_packet_encrypt(ssh_session session,
|
||||
void *packet,
|
||||
uint32_t len);
|
||||
size_t len);
|
||||
int ssh_packet_hmac_verify(ssh_session session, const void *data, size_t len,
|
||||
unsigned char *mac, enum ssh_hmac_e type);
|
||||
int ssh_packet_set_newkeys(ssh_session session,
|
||||
|
||||
@@ -96,9 +96,9 @@ EVPCTX evp_init(int nid);
|
||||
void evp_update(EVPCTX ctx, const void *data, size_t len);
|
||||
void evp_final(EVPCTX ctx, unsigned char *md, unsigned int *mdlen);
|
||||
|
||||
HMACCTX hmac_init(const void *key, size_t len, enum ssh_hmac_e type);
|
||||
void hmac_update(HMACCTX c, const void *data, size_t len);
|
||||
void hmac_final(HMACCTX ctx,unsigned char *hashmacbuf,unsigned int *len);
|
||||
HMACCTX hmac_init(const void *key,size_t len, enum ssh_hmac_e type);
|
||||
int hmac_update(HMACCTX c, const void *data, size_t len);
|
||||
int hmac_final(HMACCTX ctx, unsigned char *hashmacbuf, size_t *len);
|
||||
size_t hmac_digest_len(enum ssh_hmac_e type);
|
||||
|
||||
int ssh_kdf(struct ssh_crypto_struct *crypto,
|
||||
@@ -120,4 +120,11 @@ 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, bool etm);
|
||||
|
||||
#if defined(HAVE_LIBCRYPTO) && OPENSSL_VERSION_NUMBER >= 0x30000000L
|
||||
int evp_build_pkey(const char* name, OSSL_PARAM_BLD *param_bld, EVP_PKEY **pkey, int selection);
|
||||
int evp_dup_dsa_pkey(const ssh_key key, ssh_key new, int demote);
|
||||
int evp_dup_rsa_pkey(const ssh_key key, ssh_key new, int demote);
|
||||
int evp_dup_ecdsa_pkey(const ssh_key key, ssh_key new, int demote);
|
||||
#endif /* HAVE_LIBCRYPTO && OPENSSL_VERSION_NUMBER */
|
||||
|
||||
#endif /* WRAPPER_H_ */
|
||||
|
||||
@@ -210,8 +210,8 @@ static int match_hashed_host(const char *host, const char *sourcehash)
|
||||
HMACCTX mac;
|
||||
char *source;
|
||||
char *b64hash;
|
||||
int match;
|
||||
unsigned int size;
|
||||
int match, rc;
|
||||
size_t size;
|
||||
|
||||
if (strncmp(sourcehash, "|1|", 3) != 0) {
|
||||
return 0;
|
||||
@@ -256,8 +256,20 @@ static int match_hashed_host(const char *host, const char *sourcehash)
|
||||
return 0;
|
||||
}
|
||||
size = sizeof(buffer);
|
||||
hmac_update(mac, host, strlen(host));
|
||||
hmac_final(mac, buffer, &size);
|
||||
rc = hmac_update(mac, host, strlen(host));
|
||||
if (rc != 1) {
|
||||
ssh_buffer_free(salt);
|
||||
ssh_buffer_free(hash);
|
||||
|
||||
return 0;
|
||||
}
|
||||
rc = hmac_final(mac, buffer, &size);
|
||||
if (rc != 1) {
|
||||
ssh_buffer_free(salt);
|
||||
ssh_buffer_free(hash);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (size == ssh_buffer_get_len(hash) &&
|
||||
memcmp(buffer, ssh_buffer_get(hash), size) == 0) {
|
||||
|
||||
@@ -58,8 +58,9 @@ static int hash_hostname(const char *name,
|
||||
unsigned char *salt,
|
||||
unsigned int salt_size,
|
||||
unsigned char **hash,
|
||||
unsigned int *hash_size)
|
||||
size_t *hash_size)
|
||||
{
|
||||
int rc;
|
||||
HMACCTX mac_ctx;
|
||||
|
||||
mac_ctx = hmac_init(salt, salt_size, SSH_HMAC_SHA1);
|
||||
@@ -67,8 +68,13 @@ static int hash_hostname(const char *name,
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
hmac_update(mac_ctx, name, strlen(name));
|
||||
hmac_final(mac_ctx, *hash, hash_size);
|
||||
rc = hmac_update(mac_ctx, name, strlen(name));
|
||||
if (rc != 1)
|
||||
return SSH_ERROR;
|
||||
|
||||
rc = hmac_final(mac_ctx, *hash, hash_size);
|
||||
if (rc != 1)
|
||||
return SSH_ERROR;
|
||||
|
||||
return SSH_OK;
|
||||
}
|
||||
@@ -81,7 +87,7 @@ static int match_hashed_hostname(const char *host, const char *hashed_host)
|
||||
ssh_buffer hash = NULL;
|
||||
unsigned char hashed_buf[256] = {0};
|
||||
unsigned char *hashed_buf_ptr = hashed_buf;
|
||||
unsigned int hashed_buf_size = sizeof(hashed_buf);
|
||||
size_t hashed_buf_size = sizeof(hashed_buf);
|
||||
int cmp;
|
||||
int rc;
|
||||
int match = 0;
|
||||
|
||||
254
src/libcrypto.c
254
src/libcrypto.c
@@ -26,13 +26,14 @@
|
||||
#include <string.h>
|
||||
#ifdef HAVE_SYS_TIME_H
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
#endif /* HAVE_SYS_TIME_H */
|
||||
|
||||
#include "libssh/priv.h"
|
||||
#include "libssh/session.h"
|
||||
#include "libssh/crypto.h"
|
||||
#include "libssh/wrapper.h"
|
||||
#include "libssh/libcrypto.h"
|
||||
#include "libssh/pki.h"
|
||||
#if defined(HAVE_OPENSSL_EVP_CHACHA20) && defined(HAVE_OPENSSL_EVP_POLY1305)
|
||||
#include "libssh/bytearray.h"
|
||||
#include "libssh/chacha20-poly1305-common.h"
|
||||
@@ -40,12 +41,17 @@
|
||||
|
||||
#ifdef HAVE_LIBCRYPTO
|
||||
|
||||
#include <openssl/opensslv.h>
|
||||
#include <openssl/sha.h>
|
||||
#include <openssl/md5.h>
|
||||
#if OPENSSL_VERSION_NUMBER < 0x30000000L
|
||||
#include <openssl/dsa.h>
|
||||
#include <openssl/rsa.h>
|
||||
#include <openssl/hmac.h>
|
||||
#include <openssl/opensslv.h>
|
||||
#else
|
||||
#include <openssl/param_build.h>
|
||||
#include <openssl/core_names.h>
|
||||
#endif /* OPENSSL_VERSION_NUMBER */
|
||||
#include <openssl/rand.h>
|
||||
#include <openssl/engine.h>
|
||||
|
||||
@@ -54,11 +60,11 @@
|
||||
#ifdef HAVE_OPENSSL_AES_H
|
||||
#define HAS_AES
|
||||
#include <openssl/aes.h>
|
||||
#endif
|
||||
#endif /* HAVE_OPENSSL_AES_H */
|
||||
#ifdef HAVE_OPENSSL_DES_H
|
||||
#define HAS_DES
|
||||
#include <openssl/des.h>
|
||||
#endif
|
||||
#endif /* HAVE_OPENSSL_DES_H */
|
||||
|
||||
#if (defined(HAVE_VALGRIND_VALGRIND_H) && defined(HAVE_OPENSSL_IA32CAP_LOC))
|
||||
#include <valgrind/valgrind.h>
|
||||
@@ -200,7 +206,7 @@ void evp_final(EVPCTX ctx, unsigned char *md, unsigned int *mdlen)
|
||||
EVP_DigestFinal(ctx, md, mdlen);
|
||||
EVP_MD_CTX_free(ctx);
|
||||
}
|
||||
#endif
|
||||
#endif /* HAVE_OPENSSL_ECC */
|
||||
|
||||
SHA256CTX sha256_init(void)
|
||||
{
|
||||
@@ -414,8 +420,7 @@ int ssh_kdf(struct ssh_crypto_struct *crypto,
|
||||
return sshkdf_derive_key(crypto, key, key_len,
|
||||
key_type, output, requested_len);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* HAVE_OPENSSL_EVP_KDF_CTX_NEW_ID */
|
||||
HMACCTX hmac_init(const void *key, size_t len, enum ssh_hmac_e type)
|
||||
{
|
||||
HMACCTX ctx = NULL;
|
||||
@@ -461,17 +466,22 @@ error:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void hmac_update(HMACCTX ctx, const void *data, size_t len)
|
||||
int hmac_update(HMACCTX ctx, const void *data, size_t len)
|
||||
{
|
||||
EVP_DigestSignUpdate(ctx, data, len);
|
||||
return EVP_DigestSignUpdate(ctx, data, len);
|
||||
}
|
||||
|
||||
void hmac_final(HMACCTX ctx, unsigned char *hashmacbuf, unsigned int *len)
|
||||
int hmac_final(HMACCTX ctx, unsigned char *hashmacbuf, size_t *len)
|
||||
{
|
||||
size_t res = 0;
|
||||
EVP_DigestSignFinal(ctx, hashmacbuf, &res);
|
||||
size_t res = *len;
|
||||
int rc;
|
||||
rc = EVP_DigestSignFinal(ctx, hashmacbuf, &res);
|
||||
EVP_MD_CTX_free(ctx);
|
||||
*len = res;
|
||||
if (rc == 1) {
|
||||
*len = res;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void evp_cipher_init(struct ssh_cipher_struct *cipher)
|
||||
@@ -515,7 +525,7 @@ static void evp_cipher_init(struct ssh_cipher_struct *cipher)
|
||||
cipher->cipher = EVP_bf_cbc();
|
||||
break;
|
||||
/* ciphers not using EVP */
|
||||
#endif
|
||||
#endif /* WITH_BLOWFISH_CIPHER */
|
||||
case SSH_AEAD_CHACHA20_POLY1305:
|
||||
SSH_LOG(SSH_LOG_WARNING, "The ChaCha cipher cannot be handled here");
|
||||
break;
|
||||
@@ -822,12 +832,17 @@ struct chacha20_poly1305_keysched {
|
||||
EVP_CIPHER_CTX *main_evp;
|
||||
/* cipher handle used for encrypting the length field */
|
||||
EVP_CIPHER_CTX *header_evp;
|
||||
#if OPENSSL_VERSION_NUMBER < 0x30000000L
|
||||
/* mac handle used for authenticating the packets */
|
||||
EVP_PKEY_CTX *pctx;
|
||||
/* Poly1305 key */
|
||||
EVP_PKEY *key;
|
||||
/* MD context for digesting data in poly1305 */
|
||||
EVP_MD_CTX *mctx;
|
||||
#else
|
||||
/* MAC context used to do poly1305 */
|
||||
EVP_MAC_CTX *mctx;
|
||||
#endif /* OPENSSL_VERSION_NUMBER */
|
||||
};
|
||||
|
||||
static void
|
||||
@@ -845,11 +860,16 @@ chacha20_poly1305_cleanup(struct ssh_cipher_struct *cipher)
|
||||
ctx->main_evp = NULL;
|
||||
EVP_CIPHER_CTX_free(ctx->header_evp);
|
||||
ctx->header_evp = NULL;
|
||||
#if OPENSSL_VERSION_NUMBER < 0x30000000L
|
||||
/* ctx->pctx is freed as part of MD context */
|
||||
EVP_PKEY_free(ctx->key);
|
||||
ctx->key = NULL;
|
||||
EVP_MD_CTX_free(ctx->mctx);
|
||||
ctx->mctx = NULL;
|
||||
#else
|
||||
EVP_MAC_CTX_free(ctx->mctx);
|
||||
ctx->mctx = NULL;
|
||||
#endif /* OPENSSL_VERSION_NUMBER */
|
||||
|
||||
SAFE_FREE(cipher->chacha20_schedule);
|
||||
}
|
||||
@@ -862,6 +882,9 @@ chacha20_poly1305_set_key(struct ssh_cipher_struct *cipher,
|
||||
struct chacha20_poly1305_keysched *ctx = NULL;
|
||||
uint8_t *u8key = key;
|
||||
int ret = SSH_ERROR, rv;
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
|
||||
EVP_MAC *mac = NULL;
|
||||
#endif
|
||||
|
||||
if (cipher->chacha20_schedule == NULL) {
|
||||
ctx = calloc(1, sizeof(*ctx));
|
||||
@@ -901,14 +924,30 @@ chacha20_poly1305_set_key(struct ssh_cipher_struct *cipher,
|
||||
/* The Poly1305 key initialization is delayed to the time we know
|
||||
* the actual key for packet so we do not need to create a bogus keys
|
||||
*/
|
||||
#if OPENSSL_VERSION_NUMBER < 0x30000000L
|
||||
ctx->mctx = EVP_MD_CTX_new();
|
||||
if (ctx->mctx == NULL) {
|
||||
SSH_LOG(SSH_LOG_WARNING, "EVP_MD_CTX_new failed");
|
||||
return SSH_ERROR;
|
||||
}
|
||||
#else
|
||||
mac = EVP_MAC_fetch(NULL, "poly1305", NULL);
|
||||
if (mac == NULL) {
|
||||
SSH_LOG(SSH_LOG_WARNING, "EVP_MAC_fetch failed");
|
||||
goto out;
|
||||
}
|
||||
ctx->mctx = EVP_MAC_CTX_new(mac);
|
||||
if (ctx->mctx == NULL) {
|
||||
SSH_LOG(SSH_LOG_WARNING, "EVP_MAC_CTX_new failed");
|
||||
goto out;
|
||||
}
|
||||
#endif /* OPENSSL_VERSION_NUMBER */
|
||||
|
||||
ret = SSH_OK;
|
||||
out:
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
|
||||
EVP_MAC_free(mac);
|
||||
#endif
|
||||
if (ret != SSH_OK) {
|
||||
chacha20_poly1305_cleanup(cipher);
|
||||
}
|
||||
@@ -980,6 +1019,7 @@ chacha20_poly1305_packet_setup(struct ssh_cipher_struct *cipher,
|
||||
#endif /* DEBUG_CRYPTO */
|
||||
|
||||
/* Set the Poly1305 key */
|
||||
#if OPENSSL_VERSION_NUMBER < 0x30000000L
|
||||
if (ctx->key == NULL) {
|
||||
/* Poly1305 Initialization needs to know the actual key */
|
||||
ctx->key = EVP_PKEY_new_mac_key(EVP_PKEY_POLY1305, NULL,
|
||||
@@ -1003,6 +1043,13 @@ chacha20_poly1305_packet_setup(struct ssh_cipher_struct *cipher,
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
#else
|
||||
rv = EVP_MAC_init(ctx->mctx, poly_key, POLY1305_KEYLEN, NULL);
|
||||
if (rv != 1) {
|
||||
SSH_LOG(SSH_LOG_WARNING, "EVP_MAC_init failed");
|
||||
goto out;
|
||||
}
|
||||
#endif /* OPENSSL_VERSION_NUMBER */
|
||||
|
||||
ret = SSH_OK;
|
||||
out:
|
||||
@@ -1080,6 +1127,7 @@ chacha20_poly1305_aead_decrypt(struct ssh_cipher_struct *cipher,
|
||||
#endif /* DEBUG_CRYPTO */
|
||||
|
||||
/* Calculate MAC of received data */
|
||||
#if OPENSSL_VERSION_NUMBER < 0x30000000L
|
||||
rv = EVP_DigestSignUpdate(ctx->mctx, complete_packet,
|
||||
encrypted_size + sizeof(uint32_t));
|
||||
if (rv != 1) {
|
||||
@@ -1092,6 +1140,20 @@ chacha20_poly1305_aead_decrypt(struct ssh_cipher_struct *cipher,
|
||||
SSH_LOG(SSH_LOG_WARNING, "poly1305 verify error");
|
||||
goto out;
|
||||
}
|
||||
#else
|
||||
rv = EVP_MAC_update(ctx->mctx, complete_packet,
|
||||
encrypted_size + sizeof(uint32_t));
|
||||
if (rv != 1) {
|
||||
SSH_LOG(SSH_LOG_WARNING, "EVP_MAC_update failed");
|
||||
goto out;
|
||||
}
|
||||
|
||||
rv = EVP_MAC_final(ctx->mctx, tag, &taglen, POLY1305_TAGLEN);
|
||||
if (rv != 1) {
|
||||
SSH_LOG(SSH_LOG_WARNING, "EVP_MAC_final failed");
|
||||
goto out;
|
||||
}
|
||||
#endif /* OPENSSL_VERSION_NUMBER */
|
||||
|
||||
#ifdef DEBUG_CRYPTO
|
||||
ssh_log_hexdump("calculated mac", tag, POLY1305_TAGLEN);
|
||||
@@ -1182,6 +1244,7 @@ chacha20_poly1305_aead_encrypt(struct ssh_cipher_struct *cipher,
|
||||
}
|
||||
|
||||
/* step 4, compute the MAC */
|
||||
#if OPENSSL_VERSION_NUMBER < 0x30000000L
|
||||
ret = EVP_DigestSignUpdate(ctx->mctx, out_packet, len);
|
||||
if (ret <= 0) {
|
||||
SSH_LOG(SSH_LOG_WARNING, "EVP_DigestSignUpdate failed");
|
||||
@@ -1192,6 +1255,19 @@ chacha20_poly1305_aead_encrypt(struct ssh_cipher_struct *cipher,
|
||||
SSH_LOG(SSH_LOG_WARNING, "EVP_DigestSignFinal failed");
|
||||
return;
|
||||
}
|
||||
#else
|
||||
ret = EVP_MAC_update(ctx->mctx, (void*)out_packet, len);
|
||||
if (ret != 1) {
|
||||
SSH_LOG(SSH_LOG_WARNING, "EVP_MAC_update failed");
|
||||
return;
|
||||
}
|
||||
|
||||
ret = EVP_MAC_final(ctx->mctx, tag, &taglen, POLY1305_TAGLEN);
|
||||
if (ret != 1) {
|
||||
SSH_LOG(SSH_LOG_WARNING, "EVP_MAC_final failed");
|
||||
return;
|
||||
}
|
||||
#endif /* OPENSSL_VERSION_NUMBER */
|
||||
}
|
||||
#endif /* defined(HAVE_OPENSSL_EVP_CHACHA20) && defined(HAVE_OPENSSL_EVP_POLY1305) */
|
||||
|
||||
@@ -1222,7 +1298,7 @@ static struct ssh_cipher_struct ssh_ciphertab[] = {
|
||||
.decrypt = evp_cipher_decrypt,
|
||||
.cleanup = evp_cipher_cleanup
|
||||
},
|
||||
#endif
|
||||
#endif /* WITH_BLOWFISH_CIPHER */
|
||||
#ifdef HAS_AES
|
||||
{
|
||||
.name = "aes128-ctr",
|
||||
@@ -1398,10 +1474,10 @@ int ssh_crypto_init(void)
|
||||
/* Bit #57 denotes AES-NI instruction set extension */
|
||||
OPENSSL_ia32cap &= ~(1LL << 57);
|
||||
}
|
||||
#endif
|
||||
#endif /* CAN_DISABLE_AESNI */
|
||||
#if OPENSSL_VERSION_NUMBER < 0x10100000L
|
||||
OpenSSL_add_all_algorithms();
|
||||
#endif
|
||||
#endif /* OPENSSL_VERSION_NUMBER */
|
||||
|
||||
#if !defined(HAVE_OPENSSL_EVP_CHACHA20) || !defined(HAVE_OPENSSL_EVP_POLY1305)
|
||||
for (i = 0; ssh_ciphertab[i].name != NULL; i++) {
|
||||
@@ -1436,9 +1512,151 @@ void ssh_crypto_finalize(void)
|
||||
#if OPENSSL_VERSION_NUMBER < 0x10100000L
|
||||
EVP_cleanup();
|
||||
CRYPTO_cleanup_all_ex_data();
|
||||
#endif
|
||||
#endif /* OPENSSL_VERSION_NUMBER < 0x10100000L */
|
||||
|
||||
libcrypto_initialized = 0;
|
||||
}
|
||||
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
|
||||
/**
|
||||
* @internal
|
||||
* @brief Create EVP_PKEY from parameters
|
||||
*
|
||||
* @param[in] name Algorithm to use. For more info see manpage of EVP_PKEY_CTX_new_from_name
|
||||
*
|
||||
* @param[in] param_bld Constructed param builder for the pkey
|
||||
*
|
||||
* @param[out] pkey Created EVP_PKEY variable
|
||||
*
|
||||
* @param[in] selection Reference selections at man EVP_PKEY_FROMDATA
|
||||
*
|
||||
* @return 0 on success, -1 on error
|
||||
*/
|
||||
int evp_build_pkey(const char* name, OSSL_PARAM_BLD *param_bld,
|
||||
EVP_PKEY **pkey, int selection)
|
||||
{
|
||||
int rc;
|
||||
EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new_from_name(NULL, name, NULL);
|
||||
OSSL_PARAM *params = NULL;
|
||||
|
||||
if (ctx == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
params = OSSL_PARAM_BLD_to_param(param_bld);
|
||||
if (params == NULL) {
|
||||
EVP_PKEY_CTX_free(ctx);
|
||||
return -1;
|
||||
}
|
||||
|
||||
rc = EVP_PKEY_fromdata_init(ctx);
|
||||
if (rc != 1) {
|
||||
OSSL_PARAM_free(params);
|
||||
EVP_PKEY_CTX_free(ctx);
|
||||
return -1;
|
||||
}
|
||||
|
||||
rc = EVP_PKEY_fromdata(ctx, pkey, selection, params);
|
||||
if (rc != 1) {
|
||||
OSSL_PARAM_free(params);
|
||||
EVP_PKEY_CTX_free(ctx);
|
||||
return -1;
|
||||
}
|
||||
|
||||
OSSL_PARAM_free(params);
|
||||
EVP_PKEY_CTX_free(ctx);
|
||||
|
||||
return SSH_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief creates a copy of EVP_PKEY
|
||||
*
|
||||
* @param[in] name Algorithm to use. For more info see manpage of
|
||||
* EVP_PKEY_CTX_new_from_name
|
||||
*
|
||||
* @param[in] key Key being duplicated from
|
||||
*
|
||||
* @param[in] demote Same as at pki_key_dup, only the public
|
||||
* part of the key gets duplicated if true
|
||||
*
|
||||
* @param[out] new_key The key where the duplicate is saved
|
||||
*
|
||||
* @return 0 on success, -1 on error
|
||||
*/
|
||||
static int evp_dup_pkey(const char* name, const ssh_key key, int demote,
|
||||
ssh_key new_key)
|
||||
{
|
||||
int rc;
|
||||
EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new_from_name(NULL, name, NULL);
|
||||
OSSL_PARAM *params = NULL;
|
||||
|
||||
if (ctx == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!demote && (key->flags & SSH_KEY_FLAG_PRIVATE)) {
|
||||
rc = EVP_PKEY_todata(key->key, EVP_PKEY_KEYPAIR, ¶ms);
|
||||
if (rc != 1) {
|
||||
EVP_PKEY_CTX_free(ctx);
|
||||
return -1;
|
||||
}
|
||||
|
||||
rc = EVP_PKEY_fromdata_init(ctx);
|
||||
if (rc != 1) {
|
||||
EVP_PKEY_CTX_free(ctx);
|
||||
OSSL_PARAM_free(params);
|
||||
return -1;
|
||||
}
|
||||
|
||||
rc = EVP_PKEY_fromdata(ctx, &(new_key->key), EVP_PKEY_KEYPAIR, params);
|
||||
if (rc != 1) {
|
||||
EVP_PKEY_CTX_free(ctx);
|
||||
OSSL_PARAM_free(params);
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
rc = EVP_PKEY_todata(key->key, EVP_PKEY_PUBLIC_KEY, ¶ms);
|
||||
if (rc != 1) {
|
||||
EVP_PKEY_CTX_free(ctx);
|
||||
return -1;
|
||||
}
|
||||
|
||||
rc = EVP_PKEY_fromdata_init(ctx);
|
||||
if (rc != 1) {
|
||||
EVP_PKEY_CTX_free(ctx);
|
||||
OSSL_PARAM_free(params);
|
||||
return -1;
|
||||
}
|
||||
|
||||
rc = EVP_PKEY_fromdata(ctx, &(new_key->key), EVP_PKEY_PUBLIC_KEY, params);
|
||||
if (rc != 1) {
|
||||
EVP_PKEY_CTX_free(ctx);
|
||||
OSSL_PARAM_free(params);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
OSSL_PARAM_free(params);
|
||||
EVP_PKEY_CTX_free(ctx);
|
||||
|
||||
return SSH_OK;
|
||||
}
|
||||
|
||||
int evp_dup_dsa_pkey(const ssh_key key, ssh_key new, int demote)
|
||||
{
|
||||
return evp_dup_pkey("DSA", key, demote, new);
|
||||
}
|
||||
|
||||
int evp_dup_rsa_pkey(const ssh_key key, ssh_key new, int demote)
|
||||
{
|
||||
return evp_dup_pkey("RSA", key, demote, new);
|
||||
}
|
||||
|
||||
int evp_dup_ecdsa_pkey(const ssh_key key, ssh_key new, int demote)
|
||||
{
|
||||
return evp_dup_pkey("EC", key, demote, new);
|
||||
}
|
||||
#endif /* OPENSSL_VERSION_NUMBER */
|
||||
|
||||
#endif /* LIBCRYPTO */
|
||||
|
||||
@@ -268,14 +268,20 @@ HMACCTX hmac_init(const void *key, size_t len, enum ssh_hmac_e type) {
|
||||
return c;
|
||||
}
|
||||
|
||||
void hmac_update(HMACCTX c, const void *data, size_t len) {
|
||||
int hmac_update(HMACCTX c, const void *data, size_t len) {
|
||||
gcry_md_write(c, data, len);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void hmac_final(HMACCTX c, unsigned char *hashmacbuf, unsigned int *len) {
|
||||
*len = gcry_md_get_algo_dlen(gcry_md_get_algo(c));
|
||||
int hmac_final(HMACCTX c, unsigned char *hashmacbuf, size_t *len) {
|
||||
unsigned int tmp = gcry_md_get_algo_dlen(gcry_md_get_algo(c));
|
||||
if (tmp > SIZE_MAX) {
|
||||
return 0;
|
||||
}
|
||||
*len = (size_t)tmp;
|
||||
memcpy(hashmacbuf, gcry_md_read(c, 0), *len);
|
||||
gcry_md_close(c);
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifdef WITH_BLOWFISH_CIPHER
|
||||
|
||||
@@ -447,17 +447,21 @@ error:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void hmac_update(HMACCTX c, const void *data, size_t len)
|
||||
/* mbedtls returns 0 on success, but in this context
|
||||
* success is 1 */
|
||||
int hmac_update(HMACCTX c, const void *data, size_t len)
|
||||
{
|
||||
mbedtls_md_hmac_update(c, data, len);
|
||||
return !mbedtls_md_hmac_update(c, data, len);
|
||||
}
|
||||
|
||||
void hmac_final(HMACCTX c, unsigned char *hashmacbuf, unsigned int *len)
|
||||
int hmac_final(HMACCTX c, unsigned char *hashmacbuf, size_t *len)
|
||||
{
|
||||
*len = mbedtls_md_get_size(c->MBEDTLS_PRIVATE(md_info));
|
||||
mbedtls_md_hmac_finish(c, hashmacbuf);
|
||||
int rc;
|
||||
*len = (unsigned int)mbedtls_md_get_size(c->md_info);
|
||||
rc = !mbedtls_md_hmac_finish(c, hashmacbuf);
|
||||
mbedtls_md_free(c);
|
||||
SAFE_FREE(c);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int
|
||||
|
||||
@@ -130,14 +130,15 @@ int ssh_packet_decrypt(ssh_session session,
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned char *ssh_packet_encrypt(ssh_session session, void *data, uint32_t len)
|
||||
unsigned char *ssh_packet_encrypt(ssh_session session, void *data, size_t len)
|
||||
{
|
||||
struct ssh_crypto_struct *crypto = NULL;
|
||||
struct ssh_cipher_struct *cipher = NULL;
|
||||
HMACCTX ctx = NULL;
|
||||
char *out = NULL;
|
||||
int etm_packet_offset = 0;
|
||||
unsigned int finallen, blocksize;
|
||||
int etm_packet_offset = 0, rc;
|
||||
unsigned int blocksize;
|
||||
size_t finallen = DIGEST_MAX_LEN;
|
||||
uint32_t seq, lenfield_blocksize;
|
||||
enum ssh_hmac_e type;
|
||||
bool etm;
|
||||
@@ -161,7 +162,7 @@ unsigned char *ssh_packet_encrypt(ssh_session session, void *data, uint32_t len)
|
||||
|
||||
if ((len - lenfield_blocksize - etm_packet_offset) % blocksize != 0) {
|
||||
ssh_set_error(session, SSH_FATAL, "Cryptographic functions must be set"
|
||||
" on at least one blocksize (received %d)", len);
|
||||
" on at least one blocksize (received %zu)", len);
|
||||
return NULL;
|
||||
}
|
||||
out = calloc(1, len);
|
||||
@@ -185,9 +186,21 @@ unsigned char *ssh_packet_encrypt(ssh_session session, void *data, uint32_t len)
|
||||
}
|
||||
|
||||
if (!etm) {
|
||||
hmac_update(ctx, (unsigned char *)&seq, sizeof(uint32_t));
|
||||
hmac_update(ctx, data, len);
|
||||
hmac_final(ctx, crypto->hmacbuf, &finallen);
|
||||
rc = hmac_update(ctx, (unsigned char *)&seq, sizeof(uint32_t));
|
||||
if (rc != 1) {
|
||||
SAFE_FREE(out);
|
||||
return NULL;
|
||||
}
|
||||
rc = hmac_update(ctx, data, len);
|
||||
if (rc != 1) {
|
||||
SAFE_FREE(out);
|
||||
return NULL;
|
||||
}
|
||||
rc = hmac_final(ctx, crypto->hmacbuf, &finallen);
|
||||
if (rc != 1) {
|
||||
SAFE_FREE(out);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -197,14 +210,26 @@ unsigned char *ssh_packet_encrypt(ssh_session session, void *data, uint32_t len)
|
||||
if (type != SSH_HMAC_NONE) {
|
||||
if (etm) {
|
||||
PUSH_BE_U32(data, 0, len - etm_packet_offset);
|
||||
hmac_update(ctx, (unsigned char *)&seq, sizeof(uint32_t));
|
||||
hmac_update(ctx, data, len);
|
||||
hmac_final(ctx, crypto->hmacbuf, &finallen);
|
||||
rc = hmac_update(ctx, (unsigned char *)&seq, sizeof(uint32_t));
|
||||
if (rc != 1) {
|
||||
SAFE_FREE(out);
|
||||
return NULL;
|
||||
}
|
||||
rc = hmac_update(ctx, data, len);
|
||||
if (rc != 1) {
|
||||
SAFE_FREE(out);
|
||||
return NULL;
|
||||
}
|
||||
rc = hmac_final(ctx, crypto->hmacbuf, &finallen);
|
||||
if (rc != 1) {
|
||||
SAFE_FREE(out);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
#ifdef DEBUG_CRYPTO
|
||||
ssh_log_hexdump("mac: ", data, len);
|
||||
if (finallen != hmac_digest_len(type)) {
|
||||
printf("Final len is %d\n", finallen);
|
||||
printf("Final len is %zu\n", finallen);
|
||||
}
|
||||
ssh_log_hexdump("Packet hmac", crypto->hmacbuf, hmac_digest_len(type));
|
||||
#endif
|
||||
@@ -238,7 +263,7 @@ int ssh_packet_hmac_verify(ssh_session session,
|
||||
struct ssh_crypto_struct *crypto = NULL;
|
||||
unsigned char hmacbuf[DIGEST_MAX_LEN] = {0};
|
||||
HMACCTX ctx;
|
||||
unsigned int hmaclen;
|
||||
size_t hmaclen = DIGEST_MAX_LEN;
|
||||
uint32_t seq;
|
||||
|
||||
/* AEAD types have no mac checking */
|
||||
|
||||
Reference in New Issue
Block a user