FreeRDP
TestNCryptSmartcard.c
1 
19 #include <winpr/error.h>
20 #include <winpr/ncrypt.h>
21 #include <winpr/string.h>
22 #include <winpr/wlog.h>
23 #include <winpr/smartcard.h>
24 
25 #include <openssl/bio.h>
26 #include <openssl/x509.h>
27 
28 #define TAG "testNCrypt"
29 
30 static void crypto_print_name(const BYTE* b, DWORD sz)
31 {
32  if (sz > INT32_MAX)
33  return;
34  BIO* bio = BIO_new_mem_buf(b, (int)sz);
35  if (!bio)
36  return;
37 
38  X509* x509 = d2i_X509_bio(bio, NULL);
39  if (!x509)
40  goto bio_release;
41 
42  X509_NAME* name = X509_get_subject_name(x509);
43  if (!name)
44  goto x509_release;
45 
46  char* ret = calloc(1024, sizeof(char));
47  if (!ret)
48  goto bio_release;
49 
50  char* ret2 = X509_NAME_oneline(name, ret, 1024);
51 
52  printf("\t%s\n", ret2);
53  free(ret);
54 
55 x509_release:
56  X509_free(x509);
57 bio_release:
58  BIO_free(bio);
59 }
60 
61 int TestNCryptSmartcard(int argc, char* argv[])
62 {
63  int rc = -1;
64  DWORD providerCount = 0;
65  NCryptProviderName* names = NULL;
66 
67  WINPR_UNUSED(argc);
68  WINPR_UNUSED(argv);
69 
70  SECURITY_STATUS status = NCryptEnumStorageProviders(&providerCount, &names, NCRYPT_SILENT_FLAG);
71  if (status != ERROR_SUCCESS)
72  return -1;
73 
74  for (size_t j = 0; j < providerCount; j++)
75  {
76  const NCryptProviderName* name = &names[j];
77  NCRYPT_PROV_HANDLE provider = 0;
78  char providerNameStr[256] = { 0 };
79  PVOID enumState = NULL;
80  size_t i = 0;
81  NCryptKeyName* keyName = NULL;
82 
83  if (ConvertWCharToUtf8(name->pszName, providerNameStr, ARRAYSIZE(providerNameStr)) < 0)
84  continue;
85  printf("provider %" PRIuz ": %s\n", j, providerNameStr);
86 
87  status = NCryptOpenStorageProvider(&provider, name->pszName, 0);
88  if (status != ERROR_SUCCESS)
89  continue;
90 
91  while ((status = NCryptEnumKeys(provider, NULL, &keyName, &enumState,
92  NCRYPT_SILENT_FLAG)) == ERROR_SUCCESS)
93  {
94  NCRYPT_KEY_HANDLE phKey = 0;
95  DWORD dwFlags = 0;
96  DWORD cbOutput = 0;
97  char keyNameStr[256] = { 0 };
98  WCHAR reader[1024] = { 0 };
99  PBYTE certBytes = NULL;
100 
101  if (ConvertWCharToUtf8(keyName->pszName, keyNameStr, ARRAYSIZE(keyNameStr)) < 0)
102  continue;
103 
104  printf("\tkey %" PRIuz ": %s\n", i, keyNameStr);
105  status = NCryptOpenKey(provider, &phKey, keyName->pszName, keyName->dwLegacyKeySpec,
106  dwFlags);
107  if (status != ERROR_SUCCESS)
108  {
109  WLog_ERR(TAG, "unable to open key %s", keyNameStr);
110  continue;
111  }
112 
113  status = NCryptGetProperty(phKey, NCRYPT_READER_PROPERTY, (PBYTE)reader, sizeof(reader),
114  &cbOutput, dwFlags);
115  if (status == ERROR_SUCCESS)
116  {
117  char readerStr[1024] = { 0 };
118 
119  (void)ConvertWCharNToUtf8(reader, cbOutput, readerStr, ARRAYSIZE(readerStr));
120  printf("\treader: %s\n", readerStr);
121  }
122 
123  cbOutput = 0;
124  status =
125  NCryptGetProperty(phKey, NCRYPT_CERTIFICATE_PROPERTY, NULL, 0, &cbOutput, dwFlags);
126  if (status != ERROR_SUCCESS)
127  {
128  WLog_ERR(TAG, "unable to retrieve certificate len for key '%s'", keyNameStr);
129  goto endofloop;
130  }
131 
132  certBytes = calloc(1, cbOutput);
133  status = NCryptGetProperty(phKey, NCRYPT_CERTIFICATE_PROPERTY, certBytes, cbOutput,
134  &cbOutput, dwFlags);
135  if (status != ERROR_SUCCESS)
136  {
137  WLog_ERR(TAG, "unable to retrieve certificate for key %s", keyNameStr);
138  goto endofloop;
139  }
140 
141  crypto_print_name(certBytes, cbOutput);
142  free(certBytes);
143 
144  endofloop:
145  NCryptFreeBuffer(keyName);
146  NCryptFreeObject((NCRYPT_HANDLE)phKey);
147  i++;
148  }
149 
150  NCryptFreeBuffer(enumState);
151  NCryptFreeObject((NCRYPT_HANDLE)provider);
152 
153  if (status != NTE_NO_MORE_ITEMS)
154  {
155  (void)fprintf(stderr, "NCryptEnumKeys returned %s [0x%08" PRIx32 "]\n",
156  Win32ErrorCode2Tag(status), status);
157  }
158  }
159 
160  rc = 0;
161 fail:
162  NCryptFreeBuffer(names);
163  return rc;
164 }
a key name descriptor
a provider name descriptor