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 static void init_function_pointers(void)
42 pCryptVerifyCertificateSignatureEx = NULL;
44 hCrypt32 = GetModuleHandleA("crypt32.dll");
47 CRYPT_GET_PROC(CryptVerifyCertificateSignatureEx);
50 static BYTE subjectName[] = { 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06,
51 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61,
53 static BYTE serialNum[] = { 1 };
54 static const BYTE bigCert[] = { 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
55 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
56 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22,
57 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30,
58 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30,
59 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30,
60 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20,
61 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01,
62 0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01,
63 0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
64 static BYTE bigCertHash[] = { 0x6e, 0x30, 0x90, 0x71, 0x5f, 0xd9, 0x23,
65 0x56, 0xeb, 0xae, 0x25, 0x40, 0xe6, 0x22, 0xda, 0x19, 0x26, 0x02, 0xa6, 0x08 };
67 static const BYTE bigCertWithDifferentSubject[] = { 0x30, 0x7a, 0x02, 0x01, 0x02,
68 0x30, 0x02, 0x06, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55,
69 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67,
70 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31,
71 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31,
72 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15,
73 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x41, 0x6c,
74 0x65, 0x78, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06,
75 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55,
76 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02,
78 static const BYTE bigCertWithDifferentIssuer[] = { 0x30, 0x7a, 0x02, 0x01,
79 0x01, 0x30, 0x02, 0x06, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03,
80 0x55, 0x04, 0x03, 0x13, 0x0a, 0x41, 0x6c, 0x65, 0x78, 0x20, 0x4c, 0x61, 0x6e,
81 0x67, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30,
82 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30,
83 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30,
84 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a,
85 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02,
86 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03,
87 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff,
90 static BYTE subjectName2[] = { 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06,
91 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x41, 0x6c, 0x65, 0x78, 0x20, 0x4c, 0x61,
93 static const BYTE bigCert2[] = { 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
94 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
95 0x0a, 0x41, 0x6c, 0x65, 0x78, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22,
96 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30,
97 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30,
98 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30,
99 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x41, 0x6c, 0x65, 0x78, 0x20,
100 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01,
101 0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01,
102 0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
103 static const BYTE bigCert2WithDifferentSerial[] = { 0x30, 0x7a, 0x02, 0x01,
104 0x02, 0x30, 0x02, 0x06, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03,
105 0x55, 0x04, 0x03, 0x13, 0x0a, 0x41, 0x6c, 0x65, 0x78, 0x20, 0x4c, 0x61, 0x6e,
106 0x67, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30,
107 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30,
108 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30,
109 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x41,
110 0x6c, 0x65, 0x78, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02,
111 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03,
112 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff,
114 static BYTE bigCert2Hash[] = { 0x4a, 0x7f, 0x32, 0x1f, 0xcf, 0x3b, 0xc0,
115 0x87, 0x48, 0x2b, 0xa1, 0x86, 0x54, 0x18, 0xe4, 0x3a, 0x0e, 0x53, 0x7e, 0x2b };
117 static const BYTE certWithUsage[] = { 0x30, 0x81, 0x93, 0x02, 0x01, 0x01, 0x30,
118 0x02, 0x06, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04,
119 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00,
120 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30,
121 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30,
122 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31,
123 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61,
124 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00,
125 0x03, 0x01, 0x00, 0xa3, 0x2f, 0x30, 0x2d, 0x30, 0x2b, 0x06, 0x03, 0x55, 0x1d,
126 0x25, 0x01, 0x01, 0xff, 0x04, 0x21, 0x30, 0x1f, 0x06, 0x08, 0x2b, 0x06, 0x01,
127 0x05, 0x05, 0x07, 0x03, 0x03, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07,
128 0x03, 0x02, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01 };
130 static void testAddCert(void)
133 HCERTSTORE collection;
134 PCCERT_CONTEXT context;
135 PCCERT_CONTEXT copyContext;
138 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
139 CERT_STORE_CREATE_NEW_FLAG, NULL);
140 ok(store != NULL, "CertOpenStore failed: %d\n", GetLastError());
144 /* Weird--bad add disposition leads to an access violation in Windows.
146 ret = CertAddEncodedCertificateToStore(0, X509_ASN_ENCODING, bigCert,
147 sizeof(bigCert), 0, NULL);
148 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
149 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
150 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
151 bigCert, sizeof(bigCert), 0, NULL);
152 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
153 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
155 /* Weird--can add a cert to the NULL store (does this have special
159 ret = CertAddEncodedCertificateToStore(0, X509_ASN_ENCODING, bigCert,
160 sizeof(bigCert), CERT_STORE_ADD_ALWAYS, &context);
161 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
164 CertFreeCertificateContext(context);
166 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
167 bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL);
168 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
170 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
171 bigCert2, sizeof(bigCert2), CERT_STORE_ADD_NEW, NULL);
172 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
174 /* This has the same name as bigCert, so finding isn't done by name */
175 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
176 certWithUsage, sizeof(certWithUsage), CERT_STORE_ADD_NEW, &context);
177 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
179 ok(context != NULL, "Expected a context\n");
182 CRYPT_DATA_BLOB hash = { sizeof(bigCert2Hash), bigCert2Hash };
184 /* Duplicate (AddRef) the context so we can still use it after
185 * deleting it from the store.
187 CertDuplicateCertificateContext(context);
188 CertDeleteCertificateFromStore(context);
189 /* Set the same hash as bigCert2, and try to readd it */
190 ret = CertSetCertificateContextProperty(context, CERT_HASH_PROP_ID,
192 ok(ret, "CertSetCertificateContextProperty failed: %08x\n",
194 ret = CertAddCertificateContextToStore(store, context,
195 CERT_STORE_ADD_NEW, NULL);
196 /* The failure is a bit odd (CRYPT_E_ASN1_BADTAG), so just check
199 ok(!ret, "Expected failure\n");
200 CertFreeCertificateContext(context);
202 context = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert2,
204 ok(context != NULL, "Expected a context\n");
207 /* Try to readd bigCert2 to the store */
208 ret = CertAddCertificateContextToStore(store, context,
209 CERT_STORE_ADD_NEW, NULL);
210 ok(!ret && GetLastError() == CRYPT_E_EXISTS,
211 "Expected CRYPT_E_EXISTS, got %08x\n", GetLastError());
212 CertFreeCertificateContext(context);
215 /* Adding a cert with the same issuer name and serial number (but
216 * different subject) as an existing cert succeeds.
219 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
220 bigCert2WithDifferentSerial, sizeof(bigCert2WithDifferentSerial),
221 CERT_STORE_ADD_NEW, &context);
222 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
225 CertDeleteCertificateFromStore(context);
227 /* Adding a cert with the same subject name and serial number (but
228 * different issuer) as an existing cert succeeds.
231 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
232 bigCertWithDifferentSubject, sizeof(bigCertWithDifferentSubject),
233 CERT_STORE_ADD_NEW, &context);
234 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
237 CertDeleteCertificateFromStore(context);
239 /* Adding a cert with the same issuer name and serial number (but
240 * different otherwise) as an existing cert succeeds.
243 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
244 bigCertWithDifferentIssuer, sizeof(bigCertWithDifferentIssuer),
245 CERT_STORE_ADD_NEW, &context);
246 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
249 CertDeleteCertificateFromStore(context);
251 collection = CertOpenStore(CERT_STORE_PROV_COLLECTION, 0, 0,
252 CERT_STORE_CREATE_NEW_FLAG, NULL);
253 ok(collection != NULL, "CertOpenStore failed: %08x\n", GetLastError());
256 /* Add store to the collection, but disable updates */
257 CertAddStoreToCollection(collection, store, 0, 0);
259 context = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert2,
261 ok(context != NULL, "Expected a context\n");
264 /* Try to readd bigCert2 to the collection */
265 ret = CertAddCertificateContextToStore(collection, context,
266 CERT_STORE_ADD_NEW, NULL);
267 ok(!ret && GetLastError() == CRYPT_E_EXISTS,
268 "Expected CRYPT_E_EXISTS, got %08x\n", GetLastError());
269 /* Replacing an existing certificate context is allowed, even
270 * though updates to the collection aren't..
272 ret = CertAddCertificateContextToStore(collection, context,
273 CERT_STORE_ADD_REPLACE_EXISTING, NULL);
274 ok(ret, "CertAddCertificateContextToStore failed: %08x\n",
276 /* use the existing certificate and ask for a copy of the context*/
278 ret = CertAddCertificateContextToStore(collection, context,
279 CERT_STORE_ADD_USE_EXISTING, ©Context);
280 ok(ret, "CertAddCertificateContextToStore failed: %08x\n",
282 ok(copyContext != NULL, "Expected on output a non NULL copyContext\n");
284 CertFreeCertificateContext(copyContext);
285 /* but adding a new certificate isn't allowed. */
286 ret = CertAddCertificateContextToStore(collection, context,
287 CERT_STORE_ADD_ALWAYS, NULL);
288 ok(!ret && GetLastError() == E_ACCESSDENIED,
289 "Expected E_ACCESSDENIED, got %08x\n", GetLastError());
290 CertFreeCertificateContext(context);
293 CertCloseStore(collection, 0);
296 CertCloseStore(store, 0);
299 static void checkHash(const BYTE *data, DWORD dataLen, ALG_ID algID,
300 PCCERT_CONTEXT context, DWORD propID)
302 BYTE hash[20] = { 0 }, hashProperty[20];
305 DWORD dwSizeWithNull;
307 memset(hash, 0, sizeof(hash));
308 memset(hashProperty, 0, sizeof(hashProperty));
310 ret = CryptHashCertificate(0, algID, 0, data, dataLen, hash, &size);
311 ok(ret, "CryptHashCertificate failed: %08x\n", GetLastError());
312 ret = CertGetCertificateContextProperty(context, propID, NULL,
314 ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
316 ret = CertGetCertificateContextProperty(context, propID, hashProperty,
318 ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
320 ok(!memcmp(hash, hashProperty, size), "Unexpected hash for property %d\n",
322 ok(size == dwSizeWithNull, "Unexpected length of hash for property: received %d instead of %d\n",
323 dwSizeWithNull,size);
326 static WCHAR cspNameW[] = { 'W','i','n','e','C','r','y','p','t','T','e','m','p',0 };
328 static void testCertProperties(void)
330 PCCERT_CONTEXT context = CertCreateCertificateContext(X509_ASN_ENCODING,
331 bigCert, sizeof(bigCert));
332 DWORD propID, numProps, access, size;
334 BYTE hash[20] = { 0 }, hashProperty[20];
335 CRYPT_DATA_BLOB blob;
336 CERT_KEY_CONTEXT keyContext;
339 ok(context != NULL, "CertCreateCertificateContext failed: %08x\n",
345 propID = CertEnumCertificateContextProperties(NULL, 0);
351 propID = CertEnumCertificateContextProperties(context, propID);
354 } while (propID != 0);
355 ok(numProps == 0, "Expected 0 properties, got %d\n", numProps);
357 /* Tests with a NULL cert context. Prop ID 0 fails.. */
358 ret = CertSetCertificateContextProperty(NULL, 0, 0, NULL);
359 ok(!ret && GetLastError() == E_INVALIDARG,
360 "Expected E_INVALIDARG, got %08x\n", GetLastError());
361 /* while this just crashes.
362 ret = CertSetCertificateContextProperty(NULL,
363 CERT_KEY_PROV_HANDLE_PROP_ID, 0, NULL);
366 ret = CertSetCertificateContextProperty(context, 0, 0, NULL);
367 ok(!ret && GetLastError() == E_INVALIDARG,
368 "Expected E_INVALIDARG, got %08x\n", GetLastError());
369 /* Can't set the cert property directly, this crashes.
370 ret = CertSetCertificateContextProperty(context,
371 CERT_CERT_PROP_ID, 0, bigCert2);
375 ret = CertGetCertificateContextProperty(context,
376 CERT_ACCESS_STATE_PROP_ID, 0, NULL);
377 ret = CertGetCertificateContextProperty(context, CERT_HASH_PROP_ID,
379 ret = CertGetCertificateContextProperty(context, CERT_HASH_PROP_ID,
384 ret = CertGetCertificateContextProperty(context,
385 CERT_KEY_PROV_INFO_PROP_ID, NULL, &size);
386 ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
387 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
388 /* And, an implicit property */
389 size = sizeof(access);
390 ret = CertGetCertificateContextProperty(context,
391 CERT_ACCESS_STATE_PROP_ID, &access, &size);
392 ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
394 ok(!(access & CERT_ACCESS_STATE_WRITE_PERSIST_FLAG),
395 "Didn't expect a persisted cert\n");
396 /* Trying to set this "read only" property crashes.
397 access |= CERT_ACCESS_STATE_WRITE_PERSIST_FLAG;
398 ret = CertSetCertificateContextProperty(context,
399 CERT_ACCESS_STATE_PROP_ID, 0, &access);
402 /* Can I set the hash to an invalid hash? */
404 blob.cbData = sizeof(hash);
405 ret = CertSetCertificateContextProperty(context, CERT_HASH_PROP_ID, 0,
407 ok(ret, "CertSetCertificateContextProperty failed: %08x\n",
409 size = sizeof(hashProperty);
410 ret = CertGetCertificateContextProperty(context, CERT_HASH_PROP_ID,
411 hashProperty, &size);
412 ok(!memcmp(hashProperty, hash, sizeof(hash)), "Unexpected hash\n");
413 /* Delete the (bogus) hash, and get the real one */
414 ret = CertSetCertificateContextProperty(context, CERT_HASH_PROP_ID, 0,
416 ok(ret, "CertSetCertificateContextProperty failed: %08x\n",
418 checkHash(bigCert, sizeof(bigCert), CALG_SHA1, context,
421 /* Now that the hash property is set, we should get one property when
427 propID = CertEnumCertificateContextProperties(context, propID);
430 } while (propID != 0);
431 ok(numProps == 1, "Expected 1 properties, got %d\n", numProps);
433 /* Check a few other implicit properties */
434 checkHash(bigCert, sizeof(bigCert), CALG_MD5, context,
435 CERT_MD5_HASH_PROP_ID);
437 context->pCertInfo->Subject.pbData,
438 context->pCertInfo->Subject.cbData,
439 CALG_MD5, context, CERT_SUBJECT_NAME_MD5_HASH_PROP_ID);
441 context->pCertInfo->SubjectPublicKeyInfo.PublicKey.pbData,
442 context->pCertInfo->SubjectPublicKeyInfo.PublicKey.cbData,
443 CALG_MD5, context, CERT_SUBJECT_PUBLIC_KEY_MD5_HASH_PROP_ID);
445 /* Test key identifiers and handles and such */
447 ret = CertGetCertificateContextProperty(context,
448 CERT_KEY_IDENTIFIER_PROP_ID, NULL, &size);
449 ok(!ret && GetLastError() == ERROR_INVALID_DATA,
450 "Expected ERROR_INVALID_DATA, got %08x\n", GetLastError());
451 size = sizeof(CERT_KEY_CONTEXT);
452 ret = CertGetCertificateContextProperty(context,
453 CERT_KEY_IDENTIFIER_PROP_ID, NULL, &size);
454 ok(!ret && GetLastError() == ERROR_INVALID_DATA,
455 "Expected ERROR_INVALID_DATA, got %08x\n", GetLastError());
456 ret = CertGetCertificateContextProperty(context,
457 CERT_KEY_IDENTIFIER_PROP_ID, &keyContext, &size);
458 ok(!ret && GetLastError() == ERROR_INVALID_DATA,
459 "Expected ERROR_INVALID_DATA, got %08x\n", GetLastError());
460 /* Key context with an invalid size */
461 keyContext.cbSize = 0;
462 ret = CertSetCertificateContextProperty(context,
463 CERT_KEY_IDENTIFIER_PROP_ID, 0, &keyContext);
464 ok(ret, "CertSetCertificateContextProperty failed: %08x\n",
466 size = sizeof(keyContext);
467 ret = CertGetCertificateContextProperty(context,
468 CERT_KEY_IDENTIFIER_PROP_ID, &keyContext, &size);
469 ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
471 keyContext.cbSize = sizeof(keyContext);
472 keyContext.hCryptProv = 0;
473 keyContext.dwKeySpec = AT_SIGNATURE;
475 ret = CertSetCertificateContextProperty(context,
476 CERT_KEY_IDENTIFIER_PROP_ID, 0, &keyContext);
477 ret = CertSetCertificateContextProperty(context,
478 CERT_KEY_IDENTIFIER_PROP_ID, CERT_STORE_NO_CRYPT_RELEASE_FLAG,
481 ret = CryptAcquireContextW(&csp, cspNameW,
482 MS_DEF_PROV_W, PROV_RSA_FULL, CRYPT_NEWKEYSET);
483 ok(ret, "CryptAcquireContextW failed: %08x\n", GetLastError());
484 keyContext.hCryptProv = csp;
485 ret = CertSetCertificateContextProperty(context,
486 CERT_KEY_CONTEXT_PROP_ID, 0, &keyContext);
487 ok(ret, "CertSetCertificateContextProperty failed: %08x\n",
489 /* Now that that's set, the key prov handle property is also gettable.
491 size = sizeof(DWORD);
492 ret = CertGetCertificateContextProperty(context,
493 CERT_KEY_PROV_HANDLE_PROP_ID, &keyContext.hCryptProv, &size);
494 ok(ret, "Expected to get the CERT_KEY_PROV_HANDLE_PROP_ID, got %08x\n",
496 /* Remove the key prov handle property.. */
497 ret = CertSetCertificateContextProperty(context,
498 CERT_KEY_PROV_HANDLE_PROP_ID, 0, NULL);
499 ok(ret, "CertSetCertificateContextProperty failed: %08x\n",
501 /* and the key context's CSP is set to NULL. */
502 size = sizeof(keyContext);
503 ret = CertGetCertificateContextProperty(context,
504 CERT_KEY_CONTEXT_PROP_ID, &keyContext, &size);
505 ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
507 ok(keyContext.hCryptProv == 0, "Expected no hCryptProv\n");
509 CryptReleaseContext(csp, 0);
511 CertFreeCertificateContext(context);
514 static void testDupCert(void)
517 PCCERT_CONTEXT context, dupContext;
520 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
521 CERT_STORE_CREATE_NEW_FLAG, NULL);
522 ok(store != NULL, "CertOpenStore failed: %d\n", GetLastError());
526 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
527 bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, &context);
528 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
530 ok(context != NULL, "Expected a valid cert context\n");
533 ok(context->cbCertEncoded == sizeof(bigCert),
534 "Wrong cert size %d\n", context->cbCertEncoded);
535 ok(!memcmp(context->pbCertEncoded, bigCert, sizeof(bigCert)),
536 "Unexpected encoded cert in context\n");
537 ok(context->hCertStore == store, "Unexpected store\n");
539 dupContext = CertDuplicateCertificateContext(context);
540 ok(dupContext != NULL, "Expected valid duplicate\n");
541 /* Not only is it a duplicate, it's identical: the address is the
544 ok(dupContext == context, "Expected identical context addresses\n");
545 CertFreeCertificateContext(dupContext);
546 CertFreeCertificateContext(context);
548 CertCloseStore(store, 0);
551 static void testFindCert(void)
554 PCCERT_CONTEXT context = NULL;
556 CERT_INFO certInfo = { 0 };
557 CRYPT_HASH_BLOB blob;
559 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
560 CERT_STORE_CREATE_NEW_FLAG, NULL);
561 ok(store != NULL, "CertOpenStore failed: %d\n", GetLastError());
565 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
566 bigCert, sizeof(bigCert), CERT_STORE_ADD_NEW, NULL);
567 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
569 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
570 bigCert2, sizeof(bigCert2), CERT_STORE_ADD_NEW, NULL);
571 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
573 /* This has the same name as bigCert */
574 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
575 certWithUsage, sizeof(certWithUsage), CERT_STORE_ADD_NEW, NULL);
576 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
580 context = CertFindCertificateInStore(NULL, 0, 0, 0, NULL, NULL);
583 /* Check first cert's there, by issuer */
584 certInfo.Subject.pbData = subjectName;
585 certInfo.Subject.cbData = sizeof(subjectName);
586 certInfo.SerialNumber.pbData = serialNum;
587 certInfo.SerialNumber.cbData = sizeof(serialNum);
588 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
589 CERT_FIND_ISSUER_NAME, &certInfo.Subject, NULL);
590 ok(context != NULL, "CertFindCertificateInStore failed: %08x\n",
594 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
595 CERT_FIND_ISSUER_NAME, &certInfo.Subject, context);
596 ok(context != NULL, "Expected more than one cert\n");
599 context = CertFindCertificateInStore(store, X509_ASN_ENCODING,
600 0, CERT_FIND_ISSUER_NAME, &certInfo.Subject, context);
601 ok(context == NULL, "Expected precisely two certs\n");
605 /* Check second cert's there as well, by subject name */
606 certInfo.Subject.pbData = subjectName2;
607 certInfo.Subject.cbData = sizeof(subjectName2);
608 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
609 CERT_FIND_SUBJECT_NAME, &certInfo.Subject, NULL);
610 ok(context != NULL, "CertFindCertificateInStore failed: %08x\n",
614 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
615 CERT_FIND_SUBJECT_NAME, &certInfo.Subject, context);
616 ok(context == NULL, "Expected one cert only\n");
619 /* Strange but true: searching for the subject cert requires you to set
620 * the issuer, not the subject
622 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
623 CERT_FIND_SUBJECT_CERT, &certInfo.Subject, NULL);
624 ok(context == NULL, "Expected no certificate\n");
625 certInfo.Subject.pbData = NULL;
626 certInfo.Subject.cbData = 0;
627 certInfo.Issuer.pbData = subjectName2;
628 certInfo.Issuer.cbData = sizeof(subjectName2);
629 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
630 CERT_FIND_SUBJECT_CERT, &certInfo, NULL);
631 ok(context != NULL, "CertFindCertificateInStore failed: %08x\n",
635 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
636 CERT_FIND_SUBJECT_CERT, &certInfo.Subject, context);
637 ok(context == NULL, "Expected one cert only\n");
640 /* The nice thing about hashes, they're unique */
641 blob.pbData = bigCertHash;
642 blob.cbData = sizeof(bigCertHash);
643 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
644 CERT_FIND_SHA1_HASH, &blob, NULL);
645 ok(context != NULL, "CertFindCertificateInStore failed: %08x\n",
649 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
650 CERT_FIND_SHA1_HASH, &certInfo.Subject, context);
651 ok(context == NULL, "Expected one cert only\n");
654 CertCloseStore(store, 0);
657 static void testGetSubjectCert(void)
660 PCCERT_CONTEXT context1, context2;
661 CERT_INFO info = { 0 };
664 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
665 CERT_STORE_CREATE_NEW_FLAG, NULL);
666 ok(store != NULL, "CertOpenStore failed: %d\n", GetLastError());
670 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
671 bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL);
672 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
674 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
675 bigCert2, sizeof(bigCert2), CERT_STORE_ADD_NEW, &context1);
676 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
678 ok(context1 != NULL, "Expected a context\n");
679 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
680 certWithUsage, sizeof(certWithUsage), CERT_STORE_ADD_NEW, NULL);
681 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
684 context2 = CertGetSubjectCertificateFromStore(store, X509_ASN_ENCODING,
686 ok(!context2 && GetLastError() == E_INVALIDARG,
687 "Expected E_INVALIDARG, got %08x\n", GetLastError());
688 context2 = CertGetSubjectCertificateFromStore(store, X509_ASN_ENCODING,
690 ok(!context2 && GetLastError() == CRYPT_E_NOT_FOUND,
691 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
692 info.SerialNumber.cbData = sizeof(serialNum);
693 info.SerialNumber.pbData = serialNum;
694 context2 = CertGetSubjectCertificateFromStore(store, X509_ASN_ENCODING,
696 ok(!context2 && GetLastError() == CRYPT_E_NOT_FOUND,
697 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
698 info.Issuer.cbData = sizeof(subjectName2);
699 info.Issuer.pbData = subjectName2;
700 context2 = CertGetSubjectCertificateFromStore(store, X509_ASN_ENCODING,
703 "CertGetSubjectCertificateFromStore failed: %08x\n", GetLastError());
704 /* Not only should this find a context, but it should be the same
705 * (same address) as context1.
707 ok(context1 == context2, "Expected identical context addresses\n");
708 CertFreeCertificateContext(context2);
710 CertFreeCertificateContext(context1);
711 CertCloseStore(store, 0);
714 /* This expires in 1970 or so */
715 static const BYTE expiredCert[] = { 0x30, 0x82, 0x01, 0x33, 0x30, 0x81, 0xe2,
716 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0xc4, 0xd7, 0x7f, 0x0e, 0x6f, 0xa6,
717 0x8c, 0xaa, 0x47, 0x47, 0x40, 0xe7, 0xb7, 0x0b, 0x4a, 0x7f, 0x30, 0x09, 0x06,
718 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1d, 0x05, 0x00, 0x30, 0x1f, 0x31, 0x1d, 0x30,
719 0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63, 0x40,
720 0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63,
721 0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x36, 0x39, 0x30, 0x31, 0x30, 0x31, 0x30,
722 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x37, 0x30, 0x30, 0x31, 0x30,
723 0x31, 0x30, 0x36, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x1f, 0x31, 0x1d, 0x30,
724 0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63, 0x40,
725 0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63,
726 0x6f, 0x6d, 0x30, 0x5c, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
727 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x4b, 0x00, 0x30, 0x48, 0x02, 0x41,
728 0x00, 0xa1, 0xaf, 0x4a, 0xea, 0xa7, 0x83, 0x57, 0xc0, 0x37, 0x33, 0x7e, 0x29,
729 0x5e, 0x0d, 0xfc, 0x44, 0x74, 0x3a, 0x1d, 0xc3, 0x1b, 0x1d, 0x96, 0xed, 0x4e,
730 0xf4, 0x1b, 0x98, 0xec, 0x69, 0x1b, 0x04, 0xea, 0x25, 0xcf, 0xb3, 0x2a, 0xf5,
731 0xd9, 0x22, 0xd9, 0x8d, 0x08, 0x39, 0x81, 0xc6, 0xe0, 0x4f, 0x12, 0x37, 0x2a,
732 0x3f, 0x80, 0xa6, 0x6c, 0x67, 0x43, 0x3a, 0xdd, 0x95, 0x0c, 0xbb, 0x2f, 0x6b,
733 0x02, 0x03, 0x01, 0x00, 0x01, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02,
734 0x1d, 0x05, 0x00, 0x03, 0x41, 0x00, 0x8f, 0xa2, 0x5b, 0xd6, 0xdf, 0x34, 0xd0,
735 0xa2, 0xa7, 0x47, 0xf1, 0x13, 0x79, 0xd3, 0xf3, 0x39, 0xbd, 0x4e, 0x2b, 0xa3,
736 0xf4, 0x63, 0x37, 0xac, 0x5a, 0x0c, 0x5e, 0x4d, 0x0d, 0x54, 0x87, 0x4f, 0x31,
737 0xfb, 0xa0, 0xce, 0x8f, 0x9a, 0x2f, 0x4d, 0x48, 0xc6, 0x84, 0x8d, 0xf5, 0x70,
738 0x74, 0x17, 0xa5, 0xf3, 0x66, 0x47, 0x06, 0xd6, 0x64, 0x45, 0xbc, 0x52, 0xef,
739 0x49, 0xe5, 0xf9, 0x65, 0xf3 };
741 /* This expires in 2036 or so */
742 static const BYTE childOfExpired[] = { 0x30, 0x81, 0xcc, 0x30, 0x78, 0xa0,
743 0x03, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86,
744 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x1f, 0x31, 0x1d,
745 0x30, 0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63,
746 0x40, 0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e,
747 0x63, 0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x30, 0x36, 0x30, 0x35, 0x30, 0x35,
748 0x31, 0x37, 0x31, 0x32, 0x34, 0x39, 0x5a, 0x17, 0x0d, 0x33, 0x36, 0x30, 0x35,
749 0x30, 0x35, 0x31, 0x37, 0x31, 0x32, 0x34, 0x39, 0x5a, 0x30, 0x15, 0x31, 0x13,
750 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e,
751 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03,
752 0x01, 0x00, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
753 0x01, 0x05, 0x05, 0x00, 0x03, 0x41, 0x00, 0x20, 0x3b, 0xdb, 0x4d, 0x67, 0x50,
754 0xec, 0x73, 0x9d, 0xf9, 0x85, 0x5d, 0x18, 0xe9, 0xb4, 0x98, 0xe3, 0x31, 0xb7,
755 0x03, 0x0b, 0xc0, 0x39, 0x93, 0x56, 0x81, 0x0a, 0xfc, 0x78, 0xa8, 0x29, 0x42,
756 0x5f, 0x69, 0xfb, 0xbc, 0x5b, 0xf2, 0xa6, 0x2a, 0xbe, 0x91, 0x2c, 0xfc, 0x89,
757 0x69, 0x15, 0x18, 0x58, 0xe5, 0x02, 0x75, 0xf7, 0x2a, 0xb6, 0xa9, 0xfb, 0x47,
758 0x6a, 0x6e, 0x0a, 0x9b, 0xe9, 0xdc };
760 static void testGetIssuerCert(void)
763 PCCERT_CONTEXT parent, child;
764 DWORD flags = 0xffffffff;
765 HCERTSTORE store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
766 CERT_STORE_CREATE_NEW_FLAG, NULL);
768 ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
770 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
771 expiredCert, sizeof(expiredCert), CERT_STORE_ADD_ALWAYS, NULL);
772 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
775 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
776 childOfExpired, sizeof(childOfExpired), CERT_STORE_ADD_ALWAYS, &child);
777 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
781 parent = CertGetIssuerCertificateFromStore(NULL, NULL, NULL, NULL);
782 parent = CertGetIssuerCertificateFromStore(store, NULL, NULL, NULL);
784 parent = CertGetIssuerCertificateFromStore(NULL, NULL, NULL, &flags);
785 ok(!parent && GetLastError() == E_INVALIDARG,
786 "Expected E_INVALIDARG, got %08x\n", GetLastError());
787 parent = CertGetIssuerCertificateFromStore(store, NULL, NULL, &flags);
788 ok(!parent && GetLastError() == E_INVALIDARG,
789 "Expected E_INVALIDARG, got %08x\n", GetLastError());
790 parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
791 ok(!parent && GetLastError() == E_INVALIDARG,
792 "Expected E_INVALIDARG, got %08x\n", GetLastError());
793 /* Confusing: the caller cannot set either of the
794 * CERT_STORE_NO_*_FLAGs, as these are not checks,
797 flags = CERT_STORE_NO_CRL_FLAG | CERT_STORE_NO_ISSUER_FLAG;
798 parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
799 ok(!parent && GetLastError() == E_INVALIDARG,
800 "Expected E_INVALIDARG, got %08x\n", GetLastError());
801 /* Perform no checks */
803 parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
804 ok(parent != NULL, "CertGetIssuerCertificateFromStore failed: %08x\n",
807 CertFreeCertificateContext(parent);
808 /* Check revocation and signature only */
809 flags = CERT_STORE_REVOCATION_FLAG | CERT_STORE_SIGNATURE_FLAG;
810 parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
811 ok(parent != NULL, "CertGetIssuerCertificateFromStore failed: %08x\n",
813 /* Confusing: CERT_STORE_REVOCATION_FLAG succeeds when there is no CRL by
814 * setting CERT_STORE_NO_CRL_FLAG.
816 ok(flags == (CERT_STORE_REVOCATION_FLAG | CERT_STORE_NO_CRL_FLAG),
817 "Expected CERT_STORE_REVOCATION_FLAG | CERT_STORE_NO_CRL_FLAG, got %08x\n",
820 CertFreeCertificateContext(parent);
821 /* Now check just the time */
822 flags = CERT_STORE_TIME_VALIDITY_FLAG;
823 parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
824 ok(parent != NULL, "CertGetIssuerCertificateFromStore failed: %08x\n",
826 /* Oops: the child is not expired, so the time validity check actually
827 * succeeds, even though the signing cert is expired.
829 ok(!flags, "Expected check to succeed, got %08x\n", flags);
831 CertFreeCertificateContext(parent);
833 CertFreeCertificateContext(child);
834 CertCloseStore(store, 0);
837 static void testCryptHashCert(void)
839 static const BYTE emptyHash[] = { 0xda, 0x39, 0xa3, 0xee, 0x5e, 0x6b, 0x4b,
840 0x0d, 0x32, 0x55, 0xbf, 0xef, 0x95, 0x60, 0x18, 0x90, 0xaf, 0xd8, 0x07,
842 static const BYTE knownHash[] = { 0xae, 0x9d, 0xbf, 0x6d, 0xf5, 0x46, 0xee,
843 0x8b, 0xc5, 0x7a, 0x13, 0xba, 0xc2, 0xb1, 0x04, 0xf2, 0xbf, 0x52, 0xa8,
845 static const BYTE toHash[] = "abcdefghijklmnopqrstuvwxyz0123456789.,;!?:";
848 DWORD hashLen = sizeof(hash);
850 /* NULL buffer and nonzero length crashes
851 ret = CryptHashCertificate(0, 0, 0, NULL, size, hash, &hashLen);
852 empty hash length also crashes
853 ret = CryptHashCertificate(0, 0, 0, buf, size, hash, NULL);
855 /* Test empty hash */
856 ret = CryptHashCertificate(0, 0, 0, toHash, sizeof(toHash), NULL,
858 ok(ret, "CryptHashCertificate failed: %08x\n", GetLastError());
859 ok(hashLen == sizeof(hash), "Got unexpected size of hash %d\n", hashLen);
860 /* Test with empty buffer */
861 ret = CryptHashCertificate(0, 0, 0, NULL, 0, hash, &hashLen);
862 ok(ret, "CryptHashCertificate failed: %08x\n", GetLastError());
863 ok(!memcmp(hash, emptyHash, sizeof(emptyHash)),
864 "Unexpected hash of nothing\n");
865 /* Test a known value */
866 ret = CryptHashCertificate(0, 0, 0, toHash, sizeof(toHash), hash,
868 ok(ret, "CryptHashCertificate failed: %08x\n", GetLastError());
869 ok(!memcmp(hash, knownHash, sizeof(knownHash)), "Unexpected hash\n");
872 static void verifySig(HCRYPTPROV csp, const BYTE *toSign, size_t toSignLen,
873 const BYTE *sig, unsigned int sigLen)
876 BOOL ret = CryptCreateHash(csp, CALG_SHA1, 0, 0, &hash);
878 ok(ret, "CryptCreateHash failed: %08x\n", GetLastError());
882 DWORD mySigSize = sizeof(mySig);
884 ret = CryptHashData(hash, toSign, toSignLen, 0);
885 ok(ret, "CryptHashData failed: %08x\n", GetLastError());
886 /* use the A variant so the test can run on Win9x */
887 ret = CryptSignHashA(hash, AT_SIGNATURE, NULL, 0, mySig, &mySigSize);
888 ok(ret, "CryptSignHash failed: %08x\n", GetLastError());
891 ok(mySigSize == sigLen, "Expected sig length %d, got %d\n",
893 ok(!memcmp(mySig, sig, sigLen), "Unexpected signature\n");
895 CryptDestroyHash(hash);
899 /* Tests signing the certificate described by toBeSigned with the CSP passed in,
900 * using the algorithm with OID sigOID. The CSP is assumed to be empty, and a
901 * keyset named AT_SIGNATURE will be added to it. The signing key will be
902 * stored in *key, and the signature will be stored in sig. sigLen should be
905 static void testSignCert(HCRYPTPROV csp, const CRYPT_DATA_BLOB *toBeSigned,
906 LPCSTR sigOID, HCRYPTKEY *key, BYTE *sig, DWORD *sigLen)
910 CRYPT_ALGORITHM_IDENTIFIER algoID = { NULL, { 0, NULL } };
913 ret = CryptSignCertificate(0, 0, 0, NULL, 0, NULL, NULL, NULL, NULL);
914 ret = CryptSignCertificate(0, 0, 0, NULL, 0, NULL, NULL, NULL, &size);
915 ret = CryptSignCertificate(0, 0, 0, toBeSigned->pbData, toBeSigned->cbData,
916 NULL, NULL, NULL, &size);
918 ret = CryptSignCertificate(0, 0, 0, toBeSigned->pbData, toBeSigned->cbData,
919 &algoID, NULL, NULL, &size);
920 ok(!ret && GetLastError() == NTE_BAD_ALGID,
921 "Expected NTE_BAD_ALGID, got %08x\n", GetLastError());
922 algoID.pszObjId = (LPSTR)sigOID;
923 ret = CryptSignCertificate(0, 0, 0, toBeSigned->pbData, toBeSigned->cbData,
924 &algoID, NULL, NULL, &size);
925 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
926 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
927 ret = CryptSignCertificate(0, AT_SIGNATURE, 0, toBeSigned->pbData,
928 toBeSigned->cbData, &algoID, NULL, NULL, &size);
929 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
930 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
932 /* No keys exist in the new CSP yet.. */
933 ret = CryptSignCertificate(csp, AT_SIGNATURE, 0, toBeSigned->pbData,
934 toBeSigned->cbData, &algoID, NULL, NULL, &size);
935 ok(!ret && (GetLastError() == NTE_BAD_KEYSET || GetLastError() ==
936 NTE_NO_KEY), "Expected NTE_BAD_KEYSET or NTE_NO_KEY, got %08x\n",
938 ret = CryptGenKey(csp, AT_SIGNATURE, 0, key);
939 ok(ret, "CryptGenKey failed: %08x\n", GetLastError());
942 ret = CryptSignCertificate(csp, AT_SIGNATURE, 0, toBeSigned->pbData,
943 toBeSigned->cbData, &algoID, NULL, NULL, &size);
944 ok(ret, "CryptSignCertificate failed: %08x\n", GetLastError());
945 ok(size <= *sigLen, "Expected size <= %d, got %d\n", *sigLen, size);
948 ret = CryptSignCertificate(csp, AT_SIGNATURE, 0, toBeSigned->pbData,
949 toBeSigned->cbData, &algoID, NULL, sig, &size);
950 ok(ret, "CryptSignCertificate failed: %08x\n", GetLastError());
954 verifySig(csp, toBeSigned->pbData, toBeSigned->cbData, sig,
961 static void testVerifyCertSig(HCRYPTPROV csp, const CRYPT_DATA_BLOB *toBeSigned,
962 LPCSTR sigOID, const BYTE *sig, DWORD sigLen)
964 CERT_SIGNED_CONTENT_INFO info;
969 if (!pCryptVerifyCertificateSignatureEx)
971 skip("no CryptVerifyCertificateSignatureEx support\n");
974 ret = pCryptVerifyCertificateSignatureEx(0, 0, 0, NULL, 0, NULL, 0, NULL);
975 ok(!ret && GetLastError() == E_INVALIDARG,
976 "Expected E_INVALIDARG, got %08x\n", GetLastError());
977 ret = pCryptVerifyCertificateSignatureEx(csp, 0, 0, NULL, 0, NULL, 0, NULL);
978 ok(!ret && GetLastError() == E_INVALIDARG,
979 "Expected E_INVALIDARG, got %08x\n", GetLastError());
980 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING, 0, NULL, 0,
982 ok(!ret && GetLastError() == E_INVALIDARG,
983 "Expected E_INVALIDARG, got %08x\n", GetLastError());
985 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
986 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, NULL, 0, NULL, 0, NULL);
988 info.ToBeSigned.cbData = toBeSigned->cbData;
989 info.ToBeSigned.pbData = toBeSigned->pbData;
990 info.SignatureAlgorithm.pszObjId = (LPSTR)sigOID;
991 info.SignatureAlgorithm.Parameters.cbData = 0;
992 info.Signature.cbData = sigLen;
993 info.Signature.pbData = (BYTE *)sig;
994 info.Signature.cUnusedBits = 0;
995 ret = CryptEncodeObjectEx(X509_ASN_ENCODING, X509_CERT, &info,
996 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&cert, &size);
997 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1000 CRYPT_DATA_BLOB certBlob = { 0, NULL };
1001 PCERT_PUBLIC_KEY_INFO pubKeyInfo = NULL;
1003 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
1004 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob, 0, NULL, 0, NULL);
1005 ok(!ret && GetLastError() == CRYPT_E_ASN1_EOD,
1006 "Expected CRYPT_E_ASN1_EOD, got %08x\n", GetLastError());
1007 certBlob.cbData = 1;
1008 certBlob.pbData = (void *)0xdeadbeef;
1009 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
1010 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob, 0, NULL, 0, NULL);
1011 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
1012 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
1013 certBlob.cbData = size;
1014 certBlob.pbData = cert;
1015 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
1016 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob, 0, NULL, 0, NULL);
1017 ok(!ret && GetLastError() == E_INVALIDARG,
1018 "Expected E_INVALIDARG, got %08x\n", GetLastError());
1019 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
1020 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob,
1021 CRYPT_VERIFY_CERT_SIGN_ISSUER_NULL, NULL, 0, NULL);
1022 ok(!ret && GetLastError() == E_INVALIDARG,
1023 "Expected E_INVALIDARG, got %08x\n", GetLastError());
1025 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
1026 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob,
1027 CRYPT_VERIFY_CERT_SIGN_ISSUER_PUBKEY, NULL, 0, NULL);
1029 CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING,
1030 (LPSTR)sigOID, 0, NULL, NULL, &size);
1031 pubKeyInfo = HeapAlloc(GetProcessHeap(), 0, size);
1034 ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE,
1035 X509_ASN_ENCODING, (LPSTR)sigOID, 0, NULL, pubKeyInfo, &size);
1036 ok(ret, "CryptExportKey failed: %08x\n", GetLastError());
1039 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
1040 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob,
1041 CRYPT_VERIFY_CERT_SIGN_ISSUER_PUBKEY, pubKeyInfo, 0, NULL);
1042 ok(ret, "CryptVerifyCertificateSignatureEx failed: %08x\n",
1045 HeapFree(GetProcessHeap(), 0, pubKeyInfo);
1051 static BYTE emptyCert[] = { 0x30, 0x00 };
1053 static void testCertSigs(void)
1056 CRYPT_DATA_BLOB toBeSigned = { sizeof(emptyCert), emptyCert };
1060 DWORD sigSize = sizeof(sig);
1062 /* Just in case a previous run failed, delete this thing */
1063 CryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
1064 CRYPT_DELETEKEYSET);
1065 ret = CryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
1067 ok(ret, "CryptAcquireContext failed: %08x\n", GetLastError());
1069 testSignCert(csp, &toBeSigned, szOID_RSA_SHA1RSA, &key, sig, &sigSize);
1070 testVerifyCertSig(csp, &toBeSigned, szOID_RSA_SHA1RSA, sig, sigSize);
1072 CryptDestroyKey(key);
1073 CryptReleaseContext(csp, 0);
1074 ret = CryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
1075 CRYPT_DELETEKEYSET);
1078 static const BYTE md5SignedEmptyCert[] = {
1079 0x30,0x56,0x30,0x33,0x02,0x00,0x30,0x02,0x06,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,
1080 0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,
1081 0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x07,
1082 0x30,0x02,0x06,0x00,0x03,0x01,0x00,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,
1083 0x0d,0x02,0x05,0x05,0x00,0x03,0x11,0x00,0xfb,0x0f,0x66,0x82,0x66,0xd9,0xe5,0xf8,
1084 0xd8,0xa2,0x55,0x2b,0xe1,0xa5,0xd9,0x04 };
1085 static const BYTE md5SignedEmptyCertNoNull[] = {
1086 0x30,0x54,0x30,0x33,0x02,0x00,0x30,0x02,0x06,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,
1087 0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,
1088 0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x07,
1089 0x30,0x02,0x06,0x00,0x03,0x01,0x00,0x30,0x0a,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,
1090 0x0d,0x02,0x05,0x03,0x11,0x00,0x04,0xd9,0xa5,0xe1,0x2b,0x55,0xa2,0xd8,0xf8,0xe5,
1091 0xd9,0x66,0x82,0x66,0x0f,0xfb };
1093 static void testSignAndEncodeCert(void)
1095 static char oid_rsa_md5rsa[] = szOID_RSA_MD5RSA;
1096 static char oid_rsa_md5[] = szOID_RSA_MD5;
1099 CRYPT_ALGORITHM_IDENTIFIER algID = { 0 };
1100 CERT_INFO info = { 0 };
1103 ret = CryptSignAndEncodeCertificate(0, 0, 0, NULL, NULL, NULL, NULL, NULL,
1105 ret = CryptSignAndEncodeCertificate(0, 0, 0, NULL, NULL, NULL, NULL, NULL,
1108 ret = CryptSignAndEncodeCertificate(0, 0, 0, NULL, NULL, &algID, NULL, NULL,
1110 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
1111 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
1112 ret = CryptSignAndEncodeCertificate(0, 0, X509_ASN_ENCODING, NULL, NULL,
1113 &algID, NULL, NULL, &size);
1114 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
1115 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
1116 ret = CryptSignAndEncodeCertificate(0, 0, 0, X509_CERT_TO_BE_SIGNED, NULL,
1117 &algID, NULL, NULL, &size);
1118 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
1119 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
1120 ret = CryptSignAndEncodeCertificate(0, 0, X509_ASN_ENCODING,
1121 X509_CERT_TO_BE_SIGNED, NULL, &algID, NULL, NULL, &size);
1122 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
1123 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
1125 ret = CryptSignAndEncodeCertificate(0, 0, X509_ASN_ENCODING,
1126 X509_CERT_TO_BE_SIGNED, &info, NULL, NULL, NULL, &size);
1128 ret = CryptSignAndEncodeCertificate(0, 0, X509_ASN_ENCODING,
1129 X509_CERT_TO_BE_SIGNED, &info, &algID, NULL, NULL, &size);
1130 ok(!ret && GetLastError() == NTE_BAD_ALGID,
1131 "Expected NTE_BAD_ALGID, got %08x\n", GetLastError());
1132 algID.pszObjId = oid_rsa_md5rsa;
1133 ret = CryptSignAndEncodeCertificate(0, 0, X509_ASN_ENCODING,
1134 X509_CERT_TO_BE_SIGNED, &info, &algID, NULL, NULL, &size);
1135 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1136 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
1137 algID.pszObjId = oid_rsa_md5;
1138 ret = CryptSignAndEncodeCertificate(0, 0, X509_ASN_ENCODING,
1139 X509_CERT_TO_BE_SIGNED, &info, &algID, NULL, NULL, &size);
1140 ok(ret, "CryptSignAndEncodeCertificate failed: %08x\n", GetLastError());
1143 LPBYTE buf = HeapAlloc(GetProcessHeap(), 0, size);
1147 ret = CryptSignAndEncodeCertificate(0, 0, X509_ASN_ENCODING,
1148 X509_CERT_TO_BE_SIGNED, &info, &algID, NULL, buf, &size);
1149 ok(ret, "CryptSignAndEncodeCertificate failed: %08x\n",
1151 /* Tricky: because the NULL parameters may either be omitted or
1152 * included as an asn.1-encoded NULL (0x05,0x00), two different
1153 * values are allowed.
1155 ok(size == sizeof(md5SignedEmptyCert) ||
1156 size == sizeof(md5SignedEmptyCertNoNull), "Unexpected size %d\n",
1158 if (size == sizeof(md5SignedEmptyCert))
1159 ok(!memcmp(buf, md5SignedEmptyCert, size),
1160 "Unexpected value\n");
1161 else if (size == sizeof(md5SignedEmptyCertNoNull))
1162 ok(!memcmp(buf, md5SignedEmptyCertNoNull, size),
1163 "Unexpected value\n");
1164 HeapFree(GetProcessHeap(), 0, buf);
1169 static void testCreateSelfSignCert(void)
1171 PCCERT_CONTEXT context;
1172 CERT_NAME_BLOB name = { sizeof(subjectName), subjectName };
1176 CRYPT_KEY_PROV_INFO info;
1179 context = CertCreateSelfSignCertificate(0, NULL, 0, NULL, NULL, NULL, NULL,
1181 * Calling this with no first parameter creates a new key container, which
1182 * lasts beyond the test, so I don't test that. Nb: the generated key
1184 context = CertCreateSelfSignCertificate(0, &name, 0, NULL, NULL, NULL, NULL,
1189 CryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
1190 CRYPT_DELETEKEYSET);
1191 ret = CryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
1193 ok(ret, "CryptAcquireContext failed: %08x\n", GetLastError());
1195 context = CertCreateSelfSignCertificate(csp, &name, 0, NULL, NULL, NULL,
1197 ok(!context && GetLastError() == NTE_NO_KEY,
1198 "Expected NTE_NO_KEY, got %08x\n", GetLastError());
1199 ret = CryptGenKey(csp, AT_SIGNATURE, 0, &key);
1200 ok(ret, "CryptGenKey failed: %08x\n", GetLastError());
1203 context = CertCreateSelfSignCertificate(csp, &name, 0, NULL, NULL, NULL,
1205 ok(context != NULL, "CertCreateSelfSignCertificate failed: %08x\n",
1210 PCRYPT_KEY_PROV_INFO info;
1212 /* The context must have a key provider info property */
1213 ret = CertGetCertificateContextProperty(context,
1214 CERT_KEY_PROV_INFO_PROP_ID, NULL, &size);
1215 ok(ret && size, "Expected non-zero key provider info\n");
1218 info = HeapAlloc(GetProcessHeap(), 0, size);
1221 ret = CertGetCertificateContextProperty(context,
1222 CERT_KEY_PROV_INFO_PROP_ID, info, &size);
1223 ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
1227 /* Sanity-check the key provider */
1228 ok(!lstrcmpW(info->pwszContainerName, cspNameW),
1229 "Unexpected key container\n");
1230 ok(!lstrcmpW(info->pwszProvName, MS_DEF_PROV_W),
1231 "Unexpected provider\n");
1232 ok(info->dwKeySpec == AT_SIGNATURE,
1233 "Expected AT_SIGNATURE, got %d\n", info->dwKeySpec);
1235 HeapFree(GetProcessHeap(), 0, info);
1239 CertFreeCertificateContext(context);
1242 CryptDestroyKey(key);
1245 CryptReleaseContext(csp, 0);
1246 ret = CryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
1247 CRYPT_DELETEKEYSET);
1249 /* do the same test with AT_KEYEXCHANGE and key info*/
1250 memset(&info,0,sizeof(info));
1251 info.dwProvType = PROV_RSA_FULL;
1252 info.dwKeySpec = AT_KEYEXCHANGE;
1253 info.pwszProvName = (LPWSTR) MS_DEF_PROV_W;
1254 info.pwszContainerName = cspNameW;
1255 context = CertCreateSelfSignCertificate(0, &name, 0, &info, NULL, NULL,
1257 ok(context != NULL, "CertCreateSelfSignCertificate failed: %08x\n",
1262 PCRYPT_KEY_PROV_INFO info;
1264 /* The context must have a key provider info property */
1265 ret = CertGetCertificateContextProperty(context,
1266 CERT_KEY_PROV_INFO_PROP_ID, NULL, &size);
1267 ok(ret && size, "Expected non-zero key provider info\n");
1270 info = HeapAlloc(GetProcessHeap(), 0, size);
1273 ret = CertGetCertificateContextProperty(context,
1274 CERT_KEY_PROV_INFO_PROP_ID, info, &size);
1275 ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
1279 /* Sanity-check the key provider */
1280 ok(!lstrcmpW(info->pwszContainerName, cspNameW),
1281 "Unexpected key container\n");
1282 ok(!lstrcmpW(info->pwszProvName, MS_DEF_PROV_W),
1283 "Unexpected provider\n");
1284 ok(info->dwKeySpec == AT_KEYEXCHANGE,
1285 "Expected AT_KEYEXCHANGE, got %d\n", info->dwKeySpec);
1287 HeapFree(GetProcessHeap(), 0, info);
1291 CertFreeCertificateContext(context);
1294 CryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
1295 CRYPT_DELETEKEYSET);
1298 static const LPCSTR keyUsages[] = { szOID_PKIX_KP_CODE_SIGNING,
1299 szOID_PKIX_KP_CLIENT_AUTH, szOID_RSA_RSA };
1301 static void testKeyUsage(void)
1304 PCCERT_CONTEXT context;
1307 /* Test base cases */
1308 ret = CertGetEnhancedKeyUsage(NULL, 0, NULL, NULL);
1309 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1310 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
1312 ret = CertGetEnhancedKeyUsage(NULL, 0, NULL, &size);
1313 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1314 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
1316 ret = CertGetEnhancedKeyUsage(NULL, 0, NULL, &size);
1317 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1318 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
1320 ret = CertSetEnhancedKeyUsage(NULL, NULL);
1321 usage.cUsageIdentifier = 0;
1322 ret = CertSetEnhancedKeyUsage(NULL, &usage);
1324 /* Test with a cert with no enhanced key usage extension */
1325 context = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert,
1327 ok(context != NULL, "CertCreateCertificateContext failed: %08x\n",
1331 static const char oid[] = "1.2.3.4";
1332 BYTE buf[sizeof(CERT_ENHKEY_USAGE) + 2 * (sizeof(LPSTR) + sizeof(oid))];
1333 PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
1335 ret = CertGetEnhancedKeyUsage(context, 0, NULL, NULL);
1336 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1337 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
1339 ret = CertGetEnhancedKeyUsage(context, 0, NULL, &size);
1342 /* Windows 2000, ME, or later: even though it succeeded, we expect
1343 * CRYPT_E_NOT_FOUND, which indicates there is no enhanced key
1344 * usage set for this cert (which implies it's valid for all uses.)
1346 ok(GetLastError() == CRYPT_E_NOT_FOUND,
1347 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
1348 ok(size == sizeof(CERT_ENHKEY_USAGE), "Wrong size %d\n", size);
1349 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
1350 ok(ret, "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
1351 ok(pUsage->cUsageIdentifier == 0, "Expected 0 usages, got %d\n",
1352 pUsage->cUsageIdentifier);
1356 /* Windows NT, 95, or 98: it fails, and the last error is
1357 * CRYPT_E_NOT_FOUND.
1359 ok(GetLastError() == CRYPT_E_NOT_FOUND,
1360 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
1362 /* I can add a usage identifier when no key usage has been set */
1363 ret = CertAddEnhancedKeyUsageIdentifier(context, oid);
1364 ok(ret, "CertAddEnhancedKeyUsageIdentifier failed: %08x\n",
1367 ret = CertGetEnhancedKeyUsage(context,
1368 CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG, pUsage, &size);
1369 ok(ret && GetLastError() == 0,
1370 "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
1371 ok(pUsage->cUsageIdentifier == 1, "Expected 1 usage, got %d\n",
1372 pUsage->cUsageIdentifier);
1373 if (pUsage->cUsageIdentifier)
1374 ok(!strcmp(pUsage->rgpszUsageIdentifier[0], oid),
1375 "Expected %s, got %s\n", oid, pUsage->rgpszUsageIdentifier[0]);
1376 /* Now set an empty key usage */
1377 pUsage->cUsageIdentifier = 0;
1378 ret = CertSetEnhancedKeyUsage(context, pUsage);
1379 ok(ret, "CertSetEnhancedKeyUsage failed: %08x\n", GetLastError());
1380 /* Shouldn't find it in the cert */
1382 ret = CertGetEnhancedKeyUsage(context,
1383 CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, pUsage, &size);
1384 ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
1385 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
1386 /* Should find it as an extended property */
1387 ret = CertGetEnhancedKeyUsage(context,
1388 CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG, pUsage, &size);
1389 ok(ret && GetLastError() == 0,
1390 "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
1391 ok(pUsage->cUsageIdentifier == 0, "Expected 0 usages, got %d\n",
1392 pUsage->cUsageIdentifier);
1393 /* Should find it as either */
1394 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
1395 ok(ret && GetLastError() == 0,
1396 "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
1397 ok(pUsage->cUsageIdentifier == 0, "Expected 0 usages, got %d\n",
1398 pUsage->cUsageIdentifier);
1399 /* Add a usage identifier */
1400 ret = CertAddEnhancedKeyUsageIdentifier(context, oid);
1401 ok(ret, "CertAddEnhancedKeyUsageIdentifier failed: %08x\n",
1404 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
1405 ok(ret && GetLastError() == 0,
1406 "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
1407 ok(pUsage->cUsageIdentifier == 1, "Expected 1 identifier, got %d\n",
1408 pUsage->cUsageIdentifier);
1409 if (pUsage->cUsageIdentifier)
1410 ok(!strcmp(pUsage->rgpszUsageIdentifier[0], oid),
1411 "Expected %s, got %s\n", oid, pUsage->rgpszUsageIdentifier[0]);
1412 /* Yep, I can re-add the same usage identifier */
1413 ret = CertAddEnhancedKeyUsageIdentifier(context, oid);
1414 ok(ret, "CertAddEnhancedKeyUsageIdentifier failed: %08x\n",
1417 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
1418 ok(ret && GetLastError() == 0,
1419 "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
1420 ok(pUsage->cUsageIdentifier == 2, "Expected 2 identifiers, got %d\n",
1421 pUsage->cUsageIdentifier);
1422 if (pUsage->cUsageIdentifier)
1423 ok(!strcmp(pUsage->rgpszUsageIdentifier[0], oid),
1424 "Expected %s, got %s\n", oid, pUsage->rgpszUsageIdentifier[0]);
1425 if (pUsage->cUsageIdentifier >= 2)
1426 ok(!strcmp(pUsage->rgpszUsageIdentifier[1], oid),
1427 "Expected %s, got %s\n", oid, pUsage->rgpszUsageIdentifier[1]);
1428 /* Now set a NULL extended property--this deletes the property. */
1429 ret = CertSetEnhancedKeyUsage(context, NULL);
1430 ok(ret, "CertSetEnhancedKeyUsage failed: %08x\n", GetLastError());
1431 SetLastError(0xbaadcafe);
1433 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
1434 ok(GetLastError() == CRYPT_E_NOT_FOUND,
1435 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
1437 CertFreeCertificateContext(context);
1439 /* Now test with a cert with an enhanced key usage extension */
1440 context = CertCreateCertificateContext(X509_ASN_ENCODING, certWithUsage,
1441 sizeof(certWithUsage));
1442 ok(context != NULL, "CertCreateCertificateContext failed: %08x\n",
1447 DWORD bufSize = 0, i;
1449 /* The size may depend on what flags are used to query it, so I
1450 * realloc the buffer for each test.
1452 ret = CertGetEnhancedKeyUsage(context,
1453 CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, NULL, &bufSize);
1454 ok(ret, "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
1455 buf = HeapAlloc(GetProcessHeap(), 0, bufSize);
1458 PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
1460 /* Should find it in the cert */
1462 ret = CertGetEnhancedKeyUsage(context,
1463 CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, pUsage, &size);
1464 ok(ret && GetLastError() == 0,
1465 "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
1466 ok(pUsage->cUsageIdentifier == 3, "Expected 3 usages, got %d\n",
1467 pUsage->cUsageIdentifier);
1468 for (i = 0; i < pUsage->cUsageIdentifier; i++)
1469 ok(!strcmp(pUsage->rgpszUsageIdentifier[i], keyUsages[i]),
1470 "Expected %s, got %s\n", keyUsages[i],
1471 pUsage->rgpszUsageIdentifier[i]);
1472 HeapFree(GetProcessHeap(), 0, buf);
1474 ret = CertGetEnhancedKeyUsage(context, 0, NULL, &bufSize);
1475 ok(ret, "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
1476 buf = HeapAlloc(GetProcessHeap(), 0, bufSize);
1479 PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
1481 /* Should find it as either */
1483 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
1484 /* In Windows, GetLastError returns CRYPT_E_NOT_FOUND not found
1485 * here, even though the return is successful and the usage id
1486 * count is positive. I don't enforce that here.
1489 "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
1490 ok(pUsage->cUsageIdentifier == 3, "Expected 3 usages, got %d\n",
1491 pUsage->cUsageIdentifier);
1492 for (i = 0; i < pUsage->cUsageIdentifier; i++)
1493 ok(!strcmp(pUsage->rgpszUsageIdentifier[i], keyUsages[i]),
1494 "Expected %s, got %s\n", keyUsages[i],
1495 pUsage->rgpszUsageIdentifier[i]);
1496 HeapFree(GetProcessHeap(), 0, buf);
1498 /* Shouldn't find it as an extended property */
1499 ret = CertGetEnhancedKeyUsage(context,
1500 CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG, NULL, &size);
1501 ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
1502 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
1503 /* Adding a usage identifier overrides the cert's usage!? */
1504 ret = CertAddEnhancedKeyUsageIdentifier(context, szOID_RSA_RSA);
1505 ok(ret, "CertAddEnhancedKeyUsageIdentifier failed: %08x\n",
1507 ret = CertGetEnhancedKeyUsage(context, 0, NULL, &bufSize);
1508 ok(ret, "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
1509 buf = HeapAlloc(GetProcessHeap(), 0, bufSize);
1512 PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
1514 /* Should find it as either */
1516 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
1518 "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
1519 ok(pUsage->cUsageIdentifier == 1, "Expected 1 usage, got %d\n",
1520 pUsage->cUsageIdentifier);
1521 ok(!strcmp(pUsage->rgpszUsageIdentifier[0], szOID_RSA_RSA),
1522 "Expected %s, got %s\n", szOID_RSA_RSA,
1523 pUsage->rgpszUsageIdentifier[0]);
1524 HeapFree(GetProcessHeap(), 0, buf);
1526 /* But querying the cert directly returns its usage */
1527 ret = CertGetEnhancedKeyUsage(context,
1528 CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, NULL, &bufSize);
1529 ok(ret, "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
1530 buf = HeapAlloc(GetProcessHeap(), 0, bufSize);
1533 PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
1536 ret = CertGetEnhancedKeyUsage(context,
1537 CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, pUsage, &size);
1539 "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
1540 ok(pUsage->cUsageIdentifier == 3, "Expected 3 usages, got %d\n",
1541 pUsage->cUsageIdentifier);
1542 for (i = 0; i < pUsage->cUsageIdentifier; i++)
1543 ok(!strcmp(pUsage->rgpszUsageIdentifier[i], keyUsages[i]),
1544 "Expected %s, got %s\n", keyUsages[i],
1545 pUsage->rgpszUsageIdentifier[i]);
1546 HeapFree(GetProcessHeap(), 0, buf);
1548 /* And removing the only usage identifier in the extended property
1549 * results in the cert's key usage being found.
1551 ret = CertRemoveEnhancedKeyUsageIdentifier(context, szOID_RSA_RSA);
1552 ok(ret, "CertRemoveEnhancedKeyUsage failed: %08x\n", GetLastError());
1553 ret = CertGetEnhancedKeyUsage(context, 0, NULL, &bufSize);
1554 ok(ret, "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
1555 buf = HeapAlloc(GetProcessHeap(), 0, bufSize);
1558 PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
1560 /* Should find it as either */
1562 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
1564 "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
1565 ok(pUsage->cUsageIdentifier == 3, "Expected 3 usages, got %d\n",
1566 pUsage->cUsageIdentifier);
1567 for (i = 0; i < pUsage->cUsageIdentifier; i++)
1568 ok(!strcmp(pUsage->rgpszUsageIdentifier[i], keyUsages[i]),
1569 "Expected %s, got %s\n", keyUsages[i],
1570 pUsage->rgpszUsageIdentifier[i]);
1571 HeapFree(GetProcessHeap(), 0, buf);
1574 CertFreeCertificateContext(context);
1578 static void testCompareCertName(void)
1580 static BYTE bogus[] = { 1, 2, 3, 4 };
1581 static BYTE bogusPrime[] = { 0, 1, 2, 3, 4 };
1582 static BYTE emptyPrime[] = { 0x30, 0x00, 0x01 };
1584 CERT_NAME_BLOB blob1, blob2;
1587 ret = CertCompareCertificateName(0, NULL, NULL);
1589 /* An empty name checks against itself.. */
1590 blob1.pbData = emptyCert;
1591 blob1.cbData = sizeof(emptyCert);
1592 ret = CertCompareCertificateName(0, &blob1, &blob1);
1593 ok(ret, "CertCompareCertificateName failed: %08x\n", GetLastError());
1594 /* It doesn't have to be a valid encoded name.. */
1595 blob1.pbData = bogus;
1596 blob1.cbData = sizeof(bogus);
1597 ret = CertCompareCertificateName(0, &blob1, &blob1);
1598 ok(ret, "CertCompareCertificateName failed: %08x\n", GetLastError());
1599 /* Leading zeroes matter.. */
1600 blob2.pbData = bogusPrime;
1601 blob2.cbData = sizeof(bogusPrime);
1602 ret = CertCompareCertificateName(0, &blob1, &blob2);
1603 ok(!ret, "Expected failure\n");
1604 /* As do trailing extra bytes. */
1605 blob2.pbData = emptyPrime;
1606 blob2.cbData = sizeof(emptyPrime);
1607 ret = CertCompareCertificateName(0, &blob1, &blob2);
1608 ok(!ret, "Expected failure\n");
1611 static BYTE int1[] = { 0x88, 0xff, 0xff, 0xff };
1612 static BYTE int2[] = { 0x88, 0xff };
1613 static BYTE int3[] = { 0x23, 0xff };
1614 static BYTE int4[] = { 0x7f, 0x00 };
1615 static BYTE int5[] = { 0x7f };
1616 static BYTE int6[] = { 0x80, 0x00, 0x00, 0x00 };
1617 static BYTE int7[] = { 0x80, 0x00 };
1619 static struct IntBlobTest
1621 CRYPT_INTEGER_BLOB blob1;
1622 CRYPT_INTEGER_BLOB blob2;
1625 { { sizeof(int1), int1 }, { sizeof(int2), int2 }, TRUE },
1626 { { sizeof(int3), int3 }, { sizeof(int3), int3 }, TRUE },
1627 { { sizeof(int4), int4 }, { sizeof(int5), int5 }, TRUE },
1628 { { sizeof(int6), int6 }, { sizeof(int7), int7 }, TRUE },
1629 { { sizeof(int1), int1 }, { sizeof(int7), int7 }, FALSE },
1632 static void testCompareIntegerBlob(void)
1637 for (i = 0; i < sizeof(intBlobs) / sizeof(intBlobs[0]); i++)
1639 ret = CertCompareIntegerBlob(&intBlobs[i].blob1, &intBlobs[i].blob2);
1640 ok(ret == intBlobs[i].areEqual,
1641 "%d: expected blobs %s compare\n", i, intBlobs[i].areEqual ?
1646 static void testComparePublicKeyInfo(void)
1649 CERT_PUBLIC_KEY_INFO info1 = { { 0 } }, info2 = { { 0 } };
1650 static CHAR oid_rsa_rsa[] = szOID_RSA_RSA;
1651 static CHAR oid_rsa_sha1rsa[] = szOID_RSA_SHA1RSA;
1652 static CHAR oid_x957_dsa[] = szOID_X957_DSA;
1653 static BYTE bits1[] = { 1, 0 };
1654 static BYTE bits2[] = { 0 };
1655 static BYTE bits3[] = { 1 };
1658 ret = CertComparePublicKeyInfo(0, NULL, NULL);
1660 /* Empty public keys compare */
1661 ret = CertComparePublicKeyInfo(0, &info1, &info2);
1662 ok(ret, "CertComparePublicKeyInfo failed: %08x\n", GetLastError());
1663 /* Different OIDs appear to compare */
1664 info1.Algorithm.pszObjId = oid_rsa_rsa;
1665 info2.Algorithm.pszObjId = oid_rsa_sha1rsa;
1666 ret = CertComparePublicKeyInfo(0, &info1, &info2);
1667 ok(ret, "CertComparePublicKeyInfo failed: %08x\n", GetLastError());
1668 info2.Algorithm.pszObjId = oid_x957_dsa;
1669 ret = CertComparePublicKeyInfo(0, &info1, &info2);
1670 ok(ret, "CertComparePublicKeyInfo failed: %08x\n", GetLastError());
1671 info1.PublicKey.cbData = sizeof(bits1);
1672 info1.PublicKey.pbData = bits1;
1673 info1.PublicKey.cUnusedBits = 0;
1674 info2.PublicKey.cbData = sizeof(bits1);
1675 info2.PublicKey.pbData = bits1;
1676 info2.PublicKey.cUnusedBits = 0;
1677 ret = CertComparePublicKeyInfo(0, &info1, &info2);
1678 ok(ret, "CertComparePublicKeyInfo failed: %08x\n", GetLastError());
1679 /* Even though they compare in their used bits, these do not compare */
1680 info1.PublicKey.cbData = sizeof(bits2);
1681 info1.PublicKey.pbData = bits2;
1682 info1.PublicKey.cUnusedBits = 0;
1683 info2.PublicKey.cbData = sizeof(bits3);
1684 info2.PublicKey.pbData = bits3;
1685 info2.PublicKey.cUnusedBits = 1;
1686 ret = CertComparePublicKeyInfo(0, &info1, &info2);
1687 /* Simple (non-comparing) case */
1688 ok(!ret, "Expected keys not to compare\n");
1689 info2.PublicKey.cbData = sizeof(bits1);
1690 info2.PublicKey.pbData = bits1;
1691 info2.PublicKey.cUnusedBits = 0;
1692 ret = CertComparePublicKeyInfo(0, &info1, &info2);
1693 ok(!ret, "Expected keys not to compare\n");
1696 static void testHashPublicKeyInfo(void)
1699 CERT_PUBLIC_KEY_INFO info = { { 0 } };
1703 ret = CryptHashPublicKeyInfo(0, 0, 0, 0, NULL, NULL, NULL);
1704 ret = CryptHashPublicKeyInfo(0, 0, 0, 0, &info, NULL, NULL);
1706 ret = CryptHashPublicKeyInfo(0, 0, 0, 0, NULL, NULL, &len);
1707 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
1708 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
1709 ret = CryptHashPublicKeyInfo(0, 0, 0, X509_ASN_ENCODING, NULL, NULL, &len);
1710 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
1711 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
1712 ret = CryptHashPublicKeyInfo(0, 0, 0, X509_ASN_ENCODING, &info, NULL, &len);
1713 ok(ret, "CryptHashPublicKeyInfo failed: %08x\n", GetLastError());
1714 ok(len == 16, "Expected hash size 16, got %d\n", len);
1717 static const BYTE emptyHash[] = { 0xb8,0x51,0x3a,0x31,0x0e,0x9f,0x40,
1718 0x36,0x9c,0x92,0x45,0x1b,0x9d,0xc8,0xf9,0xf6 };
1721 ret = CryptHashPublicKeyInfo(0, 0, 0, X509_ASN_ENCODING, &info, buf,
1723 ok(ret, "CryptHashPublicKeyInfo failed: %08x\n", GetLastError());
1724 ok(!memcmp(buf, emptyHash, len), "Unexpected hash\n");
1728 static void testCompareCert(void)
1730 CERT_INFO info1 = { 0 }, info2 = { 0 };
1734 ret = CertCompareCertificate(X509_ASN_ENCODING, NULL, NULL);
1737 /* Certs with the same issuer and serial number are equal, even if they
1738 * differ in other respects (like subject).
1740 info1.SerialNumber.pbData = serialNum;
1741 info1.SerialNumber.cbData = sizeof(serialNum);
1742 info1.Issuer.pbData = subjectName;
1743 info1.Issuer.cbData = sizeof(subjectName);
1744 info1.Subject.pbData = subjectName2;
1745 info1.Subject.cbData = sizeof(subjectName2);
1746 info2.SerialNumber.pbData = serialNum;
1747 info2.SerialNumber.cbData = sizeof(serialNum);
1748 info2.Issuer.pbData = subjectName;
1749 info2.Issuer.cbData = sizeof(subjectName);
1750 info2.Subject.pbData = subjectName;
1751 info2.Subject.cbData = sizeof(subjectName);
1752 ret = CertCompareCertificate(X509_ASN_ENCODING, &info1, &info2);
1753 ok(ret, "Expected certs to be equal\n");
1755 info2.Issuer.pbData = subjectName2;
1756 info2.Issuer.cbData = sizeof(subjectName2);
1757 ret = CertCompareCertificate(X509_ASN_ENCODING, &info1, &info2);
1758 ok(!ret, "Expected certs not to be equal\n");
1761 static void testVerifySubjectCert(void)
1765 PCCERT_CONTEXT context1, context2;
1768 ret = CertVerifySubjectCertificateContext(NULL, NULL, NULL);
1771 ret = CertVerifySubjectCertificateContext(NULL, NULL, &flags);
1772 ok(ret, "CertVerifySubjectCertificateContext failed; %08x\n",
1774 flags = CERT_STORE_NO_CRL_FLAG;
1775 ret = CertVerifySubjectCertificateContext(NULL, NULL, &flags);
1776 ok(!ret && GetLastError() == E_INVALIDARG,
1777 "Expected E_INVALIDARG, got %08x\n", GetLastError());
1780 context1 = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert,
1782 ret = CertVerifySubjectCertificateContext(NULL, context1, &flags);
1783 ok(ret, "CertVerifySubjectCertificateContext failed; %08x\n",
1785 ret = CertVerifySubjectCertificateContext(context1, NULL, &flags);
1786 ok(ret, "CertVerifySubjectCertificateContext failed; %08x\n",
1788 ret = CertVerifySubjectCertificateContext(context1, context1, &flags);
1789 ok(ret, "CertVerifySubjectCertificateContext failed; %08x\n",
1792 context2 = CertCreateCertificateContext(X509_ASN_ENCODING,
1793 bigCertWithDifferentSubject, sizeof(bigCertWithDifferentSubject));
1794 SetLastError(0xdeadbeef);
1795 ret = CertVerifySubjectCertificateContext(context1, context2, &flags);
1796 ok(ret, "CertVerifySubjectCertificateContext failed; %08x\n",
1798 flags = CERT_STORE_REVOCATION_FLAG;
1799 ret = CertVerifySubjectCertificateContext(context1, context2, &flags);
1800 ok(ret, "CertVerifySubjectCertificateContext failed; %08x\n",
1802 ok(flags == (CERT_STORE_REVOCATION_FLAG | CERT_STORE_NO_CRL_FLAG),
1803 "Expected CERT_STORE_REVOCATION_FLAG | CERT_STORE_NO_CRL_FLAG, got %08x\n",
1805 flags = CERT_STORE_SIGNATURE_FLAG;
1806 ret = CertVerifySubjectCertificateContext(context1, context2, &flags);
1807 ok(ret, "CertVerifySubjectCertificateContext failed; %08x\n",
1809 ok(flags == CERT_STORE_SIGNATURE_FLAG,
1810 "Expected CERT_STORE_SIGNATURE_FLAG, got %08x\n", flags);
1811 CertFreeCertificateContext(context2);
1813 CertFreeCertificateContext(context1);
1816 static BYTE privKey[] = {
1817 0x07, 0x02, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x52, 0x53, 0x41, 0x32, 0x00,
1818 0x02, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x79, 0x10, 0x1c, 0xd0, 0x6b, 0x10,
1819 0x18, 0x30, 0x94, 0x61, 0xdc, 0x0e, 0xcb, 0x96, 0x4e, 0x21, 0x3f, 0x79, 0xcd,
1820 0xa9, 0x17, 0x62, 0xbc, 0xbb, 0x61, 0x4c, 0xe0, 0x75, 0x38, 0x6c, 0xf3, 0xde,
1821 0x60, 0x86, 0x03, 0x97, 0x65, 0xeb, 0x1e, 0x6b, 0xdb, 0x53, 0x85, 0xad, 0x68,
1822 0x21, 0xf1, 0x5d, 0xe7, 0x1f, 0xe6, 0x53, 0xb4, 0xbb, 0x59, 0x3e, 0x14, 0x27,
1823 0xb1, 0x83, 0xa7, 0x3a, 0x54, 0xe2, 0x8f, 0x65, 0x8e, 0x6a, 0x4a, 0xcf, 0x3b,
1824 0x1f, 0x65, 0xff, 0xfe, 0xf1, 0x31, 0x3a, 0x37, 0x7a, 0x8b, 0xcb, 0xc6, 0xd4,
1825 0x98, 0x50, 0x36, 0x67, 0xe4, 0xa1, 0xe8, 0x7e, 0x8a, 0xc5, 0x23, 0xf2, 0x77,
1826 0xf5, 0x37, 0x61, 0x49, 0x72, 0x59, 0xe8, 0x3d, 0xf7, 0x60, 0xb2, 0x77, 0xca,
1827 0x78, 0x54, 0x6d, 0x65, 0x9e, 0x03, 0x97, 0x1b, 0x61, 0xbd, 0x0c, 0xd8, 0x06,
1828 0x63, 0xe2, 0xc5, 0x48, 0xef, 0xb3, 0xe2, 0x6e, 0x98, 0x7d, 0xbd, 0x4e, 0x72,
1829 0x91, 0xdb, 0x31, 0x57, 0xe3, 0x65, 0x3a, 0x49, 0xca, 0xec, 0xd2, 0x02, 0x4e,
1830 0x22, 0x7e, 0x72, 0x8e, 0xf9, 0x79, 0x84, 0x82, 0xdf, 0x7b, 0x92, 0x2d, 0xaf,
1831 0xc9, 0xe4, 0x33, 0xef, 0x89, 0x5c, 0x66, 0x99, 0xd8, 0x80, 0x81, 0x47, 0x2b,
1832 0xb1, 0x66, 0x02, 0x84, 0x59, 0x7b, 0xc3, 0xbe, 0x98, 0x45, 0x4a, 0x3d, 0xdd,
1833 0xea, 0x2b, 0xdf, 0x4e, 0xb4, 0x24, 0x6b, 0xec, 0xe7, 0xd9, 0x0c, 0x45, 0xb8,
1834 0xbe, 0xca, 0x69, 0x37, 0x92, 0x4c, 0x38, 0x6b, 0x96, 0x6d, 0xcd, 0x86, 0x67,
1835 0x5c, 0xea, 0x54, 0x94, 0xa4, 0xca, 0xa4, 0x02, 0xa5, 0x21, 0x4d, 0xae, 0x40,
1836 0x8f, 0x9d, 0x51, 0x83, 0xf2, 0x3f, 0x33, 0xc1, 0x72, 0xb4, 0x1d, 0x94, 0x6e,
1837 0x7d, 0xe4, 0x27, 0x3f, 0xea, 0xff, 0xe5, 0x9b, 0xa7, 0x5e, 0x55, 0x8e, 0x0d,
1838 0x69, 0x1c, 0x7a, 0xff, 0x81, 0x9d, 0x53, 0x52, 0x97, 0x9a, 0x76, 0x79, 0xda,
1839 0x93, 0x32, 0x16, 0xec, 0x69, 0x51, 0x1a, 0x4e, 0xc3, 0xf1, 0x72, 0x80, 0x78,
1840 0x5e, 0x66, 0x4a, 0x8d, 0x85, 0x2f, 0x3f, 0xb2, 0xa7 };
1842 static const BYTE selfSignedCert[] = {
1843 0x30, 0x82, 0x01, 0x1f, 0x30, 0x81, 0xce, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02,
1844 0x10, 0xeb, 0x0d, 0x57, 0x2a, 0x9c, 0x09, 0xba, 0xa4, 0x4a, 0xb7, 0x25, 0x49,
1845 0xd9, 0x3e, 0xb5, 0x73, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1d,
1846 0x05, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03,
1847 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30,
1848 0x1e, 0x17, 0x0d, 0x30, 0x36, 0x30, 0x36, 0x32, 0x39, 0x30, 0x35, 0x30, 0x30,
1849 0x34, 0x36, 0x5a, 0x17, 0x0d, 0x30, 0x37, 0x30, 0x36, 0x32, 0x39, 0x31, 0x31,
1850 0x30, 0x30, 0x34, 0x36, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03,
1851 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e,
1852 0x67, 0x00, 0x30, 0x5c, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
1853 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x4b, 0x00, 0x30, 0x48, 0x02, 0x41,
1854 0x00, 0xe2, 0x54, 0x3a, 0xa7, 0x83, 0xb1, 0x27, 0x14, 0x3e, 0x59, 0xbb, 0xb4,
1855 0x53, 0xe6, 0x1f, 0xe7, 0x5d, 0xf1, 0x21, 0x68, 0xad, 0x85, 0x53, 0xdb, 0x6b,
1856 0x1e, 0xeb, 0x65, 0x97, 0x03, 0x86, 0x60, 0xde, 0xf3, 0x6c, 0x38, 0x75, 0xe0,
1857 0x4c, 0x61, 0xbb, 0xbc, 0x62, 0x17, 0xa9, 0xcd, 0x79, 0x3f, 0x21, 0x4e, 0x96,
1858 0xcb, 0x0e, 0xdc, 0x61, 0x94, 0x30, 0x18, 0x10, 0x6b, 0xd0, 0x1c, 0x10, 0x79,
1859 0x02, 0x03, 0x01, 0x00, 0x01, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02,
1860 0x1d, 0x05, 0x00, 0x03, 0x41, 0x00, 0x25, 0x90, 0x53, 0x34, 0xd9, 0x56, 0x41,
1861 0x5e, 0xdb, 0x7e, 0x01, 0x36, 0xec, 0x27, 0x61, 0x5e, 0xb7, 0x4d, 0x90, 0x66,
1862 0xa2, 0xe1, 0x9d, 0x58, 0x76, 0xd4, 0x9c, 0xba, 0x2c, 0x84, 0xc6, 0x83, 0x7a,
1863 0x22, 0x0d, 0x03, 0x69, 0x32, 0x1a, 0x6d, 0xcb, 0x0c, 0x15, 0xb3, 0x6b, 0xc7,
1864 0x0a, 0x8c, 0xb4, 0x5c, 0x34, 0x78, 0xe0, 0x3c, 0x9c, 0xe9, 0xf3, 0x30, 0x9f,
1865 0xa8, 0x76, 0x57, 0x92, 0x36 };
1867 static const BYTE exportedPublicKeyBlob[] = {
1868 0x06,0x02,0x00,0x00,0x00,0xa4,0x00,0x00,0x52,0x53,0x41,0x31,0x00,0x02,0x00,0x00,
1869 0x01,0x00,0x01,0x00,0x79,0x10,0x1c,0xd0,0x6b,0x10,0x18,0x30,0x94,0x61,0xdc,0x0e,
1870 0xcb,0x96,0x4e,0x21,0x3f,0x79,0xcd,0xa9,0x17,0x62,0xbc,0xbb,0x61,0x4c,0xe0,0x75,
1871 0x38,0x6c,0xf3,0xde,0x60,0x86,0x03,0x97,0x65,0xeb,0x1e,0x6b,0xdb,0x53,0x85,0xad,
1872 0x68,0x21,0xf1,0x5d,0xe7,0x1f,0xe6,0x53,0xb4,0xbb,0x59,0x3e,0x14,0x27,0xb1,0x83,
1873 0xa7,0x3a,0x54,0xe2 };
1875 static const BYTE asnEncodedPublicKey[] = {
1876 0x30,0x48,0x02,0x41,0x00,0xe2,0x54,0x3a,0xa7,0x83,0xb1,0x27,0x14,0x3e,0x59,0xbb,
1877 0xb4,0x53,0xe6,0x1f,0xe7,0x5d,0xf1,0x21,0x68,0xad,0x85,0x53,0xdb,0x6b,0x1e,0xeb,
1878 0x65,0x97,0x03,0x86,0x60,0xde,0xf3,0x6c,0x38,0x75,0xe0,0x4c,0x61,0xbb,0xbc,0x62,
1879 0x17,0xa9,0xcd,0x79,0x3f,0x21,0x4e,0x96,0xcb,0x0e,0xdc,0x61,0x94,0x30,0x18,0x10,
1880 0x6b,0xd0,0x1c,0x10,0x79,0x02,0x03,0x01,0x00,0x01 };
1882 static void testAcquireCertPrivateKey(void)
1885 PCCERT_CONTEXT cert;
1887 DWORD size, keySpec;
1889 CRYPT_KEY_PROV_INFO keyProvInfo;
1891 WCHAR ms_def_prov_w[MAX_PATH];
1893 lstrcpyW(ms_def_prov_w, MS_DEF_PROV_W);
1895 keyProvInfo.pwszContainerName = cspNameW;
1896 keyProvInfo.pwszProvName = ms_def_prov_w;
1897 keyProvInfo.dwProvType = PROV_RSA_FULL;
1898 keyProvInfo.dwFlags = 0;
1899 keyProvInfo.cProvParam = 0;
1900 keyProvInfo.rgProvParam = NULL;
1901 keyProvInfo.dwKeySpec = AT_SIGNATURE;
1903 CryptAcquireContextW(NULL, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
1904 CRYPT_DELETEKEYSET);
1906 cert = CertCreateCertificateContext(X509_ASN_ENCODING, selfSignedCert,
1907 sizeof(selfSignedCert));
1910 ret = CryptAcquireCertificatePrivateKey(NULL, 0, NULL, NULL, NULL, NULL);
1911 ret = CryptAcquireCertificatePrivateKey(NULL, 0, NULL, NULL, NULL,
1913 ret = CryptAcquireCertificatePrivateKey(NULL, 0, NULL, NULL, &keySpec,
1915 ret = CryptAcquireCertificatePrivateKey(NULL, 0, NULL, &csp, NULL, NULL);
1916 ret = CryptAcquireCertificatePrivateKey(NULL, 0, NULL, &csp, &keySpec,
1918 ret = CryptAcquireCertificatePrivateKey(cert, 0, NULL, NULL, NULL, NULL);
1921 /* Missing private key */
1922 ret = CryptAcquireCertificatePrivateKey(cert, 0, NULL, &csp, NULL, NULL);
1923 ok(!ret && GetLastError() == CRYPT_E_NO_KEY_PROPERTY,
1924 "Expected CRYPT_E_NO_KEY_PROPERTY, got %08x\n", GetLastError());
1925 ret = CryptAcquireCertificatePrivateKey(cert, 0, NULL, &csp, &keySpec,
1927 ok(!ret && GetLastError() == CRYPT_E_NO_KEY_PROPERTY,
1928 "Expected CRYPT_E_NO_KEY_PROPERTY, got %08x\n", GetLastError());
1929 CertSetCertificateContextProperty(cert, CERT_KEY_PROV_INFO_PROP_ID, 0,
1931 ret = CryptAcquireCertificatePrivateKey(cert, 0, NULL, &csp, &keySpec,
1933 ok(!ret && GetLastError() == CRYPT_E_NO_KEY_PROPERTY,
1934 "Expected CRYPT_E_NO_KEY_PROPERTY, got %08x\n", GetLastError());
1936 CryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
1938 ret = CryptImportKey(csp, privKey, sizeof(privKey), 0, 0, &key);
1939 ok(ret, "CryptImportKey failed: %08x\n", GetLastError());
1944 CERT_KEY_CONTEXT keyContext;
1946 /* Don't cache provider */
1947 ret = CryptAcquireCertificatePrivateKey(cert, 0, NULL, &certCSP,
1948 &keySpec, &callerFree);
1949 ok(ret, "CryptAcquireCertificatePrivateKey failed: %08x\n",
1951 ok(callerFree, "Expected callerFree to be TRUE\n");
1952 CryptReleaseContext(certCSP, 0);
1953 ret = CryptAcquireCertificatePrivateKey(cert, 0, NULL, &certCSP,
1955 ok(ret, "CryptAcquireCertificatePrivateKey failed: %08x\n",
1957 CryptReleaseContext(certCSP, 0);
1959 /* Use the key prov info's caching (there shouldn't be any) */
1960 ret = CryptAcquireCertificatePrivateKey(cert,
1961 CRYPT_ACQUIRE_USE_PROV_INFO_FLAG, NULL, &certCSP, &keySpec,
1963 ok(ret, "CryptAcquireCertificatePrivateKey failed: %08x\n",
1965 ok(callerFree, "Expected callerFree to be TRUE\n");
1966 CryptReleaseContext(certCSP, 0);
1968 /* Cache it (and check that it's cached) */
1969 ret = CryptAcquireCertificatePrivateKey(cert,
1970 CRYPT_ACQUIRE_CACHE_FLAG, NULL, &certCSP, &keySpec, &callerFree);
1971 ok(ret, "CryptAcquireCertificatePrivateKey failed: %08x\n",
1973 ok(!callerFree, "Expected callerFree to be FALSE\n");
1974 size = sizeof(keyContext);
1975 ret = CertGetCertificateContextProperty(cert, CERT_KEY_CONTEXT_PROP_ID,
1976 &keyContext, &size);
1977 ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
1980 /* Remove the cached provider */
1981 CryptReleaseContext(keyContext.hCryptProv, 0);
1982 CertSetCertificateContextProperty(cert, CERT_KEY_CONTEXT_PROP_ID, 0,
1984 /* Allow caching via the key prov info */
1985 keyProvInfo.dwFlags = CERT_SET_KEY_CONTEXT_PROP_ID;
1986 CertSetCertificateContextProperty(cert, CERT_KEY_PROV_INFO_PROP_ID, 0,
1988 /* Now use the key prov info's caching */
1989 ret = CryptAcquireCertificatePrivateKey(cert,
1990 CRYPT_ACQUIRE_USE_PROV_INFO_FLAG, NULL, &certCSP, &keySpec,
1992 ok(ret, "CryptAcquireCertificatePrivateKey failed: %08x\n",
1994 ok(!callerFree, "Expected callerFree to be FALSE\n");
1995 size = sizeof(keyContext);
1996 ret = CertGetCertificateContextProperty(cert, CERT_KEY_CONTEXT_PROP_ID,
1997 &keyContext, &size);
1998 ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
2001 CryptDestroyKey(key);
2004 /* Some sanity-checking on public key exporting */
2005 ret = CryptImportPublicKeyInfo(csp, X509_ASN_ENCODING,
2006 &cert->pCertInfo->SubjectPublicKeyInfo, &key);
2007 ok(ret, "CryptImportPublicKeyInfo failed: %08x\n", GetLastError());
2010 ret = CryptExportKey(key, 0, PUBLICKEYBLOB, 0, NULL, &size);
2011 ok(ret, "CryptExportKey failed: %08x\n", GetLastError());
2014 LPBYTE buf = HeapAlloc(GetProcessHeap(), 0, size), encodedKey;
2016 ret = CryptExportKey(key, 0, PUBLICKEYBLOB, 0, buf, &size);
2017 ok(ret, "CryptExportKey failed: %08x\n", GetLastError());
2018 ok(size == sizeof(exportedPublicKeyBlob), "Unexpected size %d\n",
2020 ok(!memcmp(buf, exportedPublicKeyBlob, size), "Unexpected value\n");
2021 ret = CryptEncodeObjectEx(X509_ASN_ENCODING, RSA_CSP_PUBLICKEYBLOB,
2022 buf, CRYPT_ENCODE_ALLOC_FLAG, NULL, &encodedKey, &size);
2023 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2026 ok(size == sizeof(asnEncodedPublicKey), "Unexpected size %d\n",
2028 ok(!memcmp(encodedKey, asnEncodedPublicKey, size),
2029 "Unexpected value\n");
2030 LocalFree(encodedKey);
2032 HeapFree(GetProcessHeap(), 0, buf);
2034 CryptDestroyKey(key);
2036 ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING,
2037 NULL, 0, NULL, NULL, &size);
2038 ok(ret, "CryptExportPublicKeyInfoEx failed: %08x\n", GetLastError());
2041 PCERT_PUBLIC_KEY_INFO info = HeapAlloc(GetProcessHeap(), 0, size);
2043 ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING,
2044 NULL, 0, NULL, info, &size);
2045 ok(ret, "CryptExportPublicKeyInfoEx failed: %08x\n", GetLastError());
2048 ok(info->PublicKey.cbData == sizeof(asnEncodedPublicKey),
2049 "Unexpected size %d\n", info->PublicKey.cbData);
2050 ok(!memcmp(info->PublicKey.pbData, asnEncodedPublicKey,
2051 info->PublicKey.cbData), "Unexpected value\n");
2053 HeapFree(GetProcessHeap(), 0, info);
2056 CryptReleaseContext(csp, 0);
2057 CryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
2058 CRYPT_DELETEKEYSET);
2060 CertFreeCertificateContext(cert);
2063 static void testGetPublicKeyLength(void)
2065 static char oid_rsa_rsa[] = szOID_RSA_RSA;
2066 static char oid_rsa_dh[] = szOID_RSA_DH;
2067 static char bogusOID[] = "1.2.3";
2069 CERT_PUBLIC_KEY_INFO info = { { 0 } };
2070 BYTE bogusKey[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
2071 BYTE key[] = { 0x30,0x0f,0x02,0x08,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
2072 0x02,0x03,0x01,0x00,0x01 };
2075 ret = CertGetPublicKeyLength(0, NULL);
2077 /* With an empty public key info */
2078 SetLastError(0xdeadbeef);
2079 ret = CertGetPublicKeyLength(0, &info);
2080 ok(ret == 0 && GetLastError() == ERROR_FILE_NOT_FOUND,
2081 "Expected length 0 and ERROR_FILE_NOT_FOUND, got length %d, %08x\n",
2082 ret, GetLastError());
2083 SetLastError(0xdeadbeef);
2084 ret = CertGetPublicKeyLength(X509_ASN_ENCODING, &info);
2085 ok(ret == 0 && GetLastError() == CRYPT_E_ASN1_EOD,
2086 "Expected length 0 and CRYPT_E_ASN1_EOD, got length %d, %08x\n",
2087 ret, GetLastError());
2088 /* With a nearly-empty public key info */
2089 info.Algorithm.pszObjId = oid_rsa_rsa;
2090 SetLastError(0xdeadbeef);
2091 ret = CertGetPublicKeyLength(0, &info);
2092 ok(ret == 0 && GetLastError() == ERROR_FILE_NOT_FOUND,
2093 "Expected length 0 and ERROR_FILE_NOT_FOUND, got length %d, %08x\n",
2094 ret, GetLastError());
2095 SetLastError(0xdeadbeef);
2096 ret = CertGetPublicKeyLength(X509_ASN_ENCODING, &info);
2097 ok(ret == 0 && GetLastError() == CRYPT_E_ASN1_EOD,
2098 "Expected length 0 and CRYPT_E_ASN1_EOD, got length %d, %08x\n",
2099 ret, GetLastError());
2100 /* With a bogus key */
2101 info.PublicKey.cbData = sizeof(bogusKey);
2102 info.PublicKey.pbData = bogusKey;
2103 SetLastError(0xdeadbeef);
2104 ret = CertGetPublicKeyLength(0, &info);
2105 ok(ret == 0 && GetLastError() == ERROR_FILE_NOT_FOUND,
2106 "Expected length 0 and ERROR_FILE_NOT_FOUND, got length %d, %08x\n",
2107 ret, GetLastError());
2108 SetLastError(0xdeadbeef);
2109 ret = CertGetPublicKeyLength(X509_ASN_ENCODING, &info);
2110 ok(ret == 0 && GetLastError() == CRYPT_E_ASN1_BADTAG,
2111 "Expected length 0 and CRYPT_E_ASN1_BADTAGTAG, got length %d, %08x\n",
2112 ret, GetLastError());
2113 /* With a believable RSA key but a bogus OID */
2114 info.Algorithm.pszObjId = bogusOID;
2115 info.PublicKey.cbData = sizeof(key);
2116 info.PublicKey.pbData = key;
2117 SetLastError(0xdeadbeef);
2118 ret = CertGetPublicKeyLength(0, &info);
2119 ok(ret == 0 && GetLastError() == ERROR_FILE_NOT_FOUND,
2120 "Expected length 0 and ERROR_FILE_NOT_FOUND, got length %d, %08x\n",
2121 ret, GetLastError());
2122 SetLastError(0xdeadbeef);
2123 ret = CertGetPublicKeyLength(X509_ASN_ENCODING, &info);
2124 ok(ret == 56, "Expected length 56, got %d\n", ret);
2125 /* An RSA key with the DH OID */
2126 info.Algorithm.pszObjId = oid_rsa_dh;
2127 SetLastError(0xdeadbeef);
2128 ret = CertGetPublicKeyLength(X509_ASN_ENCODING, &info);
2129 ok(ret == 0 && GetLastError() == CRYPT_E_ASN1_BADTAG,
2130 "Expected length 0 and CRYPT_E_ASN1_BADTAG, got length %d, %08x\n",
2131 ret, GetLastError());
2132 /* With the RSA OID */
2133 info.Algorithm.pszObjId = oid_rsa_rsa;
2134 SetLastError(0xdeadbeef);
2135 ret = CertGetPublicKeyLength(X509_ASN_ENCODING, &info);
2136 ok(ret == 56, "Expected length 56, got %d\n", ret);
2141 init_function_pointers();
2144 testCertProperties();
2147 testGetSubjectCert();
2148 testGetIssuerCert();
2150 testCryptHashCert();
2152 testSignAndEncodeCert();
2153 testCreateSelfSignCert();
2155 testCompareCertName();
2156 testCompareIntegerBlob();
2157 testComparePublicKeyInfo();
2158 testHashPublicKeyInfo();
2160 testVerifySubjectCert();
2161 testAcquireCertPrivateKey();
2162 testGetPublicKeyLength();