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
30 #include "wine/test.h"
32 /* The following aren't defined in wincrypt.h, as they're "reserved" */
33 #define CERT_CERT_PROP_ID 32
34 #define CERT_CRL_PROP_ID 33
35 #define CERT_CTL_PROP_ID 34
37 struct CertPropIDHeader
44 static BOOL (WINAPI * pCryptVerifyCertificateSignatureEx)
45 (HCRYPTPROV, DWORD, DWORD, void *, DWORD, void *, DWORD, void *);
47 #define CRYPT_GET_PROC(func) \
48 p ## func = (void *)GetProcAddress(hCrypt32, #func); \
50 trace("GetProcAddress(hCrypt32, \"%s\") failed\n", #func); \
52 static void init_function_pointers(void)
56 pCryptVerifyCertificateSignatureEx = NULL;
58 hCrypt32 = GetModuleHandleA("crypt32.dll");
61 CRYPT_GET_PROC(CryptVerifyCertificateSignatureEx);
64 static void testCryptHashCert(void)
66 static const BYTE emptyHash[] = { 0xda, 0x39, 0xa3, 0xee, 0x5e, 0x6b, 0x4b,
67 0x0d, 0x32, 0x55, 0xbf, 0xef, 0x95, 0x60, 0x18, 0x90, 0xaf, 0xd8, 0x07,
69 static const BYTE knownHash[] = { 0xae, 0x9d, 0xbf, 0x6d, 0xf5, 0x46, 0xee,
70 0x8b, 0xc5, 0x7a, 0x13, 0xba, 0xc2, 0xb1, 0x04, 0xf2, 0xbf, 0x52, 0xa8,
72 static const BYTE toHash[] = "abcdefghijklmnopqrstuvwxyz0123456789.,;!?:";
75 DWORD hashLen = sizeof(hash);
77 /* NULL buffer and nonzero length crashes
78 ret = CryptHashCertificate(0, 0, 0, NULL, size, hash, &hashLen);
79 empty hash length also crashes
80 ret = CryptHashCertificate(0, 0, 0, buf, size, hash, NULL);
83 ret = CryptHashCertificate(0, 0, 0, toHash, sizeof(toHash), NULL,
85 ok(ret, "CryptHashCertificate failed: %08lx\n", GetLastError());
86 ok(hashLen == sizeof(hash),
87 "Got unexpected size of hash %ld, expected %d\n", hashLen, sizeof(hash));
88 /* Test with empty buffer */
89 ret = CryptHashCertificate(0, 0, 0, NULL, 0, hash, &hashLen);
90 ok(ret, "CryptHashCertificate failed: %08lx\n", GetLastError());
91 ok(!memcmp(hash, emptyHash, sizeof(emptyHash)),
92 "Unexpected hash of nothing\n");
93 /* Test a known value */
94 ret = CryptHashCertificate(0, 0, 0, toHash, sizeof(toHash), hash,
96 ok(ret, "CryptHashCertificate failed: %08lx\n", GetLastError());
97 ok(!memcmp(hash, knownHash, sizeof(knownHash)), "Unexpected hash\n");
100 static const BYTE emptyCert[] = { 0x30, 0x00 };
101 static const BYTE bigCert[] = "\x30\x7a\x02\x01\x01\x30\x02\x06\x00"
102 "\x30\x15\x31\x13\x30\x11\x06\x03\x55\x04\x03\x13\x0a\x4a\x75\x61\x6e\x20\x4c"
103 "\x61\x6e\x67\x00\x30\x22\x18\x0f\x31\x36\x30\x31\x30\x31\x30\x31\x30\x30\x30"
104 "\x30\x30\x30\x5a\x18\x0f\x31\x36\x30\x31\x30\x31\x30\x31\x30\x30\x30\x30\x30"
105 "\x30\x5a\x30\x15\x31\x13\x30\x11\x06\x03\x55\x04\x03\x13\x0a\x4a\x75\x61\x6e"
106 "\x20\x4c\x61\x6e\x67\x00\x30\x07\x30\x02\x06\x00\x03\x01\x00\xa3\x16\x30\x14"
107 "\x30\x12\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x08\x30\x06\x01\x01\xff\x02\x01"
109 static const BYTE signedBigCert[] = {
110 0x30, 0x81, 0x93, 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06, 0x00, 0x30,
111 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a,
112 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22, 0x18, 0x0f,
113 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
114 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30,
115 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06,
116 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61,
117 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3,
118 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff,
119 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
120 0x00, 0x03, 0x11, 0x00, 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07,
121 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00 };
122 static const BYTE serializedCert[] = { 0x20, 0x00, 0x00, 0x00,
123 0x01, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x30, 0x7a, 0x02, 0x01, 0x01,
124 0x30, 0x02, 0x06, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55,
125 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67,
126 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31,
127 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31,
128 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15,
129 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75,
130 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06,
131 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55,
132 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02,
134 static const BYTE signedCRL[] = { 0x30, 0x45, 0x30, 0x2c, 0x30, 0x02, 0x06,
135 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
136 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18, 0x0f,
137 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
138 0x30, 0x5a, 0x30, 0x02, 0x06, 0x00, 0x03, 0x11, 0x00, 0x0f, 0x0e, 0x0d, 0x0c,
139 0x0b, 0x0a, 0x09, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00 };
141 static void testMemStore(void)
143 HCERTSTORE store1, store2;
144 PCCERT_CONTEXT context;
148 store1 = CertOpenStore(0, 0, 0, 0, NULL);
149 ok(!store1 && GetLastError() == ERROR_FILE_NOT_FOUND,
150 "Expected ERROR_FILE_NOT_FOUND, got %ld\n", GetLastError());
152 store1 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
153 CERT_STORE_DELETE_FLAG, NULL);
154 ok(!store1 && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED,
155 "Expected ERROR_CALL_NOT_IMPLEMENTED, got %ld\n", GetLastError());
158 store1 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
159 CERT_STORE_CREATE_NEW_FLAG, NULL);
160 ok(store1 != NULL, "CertOpenStore failed: %ld\n", GetLastError());
161 /* open existing doesn't */
162 store2 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
163 CERT_STORE_OPEN_EXISTING_FLAG, NULL);
164 ok(store2 != NULL, "CertOpenStore failed: %ld\n", GetLastError());
165 ok(store1 != store2, "Expected different stores\n");
167 /* add a bogus (empty) cert */
169 ret = CertAddEncodedCertificateToStore(store1, X509_ASN_ENCODING, emptyCert,
170 sizeof(emptyCert), CERT_STORE_ADD_ALWAYS, &context);
171 /* Windows returns CRYPT_E_ASN1_EOD, but accept CRYPT_E_ASN1_CORRUPT as
172 * well (because matching errors is tough in this case)
174 ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD || GetLastError() ==
175 CRYPT_E_ASN1_CORRUPT),
176 "Expected CRYPT_E_ASN1_EOD or CRYPT_E_ASN1_CORRUPT, got %08lx\n",
178 /* add a "signed" cert--the signature isn't a real signature, so this adds
179 * without any check of the signature's validity
181 ret = CertAddEncodedCertificateToStore(store1, X509_ASN_ENCODING,
182 signedBigCert, sizeof(signedBigCert), CERT_STORE_ADD_ALWAYS, &context);
183 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n", GetLastError());
184 ok(context != NULL, "Expected a valid cert context\n");
187 ok(context->cbCertEncoded == sizeof(signedBigCert),
188 "Expected cert of %d bytes, got %ld\n", sizeof(signedBigCert),
189 context->cbCertEncoded);
190 ok(!memcmp(context->pbCertEncoded, signedBigCert,
191 sizeof(signedBigCert)), "Unexpected encoded cert in context\n");
192 /* remove it, the rest of the tests will work on an unsigned cert */
193 ret = CertDeleteCertificateFromStore(context);
194 ok(ret, "CertDeleteCertificateFromStore failed: %08lx\n",
197 /* try adding a "signed" CRL as a cert */
198 ret = CertAddEncodedCertificateToStore(store1, X509_ASN_ENCODING,
199 signedCRL, sizeof(signedCRL), CERT_STORE_ADD_ALWAYS, &context);
200 ok(!ret && (GetLastError() == CRYPT_E_ASN1_BADTAG || GetLastError() ==
201 CRYPT_E_ASN1_CORRUPT),
202 "Expected CRYPT_E_ASN1_BADTAG or CRYPT_E_ASN1_CORRUPT, got %08lx\n",
204 /* add a cert to store1 */
205 ret = CertAddEncodedCertificateToStore(store1, X509_ASN_ENCODING, bigCert,
206 sizeof(bigCert) - 1, CERT_STORE_ADD_ALWAYS, &context);
207 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n", GetLastError());
208 ok(context != NULL, "Expected a valid cert context\n");
214 ok(context->cbCertEncoded == sizeof(bigCert) - 1,
215 "Expected cert of %d bytes, got %ld\n", sizeof(bigCert) - 1,
216 context->cbCertEncoded);
217 ok(!memcmp(context->pbCertEncoded, bigCert, sizeof(bigCert) - 1),
218 "Unexpected encoded cert in context\n");
219 ok(context->hCertStore == store1, "Unexpected store\n");
221 /* check serializing this element */
223 ret = CertSerializeCertificateStoreElement(NULL, 0, NULL, NULL);
224 ret = CertSerializeCertificateStoreElement(context, 0, NULL, NULL);
225 ret = CertSerializeCertificateStoreElement(NULL, 0, NULL, &size);
227 /* apparently flags are ignored */
228 ret = CertSerializeCertificateStoreElement(context, 1, NULL, &size);
229 ok(ret, "CertSerializeCertificateStoreElement failed: %08lx\n",
231 buf = HeapAlloc(GetProcessHeap(), 0, size);
234 ret = CertSerializeCertificateStoreElement(context, 0, buf, &size);
235 ok(size == sizeof(serializedCert), "Expected size %d, got %ld\n",
236 sizeof(serializedCert), size);
237 ok(!memcmp(serializedCert, buf, size),
238 "Unexpected serialized cert\n");
239 HeapFree(GetProcessHeap(), 0, buf);
242 ret = CertFreeCertificateContext(context);
243 ok(ret, "CertFreeCertificateContext failed: %08lx\n", GetLastError());
245 /* verify the cert's in store1 */
246 context = CertEnumCertificatesInStore(store1, NULL);
247 ok(context != NULL, "Expected a valid context\n");
248 context = CertEnumCertificatesInStore(store1, context);
249 ok(!context && GetLastError() == CRYPT_E_NOT_FOUND,
250 "Expected CRYPT_E_NOT_FOUND, got %08lx\n", GetLastError());
251 /* verify store2 (the "open existing" mem store) is still empty */
252 context = CertEnumCertificatesInStore(store2, NULL);
253 ok(!context, "Expected an empty store\n");
254 /* delete the cert from store1, and check it's empty */
255 context = CertEnumCertificatesInStore(store1, NULL);
258 /* Deleting a bitwise copy crashes with an access to an uninitialized
259 * pointer, so a cert context has some special data out there in memory
262 memcpy(©, context, sizeof(copy));
263 ret = CertDeleteCertificateFromStore(©);
265 PCCERT_CONTEXT copy = CertDuplicateCertificateContext(context);
267 ok(copy != NULL, "CertDuplicateCertificateContext failed: %08lx\n",
269 ret = CertDeleteCertificateFromStore(context);
270 ok(ret, "CertDeleteCertificateFromStore failed: %08lx\n",
272 /* try deleting a copy */
273 ret = CertDeleteCertificateFromStore(copy);
274 ok(ret, "CertDeleteCertificateFromStore failed: %08lx\n",
276 /* check that the store is empty */
277 context = CertEnumCertificatesInStore(store1, NULL);
278 ok(!context, "Expected an empty store\n");
281 /* close an empty store */
282 ret = CertCloseStore(NULL, 0);
283 ok(ret, "CertCloseStore failed: %ld\n", GetLastError());
284 ret = CertCloseStore(store1, 0);
285 ok(ret, "CertCloseStore failed: %ld\n", GetLastError());
286 ret = CertCloseStore(store2, 0);
287 ok(ret, "CertCloseStore failed: %ld\n", GetLastError());
289 /* This seems nonsensical, but you can open a read-only mem store, only
292 store1 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
293 CERT_STORE_READONLY_FLAG, NULL);
294 ok(store1 != NULL, "CertOpenStore failed: %ld\n", GetLastError());
295 /* yep, this succeeds */
296 ret = CertAddEncodedCertificateToStore(store1, X509_ASN_ENCODING, bigCert,
297 sizeof(bigCert) - 1, CERT_STORE_ADD_ALWAYS, &context);
298 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n", GetLastError());
299 ok(context != NULL, "Expected a valid cert context\n");
302 ok(context->cbCertEncoded == sizeof(bigCert) - 1,
303 "Expected cert of %d bytes, got %ld\n", sizeof(bigCert) - 1,
304 context->cbCertEncoded);
305 ok(!memcmp(context->pbCertEncoded, bigCert, sizeof(bigCert) - 1),
306 "Unexpected encoded cert in context\n");
307 ok(context->hCertStore == store1, "Unexpected store\n");
308 ret = CertDeleteCertificateFromStore(context);
309 ok(ret, "CertDeleteCertificateFromStore failed: %08lx\n",
312 CertCloseStore(store1, 0);
315 static const BYTE bigCert2[] = "\x30\x7a\x02\x01\x01\x30\x02\x06\x00"
316 "\x30\x15\x31\x13\x30\x11\x06\x03\x55\x04\x03\x13\x0a\x41\x6c\x65\x78\x20\x4c"
317 "\x61\x6e\x67\x00\x30\x22\x18\x0f\x31\x36\x30\x31\x30\x31\x30\x31\x30\x30\x30"
318 "\x30\x30\x30\x5a\x18\x0f\x31\x36\x30\x31\x30\x31\x30\x31\x30\x30\x30\x30\x30"
319 "\x30\x5a\x30\x15\x31\x13\x30\x11\x06\x03\x55\x04\x03\x13\x0a\x41\x6c\x65\x78"
320 "\x20\x4c\x61\x6e\x67\x00\x30\x07\x30\x02\x06\x00\x03\x01\x00\xa3\x16\x30\x14"
321 "\x30\x12\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x08\x30\x06\x01\x01\xff\x02\x01"
324 static void testCollectionStore(void)
326 HCERTSTORE store1, store2, collection, collection2;
327 PCCERT_CONTEXT context;
330 collection = CertOpenStore(CERT_STORE_PROV_COLLECTION, 0, 0,
331 CERT_STORE_CREATE_NEW_FLAG, NULL);
333 /* Try adding a cert to any empty collection */
334 ret = CertAddEncodedCertificateToStore(collection, X509_ASN_ENCODING,
335 bigCert, sizeof(bigCert) - 1, CERT_STORE_ADD_ALWAYS, NULL);
336 ok(!ret && GetLastError() == HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED),
337 "Expected HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED), got %08lx\n",
340 /* Create and add a cert to a memory store */
341 store1 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
342 CERT_STORE_CREATE_NEW_FLAG, NULL);
343 ret = CertAddEncodedCertificateToStore(store1, X509_ASN_ENCODING,
344 bigCert, sizeof(bigCert) - 1, CERT_STORE_ADD_ALWAYS, NULL);
345 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n", GetLastError());
346 /* Add the memory store to the collection, without allowing adding */
347 ret = CertAddStoreToCollection(collection, store1, 0, 0);
348 ok(ret, "CertAddStoreToCollection failed: %08lx\n", GetLastError());
349 /* Verify the cert is in the collection */
350 context = CertEnumCertificatesInStore(collection, NULL);
351 ok(context != NULL, "Expected a valid context\n");
354 ok(context->hCertStore == collection, "Unexpected store\n");
355 CertFreeCertificateContext(context);
357 /* Check that adding to the collection isn't allowed */
358 ret = CertAddEncodedCertificateToStore(collection, X509_ASN_ENCODING,
359 bigCert2, sizeof(bigCert2) - 1, CERT_STORE_ADD_ALWAYS, NULL);
360 ok(!ret && GetLastError() == HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED),
361 "Expected HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED), got %08lx\n",
364 /* Create a new memory store */
365 store2 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
366 CERT_STORE_CREATE_NEW_FLAG, NULL);
367 /* Try adding a store to a non-collection store */
368 ret = CertAddStoreToCollection(store1, store2,
369 CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
370 ok(!ret && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
371 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
373 /* Try adding some bogus stores */
374 /* This crashes in Windows
375 ret = CertAddStoreToCollection(0, store2,
376 CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
378 /* This "succeeds"... */
379 ret = CertAddStoreToCollection(collection, 0,
380 CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
381 ok(ret, "CertAddStoreToCollection failed: %08lx\n", GetLastError());
382 /* while this crashes.
383 ret = CertAddStoreToCollection(collection, 1,
384 CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
387 /* Add it to the collection, this time allowing adding */
388 ret = CertAddStoreToCollection(collection, store2,
389 CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
390 ok(ret, "CertAddStoreToCollection failed: %08lx\n", GetLastError());
391 /* Check that adding to the collection is allowed */
392 ret = CertAddEncodedCertificateToStore(collection, X509_ASN_ENCODING,
393 bigCert2, sizeof(bigCert2) - 1, CERT_STORE_ADD_ALWAYS, NULL);
394 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n", GetLastError());
395 /* Now check that it was actually added to store2 */
396 context = CertEnumCertificatesInStore(store2, NULL);
397 ok(context != NULL, "Expected a valid context\n");
400 ok(context->hCertStore == store2, "Unexpected store\n");
401 CertFreeCertificateContext(context);
403 /* Check that the collection has both bigCert and bigCert2. bigCert comes
404 * first because store1 was added first.
406 context = CertEnumCertificatesInStore(collection, NULL);
407 ok(context != NULL, "Expected a valid context\n");
410 ok(context->hCertStore == collection, "Unexpected store\n");
411 ok(context->cbCertEncoded == sizeof(bigCert) - 1,
412 "Expected size %d, got %ld\n", sizeof(bigCert) - 1,
413 context->cbCertEncoded);
414 ok(!memcmp(context->pbCertEncoded, bigCert, context->cbCertEncoded),
415 "Unexpected cert\n");
416 context = CertEnumCertificatesInStore(collection, context);
417 ok(context != NULL, "Expected a valid context\n");
420 ok(context->hCertStore == collection, "Unexpected store\n");
421 ok(context->cbCertEncoded == sizeof(bigCert2) - 1,
422 "Expected size %d, got %ld\n", sizeof(bigCert2) - 1,
423 context->cbCertEncoded);
424 ok(!memcmp(context->pbCertEncoded, bigCert2,
425 context->cbCertEncoded), "Unexpected cert\n");
426 context = CertEnumCertificatesInStore(collection, context);
427 ok(!context, "Unexpected cert\n");
430 /* close store2, and check that the collection is unmodified */
431 CertCloseStore(store2, 0);
432 context = CertEnumCertificatesInStore(collection, NULL);
433 ok(context != NULL, "Expected a valid context\n");
436 ok(context->hCertStore == collection, "Unexpected store\n");
437 ok(context->cbCertEncoded == sizeof(bigCert) - 1,
438 "Expected size %d, got %ld\n", sizeof(bigCert) - 1,
439 context->cbCertEncoded);
440 ok(!memcmp(context->pbCertEncoded, bigCert, context->cbCertEncoded),
441 "Unexpected cert\n");
442 context = CertEnumCertificatesInStore(collection, context);
443 ok(context != NULL, "Expected a valid context\n");
446 ok(context->hCertStore == collection, "Unexpected store\n");
447 ok(context->cbCertEncoded == sizeof(bigCert2) - 1,
448 "Expected size %d, got %ld\n", sizeof(bigCert2) - 1,
449 context->cbCertEncoded);
450 ok(!memcmp(context->pbCertEncoded, bigCert2,
451 context->cbCertEncoded), "Unexpected cert\n");
452 context = CertEnumCertificatesInStore(collection, context);
453 ok(!context, "Unexpected cert\n");
457 /* Adding a collection to a collection is legal */
458 collection2 = CertOpenStore(CERT_STORE_PROV_COLLECTION, 0, 0,
459 CERT_STORE_CREATE_NEW_FLAG, NULL);
460 ret = CertAddStoreToCollection(collection2, collection,
461 CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
462 ok(ret, "CertAddStoreToCollection failed: %08lx\n", GetLastError());
463 /* check the contents of collection2 */
464 context = CertEnumCertificatesInStore(collection2, NULL);
465 ok(context != NULL, "Expected a valid context\n");
468 ok(context->hCertStore == collection2, "Unexpected store\n");
469 ok(context->cbCertEncoded == sizeof(bigCert) - 1,
470 "Expected size %d, got %ld\n", sizeof(bigCert) - 1,
471 context->cbCertEncoded);
472 ok(!memcmp(context->pbCertEncoded, bigCert, context->cbCertEncoded),
473 "Unexpected cert\n");
474 context = CertEnumCertificatesInStore(collection2, context);
475 ok(context != NULL, "Expected a valid context\n");
478 ok(context->hCertStore == collection2, "Unexpected store\n");
479 ok(context->cbCertEncoded == sizeof(bigCert2) - 1,
480 "Expected size %d, got %ld\n", sizeof(bigCert2) - 1,
481 context->cbCertEncoded);
482 ok(!memcmp(context->pbCertEncoded, bigCert2,
483 context->cbCertEncoded), "Unexpected cert\n");
484 context = CertEnumCertificatesInStore(collection2, context);
485 ok(!context, "Unexpected cert\n");
489 /* I'd like to test closing the collection in the middle of enumeration,
490 * but my tests have been inconsistent. The first time calling
491 * CertEnumCertificatesInStore on a closed collection succeeded, while the
492 * second crashed. So anything appears to be fair game.
493 * I'd also like to test removing a store from a collection in the middle
494 * of an enumeration, but my tests in Windows have been inconclusive.
495 * In one scenario it worked. In another scenario, about a third of the
496 * time this leads to "random" crashes elsewhere in the code. This
497 * probably means this is not allowed.
500 CertCloseStore(store1, 0);
501 CertCloseStore(collection, 0);
502 CertCloseStore(collection2, 0);
504 /* Add the same cert to two memory stores, then put them in a collection */
505 store1 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
506 CERT_STORE_CREATE_NEW_FLAG, NULL);
507 ok(store1 != 0, "CertOpenStore failed: %08lx\n", GetLastError());
508 store2 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
509 CERT_STORE_CREATE_NEW_FLAG, NULL);
510 ok(store2 != 0, "CertOpenStore failed: %08lx\n", GetLastError());
512 ret = CertAddEncodedCertificateToStore(store1, X509_ASN_ENCODING,
513 bigCert, sizeof(bigCert) - 1, CERT_STORE_ADD_ALWAYS, NULL);
514 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n", GetLastError());
515 ret = CertAddEncodedCertificateToStore(store2, X509_ASN_ENCODING,
516 bigCert, sizeof(bigCert) - 1, CERT_STORE_ADD_ALWAYS, NULL);
517 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n", GetLastError());
518 collection = CertOpenStore(CERT_STORE_PROV_COLLECTION, 0, 0,
519 CERT_STORE_CREATE_NEW_FLAG, NULL);
520 ok(collection != 0, "CertOpenStore failed: %08lx\n", GetLastError());
522 ret = CertAddStoreToCollection(collection, store1,
523 CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
524 ok(ret, "CertAddStoreToCollection failed: %08lx\n", GetLastError());
525 ret = CertAddStoreToCollection(collection, store2,
526 CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
527 ok(ret, "CertAddStoreToCollection failed: %08lx\n", GetLastError());
529 /* Check that the collection has two copies of the same cert */
530 context = CertEnumCertificatesInStore(collection, NULL);
531 ok(context != NULL, "Expected a valid context\n");
534 ok(context->hCertStore == collection, "Unexpected store\n");
535 ok(context->cbCertEncoded == sizeof(bigCert) - 1,
536 "Expected size %d, got %ld\n", sizeof(bigCert) - 1,
537 context->cbCertEncoded);
538 ok(!memcmp(context->pbCertEncoded, bigCert, context->cbCertEncoded),
539 "Unexpected cert\n");
540 context = CertEnumCertificatesInStore(collection, context);
541 ok(context != NULL, "Expected a valid context\n");
544 ok(context->hCertStore == collection, "Unexpected store\n");
545 ok(context->cbCertEncoded == sizeof(bigCert) - 1,
546 "Expected size %d, got %ld\n", sizeof(bigCert) - 1,
547 context->cbCertEncoded);
548 ok(!memcmp(context->pbCertEncoded, bigCert, context->cbCertEncoded),
549 "Unexpected cert\n");
550 context = CertEnumCertificatesInStore(collection, context);
551 ok(context == NULL, "Unexpected cert\n");
555 /* The following would check whether I can delete an identical cert, rather
556 * than one enumerated from the store. It crashes, so that means I must
557 * only call CertDeleteCertificateFromStore with contexts enumerated from
559 context = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert,
560 sizeof(bigCert) - 1);
561 ok(context != NULL, "CertCreateCertificateContext failed: %08lx\n",
565 ret = CertDeleteCertificateFromStore(collection, context);
566 printf("ret is %d, GetLastError is %08lx\n", ret, GetLastError());
567 CertFreeCertificateContext(context);
571 /* Now check deleting from the collection. */
572 context = CertEnumCertificatesInStore(collection, NULL);
573 ok(context != NULL, "Expected a valid context\n");
576 CertDeleteCertificateFromStore(context);
577 /* store1 should now be empty */
578 context = CertEnumCertificatesInStore(store1, NULL);
579 ok(!context, "Unexpected cert\n");
580 /* and there should be one certificate in the collection */
581 context = CertEnumCertificatesInStore(collection, NULL);
582 ok(context != NULL, "Expected a valid cert\n");
585 ok(context->hCertStore == collection, "Unexpected store\n");
586 ok(context->cbCertEncoded == sizeof(bigCert) - 1,
587 "Expected size %d, got %ld\n", sizeof(bigCert) - 1,
588 context->cbCertEncoded);
589 ok(!memcmp(context->pbCertEncoded, bigCert, context->cbCertEncoded),
590 "Unexpected cert\n");
592 context = CertEnumCertificatesInStore(collection, context);
593 ok(context == NULL, "Unexpected cert\n");
596 /* Finally, test removing stores from the collection. No return value, so
597 * it's a bit funny to test.
600 CertRemoveStoreFromCollection(NULL, NULL);
602 /* This "succeeds," no crash, no last error set */
603 SetLastError(0xdeadbeef);
604 CertRemoveStoreFromCollection(store2, collection);
605 ok(GetLastError() == 0xdeadbeef,
606 "Didn't expect an error to be set: %08lx\n", GetLastError());
608 /* After removing store2, the collection should be empty */
609 SetLastError(0xdeadbeef);
610 CertRemoveStoreFromCollection(collection, store2);
611 ok(GetLastError() == 0xdeadbeef,
612 "Didn't expect an error to be set: %08lx\n", GetLastError());
613 context = CertEnumCertificatesInStore(collection, NULL);
614 ok(!context, "Unexpected cert\n");
616 CertCloseStore(collection, 0);
617 CertCloseStore(store2, 0);
618 CertCloseStore(store1, 0);
621 /* Looks for the property with ID propID in the buffer buf. Returns a pointer
622 * to its header if found, NULL if not.
624 static const struct CertPropIDHeader *findPropID(const BYTE *buf, DWORD size,
627 const struct CertPropIDHeader *ret = NULL;
630 while (size && !ret && !failed)
632 if (size < sizeof(struct CertPropIDHeader))
636 const struct CertPropIDHeader *hdr =
637 (const struct CertPropIDHeader *)buf;
639 size -= sizeof(struct CertPropIDHeader);
640 buf += sizeof(struct CertPropIDHeader);
643 else if (hdr->propID == propID)
655 typedef DWORD (WINAPI *SHDeleteKeyAFunc)(HKEY, LPCSTR);
657 static void testRegStore(void)
659 static const char tempKey[] = "Software\\Wine\\CryptTemp";
665 store = CertOpenStore(CERT_STORE_PROV_REG, 0, 0, 0, NULL);
666 ok(!store && GetLastError() == ERROR_INVALID_HANDLE,
667 "Expected ERROR_INVALID_HANDLE, got %ld\n", GetLastError());
668 store = CertOpenStore(CERT_STORE_PROV_REG, 0, 0, 0, key);
669 ok(!store && GetLastError() == ERROR_INVALID_HANDLE,
670 "Expected ERROR_INVALID_HANDLE, got %ld\n", GetLastError());
672 /* Opening up any old key works.. */
673 key = HKEY_CURRENT_USER;
674 store = CertOpenStore(CERT_STORE_PROV_REG, 0, 0, 0, key);
675 /* Not sure if this is a bug in DuplicateHandle, marking todo_wine for now
677 todo_wine ok(store != 0, "CertOpenStore failed: %08lx\n", GetLastError());
678 CertCloseStore(store, 0);
680 rc = RegCreateKeyExA(HKEY_CURRENT_USER, tempKey, 0, NULL, 0, KEY_ALL_ACCESS,
682 ok(!rc, "RegCreateKeyExA failed: %ld\n", rc);
688 static const char certificates[] = "Certificates\\";
689 char subKeyName[sizeof(certificates) + 20 * 2 + 1], *ptr;
691 PCCERT_CONTEXT context;
693 store = CertOpenStore(CERT_STORE_PROV_REG, 0, 0, 0, key);
694 ok(store != 0, "CertOpenStore failed: %08lx\n", GetLastError());
695 /* Add a certificate. It isn't persisted right away, since it's only
696 * added to the cache..
698 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
699 bigCert2, sizeof(bigCert2) - 1, CERT_STORE_ADD_ALWAYS, NULL);
700 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n",
702 /* so flush the cache to force a commit.. */
703 ret = CertControlStore(store, 0, CERT_STORE_CTRL_COMMIT, NULL);
704 ok(ret, "CertControlStore failed: %08lx\n", GetLastError());
705 /* and check that the expected subkey was written. */
707 ret = CryptHashCertificate(0, 0, 0, bigCert2, sizeof(bigCert2) - 1,
709 ok(ret, "CryptHashCertificate failed: %ld\n", GetLastError());
710 strcpy(subKeyName, certificates);
711 for (i = 0, ptr = subKeyName + sizeof(certificates) - 1; i < size;
713 sprintf(ptr, "%02X", hash[i]);
714 rc = RegCreateKeyExA(key, subKeyName, 0, NULL, 0, KEY_ALL_ACCESS, NULL,
716 ok(!rc, "RegCreateKeyExA failed: %ld\n", rc);
722 RegQueryValueExA(subKey, "Blob", NULL, NULL, NULL, &size);
723 buf = HeapAlloc(GetProcessHeap(), 0, size);
726 rc = RegQueryValueExA(subKey, "Blob", NULL, NULL, buf, &size);
727 ok(!rc, "RegQueryValueExA failed: %ld\n", rc);
730 const struct CertPropIDHeader *hdr;
732 /* Both the hash and the cert should be present */
733 hdr = findPropID(buf, size, CERT_CERT_PROP_ID);
734 ok(hdr != NULL, "Expected to find a cert property\n");
737 ok(hdr->cb == sizeof(bigCert2) - 1,
738 "Unexpected size %ld of cert property, expected %d\n",
739 hdr->cb, sizeof(bigCert2) - 1);
740 ok(!memcmp((BYTE *)hdr + sizeof(*hdr), bigCert2,
741 hdr->cb), "Unexpected cert in cert property\n");
743 hdr = findPropID(buf, size, CERT_HASH_PROP_ID);
744 ok(hdr != NULL, "Expected to find a hash property\n");
747 ok(hdr->cb == sizeof(hash),
748 "Unexpected size %ld of hash property, expected %d\n",
749 hdr->cb, sizeof(hash));
750 ok(!memcmp((BYTE *)hdr + sizeof(*hdr), hash,
751 hdr->cb), "Unexpected hash in cert property\n");
754 HeapFree(GetProcessHeap(), 0, buf);
759 /* Remove the existing context */
760 context = CertEnumCertificatesInStore(store, NULL);
761 ok(context != NULL, "Expected a cert context\n");
763 CertDeleteCertificateFromStore(context);
764 ret = CertControlStore(store, 0, CERT_STORE_CTRL_COMMIT, NULL);
765 ok(ret, "CertControlStore failed: %08lx\n", GetLastError());
767 /* Add a serialized cert with a bogus hash directly to the registry */
768 memset(hash, 0, sizeof(hash));
769 strcpy(subKeyName, certificates);
770 for (i = 0, ptr = subKeyName + sizeof(certificates) - 1;
771 i < sizeof(hash); i++, ptr += 2)
772 sprintf(ptr, "%02X", hash[i]);
773 rc = RegCreateKeyExA(key, subKeyName, 0, NULL, 0, KEY_ALL_ACCESS, NULL,
775 ok(!rc, "RegCreateKeyExA failed: %ld\n", rc);
778 BYTE buf[sizeof(struct CertPropIDHeader) * 2 + sizeof(hash) +
779 sizeof(bigCert) - 1], *ptr;
781 struct CertPropIDHeader *hdr;
783 hdr = (struct CertPropIDHeader *)buf;
784 hdr->propID = CERT_HASH_PROP_ID;
786 hdr->cb = sizeof(hash);
787 ptr = buf + sizeof(*hdr);
788 memcpy(ptr, hash, sizeof(hash));
790 hdr = (struct CertPropIDHeader *)ptr;
791 hdr->propID = CERT_CERT_PROP_ID;
793 hdr->cb = sizeof(bigCert) - 1;
795 memcpy(ptr, bigCert, sizeof(bigCert) - 1);
797 rc = RegSetValueExA(subKey, "Blob", 0, REG_BINARY, buf,
799 ok(!rc, "RegSetValueExA failed: %ld\n", rc);
801 ret = CertControlStore(store, 0, CERT_STORE_CTRL_RESYNC, NULL);
802 ok(ret, "CertControlStore failed: %08lx\n", GetLastError());
804 /* Make sure the bogus hash cert gets loaded. */
808 context = CertEnumCertificatesInStore(store, context);
811 } while (context != NULL);
812 ok(certCount == 1, "Expected 1 certificates, got %ld\n", certCount);
817 /* Add another serialized cert directly to the registry, this time
818 * under the correct key name (named with the correct hash value).
821 ret = CryptHashCertificate(0, 0, 0, bigCert2,
822 sizeof(bigCert2) - 1, hash, &size);
823 ok(ret, "CryptHashCertificate failed: %ld\n", GetLastError());
824 strcpy(subKeyName, certificates);
825 for (i = 0, ptr = subKeyName + sizeof(certificates) - 1;
826 i < sizeof(hash); i++, ptr += 2)
827 sprintf(ptr, "%02X", hash[i]);
828 rc = RegCreateKeyExA(key, subKeyName, 0, NULL, 0, KEY_ALL_ACCESS, NULL,
830 ok(!rc, "RegCreateKeyExA failed: %ld\n", rc);
833 BYTE buf[sizeof(struct CertPropIDHeader) * 2 + sizeof(hash) +
834 sizeof(bigCert2) - 1], *ptr;
836 PCCERT_CONTEXT context;
837 struct CertPropIDHeader *hdr;
839 /* First try with a bogus hash... */
840 hdr = (struct CertPropIDHeader *)buf;
841 hdr->propID = CERT_HASH_PROP_ID;
843 hdr->cb = sizeof(hash);
844 ptr = buf + sizeof(*hdr);
845 memset(ptr, 0, sizeof(hash));
847 hdr = (struct CertPropIDHeader *)ptr;
848 hdr->propID = CERT_CERT_PROP_ID;
850 hdr->cb = sizeof(bigCert2) - 1;
852 memcpy(ptr, bigCert2, sizeof(bigCert2) - 1);
854 rc = RegSetValueExA(subKey, "Blob", 0, REG_BINARY, buf,
856 ok(!rc, "RegSetValueExA failed: %ld\n", rc);
858 ret = CertControlStore(store, 0, CERT_STORE_CTRL_RESYNC, NULL);
859 ok(ret, "CertControlStore failed: %08lx\n", GetLastError());
861 /* and make sure just one cert still gets loaded. */
865 context = CertEnumCertificatesInStore(store, context);
868 } while (context != NULL);
869 ok(certCount == 1, "Expected 1 certificates, got %ld\n", certCount);
871 /* Try again with the correct hash... */
872 ptr = buf + sizeof(*hdr);
873 memcpy(ptr, hash, sizeof(hash));
875 rc = RegSetValueExA(subKey, "Blob", 0, REG_BINARY, buf,
877 ok(!rc, "RegSetValueExA failed: %ld\n", rc);
879 ret = CertControlStore(store, 0, CERT_STORE_CTRL_RESYNC, NULL);
880 ok(ret, "CertControlStore failed: %08lx\n", GetLastError());
882 /* and make sure two certs get loaded. */
886 context = CertEnumCertificatesInStore(store, context);
889 } while (context != NULL);
890 ok(certCount == 2, "Expected 2 certificates, got %ld\n", certCount);
894 CertCloseStore(store, 0);
895 /* Is delete allowed on a reg store? */
896 store = CertOpenStore(CERT_STORE_PROV_REG, 0, 0,
897 CERT_STORE_DELETE_FLAG, key);
898 ok(store == NULL, "Expected NULL return from CERT_STORE_DELETE_FLAG\n");
899 ok(GetLastError() == 0, "CertOpenStore failed: %08lx\n",
904 /* The CertOpenStore with CERT_STORE_DELETE_FLAG above will delete the
905 * contents of the key, but not the key itself.
907 rc = RegCreateKeyExA(HKEY_CURRENT_USER, tempKey, 0, NULL, 0, KEY_ALL_ACCESS,
909 ok(!rc, "RegCreateKeyExA failed: %ld\n", rc);
910 ok(disp == REG_OPENED_EXISTING_KEY,
911 "Expected REG_OPENED_EXISTING_KEY, got %ld\n", disp);
915 rc = RegDeleteKeyA(HKEY_CURRENT_USER, tempKey);
918 HMODULE shlwapi = LoadLibraryA("shlwapi");
920 /* Use shlwapi's SHDeleteKeyA to _really_ blow away the key,
921 * otherwise subsequent tests will fail.
925 SHDeleteKeyAFunc pSHDeleteKeyA =
926 (SHDeleteKeyAFunc)GetProcAddress(shlwapi, "SHDeleteKeyA");
929 pSHDeleteKeyA(HKEY_CURRENT_USER, tempKey);
930 FreeLibrary(shlwapi);
936 static const char MyA[] = { 'M','y',0,0 };
937 static const WCHAR MyW[] = { 'M','y',0 };
938 static const WCHAR BogusW[] = { 'B','o','g','u','s',0 };
939 static const WCHAR BogusPathW[] = { 'S','o','f','t','w','a','r','e','\\',
940 'M','i','c','r','o','s','o','f','t','\\','S','y','s','t','e','m','C','e','r',
941 't','i','f','i','c','a','t','e','s','\\','B','o','g','u','s',0 };
943 static void testSystemRegStore(void)
945 HCERTSTORE store, memStore;
947 /* Check with a UNICODE name */
948 store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0,
949 CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_OPEN_EXISTING_FLAG, MyW);
950 /* Not all OSes support CERT_STORE_PROV_SYSTEM_REGISTRY, so don't continue
951 * testing if they don't.
956 /* Check that it isn't a collection store */
957 memStore = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
958 CERT_STORE_CREATE_NEW_FLAG, NULL);
961 BOOL ret = CertAddStoreToCollection(store, memStore, 0, 0);
963 ok(!ret && GetLastError() ==
964 HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
965 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
967 CertCloseStore(memStore, 0);
969 CertCloseStore(store, 0);
971 /* Check opening a bogus store */
972 store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0,
973 CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_OPEN_EXISTING_FLAG, BogusW);
974 ok(!store && GetLastError() == ERROR_FILE_NOT_FOUND,
975 "Expected ERROR_FILE_NOT_FOUND, got %08lx\n", GetLastError());
976 store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0,
977 CERT_SYSTEM_STORE_CURRENT_USER, BogusW);
978 ok(store != 0, "CertOpenStore failed: %08lx\n", GetLastError());
980 CertCloseStore(store, 0);
981 /* Now check whether deleting is allowed */
982 store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0,
983 CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_DELETE_FLAG, BogusW);
984 RegDeleteKeyW(HKEY_CURRENT_USER, BogusPathW);
986 store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0, 0, NULL);
987 ok(!store && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
988 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
990 store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0,
991 CERT_SYSTEM_STORE_LOCAL_MACHINE | CERT_SYSTEM_STORE_CURRENT_USER, MyA);
992 ok(!store && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
993 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
995 store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0,
996 CERT_SYSTEM_STORE_LOCAL_MACHINE | CERT_SYSTEM_STORE_CURRENT_USER, MyW);
997 ok(!store && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
998 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
1000 /* The name is expected to be UNICODE, check with an ASCII name */
1001 store = CertOpenStore(CERT_STORE_PROV_SYSTEM_REGISTRY, 0, 0,
1002 CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_OPEN_EXISTING_FLAG, MyA);
1003 ok(!store && GetLastError() == ERROR_FILE_NOT_FOUND,
1004 "Expected ERROR_FILE_NOT_FOUND, got %08lx\n", GetLastError());
1007 static void testSystemStore(void)
1009 static const WCHAR baskslashW[] = { '\\',0 };
1011 WCHAR keyName[MAX_PATH];
1015 store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0, 0, NULL);
1016 ok(!store && GetLastError() == ERROR_FILE_NOT_FOUND,
1017 "Expected ERROR_FILE_NOT_FOUND, got %08lx\n", GetLastError());
1018 store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
1019 CERT_SYSTEM_STORE_LOCAL_MACHINE | CERT_SYSTEM_STORE_CURRENT_USER, MyA);
1020 ok(!store && GetLastError() == ERROR_FILE_NOT_FOUND,
1021 "Expected ERROR_FILE_NOT_FOUND, got %08lx\n", GetLastError());
1022 store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
1023 CERT_SYSTEM_STORE_LOCAL_MACHINE | CERT_SYSTEM_STORE_CURRENT_USER, MyW);
1024 ok(!store && GetLastError() == ERROR_FILE_NOT_FOUND,
1025 "Expected ERROR_FILE_NOT_FOUND, got %08lx\n", GetLastError());
1026 /* The name is expected to be UNICODE, first check with an ASCII name */
1027 store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
1028 CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_OPEN_EXISTING_FLAG, MyA);
1029 ok(!store && GetLastError() == ERROR_FILE_NOT_FOUND,
1030 "Expected ERROR_FILE_NOT_FOUND, got %08lx\n", GetLastError());
1031 /* Create the expected key */
1032 lstrcpyW(keyName, CERT_LOCAL_MACHINE_SYSTEM_STORE_REGPATH);
1033 lstrcatW(keyName, baskslashW);
1034 lstrcatW(keyName, MyW);
1035 rc = RegCreateKeyExW(HKEY_CURRENT_USER, keyName, 0, NULL, 0, KEY_READ,
1037 ok(!rc, "RegCreateKeyEx failed: %ld\n", rc);
1040 /* Check opening with a UNICODE name, specifying the create new flag */
1041 store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
1042 CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_CREATE_NEW_FLAG, MyW);
1043 ok(!store && GetLastError() == ERROR_FILE_EXISTS,
1044 "Expected ERROR_FILE_EXISTS, got %08lx\n", GetLastError());
1045 /* Now check opening with a UNICODE name, this time opening existing */
1046 store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
1047 CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_OPEN_EXISTING_FLAG, MyW);
1048 ok(store != 0, "CertOpenStore failed: %08lx\n", GetLastError());
1051 HCERTSTORE memStore = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
1052 CERT_STORE_CREATE_NEW_FLAG, NULL);
1054 /* Check that it's a collection store */
1057 BOOL ret = CertAddStoreToCollection(store, memStore, 0, 0);
1059 /* FIXME: this'll fail on NT4, but what error will it give? */
1060 ok(ret, "CertAddStoreToCollection failed: %08lx\n", GetLastError());
1061 CertCloseStore(memStore, 0);
1063 CertCloseStore(store, 0);
1066 /* Check opening a bogus store */
1067 store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
1068 CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_OPEN_EXISTING_FLAG, BogusW);
1069 ok(!store && GetLastError() == ERROR_FILE_NOT_FOUND,
1070 "Expected ERROR_FILE_NOT_FOUND, got %08lx\n", GetLastError());
1071 store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
1072 CERT_SYSTEM_STORE_CURRENT_USER, BogusW);
1073 ok(store != 0, "CertOpenStore failed: %08lx\n", GetLastError());
1075 CertCloseStore(store, 0);
1076 /* Now check whether deleting is allowed */
1077 store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
1078 CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_DELETE_FLAG, BogusW);
1079 RegDeleteKeyW(HKEY_CURRENT_USER, BogusPathW);
1082 static void testCertOpenSystemStore(void)
1086 store = CertOpenSystemStoreW(0, NULL);
1087 ok(!store && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
1088 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
1090 /* This succeeds, and on WinXP at least, the Bogus key is created under
1091 * HKCU (but not under HKLM, even when run as an administrator.)
1093 store = CertOpenSystemStoreW(0, BogusW);
1094 ok(store != 0, "CertOpenSystemStore failed: %08lx\n", GetLastError());
1096 CertCloseStore(store, 0);
1097 /* Delete it so other tests succeed next time around */
1098 store = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
1099 CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_DELETE_FLAG, BogusW);
1100 RegDeleteKeyW(HKEY_CURRENT_USER, BogusPathW);
1103 static void testCertProperties(void)
1105 PCCERT_CONTEXT context = CertCreateCertificateContext(X509_ASN_ENCODING,
1106 bigCert, sizeof(bigCert) - 1);
1108 ok(context != NULL, "CertCreateCertificateContext failed: %08lx\n",
1112 DWORD propID, numProps, access, size;
1114 BYTE hash[20] = { 0 }, hashProperty[20];
1115 CRYPT_DATA_BLOB blob;
1118 propID = CertEnumCertificateContextProperties(NULL, 0);
1124 propID = CertEnumCertificateContextProperties(context, propID);
1127 } while (propID != 0);
1128 ok(numProps == 0, "Expected 0 properties, got %ld\n", numProps);
1130 /* Tests with a NULL cert context. Prop ID 0 fails.. */
1131 ret = CertSetCertificateContextProperty(NULL, 0, 0, NULL);
1132 ok(!ret && GetLastError() ==
1133 HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
1134 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
1136 /* while this just crashes.
1137 ret = CertSetCertificateContextProperty(NULL,
1138 CERT_KEY_PROV_HANDLE_PROP_ID, 0, NULL);
1141 ret = CertSetCertificateContextProperty(context, 0, 0, NULL);
1142 ok(!ret && GetLastError() ==
1143 HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
1144 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
1146 /* Can't set the cert property directly, this crashes.
1147 ret = CertSetCertificateContextProperty(context,
1148 CERT_CERT_PROP_ID, 0, bigCert2);
1152 ret = CertGetCertificateContextProperty(context,
1153 CERT_ACCESS_STATE_PROP_ID, 0, NULL);
1155 size = sizeof(access);
1156 ret = CertGetCertificateContextProperty(context,
1157 CERT_ACCESS_STATE_PROP_ID, &access, &size);
1158 ok(ret, "CertGetCertificateContextProperty failed: %08lx\n",
1160 ok(!(access & CERT_ACCESS_STATE_WRITE_PERSIST_FLAG),
1161 "Didn't expect a persisted cert\n");
1162 /* Trying to set this "read only" property crashes.
1163 access |= CERT_ACCESS_STATE_WRITE_PERSIST_FLAG;
1164 ret = CertSetCertificateContextProperty(context,
1165 CERT_ACCESS_STATE_PROP_ID, 0, &access);
1168 /* Can I set the hash to an invalid hash? */
1170 blob.cbData = sizeof(hash);
1171 ret = CertSetCertificateContextProperty(context, CERT_HASH_PROP_ID, 0,
1173 ok(ret, "CertSetCertificateContextProperty failed: %08lx\n",
1175 size = sizeof(hashProperty);
1176 ret = CertGetCertificateContextProperty(context, CERT_HASH_PROP_ID,
1177 hashProperty, &size);
1178 ok(!memcmp(hashProperty, hash, sizeof(hash)), "Unexpected hash\n");
1179 /* Delete the (bogus) hash, and get the real one */
1180 ret = CertSetCertificateContextProperty(context, CERT_HASH_PROP_ID, 0,
1182 ok(ret, "CertSetCertificateContextProperty failed: %08lx\n",
1184 size = sizeof(hash);
1185 ret = CryptHashCertificate(0, 0, 0, bigCert, sizeof(bigCert) - 1,
1187 ok(ret, "CryptHashCertificate failed: %08lx\n", GetLastError());
1188 ret = CertGetCertificateContextProperty(context, CERT_HASH_PROP_ID,
1189 hashProperty, &size);
1190 ok(ret, "CertGetCertificateContextProperty failed: %08lx\n",
1192 ok(!memcmp(hash, hashProperty, sizeof(hash)), "Unexpected hash\n");
1194 /* Now that the hash property is set, we should get one property when
1200 propID = CertEnumCertificateContextProperties(context, propID);
1203 } while (propID != 0);
1204 ok(numProps == 1, "Expected 1 properties, got %ld\n", numProps);
1206 CertFreeCertificateContext(context);
1210 static void testAddSerialized(void)
1214 BYTE buf[sizeof(struct CertPropIDHeader) * 2 + 20 + sizeof(bigCert) - 1] =
1217 struct CertPropIDHeader *hdr;
1218 PCCERT_CONTEXT context;
1220 ret = CertAddSerializedElementToStore(0, NULL, 0, 0, 0, 0, NULL, NULL);
1221 ok(!ret && GetLastError() == ERROR_END_OF_MEDIA,
1222 "Expected ERROR_END_OF_MEDIA, got %08lx\n", GetLastError());
1224 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
1225 CERT_STORE_CREATE_NEW_FLAG, NULL);
1226 ok(store != 0, "CertOpenStore failed: %08lx\n", GetLastError());
1228 ret = CertAddSerializedElementToStore(store, NULL, 0, 0, 0, 0, NULL, NULL);
1229 ok(!ret && GetLastError() == ERROR_END_OF_MEDIA,
1230 "Expected ERROR_END_OF_MEDIA, got %08lx\n", GetLastError());
1232 /* Test with an empty property */
1233 hdr = (struct CertPropIDHeader *)buf;
1234 hdr->propID = CERT_CERT_PROP_ID;
1237 ret = CertAddSerializedElementToStore(store, buf, sizeof(buf), 0, 0, 0,
1239 ok(!ret && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
1240 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
1242 /* Test with a bad size in property header */
1243 hdr->cb = sizeof(bigCert) - 2;
1244 memcpy(buf + sizeof(struct CertPropIDHeader), bigCert, sizeof(bigCert) - 1);
1245 ret = CertAddSerializedElementToStore(store, buf, sizeof(buf), 0, 0, 0,
1247 ok(!ret && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
1248 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
1250 ret = CertAddSerializedElementToStore(store, buf,
1251 sizeof(struct CertPropIDHeader) + sizeof(bigCert) - 1, 0, 0, 0, NULL,
1253 ok(!ret && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
1254 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
1256 ret = CertAddSerializedElementToStore(store, buf,
1257 sizeof(struct CertPropIDHeader) + sizeof(bigCert) - 1, CERT_STORE_ADD_NEW,
1259 ok(!ret && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
1260 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
1262 /* Kosher size in property header, but no context type */
1263 hdr->cb = sizeof(bigCert) - 1;
1264 ret = CertAddSerializedElementToStore(store, buf, sizeof(buf), 0, 0, 0,
1266 ok(!ret && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
1267 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
1269 ret = CertAddSerializedElementToStore(store, buf,
1270 sizeof(struct CertPropIDHeader) + sizeof(bigCert) - 1, 0, 0, 0, NULL,
1272 ok(!ret && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
1273 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
1275 ret = CertAddSerializedElementToStore(store, buf,
1276 sizeof(struct CertPropIDHeader) + sizeof(bigCert) - 1, CERT_STORE_ADD_NEW,
1278 ok(!ret && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
1279 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
1281 /* With a bad context type */
1282 ret = CertAddSerializedElementToStore(store, buf, sizeof(buf), 0, 0,
1283 CERT_STORE_CRL_CONTEXT_FLAG, NULL, NULL);
1284 ok(!ret && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
1285 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
1287 ret = CertAddSerializedElementToStore(store, buf,
1288 sizeof(struct CertPropIDHeader) + sizeof(bigCert) - 1, 0, 0,
1289 CERT_STORE_CRL_CONTEXT_FLAG, NULL, NULL);
1290 ok(!ret && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
1291 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
1293 ret = CertAddSerializedElementToStore(store, buf,
1294 sizeof(struct CertPropIDHeader) + sizeof(bigCert) - 1, CERT_STORE_ADD_NEW,
1295 0, CERT_STORE_CRL_CONTEXT_FLAG, NULL, NULL);
1296 ok(!ret && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
1297 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
1299 /* Bad unknown field, good type */
1301 ret = CertAddSerializedElementToStore(store, buf, sizeof(buf), 0, 0,
1302 CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL);
1303 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
1304 "Expected ERROR_FILE_NOT_FOUND got %08lx\n", GetLastError());
1305 ret = CertAddSerializedElementToStore(store, buf,
1306 sizeof(struct CertPropIDHeader) + sizeof(bigCert) - 1, 0, 0,
1307 CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL);
1308 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
1309 "Expected ERROR_FILE_NOT_FOUND got %08lx\n", GetLastError());
1310 ret = CertAddSerializedElementToStore(store, buf,
1311 sizeof(struct CertPropIDHeader) + sizeof(bigCert) - 1, CERT_STORE_ADD_NEW,
1312 0, CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL);
1313 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
1314 "Expected ERROR_FILE_NOT_FOUND got %08lx\n", GetLastError());
1315 /* Most everything okay, but bad add disposition */
1318 ret = CertAddSerializedElementToStore(store, buf, sizeof(buf), 0, 0,
1319 CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL);
1321 ret = CertAddSerializedElementToStore(store, buf,
1322 sizeof(struct CertPropIDHeader) + sizeof(bigCert) - 1, 0, 0,
1323 CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL);
1325 /* Everything okay, but buffer's too big */
1326 ret = CertAddSerializedElementToStore(store, buf, sizeof(buf),
1327 CERT_STORE_ADD_NEW, 0, CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL);
1328 ok(ret, "CertAddSerializedElementToStore failed: %08lx\n", GetLastError());
1329 /* Everything okay, check it's not re-added */
1330 ret = CertAddSerializedElementToStore(store, buf,
1331 sizeof(struct CertPropIDHeader) + sizeof(bigCert) - 1, CERT_STORE_ADD_NEW,
1332 0, CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL);
1333 ok(!ret && GetLastError() == CRYPT_E_EXISTS,
1334 "Expected CRYPT_E_EXISTS, got %08lx\n", GetLastError());
1336 context = CertEnumCertificatesInStore(store, NULL);
1337 ok(context != NULL, "Expected a cert\n");
1339 CertDeleteCertificateFromStore(context);
1341 /* Try adding with a bogus hash. Oddly enough, it succeeds, and the hash,
1342 * when queried, is the real hash rather than the bogus hash.
1344 hdr = (struct CertPropIDHeader *)(buf + sizeof(struct CertPropIDHeader) +
1345 sizeof(bigCert) - 1);
1346 hdr->propID = CERT_HASH_PROP_ID;
1348 hdr->cb = sizeof(hash);
1349 memset(hash, 0xc, sizeof(hash));
1350 memcpy((LPBYTE)hdr + sizeof(struct CertPropIDHeader), hash, sizeof(hash));
1351 ret = CertAddSerializedElementToStore(store, buf, sizeof(buf),
1352 CERT_STORE_ADD_NEW, 0, CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL,
1353 (const void **)&context);
1354 ok(ret, "CertAddSerializedElementToStore failed: %08lx\n", GetLastError());
1357 BYTE hashVal[20], realHash[20];
1358 DWORD size = sizeof(hashVal);
1360 ret = CryptHashCertificate(0, 0, 0, bigCert, sizeof(bigCert) - 1,
1362 ok(ret, "CryptHashCertificate failed: %08lx\n", GetLastError());
1363 ret = CertGetCertificateContextProperty(context, CERT_HASH_PROP_ID,
1365 ok(ret, "CertGetCertificateContextProperty failed: %08lx\n",
1367 ok(!memcmp(hashVal, realHash, size), "Unexpected hash\n");
1370 CertCloseStore(store, 0);
1373 static const char cspName[] = "WineCryptTemp";
1375 static void verifySig(HCRYPTPROV csp, const BYTE *toSign, size_t toSignLen,
1376 const BYTE *sig, size_t sigLen)
1379 BOOL ret = CryptCreateHash(csp, CALG_SHA1, 0, 0, &hash);
1381 ok(ret, "CryptCreateHash failed: %08lx\n", GetLastError());
1385 DWORD mySigSize = sizeof(mySig);
1387 ret = CryptHashData(hash, toSign, toSignLen, 0);
1388 ok(ret, "CryptHashData failed: %08lx\n", GetLastError());
1389 /* use the A variant so the test can run on Win9x */
1390 ret = CryptSignHashA(hash, AT_SIGNATURE, NULL, 0, mySig, &mySigSize);
1391 ok(ret, "CryptSignHash failed: %08lx\n", GetLastError());
1394 ok(mySigSize == sigLen, "Expected sig length %d, got %ld\n",
1396 ok(!memcmp(mySig, sig, sigLen), "Unexpected signature\n");
1398 CryptDestroyHash(hash);
1402 /* Tests signing the certificate described by toBeSigned with the CSP passed in,
1403 * using the algorithm with OID sigOID. The CSP is assumed to be empty, and a
1404 * keyset named AT_SIGNATURE will be added to it. The signing key will be
1405 * stored in *key, and the signature will be stored in sig. sigLen should be
1406 * at least 64 bytes.
1408 static void testSignCert(HCRYPTPROV csp, const CRYPT_DATA_BLOB *toBeSigned,
1409 LPCSTR sigOID, HCRYPTKEY *key, BYTE *sig, DWORD *sigLen)
1413 CRYPT_ALGORITHM_IDENTIFIER algoID = { NULL, { 0, NULL } };
1416 ret = CryptSignCertificate(0, 0, 0, NULL, 0, NULL, NULL, NULL, NULL);
1417 ret = CryptSignCertificate(0, 0, 0, NULL, 0, NULL, NULL, NULL, &size);
1418 ret = CryptSignCertificate(0, 0, 0, toBeSigned->pbData, toBeSigned->cbData,
1419 NULL, NULL, NULL, &size);
1421 ret = CryptSignCertificate(0, 0, 0, toBeSigned->pbData, toBeSigned->cbData,
1422 &algoID, NULL, NULL, &size);
1423 ok(!ret && GetLastError() == NTE_BAD_ALGID,
1424 "Expected NTE_BAD_ALGID, got %08lx\n", GetLastError());
1425 algoID.pszObjId = (LPSTR)sigOID;
1426 ret = CryptSignCertificate(0, 0, 0, toBeSigned->pbData, toBeSigned->cbData,
1427 &algoID, NULL, NULL, &size);
1428 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1429 "Expected ERROR_INVALID_PARAMETER, got %08lx\n", GetLastError());
1430 ret = CryptSignCertificate(0, AT_SIGNATURE, 0, toBeSigned->pbData,
1431 toBeSigned->cbData, &algoID, NULL, NULL, &size);
1432 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1433 "Expected ERROR_INVALID_PARAMETER, got %08lx\n", GetLastError());
1435 /* No keys exist in the new CSP yet.. */
1436 ret = CryptSignCertificate(csp, AT_SIGNATURE, 0, toBeSigned->pbData,
1437 toBeSigned->cbData, &algoID, NULL, NULL, &size);
1438 ok(!ret && (GetLastError() == NTE_BAD_KEYSET || GetLastError() ==
1439 NTE_NO_KEY), "Expected NTE_BAD_KEYSET or NTE_NO_KEY, got %08lx\n",
1441 ret = CryptGenKey(csp, AT_SIGNATURE, 0, key);
1442 ok(ret, "CryptGenKey failed: %08lx\n", GetLastError());
1445 ret = CryptSignCertificate(csp, AT_SIGNATURE, 0, toBeSigned->pbData,
1446 toBeSigned->cbData, &algoID, NULL, NULL, &size);
1447 ok(ret, "CryptSignCertificate failed: %08lx\n", GetLastError());
1448 ok(size <= *sigLen, "Expected size <= %ld, got %ld\n", *sigLen, size);
1451 ret = CryptSignCertificate(csp, AT_SIGNATURE, 0, toBeSigned->pbData,
1452 toBeSigned->cbData, &algoID, NULL, sig, &size);
1453 ok(ret, "CryptSignCertificate failed: %08lx\n", GetLastError());
1457 verifySig(csp, toBeSigned->pbData, toBeSigned->cbData, sig,
1464 static void testVerifyCertSig(HCRYPTPROV csp, const CRYPT_DATA_BLOB *toBeSigned,
1465 LPCSTR sigOID, const BYTE *sig, DWORD sigLen)
1467 CERT_SIGNED_CONTENT_INFO info;
1472 ret = pCryptVerifyCertificateSignatureEx(0, 0, 0, NULL, 0, NULL, 0, NULL);
1473 ok(!ret && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
1474 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
1476 ret = pCryptVerifyCertificateSignatureEx(csp, 0, 0, NULL, 0, NULL, 0, NULL);
1477 ok(!ret && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
1478 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
1480 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING, 0, NULL, 0,
1482 ok(!ret && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
1483 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
1486 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
1487 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, NULL, 0, NULL, 0, NULL);
1489 info.ToBeSigned.cbData = toBeSigned->cbData;
1490 info.ToBeSigned.pbData = toBeSigned->pbData;
1491 info.SignatureAlgorithm.pszObjId = (LPSTR)sigOID;
1492 info.SignatureAlgorithm.Parameters.cbData = 0;
1493 info.Signature.cbData = sigLen;
1494 info.Signature.pbData = (BYTE *)sig;
1495 info.Signature.cUnusedBits = 0;
1496 ret = CryptEncodeObjectEx(X509_ASN_ENCODING, X509_CERT, &info,
1497 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&cert, &size);
1498 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
1501 CRYPT_DATA_BLOB certBlob = { 0, NULL };
1502 PCERT_PUBLIC_KEY_INFO pubKeyInfo = NULL;
1504 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
1505 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob, 0, NULL, 0, NULL);
1506 ok(!ret && GetLastError() == CRYPT_E_ASN1_EOD,
1507 "Expected CRYPT_E_ASN1_EOD, got %08lx\n", GetLastError());
1508 certBlob.cbData = 1;
1509 certBlob.pbData = (void *)0xdeadbeef;
1510 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
1511 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob, 0, NULL, 0, NULL);
1512 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
1513 "Expected STATUS_ACCESS_VIOLATION, got %08lx\n", GetLastError());
1514 certBlob.cbData = size;
1515 certBlob.pbData = cert;
1516 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
1517 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob, 0, NULL, 0, NULL);
1518 ok(!ret && GetLastError() ==
1519 HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
1520 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
1522 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
1523 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob,
1524 CRYPT_VERIFY_CERT_SIGN_ISSUER_NULL, NULL, 0, NULL);
1525 ok(!ret && GetLastError() ==
1526 HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
1527 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
1530 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
1531 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob,
1532 CRYPT_VERIFY_CERT_SIGN_ISSUER_PUBKEY, NULL, 0, NULL);
1534 CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING,
1535 (LPSTR)sigOID, 0, NULL, NULL, &size);
1536 pubKeyInfo = HeapAlloc(GetProcessHeap(), 0, size);
1539 ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE,
1540 X509_ASN_ENCODING, (LPSTR)sigOID, 0, NULL, pubKeyInfo, &size);
1541 ok(ret, "CryptExportKey failed: %08lx\n", GetLastError());
1544 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
1545 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob,
1546 CRYPT_VERIFY_CERT_SIGN_ISSUER_PUBKEY, pubKeyInfo, 0, NULL);
1547 ok(ret, "CryptVerifyCertificateSignatureEx failed: %08lx\n",
1550 HeapFree(GetProcessHeap(), 0, pubKeyInfo);
1556 static void testCertSigs(void)
1559 CRYPT_DATA_BLOB toBeSigned = { sizeof(emptyCert), (LPBYTE)emptyCert };
1563 DWORD sigSize = sizeof(sig);
1565 /* Just in case a previous run failed, delete this thing */
1566 CryptAcquireContextA(&csp, cspName, MS_DEF_PROV, PROV_RSA_FULL,
1567 CRYPT_DELETEKEYSET);
1568 ret = CryptAcquireContextA(&csp, cspName, MS_DEF_PROV, PROV_RSA_FULL,
1570 ok(ret, "CryptAcquireContext failed: %08lx\n", GetLastError());
1572 testSignCert(csp, &toBeSigned, szOID_RSA_SHA1RSA, &key, sig, &sigSize);
1573 testVerifyCertSig(csp, &toBeSigned, szOID_RSA_SHA1RSA, sig, sigSize);
1575 CryptDestroyKey(key);
1576 CryptReleaseContext(csp, 0);
1577 ret = CryptAcquireContextA(&csp, cspName, MS_DEF_PROV, PROV_RSA_FULL,
1578 CRYPT_DELETEKEYSET);
1583 init_function_pointers();
1585 testCryptHashCert();
1587 /* various combinations of CertOpenStore */
1589 testCollectionStore();
1591 testSystemRegStore();
1594 testCertOpenSystemStore();
1596 testCertProperties();
1597 testAddSerialized();