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