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];
298 memset(hash, 0, sizeof(hash));
299 memset(hashProperty, 0, sizeof(hashProperty));
301 ret = CryptHashCertificate(0, algID, 0, data, dataLen, hash, &size);
302 ok(ret, "CryptHashCertificate failed: %08x\n", GetLastError());
303 ret = CertGetCertificateContextProperty(context, propID, hashProperty,
305 ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
307 ok(!memcmp(hash, hashProperty, size), "Unexpected hash for property %d\n",
311 static WCHAR cspNameW[] = { 'W','i','n','e','C','r','y','p','t','T','e','m','p',0 };
313 static void testCertProperties(void)
315 PCCERT_CONTEXT context = CertCreateCertificateContext(X509_ASN_ENCODING,
316 bigCert, sizeof(bigCert));
317 DWORD propID, numProps, access, size;
319 BYTE hash[20] = { 0 }, hashProperty[20];
320 CRYPT_DATA_BLOB blob;
321 CERT_KEY_CONTEXT keyContext;
324 ok(context != NULL, "CertCreateCertificateContext failed: %08x\n",
330 propID = CertEnumCertificateContextProperties(NULL, 0);
336 propID = CertEnumCertificateContextProperties(context, propID);
339 } while (propID != 0);
340 ok(numProps == 0, "Expected 0 properties, got %d\n", numProps);
342 /* Tests with a NULL cert context. Prop ID 0 fails.. */
343 ret = CertSetCertificateContextProperty(NULL, 0, 0, NULL);
344 ok(!ret && GetLastError() == E_INVALIDARG,
345 "Expected E_INVALIDARG, got %08x\n", GetLastError());
346 /* while this just crashes.
347 ret = CertSetCertificateContextProperty(NULL,
348 CERT_KEY_PROV_HANDLE_PROP_ID, 0, NULL);
351 ret = CertSetCertificateContextProperty(context, 0, 0, NULL);
352 ok(!ret && GetLastError() == E_INVALIDARG,
353 "Expected E_INVALIDARG, got %08x\n", GetLastError());
354 /* Can't set the cert property directly, this crashes.
355 ret = CertSetCertificateContextProperty(context,
356 CERT_CERT_PROP_ID, 0, bigCert2);
360 ret = CertGetCertificateContextProperty(context,
361 CERT_ACCESS_STATE_PROP_ID, 0, NULL);
362 ret = CertGetCertificateContextProperty(context, CERT_HASH_PROP_ID,
364 ret = CertGetCertificateContextProperty(context, CERT_HASH_PROP_ID,
369 ret = CertGetCertificateContextProperty(context,
370 CERT_KEY_PROV_INFO_PROP_ID, NULL, &size);
371 ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
372 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
373 /* And, an implicit property */
374 size = sizeof(access);
375 ret = CertGetCertificateContextProperty(context,
376 CERT_ACCESS_STATE_PROP_ID, &access, &size);
377 ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
379 ok(!(access & CERT_ACCESS_STATE_WRITE_PERSIST_FLAG),
380 "Didn't expect a persisted cert\n");
381 /* Trying to set this "read only" property crashes.
382 access |= CERT_ACCESS_STATE_WRITE_PERSIST_FLAG;
383 ret = CertSetCertificateContextProperty(context,
384 CERT_ACCESS_STATE_PROP_ID, 0, &access);
387 /* Can I set the hash to an invalid hash? */
389 blob.cbData = sizeof(hash);
390 ret = CertSetCertificateContextProperty(context, CERT_HASH_PROP_ID, 0,
392 ok(ret, "CertSetCertificateContextProperty failed: %08x\n",
394 size = sizeof(hashProperty);
395 ret = CertGetCertificateContextProperty(context, CERT_HASH_PROP_ID,
396 hashProperty, &size);
397 ok(!memcmp(hashProperty, hash, sizeof(hash)), "Unexpected hash\n");
398 /* Delete the (bogus) hash, and get the real one */
399 ret = CertSetCertificateContextProperty(context, CERT_HASH_PROP_ID, 0,
401 ok(ret, "CertSetCertificateContextProperty failed: %08x\n",
403 checkHash(bigCert, sizeof(bigCert), CALG_SHA1, context,
406 /* Now that the hash property is set, we should get one property when
412 propID = CertEnumCertificateContextProperties(context, propID);
415 } while (propID != 0);
416 ok(numProps == 1, "Expected 1 properties, got %d\n", numProps);
418 /* Check a few other implicit properties */
419 checkHash(bigCert, sizeof(bigCert), CALG_MD5, context,
420 CERT_MD5_HASH_PROP_ID);
422 context->pCertInfo->Subject.pbData,
423 context->pCertInfo->Subject.cbData,
424 CALG_MD5, context, CERT_SUBJECT_NAME_MD5_HASH_PROP_ID);
426 context->pCertInfo->SubjectPublicKeyInfo.PublicKey.pbData,
427 context->pCertInfo->SubjectPublicKeyInfo.PublicKey.cbData,
428 CALG_MD5, context, CERT_SUBJECT_PUBLIC_KEY_MD5_HASH_PROP_ID);
430 /* Test key identifiers and handles and such */
432 ret = CertGetCertificateContextProperty(context,
433 CERT_KEY_IDENTIFIER_PROP_ID, NULL, &size);
434 ok(!ret && GetLastError() == ERROR_INVALID_DATA,
435 "Expected ERROR_INVALID_DATA, got %08x\n", GetLastError());
436 size = sizeof(CERT_KEY_CONTEXT);
437 ret = CertGetCertificateContextProperty(context,
438 CERT_KEY_IDENTIFIER_PROP_ID, NULL, &size);
439 ok(!ret && GetLastError() == ERROR_INVALID_DATA,
440 "Expected ERROR_INVALID_DATA, got %08x\n", GetLastError());
441 ret = CertGetCertificateContextProperty(context,
442 CERT_KEY_IDENTIFIER_PROP_ID, &keyContext, &size);
443 ok(!ret && GetLastError() == ERROR_INVALID_DATA,
444 "Expected ERROR_INVALID_DATA, got %08x\n", GetLastError());
445 /* Key context with an invalid size */
446 keyContext.cbSize = 0;
447 ret = CertSetCertificateContextProperty(context,
448 CERT_KEY_IDENTIFIER_PROP_ID, 0, &keyContext);
449 ok(ret, "CertSetCertificateContextProperty failed: %08x\n",
451 size = sizeof(keyContext);
452 ret = CertGetCertificateContextProperty(context,
453 CERT_KEY_IDENTIFIER_PROP_ID, &keyContext, &size);
454 ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
456 keyContext.cbSize = sizeof(keyContext);
457 keyContext.hCryptProv = 0;
458 keyContext.dwKeySpec = AT_SIGNATURE;
460 ret = CertSetCertificateContextProperty(context,
461 CERT_KEY_IDENTIFIER_PROP_ID, 0, &keyContext);
462 ret = CertSetCertificateContextProperty(context,
463 CERT_KEY_IDENTIFIER_PROP_ID, CERT_STORE_NO_CRYPT_RELEASE_FLAG,
466 ret = CryptAcquireContextW(&csp, cspNameW,
467 MS_DEF_PROV_W, PROV_RSA_FULL, CRYPT_NEWKEYSET);
468 ok(ret, "CryptAcquireContextW failed: %08x\n", GetLastError());
469 keyContext.hCryptProv = csp;
470 ret = CertSetCertificateContextProperty(context,
471 CERT_KEY_CONTEXT_PROP_ID, 0, &keyContext);
472 ok(ret, "CertSetCertificateContextProperty failed: %08x\n",
474 /* Now that that's set, the key prov handle property is also gettable.
476 size = sizeof(DWORD);
477 ret = CertGetCertificateContextProperty(context,
478 CERT_KEY_PROV_HANDLE_PROP_ID, &keyContext.hCryptProv, &size);
479 ok(ret, "Expected to get the CERT_KEY_PROV_HANDLE_PROP_ID, got %08x\n",
481 /* Remove the key prov handle property.. */
482 ret = CertSetCertificateContextProperty(context,
483 CERT_KEY_PROV_HANDLE_PROP_ID, 0, NULL);
484 ok(ret, "CertSetCertificateContextProperty failed: %08x\n",
486 /* and the key context's CSP is set to NULL. */
487 size = sizeof(keyContext);
488 ret = CertGetCertificateContextProperty(context,
489 CERT_KEY_CONTEXT_PROP_ID, &keyContext, &size);
490 ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
492 ok(keyContext.hCryptProv == 0, "Expected no hCryptProv\n");
494 CryptReleaseContext(csp, 0);
496 CertFreeCertificateContext(context);
499 static void testDupCert(void)
502 PCCERT_CONTEXT context, dupContext;
505 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
506 CERT_STORE_CREATE_NEW_FLAG, NULL);
507 ok(store != NULL, "CertOpenStore failed: %d\n", GetLastError());
511 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
512 bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, &context);
513 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
515 ok(context != NULL, "Expected a valid cert context\n");
518 ok(context->cbCertEncoded == sizeof(bigCert),
519 "Wrong cert size %d\n", context->cbCertEncoded);
520 ok(!memcmp(context->pbCertEncoded, bigCert, sizeof(bigCert)),
521 "Unexpected encoded cert in context\n");
522 ok(context->hCertStore == store, "Unexpected store\n");
524 dupContext = CertDuplicateCertificateContext(context);
525 ok(dupContext != NULL, "Expected valid duplicate\n");
526 /* Not only is it a duplicate, it's identical: the address is the
529 ok(dupContext == context, "Expected identical context addresses\n");
530 CertFreeCertificateContext(dupContext);
531 CertFreeCertificateContext(context);
533 CertCloseStore(store, 0);
536 static void testFindCert(void)
539 PCCERT_CONTEXT context = NULL;
541 CERT_INFO certInfo = { 0 };
542 CRYPT_HASH_BLOB blob;
544 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
545 CERT_STORE_CREATE_NEW_FLAG, NULL);
546 ok(store != NULL, "CertOpenStore failed: %d\n", GetLastError());
550 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
551 bigCert, sizeof(bigCert), CERT_STORE_ADD_NEW, NULL);
552 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
554 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
555 bigCert2, sizeof(bigCert2), CERT_STORE_ADD_NEW, NULL);
556 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
558 /* This has the same name as bigCert */
559 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
560 certWithUsage, sizeof(certWithUsage), CERT_STORE_ADD_NEW, NULL);
561 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
565 context = CertFindCertificateInStore(NULL, 0, 0, 0, NULL, NULL);
568 /* Check first cert's there, by issuer */
569 certInfo.Subject.pbData = subjectName;
570 certInfo.Subject.cbData = sizeof(subjectName);
571 certInfo.SerialNumber.pbData = serialNum;
572 certInfo.SerialNumber.cbData = sizeof(serialNum);
573 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
574 CERT_FIND_ISSUER_NAME, &certInfo.Subject, NULL);
575 ok(context != NULL, "CertFindCertificateInStore failed: %08x\n",
579 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
580 CERT_FIND_ISSUER_NAME, &certInfo.Subject, context);
581 ok(context != NULL, "Expected more than one cert\n");
584 context = CertFindCertificateInStore(store, X509_ASN_ENCODING,
585 0, CERT_FIND_ISSUER_NAME, &certInfo.Subject, context);
586 ok(context == NULL, "Expected precisely two certs\n");
590 /* Check second cert's there as well, by subject name */
591 certInfo.Subject.pbData = subjectName2;
592 certInfo.Subject.cbData = sizeof(subjectName2);
593 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
594 CERT_FIND_SUBJECT_NAME, &certInfo.Subject, NULL);
595 ok(context != NULL, "CertFindCertificateInStore failed: %08x\n",
599 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
600 CERT_FIND_SUBJECT_NAME, &certInfo.Subject, context);
601 ok(context == NULL, "Expected one cert only\n");
604 /* Strange but true: searching for the subject cert requires you to set
605 * the issuer, not the subject
607 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
608 CERT_FIND_SUBJECT_CERT, &certInfo.Subject, NULL);
609 ok(context == NULL, "Expected no certificate\n");
610 certInfo.Subject.pbData = NULL;
611 certInfo.Subject.cbData = 0;
612 certInfo.Issuer.pbData = subjectName2;
613 certInfo.Issuer.cbData = sizeof(subjectName2);
614 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
615 CERT_FIND_SUBJECT_CERT, &certInfo, NULL);
616 ok(context != NULL, "CertFindCertificateInStore failed: %08x\n",
620 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
621 CERT_FIND_SUBJECT_CERT, &certInfo.Subject, context);
622 ok(context == NULL, "Expected one cert only\n");
625 /* The nice thing about hashes, they're unique */
626 blob.pbData = bigCertHash;
627 blob.cbData = sizeof(bigCertHash);
628 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
629 CERT_FIND_SHA1_HASH, &blob, NULL);
630 ok(context != NULL, "CertFindCertificateInStore failed: %08x\n",
634 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
635 CERT_FIND_SHA1_HASH, &certInfo.Subject, context);
636 ok(context == NULL, "Expected one cert only\n");
639 CertCloseStore(store, 0);
642 static void testGetSubjectCert(void)
645 PCCERT_CONTEXT context1, context2;
646 CERT_INFO info = { 0 };
649 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
650 CERT_STORE_CREATE_NEW_FLAG, NULL);
651 ok(store != NULL, "CertOpenStore failed: %d\n", GetLastError());
655 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
656 bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL);
657 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
659 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
660 bigCert2, sizeof(bigCert2), CERT_STORE_ADD_NEW, &context1);
661 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
663 ok(context1 != NULL, "Expected a context\n");
664 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
665 certWithUsage, sizeof(certWithUsage), CERT_STORE_ADD_NEW, NULL);
666 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
669 context2 = CertGetSubjectCertificateFromStore(store, X509_ASN_ENCODING,
671 ok(!context2 && GetLastError() == E_INVALIDARG,
672 "Expected E_INVALIDARG, got %08x\n", GetLastError());
673 context2 = CertGetSubjectCertificateFromStore(store, X509_ASN_ENCODING,
675 ok(!context2 && GetLastError() == CRYPT_E_NOT_FOUND,
676 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
677 info.SerialNumber.cbData = sizeof(serialNum);
678 info.SerialNumber.pbData = serialNum;
679 context2 = CertGetSubjectCertificateFromStore(store, X509_ASN_ENCODING,
681 ok(!context2 && GetLastError() == CRYPT_E_NOT_FOUND,
682 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
683 info.Issuer.cbData = sizeof(subjectName2);
684 info.Issuer.pbData = subjectName2;
685 context2 = CertGetSubjectCertificateFromStore(store, X509_ASN_ENCODING,
688 "CertGetSubjectCertificateFromStore failed: %08x\n", GetLastError());
689 /* Not only should this find a context, but it should be the same
690 * (same address) as context1.
692 ok(context1 == context2, "Expected identical context addresses\n");
693 CertFreeCertificateContext(context2);
695 CertFreeCertificateContext(context1);
696 CertCloseStore(store, 0);
699 /* This expires in 1970 or so */
700 static const BYTE expiredCert[] = { 0x30, 0x82, 0x01, 0x33, 0x30, 0x81, 0xe2,
701 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0xc4, 0xd7, 0x7f, 0x0e, 0x6f, 0xa6,
702 0x8c, 0xaa, 0x47, 0x47, 0x40, 0xe7, 0xb7, 0x0b, 0x4a, 0x7f, 0x30, 0x09, 0x06,
703 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1d, 0x05, 0x00, 0x30, 0x1f, 0x31, 0x1d, 0x30,
704 0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63, 0x40,
705 0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63,
706 0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x36, 0x39, 0x30, 0x31, 0x30, 0x31, 0x30,
707 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x37, 0x30, 0x30, 0x31, 0x30,
708 0x31, 0x30, 0x36, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x1f, 0x31, 0x1d, 0x30,
709 0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63, 0x40,
710 0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63,
711 0x6f, 0x6d, 0x30, 0x5c, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
712 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x4b, 0x00, 0x30, 0x48, 0x02, 0x41,
713 0x00, 0xa1, 0xaf, 0x4a, 0xea, 0xa7, 0x83, 0x57, 0xc0, 0x37, 0x33, 0x7e, 0x29,
714 0x5e, 0x0d, 0xfc, 0x44, 0x74, 0x3a, 0x1d, 0xc3, 0x1b, 0x1d, 0x96, 0xed, 0x4e,
715 0xf4, 0x1b, 0x98, 0xec, 0x69, 0x1b, 0x04, 0xea, 0x25, 0xcf, 0xb3, 0x2a, 0xf5,
716 0xd9, 0x22, 0xd9, 0x8d, 0x08, 0x39, 0x81, 0xc6, 0xe0, 0x4f, 0x12, 0x37, 0x2a,
717 0x3f, 0x80, 0xa6, 0x6c, 0x67, 0x43, 0x3a, 0xdd, 0x95, 0x0c, 0xbb, 0x2f, 0x6b,
718 0x02, 0x03, 0x01, 0x00, 0x01, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02,
719 0x1d, 0x05, 0x00, 0x03, 0x41, 0x00, 0x8f, 0xa2, 0x5b, 0xd6, 0xdf, 0x34, 0xd0,
720 0xa2, 0xa7, 0x47, 0xf1, 0x13, 0x79, 0xd3, 0xf3, 0x39, 0xbd, 0x4e, 0x2b, 0xa3,
721 0xf4, 0x63, 0x37, 0xac, 0x5a, 0x0c, 0x5e, 0x4d, 0x0d, 0x54, 0x87, 0x4f, 0x31,
722 0xfb, 0xa0, 0xce, 0x8f, 0x9a, 0x2f, 0x4d, 0x48, 0xc6, 0x84, 0x8d, 0xf5, 0x70,
723 0x74, 0x17, 0xa5, 0xf3, 0x66, 0x47, 0x06, 0xd6, 0x64, 0x45, 0xbc, 0x52, 0xef,
724 0x49, 0xe5, 0xf9, 0x65, 0xf3 };
726 /* This expires in 2036 or so */
727 static const BYTE childOfExpired[] = { 0x30, 0x81, 0xcc, 0x30, 0x78, 0xa0,
728 0x03, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86,
729 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x1f, 0x31, 0x1d,
730 0x30, 0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63,
731 0x40, 0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e,
732 0x63, 0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x30, 0x36, 0x30, 0x35, 0x30, 0x35,
733 0x31, 0x37, 0x31, 0x32, 0x34, 0x39, 0x5a, 0x17, 0x0d, 0x33, 0x36, 0x30, 0x35,
734 0x30, 0x35, 0x31, 0x37, 0x31, 0x32, 0x34, 0x39, 0x5a, 0x30, 0x15, 0x31, 0x13,
735 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e,
736 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03,
737 0x01, 0x00, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
738 0x01, 0x05, 0x05, 0x00, 0x03, 0x41, 0x00, 0x20, 0x3b, 0xdb, 0x4d, 0x67, 0x50,
739 0xec, 0x73, 0x9d, 0xf9, 0x85, 0x5d, 0x18, 0xe9, 0xb4, 0x98, 0xe3, 0x31, 0xb7,
740 0x03, 0x0b, 0xc0, 0x39, 0x93, 0x56, 0x81, 0x0a, 0xfc, 0x78, 0xa8, 0x29, 0x42,
741 0x5f, 0x69, 0xfb, 0xbc, 0x5b, 0xf2, 0xa6, 0x2a, 0xbe, 0x91, 0x2c, 0xfc, 0x89,
742 0x69, 0x15, 0x18, 0x58, 0xe5, 0x02, 0x75, 0xf7, 0x2a, 0xb6, 0xa9, 0xfb, 0x47,
743 0x6a, 0x6e, 0x0a, 0x9b, 0xe9, 0xdc };
745 static void testGetIssuerCert(void)
748 PCCERT_CONTEXT parent, child;
749 DWORD flags = 0xffffffff;
750 HCERTSTORE store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
751 CERT_STORE_CREATE_NEW_FLAG, NULL);
753 ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
755 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
756 expiredCert, sizeof(expiredCert), CERT_STORE_ADD_ALWAYS, NULL);
757 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
760 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
761 childOfExpired, sizeof(childOfExpired), CERT_STORE_ADD_ALWAYS, &child);
762 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
766 parent = CertGetIssuerCertificateFromStore(NULL, NULL, NULL, NULL);
767 parent = CertGetIssuerCertificateFromStore(store, NULL, NULL, NULL);
769 parent = CertGetIssuerCertificateFromStore(NULL, NULL, NULL, &flags);
770 ok(!parent && GetLastError() == E_INVALIDARG,
771 "Expected E_INVALIDARG, got %08x\n", GetLastError());
772 parent = CertGetIssuerCertificateFromStore(store, NULL, NULL, &flags);
773 ok(!parent && GetLastError() == E_INVALIDARG,
774 "Expected E_INVALIDARG, got %08x\n", GetLastError());
775 parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
776 ok(!parent && GetLastError() == E_INVALIDARG,
777 "Expected E_INVALIDARG, got %08x\n", GetLastError());
778 /* Confusing: the caller cannot set either of the
779 * CERT_STORE_NO_*_FLAGs, as these are not checks,
782 flags = CERT_STORE_NO_CRL_FLAG | CERT_STORE_NO_ISSUER_FLAG;
783 parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
784 ok(!parent && GetLastError() == E_INVALIDARG,
785 "Expected E_INVALIDARG, got %08x\n", GetLastError());
786 /* Perform no checks */
788 parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
789 ok(parent != NULL, "CertGetIssuerCertificateFromStore failed: %08x\n",
792 CertFreeCertificateContext(parent);
793 /* Check revocation and signature only */
794 flags = CERT_STORE_REVOCATION_FLAG | CERT_STORE_SIGNATURE_FLAG;
795 parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
796 ok(parent != NULL, "CertGetIssuerCertificateFromStore failed: %08x\n",
798 /* Confusing: CERT_STORE_REVOCATION_FLAG succeeds when there is no CRL by
799 * setting CERT_STORE_NO_CRL_FLAG.
801 ok(flags == (CERT_STORE_REVOCATION_FLAG | CERT_STORE_NO_CRL_FLAG),
802 "Expected CERT_STORE_REVOCATION_FLAG | CERT_STORE_NO_CRL_FLAG, got %08x\n",
805 CertFreeCertificateContext(parent);
806 /* Now check just the time */
807 flags = CERT_STORE_TIME_VALIDITY_FLAG;
808 parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
809 ok(parent != NULL, "CertGetIssuerCertificateFromStore failed: %08x\n",
811 /* Oops: the child is not expired, so the time validity check actually
812 * succeeds, even though the signing cert is expired.
814 ok(!flags, "Expected check to succeed, got %08x\n", flags);
816 CertFreeCertificateContext(parent);
818 CertFreeCertificateContext(child);
819 CertCloseStore(store, 0);
822 static void testCryptHashCert(void)
824 static const BYTE emptyHash[] = { 0xda, 0x39, 0xa3, 0xee, 0x5e, 0x6b, 0x4b,
825 0x0d, 0x32, 0x55, 0xbf, 0xef, 0x95, 0x60, 0x18, 0x90, 0xaf, 0xd8, 0x07,
827 static const BYTE knownHash[] = { 0xae, 0x9d, 0xbf, 0x6d, 0xf5, 0x46, 0xee,
828 0x8b, 0xc5, 0x7a, 0x13, 0xba, 0xc2, 0xb1, 0x04, 0xf2, 0xbf, 0x52, 0xa8,
830 static const BYTE toHash[] = "abcdefghijklmnopqrstuvwxyz0123456789.,;!?:";
833 DWORD hashLen = sizeof(hash);
835 /* NULL buffer and nonzero length crashes
836 ret = CryptHashCertificate(0, 0, 0, NULL, size, hash, &hashLen);
837 empty hash length also crashes
838 ret = CryptHashCertificate(0, 0, 0, buf, size, hash, NULL);
840 /* Test empty hash */
841 ret = CryptHashCertificate(0, 0, 0, toHash, sizeof(toHash), NULL,
843 ok(ret, "CryptHashCertificate failed: %08x\n", GetLastError());
844 ok(hashLen == sizeof(hash), "Got unexpected size of hash %d\n", hashLen);
845 /* Test with empty buffer */
846 ret = CryptHashCertificate(0, 0, 0, NULL, 0, hash, &hashLen);
847 ok(ret, "CryptHashCertificate failed: %08x\n", GetLastError());
848 ok(!memcmp(hash, emptyHash, sizeof(emptyHash)),
849 "Unexpected hash of nothing\n");
850 /* Test a known value */
851 ret = CryptHashCertificate(0, 0, 0, toHash, sizeof(toHash), hash,
853 ok(ret, "CryptHashCertificate failed: %08x\n", GetLastError());
854 ok(!memcmp(hash, knownHash, sizeof(knownHash)), "Unexpected hash\n");
857 static void verifySig(HCRYPTPROV csp, const BYTE *toSign, size_t toSignLen,
858 const BYTE *sig, unsigned int sigLen)
861 BOOL ret = CryptCreateHash(csp, CALG_SHA1, 0, 0, &hash);
863 ok(ret, "CryptCreateHash failed: %08x\n", GetLastError());
867 DWORD mySigSize = sizeof(mySig);
869 ret = CryptHashData(hash, toSign, toSignLen, 0);
870 ok(ret, "CryptHashData failed: %08x\n", GetLastError());
871 /* use the A variant so the test can run on Win9x */
872 ret = CryptSignHashA(hash, AT_SIGNATURE, NULL, 0, mySig, &mySigSize);
873 ok(ret, "CryptSignHash failed: %08x\n", GetLastError());
876 ok(mySigSize == sigLen, "Expected sig length %d, got %d\n",
878 ok(!memcmp(mySig, sig, sigLen), "Unexpected signature\n");
880 CryptDestroyHash(hash);
884 /* Tests signing the certificate described by toBeSigned with the CSP passed in,
885 * using the algorithm with OID sigOID. The CSP is assumed to be empty, and a
886 * keyset named AT_SIGNATURE will be added to it. The signing key will be
887 * stored in *key, and the signature will be stored in sig. sigLen should be
890 static void testSignCert(HCRYPTPROV csp, const CRYPT_DATA_BLOB *toBeSigned,
891 LPCSTR sigOID, HCRYPTKEY *key, BYTE *sig, DWORD *sigLen)
895 CRYPT_ALGORITHM_IDENTIFIER algoID = { NULL, { 0, NULL } };
898 ret = CryptSignCertificate(0, 0, 0, NULL, 0, NULL, NULL, NULL, NULL);
899 ret = CryptSignCertificate(0, 0, 0, NULL, 0, NULL, NULL, NULL, &size);
900 ret = CryptSignCertificate(0, 0, 0, toBeSigned->pbData, toBeSigned->cbData,
901 NULL, NULL, NULL, &size);
903 ret = CryptSignCertificate(0, 0, 0, toBeSigned->pbData, toBeSigned->cbData,
904 &algoID, NULL, NULL, &size);
905 ok(!ret && GetLastError() == NTE_BAD_ALGID,
906 "Expected NTE_BAD_ALGID, got %08x\n", GetLastError());
907 algoID.pszObjId = (LPSTR)sigOID;
908 ret = CryptSignCertificate(0, 0, 0, toBeSigned->pbData, toBeSigned->cbData,
909 &algoID, NULL, NULL, &size);
910 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
911 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
912 ret = CryptSignCertificate(0, AT_SIGNATURE, 0, toBeSigned->pbData,
913 toBeSigned->cbData, &algoID, NULL, NULL, &size);
914 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
915 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
917 /* No keys exist in the new CSP yet.. */
918 ret = CryptSignCertificate(csp, AT_SIGNATURE, 0, toBeSigned->pbData,
919 toBeSigned->cbData, &algoID, NULL, NULL, &size);
920 ok(!ret && (GetLastError() == NTE_BAD_KEYSET || GetLastError() ==
921 NTE_NO_KEY), "Expected NTE_BAD_KEYSET or NTE_NO_KEY, got %08x\n",
923 ret = CryptGenKey(csp, AT_SIGNATURE, 0, key);
924 ok(ret, "CryptGenKey failed: %08x\n", GetLastError());
927 ret = CryptSignCertificate(csp, AT_SIGNATURE, 0, toBeSigned->pbData,
928 toBeSigned->cbData, &algoID, NULL, NULL, &size);
929 ok(ret, "CryptSignCertificate failed: %08x\n", GetLastError());
930 ok(size <= *sigLen, "Expected size <= %d, got %d\n", *sigLen, size);
933 ret = CryptSignCertificate(csp, AT_SIGNATURE, 0, toBeSigned->pbData,
934 toBeSigned->cbData, &algoID, NULL, sig, &size);
935 ok(ret, "CryptSignCertificate failed: %08x\n", GetLastError());
939 verifySig(csp, toBeSigned->pbData, toBeSigned->cbData, sig,
946 static void testVerifyCertSig(HCRYPTPROV csp, const CRYPT_DATA_BLOB *toBeSigned,
947 LPCSTR sigOID, const BYTE *sig, DWORD sigLen)
949 CERT_SIGNED_CONTENT_INFO info;
954 if(pCryptVerifyCertificateSignatureEx) {
955 ret = pCryptVerifyCertificateSignatureEx(0, 0, 0, NULL, 0, NULL, 0, NULL);
956 ok(!ret && GetLastError() == E_INVALIDARG,
957 "Expected E_INVALIDARG, got %08x\n", GetLastError());
958 ret = pCryptVerifyCertificateSignatureEx(csp, 0, 0, NULL, 0, NULL, 0, NULL);
959 ok(!ret && GetLastError() == E_INVALIDARG,
960 "Expected E_INVALIDARG, got %08x\n", GetLastError());
961 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING, 0, NULL, 0,
963 ok(!ret && GetLastError() == E_INVALIDARG,
964 "Expected E_INVALIDARG, got %08x\n", GetLastError());
966 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
967 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, NULL, 0, NULL, 0, NULL);
970 info.ToBeSigned.cbData = toBeSigned->cbData;
971 info.ToBeSigned.pbData = toBeSigned->pbData;
972 info.SignatureAlgorithm.pszObjId = (LPSTR)sigOID;
973 info.SignatureAlgorithm.Parameters.cbData = 0;
974 info.Signature.cbData = sigLen;
975 info.Signature.pbData = (BYTE *)sig;
976 info.Signature.cUnusedBits = 0;
977 ret = CryptEncodeObjectEx(X509_ASN_ENCODING, X509_CERT, &info,
978 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&cert, &size);
979 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
982 CRYPT_DATA_BLOB certBlob = { 0, NULL };
983 PCERT_PUBLIC_KEY_INFO pubKeyInfo = NULL;
985 if(pCryptVerifyCertificateSignatureEx) {
986 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
987 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob, 0, NULL, 0, NULL);
988 ok(!ret && GetLastError() == CRYPT_E_ASN1_EOD,
989 "Expected CRYPT_E_ASN1_EOD, got %08x\n", GetLastError());
991 certBlob.pbData = (void *)0xdeadbeef;
992 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
993 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob, 0, NULL, 0, NULL);
994 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
995 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
996 certBlob.cbData = size;
997 certBlob.pbData = cert;
998 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
999 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob, 0, NULL, 0, NULL);
1000 ok(!ret && GetLastError() == E_INVALIDARG,
1001 "Expected E_INVALIDARG, got %08x\n", GetLastError());
1002 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
1003 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob,
1004 CRYPT_VERIFY_CERT_SIGN_ISSUER_NULL, NULL, 0, NULL);
1005 ok(!ret && GetLastError() == E_INVALIDARG,
1006 "Expected E_INVALIDARG, got %08x\n", GetLastError());
1008 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
1009 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob,
1010 CRYPT_VERIFY_CERT_SIGN_ISSUER_PUBKEY, NULL, 0, NULL);
1013 CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING,
1014 (LPSTR)sigOID, 0, NULL, NULL, &size);
1015 pubKeyInfo = HeapAlloc(GetProcessHeap(), 0, size);
1018 ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE,
1019 X509_ASN_ENCODING, (LPSTR)sigOID, 0, NULL, pubKeyInfo, &size);
1020 ok(ret, "CryptExportKey failed: %08x\n", GetLastError());
1021 if (ret && pCryptVerifyCertificateSignatureEx)
1023 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
1024 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob,
1025 CRYPT_VERIFY_CERT_SIGN_ISSUER_PUBKEY, pubKeyInfo, 0, NULL);
1026 ok(ret, "CryptVerifyCertificateSignatureEx failed: %08x\n",
1029 HeapFree(GetProcessHeap(), 0, pubKeyInfo);
1035 static BYTE emptyCert[] = { 0x30, 0x00 };
1037 static void testCertSigs(void)
1040 CRYPT_DATA_BLOB toBeSigned = { sizeof(emptyCert), emptyCert };
1044 DWORD sigSize = sizeof(sig);
1046 /* Just in case a previous run failed, delete this thing */
1047 CryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
1048 CRYPT_DELETEKEYSET);
1049 ret = CryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
1051 ok(ret, "CryptAcquireContext failed: %08x\n", GetLastError());
1053 testSignCert(csp, &toBeSigned, szOID_RSA_SHA1RSA, &key, sig, &sigSize);
1054 testVerifyCertSig(csp, &toBeSigned, szOID_RSA_SHA1RSA, sig, sigSize);
1056 CryptDestroyKey(key);
1057 CryptReleaseContext(csp, 0);
1058 ret = CryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
1059 CRYPT_DELETEKEYSET);
1062 static const BYTE md5SignedEmptyCert[] = {
1063 0x30,0x56,0x30,0x33,0x02,0x00,0x30,0x02,0x06,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,
1064 0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,
1065 0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x07,
1066 0x30,0x02,0x06,0x00,0x03,0x01,0x00,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,
1067 0x0d,0x02,0x05,0x05,0x00,0x03,0x11,0x00,0xfb,0x0f,0x66,0x82,0x66,0xd9,0xe5,0xf8,
1068 0xd8,0xa2,0x55,0x2b,0xe1,0xa5,0xd9,0x04 };
1069 static const BYTE md5SignedEmptyCertNoNull[] = {
1070 0x30,0x54,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,0x0a,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,
1074 0x0d,0x02,0x05,0x03,0x11,0x00,0x04,0xd9,0xa5,0xe1,0x2b,0x55,0xa2,0xd8,0xf8,0xe5,
1075 0xd9,0x66,0x82,0x66,0x0f,0xfb };
1077 static void testSignAndEncodeCert(void)
1079 static char oid_rsa_md5rsa[] = szOID_RSA_MD5RSA;
1080 static char oid_rsa_md5[] = szOID_RSA_MD5;
1083 CRYPT_ALGORITHM_IDENTIFIER algID = { 0 };
1084 CERT_INFO info = { 0 };
1087 ret = CryptSignAndEncodeCertificate(0, 0, 0, NULL, NULL, NULL, NULL, NULL,
1089 ret = CryptSignAndEncodeCertificate(0, 0, 0, NULL, NULL, NULL, NULL, NULL,
1092 ret = CryptSignAndEncodeCertificate(0, 0, 0, NULL, NULL, &algID, NULL, NULL,
1094 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
1095 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
1096 ret = CryptSignAndEncodeCertificate(0, 0, X509_ASN_ENCODING, NULL, NULL,
1097 &algID, NULL, NULL, &size);
1098 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
1099 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
1100 ret = CryptSignAndEncodeCertificate(0, 0, 0, X509_CERT_TO_BE_SIGNED, NULL,
1101 &algID, NULL, NULL, &size);
1102 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
1103 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
1104 ret = CryptSignAndEncodeCertificate(0, 0, X509_ASN_ENCODING,
1105 X509_CERT_TO_BE_SIGNED, NULL, &algID, NULL, NULL, &size);
1106 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
1107 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
1109 ret = CryptSignAndEncodeCertificate(0, 0, X509_ASN_ENCODING,
1110 X509_CERT_TO_BE_SIGNED, &info, NULL, NULL, NULL, &size);
1112 ret = CryptSignAndEncodeCertificate(0, 0, X509_ASN_ENCODING,
1113 X509_CERT_TO_BE_SIGNED, &info, &algID, NULL, NULL, &size);
1114 ok(!ret && GetLastError() == NTE_BAD_ALGID,
1115 "Expected NTE_BAD_ALGID, got %08x\n", GetLastError());
1116 algID.pszObjId = oid_rsa_md5rsa;
1117 ret = CryptSignAndEncodeCertificate(0, 0, X509_ASN_ENCODING,
1118 X509_CERT_TO_BE_SIGNED, &info, &algID, NULL, NULL, &size);
1119 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1120 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
1121 algID.pszObjId = oid_rsa_md5;
1122 ret = CryptSignAndEncodeCertificate(0, 0, X509_ASN_ENCODING,
1123 X509_CERT_TO_BE_SIGNED, &info, &algID, NULL, NULL, &size);
1124 ok(ret, "CryptSignAndEncodeCertificate failed: %08x\n", GetLastError());
1127 LPBYTE buf = HeapAlloc(GetProcessHeap(), 0, size);
1131 ret = CryptSignAndEncodeCertificate(0, 0, X509_ASN_ENCODING,
1132 X509_CERT_TO_BE_SIGNED, &info, &algID, NULL, buf, &size);
1133 ok(ret, "CryptSignAndEncodeCertificate failed: %08x\n",
1135 /* Tricky: because the NULL parameters may either be omitted or
1136 * included as an asn.1-encoded NULL (0x05,0x00), two different
1137 * values are allowed.
1139 ok(size == sizeof(md5SignedEmptyCert) ||
1140 size == sizeof(md5SignedEmptyCertNoNull), "Unexpected size %d\n",
1142 if (size == sizeof(md5SignedEmptyCert))
1143 ok(!memcmp(buf, md5SignedEmptyCert, size),
1144 "Unexpected value\n");
1145 else if (size == sizeof(md5SignedEmptyCertNoNull))
1146 ok(!memcmp(buf, md5SignedEmptyCertNoNull, size),
1147 "Unexpected value\n");
1148 HeapFree(GetProcessHeap(), 0, buf);
1153 static void testCreateSelfSignCert(void)
1155 PCCERT_CONTEXT context;
1156 CERT_NAME_BLOB name = { sizeof(subjectName), subjectName };
1162 context = CertCreateSelfSignCertificate(0, NULL, 0, NULL, NULL, NULL, NULL,
1164 * Calling this with no first parameter creates a new key container, which
1165 * lasts beyond the test, so I don't test that. Nb: the generated key
1167 context = CertCreateSelfSignCertificate(0, &name, 0, NULL, NULL, NULL, NULL,
1172 CryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
1173 CRYPT_DELETEKEYSET);
1174 ret = CryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
1176 ok(ret, "CryptAcquireContext failed: %08x\n", GetLastError());
1178 context = CertCreateSelfSignCertificate(csp, &name, 0, NULL, NULL, NULL,
1180 ok(!context && GetLastError() == NTE_NO_KEY,
1181 "Expected NTE_NO_KEY, got %08x\n", GetLastError());
1182 ret = CryptGenKey(csp, AT_SIGNATURE, 0, &key);
1183 ok(ret, "CryptGenKey failed: %08x\n", GetLastError());
1186 context = CertCreateSelfSignCertificate(csp, &name, 0, NULL, NULL, NULL,
1188 ok(context != NULL, "CertCreateSelfSignCertificate failed: %08x\n",
1193 PCRYPT_KEY_PROV_INFO info;
1195 /* The context must have a key provider info property */
1196 ret = CertGetCertificateContextProperty(context,
1197 CERT_KEY_PROV_INFO_PROP_ID, NULL, &size);
1198 ok(ret && size, "Expected non-zero key provider info\n");
1201 info = HeapAlloc(GetProcessHeap(), 0, size);
1204 ret = CertGetCertificateContextProperty(context,
1205 CERT_KEY_PROV_INFO_PROP_ID, info, &size);
1206 ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
1210 /* Sanity-check the key provider */
1211 ok(!lstrcmpW(info->pwszContainerName, cspNameW),
1212 "Unexpected key container\n");
1213 ok(!lstrcmpW(info->pwszProvName, MS_DEF_PROV_W),
1214 "Unexpected provider\n");
1215 ok(info->dwKeySpec == AT_SIGNATURE,
1216 "Expected AT_SIGNATURE, got %d\n", info->dwKeySpec);
1218 HeapFree(GetProcessHeap(), 0, info);
1222 CertFreeCertificateContext(context);
1225 CryptDestroyKey(key);
1228 CryptReleaseContext(csp, 0);
1229 ret = CryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
1230 CRYPT_DELETEKEYSET);
1233 static const LPCSTR keyUsages[] = { szOID_PKIX_KP_CODE_SIGNING,
1234 szOID_PKIX_KP_CLIENT_AUTH, szOID_RSA_RSA };
1236 static void testKeyUsage(void)
1239 PCCERT_CONTEXT context;
1242 /* Test base cases */
1243 ret = CertGetEnhancedKeyUsage(NULL, 0, NULL, NULL);
1244 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1245 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
1247 ret = CertGetEnhancedKeyUsage(NULL, 0, NULL, &size);
1248 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1249 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
1251 ret = CertGetEnhancedKeyUsage(NULL, 0, NULL, &size);
1252 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1253 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
1255 ret = CertSetEnhancedKeyUsage(NULL, NULL);
1256 usage.cUsageIdentifier = 0;
1257 ret = CertSetEnhancedKeyUsage(NULL, &usage);
1259 /* Test with a cert with no enhanced key usage extension */
1260 context = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert,
1262 ok(context != NULL, "CertCreateCertificateContext failed: %08x\n",
1266 static const char oid[] = "1.2.3.4";
1267 BYTE buf[sizeof(CERT_ENHKEY_USAGE) + 2 * (sizeof(LPSTR) + sizeof(oid))];
1268 PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
1270 ret = CertGetEnhancedKeyUsage(context, 0, NULL, NULL);
1271 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1272 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
1274 ret = CertGetEnhancedKeyUsage(context, 0, NULL, &size);
1277 /* Windows 2000, ME, or later: even though it succeeded, we expect
1278 * CRYPT_E_NOT_FOUND, which indicates there is no enhanced key
1279 * usage set for this cert (which implies it's valid for all uses.)
1281 ok(GetLastError() == CRYPT_E_NOT_FOUND,
1282 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
1283 ok(size == sizeof(CERT_ENHKEY_USAGE), "Wrong size %d\n", size);
1284 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
1285 ok(ret, "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
1286 ok(pUsage->cUsageIdentifier == 0, "Expected 0 usages, got %d\n",
1287 pUsage->cUsageIdentifier);
1291 /* Windows NT, 95, or 98: it fails, and the last error is
1292 * CRYPT_E_NOT_FOUND.
1294 ok(GetLastError() == CRYPT_E_NOT_FOUND,
1295 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
1297 /* I can add a usage identifier when no key usage has been set */
1298 ret = CertAddEnhancedKeyUsageIdentifier(context, oid);
1299 ok(ret, "CertAddEnhancedKeyUsageIdentifier failed: %08x\n",
1302 ret = CertGetEnhancedKeyUsage(context,
1303 CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG, pUsage, &size);
1304 ok(ret && GetLastError() == 0,
1305 "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
1306 ok(pUsage->cUsageIdentifier == 1, "Expected 1 usage, got %d\n",
1307 pUsage->cUsageIdentifier);
1308 if (pUsage->cUsageIdentifier)
1309 ok(!strcmp(pUsage->rgpszUsageIdentifier[0], oid),
1310 "Expected %s, got %s\n", oid, pUsage->rgpszUsageIdentifier[0]);
1311 /* Now set an empty key usage */
1312 pUsage->cUsageIdentifier = 0;
1313 ret = CertSetEnhancedKeyUsage(context, pUsage);
1314 ok(ret, "CertSetEnhancedKeyUsage failed: %08x\n", GetLastError());
1315 /* Shouldn't find it in the cert */
1317 ret = CertGetEnhancedKeyUsage(context,
1318 CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, pUsage, &size);
1319 ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
1320 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
1321 /* Should find it as an extended property */
1322 ret = CertGetEnhancedKeyUsage(context,
1323 CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG, pUsage, &size);
1324 ok(ret && GetLastError() == 0,
1325 "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
1326 ok(pUsage->cUsageIdentifier == 0, "Expected 0 usages, got %d\n",
1327 pUsage->cUsageIdentifier);
1328 /* Should find it as either */
1329 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
1330 ok(ret && GetLastError() == 0,
1331 "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
1332 ok(pUsage->cUsageIdentifier == 0, "Expected 0 usages, got %d\n",
1333 pUsage->cUsageIdentifier);
1334 /* Add a usage identifier */
1335 ret = CertAddEnhancedKeyUsageIdentifier(context, oid);
1336 ok(ret, "CertAddEnhancedKeyUsageIdentifier failed: %08x\n",
1339 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
1340 ok(ret && GetLastError() == 0,
1341 "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
1342 ok(pUsage->cUsageIdentifier == 1, "Expected 1 identifier, got %d\n",
1343 pUsage->cUsageIdentifier);
1344 if (pUsage->cUsageIdentifier)
1345 ok(!strcmp(pUsage->rgpszUsageIdentifier[0], oid),
1346 "Expected %s, got %s\n", oid, pUsage->rgpszUsageIdentifier[0]);
1347 /* Yep, I can re-add the same usage identifier */
1348 ret = CertAddEnhancedKeyUsageIdentifier(context, oid);
1349 ok(ret, "CertAddEnhancedKeyUsageIdentifier failed: %08x\n",
1352 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
1353 ok(ret && GetLastError() == 0,
1354 "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
1355 ok(pUsage->cUsageIdentifier == 2, "Expected 2 identifiers, got %d\n",
1356 pUsage->cUsageIdentifier);
1357 if (pUsage->cUsageIdentifier)
1358 ok(!strcmp(pUsage->rgpszUsageIdentifier[0], oid),
1359 "Expected %s, got %s\n", oid, pUsage->rgpszUsageIdentifier[0]);
1360 if (pUsage->cUsageIdentifier >= 2)
1361 ok(!strcmp(pUsage->rgpszUsageIdentifier[1], oid),
1362 "Expected %s, got %s\n", oid, pUsage->rgpszUsageIdentifier[1]);
1363 /* Now set a NULL extended property--this deletes the property. */
1364 ret = CertSetEnhancedKeyUsage(context, NULL);
1365 ok(ret, "CertSetEnhancedKeyUsage failed: %08x\n", GetLastError());
1366 SetLastError(0xbaadcafe);
1368 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
1369 ok(GetLastError() == CRYPT_E_NOT_FOUND,
1370 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
1372 CertFreeCertificateContext(context);
1374 /* Now test with a cert with an enhanced key usage extension */
1375 context = CertCreateCertificateContext(X509_ASN_ENCODING, certWithUsage,
1376 sizeof(certWithUsage));
1377 ok(context != NULL, "CertCreateCertificateContext failed: %08x\n",
1382 DWORD bufSize = 0, i;
1384 /* The size may depend on what flags are used to query it, so I
1385 * realloc the buffer for each test.
1387 ret = CertGetEnhancedKeyUsage(context,
1388 CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, NULL, &bufSize);
1389 ok(ret, "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
1390 buf = HeapAlloc(GetProcessHeap(), 0, bufSize);
1393 PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
1395 /* Should find it in the cert */
1397 ret = CertGetEnhancedKeyUsage(context,
1398 CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, pUsage, &size);
1399 ok(ret && GetLastError() == 0,
1400 "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
1401 ok(pUsage->cUsageIdentifier == 3, "Expected 3 usages, got %d\n",
1402 pUsage->cUsageIdentifier);
1403 for (i = 0; i < pUsage->cUsageIdentifier; i++)
1404 ok(!strcmp(pUsage->rgpszUsageIdentifier[i], keyUsages[i]),
1405 "Expected %s, got %s\n", keyUsages[i],
1406 pUsage->rgpszUsageIdentifier[i]);
1407 HeapFree(GetProcessHeap(), 0, buf);
1409 ret = CertGetEnhancedKeyUsage(context, 0, NULL, &bufSize);
1410 ok(ret, "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
1411 buf = HeapAlloc(GetProcessHeap(), 0, bufSize);
1414 PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
1416 /* Should find it as either */
1418 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
1419 /* In Windows, GetLastError returns CRYPT_E_NOT_FOUND not found
1420 * here, even though the return is successful and the usage id
1421 * count is positive. I don't enforce that here.
1424 "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
1425 ok(pUsage->cUsageIdentifier == 3, "Expected 3 usages, got %d\n",
1426 pUsage->cUsageIdentifier);
1427 for (i = 0; i < pUsage->cUsageIdentifier; i++)
1428 ok(!strcmp(pUsage->rgpszUsageIdentifier[i], keyUsages[i]),
1429 "Expected %s, got %s\n", keyUsages[i],
1430 pUsage->rgpszUsageIdentifier[i]);
1431 HeapFree(GetProcessHeap(), 0, buf);
1433 /* Shouldn't find it as an extended property */
1434 ret = CertGetEnhancedKeyUsage(context,
1435 CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG, NULL, &size);
1436 ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
1437 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
1438 /* Adding a usage identifier overrides the cert's usage!? */
1439 ret = CertAddEnhancedKeyUsageIdentifier(context, szOID_RSA_RSA);
1440 ok(ret, "CertAddEnhancedKeyUsageIdentifier failed: %08x\n",
1442 ret = CertGetEnhancedKeyUsage(context, 0, NULL, &bufSize);
1443 ok(ret, "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
1444 buf = HeapAlloc(GetProcessHeap(), 0, bufSize);
1447 PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
1449 /* Should find it as either */
1451 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
1453 "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
1454 ok(pUsage->cUsageIdentifier == 1, "Expected 1 usage, got %d\n",
1455 pUsage->cUsageIdentifier);
1456 ok(!strcmp(pUsage->rgpszUsageIdentifier[0], szOID_RSA_RSA),
1457 "Expected %s, got %s\n", szOID_RSA_RSA,
1458 pUsage->rgpszUsageIdentifier[0]);
1459 HeapFree(GetProcessHeap(), 0, buf);
1461 /* But querying the cert directly returns its usage */
1462 ret = CertGetEnhancedKeyUsage(context,
1463 CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, NULL, &bufSize);
1464 ok(ret, "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
1465 buf = HeapAlloc(GetProcessHeap(), 0, bufSize);
1468 PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
1471 ret = CertGetEnhancedKeyUsage(context,
1472 CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, pUsage, &size);
1474 "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
1475 ok(pUsage->cUsageIdentifier == 3, "Expected 3 usages, got %d\n",
1476 pUsage->cUsageIdentifier);
1477 for (i = 0; i < pUsage->cUsageIdentifier; i++)
1478 ok(!strcmp(pUsage->rgpszUsageIdentifier[i], keyUsages[i]),
1479 "Expected %s, got %s\n", keyUsages[i],
1480 pUsage->rgpszUsageIdentifier[i]);
1481 HeapFree(GetProcessHeap(), 0, buf);
1483 /* And removing the only usage identifier in the extended property
1484 * results in the cert's key usage being found.
1486 ret = CertRemoveEnhancedKeyUsageIdentifier(context, szOID_RSA_RSA);
1487 ok(ret, "CertRemoveEnhancedKeyUsage failed: %08x\n", GetLastError());
1488 ret = CertGetEnhancedKeyUsage(context, 0, NULL, &bufSize);
1489 ok(ret, "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
1490 buf = HeapAlloc(GetProcessHeap(), 0, bufSize);
1493 PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
1495 /* Should find it as either */
1497 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
1499 "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
1500 ok(pUsage->cUsageIdentifier == 3, "Expected 3 usages, got %d\n",
1501 pUsage->cUsageIdentifier);
1502 for (i = 0; i < pUsage->cUsageIdentifier; i++)
1503 ok(!strcmp(pUsage->rgpszUsageIdentifier[i], keyUsages[i]),
1504 "Expected %s, got %s\n", keyUsages[i],
1505 pUsage->rgpszUsageIdentifier[i]);
1506 HeapFree(GetProcessHeap(), 0, buf);
1509 CertFreeCertificateContext(context);
1513 static void testCompareCertName(void)
1515 static BYTE bogus[] = { 1, 2, 3, 4 };
1516 static BYTE bogusPrime[] = { 0, 1, 2, 3, 4 };
1517 static BYTE emptyPrime[] = { 0x30, 0x00, 0x01 };
1519 CERT_NAME_BLOB blob1, blob2;
1522 ret = CertCompareCertificateName(0, NULL, NULL);
1524 /* An empty name checks against itself.. */
1525 blob1.pbData = emptyCert;
1526 blob1.cbData = sizeof(emptyCert);
1527 ret = CertCompareCertificateName(0, &blob1, &blob1);
1528 ok(ret, "CertCompareCertificateName failed: %08x\n", GetLastError());
1529 /* It doesn't have to be a valid encoded name.. */
1530 blob1.pbData = bogus;
1531 blob1.cbData = sizeof(bogus);
1532 ret = CertCompareCertificateName(0, &blob1, &blob1);
1533 ok(ret, "CertCompareCertificateName failed: %08x\n", GetLastError());
1534 /* Leading zeroes matter.. */
1535 blob2.pbData = bogusPrime;
1536 blob2.cbData = sizeof(bogusPrime);
1537 ret = CertCompareCertificateName(0, &blob1, &blob2);
1538 ok(!ret, "Expected failure\n");
1539 /* As do trailing extra bytes. */
1540 blob2.pbData = emptyPrime;
1541 blob2.cbData = sizeof(emptyPrime);
1542 ret = CertCompareCertificateName(0, &blob1, &blob2);
1543 ok(!ret, "Expected failure\n");
1546 static BYTE int1[] = { 0x88, 0xff, 0xff, 0xff };
1547 static BYTE int2[] = { 0x88, 0xff };
1548 static BYTE int3[] = { 0x23, 0xff };
1549 static BYTE int4[] = { 0x7f, 0x00 };
1550 static BYTE int5[] = { 0x7f };
1551 static BYTE int6[] = { 0x80, 0x00, 0x00, 0x00 };
1552 static BYTE int7[] = { 0x80, 0x00 };
1554 static struct IntBlobTest
1556 CRYPT_INTEGER_BLOB blob1;
1557 CRYPT_INTEGER_BLOB blob2;
1560 { { sizeof(int1), int1 }, { sizeof(int2), int2 }, TRUE },
1561 { { sizeof(int3), int3 }, { sizeof(int3), int3 }, TRUE },
1562 { { sizeof(int4), int4 }, { sizeof(int5), int5 }, TRUE },
1563 { { sizeof(int6), int6 }, { sizeof(int7), int7 }, TRUE },
1564 { { sizeof(int1), int1 }, { sizeof(int7), int7 }, FALSE },
1567 static void testCompareIntegerBlob(void)
1572 for (i = 0; i < sizeof(intBlobs) / sizeof(intBlobs[0]); i++)
1574 ret = CertCompareIntegerBlob(&intBlobs[i].blob1, &intBlobs[i].blob2);
1575 ok(ret == intBlobs[i].areEqual,
1576 "%d: expected blobs %s compare\n", i, intBlobs[i].areEqual ?
1581 static void testComparePublicKeyInfo(void)
1584 CERT_PUBLIC_KEY_INFO info1 = { { 0 } }, info2 = { { 0 } };
1585 static CHAR oid_rsa_rsa[] = szOID_RSA_RSA;
1586 static CHAR oid_rsa_sha1rsa[] = szOID_RSA_SHA1RSA;
1587 static CHAR oid_x957_dsa[] = szOID_X957_DSA;
1588 static BYTE bits1[] = { 1, 0 };
1589 static BYTE bits2[] = { 0 };
1590 static BYTE bits3[] = { 1 };
1593 ret = CertComparePublicKeyInfo(0, NULL, NULL);
1595 /* Empty public keys compare */
1596 ret = CertComparePublicKeyInfo(0, &info1, &info2);
1597 ok(ret, "CertComparePublicKeyInfo failed: %08x\n", GetLastError());
1598 /* Different OIDs appear to compare */
1599 info1.Algorithm.pszObjId = oid_rsa_rsa;
1600 info2.Algorithm.pszObjId = oid_rsa_sha1rsa;
1601 ret = CertComparePublicKeyInfo(0, &info1, &info2);
1602 ok(ret, "CertComparePublicKeyInfo failed: %08x\n", GetLastError());
1603 info2.Algorithm.pszObjId = oid_x957_dsa;
1604 ret = CertComparePublicKeyInfo(0, &info1, &info2);
1605 ok(ret, "CertComparePublicKeyInfo failed: %08x\n", GetLastError());
1606 info1.PublicKey.cbData = sizeof(bits1);
1607 info1.PublicKey.pbData = bits1;
1608 info1.PublicKey.cUnusedBits = 0;
1609 info2.PublicKey.cbData = sizeof(bits1);
1610 info2.PublicKey.pbData = bits1;
1611 info2.PublicKey.cUnusedBits = 0;
1612 ret = CertComparePublicKeyInfo(0, &info1, &info2);
1613 ok(ret, "CertComparePublicKeyInfo failed: %08x\n", GetLastError());
1614 /* Even though they compare in their used bits, these do not compare */
1615 info1.PublicKey.cbData = sizeof(bits2);
1616 info1.PublicKey.pbData = bits2;
1617 info1.PublicKey.cUnusedBits = 0;
1618 info2.PublicKey.cbData = sizeof(bits3);
1619 info2.PublicKey.pbData = bits3;
1620 info2.PublicKey.cUnusedBits = 1;
1621 ret = CertComparePublicKeyInfo(0, &info1, &info2);
1622 /* Simple (non-comparing) case */
1623 ok(!ret, "Expected keys not to compare\n");
1624 info2.PublicKey.cbData = sizeof(bits1);
1625 info2.PublicKey.pbData = bits1;
1626 info2.PublicKey.cUnusedBits = 0;
1627 ret = CertComparePublicKeyInfo(0, &info1, &info2);
1628 ok(!ret, "Expected keys not to compare\n");
1631 static void testHashPublicKeyInfo(void)
1634 CERT_PUBLIC_KEY_INFO info = { { 0 } };
1638 ret = CryptHashPublicKeyInfo(0, 0, 0, 0, NULL, NULL, NULL);
1639 ret = CryptHashPublicKeyInfo(0, 0, 0, 0, &info, NULL, NULL);
1641 ret = CryptHashPublicKeyInfo(0, 0, 0, 0, NULL, NULL, &len);
1642 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
1643 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
1644 ret = CryptHashPublicKeyInfo(0, 0, 0, X509_ASN_ENCODING, NULL, NULL, &len);
1645 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
1646 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
1647 ret = CryptHashPublicKeyInfo(0, 0, 0, X509_ASN_ENCODING, &info, NULL, &len);
1648 ok(ret, "CryptHashPublicKeyInfo failed: %08x\n", GetLastError());
1649 ok(len == 16, "Expected hash size 16, got %d\n", len);
1652 static const BYTE emptyHash[] = { 0xb8,0x51,0x3a,0x31,0x0e,0x9f,0x40,
1653 0x36,0x9c,0x92,0x45,0x1b,0x9d,0xc8,0xf9,0xf6 };
1656 ret = CryptHashPublicKeyInfo(0, 0, 0, X509_ASN_ENCODING, &info, buf,
1658 ok(ret, "CryptHashPublicKeyInfo failed: %08x\n", GetLastError());
1659 ok(!memcmp(buf, emptyHash, len), "Unexpected hash\n");
1663 static void testCompareCert(void)
1665 CERT_INFO info1 = { 0 }, info2 = { 0 };
1669 ret = CertCompareCertificate(X509_ASN_ENCODING, NULL, NULL);
1672 /* Certs with the same issuer and serial number are equal, even if they
1673 * differ in other respects (like subject).
1675 info1.SerialNumber.pbData = serialNum;
1676 info1.SerialNumber.cbData = sizeof(serialNum);
1677 info1.Issuer.pbData = subjectName;
1678 info1.Issuer.cbData = sizeof(subjectName);
1679 info1.Subject.pbData = subjectName2;
1680 info1.Subject.cbData = sizeof(subjectName2);
1681 info2.SerialNumber.pbData = serialNum;
1682 info2.SerialNumber.cbData = sizeof(serialNum);
1683 info2.Issuer.pbData = subjectName;
1684 info2.Issuer.cbData = sizeof(subjectName);
1685 info2.Subject.pbData = subjectName;
1686 info2.Subject.cbData = sizeof(subjectName);
1687 ret = CertCompareCertificate(X509_ASN_ENCODING, &info1, &info2);
1688 ok(ret, "Expected certs to be equal\n");
1690 info2.Issuer.pbData = subjectName2;
1691 info2.Issuer.cbData = sizeof(subjectName2);
1692 ret = CertCompareCertificate(X509_ASN_ENCODING, &info1, &info2);
1693 ok(!ret, "Expected certs not to be equal\n");
1696 static void testVerifySubjectCert(void)
1700 PCCERT_CONTEXT context1, context2;
1703 ret = CertVerifySubjectCertificateContext(NULL, NULL, NULL);
1706 ret = CertVerifySubjectCertificateContext(NULL, NULL, &flags);
1707 ok(ret, "CertVerifySubjectCertificateContext failed; %08x\n",
1709 flags = CERT_STORE_NO_CRL_FLAG;
1710 ret = CertVerifySubjectCertificateContext(NULL, NULL, &flags);
1711 ok(!ret && GetLastError() == E_INVALIDARG,
1712 "Expected E_INVALIDARG, got %08x\n", GetLastError());
1715 context1 = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert,
1717 ret = CertVerifySubjectCertificateContext(NULL, context1, &flags);
1718 ok(ret, "CertVerifySubjectCertificateContext failed; %08x\n",
1720 ret = CertVerifySubjectCertificateContext(context1, NULL, &flags);
1721 ok(ret, "CertVerifySubjectCertificateContext failed; %08x\n",
1723 ret = CertVerifySubjectCertificateContext(context1, context1, &flags);
1724 ok(ret, "CertVerifySubjectCertificateContext failed; %08x\n",
1727 context2 = CertCreateCertificateContext(X509_ASN_ENCODING,
1728 bigCertWithDifferentSubject, sizeof(bigCertWithDifferentSubject));
1729 SetLastError(0xdeadbeef);
1730 ret = CertVerifySubjectCertificateContext(context1, context2, &flags);
1731 ok(ret, "CertVerifySubjectCertificateContext failed; %08x\n",
1733 flags = CERT_STORE_REVOCATION_FLAG;
1734 ret = CertVerifySubjectCertificateContext(context1, context2, &flags);
1735 ok(ret, "CertVerifySubjectCertificateContext failed; %08x\n",
1737 ok(flags == (CERT_STORE_REVOCATION_FLAG | CERT_STORE_NO_CRL_FLAG),
1738 "Expected CERT_STORE_REVOCATION_FLAG | CERT_STORE_NO_CRL_FLAG, got %08x\n",
1740 flags = CERT_STORE_SIGNATURE_FLAG;
1741 ret = CertVerifySubjectCertificateContext(context1, context2, &flags);
1742 ok(ret, "CertVerifySubjectCertificateContext failed; %08x\n",
1744 ok(flags == CERT_STORE_SIGNATURE_FLAG,
1745 "Expected CERT_STORE_SIGNATURE_FLAG, got %08x\n", flags);
1746 CertFreeCertificateContext(context2);
1748 CertFreeCertificateContext(context1);
1751 static BYTE privKey[] = {
1752 0x07, 0x02, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x52, 0x53, 0x41, 0x32, 0x00,
1753 0x02, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x79, 0x10, 0x1c, 0xd0, 0x6b, 0x10,
1754 0x18, 0x30, 0x94, 0x61, 0xdc, 0x0e, 0xcb, 0x96, 0x4e, 0x21, 0x3f, 0x79, 0xcd,
1755 0xa9, 0x17, 0x62, 0xbc, 0xbb, 0x61, 0x4c, 0xe0, 0x75, 0x38, 0x6c, 0xf3, 0xde,
1756 0x60, 0x86, 0x03, 0x97, 0x65, 0xeb, 0x1e, 0x6b, 0xdb, 0x53, 0x85, 0xad, 0x68,
1757 0x21, 0xf1, 0x5d, 0xe7, 0x1f, 0xe6, 0x53, 0xb4, 0xbb, 0x59, 0x3e, 0x14, 0x27,
1758 0xb1, 0x83, 0xa7, 0x3a, 0x54, 0xe2, 0x8f, 0x65, 0x8e, 0x6a, 0x4a, 0xcf, 0x3b,
1759 0x1f, 0x65, 0xff, 0xfe, 0xf1, 0x31, 0x3a, 0x37, 0x7a, 0x8b, 0xcb, 0xc6, 0xd4,
1760 0x98, 0x50, 0x36, 0x67, 0xe4, 0xa1, 0xe8, 0x7e, 0x8a, 0xc5, 0x23, 0xf2, 0x77,
1761 0xf5, 0x37, 0x61, 0x49, 0x72, 0x59, 0xe8, 0x3d, 0xf7, 0x60, 0xb2, 0x77, 0xca,
1762 0x78, 0x54, 0x6d, 0x65, 0x9e, 0x03, 0x97, 0x1b, 0x61, 0xbd, 0x0c, 0xd8, 0x06,
1763 0x63, 0xe2, 0xc5, 0x48, 0xef, 0xb3, 0xe2, 0x6e, 0x98, 0x7d, 0xbd, 0x4e, 0x72,
1764 0x91, 0xdb, 0x31, 0x57, 0xe3, 0x65, 0x3a, 0x49, 0xca, 0xec, 0xd2, 0x02, 0x4e,
1765 0x22, 0x7e, 0x72, 0x8e, 0xf9, 0x79, 0x84, 0x82, 0xdf, 0x7b, 0x92, 0x2d, 0xaf,
1766 0xc9, 0xe4, 0x33, 0xef, 0x89, 0x5c, 0x66, 0x99, 0xd8, 0x80, 0x81, 0x47, 0x2b,
1767 0xb1, 0x66, 0x02, 0x84, 0x59, 0x7b, 0xc3, 0xbe, 0x98, 0x45, 0x4a, 0x3d, 0xdd,
1768 0xea, 0x2b, 0xdf, 0x4e, 0xb4, 0x24, 0x6b, 0xec, 0xe7, 0xd9, 0x0c, 0x45, 0xb8,
1769 0xbe, 0xca, 0x69, 0x37, 0x92, 0x4c, 0x38, 0x6b, 0x96, 0x6d, 0xcd, 0x86, 0x67,
1770 0x5c, 0xea, 0x54, 0x94, 0xa4, 0xca, 0xa4, 0x02, 0xa5, 0x21, 0x4d, 0xae, 0x40,
1771 0x8f, 0x9d, 0x51, 0x83, 0xf2, 0x3f, 0x33, 0xc1, 0x72, 0xb4, 0x1d, 0x94, 0x6e,
1772 0x7d, 0xe4, 0x27, 0x3f, 0xea, 0xff, 0xe5, 0x9b, 0xa7, 0x5e, 0x55, 0x8e, 0x0d,
1773 0x69, 0x1c, 0x7a, 0xff, 0x81, 0x9d, 0x53, 0x52, 0x97, 0x9a, 0x76, 0x79, 0xda,
1774 0x93, 0x32, 0x16, 0xec, 0x69, 0x51, 0x1a, 0x4e, 0xc3, 0xf1, 0x72, 0x80, 0x78,
1775 0x5e, 0x66, 0x4a, 0x8d, 0x85, 0x2f, 0x3f, 0xb2, 0xa7 };
1777 static const BYTE selfSignedCert[] = {
1778 0x30, 0x82, 0x01, 0x1f, 0x30, 0x81, 0xce, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02,
1779 0x10, 0xeb, 0x0d, 0x57, 0x2a, 0x9c, 0x09, 0xba, 0xa4, 0x4a, 0xb7, 0x25, 0x49,
1780 0xd9, 0x3e, 0xb5, 0x73, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1d,
1781 0x05, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03,
1782 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30,
1783 0x1e, 0x17, 0x0d, 0x30, 0x36, 0x30, 0x36, 0x32, 0x39, 0x30, 0x35, 0x30, 0x30,
1784 0x34, 0x36, 0x5a, 0x17, 0x0d, 0x30, 0x37, 0x30, 0x36, 0x32, 0x39, 0x31, 0x31,
1785 0x30, 0x30, 0x34, 0x36, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03,
1786 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e,
1787 0x67, 0x00, 0x30, 0x5c, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
1788 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x4b, 0x00, 0x30, 0x48, 0x02, 0x41,
1789 0x00, 0xe2, 0x54, 0x3a, 0xa7, 0x83, 0xb1, 0x27, 0x14, 0x3e, 0x59, 0xbb, 0xb4,
1790 0x53, 0xe6, 0x1f, 0xe7, 0x5d, 0xf1, 0x21, 0x68, 0xad, 0x85, 0x53, 0xdb, 0x6b,
1791 0x1e, 0xeb, 0x65, 0x97, 0x03, 0x86, 0x60, 0xde, 0xf3, 0x6c, 0x38, 0x75, 0xe0,
1792 0x4c, 0x61, 0xbb, 0xbc, 0x62, 0x17, 0xa9, 0xcd, 0x79, 0x3f, 0x21, 0x4e, 0x96,
1793 0xcb, 0x0e, 0xdc, 0x61, 0x94, 0x30, 0x18, 0x10, 0x6b, 0xd0, 0x1c, 0x10, 0x79,
1794 0x02, 0x03, 0x01, 0x00, 0x01, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02,
1795 0x1d, 0x05, 0x00, 0x03, 0x41, 0x00, 0x25, 0x90, 0x53, 0x34, 0xd9, 0x56, 0x41,
1796 0x5e, 0xdb, 0x7e, 0x01, 0x36, 0xec, 0x27, 0x61, 0x5e, 0xb7, 0x4d, 0x90, 0x66,
1797 0xa2, 0xe1, 0x9d, 0x58, 0x76, 0xd4, 0x9c, 0xba, 0x2c, 0x84, 0xc6, 0x83, 0x7a,
1798 0x22, 0x0d, 0x03, 0x69, 0x32, 0x1a, 0x6d, 0xcb, 0x0c, 0x15, 0xb3, 0x6b, 0xc7,
1799 0x0a, 0x8c, 0xb4, 0x5c, 0x34, 0x78, 0xe0, 0x3c, 0x9c, 0xe9, 0xf3, 0x30, 0x9f,
1800 0xa8, 0x76, 0x57, 0x92, 0x36 };
1802 static const BYTE exportedPublicKeyBlob[] = {
1803 0x06,0x02,0x00,0x00,0x00,0xa4,0x00,0x00,0x52,0x53,0x41,0x31,0x00,0x02,0x00,0x00,
1804 0x01,0x00,0x01,0x00,0x79,0x10,0x1c,0xd0,0x6b,0x10,0x18,0x30,0x94,0x61,0xdc,0x0e,
1805 0xcb,0x96,0x4e,0x21,0x3f,0x79,0xcd,0xa9,0x17,0x62,0xbc,0xbb,0x61,0x4c,0xe0,0x75,
1806 0x38,0x6c,0xf3,0xde,0x60,0x86,0x03,0x97,0x65,0xeb,0x1e,0x6b,0xdb,0x53,0x85,0xad,
1807 0x68,0x21,0xf1,0x5d,0xe7,0x1f,0xe6,0x53,0xb4,0xbb,0x59,0x3e,0x14,0x27,0xb1,0x83,
1808 0xa7,0x3a,0x54,0xe2 };
1810 static const BYTE asnEncodedPublicKey[] = {
1811 0x30,0x48,0x02,0x41,0x00,0xe2,0x54,0x3a,0xa7,0x83,0xb1,0x27,0x14,0x3e,0x59,0xbb,
1812 0xb4,0x53,0xe6,0x1f,0xe7,0x5d,0xf1,0x21,0x68,0xad,0x85,0x53,0xdb,0x6b,0x1e,0xeb,
1813 0x65,0x97,0x03,0x86,0x60,0xde,0xf3,0x6c,0x38,0x75,0xe0,0x4c,0x61,0xbb,0xbc,0x62,
1814 0x17,0xa9,0xcd,0x79,0x3f,0x21,0x4e,0x96,0xcb,0x0e,0xdc,0x61,0x94,0x30,0x18,0x10,
1815 0x6b,0xd0,0x1c,0x10,0x79,0x02,0x03,0x01,0x00,0x01 };
1817 static void testAcquireCertPrivateKey(void)
1820 PCCERT_CONTEXT cert;
1822 DWORD size, keySpec;
1824 CRYPT_KEY_PROV_INFO keyProvInfo;
1826 WCHAR ms_def_prov_w[MAX_PATH];
1828 lstrcpyW(ms_def_prov_w, MS_DEF_PROV_W);
1830 keyProvInfo.pwszContainerName = cspNameW;
1831 keyProvInfo.pwszProvName = ms_def_prov_w;
1832 keyProvInfo.dwProvType = PROV_RSA_FULL;
1833 keyProvInfo.dwFlags = 0;
1834 keyProvInfo.cProvParam = 0;
1835 keyProvInfo.rgProvParam = NULL;
1836 keyProvInfo.dwKeySpec = AT_SIGNATURE;
1838 CryptAcquireContextW(NULL, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
1839 CRYPT_DELETEKEYSET);
1841 cert = CertCreateCertificateContext(X509_ASN_ENCODING, selfSignedCert,
1842 sizeof(selfSignedCert));
1845 ret = CryptAcquireCertificatePrivateKey(NULL, 0, NULL, NULL, NULL, NULL);
1846 ret = CryptAcquireCertificatePrivateKey(NULL, 0, NULL, NULL, NULL,
1848 ret = CryptAcquireCertificatePrivateKey(NULL, 0, NULL, NULL, &keySpec,
1850 ret = CryptAcquireCertificatePrivateKey(NULL, 0, NULL, &csp, NULL, NULL);
1851 ret = CryptAcquireCertificatePrivateKey(NULL, 0, NULL, &csp, &keySpec,
1853 ret = CryptAcquireCertificatePrivateKey(cert, 0, NULL, NULL, NULL, NULL);
1856 /* Missing private key */
1857 ret = CryptAcquireCertificatePrivateKey(cert, 0, NULL, &csp, NULL, NULL);
1858 ok(!ret && GetLastError() == CRYPT_E_NO_KEY_PROPERTY,
1859 "Expected CRYPT_E_NO_KEY_PROPERTY, got %08x\n", GetLastError());
1860 ret = CryptAcquireCertificatePrivateKey(cert, 0, NULL, &csp, &keySpec,
1862 ok(!ret && GetLastError() == CRYPT_E_NO_KEY_PROPERTY,
1863 "Expected CRYPT_E_NO_KEY_PROPERTY, got %08x\n", GetLastError());
1864 CertSetCertificateContextProperty(cert, CERT_KEY_PROV_INFO_PROP_ID, 0,
1866 ret = CryptAcquireCertificatePrivateKey(cert, 0, NULL, &csp, &keySpec,
1868 ok(!ret && GetLastError() == CRYPT_E_NO_KEY_PROPERTY,
1869 "Expected CRYPT_E_NO_KEY_PROPERTY, got %08x\n", GetLastError());
1871 CryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
1873 ret = CryptImportKey(csp, privKey, sizeof(privKey), 0, 0, &key);
1874 ok(ret, "CryptImportKey failed: %08x\n", GetLastError());
1879 CERT_KEY_CONTEXT keyContext;
1881 /* Don't cache provider */
1882 ret = CryptAcquireCertificatePrivateKey(cert, 0, NULL, &certCSP,
1883 &keySpec, &callerFree);
1884 ok(ret, "CryptAcquireCertificatePrivateKey failed: %08x\n",
1886 ok(callerFree, "Expected callerFree to be TRUE\n");
1887 CryptReleaseContext(certCSP, 0);
1888 ret = CryptAcquireCertificatePrivateKey(cert, 0, NULL, &certCSP,
1890 ok(ret, "CryptAcquireCertificatePrivateKey failed: %08x\n",
1892 CryptReleaseContext(certCSP, 0);
1894 /* Use the key prov info's caching (there shouldn't be any) */
1895 ret = CryptAcquireCertificatePrivateKey(cert,
1896 CRYPT_ACQUIRE_USE_PROV_INFO_FLAG, NULL, &certCSP, &keySpec,
1898 ok(ret, "CryptAcquireCertificatePrivateKey failed: %08x\n",
1900 ok(callerFree, "Expected callerFree to be TRUE\n");
1901 CryptReleaseContext(certCSP, 0);
1903 /* Cache it (and check that it's cached) */
1904 ret = CryptAcquireCertificatePrivateKey(cert,
1905 CRYPT_ACQUIRE_CACHE_FLAG, NULL, &certCSP, &keySpec, &callerFree);
1906 ok(ret, "CryptAcquireCertificatePrivateKey failed: %08x\n",
1908 ok(!callerFree, "Expected callerFree to be FALSE\n");
1909 size = sizeof(keyContext);
1910 ret = CertGetCertificateContextProperty(cert, CERT_KEY_CONTEXT_PROP_ID,
1911 &keyContext, &size);
1912 ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
1915 /* Remove the cached provider */
1916 CryptReleaseContext(keyContext.hCryptProv, 0);
1917 CertSetCertificateContextProperty(cert, CERT_KEY_CONTEXT_PROP_ID, 0,
1919 /* Allow caching via the key prov info */
1920 keyProvInfo.dwFlags = CERT_SET_KEY_CONTEXT_PROP_ID;
1921 CertSetCertificateContextProperty(cert, CERT_KEY_PROV_INFO_PROP_ID, 0,
1923 /* Now use the key prov info's caching */
1924 ret = CryptAcquireCertificatePrivateKey(cert,
1925 CRYPT_ACQUIRE_USE_PROV_INFO_FLAG, NULL, &certCSP, &keySpec,
1927 ok(ret, "CryptAcquireCertificatePrivateKey failed: %08x\n",
1929 ok(!callerFree, "Expected callerFree to be FALSE\n");
1930 size = sizeof(keyContext);
1931 ret = CertGetCertificateContextProperty(cert, CERT_KEY_CONTEXT_PROP_ID,
1932 &keyContext, &size);
1933 ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
1936 CryptDestroyKey(key);
1939 /* Some sanity-checking on public key exporting */
1940 ret = CryptImportPublicKeyInfo(csp, X509_ASN_ENCODING,
1941 &cert->pCertInfo->SubjectPublicKeyInfo, &key);
1942 ok(ret, "CryptImportPublicKeyInfo failed: %08x\n", GetLastError());
1945 ret = CryptExportKey(key, 0, PUBLICKEYBLOB, 0, NULL, &size);
1946 ok(ret, "CryptExportKey failed: %08x\n", GetLastError());
1949 LPBYTE buf = HeapAlloc(GetProcessHeap(), 0, size), encodedKey;
1951 ret = CryptExportKey(key, 0, PUBLICKEYBLOB, 0, buf, &size);
1952 ok(ret, "CryptExportKey failed: %08x\n", GetLastError());
1953 ok(size == sizeof(exportedPublicKeyBlob), "Unexpected size %d\n",
1955 ok(!memcmp(buf, exportedPublicKeyBlob, size), "Unexpected value\n");
1956 ret = CryptEncodeObjectEx(X509_ASN_ENCODING, RSA_CSP_PUBLICKEYBLOB,
1957 buf, CRYPT_ENCODE_ALLOC_FLAG, NULL, &encodedKey, &size);
1958 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1961 ok(size == sizeof(asnEncodedPublicKey), "Unexpected size %d\n",
1963 ok(!memcmp(encodedKey, asnEncodedPublicKey, size),
1964 "Unexpected value\n");
1965 LocalFree(encodedKey);
1967 HeapFree(GetProcessHeap(), 0, buf);
1969 CryptDestroyKey(key);
1971 ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING,
1972 NULL, 0, NULL, NULL, &size);
1973 ok(ret, "CryptExportPublicKeyInfoEx failed: %08x\n", GetLastError());
1976 PCERT_PUBLIC_KEY_INFO info = HeapAlloc(GetProcessHeap(), 0, size);
1978 ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING,
1979 NULL, 0, NULL, info, &size);
1980 ok(ret, "CryptExportPublicKeyInfoEx failed: %08x\n", GetLastError());
1983 ok(info->PublicKey.cbData == sizeof(asnEncodedPublicKey),
1984 "Unexpected size %d\n", info->PublicKey.cbData);
1985 ok(!memcmp(info->PublicKey.pbData, asnEncodedPublicKey,
1986 info->PublicKey.cbData), "Unexpected value\n");
1988 HeapFree(GetProcessHeap(), 0, info);
1991 CryptReleaseContext(csp, 0);
1992 CryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
1993 CRYPT_DELETEKEYSET);
1995 CertFreeCertificateContext(cert);
1998 static void testGetPublicKeyLength(void)
2000 static char oid_rsa_rsa[] = szOID_RSA_RSA;
2001 static char oid_rsa_dh[] = szOID_RSA_DH;
2002 static char bogusOID[] = "1.2.3";
2004 CERT_PUBLIC_KEY_INFO info = { { 0 } };
2005 BYTE bogusKey[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
2006 BYTE key[] = { 0x30,0x0f,0x02,0x08,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
2007 0x02,0x03,0x01,0x00,0x01 };
2010 ret = CertGetPublicKeyLength(0, NULL);
2012 /* With an empty public key info */
2013 SetLastError(0xdeadbeef);
2014 ret = CertGetPublicKeyLength(0, &info);
2015 ok(ret == 0 && GetLastError() == ERROR_FILE_NOT_FOUND,
2016 "Expected length 0 and ERROR_FILE_NOT_FOUND, got length %d, %08x\n",
2017 ret, GetLastError());
2018 SetLastError(0xdeadbeef);
2019 ret = CertGetPublicKeyLength(X509_ASN_ENCODING, &info);
2020 ok(ret == 0 && GetLastError() == CRYPT_E_ASN1_EOD,
2021 "Expected length 0 and CRYPT_E_ASN1_EOD, got length %d, %08x\n",
2022 ret, GetLastError());
2023 /* With a nearly-empty public key info */
2024 info.Algorithm.pszObjId = oid_rsa_rsa;
2025 SetLastError(0xdeadbeef);
2026 ret = CertGetPublicKeyLength(0, &info);
2027 ok(ret == 0 && GetLastError() == ERROR_FILE_NOT_FOUND,
2028 "Expected length 0 and ERROR_FILE_NOT_FOUND, got length %d, %08x\n",
2029 ret, GetLastError());
2030 SetLastError(0xdeadbeef);
2031 ret = CertGetPublicKeyLength(X509_ASN_ENCODING, &info);
2032 ok(ret == 0 && GetLastError() == CRYPT_E_ASN1_EOD,
2033 "Expected length 0 and CRYPT_E_ASN1_EOD, got length %d, %08x\n",
2034 ret, GetLastError());
2035 /* With a bogus key */
2036 info.PublicKey.cbData = sizeof(bogusKey);
2037 info.PublicKey.pbData = bogusKey;
2038 SetLastError(0xdeadbeef);
2039 ret = CertGetPublicKeyLength(0, &info);
2040 ok(ret == 0 && GetLastError() == ERROR_FILE_NOT_FOUND,
2041 "Expected length 0 and ERROR_FILE_NOT_FOUND, got length %d, %08x\n",
2042 ret, GetLastError());
2043 SetLastError(0xdeadbeef);
2044 ret = CertGetPublicKeyLength(X509_ASN_ENCODING, &info);
2045 ok(ret == 0 && GetLastError() == CRYPT_E_ASN1_BADTAG,
2046 "Expected length 0 and CRYPT_E_ASN1_BADTAGTAG, got length %d, %08x\n",
2047 ret, GetLastError());
2048 /* With a believable RSA key but a bogus OID */
2049 info.Algorithm.pszObjId = bogusOID;
2050 info.PublicKey.cbData = sizeof(key);
2051 info.PublicKey.pbData = key;
2052 SetLastError(0xdeadbeef);
2053 ret = CertGetPublicKeyLength(0, &info);
2054 ok(ret == 0 && GetLastError() == ERROR_FILE_NOT_FOUND,
2055 "Expected length 0 and ERROR_FILE_NOT_FOUND, got length %d, %08x\n",
2056 ret, GetLastError());
2057 SetLastError(0xdeadbeef);
2058 ret = CertGetPublicKeyLength(X509_ASN_ENCODING, &info);
2059 ok(ret == 56, "Expected length 56, got %d\n", ret);
2060 /* An RSA key with the DH OID */
2061 info.Algorithm.pszObjId = oid_rsa_dh;
2062 SetLastError(0xdeadbeef);
2063 ret = CertGetPublicKeyLength(X509_ASN_ENCODING, &info);
2064 ok(ret == 0 && GetLastError() == CRYPT_E_ASN1_BADTAG,
2065 "Expected length 0 and CRYPT_E_ASN1_BADTAG, got length %d, %08x\n",
2066 ret, GetLastError());
2067 /* With the RSA OID */
2068 info.Algorithm.pszObjId = oid_rsa_rsa;
2069 SetLastError(0xdeadbeef);
2070 ret = CertGetPublicKeyLength(X509_ASN_ENCODING, &info);
2071 ok(ret == 56, "Expected length 56, got %d\n", ret);
2076 init_function_pointers();
2079 testCertProperties();
2082 testGetSubjectCert();
2083 testGetIssuerCert();
2085 testCryptHashCert();
2087 testSignAndEncodeCert();
2088 testCreateSelfSignCert();
2090 testCompareCertName();
2091 testCompareIntegerBlob();
2092 testComparePublicKeyInfo();
2093 testHashPublicKeyInfo();
2095 testVerifySubjectCert();
2096 testAcquireCertPrivateKey();
2097 testGetPublicKeyLength();