Correct a test that incorrectly showed signed certs couldn't be added
[wine/multimedia.git] / dlls / crypt32 / tests / cert.c
bloba3d008d4367ccbee9f2209648b056465bd8425e1
1 /*
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
21 #include <stdio.h>
22 #include <stdarg.h>
23 #include <windef.h>
24 #include <winbase.h>
25 #include <winreg.h>
26 #include <winerror.h>
27 #include <wincrypt.h>
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
38 DWORD propID;
39 DWORD unknown1;
40 DWORD cb;
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,
47 0x09 };
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,
50 0xa2 };
51 static const BYTE toHash[] = "abcdefghijklmnopqrstuvwxyz0123456789.,;!?:";
52 BOOL ret;
53 BYTE hash[20];
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);
61 /* Test empty hash */
62 ret = CryptHashCertificate(0, 0, 0, toHash, sizeof(toHash), NULL,
63 &hashLen);
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,
74 &hashLen);
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"
87 "\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,
112 0x01, 0x01 };
114 static void testMemStore(void)
116 HCERTSTORE store1, store2;
117 PCCERT_CONTEXT context;
118 BOOL ret;
120 /* NULL provider */
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());
124 /* weird flags */
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());
130 /* normal */
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 */
141 context = NULL;
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",
150 GetLastError());
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");
158 if (context)
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",
168 GetLastError());
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");
176 if (context)
178 DWORD size;
179 BYTE *buf;
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 */
189 /* These crash
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",
197 GetLastError());
198 buf = HeapAlloc(GetProcessHeap(), 0, size);
199 if (buf)
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);
223 if (context)
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
227 * someplace
228 CERT_CONTEXT copy;
229 memcpy(&copy, context, sizeof(copy));
230 ret = CertDeleteCertificateFromStore(&copy);
232 PCCERT_CONTEXT copy = CertDuplicateCertificateContext(context);
234 ok(copy != NULL, "CertDuplicateCertificateContext failed: %08lx\n",
235 GetLastError());
236 ret = CertDeleteCertificateFromStore(context);
237 ok(ret, "CertDeleteCertificateFromStore failed: %08lx\n",
238 GetLastError());
239 /* try deleting a copy */
240 ret = CertDeleteCertificateFromStore(copy);
241 ok(ret, "CertDeleteCertificateFromStore failed: %08lx\n",
242 GetLastError());
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
257 * it isn't read-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");
267 if (context)
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",
277 GetLastError());
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"
289 "\x01";
291 static void testCollectionStore(void)
293 HCERTSTORE store1, store2, collection, collection2;
294 PCCERT_CONTEXT context;
295 BOOL ret;
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",
305 GetLastError());
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");
319 if (context)
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",
329 GetLastError());
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",
339 GetLastError());
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");
365 if (context)
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");
375 if (context)
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");
385 if (context)
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");
401 if (context)
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");
411 if (context)
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");
433 if (context)
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");
443 if (context)
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");
499 if (context)
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");
509 if (context)
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
525 * the store.
526 context = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert,
527 sizeof(bigCert) - 1);
528 ok(context != NULL, "CertCreateCertificateContext failed: %08lx\n",
529 GetLastError());
530 if (context)
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");
541 if (context)
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");
550 if (context)
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.
566 /* This crashes
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 static void testCertProperties(void)
590 PCCERT_CONTEXT context = CertCreateCertificateContext(X509_ASN_ENCODING,
591 bigCert, sizeof(bigCert) - 1);
593 ok(context != NULL, "CertCreateCertificateContext failed: %08lx\n",
594 GetLastError());
595 if (context)
597 DWORD propID, numProps, access, size;
598 BOOL ret;
599 BYTE hash[20] = { 0 }, hashProperty[20];
600 CRYPT_DATA_BLOB blob;
602 /* This crashes
603 propID = CertEnumCertificateContextProperties(NULL, 0);
606 propID = 0;
607 numProps = 0;
608 do {
609 propID = CertEnumCertificateContextProperties(context, propID);
610 if (propID)
611 numProps++;
612 } while (propID != 0);
613 ok(numProps == 0, "Expected 0 properties, got %ld\n", numProps);
615 /* Tests with a NULL cert context. Prop ID 0 fails.. */
616 ret = CertSetCertificateContextProperty(NULL, 0, 0, NULL);
617 ok(!ret && GetLastError() ==
618 HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
619 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
620 GetLastError());
621 /* while this just crashes.
622 ret = CertSetCertificateContextProperty(NULL,
623 CERT_KEY_PROV_HANDLE_PROP_ID, 0, NULL);
626 ret = CertSetCertificateContextProperty(context, 0, 0, NULL);
627 ok(!ret && GetLastError() ==
628 HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
629 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
630 GetLastError());
631 /* Can't set the cert property directly, this crashes.
632 ret = CertSetCertificateContextProperty(context,
633 CERT_CERT_PROP_ID, 0, bigCert2);
636 /* This crashes.
637 ret = CertGetCertificateContextProperty(context,
638 CERT_ACCESS_STATE_PROP_ID, 0, NULL);
640 size = sizeof(access);
641 ret = CertGetCertificateContextProperty(context,
642 CERT_ACCESS_STATE_PROP_ID, &access, &size);
643 ok(ret, "CertGetCertificateContextProperty failed: %08lx\n",
644 GetLastError());
645 ok(!(access & CERT_ACCESS_STATE_WRITE_PERSIST_FLAG),
646 "Didn't expect a persisted cert\n");
647 /* Trying to set this "read only" property crashes.
648 access |= CERT_ACCESS_STATE_WRITE_PERSIST_FLAG;
649 ret = CertSetCertificateContextProperty(context,
650 CERT_ACCESS_STATE_PROP_ID, 0, &access);
653 /* Can I set the hash to an invalid hash? */
654 blob.pbData = hash;
655 blob.cbData = sizeof(hash);
656 ret = CertSetCertificateContextProperty(context, CERT_HASH_PROP_ID, 0,
657 &blob);
658 ok(ret, "CertSetCertificateContextProperty failed: %08lx\n",
659 GetLastError());
660 size = sizeof(hashProperty);
661 ret = CertGetCertificateContextProperty(context, CERT_HASH_PROP_ID,
662 hashProperty, &size);
663 ok(!memcmp(hashProperty, hash, sizeof(hash)), "Unexpected hash\n");
664 /* Delete the (bogus) hash, and get the real one */
665 ret = CertSetCertificateContextProperty(context, CERT_HASH_PROP_ID, 0,
666 NULL);
667 ok(ret, "CertSetCertificateContextProperty failed: %08lx\n",
668 GetLastError());
669 size = sizeof(hash);
670 ret = CryptHashCertificate(0, 0, 0, bigCert, sizeof(bigCert) - 1,
671 hash, &size);
672 ok(ret, "CryptHashCertificate failed: %08lx\n", GetLastError());
673 ret = CertGetCertificateContextProperty(context, CERT_HASH_PROP_ID,
674 hashProperty, &size);
675 ok(ret, "CertGetCertificateContextProperty failed: %08lx\n",
676 GetLastError());
677 ok(!memcmp(hash, hashProperty, sizeof(hash)), "Unexpected hash\n");
679 /* Now that the hash property is set, we should get one property when
680 * enumerating.
682 propID = 0;
683 numProps = 0;
684 do {
685 propID = CertEnumCertificateContextProperties(context, propID);
686 if (propID)
687 numProps++;
688 } while (propID != 0);
689 ok(numProps == 1, "Expected 1 properties, got %ld\n", numProps);
691 CertFreeCertificateContext(context);
695 static void testAddSerialized(void)
697 BOOL ret;
698 HCERTSTORE store;
699 BYTE buf[sizeof(struct CertPropIDHeader) * 2 + 20 + sizeof(bigCert) - 1] =
700 { 0 };
701 BYTE hash[20];
702 struct CertPropIDHeader *hdr;
703 PCCERT_CONTEXT context;
705 ret = CertAddSerializedElementToStore(0, NULL, 0, 0, 0, 0, NULL, NULL);
706 ok(!ret && GetLastError() == ERROR_END_OF_MEDIA,
707 "Expected ERROR_END_OF_MEDIA, got %08lx\n", GetLastError());
709 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
710 CERT_STORE_CREATE_NEW_FLAG, NULL);
711 ok(store != 0, "CertOpenStore failed: %08lx\n", GetLastError());
713 ret = CertAddSerializedElementToStore(store, NULL, 0, 0, 0, 0, NULL, NULL);
714 ok(!ret && GetLastError() == ERROR_END_OF_MEDIA,
715 "Expected ERROR_END_OF_MEDIA, got %08lx\n", GetLastError());
717 /* Test with an empty property */
718 hdr = (struct CertPropIDHeader *)buf;
719 hdr->propID = CERT_CERT_PROP_ID;
720 hdr->unknown1 = 1;
721 hdr->cb = 0;
722 ret = CertAddSerializedElementToStore(store, buf, sizeof(buf), 0, 0, 0,
723 NULL, NULL);
724 ok(!ret && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
725 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
726 GetLastError());
727 /* Test with a bad size in property header */
728 hdr->cb = sizeof(bigCert) - 2;
729 memcpy(buf + sizeof(struct CertPropIDHeader), bigCert, sizeof(bigCert) - 1);
730 ret = CertAddSerializedElementToStore(store, buf, sizeof(buf), 0, 0, 0,
731 NULL, NULL);
732 ok(!ret && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
733 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
734 GetLastError());
735 ret = CertAddSerializedElementToStore(store, buf,
736 sizeof(struct CertPropIDHeader) + sizeof(bigCert) - 1, 0, 0, 0, NULL,
737 NULL);
738 ok(!ret && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
739 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
740 GetLastError());
741 ret = CertAddSerializedElementToStore(store, buf,
742 sizeof(struct CertPropIDHeader) + sizeof(bigCert) - 1, CERT_STORE_ADD_NEW,
743 0, 0, NULL, NULL);
744 ok(!ret && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
745 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
746 GetLastError());
747 /* Kosher size in property header, but no context type */
748 hdr->cb = sizeof(bigCert) - 1;
749 ret = CertAddSerializedElementToStore(store, buf, sizeof(buf), 0, 0, 0,
750 NULL, NULL);
751 ok(!ret && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
752 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
753 GetLastError());
754 ret = CertAddSerializedElementToStore(store, buf,
755 sizeof(struct CertPropIDHeader) + sizeof(bigCert) - 1, 0, 0, 0, NULL,
756 NULL);
757 ok(!ret && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
758 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
759 GetLastError());
760 ret = CertAddSerializedElementToStore(store, buf,
761 sizeof(struct CertPropIDHeader) + sizeof(bigCert) - 1, CERT_STORE_ADD_NEW,
762 0, 0, NULL, NULL);
763 ok(!ret && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
764 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
765 GetLastError());
766 /* With a bad context type */
767 ret = CertAddSerializedElementToStore(store, buf, sizeof(buf), 0, 0,
768 CERT_STORE_CRL_CONTEXT_FLAG, NULL, NULL);
769 ok(!ret && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
770 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
771 GetLastError());
772 ret = CertAddSerializedElementToStore(store, buf,
773 sizeof(struct CertPropIDHeader) + sizeof(bigCert) - 1, 0, 0,
774 CERT_STORE_CRL_CONTEXT_FLAG, NULL, NULL);
775 ok(!ret && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
776 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
777 GetLastError());
778 ret = CertAddSerializedElementToStore(store, buf,
779 sizeof(struct CertPropIDHeader) + sizeof(bigCert) - 1, CERT_STORE_ADD_NEW,
780 0, CERT_STORE_CRL_CONTEXT_FLAG, NULL, NULL);
781 ok(!ret && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
782 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
783 GetLastError());
784 /* Bad unknown field, good type */
785 hdr->unknown1 = 2;
786 ret = CertAddSerializedElementToStore(store, buf, sizeof(buf), 0, 0,
787 CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL);
788 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
789 "Expected ERROR_FILE_NOT_FOUND got %08lx\n", GetLastError());
790 ret = CertAddSerializedElementToStore(store, buf,
791 sizeof(struct CertPropIDHeader) + sizeof(bigCert) - 1, 0, 0,
792 CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL);
793 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
794 "Expected ERROR_FILE_NOT_FOUND got %08lx\n", GetLastError());
795 ret = CertAddSerializedElementToStore(store, buf,
796 sizeof(struct CertPropIDHeader) + sizeof(bigCert) - 1, CERT_STORE_ADD_NEW,
797 0, CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL);
798 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
799 "Expected ERROR_FILE_NOT_FOUND got %08lx\n", GetLastError());
800 /* Most everything okay, but bad add disposition */
801 hdr->unknown1 = 1;
802 /* This crashes
803 ret = CertAddSerializedElementToStore(store, buf, sizeof(buf), 0, 0,
804 CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL);
805 * as does this
806 ret = CertAddSerializedElementToStore(store, buf,
807 sizeof(struct CertPropIDHeader) + sizeof(bigCert) - 1, 0, 0,
808 CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL);
810 /* Everything okay, but buffer's too big */
811 ret = CertAddSerializedElementToStore(store, buf, sizeof(buf),
812 CERT_STORE_ADD_NEW, 0, CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL);
813 ok(ret, "CertAddSerializedElementToStore failed: %08lx\n", GetLastError());
814 /* Everything okay, check it's not re-added */
815 ret = CertAddSerializedElementToStore(store, buf,
816 sizeof(struct CertPropIDHeader) + sizeof(bigCert) - 1, CERT_STORE_ADD_NEW,
817 0, CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL);
818 ok(!ret && GetLastError() == CRYPT_E_EXISTS,
819 "Expected CRYPT_E_EXISTS, got %08lx\n", GetLastError());
821 context = CertEnumCertificatesInStore(store, NULL);
822 ok(context != NULL, "Expected a cert\n");
823 if (context)
824 CertDeleteCertificateFromStore(context);
826 /* Try adding with a bogus hash. Oddly enough, it succeeds, and the hash,
827 * when queried, is the real hash rather than the bogus hash.
829 hdr = (struct CertPropIDHeader *)(buf + sizeof(struct CertPropIDHeader) +
830 sizeof(bigCert) - 1);
831 hdr->propID = CERT_HASH_PROP_ID;
832 hdr->unknown1 = 1;
833 hdr->cb = sizeof(hash);
834 memset(hash, 0xc, sizeof(hash));
835 memcpy((LPBYTE)hdr + sizeof(struct CertPropIDHeader), hash, sizeof(hash));
836 ret = CertAddSerializedElementToStore(store, buf, sizeof(buf),
837 CERT_STORE_ADD_NEW, 0, CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL,
838 (const void **)&context);
839 ok(ret, "CertAddSerializedElementToStore failed: %08lx\n", GetLastError());
840 if (context)
842 BYTE hashVal[20], realHash[20];
843 DWORD size = sizeof(hashVal);
845 ret = CryptHashCertificate(0, 0, 0, bigCert, sizeof(bigCert) - 1,
846 realHash, &size);
847 ok(ret, "CryptHashCertificate failed: %08lx\n", GetLastError());
848 ret = CertGetCertificateContextProperty(context, CERT_HASH_PROP_ID,
849 hashVal, &size);
850 ok(ret, "CertGetCertificateContextProperty failed: %08lx\n",
851 GetLastError());
852 ok(!memcmp(hashVal, realHash, size), "Unexpected hash\n");
855 CertCloseStore(store, 0);
858 START_TEST(cert)
860 testCryptHashCert();
862 /* various combinations of CertOpenStore */
863 testMemStore();
864 testCollectionStore();
866 testCertProperties();
867 testAddSerialized();