Commit 545ec32d authored by Santino Mazza's avatar Santino Mazza Committed by Alexandre Julliard

ncrypt: Implement NCryptCreatePersistedKey.

parent eea57f4e
...@@ -30,12 +30,165 @@ ...@@ -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);
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; 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) ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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 @@ ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment