2 * crypt32 cert store function tests
4 * Copyright 2005-2006 Juan Lang
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.
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.
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
30 #include "wine/test.h"
32 /* The following aren't defined in wincrypt.h, as they're "reserved" */
33 #define CERT_CERT_PROP_ID 32
34 #define CERT_CRL_PROP_ID 33
35 #define CERT_CTL_PROP_ID 34
37 struct CertPropIDHeader
44 static const BYTE emptyCert[] = { 0x30, 0x00 };
45 static const BYTE bigCert[] = "\x30\x7a\x02\x01\x01\x30\x02\x06\x00"
46 "\x30\x15\x31\x13\x30\x11\x06\x03\x55\x04\x03\x13\x0a\x4a\x75\x61\x6e\x20\x4c"
47 "\x61\x6e\x67\x00\x30\x22\x18\x0f\x31\x36\x30\x31\x30\x31\x30\x31\x30\x30\x30"
48 "\x30\x30\x30\x5a\x18\x0f\x31\x36\x30\x31\x30\x31\x30\x31\x30\x30\x30\x30\x30"
49 "\x30\x5a\x30\x15\x31\x13\x30\x11\x06\x03\x55\x04\x03\x13\x0a\x4a\x75\x61\x6e"
50 "\x20\x4c\x61\x6e\x67\x00\x30\x07\x30\x02\x06\x00\x03\x01\x00\xa3\x16\x30\x14"
51 "\x30\x12\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x08\x30\x06\x01\x01\xff\x02\x01"
53 static const BYTE signedBigCert[] = {
54 0x30, 0x81, 0x93, 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06, 0x00, 0x30,
55 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a,
56 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22, 0x18, 0x0f,
57 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
58 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30,
59 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06,
60 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61,
61 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3,
62 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff,
63 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
64 0x00, 0x03, 0x11, 0x00, 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07,
65 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00 };
66 static const BYTE serializedCert[] = { 0x20, 0x00, 0x00, 0x00,
67 0x01, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x30, 0x7a, 0x02, 0x01, 0x01,
68 0x30, 0x02, 0x06, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55,
69 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67,
70 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31,
71 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31,
72 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15,
73 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75,
74 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06,
75 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55,
76 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02,
78 static const BYTE signedCRL[] = { 0x30, 0x45, 0x30, 0x2c, 0x30, 0x02, 0x06,
79 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
80 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18, 0x0f,
81 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
82 0x30, 0x5a, 0x30, 0x02, 0x06, 0x00, 0x03, 0x11, 0x00, 0x0f, 0x0e, 0x0d, 0x0c,
83 0x0b, 0x0a, 0x09, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00 };
85 static void testDupCert(void)
89 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
90 CERT_STORE_CREATE_NEW_FLAG, NULL);
91 ok(store != NULL, "CertOpenStore failed: %ld\n", GetLastError());
94 PCCERT_CONTEXT context, dupContext;
97 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
98 bigCert, sizeof(bigCert) - 1, CERT_STORE_ADD_ALWAYS, &context);
99 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n",
101 ok(context != NULL, "Expected a valid cert context\n");
104 ok(context->cbCertEncoded == sizeof(bigCert) - 1,
105 "Expected cert of %d bytes, got %ld\n", sizeof(bigCert) - 1,
106 context->cbCertEncoded);
107 ok(!memcmp(context->pbCertEncoded, bigCert, sizeof(bigCert) - 1),
108 "Unexpected encoded cert in context\n");
109 ok(context->hCertStore == store, "Unexpected store\n");
111 dupContext = CertDuplicateCertificateContext(context);
112 ok(dupContext != NULL, "Expected valid duplicate\n");
115 ok(dupContext->cbCertEncoded == sizeof(bigCert) - 1,
116 "Expected cert of %d bytes, got %ld\n", sizeof(bigCert) - 1,
117 dupContext->cbCertEncoded);
118 ok(!memcmp(dupContext->pbCertEncoded, bigCert,
119 sizeof(bigCert) - 1),
120 "Unexpected encoded cert in context\n");
121 ok(dupContext->hCertStore == store, "Unexpected store\n");
122 CertFreeCertificateContext(dupContext);
124 CertFreeCertificateContext(context);
126 CertCloseStore(store, 0);
130 static void testMemStore(void)
132 HCERTSTORE store1, store2;
133 PCCERT_CONTEXT context;
137 store1 = CertOpenStore(0, 0, 0, 0, NULL);
138 ok(!store1 && GetLastError() == ERROR_FILE_NOT_FOUND,
139 "Expected ERROR_FILE_NOT_FOUND, got %ld\n", GetLastError());
141 store1 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
142 CERT_STORE_DELETE_FLAG, NULL);
143 ok(!store1 && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED,
144 "Expected ERROR_CALL_NOT_IMPLEMENTED, got %ld\n", GetLastError());
147 store1 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
148 CERT_STORE_CREATE_NEW_FLAG, NULL);
149 ok(store1 != NULL, "CertOpenStore failed: %ld\n", GetLastError());
150 /* open existing doesn't */
151 store2 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
152 CERT_STORE_OPEN_EXISTING_FLAG, NULL);
153 ok(store2 != NULL, "CertOpenStore failed: %ld\n", GetLastError());
154 ok(store1 != store2, "Expected different stores\n");
156 /* add a bogus (empty) cert */
158 ret = CertAddEncodedCertificateToStore(store1, X509_ASN_ENCODING, emptyCert,
159 sizeof(emptyCert), CERT_STORE_ADD_ALWAYS, &context);
160 /* Windows returns CRYPT_E_ASN1_EOD, but accept CRYPT_E_ASN1_CORRUPT as
161 * well (because matching errors is tough in this case)
163 ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD || GetLastError() ==
164 CRYPT_E_ASN1_CORRUPT),
165 "Expected CRYPT_E_ASN1_EOD or CRYPT_E_ASN1_CORRUPT, got %08lx\n",
167 /* add a "signed" cert--the signature isn't a real signature, so this adds
168 * without any check of the signature's validity
170 ret = CertAddEncodedCertificateToStore(store1, X509_ASN_ENCODING,
171 signedBigCert, sizeof(signedBigCert), CERT_STORE_ADD_ALWAYS, &context);
172 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n", GetLastError());
173 ok(context != NULL, "Expected a valid cert context\n");
176 ok(context->cbCertEncoded == sizeof(signedBigCert),
177 "Expected cert of %d bytes, got %ld\n", sizeof(signedBigCert),
178 context->cbCertEncoded);
179 ok(!memcmp(context->pbCertEncoded, signedBigCert,
180 sizeof(signedBigCert)), "Unexpected encoded cert in context\n");
181 /* remove it, the rest of the tests will work on an unsigned cert */
182 ret = CertDeleteCertificateFromStore(context);
183 ok(ret, "CertDeleteCertificateFromStore failed: %08lx\n",
186 /* try adding a "signed" CRL as a cert */
187 ret = CertAddEncodedCertificateToStore(store1, X509_ASN_ENCODING,
188 signedCRL, sizeof(signedCRL), CERT_STORE_ADD_ALWAYS, &context);
189 ok(!ret && (GetLastError() == CRYPT_E_ASN1_BADTAG || GetLastError() ==
190 CRYPT_E_ASN1_CORRUPT),
191 "Expected CRYPT_E_ASN1_BADTAG or CRYPT_E_ASN1_CORRUPT, got %08lx\n",
193 /* add a cert to store1 */
194 ret = CertAddEncodedCertificateToStore(store1, X509_ASN_ENCODING, bigCert,
195 sizeof(bigCert) - 1, CERT_STORE_ADD_ALWAYS, &context);
196 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n", GetLastError());
197 ok(context != NULL, "Expected a valid cert context\n");
203 ok(context->cbCertEncoded == sizeof(bigCert) - 1,
204 "Expected cert of %d bytes, got %ld\n", sizeof(bigCert) - 1,
205 context->cbCertEncoded);
206 ok(!memcmp(context->pbCertEncoded, bigCert, sizeof(bigCert) - 1),
207 "Unexpected encoded cert in context\n");
208 ok(context->hCertStore == store1, "Unexpected store\n");
210 /* check serializing this element */
212 ret = CertSerializeCertificateStoreElement(NULL, 0, NULL, NULL);
213 ret = CertSerializeCertificateStoreElement(context, 0, NULL, NULL);
214 ret = CertSerializeCertificateStoreElement(NULL, 0, NULL, &size);
216 /* apparently flags are ignored */
217 ret = CertSerializeCertificateStoreElement(context, 1, NULL, &size);
218 ok(ret, "CertSerializeCertificateStoreElement failed: %08lx\n",
220 buf = HeapAlloc(GetProcessHeap(), 0, size);
223 ret = CertSerializeCertificateStoreElement(context, 0, buf, &size);
224 ok(size == sizeof(serializedCert), "Expected size %d, got %ld\n",
225 sizeof(serializedCert), size);
226 ok(!memcmp(serializedCert, buf, size),
227 "Unexpected serialized cert\n");
228 HeapFree(GetProcessHeap(), 0, buf);
231 ret = CertFreeCertificateContext(context);
232 ok(ret, "CertFreeCertificateContext failed: %08lx\n", GetLastError());
234 /* verify the cert's in store1 */
235 context = CertEnumCertificatesInStore(store1, NULL);
236 ok(context != NULL, "Expected a valid context\n");
237 context = CertEnumCertificatesInStore(store1, context);
238 ok(!context && GetLastError() == CRYPT_E_NOT_FOUND,
239 "Expected CRYPT_E_NOT_FOUND, got %08lx\n", GetLastError());
240 /* verify store2 (the "open existing" mem store) is still empty */
241 context = CertEnumCertificatesInStore(store2, NULL);
242 ok(!context, "Expected an empty store\n");
243 /* delete the cert from store1, and check it's empty */
244 context = CertEnumCertificatesInStore(store1, NULL);
247 /* Deleting a bitwise copy crashes with an access to an uninitialized
248 * pointer, so a cert context has some special data out there in memory
251 memcpy(©, context, sizeof(copy));
252 ret = CertDeleteCertificateFromStore(©);
254 PCCERT_CONTEXT copy = CertDuplicateCertificateContext(context);
256 ok(copy != NULL, "CertDuplicateCertificateContext failed: %08lx\n",
258 ret = CertDeleteCertificateFromStore(context);
259 ok(ret, "CertDeleteCertificateFromStore failed: %08lx\n",
261 /* try deleting a copy */
262 ret = CertDeleteCertificateFromStore(copy);
263 ok(ret, "CertDeleteCertificateFromStore failed: %08lx\n",
265 /* check that the store is empty */
266 context = CertEnumCertificatesInStore(store1, NULL);
267 ok(!context, "Expected an empty store\n");
270 /* close an empty store */
271 ret = CertCloseStore(NULL, 0);
272 ok(ret, "CertCloseStore failed: %ld\n", GetLastError());
273 ret = CertCloseStore(store1, 0);
274 ok(ret, "CertCloseStore failed: %ld\n", GetLastError());
275 ret = CertCloseStore(store2, 0);
276 ok(ret, "CertCloseStore failed: %ld\n", GetLastError());
278 /* This seems nonsensical, but you can open a read-only mem store, only
281 store1 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
282 CERT_STORE_READONLY_FLAG, NULL);
283 ok(store1 != NULL, "CertOpenStore failed: %ld\n", GetLastError());
284 /* yep, this succeeds */
285 ret = CertAddEncodedCertificateToStore(store1, X509_ASN_ENCODING, bigCert,
286 sizeof(bigCert) - 1, CERT_STORE_ADD_ALWAYS, &context);
287 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n", GetLastError());
288 ok(context != NULL, "Expected a valid cert context\n");
291 ok(context->cbCertEncoded == sizeof(bigCert) - 1,
292 "Expected cert of %d bytes, got %ld\n", sizeof(bigCert) - 1,
293 context->cbCertEncoded);
294 ok(!memcmp(context->pbCertEncoded, bigCert, sizeof(bigCert) - 1),
295 "Unexpected encoded cert in context\n");
296 ok(context->hCertStore == store1, "Unexpected store\n");
297 ret = CertDeleteCertificateFromStore(context);
298 ok(ret, "CertDeleteCertificateFromStore failed: %08lx\n",
301 CertCloseStore(store1, 0);
304 static const BYTE bigCert2[] = "\x30\x7a\x02\x01\x01\x30\x02\x06\x00"
305 "\x30\x15\x31\x13\x30\x11\x06\x03\x55\x04\x03\x13\x0a\x41\x6c\x65\x78\x20\x4c"
306 "\x61\x6e\x67\x00\x30\x22\x18\x0f\x31\x36\x30\x31\x30\x31\x30\x31\x30\x30\x30"
307 "\x30\x30\x30\x5a\x18\x0f\x31\x36\x30\x31\x30\x31\x30\x31\x30\x30\x30\x30\x30"
308 "\x30\x5a\x30\x15\x31\x13\x30\x11\x06\x03\x55\x04\x03\x13\x0a\x41\x6c\x65\x78"
309 "\x20\x4c\x61\x6e\x67\x00\x30\x07\x30\x02\x06\x00\x03\x01\x00\xa3\x16\x30\x14"
310 "\x30\x12\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x08\x30\x06\x01\x01\xff\x02\x01"
313 static void testCollectionStore(void)
315 HCERTSTORE store1, store2, collection, collection2;
316 PCCERT_CONTEXT context;
319 collection = CertOpenStore(CERT_STORE_PROV_COLLECTION, 0, 0,
320 CERT_STORE_CREATE_NEW_FLAG, NULL);
322 /* Try adding a cert to any empty collection */
323 ret = CertAddEncodedCertificateToStore(collection, X509_ASN_ENCODING,
324 bigCert, sizeof(bigCert) - 1, CERT_STORE_ADD_ALWAYS, NULL);
325 ok(!ret && GetLastError() == HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED),
326 "Expected HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED), got %08lx\n",
329 /* Create and add a cert to a memory store */
330 store1 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
331 CERT_STORE_CREATE_NEW_FLAG, NULL);
332 ret = CertAddEncodedCertificateToStore(store1, X509_ASN_ENCODING,
333 bigCert, sizeof(bigCert) - 1, CERT_STORE_ADD_ALWAYS, NULL);
334 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n", GetLastError());
335 /* Add the memory store to the collection, without allowing adding */
336 ret = CertAddStoreToCollection(collection, store1, 0, 0);
337 ok(ret, "CertAddStoreToCollection failed: %08lx\n", GetLastError());
338 /* Verify the cert is in the collection */
339 context = CertEnumCertificatesInStore(collection, NULL);
340 ok(context != NULL, "Expected a valid context\n");
343 ok(context->hCertStore == collection, "Unexpected store\n");
344 CertFreeCertificateContext(context);
346 /* Check that adding to the collection isn't allowed */
347 ret = CertAddEncodedCertificateToStore(collection, X509_ASN_ENCODING,
348 bigCert2, sizeof(bigCert2) - 1, CERT_STORE_ADD_ALWAYS, NULL);
349 ok(!ret && GetLastError() == HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED),
350 "Expected HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED), got %08lx\n",
353 /* Create a new memory store */
354 store2 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
355 CERT_STORE_CREATE_NEW_FLAG, NULL);
356 /* Try adding a store to a non-collection store */
357 ret = CertAddStoreToCollection(store1, store2,
358 CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
359 ok(!ret && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
360 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
362 /* Try adding some bogus stores */
363 /* This crashes in Windows
364 ret = CertAddStoreToCollection(0, store2,
365 CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
367 /* This "succeeds"... */
368 ret = CertAddStoreToCollection(collection, 0,
369 CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
370 ok(ret, "CertAddStoreToCollection failed: %08lx\n", GetLastError());
371 /* while this crashes.
372 ret = CertAddStoreToCollection(collection, 1,
373 CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
376 /* Add it to the collection, this time allowing adding */
377 ret = CertAddStoreToCollection(collection, store2,
378 CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
379 ok(ret, "CertAddStoreToCollection failed: %08lx\n", GetLastError());
380 /* Check that adding to the collection is allowed */
381 ret = CertAddEncodedCertificateToStore(collection, X509_ASN_ENCODING,
382 bigCert2, sizeof(bigCert2) - 1, CERT_STORE_ADD_ALWAYS, NULL);
383 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n", GetLastError());
384 /* Now check that it was actually added to store2 */
385 context = CertEnumCertificatesInStore(store2, NULL);
386 ok(context != NULL, "Expected a valid context\n");
389 ok(context->hCertStore == store2, "Unexpected store\n");
390 CertFreeCertificateContext(context);
392 /* Check that the collection has both bigCert and bigCert2. bigCert comes
393 * first because store1 was added first.
395 context = CertEnumCertificatesInStore(collection, NULL);
396 ok(context != NULL, "Expected a valid context\n");
399 ok(context->hCertStore == collection, "Unexpected store\n");
400 ok(context->cbCertEncoded == sizeof(bigCert) - 1,
401 "Expected size %d, got %ld\n", sizeof(bigCert) - 1,
402 context->cbCertEncoded);
403 ok(!memcmp(context->pbCertEncoded, bigCert, context->cbCertEncoded),
404 "Unexpected cert\n");
405 context = CertEnumCertificatesInStore(collection, context);
406 ok(context != NULL, "Expected a valid context\n");
409 ok(context->hCertStore == collection, "Unexpected store\n");
410 ok(context->cbCertEncoded == sizeof(bigCert2) - 1,
411 "Expected size %d, got %ld\n", sizeof(bigCert2) - 1,
412 context->cbCertEncoded);
413 ok(!memcmp(context->pbCertEncoded, bigCert2,
414 context->cbCertEncoded), "Unexpected cert\n");
415 context = CertEnumCertificatesInStore(collection, context);
416 ok(!context, "Unexpected cert\n");
419 /* close store2, and check that the collection is unmodified */
420 CertCloseStore(store2, 0);
421 context = CertEnumCertificatesInStore(collection, NULL);
422 ok(context != NULL, "Expected a valid context\n");
425 ok(context->hCertStore == collection, "Unexpected store\n");
426 ok(context->cbCertEncoded == sizeof(bigCert) - 1,
427 "Expected size %d, got %ld\n", sizeof(bigCert) - 1,
428 context->cbCertEncoded);
429 ok(!memcmp(context->pbCertEncoded, bigCert, context->cbCertEncoded),
430 "Unexpected cert\n");
431 context = CertEnumCertificatesInStore(collection, context);
432 ok(context != NULL, "Expected a valid context\n");
435 ok(context->hCertStore == collection, "Unexpected store\n");
436 ok(context->cbCertEncoded == sizeof(bigCert2) - 1,
437 "Expected size %d, got %ld\n", sizeof(bigCert2) - 1,
438 context->cbCertEncoded);
439 ok(!memcmp(context->pbCertEncoded, bigCert2,
440 context->cbCertEncoded), "Unexpected cert\n");
441 context = CertEnumCertificatesInStore(collection, context);
442 ok(!context, "Unexpected cert\n");
446 /* Adding a collection to a collection is legal */
447 collection2 = CertOpenStore(CERT_STORE_PROV_COLLECTION, 0, 0,
448 CERT_STORE_CREATE_NEW_FLAG, NULL);
449 ret = CertAddStoreToCollection(collection2, collection,
450 CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
451 ok(ret, "CertAddStoreToCollection failed: %08lx\n", GetLastError());
452 /* check the contents of collection2 */
453 context = CertEnumCertificatesInStore(collection2, NULL);
454 ok(context != NULL, "Expected a valid context\n");
457 ok(context->hCertStore == collection2, "Unexpected store\n");
458 ok(context->cbCertEncoded == sizeof(bigCert) - 1,
459 "Expected size %d, got %ld\n", sizeof(bigCert) - 1,
460 context->cbCertEncoded);
461 ok(!memcmp(context->pbCertEncoded, bigCert, context->cbCertEncoded),
462 "Unexpected cert\n");
463 context = CertEnumCertificatesInStore(collection2, context);
464 ok(context != NULL, "Expected a valid context\n");
467 ok(context->hCertStore == collection2, "Unexpected store\n");
468 ok(context->cbCertEncoded == sizeof(bigCert2) - 1,
469 "Expected size %d, got %ld\n", sizeof(bigCert2) - 1,
470 context->cbCertEncoded);
471 ok(!memcmp(context->pbCertEncoded, bigCert2,
472 context->cbCertEncoded), "Unexpected cert\n");
473 context = CertEnumCertificatesInStore(collection2, context);
474 ok(!context, "Unexpected cert\n");
478 /* I'd like to test closing the collection in the middle of enumeration,
479 * but my tests have been inconsistent. The first time calling
480 * CertEnumCertificatesInStore on a closed collection succeeded, while the
481 * second crashed. So anything appears to be fair game.
482 * I'd also like to test removing a store from a collection in the middle
483 * of an enumeration, but my tests in Windows have been inconclusive.
484 * In one scenario it worked. In another scenario, about a third of the
485 * time this leads to "random" crashes elsewhere in the code. This
486 * probably means this is not allowed.
489 CertCloseStore(store1, 0);
490 CertCloseStore(collection, 0);
491 CertCloseStore(collection2, 0);
493 /* Add the same cert to two memory stores, then put them in a collection */
494 store1 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
495 CERT_STORE_CREATE_NEW_FLAG, NULL);
496 ok(store1 != 0, "CertOpenStore failed: %08lx\n", GetLastError());
497 store2 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
498 CERT_STORE_CREATE_NEW_FLAG, NULL);
499 ok(store2 != 0, "CertOpenStore failed: %08lx\n", GetLastError());
501 ret = CertAddEncodedCertificateToStore(store1, X509_ASN_ENCODING,
502 bigCert, sizeof(bigCert) - 1, CERT_STORE_ADD_ALWAYS, NULL);
503 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n", GetLastError());
504 ret = CertAddEncodedCertificateToStore(store2, X509_ASN_ENCODING,
505 bigCert, sizeof(bigCert) - 1, CERT_STORE_ADD_ALWAYS, NULL);
506 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n", GetLastError());
507 collection = CertOpenStore(CERT_STORE_PROV_COLLECTION, 0, 0,
508 CERT_STORE_CREATE_NEW_FLAG, NULL);
509 ok(collection != 0, "CertOpenStore failed: %08lx\n", GetLastError());
511 ret = CertAddStoreToCollection(collection, store1,
512 CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
513 ok(ret, "CertAddStoreToCollection failed: %08lx\n", GetLastError());
514 ret = CertAddStoreToCollection(collection, store2,
515 CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
516 ok(ret, "CertAddStoreToCollection failed: %08lx\n", GetLastError());
518 /* Check that the collection has two copies of the same cert */
519 context = CertEnumCertificatesInStore(collection, NULL);
520 ok(context != NULL, "Expected a valid context\n");
523 ok(context->hCertStore == collection, "Unexpected store\n");
524 ok(context->cbCertEncoded == sizeof(bigCert) - 1,
525 "Expected size %d, got %ld\n", sizeof(bigCert) - 1,
526 context->cbCertEncoded);
527 ok(!memcmp(context->pbCertEncoded, bigCert, context->cbCertEncoded),
528 "Unexpected cert\n");
529 context = CertEnumCertificatesInStore(collection, context);
530 ok(context != NULL, "Expected a valid context\n");
533 ok(context->hCertStore == collection, "Unexpected store\n");
534 ok(context->cbCertEncoded == sizeof(bigCert) - 1,
535 "Expected size %d, got %ld\n", sizeof(bigCert) - 1,
536 context->cbCertEncoded);
537 ok(!memcmp(context->pbCertEncoded, bigCert, context->cbCertEncoded),
538 "Unexpected cert\n");
539 context = CertEnumCertificatesInStore(collection, context);
540 ok(context == NULL, "Unexpected cert\n");
544 /* The following would check whether I can delete an identical cert, rather
545 * than one enumerated from the store. It crashes, so that means I must
546 * only call CertDeleteCertificateFromStore with contexts enumerated from
548 context = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert,
549 sizeof(bigCert) - 1);
550 ok(context != NULL, "CertCreateCertificateContext failed: %08lx\n",
554 ret = CertDeleteCertificateFromStore(collection, context);
555 printf("ret is %d, GetLastError is %08lx\n", ret, GetLastError());
556 CertFreeCertificateContext(context);
560 /* Now check deleting from the collection. */
561 context = CertEnumCertificatesInStore(collection, NULL);
562 ok(context != NULL, "Expected a valid context\n");
565 CertDeleteCertificateFromStore(context);
566 /* store1 should now be empty */
567 context = CertEnumCertificatesInStore(store1, NULL);
568 ok(!context, "Unexpected cert\n");
569 /* and there should be one certificate in the collection */
570 context = CertEnumCertificatesInStore(collection, NULL);
571 ok(context != NULL, "Expected a valid cert\n");
574 ok(context->hCertStore == collection, "Unexpected store\n");
575 ok(context->cbCertEncoded == sizeof(bigCert) - 1,
576 "Expected size %d, got %ld\n", sizeof(bigCert) - 1,
577 context->cbCertEncoded);
578 ok(!memcmp(context->pbCertEncoded, bigCert, context->cbCertEncoded),
579 "Unexpected cert\n");
581 context = CertEnumCertificatesInStore(collection, context);
582 ok(context == NULL, "Unexpected cert\n");
585 /* Finally, test removing stores from the collection. No return value, so
586 * it's a bit funny to test.
589 CertRemoveStoreFromCollection(NULL, NULL);
591 /* This "succeeds," no crash, no last error set */
592 SetLastError(0xdeadbeef);
593 CertRemoveStoreFromCollection(store2, collection);
594 ok(GetLastError() == 0xdeadbeef,
595 "Didn't expect an error to be set: %08lx\n", GetLastError());
597 /* After removing store2, the collection should be empty */
598 SetLastError(0xdeadbeef);
599 CertRemoveStoreFromCollection(collection, store2);
600 ok(GetLastError() == 0xdeadbeef,
601 "Didn't expect an error to be set: %08lx\n", GetLastError());
602 context = CertEnumCertificatesInStore(collection, NULL);
603 ok(!context, "Unexpected cert\n");
605 CertCloseStore(collection, 0);
606 CertCloseStore(store2, 0);
607 CertCloseStore(store1, 0);
610 /* Looks for the property with ID propID in the buffer buf. Returns a pointer
611 * to its header if found, NULL if not.
613 static const struct CertPropIDHeader *findPropID(const BYTE *buf, DWORD size,
616 const struct CertPropIDHeader *ret = NULL;
619 while (size && !ret && !failed)
621 if (size < sizeof(struct CertPropIDHeader))
625 const struct CertPropIDHeader *hdr =
626 (const struct CertPropIDHeader *)buf;
628 size -= sizeof(struct CertPropIDHeader);
629 buf += sizeof(struct CertPropIDHeader);
632 else if (hdr->propID == propID)
644 typedef DWORD (WINAPI *SHDeleteKeyAFunc)(HKEY, LPCSTR);
646 static void testRegStore(void)
648 static const char tempKey[] = "Software\\Wine\\CryptTemp";
654 store = CertOpenStore(CERT_STORE_PROV_REG, 0, 0, 0, NULL);
655 ok(!store && GetLastError() == ERROR_INVALID_HANDLE,
656 "Expected ERROR_INVALID_HANDLE, got %ld\n", GetLastError());
657 store = CertOpenStore(CERT_STORE_PROV_REG, 0, 0, 0, key);
658 ok(!store && GetLastError() == ERROR_INVALID_HANDLE,
659 "Expected ERROR_INVALID_HANDLE, got %ld\n", GetLastError());
661 /* Opening up any old key works.. */
662 key = HKEY_CURRENT_USER;
663 store = CertOpenStore(CERT_STORE_PROV_REG, 0, 0, 0, key);
664 /* Not sure if this is a bug in DuplicateHandle, marking todo_wine for now
666 todo_wine ok(store != 0, "CertOpenStore failed: %08lx\n", GetLastError());
667 CertCloseStore(store, 0);
669 rc = RegCreateKeyExA(HKEY_CURRENT_USER, tempKey, 0, NULL, 0, KEY_ALL_ACCESS,
671 ok(!rc, "RegCreateKeyExA failed: %ld\n", rc);
677 static const char certificates[] = "Certificates\\";
678 char subKeyName[sizeof(certificates) + 20 * 2 + 1], *ptr;
680 PCCERT_CONTEXT context;
682 store = CertOpenStore(CERT_STORE_PROV_REG, 0, 0, 0, key);
683 ok(store != 0, "CertOpenStore failed: %08lx\n", GetLastError());
684 /* Add a certificate. It isn't persisted right away, since it's only
685 * added to the cache..
687 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
688 bigCert2, sizeof(bigCert2) - 1, CERT_STORE_ADD_ALWAYS, NULL);
689 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n",
691 /* so flush the cache to force a commit.. */
692 ret = CertControlStore(store, 0, CERT_STORE_CTRL_COMMIT, NULL);
693 ok(ret, "CertControlStore failed: %08lx\n", GetLastError());
694 /* and check that the expected subkey was written. */
696 ret = CryptHashCertificate(0, 0, 0, bigCert2, sizeof(bigCert2) - 1,
698 ok(ret, "CryptHashCertificate failed: %ld\n", GetLastError());
699 strcpy(subKeyName, certificates);
700 for (i = 0, ptr = subKeyName + sizeof(certificates) - 1; i < size;
702 sprintf(ptr, "%02X", hash[i]);
703 rc = RegCreateKeyExA(key, subKeyName, 0, NULL, 0, KEY_ALL_ACCESS, NULL,
705 ok(!rc, "RegCreateKeyExA failed: %ld\n", rc);
711 RegQueryValueExA(subKey, "Blob", NULL, NULL, NULL, &size);
712 buf = HeapAlloc(GetProcessHeap(), 0, size);
715 rc = RegQueryValueExA(subKey, "Blob", NULL, NULL, buf, &size);
716 ok(!rc, "RegQueryValueExA failed: %ld\n", rc);
719 const struct CertPropIDHeader *hdr;
721 /* Both the hash and the cert should be present */
722 hdr = findPropID(buf, size, CERT_CERT_PROP_ID);
723 ok(hdr != NULL, "Expected to find a cert property\n");
726 ok(hdr->cb == sizeof(bigCert2) - 1,
727 "Unexpected size %ld of cert property, expected %d\n",
728 hdr->cb, sizeof(bigCert2) - 1);
729 ok(!memcmp((BYTE *)hdr + sizeof(*hdr), bigCert2,
730 hdr->cb), "Unexpected cert in cert property\n");
732 hdr = findPropID(buf, size, CERT_HASH_PROP_ID);
733 ok(hdr != NULL, "Expected to find a hash property\n");
736 ok(hdr->cb == sizeof(hash),
737 "Unexpected size %ld of hash property, expected %d\n",
738 hdr->cb, sizeof(hash));
739 ok(!memcmp((BYTE *)hdr + sizeof(*hdr), hash,
740 hdr->cb), "Unexpected hash in cert property\n");
743 HeapFree(GetProcessHeap(), 0, buf);
748 /* Remove the existing context */
749 context = CertEnumCertificatesInStore(store, NULL);
750 ok(context != NULL, "Expected a cert context\n");
752 CertDeleteCertificateFromStore(context);
753 ret = CertControlStore(store, 0, CERT_STORE_CTRL_COMMIT, NULL);
754 ok(ret, "CertControlStore failed: %08lx\n", GetLastError());
756 /* Add a serialized cert with a bogus hash directly to the registry */
757 memset(hash, 0, sizeof(hash));
758 strcpy(subKeyName, certificates);
759 for (i = 0, ptr = subKeyName + sizeof(certificates) - 1;
760 i < sizeof(hash); i++, ptr += 2)
761 sprintf(ptr, "%02X", hash[i]);
762 rc = RegCreateKeyExA(key, subKeyName, 0, NULL, 0, KEY_ALL_ACCESS, NULL,
764 ok(!rc, "RegCreateKeyExA failed: %ld\n", rc);
767 BYTE buf[sizeof(struct CertPropIDHeader) * 2 + sizeof(hash) +
768 sizeof(bigCert) - 1], *ptr;
770 struct CertPropIDHeader *hdr;
772 hdr = (struct CertPropIDHeader *)buf;
773 hdr->propID = CERT_HASH_PROP_ID;
775 hdr->cb = sizeof(hash);
776 ptr = buf + sizeof(*hdr);
777 memcpy(ptr, hash, sizeof(hash));
779 hdr = (struct CertPropIDHeader *)ptr;
780 hdr->propID = CERT_CERT_PROP_ID;
782 hdr->cb = sizeof(bigCert) - 1;
784 memcpy(ptr, bigCert, sizeof(bigCert) - 1);
786 rc = RegSetValueExA(subKey, "Blob", 0, REG_BINARY, buf,
788 ok(!rc, "RegSetValueExA failed: %ld\n", rc);
790 ret = CertControlStore(store, 0, CERT_STORE_CTRL_RESYNC, NULL);
791 ok(ret, "CertControlStore failed: %08lx\n", GetLastError());
793 /* Make sure the bogus hash cert gets loaded. */
797 context = CertEnumCertificatesInStore(store, context);
800 } while (context != NULL);
801 ok(certCount == 1, "Expected 1 certificates, got %ld\n", certCount);
806 /* Add another serialized cert directly to the registry, this time
807 * under the correct key name (named with the correct hash value).
810 ret = CryptHashCertificate(0, 0, 0, bigCert2,
811 sizeof(bigCert2) - 1, hash, &size);
812 ok(ret, "CryptHashCertificate failed: %ld\n", GetLastError());
813 strcpy(subKeyName, certificates);
814 for (i = 0, ptr = subKeyName + sizeof(certificates) - 1;
815 i < sizeof(hash); i++, ptr += 2)
816 sprintf(ptr, "%02X", hash[i]);
817 rc = RegCreateKeyExA(key, subKeyName, 0, NULL, 0, KEY_ALL_ACCESS, NULL,
819 ok(!rc, "RegCreateKeyExA failed: %ld\n", rc);
822 BYTE buf[sizeof(struct CertPropIDHeader) * 2 + sizeof(hash) +
823 sizeof(bigCert2) - 1], *ptr;
825 PCCERT_CONTEXT context;
826 struct CertPropIDHeader *hdr;
828 /* First try with a bogus hash... */
829 hdr = (struct CertPropIDHeader *)buf;
830 hdr->propID = CERT_HASH_PROP_ID;
832 hdr->cb = sizeof(hash);
833 ptr = buf + sizeof(*hdr);
834 memset(ptr, 0, sizeof(hash));
836 hdr = (struct CertPropIDHeader *)ptr;
837 hdr->propID = CERT_CERT_PROP_ID;
839 hdr->cb = sizeof(bigCert2) - 1;
841 memcpy(ptr, bigCert2, sizeof(bigCert2) - 1);
843 rc = RegSetValueExA(subKey, "Blob", 0, REG_BINARY, buf,
845 ok(!rc, "RegSetValueExA failed: %ld\n", rc);
847 ret = CertControlStore(store, 0, CERT_STORE_CTRL_RESYNC, NULL);
848 ok(ret, "CertControlStore failed: %08lx\n", GetLastError());
850 /* and make sure just one cert still gets loaded. */
854 context = CertEnumCertificatesInStore(store, context);
857 } while (context != NULL);
858 ok(certCount == 1, "Expected 1 certificates, got %ld\n", certCount);
860 /* Try again with the correct hash... */
861 ptr = buf + sizeof(*hdr);
862 memcpy(ptr, hash, sizeof(hash));
864 rc = RegSetValueExA(subKey, "Blob", 0, REG_BINARY, buf,
866 ok(!rc, "RegSetValueExA failed: %ld\n", rc);
868 ret = CertControlStore(store, 0, CERT_STORE_CTRL_RESYNC, NULL);
869 ok(ret, "CertControlStore failed: %08lx\n", GetLastError());
871 /* and make sure two certs get loaded. */
875 context = CertEnumCertificatesInStore(store, context);
878 } while (context != NULL);
879 ok(certCount == 2, "Expected 2 certificates, got %ld\n", certCount);
883 CertCloseStore(store, 0);
884 /* Is delete allowed on a reg store? */
885 store = CertOpenStore(CERT_STORE_PROV_REG, 0, 0,
886 CERT_STORE_DELETE_FLAG, key);
887 ok(store == NULL, "Expected NULL return from CERT_STORE_DELETE_FLAG\n");
888 ok(GetLastError() == 0, "CertOpenStore failed: %08lx\n",
893 /* The CertOpenStore with CERT_STORE_DELETE_FLAG above will delete the
894 * contents of the key, but not the key itself.
896 rc = RegCreateKeyExA(HKEY_CURRENT_USER, tempKey, 0, NULL, 0, KEY_ALL_ACCESS,
898 ok(!rc, "RegCreateKeyExA failed: %ld\n", rc);
899 ok(disp == REG_OPENED_EXISTING_KEY,
900 "Expected REG_OPENED_EXISTING_KEY, got %ld\n", disp);
904 rc = RegDeleteKeyA(HKEY_CURRENT_USER, tempKey);
907 HMODULE shlwapi = LoadLibraryA("shlwapi");
909 /* Use shlwapi's SHDeleteKeyA to _really_ blow away the key,
910 * otherwise subsequent tests will fail.
914 SHDeleteKeyAFunc pSHDeleteKeyA =
915 (SHDeleteKeyAFunc)GetProcAddress(shlwapi, "SHDeleteKeyA");
918 pSHDeleteKeyA(HKEY_CURRENT_USER, tempKey);
919 FreeLibrary(shlwapi);
925 static const char MyA[] = { 'M','y',0,0 };
926 static const WCHAR MyW[] = { 'M','y',0 };
927 static const WCHAR BogusW[] = { 'B','o','g','u','s',0 };
928 static const WCHAR BogusPathW[] = { 'S','o','f','t','w','a','r','e','\\',
929 'M','i','c','r','o','s','o','f','t','\\','S','y','s','t','e','m','C','e','r',
930 't','i','f','i','c','a','t','e','s','\\','B','o','g','u','s',0 };
932 static void testSystemRegStore(void)
934 HCERTSTORE store, memStore;
936 /* Check with a UNICODE name */
937 store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0,
938 CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_OPEN_EXISTING_FLAG, MyW);
939 /* Not all OSes support CERT_STORE_PROV_SYSTEM_REGISTRY, so don't continue
940 * testing if they don't.
945 /* Check that it isn't a collection store */
946 memStore = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
947 CERT_STORE_CREATE_NEW_FLAG, NULL);
950 BOOL ret = CertAddStoreToCollection(store, memStore, 0, 0);
952 ok(!ret && GetLastError() ==
953 HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
954 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
956 CertCloseStore(memStore, 0);
958 CertCloseStore(store, 0);
960 /* Check opening a bogus store */
961 store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0,
962 CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_OPEN_EXISTING_FLAG, BogusW);
963 ok(!store && GetLastError() == ERROR_FILE_NOT_FOUND,
964 "Expected ERROR_FILE_NOT_FOUND, got %08lx\n", GetLastError());
965 store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0,
966 CERT_SYSTEM_STORE_CURRENT_USER, BogusW);
967 ok(store != 0, "CertOpenStore failed: %08lx\n", GetLastError());
969 CertCloseStore(store, 0);
970 /* Now check whether deleting is allowed */
971 store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0,
972 CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_DELETE_FLAG, BogusW);
973 RegDeleteKeyW(HKEY_CURRENT_USER, BogusPathW);
975 store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0, 0, NULL);
976 ok(!store && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
977 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
979 store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0,
980 CERT_SYSTEM_STORE_LOCAL_MACHINE | CERT_SYSTEM_STORE_CURRENT_USER, MyA);
981 ok(!store && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
982 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
984 store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0,
985 CERT_SYSTEM_STORE_LOCAL_MACHINE | CERT_SYSTEM_STORE_CURRENT_USER, MyW);
986 ok(!store && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
987 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
989 /* The name is expected to be UNICODE, check with an ASCII name */
990 store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0,
991 CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_OPEN_EXISTING_FLAG, MyA);
992 ok(!store && GetLastError() == ERROR_FILE_NOT_FOUND,
993 "Expected ERROR_FILE_NOT_FOUND, got %08lx\n", GetLastError());
996 static void testSystemStore(void)
998 static const WCHAR baskslashW[] = { '\\',0 };
1000 WCHAR keyName[MAX_PATH];
1004 store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0, 0, NULL);
1005 ok(!store && GetLastError() == ERROR_FILE_NOT_FOUND,
1006 "Expected ERROR_FILE_NOT_FOUND, got %08lx\n", GetLastError());
1007 store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
1008 CERT_SYSTEM_STORE_LOCAL_MACHINE | CERT_SYSTEM_STORE_CURRENT_USER, MyA);
1009 ok(!store && GetLastError() == ERROR_FILE_NOT_FOUND,
1010 "Expected ERROR_FILE_NOT_FOUND, got %08lx\n", GetLastError());
1011 store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
1012 CERT_SYSTEM_STORE_LOCAL_MACHINE | CERT_SYSTEM_STORE_CURRENT_USER, MyW);
1013 ok(!store && GetLastError() == ERROR_FILE_NOT_FOUND,
1014 "Expected ERROR_FILE_NOT_FOUND, got %08lx\n", GetLastError());
1015 /* The name is expected to be UNICODE, first check with an ASCII name */
1016 store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
1017 CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_OPEN_EXISTING_FLAG, MyA);
1018 ok(!store && GetLastError() == ERROR_FILE_NOT_FOUND,
1019 "Expected ERROR_FILE_NOT_FOUND, got %08lx\n", GetLastError());
1020 /* Create the expected key */
1021 lstrcpyW(keyName, CERT_LOCAL_MACHINE_SYSTEM_STORE_REGPATH);
1022 lstrcatW(keyName, baskslashW);
1023 lstrcatW(keyName, MyW);
1024 rc = RegCreateKeyExW(HKEY_CURRENT_USER, keyName, 0, NULL, 0, KEY_READ,
1026 ok(!rc, "RegCreateKeyEx failed: %ld\n", rc);
1029 /* Check opening with a UNICODE name, specifying the create new flag */
1030 store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
1031 CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_CREATE_NEW_FLAG, MyW);
1032 ok(!store && GetLastError() == ERROR_FILE_EXISTS,
1033 "Expected ERROR_FILE_EXISTS, got %08lx\n", GetLastError());
1034 /* Now check opening with a UNICODE name, this time opening existing */
1035 store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
1036 CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_OPEN_EXISTING_FLAG, MyW);
1037 ok(store != 0, "CertOpenStore failed: %08lx\n", GetLastError());
1040 HCERTSTORE memStore = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
1041 CERT_STORE_CREATE_NEW_FLAG, NULL);
1043 /* Check that it's a collection store */
1046 BOOL ret = CertAddStoreToCollection(store, memStore, 0, 0);
1048 /* FIXME: this'll fail on NT4, but what error will it give? */
1049 ok(ret, "CertAddStoreToCollection failed: %08lx\n", GetLastError());
1050 CertCloseStore(memStore, 0);
1052 CertCloseStore(store, 0);
1055 /* Check opening a bogus store */
1056 store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
1057 CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_OPEN_EXISTING_FLAG, BogusW);
1058 ok(!store && GetLastError() == ERROR_FILE_NOT_FOUND,
1059 "Expected ERROR_FILE_NOT_FOUND, got %08lx\n", GetLastError());
1060 store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
1061 CERT_SYSTEM_STORE_CURRENT_USER, BogusW);
1062 ok(store != 0, "CertOpenStore failed: %08lx\n", GetLastError());
1064 CertCloseStore(store, 0);
1065 /* Now check whether deleting is allowed */
1066 store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
1067 CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_DELETE_FLAG, BogusW);
1068 RegDeleteKeyW(HKEY_CURRENT_USER, BogusPathW);
1071 static void testCertOpenSystemStore(void)
1075 store = CertOpenSystemStoreW(0, NULL);
1076 ok(!store && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
1077 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
1079 /* This succeeds, and on WinXP at least, the Bogus key is created under
1080 * HKCU (but not under HKLM, even when run as an administrator.)
1082 store = CertOpenSystemStoreW(0, BogusW);
1083 ok(store != 0, "CertOpenSystemStore failed: %08lx\n", GetLastError());
1085 CertCloseStore(store, 0);
1086 /* Delete it so other tests succeed next time around */
1087 store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
1088 CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_DELETE_FLAG, BogusW);
1089 RegDeleteKeyW(HKEY_CURRENT_USER, BogusPathW);
1092 static void checkHash(const BYTE *data, DWORD dataLen, ALG_ID algID,
1093 PCCERT_CONTEXT context, DWORD propID)
1095 BYTE hash[20] = { 0 }, hashProperty[20];
1099 memset(hash, 0, sizeof(hash));
1100 memset(hashProperty, 0, sizeof(hashProperty));
1101 size = sizeof(hash);
1102 ret = CryptHashCertificate(0, algID, 0, data, dataLen, hash, &size);
1103 ok(ret, "CryptHashCertificate failed: %08lx\n", GetLastError());
1104 ret = CertGetCertificateContextProperty(context, propID, hashProperty,
1106 ok(ret, "CertGetCertificateContextProperty failed: %08lx\n",
1108 ok(!memcmp(hash, hashProperty, size), "Unexpected hash for property %ld\n",
1112 static void testCertProperties(void)
1114 PCCERT_CONTEXT context = CertCreateCertificateContext(X509_ASN_ENCODING,
1115 bigCert, sizeof(bigCert) - 1);
1117 ok(context != NULL, "CertCreateCertificateContext failed: %08lx\n",
1121 DWORD propID, numProps, access, size;
1123 BYTE hash[20] = { 0 }, hashProperty[20];
1124 CRYPT_DATA_BLOB blob;
1127 propID = CertEnumCertificateContextProperties(NULL, 0);
1133 propID = CertEnumCertificateContextProperties(context, propID);
1136 } while (propID != 0);
1137 ok(numProps == 0, "Expected 0 properties, got %ld\n", numProps);
1139 /* Tests with a NULL cert context. Prop ID 0 fails.. */
1140 ret = CertSetCertificateContextProperty(NULL, 0, 0, NULL);
1141 ok(!ret && GetLastError() ==
1142 HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
1143 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
1145 /* while this just crashes.
1146 ret = CertSetCertificateContextProperty(NULL,
1147 CERT_KEY_PROV_HANDLE_PROP_ID, 0, NULL);
1150 ret = CertSetCertificateContextProperty(context, 0, 0, NULL);
1151 ok(!ret && GetLastError() ==
1152 HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
1153 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
1155 /* Can't set the cert property directly, this crashes.
1156 ret = CertSetCertificateContextProperty(context,
1157 CERT_CERT_PROP_ID, 0, bigCert2);
1161 ret = CertGetCertificateContextProperty(context,
1162 CERT_ACCESS_STATE_PROP_ID, 0, NULL);
1163 ret = CertGetCertificateContextProperty(context, CERT_HASH_PROP_ID,
1165 ret = CertGetCertificateContextProperty(context, CERT_HASH_PROP_ID,
1166 hashProperty, NULL);
1168 /* A missing prop */
1170 ret = CertGetCertificateContextProperty(context,
1171 CERT_KEY_PROV_INFO_PROP_ID, NULL, &size);
1172 ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
1173 "Expected CRYPT_E_NOT_FOUND, got %08lx\n", GetLastError());
1174 /* And, an implicit property */
1175 size = sizeof(access);
1176 ret = CertGetCertificateContextProperty(context,
1177 CERT_ACCESS_STATE_PROP_ID, &access, &size);
1178 ok(ret, "CertGetCertificateContextProperty failed: %08lx\n",
1180 ok(!(access & CERT_ACCESS_STATE_WRITE_PERSIST_FLAG),
1181 "Didn't expect a persisted cert\n");
1182 /* Trying to set this "read only" property crashes.
1183 access |= CERT_ACCESS_STATE_WRITE_PERSIST_FLAG;
1184 ret = CertSetCertificateContextProperty(context,
1185 CERT_ACCESS_STATE_PROP_ID, 0, &access);
1188 /* Can I set the hash to an invalid hash? */
1190 blob.cbData = sizeof(hash);
1191 ret = CertSetCertificateContextProperty(context, CERT_HASH_PROP_ID, 0,
1193 ok(ret, "CertSetCertificateContextProperty failed: %08lx\n",
1195 size = sizeof(hashProperty);
1196 ret = CertGetCertificateContextProperty(context, CERT_HASH_PROP_ID,
1197 hashProperty, &size);
1198 ok(!memcmp(hashProperty, hash, sizeof(hash)), "Unexpected hash\n");
1199 /* Delete the (bogus) hash, and get the real one */
1200 ret = CertSetCertificateContextProperty(context, CERT_HASH_PROP_ID, 0,
1202 ok(ret, "CertSetCertificateContextProperty failed: %08lx\n",
1204 checkHash(bigCert, sizeof(bigCert) - 1, CALG_SHA1, context,
1207 /* Now that the hash property is set, we should get one property when
1213 propID = CertEnumCertificateContextProperties(context, propID);
1216 } while (propID != 0);
1217 ok(numProps == 1, "Expected 1 properties, got %ld\n", numProps);
1219 /* Check a few other implicit properties */
1220 checkHash(bigCert, sizeof(bigCert) - 1, CALG_MD5, context,
1221 CERT_MD5_HASH_PROP_ID);
1223 context->pCertInfo->Subject.pbData,
1224 context->pCertInfo->Subject.cbData,
1225 CALG_MD5, context, CERT_SUBJECT_NAME_MD5_HASH_PROP_ID);
1227 context->pCertInfo->SubjectPublicKeyInfo.PublicKey.pbData,
1228 context->pCertInfo->SubjectPublicKeyInfo.PublicKey.cbData,
1229 CALG_MD5, context, CERT_SUBJECT_PUBLIC_KEY_MD5_HASH_PROP_ID);
1231 /* Odd: this doesn't fail on other certificates, so there must be
1232 * something weird about this cert that causes it to fail.
1235 ret = CertGetCertificateContextProperty(context,
1236 CERT_KEY_IDENTIFIER_PROP_ID, NULL, &size);
1237 todo_wine ok(!ret && GetLastError() == ERROR_INVALID_DATA,
1238 "Expected ERROR_INVALID_DATA, got %08lx\n", GetLastError());
1240 CertFreeCertificateContext(context);
1244 static void testAddSerialized(void)
1248 BYTE buf[sizeof(struct CertPropIDHeader) * 2 + 20 + sizeof(bigCert) - 1] =
1251 struct CertPropIDHeader *hdr;
1252 PCCERT_CONTEXT context;
1254 ret = CertAddSerializedElementToStore(0, NULL, 0, 0, 0, 0, NULL, NULL);
1255 ok(!ret && GetLastError() == ERROR_END_OF_MEDIA,
1256 "Expected ERROR_END_OF_MEDIA, got %08lx\n", GetLastError());
1258 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
1259 CERT_STORE_CREATE_NEW_FLAG, NULL);
1260 ok(store != 0, "CertOpenStore failed: %08lx\n", GetLastError());
1262 ret = CertAddSerializedElementToStore(store, NULL, 0, 0, 0, 0, NULL, NULL);
1263 ok(!ret && GetLastError() == ERROR_END_OF_MEDIA,
1264 "Expected ERROR_END_OF_MEDIA, got %08lx\n", GetLastError());
1266 /* Test with an empty property */
1267 hdr = (struct CertPropIDHeader *)buf;
1268 hdr->propID = CERT_CERT_PROP_ID;
1271 ret = CertAddSerializedElementToStore(store, buf, sizeof(buf), 0, 0, 0,
1273 ok(!ret && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
1274 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
1276 /* Test with a bad size in property header */
1277 hdr->cb = sizeof(bigCert) - 2;
1278 memcpy(buf + sizeof(struct CertPropIDHeader), bigCert, sizeof(bigCert) - 1);
1279 ret = CertAddSerializedElementToStore(store, buf, sizeof(buf), 0, 0, 0,
1281 ok(!ret && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
1282 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
1284 ret = CertAddSerializedElementToStore(store, buf,
1285 sizeof(struct CertPropIDHeader) + sizeof(bigCert) - 1, 0, 0, 0, NULL,
1287 ok(!ret && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
1288 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
1290 ret = CertAddSerializedElementToStore(store, buf,
1291 sizeof(struct CertPropIDHeader) + sizeof(bigCert) - 1, CERT_STORE_ADD_NEW,
1293 ok(!ret && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
1294 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
1296 /* Kosher size in property header, but no context type */
1297 hdr->cb = sizeof(bigCert) - 1;
1298 ret = CertAddSerializedElementToStore(store, buf, sizeof(buf), 0, 0, 0,
1300 ok(!ret && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
1301 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
1303 ret = CertAddSerializedElementToStore(store, buf,
1304 sizeof(struct CertPropIDHeader) + sizeof(bigCert) - 1, 0, 0, 0, NULL,
1306 ok(!ret && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
1307 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
1309 ret = CertAddSerializedElementToStore(store, buf,
1310 sizeof(struct CertPropIDHeader) + sizeof(bigCert) - 1, CERT_STORE_ADD_NEW,
1312 ok(!ret && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
1313 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
1315 /* With a bad context type */
1316 ret = CertAddSerializedElementToStore(store, buf, sizeof(buf), 0, 0,
1317 CERT_STORE_CRL_CONTEXT_FLAG, NULL, NULL);
1318 ok(!ret && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
1319 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
1321 ret = CertAddSerializedElementToStore(store, buf,
1322 sizeof(struct CertPropIDHeader) + sizeof(bigCert) - 1, 0, 0,
1323 CERT_STORE_CRL_CONTEXT_FLAG, NULL, NULL);
1324 ok(!ret && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
1325 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
1327 ret = CertAddSerializedElementToStore(store, buf,
1328 sizeof(struct CertPropIDHeader) + sizeof(bigCert) - 1, CERT_STORE_ADD_NEW,
1329 0, CERT_STORE_CRL_CONTEXT_FLAG, NULL, NULL);
1330 ok(!ret && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
1331 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
1333 /* Bad unknown field, good type */
1335 ret = CertAddSerializedElementToStore(store, buf, sizeof(buf), 0, 0,
1336 CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL);
1337 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
1338 "Expected ERROR_FILE_NOT_FOUND got %08lx\n", GetLastError());
1339 ret = CertAddSerializedElementToStore(store, buf,
1340 sizeof(struct CertPropIDHeader) + sizeof(bigCert) - 1, 0, 0,
1341 CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL);
1342 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
1343 "Expected ERROR_FILE_NOT_FOUND got %08lx\n", GetLastError());
1344 ret = CertAddSerializedElementToStore(store, buf,
1345 sizeof(struct CertPropIDHeader) + sizeof(bigCert) - 1, CERT_STORE_ADD_NEW,
1346 0, CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL);
1347 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
1348 "Expected ERROR_FILE_NOT_FOUND got %08lx\n", GetLastError());
1349 /* Most everything okay, but bad add disposition */
1352 ret = CertAddSerializedElementToStore(store, buf, sizeof(buf), 0, 0,
1353 CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL);
1355 ret = CertAddSerializedElementToStore(store, buf,
1356 sizeof(struct CertPropIDHeader) + sizeof(bigCert) - 1, 0, 0,
1357 CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL);
1359 /* Everything okay, but buffer's too big */
1360 ret = CertAddSerializedElementToStore(store, buf, sizeof(buf),
1361 CERT_STORE_ADD_NEW, 0, CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL);
1362 ok(ret, "CertAddSerializedElementToStore failed: %08lx\n", GetLastError());
1363 /* Everything okay, check it's not re-added */
1364 ret = CertAddSerializedElementToStore(store, buf,
1365 sizeof(struct CertPropIDHeader) + sizeof(bigCert) - 1, CERT_STORE_ADD_NEW,
1366 0, CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL);
1367 ok(!ret && GetLastError() == CRYPT_E_EXISTS,
1368 "Expected CRYPT_E_EXISTS, got %08lx\n", GetLastError());
1370 context = CertEnumCertificatesInStore(store, NULL);
1371 ok(context != NULL, "Expected a cert\n");
1373 CertDeleteCertificateFromStore(context);
1375 /* Try adding with a bogus hash. Oddly enough, it succeeds, and the hash,
1376 * when queried, is the real hash rather than the bogus hash.
1378 hdr = (struct CertPropIDHeader *)(buf + sizeof(struct CertPropIDHeader) +
1379 sizeof(bigCert) - 1);
1380 hdr->propID = CERT_HASH_PROP_ID;
1382 hdr->cb = sizeof(hash);
1383 memset(hash, 0xc, sizeof(hash));
1384 memcpy((LPBYTE)hdr + sizeof(struct CertPropIDHeader), hash, sizeof(hash));
1385 ret = CertAddSerializedElementToStore(store, buf, sizeof(buf),
1386 CERT_STORE_ADD_NEW, 0, CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL,
1387 (const void **)&context);
1388 ok(ret, "CertAddSerializedElementToStore failed: %08lx\n", GetLastError());
1391 BYTE hashVal[20], realHash[20];
1392 DWORD size = sizeof(hashVal);
1394 ret = CryptHashCertificate(0, 0, 0, bigCert, sizeof(bigCert) - 1,
1396 ok(ret, "CryptHashCertificate failed: %08lx\n", GetLastError());
1397 ret = CertGetCertificateContextProperty(context, CERT_HASH_PROP_ID,
1399 ok(ret, "CertGetCertificateContextProperty failed: %08lx\n",
1401 ok(!memcmp(hashVal, realHash, size), "Unexpected hash\n");
1402 CertFreeCertificateContext(context);
1405 CertCloseStore(store, 0);
1412 /* various combinations of CertOpenStore */
1414 testCollectionStore();
1416 testSystemRegStore();
1419 testCertOpenSystemStore();
1421 testCertProperties();
1422 testAddSerialized();