bcrypt-Improvements: Update patchset and implement support for AES GCM.

This commit is contained in:
Sebastian Lackner 2016-12-25 22:40:45 +01:00
parent 84b08ebde9
commit 8db21bfce6
22 changed files with 1889 additions and 10 deletions

View File

@ -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;

View File

@ -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?= <michael@fds-team.de>
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 );

View File

@ -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;

View File

@ -0,0 +1,39 @@
From f7dc69131cc016917b31c5deedf97da31b11c597 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Michael=20M=C3=BCller?= <michael@fds-team.de>
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

View File

@ -0,0 +1,83 @@
From 873d431347aa25effc70e47566e562c122a5edc8 Mon Sep 17 00:00:00 2001
From: Sebastian Lackner <sebastian@fds-team.de>
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

View File

@ -0,0 +1,29 @@
From 83b15bed14a0999bacd2a5959297bff842a125e0 Mon Sep 17 00:00:00 2001
From: Sebastian Lackner <sebastian@fds-team.de>
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

View File

@ -0,0 +1,282 @@
From 9e70e218c8a5c497ece71e17034ccae2e0baa218 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Michael=20M=C3=BCller?= <michael@fds-team.de>
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

View File

@ -0,0 +1,133 @@
From 9f68ea60cf840c9366aefe1ab486e9d1ee192843 Mon Sep 17 00:00:00 2001
From: Sebastian Lackner <sebastian@fds-team.de>
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

View File

@ -0,0 +1,149 @@
From 5313398cdabe97a17b21e2d9f25a191da7bd9434 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Michael=20M=C3=BCller?= <michael@fds-team.de>
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

View File

@ -0,0 +1,58 @@
From f7749755c11e54d1e75cd05b6656d2c474ade8ae Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Michael=20M=C3=BCller?= <michael@fds-team.de>
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

View File

@ -0,0 +1,75 @@
From 017f5d467e537e5159f9c14f703df97661a1453e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Michael=20M=C3=BCller?= <michael@fds-team.de>
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

View File

@ -0,0 +1,56 @@
From 698dc9ea948f98eba154453e6cdc79919373d007 Mon Sep 17 00:00:00 2001
From: Sebastian Lackner <sebastian@fds-team.de>
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

View File

@ -0,0 +1,168 @@
From ad15e50c53901317847236410be7b1d005e1a502 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Michael=20M=C3=BCller?= <michael@fds-team.de>
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

View File

@ -0,0 +1,83 @@
From ebe7443d7e83bd4ba3143b52010ca97eaf767a9e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Michael=20M=C3=BCller?= <michael@fds-team.de>
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

View File

@ -0,0 +1,155 @@
From ec780b6b895ed5d9cd7bad5a2f24a822c3ae0e33 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Michael=20M=C3=BCller?= <michael@fds-team.de>
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

View File

@ -0,0 +1,100 @@
From e930551dfa4e0bb97db71d056a4ed59f9e459e01 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Michael=20M=C3=BCller?= <michael@fds-team.de>
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

View File

@ -0,0 +1,77 @@
From ec32e3345f5293704d8165c8428325e536986716 Mon Sep 17 00:00:00 2001
From: Sebastian Lackner <sebastian@fds-team.de>
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

View File

@ -0,0 +1,98 @@
From 85c7ad0c67aa6cc57e93f2160922305f80d49b4c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Michael=20M=C3=BCller?= <michael@fds-team.de>
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

View File

@ -0,0 +1,103 @@
From 89b061b83343ad1b0c16f936be3bcad78829d9e8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Michael=20M=C3=BCller?= <michael@fds-team.de>
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

View File

@ -0,0 +1,102 @@
From 930962bf986a469b956e3a5e17d8c026098fadfb Mon Sep 17 00:00:00 2001
From: Sebastian Lackner <sebastian@fds-team.de>
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

View File

@ -0,0 +1,51 @@
From b7aa5302f9f16e906968b0a4483988f4e99a44b2 Mon Sep 17 00:00:00 2001
From: Sebastian Lackner <sebastian@fds-team.de>
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

View File

@ -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