1 |
#include <windows.h> |
2 |
#include <tchar.h> |
3 |
#include <Cryptuiapi.h> |
4 |
#include <commctrl.h> |
5 |
#include <cardmod.h> |
6 |
#include <Xenroll.h> |
7 |
#include <CertEnroll.h> |
8 |
|
9 |
BOOL SchGetProviderNameFromCardName(__in LPCTSTR szCardName, __out LPTSTR szProviderName, __out PDWORD pdwProviderNameLen); |
10 |
|
11 |
BSTR GetAuthenticationContainer() |
12 |
{ |
13 |
BSTR szSignatureContainer = NULL; |
14 |
HCRYPTPROV HMainCryptProv = NULL; |
15 |
BOOL bStatus = FALSE; |
16 |
LPTSTR szMainContainerName = NULL; |
17 |
CHAR szContainerName[1024]; |
18 |
DWORD dwContainerNameLen = sizeof(szContainerName); |
19 |
DWORD dwErr = 0; |
20 |
DWORD dwFlags = CRYPT_FIRST; |
21 |
DWORD dwContextArrayLen = 0; |
22 |
HCRYPTPROV hProv = NULL; |
23 |
HCRYPTKEY hKey = NULL; |
24 |
LPBYTE pbCert = NULL; |
25 |
DWORD dwCertLen = 0; |
26 |
PCCERT_CONTEXT pCertContext = NULL; |
27 |
PCCERT_CONTEXT pSelectedContext = NULL; |
28 |
HCERTSTORE hStore = NULL; |
29 |
TCHAR szCardName[256]; |
30 |
TCHAR szReaderName[256]; |
31 |
TCHAR szOutProviderName[256]; |
32 |
DWORD dwOutProviderLength = ARRAYSIZE(szOutProviderName); |
33 |
OPENCARDNAME_EX dlgStruct; |
34 |
DWORD dwReturn; |
35 |
SCARDCONTEXT hSCardContext = NULL; |
36 |
SCARDHANDLE hSCardHandle = NULL; |
37 |
LPWSTR szWideContainerName = NULL; |
38 |
__try |
39 |
{ |
40 |
dwReturn = SCardEstablishContext(SCARD_SCOPE_USER, |
41 |
NULL, |
42 |
NULL, |
43 |
&hSCardContext ); |
44 |
if ( SCARD_S_SUCCESS != dwReturn ) |
45 |
{ |
46 |
__leave; |
47 |
} |
48 |
// Initialize the structure. |
49 |
memset(&dlgStruct, 0, sizeof(dlgStruct)); |
50 |
dlgStruct.dwStructSize = sizeof(dlgStruct); |
51 |
dlgStruct.hSCardContext = hSCardContext; |
52 |
dlgStruct.dwFlags = SC_DLG_MINIMAL_UI; |
53 |
dlgStruct.lpstrRdr = szReaderName; |
54 |
dlgStruct.nMaxRdr = ARRAYSIZE(szReaderName); |
55 |
dlgStruct.lpstrCard = szCardName; |
56 |
dlgStruct.nMaxCard = ARRAYSIZE(szCardName); |
57 |
dlgStruct.lpstrTitle = L"Select Card"; |
58 |
dlgStruct.dwShareMode = 0; |
59 |
// Display the select card dialog box. |
60 |
dwReturn = SCardUIDlgSelectCard(&dlgStruct); |
61 |
if ( SCARD_S_SUCCESS != dwReturn ) |
62 |
{ |
63 |
__leave; |
64 |
} |
65 |
dwReturn = SCardUIDlgSelectCard(&dlgStruct); |
66 |
if ( SCARD_S_SUCCESS != dwReturn ) |
67 |
{ |
68 |
__leave; |
69 |
} |
70 |
if (!SchGetProviderNameFromCardName(szCardName, szOutProviderName, &dwOutProviderLength)) |
71 |
{ |
72 |
dwReturn = GetLastError(); |
73 |
__leave; |
74 |
} |
75 |
|
76 |
size_t ulNameLen = _tcslen(szReaderName); |
77 |
szMainContainerName = (LPWSTR) LocalAlloc(0,(DWORD)(ulNameLen + 6) * sizeof(WCHAR)); |
78 |
if (!szMainContainerName) |
79 |
{ |
80 |
dwReturn = GetLastError(); |
81 |
__leave; |
82 |
} |
83 |
swprintf_s(szMainContainerName,(ulNameLen + 6), L"\\\\.\\%s\\", szReaderName); |
84 |
|
85 |
bStatus = CryptAcquireContext(&HMainCryptProv, |
86 |
szMainContainerName, |
87 |
szOutProviderName, |
88 |
PROV_RSA_FULL, |
89 |
CRYPT_SILENT); |
90 |
if (!bStatus) |
91 |
{ |
92 |
dwReturn = GetLastError(); |
93 |
if (dwReturn == NTE_BAD_KEYSET) |
94 |
{ |
95 |
bStatus = CryptAcquireContext(&HMainCryptProv,NULL, szOutProviderName, PROV_RSA_FULL, CRYPT_SILENT); |
96 |
if (!bStatus) |
97 |
{ |
98 |
dwReturn = GetLastError(); |
99 |
__leave; |
100 |
} |
101 |
} |
102 |
else |
103 |
{ |
104 |
__leave; |
105 |
} |
106 |
|
107 |
} |
108 |
|
109 |
|
110 |
|
111 |
/* Enumerate all the containers */ |
112 |
while (CryptGetProvParam(HMainCryptProv, |
113 |
PP_ENUMCONTAINERS, |
114 |
(LPBYTE) szContainerName, |
115 |
&dwContainerNameLen, |
116 |
dwFlags) && |
117 |
(dwContextArrayLen < 128) |
118 |
) |
119 |
{ |
120 |
|
121 |
// convert the container name to unicode |
122 |
int wLen = MultiByteToWideChar(CP_ACP, 0, szContainerName, -1, NULL, 0); |
123 |
szWideContainerName = (LPWSTR) LocalAlloc(0,wLen * sizeof(WCHAR)); |
124 |
MultiByteToWideChar(CP_ACP, 0, szContainerName, -1, szWideContainerName, wLen); |
125 |
|
126 |
// Acquire a context on the current container |
127 |
if (CryptAcquireContext(&hProv, |
128 |
szWideContainerName, |
129 |
szOutProviderName, |
130 |
PROV_RSA_FULL, |
131 |
0)) |
132 |
{ |
133 |
// Loop over all the key specs |
134 |
if (CryptGetUserKey(hProv, |
135 |
AT_SIGNATURE, |
136 |
&hKey) ) |
137 |
{ |
138 |
if (wcsncmp(szWideContainerName,L"OPENPGP_",8) == 0 |
139 |
&& wcsstr(szWideContainerName, L"_Authenticate") != NULL) |
140 |
{ |
141 |
szSignatureContainer = SysAllocString(szWideContainerName); |
142 |
} |
143 |
CryptDestroyKey(hKey); |
144 |
hKey = NULL; |
145 |
} |
146 |
CryptReleaseContext(hProv, 0); |
147 |
hProv = NULL; |
148 |
} |
149 |
LocalFree(szWideContainerName); |
150 |
szWideContainerName = NULL; |
151 |
// prepare parameters for the next loop |
152 |
dwContainerNameLen = sizeof(szContainerName); |
153 |
dwFlags = 0; |
154 |
} |
155 |
} |
156 |
__finally |
157 |
{ |
158 |
if (szWideContainerName) |
159 |
LocalFree(szWideContainerName); |
160 |
if (hKey) |
161 |
CryptDestroyKey(hKey); |
162 |
if (hProv) |
163 |
CryptReleaseContext(hProv, 0); |
164 |
if (szMainContainerName) |
165 |
LocalFree(szMainContainerName); |
166 |
if (HMainCryptProv) |
167 |
CryptReleaseContext(HMainCryptProv, 0); |
168 |
} |
169 |
return szSignatureContainer; |
170 |
} |
171 |
|
172 |
|
173 |
HRESULT Enroll() |
174 |
{ |
175 |
BSTR bstrDN = NULL; |
176 |
BSTR bstrReq = NULL; |
177 |
BSTR bstrOID = NULL; |
178 |
ICEnroll4 * pEnroll = NULL; |
179 |
HRESULT hr; |
180 |
|
181 |
__try |
182 |
{ |
183 |
// initialize COM |
184 |
hr = CoInitializeEx( NULL, COINIT_APARTMENTTHREADED ); |
185 |
if (FAILED(hr)) |
186 |
{ |
187 |
__leave; |
188 |
} |
189 |
|
190 |
hr = CoCreateInstance( __uuidof(CEnroll2), |
191 |
NULL, |
192 |
CLSCTX_INPROC_SERVER, |
193 |
__uuidof(IEnroll4), |
194 |
(void **)&pEnroll); |
195 |
if (FAILED(hr)) |
196 |
{ |
197 |
__leave; |
198 |
} |
199 |
pEnroll->put_ContainerName(GetAuthenticationContainer()); |
200 |
pEnroll->put_KeySpec(AT_SIGNATURE); |
201 |
pEnroll->put_UseExistingKeySet(TRUE); |
202 |
pEnroll->put_WriteCertToCSP(FALSE); |
203 |
// generate the DN for the cert request |
204 |
bstrDN = SysAllocString( TEXT("CN=Your Name") // common name |
205 |
TEXT(",OU=Your Unit") // org unit |
206 |
TEXT(",O=Your Org") // organization |
207 |
TEXT(",L=Your City") // locality |
208 |
TEXT(",S=Your State") // state |
209 |
TEXT(",C=Your Country") ); // country/region |
210 |
if (NULL == bstrDN) |
211 |
{ |
212 |
hr = GetLastError(); |
213 |
__leave; |
214 |
} |
215 |
|
216 |
// generate the OID, for example, "1.3.6.1.4.1.311.2.1.21". |
217 |
bstrOID = SysAllocString(TEXT("1.3.6.1.5.5.7.3.2,1.3.6.1.4.1.311.20.2.2")); |
218 |
if (NULL == bstrOID) |
219 |
{ |
220 |
__leave; |
221 |
} |
222 |
|
223 |
// create the PKCS10 |
224 |
hr = pEnroll->createPKCS10( bstrDN, bstrOID, &bstrReq ); |
225 |
if (FAILED(hr)) |
226 |
{ |
227 |
__leave; |
228 |
} |
229 |
// do something with the PKCS10 (bstrReq); |
230 |
|
231 |
} |
232 |
__finally |
233 |
{ |
234 |
|
235 |
//clean up resources, etc. |
236 |
if ( bstrDN ) |
237 |
SysFreeString( bstrDN ); |
238 |
if ( bstrOID ) |
239 |
SysFreeString( bstrOID ); |
240 |
if ( bstrReq ) |
241 |
SysFreeString( bstrReq ); |
242 |
if ( pEnroll ) |
243 |
pEnroll->Release(); |
244 |
|
245 |
CoUninitialize(); |
246 |
} |
247 |
return hr; |
248 |
} |