From: Hans Leidekker <hans@codeweavers.com> --- dlls/dssenh/Makefile.in | 3 +- dlls/dssenh/main.c | 711 ++++++++++++++++++++----------------- dlls/dssenh/tests/dssenh.c | 130 +++---- 3 files changed, 440 insertions(+), 404 deletions(-) diff --git a/dlls/dssenh/Makefile.in b/dlls/dssenh/Makefile.in index f888dfab5fa..19ec22b0d14 100644 --- a/dlls/dssenh/Makefile.in +++ b/dlls/dssenh/Makefile.in @@ -1,5 +1,6 @@ MODULE = dssenh.dll -IMPORTS = bcrypt crypt32 advapi32 +IMPORTS = $(SYMCRYPT_PE_LIBS) crypt32 advapi32 +EXTRAINCL = $(SYMCRYPT_PE_CFLAGS) SOURCES = \ main.c \ diff --git a/dlls/dssenh/main.c b/dlls/dssenh/main.c index f637c894e70..6d49ec1cb7e 100644 --- a/dlls/dssenh/main.c +++ b/dlls/dssenh/main.c @@ -24,22 +24,27 @@ #include "winbase.h" #include "wincrypt.h" #include "winreg.h" -#include "bcrypt.h" #include "objbase.h" #include "rpcproxy.h" #include "ntsecapi.h" +#include "symcrypt.h" #include "wine/debug.h" WINE_DEFAULT_DEBUG_CHANNEL(dssenh); +#define MAGIC_DSS1 ('D' | ('S' << 8) | ('S' << 16) | ('1' << 24)) +#define MAGIC_DSS2 ('D' | ('S' << 8) | ('S' << 16) | ('2' << 24)) + #define MAGIC_KEY (('K' << 24) | ('E' << 16) | ('Y' << 8) | '0') struct key { DWORD magic; - DWORD algid; + ALG_ID algid; DWORD flags; - BCRYPT_KEY_HANDLE handle; + DWORD bitlen; + SYMCRYPT_DLGROUP *group; + SYMCRYPT_DLKEY *handle; }; #define MAGIC_CONTAINER (('C' << 24) | ('O' << 16) | ('N' << 8) | 'T') @@ -57,11 +62,12 @@ struct container #define MAGIC_HASH (('H' << 24) | ('A' << 16) | ('S' << 8) | 'H') struct hash { - DWORD magic; - BCRYPT_HASH_HANDLE handle; - DWORD len; - UCHAR value[64]; - BOOL finished; + DWORD magic; + const SYMCRYPT_HASH *desc; + SYMCRYPT_HASH_STATE state; + DWORD len; + UCHAR value[64]; + BOOL finished; }; static const char dss_path_fmt[] = "Software\\Wine\\Crypto\\DSS\\%s"; @@ -73,6 +79,50 @@ static const PROV_ENUMALGS_EX supported_base_algs[] = { CALG_MD5, 128, 128, 128, 0, S("MD5"), S("Message Digest 5 (MD5)") }, { CALG_DSS_SIGN, 1024, 512, 1024, CRYPT_FLAG_SIGNING, S("DSA_SIGN"), S("Digital Signature Algorithm") } }; +#undef S + +void * SYMCRYPT_CALL SymCryptCallbackAlloc( SIZE_T size ) +{ + return malloc( size ); +} + +void SYMCRYPT_CALL SymCryptCallbackFree( void *ptr ) +{ + free( ptr ); +} + +SYMCRYPT_ERROR SYMCRYPT_CALL SymCryptCallbackRandom( BYTE *buf, SIZE_T size ) +{ + return RtlGenRandom( buf, size ) ? SYMCRYPT_NO_ERROR : SYMCRYPT_EXTERNAL_FAILURE; +} + +void SYMCRYPT_CALL SymCryptDsaSelftest( void ) +{ +} + +void SYMCRYPT_CALL SymCryptDhSecretAgreementSelftest( void ) +{ +} + +SYMCRYPT_ERROR SYMCRYPT_CALL SymCryptDsaPct( const SYMCRYPT_DLKEY *key ) +{ + return SYMCRYPT_NO_ERROR; +} + +void SYMCRYPT_CALL SYMCRYPT_CALL SymCryptFatal( UINT32 code ) +{ +} + +void SYMCRYPT_CALL SYMCRYPT_CALL SymCryptInjectError( BYTE *buf, SIZE_T size ) +{ +} + +SYMCRYPT_CPU_FEATURES SYMCRYPT_CALL SymCryptCpuFeaturesNeverPresent( void ) +{ + return 0; +} + +UINT32 g_SymCryptFipsSelftestsPerformed; static BOOL create_container_regkey( struct container *container, REGSAM sam, HKEY *hkey ) { @@ -127,7 +177,7 @@ static BOOL open_container_regkey( const char *name, DWORD flags, REGSAM access, return !RegOpenKeyExA( rootkey, path, 0, access, hkey ); } -static const WCHAR *map_keyspec_to_keypair_name( DWORD keyspec ) +static const WCHAR *map_keyspec_to_keypair_name( DWORD keyspec, ALG_ID *algid ) { const WCHAR *name; @@ -135,9 +185,11 @@ static const WCHAR *map_keyspec_to_keypair_name( DWORD keyspec ) { case AT_KEYEXCHANGE: name = L"KeyExchangeKeyPair"; + if (algid) *algid = CALG_DH_SF; break; case AT_SIGNATURE: name = L"SignatureKeyPair"; + if (algid) *algid = CALG_DSS_SIGN; break; default: ERR( "invalid key spec %lu\n", keyspec ); @@ -146,51 +198,101 @@ static const WCHAR *map_keyspec_to_keypair_name( DWORD keyspec ) return name; } -static struct key *create_key( ALG_ID algid, DWORD flags ) +static struct key *create_key( ALG_ID algid, DWORD bitlen, DWORD flags ) { - struct key *ret; + struct key *key; switch (algid) { - case AT_SIGNATURE: case CALG_DSS_SIGN: + case CALG_DH_SF: break; default: FIXME( "unhandled algorithm %08x\n", algid ); + SetLastError( NTE_BAD_ALGID ); return NULL; } - if (!(ret = calloc( 1, sizeof(*ret) ))) return NULL; + if (!(key = calloc( 1, sizeof(*key) ))) return NULL; - ret->magic = MAGIC_KEY; - ret->algid = algid; - ret->flags = flags; - return ret; + key->magic = MAGIC_KEY; + key->algid = algid; + key->bitlen = bitlen; + key->flags = flags; + return key; } static void destroy_key( struct key *key ) { if (!key) return; - BCryptDestroyKey( key->handle ); + if (key->handle) SymCryptDlkeyFree( key->handle ); + if (key->group) SymCryptDlgroupFree( key->group ); /* Ensure compiler doesn't optimize out the assignment with 0. */ SecureZeroMemory( &key->magic, sizeof(key->magic) ); free( key ); } -static struct key *import_key( DWORD keyspec, BYTE *data, DWORD len ) +static struct key *import_key( ALG_ID algid, const BYTE *input, DWORD input_len, DWORD flags ) { - struct key *ret; + const BLOBHEADER *hdr = (const BLOBHEADER *)input; + const DSSPUBKEY *dsskey = (const DSSPUBKEY *)(hdr + 1); + UINT32 priv_size = 0, pub_size = 0, set_flags = SYMCRYPT_FLAG_KEY_NO_FIPS | SYMCRYPT_FLAG_DLKEY_DSA; + const UCHAR *prime_p, *prime_q, *generator, *pub = NULL, *priv = NULL, *seed, *count; + ULONG size, key_size; + struct key *key; + + if (input_len < sizeof(*hdr)) return NULL; + if (hdr->bType != PRIVATEKEYBLOB && hdr->bType != PUBLICKEYBLOB) return NULL; + if (hdr->bVersion != 2 || (hdr->aiKeyAlg != CALG_DSS_SIGN && hdr->aiKeyAlg != CALG_DH_SF)) return NULL; - if (!(ret = create_key( keyspec, 0 ))) return NULL; + size = sizeof(*hdr) + sizeof(*dsskey); + if (input_len < size || dsskey->bitlen & 0xf) return NULL; - if (BCryptImportKeyPair( BCRYPT_DSA_ALG_HANDLE, NULL, LEGACY_DSA_V2_PRIVATE_BLOB, &ret->handle, data, len, 0 )) + key_size = dsskey->bitlen / 8; + size += key_size * 2 /* p and g */+ 20 /* q */ + 4 /* count */ + 20 /* seed */; + size += (hdr->bType == PRIVATEKEYBLOB ? 20 /* x */ : key_size /* y */); + if (input_len != size) return NULL; + + if (!(key = create_key( algid, dsskey->bitlen, flags ))) return NULL; + if (!(key->group = SymCryptDlgroupAllocate( dsskey->bitlen, 0 )) || + !(key->handle = SymCryptDlkeyAllocate( key->group ))) { - WARN( "failed to import key\n" ); - destroy_key( ret ); + destroy_key( key ); return NULL; } - return ret; + + prime_p = (const UCHAR *)(dsskey + 1); + prime_q = prime_p + key_size; + generator = prime_q + 20; + count = generator + key_size + (hdr->bType == PRIVATEKEYBLOB ? 20 : key_size); + seed = count + 4; + + if (SymCryptDlgroupSetValue( prime_p, key_size, prime_q, 20, generator, key_size, SYMCRYPT_NUMBER_FORMAT_LSB_FIRST, + NULL, seed, 20, *(UINT32 *)count, SYMCRYPT_DLGROUP_FIPS_NONE, key->group )) + { + destroy_key( key ); + return NULL; + } + + if (hdr->bType == PRIVATEKEYBLOB) + { + priv = generator + key_size; + priv_size = 20; + } + else + { + pub = generator + key_size; + pub_size = key_size; + } + + if (SymCryptDlkeySetValue( priv, priv_size, pub, pub_size, SYMCRYPT_NUMBER_FORMAT_LSB_FIRST, set_flags, key->handle )) + { + destroy_key( key ); + return NULL; + } + + return key; } static struct key *read_key( HKEY hkey, DWORD keyspec, DWORD flags ) @@ -199,9 +301,10 @@ static struct key *read_key( HKEY hkey, DWORD keyspec, DWORD flags ) DWORD type, len; BYTE *data; DATA_BLOB blob_in, blob_out; - struct key *ret = NULL; + ALG_ID algid; + struct key *key = NULL; - if (!(value = map_keyspec_to_keypair_name( keyspec ))) return NULL; + if (!(value = map_keyspec_to_keypair_name( keyspec, &algid ))) return NULL; if (RegQueryValueExW( hkey, value, 0, &type, NULL, &len )) return NULL; if (!(data = malloc( len ))) return NULL; @@ -211,13 +314,13 @@ static struct key *read_key( HKEY hkey, DWORD keyspec, DWORD flags ) blob_in.cbData = len; if (CryptUnprotectData( &blob_in, NULL, NULL, NULL, NULL, flags, &blob_out )) { - ret = import_key( keyspec, blob_out.pbData, blob_out.cbData ); + key = import_key( algid, blob_out.pbData, blob_out.cbData, flags ); LocalFree( blob_out.pbData ); } } free( data ); - return ret; + return key; } static void destroy_container( struct container *container ) @@ -328,9 +431,14 @@ BOOL WINAPI CPReleaseContext( HCRYPTPROV hprov, DWORD flags ) { struct container *container = (struct container *)hprov; - TRACE( "%p, %08lx\n", (void *)hprov, flags ); + TRACE( "%IX, %08lx\n", hprov, flags ); + + if (!container || container->magic != MAGIC_CONTAINER) + { + SetLastError( ERROR_INVALID_PARAMETER ); + return FALSE; + } - if (container->magic != MAGIC_CONTAINER) return FALSE; destroy_container( container ); return TRUE; } @@ -364,17 +472,16 @@ BOOL WINAPI CPGetProvParam( HCRYPTPROV hprov, DWORD param, BYTE *data, DWORD *le { struct container *container = (struct container *)hprov; - TRACE( "%p, %lu, %p, %p, %08lx\n", (void *)hprov, param, data, len, flags ); + TRACE( "%IX, %lu, %p, %p, %08lx\n", hprov, param, data, len, flags ); - if (!len) + if (!container || container->magic != MAGIC_CONTAINER) { - SetLastError(ERROR_INVALID_PARAMETER); + SetLastError( NTE_BAD_UID ); return FALSE; } - - if (container->magic != MAGIC_CONTAINER) + if (!len) { - SetLastError(NTE_BAD_UID); + SetLastError( ERROR_INVALID_PARAMETER ); return FALSE; } @@ -418,10 +525,10 @@ BOOL WINAPI CPGetProvParam( HCRYPTPROV hprov, DWORD param, BYTE *data, DWORD *le { PROV_ENUMALGS alg; - alg.aiAlgid = supported_base_algs[container->alg_idx].aiAlgid; - alg.dwBitLen = supported_base_algs[container->alg_idx].dwDefaultLen; - strcpy( alg.szName, supported_base_algs[container->alg_idx].szName ); + alg.aiAlgid = supported_base_algs[container->alg_idx].aiAlgid; + alg.dwBitLen = supported_base_algs[container->alg_idx].dwDefaultLen; alg.dwNameLen = supported_base_algs[container->alg_idx].dwNameLen; + strcpy( alg.szName, supported_base_algs[container->alg_idx].szName ); return copy_param( data, len, &alg, sizeof(alg) ); } else @@ -435,6 +542,58 @@ BOOL WINAPI CPGetProvParam( HCRYPTPROV hprov, DWORD param, BYTE *data, DWORD *le } } +static BOOL export_key( const struct key *key, DWORD type, BYTE *output, DWORD output_len, DWORD *ret_len ) +{ + BLOBHEADER *hdr = (BLOBHEADER *)output; + DSSPUBKEY *dsskey = (DSSPUBKEY *)(hdr + 1); + UINT32 key_size = key->bitlen / 8, pub_size = 0, priv_size = 0; + UCHAR *prime_p, *prime_q, *generator, *pub = NULL, *priv = NULL, *seed, *count; + ULONG size; + + size = sizeof(*hdr) + sizeof(*dsskey) + key_size * 2 /* p and g */ + 20 /* q */ + 4 /* count */ + 20 /* seed */; + size += (type == PRIVATEKEYBLOB) ? 20 /* x */ : key_size; /* y */ + if (output_len < size || !output) + { + *ret_len = size; + if (output) return FALSE; + return TRUE; + } + + hdr->bType = type; + hdr->bVersion = 2; + hdr->reserved = 0; + hdr->aiKeyAlg = CALG_DSS_SIGN; + + dsskey->magic = (type == PRIVATEKEYBLOB) ? MAGIC_DSS2 : MAGIC_DSS1; + dsskey->bitlen = key->bitlen; + + prime_p = (UCHAR *)(dsskey + 1); + prime_q = prime_p + key_size; + generator = prime_q + 20; + count = generator + key_size + (type == PRIVATEKEYBLOB ? 20 : key_size); + seed = count + 4; + + if (SymCryptDlgroupGetValue( key->group, prime_p, key_size, prime_q, 20, generator, key_size, + SYMCRYPT_NUMBER_FORMAT_LSB_FIRST, NULL, seed, 20, (UINT32 *)count )) return FALSE; + + if (type == PRIVATEKEYBLOB) + { + priv = generator + key_size; + priv_size = 20; + } + else + { + pub = generator + key_size; + pub_size = key_size; + } + + if (SymCryptDlkeyGetValue( key->handle, priv, priv_size, pub, pub_size, SYMCRYPT_NUMBER_FORMAT_LSB_FIRST, 0 )) + return FALSE; + + *ret_len = size; + return TRUE; +} + static BOOL store_key_pair( struct key *key, HKEY hkey, DWORD keyspec, DWORD flags ) { const WCHAR *value; @@ -444,12 +603,11 @@ static BOOL store_key_pair( struct key *key, HKEY hkey, DWORD keyspec, DWORD fla BOOL ret = TRUE; if (!key) return TRUE; - if (!(value = map_keyspec_to_keypair_name( keyspec ))) return FALSE; + if (!(value = map_keyspec_to_keypair_name( keyspec, NULL ))) return FALSE; - if (BCryptExportKey( key->handle, NULL, LEGACY_DSA_V2_PRIVATE_BLOB, NULL, 0, &len, 0 )) return FALSE; + if (!export_key( key, PRIVATEKEYBLOB, NULL, 0, &len )) return FALSE; if (!(data = malloc( len ))) return FALSE; - - if (!BCryptExportKey( key->handle, NULL, LEGACY_DSA_V2_PRIVATE_BLOB, data, len, &len, 0 )) + if (export_key( key, PRIVATEKEYBLOB, data, len, &len )) { blob_in.pbData = data; blob_in.cbData = len; @@ -467,59 +625,51 @@ static BOOL store_key_pair( struct key *key, HKEY hkey, DWORD keyspec, DWORD fla static BOOL store_key_container_keys( struct container *container ) { HKEY hkey; - DWORD flags; + DWORD flags = (container->flags & CRYPT_MACHINE_KEYSET) ? CRYPTPROTECT_LOCAL_MACHINE : 0; BOOL ret; - if (container->flags & CRYPT_MACHINE_KEYSET) - flags = CRYPTPROTECT_LOCAL_MACHINE; - else - flags = 0; - if (!create_container_regkey( container, KEY_WRITE, &hkey )) return FALSE; ret = store_key_pair( container->exch_key, hkey, AT_KEYEXCHANGE, flags ); - if (ret) store_key_pair( container->sign_key, hkey, AT_SIGNATURE, flags ); + if (ret) ret = store_key_pair( container->sign_key, hkey, AT_SIGNATURE, flags ); RegCloseKey( hkey ); return ret; } -static struct key *duplicate_key( const struct key *key ) +static struct key *duplicate_key( const struct key *src ) { - struct key *ret; - - if (!(ret = create_key( key->algid, key->flags ))) return NULL; + struct key *dst; + DWORD len, type = SymCryptDlkeyHasPrivateKey( src->handle ) ? PRIVATEKEYBLOB : PUBLICKEYBLOB; + BYTE *data; - if (BCryptDuplicateKey( key->handle, &ret->handle, NULL, 0, 0 )) + if (!export_key( src, type, NULL, 0, &len )) return NULL; + if (!(data = malloc( len ))) return NULL; + if (!export_key( src, type, data, len, &len ) || !(dst = import_key( src->algid, data, len, src->flags ))) { - free( ret ); + free( data ); return NULL; } - return ret; + + free( data ); + return dst; } static BOOL generate_key( struct container *container, ALG_ID algid, DWORD bitlen, DWORD flags, HCRYPTKEY *ret_key ) { - struct key *key, *sign_key; - NTSTATUS status; + UINT32 generate_flags = SYMCRYPT_FLAG_KEY_NO_FIPS | SYMCRYPT_FLAG_DLKEY_DSA; + struct key *key, *sign_key, *exch_key; - if (!(key = create_key( algid, flags ))) return FALSE; + if (algid == AT_SIGNATURE) algid = CALG_DSS_SIGN; + else if (algid == AT_KEYEXCHANGE) algid = CALG_DH_SF; - if ((status = BCryptGenerateKeyPair( BCRYPT_DSA_ALG_HANDLE, &key->handle, bitlen, 0 ))) - { - ERR( "failed to generate key %08lx\n", status ); - destroy_key( key ); - return FALSE; - } - if ((status = BCryptFinalizeKeyPair( key->handle, 0 ))) - { - ERR( "failed to finalize key %08lx\n", status ); - destroy_key( key ); - return FALSE; - } + if (!(key = create_key( algid, bitlen, flags ))) return FALSE; + if (!(key->group = SymCryptDlgroupAllocate( bitlen, 0 ))) goto error; + if (SymCryptDlgroupGenerate( NULL, SYMCRYPT_DLGROUP_FIPS_186_2, key->group )) goto error; + if (!(key->handle = SymCryptDlkeyAllocate( key->group ))) goto error; + if (SymCryptDlkeyGenerate( generate_flags, key->handle )) goto error; switch (algid) { - case AT_SIGNATURE: case CALG_DSS_SIGN: if (!(sign_key = duplicate_key( key ))) { @@ -530,8 +680,19 @@ static BOOL generate_key( struct container *container, ALG_ID algid, DWORD bitle container->sign_key = sign_key; break; + case CALG_DH_SF: + if (!(exch_key = duplicate_key( key ))) + { + destroy_key( key ); + return FALSE; + } + destroy_key( container->exch_key ); + container->exch_key = exch_key; + break; + default: FIXME( "unhandled algorithm %08x\n", algid ); + SetLastError( NTE_BAD_ALGID ); return FALSE; } @@ -539,6 +700,11 @@ static BOOL generate_key( struct container *container, ALG_ID algid, DWORD bitle *ret_key = (HCRYPTKEY)key; return TRUE; + +error: + SetLastError( NTE_BAD_FLAGS ); + destroy_key( key ); + return FALSE; } BOOL WINAPI CPGenKey( HCRYPTPROV hprov, ALG_ID algid, DWORD flags, HCRYPTKEY *ret_key ) @@ -547,15 +713,14 @@ BOOL WINAPI CPGenKey( HCRYPTPROV hprov, ALG_ID algid, DWORD flags, HCRYPTKEY *re struct container *container = (struct container *)hprov; ULONG i, bitlen = HIWORD(flags) ? HIWORD(flags) : 1024; - TRACE( "%p, %08x, %08lx, %p\n", (void *)hprov, algid, flags, ret_key ); - - if (container->magic != MAGIC_CONTAINER) return FALSE; + TRACE( "%IX, %08x, %08lx, %p\n", hprov, algid, flags, ret_key ); - if (bitlen % 2) + if (!container || container->magic != MAGIC_CONTAINER || bitlen % 2 || !ret_key) { - SetLastError( STATUS_INVALID_PARAMETER ); + SetLastError( ERROR_INVALID_PARAMETER ); return FALSE; } + for (i = 0; i < ARRAY_SIZE(supported_key_lengths); i++) { if (bitlen == supported_key_lengths[i]) break; @@ -573,9 +738,9 @@ BOOL WINAPI CPDestroyKey( HCRYPTPROV hprov, HCRYPTKEY hkey ) { struct key *key = (struct key *)hkey; - TRACE( "%p, %p\n", (void *)hprov, (void *)hkey ); + TRACE( "%IX, %IX\n", hprov, hkey ); - if (key->magic != MAGIC_KEY) + if (!key || key->magic != MAGIC_KEY) { SetLastError( NTE_BAD_KEY ); return FALSE; @@ -585,50 +750,17 @@ BOOL WINAPI CPDestroyKey( HCRYPTPROV hprov, HCRYPTKEY hkey ) return TRUE; } -#define MAGIC_DSS1 ('D' | ('S' << 8) | ('S' << 16) | ('1' << 24)) -#define MAGIC_DSS2 ('D' | ('S' << 8) | ('S' << 16) | ('2' << 24)) -#define MAGIC_DSS3 ('D' | ('S' << 8) | ('S' << 16) | ('3' << 24)) - static BOOL import_key_dss2( struct container *container, ALG_ID algid, const BYTE *data, DWORD len, DWORD flags, HCRYPTKEY *ret_key ) { - const BLOBHEADER *hdr = (const BLOBHEADER *)data; - const DSSPUBKEY *pubkey = (const DSSPUBKEY *)(hdr + 1); - const WCHAR *type; struct key *key, *exch_key, *sign_key; - NTSTATUS status; - - if (len < sizeof(*hdr) + sizeof(*pubkey)) return FALSE; - - switch (pubkey->magic) - { - case MAGIC_DSS1: - type = LEGACY_DSA_V2_PUBLIC_BLOB; - break; - - case MAGIC_DSS2: - type = LEGACY_DSA_V2_PRIVATE_BLOB; - break; - default: - FIXME( "unsupported key magic %08lx\n", pubkey->magic ); - return FALSE; - } - - if (!(key = create_key( CALG_DSS_SIGN, flags ))) return FALSE; - - if ((status = BCryptImportKeyPair( BCRYPT_DSA_ALG_HANDLE, NULL, type, &key->handle, (UCHAR *)data, len, 0 ))) - { - TRACE( "failed to import key %08lx\n", status ); - destroy_key( key ); - return FALSE; - } + if (!(key = import_key( algid, data, len, flags ))) return FALSE; - if (!wcscmp(type, LEGACY_DSA_V2_PRIVATE_BLOB)) + if (SymCryptDlkeyHasPrivateKey( key->handle )) { switch (algid) { - case AT_KEYEXCHANGE: case CALG_DH_SF: if (!(exch_key = duplicate_key( key ))) { @@ -639,7 +771,6 @@ static BOOL import_key_dss2( struct container *container, ALG_ID algid, const BY container->exch_key = exch_key; break; - case AT_SIGNATURE: case CALG_DSS_SIGN: if (!(sign_key = duplicate_key( key ))) { @@ -656,84 +787,13 @@ static BOOL import_key_dss2( struct container *container, ALG_ID algid, const BY return FALSE; } - if (!store_key_container_keys( container )) return FALSE; - } - - *ret_key = (HCRYPTKEY)key; - return TRUE; -} - -static BOOL import_key_dss3( struct container *container, ALG_ID algid, const BYTE *data, DWORD len, DWORD flags, - HCRYPTKEY *ret_key ) -{ - const BLOBHEADER *hdr = (const BLOBHEADER *)data; - const DSSPUBKEY_VER3 *pubkey = (const DSSPUBKEY_VER3 *)(hdr + 1); - BCRYPT_DSA_KEY_BLOB *blob; - struct key *key; - BYTE *src, *dst; - ULONG i, size, size_q; - NTSTATUS status; - - if (len < sizeof(*hdr) + sizeof(*pubkey)) return FALSE; - - switch (pubkey->magic) - { - case MAGIC_DSS3: - break; - - default: - FIXME( "unsupported key magic %08lx\n", pubkey->magic ); - return FALSE; - } - - if ((size_q = pubkey->bitlenQ / 8) > sizeof(blob->q)) - { - FIXME( "q too large\n" ); - return FALSE; - } - - if (!(key = create_key( CALG_DSS_SIGN, flags ))) return FALSE; - - size = sizeof(*blob) + (pubkey->bitlenP / 8) * 3; - if (!(blob = calloc( 1, size ))) - { - destroy_key( key ); - return FALSE; - } - blob->dwMagic = BCRYPT_DSA_PUBLIC_MAGIC; - blob->cbKey = pubkey->bitlenP / 8; - memcpy( blob->Count, &pubkey->DSSSeed.counter, sizeof(blob->Count) ); - memcpy( blob->Seed, pubkey->DSSSeed.seed, sizeof(blob->Seed) ); - - /* q */ - src = (BYTE *)(pubkey + 1) + blob->cbKey; - for (i = 0; i < size_q; i++) blob->q[i] = src[size_q - i - 1]; - - /* p */ - src -= blob->cbKey; - dst = (BYTE *)(blob + 1); - for (i = 0; i < blob->cbKey; i++) dst[i] = src[blob->cbKey - i - 1]; - - /* g */ - src += blob->cbKey + size_q; - dst += blob->cbKey; - for (i = 0; i < blob->cbKey; i++) dst[i] = src[blob->cbKey - i - 1]; - - /* y */ - src += blob->cbKey + pubkey->bitlenJ / 8; - dst += blob->cbKey; - for (i = 0; i < blob->cbKey; i++) dst[i] = src[blob->cbKey - i - 1]; - - if ((status = BCryptImportKeyPair( BCRYPT_DSA_ALG_HANDLE, NULL, BCRYPT_DSA_PUBLIC_BLOB, &key->handle, - (UCHAR *)blob, size, 0 ))) - { - WARN( "failed to import key %08lx\n", status ); - destroy_key( key ); - free( blob ); - return FALSE; + if (!store_key_container_keys( container )) + { + destroy_key( key ); + return FALSE; + } } - free( blob ); *ret_key = (HCRYPTKEY)key; return TRUE; } @@ -745,10 +805,13 @@ BOOL WINAPI CPImportKey( HCRYPTPROV hprov, const BYTE *data, DWORD len, HCRYPTKE const BLOBHEADER *hdr; BOOL ret; - TRACE( "%p, %p, %lu, %p, %08lx, %p\n", (void *)hprov, data, len, (void *)hpubkey, flags, ret_key ); + TRACE( "%IX, %p, %lu, %IX, %08lx, %p\n", hprov, data, len, hpubkey, flags, ret_key ); - if (container->magic != MAGIC_CONTAINER) return FALSE; - if (len < sizeof(*hdr)) return FALSE; + if (!container || container->magic != MAGIC_CONTAINER || !data || len < sizeof(*hdr) || !ret_key) + { + SetLastError( ERROR_INVALID_PARAMETER ); + return FALSE; + } hdr = (const BLOBHEADER *)data; if ((hdr->bType != PRIVATEKEYBLOB && hdr->bType != PUBLICKEYBLOB) || hdr->aiKeyAlg != CALG_DSS_SIGN) @@ -763,10 +826,6 @@ BOOL WINAPI CPImportKey( HCRYPTPROV hprov, const BYTE *data, DWORD len, HCRYPTKE ret = import_key_dss2( container, hdr->aiKeyAlg, data, len, flags, ret_key ); break; - case 3: - ret = import_key_dss3( container, hdr->aiKeyAlg, data, len, flags, ret_key ); - break; - default: FIXME( "version %u not supported\n", hdr->bVersion ); return FALSE; @@ -775,16 +834,18 @@ BOOL WINAPI CPImportKey( HCRYPTPROV hprov, const BYTE *data, DWORD len, HCRYPTKE return ret; } -BOOL WINAPI CPExportKey( HCRYPTPROV hprov, HCRYPTKEY hkey, HCRYPTKEY hexpkey, DWORD blobtype, DWORD flags, - BYTE *data, DWORD *len ) +BOOL WINAPI CPExportKey( HCRYPTPROV hprov, HCRYPTKEY hkey, HCRYPTKEY hexpkey, DWORD type, DWORD flags, BYTE *data, + DWORD *len ) { struct key *key = (struct key *)hkey; - const WCHAR *type; - TRACE( "%p, %p, %p, %08lx, %08lx, %p, %p\n", (void *)hprov, (void *)hkey, (void *)hexpkey, blobtype, flags, - data, len ); + TRACE( "%IX, %IX, %IX, %08lx, %08lx, %p, %p\n", hprov, hkey, hexpkey, type, flags, data, len ); - if (key->magic != MAGIC_KEY) return FALSE; + if (!key || key->magic != MAGIC_KEY || (type != PUBLICKEYBLOB && type != PRIVATEKEYBLOB) || !len) + { + SetLastError( ERROR_INVALID_PARAMETER ); + return FALSE; + } if (hexpkey) { FIXME( "export key not supported\n" ); @@ -796,34 +857,23 @@ BOOL WINAPI CPExportKey( HCRYPTPROV hprov, HCRYPTKEY hkey, HCRYPTKEY hexpkey, DW return FALSE; } - switch (blobtype) - { - case PUBLICKEYBLOB: - type = LEGACY_DSA_V2_PUBLIC_BLOB; - break; - - case PRIVATEKEYBLOB: - type = LEGACY_DSA_V2_PRIVATE_BLOB; - break; - - default: - FIXME( "blob type %lu not supported\n", blobtype ); - return FALSE; - } - - return !BCryptExportKey( key->handle, NULL, type, data, *len, len, 0 ); + return export_key( key, type, data, *len, len ); } BOOL WINAPI CPDuplicateKey( HCRYPTPROV hprov, HCRYPTKEY hkey, DWORD *reserved, DWORD flags, HCRYPTKEY *ret_key ) { - struct key *key = (struct key *)hkey, *ret; + struct key *src = (struct key *)hkey, *dst; - TRACE( "%p, %p, %p, %08lx, %p\n", (void *)hprov, (void *)hkey, reserved, flags, ret_key ); + TRACE( "%IX, %IX, %p, %08lx, %p\n", hprov, hkey, reserved, flags, ret_key ); - if (key->magic != MAGIC_KEY) return FALSE; + if (!src || src->magic != MAGIC_KEY || !ret_key) + { + SetLastError( ERROR_INVALID_PARAMETER ); + return FALSE; + } - if (!(ret = duplicate_key( key ))) return FALSE; - *ret_key = (HCRYPTKEY)ret; + if (!(dst = duplicate_key( src ))) return FALSE; + *ret_key = (HCRYPTKEY)dst; return TRUE; } @@ -832,9 +882,13 @@ BOOL WINAPI CPGetUserKey( HCRYPTPROV hprov, DWORD keyspec, HCRYPTKEY *ret_key ) struct container *container = (struct container *)hprov; BOOL ret = FALSE; - TRACE( "%p, %08lx, %p\n", (void *)hprov, keyspec, ret_key ); + TRACE( "%IX, %08lx, %p\n", hprov, keyspec, ret_key ); - if (container->magic != MAGIC_CONTAINER) return FALSE; + if (!container || container->magic != MAGIC_CONTAINER || !ret_key) + { + SetLastError( ERROR_INVALID_PARAMETER ); + return FALSE; + } switch (keyspec) { @@ -858,12 +912,8 @@ BOOL WINAPI CPGetUserKey( HCRYPTPROV hprov, DWORD keyspec, HCRYPTKEY *ret_key ) BOOL WINAPI CPSetKeyParam( HCRYPTPROV hprov, HCRYPTKEY hkey, DWORD param, BYTE *data, DWORD flags ) { - if (!data) - { - SetLastError( ERROR_INVALID_PARAMETER ); - return FALSE; - } - + FIXME( "%IX, %IX, %lu, %p, %08lx\n", hprov, hkey, param, data, flags ); + SetLastError( ERROR_INVALID_PARAMETER ); return FALSE; } @@ -871,28 +921,32 @@ BOOL WINAPI CPGenRandom( HCRYPTPROV hprov, DWORD len, BYTE *buffer ) { struct container *container = (struct container *)hprov; - TRACE( "%p, %lu, %p\n", (void *)hprov, len, buffer ); + TRACE( "%IX, %lu, %p\n", hprov, len, buffer ); - if (container->magic != MAGIC_CONTAINER) return FALSE; + if (!container || container->magic != MAGIC_CONTAINER || !buffer) + { + SetLastError( ERROR_INVALID_PARAMETER ); + return FALSE; + } return RtlGenRandom( buffer, len ); } static struct hash *create_hash( ALG_ID algid ) { - struct hash *ret; - BCRYPT_ALG_HANDLE alg_handle; + struct hash *hash; + const SYMCRYPT_HASH *desc; DWORD len; switch (algid) { case CALG_MD5: - alg_handle = BCRYPT_MD5_ALG_HANDLE; + desc = SymCryptMd5Algorithm; len = 16; break; case CALG_SHA1: - alg_handle = BCRYPT_SHA1_ALG_HANDLE; + desc = SymCryptSha1Algorithm; len = 20; break; @@ -901,23 +955,27 @@ static struct hash *create_hash( ALG_ID algid ) return NULL; } - if (!(ret = calloc( 1, sizeof(*ret) ))) return NULL; + if (!(hash = calloc( 1, sizeof(*hash) ))) return NULL; - ret->magic = MAGIC_HASH; - ret->len = len; - if (BCryptCreateHash( alg_handle, &ret->handle, NULL, 0, NULL, 0, 0 )) - { - free( ret ); - return NULL; - } - return ret; + hash->magic = MAGIC_HASH; + hash->desc = desc; + hash->len = len; + + SymCryptHashInit( hash->desc, &hash->state ); + return hash; } BOOL WINAPI CPCreateHash( HCRYPTPROV hprov, ALG_ID algid, HCRYPTKEY hkey, DWORD flags, HCRYPTHASH *ret_hash ) { struct hash *hash; - TRACE( "%p, %08x, %p, %08lx, %p\n", (void *)hprov, algid, (void *)hkey, flags, ret_hash ); + TRACE( "%IX, %08x, %IX, %08lx, %p\n", hprov, algid, hkey, flags, ret_hash ); + + if (!ret_hash) + { + SetLastError( ERROR_INVALID_PARAMETER ); + return FALSE; + } switch (algid) { @@ -940,7 +998,6 @@ BOOL WINAPI CPCreateHash( HCRYPTPROV hprov, ALG_ID algid, HCRYPTKEY hkey, DWORD static void destroy_hash( struct hash *hash ) { if (!hash) return; - BCryptDestroyHash( hash->handle ); /* Ensure compiler doesn't optimize out the assignment with 0. */ SecureZeroMemory( &hash->magic, sizeof(hash->magic) ); free( hash ); @@ -950,9 +1007,9 @@ BOOL WINAPI CPDestroyHash( HCRYPTPROV hprov, HCRYPTHASH hhash ) { struct hash *hash = (struct hash *)hhash; - TRACE( "%p, %p\n", (void *)hprov, (void *)hhash); + TRACE( "%IX, %IX\n", hprov, hhash); - if (hash->magic != MAGIC_HASH) + if (!hash || hash->magic != MAGIC_HASH) { SetLastError( NTE_BAD_HASH ); return FALSE; @@ -962,34 +1019,36 @@ BOOL WINAPI CPDestroyHash( HCRYPTPROV hprov, HCRYPTHASH hhash ) return TRUE; } -static struct hash *duplicate_hash( const struct hash *hash ) +static struct hash *duplicate_hash( const struct hash *src ) { - struct hash *ret; + struct hash *dst; - if (!(ret = malloc( sizeof(*ret) ))) return NULL; + if (!(dst = malloc( sizeof(*dst) ))) return NULL; - ret->magic = hash->magic; - ret->len = hash->len; - if (BCryptDuplicateHash( hash->handle, &ret->handle, NULL, 0, 0 )) - { - free( ret ); - return NULL; - } - memcpy( ret->value, hash->value, sizeof(hash->value) ); - ret->finished = hash->finished; - return ret; + dst->magic = src->magic; + dst->desc = src->desc; + dst->len = src->len; + dst->finished = src->finished; + + SymCryptHashStateCopy( src->desc, &src->state, &dst->state ); + memcpy( dst->value, src->value, sizeof(src->value) ); + return dst; } BOOL WINAPI CPDuplicateHash( HCRYPTPROV hprov, HCRYPTHASH hhash, DWORD *reserved, DWORD flags, HCRYPTHASH *ret_hash ) { - struct hash *hash = (struct hash *)hhash, *ret; + struct hash *src = (struct hash *)hhash, *dst; - TRACE( "%p, %p, %p, %08lx, %p\n", (void *)hprov, (void *)hhash, reserved, flags, ret_hash ); + TRACE( "%IX, %IX, %p, %08lx, %p\n", hprov, hhash, reserved, flags, ret_hash ); - if (hash->magic != MAGIC_HASH) return FALSE; + if (!src || src->magic != MAGIC_HASH) + { + SetLastError( NTE_BAD_HASH ); + return FALSE; + } - if (!(ret = duplicate_hash( hash ))) return FALSE; - *ret_hash = (HCRYPTHASH)ret; + if (!(dst = duplicate_hash( src ))) return FALSE; + *ret_hash = (HCRYPTHASH)dst; return TRUE; } @@ -997,25 +1056,35 @@ BOOL WINAPI CPHashData( HCRYPTPROV hprov, HCRYPTHASH hhash, const BYTE *data, DW { struct hash *hash = (struct hash *)hhash; - TRACE("%p, %p, %p, %lu, %08lx\n", (void *)hprov, (void *)hhash, data, len, flags ); + TRACE("%IX, %IX, %p, %lu, %08lx\n", hprov, hhash, data, len, flags ); - if (hash->magic != MAGIC_HASH) return FALSE; + if (!hash || hash->magic != MAGIC_HASH) + { + SetLastError( NTE_BAD_HASH ); + return FALSE; + } if (hash->finished) { SetLastError( NTE_BAD_HASH_STATE ); return FALSE; } - return !BCryptHashData( hash->handle, (UCHAR *)data, len, 0 ); + + SymCryptHashAppend( hash->desc, &hash->state, data, len ); + return TRUE; } BOOL WINAPI CPGetHashParam( HCRYPTPROV hprov, HCRYPTHASH hhash, DWORD param, BYTE *data, DWORD *len, DWORD flags ) { struct hash *hash = (struct hash *)hhash; - TRACE( "%p, %p, %08lx, %p, %p, %08lx\n", (void *)hprov, (void *)hhash, param, data, len, flags ); + TRACE( "%IX, %IX, %08lx, %p, %p, %08lx\n", hprov, hhash, param, data, len, flags ); - if (hash->magic != MAGIC_HASH) return FALSE; + if (!hash || hash->magic != MAGIC_HASH) + { + SetLastError( NTE_BAD_HASH ); + return FALSE; + } switch (param) { @@ -1033,7 +1102,7 @@ BOOL WINAPI CPGetHashParam( HCRYPTPROV hprov, HCRYPTHASH hhash, DWORD param, BYT case HP_HASHVAL: if (!hash->finished) { - if (BCryptFinishHash( hash->handle, hash->value, hash->len, 0 )) return FALSE; + SymCryptHashResult( hash->desc, &hash->state, hash->value, hash->len ); hash->finished = TRUE; } if (hash->len > *len) @@ -1056,9 +1125,13 @@ BOOL WINAPI CPSetHashParam( HCRYPTPROV hprov, HCRYPTHASH hhash, DWORD param, con { struct hash *hash = (struct hash *)hhash; - TRACE( "%p, %p, %08lx, %p, %08lx\n", (void *)hprov, (void *)hhash, param, data, flags ); + TRACE( "%IX, %IX, %08lx, %p, %08lx\n", hprov, hhash, param, data, flags ); - if (hash->magic != MAGIC_HASH) return FALSE; + if (!hash || hash->magic != MAGIC_HASH) + { + SetLastError( NTE_BAD_HASH ); + return FALSE; + } switch (param) { @@ -1075,6 +1148,7 @@ BOOL WINAPI CPSetHashParam( HCRYPTPROV hprov, HCRYPTHASH hhash, DWORD param, con BOOL WINAPI CPDeriveKey( HCRYPTPROV hprov, ALG_ID algid, HCRYPTHASH hhash, DWORD flags, HCRYPTKEY *ret_key ) { + FIXME( "%p, %p, %08lx, %p\n", (void *)hprov, (void *)hhash, flags, ret_key ); return FALSE; } @@ -1096,84 +1170,77 @@ BOOL WINAPI CPSignHash( HCRYPTPROV hprov, HCRYPTHASH hhash, DWORD keyspec, const { struct container *container = (struct container *)hprov; struct hash *hash = (struct hash *)hhash; - ULONG len, i; - BYTE temp; + ULONG len; - TRACE( "%p, %p, %lu, %s, %08lx, %p, %p\n", (void *)hprov, (void *)hhash, keyspec, debugstr_w(desc), flags, sig, - siglen ); + TRACE( "%IX, %IX, %lu, %s, %08lx, %p, %p\n", hprov, hhash, keyspec, debugstr_w(desc), flags, sig, siglen ); - if (!hash->finished) + if (!container || container->magic != MAGIC_CONTAINER || !container->sign_key || !siglen) { - if (BCryptFinishHash( hash->handle, hash->value, hash->len, 0 )) return FALSE; - hash->finished = TRUE; + SetLastError( ERROR_INVALID_PARAMETER ); + return FALSE; + } + if (!hash || hash->magic != MAGIC_HASH) + { + SetLastError( NTE_BAD_HASH ); + return FALSE; + } + if (!(len = get_signature_length( container->sign_key->algid ))) + { + SetLastError( ERROR_INVALID_PARAMETER ); + return FALSE; } - - 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 (*siglen < len) { *siglen = len; return TRUE; } - if (BCryptSignHash( container->sign_key->handle, NULL, hash->value, hash->len, sig, *siglen, siglen, 0 )) + if (!hash->finished) { - return FALSE; + SymCryptHashResult( hash->desc, &hash->state, hash->value, hash->len ); + hash->finished = TRUE; } - /* Swap the r and s integers in the signature from big-endian to little-endian */ - for (i = 0; i < len / 4; i++) { - /* r */ - temp = sig[i]; - sig[i] = sig[len / 2 - 1 - i]; - sig[len / 2 - 1 - i] = temp; - /* s */ - temp = sig[len / 2 + i]; - sig[len / 2 + i] = sig[len - 1 - i]; - sig[len - 1 - i] = temp; - } + if (SymCryptDsaSign( container->sign_key->handle, hash->value, hash->len, SYMCRYPT_NUMBER_FORMAT_LSB_FIRST, 0, + sig, len )) return FALSE; + *siglen = len; return TRUE; } BOOL WINAPI CPVerifySignature( HCRYPTPROV hprov, HCRYPTHASH hhash, const BYTE *sig, DWORD siglen, HCRYPTKEY hpubkey, const WCHAR *desc, DWORD flags ) { - UCHAR signature[40]; - DWORD i; struct hash *hash = (struct hash *)hhash; struct key *key = (struct key *)hpubkey; + ULONG len; - TRACE( "%p, %p, %p, %lu %p, %s, %08lx\n", (void *)hprov, (void *)hhash, sig, siglen, (void *)hpubkey, - debugstr_w(desc), flags ); + TRACE( "%IX, %IX, %p, %lu %IX, %s, %08lx\n", hprov, hhash, sig, siglen, hpubkey, debugstr_w(desc), flags ); - if (hash->magic != MAGIC_HASH || key->magic != MAGIC_KEY) return FALSE; - if (flags) + if (!hash || hash->magic != MAGIC_HASH || !key || key->magic != MAGIC_KEY) { - FIXME( "flags %08lx not supported\n", flags ); + SetLastError( ERROR_INVALID_PARAMETER ); return FALSE; } - - if (siglen > sizeof(signature)) + if (!(len = get_signature_length( key->algid )) || len != siglen) { - FIXME( "signature longer than 40 bytes is not supported\n"); + SetLastError( ERROR_INVALID_PARAMETER ); return FALSE; } - - /* Swap the r and s integers in the signature from little-endian to big-endian */ - for (i = 0; i < siglen / 2; i++) + if (flags) { - signature[i] = sig[siglen / 2 - 1 - i]; /* r */ - signature[siglen / 2 + i] = sig[siglen - 1 - i]; /* s */ + FIXME( "flags %08lx not supported\n", flags ); + return FALSE; } if (!hash->finished) { - if (BCryptFinishHash( hash->handle, hash->value, hash->len, 0 )) return FALSE; + SymCryptHashResult( hash->desc, &hash->state, hash->value, hash->len ); hash->finished = TRUE; } - return !BCryptVerifySignature( key->handle, NULL, hash->value, hash->len, signature, siglen, 0 ); + if (SymCryptDsaVerify( key->handle, hash->value, hash->len, sig, siglen, SYMCRYPT_NUMBER_FORMAT_LSB_FIRST, 0 )) + return FALSE; + + return TRUE; } diff --git a/dlls/dssenh/tests/dssenh.c b/dlls/dssenh/tests/dssenh.c index 9c9b18ed4ba..c0f2dc39bac 100644 --- a/dlls/dssenh/tests/dssenh.c +++ b/dlls/dssenh/tests/dssenh.c @@ -84,13 +84,7 @@ static void test_acquire_context(void) result = CryptReleaseContext(hProv, 0); ok(result, "CryptReleaseContext failed.\n"); - result = CryptAcquireContextA( - &hProv, NULL, MS_DEF_DSS_PROV_A, PROV_DSS, CRYPT_VERIFYCONTEXT); - if(!result) - { - skip("DSS csp is currently not available, skipping tests.\n"); - return; - } + result = CryptAcquireContextA(&hProv, NULL, MS_DEF_DSS_PROV_A, PROV_DSS, CRYPT_VERIFYCONTEXT); ok(result, "Expected no errors.\n"); result = CryptReleaseContext(hProv, 0); @@ -211,30 +205,30 @@ struct keylength_test { 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, 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, 512 << 16, FALSE, NTE_BAD_ALGID, 0, 1, 1}, + {AT_KEYEXCHANGE, 1024 << 16, FALSE, NTE_BAD_ALGID, 0, 1, 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}, - {AT_SIGNATURE, 513 << 16, FALSE, STATUS_INVALID_PARAMETER, NTE_FAIL}, + {AT_SIGNATURE, 513 << 16, FALSE, STATUS_INVALID_PARAMETER, NTE_FAIL, 0, 1}, {AT_SIGNATURE, 768 << 16, TRUE}, {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, 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, 512 << 16, FALSE, NTE_BAD_ALGID}, + {CALG_DH_EPHEM, 1024 << 16, FALSE, NTE_BAD_ALGID}, {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, 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, 512 << 16, FALSE, NTE_BAD_ALGID, 0, 1, 1}, + {CALG_DH_SF, 1024 << 16, FALSE, NTE_BAD_ALGID, 0, 1, 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}, - {CALG_DSS_SIGN, 513 << 16, FALSE, STATUS_INVALID_PARAMETER, NTE_FAIL}, + {CALG_DSS_SIGN, 513 << 16, FALSE, STATUS_INVALID_PARAMETER, NTE_FAIL, 0, 1}, {CALG_DSS_SIGN, 768 << 16, TRUE}, {CALG_DSS_SIGN, 1024 << 16, TRUE}, {CALG_DSS_SIGN, 1088 << 16, FALSE, NTE_BAD_FLAGS} @@ -243,14 +237,14 @@ 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, 0, 0, 1}, + {AT_KEYEXCHANGE, 512 << 16, TRUE}, {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, 768 << 16, TRUE}, + {AT_KEYEXCHANGE, 1024 << 16, TRUE}, {AT_KEYEXCHANGE, 1088 << 16, FALSE, NTE_BAD_FLAGS}, {AT_SIGNATURE, 448 << 16, FALSE, NTE_BAD_FLAGS}, {AT_SIGNATURE, 512 << 16, TRUE}, - {AT_SIGNATURE, 513 << 16, FALSE, STATUS_INVALID_PARAMETER, NTE_FAIL}, + {AT_SIGNATURE, 513 << 16, FALSE, STATUS_INVALID_PARAMETER, NTE_FAIL, 0, 1}, {AT_SIGNATURE, 768 << 16, TRUE}, {AT_SIGNATURE, 1024 << 16, TRUE}, {AT_SIGNATURE, 1088 << 16, FALSE, NTE_BAD_FLAGS}, @@ -261,14 +255,14 @@ static const struct keylength_test dssDH_keylength[] = { {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, 0, 0, 1}, + {CALG_DH_SF, 512 << 16, TRUE}, {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, 768 << 16, TRUE}, + {CALG_DH_SF, 1024 << 16, TRUE}, {CALG_DH_SF, 1088 << 16, FALSE, NTE_BAD_FLAGS}, {CALG_DSS_SIGN, 448 << 16, FALSE, NTE_BAD_FLAGS}, {CALG_DSS_SIGN, 512 << 16, TRUE}, - {CALG_DSS_SIGN, 513 << 16, FALSE, STATUS_INVALID_PARAMETER, NTE_FAIL}, + {CALG_DSS_SIGN, 513 << 16, FALSE, STATUS_INVALID_PARAMETER, NTE_FAIL, 0, 1}, {CALG_DSS_SIGN, 768 << 16, TRUE}, {CALG_DSS_SIGN, 1024 << 16, TRUE}, {CALG_DSS_SIGN, 1088 << 16, FALSE, NTE_BAD_FLAGS} @@ -277,10 +271,10 @@ 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, 0, 0, 1}, + {AT_KEYEXCHANGE, 512 << 16, TRUE}, {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, 768 << 16, TRUE}, + {AT_KEYEXCHANGE, 1024 << 16, TRUE}, {AT_KEYEXCHANGE, 1088 << 16, TRUE, 0, 0, 1}, {AT_KEYEXCHANGE, 2048 << 16, TRUE, 0, 0, 1}, /* Keylength too large - test bot timeout. @@ -289,7 +283,7 @@ static const struct keylength_test dssENH_keylength[] = { {AT_KEYEXCHANGE, 4160 << 16, FALSE, NTE_BAD_FLAGS}, {AT_SIGNATURE, 448 << 16, FALSE, NTE_BAD_FLAGS}, {AT_SIGNATURE, 512 << 16, TRUE}, - {AT_SIGNATURE, 513 << 16, FALSE, STATUS_INVALID_PARAMETER, NTE_FAIL}, + {AT_SIGNATURE, 513 << 16, FALSE, STATUS_INVALID_PARAMETER, NTE_FAIL, 0, 1}, {AT_SIGNATURE, 768 << 16, TRUE}, {AT_SIGNATURE, 1024 << 16, TRUE}, {AT_SIGNATURE, 1032 << 16, FALSE, NTE_BAD_FLAGS}, @@ -302,16 +296,16 @@ static const struct keylength_test dssENH_keylength[] = { {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, 0, 0, 1}, + {CALG_DH_SF, 512 << 16, TRUE}, {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, 768 << 16, TRUE}, + {CALG_DH_SF, 1024 << 16, TRUE}, {CALG_DH_SF, 1032 << 16, FALSE, NTE_BAD_FLAGS}, {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}, - {CALG_DSS_SIGN, 513 << 16, FALSE, STATUS_INVALID_PARAMETER, NTE_FAIL}, + {CALG_DSS_SIGN, 513 << 16, FALSE, STATUS_INVALID_PARAMETER, NTE_FAIL, 0, 1}, {CALG_DSS_SIGN, 768 << 16, TRUE}, {CALG_DSS_SIGN, 1024 << 16, TRUE}, {CALG_DSS_SIGN, 1088 << 16, FALSE, NTE_BAD_FLAGS} @@ -355,13 +349,7 @@ static void test_keylength(void) BOOL result; /* acquire base dss provider */ - result = CryptAcquireContextA( - &hProv, NULL, MS_DEF_DSS_PROV_A, PROV_DSS, CRYPT_VERIFYCONTEXT); - if(!result) - { - skip("DSSENH is currently not available, skipping key length tests.\n"); - return; - } + result = CryptAcquireContextA(&hProv, NULL, MS_DEF_DSS_PROV_A, PROV_DSS, CRYPT_VERIFYCONTEXT); ok(result, "Expected no errors.\n"); result = CryptGenKey(hProv, AT_SIGNATURE, 0, &key); @@ -452,13 +440,7 @@ static void test_hash(const struct hash_test *tests, int testLen) BOOL result; int i; - result = CryptAcquireContextA( - &hProv, NULL, MS_ENH_DSS_DH_PROV_A, PROV_DSS_DH, CRYPT_VERIFYCONTEXT); - if(!result) - { - skip("DSSENH is currently not available, skipping hashing tests.\n"); - return; - } + result = CryptAcquireContextA(&hProv, NULL, MS_ENH_DSS_DH_PROV_A, PROV_DSS_DH, CRYPT_VERIFYCONTEXT); ok(result, "Expected no errors.\n"); for(i = 0; i < testLen; i++) @@ -485,8 +467,10 @@ static void test_hash(const struct hash_test *tests, int testLen) ok(dataLen == hashLen, "Expected hash length to match.\n"); hashLen = 0xdeadbeef; + memset(hashValue, 0, sizeof(hashValue)); result = CryptGetHashParam(hHash, HP_HASHVAL, hashValue, &hashLen, 0); ok(result, "Expected hash value return.\n"); + ok(dataLen == hashLen, "Expected hash length to match.\n"); ok(dataLen == hashLen, "Expected hash length to match.\n"); ok(!memcmp(hashValue, tests[i].hash, tests[i].hashLen), "Incorrect hash output.\n"); @@ -613,13 +597,7 @@ static void test_data_encryption(const struct encrypt_test *tests, int testLen) /* acquire dss enhanced provider */ SetLastError(0xdeadbeef); - result = CryptAcquireContextA( - &hProv, NULL, MS_ENH_DSS_DH_PROV_A, PROV_DSS_DH, CRYPT_VERIFYCONTEXT); - if (!result) - { - skip("DSSENH is currently not available, skipping encryption tests.\n"); - return; - } + result = CryptAcquireContextA(&hProv, NULL, MS_ENH_DSS_DH_PROV_A, PROV_DSS_DH, CRYPT_VERIFYCONTEXT); ok(result, "Expected no errors.\n"); /* testing various encryption algorithms */ @@ -709,13 +687,7 @@ static void test_cipher_modes(const struct ciphermode_test *tests, int testLen) /* acquire dss enhanced provider */ SetLastError(0xdeadbeef); - result = CryptAcquireContextA( - &hProv, NULL, MS_ENH_DSS_DH_PROV_A, PROV_DSS_DH, CRYPT_VERIFYCONTEXT); - if (!result) - { - skip("DSSENH is currently not available, skipping block cipher mode tests.\n"); - return; - } + result = CryptAcquireContextA(&hProv, NULL, MS_ENH_DSS_DH_PROV_A, PROV_DSS_DH, CRYPT_VERIFYCONTEXT); ok(result, "Expected no errors.\n"); SetLastError(0xdeadbeef); @@ -1063,18 +1035,23 @@ static void test_signhash(HCRYPTPROV hProv, const struct signature_test *test) ok(result, "Failed to destroy private key, got %lx\n", GetLastError()); } +#define MAGIC_DSS1 ('D' | ('S' << 8) | ('S' << 16) | ('1' << 24)) + static void test_exportkey(HCRYPTPROV hProv, const struct signature_test *test) { HCRYPTKEY privKey = 0; BYTE pubKeyBuffer[512]; DWORD pubKeyLen; BOOL result; + const BLOBHEADER *hdr = (const BLOBHEADER *)pubKeyBuffer; + const DSSPUBKEY *dsskey = (const DSSPUBKEY *)(hdr + 1); /* Get a private key of array specified ALG_ID */ SetLastError(0xdeadbeef); result = CryptImportKey(hProv, test->privateKey, test->privateKeyLen, 0, 0, &privKey); ok(result, "Failed to imported key, got %lx\n", GetLastError()); + pubKeyLen = 0; SetLastError(0xdeadbeef); result = CryptExportKey(privKey, 0, PUBLICKEYBLOB, 0, NULL, &pubKeyLen); ok(result, "Failed to acquire public key length, got %lx\n", GetLastError()); @@ -1086,6 +1063,7 @@ static void test_exportkey(HCRYPTPROV hProv, const struct signature_test *test) SetLastError(0xdeadbeef); result = CryptExportKey(privKey, 0, PUBLICKEYBLOB, 0, pubKeyBuffer, &pubKeyLen); ok(result, "Failed to export public key, got %lx\n", GetLastError()); + ok(dsskey->magic == MAGIC_DSS1, "got %lx\n", dsskey->magic); ok(memcmp(test->publicKey, pubKeyBuffer, test->publicKeyLen) == 0, "The exported public key doesn't match the expected public key\n"); @@ -1140,11 +1118,6 @@ static void test_signature(void) /* acquire base dss provider */ SetLastError(0xdeadbeef); result = CryptAcquireContextA(&hProv[0], NULL, MS_DEF_DSS_PROV_A, PROV_DSS, 0); - if(!result) - { - skip("DSSENH is currently not available, skipping signature verification tests.\n"); - return; - } ok(result, "Failed to acquire CSP, got %lx\n", GetLastError()); /* acquire diffie hellman dss provider */ @@ -1273,20 +1246,20 @@ static void test_keyExchange_baseDSS(HCRYPTPROV hProv, const struct keyExchange_ /* Generate key exchange keys for user1 and user2 */ result = CryptGenKey(hProv, tests[i].algid, 512 << 16 | CRYPT_PREGEN, &privKey1); - if (!result) - { - skip("skipping key exchange tests\n"); - return; - } - ok(!result && GetLastError() == NTE_BAD_ALGID, + todo_wine ok(!result && GetLastError() == NTE_BAD_ALGID, "Expected NTE_BAD_ALGID, got %lx\n", GetLastError()); result = CryptGenKey(hProv, tests[i].algid, 512 << 16 | CRYPT_PREGEN, &privKey2); - ok(!result && GetLastError() == NTE_BAD_ALGID, + todo_wine ok(!result && GetLastError() == NTE_BAD_ALGID, "Expected NTE_BAD_ALGID, got %lx\n", GetLastError()); /* Set the prime and generator values, which are agreed upon */ result = CryptSetKeyParam(privKey1, KP_P, (BYTE *)&Prime, 0); + if (!result) + { + skip("skipping key exchange tests\n"); + return; + } ok(!result && GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %lx\n", GetLastError()); @@ -1427,11 +1400,6 @@ static void test_keyExchange_dssDH(HCRYPTPROV hProv, const struct keyExchange_te /* Generate key exchange keys for user1 and user2 */ result = CryptGenKey(hProv, tests[i].algid, 512 << 16 | CRYPT_PREGEN, &privKey1); - if (!result) - { - skip("skipping key exchange tests\n"); - return; - } ok(result, "Failed to generate a key for user1, got %lx\n", GetLastError()); result = CryptGenKey(hProv, tests[i].algid, 512 << 16 | CRYPT_PREGEN, &privKey2); @@ -1439,6 +1407,11 @@ static void test_keyExchange_dssDH(HCRYPTPROV hProv, const struct keyExchange_te /* Set the prime and generator values, which are agreed upon */ result = CryptSetKeyParam(privKey1, KP_P, (BYTE *)&Prime, 0); + if (!result) + { + skip("skipping key exchange tests\n"); + return; + } ok(result, "Failed to set prime for user 1's key, got %lx\n", GetLastError()); result = CryptSetKeyParam(privKey2, KP_P, (BYTE *)&Prime, 0); @@ -1532,11 +1505,6 @@ static void test_key_exchange(void) /* acquire base dss provider */ result = CryptAcquireContextA(&hProv, NULL, MS_DEF_DSS_PROV_A, PROV_DSS, CRYPT_VERIFYCONTEXT); - if(!result) - { - skip("DSSENH is currently not available, skipping shared key tests.\n"); - return; - } ok(result, "Failed to acquire CSP.\n"); test_keyExchange_baseDSS(hProv, baseDSSkey_data, ARRAY_SIZE(baseDSSkey_data)); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/11059