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