[PATCH 2/5] dssenh: Implement CPDuplicateHash.

Hans Leidekker hans at codeweavers.com
Mon Oct 12 09:11:09 CDT 2020


Signed-off-by: Hans Leidekker <hans at codeweavers.com>
---
 dlls/dssenh/dssenh.spec    |  2 +-
 dlls/dssenh/main.c         | 31 ++++++++++++++++++++++
 dlls/dssenh/tests/dssenh.c | 53 ++++++++++++++++++++++++++++++++++++++
 3 files changed, 85 insertions(+), 1 deletion(-)

diff --git a/dlls/dssenh/dssenh.spec b/dlls/dssenh/dssenh.spec
index 2d93a98796a..a045a7e04ee 100644
--- a/dlls/dssenh/dssenh.spec
+++ b/dlls/dssenh/dssenh.spec
@@ -4,7 +4,7 @@
 @ stdcall CPDeriveKey(ptr long ptr long ptr)
 @ stdcall CPDestroyHash(ptr ptr)
 @ stdcall CPDestroyKey(ptr ptr)
-@ stub CPDuplicateHash
+@ stdcall CPDuplicateHash(ptr ptr ptr long ptr)
 @ stub CPDuplicateKey
 @ stub CPEncrypt
 @ stdcall CPExportKey(ptr ptr ptr long long ptr ptr)
diff --git a/dlls/dssenh/main.c b/dlls/dssenh/main.c
index e9b676e7358..d40dedf41b2 100644
--- a/dlls/dssenh/main.c
+++ b/dlls/dssenh/main.c
@@ -563,6 +563,37 @@ BOOL WINAPI CPDestroyHash( HCRYPTPROV hprov, HCRYPTHASH hhash )
     return TRUE;
 }
 
+static struct hash *duplicate_hash( const struct hash *hash )
+{
+    struct hash *ret;
+
+    if (!(ret = heap_alloc( sizeof(*ret) ))) return NULL;
+
+    ret->magic = hash->magic;
+    ret->len   = hash->len;
+    if (BCryptDuplicateHash( hash->handle, &ret->handle, NULL, 0, 0 ))
+    {
+        heap_free( ret );
+        return NULL;
+    }
+    memcpy( ret->value, hash->value, sizeof(hash->value) );
+    ret->finished = hash->finished;
+    return ret;
+}
+
+BOOL WINAPI CPDuplicateHash( HCRYPTPROV hprov, HCRYPTHASH hhash, DWORD *reserved, DWORD flags, HCRYPTHASH *ret_hash )
+{
+    struct hash *hash = (struct hash *)hhash, *ret;
+
+    TRACE( "%p, %p, %p, %08x, %p\n", (void *)hprov, (void *)hhash, reserved, flags, ret_hash );
+
+    if (hash->magic != MAGIC_HASH) return FALSE;
+
+    if (!(ret = duplicate_hash( hash ))) return FALSE;
+    *ret_hash = (HCRYPTHASH)ret;
+    return TRUE;
+}
+
 BOOL WINAPI CPHashData( HCRYPTPROV hprov, HCRYPTHASH hhash, const BYTE *data, DWORD len, DWORD flags )
 {
     struct hash *hash = (struct hash *)hhash;
diff --git a/dlls/dssenh/tests/dssenh.c b/dlls/dssenh/tests/dssenh.c
index d4a231562e9..704b3685c3f 100644
--- a/dlls/dssenh/tests/dssenh.c
+++ b/dlls/dssenh/tests/dssenh.c
@@ -1413,6 +1413,58 @@ static void test_key_exchange(void)
     ok(result, "Failed to release CSP provider.\n");
 }
 
+static void test_duplicate_hash(void)
+{
+    static const char expected[] =
+        {0xb9,0x7b,0xed,0xd4,0x7b,0xd8,0xa0,0xcd,0x6c,0xba,0xce,0xe9,0xb1,0x36,0xbb,0x00,0x27,0xe3,0x95,0x21};
+    HCRYPTPROV hprov;
+    HCRYPTHASH hhash, hhash2;
+    BYTE buf[20];
+    DWORD len;
+    BOOL result;
+
+    result = CryptAcquireContextA(&hprov, NULL, MS_DEF_DSS_PROV_A, PROV_DSS, CRYPT_VERIFYCONTEXT);
+    ok(result, "got %08x\n", GetLastError());
+
+    result = CryptCreateHash(hprov, CALG_SHA, 0, 0, &hhash);
+    ok(result, "got %08x\n", GetLastError());
+
+    result = CryptHashData(hhash, (const BYTE *)"winetest", sizeof("winetest"), 0);
+    ok(result, "got %08x\n", GetLastError());
+
+    len = sizeof(buf);
+    result = CryptGetHashParam(hhash, HP_HASHVAL, buf, &len, 0);
+    ok(result, "got %08x\n", GetLastError());
+    ok(!memcmp(buf, expected, sizeof(expected)), "wrong data\n");
+
+    SetLastError(0xdeadbeef);
+    result = CryptHashData(hhash, (const BYTE *)"winetest", sizeof("winetest"), 0);
+    ok(!result, "success\n");
+    todo_wine ok(GetLastError() == NTE_BAD_HASH_STATE, "got %08x\n", GetLastError());
+
+    result = CryptDuplicateHash(hhash, NULL, 0, &hhash2);
+    ok(result, "got %08x\n", GetLastError());
+
+    SetLastError(0xdeadbeef);
+    result = CryptHashData(hhash2, (const BYTE *)"winetest", sizeof("winetest"), 0);
+    ok(!result, "success\n");
+    todo_wine ok(GetLastError() == NTE_BAD_HASH_STATE, "got %08x\n", GetLastError());
+
+    len = sizeof(buf);
+    result = CryptGetHashParam(hhash2, HP_HASHVAL, buf, &len, 0);
+    ok(result, "got %08x\n", GetLastError());
+    ok(!memcmp(buf, expected, sizeof(expected)), "wrong data\n");
+
+    result = CryptDestroyHash(hhash2);
+    ok(result, "got %08x\n", GetLastError());
+
+    result = CryptDestroyHash(hhash);
+    ok(result, "got %08x\n", GetLastError());
+
+    result = CryptReleaseContext(hprov, 0);
+    ok(result, "got %08x\n", GetLastError());
+}
+
 START_TEST(dssenh)
 {
     test_acquire_context();
@@ -1422,4 +1474,5 @@ START_TEST(dssenh)
     test_cipher_modes(ciphermode_data, ARRAY_SIZE(ciphermode_data));
     test_verify_signature();
     test_key_exchange();
+    test_duplicate_hash();
 }
-- 
2.28.0




More information about the wine-devel mailing list