From: Allan Vester <vesterallan246@gmail.com> Forza Motorsport imports an AES-128 key, sets the initialization vector with BCryptSetProperty() and then calls BCryptDecrypt() with a NULL pbIV. set_key_property() rejects the property with STATUS_NOT_IMPLEMENTED, so the game never decrypts any of its content. --- dlls/bcrypt/bcrypt_main.c | 10 ++++++++++ dlls/bcrypt/tests/bcrypt.c | 16 ++++++++-------- 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/dlls/bcrypt/bcrypt_main.c b/dlls/bcrypt/bcrypt_main.c index 7260ac62e9d..c76480bd857 100644 --- a/dlls/bcrypt/bcrypt_main.c +++ b/dlls/bcrypt/bcrypt_main.c @@ -1127,6 +1127,16 @@ static NTSTATUS set_key_property( struct key *key, const WCHAR *prop, UCHAR *val return STATUS_NOT_IMPLEMENTED; } } + else if (!wcscmp( prop, BCRYPT_INITIALIZATION_VECTOR )) + { + if (!is_symmetric_key( key )) return STATUS_INVALID_HANDLE; + if (size != key->s.block_size || size > sizeof(key->s.vector)) return STATUS_INVALID_PARAMETER; + + EnterCriticalSection( &key->s.cs ); + memcpy( key->s.vector, value, size ); + LeaveCriticalSection( &key->s.cs ); + return STATUS_SUCCESS; + } else if (!wcscmp( prop, BCRYPT_KEY_LENGTH )) { if (size < sizeof(DWORD)) return STATUS_INVALID_PARAMETER; diff --git a/dlls/bcrypt/tests/bcrypt.c b/dlls/bcrypt/tests/bcrypt.c index 7e28408d00f..d11567e7ef5 100644 --- a/dlls/bcrypt/tests/bcrypt.c +++ b/dlls/bcrypt/tests/bcrypt.c @@ -4260,33 +4260,33 @@ static void test_aes_vector_property(void) ok(!ret, "got %#lx\n", ret); ret = BCryptSetProperty(key, BCRYPT_INITIALIZATION_VECTOR, (UCHAR *)vector, sizeof(vector) - 1, 0); - todo_wine ok(ret == STATUS_INVALID_PARAMETER, "got %#lx\n", ret); + ok(ret == STATUS_INVALID_PARAMETER, "got %#lx\n", ret); /* the initialization vector can be set on the key instead of being passed to BCryptEncrypt() */ ret = BCryptSetProperty(key, BCRYPT_INITIALIZATION_VECTOR, (UCHAR *)vector, sizeof(vector), 0); - todo_wine ok(!ret, "got %#lx\n", ret); + ok(!ret, "got %#lx\n", ret); size = 0; memset(output, 0, sizeof(output)); ret = BCryptEncrypt(key, input, sizeof(input), NULL, NULL, 0, output, sizeof(output), &size, 0); ok(!ret, "got %#lx\n", ret); ok(size == 16, "got %lu\n", size); - todo_wine ok(!memcmp(output, expect, sizeof(expect)), "wrong cipher text\n"); + ok(!memcmp(output, expect, sizeof(expect)), "wrong cipher text\n"); /* setting it again restarts the chain instead of continuing it */ ret = BCryptSetProperty(key, BCRYPT_INITIALIZATION_VECTOR, (UCHAR *)vector, sizeof(vector), 0); - todo_wine ok(!ret, "got %#lx\n", ret); + ok(!ret, "got %#lx\n", ret); size = 0; memset(output, 0, sizeof(output)); ret = BCryptEncrypt(key, input, sizeof(input), NULL, NULL, 0, output, sizeof(output), &size, 0); ok(!ret, "got %#lx\n", ret); ok(size == 16, "got %lu\n", size); - todo_wine ok(!memcmp(output, expect, sizeof(expect)), "wrong cipher text\n"); + ok(!memcmp(output, expect, sizeof(expect)), "wrong cipher text\n"); /* a vector passed to BCryptEncrypt() overrides the one set on the key */ ret = BCryptSetProperty(key, BCRYPT_INITIALIZATION_VECTOR, (UCHAR *)vector, sizeof(vector), 0); - todo_wine ok(!ret, "got %#lx\n", ret); + ok(!ret, "got %#lx\n", ret); size = 0; memset(iv, 0, sizeof(iv)); @@ -4298,14 +4298,14 @@ static void test_aes_vector_property(void) /* and the same vector decrypts what it encrypted */ ret = BCryptSetProperty(key, BCRYPT_INITIALIZATION_VECTOR, (UCHAR *)vector, sizeof(vector), 0); - todo_wine ok(!ret, "got %#lx\n", ret); + ok(!ret, "got %#lx\n", ret); size = 0; memset(output, 0, sizeof(output)); ret = BCryptDecrypt(key, (UCHAR *)expect, sizeof(expect), NULL, NULL, 0, output, sizeof(output), &size, 0); ok(!ret, "got %#lx\n", ret); ok(size == 16, "got %lu\n", size); - todo_wine ok(!memcmp(output, input, sizeof(input)), "wrong plain text\n"); + ok(!memcmp(output, input, sizeof(input)), "wrong plain text\n"); ret = BCryptDestroyKey(key); ok(!ret, "got %#lx\n", ret); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/11561