FreeRDP
Loading...
Searching...
No Matches
ncrypt.c
1
20#include <winpr/assert.h>
21#include <winpr/library.h>
22#include <winpr/ncrypt.h>
23
24#ifndef _WIN32
25
26#include <winpr/print.h>
27#include "../log.h"
28
29#include "ncrypt.h"
30
31#define TAG WINPR_TAG("ncrypt")
32
33const static char NCRYPT_MAGIC[6] = { 'N', 'C', 'R', 'Y', 'P', 'T' };
34
35SECURITY_STATUS checkNCryptHandle(NCRYPT_HANDLE handle, NCryptHandleType matchType)
36{
37 if (!handle)
38 {
39 WLog_VRB(TAG, "invalid handle 'NULL'");
40 return ERROR_INVALID_PARAMETER;
41 }
42
43 const NCryptBaseHandle* base = (NCryptBaseHandle*)handle;
44 if (memcmp(base->magic, NCRYPT_MAGIC, ARRAYSIZE(NCRYPT_MAGIC)) != 0)
45 {
46 char magic1[ARRAYSIZE(NCRYPT_MAGIC) + 1] = { 0 };
47 char magic2[ARRAYSIZE(NCRYPT_MAGIC) + 1] = { 0 };
48
49 memcpy(magic1, base->magic, ARRAYSIZE(NCRYPT_MAGIC));
50 memcpy(magic2, NCRYPT_MAGIC, ARRAYSIZE(NCRYPT_MAGIC));
51
52 WLog_VRB(TAG, "handle '%p' invalid magic '%s' instead of '%s'",
53 WINPR_CXX_COMPAT_CAST(const void*, base), magic1, magic2);
54 return ERROR_INVALID_PARAMETER;
55 }
56
57 switch (base->type)
58 {
59 case WINPR_NCRYPT_PROVIDER:
60 case WINPR_NCRYPT_KEY:
61 break;
62 default:
63 WLog_VRB(TAG, "handle '%p' invalid type %d", WINPR_CXX_COMPAT_CAST(const void*, base),
64 WINPR_CXX_COMPAT_CAST(int32_t, base->type));
65 return ERROR_INVALID_PARAMETER;
66 }
67
68 if ((matchType != WINPR_NCRYPT_INVALID) && (base->type != matchType))
69 {
70 WLog_VRB(TAG, "handle '%p' invalid type %d, expected %d",
71 WINPR_CXX_COMPAT_CAST(const void*, base),
72 WINPR_CXX_COMPAT_CAST(int32_t, base->type),
73 WINPR_CXX_COMPAT_CAST(int32_t, matchType));
74 return ERROR_INVALID_PARAMETER;
75 }
76 return ERROR_SUCCESS;
77}
78
79void* ncrypt_new_handle(NCryptHandleType kind, size_t len, NCryptGetPropertyFn getProp,
80 NCryptReleaseFn dtor)
81{
82 NCryptBaseHandle* ret = calloc(1, len);
83 if (!ret)
84 return NULL;
85
86 memcpy(ret->magic, NCRYPT_MAGIC, sizeof(ret->magic));
87 ret->type = kind;
88 ret->getPropertyFn = getProp;
89 ret->releaseFn = dtor;
90 return ret;
91}
92
93SECURITY_STATUS winpr_NCryptDefault_dtor(NCRYPT_HANDLE handle)
94{
96 if (h)
97 {
98 memset(h->magic, 0, sizeof(h->magic));
99 h->type = WINPR_NCRYPT_INVALID;
100 h->releaseFn = NULL;
101 free(h);
102 }
103 return ERROR_SUCCESS;
104}
105
106SECURITY_STATUS NCryptEnumStorageProviders(DWORD* wProviderCount,
107 NCryptProviderName** ppProviderList,
108 WINPR_ATTR_UNUSED DWORD dwFlags)
109{
110 NCryptProviderName* ret = NULL;
111 size_t stringAllocSize = 0;
112#ifdef WITH_PKCS11
113 LPWSTR strPtr = NULL;
114 static const WCHAR emptyComment[] = { 0 };
115 size_t copyAmount = 0;
116#endif
117
118 *wProviderCount = 0;
119 *ppProviderList = NULL;
120
121#ifdef WITH_PKCS11
122 *wProviderCount += 1;
123 stringAllocSize += (_wcslen(MS_SCARD_PROV) + 1) * 2;
124 stringAllocSize += sizeof(emptyComment);
125#endif
126
127 if (!*wProviderCount)
128 return ERROR_SUCCESS;
129
130 ret = malloc(*wProviderCount * sizeof(NCryptProviderName) + stringAllocSize);
131 if (!ret)
132 return NTE_NO_MEMORY;
133
134#ifdef WITH_PKCS11
135 strPtr = (LPWSTR)(ret + *wProviderCount);
136
137 ret->pszName = strPtr;
138 copyAmount = (_wcslen(MS_SCARD_PROV) + 1) * 2;
139 memcpy(strPtr, MS_SCARD_PROV, copyAmount);
140 strPtr += copyAmount / 2;
141
142 ret->pszComment = strPtr;
143 copyAmount = sizeof(emptyComment);
144 memcpy(strPtr, emptyComment, copyAmount);
145
146 *ppProviderList = ret;
147#endif
148
149 return ERROR_SUCCESS;
150}
151
152SECURITY_STATUS NCryptOpenStorageProvider(NCRYPT_PROV_HANDLE* phProvider, LPCWSTR pszProviderName,
153 DWORD dwFlags)
154{
155 return winpr_NCryptOpenStorageProviderEx(phProvider, pszProviderName, dwFlags, NULL);
156}
157
158SECURITY_STATUS winpr_NCryptOpenStorageProviderEx(NCRYPT_PROV_HANDLE* phProvider,
159 LPCWSTR pszProviderName, DWORD dwFlags,
160 LPCSTR* modulePaths)
161{
162#if defined(WITH_PKCS11)
163 if (pszProviderName && ((_wcscmp(pszProviderName, MS_SMART_CARD_KEY_STORAGE_PROVIDER) == 0) ||
164 (_wcscmp(pszProviderName, MS_SCARD_PROV) == 0)))
165 return NCryptOpenP11StorageProviderEx(phProvider, pszProviderName, dwFlags, modulePaths);
166
167 char buffer[128] = { 0 };
168 (void)ConvertWCharToUtf8(pszProviderName, buffer, sizeof(buffer));
169 WLog_WARN(TAG, "provider '%s' not supported", buffer);
170 return ERROR_NOT_SUPPORTED;
171#else
172 WLog_WARN(TAG, "rebuild with -DWITH_PKCS11=ON to enable smartcard logon support");
173 return ERROR_NOT_SUPPORTED;
174#endif
175}
176
177SECURITY_STATUS NCryptEnumKeys(NCRYPT_PROV_HANDLE hProvider, LPCWSTR pszScope,
178 NCryptKeyName** ppKeyName, PVOID* ppEnumState, DWORD dwFlags)
179{
180 SECURITY_STATUS ret = 0;
181 NCryptBaseProvider* provider = (NCryptBaseProvider*)hProvider;
182
183 ret = checkNCryptHandle((NCRYPT_HANDLE)hProvider, WINPR_NCRYPT_PROVIDER);
184 if (ret != ERROR_SUCCESS)
185 return ret;
186
187 return provider->enumKeysFn(hProvider, pszScope, ppKeyName, ppEnumState, dwFlags);
188}
189
190SECURITY_STATUS NCryptOpenKey(NCRYPT_PROV_HANDLE hProvider, NCRYPT_KEY_HANDLE* phKey,
191 LPCWSTR pszKeyName, DWORD dwLegacyKeySpec, DWORD dwFlags)
192{
193 SECURITY_STATUS ret = 0;
194 NCryptBaseProvider* provider = (NCryptBaseProvider*)hProvider;
195
196 ret = checkNCryptHandle((NCRYPT_HANDLE)hProvider, WINPR_NCRYPT_PROVIDER);
197 if (ret != ERROR_SUCCESS)
198 return ret;
199 if (!phKey || !pszKeyName)
200 return ERROR_INVALID_PARAMETER;
201
202 return provider->openKeyFn(hProvider, phKey, pszKeyName, dwLegacyKeySpec, dwFlags);
203}
204
205static NCryptKeyGetPropertyEnum propertyStringToEnum(LPCWSTR pszProperty)
206{
207 if (_wcscmp(pszProperty, NCRYPT_CERTIFICATE_PROPERTY) == 0)
208 {
209 return NCRYPT_PROPERTY_CERTIFICATE;
210 }
211 else if (_wcscmp(pszProperty, NCRYPT_READER_PROPERTY) == 0)
212 {
213 return NCRYPT_PROPERTY_READER;
214 }
215 else if (_wcscmp(pszProperty, NCRYPT_WINPR_SLOTID) == 0)
216 {
217 return NCRYPT_PROPERTY_SLOTID;
218 }
219 else if (_wcscmp(pszProperty, NCRYPT_NAME_PROPERTY) == 0)
220 {
221 return NCRYPT_PROPERTY_NAME;
222 }
223
224 return NCRYPT_PROPERTY_UNKNOWN;
225}
226
227SECURITY_STATUS NCryptGetProperty(NCRYPT_HANDLE hObject, LPCWSTR pszProperty, PBYTE pbOutput,
228 DWORD cbOutput, DWORD* pcbResult, DWORD dwFlags)
229{
230 NCryptKeyGetPropertyEnum property = NCRYPT_PROPERTY_UNKNOWN;
231 NCryptBaseHandle* base = NULL;
232
233 if (!hObject)
234 return ERROR_INVALID_PARAMETER;
235
236 base = (NCryptBaseHandle*)hObject;
237 if (memcmp(base->magic, NCRYPT_MAGIC, 6) != 0)
238 return ERROR_INVALID_HANDLE;
239
240 property = propertyStringToEnum(pszProperty);
241 if (property == NCRYPT_PROPERTY_UNKNOWN)
242 return ERROR_NOT_SUPPORTED;
243
244 return base->getPropertyFn(hObject, property, pbOutput, cbOutput, pcbResult, dwFlags);
245}
246
247SECURITY_STATUS NCryptFreeObject(NCRYPT_HANDLE hObject)
248{
249 NCryptBaseHandle* base = NULL;
250 SECURITY_STATUS ret = checkNCryptHandle(hObject, WINPR_NCRYPT_INVALID);
251 if (ret != ERROR_SUCCESS)
252 return ret;
253
254 base = (NCryptBaseHandle*)hObject;
255 if (base->releaseFn)
256 ret = base->releaseFn(hObject);
257
258 return ret;
259}
260
261SECURITY_STATUS NCryptFreeBuffer(PVOID pvInput)
262{
263 if (!pvInput)
264 return ERROR_INVALID_PARAMETER;
265
266 free(pvInput);
267 return ERROR_SUCCESS;
268}
269
270#else
271SECURITY_STATUS winpr_NCryptOpenStorageProviderEx(NCRYPT_PROV_HANDLE* phProvider,
272 LPCWSTR pszProviderName, DWORD dwFlags,
273 LPCSTR* modulePaths)
274{
275 typedef SECURITY_STATUS (*NCryptOpenStorageProviderFn)(NCRYPT_PROV_HANDLE * phProvider,
276 LPCWSTR pszProviderName, DWORD dwFlags);
277 SECURITY_STATUS ret = NTE_PROV_DLL_NOT_FOUND;
278 HANDLE lib = LoadLibraryA("ncrypt.dll");
279 if (!lib)
280 return NTE_PROV_DLL_NOT_FOUND;
281
282 NCryptOpenStorageProviderFn ncryptOpenStorageProviderFn =
283 GetProcAddressAs(lib, "NCryptOpenStorageProvider", NCryptOpenStorageProviderFn);
284 if (!ncryptOpenStorageProviderFn)
285 {
286 ret = NTE_PROV_DLL_NOT_FOUND;
287 goto out_free_lib;
288 }
289
290 ret = ncryptOpenStorageProviderFn(phProvider, pszProviderName, dwFlags);
291
292out_free_lib:
293 FreeLibrary(lib);
294 return ret;
295}
296#endif /* _WIN32 */
297
298const char* winpr_NCryptSecurityStatusError(SECURITY_STATUS status)
299{
300#define NTE_CASE(S) \
301 case (SECURITY_STATUS)(S): \
302 return #S
303
304 switch (status)
305 {
306 NTE_CASE(ERROR_SUCCESS);
307 NTE_CASE(ERROR_INVALID_PARAMETER);
308 NTE_CASE(ERROR_INVALID_HANDLE);
309 NTE_CASE(ERROR_NOT_SUPPORTED);
310
311 NTE_CASE(NTE_BAD_UID);
312 NTE_CASE(NTE_BAD_HASH);
313 NTE_CASE(NTE_BAD_KEY);
314 NTE_CASE(NTE_BAD_LEN);
315 NTE_CASE(NTE_BAD_DATA);
316 NTE_CASE(NTE_BAD_SIGNATURE);
317 NTE_CASE(NTE_BAD_VER);
318 NTE_CASE(NTE_BAD_ALGID);
319 NTE_CASE(NTE_BAD_FLAGS);
320 NTE_CASE(NTE_BAD_TYPE);
321 NTE_CASE(NTE_BAD_KEY_STATE);
322 NTE_CASE(NTE_BAD_HASH_STATE);
323 NTE_CASE(NTE_NO_KEY);
324 NTE_CASE(NTE_NO_MEMORY);
325 NTE_CASE(NTE_EXISTS);
326 NTE_CASE(NTE_PERM);
327 NTE_CASE(NTE_NOT_FOUND);
328 NTE_CASE(NTE_DOUBLE_ENCRYPT);
329 NTE_CASE(NTE_BAD_PROVIDER);
330 NTE_CASE(NTE_BAD_PROV_TYPE);
331 NTE_CASE(NTE_BAD_PUBLIC_KEY);
332 NTE_CASE(NTE_BAD_KEYSET);
333 NTE_CASE(NTE_PROV_TYPE_NOT_DEF);
334 NTE_CASE(NTE_PROV_TYPE_ENTRY_BAD);
335 NTE_CASE(NTE_KEYSET_NOT_DEF);
336 NTE_CASE(NTE_KEYSET_ENTRY_BAD);
337 NTE_CASE(NTE_PROV_TYPE_NO_MATCH);
338 NTE_CASE(NTE_SIGNATURE_FILE_BAD);
339 NTE_CASE(NTE_PROVIDER_DLL_FAIL);
340 NTE_CASE(NTE_PROV_DLL_NOT_FOUND);
341 NTE_CASE(NTE_BAD_KEYSET_PARAM);
342 NTE_CASE(NTE_FAIL);
343 NTE_CASE(NTE_SYS_ERR);
344 NTE_CASE(NTE_SILENT_CONTEXT);
345 NTE_CASE(NTE_TOKEN_KEYSET_STORAGE_FULL);
346 NTE_CASE(NTE_TEMPORARY_PROFILE);
347 NTE_CASE(NTE_FIXEDPARAMETER);
348
349 default:
350 return "<unknown>";
351 }
352
353#undef NTE_CASE
354}
355
356const char* winpr_NCryptGetModulePath(NCRYPT_PROV_HANDLE phProvider)
357{
358#if defined(WITH_PKCS11)
359 return NCryptGetModulePath(phProvider);
360#else
361 return NULL;
362#endif
363}
common ncrypt handle items
common ncrypt provider items
a key name descriptor
a provider name descriptor