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