Dmitry Timoshkov : crypt32/tests: Add a test to verify certificate signature.
Alexandre Julliard
julliard at winehq.org
Wed Apr 14 16:01:19 CDT 2021
Module: wine
Branch: master
Commit: 8601953ebd175db598b9c4aa1589344ef24a786e
URL: https://source.winehq.org/git/wine.git/?a=commit;h=8601953ebd175db598b9c4aa1589344ef24a786e
Author: Dmitry Timoshkov <dmitry at baikal.ru>
Date: Wed Apr 14 13:14:51 2021 +0300
crypt32/tests: Add a test to verify certificate signature.
Signed-off-by: Dmitry Timoshkov <dmitry at baikal.ru>
Signed-off-by: Hans Leidekker <hans at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>
---
dlls/crypt32/tests/Makefile.in | 2 +-
dlls/crypt32/tests/cert.c | 95 +++++++++++++++++++++++++++++++++++++++++-
2 files changed, 95 insertions(+), 2 deletions(-)
diff --git a/dlls/crypt32/tests/Makefile.in b/dlls/crypt32/tests/Makefile.in
index d96ad1cd6f1..339cff30e0f 100644
--- a/dlls/crypt32/tests/Makefile.in
+++ b/dlls/crypt32/tests/Makefile.in
@@ -1,5 +1,5 @@
TESTDLL = crypt32.dll
-IMPORTS = crypt32 advapi32 user32 shlwapi shell32
+IMPORTS = crypt32 advapi32 user32 shlwapi shell32 bcrypt
C_SRCS = \
base64.c \
diff --git a/dlls/crypt32/tests/cert.c b/dlls/crypt32/tests/cert.c
index 745770f0095..15ed98e0e30 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"
@@ -60,7 +61,6 @@ static void init_function_pointers(void)
GET_PROC(hCrypt32, CryptVerifyCertificateSignatureEx)
GET_PROC(hAdvapi32, CryptAcquireContextA)
-
#undef GET_PROC
}
@@ -4237,6 +4237,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 = BCryptOpenAlgorithmProvider(&alg, BCRYPT_SHA1_ALGORITHM, MS_PRIMITIVE_PROVIDER, 0);
+ ok(!status, "got %#x\n", status);
+
+ status = BCryptCreateHash(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 = BCryptHashData(bhash, info->ToBeSigned.pbData, info->ToBeSigned.cbData, 0);
+ ok(!status, "got %#x\n", status);
+
+ status = BCryptFinishHash(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 = BCryptGetProperty(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 = BCryptVerifySignature(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);
+ BCryptDestroyHash(bhash);
+done:
+ BCryptCloseAlgorithmProvider(alg, 0);
+
+ LocalFree(info);
+ CertFreeCertificateContext(cert);
+}
+
START_TEST(cert)
{
init_function_pointers();
@@ -4270,4 +4362,5 @@ START_TEST(cert)
testAcquireCertPrivateKey();
testGetPublicKeyLength();
testIsRDNAttrsInCertificateName();
+ test_VerifySignature();
}
More information about the wine-cvs
mailing list