source: trunk/src/crypt32/crl.c@ 21354

Last change on this file since 21354 was 21354, checked in by rlwalsh, 16 years ago

eliminate VACPP warning & info msgs - see Ticket #1

File size: 14.7 KB
Line 
1/*
2 * Copyright 2006 Juan Lang
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17 *
18 */
19
20#include <assert.h>
21#include <stdarg.h>
22#include <string.h>
23#include "windef.h"
24#include "winbase.h"
25#include "winerror.h"
26#include "wincrypt.h"
27#include "wine/debug.h"
28#include "crypt32_private.h"
29
30WINE_DEFAULT_DEBUG_CHANNEL(crypt);
31
32PCCRL_CONTEXT WINAPI CertCreateCRLContext(DWORD dwCertEncodingType,
33 const BYTE* pbCrlEncoded, DWORD cbCrlEncoded)
34{
35 PCRL_CONTEXT crl = NULL;
36 BOOL ret;
37 PCRL_INFO crlInfo = NULL;
38 DWORD size = 0;
39
40 TRACE("(%08x, %p, %d)\n", dwCertEncodingType, pbCrlEncoded,
41 cbCrlEncoded);
42
43 if ((dwCertEncodingType & CERT_ENCODING_TYPE_MASK) != X509_ASN_ENCODING)
44 {
45 SetLastError(E_INVALIDARG);
46 return NULL;
47 }
48 ret = CryptDecodeObjectEx(dwCertEncodingType, X509_CERT_CRL_TO_BE_SIGNED,
49 pbCrlEncoded, cbCrlEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL,
50 (BYTE *)&crlInfo, &size);
51 if (ret)
52 {
53 BYTE *data = NULL;
54
55 crl = Context_CreateDataContext(sizeof(CRL_CONTEXT));
56 if (!crl)
57 goto end;
58 data = CryptMemAlloc(cbCrlEncoded);
59 if (!data)
60 {
61 CryptMemFree(crl);
62 crl = NULL;
63 goto end;
64 }
65 memcpy(data, pbCrlEncoded, cbCrlEncoded);
66 crl->dwCertEncodingType = dwCertEncodingType;
67 crl->pbCrlEncoded = data;
68 crl->cbCrlEncoded = cbCrlEncoded;
69 crl->pCrlInfo = crlInfo;
70 crl->hCertStore = 0;
71 }
72
73end:
74 return (PCCRL_CONTEXT)crl;
75}
76
77BOOL WINAPI CertAddEncodedCRLToStore(HCERTSTORE hCertStore,
78 DWORD dwCertEncodingType, const BYTE *pbCrlEncoded, DWORD cbCrlEncoded,
79 DWORD dwAddDisposition, PCCRL_CONTEXT *ppCrlContext)
80{
81 PCCRL_CONTEXT crl = CertCreateCRLContext(dwCertEncodingType,
82 pbCrlEncoded, cbCrlEncoded);
83 BOOL ret;
84
85 TRACE("(%p, %08x, %p, %d, %08x, %p)\n", hCertStore, dwCertEncodingType,
86 pbCrlEncoded, cbCrlEncoded, dwAddDisposition, ppCrlContext);
87
88 if (crl)
89 {
90 ret = CertAddCRLContextToStore(hCertStore, crl, dwAddDisposition,
91 ppCrlContext);
92 CertFreeCRLContext(crl);
93 }
94 else
95 ret = FALSE;
96 return ret;
97}
98
99typedef BOOL (*CrlCompareFunc)(PCCRL_CONTEXT pCrlContext, DWORD dwType,
100 DWORD dwFlags, const void *pvPara);
101
102static BOOL compare_crl_any(PCCRL_CONTEXT pCrlContext, DWORD dwType,
103 DWORD dwFlags, const void *pvPara)
104{
105 return TRUE;
106}
107
108static BOOL compare_crl_issued_by(PCCRL_CONTEXT pCrlContext, DWORD dwType,
109 DWORD dwFlags, const void *pvPara)
110{
111 BOOL ret;
112
113 if (pvPara)
114 {
115 PCCERT_CONTEXT issuer = (PCCERT_CONTEXT)pvPara;
116
117 ret = CertCompareCertificateName(issuer->dwCertEncodingType,
118 &issuer->pCertInfo->Issuer, &pCrlContext->pCrlInfo->Issuer);
119 }
120 else
121 ret = TRUE;
122 return ret;
123}
124
125static BOOL compare_crl_existing(PCCRL_CONTEXT pCrlContext, DWORD dwType,
126 DWORD dwFlags, const void *pvPara)
127{
128 BOOL ret;
129
130 if (pvPara)
131 {
132 PCCRL_CONTEXT crl = (PCCRL_CONTEXT)pvPara;
133
134 ret = CertCompareCertificateName(pCrlContext->dwCertEncodingType,
135 &pCrlContext->pCrlInfo->Issuer, &crl->pCrlInfo->Issuer);
136 }
137 else
138 ret = TRUE;
139 return ret;
140}
141
142PCCRL_CONTEXT WINAPI CertFindCRLInStore(HCERTSTORE hCertStore,
143 DWORD dwCertEncodingType, DWORD dwFindFlags, DWORD dwFindType,
144 const void *pvFindPara, PCCRL_CONTEXT pPrevCrlContext)
145{
146 PCCRL_CONTEXT ret;
147 CrlCompareFunc compare;
148
149 TRACE("(%p, %d, %d, %d, %p, %p)\n", hCertStore, dwCertEncodingType,
150 dwFindFlags, dwFindType, pvFindPara, pPrevCrlContext);
151
152 switch (dwFindType)
153 {
154 case CRL_FIND_ANY:
155 compare = compare_crl_any;
156 break;
157 case CRL_FIND_ISSUED_BY:
158 compare = compare_crl_issued_by;
159 break;
160 case CRL_FIND_EXISTING:
161 compare = compare_crl_existing;
162 break;
163 default:
164 FIXME("find type %08x unimplemented\n", dwFindType);
165 compare = NULL;
166 }
167
168 if (compare)
169 {
170 BOOL matches = FALSE;
171
172 ret = pPrevCrlContext;
173 do {
174 ret = CertEnumCRLsInStore(hCertStore, ret);
175 if (ret)
176 matches = compare(ret, dwFindType, dwFindFlags, pvFindPara);
177 } while (ret != NULL && !matches);
178 if (!ret)
179 SetLastError(CRYPT_E_NOT_FOUND);
180 }
181 else
182 {
183 SetLastError(CRYPT_E_NOT_FOUND);
184 ret = NULL;
185 }
186 return ret;
187}
188
189PCCRL_CONTEXT WINAPI CertGetCRLFromStore(HCERTSTORE hCertStore,
190 PCCERT_CONTEXT pIssuerContext, PCCRL_CONTEXT pPrevCrlContext, DWORD *pdwFlags)
191{
192 static const DWORD supportedFlags = CERT_STORE_SIGNATURE_FLAG |
193 CERT_STORE_TIME_VALIDITY_FLAG | CERT_STORE_BASE_CRL_FLAG |
194 CERT_STORE_DELTA_CRL_FLAG;
195 PCCRL_CONTEXT ret;
196
197 TRACE("(%p, %p, %p, %08x)\n", hCertStore, pIssuerContext, pPrevCrlContext,
198 *pdwFlags);
199
200 if (*pdwFlags & ~supportedFlags)
201 {
202 SetLastError(E_INVALIDARG);
203 return NULL;
204 }
205 if (pIssuerContext)
206 ret = CertFindCRLInStore(hCertStore, pIssuerContext->dwCertEncodingType,
207 0, CRL_FIND_ISSUED_BY, pIssuerContext, pPrevCrlContext);
208 else
209 ret = CertFindCRLInStore(hCertStore, 0, 0, CRL_FIND_ANY, NULL,
210 pPrevCrlContext);
211 if (ret)
212 {
213 if (*pdwFlags & CERT_STORE_TIME_VALIDITY_FLAG)
214 {
215 if (0 == CertVerifyCRLTimeValidity(NULL, ret->pCrlInfo))
216 *pdwFlags &= ~CERT_STORE_TIME_VALIDITY_FLAG;
217 }
218 if (*pdwFlags & CERT_STORE_SIGNATURE_FLAG)
219 {
220 if (CryptVerifyCertificateSignatureEx(0, ret->dwCertEncodingType,
221 CRYPT_VERIFY_CERT_SIGN_SUBJECT_CRL, (void *)ret,
222 CRYPT_VERIFY_CERT_SIGN_ISSUER_CERT, (void *)pIssuerContext, 0,
223 NULL))
224 *pdwFlags &= ~CERT_STORE_SIGNATURE_FLAG;
225 }
226 }
227 return ret;
228}
229
230PCCRL_CONTEXT WINAPI CertDuplicateCRLContext(PCCRL_CONTEXT pCrlContext)
231{
232 TRACE("(%p)\n", pCrlContext);
233 Context_AddRef((void *)pCrlContext, sizeof(CRL_CONTEXT));
234 return pCrlContext;
235}
236
237static void CrlDataContext_Free(void *context)
238{
239 PCRL_CONTEXT crlContext = (PCRL_CONTEXT)context;
240
241 CryptMemFree(crlContext->pbCrlEncoded);
242 LocalFree((HANDLE)crlContext->pCrlInfo);
243}
244
245BOOL WINAPI CertFreeCRLContext( PCCRL_CONTEXT pCrlContext)
246{
247 TRACE("(%p)\n", pCrlContext);
248
249 if (pCrlContext)
250 Context_Release((void *)pCrlContext, sizeof(CRL_CONTEXT),
251 CrlDataContext_Free);
252 return TRUE;
253}
254
255DWORD WINAPI CertEnumCRLContextProperties(PCCRL_CONTEXT pCRLContext,
256 DWORD dwPropId)
257{
258 PCONTEXT_PROPERTY_LIST properties = Context_GetProperties(
259 (void *)pCRLContext, sizeof(CRL_CONTEXT));
260 DWORD ret;
261
262 TRACE("(%p, %d)\n", pCRLContext, dwPropId);
263
264 if (properties)
265 ret = ContextPropertyList_EnumPropIDs(properties, dwPropId);
266 else
267 ret = 0;
268 return ret;
269}
270
271static BOOL CRLContext_SetProperty(PCCRL_CONTEXT context, DWORD dwPropId,
272 DWORD dwFlags, const void *pvData);
273
274static BOOL CRLContext_GetHashProp(PCCRL_CONTEXT context, DWORD dwPropId,
275 ALG_ID algID, const BYTE *toHash, DWORD toHashLen, void *pvData,
276 DWORD *pcbData)
277{
278 BOOL ret = CryptHashCertificate(0, algID, 0, toHash, toHashLen, pvData,
279 pcbData);
280 if (ret)
281 {
282 CRYPT_DATA_BLOB blob = { *pcbData, pvData };
283
284 ret = CRLContext_SetProperty(context, dwPropId, 0, &blob);
285 }
286 return ret;
287}
288
289static BOOL CRLContext_GetProperty(PCCRL_CONTEXT context, DWORD dwPropId,
290 void *pvData, DWORD *pcbData)
291{
292 PCONTEXT_PROPERTY_LIST properties =
293 Context_GetProperties(context, sizeof(CRL_CONTEXT));
294 BOOL ret;
295 CRYPT_DATA_BLOB blob;
296
297 TRACE("(%p, %d, %p, %p)\n", context, dwPropId, pvData, pcbData);
298
299 if (properties)
300 ret = ContextPropertyList_FindProperty(properties, dwPropId, &blob);
301 else
302 ret = FALSE;
303 if (ret)
304 {
305 if (!pvData)
306 *pcbData = blob.cbData;
307 else if (*pcbData < blob.cbData)
308 {
309 SetLastError(ERROR_MORE_DATA);
310 *pcbData = blob.cbData;
311 ret = FALSE;
312 }
313 else
314 {
315 memcpy(pvData, blob.pbData, blob.cbData);
316 *pcbData = blob.cbData;
317 }
318 }
319 else
320 {
321 /* Implicit properties */
322 switch (dwPropId)
323 {
324 case CERT_SHA1_HASH_PROP_ID:
325 ret = CRLContext_GetHashProp(context, dwPropId, CALG_SHA1,
326 context->pbCrlEncoded, context->cbCrlEncoded, pvData,
327 pcbData);
328 break;
329 case CERT_MD5_HASH_PROP_ID:
330 ret = CRLContext_GetHashProp(context, dwPropId, CALG_MD5,
331 context->pbCrlEncoded, context->cbCrlEncoded, pvData,
332 pcbData);
333 break;
334 default:
335 SetLastError(CRYPT_E_NOT_FOUND);
336 }
337 }
338 TRACE("returning %d\n", ret);
339 return ret;
340}
341
342BOOL WINAPI CertGetCRLContextProperty(PCCRL_CONTEXT pCRLContext,
343 DWORD dwPropId, void *pvData, DWORD *pcbData)
344{
345 BOOL ret;
346
347 TRACE("(%p, %d, %p, %p)\n", pCRLContext, dwPropId, pvData, pcbData);
348
349 switch (dwPropId)
350 {
351 case 0:
352 case CERT_CERT_PROP_ID:
353 case CERT_CRL_PROP_ID:
354 case CERT_CTL_PROP_ID:
355 SetLastError(E_INVALIDARG);
356 ret = FALSE;
357 break;
358 case CERT_ACCESS_STATE_PROP_ID:
359 if (!pvData)
360 {
361 *pcbData = sizeof(DWORD);
362 ret = TRUE;
363 }
364 else if (*pcbData < sizeof(DWORD))
365 {
366 SetLastError(ERROR_MORE_DATA);
367 *pcbData = sizeof(DWORD);
368 ret = FALSE;
369 }
370 else
371 {
372 if (pCRLContext->hCertStore)
373 ret = CertGetStoreProperty(pCRLContext->hCertStore, dwPropId,
374 pvData, pcbData);
375 else
376 *(DWORD *)pvData = 0;
377 ret = TRUE;
378 }
379 break;
380 default:
381 ret = CRLContext_GetProperty(pCRLContext, dwPropId, pvData,
382 pcbData);
383 }
384 return ret;
385}
386
387static BOOL CRLContext_SetProperty(PCCRL_CONTEXT context, DWORD dwPropId,
388 DWORD dwFlags, const void *pvData)
389{
390 PCONTEXT_PROPERTY_LIST properties =
391 Context_GetProperties(context, sizeof(CRL_CONTEXT));
392 BOOL ret;
393
394 TRACE("(%p, %d, %08x, %p)\n", context, dwPropId, dwFlags, pvData);
395
396 if (!properties)
397 ret = FALSE;
398 else if (!pvData)
399 {
400 ContextPropertyList_RemoveProperty(properties, dwPropId);
401 ret = TRUE;
402 }
403 else
404 {
405 switch (dwPropId)
406 {
407 case CERT_AUTO_ENROLL_PROP_ID:
408 case CERT_CTL_USAGE_PROP_ID: /* same as CERT_ENHKEY_USAGE_PROP_ID */
409 case CERT_DESCRIPTION_PROP_ID:
410 case CERT_FRIENDLY_NAME_PROP_ID:
411 case CERT_HASH_PROP_ID:
412 case CERT_KEY_IDENTIFIER_PROP_ID:
413 case CERT_MD5_HASH_PROP_ID:
414 case CERT_NEXT_UPDATE_LOCATION_PROP_ID:
415 case CERT_PUBKEY_ALG_PARA_PROP_ID:
416 case CERT_PVK_FILE_PROP_ID:
417 case CERT_SIGNATURE_HASH_PROP_ID:
418 case CERT_ISSUER_PUBLIC_KEY_MD5_HASH_PROP_ID:
419 case CERT_SUBJECT_NAME_MD5_HASH_PROP_ID:
420 case CERT_SUBJECT_PUBLIC_KEY_MD5_HASH_PROP_ID:
421 case CERT_ENROLLMENT_PROP_ID:
422 case CERT_CROSS_CERT_DIST_POINTS_PROP_ID:
423 case CERT_RENEWAL_PROP_ID:
424 {
425 PCRYPT_DATA_BLOB blob = (PCRYPT_DATA_BLOB)pvData;
426
427 ret = ContextPropertyList_SetProperty(properties, dwPropId,
428 blob->pbData, blob->cbData);
429 break;
430 }
431 case CERT_DATE_STAMP_PROP_ID:
432 ret = ContextPropertyList_SetProperty(properties, dwPropId,
433 (const BYTE *)pvData, sizeof(FILETIME));
434 break;
435 default:
436 FIXME("%d: stub\n", dwPropId);
437 ret = FALSE;
438 }
439 }
440 TRACE("returning %d\n", ret);
441 return ret;
442}
443
444BOOL WINAPI CertSetCRLContextProperty(PCCRL_CONTEXT pCRLContext,
445 DWORD dwPropId, DWORD dwFlags, const void *pvData)
446{
447 BOOL ret;
448
449 TRACE("(%p, %d, %08x, %p)\n", pCRLContext, dwPropId, dwFlags, pvData);
450
451 /* Handle special cases for "read-only"/invalid prop IDs. Windows just
452 * crashes on most of these, I'll be safer.
453 */
454 switch (dwPropId)
455 {
456 case 0:
457 case CERT_ACCESS_STATE_PROP_ID:
458 case CERT_CERT_PROP_ID:
459 case CERT_CRL_PROP_ID:
460 case CERT_CTL_PROP_ID:
461 SetLastError(E_INVALIDARG);
462 return FALSE;
463 }
464 ret = CRLContext_SetProperty(pCRLContext, dwPropId, dwFlags, pvData);
465 TRACE("returning %d\n", ret);
466 return ret;
467}
468
469BOOL WINAPI CertIsValidCRLForCertificate(PCCERT_CONTEXT pCert,
470 PCCRL_CONTEXT pCrl, DWORD dwFlags, void *pvReserved)
471{
472 TRACE("(%p, %p, %08x, %p)\n", pCert, pCrl, dwFlags, pvReserved);
473 return TRUE;
474}
475
476static PCRL_ENTRY CRYPT_FindCertificateInCRL(PCERT_INFO cert, const CRL_INFO *crl)
477{
478 DWORD i;
479 PCRL_ENTRY entry = NULL;
480
481 for (i = 0; !entry && i < crl->cCRLEntry; i++)
482 if (CertCompareIntegerBlob(&crl->rgCRLEntry[i].SerialNumber,
483 &cert->SerialNumber))
484 entry = &crl->rgCRLEntry[i];
485 return entry;
486}
487
488BOOL WINAPI CertFindCertificateInCRL(PCCERT_CONTEXT pCert,
489 PCCRL_CONTEXT pCrlContext, DWORD dwFlags, void *pvReserved,
490 PCRL_ENTRY *ppCrlEntry)
491{
492 TRACE("(%p, %p, %08x, %p, %p)\n", pCert, pCrlContext, dwFlags, pvReserved,
493 ppCrlEntry);
494
495 *ppCrlEntry = CRYPT_FindCertificateInCRL(pCert->pCertInfo,
496 pCrlContext->pCrlInfo);
497 return TRUE;
498}
499
500BOOL WINAPI CertVerifyCRLRevocation(DWORD dwCertEncodingType,
501 PCERT_INFO pCertId, DWORD cCrlInfo, PCRL_INFO rgpCrlInfo[])
502{
503 DWORD i;
504 PCRL_ENTRY entry = NULL;
505
506 TRACE("(%08x, %p, %d, %p)\n", dwCertEncodingType, pCertId, cCrlInfo,
507 rgpCrlInfo);
508
509 for (i = 0; !entry && i < cCrlInfo; i++)
510 entry = CRYPT_FindCertificateInCRL(pCertId, rgpCrlInfo[i]);
511 return entry == NULL;
512}
513
514LONG WINAPI CertVerifyCRLTimeValidity(LPFILETIME pTimeToVerify,
515 PCRL_INFO pCrlInfo)
516{
517 FILETIME fileTime;
518 LONG ret;
519
520 if (!pTimeToVerify)
521 {
522 GetSystemTimeAsFileTime(&fileTime);
523 pTimeToVerify = &fileTime;
524 }
525 if ((ret = CompareFileTime(pTimeToVerify, &pCrlInfo->ThisUpdate)) >= 0)
526 {
527 ret = CompareFileTime(pTimeToVerify, &pCrlInfo->NextUpdate);
528 if (ret < 0)
529 ret = 0;
530 }
531 return ret;
532}
Note: See TracBrowser for help on using the repository browser.