diff --git a/include/libssh/wrapper.h b/include/libssh/wrapper.h index c1ddc2a8..9214a928 100644 --- a/include/libssh/wrapper.h +++ b/include/libssh/wrapper.h @@ -75,6 +75,7 @@ MD5CTX md5_init(void); void md5_ctx_free(MD5CTX); int md5_update(MD5CTX c, const void *data, size_t len); int md5_final(unsigned char *md, MD5CTX c); +int md5(const unsigned char *digest, size_t len, unsigned char *hash); SHACTX sha1_init(void); void sha1_ctx_free(SHACTX); diff --git a/src/md_crypto.c b/src/md_crypto.c index f7cda8dd..e7b1cf7a 100644 --- a/src/md_crypto.c +++ b/src/md_crypto.c @@ -322,3 +322,52 @@ md5_final(unsigned char *md, MD5CTX c) } return SSH_OK; } + +/** +* @ brief One-shot MD5. Not intended for use in security-relevant contexts. +*/ +int +md5(const unsigned char *digest, size_t len, unsigned char *hash) +{ + int rc, ret = SSH_ERROR; + unsigned int mdlen = 0; +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + EVP_MD *md5 = NULL; +#endif + MD5CTX c = EVP_MD_CTX_new(); + if (c == NULL) { + goto out; + } + +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + md5 = EVP_MD_fetch(NULL, "MD5", "provider=default,-fips"); + if (md5 == NULL) { + goto out; + } + rc = EVP_DigestInit(c, md5); +#else + rc = EVP_DigestInit_ex(c, EVP_md5(), NULL); +#endif + if (rc == 0) { + goto out; + } + + rc = EVP_DigestUpdate(c, digest, len); + if (rc != 1) { + goto out; + } + + rc = EVP_DigestFinal(c, hash, &mdlen); + if (rc != 1) { + goto out; + } + + ret = SSH_OK; + +out: + EVP_MD_CTX_free(c); +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + EVP_MD_free(md5); +#endif + return ret; +} diff --git a/src/md_gcrypt.c b/src/md_gcrypt.c index 93c7b0d9..c8830773 100644 --- a/src/md_gcrypt.c +++ b/src/md_gcrypt.c @@ -244,3 +244,9 @@ md5_final(unsigned char *md, MD5CTX c) gcry_md_close(c); return SSH_OK; } + +int md5(const unsigned char *digest, size_t len, unsigned char *hash) +{ + gcry_md_hash_buffer(GCRY_MD_MD5, hash, digest, len); + return SSH_OK; +} diff --git a/src/md_mbedcrypto.c b/src/md_mbedcrypto.c index b3529b4b..445f644d 100644 --- a/src/md_mbedcrypto.c +++ b/src/md_mbedcrypto.c @@ -405,3 +405,51 @@ md5_final(unsigned char *md, MD5CTX c) } return SSH_OK; } + +int md5(const unsigned char *digest, size_t len, unsigned char *hash) +{ + MD5CTX ctx = NULL; + int rc; + const mbedtls_md_info_t *md_info = + mbedtls_md_info_from_type(MBEDTLS_MD_MD5); + if (md_info == NULL) { + return SSH_ERROR; + } + + ctx = malloc(sizeof(mbedtls_md_context_t)); + if (ctx == NULL) { + return SSH_ERROR; + } + + mbedtls_md_init(ctx); + + rc = mbedtls_md_setup(ctx, md_info, 0); + if (rc != 0) { + mbedtls_md_free(ctx); + SAFE_FREE(ctx); + return SSH_ERROR; + } + + rc = mbedtls_md_starts(ctx); + if (rc != 0) { + mbedtls_md_free(ctx); + SAFE_FREE(ctx); + return SSH_ERROR; + } + + rc = mbedtls_md_update(ctx, digest, len); + if (rc != 0) { + mbedtls_md_free(ctx); + SAFE_FREE(ctx); + return SSH_ERROR; + } + + rc = mbedtls_md_finish(ctx, hash); + mbedtls_md_free(ctx); + SAFE_FREE(ctx); + if (rc != 0) { + return SSH_ERROR; + } + + return SSH_OK; +}