winegstreamer: Move the "flip" field to struct wg_parser_stream.
[wine/zf.git] / dlls / crypt32 / crl.c
blob31bf35bd04160fa3aa6d0d9affb0e0206342ce86
1 /*
2 * Copyright 2006 Juan Lang
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.
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.
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
20 #include <assert.h>
21 #include <stdarg.h>
22 #define NONAMELESSUNION
23 #include "windef.h"
24 #include "winbase.h"
25 #include "wincrypt.h"
26 #include "wine/debug.h"
27 #include "crypt32_private.h"
29 WINE_DEFAULT_DEBUG_CHANNEL(crypt);
31 static void CRL_free(context_t *context)
33 crl_t *crl = (crl_t*)context;
35 CryptMemFree(crl->ctx.pbCrlEncoded);
36 LocalFree(crl->ctx.pCrlInfo);
39 static const context_vtbl_t crl_vtbl;
41 static context_t *CRL_clone(context_t *context, WINECRYPT_CERTSTORE *store, BOOL use_link)
43 crl_t *crl;
45 if(use_link) {
46 crl = (crl_t*)Context_CreateLinkContext(sizeof(CRL_CONTEXT), context, store);
47 if(!crl)
48 return NULL;
49 }else {
50 const crl_t *cloned = (const crl_t*)context;
51 DWORD size = 0;
52 BOOL res;
54 crl = (crl_t*)Context_CreateDataContext(sizeof(CRL_CONTEXT), &crl_vtbl, store);
55 if(!crl)
56 return NULL;
58 Context_CopyProperties(&crl->ctx, &cloned->ctx);
60 crl->ctx.dwCertEncodingType = cloned->ctx.dwCertEncodingType;
61 crl->ctx.pbCrlEncoded = CryptMemAlloc(cloned->ctx.cbCrlEncoded);
62 memcpy(crl->ctx.pbCrlEncoded, cloned->ctx.pbCrlEncoded, cloned->ctx.cbCrlEncoded);
63 crl->ctx.cbCrlEncoded = cloned->ctx.cbCrlEncoded;
65 /* FIXME: We don't need to decode the object here, we could just clone crl info. */
66 res = CryptDecodeObjectEx(crl->ctx.dwCertEncodingType, X509_CERT_CRL_TO_BE_SIGNED,
67 crl->ctx.pbCrlEncoded, crl->ctx.cbCrlEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL,
68 &crl->ctx.pCrlInfo, &size);
69 if(!res) {
70 CertFreeCRLContext(&crl->ctx);
71 return NULL;
75 crl->ctx.hCertStore = store;
76 return &crl->base;
79 static const context_vtbl_t crl_vtbl = {
80 CRL_free,
81 CRL_clone
84 PCCRL_CONTEXT WINAPI CertCreateCRLContext(DWORD dwCertEncodingType,
85 const BYTE* pbCrlEncoded, DWORD cbCrlEncoded)
87 crl_t *crl = NULL;
88 BOOL ret;
89 PCRL_INFO crlInfo = NULL;
90 BYTE *data = NULL;
91 DWORD size = 0;
93 TRACE("(%08x, %p, %d)\n", dwCertEncodingType, pbCrlEncoded,
94 cbCrlEncoded);
96 if ((dwCertEncodingType & CERT_ENCODING_TYPE_MASK) != X509_ASN_ENCODING)
98 SetLastError(E_INVALIDARG);
99 return NULL;
101 ret = CryptDecodeObjectEx(dwCertEncodingType, X509_CERT_CRL_TO_BE_SIGNED,
102 pbCrlEncoded, cbCrlEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL,
103 &crlInfo, &size);
104 if (!ret)
105 return NULL;
107 crl = (crl_t*)Context_CreateDataContext(sizeof(CRL_CONTEXT), &crl_vtbl, &empty_store);
108 if (!crl)
109 return NULL;
111 data = CryptMemAlloc(cbCrlEncoded);
112 if (!data)
114 Context_Release(&crl->base);
115 return NULL;
118 memcpy(data, pbCrlEncoded, cbCrlEncoded);
119 crl->ctx.dwCertEncodingType = dwCertEncodingType;
120 crl->ctx.pbCrlEncoded = data;
121 crl->ctx.cbCrlEncoded = cbCrlEncoded;
122 crl->ctx.pCrlInfo = crlInfo;
123 crl->ctx.hCertStore = &empty_store;
125 return &crl->ctx;
128 BOOL WINAPI CertAddEncodedCRLToStore(HCERTSTORE hCertStore,
129 DWORD dwCertEncodingType, const BYTE *pbCrlEncoded, DWORD cbCrlEncoded,
130 DWORD dwAddDisposition, PCCRL_CONTEXT *ppCrlContext)
132 PCCRL_CONTEXT crl = CertCreateCRLContext(dwCertEncodingType,
133 pbCrlEncoded, cbCrlEncoded);
134 BOOL ret;
136 TRACE("(%p, %08x, %p, %d, %08x, %p)\n", hCertStore, dwCertEncodingType,
137 pbCrlEncoded, cbCrlEncoded, dwAddDisposition, ppCrlContext);
139 if (crl)
141 ret = CertAddCRLContextToStore(hCertStore, crl, dwAddDisposition,
142 ppCrlContext);
143 CertFreeCRLContext(crl);
145 else
146 ret = FALSE;
147 return ret;
150 typedef BOOL (*CrlCompareFunc)(PCCRL_CONTEXT pCrlContext, DWORD dwType,
151 DWORD dwFlags, const void *pvPara);
153 static BOOL compare_crl_any(PCCRL_CONTEXT pCrlContext, DWORD dwType,
154 DWORD dwFlags, const void *pvPara)
156 return TRUE;
159 static BOOL compare_crl_issued_by(PCCRL_CONTEXT pCrlContext, DWORD dwType,
160 DWORD dwFlags, const void *pvPara)
162 BOOL ret;
164 if (pvPara)
166 PCCERT_CONTEXT issuer = pvPara;
168 ret = CertCompareCertificateName(issuer->dwCertEncodingType,
169 &issuer->pCertInfo->Subject, &pCrlContext->pCrlInfo->Issuer);
170 if (ret && (dwFlags & CRL_FIND_ISSUED_BY_SIGNATURE_FLAG))
171 ret = CryptVerifyCertificateSignatureEx(0,
172 issuer->dwCertEncodingType,
173 CRYPT_VERIFY_CERT_SIGN_SUBJECT_CRL, (void *)pCrlContext,
174 CRYPT_VERIFY_CERT_SIGN_ISSUER_CERT, (void *)issuer, 0, NULL);
175 if (ret && (dwFlags & CRL_FIND_ISSUED_BY_AKI_FLAG))
177 PCERT_EXTENSION ext = CertFindExtension(
178 szOID_AUTHORITY_KEY_IDENTIFIER2, pCrlContext->pCrlInfo->cExtension,
179 pCrlContext->pCrlInfo->rgExtension);
181 if (ext)
183 CERT_AUTHORITY_KEY_ID2_INFO *info;
184 DWORD size;
186 if ((ret = CryptDecodeObjectEx(X509_ASN_ENCODING,
187 X509_AUTHORITY_KEY_ID2, ext->Value.pbData, ext->Value.cbData,
188 CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size)))
190 if (info->AuthorityCertIssuer.cAltEntry &&
191 info->AuthorityCertSerialNumber.cbData)
193 PCERT_ALT_NAME_ENTRY directoryName = NULL;
194 DWORD i;
196 for (i = 0; !directoryName &&
197 i < info->AuthorityCertIssuer.cAltEntry; i++)
198 if (info->AuthorityCertIssuer.rgAltEntry[i].
199 dwAltNameChoice == CERT_ALT_NAME_DIRECTORY_NAME)
200 directoryName =
201 &info->AuthorityCertIssuer.rgAltEntry[i];
202 if (directoryName)
204 ret = CertCompareCertificateName(
205 issuer->dwCertEncodingType,
206 &issuer->pCertInfo->Subject,
207 &directoryName->u.DirectoryName);
208 if (ret)
209 ret = CertCompareIntegerBlob(
210 &issuer->pCertInfo->SerialNumber,
211 &info->AuthorityCertSerialNumber);
213 else
215 FIXME("no supported name type in authority key id2\n");
216 ret = FALSE;
219 else if (info->KeyId.cbData)
221 DWORD size;
223 ret = CertGetCertificateContextProperty(issuer,
224 CERT_KEY_IDENTIFIER_PROP_ID, NULL, &size);
225 if (ret && size == info->KeyId.cbData)
227 LPBYTE buf = CryptMemAlloc(size);
229 if (buf)
231 CertGetCertificateContextProperty(issuer,
232 CERT_KEY_IDENTIFIER_PROP_ID, buf, &size);
233 ret = !memcmp(buf, info->KeyId.pbData, size);
234 CryptMemFree(buf);
236 else
237 ret = FALSE;
239 else
240 ret = FALSE;
242 else
244 FIXME("unsupported value for AKI extension\n");
245 ret = FALSE;
247 LocalFree(info);
250 /* else: a CRL without an AKI matches any cert */
253 else
254 ret = TRUE;
255 return ret;
258 static BOOL compare_crl_existing(PCCRL_CONTEXT pCrlContext, DWORD dwType,
259 DWORD dwFlags, const void *pvPara)
261 BOOL ret;
263 if (pvPara)
265 PCCRL_CONTEXT crl = pvPara;
267 ret = CertCompareCertificateName(pCrlContext->dwCertEncodingType,
268 &pCrlContext->pCrlInfo->Issuer, &crl->pCrlInfo->Issuer);
270 else
271 ret = TRUE;
272 return ret;
275 static BOOL compare_crl_issued_for(PCCRL_CONTEXT pCrlContext, DWORD dwType,
276 DWORD dwFlags, const void *pvPara)
278 const CRL_FIND_ISSUED_FOR_PARA *para = pvPara;
279 BOOL ret;
281 ret = CertCompareCertificateName(para->pIssuerCert->dwCertEncodingType,
282 &para->pIssuerCert->pCertInfo->Issuer, &pCrlContext->pCrlInfo->Issuer);
283 return ret;
286 PCCRL_CONTEXT WINAPI CertFindCRLInStore(HCERTSTORE hCertStore,
287 DWORD dwCertEncodingType, DWORD dwFindFlags, DWORD dwFindType,
288 const void *pvFindPara, PCCRL_CONTEXT pPrevCrlContext)
290 PCCRL_CONTEXT ret;
291 CrlCompareFunc compare;
293 TRACE("(%p, %d, %d, %d, %p, %p)\n", hCertStore, dwCertEncodingType,
294 dwFindFlags, dwFindType, pvFindPara, pPrevCrlContext);
296 switch (dwFindType)
298 case CRL_FIND_ANY:
299 compare = compare_crl_any;
300 break;
301 case CRL_FIND_ISSUED_BY:
302 compare = compare_crl_issued_by;
303 break;
304 case CRL_FIND_EXISTING:
305 compare = compare_crl_existing;
306 break;
307 case CRL_FIND_ISSUED_FOR:
308 compare = compare_crl_issued_for;
309 break;
310 default:
311 FIXME("find type %08x unimplemented\n", dwFindType);
312 compare = NULL;
315 if (compare)
317 BOOL matches = FALSE;
319 ret = pPrevCrlContext;
320 do {
321 ret = CertEnumCRLsInStore(hCertStore, ret);
322 if (ret)
323 matches = compare(ret, dwFindType, dwFindFlags, pvFindPara);
324 } while (ret != NULL && !matches);
325 if (!ret)
326 SetLastError(CRYPT_E_NOT_FOUND);
328 else
330 SetLastError(CRYPT_E_NOT_FOUND);
331 ret = NULL;
333 return ret;
336 PCCRL_CONTEXT WINAPI CertGetCRLFromStore(HCERTSTORE hCertStore,
337 PCCERT_CONTEXT pIssuerContext, PCCRL_CONTEXT pPrevCrlContext, DWORD *pdwFlags)
339 static const DWORD supportedFlags = CERT_STORE_SIGNATURE_FLAG |
340 CERT_STORE_TIME_VALIDITY_FLAG | CERT_STORE_BASE_CRL_FLAG |
341 CERT_STORE_DELTA_CRL_FLAG;
342 PCCRL_CONTEXT ret;
344 TRACE("(%p, %p, %p, %08x)\n", hCertStore, pIssuerContext, pPrevCrlContext,
345 *pdwFlags);
347 if (*pdwFlags & ~supportedFlags)
349 SetLastError(E_INVALIDARG);
350 return NULL;
352 if (pIssuerContext)
353 ret = CertFindCRLInStore(hCertStore, pIssuerContext->dwCertEncodingType,
354 0, CRL_FIND_ISSUED_BY, pIssuerContext, pPrevCrlContext);
355 else
356 ret = CertFindCRLInStore(hCertStore, 0, 0, CRL_FIND_ANY, NULL,
357 pPrevCrlContext);
358 if (ret)
360 if (*pdwFlags & CERT_STORE_TIME_VALIDITY_FLAG)
362 if (0 == CertVerifyCRLTimeValidity(NULL, ret->pCrlInfo))
363 *pdwFlags &= ~CERT_STORE_TIME_VALIDITY_FLAG;
365 if (*pdwFlags & CERT_STORE_SIGNATURE_FLAG)
367 if (CryptVerifyCertificateSignatureEx(0, ret->dwCertEncodingType,
368 CRYPT_VERIFY_CERT_SIGN_SUBJECT_CRL, (void *)ret,
369 CRYPT_VERIFY_CERT_SIGN_ISSUER_CERT, (void *)pIssuerContext, 0,
370 NULL))
371 *pdwFlags &= ~CERT_STORE_SIGNATURE_FLAG;
374 return ret;
377 PCCRL_CONTEXT WINAPI CertDuplicateCRLContext(PCCRL_CONTEXT pCrlContext)
379 TRACE("(%p)\n", pCrlContext);
380 if (pCrlContext)
381 Context_AddRef(&crl_from_ptr(pCrlContext)->base);
382 return pCrlContext;
385 BOOL WINAPI CertFreeCRLContext(PCCRL_CONTEXT pCrlContext)
387 TRACE("(%p)\n", pCrlContext);
389 if (pCrlContext)
390 Context_Release(&crl_from_ptr(pCrlContext)->base);
391 return TRUE;
394 DWORD WINAPI CertEnumCRLContextProperties(PCCRL_CONTEXT pCRLContext,
395 DWORD dwPropId)
397 TRACE("(%p, %d)\n", pCRLContext, dwPropId);
399 return ContextPropertyList_EnumPropIDs(crl_from_ptr(pCRLContext)->base.properties, dwPropId);
402 static BOOL CRLContext_SetProperty(crl_t *crl, DWORD dwPropId,
403 DWORD dwFlags, const void *pvData);
405 static BOOL CRLContext_GetHashProp(crl_t *crl, DWORD dwPropId,
406 ALG_ID algID, const BYTE *toHash, DWORD toHashLen, void *pvData,
407 DWORD *pcbData)
409 BOOL ret = CryptHashCertificate(0, algID, 0, toHash, toHashLen, pvData,
410 pcbData);
411 if (ret && pvData)
413 CRYPT_DATA_BLOB blob = { *pcbData, pvData };
415 ret = CRLContext_SetProperty(crl, dwPropId, 0, &blob);
417 return ret;
420 static BOOL CRLContext_GetProperty(crl_t *crl, DWORD dwPropId,
421 void *pvData, DWORD *pcbData)
423 BOOL ret;
424 CRYPT_DATA_BLOB blob;
426 TRACE("(%p, %d, %p, %p)\n", crl, dwPropId, pvData, pcbData);
428 if (crl->base.properties)
429 ret = ContextPropertyList_FindProperty(crl->base.properties, dwPropId, &blob);
430 else
431 ret = FALSE;
432 if (ret)
434 if (!pvData)
435 *pcbData = blob.cbData;
436 else if (*pcbData < blob.cbData)
438 SetLastError(ERROR_MORE_DATA);
439 *pcbData = blob.cbData;
440 ret = FALSE;
442 else
444 memcpy(pvData, blob.pbData, blob.cbData);
445 *pcbData = blob.cbData;
448 else
450 /* Implicit properties */
451 switch (dwPropId)
453 case CERT_SHA1_HASH_PROP_ID:
454 ret = CRLContext_GetHashProp(crl, dwPropId, CALG_SHA1,
455 crl->ctx.pbCrlEncoded, crl->ctx.cbCrlEncoded, pvData,
456 pcbData);
457 break;
458 case CERT_MD5_HASH_PROP_ID:
459 ret = CRLContext_GetHashProp(crl, dwPropId, CALG_MD5,
460 crl->ctx.pbCrlEncoded, crl->ctx.cbCrlEncoded, pvData,
461 pcbData);
462 break;
463 default:
464 SetLastError(CRYPT_E_NOT_FOUND);
467 TRACE("returning %d\n", ret);
468 return ret;
471 BOOL WINAPI CertGetCRLContextProperty(PCCRL_CONTEXT pCRLContext,
472 DWORD dwPropId, void *pvData, DWORD *pcbData)
474 BOOL ret;
476 TRACE("(%p, %d, %p, %p)\n", pCRLContext, dwPropId, pvData, pcbData);
478 switch (dwPropId)
480 case 0:
481 case CERT_CERT_PROP_ID:
482 case CERT_CRL_PROP_ID:
483 case CERT_CTL_PROP_ID:
484 SetLastError(E_INVALIDARG);
485 ret = FALSE;
486 break;
487 case CERT_ACCESS_STATE_PROP_ID:
488 if (!pvData)
490 *pcbData = sizeof(DWORD);
491 ret = TRUE;
493 else if (*pcbData < sizeof(DWORD))
495 SetLastError(ERROR_MORE_DATA);
496 *pcbData = sizeof(DWORD);
497 ret = FALSE;
499 else
501 ret = CertGetStoreProperty(pCRLContext->hCertStore, dwPropId, pvData, pcbData);
503 break;
504 default:
505 ret = CRLContext_GetProperty(crl_from_ptr(pCRLContext), dwPropId, pvData, pcbData);
507 return ret;
510 static BOOL CRLContext_SetProperty(crl_t *crl, DWORD dwPropId,
511 DWORD dwFlags, const void *pvData)
513 BOOL ret;
515 TRACE("(%p, %d, %08x, %p)\n", crl, dwPropId, dwFlags, pvData);
517 if (!crl->base.properties)
518 ret = FALSE;
519 else if (!pvData)
521 ContextPropertyList_RemoveProperty(crl->base.properties, dwPropId);
522 ret = TRUE;
524 else
526 switch (dwPropId)
528 case CERT_AUTO_ENROLL_PROP_ID:
529 case CERT_CTL_USAGE_PROP_ID: /* same as CERT_ENHKEY_USAGE_PROP_ID */
530 case CERT_DESCRIPTION_PROP_ID:
531 case CERT_FRIENDLY_NAME_PROP_ID:
532 case CERT_HASH_PROP_ID:
533 case CERT_KEY_IDENTIFIER_PROP_ID:
534 case CERT_MD5_HASH_PROP_ID:
535 case CERT_NEXT_UPDATE_LOCATION_PROP_ID:
536 case CERT_PUBKEY_ALG_PARA_PROP_ID:
537 case CERT_PVK_FILE_PROP_ID:
538 case CERT_SIGNATURE_HASH_PROP_ID:
539 case CERT_ISSUER_PUBLIC_KEY_MD5_HASH_PROP_ID:
540 case CERT_SUBJECT_NAME_MD5_HASH_PROP_ID:
541 case CERT_SUBJECT_PUBLIC_KEY_MD5_HASH_PROP_ID:
542 case CERT_ENROLLMENT_PROP_ID:
543 case CERT_CROSS_CERT_DIST_POINTS_PROP_ID:
544 case CERT_RENEWAL_PROP_ID:
546 PCRYPT_DATA_BLOB blob = (PCRYPT_DATA_BLOB)pvData;
548 ret = ContextPropertyList_SetProperty(crl->base.properties, dwPropId,
549 blob->pbData, blob->cbData);
550 break;
552 case CERT_DATE_STAMP_PROP_ID:
553 ret = ContextPropertyList_SetProperty(crl->base.properties, dwPropId,
554 pvData, sizeof(FILETIME));
555 break;
556 default:
557 FIXME("%d: stub\n", dwPropId);
558 ret = FALSE;
561 TRACE("returning %d\n", ret);
562 return ret;
565 BOOL WINAPI CertSetCRLContextProperty(PCCRL_CONTEXT pCRLContext,
566 DWORD dwPropId, DWORD dwFlags, const void *pvData)
568 BOOL ret;
570 TRACE("(%p, %d, %08x, %p)\n", pCRLContext, dwPropId, dwFlags, pvData);
572 /* Handle special cases for "read-only"/invalid prop IDs. Windows just
573 * crashes on most of these, I'll be safer.
575 switch (dwPropId)
577 case 0:
578 case CERT_ACCESS_STATE_PROP_ID:
579 case CERT_CERT_PROP_ID:
580 case CERT_CRL_PROP_ID:
581 case CERT_CTL_PROP_ID:
582 SetLastError(E_INVALIDARG);
583 return FALSE;
585 ret = CRLContext_SetProperty(crl_from_ptr(pCRLContext), dwPropId, dwFlags, pvData);
586 TRACE("returning %d\n", ret);
587 return ret;
590 static BOOL compare_dist_point_name(const CRL_DIST_POINT_NAME *name1,
591 const CRL_DIST_POINT_NAME *name2)
593 BOOL match;
595 if (name1->dwDistPointNameChoice == name2->dwDistPointNameChoice)
597 match = TRUE;
598 if (name1->dwDistPointNameChoice == CRL_DIST_POINT_FULL_NAME)
600 if (name1->u.FullName.cAltEntry == name2->u.FullName.cAltEntry)
602 DWORD i;
604 for (i = 0; match && i < name1->u.FullName.cAltEntry; i++)
606 const CERT_ALT_NAME_ENTRY *entry1 =
607 &name1->u.FullName.rgAltEntry[i];
608 const CERT_ALT_NAME_ENTRY *entry2 =
609 &name2->u.FullName.rgAltEntry[i];
611 if (entry1->dwAltNameChoice == entry2->dwAltNameChoice)
613 switch (entry1->dwAltNameChoice)
615 case CERT_ALT_NAME_URL:
616 match = !wcsicmp(entry1->u.pwszURL,
617 entry2->u.pwszURL);
618 break;
619 case CERT_ALT_NAME_DIRECTORY_NAME:
620 match = (entry1->u.DirectoryName.cbData ==
621 entry2->u.DirectoryName.cbData) &&
622 !memcmp(entry1->u.DirectoryName.pbData,
623 entry2->u.DirectoryName.pbData,
624 entry1->u.DirectoryName.cbData);
625 break;
626 default:
627 FIXME("unimplemented for type %d\n",
628 entry1->dwAltNameChoice);
629 match = FALSE;
632 else
633 match = FALSE;
636 else
637 match = FALSE;
640 else
641 match = FALSE;
642 return match;
645 static BOOL match_dist_point_with_issuing_dist_point(
646 const CRL_DIST_POINT *distPoint, const CRL_ISSUING_DIST_POINT *idp)
648 BOOL match;
650 /* While RFC 5280, section 4.2.1.13 recommends against segmenting
651 * CRL distribution points by reasons, it doesn't preclude doing so.
652 * "This profile RECOMMENDS against segmenting CRLs by reason code."
653 * If the issuing distribution point for this CRL is only valid for
654 * some reasons, only match if the reasons covered also match the
655 * reasons in the CRL distribution point.
657 if (idp->OnlySomeReasonFlags.cbData)
659 if (idp->OnlySomeReasonFlags.cbData == distPoint->ReasonFlags.cbData)
661 DWORD i;
663 match = TRUE;
664 for (i = 0; match && i < distPoint->ReasonFlags.cbData; i++)
665 if (idp->OnlySomeReasonFlags.pbData[i] !=
666 distPoint->ReasonFlags.pbData[i])
667 match = FALSE;
669 else
670 match = FALSE;
672 else
673 match = TRUE;
674 if (match)
675 match = compare_dist_point_name(&idp->DistPointName,
676 &distPoint->DistPointName);
677 return match;
680 BOOL WINAPI CertIsValidCRLForCertificate(PCCERT_CONTEXT pCert,
681 PCCRL_CONTEXT pCrl, DWORD dwFlags, void *pvReserved)
683 PCERT_EXTENSION ext;
684 BOOL ret;
686 TRACE("(%p, %p, %08x, %p)\n", pCert, pCrl, dwFlags, pvReserved);
688 if (!pCert)
689 return TRUE;
691 if ((ext = CertFindExtension(szOID_ISSUING_DIST_POINT,
692 pCrl->pCrlInfo->cExtension, pCrl->pCrlInfo->rgExtension)))
694 CRL_ISSUING_DIST_POINT *idp;
695 DWORD size;
697 if ((ret = CryptDecodeObjectEx(pCrl->dwCertEncodingType,
698 X509_ISSUING_DIST_POINT, ext->Value.pbData, ext->Value.cbData,
699 CRYPT_DECODE_ALLOC_FLAG, NULL, &idp, &size)))
701 if ((ext = CertFindExtension(szOID_CRL_DIST_POINTS,
702 pCert->pCertInfo->cExtension, pCert->pCertInfo->rgExtension)))
704 CRL_DIST_POINTS_INFO *distPoints;
706 if ((ret = CryptDecodeObjectEx(pCert->dwCertEncodingType,
707 X509_CRL_DIST_POINTS, ext->Value.pbData, ext->Value.cbData,
708 CRYPT_DECODE_ALLOC_FLAG, NULL, &distPoints, &size)))
710 DWORD i;
712 ret = FALSE;
713 for (i = 0; !ret && i < distPoints->cDistPoint; i++)
714 ret = match_dist_point_with_issuing_dist_point(
715 &distPoints->rgDistPoint[i], idp);
716 if (!ret)
717 SetLastError(CRYPT_E_NO_MATCH);
718 LocalFree(distPoints);
721 else
723 /* no CRL dist points extension in cert, can't match the CRL
724 * (which has an issuing dist point extension)
726 ret = FALSE;
727 SetLastError(CRYPT_E_NO_MATCH);
729 LocalFree(idp);
732 else
733 ret = TRUE;
734 return ret;
737 static PCRL_ENTRY CRYPT_FindCertificateInCRL(PCERT_INFO cert, const CRL_INFO *crl)
739 DWORD i;
740 PCRL_ENTRY entry = NULL;
742 for (i = 0; !entry && i < crl->cCRLEntry; i++)
743 if (CertCompareIntegerBlob(&crl->rgCRLEntry[i].SerialNumber,
744 &cert->SerialNumber))
745 entry = &crl->rgCRLEntry[i];
746 return entry;
749 BOOL WINAPI CertFindCertificateInCRL(PCCERT_CONTEXT pCert,
750 PCCRL_CONTEXT pCrlContext, DWORD dwFlags, void *pvReserved,
751 PCRL_ENTRY *ppCrlEntry)
753 TRACE("(%p, %p, %08x, %p, %p)\n", pCert, pCrlContext, dwFlags, pvReserved,
754 ppCrlEntry);
756 *ppCrlEntry = CRYPT_FindCertificateInCRL(pCert->pCertInfo,
757 pCrlContext->pCrlInfo);
758 return TRUE;
761 BOOL WINAPI CertVerifyCRLRevocation(DWORD dwCertEncodingType,
762 PCERT_INFO pCertId, DWORD cCrlInfo, PCRL_INFO rgpCrlInfo[])
764 DWORD i;
765 PCRL_ENTRY entry = NULL;
767 TRACE("(%08x, %p, %d, %p)\n", dwCertEncodingType, pCertId, cCrlInfo,
768 rgpCrlInfo);
770 for (i = 0; !entry && i < cCrlInfo; i++)
771 entry = CRYPT_FindCertificateInCRL(pCertId, rgpCrlInfo[i]);
772 return entry == NULL;
775 LONG WINAPI CertVerifyCRLTimeValidity(LPFILETIME pTimeToVerify,
776 PCRL_INFO pCrlInfo)
778 FILETIME fileTime;
779 LONG ret;
781 if (!pTimeToVerify)
783 GetSystemTimeAsFileTime(&fileTime);
784 pTimeToVerify = &fileTime;
786 if ((ret = CompareFileTime(pTimeToVerify, &pCrlInfo->ThisUpdate)) >= 0)
788 ret = CompareFileTime(pTimeToVerify, &pCrlInfo->NextUpdate);
789 if (ret < 0)
790 ret = 0;
792 return ret;