bcrypt: Add support for BCRYPT_DSA_ALGORITHM.

Signed-off-by: Hans Leidekker <hans@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
feature/deterministic
Hans Leidekker 2020-05-29 11:29:06 +02:00 committed by Alexandre Julliard
parent d1ae4a5647
commit c2a4a4ec3c
5 changed files with 369 additions and 21 deletions

View File

@ -137,6 +137,7 @@ enum alg_id
ALG_ID_RSA_SIGN,
ALG_ID_ECDSA_P256,
ALG_ID_ECDSA_P384,
ALG_ID_DSA,
/* rng */
ALG_ID_RNG,

View File

@ -118,6 +118,7 @@ builtin_algorithms[] =
{ BCRYPT_RSA_SIGN_ALGORITHM, BCRYPT_SIGNATURE_INTERFACE, 0, 0, 0 },
{ BCRYPT_ECDSA_P256_ALGORITHM, BCRYPT_SIGNATURE_INTERFACE, 0, 0, 0 },
{ BCRYPT_ECDSA_P384_ALGORITHM, BCRYPT_SIGNATURE_INTERFACE, 0, 0, 0 },
{ BCRYPT_DSA_ALGORITHM, BCRYPT_SIGNATURE_INTERFACE, 0, 0, 0 },
{ BCRYPT_RNG_ALGORITHM, BCRYPT_RNG_INTERFACE, 0, 0, 0 },
};
@ -541,6 +542,13 @@ static NTSTATUS get_rsa_property( enum mode_id mode, const WCHAR *prop, UCHAR *b
return STATUS_NOT_IMPLEMENTED;
}
static NTSTATUS get_dsa_property( enum mode_id mode, const WCHAR *prop, UCHAR *buf, ULONG size, ULONG *ret_size )
{
if (!strcmpW( prop, BCRYPT_PADDING_SCHEMES )) return STATUS_NOT_SUPPORTED;
FIXME( "unsupported property %s\n", debugstr_w(prop) );
return STATUS_NOT_IMPLEMENTED;
}
NTSTATUS get_alg_property( const struct algorithm *alg, const WCHAR *prop, UCHAR *buf, ULONG size, ULONG *ret_size )
{
NTSTATUS status;
@ -557,11 +565,14 @@ NTSTATUS get_alg_property( const struct algorithm *alg, const WCHAR *prop, UCHAR
case ALG_ID_RSA:
return get_rsa_property( alg->mode, prop, buf, size, ret_size );
case ALG_ID_DSA:
return get_dsa_property( alg->mode, prop, buf, size, ret_size );
default:
break;
}
FIXME( "unsupported property %s\n", debugstr_w(prop) );
FIXME( "unsupported property %s algorithm %u\n", debugstr_w(prop), alg->id );
return STATUS_NOT_IMPLEMENTED;
}
@ -924,15 +935,8 @@ static NTSTATUS key_export( struct key *key, const WCHAR *type, UCHAR *output, U
memcpy( output + sizeof(len), key->u.s.secret, key->u.s.secret_len );
return STATUS_SUCCESS;
}
else if (!strcmpW( type, BCRYPT_RSAPUBLIC_BLOB ))
{
*size = key->u.a.pubkey_len;
if (output_len < key->u.a.pubkey_len) return STATUS_SUCCESS;
memcpy( output, key->u.a.pubkey, key->u.a.pubkey_len );
return STATUS_SUCCESS;
}
else if (!strcmpW( type, BCRYPT_ECCPUBLIC_BLOB ))
else if (!strcmpW( type, BCRYPT_RSAPUBLIC_BLOB ) || !strcmpW( type, BCRYPT_DSA_PUBLIC_BLOB ) ||
!strcmpW( type, BCRYPT_ECCPUBLIC_BLOB ))
{
*size = key->u.a.pubkey_len;
if (output_len < key->u.a.pubkey_len) return STATUS_SUCCESS;
@ -1241,6 +1245,28 @@ static NTSTATUS key_import_pair( struct algorithm *alg, const WCHAR *type, BCRYP
*ret_key = key;
return STATUS_SUCCESS;
}
else if (!strcmpW( type, BCRYPT_DSA_PUBLIC_BLOB ))
{
BCRYPT_DSA_KEY_BLOB *dsa_blob = (BCRYPT_DSA_KEY_BLOB *)input;
ULONG size;
if (input_len < sizeof(*dsa_blob)) return STATUS_INVALID_PARAMETER;
if ((alg->id != ALG_ID_DSA) || dsa_blob->dwMagic != BCRYPT_DSA_PUBLIC_MAGIC)
return STATUS_NOT_SUPPORTED;
if (!(key = heap_alloc_zero( sizeof(*key) ))) return STATUS_NO_MEMORY;
key->hdr.magic = MAGIC_KEY;
size = sizeof(*dsa_blob) + dsa_blob->cbKey * 3;
if ((status = key_asymmetric_init( key, alg, dsa_blob->cbKey * 8, (BYTE *)dsa_blob, size )))
{
heap_free( key );
return status;
}
*ret_key = key;
return STATUS_SUCCESS;
}
FIXME( "unsupported key type %s\n", debugstr_w(type) );
return STATUS_NOT_SUPPORTED;

View File

@ -75,7 +75,11 @@ static int (*pgnutls_pubkey_verify_hash2)(gnutls_pubkey_t, gnutls_sign_algorithm
const gnutls_datum_t *, const gnutls_datum_t *);
/* Not present in gnutls version < 2.11.0 */
static int (*pgnutls_pubkey_import_rsa_raw)(gnutls_pubkey_t key, const gnutls_datum_t *m, const gnutls_datum_t *e);
static int (*pgnutls_pubkey_import_rsa_raw)(gnutls_pubkey_t, const gnutls_datum_t *, const gnutls_datum_t *);
/* Not present in gnutls version < 2.12.0 */
static int (*pgnutls_pubkey_import_dsa_raw)(gnutls_pubkey_t, const gnutls_datum_t *, const gnutls_datum_t *,
const gnutls_datum_t *, const gnutls_datum_t *);
/* Not present in gnutls version < 3.3.0 */
static int (*pgnutls_privkey_export_ecc_raw)(gnutls_privkey_t, gnutls_ecc_curve_t *,
@ -83,6 +87,8 @@ static int (*pgnutls_privkey_export_ecc_raw)(gnutls_privkey_t, gnutls_ecc_curve_
static int (*pgnutls_privkey_export_rsa_raw)(gnutls_privkey_t, gnutls_datum_t *, gnutls_datum_t *, gnutls_datum_t *,
gnutls_datum_t *, gnutls_datum_t *, gnutls_datum_t *, gnutls_datum_t *,
gnutls_datum_t *);
static int (*pgnutls_privkey_export_dsa_raw)(gnutls_privkey_t, gnutls_datum_t *, gnutls_datum_t *, gnutls_datum_t *,
gnutls_datum_t *, gnutls_datum_t *);
static int (*pgnutls_privkey_generate)(gnutls_privkey_t, gnutls_pk_algorithm_t, unsigned int, unsigned int);
/* Not present in gnutls version < 3.6.0 */
@ -142,6 +148,12 @@ static int compat_gnutls_privkey_import_ecc_raw(gnutls_privkey_t key, gnutls_ecc
return GNUTLS_E_UNKNOWN_PK_ALGORITHM;
}
static int compat_gnutls_privkey_export_dsa_raw(gnutls_privkey_t key, gnutls_datum_t *p, gnutls_datum_t *q,
gnutls_datum_t *g, gnutls_datum_t *y, gnutls_datum_t *x)
{
return GNUTLS_E_UNKNOWN_PK_ALGORITHM;
}
static gnutls_sign_algorithm_t compat_gnutls_pk_to_sign(gnutls_pk_algorithm_t pk, gnutls_digest_algorithm_t hash)
{
return GNUTLS_SIGN_UNKNOWN;
@ -159,6 +171,12 @@ static int compat_gnutls_pubkey_import_rsa_raw(gnutls_pubkey_t key, const gnutls
return GNUTLS_E_UNKNOWN_PK_ALGORITHM;
}
static int compat_gnutls_pubkey_import_dsa_raw(gnutls_pubkey_t key, const gnutls_datum_t *p, const gnutls_datum_t *q,
const gnutls_datum_t *g, const gnutls_datum_t *y)
{
return GNUTLS_E_UNKNOWN_PK_ALGORITHM;
}
static int compat_gnutls_privkey_generate(gnutls_privkey_t key, gnutls_pk_algorithm_t algo, unsigned int bits,
unsigned int flags)
{
@ -244,6 +262,11 @@ BOOL gnutls_initialize(void)
WARN("gnutls_privkey_import_ecc_raw not found\n");
pgnutls_privkey_import_ecc_raw = compat_gnutls_privkey_import_ecc_raw;
}
if (!(pgnutls_privkey_export_dsa_raw = dlsym( libgnutls_handle, "gnutls_privkey_export_dsa_raw" )))
{
WARN("gnutls_privkey_export_dsa_raw not found\n");
pgnutls_privkey_export_dsa_raw = compat_gnutls_privkey_export_dsa_raw;
}
if (!(pgnutls_pk_to_sign = dlsym( libgnutls_handle, "gnutls_pk_to_sign" )))
{
WARN("gnutls_pk_to_sign not found\n");
@ -259,6 +282,11 @@ BOOL gnutls_initialize(void)
WARN("gnutls_pubkey_import_rsa_raw not found\n");
pgnutls_pubkey_import_rsa_raw = compat_gnutls_pubkey_import_rsa_raw;
}
if (!(pgnutls_pubkey_import_dsa_raw = dlsym( libgnutls_handle, "gnutls_pubkey_import_dsa_raw" )))
{
WARN("gnutls_pubkey_import_dsa_raw not found\n");
pgnutls_pubkey_import_dsa_raw = compat_gnutls_pubkey_import_dsa_raw;
}
if (!(pgnutls_privkey_generate = dlsym( libgnutls_handle, "gnutls_privkey_generate" )))
{
WARN("gnutls_privkey_generate not found\n");
@ -704,6 +732,80 @@ static NTSTATUS export_gnutls_pubkey_ecc( gnutls_privkey_t gnutls_key, UCHAR **p
return STATUS_SUCCESS;
}
static NTSTATUS export_gnutls_pubkey_dsa( gnutls_privkey_t gnutls_key, ULONG bitlen, UCHAR **pubkey, ULONG *pubkey_len )
{
BCRYPT_DSA_KEY_BLOB *dsa_blob;
gnutls_datum_t p, q, g, y;
UCHAR *dst, *src;
int ret;
if ((ret = pgnutls_privkey_export_dsa_raw( gnutls_key, &p, &q, &g, &y, NULL )))
{
pgnutls_perror( ret );
return STATUS_INTERNAL_ERROR;
}
if (bitlen > 1024)
{
FIXME( "bitlen > 1024 not supported\n" );
return STATUS_NOT_IMPLEMENTED;
}
if (!(dsa_blob = heap_alloc( sizeof(*dsa_blob) + p.size + g.size + y.size )))
{
pgnutls_perror( ret );
free( p.data ); free( q.data ); free( g.data ); free( y.data );
return STATUS_NO_MEMORY;
}
dst = (UCHAR *)(dsa_blob + 1);
if (p.size == bitlen / 8 + 1 && !p.data[0])
{
src = p.data + 1;
p.size--;
}
else src = p.data;
memcpy( dst, src, p.size );
dst += p.size;
if (g.size == bitlen / 8 + 1 && !g.data[0])
{
src = g.data + 1;
g.size--;
}
else src = g.data;
memcpy( dst, src, g.size );
dst += g.size;
if (y.size == bitlen / 8 + 1 && !y.data[0])
{
src = y.data + 1;
y.size--;
}
else src = y.data;
memcpy( dst, src, y.size );
dst = dsa_blob->q;
if (q.size == sizeof(dsa_blob->q) + 1 && !q.data[0])
{
src = q.data + 1;
q.size--;
}
else src = q.data;
memcpy( dst, src, sizeof(dsa_blob->q) );
dsa_blob->dwMagic = BCRYPT_DSA_PUBLIC_MAGIC;
dsa_blob->cbKey = bitlen / 8;
memset( dsa_blob->Count, 0, sizeof(dsa_blob->Count) ); /* FIXME */
memset( dsa_blob->Seed, 0, sizeof(dsa_blob->Seed) ); /* FIXME */
*pubkey = (UCHAR *)dsa_blob;
*pubkey_len = sizeof(*dsa_blob) + p.size + g.size + y.size;
free( p.data ); free( q.data ); free( g.data ); free( y.data );
return STATUS_SUCCESS;
}
NTSTATUS key_asymmetric_generate( struct key *key )
{
gnutls_pk_algorithm_t pk_alg;
@ -722,6 +824,11 @@ NTSTATUS key_asymmetric_generate( struct key *key )
bitlen = key->u.a.bitlen;
break;
case ALG_ID_DSA:
pk_alg = GNUTLS_PK_DSA;
bitlen = key->u.a.bitlen;
break;
case ALG_ID_ECDH_P256:
case ALG_ID_ECDSA_P256:
pk_alg = GNUTLS_PK_ECC; /* compatible with ECDSA and ECDH */
@ -756,6 +863,10 @@ NTSTATUS key_asymmetric_generate( struct key *key )
status = export_gnutls_pubkey_ecc( handle, &key->u.a.pubkey, &key->u.a.pubkey_len );
break;
case GNUTLS_PK_DSA:
status = export_gnutls_pubkey_dsa( handle, key->u.a.bitlen, &key->u.a.pubkey, &key->u.a.pubkey_len );
break;
default:
ERR( "unhandled algorithm %u\n", pk_alg );
return STATUS_INTERNAL_ERROR;
@ -889,6 +1000,7 @@ NTSTATUS key_asymmetric_init( struct key *key, struct algorithm *alg, ULONG bitl
case ALG_ID_ECDSA_P384:
case ALG_ID_RSA:
case ALG_ID_RSA_SIGN:
case ALG_ID_DSA:
break;
default:
@ -975,6 +1087,38 @@ static NTSTATUS import_gnutls_pubkey_rsa( struct key *key, gnutls_pubkey_t *gnut
return STATUS_SUCCESS;
}
static NTSTATUS import_gnutls_pubkey_dsa( struct key *key, gnutls_pubkey_t *gnutls_key )
{
BCRYPT_DSA_KEY_BLOB *dsa_blob;
gnutls_datum_t p, q, g, y;
int ret;
if ((ret = pgnutls_pubkey_init( gnutls_key )))
{
pgnutls_perror( ret );
return STATUS_INTERNAL_ERROR;
}
dsa_blob = (BCRYPT_DSA_KEY_BLOB *)key->u.a.pubkey;
p.data = key->u.a.pubkey + sizeof(*dsa_blob);
p.size = dsa_blob->cbKey;
q.data = dsa_blob->q;
q.size = sizeof(dsa_blob->q);
g.data = key->u.a.pubkey + sizeof(*dsa_blob) + dsa_blob->cbKey;
g.size = dsa_blob->cbKey;
y.data = key->u.a.pubkey + sizeof(*dsa_blob) + dsa_blob->cbKey * 2;
y.size = dsa_blob->cbKey;
if ((ret = pgnutls_pubkey_import_dsa_raw( *gnutls_key, &p, &q, &g, &y )))
{
pgnutls_perror( ret );
pgnutls_pubkey_deinit( *gnutls_key );
return STATUS_INTERNAL_ERROR;
}
return STATUS_SUCCESS;
}
static NTSTATUS import_gnutls_pubkey( struct key *key, gnutls_pubkey_t *gnutls_key )
{
switch (key->alg_id)
@ -987,13 +1131,16 @@ static NTSTATUS import_gnutls_pubkey( struct key *key, gnutls_pubkey_t *gnutls_k
case ALG_ID_RSA_SIGN:
return import_gnutls_pubkey_rsa( key, gnutls_key );
case ALG_ID_DSA:
return import_gnutls_pubkey_dsa( key, gnutls_key );
default:
FIXME("algorithm %u not yet supported\n", key->alg_id );
return STATUS_NOT_IMPLEMENTED;
}
}
static NTSTATUS prepare_gnutls_signature_ecc( struct key *key, UCHAR *signature, ULONG signature_len,
static NTSTATUS prepare_gnutls_signature_dsa( struct key *key, UCHAR *signature, ULONG signature_len,
gnutls_datum_t *gnutls_signature )
{
struct buffer buffer;
@ -1030,7 +1177,8 @@ static NTSTATUS prepare_gnutls_signature( struct key *key, UCHAR *signature, ULO
{
case ALG_ID_ECDSA_P256:
case ALG_ID_ECDSA_P384:
return prepare_gnutls_signature_ecc( key, signature, signature_len, gnutls_signature );
case ALG_ID_DSA:
return prepare_gnutls_signature_dsa( key, signature, signature_len, gnutls_signature );
case ALG_ID_RSA:
case ALG_ID_RSA_SIGN:
@ -1101,6 +1249,18 @@ NTSTATUS key_asymmetric_verify( struct key *key, void *padding, UCHAR *hash, ULO
pk_alg = GNUTLS_PK_RSA;
break;
}
case ALG_ID_DSA:
{
if (flags) FIXME( "flags %08x not supported\n", flags );
if (hash_len != 20)
{
FIXME( "hash size %u not supported\n", hash_len );
return STATUS_INVALID_PARAMETER;
}
hash_alg = GNUTLS_DIG_SHA1;
pk_alg = GNUTLS_PK_DSA;
break;
}
default:
FIXME( "algorithm %u not yet supported\n", key->alg_id );
return STATUS_NOT_IMPLEMENTED;
@ -1134,6 +1294,7 @@ static unsigned int get_signature_length( enum alg_id id )
{
case ALG_ID_ECDSA_P256: return 64;
case ALG_ID_ECDSA_P384: return 96;
case ALG_ID_DSA: return 40;
default:
FIXME( "unhandled algorithm %u\n", id );
return 0;
@ -1155,6 +1316,7 @@ static NTSTATUS format_gnutls_signature( enum alg_id type, gnutls_datum_t signat
}
case ALG_ID_ECDSA_P256:
case ALG_ID_ECDSA_P384:
case ALG_ID_DSA:
{
int err;
unsigned int pad_size, sig_len = get_signature_length( type );
@ -1230,6 +1392,16 @@ NTSTATUS key_asymmetric_sign( struct key *key, void *padding, UCHAR *input, ULON
return STATUS_INVALID_PARAMETER;
}
}
else if (key->alg_id == ALG_ID_DSA)
{
if (flags) FIXME( "flags %08x not supported\n", flags );
if (input_len != 20)
{
FIXME( "hash size %u not supported\n", input_len );
return STATUS_INVALID_PARAMETER;
}
hash_alg = GNUTLS_DIG_SHA1;
}
else if (flags == BCRYPT_PAD_PKCS1)
{
if (!pad || !pad->pszAlgId)

View File

@ -2422,6 +2422,101 @@ static void test_BcryptDeriveKeyCapi(void)
ok(!ret, "got %08x\n", ret);
}
static UCHAR dsaHash[] =
{
0x7e,0xe3,0x74,0xe7,0xc5,0x0b,0x6b,0x70,0xdb,0xab,0x32,0x6d,0x1d,0x51,0xd6,0x74,0x79,0x8e,0x5b,0x4b
};
static UCHAR dsaSignature[] =
{
0x5f,0x95,0x1f,0x08,0x19,0x44,0xa5,0xab,0x28,0x11,0x51,0x68,0x82,0x9b,0xe4,0xc3,0x04,0x1b,0xc9,0xdc,
0x41,0x2a,0x89,0xd4,0x4a,0x8b,0x86,0xaf,0x98,0x2c,0x59,0x0b,0xd2,0x88,0xf6,0xe8,0x29,0x13,0x84,0x49
};
static UCHAR dsaPublicBlob[] =
{
0x44,0x53,0x50,0x42,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x8f,0xd2,0x92,0xbb,0x92,0xb9,0x00,0xc5,0xed,
0x52,0xcc,0x48,0x4a,0x44,0x1d,0xd3,0x74,0xfb,0x75,0xd1,0x7e,0xb6,0x24,0x9b,0x5d,0x57,0x0a,0x8a,0xc4,
0x5d,0xab,0x9c,0x26,0x86,0xc6,0x25,0x16,0x20,0xf9,0xa9,0x71,0xbc,0x1d,0x30,0xc4,0xef,0x8c,0xc4,0xdf,
0x1a,0xaf,0x96,0xdf,0x90,0xd8,0x85,0x9d,0xf9,0x2c,0x86,0x8c,0x91,0x39,0x6c,0x6d,0x11,0x4e,0x53,0x63,
0x2a,0x2b,0x26,0xa7,0xf9,0x76,0x74,0x51,0xbf,0x08,0x87,0x6f,0xe0,0x71,0x91,0x24,0x8a,0xc2,0x84,0x2d,
0x84,0x9c,0x5f,0x94,0xaa,0x38,0x53,0x77,0x84,0xba,0xbc,0xff,0x49,0x3a,0x08,0x0f,0x38,0xb5,0x91,0x5c,
0x06,0x15,0xa4,0x27,0xf4,0xa5,0x59,0xaa,0x1c,0x41,0xa3,0xa0,0xbb,0xf7,0x32,0x86,0xfb,0x94,0x41,0xff,
0xcd,0xed,0x69,0xeb,0xc6,0x5e,0xb6,0xa8,0x15,0x82,0x3b,0x60,0x1e,0x91,0x55,0xd5,0x2c,0xa5,0x74,0x5a,
0x65,0x8f,0xc6,0x56,0xc4,0x3f,0x4e,0xe3,0x3a,0x71,0xb2,0x63,0x66,0xa4,0x0d,0x0d,0xf9,0xdd,0x1e,0x48,
0x81,0xe9,0xbf,0x8f,0xbb,0x85,0x47,0x81,0x68,0x11,0xb5,0x91,0x6b,0xc4,0x05,0xef,0xa3,0xc7,0xbf,0x26,
0x53,0x4f,0xc4,0x10,0xfd,0xfa,0xed,0x61,0x64,0xd6,0x2e,0xad,0x04,0x3e,0x82,0xed,0xb2,0x22,0x76,0xd0,
0x44,0xad,0xc1,0x4c,0xde,0x33,0xa3,0x61,0x55,0xec,0x24,0xe5,0x79,0x45,0xcf,0x94,0x39,0x92,0x9f,0xd8,
0x24,0xce,0x85,0xb9
};
static void test_DSA(void)
{
BCRYPT_ALG_HANDLE alg;
BCRYPT_KEY_HANDLE key;
BCRYPT_DSA_KEY_BLOB *dsablob;
UCHAR sig[40], schemes;
ULONG len, size;
NTSTATUS ret;
BYTE *buf;
ret = pBCryptOpenAlgorithmProvider(&alg, BCRYPT_DSA_ALGORITHM, NULL, 0);
ok(!ret, "got %08x\n", ret);
ret = pBCryptGetProperty(alg, L"PaddingSchemes", (UCHAR *)&schemes, sizeof(schemes), &size, 0);
ok(ret == STATUS_NOT_SUPPORTED, "got %08x\n", ret);
ret = pBCryptImportKeyPair(alg, NULL, BCRYPT_DSA_PUBLIC_BLOB, &key, dsaPublicBlob, sizeof(dsaPublicBlob), 0);
ok(!ret, "got %08x\n", ret);
ret = pBCryptVerifySignature(key, NULL, dsaHash, sizeof(dsaHash), dsaSignature, sizeof(dsaSignature), 0);
ok(!ret, "got %08x\n", ret);
ret = pBCryptDestroyKey(key);
ok(!ret, "got %08x\n", ret);
/* sign/verify with export/import round-trip */
ret = pBCryptGenerateKeyPair(alg, &key, 512, 0);
ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
ret = pBCryptFinalizeKeyPair(key, 0);
ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
len = 0;
memset(sig, 0, sizeof(sig));
ret = pBCryptSignHash(key, NULL, dsaHash, sizeof(dsaHash), sig, sizeof(sig), &len, 0);
ok(!ret, "got %08x\n", ret);
ok(len == 40, "got %u\n", len);
size = 0;
ret = pBCryptExportKey(key, NULL, BCRYPT_DSA_PUBLIC_BLOB, NULL, 0, &size, 0);
ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
ok(size, "size not set\n");
buf = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
ret = pBCryptExportKey(key, NULL, BCRYPT_DSA_PUBLIC_BLOB, buf, size, &size, 0);
ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
dsablob = (BCRYPT_DSA_KEY_BLOB *)buf;
ok(dsablob->dwMagic == BCRYPT_DSA_PUBLIC_MAGIC, "got %08x\n", dsablob->dwMagic);
ok(dsablob->cbKey == 64, "got %u\n", dsablob->cbKey);
ok(size == sizeof(*dsablob) + dsablob->cbKey * 3, "got %u\n", size);
ret = pBCryptDestroyKey(key);
ok(!ret, "got %08x\n", ret);
ret = pBCryptImportKeyPair(alg, NULL, BCRYPT_DSA_PUBLIC_BLOB, &key, buf, size, 0);
ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
HeapFree(GetProcessHeap(), 0, buf);
ret = pBCryptVerifySignature(key, NULL, dsaHash, sizeof(dsaHash), sig, len, 0);
ok(!ret, "got %08x\n", ret);
ret = pBCryptDestroyKey(key);
ok(!ret, "got %08x\n", ret);
ret = pBCryptCloseAlgorithmProvider(alg, 0);
ok(!ret, "got %08x\n", ret);
}
START_TEST(bcrypt)
{
HMODULE module;
@ -2486,6 +2581,7 @@ START_TEST(bcrypt)
test_BCryptEnumAlgorithms();
test_aes_vector();
test_BcryptDeriveKeyCapi();
test_DSA();
FreeLibrary(module);
}

View File

@ -66,14 +66,25 @@ typedef LONG NTSTATUS;
#define BCRYPT_ECCPRIVATE_BLOB L"ECCPRIVATEBLOB"
#define BCRYPT_RSAPUBLIC_BLOB L"RSAPUBLICBLOB"
#define BCRYPT_RSAPRIVATE_BLOB L"RSAPRIVATEBLOB"
#define BCRYPT_DSA_PUBLIC_BLOB L"DSAPUBLICBLOB"
#define BCRYPT_DSA_PRIVATE_BLOB L"DSAPRIVATEBLOB"
#define MS_PRIMITIVE_PROVIDER L"Microsoft Primitive Provider"
#define MS_PLATFORM_CRYPTO_PROVIDER L"Microsoft Platform Crypto Provider"
#define BCRYPT_3DES_ALGORITHM L"3DES"
#define BCRYPT_AES_ALGORITHM L"AES"
#define BCRYPT_DES_ALGORITHM L"DES"
#define BCRYPT_DSA_ALGORITHM L"DSA"
#define BCRYPT_ECDH_P256_ALGORITHM L"ECDH_P256"
#define BCRYPT_ECDSA_P256_ALGORITHM L"ECDSA_P256"
#define BCRYPT_ECDSA_P384_ALGORITHM L"ECDSA_P384"
#define BCRYPT_ECDSA_P521_ALGORITHM L"ECDSA_P521"
#define BCRYPT_MD2_ALGORITHM L"MD2"
#define BCRYPT_MD4_ALGORITHM L"MD4"
#define BCRYPT_MD5_ALGORITHM L"MD5"
#define BCRYPT_RC2_ALGORITHM L"RC2"
#define BCRYPT_RC4_ALGORITHM L"RC4"
#define BCRYPT_RNG_ALGORITHM L"RNG"
#define BCRYPT_RSA_ALGORITHM L"RSA"
#define BCRYPT_RSA_SIGN_ALGORITHM L"RSA_SIGN"
@ -81,10 +92,6 @@ typedef LONG NTSTATUS;
#define BCRYPT_SHA256_ALGORITHM L"SHA256"
#define BCRYPT_SHA384_ALGORITHM L"SHA384"
#define BCRYPT_SHA512_ALGORITHM L"SHA512"
#define BCRYPT_ECDH_P256_ALGORITHM L"ECDH_P256"
#define BCRYPT_ECDSA_P256_ALGORITHM L"ECDSA_P256"
#define BCRYPT_ECDSA_P384_ALGORITHM L"ECDSA_P384"
#define BCRYPT_ECDSA_P521_ALGORITHM L"ECDSA_P521"
#define BCRYPT_CHAIN_MODE_NA L"ChainingModeN/A"
#define BCRYPT_CHAIN_MODE_CBC L"ChainingModeCBC"
@ -124,16 +131,27 @@ static const WCHAR BCRYPT_ECCPUBLIC_BLOB[] = {'E','C','C','P','U','B','L','I','C
static const WCHAR BCRYPT_ECCPRIVATE_BLOB[] = {'E','C','C','P','R','I','V','A','T','E','B','L','O','B',0};
static const WCHAR BCRYPT_RSAPUBLIC_BLOB[] = {'R','S','A','P','U','B','L','I','C','B','L','O','B',0};
static const WCHAR BCRYPT_RSAPRIVATE_BLOB[] = {'R','S','A','P','R','I','V','A','T','E','B','L','O','B',0};
static const WCHAR BCRYPT_DSA_PUBLIC_BLOB[] = {'D','S','A','P','U','B','L','I','C','B','L','O','B',0};
static const WCHAR BCRYPT_DSA_PRIVATE_BLOB[] = {'D','S','A','P','R','I','V','A','T','E','B','L','O','B',0};
static const WCHAR MS_PRIMITIVE_PROVIDER[] = \
{'M','i','c','r','o','s','o','f','t',' ','P','r','i','m','i','t','i','v','e',' ','P','r','o','v','i','d','e','r',0};
static const WCHAR MS_PLATFORM_CRYPTO_PROVIDER[] = \
{'M','i','c','r','o','s','o','f','t',' ','P','l','a','t','f','o','r','m',' ','C','r','y','p','t','o',' ','P','r','o','v','i','d','e','r',0};
static const WCHAR BCRYPT_3DES_ALGORITHM[] = {'3','D','E','S',0};
static const WCHAR BCRYPT_AES_ALGORITHM[] = {'A','E','S',0};
static const WCHAR BCRYPT_DES_ALGORITHM[] = {'D','E','S',0};
static const WCHAR BCRYPT_DSA_ALGORITHM[] = {'D','S','A',0};
static const WCHAR BCRYPT_ECDH_P256_ALGORITHM[] = {'E','C','D','H','_','P','2','5','6',0};
static const WCHAR BCRYPT_ECDSA_P256_ALGORITHM[] = {'E','C','D','S','A','_','P','2','5','6',0};
static const WCHAR BCRYPT_ECDSA_P384_ALGORITHM[] = {'E','C','D','S','A','_','P','3','8','4',0};
static const WCHAR BCRYPT_ECDSA_P521_ALGORITHM[] = {'E','C','D','S','A','_','P','5','2','1',0};
static const WCHAR BCRYPT_MD2_ALGORITHM[] = {'M','D','2',0};
static const WCHAR BCRYPT_MD4_ALGORITHM[] = {'M','D','4',0};
static const WCHAR BCRYPT_MD5_ALGORITHM[] = {'M','D','5',0};
static const WCHAR BCRYPT_RC2_ALGORITHM[] = {'R','C','2',0};
static const WCHAR BCRYPT_RC4_ALGORITHM[] = {'R','C','4',0};
static const WCHAR BCRYPT_RNG_ALGORITHM[] = {'R','N','G',0};
static const WCHAR BCRYPT_RSA_ALGORITHM[] = {'R','S','A',0};
static const WCHAR BCRYPT_RSA_SIGN_ALGORITHM[] = {'R','S','A','_','S','I','G','N',0};
@ -141,10 +159,6 @@ static const WCHAR BCRYPT_SHA1_ALGORITHM[] = {'S','H','A','1',0};
static const WCHAR BCRYPT_SHA256_ALGORITHM[] = {'S','H','A','2','5','6',0};
static const WCHAR BCRYPT_SHA384_ALGORITHM[] = {'S','H','A','3','8','4',0};
static const WCHAR BCRYPT_SHA512_ALGORITHM[] = {'S','H','A','5','1','2',0};
static const WCHAR BCRYPT_ECDH_P256_ALGORITHM[] = {'E','C','D','H','_','P','2','5','6',0};
static const WCHAR BCRYPT_ECDSA_P256_ALGORITHM[] = {'E','C','D','S','A','_','P','2','5','6',0};
static const WCHAR BCRYPT_ECDSA_P384_ALGORITHM[] = {'E','C','D','S','A','_','P','3','8','4',0};
static const WCHAR BCRYPT_ECDSA_P521_ALGORITHM[] = {'E','C','D','S','A','_','P','5','2','1',0};
static const WCHAR BCRYPT_CHAIN_MODE_NA[] = {'C','h','a','i','n','i','n','g','M','o','d','e','N','/','A',0};
static const WCHAR BCRYPT_CHAIN_MODE_CBC[] = {'C','h','a','i','n','i','n','g','M','o','d','e','C','B','C',0};
@ -257,6 +271,45 @@ typedef struct _BCRYPT_PKCS1_PADDING_INFO
#define BCRYPT_PAD_PSS 0x00000008
#define BCRYPT_PAD_PKCS1_OPTIONAL_HASH_OID 0x00000010
#define BCRYPT_DSA_PUBLIC_MAGIC 0x42505344
#define BCRYPT_DSA_PRIVATE_MAGIC 0x56505344
typedef struct _BCRYPT_DSA_KEY_BLOB
{
ULONG dwMagic;
ULONG cbKey;
UCHAR Count[4];
UCHAR Seed[20];
UCHAR q[20];
} BCRYPT_DSA_KEY_BLOB, *PBCRYPT_DSA_KEY_BLOB;
#define BCRYPT_DSA_PUBLIC_MAGIC_V2 0x32425044
#define BCRYPT_DSA_PRIVATE_MAGIC_V2 0x32565044
typedef enum
{
DSA_HASH_ALGORITHM_SHA1,
DSA_HASH_ALGORITHM_SHA256,
DSA_HASH_ALGORITHM_SHA512
} HASHALGORITHM_ENUM;
typedef enum
{
DSA_FIPS186_2,
DSA_FIPS186_3
} DSAFIPSVERSION_ENUM;
typedef struct _BCRYPT_DSA_KEY_BLOB_V2
{
ULONG dwMagic;
ULONG cbKey;
HASHALGORITHM_ENUM hashAlgorithm;
DSAFIPSVERSION_ENUM standardVersion;
ULONG cbSeedLength;
ULONG cbGroupSize;
UCHAR Count[4];
} BCRYPT_DSA_KEY_BLOB_V2, *PBCRYPT_DSA_KEY_BLOB_V2;
#define BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO_VERSION 1
#define BCRYPT_AUTH_MODE_CHAIN_CALLS_FLAG 0x00000001