In case the default provider does not support an algorithm, other providers are iterated and a different provider is returned that should be released.
The default provider itself is also destroyed in DllMain if we always properly release it.
Signed-off-by: Sven Baars sbaars@codeweavers.com --- I'm not sure if this is useful in practice and if it's worth the bookkeeping.
dlls/crypt32/cert.c | 58 +++++++++++++++++++++++++++++++++------------ dlls/crypt32/msg.c | 8 +++---- 2 files changed, 47 insertions(+), 19 deletions(-)
diff --git a/dlls/crypt32/cert.c b/dlls/crypt32/cert.c index 687b60bac54..584a47e9163 100644 --- a/dlls/crypt32/cert.c +++ b/dlls/crypt32/cert.c @@ -1395,11 +1395,15 @@ DWORD WINAPI CertGetPublicKeyLength(DWORD dwCertEncodingType, info = CryptFindOIDInfo(CRYPT_OID_INFO_OID_KEY, pPublicKey->Algorithm.pszObjId, 0); if (info) { + HCRYPTPROV prov; HCRYPTKEY key;
TRACE("public key algid %#x (%s)\n", info->u.Algid, debugstr_a(pPublicKey->Algorithm.pszObjId));
- ret = CryptImportPublicKeyInfo(I_CryptGetDefaultCryptProv(info->u.Algid), dwCertEncodingType, pPublicKey, &key); + prov = I_CryptGetDefaultCryptProv(info->u.Algid); + ret = CryptImportPublicKeyInfo(prov, dwCertEncodingType, pPublicKey, &key); + CryptReleaseContext(prov, 0); + if (ret) { size = sizeof(len); @@ -2249,8 +2253,9 @@ BOOL WINAPI CryptHashCertificate(HCRYPTPROV_LEGACY hCryptProv, ALG_ID Algid, DWORD dwFlags, const BYTE *pbEncoded, DWORD cbEncoded, BYTE *pbComputedHash, DWORD *pcbComputedHash) { - BOOL ret; + HCRYPTPROV prov = hCryptProv; HCRYPTHASH hHash = 0; + BOOL ret;
TRACE("(%08Ix, %d, %08lx, %p, %ld, %p, %p)\n", hCryptProv, Algid, dwFlags, pbEncoded, cbEncoded, pbComputedHash, pcbComputedHash); @@ -2259,9 +2264,9 @@ BOOL WINAPI CryptHashCertificate(HCRYPTPROV_LEGACY hCryptProv, ALG_ID Algid, Algid = CALG_SHA1;
if (!hCryptProv) - hCryptProv = I_CryptGetDefaultCryptProv(Algid); + prov = I_CryptGetDefaultCryptProv(Algid);
- ret = CryptCreateHash(hCryptProv, Algid, 0, 0, &hHash); + ret = CryptCreateHash(prov, Algid, 0, 0, &hHash); if (ret) { ret = CryptHashData(hHash, pbEncoded, cbEncoded, 0); @@ -2270,6 +2275,10 @@ BOOL WINAPI CryptHashCertificate(HCRYPTPROV_LEGACY hCryptProv, ALG_ID Algid, pcbComputedHash, 0); CryptDestroyHash(hHash); } + + if (!hCryptProv) + CryptReleaseContext(prov, 0); + return ret; }
@@ -2330,6 +2339,7 @@ BOOL WINAPI CryptHashPublicKeyInfo(HCRYPTPROV_LEGACY hCryptProv, ALG_ID Algid, DWORD dwFlags, DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pInfo, BYTE *pbComputedHash, DWORD *pcbComputedHash) { + HCRYPTPROV prov = hCryptProv; HCRYPTHASH hHash = 0; DWORD size = 0; BYTE *buf; @@ -2341,9 +2351,6 @@ BOOL WINAPI CryptHashPublicKeyInfo(HCRYPTPROV_LEGACY hCryptProv, ALG_ID Algid, if (!Algid) Algid = CALG_MD5;
- if (!hCryptProv) - hCryptProv = I_CryptGetDefaultCryptProv(Algid); - if ((dwCertEncodingType & CERT_ENCODING_TYPE_MASK) != X509_ASN_ENCODING) { SetLastError(ERROR_FILE_NOT_FOUND); @@ -2355,7 +2362,10 @@ BOOL WINAPI CryptHashPublicKeyInfo(HCRYPTPROV_LEGACY hCryptProv, ALG_ID Algid, (LPBYTE)&buf, &size); if (ret) { - ret = CryptCreateHash(hCryptProv, Algid, 0, 0, &hHash); + if (!hCryptProv) + prov = I_CryptGetDefaultCryptProv(Algid); + + ret = CryptCreateHash(prov, Algid, 0, 0, &hHash); if (ret) { ret = CryptHashData(hHash, buf, size, 0); @@ -2365,6 +2375,9 @@ BOOL WINAPI CryptHashPublicKeyInfo(HCRYPTPROV_LEGACY hCryptProv, ALG_ID Algid, CryptDestroyHash(hHash); } LocalFree(buf); + + if (!hCryptProv) + CryptReleaseContext(prov, 0); } return ret; } @@ -2373,6 +2386,7 @@ BOOL WINAPI CryptHashToBeSigned(HCRYPTPROV_LEGACY hCryptProv, DWORD dwCertEncodingType, const BYTE *pbEncoded, DWORD cbEncoded, BYTE *pbComputedHash, DWORD *pcbComputedHash) { + HCRYPTPROV prov = hCryptProv; BOOL ret; CERT_SIGNED_CONTENT_INFO *info; DWORD size; @@ -2397,9 +2411,9 @@ BOOL WINAPI CryptHashToBeSigned(HCRYPTPROV_LEGACY hCryptProv, else { if (!hCryptProv) - hCryptProv = I_CryptGetDefaultCryptProv(oidInfo->u.Algid); + prov = I_CryptGetDefaultCryptProv(oidInfo->u.Algid);
- ret = CryptCreateHash(hCryptProv, oidInfo->u.Algid, 0, 0, &hHash); + ret = CryptCreateHash(prov, oidInfo->u.Algid, 0, 0, &hHash); if (ret) { ret = CryptHashData(hHash, info->ToBeSigned.pbData, @@ -2409,6 +2423,9 @@ BOOL WINAPI CryptHashToBeSigned(HCRYPTPROV_LEGACY hCryptProv, pcbComputedHash, 0); CryptDestroyHash(hHash); } + + if (!hCryptProv) + CryptReleaseContext(prov, 0); } LocalFree(info); } @@ -2420,6 +2437,7 @@ BOOL WINAPI CryptSignCertificate(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv, DWORD cbEncodedToBeSigned, PCRYPT_ALGORITHM_IDENTIFIER pSignatureAlgorithm, const void *pvHashAuxInfo, BYTE *pbSignature, DWORD *pcbSignature) { + HCRYPTPROV prov = hCryptProv; BOOL ret; PCCRYPT_OID_INFO info; HCRYPTHASH hHash; @@ -2438,9 +2456,9 @@ BOOL WINAPI CryptSignCertificate(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv, if (info->dwGroupId == CRYPT_HASH_ALG_OID_GROUP_ID) { if (!hCryptProv) - hCryptProv = I_CryptGetDefaultCryptProv(info->u.Algid); + prov = I_CryptGetDefaultCryptProv(info->u.Algid);
- ret = CryptCreateHash(hCryptProv, info->u.Algid, 0, 0, &hHash); + ret = CryptCreateHash(prov, info->u.Algid, 0, 0, &hHash); if (ret) { ret = CryptHashData(hHash, pbEncodedToBeSigned, @@ -2450,6 +2468,9 @@ BOOL WINAPI CryptSignCertificate(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv, pcbSignature, 0); CryptDestroyHash(hHash); } + + if (!hCryptProv) + CryptReleaseContext(prov, 0); } else { @@ -2552,6 +2573,7 @@ BOOL WINAPI CryptVerifyCertificateSignature(HCRYPTPROV_LEGACY hCryptProv, static BOOL CRYPT_VerifySignature(HCRYPTPROV_LEGACY hCryptProv, DWORD dwCertEncodingType, CERT_PUBLIC_KEY_INFO *pubKeyInfo, const CERT_SIGNED_CONTENT_INFO *signedCert, const CRYPT_OID_INFO *info) { + HCRYPTPROV prov = hCryptProv; BOOL ret; HCRYPTKEY key; ALG_ID pubKeyID, hashID; @@ -2561,16 +2583,18 @@ static BOOL CRYPT_VerifySignature(HCRYPTPROV_LEGACY hCryptProv, DWORD dwCertEnco pubKeyID = *(ALG_ID *)info->ExtraInfo.pbData; else pubKeyID = hashID; + /* Load the default provider if necessary */ if (!hCryptProv) - hCryptProv = I_CryptGetDefaultCryptProv(hashID); - ret = CryptImportPublicKeyInfoEx(hCryptProv, dwCertEncodingType, + prov = I_CryptGetDefaultCryptProv(hashID); + + ret = CryptImportPublicKeyInfoEx(prov, dwCertEncodingType, pubKeyInfo, pubKeyID, 0, NULL, &key); if (ret) { HCRYPTHASH hash;
- ret = CryptCreateHash(hCryptProv, hashID, 0, 0, &hash); + ret = CryptCreateHash(prov, hashID, 0, 0, &hash); if (ret) { ret = CryptHashData(hash, signedCert->ToBeSigned.pbData, @@ -2582,6 +2606,10 @@ static BOOL CRYPT_VerifySignature(HCRYPTPROV_LEGACY hCryptProv, DWORD dwCertEnco } CryptDestroyKey(key); } + + if (!hCryptProv) + CryptReleaseContext(prov, 0); + return ret; }
diff --git a/dlls/crypt32/msg.c b/dlls/crypt32/msg.c index 6087f423f8c..d148252e05c 100644 --- a/dlls/crypt32/msg.c +++ b/dlls/crypt32/msg.c @@ -570,7 +570,7 @@ static HCRYPTMSG CHashEncodeMsg_Open(DWORD dwFlags, const void *pvMsgEncodeInfo, SetLastError(E_INVALIDARG); return NULL; } - dwFlags &= ~CMSG_CRYPT_RELEASE_CONTEXT_FLAG; + dwFlags |= CMSG_CRYPT_RELEASE_CONTEXT_FLAG; } msg = CryptMemAlloc(sizeof(CHashEncodeMsg)); if (msg) @@ -935,7 +935,7 @@ static BOOL CSignedMsgData_ConstructSignerHandles(CSignedMsgData *msg_data, { *crypt_prov = I_CryptGetDefaultCryptProv(algID); if (!*crypt_prov) return FALSE; - *flags &= ~CMSG_CRYPT_RELEASE_CONTEXT_FLAG; + *flags |= CMSG_CRYPT_RELEASE_CONTEXT_FLAG; }
ret = CryptCreateHash(*crypt_prov, algID, 0, 0, @@ -1975,7 +1975,7 @@ static HCRYPTMSG CEnvelopedEncodeMsg_Open(DWORD dwFlags, else { prov = I_CryptGetDefaultCryptProv(0); - dwFlags &= ~CMSG_CRYPT_RELEASE_CONTEXT_FLAG; + dwFlags |= CMSG_CRYPT_RELEASE_CONTEXT_FLAG; } msg = CryptMemAlloc(sizeof(CEnvelopedEncodeMsg)); if (msg) @@ -2352,7 +2352,7 @@ static BOOL CDecodeMsg_FinalizeHashedContent(CDecodeMsg *msg, { msg->crypt_prov = I_CryptGetDefaultCryptProv(algID); if (msg->crypt_prov) - msg->base.open_flags &= ~CMSG_CRYPT_RELEASE_CONTEXT_FLAG; + msg->base.open_flags |= CMSG_CRYPT_RELEASE_CONTEXT_FLAG; }
ret = CryptCreateHash(msg->crypt_prov, algID, 0, 0, &msg->u.hash);