diff --git a/dlls/dssenh/main.c b/dlls/dssenh/main.c index b575689ab1f..da269807bf9 100644 --- a/dlls/dssenh/main.c +++ b/dlls/dssenh/main.c @@ -718,10 +718,42 @@ BOOL WINAPI CPDeriveKey( HCRYPTPROV hprov, ALG_ID algid, HCRYPTHASH hhash, DWORD return FALSE; } +static DWORD get_signature_length( DWORD algid ) +{ + switch (algid) + { + case AT_SIGNATURE: + case CALG_DSS_SIGN: return 40; + default: + FIXME( "unhandled algorithm %u\n", algid ); + return 0; + } +} + +#define MAX_HASH_LEN 20 BOOL WINAPI CPSignHash( HCRYPTPROV hprov, HCRYPTHASH hhash, DWORD keyspec, const WCHAR *desc, DWORD flags, BYTE *sig, DWORD *siglen ) { - return FALSE; + struct container *container = (struct container *)hprov; + struct hash *hash = (struct hash *)hhash; + UCHAR hashval[MAX_HASH_LEN]; + ULONG len, hashlen = sizeof(hashval); + + TRACE( "%p, %p, %u, %s, %08x, %p, %p\n", (void *)hprov, (void *)hhash, keyspec, debugstr_w(desc), flags, sig, + siglen ); + + if (container->magic != MAGIC_CONTAINER || !container->sign_key) return FALSE; + if (hash->magic != MAGIC_HASH) return FALSE; + + if (!(len = get_signature_length( container->sign_key->algid ))) return FALSE; + if (!CPGetHashParam( hprov, hhash, HP_HASHVAL, hashval, &hashlen, 0 )) return FALSE; + if (*siglen < len) + { + *siglen = len; + return TRUE; + } + + return !BCryptSignHash( container->sign_key->handle, NULL, hashval, hashlen, sig, *siglen, siglen, 0 ); } BOOL WINAPI CPVerifySignature( HCRYPTPROV hprov, HCRYPTHASH hhash, const BYTE *sig, DWORD siglen, HCRYPTKEY hpubkey, diff --git a/dlls/dssenh/tests/dssenh.c b/dlls/dssenh/tests/dssenh.c index 6ad15225924..c2ab37d288b 100644 --- a/dlls/dssenh/tests/dssenh.c +++ b/dlls/dssenh/tests/dssenh.c @@ -889,12 +889,8 @@ static void test_signhash_array(HCRYPTPROV hProv, const struct signature_test *t ok(!memcmp(hashValue1, hashValue2, hashLen2), "Hashes were not identical.\n"); /* Sign hash 1 */ + signLen1 = 0; result = CryptSignHashA(hHash1, AT_SIGNATURE, NULL, 0, NULL, &signLen1); - if (!result) - { - skip("skipping sign tests\n"); - return; - } ok(result, "Failed to get signature length, got %x\n", GetLastError()); ok(signLen1 == 40, "Expected a 40-byte signature, got %d\n", signLen1); @@ -902,6 +898,7 @@ static void test_signhash_array(HCRYPTPROV hProv, const struct signature_test *t ok(result, "Failed to sign hash, got %x\n", GetLastError()); /* Sign hash 2 */ + signLen2 = 0; result = CryptSignHashA(hHash2, AT_SIGNATURE, NULL, 0, NULL, &signLen2); ok(result, "Failed to get signature length, got %x\n", GetLastError()); ok(signLen2 == 40, "Expected a 40-byte signature, got %d\n", signLen2); @@ -943,6 +940,11 @@ static void test_signhash_array(HCRYPTPROV hProv, const struct signature_test *t /* Verify signed hash 1 */ result = CryptVerifySignatureA(hHash1, signValue1, sizeof(signValue1), pubKey, NULL, 0); + if (!result) + { + skip("skipping sign tests\n"); + return; + } ok(result, "Failed to verify signature, got %x\n", GetLastError()); result = CryptCreateHash(hProv, CALG_SHA, 0, 0, &hHash2);