crypt32: Fix CertAddCertificateContextToStore when called with CERT_STORE_ADD_USE_EXI...
[wine/winequartzdrv.git] / dlls / crypt32 / tests / cert.c
blob25008be0cf375e07aaa9b96c66027972ce84b33f
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 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 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,
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 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 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;
135 HCERTSTORE collection;
136 PCCERT_CONTEXT context;
137 PCCERT_CONTEXT copyContext;
138 BOOL ret;
140 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
141 CERT_STORE_CREATE_NEW_FLAG, NULL);
142 ok(store != NULL, "CertOpenStore failed: %d\n", GetLastError());
143 if (!store)
144 return;
146 /* Weird--bad add disposition leads to an access violation in Windows.
148 ret = CertAddEncodedCertificateToStore(0, X509_ASN_ENCODING, bigCert,
149 sizeof(bigCert), 0, NULL);
150 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
151 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
152 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
153 bigCert, sizeof(bigCert), 0, NULL);
154 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
155 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
157 /* Weird--can add a cert to the NULL store (does this have special
158 * meaning?)
160 context = NULL;
161 ret = CertAddEncodedCertificateToStore(0, X509_ASN_ENCODING, bigCert,
162 sizeof(bigCert), CERT_STORE_ADD_ALWAYS, &context);
163 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
164 GetLastError());
165 if (context)
166 CertFreeCertificateContext(context);
168 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
169 bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL);
170 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
171 GetLastError());
172 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
173 bigCert2, sizeof(bigCert2), CERT_STORE_ADD_NEW, NULL);
174 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
175 GetLastError());
176 /* This has the same name as bigCert, so finding isn't done by name */
177 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
178 certWithUsage, sizeof(certWithUsage), CERT_STORE_ADD_NEW, &context);
179 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
180 GetLastError());
181 ok(context != NULL, "Expected a context\n");
182 if (context)
184 CRYPT_DATA_BLOB hash = { sizeof(bigCert2Hash), 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: %08x\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 %08x\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: %08x\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: %08x\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: %08x\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: %08x\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 %08x\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: %08x\n",
277 GetLastError());
278 /* use the existing certificate and ask for a copy of the context*/
279 copyContext = NULL;
280 ret = CertAddCertificateContextToStore(collection, context,
281 CERT_STORE_ADD_USE_EXISTING, &copyContext);
282 ok(ret, "CertAddCertificateContextToStore failed: %08x\n",
283 GetLastError());
284 ok(copyContext != NULL, "Expected on output a non NULL copyContext\n");
285 if (copyContext)
286 CertFreeCertificateContext(copyContext);
287 /* but adding a new certificate isn't allowed. */
288 ret = CertAddCertificateContextToStore(collection, context,
289 CERT_STORE_ADD_ALWAYS, NULL);
290 ok(!ret && GetLastError() == E_ACCESSDENIED,
291 "Expected E_ACCESSDENIED, got %08x\n", GetLastError());
292 CertFreeCertificateContext(context);
295 CertCloseStore(collection, 0);
298 CertCloseStore(store, 0);
301 static void checkHash(const BYTE *data, DWORD dataLen, ALG_ID algID,
302 PCCERT_CONTEXT context, DWORD propID)
304 BYTE hash[20] = { 0 }, hashProperty[20];
305 BOOL ret;
306 DWORD size;
307 DWORD dwSizeWithNull;
309 memset(hash, 0, sizeof(hash));
310 memset(hashProperty, 0, sizeof(hashProperty));
311 size = sizeof(hash);
312 ret = CryptHashCertificate(0, algID, 0, data, dataLen, hash, &size);
313 ok(ret, "CryptHashCertificate failed: %08x\n", GetLastError());
314 ret = CertGetCertificateContextProperty(context, propID, NULL,
315 &dwSizeWithNull);
316 ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
317 GetLastError());
318 ret = CertGetCertificateContextProperty(context, propID, hashProperty,
319 &size);
320 ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
321 GetLastError());
322 ok(!memcmp(hash, hashProperty, size), "Unexpected hash for property %d\n",
323 propID);
324 ok(size == dwSizeWithNull, "Unexpected length of hash for property: received %d instead of %d\n",
325 dwSizeWithNull,size);
328 static WCHAR cspNameW[] = { 'W','i','n','e','C','r','y','p','t','T','e','m','p',0 };
330 static void testCertProperties(void)
332 PCCERT_CONTEXT context = CertCreateCertificateContext(X509_ASN_ENCODING,
333 bigCert, sizeof(bigCert));
334 DWORD propID, numProps, access, size;
335 BOOL ret;
336 BYTE hash[20] = { 0 }, hashProperty[20];
337 CRYPT_DATA_BLOB blob;
338 CERT_KEY_CONTEXT keyContext;
339 HCRYPTPROV csp;
341 ok(context != NULL, "CertCreateCertificateContext failed: %08x\n",
342 GetLastError());
343 if (!context)
344 return;
346 /* This crashes
347 propID = CertEnumCertificateContextProperties(NULL, 0);
350 propID = 0;
351 numProps = 0;
352 do {
353 propID = CertEnumCertificateContextProperties(context, propID);
354 if (propID)
355 numProps++;
356 } while (propID != 0);
357 ok(numProps == 0, "Expected 0 properties, got %d\n", numProps);
359 /* Tests with a NULL cert context. Prop ID 0 fails.. */
360 ret = CertSetCertificateContextProperty(NULL, 0, 0, NULL);
361 ok(!ret && GetLastError() == E_INVALIDARG,
362 "Expected E_INVALIDARG, got %08x\n", GetLastError());
363 /* while this just crashes.
364 ret = CertSetCertificateContextProperty(NULL,
365 CERT_KEY_PROV_HANDLE_PROP_ID, 0, NULL);
368 ret = CertSetCertificateContextProperty(context, 0, 0, NULL);
369 ok(!ret && GetLastError() == E_INVALIDARG,
370 "Expected E_INVALIDARG, got %08x\n", GetLastError());
371 /* Can't set the cert property directly, this crashes.
372 ret = CertSetCertificateContextProperty(context,
373 CERT_CERT_PROP_ID, 0, bigCert2);
376 /* These all crash.
377 ret = CertGetCertificateContextProperty(context,
378 CERT_ACCESS_STATE_PROP_ID, 0, NULL);
379 ret = CertGetCertificateContextProperty(context, CERT_HASH_PROP_ID,
380 NULL, NULL);
381 ret = CertGetCertificateContextProperty(context, CERT_HASH_PROP_ID,
382 hashProperty, NULL);
384 /* A missing prop */
385 size = 0;
386 ret = CertGetCertificateContextProperty(context,
387 CERT_KEY_PROV_INFO_PROP_ID, NULL, &size);
388 ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
389 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
390 /* And, an implicit property */
391 size = sizeof(access);
392 ret = CertGetCertificateContextProperty(context,
393 CERT_ACCESS_STATE_PROP_ID, &access, &size);
394 ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
395 GetLastError());
396 ok(!(access & CERT_ACCESS_STATE_WRITE_PERSIST_FLAG),
397 "Didn't expect a persisted cert\n");
398 /* Trying to set this "read only" property crashes.
399 access |= CERT_ACCESS_STATE_WRITE_PERSIST_FLAG;
400 ret = CertSetCertificateContextProperty(context,
401 CERT_ACCESS_STATE_PROP_ID, 0, &access);
404 /* Can I set the hash to an invalid hash? */
405 blob.pbData = hash;
406 blob.cbData = sizeof(hash);
407 ret = CertSetCertificateContextProperty(context, CERT_HASH_PROP_ID, 0,
408 &blob);
409 ok(ret, "CertSetCertificateContextProperty failed: %08x\n",
410 GetLastError());
411 size = sizeof(hashProperty);
412 ret = CertGetCertificateContextProperty(context, CERT_HASH_PROP_ID,
413 hashProperty, &size);
414 ok(!memcmp(hashProperty, hash, sizeof(hash)), "Unexpected hash\n");
415 /* Delete the (bogus) hash, and get the real one */
416 ret = CertSetCertificateContextProperty(context, CERT_HASH_PROP_ID, 0,
417 NULL);
418 ok(ret, "CertSetCertificateContextProperty failed: %08x\n",
419 GetLastError());
420 checkHash(bigCert, sizeof(bigCert), CALG_SHA1, context,
421 CERT_HASH_PROP_ID);
423 /* Now that the hash property is set, we should get one property when
424 * enumerating.
426 propID = 0;
427 numProps = 0;
428 do {
429 propID = CertEnumCertificateContextProperties(context, propID);
430 if (propID)
431 numProps++;
432 } while (propID != 0);
433 ok(numProps == 1, "Expected 1 properties, got %d\n", numProps);
435 /* Check a few other implicit properties */
436 checkHash(bigCert, sizeof(bigCert), CALG_MD5, context,
437 CERT_MD5_HASH_PROP_ID);
438 checkHash(
439 context->pCertInfo->Subject.pbData,
440 context->pCertInfo->Subject.cbData,
441 CALG_MD5, context, CERT_SUBJECT_NAME_MD5_HASH_PROP_ID);
442 checkHash(
443 context->pCertInfo->SubjectPublicKeyInfo.PublicKey.pbData,
444 context->pCertInfo->SubjectPublicKeyInfo.PublicKey.cbData,
445 CALG_MD5, context, CERT_SUBJECT_PUBLIC_KEY_MD5_HASH_PROP_ID);
447 /* Test key identifiers and handles and such */
448 size = 0;
449 ret = CertGetCertificateContextProperty(context,
450 CERT_KEY_IDENTIFIER_PROP_ID, NULL, &size);
451 ok(!ret && GetLastError() == ERROR_INVALID_DATA,
452 "Expected ERROR_INVALID_DATA, got %08x\n", GetLastError());
453 size = sizeof(CERT_KEY_CONTEXT);
454 ret = CertGetCertificateContextProperty(context,
455 CERT_KEY_IDENTIFIER_PROP_ID, NULL, &size);
456 ok(!ret && GetLastError() == ERROR_INVALID_DATA,
457 "Expected ERROR_INVALID_DATA, got %08x\n", GetLastError());
458 ret = CertGetCertificateContextProperty(context,
459 CERT_KEY_IDENTIFIER_PROP_ID, &keyContext, &size);
460 ok(!ret && GetLastError() == ERROR_INVALID_DATA,
461 "Expected ERROR_INVALID_DATA, got %08x\n", GetLastError());
462 /* Key context with an invalid size */
463 keyContext.cbSize = 0;
464 ret = CertSetCertificateContextProperty(context,
465 CERT_KEY_IDENTIFIER_PROP_ID, 0, &keyContext);
466 ok(ret, "CertSetCertificateContextProperty failed: %08x\n",
467 GetLastError());
468 size = sizeof(keyContext);
469 ret = CertGetCertificateContextProperty(context,
470 CERT_KEY_IDENTIFIER_PROP_ID, &keyContext, &size);
471 ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
472 GetLastError());
473 keyContext.cbSize = sizeof(keyContext);
474 keyContext.hCryptProv = 0;
475 keyContext.dwKeySpec = AT_SIGNATURE;
476 /* Crash
477 ret = CertSetCertificateContextProperty(context,
478 CERT_KEY_IDENTIFIER_PROP_ID, 0, &keyContext);
479 ret = CertSetCertificateContextProperty(context,
480 CERT_KEY_IDENTIFIER_PROP_ID, CERT_STORE_NO_CRYPT_RELEASE_FLAG,
481 &keyContext);
483 ret = CryptAcquireContextW(&csp, cspNameW,
484 MS_DEF_PROV_W, PROV_RSA_FULL, CRYPT_NEWKEYSET);
485 ok(ret, "CryptAcquireContextW failed: %08x\n", GetLastError());
486 keyContext.hCryptProv = csp;
487 ret = CertSetCertificateContextProperty(context,
488 CERT_KEY_CONTEXT_PROP_ID, 0, &keyContext);
489 ok(ret, "CertSetCertificateContextProperty failed: %08x\n",
490 GetLastError());
491 /* Now that that's set, the key prov handle property is also gettable.
493 size = sizeof(DWORD);
494 ret = CertGetCertificateContextProperty(context,
495 CERT_KEY_PROV_HANDLE_PROP_ID, &keyContext.hCryptProv, &size);
496 ok(ret, "Expected to get the CERT_KEY_PROV_HANDLE_PROP_ID, got %08x\n",
497 GetLastError());
498 /* Remove the key prov handle property.. */
499 ret = CertSetCertificateContextProperty(context,
500 CERT_KEY_PROV_HANDLE_PROP_ID, 0, NULL);
501 ok(ret, "CertSetCertificateContextProperty failed: %08x\n",
502 GetLastError());
503 /* and the key context's CSP is set to NULL. */
504 size = sizeof(keyContext);
505 ret = CertGetCertificateContextProperty(context,
506 CERT_KEY_CONTEXT_PROP_ID, &keyContext, &size);
507 ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
508 GetLastError());
509 ok(keyContext.hCryptProv == 0, "Expected no hCryptProv\n");
511 CryptReleaseContext(csp, 0);
513 CertFreeCertificateContext(context);
516 static void testDupCert(void)
518 HCERTSTORE store;
519 PCCERT_CONTEXT context, dupContext;
520 BOOL ret;
522 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
523 CERT_STORE_CREATE_NEW_FLAG, NULL);
524 ok(store != NULL, "CertOpenStore failed: %d\n", GetLastError());
525 if (!store)
526 return;
528 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
529 bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, &context);
530 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
531 GetLastError());
532 ok(context != NULL, "Expected a valid cert context\n");
533 if (context)
535 ok(context->cbCertEncoded == sizeof(bigCert),
536 "Wrong cert size %d\n", context->cbCertEncoded);
537 ok(!memcmp(context->pbCertEncoded, bigCert, sizeof(bigCert)),
538 "Unexpected encoded cert in context\n");
539 ok(context->hCertStore == store, "Unexpected store\n");
541 dupContext = CertDuplicateCertificateContext(context);
542 ok(dupContext != NULL, "Expected valid duplicate\n");
543 /* Not only is it a duplicate, it's identical: the address is the
544 * same.
546 ok(dupContext == context, "Expected identical context addresses\n");
547 CertFreeCertificateContext(dupContext);
548 CertFreeCertificateContext(context);
550 CertCloseStore(store, 0);
553 static void testFindCert(void)
555 HCERTSTORE store;
556 PCCERT_CONTEXT context = NULL;
557 BOOL ret;
558 CERT_INFO certInfo = { 0 };
559 CRYPT_HASH_BLOB blob;
561 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
562 CERT_STORE_CREATE_NEW_FLAG, NULL);
563 ok(store != NULL, "CertOpenStore failed: %d\n", GetLastError());
564 if (!store)
565 return;
567 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
568 bigCert, sizeof(bigCert), CERT_STORE_ADD_NEW, NULL);
569 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
570 GetLastError());
571 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
572 bigCert2, sizeof(bigCert2), CERT_STORE_ADD_NEW, NULL);
573 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
574 GetLastError());
575 /* This has the same name as bigCert */
576 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
577 certWithUsage, sizeof(certWithUsage), CERT_STORE_ADD_NEW, NULL);
578 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
579 GetLastError());
581 /* Crashes
582 context = CertFindCertificateInStore(NULL, 0, 0, 0, NULL, NULL);
585 /* Check first cert's there, by issuer */
586 certInfo.Subject.pbData = subjectName;
587 certInfo.Subject.cbData = sizeof(subjectName);
588 certInfo.SerialNumber.pbData = serialNum;
589 certInfo.SerialNumber.cbData = sizeof(serialNum);
590 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
591 CERT_FIND_ISSUER_NAME, &certInfo.Subject, NULL);
592 ok(context != NULL, "CertFindCertificateInStore failed: %08x\n",
593 GetLastError());
594 if (context)
596 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
597 CERT_FIND_ISSUER_NAME, &certInfo.Subject, context);
598 ok(context != NULL, "Expected more than one cert\n");
599 if (context)
601 context = CertFindCertificateInStore(store, X509_ASN_ENCODING,
602 0, CERT_FIND_ISSUER_NAME, &certInfo.Subject, context);
603 ok(context == NULL, "Expected precisely two certs\n");
607 /* Check second cert's there as well, by subject name */
608 certInfo.Subject.pbData = subjectName2;
609 certInfo.Subject.cbData = sizeof(subjectName2);
610 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
611 CERT_FIND_SUBJECT_NAME, &certInfo.Subject, NULL);
612 ok(context != NULL, "CertFindCertificateInStore failed: %08x\n",
613 GetLastError());
614 if (context)
616 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
617 CERT_FIND_SUBJECT_NAME, &certInfo.Subject, context);
618 ok(context == NULL, "Expected one cert only\n");
621 /* Strange but true: searching for the subject cert requires you to set
622 * the issuer, not the subject
624 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
625 CERT_FIND_SUBJECT_CERT, &certInfo.Subject, NULL);
626 ok(context == NULL, "Expected no certificate\n");
627 certInfo.Subject.pbData = NULL;
628 certInfo.Subject.cbData = 0;
629 certInfo.Issuer.pbData = subjectName2;
630 certInfo.Issuer.cbData = sizeof(subjectName2);
631 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
632 CERT_FIND_SUBJECT_CERT, &certInfo, NULL);
633 ok(context != NULL, "CertFindCertificateInStore failed: %08x\n",
634 GetLastError());
635 if (context)
637 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
638 CERT_FIND_SUBJECT_CERT, &certInfo.Subject, context);
639 ok(context == NULL, "Expected one cert only\n");
642 /* The nice thing about hashes, they're unique */
643 blob.pbData = bigCertHash;
644 blob.cbData = sizeof(bigCertHash);
645 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
646 CERT_FIND_SHA1_HASH, &blob, NULL);
647 ok(context != NULL, "CertFindCertificateInStore failed: %08x\n",
648 GetLastError());
649 if (context)
651 context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
652 CERT_FIND_SHA1_HASH, &certInfo.Subject, context);
653 ok(context == NULL, "Expected one cert only\n");
656 CertCloseStore(store, 0);
659 static void testGetSubjectCert(void)
661 HCERTSTORE store;
662 PCCERT_CONTEXT context1, context2;
663 CERT_INFO info = { 0 };
664 BOOL ret;
666 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
667 CERT_STORE_CREATE_NEW_FLAG, NULL);
668 ok(store != NULL, "CertOpenStore failed: %d\n", GetLastError());
669 if (!store)
670 return;
672 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
673 bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL);
674 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
675 GetLastError());
676 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
677 bigCert2, sizeof(bigCert2), CERT_STORE_ADD_NEW, &context1);
678 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
679 GetLastError());
680 ok(context1 != NULL, "Expected a context\n");
681 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
682 certWithUsage, sizeof(certWithUsage), CERT_STORE_ADD_NEW, NULL);
683 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
684 GetLastError());
686 context2 = CertGetSubjectCertificateFromStore(store, X509_ASN_ENCODING,
687 NULL);
688 ok(!context2 && GetLastError() == E_INVALIDARG,
689 "Expected E_INVALIDARG, got %08x\n", GetLastError());
690 context2 = CertGetSubjectCertificateFromStore(store, X509_ASN_ENCODING,
691 &info);
692 ok(!context2 && GetLastError() == CRYPT_E_NOT_FOUND,
693 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
694 info.SerialNumber.cbData = sizeof(serialNum);
695 info.SerialNumber.pbData = serialNum;
696 context2 = CertGetSubjectCertificateFromStore(store, X509_ASN_ENCODING,
697 &info);
698 ok(!context2 && GetLastError() == CRYPT_E_NOT_FOUND,
699 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
700 info.Issuer.cbData = sizeof(subjectName2);
701 info.Issuer.pbData = subjectName2;
702 context2 = CertGetSubjectCertificateFromStore(store, X509_ASN_ENCODING,
703 &info);
704 ok(context2 != NULL,
705 "CertGetSubjectCertificateFromStore failed: %08x\n", GetLastError());
706 /* Not only should this find a context, but it should be the same
707 * (same address) as context1.
709 ok(context1 == context2, "Expected identical context addresses\n");
710 CertFreeCertificateContext(context2);
712 CertFreeCertificateContext(context1);
713 CertCloseStore(store, 0);
716 /* This expires in 1970 or so */
717 static const BYTE expiredCert[] = { 0x30, 0x82, 0x01, 0x33, 0x30, 0x81, 0xe2,
718 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0xc4, 0xd7, 0x7f, 0x0e, 0x6f, 0xa6,
719 0x8c, 0xaa, 0x47, 0x47, 0x40, 0xe7, 0xb7, 0x0b, 0x4a, 0x7f, 0x30, 0x09, 0x06,
720 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1d, 0x05, 0x00, 0x30, 0x1f, 0x31, 0x1d, 0x30,
721 0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63, 0x40,
722 0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63,
723 0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x36, 0x39, 0x30, 0x31, 0x30, 0x31, 0x30,
724 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x37, 0x30, 0x30, 0x31, 0x30,
725 0x31, 0x30, 0x36, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x1f, 0x31, 0x1d, 0x30,
726 0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63, 0x40,
727 0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63,
728 0x6f, 0x6d, 0x30, 0x5c, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
729 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x4b, 0x00, 0x30, 0x48, 0x02, 0x41,
730 0x00, 0xa1, 0xaf, 0x4a, 0xea, 0xa7, 0x83, 0x57, 0xc0, 0x37, 0x33, 0x7e, 0x29,
731 0x5e, 0x0d, 0xfc, 0x44, 0x74, 0x3a, 0x1d, 0xc3, 0x1b, 0x1d, 0x96, 0xed, 0x4e,
732 0xf4, 0x1b, 0x98, 0xec, 0x69, 0x1b, 0x04, 0xea, 0x25, 0xcf, 0xb3, 0x2a, 0xf5,
733 0xd9, 0x22, 0xd9, 0x8d, 0x08, 0x39, 0x81, 0xc6, 0xe0, 0x4f, 0x12, 0x37, 0x2a,
734 0x3f, 0x80, 0xa6, 0x6c, 0x67, 0x43, 0x3a, 0xdd, 0x95, 0x0c, 0xbb, 0x2f, 0x6b,
735 0x02, 0x03, 0x01, 0x00, 0x01, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02,
736 0x1d, 0x05, 0x00, 0x03, 0x41, 0x00, 0x8f, 0xa2, 0x5b, 0xd6, 0xdf, 0x34, 0xd0,
737 0xa2, 0xa7, 0x47, 0xf1, 0x13, 0x79, 0xd3, 0xf3, 0x39, 0xbd, 0x4e, 0x2b, 0xa3,
738 0xf4, 0x63, 0x37, 0xac, 0x5a, 0x0c, 0x5e, 0x4d, 0x0d, 0x54, 0x87, 0x4f, 0x31,
739 0xfb, 0xa0, 0xce, 0x8f, 0x9a, 0x2f, 0x4d, 0x48, 0xc6, 0x84, 0x8d, 0xf5, 0x70,
740 0x74, 0x17, 0xa5, 0xf3, 0x66, 0x47, 0x06, 0xd6, 0x64, 0x45, 0xbc, 0x52, 0xef,
741 0x49, 0xe5, 0xf9, 0x65, 0xf3 };
743 /* This expires in 2036 or so */
744 static const BYTE childOfExpired[] = { 0x30, 0x81, 0xcc, 0x30, 0x78, 0xa0,
745 0x03, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86,
746 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x1f, 0x31, 0x1d,
747 0x30, 0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63,
748 0x40, 0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e,
749 0x63, 0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x30, 0x36, 0x30, 0x35, 0x30, 0x35,
750 0x31, 0x37, 0x31, 0x32, 0x34, 0x39, 0x5a, 0x17, 0x0d, 0x33, 0x36, 0x30, 0x35,
751 0x30, 0x35, 0x31, 0x37, 0x31, 0x32, 0x34, 0x39, 0x5a, 0x30, 0x15, 0x31, 0x13,
752 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e,
753 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03,
754 0x01, 0x00, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
755 0x01, 0x05, 0x05, 0x00, 0x03, 0x41, 0x00, 0x20, 0x3b, 0xdb, 0x4d, 0x67, 0x50,
756 0xec, 0x73, 0x9d, 0xf9, 0x85, 0x5d, 0x18, 0xe9, 0xb4, 0x98, 0xe3, 0x31, 0xb7,
757 0x03, 0x0b, 0xc0, 0x39, 0x93, 0x56, 0x81, 0x0a, 0xfc, 0x78, 0xa8, 0x29, 0x42,
758 0x5f, 0x69, 0xfb, 0xbc, 0x5b, 0xf2, 0xa6, 0x2a, 0xbe, 0x91, 0x2c, 0xfc, 0x89,
759 0x69, 0x15, 0x18, 0x58, 0xe5, 0x02, 0x75, 0xf7, 0x2a, 0xb6, 0xa9, 0xfb, 0x47,
760 0x6a, 0x6e, 0x0a, 0x9b, 0xe9, 0xdc };
762 static void testGetIssuerCert(void)
764 BOOL ret;
765 PCCERT_CONTEXT parent, child;
766 DWORD flags = 0xffffffff;
767 HCERTSTORE store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
768 CERT_STORE_CREATE_NEW_FLAG, NULL);
770 ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
772 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
773 expiredCert, sizeof(expiredCert), CERT_STORE_ADD_ALWAYS, NULL);
774 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
775 GetLastError());
777 ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
778 childOfExpired, sizeof(childOfExpired), CERT_STORE_ADD_ALWAYS, &child);
779 ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
780 GetLastError());
782 /* These crash:
783 parent = CertGetIssuerCertificateFromStore(NULL, NULL, NULL, NULL);
784 parent = CertGetIssuerCertificateFromStore(store, NULL, NULL, NULL);
786 parent = CertGetIssuerCertificateFromStore(NULL, NULL, NULL, &flags);
787 ok(!parent && GetLastError() == E_INVALIDARG,
788 "Expected E_INVALIDARG, got %08x\n", GetLastError());
789 parent = CertGetIssuerCertificateFromStore(store, NULL, NULL, &flags);
790 ok(!parent && GetLastError() == E_INVALIDARG,
791 "Expected E_INVALIDARG, got %08x\n", GetLastError());
792 parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
793 ok(!parent && GetLastError() == E_INVALIDARG,
794 "Expected E_INVALIDARG, got %08x\n", GetLastError());
795 /* Confusing: the caller cannot set either of the
796 * CERT_STORE_NO_*_FLAGs, as these are not checks,
797 * they're results:
799 flags = CERT_STORE_NO_CRL_FLAG | CERT_STORE_NO_ISSUER_FLAG;
800 parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
801 ok(!parent && GetLastError() == E_INVALIDARG,
802 "Expected E_INVALIDARG, got %08x\n", GetLastError());
803 /* Perform no checks */
804 flags = 0;
805 parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
806 ok(parent != NULL, "CertGetIssuerCertificateFromStore failed: %08x\n",
807 GetLastError());
808 if (parent)
809 CertFreeCertificateContext(parent);
810 /* Check revocation and signature only */
811 flags = CERT_STORE_REVOCATION_FLAG | CERT_STORE_SIGNATURE_FLAG;
812 parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
813 ok(parent != NULL, "CertGetIssuerCertificateFromStore failed: %08x\n",
814 GetLastError());
815 /* Confusing: CERT_STORE_REVOCATION_FLAG succeeds when there is no CRL by
816 * setting CERT_STORE_NO_CRL_FLAG.
818 ok(flags == (CERT_STORE_REVOCATION_FLAG | CERT_STORE_NO_CRL_FLAG),
819 "Expected CERT_STORE_REVOCATION_FLAG | CERT_STORE_NO_CRL_FLAG, got %08x\n",
820 flags);
821 if (parent)
822 CertFreeCertificateContext(parent);
823 /* Now check just the time */
824 flags = CERT_STORE_TIME_VALIDITY_FLAG;
825 parent = CertGetIssuerCertificateFromStore(store, child, NULL, &flags);
826 ok(parent != NULL, "CertGetIssuerCertificateFromStore failed: %08x\n",
827 GetLastError());
828 /* Oops: the child is not expired, so the time validity check actually
829 * succeeds, even though the signing cert is expired.
831 ok(!flags, "Expected check to succeed, got %08x\n", flags);
832 if (parent)
833 CertFreeCertificateContext(parent);
835 CertFreeCertificateContext(child);
836 CertCloseStore(store, 0);
839 static void testCryptHashCert(void)
841 static const BYTE emptyHash[] = { 0xda, 0x39, 0xa3, 0xee, 0x5e, 0x6b, 0x4b,
842 0x0d, 0x32, 0x55, 0xbf, 0xef, 0x95, 0x60, 0x18, 0x90, 0xaf, 0xd8, 0x07,
843 0x09 };
844 static const BYTE knownHash[] = { 0xae, 0x9d, 0xbf, 0x6d, 0xf5, 0x46, 0xee,
845 0x8b, 0xc5, 0x7a, 0x13, 0xba, 0xc2, 0xb1, 0x04, 0xf2, 0xbf, 0x52, 0xa8,
846 0xa2 };
847 static const BYTE toHash[] = "abcdefghijklmnopqrstuvwxyz0123456789.,;!?:";
848 BOOL ret;
849 BYTE hash[20];
850 DWORD hashLen = sizeof(hash);
852 /* NULL buffer and nonzero length crashes
853 ret = CryptHashCertificate(0, 0, 0, NULL, size, hash, &hashLen);
854 empty hash length also crashes
855 ret = CryptHashCertificate(0, 0, 0, buf, size, hash, NULL);
857 /* Test empty hash */
858 ret = CryptHashCertificate(0, 0, 0, toHash, sizeof(toHash), NULL,
859 &hashLen);
860 ok(ret, "CryptHashCertificate failed: %08x\n", GetLastError());
861 ok(hashLen == sizeof(hash), "Got unexpected size of hash %d\n", hashLen);
862 /* Test with empty buffer */
863 ret = CryptHashCertificate(0, 0, 0, NULL, 0, hash, &hashLen);
864 ok(ret, "CryptHashCertificate failed: %08x\n", GetLastError());
865 ok(!memcmp(hash, emptyHash, sizeof(emptyHash)),
866 "Unexpected hash of nothing\n");
867 /* Test a known value */
868 ret = CryptHashCertificate(0, 0, 0, toHash, sizeof(toHash), hash,
869 &hashLen);
870 ok(ret, "CryptHashCertificate failed: %08x\n", GetLastError());
871 ok(!memcmp(hash, knownHash, sizeof(knownHash)), "Unexpected hash\n");
874 static void verifySig(HCRYPTPROV csp, const BYTE *toSign, size_t toSignLen,
875 const BYTE *sig, unsigned int sigLen)
877 HCRYPTHASH hash;
878 BOOL ret = CryptCreateHash(csp, CALG_SHA1, 0, 0, &hash);
880 ok(ret, "CryptCreateHash failed: %08x\n", GetLastError());
881 if (ret)
883 BYTE mySig[64];
884 DWORD mySigSize = sizeof(mySig);
886 ret = CryptHashData(hash, toSign, toSignLen, 0);
887 ok(ret, "CryptHashData failed: %08x\n", GetLastError());
888 /* use the A variant so the test can run on Win9x */
889 ret = CryptSignHashA(hash, AT_SIGNATURE, NULL, 0, mySig, &mySigSize);
890 ok(ret, "CryptSignHash failed: %08x\n", GetLastError());
891 if (ret)
893 ok(mySigSize == sigLen, "Expected sig length %d, got %d\n",
894 sigLen, mySigSize);
895 ok(!memcmp(mySig, sig, sigLen), "Unexpected signature\n");
897 CryptDestroyHash(hash);
901 /* Tests signing the certificate described by toBeSigned with the CSP passed in,
902 * using the algorithm with OID sigOID. The CSP is assumed to be empty, and a
903 * keyset named AT_SIGNATURE will be added to it. The signing key will be
904 * stored in *key, and the signature will be stored in sig. sigLen should be
905 * at least 64 bytes.
907 static void testSignCert(HCRYPTPROV csp, const CRYPT_DATA_BLOB *toBeSigned,
908 LPCSTR sigOID, HCRYPTKEY *key, BYTE *sig, DWORD *sigLen)
910 BOOL ret;
911 DWORD size = 0;
912 CRYPT_ALGORITHM_IDENTIFIER algoID = { NULL, { 0, NULL } };
914 /* These all crash
915 ret = CryptSignCertificate(0, 0, 0, NULL, 0, NULL, NULL, NULL, NULL);
916 ret = CryptSignCertificate(0, 0, 0, NULL, 0, NULL, NULL, NULL, &size);
917 ret = CryptSignCertificate(0, 0, 0, toBeSigned->pbData, toBeSigned->cbData,
918 NULL, NULL, NULL, &size);
920 ret = CryptSignCertificate(0, 0, 0, toBeSigned->pbData, toBeSigned->cbData,
921 &algoID, NULL, NULL, &size);
922 ok(!ret && GetLastError() == NTE_BAD_ALGID,
923 "Expected NTE_BAD_ALGID, got %08x\n", GetLastError());
924 algoID.pszObjId = (LPSTR)sigOID;
925 ret = CryptSignCertificate(0, 0, 0, toBeSigned->pbData, toBeSigned->cbData,
926 &algoID, NULL, NULL, &size);
927 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
928 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
929 ret = CryptSignCertificate(0, AT_SIGNATURE, 0, toBeSigned->pbData,
930 toBeSigned->cbData, &algoID, NULL, NULL, &size);
931 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
932 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
934 /* No keys exist in the new CSP yet.. */
935 ret = CryptSignCertificate(csp, AT_SIGNATURE, 0, toBeSigned->pbData,
936 toBeSigned->cbData, &algoID, NULL, NULL, &size);
937 ok(!ret && (GetLastError() == NTE_BAD_KEYSET || GetLastError() ==
938 NTE_NO_KEY), "Expected NTE_BAD_KEYSET or NTE_NO_KEY, got %08x\n",
939 GetLastError());
940 ret = CryptGenKey(csp, AT_SIGNATURE, 0, key);
941 ok(ret, "CryptGenKey failed: %08x\n", GetLastError());
942 if (ret)
944 ret = CryptSignCertificate(csp, AT_SIGNATURE, 0, toBeSigned->pbData,
945 toBeSigned->cbData, &algoID, NULL, NULL, &size);
946 ok(ret, "CryptSignCertificate failed: %08x\n", GetLastError());
947 ok(size <= *sigLen, "Expected size <= %d, got %d\n", *sigLen, size);
948 if (ret)
950 ret = CryptSignCertificate(csp, AT_SIGNATURE, 0, toBeSigned->pbData,
951 toBeSigned->cbData, &algoID, NULL, sig, &size);
952 ok(ret, "CryptSignCertificate failed: %08x\n", GetLastError());
953 if (ret)
955 *sigLen = size;
956 verifySig(csp, toBeSigned->pbData, toBeSigned->cbData, sig,
957 size);
963 static void testVerifyCertSig(HCRYPTPROV csp, const CRYPT_DATA_BLOB *toBeSigned,
964 LPCSTR sigOID, const BYTE *sig, DWORD sigLen)
966 CERT_SIGNED_CONTENT_INFO info;
967 LPBYTE cert = NULL;
968 DWORD size = 0;
969 BOOL ret;
971 if(pCryptVerifyCertificateSignatureEx) {
972 ret = pCryptVerifyCertificateSignatureEx(0, 0, 0, NULL, 0, NULL, 0, NULL);
973 ok(!ret && GetLastError() == E_INVALIDARG,
974 "Expected E_INVALIDARG, got %08x\n", GetLastError());
975 ret = pCryptVerifyCertificateSignatureEx(csp, 0, 0, NULL, 0, NULL, 0, NULL);
976 ok(!ret && GetLastError() == E_INVALIDARG,
977 "Expected E_INVALIDARG, got %08x\n", GetLastError());
978 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING, 0, NULL, 0,
979 NULL, 0, NULL);
980 ok(!ret && GetLastError() == E_INVALIDARG,
981 "Expected E_INVALIDARG, got %08x\n", GetLastError());
982 /* This crashes
983 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
984 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, NULL, 0, NULL, 0, NULL);
987 info.ToBeSigned.cbData = toBeSigned->cbData;
988 info.ToBeSigned.pbData = toBeSigned->pbData;
989 info.SignatureAlgorithm.pszObjId = (LPSTR)sigOID;
990 info.SignatureAlgorithm.Parameters.cbData = 0;
991 info.Signature.cbData = sigLen;
992 info.Signature.pbData = (BYTE *)sig;
993 info.Signature.cUnusedBits = 0;
994 ret = CryptEncodeObjectEx(X509_ASN_ENCODING, X509_CERT, &info,
995 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&cert, &size);
996 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
997 if (cert)
999 CRYPT_DATA_BLOB certBlob = { 0, NULL };
1000 PCERT_PUBLIC_KEY_INFO pubKeyInfo = NULL;
1002 if(pCryptVerifyCertificateSignatureEx) {
1003 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
1004 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob, 0, NULL, 0, NULL);
1005 ok(!ret && GetLastError() == CRYPT_E_ASN1_EOD,
1006 "Expected CRYPT_E_ASN1_EOD, got %08x\n", GetLastError());
1007 certBlob.cbData = 1;
1008 certBlob.pbData = (void *)0xdeadbeef;
1009 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
1010 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob, 0, NULL, 0, NULL);
1011 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
1012 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
1013 certBlob.cbData = size;
1014 certBlob.pbData = cert;
1015 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
1016 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob, 0, NULL, 0, NULL);
1017 ok(!ret && GetLastError() == E_INVALIDARG,
1018 "Expected E_INVALIDARG, got %08x\n", GetLastError());
1019 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
1020 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob,
1021 CRYPT_VERIFY_CERT_SIGN_ISSUER_NULL, NULL, 0, NULL);
1022 ok(!ret && GetLastError() == E_INVALIDARG,
1023 "Expected E_INVALIDARG, got %08x\n", GetLastError());
1024 /* This crashes
1025 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
1026 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob,
1027 CRYPT_VERIFY_CERT_SIGN_ISSUER_PUBKEY, NULL, 0, NULL);
1030 CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING,
1031 (LPSTR)sigOID, 0, NULL, NULL, &size);
1032 pubKeyInfo = HeapAlloc(GetProcessHeap(), 0, size);
1033 if (pubKeyInfo)
1035 ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE,
1036 X509_ASN_ENCODING, (LPSTR)sigOID, 0, NULL, pubKeyInfo, &size);
1037 ok(ret, "CryptExportKey failed: %08x\n", GetLastError());
1038 if (ret && pCryptVerifyCertificateSignatureEx)
1040 ret = pCryptVerifyCertificateSignatureEx(csp, X509_ASN_ENCODING,
1041 CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB, &certBlob,
1042 CRYPT_VERIFY_CERT_SIGN_ISSUER_PUBKEY, pubKeyInfo, 0, NULL);
1043 ok(ret, "CryptVerifyCertificateSignatureEx failed: %08x\n",
1044 GetLastError());
1046 HeapFree(GetProcessHeap(), 0, pubKeyInfo);
1048 LocalFree(cert);
1052 static BYTE emptyCert[] = { 0x30, 0x00 };
1054 static void testCertSigs(void)
1056 HCRYPTPROV csp;
1057 CRYPT_DATA_BLOB toBeSigned = { sizeof(emptyCert), emptyCert };
1058 BOOL ret;
1059 HCRYPTKEY key;
1060 BYTE sig[64];
1061 DWORD sigSize = sizeof(sig);
1063 /* Just in case a previous run failed, delete this thing */
1064 CryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
1065 CRYPT_DELETEKEYSET);
1066 ret = CryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
1067 CRYPT_NEWKEYSET);
1068 ok(ret, "CryptAcquireContext failed: %08x\n", GetLastError());
1070 testSignCert(csp, &toBeSigned, szOID_RSA_SHA1RSA, &key, sig, &sigSize);
1071 testVerifyCertSig(csp, &toBeSigned, szOID_RSA_SHA1RSA, sig, sigSize);
1073 CryptDestroyKey(key);
1074 CryptReleaseContext(csp, 0);
1075 ret = CryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
1076 CRYPT_DELETEKEYSET);
1079 static const BYTE md5SignedEmptyCert[] = {
1080 0x30,0x56,0x30,0x33,0x02,0x00,0x30,0x02,0x06,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,
1081 0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,
1082 0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x07,
1083 0x30,0x02,0x06,0x00,0x03,0x01,0x00,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,
1084 0x0d,0x02,0x05,0x05,0x00,0x03,0x11,0x00,0xfb,0x0f,0x66,0x82,0x66,0xd9,0xe5,0xf8,
1085 0xd8,0xa2,0x55,0x2b,0xe1,0xa5,0xd9,0x04 };
1086 static const BYTE md5SignedEmptyCertNoNull[] = {
1087 0x30,0x54,0x30,0x33,0x02,0x00,0x30,0x02,0x06,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,
1088 0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,
1089 0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x07,
1090 0x30,0x02,0x06,0x00,0x03,0x01,0x00,0x30,0x0a,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,
1091 0x0d,0x02,0x05,0x03,0x11,0x00,0x04,0xd9,0xa5,0xe1,0x2b,0x55,0xa2,0xd8,0xf8,0xe5,
1092 0xd9,0x66,0x82,0x66,0x0f,0xfb };
1094 static void testSignAndEncodeCert(void)
1096 static char oid_rsa_md5rsa[] = szOID_RSA_MD5RSA;
1097 static char oid_rsa_md5[] = szOID_RSA_MD5;
1098 BOOL ret;
1099 DWORD size;
1100 CRYPT_ALGORITHM_IDENTIFIER algID = { 0 };
1101 CERT_INFO info = { 0 };
1103 /* Crash
1104 ret = CryptSignAndEncodeCertificate(0, 0, 0, NULL, NULL, NULL, NULL, NULL,
1105 NULL);
1106 ret = CryptSignAndEncodeCertificate(0, 0, 0, NULL, NULL, NULL, NULL, NULL,
1107 &size);
1109 ret = CryptSignAndEncodeCertificate(0, 0, 0, NULL, NULL, &algID, NULL, NULL,
1110 &size);
1111 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
1112 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
1113 ret = CryptSignAndEncodeCertificate(0, 0, X509_ASN_ENCODING, NULL, NULL,
1114 &algID, NULL, NULL, &size);
1115 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
1116 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
1117 ret = CryptSignAndEncodeCertificate(0, 0, 0, X509_CERT_TO_BE_SIGNED, NULL,
1118 &algID, NULL, NULL, &size);
1119 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
1120 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
1121 ret = CryptSignAndEncodeCertificate(0, 0, X509_ASN_ENCODING,
1122 X509_CERT_TO_BE_SIGNED, NULL, &algID, NULL, NULL, &size);
1123 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
1124 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
1125 /* Crashes
1126 ret = CryptSignAndEncodeCertificate(0, 0, X509_ASN_ENCODING,
1127 X509_CERT_TO_BE_SIGNED, &info, NULL, NULL, NULL, &size);
1129 ret = CryptSignAndEncodeCertificate(0, 0, X509_ASN_ENCODING,
1130 X509_CERT_TO_BE_SIGNED, &info, &algID, NULL, NULL, &size);
1131 ok(!ret && GetLastError() == NTE_BAD_ALGID,
1132 "Expected NTE_BAD_ALGID, got %08x\n", GetLastError());
1133 algID.pszObjId = oid_rsa_md5rsa;
1134 ret = CryptSignAndEncodeCertificate(0, 0, X509_ASN_ENCODING,
1135 X509_CERT_TO_BE_SIGNED, &info, &algID, NULL, NULL, &size);
1136 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1137 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
1138 algID.pszObjId = oid_rsa_md5;
1139 ret = CryptSignAndEncodeCertificate(0, 0, X509_ASN_ENCODING,
1140 X509_CERT_TO_BE_SIGNED, &info, &algID, NULL, NULL, &size);
1141 ok(ret, "CryptSignAndEncodeCertificate failed: %08x\n", GetLastError());
1142 if (ret)
1144 LPBYTE buf = HeapAlloc(GetProcessHeap(), 0, size);
1146 if (buf)
1148 ret = CryptSignAndEncodeCertificate(0, 0, X509_ASN_ENCODING,
1149 X509_CERT_TO_BE_SIGNED, &info, &algID, NULL, buf, &size);
1150 ok(ret, "CryptSignAndEncodeCertificate failed: %08x\n",
1151 GetLastError());
1152 /* Tricky: because the NULL parameters may either be omitted or
1153 * included as an asn.1-encoded NULL (0x05,0x00), two different
1154 * values are allowed.
1156 ok(size == sizeof(md5SignedEmptyCert) ||
1157 size == sizeof(md5SignedEmptyCertNoNull), "Unexpected size %d\n",
1158 size);
1159 if (size == sizeof(md5SignedEmptyCert))
1160 ok(!memcmp(buf, md5SignedEmptyCert, size),
1161 "Unexpected value\n");
1162 else if (size == sizeof(md5SignedEmptyCertNoNull))
1163 ok(!memcmp(buf, md5SignedEmptyCertNoNull, size),
1164 "Unexpected value\n");
1165 HeapFree(GetProcessHeap(), 0, buf);
1170 static void testCreateSelfSignCert(void)
1172 PCCERT_CONTEXT context;
1173 CERT_NAME_BLOB name = { sizeof(subjectName), subjectName };
1174 HCRYPTPROV csp;
1175 BOOL ret;
1176 HCRYPTKEY key;
1177 CRYPT_KEY_PROV_INFO info;
1179 /* This crashes:
1180 context = CertCreateSelfSignCertificate(0, NULL, 0, NULL, NULL, NULL, NULL,
1181 NULL);
1182 * Calling this with no first parameter creates a new key container, which
1183 * lasts beyond the test, so I don't test that. Nb: the generated key
1184 * name is a GUID.
1185 context = CertCreateSelfSignCertificate(0, &name, 0, NULL, NULL, NULL, NULL,
1186 NULL);
1189 /* Acquire a CSP */
1190 CryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
1191 CRYPT_DELETEKEYSET);
1192 ret = CryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
1193 CRYPT_NEWKEYSET);
1194 ok(ret, "CryptAcquireContext failed: %08x\n", GetLastError());
1196 context = CertCreateSelfSignCertificate(csp, &name, 0, NULL, NULL, NULL,
1197 NULL, NULL);
1198 ok(!context && GetLastError() == NTE_NO_KEY,
1199 "Expected NTE_NO_KEY, got %08x\n", GetLastError());
1200 ret = CryptGenKey(csp, AT_SIGNATURE, 0, &key);
1201 ok(ret, "CryptGenKey failed: %08x\n", GetLastError());
1202 if (ret)
1204 context = CertCreateSelfSignCertificate(csp, &name, 0, NULL, NULL, NULL,
1205 NULL, NULL);
1206 ok(context != NULL, "CertCreateSelfSignCertificate failed: %08x\n",
1207 GetLastError());
1208 if (context)
1210 DWORD size = 0;
1211 PCRYPT_KEY_PROV_INFO info;
1213 /* The context must have a key provider info property */
1214 ret = CertGetCertificateContextProperty(context,
1215 CERT_KEY_PROV_INFO_PROP_ID, NULL, &size);
1216 ok(ret && size, "Expected non-zero key provider info\n");
1217 if (size)
1219 info = HeapAlloc(GetProcessHeap(), 0, size);
1220 if (info)
1222 ret = CertGetCertificateContextProperty(context,
1223 CERT_KEY_PROV_INFO_PROP_ID, info, &size);
1224 ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
1225 GetLastError());
1226 if (ret)
1228 /* Sanity-check the key provider */
1229 ok(!lstrcmpW(info->pwszContainerName, cspNameW),
1230 "Unexpected key container\n");
1231 ok(!lstrcmpW(info->pwszProvName, MS_DEF_PROV_W),
1232 "Unexpected provider\n");
1233 ok(info->dwKeySpec == AT_SIGNATURE,
1234 "Expected AT_SIGNATURE, got %d\n", info->dwKeySpec);
1236 HeapFree(GetProcessHeap(), 0, info);
1240 CertFreeCertificateContext(context);
1243 CryptDestroyKey(key);
1246 CryptReleaseContext(csp, 0);
1247 ret = CryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
1248 CRYPT_DELETEKEYSET);
1250 /* do the same test with AT_KEYEXCHANGE and key info*/
1251 memset(&info,0,sizeof(info));
1252 info.dwProvType = PROV_RSA_FULL;
1253 info.dwKeySpec = AT_KEYEXCHANGE;
1254 info.pwszProvName = (LPWSTR) MS_DEF_PROV_W;
1255 info.pwszContainerName = cspNameW;
1256 context = CertCreateSelfSignCertificate(0, &name, 0, &info, NULL, NULL,
1257 NULL, NULL);
1258 ok(context != NULL, "CertCreateSelfSignCertificate failed: %08x\n",
1259 GetLastError());
1260 if (context)
1262 DWORD size = 0;
1263 PCRYPT_KEY_PROV_INFO info;
1265 /* The context must have a key provider info property */
1266 ret = CertGetCertificateContextProperty(context,
1267 CERT_KEY_PROV_INFO_PROP_ID, NULL, &size);
1268 ok(ret && size, "Expected non-zero key provider info\n");
1269 if (size)
1271 info = HeapAlloc(GetProcessHeap(), 0, size);
1272 if (info)
1274 ret = CertGetCertificateContextProperty(context,
1275 CERT_KEY_PROV_INFO_PROP_ID, info, &size);
1276 ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
1277 GetLastError());
1278 if (ret)
1280 /* Sanity-check the key provider */
1281 ok(!lstrcmpW(info->pwszContainerName, cspNameW),
1282 "Unexpected key container\n");
1283 ok(!lstrcmpW(info->pwszProvName, MS_DEF_PROV_W),
1284 "Unexpected provider\n");
1285 ok(info->dwKeySpec == AT_KEYEXCHANGE,
1286 "Expected AT_KEYEXCHANGE, got %d\n", info->dwKeySpec);
1288 HeapFree(GetProcessHeap(), 0, info);
1292 CertFreeCertificateContext(context);
1295 CryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
1296 CRYPT_DELETEKEYSET);
1299 static const LPCSTR keyUsages[] = { szOID_PKIX_KP_CODE_SIGNING,
1300 szOID_PKIX_KP_CLIENT_AUTH, szOID_RSA_RSA };
1302 static void testKeyUsage(void)
1304 BOOL ret;
1305 PCCERT_CONTEXT context;
1306 DWORD size;
1308 /* Test base cases */
1309 ret = CertGetEnhancedKeyUsage(NULL, 0, NULL, NULL);
1310 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1311 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
1312 size = 1;
1313 ret = CertGetEnhancedKeyUsage(NULL, 0, NULL, &size);
1314 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1315 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
1316 size = 0;
1317 ret = CertGetEnhancedKeyUsage(NULL, 0, NULL, &size);
1318 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1319 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
1320 /* These crash
1321 ret = CertSetEnhancedKeyUsage(NULL, NULL);
1322 usage.cUsageIdentifier = 0;
1323 ret = CertSetEnhancedKeyUsage(NULL, &usage);
1325 /* Test with a cert with no enhanced key usage extension */
1326 context = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert,
1327 sizeof(bigCert));
1328 ok(context != NULL, "CertCreateCertificateContext failed: %08x\n",
1329 GetLastError());
1330 if (context)
1332 static const char oid[] = "1.2.3.4";
1333 BYTE buf[sizeof(CERT_ENHKEY_USAGE) + 2 * (sizeof(LPSTR) + sizeof(oid))];
1334 PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
1336 ret = CertGetEnhancedKeyUsage(context, 0, NULL, NULL);
1337 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
1338 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
1339 size = 1;
1340 ret = CertGetEnhancedKeyUsage(context, 0, NULL, &size);
1341 if (ret)
1343 /* Windows 2000, ME, or later: even though it succeeded, we expect
1344 * CRYPT_E_NOT_FOUND, which indicates there is no enhanced key
1345 * usage set for this cert (which implies it's valid for all uses.)
1347 ok(GetLastError() == CRYPT_E_NOT_FOUND,
1348 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
1349 ok(size == sizeof(CERT_ENHKEY_USAGE), "Wrong size %d\n", size);
1350 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
1351 ok(ret, "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
1352 ok(pUsage->cUsageIdentifier == 0, "Expected 0 usages, got %d\n",
1353 pUsage->cUsageIdentifier);
1355 else
1357 /* Windows NT, 95, or 98: it fails, and the last error is
1358 * CRYPT_E_NOT_FOUND.
1360 ok(GetLastError() == CRYPT_E_NOT_FOUND,
1361 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
1363 /* I can add a usage identifier when no key usage has been set */
1364 ret = CertAddEnhancedKeyUsageIdentifier(context, oid);
1365 ok(ret, "CertAddEnhancedKeyUsageIdentifier failed: %08x\n",
1366 GetLastError());
1367 size = sizeof(buf);
1368 ret = CertGetEnhancedKeyUsage(context,
1369 CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG, pUsage, &size);
1370 ok(ret && GetLastError() == 0,
1371 "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
1372 ok(pUsage->cUsageIdentifier == 1, "Expected 1 usage, got %d\n",
1373 pUsage->cUsageIdentifier);
1374 if (pUsage->cUsageIdentifier)
1375 ok(!strcmp(pUsage->rgpszUsageIdentifier[0], oid),
1376 "Expected %s, got %s\n", oid, pUsage->rgpszUsageIdentifier[0]);
1377 /* Now set an empty key usage */
1378 pUsage->cUsageIdentifier = 0;
1379 ret = CertSetEnhancedKeyUsage(context, pUsage);
1380 ok(ret, "CertSetEnhancedKeyUsage failed: %08x\n", GetLastError());
1381 /* Shouldn't find it in the cert */
1382 size = sizeof(buf);
1383 ret = CertGetEnhancedKeyUsage(context,
1384 CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, pUsage, &size);
1385 ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
1386 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
1387 /* Should find it as an extended property */
1388 ret = CertGetEnhancedKeyUsage(context,
1389 CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG, pUsage, &size);
1390 ok(ret && GetLastError() == 0,
1391 "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
1392 ok(pUsage->cUsageIdentifier == 0, "Expected 0 usages, got %d\n",
1393 pUsage->cUsageIdentifier);
1394 /* Should find it as either */
1395 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
1396 ok(ret && GetLastError() == 0,
1397 "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
1398 ok(pUsage->cUsageIdentifier == 0, "Expected 0 usages, got %d\n",
1399 pUsage->cUsageIdentifier);
1400 /* Add a usage identifier */
1401 ret = CertAddEnhancedKeyUsageIdentifier(context, oid);
1402 ok(ret, "CertAddEnhancedKeyUsageIdentifier failed: %08x\n",
1403 GetLastError());
1404 size = sizeof(buf);
1405 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
1406 ok(ret && GetLastError() == 0,
1407 "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
1408 ok(pUsage->cUsageIdentifier == 1, "Expected 1 identifier, got %d\n",
1409 pUsage->cUsageIdentifier);
1410 if (pUsage->cUsageIdentifier)
1411 ok(!strcmp(pUsage->rgpszUsageIdentifier[0], oid),
1412 "Expected %s, got %s\n", oid, pUsage->rgpszUsageIdentifier[0]);
1413 /* Yep, I can re-add the same usage identifier */
1414 ret = CertAddEnhancedKeyUsageIdentifier(context, oid);
1415 ok(ret, "CertAddEnhancedKeyUsageIdentifier failed: %08x\n",
1416 GetLastError());
1417 size = sizeof(buf);
1418 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
1419 ok(ret && GetLastError() == 0,
1420 "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
1421 ok(pUsage->cUsageIdentifier == 2, "Expected 2 identifiers, got %d\n",
1422 pUsage->cUsageIdentifier);
1423 if (pUsage->cUsageIdentifier)
1424 ok(!strcmp(pUsage->rgpszUsageIdentifier[0], oid),
1425 "Expected %s, got %s\n", oid, pUsage->rgpszUsageIdentifier[0]);
1426 if (pUsage->cUsageIdentifier >= 2)
1427 ok(!strcmp(pUsage->rgpszUsageIdentifier[1], oid),
1428 "Expected %s, got %s\n", oid, pUsage->rgpszUsageIdentifier[1]);
1429 /* Now set a NULL extended property--this deletes the property. */
1430 ret = CertSetEnhancedKeyUsage(context, NULL);
1431 ok(ret, "CertSetEnhancedKeyUsage failed: %08x\n", GetLastError());
1432 SetLastError(0xbaadcafe);
1433 size = sizeof(buf);
1434 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
1435 ok(GetLastError() == CRYPT_E_NOT_FOUND,
1436 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
1438 CertFreeCertificateContext(context);
1440 /* Now test with a cert with an enhanced key usage extension */
1441 context = CertCreateCertificateContext(X509_ASN_ENCODING, certWithUsage,
1442 sizeof(certWithUsage));
1443 ok(context != NULL, "CertCreateCertificateContext failed: %08x\n",
1444 GetLastError());
1445 if (context)
1447 LPBYTE buf = NULL;
1448 DWORD bufSize = 0, i;
1450 /* The size may depend on what flags are used to query it, so I
1451 * realloc the buffer for each test.
1453 ret = CertGetEnhancedKeyUsage(context,
1454 CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, NULL, &bufSize);
1455 ok(ret, "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
1456 buf = HeapAlloc(GetProcessHeap(), 0, bufSize);
1457 if (buf)
1459 PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
1461 /* Should find it in the cert */
1462 size = bufSize;
1463 ret = CertGetEnhancedKeyUsage(context,
1464 CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, pUsage, &size);
1465 ok(ret && GetLastError() == 0,
1466 "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
1467 ok(pUsage->cUsageIdentifier == 3, "Expected 3 usages, got %d\n",
1468 pUsage->cUsageIdentifier);
1469 for (i = 0; i < pUsage->cUsageIdentifier; i++)
1470 ok(!strcmp(pUsage->rgpszUsageIdentifier[i], keyUsages[i]),
1471 "Expected %s, got %s\n", keyUsages[i],
1472 pUsage->rgpszUsageIdentifier[i]);
1473 HeapFree(GetProcessHeap(), 0, buf);
1475 ret = CertGetEnhancedKeyUsage(context, 0, NULL, &bufSize);
1476 ok(ret, "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
1477 buf = HeapAlloc(GetProcessHeap(), 0, bufSize);
1478 if (buf)
1480 PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
1482 /* Should find it as either */
1483 size = bufSize;
1484 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
1485 /* In Windows, GetLastError returns CRYPT_E_NOT_FOUND not found
1486 * here, even though the return is successful and the usage id
1487 * count is positive. I don't enforce that here.
1489 ok(ret,
1490 "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
1491 ok(pUsage->cUsageIdentifier == 3, "Expected 3 usages, got %d\n",
1492 pUsage->cUsageIdentifier);
1493 for (i = 0; i < pUsage->cUsageIdentifier; i++)
1494 ok(!strcmp(pUsage->rgpszUsageIdentifier[i], keyUsages[i]),
1495 "Expected %s, got %s\n", keyUsages[i],
1496 pUsage->rgpszUsageIdentifier[i]);
1497 HeapFree(GetProcessHeap(), 0, buf);
1499 /* Shouldn't find it as an extended property */
1500 ret = CertGetEnhancedKeyUsage(context,
1501 CERT_FIND_PROP_ONLY_ENHKEY_USAGE_FLAG, NULL, &size);
1502 ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
1503 "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
1504 /* Adding a usage identifier overrides the cert's usage!? */
1505 ret = CertAddEnhancedKeyUsageIdentifier(context, szOID_RSA_RSA);
1506 ok(ret, "CertAddEnhancedKeyUsageIdentifier failed: %08x\n",
1507 GetLastError());
1508 ret = CertGetEnhancedKeyUsage(context, 0, NULL, &bufSize);
1509 ok(ret, "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
1510 buf = HeapAlloc(GetProcessHeap(), 0, bufSize);
1511 if (buf)
1513 PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
1515 /* Should find it as either */
1516 size = bufSize;
1517 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
1518 ok(ret,
1519 "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
1520 ok(pUsage->cUsageIdentifier == 1, "Expected 1 usage, got %d\n",
1521 pUsage->cUsageIdentifier);
1522 ok(!strcmp(pUsage->rgpszUsageIdentifier[0], szOID_RSA_RSA),
1523 "Expected %s, got %s\n", szOID_RSA_RSA,
1524 pUsage->rgpszUsageIdentifier[0]);
1525 HeapFree(GetProcessHeap(), 0, buf);
1527 /* But querying the cert directly returns its usage */
1528 ret = CertGetEnhancedKeyUsage(context,
1529 CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, NULL, &bufSize);
1530 ok(ret, "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
1531 buf = HeapAlloc(GetProcessHeap(), 0, bufSize);
1532 if (buf)
1534 PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
1536 size = bufSize;
1537 ret = CertGetEnhancedKeyUsage(context,
1538 CERT_FIND_EXT_ONLY_ENHKEY_USAGE_FLAG, pUsage, &size);
1539 ok(ret,
1540 "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
1541 ok(pUsage->cUsageIdentifier == 3, "Expected 3 usages, got %d\n",
1542 pUsage->cUsageIdentifier);
1543 for (i = 0; i < pUsage->cUsageIdentifier; i++)
1544 ok(!strcmp(pUsage->rgpszUsageIdentifier[i], keyUsages[i]),
1545 "Expected %s, got %s\n", keyUsages[i],
1546 pUsage->rgpszUsageIdentifier[i]);
1547 HeapFree(GetProcessHeap(), 0, buf);
1549 /* And removing the only usage identifier in the extended property
1550 * results in the cert's key usage being found.
1552 ret = CertRemoveEnhancedKeyUsageIdentifier(context, szOID_RSA_RSA);
1553 ok(ret, "CertRemoveEnhancedKeyUsage failed: %08x\n", GetLastError());
1554 ret = CertGetEnhancedKeyUsage(context, 0, NULL, &bufSize);
1555 ok(ret, "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
1556 buf = HeapAlloc(GetProcessHeap(), 0, bufSize);
1557 if (buf)
1559 PCERT_ENHKEY_USAGE pUsage = (PCERT_ENHKEY_USAGE)buf;
1561 /* Should find it as either */
1562 size = bufSize;
1563 ret = CertGetEnhancedKeyUsage(context, 0, pUsage, &size);
1564 ok(ret,
1565 "CertGetEnhancedKeyUsage failed: %08x\n", GetLastError());
1566 ok(pUsage->cUsageIdentifier == 3, "Expected 3 usages, got %d\n",
1567 pUsage->cUsageIdentifier);
1568 for (i = 0; i < pUsage->cUsageIdentifier; i++)
1569 ok(!strcmp(pUsage->rgpszUsageIdentifier[i], keyUsages[i]),
1570 "Expected %s, got %s\n", keyUsages[i],
1571 pUsage->rgpszUsageIdentifier[i]);
1572 HeapFree(GetProcessHeap(), 0, buf);
1575 CertFreeCertificateContext(context);
1579 static void testCompareCertName(void)
1581 static BYTE bogus[] = { 1, 2, 3, 4 };
1582 static BYTE bogusPrime[] = { 0, 1, 2, 3, 4 };
1583 static BYTE emptyPrime[] = { 0x30, 0x00, 0x01 };
1584 BOOL ret;
1585 CERT_NAME_BLOB blob1, blob2;
1587 /* crashes
1588 ret = CertCompareCertificateName(0, NULL, NULL);
1590 /* An empty name checks against itself.. */
1591 blob1.pbData = emptyCert;
1592 blob1.cbData = sizeof(emptyCert);
1593 ret = CertCompareCertificateName(0, &blob1, &blob1);
1594 ok(ret, "CertCompareCertificateName failed: %08x\n", GetLastError());
1595 /* It doesn't have to be a valid encoded name.. */
1596 blob1.pbData = bogus;
1597 blob1.cbData = sizeof(bogus);
1598 ret = CertCompareCertificateName(0, &blob1, &blob1);
1599 ok(ret, "CertCompareCertificateName failed: %08x\n", GetLastError());
1600 /* Leading zeroes matter.. */
1601 blob2.pbData = bogusPrime;
1602 blob2.cbData = sizeof(bogusPrime);
1603 ret = CertCompareCertificateName(0, &blob1, &blob2);
1604 ok(!ret, "Expected failure\n");
1605 /* As do trailing extra bytes. */
1606 blob2.pbData = emptyPrime;
1607 blob2.cbData = sizeof(emptyPrime);
1608 ret = CertCompareCertificateName(0, &blob1, &blob2);
1609 ok(!ret, "Expected failure\n");
1612 static BYTE int1[] = { 0x88, 0xff, 0xff, 0xff };
1613 static BYTE int2[] = { 0x88, 0xff };
1614 static BYTE int3[] = { 0x23, 0xff };
1615 static BYTE int4[] = { 0x7f, 0x00 };
1616 static BYTE int5[] = { 0x7f };
1617 static BYTE int6[] = { 0x80, 0x00, 0x00, 0x00 };
1618 static BYTE int7[] = { 0x80, 0x00 };
1620 static struct IntBlobTest
1622 CRYPT_INTEGER_BLOB blob1;
1623 CRYPT_INTEGER_BLOB blob2;
1624 BOOL areEqual;
1625 } intBlobs[] = {
1626 { { sizeof(int1), int1 }, { sizeof(int2), int2 }, TRUE },
1627 { { sizeof(int3), int3 }, { sizeof(int3), int3 }, TRUE },
1628 { { sizeof(int4), int4 }, { sizeof(int5), int5 }, TRUE },
1629 { { sizeof(int6), int6 }, { sizeof(int7), int7 }, TRUE },
1630 { { sizeof(int1), int1 }, { sizeof(int7), int7 }, FALSE },
1633 static void testCompareIntegerBlob(void)
1635 DWORD i;
1636 BOOL ret;
1638 for (i = 0; i < sizeof(intBlobs) / sizeof(intBlobs[0]); i++)
1640 ret = CertCompareIntegerBlob(&intBlobs[i].blob1, &intBlobs[i].blob2);
1641 ok(ret == intBlobs[i].areEqual,
1642 "%d: expected blobs %s compare\n", i, intBlobs[i].areEqual ?
1643 "to" : "not to");
1647 static void testComparePublicKeyInfo(void)
1649 BOOL ret;
1650 CERT_PUBLIC_KEY_INFO info1 = { { 0 } }, info2 = { { 0 } };
1651 static CHAR oid_rsa_rsa[] = szOID_RSA_RSA;
1652 static CHAR oid_rsa_sha1rsa[] = szOID_RSA_SHA1RSA;
1653 static CHAR oid_x957_dsa[] = szOID_X957_DSA;
1654 static BYTE bits1[] = { 1, 0 };
1655 static BYTE bits2[] = { 0 };
1656 static BYTE bits3[] = { 1 };
1658 /* crashes
1659 ret = CertComparePublicKeyInfo(0, NULL, NULL);
1661 /* Empty public keys compare */
1662 ret = CertComparePublicKeyInfo(0, &info1, &info2);
1663 ok(ret, "CertComparePublicKeyInfo failed: %08x\n", GetLastError());
1664 /* Different OIDs appear to compare */
1665 info1.Algorithm.pszObjId = oid_rsa_rsa;
1666 info2.Algorithm.pszObjId = oid_rsa_sha1rsa;
1667 ret = CertComparePublicKeyInfo(0, &info1, &info2);
1668 ok(ret, "CertComparePublicKeyInfo failed: %08x\n", GetLastError());
1669 info2.Algorithm.pszObjId = oid_x957_dsa;
1670 ret = CertComparePublicKeyInfo(0, &info1, &info2);
1671 ok(ret, "CertComparePublicKeyInfo failed: %08x\n", GetLastError());
1672 info1.PublicKey.cbData = sizeof(bits1);
1673 info1.PublicKey.pbData = bits1;
1674 info1.PublicKey.cUnusedBits = 0;
1675 info2.PublicKey.cbData = sizeof(bits1);
1676 info2.PublicKey.pbData = bits1;
1677 info2.PublicKey.cUnusedBits = 0;
1678 ret = CertComparePublicKeyInfo(0, &info1, &info2);
1679 ok(ret, "CertComparePublicKeyInfo failed: %08x\n", GetLastError());
1680 /* Even though they compare in their used bits, these do not compare */
1681 info1.PublicKey.cbData = sizeof(bits2);
1682 info1.PublicKey.pbData = bits2;
1683 info1.PublicKey.cUnusedBits = 0;
1684 info2.PublicKey.cbData = sizeof(bits3);
1685 info2.PublicKey.pbData = bits3;
1686 info2.PublicKey.cUnusedBits = 1;
1687 ret = CertComparePublicKeyInfo(0, &info1, &info2);
1688 /* Simple (non-comparing) case */
1689 ok(!ret, "Expected keys not to compare\n");
1690 info2.PublicKey.cbData = sizeof(bits1);
1691 info2.PublicKey.pbData = bits1;
1692 info2.PublicKey.cUnusedBits = 0;
1693 ret = CertComparePublicKeyInfo(0, &info1, &info2);
1694 ok(!ret, "Expected keys not to compare\n");
1697 static void testHashPublicKeyInfo(void)
1699 BOOL ret;
1700 CERT_PUBLIC_KEY_INFO info = { { 0 } };
1701 DWORD len;
1703 /* Crash
1704 ret = CryptHashPublicKeyInfo(0, 0, 0, 0, NULL, NULL, NULL);
1705 ret = CryptHashPublicKeyInfo(0, 0, 0, 0, &info, NULL, NULL);
1707 ret = CryptHashPublicKeyInfo(0, 0, 0, 0, NULL, NULL, &len);
1708 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
1709 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
1710 ret = CryptHashPublicKeyInfo(0, 0, 0, X509_ASN_ENCODING, NULL, NULL, &len);
1711 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
1712 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
1713 ret = CryptHashPublicKeyInfo(0, 0, 0, X509_ASN_ENCODING, &info, NULL, &len);
1714 ok(ret, "CryptHashPublicKeyInfo failed: %08x\n", GetLastError());
1715 ok(len == 16, "Expected hash size 16, got %d\n", len);
1716 if (len == 16)
1718 static const BYTE emptyHash[] = { 0xb8,0x51,0x3a,0x31,0x0e,0x9f,0x40,
1719 0x36,0x9c,0x92,0x45,0x1b,0x9d,0xc8,0xf9,0xf6 };
1720 BYTE buf[16];
1722 ret = CryptHashPublicKeyInfo(0, 0, 0, X509_ASN_ENCODING, &info, buf,
1723 &len);
1724 ok(ret, "CryptHashPublicKeyInfo failed: %08x\n", GetLastError());
1725 ok(!memcmp(buf, emptyHash, len), "Unexpected hash\n");
1729 static void testCompareCert(void)
1731 CERT_INFO info1 = { 0 }, info2 = { 0 };
1732 BOOL ret;
1734 /* Crashes
1735 ret = CertCompareCertificate(X509_ASN_ENCODING, NULL, NULL);
1738 /* Certs with the same issuer and serial number are equal, even if they
1739 * differ in other respects (like subject).
1741 info1.SerialNumber.pbData = serialNum;
1742 info1.SerialNumber.cbData = sizeof(serialNum);
1743 info1.Issuer.pbData = subjectName;
1744 info1.Issuer.cbData = sizeof(subjectName);
1745 info1.Subject.pbData = subjectName2;
1746 info1.Subject.cbData = sizeof(subjectName2);
1747 info2.SerialNumber.pbData = serialNum;
1748 info2.SerialNumber.cbData = sizeof(serialNum);
1749 info2.Issuer.pbData = subjectName;
1750 info2.Issuer.cbData = sizeof(subjectName);
1751 info2.Subject.pbData = subjectName;
1752 info2.Subject.cbData = sizeof(subjectName);
1753 ret = CertCompareCertificate(X509_ASN_ENCODING, &info1, &info2);
1754 ok(ret, "Expected certs to be equal\n");
1756 info2.Issuer.pbData = subjectName2;
1757 info2.Issuer.cbData = sizeof(subjectName2);
1758 ret = CertCompareCertificate(X509_ASN_ENCODING, &info1, &info2);
1759 ok(!ret, "Expected certs not to be equal\n");
1762 static void testVerifySubjectCert(void)
1764 BOOL ret;
1765 DWORD flags;
1766 PCCERT_CONTEXT context1, context2;
1768 /* Crashes
1769 ret = CertVerifySubjectCertificateContext(NULL, NULL, NULL);
1771 flags = 0;
1772 ret = CertVerifySubjectCertificateContext(NULL, NULL, &flags);
1773 ok(ret, "CertVerifySubjectCertificateContext failed; %08x\n",
1774 GetLastError());
1775 flags = CERT_STORE_NO_CRL_FLAG;
1776 ret = CertVerifySubjectCertificateContext(NULL, NULL, &flags);
1777 ok(!ret && GetLastError() == E_INVALIDARG,
1778 "Expected E_INVALIDARG, got %08x\n", GetLastError());
1780 flags = 0;
1781 context1 = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert,
1782 sizeof(bigCert));
1783 ret = CertVerifySubjectCertificateContext(NULL, context1, &flags);
1784 ok(ret, "CertVerifySubjectCertificateContext failed; %08x\n",
1785 GetLastError());
1786 ret = CertVerifySubjectCertificateContext(context1, NULL, &flags);
1787 ok(ret, "CertVerifySubjectCertificateContext failed; %08x\n",
1788 GetLastError());
1789 ret = CertVerifySubjectCertificateContext(context1, context1, &flags);
1790 ok(ret, "CertVerifySubjectCertificateContext failed; %08x\n",
1791 GetLastError());
1793 context2 = CertCreateCertificateContext(X509_ASN_ENCODING,
1794 bigCertWithDifferentSubject, sizeof(bigCertWithDifferentSubject));
1795 SetLastError(0xdeadbeef);
1796 ret = CertVerifySubjectCertificateContext(context1, context2, &flags);
1797 ok(ret, "CertVerifySubjectCertificateContext failed; %08x\n",
1798 GetLastError());
1799 flags = CERT_STORE_REVOCATION_FLAG;
1800 ret = CertVerifySubjectCertificateContext(context1, context2, &flags);
1801 ok(ret, "CertVerifySubjectCertificateContext failed; %08x\n",
1802 GetLastError());
1803 ok(flags == (CERT_STORE_REVOCATION_FLAG | CERT_STORE_NO_CRL_FLAG),
1804 "Expected CERT_STORE_REVOCATION_FLAG | CERT_STORE_NO_CRL_FLAG, got %08x\n",
1805 flags);
1806 flags = CERT_STORE_SIGNATURE_FLAG;
1807 ret = CertVerifySubjectCertificateContext(context1, context2, &flags);
1808 ok(ret, "CertVerifySubjectCertificateContext failed; %08x\n",
1809 GetLastError());
1810 ok(flags == CERT_STORE_SIGNATURE_FLAG,
1811 "Expected CERT_STORE_SIGNATURE_FLAG, got %08x\n", flags);
1812 CertFreeCertificateContext(context2);
1814 CertFreeCertificateContext(context1);
1817 static BYTE privKey[] = {
1818 0x07, 0x02, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x52, 0x53, 0x41, 0x32, 0x00,
1819 0x02, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x79, 0x10, 0x1c, 0xd0, 0x6b, 0x10,
1820 0x18, 0x30, 0x94, 0x61, 0xdc, 0x0e, 0xcb, 0x96, 0x4e, 0x21, 0x3f, 0x79, 0xcd,
1821 0xa9, 0x17, 0x62, 0xbc, 0xbb, 0x61, 0x4c, 0xe0, 0x75, 0x38, 0x6c, 0xf3, 0xde,
1822 0x60, 0x86, 0x03, 0x97, 0x65, 0xeb, 0x1e, 0x6b, 0xdb, 0x53, 0x85, 0xad, 0x68,
1823 0x21, 0xf1, 0x5d, 0xe7, 0x1f, 0xe6, 0x53, 0xb4, 0xbb, 0x59, 0x3e, 0x14, 0x27,
1824 0xb1, 0x83, 0xa7, 0x3a, 0x54, 0xe2, 0x8f, 0x65, 0x8e, 0x6a, 0x4a, 0xcf, 0x3b,
1825 0x1f, 0x65, 0xff, 0xfe, 0xf1, 0x31, 0x3a, 0x37, 0x7a, 0x8b, 0xcb, 0xc6, 0xd4,
1826 0x98, 0x50, 0x36, 0x67, 0xe4, 0xa1, 0xe8, 0x7e, 0x8a, 0xc5, 0x23, 0xf2, 0x77,
1827 0xf5, 0x37, 0x61, 0x49, 0x72, 0x59, 0xe8, 0x3d, 0xf7, 0x60, 0xb2, 0x77, 0xca,
1828 0x78, 0x54, 0x6d, 0x65, 0x9e, 0x03, 0x97, 0x1b, 0x61, 0xbd, 0x0c, 0xd8, 0x06,
1829 0x63, 0xe2, 0xc5, 0x48, 0xef, 0xb3, 0xe2, 0x6e, 0x98, 0x7d, 0xbd, 0x4e, 0x72,
1830 0x91, 0xdb, 0x31, 0x57, 0xe3, 0x65, 0x3a, 0x49, 0xca, 0xec, 0xd2, 0x02, 0x4e,
1831 0x22, 0x7e, 0x72, 0x8e, 0xf9, 0x79, 0x84, 0x82, 0xdf, 0x7b, 0x92, 0x2d, 0xaf,
1832 0xc9, 0xe4, 0x33, 0xef, 0x89, 0x5c, 0x66, 0x99, 0xd8, 0x80, 0x81, 0x47, 0x2b,
1833 0xb1, 0x66, 0x02, 0x84, 0x59, 0x7b, 0xc3, 0xbe, 0x98, 0x45, 0x4a, 0x3d, 0xdd,
1834 0xea, 0x2b, 0xdf, 0x4e, 0xb4, 0x24, 0x6b, 0xec, 0xe7, 0xd9, 0x0c, 0x45, 0xb8,
1835 0xbe, 0xca, 0x69, 0x37, 0x92, 0x4c, 0x38, 0x6b, 0x96, 0x6d, 0xcd, 0x86, 0x67,
1836 0x5c, 0xea, 0x54, 0x94, 0xa4, 0xca, 0xa4, 0x02, 0xa5, 0x21, 0x4d, 0xae, 0x40,
1837 0x8f, 0x9d, 0x51, 0x83, 0xf2, 0x3f, 0x33, 0xc1, 0x72, 0xb4, 0x1d, 0x94, 0x6e,
1838 0x7d, 0xe4, 0x27, 0x3f, 0xea, 0xff, 0xe5, 0x9b, 0xa7, 0x5e, 0x55, 0x8e, 0x0d,
1839 0x69, 0x1c, 0x7a, 0xff, 0x81, 0x9d, 0x53, 0x52, 0x97, 0x9a, 0x76, 0x79, 0xda,
1840 0x93, 0x32, 0x16, 0xec, 0x69, 0x51, 0x1a, 0x4e, 0xc3, 0xf1, 0x72, 0x80, 0x78,
1841 0x5e, 0x66, 0x4a, 0x8d, 0x85, 0x2f, 0x3f, 0xb2, 0xa7 };
1843 static const BYTE selfSignedCert[] = {
1844 0x30, 0x82, 0x01, 0x1f, 0x30, 0x81, 0xce, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02,
1845 0x10, 0xeb, 0x0d, 0x57, 0x2a, 0x9c, 0x09, 0xba, 0xa4, 0x4a, 0xb7, 0x25, 0x49,
1846 0xd9, 0x3e, 0xb5, 0x73, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1d,
1847 0x05, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03,
1848 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30,
1849 0x1e, 0x17, 0x0d, 0x30, 0x36, 0x30, 0x36, 0x32, 0x39, 0x30, 0x35, 0x30, 0x30,
1850 0x34, 0x36, 0x5a, 0x17, 0x0d, 0x30, 0x37, 0x30, 0x36, 0x32, 0x39, 0x31, 0x31,
1851 0x30, 0x30, 0x34, 0x36, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03,
1852 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e,
1853 0x67, 0x00, 0x30, 0x5c, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
1854 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x4b, 0x00, 0x30, 0x48, 0x02, 0x41,
1855 0x00, 0xe2, 0x54, 0x3a, 0xa7, 0x83, 0xb1, 0x27, 0x14, 0x3e, 0x59, 0xbb, 0xb4,
1856 0x53, 0xe6, 0x1f, 0xe7, 0x5d, 0xf1, 0x21, 0x68, 0xad, 0x85, 0x53, 0xdb, 0x6b,
1857 0x1e, 0xeb, 0x65, 0x97, 0x03, 0x86, 0x60, 0xde, 0xf3, 0x6c, 0x38, 0x75, 0xe0,
1858 0x4c, 0x61, 0xbb, 0xbc, 0x62, 0x17, 0xa9, 0xcd, 0x79, 0x3f, 0x21, 0x4e, 0x96,
1859 0xcb, 0x0e, 0xdc, 0x61, 0x94, 0x30, 0x18, 0x10, 0x6b, 0xd0, 0x1c, 0x10, 0x79,
1860 0x02, 0x03, 0x01, 0x00, 0x01, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02,
1861 0x1d, 0x05, 0x00, 0x03, 0x41, 0x00, 0x25, 0x90, 0x53, 0x34, 0xd9, 0x56, 0x41,
1862 0x5e, 0xdb, 0x7e, 0x01, 0x36, 0xec, 0x27, 0x61, 0x5e, 0xb7, 0x4d, 0x90, 0x66,
1863 0xa2, 0xe1, 0x9d, 0x58, 0x76, 0xd4, 0x9c, 0xba, 0x2c, 0x84, 0xc6, 0x83, 0x7a,
1864 0x22, 0x0d, 0x03, 0x69, 0x32, 0x1a, 0x6d, 0xcb, 0x0c, 0x15, 0xb3, 0x6b, 0xc7,
1865 0x0a, 0x8c, 0xb4, 0x5c, 0x34, 0x78, 0xe0, 0x3c, 0x9c, 0xe9, 0xf3, 0x30, 0x9f,
1866 0xa8, 0x76, 0x57, 0x92, 0x36 };
1868 static const BYTE exportedPublicKeyBlob[] = {
1869 0x06,0x02,0x00,0x00,0x00,0xa4,0x00,0x00,0x52,0x53,0x41,0x31,0x00,0x02,0x00,0x00,
1870 0x01,0x00,0x01,0x00,0x79,0x10,0x1c,0xd0,0x6b,0x10,0x18,0x30,0x94,0x61,0xdc,0x0e,
1871 0xcb,0x96,0x4e,0x21,0x3f,0x79,0xcd,0xa9,0x17,0x62,0xbc,0xbb,0x61,0x4c,0xe0,0x75,
1872 0x38,0x6c,0xf3,0xde,0x60,0x86,0x03,0x97,0x65,0xeb,0x1e,0x6b,0xdb,0x53,0x85,0xad,
1873 0x68,0x21,0xf1,0x5d,0xe7,0x1f,0xe6,0x53,0xb4,0xbb,0x59,0x3e,0x14,0x27,0xb1,0x83,
1874 0xa7,0x3a,0x54,0xe2 };
1876 static const BYTE asnEncodedPublicKey[] = {
1877 0x30,0x48,0x02,0x41,0x00,0xe2,0x54,0x3a,0xa7,0x83,0xb1,0x27,0x14,0x3e,0x59,0xbb,
1878 0xb4,0x53,0xe6,0x1f,0xe7,0x5d,0xf1,0x21,0x68,0xad,0x85,0x53,0xdb,0x6b,0x1e,0xeb,
1879 0x65,0x97,0x03,0x86,0x60,0xde,0xf3,0x6c,0x38,0x75,0xe0,0x4c,0x61,0xbb,0xbc,0x62,
1880 0x17,0xa9,0xcd,0x79,0x3f,0x21,0x4e,0x96,0xcb,0x0e,0xdc,0x61,0x94,0x30,0x18,0x10,
1881 0x6b,0xd0,0x1c,0x10,0x79,0x02,0x03,0x01,0x00,0x01 };
1883 static void testAcquireCertPrivateKey(void)
1885 BOOL ret;
1886 PCCERT_CONTEXT cert;
1887 HCRYPTPROV csp;
1888 DWORD size, keySpec;
1889 BOOL callerFree;
1890 CRYPT_KEY_PROV_INFO keyProvInfo;
1891 HCRYPTKEY key;
1892 WCHAR ms_def_prov_w[MAX_PATH];
1894 lstrcpyW(ms_def_prov_w, MS_DEF_PROV_W);
1896 keyProvInfo.pwszContainerName = cspNameW;
1897 keyProvInfo.pwszProvName = ms_def_prov_w;
1898 keyProvInfo.dwProvType = PROV_RSA_FULL;
1899 keyProvInfo.dwFlags = 0;
1900 keyProvInfo.cProvParam = 0;
1901 keyProvInfo.rgProvParam = NULL;
1902 keyProvInfo.dwKeySpec = AT_SIGNATURE;
1904 CryptAcquireContextW(NULL, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
1905 CRYPT_DELETEKEYSET);
1907 cert = CertCreateCertificateContext(X509_ASN_ENCODING, selfSignedCert,
1908 sizeof(selfSignedCert));
1910 /* Crash
1911 ret = CryptAcquireCertificatePrivateKey(NULL, 0, NULL, NULL, NULL, NULL);
1912 ret = CryptAcquireCertificatePrivateKey(NULL, 0, NULL, NULL, NULL,
1913 &callerFree);
1914 ret = CryptAcquireCertificatePrivateKey(NULL, 0, NULL, NULL, &keySpec,
1915 NULL);
1916 ret = CryptAcquireCertificatePrivateKey(NULL, 0, NULL, &csp, NULL, NULL);
1917 ret = CryptAcquireCertificatePrivateKey(NULL, 0, NULL, &csp, &keySpec,
1918 &callerFree);
1919 ret = CryptAcquireCertificatePrivateKey(cert, 0, NULL, NULL, NULL, NULL);
1922 /* Missing private key */
1923 ret = CryptAcquireCertificatePrivateKey(cert, 0, NULL, &csp, NULL, NULL);
1924 ok(!ret && GetLastError() == CRYPT_E_NO_KEY_PROPERTY,
1925 "Expected CRYPT_E_NO_KEY_PROPERTY, got %08x\n", GetLastError());
1926 ret = CryptAcquireCertificatePrivateKey(cert, 0, NULL, &csp, &keySpec,
1927 &callerFree);
1928 ok(!ret && GetLastError() == CRYPT_E_NO_KEY_PROPERTY,
1929 "Expected CRYPT_E_NO_KEY_PROPERTY, got %08x\n", GetLastError());
1930 CertSetCertificateContextProperty(cert, CERT_KEY_PROV_INFO_PROP_ID, 0,
1931 &keyProvInfo);
1932 ret = CryptAcquireCertificatePrivateKey(cert, 0, NULL, &csp, &keySpec,
1933 &callerFree);
1934 ok(!ret && GetLastError() == CRYPT_E_NO_KEY_PROPERTY,
1935 "Expected CRYPT_E_NO_KEY_PROPERTY, got %08x\n", GetLastError());
1937 CryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
1938 CRYPT_NEWKEYSET);
1939 ret = CryptImportKey(csp, privKey, sizeof(privKey), 0, 0, &key);
1940 ok(ret, "CryptImportKey failed: %08x\n", GetLastError());
1941 if (ret)
1943 HCRYPTPROV certCSP;
1944 DWORD size;
1945 CERT_KEY_CONTEXT keyContext;
1947 /* Don't cache provider */
1948 ret = CryptAcquireCertificatePrivateKey(cert, 0, NULL, &certCSP,
1949 &keySpec, &callerFree);
1950 ok(ret, "CryptAcquireCertificatePrivateKey failed: %08x\n",
1951 GetLastError());
1952 ok(callerFree, "Expected callerFree to be TRUE\n");
1953 CryptReleaseContext(certCSP, 0);
1954 ret = CryptAcquireCertificatePrivateKey(cert, 0, NULL, &certCSP,
1955 NULL, NULL);
1956 ok(ret, "CryptAcquireCertificatePrivateKey failed: %08x\n",
1957 GetLastError());
1958 CryptReleaseContext(certCSP, 0);
1960 /* Use the key prov info's caching (there shouldn't be any) */
1961 ret = CryptAcquireCertificatePrivateKey(cert,
1962 CRYPT_ACQUIRE_USE_PROV_INFO_FLAG, NULL, &certCSP, &keySpec,
1963 &callerFree);
1964 ok(ret, "CryptAcquireCertificatePrivateKey failed: %08x\n",
1965 GetLastError());
1966 ok(callerFree, "Expected callerFree to be TRUE\n");
1967 CryptReleaseContext(certCSP, 0);
1969 /* Cache it (and check that it's cached) */
1970 ret = CryptAcquireCertificatePrivateKey(cert,
1971 CRYPT_ACQUIRE_CACHE_FLAG, NULL, &certCSP, &keySpec, &callerFree);
1972 ok(ret, "CryptAcquireCertificatePrivateKey failed: %08x\n",
1973 GetLastError());
1974 ok(!callerFree, "Expected callerFree to be FALSE\n");
1975 size = sizeof(keyContext);
1976 ret = CertGetCertificateContextProperty(cert, CERT_KEY_CONTEXT_PROP_ID,
1977 &keyContext, &size);
1978 ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
1979 GetLastError());
1981 /* Remove the cached provider */
1982 CryptReleaseContext(keyContext.hCryptProv, 0);
1983 CertSetCertificateContextProperty(cert, CERT_KEY_CONTEXT_PROP_ID, 0,
1984 NULL);
1985 /* Allow caching via the key prov info */
1986 keyProvInfo.dwFlags = CERT_SET_KEY_CONTEXT_PROP_ID;
1987 CertSetCertificateContextProperty(cert, CERT_KEY_PROV_INFO_PROP_ID, 0,
1988 &keyProvInfo);
1989 /* Now use the key prov info's caching */
1990 ret = CryptAcquireCertificatePrivateKey(cert,
1991 CRYPT_ACQUIRE_USE_PROV_INFO_FLAG, NULL, &certCSP, &keySpec,
1992 &callerFree);
1993 ok(ret, "CryptAcquireCertificatePrivateKey failed: %08x\n",
1994 GetLastError());
1995 ok(!callerFree, "Expected callerFree to be FALSE\n");
1996 size = sizeof(keyContext);
1997 ret = CertGetCertificateContextProperty(cert, CERT_KEY_CONTEXT_PROP_ID,
1998 &keyContext, &size);
1999 ok(ret, "CertGetCertificateContextProperty failed: %08x\n",
2000 GetLastError());
2002 CryptDestroyKey(key);
2005 /* Some sanity-checking on public key exporting */
2006 ret = CryptImportPublicKeyInfo(csp, X509_ASN_ENCODING,
2007 &cert->pCertInfo->SubjectPublicKeyInfo, &key);
2008 ok(ret, "CryptImportPublicKeyInfo failed: %08x\n", GetLastError());
2009 if (ret)
2011 ret = CryptExportKey(key, 0, PUBLICKEYBLOB, 0, NULL, &size);
2012 ok(ret, "CryptExportKey failed: %08x\n", GetLastError());
2013 if (ret)
2015 LPBYTE buf = HeapAlloc(GetProcessHeap(), 0, size), encodedKey;
2017 ret = CryptExportKey(key, 0, PUBLICKEYBLOB, 0, buf, &size);
2018 ok(ret, "CryptExportKey failed: %08x\n", GetLastError());
2019 ok(size == sizeof(exportedPublicKeyBlob), "Unexpected size %d\n",
2020 size);
2021 ok(!memcmp(buf, exportedPublicKeyBlob, size), "Unexpected value\n");
2022 ret = CryptEncodeObjectEx(X509_ASN_ENCODING, RSA_CSP_PUBLICKEYBLOB,
2023 buf, CRYPT_ENCODE_ALLOC_FLAG, NULL, &encodedKey, &size);
2024 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2025 if (ret)
2027 ok(size == sizeof(asnEncodedPublicKey), "Unexpected size %d\n",
2028 size);
2029 ok(!memcmp(encodedKey, asnEncodedPublicKey, size),
2030 "Unexpected value\n");
2031 LocalFree(encodedKey);
2033 HeapFree(GetProcessHeap(), 0, buf);
2035 CryptDestroyKey(key);
2037 ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING,
2038 NULL, 0, NULL, NULL, &size);
2039 ok(ret, "CryptExportPublicKeyInfoEx failed: %08x\n", GetLastError());
2040 if (ret)
2042 PCERT_PUBLIC_KEY_INFO info = HeapAlloc(GetProcessHeap(), 0, size);
2044 ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING,
2045 NULL, 0, NULL, info, &size);
2046 ok(ret, "CryptExportPublicKeyInfoEx failed: %08x\n", GetLastError());
2047 if (ret)
2049 ok(info->PublicKey.cbData == sizeof(asnEncodedPublicKey),
2050 "Unexpected size %d\n", info->PublicKey.cbData);
2051 ok(!memcmp(info->PublicKey.pbData, asnEncodedPublicKey,
2052 info->PublicKey.cbData), "Unexpected value\n");
2054 HeapFree(GetProcessHeap(), 0, info);
2057 CryptReleaseContext(csp, 0);
2058 CryptAcquireContextW(&csp, cspNameW, MS_DEF_PROV_W, PROV_RSA_FULL,
2059 CRYPT_DELETEKEYSET);
2061 CertFreeCertificateContext(cert);
2064 static void testGetPublicKeyLength(void)
2066 static char oid_rsa_rsa[] = szOID_RSA_RSA;
2067 static char oid_rsa_dh[] = szOID_RSA_DH;
2068 static char bogusOID[] = "1.2.3";
2069 DWORD ret;
2070 CERT_PUBLIC_KEY_INFO info = { { 0 } };
2071 BYTE bogusKey[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
2072 BYTE key[] = { 0x30,0x0f,0x02,0x08,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
2073 0x02,0x03,0x01,0x00,0x01 };
2075 /* Crashes
2076 ret = CertGetPublicKeyLength(0, NULL);
2078 /* With an empty public key info */
2079 SetLastError(0xdeadbeef);
2080 ret = CertGetPublicKeyLength(0, &info);
2081 ok(ret == 0 && GetLastError() == ERROR_FILE_NOT_FOUND,
2082 "Expected length 0 and ERROR_FILE_NOT_FOUND, got length %d, %08x\n",
2083 ret, GetLastError());
2084 SetLastError(0xdeadbeef);
2085 ret = CertGetPublicKeyLength(X509_ASN_ENCODING, &info);
2086 ok(ret == 0 && GetLastError() == CRYPT_E_ASN1_EOD,
2087 "Expected length 0 and CRYPT_E_ASN1_EOD, got length %d, %08x\n",
2088 ret, GetLastError());
2089 /* With a nearly-empty public key info */
2090 info.Algorithm.pszObjId = oid_rsa_rsa;
2091 SetLastError(0xdeadbeef);
2092 ret = CertGetPublicKeyLength(0, &info);
2093 ok(ret == 0 && GetLastError() == ERROR_FILE_NOT_FOUND,
2094 "Expected length 0 and ERROR_FILE_NOT_FOUND, got length %d, %08x\n",
2095 ret, GetLastError());
2096 SetLastError(0xdeadbeef);
2097 ret = CertGetPublicKeyLength(X509_ASN_ENCODING, &info);
2098 ok(ret == 0 && GetLastError() == CRYPT_E_ASN1_EOD,
2099 "Expected length 0 and CRYPT_E_ASN1_EOD, got length %d, %08x\n",
2100 ret, GetLastError());
2101 /* With a bogus key */
2102 info.PublicKey.cbData = sizeof(bogusKey);
2103 info.PublicKey.pbData = bogusKey;
2104 SetLastError(0xdeadbeef);
2105 ret = CertGetPublicKeyLength(0, &info);
2106 ok(ret == 0 && GetLastError() == ERROR_FILE_NOT_FOUND,
2107 "Expected length 0 and ERROR_FILE_NOT_FOUND, got length %d, %08x\n",
2108 ret, GetLastError());
2109 SetLastError(0xdeadbeef);
2110 ret = CertGetPublicKeyLength(X509_ASN_ENCODING, &info);
2111 ok(ret == 0 && GetLastError() == CRYPT_E_ASN1_BADTAG,
2112 "Expected length 0 and CRYPT_E_ASN1_BADTAGTAG, got length %d, %08x\n",
2113 ret, GetLastError());
2114 /* With a believable RSA key but a bogus OID */
2115 info.Algorithm.pszObjId = bogusOID;
2116 info.PublicKey.cbData = sizeof(key);
2117 info.PublicKey.pbData = key;
2118 SetLastError(0xdeadbeef);
2119 ret = CertGetPublicKeyLength(0, &info);
2120 ok(ret == 0 && GetLastError() == ERROR_FILE_NOT_FOUND,
2121 "Expected length 0 and ERROR_FILE_NOT_FOUND, got length %d, %08x\n",
2122 ret, GetLastError());
2123 SetLastError(0xdeadbeef);
2124 ret = CertGetPublicKeyLength(X509_ASN_ENCODING, &info);
2125 ok(ret == 56, "Expected length 56, got %d\n", ret);
2126 /* An RSA key with the DH OID */
2127 info.Algorithm.pszObjId = oid_rsa_dh;
2128 SetLastError(0xdeadbeef);
2129 ret = CertGetPublicKeyLength(X509_ASN_ENCODING, &info);
2130 ok(ret == 0 && GetLastError() == CRYPT_E_ASN1_BADTAG,
2131 "Expected length 0 and CRYPT_E_ASN1_BADTAG, got length %d, %08x\n",
2132 ret, GetLastError());
2133 /* With the RSA OID */
2134 info.Algorithm.pszObjId = oid_rsa_rsa;
2135 SetLastError(0xdeadbeef);
2136 ret = CertGetPublicKeyLength(X509_ASN_ENCODING, &info);
2137 ok(ret == 56, "Expected length 56, got %d\n", ret);
2140 START_TEST(cert)
2142 init_function_pointers();
2144 testAddCert();
2145 testCertProperties();
2146 testDupCert();
2147 testFindCert();
2148 testGetSubjectCert();
2149 testGetIssuerCert();
2151 testCryptHashCert();
2152 testCertSigs();
2153 testSignAndEncodeCert();
2154 testCreateSelfSignCert();
2155 testKeyUsage();
2156 testCompareCertName();
2157 testCompareIntegerBlob();
2158 testComparePublicKeyInfo();
2159 testHashPublicKeyInfo();
2160 testCompareCert();
2161 testVerifySubjectCert();
2162 testAcquireCertPrivateKey();
2163 testGetPublicKeyLength();