From 545ec32d28d1a0674a031aaf34aefe1127089b27 Mon Sep 17 00:00:00 2001 From: Santino Mazza Date: Thu, 10 Mar 2022 11:05:05 +0100 Subject: [PATCH] ncrypt: Implement NCryptCreatePersistedKey. Signed-off-by: Santino Mazza Signed-off-by: Hans Leidekker Signed-off-by: Alexandre Julliard --- 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 +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)