From 8b3a864c5bd69a72e7b14a2d94d57dd935aace2f Mon Sep 17 00:00:00 2001 From: skundu07 <36504923+skundu07@users.noreply.github.com> Date: Fri, 23 Sep 2022 22:41:20 +0530 Subject: [PATCH] Add RSA-SHA2 support for the WinCNG backend (#736) Notes: Added code to support RSA-SHA2 for WinCNG backend. Credit: skundu07 --- src/wincng.c | 79 +++++++++++++++++++++++++++++++++++++++++----------- src/wincng.h | 13 ++++++--- 2 files changed, 72 insertions(+), 20 deletions(-) diff --git a/src/wincng.c b/src/wincng.c index ee5f9e6dbd..ebf7929509 100644 --- a/src/wincng.c +++ b/src/wincng.c @@ -596,7 +596,8 @@ _libssh2_wincng_hmac_cleanup(_libssh2_wincng_hash_ctx *ctx) */ int -_libssh2_wincng_key_sha1_verify(_libssh2_wincng_key_ctx *ctx, +_libssh2_wincng_key_sha_verify(_libssh2_wincng_key_ctx *ctx, + size_t hashlen, const unsigned char *sig, unsigned long sig_len, const unsigned char *m, @@ -604,30 +605,48 @@ _libssh2_wincng_key_sha1_verify(_libssh2_wincng_key_ctx *ctx, unsigned long flags) { BCRYPT_PKCS1_PADDING_INFO paddingInfoPKCS1; + BCRYPT_ALG_HANDLE hAlgHash; void *pPaddingInfo; unsigned char *data, *hash; - unsigned long datalen, hashlen; + unsigned long datalen; int ret; + if(hashlen == SHA_DIGEST_LENGTH) { + hAlgHash = _libssh2_wincng.hAlgHashSHA1; + paddingInfoPKCS1.pszAlgId = BCRYPT_SHA1_ALGORITHM; + } + else if(hashlen == SHA256_DIGEST_LENGTH) { + hAlgHash = _libssh2_wincng.hAlgHashSHA256; + paddingInfoPKCS1.pszAlgId = BCRYPT_SHA256_ALGORITHM; + } + else if(hashlen == SHA384_DIGEST_LENGTH) { + hAlgHash = _libssh2_wincng.hAlgHashSHA384; + paddingInfoPKCS1.pszAlgId = BCRYPT_SHA384_ALGORITHM; + } + else if(hashlen == SHA512_DIGEST_LENGTH) { + hAlgHash = _libssh2_wincng.hAlgHashSHA512; + paddingInfoPKCS1.pszAlgId = BCRYPT_SHA512_ALGORITHM; + } + else { + return -1; + } + datalen = m_len; data = malloc(datalen); if(!data) { return -1; } - hashlen = SHA_DIGEST_LENGTH; hash = malloc(hashlen); if(!hash) { free(data); return -1; } - memcpy(data, m, datalen); ret = _libssh2_wincng_hash(data, datalen, - _libssh2_wincng.hAlgHashSHA1, + hAlgHash, hash, hashlen); - _libssh2_wincng_safe_free(data, datalen); if(ret) { @@ -643,7 +662,6 @@ _libssh2_wincng_key_sha1_verify(_libssh2_wincng_key_ctx *ctx, } if(flags & BCRYPT_PAD_PKCS1) { - paddingInfoPKCS1.pszAlgId = BCRYPT_SHA1_ALGORITHM; pPaddingInfo = &paddingInfoPKCS1; } else @@ -1209,12 +1227,24 @@ _libssh2_wincng_rsa_sha1_verify(libssh2_rsa_ctx *rsa, const unsigned char *m, unsigned long m_len) { - return _libssh2_wincng_key_sha1_verify(rsa, sig, sig_len, m, m_len, - BCRYPT_PAD_PKCS1); + return _libssh2_wincng_key_sha_verify(rsa, SHA_DIGEST_LENGTH, sig, sig_len, + m, m_len, BCRYPT_PAD_PKCS1); } int -_libssh2_wincng_rsa_sha1_sign(LIBSSH2_SESSION *session, +_libssh2_wincng_rsa_sha2_verify(libssh2_rsa_ctx* rsa, + size_t hash_len, + const unsigned char *sig, + unsigned long sig_len, + const unsigned char *m, + unsigned long m_len) +{ + return _libssh2_wincng_key_sha_verify(rsa, hash_len, sig, sig_len, m, + m_len, BCRYPT_PAD_PKCS1); +} + +int +_libssh2_wincng_rsa_sha_sign(LIBSSH2_SESSION *session, libssh2_rsa_ctx *rsa, const unsigned char *hash, size_t hash_len, @@ -1226,14 +1256,25 @@ _libssh2_wincng_rsa_sha1_sign(LIBSSH2_SESSION *session, unsigned long cbData, datalen, siglen; int ret; + if(hash_len == SHA_DIGEST_LENGTH) + paddingInfo.pszAlgId = BCRYPT_SHA1_ALGORITHM; + else if(hash_len == SHA256_DIGEST_LENGTH) + paddingInfo.pszAlgId = BCRYPT_SHA256_ALGORITHM; + else if(hash_len == SHA384_DIGEST_LENGTH) + paddingInfo.pszAlgId = BCRYPT_SHA384_ALGORITHM; + else if(hash_len == SHA512_DIGEST_LENGTH) + paddingInfo.pszAlgId = BCRYPT_SHA512_ALGORITHM; + else { + _libssh2_error(session, LIBSSH2_ERROR_PROTO, + "Unsupported hash digest length"); + return -1; + } + datalen = (unsigned long)hash_len; data = malloc(datalen); if(!data) { return -1; } - - paddingInfo.pszAlgId = BCRYPT_SHA1_ALGORITHM; - memcpy(data, hash, datalen); ret = BCryptSignHash(rsa->hKey, &paddingInfo, @@ -1504,7 +1545,8 @@ _libssh2_wincng_dsa_sha1_verify(libssh2_dsa_ctx *dsa, const unsigned char *m, unsigned long m_len) { - return _libssh2_wincng_key_sha1_verify(dsa, sig_fixed, 40, m, m_len, 0); + return _libssh2_wincng_key_sha_verify(dsa, SHA_DIGEST_LENGTH, sig_fixed, + 40, m, m_len, 0); } int @@ -2604,8 +2646,13 @@ _libssh2_supported_key_sign_algorithms(LIBSSH2_SESSION *session, size_t key_method_len) { (void)session; - (void)key_method; - (void)key_method_len; + +#if LIBSSH2_RSA_SHA2 + if(key_method_len == 7 && + memcmp(key_method, "ssh-rsa", key_method_len) == 0) { + return "rsa-sha2-512,rsa-sha2-256,ssh-rsa"; + } +#endif return NULL; } diff --git a/src/wincng.h b/src/wincng.h index ea7554531a..a5f4506f8c 100644 --- a/src/wincng.h +++ b/src/wincng.h @@ -63,7 +63,7 @@ #define LIBSSH2_3DES 1 #define LIBSSH2_RSA 1 -#define LIBSSH2_RSA_SHA2 0 +#define LIBSSH2_RSA_SHA2 1 #define LIBSSH2_DSA 1 #define LIBSSH2_ECDSA 0 #define LIBSSH2_ED25519 0 @@ -262,9 +262,13 @@ typedef struct __libssh2_wincng_key_ctx { _libssh2_wincng_rsa_new_private_frommemory(rsactx, s, filedata, \ filedata_len, passphrase) #define _libssh2_rsa_sha1_sign(s, rsactx, hash, hash_len, sig, sig_len) \ - _libssh2_wincng_rsa_sha1_sign(s, rsactx, hash, hash_len, sig, sig_len) + _libssh2_wincng_rsa_sha_sign(s, rsactx, hash, hash_len, sig, sig_len) +#define _libssh2_rsa_sha2_sign(s, rsactx, hash, hash_len, sig, sig_len) \ + _libssh2_wincng_rsa_sha_sign(s, rsactx, hash, hash_len, sig, sig_len) #define _libssh2_rsa_sha1_verify(rsactx, sig, sig_len, m, m_len) \ _libssh2_wincng_rsa_sha1_verify(rsactx, sig, sig_len, m, m_len) +#define _libssh2_rsa_sha2_verify(rsactx, hash_len, sig, sig_len, m, m_len) \ + _libssh2_wincng_rsa_sha2_verify(rsactx, hash_len, sig, sig_len, m, m_len) #define _libssh2_rsa_free(rsactx) \ _libssh2_wincng_rsa_free(rsactx) @@ -450,7 +454,8 @@ void _libssh2_wincng_hmac_cleanup(_libssh2_wincng_hash_ctx *ctx); int -_libssh2_wincng_key_sha1_verify(_libssh2_wincng_key_ctx *ctx, +_libssh2_wincng_key_sha_verify(_libssh2_wincng_key_ctx *ctx, + size_t hashlen, const unsigned char *sig, unsigned long sig_len, const unsigned char *m, @@ -493,7 +498,7 @@ _libssh2_wincng_rsa_sha1_verify(libssh2_rsa_ctx *rsa, const unsigned char *m, unsigned long m_len); int -_libssh2_wincng_rsa_sha1_sign(LIBSSH2_SESSION *session, +_libssh2_wincng_rsa_sha_sign(LIBSSH2_SESSION *session, libssh2_rsa_ctx *rsa, const unsigned char *hash, size_t hash_len,