20 #include <winpr/assert.h>
21 #include <winpr/library.h>
22 #include <winpr/ncrypt.h>
26 #include <winpr/print.h>
31 #define TAG WINPR_TAG("ncrypt")
33 const static char NCRYPT_MAGIC[6] = {
'N',
'C',
'R',
'Y',
'P',
'T' };
35 SECURITY_STATUS checkNCryptHandle(NCRYPT_HANDLE handle, NCryptHandleType matchType)
39 WLog_VRB(TAG,
"invalid handle '%p'", handle);
40 return ERROR_INVALID_PARAMETER;
44 if (memcmp(base->magic, NCRYPT_MAGIC, ARRAYSIZE(NCRYPT_MAGIC)) != 0)
46 char magic1[ARRAYSIZE(NCRYPT_MAGIC) + 1] = { 0 };
47 char magic2[ARRAYSIZE(NCRYPT_MAGIC) + 1] = { 0 };
49 memcpy(magic1, base->magic, ARRAYSIZE(NCRYPT_MAGIC));
50 memcpy(magic2, NCRYPT_MAGIC, ARRAYSIZE(NCRYPT_MAGIC));
52 WLog_VRB(TAG,
"handle '%p' invalid magic '%s' instead of '%s'", base, magic1, magic2);
53 return ERROR_INVALID_PARAMETER;
58 case WINPR_NCRYPT_PROVIDER:
59 case WINPR_NCRYPT_KEY:
62 WLog_VRB(TAG,
"handle '%p' invalid type %d", base, base->type);
63 return ERROR_INVALID_PARAMETER;
66 if ((matchType != WINPR_NCRYPT_INVALID) && (base->type != matchType))
68 WLog_VRB(TAG,
"handle '%p' invalid type %d, expected %d", base, base->type, matchType);
69 return ERROR_INVALID_PARAMETER;
74 void* ncrypt_new_handle(NCryptHandleType kind,
size_t len, NCryptGetPropertyFn getProp,
81 memcpy(ret->magic, NCRYPT_MAGIC,
sizeof(ret->magic));
83 ret->getPropertyFn = getProp;
84 ret->releaseFn = dtor;
88 SECURITY_STATUS winpr_NCryptDefault_dtor(NCRYPT_HANDLE handle)
93 memset(h->magic, 0,
sizeof(h->magic));
94 h->type = WINPR_NCRYPT_INVALID;
101 SECURITY_STATUS NCryptEnumStorageProviders(DWORD* wProviderCount,
105 size_t stringAllocSize = 0;
107 LPWSTR strPtr = NULL;
108 static const WCHAR emptyComment[] = { 0 };
109 size_t copyAmount = 0;
113 *ppProviderList = NULL;
116 *wProviderCount += 1;
117 stringAllocSize += (_wcslen(MS_SCARD_PROV) + 1) * 2;
118 stringAllocSize +=
sizeof(emptyComment);
121 if (!*wProviderCount)
122 return ERROR_SUCCESS;
126 return NTE_NO_MEMORY;
129 strPtr = (LPWSTR)(ret + *wProviderCount);
131 ret->pszName = strPtr;
132 copyAmount = (_wcslen(MS_SCARD_PROV) + 1) * 2;
133 memcpy(strPtr, MS_SCARD_PROV, copyAmount);
134 strPtr += copyAmount / 2;
136 ret->pszComment = strPtr;
137 copyAmount =
sizeof(emptyComment);
138 memcpy(strPtr, emptyComment, copyAmount);
140 *ppProviderList = ret;
143 return ERROR_SUCCESS;
146 SECURITY_STATUS NCryptOpenStorageProvider(NCRYPT_PROV_HANDLE* phProvider, LPCWSTR pszProviderName,
149 return winpr_NCryptOpenStorageProviderEx(phProvider, pszProviderName, dwFlags, NULL);
152 SECURITY_STATUS winpr_NCryptOpenStorageProviderEx(NCRYPT_PROV_HANDLE* phProvider,
153 LPCWSTR pszProviderName, DWORD dwFlags,
156 #if defined(WITH_PKCS11)
157 if (pszProviderName && ((_wcscmp(pszProviderName, MS_SMART_CARD_KEY_STORAGE_PROVIDER) == 0) ||
158 (_wcscmp(pszProviderName, MS_SCARD_PROV) == 0)))
159 return NCryptOpenP11StorageProviderEx(phProvider, pszProviderName, dwFlags, modulePaths);
161 char buffer[128] = { 0 };
162 (void)ConvertWCharToUtf8(pszProviderName, buffer,
sizeof(buffer));
163 WLog_WARN(TAG,
"provider '%s' not supported", buffer);
164 return ERROR_NOT_SUPPORTED;
166 WLog_WARN(TAG,
"rebuild with -DWITH_PKCS11=ON to enable smartcard logon support");
167 return ERROR_NOT_SUPPORTED;
171 SECURITY_STATUS NCryptEnumKeys(NCRYPT_PROV_HANDLE hProvider, LPCWSTR pszScope,
172 NCryptKeyName** ppKeyName, PVOID* ppEnumState, DWORD dwFlags)
174 SECURITY_STATUS ret = 0;
177 ret = checkNCryptHandle((NCRYPT_HANDLE)hProvider, WINPR_NCRYPT_PROVIDER);
178 if (ret != ERROR_SUCCESS)
181 return provider->enumKeysFn(hProvider, pszScope, ppKeyName, ppEnumState, dwFlags);
184 SECURITY_STATUS NCryptOpenKey(NCRYPT_PROV_HANDLE hProvider, NCRYPT_KEY_HANDLE* phKey,
185 LPCWSTR pszKeyName, DWORD dwLegacyKeySpec, DWORD dwFlags)
187 SECURITY_STATUS ret = 0;
190 ret = checkNCryptHandle((NCRYPT_HANDLE)hProvider, WINPR_NCRYPT_PROVIDER);
191 if (ret != ERROR_SUCCESS)
193 if (!phKey || !pszKeyName)
194 return ERROR_INVALID_PARAMETER;
196 return provider->openKeyFn(hProvider, phKey, pszKeyName, dwLegacyKeySpec, dwFlags);
199 static NCryptKeyGetPropertyEnum propertyStringToEnum(LPCWSTR pszProperty)
201 if (_wcscmp(pszProperty, NCRYPT_CERTIFICATE_PROPERTY) == 0)
203 return NCRYPT_PROPERTY_CERTIFICATE;
205 else if (_wcscmp(pszProperty, NCRYPT_READER_PROPERTY) == 0)
207 return NCRYPT_PROPERTY_READER;
209 else if (_wcscmp(pszProperty, NCRYPT_WINPR_SLOTID) == 0)
211 return NCRYPT_PROPERTY_SLOTID;
213 else if (_wcscmp(pszProperty, NCRYPT_NAME_PROPERTY) == 0)
215 return NCRYPT_PROPERTY_NAME;
218 return NCRYPT_PROPERTY_UNKNOWN;
221 SECURITY_STATUS NCryptGetProperty(NCRYPT_HANDLE hObject, LPCWSTR pszProperty, PBYTE pbOutput,
222 DWORD cbOutput, DWORD* pcbResult, DWORD dwFlags)
224 NCryptKeyGetPropertyEnum
property = NCRYPT_PROPERTY_UNKNOWN;
228 return ERROR_INVALID_PARAMETER;
231 if (memcmp(base->magic, NCRYPT_MAGIC, 6) != 0)
232 return ERROR_INVALID_HANDLE;
234 property = propertyStringToEnum(pszProperty);
235 if (property == NCRYPT_PROPERTY_UNKNOWN)
236 return ERROR_NOT_SUPPORTED;
238 return base->getPropertyFn(hObject, property, pbOutput, cbOutput, pcbResult, dwFlags);
241 SECURITY_STATUS NCryptFreeObject(NCRYPT_HANDLE hObject)
244 SECURITY_STATUS ret = checkNCryptHandle(hObject, WINPR_NCRYPT_INVALID);
245 if (ret != ERROR_SUCCESS)
250 ret = base->releaseFn(hObject);
255 SECURITY_STATUS NCryptFreeBuffer(PVOID pvInput)
258 return ERROR_INVALID_PARAMETER;
261 return ERROR_SUCCESS;
265 SECURITY_STATUS winpr_NCryptOpenStorageProviderEx(NCRYPT_PROV_HANDLE* phProvider,
266 LPCWSTR pszProviderName, DWORD dwFlags,
269 typedef SECURITY_STATUS (*NCryptOpenStorageProviderFn)(NCRYPT_PROV_HANDLE * phProvider,
270 LPCWSTR pszProviderName, DWORD dwFlags);
271 SECURITY_STATUS ret = NTE_PROV_DLL_NOT_FOUND;
272 HANDLE lib = LoadLibraryA(
"ncrypt.dll");
274 return NTE_PROV_DLL_NOT_FOUND;
276 NCryptOpenStorageProviderFn ncryptOpenStorageProviderFn =
277 GetProcAddressAs(lib,
"NCryptOpenStorageProvider", NCryptOpenStorageProviderFn);
278 if (!ncryptOpenStorageProviderFn)
280 ret = NTE_PROV_DLL_NOT_FOUND;
284 ret = ncryptOpenStorageProviderFn(phProvider, pszProviderName, dwFlags);
292 const char* winpr_NCryptSecurityStatusError(SECURITY_STATUS status)
294 #define NTE_CASE(S) \
295 case (SECURITY_STATUS)(S): \
300 NTE_CASE(ERROR_SUCCESS);
301 NTE_CASE(ERROR_INVALID_PARAMETER);
302 NTE_CASE(ERROR_INVALID_HANDLE);
303 NTE_CASE(ERROR_NOT_SUPPORTED);
305 NTE_CASE(NTE_BAD_UID);
306 NTE_CASE(NTE_BAD_HASH);
307 NTE_CASE(NTE_BAD_KEY);
308 NTE_CASE(NTE_BAD_LEN);
309 NTE_CASE(NTE_BAD_DATA);
310 NTE_CASE(NTE_BAD_SIGNATURE);
311 NTE_CASE(NTE_BAD_VER);
312 NTE_CASE(NTE_BAD_ALGID);
313 NTE_CASE(NTE_BAD_FLAGS);
314 NTE_CASE(NTE_BAD_TYPE);
315 NTE_CASE(NTE_BAD_KEY_STATE);
316 NTE_CASE(NTE_BAD_HASH_STATE);
317 NTE_CASE(NTE_NO_KEY);
318 NTE_CASE(NTE_NO_MEMORY);
319 NTE_CASE(NTE_EXISTS);
321 NTE_CASE(NTE_NOT_FOUND);
322 NTE_CASE(NTE_DOUBLE_ENCRYPT);
323 NTE_CASE(NTE_BAD_PROVIDER);
324 NTE_CASE(NTE_BAD_PROV_TYPE);
325 NTE_CASE(NTE_BAD_PUBLIC_KEY);
326 NTE_CASE(NTE_BAD_KEYSET);
327 NTE_CASE(NTE_PROV_TYPE_NOT_DEF);
328 NTE_CASE(NTE_PROV_TYPE_ENTRY_BAD);
329 NTE_CASE(NTE_KEYSET_NOT_DEF);
330 NTE_CASE(NTE_KEYSET_ENTRY_BAD);
331 NTE_CASE(NTE_PROV_TYPE_NO_MATCH);
332 NTE_CASE(NTE_SIGNATURE_FILE_BAD);
333 NTE_CASE(NTE_PROVIDER_DLL_FAIL);
334 NTE_CASE(NTE_PROV_DLL_NOT_FOUND);
335 NTE_CASE(NTE_BAD_KEYSET_PARAM);
337 NTE_CASE(NTE_SYS_ERR);
338 NTE_CASE(NTE_SILENT_CONTEXT);
339 NTE_CASE(NTE_TOKEN_KEYSET_STORAGE_FULL);
340 NTE_CASE(NTE_TEMPORARY_PROFILE);
341 NTE_CASE(NTE_FIXEDPARAMETER);
350 const char* winpr_NCryptGetModulePath(NCRYPT_PROV_HANDLE phProvider)
352 #if defined(WITH_PKCS11)
353 return NCryptGetModulePath(phProvider);
common ncrypt handle items
common ncrypt provider items
a provider name descriptor