FreeRDP
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 
33 const static char NCRYPT_MAGIC[6] = { 'N', 'C', 'R', 'Y', 'P', 'T' };
34 
35 SECURITY_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 
74 void* 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 
88 SECURITY_STATUS winpr_NCryptDefault_dtor(NCRYPT_HANDLE handle)
89 {
90  NCryptBaseHandle* h = (NCryptBaseHandle*)handle;
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 
101 SECURITY_STATUS NCryptEnumStorageProviders(DWORD* wProviderCount,
102  NCryptProviderName** ppProviderList, DWORD dwFlags)
103 {
104  NCryptProviderName* ret = NULL;
105  size_t stringAllocSize = 0;
106 #ifdef WITH_PKCS11
107  LPWSTR strPtr = NULL;
108  static const WCHAR emptyComment[] = { 0 };
109  size_t copyAmount = 0;
110 #endif
111 
112  *wProviderCount = 0;
113  *ppProviderList = NULL;
114 
115 #ifdef WITH_PKCS11
116  *wProviderCount += 1;
117  stringAllocSize += (_wcslen(MS_SCARD_PROV) + 1) * 2;
118  stringAllocSize += sizeof(emptyComment);
119 #endif
120 
121  if (!*wProviderCount)
122  return ERROR_SUCCESS;
123 
124  ret = malloc(*wProviderCount * sizeof(NCryptProviderName) + stringAllocSize);
125  if (!ret)
126  return NTE_NO_MEMORY;
127 
128 #ifdef WITH_PKCS11
129  strPtr = (LPWSTR)(ret + *wProviderCount);
130 
131  ret->pszName = strPtr;
132  copyAmount = (_wcslen(MS_SCARD_PROV) + 1) * 2;
133  memcpy(strPtr, MS_SCARD_PROV, copyAmount);
134  strPtr += copyAmount / 2;
135 
136  ret->pszComment = strPtr;
137  copyAmount = sizeof(emptyComment);
138  memcpy(strPtr, emptyComment, copyAmount);
139 
140  *ppProviderList = ret;
141 #endif
142 
143  return ERROR_SUCCESS;
144 }
145 
146 SECURITY_STATUS NCryptOpenStorageProvider(NCRYPT_PROV_HANDLE* phProvider, LPCWSTR pszProviderName,
147  DWORD dwFlags)
148 {
149  return winpr_NCryptOpenStorageProviderEx(phProvider, pszProviderName, dwFlags, NULL);
150 }
151 
152 SECURITY_STATUS winpr_NCryptOpenStorageProviderEx(NCRYPT_PROV_HANDLE* phProvider,
153  LPCWSTR pszProviderName, DWORD dwFlags,
154  LPCSTR* modulePaths)
155 {
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);
160 
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;
165 #else
166  WLog_WARN(TAG, "rebuild with -DWITH_PKCS11=ON to enable smartcard logon support");
167  return ERROR_NOT_SUPPORTED;
168 #endif
169 }
170 
171 SECURITY_STATUS NCryptEnumKeys(NCRYPT_PROV_HANDLE hProvider, LPCWSTR pszScope,
172  NCryptKeyName** ppKeyName, PVOID* ppEnumState, DWORD dwFlags)
173 {
174  SECURITY_STATUS ret = 0;
175  NCryptBaseProvider* provider = (NCryptBaseProvider*)hProvider;
176 
177  ret = checkNCryptHandle((NCRYPT_HANDLE)hProvider, WINPR_NCRYPT_PROVIDER);
178  if (ret != ERROR_SUCCESS)
179  return ret;
180 
181  return provider->enumKeysFn(hProvider, pszScope, ppKeyName, ppEnumState, dwFlags);
182 }
183 
184 SECURITY_STATUS NCryptOpenKey(NCRYPT_PROV_HANDLE hProvider, NCRYPT_KEY_HANDLE* phKey,
185  LPCWSTR pszKeyName, DWORD dwLegacyKeySpec, DWORD dwFlags)
186 {
187  SECURITY_STATUS ret = 0;
188  NCryptBaseProvider* provider = (NCryptBaseProvider*)hProvider;
189 
190  ret = checkNCryptHandle((NCRYPT_HANDLE)hProvider, WINPR_NCRYPT_PROVIDER);
191  if (ret != ERROR_SUCCESS)
192  return ret;
193  if (!phKey || !pszKeyName)
194  return ERROR_INVALID_PARAMETER;
195 
196  return provider->openKeyFn(hProvider, phKey, pszKeyName, dwLegacyKeySpec, dwFlags);
197 }
198 
199 static NCryptKeyGetPropertyEnum propertyStringToEnum(LPCWSTR pszProperty)
200 {
201  if (_wcscmp(pszProperty, NCRYPT_CERTIFICATE_PROPERTY) == 0)
202  {
203  return NCRYPT_PROPERTY_CERTIFICATE;
204  }
205  else if (_wcscmp(pszProperty, NCRYPT_READER_PROPERTY) == 0)
206  {
207  return NCRYPT_PROPERTY_READER;
208  }
209  else if (_wcscmp(pszProperty, NCRYPT_WINPR_SLOTID) == 0)
210  {
211  return NCRYPT_PROPERTY_SLOTID;
212  }
213  else if (_wcscmp(pszProperty, NCRYPT_NAME_PROPERTY) == 0)
214  {
215  return NCRYPT_PROPERTY_NAME;
216  }
217 
218  return NCRYPT_PROPERTY_UNKNOWN;
219 }
220 
221 SECURITY_STATUS NCryptGetProperty(NCRYPT_HANDLE hObject, LPCWSTR pszProperty, PBYTE pbOutput,
222  DWORD cbOutput, DWORD* pcbResult, DWORD dwFlags)
223 {
224  NCryptKeyGetPropertyEnum property = NCRYPT_PROPERTY_UNKNOWN;
225  NCryptBaseHandle* base = NULL;
226 
227  if (!hObject)
228  return ERROR_INVALID_PARAMETER;
229 
230  base = (NCryptBaseHandle*)hObject;
231  if (memcmp(base->magic, NCRYPT_MAGIC, 6) != 0)
232  return ERROR_INVALID_HANDLE;
233 
234  property = propertyStringToEnum(pszProperty);
235  if (property == NCRYPT_PROPERTY_UNKNOWN)
236  return ERROR_NOT_SUPPORTED;
237 
238  return base->getPropertyFn(hObject, property, pbOutput, cbOutput, pcbResult, dwFlags);
239 }
240 
241 SECURITY_STATUS NCryptFreeObject(NCRYPT_HANDLE hObject)
242 {
243  NCryptBaseHandle* base = NULL;
244  SECURITY_STATUS ret = checkNCryptHandle(hObject, WINPR_NCRYPT_INVALID);
245  if (ret != ERROR_SUCCESS)
246  return ret;
247 
248  base = (NCryptBaseHandle*)hObject;
249  if (base->releaseFn)
250  ret = base->releaseFn(hObject);
251 
252  return ret;
253 }
254 
255 SECURITY_STATUS NCryptFreeBuffer(PVOID pvInput)
256 {
257  if (!pvInput)
258  return ERROR_INVALID_PARAMETER;
259 
260  free(pvInput);
261  return ERROR_SUCCESS;
262 }
263 
264 #else
265 SECURITY_STATUS winpr_NCryptOpenStorageProviderEx(NCRYPT_PROV_HANDLE* phProvider,
266  LPCWSTR pszProviderName, DWORD dwFlags,
267  LPCSTR* modulePaths)
268 {
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");
273  if (!lib)
274  return NTE_PROV_DLL_NOT_FOUND;
275 
276  NCryptOpenStorageProviderFn ncryptOpenStorageProviderFn =
277  GetProcAddressAs(lib, "NCryptOpenStorageProvider", NCryptOpenStorageProviderFn);
278  if (!ncryptOpenStorageProviderFn)
279  {
280  ret = NTE_PROV_DLL_NOT_FOUND;
281  goto out_free_lib;
282  }
283 
284  ret = ncryptOpenStorageProviderFn(phProvider, pszProviderName, dwFlags);
285 
286 out_free_lib:
287  FreeLibrary(lib);
288  return ret;
289 }
290 #endif /* _WIN32 */
291 
292 const char* winpr_NCryptSecurityStatusError(SECURITY_STATUS status)
293 {
294 #define NTE_CASE(S) \
295  case (SECURITY_STATUS)(S): \
296  return #S
297 
298  switch (status)
299  {
300  NTE_CASE(ERROR_SUCCESS);
301  NTE_CASE(ERROR_INVALID_PARAMETER);
302  NTE_CASE(ERROR_INVALID_HANDLE);
303  NTE_CASE(ERROR_NOT_SUPPORTED);
304 
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);
320  NTE_CASE(NTE_PERM);
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);
336  NTE_CASE(NTE_FAIL);
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);
342 
343  default:
344  return "<unknown>";
345  }
346 
347 #undef NTE_CASE
348 }
349 
350 const char* winpr_NCryptGetModulePath(NCRYPT_PROV_HANDLE phProvider)
351 {
352 #if defined(WITH_PKCS11)
353  return NCryptGetModulePath(phProvider);
354 #else
355  return NULL;
356 #endif
357 }
common ncrypt handle items
common ncrypt provider items
a key name descriptor
a provider name descriptor