bcrypt: Validate secret size in BCryptGenerateSymmetricKey().

Fixes online connection error in Forza Horizon 5.

Signed-off-by: Paul Gofman <pgofman@codeweavers.com>
Signed-off-by: Hans Leidekker <hans@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Paul Gofman 2021-11-12 17:09:46 +03:00 committed by Alexandre Julliard
parent 33bc90e687
commit 028837158a
2 changed files with 40 additions and 1 deletions

View File

@ -1521,9 +1521,10 @@ NTSTATUS WINAPI BCryptGenerateSymmetricKey( BCRYPT_ALG_HANDLE algorithm, BCRYPT_
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;
ULONG block_size;
TRACE( "%p, %p, %p, %u, %p, %u, %08x\n", algorithm, handle, object, object_len, secret, secret_len, flags );
@ -1538,6 +1539,25 @@ NTSTATUS WINAPI BCryptGenerateSymmetricKey( BCRYPT_ALG_HANDLE algorithm, BCRYPT_
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 %u exceeds key max length %u, setting to maximum.\n", secret_len, size );
secret_len = size;
}
else if (secret_len < (size = key_lengths.dwMinLength / 8))
{
WARN( "secret_len %u is less than minimum key length %u.\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 %u is not a valid key length.\n", secret_len );
return STATUS_INVALID_PARAMETER;
}
}
if (!(key = heap_alloc_zero( sizeof(*key) ))) return STATUS_NO_MEMORY;
InitializeCriticalSection( &key->u.s.cs );
key->hdr.magic = MAGIC_KEY;

View File

@ -731,6 +731,17 @@ static void test_BCryptGenerateSymmetricKey(void)
key = NULL;
buf = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len);
key = (BCRYPT_KEY_HANDLE)0xdeadbeef;
ret = pBCryptGenerateSymmetricKey(aes, &key, buf, len, secret, 1, 0);
ok(ret == STATUS_INVALID_PARAMETER, "got %08x\n", ret);
ok(key == (HANDLE)0xdeadbeef, "got unexpected key %p.\n", key);
key = (BCRYPT_KEY_HANDLE)0xdeadbeef;
ret = pBCryptGenerateSymmetricKey(aes, &key, buf, len, secret, sizeof(secret) + 1, 0);
ok(ret == STATUS_INVALID_PARAMETER, "got %08x\n", ret);
ok(key == (HANDLE)0xdeadbeef, "got unexpected key %p.\n", key);
ret = pBCryptGenerateSymmetricKey(aes, &key, buf, len, secret, sizeof(secret), 0);
ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
ok(key != NULL, "key not set\n");
@ -1101,8 +1112,16 @@ static void test_BCryptEncrypt(void)
/* 256 bit key */
buf = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len);
ret = pBCryptGenerateSymmetricKey(aes, &key, buf, len, secret256, sizeof(secret256), 0);
ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
ret = pBCryptDestroyKey(key);
ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
/* Key generations succeeds if the key size exceeds maximum and uses maximum key length
* from secret. */
ret = pBCryptGenerateSymmetricKey(aes, &key, buf, len, secret256, sizeof(secret256) + 1, 0);
ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
size = 0;
memcpy(ivbuf, iv, sizeof(iv));