Hans Leidekker : bcrypt: Add support for BCRYPT_OPAQUE_KEY_BLOB.

Alexandre Julliard julliard at winehq.org
Thu Mar 29 19:13:29 CDT 2018


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

Author: Hans Leidekker <hans at codeweavers.com>
Date:   Thu Mar 29 12:26:16 2018 +0200

bcrypt: Add support for BCRYPT_OPAQUE_KEY_BLOB.

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

---

 dlls/bcrypt/bcrypt_main.c  | 99 ++++++++++++++++++++++++++++++----------------
 dlls/bcrypt/tests/bcrypt.c | 27 +++++++++++--
 2 files changed, 88 insertions(+), 38 deletions(-)

diff --git a/dlls/bcrypt/bcrypt_main.c b/dlls/bcrypt/bcrypt_main.c
index 1490089..1e56062 100644
--- a/dlls/bcrypt/bcrypt_main.c
+++ b/dlls/bcrypt/bcrypt_main.c
@@ -1018,6 +1018,40 @@ static ULONG get_block_size( struct algorithm *alg )
     return ret;
 }
 
+static NTSTATUS key_import( BCRYPT_ALG_HANDLE algorithm, const WCHAR *type, BCRYPT_KEY_HANDLE *key, UCHAR *object,
+                            ULONG object_len, UCHAR *input, ULONG input_len )
+{
+    ULONG len;
+
+    if (!strcmpW( type, BCRYPT_KEY_DATA_BLOB ))
+    {
+        BCRYPT_KEY_DATA_BLOB_HEADER *header = (BCRYPT_KEY_DATA_BLOB_HEADER *)input;
+
+        if (input_len < sizeof(BCRYPT_KEY_DATA_BLOB_HEADER)) return STATUS_BUFFER_TOO_SMALL;
+        if (header->dwMagic != BCRYPT_KEY_DATA_BLOB_MAGIC) return STATUS_INVALID_PARAMETER;
+        if (header->dwVersion != BCRYPT_KEY_DATA_BLOB_VERSION1)
+        {
+            FIXME( "unknown key data blob version %u\n", header->dwVersion );
+            return STATUS_INVALID_PARAMETER;
+        }
+        len = header->cbKeyData;
+        if (len + sizeof(BCRYPT_KEY_DATA_BLOB_HEADER) > input_len) return STATUS_INVALID_PARAMETER;
+
+        return BCryptGenerateSymmetricKey( algorithm, key, object, object_len, (UCHAR *)&header[1], len, 0 );
+    }
+    else if (!strcmpW( type, BCRYPT_OPAQUE_KEY_BLOB ))
+    {
+        if (input_len < sizeof(len)) return STATUS_BUFFER_TOO_SMALL;
+        len = *(ULONG *)input;
+        if (len + sizeof(len) > input_len) return STATUS_INVALID_PARAMETER;
+
+        return BCryptGenerateSymmetricKey( algorithm, key, object, object_len, input + sizeof(len), len, 0 );
+    }
+
+    FIXME( "unsupported key type %s\n", debugstr_w(type) );
+    return STATUS_NOT_IMPLEMENTED;
+}
+
 static NTSTATUS key_export( struct key *key, const WCHAR *type, UCHAR *output, ULONG output_len, ULONG *size )
 {
     if (!strcmpW( type, BCRYPT_KEY_DATA_BLOB ))
@@ -1034,6 +1068,17 @@ static NTSTATUS key_export( struct key *key, const WCHAR *type, UCHAR *output, U
         memcpy( &header[1], key->u.s.secret, key->u.s.secret_len );
         return STATUS_SUCCESS;
     }
+    else if (!strcmpW( type, BCRYPT_OPAQUE_KEY_BLOB ))
+    {
+        ULONG len, req_size = sizeof(len) + key->u.s.secret_len;
+
+        *size = req_size;
+        if (output_len < req_size) return STATUS_BUFFER_TOO_SMALL;
+
+        *(ULONG *)output = key->u.s.secret_len;
+        memcpy( output + sizeof(len), key->u.s.secret, key->u.s.secret_len );
+        return STATUS_SUCCESS;
+    }
 
     FIXME( "unsupported key type %s\n", debugstr_w(type) );
     return STATUS_NOT_IMPLEMENTED;
@@ -1829,7 +1874,8 @@ static NTSTATUS key_asymmetric_verify( struct key *key, void *padding, UCHAR *ha
     return STATUS_NOT_IMPLEMENTED;
 }
 
-static NTSTATUS key_destroy( struct key *key )
+static NTSTATUS key_import( BCRYPT_ALG_HANDLE algorithm, const WCHAR *type, BCRYPT_KEY_HANDLE *key, UCHAR *object,
+                            ULONG object_len, UCHAR *input, ULONG input_len )
 {
     ERR( "support for keys not available at build time\n" );
     return STATUS_NOT_IMPLEMENTED;
@@ -1841,6 +1887,12 @@ static NTSTATUS key_export( struct key *key, const WCHAR *type, UCHAR *output, U
     return STATUS_NOT_IMPLEMENTED;
 }
 
+static NTSTATUS key_destroy( struct key *key )
+{
+    ERR( "support for keys not available at build time\n" );
+    return STATUS_NOT_IMPLEMENTED;
+}
+
 static inline BOOL key_is_symmetric( struct key *key )
 {
     ERR( "support for keys not available at build time\n" );
@@ -1880,9 +1932,9 @@ NTSTATUS WINAPI BCryptGenerateSymmetricKey( BCRYPT_ALG_HANDLE algorithm, BCRYPT_
     return STATUS_SUCCESS;
 }
 
-NTSTATUS WINAPI BCryptImportKey(BCRYPT_ALG_HANDLE algorithm, BCRYPT_KEY_HANDLE decrypt_key, LPCWSTR type,
-                                BCRYPT_KEY_HANDLE *key, PUCHAR object, ULONG object_len, PUCHAR input,
-                                ULONG input_len, ULONG flags)
+NTSTATUS WINAPI BCryptImportKey( BCRYPT_ALG_HANDLE algorithm, BCRYPT_KEY_HANDLE decrypt_key, LPCWSTR type,
+                                 BCRYPT_KEY_HANDLE *key, PUCHAR object, ULONG object_len, PUCHAR input,
+                                 ULONG input_len, ULONG flags )
 {
     struct algorithm *alg = algorithm;
 
@@ -1894,50 +1946,27 @@ NTSTATUS WINAPI BCryptImportKey(BCRYPT_ALG_HANDLE algorithm, BCRYPT_KEY_HANDLE d
 
     if (decrypt_key)
     {
-        FIXME("Decrypting of key not yet supported\n");
-        return STATUS_NO_MEMORY;
-    }
-
-    if (!strcmpW(type, BCRYPT_KEY_DATA_BLOB))
-    {
-        BCRYPT_KEY_DATA_BLOB_HEADER *key_header = (BCRYPT_KEY_DATA_BLOB_HEADER*)input;
-
-        if (input_len < sizeof(BCRYPT_KEY_DATA_BLOB_HEADER))
-            return STATUS_BUFFER_TOO_SMALL;
-
-        if (key_header->dwMagic != BCRYPT_KEY_DATA_BLOB_MAGIC)
-            return STATUS_INVALID_PARAMETER;
-
-        if (key_header->dwVersion != BCRYPT_KEY_DATA_BLOB_VERSION1)
-        {
-            FIXME("Unknown key data blob version: %d\n", key_header->dwVersion);
-            return STATUS_INVALID_PARAMETER;
-        }
-
-        if (key_header->cbKeyData + sizeof(BCRYPT_KEY_DATA_BLOB_HEADER) > input_len)
-            return STATUS_INVALID_PARAMETER;
-
-        return BCryptGenerateSymmetricKey(algorithm, key, object, object_len, (UCHAR*)&key_header[1], key_header->cbKeyData, 0);
+        FIXME( "decryption of key not yet supported\n" );
+        return STATUS_NOT_IMPLEMENTED;
     }
 
-    FIXME("Unsupported key type: %s\n", debugstr_w(type));
-    return STATUS_INVALID_PARAMETER;
+    return key_import( algorithm, type, key, object, object_len, input, input_len );
 }
 
-NTSTATUS WINAPI BCryptExportKey(BCRYPT_KEY_HANDLE export_key, BCRYPT_KEY_HANDLE encrypt_key, LPCWSTR type,
-                                PUCHAR output, ULONG output_len, ULONG *size, ULONG flags)
+NTSTATUS WINAPI BCryptExportKey( BCRYPT_KEY_HANDLE export_key, BCRYPT_KEY_HANDLE encrypt_key, LPCWSTR type,
+                                 PUCHAR output, ULONG output_len, ULONG *size, ULONG flags )
 {
     struct key *key = export_key;
 
     TRACE("%p, %p, %s, %p, %u, %p, %u\n", key, encrypt_key, debugstr_w(type), output, output_len, size, flags);
 
     if (!key || key->hdr.magic != MAGIC_KEY) return STATUS_INVALID_HANDLE;
-    if (!output || !output_len || !size) return STATUS_INVALID_PARAMETER;
+    if (!output || !type || !size) return STATUS_INVALID_PARAMETER;
 
     if (encrypt_key)
     {
-        FIXME("Encryption of key not yet supported\n");
-        return STATUS_NO_MEMORY;
+        FIXME( "encryption of key not yet supported\n" );
+        return STATUS_NOT_IMPLEMENTED;
     }
 
     return key_export( key, type, output, output_len, size );
diff --git a/dlls/bcrypt/tests/bcrypt.c b/dlls/bcrypt/tests/bcrypt.c
index 7d59f6d..2a49971 100644
--- a/dlls/bcrypt/tests/bcrypt.c
+++ b/dlls/bcrypt/tests/bcrypt.c
@@ -1393,7 +1393,7 @@ static void test_BCryptDecrypt(void)
 static void test_key_import_export(void)
 {
     UCHAR buffer1[sizeof(BCRYPT_KEY_DATA_BLOB_HEADER) + 16];
-    UCHAR buffer2[sizeof(BCRYPT_KEY_DATA_BLOB_HEADER) + 16];
+    UCHAR buffer2[sizeof(BCRYPT_KEY_DATA_BLOB_HEADER) + 16], *buf;
     BCRYPT_KEY_DATA_BLOB_HEADER *key_data1 = (void*)buffer1;
     BCRYPT_ALG_HANDLE aes;
     BCRYPT_KEY_HANDLE key;
@@ -1408,6 +1408,7 @@ static void test_key_import_export(void)
     key_data1->cbKeyData = 16;
     memset(&key_data1[1], 0x11, 16);
 
+    key = NULL;
     ret = pBCryptImportKey(aes, NULL, BCRYPT_KEY_DATA_BLOB, &key, NULL, 0, buffer1, sizeof(buffer1), 0);
     ok(ret == STATUS_SUCCESS || broken(ret == STATUS_INVALID_PARAMETER) /* vista */, "got %08x\n", ret);
     if (ret == STATUS_INVALID_PARAMETER)
@@ -1415,11 +1416,12 @@ static void test_key_import_export(void)
         win_skip("broken BCryptImportKey\n");
         return;
     }
+    ok(key != NULL, "key not set\n");
 
     size = 0;
-    ret = pBCryptExportKey(key, NULL, BCRYPT_KEY_DATA_BLOB, buffer2, 1, &size, 0);
+    ret = pBCryptExportKey(key, NULL, BCRYPT_KEY_DATA_BLOB, buffer2, 0, &size, 0);
     ok(ret == STATUS_BUFFER_TOO_SMALL, "got %08x\n", ret);
-    ok(size == sizeof(buffer2), "Got %u\n", size);
+    ok(size == sizeof(buffer2), "got %u\n", size);
 
     size = 0;
     memset(buffer2, 0xff, sizeof(buffer2));
@@ -1428,6 +1430,25 @@ static void test_key_import_export(void)
     ok(size == sizeof(buffer2), "Got %u\n", size);
     ok(!memcmp(buffer1, buffer2, sizeof(buffer1)), "Expected exported key to match imported key\n");
 
+    /* opaque blob */
+    size = 0;
+    ret = pBCryptExportKey(key, NULL, BCRYPT_OPAQUE_KEY_BLOB, buffer2, 0, &size, 0);
+    ok(ret == STATUS_BUFFER_TOO_SMALL, "got %08x\n", ret);
+    ok(size > 0, "got zero\n");
+
+    buf = HeapAlloc(GetProcessHeap(), 0, size);
+    ret = pBCryptExportKey(key, NULL, BCRYPT_OPAQUE_KEY_BLOB, buf, size, &size, 0);
+    ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
+
+    ret = pBCryptDestroyKey(key);
+    ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
+
+    key = NULL;
+    ret = pBCryptImportKey(aes, NULL, BCRYPT_OPAQUE_KEY_BLOB, &key, NULL, 0, buf, size, 0);
+    ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
+    ok(key != NULL, "key not set\n");
+    HeapFree(GetProcessHeap(), 0, buf);
+
     ret = pBCryptDestroyKey(key);
     ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
 




More information about the wine-cvs mailing list