diff --git a/include/freerdp/crypto/crypto.h b/include/freerdp/crypto/crypto.h index 1be0149ae..257eb0098 100644 --- a/include/freerdp/crypto/crypto.h +++ b/include/freerdp/crypto/crypto.h @@ -22,6 +22,7 @@ /* OpenSSL includes windows.h */ #include +#include #include #include @@ -55,6 +56,7 @@ extern "C" FREERDP_API CryptoCert crypto_cert_read(const BYTE* data, UINT32 length); FREERDP_API CryptoCert crypto_cert_pem_read(const char* data); + FREERDP_API WINPR_MD_TYPE crypto_cert_get_signature_alg(X509* xcert); FREERDP_API BYTE* crypto_cert_hash(X509* xcert, const char* hash, UINT32* length); FREERDP_API char* crypto_cert_fingerprint_by_hash(X509* xcert, const char* hash); FREERDP_API char* crypto_cert_fingerprint_by_hash_ex(X509* xcert, const char* hash, diff --git a/libfreerdp/crypto/crypto.c b/libfreerdp/crypto/crypto.c index 9f96f6b0a..b4acc627a 100644 --- a/libfreerdp/crypto/crypto.c +++ b/libfreerdp/crypto/crypto.c @@ -17,9 +17,12 @@ * limitations under the License. */ +#include + #include #include +#include #include #include @@ -1168,3 +1171,51 @@ X509* crypto_cert_from_pem(const char* data, size_t len, BOOL fromFile) return x509; } + +WINPR_MD_TYPE crypto_cert_get_signature_alg(X509* xcert) +{ + WINPR_ASSERT(xcert); + + const int nid = X509_get_signature_nid(xcert); + + int hash_nid = 0; + if (OBJ_find_sigid_algs(nid, &hash_nid, NULL) != 1) + return WINPR_MD_NONE; + + switch (hash_nid) + { + case NID_md2: + return WINPR_MD_MD2; + case NID_md4: + return WINPR_MD_MD4; + case NID_md5: + return WINPR_MD_MD5; + case NID_sha1: + return WINPR_MD_SHA1; + case NID_sha224: + return WINPR_MD_SHA224; + case NID_sha256: + return WINPR_MD_SHA256; + case NID_sha384: + return WINPR_MD_SHA384; + case NID_sha512: + return WINPR_MD_SHA512; + case NID_ripemd160: + return WINPR_MD_RIPEMD160; + case NID_sha3_224: + return WINPR_MD_SHA3_224; + case NID_sha3_256: + return WINPR_MD_SHA3_256; + case NID_sha3_384: + return WINPR_MD_SHA3_384; + case NID_sha3_512: + return WINPR_MD_SHA3_512; + case NID_shake128: + return WINPR_MD_SHAKE128; + case NID_shake256: + return WINPR_MD_SHAKE256; + case NID_undef: + default: + return WINPR_MD_NONE; + } +} diff --git a/libfreerdp/crypto/tls.c b/libfreerdp/crypto/tls.c index aff6c888b..8b3901020 100644 --- a/libfreerdp/crypto/tls.c +++ b/libfreerdp/crypto/tls.c @@ -616,7 +616,25 @@ static SecPkgContext_Bindings* tls_get_channel_bindings(X509* cert) SEC_CHANNEL_BINDINGS* ChannelBindings; SecPkgContext_Bindings* ContextBindings; const size_t PrefixLength = strnlen(TLS_SERVER_END_POINT, ARRAYSIZE(TLS_SERVER_END_POINT)); - BYTE* CertificateHash = crypto_cert_hash(cert, "sha256", &CertificateHashLength); + + /* See https://www.rfc-editor.org/rfc/rfc5929 for details about hashes */ + WINPR_MD_TYPE alg = crypto_cert_get_signature_alg(cert); + const char* hash; + switch (alg) + { + + case WINPR_MD_MD5: + case WINPR_MD_SHA1: + hash = winpr_md_type_to_string(WINPR_MD_SHA256); + break; + default: + hash = winpr_md_type_to_string(alg); + break; + } + if (!hash) + return NULL; + + BYTE* CertificateHash = crypto_cert_hash(cert, hash, &CertificateHashLength); if (!CertificateHash) return NULL;