ncrypt: Implement NCryptCreatePersistedKey.

Signed-off-by: Santino Mazza <mazzasantino1206@gmail.com>
Signed-off-by: Hans Leidekker <hans@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Santino Mazza 2022-03-10 11:05:05 +01:00 committed by Alexandre Julliard
parent eea57f4ec0
commit 545ec32d28
3 changed files with 177 additions and 95 deletions

View File

@ -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;
}

View File

@ -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;
};

View File

@ -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)