From bf83b89dabbd7a2fc612529d26d5552a54a1b147 Mon Sep 17 00:00:00 2001 From: Hans Leidekker Date: Mon, 12 Oct 2020 16:11:09 +0200 Subject: [PATCH] dssenh: Implement CPDuplicateHash. Signed-off-by: Hans Leidekker Signed-off-by: Alexandre Julliard --- 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(); }