[CRYPT32_WINETEST] Sync with Wine Staging 1.9.23. CORE-12409
[reactos.git] / rostests / winetests / crypt32 / cert.c
1 /*
2 * crypt32 cert functions tests
3 *
4 * Copyright 2005-2006 Juan Lang
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 */
20
21 //#include <stdio.h>
22 #include <stdarg.h>
23
24 #include <windef.h>
25 #include <winbase.h>
26 //#include <winreg.h>
27 //#include <winerror.h>
28 #include <wincrypt.h>
29
30 #include <wine/test.h>
31
32 static BOOL (WINAPI *pCertAddStoreToCollection)(HCERTSTORE,HCERTSTORE,DWORD,DWORD);
33 static PCCERT_CONTEXT (WINAPI *pCertCreateSelfSignCertificate)(HCRYPTPROV_OR_NCRYPT_KEY_HANDLE,PCERT_NAME_BLOB,DWORD,PCRYPT_KEY_PROV_INFO,PCRYPT_ALGORITHM_IDENTIFIER,PSYSTEMTIME,PSYSTEMTIME,PCERT_EXTENSIONS);
34 static BOOL (WINAPI *pCertGetValidUsages)(DWORD,PCCERT_CONTEXT*,int*,LPSTR*,DWORD*);
35 static BOOL (WINAPI *pCryptAcquireCertificatePrivateKey)(PCCERT_CONTEXT,DWORD,void*,HCRYPTPROV_OR_NCRYPT_KEY_HANDLE*,DWORD*,BOOL*);
36 static BOOL (WINAPI *pCryptEncodeObjectEx)(DWORD,LPCSTR,const void*,DWORD,PCRYPT_ENCODE_PARA,void*,DWORD*);
37 static BOOL (WINAPI * pCryptVerifyCertificateSignatureEx)
38 (HCRYPTPROV, DWORD, DWORD, void *, DWORD, void *, DWORD, void *);
39
40 static BOOL (WINAPI * pCryptAcquireContextA)
41 (HCRYPTPROV *, LPCSTR, LPCSTR, DWORD, DWORD);
42
43 static void init_function_pointers(void)
44 {
45 HMODULE hCrypt32 = GetModuleHandleA("crypt32.dll");
46 HMODULE hAdvapi32 = GetModuleHandleA("advapi32.dll");
47
48 #define GET_PROC(dll, func) \
49 p ## func = (void *)GetProcAddress(dll, #func); \
50 if(!p ## func) \
51 trace("GetProcAddress(%s) failed\n", #func);
52
53 GET_PROC(hCrypt32, CertAddStoreToCollection)
54 GET_PROC(hCrypt32, CertCreateSelfSignCertificate)
55 GET_PROC(hCrypt32, CertGetValidUsages)
56 GET_PROC(hCrypt32, CryptAcquireCertificatePrivateKey)
57 GET_PROC(hCrypt32, CryptEncodeObjectEx)
58 GET_PROC(hCrypt32, CryptVerifyCertificateSignatureEx)
59
60 GET_PROC(hAdvapi32, CryptAcquireContextA)
61
62 #undef GET_PROC
63 }
64
65 static BYTE subjectName[] = { 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06,
66 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61,
67 0x6e, 0x67, 0x00 };
68 static BYTE serialNum[] = { 1 };
69 static const BYTE bigCert[] = { 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
70 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
71 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22,
72 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30,
73 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30,
74 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30,
75 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20,
76 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01,
77 0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01,
78 0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
79 static BYTE bigCertHash[] = { 0x6e, 0x30, 0x90, 0x71, 0x5f, 0xd9, 0x23,
80 0x56, 0xeb, 0xae, 0x25, 0x40, 0xe6, 0x22, 0xda, 0x19, 0x26, 0x02, 0xa6, 0x08 };
81
82 static const BYTE bigCertWithDifferentSubject[] = { 0x30, 0x7a, 0x02, 0x01, 0x02,
83 0x30, 0x02, 0x06, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55,
84 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67,
85 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31,
86 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31,
87 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15,
88 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x41, 0x6c,
89 0x65, 0x78, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06,
90 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55,
91 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02,
92 0x01, 0x01 };
93 static const BYTE bigCertWithDifferentIssuer[] = { 0x30, 0x7a, 0x02, 0x01,
94 0x01, 0x30, 0x02, 0x06, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03,
95 0x55, 0x04, 0x03, 0x13, 0x0a, 0x41, 0x6c, 0x65, 0x78, 0x20, 0x4c, 0x61, 0x6e,
96 0x67, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30,
97 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30,
98 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30,
99 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a,
100 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02,
101 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03,
102 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff,
103 0x02, 0x01, 0x01 };
104
105 static BYTE subjectName2[] = { 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06,
106 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x41, 0x6c, 0x65, 0x78, 0x20, 0x4c, 0x61,
107 0x6e, 0x67, 0x00 };
108 static const BYTE bigCert2[] = { 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
109 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
110 0x0a, 0x41, 0x6c, 0x65, 0x78, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22,
111 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30,
112 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30,
113 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30,
114 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x41, 0x6c, 0x65, 0x78, 0x20,
115 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01,
116 0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01,
117 0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
118 static const BYTE bigCert2WithDifferentSerial[] = { 0x30, 0x7a, 0x02, 0x01,
119 0x02, 0x30, 0x02, 0x06, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03,
120 0x55, 0x04, 0x03, 0x13, 0x0a, 0x41, 0x6c, 0x65, 0x78, 0x20, 0x4c, 0x61, 0x6e,
121 0x67, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30,
122 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30,
123 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30,
124 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x41,
125 0x6c, 0x65, 0x78, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02,
126 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03,
127 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff,
128 0x02, 0x01, 0x01 };
129 static BYTE bigCert2Hash[] = { 0x4a, 0x7f, 0x32, 0x1f, 0xcf, 0x3b, 0xc0,
130 0x87, 0x48, 0x2b, 0xa1, 0x86, 0x54, 0x18, 0xe4, 0x3a, 0x0e, 0x53, 0x7e, 0x2b };
131
132 static const BYTE certWithUsage[] = { 0x30, 0x81, 0x93, 0x02, 0x01, 0x01, 0x30,
133 0x02, 0x06, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04,
134 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00,
135 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30,
136 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30,
137 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31,
138 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61,
139 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00,
140 0x03, 0x01, 0x00, 0xa3, 0x2f, 0x30, 0x2d, 0x30, 0x2b, 0x06, 0x03, 0x55, 0x1d,
141 0x25, 0x01, 0x01, 0xff, 0x04, 0x21, 0x30, 0x1f, 0x06, 0x08, 0x2b, 0x06, 0x01,
142 0x05, 0x05, 0x07, 0x03, 0x03, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07,
143 0x03, 0x02, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01 };
144
145 static void testAddCert(void)
146 {
147 HCERTSTORE store;
148 HCERTSTORE collection;
149 PCCERT_CONTEXT context;
150 PCCERT_CONTEXT copyContext;
151 BOOL ret;
152
153 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
154 CERT_STORE_CREATE_NEW_FLAG, NULL);
155 ok(store != NULL, "CertOpenStore failed: %d\n", GetLastError());
156 if (!store)
157 return;
158
159 /* Weird--bad add disposition leads to an access violation in Windows.
160 * Both tests crash on some win9x boxes.
161 */
162 if (0)
163 {
164 ret = CertAddEncodedCertificateToStore(0, X509_ASN_ENCODING, bigCert,
165 sizeof(bigCert), 0, NULL);
166 ok(!ret && (GetLastError() == STATUS_ACCESS_VIOLATION ||
167 GetLastError() == E_INVALIDARG),
168 "Expected STATUS_ACCESS_VIOLATION or E_INVALIDARG, got %08x\n",
169 GetLastError());
170 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
171 bigCert, sizeof(bigCert), 0, NULL);
172 ok(!ret && (GetLastError() == STATUS_ACCESS_VIOLATION ||
173 GetLastError() == E_INVALIDARG),
174 "Expected STATUS_ACCESS_VIOLATION or E_INVALIDARG, got %08x\n",
175 GetLastError());
176 }
177
178 /* Weird--can add a cert to the NULL store (does this have special
179 * meaning?)
180 */
181 context = NULL;
182 ret = CertAddEncodedCertificateToStore(0, X509_ASN_ENCODING, bigCert,
183 sizeof(bigCert), CERT_STORE_ADD_ALWAYS, &context);
184 ok(ret || broken(GetLastError() == OSS_DATA_ERROR /* win98 */),
185 "CertAddEncodedCertificateToStore failed: %08x\n", GetLastError());
186 if (context)
187 CertFreeCertificateContext(context);
188 if (!ret && GetLastError() == OSS_DATA_ERROR)
189 {
190 skip("bigCert can't be decoded, skipping tests\n");
191 return;
192 }
193
194 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
195 bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL);
196 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
197 GetLastError());
198 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
199 bigCert2, sizeof(bigCert2), CERT_STORE_ADD_NEW, NULL);
200 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
201 GetLastError());
202 /* This has the same name as bigCert, so finding isn't done by name */
203 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
204 certWithUsage, sizeof(certWithUsage), CERT_STORE_ADD_NEW, &context);
205 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
206 GetLastError());
207 ok(context != NULL, "Expected a context\n");
208 if (context)
209 {
210 CRYPT_DATA_BLOB hash = { sizeof(bigCert2Hash), bigCert2Hash };
211
212 /* Duplicate (AddRef) the context so we can still use it after
213 * deleting it from the store.
214 */
215 CertDuplicateCertificateContext(context);
216 CertDeleteCertificateFromStore(context);
217 /* Set the same hash as bigCert2, and try to readd it */
218 ret = CertSetCertificateContextProperty(context, CERT_HASH_PROP_ID,
219 0, &hash);
220 ok(ret, "CertSetCertificateContextProperty failed: %08x\n",
221 GetLastError());
222 ret = CertAddCertificateContextToStore(store, context,
223 CERT_STORE_ADD_NEW, NULL);
224 /* The failure is a bit odd (CRYPT_E_ASN1_BADTAG), so just check
225 * that it fails.
226 */
227 ok(!ret, "Expected failure\n");
228 CertFreeCertificateContext(context);
229 }
230 context = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert2,
231 sizeof(bigCert2));
232 ok(context != NULL, "Expected a context\n");
233 if (context)
234 {
235 /* Try to readd bigCert2 to the store */
236 ret = CertAddCertificateContextToStore(store, context,
237 CERT_STORE_ADD_NEW, NULL);
238 ok(!ret && GetLastError() == CRYPT_E_EXISTS,
239 "Expected CRYPT_E_EXISTS, got %08x\n", GetLastError());
240 CertFreeCertificateContext(context);
241 }
242
243 /* Adding a cert with the same issuer name and serial number (but
244 * different subject) as an existing cert succeeds.
245 */
246 context = NULL;
247 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
248 bigCert2WithDifferentSerial, sizeof(bigCert2WithDifferentSerial),
249 CERT_STORE_ADD_NEW, &context);
250 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
251 GetLastError());
252 if (context)
253 CertDeleteCertificateFromStore(context);
254
255 /* Adding a cert with the same subject name and serial number (but
256 * different issuer) as an existing cert succeeds.
257 */
258 context = NULL;
259 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
260 bigCertWithDifferentSubject, sizeof(bigCertWithDifferentSubject),
261 CERT_STORE_ADD_NEW, &context);
262 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
263 GetLastError());
264 if (context)
265 CertDeleteCertificateFromStore(context);
266
267 /* Adding a cert with the same issuer name and serial number (but
268 * different otherwise) as an existing cert succeeds.
269 */
270 context = NULL;
271 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
272 bigCertWithDifferentIssuer, sizeof(bigCertWithDifferentIssuer),
273 CERT_STORE_ADD_NEW, &context);
274 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
275 GetLastError());
276 if (context)
277 CertDeleteCertificateFromStore(context);
278
279 collection = CertOpenStore(CERT_STORE_PROV_COLLECTION, 0, 0,
280 CERT_STORE_CREATE_NEW_FLAG, NULL);
281 ok(collection != NULL, "CertOpenStore failed: %08x\n", GetLastError());
282 if (collection && pCertAddStoreToCollection)
283 {
284 /* Add store to the collection, but disable updates */
285 pCertAddStoreToCollection(collection, store, 0, 0);
286
287 context = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert2,
288 sizeof(bigCert2));
289 ok(context != NULL, "Expected a context\n");
290 if (context)
291 {
292 /* Try to readd bigCert2 to the collection */
293 ret = CertAddCertificateContextToStore(collection, context,
294 CERT_STORE_ADD_NEW, NULL);
295 ok(!ret && GetLastError() == CRYPT_E_EXISTS,
296 "Expected CRYPT_E_EXISTS, got %08x\n", GetLastError());
297 /* Replacing an existing certificate context is allowed, even
298 * though updates to the collection aren't..
299 */
300 ret = CertAddCertificateContextToStore(collection, context,
301 CERT_STORE_ADD_REPLACE_EXISTING, NULL);
302 ok(ret, "CertAddCertificateContextToStore failed: %08x\n",
303 GetLastError());
304 /* use the existing certificate and ask for a copy of the context*/
305 copyContext = NULL;
306 ret = CertAddCertificateContextToStore(collection, context,
307 CERT_STORE_ADD_USE_EXISTING, &copyContext);
308 ok(ret, "CertAddCertificateContextToStore failed: %08x\n",
309 GetLastError());
310 ok(copyContext != NULL, "Expected on output a non NULL copyContext\n");
311 if (copyContext)
312 CertFreeCertificateContext(copyContext);
313 /* but adding a new certificate isn't allowed. */
314 ret = CertAddCertificateContextToStore(collection, context,
315 CERT_STORE_ADD_ALWAYS, NULL);
316 ok(!ret && GetLastError() == E_ACCESSDENIED,
317 "Expected E_ACCESSDENIED, got %08x\n", GetLastError());
318 CertFreeCertificateContext(context);
319 }
320
321 CertCloseStore(collection, 0);
322 }
323
324 CertCloseStore(store, 0);
325 }
326
327 static void checkHash(const BYTE *data, DWORD dataLen, ALG_ID algID,
328 PCCERT_CONTEXT context, DWORD propID)
329 {
330 BYTE hash[20] = { 0 }, hashProperty[20];
331 BOOL ret;
332 DWORD size;
333 DWORD dwSizeWithNull;
334
335 memset(hash, 0, sizeof(hash));
336 memset(hashProperty, 0, sizeof(hashProperty));
337 size = sizeof(hash);
338 ret = CryptHashCertificate(0, algID, 0, data, dataLen, hash, &size);
339 ok(ret, "CryptHashCertificate failed: %08x\n", GetLastError());
340 ret = CertGetCertificateContextProperty(context, propID, NULL,
341 &dwSizeWithNull);
342 ok(ret, "algID %08x, propID %d: CertGetCertificateContextProperty failed: %08x\n",
343 algID, propID, GetLastError());
344 ret = CertGetCertificateContextProperty(context, propID, hashProperty,
345 &size);
346 ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
347 GetLastError());
348 ok(!memcmp(hash, hashProperty, size), "Unexpected hash for property %d\n",
349 propID);
350 ok(size == dwSizeWithNull, "Unexpected length of hash for property: received %d instead of %d\n",
351 dwSizeWithNull,size);
352 }
353
354 static const CHAR cspNameA[] = "WineCryptTemp";
355 static WCHAR cspNameW[] = { 'W','i','n','e','C','r','y','p','t','T','e','m','p',0 };
356 static const BYTE v1CertWithPubKey[] = {
357 0x30,0x81,0x95,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
358 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
359 0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,
360 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
361 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,
362 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
363 0x67,0x00,0x30,0x22,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
364 0x01,0x01,0x05,0x00,0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
365 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0xa3,0x16,0x30,0x14,0x30,0x12,0x06,
366 0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,
367 0x01,0x01 };
368 static const BYTE v1CertWithSubjectKeyId[] = {
369 0x30,0x7b,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,0x11,
370 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
371 0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
372 0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
373 0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,
374 0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,
375 0x00,0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00,0xa3,0x17,0x30,0x15,0x30,
376 0x13,0x06,0x03,0x55,0x1d,0x0e,0x04,0x0c,0x04,0x0a,0x4a,0x75,0x61,0x6e,0x20,
377 0x4c,0x61,0x6e,0x67,0x00 };
378 static const BYTE subjectKeyId[] = {
379 0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
380 static const BYTE selfSignedCert[] = {
381 0x30, 0x82, 0x01, 0x1f, 0x30, 0x81, 0xce, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02,
382 0x10, 0xeb, 0x0d, 0x57, 0x2a, 0x9c, 0x09, 0xba, 0xa4, 0x4a, 0xb7, 0x25, 0x49,
383 0xd9, 0x3e, 0xb5, 0x73, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1d,
384 0x05, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03,
385 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30,
386 0x1e, 0x17, 0x0d, 0x30, 0x36, 0x30, 0x36, 0x32, 0x39, 0x30, 0x35, 0x30, 0x30,
387 0x34, 0x36, 0x5a, 0x17, 0x0d, 0x30, 0x37, 0x30, 0x36, 0x32, 0x39, 0x31, 0x31,
388 0x30, 0x30, 0x34, 0x36, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03,
389 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e,
390 0x67, 0x00, 0x30, 0x5c, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
391 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x4b, 0x00, 0x30, 0x48, 0x02, 0x41,
392 0x00, 0xe2, 0x54, 0x3a, 0xa7, 0x83, 0xb1, 0x27, 0x14, 0x3e, 0x59, 0xbb, 0xb4,
393 0x53, 0xe6, 0x1f, 0xe7, 0x5d, 0xf1, 0x21, 0x68, 0xad, 0x85, 0x53, 0xdb, 0x6b,
394 0x1e, 0xeb, 0x65, 0x97, 0x03, 0x86, 0x60, 0xde, 0xf3, 0x6c, 0x38, 0x75, 0xe0,
395 0x4c, 0x61, 0xbb, 0xbc, 0x62, 0x17, 0xa9, 0xcd, 0x79, 0x3f, 0x21, 0x4e, 0x96,
396 0xcb, 0x0e, 0xdc, 0x61, 0x94, 0x30, 0x18, 0x10, 0x6b, 0xd0, 0x1c, 0x10, 0x79,
397 0x02, 0x03, 0x01, 0x00, 0x01, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02,
398 0x1d, 0x05, 0x00, 0x03, 0x41, 0x00, 0x25, 0x90, 0x53, 0x34, 0xd9, 0x56, 0x41,
399 0x5e, 0xdb, 0x7e, 0x01, 0x36, 0xec, 0x27, 0x61, 0x5e, 0xb7, 0x4d, 0x90, 0x66,
400 0xa2, 0xe1, 0x9d, 0x58, 0x76, 0xd4, 0x9c, 0xba, 0x2c, 0x84, 0xc6, 0x83, 0x7a,
401 0x22, 0x0d, 0x03, 0x69, 0x32, 0x1a, 0x6d, 0xcb, 0x0c, 0x15, 0xb3, 0x6b, 0xc7,
402 0x0a, 0x8c, 0xb4, 0x5c, 0x34, 0x78, 0xe0, 0x3c, 0x9c, 0xe9, 0xf3, 0x30, 0x9f,
403 0xa8, 0x76, 0x57, 0x92, 0x36 };
404 static const BYTE selfSignedSignatureHash[] = { 0x07,0x5a,0x3e,0xfd,0x0d,0xf6,
405 0x88,0xeb,0x00,0x64,0xbd,0xc9,0xd6,0xea,0x0a,0x7c,0xcc,0x24,0xdb,0x5d };
406
407 static void testCertProperties(void)
408 {
409 PCCERT_CONTEXT context = CertCreateCertificateContext(X509_ASN_ENCODING,
410 bigCert, sizeof(bigCert));
411 DWORD propID, numProps, access, size;
412 BOOL ret;
413 BYTE hash[20] = { 0 }, hashProperty[20];
414 CRYPT_DATA_BLOB blob;
415 CERT_KEY_CONTEXT keyContext;
416
417 ok(context != NULL || broken(GetLastError() == OSS_DATA_ERROR /* win98 */),
418 "CertCreateCertificateContext failed: %08x\n", GetLastError());
419 if (!context)
420 return;
421
422 /* This crashes
423 propID = CertEnumCertificateContextProperties(NULL, 0);
424 */
425
426 propID = 0;
427 numProps = 0;
428 do {
429 propID = CertEnumCertificateContextProperties(context, propID);
430 if (propID)
431 numProps++;
432 } while (propID != 0);
433 ok(numProps == 0, "Expected 0 properties, got %d\n", numProps);
434
435 /* Tests with a NULL cert context. Prop ID 0 fails.. */
436 ret = CertSetCertificateContextProperty(NULL, 0, 0, NULL);
437 ok(!ret && GetLastError() == E_INVALIDARG,
438 "Expected E_INVALIDARG, got %08x\n", GetLastError());
439 /* while this just crashes.
440 ret = CertSetCertificateContextProperty(NULL,
441 CERT_KEY_PROV_HANDLE_PROP_ID, 0, NULL);
442 */
443
444 ret = CertSetCertificateContextProperty(context, 0, 0, NULL);
445 ok(!ret && GetLastError() == E_INVALIDARG,
446 "Expected E_INVALIDARG, got %08x\n", GetLastError());
447 /* Can't set the cert property directly, this crashes.
448 ret = CertSetCertificateContextProperty(context,
449 CERT_CERT_PROP_ID, 0, bigCert2);
450 */
451
452 /* These all crash.
453 ret = CertGetCertificateContextProperty(context,
454 CERT_ACCESS_STATE_PROP_ID, 0, NULL);
455 ret = CertGetCertificateContextProperty(context, CERT_HASH_PROP_ID,
456 NULL, NULL);
457 ret = CertGetCertificateContextProperty(context, CERT_HASH_PROP_ID,
458 hashProperty, NULL);
459 */
460 /* A missing prop */
461 size = 0;
462 ret = CertGetCertificateContextProperty(context,
463 CERT_KEY_PROV_INFO_PROP_ID, NULL, &size);
464 ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
465 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
466 /* And, an implicit property */
467 size = sizeof(access);
468 ret = CertGetCertificateContextProperty(context,
469 CERT_ACCESS_STATE_PROP_ID, &access, &size);
470 ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
471 GetLastError());
472 ok(!(access & CERT_ACCESS_STATE_WRITE_PERSIST_FLAG),
473 "Didn't expect a persisted cert\n");
474 /* Trying to set this "read only" property crashes.
475 access |= CERT_ACCESS_STATE_WRITE_PERSIST_FLAG;
476 ret = CertSetCertificateContextProperty(context,
477 CERT_ACCESS_STATE_PROP_ID, 0, &access);
478 */
479
480 /* Can I set the hash to an invalid hash? */
481 blob.pbData = hash;
482 blob.cbData = sizeof(hash);
483 ret = CertSetCertificateContextProperty(context, CERT_HASH_PROP_ID, 0,
484 &blob);
485 ok(ret, "CertSetCertificateContextProperty failed: %08x\n",
486 GetLastError());
487 size = sizeof(hashProperty);
488 ret = CertGetCertificateContextProperty(context, CERT_HASH_PROP_ID,
489 hashProperty, &size);
490 ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
491 GetLastError());
492 ok(!memcmp(hashProperty, hash, sizeof(hash)), "Unexpected hash\n");
493 /* Delete the (bogus) hash, and get the real one */
494 ret = CertSetCertificateContextProperty(context, CERT_HASH_PROP_ID, 0,
495 NULL);
496 ok(ret, "CertSetCertificateContextProperty failed: %08x\n",
497 GetLastError());
498 checkHash(bigCert, sizeof(bigCert), CALG_SHA1, context,
499 CERT_HASH_PROP_ID);
500
501 /* Now that the hash property is set, we should get one property when
502 * enumerating.
503 */
504 propID = 0;
505 numProps = 0;
506 do {
507 propID = CertEnumCertificateContextProperties(context, propID);
508 if (propID)
509 numProps++;
510 } while (propID != 0);
511 ok(numProps == 1, "Expected 1 properties, got %d\n", numProps);
512
513 /* Check a few other implicit properties */
514 checkHash(bigCert, sizeof(bigCert), CALG_MD5, context,
515 CERT_MD5_HASH_PROP_ID);
516
517 /* Getting the signature hash fails with this bogus certificate */
518 size = 0;
519 ret = CertGetCertificateContextProperty(context,
520 CERT_SIGNATURE_HASH_PROP_ID, NULL, &size);
521 ok(!ret &&
522 (GetLastError() == CRYPT_E_ASN1_BADTAG ||
523 GetLastError() == CRYPT_E_NOT_FOUND ||
524 GetLastError() == OSS_DATA_ERROR), /* win9x */
525 "Expected CRYPT_E_ASN1_BADTAG, got %08x\n", GetLastError());
526
527 /* Test key contexts and handles and such */
528 size = 0;
529 ret = CertGetCertificateContextProperty(context, CERT_KEY_CONTEXT_PROP_ID,
530 NULL, &size);
531 ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
532 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
533 size = sizeof(CERT_KEY_CONTEXT);
534 ret = CertGetCertificateContextProperty(context, CERT_KEY_CONTEXT_PROP_ID,
535 NULL, &size);
536 ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
537 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
538 ret = CertGetCertificateContextProperty(context, CERT_KEY_CONTEXT_PROP_ID,
539 &keyContext, &size);
540 ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
541 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
542 /* Key context with an invalid size */
543 keyContext.cbSize = 0;
544 ret = CertSetCertificateContextProperty(context, CERT_KEY_CONTEXT_PROP_ID,
545 0, &keyContext);
546 ok(!ret && GetLastError() == E_INVALIDARG,
547 "Expected E_INVALIDARG, got %08x\n", GetLastError());
548 size = sizeof(keyContext);
549 ret = CertGetCertificateContextProperty(context, CERT_KEY_CONTEXT_PROP_ID,
550 &keyContext, &size);
551 ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
552 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
553 keyContext.cbSize = sizeof(keyContext);
554 keyContext.hCryptProv = 0;
555 keyContext.dwKeySpec = AT_SIGNATURE;
556 ret = CertSetCertificateContextProperty(context, CERT_KEY_CONTEXT_PROP_ID,
557 0, &keyContext);
558 ok(ret, "CertSetCertificateContextProperty failed: %08x\n", GetLastError());
559 /* Now that that's set, the key prov handle property is also gettable.
560 */
561 size = sizeof(keyContext.hCryptProv);
562 ret = CertGetCertificateContextProperty(context,
563 CERT_KEY_PROV_HANDLE_PROP_ID, &keyContext.hCryptProv, &size);
564 ok(ret, "Expected to get the CERT_KEY_PROV_HANDLE_PROP_ID, got %08x\n",
565 GetLastError());
566 /* Remove the key prov handle property.. */
567 ret = CertSetCertificateContextProperty(context,
568 CERT_KEY_PROV_HANDLE_PROP_ID, 0, NULL);
569 ok(ret, "CertSetCertificateContextProperty failed: %08x\n",
570 GetLastError());
571 /* and the key context's CSP is set to NULL. */
572 size = sizeof(keyContext);
573 ret = CertGetCertificateContextProperty(context,
574 CERT_KEY_CONTEXT_PROP_ID, &keyContext, &size);
575 ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
576 GetLastError());
577 ok(keyContext.hCryptProv == 0, "Expected no hCryptProv\n");
578
579 /* According to MSDN the subject key id can be stored as a property,
580 * as a subject key extension, or as the SHA1 hash of the public key,
581 * but this cert has none of them:
582 */
583 ret = CertGetCertificateContextProperty(context,
584 CERT_KEY_IDENTIFIER_PROP_ID, NULL, &size);
585 ok(!ret && GetLastError() == ERROR_INVALID_DATA,
586 "Expected ERROR_INVALID_DATA, got %08x\n", GetLastError());
587 CertFreeCertificateContext(context);
588 /* This cert does have a public key, but its subject key identifier still
589 * isn't available: */
590 context = CertCreateCertificateContext(X509_ASN_ENCODING,
591 v1CertWithPubKey, sizeof(v1CertWithPubKey));
592 ret = CertGetCertificateContextProperty(context,
593 CERT_KEY_IDENTIFIER_PROP_ID, NULL, &size);
594 ok(!ret && GetLastError() == ERROR_INVALID_DATA,
595 "Expected ERROR_INVALID_DATA, got %08x\n", GetLastError());
596 CertFreeCertificateContext(context);
597 /* This cert with a subject key extension can have its key identifier
598 * property retrieved:
599 */
600 context = CertCreateCertificateContext(X509_ASN_ENCODING,
601 v1CertWithSubjectKeyId, sizeof(v1CertWithSubjectKeyId));
602 ret = CertGetCertificateContextProperty(context,
603 CERT_KEY_IDENTIFIER_PROP_ID, NULL, &size);
604 ok(ret, "CertGetCertificateContextProperty failed: %08x\n", GetLastError());
605 if (ret)
606 {
607 LPBYTE buf = HeapAlloc(GetProcessHeap(), 0, size);
608
609 if (buf)
610 {
611 ret = CertGetCertificateContextProperty(context,
612 CERT_KEY_IDENTIFIER_PROP_ID, buf, &size);
613 ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
614 GetLastError());
615 ok(!memcmp(buf, subjectKeyId, size), "Unexpected subject key id\n");
616 HeapFree(GetProcessHeap(), 0, buf);
617 }
618 }
619 CertFreeCertificateContext(context);
620
621 context = CertCreateCertificateContext(X509_ASN_ENCODING,
622 selfSignedCert, sizeof(selfSignedCert));
623 /* Getting the signature hash of a valid (self-signed) cert succeeds */
624 size = 0;
625 ret = CertGetCertificateContextProperty(context,
626 CERT_SIGNATURE_HASH_PROP_ID, NULL, &size);
627 ok(ret, "CertGetCertificateContextProperty failed: %08x\n", GetLastError());
628 ok(size == sizeof(selfSignedSignatureHash), "unexpected size %d\n", size);
629 ret = CertGetCertificateContextProperty(context,
630 CERT_SIGNATURE_HASH_PROP_ID, hashProperty, &size);
631 if (ret)
632 ok(!memcmp(hashProperty, selfSignedSignatureHash, size),
633 "unexpected value\n");
634 CertFreeCertificateContext(context);
635 }
636
637 static void testCreateCert(void)
638 {
639 PCCERT_CONTEXT cert, enumCert;
640 DWORD count, size;
641 BOOL ret;
642
643 SetLastError(0xdeadbeef);
644 cert = CertCreateCertificateContext(0, NULL, 0);
645 ok(!cert && GetLastError() == E_INVALIDARG,
646 "expected E_INVALIDARG, got %08x\n", GetLastError());
647 SetLastError(0xdeadbeef);
648 cert = CertCreateCertificateContext(0, selfSignedCert,
649 sizeof(selfSignedCert));
650 ok(!cert && GetLastError() == E_INVALIDARG,
651 "expected E_INVALIDARG, got %08x\n", GetLastError());
652 SetLastError(0xdeadbeef);
653 cert = CertCreateCertificateContext(X509_ASN_ENCODING, NULL, 0);
654 ok(!cert &&
655 (GetLastError() == CRYPT_E_ASN1_EOD ||
656 broken(GetLastError() == OSS_MORE_INPUT /* NT4 */)),
657 "expected CRYPT_E_ASN1_EOD, got %08x\n", GetLastError());
658
659 cert = CertCreateCertificateContext(X509_ASN_ENCODING,
660 selfSignedCert, sizeof(selfSignedCert));
661 ok(cert != NULL, "creating cert failed: %08x\n", GetLastError());
662 /* Even in-memory certs are expected to have a store associated with them */
663 ok(cert->hCertStore != NULL, "expected created cert to have a store\n");
664 /* The cert doesn't have the archived property set (which would imply it
665 * doesn't show up in enumerations.)
666 */
667 size = 0;
668 ret = CertGetCertificateContextProperty(cert, CERT_ARCHIVED_PROP_ID,
669 NULL, &size);
670 ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
671 "expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
672 /* Strangely, enumerating the certs in the store finds none. */
673 enumCert = NULL;
674 count = 0;
675 while ((enumCert = CertEnumCertificatesInStore(cert->hCertStore, enumCert)))
676 count++;
677 ok(!count, "expected 0, got %d\n", count);
678 CertFreeCertificateContext(cert);
679 }
680
681 static void testDupCert(void)
682 {
683 PCCERT_CONTEXT context, dupContext, storeContext, storeContext2, context2;
684 HCERTSTORE store, store2;
685 BOOL ret;
686
687 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
688 CERT_STORE_CREATE_NEW_FLAG, NULL);
689 ok(store != NULL, "CertOpenStore failed: %d\n", GetLastError());
690 if (!store)
691 return;
692
693 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
694 bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, &context);
695 ok(ret || broken(GetLastError() == OSS_DATA_ERROR /* win98 */),
696 "CertAddEncodedCertificateToStore failed: %08x\n", GetLastError());
697 if (!ret && GetLastError() == OSS_DATA_ERROR)
698 {
699 skip("bigCert can't be decoded, skipping tests\n");
700 return;
701 }
702 ok(context != NULL, "Expected a valid cert context\n");
703 if (context)
704 {
705 ok(context->cbCertEncoded == sizeof(bigCert),
706 "Wrong cert size %d\n", context->cbCertEncoded);
707 ok(!memcmp(context->pbCertEncoded, bigCert, sizeof(bigCert)),
708 "Unexpected encoded cert in context\n");
709 ok(context->hCertStore == store, "Unexpected store\n");
710
711 dupContext = CertDuplicateCertificateContext(context);
712 ok(dupContext != NULL, "Expected valid duplicate\n");
713 /* Not only is it a duplicate, it's identical: the address is the
714 * same.
715 */
716 ok(dupContext == context, "Expected identical context addresses\n");
717 CertFreeCertificateContext(dupContext);
718 CertFreeCertificateContext(context);
719 }
720 CertCloseStore(store, 0);
721
722 context = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert, sizeof(bigCert));
723 ok(context != NULL, "CertCreateCertificateContext failed\n");
724
725 dupContext = CertDuplicateCertificateContext(context);
726 ok(dupContext == context, "context != dupContext\n");
727
728 ret = CertFreeCertificateContext(dupContext);
729 ok(ret, "CertFreeCertificateContext failed\n");
730
731 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0, CERT_STORE_CREATE_NEW_FLAG, NULL);
732 ok(store != NULL, "CertOpenStore failed: %d\n", GetLastError());
733
734 ret = CertAddCertificateContextToStore(store, context, CERT_STORE_ADD_NEW, &storeContext);
735 ok(ret, "CertAddCertificateContextToStore failed\n");
736 ok(storeContext != NULL && storeContext != context, "unexpected storeContext\n");
737 ok(storeContext->hCertStore == store, "unexpected hCertStore\n");
738
739 ok(storeContext->pbCertEncoded != context->pbCertEncoded, "unexpected pbCertEncoded\n");
740 ok(storeContext->cbCertEncoded == context->cbCertEncoded, "unexpected cbCertEncoded\n");
741 ok(storeContext->pCertInfo != context->pCertInfo, "unexpected pCertInfo\n");
742
743 store2 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0, CERT_STORE_CREATE_NEW_FLAG, NULL);
744 ok(store2 != NULL, "CertOpenStore failed: %d\n", GetLastError());
745
746 ret = CertAddCertificateContextToStore(store2, storeContext, CERT_STORE_ADD_NEW, &storeContext2);
747 ok(ret, "CertAddCertificateContextToStore failed\n");
748 ok(storeContext2 != NULL && storeContext2 != storeContext, "unexpected storeContext\n");
749 ok(storeContext2->hCertStore == store2, "unexpected hCertStore\n");
750
751 ok(storeContext2->pbCertEncoded != storeContext->pbCertEncoded, "unexpected pbCertEncoded\n");
752 ok(storeContext2->cbCertEncoded == storeContext->cbCertEncoded, "unexpected cbCertEncoded\n");
753 ok(storeContext2->pCertInfo != storeContext->pCertInfo, "unexpected pCertInfo\n");
754
755 CertFreeCertificateContext(storeContext2);
756 CertFreeCertificateContext(storeContext);
757
758 context2 = CertCreateCertificateContext(X509_ASN_ENCODING, certWithUsage, sizeof(certWithUsage));
759 ok(context2 != NULL, "CertCreateCertificateContext failed\n");
760
761 ok(context2->hCertStore == context->hCertStore, "Unexpected hCertStore\n");
762
763 CertFreeCertificateContext(context2);
764 ret = CertFreeCertificateContext(context);
765 ok(ret, "CertFreeCertificateContext failed\n");
766
767 CertCloseStore(store, 0);
768 CertCloseStore(store2, 0);
769
770 SetLastError(0xdeadbeef);
771 context = CertDuplicateCertificateContext(NULL);
772 ok(context == NULL, "Expected context to be NULL\n");
773
774 ret = CertFreeCertificateContext(NULL);
775 ok(ret, "CertFreeCertificateContext failed\n");
776 }
777
778 static void testLinkCert(void)
779 {
780 const CERT_CONTEXT *context, *link;
781 HCERTSTORE store;
782 BOOL ret;
783
784 context = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert, sizeof(bigCert));
785 ok(context != NULL, "CertCreateCertificateContext failed\n");
786
787 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0, CERT_STORE_CREATE_NEW_FLAG, NULL);
788 ok(store != NULL, "CertOpenStore failed: %d\n", GetLastError());
789
790 ret = CertAddCertificateLinkToStore(store, context, CERT_STORE_ADD_NEW, &link);
791 ok(ret, "CertAddCertificateContextToStore failed\n");
792 ok(link != NULL && link != context, "unexpected storeContext\n");
793 ok(link->hCertStore == store, "unexpected hCertStore\n");
794
795 ok(link->pbCertEncoded == context->pbCertEncoded, "unexpected pbCertEncoded\n");
796 ok(link->cbCertEncoded == context->cbCertEncoded, "unexpected cbCertEncoded\n");
797 ok(link->pCertInfo == context->pCertInfo, "unexpected pCertInfo\n");
798
799 CertFreeCertificateContext(link);
800 CertFreeCertificateContext(context);
801 CertCloseStore(store, 0);
802 }
803
804 static BYTE subjectName3[] = { 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06,
805 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x52, 0x6f, 0x62, 0x20, 0x20, 0x4c, 0x61,
806 0x6e, 0x67, 0x00 };
807 static const BYTE iTunesCert0[] = {
808 0x30,0x82,0x03,0xc4,0x30,0x82,0x03,0x2d,0xa0,0x03,0x02,0x01,0x02,0x02,0x10,
809 0x47,0xbf,0x19,0x95,0xdf,0x8d,0x52,0x46,0x43,0xf7,0xdb,0x6d,0x48,0x0d,0x31,
810 0xa4,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x05,0x05,
811 0x00,0x30,0x81,0x8b,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,
812 0x5a,0x41,0x31,0x15,0x30,0x13,0x06,0x03,0x55,0x04,0x08,0x13,0x0c,0x57,0x65,
813 0x73,0x74,0x65,0x72,0x6e,0x20,0x43,0x61,0x70,0x65,0x31,0x14,0x30,0x12,0x06,
814 0x03,0x55,0x04,0x07,0x13,0x0b,0x44,0x75,0x72,0x62,0x61,0x6e,0x76,0x69,0x6c,
815 0x6c,0x65,0x31,0x0f,0x30,0x0d,0x06,0x03,0x55,0x04,0x0a,0x13,0x06,0x54,0x68,
816 0x61,0x77,0x74,0x65,0x31,0x1d,0x30,0x1b,0x06,0x03,0x55,0x04,0x0b,0x13,0x14,
817 0x54,0x68,0x61,0x77,0x74,0x65,0x20,0x43,0x65,0x72,0x74,0x69,0x66,0x69,0x63,
818 0x61,0x74,0x69,0x6f,0x6e,0x31,0x1f,0x30,0x1d,0x06,0x03,0x55,0x04,0x03,0x13,
819 0x16,0x54,0x68,0x61,0x77,0x74,0x65,0x20,0x54,0x69,0x6d,0x65,0x73,0x74,0x61,
820 0x6d,0x70,0x69,0x6e,0x67,0x20,0x43,0x41,0x30,0x1e,0x17,0x0d,0x30,0x33,0x31,
821 0x32,0x30,0x34,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x17,0x0d,0x31,0x33,0x31,
822 0x32,0x30,0x33,0x32,0x33,0x35,0x39,0x35,0x39,0x5a,0x30,0x53,0x31,0x0b,0x30,
823 0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x17,0x30,0x15,0x06,
824 0x03,0x55,0x04,0x0a,0x13,0x0e,0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6e,0x2c,
825 0x20,0x49,0x6e,0x63,0x2e,0x31,0x2b,0x30,0x29,0x06,0x03,0x55,0x04,0x03,0x13,
826 0x22,0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6e,0x20,0x54,0x69,0x6d,0x65,0x20,
827 0x53,0x74,0x61,0x6d,0x70,0x69,0x6e,0x67,0x20,0x53,0x65,0x72,0x76,0x69,0x63,
828 0x65,0x73,0x20,0x43,0x41,0x30,0x82,0x01,0x22,0x30,0x0d,0x06,0x09,0x2a,0x86,
829 0x48,0x86,0xf7,0x0d,0x01,0x01,0x01,0x05,0x00,0x03,0x82,0x01,0x0f,0x00,0x30,
830 0x82,0x01,0x0a,0x02,0x82,0x01,0x01,0x00,0xa9,0xca,0xb2,0xa4,0xcc,0xcd,0x20,
831 0xaf,0x0a,0x7d,0x89,0xac,0x87,0x75,0xf0,0xb4,0x4e,0xf1,0xdf,0xc1,0x0f,0xbf,
832 0x67,0x61,0xbd,0xa3,0x64,0x1c,0xda,0xbb,0xf9,0xca,0x33,0xab,0x84,0x30,0x89,
833 0x58,0x7e,0x8c,0xdb,0x6b,0xdd,0x36,0x9e,0x0f,0xbf,0xd1,0xec,0x78,0xf2,0x77,
834 0xa6,0x7e,0x6f,0x3c,0xbf,0x93,0xaf,0x0d,0xba,0x68,0xf4,0x6c,0x94,0xca,0xbd,
835 0x52,0x2d,0xab,0x48,0x3d,0xf5,0xb6,0xd5,0x5d,0x5f,0x1b,0x02,0x9f,0xfa,0x2f,
836 0x6b,0x1e,0xa4,0xf7,0xa3,0x9a,0xa6,0x1a,0xc8,0x02,0xe1,0x7f,0x4c,0x52,0xe3,
837 0x0e,0x60,0xec,0x40,0x1c,0x7e,0xb9,0x0d,0xde,0x3f,0xc7,0xb4,0xdf,0x87,0xbd,
838 0x5f,0x7a,0x6a,0x31,0x2e,0x03,0x99,0x81,0x13,0xa8,0x47,0x20,0xce,0x31,0x73,
839 0x0d,0x57,0x2d,0xcd,0x78,0x34,0x33,0x95,0x12,0x99,0x12,0xb9,0xde,0x68,0x2f,
840 0xaa,0xe6,0xe3,0xc2,0x8a,0x8c,0x2a,0xc3,0x8b,0x21,0x87,0x66,0xbd,0x83,0x58,
841 0x57,0x6f,0x75,0xbf,0x3c,0xaa,0x26,0x87,0x5d,0xca,0x10,0x15,0x3c,0x9f,0x84,
842 0xea,0x54,0xc1,0x0a,0x6e,0xc4,0xfe,0xc5,0x4a,0xdd,0xb9,0x07,0x11,0x97,0x22,
843 0x7c,0xdb,0x3e,0x27,0xd1,0x1e,0x78,0xec,0x9f,0x31,0xc9,0xf1,0xe6,0x22,0x19,
844 0xdb,0xc4,0xb3,0x47,0x43,0x9a,0x1a,0x5f,0xa0,0x1e,0x90,0xe4,0x5e,0xf5,0xee,
845 0x7c,0xf1,0x7d,0xab,0x62,0x01,0x8f,0xf5,0x4d,0x0b,0xde,0xd0,0x22,0x56,0xa8,
846 0x95,0xcd,0xae,0x88,0x76,0xae,0xee,0xba,0x0d,0xf3,0xe4,0x4d,0xd9,0xa0,0xfb,
847 0x68,0xa0,0xae,0x14,0x3b,0xb3,0x87,0xc1,0xbb,0x02,0x03,0x01,0x00,0x01,0xa3,
848 0x81,0xdb,0x30,0x81,0xd8,0x30,0x34,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,
849 0x01,0x01,0x04,0x28,0x30,0x26,0x30,0x24,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,
850 0x07,0x30,0x01,0x86,0x18,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x6f,0x63,0x73,
851 0x70,0x2e,0x76,0x65,0x72,0x69,0x73,0x69,0x67,0x6e,0x2e,0x63,0x6f,0x6d,0x30,
852 0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,
853 0xff,0x02,0x01,0x00,0x30,0x41,0x06,0x03,0x55,0x1d,0x1f,0x04,0x3a,0x30,0x38,
854 0x30,0x36,0xa0,0x34,0xa0,0x32,0x86,0x30,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,
855 0x63,0x72,0x6c,0x2e,0x76,0x65,0x72,0x69,0x73,0x69,0x67,0x6e,0x2e,0x63,0x6f,
856 0x6d,0x2f,0x54,0x68,0x61,0x77,0x74,0x65,0x54,0x69,0x6d,0x65,0x73,0x74,0x61,
857 0x6d,0x70,0x69,0x6e,0x67,0x43,0x41,0x2e,0x63,0x72,0x6c,0x30,0x13,0x06,0x03,
858 0x55,0x1d,0x25,0x04,0x0c,0x30,0x0a,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,
859 0x03,0x08,0x30,0x0e,0x06,0x03,0x55,0x1d,0x0f,0x01,0x01,0xff,0x04,0x04,0x03,
860 0x02,0x01,0x06,0x30,0x24,0x06,0x03,0x55,0x1d,0x11,0x04,0x1d,0x30,0x1b,0xa4,
861 0x19,0x30,0x17,0x31,0x15,0x30,0x13,0x06,0x03,0x55,0x04,0x03,0x13,0x0c,0x54,
862 0x53,0x41,0x32,0x30,0x34,0x38,0x2d,0x31,0x2d,0x35,0x33,0x30,0x0d,0x06,0x09,
863 0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x05,0x05,0x00,0x03,0x81,0x81,0x00,
864 0x4a,0x6b,0xf9,0xea,0x58,0xc2,0x44,0x1c,0x31,0x89,0x79,0x99,0x2b,0x96,0xbf,
865 0x82,0xac,0x01,0xd6,0x1c,0x4c,0xcd,0xb0,0x8a,0x58,0x6e,0xdf,0x08,0x29,0xa3,
866 0x5e,0xc8,0xca,0x93,0x13,0xe7,0x04,0x52,0x0d,0xef,0x47,0x27,0x2f,0x00,0x38,
867 0xb0,0xe4,0xc9,0x93,0x4e,0x9a,0xd4,0x22,0x62,0x15,0xf7,0x3f,0x37,0x21,0x4f,
868 0x70,0x31,0x80,0xf1,0x8b,0x38,0x87,0xb3,0xe8,0xe8,0x97,0x00,0xfe,0xcf,0x55,
869 0x96,0x4e,0x24,0xd2,0xa9,0x27,0x4e,0x7a,0xae,0xb7,0x61,0x41,0xf3,0x2a,0xce,
870 0xe7,0xc9,0xd9,0x5e,0xdd,0xbb,0x2b,0x85,0x3e,0xb5,0x9d,0xb5,0xd9,0xe1,0x57,
871 0xff,0xbe,0xb4,0xc5,0x7e,0xf5,0xcf,0x0c,0x9e,0xf0,0x97,0xfe,0x2b,0xd3,0x3b,
872 0x52,0x1b,0x1b,0x38,0x27,0xf7,0x3f,0x4a };
873 static const BYTE iTunesCert1[] = {
874 0x30,0x82,0x03,0xff,0x30,0x82,0x02,0xe7,0xa0,0x03,0x02,0x01,0x02,0x02,0x10,
875 0x0d,0xe9,0x2b,0xf0,0xd4,0xd8,0x29,0x88,0x18,0x32,0x05,0x09,0x5e,0x9a,0x76,
876 0x88,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x05,0x05,
877 0x00,0x30,0x53,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,
878 0x53,0x31,0x17,0x30,0x15,0x06,0x03,0x55,0x04,0x0a,0x13,0x0e,0x56,0x65,0x72,
879 0x69,0x53,0x69,0x67,0x6e,0x2c,0x20,0x49,0x6e,0x63,0x2e,0x31,0x2b,0x30,0x29,
880 0x06,0x03,0x55,0x04,0x03,0x13,0x22,0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6e,
881 0x20,0x54,0x69,0x6d,0x65,0x20,0x53,0x74,0x61,0x6d,0x70,0x69,0x6e,0x67,0x20,
882 0x53,0x65,0x72,0x76,0x69,0x63,0x65,0x73,0x20,0x43,0x41,0x30,0x1e,0x17,0x0d,
883 0x30,0x33,0x31,0x32,0x30,0x34,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x17,0x0d,
884 0x30,0x38,0x31,0x32,0x30,0x33,0x32,0x33,0x35,0x39,0x35,0x39,0x5a,0x30,0x57,
885 0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x17,
886 0x30,0x15,0x06,0x03,0x55,0x04,0x0a,0x13,0x0e,0x56,0x65,0x72,0x69,0x53,0x69,
887 0x67,0x6e,0x2c,0x20,0x49,0x6e,0x63,0x2e,0x31,0x2f,0x30,0x2d,0x06,0x03,0x55,
888 0x04,0x03,0x13,0x26,0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6e,0x20,0x54,0x69,
889 0x6d,0x65,0x20,0x53,0x74,0x61,0x6d,0x70,0x69,0x6e,0x67,0x20,0x53,0x65,0x72,
890 0x76,0x69,0x63,0x65,0x73,0x20,0x53,0x69,0x67,0x6e,0x65,0x72,0x30,0x82,0x01,
891 0x22,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x01,0x05,
892 0x00,0x03,0x82,0x01,0x0f,0x00,0x30,0x82,0x01,0x0a,0x02,0x82,0x01,0x01,0x00,
893 0xb2,0x50,0x28,0x48,0xdd,0xd3,0x68,0x7a,0x84,0x18,0x44,0x66,0x75,0x5d,0x7e,
894 0xc4,0xb8,0x9f,0x63,0x26,0xff,0x3d,0x43,0x9c,0x7c,0x11,0x38,0x10,0x25,0x55,
895 0x73,0xd9,0x75,0x27,0x69,0xfd,0x4e,0xb9,0x20,0x5c,0xd3,0x0a,0xf9,0xa0,0x1b,
896 0x2a,0xed,0x55,0x56,0x21,0x61,0xd8,0x1e,0xdb,0xe4,0xbc,0x33,0x6b,0xc7,0xef,
897 0xdd,0xa3,0x37,0x65,0x8e,0x1b,0x93,0x0c,0xb6,0x53,0x1e,0x5c,0x7c,0x66,0x35,
898 0x5f,0x05,0x8a,0x45,0xfe,0x76,0x4e,0xdf,0x53,0x80,0xa2,0x81,0x20,0x9d,0xae,
899 0x88,0x5c,0xa2,0x08,0xf7,0xe5,0x30,0xf9,0xee,0x22,0x37,0x4c,0x42,0x0a,0xce,
900 0xdf,0xc6,0x1f,0xc4,0xd6,0x55,0xe9,0x81,0x3f,0xb5,0x52,0xa3,0x2c,0xaa,0x01,
901 0x7a,0xf2,0xa2,0xaa,0x8d,0x35,0xfe,0x9f,0xe6,0x5d,0x6a,0x05,0x9f,0x3d,0x6b,
902 0xe3,0xbf,0x96,0xc0,0xfe,0xcc,0x60,0xf9,0x40,0xe7,0x07,0xa0,0x44,0xeb,0x81,
903 0x51,0x6e,0xa5,0x2a,0xf2,0xb6,0x8a,0x10,0x28,0xed,0x8f,0xdc,0x06,0xa0,0x86,
904 0x50,0x9a,0x7b,0x4a,0x08,0x0d,0x30,0x1d,0xca,0x10,0x9e,0x6b,0xf7,0xe9,0x58,
905 0xae,0x04,0xa9,0x40,0x99,0xb2,0x28,0xe8,0x8f,0x16,0xac,0x3c,0xe3,0x53,0x6f,
906 0x4b,0xd3,0x35,0x9d,0xb5,0x6f,0x64,0x1d,0xb3,0x96,0x2c,0xbb,0x3d,0xe7,0x79,
907 0xeb,0x6d,0x7a,0xf9,0x16,0xe6,0x26,0xad,0xaf,0xef,0x99,0x53,0xb7,0x40,0x2c,
908 0x95,0xb8,0x79,0xaa,0xfe,0xd4,0x52,0xab,0x29,0x74,0x7e,0x42,0xec,0x39,0x1e,
909 0xa2,0x6a,0x16,0xe6,0x59,0xbb,0x24,0x68,0xd8,0x00,0x80,0x43,0x10,0x87,0x80,
910 0x6b,0x02,0x03,0x01,0x00,0x01,0xa3,0x81,0xca,0x30,0x81,0xc7,0x30,0x34,0x06,
911 0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x01,0x01,0x04,0x28,0x30,0x26,0x30,0x24,
912 0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x30,0x01,0x86,0x18,0x68,0x74,0x74,
913 0x70,0x3a,0x2f,0x2f,0x6f,0x63,0x73,0x70,0x2e,0x76,0x65,0x72,0x69,0x73,0x69,
914 0x67,0x6e,0x2e,0x63,0x6f,0x6d,0x30,0x0c,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,
915 0xff,0x04,0x02,0x30,0x00,0x30,0x33,0x06,0x03,0x55,0x1d,0x1f,0x04,0x2c,0x30,
916 0x2a,0x30,0x28,0xa0,0x26,0xa0,0x24,0x86,0x22,0x68,0x74,0x74,0x70,0x3a,0x2f,
917 0x2f,0x63,0x72,0x6c,0x2e,0x76,0x65,0x72,0x69,0x73,0x69,0x67,0x6e,0x2e,0x63,
918 0x6f,0x6d,0x2f,0x74,0x73,0x73,0x2d,0x63,0x61,0x2e,0x63,0x72,0x6c,0x30,0x16,
919 0x06,0x03,0x55,0x1d,0x25,0x01,0x01,0xff,0x04,0x0c,0x30,0x0a,0x06,0x08,0x2b,
920 0x06,0x01,0x05,0x05,0x07,0x03,0x08,0x30,0x0e,0x06,0x03,0x55,0x1d,0x0f,0x01,
921 0x01,0xff,0x04,0x04,0x03,0x02,0x06,0xc0,0x30,0x24,0x06,0x03,0x55,0x1d,0x11,
922 0x04,0x1d,0x30,0x1b,0xa4,0x19,0x30,0x17,0x31,0x15,0x30,0x13,0x06,0x03,0x55,
923 0x04,0x03,0x13,0x0c,0x54,0x53,0x41,0x32,0x30,0x34,0x38,0x2d,0x31,0x2d,0x35,
924 0x34,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x05,0x05,
925 0x00,0x03,0x82,0x01,0x01,0x00,0x87,0x78,0x70,0xda,0x4e,0x52,0x01,0x20,0x5b,
926 0xe0,0x79,0xc9,0x82,0x30,0xc4,0xfd,0xb9,0x19,0x96,0xbd,0x91,0x00,0xc3,0xbd,
927 0xcd,0xcd,0xc6,0xf4,0x0e,0xd8,0xff,0xf9,0x4d,0xc0,0x33,0x62,0x30,0x11,0xc5,
928 0xf5,0x74,0x1b,0xd4,0x92,0xde,0x5f,0x9c,0x20,0x13,0xb1,0x7c,0x45,0xbe,0x50,
929 0xcd,0x83,0xe7,0x80,0x17,0x83,0xa7,0x27,0x93,0x67,0x13,0x46,0xfb,0xca,0xb8,
930 0x98,0x41,0x03,0xcc,0x9b,0x51,0x5b,0x05,0x8b,0x7f,0xa8,0x6f,0xf3,0x1b,0x50,
931 0x1b,0x24,0x2e,0xf2,0x69,0x8d,0x6c,0x22,0xf7,0xbb,0xca,0x16,0x95,0xed,0x0c,
932 0x74,0xc0,0x68,0x77,0xd9,0xeb,0x99,0x62,0x87,0xc1,0x73,0x90,0xf8,0x89,0x74,
933 0x7a,0x23,0xab,0xa3,0x98,0x7b,0x97,0xb1,0xf7,0x8f,0x29,0x71,0x4d,0x2e,0x75,
934 0x1b,0x48,0x41,0xda,0xf0,0xb5,0x0d,0x20,0x54,0xd6,0x77,0xa0,0x97,0x82,0x63,
935 0x69,0xfd,0x09,0xcf,0x8a,0xf0,0x75,0xbb,0x09,0x9b,0xd9,0xf9,0x11,0x55,0x26,
936 0x9a,0x61,0x32,0xbe,0x7a,0x02,0xb0,0x7b,0x86,0xbe,0xa2,0xc3,0x8b,0x22,0x2c,
937 0x78,0xd1,0x35,0x76,0xbc,0x92,0x73,0x5c,0xf9,0xb9,0xe6,0x4c,0x15,0x0a,0x23,
938 0xcc,0xe4,0xd2,0xd4,0x34,0x2e,0x49,0x40,0x15,0x3c,0x0f,0x60,0x7a,0x24,0xc6,
939 0xa5,0x66,0xef,0x96,0xcf,0x70,0xeb,0x3e,0xe7,0xf4,0x0d,0x7e,0xdc,0xd1,0x7c,
940 0xa3,0x76,0x71,0x69,0xc1,0x9c,0x4f,0x47,0x30,0x35,0x21,0xb1,0xa2,0xaf,0x1a,
941 0x62,0x3c,0x2b,0xd9,0x8e,0xaa,0x2a,0x07,0x7b,0xd8,0x18,0xb3,0x5c,0x7b,0xe2,
942 0x9d,0xa5,0x6f,0xfe,0x3c,0x89,0xad };
943 static const BYTE iTunesCert2[] = {
944 0x30,0x82,0x04,0xbf,0x30,0x82,0x04,0x28,0xa0,0x03,0x02,0x01,0x02,0x02,0x10,
945 0x41,0x91,0xa1,0x5a,0x39,0x78,0xdf,0xcf,0x49,0x65,0x66,0x38,0x1d,0x4c,0x75,
946 0xc2,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x05,0x05,
947 0x00,0x30,0x5f,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,
948 0x53,0x31,0x17,0x30,0x15,0x06,0x03,0x55,0x04,0x0a,0x13,0x0e,0x56,0x65,0x72,
949 0x69,0x53,0x69,0x67,0x6e,0x2c,0x20,0x49,0x6e,0x63,0x2e,0x31,0x37,0x30,0x35,
950 0x06,0x03,0x55,0x04,0x0b,0x13,0x2e,0x43,0x6c,0x61,0x73,0x73,0x20,0x33,0x20,
951 0x50,0x75,0x62,0x6c,0x69,0x63,0x20,0x50,0x72,0x69,0x6d,0x61,0x72,0x79,0x20,
952 0x43,0x65,0x72,0x74,0x69,0x66,0x69,0x63,0x61,0x74,0x69,0x6f,0x6e,0x20,0x41,
953 0x75,0x74,0x68,0x6f,0x72,0x69,0x74,0x79,0x30,0x1e,0x17,0x0d,0x30,0x34,0x30,
954 0x37,0x31,0x36,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x17,0x0d,0x31,0x34,0x30,
955 0x37,0x31,0x35,0x32,0x33,0x35,0x39,0x35,0x39,0x5a,0x30,0x81,0xb4,0x31,0x0b,
956 0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x17,0x30,0x15,
957 0x06,0x03,0x55,0x04,0x0a,0x13,0x0e,0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6e,
958 0x2c,0x20,0x49,0x6e,0x63,0x2e,0x31,0x1f,0x30,0x1d,0x06,0x03,0x55,0x04,0x0b,
959 0x13,0x16,0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6e,0x20,0x54,0x72,0x75,0x73,
960 0x74,0x20,0x4e,0x65,0x74,0x77,0x6f,0x72,0x6b,0x31,0x3b,0x30,0x39,0x06,0x03,
961 0x55,0x04,0x0b,0x13,0x32,0x54,0x65,0x72,0x6d,0x73,0x20,0x6f,0x66,0x20,0x75,
962 0x73,0x65,0x20,0x61,0x74,0x20,0x68,0x74,0x74,0x70,0x73,0x3a,0x2f,0x2f,0x77,
963 0x77,0x77,0x2e,0x76,0x65,0x72,0x69,0x73,0x69,0x67,0x6e,0x2e,0x63,0x6f,0x6d,
964 0x2f,0x72,0x70,0x61,0x20,0x28,0x63,0x29,0x30,0x34,0x31,0x2e,0x30,0x2c,0x06,
965 0x03,0x55,0x04,0x03,0x13,0x25,0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6e,0x20,
966 0x43,0x6c,0x61,0x73,0x73,0x20,0x33,0x20,0x43,0x6f,0x64,0x65,0x20,0x53,0x69,
967 0x67,0x6e,0x69,0x6e,0x67,0x20,0x32,0x30,0x30,0x34,0x20,0x43,0x41,0x30,0x82,
968 0x01,0x22,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x01,
969 0x05,0x00,0x03,0x82,0x01,0x0f,0x00,0x30,0x82,0x01,0x0a,0x02,0x82,0x01,0x01,
970 0x00,0xbe,0xbc,0xee,0xbc,0x7e,0xef,0x83,0xeb,0xe0,0x37,0x4f,0xfb,0x03,0x10,
971 0x38,0xbe,0x08,0xd2,0x8c,0x7d,0x9d,0xfa,0x92,0x7f,0x19,0x0c,0xc2,0x6b,0xee,
972 0x42,0x52,0x8c,0xde,0xd3,0x1c,0x48,0x13,0x25,0xea,0xc1,0x63,0x7a,0xf9,0x51,
973 0x65,0xee,0xd3,0xaa,0x3b,0xf5,0xf0,0x94,0x9c,0x2b,0xfb,0xf2,0x66,0xd4,0x24,
974 0xda,0xf7,0xf5,0x9f,0x6e,0x19,0x39,0x36,0xbc,0xd0,0xa3,0x76,0x08,0x1e,0x22,
975 0x27,0x24,0x6c,0x38,0x91,0x27,0xe2,0x84,0x49,0xae,0x1b,0x8a,0xa1,0xfd,0x25,
976 0x82,0x2c,0x10,0x30,0xe8,0x71,0xab,0x28,0xe8,0x77,0x4a,0x51,0xf1,0xec,0xcd,
977 0xf8,0xf0,0x54,0xd4,0x6f,0xc0,0xe3,0x6d,0x0a,0x8f,0xd9,0xd8,0x64,0x8d,0x63,
978 0xb2,0x2d,0x4e,0x27,0xf6,0x85,0x0e,0xfe,0x6d,0xe3,0x29,0x99,0xe2,0x85,0x47,
979 0x7c,0x2d,0x86,0x7f,0xe8,0x57,0x8f,0xad,0x67,0xc2,0x33,0x32,0x91,0x13,0x20,
980 0xfc,0xa9,0x23,0x14,0x9a,0x6d,0xc2,0x84,0x4b,0x76,0x68,0x04,0xd5,0x71,0x2c,
981 0x5d,0x21,0xfa,0x88,0x0d,0x26,0xfd,0x1f,0x2d,0x91,0x2b,0xe7,0x01,0x55,0x4d,
982 0xf2,0x6d,0x35,0x28,0x82,0xdf,0xd9,0x6b,0x5c,0xb6,0xd6,0xd9,0xaa,0x81,0xfd,
983 0x5f,0xcd,0x83,0xba,0x63,0x9d,0xd0,0x22,0xfc,0xa9,0x3b,0x42,0x69,0xb2,0x8e,
984 0x3a,0xb5,0xbc,0xb4,0x9e,0x0f,0x5e,0xc4,0xea,0x2c,0x82,0x8b,0x28,0xfd,0x53,
985 0x08,0x96,0xdd,0xb5,0x01,0x20,0xd1,0xf9,0xa5,0x18,0xe7,0xc0,0xee,0x51,0x70,
986 0x37,0xe1,0xb6,0x05,0x48,0x52,0x48,0x6f,0x38,0xea,0xc3,0xe8,0x6c,0x7b,0x44,
987 0x84,0xbb,0x02,0x03,0x01,0x00,0x01,0xa3,0x82,0x01,0xa0,0x30,0x82,0x01,0x9c,
988 0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,
989 0x01,0xff,0x02,0x01,0x00,0x30,0x44,0x06,0x03,0x55,0x1d,0x20,0x04,0x3d,0x30,
990 0x3b,0x30,0x39,0x06,0x0b,0x60,0x86,0x48,0x01,0x86,0xf8,0x45,0x01,0x07,0x17,
991 0x03,0x30,0x2a,0x30,0x28,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x02,0x01,
992 0x16,0x1c,0x68,0x74,0x74,0x70,0x73,0x3a,0x2f,0x2f,0x77,0x77,0x77,0x2e,0x76,
993 0x65,0x72,0x69,0x73,0x69,0x67,0x6e,0x2e,0x63,0x6f,0x6d,0x2f,0x72,0x70,0x61,
994 0x30,0x31,0x06,0x03,0x55,0x1d,0x1f,0x04,0x2a,0x30,0x28,0x30,0x26,0xa0,0x24,
995 0xa0,0x22,0x86,0x20,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x63,0x72,0x6c,0x2e,
996 0x76,0x65,0x72,0x69,0x73,0x69,0x67,0x6e,0x2e,0x63,0x6f,0x6d,0x2f,0x70,0x63,
997 0x61,0x33,0x2e,0x63,0x72,0x6c,0x30,0x1d,0x06,0x03,0x55,0x1d,0x25,0x04,0x16,
998 0x30,0x14,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x03,0x02,0x06,0x08,0x2b,
999 0x06,0x01,0x05,0x05,0x07,0x03,0x03,0x30,0x0e,0x06,0x03,0x55,0x1d,0x0f,0x01,
1000 0x01,0xff,0x04,0x04,0x03,0x02,0x01,0x06,0x30,0x11,0x06,0x09,0x60,0x86,0x48,
1001 0x01,0x86,0xf8,0x42,0x01,0x01,0x04,0x04,0x03,0x02,0x00,0x01,0x30,0x29,0x06,
1002 0x03,0x55,0x1d,0x11,0x04,0x22,0x30,0x20,0xa4,0x1e,0x30,0x1c,0x31,0x1a,0x30,
1003 0x18,0x06,0x03,0x55,0x04,0x03,0x13,0x11,0x43,0x6c,0x61,0x73,0x73,0x33,0x43,
1004 0x41,0x32,0x30,0x34,0x38,0x2d,0x31,0x2d,0x34,0x33,0x30,0x1d,0x06,0x03,0x55,
1005 0x1d,0x0e,0x04,0x16,0x04,0x14,0x08,0xf5,0x51,0xe8,0xfb,0xfe,0x3d,0x3d,0x64,
1006 0x36,0x7c,0x68,0xcf,0x5b,0x78,0xa8,0xdf,0xb9,0xc5,0x37,0x30,0x81,0x80,0x06,
1007 0x03,0x55,0x1d,0x23,0x04,0x79,0x30,0x77,0xa1,0x63,0xa4,0x61,0x30,0x5f,0x31,
1008 0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x17,0x30,
1009 0x15,0x06,0x03,0x55,0x04,0x0a,0x13,0x0e,0x56,0x65,0x72,0x69,0x53,0x69,0x67,
1010 0x6e,0x2c,0x20,0x49,0x6e,0x63,0x2e,0x31,0x37,0x30,0x35,0x06,0x03,0x55,0x04,
1011 0x0b,0x13,0x2e,0x43,0x6c,0x61,0x73,0x73,0x20,0x33,0x20,0x50,0x75,0x62,0x6c,
1012 0x69,0x63,0x20,0x50,0x72,0x69,0x6d,0x61,0x72,0x79,0x20,0x43,0x65,0x72,0x74,
1013 0x69,0x66,0x69,0x63,0x61,0x74,0x69,0x6f,0x6e,0x20,0x41,0x75,0x74,0x68,0x6f,
1014 0x72,0x69,0x74,0x79,0x82,0x10,0x70,0xba,0xe4,0x1d,0x10,0xd9,0x29,0x34,0xb6,
1015 0x38,0xca,0x7b,0x03,0xcc,0xba,0xbf,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,
1016 0xf7,0x0d,0x01,0x01,0x05,0x05,0x00,0x03,0x81,0x81,0x00,0xae,0x3a,0x17,0xb8,
1017 0x4a,0x7b,0x55,0xfa,0x64,0x55,0xec,0x40,0xa4,0xed,0x49,0x41,0x90,0x99,0x9c,
1018 0x89,0xbc,0xaf,0x2e,0x1d,0xca,0x78,0x23,0xf9,0x1c,0x19,0x0f,0x7f,0xeb,0x68,
1019 0xbc,0x32,0xd9,0x88,0x38,0xde,0xdc,0x3f,0xd3,0x89,0xb4,0x3f,0xb1,0x82,0x96,
1020 0xf1,0xa4,0x5a,0xba,0xed,0x2e,0x26,0xd3,0xde,0x7c,0x01,0x6e,0x00,0x0a,0x00,
1021 0xa4,0x06,0x92,0x11,0x48,0x09,0x40,0xf9,0x1c,0x18,0x79,0x67,0x23,0x24,0xe0,
1022 0xbb,0xd5,0xe1,0x50,0xae,0x1b,0xf5,0x0e,0xdd,0xe0,0x2e,0x81,0xcd,0x80,0xa3,
1023 0x6c,0x52,0x4f,0x91,0x75,0x55,0x8a,0xba,0x22,0xf2,0xd2,0xea,0x41,0x75,0x88,
1024 0x2f,0x63,0x55,0x7d,0x1e,0x54,0x5a,0x95,0x59,0xca,0xd9,0x34,0x81,0xc0,0x5f,
1025 0x5e,0xf6,0x7a,0xb5 };
1026 static const BYTE iTunesCert3[] = {
1027 0x30,0x82,0x04,0xf1,0x30,0x82,0x03,0xd9,0xa0,0x03,0x02,0x01,0x02,0x02,0x10,
1028 0x0f,0x1a,0xa0,0xe0,0x9b,0x9b,0x61,0xa6,0xb6,0xfe,0x40,0xd2,0xdf,0x6a,0xf6,
1029 0x8d,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x05,0x05,
1030 0x00,0x30,0x81,0xb4,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,
1031 0x55,0x53,0x31,0x17,0x30,0x15,0x06,0x03,0x55,0x04,0x0a,0x13,0x0e,0x56,0x65,
1032 0x72,0x69,0x53,0x69,0x67,0x6e,0x2c,0x20,0x49,0x6e,0x63,0x2e,0x31,0x1f,0x30,
1033 0x1d,0x06,0x03,0x55,0x04,0x0b,0x13,0x16,0x56,0x65,0x72,0x69,0x53,0x69,0x67,
1034 0x6e,0x20,0x54,0x72,0x75,0x73,0x74,0x20,0x4e,0x65,0x74,0x77,0x6f,0x72,0x6b,
1035 0x31,0x3b,0x30,0x39,0x06,0x03,0x55,0x04,0x0b,0x13,0x32,0x54,0x65,0x72,0x6d,
1036 0x73,0x20,0x6f,0x66,0x20,0x75,0x73,0x65,0x20,0x61,0x74,0x20,0x68,0x74,0x74,
1037 0x70,0x73,0x3a,0x2f,0x2f,0x77,0x77,0x77,0x2e,0x76,0x65,0x72,0x69,0x73,0x69,
1038 0x67,0x6e,0x2e,0x63,0x6f,0x6d,0x2f,0x72,0x70,0x61,0x20,0x28,0x63,0x29,0x30,
1039 0x34,0x31,0x2e,0x30,0x2c,0x06,0x03,0x55,0x04,0x03,0x13,0x25,0x56,0x65,0x72,
1040 0x69,0x53,0x69,0x67,0x6e,0x20,0x43,0x6c,0x61,0x73,0x73,0x20,0x33,0x20,0x43,
1041 0x6f,0x64,0x65,0x20,0x53,0x69,0x67,0x6e,0x69,0x6e,0x67,0x20,0x32,0x30,0x30,
1042 0x34,0x20,0x43,0x41,0x30,0x1e,0x17,0x0d,0x30,0x36,0x30,0x31,0x31,0x37,0x30,
1043 0x30,0x30,0x30,0x30,0x30,0x5a,0x17,0x0d,0x30,0x38,0x30,0x31,0x32,0x32,0x32,
1044 0x33,0x35,0x39,0x35,0x39,0x5a,0x30,0x81,0xb4,0x31,0x0b,0x30,0x09,0x06,0x03,
1045 0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,
1046 0x08,0x13,0x0a,0x43,0x61,0x6c,0x69,0x66,0x6f,0x72,0x6e,0x69,0x61,0x31,0x12,
1047 0x30,0x10,0x06,0x03,0x55,0x04,0x07,0x13,0x09,0x43,0x75,0x70,0x65,0x72,0x74,
1048 0x69,0x6e,0x6f,0x31,0x1d,0x30,0x1b,0x06,0x03,0x55,0x04,0x0a,0x14,0x14,0x41,
1049 0x70,0x70,0x6c,0x65,0x20,0x43,0x6f,0x6d,0x70,0x75,0x74,0x65,0x72,0x2c,0x20,
1050 0x49,0x6e,0x63,0x2e,0x31,0x3e,0x30,0x3c,0x06,0x03,0x55,0x04,0x0b,0x13,0x35,
1051 0x44,0x69,0x67,0x69,0x74,0x61,0x6c,0x20,0x49,0x44,0x20,0x43,0x6c,0x61,0x73,
1052 0x73,0x20,0x33,0x20,0x2d,0x20,0x4d,0x69,0x63,0x72,0x6f,0x73,0x6f,0x66,0x74,
1053 0x20,0x53,0x6f,0x66,0x74,0x77,0x61,0x72,0x65,0x20,0x56,0x61,0x6c,0x69,0x64,
1054 0x61,0x74,0x69,0x6f,0x6e,0x20,0x76,0x32,0x31,0x1d,0x30,0x1b,0x06,0x03,0x55,
1055 0x04,0x03,0x14,0x14,0x41,0x70,0x70,0x6c,0x65,0x20,0x43,0x6f,0x6d,0x70,0x75,
1056 0x74,0x65,0x72,0x2c,0x20,0x49,0x6e,0x63,0x2e,0x30,0x81,0x9f,0x30,0x0d,0x06,
1057 0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x01,0x05,0x00,0x03,0x81,0x8d,
1058 0x00,0x30,0x81,0x89,0x02,0x81,0x81,0x00,0xd3,0xab,0x3b,0x7f,0xec,0x48,0x84,
1059 0xce,0xa8,0x1a,0x12,0xf3,0x3c,0x87,0xcb,0x24,0x58,0x96,0x02,0x87,0x66,0x49,
1060 0xeb,0x89,0xee,0x79,0x44,0x70,0x8d,0xe7,0xd4,0x1f,0x30,0x92,0xc0,0x9c,0x35,
1061 0x78,0xc0,0xaf,0x1c,0xb6,0x28,0xd3,0xe0,0xe0,0x9d,0xd3,0x49,0x76,0x73,0x57,
1062 0x19,0x4d,0x8d,0x70,0x85,0x64,0x4d,0x1d,0xc6,0x02,0x3e,0xe5,0x2c,0x66,0x07,
1063 0xd2,0x27,0x4b,0xd6,0xc8,0x3c,0x93,0xb6,0x15,0x0c,0xde,0x5b,0xd7,0x93,0xdd,
1064 0xbe,0x85,0x62,0x34,0x17,0x8a,0x05,0x60,0xf0,0x8a,0x1c,0x5a,0x40,0x21,0x8d,
1065 0x51,0x6c,0xb0,0x62,0xd8,0xb5,0xd4,0xf9,0xb1,0xd0,0x58,0x7a,0x7a,0x82,0x55,
1066 0xb3,0xf9,0x53,0x71,0xde,0xd2,0xc9,0x37,0x8c,0xf6,0x5a,0x1f,0x2d,0xcd,0x7c,
1067 0x67,0x02,0x03,0x01,0x00,0x01,0xa3,0x82,0x01,0x7f,0x30,0x82,0x01,0x7b,0x30,
1068 0x09,0x06,0x03,0x55,0x1d,0x13,0x04,0x02,0x30,0x00,0x30,0x0e,0x06,0x03,0x55,
1069 0x1d,0x0f,0x01,0x01,0xff,0x04,0x04,0x03,0x02,0x07,0x80,0x30,0x40,0x06,0x03,
1070 0x55,0x1d,0x1f,0x04,0x39,0x30,0x37,0x30,0x35,0xa0,0x33,0xa0,0x31,0x86,0x2f,
1071 0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x43,0x53,0x43,0x33,0x2d,0x32,0x30,0x30,
1072 0x34,0x2d,0x63,0x72,0x6c,0x2e,0x76,0x65,0x72,0x69,0x73,0x69,0x67,0x6e,0x2e,
1073 0x63,0x6f,0x6d,0x2f,0x43,0x53,0x43,0x33,0x2d,0x32,0x30,0x30,0x34,0x2e,0x63,
1074 0x72,0x6c,0x30,0x44,0x06,0x03,0x55,0x1d,0x20,0x04,0x3d,0x30,0x3b,0x30,0x39,
1075 0x06,0x0b,0x60,0x86,0x48,0x01,0x86,0xf8,0x45,0x01,0x07,0x17,0x03,0x30,0x2a,
1076 0x30,0x28,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x02,0x01,0x16,0x1c,0x68,
1077 0x74,0x74,0x70,0x73,0x3a,0x2f,0x2f,0x77,0x77,0x77,0x2e,0x76,0x65,0x72,0x69,
1078 0x73,0x69,0x67,0x6e,0x2e,0x63,0x6f,0x6d,0x2f,0x72,0x70,0x61,0x30,0x13,0x06,
1079 0x03,0x55,0x1d,0x25,0x04,0x0c,0x30,0x0a,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,
1080 0x07,0x03,0x03,0x30,0x75,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x01,0x01,
1081 0x04,0x69,0x30,0x67,0x30,0x24,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x30,
1082 0x01,0x86,0x18,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x6f,0x63,0x73,0x70,0x2e,
1083 0x76,0x65,0x72,0x69,0x73,0x69,0x67,0x6e,0x2e,0x63,0x6f,0x6d,0x30,0x3f,0x06,
1084 0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x30,0x02,0x86,0x33,0x68,0x74,0x74,0x70,
1085 0x3a,0x2f,0x2f,0x43,0x53,0x43,0x33,0x2d,0x32,0x30,0x30,0x34,0x2d,0x61,0x69,
1086 0x61,0x2e,0x76,0x65,0x72,0x69,0x73,0x69,0x67,0x6e,0x2e,0x63,0x6f,0x6d,0x2f,
1087 0x43,0x53,0x43,0x33,0x2d,0x32,0x30,0x30,0x34,0x2d,0x61,0x69,0x61,0x2e,0x63,
1088 0x65,0x72,0x30,0x1f,0x06,0x03,0x55,0x1d,0x23,0x04,0x18,0x30,0x16,0x80,0x14,
1089 0x08,0xf5,0x51,0xe8,0xfb,0xfe,0x3d,0x3d,0x64,0x36,0x7c,0x68,0xcf,0x5b,0x78,
1090 0xa8,0xdf,0xb9,0xc5,0x37,0x30,0x11,0x06,0x09,0x60,0x86,0x48,0x01,0x86,0xf8,
1091 0x42,0x01,0x01,0x04,0x04,0x03,0x02,0x04,0x10,0x30,0x16,0x06,0x0a,0x2b,0x06,
1092 0x01,0x04,0x01,0x82,0x37,0x02,0x01,0x1b,0x04,0x08,0x30,0x06,0x01,0x01,0x00,
1093 0x01,0x01,0xff,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,
1094 0x05,0x05,0x00,0x03,0x82,0x01,0x01,0x00,0x6a,0xa6,0x06,0xd0,0x33,0x18,0x64,
1095 0xe2,0x69,0x82,0xee,0x6e,0x36,0x9e,0x9d,0x9a,0x0e,0x18,0xa8,0xac,0x9d,0x10,
1096 0xed,0x01,0x3c,0xb9,0x61,0x04,0x62,0xf3,0x85,0x8f,0xcc,0x4f,0x2c,0x66,0x35,
1097 0x54,0x25,0x45,0x8d,0x95,0x1c,0xd2,0x33,0xbe,0x2e,0xdd,0x7f,0x74,0xaf,0x03,
1098 0x7b,0x86,0x63,0xb0,0xc9,0xe6,0xbd,0xc7,0x8e,0xde,0x03,0x18,0x98,0x82,0xc3,
1099 0xbb,0xf8,0x15,0x99,0x1a,0xa9,0xdd,0xb9,0x5d,0xb9,0xbd,0x53,0x95,0x25,0x76,
1100 0xfb,0x5c,0x53,0x90,0xea,0x01,0x0a,0xa0,0xb1,0xbf,0x09,0x1b,0x97,0x8f,0x40,
1101 0xfa,0x85,0x12,0x74,0x01,0xdb,0xf6,0xdb,0x09,0xd6,0x5f,0x4f,0xd7,0x17,0xb4,
1102 0xbf,0x9e,0x2f,0x86,0x52,0x5d,0x70,0x24,0x52,0x32,0x1e,0xa5,0x1d,0x39,0x8b,
1103 0x66,0xf6,0xba,0x9b,0x69,0x8e,0x12,0x60,0xdb,0xb6,0xcf,0xe6,0x0d,0xd6,0x1c,
1104 0x8f,0xd4,0x5b,0x4b,0x00,0xde,0x21,0x93,0xfb,0x6e,0xc7,0x3d,0xb4,0x66,0x0d,
1105 0x29,0x0c,0x4e,0xe9,0x3f,0x94,0xd6,0xd6,0xdc,0xec,0xf8,0x53,0x3b,0x62,0xd5,
1106 0x97,0x50,0x53,0x84,0x17,0xfe,0xe2,0xed,0x4c,0x23,0x0a,0x49,0xce,0x5b,0xe9,
1107 0x70,0x31,0xc1,0x04,0x02,0x02,0x6c,0xb8,0x52,0xcd,0xc7,0x4e,0x70,0xb4,0x13,
1108 0xd7,0xe0,0x92,0xba,0x44,0x1a,0x10,0x4c,0x6e,0x45,0xc6,0x86,0x04,0xc6,0x64,
1109 0xd3,0x9c,0x6e,0xc1,0x9c,0xac,0x74,0x3d,0x77,0x06,0x5e,0x28,0x28,0x5c,0xf5,
1110 0xe0,0x9c,0x19,0xd8,0xba,0x74,0x81,0x2d,0x67,0x77,0x93,0x8d,0xbf,0xd2,0x52,
1111 0x00,0xe6,0xa5,0x38,0x4e,0x2e,0x73,0x66,0x7a };
1112 static BYTE iTunesIssuer[] = {
1113 0x30,0x81,0xb4,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x06,
1114 0x13,0x02,0x55,0x53,0x31,0x17,0x30,0x15,0x06,0x03,0x55,0x04,
1115 0x0a,0x13,0x0e,0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6e,0x2c,
1116 0x20,0x49,0x6e,0x63,0x2e,0x31,0x1f,0x30,0x1d,0x06,0x03,0x55,
1117 0x04,0x0b,0x13,0x16,0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6e,
1118 0x20,0x54,0x72,0x75,0x73,0x74,0x20,0x4e,0x65,0x74,0x77,0x6f,
1119 0x72,0x6b,0x31,0x3b,0x30,0x39,0x06,0x03,0x55,0x04,0x0b,0x13,
1120 0x32,0x54,0x65,0x72,0x6d,0x73,0x20,0x6f,0x66,0x20,0x75,0x73,
1121 0x65,0x20,0x61,0x74,0x20,0x68,0x74,0x74,0x70,0x73,0x3a,0x2f,
1122 0x2f,0x77,0x77,0x77,0x2e,0x76,0x65,0x72,0x69,0x73,0x69,0x67,
1123 0x6e,0x2e,0x63,0x6f,0x6d,0x2f,0x72,0x70,0x61,0x20,0x28,0x63,
1124 0x29,0x30,0x34,0x31,0x2e,0x30,0x2c,0x06,0x03,0x55,0x04,0x03,
1125 0x13,0x25,0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6e,0x20,0x43,
1126 0x6c,0x61,0x73,0x73,0x20,0x33,0x20,0x43,0x6f,0x64,0x65,0x20,
1127 0x53,0x69,0x67,0x6e,0x69,0x6e,0x67,0x20,0x32,0x30,0x30,0x34,
1128 0x20,0x43,0x41 };
1129 static BYTE iTunesSerialNum[] = {
1130 0x8d,0xf6,0x6a,0xdf,0xd2,0x40,0xfe,0xb6,0xa6,0x61,0x9b,0x9b,
1131 0xe0,0xa0,0x1a,0x0f };
1132
1133 static void testFindCert(void)
1134 {
1135 HCERTSTORE store;
1136 PCCERT_CONTEXT context = NULL, subject;
1137 BOOL ret;
1138 CERT_INFO certInfo = { 0 };
1139 CRYPT_HASH_BLOB blob;
1140 BYTE otherSerialNumber[] = { 2 };
1141 DWORD count;
1142 static const WCHAR juan[] = { 'j','u','a','n',0 };
1143 static const WCHAR lang[] = { 'L','A','N','G',0 };
1144 static const WCHAR malcolm[] = { 'm','a','l','c','o','l','m',0 };
1145
1146 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
1147 CERT_STORE_CREATE_NEW_FLAG, NULL);
1148 ok(store != NULL, "CertOpenStore failed: %d\n", GetLastError());
1149 if (!store)
1150 return;
1151
1152 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1153 bigCert, sizeof(bigCert), CERT_STORE_ADD_NEW, NULL);
1154 ok(ret || broken(GetLastError() == OSS_DATA_ERROR /* win98 */),
1155 "CertAddEncodedCertificateToStore failed: %08x\n", GetLastError());
1156 if (!ret && GetLastError() == OSS_DATA_ERROR)
1157 {
1158 skip("bigCert can't be decoded, skipping tests\n");
1159 return;
1160 }
1161 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1162 bigCert2, sizeof(bigCert2), CERT_STORE_ADD_NEW, NULL);
1163 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
1164 GetLastError());
1165 /* This has the same name as bigCert */
1166 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1167 certWithUsage, sizeof(certWithUsage), CERT_STORE_ADD_NEW, NULL);
1168 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
1169 GetLastError());
1170
1171 /* Crashes
1172 context = CertFindCertificateInStore(NULL, 0, 0, 0, NULL, NULL);
1173 */
1174
1175 /* Check first cert's there, by issuer */
1176 certInfo.Subject.pbData = subjectName;
1177 certInfo.Subject.cbData = sizeof(subjectName);
1178 certInfo.SerialNumber.pbData = serialNum;
1179 certInfo.SerialNumber.cbData = sizeof(serialNum);
1180 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
1181 CERT_FIND_ISSUER_NAME, &certInfo.Subject, NULL);
1182 ok(context != NULL, "CertFindCertificateInStore failed: %08x\n",
1183 GetLastError());
1184 if (context)
1185 {
1186 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
1187 CERT_FIND_ISSUER_NAME, &certInfo.Subject, context);
1188 ok(context != NULL, "Expected more than one cert\n");
1189 if (context)
1190 {
1191 context = CertFindCertificateInStore(store, X509_ASN_ENCODING,
1192 0, CERT_FIND_ISSUER_NAME, &certInfo.Subject, context);
1193 ok(context == NULL, "Expected precisely two certs\n");
1194 }
1195 }
1196
1197 /* Check second cert's there as well, by subject name */
1198 certInfo.Subject.pbData = subjectName2;
1199 certInfo.Subject.cbData = sizeof(subjectName2);
1200 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
1201 CERT_FIND_SUBJECT_NAME, &certInfo.Subject, NULL);
1202 ok(context != NULL, "CertFindCertificateInStore failed: %08x\n",
1203 GetLastError());
1204 if (context)
1205 {
1206 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
1207 CERT_FIND_SUBJECT_NAME, &certInfo.Subject, context);
1208 ok(context == NULL, "Expected one cert only\n");
1209 }
1210
1211 /* Strange but true: searching for the subject cert requires you to set
1212 * the issuer, not the subject
1213 */
1214 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
1215 CERT_FIND_SUBJECT_CERT, &certInfo, NULL);
1216 ok(context == NULL, "Expected no certificate\n");
1217 certInfo.Subject.pbData = NULL;
1218 certInfo.Subject.cbData = 0;
1219 certInfo.Issuer.pbData = subjectName2;
1220 certInfo.Issuer.cbData = sizeof(subjectName2);
1221 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
1222 CERT_FIND_SUBJECT_CERT, &certInfo, NULL);
1223 ok(context != NULL, "CertFindCertificateInStore failed: %08x\n",
1224 GetLastError());
1225 if (context)
1226 {
1227 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
1228 CERT_FIND_SUBJECT_CERT, &certInfo, context);
1229 ok(context == NULL, "Expected one cert only\n");
1230 }
1231 /* A non-matching serial number will not match. */
1232 certInfo.SerialNumber.pbData = otherSerialNumber;
1233 certInfo.SerialNumber.cbData = sizeof(otherSerialNumber);
1234 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
1235 CERT_FIND_SUBJECT_CERT, &certInfo, NULL);
1236 ok(context == NULL, "Expected no match\n");
1237 /* No serial number will not match */
1238 certInfo.SerialNumber.cbData = 0;
1239 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
1240 CERT_FIND_SUBJECT_CERT, &certInfo, NULL);
1241 ok(context == NULL, "Expected no match\n");
1242 /* A serial number still won't match if the name doesn't */
1243 certInfo.SerialNumber.pbData = serialNum;
1244 certInfo.SerialNumber.cbData = sizeof(serialNum);
1245 certInfo.Issuer.pbData = subjectName3;
1246 certInfo.Issuer.cbData = sizeof(subjectName3);
1247 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
1248 CERT_FIND_SUBJECT_CERT, &certInfo, NULL);
1249 ok(context == NULL, "Expected no match\n");
1250
1251 /* The nice thing about hashes, they're unique */
1252 blob.pbData = bigCertHash;
1253 blob.cbData = sizeof(bigCertHash);
1254 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
1255 CERT_FIND_SHA1_HASH, &blob, NULL);
1256 ok(context != NULL, "CertFindCertificateInStore failed: %08x\n",
1257 GetLastError());
1258 if (context)
1259 {
1260 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
1261 CERT_FIND_SHA1_HASH, &certInfo.Subject, context);
1262 ok(context == NULL, "Expected one cert only\n");
1263 }
1264
1265 /* Searching for NULL string matches any context. */
1266 count = 0;
1267 context = NULL;
1268 do {
1269 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
1270 CERT_FIND_ISSUER_STR, NULL, context);
1271 if (context)
1272 count++;
1273 } while (context);
1274 ok(count == 3, "expected 3 contexts\n");
1275 count = 0;
1276 context = NULL;
1277 do {
1278 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
1279 CERT_FIND_ISSUER_STR, juan, context);
1280 if (context)
1281 count++;
1282 } while (context);
1283 ok(count == 2, "expected 2 contexts\n");
1284 count = 0;
1285 context = NULL;
1286 do {
1287 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
1288 CERT_FIND_ISSUER_STR, lang, context);
1289 if (context)
1290 count++;
1291 } while (context);
1292 ok(count == 3, "expected 3 contexts\n");
1293 SetLastError(0xdeadbeef);
1294 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
1295 CERT_FIND_ISSUER_STR, malcolm, NULL);
1296 ok(!context, "expected no certs\n");
1297 ok(GetLastError() == CRYPT_E_NOT_FOUND,
1298 "expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
1299
1300 CertCloseStore(store, 0);
1301
1302 /* Another subject cert search, using iTunes's certs */
1303 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
1304 CERT_STORE_CREATE_NEW_FLAG, NULL);
1305 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1306 iTunesCert0, sizeof(iTunesCert0), CERT_STORE_ADD_NEW, NULL);
1307 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
1308 GetLastError());
1309 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1310 iTunesCert1, sizeof(iTunesCert1), CERT_STORE_ADD_NEW, NULL);
1311 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
1312 GetLastError());
1313 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1314 iTunesCert2, sizeof(iTunesCert2), CERT_STORE_ADD_NEW, NULL);
1315 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
1316 GetLastError());
1317 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1318 iTunesCert3, sizeof(iTunesCert3), CERT_STORE_ADD_NEW, &subject);
1319 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
1320 GetLastError());
1321
1322 /* The certInfo's issuer does not match any subject, but the serial
1323 * number does match a cert whose issuer matches certInfo's issuer.
1324 * This yields a match.
1325 */
1326 certInfo.SerialNumber.cbData = sizeof(iTunesSerialNum);
1327 certInfo.SerialNumber.pbData = iTunesSerialNum;
1328 certInfo.Issuer.cbData = sizeof(iTunesIssuer);
1329 certInfo.Issuer.pbData = iTunesIssuer;
1330 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
1331 CERT_FIND_SUBJECT_CERT, &certInfo, NULL);
1332 ok(context != NULL, "Expected a match\n");
1333 if (context)
1334 {
1335 ret = CertCompareCertificateName(context->dwCertEncodingType,
1336 &certInfo.Issuer, &context->pCertInfo->Subject);
1337 ok(!ret, "Expected subject name not to match\n");
1338 ret = CertCompareCertificateName(context->dwCertEncodingType,
1339 &certInfo.Issuer, &context->pCertInfo->Issuer);
1340 ok(ret, "Expected issuer name to match\n");
1341 ret = CertCompareIntegerBlob(&certInfo.SerialNumber,
1342 &context->pCertInfo->SerialNumber);
1343 ok(ret, "Expected serial number to match\n");
1344 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
1345 CERT_FIND_SUBJECT_CERT, &certInfo, context);
1346 ok(context == NULL, "Expected one cert only\n");
1347 }
1348
1349 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
1350 CERT_FIND_ISSUER_OF, subject, NULL);
1351 ok(context != NULL, "Expected an issuer\n");
1352 if (context)
1353 {
1354 PCCERT_CONTEXT none = CertFindCertificateInStore(store,
1355 X509_ASN_ENCODING, 0, CERT_FIND_ISSUER_OF, context, NULL);
1356
1357 ok(!none, "Expected no parent of issuer\n");
1358 CertFreeCertificateContext(context);
1359 }
1360 CertFreeCertificateContext(subject);
1361 CertCloseStore(store, 0);
1362 }
1363
1364 static void testGetSubjectCert(void)
1365 {
1366 HCERTSTORE store;
1367 PCCERT_CONTEXT context1, context2;
1368 CERT_INFO info = { 0 };
1369 BOOL ret;
1370
1371 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
1372 CERT_STORE_CREATE_NEW_FLAG, NULL);
1373 ok(store != NULL, "CertOpenStore failed: %d\n", GetLastError());
1374 if (!store)
1375 return;
1376
1377 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1378 bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL);
1379 ok(ret || broken(GetLastError() == OSS_DATA_ERROR /* win98 */),
1380 "CertAddEncodedCertificateToStore failed: %08x\n", GetLastError());
1381 if (!ret && GetLastError() == OSS_DATA_ERROR)
1382 {
1383 skip("bigCert can't be decoded, skipping tests\n");
1384 return;
1385 }
1386 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1387 bigCert2, sizeof(bigCert2), CERT_STORE_ADD_NEW, &context1);
1388 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
1389 GetLastError());
1390 ok(context1 != NULL, "Expected a context\n");
1391 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1392 certWithUsage, sizeof(certWithUsage), CERT_STORE_ADD_NEW, NULL);
1393 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
1394 GetLastError());
1395
1396 context2 = CertGetSubjectCertificateFromStore(store, X509_ASN_ENCODING,
1397 NULL);
1398 ok(!context2 && GetLastError() == E_INVALIDARG,
1399 "Expected E_INVALIDARG, got %08x\n", GetLastError());
1400 context2 = CertGetSubjectCertificateFromStore(store, X509_ASN_ENCODING,
1401 &info);
1402 ok(!context2 && GetLastError() == CRYPT_E_NOT_FOUND,
1403 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
1404 info.SerialNumber.cbData = sizeof(serialNum);
1405 info.SerialNumber.pbData = serialNum;
1406 context2 = CertGetSubjectCertificateFromStore(store, X509_ASN_ENCODING,
1407 &info);
1408 ok(!context2 && GetLastError() == CRYPT_E_NOT_FOUND,
1409 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
1410 info.Issuer.cbData = sizeof(subjectName2);
1411 info.Issuer.pbData = subjectName2;
1412 context2 = CertGetSubjectCertificateFromStore(store, X509_ASN_ENCODING,
1413 &info);
1414 ok(context2 != NULL,
1415 "CertGetSubjectCertificateFromStore failed: %08x\n", GetLastError());
1416 /* Not only should this find a context, but it should be the same
1417 * (same address) as context1.
1418 */
1419 ok(context1 == context2, "Expected identical context addresses\n");
1420 CertFreeCertificateContext(context2);
1421
1422 CertFreeCertificateContext(context1);
1423 CertCloseStore(store, 0);
1424 }
1425
1426 /* This expires in 1970 or so */
1427 static const BYTE expiredCert[] = { 0x30, 0x82, 0x01, 0x33, 0x30, 0x81, 0xe2,
1428 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0xc4, 0xd7, 0x7f, 0x0e, 0x6f, 0xa6,
1429 0x8c, 0xaa, 0x47, 0x47, 0x40, 0xe7, 0xb7, 0x0b, 0x4a, 0x7f, 0x30, 0x09, 0x06,
1430 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1d, 0x05, 0x00, 0x30, 0x1f, 0x31, 0x1d, 0x30,
1431 0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63, 0x40,
1432 0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63,
1433 0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x36, 0x39, 0x30, 0x31, 0x30, 0x31, 0x30,
1434 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x37, 0x30, 0x30, 0x31, 0x30,
1435 0x31, 0x30, 0x36, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x1f, 0x31, 0x1d, 0x30,
1436 0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63, 0x40,
1437 0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63,
1438 0x6f, 0x6d, 0x30, 0x5c, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
1439 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x4b, 0x00, 0x30, 0x48, 0x02, 0x41,
1440 0x00, 0xa1, 0xaf, 0x4a, 0xea, 0xa7, 0x83, 0x57, 0xc0, 0x37, 0x33, 0x7e, 0x29,
1441 0x5e, 0x0d, 0xfc, 0x44, 0x74, 0x3a, 0x1d, 0xc3, 0x1b, 0x1d, 0x96, 0xed, 0x4e,
1442 0xf4, 0x1b, 0x98, 0xec, 0x69, 0x1b, 0x04, 0xea, 0x25, 0xcf, 0xb3, 0x2a, 0xf5,
1443 0xd9, 0x22, 0xd9, 0x8d, 0x08, 0x39, 0x81, 0xc6, 0xe0, 0x4f, 0x12, 0x37, 0x2a,
1444 0x3f, 0x80, 0xa6, 0x6c, 0x67, 0x43, 0x3a, 0xdd, 0x95, 0x0c, 0xbb, 0x2f, 0x6b,
1445 0x02, 0x03, 0x01, 0x00, 0x01, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02,
1446 0x1d, 0x05, 0x00, 0x03, 0x41, 0x00, 0x8f, 0xa2, 0x5b, 0xd6, 0xdf, 0x34, 0xd0,
1447 0xa2, 0xa7, 0x47, 0xf1, 0x13, 0x79, 0xd3, 0xf3, 0x39, 0xbd, 0x4e, 0x2b, 0xa3,
1448 0xf4, 0x63, 0x37, 0xac, 0x5a, 0x0c, 0x5e, 0x4d, 0x0d, 0x54, 0x87, 0x4f, 0x31,
1449 0xfb, 0xa0, 0xce, 0x8f, 0x9a, 0x2f, 0x4d, 0x48, 0xc6, 0x84, 0x8d, 0xf5, 0x70,
1450 0x74, 0x17, 0xa5, 0xf3, 0x66, 0x47, 0x06, 0xd6, 0x64, 0x45, 0xbc, 0x52, 0xef,
1451 0x49, 0xe5, 0xf9, 0x65, 0xf3 };
1452
1453 /* This expires in 2036 or so */
1454 static const BYTE childOfExpired[] = { 0x30, 0x81, 0xcc, 0x30, 0x78, 0xa0,
1455 0x03, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86,
1456 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x1f, 0x31, 0x1d,
1457 0x30, 0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63,
1458 0x40, 0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e,
1459 0x63, 0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x30, 0x36, 0x30, 0x35, 0x30, 0x35,
1460 0x31, 0x37, 0x31, 0x32, 0x34, 0x39, 0x5a, 0x17, 0x0d, 0x33, 0x36, 0x30, 0x35,
1461 0x30, 0x35, 0x31, 0x37, 0x31, 0x32, 0x34, 0x39, 0x5a, 0x30, 0x15, 0x31, 0x13,
1462 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e,
1463 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03,
1464 0x01, 0x00, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
1465 0x01, 0x05, 0x05, 0x00, 0x03, 0x41, 0x00, 0x20, 0x3b, 0xdb, 0x4d, 0x67, 0x50,
1466 0xec, 0x73, 0x9d, 0xf9, 0x85, 0x5d, 0x18, 0xe9, 0xb4, 0x98, 0xe3, 0x31, 0xb7,
1467 0x03, 0x0b, 0xc0, 0x39, 0x93, 0x56, 0x81, 0x0a, 0xfc, 0x78, 0xa8, 0x29, 0x42,
1468 0x5f, 0x69, 0xfb, 0xbc, 0x5b, 0xf2, 0xa6, 0x2a, 0xbe, 0x91, 0x2c, 0xfc, 0x89,
1469 0x69, 0x15, 0x18, 0x58, 0xe5, 0x02, 0x75, 0xf7, 0x2a, 0xb6, 0xa9, 0xfb, 0x47,
1470 0x6a, 0x6e, 0x0a, 0x9b, 0xe9, 0xdc };
1471 /* chain10_0 -+
1472 * +-> chain7_1
1473 * chain10_1 -+
1474 * A chain with two issuers, only one of whose dates is valid.
1475 */
1476 static const BYTE chain10_0[] = {
1477 0x30,0x82,0x01,0x9b,0x30,0x82,0x01,0x08,0xa0,0x03,0x02,0x01,0x02,0x02,0x10,
1478 0x4a,0x30,0x3a,0x42,0xa2,0x5a,0xb3,0x93,0x4d,0x94,0x06,0xad,0x6d,0x1c,0x34,
1479 0xe6,0x30,0x09,0x06,0x05,0x2b,0x0e,0x03,0x02,0x1d,0x05,0x00,0x30,0x10,0x31,
1480 0x0e,0x30,0x0c,0x06,0x03,0x55,0x04,0x03,0x13,0x05,0x43,0x65,0x72,0x74,0x31,
1481 0x30,0x1e,0x17,0x0d,0x30,0x36,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
1482 0x30,0x5a,0x17,0x0d,0x30,0x36,0x31,0x32,0x33,0x31,0x32,0x33,0x35,0x39,0x35,
1483 0x39,0x5a,0x30,0x10,0x31,0x0e,0x30,0x0c,0x06,0x03,0x55,0x04,0x03,0x13,0x05,
1484 0x43,0x65,0x72,0x74,0x31,0x30,0x81,0x9f,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,
1485 0x86,0xf7,0x0d,0x01,0x01,0x01,0x05,0x00,0x03,0x81,0x8d,0x00,0x30,0x81,0x89,
1486 0x02,0x81,0x81,0x00,0xad,0x7e,0xca,0xf3,0xe5,0x99,0xc2,0x2a,0xca,0x50,0x82,
1487 0x7c,0x2d,0xa4,0x81,0xcd,0x0d,0x0d,0x86,0xd7,0xd8,0xb2,0xde,0xc5,0xc3,0x34,
1488 0x9e,0x07,0x78,0x08,0x11,0x12,0x2d,0x21,0x0a,0x09,0x07,0x14,0x03,0x7a,0xe7,
1489 0x3b,0x58,0xf1,0xde,0x3e,0x01,0x25,0x93,0xab,0x8f,0xce,0x1f,0xc1,0x33,0x91,
1490 0xfe,0x59,0xb9,0x3b,0x9e,0x95,0x12,0x89,0x8e,0xc3,0x4b,0x98,0x1b,0x99,0xc5,
1491 0x07,0xe2,0xdf,0x15,0x4c,0x39,0x76,0x06,0xad,0xdb,0x16,0x06,0x49,0xba,0xcd,
1492 0x0f,0x07,0xd6,0xea,0x27,0xa6,0xfe,0x3d,0x88,0xe5,0x97,0x45,0x72,0xb6,0x1c,
1493 0xc0,0x1c,0xb1,0xa2,0x89,0xe8,0x37,0x9e,0xf6,0x2a,0xcf,0xd5,0x1f,0x2f,0x35,
1494 0x5e,0x8f,0x3a,0x9c,0x61,0xb1,0xf1,0x6c,0xff,0x8c,0xb2,0x2f,0x02,0x03,0x01,
1495 0x00,0x01,0x30,0x09,0x06,0x05,0x2b,0x0e,0x03,0x02,0x1d,0x05,0x00,0x03,0x81,
1496 0x81,0x00,0x85,0x6e,0x35,0x2f,0x2c,0x51,0x4f,0xd6,0x2a,0xe4,0x9e,0xd0,0x4b,
1497 0xe6,0x90,0xfd,0xf7,0x20,0xad,0x76,0x3f,0x93,0xea,0x7f,0x0d,0x1f,0xb3,0x8e,
1498 0xfd,0xe0,0xe1,0xd6,0xd7,0x9c,0x7d,0x46,0x6b,0x15,0x5c,0xe6,0xc9,0x62,0x3b,
1499 0x70,0x4a,0x4b,0xb2,0x82,0xe3,0x55,0x0c,0xc4,0x90,0x44,0x06,0x6c,0x86,0x1c,
1500 0x6d,0x47,0x12,0xda,0x33,0x95,0x5d,0x98,0x43,0xcb,0x7c,0xfa,0x2b,0xee,0xc4,
1501 0x2d,0xc8,0x95,0x33,0x89,0x08,0x3f,0x9f,0x87,0xea,0x20,0x04,0xaf,0x58,0x4b,
1502 0x9d,0xc0,0x7c,0x0a,0x1b,0x05,0x31,0x3b,0xbb,0x13,0x58,0x2e,0x3f,0x61,0x6b,
1503 0x10,0xb4,0xeb,0xb9,0x1a,0x30,0xfd,0xea,0xca,0x29,0x99,0x5f,0x42,0x2b,0x00,
1504 0xb0,0x08,0xc3,0xf0,0xb6,0xd6,0x6b,0xf9,0x35,0x95 };
1505 static const BYTE chain10_1[] = {
1506 0x30,0x82,0x01,0x9b,0x30,0x82,0x01,0x08,0xa0,0x03,0x02,0x01,0x02,0x02,0x10,
1507 0xbf,0x99,0x4f,0x14,0x03,0x77,0x44,0xb8,0x49,0x02,0x70,0xa1,0xb8,0x9c,0xa7,
1508 0x24,0x30,0x09,0x06,0x05,0x2b,0x0e,0x03,0x02,0x1d,0x05,0x00,0x30,0x10,0x31,
1509 0x0e,0x30,0x0c,0x06,0x03,0x55,0x04,0x03,0x13,0x05,0x43,0x65,0x72,0x74,0x31,
1510 0x30,0x1e,0x17,0x0d,0x30,0x37,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
1511 0x30,0x5a,0x17,0x0d,0x30,0x37,0x31,0x32,0x33,0x31,0x32,0x33,0x35,0x39,0x35,
1512 0x39,0x5a,0x30,0x10,0x31,0x0e,0x30,0x0c,0x06,0x03,0x55,0x04,0x03,0x13,0x05,
1513 0x43,0x65,0x72,0x74,0x31,0x30,0x81,0x9f,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,
1514 0x86,0xf7,0x0d,0x01,0x01,0x01,0x05,0x00,0x03,0x81,0x8d,0x00,0x30,0x81,0x89,
1515 0x02,0x81,0x81,0x00,0xad,0x7e,0xca,0xf3,0xe5,0x99,0xc2,0x2a,0xca,0x50,0x82,
1516 0x7c,0x2d,0xa4,0x81,0xcd,0x0d,0x0d,0x86,0xd7,0xd8,0xb2,0xde,0xc5,0xc3,0x34,
1517 0x9e,0x07,0x78,0x08,0x11,0x12,0x2d,0x21,0x0a,0x09,0x07,0x14,0x03,0x7a,0xe7,
1518 0x3b,0x58,0xf1,0xde,0x3e,0x01,0x25,0x93,0xab,0x8f,0xce,0x1f,0xc1,0x33,0x91,
1519 0xfe,0x59,0xb9,0x3b,0x9e,0x95,0x12,0x89,0x8e,0xc3,0x4b,0x98,0x1b,0x99,0xc5,
1520 0x07,0xe2,0xdf,0x15,0x4c,0x39,0x76,0x06,0xad,0xdb,0x16,0x06,0x49,0xba,0xcd,
1521 0x0f,0x07,0xd6,0xea,0x27,0xa6,0xfe,0x3d,0x88,0xe5,0x97,0x45,0x72,0xb6,0x1c,
1522 0xc0,0x1c,0xb1,0xa2,0x89,0xe8,0x37,0x9e,0xf6,0x2a,0xcf,0xd5,0x1f,0x2f,0x35,
1523 0x5e,0x8f,0x3a,0x9c,0x61,0xb1,0xf1,0x6c,0xff,0x8c,0xb2,0x2f,0x02,0x03,0x01,
1524 0x00,0x01,0x30,0x09,0x06,0x05,0x2b,0x0e,0x03,0x02,0x1d,0x05,0x00,0x03,0x81,
1525 0x81,0x00,0xa8,0xec,0x8c,0x34,0xe7,0x2c,0xdf,0x75,0x87,0xc4,0xf7,0xda,0x71,
1526 0x72,0x29,0xb2,0x48,0xa8,0x2a,0xec,0x7b,0x7d,0x19,0xb9,0x5f,0x1d,0xd9,0x91,
1527 0x2b,0xc4,0x28,0x7e,0xd6,0xb5,0x91,0x69,0xa5,0x8a,0x1a,0x1f,0x97,0x98,0x46,
1528 0x9d,0xdf,0x12,0xf6,0x45,0x62,0xad,0x60,0xb6,0xba,0xb0,0xfd,0xf5,0x9f,0xc6,
1529 0x98,0x05,0x4f,0x4d,0x48,0xdc,0xee,0x69,0xbe,0xb8,0xc4,0xc4,0xd7,0x1b,0xb1,
1530 0x1f,0x64,0xd6,0x45,0xa7,0xdb,0xb3,0x87,0x63,0x0f,0x54,0xe1,0x3a,0x6b,0x57,
1531 0x36,0xd7,0x68,0x65,0xcf,0xda,0x57,0x8d,0xcd,0x84,0x75,0x47,0x26,0x2c,0xef,
1532 0x1e,0x8f,0xc7,0x3b,0xee,0x5d,0x03,0xa6,0xdf,0x3a,0x20,0xb2,0xcc,0xc9,0x09,
1533 0x2c,0xfe,0x2b,0x79,0xb0,0xca,0x2c,0x9a,0x81,0x6b };
1534 static const BYTE chain7_1[] = {
1535 0x30,0x82,0x01,0x93,0x30,0x81,0xfd,0xa0,0x03,0x02,0x01,0x02,0x02,0x01,0x01,
1536 0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x05,0x05,0x00,
1537 0x30,0x10,0x31,0x0e,0x30,0x0c,0x06,0x03,0x55,0x04,0x03,0x13,0x05,0x43,0x65,
1538 0x72,0x74,0x31,0x30,0x1e,0x17,0x0d,0x30,0x37,0x30,0x31,0x30,0x31,0x30,0x30,
1539 0x30,0x30,0x30,0x30,0x5a,0x17,0x0d,0x30,0x37,0x31,0x32,0x33,0x31,0x32,0x33,
1540 0x35,0x39,0x35,0x39,0x5a,0x30,0x10,0x31,0x0e,0x30,0x0c,0x06,0x03,0x55,0x04,
1541 0x03,0x13,0x05,0x43,0x65,0x72,0x74,0x32,0x30,0x81,0x9f,0x30,0x0d,0x06,0x09,
1542 0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x01,0x05,0x00,0x03,0x81,0x8d,0x00,
1543 0x30,0x81,0x89,0x02,0x81,0x81,0x00,0xb8,0x52,0xda,0xc5,0x4b,0x3f,0xe5,0x33,
1544 0x0e,0x67,0x5f,0x48,0x21,0xdc,0x7e,0xef,0x37,0x33,0xba,0xff,0xb4,0xc6,0xdc,
1545 0xb6,0x17,0x8e,0x20,0x55,0x07,0x12,0xd2,0x7b,0x3c,0xce,0x30,0xc5,0xa7,0x48,
1546 0x9f,0x6e,0xfe,0xb8,0xbe,0xdb,0x9f,0x9b,0x17,0x60,0x16,0xde,0xc6,0x8b,0x47,
1547 0xd1,0x57,0x71,0x3c,0x93,0xfc,0xbd,0xec,0x44,0x32,0x3b,0xb9,0xcf,0x6b,0x05,
1548 0x72,0xa7,0x87,0x8e,0x7e,0xd4,0x9a,0x87,0x1c,0x2f,0xb7,0x82,0x40,0xfc,0x6a,
1549 0x80,0x83,0x68,0x28,0xce,0x84,0xf4,0x0b,0x2e,0x44,0xcb,0x53,0xac,0x85,0x85,
1550 0xb5,0x46,0x36,0x98,0x3c,0x10,0x02,0xaa,0x02,0xbc,0x8b,0xa2,0x23,0xb2,0xd3,
1551 0x51,0x9a,0x22,0x4a,0xe3,0xaa,0x4e,0x7c,0xda,0x38,0xcf,0x49,0x98,0x72,0xa3,
1552 0x02,0x03,0x01,0x00,0x01,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,
1553 0x01,0x01,0x05,0x05,0x00,0x03,0x81,0x81,0x00,0x9f,0x69,0xfd,0x26,0xd5,0x4b,
1554 0xe0,0xab,0x12,0x21,0xb9,0xfc,0xf7,0xe0,0x0c,0x09,0x94,0xad,0x27,0xd7,0x9d,
1555 0xa3,0xcc,0x46,0x2a,0x25,0x9a,0x24,0xa7,0x31,0x58,0x78,0xf5,0xfc,0x30,0xe1,
1556 0x6d,0xfd,0x59,0xab,0xbe,0x69,0xa0,0xea,0xe3,0x7d,0x7a,0x7b,0xe5,0x85,0xeb,
1557 0x86,0x6a,0x84,0x3c,0x96,0x01,0x1a,0x70,0xa7,0xb8,0xcb,0xf2,0x11,0xe7,0x52,
1558 0x9c,0x58,0x2d,0xac,0x63,0xce,0x72,0x4b,0xad,0x62,0xa8,0x1d,0x75,0x96,0xe2,
1559 0x27,0xf5,0x6f,0xba,0x91,0xf8,0xf1,0xb0,0xbf,0x90,0x24,0x6d,0xba,0x5d,0xd7,
1560 0x39,0x63,0x3b,0x7c,0x04,0x5d,0x89,0x9d,0x1c,0xf2,0xf7,0xcc,0xdf,0x6e,0x8a,
1561 0x43,0xa9,0xdd,0x86,0x05,0xa2,0xf3,0x22,0x2d,0x1e,0x70,0xa1,0x59,0xd7,0xa5,
1562 0x94,0x7d };
1563
1564 static void testGetIssuerCert(void)
1565 {
1566 BOOL ret;
1567 PCCERT_CONTEXT parent, child, cert1, cert2, cert3;
1568 DWORD flags = 0xffffffff, size;
1569 CERT_NAME_BLOB certsubject;
1570 BYTE *certencoded;
1571 WCHAR rootW[] = {'R', 'O', 'O', 'T', '\0'},
1572 certname[] = {'C', 'N', '=', 'd', 'u', 'm', 'm', 'y', ',', ' ', 'T', '=', 'T', 'e', 's', 't', '\0'};
1573 HCERTSTORE store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
1574 CERT_STORE_CREATE_NEW_FLAG, NULL);
1575
1576 ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
1577
1578 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1579 expiredCert, sizeof(expiredCert), CERT_STORE_ADD_ALWAYS, NULL);
1580 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
1581 GetLastError());
1582
1583 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1584 childOfExpired, sizeof(childOfExpired), CERT_STORE_ADD_ALWAYS, &child);
1585 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
1586 GetLastError());
1587
1588 /* These crash:
1589 parent = CertGetIssuerCertificateFromStore(NULL, NULL, NULL, NULL);
1590 parent = CertGetIssuerCertificateFromStore(store, NULL, NULL, NULL);
1591 */
1592 parent = CertGetIssuerCertificateFromStore(NULL, NULL, NULL, &flags);
1593 ok(!parent && GetLastError() == E_INVALIDARG,
1594 "Expected E_INVALIDARG, got %08x\n", GetLastError());
1595 parent = CertGetIssuerCertificateFromStore(store, NULL, NULL, &flags);
1596 ok(!parent && GetLastError() == E_INVALIDARG,
1597 "Expected E_INVALIDARG, got %08x\n", GetLastError());
1598 parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
1599 ok(!parent && GetLastError() == E_INVALIDARG,
1600 "Expected E_INVALIDARG, got %08x\n", GetLastError());
1601 /* Confusing: the caller cannot set either of the
1602 * CERT_STORE_NO_*_FLAGs, as these are not checks,
1603 * they're results:
1604 */
1605 flags = CERT_STORE_NO_CRL_FLAG | CERT_STORE_NO_ISSUER_FLAG;
1606 parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
1607 ok(!parent && GetLastError() == E_INVALIDARG,
1608 "Expected E_INVALIDARG, got %08x\n", GetLastError());
1609 /* Perform no checks */
1610 flags = 0;
1611 parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
1612 ok(parent != NULL, "CertGetIssuerCertificateFromStore failed: %08x\n",
1613 GetLastError());
1614 if (parent)
1615 CertFreeCertificateContext(parent);
1616 /* Check revocation and signature only */
1617 flags = CERT_STORE_REVOCATION_FLAG | CERT_STORE_SIGNATURE_FLAG;
1618 parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
1619 ok(parent != NULL, "CertGetIssuerCertificateFromStore failed: %08x\n",
1620 GetLastError());
1621 /* Confusing: CERT_STORE_REVOCATION_FLAG succeeds when there is no CRL by
1622 * setting CERT_STORE_NO_CRL_FLAG.
1623 */
1624 ok(flags == (CERT_STORE_REVOCATION_FLAG | CERT_STORE_NO_CRL_FLAG),
1625 "Expected CERT_STORE_REVOCATION_FLAG | CERT_STORE_NO_CRL_FLAG, got %08x\n",
1626 flags);
1627 if (parent)
1628 CertFreeCertificateContext(parent);
1629 /* Checking time validity is not productive, because while most Windows
1630 * versions return 0 (time valid) because the child is not expired,
1631 * Windows 2003 SP1 returns that it is expired. Thus the range of
1632 * possibilities is covered, and a test verifies nothing.
1633 */
1634
1635 CertFreeCertificateContext(child);
1636 CertCloseStore(store, 0);
1637
1638 flags = 0;
1639 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
1640 CERT_STORE_CREATE_NEW_FLAG, NULL);
1641 /* With only the child certificate, no issuer will be found */
1642 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1643 chain7_1, sizeof(chain7_1), CERT_STORE_ADD_ALWAYS, &child);
1644 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n", GetLastError());
1645 parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
1646 ok(parent == NULL, "Expected no issuer\n");
1647 ok(GetLastError() == CRYPT_E_NOT_FOUND, "Expected CRYPT_E_NOT_FOUND, got %08X\n", GetLastError());
1648 /* Adding an issuer allows one (and only one) issuer to be found */
1649 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1650 chain10_1, sizeof(chain10_1), CERT_STORE_ADD_ALWAYS, &cert1);
1651 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n", GetLastError());
1652 parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
1653 ok(parent == cert1, "Expected cert1 to be the issuer\n");
1654 parent = CertGetIssuerCertificateFromStore(store, child, parent, &flags);
1655 ok(parent == NULL, "Expected only one issuer\n");
1656 ok(GetLastError() == CRYPT_E_NOT_FOUND, "Expected CRYPT_E_NOT_FOUND, got %08X\n", GetLastError());
1657 /* Adding a second issuer allows two issuers to be found - and the second
1658 * issuer is found before the first, implying certs are added to the head
1659 * of a list.
1660 */
1661 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1662 chain10_0, sizeof(chain10_0), CERT_STORE_ADD_ALWAYS, &cert2);
1663 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n", GetLastError());
1664 parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
1665 ok(parent == cert2, "Expected cert2 to be the first issuer\n");
1666 parent = CertGetIssuerCertificateFromStore(store, child, parent, &flags);
1667 ok(parent == cert1, "Expected cert1 to be the second issuer\n");
1668 parent = CertGetIssuerCertificateFromStore(store, child, parent, &flags);
1669 ok(parent == NULL, "Expected no more than two issuers\n");
1670 ok(GetLastError() == CRYPT_E_NOT_FOUND, "Expected CRYPT_E_NOT_FOUND, got %08X\n", GetLastError());
1671 CertFreeCertificateContext(child);
1672 CertFreeCertificateContext(cert1);
1673 CertFreeCertificateContext(cert2);
1674 CertCloseStore(store, 0);
1675
1676 /* Repeat the test, reversing the order in which issuers are added,
1677 * to show it's order-dependent.
1678 */
1679 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
1680 CERT_STORE_CREATE_NEW_FLAG, NULL);
1681 /* With only the child certificate, no issuer will be found */
1682 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1683 chain7_1, sizeof(chain7_1), CERT_STORE_ADD_ALWAYS, &child);
1684 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n", GetLastError());
1685 parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
1686 ok(parent == NULL, "Expected no issuer\n");
1687 ok(GetLastError() == CRYPT_E_NOT_FOUND, "Expected CRYPT_E_NOT_FOUND, got %08X\n", GetLastError());
1688 /* Adding an issuer allows one (and only one) issuer to be found */
1689 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1690 chain10_0, sizeof(chain10_0), CERT_STORE_ADD_ALWAYS, &cert1);
1691 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n", GetLastError());
1692 parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
1693 ok(parent == cert1, "Expected cert1 to be the issuer\n");
1694 parent = CertGetIssuerCertificateFromStore(store, child, parent, &flags);
1695 ok(parent == NULL, "Expected only one issuer\n");
1696 ok(GetLastError() == CRYPT_E_NOT_FOUND, "Expected CRYPT_E_NOT_FOUND, got %08X\n", GetLastError());
1697 /* Adding a second issuer allows two issuers to be found - and the second
1698 * issuer is found before the first, implying certs are added to the head
1699 * of a list.
1700 */
1701 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
1702 chain10_1, sizeof(chain10_1), CERT_STORE_ADD_ALWAYS, &cert2);
1703 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n", GetLastError());
1704 parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
1705 ok(parent == cert2, "Expected cert2 to be the first issuer\n");
1706 parent = CertGetIssuerCertificateFromStore(store, child, parent, &flags);
1707 ok(parent == cert1, "Expected cert1 to be the second issuer\n");
1708 parent = CertGetIssuerCertificateFromStore(store, child, parent, &flags);
1709 ok(parent == NULL, "Expected no more than two issuers\n");
1710 ok(GetLastError() == CRYPT_E_NOT_FOUND, "Expected CRYPT_E_NOT_FOUND, got %08X\n", GetLastError());
1711
1712 /* Self-sign a certificate, add to the store and test getting the issuer */
1713 size = 0;
1714 ok(CertStrToNameW(X509_ASN_ENCODING, certname, CERT_X500_NAME_STR, NULL, NULL, &size, NULL),
1715 "CertStrToName should have worked\n");
1716 certencoded = HeapAlloc(GetProcessHeap(), 0, size);
1717 ok(CertStrToNameW(X509_ASN_ENCODING, certname, CERT_X500_NAME_STR, NULL, certencoded, &size, NULL),
1718 "CertStrToName should have worked\n");
1719 certsubject.pbData = certencoded;
1720 certsubject.cbData = size;
1721 cert3 = CertCreateSelfSignCertificate(0, &certsubject, 0, NULL, NULL, NULL, NULL, NULL);
1722 ok(cert3 != NULL, "CertCreateSelfSignCertificate should have worked\n");
1723 ret = CertAddCertificateContextToStore(store, cert3, CERT_STORE_ADD_REPLACE_EXISTING, 0);
1724 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n", GetLastError());
1725 CertFreeCertificateContext(cert3);
1726 cert3 = CertEnumCertificatesInStore(store, NULL);
1727 ok(cert3 != NULL, "CertEnumCertificatesInStore should have worked\n");
1728 SetLastError(0xdeadbeef);
1729 flags = 0;
1730 parent = CertGetIssuerCertificateFromStore(store, cert3, NULL, &flags);
1731 ok(!parent, "Expected NULL\n");
1732 ok(GetLastError() == CRYPT_E_SELF_SIGNED,
1733 "Expected CRYPT_E_SELF_SIGNED, got %08X\n", GetLastError());
1734 CertFreeCertificateContext(child);
1735 CertFreeCertificateContext(cert1);
1736 CertFreeCertificateContext(cert2);
1737 CertCloseStore(store, 0);
1738 HeapFree(GetProcessHeap(), 0, certencoded);
1739
1740 /* Test root storage self-signed certificate */
1741 store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0, CERT_SYSTEM_STORE_CURRENT_USER, rootW);
1742 ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
1743 flags = 0;
1744 cert1 = CertEnumCertificatesInStore(store, NULL);
1745 ok(cert1 != NULL, "CertEnumCertificatesInStore should have worked\n");
1746 SetLastError(0xdeadbeef);
1747 parent = CertGetIssuerCertificateFromStore(store, cert1, NULL, &flags);
1748 ok(!parent, "Expected NULL\n");
1749 ok(GetLastError() == CRYPT_E_SELF_SIGNED,
1750 "Expected CRYPT_E_SELF_SIGNED, got %08X\n", GetLastError());
1751 CertCloseStore(store, 0);
1752 }
1753
1754 static void testCryptHashCert(void)
1755 {
1756 static const BYTE emptyHash[] = { 0xda, 0x39, 0xa3, 0xee, 0x5e, 0x6b, 0x4b,
1757 0x0d, 0x32, 0x55, 0xbf, 0xef, 0x95, 0x60, 0x18, 0x90, 0xaf, 0xd8, 0x07,
1758 0x09 };
1759 static const BYTE knownHash[] = { 0xae, 0x9d, 0xbf, 0x6d, 0xf5, 0x46, 0xee,
1760 0x8b, 0xc5, 0x7a, 0x13, 0xba, 0xc2, 0xb1, 0x04, 0xf2, 0xbf, 0x52, 0xa8,
1761 0xa2 };
1762 static const BYTE toHash[] = "abcdefghijklmnopqrstuvwxyz0123456789.,;!?:";
1763 BOOL ret;
1764 BYTE hash[20];
1765 DWORD hashLen = sizeof(hash);
1766
1767 /* NULL buffer and nonzero length crashes
1768 ret = CryptHashCertificate(0, 0, 0, NULL, size, hash, &hashLen);
1769 empty hash length also crashes
1770 ret = CryptHashCertificate(0, 0, 0, buf, size, hash, NULL);
1771 */
1772 /* Test empty hash */
1773 ret = CryptHashCertificate(0, 0, 0, toHash, sizeof(toHash), NULL,
1774 &hashLen);
1775 ok(ret, "CryptHashCertificate failed: %08x\n", GetLastError());
1776 ok(hashLen == sizeof(hash), "Got unexpected size of hash %d\n", hashLen);
1777 /* Test with empty buffer */
1778 ret = CryptHashCertificate(0, 0, 0, NULL, 0, hash, &hashLen);
1779 ok(ret, "CryptHashCertificate failed: %08x\n", GetLastError());
1780 ok(!memcmp(hash, emptyHash, sizeof(emptyHash)),
1781 "Unexpected hash of nothing\n");
1782 /* Test a known value */
1783 ret = CryptHashCertificate(0, 0, 0, toHash, sizeof(toHash), hash,
1784 &hashLen);
1785 ok(ret, "CryptHashCertificate failed: %08x\n", GetLastError());
1786 ok(!memcmp(hash, knownHash, sizeof(knownHash)), "Unexpected hash\n");
1787 }
1788
1789 static void verifySig(HCRYPTPROV csp, const BYTE *toSign, size_t toSignLen,
1790 const BYTE *sig, unsigned int sigLen)
1791 {
1792 HCRYPTHASH hash;
1793 BOOL ret = CryptCreateHash(csp, CALG_SHA1, 0, 0, &hash);
1794
1795 ok(ret, "CryptCreateHash failed: %08x\n", GetLastError());
1796 if (ret)
1797 {
1798 BYTE mySig[64];
1799 DWORD mySigSize = sizeof(mySig);
1800
1801 ret = CryptHashData(hash, toSign, toSignLen, 0);
1802 ok(ret, "CryptHashData failed: %08x\n", GetLastError());
1803 /* use the A variant so the test can run on Win9x */
1804 ret = CryptSignHashA(hash, AT_SIGNATURE, NULL, 0, mySig, &mySigSize);
1805 ok(ret, "CryptSignHash failed: %08x\n", GetLastError());
1806 if (ret)
1807 {
1808 ok(mySigSize == sigLen, "Expected sig length %d, got %d\n",
1809 sigLen, mySigSize);
1810 ok(!memcmp(mySig, sig, sigLen), "Unexpected signature\n");
1811 }
1812 CryptDestroyHash(hash);
1813 }
1814 }
1815
1816 /* Tests signing the certificate described by toBeSigned with the CSP passed in,
1817 * using the algorithm with OID sigOID. The CSP is assumed to be empty, and a
1818 * keyset named AT_SIGNATURE will be added to it. The signature will be stored
1819 * in sig. sigLen should be at least 64 bytes.
1820 */
1821 static void testSignCert(HCRYPTPROV csp, const CRYPT_DATA_BLOB *toBeSigned,
1822 LPCSTR sigOID, BYTE *sig, DWORD *sigLen)
1823 {
1824 BOOL ret;
1825 DWORD size = 0;
1826 CRYPT_ALGORITHM_IDENTIFIER algoID = { NULL, { 0, NULL } };
1827 HCRYPTKEY key;
1828
1829 /* These all crash
1830 ret = CryptSignCertificate(0, 0, 0, NULL, 0, NULL, NULL, NULL, NULL);
1831 ret = CryptSignCertificate(0, 0, 0, NULL, 0, NULL, NULL, NULL, &size);
1832 ret = CryptSignCertificate(0, 0, 0, toBeSigned->pbData, toBeSigned->cbData,
1833 NULL, NULL, NULL, &size);
1834 */
1835 ret = CryptSignCertificate(0, 0, 0, toBeSigned->pbData, toBeSigned->cbData,
1836 &algoID, NULL, NULL, &size);
1837 ok(!ret && GetLastError() == NTE_BAD_ALGID,
1838 "Expected NTE_BAD_ALGID, got %08x\n", GetLastError());
1839 algoID.pszObjId = (LPSTR)sigOID;
1840 ret = CryptSignCertificate(0, 0, 0, toBeSigned->pbData, toBeSigned->cbData,
1841 &algoID, NULL, NULL, &size);
1842 ok(!ret &&
1843 (GetLastError() == ERROR_INVALID_PARAMETER || GetLastError() == NTE_BAD_ALGID),
1844 "Expected ERROR_INVALID_PARAMETER or NTE_BAD_ALGID, got %08x\n",
1845 GetLastError());
1846 ret = CryptSignCertificate(0, AT_SIGNATURE, 0, toBeSigned->pbData,
1847 toBeSigned->cbData, &algoID, NULL, NULL, &size);
1848 ok(!ret &&
1849 (GetLastError() == ERROR_INVALID_PARAMETER || GetLastError() == NTE_BAD_ALGID),
1850 "Expected ERROR_INVALID_PARAMETER or NTE_BAD_ALGID, got %08x\n",
1851 GetLastError());
1852
1853 /* No keys exist in the new CSP yet.. */
1854 ret = CryptSignCertificate(csp, AT_SIGNATURE, 0, toBeSigned->pbData,
1855 toBeSigned->cbData, &algoID, NULL, NULL, &size);
1856 ok(!ret && (GetLastError() == NTE_BAD_KEYSET || GetLastError() ==
1857 NTE_NO_KEY), "Expected NTE_BAD_KEYSET or NTE_NO_KEY, got %08x\n",
1858 GetLastError());
1859 ret = CryptGenKey(csp, AT_SIGNATURE, 0, &key);
1860 ok(ret, "CryptGenKey failed: %08x\n", GetLastError());
1861 if (ret)
1862 {
1863 ret = CryptSignCertificate(csp, AT_SIGNATURE, 0, toBeSigned->pbData,
1864 toBeSigned->cbData, &algoID, NULL, NULL, &size);
1865 ok(ret, "CryptSignCertificate failed: %08x\n", GetLastError());
1866 ok(size <= *sigLen, "Expected size <= %d, got %d\n", *sigLen, size);
1867 if (ret)
1868 {
1869 ret = CryptSignCertificate(csp, AT_SIGNATURE, 0, toBeSigned->pbData,
1870 toBeSigned->cbData, &algoID, NULL, sig, &size);
1871 ok(ret, "CryptSignCertificate failed: %08x\n", GetLastError());
1872 if (ret)
1873 {
1874 *sigLen = size;
1875 verifySig(csp, toBeSigned->pbData, toBeSigned->cbData, sig,
1876 size);
1877 }
1878 }
1879 CryptDestroyKey(key);
1880 }
1881 }
1882
1883 static void testVerifyCertSig(HCRYPTPROV csp, const CRYPT_DATA_BLOB *toBeSigned,
1884 LPCSTR sigOID, const BYTE *sig, DWORD sigLen)
1885 {
1886 CERT_SIGNED_CONTENT_INFO info;
1887 LPBYTE cert = NULL;
1888 DWORD size = 0;
1889 BOOL ret;
1890
1891 if (!pCryptEncodeObjectEx)
1892 {
1893 win_skip("no CryptEncodeObjectEx support\n");
1894 return;
1895 }
1896 ret = CryptVerifyCertificateSignature(0, 0, NULL, 0, NULL);
1897 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
1898 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
1899 ret = CryptVerifyCertificateSignature(csp, 0, NULL, 0, NULL);
1900 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
1901 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
1902 ret = CryptVerifyCertificateSignature(csp, X509_ASN_ENCODING, NULL, 0,
1903 NULL);
1904 ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
1905 GetLastError() == OSS_BAD_ARG),
1906 "Expected CRYPT_E_ASN1_EOD or OSS_BAD_ARG, got %08x\n", GetLastError());
1907 info.ToBeSigned.cbData = toBeSigned->cbData;
1908 info.ToBeSigned.pbData = toBeSigned->pbData;
1909 info.SignatureAlgorithm.pszObjId = (LPSTR)sigOID;
1910 info.SignatureAlgorithm.Parameters.cbData = 0;
1911 info.Signature.cbData = sigLen;
1912 info.Signature.pbData = (BYTE *)sig;
1913 info.Signature.cUnusedBits = 0;
1914 ret = pCryptEncodeObjectEx(X509_ASN_ENCODING, X509_CERT, &info,
1915 CRYPT_ENCODE_ALLOC_FLAG, NULL, &cert, &size);
1916 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1917 if (cert)
1918 {
1919 PCERT_PUBLIC_KEY_INFO pubKeyInfo = NULL;
1920 DWORD pubKeySize;
1921
1922 if (0)
1923 {
1924 /* Crashes prior to Vista */
1925 ret = CryptVerifyCertificateSignature(csp, X509_ASN_ENCODING,
1926 cert, size, NULL);
1927 }
1928 CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING,
1929 (LPSTR)sigOID, 0, NULL, NULL, &pubKeySize);
1930 pubKeyInfo = HeapAlloc(GetProcessHeap(), 0, pubKeySize);
1931 if (pubKeyInfo)
1932 {
1933 ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE,
1934 X509_ASN_ENCODING, (LPSTR)sigOID, 0, NULL, pubKeyInfo,
1935 &pubKeySize);
1936 ok(ret, "CryptExportKey failed: %08x\n", GetLastError());
1937 if (ret)
1938 {
1939 ret = CryptVerifyCertificateSignature(csp, X509_ASN_ENCODING,
1940 cert, size, pubKeyInfo);
1941 ok(ret, "CryptVerifyCertificateSignature failed: %08x\n",
1942 GetLastError());
1943 }
1944 HeapFree(GetProcessHeap(), 0, pubKeyInfo);
1945 }
1946 LocalFree(cert);
1947 }
1948 }
1949
1950 static void testVerifyCertSigEx(HCRYPTPROV csp, const CRYPT_DATA_BLOB *toBeSigned,
1951 LPCSTR sigOID, const BYTE *sig, DWORD sigLen)
1952 {
1953 CERT_SIGNED_CONTENT_INFO info;
1954 LPBYTE cert = NULL;
1955 DWORD size = 0;
1956 BOOL ret;
1957
1958 if (!pCryptVerifyCertificateSignatureEx)
1959 {
1960 win_skip("no CryptVerifyCertificateSignatureEx support\n");
1961 return;
1962 }
1963 if (!pCryptEncodeObjectEx)
1964 {
1965 win_skip("no CryptEncodeObjectEx support\n");
1966 return;
1967 }
1968 ret = pCryptVerifyCertificateSignatureEx(0, 0, 0, NULL, 0, NULL, 0, NULL);
1969 ok(!ret && GetLastError() == E_INVALIDARG,
1970 "Expected E_INVALIDARG, got %08x\n", GetLastError());
1971 ret = pCryptVerifyCertificateSignatureEx(csp, 0, 0, NULL, 0, NULL, 0, NULL);
1972 ok(!ret && GetLastError() == E_INVALIDARG,
1973 "Expected E_INVALIDARG, got %08x\n", GetLastError());
1974 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING, 0, NULL, 0,
1975 NULL, 0, NULL);
1976 ok(!ret && GetLastError() == E_INVALIDARG,
1977 "Expected E_INVALIDARG, got %08x\n", GetLastError());
1978 /* This crashes
1979 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
1980 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, NULL, 0, NULL, 0, NULL);
1981 */
1982 info.ToBeSigned.cbData = toBeSigned->cbData;
1983 info.ToBeSigned.pbData = toBeSigned->pbData;
1984 info.SignatureAlgorithm.pszObjId = (LPSTR)sigOID;
1985 info.SignatureAlgorithm.Parameters.cbData = 0;
1986 info.Signature.cbData = sigLen;
1987 info.Signature.pbData = (BYTE *)sig;
1988 info.Signature.cUnusedBits = 0;
1989 ret = pCryptEncodeObjectEx(X509_ASN_ENCODING, X509_CERT, &info,
1990 CRYPT_ENCODE_ALLOC_FLAG, NULL, &cert, &size);
1991 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1992 if (cert)
1993 {
1994 CRYPT_DATA_BLOB certBlob = { 0, NULL };
1995 PCERT_PUBLIC_KEY_INFO pubKeyInfo = NULL;
1996
1997 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
1998 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob, 0, NULL, 0, NULL);
1999 ok(!ret && GetLastError() == CRYPT_E_ASN1_EOD,
2000 "Expected CRYPT_E_ASN1_EOD, got %08x\n", GetLastError());
2001 certBlob.cbData = 1;
2002 certBlob.pbData = (void *)0xdeadbeef;
2003 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
2004 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob, 0, NULL, 0, NULL);
2005 ok(!ret && (GetLastError() == STATUS_ACCESS_VIOLATION ||
2006 GetLastError() == CRYPT_E_ASN1_EOD /* Win9x */ ||
2007 GetLastError() == CRYPT_E_ASN1_BADTAG /* Win98 */),
2008 "Expected STATUS_ACCESS_VIOLATION, CRYPT_E_ASN1_EOD, OR CRYPT_E_ASN1_BADTAG, got %08x\n",
2009 GetLastError());
2010
2011 certBlob.cbData = size;
2012 certBlob.pbData = cert;
2013 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
2014 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob, 0, NULL, 0, NULL);
2015 ok(!ret && GetLastError() == E_INVALIDARG,
2016 "Expected E_INVALIDARG, got %08x\n", GetLastError());
2017 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
2018 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob,
2019 CRYPT_VERIFY_CERT_SIGN_ISSUER_NULL, NULL, 0, NULL);
2020 ok(!ret && GetLastError() == E_INVALIDARG,
2021 "Expected E_INVALIDARG, got %08x\n", GetLastError());
2022 /* This crashes
2023 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
2024 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob,
2025 CRYPT_VERIFY_CERT_SIGN_ISSUER_PUBKEY, NULL, 0, NULL);
2026 */
2027 CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING,
2028 (LPSTR)sigOID, 0, NULL, NULL, &size);
2029 pubKeyInfo = HeapAlloc(GetProcessHeap(), 0, size);
2030 if (pubKeyInfo)
2031 {
2032 ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE,
2033 X509_ASN_ENCODING, (LPSTR)sigOID, 0, NULL, pubKeyInfo, &size);
2034 ok(ret, "CryptExportKey failed: %08x\n", GetLastError());
2035 if (ret)
2036 {
2037 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
2038 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob,
2039 CRYPT_VERIFY_CERT_SIGN_ISSUER_PUBKEY, pubKeyInfo, 0, NULL);
2040 ok(ret, "CryptVerifyCertificateSignatureEx failed: %08x\n",
2041 GetLastError());
2042 }
2043 HeapFree(GetProcessHeap(), 0, pubKeyInfo);
2044 }
2045 LocalFree(cert);
2046 }
2047 }
2048
2049 static BYTE emptyCert[] = { 0x30, 0x00 };
2050
2051 static void testCertSigs(void)
2052 {
2053 HCRYPTPROV csp;
2054 CRYPT_DATA_BLOB toBeSigned = { sizeof(emptyCert), emptyCert };
2055 BOOL ret;
2056 BYTE sig[64];
2057 DWORD sigSize = sizeof(sig);
2058
2059 /* Just in case a previous run failed, delete this thing */
2060 pCryptAcquireContextA(&csp, cspNameA, MS_DEF_PROV_A, PROV_RSA_FULL,
2061 CRYPT_DELETEKEYSET);
2062 ret = pCryptAcquireContextA(&csp, cspNameA, MS_DEF_PROV_A, PROV_RSA_FULL,
2063 CRYPT_NEWKEYSET);
2064 ok(ret, "CryptAcquireContext failed: %08x\n", GetLastError());
2065
2066 testSignCert(csp, &toBeSigned, szOID_RSA_SHA1RSA, sig, &sigSize);
2067 testVerifyCertSig(csp, &toBeSigned, szOID_RSA_SHA1RSA, sig, sigSize);
2068 testVerifyCertSigEx(csp, &toBeSigned, szOID_RSA_SHA1RSA, sig, sigSize);
2069
2070 CryptReleaseContext(csp, 0);
2071 ret = pCryptAcquireContextA(&csp, cspNameA, MS_DEF_PROV_A, PROV_RSA_FULL,
2072 CRYPT_DELETEKEYSET);
2073 ok(ret, "CryptAcquireContext failed: %08x\n", GetLastError());
2074 }
2075
2076 static const BYTE md5SignedEmptyCert[] = {
2077 0x30,0x56,0x30,0x33,0x02,0x00,0x30,0x02,0x06,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,
2078 0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,
2079 0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x07,
2080 0x30,0x02,0x06,0x00,0x03,0x01,0x00,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,
2081 0x0d,0x02,0x05,0x05,0x00,0x03,0x11,0x00,0xfb,0x0f,0x66,0x82,0x66,0xd9,0xe5,0xf8,
2082 0xd8,0xa2,0x55,0x2b,0xe1,0xa5,0xd9,0x04 };
2083 static const BYTE md5SignedEmptyCertNoNull[] = {
2084 0x30,0x54,0x30,0x33,0x02,0x00,0x30,0x02,0x06,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,
2085 0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,
2086 0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x07,
2087 0x30,0x02,0x06,0x00,0x03,0x01,0x00,0x30,0x0a,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,
2088 0x0d,0x02,0x05,0x03,0x11,0x00,0x04,0xd9,0xa5,0xe1,0x2b,0x55,0xa2,0xd8,0xf8,0xe5,
2089 0xd9,0x66,0x82,0x66,0x0f,0xfb };
2090
2091 static void testSignAndEncodeCert(void)
2092 {
2093 static char oid_rsa_md5rsa[] = szOID_RSA_MD5RSA;
2094 static char oid_rsa_md5[] = szOID_RSA_MD5;
2095 BOOL ret;
2096 DWORD size;
2097 CRYPT_ALGORITHM_IDENTIFIER algID = { 0 };
2098 CERT_INFO info = { 0 };
2099
2100 /* Crash
2101 ret = CryptSignAndEncodeCertificate(0, 0, 0, NULL, NULL, NULL, NULL, NULL,
2102 NULL);
2103 ret = CryptSignAndEncodeCertificate(0, 0, 0, NULL, NULL, NULL, NULL, NULL,
2104 &size);
2105 */
2106 ret = CryptSignAndEncodeCertificate(0, 0, 0, NULL, NULL, &algID, NULL, NULL,
2107 &size);
2108 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2109 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2110 ret = CryptSignAndEncodeCertificate(0, 0, X509_ASN_ENCODING, NULL, NULL,
2111 &algID, NULL, NULL, &size);
2112 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2113 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2114 ret = CryptSignAndEncodeCertificate(0, 0, 0, X509_CERT_TO_BE_SIGNED, NULL,
2115 &algID, NULL, NULL, &size);
2116 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2117 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2118 /* Crashes on some win9x boxes */
2119 if (0)
2120 {
2121 ret = CryptSignAndEncodeCertificate(0, 0, X509_ASN_ENCODING,
2122 X509_CERT_TO_BE_SIGNED, NULL, &algID, NULL, NULL, &size);
2123 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
2124 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
2125 }
2126 /* Crashes
2127 ret = CryptSignAndEncodeCertificate(0, 0, X509_ASN_ENCODING,
2128 X509_CERT_TO_BE_SIGNED, &info, NULL, NULL, NULL, &size);
2129 */
2130 ret = CryptSignAndEncodeCertificate(0, 0, X509_ASN_ENCODING,
2131 X509_CERT_TO_BE_SIGNED, &info, &algID, NULL, NULL, &size);
2132 ok(!ret &&
2133 (GetLastError() == NTE_BAD_ALGID ||
2134 GetLastError() == OSS_BAD_PTR), /* win9x */
2135 "Expected NTE_BAD_ALGID, got %08x\n", GetLastError());
2136 algID.pszObjId = oid_rsa_md5rsa;
2137 ret = CryptSignAndEncodeCertificate(0, 0, X509_ASN_ENCODING,
2138 X509_CERT_TO_BE_SIGNED, &info, &algID, NULL, NULL, &size);
2139 ok(!ret &&
2140 (GetLastError() == ERROR_INVALID_PARAMETER ||
2141 GetLastError() == NTE_BAD_ALGID ||
2142 GetLastError() == OSS_BAD_PTR), /* Win9x */
2143 "Expected ERROR_INVALID_PARAMETER or NTE_BAD_ALGID, got %08x\n",
2144 GetLastError());
2145 algID.pszObjId = oid_rsa_md5;
2146 ret = CryptSignAndEncodeCertificate(0, 0, X509_ASN_ENCODING,
2147 X509_CERT_TO_BE_SIGNED, &info, &algID, NULL, NULL, &size);
2148 /* oid_rsa_md5 not present in some win2k */
2149 if (ret)
2150 {
2151 LPBYTE buf = HeapAlloc(GetProcessHeap(), 0, size);
2152
2153 if (buf)
2154 {
2155 ret = CryptSignAndEncodeCertificate(0, 0, X509_ASN_ENCODING,
2156 X509_CERT_TO_BE_SIGNED, &info, &algID, NULL, buf, &size);
2157 ok(ret, "CryptSignAndEncodeCertificate failed: %08x\n",
2158 GetLastError());
2159 /* Tricky: because the NULL parameters may either be omitted or
2160 * included as an asn.1-encoded NULL (0x05,0x00), two different
2161 * values are allowed.
2162 */
2163 ok(size == sizeof(md5SignedEmptyCert) ||
2164 size == sizeof(md5SignedEmptyCertNoNull), "Unexpected size %d\n",
2165 size);
2166 if (size == sizeof(md5SignedEmptyCert))
2167 ok(!memcmp(buf, md5SignedEmptyCert, size),
2168 "Unexpected value\n");
2169 else if (size == sizeof(md5SignedEmptyCertNoNull))
2170 ok(!memcmp(buf, md5SignedEmptyCertNoNull, size),
2171 "Unexpected value\n");
2172 HeapFree(GetProcessHeap(), 0, buf);
2173 }
2174 }
2175 }
2176
2177 static void testCreateSelfSignCert(void)
2178 {
2179 PCCERT_CONTEXT context;
2180 CERT_NAME_BLOB name = { sizeof(subjectName), subjectName };
2181 HCRYPTPROV csp;
2182 BOOL ret;
2183 HCRYPTKEY key;
2184 CRYPT_KEY_PROV_INFO info;
2185
2186 if (!pCertCreateSelfSignCertificate)
2187 {
2188 win_skip("CertCreateSelfSignCertificate() is not available\n");
2189 return;
2190 }
2191
2192 /* This crashes:
2193 context = pCertCreateSelfSignCertificate(0, NULL, 0, NULL, NULL, NULL, NULL,
2194 NULL);
2195 * Calling this with no first parameter creates a new key container, which
2196 * lasts beyond the test, so I don't test that. Nb: the generated key
2197 * name is a GUID.
2198 context = pCertCreateSelfSignCertificate(0, &name, 0, NULL, NULL, NULL, NULL,
2199 NULL);
2200 */
2201
2202 /* Acquire a CSP */
2203 pCryptAcquireContextA(&csp, cspNameA, MS_DEF_PROV_A, PROV_RSA_FULL,
2204 CRYPT_DELETEKEYSET);
2205 ret = pCryptAcquireContextA(&csp, cspNameA, MS_DEF_PROV_A, PROV_RSA_FULL,
2206 CRYPT_NEWKEYSET);
2207 ok(ret, "CryptAcquireContext failed: %08x\n", GetLastError());
2208
2209 context = pCertCreateSelfSignCertificate(csp, &name, 0, NULL, NULL, NULL,
2210 NULL, NULL);
2211 ok(!context && GetLastError() == NTE_NO_KEY,
2212 "Expected NTE_NO_KEY, got %08x\n", GetLastError());
2213 ret = CryptGenKey(csp, AT_SIGNATURE, 0, &key);
2214 ok(ret, "CryptGenKey failed: %08x\n", GetLastError());
2215 if (ret)
2216 {
2217 context = pCertCreateSelfSignCertificate(csp, &name, 0, NULL, NULL, NULL,
2218 NULL, NULL);
2219 ok(context != NULL, "CertCreateSelfSignCertificate failed: %08x\n",
2220 GetLastError());
2221 if (context)
2222 {
2223 DWORD size = 0;
2224
2225 /* The context must have a key provider info property */
2226 ret = CertGetCertificateContextProperty(context,
2227 CERT_KEY_PROV_INFO_PROP_ID, NULL, &size);
2228 ok(ret && size, "Expected non-zero key provider info\n");
2229 if (size)
2230 {
2231 PCRYPT_KEY_PROV_INFO pInfo = HeapAlloc(GetProcessHeap(), 0, size);
2232
2233 if (pInfo)
2234 {
2235 ret = CertGetCertificateContextProperty(context,
2236 CERT_KEY_PROV_INFO_PROP_ID, pInfo, &size);
2237 ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
2238 GetLastError());
2239 if (ret)
2240 {
2241 /* Sanity-check the key provider */
2242 ok(!lstrcmpW(pInfo->pwszContainerName, cspNameW),
2243 "Unexpected key container\n");
2244 ok(!lstrcmpW(pInfo->pwszProvName, MS_DEF_PROV_W),
2245 "Unexpected provider\n");
2246 ok(pInfo->dwKeySpec == AT_SIGNATURE,
2247 "Expected AT_SIGNATURE, got %d\n", pInfo->dwKeySpec);
2248 }
2249 HeapFree(GetProcessHeap(), 0, pInfo);
2250 }
2251 }
2252
2253 CertFreeCertificateContext(context);
2254 }
2255
2256 CryptDestroyKey(key);
2257 }
2258
2259 CryptReleaseContext(csp, 0);
2260 ret = pCryptAcquireContextA(&csp, cspNameA, MS_DEF_PROV_A, PROV_RSA_FULL,
2261 CRYPT_DELETEKEYSET);
2262 ok(ret, "CryptAcquireContext failed: %08x\n", GetLastError());
2263
2264 /* Do the same test with a CSP, AT_KEYEXCHANGE and key info */
2265 pCryptAcquireContextA(&csp, cspNameA, MS_DEF_PROV_A, PROV_RSA_FULL,
2266 CRYPT_DELETEKEYSET);
2267 ret = pCryptAcquireContextA(&csp, cspNameA, MS_DEF_PROV_A, PROV_RSA_FULL,
2268 CRYPT_NEWKEYSET);
2269 ok(ret, "CryptAcquireContext failed: %08x\n", GetLastError());
2270 ret = CryptGenKey(csp, AT_SIGNATURE, 0, &key);
2271 ok(ret, "CryptGenKey failed: %08x\n", GetLastError());
2272
2273 memset(&info,0,sizeof(info));
2274 info.dwProvType = PROV_RSA_FULL;
2275 info.dwKeySpec = AT_KEYEXCHANGE;
2276 info.pwszProvName = (LPWSTR) MS_DEF_PROV_W;
2277 info.pwszContainerName = cspNameW;
2278 /* This should fail because the CSP doesn't have the specified key. */
2279 SetLastError(0xdeadbeef);
2280 context = pCertCreateSelfSignCertificate(csp, &name, 0, &info, NULL, NULL,
2281 NULL, NULL);
2282 ok(context == NULL, "expected failure\n");
2283 if (context != NULL)
2284 CertFreeCertificateContext(context);
2285 else
2286 ok(GetLastError() == NTE_NO_KEY, "expected NTE_NO_KEY, got %08x\n",
2287 GetLastError());
2288 /* Again, with a CSP, AT_SIGNATURE and key info */
2289 info.dwKeySpec = AT_SIGNATURE;
2290 SetLastError(0xdeadbeef);
2291 context = pCertCreateSelfSignCertificate(csp, &name, 0, &info, NULL, NULL,
2292 NULL, NULL);
2293 ok(context != NULL,
2294 "CertCreateSelfSignCertificate failed: %08x\n", GetLastError());
2295 if (context)
2296 {
2297 DWORD size = 0;
2298
2299 /* The context must have a key provider info property */
2300 ret = CertGetCertificateContextProperty(context,
2301 CERT_KEY_PROV_INFO_PROP_ID, NULL, &size);
2302 ok(ret && size, "Expected non-zero key provider info\n");
2303 if (size)
2304 {
2305 PCRYPT_KEY_PROV_INFO pInfo = HeapAlloc(GetProcessHeap(), 0, size);
2306
2307 if (pInfo)
2308 {
2309 ret = CertGetCertificateContextProperty(context,
2310 CERT_KEY_PROV_INFO_PROP_ID, pInfo, &size);
2311 ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
2312 GetLastError());
2313 if (ret)
2314 {
2315 /* Sanity-check the key provider */
2316 ok(!lstrcmpW(pInfo->pwszContainerName, cspNameW),
2317 "Unexpected key container\n");
2318 ok(!lstrcmpW(pInfo->pwszProvName, MS_DEF_PROV_W),
2319 "Unexpected provider\n");
2320 ok(pInfo->dwKeySpec == AT_SIGNATURE,
2321 "Expected AT_SIGNATURE, got %d\n", pInfo->dwKeySpec);
2322 }
2323 HeapFree(GetProcessHeap(), 0, pInfo);
2324 }
2325 }
2326
2327 CertFreeCertificateContext(context);
2328 }
2329 CryptDestroyKey(key);
2330
2331 CryptReleaseContext(csp, 0);
2332 ret = pCryptAcquireContextA(&csp, cspNameA, MS_DEF_PROV_A, PROV_RSA_FULL,
2333 CRYPT_DELETEKEYSET);
2334 ok(ret, "CryptAcquireContext failed: %08x\n", GetLastError());
2335
2336 /* Do the same test with no CSP, AT_KEYEXCHANGE and key info */
2337 info.dwKeySpec = AT_KEYEXCHANGE;
2338 context = pCertCreateSelfSignCertificate(0, &name, 0, &info, NULL, NULL,
2339 NULL, NULL);
2340 ok(context != NULL, "CertCreateSelfSignCertificate failed: %08x\n",
2341 GetLastError());
2342 if (context)
2343 {
2344 DWORD size = 0;
2345
2346 /* The context must have a key provider info property */
2347 ret = CertGetCertificateContextProperty(context,
2348 CERT_KEY_PROV_INFO_PROP_ID, NULL, &size);
2349 ok(ret && size, "Expected non-zero key provider info\n");
2350 if (size)
2351 {
2352 PCRYPT_KEY_PROV_INFO pInfo = HeapAlloc(GetProcessHeap(), 0, size);
2353
2354 if (pInfo)
2355 {
2356 ret = CertGetCertificateContextProperty(context,
2357 CERT_KEY_PROV_INFO_PROP_ID, pInfo, &size);
2358 ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
2359 GetLastError());
2360 if (ret)
2361 {
2362 /* Sanity-check the key provider */
2363 ok(!lstrcmpW(pInfo->pwszContainerName, cspNameW),
2364 "Unexpected key container\n");
2365 ok(!lstrcmpW(pInfo->pwszProvName, MS_DEF_PROV_W),
2366 "Unexpected provider\n");
2367 ok(pInfo->dwKeySpec == AT_KEYEXCHANGE,
2368 "Expected AT_KEYEXCHANGE, got %d\n", pInfo->dwKeySpec);
2369 }
2370 HeapFree(GetProcessHeap(), 0, pInfo);
2371 }
2372 }
2373
2374 CertFreeCertificateContext(context);
2375 }
2376
2377 pCryptAcquireContextA(&csp, cspNameA, MS_DEF_PROV_A, PROV_RSA_FULL,
2378 CRYPT_DELETEKEYSET);
2379
2380 /* Acquire a CSP and generate an AT_KEYEXCHANGE key in it. */
2381 pCryptAcquireContextA(&csp, cspNameA, MS_DEF_PROV_A, PROV_RSA_FULL,
2382 CRYPT_DELETEKEYSET);
2383 ret = pCryptAcquireContextA(&csp, cspNameA, MS_DEF_PROV_A, PROV_RSA_FULL,
2384 CRYPT_NEWKEYSET);
2385 ok(ret, "CryptAcquireContext failed: %08x\n", GetLastError());
2386
2387 context = pCertCreateSelfSignCertificate(csp, &name, 0, NULL, NULL, NULL,
2388 NULL, NULL);
2389 ok(!context && GetLastError() == NTE_NO_KEY,
2390 "Expected NTE_NO_KEY, got %08x\n", GetLastError());
2391 ret = CryptGenKey(csp, AT_KEYEXCHANGE, 0, &key);
2392 ok(ret, "CryptGenKey failed: %08x\n", GetLastError());
2393 CryptDestroyKey(key);
2394
2395 memset(&info,0,sizeof(info));
2396 info.dwProvType = PROV_RSA_FULL;
2397 info.dwKeySpec = AT_SIGNATURE;
2398 info.pwszProvName = (LPWSTR) MS_DEF_PROV_W;
2399 info.pwszContainerName = cspNameW;
2400 /* This should fail because the CSP doesn't have the specified key. */
2401 SetLastError(0xdeadbeef);
2402 context = pCertCreateSelfSignCertificate(csp, &name, 0, &info, NULL, NULL,
2403 NULL, NULL);
2404 ok(context == NULL, "expected failure\n");
2405 if (context != NULL)
2406 CertFreeCertificateContext(context);
2407 else
2408 ok(GetLastError() == NTE_NO_KEY, "expected NTE_NO_KEY, got %08x\n",
2409 GetLastError());
2410 /* Again, with a CSP, AT_KEYEXCHANGE and key info. This succeeds because the
2411 * CSP has an AT_KEYEXCHANGE key in it.
2412 */
2413 info.dwKeySpec = AT_KEYEXCHANGE;
2414 SetLastError(0xdeadbeef);
2415 context = pCertCreateSelfSignCertificate(csp, &name, 0, &info, NULL, NULL,
2416 NULL, NULL);
2417 ok(context != NULL,
2418 "CertCreateSelfSignCertificate failed: %08x\n", GetLastError());
2419 if (context)
2420 {
2421 DWORD size = 0;
2422
2423 /* The context must have a key provider info property */
2424 ret = CertGetCertificateContextProperty(context,
2425 CERT_KEY_PROV_INFO_PROP_ID, NULL, &size);
2426 ok(ret && size, "Expected non-zero key provider info\n");
2427 if (size)
2428 {
2429 PCRYPT_KEY_PROV_INFO pInfo = HeapAlloc(GetProcessHeap(), 0, size);
2430
2431 if (pInfo)
2432 {
2433 ret = CertGetCertificateContextProperty(context,
2434 CERT_KEY_PROV_INFO_PROP_ID, pInfo, &size);
2435 ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
2436 GetLastError());
2437 if (ret)
2438 {
2439 /* Sanity-check the key provider */
2440 ok(!lstrcmpW(pInfo->pwszContainerName, cspNameW),
2441 "Unexpected key container\n");
2442 ok(!lstrcmpW(pInfo->pwszProvName, MS_DEF_PROV_W),
2443 "Unexpected provider\n");
2444 ok(pInfo->dwKeySpec == AT_KEYEXCHANGE,
2445 "Expected AT_KEYEXCHANGE, got %d\n", pInfo->dwKeySpec);
2446 }
2447 HeapFree(GetProcessHeap(), 0, pInfo);
2448 }
2449 }
2450
2451 CertFreeCertificateContext(context);
2452 }
2453
2454 CryptReleaseContext(csp, 0);
2455 ret = pCryptAcquireContextA(&csp, cspNameA, MS_DEF_PROV_A, PROV_RSA_FULL,
2456 CRYPT_DELETEKEYSET);
2457 ok(ret, "CryptAcquireContext failed: %08x\n", GetLastError());
2458
2459 }
2460
2461 static void testIntendedKeyUsage(void)
2462 {
2463 BOOL ret;
2464 CERT_INFO info = { 0 };
2465 static char oid_key_usage[] = szOID_KEY_USAGE;
2466 /* A couple "key usages". Really they're just encoded bits which aren't
2467 * necessarily restricted to the defined key usage values.
2468 */
2469 static BYTE usage1[] = { 0x03,0x03,0x00,0xff,0xff };
2470 static BYTE usage2[] = { 0x03,0x03,0x01,0xff,0xfe };
2471 static const BYTE expected_usage1[] = { 0xff,0xff,0x00,0x00 };
2472 static const BYTE expected_usage2[] = { 0xff,0xfe,0x00,0x00 };
2473 CERT_EXTENSION ext = { oid_key_usage, TRUE, { sizeof(usage1), usage1 } };
2474 BYTE usage_bytes[4];
2475
2476 if (0)
2477 {
2478 /* Crash */
2479 CertGetIntendedKeyUsage(0, NULL, NULL, 0);
2480 }
2481 ret = CertGetIntendedKeyUsage(0, &info, NULL, 0);
2482 ok(!ret, "expected failure\n");
2483 ret = CertGetIntendedKeyUsage(0, &info, usage_bytes, sizeof(usage_bytes));
2484 ok(!ret, "expected failure\n");
2485 ret = CertGetIntendedKeyUsage(X509_ASN_ENCODING, &info, NULL, 0);
2486 ok(!ret, "expected failure\n");
2487 ret = CertGetIntendedKeyUsage(X509_ASN_ENCODING, &info, usage_bytes,
2488 sizeof(usage_bytes));
2489 ok(!ret, "expected failure\n");
2490 info.cExtension = 1;
2491 info.rgExtension = &ext;
2492 ret = CertGetIntendedKeyUsage(X509_ASN_ENCODING, &info, NULL, 0);
2493 ok(!ret, "expected failure\n");
2494 /* The unused bytes are filled with 0. */
2495 ret = CertGetIntendedKeyUsage(X509_ASN_ENCODING, &info, usage_bytes,
2496 sizeof(usage_bytes));
2497 ok(ret, "CertGetIntendedKeyUsage failed: %08x\n", GetLastError());
2498 ok(!memcmp(usage_bytes, expected_usage1, sizeof(expected_usage1)),
2499 "unexpected value\n");
2500 /* The usage bytes are copied in big-endian order. */
2501 ext.Value.cbData = sizeof(usage2);
2502 ext.Value.pbData = usage2;
2503 ret = CertGetIntendedKeyUsage(X509_ASN_ENCODING, &info, usage_bytes,
2504 sizeof(usage_bytes));
2505 ok(ret, "CertGetIntendedKeyUsage failed: %08x\n", GetLastError());
2506 ok(!memcmp(usage_bytes, expected_usage2, sizeof(expected_usage2)),
2507 "unexpected value\n");
2508 }
2509
2510 static const LPCSTR keyUsages[] = { szOID_PKIX_KP_CODE_SIGNING,
2511 szOID_PKIX_KP_CLIENT_AUTH, szOID_RSA_RSA };
2512
2513 static void testKeyUsage(void)
2514 {
2515 BOOL ret;
2516 PCCERT_CONTEXT context;
2517 DWORD size;
2518
2519 /* Test base cases */
2520 ret = CertGetEnhancedKeyUsage(NULL, 0, NULL, NULL);
2521 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
2522 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
2523 size = 1;
2524 ret = CertGetEnhancedKeyUsage(NULL, 0, NULL, &size);
2525 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
2526 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
2527 size = 0;
2528 ret = CertGetEnhancedKeyUsage(NULL, 0, NULL, &size);
2529 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
2530 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
2531 /* These crash
2532 ret = CertSetEnhancedKeyUsage(NULL, NULL);
2533 usage.cUsageIdentifier = 0;
2534 ret = CertSetEnhancedKeyUsage(NULL, &usage);
2535 */
2536 /* Test with a cert with no enhanced key usage extension */
2537 context = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert,
2538 sizeof(bigCert));
2539 ok(context != NULL, "CertCreateCertificateContext failed: %08x\n",
2540 GetLastError());
2541 if (context)
2542 {
2543 static const char oid[] = "1.2.3.4";
2544 BYTE buf[sizeof(CERT_ENHKEY_USAGE) + 2 * (sizeof(LPSTR) + sizeof(oid))];
2545 PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
2546
2547 ret = CertGetEnhancedKeyUsage(context, 0, NULL, NULL);
2548 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
2549 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
2550 size = 1;
2551 ret = CertGetEnhancedKeyUsage(context, 0, NULL, &size);
2552 if (ret)
2553 {
2554 /* Windows 2000, ME, or later: even though it succeeded, we expect
2555 * CRYPT_E_NOT_FOUND, which indicates there is no enhanced key
2556 * usage set for this cert (which implies it's valid for all uses.)
2557 */
2558 ok(GetLastError() == CRYPT_E_NOT_FOUND,
2559 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
2560 ok(size == sizeof(CERT_ENHKEY_USAGE), "Wrong size %d\n", size);
2561 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
2562 ok(ret, "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2563 ok(pUsage->cUsageIdentifier == 0, "Expected 0 usages, got %d\n",
2564 pUsage->cUsageIdentifier);
2565 }
2566 else
2567 {
2568 /* Windows NT, 95, or 98: it fails, and the last error is
2569 * CRYPT_E_NOT_FOUND.
2570 */
2571 ok(GetLastError() == CRYPT_E_NOT_FOUND,
2572 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
2573 }
2574 /* I can add a usage identifier when no key usage has been set */
2575 ret = CertAddEnhancedKeyUsageIdentifier(context, oid);
2576 ok(ret, "CertAddEnhancedKeyUsageIdentifier failed: %08x\n",
2577 GetLastError());
2578 size = sizeof(buf);
2579 ret = CertGetEnhancedKeyUsage(context,
2580 CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG, pUsage, &size);
2581 ok(ret && GetLastError() == 0,
2582 "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2583 ok(pUsage->cUsageIdentifier == 1, "Expected 1 usage, got %d\n",
2584 pUsage->cUsageIdentifier);
2585 if (pUsage->cUsageIdentifier)
2586 ok(!strcmp(pUsage->rgpszUsageIdentifier[0], oid),
2587 "Expected %s, got %s\n", oid, pUsage->rgpszUsageIdentifier[0]);
2588 /* Now set an empty key usage */
2589 pUsage->cUsageIdentifier = 0;
2590 ret = CertSetEnhancedKeyUsage(context, pUsage);
2591 ok(ret, "CertSetEnhancedKeyUsage failed: %08x\n", GetLastError());
2592 /* Shouldn't find it in the cert */
2593 size = sizeof(buf);
2594 ret = CertGetEnhancedKeyUsage(context,
2595 CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, pUsage, &size);
2596 ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
2597 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
2598 /* Should find it as an extended property */
2599 ret = CertGetEnhancedKeyUsage(context,
2600 CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG, pUsage, &size);
2601 ok(ret && GetLastError() == 0,
2602 "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2603 ok(pUsage->cUsageIdentifier == 0, "Expected 0 usages, got %d\n",
2604 pUsage->cUsageIdentifier);
2605 /* Should find it as either */
2606 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
2607 ok(ret && GetLastError() == 0,
2608 "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2609 ok(pUsage->cUsageIdentifier == 0, "Expected 0 usages, got %d\n",
2610 pUsage->cUsageIdentifier);
2611 /* Add a usage identifier */
2612 ret = CertAddEnhancedKeyUsageIdentifier(context, oid);
2613 ok(ret, "CertAddEnhancedKeyUsageIdentifier failed: %08x\n",
2614 GetLastError());
2615 size = sizeof(buf);
2616 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
2617 ok(ret && GetLastError() == 0,
2618 "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2619 ok(pUsage->cUsageIdentifier == 1, "Expected 1 identifier, got %d\n",
2620 pUsage->cUsageIdentifier);
2621 if (pUsage->cUsageIdentifier)
2622 ok(!strcmp(pUsage->rgpszUsageIdentifier[0], oid),
2623 "Expected %s, got %s\n", oid, pUsage->rgpszUsageIdentifier[0]);
2624 /* Re-adding the same usage identifier succeeds, though it only adds
2625 * a duplicate usage identifier on versions prior to Vista
2626 */
2627 ret = CertAddEnhancedKeyUsageIdentifier(context, oid);
2628 ok(ret, "CertAddEnhancedKeyUsageIdentifier failed: %08x\n",
2629 GetLastError());
2630 size = sizeof(buf);
2631 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
2632 ok(ret && GetLastError() == 0,
2633 "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2634 ok(pUsage->cUsageIdentifier == 1 || pUsage->cUsageIdentifier == 2,
2635 "Expected 1 or 2 identifiers, got %d\n", pUsage->cUsageIdentifier);
2636 if (pUsage->cUsageIdentifier)
2637 ok(!strcmp(pUsage->rgpszUsageIdentifier[0], oid),
2638 "Expected %s, got %s\n", oid, pUsage->rgpszUsageIdentifier[0]);
2639 if (pUsage->cUsageIdentifier >= 2)
2640 ok(!strcmp(pUsage->rgpszUsageIdentifier[1], oid),
2641 "Expected %s, got %s\n", oid, pUsage->rgpszUsageIdentifier[1]);
2642 /* Now set a NULL extended property--this deletes the property. */
2643 ret = CertSetEnhancedKeyUsage(context, NULL);
2644 ok(ret, "CertSetEnhancedKeyUsage failed: %08x\n", GetLastError());
2645 SetLastError(0xbaadcafe);
2646 size = sizeof(buf);
2647 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
2648 ok(ret || broken(!ret && GetLastError() == CRYPT_E_NOT_FOUND /* NT4 */),
2649 "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2650 ok(GetLastError() == CRYPT_E_NOT_FOUND,
2651 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
2652
2653 CertFreeCertificateContext(context);
2654 }
2655 /* Now test with a cert with an enhanced key usage extension */
2656 context = CertCreateCertificateContext(X509_ASN_ENCODING, certWithUsage,
2657 sizeof(certWithUsage));
2658 ok(context != NULL, "CertCreateCertificateContext failed: %08x\n",
2659 GetLastError());
2660 if (context)
2661 {
2662 LPBYTE buf = NULL;
2663 DWORD bufSize = 0, i;
2664
2665 /* The size may depend on what flags are used to query it, so I
2666 * realloc the buffer for each test.
2667 */
2668 ret = CertGetEnhancedKeyUsage(context,
2669 CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, NULL, &bufSize);
2670 ok(ret, "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2671 buf = HeapAlloc(GetProcessHeap(), 0, bufSize);
2672 if (buf)
2673 {
2674 PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
2675
2676 /* Should find it in the cert */
2677 size = bufSize;
2678 ret = CertGetEnhancedKeyUsage(context,
2679 CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, pUsage, &size);
2680 ok(ret && GetLastError() == 0,
2681 "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2682 ok(pUsage->cUsageIdentifier == 3, "Expected 3 usages, got %d\n",
2683 pUsage->cUsageIdentifier);
2684 for (i = 0; i < pUsage->cUsageIdentifier; i++)
2685 ok(!strcmp(pUsage->rgpszUsageIdentifier[i], keyUsages[i]),
2686 "Expected %s, got %s\n", keyUsages[i],
2687 pUsage->rgpszUsageIdentifier[i]);
2688 HeapFree(GetProcessHeap(), 0, buf);
2689 }
2690 ret = CertGetEnhancedKeyUsage(context, 0, NULL, &bufSize);
2691 ok(ret, "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2692 buf = HeapAlloc(GetProcessHeap(), 0, bufSize);
2693 if (buf)
2694 {
2695 PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
2696
2697 /* Should find it as either */
2698 size = bufSize;
2699 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
2700 /* In Windows, GetLastError returns CRYPT_E_NOT_FOUND not found
2701 * here, even though the return is successful and the usage id
2702 * count is positive. I don't enforce that here.
2703 */
2704 ok(ret,
2705 "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2706 ok(pUsage->cUsageIdentifier == 3, "Expected 3 usages, got %d\n",
2707 pUsage->cUsageIdentifier);
2708 for (i = 0; i < pUsage->cUsageIdentifier; i++)
2709 ok(!strcmp(pUsage->rgpszUsageIdentifier[i], keyUsages[i]),
2710 "Expected %s, got %s\n", keyUsages[i],
2711 pUsage->rgpszUsageIdentifier[i]);
2712 HeapFree(GetProcessHeap(), 0, buf);
2713 }
2714 /* Shouldn't find it as an extended property */
2715 ret = CertGetEnhancedKeyUsage(context,
2716 CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG, NULL, &size);
2717 ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
2718 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
2719 /* Adding a usage identifier overrides the cert's usage!? */
2720 ret = CertAddEnhancedKeyUsageIdentifier(context, szOID_RSA_RSA);
2721 ok(ret, "CertAddEnhancedKeyUsageIdentifier failed: %08x\n",
2722 GetLastError());
2723 ret = CertGetEnhancedKeyUsage(context, 0, NULL, &bufSize);
2724 ok(ret, "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2725 buf = HeapAlloc(GetProcessHeap(), 0, bufSize);
2726 if (buf)
2727 {
2728 PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
2729
2730 /* Should find it as either */
2731 size = bufSize;
2732 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
2733 ok(ret,
2734 "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2735 ok(pUsage->cUsageIdentifier == 1, "Expected 1 usage, got %d\n",
2736 pUsage->cUsageIdentifier);
2737 ok(!strcmp(pUsage->rgpszUsageIdentifier[0], szOID_RSA_RSA),
2738 "Expected %s, got %s\n", szOID_RSA_RSA,
2739 pUsage->rgpszUsageIdentifier[0]);
2740 HeapFree(GetProcessHeap(), 0, buf);
2741 }
2742 /* But querying the cert directly returns its usage */
2743 ret = CertGetEnhancedKeyUsage(context,
2744 CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, NULL, &bufSize);
2745 ok(ret, "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2746 buf = HeapAlloc(GetProcessHeap(), 0, bufSize);
2747 if (buf)
2748 {
2749 PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
2750
2751 size = bufSize;
2752 ret = CertGetEnhancedKeyUsage(context,
2753 CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, pUsage, &size);
2754 ok(ret,
2755 "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2756 ok(pUsage->cUsageIdentifier == 3, "Expected 3 usages, got %d\n",
2757 pUsage->cUsageIdentifier);
2758 for (i = 0; i < pUsage->cUsageIdentifier; i++)
2759 ok(!strcmp(pUsage->rgpszUsageIdentifier[i], keyUsages[i]),
2760 "Expected %s, got %s\n", keyUsages[i],
2761 pUsage->rgpszUsageIdentifier[i]);
2762 HeapFree(GetProcessHeap(), 0, buf);
2763 }
2764 /* And removing the only usage identifier in the extended property
2765 * results in the cert's key usage being found.
2766 */
2767 ret = CertRemoveEnhancedKeyUsageIdentifier(context, szOID_RSA_RSA);
2768 ok(ret, "CertRemoveEnhancedKeyUsage failed: %08x\n", GetLastError());
2769 ret = CertGetEnhancedKeyUsage(context, 0, NULL, &bufSize);
2770 ok(ret, "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2771 buf = HeapAlloc(GetProcessHeap(), 0, bufSize);
2772 if (buf)
2773 {
2774 PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
2775
2776 /* Should find it as either */
2777 size = bufSize;
2778 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
2779 ok(ret,
2780 "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
2781 ok(pUsage->cUsageIdentifier == 3, "Expected 3 usages, got %d\n",
2782 pUsage->cUsageIdentifier);
2783 for (i = 0; i < pUsage->cUsageIdentifier; i++)
2784 ok(!strcmp(pUsage->rgpszUsageIdentifier[i], keyUsages[i]),
2785 "Expected %s, got %s\n", keyUsages[i],
2786 pUsage->rgpszUsageIdentifier[i]);
2787 HeapFree(GetProcessHeap(), 0, buf);
2788 }
2789
2790 CertFreeCertificateContext(context);
2791 }
2792 }
2793
2794 static const BYTE cert2WithUsage[] = {
2795 0x30,0x81,0x89,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
2796 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
2797 0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,
2798 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
2799 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,
2800 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
2801 0x67,0x00,0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00,0xa3,0x25,0x30,0x23,
2802 0x30,0x21,0x06,0x03,0x55,0x1d,0x25,0x01,0x01,0xff,0x04,0x17,0x30,0x15,0x06,
2803 0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x03,0x02,0x06,0x09,0x2a,0x86,0x48,0x86,
2804 0xf7,0x0d,0x01,0x01,0x01 };
2805
2806 static void testGetValidUsages(void)
2807 {
2808 static const LPCSTR expectedOIDs[] = {
2809 "1.3.6.1.5.5.7.3.3",
2810 "1.3.6.1.5.5.7.3.2",
2811 "1.2.840.113549.1.1.1",
2812 };
2813 static const LPCSTR expectedOIDs2[] = {
2814 "1.3.6.1.5.5.7.3.2",
2815 "1.2.840.113549.1.1.1",
2816 };
2817 BOOL ret;
2818 int numOIDs;
2819 DWORD size;
2820 LPSTR *oids = NULL;
2821 PCCERT_CONTEXT contexts[3];
2822
2823 if (!pCertGetValidUsages)
2824 {
2825 win_skip("CertGetValidUsages() is not available\n");
2826 return;
2827 }
2828
2829 /* Crash
2830 ret = pCertGetValidUsages(0, NULL, NULL, NULL, NULL);
2831 ret = pCertGetValidUsages(0, NULL, NULL, NULL, &size);
2832 */
2833 contexts[0] = NULL;
2834 numOIDs = size = 0xdeadbeef;
2835 SetLastError(0xdeadbeef);
2836 ret = pCertGetValidUsages(1, &contexts[0], &numOIDs, NULL, &size);
2837 ok(ret, "CertGetValidUsages failed: %d\n", GetLastError());
2838 ok(numOIDs == -1, "Expected -1, got %d\n", numOIDs);
2839 ok(size == 0, "Expected size 0, got %d\n", size);
2840 contexts[0] = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert,
2841 sizeof(bigCert));
2842 contexts[1] = CertCreateCertificateContext(X509_ASN_ENCODING, certWithUsage,
2843 sizeof(certWithUsage));
2844 contexts[2] = CertCreateCertificateContext(X509_ASN_ENCODING,
2845 cert2WithUsage, sizeof(cert2WithUsage));
2846 numOIDs = size = 0xdeadbeef;
2847 ret = pCertGetValidUsages(0, NULL, &numOIDs, NULL, &size);
2848 ok(ret, "CertGetValidUsages failed: %08x\n", GetLastError());
2849 ok(numOIDs == -1, "Expected -1, got %d\n", numOIDs);
2850 ok(size == 0, "Expected size 0, got %d\n", size);
2851 numOIDs = size = 0xdeadbeef;
2852 ret = pCertGetValidUsages(1, contexts, &numOIDs, NULL, &size);
2853 ok(ret, "CertGetValidUsages failed: %08x\n", GetLastError());
2854 ok(numOIDs == -1, "Expected -1, got %d\n", numOIDs);
2855 ok(size == 0, "Expected size 0, got %d\n", size);
2856 ret = pCertGetValidUsages(1, &contexts[1], &numOIDs, NULL, &size);
2857 ok(ret, "CertGetValidUsages failed: %08x\n", GetLastError());
2858 ok(numOIDs == 3, "Expected 3, got %d\n", numOIDs);
2859 ok(size, "Expected non-zero size\n");
2860 oids = HeapAlloc(GetProcessHeap(), 0, size);
2861 if (oids)
2862 {
2863 int i;
2864 DWORD smallSize = 1;
2865
2866 SetLastError(0xdeadbeef);
2867 ret = pCertGetValidUsages(1, &contexts[1], &numOIDs, oids, &smallSize);
2868 ok(!ret && GetLastError() == ERROR_MORE_DATA,
2869 "Expected ERROR_MORE_DATA, got %d\n", GetLastError());
2870 ret = pCertGetValidUsages(1, &contexts[1], &numOIDs, oids, &size);
2871 ok(ret, "CertGetValidUsages failed: %08x\n", GetLastError());
2872 for (i = 0; i < numOIDs; i++)
2873 ok(!lstrcmpA(oids[i], expectedOIDs[i]), "unexpected OID %s\n",
2874 oids[i]);
2875 HeapFree(GetProcessHeap(), 0, oids);
2876 }
2877 numOIDs = 0xdeadbeef;
2878 /* Oddly enough, this crashes when the number of contexts is not 1:
2879 ret = pCertGetValidUsages(2, contexts, &numOIDs, NULL, &size);
2880 * but setting size to 0 allows it to succeed:
2881 */
2882 size = 0;
2883 ret = pCertGetValidUsages(2, contexts, &numOIDs, NULL, &size);
2884 ok(ret, "CertGetValidUsages failed: %08x\n", GetLastError());
2885 ok(numOIDs == 3, "Expected 3, got %d\n", numOIDs);
2886 ok(size, "Expected non-zero size\n");
2887 oids = HeapAlloc(GetProcessHeap(), 0, size);
2888 if (oids)
2889 {
2890 int i;
2891
2892 ret = pCertGetValidUsages(1, &contexts[1], &numOIDs, oids, &size);
2893 ok(ret, "CertGetValidUsages failed: %08x\n", GetLastError());
2894 for (i = 0; i < numOIDs; i++)
2895 ok(!lstrcmpA(oids[i], expectedOIDs[i]), "unexpected OID %s\n",
2896 oids[i]);
2897 HeapFree(GetProcessHeap(), 0, oids);
2898 }
2899 numOIDs = 0xdeadbeef;
2900 size = 0;
2901 ret = pCertGetValidUsages(1, &contexts[2], &numOIDs, NULL, &size);
2902 ok(ret, "CertGetValidUsages failed: %08x\n", GetLastError());
2903 ok(numOIDs == 2, "Expected 2, got %d\n", numOIDs);
2904 ok(size, "Expected non-zero size\n");
2905 oids = HeapAlloc(GetProcessHeap(), 0, size);
2906 if (oids)
2907 {
2908 int i;
2909
2910 ret = pCertGetValidUsages(1, &contexts[2], &numOIDs, oids, &size);
2911 ok(ret, "CertGetValidUsages failed: %08x\n", GetLastError());
2912 for (i = 0; i < numOIDs; i++)
2913 ok(!lstrcmpA(oids[i], expectedOIDs2[i]), "unexpected OID %s\n",
2914 oids[i]);
2915 HeapFree(GetProcessHeap(), 0, oids);
2916 }
2917 numOIDs = 0xdeadbeef;
2918 size = 0;
2919 ret = pCertGetValidUsages(3, contexts, &numOIDs, NULL, &size);
2920 ok(ret, "CertGetValidUsages failed: %08x\n", GetLastError());
2921 ok(numOIDs == 2, "Expected 2, got %d\n", numOIDs);
2922 ok(size, "Expected non-zero size\n");
2923 oids = HeapAlloc(GetProcessHeap(), 0, size);
2924 if (oids)
2925 {
2926 int i;
2927
2928 ret = pCertGetValidUsages(3, contexts, &numOIDs, oids, &size);
2929 ok(ret, "CertGetValidUsages failed: %08x\n", GetLastError());
2930 for (i = 0; i < numOIDs; i++)
2931 ok(!lstrcmpA(oids[i], expectedOIDs2[i]), "unexpected OID %s\n",
2932 oids[i]);
2933 HeapFree(GetProcessHeap(), 0, oids);
2934 }
2935 CertFreeCertificateContext(contexts[0]);
2936 CertFreeCertificateContext(contexts[1]);
2937 CertFreeCertificateContext(contexts[2]);
2938 }
2939
2940 static BYTE cn[] = {
2941 0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,0x55,0x04,0x03,0x13,0x09,0x4a,0x75,
2942 0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67 };
2943 static BYTE cnWithLeadingSpace[] = {
2944 0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x20,0x4a,
2945 0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67 };
2946 static BYTE cnWithTrailingSpace[] = {
2947 0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,
2948 0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x20 };
2949 static BYTE cnWithIntermediateSpace[] = {
2950 0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,
2951 0x61,0x6e,0x20,0x20,0x4c,0x61,0x6e,0x67 };
2952 static BYTE cnThenO[] = {
2953 0x30,0x2d,0x31,0x2b,0x30,0x10,0x06,0x03,0x55,0x04,0x03,0x13,0x09,0x4a,0x75,
2954 0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x30,0x17,0x06,0x03,0x55,0x04,0x0a,0x13,
2955 0x10,0x54,0x68,0x65,0x20,0x57,0x69,0x6e,0x65,0x20,0x50,0x72,0x6f,0x6a,0x65,
2956 0x63,0x74 };
2957 static BYTE oThenCN[] = {
2958 0x30,0x2d,0x31,0x2b,0x30,0x10,0x06,0x03,0x55,0x04,0x0a,0x13,0x09,0x4a,0x75,
2959 0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x30,0x17,0x06,0x03,0x55,0x04,0x03,0x13,
2960 0x10,0x54,0x68,0x65,0x20,0x57,0x69,0x6e,0x65,0x20,0x50,0x72,0x6f,0x6a,0x65,
2961 0x63,0x74 };
2962
2963 static void testCompareCertName(void)
2964 {
2965 static BYTE bogus[] = { 1, 2, 3, 4 };
2966 static BYTE bogusPrime[] = { 0, 1, 2, 3, 4 };
2967 static BYTE emptyPrime[] = { 0x30, 0x00, 0x01 };
2968 BOOL ret;
2969 CERT_NAME_BLOB blob1, blob2;
2970
2971 /* crashes
2972 ret = CertCompareCertificateName(0, NULL, NULL);
2973 */
2974 /* An empty name checks against itself.. */
2975 blob1.pbData = emptyCert;
2976 blob1.cbData = sizeof(emptyCert);
2977 ret = CertCompareCertificateName(0, &blob1, &blob1);
2978 ok(ret, "CertCompareCertificateName failed: %08x\n", GetLastError());
2979 /* It doesn't have to be a valid encoded name.. */
2980 blob1.pbData = bogus;
2981 blob1.cbData = sizeof(bogus);
2982 ret = CertCompareCertificateName(0, &blob1, &blob1);
2983 ok(ret, "CertCompareCertificateName failed: %08x\n", GetLastError());
2984 /* Leading zeroes matter.. */
2985 blob2.pbData = bogusPrime;
2986 blob2.cbData = sizeof(bogusPrime);
2987 ret = CertCompareCertificateName(0, &blob1, &blob2);
2988 ok(!ret, "Expected failure\n");
2989 /* As do trailing extra bytes. */
2990 blob2.pbData = emptyPrime;
2991 blob2.cbData = sizeof(emptyPrime);
2992 ret = CertCompareCertificateName(0, &blob1, &blob2);
2993 ok(!ret, "Expected failure\n");
2994 /* Tests to show that CertCompareCertificateName doesn't decode the name
2995 * to remove spaces, or to do an order-independent comparison.
2996 */
2997 /* Compare CN="Juan Lang" with CN=" Juan Lang" */
2998 blob1.pbData = cn;
2999 blob1.cbData = sizeof(cn);
3000 blob2.pbData = cnWithLeadingSpace;
3001 blob2.cbData = sizeof(cnWithLeadingSpace);
3002 ret = CertCompareCertificateName(0, &blob1, &blob2);
3003 ok(!ret, "Expected failure\n");
3004 ret = CertCompareCertificateName(X509_ASN_ENCODING, &blob1, &blob2);
3005 ok(!ret, "Expected failure\n");
3006 /* Compare CN="Juan Lang" with CN="Juan Lang " */
3007 blob2.pbData = cnWithTrailingSpace;
3008 blob2.cbData = sizeof(cnWithTrailingSpace);
3009 ret = CertCompareCertificateName(0, &blob1, &blob2);
3010 ok(!ret, "Expected failure\n");
3011 ret = CertCompareCertificateName(X509_ASN_ENCODING, &blob1, &blob2);
3012 ok(!ret, "Expected failure\n");
3013 /* Compare CN="Juan Lang" with CN="Juan Lang" */
3014 blob2.pbData = cnWithIntermediateSpace;
3015 blob2.cbData = sizeof(cnWithIntermediateSpace);
3016 ret = CertCompareCertificateName(0, &blob1, &blob2);
3017 ok(!ret, "Expected failure\n");
3018 ret = CertCompareCertificateName(X509_ASN_ENCODING, &blob1, &blob2);
3019 ok(!ret, "Expected failure\n");
3020 /* Compare 'CN="Juan Lang", O="The Wine Project"' with
3021 * 'O="The Wine Project", CN="Juan Lang"'
3022 */
3023 blob1.pbData = cnThenO;
3024 blob1.cbData = sizeof(cnThenO);
3025 blob2.pbData = oThenCN;
3026 blob2.cbData = sizeof(oThenCN);
3027 ret = CertCompareCertificateName(0, &blob1, &blob2);
3028 ok(!ret, "Expected failure\n");
3029 ret = CertCompareCertificateName(X509_ASN_ENCODING, &blob1, &blob2);
3030 ok(!ret, "Expected failure\n");
3031 }
3032
3033 static void testIsRDNAttrsInCertificateName(void)
3034 {
3035 static char oid_1_2_3[] = "1.2.3";
3036 static char oid_common_name[] = szOID_COMMON_NAME;
3037 static char oid_organization[] = szOID_ORGANIZATION_NAME;
3038 static char juan[] = "Juan Lang";
3039 static char juan_with_leading_space[] = " Juan Lang";
3040 static char juan_with_intermediate_space[] = "Juan Lang";
3041 static char juan_with_trailing_space[] = "Juan Lang ";
3042 static char juan_lower_case[] = "juan lang";
3043 static WCHAR juanW[] = { 'J','u','a','n',' ','L','a','n','g',0 };
3044 static char the_wine_project[] = "The Wine Project";
3045 BOOL ret;
3046 CERT_NAME_BLOB name;
3047 CERT_RDN_ATTR attr[2];
3048 CERT_RDN rdn = { 0, NULL };
3049
3050 name.cbData = sizeof(cn);
3051 name.pbData = cn;
3052 if (0)
3053 {
3054 /* Crash */
3055 CertIsRDNAttrsInCertificateName(0, 0, NULL, NULL);
3056 CertIsRDNAttrsInCertificateName(X509_ASN_ENCODING, 0, &name, NULL);
3057 }
3058 SetLastError(0xdeadbeef);
3059 ret = CertIsRDNAttrsInCertificateName(0, 0, &name, NULL);
3060 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
3061 "expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
3062 ret = CertIsRDNAttrsInCertificateName(X509_ASN_ENCODING, 0, &name, &rdn);
3063 ok(ret, "CertIsRDNAttrsInCertificateName failed: %08x\n", GetLastError());
3064 attr[0].pszObjId = oid_1_2_3;
3065 rdn.rgRDNAttr = attr;
3066 rdn.cRDNAttr = 1;
3067 SetLastError(0xdeadbeef);
3068 ret = CertIsRDNAttrsInCertificateName(X509_ASN_ENCODING, 0, &name, &rdn);
3069 ok(!ret && GetLastError() == CRYPT_E_NO_MATCH,
3070 "expected CRYPT_E_NO_MATCH, got %08x\n", GetLastError());
3071 attr[0].pszObjId = oid_common_name;
3072 attr[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
3073 attr[0].Value.cbData = strlen(juan);
3074 attr[0].Value.pbData = (BYTE *)juan;
3075 ret = CertIsRDNAttrsInCertificateName(X509_ASN_ENCODING, 0, &name, &rdn);
3076 ok(ret, "CertIsRDNAttrsInCertificateName failed: %08x\n", GetLastError());
3077 /* Again, spaces are not removed for name comparison. */
3078 attr[0].Value.cbData = strlen(juan_with_leading_space);
3079 attr[0].Value.pbData = (BYTE *)juan_with_leading_space;
3080 SetLastError(0xdeadbeef);
3081 ret = CertIsRDNAttrsInCertificateName(X509_ASN_ENCODING, 0, &name, &rdn);
3082 ok(!ret && GetLastError() == CRYPT_E_NO_MATCH,
3083 "expected CRYPT_E_NO_MATCH, got %08x\n", GetLastError());
3084 attr[0].Value.cbData = strlen(juan_with_intermediate_space);
3085 attr[0].Value.pbData = (BYTE *)juan_with_intermediate_space;
3086 SetLastError(0xdeadbeef);
3087 ret = CertIsRDNAttrsInCertificateName(X509_ASN_ENCODING, 0, &name, &rdn);
3088 ok(!ret && GetLastError() == CRYPT_E_NO_MATCH,
3089 "expected CRYPT_E_NO_MATCH, got %08x\n", GetLastError());
3090 attr[0].Value.cbData = strlen(juan_with_trailing_space);
3091 attr[0].Value.pbData = (BYTE *)juan_with_trailing_space;
3092 SetLastError(0xdeadbeef);
3093 ret = CertIsRDNAttrsInCertificateName(X509_ASN_ENCODING, 0, &name, &rdn);
3094 ok(!ret && GetLastError() == CRYPT_E_NO_MATCH,
3095 "expected CRYPT_E_NO_MATCH, got %08x\n", GetLastError());
3096 /* The lower case name isn't matched unless a case insensitive match is
3097 * specified.
3098 */
3099 attr[0].Value.cbData = strlen(juan_lower_case);
3100 attr[0].Value.pbData = (BYTE *)juan_lower_case;
3101 SetLastError(0xdeadbeef);
3102 ret = CertIsRDNAttrsInCertificateName(X509_ASN_ENCODING, 0, &name, &rdn);
3103 ok(!ret && GetLastError() == CRYPT_E_NO_MATCH,
3104 "expected CRYPT_E_NO_MATCH, got %08x\n", GetLastError());
3105 ret = CertIsRDNAttrsInCertificateName(X509_ASN_ENCODING,
3106 CERT_CASE_INSENSITIVE_IS_RDN_ATTRS_FLAG, &name, &rdn);
3107 ok(ret ||
3108 broken(!ret && GetLastError() == CRYPT_E_NO_MATCH), /* Older crypt32 */
3109 "CertIsRDNAttrsInCertificateName failed: %08x\n", GetLastError());
3110 /* The values don't match unless they have the same RDN type */
3111 attr[0].dwValueType = CERT_RDN_UNICODE_STRING;
3112 attr[0].Value.cbData = lstrlenW(juanW) * sizeof(WCHAR);
3113 attr[0].Value.pbData = (BYTE *)juanW;
3114 SetLastError(0xdeadbeef);
3115 ret = CertIsRDNAttrsInCertificateName(X509_ASN_ENCODING, 0, &name, &rdn);
3116 ok(!ret && GetLastError() == CRYPT_E_NO_MATCH,
3117 "expected CRYPT_E_NO_MATCH, got %08x\n", GetLastError());
3118 SetLastError(0xdeadbeef);
3119 ret = CertIsRDNAttrsInCertificateName(X509_ASN_ENCODING,
3120 CERT_UNICODE_IS_RDN_ATTRS_FLAG, &name, &rdn);
3121 ok(!ret && GetLastError() == CRYPT_E_NO_MATCH,
3122 "expected CRYPT_E_NO_MATCH, got %08x\n", GetLastError());
3123 attr[0].dwValueType = CERT_RDN_IA5_STRING;
3124 attr[0].Value.cbData = strlen(juan);
3125 attr[0].Value.pbData = (BYTE *)juan;
3126 SetLastError(0xdeadbeef);
3127 ret = CertIsRDNAttrsInCertificateName(X509_ASN_ENCODING, 0, &name, &rdn);
3128 ok(!ret && GetLastError() == CRYPT_E_NO_MATCH,
3129 "expected CRYPT_E_NO_MATCH, got %08x\n", GetLastError());
3130 /* All attributes must be present */
3131 attr[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
3132 attr[0].Value.cbData = strlen(juan);
3133 attr[0].Value.pbData = (BYTE *)juan;
3134 attr[1].pszObjId = oid_organization;
3135 attr[1].dwValueType = CERT_RDN_PRINTABLE_STRING;
3136 attr[1].Value.cbData = strlen(the_wine_project);
3137 attr[1].Value.pbData = (BYTE *)the_wine_project;
3138 rdn.cRDNAttr = 2;
3139 SetLastError(0xdeadbeef);
3140 ret = CertIsRDNAttrsInCertificateName(X509_ASN_ENCODING, 0, &name, &rdn);
3141 ok(!ret && GetLastError() == CRYPT_E_NO_MATCH,
3142 "expected CRYPT_E_NO_MATCH, got %08x\n", GetLastError());
3143 /* Order also matters */
3144 name.pbData = cnThenO;
3145 name.cbData = sizeof(cnThenO);
3146 ret = CertIsRDNAttrsInCertificateName(X509_ASN_ENCODING, 0, &name, &rdn);
3147 ok(ret, "CertIsRDNAttrsInCertificateName failed: %08x\n", GetLastError());
3148 name.pbData = oThenCN;
3149 name.cbData = sizeof(oThenCN);
3150 SetLastError(0xdeadbeef);
3151 ret = CertIsRDNAttrsInCertificateName(X509_ASN_ENCODING, 0, &name, &rdn);
3152 ok(!ret && GetLastError() == CRYPT_E_NO_MATCH,
3153 "expected CRYPT_E_NO_MATCH, got %08x\n", GetLastError());
3154 }
3155
3156 static BYTE int1[] = { 0x88, 0xff, 0xff, 0xff };
3157 static BYTE int2[] = { 0x88, 0xff };
3158 static BYTE int3[] = { 0x23, 0xff };
3159 static BYTE int4[] = { 0x7f, 0x00 };
3160 static BYTE int5[] = { 0x7f };
3161 static BYTE int6[] = { 0x80, 0x00, 0x00, 0x00 };
3162 static BYTE int7[] = { 0x80, 0x00 };
3163
3164 static struct IntBlobTest
3165 {
3166 CRYPT_INTEGER_BLOB blob1;
3167 CRYPT_INTEGER_BLOB blob2;
3168 BOOL areEqual;
3169 } intBlobs[] = {
3170 { { sizeof(int1), int1 }, { sizeof(int2), int2 }, TRUE },
3171 { { sizeof(int3), int3 }, { sizeof(int3), int3 }, TRUE },
3172 { { sizeof(int4), int4 }, { sizeof(int5), int5 }, TRUE },
3173 { { sizeof(int6), int6 }, { sizeof(int7), int7 }, TRUE },
3174 { { sizeof(int1), int1 }, { sizeof(int7), int7 }, FALSE },
3175 };
3176
3177 static void testCompareIntegerBlob(void)
3178 {
3179 DWORD i;
3180 BOOL ret;
3181
3182 for (i = 0; i < sizeof(intBlobs) / sizeof(intBlobs[0]); i++)
3183 {
3184 ret = CertCompareIntegerBlob(&intBlobs[i].blob1, &intBlobs[i].blob2);
3185 ok(ret == intBlobs[i].areEqual,
3186 "%d: expected blobs %s compare\n", i, intBlobs[i].areEqual ?
3187 "to" : "not to");
3188 }
3189 }
3190
3191 static void testComparePublicKeyInfo(void)
3192 {
3193 BOOL ret;
3194 CERT_PUBLIC_KEY_INFO info1 = { { 0 } }, info2 = { { 0 } };
3195 static CHAR oid_rsa_rsa[] = szOID_RSA_RSA;
3196 static CHAR oid_rsa_sha1rsa[] = szOID_RSA_SHA1RSA;
3197 static CHAR oid_x957_dsa[] = szOID_X957_DSA;
3198 static BYTE bits1[] = { 1, 0 };
3199 static BYTE bits2[] = { 0 };
3200 static BYTE bits3[] = { 1 };
3201 static BYTE bits4[] = { 0x30,8, 2,1,0x81, 2,3,1,0,1 };
3202 static BYTE bits5[] = { 0x30,9, 2,2,0,0x81, 2,3,1,0,1 };
3203 static BYTE bits6[] = { 0x30,9, 2,2,0,0x82, 2,3,1,0,1 };
3204
3205 /* crashes
3206 ret = CertComparePublicKeyInfo(0, NULL, NULL);
3207 */
3208 /* Empty public keys compare */
3209 ret = CertComparePublicKeyInfo(0, &info1, &info2);
3210 ok(ret, "CertComparePublicKeyInfo failed: %08x\n", GetLastError());
3211 /* Different OIDs appear to compare */
3212 info1.Algorithm.pszObjId = oid_rsa_rsa;
3213 info2.Algorithm.pszObjId = oid_rsa_sha1rsa;
3214 ret = CertComparePublicKeyInfo(0, &info1, &info2);
3215 ok(ret, "CertComparePublicKeyInfo failed: %08x\n", GetLastError());
3216 info2.Algorithm.pszObjId = oid_x957_dsa;
3217 ret = CertComparePublicKeyInfo(0, &info1, &info2);
3218 ok(ret, "CertComparePublicKeyInfo failed: %08x\n", GetLastError());
3219 info1.PublicKey.cbData = sizeof(bits1);
3220 info1.PublicKey.pbData = bits1;
3221 info1.PublicKey.cUnusedBits = 0;
3222 info2.PublicKey.cbData = sizeof(bits1);
3223 info2.PublicKey.pbData = bits1;
3224 info2.PublicKey.cUnusedBits = 0;
3225 ret = CertComparePublicKeyInfo(0, &info1, &info2);
3226 ok(ret, "CertComparePublicKeyInfo failed: %08x\n", GetLastError());
3227 info2.Algorithm.pszObjId = oid_rsa_rsa;
3228 info1.PublicKey.cbData = sizeof(bits4);
3229 info1.PublicKey.pbData = bits4;
3230 info1.PublicKey.cUnusedBits = 0;
3231 info2.PublicKey.cbData = sizeof(bits5);
3232 info2.PublicKey.pbData = bits5;
3233 info2.PublicKey.cUnusedBits = 0;
3234 ret = CertComparePublicKeyInfo(0, &info1, &info2);
3235 ok(!ret, "CertComparePublicKeyInfo: as raw binary: keys should be unequal\n");
3236 ret = CertComparePublicKeyInfo(X509_ASN_ENCODING, &info1, &info2);
3237 ok(ret ||
3238 broken(!ret), /* win9x */
3239 "CertComparePublicKeyInfo: as ASN.1 encoded: keys should be equal\n");
3240 info1.PublicKey.cUnusedBits = 1;
3241 info2.PublicKey.cUnusedBits = 5;
3242 ret = CertComparePublicKeyInfo(X509_ASN_ENCODING, &info1, &info2);
3243 ok(ret ||
3244 broken(!ret), /* win9x */
3245 "CertComparePublicKeyInfo: ASN.1 encoding should ignore cUnusedBits\n");
3246 info1.PublicKey.cUnusedBits = 0;
3247 info2.PublicKey.cUnusedBits = 0;
3248 info1.PublicKey.cbData--; /* kill one byte, make ASN.1 encoded data invalid */
3249 ret = CertComparePublicKeyInfo(X509_ASN_ENCODING, &info1, &info2);
3250 ok(!ret, "CertComparePublicKeyInfo: comparing bad ASN.1 encoded key should fail\n");
3251 /* Even though they compare in their used bits, these do not compare */
3252 info1.PublicKey.cbData = sizeof(bits2);
3253 info1.PublicKey.pbData = bits2;
3254 info1.PublicKey.cUnusedBits = 0;
3255 info2.PublicKey.cbData = sizeof(bits3);
3256 info2.PublicKey.pbData = bits3;
3257 info2.PublicKey.cUnusedBits = 1;
3258 ret = CertComparePublicKeyInfo(0, &info1, &info2);
3259 /* Simple (non-comparing) case */
3260 ok(!ret, "Expected keys not to compare\n");
3261 info2.PublicKey.cbData = sizeof(bits1);
3262 info2.PublicKey.pbData = bits1;
3263 info2.PublicKey.cUnusedBits = 0;
3264 ret = CertComparePublicKeyInfo(0, &info1, &info2);
3265 ok(!ret, "Expected keys not to compare\n");
3266 /* ASN.1 encoded non-comparing case */
3267 info1.PublicKey.cbData = sizeof(bits5);
3268 info1.PublicKey.pbData = bits5;
3269 info1.PublicKey.cUnusedBits = 0;
3270 info2.PublicKey.cbData = sizeof(bits6);
3271 info2.PublicKey.pbData = bits6;
3272 info2.PublicKey.cUnusedBits = 0;
3273 ret = CertComparePublicKeyInfo(X509_ASN_ENCODING, &info1, &info2);
3274 ok(!ret, "CertComparePublicKeyInfo: different keys should be unequal\n");
3275 }
3276
3277 static void testHashPublicKeyInfo(void)
3278 {
3279 BOOL ret;
3280 CERT_PUBLIC_KEY_INFO info = { { 0 } };
3281 DWORD len;
3282
3283 /* Crash
3284 ret = CryptHashPublicKeyInfo(0, 0, 0, 0, NULL, NULL, NULL);
3285 ret = CryptHashPublicKeyInfo(0, 0, 0, 0, &info, NULL, NULL);
3286 */
3287 ret = CryptHashPublicKeyInfo(0, 0, 0, 0, NULL, NULL, &len);
3288 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
3289 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
3290 /* Crashes on some win9x boxes */
3291 if (0)
3292 {
3293 ret = CryptHashPublicKeyInfo(0, 0, 0, X509_ASN_ENCODING, NULL, NULL, &len);
3294 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
3295 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
3296 }
3297 ret = CryptHashPublicKeyInfo(0, 0, 0, X509_ASN_ENCODING, &info, NULL, &len);
3298 ok(ret ||
3299 broken(!ret), /* win9x */
3300 "CryptHashPublicKeyInfo failed: %08x\n", GetLastError());
3301 if (ret)
3302 {
3303 ok(len == 16, "Expected hash size 16, got %d\n", len);
3304 if (len == 16)
3305 {
3306 static const BYTE emptyHash[] = { 0xb8,0x51,0x3a,0x31,0x0e,0x9f,0x40,
3307 0x36,0x9c,0x92,0x45,0x1b,0x9d,0xc8,0xf9,0xf6 };
3308 BYTE buf[16];
3309
3310 ret = CryptHashPublicKeyInfo(0, 0, 0, X509_ASN_ENCODING, &info, buf,
3311 &len);
3312 ok(ret, "CryptHashPublicKeyInfo failed: %08x\n", GetLastError());
3313 ok(!memcmp(buf, emptyHash, len), "Unexpected hash\n");
3314 }
3315 }
3316 }
3317
3318 static const BYTE md5SignedEmptyCertHash[] = { 0xfb,0x0f,0x66,0x82,0x66,0xd9,
3319 0xe5,0xf8,0xd8,0xa2,0x55,0x2b,0xe1,0xa5,0xd9,0x04 };
3320
3321 static void testHashToBeSigned(void)
3322 {
3323 BOOL ret;
3324 DWORD size;
3325 BYTE hash[16];
3326
3327 /* Crash */
3328 if (0)
3329 {
3330 CryptHashToBeSigned(0, 0, NULL, 0, NULL, NULL);
3331 }
3332 SetLastError(0xdeadbeef);
3333 ret = CryptHashToBeSigned(0, 0, NULL, 0, NULL, &size);
3334 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
3335 "expected ERROR_FILE_NOT_FOUND, got %d\n", GetLastError());
3336 SetLastError(0xdeadbeef);
3337 ret = CryptHashToBeSigned(0, X509_ASN_ENCODING, NULL, 0, NULL, &size);
3338 ok(!ret &&
3339 (GetLastError() == CRYPT_E_ASN1_EOD ||
3340 GetLastError() == OSS_BAD_ARG), /* win9x */
3341 "expected CRYPT_E_ASN1_EOD, got %08x\n", GetLastError());
3342 /* Can't sign anything: has to be asn.1 encoded, at least */
3343 SetLastError(0xdeadbeef);
3344 ret = CryptHashToBeSigned(0, X509_ASN_ENCODING, int1, sizeof(int1),
3345 NULL, &size);
3346 ok(!ret &&
3347 (GetLastError() == CRYPT_E_ASN1_BADTAG ||
3348 GetLastError() == OSS_MORE_INPUT), /* win9x */
3349 "expected CRYPT_E_ASN1_BADTAG, got %08x\n", GetLastError());
3350 /* Can't be empty, either */
3351 SetLastError(0xdeadbeef);
3352 ret = CryptHashToBeSigned(0, X509_ASN_ENCODING, emptyCert,
3353 sizeof(emptyCert), NULL, &size);
3354 ok(!ret &&
3355 (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
3356 GetLastError() == OSS_DATA_ERROR), /* win9x */
3357 "expected CRYPT_E_ASN1_CORRUPT, got %08x\n", GetLastError());
3358 /* Signing a cert works */
3359 ret = CryptHashToBeSigned(0, X509_ASN_ENCODING, md5SignedEmptyCert,
3360 sizeof(md5SignedEmptyCert), NULL, &size);
3361 ok(ret ||
3362 broken(!ret), /* win9x */
3363 "CryptHashToBeSigned failed: %08x\n", GetLastError());
3364 if (ret)
3365 {
3366 ok(size == sizeof(md5SignedEmptyCertHash), "unexpected size %d\n", size);
3367 }
3368
3369 ret = CryptHashToBeSigned(0, X509_ASN_ENCODING, md5SignedEmptyCert,
3370 sizeof(md5SignedEmptyCert), hash, &size);
3371 ok(ret || broken(!ret && GetLastError() == NTE_BAD_ALGID) /* NT4 */,
3372 "CryptHashToBeSigned failed: %08x\n", GetLastError());
3373
3374 ok(!memcmp(hash, md5SignedEmptyCertHash, size), "unexpected value\n");
3375 }
3376
3377 static void testCompareCert(void)
3378 {
3379 CERT_INFO info1 = { 0 }, info2 = { 0 };
3380 BOOL ret;
3381
3382 /* Crashes */
3383 if (0)
3384 CertCompareCertificate(X509_ASN_ENCODING, NULL, NULL);
3385
3386 /* Certs with the same issuer and serial number are equal, even if they
3387 * differ in other respects (like subject).
3388 */
3389 info1.SerialNumber.pbData = serialNum;
3390 info1.SerialNumber.cbData = sizeof(serialNum);
3391 info1.Issuer.pbData = subjectName;
3392 info1.Issuer.cbData = sizeof(subjectName);
3393 info1.Subject.pbData = subjectName2;
3394 info1.Subject.cbData = sizeof(subjectName2);
3395 info2.SerialNumber.pbData = serialNum;
3396 info2.SerialNumber.cbData = sizeof(serialNum);
3397 info2.Issuer.pbData = subjectName;
3398 info2.Issuer.cbData = sizeof(subjectName);
3399 info2.Subject.pbData = subjectName;
3400 info2.Subject.cbData = sizeof(subjectName);
3401 ret = CertCompareCertificate(X509_ASN_ENCODING, &info1, &info2);
3402 ok(ret, "Expected certs to be equal\n");
3403
3404 info2.Issuer.pbData = subjectName2;
3405 info2.Issuer.cbData = sizeof(subjectName2);
3406 ret = CertCompareCertificate(X509_ASN_ENCODING, &info1, &info2);
3407 ok(!ret, "Expected certs not to be equal\n");
3408 }
3409
3410 static void testVerifySubjectCert(void)
3411 {
3412 BOOL ret;
3413 DWORD flags;
3414 PCCERT_CONTEXT context1, context2;
3415
3416 /* Crashes
3417 ret = CertVerifySubjectCertificateContext(NULL, NULL, NULL);
3418 */
3419 flags = 0;
3420 ret = CertVerifySubjectCertificateContext(NULL, NULL, &flags);
3421 ok(ret, "CertVerifySubjectCertificateContext failed; %08x\n",
3422 GetLastError());
3423 flags = CERT_STORE_NO_CRL_FLAG;
3424 ret = CertVerifySubjectCertificateContext(NULL, NULL, &flags);
3425 ok(!ret && GetLastError() == E_INVALIDARG,
3426 "Expected E_INVALIDARG, got %08x\n", GetLastError());
3427
3428 flags = 0;
3429 context1 = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert,
3430 sizeof(bigCert));
3431 ret = CertVerifySubjectCertificateContext(NULL, context1, &flags);
3432 ok(ret, "CertVerifySubjectCertificateContext failed; %08x\n",
3433 GetLastError());
3434 ret = CertVerifySubjectCertificateContext(context1, NULL, &flags);
3435 ok(ret, "CertVerifySubjectCertificateContext failed; %08x\n",
3436 GetLastError());
3437 ret = CertVerifySubjectCertificateContext(context1, context1, &flags);
3438 ok(ret, "CertVerifySubjectCertificateContext failed; %08x\n",
3439 GetLastError());
3440
3441 context2 = CertCreateCertificateContext(X509_ASN_ENCODING,
3442 bigCertWithDifferentSubject, sizeof(bigCertWithDifferentSubject));
3443 SetLastError(0xdeadbeef);
3444 ret = CertVerifySubjectCertificateContext(context1, context2, &flags);
3445 ok(ret, "CertVerifySubjectCertificateContext failed; %08x\n",
3446 GetLastError());
3447 flags = CERT_STORE_REVOCATION_FLAG;
3448 ret = CertVerifySubjectCertificateContext(context1, context2, &flags);
3449 ok(ret, "CertVerifySubjectCertificateContext failed; %08x\n",
3450 GetLastError());
3451 ok(flags == (CERT_STORE_REVOCATION_FLAG | CERT_STORE_NO_CRL_FLAG),
3452 "Expected CERT_STORE_REVOCATION_FLAG | CERT_STORE_NO_CRL_FLAG, got %08x\n",
3453 flags);
3454 flags = CERT_STORE_SIGNATURE_FLAG;
3455 ret = CertVerifySubjectCertificateContext(context1, context2, &flags);
3456 ok(ret, "CertVerifySubjectCertificateContext failed; %08x\n",
3457 GetLastError());
3458 ok(flags == CERT_STORE_SIGNATURE_FLAG,
3459 "Expected CERT_STORE_SIGNATURE_FLAG, got %08x\n", flags);
3460 CertFreeCertificateContext(context2);
3461
3462 CertFreeCertificateContext(context1);
3463 }
3464
3465 static const BYTE rootWithKeySignAndCRLSign[] = {
3466 0x30,0x82,0x01,0xdf,0x30,0x82,0x01,0x4c,0xa0,0x03,0x02,0x01,0x02,0x02,0x10,
3467 0x5b,0xc7,0x0b,0x27,0x99,0xbb,0x2e,0x99,0x47,0x9d,0x45,0x4e,0x7c,0x1a,0xca,
3468 0xe8,0x30,0x09,0x06,0x05,0x2b,0x0e,0x03,0x02,0x1d,0x05,0x00,0x30,0x10,0x31,
3469 0x0e,0x30,0x0c,0x06,0x03,0x55,0x04,0x03,0x13,0x05,0x43,0x65,0x72,0x74,0x31,
3470 0x30,0x1e,0x17,0x0d,0x30,0x37,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
3471 0x30,0x5a,0x17,0x0d,0x30,0x37,0x31,0x32,0x33,0x31,0x32,0x33,0x35,0x39,0x35,
3472 0x39,0x5a,0x30,0x10,0x31,0x0e,0x30,0x0c,0x06,0x03,0x55,0x04,0x03,0x13,0x05,
3473 0x43,0x65,0x72,0x74,0x31,0x30,0x81,0x9f,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,
3474 0x86,0xf7,0x0d,0x01,0x01,0x01,0x05,0x00,0x03,0x81,0x8d,0x00,0x30,0x81,0x89,
3475 0x02,0x81,0x81,0x00,0xad,0x7e,0xca,0xf3,0xe5,0x99,0xc2,0x2a,0xca,0x50,0x82,
3476 0x7c,0x2d,0xa4,0x81,0xcd,0x0d,0x0d,0x86,0xd7,0xd8,0xb2,0xde,0xc5,0xc3,0x34,
3477 0x9e,0x07,0x78,0x08,0x11,0x12,0x2d,0x21,0x0a,0x09,0x07,0x14,0x03,0x7a,0xe7,
3478 0x3b,0x58,0xf1,0xde,0x3e,0x01,0x25,0x93,0xab,0x8f,0xce,0x1f,0xc1,0x33,0x91,
3479 0xfe,0x59,0xb9,0x3b,0x9e,0x95,0x12,0x89,0x8e,0xc3,0x4b,0x98,0x1b,0x99,0xc5,
3480 0x07,0xe2,0xdf,0x15,0x4c,0x39,0x76,0x06,0xad,0xdb,0x16,0x06,0x49,0xba,0xcd,
3481 0x0f,0x07,0xd6,0xea,0x27,0xa6,0xfe,0x3d,0x88,0xe5,0x97,0x45,0x72,0xb6,0x1c,
3482 0xc0,0x1c,0xb1,0xa2,0x89,0xe8,0x37,0x9e,0xf6,0x2a,0xcf,0xd5,0x1f,0x2f,0x35,
3483 0x5e,0x8f,0x3a,0x9c,0x61,0xb1,0xf1,0x6c,0xff,0x8c,0xb2,0x2f,0x02,0x03,0x01,
3484 0x00,0x01,0xa3,0x42,0x30,0x40,0x30,0x0e,0x06,0x03,0x55,0x1d,0x0f,0x01,0x01,
3485 0xff,0x04,0x04,0x03,0x02,0x00,0x06,0x30,0x0f,0x06,0x03,0x55,0x1d,0x13,0x01,
3486 0x01,0xff,0x04,0x05,0x30,0x03,0x01,0x01,0xff,0x30,0x1d,0x06,0x03,0x55,0x1d,
3487 0x0e,0x04,0x16,0x04,0x14,0x14,0x8c,0x16,0xbb,0xbe,0x70,0xa2,0x28,0x89,0xa0,
3488 0x58,0xff,0x98,0xbd,0xa8,0x24,0x2b,0x8a,0xe9,0x9a,0x30,0x09,0x06,0x05,0x2b,
3489 0x0e,0x03,0x02,0x1d,0x05,0x00,0x03,0x81,0x81,0x00,0x74,0xcb,0x21,0xfd,0x2d,
3490 0x25,0xdc,0xa5,0xaa,0xa1,0x26,0xdc,0x8b,0x40,0x11,0x64,0xae,0x5c,0x71,0x3c,
3491 0x28,0xbc,0xf9,0xb3,0xcb,0xa5,0x94,0xb2,0x8d,0x4c,0x23,0x2b,0x9b,0xde,0x2c,
3492 0x4c,0x30,0x04,0xc6,0x88,0x10,0x2f,0x53,0xfd,0x6c,0x82,0xf1,0x13,0xfb,0xda,
3493 0x27,0x75,0x25,0x48,0xe4,0x72,0x09,0x2a,0xee,0xb4,0x1e,0xc9,0x55,0xf5,0xf7,
3494 0x82,0x91,0xd8,0x4b,0xe4,0x3a,0xfe,0x97,0x87,0xdf,0xfb,0x15,0x5a,0x12,0x3e,
3495 0x12,0xe6,0xad,0x40,0x0b,0xcf,0xee,0x1a,0x44,0xe0,0x83,0xb2,0x67,0x94,0xd4,
3496 0x2e,0x7c,0xf2,0x06,0x9d,0xb3,0x3b,0x7e,0x2f,0xda,0x25,0x66,0x7e,0xa7,0x1f,
3497 0x45,0xd4,0xf5,0xe3,0xdf,0x2a,0xf1,0x18,0x28,0x20,0xb5,0xf8,0xf5,0x8d,0x7a,
3498 0x2e,0x84,0xee };
3499 static const BYTE eeCert[] = {
3500 0x30,0x82,0x01,0xb9,0x30,0x82,0x01,0x22,0xa0,0x03,0x02,0x01,0x02,0x02,0x01,
3501 0x01,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x05,0x05,
3502 0x00,0x30,0x10,0x31,0x0e,0x30,0x0c,0x06,0x03,0x55,0x04,0x03,0x13,0x05,0x43,
3503 0x65,0x72,0x74,0x31,0x30,0x1e,0x17,0x0d,0x30,0x37,0x30,0x35,0x30,0x31,0x30,
3504 0x30,0x30,0x30,0x30,0x30,0x5a,0x17,0x0d,0x30,0x37,0x31,0x30,0x30,0x31,0x30,
3505 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x10,0x31,0x0e,0x30,0x0c,0x06,0x03,0x55,
3506 0x04,0x03,0x13,0x05,0x43,0x65,0x72,0x74,0x32,0x30,0x81,0x9f,0x30,0x0d,0x06,
3507 0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x01,0x05,0x00,0x03,0x81,0x8d,
3508 0x00,0x30,0x81,0x89,0x02,0x81,0x81,0x00,0xb8,0x52,0xda,0xc5,0x4b,0x3f,0xe5,
3509 0x33,0x0e,0x67,0x5f,0x48,0x21,0xdc,0x7e,0xef,0x37,0x33,0xba,0xff,0xb4,0xc6,
3510 0xdc,0xb6,0x17,0x8e,0x20,0x55,0x07,0x12,0xd2,0x7b,0x3c,0xce,0x30,0xc5,0xa7,
3511 0x48,0x9f,0x6e,0xfe,0xb8,0xbe,0xdb,0x9f,0x9b,0x17,0x60,0x16,0xde,0xc6,0x8b,
3512 0x47,0xd1,0x57,0x71,0x3c,0x93,0xfc,0xbd,0xec,0x44,0x32,0x3b,0xb9,0xcf,0x6b,
3513 0x05,0x72,0xa7,0x87,0x8e,0x7e,0xd4,0x9a,0x87,0x1c,0x2f,0xb7,0x82,0x40,0xfc,
3514 0x6a,0x80,0x83,0x68,0x28,0xce,0x84,0xf4,0x0b,0x2e,0x44,0xcb,0x53,0xac,0x85,
3515 0x85,0xb5,0x46,0x36,0x98,0x3c,0x10,0x02,0xaa,0x02,0xbc,0x8b,0xa2,0x23,0xb2,
3516 0xd3,0x51,0x9a,0x22,0x4a,0xe3,0xaa,0x4e,0x7c,0xda,0x38,0xcf,0x49,0x98,0x72,
3517 0xa3,0x02,0x03,0x01,0x00,0x01,0xa3,0x23,0x30,0x21,0x30,0x1f,0x06,0x03,0x55,
3518 0x1d,0x23,0x04,0x18,0x30,0x18,0x80,0x14,0x14,0x8c,0x16,0xbb,0xbe,0x70,0xa2,
3519 0x28,0x89,0xa0,0x58,0xff,0x98,0xbd,0xa8,0x24,0x2b,0x8a,0xe9,0x9a,0x30,0x0d,
3520 0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x05,0x05,0x00,0x03,0x81,
3521 0x81,0x00,0x8a,0x49,0xa9,0x86,0x5e,0xc9,0x33,0x7e,0xfd,0xab,0x64,0x1f,0x6d,
3522 0x00,0xd7,0x9b,0xec,0xd1,0x5b,0x38,0xcc,0xd6,0xf3,0xf2,0xb4,0x75,0x70,0x00,
3523 0x82,0x9d,0x37,0x58,0xe1,0xcd,0x2c,0x61,0xb3,0x28,0xe7,0x8a,0x00,0xbe,0x6e,
3524 0xca,0xe8,0x55,0xd5,0xad,0x3a,0xea,0xaf,0x13,0x20,0x1c,0x44,0xfc,0xb4,0xf9,
3525 0x29,0x2b,0xdc,0x8a,0x2d,0x1b,0x27,0x9e,0xb9,0x3b,0x4a,0x71,0x9d,0x47,0x7d,
3526 0xf7,0x92,0x6b,0x21,0x7f,0xfa,0x88,0x79,0x94,0x33,0xf6,0xdd,0x92,0x04,0x92,
3527 0xd6,0x5e,0x0a,0x74,0xf2,0x85,0xa6,0xd5,0x3c,0x28,0xc0,0x89,0x5d,0xda,0xf3,
3528 0xa6,0x01,0xc2,0xe9,0xa3,0xc1,0xb7,0x21,0x08,0xba,0x18,0x07,0x45,0xeb,0x77,
3529 0x7d,0xcd,0xc6,0xe7,0x2a,0x7b,0x46,0xd2,0x3d,0xb5 };
3530 static const BYTE rootSignedCRL[] = {
3531 0x30,0x82,0x01,0x1f,0x30,0x81,0x89,0x02,0x01,0x01,0x30,0x0d,0x06,0x09,0x2a,
3532 0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x05,0x05,0x00,0x30,0x10,0x31,0x0e,0x30,
3533 0x0c,0x06,0x03,0x55,0x04,0x03,0x13,0x05,0x43,0x65,0x72,0x74,0x31,0x17,0x0d,
3534 0x30,0x37,0x30,0x39,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x17,0x0d,
3535 0x30,0x37,0x31,0x32,0x33,0x31,0x32,0x33,0x35,0x39,0x35,0x39,0x5a,0x30,0x14,
3536 0x30,0x12,0x02,0x01,0x01,0x17,0x0d,0x30,0x37,0x30,0x39,0x30,0x31,0x30,0x30,
3537 0x30,0x30,0x30,0x30,0x5a,0xa0,0x2f,0x30,0x2d,0x30,0x0a,0x06,0x03,0x55,0x1d,
3538 0x14,0x04,0x03,0x02,0x01,0x01,0x30,0x1f,0x06,0x03,0x55,0x1d,0x23,0x04,0x18,
3539 0x30,0x18,0x80,0x14,0x14,0x8c,0x16,0xbb,0xbe,0x70,0xa2,0x28,0x89,0xa0,0x58,
3540 0xff,0x98,0xbd,0xa8,0x24,0x2b,0x8a,0xe9,0x9a,0x30,0x0d,0x06,0x09,0x2a,0x86,
3541 0x48,0x86,0xf7,0x0d,0x01,0x01,0x05,0x05,0x00,0x03,0x81,0x81,0x00,0xa3,0xcf,
3542 0x17,0x5d,0x7a,0x08,0xab,0x11,0x1a,0xbd,0x5c,0xde,0x9a,0x22,0x92,0x38,0xe6,
3543 0x96,0xcc,0xb1,0xc5,0x42,0x86,0xa6,0xae,0xad,0xa3,0x1a,0x2b,0xa0,0xb0,0x65,
3544 0xaa,0x9c,0xd7,0x2d,0x44,0x8c,0xae,0x61,0xc7,0x30,0x17,0x89,0x84,0x3b,0x4a,
3545 0x8f,0x17,0x08,0x06,0x37,0x1c,0xf7,0x2d,0x4e,0x47,0x07,0x61,0x50,0xd9,0x06,
3546 0xd1,0x46,0xed,0x0a,0xbb,0xc3,0x9b,0x36,0x0b,0xa7,0x27,0x2f,0x2b,0x55,0xce,
3547 0x2a,0xa5,0x60,0xc6,0x53,0x28,0xe8,0xee,0xad,0x0e,0x2b,0xe8,0xd7,0x5f,0xc9,
3548 0xa5,0xed,0xf9,0x77,0xb0,0x3c,0x81,0xcf,0xcc,0x49,0xb2,0x1a,0xc3,0xfd,0x34,
3549 0xd5,0xbc,0xb0,0xd5,0xa5,0x9c,0x1b,0x72,0xc3,0x0f,0xa3,0xe3,0x3c,0xf0,0xc3,
3550 0x91,0xe8,0x93,0x4f,0xd4,0x2f };
3551
3552 static void testVerifyRevocation(void)
3553 {
3554 BOOL ret;
3555 CERT_REVOCATION_STATUS status = { 0 };
3556 PCCERT_CONTEXT certs[2];
3557 CERT_REVOCATION_PARA revPara = { sizeof(revPara), 0 };
3558
3559 /* Crash
3560 ret = CertVerifyRevocation(0, 0, 0, NULL, 0, NULL, NULL);
3561 */
3562 SetLastError(0xdeadbeef);
3563 ret = CertVerifyRevocation(0, 0, 0, NULL, 0, NULL, &status);
3564 ok(!ret && GetLastError() == E_INVALIDARG,
3565 "Expected E_INVALIDARG, got %08x\n", GetLastError());
3566 status.cbSize = sizeof(status);
3567 ret = CertVerifyRevocation(0, 0, 0, NULL, 0, NULL, &status);
3568 ok(ret, "CertVerifyRevocation failed: %08x\n", GetLastError());
3569 ret = CertVerifyRevocation(0, 2, 0, NULL, 0, NULL, &status);
3570 ok(ret, "CertVerifyRevocation failed: %08x\n", GetLastError());
3571 ret = CertVerifyRevocation(2, 0, 0, NULL, 0, NULL, &status);
3572 ok(ret, "CertVerifyRevocation failed: %08x\n", GetLastError());
3573 certs[0] = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert,
3574 sizeof(bigCert));
3575 SetLastError(0xdeadbeef);
3576 ret = CertVerifyRevocation(0, 0, 1, (void **)certs, 0, NULL, &status);
3577 ok(!ret && GetLastError() == CRYPT_E_NO_REVOCATION_DLL,
3578 "Expected CRYPT_E_NO_REVOCATION_DLL, got %08x\n", GetLastError());
3579 SetLastError(0xdeadbeef);
3580 ret = CertVerifyRevocation(0, 2, 1, (void **)certs, 0, NULL, &status);
3581 ok(!ret && GetLastError() == CRYPT_E_NO_REVOCATION_DLL,
3582 "Expected CRYPT_E_NO_REVOCATION_DLL, got %08x\n", GetLastError());
3583
3584 CertFreeCertificateContext(certs[0]);
3585
3586 certs[0] = CertCreateCertificateContext(X509_ASN_ENCODING,
3587 rootWithKeySignAndCRLSign, sizeof(rootWithKeySignAndCRLSign));
3588 certs[1] = CertCreateCertificateContext(X509_ASN_ENCODING,
3589 eeCert, sizeof(eeCert));
3590 /* The root cert itself can't be checked for revocation */
3591 SetLastError(0xdeadbeef);
3592 ret = CertVerifyRevocation(X509_ASN_ENCODING, CERT_CONTEXT_REVOCATION_TYPE,
3593 1, (void **)certs, 0, NULL, &status);
3594 if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
3595 {
3596 win_skip("CERT_CONTEXT_REVOCATION_TYPE unsupported, skipping\n");
3597 return;
3598 }
3599 ok(!ret && GetLastError() == CRYPT_E_NO_REVOCATION_CHECK,
3600 "expected CRYPT_E_NO_REVOCATION_CHECK, got %08x\n", GetLastError());
3601 ok(status.dwError == CRYPT_E_NO_REVOCATION_CHECK,
3602 "expected CRYPT_E_NO_REVOCATION_CHECK, got %08x\n", status.dwError);
3603 ok(status.dwIndex == 0, "expected index 0, got %d\n", status.dwIndex);
3604 /* Neither can the end cert */
3605 SetLastError(0xdeadbeef);
3606 ret = CertVerifyRevocation(X509_ASN_ENCODING, CERT_CONTEXT_REVOCATION_TYPE,
3607 1, (void **)&certs[1], 0, NULL, &status);
3608 ok(!ret && (GetLastError() == CRYPT_E_NO_REVOCATION_CHECK /* Win9x */ ||
3609 GetLastError() == CRYPT_E_REVOCATION_OFFLINE),
3610 "expected CRYPT_E_NO_REVOCATION_CHECK or CRYPT_E_REVOCATION_OFFLINE, got %08x\n",
3611 GetLastError());
3612 ok(status.dwError == CRYPT_E_NO_REVOCATION_CHECK /* Win9x */ ||
3613 status.dwError == CRYPT_E_REVOCATION_OFFLINE,
3614 "expected CRYPT_E_NO_REVOCATION_CHECK or CRYPT_E_REVOCATION_OFFLINE, got %08x\n",
3615 status.dwError);
3616 ok(status.dwIndex == 0, "expected index 0, got %d\n", status.dwIndex);
3617 /* Both certs together can't, either (they're not CRLs) */
3618 SetLastError(0xdeadbeef);
3619 ret = CertVerifyRevocation(X509_ASN_ENCODING, CERT_CONTEXT_REVOCATION_TYPE,
3620 2, (void **)certs, 0, NULL, &status);
3621 ok(!ret && (GetLastError() == CRYPT_E_NO_REVOCATION_CHECK ||
3622 GetLastError() == CRYPT_E_REVOCATION_OFFLINE /* WinME */),
3623 "expected CRYPT_E_NO_REVOCATION_CHECK or CRYPT_E_REVOCATION_OFFLINE, got %08x\n",
3624 GetLastError());
3625 ok(status.dwError == CRYPT_E_NO_REVOCATION_CHECK ||
3626 status.dwError == CRYPT_E_REVOCATION_OFFLINE /* WinME */,
3627 "expected CRYPT_E_NO_REVOCATION_CHECK or CRYPT_E_REVOCATION_OFFLINE, got %08x\n",
3628 status.dwError);
3629 ok(status.dwIndex == 0, "expected index 0, got %d\n", status.dwIndex);
3630 /* Now add a CRL to the hCrlStore */
3631 revPara.hCrlStore = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
3632 CERT_STORE_CREATE_NEW_FLAG, NULL);
3633 CertAddEncodedCRLToStore(revPara.hCrlStore, X509_ASN_ENCODING,
3634 rootSignedCRL, sizeof(rootSignedCRL), CERT_STORE_ADD_ALWAYS, NULL);
3635 SetLastError(0xdeadbeef);
3636 ret = CertVerifyRevocation(X509_ASN_ENCODING, CERT_CONTEXT_REVOCATION_TYPE,
3637 2, (void **)certs, 0, &revPara, &status);
3638 ok(!ret && (GetLastError() == CRYPT_E_NO_REVOCATION_CHECK ||
3639 GetLastError() == CRYPT_E_REVOCATION_OFFLINE /* WinME */),
3640 "expected CRYPT_E_NO_REVOCATION_CHECK or CRYPT_E_REVOCATION_OFFLINE, got %08x\n",
3641 GetLastError());
3642 ok(status.dwError == CRYPT_E_NO_REVOCATION_CHECK ||
3643 status.dwError == CRYPT_E_REVOCATION_OFFLINE /* WinME */,
3644 "expected CRYPT_E_NO_REVOCATION_CHECK or CRYPT_E_REVOCATION_OFFLINE, got %08x\n",
3645 status.dwError);
3646 ok(status.dwIndex == 0, "expected index 0, got %d\n", status.dwIndex);
3647 /* Specifying CERT_VERIFY_REV_CHAIN_FLAG doesn't change things either */
3648 SetLastError(0xdeadbeef);
3649 ret = CertVerifyRevocation(X509_ASN_ENCODING, CERT_CONTEXT_REVOCATION_TYPE,
3650 2, (void **)certs, CERT_VERIFY_REV_CHAIN_FLAG, &revPara, &status);
3651 ok(!ret && GetLastError() == CRYPT_E_NO_REVOCATION_CHECK,
3652 "expected CRYPT_E_NO_REVOCATION_CHECK, got %08x\n", GetLastError());
3653 ok(status.dwError == CRYPT_E_NO_REVOCATION_CHECK,
3654 "expected CRYPT_E_NO_REVOCATION_CHECK, got %08x\n", status.dwError);
3655 ok(status.dwIndex == 0, "expected index 0, got %d\n", status.dwIndex);
3656 /* Again, specifying the issuer cert: no change */
3657 revPara.pIssuerCert = certs[0];
3658 SetLastError(0xdeadbeef);
3659 ret = CertVerifyRevocation(X509_ASN_ENCODING, CERT_CONTEXT_REVOCATION_TYPE,
3660 1, (void **)&certs[1], 0, &revPara, &status);
3661 /* Win2k thinks the cert is revoked, and it is, except the CRL is out of
3662 * date, hence the revocation status should be unknown.
3663 */
3664 ok(!ret && (GetLastError() == CRYPT_E_NO_REVOCATION_CHECK ||
3665 broken(GetLastError() == CRYPT_E_REVOKED /* Win2k */)),
3666 "expected CRYPT_E_NO_REVOCATION_CHECK, got %08x\n", GetLastError());
3667 ok(status.dwError == CRYPT_E_NO_REVOCATION_CHECK ||
3668 broken(status.dwError == CRYPT_E_REVOKED /* Win2k */),
3669 "expected CRYPT_E_NO_REVOCATION_CHECK, got %08x\n", status.dwError);
3670 ok(status.dwIndex == 0, "expected index 0, got %d\n", status.dwIndex);
3671 CertCloseStore(revPara.hCrlStore, 0);
3672 CertFreeCertificateContext(certs[1]);
3673 CertFreeCertificateContext(certs[0]);
3674 }
3675
3676 static BYTE privKey[] = {
3677 0x07, 0x02, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x52, 0x53, 0x41, 0x32, 0x00,
3678 0x02, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x79, 0x10, 0x1c, 0xd0, 0x6b, 0x10,
3679 0x18, 0x30, 0x94, 0x61, 0xdc, 0x0e, 0xcb, 0x96, 0x4e, 0x21, 0x3f, 0x79, 0xcd,
3680 0xa9, 0x17, 0x62, 0xbc, 0xbb, 0x61, 0x4c, 0xe0, 0x75, 0x38, 0x6c, 0xf3, 0xde,
3681 0x60, 0x86, 0x03, 0x97, 0x65, 0xeb, 0x1e, 0x6b, 0xdb, 0x53, 0x85, 0xad, 0x68,
3682 0x21, 0xf1, 0x5d, 0xe7, 0x1f, 0xe6, 0x53, 0xb4, 0xbb, 0x59, 0x3e, 0x14, 0x27,
3683 0xb1, 0x83, 0xa7, 0x3a, 0x54, 0xe2, 0x8f, 0x65, 0x8e, 0x6a, 0x4a, 0xcf, 0x3b,
3684 0x1f, 0x65, 0xff, 0xfe, 0xf1, 0x31, 0x3a, 0x37, 0x7a, 0x8b, 0xcb, 0xc6, 0xd4,
3685 0x98, 0x50, 0x36, 0x67, 0xe4, 0xa1, 0xe8, 0x7e, 0x8a, 0xc5, 0x23, 0xf2, 0x77,
3686 0xf5, 0x37, 0x61, 0x49, 0x72, 0x59, 0xe8, 0x3d, 0xf7, 0x60, 0xb2, 0x77, 0xca,
3687 0x78, 0x54, 0x6d, 0x65, 0x9e, 0x03, 0x97, 0x1b, 0x61, 0xbd, 0x0c, 0xd8, 0x06,
3688 0x63, 0xe2, 0xc5, 0x48, 0xef, 0xb3, 0xe2, 0x6e, 0x98, 0x7d, 0xbd, 0x4e, 0x72,
3689 0x91, 0xdb, 0x31, 0x57, 0xe3, 0x65, 0x3a, 0x49, 0xca, 0xec, 0xd2, 0x02, 0x4e,
3690 0x22, 0x7e, 0x72, 0x8e, 0xf9, 0x79, 0x84, 0x82, 0xdf, 0x7b, 0x92, 0x2d, 0xaf,
3691 0xc9, 0xe4, 0x33, 0xef, 0x89, 0x5c, 0x66, 0x99, 0xd8, 0x80, 0x81, 0x47, 0x2b,
3692 0xb1, 0x66, 0x02, 0x84, 0x59, 0x7b, 0xc3, 0xbe, 0x98, 0x45, 0x4a, 0x3d, 0xdd,
3693 0xea, 0x2b, 0xdf, 0x4e, 0xb4, 0x24, 0x6b, 0xec, 0xe7, 0xd9, 0x0c, 0x45, 0xb8,
3694 0xbe, 0xca, 0x69, 0x37, 0x92, 0x4c, 0x38, 0x6b, 0x96, 0x6d, 0xcd, 0x86, 0x67,
3695 0x5c, 0xea, 0x54, 0x94, 0xa4, 0xca, 0xa4, 0x02, 0xa5, 0x21, 0x4d, 0xae, 0x40,
3696 0x8f, 0x9d, 0x51, 0x83, 0xf2, 0x3f, 0x33, 0xc1, 0x72, 0xb4, 0x1d, 0x94, 0x6e,
3697 0x7d, 0xe4, 0x27, 0x3f, 0xea, 0xff, 0xe5, 0x9b, 0xa7, 0x5e, 0x55, 0x8e, 0x0d,
3698 0x69, 0x1c, 0x7a, 0xff, 0x81, 0x9d, 0x53, 0x52, 0x97, 0x9a, 0x76, 0x79, 0xda,
3699 0x93, 0x32, 0x16, 0xec, 0x69, 0x51, 0x1a, 0x4e, 0xc3, 0xf1, 0x72, 0x80, 0x78,
3700 0x5e, 0x66, 0x4a, 0x8d, 0x85, 0x2f, 0x3f, 0xb2, 0xa7 };
3701
3702 static const BYTE exportedPublicKeyBlob[] = {
3703 0x06,0x02,0x00,0x00,0x00,0xa4,0x00,0x00,0x52,0x53,0x41,0x31,0x00,0x02,0x00,0x00,
3704 0x01,0x00,0x01,0x00,0x79,0x10,0x1c,0xd0,0x6b,0x10,0x18,0x30,0x94,0x61,0xdc,0x0e,
3705 0xcb,0x96,0x4e,0x21,0x3f,0x79,0xcd,0xa9,0x17,0x62,0xbc,0xbb,0x61,0x4c,0xe0,0x75,
3706 0x38,0x6c,0xf3,0xde,0x60,0x86,0x03,0x97,0x65,0xeb,0x1e,0x6b,0xdb,0x53,0x85,0xad,
3707 0x68,0x21,0xf1,0x5d,0xe7,0x1f,0xe6,0x53,0xb4,0xbb,0x59,0x3e,0x14,0x27,0xb1,0x83,
3708 0xa7,0x3a,0x54,0xe2 };
3709
3710 static const BYTE asnEncodedPublicKey[] = {
3711 0x30,0x48,0x02,0x41,0x00,0xe2,0x54,0x3a,0xa7,0x83,0xb1,0x27,0x14,0x3e,0x59,0xbb,
3712 0xb4,0x53,0xe6,0x1f,0xe7,0x5d,0xf1,0x21,0x68,0xad,0x85,0x53,0xdb,0x6b,0x1e,0xeb,
3713 0x65,0x97,0x03,0x86,0x60,0xde,0xf3,0x6c,0x38,0x75,0xe0,0x4c,0x61,0xbb,0xbc,0x62,
3714 0x17,0xa9,0xcd,0x79,0x3f,0x21,0x4e,0x96,0xcb,0x0e,0xdc,0x61,0x94,0x30,0x18,0x10,
3715 0x6b,0xd0,0x1c,0x10,0x79,0x02,0x03,0x01,0x00,0x01 };
3716
3717 static void testAcquireCertPrivateKey(void)
3718 {
3719 BOOL ret;
3720 PCCERT_CONTEXT cert;
3721 HCRYPTPROV csp;
3722 DWORD size, keySpec;
3723 BOOL callerFree;
3724 CRYPT_KEY_PROV_INFO keyProvInfo;
3725 HCRYPTKEY key;
3726 WCHAR ms_def_prov_w[MAX_PATH];
3727
3728 if (!pCryptAcquireCertificatePrivateKey)
3729 {
3730 win_skip("CryptAcquireCertificatePrivateKey() is not available\n");
3731 return;
3732 }
3733
3734 lstrcpyW(ms_def_prov_w, MS_DEF_PROV_W);
3735
3736 keyProvInfo.pwszContainerName = cspNameW;
3737 keyProvInfo.pwszProvName = ms_def_prov_w;
3738 keyProvInfo.dwProvType = PROV_RSA_FULL;
3739 keyProvInfo.dwFlags = 0;
3740 keyProvInfo.cProvParam = 0;
3741 keyProvInfo.rgProvParam = NULL;
3742 keyProvInfo.dwKeySpec = AT_SIGNATURE;
3743
3744 pCryptAcquireContextA(NULL, cspNameA, MS_DEF_PROV_A, PROV_RSA_FULL,
3745 CRYPT_DELETEKEYSET);
3746
3747 cert = CertCreateCertificateContext(X509_ASN_ENCODING, selfSignedCert,
3748 sizeof(selfSignedCert));
3749
3750 /* Crash
3751 ret = pCryptAcquireCertificatePrivateKey(NULL, 0, NULL, NULL, NULL, NULL);
3752 ret = pCryptAcquireCertificatePrivateKey(NULL, 0, NULL, NULL, NULL,
3753 &callerFree);
3754 ret = pCryptAcquireCertificatePrivateKey(NULL, 0, NULL, NULL, &keySpec,
3755 NULL);
3756 ret = pCryptAcquireCertificatePrivateKey(NULL, 0, NULL, &csp, NULL, NULL);
3757 ret = pCryptAcquireCertificatePrivateKey(NULL, 0, NULL, &csp, &keySpec,
3758 &callerFree);
3759 ret = pCryptAcquireCertificatePrivateKey(cert, 0, NULL, NULL, NULL, NULL);
3760 */
3761
3762 /* Missing private key */
3763 ret = pCryptAcquireCertificatePrivateKey(cert, 0, NULL, &csp, NULL, NULL);
3764 ok(!ret && GetLastError() == CRYPT_E_NO_KEY_PROPERTY,
3765 "Expected CRYPT_E_NO_KEY_PROPERTY, got %08x\n", GetLastError());
3766 ret = pCryptAcquireCertificatePrivateKey(cert, 0, NULL, &csp, &keySpec,
3767 &callerFree);
3768 ok(!ret && GetLastError() == CRYPT_E_NO_KEY_PROPERTY,
3769 "Expected CRYPT_E_NO_KEY_PROPERTY, got %08x\n", GetLastError());
3770 CertSetCertificateContextProperty(cert, CERT_KEY_PROV_INFO_PROP_ID, 0,
3771 &keyProvInfo);
3772 ret = pCryptAcquireCertificatePrivateKey(cert, 0, NULL, &csp, &keySpec,
3773 &callerFree);
3774 ok(!ret && (GetLastError() == CRYPT_E_NO_KEY_PROPERTY || GetLastError() == NTE_BAD_KEYSET /* win8 */),
3775 "Expected CRYPT_E_NO_KEY_PROPERTY, got %08x\n", GetLastError());
3776
3777 pCryptAcquireContextA(&csp, cspNameA, MS_DEF_PROV_A, PROV_RSA_FULL,
3778 CRYPT_NEWKEYSET);
3779 ret = CryptImportKey(csp, privKey, sizeof(privKey), 0, 0, &key);
3780 ok(ret, "CryptImportKey failed: %08x\n", GetLastError());
3781 if (ret)
3782 {
3783 HCRYPTPROV certCSP;
3784 DWORD size;
3785 CERT_KEY_CONTEXT keyContext;
3786
3787 /* Don't cache provider */
3788 ret = pCryptAcquireCertificatePrivateKey(cert, 0, NULL, &certCSP,
3789 &keySpec, &callerFree);
3790 ok(ret ||
3791 broken(!ret), /* win95 */
3792 "CryptAcquireCertificatePrivateKey failed: %08x\n",
3793 GetLastError());
3794 if (ret)
3795 {
3796 ok(callerFree, "Expected callerFree to be TRUE\n");
3797 CryptReleaseContext(certCSP, 0);
3798 }
3799
3800 ret = pCryptAcquireCertificatePrivateKey(cert, 0, NULL, &certCSP,
3801 NULL, NULL);
3802 ok(ret ||
3803 broken(!ret), /* win95 */
3804 "CryptAcquireCertificatePrivateKey failed: %08x\n",
3805 GetLastError());
3806 CryptReleaseContext(certCSP, 0);
3807
3808 /* Use the key prov info's caching (there shouldn't be any) */
3809 ret = pCryptAcquireCertificatePrivateKey(cert,
3810 CRYPT_ACQUIRE_USE_PROV_INFO_FLAG, NULL, &certCSP, &keySpec,
3811 &callerFree);
3812 ok(ret ||
3813 broken(!ret), /* win95 */
3814 "CryptAcquireCertificatePrivateKey failed: %08x\n",
3815 GetLastError());
3816 if (ret)
3817 {
3818 ok(callerFree, "Expected callerFree to be TRUE\n");
3819 CryptReleaseContext(certCSP, 0);
3820 }
3821
3822 /* Cache it (and check that it's cached) */
3823 ret = pCryptAcquireCertificatePrivateKey(cert,
3824 CRYPT_ACQUIRE_CACHE_FLAG, NULL, &certCSP, &keySpec, &callerFree);
3825 ok(ret ||
3826 broken(!ret), /* win95 */
3827 "CryptAcquireCertificatePrivateKey failed: %08x\n",
3828 GetLastError());
3829 ok(!callerFree, "Expected callerFree to be FALSE\n");
3830 size = sizeof(keyContext);
3831 ret = CertGetCertificateContextProperty(cert, CERT_KEY_CONTEXT_PROP_ID,
3832 &keyContext, &size);
3833 ok(ret ||
3834 broken(!ret), /* win95 */
3835 "CertGetCertificateContextProperty failed: %08x\n",
3836 GetLastError());
3837
3838 /* Remove the cached provider */
3839 CryptReleaseContext(keyContext.hCryptProv, 0);
3840 CertSetCertificateContextProperty(cert, CERT_KEY_CONTEXT_PROP_ID, 0,
3841 NULL);
3842 /* Allow caching via the key prov info */
3843 keyProvInfo.dwFlags = CERT_SET_KEY_CONTEXT_PROP_ID;
3844 CertSetCertificateContextProperty(cert, CERT_KEY_PROV_INFO_PROP_ID, 0,
3845 &keyProvInfo);
3846 /* Now use the key prov info's caching */
3847 ret = pCryptAcquireCertificatePrivateKey(cert,
3848 CRYPT_ACQUIRE_USE_PROV_INFO_FLAG, NULL, &certCSP, &keySpec,
3849 &callerFree);
3850 ok(ret ||
3851 broken(!ret), /* win95 */
3852 "CryptAcquireCertificatePrivateKey failed: %08x\n",
3853 GetLastError());
3854 ok(!callerFree, "Expected callerFree to be FALSE\n");
3855 size = sizeof(keyContext);
3856 ret = CertGetCertificateContextProperty(cert, CERT_KEY_CONTEXT_PROP_ID,
3857 &keyContext, &size);
3858 ok(ret ||
3859 broken(!ret), /* win95 */
3860 "CertGetCertificateContextProperty failed: %08x\n",
3861 GetLastError());
3862 CryptReleaseContext(certCSP, 0);
3863
3864 CryptDestroyKey(key);
3865 }
3866
3867 /* Some sanity-checking on public key exporting */
3868 ret = CryptImportPublicKeyInfo(csp, X509_ASN_ENCODING,
3869 &cert->pCertInfo->SubjectPublicKeyInfo, &key);
3870 ok(ret, "CryptImportPublicKeyInfo failed: %08x\n", GetLastError());
3871 if (ret)
3872 {
3873 ret = CryptExportKey(key, 0, PUBLICKEYBLOB, 0, NULL, &size);
3874 ok(ret, "CryptExportKey failed: %08x\n", GetLastError());
3875 if (ret)
3876 {
3877 LPBYTE buf = HeapAlloc(GetProcessHeap(), 0, size), encodedKey;
3878
3879 ret = CryptExportKey(key, 0, PUBLICKEYBLOB, 0, buf, &size);
3880 ok(ret, "CryptExportKey failed: %08x\n", GetLastError());
3881 ok(size == sizeof(exportedPublicKeyBlob), "Unexpected size %d\n",
3882 size);
3883 ok(!memcmp(buf, exportedPublicKeyBlob, size), "Unexpected value\n");
3884 ret = pCryptEncodeObjectEx(X509_ASN_ENCODING, RSA_CSP_PUBLICKEYBLOB,
3885 buf, CRYPT_ENCODE_ALLOC_FLAG, NULL, &encodedKey, &size);
3886 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3887 if (ret)
3888 {
3889 ok(size == sizeof(asnEncodedPublicKey), "Unexpected size %d\n",
3890 size);
3891 ok(!memcmp(encodedKey, asnEncodedPublicKey, size),
3892 "Unexpected value\n");
3893 LocalFree(encodedKey);
3894 }
3895 HeapFree(GetProcessHeap(), 0, buf);
3896 }
3897 CryptDestroyKey(key);
3898 }
3899 ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING,
3900 NULL, 0, NULL, NULL, &size);
3901 ok(ret, "CryptExportPublicKeyInfoEx failed: %08x\n", GetLastError());
3902 if (ret)
3903 {
3904 PCERT_PUBLIC_KEY_INFO info = HeapAlloc(GetProcessHeap(), 0, size);
3905
3906 ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING,
3907 NULL, 0, NULL, info, &size);
3908 ok(ret, "CryptExportPublicKeyInfoEx failed: %08x\n", GetLastError());
3909 if (ret)
3910 {
3911 ok(info->PublicKey.cbData == sizeof(asnEncodedPublicKey),
3912 "Unexpected size %d\n", info->PublicKey.cbData);
3913 ok(!memcmp(info->PublicKey.pbData, asnEncodedPublicKey,
3914 info->PublicKey.cbData), "Unexpected value\n");
3915 }
3916 HeapFree(GetProcessHeap(), 0, info);
3917 }
3918
3919 CryptReleaseContext(csp, 0);
3920 pCryptAcquireContextA(&csp, cspNameA, MS_DEF_PROV_A, PROV_RSA_FULL,
3921 CRYPT_DELETEKEYSET);
3922
3923 CertFreeCertificateContext(cert);
3924 }
3925
3926 static void testGetPublicKeyLength(void)
3927 {
3928 static char oid_rsa_rsa[] = szOID_RSA_RSA;
3929 static char oid_rsa_dh[] = szOID_RSA_DH;
3930 static char bogusOID[] = "1.2.3";
3931 DWORD ret;
3932 CERT_PUBLIC_KEY_INFO info = { { 0 } };
3933 BYTE bogusKey[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
3934 BYTE key[] = { 0x30,0x0f,0x02,0x08,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
3935 0x02,0x03,0x01,0x00,0x01 };
3936
3937 /* Crashes
3938 ret = CertGetPublicKeyLength(0, NULL);
3939 */
3940 /* With an empty public key info */
3941 SetLastError(0xdeadbeef);
3942 ret = CertGetPublicKeyLength(0, &info);
3943 ok(ret == 0 && GetLastError() == ERROR_FILE_NOT_FOUND,
3944 "Expected length 0 and ERROR_FILE_NOT_FOUND, got length %d, %08x\n",
3945 ret, GetLastError());
3946 SetLastError(0xdeadbeef);
3947 ret = CertGetPublicKeyLength(X509_ASN_ENCODING, &info);
3948 ok(ret == 0 &&
3949 (GetLastError() == CRYPT_E_ASN1_EOD ||
3950 GetLastError() == OSS_BAD_ARG), /* win9x */
3951 "Expected length 0 and CRYPT_E_ASN1_EOD, got length %d, %08x\n",
3952 ret, GetLastError());
3953 /* With a nearly-empty public key info */
3954 info.Algorithm.pszObjId = oid_rsa_rsa;
3955 SetLastError(0xdeadbeef);
3956 ret = CertGetPublicKeyLength(0, &info);
3957 ok(ret == 0 && GetLastError() == ERROR_FILE_NOT_FOUND,
3958 "Expected length 0 and ERROR_FILE_NOT_FOUND, got length %d, %08x\n",
3959 ret, GetLastError());
3960 SetLastError(0xdeadbeef);
3961 ret = CertGetPublicKeyLength(X509_ASN_ENCODING, &info);
3962 ok(ret == 0 &&
3963 (GetLastError() == CRYPT_E_ASN1_EOD ||
3964 GetLastError() == OSS_BAD_ARG), /* win9x */
3965 "Expected length 0 and CRYPT_E_ASN1_EOD, got length %d, %08x\n",
3966 ret, GetLastError());
3967 /* With a bogus key */
3968 info.PublicKey.cbData = sizeof(bogusKey);
3969 info.PublicKey.pbData = bogusKey;
3970 SetLastError(0xdeadbeef);
3971 ret = CertGetPublicKeyLength(0, &info);
3972 ok(ret == 0 && GetLastError() == ERROR_FILE_NOT_FOUND,
3973 "Expected length 0 and ERROR_FILE_NOT_FOUND, got length %d, %08x\n",
3974 ret, GetLastError());
3975 SetLastError(0xdeadbeef);
3976 ret = CertGetPublicKeyLength(X509_ASN_ENCODING, &info);
3977 ok(ret == 0 &&
3978 (GetLastError() == CRYPT_E_ASN1_BADTAG ||
3979 GetLastError() == OSS_PDU_MISMATCH), /* win9x */
3980 "Expected length 0 and CRYPT_E_ASN1_BADTAGTAG, got length %d, %08x\n",
3981 ret, GetLastError());
3982 /* With a believable RSA key but a bogus OID */
3983 info.Algorithm.pszObjId = bogusOID;
3984 info.PublicKey.cbData = sizeof(key);
3985 info.PublicKey.pbData = key;
3986 SetLastError(0xdeadbeef);
3987 ret = CertGetPublicKeyLength(0, &info);
3988 ok(ret == 0 && GetLastError() == ERROR_FILE_NOT_FOUND,
3989 "Expected length 0 and ERROR_FILE_NOT_FOUND, got length %d, %08x\n",
3990 ret, GetLastError());
3991 SetLastError(0xdeadbeef);
3992 ret = CertGetPublicKeyLength(X509_ASN_ENCODING, &info);
3993 ok(ret == 56 || broken(ret == 0 && GetLastError() == NTE_BAD_LEN) /* Win7 */,
3994 "Expected length 56, got %d\n", ret);
3995 /* An RSA key with the DH OID */
3996 info.Algorithm.pszObjId = oid_rsa_dh;
3997 SetLastError(0xdeadbeef);
3998 ret = CertGetPublicKeyLength(X509_ASN_ENCODING, &info);
3999 ok(ret == 0 &&
4000 (GetLastError() == CRYPT_E_ASN1_BADTAG ||
4001 GetLastError() == E_INVALIDARG), /* win9x */
4002 "Expected length 0 and CRYPT_E_ASN1_BADTAG, got length %d, %08x\n",
4003 ret, GetLastError());
4004 /* With the RSA OID */
4005 info.Algorithm.pszObjId = oid_rsa_rsa;
4006 SetLastError(0xdeadbeef);
4007 ret = CertGetPublicKeyLength(X509_ASN_ENCODING, &info);
4008 ok(ret == 56 || broken(ret == 0 && GetLastError() == NTE_BAD_LEN) /* Win7 */,
4009 "Expected length 56, got %d\n", ret);
4010 /* With the RSA OID and a message encoding */
4011 info.Algorithm.pszObjId = oid_rsa_rsa;
4012 SetLastError(0xdeadbeef);
4013 ret = CertGetPublicKeyLength(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, &info);
4014 ok(ret == 56 || broken(ret == 0 && GetLastError() == NTE_BAD_LEN) /* Win7 */,
4015 "Expected length 56, got %d\n", ret);
4016 }
4017
4018 START_TEST(cert)
4019 {
4020 init_function_pointers();
4021
4022 testAddCert();
4023 testCertProperties();
4024 testCreateCert();
4025 testDupCert();
4026 testFindCert();
4027 testGetSubjectCert();
4028 testGetIssuerCert();
4029 testLinkCert();
4030
4031 testCryptHashCert();
4032 testCertSigs();
4033 testSignAndEncodeCert();
4034 testCreateSelfSignCert();
4035 testIntendedKeyUsage();
4036 testKeyUsage();
4037 testGetValidUsages();
4038 testCompareCertName();
4039 testCompareIntegerBlob();
4040 testComparePublicKeyInfo();
4041 testHashPublicKeyInfo();
4042 testHashToBeSigned();
4043 testCompareCert();
4044 testVerifySubjectCert();
4045 testVerifyRevocation();
4046 testAcquireCertPrivateKey();
4047 testGetPublicKeyLength();
4048 testIsRDNAttrsInCertificateName();
4049 }