bcrypt: Implement BCryptDeriveKeyCapi.
Signed-off-by: Hans Leidekker <hans@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
23ad2662c3
commit
0e17045288
|
@ -8,6 +8,7 @@
|
||||||
@ stdcall BCryptDecrypt(ptr ptr long ptr ptr long ptr long ptr long)
|
@ stdcall BCryptDecrypt(ptr ptr long ptr ptr long ptr long ptr long)
|
||||||
@ stub BCryptDeleteContext
|
@ stub BCryptDeleteContext
|
||||||
@ stdcall BCryptDeriveKey(ptr wstr ptr ptr long ptr long)
|
@ stdcall BCryptDeriveKey(ptr wstr ptr ptr long ptr long)
|
||||||
|
@ stdcall BCryptDeriveKeyCapi(ptr ptr ptr long long)
|
||||||
@ stdcall BCryptDeriveKeyPBKDF2(ptr ptr long ptr long int64 ptr long long)
|
@ stdcall BCryptDeriveKeyPBKDF2(ptr ptr long ptr long int64 ptr long long)
|
||||||
@ stdcall BCryptDestroyHash(ptr)
|
@ stdcall BCryptDestroyHash(ptr)
|
||||||
@ stdcall BCryptDestroyKey(ptr)
|
@ stdcall BCryptDestroyKey(ptr)
|
||||||
|
|
|
@ -1609,6 +1609,53 @@ NTSTATUS WINAPI BCryptSetProperty( BCRYPT_HANDLE handle, const WCHAR *prop, UCHA
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define HMAC_PAD_LEN 64
|
||||||
|
NTSTATUS WINAPI BCryptDeriveKeyCapi( BCRYPT_HASH_HANDLE handle, BCRYPT_ALG_HANDLE halg, UCHAR *key, ULONG keylen, ULONG flags )
|
||||||
|
{
|
||||||
|
struct hash *hash = handle;
|
||||||
|
UCHAR buf[MAX_HASH_OUTPUT_BYTES * 2];
|
||||||
|
NTSTATUS status;
|
||||||
|
ULONG len;
|
||||||
|
|
||||||
|
TRACE( "%p, %p, %p, %u, %08x\n", handle, halg, key, keylen, flags );
|
||||||
|
|
||||||
|
if (!key || !keylen) return STATUS_INVALID_PARAMETER;
|
||||||
|
if (!hash || hash->hdr.magic != MAGIC_HASH) return STATUS_INVALID_HANDLE;
|
||||||
|
if (keylen > builtin_algorithms[hash->alg_id].hash_length * 2) return STATUS_INVALID_PARAMETER;
|
||||||
|
|
||||||
|
if (halg)
|
||||||
|
{
|
||||||
|
FIXME( "algorithm handle not supported\n" );
|
||||||
|
return STATUS_NOT_IMPLEMENTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
len = builtin_algorithms[hash->alg_id].hash_length;
|
||||||
|
if ((status = BCryptFinishHash( handle, buf, len, 0 ))) return status;
|
||||||
|
|
||||||
|
if (len < keylen)
|
||||||
|
{
|
||||||
|
UCHAR pad1[HMAC_PAD_LEN], pad2[HMAC_PAD_LEN];
|
||||||
|
ULONG i;
|
||||||
|
|
||||||
|
for (i = 0; i < sizeof(pad1); i++)
|
||||||
|
{
|
||||||
|
pad1[i] = 0x36 ^ (i < len ? buf[i] : 0);
|
||||||
|
pad2[i] = 0x5c ^ (i < len ? buf[i] : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((status = prepare_hash( hash )) ||
|
||||||
|
(status = BCryptHashData( handle, pad1, sizeof(pad1), 0 )) ||
|
||||||
|
(status = BCryptFinishHash( handle, buf, len, 0 ))) return status;
|
||||||
|
|
||||||
|
if ((status = prepare_hash( hash )) ||
|
||||||
|
(status = BCryptHashData( handle, pad2, sizeof(pad2), 0 )) ||
|
||||||
|
(status = BCryptFinishHash( handle, buf + len, len, 0 ))) return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy( key, buf, keylen );
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
static NTSTATUS pbkdf2( BCRYPT_HASH_HANDLE handle, UCHAR *pwd, ULONG pwd_len, UCHAR *salt, ULONG salt_len,
|
static NTSTATUS pbkdf2( BCRYPT_HASH_HANDLE handle, UCHAR *pwd, ULONG pwd_len, UCHAR *salt, ULONG salt_len,
|
||||||
ULONGLONG iterations, ULONG i, UCHAR *dst, ULONG hash_len )
|
ULONGLONG iterations, ULONG i, UCHAR *dst, ULONG hash_len )
|
||||||
{
|
{
|
||||||
|
|
|
@ -32,6 +32,7 @@ static NTSTATUS (WINAPI *pBCryptCreateHash)(BCRYPT_ALG_HANDLE, BCRYPT_HASH_HANDL
|
||||||
ULONG, ULONG);
|
ULONG, ULONG);
|
||||||
static NTSTATUS (WINAPI *pBCryptDecrypt)(BCRYPT_KEY_HANDLE, PUCHAR, ULONG, VOID *, PUCHAR, ULONG, PUCHAR, ULONG,
|
static NTSTATUS (WINAPI *pBCryptDecrypt)(BCRYPT_KEY_HANDLE, PUCHAR, ULONG, VOID *, PUCHAR, ULONG, PUCHAR, ULONG,
|
||||||
ULONG *, ULONG);
|
ULONG *, ULONG);
|
||||||
|
static NTSTATUS (WINAPI *pBCryptDeriveKeyCapi)(BCRYPT_HASH_HANDLE, BCRYPT_ALG_HANDLE, UCHAR *, ULONG, ULONG);
|
||||||
static NTSTATUS (WINAPI *pBCryptDeriveKeyPBKDF2)(BCRYPT_ALG_HANDLE, PUCHAR, ULONG, PUCHAR, ULONG, ULONGLONG,
|
static NTSTATUS (WINAPI *pBCryptDeriveKeyPBKDF2)(BCRYPT_ALG_HANDLE, PUCHAR, ULONG, PUCHAR, ULONG, ULONGLONG,
|
||||||
PUCHAR, ULONG, ULONG);
|
PUCHAR, ULONG, ULONG);
|
||||||
static NTSTATUS (WINAPI *pBCryptDestroyHash)(BCRYPT_HASH_HANDLE);
|
static NTSTATUS (WINAPI *pBCryptDestroyHash)(BCRYPT_HASH_HANDLE);
|
||||||
|
@ -2356,6 +2357,71 @@ static void test_aes_vector(void)
|
||||||
ok(!ret, "got %08x\n", ret);
|
ok(!ret, "got %08x\n", ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void test_BcryptDeriveKeyCapi(void)
|
||||||
|
{
|
||||||
|
static const UCHAR expect[] =
|
||||||
|
{0xda,0x39,0xa3,0xee,0x5e,0x6b,0x4b,0x0d,0x32,0x55,0xbf,0xef,0x95,0x60,0x18,0x90,0xaf,0xd8,0x07,0x09};
|
||||||
|
static const UCHAR expect2[] =
|
||||||
|
{0x9b,0x03,0x17,0x41,0xf4,0x75,0x11,0xac,0xff,0x22,0xee,0x40,0xbb,0xe8,0xf9,0x74,0x17,0x26,0xb6,0xf2,
|
||||||
|
0xf8,0xc7,0x88,0x02,0x9a,0xdc,0x0d,0xd7,0x83,0x58,0xea,0x65,0x2e,0x8b,0x85,0xc6,0xdb,0xb7,0xed,0x1c};
|
||||||
|
BCRYPT_ALG_HANDLE alg;
|
||||||
|
BCRYPT_HASH_HANDLE hash;
|
||||||
|
UCHAR key[40];
|
||||||
|
NTSTATUS ret;
|
||||||
|
|
||||||
|
ret = pBCryptOpenAlgorithmProvider(&alg, BCRYPT_SHA1_ALGORITHM, NULL, 0);
|
||||||
|
ok(!ret, "got %08x\n", ret);
|
||||||
|
|
||||||
|
ret = pBCryptCreateHash(alg, &hash, NULL, 0, NULL, 0, 0);
|
||||||
|
ok(!ret || broken(ret == STATUS_INVALID_PARAMETER) /* win2k8 */, "got %08x\n", ret);
|
||||||
|
if (ret == STATUS_INVALID_PARAMETER)
|
||||||
|
{
|
||||||
|
win_skip( "broken BCryptCreateHash\n" );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = pBCryptDeriveKeyCapi(NULL, NULL, NULL, 0, 0);
|
||||||
|
ok(ret == STATUS_INVALID_PARAMETER, "got %08x\n", ret);
|
||||||
|
|
||||||
|
ret = pBCryptDeriveKeyCapi(hash, NULL, NULL, 0, 0);
|
||||||
|
ok(ret == STATUS_INVALID_PARAMETER, "got %08x\n", ret);
|
||||||
|
|
||||||
|
ret = pBCryptDeriveKeyCapi(hash, NULL, key, 0, 0);
|
||||||
|
ok(ret == STATUS_INVALID_PARAMETER, "got %08x\n", ret);
|
||||||
|
|
||||||
|
ret = pBCryptDeriveKeyCapi(hash, NULL, key, 41, 0);
|
||||||
|
ok(ret == STATUS_INVALID_PARAMETER, "got %08x\n", ret);
|
||||||
|
|
||||||
|
memset(key, 0, sizeof(key));
|
||||||
|
ret = pBCryptDeriveKeyCapi(hash, NULL, key, 20, 0);
|
||||||
|
ok(!ret, "got %08x\n", ret);
|
||||||
|
ok(!memcmp(key, expect, sizeof(expect) - 1), "wrong key data\n");
|
||||||
|
|
||||||
|
ret = pBCryptDeriveKeyCapi(hash, NULL, key, 20, 0);
|
||||||
|
todo_wine ok(ret == STATUS_INVALID_HANDLE, "got %08x\n", ret);
|
||||||
|
|
||||||
|
ret = pBCryptHashData(hash, NULL, 0, 0);
|
||||||
|
todo_wine ok(ret == STATUS_INVALID_HANDLE, "got %08x\n", ret);
|
||||||
|
|
||||||
|
ret = pBCryptDestroyHash(hash);
|
||||||
|
ok(!ret, "got %08x\n", ret);
|
||||||
|
|
||||||
|
ret = pBCryptCreateHash(alg, &hash, NULL, 0, NULL, 0, 0);
|
||||||
|
ok(!ret, "got %08x\n", ret);
|
||||||
|
|
||||||
|
ret = pBCryptHashData(hash, (UCHAR *)"test", 4, 0);
|
||||||
|
ok(!ret, "got %08x\n", ret);
|
||||||
|
|
||||||
|
/* padding */
|
||||||
|
memset(key, 0, sizeof(key));
|
||||||
|
ret = pBCryptDeriveKeyCapi(hash, NULL, key, 40, 0);
|
||||||
|
ok(!ret, "got %08x\n", ret);
|
||||||
|
ok(!memcmp(key, expect2, sizeof(expect2) - 1), "wrong key data\n");
|
||||||
|
|
||||||
|
ret = pBCryptCloseAlgorithmProvider(alg, 0);
|
||||||
|
ok(!ret, "got %08x\n", ret);
|
||||||
|
}
|
||||||
|
|
||||||
START_TEST(bcrypt)
|
START_TEST(bcrypt)
|
||||||
{
|
{
|
||||||
HMODULE module;
|
HMODULE module;
|
||||||
|
@ -2370,6 +2436,7 @@ START_TEST(bcrypt)
|
||||||
pBCryptCloseAlgorithmProvider = (void *)GetProcAddress(module, "BCryptCloseAlgorithmProvider");
|
pBCryptCloseAlgorithmProvider = (void *)GetProcAddress(module, "BCryptCloseAlgorithmProvider");
|
||||||
pBCryptCreateHash = (void *)GetProcAddress(module, "BCryptCreateHash");
|
pBCryptCreateHash = (void *)GetProcAddress(module, "BCryptCreateHash");
|
||||||
pBCryptDecrypt = (void *)GetProcAddress(module, "BCryptDecrypt");
|
pBCryptDecrypt = (void *)GetProcAddress(module, "BCryptDecrypt");
|
||||||
|
pBCryptDeriveKeyCapi = (void *)GetProcAddress(module, "BCryptDeriveKeyCapi");
|
||||||
pBCryptDeriveKeyPBKDF2 = (void *)GetProcAddress(module, "BCryptDeriveKeyPBKDF2");
|
pBCryptDeriveKeyPBKDF2 = (void *)GetProcAddress(module, "BCryptDeriveKeyPBKDF2");
|
||||||
pBCryptDestroyHash = (void *)GetProcAddress(module, "BCryptDestroyHash");
|
pBCryptDestroyHash = (void *)GetProcAddress(module, "BCryptDestroyHash");
|
||||||
pBCryptDestroyKey = (void *)GetProcAddress(module, "BCryptDestroyKey");
|
pBCryptDestroyKey = (void *)GetProcAddress(module, "BCryptDestroyKey");
|
||||||
|
@ -2418,6 +2485,7 @@ START_TEST(bcrypt)
|
||||||
test_BCryptSignHash();
|
test_BCryptSignHash();
|
||||||
test_BCryptEnumAlgorithms();
|
test_BCryptEnumAlgorithms();
|
||||||
test_aes_vector();
|
test_aes_vector();
|
||||||
|
test_BcryptDeriveKeyCapi();
|
||||||
|
|
||||||
FreeLibrary(module);
|
FreeLibrary(module);
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
@ stdcall BCryptDecrypt(ptr ptr long ptr ptr long ptr long ptr long) bcrypt.BCryptDecrypt
|
@ stdcall BCryptDecrypt(ptr ptr long ptr ptr long ptr long ptr long) bcrypt.BCryptDecrypt
|
||||||
@ stub BCryptDeleteContext
|
@ stub BCryptDeleteContext
|
||||||
@ stdcall BCryptDeriveKey(ptr wstr ptr ptr long ptr long) bcrypt.BCryptDeriveKey
|
@ stdcall BCryptDeriveKey(ptr wstr ptr ptr long ptr long) bcrypt.BCryptDeriveKey
|
||||||
@ stub BCryptDeriveKeyCapi
|
@ stdcall BCryptDeriveKeyCapi(ptr ptr ptr long long) bcrypt.BCryptDeriveKeyCapi
|
||||||
@ stdcall BCryptDeriveKeyPBKDF2(ptr ptr long ptr long int64 ptr long long) bcrypt.BCryptDeriveKeyPBKDF2
|
@ stdcall BCryptDeriveKeyPBKDF2(ptr ptr long ptr long int64 ptr long long) bcrypt.BCryptDeriveKeyPBKDF2
|
||||||
@ stdcall BCryptDestroyHash(ptr) bcrypt.BCryptDestroyHash
|
@ stdcall BCryptDestroyHash(ptr) bcrypt.BCryptDestroyHash
|
||||||
@ stdcall BCryptDestroyKey(ptr) bcrypt.BCryptDestroyKey
|
@ stdcall BCryptDestroyKey(ptr) bcrypt.BCryptDestroyKey
|
||||||
|
|
|
@ -348,6 +348,7 @@ NTSTATUS WINAPI BCryptCloseAlgorithmProvider(BCRYPT_ALG_HANDLE, ULONG);
|
||||||
NTSTATUS WINAPI BCryptCreateHash(BCRYPT_ALG_HANDLE, BCRYPT_HASH_HANDLE *, PUCHAR, ULONG, PUCHAR, ULONG, ULONG);
|
NTSTATUS WINAPI BCryptCreateHash(BCRYPT_ALG_HANDLE, BCRYPT_HASH_HANDLE *, PUCHAR, ULONG, PUCHAR, ULONG, ULONG);
|
||||||
NTSTATUS WINAPI BCryptDecrypt(BCRYPT_KEY_HANDLE, PUCHAR, ULONG, VOID *, PUCHAR, ULONG, PUCHAR, ULONG, ULONG *, ULONG);
|
NTSTATUS WINAPI BCryptDecrypt(BCRYPT_KEY_HANDLE, PUCHAR, ULONG, VOID *, PUCHAR, ULONG, PUCHAR, ULONG, ULONG *, ULONG);
|
||||||
NTSTATUS WINAPI BCryptDeriveKey(BCRYPT_SECRET_HANDLE, LPCWSTR, BCryptBufferDesc*, PUCHAR, ULONG, ULONG *, ULONG);
|
NTSTATUS WINAPI BCryptDeriveKey(BCRYPT_SECRET_HANDLE, LPCWSTR, BCryptBufferDesc*, PUCHAR, ULONG, ULONG *, ULONG);
|
||||||
|
NTSTATUS WINAPI BCryptDeriveKeyCapi(BCRYPT_HASH_HANDLE, BCRYPT_ALG_HANDLE, PUCHAR, ULONG, ULONG);
|
||||||
NTSTATUS WINAPI BCryptDeriveKeyPBKDF2(BCRYPT_ALG_HANDLE, PUCHAR, ULONG, PUCHAR, ULONG, ULONGLONG, PUCHAR, ULONG, ULONG);
|
NTSTATUS WINAPI BCryptDeriveKeyPBKDF2(BCRYPT_ALG_HANDLE, PUCHAR, ULONG, PUCHAR, ULONG, ULONGLONG, PUCHAR, ULONG, ULONG);
|
||||||
NTSTATUS WINAPI BCryptDestroyHash(BCRYPT_HASH_HANDLE);
|
NTSTATUS WINAPI BCryptDestroyHash(BCRYPT_HASH_HANDLE);
|
||||||
NTSTATUS WINAPI BCryptDestroyKey(BCRYPT_KEY_HANDLE);
|
NTSTATUS WINAPI BCryptDestroyKey(BCRYPT_KEY_HANDLE);
|
||||||
|
|
Loading…
Reference in New Issue