v2: Move the tests to crypt32.
Signed-off-by: Dmitry Timoshkov dmitry@baikal.ru --- dlls/crypt32/tests/cert.c | 116 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 116 insertions(+)
diff --git a/dlls/crypt32/tests/cert.c b/dlls/crypt32/tests/cert.c index 745770f0095..3f50fad482c 100644 --- a/dlls/crypt32/tests/cert.c +++ b/dlls/crypt32/tests/cert.c @@ -28,6 +28,7 @@ #include <winreg.h> #include <winerror.h> #include <wincrypt.h> +#include <bcrypt.h>
#include "wine/test.h"
@@ -42,10 +43,22 @@ static BOOL (WINAPI * pCryptVerifyCertificateSignatureEx) static BOOL (WINAPI * pCryptAcquireContextA) (HCRYPTPROV *, LPCSTR, LPCSTR, DWORD, DWORD);
+static NTSTATUS (WINAPI *pBCryptCloseAlgorithmProvider)(BCRYPT_ALG_HANDLE, ULONG); +static NTSTATUS (WINAPI *pBCryptCreateHash)(BCRYPT_ALG_HANDLE, BCRYPT_HASH_HANDLE *, PUCHAR, ULONG, PUCHAR, + ULONG, ULONG); +static NTSTATUS (WINAPI *pBCryptDestroyHash)(BCRYPT_HASH_HANDLE); +static NTSTATUS (WINAPI *pBCryptDestroyKey)(BCRYPT_KEY_HANDLE); +static NTSTATUS (WINAPI *pBCryptFinishHash)(BCRYPT_HASH_HANDLE, PUCHAR, ULONG, ULONG); +static NTSTATUS (WINAPI *pBCryptHashData)(BCRYPT_HASH_HANDLE, PUCHAR, ULONG, ULONG); +static NTSTATUS (WINAPI *pBCryptGetProperty)(BCRYPT_HANDLE, LPCWSTR, PUCHAR, ULONG, ULONG *, ULONG); +static NTSTATUS (WINAPI *pBCryptOpenAlgorithmProvider)(BCRYPT_ALG_HANDLE *, LPCWSTR, LPCWSTR, ULONG); +static NTSTATUS (WINAPI *pBCryptVerifySignature)(BCRYPT_KEY_HANDLE, VOID *, UCHAR *, ULONG, UCHAR *, ULONG, ULONG); + static void init_function_pointers(void) { HMODULE hCrypt32 = GetModuleHandleA("crypt32.dll"); HMODULE hAdvapi32 = GetModuleHandleA("advapi32.dll"); + HMODULE hBcrypt = LoadLibraryA("bcrypt.dll");
#define GET_PROC(dll, func) \ p ## func = (void *)GetProcAddress(dll, #func); \ @@ -61,6 +74,16 @@ static void init_function_pointers(void)
GET_PROC(hAdvapi32, CryptAcquireContextA)
+ GET_PROC(hBcrypt, BCryptCloseAlgorithmProvider) + GET_PROC(hBcrypt, BCryptCreateHash) + GET_PROC(hBcrypt, BCryptDestroyHash) + GET_PROC(hBcrypt, BCryptDestroyKey) + GET_PROC(hBcrypt, BCryptFinishHash) + GET_PROC(hBcrypt, BCryptHashData) + GET_PROC(hBcrypt, BCryptGetProperty) + GET_PROC(hBcrypt, BCryptOpenAlgorithmProvider) + GET_PROC(hBcrypt, BCryptVerifySignature) + #undef GET_PROC }
@@ -4237,6 +4260,98 @@ static void testKeyProvInfo(void) CertCloseStore(store, 0); }
+static void test_VerifySignature(void) +{ + PCCERT_CONTEXT cert; + PCERT_SIGNED_CONTENT_INFO info; + DWORD size; + BOOL ret; + HCRYPTPROV prov; + HCRYPTKEY key; + HCRYPTHASH hash; + BYTE hash_value[20], *sig_value; + DWORD hash_len, i; + BCRYPT_KEY_HANDLE bkey; + BCRYPT_HASH_HANDLE bhash; + BCRYPT_ALG_HANDLE alg; + BCRYPT_PKCS1_PADDING_INFO pad; + NTSTATUS status; + + cert = CertCreateCertificateContext(X509_ASN_ENCODING, selfSignedCert, sizeof(selfSignedCert)); + ok(cert != NULL, "CertCreateCertificateContext error %#x\n", GetLastError()); + + /* 1. Verify certificate signature with Crypto API */ + ret = CryptVerifyCertificateSignature(0, cert->dwCertEncodingType, + cert->pbCertEncoded, cert->cbCertEncoded, &cert->pCertInfo->SubjectPublicKeyInfo); + ok(ret, "CryptVerifyCertificateSignature error %#x\n", GetLastError()); + + /* 2. Verify certificate signature with Crypto API manually */ + ret = pCryptAcquireContextA(&prov, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT); + ok(ret, "CryptAcquireContext error %#x\n", GetLastError()); + + ret = CryptImportPublicKeyInfoEx(prov, cert->dwCertEncodingType, &cert->pCertInfo->SubjectPublicKeyInfo, 0, 0, NULL, &key); + ok(ret, "CryptImportPublicKeyInfoEx error %#x\n", GetLastError()); + + ret = CryptDecodeObjectEx(cert->dwCertEncodingType, X509_CERT, + cert->pbCertEncoded, cert->cbCertEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size); + ok(ret, "CryptDecodeObjectEx error %#x\n", GetLastError()); + + ret = CryptCreateHash(prov, CALG_SHA1, 0, 0, &hash); + ok(ret, "CryptCreateHash error %#x\n", GetLastError()); + + ret = CryptHashData(hash, info->ToBeSigned.pbData, info->ToBeSigned.cbData, 0); + ok(ret, "CryptHashData error %#x\n", GetLastError()); + + ret = CryptVerifySignatureW(hash, info->Signature.pbData, info->Signature.cbData, key, NULL, 0); + ok(ret, "CryptVerifySignature error %#x\n", GetLastError()); + + CryptDestroyHash(hash); + CryptDestroyKey(key); + CryptReleaseContext(prov, 0); + + /* 3. Verify certificate signature with CNG */ + ret = CryptImportPublicKeyInfoEx2(cert->dwCertEncodingType, &cert->pCertInfo->SubjectPublicKeyInfo, 0, NULL, &bkey); + ok(ret, "CryptImportPublicKeyInfoEx error %#x\n", GetLastError()); + + status = pBCryptOpenAlgorithmProvider(&alg, BCRYPT_SHA1_ALGORITHM, MS_PRIMITIVE_PROVIDER, 0); + ok(!status, "got %#x\n", status); + + status = pBCryptCreateHash(alg, &bhash, NULL, 0, NULL, 0, 0); + ok(!status || broken(status == STATUS_INVALID_PARAMETER) /* Vista */, "got %#x\n", status); + if (status == STATUS_INVALID_PARAMETER) + { + win_skip("broken BCryptCreateHash\n"); + goto done; + } + + status = pBCryptHashData(bhash, info->ToBeSigned.pbData, info->ToBeSigned.cbData, 0); + ok(!status, "got %#x\n", status); + + status = pBCryptFinishHash(bhash, hash_value, sizeof(hash_value), 0); + ok(!status, "got %#x\n", status); + ok(!memcmp(hash_value, selfSignedSignatureHash, sizeof(hash_value)), "got wrong hash value\n"); + + status = pBCryptGetProperty(bhash, BCRYPT_HASH_LENGTH, (BYTE *)&hash_len, sizeof(hash_len), &size, 0); + ok(!status, "got %#x\n", status); + ok(hash_len == sizeof(hash_value), "got %u\n", hash_len); + + sig_value = HeapAlloc(GetProcessHeap(), 0, info->Signature.cbData); + for (i = 0; i < info->Signature.cbData; i++) + sig_value[i] = info->Signature.pbData[info->Signature.cbData - i - 1]; + + pad.pszAlgId = BCRYPT_SHA1_ALGORITHM; + status = pBCryptVerifySignature(bkey, &pad, hash_value, sizeof(hash_value), sig_value, info->Signature.cbData, BCRYPT_PAD_PKCS1); + ok(!status, "got %#x\n", status); + + HeapFree(GetProcessHeap(), 0, sig_value); + pBCryptDestroyHash(bhash); +done: + pBCryptCloseAlgorithmProvider(alg, 0); + + LocalFree(info); + CertFreeCertificateContext(cert); +} + START_TEST(cert) { init_function_pointers(); @@ -4270,4 +4385,5 @@ START_TEST(cert) testAcquireCertPrivateKey(); testGetPublicKeyLength(); testIsRDNAttrsInCertificateName(); + test_VerifySignature(); }
On Wed, 2021-04-14 at 11:59 +0300, Dmitry Timoshkov wrote:
+static NTSTATUS (WINAPI *pBCryptCloseAlgorithmProvider)(BCRYPT_ALG_HANDLE, ULONG); +static NTSTATUS (WINAPI *pBCryptCreateHash)(BCRYPT_ALG_HANDLE, BCRYPT_HASH_HANDLE *, PUCHAR, ULONG, PUCHAR,
ULONG, ULONG);
+static NTSTATUS (WINAPI *pBCryptDestroyHash)(BCRYPT_HASH_HANDLE); +static NTSTATUS (WINAPI *pBCryptDestroyKey)(BCRYPT_KEY_HANDLE); +static NTSTATUS (WINAPI *pBCryptFinishHash)(BCRYPT_HASH_HANDLE, PUCHAR, ULONG, ULONG); +static NTSTATUS (WINAPI *pBCryptHashData)(BCRYPT_HASH_HANDLE, PUCHAR, ULONG, ULONG); +static NTSTATUS (WINAPI *pBCryptGetProperty)(BCRYPT_HANDLE, LPCWSTR, PUCHAR, ULONG, ULONG *, ULONG); +static NTSTATUS (WINAPI *pBCryptOpenAlgorithmProvider)(BCRYPT_ALG_HANDLE *, LPCWSTR, LPCWSTR, ULONG); +static NTSTATUS (WINAPI *pBCryptVerifySignature)(BCRYPT_KEY_HANDLE, VOID *, UCHAR *, ULONG, UCHAR *, ULONG, ULONG)
Do we need to load these dynamically? It looks like they're all supported since Vista.
Hans Leidekker hans@codeweavers.com wrote:
On Wed, 2021-04-14 at 11:59 +0300, Dmitry Timoshkov wrote:
+static NTSTATUS (WINAPI *pBCryptCloseAlgorithmProvider)(BCRYPT_ALG_HANDLE, ULONG); +static NTSTATUS (WINAPI *pBCryptCreateHash)(BCRYPT_ALG_HANDLE, BCRYPT_HASH_HANDLE *, PUCHAR, ULONG, PUCHAR,
ULONG, ULONG);
+static NTSTATUS (WINAPI *pBCryptDestroyHash)(BCRYPT_HASH_HANDLE); +static NTSTATUS (WINAPI *pBCryptDestroyKey)(BCRYPT_KEY_HANDLE); +static NTSTATUS (WINAPI *pBCryptFinishHash)(BCRYPT_HASH_HANDLE, PUCHAR, ULONG, ULONG); +static NTSTATUS (WINAPI *pBCryptHashData)(BCRYPT_HASH_HANDLE, PUCHAR, ULONG, ULONG); +static NTSTATUS (WINAPI *pBCryptGetProperty)(BCRYPT_HANDLE, LPCWSTR, PUCHAR, ULONG, ULONG *, ULONG); +static NTSTATUS (WINAPI *pBCryptOpenAlgorithmProvider)(BCRYPT_ALG_HANDLE *, LPCWSTR, LPCWSTR, ULONG); +static NTSTATUS (WINAPI *pBCryptVerifySignature)(BCRYPT_KEY_HANDLE, VOID *, UCHAR *, ULONG, UCHAR *, ULONG, ULONG)
Do we need to load these dynamically? It looks like they're all supported since Vista.
I just decided to follow what bcrypt tests are doing. If that's preferrable - I can cetainly remove the dynamic linking.
On Wed, 2021-04-14 at 12:24 +0300, Dmitry Timoshkov wrote:
Hans Leidekker hans@codeweavers.com wrote:
On Wed, 2021-04-14 at 11:59 +0300, Dmitry Timoshkov wrote:
+static NTSTATUS (WINAPI *pBCryptCloseAlgorithmProvider)(BCRYPT_ALG_HANDLE, ULONG); +static NTSTATUS (WINAPI *pBCryptCreateHash)(BCRYPT_ALG_HANDLE, BCRYPT_HASH_HANDLE *, PUCHAR, ULONG, PUCHAR,
ULONG, ULONG);
+static NTSTATUS (WINAPI *pBCryptDestroyHash)(BCRYPT_HASH_HANDLE); +static NTSTATUS (WINAPI *pBCryptDestroyKey)(BCRYPT_KEY_HANDLE); +static NTSTATUS (WINAPI *pBCryptFinishHash)(BCRYPT_HASH_HANDLE, PUCHAR, ULONG, ULONG); +static NTSTATUS (WINAPI *pBCryptHashData)(BCRYPT_HASH_HANDLE, PUCHAR, ULONG, ULONG); +static NTSTATUS (WINAPI *pBCryptGetProperty)(BCRYPT_HANDLE, LPCWSTR, PUCHAR, ULONG, ULONG *, ULONG); +static NTSTATUS (WINAPI *pBCryptOpenAlgorithmProvider)(BCRYPT_ALG_HANDLE *, LPCWSTR, LPCWSTR, ULONG); +static NTSTATUS (WINAPI *pBCryptVerifySignature)(BCRYPT_KEY_HANDLE, VOID *, UCHAR *, ULONG, UCHAR *, ULONG, ULONG)
Do we need to load these dynamically? It looks like they're all supported since Vista.
I just decided to follow what bcrypt tests are doing. If that's preferrable - I can cetainly remove the dynamic linking.
I believe the bcrypt tests do that mostly for historical reasons (it does use one or two exports that were added after Vista). Here there's no need for dynamic linking it seems.