[PATCH v4 1/4] ncrypt: Implement NCryptCreatePersistedKey.

Hans Leidekker hans at codeweavers.com
Thu Mar 10 04:05:05 CST 2022


From: Santino Mazza <mazzasantino1206 at gmail.com>

v4: Trim the list of algorithms.
    Formatting.

Signed-off-by: Santino Mazza <mazzasantino1206 at gmail.com>
Signed-off-by: Hans Leidekker <hans at codeweavers.com>
---
 dlls/ncrypt/main.c            | 253 +++++++++++++++++++++-------------
 dlls/ncrypt/ncrypt_internal.h |  11 ++
 dlls/ncrypt/tests/ncrypt.c    |   8 +-
 3 files changed, 177 insertions(+), 95 deletions(-)

diff --git a/dlls/ncrypt/main.c b/dlls/ncrypt/main.c
index 8ace3e55731..f76d5885476 100644
--- a/dlls/ncrypt/main.c
+++ b/dlls/ncrypt/main.c
@@ -30,12 +30,165 @@
 
 WINE_DEFAULT_DEBUG_CHANNEL(ncrypt);
 
+static struct object *allocate_object(enum object_type type)
+{
+    struct object *ret;
+    if (!(ret = calloc(1, sizeof(*ret)))) return NULL;
+    ret->type = type;
+    return ret;
+}
+
+static struct object_property *get_object_property(struct object *object, const WCHAR *name)
+{
+    unsigned int i;
+    for (i = 0; i < object->num_properties; i++)
+    {
+        struct object_property *property = &object->properties[i];
+        if (!lstrcmpW(property->key, name)) return property;
+    }
+    return NULL;
+}
+
+struct object_property *add_object_property(struct object *object, const WCHAR *name)
+{
+    struct object_property *property;
+
+    if (!object->num_properties)
+    {
+        if (!(object->properties = malloc(sizeof(*property))))
+        {
+            ERR("Error allocating memory.\n");
+            return NULL;
+        }
+        property = &object->properties[object->num_properties++];
+    }
+    else
+    {
+        struct object_property *tmp;
+        if (!(tmp = realloc(object->properties, sizeof(*property) * (object->num_properties + 1))))
+        {
+            ERR("Error allocating memory.\n");
+            return NULL;
+        }
+        object->properties = tmp;
+        property = &object->properties[object->num_properties++];
+    }
+
+    memset(property, 0, sizeof(*property));
+    if (!(property->key = malloc((lstrlenW(name) + 1) * sizeof(WCHAR))))
+    {
+        ERR("Error allocating memory.\n");
+        return NULL;
+    }
+
+    lstrcpyW(property->key, name);
+    return property;
+}
+
+static SECURITY_STATUS set_object_property(struct object *object, const WCHAR *name, BYTE *value, DWORD value_size)
+{
+    struct object_property *property = get_object_property(object, name);
+    void *tmp;
+
+    if (!property && !(property = add_object_property(object, name))) return NTE_NO_MEMORY;
+
+    property->value_size = value_size;
+    if (!(tmp = realloc(property->value, value_size)))
+    {
+        ERR("Error allocating memory.\n");
+        free(property->key);
+        property->key = NULL;
+        return NTE_NO_MEMORY;
+    }
+
+    property->value = tmp;
+    memcpy(property->value, value, value_size);
+
+    return ERROR_SUCCESS;
+}
+
+static struct object *create_key_object(enum algid algid, NCRYPT_PROV_HANDLE provider)
+{
+    struct object *object;
+    NTSTATUS ret;
+
+    if (!(object = allocate_object(KEY)))
+    {
+        ERR("Error allocating memory\n");
+        return NULL;
+    }
+
+    switch (algid)
+    {
+    case RSA:
+    {
+        ret = BCryptOpenAlgorithmProvider(&object->key.bcrypt_alg, BCRYPT_RSA_ALGORITHM, NULL, 0);
+        if (ret != ERROR_SUCCESS)
+        {
+            ERR("Error opening algorithm provider\n");
+            free(object);
+            return NULL;
+        }
+
+        object->key.algid = RSA;
+        set_object_property(object, NCRYPT_ALGORITHM_GROUP_PROPERTY, (BYTE *)BCRYPT_RSA_ALGORITHM,
+                            sizeof(BCRYPT_RSA_ALGORITHM));
+        break;
+    }
+    default:
+    {
+        ERR("Invalid algid %#x\n", algid);
+        free(object);
+        return NULL;
+    }
+    }
+
+    set_object_property(object, NCRYPT_PROVIDER_HANDLE_PROPERTY, (BYTE *)&provider, sizeof(provider));
+    return object;
+}
+
 SECURITY_STATUS WINAPI NCryptCreatePersistedKey(NCRYPT_PROV_HANDLE provider, NCRYPT_KEY_HANDLE *key,
                                                 const WCHAR *algid, const WCHAR *name, DWORD keyspec, DWORD flags)
 {
-    FIXME("(%#Ix, %p, %s, %s, %#lx, %#lx): stub\n", provider, key, wine_dbgstr_w(algid),
+    struct object *object;
+
+    TRACE("(%#Ix, %p, %s, %s, %#lx, %#lx)\n", provider, key, wine_dbgstr_w(algid),
           wine_dbgstr_w(name), keyspec, flags);
-    return NTE_NOT_SUPPORTED;
+
+    if (!provider) return NTE_INVALID_HANDLE;
+    if (!algid) return HRESULT_FROM_WIN32(RPC_X_NULL_REF_POINTER);
+    if (name) FIXME("Persistant keys not supported\n");
+
+    if (!lstrcmpiW(algid, BCRYPT_RSA_ALGORITHM))
+    {
+        NTSTATUS ret;
+        DWORD default_bitlen = 1024;
+
+        if (!(object = create_key_object(RSA, provider)))
+        {
+            ERR("Error allocating memory\n");
+            return NTE_NO_MEMORY;
+        }
+
+        ret = BCryptGenerateKeyPair(object->key.bcrypt_alg, &object->key.bcrypt_key, default_bitlen, 0);
+        if (ret != ERROR_SUCCESS)
+        {
+            ERR("Error generating key pair\n");
+            BCryptCloseAlgorithmProvider(object->key.bcrypt_alg, 0);
+            free(object);
+            return NTE_INTERNAL_ERROR;
+        }
+
+        set_object_property(object, NCRYPT_LENGTH_PROPERTY, (BYTE *)&default_bitlen, sizeof(default_bitlen));
+    }
+    else
+    {
+        FIXME("Algorithm not handled %s\n", wine_dbgstr_w(algid));
+        return NTE_NOT_SUPPORTED;
+    }
+
+    *key = (NCRYPT_KEY_HANDLE)object;
+    return ERROR_SUCCESS;
 }
 
 SECURITY_STATUS WINAPI NCryptDecrypt(NCRYPT_KEY_HANDLE key, BYTE *input, DWORD insize, void *padding,
@@ -132,17 +285,6 @@ SECURITY_STATUS WINAPI NCryptFreeObject(NCRYPT_HANDLE handle)
     return ret;
 }
 
-static struct object_property *get_object_property(struct object *object, const WCHAR *name)
-{
-    unsigned int i;
-    for (i = 0; i < object->num_properties; i++)
-    {
-        struct object_property *property = &object->properties[i];
-        if (!lstrcmpW(property->key, name)) return property;
-    }
-    return NULL;
-}
-
 SECURITY_STATUS WINAPI NCryptGetProperty(NCRYPT_HANDLE handle, const WCHAR *name, BYTE *output,
                                          DWORD outsize, DWORD *result, DWORD flags)
 {
@@ -163,72 +305,6 @@ SECURITY_STATUS WINAPI NCryptGetProperty(NCRYPT_HANDLE handle, const WCHAR *name
     return ERROR_SUCCESS;
 }
 
-static struct object *allocate_object(enum object_type type)
-{
-    struct object *ret;
-    if (!(ret = calloc(1, sizeof(*ret)))) return NULL;
-    ret->type = type;
-    return ret;
-}
-
-struct object_property *add_object_property(struct object *object, const WCHAR *name)
-{
-    struct object_property *property;
-
-    if (!object->num_properties)
-    {
-        if (!(object->properties = malloc(sizeof(*property))))
-        {
-            ERR("Error allocating memory.\n");
-            return NULL;
-        }
-        property = &object->properties[object->num_properties++];
-    }
-    else
-    {
-        struct object_property *tmp;
-        if (!(tmp = realloc(object->properties, sizeof(*property) * (object->num_properties + 1))))
-        {
-            ERR("Error allocating memory.\n");
-            return NULL;
-        }
-        object->properties = tmp;
-        property = &object->properties[object->num_properties++];
-    }
-
-    memset(property, 0, sizeof(*property));
-    if (!(property->key = malloc((lstrlenW(name) + 1) * sizeof(WCHAR))))
-    {
-        ERR("Error allocating memory.\n");
-        return NULL;
-    }
-
-    lstrcpyW(property->key, name);
-    return property;
-}
-
-static SECURITY_STATUS set_object_property(struct object *object, const WCHAR *name, BYTE *value, DWORD value_size)
-{
-    struct object_property *property = get_object_property(object, name);
-    void *tmp;
-
-    if (!property && !(property = add_object_property(object, name))) return NTE_NO_MEMORY;
-
-    property->value_size = value_size;
-    if (!(tmp = realloc(property->value, value_size)))
-    {
-        ERR("Error allocating memory.\n");
-        free(property->key);
-        property->key = NULL;
-        return NTE_NO_MEMORY;
-    }
-
-    property->value = tmp;
-    memcpy(property->value, value, value_size);
-
-    return ERROR_SUCCESS;
-}
-
 SECURITY_STATUS WINAPI NCryptImportKey(NCRYPT_PROV_HANDLE provider, NCRYPT_KEY_HANDLE decrypt_key,
                                        const WCHAR *type, NCryptBufferDesc *params, NCRYPT_KEY_HANDLE *handle,
                                        BYTE *data, DWORD datasize, DWORD flags)
@@ -259,12 +335,6 @@ SECURITY_STATUS WINAPI NCryptImportKey(NCRYPT_PROV_HANDLE provider, NCRYPT_KEY_H
         return NTE_BAD_FLAGS;
     }
 
-    if (!(object = allocate_object(KEY)))
-    {
-        ERR("Error allocating memory\n");
-        return NTE_NO_MEMORY;
-    }
-
     switch(header->Magic)
     {
     case BCRYPT_RSAFULLPRIVATE_MAGIC:
@@ -273,13 +343,13 @@ SECURITY_STATUS WINAPI NCryptImportKey(NCRYPT_PROV_HANDLE provider, NCRYPT_KEY_H
     {
         NTSTATUS ret;
         BCRYPT_RSAKEY_BLOB *rsablob = (BCRYPT_RSAKEY_BLOB *)data;
-        ret = BCryptOpenAlgorithmProvider(&object->key.bcrypt_alg, BCRYPT_RSA_ALGORITHM, NULL, 0);
-        if (ret != ERROR_SUCCESS)
+
+        if (!(object = create_key_object(RSA, provider)))
         {
-            ERR("Error opening algorithm provider\n");
-            free(object);
-            return NTE_INTERNAL_ERROR;
+            ERR("Error allocating memory\n");
+            return NTE_NO_MEMORY;
         }
+
         ret = BCryptImportKeyPair(object->key.bcrypt_alg, NULL, type, &object->key.bcrypt_key, data, datasize, 0);
         if (ret != ERROR_SUCCESS)
         {
@@ -289,14 +359,11 @@ SECURITY_STATUS WINAPI NCryptImportKey(NCRYPT_PROV_HANDLE provider, NCRYPT_KEY_H
             return NTE_BAD_DATA;
         }
 
-        set_object_property(object, NCRYPT_PROVIDER_HANDLE_PROPERTY, (BYTE *)&provider, sizeof(provider));
-        set_object_property(object, NCRYPT_ALGORITHM_GROUP_PROPERTY, (BYTE *)BCRYPT_RSA_ALGORITHM, sizeof(BCRYPT_RSA_ALGORITHM));
         set_object_property(object, NCRYPT_LENGTH_PROPERTY, (BYTE *)&rsablob->BitLength, sizeof(rsablob->BitLength));
         break;
     }
     default:
         FIXME("Unhandled key magic %#lx\n", header->Magic);
-        free(object);
         return NTE_INVALID_PARAMETER;
     }
 
diff --git a/dlls/ncrypt/ncrypt_internal.h b/dlls/ncrypt/ncrypt_internal.h
index e5884c8871a..0ab20de14ad 100644
--- a/dlls/ncrypt/ncrypt_internal.h
+++ b/dlls/ncrypt/ncrypt_internal.h
@@ -18,8 +18,19 @@
 
 #include <bcrypt.h>
 
+enum algid
+{
+    /* symmetric */
+    AES,
+    /* asymmetric */
+    RSA,
+    DSA,
+    ECDSA,
+};
+
 struct key
 {
+    enum algid algid;
     BCRYPT_ALG_HANDLE bcrypt_alg;
     BCRYPT_KEY_HANDLE bcrypt_key;
 };
diff --git a/dlls/ncrypt/tests/ncrypt.c b/dlls/ncrypt/tests/ncrypt.c
index cf434054428..ec69b236ac9 100644
--- a/dlls/ncrypt/tests/ncrypt.c
+++ b/dlls/ncrypt/tests/ncrypt.c
@@ -229,6 +229,7 @@ static void test_set_property(void)
     {
     ret = NCryptSetProperty(key, NCRYPT_NAME_PROPERTY, (BYTE *)L"Key name", sizeof(L"Key name"), 0);
     ok(ret == NTE_NOT_SUPPORTED, "got %#lx\n", ret);
+    }
     NCryptFreeObject(key);
 
     key = 0;
@@ -240,6 +241,8 @@ static void test_set_property(void)
     ret = NCryptSetProperty(key, NCRYPT_LENGTH_PROPERTY, (BYTE *)&keylength, sizeof(keylength), 0);
     ok(ret == ERROR_SUCCESS, "got %#lx\n", ret);
 
+    todo_wine
+    {
     ret = NCryptSetProperty(key, NCRYPT_NAME_PROPERTY, (BYTE *)L"Key name", sizeof(L"Key name"), 0);
     ok(ret == NTE_NOT_SUPPORTED, "got %#lx\n", ret);
 
@@ -261,7 +264,6 @@ static void test_create_persisted_key(void)
     ret = NCryptOpenStorageProvider(&prov, NULL, 0);
     ok(ret == ERROR_SUCCESS, "got %#lx\n", ret);
 
-    todo_wine {
     key = 0;
     ret = NCryptCreatePersistedKey(0, &key, BCRYPT_RSA_ALGORITHM, NULL, 0, 0);
     ok(ret == NTE_INVALID_HANDLE, "got %#lx\n", ret);
@@ -292,14 +294,16 @@ static void test_create_persisted_key(void)
     NCryptFinalizeKey(key, 0);
     NCryptFreeObject(key);
 
+    todo_wine
+    {
     key = 0;
     ret = NCryptCreatePersistedKey(prov, &key, BCRYPT_AES_ALGORITHM, NULL, 0, 0);
     ok(ret == ERROR_SUCCESS || broken(ret == NTE_NOT_SUPPORTED) /* win 7 */, "got %#lx\n", ret);
     if (ret == NTE_NOT_SUPPORTED) win_skip("broken, symmetric keys not supported.\n");
     else ok(key, "got null handle\n");
+    }
 
     NCryptFreeObject(prov);
-    }
 }
 
 START_TEST(ncrypt)
-- 
2.30.2




More information about the wine-devel mailing list