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
25 #define WIN32_NO_STATUS
30 #include "ncrypt_internal.h"
31 #include "wine/debug.h"
33 WINE_DEFAULT_DEBUG_CHANNEL(ncrypt
);
35 static SECURITY_STATUS
map_ntstatus(NTSTATUS 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
;
45 FIXME("unhandled status %#lx\n", status
);
46 return NTE_INTERNAL_ERROR
;
50 static struct object
*allocate_object(enum object_type type
)
53 if (!(ret
= calloc(1, sizeof(*ret
)))) return NULL
;
58 static struct object_property
*get_object_property(struct object
*object
, const WCHAR
*name
)
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
;
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");
80 property
= &object
->properties
[object
->num_properties
++];
84 struct object_property
*tmp
;
85 if (!(tmp
= realloc(object
->properties
, sizeof(*property
) * (object
->num_properties
+ 1))))
87 ERR("Error allocating memory.\n");
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");
101 lstrcpyW(property
->key
, name
);
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
);
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");
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
;
132 if (!(object
= allocate_object(KEY
)))
134 ERR("Error allocating memory\n");
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
);
150 object
->key
.algid
= RSA
;
151 set_object_property(object
, NCRYPT_ALGORITHM_GROUP_PROPERTY
, (BYTE
*)BCRYPT_RSA_ALGORITHM
,
152 sizeof(BCRYPT_RSA_ALGORITHM
));
157 ERR("Invalid algid %#x\n", algid
);
163 set_object_property(object
, NCRYPT_PROVIDER_HANDLE_PROPERTY
, (BYTE
*)&provider
, sizeof(provider
));
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
))
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);
196 return map_ntstatus(status
);
199 set_object_property(object
, NCRYPT_LENGTH_PROPERTY
, (BYTE
*)&default_bitlen
, sizeof(default_bitlen
));
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
;
251 struct object_property
*prop
;
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
;
297 TRACE("(%#Ix)\n", handle
);
301 WARN("invalid handle %#Ix\n", handle
);
302 return NTE_INVALID_HANDLE
;
305 switch (object
->type
)
309 if ((ret
= free_key_object(&object
->key
))) return ret
;
312 case STORAGE_PROVIDER
:
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
);
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
);
362 FIXME("Key blob decryption not implemented\n");
363 return NTE_NOT_SUPPORTED
;
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");
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
:
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);
401 return map_ntstatus(status
);
404 set_object_property(object
, NCRYPT_LENGTH_PROPERTY
, (BYTE
*)&rsablob
->BitLength
, sizeof(rsablob
->BitLength
));
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
);
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
));