diff --git a/patches/bcrypt-Improvements/0001-bcrypt-Add-AES-provider.patch b/patches/bcrypt-Improvements/0001-bcrypt-Add-AES-provider.patch index 8a55efac..9d4b8aa9 100644 --- a/patches/bcrypt-Improvements/0001-bcrypt-Add-AES-provider.patch +++ b/patches/bcrypt-Improvements/0001-bcrypt-Add-AES-provider.patch @@ -469,7 +469,7 @@ index 6023c94..937bdf7 100644 + struct key *key = handle; + NTSTATUS status; + -+ FIXME( "%p, %p, %u, %p, %p, %u, %p, %u, %p, %08x\n", handle, input, input_len, ++ TRACE( "%p, %p, %u, %p, %p, %u, %p, %u, %p, %08x\n", handle, input, input_len, + padding, iv, iv_len, output, output_len, ret_len, flags ); + + if (!key || key->hdr.magic != MAGIC_KEY) return STATUS_INVALID_HANDLE; diff --git a/patches/bcrypt-Improvements/0006-bcrypt-Fix-handling-of-padding-when-input-size-equal.patch b/patches/bcrypt-Improvements/0006-bcrypt-Fix-handling-of-padding-when-input-size-equal.patch index 27b0756b..5139ec41 100644 --- a/patches/bcrypt-Improvements/0006-bcrypt-Fix-handling-of-padding-when-input-size-equal.patch +++ b/patches/bcrypt-Improvements/0006-bcrypt-Fix-handling-of-padding-when-input-size-equal.patch @@ -1,16 +1,16 @@ -From 8554c6eea279baa21e10d3b742e1c62a732bbe69 Mon Sep 17 00:00:00 2001 +From 026aff5aa7c66fdc8e8c724dc73217585e8edf91 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20M=C3=BCller?= Date: Wed, 21 Dec 2016 04:09:03 +0100 Subject: bcrypt: Fix handling of padding when input size equals block size for AES. --- - dlls/bcrypt/bcrypt_main.c | 13 +++++++------ + dlls/bcrypt/bcrypt_main.c | 14 ++++++++------ dlls/bcrypt/tests/bcrypt.c | 33 ++++++++++++++++++++++++++++++++- - 2 files changed, 39 insertions(+), 7 deletions(-) + 2 files changed, 40 insertions(+), 7 deletions(-) diff --git a/dlls/bcrypt/bcrypt_main.c b/dlls/bcrypt/bcrypt_main.c -index 944a9ea..f97638f 100644 +index 944a9ea..f53ea1c 100644 --- a/dlls/bcrypt/bcrypt_main.c +++ b/dlls/bcrypt/bcrypt_main.c @@ -997,11 +997,12 @@ NTSTATUS WINAPI BCryptEncrypt( BCRYPT_KEY_HANDLE handle, UCHAR *input, ULONG inp @@ -31,12 +31,13 @@ index 944a9ea..f97638f 100644 if (!output) return STATUS_SUCCESS; if (output_len < *ret_len) return STATUS_BUFFER_TOO_SMALL; -@@ -1014,7 +1015,7 @@ NTSTATUS WINAPI BCryptEncrypt( BCRYPT_KEY_HANDLE handle, UCHAR *input, ULONG inp +@@ -1014,7 +1015,8 @@ NTSTATUS WINAPI BCryptEncrypt( BCRYPT_KEY_HANDLE handle, UCHAR *input, ULONG inp src += key->block_size; dst += key->block_size; } - if (bytes_left) -+ if (bytes_left || (flags & BCRYPT_BLOCK_PADDING)) ++ ++ if (flags & BCRYPT_BLOCK_PADDING) { if (!(buf = HeapAlloc( GetProcessHeap(), 0, key->block_size ))) return STATUS_NO_MEMORY; memcpy( buf, src, bytes_left ); diff --git a/patches/bcrypt-Improvements/0007-bcrypt-Properly-handle-padding-in-AES-decryption.patch b/patches/bcrypt-Improvements/0007-bcrypt-Properly-handle-padding-in-AES-decryption.patch index 842103df..33b8a169 100644 --- a/patches/bcrypt-Improvements/0007-bcrypt-Properly-handle-padding-in-AES-decryption.patch +++ b/patches/bcrypt-Improvements/0007-bcrypt-Properly-handle-padding-in-AES-decryption.patch @@ -20,7 +20,7 @@ index f97638f..653301b 100644 + UCHAR *buf, *src, *dst; NTSTATUS status; - FIXME( "%p, %p, %u, %p, %p, %u, %p, %u, %p, %08x\n", handle, input, input_len, + TRACE( "%p, %p, %u, %p, %p, %u, %p, %u, %p, %08x\n", handle, input, input_len, @@ -1052,11 +1054,44 @@ NTSTATUS WINAPI BCryptDecrypt( BCRYPT_KEY_HANDLE handle, UCHAR *input, ULONG inp if ((status = key_set_params( key, iv, iv_len ))) return status; diff --git a/patches/bcrypt-Improvements/0008-bcrypt-Fix-use-after-free-in-key_init.patch b/patches/bcrypt-Improvements/0008-bcrypt-Fix-use-after-free-in-key_init.patch new file mode 100644 index 00000000..98fd48a9 --- /dev/null +++ b/patches/bcrypt-Improvements/0008-bcrypt-Fix-use-after-free-in-key_init.patch @@ -0,0 +1,39 @@ +From f7dc69131cc016917b31c5deedf97da31b11c597 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Michael=20M=C3=BCller?= +Date: Mon, 26 Dec 2016 02:43:39 +0100 +Subject: bcrypt: Fix use-after-free in key_init. + +--- + dlls/bcrypt/bcrypt_main.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/dlls/bcrypt/bcrypt_main.c b/dlls/bcrypt/bcrypt_main.c +index 09bf6c30..a9006a4 100644 +--- a/dlls/bcrypt/bcrypt_main.c ++++ b/dlls/bcrypt/bcrypt_main.c +@@ -791,6 +791,8 @@ static ULONG get_block_size( enum alg_id alg ) + + static NTSTATUS key_init( struct key *key, enum alg_id id, UCHAR *secret, ULONG secret_len ) + { ++ UCHAR *buffer; ++ + if (!libgnutls_handle) return STATUS_INTERNAL_ERROR; + + switch (id) +@@ -804,10 +806,12 @@ static NTSTATUS key_init( struct key *key, enum alg_id id, UCHAR *secret, ULONG + } + + if (!(key->block_size = get_block_size( id ))) return STATUS_INVALID_PARAMETER; ++ if (!(buffer = HeapAlloc( GetProcessHeap(), 0, secret_len ))) return STATUS_NO_MEMORY; ++ memcpy( buffer, secret, secret_len ); + + key->alg_id = id; + key->handle = 0; /* initialized on first use */ +- key->secret = secret; ++ key->secret = buffer; + key->secret_len = secret_len; + + return STATUS_SUCCESS; +-- +2.9.0 + diff --git a/patches/bcrypt-Improvements/0009-bcrypt-Handle-NULL-pointers-in-BCryptDuplicateHash-a.patch b/patches/bcrypt-Improvements/0009-bcrypt-Handle-NULL-pointers-in-BCryptDuplicateHash-a.patch new file mode 100644 index 00000000..333d1ac0 --- /dev/null +++ b/patches/bcrypt-Improvements/0009-bcrypt-Handle-NULL-pointers-in-BCryptDuplicateHash-a.patch @@ -0,0 +1,83 @@ +From 873d431347aa25effc70e47566e562c122a5edc8 Mon Sep 17 00:00:00 2001 +From: Sebastian Lackner +Date: Mon, 26 Dec 2016 04:23:31 +0100 +Subject: bcrypt: Handle NULL pointers in BCryptDuplicateHash and add tests. + +--- + dlls/bcrypt/bcrypt_main.c | 1 + + dlls/bcrypt/tests/bcrypt.c | 26 +++++++++++++++++++++++++- + 2 files changed, 26 insertions(+), 1 deletion(-) + +diff --git a/dlls/bcrypt/bcrypt_main.c b/dlls/bcrypt/bcrypt_main.c +index a9006a4..d1516cc 100644 +--- a/dlls/bcrypt/bcrypt_main.c ++++ b/dlls/bcrypt/bcrypt_main.c +@@ -681,6 +681,7 @@ NTSTATUS WINAPI BCryptDuplicateHash( BCRYPT_HASH_HANDLE handle, BCRYPT_HASH_HAND + TRACE( "%p, %p, %p, %u, %u\n", handle, handle_copy, object, object_count, flags ); + + if (!hash_orig || hash_orig->hdr.magic != MAGIC_HASH) return STATUS_INVALID_HANDLE; ++ if (!handle_copy) return STATUS_INVALID_PARAMETER; + if (!(hash_copy = HeapAlloc( GetProcessHeap(), 0, sizeof(*hash_copy) ))) + return STATUS_NO_MEMORY; + +diff --git a/dlls/bcrypt/tests/bcrypt.c b/dlls/bcrypt/tests/bcrypt.c +index 997b298..bfe3a7e 100644 +--- a/dlls/bcrypt/tests/bcrypt.c ++++ b/dlls/bcrypt/tests/bcrypt.c +@@ -33,6 +33,7 @@ static NTSTATUS (WINAPI *pBCryptCreateHash)(BCRYPT_ALG_HANDLE, BCRYPT_HASH_HANDL + ULONG, ULONG); + static NTSTATUS (WINAPI *pBCryptHash)(BCRYPT_ALG_HANDLE, UCHAR *, ULONG, UCHAR *, ULONG, UCHAR *, ULONG); + static NTSTATUS (WINAPI *pBCryptHashData)(BCRYPT_HASH_HANDLE, PUCHAR, ULONG, ULONG); ++static NTSTATUS (WINAPI *pBCryptDuplicateHash)(BCRYPT_HASH_HANDLE, BCRYPT_HASH_HANDLE *, UCHAR *, ULONG, ULONG); + static NTSTATUS (WINAPI *pBCryptFinishHash)(BCRYPT_HASH_HANDLE, PUCHAR, ULONG, ULONG); + static NTSTATUS (WINAPI *pBCryptDestroyHash)(BCRYPT_HASH_HANDLE); + static NTSTATUS (WINAPI *pBCryptGenRandom)(BCRYPT_ALG_HANDLE, PUCHAR, ULONG, ULONG); +@@ -173,7 +174,7 @@ static void test_sha1(void) + static const char expected[] = "961fa64958818f767707072755d7018dcd278e94"; + static const char expected_hmac[] = "2472cf65d0e090618d769d3e46f0d9446cf212da"; + BCRYPT_ALG_HANDLE alg; +- BCRYPT_HASH_HANDLE hash; ++ BCRYPT_HASH_HANDLE hash, hash2; + UCHAR buf[512], buf_hmac[1024], sha1[20], sha1_hmac[20]; + ULONG size, len; + char str[41]; +@@ -260,6 +261,28 @@ static void test_sha1(void) + test_hash_length(hash, 20); + test_alg_name(hash, "SHA1"); + ++ ret = pBCryptDuplicateHash(NULL, &hash2, NULL, 0, 0); ++ ok(ret == STATUS_INVALID_HANDLE, "got %08x\n", ret); ++ ++ ret = pBCryptDuplicateHash(hash, NULL, NULL, 0, 0); ++ ok(ret == STATUS_INVALID_PARAMETER, "got %08x\n", ret); ++ ++ hash2 = (void *)0xdeadbeef; ++ ret = pBCryptDuplicateHash(hash, &hash2, NULL, 0, 0); ++ ok(ret == STATUS_SUCCESS || broken(ret == STATUS_INVALID_PARAMETER) /* < Win 7 */, "got %08x\n", ret); ++ ++ if (ret == STATUS_SUCCESS) ++ { ++ memset(sha1_hmac, 0, sizeof(sha1_hmac)); ++ ret = pBCryptFinishHash(hash2, sha1_hmac, sizeof(sha1_hmac), 0); ++ ok(ret == STATUS_SUCCESS, "got %08x\n", ret); ++ format_hash( sha1_hmac, sizeof(sha1_hmac), str ); ++ ok(!strcmp(str, expected_hmac), "got %s\n", str); ++ ++ ret = pBCryptDestroyHash(hash2); ++ ok(ret == STATUS_SUCCESS, "got %08x\n", ret); ++ } ++ + memset(sha1_hmac, 0, sizeof(sha1_hmac)); + ret = pBCryptFinishHash(hash, sha1_hmac, sizeof(sha1_hmac), 0); + ok(ret == STATUS_SUCCESS, "got %08x\n", ret); +@@ -1179,6 +1202,7 @@ START_TEST(bcrypt) + pBCryptCreateHash = (void *)GetProcAddress(module, "BCryptCreateHash"); + pBCryptHash = (void *)GetProcAddress(module, "BCryptHash"); + pBCryptHashData = (void *)GetProcAddress(module, "BCryptHashData"); ++ pBCryptDuplicateHash = (void *)GetProcAddress(module, "BCryptDuplicateHash"); + pBCryptFinishHash = (void *)GetProcAddress(module, "BCryptFinishHash"); + pBCryptDestroyHash = (void *)GetProcAddress(module, "BCryptDestroyHash"); + pBCryptGenRandom = (void *)GetProcAddress(module, "BCryptGenRandom"); +-- +2.9.0 + diff --git a/patches/bcrypt-Improvements/0010-bcrypt-tests-Add-test-for-bugs-in-BCryptGetProperty.patch b/patches/bcrypt-Improvements/0010-bcrypt-tests-Add-test-for-bugs-in-BCryptGetProperty.patch new file mode 100644 index 00000000..e7ad8e58 --- /dev/null +++ b/patches/bcrypt-Improvements/0010-bcrypt-tests-Add-test-for-bugs-in-BCryptGetProperty.patch @@ -0,0 +1,29 @@ +From 83b15bed14a0999bacd2a5959297bff842a125e0 Mon Sep 17 00:00:00 2001 +From: Sebastian Lackner +Date: Mon, 26 Dec 2016 04:38:15 +0100 +Subject: bcrypt/tests: Add test for bugs in BCryptGetProperty. + +--- + dlls/bcrypt/tests/bcrypt.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/dlls/bcrypt/tests/bcrypt.c b/dlls/bcrypt/tests/bcrypt.c +index bfe3a7e..23e150e 100644 +--- a/dlls/bcrypt/tests/bcrypt.c ++++ b/dlls/bcrypt/tests/bcrypt.c +@@ -841,6 +841,12 @@ static void test_aes(void) + ok(size == 64, "got %u\n", size); + + size = 0; ++ ret = pBCryptGetProperty(alg, BCRYPT_CHAINING_MODE, mode, sizeof(mode) - 1, &size, 0); ++ todo_wine ok(ret == STATUS_BUFFER_TOO_SMALL, "got %08x\n", ret); ++ ok(size == 64, "got %u\n", size); ++ ++ size = 0; ++ memset(mode, 0, sizeof(mode)); + ret = pBCryptGetProperty(alg, BCRYPT_CHAINING_MODE, mode, sizeof(mode), &size, 0); + ok(ret == STATUS_SUCCESS, "got %08x\n", ret); + ok(!lstrcmpW((const WCHAR *)mode, BCRYPT_CHAIN_MODE_CBC), "got %s\n", mode); +-- +2.9.0 + diff --git a/patches/bcrypt-Improvements/0011-bcrypt-tests-Add-tests-for-AES-GCM-mode.patch b/patches/bcrypt-Improvements/0011-bcrypt-tests-Add-tests-for-AES-GCM-mode.patch new file mode 100644 index 00000000..37667bda --- /dev/null +++ b/patches/bcrypt-Improvements/0011-bcrypt-tests-Add-tests-for-AES-GCM-mode.patch @@ -0,0 +1,282 @@ +From 9e70e218c8a5c497ece71e17034ccae2e0baa218 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Michael=20M=C3=BCller?= +Date: Mon, 26 Dec 2016 05:37:02 +0100 +Subject: bcrypt/tests: Add tests for AES GCM mode. + +--- + dlls/bcrypt/tests/bcrypt.c | 155 ++++++++++++++++++++++++++++++++++++++++++++- + include/bcrypt.h | 29 +++++++++ + include/ntstatus.h | 2 + + 3 files changed, 185 insertions(+), 1 deletion(-) + +diff --git a/dlls/bcrypt/tests/bcrypt.c b/dlls/bcrypt/tests/bcrypt.c +index 23e150e..699a995 100644 +--- a/dlls/bcrypt/tests/bcrypt.c ++++ b/dlls/bcrypt/tests/bcrypt.c +@@ -941,6 +941,8 @@ static void test_BCryptGenerateSymmetricKey(void) + + static void test_BCryptEncrypt(void) + { ++ static UCHAR nonce[] = ++ {0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60}; + static UCHAR secret[] = + {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f}; + static UCHAR iv[] = +@@ -959,15 +961,28 @@ static void test_BCryptEncrypt(void) + {0xc6,0xa1,0x3b,0x37,0x87,0x8f,0x5b,0x82,0x6f,0x4f,0x81,0x62,0xa1,0xc8,0xd8,0x79, + 0xb1,0xa2,0x92,0x73,0xbe,0x2c,0x42,0x07,0xa5,0xac,0xe3,0x93,0x39,0x8c,0xb6,0xfb, + 0x87,0x5d,0xea,0xa3,0x7e,0x0f,0xde,0xfa,0xd9,0xec,0x6c,0x4e,0x3c,0x76,0x86,0xe4}; ++ static UCHAR expected4[] = ++ {0xe1,0x82,0xc3,0xc0,0x24,0xfb,0x86,0x85,0xf3,0xf1,0x2b,0x7d,0x09,0xb4,0x73,0x67, ++ 0x86,0x64,0xc3,0xfe,0xa3,0x07,0x61,0xf8,0x16,0xc9,0x78,0x7f,0xe7,0xb1,0xc4,0x94}; ++ static UCHAR expected_tag[] = ++ {0x89,0xb3,0x92,0x00,0x39,0x20,0x09,0xb4,0x6a,0xd6,0xaf,0xca,0x4b,0x5b,0xfd,0xd0}; ++ static UCHAR expected_tag2[] = ++ {0x9a,0x92,0x32,0x2c,0x61,0x2a,0xae,0xef,0x66,0x2a,0xfb,0x55,0xe9,0x48,0xdf,0xbd}; ++ BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO auth_info; ++ UCHAR *buf, ciphertext[48], ivbuf[16], tag[16]; ++ BCRYPT_AUTH_TAG_LENGTHS_STRUCT tag_length; + BCRYPT_ALG_HANDLE aes; + BCRYPT_KEY_HANDLE key; +- UCHAR *buf, ciphertext[48], ivbuf[16]; + ULONG size, len, i; + NTSTATUS ret; + + ret = pBCryptOpenAlgorithmProvider(&aes, BCRYPT_AES_ALGORITHM, NULL, 0); + ok(ret == STATUS_SUCCESS, "got %08x\n", ret); + ++ /****************** ++ * AES - CBC mode * ++ ******************/ ++ + len = 0xdeadbeef; + size = sizeof(len); + ret = pBCryptGetProperty(aes, BCRYPT_OBJECT_LENGTH, (UCHAR *)&len, sizeof(len), &size, 0); +@@ -1054,12 +1069,101 @@ static void test_BCryptEncrypt(void) + ok(ret == STATUS_SUCCESS, "got %08x\n", ret); + HeapFree(GetProcessHeap(), 0, buf); + ++ /****************** ++ * AES - GCM mode * ++ ******************/ ++ ++ size = 0; ++ ret = BCryptGetProperty(aes, BCRYPT_AUTH_TAG_LENGTH, NULL, 0, &size, 0); ++ todo_wine ok(ret == STATUS_NOT_SUPPORTED, "got %08x\n", ret); ++ ++ ret = BCryptSetProperty(aes, BCRYPT_CHAINING_MODE, (UCHAR*)BCRYPT_CHAIN_MODE_GCM, sizeof(BCRYPT_CHAIN_MODE_GCM), 0); ++ todo_wine ok(ret == STATUS_SUCCESS, "got %08x\n", ret); ++ ++ size = 0; ++ ret = BCryptGetProperty(aes, BCRYPT_AUTH_TAG_LENGTH, NULL, 0, &size, 0); ++ todo_wine ok(ret == STATUS_SUCCESS, "got %08x\n", ret); ++ todo_wine ok(size == sizeof(tag_length), "got %u\n", size); ++ ++ size = 0; ++ memset(&tag_length, 0, sizeof(tag_length)); ++ ret = BCryptGetProperty(aes, BCRYPT_AUTH_TAG_LENGTH, (UCHAR*)&tag_length, sizeof(tag_length), &size, 0); ++ todo_wine ok(ret == STATUS_SUCCESS, "got %08x\n", ret); ++ todo_wine ok(size == sizeof(tag_length), "got %u\n", size); ++ todo_wine ok(tag_length.dwMinLength == 12, "Expected 12, got %d\n", tag_length.dwMinLength); ++ todo_wine ok(tag_length.dwMaxLength == 16, "Expected 16, got %d\n", tag_length.dwMaxLength); ++ todo_wine ok(tag_length.dwIncrement == 1, "Expected 1, got %d\n", tag_length.dwIncrement); ++ ++ len = 0xdeadbeef; ++ size = sizeof(len); ++ ret = pBCryptGetProperty(aes, BCRYPT_OBJECT_LENGTH, (UCHAR *)&len, sizeof(len), &size, 0); ++ ok(ret == STATUS_SUCCESS, "got %08x\n", ret); ++ ++ buf = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len); ++ ret = pBCryptGenerateSymmetricKey(aes, &key, buf, len, secret, sizeof(secret), 0); ++ ok(ret == STATUS_SUCCESS, "got %08x\n", ret); ++ ++ memset(&auth_info, 0, sizeof(auth_info)); ++ auth_info.cbSize = sizeof(auth_info); ++ auth_info.dwInfoVersion = 1; ++ auth_info.pbNonce = nonce; ++ auth_info.cbNonce = sizeof(nonce); ++ auth_info.pbTag = tag; ++ auth_info.cbTag = sizeof(tag); ++ ++ /* input size is a multiple of block size */ ++ size = 0; ++ memcpy(ivbuf, iv, sizeof(iv)); ++ memset(ciphertext, 0xff, sizeof(ciphertext)); ++ memset(tag, 0xff, sizeof(tag)); ++ ret = pBCryptEncrypt(key, data2, 32, &auth_info, ivbuf, 16, ciphertext, 32, &size, 0); ++ todo_wine ok(ret == STATUS_SUCCESS, "got %08x\n", ret); ++ todo_wine ok(size == 32, "got %u\n", size); ++ todo_wine ok(!memcmp(ciphertext, expected4, sizeof(expected4)), "wrong data\n"); ++ todo_wine ok(!memcmp(tag, expected_tag, sizeof(expected_tag)), "wrong tag\n"); ++ for (i = 0; i < 32; i++) ++ todo_wine ok(ciphertext[i] == expected4[i], "%u: %02x != %02x\n", i, ciphertext[i], expected4[i]); ++ for (i = 0; i < 16; i++) ++ todo_wine ok(tag[i] == expected_tag[i], "%u: %02x != %02x\n", i, tag[i], expected_tag[i]); ++ ++ /* input size is not multiple of block size */ ++ size = 0; ++ memcpy(ivbuf, iv, sizeof(iv)); ++ memset(ciphertext, 0xff, sizeof(ciphertext)); ++ memset(tag, 0xff, sizeof(tag)); ++ ret = pBCryptEncrypt(key, data2, 24, &auth_info, ivbuf, 16, ciphertext, 24, &size, 0); ++ todo_wine ok(ret == STATUS_SUCCESS, "got %08x\n", ret); ++ todo_wine ok(size == 24, "got %u\n", size); ++ todo_wine ok(!memcmp(ciphertext, expected4, 24), "wrong data\n"); ++ todo_wine ok(!memcmp(tag, expected_tag2, sizeof(expected_tag2)), "wrong tag\n"); ++ for (i = 0; i < 24; i++) ++ todo_wine ok(ciphertext[i] == expected4[i], "%u: %02x != %02x\n", i, ciphertext[i], expected4[i]); ++ for (i = 0; i < 16; i++) ++ todo_wine ok(tag[i] == expected_tag2[i], "%u: %02x != %02x\n", i, tag[i], expected_tag2[i]); ++ ++ /* test with padding */ ++ memcpy(ivbuf, iv, sizeof(iv)); ++ memset(ciphertext, 0, sizeof(ciphertext)); ++ ret = pBCryptEncrypt(key, data2, 32, &auth_info, ivbuf, 16, ciphertext, 32, &size, BCRYPT_BLOCK_PADDING); ++ todo_wine ok(ret == STATUS_BUFFER_TOO_SMALL, "got %08x\n", ret); ++ ++ memcpy(ivbuf, iv, sizeof(iv)); ++ memset(ciphertext, 0, sizeof(ciphertext)); ++ ret = pBCryptEncrypt(key, data2, 32, &auth_info, ivbuf, 16, ciphertext, 48, &size, BCRYPT_BLOCK_PADDING); ++ todo_wine ok(ret == STATUS_INVALID_PARAMETER, "got %08x\n", ret); ++ ++ ret = pBCryptDestroyKey(key); ++ ok(ret == STATUS_SUCCESS, "got %08x\n", ret); ++ HeapFree(GetProcessHeap(), 0, buf); ++ + ret = pBCryptCloseAlgorithmProvider(aes, 0); + ok(ret == STATUS_SUCCESS, "got %08x\n", ret); + } + + static void test_BCryptDecrypt(void) + { ++ static UCHAR nonce[] = ++ {0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60}; + static UCHAR secret[] = + {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f}; + static UCHAR iv[] = +@@ -1081,6 +1185,12 @@ static void test_BCryptDecrypt(void) + {0xc6,0xa1,0x3b,0x37,0x87,0x8f,0x5b,0x82,0x6f,0x4f,0x81,0x62,0xa1,0xc8,0xd8,0x79, + 0xb1,0xa2,0x92,0x73,0xbe,0x2c,0x42,0x07,0xa5,0xac,0xe3,0x93,0x39,0x8c,0xb6,0xfb, + 0x87,0x5d,0xea,0xa3,0x7e,0x0f,0xde,0xfa,0xd9,0xec,0x6c,0x4e,0x3c,0x76,0x86,0xe4}; ++ static UCHAR ciphertext4[] = ++ {0xe1,0x82,0xc3,0xc0,0x24,0xfb,0x86,0x85,0xf3,0xf1,0x2b,0x7d,0x09,0xb4,0x73,0x67, ++ 0x86,0x64,0xc3,0xfe,0xa3,0x07,0x61,0xf8,0x16,0xc9,0x78,0x7f,0xe7,0xb1,0xc4,0x94}; ++ static UCHAR tag[] = ++ {0x89,0xb3,0x92,0x00,0x39,0x20,0x09,0xb4,0x6a,0xd6,0xaf,0xca,0x4b,0x5b,0xfd,0xd0}; ++ BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO auth_info; + BCRYPT_ALG_HANDLE aes; + BCRYPT_KEY_HANDLE key; + UCHAR *buf, plaintext[48], ivbuf[16]; +@@ -1090,6 +1200,10 @@ static void test_BCryptDecrypt(void) + ret = pBCryptOpenAlgorithmProvider(&aes, BCRYPT_AES_ALGORITHM, NULL, 0); + ok(ret == STATUS_SUCCESS, "got %08x\n", ret); + ++ /****************** ++ * AES - CBC mode * ++ ******************/ ++ + len = 0xdeadbeef; + size = sizeof(len); + ret = pBCryptGetProperty(aes, BCRYPT_OBJECT_LENGTH, (UCHAR *)&len, sizeof(len), &size, 0); +@@ -1187,6 +1301,45 @@ static void test_BCryptDecrypt(void) + ok(ret == STATUS_SUCCESS, "got %08x\n", ret); + HeapFree(GetProcessHeap(), 0, buf); + ++ /****************** ++ * AES - GCM mode * ++ ******************/ ++ ++ ret = BCryptSetProperty(aes, BCRYPT_CHAINING_MODE, (UCHAR*)BCRYPT_CHAIN_MODE_GCM, sizeof(BCRYPT_CHAIN_MODE_GCM), 0); ++ todo_wine ok(ret == STATUS_SUCCESS, "got %08x\n", ret); ++ ++ buf = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len); ++ ret = pBCryptGenerateSymmetricKey(aes, &key, buf, len, secret, sizeof(secret), 0); ++ ok(ret == STATUS_SUCCESS, "got %08x\n", ret); ++ ++ memset(&auth_info, 0, sizeof(auth_info)); ++ auth_info.cbSize = sizeof(auth_info); ++ auth_info.dwInfoVersion = 1; ++ auth_info.pbNonce = nonce; ++ auth_info.cbNonce = sizeof(nonce); ++ auth_info.pbTag = tag; ++ auth_info.cbTag = sizeof(tag); ++ ++ /* input size is a multiple of block size */ ++ size = 0; ++ memcpy(ivbuf, iv, sizeof(iv)); ++ memset(plaintext, 0, sizeof(plaintext)); ++ ret = pBCryptDecrypt(key, ciphertext4, 32, &auth_info, ivbuf, 16, plaintext, 32, &size, 0); ++ todo_wine ok(ret == STATUS_SUCCESS, "got %08x\n", ret); ++ todo_wine ok(size == 32, "got %u\n", size); ++ todo_wine ok(!memcmp(plaintext, expected3, sizeof(expected3)), "wrong data\n"); ++ ++ /* test with wrong tag */ ++ memcpy(ivbuf, iv, sizeof(iv)); ++ auth_info.pbTag = iv; /* wrong tag */ ++ ret = pBCryptDecrypt(key, ciphertext4, 32, &auth_info, ivbuf, 16, plaintext, 32, &size, 0); ++ todo_wine ok(ret == STATUS_AUTH_TAG_MISMATCH, "got %08x\n", ret); ++ todo_wine ok(size == 32, "got %u\n", size); ++ ++ ret = pBCryptDestroyKey(key); ++ ok(ret == STATUS_SUCCESS, "got %08x\n", ret); ++ HeapFree(GetProcessHeap(), 0, buf); ++ + ret = pBCryptCloseAlgorithmProvider(aes, 0); + ok(ret == STATUS_SUCCESS, "got %08x\n", ret); + } +diff --git a/include/bcrypt.h b/include/bcrypt.h +index 6af85e3..b8ff624 100644 +--- a/include/bcrypt.h ++++ b/include/bcrypt.h +@@ -85,6 +85,35 @@ typedef struct _BCRYPT_ALGORITHM_IDENTIFIER + ULONG dwFlags; + } BCRYPT_ALGORITHM_IDENTIFIER; + ++typedef struct __BCRYPT_KEY_LENGTHS_STRUCT ++{ ++ ULONG dwMinLength; ++ ULONG dwMaxLength; ++ ULONG dwIncrement; ++} BCRYPT_KEY_LENGTHS_STRUCT, BCRYPT_AUTH_TAG_LENGTHS_STRUCT; ++ ++typedef struct _BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO ++{ ++ ULONG cbSize; ++ ULONG dwInfoVersion; ++ UCHAR *pbNonce; ++ ULONG cbNonce; ++ UCHAR *pbAuthData; ++ ULONG cbAuthData; ++ UCHAR *pbTag; ++ ULONG cbTag; ++ UCHAR *pbMacContext; ++ ULONG cbMacContext; ++ ULONG cbAAD; ++ ULONGLONG cbData; ++ ULONG dwFlags; ++} BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO, *PBCRYPT_AUTHENTICATED_CIPHER_MODE_INFO; ++ ++#define BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO_VERSION 1 ++ ++#define BCRYPT_AUTH_MODE_CHAIN_CALLS_FLAG 0x00000001 ++#define BCRYPT_AUTH_MODE_IN_PROGRESS_FLAG 0x00000002 ++ + typedef PVOID BCRYPT_ALG_HANDLE; + typedef PVOID BCRYPT_KEY_HANDLE; + typedef PVOID BCRYPT_HANDLE; +diff --git a/include/ntstatus.h b/include/ntstatus.h +index 86dad85..7026de7 100644 +--- a/include/ntstatus.h ++++ b/include/ntstatus.h +@@ -990,6 +990,8 @@ + + #define STATUS_WOW_ASSERTION ((NTSTATUS) 0xC0009898) + ++#define STATUS_AUTH_TAG_MISMATCH ((NTSTATUS) 0xC000A002) ++ + #define RPC_NT_INVALID_STRING_BINDING ((NTSTATUS) 0xC0020001) + #define RPC_NT_WRONG_KIND_OF_BINDING ((NTSTATUS) 0xC0020002) + #define RPC_NT_INVALID_BINDING ((NTSTATUS) 0xC0020003) +-- +2.9.0 + diff --git a/patches/bcrypt-Improvements/0012-bcrypt-Pass-object-to-get_-alg-hash-_property-instea.patch b/patches/bcrypt-Improvements/0012-bcrypt-Pass-object-to-get_-alg-hash-_property-instea.patch new file mode 100644 index 00000000..d64be794 --- /dev/null +++ b/patches/bcrypt-Improvements/0012-bcrypt-Pass-object-to-get_-alg-hash-_property-instea.patch @@ -0,0 +1,133 @@ +From 9f68ea60cf840c9366aefe1ab486e9d1ee192843 Mon Sep 17 00:00:00 2001 +From: Sebastian Lackner +Date: Mon, 26 Dec 2016 06:18:01 +0100 +Subject: bcrypt: Pass object to get_{alg,hash}_property instead of alg_id. + +--- + dlls/bcrypt/bcrypt_main.c | 32 ++++++++++++++++---------------- + 1 file changed, 16 insertions(+), 16 deletions(-) + +diff --git a/dlls/bcrypt/bcrypt_main.c b/dlls/bcrypt/bcrypt_main.c +index d1516cc..8a5161b 100644 +--- a/dlls/bcrypt/bcrypt_main.c ++++ b/dlls/bcrypt/bcrypt_main.c +@@ -450,16 +450,16 @@ static NTSTATUS generic_alg_property( enum alg_id id, const WCHAR *prop, UCHAR * + return STATUS_NOT_IMPLEMENTED; + } + +-static NTSTATUS get_alg_property( enum alg_id id, const WCHAR *prop, UCHAR *buf, ULONG size, ULONG *ret_size ) ++static NTSTATUS get_alg_property( const struct algorithm *alg, const WCHAR *prop, UCHAR *buf, ULONG size, ULONG *ret_size ) + { + NTSTATUS status; + ULONG value; + +- status = generic_alg_property( id, prop, buf, size, ret_size ); ++ status = generic_alg_property( alg->id, prop, buf, size, ret_size ); + if (status != STATUS_NOT_IMPLEMENTED) + return status; + +- switch (id) ++ switch (alg->id) + { + case ALG_ID_AES: + if (!strcmpW( prop, BCRYPT_BLOCK_LENGTH )) +@@ -540,7 +540,7 @@ static NTSTATUS get_alg_property( enum alg_id id, const WCHAR *prop, UCHAR *buf, + return STATUS_NOT_IMPLEMENTED; + + default: +- FIXME( "unsupported algorithm %u\n", id ); ++ FIXME( "unsupported algorithm %u\n", alg->id ); + return STATUS_NOT_IMPLEMENTED; + } + +@@ -555,11 +555,11 @@ static NTSTATUS get_alg_property( enum alg_id id, const WCHAR *prop, UCHAR *buf, + return STATUS_SUCCESS; + } + +-static NTSTATUS get_hash_property( enum alg_id id, const WCHAR *prop, UCHAR *buf, ULONG size, ULONG *ret_size ) ++static NTSTATUS get_hash_property( const struct hash *hash, const WCHAR *prop, UCHAR *buf, ULONG size, ULONG *ret_size ) + { + NTSTATUS status; + +- status = generic_alg_property( id, prop, buf, size, ret_size ); ++ status = generic_alg_property( hash->alg_id, prop, buf, size, ret_size ); + if (status == STATUS_NOT_IMPLEMENTED) + FIXME( "unsupported property %s\n", debugstr_w(prop) ); + return status; +@@ -579,12 +579,12 @@ NTSTATUS WINAPI BCryptGetProperty( BCRYPT_HANDLE handle, LPCWSTR prop, UCHAR *bu + case MAGIC_ALG: + { + const struct algorithm *alg = (const struct algorithm *)object; +- return get_alg_property( alg->id, prop, buffer, count, res ); ++ return get_alg_property( alg, prop, buffer, count, res ); + } + case MAGIC_HASH: + { + const struct hash *hash = (const struct hash *)object; +- return get_hash_property( hash->alg_id, prop, buffer, count, res ); ++ return get_hash_property( hash, prop, buffer, count, res ); + } + default: + WARN( "unknown magic %08x\n", object->magic ); +@@ -783,34 +783,34 @@ struct key + ULONG secret_len; + }; + +-static ULONG get_block_size( enum alg_id alg ) ++static ULONG get_block_size( struct algorithm *alg ) + { + ULONG ret = 0, size = sizeof(ret); + get_alg_property( alg, BCRYPT_BLOCK_LENGTH, (UCHAR *)&ret, sizeof(ret), &size ); + return ret; + } + +-static NTSTATUS key_init( struct key *key, enum alg_id id, UCHAR *secret, ULONG secret_len ) ++static NTSTATUS key_init( struct key *key, struct algorithm *alg, UCHAR *secret, ULONG secret_len ) + { + UCHAR *buffer; + + if (!libgnutls_handle) return STATUS_INTERNAL_ERROR; + +- switch (id) ++ switch (alg->id) + { + case ALG_ID_AES: + break; + + default: +- FIXME( "algorithm %u not supported\n", id ); ++ FIXME( "algorithm %u not supported\n", alg->id ); + return STATUS_NOT_SUPPORTED; + } + +- if (!(key->block_size = get_block_size( id ))) return STATUS_INVALID_PARAMETER; ++ if (!(key->block_size = get_block_size( alg ))) return STATUS_INVALID_PARAMETER; + if (!(buffer = HeapAlloc( GetProcessHeap(), 0, secret_len ))) return STATUS_NO_MEMORY; + memcpy( buffer, secret, secret_len ); + +- key->alg_id = id; ++ key->alg_id = alg->id; + key->handle = 0; /* initialized on first use */ + key->secret = buffer; + key->secret_len = secret_len; +@@ -906,7 +906,7 @@ struct key + ULONG block_size; + }; + +-static NTSTATUS key_init( struct key *key, enum alg_id id, const UCHAR *secret, ULONG secret_len ) ++static NTSTATUS key_init( struct key *key, struct algorithm *alg, UCHAR *secret, ULONG secret_len ) + { + ERR( "support for keys not available at build time\n" ); + return STATUS_NOT_IMPLEMENTED; +@@ -955,7 +955,7 @@ NTSTATUS WINAPI BCryptGenerateSymmetricKey( BCRYPT_ALG_HANDLE algorithm, BCRYPT_ + if (!(key = HeapAlloc( GetProcessHeap(), 0, sizeof(*key) ))) return STATUS_NO_MEMORY; + key->hdr.magic = MAGIC_KEY; + +- if ((status = key_init( key, alg->id, secret, secret_len ))) ++ if ((status = key_init( key, alg, secret, secret_len ))) + { + HeapFree( GetProcessHeap(), 0, key ); + return status; +-- +2.9.0 + diff --git a/patches/bcrypt-Improvements/0013-bcrypt-Implement-BCryptSetProperty-for-algorithms.patch b/patches/bcrypt-Improvements/0013-bcrypt-Implement-BCryptSetProperty-for-algorithms.patch new file mode 100644 index 00000000..abc60ce8 --- /dev/null +++ b/patches/bcrypt-Improvements/0013-bcrypt-Implement-BCryptSetProperty-for-algorithms.patch @@ -0,0 +1,149 @@ +From 5313398cdabe97a17b21e2d9f25a191da7bd9434 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Michael=20M=C3=BCller?= +Date: Mon, 26 Dec 2016 06:08:33 +0100 +Subject: bcrypt: Implement BCryptSetProperty for algorithms. + +--- + dlls/bcrypt/bcrypt_main.c | 66 ++++++++++++++++++++++++++++++++++++++++++++-- + dlls/bcrypt/tests/bcrypt.c | 6 ++--- + 2 files changed, 67 insertions(+), 5 deletions(-) + +diff --git a/dlls/bcrypt/bcrypt_main.c b/dlls/bcrypt/bcrypt_main.c +index 8a5161b..4757878 100644 +--- a/dlls/bcrypt/bcrypt_main.c ++++ b/dlls/bcrypt/bcrypt_main.c +@@ -153,6 +153,12 @@ enum alg_id + ALG_ID_SHA512 + }; + ++enum mode_id ++{ ++ MODE_ID_CBC, ++ MODE_ID_GCM ++}; ++ + #define MAX_HASH_OUTPUT_BYTES 64 + + static const struct { +@@ -172,6 +178,7 @@ struct algorithm + { + struct object hdr; + enum alg_id id; ++ enum mode_id mode; + BOOL hmac; + }; + +@@ -265,6 +272,7 @@ NTSTATUS WINAPI BCryptOpenAlgorithmProvider( BCRYPT_ALG_HANDLE *handle, LPCWSTR + if (!(alg = HeapAlloc( GetProcessHeap(), 0, sizeof(*alg) ))) return STATUS_NO_MEMORY; + alg->hdr.magic = MAGIC_ALG; + alg->id = alg_id; ++ alg->mode = MODE_ID_CBC; + alg->hmac = flags & BCRYPT_ALG_HANDLE_HMAC_FLAG; + + *handle = alg; +@@ -555,6 +563,40 @@ static NTSTATUS get_alg_property( const struct algorithm *alg, const WCHAR *prop + return STATUS_SUCCESS; + } + ++static NTSTATUS set_alg_property( struct algorithm *alg, const WCHAR *prop, UCHAR *value, ULONG size, ULONG flags ) ++{ ++ switch (alg->id) ++ { ++ case ALG_ID_AES: ++ if (!strcmpW( prop, BCRYPT_CHAINING_MODE )) ++ { ++ if (size == sizeof(BCRYPT_CHAIN_MODE_CBC) && ++ !strncmpW( (WCHAR *)value, BCRYPT_CHAIN_MODE_CBC, size )) ++ { ++ alg->mode = MODE_ID_CBC; ++ return STATUS_SUCCESS; ++ } ++ else if (size == sizeof(BCRYPT_CHAIN_MODE_GCM) && ++ !strncmpW( (WCHAR *)value, BCRYPT_CHAIN_MODE_GCM, size )) ++ { ++ alg->mode = MODE_ID_GCM; ++ return STATUS_SUCCESS; ++ } ++ else ++ { ++ FIXME( "unsupported mode %s\n", debugstr_wn( (WCHAR *)value, size ) ); ++ return STATUS_NOT_IMPLEMENTED; ++ } ++ } ++ FIXME( "unsupported aes algorithm property %s\n", debugstr_w(prop) ); ++ return STATUS_NOT_IMPLEMENTED; ++ ++ default: ++ FIXME( "unsupported algorithm %u\n", alg->id ); ++ return STATUS_NOT_IMPLEMENTED; ++ } ++} ++ + static NTSTATUS get_hash_property( const struct hash *hash, const WCHAR *prop, UCHAR *buf, ULONG size, ULONG *ret_size ) + { + NTSTATUS status; +@@ -595,8 +637,28 @@ NTSTATUS WINAPI BCryptGetProperty( BCRYPT_HANDLE handle, LPCWSTR prop, UCHAR *bu + NTSTATUS WINAPI BCryptSetProperty( BCRYPT_HANDLE handle, const WCHAR *prop, UCHAR *value, + ULONG size, ULONG flags ) + { +- FIXME( "%p, %s, %p, %u, %08x\n", handle, debugstr_w(prop), value, size, flags ); +- return STATUS_NOT_IMPLEMENTED; ++ struct object *object = handle; ++ ++ TRACE( "%p, %s, %p, %u, %08x\n", handle, debugstr_w(prop), value, size, flags ); ++ ++ if (!object) return STATUS_INVALID_HANDLE; ++ ++ switch (object->magic) ++ { ++ case MAGIC_ALG: ++ { ++ struct algorithm *alg = (struct algorithm *)object; ++ return set_alg_property( alg, prop, value, size, flags ); ++ } ++ case MAGIC_KEY: ++ { ++ FIXME( "keys not implemented yet\n" ); ++ return STATUS_NOT_IMPLEMENTED; ++ } ++ default: ++ WARN( "unknown magic %08x\n", object->magic ); ++ return STATUS_INVALID_HANDLE; ++ } + } + + NTSTATUS WINAPI BCryptCreateHash( BCRYPT_ALG_HANDLE algorithm, BCRYPT_HASH_HANDLE *handle, UCHAR *object, ULONG objectlen, +diff --git a/dlls/bcrypt/tests/bcrypt.c b/dlls/bcrypt/tests/bcrypt.c +index 699a995..d850738 100644 +--- a/dlls/bcrypt/tests/bcrypt.c ++++ b/dlls/bcrypt/tests/bcrypt.c +@@ -889,7 +889,7 @@ static void test_BCryptGenerateSymmetricKey(void) + + ret = pBCryptSetProperty(aes, BCRYPT_CHAINING_MODE, (UCHAR *)BCRYPT_CHAIN_MODE_CBC, + sizeof(BCRYPT_CHAIN_MODE_CBC), 0); +- todo_wine ok(ret == STATUS_SUCCESS, "got %08x\n", ret); ++ ok(ret == STATUS_SUCCESS, "got %08x\n", ret); + + size = 0xdeadbeef; + ret = pBCryptEncrypt(key, NULL, 0, NULL, NULL, 0, NULL, 0, &size, 0); +@@ -1078,7 +1078,7 @@ static void test_BCryptEncrypt(void) + todo_wine ok(ret == STATUS_NOT_SUPPORTED, "got %08x\n", ret); + + ret = BCryptSetProperty(aes, BCRYPT_CHAINING_MODE, (UCHAR*)BCRYPT_CHAIN_MODE_GCM, sizeof(BCRYPT_CHAIN_MODE_GCM), 0); +- todo_wine ok(ret == STATUS_SUCCESS, "got %08x\n", ret); ++ ok(ret == STATUS_SUCCESS, "got %08x\n", ret); + + size = 0; + ret = BCryptGetProperty(aes, BCRYPT_AUTH_TAG_LENGTH, NULL, 0, &size, 0); +@@ -1306,7 +1306,7 @@ static void test_BCryptDecrypt(void) + ******************/ + + ret = BCryptSetProperty(aes, BCRYPT_CHAINING_MODE, (UCHAR*)BCRYPT_CHAIN_MODE_GCM, sizeof(BCRYPT_CHAIN_MODE_GCM), 0); +- todo_wine ok(ret == STATUS_SUCCESS, "got %08x\n", ret); ++ ok(ret == STATUS_SUCCESS, "got %08x\n", ret); + + buf = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len); + ret = pBCryptGenerateSymmetricKey(aes, &key, buf, len, secret, sizeof(secret), 0); +-- +2.9.0 + diff --git a/patches/bcrypt-Improvements/0014-bcrypt-Implement-BCryptGetProperty-for-BCRYPT_CHAINI.patch b/patches/bcrypt-Improvements/0014-bcrypt-Implement-BCryptGetProperty-for-BCRYPT_CHAINI.patch new file mode 100644 index 00000000..3a9b2a66 --- /dev/null +++ b/patches/bcrypt-Improvements/0014-bcrypt-Implement-BCryptGetProperty-for-BCRYPT_CHAINI.patch @@ -0,0 +1,58 @@ +From f7749755c11e54d1e75cd05b6656d2c474ade8ae Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Michael=20M=C3=BCller?= +Date: Mon, 26 Dec 2016 06:46:11 +0100 +Subject: bcrypt: Implement BCryptGetProperty for BCRYPT_CHAINING_MODE. + +--- + dlls/bcrypt/bcrypt_main.c | 19 ++++++++++--------- + dlls/bcrypt/tests/bcrypt.c | 2 +- + 2 files changed, 11 insertions(+), 10 deletions(-) + +diff --git a/dlls/bcrypt/bcrypt_main.c b/dlls/bcrypt/bcrypt_main.c +index 4757878..24dee8b 100644 +--- a/dlls/bcrypt/bcrypt_main.c ++++ b/dlls/bcrypt/bcrypt_main.c +@@ -482,17 +482,18 @@ static NTSTATUS get_alg_property( const struct algorithm *alg, const WCHAR *prop + } + if (!strcmpW( prop, BCRYPT_CHAINING_MODE )) + { +- if (size >= sizeof(BCRYPT_CHAIN_MODE_CBC)) ++ const WCHAR *mode; ++ switch (alg->mode) + { +- memcpy(buf, BCRYPT_CHAIN_MODE_CBC, sizeof(BCRYPT_CHAIN_MODE_CBC)); +- *ret_size = sizeof(BCRYPT_CHAIN_MODE_CBC) * sizeof(WCHAR); +- return STATUS_SUCCESS; +- } +- else +- { +- *ret_size = sizeof(BCRYPT_CHAIN_MODE_CBC) * sizeof(WCHAR); +- return STATUS_BUFFER_TOO_SMALL; ++ case MODE_ID_GCM: mode = BCRYPT_CHAIN_MODE_GCM; break; ++ case MODE_ID_CBC: mode = BCRYPT_CHAIN_MODE_CBC; break; ++ default: return STATUS_NOT_IMPLEMENTED; + } ++ ++ *ret_size = 64; ++ if (size < *ret_size) return STATUS_BUFFER_TOO_SMALL; ++ memcpy( buf, mode, (strlenW(mode) + 1) * sizeof(WCHAR) ); ++ return STATUS_SUCCESS; + } + FIXME( "unsupported aes algorithm property %s\n", debugstr_w(prop) ); + return STATUS_NOT_IMPLEMENTED; +diff --git a/dlls/bcrypt/tests/bcrypt.c b/dlls/bcrypt/tests/bcrypt.c +index d850738..bbf18c4 100644 +--- a/dlls/bcrypt/tests/bcrypt.c ++++ b/dlls/bcrypt/tests/bcrypt.c +@@ -842,7 +842,7 @@ static void test_aes(void) + + size = 0; + ret = pBCryptGetProperty(alg, BCRYPT_CHAINING_MODE, mode, sizeof(mode) - 1, &size, 0); +- todo_wine ok(ret == STATUS_BUFFER_TOO_SMALL, "got %08x\n", ret); ++ ok(ret == STATUS_BUFFER_TOO_SMALL, "got %08x\n", ret); + ok(size == 64, "got %u\n", size); + + size = 0; +-- +2.9.0 + diff --git a/patches/bcrypt-Improvements/0015-bcrypt-Implement-BCryptGetProperty-for-BCRYPT_AUTH_T.patch b/patches/bcrypt-Improvements/0015-bcrypt-Implement-BCryptGetProperty-for-BCRYPT_AUTH_T.patch new file mode 100644 index 00000000..d2d88f96 --- /dev/null +++ b/patches/bcrypt-Improvements/0015-bcrypt-Implement-BCryptGetProperty-for-BCRYPT_AUTH_T.patch @@ -0,0 +1,75 @@ +From 017f5d467e537e5159f9c14f703df97661a1453e Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Michael=20M=C3=BCller?= +Date: Mon, 26 Dec 2016 06:50:28 +0100 +Subject: bcrypt: Implement BCryptGetProperty for BCRYPT_AUTH_TAG_LENGTH. + +--- + dlls/bcrypt/bcrypt_main.c | 14 ++++++++++++++ + dlls/bcrypt/tests/bcrypt.c | 16 ++++++++-------- + 2 files changed, 22 insertions(+), 8 deletions(-) + +diff --git a/dlls/bcrypt/bcrypt_main.c b/dlls/bcrypt/bcrypt_main.c +index 24dee8b..dc5c798 100644 +--- a/dlls/bcrypt/bcrypt_main.c ++++ b/dlls/bcrypt/bcrypt_main.c +@@ -495,6 +495,20 @@ static NTSTATUS get_alg_property( const struct algorithm *alg, const WCHAR *prop + memcpy( buf, mode, (strlenW(mode) + 1) * sizeof(WCHAR) ); + return STATUS_SUCCESS; + } ++ if (!strcmpW( prop, BCRYPT_AUTH_TAG_LENGTH )) ++ { ++ BCRYPT_AUTH_TAG_LENGTHS_STRUCT *tag_length = (void *)buf; ++ if (alg->mode != MODE_ID_GCM) return STATUS_NOT_SUPPORTED; ++ *ret_size = sizeof(*tag_length); ++ if (tag_length && size < *ret_size) return STATUS_BUFFER_TOO_SMALL; ++ if (tag_length) ++ { ++ tag_length->dwMinLength = 12; ++ tag_length->dwMaxLength = 16; ++ tag_length->dwIncrement = 1; ++ } ++ return STATUS_SUCCESS; ++ } + FIXME( "unsupported aes algorithm property %s\n", debugstr_w(prop) ); + return STATUS_NOT_IMPLEMENTED; + +diff --git a/dlls/bcrypt/tests/bcrypt.c b/dlls/bcrypt/tests/bcrypt.c +index bbf18c4..513d11f 100644 +--- a/dlls/bcrypt/tests/bcrypt.c ++++ b/dlls/bcrypt/tests/bcrypt.c +@@ -1075,24 +1075,24 @@ static void test_BCryptEncrypt(void) + + size = 0; + ret = BCryptGetProperty(aes, BCRYPT_AUTH_TAG_LENGTH, NULL, 0, &size, 0); +- todo_wine ok(ret == STATUS_NOT_SUPPORTED, "got %08x\n", ret); ++ ok(ret == STATUS_NOT_SUPPORTED, "got %08x\n", ret); + + ret = BCryptSetProperty(aes, BCRYPT_CHAINING_MODE, (UCHAR*)BCRYPT_CHAIN_MODE_GCM, sizeof(BCRYPT_CHAIN_MODE_GCM), 0); + ok(ret == STATUS_SUCCESS, "got %08x\n", ret); + + size = 0; + ret = BCryptGetProperty(aes, BCRYPT_AUTH_TAG_LENGTH, NULL, 0, &size, 0); +- todo_wine ok(ret == STATUS_SUCCESS, "got %08x\n", ret); +- todo_wine ok(size == sizeof(tag_length), "got %u\n", size); ++ ok(ret == STATUS_SUCCESS, "got %08x\n", ret); ++ ok(size == sizeof(tag_length), "got %u\n", size); + + size = 0; + memset(&tag_length, 0, sizeof(tag_length)); + ret = BCryptGetProperty(aes, BCRYPT_AUTH_TAG_LENGTH, (UCHAR*)&tag_length, sizeof(tag_length), &size, 0); +- todo_wine ok(ret == STATUS_SUCCESS, "got %08x\n", ret); +- todo_wine ok(size == sizeof(tag_length), "got %u\n", size); +- todo_wine ok(tag_length.dwMinLength == 12, "Expected 12, got %d\n", tag_length.dwMinLength); +- todo_wine ok(tag_length.dwMaxLength == 16, "Expected 16, got %d\n", tag_length.dwMaxLength); +- todo_wine ok(tag_length.dwIncrement == 1, "Expected 1, got %d\n", tag_length.dwIncrement); ++ ok(ret == STATUS_SUCCESS, "got %08x\n", ret); ++ ok(size == sizeof(tag_length), "got %u\n", size); ++ ok(tag_length.dwMinLength == 12, "Expected 12, got %d\n", tag_length.dwMinLength); ++ ok(tag_length.dwMaxLength == 16, "Expected 16, got %d\n", tag_length.dwMaxLength); ++ ok(tag_length.dwIncrement == 1, "Expected 1, got %d\n", tag_length.dwIncrement); + + len = 0xdeadbeef; + size = sizeof(len); +-- +2.9.0 + diff --git a/patches/bcrypt-Improvements/0016-bcrypt-Fix-string-comparison-in-set_alg_property.patch b/patches/bcrypt-Improvements/0016-bcrypt-Fix-string-comparison-in-set_alg_property.patch new file mode 100644 index 00000000..cf597c86 --- /dev/null +++ b/patches/bcrypt-Improvements/0016-bcrypt-Fix-string-comparison-in-set_alg_property.patch @@ -0,0 +1,56 @@ +From 698dc9ea948f98eba154453e6cdc79919373d007 Mon Sep 17 00:00:00 2001 +From: Sebastian Lackner +Date: Mon, 26 Dec 2016 07:21:27 +0100 +Subject: bcrypt: Fix string comparison in set_alg_property. + +--- + dlls/bcrypt/bcrypt_main.c | 6 ++---- + dlls/bcrypt/tests/bcrypt.c | 11 +++++++++++ + 2 files changed, 13 insertions(+), 4 deletions(-) + +diff --git a/dlls/bcrypt/bcrypt_main.c b/dlls/bcrypt/bcrypt_main.c +index dc5c798..7eea550 100644 +--- a/dlls/bcrypt/bcrypt_main.c ++++ b/dlls/bcrypt/bcrypt_main.c +@@ -585,14 +585,12 @@ static NTSTATUS set_alg_property( struct algorithm *alg, const WCHAR *prop, UCHA + case ALG_ID_AES: + if (!strcmpW( prop, BCRYPT_CHAINING_MODE )) + { +- if (size == sizeof(BCRYPT_CHAIN_MODE_CBC) && +- !strncmpW( (WCHAR *)value, BCRYPT_CHAIN_MODE_CBC, size )) ++ if (!strncmpW( (WCHAR *)value, BCRYPT_CHAIN_MODE_CBC, size )) + { + alg->mode = MODE_ID_CBC; + return STATUS_SUCCESS; + } +- else if (size == sizeof(BCRYPT_CHAIN_MODE_GCM) && +- !strncmpW( (WCHAR *)value, BCRYPT_CHAIN_MODE_GCM, size )) ++ else if (!strncmpW( (WCHAR *)value, BCRYPT_CHAIN_MODE_GCM, size )) + { + alg->mode = MODE_ID_GCM; + return STATUS_SUCCESS; +diff --git a/dlls/bcrypt/tests/bcrypt.c b/dlls/bcrypt/tests/bcrypt.c +index 513d11f..77aacdc 100644 +--- a/dlls/bcrypt/tests/bcrypt.c ++++ b/dlls/bcrypt/tests/bcrypt.c +@@ -852,6 +852,17 @@ static void test_aes(void) + ok(!lstrcmpW((const WCHAR *)mode, BCRYPT_CHAIN_MODE_CBC), "got %s\n", mode); + ok(size == 64, "got %u\n", size); + ++ memcpy(mode, BCRYPT_CHAIN_MODE_GCM, sizeof(BCRYPT_CHAIN_MODE_GCM)); ++ ret = pBCryptSetProperty(alg, BCRYPT_CHAINING_MODE, mode, sizeof(mode), 0); ++ ok(ret == STATUS_SUCCESS, "got %08x\n", ret); ++ ++ size = 0; ++ memset(mode, 0, sizeof(mode)); ++ ret = pBCryptGetProperty(alg, BCRYPT_CHAINING_MODE, mode, sizeof(mode), &size, 0); ++ ok(ret == STATUS_SUCCESS, "got %08x\n", ret); ++ ok(!lstrcmpW((const WCHAR *)mode, BCRYPT_CHAIN_MODE_GCM), "got %s\n", mode); ++ ok(size == 64, "got %u\n", size); ++ + test_alg_name(alg, "AES"); + + ret = pBCryptCloseAlgorithmProvider(alg, 0); +-- +2.9.0 + diff --git a/patches/bcrypt-Improvements/0017-bcrypt-Implement-BCryptEncrypt-for-AES-GCM-mode.patch b/patches/bcrypt-Improvements/0017-bcrypt-Implement-BCryptEncrypt-for-AES-GCM-mode.patch new file mode 100644 index 00000000..8d88b5c8 --- /dev/null +++ b/patches/bcrypt-Improvements/0017-bcrypt-Implement-BCryptEncrypt-for-AES-GCM-mode.patch @@ -0,0 +1,168 @@ +From ad15e50c53901317847236410be7b1d005e1a502 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Michael=20M=C3=BCller?= +Date: Mon, 26 Dec 2016 07:46:57 +0100 +Subject: bcrypt: Implement BCryptEncrypt for AES GCM mode. + +--- + dlls/bcrypt/bcrypt_main.c | 50 ++++++++++++++++++++++++++++++++++++++-------- + dlls/bcrypt/tests/bcrypt.c | 18 ++++++++--------- + 2 files changed, 51 insertions(+), 17 deletions(-) + +diff --git a/dlls/bcrypt/bcrypt_main.c b/dlls/bcrypt/bcrypt_main.c +index 774f29a..a143580 100644 +--- a/dlls/bcrypt/bcrypt_main.c ++++ b/dlls/bcrypt/bcrypt_main.c +@@ -62,6 +62,12 @@ MAKE_FUNCPTR(gnutls_global_set_log_level); + MAKE_FUNCPTR(gnutls_perror); + #undef MAKE_FUNCPTR + ++#if GNUTLS_VERSION_MAJOR < 3 ++#define GNUTLS_CIPHER_AES_192_CBC 92 ++#define GNUTLS_CIPHER_AES_128_GCM 93 ++#define GNUTLS_CIPHER_AES_256_GCM 94 ++#endif ++ + static void gnutls_log( int level, const char *msg ) + { + TRACE( "<%d> %s", level, msg ); +@@ -852,6 +858,7 @@ struct key + { + struct object hdr; + enum alg_id alg_id; ++ enum mode_id mode; + ULONG block_size; + gnutls_cipher_hd_t handle; + UCHAR *secret; +@@ -886,6 +893,7 @@ static NTSTATUS key_init( struct key *key, struct algorithm *alg, UCHAR *secret, + memcpy( buffer, secret, secret_len ); + + key->alg_id = alg->id; ++ key->mode = alg->mode; + key->handle = 0; /* initialized on first use */ + key->secret = buffer; + key->secret_len = secret_len; +@@ -898,9 +906,13 @@ static gnutls_cipher_algorithm_t get_gnutls_cipher( const struct key *key ) + switch (key->alg_id) + { + case ALG_ID_AES: +- FIXME( "handle block size and chaining mode\n" ); +- return GNUTLS_CIPHER_AES_128_CBC; +- ++ WARN( "handle block size\n" ); ++ switch (key->mode) ++ { ++ case MODE_ID_GCM: return GNUTLS_CIPHER_AES_128_GCM; ++ case MODE_ID_CBC: ++ default: return GNUTLS_CIPHER_AES_128_CBC; ++ } + default: + FIXME( "algorithm %u not supported\n", key->alg_id ); + return GNUTLS_CIPHER_UNKNOWN; +@@ -978,12 +990,14 @@ static NTSTATUS key_destroy( struct key *key ) + struct key + { + struct object hdr; ++ enum mode_id mode; + ULONG block_size; + }; + + static NTSTATUS key_init( struct key *key, struct algorithm *alg, UCHAR *secret, ULONG secret_len ) + { + ERR( "support for keys not available at build time\n" ); ++ key->mode = MODE_ID_CBC; + return STATUS_NOT_IMPLEMENTED; + } + +@@ -1063,17 +1077,37 @@ NTSTATUS WINAPI BCryptEncrypt( BCRYPT_KEY_HANDLE handle, UCHAR *input, ULONG inp + padding, iv, iv_len, output, output_len, ret_len, flags ); + + if (!key || key->hdr.magic != MAGIC_KEY) return STATUS_INVALID_HANDLE; +- if (padding) +- { +- FIXME( "padding info not implemented\n" ); +- return STATUS_NOT_IMPLEMENTED; +- } + if (flags & ~BCRYPT_BLOCK_PADDING) + { + FIXME( "flags %08x not implemented\n", flags ); + return STATUS_NOT_IMPLEMENTED; + } + ++ if (key->mode == MODE_ID_GCM) ++ { ++ BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO *auth_info = padding; ++ ++ if (!auth_info) return STATUS_INVALID_PARAMETER; ++ if (!auth_info->pbNonce) return STATUS_INVALID_PARAMETER; ++ if (!auth_info->pbTag) return STATUS_INVALID_PARAMETER; ++ if (auth_info->cbTag < 12 || auth_info->cbTag > 16) return STATUS_INVALID_PARAMETER; ++ if (auth_info->dwFlags & BCRYPT_AUTH_MODE_CHAIN_CALLS_FLAG) ++ FIXME( "call chaining not implemented\n" ); ++ ++ if ((status = key_set_params( key, auth_info->pbNonce, auth_info->cbNonce ))) ++ return status; ++ ++ *ret_len = input_len; ++ if (flags & BCRYPT_BLOCK_PADDING) return STATUS_INVALID_PARAMETER; ++ if (!output) return STATUS_SUCCESS; ++ if (output_len < *ret_len) return STATUS_BUFFER_TOO_SMALL; ++ ++ if ((status = key_encrypt( key, input, input_len, output, output_len ))) ++ return status; ++ ++ return STATUS_SUCCESS; ++ } ++ + if ((status = key_set_params( key, iv, iv_len ))) return status; + + *ret_len = input_len; +diff --git a/dlls/bcrypt/tests/bcrypt.c b/dlls/bcrypt/tests/bcrypt.c +index 77aacdc..d2a74ce 100644 +--- a/dlls/bcrypt/tests/bcrypt.c ++++ b/dlls/bcrypt/tests/bcrypt.c +@@ -1128,12 +1128,12 @@ static void test_BCryptEncrypt(void) + memset(ciphertext, 0xff, sizeof(ciphertext)); + memset(tag, 0xff, sizeof(tag)); + ret = pBCryptEncrypt(key, data2, 32, &auth_info, ivbuf, 16, ciphertext, 32, &size, 0); +- todo_wine ok(ret == STATUS_SUCCESS, "got %08x\n", ret); +- todo_wine ok(size == 32, "got %u\n", size); +- todo_wine ok(!memcmp(ciphertext, expected4, sizeof(expected4)), "wrong data\n"); ++ ok(ret == STATUS_SUCCESS, "got %08x\n", ret); ++ ok(size == 32, "got %u\n", size); ++ ok(!memcmp(ciphertext, expected4, sizeof(expected4)), "wrong data\n"); + todo_wine ok(!memcmp(tag, expected_tag, sizeof(expected_tag)), "wrong tag\n"); + for (i = 0; i < 32; i++) +- todo_wine ok(ciphertext[i] == expected4[i], "%u: %02x != %02x\n", i, ciphertext[i], expected4[i]); ++ ok(ciphertext[i] == expected4[i], "%u: %02x != %02x\n", i, ciphertext[i], expected4[i]); + for (i = 0; i < 16; i++) + todo_wine ok(tag[i] == expected_tag[i], "%u: %02x != %02x\n", i, tag[i], expected_tag[i]); + +@@ -1143,12 +1143,12 @@ static void test_BCryptEncrypt(void) + memset(ciphertext, 0xff, sizeof(ciphertext)); + memset(tag, 0xff, sizeof(tag)); + ret = pBCryptEncrypt(key, data2, 24, &auth_info, ivbuf, 16, ciphertext, 24, &size, 0); +- todo_wine ok(ret == STATUS_SUCCESS, "got %08x\n", ret); +- todo_wine ok(size == 24, "got %u\n", size); +- todo_wine ok(!memcmp(ciphertext, expected4, 24), "wrong data\n"); ++ ok(ret == STATUS_SUCCESS, "got %08x\n", ret); ++ ok(size == 24, "got %u\n", size); ++ ok(!memcmp(ciphertext, expected4, 24), "wrong data\n"); + todo_wine ok(!memcmp(tag, expected_tag2, sizeof(expected_tag2)), "wrong tag\n"); + for (i = 0; i < 24; i++) +- todo_wine ok(ciphertext[i] == expected4[i], "%u: %02x != %02x\n", i, ciphertext[i], expected4[i]); ++ ok(ciphertext[i] == expected4[i], "%u: %02x != %02x\n", i, ciphertext[i], expected4[i]); + for (i = 0; i < 16; i++) + todo_wine ok(tag[i] == expected_tag2[i], "%u: %02x != %02x\n", i, tag[i], expected_tag2[i]); + +@@ -1161,7 +1161,7 @@ static void test_BCryptEncrypt(void) + memcpy(ivbuf, iv, sizeof(iv)); + memset(ciphertext, 0, sizeof(ciphertext)); + ret = pBCryptEncrypt(key, data2, 32, &auth_info, ivbuf, 16, ciphertext, 48, &size, BCRYPT_BLOCK_PADDING); +- todo_wine ok(ret == STATUS_INVALID_PARAMETER, "got %08x\n", ret); ++ ok(ret == STATUS_INVALID_PARAMETER, "got %08x\n", ret); + + ret = pBCryptDestroyKey(key); + ok(ret == STATUS_SUCCESS, "got %08x\n", ret); +-- +2.9.0 + diff --git a/patches/bcrypt-Improvements/0018-bcrypt-Implement-BCryptDecrypt-for-AES-GCM-mode.patch b/patches/bcrypt-Improvements/0018-bcrypt-Implement-BCryptDecrypt-for-AES-GCM-mode.patch new file mode 100644 index 00000000..ca15f08a --- /dev/null +++ b/patches/bcrypt-Improvements/0018-bcrypt-Implement-BCryptDecrypt-for-AES-GCM-mode.patch @@ -0,0 +1,83 @@ +From ebe7443d7e83bd4ba3143b52010ca97eaf767a9e Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Michael=20M=C3=BCller?= +Date: Mon, 26 Dec 2016 07:53:10 +0100 +Subject: bcrypt: Implement BCryptDecrypt for AES GCM mode. + +--- + dlls/bcrypt/bcrypt_main.c | 28 +++++++++++++++++++++++----- + dlls/bcrypt/tests/bcrypt.c | 8 ++++---- + 2 files changed, 27 insertions(+), 9 deletions(-) + +diff --git a/dlls/bcrypt/bcrypt_main.c b/dlls/bcrypt/bcrypt_main.c +index 77db0b1..c41524d 100644 +--- a/dlls/bcrypt/bcrypt_main.c ++++ b/dlls/bcrypt/bcrypt_main.c +@@ -1153,17 +1153,35 @@ NTSTATUS WINAPI BCryptDecrypt( BCRYPT_KEY_HANDLE handle, UCHAR *input, ULONG inp + padding, iv, iv_len, output, output_len, ret_len, flags ); + + if (!key || key->hdr.magic != MAGIC_KEY) return STATUS_INVALID_HANDLE; +- if (padding) +- { +- FIXME( "padding info not implemented\n" ); +- return STATUS_NOT_IMPLEMENTED; +- } + if (flags & ~BCRYPT_BLOCK_PADDING) + { + FIXME( "flags %08x not supported\n", flags ); + return STATUS_NOT_IMPLEMENTED; + } + ++ if (key->mode == MODE_ID_GCM) ++ { ++ BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO *auth_info = padding; ++ ++ if (!auth_info) return STATUS_INVALID_PARAMETER; ++ if (!auth_info->pbNonce) return STATUS_INVALID_PARAMETER; ++ if (!auth_info->pbTag) return STATUS_INVALID_PARAMETER; ++ if (auth_info->cbTag < 12 || auth_info->cbTag > 16) return STATUS_INVALID_PARAMETER; ++ ++ if ((status = key_set_params( key, auth_info->pbNonce, auth_info->cbNonce ))) ++ return status; ++ ++ *ret_len = input_len; ++ if (flags & BCRYPT_BLOCK_PADDING) return STATUS_INVALID_PARAMETER; ++ if (!output) return STATUS_SUCCESS; ++ if (output_len < *ret_len) return STATUS_BUFFER_TOO_SMALL; ++ ++ if ((status = key_decrypt( key, input, input_len, output, output_len ))) ++ return status; ++ ++ return STATUS_SUCCESS; ++ } ++ + if ((status = key_set_params( key, iv, iv_len ))) return status; + + *ret_len = input_len; +diff --git a/dlls/bcrypt/tests/bcrypt.c b/dlls/bcrypt/tests/bcrypt.c +index d2a74ce..3a1bc00 100644 +--- a/dlls/bcrypt/tests/bcrypt.c ++++ b/dlls/bcrypt/tests/bcrypt.c +@@ -1336,16 +1336,16 @@ static void test_BCryptDecrypt(void) + memcpy(ivbuf, iv, sizeof(iv)); + memset(plaintext, 0, sizeof(plaintext)); + ret = pBCryptDecrypt(key, ciphertext4, 32, &auth_info, ivbuf, 16, plaintext, 32, &size, 0); +- todo_wine ok(ret == STATUS_SUCCESS, "got %08x\n", ret); +- todo_wine ok(size == 32, "got %u\n", size); +- todo_wine ok(!memcmp(plaintext, expected3, sizeof(expected3)), "wrong data\n"); ++ ok(ret == STATUS_SUCCESS, "got %08x\n", ret); ++ ok(size == 32, "got %u\n", size); ++ ok(!memcmp(plaintext, expected3, sizeof(expected3)), "wrong data\n"); + + /* test with wrong tag */ + memcpy(ivbuf, iv, sizeof(iv)); + auth_info.pbTag = iv; /* wrong tag */ + ret = pBCryptDecrypt(key, ciphertext4, 32, &auth_info, ivbuf, 16, plaintext, 32, &size, 0); + todo_wine ok(ret == STATUS_AUTH_TAG_MISMATCH, "got %08x\n", ret); +- todo_wine ok(size == 32, "got %u\n", size); ++ ok(size == 32, "got %u\n", size); + + ret = pBCryptDestroyKey(key); + ok(ret == STATUS_SUCCESS, "got %08x\n", ret); +-- +2.9.0 + diff --git a/patches/bcrypt-Improvements/0019-bcrypt-Add-support-for-computing-comparing-cipher-ta.patch b/patches/bcrypt-Improvements/0019-bcrypt-Add-support-for-computing-comparing-cipher-ta.patch new file mode 100644 index 00000000..6c94b5d5 --- /dev/null +++ b/patches/bcrypt-Improvements/0019-bcrypt-Add-support-for-computing-comparing-cipher-ta.patch @@ -0,0 +1,155 @@ +From ec780b6b895ed5d9cd7bad5a2f24a822c3ae0e33 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Michael=20M=C3=BCller?= +Date: Mon, 26 Dec 2016 08:02:36 +0100 +Subject: bcrypt: Add support for computing/comparing cipher tag. + +--- + dlls/bcrypt/bcrypt_main.c | 41 ++++++++++++++++++++++++++++++++++++++++- + dlls/bcrypt/tests/bcrypt.c | 10 +++++----- + 2 files changed, 45 insertions(+), 6 deletions(-) + +diff --git a/dlls/bcrypt/bcrypt_main.c b/dlls/bcrypt/bcrypt_main.c +index c41524d..8a2df46 100644 +--- a/dlls/bcrypt/bcrypt_main.c ++++ b/dlls/bcrypt/bcrypt_main.c +@@ -49,6 +49,9 @@ static HINSTANCE instance; + #if defined(HAVE_GNUTLS_HASH) && !defined(HAVE_COMMONCRYPTO_COMMONDIGEST_H) + WINE_DECLARE_DEBUG_CHANNEL(winediag); + ++/* Not present in gnutls version < 3.0 */ ++static int (*pgnutls_cipher_tag)(gnutls_cipher_hd_t handle, void * tag, size_t tag_size); ++ + static void *libgnutls_handle; + #define MAKE_FUNCPTR(f) static typeof(f) * p##f + MAKE_FUNCPTR(gnutls_cipher_init); +@@ -68,6 +71,11 @@ MAKE_FUNCPTR(gnutls_perror); + #define GNUTLS_CIPHER_AES_256_GCM 94 + #endif + ++static int compat_gnutls_cipher_tag(gnutls_cipher_hd_t handle, void * tag, size_t tag_size) ++{ ++ return GNUTLS_E_UNKNOWN_CIPHER_TYPE; ++} ++ + static void gnutls_log( int level, const char *msg ) + { + TRACE( "<%d> %s", level, msg ); +@@ -101,6 +109,12 @@ static BOOL gnutls_initialize(void) + LOAD_FUNCPTR(gnutls_perror) + #undef LOAD_FUNCPTR + ++ if (!(pgnutls_cipher_tag = wine_dlsym( libgnutls_handle, "gnutls_cipher_tag", NULL, 0 ))) ++ { ++ WARN("gnutls_cipher_tag not found\n"); ++ pgnutls_cipher_tag = compat_gnutls_cipher_tag; ++ } ++ + if ((ret = pgnutls_global_init()) != GNUTLS_E_SUCCESS) + { + pgnutls_perror( ret ); +@@ -979,6 +993,19 @@ static NTSTATUS key_decrypt( struct key *key, const UCHAR *input, ULONG input_le + return STATUS_SUCCESS; + } + ++static NTSTATUS key_get_tag( struct key *key, UCHAR *tag, ULONG len ) ++{ ++ int ret; ++ ++ if ((ret = pgnutls_cipher_tag( key->handle, tag, len ))) ++ { ++ pgnutls_perror( ret ); ++ return STATUS_INTERNAL_ERROR; ++ } ++ ++ return STATUS_SUCCESS; ++} ++ + static NTSTATUS key_destroy( struct key *key ) + { + if (key->handle) pgnutls_cipher_deinit( key->handle ); +@@ -1019,6 +1046,12 @@ static NTSTATUS key_decrypt( struct key *key, const UCHAR *input, ULONG input_le + return STATUS_NOT_IMPLEMENTED; + } + ++static NTSTATUS key_get_tag( struct key *key, UCHAR *tag, ULONG len ) ++{ ++ ERR( "support for keys not available at build time\n" ); ++ return STATUS_NOT_IMPLEMENTED; ++} ++ + static NTSTATUS key_destroy( struct key *key ) + { + ERR( "support for keys not available at build time\n" ); +@@ -1103,7 +1136,7 @@ NTSTATUS WINAPI BCryptEncrypt( BCRYPT_KEY_HANDLE handle, UCHAR *input, ULONG inp + if ((status = key_encrypt( key, input, input_len, output, output_len ))) + return status; + +- return STATUS_SUCCESS; ++ return key_get_tag( key, auth_info->pbTag, auth_info->cbTag ); + } + + if ((status = key_set_params( key, iv, iv_len ))) return status; +@@ -1162,6 +1195,7 @@ NTSTATUS WINAPI BCryptDecrypt( BCRYPT_KEY_HANDLE handle, UCHAR *input, ULONG inp + if (key->mode == MODE_ID_GCM) + { + BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO *auth_info = padding; ++ UCHAR tag[16]; + + if (!auth_info) return STATUS_INVALID_PARAMETER; + if (!auth_info->pbNonce) return STATUS_INVALID_PARAMETER; +@@ -1179,6 +1213,11 @@ NTSTATUS WINAPI BCryptDecrypt( BCRYPT_KEY_HANDLE handle, UCHAR *input, ULONG inp + if ((status = key_decrypt( key, input, input_len, output, output_len ))) + return status; + ++ if ((status = key_get_tag( key, tag, sizeof(tag) ))) ++ return status; ++ if (memcmp( tag, auth_info->pbTag, auth_info->cbTag )) ++ return STATUS_AUTH_TAG_MISMATCH; ++ + return STATUS_SUCCESS; + } + +diff --git a/dlls/bcrypt/tests/bcrypt.c b/dlls/bcrypt/tests/bcrypt.c +index 3a1bc00..5d8447c 100644 +--- a/dlls/bcrypt/tests/bcrypt.c ++++ b/dlls/bcrypt/tests/bcrypt.c +@@ -1131,11 +1131,11 @@ static void test_BCryptEncrypt(void) + ok(ret == STATUS_SUCCESS, "got %08x\n", ret); + ok(size == 32, "got %u\n", size); + ok(!memcmp(ciphertext, expected4, sizeof(expected4)), "wrong data\n"); +- todo_wine ok(!memcmp(tag, expected_tag, sizeof(expected_tag)), "wrong tag\n"); ++ ok(!memcmp(tag, expected_tag, sizeof(expected_tag)), "wrong tag\n"); + for (i = 0; i < 32; i++) + ok(ciphertext[i] == expected4[i], "%u: %02x != %02x\n", i, ciphertext[i], expected4[i]); + for (i = 0; i < 16; i++) +- todo_wine ok(tag[i] == expected_tag[i], "%u: %02x != %02x\n", i, tag[i], expected_tag[i]); ++ ok(tag[i] == expected_tag[i], "%u: %02x != %02x\n", i, tag[i], expected_tag[i]); + + /* input size is not multiple of block size */ + size = 0; +@@ -1146,11 +1146,11 @@ static void test_BCryptEncrypt(void) + ok(ret == STATUS_SUCCESS, "got %08x\n", ret); + ok(size == 24, "got %u\n", size); + ok(!memcmp(ciphertext, expected4, 24), "wrong data\n"); +- todo_wine ok(!memcmp(tag, expected_tag2, sizeof(expected_tag2)), "wrong tag\n"); ++ ok(!memcmp(tag, expected_tag2, sizeof(expected_tag2)), "wrong tag\n"); + for (i = 0; i < 24; i++) + ok(ciphertext[i] == expected4[i], "%u: %02x != %02x\n", i, ciphertext[i], expected4[i]); + for (i = 0; i < 16; i++) +- todo_wine ok(tag[i] == expected_tag2[i], "%u: %02x != %02x\n", i, tag[i], expected_tag2[i]); ++ ok(tag[i] == expected_tag2[i], "%u: %02x != %02x\n", i, tag[i], expected_tag2[i]); + + /* test with padding */ + memcpy(ivbuf, iv, sizeof(iv)); +@@ -1344,7 +1344,7 @@ static void test_BCryptDecrypt(void) + memcpy(ivbuf, iv, sizeof(iv)); + auth_info.pbTag = iv; /* wrong tag */ + ret = pBCryptDecrypt(key, ciphertext4, 32, &auth_info, ivbuf, 16, plaintext, 32, &size, 0); +- todo_wine ok(ret == STATUS_AUTH_TAG_MISMATCH, "got %08x\n", ret); ++ ok(ret == STATUS_AUTH_TAG_MISMATCH, "got %08x\n", ret); + ok(size == 32, "got %u\n", size); + + ret = pBCryptDestroyKey(key); +-- +2.9.0 + diff --git a/patches/bcrypt-Improvements/0020-bcrypt-Implement-BCryptDuplicateKey.patch b/patches/bcrypt-Improvements/0020-bcrypt-Implement-BCryptDuplicateKey.patch new file mode 100644 index 00000000..3bdd9084 --- /dev/null +++ b/patches/bcrypt-Improvements/0020-bcrypt-Implement-BCryptDuplicateKey.patch @@ -0,0 +1,100 @@ +From e930551dfa4e0bb97db71d056a4ed59f9e459e01 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Michael=20M=C3=BCller?= +Date: Mon, 26 Dec 2016 08:28:24 +0100 +Subject: bcrypt: Implement BCryptDuplicateKey. + +--- + dlls/bcrypt/bcrypt.spec | 2 +- + dlls/bcrypt/bcrypt_main.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 50 insertions(+), 1 deletion(-) + +diff --git a/dlls/bcrypt/bcrypt.spec b/dlls/bcrypt/bcrypt.spec +index 9ecd21d..f5911d2 100644 +--- a/dlls/bcrypt/bcrypt.spec ++++ b/dlls/bcrypt/bcrypt.spec +@@ -12,7 +12,7 @@ + @ stdcall BCryptDestroyKey(ptr) + @ stub BCryptDestroySecret + @ stdcall BCryptDuplicateHash(ptr ptr ptr long long) +-@ stub BCryptDuplicateKey ++@ stdcall BCryptDuplicateKey(ptr ptr ptr long long) + @ stdcall BCryptEncrypt(ptr ptr long ptr ptr long ptr long ptr long) + @ stdcall BCryptEnumAlgorithms(long ptr ptr long) + @ stub BCryptEnumContextFunctionProviders +diff --git a/dlls/bcrypt/bcrypt_main.c b/dlls/bcrypt/bcrypt_main.c +index 198b010..37d6909 100644 +--- a/dlls/bcrypt/bcrypt_main.c ++++ b/dlls/bcrypt/bcrypt_main.c +@@ -915,6 +915,24 @@ static NTSTATUS key_init( struct key *key, struct algorithm *alg, UCHAR *secret, + return STATUS_SUCCESS; + } + ++static NTSTATUS key_duplicate( struct key *key_orig, struct key *key_copy ) ++{ ++ UCHAR *buffer; ++ ++ if (!(buffer = HeapAlloc( GetProcessHeap(), 0, key_orig->secret_len ))) return STATUS_NO_MEMORY; ++ memcpy( buffer, key_orig->secret, key_orig->secret_len ); ++ ++ key_copy->hdr = key_orig->hdr; ++ key_copy->alg_id = key_orig->alg_id; ++ key_copy->mode = key_orig->mode; ++ key_copy->block_size = key_orig->block_size; ++ key_copy->handle = NULL; ++ key_copy->secret = buffer; ++ key_copy->secret_len = key_orig->secret_len; ++ ++ return STATUS_SUCCESS; ++} ++ + static gnutls_cipher_algorithm_t get_gnutls_cipher( const struct key *key ) + { + switch (key->alg_id) +@@ -1028,6 +1046,13 @@ static NTSTATUS key_init( struct key *key, struct algorithm *alg, UCHAR *secret, + return STATUS_NOT_IMPLEMENTED; + } + ++static NTSTATUS key_duplicate( struct key *key_orig, struct key *key_copy ) ++{ ++ ERR( "support for keys not available at build time\n" ); ++ key_copy->mode = MODE_ID_CBC; ++ return STATUS_NOT_IMPLEMENTED; ++} ++ + static NTSTATUS key_set_params( struct key *key, UCHAR *iv, ULONG iv_len ) + { + ERR( "support for keys not available at build time\n" ); +@@ -1087,6 +1112,30 @@ NTSTATUS WINAPI BCryptGenerateSymmetricKey( BCRYPT_ALG_HANDLE algorithm, BCRYPT_ + return STATUS_SUCCESS; + } + ++NTSTATUS WINAPI BCryptDuplicateKey( BCRYPT_KEY_HANDLE handle, BCRYPT_KEY_HANDLE *handle_copy, ++ UCHAR *object, ULONG object_len, ULONG flags ) ++{ ++ struct key *key_orig = handle; ++ struct key *key_copy; ++ NTSTATUS status; ++ ++ TRACE( "%p, %p, %p, %u, %08x\n", handle, handle_copy, object, object_len, flags ); ++ ++ if (!key_orig || key_orig->hdr.magic != MAGIC_KEY) return STATUS_INVALID_HANDLE; ++ if (!handle_copy) return STATUS_INVALID_PARAMETER; ++ if (!(key_copy = HeapAlloc( GetProcessHeap(), 0, sizeof(*key_copy) ))) ++ return STATUS_NO_MEMORY; ++ ++ if ((status = key_duplicate( key_orig, key_copy ))) ++ { ++ HeapFree( GetProcessHeap(), 0, key_copy ); ++ return status; ++ } ++ ++ *handle_copy = key_copy; ++ return STATUS_SUCCESS; ++} ++ + NTSTATUS WINAPI BCryptDestroyKey( BCRYPT_KEY_HANDLE handle ) + { + struct key *key = handle; +-- +2.9.0 + diff --git a/patches/bcrypt-Improvements/0021-bcrypt-tests-Add-tests-for-BCryptDuplicateKey.patch b/patches/bcrypt-Improvements/0021-bcrypt-tests-Add-tests-for-BCryptDuplicateKey.patch new file mode 100644 index 00000000..3d5e2186 --- /dev/null +++ b/patches/bcrypt-Improvements/0021-bcrypt-tests-Add-tests-for-BCryptDuplicateKey.patch @@ -0,0 +1,77 @@ +From ec32e3345f5293704d8165c8428325e536986716 Mon Sep 17 00:00:00 2001 +From: Sebastian Lackner +Date: Mon, 26 Dec 2016 08:30:43 +0100 +Subject: bcrypt/tests: Add tests for BCryptDuplicateKey. + +--- + dlls/bcrypt/tests/bcrypt.c | 33 ++++++++++++++++++++++++++++++++- + 1 file changed, 32 insertions(+), 1 deletion(-) + +diff --git a/dlls/bcrypt/tests/bcrypt.c b/dlls/bcrypt/tests/bcrypt.c +index 5d8447c..a55d9a9 100644 +--- a/dlls/bcrypt/tests/bcrypt.c ++++ b/dlls/bcrypt/tests/bcrypt.c +@@ -45,6 +45,7 @@ static NTSTATUS (WINAPI *pBCryptEncrypt)(BCRYPT_KEY_HANDLE, PUCHAR, ULONG, VOID + ULONG *, ULONG); + static NTSTATUS (WINAPI *pBCryptDecrypt)(BCRYPT_KEY_HANDLE, PUCHAR, ULONG, VOID *, PUCHAR, ULONG, PUCHAR, ULONG, + ULONG *, ULONG); ++static NTSTATUS (WINAPI *pBCryptDuplicateKey)(BCRYPT_KEY_HANDLE, BCRYPT_KEY_HANDLE *, UCHAR *, ULONG, ULONG); + static NTSTATUS (WINAPI *pBCryptDestroyKey)(BCRYPT_KEY_HANDLE); + + static void test_BCryptGenRandom(void) +@@ -880,7 +881,7 @@ static void test_BCryptGenerateSymmetricKey(void) + static UCHAR expected[] = + {0xc6,0xa1,0x3b,0x37,0x87,0x8f,0x5b,0x82,0x6f,0x4f,0x81,0x62,0xa1,0xc8,0xd8,0x79}; + BCRYPT_ALG_HANDLE aes; +- BCRYPT_KEY_HANDLE key; ++ BCRYPT_KEY_HANDLE key, key2; + UCHAR *buf, ciphertext[16], plaintext[16], ivbuf[16]; + ULONG size, len, i; + NTSTATUS ret; +@@ -923,6 +924,35 @@ static void test_BCryptGenerateSymmetricKey(void) + for (i = 0; i < 16; i++) + ok(ciphertext[i] == expected[i], "%u: %02x != %02x\n", i, ciphertext[i], expected[i]); + ++ ret = pBCryptDuplicateKey(NULL, &key2, NULL, 0, 0); ++ ok(ret == STATUS_INVALID_HANDLE, "got %08x\n", ret); ++ ++ if (0) /* crashes on some Windows versions */ ++ { ++ ret = pBCryptDuplicateKey(key, NULL, NULL, 0, 0); ++ ok(ret == STATUS_INVALID_PARAMETER, "got %08x\n", ret); ++ } ++ ++ key2 = (void *)0xdeadbeef; ++ ret = pBCryptDuplicateKey(key, &key2, NULL, 0, 0); ++ ok(ret == STATUS_SUCCESS || broken(ret == STATUS_INVALID_PARAMETER), "got %08x\n", ret); ++ ++ if (ret == STATUS_SUCCESS) ++ { ++ size = 0; ++ memcpy(ivbuf, iv, sizeof(iv)); ++ memset(ciphertext, 0, sizeof(ciphertext)); ++ ret = pBCryptEncrypt(key2, data, 16, NULL, ivbuf, 16, ciphertext, 16, &size, 0); ++ ok(ret == STATUS_SUCCESS, "got %08x\n", ret); ++ ok(size == 16, "got %u\n", size); ++ ok(!memcmp(ciphertext, expected, sizeof(expected)), "wrong data\n"); ++ for (i = 0; i < 16; i++) ++ ok(ciphertext[i] == expected[i], "%u: %02x != %02x\n", i, ciphertext[i], expected[i]); ++ ++ ret = pBCryptDestroyKey(key2); ++ ok(ret == STATUS_SUCCESS, "got %08x\n", ret); ++ } ++ + size = 0xdeadbeef; + ret = pBCryptDecrypt(key, NULL, 0, NULL, NULL, 0, NULL, 0, &size, 0); + ok(ret == STATUS_SUCCESS, "got %08x\n", ret); +@@ -1381,6 +1411,7 @@ START_TEST(bcrypt) + pBCryptGenerateSymmetricKey = (void *)GetProcAddress(module, "BCryptGenerateSymmetricKey"); + pBCryptEncrypt = (void *)GetProcAddress(module, "BCryptEncrypt"); + pBCryptDecrypt = (void *)GetProcAddress(module, "BCryptDecrypt"); ++ pBCryptDuplicateKey = (void *)GetProcAddress(module, "BCryptDuplicateKey"); + pBCryptDestroyKey = (void *)GetProcAddress(module, "BCryptDestroyKey"); + + test_BCryptGenRandom(); +-- +2.9.0 + diff --git a/patches/bcrypt-Improvements/0022-bcrypt-Allow-to-call-BCryptSetProperty-on-key-object.patch b/patches/bcrypt-Improvements/0022-bcrypt-Allow-to-call-BCryptSetProperty-on-key-object.patch new file mode 100644 index 00000000..9e007bf8 --- /dev/null +++ b/patches/bcrypt-Improvements/0022-bcrypt-Allow-to-call-BCryptSetProperty-on-key-object.patch @@ -0,0 +1,98 @@ +From 85c7ad0c67aa6cc57e93f2160922305f80d49b4c Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Michael=20M=C3=BCller?= +Date: Mon, 26 Dec 2016 08:41:31 +0100 +Subject: bcrypt: Allow to call BCryptSetProperty on key objects. + +--- + dlls/bcrypt/bcrypt_main.c | 38 ++++++++++++++++++++++++++++++++++++-- + dlls/bcrypt/tests/bcrypt.c | 4 ++++ + 2 files changed, 40 insertions(+), 2 deletions(-) + +diff --git a/dlls/bcrypt/bcrypt_main.c b/dlls/bcrypt/bcrypt_main.c +index a07250e..3638c77 100644 +--- a/dlls/bcrypt/bcrypt_main.c ++++ b/dlls/bcrypt/bcrypt_main.c +@@ -215,6 +215,9 @@ int alg_block_bits[] = + /* ALG_ID_SHA512 */ 1024 + }; + ++struct key; ++static NTSTATUS set_key_property( struct key *key, const WCHAR *prop, UCHAR *value, ULONG size, ULONG flags ); ++ + NTSTATUS WINAPI BCryptGenRandom(BCRYPT_ALG_HANDLE handle, UCHAR *buffer, ULONG count, ULONG flags) + { + const DWORD supported_flags = BCRYPT_USE_SYSTEM_PREFERRED_RNG; +@@ -685,8 +688,8 @@ NTSTATUS WINAPI BCryptSetProperty( BCRYPT_HANDLE handle, const WCHAR *prop, UCHA + } + case MAGIC_KEY: + { +- FIXME( "keys not implemented yet\n" ); +- return STATUS_NOT_IMPLEMENTED; ++ struct key *key = (struct key *)object; ++ return set_key_property( key, prop, value, size, flags ); + } + default: + WARN( "unknown magic %08x\n", object->magic ); +@@ -933,6 +936,31 @@ static NTSTATUS key_duplicate( struct key *key_orig, struct key *key_copy ) + return STATUS_SUCCESS; + } + ++static NTSTATUS set_key_property( struct key *key, const WCHAR *prop, UCHAR *value, ULONG size, ULONG flags ) ++{ ++ if (!strcmpW( prop, BCRYPT_CHAINING_MODE )) ++ { ++ if (!strncmpW( (WCHAR *)value, BCRYPT_CHAIN_MODE_CBC, size )) ++ { ++ key->mode = MODE_ID_CBC; ++ return STATUS_SUCCESS; ++ } ++ else if (!strncmpW( (WCHAR *)value, BCRYPT_CHAIN_MODE_GCM, size )) ++ { ++ key->mode = MODE_ID_GCM; ++ return STATUS_SUCCESS; ++ } ++ else ++ { ++ FIXME( "unsupported mode %s\n", debugstr_wn( (WCHAR *)value, size ) ); ++ return STATUS_NOT_IMPLEMENTED; ++ } ++ } ++ ++ FIXME( "unsupported key property %s\n", debugstr_w(prop) ); ++ return STATUS_NOT_IMPLEMENTED; ++} ++ + static gnutls_cipher_algorithm_t get_gnutls_cipher( const struct key *key ) + { + switch (key->alg_id) +@@ -1050,6 +1078,12 @@ static NTSTATUS key_duplicate( struct key *key_orig, struct key *key_copy ) + return STATUS_NOT_IMPLEMENTED; + } + ++static NTSTATUS set_key_property( struct key *key, const WCHAR *prop, UCHAR *value, ULONG size, ULONG flags ) ++{ ++ ERR( "support for keys not available at build time\n" ); ++ return STATUS_NOT_IMPLEMENTED; ++} ++ + static NTSTATUS key_set_params( struct key *key, UCHAR *iv, ULONG iv_len ) + { + ERR( "support for keys not available at build time\n" ); +diff --git a/dlls/bcrypt/tests/bcrypt.c b/dlls/bcrypt/tests/bcrypt.c +index a55d9a9..62f0ca7 100644 +--- a/dlls/bcrypt/tests/bcrypt.c ++++ b/dlls/bcrypt/tests/bcrypt.c +@@ -903,6 +903,10 @@ static void test_BCryptGenerateSymmetricKey(void) + sizeof(BCRYPT_CHAIN_MODE_CBC), 0); + ok(ret == STATUS_SUCCESS, "got %08x\n", ret); + ++ ret = pBCryptSetProperty(key, BCRYPT_CHAINING_MODE, (UCHAR *)BCRYPT_CHAIN_MODE_CBC, ++ sizeof(BCRYPT_CHAIN_MODE_CBC), 0); ++ ok(ret == STATUS_SUCCESS || broken(ret == STATUS_NOT_SUPPORTED) /* < Win 8 */, "got %08x\n", ret); ++ + size = 0xdeadbeef; + ret = pBCryptEncrypt(key, NULL, 0, NULL, NULL, 0, NULL, 0, &size, 0); + ok(ret == STATUS_SUCCESS, "got %08x\n", ret); +-- +2.9.0 + diff --git a/patches/bcrypt-Improvements/0023-bcrypt-Add-support-for-auth-data-in-AES-GCM-mode.patch b/patches/bcrypt-Improvements/0023-bcrypt-Add-support-for-auth-data-in-AES-GCM-mode.patch new file mode 100644 index 00000000..2bd9da6f --- /dev/null +++ b/patches/bcrypt-Improvements/0023-bcrypt-Add-support-for-auth-data-in-AES-GCM-mode.patch @@ -0,0 +1,103 @@ +From 89b061b83343ad1b0c16f936be3bcad78829d9e8 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Michael=20M=C3=BCller?= +Date: Mon, 26 Dec 2016 15:01:19 +0100 +Subject: bcrypt: Add support for auth data in AES GCM mode. + +--- + dlls/bcrypt/bcrypt_main.c | 38 ++++++++++++++++++++++++++++++++++++-- + 1 file changed, 36 insertions(+), 2 deletions(-) + +diff --git a/dlls/bcrypt/bcrypt_main.c b/dlls/bcrypt/bcrypt_main.c +index 3638c77..34b6497 100644 +--- a/dlls/bcrypt/bcrypt_main.c ++++ b/dlls/bcrypt/bcrypt_main.c +@@ -50,7 +50,8 @@ static HINSTANCE instance; + WINE_DECLARE_DEBUG_CHANNEL(winediag); + + /* Not present in gnutls version < 3.0 */ +-static int (*pgnutls_cipher_tag)(gnutls_cipher_hd_t handle, void * tag, size_t tag_size); ++static int (*pgnutls_cipher_tag)(gnutls_cipher_hd_t handle, void *tag, size_t tag_size); ++static int (*pgnutls_cipher_add_auth)(gnutls_cipher_hd_t handle, const void *ptext, size_t ptext_size); + + static void *libgnutls_handle; + #define MAKE_FUNCPTR(f) static typeof(f) * p##f +@@ -71,7 +72,12 @@ MAKE_FUNCPTR(gnutls_perror); + #define GNUTLS_CIPHER_AES_256_GCM 94 + #endif + +-static int compat_gnutls_cipher_tag(gnutls_cipher_hd_t handle, void * tag, size_t tag_size) ++static int compat_gnutls_cipher_tag(gnutls_cipher_hd_t handle, void *tag, size_t tag_size) ++{ ++ return GNUTLS_E_UNKNOWN_CIPHER_TYPE; ++} ++ ++static int compat_gnutls_cipher_add_auth(gnutls_cipher_hd_t handle, const void *ptext, size_t ptext_size) + { + return GNUTLS_E_UNKNOWN_CIPHER_TYPE; + } +@@ -114,6 +120,11 @@ static BOOL gnutls_initialize(void) + WARN("gnutls_cipher_tag not found\n"); + pgnutls_cipher_tag = compat_gnutls_cipher_tag; + } ++ if (!(pgnutls_cipher_add_auth = wine_dlsym( libgnutls_handle, "gnutls_cipher_add_auth", NULL, 0 ))) ++ { ++ WARN("gnutls_cipher_add_auth not found\n"); ++ pgnutls_cipher_add_auth = compat_gnutls_cipher_add_auth; ++ } + + if ((ret = pgnutls_global_init()) != GNUTLS_E_SUCCESS) + { +@@ -1011,6 +1022,19 @@ static NTSTATUS key_set_params( struct key *key, UCHAR *iv, ULONG iv_len ) + return STATUS_SUCCESS; + } + ++static NTSTATUS key_set_auth_data( struct key *key, UCHAR *auth_data, ULONG len ) ++{ ++ int ret; ++ ++ if ((ret = pgnutls_cipher_add_auth( key->handle, auth_data, len ))) ++ { ++ pgnutls_perror( ret ); ++ return STATUS_INTERNAL_ERROR; ++ } ++ ++ return STATUS_SUCCESS; ++} ++ + static NTSTATUS key_encrypt( struct key *key, const UCHAR *input, ULONG input_len, UCHAR *output, + ULONG output_len ) + { +@@ -1090,6 +1114,12 @@ static NTSTATUS key_set_params( struct key *key, UCHAR *iv, ULONG iv_len ) + return STATUS_NOT_IMPLEMENTED; + } + ++static NTSTATUS key_set_auth_data( struct key *key, UCHAR *auth_data, ULONG len ) ++{ ++ ERR( "support for keys not available at build time\n" ); ++ return STATUS_NOT_IMPLEMENTED; ++} ++ + static NTSTATUS key_encrypt( struct key *key, const UCHAR *input, ULONG input_len, UCHAR *output, + ULONG output_len ) + { +@@ -1215,6 +1245,8 @@ NTSTATUS WINAPI BCryptEncrypt( BCRYPT_KEY_HANDLE handle, UCHAR *input, ULONG inp + if (!output) return STATUS_SUCCESS; + if (output_len < *ret_len) return STATUS_BUFFER_TOO_SMALL; + ++ if (auth_info->pbAuthData && (status = key_set_auth_data( key, auth_info->pbAuthData, auth_info->cbAuthData ))) ++ return status; + if ((status = key_encrypt( key, input, input_len, output, output_len ))) + return status; + +@@ -1292,6 +1324,8 @@ NTSTATUS WINAPI BCryptDecrypt( BCRYPT_KEY_HANDLE handle, UCHAR *input, ULONG inp + if (!output) return STATUS_SUCCESS; + if (output_len < *ret_len) return STATUS_BUFFER_TOO_SMALL; + ++ if (auth_info->pbAuthData && (status = key_set_auth_data( key, auth_info->pbAuthData, auth_info->cbAuthData ))) ++ return status; + if ((status = key_decrypt( key, input, input_len, output, output_len ))) + return status; + +-- +2.9.0 + diff --git a/patches/bcrypt-Improvements/0024-bcrypt-tests-Add-tests-for-auth-data-in-AES-GCM-mode.patch b/patches/bcrypt-Improvements/0024-bcrypt-tests-Add-tests-for-auth-data-in-AES-GCM-mode.patch new file mode 100644 index 00000000..bd893827 --- /dev/null +++ b/patches/bcrypt-Improvements/0024-bcrypt-tests-Add-tests-for-auth-data-in-AES-GCM-mode.patch @@ -0,0 +1,102 @@ +From 930962bf986a469b956e3a5e17d8c026098fadfb Mon Sep 17 00:00:00 2001 +From: Sebastian Lackner +Date: Mon, 26 Dec 2016 15:01:38 +0100 +Subject: bcrypt/tests: Add tests for auth data in AES GCM mode. + +--- + dlls/bcrypt/tests/bcrypt.c | 44 ++++++++++++++++++++++++++++++++++++++++++-- + 1 file changed, 42 insertions(+), 2 deletions(-) + +diff --git a/dlls/bcrypt/tests/bcrypt.c b/dlls/bcrypt/tests/bcrypt.c +index 62f0ca7..a18e495 100644 +--- a/dlls/bcrypt/tests/bcrypt.c ++++ b/dlls/bcrypt/tests/bcrypt.c +@@ -987,7 +987,9 @@ static void test_BCryptGenerateSymmetricKey(void) + static void test_BCryptEncrypt(void) + { + static UCHAR nonce[] = +- {0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60}; ++ {0x10,0x20,0x30,0x40,0x50,0x60,0x10,0x20,0x30,0x40,0x50,0x60}; ++ static UCHAR auth_data[] = ++ {0x60,0x50,0x40,0x30,0x20,0x10,0x60,0x50,0x40,0x30,0x20,0x10}; + static UCHAR secret[] = + {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f}; + static UCHAR iv[] = +@@ -1013,6 +1015,8 @@ static void test_BCryptEncrypt(void) + {0x89,0xb3,0x92,0x00,0x39,0x20,0x09,0xb4,0x6a,0xd6,0xaf,0xca,0x4b,0x5b,0xfd,0xd0}; + static UCHAR expected_tag2[] = + {0x9a,0x92,0x32,0x2c,0x61,0x2a,0xae,0xef,0x66,0x2a,0xfb,0x55,0xe9,0x48,0xdf,0xbd}; ++ static UCHAR expected_tag3[] = ++ {0x17,0x9d,0xc0,0x7a,0xf0,0xcf,0xaa,0xd5,0x1c,0x11,0xc4,0x4b,0xd6,0xa3,0x3e,0x77}; + BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO auth_info; + UCHAR *buf, ciphertext[48], ivbuf[16], tag[16]; + BCRYPT_AUTH_TAG_LENGTHS_STRUCT tag_length; +@@ -1186,6 +1190,24 @@ static void test_BCryptEncrypt(void) + for (i = 0; i < 16; i++) + ok(tag[i] == expected_tag2[i], "%u: %02x != %02x\n", i, tag[i], expected_tag2[i]); + ++ /* test with auth data */ ++ auth_info.pbAuthData = auth_data; ++ auth_info.cbAuthData = sizeof(auth_data); ++ ++ size = 0; ++ memcpy(ivbuf, iv, sizeof(iv)); ++ memset(ciphertext, 0xff, sizeof(ciphertext)); ++ memset(tag, 0xff, sizeof(tag)); ++ ret = pBCryptEncrypt(key, data2, 32, &auth_info, ivbuf, 16, ciphertext, 32, &size, 0); ++ ok(ret == STATUS_SUCCESS, "got %08x\n", ret); ++ ok(size == 32, "got %u\n", size); ++ ok(!memcmp(ciphertext, expected4, sizeof(expected4)), "wrong data\n"); ++ ok(!memcmp(tag, expected_tag3, sizeof(expected_tag3)), "wrong tag\n"); ++ for (i = 0; i < 32; i++) ++ ok(ciphertext[i] == expected4[i], "%u: %02x != %02x\n", i, ciphertext[i], expected4[i]); ++ for (i = 0; i < 16; i++) ++ ok(tag[i] == expected_tag3[i], "%u: %02x != %02x\n", i, tag[i], expected_tag3[i]); ++ + /* test with padding */ + memcpy(ivbuf, iv, sizeof(iv)); + memset(ciphertext, 0, sizeof(ciphertext)); +@@ -1208,7 +1230,9 @@ static void test_BCryptEncrypt(void) + static void test_BCryptDecrypt(void) + { + static UCHAR nonce[] = +- {0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60}; ++ {0x10,0x20,0x30,0x40,0x50,0x60,0x10,0x20,0x30,0x40,0x50,0x60}; ++ static UCHAR auth_data[] = ++ {0x60,0x50,0x40,0x30,0x20,0x10,0x60,0x50,0x40,0x30,0x20,0x10}; + static UCHAR secret[] = + {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f}; + static UCHAR iv[] = +@@ -1235,6 +1259,8 @@ static void test_BCryptDecrypt(void) + 0x86,0x64,0xc3,0xfe,0xa3,0x07,0x61,0xf8,0x16,0xc9,0x78,0x7f,0xe7,0xb1,0xc4,0x94}; + static UCHAR tag[] = + {0x89,0xb3,0x92,0x00,0x39,0x20,0x09,0xb4,0x6a,0xd6,0xaf,0xca,0x4b,0x5b,0xfd,0xd0}; ++ static UCHAR tag2[] = ++ {0x17,0x9d,0xc0,0x7a,0xf0,0xcf,0xaa,0xd5,0x1c,0x11,0xc4,0x4b,0xd6,0xa3,0x3e,0x77}; + BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO auth_info; + BCRYPT_ALG_HANDLE aes; + BCRYPT_KEY_HANDLE key; +@@ -1374,6 +1400,20 @@ static void test_BCryptDecrypt(void) + ok(size == 32, "got %u\n", size); + ok(!memcmp(plaintext, expected3, sizeof(expected3)), "wrong data\n"); + ++ /* test with auuth data */ ++ auth_info.pbAuthData = auth_data; ++ auth_info.cbAuthData = sizeof(auth_data); ++ auth_info.pbTag = tag2; ++ auth_info.cbTag = sizeof(tag2); ++ ++ size = 0; ++ memcpy(ivbuf, iv, sizeof(iv)); ++ memset(plaintext, 0, sizeof(plaintext)); ++ ret = pBCryptDecrypt(key, ciphertext4, 32, &auth_info, ivbuf, 16, plaintext, 32, &size, 0); ++ ok(ret == STATUS_SUCCESS, "got %08x\n", ret); ++ ok(size == 32, "got %u\n", size); ++ ok(!memcmp(plaintext, expected3, sizeof(expected3)), "wrong data\n"); ++ + /* test with wrong tag */ + memcpy(ivbuf, iv, sizeof(iv)); + auth_info.pbTag = iv; /* wrong tag */ +-- +2.9.0 + diff --git a/patches/bcrypt-Improvements/0025-bcrypt-Avoid-crash-in-tests-when-compiling-without-g.patch b/patches/bcrypt-Improvements/0025-bcrypt-Avoid-crash-in-tests-when-compiling-without-g.patch new file mode 100644 index 00000000..672c29ea --- /dev/null +++ b/patches/bcrypt-Improvements/0025-bcrypt-Avoid-crash-in-tests-when-compiling-without-g.patch @@ -0,0 +1,51 @@ +From b7aa5302f9f16e906968b0a4483988f4e99a44b2 Mon Sep 17 00:00:00 2001 +From: Sebastian Lackner +Date: Mon, 26 Dec 2016 16:20:57 +0100 +Subject: bcrypt: Avoid crash in tests when compiling without gnutls support. + +--- + dlls/bcrypt/bcrypt_main.c | 11 ++++++++++- + 1 file changed, 10 insertions(+), 1 deletion(-) + +diff --git a/dlls/bcrypt/bcrypt_main.c b/dlls/bcrypt/bcrypt_main.c +index 75eaf46..564b2a5 100644 +--- a/dlls/bcrypt/bcrypt_main.c ++++ b/dlls/bcrypt/bcrypt_main.c +@@ -1163,12 +1163,17 @@ NTSTATUS WINAPI BCryptGenerateSymmetricKey( BCRYPT_ALG_HANDLE algorithm, BCRYPT_ + if (!alg || alg->hdr.magic != MAGIC_ALG) return STATUS_INVALID_HANDLE; + if (object) FIXME( "ignoring object buffer\n" ); + +- if (!(key = HeapAlloc( GetProcessHeap(), 0, sizeof(*key) ))) return STATUS_NO_MEMORY; ++ if (!(key = HeapAlloc( GetProcessHeap(), 0, sizeof(*key) ))) ++ { ++ *handle = NULL; ++ return STATUS_NO_MEMORY; ++ } + key->hdr.magic = MAGIC_KEY; + + if ((status = key_init( key, alg, secret, secret_len ))) + { + HeapFree( GetProcessHeap(), 0, key ); ++ *handle = NULL; + return status; + } + +@@ -1188,11 +1193,15 @@ NTSTATUS WINAPI BCryptDuplicateKey( BCRYPT_KEY_HANDLE handle, BCRYPT_KEY_HANDLE + if (!key_orig || key_orig->hdr.magic != MAGIC_KEY) return STATUS_INVALID_HANDLE; + if (!handle_copy) return STATUS_INVALID_PARAMETER; + if (!(key_copy = HeapAlloc( GetProcessHeap(), 0, sizeof(*key_copy) ))) ++ { ++ *handle_copy = NULL; + return STATUS_NO_MEMORY; ++ } + + if ((status = key_duplicate( key_orig, key_copy ))) + { + HeapFree( GetProcessHeap(), 0, key_copy ); ++ *handle_copy = NULL; + return status; + } + +-- +2.9.0 + diff --git a/patches/patchinstall.sh b/patches/patchinstall.sh index 325700eb..7bfcf494 100755 --- a/patches/patchinstall.sh +++ b/patches/patchinstall.sh @@ -52,7 +52,7 @@ usage() # Get the upstream commit sha upstream_commit() { - echo "1bcd38f788bb5165cc65a830ea912ff4eda50b84" + echo "80d2edd5845c09b98cb5b6b7779b4455dfbc1095" } # Show version information @@ -2862,7 +2862,8 @@ fi # | # | Modified files: # | * dlls/bcrypt/Makefile.in, dlls/bcrypt/bcrypt.spec, dlls/bcrypt/bcrypt_internal.h, dlls/bcrypt/bcrypt_main.c, -# | dlls/bcrypt/sha256.c, dlls/bcrypt/sha384.c, dlls/bcrypt/sha512.c, dlls/bcrypt/tests/bcrypt.c, include/bcrypt.h +# | dlls/bcrypt/sha256.c, dlls/bcrypt/sha384.c, dlls/bcrypt/sha512.c, dlls/bcrypt/tests/bcrypt.c, include/bcrypt.h, +# | include/ntstatus.h # | if test "$enable_bcrypt_Improvements" -eq 1; then patch_apply bcrypt-Improvements/0001-bcrypt-Add-AES-provider.patch @@ -2872,6 +2873,24 @@ if test "$enable_bcrypt_Improvements" -eq 1; then patch_apply bcrypt-Improvements/0005-bcrypt-Implement-BCryptDuplicateHash.patch patch_apply bcrypt-Improvements/0006-bcrypt-Fix-handling-of-padding-when-input-size-equal.patch patch_apply bcrypt-Improvements/0007-bcrypt-Properly-handle-padding-in-AES-decryption.patch + patch_apply bcrypt-Improvements/0008-bcrypt-Fix-use-after-free-in-key_init.patch + patch_apply bcrypt-Improvements/0009-bcrypt-Handle-NULL-pointers-in-BCryptDuplicateHash-a.patch + patch_apply bcrypt-Improvements/0010-bcrypt-tests-Add-test-for-bugs-in-BCryptGetProperty.patch + patch_apply bcrypt-Improvements/0011-bcrypt-tests-Add-tests-for-AES-GCM-mode.patch + patch_apply bcrypt-Improvements/0012-bcrypt-Pass-object-to-get_-alg-hash-_property-instea.patch + patch_apply bcrypt-Improvements/0013-bcrypt-Implement-BCryptSetProperty-for-algorithms.patch + patch_apply bcrypt-Improvements/0014-bcrypt-Implement-BCryptGetProperty-for-BCRYPT_CHAINI.patch + patch_apply bcrypt-Improvements/0015-bcrypt-Implement-BCryptGetProperty-for-BCRYPT_AUTH_T.patch + patch_apply bcrypt-Improvements/0016-bcrypt-Fix-string-comparison-in-set_alg_property.patch + patch_apply bcrypt-Improvements/0017-bcrypt-Implement-BCryptEncrypt-for-AES-GCM-mode.patch + patch_apply bcrypt-Improvements/0018-bcrypt-Implement-BCryptDecrypt-for-AES-GCM-mode.patch + patch_apply bcrypt-Improvements/0019-bcrypt-Add-support-for-computing-comparing-cipher-ta.patch + patch_apply bcrypt-Improvements/0020-bcrypt-Implement-BCryptDuplicateKey.patch + patch_apply bcrypt-Improvements/0021-bcrypt-tests-Add-tests-for-BCryptDuplicateKey.patch + patch_apply bcrypt-Improvements/0022-bcrypt-Allow-to-call-BCryptSetProperty-on-key-object.patch + patch_apply bcrypt-Improvements/0023-bcrypt-Add-support-for-auth-data-in-AES-GCM-mode.patch + patch_apply bcrypt-Improvements/0024-bcrypt-tests-Add-tests-for-auth-data-in-AES-GCM-mode.patch + patch_apply bcrypt-Improvements/0025-bcrypt-Avoid-crash-in-tests-when-compiling-without-g.patch ( echo '+ { "Hans Leidekker", "bcrypt: Add AES provider.", 1 },'; echo '+ { "Michael Müller", "bcrypt: Directly implement hmac computation.", 1 },'; @@ -2880,6 +2899,24 @@ if test "$enable_bcrypt_Improvements" -eq 1; then echo '+ { "Michael Müller", "bcrypt: Implement BCryptDuplicateHash.", 1 },'; echo '+ { "Michael Müller", "bcrypt: Fix handling of padding when input size equals block size for AES.", 1 },'; echo '+ { "Michael Müller", "bcrypt: Properly handle padding in AES decryption.", 1 },'; + echo '+ { "Michael Müller", "bcrypt: Fix use-after-free in key_init.", 1 },'; + echo '+ { "Sebastian Lackner", "bcrypt: Handle NULL pointers in BCryptDuplicateHash and add tests.", 1 },'; + echo '+ { "Sebastian Lackner", "bcrypt/tests: Add test for bugs in BCryptGetProperty.", 1 },'; + echo '+ { "Michael Müller", "bcrypt/tests: Add tests for AES GCM mode.", 1 },'; + echo '+ { "Sebastian Lackner", "bcrypt: Pass object to get_{alg,hash}_property instead of alg_id.", 1 },'; + echo '+ { "Michael Müller", "bcrypt: Implement BCryptSetProperty for algorithms.", 1 },'; + echo '+ { "Michael Müller", "bcrypt: Implement BCryptGetProperty for BCRYPT_CHAINING_MODE.", 1 },'; + echo '+ { "Michael Müller", "bcrypt: Implement BCryptGetProperty for BCRYPT_AUTH_TAG_LENGTH.", 1 },'; + echo '+ { "Sebastian Lackner", "bcrypt: Fix string comparison in set_alg_property.", 1 },'; + echo '+ { "Michael Müller", "bcrypt: Implement BCryptEncrypt for AES GCM mode.", 1 },'; + echo '+ { "Michael Müller", "bcrypt: Implement BCryptDecrypt for AES GCM mode.", 1 },'; + echo '+ { "Michael Müller", "bcrypt: Add support for computing/comparing cipher tag.", 1 },'; + echo '+ { "Michael Müller", "bcrypt: Implement BCryptDuplicateKey.", 1 },'; + echo '+ { "Sebastian Lackner", "bcrypt/tests: Add tests for BCryptDuplicateKey.", 1 },'; + echo '+ { "Michael Müller", "bcrypt: Allow to call BCryptSetProperty on key objects.", 1 },'; + echo '+ { "Michael Müller", "bcrypt: Add support for auth data in AES GCM mode.", 1 },'; + echo '+ { "Sebastian Lackner", "bcrypt/tests: Add tests for auth data in AES GCM mode.", 1 },'; + echo '+ { "Sebastian Lackner", "bcrypt: Avoid crash in tests when compiling without gnutls support.", 1 },'; ) >> "$patchlist" fi