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