Module: wine Branch: master Commit: 650fe1fd789fd6b72b14eaf9c08a30d6c40f8def URL: https://gitlab.winehq.org/wine/wine/-/commit/650fe1fd789fd6b72b14eaf9c08a30d...
Author: Paul Gofman pgofman@codeweavers.com Date: Thu Jun 29 12:39:33 2023 -0600
crypt32: Support CNG keys in CDecodeSignedMsg_VerifySignatureWithKey().
---
dlls/crypt32/cert.c | 2 +- dlls/crypt32/crypt32_private.h | 2 ++ dlls/crypt32/msg.c | 42 +++++++++++++++++++++++++++++++++++++----- dlls/crypt32/tests/msg.c | 4 ++-- 4 files changed, 42 insertions(+), 8 deletions(-)
diff --git a/dlls/crypt32/cert.c b/dlls/crypt32/cert.c index 0005d5db14a..a6fefb30b05 100644 --- a/dlls/crypt32/cert.c +++ b/dlls/crypt32/cert.c @@ -2810,7 +2810,7 @@ static BOOL CNG_PrepareSignatureECC(BYTE *encoded_sig, DWORD encoded_size, BYTE return TRUE; }
-static BOOL cng_prepare_signature(const char *alg_oid, BYTE *encoded_sig, DWORD encoded_sig_len, +BOOL cng_prepare_signature(const char *alg_oid, BYTE *encoded_sig, DWORD encoded_sig_len, BYTE **sig_value, DWORD *sig_len) { if (!strcmp(alg_oid, szOID_ECC_PUBLIC_KEY)) diff --git a/dlls/crypt32/crypt32_private.h b/dlls/crypt32/crypt32_private.h index d61fcfb7d6e..b5beb1b8a0e 100644 --- a/dlls/crypt32/crypt32_private.h +++ b/dlls/crypt32/crypt32_private.h @@ -23,6 +23,8 @@ #include "wine/unixlib.h"
BOOL CNG_ImportPubKey(CERT_PUBLIC_KEY_INFO *pubKeyInfo, BCRYPT_KEY_HANDLE *key) DECLSPEC_HIDDEN; +BOOL cng_prepare_signature(const char *alg_oid, BYTE *encoded_sig, DWORD encoded_sig_len, + BYTE **sig_value, DWORD *sig_len) DECLSPEC_HIDDEN;
/* a few asn.1 tags we need */ #define ASN_BOOL (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x01) diff --git a/dlls/crypt32/msg.c b/dlls/crypt32/msg.c index de5730bc064..94642ecfce2 100644 --- a/dlls/crypt32/msg.c +++ b/dlls/crypt32/msg.c @@ -3316,24 +3316,56 @@ static BOOL CDecodeHashMsg_VerifyHash(CDecodeMsg *msg) return ret; }
+static BOOL cng_verify_msg_signature(CMSG_CMS_SIGNER_INFO *signer, HCRYPTHASH hash, CERT_PUBLIC_KEY_INFO *key_info) +{ + BYTE *hash_value, *sig_value = NULL; + DWORD hash_len, sig_len; + BCRYPT_KEY_HANDLE key; + BOOL ret = FALSE; + NTSTATUS status; + + if (!CryptImportPublicKeyInfoEx2(X509_ASN_ENCODING, key_info, 0, NULL, &key)) return FALSE; + if (!extract_hash(hash, &hash_value, &hash_len)) goto done; + if (!cng_prepare_signature(key_info->Algorithm.pszObjId, signer->EncryptedHash.pbData, + signer->EncryptedHash.cbData, &sig_value, &sig_len)) goto done; + status = BCryptVerifySignature(key, NULL, hash_value, hash_len, sig_value, sig_len, 0); + if (status) + { + FIXME("Failed to verify signature: %08lx.\n", status); + SetLastError(RtlNtStatusToDosError(status)); + } + ret = !status; +done: + CryptMemFree(sig_value); + CryptMemFree(hash_value); + BCryptDestroyKey(key); + return ret; +} + static BOOL CDecodeSignedMsg_VerifySignatureWithKey(CDecodeMsg *msg, HCRYPTPROV prov, DWORD signerIndex, PCERT_PUBLIC_KEY_INFO keyInfo) { + HCRYPTHASH hash; HCRYPTKEY key; BOOL ret; + ALG_ID alg_id = 0; + + if (msg->u.signed_data.info->rgSignerInfo[signerIndex].AuthAttrs.cAttr) + hash = msg->u.signed_data.signerHandles[signerIndex].authAttrHash; + else + hash = msg->u.signed_data.signerHandles[signerIndex].contentHash; + + if (keyInfo->Algorithm.pszObjId) alg_id = CertOIDToAlgId(keyInfo->Algorithm.pszObjId); + if (alg_id == CALG_OID_INFO_PARAMETERS || alg_id == CALG_OID_INFO_CNG_ONLY) + return cng_verify_msg_signature(&msg->u.signed_data.info->rgSignerInfo[signerIndex], hash, keyInfo);
if (!prov) prov = msg->crypt_prov; ret = CryptImportPublicKeyInfo(prov, X509_ASN_ENCODING, keyInfo, &key); if (ret) { - HCRYPTHASH hash; CRYPT_HASH_BLOB reversedHash;
- if (msg->u.signed_data.info->rgSignerInfo[signerIndex].AuthAttrs.cAttr) - hash = msg->u.signed_data.signerHandles[signerIndex].authAttrHash; - else - hash = msg->u.signed_data.signerHandles[signerIndex].contentHash; ret = CRYPT_ConstructBlob(&reversedHash, &msg->u.signed_data.info->rgSignerInfo[signerIndex].EncryptedHash); if (ret) diff --git a/dlls/crypt32/tests/msg.c b/dlls/crypt32/tests/msg.c index c663909ed7c..d8ac7f75d78 100644 --- a/dlls/crypt32/tests/msg.c +++ b/dlls/crypt32/tests/msg.c @@ -3608,12 +3608,12 @@ static void test_verify_ecc_signature(void) BCryptDestroyKey(bkey);
bret = CryptMsgControl(msg, 0, CMSG_CTRL_VERIFY_SIGNATURE, cert->pCertInfo); - todo_wine ok(bret, "failed, error %#lx.\n", GetLastError()); + ok(bret, "failed, error %#lx.\n", GetLastError());
verify_para.dwSignerType = CMSG_VERIFY_SIGNER_CERT; verify_para.pvSigner = (void *)cert; bret = CryptMsgControl(msg, 0, CMSG_CTRL_VERIFY_SIGNATURE_EX, &verify_para); - todo_wine ok(bret, "failed, error %#lx.\n", GetLastError()); + ok(bret, "failed, error %#lx.\n", GetLastError());
free(signer_info); free(cert_info);