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