dssenh: Implement CPGenKey.

Signed-off-by: Hans Leidekker <hans@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Hans Leidekker 2020-10-14 11:03:57 +02:00 committed by Alexandre Julliard
parent 52ad894784
commit 90bb4fe34b
2 changed files with 164 additions and 88 deletions

View file

@ -19,6 +19,8 @@
#include <stdarg.h>
#include "ntstatus.h"
#define WIN32_NO_STATUS
#include "windef.h"
#include "winbase.h"
#include "wincrypt.h"
@ -309,27 +311,6 @@ BOOL WINAPI CPGetProvParam( HCRYPTPROV hprov, DWORD param, BYTE *data, DWORD *le
return FALSE;
}
BOOL WINAPI CPGenKey( HCRYPTPROV hprov, ALG_ID algid, DWORD flags, HCRYPTKEY *ret_key )
{
return FALSE;
}
BOOL WINAPI CPDestroyKey( HCRYPTPROV hprov, HCRYPTKEY hkey )
{
struct key *key = (struct key *)hkey;
TRACE( "%p, %p\n", (void *)hprov, (void *)hkey );
if (key->magic != MAGIC_KEY)
{
SetLastError( NTE_BAD_KEY );
return FALSE;
}
destroy_key( key );
return TRUE;
}
static BOOL store_key_pair( struct key *key, HKEY hkey, DWORD keyspec, DWORD flags )
{
const WCHAR *value;
@ -378,6 +359,112 @@ static BOOL store_key_container_keys( struct container *container )
return ret;
}
static struct key *duplicate_key( const struct key *key )
{
struct key *ret;
if (!(ret = create_key( key->algid, key->flags ))) return NULL;
if (BCryptDuplicateKey( key->handle, &ret->handle, NULL, 0, 0 ))
{
heap_free( ret );
return NULL;
}
return ret;
}
static BOOL generate_key( struct container *container, ALG_ID algid, DWORD bitlen, DWORD flags, HCRYPTKEY *ret_key )
{
struct key *key, *sign_key;
NTSTATUS status;
if (!(key = create_key( algid, flags ))) return FALSE;
if ((status = BCryptGenerateKeyPair( key->alg_handle, &key->handle, bitlen, 0 )))
{
ERR( "failed to generate key %08x\n", status );
destroy_key( key );
return FALSE;
}
if ((status = BCryptFinalizeKeyPair( key->handle, 0 )))
{
ERR( "failed to finalize key %08x\n", status );
destroy_key( key );
return FALSE;
}
switch (algid)
{
case AT_SIGNATURE:
case CALG_DSS_SIGN:
if (!(sign_key = duplicate_key( key )))
{
destroy_key( key );
return FALSE;
}
destroy_key( container->sign_key );
container->sign_key = sign_key;
break;
default:
FIXME( "unhandled algorithm %08x\n", algid );
return FALSE;
}
if (!store_key_container_keys( container ))
{
destroy_key( key );
return FALSE;
}
*ret_key = (HCRYPTKEY)key;
return TRUE;
}
BOOL WINAPI CPGenKey( HCRYPTPROV hprov, ALG_ID algid, DWORD flags, HCRYPTKEY *ret_key )
{
static const unsigned int supported_key_lengths[] = { 512, 768, 1024 };
struct container *container = (struct container *)hprov;
ULONG i, bitlen = HIWORD(flags) ? HIWORD(flags) : 1024;
TRACE( "%p, %08x, %08x, %p\n", (void *)hprov, algid, flags, ret_key );
if (container->magic != MAGIC_CONTAINER) return FALSE;
if (bitlen % 2)
{
SetLastError( STATUS_INVALID_PARAMETER );
return FALSE;
}
for (i = 0; i < ARRAY_SIZE(supported_key_lengths); i++)
{
if (bitlen == supported_key_lengths[i]) break;
}
if (i >= ARRAY_SIZE(supported_key_lengths))
{
SetLastError( NTE_BAD_FLAGS );
return FALSE;
}
return generate_key( container, algid, bitlen, LOWORD(flags), ret_key );
}
BOOL WINAPI CPDestroyKey( HCRYPTPROV hprov, HCRYPTKEY hkey )
{
struct key *key = (struct key *)hkey;
TRACE( "%p, %p\n", (void *)hprov, (void *)hkey );
if (key->magic != MAGIC_KEY)
{
SetLastError( NTE_BAD_KEY );
return FALSE;
}
destroy_key( key );
return TRUE;
}
#define MAGIC_DSS1 ('D' | ('S' << 8) | ('S' << 16) | ('1' << 24))
#define MAGIC_DSS2 ('D' | ('S' << 8) | ('S' << 16) | ('2' << 24))
@ -493,20 +580,6 @@ BOOL WINAPI CPExportKey( HCRYPTPROV hprov, HCRYPTKEY hkey, HCRYPTKEY hexpkey, DW
return !BCryptExportKey( key->handle, NULL, LEGACY_DSA_V2_PUBLIC_BLOB, data, *len, len, 0 );
}
static struct key *duplicate_key( const struct key *key )
{
struct key *ret;
if (!(ret = create_key( key->algid, key->flags ))) return NULL;
if (BCryptDuplicateKey( key->handle, &ret->handle, NULL, 0, 0 ))
{
heap_free( ret );
return NULL;
}
return ret;
}
BOOL WINAPI CPDuplicateKey( HCRYPTPROV hprov, HCRYPTKEY hkey, DWORD *reserved, DWORD flags, HCRYPTKEY *ret_key )
{
struct key *key = (struct key *)hkey, *ret;

View file

@ -184,14 +184,16 @@ struct keylength_test {
BOOL expectedResult;
DWORD expectedError;
DWORD brokenError;
int todo_result;
int todo_error;
};
static const struct keylength_test baseDSS_keylength[] = {
/* AT_KEYEXCHANGE is not supported by the base DSS provider */
{AT_KEYEXCHANGE, 448 << 16, FALSE, NTE_BAD_ALGID},
{AT_KEYEXCHANGE, 512 << 16, FALSE, NTE_BAD_ALGID},
{AT_KEYEXCHANGE, 1024 << 16, FALSE, NTE_BAD_ALGID},
{AT_KEYEXCHANGE, 1088 << 16, FALSE, NTE_BAD_ALGID},
{AT_KEYEXCHANGE, 448 << 16, FALSE, NTE_BAD_ALGID, 0, 0, 1},
{AT_KEYEXCHANGE, 512 << 16, FALSE, NTE_BAD_ALGID, 0, 0, 1},
{AT_KEYEXCHANGE, 1024 << 16, FALSE, NTE_BAD_ALGID, 0, 0, 1},
{AT_KEYEXCHANGE, 1088 << 16, FALSE, NTE_BAD_ALGID, 0, 0, 1},
/* min 512 max 1024 increment by 64 */
{AT_SIGNATURE, 448 << 16, FALSE, NTE_BAD_FLAGS},
{AT_SIGNATURE, 512 << 16, TRUE},
@ -200,15 +202,15 @@ static const struct keylength_test baseDSS_keylength[] = {
{AT_SIGNATURE, 1024 << 16, TRUE},
{AT_SIGNATURE, 1088 << 16, FALSE, NTE_BAD_FLAGS},
/* CALG_DH_EPHEM is not supported by the base DSS provider */
{CALG_DH_EPHEM, 448 << 16, FALSE, NTE_BAD_ALGID},
{CALG_DH_EPHEM, 512 << 16, FALSE, NTE_BAD_ALGID},
{CALG_DH_EPHEM, 1024 << 16, FALSE, NTE_BAD_ALGID},
{CALG_DH_EPHEM, 1088 << 16, FALSE, NTE_BAD_ALGID},
{CALG_DH_EPHEM, 448 << 16, FALSE, NTE_BAD_ALGID, 0, 0, 1},
{CALG_DH_EPHEM, 512 << 16, FALSE, NTE_BAD_ALGID, 0, 0, 1},
{CALG_DH_EPHEM, 1024 << 16, FALSE, NTE_BAD_ALGID, 0, 0, 1},
{CALG_DH_EPHEM, 1088 << 16, FALSE, NTE_BAD_ALGID, 0, 0, 1},
/* CALG_DH_SF is not supported by the base DSS provider */
{CALG_DH_SF, 448 << 16, FALSE, NTE_BAD_ALGID},
{CALG_DH_SF, 512 << 16, FALSE, NTE_BAD_ALGID},
{CALG_DH_SF, 1024 << 16, FALSE, NTE_BAD_ALGID},
{CALG_DH_SF, 1088 << 16, FALSE, NTE_BAD_ALGID},
{CALG_DH_SF, 448 << 16, FALSE, NTE_BAD_ALGID, 0, 0, 1},
{CALG_DH_SF, 512 << 16, FALSE, NTE_BAD_ALGID, 0, 0, 1},
{CALG_DH_SF, 1024 << 16, FALSE, NTE_BAD_ALGID, 0, 0, 1},
{CALG_DH_SF, 1088 << 16, FALSE, NTE_BAD_ALGID, 0, 0, 1},
/* min 512 max 1024, increment by 64 */
{CALG_DSS_SIGN, 448 << 16, FALSE, NTE_BAD_FLAGS},
{CALG_DSS_SIGN, 512 << 16, TRUE},
@ -221,10 +223,10 @@ static const struct keylength_test baseDSS_keylength[] = {
static const struct keylength_test dssDH_keylength[] = {
/* min 512 max 1024, increment by 64 */
{AT_KEYEXCHANGE, 448 << 16, FALSE, NTE_BAD_FLAGS},
{AT_KEYEXCHANGE, 512 << 16, TRUE},
{AT_KEYEXCHANGE, 513 << 16, FALSE, NTE_BAD_FLAGS},
{AT_KEYEXCHANGE, 768 << 16, TRUE},
{AT_KEYEXCHANGE, 1024 << 16, TRUE},
{AT_KEYEXCHANGE, 512 << 16, TRUE, 0, 0, 1},
{AT_KEYEXCHANGE, 513 << 16, FALSE, NTE_BAD_FLAGS, 0, 0, 1},
{AT_KEYEXCHANGE, 768 << 16, TRUE, 0, 0, 1},
{AT_KEYEXCHANGE, 1024 << 16, TRUE, 0, 0, 1},
{AT_KEYEXCHANGE, 1088 << 16, FALSE, NTE_BAD_FLAGS},
{AT_SIGNATURE, 448 << 16, FALSE, NTE_BAD_FLAGS},
{AT_SIGNATURE, 512 << 16, TRUE},
@ -233,16 +235,16 @@ static const struct keylength_test dssDH_keylength[] = {
{AT_SIGNATURE, 1024 << 16, TRUE},
{AT_SIGNATURE, 1088 << 16, FALSE, NTE_BAD_FLAGS},
{CALG_DH_EPHEM, 448 << 16, FALSE, NTE_BAD_FLAGS},
{CALG_DH_EPHEM, 512 << 16, TRUE},
{CALG_DH_EPHEM, 513 << 16, FALSE, NTE_BAD_FLAGS},
{CALG_DH_EPHEM, 768 << 16, TRUE},
{CALG_DH_EPHEM, 1024 << 16, TRUE},
{CALG_DH_EPHEM, 512 << 16, TRUE, 0, 0, 1},
{CALG_DH_EPHEM, 513 << 16, FALSE, NTE_BAD_FLAGS, 0, 0, 1},
{CALG_DH_EPHEM, 768 << 16, TRUE, 0, 0, 1},
{CALG_DH_EPHEM, 1024 << 16, TRUE, 0, 0, 1},
{CALG_DH_EPHEM, 1088 << 16, FALSE, NTE_BAD_FLAGS},
{CALG_DH_SF, 448 << 16, FALSE, NTE_BAD_FLAGS},
{CALG_DH_SF, 512 << 16, TRUE},
{CALG_DH_SF, 513 << 16, FALSE, NTE_BAD_FLAGS},
{CALG_DH_SF, 768 << 16, TRUE},
{CALG_DH_SF, 1024 << 16, TRUE},
{CALG_DH_SF, 512 << 16, TRUE, 0, 0, 1},
{CALG_DH_SF, 513 << 16, FALSE, NTE_BAD_FLAGS, 0, 0, 1},
{CALG_DH_SF, 768 << 16, TRUE, 0, 0, 1},
{CALG_DH_SF, 1024 << 16, TRUE, 0, 0, 1},
{CALG_DH_SF, 1088 << 16, FALSE, NTE_BAD_FLAGS},
{CALG_DSS_SIGN, 448 << 16, FALSE, NTE_BAD_FLAGS},
{CALG_DSS_SIGN, 512 << 16, TRUE},
@ -255,12 +257,12 @@ static const struct keylength_test dssDH_keylength[] = {
static const struct keylength_test dssENH_keylength[] = {
/* min 512 max 1024 (AT_KEYEXCHANGE, CALG_DH_EPHEM, CALG_DH_SF max 4096), increment by 64*/
{AT_KEYEXCHANGE, 448 << 16, FALSE, NTE_BAD_FLAGS},
{AT_KEYEXCHANGE, 512 << 16, TRUE},
{AT_KEYEXCHANGE, 513 << 16, FALSE, NTE_BAD_FLAGS},
{AT_KEYEXCHANGE, 768 << 16, TRUE},
{AT_KEYEXCHANGE, 1024 << 16, TRUE},
{AT_KEYEXCHANGE, 1088 << 16, TRUE},
{AT_KEYEXCHANGE, 2048 << 16, TRUE},
{AT_KEYEXCHANGE, 512 << 16, TRUE, 0, 0, 1},
{AT_KEYEXCHANGE, 513 << 16, FALSE, NTE_BAD_FLAGS, 0, 0, 1},
{AT_KEYEXCHANGE, 768 << 16, TRUE, 0, 0, 1},
{AT_KEYEXCHANGE, 1024 << 16, TRUE, 0, 0, 1},
{AT_KEYEXCHANGE, 1088 << 16, TRUE, 0, 0, 1},
{AT_KEYEXCHANGE, 2048 << 16, TRUE, 0, 0, 1},
/* Keylength too large - test bot timeout.
{AT_KEYEXCHANGE, 3072 << 16, TRUE},
{AT_KEYEXCHANGE, 4096 << 16, TRUE}, */
@ -272,20 +274,20 @@ static const struct keylength_test dssENH_keylength[] = {
{AT_SIGNATURE, 1024 << 16, TRUE},
{AT_SIGNATURE, 1032 << 16, FALSE, NTE_BAD_FLAGS},
{CALG_DH_EPHEM, 448 << 16, FALSE, NTE_BAD_FLAGS},
{CALG_DH_EPHEM, 512 << 16, TRUE},
{CALG_DH_EPHEM, 513 << 16, FALSE, NTE_BAD_FLAGS},
{CALG_DH_EPHEM, 768 << 16, TRUE},
{CALG_DH_EPHEM, 1024 << 16, TRUE},
{CALG_DH_EPHEM, 512 << 16, TRUE, 0, 0, 1},
{CALG_DH_EPHEM, 513 << 16, FALSE, NTE_BAD_FLAGS, 0, 0, 1},
{CALG_DH_EPHEM, 768 << 16, TRUE, 0, 0, 1},
{CALG_DH_EPHEM, 1024 << 16, TRUE, 0, 0, 1},
{CALG_DH_EPHEM, 1040 << 16, FALSE, NTE_BAD_FLAGS},
{CALG_DH_EPHEM, 1088 << 16, TRUE},
{CALG_DH_EPHEM, 1088 << 16, TRUE, 0, 0, 1},
{CALG_DH_EPHEM, 4160 << 16, FALSE, NTE_BAD_FLAGS},
{CALG_DH_SF, 448 << 16, FALSE, NTE_BAD_FLAGS},
{CALG_DH_SF, 512 << 16, TRUE},
{CALG_DH_SF, 513 << 16, FALSE, NTE_BAD_FLAGS},
{CALG_DH_SF, 768 << 16, TRUE},
{CALG_DH_SF, 1024 << 16, TRUE},
{CALG_DH_SF, 512 << 16, TRUE, 0, 0, 1},
{CALG_DH_SF, 513 << 16, FALSE, NTE_BAD_FLAGS, 0, 0, 1},
{CALG_DH_SF, 768 << 16, TRUE, 0, 0, 1},
{CALG_DH_SF, 1024 << 16, TRUE, 0, 0, 1},
{CALG_DH_SF, 1032 << 16, FALSE, NTE_BAD_FLAGS},
{CALG_DH_SF, 1088 << 16, TRUE},
{CALG_DH_SF, 1088 << 16, TRUE, 0, 0, 1},
{CALG_DH_SF, 4160 << 16, FALSE, NTE_BAD_FLAGS},
{CALG_DSS_SIGN, 448 << 16, FALSE, NTE_BAD_FLAGS},
{CALG_DSS_SIGN, 512 << 16, TRUE},
@ -307,16 +309,22 @@ static void test_keylength_array(HCRYPTPROV hProv,const struct keylength_test *t
result = CryptGenKey(hProv, tests[i].algid, tests[i].flags, &key);
/* success */
if(tests[i].expectedResult)
if (tests[i].expectedResult)
{
ok(result, "%d: Expected a key, got %08x\n", i, GetLastError());
result = CryptDestroyKey(key);
ok(result, "Expected no errors.\n");
todo_wine_if (tests[i].todo_result) ok(result, "%d: got %08x\n", i, GetLastError());
if (result)
{
result = CryptDestroyKey(key);
ok(result, "%d: got %08x\n", i, GetLastError());
}
}
else
ok(!result && (GetLastError() == tests[i].expectedError ||
broken(GetLastError() == tests[i].brokenError)),
"%d: got %x.\n", i, GetLastError());
{
todo_wine_if (tests[i].todo_result) ok(!result, "%d: got %x\n", i, GetLastError());
todo_wine_if (tests[i].todo_error)
ok(GetLastError() == tests[i].expectedError ||
broken(GetLastError() == tests[i].brokenError), "%d: got %08x\n", i, GetLastError());
}
}
}
@ -337,12 +345,7 @@ static void test_keylength(void)
ok(result, "Expected no errors.\n");
result = CryptGenKey(hProv, AT_SIGNATURE, 0, &key);
todo_wine ok(result, "Expected no errors.\n");
if (!result)
{
skip("skipping key length tests\n");
return;
}
ok(result, "Expected no errors.\n");
result = CryptDestroyKey(key);
ok(result, "Expected no errors.\n");