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 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
;
48 FIXME("unhandled status %#lx\n", status
);
49 return NTE_INTERNAL_ERROR
;
53 static struct object
*allocate_object(enum object_type type
)
56 if (!(ret
= calloc(1, sizeof(*ret
)))) return NULL
;
61 static struct object_property
*get_object_property(struct object
*object
, const WCHAR
*name
)
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
;
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");
83 property
= &object
->properties
[object
->num_properties
++];
87 struct object_property
*tmp
;
88 if (!(tmp
= realloc(object
->properties
, sizeof(*property
) * (object
->num_properties
+ 1))))
90 ERR("Error allocating memory.\n");
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");
104 lstrcpyW(property
->key
, name
);
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
);
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");
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
;
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
));
145 ERR("Invalid algid %#x\n", algid
);
149 set_object_property(object
, NCRYPT_PROVIDER_HANDLE_PROPERTY
, (BYTE
*)&provider
, sizeof(provider
));
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
))
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
);
181 return map_ntstatus(status
);
184 set_object_property(object
, NCRYPT_LENGTH_PROPERTY
, (BYTE
*)&default_bitlen
, sizeof(default_bitlen
));
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
;
255 struct object_property
*prop
;
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
;
298 TRACE("(%#Ix)\n", handle
);
302 WARN("invalid handle %#Ix\n", handle
);
303 return NTE_INVALID_HANDLE
;
306 switch (object
->type
)
310 if ((ret
= free_key_object(&object
->key
))) return ret
;
313 case STORAGE_PROVIDER
:
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
);
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
);
363 FIXME("Key blob decryption not implemented\n");
364 return NTE_NOT_SUPPORTED
;
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");
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
:
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
);
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
NCryptExportKey(NCRYPT_KEY_HANDLE key
, NCRYPT_KEY_HANDLE encrypt_key
, const WCHAR
*type
,
417 NCryptBufferDesc
*params
, BYTE
*output
, DWORD output_len
, DWORD
*ret_len
,
420 struct object
*object
= (struct object
*)key
;
422 TRACE("(%#Ix, %#Ix, %s, %p, %p, %lu, %p, %#lx)\n", key
, encrypt_key
, wine_dbgstr_w(type
), params
, output
,
423 output_len
, ret_len
, flags
);
427 FIXME("Key blob encryption not implemented\n");
428 return NTE_NOT_SUPPORTED
;
432 FIXME("Parameter information not implemented\n");
433 return NTE_NOT_SUPPORTED
;
435 if (flags
== NCRYPT_SILENT_FLAG
)
437 FIXME("Silent flag not implemented\n");
440 return map_ntstatus(BCryptExportKey(object
->key
.bcrypt_key
, NULL
, type
, output
, output_len
, ret_len
, 0));
443 SECURITY_STATUS WINAPI
NCryptIsAlgSupported(NCRYPT_PROV_HANDLE provider
, const WCHAR
*algid
, DWORD flags
)
445 static const ULONG supported
= BCRYPT_CIPHER_OPERATION
|\
446 BCRYPT_ASYMMETRIC_ENCRYPTION_OPERATION
|\
447 BCRYPT_SIGNATURE_OPERATION
|\
448 BCRYPT_SECRET_AGREEMENT_OPERATION
;
449 BCRYPT_ALGORITHM_IDENTIFIER
*list
;
453 TRACE("(%#Ix, %s, %#lx)\n", provider
, wine_dbgstr_w(algid
), flags
);
455 if (!provider
) return NTE_INVALID_HANDLE
;
456 if (!algid
) return HRESULT_FROM_WIN32(RPC_X_NULL_REF_POINTER
);
457 if (flags
== NCRYPT_SILENT_FLAG
)
459 FIXME("Silent flag not implemented\n");
463 WARN("Invalid flags %#lx\n", flags
);
464 return NTE_BAD_FLAGS
;
466 if (!lstrcmpiW(BCRYPT_RSA_SIGN_ALGORITHM
, algid
)) return NTE_NOT_SUPPORTED
;
468 status
= BCryptEnumAlgorithms(supported
, &count
, &list
, 0);
469 if (status
!= STATUS_SUCCESS
)
471 ERR("Error retrieving algorithm list %#lx\n", status
);
472 return map_ntstatus(status
);
475 status
= STATUS_NOT_SUPPORTED
;
476 for (i
= 0; i
< count
; i
++)
478 if (!lstrcmpiW(list
[i
].pszName
, algid
))
480 status
= STATUS_SUCCESS
;
485 BCryptFreeBuffer(list
);
486 return map_ntstatus(status
);
489 BOOL WINAPI
NCryptIsKeyHandle(NCRYPT_KEY_HANDLE hKey
)
491 FIXME("(%#Ix): stub\n", hKey
);
495 SECURITY_STATUS WINAPI
NCryptOpenKey(NCRYPT_PROV_HANDLE provider
, NCRYPT_KEY_HANDLE
*key
,
496 const WCHAR
*name
, DWORD keyspec
, DWORD flags
)
498 FIXME("(%#Ix, %p, %s, %#lx, %#lx): stub\n", provider
, key
, wine_dbgstr_w(name
), keyspec
, flags
);
499 return NTE_NOT_SUPPORTED
;
502 SECURITY_STATUS WINAPI
NCryptOpenStorageProvider(NCRYPT_PROV_HANDLE
*provider
, const WCHAR
*name
, DWORD flags
)
504 struct object
*object
;
506 FIXME("(%p, %s, %#lx): stub\n", provider
, wine_dbgstr_w(name
), flags
);
508 if (!(object
= allocate_object(STORAGE_PROVIDER
)))
510 ERR("Error allocating memory.\n");
511 return NTE_NO_MEMORY
;
513 *provider
= (NCRYPT_PROV_HANDLE
)object
;
514 return ERROR_SUCCESS
;
517 SECURITY_STATUS WINAPI
NCryptSetProperty(NCRYPT_HANDLE handle
, const WCHAR
*name
, BYTE
*input
, DWORD insize
, DWORD flags
)
519 struct object
*object
= (struct object
*)handle
;
521 TRACE("(%#Ix, %s, %p, %lu, %#lx)\n", handle
, wine_dbgstr_w(name
), input
, insize
, flags
);
522 if (flags
) FIXME("flags %#lx not supported\n", flags
);
524 if (!object
) return NTE_INVALID_HANDLE
;
525 return set_object_property(object
, name
, input
, insize
);
528 SECURITY_STATUS WINAPI
NCryptSignHash(NCRYPT_KEY_HANDLE handle
, void *padding
, BYTE
*value
, DWORD value_len
,
529 BYTE
*sig
, DWORD sig_len
, DWORD
*ret_len
, DWORD flags
)
531 struct object
*object
= (struct object
*)handle
;
533 TRACE("(%#Ix, %p, %p, %lu, %p, %lu, %#lx)\n", handle
, padding
, value
, value_len
, sig
, sig_len
, flags
);
534 if (flags
& NCRYPT_SILENT_FLAG
) FIXME("Silent flag not implemented\n");
536 if (!object
|| object
->type
!= KEY
) return NTE_INVALID_HANDLE
;
538 return map_ntstatus(BCryptSignHash(object
->key
.bcrypt_key
, padding
, value
, value_len
, sig
, sig_len
,
539 ret_len
, flags
& ~NCRYPT_SILENT_FLAG
));
542 SECURITY_STATUS WINAPI
NCryptVerifySignature(NCRYPT_KEY_HANDLE handle
, void *padding
, BYTE
*hash
, DWORD hash_size
,
543 BYTE
*signature
, DWORD signature_size
, DWORD flags
)
545 struct object
*key_object
= (struct object
*)handle
;
547 TRACE("(%#Ix, %p, %p, %lu, %p, %lu, %#lx)\n", handle
, padding
, hash
, hash_size
, signature
,
548 signature_size
, flags
);
550 if (!hash_size
|| !signature_size
) return NTE_INVALID_PARAMETER
;
551 if (!hash
|| !signature
) return HRESULT_FROM_WIN32(RPC_X_NULL_REF_POINTER
);
552 if (!handle
|| key_object
->type
!= KEY
) return NTE_INVALID_HANDLE
;
554 if (key_object
->key
.algid
< RSA
)
556 FIXME("Symmetric keys not supported.\n");
557 return NTE_NOT_SUPPORTED
;
560 return map_ntstatus(BCryptVerifySignature(key_object
->key
.bcrypt_key
, padding
, hash
, hash_size
, signature
,
561 signature_size
, flags
));