include/mscvpdb.h: Use flexible array members for the rest of structures.
[wine.git] / dlls / ncrypt / main.c
blob3511f8f2d3f3a9ee331ebbd040317f47c8bcb025
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 STATUS_NO_MEMORY: return NTE_NO_MEMORY;
44 case STATUS_NOT_SUPPORTED: return NTE_NOT_SUPPORTED;
45 case NTE_BAD_DATA: return NTE_BAD_DATA;
46 case STATUS_BUFFER_TOO_SMALL: return NTE_BUFFER_TOO_SMALL;
47 default:
48 FIXME("unhandled status %#lx\n", status);
49 return NTE_INTERNAL_ERROR;
53 static struct object *allocate_object(enum object_type type)
55 struct object *ret;
56 if (!(ret = calloc(1, sizeof(*ret)))) return NULL;
57 ret->type = type;
58 return ret;
61 static struct object_property *get_object_property(struct object *object, const WCHAR *name)
63 unsigned int i;
64 for (i = 0; i < object->num_properties; i++)
66 struct object_property *property = &object->properties[i];
67 if (!lstrcmpW(property->key, name)) return property;
69 return NULL;
72 struct object_property *add_object_property(struct object *object, const WCHAR *name)
74 struct object_property *property;
76 if (!object->num_properties)
78 if (!(object->properties = malloc(sizeof(*property))))
80 ERR("Error allocating memory.\n");
81 return NULL;
83 property = &object->properties[object->num_properties++];
85 else
87 struct object_property *tmp;
88 if (!(tmp = realloc(object->properties, sizeof(*property) * (object->num_properties + 1))))
90 ERR("Error allocating memory.\n");
91 return NULL;
93 object->properties = tmp;
94 property = &object->properties[object->num_properties++];
97 memset(property, 0, sizeof(*property));
98 if (!(property->key = wcsdup(name)))
100 ERR("Error allocating memory.\n");
101 return NULL;
104 return property;
107 static SECURITY_STATUS set_object_property(struct object *object, const WCHAR *name, BYTE *value, DWORD value_size)
109 struct object_property *property = get_object_property(object, name);
110 void *tmp;
112 if (!property && !(property = add_object_property(object, name))) return NTE_NO_MEMORY;
114 property->value_size = value_size;
115 if (!(tmp = realloc(property->value, value_size)))
117 ERR("Error allocating memory.\n");
118 free(property->key);
119 property->key = NULL;
120 return NTE_NO_MEMORY;
123 property->value = tmp;
124 memcpy(property->value, value, value_size);
126 return ERROR_SUCCESS;
129 static struct object *create_key_object(enum algid algid, NCRYPT_PROV_HANDLE provider)
131 NCRYPT_SUPPORTED_LENGTHS supported_lengths = {512, 16384, 8, 1024};
132 struct object *object;
133 DWORD dw_value;
135 switch (algid)
137 case RSA:
138 if (!(object = allocate_object(KEY))) return NULL;
140 object->key.algid = RSA;
141 set_object_property(object, NCRYPT_ALGORITHM_PROPERTY, (BYTE *)BCRYPT_RSA_ALGORITHM,
142 sizeof(BCRYPT_RSA_ALGORITHM));
143 set_object_property(object, NCRYPT_ALGORITHM_GROUP_PROPERTY, (BYTE *)BCRYPT_RSA_ALGORITHM,
144 sizeof(BCRYPT_RSA_ALGORITHM));
145 set_object_property(object, NCRYPT_LENGTHS_PROPERTY, (BYTE *)&supported_lengths,
146 sizeof(supported_lengths));
147 dw_value = 128;
148 set_object_property(object, NCRYPT_BLOCK_LENGTH_PROPERTY, (BYTE *)&dw_value, sizeof(dw_value));
149 dw_value = 128;
150 set_object_property(object, BCRYPT_SIGNATURE_LENGTH, (BYTE *)&dw_value, sizeof(dw_value));
151 break;
153 default:
154 ERR("Invalid algid %#x\n", algid);
155 return NULL;
158 dw_value = 0;
159 set_object_property(object, NCRYPT_EXPORT_POLICY_PROPERTY, (BYTE *)&dw_value, sizeof(dw_value));
160 dw_value = NCRYPT_ALLOW_ALL_USAGES;
161 set_object_property(object, NCRYPT_KEY_USAGE_PROPERTY, (BYTE *)&dw_value, sizeof(dw_value));
162 dw_value = 0;
163 set_object_property(object, NCRYPT_KEY_TYPE_PROPERTY, (BYTE *)&dw_value, sizeof(dw_value));
164 set_object_property(object, NCRYPT_PROVIDER_HANDLE_PROPERTY, (BYTE *)&provider, sizeof(provider));
165 return object;
168 SECURITY_STATUS WINAPI NCryptCreatePersistedKey(NCRYPT_PROV_HANDLE provider, NCRYPT_KEY_HANDLE *key,
169 const WCHAR *algid, const WCHAR *name, DWORD keyspec, DWORD flags)
171 struct object *object;
173 TRACE("(%#Ix, %p, %s, %s, %#lx, %#lx)\n", provider, key, wine_dbgstr_w(algid),
174 wine_dbgstr_w(name), keyspec, flags);
176 if (!provider) return NTE_INVALID_HANDLE;
177 if (!algid) return HRESULT_FROM_WIN32(RPC_X_NULL_REF_POINTER);
178 if (name) FIXME("Persistent keys are not supported\n");
180 if (!lstrcmpiW(algid, BCRYPT_RSA_ALGORITHM))
182 NTSTATUS status;
183 DWORD default_bitlen = 1024;
185 if (!(object = create_key_object(RSA, provider)))
187 ERR("Error allocating memory\n");
188 return NTE_NO_MEMORY;
191 status = BCryptGenerateKeyPair(BCRYPT_RSA_ALG_HANDLE, &object->key.bcrypt_key, default_bitlen, 0);
192 if (status != STATUS_SUCCESS)
194 ERR("Error generating key pair %#lx\n", status);
195 free(object);
196 return map_ntstatus(status);
199 set_object_property(object, NCRYPT_LENGTH_PROPERTY, (BYTE *)&default_bitlen, sizeof(default_bitlen));
200 set_object_property(object, BCRYPT_PUBLIC_KEY_LENGTH, (BYTE *)&default_bitlen, sizeof(default_bitlen));
202 else
204 FIXME("Algorithm not handled %s\n", wine_dbgstr_w(algid));
205 return NTE_NOT_SUPPORTED;
208 *key = (NCRYPT_KEY_HANDLE)object;
209 return ERROR_SUCCESS;
212 SECURITY_STATUS WINAPI NCryptDecrypt(NCRYPT_KEY_HANDLE key, BYTE *input, DWORD insize, void *padding,
213 BYTE *output, DWORD outsize, DWORD *result, DWORD flags)
215 FIXME("(%#Ix, %p, %lu, %p, %p, %lu, %p, %#lx): stub\n", key, input, insize, padding,
216 output, outsize, result, flags);
217 return NTE_NOT_SUPPORTED;
220 SECURITY_STATUS WINAPI NCryptDeleteKey(NCRYPT_KEY_HANDLE key, DWORD flags)
222 FIXME("(%#Ix, %#lx): stub\n", key, flags);
223 return NTE_NOT_SUPPORTED;
226 SECURITY_STATUS WINAPI NCryptEncrypt(NCRYPT_KEY_HANDLE key, BYTE *input, DWORD insize, void *padding,
227 BYTE *output, DWORD outsize, DWORD *result, DWORD flags)
229 struct object *key_object = (struct object *)key;
231 TRACE("(%#Ix, %p, %lu, %p, %p, %lu, %p, %#lx)\n", key, input, insize, padding,
232 output, outsize, result, flags);
234 if (flags & ~(NCRYPT_NO_PADDING_FLAG | NCRYPT_PAD_OAEP_FLAG
235 | NCRYPT_PAD_PKCS1_FLAG | NCRYPT_SILENT_FLAG))
237 FIXME("Flags %lx not supported\n", flags);
238 return NTE_BAD_FLAGS;
241 if (flags & NCRYPT_NO_PADDING_FLAG || flags & NCRYPT_PAD_OAEP_FLAG)
243 FIXME("No padding and oaep padding not supported\n");
244 return NTE_NOT_SUPPORTED;
247 if (key_object->type != KEY) return NTE_INVALID_HANDLE;
249 return map_ntstatus(BCryptEncrypt(key_object->key.bcrypt_key, input, insize, padding,
250 NULL, 0, output, outsize, result, flags));
253 SECURITY_STATUS WINAPI NCryptEnumAlgorithms(NCRYPT_PROV_HANDLE provider, DWORD alg_ops,
254 DWORD *alg_count, NCryptAlgorithmName **alg_list, DWORD flags)
256 FIXME("(%#Ix, %#lx, %p, %p, %#lx): stub\n", provider, alg_ops, alg_count, alg_list, flags);
257 return NTE_NOT_SUPPORTED;
260 SECURITY_STATUS WINAPI NCryptEnumKeys(NCRYPT_PROV_HANDLE provider, const WCHAR *scope,
261 NCryptKeyName **key_name, PVOID *enum_state, DWORD flags)
263 FIXME("(%#Ix, %p, %p, %p, %#lx): stub\n", provider, scope, key_name, enum_state, flags);
264 return NTE_NOT_SUPPORTED;
267 SECURITY_STATUS WINAPI NCryptFinalizeKey(NCRYPT_KEY_HANDLE handle, DWORD flags)
269 struct object *object = (struct object *)handle;
270 DWORD key_length;
271 struct object_property *prop;
272 NTSTATUS status;
274 TRACE("(%#Ix, %#lx)\n", handle, flags);
276 if (!object || object->type != KEY) return NTE_INVALID_HANDLE;
278 if (!(prop = get_object_property(object, NCRYPT_LENGTH_PROPERTY))) return NTE_INVALID_HANDLE;
279 key_length = *(DWORD *)prop->value;
280 status = BCryptSetProperty(object->key.bcrypt_key, BCRYPT_KEY_LENGTH, (UCHAR *)&key_length, sizeof(key_length), 0);
281 if (status != STATUS_SUCCESS)
283 ERR("Error setting key length property\n");
284 return map_ntstatus(status);
287 status = BCryptFinalizeKeyPair(object->key.bcrypt_key, 0);
288 if (status != STATUS_SUCCESS)
290 ERR("Error finalizing key pair\n");
291 return map_ntstatus(status);
294 return ERROR_SUCCESS;
297 SECURITY_STATUS WINAPI NCryptFreeBuffer(PVOID buf)
299 FIXME("(%p): stub\n", buf);
300 return NTE_NOT_SUPPORTED;
303 static SECURITY_STATUS free_key_object(struct key *key)
305 return map_ntstatus( BCryptDestroyKey(key->bcrypt_key) );
308 SECURITY_STATUS WINAPI NCryptFreeObject(NCRYPT_HANDLE handle)
310 struct object *object = (struct object *)handle;
311 SECURITY_STATUS ret = STATUS_SUCCESS;
312 unsigned int i;
314 TRACE("(%#Ix)\n", handle);
316 if (!object)
318 WARN("invalid handle %#Ix\n", handle);
319 return NTE_INVALID_HANDLE;
322 switch (object->type)
324 case KEY:
326 if ((ret = free_key_object(&object->key))) return ret;
327 break;
329 case STORAGE_PROVIDER:
330 break;
332 default:
333 WARN("invalid handle %#Ix\n", handle);
334 return NTE_INVALID_HANDLE;
337 for (i = 0; i < object->num_properties; i++)
339 free(object->properties[i].key);
340 free(object->properties[i].value);
342 free(object->properties);
343 free(object);
344 return ret;
347 SECURITY_STATUS WINAPI NCryptGetProperty(NCRYPT_HANDLE handle, const WCHAR *name, BYTE *output,
348 DWORD outsize, DWORD *result, DWORD flags)
350 struct object *object = (struct object *)handle;
351 const struct object_property *property;
353 TRACE("(%#Ix, %s, %p, %lu, %p, %#lx)\n", handle, wine_dbgstr_w(name), output, outsize, result, flags);
354 if (flags) FIXME("flags %#lx not supported\n", flags);
356 if (!object) return NTE_INVALID_HANDLE;
357 if (!(property = get_object_property(object, name))) return NTE_INVALID_PARAMETER;
359 *result = property->value_size;
360 if (!output) return ERROR_SUCCESS;
361 if (outsize < property->value_size) return NTE_BUFFER_TOO_SMALL;
363 memcpy(output, property->value, property->value_size);
364 return ERROR_SUCCESS;
367 SECURITY_STATUS WINAPI NCryptImportKey(NCRYPT_PROV_HANDLE provider, NCRYPT_KEY_HANDLE decrypt_key,
368 const WCHAR *type, NCryptBufferDesc *params, NCRYPT_KEY_HANDLE *handle,
369 BYTE *data, DWORD datasize, DWORD flags)
371 BCRYPT_KEY_BLOB *header = (BCRYPT_KEY_BLOB *)data;
372 struct object *object;
374 TRACE("(%#Ix, %#Ix, %s, %p, %p, %p, %lu, %#lx)\n", provider, decrypt_key, wine_dbgstr_w(type),
375 params, handle, data, datasize, flags);
377 if (decrypt_key)
379 FIXME("Key blob decryption not implemented\n");
380 return NTE_NOT_SUPPORTED;
382 if (params)
384 FIXME("Parameter information not implemented\n");
385 return NTE_NOT_SUPPORTED;
387 if (flags == NCRYPT_SILENT_FLAG)
389 FIXME("Silent flag not implemented\n");
391 else if (flags)
393 WARN("Invalid flags %#lx\n", flags);
394 return NTE_BAD_FLAGS;
397 switch(header->Magic)
399 case BCRYPT_RSAFULLPRIVATE_MAGIC:
400 case BCRYPT_RSAPRIVATE_MAGIC:
401 case BCRYPT_RSAPUBLIC_MAGIC:
403 NTSTATUS status;
404 BCRYPT_RSAKEY_BLOB *rsablob = (BCRYPT_RSAKEY_BLOB *)data;
406 if (!(object = create_key_object(RSA, provider)))
408 ERR("Error allocating memory\n");
409 return NTE_NO_MEMORY;
412 status = BCryptImportKeyPair(BCRYPT_RSA_ALG_HANDLE, NULL, type, &object->key.bcrypt_key, data, datasize, 0);
413 if (status != STATUS_SUCCESS)
415 WARN("Error importing key pair %#lx\n", status);
416 free(object);
417 return map_ntstatus(status);
420 set_object_property(object, NCRYPT_LENGTH_PROPERTY, (BYTE *)&rsablob->BitLength, sizeof(rsablob->BitLength));
421 set_object_property(object, BCRYPT_PUBLIC_KEY_LENGTH, (BYTE *)&rsablob->BitLength, sizeof(rsablob->BitLength));
422 break;
424 default:
425 FIXME("Unhandled key magic %#lx\n", header->Magic);
426 return NTE_INVALID_PARAMETER;
429 *handle = (NCRYPT_KEY_HANDLE)object;
430 return ERROR_SUCCESS;
433 SECURITY_STATUS WINAPI NCryptExportKey(NCRYPT_KEY_HANDLE key, NCRYPT_KEY_HANDLE encrypt_key, const WCHAR *type,
434 NCryptBufferDesc *params, BYTE *output, DWORD output_len, DWORD *ret_len,
435 DWORD flags)
437 struct object *object = (struct object *)key;
439 TRACE("(%#Ix, %#Ix, %s, %p, %p, %lu, %p, %#lx)\n", key, encrypt_key, wine_dbgstr_w(type), params, output,
440 output_len, ret_len, flags);
442 if (encrypt_key)
444 FIXME("Key blob encryption not implemented\n");
445 return NTE_NOT_SUPPORTED;
447 if (params)
449 FIXME("Parameter information not implemented\n");
450 return NTE_NOT_SUPPORTED;
452 if (flags == NCRYPT_SILENT_FLAG)
454 FIXME("Silent flag not implemented\n");
457 return map_ntstatus(BCryptExportKey(object->key.bcrypt_key, NULL, type, output, output_len, ret_len, 0));
460 SECURITY_STATUS WINAPI NCryptIsAlgSupported(NCRYPT_PROV_HANDLE provider, const WCHAR *algid, DWORD flags)
462 static const ULONG supported = BCRYPT_CIPHER_OPERATION |\
463 BCRYPT_ASYMMETRIC_ENCRYPTION_OPERATION |\
464 BCRYPT_SIGNATURE_OPERATION |\
465 BCRYPT_SECRET_AGREEMENT_OPERATION;
466 BCRYPT_ALGORITHM_IDENTIFIER *list;
467 ULONG i, count;
468 NTSTATUS status;
470 TRACE("(%#Ix, %s, %#lx)\n", provider, wine_dbgstr_w(algid), flags);
472 if (!provider) return NTE_INVALID_HANDLE;
473 if (!algid) return HRESULT_FROM_WIN32(RPC_X_NULL_REF_POINTER);
474 if (flags == NCRYPT_SILENT_FLAG)
476 FIXME("Silent flag not implemented\n");
478 else if (flags)
480 WARN("Invalid flags %#lx\n", flags);
481 return NTE_BAD_FLAGS;
483 if (!lstrcmpiW(BCRYPT_RSA_SIGN_ALGORITHM, algid)) return NTE_NOT_SUPPORTED;
485 status = BCryptEnumAlgorithms(supported, &count, &list, 0);
486 if (status != STATUS_SUCCESS)
488 ERR("Error retrieving algorithm list %#lx\n", status);
489 return map_ntstatus(status);
492 status = STATUS_NOT_SUPPORTED;
493 for (i = 0; i < count; i++)
495 if (!lstrcmpiW(list[i].pszName, algid))
497 status = STATUS_SUCCESS;
498 break;
502 BCryptFreeBuffer(list);
503 return map_ntstatus(status);
506 BOOL WINAPI NCryptIsKeyHandle(NCRYPT_KEY_HANDLE hKey)
508 FIXME("(%#Ix): stub\n", hKey);
509 return FALSE;
512 SECURITY_STATUS WINAPI NCryptOpenKey(NCRYPT_PROV_HANDLE provider, NCRYPT_KEY_HANDLE *key,
513 const WCHAR *name, DWORD keyspec, DWORD flags)
515 FIXME("(%#Ix, %p, %s, %#lx, %#lx): stub\n", provider, key, wine_dbgstr_w(name), keyspec, flags);
516 return NTE_NOT_SUPPORTED;
519 SECURITY_STATUS WINAPI NCryptOpenStorageProvider(NCRYPT_PROV_HANDLE *provider, const WCHAR *name, DWORD flags)
521 struct object *object;
523 FIXME("(%p, %s, %#lx): stub\n", provider, wine_dbgstr_w(name), flags);
525 if (!(object = allocate_object(STORAGE_PROVIDER)))
527 ERR("Error allocating memory.\n");
528 return NTE_NO_MEMORY;
530 *provider = (NCRYPT_PROV_HANDLE)object;
531 return ERROR_SUCCESS;
534 SECURITY_STATUS WINAPI NCryptSetProperty(NCRYPT_HANDLE handle, const WCHAR *name, BYTE *input, DWORD insize, DWORD flags)
536 struct object *object = (struct object *)handle;
538 TRACE("(%#Ix, %s, %p, %lu, %#lx)\n", handle, wine_dbgstr_w(name), input, insize, flags);
539 if (flags) FIXME("flags %#lx not supported\n", flags);
541 if (!object) return NTE_INVALID_HANDLE;
542 return set_object_property(object, name, input, insize);
545 SECURITY_STATUS WINAPI NCryptSignHash(NCRYPT_KEY_HANDLE handle, void *padding, BYTE *value, DWORD value_len,
546 BYTE *sig, DWORD sig_len, DWORD *ret_len, DWORD flags)
548 struct object *object = (struct object *)handle;
550 TRACE("(%#Ix, %p, %p, %lu, %p, %lu, %#lx)\n", handle, padding, value, value_len, sig, sig_len, flags);
551 if (flags & NCRYPT_SILENT_FLAG) FIXME("Silent flag not implemented\n");
553 if (!object || object->type != KEY) return NTE_INVALID_HANDLE;
555 return map_ntstatus(BCryptSignHash(object->key.bcrypt_key, padding, value, value_len, sig, sig_len,
556 ret_len, flags & ~NCRYPT_SILENT_FLAG));
559 SECURITY_STATUS WINAPI NCryptVerifySignature(NCRYPT_KEY_HANDLE handle, void *padding, BYTE *hash, DWORD hash_size,
560 BYTE *signature, DWORD signature_size, DWORD flags)
562 struct object *key_object = (struct object *)handle;
564 TRACE("(%#Ix, %p, %p, %lu, %p, %lu, %#lx)\n", handle, padding, hash, hash_size, signature,
565 signature_size, flags);
567 if (!hash_size || !signature_size) return NTE_INVALID_PARAMETER;
568 if (!hash || !signature) return HRESULT_FROM_WIN32(RPC_X_NULL_REF_POINTER);
569 if (!handle || key_object->type != KEY) return NTE_INVALID_HANDLE;
571 if (key_object->key.algid < RSA)
573 FIXME("Symmetric keys not supported.\n");
574 return NTE_NOT_SUPPORTED;
577 return map_ntstatus(BCryptVerifySignature(key_object->key.bcrypt_key, padding, hash, hash_size, signature,
578 signature_size, flags));