Paul Gofman : bcrypt: Validate secret size in BCryptGenerateSymmetricKey().
Alexandre Julliard
julliard at winehq.org
Fri Nov 12 16:16:04 CST 2021
Module: wine
Branch: master
Commit: 028837158a77bbe4c77e9e0ac0d439d25af53296
URL: https://source.winehq.org/git/wine.git/?a=commit;h=028837158a77bbe4c77e9e0ac0d439d25af53296
Author: Paul Gofman <pgofman at codeweavers.com>
Date: Fri Nov 12 17:09:46 2021 +0300
bcrypt: Validate secret size in BCryptGenerateSymmetricKey().
Fixes online connection error in Forza Horizon 5.
Signed-off-by: Paul Gofman <pgofman at codeweavers.com>
Signed-off-by: Hans Leidekker <hans at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>
---
dlls/bcrypt/bcrypt_main.c | 22 +++++++++++++++++++++-
dlls/bcrypt/tests/bcrypt.c | 19 +++++++++++++++++++
2 files changed, 40 insertions(+), 1 deletion(-)
diff --git a/dlls/bcrypt/bcrypt_main.c b/dlls/bcrypt/bcrypt_main.c
index 9e0d06e9cc7..542bd0756a0 100644
--- a/dlls/bcrypt/bcrypt_main.c
+++ b/dlls/bcrypt/bcrypt_main.c
@@ -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;
diff --git a/dlls/bcrypt/tests/bcrypt.c b/dlls/bcrypt/tests/bcrypt.c
index fb5ac03b039..4dd0f4195aa 100644
--- a/dlls/bcrypt/tests/bcrypt.c
+++ b/dlls/bcrypt/tests/bcrypt.c
@@ -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));
More information about the wine-cvs
mailing list