2 * crypt32 cert functions tests
4 * Copyright 2005 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
29 #include "wine/test.h"
31 /* The following aren't defined in wincrypt.h, as they're "reserved" */
32 #define CERT_CERT_PROP_ID 32
33 #define CERT_CRL_PROP_ID 33
34 #define CERT_CTL_PROP_ID 34
36 struct CertPropIDHeader
43 static void testCryptHashCert(void)
45 static const BYTE emptyHash[] = { 0xda, 0x39, 0xa3, 0xee, 0x5e, 0x6b, 0x4b,
46 0x0d, 0x32, 0x55, 0xbf, 0xef, 0x95, 0x60, 0x18, 0x90, 0xaf, 0xd8, 0x07,
48 static const BYTE knownHash[] = { 0xae, 0x9d, 0xbf, 0x6d, 0xf5, 0x46, 0xee,
49 0x8b, 0xc5, 0x7a, 0x13, 0xba, 0xc2, 0xb1, 0x04, 0xf2, 0xbf, 0x52, 0xa8,
51 static const BYTE toHash[] = "abcdefghijklmnopqrstuvwxyz0123456789.,;!?:";
54 DWORD hashLen = sizeof(hash);
56 /* NULL buffer and nonzero length crashes
57 ret = CryptHashCertificate(0, 0, 0, NULL, size, hash, &hashLen);
58 empty hash length also crashes
59 ret = CryptHashCertificate(0, 0, 0, buf, size, hash, NULL);
62 ret = CryptHashCertificate(0, 0, 0, toHash, sizeof(toHash), NULL,
64 ok(ret, "CryptHashCertificate failed: %08lx\n", GetLastError());
65 ok(hashLen == sizeof(hash),
66 "Got unexpected size of hash %ld, expected %d\n", hashLen, sizeof(hash));
67 /* Test with empty buffer */
68 ret = CryptHashCertificate(0, 0, 0, NULL, 0, hash, &hashLen);
69 ok(ret, "CryptHashCertificate failed: %08lx\n", GetLastError());
70 ok(!memcmp(hash, emptyHash, sizeof(emptyHash)),
71 "Unexpected hash of nothing\n");
72 /* Test a known value */
73 ret = CryptHashCertificate(0, 0, 0, toHash, sizeof(toHash), hash,
75 ok(ret, "CryptHashCertificate failed: %08lx\n", GetLastError());
76 ok(!memcmp(hash, knownHash, sizeof(knownHash)), "Unexpected hash\n");
79 static const BYTE emptyCert[] = { 0x30, 0x00 };
80 static const BYTE bigCert[] = "\x30\x7a\x02\x01\x01\x30\x02\x06\x00"
81 "\x30\x15\x31\x13\x30\x11\x06\x03\x55\x04\x03\x13\x0a\x4a\x75\x61\x6e\x20\x4c"
82 "\x61\x6e\x67\x00\x30\x22\x18\x0f\x31\x36\x30\x31\x30\x31\x30\x31\x30\x30\x30"
83 "\x30\x30\x30\x5a\x18\x0f\x31\x36\x30\x31\x30\x31\x30\x31\x30\x30\x30\x30\x30"
84 "\x30\x5a\x30\x15\x31\x13\x30\x11\x06\x03\x55\x04\x03\x13\x0a\x4a\x75\x61\x6e"
85 "\x20\x4c\x61\x6e\x67\x00\x30\x07\x30\x02\x06\x00\x03\x01\x00\xa3\x16\x30\x14"
86 "\x30\x12\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x08\x30\x06\x01\x01\xff\x02\x01"
88 static const BYTE signedBigCert[] = {
89 0x30, 0x81, 0x93, 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06, 0x00, 0x30,
90 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a,
91 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22, 0x18, 0x0f,
92 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
93 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30,
94 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06,
95 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61,
96 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3,
97 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff,
98 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
99 0x00, 0x03, 0x11, 0x00, 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07,
100 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00 };
101 static const BYTE serializedCert[] = { 0x20, 0x00, 0x00, 0x00,
102 0x01, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x30, 0x7a, 0x02, 0x01, 0x01,
103 0x30, 0x02, 0x06, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55,
104 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67,
105 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31,
106 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31,
107 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15,
108 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75,
109 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06,
110 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55,
111 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02,
114 static void testMemStore(void)
116 HCERTSTORE store1, store2;
117 PCCERT_CONTEXT context;
121 store1 = CertOpenStore(0, 0, 0, 0, NULL);
122 ok(!store1 && GetLastError() == ERROR_FILE_NOT_FOUND,
123 "Expected ERROR_FILE_NOT_FOUND, got %ld\n", GetLastError());
125 store1 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
126 CERT_STORE_DELETE_FLAG, NULL);
127 ok(!store1 && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED,
128 "Expected ERROR_CALL_NOT_IMPLEMENTED, got %ld\n", GetLastError());
131 store1 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
132 CERT_STORE_CREATE_NEW_FLAG, NULL);
133 ok(store1 != NULL, "CertOpenStore failed: %ld\n", GetLastError());
134 /* open existing doesn't */
135 store2 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
136 CERT_STORE_OPEN_EXISTING_FLAG, NULL);
137 ok(store2 != NULL, "CertOpenStore failed: %ld\n", GetLastError());
138 ok(store1 != store2, "Expected different stores\n");
140 /* add a bogus (empty) cert */
142 ret = CertAddEncodedCertificateToStore(store1, X509_ASN_ENCODING, emptyCert,
143 sizeof(emptyCert), CERT_STORE_ADD_ALWAYS, &context);
144 /* Windows returns CRYPT_E_ASN1_EOD, but accept CRYPT_E_ASN1_CORRUPT as
145 * well (because matching errors is tough in this case)
147 ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD || GetLastError() ==
148 CRYPT_E_ASN1_CORRUPT),
149 "Expected CRYPT_E_ASN1_EOD or CRYPT_E_ASN1_CORRUPT, got %08lx\n",
151 /* add a "signed" cert--the signature isn't a real signature, so this adds
152 * without any check of the signature's validity
154 ret = CertAddEncodedCertificateToStore(store1, X509_ASN_ENCODING,
155 signedBigCert, sizeof(signedBigCert), CERT_STORE_ADD_ALWAYS, &context);
156 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n", GetLastError());
157 ok(context != NULL, "Expected a valid cert context\n");
160 ok(context->cbCertEncoded == sizeof(signedBigCert),
161 "Expected cert of %d bytes, got %ld\n", sizeof(signedBigCert),
162 context->cbCertEncoded);
163 ok(!memcmp(context->pbCertEncoded, signedBigCert,
164 sizeof(signedBigCert)), "Unexpected encoded cert in context\n");
165 /* remove it, the rest of the tests will work on an unsigned cert */
166 ret = CertDeleteCertificateFromStore(context);
167 ok(ret, "CertDeleteCertificateFromStore failed: %08lx\n",
169 CertFreeCertificateContext(context);
171 /* add a cert to store1 */
172 ret = CertAddEncodedCertificateToStore(store1, X509_ASN_ENCODING, bigCert,
173 sizeof(bigCert) - 1, CERT_STORE_ADD_ALWAYS, &context);
174 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n", GetLastError());
175 ok(context != NULL, "Expected a valid cert context\n");
181 ok(context->cbCertEncoded == sizeof(bigCert) - 1,
182 "Expected cert of %d bytes, got %ld\n", sizeof(bigCert) - 1,
183 context->cbCertEncoded);
184 ok(!memcmp(context->pbCertEncoded, bigCert, sizeof(bigCert) - 1),
185 "Unexpected encoded cert in context\n");
186 ok(context->hCertStore == store1, "Unexpected store\n");
188 /* check serializing this element */
190 ret = CertSerializeCertificateStoreElement(NULL, 0, NULL, NULL);
191 ret = CertSerializeCertificateStoreElement(context, 0, NULL, NULL);
192 ret = CertSerializeCertificateStoreElement(NULL, 0, NULL, &size);
194 /* apparently flags are ignored */
195 ret = CertSerializeCertificateStoreElement(context, 1, NULL, &size);
196 ok(ret, "CertSerializeCertificateStoreElement failed: %08lx\n",
198 buf = HeapAlloc(GetProcessHeap(), 0, size);
201 ret = CertSerializeCertificateStoreElement(context, 0, buf, &size);
202 ok(size == sizeof(serializedCert), "Expected size %d, got %ld\n",
203 sizeof(serializedCert), size);
204 ok(!memcmp(serializedCert, buf, size),
205 "Unexpected serialized cert\n");
206 HeapFree(GetProcessHeap(), 0, buf);
209 ret = CertFreeCertificateContext(context);
210 ok(ret, "CertFreeCertificateContext failed: %08lx\n", GetLastError());
212 /* verify the cert's in store1 */
213 context = CertEnumCertificatesInStore(store1, NULL);
214 ok(context != NULL, "Expected a valid context\n");
215 context = CertEnumCertificatesInStore(store1, context);
216 ok(!context && GetLastError() == CRYPT_E_NOT_FOUND,
217 "Expected CRYPT_E_NOT_FOUND, got %08lx\n", GetLastError());
218 /* verify store2 (the "open existing" mem store) is still empty */
219 context = CertEnumCertificatesInStore(store2, NULL);
220 ok(!context, "Expected an empty store\n");
221 /* delete the cert from store1, and check it's empty */
222 context = CertEnumCertificatesInStore(store1, NULL);
225 /* Deleting a bitwise copy crashes with an access to an uninitialized
226 * pointer, so a cert context has some special data out there in memory
229 memcpy(©, context, sizeof(copy));
230 ret = CertDeleteCertificateFromStore(©);
232 PCCERT_CONTEXT copy = CertDuplicateCertificateContext(context);
234 ok(copy != NULL, "CertDuplicateCertificateContext failed: %08lx\n",
236 ret = CertDeleteCertificateFromStore(context);
237 ok(ret, "CertDeleteCertificateFromStore failed: %08lx\n",
239 /* try deleting a copy */
240 ret = CertDeleteCertificateFromStore(copy);
241 ok(ret, "CertDeleteCertificateFromStore failed: %08lx\n",
243 /* check that the store is empty */
244 context = CertEnumCertificatesInStore(store1, NULL);
245 ok(!context, "Expected an empty store\n");
248 /* close an empty store */
249 ret = CertCloseStore(NULL, 0);
250 ok(ret, "CertCloseStore failed: %ld\n", GetLastError());
251 ret = CertCloseStore(store1, 0);
252 ok(ret, "CertCloseStore failed: %ld\n", GetLastError());
253 ret = CertCloseStore(store2, 0);
254 ok(ret, "CertCloseStore failed: %ld\n", GetLastError());
256 /* This seems nonsensical, but you can open a read-only mem store, only
259 store1 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
260 CERT_STORE_READONLY_FLAG, NULL);
261 ok(store1 != NULL, "CertOpenStore failed: %ld\n", GetLastError());
262 /* yep, this succeeds */
263 ret = CertAddEncodedCertificateToStore(store1, X509_ASN_ENCODING, bigCert,
264 sizeof(bigCert) - 1, CERT_STORE_ADD_ALWAYS, &context);
265 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n", GetLastError());
266 ok(context != NULL, "Expected a valid cert context\n");
269 ok(context->cbCertEncoded == sizeof(bigCert) - 1,
270 "Expected cert of %d bytes, got %ld\n", sizeof(bigCert) - 1,
271 context->cbCertEncoded);
272 ok(!memcmp(context->pbCertEncoded, bigCert, sizeof(bigCert) - 1),
273 "Unexpected encoded cert in context\n");
274 ok(context->hCertStore == store1, "Unexpected store\n");
275 ret = CertDeleteCertificateFromStore(context);
276 ok(ret, "CertDeleteCertificateFromStore failed: %08lx\n",
279 CertCloseStore(store1, 0);
282 static const BYTE bigCert2[] = "\x30\x7a\x02\x01\x01\x30\x02\x06\x00"
283 "\x30\x15\x31\x13\x30\x11\x06\x03\x55\x04\x03\x13\x0a\x41\x6c\x65\x78\x20\x4c"
284 "\x61\x6e\x67\x00\x30\x22\x18\x0f\x31\x36\x30\x31\x30\x31\x30\x31\x30\x30\x30"
285 "\x30\x30\x30\x5a\x18\x0f\x31\x36\x30\x31\x30\x31\x30\x31\x30\x30\x30\x30\x30"
286 "\x30\x5a\x30\x15\x31\x13\x30\x11\x06\x03\x55\x04\x03\x13\x0a\x41\x6c\x65\x78"
287 "\x20\x4c\x61\x6e\x67\x00\x30\x07\x30\x02\x06\x00\x03\x01\x00\xa3\x16\x30\x14"
288 "\x30\x12\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x08\x30\x06\x01\x01\xff\x02\x01"
291 static void testCollectionStore(void)
293 HCERTSTORE store1, store2, collection, collection2;
294 PCCERT_CONTEXT context;
297 collection = CertOpenStore(CERT_STORE_PROV_COLLECTION, 0, 0,
298 CERT_STORE_CREATE_NEW_FLAG, NULL);
300 /* Try adding a cert to any empty collection */
301 ret = CertAddEncodedCertificateToStore(collection, X509_ASN_ENCODING,
302 bigCert, sizeof(bigCert) - 1, CERT_STORE_ADD_ALWAYS, NULL);
303 ok(!ret && GetLastError() == HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED),
304 "Expected HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED), got %08lx\n",
307 /* Create and add a cert to a memory store */
308 store1 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
309 CERT_STORE_CREATE_NEW_FLAG, NULL);
310 ret = CertAddEncodedCertificateToStore(store1, X509_ASN_ENCODING,
311 bigCert, sizeof(bigCert) - 1, CERT_STORE_ADD_ALWAYS, NULL);
312 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n", GetLastError());
313 /* Add the memory store to the collection, without allowing adding */
314 ret = CertAddStoreToCollection(collection, store1, 0, 0);
315 ok(ret, "CertAddStoreToCollection failed: %08lx\n", GetLastError());
316 /* Verify the cert is in the collection */
317 context = CertEnumCertificatesInStore(collection, NULL);
318 ok(context != NULL, "Expected a valid context\n");
321 ok(context->hCertStore == collection, "Unexpected store\n");
322 CertFreeCertificateContext(context);
324 /* Check that adding to the collection isn't allowed */
325 ret = CertAddEncodedCertificateToStore(collection, X509_ASN_ENCODING,
326 bigCert2, sizeof(bigCert2) - 1, CERT_STORE_ADD_ALWAYS, NULL);
327 ok(!ret && GetLastError() == HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED),
328 "Expected HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED), got %08lx\n",
331 /* Create a new memory store */
332 store2 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
333 CERT_STORE_CREATE_NEW_FLAG, NULL);
334 /* Try adding a store to a non-collection store */
335 ret = CertAddStoreToCollection(store1, store2,
336 CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
337 ok(!ret && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
338 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
340 /* Try adding some bogus stores */
341 /* This crashes in Windows
342 ret = CertAddStoreToCollection(0, store2,
343 CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
345 /* This "succeeds"... */
346 ret = CertAddStoreToCollection(collection, 0,
347 CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
348 ok(ret, "CertAddStoreToCollection failed: %08lx\n", GetLastError());
349 /* while this crashes.
350 ret = CertAddStoreToCollection(collection, 1,
351 CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
354 /* Add it to the collection, this time allowing adding */
355 ret = CertAddStoreToCollection(collection, store2,
356 CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
357 ok(ret, "CertAddStoreToCollection failed: %08lx\n", GetLastError());
358 /* Check that adding to the collection is allowed */
359 ret = CertAddEncodedCertificateToStore(collection, X509_ASN_ENCODING,
360 bigCert2, sizeof(bigCert2) - 1, CERT_STORE_ADD_ALWAYS, NULL);
361 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n", GetLastError());
362 /* Now check that it was actually added to store2 */
363 context = CertEnumCertificatesInStore(store2, NULL);
364 ok(context != NULL, "Expected a valid context\n");
367 ok(context->hCertStore == store2, "Unexpected store\n");
368 CertFreeCertificateContext(context);
370 /* Check that the collection has both bigCert and bigCert2. bigCert comes
371 * first because store1 was added first.
373 context = CertEnumCertificatesInStore(collection, NULL);
374 ok(context != NULL, "Expected a valid context\n");
377 ok(context->hCertStore == collection, "Unexpected store\n");
378 ok(context->cbCertEncoded == sizeof(bigCert) - 1,
379 "Expected size %d, got %ld\n", sizeof(bigCert) - 1,
380 context->cbCertEncoded);
381 ok(!memcmp(context->pbCertEncoded, bigCert, context->cbCertEncoded),
382 "Unexpected cert\n");
383 context = CertEnumCertificatesInStore(collection, context);
384 ok(context != NULL, "Expected a valid context\n");
387 ok(context->hCertStore == collection, "Unexpected store\n");
388 ok(context->cbCertEncoded == sizeof(bigCert2) - 1,
389 "Expected size %d, got %ld\n", sizeof(bigCert2) - 1,
390 context->cbCertEncoded);
391 ok(!memcmp(context->pbCertEncoded, bigCert2,
392 context->cbCertEncoded), "Unexpected cert\n");
393 context = CertEnumCertificatesInStore(collection, context);
394 ok(!context, "Unexpected cert\n");
397 /* close store2, and check that the collection is unmodified */
398 CertCloseStore(store2, 0);
399 context = CertEnumCertificatesInStore(collection, NULL);
400 ok(context != NULL, "Expected a valid context\n");
403 ok(context->hCertStore == collection, "Unexpected store\n");
404 ok(context->cbCertEncoded == sizeof(bigCert) - 1,
405 "Expected size %d, got %ld\n", sizeof(bigCert) - 1,
406 context->cbCertEncoded);
407 ok(!memcmp(context->pbCertEncoded, bigCert, context->cbCertEncoded),
408 "Unexpected cert\n");
409 context = CertEnumCertificatesInStore(collection, context);
410 ok(context != NULL, "Expected a valid context\n");
413 ok(context->hCertStore == collection, "Unexpected store\n");
414 ok(context->cbCertEncoded == sizeof(bigCert2) - 1,
415 "Expected size %d, got %ld\n", sizeof(bigCert2) - 1,
416 context->cbCertEncoded);
417 ok(!memcmp(context->pbCertEncoded, bigCert2,
418 context->cbCertEncoded), "Unexpected cert\n");
419 context = CertEnumCertificatesInStore(collection, context);
420 ok(!context, "Unexpected cert\n");
424 /* Adding a collection to a collection is legal */
425 collection2 = CertOpenStore(CERT_STORE_PROV_COLLECTION, 0, 0,
426 CERT_STORE_CREATE_NEW_FLAG, NULL);
427 ret = CertAddStoreToCollection(collection2, collection,
428 CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
429 ok(ret, "CertAddStoreToCollection failed: %08lx\n", GetLastError());
430 /* check the contents of collection2 */
431 context = CertEnumCertificatesInStore(collection2, NULL);
432 ok(context != NULL, "Expected a valid context\n");
435 ok(context->hCertStore == collection2, "Unexpected store\n");
436 ok(context->cbCertEncoded == sizeof(bigCert) - 1,
437 "Expected size %d, got %ld\n", sizeof(bigCert) - 1,
438 context->cbCertEncoded);
439 ok(!memcmp(context->pbCertEncoded, bigCert, context->cbCertEncoded),
440 "Unexpected cert\n");
441 context = CertEnumCertificatesInStore(collection2, context);
442 ok(context != NULL, "Expected a valid context\n");
445 ok(context->hCertStore == collection2, "Unexpected store\n");
446 ok(context->cbCertEncoded == sizeof(bigCert2) - 1,
447 "Expected size %d, got %ld\n", sizeof(bigCert2) - 1,
448 context->cbCertEncoded);
449 ok(!memcmp(context->pbCertEncoded, bigCert2,
450 context->cbCertEncoded), "Unexpected cert\n");
451 context = CertEnumCertificatesInStore(collection2, context);
452 ok(!context, "Unexpected cert\n");
456 /* I'd like to test closing the collection in the middle of enumeration,
457 * but my tests have been inconsistent. The first time calling
458 * CertEnumCertificatesInStore on a closed collection succeeded, while the
459 * second crashed. So anything appears to be fair game.
460 * I'd also like to test removing a store from a collection in the middle
461 * of an enumeration, but my tests in Windows have been inconclusive.
462 * In one scenario it worked. In another scenario, about a third of the
463 * time this leads to "random" crashes elsewhere in the code. This
464 * probably means this is not allowed.
467 CertCloseStore(store1, 0);
468 CertCloseStore(collection, 0);
469 CertCloseStore(collection2, 0);
471 /* Add the same cert to two memory stores, then put them in a collection */
472 store1 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
473 CERT_STORE_CREATE_NEW_FLAG, NULL);
474 ok(store1 != 0, "CertOpenStore failed: %08lx\n", GetLastError());
475 store2 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
476 CERT_STORE_CREATE_NEW_FLAG, NULL);
477 ok(store2 != 0, "CertOpenStore failed: %08lx\n", GetLastError());
479 ret = CertAddEncodedCertificateToStore(store1, X509_ASN_ENCODING,
480 bigCert, sizeof(bigCert) - 1, CERT_STORE_ADD_ALWAYS, NULL);
481 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n", GetLastError());
482 ret = CertAddEncodedCertificateToStore(store2, X509_ASN_ENCODING,
483 bigCert, sizeof(bigCert) - 1, CERT_STORE_ADD_ALWAYS, NULL);
484 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n", GetLastError());
485 collection = CertOpenStore(CERT_STORE_PROV_COLLECTION, 0, 0,
486 CERT_STORE_CREATE_NEW_FLAG, NULL);
487 ok(collection != 0, "CertOpenStore failed: %08lx\n", GetLastError());
489 ret = CertAddStoreToCollection(collection, store1,
490 CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
491 ok(ret, "CertAddStoreToCollection failed: %08lx\n", GetLastError());
492 ret = CertAddStoreToCollection(collection, store2,
493 CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
494 ok(ret, "CertAddStoreToCollection failed: %08lx\n", GetLastError());
496 /* Check that the collection has two copies of the same cert */
497 context = CertEnumCertificatesInStore(collection, NULL);
498 ok(context != NULL, "Expected a valid context\n");
501 ok(context->hCertStore == collection, "Unexpected store\n");
502 ok(context->cbCertEncoded == sizeof(bigCert) - 1,
503 "Expected size %d, got %ld\n", sizeof(bigCert) - 1,
504 context->cbCertEncoded);
505 ok(!memcmp(context->pbCertEncoded, bigCert, context->cbCertEncoded),
506 "Unexpected cert\n");
507 context = CertEnumCertificatesInStore(collection, context);
508 ok(context != NULL, "Expected a valid context\n");
511 ok(context->hCertStore == collection, "Unexpected store\n");
512 ok(context->cbCertEncoded == sizeof(bigCert) - 1,
513 "Expected size %d, got %ld\n", sizeof(bigCert) - 1,
514 context->cbCertEncoded);
515 ok(!memcmp(context->pbCertEncoded, bigCert, context->cbCertEncoded),
516 "Unexpected cert\n");
517 context = CertEnumCertificatesInStore(collection, context);
518 ok(context == NULL, "Unexpected cert\n");
522 /* The following would check whether I can delete an identical cert, rather
523 * than one enumerated from the store. It crashes, so that means I must
524 * only call CertDeleteCertificateFromStore with contexts enumerated from
526 context = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert,
527 sizeof(bigCert) - 1);
528 ok(context != NULL, "CertCreateCertificateContext failed: %08lx\n",
532 ret = CertDeleteCertificateFromStore(collection, context);
533 printf("ret is %d, GetLastError is %08lx\n", ret, GetLastError());
534 CertFreeCertificateContext(context);
538 /* Now check deleting from the collection. */
539 context = CertEnumCertificatesInStore(collection, NULL);
540 ok(context != NULL, "Expected a valid context\n");
543 CertDeleteCertificateFromStore(context);
544 /* store1 should now be empty */
545 context = CertEnumCertificatesInStore(store1, NULL);
546 ok(!context, "Unexpected cert\n");
547 /* and there should be one certificate in the collection */
548 context = CertEnumCertificatesInStore(collection, NULL);
549 ok(context != NULL, "Expected a valid cert\n");
552 ok(context->hCertStore == collection, "Unexpected store\n");
553 ok(context->cbCertEncoded == sizeof(bigCert) - 1,
554 "Expected size %d, got %ld\n", sizeof(bigCert) - 1,
555 context->cbCertEncoded);
556 ok(!memcmp(context->pbCertEncoded, bigCert, context->cbCertEncoded),
557 "Unexpected cert\n");
559 context = CertEnumCertificatesInStore(collection, context);
560 ok(context == NULL, "Unexpected cert\n");
563 /* Finally, test removing stores from the collection. No return value, so
564 * it's a bit funny to test.
567 CertRemoveStoreFromCollection(NULL, NULL);
569 /* This "succeeds," no crash, no last error set */
570 SetLastError(0xdeadbeef);
571 CertRemoveStoreFromCollection(store2, collection);
572 ok(GetLastError() == 0xdeadbeef,
573 "Didn't expect an error to be set: %08lx\n", GetLastError());
575 /* After removing store2, the collection should be empty */
576 SetLastError(0xdeadbeef);
577 CertRemoveStoreFromCollection(collection, store2);
578 ok(GetLastError() == 0xdeadbeef,
579 "Didn't expect an error to be set: %08lx\n", GetLastError());
580 context = CertEnumCertificatesInStore(collection, NULL);
581 ok(!context, "Unexpected cert\n");
583 CertCloseStore(collection, 0);
584 CertCloseStore(store2, 0);
585 CertCloseStore(store1, 0);
588 /* Looks for the property with ID propID in the buffer buf. Returns a pointer
589 * to its header if found, NULL if not.
591 static const struct CertPropIDHeader *findPropID(const BYTE *buf, DWORD size,
594 const struct CertPropIDHeader *ret = NULL;
597 while (size && !ret && !failed)
599 if (size < sizeof(struct CertPropIDHeader))
603 const struct CertPropIDHeader *hdr =
604 (const struct CertPropIDHeader *)buf;
606 size -= sizeof(struct CertPropIDHeader);
607 buf += sizeof(struct CertPropIDHeader);
610 else if (hdr->propID == propID)
622 typedef DWORD (WINAPI *SHDeleteKeyAFunc)(HKEY, LPCSTR);
624 static void testRegStore(void)
626 static const char tempKey[] = "Software\\Wine\\CryptTemp";
632 store = CertOpenStore(CERT_STORE_PROV_REG, 0, 0, 0, NULL);
633 ok(!store && GetLastError() == ERROR_INVALID_HANDLE,
634 "Expected ERROR_INVALID_HANDLE, got %ld\n", GetLastError());
635 store = CertOpenStore(CERT_STORE_PROV_REG, 0, 0, 0, key);
636 ok(!store && GetLastError() == ERROR_INVALID_HANDLE,
637 "Expected ERROR_INVALID_HANDLE, got %ld\n", GetLastError());
639 /* Opening up any old key works.. */
640 key = HKEY_CURRENT_USER;
641 store = CertOpenStore(CERT_STORE_PROV_REG, 0, 0, 0, key);
642 /* Not sure if this is a bug in DuplicateHandle, marking todo_wine for now
644 todo_wine ok(store != 0, "CertOpenStore failed: %08lx\n", GetLastError());
645 CertCloseStore(store, 0);
647 rc = RegCreateKeyExA(HKEY_CURRENT_USER, tempKey, 0, NULL, 0, KEY_ALL_ACCESS,
649 ok(!rc, "RegCreateKeyExA failed: %ld\n", rc);
655 static const char certificates[] = "Certificates\\";
656 char subKeyName[sizeof(certificates) + 20 * 2 + 1], *ptr;
658 PCCERT_CONTEXT context;
660 store = CertOpenStore(CERT_STORE_PROV_REG, 0, 0, 0, key);
661 ok(store != 0, "CertOpenStore failed: %08lx\n", GetLastError());
662 /* Add a certificate. It isn't persisted right away, since it's only
663 * added to the cache..
665 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
666 bigCert2, sizeof(bigCert2) - 1, CERT_STORE_ADD_ALWAYS, NULL);
667 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n",
669 /* so flush the cache to force a commit.. */
670 ret = CertControlStore(store, 0, CERT_STORE_CTRL_COMMIT, NULL);
671 ok(ret, "CertControlStore failed: %08lx\n", GetLastError());
672 /* and check that the expected subkey was written. */
674 ret = CryptHashCertificate(0, 0, 0, bigCert2, sizeof(bigCert2) - 1,
676 ok(ret, "CryptHashCertificate failed: %ld\n", GetLastError());
677 strcpy(subKeyName, certificates);
678 for (i = 0, ptr = subKeyName + sizeof(certificates) - 1; i < size;
680 sprintf(ptr, "%02X", hash[i]);
681 rc = RegCreateKeyExA(key, subKeyName, 0, NULL, 0, KEY_ALL_ACCESS, NULL,
683 ok(!rc, "RegCreateKeyExA failed: %ld\n", rc);
689 RegQueryValueExA(subKey, "Blob", NULL, NULL, NULL, &size);
690 buf = HeapAlloc(GetProcessHeap(), 0, size);
693 rc = RegQueryValueExA(subKey, "Blob", NULL, NULL, buf, &size);
694 ok(!rc, "RegQueryValueExA failed: %ld\n", rc);
697 const struct CertPropIDHeader *hdr;
699 /* Both the hash and the cert should be present */
700 hdr = findPropID(buf, size, CERT_CERT_PROP_ID);
701 ok(hdr != NULL, "Expected to find a cert property\n");
704 ok(hdr->cb == sizeof(bigCert2) - 1,
705 "Unexpected size %ld of cert property, expected %d\n",
706 hdr->cb, sizeof(bigCert2) - 1);
707 ok(!memcmp((BYTE *)hdr + sizeof(*hdr), bigCert2,
708 hdr->cb), "Unexpected cert in cert property\n");
710 hdr = findPropID(buf, size, CERT_HASH_PROP_ID);
711 ok(hdr != NULL, "Expected to find a hash property\n");
714 ok(hdr->cb == sizeof(hash),
715 "Unexpected size %ld of hash property, expected %d\n",
716 hdr->cb, sizeof(hash));
717 ok(!memcmp((BYTE *)hdr + sizeof(*hdr), hash,
718 hdr->cb), "Unexpected hash in cert property\n");
721 HeapFree(GetProcessHeap(), 0, buf);
726 /* Remove the existing context */
727 context = CertEnumCertificatesInStore(store, NULL);
728 ok(context != NULL, "Expected a cert context\n");
731 CertDeleteCertificateFromStore(context);
732 CertFreeCertificateContext(context);
734 ret = CertControlStore(store, 0, CERT_STORE_CTRL_COMMIT, NULL);
735 ok(ret, "CertControlStore failed: %08lx\n", GetLastError());
737 /* Add a serialized cert with a bogus hash directly to the registry */
738 memset(hash, 0, sizeof(hash));
739 strcpy(subKeyName, certificates);
740 for (i = 0, ptr = subKeyName + sizeof(certificates) - 1;
741 i < sizeof(hash); i++, ptr += 2)
742 sprintf(ptr, "%02X", hash[i]);
743 rc = RegCreateKeyExA(key, subKeyName, 0, NULL, 0, KEY_ALL_ACCESS, NULL,
745 ok(!rc, "RegCreateKeyExA failed: %ld\n", rc);
748 BYTE buf[sizeof(struct CertPropIDHeader) * 2 + sizeof(hash) +
749 sizeof(bigCert) - 1], *ptr;
751 struct CertPropIDHeader *hdr;
753 hdr = (struct CertPropIDHeader *)buf;
754 hdr->propID = CERT_HASH_PROP_ID;
756 hdr->cb = sizeof(hash);
757 ptr = buf + sizeof(*hdr);
758 memcpy(ptr, hash, sizeof(hash));
760 hdr = (struct CertPropIDHeader *)ptr;
761 hdr->propID = CERT_CERT_PROP_ID;
763 hdr->cb = sizeof(bigCert) - 1;
765 memcpy(ptr, bigCert, sizeof(bigCert) - 1);
767 rc = RegSetValueExA(subKey, "Blob", 0, REG_BINARY, buf,
769 ok(!rc, "RegSetValueExA failed: %ld\n", rc);
771 ret = CertControlStore(store, 0, CERT_STORE_CTRL_RESYNC, NULL);
772 ok(ret, "CertControlStore failed: %08lx\n", GetLastError());
774 /* Make sure the bogus hash cert gets loaded. */
778 context = CertEnumCertificatesInStore(store, context);
781 } while (context != NULL);
782 ok(certCount == 1, "Expected 1 certificates, got %ld\n", certCount);
787 /* Add another serialized cert directly to the registry, this time
788 * under the correct key name (named with the correct hash value).
791 ret = CryptHashCertificate(0, 0, 0, bigCert2,
792 sizeof(bigCert2) - 1, hash, &size);
793 ok(ret, "CryptHashCertificate failed: %ld\n", GetLastError());
794 strcpy(subKeyName, certificates);
795 for (i = 0, ptr = subKeyName + sizeof(certificates) - 1;
796 i < sizeof(hash); i++, ptr += 2)
797 sprintf(ptr, "%02X", hash[i]);
798 rc = RegCreateKeyExA(key, subKeyName, 0, NULL, 0, KEY_ALL_ACCESS, NULL,
800 ok(!rc, "RegCreateKeyExA failed: %ld\n", rc);
803 BYTE buf[sizeof(struct CertPropIDHeader) * 2 + sizeof(hash) +
804 sizeof(bigCert2) - 1], *ptr;
806 PCCERT_CONTEXT context;
807 struct CertPropIDHeader *hdr;
809 /* First try with a bogus hash... */
810 hdr = (struct CertPropIDHeader *)buf;
811 hdr->propID = CERT_HASH_PROP_ID;
813 hdr->cb = sizeof(hash);
814 ptr = buf + sizeof(*hdr);
815 memset(ptr, 0, sizeof(hash));
817 hdr = (struct CertPropIDHeader *)ptr;
818 hdr->propID = CERT_CERT_PROP_ID;
820 hdr->cb = sizeof(bigCert2) - 1;
822 memcpy(ptr, bigCert2, sizeof(bigCert2) - 1);
824 rc = RegSetValueExA(subKey, "Blob", 0, REG_BINARY, buf,
826 ok(!rc, "RegSetValueExA failed: %ld\n", rc);
828 ret = CertControlStore(store, 0, CERT_STORE_CTRL_RESYNC, NULL);
829 ok(ret, "CertControlStore failed: %08lx\n", GetLastError());
831 /* and make sure just one cert still gets loaded. */
835 context = CertEnumCertificatesInStore(store, context);
838 } while (context != NULL);
839 ok(certCount == 1, "Expected 1 certificates, got %ld\n", certCount);
841 /* Try again with the correct hash... */
842 ptr = buf + sizeof(*hdr);
843 memcpy(ptr, hash, sizeof(hash));
845 rc = RegSetValueExA(subKey, "Blob", 0, REG_BINARY, buf,
847 ok(!rc, "RegSetValueExA failed: %ld\n", rc);
849 ret = CertControlStore(store, 0, CERT_STORE_CTRL_RESYNC, NULL);
850 ok(ret, "CertControlStore failed: %08lx\n", GetLastError());
852 /* and make sure two certs get loaded. */
856 context = CertEnumCertificatesInStore(store, context);
859 } while (context != NULL);
860 ok(certCount == 2, "Expected 2 certificates, got %ld\n", certCount);
864 CertCloseStore(store, 0);
865 /* Is delete allowed on a reg store? */
866 store = CertOpenStore(CERT_STORE_PROV_REG, 0, 0,
867 CERT_STORE_DELETE_FLAG, key);
868 ok(store == NULL, "Expected NULL return from CERT_STORE_DELETE_FLAG\n");
869 ok(GetLastError() == 0, "CertOpenStore failed: %08lx\n",
874 /* The CertOpenStore with CERT_STORE_DELETE_FLAG above will delete the
875 * contents of the key, but not the key itself.
877 rc = RegCreateKeyExA(HKEY_CURRENT_USER, tempKey, 0, NULL, 0, KEY_ALL_ACCESS,
879 ok(!rc, "RegCreateKeyExA failed: %ld\n", rc);
880 ok(disp == REG_OPENED_EXISTING_KEY,
881 "Expected REG_OPENED_EXISTING_KEY, got %ld\n", disp);
885 rc = RegDeleteKeyA(HKEY_CURRENT_USER, tempKey);
886 ok(!rc, "RegDeleteKeyA failed: %ld\n", rc);
889 HMODULE shlwapi = LoadLibraryA("shlwapi");
891 /* Use shlwapi's SHDeleteKeyA to _really_ blow away the key,
892 * otherwise subsequent tests will fail.
896 SHDeleteKeyAFunc pSHDeleteKeyA =
897 (SHDeleteKeyAFunc)GetProcAddress(shlwapi, "SHDeleteKeyA");
900 pSHDeleteKeyA(HKEY_CURRENT_USER, tempKey);
901 FreeLibrary(shlwapi);
907 static const char MyA[] = { 'M','y',0,0 };
908 static const WCHAR MyW[] = { 'M','y',0 };
909 static const WCHAR BogusW[] = { 'B','o','g','u','s',0 };
910 static const WCHAR BogusPathW[] = { 'S','o','f','t','w','a','r','e','\\',
911 'M','i','c','r','o','s','o','f','t','\\','S','y','s','t','e','m','C','e','r',
912 't','i','f','i','c','a','t','e','s','\\','B','o','g','u','s',0 };
914 static void testSystemRegStore(void)
916 HCERTSTORE store, memStore;
918 /* Check with a UNICODE name */
919 store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0,
920 CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_OPEN_EXISTING_FLAG, MyW);
921 /* Not all OSes support CERT_STORE_PROV_SYSTEM_REGISTRY, so don't continue
922 * testing if they don't.
927 /* Check that it isn't a collection store */
928 memStore = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
929 CERT_STORE_CREATE_NEW_FLAG, NULL);
932 BOOL ret = CertAddStoreToCollection(store, memStore, 0, 0);
934 ok(!ret && GetLastError() ==
935 HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
936 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
938 CertCloseStore(memStore, 0);
940 CertCloseStore(store, 0);
942 /* Check opening a bogus store */
943 store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0,
944 CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_OPEN_EXISTING_FLAG, BogusW);
945 ok(!store && GetLastError() == ERROR_FILE_NOT_FOUND,
946 "Expected ERROR_FILE_NOT_FOUND, got %08lx\n", GetLastError());
947 store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0,
948 CERT_SYSTEM_STORE_CURRENT_USER, BogusW);
949 ok(store != 0, "CertOpenStore failed: %08lx\n", GetLastError());
951 CertCloseStore(store, 0);
952 /* Now check whether deleting is allowed */
953 store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0,
954 CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_DELETE_FLAG, BogusW);
955 RegDeleteKeyW(HKEY_CURRENT_USER, BogusPathW);
957 store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0, 0, NULL);
958 ok(!store && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
959 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
961 store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0,
962 CERT_SYSTEM_STORE_LOCAL_MACHINE | CERT_SYSTEM_STORE_CURRENT_USER, MyA);
963 ok(!store && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
964 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
966 store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0,
967 CERT_SYSTEM_STORE_LOCAL_MACHINE | CERT_SYSTEM_STORE_CURRENT_USER, MyW);
968 ok(!store && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
969 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
971 /* The name is expected to be UNICODE, check with an ASCII name */
972 store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0,
973 CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_OPEN_EXISTING_FLAG, MyA);
974 ok(!store && GetLastError() == ERROR_FILE_NOT_FOUND,
975 "Expected ERROR_FILE_NOT_FOUND, got %08lx\n", GetLastError());
978 static void testCertProperties(void)
980 PCCERT_CONTEXT context = CertCreateCertificateContext(X509_ASN_ENCODING,
981 bigCert, sizeof(bigCert) - 1);
983 ok(context != NULL, "CertCreateCertificateContext failed: %08lx\n",
987 DWORD propID, numProps, access, size;
989 BYTE hash[20] = { 0 }, hashProperty[20];
990 CRYPT_DATA_BLOB blob;
993 propID = CertEnumCertificateContextProperties(NULL, 0);
999 propID = CertEnumCertificateContextProperties(context, propID);
1002 } while (propID != 0);
1003 ok(numProps == 0, "Expected 0 properties, got %ld\n", numProps);
1005 /* Tests with a NULL cert context. Prop ID 0 fails.. */
1006 ret = CertSetCertificateContextProperty(NULL, 0, 0, NULL);
1007 ok(!ret && GetLastError() ==
1008 HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
1009 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
1011 /* while this just crashes.
1012 ret = CertSetCertificateContextProperty(NULL,
1013 CERT_KEY_PROV_HANDLE_PROP_ID, 0, NULL);
1016 ret = CertSetCertificateContextProperty(context, 0, 0, NULL);
1017 ok(!ret && GetLastError() ==
1018 HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
1019 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
1021 /* Can't set the cert property directly, this crashes.
1022 ret = CertSetCertificateContextProperty(context,
1023 CERT_CERT_PROP_ID, 0, bigCert2);
1027 ret = CertGetCertificateContextProperty(context,
1028 CERT_ACCESS_STATE_PROP_ID, 0, NULL);
1030 size = sizeof(access);
1031 ret = CertGetCertificateContextProperty(context,
1032 CERT_ACCESS_STATE_PROP_ID, &access, &size);
1033 ok(ret, "CertGetCertificateContextProperty failed: %08lx\n",
1035 ok(!(access & CERT_ACCESS_STATE_WRITE_PERSIST_FLAG),
1036 "Didn't expect a persisted cert\n");
1037 /* Trying to set this "read only" property crashes.
1038 access |= CERT_ACCESS_STATE_WRITE_PERSIST_FLAG;
1039 ret = CertSetCertificateContextProperty(context,
1040 CERT_ACCESS_STATE_PROP_ID, 0, &access);
1043 /* Can I set the hash to an invalid hash? */
1045 blob.cbData = sizeof(hash);
1046 ret = CertSetCertificateContextProperty(context, CERT_HASH_PROP_ID, 0,
1048 ok(ret, "CertSetCertificateContextProperty failed: %08lx\n",
1050 size = sizeof(hashProperty);
1051 ret = CertGetCertificateContextProperty(context, CERT_HASH_PROP_ID,
1052 hashProperty, &size);
1053 ok(!memcmp(hashProperty, hash, sizeof(hash)), "Unexpected hash\n");
1054 /* Delete the (bogus) hash, and get the real one */
1055 ret = CertSetCertificateContextProperty(context, CERT_HASH_PROP_ID, 0,
1057 ok(ret, "CertSetCertificateContextProperty failed: %08lx\n",
1059 size = sizeof(hash);
1060 ret = CryptHashCertificate(0, 0, 0, bigCert, sizeof(bigCert) - 1,
1062 ok(ret, "CryptHashCertificate failed: %08lx\n", GetLastError());
1063 ret = CertGetCertificateContextProperty(context, CERT_HASH_PROP_ID,
1064 hashProperty, &size);
1065 ok(ret, "CertGetCertificateContextProperty failed: %08lx\n",
1067 ok(!memcmp(hash, hashProperty, sizeof(hash)), "Unexpected hash\n");
1069 /* Now that the hash property is set, we should get one property when
1075 propID = CertEnumCertificateContextProperties(context, propID);
1078 } while (propID != 0);
1079 ok(numProps == 1, "Expected 1 properties, got %ld\n", numProps);
1081 CertFreeCertificateContext(context);
1085 static void testAddSerialized(void)
1089 BYTE buf[sizeof(struct CertPropIDHeader) * 2 + 20 + sizeof(bigCert) - 1] =
1092 struct CertPropIDHeader *hdr;
1093 PCCERT_CONTEXT context;
1095 ret = CertAddSerializedElementToStore(0, NULL, 0, 0, 0, 0, NULL, NULL);
1096 ok(!ret && GetLastError() == ERROR_END_OF_MEDIA,
1097 "Expected ERROR_END_OF_MEDIA, got %08lx\n", GetLastError());
1099 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
1100 CERT_STORE_CREATE_NEW_FLAG, NULL);
1101 ok(store != 0, "CertOpenStore failed: %08lx\n", GetLastError());
1103 ret = CertAddSerializedElementToStore(store, NULL, 0, 0, 0, 0, NULL, NULL);
1104 ok(!ret && GetLastError() == ERROR_END_OF_MEDIA,
1105 "Expected ERROR_END_OF_MEDIA, got %08lx\n", GetLastError());
1107 /* Test with an empty property */
1108 hdr = (struct CertPropIDHeader *)buf;
1109 hdr->propID = CERT_CERT_PROP_ID;
1112 ret = CertAddSerializedElementToStore(store, buf, sizeof(buf), 0, 0, 0,
1114 ok(!ret && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
1115 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
1117 /* Test with a bad size in property header */
1118 hdr->cb = sizeof(bigCert) - 2;
1119 memcpy(buf + sizeof(struct CertPropIDHeader), bigCert, sizeof(bigCert) - 1);
1120 ret = CertAddSerializedElementToStore(store, buf, sizeof(buf), 0, 0, 0,
1122 ok(!ret && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
1123 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
1125 ret = CertAddSerializedElementToStore(store, buf,
1126 sizeof(struct CertPropIDHeader) + sizeof(bigCert) - 1, 0, 0, 0, NULL,
1128 ok(!ret && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
1129 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
1131 ret = CertAddSerializedElementToStore(store, buf,
1132 sizeof(struct CertPropIDHeader) + sizeof(bigCert) - 1, CERT_STORE_ADD_NEW,
1134 ok(!ret && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
1135 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
1137 /* Kosher size in property header, but no context type */
1138 hdr->cb = sizeof(bigCert) - 1;
1139 ret = CertAddSerializedElementToStore(store, buf, sizeof(buf), 0, 0, 0,
1141 ok(!ret && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
1142 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
1144 ret = CertAddSerializedElementToStore(store, buf,
1145 sizeof(struct CertPropIDHeader) + sizeof(bigCert) - 1, 0, 0, 0, NULL,
1147 ok(!ret && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
1148 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
1150 ret = CertAddSerializedElementToStore(store, buf,
1151 sizeof(struct CertPropIDHeader) + sizeof(bigCert) - 1, CERT_STORE_ADD_NEW,
1153 ok(!ret && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
1154 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
1156 /* With a bad context type */
1157 ret = CertAddSerializedElementToStore(store, buf, sizeof(buf), 0, 0,
1158 CERT_STORE_CRL_CONTEXT_FLAG, NULL, NULL);
1159 ok(!ret && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
1160 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
1162 ret = CertAddSerializedElementToStore(store, buf,
1163 sizeof(struct CertPropIDHeader) + sizeof(bigCert) - 1, 0, 0,
1164 CERT_STORE_CRL_CONTEXT_FLAG, NULL, NULL);
1165 ok(!ret && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
1166 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
1168 ret = CertAddSerializedElementToStore(store, buf,
1169 sizeof(struct CertPropIDHeader) + sizeof(bigCert) - 1, CERT_STORE_ADD_NEW,
1170 0, CERT_STORE_CRL_CONTEXT_FLAG, NULL, NULL);
1171 ok(!ret && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
1172 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
1174 /* Bad unknown field, good type */
1176 ret = CertAddSerializedElementToStore(store, buf, sizeof(buf), 0, 0,
1177 CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL);
1178 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
1179 "Expected ERROR_FILE_NOT_FOUND got %08lx\n", GetLastError());
1180 ret = CertAddSerializedElementToStore(store, buf,
1181 sizeof(struct CertPropIDHeader) + sizeof(bigCert) - 1, 0, 0,
1182 CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL);
1183 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
1184 "Expected ERROR_FILE_NOT_FOUND got %08lx\n", GetLastError());
1185 ret = CertAddSerializedElementToStore(store, buf,
1186 sizeof(struct CertPropIDHeader) + sizeof(bigCert) - 1, CERT_STORE_ADD_NEW,
1187 0, CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL);
1188 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
1189 "Expected ERROR_FILE_NOT_FOUND got %08lx\n", GetLastError());
1190 /* Most everything okay, but bad add disposition */
1193 ret = CertAddSerializedElementToStore(store, buf, sizeof(buf), 0, 0,
1194 CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL);
1196 ret = CertAddSerializedElementToStore(store, buf,
1197 sizeof(struct CertPropIDHeader) + sizeof(bigCert) - 1, 0, 0,
1198 CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL);
1200 /* Everything okay, but buffer's too big */
1201 ret = CertAddSerializedElementToStore(store, buf, sizeof(buf),
1202 CERT_STORE_ADD_NEW, 0, CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL);
1203 ok(ret, "CertAddSerializedElementToStore failed: %08lx\n", GetLastError());
1204 /* Everything okay, check it's not re-added */
1205 ret = CertAddSerializedElementToStore(store, buf,
1206 sizeof(struct CertPropIDHeader) + sizeof(bigCert) - 1, CERT_STORE_ADD_NEW,
1207 0, CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL);
1208 ok(!ret && GetLastError() == CRYPT_E_EXISTS,
1209 "Expected CRYPT_E_EXISTS, got %08lx\n", GetLastError());
1211 context = CertEnumCertificatesInStore(store, NULL);
1212 ok(context != NULL, "Expected a cert\n");
1214 CertDeleteCertificateFromStore(context);
1216 /* Try adding with a bogus hash. Oddly enough, it succeeds, and the hash,
1217 * when queried, is the real hash rather than the bogus hash.
1219 hdr = (struct CertPropIDHeader *)(buf + sizeof(struct CertPropIDHeader) +
1220 sizeof(bigCert) - 1);
1221 hdr->propID = CERT_HASH_PROP_ID;
1223 hdr->cb = sizeof(hash);
1224 memset(hash, 0xc, sizeof(hash));
1225 memcpy((LPBYTE)hdr + sizeof(struct CertPropIDHeader), hash, sizeof(hash));
1226 ret = CertAddSerializedElementToStore(store, buf, sizeof(buf),
1227 CERT_STORE_ADD_NEW, 0, CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL,
1228 (const void **)&context);
1229 ok(ret, "CertAddSerializedElementToStore failed: %08lx\n", GetLastError());
1232 BYTE hashVal[20], realHash[20];
1233 DWORD size = sizeof(hashVal);
1235 ret = CryptHashCertificate(0, 0, 0, bigCert, sizeof(bigCert) - 1,
1237 ok(ret, "CryptHashCertificate failed: %08lx\n", GetLastError());
1238 ret = CertGetCertificateContextProperty(context, CERT_HASH_PROP_ID,
1240 ok(ret, "CertGetCertificateContextProperty failed: %08lx\n",
1242 ok(!memcmp(hashVal, realHash, size), "Unexpected hash\n");
1245 CertCloseStore(store, 0);
1250 testCryptHashCert();
1252 /* various combinations of CertOpenStore */
1254 testCollectionStore();
1256 testSystemRegStore();
1258 testCertProperties();
1259 testAddSerialized();