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 void testCertProperties(void)
315 PCCERT_CONTEXT context = CertCreateCertificateContext(X509_ASN_ENCODING,
316 bigCert, sizeof(bigCert));
318 ok(context != NULL, "CertCreateCertificateContext failed: %08lx\n",
322 DWORD propID, numProps, access, size;
324 BYTE hash[20] = { 0 }, hashProperty[20];
325 CRYPT_DATA_BLOB blob;
328 propID = CertEnumCertificateContextProperties(NULL, 0);
334 propID = CertEnumCertificateContextProperties(context, propID);
337 } while (propID != 0);
338 ok(numProps == 0, "Expected 0 properties, got %ld\n", numProps);
340 /* Tests with a NULL cert context. Prop ID 0 fails.. */
341 ret = CertSetCertificateContextProperty(NULL, 0, 0, NULL);
342 ok(!ret && GetLastError() == E_INVALIDARG,
343 "Expected E_INVALIDARG, got %08lx\n", GetLastError());
344 /* while this just crashes.
345 ret = CertSetCertificateContextProperty(NULL,
346 CERT_KEY_PROV_HANDLE_PROP_ID, 0, NULL);
349 ret = CertSetCertificateContextProperty(context, 0, 0, NULL);
350 ok(!ret && GetLastError() == E_INVALIDARG,
351 "Expected E_INVALIDARG, got %08lx\n", GetLastError());
352 /* Can't set the cert property directly, this crashes.
353 ret = CertSetCertificateContextProperty(context,
354 CERT_CERT_PROP_ID, 0, bigCert2);
358 ret = CertGetCertificateContextProperty(context,
359 CERT_ACCESS_STATE_PROP_ID, 0, NULL);
360 ret = CertGetCertificateContextProperty(context, CERT_HASH_PROP_ID,
362 ret = CertGetCertificateContextProperty(context, CERT_HASH_PROP_ID,
367 ret = CertGetCertificateContextProperty(context,
368 CERT_KEY_PROV_INFO_PROP_ID, NULL, &size);
369 ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
370 "Expected CRYPT_E_NOT_FOUND, got %08lx\n", GetLastError());
371 /* And, an implicit property */
372 size = sizeof(access);
373 ret = CertGetCertificateContextProperty(context,
374 CERT_ACCESS_STATE_PROP_ID, &access, &size);
375 ok(ret, "CertGetCertificateContextProperty failed: %08lx\n",
377 ok(!(access & CERT_ACCESS_STATE_WRITE_PERSIST_FLAG),
378 "Didn't expect a persisted cert\n");
379 /* Trying to set this "read only" property crashes.
380 access |= CERT_ACCESS_STATE_WRITE_PERSIST_FLAG;
381 ret = CertSetCertificateContextProperty(context,
382 CERT_ACCESS_STATE_PROP_ID, 0, &access);
385 /* Can I set the hash to an invalid hash? */
387 blob.cbData = sizeof(hash);
388 ret = CertSetCertificateContextProperty(context, CERT_HASH_PROP_ID, 0,
390 ok(ret, "CertSetCertificateContextProperty failed: %08lx\n",
392 size = sizeof(hashProperty);
393 ret = CertGetCertificateContextProperty(context, CERT_HASH_PROP_ID,
394 hashProperty, &size);
395 ok(!memcmp(hashProperty, hash, sizeof(hash)), "Unexpected hash\n");
396 /* Delete the (bogus) hash, and get the real one */
397 ret = CertSetCertificateContextProperty(context, CERT_HASH_PROP_ID, 0,
399 ok(ret, "CertSetCertificateContextProperty failed: %08lx\n",
401 checkHash(bigCert, sizeof(bigCert), CALG_SHA1, context,
404 /* Now that the hash property is set, we should get one property when
410 propID = CertEnumCertificateContextProperties(context, propID);
413 } while (propID != 0);
414 ok(numProps == 1, "Expected 1 properties, got %ld\n", numProps);
416 /* Check a few other implicit properties */
417 checkHash(bigCert, sizeof(bigCert), CALG_MD5, context,
418 CERT_MD5_HASH_PROP_ID);
420 context->pCertInfo->Subject.pbData,
421 context->pCertInfo->Subject.cbData,
422 CALG_MD5, context, CERT_SUBJECT_NAME_MD5_HASH_PROP_ID);
424 context->pCertInfo->SubjectPublicKeyInfo.PublicKey.pbData,
425 context->pCertInfo->SubjectPublicKeyInfo.PublicKey.cbData,
426 CALG_MD5, context, CERT_SUBJECT_PUBLIC_KEY_MD5_HASH_PROP_ID);
428 /* Odd: this doesn't fail on other certificates, so there must be
429 * something weird about this cert that causes it to fail.
432 ret = CertGetCertificateContextProperty(context,
433 CERT_KEY_IDENTIFIER_PROP_ID, NULL, &size);
434 todo_wine ok(!ret && GetLastError() == ERROR_INVALID_DATA,
435 "Expected ERROR_INVALID_DATA, got %08lx\n", GetLastError());
437 CertFreeCertificateContext(context);
441 static void testDupCert(void)
445 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
446 CERT_STORE_CREATE_NEW_FLAG, NULL);
447 ok(store != NULL, "CertOpenStore failed: %ld\n", GetLastError());
450 PCCERT_CONTEXT context, dupContext;
453 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
454 bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, &context);
455 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n",
457 ok(context != NULL, "Expected a valid cert context\n");
460 ok(context->cbCertEncoded == sizeof(bigCert),
461 "Wrong cert size %ld\n", context->cbCertEncoded);
462 ok(!memcmp(context->pbCertEncoded, bigCert, sizeof(bigCert)),
463 "Unexpected encoded cert in context\n");
464 ok(context->hCertStore == store, "Unexpected store\n");
466 dupContext = CertDuplicateCertificateContext(context);
467 ok(dupContext != NULL, "Expected valid duplicate\n");
468 /* Not only is it a duplicate, it's identical: the address is the
471 ok(dupContext == context, "Expected identical context addresses\n");
472 CertFreeCertificateContext(dupContext);
473 CertFreeCertificateContext(context);
475 CertCloseStore(store, 0);
479 static void testFindCert(void)
483 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
484 CERT_STORE_CREATE_NEW_FLAG, NULL);
485 ok(store != NULL, "CertOpenStore failed: %ld\n", GetLastError());
488 PCCERT_CONTEXT context = NULL;
490 CERT_INFO certInfo = { 0 };
491 CRYPT_HASH_BLOB blob;
493 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
494 bigCert, sizeof(bigCert), CERT_STORE_ADD_NEW, NULL);
495 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n",
497 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
498 bigCert2, sizeof(bigCert2), CERT_STORE_ADD_NEW, NULL);
499 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n",
501 /* This has the same name as bigCert */
502 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
503 certWithUsage, sizeof(certWithUsage), CERT_STORE_ADD_NEW, NULL);
504 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n",
508 context = CertFindCertificateInStore(NULL, 0, 0, 0, NULL, NULL);
511 /* Check first cert's there, by issuer */
512 certInfo.Subject.pbData = (LPBYTE)subjectName;
513 certInfo.Subject.cbData = sizeof(subjectName);
514 certInfo.SerialNumber.pbData = (LPBYTE)serialNum;
515 certInfo.SerialNumber.cbData = sizeof(serialNum);
516 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
517 CERT_FIND_ISSUER_NAME, &certInfo.Subject, NULL);
518 ok(context != NULL, "CertFindCertificateInStore failed: %08lx\n",
522 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
523 CERT_FIND_ISSUER_NAME, &certInfo.Subject, context);
524 ok(context != NULL, "Expected more than one cert\n");
527 context = CertFindCertificateInStore(store, X509_ASN_ENCODING,
528 0, CERT_FIND_ISSUER_NAME, &certInfo.Subject, context);
529 ok(context == NULL, "Expected precisely two certs\n");
533 /* Check second cert's there as well, by subject name */
534 certInfo.Subject.pbData = (LPBYTE)subjectName2;
535 certInfo.Subject.cbData = sizeof(subjectName2);
536 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
537 CERT_FIND_SUBJECT_NAME, &certInfo.Subject, NULL);
538 ok(context != NULL, "CertFindCertificateInStore failed: %08lx\n",
542 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
543 CERT_FIND_ISSUER_NAME, &certInfo.Subject, context);
544 ok(context == NULL, "Expected one cert only\n");
547 /* Strange but true: searching for the subject cert requires you to set
548 * the issuer, not the subject
550 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
551 CERT_FIND_SUBJECT_CERT, &certInfo.Subject, NULL);
552 ok(context == NULL, "Expected no certificate\n");
553 certInfo.Subject.pbData = NULL;
554 certInfo.Subject.cbData = 0;
555 certInfo.Issuer.pbData = (LPBYTE)subjectName2;
556 certInfo.Issuer.cbData = sizeof(subjectName2);
557 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
558 CERT_FIND_SUBJECT_CERT, &certInfo, NULL);
559 ok(context != NULL, "CertFindCertificateInStore failed: %08lx\n",
563 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
564 CERT_FIND_ISSUER_NAME, &certInfo.Subject, context);
565 ok(context == NULL, "Expected one cert only\n");
568 /* The nice thing about hashes, they're unique */
569 blob.pbData = (LPBYTE)bigCertHash;
570 blob.cbData = sizeof(bigCertHash);
571 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
572 CERT_FIND_SHA1_HASH, &blob, NULL);
573 ok(context != NULL, "CertFindCertificateInStore failed: %08lx\n",
577 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
578 CERT_FIND_ISSUER_NAME, &certInfo.Subject, context);
579 ok(context == NULL, "Expected one cert only\n");
582 CertCloseStore(store, 0);
586 static void testGetSubjectCert(void)
590 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
591 CERT_STORE_CREATE_NEW_FLAG, NULL);
592 ok(store != NULL, "CertOpenStore failed: %ld\n", GetLastError());
595 PCCERT_CONTEXT context1, context2;
596 CERT_INFO info = { 0 };
599 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
600 bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL);
601 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n",
603 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
604 bigCert2, sizeof(bigCert2), CERT_STORE_ADD_NEW, &context1);
605 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n",
607 ok(context1 != NULL, "Expected a context\n");
608 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
609 certWithUsage, sizeof(certWithUsage), CERT_STORE_ADD_NEW, NULL);
610 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n",
613 context2 = CertGetSubjectCertificateFromStore(store, X509_ASN_ENCODING,
615 ok(!context2 && GetLastError() == E_INVALIDARG,
616 "Expected E_INVALIDARG, got %08lx\n", GetLastError());
617 context2 = CertGetSubjectCertificateFromStore(store, X509_ASN_ENCODING,
619 ok(!context2 && GetLastError() == CRYPT_E_NOT_FOUND,
620 "Expected CRYPT_E_NOT_FOUND, got %08lx\n", GetLastError());
621 info.SerialNumber.cbData = sizeof(serialNum);
622 info.SerialNumber.pbData = (LPBYTE)serialNum;
623 context2 = CertGetSubjectCertificateFromStore(store, X509_ASN_ENCODING,
625 ok(!context2 && GetLastError() == CRYPT_E_NOT_FOUND,
626 "Expected CRYPT_E_NOT_FOUND, got %08lx\n", GetLastError());
627 info.Issuer.cbData = sizeof(subjectName2);
628 info.Issuer.pbData = (LPBYTE)subjectName2;
629 context2 = CertGetSubjectCertificateFromStore(store, X509_ASN_ENCODING,
632 "CertGetSubjectCertificateFromStore failed: %08lx\n", GetLastError());
633 /* Not only should this find a context, but it should be the same
634 * (same address) as context1.
636 ok(context1 == context2, "Expected identical context addresses\n");
637 CertFreeCertificateContext(context2);
639 CertFreeCertificateContext(context1);
640 CertCloseStore(store, 0);
644 /* This expires in 1970 or so */
645 static const BYTE expiredCert[] = { 0x30, 0x82, 0x01, 0x33, 0x30, 0x81, 0xe2,
646 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0xc4, 0xd7, 0x7f, 0x0e, 0x6f, 0xa6,
647 0x8c, 0xaa, 0x47, 0x47, 0x40, 0xe7, 0xb7, 0x0b, 0x4a, 0x7f, 0x30, 0x09, 0x06,
648 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1d, 0x05, 0x00, 0x30, 0x1f, 0x31, 0x1d, 0x30,
649 0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63, 0x40,
650 0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63,
651 0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x36, 0x39, 0x30, 0x31, 0x30, 0x31, 0x30,
652 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x37, 0x30, 0x30, 0x31, 0x30,
653 0x31, 0x30, 0x36, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x1f, 0x31, 0x1d, 0x30,
654 0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63, 0x40,
655 0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63,
656 0x6f, 0x6d, 0x30, 0x5c, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
657 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x4b, 0x00, 0x30, 0x48, 0x02, 0x41,
658 0x00, 0xa1, 0xaf, 0x4a, 0xea, 0xa7, 0x83, 0x57, 0xc0, 0x37, 0x33, 0x7e, 0x29,
659 0x5e, 0x0d, 0xfc, 0x44, 0x74, 0x3a, 0x1d, 0xc3, 0x1b, 0x1d, 0x96, 0xed, 0x4e,
660 0xf4, 0x1b, 0x98, 0xec, 0x69, 0x1b, 0x04, 0xea, 0x25, 0xcf, 0xb3, 0x2a, 0xf5,
661 0xd9, 0x22, 0xd9, 0x8d, 0x08, 0x39, 0x81, 0xc6, 0xe0, 0x4f, 0x12, 0x37, 0x2a,
662 0x3f, 0x80, 0xa6, 0x6c, 0x67, 0x43, 0x3a, 0xdd, 0x95, 0x0c, 0xbb, 0x2f, 0x6b,
663 0x02, 0x03, 0x01, 0x00, 0x01, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02,
664 0x1d, 0x05, 0x00, 0x03, 0x41, 0x00, 0x8f, 0xa2, 0x5b, 0xd6, 0xdf, 0x34, 0xd0,
665 0xa2, 0xa7, 0x47, 0xf1, 0x13, 0x79, 0xd3, 0xf3, 0x39, 0xbd, 0x4e, 0x2b, 0xa3,
666 0xf4, 0x63, 0x37, 0xac, 0x5a, 0x0c, 0x5e, 0x4d, 0x0d, 0x54, 0x87, 0x4f, 0x31,
667 0xfb, 0xa0, 0xce, 0x8f, 0x9a, 0x2f, 0x4d, 0x48, 0xc6, 0x84, 0x8d, 0xf5, 0x70,
668 0x74, 0x17, 0xa5, 0xf3, 0x66, 0x47, 0x06, 0xd6, 0x64, 0x45, 0xbc, 0x52, 0xef,
669 0x49, 0xe5, 0xf9, 0x65, 0xf3 };
671 /* This expires in 2036 or so */
672 static const BYTE childOfExpired[] = { 0x30, 0x81, 0xcc, 0x30, 0x78, 0xa0,
673 0x03, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86,
674 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x1f, 0x31, 0x1d,
675 0x30, 0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63,
676 0x40, 0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e,
677 0x63, 0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x30, 0x36, 0x30, 0x35, 0x30, 0x35,
678 0x31, 0x37, 0x31, 0x32, 0x34, 0x39, 0x5a, 0x17, 0x0d, 0x33, 0x36, 0x30, 0x35,
679 0x30, 0x35, 0x31, 0x37, 0x31, 0x32, 0x34, 0x39, 0x5a, 0x30, 0x15, 0x31, 0x13,
680 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e,
681 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03,
682 0x01, 0x00, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
683 0x01, 0x05, 0x05, 0x00, 0x03, 0x41, 0x00, 0x20, 0x3b, 0xdb, 0x4d, 0x67, 0x50,
684 0xec, 0x73, 0x9d, 0xf9, 0x85, 0x5d, 0x18, 0xe9, 0xb4, 0x98, 0xe3, 0x31, 0xb7,
685 0x03, 0x0b, 0xc0, 0x39, 0x93, 0x56, 0x81, 0x0a, 0xfc, 0x78, 0xa8, 0x29, 0x42,
686 0x5f, 0x69, 0xfb, 0xbc, 0x5b, 0xf2, 0xa6, 0x2a, 0xbe, 0x91, 0x2c, 0xfc, 0x89,
687 0x69, 0x15, 0x18, 0x58, 0xe5, 0x02, 0x75, 0xf7, 0x2a, 0xb6, 0xa9, 0xfb, 0x47,
688 0x6a, 0x6e, 0x0a, 0x9b, 0xe9, 0xdc };
690 static void testGetIssuerCert(void)
693 PCCERT_CONTEXT parent, child;
694 DWORD flags = 0xffffffff;
695 HCERTSTORE store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
696 CERT_STORE_CREATE_NEW_FLAG, NULL);
698 ok(store != NULL, "CertOpenStore failed: %08lx\n", GetLastError());
700 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
701 expiredCert, sizeof(expiredCert), CERT_STORE_ADD_ALWAYS, NULL);
702 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n",
705 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
706 childOfExpired, sizeof(childOfExpired), CERT_STORE_ADD_ALWAYS, &child);
707 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n",
711 parent = CertGetIssuerCertificateFromStore(NULL, NULL, NULL, NULL);
712 parent = CertGetIssuerCertificateFromStore(store, NULL, NULL, NULL);
714 parent = CertGetIssuerCertificateFromStore(NULL, NULL, NULL, &flags);
715 ok(!parent && GetLastError() == E_INVALIDARG,
716 "Expected E_INVALIDARG, got %08lx\n", GetLastError());
717 parent = CertGetIssuerCertificateFromStore(store, NULL, NULL, &flags);
718 ok(!parent && GetLastError() == E_INVALIDARG,
719 "Expected E_INVALIDARG, got %08lx\n", GetLastError());
720 parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
721 ok(!parent && GetLastError() == E_INVALIDARG,
722 "Expected E_INVALIDARG, got %08lx\n", GetLastError());
723 /* Confusing: the caller cannot set either of the
724 * CERT_STORE_NO_*_FLAGs, as these are not checks,
727 flags = CERT_STORE_NO_CRL_FLAG | CERT_STORE_NO_ISSUER_FLAG;
728 parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
729 ok(!parent && GetLastError() == E_INVALIDARG,
730 "Expected E_INVALIDARG, got %08lx\n", GetLastError());
731 /* Perform no checks */
733 parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
734 ok(parent != NULL, "CertGetIssuerCertificateFromStore failed: %08lx\n",
737 CertFreeCertificateContext(parent);
738 /* Check revocation and signature only */
739 flags = CERT_STORE_REVOCATION_FLAG | CERT_STORE_SIGNATURE_FLAG;
740 parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
741 ok(parent != NULL, "CertGetIssuerCertificateFromStore failed: %08lx\n",
743 /* Confusing: CERT_STORE_REVOCATION_FLAG succeeds when there is no CRL by
744 * setting CERT_STORE_NO_CRL_FLAG.
746 ok(flags == (CERT_STORE_REVOCATION_FLAG | CERT_STORE_NO_CRL_FLAG),
747 "Expected CERT_STORE_REVOCATION_FLAG | CERT_STORE_NO_CRL_FLAG, got %08lx\n",
750 CertFreeCertificateContext(parent);
751 /* Now check just the time */
752 flags = CERT_STORE_TIME_VALIDITY_FLAG;
753 parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
754 ok(parent != NULL, "CertGetIssuerCertificateFromStore failed: %08lx\n",
756 /* Oops: the child is not expired, so the time validity check actually
757 * succeeds, even though the signing cert is expired.
759 ok(!flags, "Expected check to succeed, got %08lx\n", flags);
761 CertFreeCertificateContext(parent);
763 CertFreeCertificateContext(child);
764 CertCloseStore(store, 0);
767 static void testCryptHashCert(void)
769 static const BYTE emptyHash[] = { 0xda, 0x39, 0xa3, 0xee, 0x5e, 0x6b, 0x4b,
770 0x0d, 0x32, 0x55, 0xbf, 0xef, 0x95, 0x60, 0x18, 0x90, 0xaf, 0xd8, 0x07,
772 static const BYTE knownHash[] = { 0xae, 0x9d, 0xbf, 0x6d, 0xf5, 0x46, 0xee,
773 0x8b, 0xc5, 0x7a, 0x13, 0xba, 0xc2, 0xb1, 0x04, 0xf2, 0xbf, 0x52, 0xa8,
775 static const BYTE toHash[] = "abcdefghijklmnopqrstuvwxyz0123456789.,;!?:";
778 DWORD hashLen = sizeof(hash);
780 /* NULL buffer and nonzero length crashes
781 ret = CryptHashCertificate(0, 0, 0, NULL, size, hash, &hashLen);
782 empty hash length also crashes
783 ret = CryptHashCertificate(0, 0, 0, buf, size, hash, NULL);
785 /* Test empty hash */
786 ret = CryptHashCertificate(0, 0, 0, toHash, sizeof(toHash), NULL,
788 ok(ret, "CryptHashCertificate failed: %08lx\n", GetLastError());
789 ok(hashLen == sizeof(hash), "Got unexpected size of hash %ld\n", hashLen);
790 /* Test with empty buffer */
791 ret = CryptHashCertificate(0, 0, 0, NULL, 0, hash, &hashLen);
792 ok(ret, "CryptHashCertificate failed: %08lx\n", GetLastError());
793 ok(!memcmp(hash, emptyHash, sizeof(emptyHash)),
794 "Unexpected hash of nothing\n");
795 /* Test a known value */
796 ret = CryptHashCertificate(0, 0, 0, toHash, sizeof(toHash), hash,
798 ok(ret, "CryptHashCertificate failed: %08lx\n", GetLastError());
799 ok(!memcmp(hash, knownHash, sizeof(knownHash)), "Unexpected hash\n");
802 static const WCHAR cspNameW[] = { 'W','i','n','e','C','r','y','p','t','T','e',
805 static void verifySig(HCRYPTPROV csp, const BYTE *toSign, size_t toSignLen,
806 const BYTE *sig, unsigned int sigLen)
809 BOOL ret = CryptCreateHash(csp, CALG_SHA1, 0, 0, &hash);
811 ok(ret, "CryptCreateHash failed: %08lx\n", GetLastError());
815 DWORD mySigSize = sizeof(mySig);
817 ret = CryptHashData(hash, toSign, toSignLen, 0);
818 ok(ret, "CryptHashData failed: %08lx\n", GetLastError());
819 /* use the A variant so the test can run on Win9x */
820 ret = CryptSignHashA(hash, AT_SIGNATURE, NULL, 0, mySig, &mySigSize);
821 ok(ret, "CryptSignHash failed: %08lx\n", GetLastError());
824 ok(mySigSize == sigLen, "Expected sig length %d, got %ld\n",
826 ok(!memcmp(mySig, sig, sigLen), "Unexpected signature\n");
828 CryptDestroyHash(hash);
832 /* Tests signing the certificate described by toBeSigned with the CSP passed in,
833 * using the algorithm with OID sigOID. The CSP is assumed to be empty, and a
834 * keyset named AT_SIGNATURE will be added to it. The signing key will be
835 * stored in *key, and the signature will be stored in sig. sigLen should be
838 static void testSignCert(HCRYPTPROV csp, const CRYPT_DATA_BLOB *toBeSigned,
839 LPCSTR sigOID, HCRYPTKEY *key, BYTE *sig, DWORD *sigLen)
843 CRYPT_ALGORITHM_IDENTIFIER algoID = { NULL, { 0, NULL } };
846 ret = CryptSignCertificate(0, 0, 0, NULL, 0, NULL, NULL, NULL, NULL);
847 ret = CryptSignCertificate(0, 0, 0, NULL, 0, NULL, NULL, NULL, &size);
848 ret = CryptSignCertificate(0, 0, 0, toBeSigned->pbData, toBeSigned->cbData,
849 NULL, NULL, NULL, &size);
851 ret = CryptSignCertificate(0, 0, 0, toBeSigned->pbData, toBeSigned->cbData,
852 &algoID, NULL, NULL, &size);
853 ok(!ret && GetLastError() == NTE_BAD_ALGID,
854 "Expected NTE_BAD_ALGID, got %08lx\n", GetLastError());
855 algoID.pszObjId = (LPSTR)sigOID;
856 ret = CryptSignCertificate(0, 0, 0, toBeSigned->pbData, toBeSigned->cbData,
857 &algoID, NULL, NULL, &size);
858 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
859 "Expected ERROR_INVALID_PARAMETER, got %08lx\n", GetLastError());
860 ret = CryptSignCertificate(0, AT_SIGNATURE, 0, toBeSigned->pbData,
861 toBeSigned->cbData, &algoID, NULL, NULL, &size);
862 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
863 "Expected ERROR_INVALID_PARAMETER, got %08lx\n", GetLastError());
865 /* No keys exist in the new CSP yet.. */
866 ret = CryptSignCertificate(csp, AT_SIGNATURE, 0, toBeSigned->pbData,
867 toBeSigned->cbData, &algoID, NULL, NULL, &size);
868 ok(!ret && (GetLastError() == NTE_BAD_KEYSET || GetLastError() ==
869 NTE_NO_KEY), "Expected NTE_BAD_KEYSET or NTE_NO_KEY, got %08lx\n",
871 ret = CryptGenKey(csp, AT_SIGNATURE, 0, key);
872 ok(ret, "CryptGenKey failed: %08lx\n", GetLastError());
875 ret = CryptSignCertificate(csp, AT_SIGNATURE, 0, toBeSigned->pbData,
876 toBeSigned->cbData, &algoID, NULL, NULL, &size);
877 ok(ret, "CryptSignCertificate failed: %08lx\n", GetLastError());
878 ok(size <= *sigLen, "Expected size <= %ld, got %ld\n", *sigLen, size);
881 ret = CryptSignCertificate(csp, AT_SIGNATURE, 0, toBeSigned->pbData,
882 toBeSigned->cbData, &algoID, NULL, sig, &size);
883 ok(ret, "CryptSignCertificate failed: %08lx\n", GetLastError());
887 verifySig(csp, toBeSigned->pbData, toBeSigned->cbData, sig,
894 static void testVerifyCertSig(HCRYPTPROV csp, const CRYPT_DATA_BLOB *toBeSigned,
895 LPCSTR sigOID, const BYTE *sig, DWORD sigLen)
897 CERT_SIGNED_CONTENT_INFO info;
902 if(pCryptVerifyCertificateSignatureEx) {
903 ret = pCryptVerifyCertificateSignatureEx(0, 0, 0, NULL, 0, NULL, 0, NULL);
904 ok(!ret && GetLastError() == E_INVALIDARG,
905 "Expected E_INVALIDARG, got %08lx\n", GetLastError());
906 ret = pCryptVerifyCertificateSignatureEx(csp, 0, 0, NULL, 0, NULL, 0, NULL);
907 ok(!ret && GetLastError() == E_INVALIDARG,
908 "Expected E_INVALIDARG, got %08lx\n", GetLastError());
909 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING, 0, NULL, 0,
911 ok(!ret && GetLastError() == E_INVALIDARG,
912 "Expected E_INVALIDARG, got %08lx\n", GetLastError());
914 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
915 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, NULL, 0, NULL, 0, NULL);
918 info.ToBeSigned.cbData = toBeSigned->cbData;
919 info.ToBeSigned.pbData = toBeSigned->pbData;
920 info.SignatureAlgorithm.pszObjId = (LPSTR)sigOID;
921 info.SignatureAlgorithm.Parameters.cbData = 0;
922 info.Signature.cbData = sigLen;
923 info.Signature.pbData = (BYTE *)sig;
924 info.Signature.cUnusedBits = 0;
925 ret = CryptEncodeObjectEx(X509_ASN_ENCODING, X509_CERT, &info,
926 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&cert, &size);
927 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
930 CRYPT_DATA_BLOB certBlob = { 0, NULL };
931 PCERT_PUBLIC_KEY_INFO pubKeyInfo = NULL;
933 if(pCryptVerifyCertificateSignatureEx) {
934 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
935 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob, 0, NULL, 0, NULL);
936 ok(!ret && GetLastError() == CRYPT_E_ASN1_EOD,
937 "Expected CRYPT_E_ASN1_EOD, got %08lx\n", GetLastError());
939 certBlob.pbData = (void *)0xdeadbeef;
940 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
941 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob, 0, NULL, 0, NULL);
942 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
943 "Expected STATUS_ACCESS_VIOLATION, got %08lx\n", GetLastError());
944 certBlob.cbData = size;
945 certBlob.pbData = cert;
946 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
947 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob, 0, NULL, 0, NULL);
948 ok(!ret && GetLastError() == E_INVALIDARG,
949 "Expected E_INVALIDARG, got %08lx\n", GetLastError());
950 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
951 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob,
952 CRYPT_VERIFY_CERT_SIGN_ISSUER_NULL, NULL, 0, NULL);
953 ok(!ret && GetLastError() == E_INVALIDARG,
954 "Expected E_INVALIDARG, got %08lx\n", GetLastError());
956 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
957 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob,
958 CRYPT_VERIFY_CERT_SIGN_ISSUER_PUBKEY, NULL, 0, NULL);
961 CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING,
962 (LPSTR)sigOID, 0, NULL, NULL, &size);
963 pubKeyInfo = HeapAlloc(GetProcessHeap(), 0, size);
966 ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE,
967 X509_ASN_ENCODING, (LPSTR)sigOID, 0, NULL, pubKeyInfo, &size);
968 ok(ret, "CryptExportKey failed: %08lx\n", GetLastError());
969 if (ret && pCryptVerifyCertificateSignatureEx)
971 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
972 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob,
973 CRYPT_VERIFY_CERT_SIGN_ISSUER_PUBKEY, pubKeyInfo, 0, NULL);
974 ok(ret, "CryptVerifyCertificateSignatureEx failed: %08lx\n",
977 HeapFree(GetProcessHeap(), 0, pubKeyInfo);
983 static const BYTE emptyCert[] = { 0x30, 0x00 };
985 static void testCertSigs(void)
988 CRYPT_DATA_BLOB toBeSigned = { sizeof(emptyCert), (LPBYTE)emptyCert };
992 DWORD sigSize = sizeof(sig);
994 /* Just in case a previous run failed, delete this thing */
995 CryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
997 ret = CryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
999 ok(ret, "CryptAcquireContext failed: %08lx\n", GetLastError());
1001 testSignCert(csp, &toBeSigned, szOID_RSA_SHA1RSA, &key, sig, &sigSize);
1002 testVerifyCertSig(csp, &toBeSigned, szOID_RSA_SHA1RSA, sig, sigSize);
1004 CryptDestroyKey(key);
1005 CryptReleaseContext(csp, 0);
1006 ret = CryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
1007 CRYPT_DELETEKEYSET);
1010 static void testCreateSelfSignCert(void)
1012 PCCERT_CONTEXT context;
1013 CERT_NAME_BLOB name = { sizeof(subjectName), (LPBYTE)subjectName };
1019 context = CertCreateSelfSignCertificate(0, NULL, 0, NULL, NULL, NULL, NULL,
1021 * Calling this with no first parameter creates a new key container, which
1022 * lasts beyond the test, so I don't test that. Nb: the generated key
1024 context = CertCreateSelfSignCertificate(0, &name, 0, NULL, NULL, NULL, NULL,
1029 CryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
1030 CRYPT_DELETEKEYSET);
1031 ret = CryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
1033 ok(ret, "CryptAcquireContext failed: %08lx\n", GetLastError());
1035 context = CertCreateSelfSignCertificate(csp, &name, 0, NULL, NULL, NULL,
1037 ok(!context && GetLastError() == NTE_NO_KEY,
1038 "Expected NTE_NO_KEY, got %08lx\n", GetLastError());
1039 ret = CryptGenKey(csp, AT_SIGNATURE, 0, &key);
1040 ok(ret, "CryptGenKey failed: %08lx\n", GetLastError());
1043 context = CertCreateSelfSignCertificate(csp, &name, 0, NULL, NULL, NULL,
1045 ok(context != NULL, "CertCreateSelfSignCertificate failed: %08lx\n",
1050 PCRYPT_KEY_PROV_INFO info;
1052 /* The context must have a key provider info property */
1053 ret = CertGetCertificateContextProperty(context,
1054 CERT_KEY_PROV_INFO_PROP_ID, NULL, &size);
1055 ok(ret && size, "Expected non-zero key provider info\n");
1058 info = HeapAlloc(GetProcessHeap(), 0, size);
1061 ret = CertGetCertificateContextProperty(context,
1062 CERT_KEY_PROV_INFO_PROP_ID, info, &size);
1063 ok(ret, "CertGetCertificateContextProperty failed: %08lx\n",
1067 /* Sanity-check the key provider */
1068 ok(!lstrcmpW(info->pwszContainerName, cspNameW),
1069 "Unexpected key container\n");
1070 ok(!lstrcmpW(info->pwszProvName, MS_DEF_PROV_W),
1071 "Unexpected provider\n");
1072 ok(info->dwKeySpec == AT_SIGNATURE,
1073 "Expected AT_SIGNATURE, got %ld\n", info->dwKeySpec);
1075 HeapFree(GetProcessHeap(), 0, info);
1079 CertFreeCertificateContext(context);
1082 CryptDestroyKey(key);
1085 CryptReleaseContext(csp, 0);
1086 ret = CryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
1087 CRYPT_DELETEKEYSET);
1090 static const LPCSTR keyUsages[] = { szOID_PKIX_KP_CODE_SIGNING,
1091 szOID_PKIX_KP_CLIENT_AUTH, szOID_RSA_RSA };
1093 static void testKeyUsage(void)
1096 PCCERT_CONTEXT context;
1099 /* Test base cases */
1100 ret = CertGetEnhancedKeyUsage(NULL, 0, NULL, NULL);
1101 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1102 "Expected ERROR_INVALID_PARAMETER, got %08lx\n", GetLastError());
1104 ret = CertGetEnhancedKeyUsage(NULL, 0, NULL, &size);
1105 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1106 "Expected ERROR_INVALID_PARAMETER, got %08lx\n", GetLastError());
1108 ret = CertGetEnhancedKeyUsage(NULL, 0, NULL, &size);
1109 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1110 "Expected ERROR_INVALID_PARAMETER, got %08lx\n", GetLastError());
1112 ret = CertSetEnhancedKeyUsage(NULL, NULL);
1113 usage.cUsageIdentifier = 0;
1114 ret = CertSetEnhancedKeyUsage(NULL, &usage);
1116 /* Test with a cert with no enhanced key usage extension */
1117 context = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert,
1119 ok(context != NULL, "CertCreateCertificateContext failed: %08lx\n",
1123 static const char oid[] = "1.2.3.4";
1124 BYTE buf[sizeof(CERT_ENHKEY_USAGE) + 2 * (sizeof(LPSTR) + sizeof(oid))];
1125 PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
1127 ret = CertGetEnhancedKeyUsage(context, 0, NULL, NULL);
1128 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1129 "Expected ERROR_INVALID_PARAMETER, got %08lx\n", GetLastError());
1131 ret = CertGetEnhancedKeyUsage(context, 0, NULL, &size);
1134 /* Windows 2000, ME, or later: even though it succeeded, we expect
1135 * CRYPT_E_NOT_FOUND, which indicates there is no enhanced key
1136 * usage set for this cert (which implies it's valid for all uses.)
1138 ok(GetLastError() == CRYPT_E_NOT_FOUND,
1139 "Expected CRYPT_E_NOT_FOUND, got %08lx\n", GetLastError());
1140 ok(size == sizeof(CERT_ENHKEY_USAGE), "Wrong size %ld\n", size);
1141 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
1142 ok(ret, "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
1143 ok(pUsage->cUsageIdentifier == 0, "Expected 0 usages, got %ld\n",
1144 pUsage->cUsageIdentifier);
1148 /* Windows NT, 95, or 98: it fails, and the last error is
1149 * CRYPT_E_NOT_FOUND.
1151 ok(GetLastError() == CRYPT_E_NOT_FOUND,
1152 "Expected CRYPT_E_NOT_FOUND, got %08lx\n", GetLastError());
1154 /* I can add a usage identifier when no key usage has been set */
1155 ret = CertAddEnhancedKeyUsageIdentifier(context, oid);
1156 ok(ret, "CertAddEnhancedKeyUsageIdentifier failed: %08lx\n",
1159 ret = CertGetEnhancedKeyUsage(context,
1160 CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG, pUsage, &size);
1161 ok(ret && GetLastError() == 0,
1162 "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
1163 ok(pUsage->cUsageIdentifier == 1, "Expected 1 usage, got %ld\n",
1164 pUsage->cUsageIdentifier);
1165 if (pUsage->cUsageIdentifier)
1166 ok(!strcmp(pUsage->rgpszUsageIdentifier[0], oid),
1167 "Expected %s, got %s\n", oid, pUsage->rgpszUsageIdentifier[0]);
1168 /* Now set an empty key usage */
1169 pUsage->cUsageIdentifier = 0;
1170 ret = CertSetEnhancedKeyUsage(context, pUsage);
1171 ok(ret, "CertSetEnhancedKeyUsage failed: %08lx\n", GetLastError());
1172 /* Shouldn't find it in the cert */
1174 ret = CertGetEnhancedKeyUsage(context,
1175 CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, pUsage, &size);
1176 ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
1177 "Expected CRYPT_E_NOT_FOUND, got %08lx\n", GetLastError());
1178 /* Should find it as an extended property */
1179 ret = CertGetEnhancedKeyUsage(context,
1180 CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG, pUsage, &size);
1181 ok(ret && GetLastError() == 0,
1182 "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
1183 ok(pUsage->cUsageIdentifier == 0, "Expected 0 usages, got %ld\n",
1184 pUsage->cUsageIdentifier);
1185 /* Should find it as either */
1186 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
1187 ok(ret && GetLastError() == 0,
1188 "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
1189 ok(pUsage->cUsageIdentifier == 0, "Expected 0 usages, got %ld\n",
1190 pUsage->cUsageIdentifier);
1191 /* Add a usage identifier */
1192 ret = CertAddEnhancedKeyUsageIdentifier(context, oid);
1193 ok(ret, "CertAddEnhancedKeyUsageIdentifier failed: %08lx\n",
1196 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
1197 ok(ret && GetLastError() == 0,
1198 "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
1199 ok(pUsage->cUsageIdentifier == 1, "Expected 1 identifier, got %ld\n",
1200 pUsage->cUsageIdentifier);
1201 if (pUsage->cUsageIdentifier)
1202 ok(!strcmp(pUsage->rgpszUsageIdentifier[0], oid),
1203 "Expected %s, got %s\n", oid, pUsage->rgpszUsageIdentifier[0]);
1204 /* Yep, I can re-add the same usage identifier */
1205 ret = CertAddEnhancedKeyUsageIdentifier(context, oid);
1206 ok(ret, "CertAddEnhancedKeyUsageIdentifier failed: %08lx\n",
1209 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
1210 ok(ret && GetLastError() == 0,
1211 "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
1212 ok(pUsage->cUsageIdentifier == 2, "Expected 2 identifiers, got %ld\n",
1213 pUsage->cUsageIdentifier);
1214 if (pUsage->cUsageIdentifier)
1215 ok(!strcmp(pUsage->rgpszUsageIdentifier[0], oid),
1216 "Expected %s, got %s\n", oid, pUsage->rgpszUsageIdentifier[0]);
1217 if (pUsage->cUsageIdentifier >= 2)
1218 ok(!strcmp(pUsage->rgpszUsageIdentifier[1], oid),
1219 "Expected %s, got %s\n", oid, pUsage->rgpszUsageIdentifier[1]);
1220 /* Now set a NULL extended property--this deletes the property. */
1221 ret = CertSetEnhancedKeyUsage(context, NULL);
1222 ok(ret, "CertSetEnhancedKeyUsage failed: %08lx\n", GetLastError());
1223 SetLastError(0xbaadcafe);
1225 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
1226 ok(GetLastError() == CRYPT_E_NOT_FOUND,
1227 "Expected CRYPT_E_NOT_FOUND, got %08lx\n", GetLastError());
1229 CertFreeCertificateContext(context);
1231 /* Now test with a cert with an enhanced key usage extension */
1232 context = CertCreateCertificateContext(X509_ASN_ENCODING, certWithUsage,
1233 sizeof(certWithUsage));
1234 ok(context != NULL, "CertCreateCertificateContext failed: %08lx\n",
1239 DWORD bufSize = 0, i;
1241 /* The size may depend on what flags are used to query it, so I
1242 * realloc the buffer for each test.
1244 ret = CertGetEnhancedKeyUsage(context,
1245 CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, NULL, &bufSize);
1246 ok(ret, "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
1247 buf = HeapAlloc(GetProcessHeap(), 0, bufSize);
1250 PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
1252 /* Should find it in the cert */
1254 ret = CertGetEnhancedKeyUsage(context,
1255 CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, pUsage, &size);
1256 ok(ret && GetLastError() == 0,
1257 "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
1258 ok(pUsage->cUsageIdentifier == 3, "Expected 3 usages, got %ld\n",
1259 pUsage->cUsageIdentifier);
1260 for (i = 0; i < pUsage->cUsageIdentifier; i++)
1261 ok(!strcmp(pUsage->rgpszUsageIdentifier[i], keyUsages[i]),
1262 "Expected %s, got %s\n", keyUsages[i],
1263 pUsage->rgpszUsageIdentifier[i]);
1264 HeapFree(GetProcessHeap(), 0, buf);
1266 ret = CertGetEnhancedKeyUsage(context, 0, NULL, &bufSize);
1267 ok(ret, "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
1268 buf = HeapAlloc(GetProcessHeap(), 0, bufSize);
1271 PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
1273 /* Should find it as either */
1275 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
1276 /* In Windows, GetLastError returns CRYPT_E_NOT_FOUND not found
1277 * here, even though the return is successful and the usage id
1278 * count is positive. I don't enforce that here.
1281 "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
1282 ok(pUsage->cUsageIdentifier == 3, "Expected 3 usages, got %ld\n",
1283 pUsage->cUsageIdentifier);
1284 for (i = 0; i < pUsage->cUsageIdentifier; i++)
1285 ok(!strcmp(pUsage->rgpszUsageIdentifier[i], keyUsages[i]),
1286 "Expected %s, got %s\n", keyUsages[i],
1287 pUsage->rgpszUsageIdentifier[i]);
1288 HeapFree(GetProcessHeap(), 0, buf);
1290 /* Shouldn't find it as an extended property */
1291 ret = CertGetEnhancedKeyUsage(context,
1292 CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG, NULL, &size);
1293 ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
1294 "Expected CRYPT_E_NOT_FOUND, got %08lx\n", GetLastError());
1295 /* Adding a usage identifier overrides the cert's usage!? */
1296 ret = CertAddEnhancedKeyUsageIdentifier(context, szOID_RSA_RSA);
1297 ok(ret, "CertAddEnhancedKeyUsageIdentifier failed: %08lx\n",
1299 ret = CertGetEnhancedKeyUsage(context, 0, NULL, &bufSize);
1300 ok(ret, "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
1301 buf = HeapAlloc(GetProcessHeap(), 0, bufSize);
1304 PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
1306 /* Should find it as either */
1308 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
1310 "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
1311 ok(pUsage->cUsageIdentifier == 1, "Expected 1 usage, got %ld\n",
1312 pUsage->cUsageIdentifier);
1313 ok(!strcmp(pUsage->rgpszUsageIdentifier[0], szOID_RSA_RSA),
1314 "Expected %s, got %s\n", szOID_RSA_RSA,
1315 pUsage->rgpszUsageIdentifier[0]);
1316 HeapFree(GetProcessHeap(), 0, buf);
1318 /* But querying the cert directly returns its usage */
1319 ret = CertGetEnhancedKeyUsage(context,
1320 CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, NULL, &bufSize);
1321 ok(ret, "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
1322 buf = HeapAlloc(GetProcessHeap(), 0, bufSize);
1325 PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
1328 ret = CertGetEnhancedKeyUsage(context,
1329 CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, pUsage, &size);
1331 "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
1332 ok(pUsage->cUsageIdentifier == 3, "Expected 3 usages, got %ld\n",
1333 pUsage->cUsageIdentifier);
1334 for (i = 0; i < pUsage->cUsageIdentifier; i++)
1335 ok(!strcmp(pUsage->rgpszUsageIdentifier[i], keyUsages[i]),
1336 "Expected %s, got %s\n", keyUsages[i],
1337 pUsage->rgpszUsageIdentifier[i]);
1338 HeapFree(GetProcessHeap(), 0, buf);
1340 /* And removing the only usage identifier in the extended property
1341 * results in the cert's key usage being found.
1343 ret = CertRemoveEnhancedKeyUsageIdentifier(context, szOID_RSA_RSA);
1344 ok(ret, "CertRemoveEnhancedKeyUsage failed: %08lx\n", GetLastError());
1345 ret = CertGetEnhancedKeyUsage(context, 0, NULL, &bufSize);
1346 ok(ret, "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
1347 buf = HeapAlloc(GetProcessHeap(), 0, bufSize);
1350 PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
1352 /* Should find it as either */
1354 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
1356 "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
1357 ok(pUsage->cUsageIdentifier == 3, "Expected 3 usages, got %ld\n",
1358 pUsage->cUsageIdentifier);
1359 for (i = 0; i < pUsage->cUsageIdentifier; i++)
1360 ok(!strcmp(pUsage->rgpszUsageIdentifier[i], keyUsages[i]),
1361 "Expected %s, got %s\n", keyUsages[i],
1362 pUsage->rgpszUsageIdentifier[i]);
1363 HeapFree(GetProcessHeap(), 0, buf);
1366 CertFreeCertificateContext(context);
1370 static void testCompareCertName(void)
1372 static const BYTE bogus[] = { 1, 2, 3, 4 };
1373 static const BYTE bogusPrime[] = { 0, 1, 2, 3, 4 };
1374 static const BYTE emptyPrime[] = { 0x30, 0x00, 0x01 };
1376 CERT_NAME_BLOB blob1, blob2;
1379 ret = CertCompareCertificateName(0, NULL, NULL);
1381 /* An empty name checks against itself.. */
1382 blob1.pbData = (LPBYTE)emptyCert;
1383 blob1.cbData = sizeof(emptyCert);
1384 ret = CertCompareCertificateName(0, &blob1, &blob1);
1385 ok(ret, "CertCompareCertificateName failed: %08lx\n", GetLastError());
1386 /* It doesn't have to be a valid encoded name.. */
1387 blob1.pbData = (LPBYTE)bogus;
1388 blob1.cbData = sizeof(bogus);
1389 ret = CertCompareCertificateName(0, &blob1, &blob1);
1390 ok(ret, "CertCompareCertificateName failed: %08lx\n", GetLastError());
1391 /* Leading zeroes matter.. */
1392 blob2.pbData = (LPBYTE)bogusPrime;
1393 blob2.cbData = sizeof(bogusPrime);
1394 ret = CertCompareCertificateName(0, &blob1, &blob2);
1395 ok(!ret, "Expected failure\n");
1396 /* As do trailing extra bytes. */
1397 blob2.pbData = (LPBYTE)emptyPrime;
1398 blob2.cbData = sizeof(emptyPrime);
1399 ret = CertCompareCertificateName(0, &blob1, &blob2);
1400 ok(!ret, "Expected failure\n");
1403 static const BYTE int1[] = { 0x88, 0xff, 0xff, 0xff };
1404 static const BYTE int2[] = { 0x88, 0xff };
1405 static const BYTE int3[] = { 0x23, 0xff };
1406 static const BYTE int4[] = { 0x7f, 0x00 };
1407 static const BYTE int5[] = { 0x7f };
1408 static const BYTE int6[] = { 0x80, 0x00, 0x00, 0x00 };
1409 static const BYTE int7[] = { 0x80, 0x00 };
1413 CRYPT_INTEGER_BLOB blob1;
1414 CRYPT_INTEGER_BLOB blob2;
1417 { { sizeof(int1), (LPBYTE)int1 }, { sizeof(int2), (LPBYTE)int2 }, TRUE },
1418 { { sizeof(int3), (LPBYTE)int3 }, { sizeof(int3), (LPBYTE)int3 }, TRUE },
1419 { { sizeof(int4), (LPBYTE)int4 }, { sizeof(int5), (LPBYTE)int5 }, TRUE },
1420 { { sizeof(int6), (LPBYTE)int6 }, { sizeof(int7), (LPBYTE)int7 }, TRUE },
1421 { { sizeof(int1), (LPBYTE)int1 }, { sizeof(int7), (LPBYTE)int7 }, FALSE },
1424 static void testCompareIntegerBlob(void)
1429 for (i = 0; i < sizeof(intBlobs) / sizeof(intBlobs[0]); i++)
1431 ret = CertCompareIntegerBlob(&intBlobs[i].blob1, &intBlobs[i].blob2);
1432 ok(ret == intBlobs[i].areEqual,
1433 "%ld: expected blobs %s compare\n", i, intBlobs[i].areEqual ?
1438 static void testComparePublicKeyInfo(void)
1441 CERT_PUBLIC_KEY_INFO info1 = { { 0 } }, info2 = { { 0 } };
1442 static CHAR oid_rsa_rsa[] = szOID_RSA_RSA;
1443 static CHAR oid_rsa_sha1rsa[] = szOID_RSA_SHA1RSA;
1444 static CHAR oid_x957_dsa[] = szOID_X957_DSA;
1445 static const BYTE bits1[] = { 1, 0 };
1446 static const BYTE bits2[] = { 0 };
1447 static const BYTE bits3[] = { 1 };
1450 ret = CertComparePublicKeyInfo(0, NULL, NULL);
1452 /* Empty public keys compare */
1453 ret = CertComparePublicKeyInfo(0, &info1, &info2);
1454 ok(ret, "CertComparePublicKeyInfo failed: %08lx\n", GetLastError());
1455 /* Different OIDs appear to compare */
1456 info1.Algorithm.pszObjId = oid_rsa_rsa;
1457 info2.Algorithm.pszObjId = oid_rsa_sha1rsa;
1458 ret = CertComparePublicKeyInfo(0, &info1, &info2);
1459 ok(ret, "CertComparePublicKeyInfo failed: %08lx\n", GetLastError());
1460 info2.Algorithm.pszObjId = oid_x957_dsa;
1461 ret = CertComparePublicKeyInfo(0, &info1, &info2);
1462 ok(ret, "CertComparePublicKeyInfo failed: %08lx\n", GetLastError());
1463 info1.PublicKey.cbData = sizeof(bits1);
1464 info1.PublicKey.pbData = (LPBYTE)bits1;
1465 info1.PublicKey.cUnusedBits = 0;
1466 info2.PublicKey.cbData = sizeof(bits1);
1467 info2.PublicKey.pbData = (LPBYTE)bits1;
1468 info2.PublicKey.cUnusedBits = 0;
1469 ret = CertComparePublicKeyInfo(0, &info1, &info2);
1470 ok(ret, "CertComparePublicKeyInfo failed: %08lx\n", GetLastError());
1471 /* Even though they compare in their used bits, these do not compare */
1472 info1.PublicKey.cbData = sizeof(bits2);
1473 info1.PublicKey.pbData = (LPBYTE)bits2;
1474 info1.PublicKey.cUnusedBits = 0;
1475 info2.PublicKey.cbData = sizeof(bits3);
1476 info2.PublicKey.pbData = (LPBYTE)bits3;
1477 info2.PublicKey.cUnusedBits = 1;
1478 ret = CertComparePublicKeyInfo(0, &info1, &info2);
1479 /* Simple (non-comparing) case */
1480 ok(!ret, "Expected keys not to compare\n");
1481 info2.PublicKey.cbData = sizeof(bits1);
1482 info2.PublicKey.pbData = (LPBYTE)bits1;
1483 info2.PublicKey.cUnusedBits = 0;
1484 ret = CertComparePublicKeyInfo(0, &info1, &info2);
1485 ok(!ret, "Expected keys not to compare\n");
1488 void testCompareCert(void)
1490 CERT_INFO info1 = { 0 }, info2 = { 0 };
1494 ret = CertCompareCertificate(X509_ASN_ENCODING, NULL, NULL);
1497 /* Certs with the same issuer and serial number are equal, even if they
1498 * differ in other respects (like subject).
1500 info1.SerialNumber.pbData = (LPBYTE)serialNum;
1501 info1.SerialNumber.cbData = sizeof(serialNum);
1502 info1.Issuer.pbData = (LPBYTE)subjectName;
1503 info1.Issuer.cbData = sizeof(subjectName);
1504 info1.Subject.pbData = (LPBYTE)subjectName2;
1505 info1.Subject.cbData = sizeof(subjectName2);
1506 info2.SerialNumber.pbData = (LPBYTE)serialNum;
1507 info2.SerialNumber.cbData = sizeof(serialNum);
1508 info2.Issuer.pbData = (LPBYTE)subjectName;
1509 info2.Issuer.cbData = sizeof(subjectName);
1510 info2.Subject.pbData = (LPBYTE)subjectName;
1511 info2.Subject.cbData = sizeof(subjectName);
1512 ret = CertCompareCertificate(X509_ASN_ENCODING, &info1, &info2);
1513 ok(ret, "Expected certs to be equal\n");
1515 info2.Issuer.pbData = (LPBYTE)subjectName2;
1516 info2.Issuer.cbData = sizeof(subjectName2);
1517 ret = CertCompareCertificate(X509_ASN_ENCODING, &info1, &info2);
1518 ok(!ret, "Expected certs not to be equal\n");
1521 static void testVerifySubjectCert(void)
1525 PCCERT_CONTEXT context1, context2;
1528 ret = CertVerifySubjectCertificateContext(NULL, NULL, NULL);
1531 ret = CertVerifySubjectCertificateContext(NULL, NULL, &flags);
1532 ok(ret, "CertVerifySubjectCertificateContext failed; %08lx\n",
1534 flags = CERT_STORE_NO_CRL_FLAG;
1535 ret = CertVerifySubjectCertificateContext(NULL, NULL, &flags);
1536 ok(!ret && GetLastError() == E_INVALIDARG,
1537 "Expected E_INVALIDARG, got %08lx\n", GetLastError());
1540 context1 = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert,
1542 ret = CertVerifySubjectCertificateContext(NULL, context1, &flags);
1543 ok(ret, "CertVerifySubjectCertificateContext failed; %08lx\n",
1545 ret = CertVerifySubjectCertificateContext(context1, NULL, &flags);
1546 ok(ret, "CertVerifySubjectCertificateContext failed; %08lx\n",
1548 ret = CertVerifySubjectCertificateContext(context1, context1, &flags);
1549 ok(ret, "CertVerifySubjectCertificateContext failed; %08lx\n",
1552 context2 = CertCreateCertificateContext(X509_ASN_ENCODING,
1553 bigCertWithDifferentSubject, sizeof(bigCertWithDifferentSubject));
1554 SetLastError(0xdeadbeef);
1555 ret = CertVerifySubjectCertificateContext(context1, context2, &flags);
1556 ok(ret, "CertVerifySubjectCertificateContext failed; %08lx\n",
1558 flags = CERT_STORE_REVOCATION_FLAG;
1559 ret = CertVerifySubjectCertificateContext(context1, context2, &flags);
1560 ok(ret, "CertVerifySubjectCertificateContext failed; %08lx\n",
1562 ok(flags == (CERT_STORE_REVOCATION_FLAG | CERT_STORE_NO_CRL_FLAG),
1563 "Expected CERT_STORE_REVOCATION_FLAG | CERT_STORE_NO_CRL_FLAG, got %08lx\n",
1565 flags = CERT_STORE_SIGNATURE_FLAG;
1566 ret = CertVerifySubjectCertificateContext(context1, context2, &flags);
1567 ok(ret, "CertVerifySubjectCertificateContext failed; %08lx\n",
1569 ok(flags == CERT_STORE_SIGNATURE_FLAG,
1570 "Expected CERT_STORE_SIGNATURE_FLAG, got %08lx\n", flags);
1571 CertFreeCertificateContext(context2);
1573 CertFreeCertificateContext(context1);
1578 init_function_pointers();
1581 testCertProperties();
1584 testGetSubjectCert();
1585 testGetIssuerCert();
1587 testCryptHashCert();
1589 testCreateSelfSignCert();
1591 testCompareCertName();
1592 testCompareIntegerBlob();
1593 testComparePublicKeyInfo();
1595 testVerifySubjectCert();