FreeRDP
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Modules Pages
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
30static 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
55x509_release:
56 X509_free(x509);
57bio_release:
58 BIO_free(bio);
59}
60
61int 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;
161fail:
162 NCryptFreeBuffer(names);
163 return rc;
164}
a key name descriptor
a provider name descriptor