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 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",
597 DWORD propID
, numProps
, access
, size
;
599 BYTE hash
[20] = { 0 }, hashProperty
[20];
600 CRYPT_DATA_BLOB blob
;
603 propID = CertEnumCertificateContextProperties(NULL, 0);
609 propID
= CertEnumCertificateContextProperties(context
, propID
);
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",
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",
631 /* Can't set the cert property directly, this crashes.
632 ret = CertSetCertificateContextProperty(context,
633 CERT_CERT_PROP_ID, 0, bigCert2);
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",
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? */
655 blob
.cbData
= sizeof(hash
);
656 ret
= CertSetCertificateContextProperty(context
, CERT_HASH_PROP_ID
, 0,
658 ok(ret
, "CertSetCertificateContextProperty failed: %08lx\n",
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,
667 ok(ret
, "CertSetCertificateContextProperty failed: %08lx\n",
670 ret
= CryptHashCertificate(0, 0, 0, bigCert
, sizeof(bigCert
) - 1,
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",
677 ok(!memcmp(hash
, hashProperty
, sizeof(hash
)), "Unexpected hash\n");
679 /* Now that the hash property is set, we should get one property when
685 propID
= CertEnumCertificateContextProperties(context
, propID
);
688 } while (propID
!= 0);
689 ok(numProps
== 1, "Expected 1 properties, got %ld\n", numProps
);
691 CertFreeCertificateContext(context
);
695 static void testAddSerialized(void)
699 BYTE buf
[sizeof(struct CertPropIDHeader
) * 2 + 20 + sizeof(bigCert
) - 1] =
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
;
722 ret
= CertAddSerializedElementToStore(store
, buf
, sizeof(buf
), 0, 0, 0,
724 ok(!ret
&& GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER
),
725 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
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,
732 ok(!ret
&& GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER
),
733 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
735 ret
= CertAddSerializedElementToStore(store
, buf
,
736 sizeof(struct CertPropIDHeader
) + sizeof(bigCert
) - 1, 0, 0, 0, NULL
,
738 ok(!ret
&& GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER
),
739 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
741 ret
= CertAddSerializedElementToStore(store
, buf
,
742 sizeof(struct CertPropIDHeader
) + sizeof(bigCert
) - 1, CERT_STORE_ADD_NEW
,
744 ok(!ret
&& GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER
),
745 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
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,
751 ok(!ret
&& GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER
),
752 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
754 ret
= CertAddSerializedElementToStore(store
, buf
,
755 sizeof(struct CertPropIDHeader
) + sizeof(bigCert
) - 1, 0, 0, 0, NULL
,
757 ok(!ret
&& GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER
),
758 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
760 ret
= CertAddSerializedElementToStore(store
, buf
,
761 sizeof(struct CertPropIDHeader
) + sizeof(bigCert
) - 1, CERT_STORE_ADD_NEW
,
763 ok(!ret
&& GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER
),
764 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
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",
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",
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",
784 /* Bad unknown field, good type */
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 */
803 ret = CertAddSerializedElementToStore(store, buf, sizeof(buf), 0, 0,
804 CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL);
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");
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
;
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());
842 BYTE hashVal
[20], realHash
[20];
843 DWORD size
= sizeof(hashVal
);
845 ret
= CryptHashCertificate(0, 0, 0, bigCert
, sizeof(bigCert
) - 1,
847 ok(ret
, "CryptHashCertificate failed: %08lx\n", GetLastError());
848 ret
= CertGetCertificateContextProperty(context
, CERT_HASH_PROP_ID
,
850 ok(ret
, "CertGetCertificateContextProperty failed: %08lx\n",
852 ok(!memcmp(hashVal
, realHash
, size
), "Unexpected hash\n");
855 CertCloseStore(store
, 0);
862 /* various combinations of CertOpenStore */
864 testCollectionStore();
866 testCertProperties();