urlmon: Don't create stgmed_obj for binding to object.
[wine] / dlls / crypt32 / tests / crl.c
1 /*
2  * crypt32 CRL functions tests
3  *
4  * Copyright 2005-2006 Juan Lang
5  *
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.
10  *
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.
15  *
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
19  */
20
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>
29
30 #include "wine/test.h"
31
32
33 static const BYTE bigCert[] = { 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
34  0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
35  0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22,
36  0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30,
37  0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30,
38  0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30,
39  0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20,
40  0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01,
41  0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01,
42  0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
43 static const BYTE bigCert2[] = { 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
44  0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
45  0x0a, 0x41, 0x6c, 0x65, 0x78, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22,
46  0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30,
47  0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30,
48  0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30,
49  0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x41, 0x6c, 0x65, 0x78, 0x20,
50  0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01,
51  0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01,
52  0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
53 static const BYTE bigCertWithDifferentIssuer[] = { 0x30, 0x7a, 0x02, 0x01,
54  0x01, 0x30, 0x02, 0x06, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03,
55  0x55, 0x04, 0x03, 0x13, 0x0a, 0x41, 0x6c, 0x65, 0x78, 0x20, 0x4c, 0x61, 0x6e,
56  0x67, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30,
57  0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30,
58  0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30,
59  0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a,
60  0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02,
61  0x06, 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03,
62  0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff,
63  0x02, 0x01, 0x01 };
64 static const BYTE CRL[] = { 0x30, 0x2c, 0x30, 0x02, 0x06, 0x00,
65  0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a,
66  0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18, 0x0f, 0x31,
67  0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
68  0x5a };
69 static const BYTE newerCRL[] = { 0x30, 0x2a, 0x30, 0x02, 0x06, 0x00, 0x30,
70  0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a,
71  0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x17, 0x0d, 0x30, 0x36,
72  0x30, 0x35, 0x31, 0x36, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a };
73 static const BYTE signedCRL[] = { 0x30, 0x45, 0x30, 0x2c, 0x30, 0x02, 0x06,
74  0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
75  0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18, 0x0f,
76  0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
77  0x30, 0x5a, 0x30, 0x02, 0x06, 0x00, 0x03, 0x11, 0x00, 0x0f, 0x0e, 0x0d, 0x0c,
78  0x0b, 0x0a, 0x09, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00 };
79
80 static BOOL (WINAPI *pCertFindCertificateInCRL)(PCCERT_CONTEXT,PCCRL_CONTEXT,DWORD,void*,PCRL_ENTRY*);
81 static PCCRL_CONTEXT (WINAPI *pCertFindCRLInStore)(HCERTSTORE,DWORD,DWORD,DWORD,const void*,PCCRL_CONTEXT);
82 static BOOL (WINAPI *pCertIsValidCRLForCertificate)(PCCERT_CONTEXT, PCCRL_CONTEXT, DWORD, void*);
83
84 static void init_function_pointers(void)
85 {
86     HMODULE hdll = GetModuleHandleA("crypt32.dll");
87     pCertFindCertificateInCRL = (void*)GetProcAddress(hdll, "CertFindCertificateInCRL");
88     pCertFindCRLInStore = (void*)GetProcAddress(hdll, "CertFindCRLInStore");
89     pCertIsValidCRLForCertificate = (void*)GetProcAddress(hdll, "CertIsValidCRLForCertificate");
90 }
91
92 static void testCreateCRL(void)
93 {
94     PCCRL_CONTEXT context;
95     DWORD GLE;
96
97     context = CertCreateCRLContext(0, NULL, 0);
98     ok(!context && GetLastError() == E_INVALIDARG,
99      "Expected E_INVALIDARG, got %08x\n", GetLastError());
100     context = CertCreateCRLContext(X509_ASN_ENCODING, NULL, 0);
101     GLE = GetLastError();
102     ok(!context && (GLE == CRYPT_E_ASN1_EOD || GLE == OSS_MORE_INPUT),
103      "Expected CRYPT_E_ASN1_EOD or OSS_MORE_INPUT, got %08x\n", GLE);
104     context = CertCreateCRLContext(X509_ASN_ENCODING, bigCert, sizeof(bigCert));
105     GLE = GetLastError();
106     ok(!context, "Expected failure\n");
107     context = CertCreateCRLContext(X509_ASN_ENCODING, signedCRL,
108      sizeof(signedCRL) - 1);
109     ok(!context, "Expected failure\n");
110     context = CertCreateCRLContext(X509_ASN_ENCODING, signedCRL,
111      sizeof(signedCRL));
112     ok(context != NULL, "CertCreateCRLContext failed: %08x\n", GetLastError());
113     if (context)
114         CertFreeCRLContext(context);
115     context = CertCreateCRLContext(X509_ASN_ENCODING, CRL, sizeof(CRL));
116     ok(context != NULL, "CertCreateCRLContext failed: %08x\n", GetLastError());
117     if (context)
118         CertFreeCRLContext(context);
119 }
120
121 static void testAddCRL(void)
122 {
123     HCERTSTORE store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
124      CERT_STORE_CREATE_NEW_FLAG, NULL);
125     PCCRL_CONTEXT context;
126     BOOL ret;
127     DWORD GLE;
128
129     if (!store) return;
130
131     /* Bad CRL encoding type */
132     ret = CertAddEncodedCRLToStore(0, 0, NULL, 0, 0, NULL);
133     ok(!ret && GetLastError() == E_INVALIDARG,
134      "Expected E_INVALIDARG, got %08x\n", GetLastError());
135     ret = CertAddEncodedCRLToStore(store, 0, NULL, 0, 0, NULL);
136     ok(!ret && GetLastError() == E_INVALIDARG,
137      "Expected E_INVALIDARG, got %08x\n", GetLastError());
138     ret = CertAddEncodedCRLToStore(0, 0, signedCRL, sizeof(signedCRL), 0, NULL);
139     ok(!ret && GetLastError() == E_INVALIDARG,
140      "Expected E_INVALIDARG, got %08x\n", GetLastError());
141     ret = CertAddEncodedCRLToStore(store, 0, signedCRL, sizeof(signedCRL), 0,
142      NULL);
143     ok(!ret && GetLastError() == E_INVALIDARG,
144      "Expected E_INVALIDARG, got %08x\n", GetLastError());
145     ret = CertAddEncodedCRLToStore(0, 0, signedCRL, sizeof(signedCRL),
146      CERT_STORE_ADD_ALWAYS, NULL);
147     ok(!ret && GetLastError() == E_INVALIDARG,
148      "Expected E_INVALIDARG, got %08x\n", GetLastError());
149     ret = CertAddEncodedCRLToStore(store, 0, signedCRL, sizeof(signedCRL),
150      CERT_STORE_ADD_ALWAYS, NULL);
151     ok(!ret && GetLastError() == E_INVALIDARG,
152      "Expected E_INVALIDARG, got %08x\n", GetLastError());
153
154     /* No CRL */
155     ret = CertAddEncodedCRLToStore(0, X509_ASN_ENCODING, NULL, 0, 0, NULL);
156     GLE = GetLastError();
157     ok(!ret && (GLE == CRYPT_E_ASN1_EOD || GLE == OSS_MORE_INPUT),
158      "Expected CRYPT_E_ASN1_EOD or OSS_MORE_INPUT, got %08x\n", GLE);
159     ret = CertAddEncodedCRLToStore(store, X509_ASN_ENCODING, NULL, 0, 0, NULL);
160     GLE = GetLastError();
161     ok(!ret && (GLE == CRYPT_E_ASN1_EOD || GLE == OSS_MORE_INPUT),
162      "Expected CRYPT_E_ASN1_EOD or OSS_MORE_INPUT, got %08x\n", GLE);
163
164     /* Weird--bad add disposition leads to an access violation in Windows. */
165     ret = CertAddEncodedCRLToStore(0, X509_ASN_ENCODING, signedCRL,
166      sizeof(signedCRL), 0, NULL);
167     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
168      "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
169     ret = CertAddEncodedCRLToStore(store, X509_ASN_ENCODING, signedCRL,
170      sizeof(signedCRL), 0, NULL);
171     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
172      "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
173
174     /* Weird--can add a CRL to the NULL store (does this have special meaning?)
175      */
176     context = NULL;
177     ret = CertAddEncodedCRLToStore(0, X509_ASN_ENCODING, signedCRL,
178      sizeof(signedCRL), CERT_STORE_ADD_ALWAYS, &context);
179     ok(ret, "CertAddEncodedCRLToStore failed: %08x\n", GetLastError());
180     if (context)
181         CertFreeCRLContext(context);
182
183     /* Normal cases: a "signed" CRL is okay.. */
184     ret = CertAddEncodedCRLToStore(store, X509_ASN_ENCODING, signedCRL,
185      sizeof(signedCRL), CERT_STORE_ADD_ALWAYS, NULL);
186     /* and an unsigned one is too. */
187     ret = CertAddEncodedCRLToStore(store, X509_ASN_ENCODING, CRL, sizeof(CRL),
188      CERT_STORE_ADD_ALWAYS, NULL);
189     ok(ret, "CertAddEncodedCRLToStore failed: %08x\n", GetLastError());
190
191     ret = CertAddEncodedCRLToStore(store, X509_ASN_ENCODING, newerCRL,
192      sizeof(newerCRL), CERT_STORE_ADD_NEW, NULL);
193     ok(!ret && GetLastError() == CRYPT_E_EXISTS,
194      "Expected CRYPT_E_EXISTS, got %08x\n", GetLastError());
195
196     /* This should replace (one of) the existing CRL(s). */
197     ret = CertAddEncodedCRLToStore(store, X509_ASN_ENCODING, newerCRL,
198      sizeof(newerCRL), CERT_STORE_ADD_NEWER, NULL);
199     ok(ret, "CertAddEncodedCRLToStore failed: %08x\n", GetLastError());
200
201     CertCloseStore(store, 0);
202 }
203
204 static void testFindCRL(void)
205 {
206     HCERTSTORE store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
207      CERT_STORE_CREATE_NEW_FLAG, NULL);
208     PCCRL_CONTEXT context;
209     PCCERT_CONTEXT cert;
210     BOOL ret;
211
212     if (!store) return;
213     if (!pCertFindCRLInStore)
214     {
215         skip("CertFindCRLInStore() is not available\n");
216         return;
217     }
218
219     ret = CertAddEncodedCRLToStore(store, X509_ASN_ENCODING, signedCRL,
220      sizeof(signedCRL), CERT_STORE_ADD_ALWAYS, NULL);
221     ok(ret, "CertAddEncodedCRLToStore failed: %08x\n", GetLastError());
222
223     /* Crashes
224     context = pCertFindCRLInStore(NULL, 0, 0, 0, NULL, NULL);
225      */
226
227     /* Find any context */
228     context = pCertFindCRLInStore(store, 0, 0, CRL_FIND_ANY, NULL, NULL);
229     ok(context != NULL, "Expected a context\n");
230     if (context)
231         CertFreeCRLContext(context);
232     /* Bogus flags are ignored */
233     context = pCertFindCRLInStore(store, 0, 1234, CRL_FIND_ANY, NULL, NULL);
234     ok(context != NULL, "Expected a context\n");
235     if (context)
236         CertFreeCRLContext(context);
237     /* CRL encoding type is ignored too */
238     context = pCertFindCRLInStore(store, 1234, 0, CRL_FIND_ANY, NULL, NULL);
239     ok(context != NULL, "Expected a context\n");
240     if (context)
241         CertFreeCRLContext(context);
242
243     /* This appears to match any cert */
244     context = pCertFindCRLInStore(store, 0, 0, CRL_FIND_ISSUED_BY, NULL, NULL);
245     ok(context != NULL, "Expected a context\n");
246     if (context)
247         CertFreeCRLContext(context);
248
249     /* Try to match an issuer that isn't in the store */
250     cert = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert2,
251      sizeof(bigCert2));
252     ok(cert != NULL, "CertCreateCertificateContext failed: %08x\n",
253      GetLastError());
254     context = pCertFindCRLInStore(store, 0, 0, CRL_FIND_ISSUED_BY, cert, NULL);
255     ok(context == NULL, "Expected no matching context\n");
256     CertFreeCertificateContext(cert);
257
258     /* Match an issuer that is in the store */
259     cert = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert,
260      sizeof(bigCert));
261     ok(cert != NULL, "CertCreateCertificateContext failed: %08x\n",
262      GetLastError());
263     context = pCertFindCRLInStore(store, 0, 0, CRL_FIND_ISSUED_BY, cert, NULL);
264     ok(context != NULL, "Expected a context\n");
265     if (context)
266         CertFreeCRLContext(context);
267     CertFreeCertificateContext(cert);
268
269     CertCloseStore(store, 0);
270 }
271
272 static void testGetCRLFromStore(void)
273 {
274     HCERTSTORE store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
275      CERT_STORE_CREATE_NEW_FLAG, NULL);
276     PCCRL_CONTEXT context;
277     PCCERT_CONTEXT cert;
278     DWORD flags;
279     BOOL ret;
280
281     if (!store) return;
282
283     /* Crash
284     context = CertGetCRLFromStore(NULL, NULL, NULL, NULL);
285     context = CertGetCRLFromStore(store, NULL, NULL, NULL);
286      */
287
288     /* Bogus flags */
289     flags = 0xffffffff;
290     context = CertGetCRLFromStore(store, NULL, NULL, &flags);
291     ok(!context && GetLastError() == E_INVALIDARG,
292      "Expected E_INVALIDARG, got %08x\n", GetLastError());
293
294     /* Test an empty store */
295     flags = 0;
296     context = CertGetCRLFromStore(store, NULL, NULL, &flags);
297     ok(context == NULL && GetLastError() == CRYPT_E_NOT_FOUND,
298      "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
299
300     ret = CertAddEncodedCRLToStore(store, X509_ASN_ENCODING, signedCRL,
301      sizeof(signedCRL), CERT_STORE_ADD_ALWAYS, NULL);
302     ok(ret, "CertAddEncodedCRLToStore failed: %08x\n", GetLastError());
303
304     /* NULL matches any CRL */
305     flags = 0;
306     context = CertGetCRLFromStore(store, NULL, NULL, &flags);
307     ok(context != NULL, "Expected a context\n");
308     CertFreeCRLContext(context);
309
310     /* This cert's issuer isn't in */
311     cert = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert2,
312      sizeof(bigCert2));
313     ok(cert != NULL, "CertCreateCertificateContext failed: %08x\n",
314      GetLastError());
315     context = CertGetCRLFromStore(store, cert, NULL, &flags);
316     ok(context == NULL && GetLastError() == CRYPT_E_NOT_FOUND,
317      "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
318     CertFreeCertificateContext(cert);
319
320     /* But this one is */
321     cert = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert,
322      sizeof(bigCert));
323     ok(cert != NULL, "CertCreateCertificateContext failed: %08x\n",
324      GetLastError());
325     context = CertGetCRLFromStore(store, cert, NULL, &flags);
326     ok(context != NULL, "Expected a context\n");
327     CertFreeCRLContext(context);
328     CertFreeCertificateContext(cert);
329
330     CertCloseStore(store, 0);
331 }
332
333 static void checkCRLHash(const BYTE *data, DWORD dataLen, ALG_ID algID,
334  PCCRL_CONTEXT context, DWORD propID)
335 {
336     BYTE hash[20] = { 0 }, hashProperty[20];
337     BOOL ret;
338     DWORD size;
339
340     memset(hash, 0, sizeof(hash));
341     memset(hashProperty, 0, sizeof(hashProperty));
342     size = sizeof(hash);
343     ret = CryptHashCertificate(0, algID, 0, data, dataLen, hash, &size);
344     ok(ret, "CryptHashCertificate failed: %08x\n", GetLastError());
345     ret = CertGetCRLContextProperty(context, propID, hashProperty, &size);
346     ok(ret, "CertGetCRLContextProperty failed: %08x\n", GetLastError());
347     ok(!memcmp(hash, hashProperty, size), "Unexpected hash for property %d\n",
348      propID);
349 }
350
351 static void testCRLProperties(void)
352 {
353     PCCRL_CONTEXT context = CertCreateCRLContext(X509_ASN_ENCODING,
354      CRL, sizeof(CRL));
355
356     ok(context != NULL, "CertCreateCRLContext failed: %08x\n", GetLastError());
357     if (context)
358     {
359         DWORD propID, numProps, access, size;
360         BOOL ret;
361         BYTE hash[20] = { 0 }, hashProperty[20];
362         CRYPT_DATA_BLOB blob;
363
364         /* This crashes
365         propID = CertEnumCRLContextProperties(NULL, 0);
366          */
367
368         propID = 0;
369         numProps = 0;
370         do {
371             propID = CertEnumCRLContextProperties(context, propID);
372             if (propID)
373                 numProps++;
374         } while (propID != 0);
375         ok(numProps == 0, "Expected 0 properties, got %d\n", numProps);
376
377         /* Tests with a NULL cert context.  Prop ID 0 fails.. */
378         ret = CertSetCRLContextProperty(NULL, 0, 0, NULL);
379         ok(!ret && GetLastError() == E_INVALIDARG,
380          "Expected E_INVALIDARG, got %08x\n", GetLastError());
381         /* while this just crashes.
382         ret = CertSetCRLContextProperty(NULL, CERT_KEY_PROV_HANDLE_PROP_ID, 0,
383          NULL);
384          */
385
386         ret = CertSetCRLContextProperty(context, 0, 0, NULL);
387         ok(!ret && GetLastError() == E_INVALIDARG,
388          "Expected E_INVALIDARG, got %08x\n", GetLastError());
389         /* Can't set the cert property directly, this crashes.
390         ret = CertSetCRLContextProperty(context, CERT_CRL_PROP_ID, 0, CRL);
391          */
392
393         /* These all crash.
394         ret = CertGetCRLContextProperty(context, CERT_ACCESS_STATE_PROP_ID, 0,
395          NULL);
396         ret = CertGetCRLContextProperty(context, CERT_HASH_PROP_ID, NULL, NULL);
397         ret = CertGetCRLContextProperty(context, CERT_HASH_PROP_ID, 
398          hashProperty, NULL);
399          */
400         /* A missing prop */
401         size = 0;
402         ret = CertGetCRLContextProperty(context, CERT_KEY_PROV_INFO_PROP_ID,
403          NULL, &size);
404         ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
405          "Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
406         /* And, an implicit property */
407         ret = CertGetCRLContextProperty(context, CERT_ACCESS_STATE_PROP_ID,
408          NULL, &size);
409         ok(ret, "CertGetCRLContextProperty failed: %08x\n", GetLastError());
410         ret = CertGetCRLContextProperty(context, CERT_ACCESS_STATE_PROP_ID,
411          &access, &size);
412         ok(ret, "CertGetCRLContextProperty failed: %08x\n", GetLastError());
413         ok(!(access & CERT_ACCESS_STATE_WRITE_PERSIST_FLAG),
414          "Didn't expect a persisted crl\n");
415         /* Trying to set this "read only" property crashes.
416         access |= CERT_ACCESS_STATE_WRITE_PERSIST_FLAG;
417         ret = CertSetCRLContextProperty(context, CERT_ACCESS_STATE_PROP_ID, 0,
418          &access);
419          */
420
421         /* Can I set the hash to an invalid hash? */
422         blob.pbData = hash;
423         blob.cbData = sizeof(hash);
424         ret = CertSetCRLContextProperty(context, CERT_HASH_PROP_ID, 0, &blob);
425         ok(ret, "CertSetCRLContextProperty failed: %08x\n",
426          GetLastError());
427         size = sizeof(hashProperty);
428         ret = CertGetCRLContextProperty(context, CERT_HASH_PROP_ID,
429          hashProperty, &size);
430         ok(!memcmp(hashProperty, hash, sizeof(hash)), "Unexpected hash\n");
431         /* Delete the (bogus) hash, and get the real one */
432         ret = CertSetCRLContextProperty(context, CERT_HASH_PROP_ID, 0, NULL);
433         ok(ret, "CertSetCRLContextProperty failed: %08x\n", GetLastError());
434         checkCRLHash(CRL, sizeof(CRL), CALG_SHA1, context, CERT_HASH_PROP_ID);
435
436         /* Now that the hash property is set, we should get one property when
437          * enumerating.
438          */
439         propID = 0;
440         numProps = 0;
441         do {
442             propID = CertEnumCRLContextProperties(context, propID);
443             if (propID)
444                 numProps++;
445         } while (propID != 0);
446         ok(numProps == 1, "Expected 1 properties, got %d\n", numProps);
447
448         /* Check a few other implicit properties */
449         checkCRLHash(CRL, sizeof(CRL), CALG_MD5, context,
450          CERT_MD5_HASH_PROP_ID);
451
452         CertFreeCRLContext(context);
453     }
454 }
455
456 static const BYTE v1CRLWithIssuerAndEntry[] = { 0x30, 0x44, 0x30, 0x02, 0x06,
457  0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
458  0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18, 0x0f,
459  0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
460  0x30, 0x5a, 0x30, 0x16, 0x30, 0x14, 0x02, 0x01, 0x01, 0x18, 0x0f, 0x31, 0x36,
461  0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a };
462 static const BYTE v2CRLWithIssuingDistPoint[] = { 0x30,0x5c,0x02,0x01,0x01,
463  0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,
464  0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,
465  0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,
466  0x16,0x30,0x14,0x02,0x01,0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
467  0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0xa0,0x13,0x30,0x11,0x30,0x0f,0x06,
468  0x03,0x55,0x1d,0x13,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
469 static const BYTE verisignCRL[] = { 0x30, 0x82, 0x01, 0xb1, 0x30, 0x82, 0x01,
470  0x1a, 0x02, 0x01, 0x01, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
471  0x0d, 0x01, 0x01, 0x02, 0x05, 0x00, 0x30, 0x61, 0x31, 0x11, 0x30, 0x0f, 0x06,
472  0x03, 0x55, 0x04, 0x07, 0x13, 0x08, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65,
473  0x74, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0e, 0x56,
474  0x65, 0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e,
475  0x31, 0x33, 0x30, 0x31, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x2a, 0x56, 0x65,
476  0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x20, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x72,
477  0x63, 0x69, 0x61, 0x6c, 0x20, 0x53, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65,
478  0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x65, 0x72, 0x73, 0x20, 0x43,
479  0x41, 0x17, 0x0d, 0x30, 0x31, 0x30, 0x33, 0x32, 0x34, 0x30, 0x30, 0x30, 0x30,
480  0x30, 0x30, 0x5a, 0x17, 0x0d, 0x30, 0x34, 0x30, 0x31, 0x30, 0x37, 0x32, 0x33,
481  0x35, 0x39, 0x35, 0x39, 0x5a, 0x30, 0x69, 0x30, 0x21, 0x02, 0x10, 0x1b, 0x51,
482  0x90, 0xf7, 0x37, 0x24, 0x39, 0x9c, 0x92, 0x54, 0xcd, 0x42, 0x46, 0x37, 0x99,
483  0x6a, 0x17, 0x0d, 0x30, 0x31, 0x30, 0x31, 0x33, 0x30, 0x30, 0x30, 0x30, 0x31,
484  0x32, 0x34, 0x5a, 0x30, 0x21, 0x02, 0x10, 0x75, 0x0e, 0x40, 0xff, 0x97, 0xf0,
485  0x47, 0xed, 0xf5, 0x56, 0xc7, 0x08, 0x4e, 0xb1, 0xab, 0xfd, 0x17, 0x0d, 0x30,
486  0x31, 0x30, 0x31, 0x33, 0x31, 0x30, 0x30, 0x30, 0x30, 0x34, 0x39, 0x5a, 0x30,
487  0x21, 0x02, 0x10, 0x77, 0xe6, 0x5a, 0x43, 0x59, 0x93, 0x5d, 0x5f, 0x7a, 0x75,
488  0x80, 0x1a, 0xcd, 0xad, 0xc2, 0x22, 0x17, 0x0d, 0x30, 0x30, 0x30, 0x38, 0x33,
489  0x31, 0x30, 0x30, 0x30, 0x30, 0x35, 0x36, 0x5a, 0xa0, 0x1a, 0x30, 0x18, 0x30,
490  0x09, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x02, 0x30, 0x00, 0x30, 0x0b, 0x06,
491  0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03, 0x02, 0x05, 0xa0, 0x30, 0x0d, 0x06,
492  0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x02, 0x05, 0x00, 0x03,
493  0x81, 0x81, 0x00, 0x18, 0x2c, 0xe8, 0xfc, 0x16, 0x6d, 0x91, 0x4a, 0x3d, 0x88,
494  0x54, 0x48, 0x5d, 0xb8, 0x11, 0xbf, 0x64, 0xbb, 0xf9, 0xda, 0x59, 0x19, 0xdd,
495  0x0e, 0x65, 0xab, 0xc0, 0x0c, 0xfa, 0x67, 0x7e, 0x21, 0x1e, 0x83, 0x0e, 0xcf,
496  0x9b, 0x89, 0x8a, 0xcf, 0x0c, 0x4b, 0xc1, 0x39, 0x9d, 0xe7, 0x6a, 0xac, 0x46,
497  0x74, 0x6a, 0x91, 0x62, 0x22, 0x0d, 0xc4, 0x08, 0xbd, 0xf5, 0x0a, 0x90, 0x7f,
498  0x06, 0x21, 0x3d, 0x7e, 0xa7, 0xaa, 0x5e, 0xcd, 0x22, 0x15, 0xe6, 0x0c, 0x75,
499  0x8e, 0x6e, 0xad, 0xf1, 0x84, 0xe4, 0x22, 0xb4, 0x30, 0x6f, 0xfb, 0x64, 0x8f,
500  0xd7, 0x80, 0x43, 0xf5, 0x19, 0x18, 0x66, 0x1d, 0x72, 0xa3, 0xe3, 0x94, 0x82,
501  0x28, 0x52, 0xa0, 0x06, 0x4e, 0xb1, 0xc8, 0x92, 0x0c, 0x97, 0xbe, 0x15, 0x07,
502  0xab, 0x7a, 0xc9, 0xea, 0x08, 0x67, 0x43, 0x4d, 0x51, 0x63, 0x3b, 0x9c, 0x9c,
503  0xcd };
504
505 static void testIsValidCRLForCert(void)
506 {
507     BOOL ret;
508     PCCERT_CONTEXT cert1, cert2;
509     PCCRL_CONTEXT crl;
510     HCERTSTORE store;
511
512     if(!pCertIsValidCRLForCertificate) return;
513
514     crl = CertCreateCRLContext(X509_ASN_ENCODING, v1CRLWithIssuerAndEntry,
515      sizeof(v1CRLWithIssuerAndEntry));
516     ok(crl != NULL, "CertCreateCRLContext failed: %08x\n", GetLastError());
517     cert1 = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert,
518      sizeof(bigCert));
519     ok(cert1 != NULL, "CertCreateCertificateContext failed: %08x\n",
520      GetLastError());
521
522     /* Crash
523     ret = CertIsValidCRLForCertificate(NULL, NULL, 0, NULL);
524     ret = CertIsValidCRLForCertificate(cert1, NULL, 0, NULL);
525      */
526
527     /* Curiously, any CRL is valid for the NULL certificate */
528     ret = pCertIsValidCRLForCertificate(NULL, crl, 0, NULL);
529     ok(ret, "CertIsValidCRLForCertificate failed: %08x\n", GetLastError());
530
531     /* Same issuer for both cert and CRL, this CRL is valid for that cert */
532     ret = pCertIsValidCRLForCertificate(cert1, crl, 0, NULL);
533     ok(ret, "CertIsValidCRLForCertificate failed: %08x\n", GetLastError());
534
535     cert2 = CertCreateCertificateContext(X509_ASN_ENCODING,
536      bigCertWithDifferentIssuer, sizeof(bigCertWithDifferentIssuer));
537     ok(cert2 != NULL, "CertCreateCertificateContext failed: %08x\n",
538      GetLastError());
539
540     /* Yet more curious: different issuers for these, yet the CRL is valid for
541      * that cert.  According to MSDN, the relevant bit to check is whether the
542      * CRL has a CRL_ISSUING_DIST_POINT extension.
543      */
544     ret = pCertIsValidCRLForCertificate(cert2, crl, 0, NULL);
545     ok(ret, "CertIsValidCRLForCertificate failed: %08x\n", GetLastError());
546
547     CertFreeCRLContext(crl);
548
549     /* Yet with a CRL_ISSUING_DIST_POINT in the CRL, I still can't get this
550      * to say the CRL is not valid for either cert.
551      */
552     crl = CertCreateCRLContext(X509_ASN_ENCODING, v2CRLWithIssuingDistPoint,
553      sizeof(v2CRLWithIssuingDistPoint));
554     ok(crl != NULL, "CertCreateCRLContext failed: %08x\n", GetLastError());
555
556     ret = pCertIsValidCRLForCertificate(cert1, crl, 0, NULL);
557     ok(ret, "CertIsValidCRLForCertificate failed: %08x\n", GetLastError());
558     ret = pCertIsValidCRLForCertificate(cert2, crl, 0, NULL);
559     ok(ret, "CertIsValidCRLForCertificate failed: %08x\n", GetLastError());
560
561     CertFreeCRLContext(crl);
562
563     /* And again, with a real CRL, the CRL is valid for both certs. */
564     crl = CertCreateCRLContext(X509_ASN_ENCODING, verisignCRL,
565      sizeof(verisignCRL));
566     ok(crl != NULL, "CertCreateCRLContext failed: %08x\n", GetLastError());
567
568     ret = pCertIsValidCRLForCertificate(cert1, crl, 0, NULL);
569     ok(ret, "CertIsValidCRLForCertificate failed: %08x\n", GetLastError());
570     ret = pCertIsValidCRLForCertificate(cert2, crl, 0, NULL);
571     ok(ret, "CertIsValidCRLForCertificate failed: %08x\n", GetLastError());
572
573     CertFreeCRLContext(crl);
574
575     /* One last test: a CRL in a different store than the cert is also valid
576      * for the cert, so CertIsValidCRLForCertificate must always return TRUE?
577      */
578     store = CertOpenStore(CERT_STORE_PROV_MEMORY, X509_ASN_ENCODING, 0,
579      CERT_STORE_CREATE_NEW_FLAG, NULL);
580     ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
581
582     ret = CertAddEncodedCRLToStore(store, X509_ASN_ENCODING, verisignCRL,
583      sizeof(verisignCRL), CERT_STORE_ADD_ALWAYS, &crl);
584     ok(ret, "CertAddEncodedCRLToStore failed: %08x\n", GetLastError());
585
586     ret = pCertIsValidCRLForCertificate(cert1, crl, 0, NULL);
587     ok(ret, "CertIsValidCRLForCertificate failed: %08x\n", GetLastError());
588     ret = pCertIsValidCRLForCertificate(cert2, crl, 0, NULL);
589     ok(ret, "CertIsValidCRLForCertificate failed: %08x\n", GetLastError());
590
591     CertFreeCRLContext(crl);
592
593     CertCloseStore(store, 0);
594
595     CertFreeCertificateContext(cert2);
596     CertFreeCertificateContext(cert1);
597 }
598
599 static const BYTE crlWithDifferentIssuer[] = {
600  0x30,0x47,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,0x11,
601  0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x41,0x6c,0x65,0x78,0x20,0x4c,0x61,0x6e,
602  0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,
603  0x30,0x30,0x30,0x5a,0x30,0x16,0x30,0x14,0x02,0x01,0x01,0x18,0x0f,0x31,0x36,
604  0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a };
605
606 static void testFindCertInCRL(void)
607 {
608     BOOL ret;
609     PCCERT_CONTEXT cert;
610     PCCRL_CONTEXT crl;
611     PCRL_ENTRY entry;
612
613     if (!pCertFindCertificateInCRL)
614     {
615         skip("CertFindCertificateInCRL() is not available\n");
616         return;
617     }
618
619     cert = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert,
620      sizeof(bigCert));
621     ok(cert != NULL, "CertCreateCertificateContext failed: %08x\n",
622      GetLastError());
623
624     /* Crash
625     ret = pCertFindCertificateInCRL(NULL, NULL, 0, NULL, NULL);
626     ret = pCertFindCertificateInCRL(NULL, crl, 0, NULL, NULL);
627     ret = pCertFindCertificateInCRL(cert, NULL, 0, NULL, NULL);
628     ret = pCertFindCertificateInCRL(cert, crl, 0, NULL, NULL);
629     ret = pCertFindCertificateInCRL(NULL, NULL, 0, NULL, &entry);
630     ret = pCertFindCertificateInCRL(NULL, crl, 0, NULL, &entry);
631     ret = pCertFindCertificateInCRL(cert, NULL, 0, NULL, &entry);
632      */
633
634     crl = CertCreateCRLContext(X509_ASN_ENCODING, verisignCRL,
635      sizeof(verisignCRL));
636     ret = pCertFindCertificateInCRL(cert, crl, 0, NULL, &entry);
637     ok(ret, "CertFindCertificateInCRL failed: %08x\n", GetLastError());
638     ok(entry == NULL, "Expected not to find an entry in CRL\n");
639     CertFreeCRLContext(crl);
640
641     crl = CertCreateCRLContext(X509_ASN_ENCODING, v1CRLWithIssuerAndEntry,
642      sizeof(v1CRLWithIssuerAndEntry));
643     ret = pCertFindCertificateInCRL(cert, crl, 0, NULL, &entry);
644     ok(ret, "CertFindCertificateInCRL failed: %08x\n", GetLastError());
645     ok(entry != NULL, "Expected to find an entry in CRL\n");
646     CertFreeCRLContext(crl);
647
648     /* Entry found even though CRL issuer doesn't match cert issuer */
649     crl = CertCreateCRLContext(X509_ASN_ENCODING, crlWithDifferentIssuer,
650      sizeof(crlWithDifferentIssuer));
651     ret = pCertFindCertificateInCRL(cert, crl, 0, NULL, &entry);
652     ok(ret, "CertFindCertificateInCRL failed: %08x\n", GetLastError());
653     ok(entry != NULL, "Expected to find an entry in CRL\n");
654     CertFreeCRLContext(crl);
655
656     CertFreeCertificateContext(cert);
657 }
658
659 static void testVerifyCRLRevocation(void)
660 {
661     BOOL ret;
662     PCCERT_CONTEXT cert;
663     PCCRL_CONTEXT crl;
664
665     ret = CertVerifyCRLRevocation(0, NULL, 0, NULL);
666     ok(ret, "CertVerifyCRLRevocation failed: %08x\n", GetLastError());
667     ret = CertVerifyCRLRevocation(X509_ASN_ENCODING, NULL, 0, NULL);
668     ok(ret, "CertVerifyCRLRevocation failed: %08x\n", GetLastError());
669
670     cert = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert,
671      sizeof(bigCert));
672
673     /* Check against no CRL */
674     ret = CertVerifyCRLRevocation(0, cert->pCertInfo, 0, NULL);
675     ok(ret, "CertVerifyCRLRevocation failed: %08x\n", GetLastError());
676     ret = CertVerifyCRLRevocation(X509_ASN_ENCODING, cert->pCertInfo, 0, NULL);
677     ok(ret, "CertVerifyCRLRevocation failed: %08x\n", GetLastError());
678
679     /* Check against CRL with entry for the cert */
680     crl = CertCreateCRLContext(X509_ASN_ENCODING, v1CRLWithIssuerAndEntry,
681      sizeof(v1CRLWithIssuerAndEntry));
682     ret = CertVerifyCRLRevocation(0, cert->pCertInfo, 1,
683      (PCRL_INFO *)&crl->pCrlInfo);
684     ok(!ret, "CertVerifyCRLRevocation should have been revoked\n");
685     ret = CertVerifyCRLRevocation(X509_ASN_ENCODING, cert->pCertInfo, 1,
686      (PCRL_INFO *)&crl->pCrlInfo);
687     ok(!ret, "CertVerifyCRLRevocation should have been revoked\n");
688     CertFreeCRLContext(crl);
689
690     /* Check against CRL with different issuer and entry for the cert */
691     crl = CertCreateCRLContext(X509_ASN_ENCODING, v1CRLWithIssuerAndEntry,
692      sizeof(v1CRLWithIssuerAndEntry));
693     ok(crl != NULL, "CertCreateCRLContext failed: %08x\n", GetLastError());
694     ret = CertVerifyCRLRevocation(X509_ASN_ENCODING, cert->pCertInfo, 1,
695      (PCRL_INFO *)&crl->pCrlInfo);
696     ok(!ret, "CertVerifyCRLRevocation should have been revoked\n");
697     CertFreeCRLContext(crl);
698
699     /* Check against CRL without entry for the cert */
700     crl = CertCreateCRLContext(X509_ASN_ENCODING, verisignCRL,
701      sizeof(verisignCRL));
702     ret = CertVerifyCRLRevocation(0, cert->pCertInfo, 1,
703      (PCRL_INFO *)&crl->pCrlInfo);
704     ok(ret, "CertVerifyCRLRevocation failed: %08x\n", GetLastError());
705     ret = CertVerifyCRLRevocation(X509_ASN_ENCODING, cert->pCertInfo, 1,
706      (PCRL_INFO *)&crl->pCrlInfo);
707     ok(ret, "CertVerifyCRLRevocation failed: %08x\n", GetLastError());
708     CertFreeCRLContext(crl);
709
710     CertFreeCertificateContext(cert);
711 }
712
713 START_TEST(crl)
714 {
715     init_function_pointers();
716
717     testCreateCRL();
718     testAddCRL();
719     testFindCRL();
720     testGetCRLFromStore();
721
722     testCRLProperties();
723
724     testIsValidCRLForCert();
725     testFindCertInCRL();
726     testVerifyCRLRevocation();
727 }