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

Dmitry Timoshkov dmitry at baikal.ru
Tue Apr 13 13:28:02 CDT 2021


Signed-off-by: Dmitry Timoshkov <dmitry at baikal.ru>
---
 dlls/bcrypt/tests/Makefile.in |   2 +-
 dlls/bcrypt/tests/bcrypt.c    | 121 ++++++++++++++++++++++++++++++++++
 2 files changed, 122 insertions(+), 1 deletion(-)

diff --git a/dlls/bcrypt/tests/Makefile.in b/dlls/bcrypt/tests/Makefile.in
index 1bf7d2c48f1..b0f3e57f3ed 100644
--- a/dlls/bcrypt/tests/Makefile.in
+++ b/dlls/bcrypt/tests/Makefile.in
@@ -1,5 +1,5 @@
 TESTDLL  = bcrypt.dll
-IMPORTS  = bcrypt user32 advapi32
+IMPORTS  = bcrypt user32 advapi32 crypt32
 
 C_SRCS = \
 	bcrypt.c
diff --git a/dlls/bcrypt/tests/bcrypt.c b/dlls/bcrypt/tests/bcrypt.c
index 456727d04a9..58fc52f55c6 100644
--- a/dlls/bcrypt/tests/bcrypt.c
+++ b/dlls/bcrypt/tests/bcrypt.c
@@ -24,6 +24,7 @@
 #include <windows.h>
 #include <bcrypt.h>
 #include <ncrypt.h>
+#include <wincrypt.h>
 
 #include "wine/test.h"
 
@@ -2741,6 +2742,125 @@ static void test_SecretAgreement(void)
     ok(status == STATUS_SUCCESS, "got %08x\n", status);
 }
 
+/* Copied from dlls/crypt32/tests/cert.c */
+static const BYTE selfSignedCert[] = {
+ 0x30, 0x82, 0x01, 0x1f, 0x30, 0x81, 0xce, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02,
+ 0x10, 0xeb, 0x0d, 0x57, 0x2a, 0x9c, 0x09, 0xba, 0xa4, 0x4a, 0xb7, 0x25, 0x49,
+ 0xd9, 0x3e, 0xb5, 0x73, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1d,
+ 0x05, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03,
+ 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30,
+ 0x1e, 0x17, 0x0d, 0x30, 0x36, 0x30, 0x36, 0x32, 0x39, 0x30, 0x35, 0x30, 0x30,
+ 0x34, 0x36, 0x5a, 0x17, 0x0d, 0x30, 0x37, 0x30, 0x36, 0x32, 0x39, 0x31, 0x31,
+ 0x30, 0x30, 0x34, 0x36, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03,
+ 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e,
+ 0x67, 0x00, 0x30, 0x5c, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
+ 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x4b, 0x00, 0x30, 0x48, 0x02, 0x41,
+ 0x00, 0xe2, 0x54, 0x3a, 0xa7, 0x83, 0xb1, 0x27, 0x14, 0x3e, 0x59, 0xbb, 0xb4,
+ 0x53, 0xe6, 0x1f, 0xe7, 0x5d, 0xf1, 0x21, 0x68, 0xad, 0x85, 0x53, 0xdb, 0x6b,
+ 0x1e, 0xeb, 0x65, 0x97, 0x03, 0x86, 0x60, 0xde, 0xf3, 0x6c, 0x38, 0x75, 0xe0,
+ 0x4c, 0x61, 0xbb, 0xbc, 0x62, 0x17, 0xa9, 0xcd, 0x79, 0x3f, 0x21, 0x4e, 0x96,
+ 0xcb, 0x0e, 0xdc, 0x61, 0x94, 0x30, 0x18, 0x10, 0x6b, 0xd0, 0x1c, 0x10, 0x79,
+ 0x02, 0x03, 0x01, 0x00, 0x01, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02,
+ 0x1d, 0x05, 0x00, 0x03, 0x41, 0x00, 0x25, 0x90, 0x53, 0x34, 0xd9, 0x56, 0x41,
+ 0x5e, 0xdb, 0x7e, 0x01, 0x36, 0xec, 0x27, 0x61, 0x5e, 0xb7, 0x4d, 0x90, 0x66,
+ 0xa2, 0xe1, 0x9d, 0x58, 0x76, 0xd4, 0x9c, 0xba, 0x2c, 0x84, 0xc6, 0x83, 0x7a,
+ 0x22, 0x0d, 0x03, 0x69, 0x32, 0x1a, 0x6d, 0xcb, 0x0c, 0x15, 0xb3, 0x6b, 0xc7,
+ 0x0a, 0x8c, 0xb4, 0x5c, 0x34, 0x78, 0xe0, 0x3c, 0x9c, 0xe9, 0xf3, 0x30, 0x9f,
+ 0xa8, 0x76, 0x57, 0x92, 0x36 };
+static const BYTE selfSignedSignatureHash[] = { 0x07,0x5a,0x3e,0xfd,0x0d,0xf6,
+ 0x88,0xeb,0x00,0x64,0xbd,0xc9,0xd6,0xea,0x0a,0x7c,0xcc,0x24,0xdb,0x5d };
+
+HCRYPTPROV WINAPI I_CryptGetDefaultCryptProv(ALG_ID);
+
+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, sig_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());
+
+    prov = I_CryptGetDefaultCryptProv(0);
+    ok(prov, "hCryptProv can't be NULL\n");
+    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);
+    CryptDestroyHash(hash);
+    CryptDestroyKey(key);
+    CryptReleaseContext(prov, 0);
+
+    /* 2. 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_len = info->Signature.cbData;
+    sig_value = CryptMemAlloc(sig_len);
+    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, sig_len, BCRYPT_PAD_PKCS1);
+    ok(!status, "got %#x\n", status);
+
+    CryptMemFree(sig_value);
+    BCryptDestroyHash(bhash);
+done:
+    BCryptCloseAlgorithmProvider(alg, 0);
+
+    LocalFree(info);
+    CertFreeCertificateContext(cert);
+}
+
 START_TEST(bcrypt)
 {
     HMODULE module;
@@ -2808,6 +2928,7 @@ START_TEST(bcrypt)
     test_BcryptDeriveKeyCapi();
     test_DSA();
     test_SecretAgreement();
+    test_VerifySignature();
 
     FreeLibrary(module);
 }
-- 
2.31.1




More information about the wine-devel mailing list