1 |
vletoux |
12 |
#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 |
|
|
} |