[PATCH v2] crypt32/tests: Add a test to verify certificate signature.

Dmitry Timoshkov dmitry at baikal.ru
Wed Apr 14 03:59:14 CDT 2021


v2: Move the tests to crypt32.

Signed-off-by: Dmitry Timoshkov <dmitry at 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();
 }
-- 
2.31.1




More information about the wine-devel mailing list