Signed-off-by: Hans Leidekker <hans(a)codeweavers.com>
---
dlls/bcrypt/bcrypt_main.c | 130 +++++++++++++++++++++++++++------------------
dlls/bcrypt/tests/bcrypt.c | 31 ++++++++++-
2 files changed, 107 insertions(+), 54 deletions(-)
diff --git a/dlls/bcrypt/bcrypt_main.c b/dlls/bcrypt/bcrypt_main.c
index 2b9ae0b766..0c68a4f3e6 100644
--- a/dlls/bcrypt/bcrypt_main.c
+++ b/dlls/bcrypt/bcrypt_main.c
@@ -413,6 +413,63 @@ static NTSTATUS generic_alg_property( enum alg_id id, const WCHAR *prop, UCHAR *
return STATUS_NOT_IMPLEMENTED;
}
+static NTSTATUS get_aes_property( enum mode_id mode, const WCHAR *prop, UCHAR *buf, ULONG size, ULONG *ret_size )
+{
+ if (!strcmpW( prop, BCRYPT_BLOCK_LENGTH ))
+ {
+ *ret_size = sizeof(ULONG);
+ if (size < sizeof(ULONG)) return STATUS_BUFFER_TOO_SMALL;
+ if (buf) *(ULONG *)buf = BLOCK_LENGTH_AES;
+ return STATUS_SUCCESS;
+ }
+ if (!strcmpW( prop, BCRYPT_CHAINING_MODE ))
+ {
+ const WCHAR *str;
+ switch (mode)
+ {
+ case MODE_ID_ECB: str = BCRYPT_CHAIN_MODE_ECB; break;
+ case MODE_ID_CBC: str = BCRYPT_CHAIN_MODE_CBC; break;
+ case MODE_ID_GCM: str = BCRYPT_CHAIN_MODE_GCM; break;
+ default: return STATUS_NOT_IMPLEMENTED;
+ }
+
+ *ret_size = 64;
+ if (size < *ret_size) return STATUS_BUFFER_TOO_SMALL;
+ memcpy( buf, str, (strlenW(str) + 1) * sizeof(WCHAR) );
+ return STATUS_SUCCESS;
+ }
+ if (!strcmpW( prop, BCRYPT_KEY_LENGTHS ))
+ {
+ BCRYPT_KEY_LENGTHS_STRUCT *key_lengths = (void *)buf;
+ *ret_size = sizeof(*key_lengths);
+ if (key_lengths && size < *ret_size) return STATUS_BUFFER_TOO_SMALL;
+ if (key_lengths)
+ {
+ key_lengths->dwMinLength = 128;
+ key_lengths->dwMaxLength = 256;
+ key_lengths->dwIncrement = 64;
+ }
+ return STATUS_SUCCESS;
+ }
+ if (!strcmpW( prop, BCRYPT_AUTH_TAG_LENGTH ))
+ {
+ BCRYPT_AUTH_TAG_LENGTHS_STRUCT *tag_length = (void *)buf;
+ if (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 property %s\n", debugstr_w(prop) );
+ return STATUS_NOT_IMPLEMENTED;
+}
+
NTSTATUS get_alg_property( const struct algorithm *alg, const WCHAR *prop, UCHAR *buf, ULONG size, ULONG *ret_size )
{
NTSTATUS status;
@@ -424,59 +481,7 @@ NTSTATUS get_alg_property( const struct algorithm *alg, const WCHAR *prop, UCHAR
switch (alg->id)
{
case ALG_ID_AES:
- if (!strcmpW( prop, BCRYPT_BLOCK_LENGTH ))
- {
- *ret_size = sizeof(ULONG);
- if (size < sizeof(ULONG))
- return STATUS_BUFFER_TOO_SMALL;
- if (buf)
- *(ULONG *)buf = BLOCK_LENGTH_AES;
- return STATUS_SUCCESS;
- }
- if (!strcmpW( prop, BCRYPT_CHAINING_MODE ))
- {
- const WCHAR *mode;
- switch (alg->mode)
- {
- case MODE_ID_ECB: mode = BCRYPT_CHAIN_MODE_ECB; break;
- case MODE_ID_CBC: mode = BCRYPT_CHAIN_MODE_CBC; break;
- case MODE_ID_GCM: mode = BCRYPT_CHAIN_MODE_GCM; 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;
- }
- if (!strcmpW( prop, BCRYPT_KEY_LENGTHS ))
- {
- BCRYPT_KEY_LENGTHS_STRUCT *key_lengths = (void *)buf;
- *ret_size = sizeof(*key_lengths);
- if (key_lengths && size < *ret_size) return STATUS_BUFFER_TOO_SMALL;
- if (key_lengths)
- {
- key_lengths->dwMinLength = 128;
- key_lengths->dwMaxLength = 256;
- key_lengths->dwIncrement = 64;
- }
- 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;
- }
- break;
+ return get_aes_property( alg->mode, prop, buf, size, ret_size );
default:
break;
@@ -533,6 +538,20 @@ static NTSTATUS get_hash_property( const struct hash *hash, const WCHAR *prop, U
return status;
}
+static NTSTATUS get_key_property( const struct key *key, const WCHAR *prop, UCHAR *buf, ULONG size, ULONG *ret_size )
+{
+ switch (key->alg_id)
+ {
+ case ALG_ID_AES:
+ if (!strcmpW( prop, BCRYPT_AUTH_TAG_LENGTH )) return STATUS_NOT_SUPPORTED;
+ return get_aes_property( key->u.s.mode, prop, buf, size, ret_size );
+
+ default:
+ FIXME( "unsupported algorithm %u\n", key->alg_id );
+ return STATUS_NOT_IMPLEMENTED;
+ }
+}
+
NTSTATUS WINAPI BCryptGetProperty( BCRYPT_HANDLE handle, LPCWSTR prop, UCHAR *buffer, ULONG count, ULONG *res, ULONG flags )
{
struct object *object = handle;
@@ -549,6 +568,11 @@ NTSTATUS WINAPI BCryptGetProperty( BCRYPT_HANDLE handle, LPCWSTR prop, UCHAR *bu
const struct algorithm *alg = (const struct algorithm *)object;
return get_alg_property( alg, prop, buffer, count, res );
}
+ case MAGIC_KEY:
+ {
+ const struct key *key = (const struct key *)object;
+ return get_key_property( key, prop, buffer, count, res );
+ }
case MAGIC_HASH:
{
const struct hash *hash = (const struct hash *)object;
diff --git a/dlls/bcrypt/tests/bcrypt.c b/dlls/bcrypt/tests/bcrypt.c
index 6865e87ca8..c3f8f3d78a 100644
--- a/dlls/bcrypt/tests/bcrypt.c
+++ b/dlls/bcrypt/tests/bcrypt.c
@@ -507,7 +507,8 @@ static void test_BCryptGenerateSymmetricKey(void)
{0xc6,0xa1,0x3b,0x37,0x87,0x8f,0x5b,0x82,0x6f,0x4f,0x81,0x62,0xa1,0xc8,0xd8,0x79};
BCRYPT_ALG_HANDLE aes;
BCRYPT_KEY_HANDLE key, key2;
- UCHAR *buf, ciphertext[16], plaintext[16], ivbuf[16];
+ UCHAR *buf, ciphertext[16], plaintext[16], ivbuf[16], mode[64];
+ BCRYPT_KEY_LENGTHS_STRUCT key_lengths;
ULONG size, len, i;
NTSTATUS ret;
@@ -608,6 +609,27 @@ static void test_BCryptGenerateSymmetricKey(void)
ok(size == 16, "got %u\n", size);
ok(!memcmp(plaintext, data, sizeof(data)), "wrong data\n");
+ memset(mode, 0, sizeof(mode));
+ ret = pBCryptGetProperty(key, 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), "wrong mode\n");
+
+ len = 0;
+ size = 0;
+ ret = pBCryptGetProperty(key, BCRYPT_BLOCK_LENGTH, (UCHAR *)&len, sizeof(len), &size, 0);
+ ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
+ ok(len == 16, "got %u\n", len);
+ ok(size == sizeof(len), "got %u\n", size);
+
+ size = 0;
+ memset(&key_lengths, 0, sizeof(key_lengths));
+ ret = pBCryptGetProperty(aes, BCRYPT_KEY_LENGTHS, (UCHAR*)&key_lengths, sizeof(key_lengths), &size, 0);
+ ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
+ ok(size == sizeof(key_lengths), "got %u\n", size);
+ ok(key_lengths.dwMinLength == 128, "Expected 128, got %d\n", key_lengths.dwMinLength);
+ ok(key_lengths.dwMaxLength == 256, "Expected 256, got %d\n", key_lengths.dwMaxLength);
+ ok(key_lengths.dwIncrement == 64, "Expected 64, got %d\n", key_lengths.dwIncrement);
+
ret = pBCryptDestroyKey(key);
ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
HeapFree(GetProcessHeap(), 0, buf);
@@ -855,6 +877,9 @@ static void test_BCryptEncrypt(void)
ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
ok(key != NULL, "key not set\n");
+ ret = pBCryptGetProperty(key, BCRYPT_AUTH_TAG_LENGTH, (UCHAR*)&tag_length, sizeof(tag_length), &size, 0);
+ ok(ret == STATUS_NOT_SUPPORTED, "got %08x\n", ret);
+
memset(&auth_info, 0, sizeof(auth_info));
auth_info.cbSize = sizeof(auth_info);
auth_info.dwInfoVersion = 1;
@@ -1108,6 +1133,7 @@ static void test_BCryptDecrypt(void)
{0x17,0x9d,0xc0,0x7a,0xf0,0xcf,0xaa,0xd5,0x1c,0x11,0xc4,0x4b,0xd6,0xa3,0x3e,0x77};
BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO auth_info;
BCRYPT_KEY_LENGTHS_STRUCT key_lengths;
+ BCRYPT_AUTH_TAG_LENGTHS_STRUCT tag_lengths;
BCRYPT_ALG_HANDLE aes;
BCRYPT_KEY_HANDLE key;
UCHAR *buf, plaintext[48], ivbuf[16];
@@ -1242,6 +1268,9 @@ static void test_BCryptDecrypt(void)
ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
ok(key != NULL, "key not set\n");
+ ret = pBCryptGetProperty(key, BCRYPT_AUTH_TAG_LENGTH, (UCHAR*)&tag_lengths, sizeof(tag_lengths), &size, 0);
+ ok(ret == STATUS_NOT_SUPPORTED, "got %08x\n", ret);
+
memset(&auth_info, 0, sizeof(auth_info));
auth_info.cbSize = sizeof(auth_info);
auth_info.dwInfoVersion = 1;
--
2.11.0