[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