2 * crypt32 cert functions tests
4 * Copyright 2005-2006 Juan Lang
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
30 #include "wine/test.h"
32 static BOOL (WINAPI * pCryptVerifyCertificateSignatureEx)
33 (HCRYPTPROV, DWORD, DWORD, void *, DWORD, void *, DWORD, void *);
35 #define CRYPT_GET_PROC(func) \
36 p ## func = (void *)GetProcAddress(hCrypt32, #func); \
38 trace("GetProcAddress(hCrypt32, \"%s\") failed\n", #func); \
40 static void init_function_pointers(void)
44 pCryptVerifyCertificateSignatureEx = NULL;
46 hCrypt32 = GetModuleHandleA("crypt32.dll");
49 CRYPT_GET_PROC(CryptVerifyCertificateSignatureEx);
52 static const BYTE subjectName[] = { 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06,
53 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61,
55 static const BYTE serialNum[] = { 1 };
56 static const BYTE bigCert[] = { 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
57 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
58 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22,
59 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30,
60 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30,
61 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30,
62 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20,
63 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01,
64 0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01,
65 0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
66 static const BYTE bigCertHash[] = { 0x6e, 0x30, 0x90, 0x71, 0x5f, 0xd9, 0x23,
67 0x56, 0xeb, 0xae, 0x25, 0x40, 0xe6, 0x22, 0xda, 0x19, 0x26, 0x02, 0xa6, 0x08 };
69 static const BYTE bigCertWithDifferentSubject[] = { 0x30, 0x7a, 0x02, 0x01, 0x02,
70 0x30, 0x02, 0x06, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55,
71 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67,
72 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31,
73 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31,
74 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15,
75 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x41, 0x6c,
76 0x65, 0x78, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06,
77 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55,
78 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02,
80 static const BYTE bigCertWithDifferentIssuer[] = { 0x30, 0x7a, 0x02, 0x01,
81 0x01, 0x30, 0x02, 0x06, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03,
82 0x55, 0x04, 0x03, 0x13, 0x0a, 0x41, 0x6c, 0x65, 0x78, 0x20, 0x4c, 0x61, 0x6e,
83 0x67, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30,
84 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30,
85 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30,
86 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a,
87 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02,
88 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03,
89 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff,
92 static const BYTE subjectName2[] = { 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06,
93 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x41, 0x6c, 0x65, 0x78, 0x20, 0x4c, 0x61,
95 static const BYTE bigCert2[] = { 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
96 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
97 0x0a, 0x41, 0x6c, 0x65, 0x78, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22,
98 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30,
99 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30,
100 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30,
101 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x41, 0x6c, 0x65, 0x78, 0x20,
102 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01,
103 0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01,
104 0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
105 static const BYTE bigCert2WithDifferentSerial[] = { 0x30, 0x7a, 0x02, 0x01,
106 0x02, 0x30, 0x02, 0x06, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03,
107 0x55, 0x04, 0x03, 0x13, 0x0a, 0x41, 0x6c, 0x65, 0x78, 0x20, 0x4c, 0x61, 0x6e,
108 0x67, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30,
109 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30,
110 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30,
111 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x41,
112 0x6c, 0x65, 0x78, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02,
113 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03,
114 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff,
116 static const BYTE bigCert2Hash[] = { 0x4a, 0x7f, 0x32, 0x1f, 0xcf, 0x3b, 0xc0,
117 0x87, 0x48, 0x2b, 0xa1, 0x86, 0x54, 0x18, 0xe4, 0x3a, 0x0e, 0x53, 0x7e, 0x2b };
119 static const BYTE certWithUsage[] = { 0x30, 0x81, 0x93, 0x02, 0x01, 0x01, 0x30,
120 0x02, 0x06, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04,
121 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00,
122 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30,
123 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30,
124 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31,
125 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61,
126 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00,
127 0x03, 0x01, 0x00, 0xa3, 0x2f, 0x30, 0x2d, 0x30, 0x2b, 0x06, 0x03, 0x55, 0x1d,
128 0x25, 0x01, 0x01, 0xff, 0x04, 0x21, 0x30, 0x1f, 0x06, 0x08, 0x2b, 0x06, 0x01,
129 0x05, 0x05, 0x07, 0x03, 0x03, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07,
130 0x03, 0x02, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01 };
132 static void testAddCert(void)
136 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
137 CERT_STORE_CREATE_NEW_FLAG, NULL);
138 ok(store != NULL, "CertOpenStore failed: %ld\n", GetLastError());
141 HCERTSTORE collection;
142 PCCERT_CONTEXT context;
145 /* Weird--bad add disposition leads to an access violation in Windows.
147 ret = CertAddEncodedCertificateToStore(0, X509_ASN_ENCODING, bigCert,
148 sizeof(bigCert), 0, NULL);
149 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
150 "Expected STATUS_ACCESS_VIOLATION, got %08lx\n", GetLastError());
151 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
152 bigCert, sizeof(bigCert), 0, NULL);
153 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
154 "Expected STATUS_ACCESS_VIOLATION, got %08lx\n", GetLastError());
156 /* Weird--can add a cert to the NULL store (does this have special
160 ret = CertAddEncodedCertificateToStore(0, X509_ASN_ENCODING, bigCert,
161 sizeof(bigCert), CERT_STORE_ADD_ALWAYS, &context);
162 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n",
165 CertFreeCertificateContext(context);
167 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
168 bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL);
169 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n",
171 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
172 bigCert2, sizeof(bigCert2), CERT_STORE_ADD_NEW, NULL);
173 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n",
175 /* This has the same name as bigCert, so finding isn't done by name */
176 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
177 certWithUsage, sizeof(certWithUsage), CERT_STORE_ADD_NEW, &context);
178 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n",
180 ok(context != NULL, "Expected a context\n");
183 CRYPT_DATA_BLOB hash = { sizeof(bigCert2Hash),
184 (LPBYTE)bigCert2Hash };
186 /* Duplicate (AddRef) the context so we can still use it after
187 * deleting it from the store.
189 CertDuplicateCertificateContext(context);
190 CertDeleteCertificateFromStore(context);
191 /* Set the same hash as bigCert2, and try to readd it */
192 ret = CertSetCertificateContextProperty(context, CERT_HASH_PROP_ID,
194 ok(ret, "CertSetCertificateContextProperty failed: %08lx\n",
196 ret = CertAddCertificateContextToStore(store, context,
197 CERT_STORE_ADD_NEW, NULL);
198 /* The failure is a bit odd (CRYPT_E_ASN1_BADTAG), so just check
201 ok(!ret, "Expected failure\n");
202 CertFreeCertificateContext(context);
204 context = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert2,
206 ok(context != NULL, "Expected a context\n");
209 /* Try to readd bigCert2 to the store */
210 ret = CertAddCertificateContextToStore(store, context,
211 CERT_STORE_ADD_NEW, NULL);
212 ok(!ret && GetLastError() == CRYPT_E_EXISTS,
213 "Expected CRYPT_E_EXISTS, got %08lx\n", GetLastError());
214 CertFreeCertificateContext(context);
217 /* Adding a cert with the same issuer name and serial number (but
218 * different subject) as an existing cert succeeds.
221 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
222 bigCert2WithDifferentSerial, sizeof(bigCert2WithDifferentSerial),
223 CERT_STORE_ADD_NEW, &context);
224 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n",
227 CertDeleteCertificateFromStore(context);
229 /* Adding a cert with the same subject name and serial number (but
230 * different issuer) as an existing cert succeeds.
233 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
234 bigCertWithDifferentSubject, sizeof(bigCertWithDifferentSubject),
235 CERT_STORE_ADD_NEW, &context);
236 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n",
239 CertDeleteCertificateFromStore(context);
241 /* Adding a cert with the same issuer name and serial number (but
242 * different otherwise) as an existing cert succeeds.
245 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
246 bigCertWithDifferentIssuer, sizeof(bigCertWithDifferentIssuer),
247 CERT_STORE_ADD_NEW, &context);
248 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n",
251 CertDeleteCertificateFromStore(context);
253 collection = CertOpenStore(CERT_STORE_PROV_COLLECTION, 0, 0,
254 CERT_STORE_CREATE_NEW_FLAG, NULL);
255 ok(collection != NULL, "CertOpenStore failed: %08lx\n", GetLastError());
258 /* Add store to the collection, but disable updates */
259 CertAddStoreToCollection(collection, store, 0, 0);
261 context = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert2,
263 ok(context != NULL, "Expected a context\n");
266 /* Try to readd bigCert2 to the collection */
267 ret = CertAddCertificateContextToStore(collection, context,
268 CERT_STORE_ADD_NEW, NULL);
269 ok(!ret && GetLastError() == CRYPT_E_EXISTS,
270 "Expected CRYPT_E_EXISTS, got %08lx\n", GetLastError());
271 /* Replacing an existing certificate context is allowed, even
272 * though updates to the collection aren't..
274 ret = CertAddCertificateContextToStore(collection, context,
275 CERT_STORE_ADD_REPLACE_EXISTING, NULL);
276 ok(ret, "CertAddCertificateContextToStore failed: %08lx\n",
278 /* but adding a new certificate isn't allowed. */
279 ret = CertAddCertificateContextToStore(collection, context,
280 CERT_STORE_ADD_ALWAYS, NULL);
281 ok(!ret && GetLastError() == E_ACCESSDENIED,
282 "Expected E_ACCESSDENIED, got %08lx\n", GetLastError());
283 CertFreeCertificateContext(context);
286 CertCloseStore(collection, 0);
289 CertCloseStore(store, 0);
293 static void checkHash(const BYTE *data, DWORD dataLen, ALG_ID algID,
294 PCCERT_CONTEXT context, DWORD propID)
296 BYTE hash[20] = { 0 }, hashProperty[20];
300 memset(hash, 0, sizeof(hash));
301 memset(hashProperty, 0, sizeof(hashProperty));
303 ret = CryptHashCertificate(0, algID, 0, data, dataLen, hash, &size);
304 ok(ret, "CryptHashCertificate failed: %08lx\n", GetLastError());
305 ret = CertGetCertificateContextProperty(context, propID, hashProperty,
307 ok(ret, "CertGetCertificateContextProperty failed: %08lx\n",
309 ok(!memcmp(hash, hashProperty, size), "Unexpected hash for property %ld\n",
313 static const WCHAR cspNameW[] = { 'W','i','n','e','C','r','y','p','t','T','e',
316 static void testCertProperties(void)
318 PCCERT_CONTEXT context = CertCreateCertificateContext(X509_ASN_ENCODING,
319 bigCert, sizeof(bigCert));
321 ok(context != NULL, "CertCreateCertificateContext failed: %08lx\n",
325 DWORD propID, numProps, access, size;
327 BYTE hash[20] = { 0 }, hashProperty[20];
328 CRYPT_DATA_BLOB blob;
329 CERT_KEY_CONTEXT keyContext;
333 propID = CertEnumCertificateContextProperties(NULL, 0);
339 propID = CertEnumCertificateContextProperties(context, propID);
342 } while (propID != 0);
343 ok(numProps == 0, "Expected 0 properties, got %ld\n", numProps);
345 /* Tests with a NULL cert context. Prop ID 0 fails.. */
346 ret = CertSetCertificateContextProperty(NULL, 0, 0, NULL);
347 ok(!ret && GetLastError() == E_INVALIDARG,
348 "Expected E_INVALIDARG, got %08lx\n", GetLastError());
349 /* while this just crashes.
350 ret = CertSetCertificateContextProperty(NULL,
351 CERT_KEY_PROV_HANDLE_PROP_ID, 0, NULL);
354 ret = CertSetCertificateContextProperty(context, 0, 0, NULL);
355 ok(!ret && GetLastError() == E_INVALIDARG,
356 "Expected E_INVALIDARG, got %08lx\n", GetLastError());
357 /* Can't set the cert property directly, this crashes.
358 ret = CertSetCertificateContextProperty(context,
359 CERT_CERT_PROP_ID, 0, bigCert2);
363 ret = CertGetCertificateContextProperty(context,
364 CERT_ACCESS_STATE_PROP_ID, 0, NULL);
365 ret = CertGetCertificateContextProperty(context, CERT_HASH_PROP_ID,
367 ret = CertGetCertificateContextProperty(context, CERT_HASH_PROP_ID,
372 ret = CertGetCertificateContextProperty(context,
373 CERT_KEY_PROV_INFO_PROP_ID, NULL, &size);
374 ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
375 "Expected CRYPT_E_NOT_FOUND, got %08lx\n", GetLastError());
376 /* And, an implicit property */
377 size = sizeof(access);
378 ret = CertGetCertificateContextProperty(context,
379 CERT_ACCESS_STATE_PROP_ID, &access, &size);
380 ok(ret, "CertGetCertificateContextProperty failed: %08lx\n",
382 ok(!(access & CERT_ACCESS_STATE_WRITE_PERSIST_FLAG),
383 "Didn't expect a persisted cert\n");
384 /* Trying to set this "read only" property crashes.
385 access |= CERT_ACCESS_STATE_WRITE_PERSIST_FLAG;
386 ret = CertSetCertificateContextProperty(context,
387 CERT_ACCESS_STATE_PROP_ID, 0, &access);
390 /* Can I set the hash to an invalid hash? */
392 blob.cbData = sizeof(hash);
393 ret = CertSetCertificateContextProperty(context, CERT_HASH_PROP_ID, 0,
395 ok(ret, "CertSetCertificateContextProperty failed: %08lx\n",
397 size = sizeof(hashProperty);
398 ret = CertGetCertificateContextProperty(context, CERT_HASH_PROP_ID,
399 hashProperty, &size);
400 ok(!memcmp(hashProperty, hash, sizeof(hash)), "Unexpected hash\n");
401 /* Delete the (bogus) hash, and get the real one */
402 ret = CertSetCertificateContextProperty(context, CERT_HASH_PROP_ID, 0,
404 ok(ret, "CertSetCertificateContextProperty failed: %08lx\n",
406 checkHash(bigCert, sizeof(bigCert), CALG_SHA1, context,
409 /* Now that the hash property is set, we should get one property when
415 propID = CertEnumCertificateContextProperties(context, propID);
418 } while (propID != 0);
419 ok(numProps == 1, "Expected 1 properties, got %ld\n", numProps);
421 /* Check a few other implicit properties */
422 checkHash(bigCert, sizeof(bigCert), CALG_MD5, context,
423 CERT_MD5_HASH_PROP_ID);
425 context->pCertInfo->Subject.pbData,
426 context->pCertInfo->Subject.cbData,
427 CALG_MD5, context, CERT_SUBJECT_NAME_MD5_HASH_PROP_ID);
429 context->pCertInfo->SubjectPublicKeyInfo.PublicKey.pbData,
430 context->pCertInfo->SubjectPublicKeyInfo.PublicKey.cbData,
431 CALG_MD5, context, CERT_SUBJECT_PUBLIC_KEY_MD5_HASH_PROP_ID);
433 /* Test key identifiers and handles and such */
435 ret = CertGetCertificateContextProperty(context,
436 CERT_KEY_IDENTIFIER_PROP_ID, NULL, &size);
437 ok(!ret && GetLastError() == ERROR_INVALID_DATA,
438 "Expected ERROR_INVALID_DATA, got %08lx\n", GetLastError());
439 size = sizeof(CERT_KEY_CONTEXT);
440 ret = CertGetCertificateContextProperty(context,
441 CERT_KEY_IDENTIFIER_PROP_ID, NULL, &size);
442 ok(!ret && GetLastError() == ERROR_INVALID_DATA,
443 "Expected ERROR_INVALID_DATA, got %08lx\n", GetLastError());
444 ret = CertGetCertificateContextProperty(context,
445 CERT_KEY_IDENTIFIER_PROP_ID, &keyContext, &size);
446 ok(!ret && GetLastError() == ERROR_INVALID_DATA,
447 "Expected ERROR_INVALID_DATA, got %08lx\n", GetLastError());
448 /* Key context with an invalid size */
449 keyContext.cbSize = 0;
450 ret = CertSetCertificateContextProperty(context,
451 CERT_KEY_IDENTIFIER_PROP_ID, 0, &keyContext);
452 ok(ret, "CertSetCertificateContextProperty failed: %08lx\n",
454 size = sizeof(keyContext);
455 ret = CertGetCertificateContextProperty(context,
456 CERT_KEY_IDENTIFIER_PROP_ID, &keyContext, &size);
457 ok(ret, "CertGetCertificateContextProperty failed: %08lx\n",
459 keyContext.cbSize = sizeof(keyContext);
460 keyContext.hCryptProv = 0;
461 keyContext.dwKeySpec = AT_SIGNATURE;
463 ret = CertSetCertificateContextProperty(context,
464 CERT_KEY_IDENTIFIER_PROP_ID, 0, &keyContext);
465 ret = CertSetCertificateContextProperty(context,
466 CERT_KEY_IDENTIFIER_PROP_ID, CERT_STORE_NO_CRYPT_RELEASE_FLAG,
469 ret = CryptAcquireContextW(&csp, cspNameW,
470 MS_DEF_PROV_W, PROV_RSA_FULL, CRYPT_NEWKEYSET);
471 ok(ret, "CryptAcquireContextW failed: %08lx\n", GetLastError());
472 keyContext.hCryptProv = csp;
473 ret = CertSetCertificateContextProperty(context,
474 CERT_KEY_CONTEXT_PROP_ID, 0, &keyContext);
475 ok(ret, "CertSetCertificateContextProperty failed: %08lx\n",
477 /* Now that that's set, the key prov handle property is also gettable.
479 size = sizeof(DWORD);
480 ret = CertGetCertificateContextProperty(context,
481 CERT_KEY_PROV_HANDLE_PROP_ID, &keyContext.hCryptProv, &size);
482 ok(ret, "Expected to get the CERT_KEY_PROV_HANDLE_PROP_ID, got %08lx\n",
484 /* Remove the key prov handle property.. */
485 ret = CertSetCertificateContextProperty(context,
486 CERT_KEY_PROV_HANDLE_PROP_ID, 0, NULL);
487 ok(ret, "CertSetCertificateContextProperty failed: %08lx\n",
489 /* and the key context's CSP is set to NULL. */
490 size = sizeof(keyContext);
491 ret = CertGetCertificateContextProperty(context,
492 CERT_KEY_CONTEXT_PROP_ID, &keyContext, &size);
493 ok(ret, "CertGetCertificateContextProperty failed: %08lx\n",
495 ok(keyContext.hCryptProv == 0, "Expected no hCryptProv\n");
497 CryptReleaseContext(csp, 0);
499 CertFreeCertificateContext(context);
503 static void testDupCert(void)
507 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
508 CERT_STORE_CREATE_NEW_FLAG, NULL);
509 ok(store != NULL, "CertOpenStore failed: %ld\n", GetLastError());
512 PCCERT_CONTEXT context, dupContext;
515 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
516 bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, &context);
517 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n",
519 ok(context != NULL, "Expected a valid cert context\n");
522 ok(context->cbCertEncoded == sizeof(bigCert),
523 "Wrong cert size %ld\n", context->cbCertEncoded);
524 ok(!memcmp(context->pbCertEncoded, bigCert, sizeof(bigCert)),
525 "Unexpected encoded cert in context\n");
526 ok(context->hCertStore == store, "Unexpected store\n");
528 dupContext = CertDuplicateCertificateContext(context);
529 ok(dupContext != NULL, "Expected valid duplicate\n");
530 /* Not only is it a duplicate, it's identical: the address is the
533 ok(dupContext == context, "Expected identical context addresses\n");
534 CertFreeCertificateContext(dupContext);
535 CertFreeCertificateContext(context);
537 CertCloseStore(store, 0);
541 static void testFindCert(void)
545 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
546 CERT_STORE_CREATE_NEW_FLAG, NULL);
547 ok(store != NULL, "CertOpenStore failed: %ld\n", GetLastError());
550 PCCERT_CONTEXT context = NULL;
552 CERT_INFO certInfo = { 0 };
553 CRYPT_HASH_BLOB blob;
555 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
556 bigCert, sizeof(bigCert), CERT_STORE_ADD_NEW, NULL);
557 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n",
559 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
560 bigCert2, sizeof(bigCert2), CERT_STORE_ADD_NEW, NULL);
561 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n",
563 /* This has the same name as bigCert */
564 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
565 certWithUsage, sizeof(certWithUsage), CERT_STORE_ADD_NEW, NULL);
566 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n",
570 context = CertFindCertificateInStore(NULL, 0, 0, 0, NULL, NULL);
573 /* Check first cert's there, by issuer */
574 certInfo.Subject.pbData = (LPBYTE)subjectName;
575 certInfo.Subject.cbData = sizeof(subjectName);
576 certInfo.SerialNumber.pbData = (LPBYTE)serialNum;
577 certInfo.SerialNumber.cbData = sizeof(serialNum);
578 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
579 CERT_FIND_ISSUER_NAME, &certInfo.Subject, NULL);
580 ok(context != NULL, "CertFindCertificateInStore failed: %08lx\n",
584 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
585 CERT_FIND_ISSUER_NAME, &certInfo.Subject, context);
586 ok(context != NULL, "Expected more than one cert\n");
589 context = CertFindCertificateInStore(store, X509_ASN_ENCODING,
590 0, CERT_FIND_ISSUER_NAME, &certInfo.Subject, context);
591 ok(context == NULL, "Expected precisely two certs\n");
595 /* Check second cert's there as well, by subject name */
596 certInfo.Subject.pbData = (LPBYTE)subjectName2;
597 certInfo.Subject.cbData = sizeof(subjectName2);
598 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
599 CERT_FIND_SUBJECT_NAME, &certInfo.Subject, NULL);
600 ok(context != NULL, "CertFindCertificateInStore failed: %08lx\n",
604 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
605 CERT_FIND_ISSUER_NAME, &certInfo.Subject, context);
606 ok(context == NULL, "Expected one cert only\n");
609 /* Strange but true: searching for the subject cert requires you to set
610 * the issuer, not the subject
612 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
613 CERT_FIND_SUBJECT_CERT, &certInfo.Subject, NULL);
614 ok(context == NULL, "Expected no certificate\n");
615 certInfo.Subject.pbData = NULL;
616 certInfo.Subject.cbData = 0;
617 certInfo.Issuer.pbData = (LPBYTE)subjectName2;
618 certInfo.Issuer.cbData = sizeof(subjectName2);
619 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
620 CERT_FIND_SUBJECT_CERT, &certInfo, NULL);
621 ok(context != NULL, "CertFindCertificateInStore failed: %08lx\n",
625 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
626 CERT_FIND_ISSUER_NAME, &certInfo.Subject, context);
627 ok(context == NULL, "Expected one cert only\n");
630 /* The nice thing about hashes, they're unique */
631 blob.pbData = (LPBYTE)bigCertHash;
632 blob.cbData = sizeof(bigCertHash);
633 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
634 CERT_FIND_SHA1_HASH, &blob, NULL);
635 ok(context != NULL, "CertFindCertificateInStore failed: %08lx\n",
639 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
640 CERT_FIND_ISSUER_NAME, &certInfo.Subject, context);
641 ok(context == NULL, "Expected one cert only\n");
644 CertCloseStore(store, 0);
648 static void testGetSubjectCert(void)
652 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
653 CERT_STORE_CREATE_NEW_FLAG, NULL);
654 ok(store != NULL, "CertOpenStore failed: %ld\n", GetLastError());
657 PCCERT_CONTEXT context1, context2;
658 CERT_INFO info = { 0 };
661 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
662 bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL);
663 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n",
665 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
666 bigCert2, sizeof(bigCert2), CERT_STORE_ADD_NEW, &context1);
667 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n",
669 ok(context1 != NULL, "Expected a context\n");
670 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
671 certWithUsage, sizeof(certWithUsage), CERT_STORE_ADD_NEW, NULL);
672 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n",
675 context2 = CertGetSubjectCertificateFromStore(store, X509_ASN_ENCODING,
677 ok(!context2 && GetLastError() == E_INVALIDARG,
678 "Expected E_INVALIDARG, got %08lx\n", GetLastError());
679 context2 = CertGetSubjectCertificateFromStore(store, X509_ASN_ENCODING,
681 ok(!context2 && GetLastError() == CRYPT_E_NOT_FOUND,
682 "Expected CRYPT_E_NOT_FOUND, got %08lx\n", GetLastError());
683 info.SerialNumber.cbData = sizeof(serialNum);
684 info.SerialNumber.pbData = (LPBYTE)serialNum;
685 context2 = CertGetSubjectCertificateFromStore(store, X509_ASN_ENCODING,
687 ok(!context2 && GetLastError() == CRYPT_E_NOT_FOUND,
688 "Expected CRYPT_E_NOT_FOUND, got %08lx\n", GetLastError());
689 info.Issuer.cbData = sizeof(subjectName2);
690 info.Issuer.pbData = (LPBYTE)subjectName2;
691 context2 = CertGetSubjectCertificateFromStore(store, X509_ASN_ENCODING,
694 "CertGetSubjectCertificateFromStore failed: %08lx\n", GetLastError());
695 /* Not only should this find a context, but it should be the same
696 * (same address) as context1.
698 ok(context1 == context2, "Expected identical context addresses\n");
699 CertFreeCertificateContext(context2);
701 CertFreeCertificateContext(context1);
702 CertCloseStore(store, 0);
706 /* This expires in 1970 or so */
707 static const BYTE expiredCert[] = { 0x30, 0x82, 0x01, 0x33, 0x30, 0x81, 0xe2,
708 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0xc4, 0xd7, 0x7f, 0x0e, 0x6f, 0xa6,
709 0x8c, 0xaa, 0x47, 0x47, 0x40, 0xe7, 0xb7, 0x0b, 0x4a, 0x7f, 0x30, 0x09, 0x06,
710 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1d, 0x05, 0x00, 0x30, 0x1f, 0x31, 0x1d, 0x30,
711 0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63, 0x40,
712 0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63,
713 0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x36, 0x39, 0x30, 0x31, 0x30, 0x31, 0x30,
714 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x37, 0x30, 0x30, 0x31, 0x30,
715 0x31, 0x30, 0x36, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x1f, 0x31, 0x1d, 0x30,
716 0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63, 0x40,
717 0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63,
718 0x6f, 0x6d, 0x30, 0x5c, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
719 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x4b, 0x00, 0x30, 0x48, 0x02, 0x41,
720 0x00, 0xa1, 0xaf, 0x4a, 0xea, 0xa7, 0x83, 0x57, 0xc0, 0x37, 0x33, 0x7e, 0x29,
721 0x5e, 0x0d, 0xfc, 0x44, 0x74, 0x3a, 0x1d, 0xc3, 0x1b, 0x1d, 0x96, 0xed, 0x4e,
722 0xf4, 0x1b, 0x98, 0xec, 0x69, 0x1b, 0x04, 0xea, 0x25, 0xcf, 0xb3, 0x2a, 0xf5,
723 0xd9, 0x22, 0xd9, 0x8d, 0x08, 0x39, 0x81, 0xc6, 0xe0, 0x4f, 0x12, 0x37, 0x2a,
724 0x3f, 0x80, 0xa6, 0x6c, 0x67, 0x43, 0x3a, 0xdd, 0x95, 0x0c, 0xbb, 0x2f, 0x6b,
725 0x02, 0x03, 0x01, 0x00, 0x01, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02,
726 0x1d, 0x05, 0x00, 0x03, 0x41, 0x00, 0x8f, 0xa2, 0x5b, 0xd6, 0xdf, 0x34, 0xd0,
727 0xa2, 0xa7, 0x47, 0xf1, 0x13, 0x79, 0xd3, 0xf3, 0x39, 0xbd, 0x4e, 0x2b, 0xa3,
728 0xf4, 0x63, 0x37, 0xac, 0x5a, 0x0c, 0x5e, 0x4d, 0x0d, 0x54, 0x87, 0x4f, 0x31,
729 0xfb, 0xa0, 0xce, 0x8f, 0x9a, 0x2f, 0x4d, 0x48, 0xc6, 0x84, 0x8d, 0xf5, 0x70,
730 0x74, 0x17, 0xa5, 0xf3, 0x66, 0x47, 0x06, 0xd6, 0x64, 0x45, 0xbc, 0x52, 0xef,
731 0x49, 0xe5, 0xf9, 0x65, 0xf3 };
733 /* This expires in 2036 or so */
734 static const BYTE childOfExpired[] = { 0x30, 0x81, 0xcc, 0x30, 0x78, 0xa0,
735 0x03, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86,
736 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x1f, 0x31, 0x1d,
737 0x30, 0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63,
738 0x40, 0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e,
739 0x63, 0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x30, 0x36, 0x30, 0x35, 0x30, 0x35,
740 0x31, 0x37, 0x31, 0x32, 0x34, 0x39, 0x5a, 0x17, 0x0d, 0x33, 0x36, 0x30, 0x35,
741 0x30, 0x35, 0x31, 0x37, 0x31, 0x32, 0x34, 0x39, 0x5a, 0x30, 0x15, 0x31, 0x13,
742 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e,
743 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03,
744 0x01, 0x00, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
745 0x01, 0x05, 0x05, 0x00, 0x03, 0x41, 0x00, 0x20, 0x3b, 0xdb, 0x4d, 0x67, 0x50,
746 0xec, 0x73, 0x9d, 0xf9, 0x85, 0x5d, 0x18, 0xe9, 0xb4, 0x98, 0xe3, 0x31, 0xb7,
747 0x03, 0x0b, 0xc0, 0x39, 0x93, 0x56, 0x81, 0x0a, 0xfc, 0x78, 0xa8, 0x29, 0x42,
748 0x5f, 0x69, 0xfb, 0xbc, 0x5b, 0xf2, 0xa6, 0x2a, 0xbe, 0x91, 0x2c, 0xfc, 0x89,
749 0x69, 0x15, 0x18, 0x58, 0xe5, 0x02, 0x75, 0xf7, 0x2a, 0xb6, 0xa9, 0xfb, 0x47,
750 0x6a, 0x6e, 0x0a, 0x9b, 0xe9, 0xdc };
752 static void testGetIssuerCert(void)
755 PCCERT_CONTEXT parent, child;
756 DWORD flags = 0xffffffff;
757 HCERTSTORE store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
758 CERT_STORE_CREATE_NEW_FLAG, NULL);
760 ok(store != NULL, "CertOpenStore failed: %08lx\n", GetLastError());
762 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
763 expiredCert, sizeof(expiredCert), CERT_STORE_ADD_ALWAYS, NULL);
764 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n",
767 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
768 childOfExpired, sizeof(childOfExpired), CERT_STORE_ADD_ALWAYS, &child);
769 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n",
773 parent = CertGetIssuerCertificateFromStore(NULL, NULL, NULL, NULL);
774 parent = CertGetIssuerCertificateFromStore(store, NULL, NULL, NULL);
776 parent = CertGetIssuerCertificateFromStore(NULL, NULL, NULL, &flags);
777 ok(!parent && GetLastError() == E_INVALIDARG,
778 "Expected E_INVALIDARG, got %08lx\n", GetLastError());
779 parent = CertGetIssuerCertificateFromStore(store, NULL, NULL, &flags);
780 ok(!parent && GetLastError() == E_INVALIDARG,
781 "Expected E_INVALIDARG, got %08lx\n", GetLastError());
782 parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
783 ok(!parent && GetLastError() == E_INVALIDARG,
784 "Expected E_INVALIDARG, got %08lx\n", GetLastError());
785 /* Confusing: the caller cannot set either of the
786 * CERT_STORE_NO_*_FLAGs, as these are not checks,
789 flags = CERT_STORE_NO_CRL_FLAG | CERT_STORE_NO_ISSUER_FLAG;
790 parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
791 ok(!parent && GetLastError() == E_INVALIDARG,
792 "Expected E_INVALIDARG, got %08lx\n", GetLastError());
793 /* Perform no checks */
795 parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
796 ok(parent != NULL, "CertGetIssuerCertificateFromStore failed: %08lx\n",
799 CertFreeCertificateContext(parent);
800 /* Check revocation and signature only */
801 flags = CERT_STORE_REVOCATION_FLAG | CERT_STORE_SIGNATURE_FLAG;
802 parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
803 ok(parent != NULL, "CertGetIssuerCertificateFromStore failed: %08lx\n",
805 /* Confusing: CERT_STORE_REVOCATION_FLAG succeeds when there is no CRL by
806 * setting CERT_STORE_NO_CRL_FLAG.
808 ok(flags == (CERT_STORE_REVOCATION_FLAG | CERT_STORE_NO_CRL_FLAG),
809 "Expected CERT_STORE_REVOCATION_FLAG | CERT_STORE_NO_CRL_FLAG, got %08lx\n",
812 CertFreeCertificateContext(parent);
813 /* Now check just the time */
814 flags = CERT_STORE_TIME_VALIDITY_FLAG;
815 parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
816 ok(parent != NULL, "CertGetIssuerCertificateFromStore failed: %08lx\n",
818 /* Oops: the child is not expired, so the time validity check actually
819 * succeeds, even though the signing cert is expired.
821 ok(!flags, "Expected check to succeed, got %08lx\n", flags);
823 CertFreeCertificateContext(parent);
825 CertFreeCertificateContext(child);
826 CertCloseStore(store, 0);
829 static void testCryptHashCert(void)
831 static const BYTE emptyHash[] = { 0xda, 0x39, 0xa3, 0xee, 0x5e, 0x6b, 0x4b,
832 0x0d, 0x32, 0x55, 0xbf, 0xef, 0x95, 0x60, 0x18, 0x90, 0xaf, 0xd8, 0x07,
834 static const BYTE knownHash[] = { 0xae, 0x9d, 0xbf, 0x6d, 0xf5, 0x46, 0xee,
835 0x8b, 0xc5, 0x7a, 0x13, 0xba, 0xc2, 0xb1, 0x04, 0xf2, 0xbf, 0x52, 0xa8,
837 static const BYTE toHash[] = "abcdefghijklmnopqrstuvwxyz0123456789.,;!?:";
840 DWORD hashLen = sizeof(hash);
842 /* NULL buffer and nonzero length crashes
843 ret = CryptHashCertificate(0, 0, 0, NULL, size, hash, &hashLen);
844 empty hash length also crashes
845 ret = CryptHashCertificate(0, 0, 0, buf, size, hash, NULL);
847 /* Test empty hash */
848 ret = CryptHashCertificate(0, 0, 0, toHash, sizeof(toHash), NULL,
850 ok(ret, "CryptHashCertificate failed: %08lx\n", GetLastError());
851 ok(hashLen == sizeof(hash), "Got unexpected size of hash %ld\n", hashLen);
852 /* Test with empty buffer */
853 ret = CryptHashCertificate(0, 0, 0, NULL, 0, hash, &hashLen);
854 ok(ret, "CryptHashCertificate failed: %08lx\n", GetLastError());
855 ok(!memcmp(hash, emptyHash, sizeof(emptyHash)),
856 "Unexpected hash of nothing\n");
857 /* Test a known value */
858 ret = CryptHashCertificate(0, 0, 0, toHash, sizeof(toHash), hash,
860 ok(ret, "CryptHashCertificate failed: %08lx\n", GetLastError());
861 ok(!memcmp(hash, knownHash, sizeof(knownHash)), "Unexpected hash\n");
864 static void verifySig(HCRYPTPROV csp, const BYTE *toSign, size_t toSignLen,
865 const BYTE *sig, unsigned int sigLen)
868 BOOL ret = CryptCreateHash(csp, CALG_SHA1, 0, 0, &hash);
870 ok(ret, "CryptCreateHash failed: %08lx\n", GetLastError());
874 DWORD mySigSize = sizeof(mySig);
876 ret = CryptHashData(hash, toSign, toSignLen, 0);
877 ok(ret, "CryptHashData failed: %08lx\n", GetLastError());
878 /* use the A variant so the test can run on Win9x */
879 ret = CryptSignHashA(hash, AT_SIGNATURE, NULL, 0, mySig, &mySigSize);
880 ok(ret, "CryptSignHash failed: %08lx\n", GetLastError());
883 ok(mySigSize == sigLen, "Expected sig length %d, got %ld\n",
885 ok(!memcmp(mySig, sig, sigLen), "Unexpected signature\n");
887 CryptDestroyHash(hash);
891 /* Tests signing the certificate described by toBeSigned with the CSP passed in,
892 * using the algorithm with OID sigOID. The CSP is assumed to be empty, and a
893 * keyset named AT_SIGNATURE will be added to it. The signing key will be
894 * stored in *key, and the signature will be stored in sig. sigLen should be
897 static void testSignCert(HCRYPTPROV csp, const CRYPT_DATA_BLOB *toBeSigned,
898 LPCSTR sigOID, HCRYPTKEY *key, BYTE *sig, DWORD *sigLen)
902 CRYPT_ALGORITHM_IDENTIFIER algoID = { NULL, { 0, NULL } };
905 ret = CryptSignCertificate(0, 0, 0, NULL, 0, NULL, NULL, NULL, NULL);
906 ret = CryptSignCertificate(0, 0, 0, NULL, 0, NULL, NULL, NULL, &size);
907 ret = CryptSignCertificate(0, 0, 0, toBeSigned->pbData, toBeSigned->cbData,
908 NULL, NULL, NULL, &size);
910 ret = CryptSignCertificate(0, 0, 0, toBeSigned->pbData, toBeSigned->cbData,
911 &algoID, NULL, NULL, &size);
912 ok(!ret && GetLastError() == NTE_BAD_ALGID,
913 "Expected NTE_BAD_ALGID, got %08lx\n", GetLastError());
914 algoID.pszObjId = (LPSTR)sigOID;
915 ret = CryptSignCertificate(0, 0, 0, toBeSigned->pbData, toBeSigned->cbData,
916 &algoID, NULL, NULL, &size);
917 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
918 "Expected ERROR_INVALID_PARAMETER, got %08lx\n", GetLastError());
919 ret = CryptSignCertificate(0, AT_SIGNATURE, 0, toBeSigned->pbData,
920 toBeSigned->cbData, &algoID, NULL, NULL, &size);
921 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
922 "Expected ERROR_INVALID_PARAMETER, got %08lx\n", GetLastError());
924 /* No keys exist in the new CSP yet.. */
925 ret = CryptSignCertificate(csp, AT_SIGNATURE, 0, toBeSigned->pbData,
926 toBeSigned->cbData, &algoID, NULL, NULL, &size);
927 ok(!ret && (GetLastError() == NTE_BAD_KEYSET || GetLastError() ==
928 NTE_NO_KEY), "Expected NTE_BAD_KEYSET or NTE_NO_KEY, got %08lx\n",
930 ret = CryptGenKey(csp, AT_SIGNATURE, 0, key);
931 ok(ret, "CryptGenKey failed: %08lx\n", GetLastError());
934 ret = CryptSignCertificate(csp, AT_SIGNATURE, 0, toBeSigned->pbData,
935 toBeSigned->cbData, &algoID, NULL, NULL, &size);
936 ok(ret, "CryptSignCertificate failed: %08lx\n", GetLastError());
937 ok(size <= *sigLen, "Expected size <= %ld, got %ld\n", *sigLen, size);
940 ret = CryptSignCertificate(csp, AT_SIGNATURE, 0, toBeSigned->pbData,
941 toBeSigned->cbData, &algoID, NULL, sig, &size);
942 ok(ret, "CryptSignCertificate failed: %08lx\n", GetLastError());
946 verifySig(csp, toBeSigned->pbData, toBeSigned->cbData, sig,
953 static void testVerifyCertSig(HCRYPTPROV csp, const CRYPT_DATA_BLOB *toBeSigned,
954 LPCSTR sigOID, const BYTE *sig, DWORD sigLen)
956 CERT_SIGNED_CONTENT_INFO info;
961 if(pCryptVerifyCertificateSignatureEx) {
962 ret = pCryptVerifyCertificateSignatureEx(0, 0, 0, NULL, 0, NULL, 0, NULL);
963 ok(!ret && GetLastError() == E_INVALIDARG,
964 "Expected E_INVALIDARG, got %08lx\n", GetLastError());
965 ret = pCryptVerifyCertificateSignatureEx(csp, 0, 0, NULL, 0, NULL, 0, NULL);
966 ok(!ret && GetLastError() == E_INVALIDARG,
967 "Expected E_INVALIDARG, got %08lx\n", GetLastError());
968 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING, 0, NULL, 0,
970 ok(!ret && GetLastError() == E_INVALIDARG,
971 "Expected E_INVALIDARG, got %08lx\n", GetLastError());
973 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
974 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, NULL, 0, NULL, 0, NULL);
977 info.ToBeSigned.cbData = toBeSigned->cbData;
978 info.ToBeSigned.pbData = toBeSigned->pbData;
979 info.SignatureAlgorithm.pszObjId = (LPSTR)sigOID;
980 info.SignatureAlgorithm.Parameters.cbData = 0;
981 info.Signature.cbData = sigLen;
982 info.Signature.pbData = (BYTE *)sig;
983 info.Signature.cUnusedBits = 0;
984 ret = CryptEncodeObjectEx(X509_ASN_ENCODING, X509_CERT, &info,
985 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&cert, &size);
986 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
989 CRYPT_DATA_BLOB certBlob = { 0, NULL };
990 PCERT_PUBLIC_KEY_INFO pubKeyInfo = NULL;
992 if(pCryptVerifyCertificateSignatureEx) {
993 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
994 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob, 0, NULL, 0, NULL);
995 ok(!ret && GetLastError() == CRYPT_E_ASN1_EOD,
996 "Expected CRYPT_E_ASN1_EOD, got %08lx\n", GetLastError());
998 certBlob.pbData = (void *)0xdeadbeef;
999 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
1000 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob, 0, NULL, 0, NULL);
1001 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
1002 "Expected STATUS_ACCESS_VIOLATION, got %08lx\n", GetLastError());
1003 certBlob.cbData = size;
1004 certBlob.pbData = cert;
1005 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
1006 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob, 0, NULL, 0, NULL);
1007 ok(!ret && GetLastError() == E_INVALIDARG,
1008 "Expected E_INVALIDARG, got %08lx\n", GetLastError());
1009 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
1010 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob,
1011 CRYPT_VERIFY_CERT_SIGN_ISSUER_NULL, NULL, 0, NULL);
1012 ok(!ret && GetLastError() == E_INVALIDARG,
1013 "Expected E_INVALIDARG, got %08lx\n", GetLastError());
1015 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
1016 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob,
1017 CRYPT_VERIFY_CERT_SIGN_ISSUER_PUBKEY, NULL, 0, NULL);
1020 CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING,
1021 (LPSTR)sigOID, 0, NULL, NULL, &size);
1022 pubKeyInfo = HeapAlloc(GetProcessHeap(), 0, size);
1025 ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE,
1026 X509_ASN_ENCODING, (LPSTR)sigOID, 0, NULL, pubKeyInfo, &size);
1027 ok(ret, "CryptExportKey failed: %08lx\n", GetLastError());
1028 if (ret && pCryptVerifyCertificateSignatureEx)
1030 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
1031 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob,
1032 CRYPT_VERIFY_CERT_SIGN_ISSUER_PUBKEY, pubKeyInfo, 0, NULL);
1033 ok(ret, "CryptVerifyCertificateSignatureEx failed: %08lx\n",
1036 HeapFree(GetProcessHeap(), 0, pubKeyInfo);
1042 static const BYTE emptyCert[] = { 0x30, 0x00 };
1044 static void testCertSigs(void)
1047 CRYPT_DATA_BLOB toBeSigned = { sizeof(emptyCert), (LPBYTE)emptyCert };
1051 DWORD sigSize = sizeof(sig);
1053 /* Just in case a previous run failed, delete this thing */
1054 CryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
1055 CRYPT_DELETEKEYSET);
1056 ret = CryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
1058 ok(ret, "CryptAcquireContext failed: %08lx\n", GetLastError());
1060 testSignCert(csp, &toBeSigned, szOID_RSA_SHA1RSA, &key, sig, &sigSize);
1061 testVerifyCertSig(csp, &toBeSigned, szOID_RSA_SHA1RSA, sig, sigSize);
1063 CryptDestroyKey(key);
1064 CryptReleaseContext(csp, 0);
1065 ret = CryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
1066 CRYPT_DELETEKEYSET);
1069 static void testCreateSelfSignCert(void)
1071 PCCERT_CONTEXT context;
1072 CERT_NAME_BLOB name = { sizeof(subjectName), (LPBYTE)subjectName };
1078 context = CertCreateSelfSignCertificate(0, NULL, 0, NULL, NULL, NULL, NULL,
1080 * Calling this with no first parameter creates a new key container, which
1081 * lasts beyond the test, so I don't test that. Nb: the generated key
1083 context = CertCreateSelfSignCertificate(0, &name, 0, NULL, NULL, NULL, NULL,
1088 CryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
1089 CRYPT_DELETEKEYSET);
1090 ret = CryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
1092 ok(ret, "CryptAcquireContext failed: %08lx\n", GetLastError());
1094 context = CertCreateSelfSignCertificate(csp, &name, 0, NULL, NULL, NULL,
1096 ok(!context && GetLastError() == NTE_NO_KEY,
1097 "Expected NTE_NO_KEY, got %08lx\n", GetLastError());
1098 ret = CryptGenKey(csp, AT_SIGNATURE, 0, &key);
1099 ok(ret, "CryptGenKey failed: %08lx\n", GetLastError());
1102 context = CertCreateSelfSignCertificate(csp, &name, 0, NULL, NULL, NULL,
1104 ok(context != NULL, "CertCreateSelfSignCertificate failed: %08lx\n",
1109 PCRYPT_KEY_PROV_INFO info;
1111 /* The context must have a key provider info property */
1112 ret = CertGetCertificateContextProperty(context,
1113 CERT_KEY_PROV_INFO_PROP_ID, NULL, &size);
1114 ok(ret && size, "Expected non-zero key provider info\n");
1117 info = HeapAlloc(GetProcessHeap(), 0, size);
1120 ret = CertGetCertificateContextProperty(context,
1121 CERT_KEY_PROV_INFO_PROP_ID, info, &size);
1122 ok(ret, "CertGetCertificateContextProperty failed: %08lx\n",
1126 /* Sanity-check the key provider */
1127 ok(!lstrcmpW(info->pwszContainerName, cspNameW),
1128 "Unexpected key container\n");
1129 ok(!lstrcmpW(info->pwszProvName, MS_DEF_PROV_W),
1130 "Unexpected provider\n");
1131 ok(info->dwKeySpec == AT_SIGNATURE,
1132 "Expected AT_SIGNATURE, got %ld\n", info->dwKeySpec);
1134 HeapFree(GetProcessHeap(), 0, info);
1138 CertFreeCertificateContext(context);
1141 CryptDestroyKey(key);
1144 CryptReleaseContext(csp, 0);
1145 ret = CryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
1146 CRYPT_DELETEKEYSET);
1149 static const LPCSTR keyUsages[] = { szOID_PKIX_KP_CODE_SIGNING,
1150 szOID_PKIX_KP_CLIENT_AUTH, szOID_RSA_RSA };
1152 static void testKeyUsage(void)
1155 PCCERT_CONTEXT context;
1158 /* Test base cases */
1159 ret = CertGetEnhancedKeyUsage(NULL, 0, NULL, NULL);
1160 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1161 "Expected ERROR_INVALID_PARAMETER, got %08lx\n", GetLastError());
1163 ret = CertGetEnhancedKeyUsage(NULL, 0, NULL, &size);
1164 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1165 "Expected ERROR_INVALID_PARAMETER, got %08lx\n", GetLastError());
1167 ret = CertGetEnhancedKeyUsage(NULL, 0, NULL, &size);
1168 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1169 "Expected ERROR_INVALID_PARAMETER, got %08lx\n", GetLastError());
1171 ret = CertSetEnhancedKeyUsage(NULL, NULL);
1172 usage.cUsageIdentifier = 0;
1173 ret = CertSetEnhancedKeyUsage(NULL, &usage);
1175 /* Test with a cert with no enhanced key usage extension */
1176 context = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert,
1178 ok(context != NULL, "CertCreateCertificateContext failed: %08lx\n",
1182 static const char oid[] = "1.2.3.4";
1183 BYTE buf[sizeof(CERT_ENHKEY_USAGE) + 2 * (sizeof(LPSTR) + sizeof(oid))];
1184 PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
1186 ret = CertGetEnhancedKeyUsage(context, 0, NULL, NULL);
1187 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1188 "Expected ERROR_INVALID_PARAMETER, got %08lx\n", GetLastError());
1190 ret = CertGetEnhancedKeyUsage(context, 0, NULL, &size);
1193 /* Windows 2000, ME, or later: even though it succeeded, we expect
1194 * CRYPT_E_NOT_FOUND, which indicates there is no enhanced key
1195 * usage set for this cert (which implies it's valid for all uses.)
1197 ok(GetLastError() == CRYPT_E_NOT_FOUND,
1198 "Expected CRYPT_E_NOT_FOUND, got %08lx\n", GetLastError());
1199 ok(size == sizeof(CERT_ENHKEY_USAGE), "Wrong size %ld\n", size);
1200 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
1201 ok(ret, "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
1202 ok(pUsage->cUsageIdentifier == 0, "Expected 0 usages, got %ld\n",
1203 pUsage->cUsageIdentifier);
1207 /* Windows NT, 95, or 98: it fails, and the last error is
1208 * CRYPT_E_NOT_FOUND.
1210 ok(GetLastError() == CRYPT_E_NOT_FOUND,
1211 "Expected CRYPT_E_NOT_FOUND, got %08lx\n", GetLastError());
1213 /* I can add a usage identifier when no key usage has been set */
1214 ret = CertAddEnhancedKeyUsageIdentifier(context, oid);
1215 ok(ret, "CertAddEnhancedKeyUsageIdentifier failed: %08lx\n",
1218 ret = CertGetEnhancedKeyUsage(context,
1219 CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG, pUsage, &size);
1220 ok(ret && GetLastError() == 0,
1221 "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
1222 ok(pUsage->cUsageIdentifier == 1, "Expected 1 usage, got %ld\n",
1223 pUsage->cUsageIdentifier);
1224 if (pUsage->cUsageIdentifier)
1225 ok(!strcmp(pUsage->rgpszUsageIdentifier[0], oid),
1226 "Expected %s, got %s\n", oid, pUsage->rgpszUsageIdentifier[0]);
1227 /* Now set an empty key usage */
1228 pUsage->cUsageIdentifier = 0;
1229 ret = CertSetEnhancedKeyUsage(context, pUsage);
1230 ok(ret, "CertSetEnhancedKeyUsage failed: %08lx\n", GetLastError());
1231 /* Shouldn't find it in the cert */
1233 ret = CertGetEnhancedKeyUsage(context,
1234 CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, pUsage, &size);
1235 ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
1236 "Expected CRYPT_E_NOT_FOUND, got %08lx\n", GetLastError());
1237 /* Should find it as an extended property */
1238 ret = CertGetEnhancedKeyUsage(context,
1239 CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG, pUsage, &size);
1240 ok(ret && GetLastError() == 0,
1241 "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
1242 ok(pUsage->cUsageIdentifier == 0, "Expected 0 usages, got %ld\n",
1243 pUsage->cUsageIdentifier);
1244 /* Should find it as either */
1245 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
1246 ok(ret && GetLastError() == 0,
1247 "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
1248 ok(pUsage->cUsageIdentifier == 0, "Expected 0 usages, got %ld\n",
1249 pUsage->cUsageIdentifier);
1250 /* Add a usage identifier */
1251 ret = CertAddEnhancedKeyUsageIdentifier(context, oid);
1252 ok(ret, "CertAddEnhancedKeyUsageIdentifier failed: %08lx\n",
1255 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
1256 ok(ret && GetLastError() == 0,
1257 "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
1258 ok(pUsage->cUsageIdentifier == 1, "Expected 1 identifier, got %ld\n",
1259 pUsage->cUsageIdentifier);
1260 if (pUsage->cUsageIdentifier)
1261 ok(!strcmp(pUsage->rgpszUsageIdentifier[0], oid),
1262 "Expected %s, got %s\n", oid, pUsage->rgpszUsageIdentifier[0]);
1263 /* Yep, I can re-add the same usage identifier */
1264 ret = CertAddEnhancedKeyUsageIdentifier(context, oid);
1265 ok(ret, "CertAddEnhancedKeyUsageIdentifier failed: %08lx\n",
1268 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
1269 ok(ret && GetLastError() == 0,
1270 "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
1271 ok(pUsage->cUsageIdentifier == 2, "Expected 2 identifiers, got %ld\n",
1272 pUsage->cUsageIdentifier);
1273 if (pUsage->cUsageIdentifier)
1274 ok(!strcmp(pUsage->rgpszUsageIdentifier[0], oid),
1275 "Expected %s, got %s\n", oid, pUsage->rgpszUsageIdentifier[0]);
1276 if (pUsage->cUsageIdentifier >= 2)
1277 ok(!strcmp(pUsage->rgpszUsageIdentifier[1], oid),
1278 "Expected %s, got %s\n", oid, pUsage->rgpszUsageIdentifier[1]);
1279 /* Now set a NULL extended property--this deletes the property. */
1280 ret = CertSetEnhancedKeyUsage(context, NULL);
1281 ok(ret, "CertSetEnhancedKeyUsage failed: %08lx\n", GetLastError());
1282 SetLastError(0xbaadcafe);
1284 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
1285 ok(GetLastError() == CRYPT_E_NOT_FOUND,
1286 "Expected CRYPT_E_NOT_FOUND, got %08lx\n", GetLastError());
1288 CertFreeCertificateContext(context);
1290 /* Now test with a cert with an enhanced key usage extension */
1291 context = CertCreateCertificateContext(X509_ASN_ENCODING, certWithUsage,
1292 sizeof(certWithUsage));
1293 ok(context != NULL, "CertCreateCertificateContext failed: %08lx\n",
1298 DWORD bufSize = 0, i;
1300 /* The size may depend on what flags are used to query it, so I
1301 * realloc the buffer for each test.
1303 ret = CertGetEnhancedKeyUsage(context,
1304 CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, NULL, &bufSize);
1305 ok(ret, "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
1306 buf = HeapAlloc(GetProcessHeap(), 0, bufSize);
1309 PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
1311 /* Should find it in the cert */
1313 ret = CertGetEnhancedKeyUsage(context,
1314 CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, pUsage, &size);
1315 ok(ret && GetLastError() == 0,
1316 "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
1317 ok(pUsage->cUsageIdentifier == 3, "Expected 3 usages, got %ld\n",
1318 pUsage->cUsageIdentifier);
1319 for (i = 0; i < pUsage->cUsageIdentifier; i++)
1320 ok(!strcmp(pUsage->rgpszUsageIdentifier[i], keyUsages[i]),
1321 "Expected %s, got %s\n", keyUsages[i],
1322 pUsage->rgpszUsageIdentifier[i]);
1323 HeapFree(GetProcessHeap(), 0, buf);
1325 ret = CertGetEnhancedKeyUsage(context, 0, NULL, &bufSize);
1326 ok(ret, "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
1327 buf = HeapAlloc(GetProcessHeap(), 0, bufSize);
1330 PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
1332 /* Should find it as either */
1334 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
1335 /* In Windows, GetLastError returns CRYPT_E_NOT_FOUND not found
1336 * here, even though the return is successful and the usage id
1337 * count is positive. I don't enforce that here.
1340 "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
1341 ok(pUsage->cUsageIdentifier == 3, "Expected 3 usages, got %ld\n",
1342 pUsage->cUsageIdentifier);
1343 for (i = 0; i < pUsage->cUsageIdentifier; i++)
1344 ok(!strcmp(pUsage->rgpszUsageIdentifier[i], keyUsages[i]),
1345 "Expected %s, got %s\n", keyUsages[i],
1346 pUsage->rgpszUsageIdentifier[i]);
1347 HeapFree(GetProcessHeap(), 0, buf);
1349 /* Shouldn't find it as an extended property */
1350 ret = CertGetEnhancedKeyUsage(context,
1351 CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG, NULL, &size);
1352 ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
1353 "Expected CRYPT_E_NOT_FOUND, got %08lx\n", GetLastError());
1354 /* Adding a usage identifier overrides the cert's usage!? */
1355 ret = CertAddEnhancedKeyUsageIdentifier(context, szOID_RSA_RSA);
1356 ok(ret, "CertAddEnhancedKeyUsageIdentifier failed: %08lx\n",
1358 ret = CertGetEnhancedKeyUsage(context, 0, NULL, &bufSize);
1359 ok(ret, "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
1360 buf = HeapAlloc(GetProcessHeap(), 0, bufSize);
1363 PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
1365 /* Should find it as either */
1367 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
1369 "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
1370 ok(pUsage->cUsageIdentifier == 1, "Expected 1 usage, got %ld\n",
1371 pUsage->cUsageIdentifier);
1372 ok(!strcmp(pUsage->rgpszUsageIdentifier[0], szOID_RSA_RSA),
1373 "Expected %s, got %s\n", szOID_RSA_RSA,
1374 pUsage->rgpszUsageIdentifier[0]);
1375 HeapFree(GetProcessHeap(), 0, buf);
1377 /* But querying the cert directly returns its usage */
1378 ret = CertGetEnhancedKeyUsage(context,
1379 CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, NULL, &bufSize);
1380 ok(ret, "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
1381 buf = HeapAlloc(GetProcessHeap(), 0, bufSize);
1384 PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
1387 ret = CertGetEnhancedKeyUsage(context,
1388 CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, pUsage, &size);
1390 "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
1391 ok(pUsage->cUsageIdentifier == 3, "Expected 3 usages, got %ld\n",
1392 pUsage->cUsageIdentifier);
1393 for (i = 0; i < pUsage->cUsageIdentifier; i++)
1394 ok(!strcmp(pUsage->rgpszUsageIdentifier[i], keyUsages[i]),
1395 "Expected %s, got %s\n", keyUsages[i],
1396 pUsage->rgpszUsageIdentifier[i]);
1397 HeapFree(GetProcessHeap(), 0, buf);
1399 /* And removing the only usage identifier in the extended property
1400 * results in the cert's key usage being found.
1402 ret = CertRemoveEnhancedKeyUsageIdentifier(context, szOID_RSA_RSA);
1403 ok(ret, "CertRemoveEnhancedKeyUsage failed: %08lx\n", GetLastError());
1404 ret = CertGetEnhancedKeyUsage(context, 0, NULL, &bufSize);
1405 ok(ret, "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
1406 buf = HeapAlloc(GetProcessHeap(), 0, bufSize);
1409 PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
1411 /* Should find it as either */
1413 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
1415 "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
1416 ok(pUsage->cUsageIdentifier == 3, "Expected 3 usages, got %ld\n",
1417 pUsage->cUsageIdentifier);
1418 for (i = 0; i < pUsage->cUsageIdentifier; i++)
1419 ok(!strcmp(pUsage->rgpszUsageIdentifier[i], keyUsages[i]),
1420 "Expected %s, got %s\n", keyUsages[i],
1421 pUsage->rgpszUsageIdentifier[i]);
1422 HeapFree(GetProcessHeap(), 0, buf);
1425 CertFreeCertificateContext(context);
1429 static void testCompareCertName(void)
1431 static const BYTE bogus[] = { 1, 2, 3, 4 };
1432 static const BYTE bogusPrime[] = { 0, 1, 2, 3, 4 };
1433 static const BYTE emptyPrime[] = { 0x30, 0x00, 0x01 };
1435 CERT_NAME_BLOB blob1, blob2;
1438 ret = CertCompareCertificateName(0, NULL, NULL);
1440 /* An empty name checks against itself.. */
1441 blob1.pbData = (LPBYTE)emptyCert;
1442 blob1.cbData = sizeof(emptyCert);
1443 ret = CertCompareCertificateName(0, &blob1, &blob1);
1444 ok(ret, "CertCompareCertificateName failed: %08lx\n", GetLastError());
1445 /* It doesn't have to be a valid encoded name.. */
1446 blob1.pbData = (LPBYTE)bogus;
1447 blob1.cbData = sizeof(bogus);
1448 ret = CertCompareCertificateName(0, &blob1, &blob1);
1449 ok(ret, "CertCompareCertificateName failed: %08lx\n", GetLastError());
1450 /* Leading zeroes matter.. */
1451 blob2.pbData = (LPBYTE)bogusPrime;
1452 blob2.cbData = sizeof(bogusPrime);
1453 ret = CertCompareCertificateName(0, &blob1, &blob2);
1454 ok(!ret, "Expected failure\n");
1455 /* As do trailing extra bytes. */
1456 blob2.pbData = (LPBYTE)emptyPrime;
1457 blob2.cbData = sizeof(emptyPrime);
1458 ret = CertCompareCertificateName(0, &blob1, &blob2);
1459 ok(!ret, "Expected failure\n");
1462 static const BYTE int1[] = { 0x88, 0xff, 0xff, 0xff };
1463 static const BYTE int2[] = { 0x88, 0xff };
1464 static const BYTE int3[] = { 0x23, 0xff };
1465 static const BYTE int4[] = { 0x7f, 0x00 };
1466 static const BYTE int5[] = { 0x7f };
1467 static const BYTE int6[] = { 0x80, 0x00, 0x00, 0x00 };
1468 static const BYTE int7[] = { 0x80, 0x00 };
1472 CRYPT_INTEGER_BLOB blob1;
1473 CRYPT_INTEGER_BLOB blob2;
1476 { { sizeof(int1), (LPBYTE)int1 }, { sizeof(int2), (LPBYTE)int2 }, TRUE },
1477 { { sizeof(int3), (LPBYTE)int3 }, { sizeof(int3), (LPBYTE)int3 }, TRUE },
1478 { { sizeof(int4), (LPBYTE)int4 }, { sizeof(int5), (LPBYTE)int5 }, TRUE },
1479 { { sizeof(int6), (LPBYTE)int6 }, { sizeof(int7), (LPBYTE)int7 }, TRUE },
1480 { { sizeof(int1), (LPBYTE)int1 }, { sizeof(int7), (LPBYTE)int7 }, FALSE },
1483 static void testCompareIntegerBlob(void)
1488 for (i = 0; i < sizeof(intBlobs) / sizeof(intBlobs[0]); i++)
1490 ret = CertCompareIntegerBlob(&intBlobs[i].blob1, &intBlobs[i].blob2);
1491 ok(ret == intBlobs[i].areEqual,
1492 "%ld: expected blobs %s compare\n", i, intBlobs[i].areEqual ?
1497 static void testComparePublicKeyInfo(void)
1500 CERT_PUBLIC_KEY_INFO info1 = { { 0 } }, info2 = { { 0 } };
1501 static CHAR oid_rsa_rsa[] = szOID_RSA_RSA;
1502 static CHAR oid_rsa_sha1rsa[] = szOID_RSA_SHA1RSA;
1503 static CHAR oid_x957_dsa[] = szOID_X957_DSA;
1504 static const BYTE bits1[] = { 1, 0 };
1505 static const BYTE bits2[] = { 0 };
1506 static const BYTE bits3[] = { 1 };
1509 ret = CertComparePublicKeyInfo(0, NULL, NULL);
1511 /* Empty public keys compare */
1512 ret = CertComparePublicKeyInfo(0, &info1, &info2);
1513 ok(ret, "CertComparePublicKeyInfo failed: %08lx\n", GetLastError());
1514 /* Different OIDs appear to compare */
1515 info1.Algorithm.pszObjId = oid_rsa_rsa;
1516 info2.Algorithm.pszObjId = oid_rsa_sha1rsa;
1517 ret = CertComparePublicKeyInfo(0, &info1, &info2);
1518 ok(ret, "CertComparePublicKeyInfo failed: %08lx\n", GetLastError());
1519 info2.Algorithm.pszObjId = oid_x957_dsa;
1520 ret = CertComparePublicKeyInfo(0, &info1, &info2);
1521 ok(ret, "CertComparePublicKeyInfo failed: %08lx\n", GetLastError());
1522 info1.PublicKey.cbData = sizeof(bits1);
1523 info1.PublicKey.pbData = (LPBYTE)bits1;
1524 info1.PublicKey.cUnusedBits = 0;
1525 info2.PublicKey.cbData = sizeof(bits1);
1526 info2.PublicKey.pbData = (LPBYTE)bits1;
1527 info2.PublicKey.cUnusedBits = 0;
1528 ret = CertComparePublicKeyInfo(0, &info1, &info2);
1529 ok(ret, "CertComparePublicKeyInfo failed: %08lx\n", GetLastError());
1530 /* Even though they compare in their used bits, these do not compare */
1531 info1.PublicKey.cbData = sizeof(bits2);
1532 info1.PublicKey.pbData = (LPBYTE)bits2;
1533 info1.PublicKey.cUnusedBits = 0;
1534 info2.PublicKey.cbData = sizeof(bits3);
1535 info2.PublicKey.pbData = (LPBYTE)bits3;
1536 info2.PublicKey.cUnusedBits = 1;
1537 ret = CertComparePublicKeyInfo(0, &info1, &info2);
1538 /* Simple (non-comparing) case */
1539 ok(!ret, "Expected keys not to compare\n");
1540 info2.PublicKey.cbData = sizeof(bits1);
1541 info2.PublicKey.pbData = (LPBYTE)bits1;
1542 info2.PublicKey.cUnusedBits = 0;
1543 ret = CertComparePublicKeyInfo(0, &info1, &info2);
1544 ok(!ret, "Expected keys not to compare\n");
1547 static void testHashPublicKeyInfo(void)
1550 CERT_PUBLIC_KEY_INFO info = { { 0 } };
1554 ret = CryptHashPublicKeyInfo(0, 0, 0, 0, NULL, NULL, NULL);
1555 ret = CryptHashPublicKeyInfo(0, 0, 0, 0, &info, NULL, NULL);
1557 ret = CryptHashPublicKeyInfo(0, 0, 0, 0, NULL, NULL, &len);
1558 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
1559 "Expected ERROR_FILE_NOT_FOUND, got %08lx\n", GetLastError());
1560 ret = CryptHashPublicKeyInfo(0, 0, 0, X509_ASN_ENCODING, NULL, NULL, &len);
1561 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
1562 "Expected STATUS_ACCESS_VIOLATION, got %08lx\n", GetLastError());
1563 ret = CryptHashPublicKeyInfo(0, 0, 0, X509_ASN_ENCODING, &info, NULL, &len);
1564 ok(ret, "CryptHashPublicKeyInfo failed: %08lx\n", GetLastError());
1565 ok(len == 16, "Expected hash size 16, got %ld\n", len);
1568 static const BYTE emptyHash[] = { 0xb8,0x51,0x3a,0x31,0x0e,0x9f,0x40,
1569 0x36,0x9c,0x92,0x45,0x1b,0x9d,0xc8,0xf9,0xf6 };
1572 ret = CryptHashPublicKeyInfo(0, 0, 0, X509_ASN_ENCODING, &info, buf,
1574 ok(ret, "CryptHashPublicKeyInfo failed: %08lx\n", GetLastError());
1575 ok(!memcmp(buf, emptyHash, len), "Unexpected hash\n");
1579 void testCompareCert(void)
1581 CERT_INFO info1 = { 0 }, info2 = { 0 };
1585 ret = CertCompareCertificate(X509_ASN_ENCODING, NULL, NULL);
1588 /* Certs with the same issuer and serial number are equal, even if they
1589 * differ in other respects (like subject).
1591 info1.SerialNumber.pbData = (LPBYTE)serialNum;
1592 info1.SerialNumber.cbData = sizeof(serialNum);
1593 info1.Issuer.pbData = (LPBYTE)subjectName;
1594 info1.Issuer.cbData = sizeof(subjectName);
1595 info1.Subject.pbData = (LPBYTE)subjectName2;
1596 info1.Subject.cbData = sizeof(subjectName2);
1597 info2.SerialNumber.pbData = (LPBYTE)serialNum;
1598 info2.SerialNumber.cbData = sizeof(serialNum);
1599 info2.Issuer.pbData = (LPBYTE)subjectName;
1600 info2.Issuer.cbData = sizeof(subjectName);
1601 info2.Subject.pbData = (LPBYTE)subjectName;
1602 info2.Subject.cbData = sizeof(subjectName);
1603 ret = CertCompareCertificate(X509_ASN_ENCODING, &info1, &info2);
1604 ok(ret, "Expected certs to be equal\n");
1606 info2.Issuer.pbData = (LPBYTE)subjectName2;
1607 info2.Issuer.cbData = sizeof(subjectName2);
1608 ret = CertCompareCertificate(X509_ASN_ENCODING, &info1, &info2);
1609 ok(!ret, "Expected certs not to be equal\n");
1612 static void testVerifySubjectCert(void)
1616 PCCERT_CONTEXT context1, context2;
1619 ret = CertVerifySubjectCertificateContext(NULL, NULL, NULL);
1622 ret = CertVerifySubjectCertificateContext(NULL, NULL, &flags);
1623 ok(ret, "CertVerifySubjectCertificateContext failed; %08lx\n",
1625 flags = CERT_STORE_NO_CRL_FLAG;
1626 ret = CertVerifySubjectCertificateContext(NULL, NULL, &flags);
1627 ok(!ret && GetLastError() == E_INVALIDARG,
1628 "Expected E_INVALIDARG, got %08lx\n", GetLastError());
1631 context1 = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert,
1633 ret = CertVerifySubjectCertificateContext(NULL, context1, &flags);
1634 ok(ret, "CertVerifySubjectCertificateContext failed; %08lx\n",
1636 ret = CertVerifySubjectCertificateContext(context1, NULL, &flags);
1637 ok(ret, "CertVerifySubjectCertificateContext failed; %08lx\n",
1639 ret = CertVerifySubjectCertificateContext(context1, context1, &flags);
1640 ok(ret, "CertVerifySubjectCertificateContext failed; %08lx\n",
1643 context2 = CertCreateCertificateContext(X509_ASN_ENCODING,
1644 bigCertWithDifferentSubject, sizeof(bigCertWithDifferentSubject));
1645 SetLastError(0xdeadbeef);
1646 ret = CertVerifySubjectCertificateContext(context1, context2, &flags);
1647 ok(ret, "CertVerifySubjectCertificateContext failed; %08lx\n",
1649 flags = CERT_STORE_REVOCATION_FLAG;
1650 ret = CertVerifySubjectCertificateContext(context1, context2, &flags);
1651 ok(ret, "CertVerifySubjectCertificateContext failed; %08lx\n",
1653 ok(flags == (CERT_STORE_REVOCATION_FLAG | CERT_STORE_NO_CRL_FLAG),
1654 "Expected CERT_STORE_REVOCATION_FLAG | CERT_STORE_NO_CRL_FLAG, got %08lx\n",
1656 flags = CERT_STORE_SIGNATURE_FLAG;
1657 ret = CertVerifySubjectCertificateContext(context1, context2, &flags);
1658 ok(ret, "CertVerifySubjectCertificateContext failed; %08lx\n",
1660 ok(flags == CERT_STORE_SIGNATURE_FLAG,
1661 "Expected CERT_STORE_SIGNATURE_FLAG, got %08lx\n", flags);
1662 CertFreeCertificateContext(context2);
1664 CertFreeCertificateContext(context1);
1667 static const BYTE privKey[] = {
1668 0x07, 0x02, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x52, 0x53, 0x41, 0x32, 0x00,
1669 0x02, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x79, 0x10, 0x1c, 0xd0, 0x6b, 0x10,
1670 0x18, 0x30, 0x94, 0x61, 0xdc, 0x0e, 0xcb, 0x96, 0x4e, 0x21, 0x3f, 0x79, 0xcd,
1671 0xa9, 0x17, 0x62, 0xbc, 0xbb, 0x61, 0x4c, 0xe0, 0x75, 0x38, 0x6c, 0xf3, 0xde,
1672 0x60, 0x86, 0x03, 0x97, 0x65, 0xeb, 0x1e, 0x6b, 0xdb, 0x53, 0x85, 0xad, 0x68,
1673 0x21, 0xf1, 0x5d, 0xe7, 0x1f, 0xe6, 0x53, 0xb4, 0xbb, 0x59, 0x3e, 0x14, 0x27,
1674 0xb1, 0x83, 0xa7, 0x3a, 0x54, 0xe2, 0x8f, 0x65, 0x8e, 0x6a, 0x4a, 0xcf, 0x3b,
1675 0x1f, 0x65, 0xff, 0xfe, 0xf1, 0x31, 0x3a, 0x37, 0x7a, 0x8b, 0xcb, 0xc6, 0xd4,
1676 0x98, 0x50, 0x36, 0x67, 0xe4, 0xa1, 0xe8, 0x7e, 0x8a, 0xc5, 0x23, 0xf2, 0x77,
1677 0xf5, 0x37, 0x61, 0x49, 0x72, 0x59, 0xe8, 0x3d, 0xf7, 0x60, 0xb2, 0x77, 0xca,
1678 0x78, 0x54, 0x6d, 0x65, 0x9e, 0x03, 0x97, 0x1b, 0x61, 0xbd, 0x0c, 0xd8, 0x06,
1679 0x63, 0xe2, 0xc5, 0x48, 0xef, 0xb3, 0xe2, 0x6e, 0x98, 0x7d, 0xbd, 0x4e, 0x72,
1680 0x91, 0xdb, 0x31, 0x57, 0xe3, 0x65, 0x3a, 0x49, 0xca, 0xec, 0xd2, 0x02, 0x4e,
1681 0x22, 0x7e, 0x72, 0x8e, 0xf9, 0x79, 0x84, 0x82, 0xdf, 0x7b, 0x92, 0x2d, 0xaf,
1682 0xc9, 0xe4, 0x33, 0xef, 0x89, 0x5c, 0x66, 0x99, 0xd8, 0x80, 0x81, 0x47, 0x2b,
1683 0xb1, 0x66, 0x02, 0x84, 0x59, 0x7b, 0xc3, 0xbe, 0x98, 0x45, 0x4a, 0x3d, 0xdd,
1684 0xea, 0x2b, 0xdf, 0x4e, 0xb4, 0x24, 0x6b, 0xec, 0xe7, 0xd9, 0x0c, 0x45, 0xb8,
1685 0xbe, 0xca, 0x69, 0x37, 0x92, 0x4c, 0x38, 0x6b, 0x96, 0x6d, 0xcd, 0x86, 0x67,
1686 0x5c, 0xea, 0x54, 0x94, 0xa4, 0xca, 0xa4, 0x02, 0xa5, 0x21, 0x4d, 0xae, 0x40,
1687 0x8f, 0x9d, 0x51, 0x83, 0xf2, 0x3f, 0x33, 0xc1, 0x72, 0xb4, 0x1d, 0x94, 0x6e,
1688 0x7d, 0xe4, 0x27, 0x3f, 0xea, 0xff, 0xe5, 0x9b, 0xa7, 0x5e, 0x55, 0x8e, 0x0d,
1689 0x69, 0x1c, 0x7a, 0xff, 0x81, 0x9d, 0x53, 0x52, 0x97, 0x9a, 0x76, 0x79, 0xda,
1690 0x93, 0x32, 0x16, 0xec, 0x69, 0x51, 0x1a, 0x4e, 0xc3, 0xf1, 0x72, 0x80, 0x78,
1691 0x5e, 0x66, 0x4a, 0x8d, 0x85, 0x2f, 0x3f, 0xb2, 0xa7 };
1693 static const BYTE selfSignedCert[] = {
1694 0x30, 0x82, 0x01, 0x1f, 0x30, 0x81, 0xce, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02,
1695 0x10, 0xeb, 0x0d, 0x57, 0x2a, 0x9c, 0x09, 0xba, 0xa4, 0x4a, 0xb7, 0x25, 0x49,
1696 0xd9, 0x3e, 0xb5, 0x73, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1d,
1697 0x05, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03,
1698 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30,
1699 0x1e, 0x17, 0x0d, 0x30, 0x36, 0x30, 0x36, 0x32, 0x39, 0x30, 0x35, 0x30, 0x30,
1700 0x34, 0x36, 0x5a, 0x17, 0x0d, 0x30, 0x37, 0x30, 0x36, 0x32, 0x39, 0x31, 0x31,
1701 0x30, 0x30, 0x34, 0x36, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03,
1702 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e,
1703 0x67, 0x00, 0x30, 0x5c, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
1704 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x4b, 0x00, 0x30, 0x48, 0x02, 0x41,
1705 0x00, 0xe2, 0x54, 0x3a, 0xa7, 0x83, 0xb1, 0x27, 0x14, 0x3e, 0x59, 0xbb, 0xb4,
1706 0x53, 0xe6, 0x1f, 0xe7, 0x5d, 0xf1, 0x21, 0x68, 0xad, 0x85, 0x53, 0xdb, 0x6b,
1707 0x1e, 0xeb, 0x65, 0x97, 0x03, 0x86, 0x60, 0xde, 0xf3, 0x6c, 0x38, 0x75, 0xe0,
1708 0x4c, 0x61, 0xbb, 0xbc, 0x62, 0x17, 0xa9, 0xcd, 0x79, 0x3f, 0x21, 0x4e, 0x96,
1709 0xcb, 0x0e, 0xdc, 0x61, 0x94, 0x30, 0x18, 0x10, 0x6b, 0xd0, 0x1c, 0x10, 0x79,
1710 0x02, 0x03, 0x01, 0x00, 0x01, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02,
1711 0x1d, 0x05, 0x00, 0x03, 0x41, 0x00, 0x25, 0x90, 0x53, 0x34, 0xd9, 0x56, 0x41,
1712 0x5e, 0xdb, 0x7e, 0x01, 0x36, 0xec, 0x27, 0x61, 0x5e, 0xb7, 0x4d, 0x90, 0x66,
1713 0xa2, 0xe1, 0x9d, 0x58, 0x76, 0xd4, 0x9c, 0xba, 0x2c, 0x84, 0xc6, 0x83, 0x7a,
1714 0x22, 0x0d, 0x03, 0x69, 0x32, 0x1a, 0x6d, 0xcb, 0x0c, 0x15, 0xb3, 0x6b, 0xc7,
1715 0x0a, 0x8c, 0xb4, 0x5c, 0x34, 0x78, 0xe0, 0x3c, 0x9c, 0xe9, 0xf3, 0x30, 0x9f,
1716 0xa8, 0x76, 0x57, 0x92, 0x36 };
1718 static void testAcquireCertPrivateKey(void)
1721 PCCERT_CONTEXT cert;
1725 CRYPT_KEY_PROV_INFO keyProvInfo;
1728 keyProvInfo.pwszContainerName = (LPWSTR)cspNameW;
1729 keyProvInfo.pwszProvName = (LPWSTR)MS_DEF_PROV_W;
1730 keyProvInfo.dwProvType = PROV_RSA_FULL;
1731 keyProvInfo.dwFlags = 0;
1732 keyProvInfo.cProvParam = 0;
1733 keyProvInfo.rgProvParam = NULL;
1734 keyProvInfo.dwKeySpec = AT_SIGNATURE;
1736 CryptAcquireContextW(NULL, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
1737 CRYPT_DELETEKEYSET);
1739 cert = CertCreateCertificateContext(X509_ASN_ENCODING, selfSignedCert,
1740 sizeof(selfSignedCert));
1743 ret = CryptAcquireCertificatePrivateKey(NULL, 0, NULL, NULL, NULL, NULL);
1744 ret = CryptAcquireCertificatePrivateKey(NULL, 0, NULL, NULL, NULL,
1746 ret = CryptAcquireCertificatePrivateKey(NULL, 0, NULL, NULL, &keySpec,
1748 ret = CryptAcquireCertificatePrivateKey(NULL, 0, NULL, &csp, NULL, NULL);
1749 ret = CryptAcquireCertificatePrivateKey(NULL, 0, NULL, &csp, &keySpec,
1751 ret = CryptAcquireCertificatePrivateKey(cert, 0, NULL, NULL, NULL, NULL);
1754 /* Missing private key */
1755 ret = CryptAcquireCertificatePrivateKey(cert, 0, NULL, &csp, NULL, NULL);
1756 ok(!ret && GetLastError() == CRYPT_E_NO_KEY_PROPERTY,
1757 "Expected CRYPT_E_NO_KEY_PROPERTY, got %08lx\n", GetLastError());
1758 ret = CryptAcquireCertificatePrivateKey(cert, 0, NULL, &csp, &keySpec,
1760 ok(!ret && GetLastError() == CRYPT_E_NO_KEY_PROPERTY,
1761 "Expected CRYPT_E_NO_KEY_PROPERTY, got %08lx\n", GetLastError());
1762 CertSetCertificateContextProperty(cert, CERT_KEY_PROV_INFO_PROP_ID, 0,
1764 ret = CryptAcquireCertificatePrivateKey(cert, 0, NULL, &csp, &keySpec,
1766 ok(!ret && GetLastError() == CRYPT_E_NO_KEY_PROPERTY,
1767 "Expected CRYPT_E_NO_KEY_PROPERTY, got %08lx\n", GetLastError());
1769 CryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
1771 ret = CryptImportKey(csp, (LPBYTE)privKey, sizeof(privKey), 0, 0, &key);
1772 ok(ret, "CryptImportKey failed: %08lx\n", GetLastError());
1777 CERT_KEY_CONTEXT keyContext;
1779 /* Don't cache provider */
1780 ret = CryptAcquireCertificatePrivateKey(cert, 0, NULL, &certCSP,
1781 &keySpec, &callerFree);
1782 ok(ret, "CryptAcquireCertificatePrivateKey failed: %08lx\n",
1784 ok(callerFree, "Expected callerFree to be TRUE\n");
1785 CryptReleaseContext(certCSP, 0);
1786 ret = CryptAcquireCertificatePrivateKey(cert, 0, NULL, &certCSP,
1788 ok(ret, "CryptAcquireCertificatePrivateKey failed: %08lx\n",
1790 CryptReleaseContext(certCSP, 0);
1792 /* Use the key prov info's caching (there shouldn't be any) */
1793 ret = CryptAcquireCertificatePrivateKey(cert,
1794 CRYPT_ACQUIRE_USE_PROV_INFO_FLAG, NULL, &certCSP, &keySpec,
1796 ok(ret, "CryptAcquireCertificatePrivateKey failed: %08lx\n",
1798 ok(callerFree, "Expected callerFree to be TRUE\n");
1799 CryptReleaseContext(certCSP, 0);
1801 /* Cache it (and check that it's cached) */
1802 ret = CryptAcquireCertificatePrivateKey(cert,
1803 CRYPT_ACQUIRE_CACHE_FLAG, NULL, &certCSP, &keySpec, &callerFree);
1804 ok(ret, "CryptAcquireCertificatePrivateKey failed: %08lx\n",
1806 ok(!callerFree, "Expected callerFree to be FALSE\n");
1807 size = sizeof(keyContext);
1808 ret = CertGetCertificateContextProperty(cert, CERT_KEY_CONTEXT_PROP_ID,
1809 &keyContext, &size);
1810 ok(ret, "CertGetCertificateContextProperty failed: %08lx\n",
1813 /* Remove the cached provider */
1814 CryptReleaseContext(keyContext.hCryptProv, 0);
1815 CertSetCertificateContextProperty(cert, CERT_KEY_CONTEXT_PROP_ID, 0,
1817 /* Allow caching via the key prov info */
1818 keyProvInfo.dwFlags = CERT_SET_KEY_CONTEXT_PROP_ID;
1819 CertSetCertificateContextProperty(cert, CERT_KEY_PROV_INFO_PROP_ID, 0,
1821 /* Now use the key prov info's caching */
1822 ret = CryptAcquireCertificatePrivateKey(cert,
1823 CRYPT_ACQUIRE_USE_PROV_INFO_FLAG, NULL, &certCSP, &keySpec,
1825 ok(ret, "CryptAcquireCertificatePrivateKey failed: %08lx\n",
1827 ok(!callerFree, "Expected callerFree to be FALSE\n");
1828 size = sizeof(keyContext);
1829 ret = CertGetCertificateContextProperty(cert, CERT_KEY_CONTEXT_PROP_ID,
1830 &keyContext, &size);
1831 ok(ret, "CertGetCertificateContextProperty failed: %08lx\n",
1834 CryptDestroyKey(key);
1837 CryptReleaseContext(csp, 0);
1838 CryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
1839 CRYPT_DELETEKEYSET);
1841 CertFreeCertificateContext(cert);
1846 init_function_pointers();
1849 testCertProperties();
1852 testGetSubjectCert();
1853 testGetIssuerCert();
1855 testCryptHashCert();
1857 testCreateSelfSignCert();
1859 testCompareCertName();
1860 testCompareIntegerBlob();
1861 testComparePublicKeyInfo();
1862 testHashPublicKeyInfo();
1864 testVerifySubjectCert();
1865 testAcquireCertPrivateKey();