crypt32: Implement CryptAcquireCertificatePrivateKey.
[wine/hacks.git] / dlls / crypt32 / tests / cert.c
blob49692e22eb9b6a8fc7941f85dac3a41e0507fc5c
1 /*
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
21 #include <assert.h>
22 #include <stdio.h>
23 #include <stdarg.h>
24 #include <windef.h>
25 #include <winbase.h>
26 #include <winreg.h>
27 #include <winerror.h>
28 #include <wincrypt.h>
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); \
37 if(!p ## func) \
38 trace("GetProcAddress(hCrypt32, \"%s\") failed\n", #func); \
40 static void init_function_pointers(void)
42 HMODULE hCrypt32;
44 pCryptVerifyCertificateSignatureEx = NULL;
46 hCrypt32 = GetModuleHandleA("crypt32.dll");
47 assert(hCrypt32);
49 CRYPT_GET_PROC(CryptVerifyCertificateSignatureEx);
52 static const BYTE subjectName[] = { 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06,
53 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61,
54 0x6e, 0x67, 0x00 };
55 static const BYTE serialNum[] = { 1 };
56 static const BYTE bigCert[] = { 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
57 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
58 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22,
59 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30,
60 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30,
61 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30,
62 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20,
63 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01,
64 0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01,
65 0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
66 static const BYTE bigCertHash[] = { 0x6e, 0x30, 0x90, 0x71, 0x5f, 0xd9, 0x23,
67 0x56, 0xeb, 0xae, 0x25, 0x40, 0xe6, 0x22, 0xda, 0x19, 0x26, 0x02, 0xa6, 0x08 };
69 static const BYTE bigCertWithDifferentSubject[] = { 0x30, 0x7a, 0x02, 0x01, 0x02,
70 0x30, 0x02, 0x06, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55,
71 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67,
72 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31,
73 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31,
74 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15,
75 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x41, 0x6c,
76 0x65, 0x78, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06,
77 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55,
78 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02,
79 0x01, 0x01 };
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,
90 0x02, 0x01, 0x01 };
92 static const BYTE subjectName2[] = { 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06,
93 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x41, 0x6c, 0x65, 0x78, 0x20, 0x4c, 0x61,
94 0x6e, 0x67, 0x00 };
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,
115 0x02, 0x01, 0x01 };
116 static const BYTE bigCert2Hash[] = { 0x4a, 0x7f, 0x32, 0x1f, 0xcf, 0x3b, 0xc0,
117 0x87, 0x48, 0x2b, 0xa1, 0x86, 0x54, 0x18, 0xe4, 0x3a, 0x0e, 0x53, 0x7e, 0x2b };
119 static const BYTE certWithUsage[] = { 0x30, 0x81, 0x93, 0x02, 0x01, 0x01, 0x30,
120 0x02, 0x06, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04,
121 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00,
122 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30,
123 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30,
124 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31,
125 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61,
126 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00,
127 0x03, 0x01, 0x00, 0xa3, 0x2f, 0x30, 0x2d, 0x30, 0x2b, 0x06, 0x03, 0x55, 0x1d,
128 0x25, 0x01, 0x01, 0xff, 0x04, 0x21, 0x30, 0x1f, 0x06, 0x08, 0x2b, 0x06, 0x01,
129 0x05, 0x05, 0x07, 0x03, 0x03, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07,
130 0x03, 0x02, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01 };
132 static void testAddCert(void)
134 HCERTSTORE store;
136 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
137 CERT_STORE_CREATE_NEW_FLAG, NULL);
138 ok(store != NULL, "CertOpenStore failed: %ld\n", GetLastError());
139 if (store != NULL)
141 HCERTSTORE collection;
142 PCCERT_CONTEXT context;
143 BOOL ret;
145 /* Weird--bad add disposition leads to an access violation in Windows.
147 ret = CertAddEncodedCertificateToStore(0, X509_ASN_ENCODING, bigCert,
148 sizeof(bigCert), 0, NULL);
149 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
150 "Expected STATUS_ACCESS_VIOLATION, got %08lx\n", GetLastError());
151 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
152 bigCert, sizeof(bigCert), 0, NULL);
153 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
154 "Expected STATUS_ACCESS_VIOLATION, got %08lx\n", GetLastError());
156 /* Weird--can add a cert to the NULL store (does this have special
157 * meaning?)
159 context = NULL;
160 ret = CertAddEncodedCertificateToStore(0, X509_ASN_ENCODING, bigCert,
161 sizeof(bigCert), CERT_STORE_ADD_ALWAYS, &context);
162 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n",
163 GetLastError());
164 if (context)
165 CertFreeCertificateContext(context);
167 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
168 bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL);
169 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n",
170 GetLastError());
171 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
172 bigCert2, sizeof(bigCert2), CERT_STORE_ADD_NEW, NULL);
173 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n",
174 GetLastError());
175 /* This has the same name as bigCert, so finding isn't done by name */
176 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
177 certWithUsage, sizeof(certWithUsage), CERT_STORE_ADD_NEW, &context);
178 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n",
179 GetLastError());
180 ok(context != NULL, "Expected a context\n");
181 if (context)
183 CRYPT_DATA_BLOB hash = { sizeof(bigCert2Hash),
184 (LPBYTE)bigCert2Hash };
186 /* Duplicate (AddRef) the context so we can still use it after
187 * deleting it from the store.
189 CertDuplicateCertificateContext(context);
190 CertDeleteCertificateFromStore(context);
191 /* Set the same hash as bigCert2, and try to readd it */
192 ret = CertSetCertificateContextProperty(context, CERT_HASH_PROP_ID,
193 0, &hash);
194 ok(ret, "CertSetCertificateContextProperty failed: %08lx\n",
195 GetLastError());
196 ret = CertAddCertificateContextToStore(store, context,
197 CERT_STORE_ADD_NEW, NULL);
198 /* The failure is a bit odd (CRYPT_E_ASN1_BADTAG), so just check
199 * that it fails.
201 ok(!ret, "Expected failure\n");
202 CertFreeCertificateContext(context);
204 context = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert2,
205 sizeof(bigCert2));
206 ok(context != NULL, "Expected a context\n");
207 if (context)
209 /* Try to readd bigCert2 to the store */
210 ret = CertAddCertificateContextToStore(store, context,
211 CERT_STORE_ADD_NEW, NULL);
212 ok(!ret && GetLastError() == CRYPT_E_EXISTS,
213 "Expected CRYPT_E_EXISTS, got %08lx\n", GetLastError());
214 CertFreeCertificateContext(context);
217 /* Adding a cert with the same issuer name and serial number (but
218 * different subject) as an existing cert succeeds.
220 context = NULL;
221 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
222 bigCert2WithDifferentSerial, sizeof(bigCert2WithDifferentSerial),
223 CERT_STORE_ADD_NEW, &context);
224 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n",
225 GetLastError());
226 if (context)
227 CertDeleteCertificateFromStore(context);
229 /* Adding a cert with the same subject name and serial number (but
230 * different issuer) as an existing cert succeeds.
232 context = NULL;
233 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
234 bigCertWithDifferentSubject, sizeof(bigCertWithDifferentSubject),
235 CERT_STORE_ADD_NEW, &context);
236 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n",
237 GetLastError());
238 if (context)
239 CertDeleteCertificateFromStore(context);
241 /* Adding a cert with the same issuer name and serial number (but
242 * different otherwise) as an existing cert succeeds.
244 context = NULL;
245 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
246 bigCertWithDifferentIssuer, sizeof(bigCertWithDifferentIssuer),
247 CERT_STORE_ADD_NEW, &context);
248 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n",
249 GetLastError());
250 if (context)
251 CertDeleteCertificateFromStore(context);
253 collection = CertOpenStore(CERT_STORE_PROV_COLLECTION, 0, 0,
254 CERT_STORE_CREATE_NEW_FLAG, NULL);
255 ok(collection != NULL, "CertOpenStore failed: %08lx\n", GetLastError());
256 if (collection)
258 /* Add store to the collection, but disable updates */
259 CertAddStoreToCollection(collection, store, 0, 0);
261 context = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert2,
262 sizeof(bigCert2));
263 ok(context != NULL, "Expected a context\n");
264 if (context)
266 /* Try to readd bigCert2 to the collection */
267 ret = CertAddCertificateContextToStore(collection, context,
268 CERT_STORE_ADD_NEW, NULL);
269 ok(!ret && GetLastError() == CRYPT_E_EXISTS,
270 "Expected CRYPT_E_EXISTS, got %08lx\n", GetLastError());
271 /* Replacing an existing certificate context is allowed, even
272 * though updates to the collection aren't..
274 ret = CertAddCertificateContextToStore(collection, context,
275 CERT_STORE_ADD_REPLACE_EXISTING, NULL);
276 ok(ret, "CertAddCertificateContextToStore failed: %08lx\n",
277 GetLastError());
278 /* but adding a new certificate isn't allowed. */
279 ret = CertAddCertificateContextToStore(collection, context,
280 CERT_STORE_ADD_ALWAYS, NULL);
281 ok(!ret && GetLastError() == E_ACCESSDENIED,
282 "Expected E_ACCESSDENIED, got %08lx\n", GetLastError());
283 CertFreeCertificateContext(context);
286 CertCloseStore(collection, 0);
289 CertCloseStore(store, 0);
293 static void checkHash(const BYTE *data, DWORD dataLen, ALG_ID algID,
294 PCCERT_CONTEXT context, DWORD propID)
296 BYTE hash[20] = { 0 }, hashProperty[20];
297 BOOL ret;
298 DWORD size;
300 memset(hash, 0, sizeof(hash));
301 memset(hashProperty, 0, sizeof(hashProperty));
302 size = sizeof(hash);
303 ret = CryptHashCertificate(0, algID, 0, data, dataLen, hash, &size);
304 ok(ret, "CryptHashCertificate failed: %08lx\n", GetLastError());
305 ret = CertGetCertificateContextProperty(context, propID, hashProperty,
306 &size);
307 ok(ret, "CertGetCertificateContextProperty failed: %08lx\n",
308 GetLastError());
309 ok(!memcmp(hash, hashProperty, size), "Unexpected hash for property %ld\n",
310 propID);
313 static const WCHAR cspNameW[] = { 'W','i','n','e','C','r','y','p','t','T','e',
314 'm','p',0 };
316 static void testCertProperties(void)
318 PCCERT_CONTEXT context = CertCreateCertificateContext(X509_ASN_ENCODING,
319 bigCert, sizeof(bigCert));
321 ok(context != NULL, "CertCreateCertificateContext failed: %08lx\n",
322 GetLastError());
323 if (context)
325 DWORD propID, numProps, access, size;
326 BOOL ret;
327 BYTE hash[20] = { 0 }, hashProperty[20];
328 CRYPT_DATA_BLOB blob;
329 CERT_KEY_CONTEXT keyContext;
330 HCRYPTPROV csp;
332 /* This crashes
333 propID = CertEnumCertificateContextProperties(NULL, 0);
336 propID = 0;
337 numProps = 0;
338 do {
339 propID = CertEnumCertificateContextProperties(context, propID);
340 if (propID)
341 numProps++;
342 } while (propID != 0);
343 ok(numProps == 0, "Expected 0 properties, got %ld\n", numProps);
345 /* Tests with a NULL cert context. Prop ID 0 fails.. */
346 ret = CertSetCertificateContextProperty(NULL, 0, 0, NULL);
347 ok(!ret && GetLastError() == E_INVALIDARG,
348 "Expected E_INVALIDARG, got %08lx\n", GetLastError());
349 /* while this just crashes.
350 ret = CertSetCertificateContextProperty(NULL,
351 CERT_KEY_PROV_HANDLE_PROP_ID, 0, NULL);
354 ret = CertSetCertificateContextProperty(context, 0, 0, NULL);
355 ok(!ret && GetLastError() == E_INVALIDARG,
356 "Expected E_INVALIDARG, got %08lx\n", GetLastError());
357 /* Can't set the cert property directly, this crashes.
358 ret = CertSetCertificateContextProperty(context,
359 CERT_CERT_PROP_ID, 0, bigCert2);
362 /* These all crash.
363 ret = CertGetCertificateContextProperty(context,
364 CERT_ACCESS_STATE_PROP_ID, 0, NULL);
365 ret = CertGetCertificateContextProperty(context, CERT_HASH_PROP_ID,
366 NULL, NULL);
367 ret = CertGetCertificateContextProperty(context, CERT_HASH_PROP_ID,
368 hashProperty, NULL);
370 /* A missing prop */
371 size = 0;
372 ret = CertGetCertificateContextProperty(context,
373 CERT_KEY_PROV_INFO_PROP_ID, NULL, &size);
374 ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
375 "Expected CRYPT_E_NOT_FOUND, got %08lx\n", GetLastError());
376 /* And, an implicit property */
377 size = sizeof(access);
378 ret = CertGetCertificateContextProperty(context,
379 CERT_ACCESS_STATE_PROP_ID, &access, &size);
380 ok(ret, "CertGetCertificateContextProperty failed: %08lx\n",
381 GetLastError());
382 ok(!(access & CERT_ACCESS_STATE_WRITE_PERSIST_FLAG),
383 "Didn't expect a persisted cert\n");
384 /* Trying to set this "read only" property crashes.
385 access |= CERT_ACCESS_STATE_WRITE_PERSIST_FLAG;
386 ret = CertSetCertificateContextProperty(context,
387 CERT_ACCESS_STATE_PROP_ID, 0, &access);
390 /* Can I set the hash to an invalid hash? */
391 blob.pbData = hash;
392 blob.cbData = sizeof(hash);
393 ret = CertSetCertificateContextProperty(context, CERT_HASH_PROP_ID, 0,
394 &blob);
395 ok(ret, "CertSetCertificateContextProperty failed: %08lx\n",
396 GetLastError());
397 size = sizeof(hashProperty);
398 ret = CertGetCertificateContextProperty(context, CERT_HASH_PROP_ID,
399 hashProperty, &size);
400 ok(!memcmp(hashProperty, hash, sizeof(hash)), "Unexpected hash\n");
401 /* Delete the (bogus) hash, and get the real one */
402 ret = CertSetCertificateContextProperty(context, CERT_HASH_PROP_ID, 0,
403 NULL);
404 ok(ret, "CertSetCertificateContextProperty failed: %08lx\n",
405 GetLastError());
406 checkHash(bigCert, sizeof(bigCert), CALG_SHA1, context,
407 CERT_HASH_PROP_ID);
409 /* Now that the hash property is set, we should get one property when
410 * enumerating.
412 propID = 0;
413 numProps = 0;
414 do {
415 propID = CertEnumCertificateContextProperties(context, propID);
416 if (propID)
417 numProps++;
418 } while (propID != 0);
419 ok(numProps == 1, "Expected 1 properties, got %ld\n", numProps);
421 /* Check a few other implicit properties */
422 checkHash(bigCert, sizeof(bigCert), CALG_MD5, context,
423 CERT_MD5_HASH_PROP_ID);
424 checkHash(
425 context->pCertInfo->Subject.pbData,
426 context->pCertInfo->Subject.cbData,
427 CALG_MD5, context, CERT_SUBJECT_NAME_MD5_HASH_PROP_ID);
428 checkHash(
429 context->pCertInfo->SubjectPublicKeyInfo.PublicKey.pbData,
430 context->pCertInfo->SubjectPublicKeyInfo.PublicKey.cbData,
431 CALG_MD5, context, CERT_SUBJECT_PUBLIC_KEY_MD5_HASH_PROP_ID);
433 /* Test key identifiers and handles and such */
434 size = 0;
435 ret = CertGetCertificateContextProperty(context,
436 CERT_KEY_IDENTIFIER_PROP_ID, NULL, &size);
437 ok(!ret && GetLastError() == ERROR_INVALID_DATA,
438 "Expected ERROR_INVALID_DATA, got %08lx\n", GetLastError());
439 size = sizeof(CERT_KEY_CONTEXT);
440 ret = CertGetCertificateContextProperty(context,
441 CERT_KEY_IDENTIFIER_PROP_ID, NULL, &size);
442 ok(!ret && GetLastError() == ERROR_INVALID_DATA,
443 "Expected ERROR_INVALID_DATA, got %08lx\n", GetLastError());
444 ret = CertGetCertificateContextProperty(context,
445 CERT_KEY_IDENTIFIER_PROP_ID, &keyContext, &size);
446 ok(!ret && GetLastError() == ERROR_INVALID_DATA,
447 "Expected ERROR_INVALID_DATA, got %08lx\n", GetLastError());
448 /* Key context with an invalid size */
449 keyContext.cbSize = 0;
450 ret = CertSetCertificateContextProperty(context,
451 CERT_KEY_IDENTIFIER_PROP_ID, 0, &keyContext);
452 ok(ret, "CertSetCertificateContextProperty failed: %08lx\n",
453 GetLastError());
454 size = sizeof(keyContext);
455 ret = CertGetCertificateContextProperty(context,
456 CERT_KEY_IDENTIFIER_PROP_ID, &keyContext, &size);
457 ok(ret, "CertGetCertificateContextProperty failed: %08lx\n",
458 GetLastError());
459 keyContext.cbSize = sizeof(keyContext);
460 keyContext.hCryptProv = 0;
461 keyContext.dwKeySpec = AT_SIGNATURE;
462 /* Crash
463 ret = CertSetCertificateContextProperty(context,
464 CERT_KEY_IDENTIFIER_PROP_ID, 0, &keyContext);
465 ret = CertSetCertificateContextProperty(context,
466 CERT_KEY_IDENTIFIER_PROP_ID, CERT_STORE_NO_CRYPT_RELEASE_FLAG,
467 &keyContext);
469 ret = CryptAcquireContextW(&csp, cspNameW,
470 MS_DEF_PROV_W, PROV_RSA_FULL, CRYPT_NEWKEYSET);
471 ok(ret, "CryptAcquireContextW failed: %08lx\n", GetLastError());
472 keyContext.hCryptProv = csp;
473 ret = CertSetCertificateContextProperty(context,
474 CERT_KEY_CONTEXT_PROP_ID, 0, &keyContext);
475 ok(ret, "CertSetCertificateContextProperty failed: %08lx\n",
476 GetLastError());
477 /* Now that that's set, the key prov handle property is also gettable.
479 size = sizeof(DWORD);
480 ret = CertGetCertificateContextProperty(context,
481 CERT_KEY_PROV_HANDLE_PROP_ID, &keyContext.hCryptProv, &size);
482 ok(ret, "Expected to get the CERT_KEY_PROV_HANDLE_PROP_ID, got %08lx\n",
483 GetLastError());
484 /* Remove the key prov handle property.. */
485 ret = CertSetCertificateContextProperty(context,
486 CERT_KEY_PROV_HANDLE_PROP_ID, 0, NULL);
487 ok(ret, "CertSetCertificateContextProperty failed: %08lx\n",
488 GetLastError());
489 /* and the key context's CSP is set to NULL. */
490 size = sizeof(keyContext);
491 ret = CertGetCertificateContextProperty(context,
492 CERT_KEY_CONTEXT_PROP_ID, &keyContext, &size);
493 ok(ret, "CertGetCertificateContextProperty failed: %08lx\n",
494 GetLastError());
495 ok(keyContext.hCryptProv == 0, "Expected no hCryptProv\n");
497 CryptReleaseContext(csp, 0);
499 CertFreeCertificateContext(context);
503 static void testDupCert(void)
505 HCERTSTORE store;
507 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
508 CERT_STORE_CREATE_NEW_FLAG, NULL);
509 ok(store != NULL, "CertOpenStore failed: %ld\n", GetLastError());
510 if (store != NULL)
512 PCCERT_CONTEXT context, dupContext;
513 BOOL ret;
515 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
516 bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, &context);
517 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n",
518 GetLastError());
519 ok(context != NULL, "Expected a valid cert context\n");
520 if (context)
522 ok(context->cbCertEncoded == sizeof(bigCert),
523 "Wrong cert size %ld\n", context->cbCertEncoded);
524 ok(!memcmp(context->pbCertEncoded, bigCert, sizeof(bigCert)),
525 "Unexpected encoded cert in context\n");
526 ok(context->hCertStore == store, "Unexpected store\n");
528 dupContext = CertDuplicateCertificateContext(context);
529 ok(dupContext != NULL, "Expected valid duplicate\n");
530 /* Not only is it a duplicate, it's identical: the address is the
531 * same.
533 ok(dupContext == context, "Expected identical context addresses\n");
534 CertFreeCertificateContext(dupContext);
535 CertFreeCertificateContext(context);
537 CertCloseStore(store, 0);
541 static void testFindCert(void)
543 HCERTSTORE store;
545 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
546 CERT_STORE_CREATE_NEW_FLAG, NULL);
547 ok(store != NULL, "CertOpenStore failed: %ld\n", GetLastError());
548 if (store)
550 PCCERT_CONTEXT context = NULL;
551 BOOL ret;
552 CERT_INFO certInfo = { 0 };
553 CRYPT_HASH_BLOB blob;
555 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
556 bigCert, sizeof(bigCert), CERT_STORE_ADD_NEW, NULL);
557 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n",
558 GetLastError());
559 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
560 bigCert2, sizeof(bigCert2), CERT_STORE_ADD_NEW, NULL);
561 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n",
562 GetLastError());
563 /* This has the same name as bigCert */
564 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
565 certWithUsage, sizeof(certWithUsage), CERT_STORE_ADD_NEW, NULL);
566 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n",
567 GetLastError());
569 /* Crashes
570 context = CertFindCertificateInStore(NULL, 0, 0, 0, NULL, NULL);
573 /* Check first cert's there, by issuer */
574 certInfo.Subject.pbData = (LPBYTE)subjectName;
575 certInfo.Subject.cbData = sizeof(subjectName);
576 certInfo.SerialNumber.pbData = (LPBYTE)serialNum;
577 certInfo.SerialNumber.cbData = sizeof(serialNum);
578 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
579 CERT_FIND_ISSUER_NAME, &certInfo.Subject, NULL);
580 ok(context != NULL, "CertFindCertificateInStore failed: %08lx\n",
581 GetLastError());
582 if (context)
584 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
585 CERT_FIND_ISSUER_NAME, &certInfo.Subject, context);
586 ok(context != NULL, "Expected more than one cert\n");
587 if (context)
589 context = CertFindCertificateInStore(store, X509_ASN_ENCODING,
590 0, CERT_FIND_ISSUER_NAME, &certInfo.Subject, context);
591 ok(context == NULL, "Expected precisely two certs\n");
595 /* Check second cert's there as well, by subject name */
596 certInfo.Subject.pbData = (LPBYTE)subjectName2;
597 certInfo.Subject.cbData = sizeof(subjectName2);
598 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
599 CERT_FIND_SUBJECT_NAME, &certInfo.Subject, NULL);
600 ok(context != NULL, "CertFindCertificateInStore failed: %08lx\n",
601 GetLastError());
602 if (context)
604 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
605 CERT_FIND_ISSUER_NAME, &certInfo.Subject, context);
606 ok(context == NULL, "Expected one cert only\n");
609 /* Strange but true: searching for the subject cert requires you to set
610 * the issuer, not the subject
612 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
613 CERT_FIND_SUBJECT_CERT, &certInfo.Subject, NULL);
614 ok(context == NULL, "Expected no certificate\n");
615 certInfo.Subject.pbData = NULL;
616 certInfo.Subject.cbData = 0;
617 certInfo.Issuer.pbData = (LPBYTE)subjectName2;
618 certInfo.Issuer.cbData = sizeof(subjectName2);
619 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
620 CERT_FIND_SUBJECT_CERT, &certInfo, NULL);
621 ok(context != NULL, "CertFindCertificateInStore failed: %08lx\n",
622 GetLastError());
623 if (context)
625 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
626 CERT_FIND_ISSUER_NAME, &certInfo.Subject, context);
627 ok(context == NULL, "Expected one cert only\n");
630 /* The nice thing about hashes, they're unique */
631 blob.pbData = (LPBYTE)bigCertHash;
632 blob.cbData = sizeof(bigCertHash);
633 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
634 CERT_FIND_SHA1_HASH, &blob, NULL);
635 ok(context != NULL, "CertFindCertificateInStore failed: %08lx\n",
636 GetLastError());
637 if (context)
639 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
640 CERT_FIND_ISSUER_NAME, &certInfo.Subject, context);
641 ok(context == NULL, "Expected one cert only\n");
644 CertCloseStore(store, 0);
648 static void testGetSubjectCert(void)
650 HCERTSTORE store;
652 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
653 CERT_STORE_CREATE_NEW_FLAG, NULL);
654 ok(store != NULL, "CertOpenStore failed: %ld\n", GetLastError());
655 if (store != NULL)
657 PCCERT_CONTEXT context1, context2;
658 CERT_INFO info = { 0 };
659 BOOL ret;
661 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
662 bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL);
663 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n",
664 GetLastError());
665 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
666 bigCert2, sizeof(bigCert2), CERT_STORE_ADD_NEW, &context1);
667 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n",
668 GetLastError());
669 ok(context1 != NULL, "Expected a context\n");
670 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
671 certWithUsage, sizeof(certWithUsage), CERT_STORE_ADD_NEW, NULL);
672 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n",
673 GetLastError());
675 context2 = CertGetSubjectCertificateFromStore(store, X509_ASN_ENCODING,
676 NULL);
677 ok(!context2 && GetLastError() == E_INVALIDARG,
678 "Expected E_INVALIDARG, got %08lx\n", GetLastError());
679 context2 = CertGetSubjectCertificateFromStore(store, X509_ASN_ENCODING,
680 &info);
681 ok(!context2 && GetLastError() == CRYPT_E_NOT_FOUND,
682 "Expected CRYPT_E_NOT_FOUND, got %08lx\n", GetLastError());
683 info.SerialNumber.cbData = sizeof(serialNum);
684 info.SerialNumber.pbData = (LPBYTE)serialNum;
685 context2 = CertGetSubjectCertificateFromStore(store, X509_ASN_ENCODING,
686 &info);
687 ok(!context2 && GetLastError() == CRYPT_E_NOT_FOUND,
688 "Expected CRYPT_E_NOT_FOUND, got %08lx\n", GetLastError());
689 info.Issuer.cbData = sizeof(subjectName2);
690 info.Issuer.pbData = (LPBYTE)subjectName2;
691 context2 = CertGetSubjectCertificateFromStore(store, X509_ASN_ENCODING,
692 &info);
693 ok(context2 != NULL,
694 "CertGetSubjectCertificateFromStore failed: %08lx\n", GetLastError());
695 /* Not only should this find a context, but it should be the same
696 * (same address) as context1.
698 ok(context1 == context2, "Expected identical context addresses\n");
699 CertFreeCertificateContext(context2);
701 CertFreeCertificateContext(context1);
702 CertCloseStore(store, 0);
706 /* This expires in 1970 or so */
707 static const BYTE expiredCert[] = { 0x30, 0x82, 0x01, 0x33, 0x30, 0x81, 0xe2,
708 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0xc4, 0xd7, 0x7f, 0x0e, 0x6f, 0xa6,
709 0x8c, 0xaa, 0x47, 0x47, 0x40, 0xe7, 0xb7, 0x0b, 0x4a, 0x7f, 0x30, 0x09, 0x06,
710 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1d, 0x05, 0x00, 0x30, 0x1f, 0x31, 0x1d, 0x30,
711 0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63, 0x40,
712 0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63,
713 0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x36, 0x39, 0x30, 0x31, 0x30, 0x31, 0x30,
714 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x37, 0x30, 0x30, 0x31, 0x30,
715 0x31, 0x30, 0x36, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x1f, 0x31, 0x1d, 0x30,
716 0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63, 0x40,
717 0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63,
718 0x6f, 0x6d, 0x30, 0x5c, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
719 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x4b, 0x00, 0x30, 0x48, 0x02, 0x41,
720 0x00, 0xa1, 0xaf, 0x4a, 0xea, 0xa7, 0x83, 0x57, 0xc0, 0x37, 0x33, 0x7e, 0x29,
721 0x5e, 0x0d, 0xfc, 0x44, 0x74, 0x3a, 0x1d, 0xc3, 0x1b, 0x1d, 0x96, 0xed, 0x4e,
722 0xf4, 0x1b, 0x98, 0xec, 0x69, 0x1b, 0x04, 0xea, 0x25, 0xcf, 0xb3, 0x2a, 0xf5,
723 0xd9, 0x22, 0xd9, 0x8d, 0x08, 0x39, 0x81, 0xc6, 0xe0, 0x4f, 0x12, 0x37, 0x2a,
724 0x3f, 0x80, 0xa6, 0x6c, 0x67, 0x43, 0x3a, 0xdd, 0x95, 0x0c, 0xbb, 0x2f, 0x6b,
725 0x02, 0x03, 0x01, 0x00, 0x01, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02,
726 0x1d, 0x05, 0x00, 0x03, 0x41, 0x00, 0x8f, 0xa2, 0x5b, 0xd6, 0xdf, 0x34, 0xd0,
727 0xa2, 0xa7, 0x47, 0xf1, 0x13, 0x79, 0xd3, 0xf3, 0x39, 0xbd, 0x4e, 0x2b, 0xa3,
728 0xf4, 0x63, 0x37, 0xac, 0x5a, 0x0c, 0x5e, 0x4d, 0x0d, 0x54, 0x87, 0x4f, 0x31,
729 0xfb, 0xa0, 0xce, 0x8f, 0x9a, 0x2f, 0x4d, 0x48, 0xc6, 0x84, 0x8d, 0xf5, 0x70,
730 0x74, 0x17, 0xa5, 0xf3, 0x66, 0x47, 0x06, 0xd6, 0x64, 0x45, 0xbc, 0x52, 0xef,
731 0x49, 0xe5, 0xf9, 0x65, 0xf3 };
733 /* This expires in 2036 or so */
734 static const BYTE childOfExpired[] = { 0x30, 0x81, 0xcc, 0x30, 0x78, 0xa0,
735 0x03, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86,
736 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x1f, 0x31, 0x1d,
737 0x30, 0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63,
738 0x40, 0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e,
739 0x63, 0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x30, 0x36, 0x30, 0x35, 0x30, 0x35,
740 0x31, 0x37, 0x31, 0x32, 0x34, 0x39, 0x5a, 0x17, 0x0d, 0x33, 0x36, 0x30, 0x35,
741 0x30, 0x35, 0x31, 0x37, 0x31, 0x32, 0x34, 0x39, 0x5a, 0x30, 0x15, 0x31, 0x13,
742 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e,
743 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03,
744 0x01, 0x00, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
745 0x01, 0x05, 0x05, 0x00, 0x03, 0x41, 0x00, 0x20, 0x3b, 0xdb, 0x4d, 0x67, 0x50,
746 0xec, 0x73, 0x9d, 0xf9, 0x85, 0x5d, 0x18, 0xe9, 0xb4, 0x98, 0xe3, 0x31, 0xb7,
747 0x03, 0x0b, 0xc0, 0x39, 0x93, 0x56, 0x81, 0x0a, 0xfc, 0x78, 0xa8, 0x29, 0x42,
748 0x5f, 0x69, 0xfb, 0xbc, 0x5b, 0xf2, 0xa6, 0x2a, 0xbe, 0x91, 0x2c, 0xfc, 0x89,
749 0x69, 0x15, 0x18, 0x58, 0xe5, 0x02, 0x75, 0xf7, 0x2a, 0xb6, 0xa9, 0xfb, 0x47,
750 0x6a, 0x6e, 0x0a, 0x9b, 0xe9, 0xdc };
752 static void testGetIssuerCert(void)
754 BOOL ret;
755 PCCERT_CONTEXT parent, child;
756 DWORD flags = 0xffffffff;
757 HCERTSTORE store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
758 CERT_STORE_CREATE_NEW_FLAG, NULL);
760 ok(store != NULL, "CertOpenStore failed: %08lx\n", GetLastError());
762 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
763 expiredCert, sizeof(expiredCert), CERT_STORE_ADD_ALWAYS, NULL);
764 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n",
765 GetLastError());
767 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
768 childOfExpired, sizeof(childOfExpired), CERT_STORE_ADD_ALWAYS, &child);
769 ok(ret, "CertAddEncodedCertificateToStore failed: %08lx\n",
770 GetLastError());
772 /* These crash:
773 parent = CertGetIssuerCertificateFromStore(NULL, NULL, NULL, NULL);
774 parent = CertGetIssuerCertificateFromStore(store, NULL, NULL, NULL);
776 parent = CertGetIssuerCertificateFromStore(NULL, NULL, NULL, &flags);
777 ok(!parent && GetLastError() == E_INVALIDARG,
778 "Expected E_INVALIDARG, got %08lx\n", GetLastError());
779 parent = CertGetIssuerCertificateFromStore(store, NULL, NULL, &flags);
780 ok(!parent && GetLastError() == E_INVALIDARG,
781 "Expected E_INVALIDARG, got %08lx\n", GetLastError());
782 parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
783 ok(!parent && GetLastError() == E_INVALIDARG,
784 "Expected E_INVALIDARG, got %08lx\n", GetLastError());
785 /* Confusing: the caller cannot set either of the
786 * CERT_STORE_NO_*_FLAGs, as these are not checks,
787 * they're results:
789 flags = CERT_STORE_NO_CRL_FLAG | CERT_STORE_NO_ISSUER_FLAG;
790 parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
791 ok(!parent && GetLastError() == E_INVALIDARG,
792 "Expected E_INVALIDARG, got %08lx\n", GetLastError());
793 /* Perform no checks */
794 flags = 0;
795 parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
796 ok(parent != NULL, "CertGetIssuerCertificateFromStore failed: %08lx\n",
797 GetLastError());
798 if (parent)
799 CertFreeCertificateContext(parent);
800 /* Check revocation and signature only */
801 flags = CERT_STORE_REVOCATION_FLAG | CERT_STORE_SIGNATURE_FLAG;
802 parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
803 ok(parent != NULL, "CertGetIssuerCertificateFromStore failed: %08lx\n",
804 GetLastError());
805 /* Confusing: CERT_STORE_REVOCATION_FLAG succeeds when there is no CRL by
806 * setting CERT_STORE_NO_CRL_FLAG.
808 ok(flags == (CERT_STORE_REVOCATION_FLAG | CERT_STORE_NO_CRL_FLAG),
809 "Expected CERT_STORE_REVOCATION_FLAG | CERT_STORE_NO_CRL_FLAG, got %08lx\n",
810 flags);
811 if (parent)
812 CertFreeCertificateContext(parent);
813 /* Now check just the time */
814 flags = CERT_STORE_TIME_VALIDITY_FLAG;
815 parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
816 ok(parent != NULL, "CertGetIssuerCertificateFromStore failed: %08lx\n",
817 GetLastError());
818 /* Oops: the child is not expired, so the time validity check actually
819 * succeeds, even though the signing cert is expired.
821 ok(!flags, "Expected check to succeed, got %08lx\n", flags);
822 if (parent)
823 CertFreeCertificateContext(parent);
825 CertFreeCertificateContext(child);
826 CertCloseStore(store, 0);
829 static void testCryptHashCert(void)
831 static const BYTE emptyHash[] = { 0xda, 0x39, 0xa3, 0xee, 0x5e, 0x6b, 0x4b,
832 0x0d, 0x32, 0x55, 0xbf, 0xef, 0x95, 0x60, 0x18, 0x90, 0xaf, 0xd8, 0x07,
833 0x09 };
834 static const BYTE knownHash[] = { 0xae, 0x9d, 0xbf, 0x6d, 0xf5, 0x46, 0xee,
835 0x8b, 0xc5, 0x7a, 0x13, 0xba, 0xc2, 0xb1, 0x04, 0xf2, 0xbf, 0x52, 0xa8,
836 0xa2 };
837 static const BYTE toHash[] = "abcdefghijklmnopqrstuvwxyz0123456789.,;!?:";
838 BOOL ret;
839 BYTE hash[20];
840 DWORD hashLen = sizeof(hash);
842 /* NULL buffer and nonzero length crashes
843 ret = CryptHashCertificate(0, 0, 0, NULL, size, hash, &hashLen);
844 empty hash length also crashes
845 ret = CryptHashCertificate(0, 0, 0, buf, size, hash, NULL);
847 /* Test empty hash */
848 ret = CryptHashCertificate(0, 0, 0, toHash, sizeof(toHash), NULL,
849 &hashLen);
850 ok(ret, "CryptHashCertificate failed: %08lx\n", GetLastError());
851 ok(hashLen == sizeof(hash), "Got unexpected size of hash %ld\n", hashLen);
852 /* Test with empty buffer */
853 ret = CryptHashCertificate(0, 0, 0, NULL, 0, hash, &hashLen);
854 ok(ret, "CryptHashCertificate failed: %08lx\n", GetLastError());
855 ok(!memcmp(hash, emptyHash, sizeof(emptyHash)),
856 "Unexpected hash of nothing\n");
857 /* Test a known value */
858 ret = CryptHashCertificate(0, 0, 0, toHash, sizeof(toHash), hash,
859 &hashLen);
860 ok(ret, "CryptHashCertificate failed: %08lx\n", GetLastError());
861 ok(!memcmp(hash, knownHash, sizeof(knownHash)), "Unexpected hash\n");
864 static void verifySig(HCRYPTPROV csp, const BYTE *toSign, size_t toSignLen,
865 const BYTE *sig, unsigned int sigLen)
867 HCRYPTHASH hash;
868 BOOL ret = CryptCreateHash(csp, CALG_SHA1, 0, 0, &hash);
870 ok(ret, "CryptCreateHash failed: %08lx\n", GetLastError());
871 if (ret)
873 BYTE mySig[64];
874 DWORD mySigSize = sizeof(mySig);
876 ret = CryptHashData(hash, toSign, toSignLen, 0);
877 ok(ret, "CryptHashData failed: %08lx\n", GetLastError());
878 /* use the A variant so the test can run on Win9x */
879 ret = CryptSignHashA(hash, AT_SIGNATURE, NULL, 0, mySig, &mySigSize);
880 ok(ret, "CryptSignHash failed: %08lx\n", GetLastError());
881 if (ret)
883 ok(mySigSize == sigLen, "Expected sig length %d, got %ld\n",
884 sigLen, mySigSize);
885 ok(!memcmp(mySig, sig, sigLen), "Unexpected signature\n");
887 CryptDestroyHash(hash);
891 /* Tests signing the certificate described by toBeSigned with the CSP passed in,
892 * using the algorithm with OID sigOID. The CSP is assumed to be empty, and a
893 * keyset named AT_SIGNATURE will be added to it. The signing key will be
894 * stored in *key, and the signature will be stored in sig. sigLen should be
895 * at least 64 bytes.
897 static void testSignCert(HCRYPTPROV csp, const CRYPT_DATA_BLOB *toBeSigned,
898 LPCSTR sigOID, HCRYPTKEY *key, BYTE *sig, DWORD *sigLen)
900 BOOL ret;
901 DWORD size = 0;
902 CRYPT_ALGORITHM_IDENTIFIER algoID = { NULL, { 0, NULL } };
904 /* These all crash
905 ret = CryptSignCertificate(0, 0, 0, NULL, 0, NULL, NULL, NULL, NULL);
906 ret = CryptSignCertificate(0, 0, 0, NULL, 0, NULL, NULL, NULL, &size);
907 ret = CryptSignCertificate(0, 0, 0, toBeSigned->pbData, toBeSigned->cbData,
908 NULL, NULL, NULL, &size);
910 ret = CryptSignCertificate(0, 0, 0, toBeSigned->pbData, toBeSigned->cbData,
911 &algoID, NULL, NULL, &size);
912 ok(!ret && GetLastError() == NTE_BAD_ALGID,
913 "Expected NTE_BAD_ALGID, got %08lx\n", GetLastError());
914 algoID.pszObjId = (LPSTR)sigOID;
915 ret = CryptSignCertificate(0, 0, 0, toBeSigned->pbData, toBeSigned->cbData,
916 &algoID, NULL, NULL, &size);
917 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
918 "Expected ERROR_INVALID_PARAMETER, got %08lx\n", GetLastError());
919 ret = CryptSignCertificate(0, AT_SIGNATURE, 0, toBeSigned->pbData,
920 toBeSigned->cbData, &algoID, NULL, NULL, &size);
921 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
922 "Expected ERROR_INVALID_PARAMETER, got %08lx\n", GetLastError());
924 /* No keys exist in the new CSP yet.. */
925 ret = CryptSignCertificate(csp, AT_SIGNATURE, 0, toBeSigned->pbData,
926 toBeSigned->cbData, &algoID, NULL, NULL, &size);
927 ok(!ret && (GetLastError() == NTE_BAD_KEYSET || GetLastError() ==
928 NTE_NO_KEY), "Expected NTE_BAD_KEYSET or NTE_NO_KEY, got %08lx\n",
929 GetLastError());
930 ret = CryptGenKey(csp, AT_SIGNATURE, 0, key);
931 ok(ret, "CryptGenKey failed: %08lx\n", GetLastError());
932 if (ret)
934 ret = CryptSignCertificate(csp, AT_SIGNATURE, 0, toBeSigned->pbData,
935 toBeSigned->cbData, &algoID, NULL, NULL, &size);
936 ok(ret, "CryptSignCertificate failed: %08lx\n", GetLastError());
937 ok(size <= *sigLen, "Expected size <= %ld, got %ld\n", *sigLen, size);
938 if (ret)
940 ret = CryptSignCertificate(csp, AT_SIGNATURE, 0, toBeSigned->pbData,
941 toBeSigned->cbData, &algoID, NULL, sig, &size);
942 ok(ret, "CryptSignCertificate failed: %08lx\n", GetLastError());
943 if (ret)
945 *sigLen = size;
946 verifySig(csp, toBeSigned->pbData, toBeSigned->cbData, sig,
947 size);
953 static void testVerifyCertSig(HCRYPTPROV csp, const CRYPT_DATA_BLOB *toBeSigned,
954 LPCSTR sigOID, const BYTE *sig, DWORD sigLen)
956 CERT_SIGNED_CONTENT_INFO info;
957 LPBYTE cert = NULL;
958 DWORD size = 0;
959 BOOL ret;
961 if(pCryptVerifyCertificateSignatureEx) {
962 ret = pCryptVerifyCertificateSignatureEx(0, 0, 0, NULL, 0, NULL, 0, NULL);
963 ok(!ret && GetLastError() == E_INVALIDARG,
964 "Expected E_INVALIDARG, got %08lx\n", GetLastError());
965 ret = pCryptVerifyCertificateSignatureEx(csp, 0, 0, NULL, 0, NULL, 0, NULL);
966 ok(!ret && GetLastError() == E_INVALIDARG,
967 "Expected E_INVALIDARG, got %08lx\n", GetLastError());
968 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING, 0, NULL, 0,
969 NULL, 0, NULL);
970 ok(!ret && GetLastError() == E_INVALIDARG,
971 "Expected E_INVALIDARG, got %08lx\n", GetLastError());
972 /* This crashes
973 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
974 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, NULL, 0, NULL, 0, NULL);
977 info.ToBeSigned.cbData = toBeSigned->cbData;
978 info.ToBeSigned.pbData = toBeSigned->pbData;
979 info.SignatureAlgorithm.pszObjId = (LPSTR)sigOID;
980 info.SignatureAlgorithm.Parameters.cbData = 0;
981 info.Signature.cbData = sigLen;
982 info.Signature.pbData = (BYTE *)sig;
983 info.Signature.cUnusedBits = 0;
984 ret = CryptEncodeObjectEx(X509_ASN_ENCODING, X509_CERT, &info,
985 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&cert, &size);
986 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
987 if (cert)
989 CRYPT_DATA_BLOB certBlob = { 0, NULL };
990 PCERT_PUBLIC_KEY_INFO pubKeyInfo = NULL;
992 if(pCryptVerifyCertificateSignatureEx) {
993 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
994 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob, 0, NULL, 0, NULL);
995 ok(!ret && GetLastError() == CRYPT_E_ASN1_EOD,
996 "Expected CRYPT_E_ASN1_EOD, got %08lx\n", GetLastError());
997 certBlob.cbData = 1;
998 certBlob.pbData = (void *)0xdeadbeef;
999 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
1000 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob, 0, NULL, 0, NULL);
1001 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
1002 "Expected STATUS_ACCESS_VIOLATION, got %08lx\n", GetLastError());
1003 certBlob.cbData = size;
1004 certBlob.pbData = cert;
1005 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
1006 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob, 0, NULL, 0, NULL);
1007 ok(!ret && GetLastError() == E_INVALIDARG,
1008 "Expected E_INVALIDARG, got %08lx\n", GetLastError());
1009 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
1010 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob,
1011 CRYPT_VERIFY_CERT_SIGN_ISSUER_NULL, NULL, 0, NULL);
1012 ok(!ret && GetLastError() == E_INVALIDARG,
1013 "Expected E_INVALIDARG, got %08lx\n", GetLastError());
1014 /* This crashes
1015 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
1016 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob,
1017 CRYPT_VERIFY_CERT_SIGN_ISSUER_PUBKEY, NULL, 0, NULL);
1020 CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING,
1021 (LPSTR)sigOID, 0, NULL, NULL, &size);
1022 pubKeyInfo = HeapAlloc(GetProcessHeap(), 0, size);
1023 if (pubKeyInfo)
1025 ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE,
1026 X509_ASN_ENCODING, (LPSTR)sigOID, 0, NULL, pubKeyInfo, &size);
1027 ok(ret, "CryptExportKey failed: %08lx\n", GetLastError());
1028 if (ret && pCryptVerifyCertificateSignatureEx)
1030 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
1031 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob,
1032 CRYPT_VERIFY_CERT_SIGN_ISSUER_PUBKEY, pubKeyInfo, 0, NULL);
1033 ok(ret, "CryptVerifyCertificateSignatureEx failed: %08lx\n",
1034 GetLastError());
1036 HeapFree(GetProcessHeap(), 0, pubKeyInfo);
1038 LocalFree(cert);
1042 static const BYTE emptyCert[] = { 0x30, 0x00 };
1044 static void testCertSigs(void)
1046 HCRYPTPROV csp;
1047 CRYPT_DATA_BLOB toBeSigned = { sizeof(emptyCert), (LPBYTE)emptyCert };
1048 BOOL ret;
1049 HCRYPTKEY key;
1050 BYTE sig[64];
1051 DWORD sigSize = sizeof(sig);
1053 /* Just in case a previous run failed, delete this thing */
1054 CryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
1055 CRYPT_DELETEKEYSET);
1056 ret = CryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
1057 CRYPT_NEWKEYSET);
1058 ok(ret, "CryptAcquireContext failed: %08lx\n", GetLastError());
1060 testSignCert(csp, &toBeSigned, szOID_RSA_SHA1RSA, &key, sig, &sigSize);
1061 testVerifyCertSig(csp, &toBeSigned, szOID_RSA_SHA1RSA, sig, sigSize);
1063 CryptDestroyKey(key);
1064 CryptReleaseContext(csp, 0);
1065 ret = CryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
1066 CRYPT_DELETEKEYSET);
1069 static void testCreateSelfSignCert(void)
1071 PCCERT_CONTEXT context;
1072 CERT_NAME_BLOB name = { sizeof(subjectName), (LPBYTE)subjectName };
1073 HCRYPTPROV csp;
1074 BOOL ret;
1075 HCRYPTKEY key;
1077 /* This crashes:
1078 context = CertCreateSelfSignCertificate(0, NULL, 0, NULL, NULL, NULL, NULL,
1079 NULL);
1080 * Calling this with no first parameter creates a new key container, which
1081 * lasts beyond the test, so I don't test that. Nb: the generated key
1082 * name is a GUID.
1083 context = CertCreateSelfSignCertificate(0, &name, 0, NULL, NULL, NULL, NULL,
1084 NULL);
1087 /* Acquire a CSP */
1088 CryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
1089 CRYPT_DELETEKEYSET);
1090 ret = CryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
1091 CRYPT_NEWKEYSET);
1092 ok(ret, "CryptAcquireContext failed: %08lx\n", GetLastError());
1094 context = CertCreateSelfSignCertificate(csp, &name, 0, NULL, NULL, NULL,
1095 NULL, NULL);
1096 ok(!context && GetLastError() == NTE_NO_KEY,
1097 "Expected NTE_NO_KEY, got %08lx\n", GetLastError());
1098 ret = CryptGenKey(csp, AT_SIGNATURE, 0, &key);
1099 ok(ret, "CryptGenKey failed: %08lx\n", GetLastError());
1100 if (ret)
1102 context = CertCreateSelfSignCertificate(csp, &name, 0, NULL, NULL, NULL,
1103 NULL, NULL);
1104 ok(context != NULL, "CertCreateSelfSignCertificate failed: %08lx\n",
1105 GetLastError());
1106 if (context)
1108 DWORD size = 0;
1109 PCRYPT_KEY_PROV_INFO info;
1111 /* The context must have a key provider info property */
1112 ret = CertGetCertificateContextProperty(context,
1113 CERT_KEY_PROV_INFO_PROP_ID, NULL, &size);
1114 ok(ret && size, "Expected non-zero key provider info\n");
1115 if (size)
1117 info = HeapAlloc(GetProcessHeap(), 0, size);
1118 if (info)
1120 ret = CertGetCertificateContextProperty(context,
1121 CERT_KEY_PROV_INFO_PROP_ID, info, &size);
1122 ok(ret, "CertGetCertificateContextProperty failed: %08lx\n",
1123 GetLastError());
1124 if (ret)
1126 /* Sanity-check the key provider */
1127 ok(!lstrcmpW(info->pwszContainerName, cspNameW),
1128 "Unexpected key container\n");
1129 ok(!lstrcmpW(info->pwszProvName, MS_DEF_PROV_W),
1130 "Unexpected provider\n");
1131 ok(info->dwKeySpec == AT_SIGNATURE,
1132 "Expected AT_SIGNATURE, got %ld\n", info->dwKeySpec);
1134 HeapFree(GetProcessHeap(), 0, info);
1138 CertFreeCertificateContext(context);
1141 CryptDestroyKey(key);
1144 CryptReleaseContext(csp, 0);
1145 ret = CryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
1146 CRYPT_DELETEKEYSET);
1149 static const LPCSTR keyUsages[] = { szOID_PKIX_KP_CODE_SIGNING,
1150 szOID_PKIX_KP_CLIENT_AUTH, szOID_RSA_RSA };
1152 static void testKeyUsage(void)
1154 BOOL ret;
1155 PCCERT_CONTEXT context;
1156 DWORD size;
1158 /* Test base cases */
1159 ret = CertGetEnhancedKeyUsage(NULL, 0, NULL, NULL);
1160 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1161 "Expected ERROR_INVALID_PARAMETER, got %08lx\n", GetLastError());
1162 size = 1;
1163 ret = CertGetEnhancedKeyUsage(NULL, 0, NULL, &size);
1164 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1165 "Expected ERROR_INVALID_PARAMETER, got %08lx\n", GetLastError());
1166 size = 0;
1167 ret = CertGetEnhancedKeyUsage(NULL, 0, NULL, &size);
1168 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1169 "Expected ERROR_INVALID_PARAMETER, got %08lx\n", GetLastError());
1170 /* These crash
1171 ret = CertSetEnhancedKeyUsage(NULL, NULL);
1172 usage.cUsageIdentifier = 0;
1173 ret = CertSetEnhancedKeyUsage(NULL, &usage);
1175 /* Test with a cert with no enhanced key usage extension */
1176 context = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert,
1177 sizeof(bigCert));
1178 ok(context != NULL, "CertCreateCertificateContext failed: %08lx\n",
1179 GetLastError());
1180 if (context)
1182 static const char oid[] = "1.2.3.4";
1183 BYTE buf[sizeof(CERT_ENHKEY_USAGE) + 2 * (sizeof(LPSTR) + sizeof(oid))];
1184 PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
1186 ret = CertGetEnhancedKeyUsage(context, 0, NULL, NULL);
1187 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1188 "Expected ERROR_INVALID_PARAMETER, got %08lx\n", GetLastError());
1189 size = 1;
1190 ret = CertGetEnhancedKeyUsage(context, 0, NULL, &size);
1191 if (ret)
1193 /* Windows 2000, ME, or later: even though it succeeded, we expect
1194 * CRYPT_E_NOT_FOUND, which indicates there is no enhanced key
1195 * usage set for this cert (which implies it's valid for all uses.)
1197 ok(GetLastError() == CRYPT_E_NOT_FOUND,
1198 "Expected CRYPT_E_NOT_FOUND, got %08lx\n", GetLastError());
1199 ok(size == sizeof(CERT_ENHKEY_USAGE), "Wrong size %ld\n", size);
1200 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
1201 ok(ret, "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
1202 ok(pUsage->cUsageIdentifier == 0, "Expected 0 usages, got %ld\n",
1203 pUsage->cUsageIdentifier);
1205 else
1207 /* Windows NT, 95, or 98: it fails, and the last error is
1208 * CRYPT_E_NOT_FOUND.
1210 ok(GetLastError() == CRYPT_E_NOT_FOUND,
1211 "Expected CRYPT_E_NOT_FOUND, got %08lx\n", GetLastError());
1213 /* I can add a usage identifier when no key usage has been set */
1214 ret = CertAddEnhancedKeyUsageIdentifier(context, oid);
1215 ok(ret, "CertAddEnhancedKeyUsageIdentifier failed: %08lx\n",
1216 GetLastError());
1217 size = sizeof(buf);
1218 ret = CertGetEnhancedKeyUsage(context,
1219 CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG, pUsage, &size);
1220 ok(ret && GetLastError() == 0,
1221 "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
1222 ok(pUsage->cUsageIdentifier == 1, "Expected 1 usage, got %ld\n",
1223 pUsage->cUsageIdentifier);
1224 if (pUsage->cUsageIdentifier)
1225 ok(!strcmp(pUsage->rgpszUsageIdentifier[0], oid),
1226 "Expected %s, got %s\n", oid, pUsage->rgpszUsageIdentifier[0]);
1227 /* Now set an empty key usage */
1228 pUsage->cUsageIdentifier = 0;
1229 ret = CertSetEnhancedKeyUsage(context, pUsage);
1230 ok(ret, "CertSetEnhancedKeyUsage failed: %08lx\n", GetLastError());
1231 /* Shouldn't find it in the cert */
1232 size = sizeof(buf);
1233 ret = CertGetEnhancedKeyUsage(context,
1234 CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, pUsage, &size);
1235 ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
1236 "Expected CRYPT_E_NOT_FOUND, got %08lx\n", GetLastError());
1237 /* Should find it as an extended property */
1238 ret = CertGetEnhancedKeyUsage(context,
1239 CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG, pUsage, &size);
1240 ok(ret && GetLastError() == 0,
1241 "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
1242 ok(pUsage->cUsageIdentifier == 0, "Expected 0 usages, got %ld\n",
1243 pUsage->cUsageIdentifier);
1244 /* Should find it as either */
1245 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
1246 ok(ret && GetLastError() == 0,
1247 "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
1248 ok(pUsage->cUsageIdentifier == 0, "Expected 0 usages, got %ld\n",
1249 pUsage->cUsageIdentifier);
1250 /* Add a usage identifier */
1251 ret = CertAddEnhancedKeyUsageIdentifier(context, oid);
1252 ok(ret, "CertAddEnhancedKeyUsageIdentifier failed: %08lx\n",
1253 GetLastError());
1254 size = sizeof(buf);
1255 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
1256 ok(ret && GetLastError() == 0,
1257 "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
1258 ok(pUsage->cUsageIdentifier == 1, "Expected 1 identifier, got %ld\n",
1259 pUsage->cUsageIdentifier);
1260 if (pUsage->cUsageIdentifier)
1261 ok(!strcmp(pUsage->rgpszUsageIdentifier[0], oid),
1262 "Expected %s, got %s\n", oid, pUsage->rgpszUsageIdentifier[0]);
1263 /* Yep, I can re-add the same usage identifier */
1264 ret = CertAddEnhancedKeyUsageIdentifier(context, oid);
1265 ok(ret, "CertAddEnhancedKeyUsageIdentifier failed: %08lx\n",
1266 GetLastError());
1267 size = sizeof(buf);
1268 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
1269 ok(ret && GetLastError() == 0,
1270 "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
1271 ok(pUsage->cUsageIdentifier == 2, "Expected 2 identifiers, got %ld\n",
1272 pUsage->cUsageIdentifier);
1273 if (pUsage->cUsageIdentifier)
1274 ok(!strcmp(pUsage->rgpszUsageIdentifier[0], oid),
1275 "Expected %s, got %s\n", oid, pUsage->rgpszUsageIdentifier[0]);
1276 if (pUsage->cUsageIdentifier >= 2)
1277 ok(!strcmp(pUsage->rgpszUsageIdentifier[1], oid),
1278 "Expected %s, got %s\n", oid, pUsage->rgpszUsageIdentifier[1]);
1279 /* Now set a NULL extended property--this deletes the property. */
1280 ret = CertSetEnhancedKeyUsage(context, NULL);
1281 ok(ret, "CertSetEnhancedKeyUsage failed: %08lx\n", GetLastError());
1282 SetLastError(0xbaadcafe);
1283 size = sizeof(buf);
1284 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
1285 ok(GetLastError() == CRYPT_E_NOT_FOUND,
1286 "Expected CRYPT_E_NOT_FOUND, got %08lx\n", GetLastError());
1288 CertFreeCertificateContext(context);
1290 /* Now test with a cert with an enhanced key usage extension */
1291 context = CertCreateCertificateContext(X509_ASN_ENCODING, certWithUsage,
1292 sizeof(certWithUsage));
1293 ok(context != NULL, "CertCreateCertificateContext failed: %08lx\n",
1294 GetLastError());
1295 if (context)
1297 LPBYTE buf = NULL;
1298 DWORD bufSize = 0, i;
1300 /* The size may depend on what flags are used to query it, so I
1301 * realloc the buffer for each test.
1303 ret = CertGetEnhancedKeyUsage(context,
1304 CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, NULL, &bufSize);
1305 ok(ret, "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
1306 buf = HeapAlloc(GetProcessHeap(), 0, bufSize);
1307 if (buf)
1309 PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
1311 /* Should find it in the cert */
1312 size = bufSize;
1313 ret = CertGetEnhancedKeyUsage(context,
1314 CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, pUsage, &size);
1315 ok(ret && GetLastError() == 0,
1316 "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
1317 ok(pUsage->cUsageIdentifier == 3, "Expected 3 usages, got %ld\n",
1318 pUsage->cUsageIdentifier);
1319 for (i = 0; i < pUsage->cUsageIdentifier; i++)
1320 ok(!strcmp(pUsage->rgpszUsageIdentifier[i], keyUsages[i]),
1321 "Expected %s, got %s\n", keyUsages[i],
1322 pUsage->rgpszUsageIdentifier[i]);
1323 HeapFree(GetProcessHeap(), 0, buf);
1325 ret = CertGetEnhancedKeyUsage(context, 0, NULL, &bufSize);
1326 ok(ret, "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
1327 buf = HeapAlloc(GetProcessHeap(), 0, bufSize);
1328 if (buf)
1330 PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
1332 /* Should find it as either */
1333 size = bufSize;
1334 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
1335 /* In Windows, GetLastError returns CRYPT_E_NOT_FOUND not found
1336 * here, even though the return is successful and the usage id
1337 * count is positive. I don't enforce that here.
1339 ok(ret,
1340 "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
1341 ok(pUsage->cUsageIdentifier == 3, "Expected 3 usages, got %ld\n",
1342 pUsage->cUsageIdentifier);
1343 for (i = 0; i < pUsage->cUsageIdentifier; i++)
1344 ok(!strcmp(pUsage->rgpszUsageIdentifier[i], keyUsages[i]),
1345 "Expected %s, got %s\n", keyUsages[i],
1346 pUsage->rgpszUsageIdentifier[i]);
1347 HeapFree(GetProcessHeap(), 0, buf);
1349 /* Shouldn't find it as an extended property */
1350 ret = CertGetEnhancedKeyUsage(context,
1351 CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG, NULL, &size);
1352 ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
1353 "Expected CRYPT_E_NOT_FOUND, got %08lx\n", GetLastError());
1354 /* Adding a usage identifier overrides the cert's usage!? */
1355 ret = CertAddEnhancedKeyUsageIdentifier(context, szOID_RSA_RSA);
1356 ok(ret, "CertAddEnhancedKeyUsageIdentifier failed: %08lx\n",
1357 GetLastError());
1358 ret = CertGetEnhancedKeyUsage(context, 0, NULL, &bufSize);
1359 ok(ret, "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
1360 buf = HeapAlloc(GetProcessHeap(), 0, bufSize);
1361 if (buf)
1363 PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
1365 /* Should find it as either */
1366 size = bufSize;
1367 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
1368 ok(ret,
1369 "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
1370 ok(pUsage->cUsageIdentifier == 1, "Expected 1 usage, got %ld\n",
1371 pUsage->cUsageIdentifier);
1372 ok(!strcmp(pUsage->rgpszUsageIdentifier[0], szOID_RSA_RSA),
1373 "Expected %s, got %s\n", szOID_RSA_RSA,
1374 pUsage->rgpszUsageIdentifier[0]);
1375 HeapFree(GetProcessHeap(), 0, buf);
1377 /* But querying the cert directly returns its usage */
1378 ret = CertGetEnhancedKeyUsage(context,
1379 CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, NULL, &bufSize);
1380 ok(ret, "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
1381 buf = HeapAlloc(GetProcessHeap(), 0, bufSize);
1382 if (buf)
1384 PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
1386 size = bufSize;
1387 ret = CertGetEnhancedKeyUsage(context,
1388 CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, pUsage, &size);
1389 ok(ret,
1390 "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
1391 ok(pUsage->cUsageIdentifier == 3, "Expected 3 usages, got %ld\n",
1392 pUsage->cUsageIdentifier);
1393 for (i = 0; i < pUsage->cUsageIdentifier; i++)
1394 ok(!strcmp(pUsage->rgpszUsageIdentifier[i], keyUsages[i]),
1395 "Expected %s, got %s\n", keyUsages[i],
1396 pUsage->rgpszUsageIdentifier[i]);
1397 HeapFree(GetProcessHeap(), 0, buf);
1399 /* And removing the only usage identifier in the extended property
1400 * results in the cert's key usage being found.
1402 ret = CertRemoveEnhancedKeyUsageIdentifier(context, szOID_RSA_RSA);
1403 ok(ret, "CertRemoveEnhancedKeyUsage failed: %08lx\n", GetLastError());
1404 ret = CertGetEnhancedKeyUsage(context, 0, NULL, &bufSize);
1405 ok(ret, "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
1406 buf = HeapAlloc(GetProcessHeap(), 0, bufSize);
1407 if (buf)
1409 PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
1411 /* Should find it as either */
1412 size = bufSize;
1413 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
1414 ok(ret,
1415 "CertGetEnhancedKeyUsage failed: %08lx\n", GetLastError());
1416 ok(pUsage->cUsageIdentifier == 3, "Expected 3 usages, got %ld\n",
1417 pUsage->cUsageIdentifier);
1418 for (i = 0; i < pUsage->cUsageIdentifier; i++)
1419 ok(!strcmp(pUsage->rgpszUsageIdentifier[i], keyUsages[i]),
1420 "Expected %s, got %s\n", keyUsages[i],
1421 pUsage->rgpszUsageIdentifier[i]);
1422 HeapFree(GetProcessHeap(), 0, buf);
1425 CertFreeCertificateContext(context);
1429 static void testCompareCertName(void)
1431 static const BYTE bogus[] = { 1, 2, 3, 4 };
1432 static const BYTE bogusPrime[] = { 0, 1, 2, 3, 4 };
1433 static const BYTE emptyPrime[] = { 0x30, 0x00, 0x01 };
1434 BOOL ret;
1435 CERT_NAME_BLOB blob1, blob2;
1437 /* crashes
1438 ret = CertCompareCertificateName(0, NULL, NULL);
1440 /* An empty name checks against itself.. */
1441 blob1.pbData = (LPBYTE)emptyCert;
1442 blob1.cbData = sizeof(emptyCert);
1443 ret = CertCompareCertificateName(0, &blob1, &blob1);
1444 ok(ret, "CertCompareCertificateName failed: %08lx\n", GetLastError());
1445 /* It doesn't have to be a valid encoded name.. */
1446 blob1.pbData = (LPBYTE)bogus;
1447 blob1.cbData = sizeof(bogus);
1448 ret = CertCompareCertificateName(0, &blob1, &blob1);
1449 ok(ret, "CertCompareCertificateName failed: %08lx\n", GetLastError());
1450 /* Leading zeroes matter.. */
1451 blob2.pbData = (LPBYTE)bogusPrime;
1452 blob2.cbData = sizeof(bogusPrime);
1453 ret = CertCompareCertificateName(0, &blob1, &blob2);
1454 ok(!ret, "Expected failure\n");
1455 /* As do trailing extra bytes. */
1456 blob2.pbData = (LPBYTE)emptyPrime;
1457 blob2.cbData = sizeof(emptyPrime);
1458 ret = CertCompareCertificateName(0, &blob1, &blob2);
1459 ok(!ret, "Expected failure\n");
1462 static const BYTE int1[] = { 0x88, 0xff, 0xff, 0xff };
1463 static const BYTE int2[] = { 0x88, 0xff };
1464 static const BYTE int3[] = { 0x23, 0xff };
1465 static const BYTE int4[] = { 0x7f, 0x00 };
1466 static const BYTE int5[] = { 0x7f };
1467 static const BYTE int6[] = { 0x80, 0x00, 0x00, 0x00 };
1468 static const BYTE int7[] = { 0x80, 0x00 };
1470 struct IntBlobTest
1472 CRYPT_INTEGER_BLOB blob1;
1473 CRYPT_INTEGER_BLOB blob2;
1474 BOOL areEqual;
1475 } intBlobs[] = {
1476 { { sizeof(int1), (LPBYTE)int1 }, { sizeof(int2), (LPBYTE)int2 }, TRUE },
1477 { { sizeof(int3), (LPBYTE)int3 }, { sizeof(int3), (LPBYTE)int3 }, TRUE },
1478 { { sizeof(int4), (LPBYTE)int4 }, { sizeof(int5), (LPBYTE)int5 }, TRUE },
1479 { { sizeof(int6), (LPBYTE)int6 }, { sizeof(int7), (LPBYTE)int7 }, TRUE },
1480 { { sizeof(int1), (LPBYTE)int1 }, { sizeof(int7), (LPBYTE)int7 }, FALSE },
1483 static void testCompareIntegerBlob(void)
1485 DWORD i;
1486 BOOL ret;
1488 for (i = 0; i < sizeof(intBlobs) / sizeof(intBlobs[0]); i++)
1490 ret = CertCompareIntegerBlob(&intBlobs[i].blob1, &intBlobs[i].blob2);
1491 ok(ret == intBlobs[i].areEqual,
1492 "%ld: expected blobs %s compare\n", i, intBlobs[i].areEqual ?
1493 "to" : "not to");
1497 static void testComparePublicKeyInfo(void)
1499 BOOL ret;
1500 CERT_PUBLIC_KEY_INFO info1 = { { 0 } }, info2 = { { 0 } };
1501 static CHAR oid_rsa_rsa[] = szOID_RSA_RSA;
1502 static CHAR oid_rsa_sha1rsa[] = szOID_RSA_SHA1RSA;
1503 static CHAR oid_x957_dsa[] = szOID_X957_DSA;
1504 static const BYTE bits1[] = { 1, 0 };
1505 static const BYTE bits2[] = { 0 };
1506 static const BYTE bits3[] = { 1 };
1508 /* crashes
1509 ret = CertComparePublicKeyInfo(0, NULL, NULL);
1511 /* Empty public keys compare */
1512 ret = CertComparePublicKeyInfo(0, &info1, &info2);
1513 ok(ret, "CertComparePublicKeyInfo failed: %08lx\n", GetLastError());
1514 /* Different OIDs appear to compare */
1515 info1.Algorithm.pszObjId = oid_rsa_rsa;
1516 info2.Algorithm.pszObjId = oid_rsa_sha1rsa;
1517 ret = CertComparePublicKeyInfo(0, &info1, &info2);
1518 ok(ret, "CertComparePublicKeyInfo failed: %08lx\n", GetLastError());
1519 info2.Algorithm.pszObjId = oid_x957_dsa;
1520 ret = CertComparePublicKeyInfo(0, &info1, &info2);
1521 ok(ret, "CertComparePublicKeyInfo failed: %08lx\n", GetLastError());
1522 info1.PublicKey.cbData = sizeof(bits1);
1523 info1.PublicKey.pbData = (LPBYTE)bits1;
1524 info1.PublicKey.cUnusedBits = 0;
1525 info2.PublicKey.cbData = sizeof(bits1);
1526 info2.PublicKey.pbData = (LPBYTE)bits1;
1527 info2.PublicKey.cUnusedBits = 0;
1528 ret = CertComparePublicKeyInfo(0, &info1, &info2);
1529 ok(ret, "CertComparePublicKeyInfo failed: %08lx\n", GetLastError());
1530 /* Even though they compare in their used bits, these do not compare */
1531 info1.PublicKey.cbData = sizeof(bits2);
1532 info1.PublicKey.pbData = (LPBYTE)bits2;
1533 info1.PublicKey.cUnusedBits = 0;
1534 info2.PublicKey.cbData = sizeof(bits3);
1535 info2.PublicKey.pbData = (LPBYTE)bits3;
1536 info2.PublicKey.cUnusedBits = 1;
1537 ret = CertComparePublicKeyInfo(0, &info1, &info2);
1538 /* Simple (non-comparing) case */
1539 ok(!ret, "Expected keys not to compare\n");
1540 info2.PublicKey.cbData = sizeof(bits1);
1541 info2.PublicKey.pbData = (LPBYTE)bits1;
1542 info2.PublicKey.cUnusedBits = 0;
1543 ret = CertComparePublicKeyInfo(0, &info1, &info2);
1544 ok(!ret, "Expected keys not to compare\n");
1547 void testCompareCert(void)
1549 CERT_INFO info1 = { 0 }, info2 = { 0 };
1550 BOOL ret;
1552 /* Crashes
1553 ret = CertCompareCertificate(X509_ASN_ENCODING, NULL, NULL);
1556 /* Certs with the same issuer and serial number are equal, even if they
1557 * differ in other respects (like subject).
1559 info1.SerialNumber.pbData = (LPBYTE)serialNum;
1560 info1.SerialNumber.cbData = sizeof(serialNum);
1561 info1.Issuer.pbData = (LPBYTE)subjectName;
1562 info1.Issuer.cbData = sizeof(subjectName);
1563 info1.Subject.pbData = (LPBYTE)subjectName2;
1564 info1.Subject.cbData = sizeof(subjectName2);
1565 info2.SerialNumber.pbData = (LPBYTE)serialNum;
1566 info2.SerialNumber.cbData = sizeof(serialNum);
1567 info2.Issuer.pbData = (LPBYTE)subjectName;
1568 info2.Issuer.cbData = sizeof(subjectName);
1569 info2.Subject.pbData = (LPBYTE)subjectName;
1570 info2.Subject.cbData = sizeof(subjectName);
1571 ret = CertCompareCertificate(X509_ASN_ENCODING, &info1, &info2);
1572 ok(ret, "Expected certs to be equal\n");
1574 info2.Issuer.pbData = (LPBYTE)subjectName2;
1575 info2.Issuer.cbData = sizeof(subjectName2);
1576 ret = CertCompareCertificate(X509_ASN_ENCODING, &info1, &info2);
1577 ok(!ret, "Expected certs not to be equal\n");
1580 static void testVerifySubjectCert(void)
1582 BOOL ret;
1583 DWORD flags;
1584 PCCERT_CONTEXT context1, context2;
1586 /* Crashes
1587 ret = CertVerifySubjectCertificateContext(NULL, NULL, NULL);
1589 flags = 0;
1590 ret = CertVerifySubjectCertificateContext(NULL, NULL, &flags);
1591 ok(ret, "CertVerifySubjectCertificateContext failed; %08lx\n",
1592 GetLastError());
1593 flags = CERT_STORE_NO_CRL_FLAG;
1594 ret = CertVerifySubjectCertificateContext(NULL, NULL, &flags);
1595 ok(!ret && GetLastError() == E_INVALIDARG,
1596 "Expected E_INVALIDARG, got %08lx\n", GetLastError());
1598 flags = 0;
1599 context1 = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert,
1600 sizeof(bigCert));
1601 ret = CertVerifySubjectCertificateContext(NULL, context1, &flags);
1602 ok(ret, "CertVerifySubjectCertificateContext failed; %08lx\n",
1603 GetLastError());
1604 ret = CertVerifySubjectCertificateContext(context1, NULL, &flags);
1605 ok(ret, "CertVerifySubjectCertificateContext failed; %08lx\n",
1606 GetLastError());
1607 ret = CertVerifySubjectCertificateContext(context1, context1, &flags);
1608 ok(ret, "CertVerifySubjectCertificateContext failed; %08lx\n",
1609 GetLastError());
1611 context2 = CertCreateCertificateContext(X509_ASN_ENCODING,
1612 bigCertWithDifferentSubject, sizeof(bigCertWithDifferentSubject));
1613 SetLastError(0xdeadbeef);
1614 ret = CertVerifySubjectCertificateContext(context1, context2, &flags);
1615 ok(ret, "CertVerifySubjectCertificateContext failed; %08lx\n",
1616 GetLastError());
1617 flags = CERT_STORE_REVOCATION_FLAG;
1618 ret = CertVerifySubjectCertificateContext(context1, context2, &flags);
1619 ok(ret, "CertVerifySubjectCertificateContext failed; %08lx\n",
1620 GetLastError());
1621 ok(flags == (CERT_STORE_REVOCATION_FLAG | CERT_STORE_NO_CRL_FLAG),
1622 "Expected CERT_STORE_REVOCATION_FLAG | CERT_STORE_NO_CRL_FLAG, got %08lx\n",
1623 flags);
1624 flags = CERT_STORE_SIGNATURE_FLAG;
1625 ret = CertVerifySubjectCertificateContext(context1, context2, &flags);
1626 ok(ret, "CertVerifySubjectCertificateContext failed; %08lx\n",
1627 GetLastError());
1628 ok(flags == CERT_STORE_SIGNATURE_FLAG,
1629 "Expected CERT_STORE_SIGNATURE_FLAG, got %08lx\n", flags);
1630 CertFreeCertificateContext(context2);
1632 CertFreeCertificateContext(context1);
1635 static const BYTE privKey[] = {
1636 0x07, 0x02, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x52, 0x53, 0x41, 0x32, 0x00,
1637 0x02, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x79, 0x10, 0x1c, 0xd0, 0x6b, 0x10,
1638 0x18, 0x30, 0x94, 0x61, 0xdc, 0x0e, 0xcb, 0x96, 0x4e, 0x21, 0x3f, 0x79, 0xcd,
1639 0xa9, 0x17, 0x62, 0xbc, 0xbb, 0x61, 0x4c, 0xe0, 0x75, 0x38, 0x6c, 0xf3, 0xde,
1640 0x60, 0x86, 0x03, 0x97, 0x65, 0xeb, 0x1e, 0x6b, 0xdb, 0x53, 0x85, 0xad, 0x68,
1641 0x21, 0xf1, 0x5d, 0xe7, 0x1f, 0xe6, 0x53, 0xb4, 0xbb, 0x59, 0x3e, 0x14, 0x27,
1642 0xb1, 0x83, 0xa7, 0x3a, 0x54, 0xe2, 0x8f, 0x65, 0x8e, 0x6a, 0x4a, 0xcf, 0x3b,
1643 0x1f, 0x65, 0xff, 0xfe, 0xf1, 0x31, 0x3a, 0x37, 0x7a, 0x8b, 0xcb, 0xc6, 0xd4,
1644 0x98, 0x50, 0x36, 0x67, 0xe4, 0xa1, 0xe8, 0x7e, 0x8a, 0xc5, 0x23, 0xf2, 0x77,
1645 0xf5, 0x37, 0x61, 0x49, 0x72, 0x59, 0xe8, 0x3d, 0xf7, 0x60, 0xb2, 0x77, 0xca,
1646 0x78, 0x54, 0x6d, 0x65, 0x9e, 0x03, 0x97, 0x1b, 0x61, 0xbd, 0x0c, 0xd8, 0x06,
1647 0x63, 0xe2, 0xc5, 0x48, 0xef, 0xb3, 0xe2, 0x6e, 0x98, 0x7d, 0xbd, 0x4e, 0x72,
1648 0x91, 0xdb, 0x31, 0x57, 0xe3, 0x65, 0x3a, 0x49, 0xca, 0xec, 0xd2, 0x02, 0x4e,
1649 0x22, 0x7e, 0x72, 0x8e, 0xf9, 0x79, 0x84, 0x82, 0xdf, 0x7b, 0x92, 0x2d, 0xaf,
1650 0xc9, 0xe4, 0x33, 0xef, 0x89, 0x5c, 0x66, 0x99, 0xd8, 0x80, 0x81, 0x47, 0x2b,
1651 0xb1, 0x66, 0x02, 0x84, 0x59, 0x7b, 0xc3, 0xbe, 0x98, 0x45, 0x4a, 0x3d, 0xdd,
1652 0xea, 0x2b, 0xdf, 0x4e, 0xb4, 0x24, 0x6b, 0xec, 0xe7, 0xd9, 0x0c, 0x45, 0xb8,
1653 0xbe, 0xca, 0x69, 0x37, 0x92, 0x4c, 0x38, 0x6b, 0x96, 0x6d, 0xcd, 0x86, 0x67,
1654 0x5c, 0xea, 0x54, 0x94, 0xa4, 0xca, 0xa4, 0x02, 0xa5, 0x21, 0x4d, 0xae, 0x40,
1655 0x8f, 0x9d, 0x51, 0x83, 0xf2, 0x3f, 0x33, 0xc1, 0x72, 0xb4, 0x1d, 0x94, 0x6e,
1656 0x7d, 0xe4, 0x27, 0x3f, 0xea, 0xff, 0xe5, 0x9b, 0xa7, 0x5e, 0x55, 0x8e, 0x0d,
1657 0x69, 0x1c, 0x7a, 0xff, 0x81, 0x9d, 0x53, 0x52, 0x97, 0x9a, 0x76, 0x79, 0xda,
1658 0x93, 0x32, 0x16, 0xec, 0x69, 0x51, 0x1a, 0x4e, 0xc3, 0xf1, 0x72, 0x80, 0x78,
1659 0x5e, 0x66, 0x4a, 0x8d, 0x85, 0x2f, 0x3f, 0xb2, 0xa7 };
1661 static const BYTE selfSignedCert[] = {
1662 0x30, 0x82, 0x01, 0x1f, 0x30, 0x81, 0xce, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02,
1663 0x10, 0xeb, 0x0d, 0x57, 0x2a, 0x9c, 0x09, 0xba, 0xa4, 0x4a, 0xb7, 0x25, 0x49,
1664 0xd9, 0x3e, 0xb5, 0x73, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1d,
1665 0x05, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03,
1666 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30,
1667 0x1e, 0x17, 0x0d, 0x30, 0x36, 0x30, 0x36, 0x32, 0x39, 0x30, 0x35, 0x30, 0x30,
1668 0x34, 0x36, 0x5a, 0x17, 0x0d, 0x30, 0x37, 0x30, 0x36, 0x32, 0x39, 0x31, 0x31,
1669 0x30, 0x30, 0x34, 0x36, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03,
1670 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e,
1671 0x67, 0x00, 0x30, 0x5c, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
1672 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x4b, 0x00, 0x30, 0x48, 0x02, 0x41,
1673 0x00, 0xe2, 0x54, 0x3a, 0xa7, 0x83, 0xb1, 0x27, 0x14, 0x3e, 0x59, 0xbb, 0xb4,
1674 0x53, 0xe6, 0x1f, 0xe7, 0x5d, 0xf1, 0x21, 0x68, 0xad, 0x85, 0x53, 0xdb, 0x6b,
1675 0x1e, 0xeb, 0x65, 0x97, 0x03, 0x86, 0x60, 0xde, 0xf3, 0x6c, 0x38, 0x75, 0xe0,
1676 0x4c, 0x61, 0xbb, 0xbc, 0x62, 0x17, 0xa9, 0xcd, 0x79, 0x3f, 0x21, 0x4e, 0x96,
1677 0xcb, 0x0e, 0xdc, 0x61, 0x94, 0x30, 0x18, 0x10, 0x6b, 0xd0, 0x1c, 0x10, 0x79,
1678 0x02, 0x03, 0x01, 0x00, 0x01, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02,
1679 0x1d, 0x05, 0x00, 0x03, 0x41, 0x00, 0x25, 0x90, 0x53, 0x34, 0xd9, 0x56, 0x41,
1680 0x5e, 0xdb, 0x7e, 0x01, 0x36, 0xec, 0x27, 0x61, 0x5e, 0xb7, 0x4d, 0x90, 0x66,
1681 0xa2, 0xe1, 0x9d, 0x58, 0x76, 0xd4, 0x9c, 0xba, 0x2c, 0x84, 0xc6, 0x83, 0x7a,
1682 0x22, 0x0d, 0x03, 0x69, 0x32, 0x1a, 0x6d, 0xcb, 0x0c, 0x15, 0xb3, 0x6b, 0xc7,
1683 0x0a, 0x8c, 0xb4, 0x5c, 0x34, 0x78, 0xe0, 0x3c, 0x9c, 0xe9, 0xf3, 0x30, 0x9f,
1684 0xa8, 0x76, 0x57, 0x92, 0x36 };
1686 static void testAcquireCertPrivateKey(void)
1688 BOOL ret;
1689 PCCERT_CONTEXT cert;
1690 HCRYPTPROV csp;
1691 DWORD keySpec;
1692 BOOL callerFree;
1693 CRYPT_KEY_PROV_INFO keyProvInfo;
1694 HCRYPTKEY key;
1696 keyProvInfo.pwszContainerName = (LPWSTR)cspNameW;
1697 keyProvInfo.pwszProvName = (LPWSTR)MS_DEF_PROV_W;
1698 keyProvInfo.dwProvType = PROV_RSA_FULL;
1699 keyProvInfo.dwFlags = 0;
1700 keyProvInfo.cProvParam = 0;
1701 keyProvInfo.rgProvParam = NULL;
1702 keyProvInfo.dwKeySpec = AT_SIGNATURE;
1704 CryptAcquireContextW(NULL, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
1705 CRYPT_DELETEKEYSET);
1707 cert = CertCreateCertificateContext(X509_ASN_ENCODING, selfSignedCert,
1708 sizeof(selfSignedCert));
1710 /* Crash
1711 ret = CryptAcquireCertificatePrivateKey(NULL, 0, NULL, NULL, NULL, NULL);
1712 ret = CryptAcquireCertificatePrivateKey(NULL, 0, NULL, NULL, NULL,
1713 &callerFree);
1714 ret = CryptAcquireCertificatePrivateKey(NULL, 0, NULL, NULL, &keySpec,
1715 NULL);
1716 ret = CryptAcquireCertificatePrivateKey(NULL, 0, NULL, &csp, NULL, NULL);
1717 ret = CryptAcquireCertificatePrivateKey(NULL, 0, NULL, &csp, &keySpec,
1718 &callerFree);
1719 ret = CryptAcquireCertificatePrivateKey(cert, 0, NULL, NULL, NULL, NULL);
1722 /* Missing private key */
1723 ret = CryptAcquireCertificatePrivateKey(cert, 0, NULL, &csp, NULL, NULL);
1724 ok(!ret && GetLastError() == CRYPT_E_NO_KEY_PROPERTY,
1725 "Expected CRYPT_E_NO_KEY_PROPERTY, got %08lx\n", GetLastError());
1726 ret = CryptAcquireCertificatePrivateKey(cert, 0, NULL, &csp, &keySpec,
1727 &callerFree);
1728 ok(!ret && GetLastError() == CRYPT_E_NO_KEY_PROPERTY,
1729 "Expected CRYPT_E_NO_KEY_PROPERTY, got %08lx\n", GetLastError());
1730 CertSetCertificateContextProperty(cert, CERT_KEY_PROV_INFO_PROP_ID, 0,
1731 &keyProvInfo);
1732 ret = CryptAcquireCertificatePrivateKey(cert, 0, NULL, &csp, &keySpec,
1733 &callerFree);
1734 ok(!ret && GetLastError() == CRYPT_E_NO_KEY_PROPERTY,
1735 "Expected CRYPT_E_NO_KEY_PROPERTY, got %08lx\n", GetLastError());
1737 CryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
1738 CRYPT_NEWKEYSET);
1739 ret = CryptImportKey(csp, (LPBYTE)privKey, sizeof(privKey), 0, 0, &key);
1740 ok(ret, "CryptImportKey failed: %08lx\n", GetLastError());
1741 if (ret)
1743 HCRYPTPROV certCSP;
1744 DWORD size;
1745 CERT_KEY_CONTEXT keyContext;
1747 /* Don't cache provider */
1748 ret = CryptAcquireCertificatePrivateKey(cert, 0, NULL, &certCSP,
1749 &keySpec, &callerFree);
1750 ok(ret, "CryptAcquireCertificatePrivateKey failed: %08lx\n",
1751 GetLastError());
1752 ok(callerFree, "Expected callerFree to be TRUE\n");
1753 CryptReleaseContext(certCSP, 0);
1754 ret = CryptAcquireCertificatePrivateKey(cert, 0, NULL, &certCSP,
1755 NULL, NULL);
1756 ok(ret, "CryptAcquireCertificatePrivateKey failed: %08lx\n",
1757 GetLastError());
1758 CryptReleaseContext(certCSP, 0);
1760 /* Use the key prov info's caching (there shouldn't be any) */
1761 ret = CryptAcquireCertificatePrivateKey(cert,
1762 CRYPT_ACQUIRE_USE_PROV_INFO_FLAG, NULL, &certCSP, &keySpec,
1763 &callerFree);
1764 ok(ret, "CryptAcquireCertificatePrivateKey failed: %08lx\n",
1765 GetLastError());
1766 ok(callerFree, "Expected callerFree to be TRUE\n");
1767 CryptReleaseContext(certCSP, 0);
1769 /* Cache it (and check that it's cached) */
1770 ret = CryptAcquireCertificatePrivateKey(cert,
1771 CRYPT_ACQUIRE_CACHE_FLAG, NULL, &certCSP, &keySpec, &callerFree);
1772 ok(ret, "CryptAcquireCertificatePrivateKey failed: %08lx\n",
1773 GetLastError());
1774 ok(!callerFree, "Expected callerFree to be FALSE\n");
1775 size = sizeof(keyContext);
1776 ret = CertGetCertificateContextProperty(cert, CERT_KEY_CONTEXT_PROP_ID,
1777 &keyContext, &size);
1778 ok(ret, "CertGetCertificateContextProperty failed: %08lx\n",
1779 GetLastError());
1781 /* Remove the cached provider */
1782 CryptReleaseContext(keyContext.hCryptProv, 0);
1783 CertSetCertificateContextProperty(cert, CERT_KEY_CONTEXT_PROP_ID, 0,
1784 NULL);
1785 /* Allow caching via the key prov info */
1786 keyProvInfo.dwFlags = CERT_SET_KEY_CONTEXT_PROP_ID;
1787 CertSetCertificateContextProperty(cert, CERT_KEY_PROV_INFO_PROP_ID, 0,
1788 &keyProvInfo);
1789 /* Now use the key prov info's caching */
1790 ret = CryptAcquireCertificatePrivateKey(cert,
1791 CRYPT_ACQUIRE_USE_PROV_INFO_FLAG, NULL, &certCSP, &keySpec,
1792 &callerFree);
1793 ok(ret, "CryptAcquireCertificatePrivateKey failed: %08lx\n",
1794 GetLastError());
1795 ok(!callerFree, "Expected callerFree to be FALSE\n");
1796 size = sizeof(keyContext);
1797 ret = CertGetCertificateContextProperty(cert, CERT_KEY_CONTEXT_PROP_ID,
1798 &keyContext, &size);
1799 ok(ret, "CertGetCertificateContextProperty failed: %08lx\n",
1800 GetLastError());
1802 CryptDestroyKey(key);
1805 CryptReleaseContext(csp, 0);
1806 CryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
1807 CRYPT_DELETEKEYSET);
1809 CertFreeCertificateContext(cert);
1812 START_TEST(cert)
1814 init_function_pointers();
1816 testAddCert();
1817 testCertProperties();
1818 testDupCert();
1819 testFindCert();
1820 testGetSubjectCert();
1821 testGetIssuerCert();
1823 testCryptHashCert();
1824 testCertSigs();
1825 testCreateSelfSignCert();
1826 testKeyUsage();
1827 testCompareCertName();
1828 testCompareIntegerBlob();
1829 testComparePublicKeyInfo();
1830 testCompareCert();
1831 testVerifySubjectCert();
1832 testAcquireCertPrivateKey();