bcrypt: Add full support for algorithm pseudo-handles.

This commit is contained in:
Hans Leidekker 2022-09-10 13:38:10 +02:00 committed by Alexandre Julliard
parent f527e4a694
commit 6f5028dd03
4 changed files with 422 additions and 175 deletions

View file

@ -146,10 +146,11 @@ enum alg_id
enum mode_id
{
MODE_ID_ECB,
MODE_ID_CBC,
MODE_ID_GCM,
MODE_ID_ECB,
MODE_ID_CFB,
MODE_ID_CCM,
MODE_ID_GCM,
};
struct algorithm

View file

@ -175,14 +175,103 @@ NTSTATUS WINAPI BCryptEnumAlgorithms( ULONG type, ULONG *ret_count, BCRYPT_ALGOR
return STATUS_SUCCESS;
}
NTSTATUS WINAPI BCryptGenRandom(BCRYPT_ALG_HANDLE handle, UCHAR *buffer, ULONG count, ULONG flags)
static const struct algorithm pseudo_algorithms[] =
{
{{ MAGIC_ALG }, ALG_ID_MD2 },
{{ MAGIC_ALG }, ALG_ID_MD4 },
{{ MAGIC_ALG }, ALG_ID_MD5 },
{{ MAGIC_ALG }, ALG_ID_SHA1 },
{{ MAGIC_ALG }, ALG_ID_SHA256 },
{{ MAGIC_ALG }, ALG_ID_SHA384 },
{{ MAGIC_ALG }, ALG_ID_SHA512 },
{{ 0 }}, /* RC4 */
{{ MAGIC_ALG }, ALG_ID_RNG },
{{ MAGIC_ALG }, ALG_ID_MD5, 0, BCRYPT_ALG_HANDLE_HMAC_FLAG },
{{ MAGIC_ALG }, ALG_ID_SHA1, 0, BCRYPT_ALG_HANDLE_HMAC_FLAG },
{{ MAGIC_ALG }, ALG_ID_SHA256, 0, BCRYPT_ALG_HANDLE_HMAC_FLAG },
{{ MAGIC_ALG }, ALG_ID_SHA384, 0, BCRYPT_ALG_HANDLE_HMAC_FLAG },
{{ MAGIC_ALG }, ALG_ID_SHA512, 0, BCRYPT_ALG_HANDLE_HMAC_FLAG },
{{ MAGIC_ALG }, ALG_ID_RSA },
{{ 0 }}, /* ECDSA */
{{ 0 }}, /* AES_CMAC */
{{ 0 }}, /* AES_GMAC */
{{ MAGIC_ALG }, ALG_ID_MD2, 0, BCRYPT_ALG_HANDLE_HMAC_FLAG },
{{ MAGIC_ALG }, ALG_ID_MD4, 0, BCRYPT_ALG_HANDLE_HMAC_FLAG },
{{ MAGIC_ALG }, ALG_ID_3DES, MODE_ID_CBC },
{{ MAGIC_ALG }, ALG_ID_3DES, MODE_ID_ECB },
{{ MAGIC_ALG }, ALG_ID_3DES, MODE_ID_CFB },
{{ 0 }}, /* 3DES_112_CBC */
{{ 0 }}, /* 3DES_112_ECB */
{{ 0 }}, /* 3DES_112_CFB */
{{ MAGIC_ALG }, ALG_ID_AES, MODE_ID_CBC },
{{ MAGIC_ALG }, ALG_ID_AES, MODE_ID_ECB },
{{ MAGIC_ALG }, ALG_ID_AES, MODE_ID_CFB },
{{ MAGIC_ALG }, ALG_ID_AES, MODE_ID_CCM },
{{ MAGIC_ALG }, ALG_ID_AES, MODE_ID_GCM },
{{ 0 }}, /* DES_CBC */
{{ 0 }}, /* DES_ECB */
{{ 0 }}, /* DES_CFB */
{{ 0 }}, /* DESX_CBC */
{{ 0 }}, /* DESX_ECB */
{{ 0 }}, /* DESX_CFB */
{{ 0 }}, /* RC2_CBC */
{{ 0 }}, /* RC2_ECB */
{{ 0 }}, /* RC2_CFB */
{{ 0 }}, /* DH */
{{ 0 }}, /* ECDH */
{{ MAGIC_ALG }, ALG_ID_ECDH_P256 },
{{ MAGIC_ALG }, ALG_ID_ECDH_P384 },
{{ 0 }}, /* ECDH_P512 */
{{ MAGIC_ALG }, ALG_ID_DSA },
{{ MAGIC_ALG }, ALG_ID_ECDSA_P256 },
{{ MAGIC_ALG }, ALG_ID_ECDSA_P384 },
{{ 0 }}, /* ECDSA_P512 */
{{ MAGIC_ALG }, ALG_ID_RSA_SIGN },
};
/* Algorithm pseudo-handles are denoted by having the lowest bit set.
* An aligned algorithm pointer will never have this bit set.
*/
static inline BOOL is_alg_pseudo_handle( BCRYPT_ALG_HANDLE handle )
{
return (((ULONG_PTR)handle & 1) == 1);
}
static struct object *get_object( BCRYPT_HANDLE handle, ULONG magic )
{
ULONG idx;
if (!handle) return NULL;
if (!is_alg_pseudo_handle( handle ))
{
struct object *obj = handle;
if (magic && obj->magic != magic) return NULL;
return obj;
}
idx = (ULONG_PTR)handle >> 4;
if (idx > ARRAY_SIZE(pseudo_algorithms) || !pseudo_algorithms[idx].hdr.magic)
{
FIXME( "pseudo-handle %p not supported\n", handle );
return NULL;
}
return (struct object *)&pseudo_algorithms[idx];
}
static inline struct algorithm *get_alg_object( BCRYPT_ALG_HANDLE handle )
{
return (struct algorithm *)get_object( handle, MAGIC_ALG );
}
NTSTATUS WINAPI BCryptGenRandom( BCRYPT_ALG_HANDLE handle, UCHAR *buffer, ULONG count, ULONG flags )
{
const DWORD supported_flags = BCRYPT_USE_SYSTEM_PREFERRED_RNG;
struct algorithm *algorithm = handle;
struct algorithm *alg = get_alg_object( handle );
TRACE("%p, %p, %lu, %#lx - semi-stub\n", handle, buffer, count, flags);
if (!algorithm)
if (!handle)
{
/* It's valid to call without an algorithm if BCRYPT_USE_SYSTEM_PREFERRED_RNG
* is set. In this case the preferred system RNG is used.
@ -190,18 +279,12 @@ NTSTATUS WINAPI BCryptGenRandom(BCRYPT_ALG_HANDLE handle, UCHAR *buffer, ULONG c
if (!(flags & BCRYPT_USE_SYSTEM_PREFERRED_RNG))
return STATUS_INVALID_HANDLE;
}
else if (((ULONG_PTR)algorithm & 1) == 1)
else if (is_alg_pseudo_handle( handle ) && handle != BCRYPT_RNG_ALG_HANDLE)
{
/* Pseudo algorithm handles are denoted by having the lowest bit set.
* An aligned algorithm pointer will never have this bit set.
*/
if (algorithm != BCRYPT_RNG_ALG_HANDLE)
{
FIXME("pseudo-handle algorithm %p not supported\n", algorithm);
return STATUS_NOT_IMPLEMENTED;
}
FIXME( "pseudo-handle %p not supported\n", handle );
return STATUS_NOT_IMPLEMENTED;
}
else if (algorithm->hdr.magic != MAGIC_ALG || algorithm->id != ALG_ID_RNG)
else if (!alg || alg->id != ALG_ID_RNG)
return STATUS_INVALID_HANDLE;
if (!buffer)
@ -210,23 +293,33 @@ NTSTATUS WINAPI BCryptGenRandom(BCRYPT_ALG_HANDLE handle, UCHAR *buffer, ULONG c
if (flags & ~supported_flags)
FIXME("unsupported flags %#lx\n", flags & ~supported_flags);
if (algorithm)
if (alg)
FIXME("ignoring selected algorithm\n");
/* When zero bytes are requested the function returns success too. */
if (!count)
return STATUS_SUCCESS;
if (algorithm || (flags & BCRYPT_USE_SYSTEM_PREFERRED_RNG))
if (alg || (flags & BCRYPT_USE_SYSTEM_PREFERRED_RNG))
{
if (RtlGenRandom(buffer, count))
return STATUS_SUCCESS;
if (RtlGenRandom(buffer, count)) return STATUS_SUCCESS;
}
FIXME("called with unsupported parameters, returning error\n");
return STATUS_NOT_IMPLEMENTED;
}
static struct algorithm *create_algorithm( enum alg_id id, enum mode_id mode, DWORD flags )
{
struct algorithm *ret;
if (!(ret = calloc( 1, sizeof(*ret) ))) return NULL;
ret->hdr.magic = MAGIC_ALG;
ret->id = id;
ret->mode = mode;
ret->flags = flags;
return ret;
}
NTSTATUS WINAPI BCryptOpenAlgorithmProvider( BCRYPT_ALG_HANDLE *handle, const WCHAR *id, const WCHAR *implementation,
DWORD flags )
{
@ -264,25 +357,25 @@ NTSTATUS WINAPI BCryptOpenAlgorithmProvider( BCRYPT_ALG_HANDLE *handle, const WC
return STATUS_NOT_IMPLEMENTED;
}
if (!(alg = malloc( sizeof(*alg) ))) return STATUS_NO_MEMORY;
alg->hdr.magic = MAGIC_ALG;
alg->id = alg_id;
alg->mode = MODE_ID_CBC;
alg->flags = flags;
if (!(alg = create_algorithm( alg_id, 0, flags ))) return STATUS_NO_MEMORY;
*handle = alg;
return STATUS_SUCCESS;
}
static void destroy_object( struct object *obj )
{
obj->magic = 0;
free( obj );
}
NTSTATUS WINAPI BCryptCloseAlgorithmProvider( BCRYPT_ALG_HANDLE handle, DWORD flags )
{
struct algorithm *alg = handle;
TRACE( "%p, %#lx\n", handle, flags );
if (!alg || alg->hdr.magic != MAGIC_ALG) return STATUS_INVALID_HANDLE;
alg->hdr.magic = 0;
free( alg );
if (!handle || is_alg_pseudo_handle( handle ) || alg->hdr.magic != MAGIC_ALG) return STATUS_INVALID_HANDLE;
destroy_object( &alg->hdr );
return STATUS_SUCCESS;
}
@ -349,8 +442,7 @@ static NTSTATUS hash_init( struct hash_impl *hash, enum alg_id alg_id )
return STATUS_SUCCESS;
}
static NTSTATUS hash_update( struct hash_impl *hash, enum alg_id alg_id,
UCHAR *input, ULONG size )
static NTSTATUS hash_update( struct hash_impl *hash, enum alg_id alg_id, UCHAR *input, ULONG size )
{
switch (alg_id)
{
@ -389,8 +481,7 @@ static NTSTATUS hash_update( struct hash_impl *hash, enum alg_id alg_id,
return STATUS_SUCCESS;
}
static NTSTATUS hash_finish( struct hash_impl *hash, enum alg_id alg_id,
UCHAR *output, ULONG size )
static NTSTATUS hash_finish( struct hash_impl *hash, enum alg_id alg_id, UCHAR *output, ULONG size )
{
switch (alg_id)
{
@ -605,8 +696,8 @@ static NTSTATUS get_dsa_property( enum mode_id mode, const WCHAR *prop, UCHAR *b
return STATUS_NOT_IMPLEMENTED;
}
static NTSTATUS get_alg_property( const struct algorithm *alg, const WCHAR *prop,
UCHAR *buf, ULONG size, ULONG *ret_size )
static NTSTATUS get_alg_property( const struct algorithm *alg, const WCHAR *prop, UCHAR *buf, ULONG size,
ULONG *ret_size )
{
NTSTATUS status;
@ -766,7 +857,7 @@ static NTSTATUS get_key_property( const struct key *key, const WCHAR *prop, UCHA
NTSTATUS WINAPI BCryptGetProperty( BCRYPT_HANDLE handle, const WCHAR *prop, UCHAR *buffer, ULONG count, ULONG *res,
ULONG flags )
{
struct object *object = handle;
struct object *object = get_object( handle, 0 );
TRACE( "%p, %s, %p, %lu, %p, %#lx\n", handle, wine_dbgstr_w(prop), buffer, count, res, flags );
@ -857,25 +948,26 @@ static NTSTATUS hash_create( const struct algorithm *alg, UCHAR *secret, ULONG s
return STATUS_SUCCESS;
}
NTSTATUS WINAPI BCryptCreateHash( BCRYPT_ALG_HANDLE algorithm, BCRYPT_HASH_HANDLE *handle, UCHAR *object,
NTSTATUS WINAPI BCryptCreateHash( BCRYPT_ALG_HANDLE handle, BCRYPT_HASH_HANDLE *ret_handle, UCHAR *object,
ULONG object_len, UCHAR *secret, ULONG secret_len, ULONG flags )
{
struct algorithm *alg = algorithm;
struct algorithm *alg = get_alg_object( handle );
struct hash *hash;
NTSTATUS status;
TRACE( "%p, %p, %p, %lu, %p, %lu, %#lx\n", algorithm, handle, object, object_len, secret, secret_len, flags );
TRACE( "%p, %p, %p, %lu, %p, %lu, %#lx\n", handle, ret_handle, object, object_len, secret, secret_len, flags );
if (flags & ~BCRYPT_HASH_REUSABLE_FLAG)
{
FIXME( "unimplemented flags %#lx\n", flags );
return STATUS_NOT_IMPLEMENTED;
}
if (!alg || alg->hdr.magic != MAGIC_ALG) return STATUS_INVALID_HANDLE;
if (object) FIXME( "ignoring object buffer\n" );
if (!alg) return STATUS_INVALID_HANDLE;
if (!ret_handle) return STATUS_INVALID_PARAMETER;
if ((status = hash_create( alg, secret, secret_len, flags, &hash ))) return status;
*handle = hash;
*ret_handle = hash;
return STATUS_SUCCESS;
}
@ -908,9 +1000,8 @@ NTSTATUS WINAPI BCryptDuplicateHash( BCRYPT_HASH_HANDLE handle, BCRYPT_HASH_HAND
static void hash_destroy( struct hash *hash )
{
if (!hash) return;
hash->hdr.magic = 0;
free( hash->secret );
free( hash );
destroy_object( &hash->hdr );
}
NTSTATUS WINAPI BCryptDestroyHash( BCRYPT_HASH_HANDLE handle )
@ -970,16 +1061,16 @@ NTSTATUS WINAPI BCryptFinishHash( BCRYPT_HASH_HANDLE handle, UCHAR *output, ULON
return hash_finalize( hash, output, size );
}
NTSTATUS WINAPI BCryptHash( BCRYPT_ALG_HANDLE algorithm, UCHAR *secret, ULONG secret_len,
NTSTATUS WINAPI BCryptHash( BCRYPT_ALG_HANDLE handle, UCHAR *secret, ULONG secret_len,
UCHAR *input, ULONG input_len, UCHAR *output, ULONG output_len )
{
struct algorithm *alg = algorithm;
struct algorithm *alg = get_alg_object( handle );
struct hash *hash;
NTSTATUS status;
TRACE( "%p, %p, %lu, %p, %lu, %p, %lu\n", algorithm, secret, secret_len, input, input_len, output, output_len );
TRACE( "%p, %p, %lu, %p, %lu, %p, %lu\n", handle, secret, secret_len, input, input_len, output, output_len );
if (!alg || alg->hdr.magic != MAGIC_ALG) return STATUS_INVALID_HANDLE;
if (!alg) return STATUS_INVALID_HANDLE;
if ((status = hash_create( alg, secret, secret_len, 0, &hash ))) return status;
if ((status = hash_update( &hash->inner, hash->alg_id, input, input_len )))
@ -1040,7 +1131,76 @@ static NTSTATUS key_symmetric_set_vector( struct key *key, UCHAR *vector, ULONG
return STATUS_SUCCESS;
}
static NTSTATUS key_import( BCRYPT_ALG_HANDLE algorithm, const WCHAR *type, BCRYPT_KEY_HANDLE *key, UCHAR *object,
static struct key *create_symmetric_key( enum alg_id alg, enum mode_id mode, ULONG block_size, UCHAR *secret,
ULONG secret_len )
{
struct key *ret;
if (!(ret = calloc( 1, sizeof(*ret) ))) return NULL;
InitializeCriticalSection( &ret->u.s.cs );
ret->hdr.magic = MAGIC_KEY;
ret->alg_id = alg;
ret->u.s.mode = mode;
ret->u.s.block_size = block_size;
if (!(ret->u.s.secret = malloc( secret_len )))
{
DeleteCriticalSection( &ret->u.s.cs );
free( ret );
return NULL;
}
memcpy( ret->u.s.secret, secret, secret_len );
ret->u.s.secret_len = secret_len;
return ret;
}
static ULONG get_block_size( struct algorithm *alg )
{
ULONG ret = 0, size = sizeof(ret);
get_alg_property( alg, BCRYPT_BLOCK_LENGTH, (UCHAR *)&ret, sizeof(ret), &size );
return ret;
}
static NTSTATUS generate_symmetric_key( struct algorithm *alg, BCRYPT_KEY_HANDLE *ret_handle, UCHAR *secret,
ULONG secret_len )
{
BCRYPT_KEY_LENGTHS_STRUCT key_lengths;
ULONG block_size, size;
struct key *key;
NTSTATUS status;
if (!(block_size = get_block_size( alg ))) return STATUS_INVALID_PARAMETER;
if (!get_alg_property( alg, BCRYPT_KEY_LENGTHS, (UCHAR *)&key_lengths, sizeof(key_lengths), &size ))
{
if (secret_len > (size = key_lengths.dwMaxLength / 8))
{
WARN( "secret_len %lu exceeds key max length %lu, setting to maximum\n", secret_len, size );
secret_len = size;
}
else if (secret_len < (size = key_lengths.dwMinLength / 8))
{
WARN( "secret_len %lu is less than minimum key length %lu\n", secret_len, size );
return STATUS_INVALID_PARAMETER;
}
else if (key_lengths.dwIncrement && (secret_len * 8 - key_lengths.dwMinLength) % key_lengths.dwIncrement)
{
WARN( "secret_len %lu is not a valid key length\n", secret_len );
return STATUS_INVALID_PARAMETER;
}
}
if (!(key = create_symmetric_key( alg->id, alg->mode, block_size, secret, secret_len ))) status = STATUS_NO_MEMORY;
else
{
*ret_handle = key;
status = STATUS_SUCCESS;
}
return status;
}
static NTSTATUS key_import( struct algorithm *alg, const WCHAR *type, BCRYPT_KEY_HANDLE *key, UCHAR *object,
ULONG object_len, UCHAR *input, ULONG input_len )
{
ULONG len;
@ -1059,7 +1219,7 @@ static NTSTATUS key_import( BCRYPT_ALG_HANDLE algorithm, const WCHAR *type, BCRY
len = header->cbKeyData;
if (len + sizeof(BCRYPT_KEY_DATA_BLOB_HEADER) > input_len) return STATUS_INVALID_PARAMETER;
return BCryptGenerateSymmetricKey( algorithm, key, object, object_len, (UCHAR *)&header[1], len, 0 );
return generate_symmetric_key( alg, key, (UCHAR *)&header[1], len );
}
else if (!wcscmp( type, BCRYPT_OPAQUE_KEY_BLOB ))
{
@ -1067,7 +1227,7 @@ static NTSTATUS key_import( BCRYPT_ALG_HANDLE algorithm, const WCHAR *type, BCRY
len = *(ULONG *)input;
if (len + sizeof(len) > input_len) return STATUS_INVALID_PARAMETER;
return BCryptGenerateSymmetricKey( algorithm, key, object, object_len, input + sizeof(len), len, 0 );
return generate_symmetric_key( alg, key, input + sizeof(len), len );
}
FIXME( "unsupported key type %s\n", debugstr_w(type) );
@ -1338,8 +1498,7 @@ static void key_destroy( struct key *key )
else
UNIX_CALL( key_asymmetric_destroy, key );
key->hdr.magic = 0;
free( key );
destroy_object( &key->hdr );
}
static NTSTATUS key_import_pair( struct algorithm *alg, const WCHAR *type, BCRYPT_KEY_HANDLE *ret_key, UCHAR *input,
@ -1599,87 +1758,38 @@ static NTSTATUS key_import_pair( struct algorithm *alg, const WCHAR *type, BCRYP
return STATUS_NOT_SUPPORTED;
}
static ULONG get_block_size( struct algorithm *alg )
{
ULONG ret = 0, size = sizeof(ret);
get_alg_property( alg, BCRYPT_BLOCK_LENGTH, (UCHAR *)&ret, sizeof(ret), &size );
return ret;
}
NTSTATUS WINAPI BCryptGenerateSymmetricKey( BCRYPT_ALG_HANDLE algorithm, BCRYPT_KEY_HANDLE *handle,
NTSTATUS WINAPI BCryptGenerateSymmetricKey( BCRYPT_ALG_HANDLE handle, BCRYPT_KEY_HANDLE *ret_handle,
UCHAR *object, ULONG object_len, UCHAR *secret, ULONG secret_len,
ULONG flags )
{
BCRYPT_KEY_LENGTHS_STRUCT key_lengths;
struct algorithm *alg = algorithm;
ULONG block_size, size;
struct key *key;
struct algorithm *alg = get_alg_object( handle );
TRACE( "%p, %p, %p, %lu, %p, %lu, %#lx\n", algorithm, handle, object, object_len, secret, secret_len, flags );
if (!alg || alg->hdr.magic != MAGIC_ALG) return STATUS_INVALID_HANDLE;
TRACE( "%p, %p, %p, %lu, %p, %lu, %#lx\n", handle, ret_handle, object, object_len, secret, secret_len, flags );
if (object) FIXME( "ignoring object buffer\n" );
if (!bcrypt_handle)
{
ERR( "no encryption support\n" );
return STATUS_NOT_IMPLEMENTED;
}
if (!(block_size = get_block_size( alg ))) return STATUS_INVALID_PARAMETER;
if (!get_alg_property( alg, BCRYPT_KEY_LENGTHS, (UCHAR*)&key_lengths, sizeof(key_lengths), &size ))
{
if (secret_len > (size = key_lengths.dwMaxLength / 8))
{
WARN( "secret_len %lu exceeds key max length %lu, setting to maximum\n", secret_len, size );
secret_len = size;
}
else if (secret_len < (size = key_lengths.dwMinLength / 8))
{
WARN( "secret_len %lu is less than minimum key length %lu\n", secret_len, size );
return STATUS_INVALID_PARAMETER;
}
else if (key_lengths.dwIncrement && (secret_len * 8 - key_lengths.dwMinLength) % key_lengths.dwIncrement)
{
WARN( "secret_len %lu is not a valid key length\n", secret_len );
return STATUS_INVALID_PARAMETER;
}
}
if (!(key = calloc( 1, sizeof(*key) ))) return STATUS_NO_MEMORY;
InitializeCriticalSection( &key->u.s.cs );
key->hdr.magic = MAGIC_KEY;
key->alg_id = alg->id;
key->u.s.mode = alg->mode;
key->u.s.block_size = block_size;
if (!(key->u.s.secret = malloc( secret_len )))
{
free( key );
return STATUS_NO_MEMORY;
}
memcpy( key->u.s.secret, secret, secret_len );
key->u.s.secret_len = secret_len;
*handle = key;
return STATUS_SUCCESS;
if (!alg) return STATUS_INVALID_HANDLE;
return generate_symmetric_key( alg, ret_handle, secret, secret_len );
}
NTSTATUS WINAPI BCryptGenerateKeyPair( BCRYPT_ALG_HANDLE algorithm, BCRYPT_KEY_HANDLE *handle, ULONG key_len,
NTSTATUS WINAPI BCryptGenerateKeyPair( BCRYPT_ALG_HANDLE handle, BCRYPT_KEY_HANDLE *ret_handle, ULONG key_len,
ULONG flags )
{
struct algorithm *alg = algorithm;
struct algorithm *alg = get_alg_object( handle );
struct key *key;
NTSTATUS status;
TRACE( "%p, %p, %lu, %#lx\n", algorithm, handle, key_len, flags );
TRACE( "%p, %p, %lu, %#lx\n", handle, ret_handle, key_len, flags );
if (!alg || alg->hdr.magic != MAGIC_ALG) return STATUS_INVALID_HANDLE;
if (!handle) return STATUS_INVALID_PARAMETER;
if (!alg) return STATUS_INVALID_HANDLE;
if (!ret_handle) return STATUS_INVALID_PARAMETER;
if ((status = key_asymmetric_create( alg->id, key_len, &key ))) return status;
*handle = key;
*ret_handle = key;
return STATUS_SUCCESS;
}
@ -1693,25 +1803,24 @@ NTSTATUS WINAPI BCryptFinalizeKeyPair( BCRYPT_KEY_HANDLE handle, ULONG flags )
return UNIX_CALL( key_asymmetric_generate, key );
}
NTSTATUS WINAPI BCryptImportKey( BCRYPT_ALG_HANDLE algorithm, BCRYPT_KEY_HANDLE decrypt_key, const WCHAR *type,
BCRYPT_KEY_HANDLE *key, UCHAR *object, ULONG object_len, UCHAR *input,
NTSTATUS WINAPI BCryptImportKey( BCRYPT_ALG_HANDLE handle, BCRYPT_KEY_HANDLE decrypt_key, const WCHAR *type,
BCRYPT_KEY_HANDLE *ret_handle, UCHAR *object, ULONG object_len, UCHAR *input,
ULONG input_len, ULONG flags )
{
struct algorithm *alg = algorithm;
struct algorithm *alg = get_alg_object( handle );
TRACE( "%p, %p, %s, %p, %p, %lu, %p, %lu, %#lx\n", algorithm, decrypt_key, debugstr_w(type), key, object,
TRACE( "%p, %p, %s, %p, %p, %lu, %p, %lu, %#lx\n", handle, decrypt_key, debugstr_w(type), ret_handle, object,
object_len, input, input_len, flags );
if (!alg || alg->hdr.magic != MAGIC_ALG) return STATUS_INVALID_HANDLE;
if (!key || !type || !input) return STATUS_INVALID_PARAMETER;
if (!alg) return STATUS_INVALID_HANDLE;
if (!ret_handle || !type || !input) return STATUS_INVALID_PARAMETER;
if (decrypt_key)
{
FIXME( "decryption of key not yet supported\n" );
return STATUS_NOT_IMPLEMENTED;
}
return key_import( algorithm, type, key, object, object_len, input, input_len );
return key_import( alg, type, ret_handle, object, object_len, input, input_len );
}
NTSTATUS WINAPI BCryptExportKey( BCRYPT_KEY_HANDLE export_key, BCRYPT_KEY_HANDLE encrypt_key, const WCHAR *type,
@ -1793,52 +1902,52 @@ NTSTATUS WINAPI BCryptDuplicateKey( BCRYPT_KEY_HANDLE handle, BCRYPT_KEY_HANDLE
return STATUS_SUCCESS;
}
NTSTATUS WINAPI BCryptImportKeyPair( BCRYPT_ALG_HANDLE algorithm, BCRYPT_KEY_HANDLE decrypt_key, const WCHAR *type,
BCRYPT_KEY_HANDLE *ret_key, UCHAR *input, ULONG input_len, ULONG flags )
static const WCHAR *resolve_blob_type( const WCHAR *type, UCHAR *input, ULONG input_len )
{
struct algorithm *alg = algorithm;
BCRYPT_KEY_BLOB *blob = (BCRYPT_KEY_BLOB *)input;
TRACE( "%p, %p, %s, %p, %p, %lu, %#lx\n", algorithm, decrypt_key, debugstr_w(type), ret_key, input,
if (!type) return NULL;
if (wcscmp( type, BCRYPT_PUBLIC_KEY_BLOB )) return type;
if (input_len < sizeof(*blob)) return NULL;
switch (blob->Magic)
{
case BCRYPT_ECDH_PUBLIC_P256_MAGIC:
case BCRYPT_ECDH_PUBLIC_P384_MAGIC:
case BCRYPT_ECDSA_PUBLIC_P256_MAGIC:
case BCRYPT_ECDSA_PUBLIC_P384_MAGIC:
return BCRYPT_ECCPUBLIC_BLOB;
case BCRYPT_RSAPUBLIC_MAGIC:
return BCRYPT_RSAPUBLIC_BLOB;
case BCRYPT_DSA_PUBLIC_MAGIC:
return BCRYPT_DSA_PUBLIC_BLOB;
default:
FIXME( "unsupported key magic %#lx\n", blob->Magic );
return NULL;
}
}
NTSTATUS WINAPI BCryptImportKeyPair( BCRYPT_ALG_HANDLE handle, BCRYPT_KEY_HANDLE decrypt_key, const WCHAR *type,
BCRYPT_KEY_HANDLE *ret_handle, UCHAR *input, ULONG input_len, ULONG flags )
{
struct algorithm *alg = get_alg_object( handle );
TRACE( "%p, %p, %s, %p, %p, %lu, %#lx\n", handle, decrypt_key, debugstr_w(type), ret_handle, input,
input_len, flags );
if (!alg || alg->hdr.magic != MAGIC_ALG) return STATUS_INVALID_HANDLE;
if (!ret_key || !type || !input) return STATUS_INVALID_PARAMETER;
if (!alg) return STATUS_INVALID_HANDLE;
if (!ret_handle || !input || !(type = resolve_blob_type( type, input, input_len )))
return STATUS_INVALID_PARAMETER;
if (decrypt_key)
{
FIXME( "decryption of key not yet supported\n" );
return STATUS_NOT_IMPLEMENTED;
}
if (!wcscmp( type, BCRYPT_PUBLIC_KEY_BLOB ))
{
BCRYPT_KEY_BLOB *key_blob = (BCRYPT_KEY_BLOB *)input;
if (input_len < sizeof(*key_blob)) return STATUS_INVALID_PARAMETER;
switch (key_blob->Magic)
{
case BCRYPT_ECDH_PUBLIC_P256_MAGIC:
case BCRYPT_ECDH_PUBLIC_P384_MAGIC:
case BCRYPT_ECDSA_PUBLIC_P256_MAGIC:
case BCRYPT_ECDSA_PUBLIC_P384_MAGIC:
type = BCRYPT_ECCPUBLIC_BLOB;
break;
case BCRYPT_RSAPUBLIC_MAGIC:
type = BCRYPT_RSAPUBLIC_BLOB;
break;
case BCRYPT_DSA_PUBLIC_MAGIC:
type = BCRYPT_DSA_PUBLIC_BLOB;
break;
default:
FIXME( "unsupported key magic %#lx\n", key_blob->Magic );
return STATUS_NOT_SUPPORTED;
}
}
return key_import_pair( alg, type, ret_key, input, input_len );
return key_import_pair( alg, type, ret_handle, input, input_len );
}
NTSTATUS WINAPI BCryptSignHash( BCRYPT_KEY_HANDLE handle, void *padding, UCHAR *input, ULONG input_len,
@ -1993,7 +2102,8 @@ NTSTATUS WINAPI BCryptSetProperty( BCRYPT_HANDLE handle, const WCHAR *prop, UCHA
TRACE( "%p, %s, %p, %lu, %#lx\n", handle, debugstr_w(prop), value, size, flags );
if (!object) return STATUS_INVALID_HANDLE;
if (!handle) return STATUS_INVALID_HANDLE;
if (is_alg_pseudo_handle( handle )) return STATUS_ACCESS_DENIED;
switch (object->magic)
{
@ -2107,20 +2217,14 @@ static NTSTATUS pbkdf2( struct hash *hash, UCHAR *pwd, ULONG pwd_len, UCHAR *sal
return status;
}
NTSTATUS WINAPI BCryptDeriveKeyPBKDF2( BCRYPT_ALG_HANDLE handle, UCHAR *pwd, ULONG pwd_len, UCHAR *salt, ULONG salt_len,
ULONGLONG iterations, UCHAR *dk, ULONG dk_len, ULONG flags )
static NTSTATUS derive_key_pbkdf2( struct algorithm *alg, UCHAR *pwd, ULONG pwd_len, UCHAR *salt, ULONG salt_len,
ULONGLONG iterations, UCHAR *dk, ULONG dk_len )
{
struct algorithm *alg = handle;
ULONG hash_len, block_count, bytes_left, i;
struct hash *hash;
UCHAR *partial;
NTSTATUS status;
TRACE( "%p, %p, %lu, %p, %lu, %s, %p, %lu, %#lx\n", handle, pwd, pwd_len, salt, salt_len,
wine_dbgstr_longlong(iterations), dk, dk_len, flags );
if (!alg || alg->hdr.magic != MAGIC_ALG) return STATUS_INVALID_HANDLE;
hash_len = builtin_algorithms[alg->id].hash_length;
if (dk_len <= 0 || dk_len > ((((ULONGLONG)1) << 32) - 1) * hash_len) return STATUS_INVALID_PARAMETER;
@ -2159,6 +2263,18 @@ NTSTATUS WINAPI BCryptDeriveKeyPBKDF2( BCRYPT_ALG_HANDLE handle, UCHAR *pwd, ULO
return STATUS_SUCCESS;
}
NTSTATUS WINAPI BCryptDeriveKeyPBKDF2( BCRYPT_ALG_HANDLE handle, UCHAR *pwd, ULONG pwd_len, UCHAR *salt, ULONG salt_len,
ULONGLONG iterations, UCHAR *dk, ULONG dk_len, ULONG flags )
{
struct algorithm *alg = get_alg_object( handle );
TRACE( "%p, %p, %lu, %p, %lu, %s, %p, %lu, %#lx\n", handle, pwd, pwd_len, salt, salt_len,
wine_dbgstr_longlong(iterations), dk, dk_len, flags );
if (!alg) return STATUS_INVALID_HANDLE;
return derive_key_pbkdf2( alg, pwd, pwd_len, salt, salt_len, iterations, dk, dk_len );
}
NTSTATUS WINAPI BCryptSecretAgreement( BCRYPT_KEY_HANDLE privatekey, BCRYPT_KEY_HANDLE publickey,
BCRYPT_SECRET_HANDLE *handle, ULONG flags )
{
@ -2186,8 +2302,7 @@ NTSTATUS WINAPI BCryptDestroySecret(BCRYPT_SECRET_HANDLE handle)
FIXME( "%p\n", handle );
if (!secret || secret->hdr.magic != MAGIC_SECRET) return STATUS_INVALID_HANDLE;
secret->hdr.magic = 0;
free( secret );
destroy_object( &secret->hdr );
return STATUS_SUCCESS;
}

View file

@ -63,8 +63,12 @@ static void test_BCryptGenRandom(void)
{
ret = BCryptGenRandom(BCRYPT_RNG_ALG_HANDLE, buffer, sizeof(buffer), 0);
ok(ret == STATUS_SUCCESS, "Expected success, got %#lx\n", ret);
ret = BCryptCloseAlgorithmProvider(BCRYPT_RNG_ALG_HANDLE, 0);
ok(ret == STATUS_INVALID_HANDLE, "got %#lx\n", ret);
}
else win_skip("BCryptGenRandom pseudo handles are not available\n");
}
static void test_BCryptGetFipsAlgorithmMode(void)
@ -323,6 +327,14 @@ static void test_hash(const struct hash_test *test)
ret = BCryptCloseAlgorithmProvider(alg, 0);
ok(ret == STATUS_SUCCESS, "got %#lx\n", ret);
if (pBCryptHash)
{
ret = BCryptCreateHash(BCRYPT_SHA1_ALG_HANDLE, &hash, NULL, 0, NULL, 0, 0);
ok(ret == STATUS_SUCCESS, "got %#lx\n", ret);
ret = BCryptDestroyHash(hash);
ok(ret == STATUS_SUCCESS, "got %#lx\n", ret);
}
}
static void test_hashes(void)
@ -433,6 +445,15 @@ static void test_BcryptHash(void)
ret = BCryptCloseAlgorithmProvider(alg, 0);
ok(ret == STATUS_SUCCESS, "got %#lx\n", ret);
if (pBCryptHash)
{
memset(md5, 0, sizeof(md5));
ret = pBCryptHash(BCRYPT_MD5_ALG_HANDLE, NULL, 0, (UCHAR *)"test", sizeof("test"), md5, sizeof(md5));
ok(ret == STATUS_SUCCESS, "got %#lx\n", ret);
format_hash( md5, sizeof(md5), str );
ok(!strcmp(str, expected), "got %s\n", str);
}
}
/* test vectors from RFC 6070 */
@ -502,6 +523,13 @@ static void test_BcryptDeriveKeyPBKDF2(void)
ret = BCryptCloseAlgorithmProvider(alg, 0);
ok(ret == STATUS_SUCCESS, "got %#lx\n", ret);
if (pBCryptHash)
{
ret = BCryptDeriveKeyPBKDF2(BCRYPT_HMAC_SHA1_ALG_HANDLE, rfc6070[0].pwd, rfc6070[0].pwd_len, rfc6070[0].salt,
rfc6070[0].salt_len, 1, buf, rfc6070[0].dk_len, 0);
ok(ret == STATUS_SUCCESS, "got %#lx\n", ret);
}
}
static void test_rng(void)
@ -610,6 +638,19 @@ static void test_aes(void)
ret = BCryptCloseAlgorithmProvider(alg, 0);
ok(ret == STATUS_SUCCESS, "got %#lx\n", ret);
if (pBCryptHash)
{
ret = BCryptSetProperty(BCRYPT_AES_CBC_ALG_HANDLE, BCRYPT_CHAINING_MODE, (UCHAR *)BCRYPT_CHAIN_MODE_GCM, 0, 0);
ok(ret == STATUS_ACCESS_DENIED, "got %#lx\n", ret);
size = 0;
memset(mode, 0, sizeof(mode));
ret = BCryptGetProperty(BCRYPT_AES_CBC_ALG_HANDLE, BCRYPT_CHAINING_MODE, mode, sizeof(mode), &size, 0);
ok(ret == STATUS_SUCCESS, "got %#lx\n", ret);
ok(!lstrcmpW((const WCHAR *)mode, BCRYPT_CHAIN_MODE_CBC), "got %s\n", wine_dbgstr_w((const WCHAR *)mode));
ok(size == 64, "got %lu\n", size);
}
}
static void test_3des(void)
@ -687,7 +728,7 @@ static void test_BCryptGenerateSymmetricKey(void)
BCRYPT_KEY_HANDLE key, key2;
UCHAR *buf, ciphertext[16], plaintext[16], ivbuf[16], mode[64];
BCRYPT_KEY_LENGTHS_STRUCT key_lengths;
ULONG size, len, i;
ULONG size, len, len2, i;
NTSTATUS ret;
DWORD keylen;
@ -697,6 +738,7 @@ static void test_BCryptGenerateSymmetricKey(void)
len = size = 0xdeadbeef;
ret = BCryptGetProperty(aes, BCRYPT_OBJECT_LENGTH, (UCHAR *)&len, sizeof(len), &size, 0);
ok(ret == STATUS_SUCCESS, "got %#lx\n", ret);
len2 = len;
key = (void *)0xdeadbeef;
ret = BCryptGenerateSymmetricKey(NULL, &key, NULL, 0, secret, sizeof(secret), 0);
@ -848,8 +890,16 @@ static void test_BCryptGenerateSymmetricKey(void)
ret = BCryptDestroyKey(key);
ok(ret == STATUS_SUCCESS, "got %#lx\n", ret);
free(buf);
if (pBCryptHash)
{
ret = BCryptGenerateSymmetricKey(BCRYPT_AES_CBC_ALG_HANDLE, &key, buf, len2, secret, sizeof(secret), 0);
ok(ret == STATUS_SUCCESS, "got %#lx\n", ret);
ret = BCryptDestroyKey(key);
ok(ret == STATUS_SUCCESS, "got %#lx\n", ret);
}
free(buf);
ret = BCryptCloseAlgorithmProvider(aes, 0);
ok(ret == STATUS_SUCCESS, "got %#lx\n", ret);
}
@ -1949,11 +1999,18 @@ static void test_key_import_export(void)
ret = BCryptImportKey(aes, NULL, BCRYPT_OPAQUE_KEY_BLOB, &key, NULL, 0, buf, size, 0);
ok(ret == STATUS_SUCCESS, "got %#lx\n", ret);
ok(key != NULL, "key not set\n");
free(buf);
ret = BCryptDestroyKey(key);
ok(ret == STATUS_SUCCESS, "got %#lx\n", ret);
if (pBCryptHash)
{
ret = BCryptImportKey(BCRYPT_AES_CBC_ALG_HANDLE, NULL, BCRYPT_OPAQUE_KEY_BLOB, &key, NULL, 0, buf, size, 0);
ok(ret == STATUS_SUCCESS, "got %#lx\n", ret);
BCryptDestroyKey(key);
}
free(buf);
ret = BCryptCloseAlgorithmProvider(aes, 0);
ok(ret == STATUS_SUCCESS, "got %#lx\n", ret);
}
@ -2029,6 +2086,14 @@ static void test_ECDSA(void)
ok(!status, "BCryptImportKeyPair failed: %#lx\n", status);
BCryptDestroyKey(key);
if (pBCryptHash)
{
status = BCryptImportKeyPair(BCRYPT_ECDSA_P256_ALG_HANDLE, NULL, BCRYPT_PUBLIC_KEY_BLOB, &key, buffer,
size, 0);
ok(!status, "BCryptImportKeyPair failed: %#lx\n", status);
BCryptDestroyKey(key);
}
status = BCryptImportKeyPair(alg, NULL, BCRYPT_ECCPUBLIC_BLOB, &key, buffer, size, 0);
ok(!status, "BCryptImportKeyPair failed: %#lx\n", status);
@ -2208,14 +2273,15 @@ static void test_rsa_encrypt(void)
oaep_pad.pbLabel = (PUCHAR)"test";
oaep_pad.cbLabel = 5;
BCryptOpenAlgorithmProvider(&rsa, BCRYPT_RSA_ALGORITHM, NULL, 0);
BCryptGenerateKeyPair(rsa, &key, 512, 0);
ret = BCryptOpenAlgorithmProvider(&rsa, BCRYPT_RSA_ALGORITHM, NULL, 0);
ok(ret == STATUS_SUCCESS, "got %lx\n", ret);
ret = BCryptGenerateKeyPair(rsa, &key, 512, 0);
ok(ret == STATUS_SUCCESS, "got %lx\n", ret);
todo_wine {
/* Not finalized key */
ret = BCryptEncrypt(key, input, sizeof(input), NULL, NULL, 0, NULL, 0, &encrypted_size, 0);
ok(ret == STATUS_INVALID_HANDLE, "got %lx\n", ret);
BCryptFinalizeKeyPair(key, 0);
/* No padding */
@ -2300,6 +2366,14 @@ static void test_rsa_encrypt(void)
free(encrypted_a);
free(encrypted_b);
BCryptDestroyKey(key);
if (pBCryptHash)
{
ret = BCryptGenerateKeyPair(BCRYPT_RSA_ALG_HANDLE, &key, 512, 0);
ok(ret == STATUS_SUCCESS, "got %lx\n", ret);
BCryptDestroyKey(key);
}
}
static void test_RSA(void)

View file

@ -401,8 +401,65 @@ typedef PVOID BCRYPT_HANDLE;
typedef PVOID BCRYPT_HASH_HANDLE;
typedef PVOID BCRYPT_SECRET_HANDLE;
/* Pseudo handles for BCryptGenRandom */
#define BCRYPT_RNG_ALG_HANDLE ((BCRYPT_ALG_HANDLE)0x00000081)
/* Pseudo handles */
#define BCRYPT_MD2_ALG_HANDLE ((BCRYPT_ALG_HANDLE)0x00000001)
#define BCRYPT_MD4_ALG_HANDLE ((BCRYPT_ALG_HANDLE)0x00000011)
#define BCRYPT_MD5_ALG_HANDLE ((BCRYPT_ALG_HANDLE)0x00000021)
#define BCRYPT_SHA1_ALG_HANDLE ((BCRYPT_ALG_HANDLE)0x00000031)
#define BCRYPT_SHA256_ALG_HANDLE ((BCRYPT_ALG_HANDLE)0x00000041)
#define BCRYPT_SHA384_ALG_HANDLE ((BCRYPT_ALG_HANDLE)0x00000051)
#define BCRYPT_SHA512_ALG_HANDLE ((BCRYPT_ALG_HANDLE)0x00000061)
#define BCRYPT_RC4_ALG_HANDLE ((BCRYPT_ALG_HANDLE)0x00000071)
#define BCRYPT_RNG_ALG_HANDLE ((BCRYPT_ALG_HANDLE)0x00000081)
#define BCRYPT_HMAC_MD5_ALG_HANDLE ((BCRYPT_ALG_HANDLE)0x00000091)
#define BCRYPT_HMAC_SHA1_ALG_HANDLE ((BCRYPT_ALG_HANDLE)0x000000a1)
#define BCRYPT_HMAC_SHA256_ALG_HANDLE ((BCRYPT_ALG_HANDLE)0x000000b1)
#define BCRYPT_HMAC_SHA384_ALG_HANDLE ((BCRYPT_ALG_HANDLE)0x000000c1)
#define BCRYPT_HMAC_SHA512_ALG_HANDLE ((BCRYPT_ALG_HANDLE)0x000000d1)
#define BCRYPT_RSA_ALG_HANDLE ((BCRYPT_ALG_HANDLE)0x000000e1)
#define BCRYPT_ECDSA_ALG_HANDLE ((BCRYPT_ALG_HANDLE)0x000000f1)
#define BCRYPT_AES_CMAC_ALG_HANDLE ((BCRYPT_ALG_HANDLE)0x00000101)
#define BCRYPT_AES_GMAC_ALG_HANDLE ((BCRYPT_ALG_HANDLE)0x00000111)
#define BCRYPT_HMAC_MD2_ALG_HANDLE ((BCRYPT_ALG_HANDLE)0x00000121)
#define BCRYPT_HMAC_MD4_ALG_HANDLE ((BCRYPT_ALG_HANDLE)0x00000131)
#define BCRYPT_3DES_CBC_ALG_HANDLE ((BCRYPT_ALG_HANDLE)0x00000141)
#define BCRYPT_3DES_ECB_ALG_HANDLE ((BCRYPT_ALG_HANDLE)0x00000151)
#define BCRYPT_3DES_CFB_ALG_HANDLE ((BCRYPT_ALG_HANDLE)0x00000161)
#define BCRYPT_3DES_112_CBC_ALG_HANDLE ((BCRYPT_ALG_HANDLE)0x00000171)
#define BCRYPT_3DES_112_ECB_ALG_HANDLE ((BCRYPT_ALG_HANDLE)0x00000181)
#define BCRYPT_3DES_112_CFB_ALG_HANDLE ((BCRYPT_ALG_HANDLE)0x00000191)
#define BCRYPT_AES_CBC_ALG_HANDLE ((BCRYPT_ALG_HANDLE)0x000001a1)
#define BCRYPT_AES_ECB_ALG_HANDLE ((BCRYPT_ALG_HANDLE)0x000001b1)
#define BCRYPT_AES_CFB_ALG_HANDLE ((BCRYPT_ALG_HANDLE)0x000001c1)
#define BCRYPT_AES_CCM_ALG_HANDLE ((BCRYPT_ALG_HANDLE)0x000001d1)
#define BCRYPT_AES_GCM_ALG_HANDLE ((BCRYPT_ALG_HANDLE)0x000001e1)
#define BCRYPT_DES_CBC_ALG_HANDLE ((BCRYPT_ALG_HANDLE)0x000001f1)
#define BCRYPT_DES_ECB_ALG_HANDLE ((BCRYPT_ALG_HANDLE)0x00000201)
#define BCRYPT_DES_CFB_ALG_HANDLE ((BCRYPT_ALG_HANDLE)0x00000211)
#define BCRYPT_DESX_CBC_ALG_HANDLE ((BCRYPT_ALG_HANDLE)0x00000221)
#define BCRYPT_DESX_ECB_ALG_HANDLE ((BCRYPT_ALG_HANDLE)0x00000231)
#define BCRYPT_DESX_CFB_ALG_HANDLE ((BCRYPT_ALG_HANDLE)0x00000241)
#define BCRYPT_RC2_CBC_ALG_HANDLE ((BCRYPT_ALG_HANDLE)0x00000251)
#define BCRYPT_RC2_ECB_ALG_HANDLE ((BCRYPT_ALG_HANDLE)0x00000261)
#define BCRYPT_RC2_CFB_ALG_HANDLE ((BCRYPT_ALG_HANDLE)0x00000271)
#define BCRYPT_DH_ALG_HANDLE ((BCRYPT_ALG_HANDLE)0x00000281)
#define BCRYPT_ECDH_ALG_HANDLE ((BCRYPT_ALG_HANDLE)0x00000291)
#define BCRYPT_ECDH_P256_ALG_HANDLE ((BCRYPT_ALG_HANDLE)0x000002a1)
#define BCRYPT_ECDH_P384_ALG_HANDLE ((BCRYPT_ALG_HANDLE)0x000002b1)
#define BCRYPT_ECDH_P521_ALG_HANDLE ((BCRYPT_ALG_HANDLE)0x000002c1)
#define BCRYPT_DSA_ALG_HANDLE ((BCRYPT_ALG_HANDLE)0x000002d1)
#define BCRYPT_ECDSA_P256_ALG_HANDLE ((BCRYPT_ALG_HANDLE)0x000002e1)
#define BCRYPT_ECDSA_P384_ALG_HANDLE ((BCRYPT_ALG_HANDLE)0x000002f1)
#define BCRYPT_ECDSA_P521_ALG_HANDLE ((BCRYPT_ALG_HANDLE)0x00000301)
#define BCRYPT_RSA_SIGN_ALG_HANDLE ((BCRYPT_ALG_HANDLE)0x00000311)
#define BCRYPT_CAPI_KDF_ALG_HANDLE ((BCRYPT_ALG_HANDLE)0x00000321)
#define BCRYPT_PBKDF2_ALG_HANDLE ((BCRYPT_ALG_HANDLE)0x00000331)
#define BCRYPT_SP800108_CTR_HMAC_ALG_HANDLE ((BCRYPT_ALG_HANDLE)0x00000341)
#define BCRYPT_SP80056A_CONCAT_ALG_HANDLE ((BCRYPT_ALG_HANDLE)0x00000351)
#define BCRYPT_TLS1_1_KDF_ALG_HANDLE ((BCRYPT_ALG_HANDLE)0x00000361)
#define BCRYPT_TLS1_2_KDF_ALG_HANDLE ((BCRYPT_ALG_HANDLE)0x00000371)
#define BCRYPT_XTS_AES_ALG_HANDLE ((BCRYPT_ALG_HANDLE)0x00000381)
#define BCRYPT_HKDF_ALG_HANDLE ((BCRYPT_ALG_HANDLE)0x00000391)
/* Flags for BCryptGenRandom */
#define BCRYPT_RNG_USE_ENTROPY_IN_BUFFER 0x00000001