windows.media: Partially implement IClosedCaptionPropertiesStatics_get_FontSize.
[wine.git] / dlls / ncrypt / main.c
blob89fbfcb795ab1030af8913a212aa897d380cae32
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 = malloc((lstrlenW(name) + 1) * sizeof(WCHAR))))
100 ERR("Error allocating memory.\n");
101 return NULL;
104 lstrcpyW(property->key, name);
105 return property;
108 static SECURITY_STATUS set_object_property(struct object *object, const WCHAR *name, BYTE *value, DWORD value_size)
110 struct object_property *property = get_object_property(object, name);
111 void *tmp;
113 if (!property && !(property = add_object_property(object, name))) return NTE_NO_MEMORY;
115 property->value_size = value_size;
116 if (!(tmp = realloc(property->value, value_size)))
118 ERR("Error allocating memory.\n");
119 free(property->key);
120 property->key = NULL;
121 return NTE_NO_MEMORY;
124 property->value = tmp;
125 memcpy(property->value, value, value_size);
127 return ERROR_SUCCESS;
130 static struct object *create_key_object(enum algid algid, NCRYPT_PROV_HANDLE provider)
132 struct object *object;
134 switch (algid)
136 case RSA:
137 if (!(object = allocate_object(KEY))) return NULL;
139 object->key.algid = RSA;
140 set_object_property(object, NCRYPT_ALGORITHM_GROUP_PROPERTY, (BYTE *)BCRYPT_RSA_ALGORITHM,
141 sizeof(BCRYPT_RSA_ALGORITHM));
142 break;
144 default:
145 ERR("Invalid algid %#x\n", algid);
146 return NULL;
149 set_object_property(object, NCRYPT_PROVIDER_HANDLE_PROPERTY, (BYTE *)&provider, sizeof(provider));
150 return object;
153 SECURITY_STATUS WINAPI NCryptCreatePersistedKey(NCRYPT_PROV_HANDLE provider, NCRYPT_KEY_HANDLE *key,
154 const WCHAR *algid, const WCHAR *name, DWORD keyspec, DWORD flags)
156 struct object *object;
158 TRACE("(%#Ix, %p, %s, %s, %#lx, %#lx)\n", provider, key, wine_dbgstr_w(algid),
159 wine_dbgstr_w(name), keyspec, flags);
161 if (!provider) return NTE_INVALID_HANDLE;
162 if (!algid) return HRESULT_FROM_WIN32(RPC_X_NULL_REF_POINTER);
163 if (name) FIXME("Persistent keys are not supported\n");
165 if (!lstrcmpiW(algid, BCRYPT_RSA_ALGORITHM))
167 NTSTATUS status;
168 DWORD default_bitlen = 1024;
170 if (!(object = create_key_object(RSA, provider)))
172 ERR("Error allocating memory\n");
173 return NTE_NO_MEMORY;
176 status = BCryptGenerateKeyPair(BCRYPT_RSA_ALG_HANDLE, &object->key.bcrypt_key, default_bitlen, 0);
177 if (status != STATUS_SUCCESS)
179 ERR("Error generating key pair %#lx\n", status);
180 free(object);
181 return map_ntstatus(status);
184 set_object_property(object, NCRYPT_LENGTH_PROPERTY, (BYTE *)&default_bitlen, sizeof(default_bitlen));
186 else
188 FIXME("Algorithm not handled %s\n", wine_dbgstr_w(algid));
189 return NTE_NOT_SUPPORTED;
192 *key = (NCRYPT_KEY_HANDLE)object;
193 return ERROR_SUCCESS;
196 SECURITY_STATUS WINAPI NCryptDecrypt(NCRYPT_KEY_HANDLE key, BYTE *input, DWORD insize, void *padding,
197 BYTE *output, DWORD outsize, DWORD *result, DWORD flags)
199 FIXME("(%#Ix, %p, %lu, %p, %p, %lu, %p, %#lx): stub\n", key, input, insize, padding,
200 output, outsize, result, flags);
201 return NTE_NOT_SUPPORTED;
204 SECURITY_STATUS WINAPI NCryptDeleteKey(NCRYPT_KEY_HANDLE key, DWORD flags)
206 FIXME("(%#Ix, %#lx): stub\n", key, flags);
207 return NTE_NOT_SUPPORTED;
210 SECURITY_STATUS WINAPI NCryptEncrypt(NCRYPT_KEY_HANDLE key, BYTE *input, DWORD insize, void *padding,
211 BYTE *output, DWORD outsize, DWORD *result, DWORD flags)
213 struct object *key_object = (struct object *)key;
215 TRACE("(%#Ix, %p, %lu, %p, %p, %lu, %p, %#lx)\n", key, input, insize, padding,
216 output, outsize, result, flags);
218 if (flags & ~(NCRYPT_NO_PADDING_FLAG | NCRYPT_PAD_OAEP_FLAG
219 | NCRYPT_PAD_PKCS1_FLAG | NCRYPT_SILENT_FLAG))
221 FIXME("Flags %lx not supported\n", flags);
222 return NTE_BAD_FLAGS;
225 if (flags & NCRYPT_NO_PADDING_FLAG || flags & NCRYPT_PAD_OAEP_FLAG)
227 FIXME("No padding and oaep padding not supported\n");
228 return NTE_NOT_SUPPORTED;
231 if (key_object->type != KEY) return NTE_INVALID_HANDLE;
233 return map_ntstatus(BCryptEncrypt(key_object->key.bcrypt_key, input, insize, padding,
234 NULL, 0, output, outsize, result, flags));
237 SECURITY_STATUS WINAPI NCryptEnumAlgorithms(NCRYPT_PROV_HANDLE provider, DWORD alg_ops,
238 DWORD *alg_count, NCryptAlgorithmName **alg_list, DWORD flags)
240 FIXME("(%#Ix, %#lx, %p, %p, %#lx): stub\n", provider, alg_ops, alg_count, alg_list, flags);
241 return NTE_NOT_SUPPORTED;
244 SECURITY_STATUS WINAPI NCryptEnumKeys(NCRYPT_PROV_HANDLE provider, const WCHAR *scope,
245 NCryptKeyName **key_name, PVOID *enum_state, DWORD flags)
247 FIXME("(%#Ix, %p, %p, %p, %#lx): stub\n", provider, scope, key_name, enum_state, flags);
248 return NTE_NOT_SUPPORTED;
251 SECURITY_STATUS WINAPI NCryptFinalizeKey(NCRYPT_KEY_HANDLE handle, DWORD flags)
253 struct object *object = (struct object *)handle;
254 DWORD key_length;
255 struct object_property *prop;
256 NTSTATUS status;
258 TRACE("(%#Ix, %#lx)\n", handle, flags);
260 if (!object || object->type != KEY) return NTE_INVALID_HANDLE;
262 if (!(prop = get_object_property(object, NCRYPT_LENGTH_PROPERTY))) return NTE_INVALID_HANDLE;
263 key_length = *(DWORD *)prop->value;
264 status = BCryptSetProperty(object->key.bcrypt_key, BCRYPT_KEY_LENGTH, (UCHAR *)&key_length, sizeof(key_length), 0);
265 if (status != STATUS_SUCCESS)
267 ERR("Error setting key length property\n");
268 return map_ntstatus(status);
271 status = BCryptFinalizeKeyPair(object->key.bcrypt_key, 0);
272 if (status != STATUS_SUCCESS)
274 ERR("Error finalizing key pair\n");
275 return map_ntstatus(status);
278 return ERROR_SUCCESS;
281 SECURITY_STATUS WINAPI NCryptFreeBuffer(PVOID buf)
283 FIXME("(%p): stub\n", buf);
284 return NTE_NOT_SUPPORTED;
287 static SECURITY_STATUS free_key_object(struct key *key)
289 return map_ntstatus( BCryptDestroyKey(key->bcrypt_key) );
292 SECURITY_STATUS WINAPI NCryptFreeObject(NCRYPT_HANDLE handle)
294 struct object *object = (struct object *)handle;
295 SECURITY_STATUS ret = STATUS_SUCCESS;
296 unsigned int i;
298 TRACE("(%#Ix)\n", handle);
300 if (!object)
302 WARN("invalid handle %#Ix\n", handle);
303 return NTE_INVALID_HANDLE;
306 switch (object->type)
308 case KEY:
310 if ((ret = free_key_object(&object->key))) return ret;
311 break;
313 case STORAGE_PROVIDER:
314 break;
316 default:
317 WARN("invalid handle %#Ix\n", handle);
318 return NTE_INVALID_HANDLE;
321 for (i = 0; i < object->num_properties; i++)
323 free(object->properties[i].key);
324 free(object->properties[i].value);
326 free(object->properties);
327 free(object);
328 return ret;
331 SECURITY_STATUS WINAPI NCryptGetProperty(NCRYPT_HANDLE handle, const WCHAR *name, BYTE *output,
332 DWORD outsize, DWORD *result, DWORD flags)
334 struct object *object = (struct object *)handle;
335 const struct object_property *property;
337 TRACE("(%#Ix, %s, %p, %lu, %p, %#lx)\n", handle, wine_dbgstr_w(name), output, outsize, result, flags);
338 if (flags) FIXME("flags %#lx not supported\n", flags);
340 if (!object) return NTE_INVALID_HANDLE;
341 if (!(property = get_object_property(object, name))) return NTE_INVALID_PARAMETER;
343 *result = property->value_size;
344 if (!output) return ERROR_SUCCESS;
345 if (outsize < property->value_size) return NTE_BUFFER_TOO_SMALL;
347 memcpy(output, property->value, property->value_size);
348 return ERROR_SUCCESS;
351 SECURITY_STATUS WINAPI NCryptImportKey(NCRYPT_PROV_HANDLE provider, NCRYPT_KEY_HANDLE decrypt_key,
352 const WCHAR *type, NCryptBufferDesc *params, NCRYPT_KEY_HANDLE *handle,
353 BYTE *data, DWORD datasize, DWORD flags)
355 BCRYPT_KEY_BLOB *header = (BCRYPT_KEY_BLOB *)data;
356 struct object *object;
358 TRACE("(%#Ix, %#Ix, %s, %p, %p, %p, %lu, %#lx)\n", provider, decrypt_key, wine_dbgstr_w(type),
359 params, handle, data, datasize, flags);
361 if (decrypt_key)
363 FIXME("Key blob decryption not implemented\n");
364 return NTE_NOT_SUPPORTED;
366 if (params)
368 FIXME("Parameter information not implemented\n");
369 return NTE_NOT_SUPPORTED;
371 if (flags == NCRYPT_SILENT_FLAG)
373 FIXME("Silent flag not implemented\n");
375 else if (flags)
377 WARN("Invalid flags %#lx\n", flags);
378 return NTE_BAD_FLAGS;
381 switch(header->Magic)
383 case BCRYPT_RSAFULLPRIVATE_MAGIC:
384 case BCRYPT_RSAPRIVATE_MAGIC:
385 case BCRYPT_RSAPUBLIC_MAGIC:
387 NTSTATUS status;
388 BCRYPT_RSAKEY_BLOB *rsablob = (BCRYPT_RSAKEY_BLOB *)data;
390 if (!(object = create_key_object(RSA, provider)))
392 ERR("Error allocating memory\n");
393 return NTE_NO_MEMORY;
396 status = BCryptImportKeyPair(BCRYPT_RSA_ALG_HANDLE, NULL, type, &object->key.bcrypt_key, data, datasize, 0);
397 if (status != STATUS_SUCCESS)
399 WARN("Error importing key pair %#lx\n", status);
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 static const ULONG supported = BCRYPT_CIPHER_OPERATION |\
419 BCRYPT_ASYMMETRIC_ENCRYPTION_OPERATION |\
420 BCRYPT_SIGNATURE_OPERATION |\
421 BCRYPT_SECRET_AGREEMENT_OPERATION;
422 BCRYPT_ALGORITHM_IDENTIFIER *list;
423 ULONG i, count;
424 NTSTATUS status;
426 TRACE("(%#Ix, %s, %#lx)\n", provider, wine_dbgstr_w(algid), flags);
428 if (!provider) return NTE_INVALID_HANDLE;
429 if (!algid) return HRESULT_FROM_WIN32(RPC_X_NULL_REF_POINTER);
430 if (flags == NCRYPT_SILENT_FLAG)
432 FIXME("Silent flag not implemented\n");
434 else if (flags)
436 WARN("Invalid flags %#lx\n", flags);
437 return NTE_BAD_FLAGS;
439 if (!lstrcmpiW(BCRYPT_RSA_SIGN_ALGORITHM, algid)) return NTE_NOT_SUPPORTED;
441 status = BCryptEnumAlgorithms(supported, &count, &list, 0);
442 if (status != STATUS_SUCCESS)
444 ERR("Error retrieving algorithm list %#lx\n", status);
445 return map_ntstatus(status);
448 status = STATUS_NOT_SUPPORTED;
449 for (i = 0; i < count; i++)
451 if (!lstrcmpiW(list[i].pszName, algid))
453 status = STATUS_SUCCESS;
454 break;
458 BCryptFreeBuffer(list);
459 return map_ntstatus(status);
462 BOOL WINAPI NCryptIsKeyHandle(NCRYPT_KEY_HANDLE hKey)
464 FIXME("(%#Ix): stub\n", hKey);
465 return FALSE;
468 SECURITY_STATUS WINAPI NCryptOpenKey(NCRYPT_PROV_HANDLE provider, NCRYPT_KEY_HANDLE *key,
469 const WCHAR *name, DWORD keyspec, DWORD flags)
471 FIXME("(%#Ix, %p, %s, %#lx, %#lx): stub\n", provider, key, wine_dbgstr_w(name), keyspec, flags);
472 return NTE_NOT_SUPPORTED;
475 SECURITY_STATUS WINAPI NCryptOpenStorageProvider(NCRYPT_PROV_HANDLE *provider, const WCHAR *name, DWORD flags)
477 struct object *object;
479 FIXME("(%p, %s, %#lx): stub\n", provider, wine_dbgstr_w(name), flags);
481 if (!(object = allocate_object(STORAGE_PROVIDER)))
483 ERR("Error allocating memory.\n");
484 return NTE_NO_MEMORY;
486 *provider = (NCRYPT_PROV_HANDLE)object;
487 return ERROR_SUCCESS;
490 SECURITY_STATUS WINAPI NCryptSetProperty(NCRYPT_HANDLE handle, const WCHAR *name, BYTE *input, DWORD insize, DWORD flags)
492 struct object *object = (struct object *)handle;
494 TRACE("(%#Ix, %s, %p, %lu, %#lx)\n", handle, wine_dbgstr_w(name), input, insize, flags);
495 if (flags) FIXME("flags %#lx not supported\n", flags);
497 if (!object) return NTE_INVALID_HANDLE;
498 return set_object_property(object, name, input, insize);
501 SECURITY_STATUS WINAPI NCryptVerifySignature(NCRYPT_KEY_HANDLE handle, void *padding, BYTE *hash, DWORD hash_size,
502 BYTE *signature, DWORD signature_size, DWORD flags)
504 struct object *key_object = (struct object *)handle;
506 TRACE("(%#Ix, %p, %p, %lu, %p, %lu, %#lx)\n", handle, padding, hash, hash_size, signature,
507 signature_size, flags);
509 if (!hash_size || !signature_size) return NTE_INVALID_PARAMETER;
510 if (!hash || !signature) return HRESULT_FROM_WIN32(RPC_X_NULL_REF_POINTER);
511 if (!handle || key_object->type != KEY) return NTE_INVALID_HANDLE;
513 if (key_object->key.algid < RSA)
515 FIXME("Symmetric keys not supported.\n");
516 return NTE_NOT_SUPPORTED;
519 return map_ntstatus(BCryptVerifySignature(key_object->key.bcrypt_key, padding, hash, hash_size, signature,
520 signature_size, flags));