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
= wcsdup(name
)))
100 ERR("Error allocating memory.\n");
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
);
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");
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
;
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
));
148 set_object_property(object
, NCRYPT_BLOCK_LENGTH_PROPERTY
, (BYTE
*)&dw_value
, sizeof(dw_value
));
150 set_object_property(object
, BCRYPT_SIGNATURE_LENGTH
, (BYTE
*)&dw_value
, sizeof(dw_value
));
154 ERR("Invalid algid %#x\n", algid
);
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
));
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
));
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
))
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
);
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
));
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
;
271 struct object_property
*prop
;
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
;
314 TRACE("(%#Ix)\n", handle
);
318 WARN("invalid handle %#Ix\n", handle
);
319 return NTE_INVALID_HANDLE
;
322 switch (object
->type
)
326 if ((ret
= free_key_object(&object
->key
))) return ret
;
329 case STORAGE_PROVIDER
:
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
);
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
);
379 FIXME("Key blob decryption not implemented\n");
380 return NTE_NOT_SUPPORTED
;
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");
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
:
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
);
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
));
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
,
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
);
444 FIXME("Key blob encryption not implemented\n");
445 return NTE_NOT_SUPPORTED
;
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
;
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");
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
;
502 BCryptFreeBuffer(list
);
503 return map_ntstatus(status
);
506 BOOL WINAPI
NCryptIsKeyHandle(NCRYPT_KEY_HANDLE hKey
)
508 FIXME("(%#Ix): stub\n", hKey
);
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
));