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)
135 HCERTSTORE collection;
136 PCCERT_CONTEXT context;
139 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
140 CERT_STORE_CREATE_NEW_FLAG, NULL);
141 ok(store != NULL, "CertOpenStore failed: %ld\n", GetLastError());
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);
292 static void checkHash(const BYTE *data, DWORD dataLen, ALG_ID algID,
293 PCCERT_CONTEXT context, DWORD propID)
295 BYTE hash[20] = { 0 }, hashProperty[20];
299 memset(hash, 0, sizeof(hash));
300 memset(hashProperty, 0, sizeof(hashProperty));
302 ret = CryptHashCertificate(0, algID, 0, data, dataLen, hash, &size);
303 ok(ret, "CryptHashCertificate failed: %08lx\n", GetLastError());
304 ret = CertGetCertificateContextProperty(context, propID, hashProperty,
306 ok(ret, "CertGetCertificateContextProperty failed: %08lx\n",
308 ok(!memcmp(hash, hashProperty, size), "Unexpected hash for property %ld\n",
312 static const WCHAR cspNameW[] = { 'W','i','n','e','C','r','y','p','t','T','e',
315 static void testCertProperties(void)
317 PCCERT_CONTEXT context = CertCreateCertificateContext(X509_ASN_ENCODING,
318 bigCert, sizeof(bigCert));
319 DWORD propID, numProps, access, size;
321 BYTE hash[20] = { 0 }, hashProperty[20];
322 CRYPT_DATA_BLOB blob;
323 CERT_KEY_CONTEXT keyContext;
326 ok(context != NULL, "CertCreateCertificateContext failed: %08lx\n",
332 propID = CertEnumCertificateContextProperties(NULL, 0);
338 propID = CertEnumCertificateContextProperties(context, propID);
341 } while (propID != 0);
342 ok(numProps == 0, "Expected 0 properties, got %ld\n", numProps);
344 /* Tests with a NULL cert context. Prop ID 0 fails.. */
345 ret = CertSetCertificateContextProperty(NULL, 0, 0, NULL);
346 ok(!ret && GetLastError() == E_INVALIDARG,
347 "Expected E_INVALIDARG, got %08lx\n", GetLastError());
348 /* while this just crashes.
349 ret = CertSetCertificateContextProperty(NULL,
350 CERT_KEY_PROV_HANDLE_PROP_ID, 0, NULL);
353 ret = CertSetCertificateContextProperty(context, 0, 0, NULL);
354 ok(!ret && GetLastError() == E_INVALIDARG,
355 "Expected E_INVALIDARG, got %08lx\n", GetLastError());
356 /* Can't set the cert property directly, this crashes.
357 ret = CertSetCertificateContextProperty(context,
358 CERT_CERT_PROP_ID, 0, bigCert2);
362 ret = CertGetCertificateContextProperty(context,
363 CERT_ACCESS_STATE_PROP_ID, 0, NULL);
364 ret = CertGetCertificateContextProperty(context, CERT_HASH_PROP_ID,
366 ret = CertGetCertificateContextProperty(context, CERT_HASH_PROP_ID,
371 ret = CertGetCertificateContextProperty(context,
372 CERT_KEY_PROV_INFO_PROP_ID, NULL, &size);
373 ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
374 "Expected CRYPT_E_NOT_FOUND, got %08lx\n", GetLastError());
375 /* And, an implicit property */
376 size = sizeof(access);
377 ret = CertGetCertificateContextProperty(context,
378 CERT_ACCESS_STATE_PROP_ID, &access, &size);
379 ok(ret, "CertGetCertificateContextProperty failed: %08lx\n",
381 ok(!(access & CERT_ACCESS_STATE_WRITE_PERSIST_FLAG),
382 "Didn't expect a persisted cert\n");
383 /* Trying to set this "read only" property crashes.
384 access |= CERT_ACCESS_STATE_WRITE_PERSIST_FLAG;
385 ret = CertSetCertificateContextProperty(context,
386 CERT_ACCESS_STATE_PROP_ID, 0, &access);
389 /* Can I set the hash to an invalid hash? */
391 blob.cbData = sizeof(hash);
392 ret = CertSetCertificateContextProperty(context, CERT_HASH_PROP_ID, 0,
394 ok(ret, "CertSetCertificateContextProperty failed: %08lx\n",
396 size = sizeof(hashProperty);
397 ret = CertGetCertificateContextProperty(context, CERT_HASH_PROP_ID,
398 hashProperty, &size);
399 ok(!memcmp(hashProperty, hash, sizeof(hash)), "Unexpected hash\n");
400 /* Delete the (bogus) hash, and get the real one */
401 ret = CertSetCertificateContextProperty(context, CERT_HASH_PROP_ID, 0,
403 ok(ret, "CertSetCertificateContextProperty failed: %08lx\n",
405 checkHash(bigCert, sizeof(bigCert), CALG_SHA1, context,
408 /* Now that the hash property is set, we should get one property when
414 propID = CertEnumCertificateContextProperties(context, propID);
417 } while (propID != 0);
418 ok(numProps == 1, "Expected 1 properties, got %ld\n", numProps);
420 /* Check a few other implicit properties */
421 checkHash(bigCert, sizeof(bigCert), CALG_MD5, context,
422 CERT_MD5_HASH_PROP_ID);
424 context->pCertInfo->Subject.pbData,
425 context->pCertInfo->Subject.cbData,
426 CALG_MD5, context, CERT_SUBJECT_NAME_MD5_HASH_PROP_ID);
428 context->pCertInfo->SubjectPublicKeyInfo.PublicKey.pbData,
429 context->pCertInfo->SubjectPublicKeyInfo.PublicKey.cbData,
430 CALG_MD5, context, CERT_SUBJECT_PUBLIC_KEY_MD5_HASH_PROP_ID);
432 /* Test key identifiers and handles and such */
434 ret = CertGetCertificateContextProperty(context,
435 CERT_KEY_IDENTIFIER_PROP_ID, NULL, &size);
436 ok(!ret && GetLastError() == ERROR_INVALID_DATA,
437 "Expected ERROR_INVALID_DATA, got %08lx\n", GetLastError());
438 size = sizeof(CERT_KEY_CONTEXT);
439 ret = CertGetCertificateContextProperty(context,
440 CERT_KEY_IDENTIFIER_PROP_ID, NULL, &size);
441 ok(!ret && GetLastError() == ERROR_INVALID_DATA,
442 "Expected ERROR_INVALID_DATA, got %08lx\n", GetLastError());
443 ret = CertGetCertificateContextProperty(context,
444 CERT_KEY_IDENTIFIER_PROP_ID, &keyContext, &size);
445 ok(!ret && GetLastError() == ERROR_INVALID_DATA,
446 "Expected ERROR_INVALID_DATA, got %08lx\n", GetLastError());
447 /* Key context with an invalid size */
448 keyContext.cbSize = 0;
449 ret = CertSetCertificateContextProperty(context,
450 CERT_KEY_IDENTIFIER_PROP_ID, 0, &keyContext);
451 ok(ret, "CertSetCertificateContextProperty failed: %08lx\n",
453 size = sizeof(keyContext);
454 ret = CertGetCertificateContextProperty(context,
455 CERT_KEY_IDENTIFIER_PROP_ID, &keyContext, &size);
456 ok(ret, "CertGetCertificateContextProperty failed: %08lx\n",
458 keyContext.cbSize = sizeof(keyContext);
459 keyContext.hCryptProv = 0;
460 keyContext.dwKeySpec = AT_SIGNATURE;
462 ret = CertSetCertificateContextProperty(context,
463 CERT_KEY_IDENTIFIER_PROP_ID, 0, &keyContext);
464 ret = CertSetCertificateContextProperty(context,
465 CERT_KEY_IDENTIFIER_PROP_ID, CERT_STORE_NO_CRYPT_RELEASE_FLAG,
468 ret = CryptAcquireContextW(&csp, cspNameW,
469 MS_DEF_PROV_W, PROV_RSA_FULL, CRYPT_NEWKEYSET);
470 ok(ret, "CryptAcquireContextW failed: %08lx\n", GetLastError());
471 keyContext.hCryptProv = csp;
472 ret = CertSetCertificateContextProperty(context,
473 CERT_KEY_CONTEXT_PROP_ID, 0, &keyContext);
474 ok(ret, "CertSetCertificateContextProperty failed: %08lx\n",
476 /* Now that that's set, the key prov handle property is also gettable.
478 size = sizeof(DWORD);
479 ret = CertGetCertificateContextProperty(context,
480 CERT_KEY_PROV_HANDLE_PROP_ID, &keyContext.hCryptProv, &size);
481 ok(ret, "Expected to get the CERT_KEY_PROV_HANDLE_PROP_ID, got %08lx\n",
483 /* Remove the key prov handle property.. */
484 ret = CertSetCertificateContextProperty(context,
485 CERT_KEY_PROV_HANDLE_PROP_ID, 0, NULL);
486 ok(ret, "CertSetCertificateContextProperty failed: %08lx\n",
488 /* and the key context's CSP is set to NULL. */
489 size = sizeof(keyContext);
490 ret = CertGetCertificateContextProperty(context,
491 CERT_KEY_CONTEXT_PROP_ID, &keyContext, &size);
492 ok(ret, "CertGetCertificateContextProperty failed: %08lx\n",
494 ok(keyContext.hCryptProv == 0, "Expected no hCryptProv\n");
496 CryptReleaseContext(csp, 0);
498 CertFreeCertificateContext(context);
501 static void testDupCert(void)
504 PCCERT_CONTEXT context, dupContext;
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());
513 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
514 bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, &context);
515 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n",
517 ok(context != NULL, "Expected a valid cert context\n");
520 ok(context->cbCertEncoded == sizeof(bigCert),
521 "Wrong cert size %ld\n", context->cbCertEncoded);
522 ok(!memcmp(context->pbCertEncoded, bigCert, sizeof(bigCert)),
523 "Unexpected encoded cert in context\n");
524 ok(context->hCertStore == store, "Unexpected store\n");
526 dupContext = CertDuplicateCertificateContext(context);
527 ok(dupContext != NULL, "Expected valid duplicate\n");
528 /* Not only is it a duplicate, it's identical: the address is the
531 ok(dupContext == context, "Expected identical context addresses\n");
532 CertFreeCertificateContext(dupContext);
533 CertFreeCertificateContext(context);
535 CertCloseStore(store, 0);
538 static void testFindCert(void)
541 PCCERT_CONTEXT context = NULL;
543 CERT_INFO certInfo = { 0 };
544 CRYPT_HASH_BLOB blob;
546 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
547 CERT_STORE_CREATE_NEW_FLAG, NULL);
548 ok(store != NULL, "CertOpenStore failed: %ld\n", GetLastError());
552 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
553 bigCert, sizeof(bigCert), CERT_STORE_ADD_NEW, NULL);
554 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n",
556 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
557 bigCert2, sizeof(bigCert2), CERT_STORE_ADD_NEW, NULL);
558 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n",
560 /* This has the same name as bigCert */
561 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
562 certWithUsage, sizeof(certWithUsage), CERT_STORE_ADD_NEW, NULL);
563 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n",
567 context = CertFindCertificateInStore(NULL, 0, 0, 0, NULL, NULL);
570 /* Check first cert's there, by issuer */
571 certInfo.Subject.pbData = (LPBYTE)subjectName;
572 certInfo.Subject.cbData = sizeof(subjectName);
573 certInfo.SerialNumber.pbData = (LPBYTE)serialNum;
574 certInfo.SerialNumber.cbData = sizeof(serialNum);
575 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
576 CERT_FIND_ISSUER_NAME, &certInfo.Subject, NULL);
577 ok(context != NULL, "CertFindCertificateInStore failed: %08lx\n",
581 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
582 CERT_FIND_ISSUER_NAME, &certInfo.Subject, context);
583 ok(context != NULL, "Expected more than one cert\n");
586 context = CertFindCertificateInStore(store, X509_ASN_ENCODING,
587 0, CERT_FIND_ISSUER_NAME, &certInfo.Subject, context);
588 ok(context == NULL, "Expected precisely two certs\n");
592 /* Check second cert's there as well, by subject name */
593 certInfo.Subject.pbData = (LPBYTE)subjectName2;
594 certInfo.Subject.cbData = sizeof(subjectName2);
595 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
596 CERT_FIND_SUBJECT_NAME, &certInfo.Subject, NULL);
597 ok(context != NULL, "CertFindCertificateInStore failed: %08lx\n",
601 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
602 CERT_FIND_SUBJECT_NAME, &certInfo.Subject, context);
603 ok(context == NULL, "Expected one cert only\n");
606 /* Strange but true: searching for the subject cert requires you to set
607 * the issuer, not the subject
609 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
610 CERT_FIND_SUBJECT_CERT, &certInfo.Subject, NULL);
611 ok(context == NULL, "Expected no certificate\n");
612 certInfo.Subject.pbData = NULL;
613 certInfo.Subject.cbData = 0;
614 certInfo.Issuer.pbData = (LPBYTE)subjectName2;
615 certInfo.Issuer.cbData = sizeof(subjectName2);
616 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
617 CERT_FIND_SUBJECT_CERT, &certInfo, NULL);
618 ok(context != NULL, "CertFindCertificateInStore failed: %08lx\n",
622 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
623 CERT_FIND_SUBJECT_CERT, &certInfo.Subject, context);
624 ok(context == NULL, "Expected one cert only\n");
627 /* The nice thing about hashes, they're unique */
628 blob.pbData = (LPBYTE)bigCertHash;
629 blob.cbData = sizeof(bigCertHash);
630 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
631 CERT_FIND_SHA1_HASH, &blob, NULL);
632 ok(context != NULL, "CertFindCertificateInStore failed: %08lx\n",
636 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
637 CERT_FIND_SHA1_HASH, &certInfo.Subject, context);
638 ok(context == NULL, "Expected one cert only\n");
641 CertCloseStore(store, 0);
644 static void testGetSubjectCert(void)
647 PCCERT_CONTEXT context1, context2;
648 CERT_INFO info = { 0 };
651 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
652 CERT_STORE_CREATE_NEW_FLAG, NULL);
653 ok(store != NULL, "CertOpenStore failed: %ld\n", GetLastError());
657 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
658 bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL);
659 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n",
661 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
662 bigCert2, sizeof(bigCert2), CERT_STORE_ADD_NEW, &context1);
663 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n",
665 ok(context1 != NULL, "Expected a context\n");
666 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
667 certWithUsage, sizeof(certWithUsage), CERT_STORE_ADD_NEW, NULL);
668 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n",
671 context2 = CertGetSubjectCertificateFromStore(store, X509_ASN_ENCODING,
673 ok(!context2 && GetLastError() == E_INVALIDARG,
674 "Expected E_INVALIDARG, got %08lx\n", GetLastError());
675 context2 = CertGetSubjectCertificateFromStore(store, X509_ASN_ENCODING,
677 ok(!context2 && GetLastError() == CRYPT_E_NOT_FOUND,
678 "Expected CRYPT_E_NOT_FOUND, got %08lx\n", GetLastError());
679 info.SerialNumber.cbData = sizeof(serialNum);
680 info.SerialNumber.pbData = (LPBYTE)serialNum;
681 context2 = CertGetSubjectCertificateFromStore(store, X509_ASN_ENCODING,
683 ok(!context2 && GetLastError() == CRYPT_E_NOT_FOUND,
684 "Expected CRYPT_E_NOT_FOUND, got %08lx\n", GetLastError());
685 info.Issuer.cbData = sizeof(subjectName2);
686 info.Issuer.pbData = (LPBYTE)subjectName2;
687 context2 = CertGetSubjectCertificateFromStore(store, X509_ASN_ENCODING,
690 "CertGetSubjectCertificateFromStore failed: %08lx\n", GetLastError());
691 /* Not only should this find a context, but it should be the same
692 * (same address) as context1.
694 ok(context1 == context2, "Expected identical context addresses\n");
695 CertFreeCertificateContext(context2);
697 CertFreeCertificateContext(context1);
698 CertCloseStore(store, 0);
701 /* This expires in 1970 or so */
702 static const BYTE expiredCert[] = { 0x30, 0x82, 0x01, 0x33, 0x30, 0x81, 0xe2,
703 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0xc4, 0xd7, 0x7f, 0x0e, 0x6f, 0xa6,
704 0x8c, 0xaa, 0x47, 0x47, 0x40, 0xe7, 0xb7, 0x0b, 0x4a, 0x7f, 0x30, 0x09, 0x06,
705 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1d, 0x05, 0x00, 0x30, 0x1f, 0x31, 0x1d, 0x30,
706 0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63, 0x40,
707 0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63,
708 0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x36, 0x39, 0x30, 0x31, 0x30, 0x31, 0x30,
709 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x37, 0x30, 0x30, 0x31, 0x30,
710 0x31, 0x30, 0x36, 0x30, 0x30, 0x30, 0x30, 0x5a, 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, 0x5c, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
714 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x4b, 0x00, 0x30, 0x48, 0x02, 0x41,
715 0x00, 0xa1, 0xaf, 0x4a, 0xea, 0xa7, 0x83, 0x57, 0xc0, 0x37, 0x33, 0x7e, 0x29,
716 0x5e, 0x0d, 0xfc, 0x44, 0x74, 0x3a, 0x1d, 0xc3, 0x1b, 0x1d, 0x96, 0xed, 0x4e,
717 0xf4, 0x1b, 0x98, 0xec, 0x69, 0x1b, 0x04, 0xea, 0x25, 0xcf, 0xb3, 0x2a, 0xf5,
718 0xd9, 0x22, 0xd9, 0x8d, 0x08, 0x39, 0x81, 0xc6, 0xe0, 0x4f, 0x12, 0x37, 0x2a,
719 0x3f, 0x80, 0xa6, 0x6c, 0x67, 0x43, 0x3a, 0xdd, 0x95, 0x0c, 0xbb, 0x2f, 0x6b,
720 0x02, 0x03, 0x01, 0x00, 0x01, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02,
721 0x1d, 0x05, 0x00, 0x03, 0x41, 0x00, 0x8f, 0xa2, 0x5b, 0xd6, 0xdf, 0x34, 0xd0,
722 0xa2, 0xa7, 0x47, 0xf1, 0x13, 0x79, 0xd3, 0xf3, 0x39, 0xbd, 0x4e, 0x2b, 0xa3,
723 0xf4, 0x63, 0x37, 0xac, 0x5a, 0x0c, 0x5e, 0x4d, 0x0d, 0x54, 0x87, 0x4f, 0x31,
724 0xfb, 0xa0, 0xce, 0x8f, 0x9a, 0x2f, 0x4d, 0x48, 0xc6, 0x84, 0x8d, 0xf5, 0x70,
725 0x74, 0x17, 0xa5, 0xf3, 0x66, 0x47, 0x06, 0xd6, 0x64, 0x45, 0xbc, 0x52, 0xef,
726 0x49, 0xe5, 0xf9, 0x65, 0xf3 };
728 /* This expires in 2036 or so */
729 static const BYTE childOfExpired[] = { 0x30, 0x81, 0xcc, 0x30, 0x78, 0xa0,
730 0x03, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86,
731 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x1f, 0x31, 0x1d,
732 0x30, 0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63,
733 0x40, 0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e,
734 0x63, 0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x30, 0x36, 0x30, 0x35, 0x30, 0x35,
735 0x31, 0x37, 0x31, 0x32, 0x34, 0x39, 0x5a, 0x17, 0x0d, 0x33, 0x36, 0x30, 0x35,
736 0x30, 0x35, 0x31, 0x37, 0x31, 0x32, 0x34, 0x39, 0x5a, 0x30, 0x15, 0x31, 0x13,
737 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e,
738 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03,
739 0x01, 0x00, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
740 0x01, 0x05, 0x05, 0x00, 0x03, 0x41, 0x00, 0x20, 0x3b, 0xdb, 0x4d, 0x67, 0x50,
741 0xec, 0x73, 0x9d, 0xf9, 0x85, 0x5d, 0x18, 0xe9, 0xb4, 0x98, 0xe3, 0x31, 0xb7,
742 0x03, 0x0b, 0xc0, 0x39, 0x93, 0x56, 0x81, 0x0a, 0xfc, 0x78, 0xa8, 0x29, 0x42,
743 0x5f, 0x69, 0xfb, 0xbc, 0x5b, 0xf2, 0xa6, 0x2a, 0xbe, 0x91, 0x2c, 0xfc, 0x89,
744 0x69, 0x15, 0x18, 0x58, 0xe5, 0x02, 0x75, 0xf7, 0x2a, 0xb6, 0xa9, 0xfb, 0x47,
745 0x6a, 0x6e, 0x0a, 0x9b, 0xe9, 0xdc };
747 static void testGetIssuerCert(void)
750 PCCERT_CONTEXT parent, child;
751 DWORD flags = 0xffffffff;
752 HCERTSTORE store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
753 CERT_STORE_CREATE_NEW_FLAG, NULL);
755 ok(store != NULL, "CertOpenStore failed: %08lx\n", GetLastError());
757 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
758 expiredCert, sizeof(expiredCert), CERT_STORE_ADD_ALWAYS, NULL);
759 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n",
762 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
763 childOfExpired, sizeof(childOfExpired), CERT_STORE_ADD_ALWAYS, &child);
764 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n",
768 parent = CertGetIssuerCertificateFromStore(NULL, NULL, NULL, NULL);
769 parent = CertGetIssuerCertificateFromStore(store, NULL, NULL, NULL);
771 parent = CertGetIssuerCertificateFromStore(NULL, NULL, NULL, &flags);
772 ok(!parent && GetLastError() == E_INVALIDARG,
773 "Expected E_INVALIDARG, got %08lx\n", GetLastError());
774 parent = CertGetIssuerCertificateFromStore(store, NULL, NULL, &flags);
775 ok(!parent && GetLastError() == E_INVALIDARG,
776 "Expected E_INVALIDARG, got %08lx\n", GetLastError());
777 parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
778 ok(!parent && GetLastError() == E_INVALIDARG,
779 "Expected E_INVALIDARG, got %08lx\n", GetLastError());
780 /* Confusing: the caller cannot set either of the
781 * CERT_STORE_NO_*_FLAGs, as these are not checks,
784 flags = CERT_STORE_NO_CRL_FLAG | CERT_STORE_NO_ISSUER_FLAG;
785 parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
786 ok(!parent && GetLastError() == E_INVALIDARG,
787 "Expected E_INVALIDARG, got %08lx\n", GetLastError());
788 /* Perform no checks */
790 parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
791 ok(parent != NULL, "CertGetIssuerCertificateFromStore failed: %08lx\n",
794 CertFreeCertificateContext(parent);
795 /* Check revocation and signature only */
796 flags = CERT_STORE_REVOCATION_FLAG | CERT_STORE_SIGNATURE_FLAG;
797 parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
798 ok(parent != NULL, "CertGetIssuerCertificateFromStore failed: %08lx\n",
800 /* Confusing: CERT_STORE_REVOCATION_FLAG succeeds when there is no CRL by
801 * setting CERT_STORE_NO_CRL_FLAG.
803 ok(flags == (CERT_STORE_REVOCATION_FLAG | CERT_STORE_NO_CRL_FLAG),
804 "Expected CERT_STORE_REVOCATION_FLAG | CERT_STORE_NO_CRL_FLAG, got %08lx\n",
807 CertFreeCertificateContext(parent);
808 /* Now check just the time */
809 flags = CERT_STORE_TIME_VALIDITY_FLAG;
810 parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
811 ok(parent != NULL, "CertGetIssuerCertificateFromStore failed: %08lx\n",
813 /* Oops: the child is not expired, so the time validity check actually
814 * succeeds, even though the signing cert is expired.
816 ok(!flags, "Expected check to succeed, got %08lx\n", flags);
818 CertFreeCertificateContext(parent);
820 CertFreeCertificateContext(child);
821 CertCloseStore(store, 0);
824 static void testCryptHashCert(void)
826 static const BYTE emptyHash[] = { 0xda, 0x39, 0xa3, 0xee, 0x5e, 0x6b, 0x4b,
827 0x0d, 0x32, 0x55, 0xbf, 0xef, 0x95, 0x60, 0x18, 0x90, 0xaf, 0xd8, 0x07,
829 static const BYTE knownHash[] = { 0xae, 0x9d, 0xbf, 0x6d, 0xf5, 0x46, 0xee,
830 0x8b, 0xc5, 0x7a, 0x13, 0xba, 0xc2, 0xb1, 0x04, 0xf2, 0xbf, 0x52, 0xa8,
832 static const BYTE toHash[] = "abcdefghijklmnopqrstuvwxyz0123456789.,;!?:";
835 DWORD hashLen = sizeof(hash);
837 /* NULL buffer and nonzero length crashes
838 ret = CryptHashCertificate(0, 0, 0, NULL, size, hash, &hashLen);
839 empty hash length also crashes
840 ret = CryptHashCertificate(0, 0, 0, buf, size, hash, NULL);
842 /* Test empty hash */
843 ret = CryptHashCertificate(0, 0, 0, toHash, sizeof(toHash), NULL,
845 ok(ret, "CryptHashCertificate failed: %08lx\n", GetLastError());
846 ok(hashLen == sizeof(hash), "Got unexpected size of hash %ld\n", hashLen);
847 /* Test with empty buffer */
848 ret = CryptHashCertificate(0, 0, 0, NULL, 0, hash, &hashLen);
849 ok(ret, "CryptHashCertificate failed: %08lx\n", GetLastError());
850 ok(!memcmp(hash, emptyHash, sizeof(emptyHash)),
851 "Unexpected hash of nothing\n");
852 /* Test a known value */
853 ret = CryptHashCertificate(0, 0, 0, toHash, sizeof(toHash), hash,
855 ok(ret, "CryptHashCertificate failed: %08lx\n", GetLastError());
856 ok(!memcmp(hash, knownHash, sizeof(knownHash)), "Unexpected hash\n");
859 static void verifySig(HCRYPTPROV csp, const BYTE *toSign, size_t toSignLen,
860 const BYTE *sig, unsigned int sigLen)
863 BOOL ret = CryptCreateHash(csp, CALG_SHA1, 0, 0, &hash);
865 ok(ret, "CryptCreateHash failed: %08lx\n", GetLastError());
869 DWORD mySigSize = sizeof(mySig);
871 ret = CryptHashData(hash, toSign, toSignLen, 0);
872 ok(ret, "CryptHashData failed: %08lx\n", GetLastError());
873 /* use the A variant so the test can run on Win9x */
874 ret = CryptSignHashA(hash, AT_SIGNATURE, NULL, 0, mySig, &mySigSize);
875 ok(ret, "CryptSignHash failed: %08lx\n", GetLastError());
878 ok(mySigSize == sigLen, "Expected sig length %d, got %ld\n",
880 ok(!memcmp(mySig, sig, sigLen), "Unexpected signature\n");
882 CryptDestroyHash(hash);
886 /* Tests signing the certificate described by toBeSigned with the CSP passed in,
887 * using the algorithm with OID sigOID. The CSP is assumed to be empty, and a
888 * keyset named AT_SIGNATURE will be added to it. The signing key will be
889 * stored in *key, and the signature will be stored in sig. sigLen should be
892 static void testSignCert(HCRYPTPROV csp, const CRYPT_DATA_BLOB *toBeSigned,
893 LPCSTR sigOID, HCRYPTKEY *key, BYTE *sig, DWORD *sigLen)
897 CRYPT_ALGORITHM_IDENTIFIER algoID = { NULL, { 0, NULL } };
900 ret = CryptSignCertificate(0, 0, 0, NULL, 0, NULL, NULL, NULL, NULL);
901 ret = CryptSignCertificate(0, 0, 0, NULL, 0, NULL, NULL, NULL, &size);
902 ret = CryptSignCertificate(0, 0, 0, toBeSigned->pbData, toBeSigned->cbData,
903 NULL, NULL, NULL, &size);
905 ret = CryptSignCertificate(0, 0, 0, toBeSigned->pbData, toBeSigned->cbData,
906 &algoID, NULL, NULL, &size);
907 ok(!ret && GetLastError() == NTE_BAD_ALGID,
908 "Expected NTE_BAD_ALGID, got %08lx\n", GetLastError());
909 algoID.pszObjId = (LPSTR)sigOID;
910 ret = CryptSignCertificate(0, 0, 0, toBeSigned->pbData, toBeSigned->cbData,
911 &algoID, NULL, NULL, &size);
912 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
913 "Expected ERROR_INVALID_PARAMETER, got %08lx\n", GetLastError());
914 ret = CryptSignCertificate(0, AT_SIGNATURE, 0, toBeSigned->pbData,
915 toBeSigned->cbData, &algoID, NULL, NULL, &size);
916 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
917 "Expected ERROR_INVALID_PARAMETER, got %08lx\n", GetLastError());
919 /* No keys exist in the new CSP yet.. */
920 ret = CryptSignCertificate(csp, AT_SIGNATURE, 0, toBeSigned->pbData,
921 toBeSigned->cbData, &algoID, NULL, NULL, &size);
922 ok(!ret && (GetLastError() == NTE_BAD_KEYSET || GetLastError() ==
923 NTE_NO_KEY), "Expected NTE_BAD_KEYSET or NTE_NO_KEY, got %08lx\n",
925 ret = CryptGenKey(csp, AT_SIGNATURE, 0, key);
926 ok(ret, "CryptGenKey failed: %08lx\n", GetLastError());
929 ret = CryptSignCertificate(csp, AT_SIGNATURE, 0, toBeSigned->pbData,
930 toBeSigned->cbData, &algoID, NULL, NULL, &size);
931 ok(ret, "CryptSignCertificate failed: %08lx\n", GetLastError());
932 ok(size <= *sigLen, "Expected size <= %ld, got %ld\n", *sigLen, size);
935 ret = CryptSignCertificate(csp, AT_SIGNATURE, 0, toBeSigned->pbData,
936 toBeSigned->cbData, &algoID, NULL, sig, &size);
937 ok(ret, "CryptSignCertificate failed: %08lx\n", GetLastError());
941 verifySig(csp, toBeSigned->pbData, toBeSigned->cbData, sig,
948 static void testVerifyCertSig(HCRYPTPROV csp, const CRYPT_DATA_BLOB *toBeSigned,
949 LPCSTR sigOID, const BYTE *sig, DWORD sigLen)
951 CERT_SIGNED_CONTENT_INFO info;
956 if(pCryptVerifyCertificateSignatureEx) {
957 ret = pCryptVerifyCertificateSignatureEx(0, 0, 0, NULL, 0, NULL, 0, NULL);
958 ok(!ret && GetLastError() == E_INVALIDARG,
959 "Expected E_INVALIDARG, got %08lx\n", GetLastError());
960 ret = pCryptVerifyCertificateSignatureEx(csp, 0, 0, NULL, 0, NULL, 0, NULL);
961 ok(!ret && GetLastError() == E_INVALIDARG,
962 "Expected E_INVALIDARG, got %08lx\n", GetLastError());
963 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING, 0, NULL, 0,
965 ok(!ret && GetLastError() == E_INVALIDARG,
966 "Expected E_INVALIDARG, got %08lx\n", GetLastError());
968 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
969 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, NULL, 0, NULL, 0, NULL);
972 info.ToBeSigned.cbData = toBeSigned->cbData;
973 info.ToBeSigned.pbData = toBeSigned->pbData;
974 info.SignatureAlgorithm.pszObjId = (LPSTR)sigOID;
975 info.SignatureAlgorithm.Parameters.cbData = 0;
976 info.Signature.cbData = sigLen;
977 info.Signature.pbData = (BYTE *)sig;
978 info.Signature.cUnusedBits = 0;
979 ret = CryptEncodeObjectEx(X509_ASN_ENCODING, X509_CERT, &info,
980 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&cert, &size);
981 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
984 CRYPT_DATA_BLOB certBlob = { 0, NULL };
985 PCERT_PUBLIC_KEY_INFO pubKeyInfo = NULL;
987 if(pCryptVerifyCertificateSignatureEx) {
988 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
989 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob, 0, NULL, 0, NULL);
990 ok(!ret && GetLastError() == CRYPT_E_ASN1_EOD,
991 "Expected CRYPT_E_ASN1_EOD, got %08lx\n", GetLastError());
993 certBlob.pbData = (void *)0xdeadbeef;
994 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
995 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob, 0, NULL, 0, NULL);
996 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
997 "Expected STATUS_ACCESS_VIOLATION, got %08lx\n", GetLastError());
998 certBlob.cbData = size;
999 certBlob.pbData = cert;
1000 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
1001 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob, 0, NULL, 0, NULL);
1002 ok(!ret && GetLastError() == E_INVALIDARG,
1003 "Expected E_INVALIDARG, got %08lx\n", GetLastError());
1004 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
1005 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob,
1006 CRYPT_VERIFY_CERT_SIGN_ISSUER_NULL, NULL, 0, NULL);
1007 ok(!ret && GetLastError() == E_INVALIDARG,
1008 "Expected E_INVALIDARG, got %08lx\n", GetLastError());
1010 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
1011 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob,
1012 CRYPT_VERIFY_CERT_SIGN_ISSUER_PUBKEY, NULL, 0, NULL);
1015 CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING,
1016 (LPSTR)sigOID, 0, NULL, NULL, &size);
1017 pubKeyInfo = HeapAlloc(GetProcessHeap(), 0, size);
1020 ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE,
1021 X509_ASN_ENCODING, (LPSTR)sigOID, 0, NULL, pubKeyInfo, &size);
1022 ok(ret, "CryptExportKey failed: %08lx\n", GetLastError());
1023 if (ret && pCryptVerifyCertificateSignatureEx)
1025 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
1026 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob,
1027 CRYPT_VERIFY_CERT_SIGN_ISSUER_PUBKEY, pubKeyInfo, 0, NULL);
1028 ok(ret, "CryptVerifyCertificateSignatureEx failed: %08lx\n",
1031 HeapFree(GetProcessHeap(), 0, pubKeyInfo);
1037 static const BYTE emptyCert[] = { 0x30, 0x00 };
1039 static void testCertSigs(void)
1042 CRYPT_DATA_BLOB toBeSigned = { sizeof(emptyCert), (LPBYTE)emptyCert };
1046 DWORD sigSize = sizeof(sig);
1048 /* Just in case a previous run failed, delete this thing */
1049 CryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
1050 CRYPT_DELETEKEYSET);
1051 ret = CryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
1053 ok(ret, "CryptAcquireContext failed: %08lx\n", GetLastError());
1055 testSignCert(csp, &toBeSigned, szOID_RSA_SHA1RSA, &key, sig, &sigSize);
1056 testVerifyCertSig(csp, &toBeSigned, szOID_RSA_SHA1RSA, sig, sigSize);
1058 CryptDestroyKey(key);
1059 CryptReleaseContext(csp, 0);
1060 ret = CryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
1061 CRYPT_DELETEKEYSET);
1064 static void testCreateSelfSignCert(void)
1066 PCCERT_CONTEXT context;
1067 CERT_NAME_BLOB name = { sizeof(subjectName), (LPBYTE)subjectName };
1073 context = CertCreateSelfSignCertificate(0, NULL, 0, NULL, NULL, NULL, NULL,
1075 * Calling this with no first parameter creates a new key container, which
1076 * lasts beyond the test, so I don't test that. Nb: the generated key
1078 context = CertCreateSelfSignCertificate(0, &name, 0, NULL, NULL, NULL, NULL,
1083 CryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
1084 CRYPT_DELETEKEYSET);
1085 ret = CryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
1087 ok(ret, "CryptAcquireContext failed: %08lx\n", GetLastError());
1089 context = CertCreateSelfSignCertificate(csp, &name, 0, NULL, NULL, NULL,
1091 ok(!context && GetLastError() == NTE_NO_KEY,
1092 "Expected NTE_NO_KEY, got %08lx\n", GetLastError());
1093 ret = CryptGenKey(csp, AT_SIGNATURE, 0, &key);
1094 ok(ret, "CryptGenKey failed: %08lx\n", GetLastError());
1097 context = CertCreateSelfSignCertificate(csp, &name, 0, NULL, NULL, NULL,
1099 ok(context != NULL, "CertCreateSelfSignCertificate failed: %08lx\n",
1104 PCRYPT_KEY_PROV_INFO info;
1106 /* The context must have a key provider info property */
1107 ret = CertGetCertificateContextProperty(context,
1108 CERT_KEY_PROV_INFO_PROP_ID, NULL, &size);
1109 ok(ret && size, "Expected non-zero key provider info\n");
1112 info = HeapAlloc(GetProcessHeap(), 0, size);
1115 ret = CertGetCertificateContextProperty(context,
1116 CERT_KEY_PROV_INFO_PROP_ID, info, &size);
1117 ok(ret, "CertGetCertificateContextProperty failed: %08lx\n",
1121 /* Sanity-check the key provider */
1122 ok(!lstrcmpW(info->pwszContainerName, cspNameW),
1123 "Unexpected key container\n");
1124 ok(!lstrcmpW(info->pwszProvName, MS_DEF_PROV_W),
1125 "Unexpected provider\n");
1126 ok(info->dwKeySpec == AT_SIGNATURE,
1127 "Expected AT_SIGNATURE, got %ld\n", info->dwKeySpec);
1129 HeapFree(GetProcessHeap(), 0, info);
1133 CertFreeCertificateContext(context);
1136 CryptDestroyKey(key);
1139 CryptReleaseContext(csp, 0);
1140 ret = CryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
1141 CRYPT_DELETEKEYSET);
1144 static const LPCSTR keyUsages[] = { szOID_PKIX_KP_CODE_SIGNING,
1145 szOID_PKIX_KP_CLIENT_AUTH, szOID_RSA_RSA };
1147 static void testKeyUsage(void)
1150 PCCERT_CONTEXT context;
1153 /* Test base cases */
1154 ret = CertGetEnhancedKeyUsage(NULL, 0, NULL, NULL);
1155 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1156 "Expected ERROR_INVALID_PARAMETER, got %08lx\n", GetLastError());
1158 ret = CertGetEnhancedKeyUsage(NULL, 0, NULL, &size);
1159 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1160 "Expected ERROR_INVALID_PARAMETER, got %08lx\n", GetLastError());
1162 ret = CertGetEnhancedKeyUsage(NULL, 0, NULL, &size);
1163 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1164 "Expected ERROR_INVALID_PARAMETER, got %08lx\n", GetLastError());
1166 ret = CertSetEnhancedKeyUsage(NULL, NULL);
1167 usage.cUsageIdentifier = 0;
1168 ret = CertSetEnhancedKeyUsage(NULL, &usage);
1170 /* Test with a cert with no enhanced key usage extension */
1171 context = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert,
1173 ok(context != NULL, "CertCreateCertificateContext failed: %08lx\n",
1177 static const char oid[] = "1.2.3.4";
1178 BYTE buf[sizeof(CERT_ENHKEY_USAGE) + 2 * (sizeof(LPSTR) + sizeof(oid))];
1179 PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
1181 ret = CertGetEnhancedKeyUsage(context, 0, NULL, NULL);
1182 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1183 "Expected ERROR_INVALID_PARAMETER, got %08lx\n", GetLastError());
1185 ret = CertGetEnhancedKeyUsage(context, 0, NULL, &size);
1188 /* Windows 2000, ME, or later: even though it succeeded, we expect
1189 * CRYPT_E_NOT_FOUND, which indicates there is no enhanced key
1190 * usage set for this cert (which implies it's valid for all uses.)
1192 ok(GetLastError() == CRYPT_E_NOT_FOUND,
1193 "Expected CRYPT_E_NOT_FOUND, got %08lx\n", GetLastError());
1194 ok(size == sizeof(CERT_ENHKEY_USAGE), "Wrong size %ld\n", size);
1195 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
1196 ok(ret, "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
1197 ok(pUsage->cUsageIdentifier == 0, "Expected 0 usages, got %ld\n",
1198 pUsage->cUsageIdentifier);
1202 /* Windows NT, 95, or 98: it fails, and the last error is
1203 * CRYPT_E_NOT_FOUND.
1205 ok(GetLastError() == CRYPT_E_NOT_FOUND,
1206 "Expected CRYPT_E_NOT_FOUND, got %08lx\n", GetLastError());
1208 /* I can add a usage identifier when no key usage has been set */
1209 ret = CertAddEnhancedKeyUsageIdentifier(context, oid);
1210 ok(ret, "CertAddEnhancedKeyUsageIdentifier failed: %08lx\n",
1213 ret = CertGetEnhancedKeyUsage(context,
1214 CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG, pUsage, &size);
1215 ok(ret && GetLastError() == 0,
1216 "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
1217 ok(pUsage->cUsageIdentifier == 1, "Expected 1 usage, got %ld\n",
1218 pUsage->cUsageIdentifier);
1219 if (pUsage->cUsageIdentifier)
1220 ok(!strcmp(pUsage->rgpszUsageIdentifier[0], oid),
1221 "Expected %s, got %s\n", oid, pUsage->rgpszUsageIdentifier[0]);
1222 /* Now set an empty key usage */
1223 pUsage->cUsageIdentifier = 0;
1224 ret = CertSetEnhancedKeyUsage(context, pUsage);
1225 ok(ret, "CertSetEnhancedKeyUsage failed: %08lx\n", GetLastError());
1226 /* Shouldn't find it in the cert */
1228 ret = CertGetEnhancedKeyUsage(context,
1229 CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, pUsage, &size);
1230 ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
1231 "Expected CRYPT_E_NOT_FOUND, got %08lx\n", GetLastError());
1232 /* Should find it as an extended property */
1233 ret = CertGetEnhancedKeyUsage(context,
1234 CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG, pUsage, &size);
1235 ok(ret && GetLastError() == 0,
1236 "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
1237 ok(pUsage->cUsageIdentifier == 0, "Expected 0 usages, got %ld\n",
1238 pUsage->cUsageIdentifier);
1239 /* Should find it as either */
1240 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
1241 ok(ret && GetLastError() == 0,
1242 "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
1243 ok(pUsage->cUsageIdentifier == 0, "Expected 0 usages, got %ld\n",
1244 pUsage->cUsageIdentifier);
1245 /* Add a usage identifier */
1246 ret = CertAddEnhancedKeyUsageIdentifier(context, oid);
1247 ok(ret, "CertAddEnhancedKeyUsageIdentifier failed: %08lx\n",
1250 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
1251 ok(ret && GetLastError() == 0,
1252 "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
1253 ok(pUsage->cUsageIdentifier == 1, "Expected 1 identifier, got %ld\n",
1254 pUsage->cUsageIdentifier);
1255 if (pUsage->cUsageIdentifier)
1256 ok(!strcmp(pUsage->rgpszUsageIdentifier[0], oid),
1257 "Expected %s, got %s\n", oid, pUsage->rgpszUsageIdentifier[0]);
1258 /* Yep, I can re-add the same usage identifier */
1259 ret = CertAddEnhancedKeyUsageIdentifier(context, oid);
1260 ok(ret, "CertAddEnhancedKeyUsageIdentifier failed: %08lx\n",
1263 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
1264 ok(ret && GetLastError() == 0,
1265 "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
1266 ok(pUsage->cUsageIdentifier == 2, "Expected 2 identifiers, got %ld\n",
1267 pUsage->cUsageIdentifier);
1268 if (pUsage->cUsageIdentifier)
1269 ok(!strcmp(pUsage->rgpszUsageIdentifier[0], oid),
1270 "Expected %s, got %s\n", oid, pUsage->rgpszUsageIdentifier[0]);
1271 if (pUsage->cUsageIdentifier >= 2)
1272 ok(!strcmp(pUsage->rgpszUsageIdentifier[1], oid),
1273 "Expected %s, got %s\n", oid, pUsage->rgpszUsageIdentifier[1]);
1274 /* Now set a NULL extended property--this deletes the property. */
1275 ret = CertSetEnhancedKeyUsage(context, NULL);
1276 ok(ret, "CertSetEnhancedKeyUsage failed: %08lx\n", GetLastError());
1277 SetLastError(0xbaadcafe);
1279 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
1280 ok(GetLastError() == CRYPT_E_NOT_FOUND,
1281 "Expected CRYPT_E_NOT_FOUND, got %08lx\n", GetLastError());
1283 CertFreeCertificateContext(context);
1285 /* Now test with a cert with an enhanced key usage extension */
1286 context = CertCreateCertificateContext(X509_ASN_ENCODING, certWithUsage,
1287 sizeof(certWithUsage));
1288 ok(context != NULL, "CertCreateCertificateContext failed: %08lx\n",
1293 DWORD bufSize = 0, i;
1295 /* The size may depend on what flags are used to query it, so I
1296 * realloc the buffer for each test.
1298 ret = CertGetEnhancedKeyUsage(context,
1299 CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, 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 in the cert */
1308 ret = CertGetEnhancedKeyUsage(context,
1309 CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, pUsage, &size);
1310 ok(ret && GetLastError() == 0,
1311 "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
1312 ok(pUsage->cUsageIdentifier == 3, "Expected 3 usages, got %ld\n",
1313 pUsage->cUsageIdentifier);
1314 for (i = 0; i < pUsage->cUsageIdentifier; i++)
1315 ok(!strcmp(pUsage->rgpszUsageIdentifier[i], keyUsages[i]),
1316 "Expected %s, got %s\n", keyUsages[i],
1317 pUsage->rgpszUsageIdentifier[i]);
1318 HeapFree(GetProcessHeap(), 0, buf);
1320 ret = CertGetEnhancedKeyUsage(context, 0, 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;
1327 /* Should find it as either */
1329 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
1330 /* In Windows, GetLastError returns CRYPT_E_NOT_FOUND not found
1331 * here, even though the return is successful and the usage id
1332 * count is positive. I don't enforce that here.
1335 "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
1336 ok(pUsage->cUsageIdentifier == 3, "Expected 3 usages, got %ld\n",
1337 pUsage->cUsageIdentifier);
1338 for (i = 0; i < pUsage->cUsageIdentifier; i++)
1339 ok(!strcmp(pUsage->rgpszUsageIdentifier[i], keyUsages[i]),
1340 "Expected %s, got %s\n", keyUsages[i],
1341 pUsage->rgpszUsageIdentifier[i]);
1342 HeapFree(GetProcessHeap(), 0, buf);
1344 /* Shouldn't find it as an extended property */
1345 ret = CertGetEnhancedKeyUsage(context,
1346 CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG, NULL, &size);
1347 ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
1348 "Expected CRYPT_E_NOT_FOUND, got %08lx\n", GetLastError());
1349 /* Adding a usage identifier overrides the cert's usage!? */
1350 ret = CertAddEnhancedKeyUsageIdentifier(context, szOID_RSA_RSA);
1351 ok(ret, "CertAddEnhancedKeyUsageIdentifier failed: %08lx\n",
1353 ret = CertGetEnhancedKeyUsage(context, 0, NULL, &bufSize);
1354 ok(ret, "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
1355 buf = HeapAlloc(GetProcessHeap(), 0, bufSize);
1358 PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
1360 /* Should find it as either */
1362 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
1364 "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
1365 ok(pUsage->cUsageIdentifier == 1, "Expected 1 usage, got %ld\n",
1366 pUsage->cUsageIdentifier);
1367 ok(!strcmp(pUsage->rgpszUsageIdentifier[0], szOID_RSA_RSA),
1368 "Expected %s, got %s\n", szOID_RSA_RSA,
1369 pUsage->rgpszUsageIdentifier[0]);
1370 HeapFree(GetProcessHeap(), 0, buf);
1372 /* But querying the cert directly returns its usage */
1373 ret = CertGetEnhancedKeyUsage(context,
1374 CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, NULL, &bufSize);
1375 ok(ret, "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
1376 buf = HeapAlloc(GetProcessHeap(), 0, bufSize);
1379 PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
1382 ret = CertGetEnhancedKeyUsage(context,
1383 CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, pUsage, &size);
1385 "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
1386 ok(pUsage->cUsageIdentifier == 3, "Expected 3 usages, got %ld\n",
1387 pUsage->cUsageIdentifier);
1388 for (i = 0; i < pUsage->cUsageIdentifier; i++)
1389 ok(!strcmp(pUsage->rgpszUsageIdentifier[i], keyUsages[i]),
1390 "Expected %s, got %s\n", keyUsages[i],
1391 pUsage->rgpszUsageIdentifier[i]);
1392 HeapFree(GetProcessHeap(), 0, buf);
1394 /* And removing the only usage identifier in the extended property
1395 * results in the cert's key usage being found.
1397 ret = CertRemoveEnhancedKeyUsageIdentifier(context, szOID_RSA_RSA);
1398 ok(ret, "CertRemoveEnhancedKeyUsage failed: %08lx\n", GetLastError());
1399 ret = CertGetEnhancedKeyUsage(context, 0, NULL, &bufSize);
1400 ok(ret, "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
1401 buf = HeapAlloc(GetProcessHeap(), 0, bufSize);
1404 PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
1406 /* Should find it as either */
1408 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
1410 "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
1411 ok(pUsage->cUsageIdentifier == 3, "Expected 3 usages, got %ld\n",
1412 pUsage->cUsageIdentifier);
1413 for (i = 0; i < pUsage->cUsageIdentifier; i++)
1414 ok(!strcmp(pUsage->rgpszUsageIdentifier[i], keyUsages[i]),
1415 "Expected %s, got %s\n", keyUsages[i],
1416 pUsage->rgpszUsageIdentifier[i]);
1417 HeapFree(GetProcessHeap(), 0, buf);
1420 CertFreeCertificateContext(context);
1424 static void testCompareCertName(void)
1426 static const BYTE bogus[] = { 1, 2, 3, 4 };
1427 static const BYTE bogusPrime[] = { 0, 1, 2, 3, 4 };
1428 static const BYTE emptyPrime[] = { 0x30, 0x00, 0x01 };
1430 CERT_NAME_BLOB blob1, blob2;
1433 ret = CertCompareCertificateName(0, NULL, NULL);
1435 /* An empty name checks against itself.. */
1436 blob1.pbData = (LPBYTE)emptyCert;
1437 blob1.cbData = sizeof(emptyCert);
1438 ret = CertCompareCertificateName(0, &blob1, &blob1);
1439 ok(ret, "CertCompareCertificateName failed: %08lx\n", GetLastError());
1440 /* It doesn't have to be a valid encoded name.. */
1441 blob1.pbData = (LPBYTE)bogus;
1442 blob1.cbData = sizeof(bogus);
1443 ret = CertCompareCertificateName(0, &blob1, &blob1);
1444 ok(ret, "CertCompareCertificateName failed: %08lx\n", GetLastError());
1445 /* Leading zeroes matter.. */
1446 blob2.pbData = (LPBYTE)bogusPrime;
1447 blob2.cbData = sizeof(bogusPrime);
1448 ret = CertCompareCertificateName(0, &blob1, &blob2);
1449 ok(!ret, "Expected failure\n");
1450 /* As do trailing extra bytes. */
1451 blob2.pbData = (LPBYTE)emptyPrime;
1452 blob2.cbData = sizeof(emptyPrime);
1453 ret = CertCompareCertificateName(0, &blob1, &blob2);
1454 ok(!ret, "Expected failure\n");
1457 static const BYTE int1[] = { 0x88, 0xff, 0xff, 0xff };
1458 static const BYTE int2[] = { 0x88, 0xff };
1459 static const BYTE int3[] = { 0x23, 0xff };
1460 static const BYTE int4[] = { 0x7f, 0x00 };
1461 static const BYTE int5[] = { 0x7f };
1462 static const BYTE int6[] = { 0x80, 0x00, 0x00, 0x00 };
1463 static const BYTE int7[] = { 0x80, 0x00 };
1467 CRYPT_INTEGER_BLOB blob1;
1468 CRYPT_INTEGER_BLOB blob2;
1471 { { sizeof(int1), (LPBYTE)int1 }, { sizeof(int2), (LPBYTE)int2 }, TRUE },
1472 { { sizeof(int3), (LPBYTE)int3 }, { sizeof(int3), (LPBYTE)int3 }, TRUE },
1473 { { sizeof(int4), (LPBYTE)int4 }, { sizeof(int5), (LPBYTE)int5 }, TRUE },
1474 { { sizeof(int6), (LPBYTE)int6 }, { sizeof(int7), (LPBYTE)int7 }, TRUE },
1475 { { sizeof(int1), (LPBYTE)int1 }, { sizeof(int7), (LPBYTE)int7 }, FALSE },
1478 static void testCompareIntegerBlob(void)
1483 for (i = 0; i < sizeof(intBlobs) / sizeof(intBlobs[0]); i++)
1485 ret = CertCompareIntegerBlob(&intBlobs[i].blob1, &intBlobs[i].blob2);
1486 ok(ret == intBlobs[i].areEqual,
1487 "%ld: expected blobs %s compare\n", i, intBlobs[i].areEqual ?
1492 static void testComparePublicKeyInfo(void)
1495 CERT_PUBLIC_KEY_INFO info1 = { { 0 } }, info2 = { { 0 } };
1496 static CHAR oid_rsa_rsa[] = szOID_RSA_RSA;
1497 static CHAR oid_rsa_sha1rsa[] = szOID_RSA_SHA1RSA;
1498 static CHAR oid_x957_dsa[] = szOID_X957_DSA;
1499 static const BYTE bits1[] = { 1, 0 };
1500 static const BYTE bits2[] = { 0 };
1501 static const BYTE bits3[] = { 1 };
1504 ret = CertComparePublicKeyInfo(0, NULL, NULL);
1506 /* Empty public keys compare */
1507 ret = CertComparePublicKeyInfo(0, &info1, &info2);
1508 ok(ret, "CertComparePublicKeyInfo failed: %08lx\n", GetLastError());
1509 /* Different OIDs appear to compare */
1510 info1.Algorithm.pszObjId = oid_rsa_rsa;
1511 info2.Algorithm.pszObjId = oid_rsa_sha1rsa;
1512 ret = CertComparePublicKeyInfo(0, &info1, &info2);
1513 ok(ret, "CertComparePublicKeyInfo failed: %08lx\n", GetLastError());
1514 info2.Algorithm.pszObjId = oid_x957_dsa;
1515 ret = CertComparePublicKeyInfo(0, &info1, &info2);
1516 ok(ret, "CertComparePublicKeyInfo failed: %08lx\n", GetLastError());
1517 info1.PublicKey.cbData = sizeof(bits1);
1518 info1.PublicKey.pbData = (LPBYTE)bits1;
1519 info1.PublicKey.cUnusedBits = 0;
1520 info2.PublicKey.cbData = sizeof(bits1);
1521 info2.PublicKey.pbData = (LPBYTE)bits1;
1522 info2.PublicKey.cUnusedBits = 0;
1523 ret = CertComparePublicKeyInfo(0, &info1, &info2);
1524 ok(ret, "CertComparePublicKeyInfo failed: %08lx\n", GetLastError());
1525 /* Even though they compare in their used bits, these do not compare */
1526 info1.PublicKey.cbData = sizeof(bits2);
1527 info1.PublicKey.pbData = (LPBYTE)bits2;
1528 info1.PublicKey.cUnusedBits = 0;
1529 info2.PublicKey.cbData = sizeof(bits3);
1530 info2.PublicKey.pbData = (LPBYTE)bits3;
1531 info2.PublicKey.cUnusedBits = 1;
1532 ret = CertComparePublicKeyInfo(0, &info1, &info2);
1533 /* Simple (non-comparing) case */
1534 ok(!ret, "Expected keys not to compare\n");
1535 info2.PublicKey.cbData = sizeof(bits1);
1536 info2.PublicKey.pbData = (LPBYTE)bits1;
1537 info2.PublicKey.cUnusedBits = 0;
1538 ret = CertComparePublicKeyInfo(0, &info1, &info2);
1539 ok(!ret, "Expected keys not to compare\n");
1542 static void testHashPublicKeyInfo(void)
1545 CERT_PUBLIC_KEY_INFO info = { { 0 } };
1549 ret = CryptHashPublicKeyInfo(0, 0, 0, 0, NULL, NULL, NULL);
1550 ret = CryptHashPublicKeyInfo(0, 0, 0, 0, &info, NULL, NULL);
1552 ret = CryptHashPublicKeyInfo(0, 0, 0, 0, NULL, NULL, &len);
1553 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
1554 "Expected ERROR_FILE_NOT_FOUND, got %08lx\n", GetLastError());
1555 ret = CryptHashPublicKeyInfo(0, 0, 0, X509_ASN_ENCODING, NULL, NULL, &len);
1556 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
1557 "Expected STATUS_ACCESS_VIOLATION, got %08lx\n", GetLastError());
1558 ret = CryptHashPublicKeyInfo(0, 0, 0, X509_ASN_ENCODING, &info, NULL, &len);
1559 ok(ret, "CryptHashPublicKeyInfo failed: %08lx\n", GetLastError());
1560 ok(len == 16, "Expected hash size 16, got %ld\n", len);
1563 static const BYTE emptyHash[] = { 0xb8,0x51,0x3a,0x31,0x0e,0x9f,0x40,
1564 0x36,0x9c,0x92,0x45,0x1b,0x9d,0xc8,0xf9,0xf6 };
1567 ret = CryptHashPublicKeyInfo(0, 0, 0, X509_ASN_ENCODING, &info, buf,
1569 ok(ret, "CryptHashPublicKeyInfo failed: %08lx\n", GetLastError());
1570 ok(!memcmp(buf, emptyHash, len), "Unexpected hash\n");
1574 void testCompareCert(void)
1576 CERT_INFO info1 = { 0 }, info2 = { 0 };
1580 ret = CertCompareCertificate(X509_ASN_ENCODING, NULL, NULL);
1583 /* Certs with the same issuer and serial number are equal, even if they
1584 * differ in other respects (like subject).
1586 info1.SerialNumber.pbData = (LPBYTE)serialNum;
1587 info1.SerialNumber.cbData = sizeof(serialNum);
1588 info1.Issuer.pbData = (LPBYTE)subjectName;
1589 info1.Issuer.cbData = sizeof(subjectName);
1590 info1.Subject.pbData = (LPBYTE)subjectName2;
1591 info1.Subject.cbData = sizeof(subjectName2);
1592 info2.SerialNumber.pbData = (LPBYTE)serialNum;
1593 info2.SerialNumber.cbData = sizeof(serialNum);
1594 info2.Issuer.pbData = (LPBYTE)subjectName;
1595 info2.Issuer.cbData = sizeof(subjectName);
1596 info2.Subject.pbData = (LPBYTE)subjectName;
1597 info2.Subject.cbData = sizeof(subjectName);
1598 ret = CertCompareCertificate(X509_ASN_ENCODING, &info1, &info2);
1599 ok(ret, "Expected certs to be equal\n");
1601 info2.Issuer.pbData = (LPBYTE)subjectName2;
1602 info2.Issuer.cbData = sizeof(subjectName2);
1603 ret = CertCompareCertificate(X509_ASN_ENCODING, &info1, &info2);
1604 ok(!ret, "Expected certs not to be equal\n");
1607 static void testVerifySubjectCert(void)
1611 PCCERT_CONTEXT context1, context2;
1614 ret = CertVerifySubjectCertificateContext(NULL, NULL, NULL);
1617 ret = CertVerifySubjectCertificateContext(NULL, NULL, &flags);
1618 ok(ret, "CertVerifySubjectCertificateContext failed; %08lx\n",
1620 flags = CERT_STORE_NO_CRL_FLAG;
1621 ret = CertVerifySubjectCertificateContext(NULL, NULL, &flags);
1622 ok(!ret && GetLastError() == E_INVALIDARG,
1623 "Expected E_INVALIDARG, got %08lx\n", GetLastError());
1626 context1 = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert,
1628 ret = CertVerifySubjectCertificateContext(NULL, context1, &flags);
1629 ok(ret, "CertVerifySubjectCertificateContext failed; %08lx\n",
1631 ret = CertVerifySubjectCertificateContext(context1, NULL, &flags);
1632 ok(ret, "CertVerifySubjectCertificateContext failed; %08lx\n",
1634 ret = CertVerifySubjectCertificateContext(context1, context1, &flags);
1635 ok(ret, "CertVerifySubjectCertificateContext failed; %08lx\n",
1638 context2 = CertCreateCertificateContext(X509_ASN_ENCODING,
1639 bigCertWithDifferentSubject, sizeof(bigCertWithDifferentSubject));
1640 SetLastError(0xdeadbeef);
1641 ret = CertVerifySubjectCertificateContext(context1, context2, &flags);
1642 ok(ret, "CertVerifySubjectCertificateContext failed; %08lx\n",
1644 flags = CERT_STORE_REVOCATION_FLAG;
1645 ret = CertVerifySubjectCertificateContext(context1, context2, &flags);
1646 ok(ret, "CertVerifySubjectCertificateContext failed; %08lx\n",
1648 ok(flags == (CERT_STORE_REVOCATION_FLAG | CERT_STORE_NO_CRL_FLAG),
1649 "Expected CERT_STORE_REVOCATION_FLAG | CERT_STORE_NO_CRL_FLAG, got %08lx\n",
1651 flags = CERT_STORE_SIGNATURE_FLAG;
1652 ret = CertVerifySubjectCertificateContext(context1, context2, &flags);
1653 ok(ret, "CertVerifySubjectCertificateContext failed; %08lx\n",
1655 ok(flags == CERT_STORE_SIGNATURE_FLAG,
1656 "Expected CERT_STORE_SIGNATURE_FLAG, got %08lx\n", flags);
1657 CertFreeCertificateContext(context2);
1659 CertFreeCertificateContext(context1);
1662 static const BYTE privKey[] = {
1663 0x07, 0x02, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x52, 0x53, 0x41, 0x32, 0x00,
1664 0x02, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x79, 0x10, 0x1c, 0xd0, 0x6b, 0x10,
1665 0x18, 0x30, 0x94, 0x61, 0xdc, 0x0e, 0xcb, 0x96, 0x4e, 0x21, 0x3f, 0x79, 0xcd,
1666 0xa9, 0x17, 0x62, 0xbc, 0xbb, 0x61, 0x4c, 0xe0, 0x75, 0x38, 0x6c, 0xf3, 0xde,
1667 0x60, 0x86, 0x03, 0x97, 0x65, 0xeb, 0x1e, 0x6b, 0xdb, 0x53, 0x85, 0xad, 0x68,
1668 0x21, 0xf1, 0x5d, 0xe7, 0x1f, 0xe6, 0x53, 0xb4, 0xbb, 0x59, 0x3e, 0x14, 0x27,
1669 0xb1, 0x83, 0xa7, 0x3a, 0x54, 0xe2, 0x8f, 0x65, 0x8e, 0x6a, 0x4a, 0xcf, 0x3b,
1670 0x1f, 0x65, 0xff, 0xfe, 0xf1, 0x31, 0x3a, 0x37, 0x7a, 0x8b, 0xcb, 0xc6, 0xd4,
1671 0x98, 0x50, 0x36, 0x67, 0xe4, 0xa1, 0xe8, 0x7e, 0x8a, 0xc5, 0x23, 0xf2, 0x77,
1672 0xf5, 0x37, 0x61, 0x49, 0x72, 0x59, 0xe8, 0x3d, 0xf7, 0x60, 0xb2, 0x77, 0xca,
1673 0x78, 0x54, 0x6d, 0x65, 0x9e, 0x03, 0x97, 0x1b, 0x61, 0xbd, 0x0c, 0xd8, 0x06,
1674 0x63, 0xe2, 0xc5, 0x48, 0xef, 0xb3, 0xe2, 0x6e, 0x98, 0x7d, 0xbd, 0x4e, 0x72,
1675 0x91, 0xdb, 0x31, 0x57, 0xe3, 0x65, 0x3a, 0x49, 0xca, 0xec, 0xd2, 0x02, 0x4e,
1676 0x22, 0x7e, 0x72, 0x8e, 0xf9, 0x79, 0x84, 0x82, 0xdf, 0x7b, 0x92, 0x2d, 0xaf,
1677 0xc9, 0xe4, 0x33, 0xef, 0x89, 0x5c, 0x66, 0x99, 0xd8, 0x80, 0x81, 0x47, 0x2b,
1678 0xb1, 0x66, 0x02, 0x84, 0x59, 0x7b, 0xc3, 0xbe, 0x98, 0x45, 0x4a, 0x3d, 0xdd,
1679 0xea, 0x2b, 0xdf, 0x4e, 0xb4, 0x24, 0x6b, 0xec, 0xe7, 0xd9, 0x0c, 0x45, 0xb8,
1680 0xbe, 0xca, 0x69, 0x37, 0x92, 0x4c, 0x38, 0x6b, 0x96, 0x6d, 0xcd, 0x86, 0x67,
1681 0x5c, 0xea, 0x54, 0x94, 0xa4, 0xca, 0xa4, 0x02, 0xa5, 0x21, 0x4d, 0xae, 0x40,
1682 0x8f, 0x9d, 0x51, 0x83, 0xf2, 0x3f, 0x33, 0xc1, 0x72, 0xb4, 0x1d, 0x94, 0x6e,
1683 0x7d, 0xe4, 0x27, 0x3f, 0xea, 0xff, 0xe5, 0x9b, 0xa7, 0x5e, 0x55, 0x8e, 0x0d,
1684 0x69, 0x1c, 0x7a, 0xff, 0x81, 0x9d, 0x53, 0x52, 0x97, 0x9a, 0x76, 0x79, 0xda,
1685 0x93, 0x32, 0x16, 0xec, 0x69, 0x51, 0x1a, 0x4e, 0xc3, 0xf1, 0x72, 0x80, 0x78,
1686 0x5e, 0x66, 0x4a, 0x8d, 0x85, 0x2f, 0x3f, 0xb2, 0xa7 };
1688 static const BYTE selfSignedCert[] = {
1689 0x30, 0x82, 0x01, 0x1f, 0x30, 0x81, 0xce, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02,
1690 0x10, 0xeb, 0x0d, 0x57, 0x2a, 0x9c, 0x09, 0xba, 0xa4, 0x4a, 0xb7, 0x25, 0x49,
1691 0xd9, 0x3e, 0xb5, 0x73, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1d,
1692 0x05, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03,
1693 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30,
1694 0x1e, 0x17, 0x0d, 0x30, 0x36, 0x30, 0x36, 0x32, 0x39, 0x30, 0x35, 0x30, 0x30,
1695 0x34, 0x36, 0x5a, 0x17, 0x0d, 0x30, 0x37, 0x30, 0x36, 0x32, 0x39, 0x31, 0x31,
1696 0x30, 0x30, 0x34, 0x36, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03,
1697 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e,
1698 0x67, 0x00, 0x30, 0x5c, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
1699 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x4b, 0x00, 0x30, 0x48, 0x02, 0x41,
1700 0x00, 0xe2, 0x54, 0x3a, 0xa7, 0x83, 0xb1, 0x27, 0x14, 0x3e, 0x59, 0xbb, 0xb4,
1701 0x53, 0xe6, 0x1f, 0xe7, 0x5d, 0xf1, 0x21, 0x68, 0xad, 0x85, 0x53, 0xdb, 0x6b,
1702 0x1e, 0xeb, 0x65, 0x97, 0x03, 0x86, 0x60, 0xde, 0xf3, 0x6c, 0x38, 0x75, 0xe0,
1703 0x4c, 0x61, 0xbb, 0xbc, 0x62, 0x17, 0xa9, 0xcd, 0x79, 0x3f, 0x21, 0x4e, 0x96,
1704 0xcb, 0x0e, 0xdc, 0x61, 0x94, 0x30, 0x18, 0x10, 0x6b, 0xd0, 0x1c, 0x10, 0x79,
1705 0x02, 0x03, 0x01, 0x00, 0x01, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02,
1706 0x1d, 0x05, 0x00, 0x03, 0x41, 0x00, 0x25, 0x90, 0x53, 0x34, 0xd9, 0x56, 0x41,
1707 0x5e, 0xdb, 0x7e, 0x01, 0x36, 0xec, 0x27, 0x61, 0x5e, 0xb7, 0x4d, 0x90, 0x66,
1708 0xa2, 0xe1, 0x9d, 0x58, 0x76, 0xd4, 0x9c, 0xba, 0x2c, 0x84, 0xc6, 0x83, 0x7a,
1709 0x22, 0x0d, 0x03, 0x69, 0x32, 0x1a, 0x6d, 0xcb, 0x0c, 0x15, 0xb3, 0x6b, 0xc7,
1710 0x0a, 0x8c, 0xb4, 0x5c, 0x34, 0x78, 0xe0, 0x3c, 0x9c, 0xe9, 0xf3, 0x30, 0x9f,
1711 0xa8, 0x76, 0x57, 0x92, 0x36 };
1713 static const BYTE exportedPublicKeyBlob[] = {
1714 0x06,0x02,0x00,0x00,0x00,0xa4,0x00,0x00,0x52,0x53,0x41,0x31,0x00,0x02,0x00,0x00,
1715 0x01,0x00,0x01,0x00,0x79,0x10,0x1c,0xd0,0x6b,0x10,0x18,0x30,0x94,0x61,0xdc,0x0e,
1716 0xcb,0x96,0x4e,0x21,0x3f,0x79,0xcd,0xa9,0x17,0x62,0xbc,0xbb,0x61,0x4c,0xe0,0x75,
1717 0x38,0x6c,0xf3,0xde,0x60,0x86,0x03,0x97,0x65,0xeb,0x1e,0x6b,0xdb,0x53,0x85,0xad,
1718 0x68,0x21,0xf1,0x5d,0xe7,0x1f,0xe6,0x53,0xb4,0xbb,0x59,0x3e,0x14,0x27,0xb1,0x83,
1719 0xa7,0x3a,0x54,0xe2 };
1721 static const BYTE asnEncodedPublicKey[] = {
1722 0x30,0x48,0x02,0x41,0x00,0xe2,0x54,0x3a,0xa7,0x83,0xb1,0x27,0x14,0x3e,0x59,0xbb,
1723 0xb4,0x53,0xe6,0x1f,0xe7,0x5d,0xf1,0x21,0x68,0xad,0x85,0x53,0xdb,0x6b,0x1e,0xeb,
1724 0x65,0x97,0x03,0x86,0x60,0xde,0xf3,0x6c,0x38,0x75,0xe0,0x4c,0x61,0xbb,0xbc,0x62,
1725 0x17,0xa9,0xcd,0x79,0x3f,0x21,0x4e,0x96,0xcb,0x0e,0xdc,0x61,0x94,0x30,0x18,0x10,
1726 0x6b,0xd0,0x1c,0x10,0x79,0x02,0x03,0x01,0x00,0x01 };
1728 static void testAcquireCertPrivateKey(void)
1731 PCCERT_CONTEXT cert;
1733 DWORD size, keySpec;
1735 CRYPT_KEY_PROV_INFO keyProvInfo;
1738 keyProvInfo.pwszContainerName = (LPWSTR)cspNameW;
1739 keyProvInfo.pwszProvName = (LPWSTR)MS_DEF_PROV_W;
1740 keyProvInfo.dwProvType = PROV_RSA_FULL;
1741 keyProvInfo.dwFlags = 0;
1742 keyProvInfo.cProvParam = 0;
1743 keyProvInfo.rgProvParam = NULL;
1744 keyProvInfo.dwKeySpec = AT_SIGNATURE;
1746 CryptAcquireContextW(NULL, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
1747 CRYPT_DELETEKEYSET);
1749 cert = CertCreateCertificateContext(X509_ASN_ENCODING, selfSignedCert,
1750 sizeof(selfSignedCert));
1753 ret = CryptAcquireCertificatePrivateKey(NULL, 0, NULL, NULL, NULL, NULL);
1754 ret = CryptAcquireCertificatePrivateKey(NULL, 0, NULL, NULL, NULL,
1756 ret = CryptAcquireCertificatePrivateKey(NULL, 0, NULL, NULL, &keySpec,
1758 ret = CryptAcquireCertificatePrivateKey(NULL, 0, NULL, &csp, NULL, NULL);
1759 ret = CryptAcquireCertificatePrivateKey(NULL, 0, NULL, &csp, &keySpec,
1761 ret = CryptAcquireCertificatePrivateKey(cert, 0, NULL, NULL, NULL, NULL);
1764 /* Missing private key */
1765 ret = CryptAcquireCertificatePrivateKey(cert, 0, NULL, &csp, NULL, NULL);
1766 ok(!ret && GetLastError() == CRYPT_E_NO_KEY_PROPERTY,
1767 "Expected CRYPT_E_NO_KEY_PROPERTY, got %08lx\n", GetLastError());
1768 ret = CryptAcquireCertificatePrivateKey(cert, 0, NULL, &csp, &keySpec,
1770 ok(!ret && GetLastError() == CRYPT_E_NO_KEY_PROPERTY,
1771 "Expected CRYPT_E_NO_KEY_PROPERTY, got %08lx\n", GetLastError());
1772 CertSetCertificateContextProperty(cert, CERT_KEY_PROV_INFO_PROP_ID, 0,
1774 ret = CryptAcquireCertificatePrivateKey(cert, 0, NULL, &csp, &keySpec,
1776 ok(!ret && GetLastError() == CRYPT_E_NO_KEY_PROPERTY,
1777 "Expected CRYPT_E_NO_KEY_PROPERTY, got %08lx\n", GetLastError());
1779 CryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
1781 ret = CryptImportKey(csp, (LPBYTE)privKey, sizeof(privKey), 0, 0, &key);
1782 ok(ret, "CryptImportKey failed: %08lx\n", GetLastError());
1787 CERT_KEY_CONTEXT keyContext;
1789 /* Don't cache provider */
1790 ret = CryptAcquireCertificatePrivateKey(cert, 0, NULL, &certCSP,
1791 &keySpec, &callerFree);
1792 ok(ret, "CryptAcquireCertificatePrivateKey failed: %08lx\n",
1794 ok(callerFree, "Expected callerFree to be TRUE\n");
1795 CryptReleaseContext(certCSP, 0);
1796 ret = CryptAcquireCertificatePrivateKey(cert, 0, NULL, &certCSP,
1798 ok(ret, "CryptAcquireCertificatePrivateKey failed: %08lx\n",
1800 CryptReleaseContext(certCSP, 0);
1802 /* Use the key prov info's caching (there shouldn't be any) */
1803 ret = CryptAcquireCertificatePrivateKey(cert,
1804 CRYPT_ACQUIRE_USE_PROV_INFO_FLAG, NULL, &certCSP, &keySpec,
1806 ok(ret, "CryptAcquireCertificatePrivateKey failed: %08lx\n",
1808 ok(callerFree, "Expected callerFree to be TRUE\n");
1809 CryptReleaseContext(certCSP, 0);
1811 /* Cache it (and check that it's cached) */
1812 ret = CryptAcquireCertificatePrivateKey(cert,
1813 CRYPT_ACQUIRE_CACHE_FLAG, NULL, &certCSP, &keySpec, &callerFree);
1814 ok(ret, "CryptAcquireCertificatePrivateKey failed: %08lx\n",
1816 ok(!callerFree, "Expected callerFree to be FALSE\n");
1817 size = sizeof(keyContext);
1818 ret = CertGetCertificateContextProperty(cert, CERT_KEY_CONTEXT_PROP_ID,
1819 &keyContext, &size);
1820 ok(ret, "CertGetCertificateContextProperty failed: %08lx\n",
1823 /* Remove the cached provider */
1824 CryptReleaseContext(keyContext.hCryptProv, 0);
1825 CertSetCertificateContextProperty(cert, CERT_KEY_CONTEXT_PROP_ID, 0,
1827 /* Allow caching via the key prov info */
1828 keyProvInfo.dwFlags = CERT_SET_KEY_CONTEXT_PROP_ID;
1829 CertSetCertificateContextProperty(cert, CERT_KEY_PROV_INFO_PROP_ID, 0,
1831 /* Now use the key prov info's caching */
1832 ret = CryptAcquireCertificatePrivateKey(cert,
1833 CRYPT_ACQUIRE_USE_PROV_INFO_FLAG, NULL, &certCSP, &keySpec,
1835 ok(ret, "CryptAcquireCertificatePrivateKey failed: %08lx\n",
1837 ok(!callerFree, "Expected callerFree to be FALSE\n");
1838 size = sizeof(keyContext);
1839 ret = CertGetCertificateContextProperty(cert, CERT_KEY_CONTEXT_PROP_ID,
1840 &keyContext, &size);
1841 ok(ret, "CertGetCertificateContextProperty failed: %08lx\n",
1844 CryptDestroyKey(key);
1847 /* Some sanity-checking on public key exporting */
1848 ret = CryptImportPublicKeyInfo(csp, X509_ASN_ENCODING,
1849 &cert->pCertInfo->SubjectPublicKeyInfo, &key);
1850 ok(ret, "CryptImportPublicKeyInfo failed: %08lx\n", GetLastError());
1853 ret = CryptExportKey(key, 0, PUBLICKEYBLOB, 0, NULL, &size);
1854 ok(ret, "CryptExportKey failed: %08lx\n", GetLastError());
1857 LPBYTE buf = HeapAlloc(GetProcessHeap(), 0, size), encodedKey;
1859 ret = CryptExportKey(key, 0, PUBLICKEYBLOB, 0, buf, &size);
1860 ok(ret, "CryptExportKey failed: %08lx\n", GetLastError());
1861 ok(size == sizeof(exportedPublicKeyBlob), "Unexpected size %ld\n",
1863 ok(!memcmp(buf, exportedPublicKeyBlob, size), "Unexpected value\n");
1864 ret = CryptEncodeObjectEx(X509_ASN_ENCODING, RSA_CSP_PUBLICKEYBLOB,
1865 buf, CRYPT_ENCODE_ALLOC_FLAG, NULL, &encodedKey, &size);
1866 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
1869 ok(size == sizeof(asnEncodedPublicKey), "Unexpected size %ld\n",
1871 ok(!memcmp(encodedKey, asnEncodedPublicKey, size),
1872 "Unexpected value\n");
1873 LocalFree(encodedKey);
1875 HeapFree(GetProcessHeap(), 0, buf);
1877 CryptDestroyKey(key);
1879 ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING,
1880 NULL, 0, NULL, NULL, &size);
1881 ok(ret, "CryptExportPublicKeyInfoEx failed: %08lx\n", GetLastError());
1884 PCERT_PUBLIC_KEY_INFO info = HeapAlloc(GetProcessHeap(), 0, size);
1886 ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING,
1887 NULL, 0, NULL, info, &size);
1888 ok(ret, "CryptExportPublicKeyInfoEx failed: %08lx\n", GetLastError());
1891 ok(info->PublicKey.cbData == sizeof(asnEncodedPublicKey),
1892 "Unexpected size %ld\n", info->PublicKey.cbData);
1893 ok(!memcmp(info->PublicKey.pbData, asnEncodedPublicKey,
1894 info->PublicKey.cbData), "Unexpected value\n");
1896 HeapFree(GetProcessHeap(), 0, info);
1899 CryptReleaseContext(csp, 0);
1900 CryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
1901 CRYPT_DELETEKEYSET);
1903 CertFreeCertificateContext(cert);
1908 init_function_pointers();
1911 testCertProperties();
1914 testGetSubjectCert();
1915 testGetIssuerCert();
1917 testCryptHashCert();
1919 testCreateSelfSignCert();
1921 testCompareCertName();
1922 testCompareIntegerBlob();
1923 testComparePublicKeyInfo();
1924 testHashPublicKeyInfo();
1926 testVerifySubjectCert();
1927 testAcquireCertPrivateKey();