wrc: Store version and characteristics as simple integers.
[wine.git] / dlls / ncrypt / main.c
blobcc979a539d278f690399fa51a4106d20078daf69
1 /*
2 * New cryptographic library (ncrypt.dll)
4 * Copyright 2016 Alex Henrie
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include <stdarg.h>
22 #include <stdlib.h>
24 #include "ntstatus.h"
25 #define WIN32_NO_STATUS
26 #include "windef.h"
27 #include "winbase.h"
28 #include "ncrypt.h"
29 #include "bcrypt.h"
30 #include "ncrypt_internal.h"
31 #include "wine/debug.h"
33 WINE_DEFAULT_DEBUG_CHANNEL(ncrypt);
35 static SECURITY_STATUS map_ntstatus(NTSTATUS status)
37 switch (status)
39 case STATUS_INVALID_HANDLE: return NTE_INVALID_HANDLE;
40 case STATUS_INVALID_SIGNATURE: return NTE_BAD_SIGNATURE;
41 case STATUS_SUCCESS: return ERROR_SUCCESS;
42 case STATUS_INVALID_PARAMETER: return NTE_INVALID_PARAMETER;
43 case NTE_BAD_DATA: return NTE_BAD_DATA;
44 default:
45 FIXME("unhandled status %#lx\n", status);
46 return NTE_INTERNAL_ERROR;
50 static struct object *allocate_object(enum object_type type)
52 struct object *ret;
53 if (!(ret = calloc(1, sizeof(*ret)))) return NULL;
54 ret->type = type;
55 return ret;
58 static struct object_property *get_object_property(struct object *object, const WCHAR *name)
60 unsigned int i;
61 for (i = 0; i < object->num_properties; i++)
63 struct object_property *property = &object->properties[i];
64 if (!lstrcmpW(property->key, name)) return property;
66 return NULL;
69 struct object_property *add_object_property(struct object *object, const WCHAR *name)
71 struct object_property *property;
73 if (!object->num_properties)
75 if (!(object->properties = malloc(sizeof(*property))))
77 ERR("Error allocating memory.\n");
78 return NULL;
80 property = &object->properties[object->num_properties++];
82 else
84 struct object_property *tmp;
85 if (!(tmp = realloc(object->properties, sizeof(*property) * (object->num_properties + 1))))
87 ERR("Error allocating memory.\n");
88 return NULL;
90 object->properties = tmp;
91 property = &object->properties[object->num_properties++];
94 memset(property, 0, sizeof(*property));
95 if (!(property->key = malloc((lstrlenW(name) + 1) * sizeof(WCHAR))))
97 ERR("Error allocating memory.\n");
98 return NULL;
101 lstrcpyW(property->key, name);
102 return property;
105 static SECURITY_STATUS set_object_property(struct object *object, const WCHAR *name, BYTE *value, DWORD value_size)
107 struct object_property *property = get_object_property(object, name);
108 void *tmp;
110 if (!property && !(property = add_object_property(object, name))) return NTE_NO_MEMORY;
112 property->value_size = value_size;
113 if (!(tmp = realloc(property->value, value_size)))
115 ERR("Error allocating memory.\n");
116 free(property->key);
117 property->key = NULL;
118 return NTE_NO_MEMORY;
121 property->value = tmp;
122 memcpy(property->value, value, value_size);
124 return ERROR_SUCCESS;
127 static struct object *create_key_object(enum algid algid, NCRYPT_PROV_HANDLE provider)
129 struct object *object;
130 NTSTATUS status;
132 if (!(object = allocate_object(KEY)))
134 ERR("Error allocating memory\n");
135 return NULL;
138 switch (algid)
140 case RSA:
142 status = BCryptOpenAlgorithmProvider(&object->key.bcrypt_alg, BCRYPT_RSA_ALGORITHM, NULL, 0);
143 if (status != STATUS_SUCCESS)
145 ERR("Error opening algorithm provider %#lx\n", status);
146 free(object);
147 return NULL;
150 object->key.algid = RSA;
151 set_object_property(object, NCRYPT_ALGORITHM_GROUP_PROPERTY, (BYTE *)BCRYPT_RSA_ALGORITHM,
152 sizeof(BCRYPT_RSA_ALGORITHM));
153 break;
155 default:
157 ERR("Invalid algid %#x\n", algid);
158 free(object);
159 return NULL;
163 set_object_property(object, NCRYPT_PROVIDER_HANDLE_PROPERTY, (BYTE *)&provider, sizeof(provider));
164 return object;
167 SECURITY_STATUS WINAPI NCryptCreatePersistedKey(NCRYPT_PROV_HANDLE provider, NCRYPT_KEY_HANDLE *key,
168 const WCHAR *algid, const WCHAR *name, DWORD keyspec, DWORD flags)
170 struct object *object;
172 TRACE("(%#Ix, %p, %s, %s, %#lx, %#lx)\n", provider, key, wine_dbgstr_w(algid),
173 wine_dbgstr_w(name), keyspec, flags);
175 if (!provider) return NTE_INVALID_HANDLE;
176 if (!algid) return HRESULT_FROM_WIN32(RPC_X_NULL_REF_POINTER);
177 if (name) FIXME("Persistent keys are not supported\n");
179 if (!lstrcmpiW(algid, BCRYPT_RSA_ALGORITHM))
181 NTSTATUS status;
182 DWORD default_bitlen = 1024;
184 if (!(object = create_key_object(RSA, provider)))
186 ERR("Error allocating memory\n");
187 return NTE_NO_MEMORY;
190 status = BCryptGenerateKeyPair(object->key.bcrypt_alg, &object->key.bcrypt_key, default_bitlen, 0);
191 if (status != STATUS_SUCCESS)
193 ERR("Error generating key pair %#lx\n", status);
194 BCryptCloseAlgorithmProvider(object->key.bcrypt_alg, 0);
195 free(object);
196 return map_ntstatus(status);
199 set_object_property(object, NCRYPT_LENGTH_PROPERTY, (BYTE *)&default_bitlen, sizeof(default_bitlen));
201 else
203 FIXME("Algorithm not handled %s\n", wine_dbgstr_w(algid));
204 return NTE_NOT_SUPPORTED;
207 *key = (NCRYPT_KEY_HANDLE)object;
208 return ERROR_SUCCESS;
211 SECURITY_STATUS WINAPI NCryptDecrypt(NCRYPT_KEY_HANDLE key, BYTE *input, DWORD insize, void *padding,
212 BYTE *output, DWORD outsize, DWORD *result, DWORD flags)
214 FIXME("(%#Ix, %p, %lu, %p, %p, %lu, %p, %#lx): stub\n", key, input, insize, padding,
215 output, outsize, result, flags);
216 return NTE_NOT_SUPPORTED;
219 SECURITY_STATUS WINAPI NCryptDeleteKey(NCRYPT_KEY_HANDLE key, DWORD flags)
221 FIXME("(%#Ix, %#lx): stub\n", key, flags);
222 return NTE_NOT_SUPPORTED;
225 SECURITY_STATUS WINAPI NCryptEncrypt(NCRYPT_KEY_HANDLE key, BYTE *input, DWORD insize, void *padding,
226 BYTE *output, DWORD outsize, DWORD *result, DWORD flags)
228 FIXME("(%#Ix, %p, %lu, %p, %p, %lu, %p, %#lx): stub\n", key, input, insize, padding,
229 output, outsize, result, flags);
230 return NTE_NOT_SUPPORTED;
233 SECURITY_STATUS WINAPI NCryptEnumAlgorithms(NCRYPT_PROV_HANDLE provider, DWORD alg_ops,
234 DWORD *alg_count, NCryptAlgorithmName **alg_list, DWORD flags)
236 FIXME("(%#Ix, %#lx, %p, %p, %#lx): stub\n", provider, alg_ops, alg_count, alg_list, flags);
237 return NTE_NOT_SUPPORTED;
240 SECURITY_STATUS WINAPI NCryptEnumKeys(NCRYPT_PROV_HANDLE provider, const WCHAR *scope,
241 NCryptKeyName **key_name, PVOID *enum_state, DWORD flags)
243 FIXME("(%#Ix, %p, %p, %p, %#lx): stub\n", provider, scope, key_name, enum_state, flags);
244 return NTE_NOT_SUPPORTED;
247 SECURITY_STATUS WINAPI NCryptFinalizeKey(NCRYPT_KEY_HANDLE handle, DWORD flags)
249 struct object *object = (struct object *)handle;
250 DWORD key_length;
251 struct object_property *prop;
252 NTSTATUS status;
254 TRACE("(%#Ix, %#lx)\n", handle, flags);
256 if (!object || object->type != KEY) return NTE_INVALID_HANDLE;
258 if (!(prop = get_object_property(object, NCRYPT_LENGTH_PROPERTY))) return NTE_INVALID_HANDLE;
259 key_length = *(DWORD *)prop->value;
260 status = BCryptSetProperty(object->key.bcrypt_key, BCRYPT_KEY_LENGTH, (UCHAR *)&key_length, sizeof(key_length), 0);
261 if (status != STATUS_SUCCESS)
263 ERR("Error setting key length property\n");
264 return map_ntstatus(status);
267 status = BCryptFinalizeKeyPair(object->key.bcrypt_key, 0);
268 if (status != STATUS_SUCCESS)
270 ERR("Error finalizing key pair\n");
271 return map_ntstatus(status);
274 return ERROR_SUCCESS;
277 SECURITY_STATUS WINAPI NCryptFreeBuffer(PVOID buf)
279 FIXME("(%p): stub\n", buf);
280 return NTE_NOT_SUPPORTED;
283 static SECURITY_STATUS free_key_object(struct key *key)
285 NTSTATUS status, status2;
286 status = BCryptDestroyKey(key->bcrypt_key);
287 if ((status2 = BCryptCloseAlgorithmProvider(key->bcrypt_alg, 0))) return map_ntstatus(status2);
288 return status ? map_ntstatus(status) : ERROR_SUCCESS;
291 SECURITY_STATUS WINAPI NCryptFreeObject(NCRYPT_HANDLE handle)
293 struct object *object = (struct object *)handle;
294 SECURITY_STATUS ret = STATUS_SUCCESS;
295 unsigned int i;
297 TRACE("(%#Ix)\n", handle);
299 if (!object)
301 WARN("invalid handle %#Ix\n", handle);
302 return NTE_INVALID_HANDLE;
305 switch (object->type)
307 case KEY:
309 if ((ret = free_key_object(&object->key))) return ret;
310 break;
312 case STORAGE_PROVIDER:
313 break;
315 default:
316 WARN("invalid handle %#Ix\n", handle);
317 return NTE_INVALID_HANDLE;
320 for (i = 0; i < object->num_properties; i++)
322 free(object->properties[i].key);
323 free(object->properties[i].value);
325 free(object->properties);
326 free(object);
327 return ret;
330 SECURITY_STATUS WINAPI NCryptGetProperty(NCRYPT_HANDLE handle, const WCHAR *name, BYTE *output,
331 DWORD outsize, DWORD *result, DWORD flags)
333 struct object *object = (struct object *)handle;
334 const struct object_property *property;
336 TRACE("(%#Ix, %s, %p, %lu, %p, %#lx)\n", handle, wine_dbgstr_w(name), output, outsize, result, flags);
337 if (flags) FIXME("flags %#lx not supported\n", flags);
339 if (!object) return NTE_INVALID_HANDLE;
340 if (!(property = get_object_property(object, name))) return NTE_INVALID_PARAMETER;
342 *result = property->value_size;
343 if (!output) return ERROR_SUCCESS;
344 if (outsize < property->value_size) return NTE_BUFFER_TOO_SMALL;
346 memcpy(output, property->value, property->value_size);
347 return ERROR_SUCCESS;
350 SECURITY_STATUS WINAPI NCryptImportKey(NCRYPT_PROV_HANDLE provider, NCRYPT_KEY_HANDLE decrypt_key,
351 const WCHAR *type, NCryptBufferDesc *params, NCRYPT_KEY_HANDLE *handle,
352 BYTE *data, DWORD datasize, DWORD flags)
354 BCRYPT_KEY_BLOB *header = (BCRYPT_KEY_BLOB *)data;
355 struct object *object;
357 TRACE("(%#Ix, %#Ix, %s, %p, %p, %p, %lu, %#lx)\n", provider, decrypt_key, wine_dbgstr_w(type),
358 params, handle, data, datasize, flags);
360 if (decrypt_key)
362 FIXME("Key blob decryption not implemented\n");
363 return NTE_NOT_SUPPORTED;
365 if (params)
367 FIXME("Parameter information not implemented\n");
368 return NTE_NOT_SUPPORTED;
370 if (flags == NCRYPT_SILENT_FLAG)
372 FIXME("Silent flag not implemented\n");
374 else if (flags)
376 ERR("Invalid flags %#lx\n", flags);
377 return NTE_BAD_FLAGS;
380 switch(header->Magic)
382 case BCRYPT_RSAFULLPRIVATE_MAGIC:
383 case BCRYPT_RSAPRIVATE_MAGIC:
384 case BCRYPT_RSAPUBLIC_MAGIC:
386 NTSTATUS status;
387 BCRYPT_RSAKEY_BLOB *rsablob = (BCRYPT_RSAKEY_BLOB *)data;
389 if (!(object = create_key_object(RSA, provider)))
391 ERR("Error allocating memory\n");
392 return NTE_NO_MEMORY;
395 status = BCryptImportKeyPair(object->key.bcrypt_alg, NULL, type, &object->key.bcrypt_key, data, datasize, 0);
396 if (status != STATUS_SUCCESS)
398 WARN("Error importing key pair %#lx\n", status);
399 BCryptCloseAlgorithmProvider(object->key.bcrypt_alg, 0);
400 free(object);
401 return map_ntstatus(status);
404 set_object_property(object, NCRYPT_LENGTH_PROPERTY, (BYTE *)&rsablob->BitLength, sizeof(rsablob->BitLength));
405 break;
407 default:
408 FIXME("Unhandled key magic %#lx\n", header->Magic);
409 return NTE_INVALID_PARAMETER;
412 *handle = (NCRYPT_KEY_HANDLE)object;
413 return ERROR_SUCCESS;
416 SECURITY_STATUS WINAPI NCryptIsAlgSupported(NCRYPT_PROV_HANDLE provider, const WCHAR *algid, DWORD flags)
418 FIXME("(%#Ix, %s, %#lx): stub\n", provider, wine_dbgstr_w(algid), flags);
419 return NTE_NOT_SUPPORTED;
422 BOOL WINAPI NCryptIsKeyHandle(NCRYPT_KEY_HANDLE hKey)
424 FIXME("(%#Ix): stub\n", hKey);
425 return FALSE;
428 SECURITY_STATUS WINAPI NCryptOpenKey(NCRYPT_PROV_HANDLE provider, NCRYPT_KEY_HANDLE *key,
429 const WCHAR *name, DWORD keyspec, DWORD flags)
431 FIXME("(%#Ix, %p, %s, %#lx, %#lx): stub\n", provider, key, wine_dbgstr_w(name), keyspec, flags);
432 return NTE_NOT_SUPPORTED;
435 SECURITY_STATUS WINAPI NCryptOpenStorageProvider(NCRYPT_PROV_HANDLE *provider, const WCHAR *name, DWORD flags)
437 struct object *object;
439 FIXME("(%p, %s, %#lx): stub\n", provider, wine_dbgstr_w(name), flags);
441 if (!(object = allocate_object(STORAGE_PROVIDER)))
443 ERR("Error allocating memory.\n");
444 return NTE_NO_MEMORY;
446 *provider = (NCRYPT_PROV_HANDLE)object;
447 return ERROR_SUCCESS;
450 SECURITY_STATUS WINAPI NCryptSetProperty(NCRYPT_HANDLE handle, const WCHAR *name, BYTE *input, DWORD insize, DWORD flags)
452 struct object *object = (struct object *)handle;
454 TRACE("(%#Ix, %s, %p, %lu, %#lx)\n", handle, wine_dbgstr_w(name), input, insize, flags);
455 if (flags) FIXME("flags %#lx not supported\n", flags);
457 if (!object) return NTE_INVALID_HANDLE;
458 return set_object_property(object, name, input, insize);
461 SECURITY_STATUS WINAPI NCryptVerifySignature(NCRYPT_KEY_HANDLE handle, void *padding, BYTE *hash, DWORD hash_size,
462 BYTE *signature, DWORD signature_size, DWORD flags)
464 struct object *key_object = (struct object *)handle;
466 TRACE("(%#Ix, %p, %p, %lu, %p, %lu, %#lx)\n", handle, padding, hash, hash_size, signature,
467 signature_size, flags);
469 if (!hash_size || !signature_size) return NTE_INVALID_PARAMETER;
470 if (!hash || !signature) return HRESULT_FROM_WIN32(RPC_X_NULL_REF_POINTER);
471 if (!handle || key_object->type != KEY) return NTE_INVALID_HANDLE;
473 if (key_object->key.algid < RSA)
475 FIXME("Symmetric keys not supported.\n");
476 return NTE_NOT_SUPPORTED;
479 return map_ntstatus(BCryptVerifySignature(key_object->key.bcrypt_key, padding, hash, hash_size, signature,
480 signature_size, flags));