Hans Leidekker : bcrypt: Support retrieving properties from key handles.

Alexandre Julliard julliard at winehq.org
Tue Dec 4 16:33:54 CST 2018


Module: wine
Branch: master
Commit: dc97df72ff24b40a8d95dbf5bc94967ed5b783cf
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=dc97df72ff24b40a8d95dbf5bc94967ed5b783cf

Author: Hans Leidekker <hans at codeweavers.com>
Date:   Tue Dec  4 08:59:20 2018 +0100

bcrypt: Support retrieving properties from key handles.

Signed-off-by: Hans Leidekker <hans at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/bcrypt/bcrypt_internal.h |  10 ++++
 dlls/bcrypt/bcrypt_main.c     | 130 +++++++++++++++++++++++++-----------------
 dlls/bcrypt/tests/bcrypt.c    |  31 +++++++++-
 3 files changed, 117 insertions(+), 54 deletions(-)

diff --git a/dlls/bcrypt/bcrypt_internal.h b/dlls/bcrypt/bcrypt_internal.h
index a40f9d1..593e784 100644
--- a/dlls/bcrypt/bcrypt_internal.h
+++ b/dlls/bcrypt/bcrypt_internal.h
@@ -198,9 +198,19 @@ struct key
     } u;
 };
 #else
+struct key_symmetric
+{
+    enum mode_id mode;
+};
+
 struct key
 {
     struct object hdr;
+    enum alg_id   alg_id;
+    union
+    {
+        struct key_symmetric s;
+    } u;
 };
 #endif
 
diff --git a/dlls/bcrypt/bcrypt_main.c b/dlls/bcrypt/bcrypt_main.c
index 2b9ae0b..0c68a4f 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 6865e87..c3f8f3d 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;




More information about the wine-cvs mailing list