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