mirror of
git://source.winehq.org/git/wine.git
synced 2024-09-06 21:20:41 +00:00
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:
parent
eea57f4ec0
commit
545ec32d28
|
@ -30,12 +30,165 @@
|
||||||
|
|
||||||
WINE_DEFAULT_DEBUG_CHANNEL(ncrypt);
|
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,
|
SECURITY_STATUS WINAPI NCryptCreatePersistedKey(NCRYPT_PROV_HANDLE provider, NCRYPT_KEY_HANDLE *key,
|
||||||
const WCHAR *algid, const WCHAR *name, DWORD keyspec, DWORD flags)
|
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);
|
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,
|
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;
|
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,
|
SECURITY_STATUS WINAPI NCryptGetProperty(NCRYPT_HANDLE handle, const WCHAR *name, BYTE *output,
|
||||||
DWORD outsize, DWORD *result, DWORD flags)
|
DWORD outsize, DWORD *result, DWORD flags)
|
||||||
{
|
{
|
||||||
|
@ -163,72 +305,6 @@ SECURITY_STATUS WINAPI NCryptGetProperty(NCRYPT_HANDLE handle, const WCHAR *name
|
||||||
return ERROR_SUCCESS;
|
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,
|
SECURITY_STATUS WINAPI NCryptImportKey(NCRYPT_PROV_HANDLE provider, NCRYPT_KEY_HANDLE decrypt_key,
|
||||||
const WCHAR *type, NCryptBufferDesc *params, NCRYPT_KEY_HANDLE *handle,
|
const WCHAR *type, NCryptBufferDesc *params, NCRYPT_KEY_HANDLE *handle,
|
||||||
BYTE *data, DWORD datasize, DWORD flags)
|
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;
|
return NTE_BAD_FLAGS;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(object = allocate_object(KEY)))
|
|
||||||
{
|
|
||||||
ERR("Error allocating memory\n");
|
|
||||||
return NTE_NO_MEMORY;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch(header->Magic)
|
switch(header->Magic)
|
||||||
{
|
{
|
||||||
case BCRYPT_RSAFULLPRIVATE_MAGIC:
|
case BCRYPT_RSAFULLPRIVATE_MAGIC:
|
||||||
|
@ -273,13 +343,13 @@ SECURITY_STATUS WINAPI NCryptImportKey(NCRYPT_PROV_HANDLE provider, NCRYPT_KEY_H
|
||||||
{
|
{
|
||||||
NTSTATUS ret;
|
NTSTATUS ret;
|
||||||
BCRYPT_RSAKEY_BLOB *rsablob = (BCRYPT_RSAKEY_BLOB *)data;
|
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");
|
ERR("Error allocating memory\n");
|
||||||
free(object);
|
return NTE_NO_MEMORY;
|
||||||
return NTE_INTERNAL_ERROR;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = BCryptImportKeyPair(object->key.bcrypt_alg, NULL, type, &object->key.bcrypt_key, data, datasize, 0);
|
ret = BCryptImportKeyPair(object->key.bcrypt_alg, NULL, type, &object->key.bcrypt_key, data, datasize, 0);
|
||||||
if (ret != ERROR_SUCCESS)
|
if (ret != ERROR_SUCCESS)
|
||||||
{
|
{
|
||||||
|
@ -289,14 +359,11 @@ SECURITY_STATUS WINAPI NCryptImportKey(NCRYPT_PROV_HANDLE provider, NCRYPT_KEY_H
|
||||||
return NTE_BAD_DATA;
|
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));
|
set_object_property(object, NCRYPT_LENGTH_PROPERTY, (BYTE *)&rsablob->BitLength, sizeof(rsablob->BitLength));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
FIXME("Unhandled key magic %#lx\n", header->Magic);
|
FIXME("Unhandled key magic %#lx\n", header->Magic);
|
||||||
free(object);
|
|
||||||
return NTE_INVALID_PARAMETER;
|
return NTE_INVALID_PARAMETER;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,8 +18,19 @@
|
||||||
|
|
||||||
#include <bcrypt.h>
|
#include <bcrypt.h>
|
||||||
|
|
||||||
|
enum algid
|
||||||
|
{
|
||||||
|
/* symmetric */
|
||||||
|
AES,
|
||||||
|
/* asymmetric */
|
||||||
|
RSA,
|
||||||
|
DSA,
|
||||||
|
ECDSA,
|
||||||
|
};
|
||||||
|
|
||||||
struct key
|
struct key
|
||||||
{
|
{
|
||||||
|
enum algid algid;
|
||||||
BCRYPT_ALG_HANDLE bcrypt_alg;
|
BCRYPT_ALG_HANDLE bcrypt_alg;
|
||||||
BCRYPT_KEY_HANDLE bcrypt_key;
|
BCRYPT_KEY_HANDLE bcrypt_key;
|
||||||
};
|
};
|
||||||
|
|
|
@ -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);
|
ret = NCryptSetProperty(key, NCRYPT_NAME_PROPERTY, (BYTE *)L"Key name", sizeof(L"Key name"), 0);
|
||||||
ok(ret == NTE_NOT_SUPPORTED, "got %#lx\n", ret);
|
ok(ret == NTE_NOT_SUPPORTED, "got %#lx\n", ret);
|
||||||
|
}
|
||||||
NCryptFreeObject(key);
|
NCryptFreeObject(key);
|
||||||
|
|
||||||
key = 0;
|
key = 0;
|
||||||
|
@ -240,6 +241,8 @@ static void test_set_property(void)
|
||||||
ret = NCryptSetProperty(key, NCRYPT_LENGTH_PROPERTY, (BYTE *)&keylength, sizeof(keylength), 0);
|
ret = NCryptSetProperty(key, NCRYPT_LENGTH_PROPERTY, (BYTE *)&keylength, sizeof(keylength), 0);
|
||||||
ok(ret == ERROR_SUCCESS, "got %#lx\n", ret);
|
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);
|
ret = NCryptSetProperty(key, NCRYPT_NAME_PROPERTY, (BYTE *)L"Key name", sizeof(L"Key name"), 0);
|
||||||
ok(ret == NTE_NOT_SUPPORTED, "got %#lx\n", ret);
|
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);
|
ret = NCryptOpenStorageProvider(&prov, NULL, 0);
|
||||||
ok(ret == ERROR_SUCCESS, "got %#lx\n", ret);
|
ok(ret == ERROR_SUCCESS, "got %#lx\n", ret);
|
||||||
|
|
||||||
todo_wine {
|
|
||||||
key = 0;
|
key = 0;
|
||||||
ret = NCryptCreatePersistedKey(0, &key, BCRYPT_RSA_ALGORITHM, NULL, 0, 0);
|
ret = NCryptCreatePersistedKey(0, &key, BCRYPT_RSA_ALGORITHM, NULL, 0, 0);
|
||||||
ok(ret == NTE_INVALID_HANDLE, "got %#lx\n", ret);
|
ok(ret == NTE_INVALID_HANDLE, "got %#lx\n", ret);
|
||||||
|
@ -292,14 +294,16 @@ static void test_create_persisted_key(void)
|
||||||
NCryptFinalizeKey(key, 0);
|
NCryptFinalizeKey(key, 0);
|
||||||
NCryptFreeObject(key);
|
NCryptFreeObject(key);
|
||||||
|
|
||||||
|
todo_wine
|
||||||
|
{
|
||||||
key = 0;
|
key = 0;
|
||||||
ret = NCryptCreatePersistedKey(prov, &key, BCRYPT_AES_ALGORITHM, NULL, 0, 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);
|
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");
|
if (ret == NTE_NOT_SUPPORTED) win_skip("broken, symmetric keys not supported.\n");
|
||||||
else ok(key, "got null handle\n");
|
else ok(key, "got null handle\n");
|
||||||
|
}
|
||||||
|
|
||||||
NCryptFreeObject(prov);
|
NCryptFreeObject(prov);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
START_TEST(ncrypt)
|
START_TEST(ncrypt)
|
||||||
|
|
Loading…
Reference in a new issue