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 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 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 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 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 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: %d\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 %08x\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 %08x\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: %08x\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: %08x\n",
171 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
172 bigCert2, sizeof(bigCert2), CERT_STORE_ADD_NEW, NULL);
173 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\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: %08x\n",
180 ok(context != NULL, "Expected a context\n");
183 CRYPT_DATA_BLOB hash = { sizeof(bigCert2Hash), bigCert2Hash };
185 /* Duplicate (AddRef) the context so we can still use it after
186 * deleting it from the store.
188 CertDuplicateCertificateContext(context);
189 CertDeleteCertificateFromStore(context);
190 /* Set the same hash as bigCert2, and try to readd it */
191 ret = CertSetCertificateContextProperty(context, CERT_HASH_PROP_ID,
193 ok(ret, "CertSetCertificateContextProperty failed: %08x\n",
195 ret = CertAddCertificateContextToStore(store, context,
196 CERT_STORE_ADD_NEW, NULL);
197 /* The failure is a bit odd (CRYPT_E_ASN1_BADTAG), so just check
200 ok(!ret, "Expected failure\n");
201 CertFreeCertificateContext(context);
203 context = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert2,
205 ok(context != NULL, "Expected a context\n");
208 /* Try to readd bigCert2 to the store */
209 ret = CertAddCertificateContextToStore(store, context,
210 CERT_STORE_ADD_NEW, NULL);
211 ok(!ret && GetLastError() == CRYPT_E_EXISTS,
212 "Expected CRYPT_E_EXISTS, got %08x\n", GetLastError());
213 CertFreeCertificateContext(context);
216 /* Adding a cert with the same issuer name and serial number (but
217 * different subject) as an existing cert succeeds.
220 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
221 bigCert2WithDifferentSerial, sizeof(bigCert2WithDifferentSerial),
222 CERT_STORE_ADD_NEW, &context);
223 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
226 CertDeleteCertificateFromStore(context);
228 /* Adding a cert with the same subject name and serial number (but
229 * different issuer) as an existing cert succeeds.
232 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
233 bigCertWithDifferentSubject, sizeof(bigCertWithDifferentSubject),
234 CERT_STORE_ADD_NEW, &context);
235 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
238 CertDeleteCertificateFromStore(context);
240 /* Adding a cert with the same issuer name and serial number (but
241 * different otherwise) as an existing cert succeeds.
244 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
245 bigCertWithDifferentIssuer, sizeof(bigCertWithDifferentIssuer),
246 CERT_STORE_ADD_NEW, &context);
247 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
250 CertDeleteCertificateFromStore(context);
252 collection = CertOpenStore(CERT_STORE_PROV_COLLECTION, 0, 0,
253 CERT_STORE_CREATE_NEW_FLAG, NULL);
254 ok(collection != NULL, "CertOpenStore failed: %08x\n", GetLastError());
257 /* Add store to the collection, but disable updates */
258 CertAddStoreToCollection(collection, store, 0, 0);
260 context = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert2,
262 ok(context != NULL, "Expected a context\n");
265 /* Try to readd bigCert2 to the collection */
266 ret = CertAddCertificateContextToStore(collection, context,
267 CERT_STORE_ADD_NEW, NULL);
268 ok(!ret && GetLastError() == CRYPT_E_EXISTS,
269 "Expected CRYPT_E_EXISTS, got %08x\n", GetLastError());
270 /* Replacing an existing certificate context is allowed, even
271 * though updates to the collection aren't..
273 ret = CertAddCertificateContextToStore(collection, context,
274 CERT_STORE_ADD_REPLACE_EXISTING, NULL);
275 ok(ret, "CertAddCertificateContextToStore failed: %08x\n",
277 /* but adding a new certificate isn't allowed. */
278 ret = CertAddCertificateContextToStore(collection, context,
279 CERT_STORE_ADD_ALWAYS, NULL);
280 ok(!ret && GetLastError() == E_ACCESSDENIED,
281 "Expected E_ACCESSDENIED, got %08x\n", GetLastError());
282 CertFreeCertificateContext(context);
285 CertCloseStore(collection, 0);
288 CertCloseStore(store, 0);
291 static void checkHash(const BYTE *data, DWORD dataLen, ALG_ID algID,
292 PCCERT_CONTEXT context, DWORD propID)
294 BYTE hash[20] = { 0 }, hashProperty[20];
297 DWORD dwSizeWithNull;
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: %08x\n", GetLastError());
304 ret = CertGetCertificateContextProperty(context, propID, NULL,
306 ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
308 ret = CertGetCertificateContextProperty(context, propID, hashProperty,
310 ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
312 ok(!memcmp(hash, hashProperty, size), "Unexpected hash for property %d\n",
314 ok(size == dwSizeWithNull, "Unexpected length of hash for property: received %d instead of %d\n",
315 dwSizeWithNull,size);
318 static WCHAR cspNameW[] = { 'W','i','n','e','C','r','y','p','t','T','e','m','p',0 };
320 static void testCertProperties(void)
322 PCCERT_CONTEXT context = CertCreateCertificateContext(X509_ASN_ENCODING,
323 bigCert, sizeof(bigCert));
324 DWORD propID, numProps, access, size;
326 BYTE hash[20] = { 0 }, hashProperty[20];
327 CRYPT_DATA_BLOB blob;
328 CERT_KEY_CONTEXT keyContext;
331 ok(context != NULL, "CertCreateCertificateContext failed: %08x\n",
337 propID = CertEnumCertificateContextProperties(NULL, 0);
343 propID = CertEnumCertificateContextProperties(context, propID);
346 } while (propID != 0);
347 ok(numProps == 0, "Expected 0 properties, got %d\n", numProps);
349 /* Tests with a NULL cert context. Prop ID 0 fails.. */
350 ret = CertSetCertificateContextProperty(NULL, 0, 0, NULL);
351 ok(!ret && GetLastError() == E_INVALIDARG,
352 "Expected E_INVALIDARG, got %08x\n", GetLastError());
353 /* while this just crashes.
354 ret = CertSetCertificateContextProperty(NULL,
355 CERT_KEY_PROV_HANDLE_PROP_ID, 0, NULL);
358 ret = CertSetCertificateContextProperty(context, 0, 0, NULL);
359 ok(!ret && GetLastError() == E_INVALIDARG,
360 "Expected E_INVALIDARG, got %08x\n", GetLastError());
361 /* Can't set the cert property directly, this crashes.
362 ret = CertSetCertificateContextProperty(context,
363 CERT_CERT_PROP_ID, 0, bigCert2);
367 ret = CertGetCertificateContextProperty(context,
368 CERT_ACCESS_STATE_PROP_ID, 0, NULL);
369 ret = CertGetCertificateContextProperty(context, CERT_HASH_PROP_ID,
371 ret = CertGetCertificateContextProperty(context, CERT_HASH_PROP_ID,
376 ret = CertGetCertificateContextProperty(context,
377 CERT_KEY_PROV_INFO_PROP_ID, NULL, &size);
378 ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
379 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
380 /* And, an implicit property */
381 size = sizeof(access);
382 ret = CertGetCertificateContextProperty(context,
383 CERT_ACCESS_STATE_PROP_ID, &access, &size);
384 ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
386 ok(!(access & CERT_ACCESS_STATE_WRITE_PERSIST_FLAG),
387 "Didn't expect a persisted cert\n");
388 /* Trying to set this "read only" property crashes.
389 access |= CERT_ACCESS_STATE_WRITE_PERSIST_FLAG;
390 ret = CertSetCertificateContextProperty(context,
391 CERT_ACCESS_STATE_PROP_ID, 0, &access);
394 /* Can I set the hash to an invalid hash? */
396 blob.cbData = sizeof(hash);
397 ret = CertSetCertificateContextProperty(context, CERT_HASH_PROP_ID, 0,
399 ok(ret, "CertSetCertificateContextProperty failed: %08x\n",
401 size = sizeof(hashProperty);
402 ret = CertGetCertificateContextProperty(context, CERT_HASH_PROP_ID,
403 hashProperty, &size);
404 ok(!memcmp(hashProperty, hash, sizeof(hash)), "Unexpected hash\n");
405 /* Delete the (bogus) hash, and get the real one */
406 ret = CertSetCertificateContextProperty(context, CERT_HASH_PROP_ID, 0,
408 ok(ret, "CertSetCertificateContextProperty failed: %08x\n",
410 checkHash(bigCert, sizeof(bigCert), CALG_SHA1, context,
413 /* Now that the hash property is set, we should get one property when
419 propID = CertEnumCertificateContextProperties(context, propID);
422 } while (propID != 0);
423 ok(numProps == 1, "Expected 1 properties, got %d\n", numProps);
425 /* Check a few other implicit properties */
426 checkHash(bigCert, sizeof(bigCert), CALG_MD5, context,
427 CERT_MD5_HASH_PROP_ID);
429 context->pCertInfo->Subject.pbData,
430 context->pCertInfo->Subject.cbData,
431 CALG_MD5, context, CERT_SUBJECT_NAME_MD5_HASH_PROP_ID);
433 context->pCertInfo->SubjectPublicKeyInfo.PublicKey.pbData,
434 context->pCertInfo->SubjectPublicKeyInfo.PublicKey.cbData,
435 CALG_MD5, context, CERT_SUBJECT_PUBLIC_KEY_MD5_HASH_PROP_ID);
437 /* Test key identifiers and handles and such */
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 %08x\n", GetLastError());
443 size = sizeof(CERT_KEY_CONTEXT);
444 ret = CertGetCertificateContextProperty(context,
445 CERT_KEY_IDENTIFIER_PROP_ID, NULL, &size);
446 ok(!ret && GetLastError() == ERROR_INVALID_DATA,
447 "Expected ERROR_INVALID_DATA, got %08x\n", GetLastError());
448 ret = CertGetCertificateContextProperty(context,
449 CERT_KEY_IDENTIFIER_PROP_ID, &keyContext, &size);
450 ok(!ret && GetLastError() == ERROR_INVALID_DATA,
451 "Expected ERROR_INVALID_DATA, got %08x\n", GetLastError());
452 /* Key context with an invalid size */
453 keyContext.cbSize = 0;
454 ret = CertSetCertificateContextProperty(context,
455 CERT_KEY_IDENTIFIER_PROP_ID, 0, &keyContext);
456 ok(ret, "CertSetCertificateContextProperty failed: %08x\n",
458 size = sizeof(keyContext);
459 ret = CertGetCertificateContextProperty(context,
460 CERT_KEY_IDENTIFIER_PROP_ID, &keyContext, &size);
461 ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
463 keyContext.cbSize = sizeof(keyContext);
464 keyContext.hCryptProv = 0;
465 keyContext.dwKeySpec = AT_SIGNATURE;
467 ret = CertSetCertificateContextProperty(context,
468 CERT_KEY_IDENTIFIER_PROP_ID, 0, &keyContext);
469 ret = CertSetCertificateContextProperty(context,
470 CERT_KEY_IDENTIFIER_PROP_ID, CERT_STORE_NO_CRYPT_RELEASE_FLAG,
473 ret = CryptAcquireContextW(&csp, cspNameW,
474 MS_DEF_PROV_W, PROV_RSA_FULL, CRYPT_NEWKEYSET);
475 ok(ret, "CryptAcquireContextW failed: %08x\n", GetLastError());
476 keyContext.hCryptProv = csp;
477 ret = CertSetCertificateContextProperty(context,
478 CERT_KEY_CONTEXT_PROP_ID, 0, &keyContext);
479 ok(ret, "CertSetCertificateContextProperty failed: %08x\n",
481 /* Now that that's set, the key prov handle property is also gettable.
483 size = sizeof(DWORD);
484 ret = CertGetCertificateContextProperty(context,
485 CERT_KEY_PROV_HANDLE_PROP_ID, &keyContext.hCryptProv, &size);
486 ok(ret, "Expected to get the CERT_KEY_PROV_HANDLE_PROP_ID, got %08x\n",
488 /* Remove the key prov handle property.. */
489 ret = CertSetCertificateContextProperty(context,
490 CERT_KEY_PROV_HANDLE_PROP_ID, 0, NULL);
491 ok(ret, "CertSetCertificateContextProperty failed: %08x\n",
493 /* and the key context's CSP is set to NULL. */
494 size = sizeof(keyContext);
495 ret = CertGetCertificateContextProperty(context,
496 CERT_KEY_CONTEXT_PROP_ID, &keyContext, &size);
497 ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
499 ok(keyContext.hCryptProv == 0, "Expected no hCryptProv\n");
501 CryptReleaseContext(csp, 0);
503 CertFreeCertificateContext(context);
506 static void testDupCert(void)
509 PCCERT_CONTEXT context, dupContext;
512 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
513 CERT_STORE_CREATE_NEW_FLAG, NULL);
514 ok(store != NULL, "CertOpenStore failed: %d\n", GetLastError());
518 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
519 bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, &context);
520 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
522 ok(context != NULL, "Expected a valid cert context\n");
525 ok(context->cbCertEncoded == sizeof(bigCert),
526 "Wrong cert size %d\n", context->cbCertEncoded);
527 ok(!memcmp(context->pbCertEncoded, bigCert, sizeof(bigCert)),
528 "Unexpected encoded cert in context\n");
529 ok(context->hCertStore == store, "Unexpected store\n");
531 dupContext = CertDuplicateCertificateContext(context);
532 ok(dupContext != NULL, "Expected valid duplicate\n");
533 /* Not only is it a duplicate, it's identical: the address is the
536 ok(dupContext == context, "Expected identical context addresses\n");
537 CertFreeCertificateContext(dupContext);
538 CertFreeCertificateContext(context);
540 CertCloseStore(store, 0);
543 static void testFindCert(void)
546 PCCERT_CONTEXT context = NULL;
548 CERT_INFO certInfo = { 0 };
549 CRYPT_HASH_BLOB blob;
551 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
552 CERT_STORE_CREATE_NEW_FLAG, NULL);
553 ok(store != NULL, "CertOpenStore failed: %d\n", GetLastError());
557 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
558 bigCert, sizeof(bigCert), CERT_STORE_ADD_NEW, NULL);
559 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
561 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
562 bigCert2, sizeof(bigCert2), CERT_STORE_ADD_NEW, NULL);
563 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
565 /* This has the same name as bigCert */
566 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
567 certWithUsage, sizeof(certWithUsage), CERT_STORE_ADD_NEW, NULL);
568 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
572 context = CertFindCertificateInStore(NULL, 0, 0, 0, NULL, NULL);
575 /* Check first cert's there, by issuer */
576 certInfo.Subject.pbData = subjectName;
577 certInfo.Subject.cbData = sizeof(subjectName);
578 certInfo.SerialNumber.pbData = serialNum;
579 certInfo.SerialNumber.cbData = sizeof(serialNum);
580 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
581 CERT_FIND_ISSUER_NAME, &certInfo.Subject, NULL);
582 ok(context != NULL, "CertFindCertificateInStore failed: %08x\n",
586 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
587 CERT_FIND_ISSUER_NAME, &certInfo.Subject, context);
588 ok(context != NULL, "Expected more than one cert\n");
591 context = CertFindCertificateInStore(store, X509_ASN_ENCODING,
592 0, CERT_FIND_ISSUER_NAME, &certInfo.Subject, context);
593 ok(context == NULL, "Expected precisely two certs\n");
597 /* Check second cert's there as well, by subject name */
598 certInfo.Subject.pbData = subjectName2;
599 certInfo.Subject.cbData = sizeof(subjectName2);
600 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
601 CERT_FIND_SUBJECT_NAME, &certInfo.Subject, NULL);
602 ok(context != NULL, "CertFindCertificateInStore failed: %08x\n",
606 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
607 CERT_FIND_SUBJECT_NAME, &certInfo.Subject, context);
608 ok(context == NULL, "Expected one cert only\n");
611 /* Strange but true: searching for the subject cert requires you to set
612 * the issuer, not the subject
614 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
615 CERT_FIND_SUBJECT_CERT, &certInfo.Subject, NULL);
616 ok(context == NULL, "Expected no certificate\n");
617 certInfo.Subject.pbData = NULL;
618 certInfo.Subject.cbData = 0;
619 certInfo.Issuer.pbData = subjectName2;
620 certInfo.Issuer.cbData = sizeof(subjectName2);
621 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
622 CERT_FIND_SUBJECT_CERT, &certInfo, NULL);
623 ok(context != NULL, "CertFindCertificateInStore failed: %08x\n",
627 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
628 CERT_FIND_SUBJECT_CERT, &certInfo.Subject, context);
629 ok(context == NULL, "Expected one cert only\n");
632 /* The nice thing about hashes, they're unique */
633 blob.pbData = bigCertHash;
634 blob.cbData = sizeof(bigCertHash);
635 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
636 CERT_FIND_SHA1_HASH, &blob, NULL);
637 ok(context != NULL, "CertFindCertificateInStore failed: %08x\n",
641 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
642 CERT_FIND_SHA1_HASH, &certInfo.Subject, context);
643 ok(context == NULL, "Expected one cert only\n");
646 CertCloseStore(store, 0);
649 static void testGetSubjectCert(void)
652 PCCERT_CONTEXT context1, context2;
653 CERT_INFO info = { 0 };
656 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
657 CERT_STORE_CREATE_NEW_FLAG, NULL);
658 ok(store != NULL, "CertOpenStore failed: %d\n", GetLastError());
662 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
663 bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL);
664 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
666 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
667 bigCert2, sizeof(bigCert2), CERT_STORE_ADD_NEW, &context1);
668 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
670 ok(context1 != NULL, "Expected a context\n");
671 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
672 certWithUsage, sizeof(certWithUsage), CERT_STORE_ADD_NEW, NULL);
673 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
676 context2 = CertGetSubjectCertificateFromStore(store, X509_ASN_ENCODING,
678 ok(!context2 && GetLastError() == E_INVALIDARG,
679 "Expected E_INVALIDARG, got %08x\n", GetLastError());
680 context2 = CertGetSubjectCertificateFromStore(store, X509_ASN_ENCODING,
682 ok(!context2 && GetLastError() == CRYPT_E_NOT_FOUND,
683 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
684 info.SerialNumber.cbData = sizeof(serialNum);
685 info.SerialNumber.pbData = serialNum;
686 context2 = CertGetSubjectCertificateFromStore(store, X509_ASN_ENCODING,
688 ok(!context2 && GetLastError() == CRYPT_E_NOT_FOUND,
689 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
690 info.Issuer.cbData = sizeof(subjectName2);
691 info.Issuer.pbData = subjectName2;
692 context2 = CertGetSubjectCertificateFromStore(store, X509_ASN_ENCODING,
695 "CertGetSubjectCertificateFromStore failed: %08x\n", GetLastError());
696 /* Not only should this find a context, but it should be the same
697 * (same address) as context1.
699 ok(context1 == context2, "Expected identical context addresses\n");
700 CertFreeCertificateContext(context2);
702 CertFreeCertificateContext(context1);
703 CertCloseStore(store, 0);
706 /* This expires in 1970 or so */
707 static const BYTE expiredCert[] = { 0x30, 0x82, 0x01, 0x33, 0x30, 0x81, 0xe2,
708 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0xc4, 0xd7, 0x7f, 0x0e, 0x6f, 0xa6,
709 0x8c, 0xaa, 0x47, 0x47, 0x40, 0xe7, 0xb7, 0x0b, 0x4a, 0x7f, 0x30, 0x09, 0x06,
710 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1d, 0x05, 0x00, 0x30, 0x1f, 0x31, 0x1d, 0x30,
711 0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63, 0x40,
712 0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63,
713 0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x36, 0x39, 0x30, 0x31, 0x30, 0x31, 0x30,
714 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x37, 0x30, 0x30, 0x31, 0x30,
715 0x31, 0x30, 0x36, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x1f, 0x31, 0x1d, 0x30,
716 0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63, 0x40,
717 0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63,
718 0x6f, 0x6d, 0x30, 0x5c, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
719 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x4b, 0x00, 0x30, 0x48, 0x02, 0x41,
720 0x00, 0xa1, 0xaf, 0x4a, 0xea, 0xa7, 0x83, 0x57, 0xc0, 0x37, 0x33, 0x7e, 0x29,
721 0x5e, 0x0d, 0xfc, 0x44, 0x74, 0x3a, 0x1d, 0xc3, 0x1b, 0x1d, 0x96, 0xed, 0x4e,
722 0xf4, 0x1b, 0x98, 0xec, 0x69, 0x1b, 0x04, 0xea, 0x25, 0xcf, 0xb3, 0x2a, 0xf5,
723 0xd9, 0x22, 0xd9, 0x8d, 0x08, 0x39, 0x81, 0xc6, 0xe0, 0x4f, 0x12, 0x37, 0x2a,
724 0x3f, 0x80, 0xa6, 0x6c, 0x67, 0x43, 0x3a, 0xdd, 0x95, 0x0c, 0xbb, 0x2f, 0x6b,
725 0x02, 0x03, 0x01, 0x00, 0x01, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02,
726 0x1d, 0x05, 0x00, 0x03, 0x41, 0x00, 0x8f, 0xa2, 0x5b, 0xd6, 0xdf, 0x34, 0xd0,
727 0xa2, 0xa7, 0x47, 0xf1, 0x13, 0x79, 0xd3, 0xf3, 0x39, 0xbd, 0x4e, 0x2b, 0xa3,
728 0xf4, 0x63, 0x37, 0xac, 0x5a, 0x0c, 0x5e, 0x4d, 0x0d, 0x54, 0x87, 0x4f, 0x31,
729 0xfb, 0xa0, 0xce, 0x8f, 0x9a, 0x2f, 0x4d, 0x48, 0xc6, 0x84, 0x8d, 0xf5, 0x70,
730 0x74, 0x17, 0xa5, 0xf3, 0x66, 0x47, 0x06, 0xd6, 0x64, 0x45, 0xbc, 0x52, 0xef,
731 0x49, 0xe5, 0xf9, 0x65, 0xf3 };
733 /* This expires in 2036 or so */
734 static const BYTE childOfExpired[] = { 0x30, 0x81, 0xcc, 0x30, 0x78, 0xa0,
735 0x03, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86,
736 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x1f, 0x31, 0x1d,
737 0x30, 0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63,
738 0x40, 0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e,
739 0x63, 0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x30, 0x36, 0x30, 0x35, 0x30, 0x35,
740 0x31, 0x37, 0x31, 0x32, 0x34, 0x39, 0x5a, 0x17, 0x0d, 0x33, 0x36, 0x30, 0x35,
741 0x30, 0x35, 0x31, 0x37, 0x31, 0x32, 0x34, 0x39, 0x5a, 0x30, 0x15, 0x31, 0x13,
742 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e,
743 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03,
744 0x01, 0x00, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
745 0x01, 0x05, 0x05, 0x00, 0x03, 0x41, 0x00, 0x20, 0x3b, 0xdb, 0x4d, 0x67, 0x50,
746 0xec, 0x73, 0x9d, 0xf9, 0x85, 0x5d, 0x18, 0xe9, 0xb4, 0x98, 0xe3, 0x31, 0xb7,
747 0x03, 0x0b, 0xc0, 0x39, 0x93, 0x56, 0x81, 0x0a, 0xfc, 0x78, 0xa8, 0x29, 0x42,
748 0x5f, 0x69, 0xfb, 0xbc, 0x5b, 0xf2, 0xa6, 0x2a, 0xbe, 0x91, 0x2c, 0xfc, 0x89,
749 0x69, 0x15, 0x18, 0x58, 0xe5, 0x02, 0x75, 0xf7, 0x2a, 0xb6, 0xa9, 0xfb, 0x47,
750 0x6a, 0x6e, 0x0a, 0x9b, 0xe9, 0xdc };
752 static void testGetIssuerCert(void)
755 PCCERT_CONTEXT parent, child;
756 DWORD flags = 0xffffffff;
757 HCERTSTORE store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
758 CERT_STORE_CREATE_NEW_FLAG, NULL);
760 ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
762 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
763 expiredCert, sizeof(expiredCert), CERT_STORE_ADD_ALWAYS, NULL);
764 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
767 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
768 childOfExpired, sizeof(childOfExpired), CERT_STORE_ADD_ALWAYS, &child);
769 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
773 parent = CertGetIssuerCertificateFromStore(NULL, NULL, NULL, NULL);
774 parent = CertGetIssuerCertificateFromStore(store, NULL, NULL, NULL);
776 parent = CertGetIssuerCertificateFromStore(NULL, NULL, NULL, &flags);
777 ok(!parent && GetLastError() == E_INVALIDARG,
778 "Expected E_INVALIDARG, got %08x\n", GetLastError());
779 parent = CertGetIssuerCertificateFromStore(store, NULL, NULL, &flags);
780 ok(!parent && GetLastError() == E_INVALIDARG,
781 "Expected E_INVALIDARG, got %08x\n", GetLastError());
782 parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
783 ok(!parent && GetLastError() == E_INVALIDARG,
784 "Expected E_INVALIDARG, got %08x\n", GetLastError());
785 /* Confusing: the caller cannot set either of the
786 * CERT_STORE_NO_*_FLAGs, as these are not checks,
789 flags = CERT_STORE_NO_CRL_FLAG | CERT_STORE_NO_ISSUER_FLAG;
790 parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
791 ok(!parent && GetLastError() == E_INVALIDARG,
792 "Expected E_INVALIDARG, got %08x\n", GetLastError());
793 /* Perform no checks */
795 parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
796 ok(parent != NULL, "CertGetIssuerCertificateFromStore failed: %08x\n",
799 CertFreeCertificateContext(parent);
800 /* Check revocation and signature only */
801 flags = CERT_STORE_REVOCATION_FLAG | CERT_STORE_SIGNATURE_FLAG;
802 parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
803 ok(parent != NULL, "CertGetIssuerCertificateFromStore failed: %08x\n",
805 /* Confusing: CERT_STORE_REVOCATION_FLAG succeeds when there is no CRL by
806 * setting CERT_STORE_NO_CRL_FLAG.
808 ok(flags == (CERT_STORE_REVOCATION_FLAG | CERT_STORE_NO_CRL_FLAG),
809 "Expected CERT_STORE_REVOCATION_FLAG | CERT_STORE_NO_CRL_FLAG, got %08x\n",
812 CertFreeCertificateContext(parent);
813 /* Now check just the time */
814 flags = CERT_STORE_TIME_VALIDITY_FLAG;
815 parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
816 ok(parent != NULL, "CertGetIssuerCertificateFromStore failed: %08x\n",
818 /* Oops: the child is not expired, so the time validity check actually
819 * succeeds, even though the signing cert is expired.
821 ok(!flags, "Expected check to succeed, got %08x\n", flags);
823 CertFreeCertificateContext(parent);
825 CertFreeCertificateContext(child);
826 CertCloseStore(store, 0);
829 static void testCryptHashCert(void)
831 static const BYTE emptyHash[] = { 0xda, 0x39, 0xa3, 0xee, 0x5e, 0x6b, 0x4b,
832 0x0d, 0x32, 0x55, 0xbf, 0xef, 0x95, 0x60, 0x18, 0x90, 0xaf, 0xd8, 0x07,
834 static const BYTE knownHash[] = { 0xae, 0x9d, 0xbf, 0x6d, 0xf5, 0x46, 0xee,
835 0x8b, 0xc5, 0x7a, 0x13, 0xba, 0xc2, 0xb1, 0x04, 0xf2, 0xbf, 0x52, 0xa8,
837 static const BYTE toHash[] = "abcdefghijklmnopqrstuvwxyz0123456789.,;!?:";
840 DWORD hashLen = sizeof(hash);
842 /* NULL buffer and nonzero length crashes
843 ret = CryptHashCertificate(0, 0, 0, NULL, size, hash, &hashLen);
844 empty hash length also crashes
845 ret = CryptHashCertificate(0, 0, 0, buf, size, hash, NULL);
847 /* Test empty hash */
848 ret = CryptHashCertificate(0, 0, 0, toHash, sizeof(toHash), NULL,
850 ok(ret, "CryptHashCertificate failed: %08x\n", GetLastError());
851 ok(hashLen == sizeof(hash), "Got unexpected size of hash %d\n", hashLen);
852 /* Test with empty buffer */
853 ret = CryptHashCertificate(0, 0, 0, NULL, 0, hash, &hashLen);
854 ok(ret, "CryptHashCertificate failed: %08x\n", GetLastError());
855 ok(!memcmp(hash, emptyHash, sizeof(emptyHash)),
856 "Unexpected hash of nothing\n");
857 /* Test a known value */
858 ret = CryptHashCertificate(0, 0, 0, toHash, sizeof(toHash), hash,
860 ok(ret, "CryptHashCertificate failed: %08x\n", GetLastError());
861 ok(!memcmp(hash, knownHash, sizeof(knownHash)), "Unexpected hash\n");
864 static void verifySig(HCRYPTPROV csp, const BYTE *toSign, size_t toSignLen,
865 const BYTE *sig, unsigned int sigLen)
868 BOOL ret = CryptCreateHash(csp, CALG_SHA1, 0, 0, &hash);
870 ok(ret, "CryptCreateHash failed: %08x\n", GetLastError());
874 DWORD mySigSize = sizeof(mySig);
876 ret = CryptHashData(hash, toSign, toSignLen, 0);
877 ok(ret, "CryptHashData failed: %08x\n", GetLastError());
878 /* use the A variant so the test can run on Win9x */
879 ret = CryptSignHashA(hash, AT_SIGNATURE, NULL, 0, mySig, &mySigSize);
880 ok(ret, "CryptSignHash failed: %08x\n", GetLastError());
883 ok(mySigSize == sigLen, "Expected sig length %d, got %d\n",
885 ok(!memcmp(mySig, sig, sigLen), "Unexpected signature\n");
887 CryptDestroyHash(hash);
891 /* Tests signing the certificate described by toBeSigned with the CSP passed in,
892 * using the algorithm with OID sigOID. The CSP is assumed to be empty, and a
893 * keyset named AT_SIGNATURE will be added to it. The signing key will be
894 * stored in *key, and the signature will be stored in sig. sigLen should be
897 static void testSignCert(HCRYPTPROV csp, const CRYPT_DATA_BLOB *toBeSigned,
898 LPCSTR sigOID, HCRYPTKEY *key, BYTE *sig, DWORD *sigLen)
902 CRYPT_ALGORITHM_IDENTIFIER algoID = { NULL, { 0, NULL } };
905 ret = CryptSignCertificate(0, 0, 0, NULL, 0, NULL, NULL, NULL, NULL);
906 ret = CryptSignCertificate(0, 0, 0, NULL, 0, NULL, NULL, NULL, &size);
907 ret = CryptSignCertificate(0, 0, 0, toBeSigned->pbData, toBeSigned->cbData,
908 NULL, NULL, NULL, &size);
910 ret = CryptSignCertificate(0, 0, 0, toBeSigned->pbData, toBeSigned->cbData,
911 &algoID, NULL, NULL, &size);
912 ok(!ret && GetLastError() == NTE_BAD_ALGID,
913 "Expected NTE_BAD_ALGID, got %08x\n", GetLastError());
914 algoID.pszObjId = (LPSTR)sigOID;
915 ret = CryptSignCertificate(0, 0, 0, toBeSigned->pbData, toBeSigned->cbData,
916 &algoID, NULL, NULL, &size);
917 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
918 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
919 ret = CryptSignCertificate(0, AT_SIGNATURE, 0, toBeSigned->pbData,
920 toBeSigned->cbData, &algoID, NULL, NULL, &size);
921 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
922 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
924 /* No keys exist in the new CSP yet.. */
925 ret = CryptSignCertificate(csp, AT_SIGNATURE, 0, toBeSigned->pbData,
926 toBeSigned->cbData, &algoID, NULL, NULL, &size);
927 ok(!ret && (GetLastError() == NTE_BAD_KEYSET || GetLastError() ==
928 NTE_NO_KEY), "Expected NTE_BAD_KEYSET or NTE_NO_KEY, got %08x\n",
930 ret = CryptGenKey(csp, AT_SIGNATURE, 0, key);
931 ok(ret, "CryptGenKey failed: %08x\n", GetLastError());
934 ret = CryptSignCertificate(csp, AT_SIGNATURE, 0, toBeSigned->pbData,
935 toBeSigned->cbData, &algoID, NULL, NULL, &size);
936 ok(ret, "CryptSignCertificate failed: %08x\n", GetLastError());
937 ok(size <= *sigLen, "Expected size <= %d, got %d\n", *sigLen, size);
940 ret = CryptSignCertificate(csp, AT_SIGNATURE, 0, toBeSigned->pbData,
941 toBeSigned->cbData, &algoID, NULL, sig, &size);
942 ok(ret, "CryptSignCertificate failed: %08x\n", GetLastError());
946 verifySig(csp, toBeSigned->pbData, toBeSigned->cbData, sig,
953 static void testVerifyCertSig(HCRYPTPROV csp, const CRYPT_DATA_BLOB *toBeSigned,
954 LPCSTR sigOID, const BYTE *sig, DWORD sigLen)
956 CERT_SIGNED_CONTENT_INFO info;
961 if(pCryptVerifyCertificateSignatureEx) {
962 ret = pCryptVerifyCertificateSignatureEx(0, 0, 0, NULL, 0, NULL, 0, NULL);
963 ok(!ret && GetLastError() == E_INVALIDARG,
964 "Expected E_INVALIDARG, got %08x\n", GetLastError());
965 ret = pCryptVerifyCertificateSignatureEx(csp, 0, 0, NULL, 0, NULL, 0, NULL);
966 ok(!ret && GetLastError() == E_INVALIDARG,
967 "Expected E_INVALIDARG, got %08x\n", GetLastError());
968 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING, 0, NULL, 0,
970 ok(!ret && GetLastError() == E_INVALIDARG,
971 "Expected E_INVALIDARG, got %08x\n", GetLastError());
973 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
974 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, NULL, 0, NULL, 0, NULL);
977 info.ToBeSigned.cbData = toBeSigned->cbData;
978 info.ToBeSigned.pbData = toBeSigned->pbData;
979 info.SignatureAlgorithm.pszObjId = (LPSTR)sigOID;
980 info.SignatureAlgorithm.Parameters.cbData = 0;
981 info.Signature.cbData = sigLen;
982 info.Signature.pbData = (BYTE *)sig;
983 info.Signature.cUnusedBits = 0;
984 ret = CryptEncodeObjectEx(X509_ASN_ENCODING, X509_CERT, &info,
985 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&cert, &size);
986 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
989 CRYPT_DATA_BLOB certBlob = { 0, NULL };
990 PCERT_PUBLIC_KEY_INFO pubKeyInfo = NULL;
992 if(pCryptVerifyCertificateSignatureEx) {
993 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
994 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob, 0, NULL, 0, NULL);
995 ok(!ret && GetLastError() == CRYPT_E_ASN1_EOD,
996 "Expected CRYPT_E_ASN1_EOD, got %08x\n", GetLastError());
998 certBlob.pbData = (void *)0xdeadbeef;
999 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
1000 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob, 0, NULL, 0, NULL);
1001 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
1002 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
1003 certBlob.cbData = size;
1004 certBlob.pbData = cert;
1005 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
1006 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob, 0, NULL, 0, NULL);
1007 ok(!ret && GetLastError() == E_INVALIDARG,
1008 "Expected E_INVALIDARG, got %08x\n", GetLastError());
1009 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
1010 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob,
1011 CRYPT_VERIFY_CERT_SIGN_ISSUER_NULL, NULL, 0, NULL);
1012 ok(!ret && GetLastError() == E_INVALIDARG,
1013 "Expected E_INVALIDARG, got %08x\n", GetLastError());
1015 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
1016 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob,
1017 CRYPT_VERIFY_CERT_SIGN_ISSUER_PUBKEY, NULL, 0, NULL);
1020 CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING,
1021 (LPSTR)sigOID, 0, NULL, NULL, &size);
1022 pubKeyInfo = HeapAlloc(GetProcessHeap(), 0, size);
1025 ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE,
1026 X509_ASN_ENCODING, (LPSTR)sigOID, 0, NULL, pubKeyInfo, &size);
1027 ok(ret, "CryptExportKey failed: %08x\n", GetLastError());
1028 if (ret && pCryptVerifyCertificateSignatureEx)
1030 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
1031 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob,
1032 CRYPT_VERIFY_CERT_SIGN_ISSUER_PUBKEY, pubKeyInfo, 0, NULL);
1033 ok(ret, "CryptVerifyCertificateSignatureEx failed: %08x\n",
1036 HeapFree(GetProcessHeap(), 0, pubKeyInfo);
1042 static BYTE emptyCert[] = { 0x30, 0x00 };
1044 static void testCertSigs(void)
1047 CRYPT_DATA_BLOB toBeSigned = { sizeof(emptyCert), emptyCert };
1051 DWORD sigSize = sizeof(sig);
1053 /* Just in case a previous run failed, delete this thing */
1054 CryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
1055 CRYPT_DELETEKEYSET);
1056 ret = CryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
1058 ok(ret, "CryptAcquireContext failed: %08x\n", GetLastError());
1060 testSignCert(csp, &toBeSigned, szOID_RSA_SHA1RSA, &key, sig, &sigSize);
1061 testVerifyCertSig(csp, &toBeSigned, szOID_RSA_SHA1RSA, sig, sigSize);
1063 CryptDestroyKey(key);
1064 CryptReleaseContext(csp, 0);
1065 ret = CryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
1066 CRYPT_DELETEKEYSET);
1069 static const BYTE md5SignedEmptyCert[] = {
1070 0x30,0x56,0x30,0x33,0x02,0x00,0x30,0x02,0x06,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,
1071 0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,
1072 0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x07,
1073 0x30,0x02,0x06,0x00,0x03,0x01,0x00,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,
1074 0x0d,0x02,0x05,0x05,0x00,0x03,0x11,0x00,0xfb,0x0f,0x66,0x82,0x66,0xd9,0xe5,0xf8,
1075 0xd8,0xa2,0x55,0x2b,0xe1,0xa5,0xd9,0x04 };
1076 static const BYTE md5SignedEmptyCertNoNull[] = {
1077 0x30,0x54,0x30,0x33,0x02,0x00,0x30,0x02,0x06,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,
1078 0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,
1079 0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x07,
1080 0x30,0x02,0x06,0x00,0x03,0x01,0x00,0x30,0x0a,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,
1081 0x0d,0x02,0x05,0x03,0x11,0x00,0x04,0xd9,0xa5,0xe1,0x2b,0x55,0xa2,0xd8,0xf8,0xe5,
1082 0xd9,0x66,0x82,0x66,0x0f,0xfb };
1084 static void testSignAndEncodeCert(void)
1086 static char oid_rsa_md5rsa[] = szOID_RSA_MD5RSA;
1087 static char oid_rsa_md5[] = szOID_RSA_MD5;
1090 CRYPT_ALGORITHM_IDENTIFIER algID = { 0 };
1091 CERT_INFO info = { 0 };
1094 ret = CryptSignAndEncodeCertificate(0, 0, 0, NULL, NULL, NULL, NULL, NULL,
1096 ret = CryptSignAndEncodeCertificate(0, 0, 0, NULL, NULL, NULL, NULL, NULL,
1099 ret = CryptSignAndEncodeCertificate(0, 0, 0, NULL, NULL, &algID, NULL, NULL,
1101 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
1102 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
1103 ret = CryptSignAndEncodeCertificate(0, 0, X509_ASN_ENCODING, NULL, NULL,
1104 &algID, NULL, NULL, &size);
1105 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
1106 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
1107 ret = CryptSignAndEncodeCertificate(0, 0, 0, X509_CERT_TO_BE_SIGNED, NULL,
1108 &algID, NULL, NULL, &size);
1109 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
1110 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
1111 ret = CryptSignAndEncodeCertificate(0, 0, X509_ASN_ENCODING,
1112 X509_CERT_TO_BE_SIGNED, NULL, &algID, NULL, NULL, &size);
1113 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
1114 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
1116 ret = CryptSignAndEncodeCertificate(0, 0, X509_ASN_ENCODING,
1117 X509_CERT_TO_BE_SIGNED, &info, NULL, NULL, NULL, &size);
1119 ret = CryptSignAndEncodeCertificate(0, 0, X509_ASN_ENCODING,
1120 X509_CERT_TO_BE_SIGNED, &info, &algID, NULL, NULL, &size);
1121 ok(!ret && GetLastError() == NTE_BAD_ALGID,
1122 "Expected NTE_BAD_ALGID, got %08x\n", GetLastError());
1123 algID.pszObjId = oid_rsa_md5rsa;
1124 ret = CryptSignAndEncodeCertificate(0, 0, X509_ASN_ENCODING,
1125 X509_CERT_TO_BE_SIGNED, &info, &algID, NULL, NULL, &size);
1126 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1127 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
1128 algID.pszObjId = oid_rsa_md5;
1129 ret = CryptSignAndEncodeCertificate(0, 0, X509_ASN_ENCODING,
1130 X509_CERT_TO_BE_SIGNED, &info, &algID, NULL, NULL, &size);
1131 ok(ret, "CryptSignAndEncodeCertificate failed: %08x\n", GetLastError());
1134 LPBYTE buf = HeapAlloc(GetProcessHeap(), 0, size);
1138 ret = CryptSignAndEncodeCertificate(0, 0, X509_ASN_ENCODING,
1139 X509_CERT_TO_BE_SIGNED, &info, &algID, NULL, buf, &size);
1140 ok(ret, "CryptSignAndEncodeCertificate failed: %08x\n",
1142 /* Tricky: because the NULL parameters may either be omitted or
1143 * included as an asn.1-encoded NULL (0x05,0x00), two different
1144 * values are allowed.
1146 ok(size == sizeof(md5SignedEmptyCert) ||
1147 size == sizeof(md5SignedEmptyCertNoNull), "Unexpected size %d\n",
1149 if (size == sizeof(md5SignedEmptyCert))
1150 ok(!memcmp(buf, md5SignedEmptyCert, size),
1151 "Unexpected value\n");
1152 else if (size == sizeof(md5SignedEmptyCertNoNull))
1153 ok(!memcmp(buf, md5SignedEmptyCertNoNull, size),
1154 "Unexpected value\n");
1155 HeapFree(GetProcessHeap(), 0, buf);
1160 static void testCreateSelfSignCert(void)
1162 PCCERT_CONTEXT context;
1163 CERT_NAME_BLOB name = { sizeof(subjectName), subjectName };
1167 CRYPT_KEY_PROV_INFO info;
1170 context = CertCreateSelfSignCertificate(0, NULL, 0, NULL, NULL, NULL, NULL,
1172 * Calling this with no first parameter creates a new key container, which
1173 * lasts beyond the test, so I don't test that. Nb: the generated key
1175 context = CertCreateSelfSignCertificate(0, &name, 0, NULL, NULL, NULL, NULL,
1180 CryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
1181 CRYPT_DELETEKEYSET);
1182 ret = CryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
1184 ok(ret, "CryptAcquireContext failed: %08x\n", GetLastError());
1186 context = CertCreateSelfSignCertificate(csp, &name, 0, NULL, NULL, NULL,
1188 ok(!context && GetLastError() == NTE_NO_KEY,
1189 "Expected NTE_NO_KEY, got %08x\n", GetLastError());
1190 ret = CryptGenKey(csp, AT_SIGNATURE, 0, &key);
1191 ok(ret, "CryptGenKey failed: %08x\n", GetLastError());
1194 context = CertCreateSelfSignCertificate(csp, &name, 0, NULL, NULL, NULL,
1196 ok(context != NULL, "CertCreateSelfSignCertificate failed: %08x\n",
1201 PCRYPT_KEY_PROV_INFO info;
1203 /* The context must have a key provider info property */
1204 ret = CertGetCertificateContextProperty(context,
1205 CERT_KEY_PROV_INFO_PROP_ID, NULL, &size);
1206 ok(ret && size, "Expected non-zero key provider info\n");
1209 info = HeapAlloc(GetProcessHeap(), 0, size);
1212 ret = CertGetCertificateContextProperty(context,
1213 CERT_KEY_PROV_INFO_PROP_ID, info, &size);
1214 ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
1218 /* Sanity-check the key provider */
1219 ok(!lstrcmpW(info->pwszContainerName, cspNameW),
1220 "Unexpected key container\n");
1221 ok(!lstrcmpW(info->pwszProvName, MS_DEF_PROV_W),
1222 "Unexpected provider\n");
1223 ok(info->dwKeySpec == AT_SIGNATURE,
1224 "Expected AT_SIGNATURE, got %d\n", info->dwKeySpec);
1226 HeapFree(GetProcessHeap(), 0, info);
1230 CertFreeCertificateContext(context);
1233 CryptDestroyKey(key);
1236 CryptReleaseContext(csp, 0);
1237 ret = CryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
1238 CRYPT_DELETEKEYSET);
1240 /* do the same test with AT_KEYEXCHANGE and key info*/
1241 memset(&info,0,sizeof(info));
1242 info.dwProvType = PROV_RSA_FULL;
1243 info.dwKeySpec = AT_KEYEXCHANGE;
1244 info.pwszProvName = (LPWSTR) MS_DEF_PROV_W;
1245 info.pwszContainerName = cspNameW;
1246 context = CertCreateSelfSignCertificate(0, &name, 0, &info, NULL, NULL,
1248 ok(context != NULL, "CertCreateSelfSignCertificate failed: %08x\n",
1253 PCRYPT_KEY_PROV_INFO info;
1255 /* The context must have a key provider info property */
1256 ret = CertGetCertificateContextProperty(context,
1257 CERT_KEY_PROV_INFO_PROP_ID, NULL, &size);
1258 ok(ret && size, "Expected non-zero key provider info\n");
1261 info = HeapAlloc(GetProcessHeap(), 0, size);
1264 ret = CertGetCertificateContextProperty(context,
1265 CERT_KEY_PROV_INFO_PROP_ID, info, &size);
1266 ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
1270 /* Sanity-check the key provider */
1271 ok(!lstrcmpW(info->pwszContainerName, cspNameW),
1272 "Unexpected key container\n");
1273 ok(!lstrcmpW(info->pwszProvName, MS_DEF_PROV_W),
1274 "Unexpected provider\n");
1275 ok(info->dwKeySpec == AT_KEYEXCHANGE,
1276 "Expected AT_KEYEXCHANGE, got %d\n", info->dwKeySpec);
1278 HeapFree(GetProcessHeap(), 0, info);
1282 CertFreeCertificateContext(context);
1285 CryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
1286 CRYPT_DELETEKEYSET);
1289 static const LPCSTR keyUsages[] = { szOID_PKIX_KP_CODE_SIGNING,
1290 szOID_PKIX_KP_CLIENT_AUTH, szOID_RSA_RSA };
1292 static void testKeyUsage(void)
1295 PCCERT_CONTEXT context;
1298 /* Test base cases */
1299 ret = CertGetEnhancedKeyUsage(NULL, 0, NULL, NULL);
1300 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1301 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
1303 ret = CertGetEnhancedKeyUsage(NULL, 0, NULL, &size);
1304 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1305 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
1307 ret = CertGetEnhancedKeyUsage(NULL, 0, NULL, &size);
1308 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1309 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
1311 ret = CertSetEnhancedKeyUsage(NULL, NULL);
1312 usage.cUsageIdentifier = 0;
1313 ret = CertSetEnhancedKeyUsage(NULL, &usage);
1315 /* Test with a cert with no enhanced key usage extension */
1316 context = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert,
1318 ok(context != NULL, "CertCreateCertificateContext failed: %08x\n",
1322 static const char oid[] = "1.2.3.4";
1323 BYTE buf[sizeof(CERT_ENHKEY_USAGE) + 2 * (sizeof(LPSTR) + sizeof(oid))];
1324 PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
1326 ret = CertGetEnhancedKeyUsage(context, 0, NULL, NULL);
1327 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1328 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
1330 ret = CertGetEnhancedKeyUsage(context, 0, NULL, &size);
1333 /* Windows 2000, ME, or later: even though it succeeded, we expect
1334 * CRYPT_E_NOT_FOUND, which indicates there is no enhanced key
1335 * usage set for this cert (which implies it's valid for all uses.)
1337 ok(GetLastError() == CRYPT_E_NOT_FOUND,
1338 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
1339 ok(size == sizeof(CERT_ENHKEY_USAGE), "Wrong size %d\n", size);
1340 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
1341 ok(ret, "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
1342 ok(pUsage->cUsageIdentifier == 0, "Expected 0 usages, got %d\n",
1343 pUsage->cUsageIdentifier);
1347 /* Windows NT, 95, or 98: it fails, and the last error is
1348 * CRYPT_E_NOT_FOUND.
1350 ok(GetLastError() == CRYPT_E_NOT_FOUND,
1351 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
1353 /* I can add a usage identifier when no key usage has been set */
1354 ret = CertAddEnhancedKeyUsageIdentifier(context, oid);
1355 ok(ret, "CertAddEnhancedKeyUsageIdentifier failed: %08x\n",
1358 ret = CertGetEnhancedKeyUsage(context,
1359 CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG, pUsage, &size);
1360 ok(ret && GetLastError() == 0,
1361 "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
1362 ok(pUsage->cUsageIdentifier == 1, "Expected 1 usage, got %d\n",
1363 pUsage->cUsageIdentifier);
1364 if (pUsage->cUsageIdentifier)
1365 ok(!strcmp(pUsage->rgpszUsageIdentifier[0], oid),
1366 "Expected %s, got %s\n", oid, pUsage->rgpszUsageIdentifier[0]);
1367 /* Now set an empty key usage */
1368 pUsage->cUsageIdentifier = 0;
1369 ret = CertSetEnhancedKeyUsage(context, pUsage);
1370 ok(ret, "CertSetEnhancedKeyUsage failed: %08x\n", GetLastError());
1371 /* Shouldn't find it in the cert */
1373 ret = CertGetEnhancedKeyUsage(context,
1374 CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, pUsage, &size);
1375 ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
1376 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
1377 /* Should find it as an extended property */
1378 ret = CertGetEnhancedKeyUsage(context,
1379 CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG, pUsage, &size);
1380 ok(ret && GetLastError() == 0,
1381 "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
1382 ok(pUsage->cUsageIdentifier == 0, "Expected 0 usages, got %d\n",
1383 pUsage->cUsageIdentifier);
1384 /* Should find it as either */
1385 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
1386 ok(ret && GetLastError() == 0,
1387 "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
1388 ok(pUsage->cUsageIdentifier == 0, "Expected 0 usages, got %d\n",
1389 pUsage->cUsageIdentifier);
1390 /* Add a usage identifier */
1391 ret = CertAddEnhancedKeyUsageIdentifier(context, oid);
1392 ok(ret, "CertAddEnhancedKeyUsageIdentifier failed: %08x\n",
1395 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
1396 ok(ret && GetLastError() == 0,
1397 "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
1398 ok(pUsage->cUsageIdentifier == 1, "Expected 1 identifier, got %d\n",
1399 pUsage->cUsageIdentifier);
1400 if (pUsage->cUsageIdentifier)
1401 ok(!strcmp(pUsage->rgpszUsageIdentifier[0], oid),
1402 "Expected %s, got %s\n", oid, pUsage->rgpszUsageIdentifier[0]);
1403 /* Yep, I can re-add the same usage identifier */
1404 ret = CertAddEnhancedKeyUsageIdentifier(context, oid);
1405 ok(ret, "CertAddEnhancedKeyUsageIdentifier failed: %08x\n",
1408 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
1409 ok(ret && GetLastError() == 0,
1410 "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
1411 ok(pUsage->cUsageIdentifier == 2, "Expected 2 identifiers, got %d\n",
1412 pUsage->cUsageIdentifier);
1413 if (pUsage->cUsageIdentifier)
1414 ok(!strcmp(pUsage->rgpszUsageIdentifier[0], oid),
1415 "Expected %s, got %s\n", oid, pUsage->rgpszUsageIdentifier[0]);
1416 if (pUsage->cUsageIdentifier >= 2)
1417 ok(!strcmp(pUsage->rgpszUsageIdentifier[1], oid),
1418 "Expected %s, got %s\n", oid, pUsage->rgpszUsageIdentifier[1]);
1419 /* Now set a NULL extended property--this deletes the property. */
1420 ret = CertSetEnhancedKeyUsage(context, NULL);
1421 ok(ret, "CertSetEnhancedKeyUsage failed: %08x\n", GetLastError());
1422 SetLastError(0xbaadcafe);
1424 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
1425 ok(GetLastError() == CRYPT_E_NOT_FOUND,
1426 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
1428 CertFreeCertificateContext(context);
1430 /* Now test with a cert with an enhanced key usage extension */
1431 context = CertCreateCertificateContext(X509_ASN_ENCODING, certWithUsage,
1432 sizeof(certWithUsage));
1433 ok(context != NULL, "CertCreateCertificateContext failed: %08x\n",
1438 DWORD bufSize = 0, i;
1440 /* The size may depend on what flags are used to query it, so I
1441 * realloc the buffer for each test.
1443 ret = CertGetEnhancedKeyUsage(context,
1444 CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, NULL, &bufSize);
1445 ok(ret, "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
1446 buf = HeapAlloc(GetProcessHeap(), 0, bufSize);
1449 PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
1451 /* Should find it in the cert */
1453 ret = CertGetEnhancedKeyUsage(context,
1454 CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, pUsage, &size);
1455 ok(ret && GetLastError() == 0,
1456 "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
1457 ok(pUsage->cUsageIdentifier == 3, "Expected 3 usages, got %d\n",
1458 pUsage->cUsageIdentifier);
1459 for (i = 0; i < pUsage->cUsageIdentifier; i++)
1460 ok(!strcmp(pUsage->rgpszUsageIdentifier[i], keyUsages[i]),
1461 "Expected %s, got %s\n", keyUsages[i],
1462 pUsage->rgpszUsageIdentifier[i]);
1463 HeapFree(GetProcessHeap(), 0, buf);
1465 ret = CertGetEnhancedKeyUsage(context, 0, NULL, &bufSize);
1466 ok(ret, "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
1467 buf = HeapAlloc(GetProcessHeap(), 0, bufSize);
1470 PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
1472 /* Should find it as either */
1474 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
1475 /* In Windows, GetLastError returns CRYPT_E_NOT_FOUND not found
1476 * here, even though the return is successful and the usage id
1477 * count is positive. I don't enforce that here.
1480 "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
1481 ok(pUsage->cUsageIdentifier == 3, "Expected 3 usages, got %d\n",
1482 pUsage->cUsageIdentifier);
1483 for (i = 0; i < pUsage->cUsageIdentifier; i++)
1484 ok(!strcmp(pUsage->rgpszUsageIdentifier[i], keyUsages[i]),
1485 "Expected %s, got %s\n", keyUsages[i],
1486 pUsage->rgpszUsageIdentifier[i]);
1487 HeapFree(GetProcessHeap(), 0, buf);
1489 /* Shouldn't find it as an extended property */
1490 ret = CertGetEnhancedKeyUsage(context,
1491 CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG, NULL, &size);
1492 ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
1493 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
1494 /* Adding a usage identifier overrides the cert's usage!? */
1495 ret = CertAddEnhancedKeyUsageIdentifier(context, szOID_RSA_RSA);
1496 ok(ret, "CertAddEnhancedKeyUsageIdentifier failed: %08x\n",
1498 ret = CertGetEnhancedKeyUsage(context, 0, NULL, &bufSize);
1499 ok(ret, "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
1500 buf = HeapAlloc(GetProcessHeap(), 0, bufSize);
1503 PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
1505 /* Should find it as either */
1507 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
1509 "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
1510 ok(pUsage->cUsageIdentifier == 1, "Expected 1 usage, got %d\n",
1511 pUsage->cUsageIdentifier);
1512 ok(!strcmp(pUsage->rgpszUsageIdentifier[0], szOID_RSA_RSA),
1513 "Expected %s, got %s\n", szOID_RSA_RSA,
1514 pUsage->rgpszUsageIdentifier[0]);
1515 HeapFree(GetProcessHeap(), 0, buf);
1517 /* But querying the cert directly returns its usage */
1518 ret = CertGetEnhancedKeyUsage(context,
1519 CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, NULL, &bufSize);
1520 ok(ret, "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
1521 buf = HeapAlloc(GetProcessHeap(), 0, bufSize);
1524 PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
1527 ret = CertGetEnhancedKeyUsage(context,
1528 CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, pUsage, &size);
1530 "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
1531 ok(pUsage->cUsageIdentifier == 3, "Expected 3 usages, got %d\n",
1532 pUsage->cUsageIdentifier);
1533 for (i = 0; i < pUsage->cUsageIdentifier; i++)
1534 ok(!strcmp(pUsage->rgpszUsageIdentifier[i], keyUsages[i]),
1535 "Expected %s, got %s\n", keyUsages[i],
1536 pUsage->rgpszUsageIdentifier[i]);
1537 HeapFree(GetProcessHeap(), 0, buf);
1539 /* And removing the only usage identifier in the extended property
1540 * results in the cert's key usage being found.
1542 ret = CertRemoveEnhancedKeyUsageIdentifier(context, szOID_RSA_RSA);
1543 ok(ret, "CertRemoveEnhancedKeyUsage failed: %08x\n", GetLastError());
1544 ret = CertGetEnhancedKeyUsage(context, 0, NULL, &bufSize);
1545 ok(ret, "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
1546 buf = HeapAlloc(GetProcessHeap(), 0, bufSize);
1549 PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
1551 /* Should find it as either */
1553 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
1555 "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
1556 ok(pUsage->cUsageIdentifier == 3, "Expected 3 usages, got %d\n",
1557 pUsage->cUsageIdentifier);
1558 for (i = 0; i < pUsage->cUsageIdentifier; i++)
1559 ok(!strcmp(pUsage->rgpszUsageIdentifier[i], keyUsages[i]),
1560 "Expected %s, got %s\n", keyUsages[i],
1561 pUsage->rgpszUsageIdentifier[i]);
1562 HeapFree(GetProcessHeap(), 0, buf);
1565 CertFreeCertificateContext(context);
1569 static void testCompareCertName(void)
1571 static BYTE bogus[] = { 1, 2, 3, 4 };
1572 static BYTE bogusPrime[] = { 0, 1, 2, 3, 4 };
1573 static BYTE emptyPrime[] = { 0x30, 0x00, 0x01 };
1575 CERT_NAME_BLOB blob1, blob2;
1578 ret = CertCompareCertificateName(0, NULL, NULL);
1580 /* An empty name checks against itself.. */
1581 blob1.pbData = emptyCert;
1582 blob1.cbData = sizeof(emptyCert);
1583 ret = CertCompareCertificateName(0, &blob1, &blob1);
1584 ok(ret, "CertCompareCertificateName failed: %08x\n", GetLastError());
1585 /* It doesn't have to be a valid encoded name.. */
1586 blob1.pbData = bogus;
1587 blob1.cbData = sizeof(bogus);
1588 ret = CertCompareCertificateName(0, &blob1, &blob1);
1589 ok(ret, "CertCompareCertificateName failed: %08x\n", GetLastError());
1590 /* Leading zeroes matter.. */
1591 blob2.pbData = bogusPrime;
1592 blob2.cbData = sizeof(bogusPrime);
1593 ret = CertCompareCertificateName(0, &blob1, &blob2);
1594 ok(!ret, "Expected failure\n");
1595 /* As do trailing extra bytes. */
1596 blob2.pbData = emptyPrime;
1597 blob2.cbData = sizeof(emptyPrime);
1598 ret = CertCompareCertificateName(0, &blob1, &blob2);
1599 ok(!ret, "Expected failure\n");
1602 static BYTE int1[] = { 0x88, 0xff, 0xff, 0xff };
1603 static BYTE int2[] = { 0x88, 0xff };
1604 static BYTE int3[] = { 0x23, 0xff };
1605 static BYTE int4[] = { 0x7f, 0x00 };
1606 static BYTE int5[] = { 0x7f };
1607 static BYTE int6[] = { 0x80, 0x00, 0x00, 0x00 };
1608 static BYTE int7[] = { 0x80, 0x00 };
1610 static struct IntBlobTest
1612 CRYPT_INTEGER_BLOB blob1;
1613 CRYPT_INTEGER_BLOB blob2;
1616 { { sizeof(int1), int1 }, { sizeof(int2), int2 }, TRUE },
1617 { { sizeof(int3), int3 }, { sizeof(int3), int3 }, TRUE },
1618 { { sizeof(int4), int4 }, { sizeof(int5), int5 }, TRUE },
1619 { { sizeof(int6), int6 }, { sizeof(int7), int7 }, TRUE },
1620 { { sizeof(int1), int1 }, { sizeof(int7), int7 }, FALSE },
1623 static void testCompareIntegerBlob(void)
1628 for (i = 0; i < sizeof(intBlobs) / sizeof(intBlobs[0]); i++)
1630 ret = CertCompareIntegerBlob(&intBlobs[i].blob1, &intBlobs[i].blob2);
1631 ok(ret == intBlobs[i].areEqual,
1632 "%d: expected blobs %s compare\n", i, intBlobs[i].areEqual ?
1637 static void testComparePublicKeyInfo(void)
1640 CERT_PUBLIC_KEY_INFO info1 = { { 0 } }, info2 = { { 0 } };
1641 static CHAR oid_rsa_rsa[] = szOID_RSA_RSA;
1642 static CHAR oid_rsa_sha1rsa[] = szOID_RSA_SHA1RSA;
1643 static CHAR oid_x957_dsa[] = szOID_X957_DSA;
1644 static BYTE bits1[] = { 1, 0 };
1645 static BYTE bits2[] = { 0 };
1646 static BYTE bits3[] = { 1 };
1649 ret = CertComparePublicKeyInfo(0, NULL, NULL);
1651 /* Empty public keys compare */
1652 ret = CertComparePublicKeyInfo(0, &info1, &info2);
1653 ok(ret, "CertComparePublicKeyInfo failed: %08x\n", GetLastError());
1654 /* Different OIDs appear to compare */
1655 info1.Algorithm.pszObjId = oid_rsa_rsa;
1656 info2.Algorithm.pszObjId = oid_rsa_sha1rsa;
1657 ret = CertComparePublicKeyInfo(0, &info1, &info2);
1658 ok(ret, "CertComparePublicKeyInfo failed: %08x\n", GetLastError());
1659 info2.Algorithm.pszObjId = oid_x957_dsa;
1660 ret = CertComparePublicKeyInfo(0, &info1, &info2);
1661 ok(ret, "CertComparePublicKeyInfo failed: %08x\n", GetLastError());
1662 info1.PublicKey.cbData = sizeof(bits1);
1663 info1.PublicKey.pbData = bits1;
1664 info1.PublicKey.cUnusedBits = 0;
1665 info2.PublicKey.cbData = sizeof(bits1);
1666 info2.PublicKey.pbData = bits1;
1667 info2.PublicKey.cUnusedBits = 0;
1668 ret = CertComparePublicKeyInfo(0, &info1, &info2);
1669 ok(ret, "CertComparePublicKeyInfo failed: %08x\n", GetLastError());
1670 /* Even though they compare in their used bits, these do not compare */
1671 info1.PublicKey.cbData = sizeof(bits2);
1672 info1.PublicKey.pbData = bits2;
1673 info1.PublicKey.cUnusedBits = 0;
1674 info2.PublicKey.cbData = sizeof(bits3);
1675 info2.PublicKey.pbData = bits3;
1676 info2.PublicKey.cUnusedBits = 1;
1677 ret = CertComparePublicKeyInfo(0, &info1, &info2);
1678 /* Simple (non-comparing) case */
1679 ok(!ret, "Expected keys not to compare\n");
1680 info2.PublicKey.cbData = sizeof(bits1);
1681 info2.PublicKey.pbData = bits1;
1682 info2.PublicKey.cUnusedBits = 0;
1683 ret = CertComparePublicKeyInfo(0, &info1, &info2);
1684 ok(!ret, "Expected keys not to compare\n");
1687 static void testHashPublicKeyInfo(void)
1690 CERT_PUBLIC_KEY_INFO info = { { 0 } };
1694 ret = CryptHashPublicKeyInfo(0, 0, 0, 0, NULL, NULL, NULL);
1695 ret = CryptHashPublicKeyInfo(0, 0, 0, 0, &info, NULL, NULL);
1697 ret = CryptHashPublicKeyInfo(0, 0, 0, 0, NULL, NULL, &len);
1698 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
1699 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
1700 ret = CryptHashPublicKeyInfo(0, 0, 0, X509_ASN_ENCODING, NULL, NULL, &len);
1701 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
1702 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
1703 ret = CryptHashPublicKeyInfo(0, 0, 0, X509_ASN_ENCODING, &info, NULL, &len);
1704 ok(ret, "CryptHashPublicKeyInfo failed: %08x\n", GetLastError());
1705 ok(len == 16, "Expected hash size 16, got %d\n", len);
1708 static const BYTE emptyHash[] = { 0xb8,0x51,0x3a,0x31,0x0e,0x9f,0x40,
1709 0x36,0x9c,0x92,0x45,0x1b,0x9d,0xc8,0xf9,0xf6 };
1712 ret = CryptHashPublicKeyInfo(0, 0, 0, X509_ASN_ENCODING, &info, buf,
1714 ok(ret, "CryptHashPublicKeyInfo failed: %08x\n", GetLastError());
1715 ok(!memcmp(buf, emptyHash, len), "Unexpected hash\n");
1719 static void testCompareCert(void)
1721 CERT_INFO info1 = { 0 }, info2 = { 0 };
1725 ret = CertCompareCertificate(X509_ASN_ENCODING, NULL, NULL);
1728 /* Certs with the same issuer and serial number are equal, even if they
1729 * differ in other respects (like subject).
1731 info1.SerialNumber.pbData = serialNum;
1732 info1.SerialNumber.cbData = sizeof(serialNum);
1733 info1.Issuer.pbData = subjectName;
1734 info1.Issuer.cbData = sizeof(subjectName);
1735 info1.Subject.pbData = subjectName2;
1736 info1.Subject.cbData = sizeof(subjectName2);
1737 info2.SerialNumber.pbData = serialNum;
1738 info2.SerialNumber.cbData = sizeof(serialNum);
1739 info2.Issuer.pbData = subjectName;
1740 info2.Issuer.cbData = sizeof(subjectName);
1741 info2.Subject.pbData = subjectName;
1742 info2.Subject.cbData = sizeof(subjectName);
1743 ret = CertCompareCertificate(X509_ASN_ENCODING, &info1, &info2);
1744 ok(ret, "Expected certs to be equal\n");
1746 info2.Issuer.pbData = subjectName2;
1747 info2.Issuer.cbData = sizeof(subjectName2);
1748 ret = CertCompareCertificate(X509_ASN_ENCODING, &info1, &info2);
1749 ok(!ret, "Expected certs not to be equal\n");
1752 static void testVerifySubjectCert(void)
1756 PCCERT_CONTEXT context1, context2;
1759 ret = CertVerifySubjectCertificateContext(NULL, NULL, NULL);
1762 ret = CertVerifySubjectCertificateContext(NULL, NULL, &flags);
1763 ok(ret, "CertVerifySubjectCertificateContext failed; %08x\n",
1765 flags = CERT_STORE_NO_CRL_FLAG;
1766 ret = CertVerifySubjectCertificateContext(NULL, NULL, &flags);
1767 ok(!ret && GetLastError() == E_INVALIDARG,
1768 "Expected E_INVALIDARG, got %08x\n", GetLastError());
1771 context1 = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert,
1773 ret = CertVerifySubjectCertificateContext(NULL, context1, &flags);
1774 ok(ret, "CertVerifySubjectCertificateContext failed; %08x\n",
1776 ret = CertVerifySubjectCertificateContext(context1, NULL, &flags);
1777 ok(ret, "CertVerifySubjectCertificateContext failed; %08x\n",
1779 ret = CertVerifySubjectCertificateContext(context1, context1, &flags);
1780 ok(ret, "CertVerifySubjectCertificateContext failed; %08x\n",
1783 context2 = CertCreateCertificateContext(X509_ASN_ENCODING,
1784 bigCertWithDifferentSubject, sizeof(bigCertWithDifferentSubject));
1785 SetLastError(0xdeadbeef);
1786 ret = CertVerifySubjectCertificateContext(context1, context2, &flags);
1787 ok(ret, "CertVerifySubjectCertificateContext failed; %08x\n",
1789 flags = CERT_STORE_REVOCATION_FLAG;
1790 ret = CertVerifySubjectCertificateContext(context1, context2, &flags);
1791 ok(ret, "CertVerifySubjectCertificateContext failed; %08x\n",
1793 ok(flags == (CERT_STORE_REVOCATION_FLAG | CERT_STORE_NO_CRL_FLAG),
1794 "Expected CERT_STORE_REVOCATION_FLAG | CERT_STORE_NO_CRL_FLAG, got %08x\n",
1796 flags = CERT_STORE_SIGNATURE_FLAG;
1797 ret = CertVerifySubjectCertificateContext(context1, context2, &flags);
1798 ok(ret, "CertVerifySubjectCertificateContext failed; %08x\n",
1800 ok(flags == CERT_STORE_SIGNATURE_FLAG,
1801 "Expected CERT_STORE_SIGNATURE_FLAG, got %08x\n", flags);
1802 CertFreeCertificateContext(context2);
1804 CertFreeCertificateContext(context1);
1807 static BYTE privKey[] = {
1808 0x07, 0x02, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x52, 0x53, 0x41, 0x32, 0x00,
1809 0x02, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x79, 0x10, 0x1c, 0xd0, 0x6b, 0x10,
1810 0x18, 0x30, 0x94, 0x61, 0xdc, 0x0e, 0xcb, 0x96, 0x4e, 0x21, 0x3f, 0x79, 0xcd,
1811 0xa9, 0x17, 0x62, 0xbc, 0xbb, 0x61, 0x4c, 0xe0, 0x75, 0x38, 0x6c, 0xf3, 0xde,
1812 0x60, 0x86, 0x03, 0x97, 0x65, 0xeb, 0x1e, 0x6b, 0xdb, 0x53, 0x85, 0xad, 0x68,
1813 0x21, 0xf1, 0x5d, 0xe7, 0x1f, 0xe6, 0x53, 0xb4, 0xbb, 0x59, 0x3e, 0x14, 0x27,
1814 0xb1, 0x83, 0xa7, 0x3a, 0x54, 0xe2, 0x8f, 0x65, 0x8e, 0x6a, 0x4a, 0xcf, 0x3b,
1815 0x1f, 0x65, 0xff, 0xfe, 0xf1, 0x31, 0x3a, 0x37, 0x7a, 0x8b, 0xcb, 0xc6, 0xd4,
1816 0x98, 0x50, 0x36, 0x67, 0xe4, 0xa1, 0xe8, 0x7e, 0x8a, 0xc5, 0x23, 0xf2, 0x77,
1817 0xf5, 0x37, 0x61, 0x49, 0x72, 0x59, 0xe8, 0x3d, 0xf7, 0x60, 0xb2, 0x77, 0xca,
1818 0x78, 0x54, 0x6d, 0x65, 0x9e, 0x03, 0x97, 0x1b, 0x61, 0xbd, 0x0c, 0xd8, 0x06,
1819 0x63, 0xe2, 0xc5, 0x48, 0xef, 0xb3, 0xe2, 0x6e, 0x98, 0x7d, 0xbd, 0x4e, 0x72,
1820 0x91, 0xdb, 0x31, 0x57, 0xe3, 0x65, 0x3a, 0x49, 0xca, 0xec, 0xd2, 0x02, 0x4e,
1821 0x22, 0x7e, 0x72, 0x8e, 0xf9, 0x79, 0x84, 0x82, 0xdf, 0x7b, 0x92, 0x2d, 0xaf,
1822 0xc9, 0xe4, 0x33, 0xef, 0x89, 0x5c, 0x66, 0x99, 0xd8, 0x80, 0x81, 0x47, 0x2b,
1823 0xb1, 0x66, 0x02, 0x84, 0x59, 0x7b, 0xc3, 0xbe, 0x98, 0x45, 0x4a, 0x3d, 0xdd,
1824 0xea, 0x2b, 0xdf, 0x4e, 0xb4, 0x24, 0x6b, 0xec, 0xe7, 0xd9, 0x0c, 0x45, 0xb8,
1825 0xbe, 0xca, 0x69, 0x37, 0x92, 0x4c, 0x38, 0x6b, 0x96, 0x6d, 0xcd, 0x86, 0x67,
1826 0x5c, 0xea, 0x54, 0x94, 0xa4, 0xca, 0xa4, 0x02, 0xa5, 0x21, 0x4d, 0xae, 0x40,
1827 0x8f, 0x9d, 0x51, 0x83, 0xf2, 0x3f, 0x33, 0xc1, 0x72, 0xb4, 0x1d, 0x94, 0x6e,
1828 0x7d, 0xe4, 0x27, 0x3f, 0xea, 0xff, 0xe5, 0x9b, 0xa7, 0x5e, 0x55, 0x8e, 0x0d,
1829 0x69, 0x1c, 0x7a, 0xff, 0x81, 0x9d, 0x53, 0x52, 0x97, 0x9a, 0x76, 0x79, 0xda,
1830 0x93, 0x32, 0x16, 0xec, 0x69, 0x51, 0x1a, 0x4e, 0xc3, 0xf1, 0x72, 0x80, 0x78,
1831 0x5e, 0x66, 0x4a, 0x8d, 0x85, 0x2f, 0x3f, 0xb2, 0xa7 };
1833 static const BYTE selfSignedCert[] = {
1834 0x30, 0x82, 0x01, 0x1f, 0x30, 0x81, 0xce, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02,
1835 0x10, 0xeb, 0x0d, 0x57, 0x2a, 0x9c, 0x09, 0xba, 0xa4, 0x4a, 0xb7, 0x25, 0x49,
1836 0xd9, 0x3e, 0xb5, 0x73, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1d,
1837 0x05, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03,
1838 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30,
1839 0x1e, 0x17, 0x0d, 0x30, 0x36, 0x30, 0x36, 0x32, 0x39, 0x30, 0x35, 0x30, 0x30,
1840 0x34, 0x36, 0x5a, 0x17, 0x0d, 0x30, 0x37, 0x30, 0x36, 0x32, 0x39, 0x31, 0x31,
1841 0x30, 0x30, 0x34, 0x36, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03,
1842 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e,
1843 0x67, 0x00, 0x30, 0x5c, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
1844 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x4b, 0x00, 0x30, 0x48, 0x02, 0x41,
1845 0x00, 0xe2, 0x54, 0x3a, 0xa7, 0x83, 0xb1, 0x27, 0x14, 0x3e, 0x59, 0xbb, 0xb4,
1846 0x53, 0xe6, 0x1f, 0xe7, 0x5d, 0xf1, 0x21, 0x68, 0xad, 0x85, 0x53, 0xdb, 0x6b,
1847 0x1e, 0xeb, 0x65, 0x97, 0x03, 0x86, 0x60, 0xde, 0xf3, 0x6c, 0x38, 0x75, 0xe0,
1848 0x4c, 0x61, 0xbb, 0xbc, 0x62, 0x17, 0xa9, 0xcd, 0x79, 0x3f, 0x21, 0x4e, 0x96,
1849 0xcb, 0x0e, 0xdc, 0x61, 0x94, 0x30, 0x18, 0x10, 0x6b, 0xd0, 0x1c, 0x10, 0x79,
1850 0x02, 0x03, 0x01, 0x00, 0x01, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02,
1851 0x1d, 0x05, 0x00, 0x03, 0x41, 0x00, 0x25, 0x90, 0x53, 0x34, 0xd9, 0x56, 0x41,
1852 0x5e, 0xdb, 0x7e, 0x01, 0x36, 0xec, 0x27, 0x61, 0x5e, 0xb7, 0x4d, 0x90, 0x66,
1853 0xa2, 0xe1, 0x9d, 0x58, 0x76, 0xd4, 0x9c, 0xba, 0x2c, 0x84, 0xc6, 0x83, 0x7a,
1854 0x22, 0x0d, 0x03, 0x69, 0x32, 0x1a, 0x6d, 0xcb, 0x0c, 0x15, 0xb3, 0x6b, 0xc7,
1855 0x0a, 0x8c, 0xb4, 0x5c, 0x34, 0x78, 0xe0, 0x3c, 0x9c, 0xe9, 0xf3, 0x30, 0x9f,
1856 0xa8, 0x76, 0x57, 0x92, 0x36 };
1858 static const BYTE exportedPublicKeyBlob[] = {
1859 0x06,0x02,0x00,0x00,0x00,0xa4,0x00,0x00,0x52,0x53,0x41,0x31,0x00,0x02,0x00,0x00,
1860 0x01,0x00,0x01,0x00,0x79,0x10,0x1c,0xd0,0x6b,0x10,0x18,0x30,0x94,0x61,0xdc,0x0e,
1861 0xcb,0x96,0x4e,0x21,0x3f,0x79,0xcd,0xa9,0x17,0x62,0xbc,0xbb,0x61,0x4c,0xe0,0x75,
1862 0x38,0x6c,0xf3,0xde,0x60,0x86,0x03,0x97,0x65,0xeb,0x1e,0x6b,0xdb,0x53,0x85,0xad,
1863 0x68,0x21,0xf1,0x5d,0xe7,0x1f,0xe6,0x53,0xb4,0xbb,0x59,0x3e,0x14,0x27,0xb1,0x83,
1864 0xa7,0x3a,0x54,0xe2 };
1866 static const BYTE asnEncodedPublicKey[] = {
1867 0x30,0x48,0x02,0x41,0x00,0xe2,0x54,0x3a,0xa7,0x83,0xb1,0x27,0x14,0x3e,0x59,0xbb,
1868 0xb4,0x53,0xe6,0x1f,0xe7,0x5d,0xf1,0x21,0x68,0xad,0x85,0x53,0xdb,0x6b,0x1e,0xeb,
1869 0x65,0x97,0x03,0x86,0x60,0xde,0xf3,0x6c,0x38,0x75,0xe0,0x4c,0x61,0xbb,0xbc,0x62,
1870 0x17,0xa9,0xcd,0x79,0x3f,0x21,0x4e,0x96,0xcb,0x0e,0xdc,0x61,0x94,0x30,0x18,0x10,
1871 0x6b,0xd0,0x1c,0x10,0x79,0x02,0x03,0x01,0x00,0x01 };
1873 static void testAcquireCertPrivateKey(void)
1876 PCCERT_CONTEXT cert;
1878 DWORD size, keySpec;
1880 CRYPT_KEY_PROV_INFO keyProvInfo;
1882 WCHAR ms_def_prov_w[MAX_PATH];
1884 lstrcpyW(ms_def_prov_w, MS_DEF_PROV_W);
1886 keyProvInfo.pwszContainerName = cspNameW;
1887 keyProvInfo.pwszProvName = ms_def_prov_w;
1888 keyProvInfo.dwProvType = PROV_RSA_FULL;
1889 keyProvInfo.dwFlags = 0;
1890 keyProvInfo.cProvParam = 0;
1891 keyProvInfo.rgProvParam = NULL;
1892 keyProvInfo.dwKeySpec = AT_SIGNATURE;
1894 CryptAcquireContextW(NULL, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
1895 CRYPT_DELETEKEYSET);
1897 cert = CertCreateCertificateContext(X509_ASN_ENCODING, selfSignedCert,
1898 sizeof(selfSignedCert));
1901 ret = CryptAcquireCertificatePrivateKey(NULL, 0, NULL, NULL, NULL, NULL);
1902 ret = CryptAcquireCertificatePrivateKey(NULL, 0, NULL, NULL, NULL,
1904 ret = CryptAcquireCertificatePrivateKey(NULL, 0, NULL, NULL, &keySpec,
1906 ret = CryptAcquireCertificatePrivateKey(NULL, 0, NULL, &csp, NULL, NULL);
1907 ret = CryptAcquireCertificatePrivateKey(NULL, 0, NULL, &csp, &keySpec,
1909 ret = CryptAcquireCertificatePrivateKey(cert, 0, NULL, NULL, NULL, NULL);
1912 /* Missing private key */
1913 ret = CryptAcquireCertificatePrivateKey(cert, 0, NULL, &csp, NULL, NULL);
1914 ok(!ret && GetLastError() == CRYPT_E_NO_KEY_PROPERTY,
1915 "Expected CRYPT_E_NO_KEY_PROPERTY, got %08x\n", GetLastError());
1916 ret = CryptAcquireCertificatePrivateKey(cert, 0, NULL, &csp, &keySpec,
1918 ok(!ret && GetLastError() == CRYPT_E_NO_KEY_PROPERTY,
1919 "Expected CRYPT_E_NO_KEY_PROPERTY, got %08x\n", GetLastError());
1920 CertSetCertificateContextProperty(cert, CERT_KEY_PROV_INFO_PROP_ID, 0,
1922 ret = CryptAcquireCertificatePrivateKey(cert, 0, NULL, &csp, &keySpec,
1924 ok(!ret && GetLastError() == CRYPT_E_NO_KEY_PROPERTY,
1925 "Expected CRYPT_E_NO_KEY_PROPERTY, got %08x\n", GetLastError());
1927 CryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
1929 ret = CryptImportKey(csp, privKey, sizeof(privKey), 0, 0, &key);
1930 ok(ret, "CryptImportKey failed: %08x\n", GetLastError());
1935 CERT_KEY_CONTEXT keyContext;
1937 /* Don't cache provider */
1938 ret = CryptAcquireCertificatePrivateKey(cert, 0, NULL, &certCSP,
1939 &keySpec, &callerFree);
1940 ok(ret, "CryptAcquireCertificatePrivateKey failed: %08x\n",
1942 ok(callerFree, "Expected callerFree to be TRUE\n");
1943 CryptReleaseContext(certCSP, 0);
1944 ret = CryptAcquireCertificatePrivateKey(cert, 0, NULL, &certCSP,
1946 ok(ret, "CryptAcquireCertificatePrivateKey failed: %08x\n",
1948 CryptReleaseContext(certCSP, 0);
1950 /* Use the key prov info's caching (there shouldn't be any) */
1951 ret = CryptAcquireCertificatePrivateKey(cert,
1952 CRYPT_ACQUIRE_USE_PROV_INFO_FLAG, NULL, &certCSP, &keySpec,
1954 ok(ret, "CryptAcquireCertificatePrivateKey failed: %08x\n",
1956 ok(callerFree, "Expected callerFree to be TRUE\n");
1957 CryptReleaseContext(certCSP, 0);
1959 /* Cache it (and check that it's cached) */
1960 ret = CryptAcquireCertificatePrivateKey(cert,
1961 CRYPT_ACQUIRE_CACHE_FLAG, NULL, &certCSP, &keySpec, &callerFree);
1962 ok(ret, "CryptAcquireCertificatePrivateKey failed: %08x\n",
1964 ok(!callerFree, "Expected callerFree to be FALSE\n");
1965 size = sizeof(keyContext);
1966 ret = CertGetCertificateContextProperty(cert, CERT_KEY_CONTEXT_PROP_ID,
1967 &keyContext, &size);
1968 ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
1971 /* Remove the cached provider */
1972 CryptReleaseContext(keyContext.hCryptProv, 0);
1973 CertSetCertificateContextProperty(cert, CERT_KEY_CONTEXT_PROP_ID, 0,
1975 /* Allow caching via the key prov info */
1976 keyProvInfo.dwFlags = CERT_SET_KEY_CONTEXT_PROP_ID;
1977 CertSetCertificateContextProperty(cert, CERT_KEY_PROV_INFO_PROP_ID, 0,
1979 /* Now use the key prov info's caching */
1980 ret = CryptAcquireCertificatePrivateKey(cert,
1981 CRYPT_ACQUIRE_USE_PROV_INFO_FLAG, NULL, &certCSP, &keySpec,
1983 ok(ret, "CryptAcquireCertificatePrivateKey failed: %08x\n",
1985 ok(!callerFree, "Expected callerFree to be FALSE\n");
1986 size = sizeof(keyContext);
1987 ret = CertGetCertificateContextProperty(cert, CERT_KEY_CONTEXT_PROP_ID,
1988 &keyContext, &size);
1989 ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
1992 CryptDestroyKey(key);
1995 /* Some sanity-checking on public key exporting */
1996 ret = CryptImportPublicKeyInfo(csp, X509_ASN_ENCODING,
1997 &cert->pCertInfo->SubjectPublicKeyInfo, &key);
1998 ok(ret, "CryptImportPublicKeyInfo failed: %08x\n", GetLastError());
2001 ret = CryptExportKey(key, 0, PUBLICKEYBLOB, 0, NULL, &size);
2002 ok(ret, "CryptExportKey failed: %08x\n", GetLastError());
2005 LPBYTE buf = HeapAlloc(GetProcessHeap(), 0, size), encodedKey;
2007 ret = CryptExportKey(key, 0, PUBLICKEYBLOB, 0, buf, &size);
2008 ok(ret, "CryptExportKey failed: %08x\n", GetLastError());
2009 ok(size == sizeof(exportedPublicKeyBlob), "Unexpected size %d\n",
2011 ok(!memcmp(buf, exportedPublicKeyBlob, size), "Unexpected value\n");
2012 ret = CryptEncodeObjectEx(X509_ASN_ENCODING, RSA_CSP_PUBLICKEYBLOB,
2013 buf, CRYPT_ENCODE_ALLOC_FLAG, NULL, &encodedKey, &size);
2014 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2017 ok(size == sizeof(asnEncodedPublicKey), "Unexpected size %d\n",
2019 ok(!memcmp(encodedKey, asnEncodedPublicKey, size),
2020 "Unexpected value\n");
2021 LocalFree(encodedKey);
2023 HeapFree(GetProcessHeap(), 0, buf);
2025 CryptDestroyKey(key);
2027 ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING,
2028 NULL, 0, NULL, NULL, &size);
2029 ok(ret, "CryptExportPublicKeyInfoEx failed: %08x\n", GetLastError());
2032 PCERT_PUBLIC_KEY_INFO info = HeapAlloc(GetProcessHeap(), 0, size);
2034 ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING,
2035 NULL, 0, NULL, info, &size);
2036 ok(ret, "CryptExportPublicKeyInfoEx failed: %08x\n", GetLastError());
2039 ok(info->PublicKey.cbData == sizeof(asnEncodedPublicKey),
2040 "Unexpected size %d\n", info->PublicKey.cbData);
2041 ok(!memcmp(info->PublicKey.pbData, asnEncodedPublicKey,
2042 info->PublicKey.cbData), "Unexpected value\n");
2044 HeapFree(GetProcessHeap(), 0, info);
2047 CryptReleaseContext(csp, 0);
2048 CryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
2049 CRYPT_DELETEKEYSET);
2051 CertFreeCertificateContext(cert);
2054 static void testGetPublicKeyLength(void)
2056 static char oid_rsa_rsa[] = szOID_RSA_RSA;
2057 static char oid_rsa_dh[] = szOID_RSA_DH;
2058 static char bogusOID[] = "1.2.3";
2060 CERT_PUBLIC_KEY_INFO info = { { 0 } };
2061 BYTE bogusKey[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
2062 BYTE key[] = { 0x30,0x0f,0x02,0x08,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
2063 0x02,0x03,0x01,0x00,0x01 };
2066 ret = CertGetPublicKeyLength(0, NULL);
2068 /* With an empty public key info */
2069 SetLastError(0xdeadbeef);
2070 ret = CertGetPublicKeyLength(0, &info);
2071 ok(ret == 0 && GetLastError() == ERROR_FILE_NOT_FOUND,
2072 "Expected length 0 and ERROR_FILE_NOT_FOUND, got length %d, %08x\n",
2073 ret, GetLastError());
2074 SetLastError(0xdeadbeef);
2075 ret = CertGetPublicKeyLength(X509_ASN_ENCODING, &info);
2076 ok(ret == 0 && GetLastError() == CRYPT_E_ASN1_EOD,
2077 "Expected length 0 and CRYPT_E_ASN1_EOD, got length %d, %08x\n",
2078 ret, GetLastError());
2079 /* With a nearly-empty public key info */
2080 info.Algorithm.pszObjId = oid_rsa_rsa;
2081 SetLastError(0xdeadbeef);
2082 ret = CertGetPublicKeyLength(0, &info);
2083 ok(ret == 0 && GetLastError() == ERROR_FILE_NOT_FOUND,
2084 "Expected length 0 and ERROR_FILE_NOT_FOUND, got length %d, %08x\n",
2085 ret, GetLastError());
2086 SetLastError(0xdeadbeef);
2087 ret = CertGetPublicKeyLength(X509_ASN_ENCODING, &info);
2088 ok(ret == 0 && GetLastError() == CRYPT_E_ASN1_EOD,
2089 "Expected length 0 and CRYPT_E_ASN1_EOD, got length %d, %08x\n",
2090 ret, GetLastError());
2091 /* With a bogus key */
2092 info.PublicKey.cbData = sizeof(bogusKey);
2093 info.PublicKey.pbData = bogusKey;
2094 SetLastError(0xdeadbeef);
2095 ret = CertGetPublicKeyLength(0, &info);
2096 ok(ret == 0 && GetLastError() == ERROR_FILE_NOT_FOUND,
2097 "Expected length 0 and ERROR_FILE_NOT_FOUND, got length %d, %08x\n",
2098 ret, GetLastError());
2099 SetLastError(0xdeadbeef);
2100 ret = CertGetPublicKeyLength(X509_ASN_ENCODING, &info);
2101 ok(ret == 0 && GetLastError() == CRYPT_E_ASN1_BADTAG,
2102 "Expected length 0 and CRYPT_E_ASN1_BADTAGTAG, got length %d, %08x\n",
2103 ret, GetLastError());
2104 /* With a believable RSA key but a bogus OID */
2105 info.Algorithm.pszObjId = bogusOID;
2106 info.PublicKey.cbData = sizeof(key);
2107 info.PublicKey.pbData = key;
2108 SetLastError(0xdeadbeef);
2109 ret = CertGetPublicKeyLength(0, &info);
2110 ok(ret == 0 && GetLastError() == ERROR_FILE_NOT_FOUND,
2111 "Expected length 0 and ERROR_FILE_NOT_FOUND, got length %d, %08x\n",
2112 ret, GetLastError());
2113 SetLastError(0xdeadbeef);
2114 ret = CertGetPublicKeyLength(X509_ASN_ENCODING, &info);
2115 ok(ret == 56, "Expected length 56, got %d\n", ret);
2116 /* An RSA key with the DH OID */
2117 info.Algorithm.pszObjId = oid_rsa_dh;
2118 SetLastError(0xdeadbeef);
2119 ret = CertGetPublicKeyLength(X509_ASN_ENCODING, &info);
2120 ok(ret == 0 && GetLastError() == CRYPT_E_ASN1_BADTAG,
2121 "Expected length 0 and CRYPT_E_ASN1_BADTAG, got length %d, %08x\n",
2122 ret, GetLastError());
2123 /* With the RSA OID */
2124 info.Algorithm.pszObjId = oid_rsa_rsa;
2125 SetLastError(0xdeadbeef);
2126 ret = CertGetPublicKeyLength(X509_ASN_ENCODING, &info);
2127 ok(ret == 56, "Expected length 56, got %d\n", ret);
2132 init_function_pointers();
2135 testCertProperties();
2138 testGetSubjectCert();
2139 testGetIssuerCert();
2141 testCryptHashCert();
2143 testSignAndEncodeCert();
2144 testCreateSelfSignCert();
2146 testCompareCertName();
2147 testCompareIntegerBlob();
2148 testComparePublicKeyInfo();
2149 testHashPublicKeyInfo();
2151 testVerifySubjectCert();
2152 testAcquireCertPrivateKey();
2153 testGetPublicKeyLength();