ReactOS 0.4.17-dev-444-g71ee754
chain.c
Go to the documentation of this file.
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 <stdarg.h>
21#include <wchar.h>
22
23#include "windef.h"
24#include "winbase.h"
25#include "winnls.h"
26#define CERT_CHAIN_PARA_HAS_EXTRA_FIELDS
27#define CERT_REVOCATION_PARA_HAS_EXTRA_FIELDS
28#include "wincrypt.h"
29#include "wininet.h"
30#include "wine/debug.h"
31#include "crypt32_private.h"
32
35
36#define DEFAULT_CYCLE_MODULUS 7
37
38/* This represents a subset of a certificate chain engine: it doesn't include
39 * the "hOther" store described by MSDN, because I'm not sure how that's used.
40 * It also doesn't include the "hTrust" store, because I don't yet implement
41 * CTLs or complex certificate chains.
42 */
44{
53
55 DWORD cStores, HCERTSTORE *stores)
56{
57 DWORD i;
58
59 for (i = 0; i < cStores; i++)
61}
62
63static inline void CRYPT_CloseStores(DWORD cStores, HCERTSTORE *stores)
64{
65 DWORD i;
66
67 for (i = 0; i < cStores; i++)
68 CertCloseStore(stores[i], 0);
69}
70
71/* Finds cert in store by comparing the cert's hashes. */
74{
75 PCCERT_CONTEXT matching = NULL;
76 BYTE hash[20];
77 DWORD size = sizeof(hash);
78
80 {
81 CRYPT_HASH_BLOB blob = { sizeof(hash), hash };
82
83 matching = CertFindCertificateInStore(store, cert->dwCertEncodingType,
85 }
86 return matching;
87}
88
90{
91 BOOL ret = TRUE;
92
93 if (store)
94 {
95 HCERTSTORE rootStore = CertOpenSystemStoreW(0, L"Root");
97
98 do {
100 if (cert)
101 {
102 if (!(check = CRYPT_FindCertInStore(rootStore, cert)))
103 ret = FALSE;
104 else
106 }
107 } while (ret && cert);
108 if (cert)
110 CertCloseStore(rootStore, 0);
111 }
112 return ret;
113}
114
116{
118 HCERTSTORE worldStores[4];
119
120 if(!root) {
121 if(config->cbSize >= sizeof(CERT_CHAIN_ENGINE_CONFIG) && config->hExclusiveRoot)
122 root = CertDuplicateStore(config->hExclusiveRoot);
123 else if (config->hRestrictedRoot)
124 root = CertDuplicateStore(config->hRestrictedRoot);
125 else
126 root = CertOpenStore(CERT_STORE_PROV_SYSTEM_W, 0, 0, system_store, L"Root");
127 if(!root)
128 return NULL;
129 }
130
131 engine = CryptMemAlloc(sizeof(CertificateChainEngine));
132 if(!engine) {
134 return NULL;
135 }
136
137 engine->ref = 1;
138 engine->hRoot = root;
140 worldStores[0] = CertDuplicateStore(engine->hRoot);
141 worldStores[1] = CertOpenStore(CERT_STORE_PROV_SYSTEM_W, 0, 0, system_store, L"CA");
142 worldStores[2] = CertOpenStore(CERT_STORE_PROV_SYSTEM_W, 0, 0, system_store, L"My");
143 worldStores[3] = CertOpenStore(CERT_STORE_PROV_SYSTEM_W, 0, 0, system_store, L"Trust");
144
145 CRYPT_AddStoresToCollection(engine->hWorld, ARRAY_SIZE(worldStores), worldStores);
146 CRYPT_AddStoresToCollection(engine->hWorld, config->cAdditionalStore, config->rghAdditionalStore);
147 CRYPT_CloseStores(ARRAY_SIZE(worldStores), worldStores);
148
149 engine->dwFlags = config->dwFlags;
150 engine->dwUrlRetrievalTimeout = config->dwUrlRetrievalTimeout;
151 engine->MaximumCachedCertificates = config->MaximumCachedCertificates;
152 if(config->CycleDetectionModulus)
153 engine->CycleDetectionModulus = config->CycleDetectionModulus;
154 else
156
157 return engine;
158}
159
161
163{
164 const CERT_CHAIN_ENGINE_CONFIG config = { sizeof(config) };
165
167 if(!allow_default)
168 return NULL;
169
170 if(!default_cu_engine) {
175 }
176
177 return default_cu_engine;
178 }
179
181 if(!allow_default)
182 return NULL;
183
184 if(!default_lm_engine) {
189 }
190
191 return default_lm_engine;
192 }
193
195}
196
198{
199 if(!engine || InterlockedDecrement(&engine->ref))
200 return;
201
202 CertCloseStore(engine->hWorld, 0);
203 CertCloseStore(engine->hRoot, 0);
204 CryptMemFree(engine);
205}
206
208{
220
222 HCERTCHAINENGINE *phChainEngine)
223{
224 BOOL ret;
225
226 TRACE("(%p, %p)\n", pConfig, phChainEngine);
227
229 && pConfig->cbSize != sizeof(CERT_CHAIN_ENGINE_CONFIG))
230 {
232 return FALSE;
233 }
235 if (!ret)
236 {
237 *phChainEngine = NULL;
238 return FALSE;
239 }
240
242 return *phChainEngine != NULL;
243}
244
246{
247 TRACE("(%p)\n", hChainEngine);
249}
250
252{
255}
256
257typedef struct _CertificateChain
258{
263
265{
266 DWORD size, status = 0;
268 BOOL ret;
269
271 cert->pCertInfo->cExtension, cert->pCertInfo->rgExtension)))
272 {
274
275 ret = CryptDecodeObjectEx(cert->dwCertEncodingType,
276 X509_AUTHORITY_KEY_ID2, ext->Value.pbData, ext->Value.cbData,
278 &info, &size);
279 if (ret)
280 {
281 if (info->AuthorityCertIssuer.cAltEntry &&
282 info->AuthorityCertSerialNumber.cbData)
283 {
284 PCERT_ALT_NAME_ENTRY directoryName = NULL;
285 DWORD i;
286
287 for (i = 0; !directoryName &&
288 i < info->AuthorityCertIssuer.cAltEntry; i++)
289 if (info->AuthorityCertIssuer.rgAltEntry[i].dwAltNameChoice
291 directoryName =
292 &info->AuthorityCertIssuer.rgAltEntry[i];
293 if (directoryName)
294 {
295 if (CertCompareCertificateName(cert->dwCertEncodingType, &directoryName->DirectoryName, &cert->pCertInfo->Issuer)
296 && CertCompareIntegerBlob(&info->AuthorityCertSerialNumber, &cert->pCertInfo->SerialNumber))
298 }
299 else
300 {
301 FIXME("no supported name type in authority key id2\n");
302 ret = FALSE;
303 }
304 }
305 else if (info->KeyId.cbData)
306 {
309 if (ret && size == info->KeyId.cbData)
310 {
312
313 if (buf)
314 {
316 if (!memcmp(buf, info->KeyId.pbData, size))
319 }
320 }
321 }
323 }
324 }
326 cert->pCertInfo->cExtension, cert->pCertInfo->rgExtension)))
327 {
329
330 ret = CryptDecodeObjectEx(cert->dwCertEncodingType,
331 X509_AUTHORITY_KEY_ID, ext->Value.pbData, ext->Value.cbData,
333 &info, &size);
334 if (ret)
335 {
336 if (info->CertIssuer.cbData && info->CertSerialNumber.cbData)
337 {
338 if (CertCompareCertificateName(cert->dwCertEncodingType, &info->CertIssuer, &cert->pCertInfo->Issuer)
339 && CertCompareIntegerBlob(&info->CertSerialNumber, &cert->pCertInfo->SerialNumber))
341 }
342 else if (info->KeyId.cbData)
343 {
346 if (ret && size == info->KeyId.cbData)
347 {
349
350 if (buf)
351 {
354 if (!memcmp(buf, info->KeyId.pbData, size))
357 }
358 }
359 }
361 }
362 }
363 else
364 if (CertCompareCertificateName(cert->dwCertEncodingType, &cert->pCertInfo->Subject, &cert->pCertInfo->Issuer))
366
367 if (status)
369
370 return status;
371}
372
374{
375 CertFreeCertificateContext(element->pCertContext);
377}
378
380{
381 DWORD i, j, cyclicCertIndex = 0;
382
383 /* O(n^2) - I don't think there's a faster way */
384 for (i = 0; !cyclicCertIndex && i < chain->cElement; i++)
385 for (j = i + 1; !cyclicCertIndex && j < chain->cElement; j++)
387 chain->rgpElement[i]->pCertContext->pCertInfo,
388 chain->rgpElement[j]->pCertContext->pCertInfo))
389 cyclicCertIndex = j;
390 if (cyclicCertIndex)
391 {
392 chain->rgpElement[cyclicCertIndex]->TrustStatus.dwErrorStatus
394 /* Release remaining certs */
395 for (i = cyclicCertIndex + 1; i < chain->cElement; i++)
396 CRYPT_FreeChainElement(chain->rgpElement[i]);
397 /* Truncate chain */
398 chain->cElement = cyclicCertIndex + 1;
399 }
400}
401
402/* Checks whether the chain is cyclic by examining the last element's status */
404{
405 if (chain->cElement)
406 return chain->rgpElement[chain->cElement - 1]->TrustStatus.dwErrorStatus
408 else
409 return FALSE;
410}
411
412static inline void CRYPT_CombineTrustStatus(CERT_TRUST_STATUS *chainStatus,
413 const CERT_TRUST_STATUS *elementStatus)
414{
415 /* Any error that applies to an element also applies to a chain.. */
416 chainStatus->dwErrorStatus |= elementStatus->dwErrorStatus;
417 /* but the bottom nibble of an element's info status doesn't apply to the
418 * chain.
419 */
420 chainStatus->dwInfoStatus |= (elementStatus->dwInfoStatus & 0xfffffff0);
421}
422
425{
426 BOOL ret = FALSE;
428
429 if (element)
430 {
431 if (!chain->cElement)
432 chain->rgpElement = CryptMemAlloc(sizeof(PCERT_CHAIN_ELEMENT));
433 else
434 chain->rgpElement = CryptMemRealloc(chain->rgpElement,
435 (chain->cElement + 1) * sizeof(PCERT_CHAIN_ELEMENT));
436 if (chain->rgpElement)
437 {
438 chain->rgpElement[chain->cElement++] = element;
439 memset(element, 0, sizeof(CERT_CHAIN_ELEMENT));
440 element->cbSize = sizeof(CERT_CHAIN_ELEMENT);
442 if (chain->cElement > 1)
443 chain->rgpElement[chain->cElement - 2]->TrustStatus.dwInfoStatus
444 = subjectInfoStatus;
445 /* FIXME: initialize the rest of element */
446 if (!(chain->cElement % engine->CycleDetectionModulus))
447 {
449 /* Reinitialize the element pointer in case the chain is
450 * cyclic, in which case the chain is truncated.
451 */
452 element = chain->rgpElement[chain->cElement - 1];
453 }
454 CRYPT_CombineTrustStatus(&chain->TrustStatus,
455 &element->TrustStatus);
456 ret = TRUE;
457 }
458 else
460 }
461 return ret;
462}
463
465{
466 DWORD i;
467
468 for (i = 0; i < chain->cElement; i++)
469 CRYPT_FreeChainElement(chain->rgpElement[i]);
470 CryptMemFree(chain->rgpElement);
472}
473
475 PCERT_CHAIN_ELEMENT rootElement)
476{
478 rootElement->pCertContext);
479
480 if (!trustedRoot)
481 rootElement->TrustStatus.dwErrorStatus |=
483 else
484 CertFreeCertificateContext(trustedRoot);
485}
486
488 PCERT_CHAIN_ELEMENT rootElement)
489{
490 PCCERT_CONTEXT root = rootElement->pCertContext;
491
492 if (!CryptVerifyCertificateSignatureEx(0, root->dwCertEncodingType,
495 {
496 TRACE_(chain)("Last certificate's signature is invalid\n");
497 rootElement->TrustStatus.dwErrorStatus |=
499 }
500 CRYPT_CheckTrustedStatus(hRoot, rootElement);
501}
502
503/* Decodes a cert's basic constraints extension (either szOID_BASIC_CONSTRAINTS
504 * or szOID_BASIC_CONSTRAINTS2, whichever is present) into a
505 * CERT_BASIC_CONSTRAINTS2_INFO. If it neither extension is present, sets
506 * constraints->fCA to defaultIfNotSpecified.
507 * Returns FALSE if the extension is present but couldn't be decoded.
508 */
510 CERT_BASIC_CONSTRAINTS2_INFO *constraints, BOOL defaultIfNotSpecified)
511{
512 BOOL ret = TRUE;
514 cert->pCertInfo->cExtension, cert->pCertInfo->rgExtension);
515
516 constraints->fPathLenConstraint = FALSE;
517 if (ext)
518 {
520 DWORD size = 0;
521
523 ext->Value.pbData, ext->Value.cbData, CRYPT_DECODE_ALLOC_FLAG,
524 NULL, &info, &size);
525 if (ret)
526 {
527 if (info->SubjectType.cbData == 1)
528 constraints->fCA =
529 info->SubjectType.pbData[0] & CERT_CA_SUBJECT_FLAG;
531 }
532 }
533 else
534 {
536 cert->pCertInfo->cExtension, cert->pCertInfo->rgExtension);
537 if (ext)
538 {
540
542 szOID_BASIC_CONSTRAINTS2, ext->Value.pbData, ext->Value.cbData,
543 0, NULL, constraints, &size);
544 }
545 else
546 constraints->fCA = defaultIfNotSpecified;
547 }
548 return ret;
549}
550
551/* Checks element's basic constraints to see if it can act as a CA, with
552 * remainingCAs CAs left in this chain. In general, a cert must include the
553 * basic constraints extension, with the CA flag asserted, in order to be
554 * allowed to be a CA. A V1 or V2 cert, which has no extensions, is also
555 * allowed to be a CA if it's installed locally (in the engine's world store.)
556 * This matches the expected usage in RFC 5280, section 4.2.1.9: a conforming
557 * CA MUST include the basic constraints extension in all certificates that are
558 * used to validate digital signatures on certificates. It also matches
559 * section 6.1.4(k): "If a certificate is a v1 or v2 certificate, then the
560 * application MUST either verify that the certificate is a CA certificate
561 * through out-of-band means or reject the certificate." Rejecting the
562 * certificate prohibits a large number of commonly used certificates, so
563 * accepting locally installed ones is a compromise.
564 * Root certificates are also allowed to be CAs even without a basic
565 * constraints extension. This is implied by RFC 5280, section 6.1: the
566 * root of a certificate chain's only requirement is that it was used to issue
567 * the next certificate in the chain.
568 * Updates chainConstraints with the element's constraints, if:
569 * 1. chainConstraints doesn't have a path length constraint, or
570 * 2. element's path length constraint is smaller than chainConstraints's
571 * Sets *pathLengthConstraintViolated to TRUE if a path length violation
572 * occurs.
573 * Returns TRUE if the element can be a CA, and the length of the remaining
574 * chain is valid.
575 */
578 DWORD remainingCAs, BOOL isRoot, BOOL *pathLengthConstraintViolated)
579{
580 BOOL validBasicConstraints, implicitCA = FALSE;
582
583 if (isRoot)
584 implicitCA = TRUE;
585 else if (cert->pCertInfo->dwVersion == CERT_V1 ||
586 cert->pCertInfo->dwVersion == CERT_V2)
587 {
588 BYTE hash[20];
589 DWORD size = sizeof(hash);
590
592 hash, &size))
593 {
594 CRYPT_HASH_BLOB blob = { sizeof(hash), hash };
596 engine->hWorld, cert->dwCertEncodingType, 0, CERT_FIND_SHA1_HASH,
597 &blob, NULL);
598
599 if (localCert)
600 {
602 implicitCA = TRUE;
603 }
604 }
605 }
606 if ((validBasicConstraints = CRYPT_DecodeBasicConstraints(cert,
607 &constraints, implicitCA)))
608 {
609 chainConstraints->fCA = constraints.fCA;
610 if (!constraints.fCA)
611 {
612 TRACE_(chain)("chain element %ld can't be a CA\n", remainingCAs + 1);
613 validBasicConstraints = FALSE;
614 }
615 else if (constraints.fPathLenConstraint)
616 {
617 /* If the element has path length constraints, they apply to the
618 * entire remaining chain.
619 */
620 if (!chainConstraints->fPathLenConstraint ||
621 constraints.dwPathLenConstraint <
622 chainConstraints->dwPathLenConstraint)
623 {
624 TRACE_(chain)("setting path length constraint to %ld\n",
625 chainConstraints->dwPathLenConstraint);
626 chainConstraints->fPathLenConstraint = TRUE;
627 chainConstraints->dwPathLenConstraint =
628 constraints.dwPathLenConstraint;
629 }
630 }
631 }
632 if (chainConstraints->fPathLenConstraint &&
633 remainingCAs > chainConstraints->dwPathLenConstraint)
634 {
635 TRACE_(chain)("remaining CAs %ld exceed max path length %ld\n",
636 remainingCAs, chainConstraints->dwPathLenConstraint);
637 validBasicConstraints = FALSE;
638 *pathLengthConstraintViolated = TRUE;
639 }
640 return validBasicConstraints;
641}
642
644{
645 BOOL match;
646
647 /* RFC 5280, section 4.2.1.10:
648 * "For URIs, the constraint applies to the host part of the name...
649 * When the constraint begins with a period, it MAY be expanded with one
650 * or more labels. That is, the constraint ".example.com" is satisfied by
651 * both host.example.com and my.host.example.com. However, the constraint
652 * ".example.com" is not satisfied by "example.com". When the constraint
653 * does not begin with a period, it specifies a host."
654 * and for email addresses,
655 * "To indicate all Internet mail addresses on a particular host, the
656 * constraint is specified as the host name. For example, the constraint
657 * "example.com" is satisfied by any mail address at the host
658 * "example.com". To specify any address within a domain, the constraint
659 * is specified with a leading period (as with URIs)."
660 */
661 if (constraint[0] == '.')
662 {
663 /* Must be strictly greater than, a name can't begin with '.' */
664 if (lstrlenW(name) > lstrlenW(constraint))
665 match = !lstrcmpiW(name + lstrlenW(name) - lstrlenW(constraint),
666 constraint);
667 else
668 {
669 /* name is too short, no match */
670 match = FALSE;
671 }
672 }
673 else
674 match = !lstrcmpiW(name, constraint);
675 return match;
676}
677
679 DWORD *trustErrorStatus)
680{
681 BOOL match = FALSE;
682
683 TRACE("%s, %s\n", debugstr_w(constraint), debugstr_w(name));
684
685 if (!constraint)
686 *trustErrorStatus |= CERT_TRUST_INVALID_NAME_CONSTRAINTS;
687 else if (!name)
688 ; /* no match */
689 else
690 {
691 LPCWSTR colon, authority_end, at, hostname = NULL;
692 /* The maximum length for a hostname is 254 in the DNS, see RFC 1034 */
693 WCHAR hostname_buf[255];
694
695 /* RFC 5280: only the hostname portion of the URL is compared. From
696 * section 4.2.1.10:
697 * "For URIs, the constraint applies to the host part of the name.
698 * The constraint MUST be specified as a fully qualified domain name
699 * and MAY specify a host or a domain."
700 * The format for URIs is in RFC 2396.
701 *
702 * First, remove any scheme that's present. */
703 colon = wcschr(name, ':');
704 if (colon && *(colon + 1) == '/' && *(colon + 2) == '/')
705 name = colon + 3;
706 /* Next, find the end of the authority component. (The authority is
707 * generally just the hostname, but it may contain a username or a port.
708 * Those are removed next.)
709 */
710 authority_end = wcschr(name, '/');
711 if (!authority_end)
712 authority_end = wcschr(name, '?');
713 if (!authority_end)
714 authority_end = name + lstrlenW(name);
715 /* Remove any port number from the authority. The userinfo portion
716 * of an authority may contain a colon, so stop if a userinfo portion
717 * is found (indicated by '@').
718 */
719 for (colon = authority_end; colon >= name && *colon != ':' &&
720 *colon != '@'; colon--)
721 ;
722 if (*colon == ':')
723 authority_end = colon;
724 /* Remove any username from the authority */
725 if ((at = wcschr(name, '@')))
726 name = at;
727 /* Ignore any path or query portion of the URL. */
728 if (*authority_end)
729 {
730 if (authority_end - name < ARRAY_SIZE(hostname_buf))
731 {
732 memcpy(hostname_buf, name,
733 (authority_end - name) * sizeof(WCHAR));
734 hostname_buf[authority_end - name] = 0;
735 hostname = hostname_buf;
736 }
737 /* else: Hostname is too long, not a match */
738 }
739 else
740 hostname = name;
741 if (hostname)
742 match = domain_name_matches(constraint, hostname);
743 }
744 return match;
745}
746
748 DWORD *trustErrorStatus)
749{
750 BOOL match = FALSE;
751 LPCWSTR at;
752
753 TRACE("%s, %s\n", debugstr_w(constraint), debugstr_w(name));
754
755 if (!constraint)
756 *trustErrorStatus |= CERT_TRUST_INVALID_NAME_CONSTRAINTS;
757 else if (!name)
758 ; /* no match */
759 else if (wcschr(constraint, '@'))
760 match = !lstrcmpiW(constraint, name);
761 else
762 {
763 if ((at = wcschr(name, '@')))
764 match = domain_name_matches(constraint, at + 1);
765 else
766 match = !lstrcmpiW(constraint, name);
767 }
768 return match;
769}
770
772 DWORD *trustErrorStatus)
773{
774 BOOL match = FALSE;
775
776 TRACE("%s, %s\n", debugstr_w(constraint), debugstr_w(name));
777
778 if (!constraint)
779 *trustErrorStatus |= CERT_TRUST_INVALID_NAME_CONSTRAINTS;
780 else if (!name)
781 ; /* no match */
782 /* RFC 5280, section 4.2.1.10:
783 * "DNS name restrictions are expressed as host.example.com. Any DNS name
784 * that can be constructed by simply adding zero or more labels to the
785 * left-hand side of the name satisfies the name constraint. For example,
786 * www.host.example.com would satisfy the constraint but host1.example.com
787 * would not."
788 */
789 else if (lstrlenW(name) == lstrlenW(constraint))
790 match = !lstrcmpiW(name, constraint);
791 else if (lstrlenW(name) > lstrlenW(constraint))
792 {
793 match = !lstrcmpiW(name + lstrlenW(name) - lstrlenW(constraint),
794 constraint);
795 if (match)
796 {
797 BOOL dot = FALSE;
798 LPCWSTR ptr;
799
800 /* This only matches if name is a subdomain of constraint, i.e.
801 * there's a '.' between the beginning of the name and the
802 * matching portion of the name.
803 */
804 for (ptr = name + lstrlenW(name) - lstrlenW(constraint);
805 !dot && ptr >= name; ptr--)
806 if (*ptr == '.')
807 dot = TRUE;
808 match = dot;
809 }
810 }
811 /* else: name is too short, no match */
812
813 return match;
814}
815
816static BOOL ip_address_matches(const CRYPT_DATA_BLOB *constraint,
817 const CRYPT_DATA_BLOB *name, DWORD *trustErrorStatus)
818{
819 BOOL match = FALSE;
820
821 TRACE("(%ld, %p), (%ld, %p)\n", constraint->cbData, constraint->pbData,
822 name->cbData, name->pbData);
823
824 /* RFC5280, section 4.2.1.10, iPAddress syntax: either 8 or 32 bytes, for
825 * IPv4 or IPv6 addresses, respectively.
826 */
827 if (constraint->cbData != sizeof(DWORD) * 2 && constraint->cbData != 32)
828 *trustErrorStatus |= CERT_TRUST_INVALID_NAME_CONSTRAINTS;
829 else if (name->cbData == sizeof(DWORD) &&
830 constraint->cbData == sizeof(DWORD) * 2)
831 {
832 DWORD subnet, mask, addr;
833
834 memcpy(&subnet, constraint->pbData, sizeof(subnet));
835 memcpy(&mask, constraint->pbData + sizeof(subnet), sizeof(mask));
836 memcpy(&addr, name->pbData, sizeof(addr));
837 /* These are really in big-endian order, but for equality matching we
838 * don't need to swap to host order
839 */
840 match = (subnet & mask) == (addr & mask);
841 }
842 else if (name->cbData == 16 && constraint->cbData == 32)
843 {
844 const BYTE *subnet, *mask, *addr;
845 DWORD i;
846
847 subnet = constraint->pbData;
848 mask = constraint->pbData + 16;
849 addr = name->pbData;
850 match = TRUE;
851 for (i = 0; match && i < 16; i++)
852 if ((subnet[i] & mask[i]) != (addr[i] & mask[i]))
853 match = FALSE;
854 }
855 /* else: name is wrong size, no match */
856
857 return match;
858}
859
861 const CERT_NAME_BLOB *name)
862{
863 CERT_NAME_INFO *constraintName;
864 DWORD size;
865 BOOL match = FALSE;
866
868 constraint->cbData, CRYPT_DECODE_ALLOC_FLAG, NULL, &constraintName, &size))
869 {
870 DWORD i;
871
872 match = TRUE;
873 for (i = 0; match && i < constraintName->cRDN; i++)
876 (CERT_NAME_BLOB *)name, &constraintName->rgRDN[i]);
877 LocalFree(constraintName);
878 }
879 return match;
880}
881
883 const CERT_ALT_NAME_ENTRY *constraint, DWORD *trustErrorStatus, BOOL *present)
884{
885 BOOL match = FALSE;
886
887 if (name->dwAltNameChoice == constraint->dwAltNameChoice)
888 {
889 if (present)
890 *present = TRUE;
891 switch (constraint->dwAltNameChoice)
892 {
894 match = rfc822_name_matches(constraint->pwszURL,
895 name->pwszURL, trustErrorStatus);
896 break;
898 match = dns_name_matches(constraint->pwszURL,
899 name->pwszURL, trustErrorStatus);
900 break;
902 match = url_matches(constraint->pwszURL,
903 name->pwszURL, trustErrorStatus);
904 break;
906 match = ip_address_matches(&constraint->IPAddress,
907 &name->IPAddress, trustErrorStatus);
908 break;
911 &name->DirectoryName);
912 break;
913 default:
914 ERR("name choice %ld unsupported in this context\n",
915 constraint->dwAltNameChoice);
916 *trustErrorStatus |=
918 }
919 }
920 else if (present)
921 *present = FALSE;
922 return match;
923}
924
926 const CERT_NAME_CONSTRAINTS_INFO *nameConstraints, DWORD *trustErrorStatus)
927{
928 DWORD i;
929 BOOL match = FALSE;
930
931 for (i = 0; !match && i < nameConstraints->cExcludedSubtree; i++)
933 &nameConstraints->rgExcludedSubtree[i].Base, trustErrorStatus, NULL);
934 return match;
935}
936
938 const CERT_NAME_CONSTRAINTS_INFO *nameConstraints, DWORD *trustErrorStatus,
939 BOOL *present)
940{
941 DWORD i;
942 BOOL match = FALSE;
943
944 for (i = 0; !match && i < nameConstraints->cPermittedSubtree; i++)
946 &nameConstraints->rgPermittedSubtree[i].Base, trustErrorStatus,
947 present);
948 return match;
949}
950
952{
954
956 cert->cExtension, cert->rgExtension);
957 if (!ext)
959 cert->cExtension, cert->rgExtension);
960 return ext;
961}
962
964 const CERT_NAME_CONSTRAINTS_INFO *nameConstraints, DWORD *trustErrorStatus)
965{
966 CERT_ALT_NAME_INFO *subjectAltName;
967 DWORD size;
968
970 altNameExt->Value.pbData, altNameExt->Value.cbData,
972 &subjectAltName, &size))
973 {
974 DWORD i;
975
976 for (i = 0; i < subjectAltName->cAltEntry; i++)
977 {
978 BOOL nameFormPresent;
979
980 /* A name constraint only applies if the name form is present.
981 * From RFC 5280, section 4.2.1.10:
982 * "Restrictions apply only when the specified name form is
983 * present. If no name of the type is in the certificate,
984 * the certificate is acceptable."
985 */
987 &subjectAltName->rgAltEntry[i], nameConstraints,
988 trustErrorStatus))
989 {
990 TRACE_(chain)("subject alternate name form %ld excluded\n",
991 subjectAltName->rgAltEntry[i].dwAltNameChoice);
992 *trustErrorStatus |=
994 }
995 nameFormPresent = FALSE;
997 &subjectAltName->rgAltEntry[i], nameConstraints,
998 trustErrorStatus, &nameFormPresent) && nameFormPresent)
999 {
1000 TRACE_(chain)("subject alternate name form %ld not permitted\n",
1001 subjectAltName->rgAltEntry[i].dwAltNameChoice);
1002 *trustErrorStatus |=
1004 }
1005 }
1006 LocalFree(subjectAltName);
1007 }
1008 else
1009 *trustErrorStatus |=
1011}
1012
1014 const CERT_NAME_CONSTRAINTS_INFO *nameConstraints, DWORD *trustErrorStatus)
1015{
1016 DWORD i;
1017 BOOL match = FALSE;
1018
1019 for (i = 0; !match && i < nameConstraints->cExcludedSubtree; i++)
1020 {
1021 const CERT_ALT_NAME_ENTRY *constraint =
1022 &nameConstraints->rgExcludedSubtree[i].Base;
1023
1024 if (constraint->dwAltNameChoice == CERT_ALT_NAME_RFC822_NAME)
1026 (LPCWSTR)attr->Value.pbData, trustErrorStatus);
1027 }
1028 return match;
1029}
1030
1032 const CERT_NAME_CONSTRAINTS_INFO *nameConstraints, DWORD *trustErrorStatus,
1033 BOOL *present)
1034{
1035 DWORD i;
1036 BOOL match = FALSE;
1037
1038 for (i = 0; !match && i < nameConstraints->cPermittedSubtree; i++)
1039 {
1040 const CERT_ALT_NAME_ENTRY *constraint =
1041 &nameConstraints->rgPermittedSubtree[i].Base;
1042
1043 if (constraint->dwAltNameChoice == CERT_ALT_NAME_RFC822_NAME)
1044 {
1045 *present = TRUE;
1047 (LPCWSTR)attr->Value.pbData, trustErrorStatus);
1048 }
1049 }
1050 return match;
1051}
1052
1055 const CERT_NAME_CONSTRAINTS_INFO *nameConstraints, DWORD *trustErrorStatus)
1056{
1058 DWORD size;
1059
1061 subjectName->pbData, subjectName->cbData,
1063 {
1064 DWORD i, j;
1065
1066 for (i = 0; i < name->cRDN; i++)
1067 for (j = 0; j < name->rgRDN[i].cRDNAttr; j++)
1068 if (!strcmp(name->rgRDN[i].rgRDNAttr[j].pszObjId,
1070 {
1071 BOOL nameFormPresent;
1072
1073 /* A name constraint only applies if the name form is
1074 * present. From RFC 5280, section 4.2.1.10:
1075 * "Restrictions apply only when the specified name form is
1076 * present. If no name of the type is in the certificate,
1077 * the certificate is acceptable."
1078 */
1080 &name->rgRDN[i].rgRDNAttr[j], nameConstraints,
1081 trustErrorStatus))
1082 {
1083 TRACE_(chain)(
1084 "email address in subject name is excluded\n");
1085 *trustErrorStatus |=
1087 }
1088 nameFormPresent = FALSE;
1090 &name->rgRDN[i].rgRDNAttr[j], nameConstraints,
1091 trustErrorStatus, &nameFormPresent) && nameFormPresent)
1092 {
1093 TRACE_(chain)(
1094 "email address in subject name is not permitted\n");
1095 *trustErrorStatus |=
1097 }
1098 }
1099 LocalFree(name);
1100 }
1101 else
1102 *trustErrorStatus |=
1104}
1105
1107{
1108 BOOL empty;
1109
1110 if (!name->cbData)
1111 empty = TRUE;
1112 else if (name->cbData == 2 && name->pbData[1] == 0)
1113 {
1114 /* An empty sequence is also empty */
1115 empty = TRUE;
1116 }
1117 else
1118 empty = FALSE;
1119 return empty;
1120}
1121
1123 const CERT_NAME_CONSTRAINTS_INFO *nameConstraints, DWORD *trustErrorStatus)
1124{
1125 BOOL hasEmailConstraint = FALSE;
1126 DWORD i;
1127
1128 /* In general, a subject distinguished name only matches a directory name
1129 * constraint. However, an exception exists for email addresses.
1130 * From RFC 5280, section 4.2.1.6:
1131 * "Legacy implementations exist where an electronic mail address is
1132 * embedded in the subject distinguished name as an emailAddress
1133 * attribute [RFC2985]."
1134 * If an email address constraint exists, check that constraint separately.
1135 */
1136 for (i = 0; !hasEmailConstraint && i < nameConstraints->cExcludedSubtree;
1137 i++)
1138 if (nameConstraints->rgExcludedSubtree[i].Base.dwAltNameChoice ==
1140 hasEmailConstraint = TRUE;
1141 for (i = 0; !hasEmailConstraint && i < nameConstraints->cPermittedSubtree;
1142 i++)
1143 if (nameConstraints->rgPermittedSubtree[i].Base.dwAltNameChoice ==
1145 hasEmailConstraint = TRUE;
1146 if (hasEmailConstraint)
1148 trustErrorStatus);
1149 for (i = 0; i < nameConstraints->cExcludedSubtree; i++)
1150 {
1151 CERT_ALT_NAME_ENTRY *constraint =
1152 &nameConstraints->rgExcludedSubtree[i].Base;
1153
1154 if (constraint->dwAltNameChoice == CERT_ALT_NAME_DIRECTORY_NAME &&
1156 {
1157 TRACE_(chain)("subject name is excluded\n");
1158 *trustErrorStatus |=
1160 }
1161 }
1162 /* RFC 5280, section 4.2.1.10:
1163 * "Restrictions apply only when the specified name form is present.
1164 * If no name of the type is in the certificate, the certificate is
1165 * acceptable."
1166 * An empty name can't have the name form present, so don't check it.
1167 */
1168 if (nameConstraints->cPermittedSubtree && !CRYPT_IsEmptyName(subjectName))
1169 {
1170 BOOL match = FALSE, hasDirectoryConstraint = FALSE;
1171
1172 for (i = 0; !match && i < nameConstraints->cPermittedSubtree; i++)
1173 {
1174 CERT_ALT_NAME_ENTRY *constraint =
1175 &nameConstraints->rgPermittedSubtree[i].Base;
1176
1178 {
1179 hasDirectoryConstraint = TRUE;
1181 subjectName);
1182 }
1183 }
1184 if (hasDirectoryConstraint && !match)
1185 {
1186 TRACE_(chain)("subject name is not permitted\n");
1188 }
1189 }
1190}
1191
1193 const CERT_NAME_CONSTRAINTS_INFO *nameConstraints, const CERT_INFO *cert,
1194 DWORD *trustErrorStatus)
1195{
1197
1198 if (ext)
1199 compare_alt_name_with_constraints(ext, nameConstraints,
1200 trustErrorStatus);
1201 /* Name constraints apply to the subject alternative name as well as the
1202 * subject name. From RFC 5280, section 4.2.1.10:
1203 * "Restrictions apply to the subject distinguished name and apply to
1204 * subject alternative names."
1205 */
1206 compare_subject_with_constraints(&cert->Subject, nameConstraints,
1207 trustErrorStatus);
1208}
1209
1210/* Gets cert's name constraints, if any. Free with LocalFree. */
1212{
1214
1216
1218 cert->rgExtension)))
1219 {
1220 DWORD size;
1221
1223 ext->Value.pbData, ext->Value.cbData,
1225 &size);
1226 }
1227 return info;
1228}
1229
1231{
1232 DWORD i;
1233 BOOL ret = TRUE;
1234
1235 /* Make sure at least one permitted or excluded subtree is present. From
1236 * RFC 5280, section 4.2.1.10:
1237 * "Conforming CAs MUST NOT issue certificates where name constraints is an
1238 * empty sequence. That is, either the permittedSubtrees field or the
1239 * excludedSubtrees MUST be present."
1240 */
1241 if (!info->cPermittedSubtree && !info->cExcludedSubtree)
1242 {
1243 WARN_(chain)("constraints contain no permitted nor excluded subtree\n");
1244 ret = FALSE;
1245 }
1246 /* Check that none of the constraints specifies a minimum or a maximum.
1247 * See RFC 5280, section 4.2.1.10:
1248 * "Within this profile, the minimum and maximum fields are not used with
1249 * any name forms, thus, the minimum MUST be zero, and maximum MUST be
1250 * absent. However, if an application encounters a critical name
1251 * constraints extension that specifies other values for minimum or
1252 * maximum for a name form that appears in a subsequent certificate, the
1253 * application MUST either process these fields or reject the
1254 * certificate."
1255 * Since it gives no guidance as to how to process these fields, we
1256 * reject any name constraint that contains them.
1257 */
1258 for (i = 0; ret && i < info->cPermittedSubtree; i++)
1259 if (info->rgPermittedSubtree[i].dwMinimum ||
1260 info->rgPermittedSubtree[i].fMaximum)
1261 {
1262 TRACE_(chain)("found a minimum or maximum in permitted subtrees\n");
1263 ret = FALSE;
1264 }
1265 for (i = 0; ret && i < info->cExcludedSubtree; i++)
1266 if (info->rgExcludedSubtree[i].dwMinimum ||
1267 info->rgExcludedSubtree[i].fMaximum)
1268 {
1269 TRACE_(chain)("found a minimum or maximum in excluded subtrees\n");
1270 ret = FALSE;
1271 }
1272 return ret;
1273}
1274
1276{
1277 int i, j;
1278
1279 /* Microsoft's implementation appears to violate RFC 3280: according to
1280 * MSDN, the various CERT_TRUST_*_NAME_CONSTRAINT errors are set if a CA's
1281 * name constraint is violated in the end cert. According to RFC 3280,
1282 * the constraints should be checked against every subsequent certificate
1283 * in the chain, not just the end cert.
1284 * Microsoft's implementation also sets the name constraint errors on the
1285 * certs whose constraints were violated, not on the certs that violated
1286 * them.
1287 * In order to be error-compatible with Microsoft's implementation, while
1288 * still adhering to RFC 3280, I use a O(n ^ 2) algorithm to check name
1289 * constraints.
1290 */
1291 for (i = chain->cElement - 1; i > 0; i--)
1292 {
1293 CERT_NAME_CONSTRAINTS_INFO *nameConstraints;
1294
1295 if ((nameConstraints = CRYPT_GetNameConstraints(
1296 chain->rgpElement[i]->pCertContext->pCertInfo)))
1297 {
1298 if (!CRYPT_IsValidNameConstraint(nameConstraints))
1299 chain->rgpElement[i]->TrustStatus.dwErrorStatus |=
1301 else
1302 {
1303 for (j = i - 1; j >= 0; j--)
1304 {
1305 DWORD errorStatus = 0;
1306
1307 /* According to RFC 3280, self-signed certs don't have name
1308 * constraints checked unless they're the end cert.
1309 */
1310 if (j == 0 || !CRYPT_IsCertificateSelfSigned(
1311 chain->rgpElement[j]->pCertContext))
1312 {
1313 CRYPT_CheckNameConstraints(nameConstraints,
1314 chain->rgpElement[j]->pCertContext->pCertInfo,
1315 &errorStatus);
1316 if (errorStatus)
1317 {
1318 chain->rgpElement[i]->TrustStatus.dwErrorStatus |=
1319 errorStatus;
1320 CRYPT_CombineTrustStatus(&chain->TrustStatus,
1321 &chain->rgpElement[i]->TrustStatus);
1322 }
1323 else
1324 chain->rgpElement[i]->TrustStatus.dwInfoStatus |=
1326 }
1327 }
1328 }
1329 LocalFree(nameConstraints);
1330 }
1331 }
1332}
1333
1334/* Gets cert's policies info, if any. Free with LocalFree. */
1336{
1338 CERT_POLICIES_INFO *policies = NULL;
1339
1340 ext = CertFindExtension(szOID_KEY_USAGE, cert->pCertInfo->cExtension,
1341 cert->pCertInfo->rgExtension);
1342 if (ext)
1343 {
1344 DWORD size;
1345
1347 ext->Value.pbData, ext->Value.cbData, CRYPT_DECODE_ALLOC_FLAG, NULL,
1348 &policies, &size);
1349 }
1350 return policies;
1351}
1352
1354 DWORD *errorStatus)
1355{
1356 DWORD i;
1357
1358 for (i = 0; i < policies->cPolicyInfo; i++)
1359 {
1360 /* For now, the only accepted policy identifier is the anyPolicy
1361 * identifier.
1362 * FIXME: the policy identifiers should be compared against the
1363 * cert's certificate policies extension, subject to the policy
1364 * mappings extension, and the policy constraints extension.
1365 * See RFC 5280, sections 4.2.1.4, 4.2.1.5, and 4.2.1.11.
1366 */
1369 {
1370 FIXME("unsupported policy %s\n",
1373 }
1374 }
1375}
1376
1378{
1379 int i, j;
1380
1381 for (i = chain->cElement - 1; i > 0; i--)
1382 {
1383 CERT_POLICIES_INFO *policies;
1384
1385 if ((policies = CRYPT_GetPolicies(chain->rgpElement[i]->pCertContext)))
1386 {
1387 for (j = i - 1; j >= 0; j--)
1388 {
1389 DWORD errorStatus = 0;
1390
1391 CRYPT_CheckPolicies(policies,
1392 chain->rgpElement[j]->pCertContext->pCertInfo, &errorStatus);
1393 if (errorStatus)
1394 {
1395 chain->rgpElement[i]->TrustStatus.dwErrorStatus |=
1396 errorStatus;
1397 CRYPT_CombineTrustStatus(&chain->TrustStatus,
1398 &chain->rgpElement[i]->TrustStatus);
1399 }
1400 }
1401 LocalFree(policies);
1402 }
1403 }
1404}
1405
1407{
1410 LPWSTR str = NULL;
1411
1412 if (len)
1413 {
1414 str = CryptMemAlloc(len * sizeof(WCHAR));
1415 if (str)
1418 }
1419 return str;
1420}
1421
1423{
1424 LPWSTR str;
1425
1426 switch (entry->dwAltNameChoice)
1427 {
1429 TRACE_(chain)("CERT_ALT_NAME_OTHER_NAME, oid = %s\n",
1430 debugstr_a(entry->pOtherName->pszObjId));
1431 break;
1433 TRACE_(chain)("CERT_ALT_NAME_RFC822_NAME: %s\n",
1434 debugstr_w(entry->pwszRfc822Name));
1435 break;
1437 TRACE_(chain)("CERT_ALT_NAME_DNS_NAME: %s\n",
1438 debugstr_w(entry->pwszDNSName));
1439 break;
1441 str = name_value_to_str(&entry->DirectoryName);
1442 TRACE_(chain)("CERT_ALT_NAME_DIRECTORY_NAME: %s\n", debugstr_w(str));
1444 break;
1445 case CERT_ALT_NAME_URL:
1446 TRACE_(chain)("CERT_ALT_NAME_URL: %s\n", debugstr_w(entry->pwszURL));
1447 break;
1449 TRACE_(chain)("CERT_ALT_NAME_IP_ADDRESS: %ld bytes\n",
1450 entry->IPAddress.cbData);
1451 break;
1453 TRACE_(chain)("CERT_ALT_NAME_REGISTERED_ID: %s\n",
1454 debugstr_a(entry->pszRegisteredID));
1455 break;
1456 default:
1457 TRACE_(chain)("dwAltNameChoice = %ld\n", entry->dwAltNameChoice);
1458 }
1459}
1460
1462{
1464 DWORD size;
1465
1466 TRACE_(chain)("%s:\n", type);
1468 ext->Value.pbData, ext->Value.cbData,
1470 {
1471 DWORD i;
1472
1473 TRACE_(chain)("%ld alt name entries:\n", name->cAltEntry);
1474 for (i = 0; i < name->cAltEntry; i++)
1475 dump_alt_name_entry(&name->rgAltEntry[i]);
1476 LocalFree(name);
1477 }
1478}
1479
1481{
1483 DWORD size = 0;
1484
1486 ext->Value.pbData, ext->Value.cbData, CRYPT_DECODE_ALLOC_FLAG,
1487 NULL, &info, &size))
1488 {
1489 TRACE_(chain)("SubjectType: %02x\n", info->SubjectType.pbData[0]);
1490 TRACE_(chain)("%s path length constraint\n",
1491 info->fPathLenConstraint ? "has" : "doesn't have");
1492 TRACE_(chain)("path length=%ld\n", info->dwPathLenConstraint);
1493 LocalFree(info);
1494 }
1495}
1496
1498{
1499 CERT_BASIC_CONSTRAINTS2_INFO constraints;
1501
1503 szOID_BASIC_CONSTRAINTS2, ext->Value.pbData, ext->Value.cbData,
1504 0, NULL, &constraints, &size))
1505 {
1506 TRACE_(chain)("basic constraints:\n");
1507 TRACE_(chain)("can%s be a CA\n", constraints.fCA ? "" : "not");
1508 TRACE_(chain)("%s path length constraint\n",
1509 constraints.fPathLenConstraint ? "has" : "doesn't have");
1510 TRACE_(chain)("path length=%ld\n", constraints.dwPathLenConstraint);
1511 }
1512}
1513
1515{
1517 DWORD size = sizeof(usage);
1518
1520 ext->Value.cbData, CRYPT_DECODE_NOCOPY_FLAG, NULL, &usage, &size))
1521 {
1522#define trace_usage_bit(bits, bit) \
1523 if ((bits) & (bit)) TRACE_(chain)("%s\n", #bit)
1524 if (usage.cbData)
1525 {
1534 }
1535#undef trace_usage_bit
1536 if (usage.cbData > 1 && usage.pbData[1] & CERT_DECIPHER_ONLY_KEY_USAGE)
1537 TRACE_(chain)("CERT_DECIPHER_ONLY_KEY_USAGE\n");
1538 }
1539}
1540
1542{
1543 dump_alt_name_entry(&subtree->Base);
1544 TRACE_(chain)("dwMinimum = %ld, fMaximum = %d, dwMaximum = %ld\n",
1545 subtree->dwMinimum, subtree->fMaximum, subtree->dwMaximum);
1546}
1547
1549{
1550 CERT_NAME_CONSTRAINTS_INFO *nameConstraints;
1551 DWORD size;
1552
1554 ext->Value.pbData, ext->Value.cbData,
1556 &size))
1557 {
1558 DWORD i;
1559
1560 TRACE_(chain)("%ld permitted subtrees:\n",
1561 nameConstraints->cPermittedSubtree);
1562 for (i = 0; i < nameConstraints->cPermittedSubtree; i++)
1563 dump_general_subtree(&nameConstraints->rgPermittedSubtree[i]);
1564 TRACE_(chain)("%ld excluded subtrees:\n",
1565 nameConstraints->cExcludedSubtree);
1566 for (i = 0; i < nameConstraints->cExcludedSubtree; i++)
1567 dump_general_subtree(&nameConstraints->rgExcludedSubtree[i]);
1568 LocalFree(nameConstraints);
1569 }
1570}
1571
1573{
1574 CERT_POLICIES_INFO *policies;
1575 DWORD size;
1576
1578 ext->Value.pbData, ext->Value.cbData, CRYPT_DECODE_ALLOC_FLAG, NULL,
1579 &policies, &size))
1580 {
1581 DWORD i, j;
1582
1583 TRACE_(chain)("%ld policies:\n", policies->cPolicyInfo);
1584 for (i = 0; i < policies->cPolicyInfo; i++)
1585 {
1586 TRACE_(chain)("policy identifier: %s\n",
1588 TRACE_(chain)("%ld policy qualifiers:\n",
1589 policies->rgPolicyInfo[i].cPolicyQualifier);
1590 for (j = 0; j < policies->rgPolicyInfo[i].cPolicyQualifier; j++)
1591 TRACE_(chain)("%s\n", debugstr_a(
1592 policies->rgPolicyInfo[i].rgPolicyQualifier[j].
1593 pszPolicyQualifierId));
1594 }
1595 LocalFree(policies);
1596 }
1597}
1598
1600{
1602 DWORD size;
1603
1605 ext->Value.pbData, ext->Value.cbData, CRYPT_DECODE_ALLOC_FLAG, NULL,
1606 &usage, &size))
1607 {
1608 DWORD i;
1609
1610 TRACE_(chain)("%ld usages:\n", usage->cUsageIdentifier);
1611 for (i = 0; i < usage->cUsageIdentifier; i++)
1612 TRACE_(chain)("%s\n", usage->rgpszUsageIdentifier[i]);
1614 }
1615}
1616
1618{
1620 DWORD size = sizeof(usage);
1621
1623 ext->Value.cbData, CRYPT_DECODE_NOCOPY_FLAG, NULL, &usage, &size))
1624 {
1625#define trace_cert_type_bit(bits, bit) \
1626 if ((bits) & (bit)) TRACE_(chain)("%s\n", #bit)
1627 if (usage.cbData)
1628 {
1629 trace_cert_type_bit(usage.pbData[0],
1631 trace_cert_type_bit(usage.pbData[0],
1638 }
1639#undef trace_cert_type_bit
1640 }
1641}
1642
1644{
1645 TRACE_(chain)("%s (%scritical)\n", debugstr_a(ext->pszObjId),
1646 ext->fCritical ? "" : "not ");
1647 if (!strcmp(ext->pszObjId, szOID_SUBJECT_ALT_NAME))
1648 dump_alt_name("subject alt name", ext);
1649 else if (!strcmp(ext->pszObjId, szOID_ISSUER_ALT_NAME))
1650 dump_alt_name("issuer alt name", ext);
1651 else if (!strcmp(ext->pszObjId, szOID_BASIC_CONSTRAINTS))
1653 else if (!strcmp(ext->pszObjId, szOID_KEY_USAGE))
1655 else if (!strcmp(ext->pszObjId, szOID_SUBJECT_ALT_NAME2))
1656 dump_alt_name("subject alt name 2", ext);
1657 else if (!strcmp(ext->pszObjId, szOID_ISSUER_ALT_NAME2))
1658 dump_alt_name("issuer alt name 2", ext);
1659 else if (!strcmp(ext->pszObjId, szOID_BASIC_CONSTRAINTS2))
1661 else if (!strcmp(ext->pszObjId, szOID_NAME_CONSTRAINTS))
1663 else if (!strcmp(ext->pszObjId, szOID_CERT_POLICIES))
1665 else if (!strcmp(ext->pszObjId, szOID_ENHANCED_KEY_USAGE))
1667 else if (!strcmp(ext->pszObjId, szOID_NETSCAPE_CERT_TYPE))
1669}
1670
1672{
1673 char date[80];
1674 char dateFmt[80]; /* sufficient for all versions of LOCALE_SSHORTDATE */
1675 SYSTEMTIME sysTime;
1676
1677 if (!time) return "(null)";
1678
1680 FileTimeToSystemTime(time, &sysTime);
1681 GetDateFormatA(LOCALE_SYSTEM_DEFAULT, 0, &sysTime, dateFmt, date, ARRAY_SIZE(date));
1682 return wine_dbg_sprintf("%s", date);
1683}
1684
1686{
1687 LPWSTR name = NULL;
1688 DWORD len, i;
1689
1690 TRACE_(chain)("%p: version %ld\n", cert, cert->pCertInfo->dwVersion);
1693 name = CryptMemAlloc(len * sizeof(WCHAR));
1694 if (name)
1695 {
1698 TRACE_(chain)("issued by %s\n", debugstr_w(name));
1700 }
1702 NULL, 0);
1703 name = CryptMemAlloc(len * sizeof(WCHAR));
1704 if (name)
1705 {
1707 name, len);
1708 TRACE_(chain)("issued to %s\n", debugstr_w(name));
1710 }
1711 TRACE_(chain)("valid from %s to %s\n",
1712 filetime_to_str(&cert->pCertInfo->NotBefore),
1713 filetime_to_str(&cert->pCertInfo->NotAfter));
1714 TRACE_(chain)("%ld extensions\n", cert->pCertInfo->cExtension);
1715 for (i = 0; i < cert->pCertInfo->cExtension; i++)
1716 dump_extension(&cert->pCertInfo->rgExtension[i]);
1717}
1718
1720 PCCERT_CONTEXT cert, BOOL isRoot, BOOL isCA, DWORD index)
1721{
1723 BOOL ret;
1724 BYTE usageBits = 0;
1725
1726 ext = CertFindExtension(szOID_KEY_USAGE, cert->pCertInfo->cExtension,
1727 cert->pCertInfo->rgExtension);
1728 if (ext)
1729 {
1731 DWORD size = sizeof(usage);
1732
1733 ret = CryptDecodeObjectEx(cert->dwCertEncodingType, X509_BITS,
1734 ext->Value.pbData, ext->Value.cbData, CRYPT_DECODE_NOCOPY_FLAG, NULL,
1735 &usage, &size);
1736 if (!ret)
1737 return FALSE;
1738 else if (usage.cbData > 2)
1739 {
1740 /* The key usage extension only defines 9 bits => no more than 2
1741 * bytes are needed to encode all known usages.
1742 */
1743 return FALSE;
1744 }
1745 else
1746 {
1747 /* The only bit relevant to chain validation is the keyCertSign
1748 * bit, which is always in the least significant byte of the
1749 * key usage bits.
1750 */
1751 usageBits = usage.pbData[usage.cbData - 1];
1752 }
1753 }
1754 if (isCA)
1755 {
1756 if (!ext)
1757 {
1758 /* MS appears to violate RFC 5280, section 4.2.1.3 (Key Usage)
1759 * here. Quoting the RFC:
1760 * "This [key usage] extension MUST appear in certificates that
1761 * contain public keys that are used to validate digital signatures
1762 * on other public key certificates or CRLs."
1763 * MS appears to accept certs that do not contain key usage
1764 * extensions as CA certs. V1 and V2 certificates did not have
1765 * extensions, and many root certificates are V1 certificates, so
1766 * perhaps this is prudent. On the other hand, MS also accepts V3
1767 * certs without key usage extensions. Because some CAs, e.g.
1768 * Certum, also do not include key usage extensions in their
1769 * intermediate certificates, we are forced to accept V3
1770 * certificates without key usage extensions as well.
1771 */
1772 ret = TRUE;
1773 }
1774 else
1775 {
1776 if (!(usageBits & CERT_KEY_CERT_SIGN_KEY_USAGE))
1777 {
1778 WARN_(chain)("keyCertSign not asserted on a CA cert\n");
1779 ret = FALSE;
1780 }
1781 else
1782 ret = TRUE;
1783 }
1784 }
1785 else
1786 {
1787 if (ext && (usageBits & CERT_KEY_CERT_SIGN_KEY_USAGE))
1788 {
1789 WARN_(chain)("keyCertSign asserted on a non-CA cert\n");
1790 ret = FALSE;
1791 }
1792 else
1793 ret = TRUE;
1794 }
1795 return ret;
1796}
1797
1799{
1800 BOOL ret = TRUE;
1801 DWORD i;
1802
1803 for (i = 0; ret && i < cert->pCertInfo->cExtension; i++)
1804 {
1805 if (cert->pCertInfo->rgExtension[i].fCritical)
1806 {
1807 LPCSTR oid = cert->pCertInfo->rgExtension[i].pszObjId;
1808
1810 ret = TRUE;
1811 else if (!strcmp(oid, szOID_BASIC_CONSTRAINTS2))
1812 ret = TRUE;
1813 else if (!strcmp(oid, szOID_NAME_CONSTRAINTS))
1814 ret = TRUE;
1815 else if (!strcmp(oid, szOID_KEY_USAGE))
1816 ret = TRUE;
1817 else if (!strcmp(oid, szOID_SUBJECT_ALT_NAME))
1818 ret = TRUE;
1819 else if (!strcmp(oid, szOID_SUBJECT_ALT_NAME2))
1820 ret = TRUE;
1821 else if (!strcmp(oid, szOID_CERT_POLICIES))
1822 ret = TRUE;
1823 else if (!strcmp(oid, szOID_ENHANCED_KEY_USAGE))
1824 ret = TRUE;
1825 else
1826 {
1827 FIXME("unsupported critical extension %s\n",
1828 debugstr_a(oid));
1829 ret = FALSE;
1830 }
1831 }
1832 }
1833 return ret;
1834}
1835
1837{
1838 BOOL ret = TRUE;
1839
1840 /* Checks whether the contents of the cert match the cert's version. */
1841 switch (cert->pCertInfo->dwVersion)
1842 {
1843 case CERT_V1:
1844 /* A V1 cert may not contain unique identifiers. See RFC 5280,
1845 * section 4.1.2.8:
1846 * "These fields MUST only appear if the version is 2 or 3 (Section
1847 * 4.1.2.1). These fields MUST NOT appear if the version is 1."
1848 */
1849 if (cert->pCertInfo->IssuerUniqueId.cbData ||
1850 cert->pCertInfo->SubjectUniqueId.cbData)
1851 ret = FALSE;
1852 /* A V1 cert may not contain extensions. See RFC 5280, section 4.1.2.9:
1853 * "This field MUST only appear if the version is 3 (Section 4.1.2.1)."
1854 */
1855 if (cert->pCertInfo->cExtension)
1856 ret = FALSE;
1857 break;
1858 case CERT_V2:
1859 /* A V2 cert may not contain extensions. See RFC 5280, section 4.1.2.9:
1860 * "This field MUST only appear if the version is 3 (Section 4.1.2.1)."
1861 */
1862 if (cert->pCertInfo->cExtension)
1863 ret = FALSE;
1864 break;
1865 case CERT_V3:
1866 /* Do nothing, all fields are allowed for V3 certs */
1867 break;
1868 default:
1869 WARN_(chain)("invalid cert version %ld\n", cert->pCertInfo->dwVersion);
1870 ret = FALSE;
1871 }
1872 return ret;
1873}
1874
1877{
1878 PCERT_CHAIN_ELEMENT rootElement = chain->rgpElement[chain->cElement - 1];
1879 int i;
1880 BOOL pathLengthConstraintViolated = FALSE;
1881 CERT_BASIC_CONSTRAINTS2_INFO constraints = { FALSE, FALSE, 0 };
1882 DWORD status;
1883
1884 TRACE_(chain)("checking chain with %ld elements for time %s\n",
1885 chain->cElement, filetime_to_str(time));
1886 for (i = chain->cElement - 1; i >= 0; i--)
1887 {
1888 BOOL isRoot;
1889
1890 if (TRACE_ON(chain))
1891 dump_element(chain->rgpElement[i]->pCertContext);
1892 if (i == chain->cElement - 1)
1894 chain->rgpElement[i]->pCertContext);
1895 else
1896 isRoot = FALSE;
1897 if (!CRYPT_IsCertVersionValid(chain->rgpElement[i]->pCertContext))
1898 {
1899 /* MS appears to accept certs whose versions don't match their
1900 * contents, so there isn't an appropriate error code.
1901 */
1902 chain->rgpElement[i]->TrustStatus.dwErrorStatus |=
1904 }
1906 chain->rgpElement[i]->pCertContext->pCertInfo) != 0)
1907 chain->rgpElement[i]->TrustStatus.dwErrorStatus |=
1909 if (i != 0)
1910 {
1911 /* Check the signature of the cert this issued */
1914 (void *)chain->rgpElement[i - 1]->pCertContext,
1916 (void *)chain->rgpElement[i]->pCertContext, 0, NULL))
1917 chain->rgpElement[i - 1]->TrustStatus.dwErrorStatus |=
1919 /* Once a path length constraint has been violated, every remaining
1920 * CA cert's basic constraints is considered invalid.
1921 */
1922 if (pathLengthConstraintViolated)
1923 chain->rgpElement[i]->TrustStatus.dwErrorStatus |=
1925 else if (!CRYPT_CheckBasicConstraintsForCA(engine,
1926 chain->rgpElement[i]->pCertContext, &constraints, i - 1, isRoot,
1927 &pathLengthConstraintViolated))
1928 chain->rgpElement[i]->TrustStatus.dwErrorStatus |=
1930 else if (constraints.fPathLenConstraint &&
1931 constraints.dwPathLenConstraint)
1932 {
1933 /* This one's valid - decrement max length */
1934 constraints.dwPathLenConstraint--;
1935 }
1936 }
1937 else
1938 {
1939 /* Check whether end cert has a basic constraints extension */
1941 chain->rgpElement[i]->pCertContext, &constraints, FALSE))
1942 chain->rgpElement[i]->TrustStatus.dwErrorStatus |=
1944 }
1945 if (!CRYPT_KeyUsageValid(engine, chain->rgpElement[i]->pCertContext,
1946 isRoot, constraints.fCA, i))
1947 chain->rgpElement[i]->TrustStatus.dwErrorStatus |=
1950 {
1951 /* If the chain is cyclic, then the path length constraints
1952 * are violated, because the chain is infinitely long.
1953 */
1954 pathLengthConstraintViolated = TRUE;
1955 chain->TrustStatus.dwErrorStatus |=
1958 }
1959 /* Check whether every critical extension is supported */
1961 chain->rgpElement[i]->pCertContext))
1962 chain->rgpElement[i]->TrustStatus.dwErrorStatus |=
1965 CRYPT_CombineTrustStatus(&chain->TrustStatus,
1966 &chain->rgpElement[i]->TrustStatus);
1967 }
1971 {
1972 rootElement->TrustStatus.dwInfoStatus |= status;
1973 CRYPT_CheckRootCert(engine->hRoot, rootElement);
1974 }
1975 CRYPT_CombineTrustStatus(&chain->TrustStatus, &rootElement->TrustStatus);
1976}
1977
1979 HCERTSTORE store, DWORD type, void *para, DWORD flags, PCCERT_CONTEXT prev_issuer)
1980{
1981 CRYPT_URL_ARRAY *urls;
1983 DWORD size;
1984 BOOL res;
1985
1986 issuer = CertFindCertificateInStore(store, cert->dwCertEncodingType, 0, type, para, prev_issuer);
1987 if(issuer) {
1988 TRACE("Found in store %p\n", issuer);
1989 return issuer;
1990 }
1991
1992 /* FIXME: For alternate issuers, we don't search world store nor try to retrieve issuer from URL.
1993 * This needs more tests.
1994 */
1995 if(prev_issuer)
1996 return NULL;
1997
1998 if(engine->hWorld) {
1999 issuer = CertFindCertificateInStore(engine->hWorld, cert->dwCertEncodingType, 0, type, para, NULL);
2000 if(issuer) {
2001 TRACE("Found in world %p\n", issuer);
2002 return issuer;
2003 }
2004 }
2005
2007 if(!res)
2008 return NULL;
2009
2010 urls = CryptMemAlloc(size);
2011 if(!urls)
2012 return NULL;
2013
2015 if(res)
2016 {
2017 CERT_CONTEXT *new_cert;
2018 HCERTSTORE new_store;
2019 unsigned i;
2020
2021 for(i=0; i < urls->cUrl; i++)
2022 {
2023 TRACE("Trying URL %s\n", debugstr_w(urls->rgwszUrl[i]));
2024
2027 0, (void**)&new_cert, NULL, NULL, NULL, NULL);
2028 if(!res)
2029 {
2030 TRACE("CryptRetrieveObjectByUrlW failed: %lu\n", GetLastError());
2031 continue;
2032 }
2033
2034 /* FIXME: Use new_cert->hCertStore once cert ref count bug is fixed. */
2037 issuer = CertFindCertificateInStore(new_store, cert->dwCertEncodingType, 0, type, para, NULL);
2039 CertCloseStore(new_store, 0);
2040 if(issuer)
2041 {
2042 TRACE("Found downloaded issuer %p\n", issuer);
2043 break;
2044 }
2045 }
2046 }
2047
2048 CryptMemFree(urls);
2049 return issuer;
2050}
2051
2053 HCERTSTORE store, PCCERT_CONTEXT subject, PCCERT_CONTEXT prevIssuer,
2054 DWORD flags, DWORD *infoStatus)
2055{
2058 DWORD size;
2059
2060 *infoStatus = 0;
2062 subject->pCertInfo->cExtension, subject->pCertInfo->rgExtension)))
2063 {
2065 BOOL ret;
2066
2068 X509_AUTHORITY_KEY_ID, ext->Value.pbData, ext->Value.cbData,
2070 &info, &size);
2071 if (ret)
2072 {
2073 CERT_ID id;
2074
2075 if (info->CertIssuer.cbData && info->CertSerialNumber.cbData)
2076 {
2077 id.dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER;
2078 memcpy(&id.IssuerSerialNumber.Issuer, &info->CertIssuer,
2079 sizeof(CERT_NAME_BLOB));
2080 memcpy(&id.IssuerSerialNumber.SerialNumber,
2081 &info->CertSerialNumber, sizeof(CRYPT_INTEGER_BLOB));
2082
2083 issuer = CRYPT_FindIssuer(engine, subject, store, CERT_FIND_CERT_ID, &id, flags, prevIssuer);
2084 if (issuer)
2085 {
2086 TRACE_(chain)("issuer found by issuer/serial number\n");
2088 }
2089 }
2090 else if (info->KeyId.cbData)
2091 {
2092 id.dwIdChoice = CERT_ID_KEY_IDENTIFIER;
2093
2094 memcpy(&id.KeyId, &info->KeyId, sizeof(CRYPT_HASH_BLOB));
2095 issuer = CRYPT_FindIssuer(engine, subject, store, CERT_FIND_CERT_ID, &id, flags, prevIssuer);
2096 if (issuer)
2097 {
2098 TRACE_(chain)("issuer found by key id\n");
2099 *infoStatus = CERT_TRUST_HAS_KEY_MATCH_ISSUER;
2100 }
2101 }
2102 LocalFree(info);
2103 }
2104 }
2106 subject->pCertInfo->cExtension, subject->pCertInfo->rgExtension)))
2107 {
2109 BOOL ret;
2110
2112 X509_AUTHORITY_KEY_ID2, ext->Value.pbData, ext->Value.cbData,
2114 &info, &size);
2115 if (ret)
2116 {
2117 CERT_ID id;
2118
2119 if (info->AuthorityCertIssuer.cAltEntry &&
2120 info->AuthorityCertSerialNumber.cbData)
2121 {
2122 PCERT_ALT_NAME_ENTRY directoryName = NULL;
2123 DWORD i;
2124
2125 for (i = 0; !directoryName &&
2126 i < info->AuthorityCertIssuer.cAltEntry; i++)
2127 if (info->AuthorityCertIssuer.rgAltEntry[i].dwAltNameChoice
2129 directoryName =
2130 &info->AuthorityCertIssuer.rgAltEntry[i];
2131 if (directoryName)
2132 {
2133 id.dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER;
2134 memcpy(&id.IssuerSerialNumber.Issuer,
2135 &directoryName->DirectoryName, sizeof(CERT_NAME_BLOB));
2136 memcpy(&id.IssuerSerialNumber.SerialNumber,
2137 &info->AuthorityCertSerialNumber,
2138 sizeof(CRYPT_INTEGER_BLOB));
2139
2140 issuer = CRYPT_FindIssuer(engine, subject, store, CERT_FIND_CERT_ID, &id, flags, prevIssuer);
2141 if (issuer)
2142 {
2143 TRACE_(chain)("issuer found by directory name\n");
2145 }
2146 }
2147 else
2148 FIXME("no supported name type in authority key id2\n");
2149 }
2150 else if (info->KeyId.cbData)
2151 {
2152 id.dwIdChoice = CERT_ID_KEY_IDENTIFIER;
2153 memcpy(&id.KeyId, &info->KeyId, sizeof(CRYPT_HASH_BLOB));
2154 issuer = CRYPT_FindIssuer(engine, subject, store, CERT_FIND_CERT_ID, &id, flags, prevIssuer);
2155 if (issuer)
2156 {
2157 TRACE_(chain)("issuer found by key id\n");
2158 *infoStatus = CERT_TRUST_HAS_KEY_MATCH_ISSUER;
2159 }
2160 }
2161 LocalFree(info);
2162 }
2163 }
2164 else
2165 {
2166 issuer = CRYPT_FindIssuer(engine, subject, store, CERT_FIND_SUBJECT_NAME,
2167 &subject->pCertInfo->Issuer, flags, prevIssuer);
2168 TRACE_(chain)("issuer found by name\n");
2170 }
2171 return issuer;
2172}
2173
2174/* Builds a simple chain by finding an issuer for the last cert in the chain,
2175 * until reaching a self-signed cert, or until no issuer can be found.
2176 */
2179{
2180 BOOL ret = TRUE;
2181 PCCERT_CONTEXT cert = chain->rgpElement[chain->cElement - 1]->pCertContext;
2182
2183 while (ret && !CRYPT_IsSimpleChainCyclic(chain) &&
2185 {
2187 &chain->rgpElement[chain->cElement - 1]->TrustStatus.dwInfoStatus);
2188
2189 if (issuer)
2190 {
2192 chain->rgpElement[chain->cElement - 1]->TrustStatus.dwInfoStatus);
2193 /* CRYPT_AddCertToSimpleChain add-ref's the issuer, so free it to
2194 * close the enumeration that found it
2195 */
2197 cert = issuer;
2198 }
2199 else
2200 {
2201 TRACE_(chain)("Couldn't find issuer, halting chain creation\n");
2202 chain->TrustStatus.dwErrorStatus |= CERT_TRUST_IS_PARTIAL_CHAIN;
2203 break;
2204 }
2205 }
2206 return ret;
2207}
2208
2210{
2211 if (!pTime)
2212 return "(nil)";
2213 return wine_dbg_sprintf("%p (%s)", pTime, filetime_to_str(pTime));
2214}
2215
2218 PCERT_SIMPLE_CHAIN *ppChain)
2219{
2220 BOOL ret = FALSE;
2222
2223 TRACE("(%p, %p, %p, %s)\n", engine, world, cert, debugstr_filetime(pTime));
2224
2226 if (chain)
2227 {
2228 memset(chain, 0, sizeof(CERT_SIMPLE_CHAIN));
2229 chain->cbSize = sizeof(CERT_SIMPLE_CHAIN);
2231 if (ret)
2232 {
2233 ret = CRYPT_BuildSimpleChain(engine, world, flags, chain);
2234 if (ret)
2235 CRYPT_CheckSimpleChain(engine, chain, pTime);
2236 }
2237 if (!ret)
2238 {
2240 chain = NULL;
2241 }
2242 *ppChain = chain;
2243 }
2244 return ret;
2245}
2246
2248 PCCERT_CONTEXT cert, LPFILETIME pTime, HCERTSTORE hAdditionalStore, DWORD flags,
2249 CertificateChain **ppChain)
2250{
2251 PCERT_SIMPLE_CHAIN simpleChain = NULL;
2252 HCERTSTORE world;
2253 BOOL ret;
2254
2257 CertAddStoreToCollection(world, engine->hWorld, 0, 0);
2258 if (hAdditionalStore)
2259 CertAddStoreToCollection(world, hAdditionalStore, 0, 0);
2260 /* FIXME: only simple chains are supported for now, as CTLs aren't
2261 * supported yet.
2262 */
2263 if ((ret = CRYPT_GetSimpleChainForCert(engine, world, cert, pTime, flags, &simpleChain)))
2264 {
2266
2267 if (chain)
2268 {
2269 chain->ref = 1;
2270 chain->world = world;
2271 chain->context.cbSize = sizeof(CERT_CHAIN_CONTEXT);
2272 chain->context.TrustStatus = simpleChain->TrustStatus;
2273 chain->context.cChain = 1;
2274 chain->context.rgpChain = CryptMemAlloc(sizeof(PCERT_SIMPLE_CHAIN));
2275 chain->context.rgpChain[0] = simpleChain;
2276 chain->context.cLowerQualityChainContext = 0;
2277 chain->context.rgpLowerQualityChainContext = NULL;
2278 chain->context.fHasRevocationFreshnessTime = FALSE;
2279 chain->context.dwRevocationFreshnessTime = 0;
2280 }
2281 else
2282 {
2283 CRYPT_FreeSimpleChain(simpleChain);
2284 ret = FALSE;
2285 }
2286 *ppChain = chain;
2287 }
2288 return ret;
2289}
2290
2291/* Makes and returns a copy of chain, up to and including element iElement. */
2293 const CERT_SIMPLE_CHAIN *chain, DWORD iElement)
2294{
2296
2297 if (copy)
2298 {
2299 memset(copy, 0, sizeof(CERT_SIMPLE_CHAIN));
2300 copy->cbSize = sizeof(CERT_SIMPLE_CHAIN);
2301 copy->rgpElement =
2302 CryptMemAlloc((iElement + 1) * sizeof(PCERT_CHAIN_ELEMENT));
2303 if (copy->rgpElement)
2304 {
2305 DWORD i;
2306 BOOL ret = TRUE;
2307
2308 memset(copy->rgpElement, 0,
2309 (iElement + 1) * sizeof(PCERT_CHAIN_ELEMENT));
2310 for (i = 0; ret && i <= iElement; i++)
2311 {
2314
2315 if (element)
2316 {
2317 *element = *chain->rgpElement[i];
2319 chain->rgpElement[i]->pCertContext);
2320 /* Reset the trust status of the copied element, it'll get
2321 * rechecked after the new chain is done.
2322 */
2323 memset(&element->TrustStatus, 0, sizeof(CERT_TRUST_STATUS));
2324 copy->rgpElement[copy->cElement++] = element;
2325 }
2326 else
2327 ret = FALSE;
2328 }
2329 if (!ret)
2330 {
2331 for (i = 0; i <= iElement; i++)
2332 CryptMemFree(copy->rgpElement[i]);
2333 CryptMemFree(copy->rgpElement);
2335 copy = NULL;
2336 }
2337 }
2338 else
2339 {
2341 copy = NULL;
2342 }
2343 }
2344 return copy;
2345}
2346
2348{
2349 DWORD i;
2350
2351 for (i = 0; i < chain->context.cLowerQualityChainContext; i++)
2352 CertFreeCertificateChain(chain->context.rgpLowerQualityChainContext[i]);
2353 CryptMemFree(chain->context.rgpLowerQualityChainContext);
2354 chain->context.cLowerQualityChainContext = 0;
2355 chain->context.rgpLowerQualityChainContext = NULL;
2356}
2357
2359{
2360 DWORD i;
2361
2363 for (i = 0; i < chain->context.cChain; i++)
2364 CRYPT_FreeSimpleChain(chain->context.rgpChain[i]);
2365 CryptMemFree(chain->context.rgpChain);
2366 CertCloseStore(chain->world, 0);
2368}
2369
2370/* Makes and returns a copy of chain, up to and including element iElement of
2371 * simple chain iChain.
2372 */
2374 DWORD iChain, DWORD iElement)
2375{
2377
2378 if (copy)
2379 {
2380 copy->ref = 1;
2381 copy->world = CertDuplicateStore(chain->world);
2382 copy->context.cbSize = sizeof(CERT_CHAIN_CONTEXT);
2383 /* Leave the trust status of the copied chain unset, it'll get
2384 * rechecked after the new chain is done.
2385 */
2386 memset(&copy->context.TrustStatus, 0, sizeof(CERT_TRUST_STATUS));
2387 copy->context.cLowerQualityChainContext = 0;
2388 copy->context.rgpLowerQualityChainContext = NULL;
2389 copy->context.fHasRevocationFreshnessTime = FALSE;
2390 copy->context.dwRevocationFreshnessTime = 0;
2391 copy->context.rgpChain = CryptMemAlloc(
2392 (iChain + 1) * sizeof(PCERT_SIMPLE_CHAIN));
2393 if (copy->context.rgpChain)
2394 {
2395 BOOL ret = TRUE;
2396 DWORD i;
2397
2398 memset(copy->context.rgpChain, 0,
2399 (iChain + 1) * sizeof(PCERT_SIMPLE_CHAIN));
2400 if (iChain)
2401 {
2402 for (i = 0; ret && iChain && i < iChain - 1; i++)
2403 {
2404 copy->context.rgpChain[i] =
2405 CRYPT_CopySimpleChainToElement(chain->context.rgpChain[i],
2406 chain->context.rgpChain[i]->cElement - 1);
2407 if (!copy->context.rgpChain[i])
2408 ret = FALSE;
2409 }
2410 }
2411 else
2412 i = 0;
2413 if (ret)
2414 {
2415 copy->context.rgpChain[i] =
2416 CRYPT_CopySimpleChainToElement(chain->context.rgpChain[i],
2417 iElement);
2418 if (!copy->context.rgpChain[i])
2419 ret = FALSE;
2420 }
2421 if (!ret)
2422 {
2424 copy = NULL;
2425 }
2426 else
2427 copy->context.cChain = iChain + 1;
2428 }
2429 else
2430 {
2432 copy = NULL;
2433 }
2434 }
2435 return copy;
2436}
2437
2439 CertificateChainEngine *engine, LPFILETIME pTime, HCERTSTORE hAdditionalStore,
2441{
2442 CertificateChain *alternate;
2443
2444 TRACE("(%p, %s, %p, %p)\n", engine, debugstr_filetime(pTime),
2445 hAdditionalStore, chain);
2446
2447 /* Always start with the last "lower quality" chain to ensure a consistent
2448 * order of alternate creation:
2449 */
2450 if (chain->context.cLowerQualityChainContext)
2451 chain = (CertificateChain*)chain->context.rgpLowerQualityChainContext[
2452 chain->context.cLowerQualityChainContext - 1];
2453 /* A chain with only one element can't have any alternates */
2454 if (chain->context.cChain <= 1 && chain->context.rgpChain[0]->cElement <= 1)
2455 alternate = NULL;
2456 else
2457 {
2458 DWORD i, j, infoStatus;
2459 PCCERT_CONTEXT alternateIssuer = NULL;
2460
2461 alternate = NULL;
2462 for (i = 0; !alternateIssuer && i < chain->context.cChain; i++)
2463 for (j = 0; !alternateIssuer &&
2464 j < chain->context.rgpChain[i]->cElement - 1; j++)
2465 {
2466 PCCERT_CONTEXT subject =
2467 chain->context.rgpChain[i]->rgpElement[j]->pCertContext;
2469 chain->context.rgpChain[i]->rgpElement[j + 1]->pCertContext);
2470
2471 alternateIssuer = CRYPT_GetIssuer(engine, prevIssuer->hCertStore,
2472 subject, prevIssuer, flags, &infoStatus);
2473 }
2474 if (alternateIssuer)
2475 {
2476 i--;
2477 j--;
2478 alternate = CRYPT_CopyChainToElement(chain, i, j);
2479 if (alternate)
2480 {
2482 alternate->context.rgpChain[i], alternateIssuer, infoStatus);
2483
2484 /* CRYPT_AddCertToSimpleChain add-ref's the issuer, so free it
2485 * to close the enumeration that found it
2486 */
2487 CertFreeCertificateContext(alternateIssuer);
2488 if (ret)
2489 {
2490 ret = CRYPT_BuildSimpleChain(engine, alternate->world,
2491 flags, alternate->context.rgpChain[i]);
2492 if (ret)
2494 alternate->context.rgpChain[i], pTime);
2496 &alternate->context.rgpChain[i]->TrustStatus);
2497 }
2498 if (!ret)
2499 {
2500 CRYPT_FreeChainContext(alternate);
2501 alternate = NULL;
2502 }
2503 }
2504 }
2505 }
2506 TRACE("%p\n", alternate);
2507 return alternate;
2508}
2509
2510#define CHAIN_QUALITY_SIGNATURE_VALID 0x16
2511#define CHAIN_QUALITY_TIME_VALID 8
2512#define CHAIN_QUALITY_COMPLETE_CHAIN 4
2513#define CHAIN_QUALITY_BASIC_CONSTRAINTS 2
2514#define CHAIN_QUALITY_TRUSTED_ROOT 1
2515
2516#define CHAIN_QUALITY_HIGHEST \
2517 CHAIN_QUALITY_SIGNATURE_VALID | CHAIN_QUALITY_TIME_VALID | \
2518 CHAIN_QUALITY_COMPLETE_CHAIN | CHAIN_QUALITY_BASIC_CONSTRAINTS | \
2519 CHAIN_QUALITY_TRUSTED_ROOT
2520
2521#define IS_TRUST_ERROR_SET(TrustStatus, bits) \
2522 (TrustStatus)->dwErrorStatus & (bits)
2523
2525{
2527
2528 if (IS_TRUST_ERROR_SET(&chain->context.TrustStatus,
2530 quality &= ~CHAIN_QUALITY_TRUSTED_ROOT;
2531 if (IS_TRUST_ERROR_SET(&chain->context.TrustStatus,
2533 quality &= ~CHAIN_QUALITY_BASIC_CONSTRAINTS;
2534 if (IS_TRUST_ERROR_SET(&chain->context.TrustStatus,
2536 quality &= ~CHAIN_QUALITY_COMPLETE_CHAIN;
2537 if (IS_TRUST_ERROR_SET(&chain->context.TrustStatus,
2539 quality &= ~CHAIN_QUALITY_TIME_VALID;
2540 if (IS_TRUST_ERROR_SET(&chain->context.TrustStatus,
2542 quality &= ~CHAIN_QUALITY_SIGNATURE_VALID;
2543 return quality;
2544}
2545
2546/* Chooses the highest quality chain among chain and its "lower quality"
2547 * alternate chains. Returns the highest quality chain, with all other
2548 * chains as lower quality chains of it.
2549 */
2552{
2553 DWORD i;
2554
2555 /* There are always only two chains being considered: chain, and an
2556 * alternate at chain->rgpLowerQualityChainContext[i]. If the alternate
2557 * has a higher quality than chain, the alternate gets assigned the lower
2558 * quality contexts, with chain taking the alternate's place among the
2559 * lower quality contexts.
2560 */
2561 for (i = 0; i < chain->context.cLowerQualityChainContext; i++)
2562 {
2563 CertificateChain *alternate =
2564 (CertificateChain*)chain->context.rgpLowerQualityChainContext[i];
2565
2567 {
2569 chain->context.cLowerQualityChainContext;
2571 chain->context.rgpLowerQualityChainContext;
2574 chain->context.cLowerQualityChainContext = 0;
2575 chain->context.rgpLowerQualityChainContext = NULL;
2576 chain = alternate;
2577 }
2578 }
2579 return chain;
2580}
2581
2583 const CertificateChain *alternate)
2584{
2585 BOOL ret;
2586
2587 if (chain->context.cLowerQualityChainContext)
2588 chain->context.rgpLowerQualityChainContext =
2589 CryptMemRealloc(chain->context.rgpLowerQualityChainContext,
2590 (chain->context.cLowerQualityChainContext + 1) *
2591 sizeof(PCCERT_CHAIN_CONTEXT));
2592 else
2593 chain->context.rgpLowerQualityChainContext =
2595 if (chain->context.rgpLowerQualityChainContext)
2596 {
2597 chain->context.rgpLowerQualityChainContext[
2598 chain->context.cLowerQualityChainContext++] =
2599 (PCCERT_CHAIN_CONTEXT)alternate;
2600 ret = TRUE;
2601 }
2602 else
2603 ret = FALSE;
2604 return ret;
2605}
2606
2609{
2610 DWORD j, iElement;
2612
2613 for (j = 0, iElement = 0; !element && j < chain->cChain; j++)
2614 {
2615 if (iElement + chain->rgpChain[j]->cElement < i)
2616 iElement += chain->rgpChain[j]->cElement;
2617 else
2618 element = chain->rgpChain[j]->rgpElement[i - iElement];
2619 }
2620 return element;
2621}
2622
2627
2629 LPFILETIME pTime, HCERTSTORE hAdditionalStore,
2630 const CERT_CHAIN_PARA *pChainPara, DWORD chainFlags)
2631{
2632 DWORD cContext;
2633
2634 if (chainFlags & CERT_CHAIN_REVOCATION_CHECK_END_CERT)
2635 cContext = 1;
2636 else if ((chainFlags & CERT_CHAIN_REVOCATION_CHECK_CHAIN) ||
2638 {
2639 DWORD i;
2640
2641 for (i = 0, cContext = 0; i < chain->cChain; i++)
2642 {
2643 if (i < chain->cChain - 1 ||
2645 cContext += chain->rgpChain[i]->cElement;
2646 else
2647 cContext += chain->rgpChain[i]->cElement - 1;
2648 }
2649 }
2650 else
2651 cContext = 0;
2652 if (cContext)
2653 {
2654 DWORD i, j, iContext, revocationFlags;
2655 CERT_REVOCATION_PARA revocationPara = { sizeof(revocationPara), 0 };
2656 CERT_REVOCATION_STATUS revocationStatus =
2657 { sizeof(revocationStatus), 0 };
2658 BOOL ret;
2659
2660 revocationFlags = CERT_VERIFY_REV_CHAIN_FLAG;
2662 revocationFlags |= CERT_VERIFY_CACHE_ONLY_BASED_REVOCATION;
2665 revocationPara.pftTimeToUse = pTime;
2666 if (hAdditionalStore)
2667 {
2668 revocationPara.cCertStore = 1;
2669 revocationPara.rgCertStore = &hAdditionalStore;
2670 revocationPara.hCrlStore = hAdditionalStore;
2671 }
2672 if (pChainPara->cbSize == sizeof(CERT_CHAIN_PARA))
2673 {
2674 revocationPara.dwUrlRetrievalTimeout =
2675 pChainPara->dwUrlRetrievalTimeout;
2676 revocationPara.fCheckFreshnessTime =
2677 pChainPara->fCheckRevocationFreshnessTime;
2678 revocationPara.dwFreshnessTime =
2679 pChainPara->dwRevocationFreshnessTime;
2680 }
2681 for (i = 0, iContext = 0; iContext < cContext && i < chain->cChain; i++)
2682 {
2683 for (j = 0; iContext < cContext &&
2684 j < chain->rgpChain[i]->cElement; j++, iContext++)
2685 {
2686 PCCERT_CONTEXT certToCheck =
2687 chain->rgpChain[i]->rgpElement[j]->pCertContext;
2688
2689 if (j < chain->rgpChain[i]->cElement - 1)
2690 revocationPara.pIssuerCert =
2691 chain->rgpChain[i]->rgpElement[j + 1]->pCertContext;
2692 else
2693 revocationPara.pIssuerCert = NULL;
2695 CERT_CONTEXT_REVOCATION_TYPE, 1, (void **)&certToCheck,
2696 revocationFlags, &revocationPara, &revocationStatus);
2697
2698 if (!ret && chainFlags & CERT_CHAIN_REVOCATION_CHECK_CHAIN
2699 && revocationStatus.dwError == CRYPT_E_NO_REVOCATION_CHECK && revocationPara.pIssuerCert == NULL)
2700 ret = TRUE;
2701
2702 if (!ret)
2703 {
2705 chain, iContext);
2706 DWORD error;
2707
2708 switch (revocationStatus.dwError)
2709 {
2713 /* If the revocation status is unknown, it's assumed
2714 * to be offline too.
2715 */
2718 break;
2721 break;
2722 case CRYPT_E_REVOKED:
2724 break;
2725 default:
2726 WARN("unmapped error %08lx\n", revocationStatus.dwError);
2727 error = 0;
2728 }
2729 if (element)
2730 {
2731 /* FIXME: set element's pRevocationInfo member */
2732 element->TrustStatus.dwErrorStatus |= error;
2733 }
2734 chain->TrustStatus.dwErrorStatus |= error;
2735 }
2736 }
2737 }
2738 }
2739}
2740
2742 const CERT_CHAIN_PARA *pChainPara)
2743{
2744 if (pChainPara->cbSize >= sizeof(CERT_CHAIN_PARA_NO_EXTRA_FIELDS) &&
2746 {
2747 PCCERT_CONTEXT endCert;
2749 BOOL validForUsage;
2750
2751 /* A chain, if created, always includes the end certificate */
2752 endCert = chain->rgpChain[0]->rgpElement[0]->pCertContext;
2753 /* The extended key usage extension specifies how a certificate's
2754 * public key may be used. From RFC 5280, section 4.2.1.12:
2755 * "This extension indicates one or more purposes for which the
2756 * certified public key may be used, in addition to or in place of the
2757 * basic purposes indicated in the key usage extension."
2758 * If the extension is present, it only satisfies the requested usage
2759 * if that usage is included in the extension:
2760 * "If the extension is present, then the certificate MUST only be used
2761 * for one of the purposes indicated."
2762 * There is also the special anyExtendedKeyUsage OID, but it doesn't
2763 * have to be respected:
2764 * "Applications that require the presence of a particular purpose
2765 * MAY reject certificates that include the anyExtendedKeyUsage OID
2766 * but not the particular OID expected for the application."
2767 * For now, I'm being more conservative and ignoring the presence of
2768 * the anyExtendedKeyUsage OID.
2769 */
2771 endCert->pCertInfo->cExtension, endCert->pCertInfo->rgExtension)))
2772 {
2773 const CERT_ENHKEY_USAGE *requestedUsage =
2774 &pChainPara->RequestedUsage.Usage;
2776 DWORD size;
2777
2779 X509_ENHANCED_KEY_USAGE, ext->Value.pbData, ext->Value.cbData,
2781 {
2782 if (pChainPara->RequestedUsage.dwType == USAGE_MATCH_TYPE_AND)
2783 {
2784 DWORD i, j;
2785
2786 /* For AND matches, all usages must be present */
2787 validForUsage = TRUE;
2788 for (i = 0; validForUsage &&
2789 i < requestedUsage->cUsageIdentifier; i++)
2790 {
2791 BOOL match = FALSE;
2792
2793 for (j = 0; !match && j < usage->cUsageIdentifier; j++)
2794 match = !strcmp(usage->rgpszUsageIdentifier[j],
2795 requestedUsage->rgpszUsageIdentifier[i]);
2796 if (!match)
2797 validForUsage = FALSE;
2798 }
2799 }
2800 else
2801 {
2802 DWORD i, j;
2803
2804 /* For OR matches, any matching usage suffices */
2805 validForUsage = FALSE;
2806 for (i = 0; !validForUsage &&
2807 i < requestedUsage->cUsageIdentifier; i++)
2808 {
2809 for (j = 0; !validForUsage &&
2810 j < usage->cUsageIdentifier; j++)
2811 validForUsage =
2812 !strcmp(usage->rgpszUsageIdentifier[j],
2813 requestedUsage->rgpszUsageIdentifier[i]);
2814 }
2815 }
2817 }
2818 else
2819 validForUsage = FALSE;
2820 }
2821 else
2822 {
2823 /* If the extension isn't present, any interpretation is valid:
2824 * "Certificate using applications MAY require that the extended
2825 * key usage extension be present and that a particular purpose
2826 * be indicated in order for the certificate to be acceptable to
2827 * that application."
2828 * Not all web sites include the extended key usage extension, so
2829 * accept chains without it.
2830 */
2831 TRACE_(chain)("requested usage from certificate with no usages\n");
2832 validForUsage = TRUE;
2833 }
2834 if (!validForUsage)
2835 {
2836 chain->TrustStatus.dwErrorStatus |=
2838 chain->rgpChain[0]->rgpElement[0]->TrustStatus.dwErrorStatus |=
2840 }
2841 }
2842 if (pChainPara->cbSize >= sizeof(CERT_CHAIN_PARA) &&
2843 pChainPara->RequestedIssuancePolicy.Usage.cUsageIdentifier)
2844 FIXME("unimplemented for RequestedIssuancePolicy\n");
2845}
2846
2847static void dump_usage_match(LPCSTR name, const CERT_USAGE_MATCH *usageMatch)
2848{
2849 if (usageMatch->Usage.cUsageIdentifier)
2850 {
2851 DWORD i;
2852
2853 TRACE_(chain)("%s: %s\n", name,
2854 usageMatch->dwType == USAGE_MATCH_TYPE_AND ? "AND" : "OR");
2855 for (i = 0; i < usageMatch->Usage.cUsageIdentifier; i++)
2856 TRACE_(chain)("%s\n", usageMatch->Usage.rgpszUsageIdentifier[i]);
2857 }
2858}
2859
2860static void dump_chain_para(const CERT_CHAIN_PARA *pChainPara)
2861{
2862 TRACE_(chain)("%ld\n", pChainPara->cbSize);
2863 if (pChainPara->cbSize >= sizeof(CERT_CHAIN_PARA_NO_EXTRA_FIELDS))
2864 dump_usage_match("RequestedUsage", &pChainPara->RequestedUsage);
2865 if (pChainPara->cbSize >= sizeof(CERT_CHAIN_PARA))
2866 {
2867 dump_usage_match("RequestedIssuancePolicy",
2868 &pChainPara->RequestedIssuancePolicy);
2869 TRACE_(chain)("%ld\n", pChainPara->dwUrlRetrievalTimeout);
2870 TRACE_(chain)("%d\n", pChainPara->fCheckRevocationFreshnessTime);
2871 TRACE_(chain)("%ld\n", pChainPara->dwRevocationFreshnessTime);
2872 }
2873}
2874
2876 PCCERT_CONTEXT pCertContext, LPFILETIME pTime, HCERTSTORE hAdditionalStore,
2878 PCCERT_CHAIN_CONTEXT* ppChainContext)
2879{
2880 CertificateChainEngine *engine;
2881 BOOL ret;
2883
2884 TRACE("(%p, %p, %s, %p, %p, %08lx, %p, %p)\n", hChainEngine, pCertContext,
2885 debugstr_filetime(pTime), hAdditionalStore, pChainPara, dwFlags,
2886 pvReserved, ppChainContext);
2887
2888 engine = get_chain_engine(hChainEngine, TRUE);
2889 if (!engine)
2890 return FALSE;
2891
2892 if (ppChainContext)
2893 *ppChainContext = NULL;
2894 if (!pChainPara)
2895 {
2897 return FALSE;
2898 }
2899 if (!pCertContext->pCertInfo->SignatureAlgorithm.pszObjId)
2900 {
2902 return FALSE;
2903 }
2904
2905 if (TRACE_ON(chain))
2906 dump_chain_para(pChainPara);
2907 /* FIXME: what about HCCE_LOCAL_MACHINE? */
2908 ret = CRYPT_BuildCandidateChainFromCert(engine, pCertContext, pTime,
2909 hAdditionalStore, dwFlags, &chain);
2910 if (ret)
2911 {
2912 CertificateChain *alternate = NULL;
2913 PCERT_CHAIN_CONTEXT pChain;
2914
2915 do {
2916 alternate = CRYPT_BuildAlternateContextFromChain(engine,
2917 pTime, hAdditionalStore, dwFlags, chain);
2918
2919 /* Alternate contexts are added as "lower quality" contexts of
2920 * chain, to avoid loops in alternate chain creation.
2921 * The highest-quality chain is chosen at the end.
2922 */
2923 if (alternate)
2925 } while (ret && alternate);
2929 pChain = (PCERT_CHAIN_CONTEXT)chain;
2930 CRYPT_VerifyChainRevocation(pChain, pTime, hAdditionalStore,
2931 pChainPara, dwFlags);
2932 CRYPT_CheckUsages(pChain, pChainPara);
2933 TRACE_(chain)("error status: %08lx\n",
2934 pChain->TrustStatus.dwErrorStatus);
2935 if (ppChainContext)
2936 *ppChainContext = pChain;
2937 else
2939 }
2940 TRACE("returning %d\n", ret);
2941 return ret;
2942}
2943
2945 PCCERT_CHAIN_CONTEXT pChainContext)
2946{
2947 CertificateChain *chain = (CertificateChain*)pChainContext;
2948
2949 TRACE("(%p)\n", pChainContext);
2950
2951 if (chain)
2953 return pChainContext;
2954}
2955
2957{
2958 CertificateChain *chain = (CertificateChain*)pChainContext;
2959
2960 TRACE("(%p)\n", pChainContext);
2961
2962 if (chain)
2963 {
2964 if (InterlockedDecrement(&chain->ref) == 0)
2966 }
2967}
2968
2970 DWORD certEncodingType, DWORD findFlags, DWORD findType,
2971 const void *findPara, PCCERT_CHAIN_CONTEXT prevChainContext)
2972{
2973 FIXME("(%p, %08lx, %08lx, %ld, %p, %p): stub\n", store, certEncodingType,
2974 findFlags, findType, findPara, prevChainContext);
2975 return NULL;
2976}
2977
2979 LONG *iChain, LONG *iElement)
2980{
2981 DWORD i, j;
2982
2983 for (i = 0; i < chain->cChain; i++)
2984 for (j = 0; j < chain->rgpChain[i]->cElement; j++)
2985 if (chain->rgpChain[i]->rgpElement[j]->TrustStatus.dwErrorStatus &
2986 error)
2987 {
2988 *iChain = i;
2989 *iElement = j;
2990 return;
2991 }
2992}
2993
2995 PCCERT_CHAIN_CONTEXT pChainContext, PCERT_CHAIN_POLICY_PARA pPolicyPara,
2996 PCERT_CHAIN_POLICY_STATUS pPolicyStatus)
2997{
2998 DWORD checks = 0;
2999
3000 if (pPolicyPara)
3001 checks = pPolicyPara->dwFlags;
3002 pPolicyStatus->lChainIndex = pPolicyStatus->lElementIndex = -1;
3003 pPolicyStatus->dwError = NO_ERROR;
3004 if (pChainContext->TrustStatus.dwErrorStatus &
3006 {
3007 pPolicyStatus->dwError = TRUST_E_CERT_SIGNATURE;
3008 find_element_with_error(pChainContext,
3010 &pPolicyStatus->lElementIndex);
3011 }
3012 else if (pChainContext->TrustStatus.dwErrorStatus & CERT_TRUST_IS_CYCLIC)
3013 {
3014 pPolicyStatus->dwError = CERT_E_CHAINING;
3016 &pPolicyStatus->lChainIndex, &pPolicyStatus->lElementIndex);
3017 /* For a cyclic chain, which element is a cycle isn't meaningful */
3018 pPolicyStatus->lElementIndex = -1;
3019 }
3020 if (!pPolicyStatus->dwError &&
3023 {
3024 pPolicyStatus->dwError = CERT_E_UNTRUSTEDROOT;
3025 find_element_with_error(pChainContext,
3027 &pPolicyStatus->lElementIndex);
3028 }
3029 if (!pPolicyStatus->dwError &&
3032 {
3033 pPolicyStatus->dwError = CERT_E_EXPIRED;
3034 find_element_with_error(pChainContext,
3036 &pPolicyStatus->lElementIndex);
3037 }
3038 if (!pPolicyStatus->dwError &&
3039 pChainContext->TrustStatus.dwErrorStatus &
3042 {
3043 pPolicyStatus->dwError = CERT_E_WRONG_USAGE;
3044 find_element_with_error(pChainContext,
3046 &pPolicyStatus->lElementIndex);
3047 }
3048 if (!pPolicyStatus->dwError &&
3049 pChainContext->TrustStatus.dwErrorStatus &
3052 {
3053 pPolicyStatus->dwError = CERT_E_CRITICAL;
3054 find_element_with_error(pChainContext,
3056 &pPolicyStatus->lElementIndex);
3057 }
3058 return TRUE;
3059}
3060
30620x30,0x47,0x02,0x40,0x81,0x55,0x22,0xb9,0x8a,0xa4,0x6f,0xed,0xd6,0xe7,0xd9,
30630x66,0x0f,0x55,0xbc,0xd7,0xcd,0xd5,0xbc,0x4e,0x40,0x02,0x21,0xa2,0xb1,0xf7,
30640x87,0x30,0x85,0x5e,0xd2,0xf2,0x44,0xb9,0xdc,0x9b,0x75,0xb6,0xfb,0x46,0x5f,
30650x42,0xb6,0x9d,0x23,0x36,0x0b,0xde,0x54,0x0f,0xcd,0xbd,0x1f,0x99,0x2a,0x10,
30660x58,0x11,0xcb,0x40,0xcb,0xb5,0xa7,0x41,0x02,0x03,0x01,0x00,0x01 };
30680x30,0x47,0x02,0x40,0x9c,0x50,0x05,0x1d,0xe2,0x0e,0x4c,0x53,0xd8,0xd9,0xb5,
30690xe5,0xfd,0xe9,0xe3,0xad,0x83,0x4b,0x80,0x08,0xd9,0xdc,0xe8,0xe8,0x35,0xf8,
30700x11,0xf1,0xe9,0x9b,0x03,0x7a,0x65,0x64,0x76,0x35,0xce,0x38,0x2c,0xf2,0xb6,
30710x71,0x9e,0x06,0xd9,0xbf,0xbb,0x31,0x69,0xa3,0xf6,0x30,0xa0,0x78,0x7b,0x18,
30720xdd,0x50,0x4d,0x79,0x1e,0xeb,0x61,0xc1,0x02,0x03,0x01,0x00,0x01 };
3073
3076{
3077 if (extraPara)
3078 {
3079 TRACE_(chain)("cbSize = %ld\n", extraPara->cbSize);
3080 TRACE_(chain)("dwRegPolicySettings = %08lx\n",
3081 extraPara->dwRegPolicySettings);
3082 TRACE_(chain)("pSignerInfo = %p\n", extraPara->pSignerInfo);
3083 }
3084}
3085
3087 PCCERT_CHAIN_CONTEXT pChainContext, PCERT_CHAIN_POLICY_PARA pPolicyPara,
3088 PCERT_CHAIN_POLICY_STATUS pPolicyStatus)
3089{
3090 BOOL ret = verify_base_policy(szPolicyOID, pChainContext, pPolicyPara,
3091 pPolicyStatus);
3093
3094 if (pPolicyPara)
3095 extraPara = pPolicyPara->pvExtraPolicyPara;
3096 if (TRACE_ON(chain))
3098 if (ret && pPolicyStatus->dwError == CERT_E_UNTRUSTEDROOT)
3099 {
3100 CERT_PUBLIC_KEY_INFO msPubKey = { { 0 } };
3101 BOOL isMSTestRoot = FALSE;
3102 PCCERT_CONTEXT failingCert =
3103 pChainContext->rgpChain[pPolicyStatus->lChainIndex]->
3104 rgpElement[pPolicyStatus->lElementIndex]->pCertContext;
3105 DWORD i;
3106 CRYPT_DATA_BLOB keyBlobs[] = {
3107 { sizeof(msTestPubKey1), msTestPubKey1 },
3108 { sizeof(msTestPubKey2), msTestPubKey2 },
3109 };
3110
3111 /* Check whether the root is an MS test root */
3112 for (i = 0; !isMSTestRoot && i < ARRAY_SIZE(keyBlobs); i++)
3113 {
3114 msPubKey.PublicKey.cbData = keyBlobs[i].cbData;
3115 msPubKey.PublicKey.pbData = keyBlobs[i].pbData;
3118 &failingCert->pCertInfo->SubjectPublicKeyInfo, &msPubKey))
3119 isMSTestRoot = TRUE;
3120 }
3121 if (isMSTestRoot)
3122 pPolicyStatus->dwError = CERT_E_UNTRUSTEDTESTROOT;
3123 }
3124 return ret;
3125}
3126
3128 PCCERT_CHAIN_CONTEXT pChainContext, PCERT_CHAIN_POLICY_PARA pPolicyPara,
3129 PCERT_CHAIN_POLICY_STATUS pPolicyStatus)
3130{
3131 pPolicyStatus->lChainIndex = pPolicyStatus->lElementIndex = -1;
3132 if (pChainContext->TrustStatus.dwErrorStatus &
3134 {
3135 pPolicyStatus->dwError = TRUST_E_BASIC_CONSTRAINTS;
3136 find_element_with_error(pChainContext,
3138 &pPolicyStatus->lElementIndex);
3139 }
3140 else
3141 pPolicyStatus->dwError = NO_ERROR;
3142 return TRUE;
3143}
3144
3147{
3148 BOOL matches = FALSE;
3150 DWORD size;
3151
3153 /* This could be spoofed by the embedded NULL vulnerability, since the
3154 * returned CERT_ALT_NAME_INFO doesn't have a way to indicate the
3155 * encoded length of a name. Fortunately CryptDecodeObjectEx fails if
3156 * the encoded form of the name contains a NULL.
3157 */
3159 ext->Value.pbData, ext->Value.cbData,
3161 &subjectName, &size))
3162 {
3163 DWORD i;
3164
3165 /* RFC 5280 states that multiple instances of each name type may exist,
3166 * in section 4.2.1.6:
3167 * "Multiple name forms, and multiple instances of each name form,
3168 * MAY be included."
3169 * It doesn't specify the behavior in such cases, but both RFC 2818
3170 * and RFC 2595 explicitly accept a certificate if any name matches.
3171 */
3172 for (i = 0; !matches && i < subjectName->cAltEntry; i++)
3173 {
3174 if (subjectName->rgAltEntry[i].dwAltNameChoice ==
3176 {
3177 TRACE_(chain)("dNSName: %s\n", debugstr_w(
3178 subjectName->rgAltEntry[i].pwszDNSName));
3179 if (subjectName->rgAltEntry[i].pwszDNSName[0] == '*')
3180 {
3181 LPCWSTR server_name_dot;
3182
3183 /* Matching a wildcard: a wildcard matches a single name
3184 * component, which is terminated by a dot. RFC 1034
3185 * doesn't define whether multiple wildcards are allowed,
3186 * but I will assume that they are not until proven
3187 * otherwise. RFC 1034 also states that 'the "*" label
3188 * always matches at least one whole label and sometimes
3189 * more, but always whole labels.' Native crypt32 does not
3190 * match more than one label with a wildcard, so I do the
3191 * same here. Thus, a wildcard only accepts the first
3192 * label, then requires an exact match of the remaining
3193 * string.
3194 */
3195 server_name_dot = wcschr(server_name, '.');
3196 if (server_name_dot)
3197 {
3198 if (!wcsicmp(server_name_dot,
3199 subjectName->rgAltEntry[i].pwszDNSName + 1))
3200 matches = TRUE;
3201 }
3202 }
3203 else if (!wcsicmp(server_name,
3204 subjectName->rgAltEntry[i].pwszDNSName))
3205 matches = TRUE;
3206 }
3207 }
3209 }
3210 return matches;
3211}
3212
3214 const WCHAR *component, size_t len)
3215{
3216 DWORD i, j;
3217
3218 for (i = 0; i < name->cRDN; i++)
3219 for (j = 0; j < name->rgRDN[i].cRDNAttr; j++)
3221 name->rgRDN[i].rgRDNAttr[j].pszObjId))
3222 {
3223 const CERT_RDN_ATTR *attr;
3224
3225 attr = &name->rgRDN[i].rgRDNAttr[j];
3226 /* Compare with wcsnicmp rather than wcsicmp in order to avoid
3227 * a match with a string with an embedded NULL. The component
3228 * must match one domain component attribute's entire string
3229 * value with a case-insensitive match.
3230 */
3231 if ((len == attr->Value.cbData / sizeof(WCHAR)) &&
3232 !wcsnicmp(component, (LPCWSTR)attr->Value.pbData, len))
3233 return TRUE;
3234 }
3235 return FALSE;
3236}
3237
3238static BOOL match_domain_component(LPCWSTR allowed_component, DWORD allowed_len,
3239 LPCWSTR server_component, DWORD server_len, BOOL allow_wildcards,
3240 BOOL *see_wildcard)
3241{
3242 LPCWSTR allowed_ptr, server_ptr;
3243 BOOL matches = TRUE;
3244
3245 *see_wildcard = FALSE;
3246
3247 if (server_len < allowed_len)
3248 {
3249 WARN_(chain)("domain component %s too short for %s\n",
3250 debugstr_wn(server_component, server_len),
3251 debugstr_wn(allowed_component, allowed_len));
3252 /* A domain component can't contain a wildcard character, so a domain
3253 * component shorter than the allowed string can't produce a match.
3254 */
3255 return FALSE;
3256 }
3257 for (allowed_ptr = allowed_component, server_ptr = server_component;
3258 matches && allowed_ptr - allowed_component < allowed_len;
3259 allowed_ptr++, server_ptr++)
3260 {
3261 if (*allowed_ptr == '*')
3262 {
3263 if (allowed_ptr - allowed_component < allowed_len - 1)
3264 {
3265 WARN_(chain)("non-wildcard characters after wildcard not supported\n");
3266 matches = FALSE;
3267 }
3268 else if (!allow_wildcards)
3269 {
3270 WARN_(chain)("wildcard after non-wildcard component\n");
3271 matches = FALSE;
3272 }
3273 else
3274 {
3275 /* the preceding characters must have matched, so the rest of
3276 * the component also matches.
3277 */
3278 *see_wildcard = TRUE;
3279 break;
3280 }
3281 }
3282 if (matches)
3283 matches = towlower(*allowed_ptr) == towlower(*server_ptr);
3284 }
3285 if (matches && server_ptr - server_component < server_len)
3286 {
3287 /* If there are unmatched characters in the server domain component,
3288 * the server domain only matches if the allowed string ended in a '*'.
3289 */
3290 matches = *allowed_ptr == '*';
3291 }
3292 return matches;
3293}
3294
3296{
3297 LPCWSTR allowed = (LPCWSTR)nameAttr->Value.pbData;
3298 LPCWSTR allowed_component = allowed;
3299 DWORD allowed_len = nameAttr->Value.cbData / sizeof(WCHAR);
3300 LPCWSTR server_component = server_name;
3301 DWORD server_len = lstrlenW(server_name);
3302 BOOL matches = TRUE, allow_wildcards = TRUE;
3303
3304 TRACE_(chain)("CN = %s\n", debugstr_wn(allowed_component, allowed_len));
3305
3306 /* Remove trailing NULLs from the allowed name; while they shouldn't appear
3307 * in a certificate in the first place, they sometimes do, and they should
3308 * be ignored.
3309 */
3310 while (allowed_len && allowed_component[allowed_len - 1] == 0)
3311 allowed_len--;
3312
3313 /* From RFC 2818 (HTTP over TLS), section 3.1:
3314 * "Names may contain the wildcard character * which is considered to match
3315 * any single domain name component or component fragment. E.g.,
3316 * *.a.com matches foo.a.com but not bar.foo.a.com. f*.com matches foo.com
3317 * but not bar.com."
3318 *
3319 * And from RFC 2595 (Using TLS with IMAP, POP3 and ACAP), section 2.4:
3320 * "A "*" wildcard character MAY be used as the left-most name component in
3321 * the certificate. For example, *.example.com would match a.example.com,
3322 * foo.example.com, etc. but would not match example.com."
3323 *
3324 * There are other protocols which use TLS, and none of them is
3325 * authoritative. This accepts certificates in common usage, e.g.
3326 * *.domain.com matches www.domain.com but not domain.com, and
3327 * www*.domain.com matches www1.domain.com but not mail.domain.com.
3328 */
3329 do {
3330 LPCWSTR allowed_dot, server_dot;
3331
3332 allowed_dot = wmemchr(allowed_component, '.',
3333 allowed_len - (allowed_component - allowed));
3334 server_dot = wmemchr(server_component, '.',
3335 server_len - (server_component - server_name));
3336 /* The number of components must match */
3337 if ((!allowed_dot && server_dot) || (allowed_dot && !server_dot))
3338 {
3339 if (!allowed_dot)
3340 WARN_(chain)("%s: too many components for CN=%s\n",
3341 debugstr_w(server_name), debugstr_wn(allowed, allowed_len));
3342 else
3343 WARN_(chain)("%s: not enough components for CN=%s\n",
3344 debugstr_w(server_name), debugstr_wn(allowed, allowed_len));
3345 matches = FALSE;
3346 }
3347 else
3348 {
3349 LPCWSTR allowed_end, server_end;
3350 BOOL has_wildcard;
3351
3352 allowed_end = allowed_dot ? allowed_dot : allowed + allowed_len;
3353 server_end = server_dot ? server_dot : server_name + server_len;
3354 matches = match_domain_component(allowed_component,
3355 allowed_end - allowed_component, server_component,
3356 server_end - server_component, allow_wildcards, &has_wildcard);
3357 /* Once a non-wildcard component is seen, no wildcard components
3358 * may follow
3359 */
3360 if (!has_wildcard)
3361 allow_wildcards = FALSE;
3362 if (matches)
3363 {
3364 allowed_component = allowed_dot ? allowed_dot + 1 : allowed_end;
3365 server_component = server_dot ? server_dot + 1 : server_end;
3366 }
3367 }
3368 } while (matches && allowed_component &&
3369 allowed_component - allowed < allowed_len &&
3370 server_component && server_component - server_name < server_len);
3371 TRACE_(chain)("returning %d\n", matches);
3372 return matches;
3373}
3374
3376{
3377 BOOL matches = FALSE;
3379 DWORD size;
3380
3383 cert->pCertInfo->Subject.pbData, cert->pCertInfo->Subject.cbData,
3385 &name, &size))
3386 {
3387 /* If the subject distinguished name contains any name components,
3388 * make sure all of them are present.
3389 */
3391 {
3393
3394 do {
3395 LPCWSTR dot = wcschr(ptr, '.'), end;
3396 /* 254 is the maximum DNS label length, see RFC 1035 */
3397 size_t len;
3398
3399 end = dot ? dot : ptr + lstrlenW(ptr);
3400 len = end - ptr;
3401 if (len >= 255)
3402 {
3403 WARN_(chain)("domain component %s too long\n",
3404 debugstr_wn(ptr, len));
3405 matches = FALSE;
3406 }
3408
3409 ptr = dot ? dot + 1 : end;
3410 } while (matches && ptr && *ptr);
3411 }
3412 else
3413 {
3414 DWORD i, j;
3415
3416 /* If the certificate isn't using a DN attribute in the name, make
3417 * make sure at least one common name matches. From RFC 2818,
3418 * section 3.1:
3419 * "If more than one identity of a given type is present in the
3420 * certificate (e.g., more than one dNSName name, a match in any
3421 * one of the set is considered acceptable.)"
3422 */
3423 for (i = 0; !matches && i < name->cRDN; i++)
3424 for (j = 0; !matches && j < name->rgRDN[i].cRDNAttr; j++)
3425 {
3426 PCERT_RDN_ATTR attr = &name->rgRDN[i].rgRDNAttr[j];
3427
3428 if (attr->pszObjId && !strcmp(szOID_COMMON_NAME,
3429 attr->pszObjId))
3431 }
3432 }
3433 LocalFree(name);
3434 }
3435 return matches;
3436}
3437
3439{
3440 if (sslPara)
3441 {
3442 TRACE_(chain)("cbSize = %ld\n", sslPara->cbSize);
3443 TRACE_(chain)("dwAuthType = %ld\n", sslPara->dwAuthType);
3444 TRACE_(chain)("fdwChecks = %08lx\n", sslPara->fdwChecks);
3445 TRACE_(chain)("pwszServerName = %s\n",
3446 debugstr_w(sslPara->pwszServerName));
3447 }
3448}
3449
3451 PCCERT_CHAIN_CONTEXT pChainContext, PCERT_CHAIN_POLICY_PARA pPolicyPara,
3452 PCERT_CHAIN_POLICY_STATUS pPolicyStatus)
3453{
3454 HTTPSPolicyCallbackData *sslPara = NULL;
3455 DWORD checks = 0, baseChecks = 0;
3456
3457 if (pPolicyPara)
3458 {
3459 baseChecks = pPolicyPara->dwFlags;
3460 sslPara = pPolicyPara->pvExtraPolicyPara;
3461 }
3462 if (TRACE_ON(chain))
3464 if (sslPara && sslPara->cbSize >= sizeof(HTTPSPolicyCallbackData))
3465 checks = sslPara->fdwChecks;
3466 pPolicyStatus->lChainIndex = pPolicyStatus->lElementIndex = -1;
3467 if (pChainContext->TrustStatus.dwErrorStatus &
3469 {
3470 pPolicyStatus->dwError = TRUST_E_CERT_SIGNATURE;
3471 find_element_with_error(pChainContext,
3473 &pPolicyStatus->lElementIndex);
3474 }
3475 else if (pChainContext->TrustStatus.dwErrorStatus &
3477 !(checks & SECURITY_FLAG_IGNORE_UNKNOWN_CA) &&
3479 {
3480 pPolicyStatus->dwError = CERT_E_UNTRUSTEDROOT;
3481 find_element_with_error(pChainContext,
3483 &pPolicyStatus->lElementIndex);
3484 }
3485 else if (pChainContext->TrustStatus.dwErrorStatus & CERT_TRUST_IS_CYCLIC)
3486 {
3487 pPolicyStatus->dwError = CERT_E_UNTRUSTEDROOT;
3488 find_element_with_error(pChainContext,
3489 CERT_TRUST_IS_CYCLIC, &pPolicyStatus->lChainIndex,
3490 &pPolicyStatus->lElementIndex);
3491 /* For a cyclic chain, which element is a cycle isn't meaningful */
3492 pPolicyStatus->lElementIndex = -1;
3493 }
3494 else if (pChainContext->TrustStatus.dwErrorStatus &
3498 {
3499 pPolicyStatus->dwError = CERT_E_EXPIRED;
3500 find_element_with_error(pChainContext,
3502 &pPolicyStatus->lElementIndex);
3503 }
3504 else if (pChainContext->TrustStatus.dwErrorStatus &
3507 {
3508 pPolicyStatus->dwError = CERT_E_WRONG_USAGE;
3509 find_element_with_error(pChainContext,
3511 &pPolicyStatus->lElementIndex);
3512 }
3513 else if (pChainContext->TrustStatus.dwErrorStatus &
3515 {
3516 pPolicyStatus->dwError = CERT_E_REVOKED;
3517 find_element_with_error(pChainContext,
3518 CERT_TRUST_IS_REVOKED, &pPolicyStatus->lChainIndex,
3519 &pPolicyStatus->lElementIndex);
3520 }
3521 else if (pChainContext->TrustStatus.dwErrorStatus &
3524 {
3525 pPolicyStatus->dwError = CERT_E_REVOCATION_FAILURE;
3526 find_element_with_error(pChainContext,
3528 &pPolicyStatus->lElementIndex);
3529 }
3530 else if (pChainContext->TrustStatus.dwErrorStatus &
3532 {
3533 pPolicyStatus->dwError = CERT_E_CRITICAL;
3534 find_element_with_error(pChainContext,
3536 &pPolicyStatus->lElementIndex);
3537 }
3538 else
3539 pPolicyStatus->dwError = NO_ERROR;
3540 /* We only need bother checking whether the name in the end certificate
3541 * matches if the chain is otherwise okay.
3542 */
3543 if (!pPolicyStatus->dwError && pPolicyPara &&
3544 pPolicyPara->cbSize >= sizeof(CERT_CHAIN_POLICY_PARA))
3545 {
3546 if (sslPara && sslPara->cbSize >= sizeof(HTTPSPolicyCallbackData))
3547 {
3548 if (sslPara->dwAuthType == AUTHTYPE_SERVER &&
3549 sslPara->pwszServerName &&
3551 {
3553 PCERT_EXTENSION altNameExt;
3554 BOOL matches;
3555
3556 cert = pChainContext->rgpChain[0]->rgpElement[0]->pCertContext;
3557 altNameExt = get_subject_alt_name_ext(cert->pCertInfo);
3558 /* If the alternate name extension exists, the name it contains
3559 * is bound to the certificate, so make sure the name matches
3560 * it. Otherwise, look for the server name in the subject
3561 * distinguished name. RFC5280, section 4.2.1.6:
3562 * "Whenever such identities are to be bound into a
3563 * certificate, the subject alternative name (or issuer
3564 * alternative name) extension MUST be used; however, a DNS
3565 * name MAY also be represented in the subject field using the
3566 * domainComponent attribute."
3567 */
3568 if (altNameExt)
3570 sslPara->pwszServerName);
3571 else
3573 sslPara->pwszServerName);
3574 if (!matches)
3575 {
3576 pPolicyStatus->dwError = CERT_E_CN_NO_MATCH;
3577 pPolicyStatus->lChainIndex = 0;
3578 pPolicyStatus->lElementIndex = 0;
3579 }
3580 }
3581 }
3582 }
3583 return TRUE;
3584}
3585
3586static BYTE msPubKey1[] = {
35870x30,0x82,0x01,0x0a,0x02,0x82,0x01,0x01,0x00,0xdf,0x08,0xba,0xe3,0x3f,0x6e,
35880x64,0x9b,0xf5,0x89,0xaf,0x28,0x96,0x4a,0x07,0x8f,0x1b,0x2e,0x8b,0x3e,0x1d,
35890xfc,0xb8,0x80,0x69,0xa3,0xa1,0xce,0xdb,0xdf,0xb0,0x8e,0x6c,0x89,0x76,0x29,
35900x4f,0xca,0x60,0x35,0x39,0xad,0x72,0x32,0xe0,0x0b,0xae,0x29,0x3d,0x4c,0x16,
35910xd9,0x4b,0x3c,0x9d,0xda,0xc5,0xd3,0xd1,0x09,0xc9,0x2c,0x6f,0xa6,0xc2,0x60,
35920x53,0x45,0xdd,0x4b,0xd1,0x55,0xcd,0x03,0x1c,0xd2,0x59,0x56,0x24,0xf3,0xe5,
35930x78,0xd8,0x07,0xcc,0xd8,0xb3,0x1f,0x90,0x3f,0xc0,0x1a,0x71,0x50,0x1d,0x2d,
35940xa7,0x12,0x08,0x6d,0x7c,0xb0,0x86,0x6c,0xc7,0xba,0x85,0x32,0x07,0xe1,0x61,
35950x6f,0xaf,0x03,0xc5,0x6d,0xe5,0xd6,0xa1,0x8f,0x36,0xf6,0xc1,0x0b,0xd1,0x3e,
35960x69,0x97,0x48,0x72,0xc9,0x7f,0xa4,0xc8,0xc2,0x4a,0x4c,0x7e,0xa1,0xd1,0x94,
35970xa6,0xd7,0xdc,0xeb,0x05,0x46,0x2e,0xb8,0x18,0xb4,0x57,0x1d,0x86,0x49,0xdb,
35980x69,0x4a,0x2c,0x21,0xf5,0x5e,0x0f,0x54,0x2d,0x5a,0x43,0xa9,0x7a,0x7e,0x6a,
35990x8e,0x50,0x4d,0x25,0x57,0xa1,0xbf,0x1b,0x15,0x05,0x43,0x7b,0x2c,0x05,0x8d,
36000xbd,0x3d,0x03,0x8c,0x93,0x22,0x7d,0x63,0xea,0x0a,0x57,0x05,0x06,0x0a,0xdb,
36010x61,0x98,0x65,0x2d,0x47,0x49,0xa8,0xe7,0xe6,0x56,0x75,0x5c,0xb8,0x64,0x08,
36020x63,0xa9,0x30,0x40,0x66,0xb2,0xf9,0xb6,0xe3,0x34,0xe8,0x67,0x30,0xe1,0x43,
36030x0b,0x87,0xff,0xc9,0xbe,0x72,0x10,0x5e,0x23,0xf0,0x9b,0xa7,0x48,0x65,0xbf,
36040x09,0x88,0x7b,0xcd,0x72,0xbc,0x2e,0x79,0x9b,0x7b,0x02,0x03,0x01,0x00,0x01 };
3605static BYTE msPubKey2[] = {
36060x30,0x82,0x01,0x0a,0x02,0x82,0x01,0x01,0x00,0xa9,0x02,0xbd,0xc1,0x70,0xe6,
36070x3b,0xf2,0x4e,0x1b,0x28,0x9f,0x97,0x78,0x5e,0x30,0xea,0xa2,0xa9,0x8d,0x25,
36080x5f,0xf8,0xfe,0x95,0x4c,0xa3,0xb7,0xfe,0x9d,0xa2,0x20,0x3e,0x7c,0x51,0xa2,
36090x9b,0xa2,0x8f,0x60,0x32,0x6b,0xd1,0x42,0x64,0x79,0xee,0xac,0x76,0xc9,0x54,
36100xda,0xf2,0xeb,0x9c,0x86,0x1c,0x8f,0x9f,0x84,0x66,0xb3,0xc5,0x6b,0x7a,0x62,
36110x23,0xd6,0x1d,0x3c,0xde,0x0f,0x01,0x92,0xe8,0x96,0xc4,0xbf,0x2d,0x66,0x9a,
36120x9a,0x68,0x26,0x99,0xd0,0x3a,0x2c,0xbf,0x0c,0xb5,0x58,0x26,0xc1,0x46,0xe7,
36130x0a,0x3e,0x38,0x96,0x2c,0xa9,0x28,0x39,0xa8,0xec,0x49,0x83,0x42,0xe3,0x84,
36140x0f,0xbb,0x9a,0x6c,0x55,0x61,0xac,0x82,0x7c,0xa1,0x60,0x2d,0x77,0x4c,0xe9,
36150x99,0xb4,0x64,0x3b,0x9a,0x50,0x1c,0x31,0x08,0x24,0x14,0x9f,0xa9,0xe7,0x91,
36160x2b,0x18,0xe6,0x3d,0x98,0x63,0x14,0x60,0x58,0x05,0x65,0x9f,0x1d,0x37,0x52,
36170x87,0xf7,0xa7,0xef,0x94,0x02,0xc6,0x1b,0xd3,0xbf,0x55,0x45,0xb3,0x89,0x80,
36180xbf,0x3a,0xec,0x54,0x94,0x4e,0xae,0xfd,0xa7,0x7a,0x6d,0x74,0x4e,0xaf,0x18,
36190xcc,0x96,0x09,0x28,0x21,0x00,0x57,0x90,0x60,0x69,0x37,0xbb,0x4b,0x12,0x07,
36200x3c,0x56,0xff,0x5b,0xfb,0xa4,0x66,0x0a,0x08,0xa6,0xd2,0x81,0x56,0x57,0xef,
36210xb6,0x3b,0x5e,0x16,0x81,0x77,0x04,0xda,0xf6,0xbe,0xae,0x80,0x95,0xfe,0xb0,
36220xcd,0x7f,0xd6,0xa7,0x1a,0x72,0x5c,0x3c,0xca,0xbc,0xf0,0x08,0xa3,0x22,0x30,
36230xb3,0x06,0x85,0xc9,0xb3,0x20,0x77,0x13,0x85,0xdf,0x02,0x03,0x01,0x00,0x01 };
3624static BYTE msPubKey3[] = {
36250x30,0x82,0x02,0x0a,0x02,0x82,0x02,0x01,0x00,0xf3,0x5d,0xfa,0x80,0x67,0xd4,
36260x5a,0xa7,0xa9,0x0c,0x2c,0x90,0x20,0xd0,0x35,0x08,0x3c,0x75,0x84,0xcd,0xb7,
36270x07,0x89,0x9c,0x89,0xda,0xde,0xce,0xc3,0x60,0xfa,0x91,0x68,0x5a,0x9e,0x94,
36280x71,0x29,0x18,0x76,0x7c,0xc2,0xe0,0xc8,0x25,0x76,0x94,0x0e,0x58,0xfa,0x04,
36290x34,0x36,0xe6,0xdf,0xaf,0xf7,0x80,0xba,0xe9,0x58,0x0b,0x2b,0x93,0xe5,0x9d,
36300x05,0xe3,0x77,0x22,0x91,0xf7,0x34,0x64,0x3c,0x22,0x91,0x1d,0x5e,0xe1,0x09,
36310x90,0xbc,0x14,0xfe,0xfc,0x75,0x58,0x19,0xe1,0x79,0xb7,0x07,0x92,0xa3,0xae,
36320x88,0x59,0x08,0xd8,0x9f,0x07,0xca,0x03,0x58,0xfc,0x68,0x29,0x6d,0x32,0xd7,
36330xd2,0xa8,0xcb,0x4b,0xfc,0xe1,0x0b,0x48,0x32,0x4f,0xe6,0xeb,0xb8,0xad,0x4f,
36340xe4,0x5c,0x6f,0x13,0x94,0x99,0xdb,0x95,0xd5,0x75,0xdb,0xa8,0x1a,0xb7,0x94,
36350x91,0xb4,0x77,0x5b,0xf5,0x48,0x0c,0x8f,0x6a,0x79,0x7d,0x14,0x70,0x04,0x7d,
36360x6d,0xaf,0x90,0xf5,0xda,0x70,0xd8,0x47,0xb7,0xbf,0x9b,0x2f,0x6c,0xe7,0x05,
36370xb7,0xe1,0x11,0x60,0xac,0x79,0x91,0x14,0x7c,0xc5,0xd6,0xa6,0xe4,0xe1,0x7e,
36380xd5,0xc3,0x7e,0xe5,0x92,0xd2,0x3c,0x00,0xb5,0x36,0x82,0xde,0x79,0xe1,0x6d,
36390xf3,0xb5,0x6e,0xf8,0x9f,0x33,0xc9,0xcb,0x52,0x7d,0x73,0x98,0x36,0xdb,0x8b,
36400xa1,0x6b,0xa2,0x95,0x97,0x9b,0xa3,0xde,0xc2,0x4d,0x26,0xff,0x06,0x96,0x67,
36410x25,0x06,0xc8,0xe7,0xac,0xe4,0xee,0x12,0x33,0x95,0x31,0x99,0xc8,0x35,0x08,
36420x4e,0x34,0xca,0x79,0x53,0xd5,0xb5,0xbe,0x63,0x32,0x59,0x40,0x36,0xc0,0xa5,
36430x4e,0x04,0x4d,0x3d,0xdb,0x5b,0x07,0x33,0xe4,0x58,0xbf,0xef,0x3f,0x53,0x64,
36440xd8,0x42,0x59,0x35,0x57,0xfd,0x0f,0x45,0x7c,0x24,0x04,0x4d,0x9e,0xd6,0x38,
36450x74,0x11,0x97,0x22,0x90,0xce,0x68,0x44,0x74,0x92,0x6f,0xd5,0x4b,0x6f,0xb0,
36460x86,0xe3,0xc7,0x36,0x42,0xa0,0xd0,0xfc,0xc1,0xc0,0x5a,0xf9,0xa3,0x61,0xb9,
36470x30,0x47,0x71,0x96,0x0a,0x16,0xb0,0x91,0xc0,0x42,0x95,0xef,0x10,0x7f,0x28,
36480x6a,0xe3,0x2a,0x1f,0xb1,0xe4,0xcd,0x03,0x3f,0x77,0x71,0x04,0xc7,0x20,0xfc,
36490x49,0x0f,0x1d,0x45,0x88,0xa4,0xd7,0xcb,0x7e,0x88,0xad,0x8e,0x2d,0xec,0x45,
36500xdb,0xc4,0x51,0x04,0xc9,0x2a,0xfc,0xec,0x86,0x9e,0x9a,0x11,0x97,0x5b,0xde,
36510xce,0x53,0x88,0xe6,0xe2,0xb7,0xfd,0xac,0x95,0xc2,0x28,0x40,0xdb,0xef,0x04,
36520x90,0xdf,0x81,0x33,0x39,0xd9,0xb2,0x45,0xa5,0x23,0x87,0x06,0xa5,0x55,0x89,
36530x31,0xbb,0x06,0x2d,0x60,0x0e,0x41,0x18,0x7d,0x1f,0x2e,0xb5,0x97,0xcb,0x11,
36540xeb,0x15,0xd5,0x24,0xa5,0x94,0xef,0x15,0x14,0x89,0xfd,0x4b,0x73,0xfa,0x32,
36550x5b,0xfc,0xd1,0x33,0x00,0xf9,0x59,0x62,0x70,0x07,0x32,0xea,0x2e,0xab,0x40,
36560x2d,0x7b,0xca,0xdd,0x21,0x67,0x1b,0x30,0x99,0x8f,0x16,0xaa,0x23,0xa8,0x41,
36570xd1,0xb0,0x6e,0x11,0x9b,0x36,0xc4,0xde,0x40,0x74,0x9c,0xe1,0x58,0x65,0xc1,
36580x60,0x1e,0x7a,0x5b,0x38,0xc8,0x8f,0xbb,0x04,0x26,0x7c,0xd4,0x16,0x40,0xe5,
36590xb6,0x6b,0x6c,0xaa,0x86,0xfd,0x00,0xbf,0xce,0xc1,0x35,0x02,0x03,0x01,0x00,
36600x01 };
3661/* from Microsoft Root Certificate Authority 2010 */
3662static BYTE msPubKey4[] = {
36630x30,0x82,0x02,0x0a,0x02,0x82,0x02,0x01,0x00,0xb9,0x08,0x9e,0x28,0xe4,0xe4,
36640xec,0x06,0x4e,0x50,0x68,0xb3,0x41,0xc5,0x7b,0xeb,0xae,0xb6,0x8e,0xaf,0x81,
36650xba,0x22,0x44,0x1f,0x65,0x34,0x69,0x4c,0xbe,0x70,0x40,0x17,0xf2,0x16,0x7b,
36660xe2,0x79,0xfd,0x86,0xed,0x0d,0x39,0xf4,0x1b,0xa8,0xad,0x92,0x90,0x1e,0xcb,
36670x3d,0x76,0x8f,0x5a,0xd9,0xb5,0x91,0x10,0x2e,0x3c,0x05,0x8d,0x8a,0x6d,0x24,
36680x54,0xe7,0x1f,0xed,0x56,0xad,0x83,0xb4,0x50,0x9c,0x15,0xa5,0x17,0x74,0x88,
36690x59,0x20,0xfc,0x08,0xc5,0x84,0x76,0xd3,0x68,0xd4,0x6f,0x28,0x78,0xce,0x5c,
36700xb8,0xf3,0x50,0x90,0x44,0xff,0xe3,0x63,0x5f,0xbe,0xa1,0x9a,0x2c,0x96,0x15,
36710x04,0xd6,0x07,0xfe,0x1e,0x84,0x21,0xe0,0x42,0x31,0x11,0xc4,0x28,0x36,0x94,
36720xcf,0x50,0xa4,0x62,0x9e,0xc9,0xd6,0xab,0x71,0x00,0xb2,0x5b,0x0c,0xe6,0x96,
36730xd4,0x0a,0x24,0x96,0xf5,0xff,0xc6,0xd5,0xb7,0x1b,0xd7,0xcb,0xb7,0x21,0x62,
36740xaf,0x12,0xdc,0xa1,0x5d,0x37,0xe3,0x1a,0xfb,0x1a,0x46,0x98,0xc0,0x9b,0xc0,
36750xe7,0x63,0x1f,0x2a,0x08,0x93,0x02,0x7e,0x1e,0x6a,0x8e,0xf2,0x9f,0x18,0x89,
36760xe4,0x22,0x85,0xa2,0xb1,0x84,0x57,0x40,0xff,0xf5,0x0e,0xd8,0x6f,0x9c,0xed,
36770xe2,0x45,0x31,0x01,0xcd,0x17,0xe9,0x7f,0xb0,0x81,0x45,0xe3,0xaa,0x21,0x40,
36780x26,0xa1,0x72,0xaa,0xa7,0x4f,0x3c,0x01,0x05,0x7e,0xee,0x83,0x58,0xb1,0x5e,
36790x06,0x63,0x99,0x62,0x91,0x78,0x82,0xb7,0x0d,0x93,0x0c,0x24,0x6a,0xb4,0x1b,
36800xdb,0x27,0xec,0x5f,0x95,0x04,0x3f,0x93,0x4a,0x30,0xf5,0x97,0x18,0xb3,0xa7,
36810xf9,0x19,0xa7,0x93,0x33,0x1d,0x01,0xc8,0xdb,0x22,0x52,0x5c,0xd7,0x25,0xc9,
36820x46,0xf9,0xa2,0xfb,0x87,0x59,0x43,0xbe,0x9b,0x62,0xb1,0x8d,0x2d,0x86,0x44,
36830x1a,0x46,0xac,0x78,0x61,0x7e,0x30,0x09,0xfa,0xae,0x89,0xc4,0x41,0x2a,0x22,
36840x66,0x03,0x91,0x39,0x45,0x9c,0xc7,0x8b,0x0c,0xa8,0xca,0x0d,0x2f,0xfb,0x52,
36850xea,0x0c,0xf7,0x63,0x33,0x23,0x9d,0xfe,0xb0,0x1f,0xad,0x67,0xd6,0xa7,0x50,
36860x03,0xc6,0x04,0x70,0x63,0xb5,0x2c,0xb1,0x86,0x5a,0x43,0xb7,0xfb,0xae,0xf9,
36870x6e,0x29,0x6e,0x21,0x21,0x41,0x26,0x06,0x8c,0xc9,0xc3,0xee,0xb0,0xc2,0x85,
36880x93,0xa1,0xb9,0x85,0xd9,0xe6,0x32,0x6c,0x4b,0x4c,0x3f,0xd6,0x5d,0xa3,0xe5,
36890xb5,0x9d,0x77,0xc3,0x9c,0xc0,0x55,0xb7,0x74,0x00,0xe3,0xb8,0x38,0xab,0x83,
36900x97,0x50,0xe1,0x9a,0x42,0x24,0x1d,0xc6,0xc0,0xa3,0x30,0xd1,0x1a,0x5a,0xc8,
36910x52,0x34,0xf7,0x73,0xf1,0xc7,0x18,0x1f,0x33,0xad,0x7a,0xec,0xcb,0x41,0x60,
36920xf3,0x23,0x94,0x20,0xc2,0x48,0x45,0xac,0x5c,0x51,0xc6,0x2e,0x80,0xc2,0xe2,
36930x77,0x15,0xbd,0x85,0x87,0xed,0x36,0x9d,0x96,0x91,0xee,0x00,0xb5,0xa3,0x70,
36940xec,0x9f,0xe3,0x8d,0x80,0x68,0x83,0x76,0xba,0xaf,0x5d,0x70,0x52,0x22,0x16,
36950xe2,0x66,0xfb,0xba,0xb3,0xc5,0xc2,0xf7,0x3e,0x2f,0x77,0xa6,0xca,0xde,0xc1,
36960xa6,0xc6,0x48,0x4c,0xc3,0x37,0x51,0x23,0xd3,0x27,0xd7,0xb8,0x4e,0x70,0x96,
36970xf0,0xa1,0x44,0x76,0xaf,0x78,0xcf,0x9a,0xe1,0x66,0x13,0x02,0x03,0x01,0x00,
36980x01 };
3699/* from Microsoft Root Certificate Authority 2011 */
3700static BYTE msPubKey5[] = {
37010x30,0x82,0x02,0x0a,0x02,0x82,0x02,0x01,0x00,0xb2,0x80,0x41,0xaa,0x35,0x38,
37020x4d,0x13,0x72,0x32,0x68,0x22,0x4d,0xb8,0xb2,0xf1,0xff,0xd5,0x52,0xbc,0x6c,
37030xc7,0xf5,0xd2,0x4a,0x8c,0x36,0xee,0xd1,0xc2,0x5c,0x7e,0x8c,0x8a,0xae,0xaf,
37040x13,0x28,0x6f,0xc0,0x73,0xe3,0x3a,0xce,0xd0,0x25,0xa8,0x5a,0x3a,0x6d,0xef,
37050xa8,0xb8,0x59,0xab,0x13,0x23,0x68,0xcd,0x0c,0x29,0x87,0xd1,0x6f,0x80,0x5c,
37060x8f,0x44,0x7f,0x5d,0x90,0x01,0x52,0x58,0xac,0x51,0xc5,0x5f,0x2a,0x87,0xdc,
37070xdc,0xd8,0x0a,0x1d,0xc1,0x03,0xb9,0x7b,0xb0,0x56,0xe8,0xa3,0xde,0x64,0x61,
37080xc2,0x9e,0xf8,0xf3,0x7c,0xb9,0xec,0x0d,0xb5,0x54,0xfe,0x4c,0xb6,0x65,0x4f,
37090x88,0xf0,0x9c,0x48,0x99,0x0c,0x42,0x0b,0x09,0x7c,0x31,0x59,0x17,0x79,0x06,
37100x78,0x28,0x8d,0x89,0x3a,0x4c,0x03,0x25,0xbe,0x71,0x6a,0x5c,0x0b,0xe7,0x84,
37110x60,0xa4,0x99,0x22,0xe3,0xd2,0xaf,0x84,0xa4,0xa7,0xfb,0xd1,0x98,0xed,0x0c,
37120xa9,0xde,0x94,0x89,0xe1,0x0e,0xa0,0xdc,0xc0,0xce,0x99,0x3d,0xea,0x08,0x52,
37130xbb,0x56,0x79,0xe4,0x1f,0x84,0xba,0x1e,0xb8,0xb4,0xc4,0x49,0x5c,0x4f,0x31,
37140x4b,0x87,0xdd,0xdd,0x05,0x67,0x26,0x99,0x80,0xe0,0x71,0x11,0xa3,0xb8,0xa5,
37150x41,0xe2,0xa4,0x53,0xb9,0xf7,0x32,0x29,0x83,0x0c,0x13,0xbf,0x36,0x5e,0x04,
37160xb3,0x4b,0x43,0x47,0x2f,0x6b,0xe2,0x91,0x1e,0xd3,0x98,0x4f,0xdd,0x42,0x07,
37170xc8,0xe8,0x1d,0x12,0xfc,0x99,0xa9,0x6b,0x3e,0x92,0x7e,0xc8,0xd6,0x69,0x3a,
37180xfc,0x64,0xbd,0xb6,0x09,0x9d,0xca,0xfd,0x0c,0x0b,0xa2,0x9b,0x77,0x60,0x4b,
37190x03,0x94,0xa4,0x30,0x69,0x12,0xd6,0x42,0x2d,0xc1,0x41,0x4c,0xca,0xdc,0xaa,
37200xfd,0x8f,0x5b,0x83,0x46,0x9a,0xd9,0xfc,0xb1,0xd1,0xe3,0xb3,0xc9,0x7f,0x48,
37210x7a,0xcd,0x24,0xf0,0x41,0x8f,0x5c,0x74,0xd0,0xac,0xb0,0x10,0x20,0x06,0x49,
37220xb7,0xc7,0x2d,0x21,0xc8,0x57,0xe3,0xd0,0x86,0xf3,0x03,0x68,0xfb,0xd0,0xce,
37230x71,0xc1,0x89,0x99,0x4a,0x64,0x01,0x6c,0xfd,0xec,0x30,0x91,0xcf,0x41,0x3c,
37240x92,0xc7,0xe5,0xba,0x86,0x1d,0x61,0x84,0xc7,0x5f,0x83,0x39,0x62,0xae,0xb4,
37250x92,0x2f,0x47,0xf3,0x0b,0xf8,0x55,0xeb,0xa0,0x1f,0x59,0xd0,0xbb,0x74,0x9b,
37260x1e,0xd0,0x76,0xe6,0xf2,0xe9,0x06,0xd7,0x10,0xe8,0xfa,0x64,0xde,0x69,0xc6,
37270x35,0x96,0x88,0x02,0xf0,0x46,0xb8,0x3f,0x27,0x99,0x6f,0xcb,0x71,0x89,0x29,
37280x35,0xf7,0x48,0x16,0x02,0x35,0x8f,0xd5,0x79,0x7c,0x4d,0x02,0xcf,0x5f,0xeb,
37290x8a,0x83,0x4f,0x45,0x71,0x88,0xf9,0xa9,0x0d,0x4e,0x72,0xe9,0xc2,0x9c,0x07,
37300xcf,0x49,0x1b,0x4e,0x04,0x0e,0x63,0x51,0x8c,0x5e,0xd8,0x00,0xc1,0x55,0x2c,
37310xb6,0xc6,0xe0,0xc2,0x65,0x4e,0xc9,0x34,0x39,0xf5,0x9c,0xb3,0xc4,0x7e,0xe8,
37320x61,0x6e,0x13,0x5f,0x15,0xc4,0x5f,0xd9,0x7e,0xed,0x1d,0xce,0xee,0x44,0xec,
37330xcb,0x2e,0x86,0xb1,0xec,0x38,0xf6,0x70,0xed,0xab,0x5c,0x13,0xc1,0xd9,0x0f,
37340x0d,0xc7,0x80,0xb2,0x55,0xed,0x34,0xf7,0xac,0x9b,0xe4,0xc3,0xda,0xe7,0x47,
37350x3c,0xa6,0xb5,0x8f,0x31,0xdf,0xc5,0x4b,0xaf,0xeb,0xf1,0x02,0x03,0x01,0x00,
37360x01 };
3737
3739 PCCERT_CHAIN_CONTEXT pChainContext, PCERT_CHAIN_POLICY_PARA pPolicyPara,
3740 PCERT_CHAIN_POLICY_STATUS pPolicyStatus)
3741{
3742 BOOL isMSRoot = FALSE;
3743
3744 CERT_PUBLIC_KEY_INFO msPubKey = { { 0 } };
3745 DWORD i;
3746 static const CRYPT_DATA_BLOB keyBlobs[] = {
3747 { sizeof(msPubKey1), msPubKey1 },
3748 { sizeof(msPubKey2), msPubKey2 },
3749 { sizeof(msPubKey3), msPubKey3 },
3750 { sizeof(msPubKey4), msPubKey4 },
3751 };
3752 static const CRYPT_DATA_BLOB keyBlobs_approot[] = {
3753 { sizeof(msPubKey5), msPubKey5 },
3754 };
3755 PCERT_SIMPLE_CHAIN rootChain =
3756 pChainContext->rgpChain[pChainContext->cChain - 1];
3758 rootChain->rgpElement[rootChain->cElement - 1]->pCertContext;
3759
3760 const CRYPT_DATA_BLOB *keys;
3761 unsigned int key_count;
3762
3764 {
3765 keys = keyBlobs_approot;
3766 key_count = ARRAY_SIZE(keyBlobs_approot);
3767 }
3768 else
3769 {
3770 keys = keyBlobs;
3771 key_count = ARRAY_SIZE(keyBlobs);
3772 }
3773
3774 for (i = 0; !isMSRoot && i < key_count; i++)
3775 {
3776 msPubKey.PublicKey.cbData = keys[i].cbData;
3777 msPubKey.PublicKey.pbData = keys[i].pbData;
3779 &root->pCertInfo->SubjectPublicKeyInfo, &msPubKey)) isMSRoot = TRUE;
3780 }
3781
3782 pPolicyStatus->lChainIndex = pPolicyStatus->lElementIndex = 0;
3783
3784 if (isMSRoot)
3785 pPolicyStatus->dwError = 0;
3786 else
3787 pPolicyStatus->dwError = CERT_E_UNTRUSTEDROOT;
3788
3789 return TRUE;
3790}
3791
3793 PCCERT_CHAIN_CONTEXT pChainContext, PCERT_CHAIN_POLICY_PARA pPolicyPara,
3794 PCERT_CHAIN_POLICY_STATUS pPolicyStatus);
3795
3797{
3798 if (para)
3799 {
3800 TRACE_(chain)("cbSize = %ld\n", para->cbSize);
3801 TRACE_(chain)("dwFlags = %08lx\n", para->dwFlags);
3802 TRACE_(chain)("pvExtraPolicyPara = %p\n", para->pvExtraPolicyPara);
3803 }
3804}
3805
3807 PCCERT_CHAIN_CONTEXT pChainContext, PCERT_CHAIN_POLICY_PARA pPolicyPara,
3808 PCERT_CHAIN_POLICY_STATUS pPolicyStatus)
3809{
3810 static HCRYPTOIDFUNCSET set = NULL;
3811 BOOL ret = FALSE;
3813 HCRYPTOIDFUNCADDR hFunc = NULL;
3814
3815 TRACE("(%s, %p, %p, %p)\n", debugstr_a(szPolicyOID), pChainContext,
3816 pPolicyPara, pPolicyStatus);
3817 if (TRACE_ON(chain))
3818 dump_policy_para(pPolicyPara);
3819
3820 if (IS_INTOID(szPolicyOID))
3821 {
3822 switch (LOWORD(szPolicyOID))
3823 {
3825 verifyPolicy = verify_base_policy;
3826 break;
3828 verifyPolicy = verify_authenticode_policy;
3829 break;
3831 verifyPolicy = verify_ssl_policy;
3832 break;
3834 verifyPolicy = verify_basic_constraints_policy;
3835 break;
3837 verifyPolicy = verify_ms_root_policy;
3838 break;
3839 default:
3840 FIXME("unimplemented for %d\n", LOWORD(szPolicyOID));
3841 }
3842 }
3843 if (!verifyPolicy)
3844 {
3845 if (!set)
3849 (void **)&verifyPolicy, &hFunc);
3850 }
3851 if (verifyPolicy)
3852 ret = verifyPolicy(szPolicyOID, pChainContext, pPolicyPara,
3853 pPolicyStatus);
3854 if (hFunc)
3856 TRACE("returning %d (%08lx)\n", ret, pPolicyStatus->dwError);
3857 return ret;
3858}
#define InterlockedIncrement
Definition: armddk.h:53
#define InterlockedDecrement
Definition: armddk.h:52
#define WINE_DEFAULT_DEBUG_CHANNEL(t)
Definition: precomp.h:23
char * hostname
Definition: ftp.c:88
#define ARRAY_SIZE(A)
Definition: main.h:20
INT copy(TCHAR source[MAX_PATH], TCHAR dest[MAX_PATH], INT append, DWORD lpdwFlags, BOOL bTouch)
Definition: copy.c:51
#define FIXME(fmt,...)
Definition: precomp.h:53
#define WARN(fmt,...)
Definition: precomp.h:61
#define ERR(fmt,...)
Definition: precomp.h:57
struct _root root
Definition: _set.h:50
BOOL WINAPI CertAddStoreToCollection(HCERTSTORE hCollectionStore, HCERTSTORE hSiblingStore, DWORD dwUpdateFlags, DWORD dwPriority)
BOOL WINAPI CryptDecodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
Definition: decode.c:6998
DWORD cert_name_to_str_with_indent(DWORD dwCertEncodingType, DWORD indent, const CERT_NAME_BLOB *pName, DWORD dwStrType, LPWSTR psz, DWORD csz)
Definition: str.c:336
#define IS_INTOID(x)
BOOL WINAPI CryptRetrieveObjectByUrlW(LPCWSTR pszURL, LPCSTR pszObjectOid, DWORD dwRetrievalFlags, DWORD dwTimeout, LPVOID *ppvObject, HCRYPTASYNC hAsyncRetrieve, PCRYPT_CREDENTIALS pCredentials, LPVOID pvVerify, PCRYPT_RETRIEVE_AUX_INFO pAuxInfo)
BOOL WINAPI CryptGetObjectUrl(LPCSTR pszUrlOid, LPVOID pvPara, DWORD dwFlags, PCRYPT_URL_ARRAY pUrlArray, DWORD *pcbUrlArray, PCRYPT_URL_INFO pUrlInfo, DWORD *pcbUrlInfo, LPVOID pvReserved)
#define NO_ERROR
Definition: dderror.h:5
#define E_INVALIDARG
Definition: ddrawi.h:101
struct config_s config
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
static const WCHAR empty[1]
Definition: string.c:47
BOOL WINAPI CertAddCertificateContextToStore(HCERTSTORE hCertStore, PCCERT_CONTEXT pCertContext, DWORD dwAddDisposition, PCCERT_CONTEXT *ppStoreContext)
Definition: cert.c:284
BOOL WINAPI CertFreeCertificateContext(PCCERT_CONTEXT pCertContext)
Definition: cert.c:369
BOOL WINAPI CertCompareCertificateName(DWORD dwCertEncodingType, PCERT_NAME_BLOB pCertName1, PCERT_NAME_BLOB pCertName2)
Definition: cert.c:1250
PCCERT_CONTEXT WINAPI CertFindCertificateInStore(HCERTSTORE hCertStore, DWORD dwCertEncodingType, DWORD dwFlags, DWORD dwType, const void *pvPara, PCCERT_CONTEXT pPrevCertContext)
Definition: cert.c:1830
BOOL WINAPI CertVerifyRevocation(DWORD dwEncodingType, DWORD dwRevType, DWORD cContext, PVOID rgpvContext[], DWORD dwFlags, PCERT_REVOCATION_PARA pRevPara, PCERT_REVOCATION_STATUS pRevStatus)
Definition: cert.c:2005
BOOL WINAPI CertIsRDNAttrsInCertificateName(DWORD dwCertEncodingType, DWORD dwFlags, PCERT_NAME_BLOB pCertName, PCERT_RDN pRDN)
Definition: cert.c:2202
BOOL WINAPI CryptVerifyCertificateSignatureEx(HCRYPTPROV_LEGACY hCryptProv, DWORD dwCertEncodingType, DWORD dwSubjectType, void *pvSubject, DWORD dwIssuerType, void *pvIssuer, DWORD dwFlags, void *pvReserved)
Definition: cert.c:2914
BOOL WINAPI CertCompareCertificate(DWORD dwCertEncodingType, PCERT_INFO pCertId1, PCERT_INFO pCertId2)
Definition: cert.c:1236
PCERT_EXTENSION WINAPI CertFindExtension(LPCSTR pszObjId, DWORD cExtensions, CERT_EXTENSION rgExtensions[])
Definition: cert.c:2099
BOOL WINAPI CertGetCertificateContextProperty(PCCERT_CONTEXT pCertContext, DWORD dwPropId, void *pvData, DWORD *pcbData)
Definition: cert.c:615
BOOL WINAPI CertComparePublicKeyInfo(DWORD dwCertEncodingType, PCERT_PUBLIC_KEY_INFO pPublicKey1, PCERT_PUBLIC_KEY_INFO pPublicKey2)
Definition: cert.c:1314
PCCERT_CONTEXT WINAPI CertDuplicateCertificateContext(PCCERT_CONTEXT pCertContext)
Definition: cert.c:358
LONG WINAPI CertVerifyTimeValidity(LPFILETIME pTimeToVerify, PCERT_INFO pCertInfo)
Definition: cert.c:2229
BOOL WINAPI CertCompareIntegerBlob(PCRYPT_INTEGER_BLOB pInt1, PCRYPT_INTEGER_BLOB pInt2)
Definition: cert.c:1291
PCERT_RDN_ATTR WINAPI CertFindRDNAttr(LPCSTR pszObjId, PCERT_NAME_INFO pName)
Definition: cert.c:2122
BOOL WINAPI CertVerifyCertificateChainPolicy(LPCSTR szPolicyOID, PCCERT_CHAIN_CONTEXT pChainContext, PCERT_CHAIN_POLICY_PARA pPolicyPara, PCERT_CHAIN_POLICY_STATUS pPolicyStatus)
Definition: chain.c:3806
static void CRYPT_CheckChainPolicies(PCERT_SIMPLE_CHAIN chain)
Definition: chain.c:1377
static void dump_netscape_cert_type(const CERT_EXTENSION *ext)
Definition: chain.c:1617
BOOL WINAPI CertGetCertificateChain(HCERTCHAINENGINE hChainEngine, PCCERT_CONTEXT pCertContext, LPFILETIME pTime, HCERTSTORE hAdditionalStore, PCERT_CHAIN_PARA pChainPara, DWORD dwFlags, LPVOID pvReserved, PCCERT_CHAIN_CONTEXT *ppChainContext)
Definition: chain.c:2875
static void CRYPT_CheckSimpleChainForCycles(PCERT_SIMPLE_CHAIN chain)
Definition: chain.c:379
static void CRYPT_CheckChainNameConstraints(PCERT_SIMPLE_CHAIN chain)
Definition: chain.c:1275
static BOOL WINAPI verify_ms_root_policy(LPCSTR szPolicyOID, PCCERT_CHAIN_CONTEXT pChainContext, PCERT_CHAIN_POLICY_PARA pPolicyPara, PCERT_CHAIN_POLICY_STATUS pPolicyStatus)
Definition: chain.c:3738
static void CRYPT_CloseStores(DWORD cStores, HCERTSTORE *stores)
Definition: chain.c:63
static BOOL find_matching_domain_component(const CERT_NAME_INFO *name, const WCHAR *component, size_t len)
Definition: chain.c:3213
static CertificateChainEngine * default_lm_engine
Definition: chain.c:160
static DWORD CRYPT_ChainQuality(const CertificateChain *chain)
Definition: chain.c:2524
static BOOL CRYPT_BuildCandidateChainFromCert(CertificateChainEngine *engine, PCCERT_CONTEXT cert, LPFILETIME pTime, HCERTSTORE hAdditionalStore, DWORD flags, CertificateChain **ppChain)
Definition: chain.c:2247
static void CRYPT_CheckPolicies(const CERT_POLICIES_INFO *policies, CERT_INFO *cert, DWORD *errorStatus)
Definition: chain.c:1353
static BOOL CRYPT_AddAlternateChainToChain(CertificateChain *chain, const CertificateChain *alternate)
Definition: chain.c:2582
static BOOL match_dns_to_subject_alt_name(const CERT_EXTENSION *ext, LPCWSTR server_name)
Definition: chain.c:3145
static CertificateChainEngine * get_chain_engine(HCERTCHAINENGINE handle, BOOL allow_default)
Definition: chain.c:162
static BOOL CRYPT_CheckRestrictedRoot(HCERTSTORE store)
Definition: chain.c:89
static BOOL WINAPI verify_ssl_policy(LPCSTR szPolicyOID, PCCERT_CHAIN_CONTEXT pChainContext, PCERT_CHAIN_POLICY_PARA pPolicyPara, PCERT_CHAIN_POLICY_STATUS pPolicyStatus)
Definition: chain.c:3450
static void CRYPT_VerifyChainRevocation(PCERT_CHAIN_CONTEXT chain, LPFILETIME pTime, HCERTSTORE hAdditionalStore, const CERT_CHAIN_PARA *pChainPara, DWORD chainFlags)
Definition: chain.c:2628
struct _CERT_CHAIN_PARA_NO_EXTRA_FIELDS CERT_CHAIN_PARA_NO_EXTRA_FIELDS
static void free_chain_engine(CertificateChainEngine *engine)
Definition: chain.c:197
static BOOL WINAPI verify_basic_constraints_policy(LPCSTR szPolicyOID, PCCERT_CHAIN_CONTEXT pChainContext, PCERT_CHAIN_POLICY_PARA pPolicyPara, PCERT_CHAIN_POLICY_STATUS pPolicyStatus)
Definition: chain.c:3127
#define CHAIN_QUALITY_HIGHEST
Definition: chain.c:2516
static void dump_policy_para(PCERT_CHAIN_POLICY_PARA para)
Definition: chain.c:3796
static void dump_extension(const CERT_EXTENSION *ext)
Definition: chain.c:1643
static BOOL CRYPT_AddCertToSimpleChain(const CertificateChainEngine *engine, PCERT_SIMPLE_CHAIN chain, PCCERT_CONTEXT cert, DWORD subjectInfoStatus)
Definition: chain.c:423
void default_chain_engine_free(void)
Definition: chain.c:251
static BYTE msPubKey3[]
Definition: chain.c:3624
static void CRYPT_FreeChainElement(PCERT_CHAIN_ELEMENT element)
Definition: chain.c:373
static BOOL url_matches(LPCWSTR constraint, LPCWSTR name, DWORD *trustErrorStatus)
Definition: chain.c:678
static BOOL ip_address_matches(const CRYPT_DATA_BLOB *constraint, const CRYPT_DATA_BLOB *name, DWORD *trustErrorStatus)
Definition: chain.c:816
static BYTE msTestPubKey2[]
Definition: chain.c:3067
static void dump_basic_constraints(const CERT_EXTENSION *ext)
Definition: chain.c:1480
static void dump_key_usage(const CERT_EXTENSION *ext)
Definition: chain.c:1514
static BOOL CRYPT_KeyUsageValid(CertificateChainEngine *engine, PCCERT_CONTEXT cert, BOOL isRoot, BOOL isCA, DWORD index)
Definition: chain.c:1719
#define IS_TRUST_ERROR_SET(TrustStatus, bits)
Definition: chain.c:2521
static BYTE msPubKey4[]
Definition: chain.c:3662
struct _CertificateChain CertificateChain
VOID WINAPI CertFreeCertificateChain(PCCERT_CHAIN_CONTEXT pChainContext)
Definition: chain.c:2956
static BOOL WINAPI verify_base_policy(LPCSTR szPolicyOID, PCCERT_CHAIN_CONTEXT pChainContext, PCERT_CHAIN_POLICY_PARA pPolicyPara, PCERT_CHAIN_POLICY_STATUS pPolicyStatus)
Definition: chain.c:2994
static void CRYPT_FreeLowerQualityChains(CertificateChain *chain)
Definition: chain.c:2347
void WINAPI CertFreeCertificateChainEngine(HCERTCHAINENGINE hChainEngine)
Definition: chain.c:245
static BOOL rfc822_attr_matches_excluded_name(const CERT_RDN_ATTR *attr, const CERT_NAME_CONSTRAINTS_INFO *nameConstraints, DWORD *trustErrorStatus)
Definition: chain.c:1013
static void dump_enhanced_key_usage(const CERT_EXTENSION *ext)
Definition: chain.c:1599
struct _CERT_CHAIN_ENGINE_CONFIG_NO_EXCLUSIVE_ROOT CERT_CHAIN_ENGINE_CONFIG_NO_EXCLUSIVE_ROOT
static BOOL dns_name_matches(LPCWSTR constraint, LPCWSTR name, DWORD *trustErrorStatus)
Definition: chain.c:771
static BOOL domain_name_matches(LPCWSTR constraint, LPCWSTR name)
Definition: chain.c:643
BOOL WINAPI CertCreateCertificateChainEngine(PCERT_CHAIN_ENGINE_CONFIG pConfig, HCERTCHAINENGINE *phChainEngine)
Definition: chain.c:221
static void dump_basic_constraints2(const CERT_EXTENSION *ext)
Definition: chain.c:1497
static void find_element_with_error(PCCERT_CHAIN_CONTEXT chain, DWORD error, LONG *iChain, LONG *iElement)
Definition: chain.c:2978
static CertificateChain * CRYPT_CopyChainToElement(CertificateChain *chain, DWORD iChain, DWORD iElement)
Definition: chain.c:2373
static BOOL CRYPT_IsValidNameConstraint(const CERT_NAME_CONSTRAINTS_INFO *info)
Definition: chain.c:1230
static void dump_alt_name(LPCSTR type, const CERT_EXTENSION *ext)
Definition: chain.c:1461
static void dump_ssl_extra_chain_policy_para(HTTPSPolicyCallbackData *sslPara)
Definition: chain.c:3438
static CERT_POLICIES_INFO * CRYPT_GetPolicies(PCCERT_CONTEXT cert)
Definition: chain.c:1335
static void compare_alt_name_with_constraints(const CERT_EXTENSION *altNameExt, const CERT_NAME_CONSTRAINTS_INFO *nameConstraints, DWORD *trustErrorStatus)
Definition: chain.c:963
static BYTE msPubKey5[]
Definition: chain.c:3700
static BOOL rfc822_attr_matches_permitted_name(const CERT_RDN_ATTR *attr, const CERT_NAME_CONSTRAINTS_INFO *nameConstraints, DWORD *trustErrorStatus, BOOL *present)
Definition: chain.c:1031
#define DEFAULT_CYCLE_MODULUS
Definition: chain.c:36
static void compare_subject_with_constraints(const CERT_NAME_BLOB *subjectName, const CERT_NAME_CONSTRAINTS_INFO *nameConstraints, DWORD *trustErrorStatus)
Definition: chain.c:1122
static PCCERT_CONTEXT CRYPT_FindCertInStore(HCERTSTORE store, PCCERT_CONTEXT cert)
Definition: chain.c:72
static BYTE msPubKey2[]
Definition: chain.c:3605
PCCERT_CHAIN_CONTEXT WINAPI CertFindChainInStore(HCERTSTORE store, DWORD certEncodingType, DWORD findFlags, DWORD findType, const void *findPara, PCCERT_CHAIN_CONTEXT prevChainContext)
Definition: chain.c:2969
static void CRYPT_CheckUsages(PCERT_CHAIN_CONTEXT chain, const CERT_CHAIN_PARA *pChainPara)
Definition: chain.c:2741
static void dump_usage_match(LPCSTR name, const CERT_USAGE_MATCH *usageMatch)
Definition: chain.c:2847
static BOOL CRYPT_IsCertVersionValid(PCCERT_CONTEXT cert)
Definition: chain.c:1836
static void CRYPT_CheckSimpleChain(CertificateChainEngine *engine, PCERT_SIMPLE_CHAIN chain, LPFILETIME time)
Definition: chain.c:1875
static LPCSTR debugstr_filetime(LPFILETIME pTime)
Definition: chain.c:2209
static void CRYPT_CheckTrustedStatus(HCERTSTORE hRoot, PCERT_CHAIN_ELEMENT rootElement)
Definition: chain.c:474
static BOOL CRYPT_CheckBasicConstraintsForCA(CertificateChainEngine *engine, PCCERT_CONTEXT cert, CERT_BASIC_CONSTRAINTS2_INFO *chainConstraints, DWORD remainingCAs, BOOL isRoot, BOOL *pathLengthConstraintViolated)
Definition: chain.c:576
static BOOL match_dns_to_subject_dn(PCCERT_CONTEXT cert, LPCWSTR server_name)
Definition: chain.c:3375
PCCERT_CHAIN_CONTEXT WINAPI CertDuplicateCertificateChain(PCCERT_CHAIN_CONTEXT pChainContext)
Definition: chain.c:2944
#define trace_cert_type_bit(bits, bit)
static BOOL alt_name_matches_excluded_name(const CERT_ALT_NAME_ENTRY *name, const CERT_NAME_CONSTRAINTS_INFO *nameConstraints, DWORD *trustErrorStatus)
Definition: chain.c:925
static PCERT_EXTENSION get_subject_alt_name_ext(const CERT_INFO *cert)
Definition: chain.c:951
static CertificateChain * CRYPT_BuildAlternateContextFromChain(CertificateChainEngine *engine, LPFILETIME pTime, HCERTSTORE hAdditionalStore, DWORD flags, CertificateChain *chain)
Definition: chain.c:2438
static PCCERT_CONTEXT CRYPT_GetIssuer(const CertificateChainEngine *engine, HCERTSTORE store, PCCERT_CONTEXT subject, PCCERT_CONTEXT prevIssuer, DWORD flags, DWORD *infoStatus)
Definition: chain.c:2052
static CertificateChain * CRYPT_ChooseHighestQualityChain(CertificateChain *chain)
Definition: chain.c:2550
static BOOL CRYPT_CriticalExtensionsSupported(PCCERT_CONTEXT cert)
Definition: chain.c:1798
static PCERT_CHAIN_ELEMENT CRYPT_FindIthElementInChain(const CERT_CHAIN_CONTEXT *chain, DWORD i)
Definition: chain.c:2607
static LPWSTR name_value_to_str(const CERT_NAME_BLOB *name)
Definition: chain.c:1406
static void CRYPT_CheckNameConstraints(const CERT_NAME_CONSTRAINTS_INFO *nameConstraints, const CERT_INFO *cert, DWORD *trustErrorStatus)
Definition: chain.c:1192
static BOOL rfc822_name_matches(LPCWSTR constraint, LPCWSTR name, DWORD *trustErrorStatus)
Definition: chain.c:747
static BOOL CRYPT_IsEmptyName(const CERT_NAME_BLOB *name)
Definition: chain.c:1106
#define trace_usage_bit(bits, bit)
static void dump_alt_name_entry(const CERT_ALT_NAME_ENTRY *entry)
Definition: chain.c:1422
static BOOL match_common_name(LPCWSTR server_name, const CERT_RDN_ATTR *nameAttr)
Definition: chain.c:3295
static PCERT_SIMPLE_CHAIN CRYPT_CopySimpleChainToElement(const CERT_SIMPLE_CHAIN *chain, DWORD iElement)
Definition: chain.c:2292
static LPCSTR filetime_to_str(const FILETIME *time)
Definition: chain.c:1671
HCERTCHAINENGINE CRYPT_CreateChainEngine(HCERTSTORE root, DWORD system_store, const CERT_CHAIN_ENGINE_CONFIG *config)
Definition: chain.c:115
static void CRYPT_CheckRootCert(HCERTSTORE hRoot, PCERT_CHAIN_ELEMENT rootElement)
Definition: chain.c:487
static void dump_name_constraints(const CERT_EXTENSION *ext)
Definition: chain.c:1548
static CERT_NAME_CONSTRAINTS_INFO * CRYPT_GetNameConstraints(CERT_INFO *cert)
Definition: chain.c:1211
static BOOL CRYPT_DecodeBasicConstraints(PCCERT_CONTEXT cert, CERT_BASIC_CONSTRAINTS2_INFO *constraints, BOOL defaultIfNotSpecified)
Definition: chain.c:509
static BOOL alt_name_matches(const CERT_ALT_NAME_ENTRY *name, const CERT_ALT_NAME_ENTRY *constraint, DWORD *trustErrorStatus, BOOL *present)
Definition: chain.c:882
static BOOL directory_name_matches(const CERT_NAME_BLOB *constraint, const CERT_NAME_BLOB *name)
Definition: chain.c:860
static void dump_authenticode_extra_chain_policy_para(AUTHENTICODE_EXTRA_CERT_CHAIN_POLICY_PARA *extraPara)
Definition: chain.c:3074
static void CRYPT_FreeSimpleChain(PCERT_SIMPLE_CHAIN chain)
Definition: chain.c:464
static void CRYPT_AddStoresToCollection(HCERTSTORE collection, DWORD cStores, HCERTSTORE *stores)
Definition: chain.c:54
static CertificateChainEngine * default_cu_engine
Definition: chain.c:160
static BOOL CRYPT_IsSimpleChainCyclic(const CERT_SIMPLE_CHAIN *chain)
Definition: chain.c:403
static void dump_general_subtree(const CERT_GENERAL_SUBTREE *subtree)
Definition: chain.c:1541
static void CRYPT_FreeChainContext(CertificateChain *chain)
Definition: chain.c:2358
static BOOL WINAPI verify_authenticode_policy(LPCSTR szPolicyOID, PCCERT_CHAIN_CONTEXT pChainContext, PCERT_CHAIN_POLICY_PARA pPolicyPara, PCERT_CHAIN_POLICY_STATUS pPolicyStatus)
Definition: chain.c:3086
static BYTE msTestPubKey1[]
Definition: chain.c:3061
struct _CertificateChainEngine CertificateChainEngine
static BOOL CRYPT_BuildSimpleChain(const CertificateChainEngine *engine, HCERTSTORE world, DWORD flags, PCERT_SIMPLE_CHAIN chain)
Definition: chain.c:2177
static BOOL match_domain_component(LPCWSTR allowed_component, DWORD allowed_len, LPCWSTR server_component, DWORD server_len, BOOL allow_wildcards, BOOL *see_wildcard)
Definition: chain.c:3238
static void compare_subject_with_email_constraints(const CERT_NAME_BLOB *subjectName, const CERT_NAME_CONSTRAINTS_INFO *nameConstraints, DWORD *trustErrorStatus)
Definition: chain.c:1053
static BYTE msPubKey1[]
Definition: chain.c:3586
DWORD CRYPT_IsCertificateSelfSigned(const CERT_CONTEXT *cert)
Definition: chain.c:264
static void dump_cert_policies(const CERT_EXTENSION *ext)
Definition: chain.c:1572
static void dump_chain_para(const CERT_CHAIN_PARA *pChainPara)
Definition: chain.c:2860
static void dump_element(PCCERT_CONTEXT cert)
Definition: chain.c:1685
static BOOL alt_name_matches_permitted_name(const CERT_ALT_NAME_ENTRY *name, const CERT_NAME_CONSTRAINTS_INFO *nameConstraints, DWORD *trustErrorStatus, BOOL *present)
Definition: chain.c:937
static BOOL CRYPT_GetSimpleChainForCert(CertificateChainEngine *engine, HCERTSTORE world, PCCERT_CONTEXT cert, LPFILETIME pTime, DWORD flags, PCERT_SIMPLE_CHAIN *ppChain)
Definition: chain.c:2216
BOOL(WINAPI * CertVerifyCertificateChainPolicyFunc)(LPCSTR szPolicyOID, PCCERT_CHAIN_CONTEXT pChainContext, PCERT_CHAIN_POLICY_PARA pPolicyPara, PCERT_CHAIN_POLICY_STATUS pPolicyStatus)
Definition: chain.c:3792
static PCCERT_CONTEXT CRYPT_FindIssuer(const CertificateChainEngine *engine, const CERT_CONTEXT *cert, HCERTSTORE store, DWORD type, void *para, DWORD flags, PCCERT_CONTEXT prev_issuer)
Definition: chain.c:1978
static void CRYPT_CombineTrustStatus(CERT_TRUST_STATUS *chainStatus, const CERT_TRUST_STATUS *elementStatus)
Definition: chain.c:412
LPVOID WINAPI CryptMemAlloc(ULONG cbSize)
Definition: main.c:136
LPVOID WINAPI CryptMemRealloc(LPVOID pv, ULONG cbSize)
Definition: main.c:141
VOID WINAPI CryptMemFree(LPVOID pv)
Definition: main.c:146
static WCHAR issuer[MAX_STRING_RESOURCE_LEN]
Definition: object.c:1972
HCRYPTOIDFUNCSET WINAPI CryptInitOIDFunctionSet(LPCSTR pszFuncName, DWORD dwFlags)
Definition: oid.c:103
BOOL WINAPI CryptGetOIDFunctionAddress(HCRYPTOIDFUNCSET hFuncSet, DWORD dwEncodingType, LPCSTR pszOID, DWORD dwFlags, void **ppvFuncAddr, HCRYPTOIDFUNCADDR *phFuncAddr)
Definition: oid.c:375
BOOL WINAPI CryptFreeOIDFunctionAddress(HCRYPTOIDFUNCADDR hFuncAddr, DWORD dwFlags)
Definition: oid.c:456
HCERTSTORE WINAPI CertOpenStore(LPCSTR lpszStoreProvider, DWORD dwMsgAndCertEncodingType, HCRYPTPROV_LEGACY hCryptProv, DWORD dwFlags, const void *pvPara)
Definition: store.c:809
HCERTSTORE WINAPI CertDuplicateStore(HCERTSTORE hCertStore)
Definition: store.c:1110
PCCERT_CONTEXT WINAPI CertEnumCertificatesInStore(HCERTSTORE hCertStore, PCCERT_CONTEXT pPrev)
Definition: store.c:922
BOOL WINAPI CertCloseStore(HCERTSTORE hCertStore, DWORD dwFlags)
Definition: store.c:1121
HCERTSTORE WINAPI CertOpenSystemStoreW(HCRYPTPROV_LEGACY hProv, LPCWSTR szSubSystemProtocol)
Definition: store.c:910
DWORD WINAPI CertGetNameStringW(PCCERT_CONTEXT cert, DWORD type, DWORD flags, void *type_para, LPWSTR name_string, DWORD name_len)
Definition: str.c:1013
const char * wine_dbg_sprintf(const char *format,...)
Definition: compat.c:296
#define wcschr
Definition: compat.h:17
#define wcsnicmp
Definition: compat.h:14
#define TRACE_(x)
Definition: compat.h:76
#define SetLastError(x)
Definition: compat.h:752
#define TRACE_ON(x)
Definition: compat.h:75
#define WINE_DECLARE_DEBUG_CHANNEL(x)
Definition: compat.h:45
#define wcsicmp
Definition: compat.h:15
#define lstrlenW
Definition: compat.h:750
static const WCHAR *const ext[]
Definition: module.c:53
BOOL WINAPI FileTimeToSystemTime(IN CONST FILETIME *lpFileTime, OUT LPSYSTEMTIME lpSystemTime)
Definition: time.c:183
INT WINAPI GetLocaleInfoA(LCID lcid, LCTYPE lctype, LPSTR buffer, INT len)
Definition: locale.c:1609
int WINAPI lstrcmpiW(LPCWSTR str1, LPCWSTR str2)
Definition: locale.c:4171
const UINT * keys
Definition: locale.c:418
_ACRTIMP int __cdecl memcmp(const void *, const void *, size_t)
Definition: string.c:2807
_ACRTIMP int __cdecl strcmp(const char *, const char *)
Definition: string.c:3324
static wchar_t * wmemchr(const wchar_t *s, wchar_t c, size_t n)
Definition: wchar.h:48
#define check(expected, result)
Definition: dplayx.c:32
return ret
Definition: mutex.c:146
#define L(x)
Definition: resources.c:13
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
GLuint GLuint end
Definition: gl.h:1545
GLuint res
Definition: glext.h:9613
GLsizeiptr size
Definition: glext.h:5919
GLuint index
Definition: glext.h:6031
GLenum GLint GLuint mask
Definition: glext.h:6028
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
GLbitfield flags
Definition: glext.h:7161
GLenum const GLvoid * addr
Definition: glext.h:9621
GLenum GLsizei len
Definition: glext.h:6722
GLuint id
Definition: glext.h:5910
GLsizeiptr const GLvoid GLenum usage
Definition: glext.h:5919
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint j
Definition: glfuncs.h:250
HLOCAL NTAPI LocalFree(HLOCAL hMem)
Definition: heapmem.c:1594
#define InterlockedCompareExchangePointer
Definition: interlocked.h:144
uint32_t entry
Definition: isohybrid.c:63
int quality
Definition: jpeglib.h:994
#define debugstr_a
Definition: kernel32.h:31
#define debugstr_wn
Definition: kernel32.h:33
#define debugstr_w
Definition: kernel32.h:32
INT WINAPI GetDateFormatA(LCID lcid, DWORD dwFlags, const SYSTEMTIME *lpTime, LPCSTR lpFormat, LPSTR lpDateStr, INT cchOut)
Definition: lcformat.c:944
if(dx< 0)
Definition: linetemp.h:194
__u16 date
Definition: mkdosfs.c:8
__u16 time
Definition: mkdosfs.c:8
#define error(str)
Definition: mkdosfs.c:1605
#define matches(FN)
Definition: match.h:70
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
static PVOID ptr
Definition: dispmode.c:27
static HTREEITEM hRoot
Definition: treeview.c:383
static BYTE subjectName[]
Definition: cert.c:35
static BYTE cert[]
Definition: msg.c:1374
static LPCWSTR LPVOID pvReserved
Definition: asmcache.c:749
static ICollection collection
Definition: typelib.c:201
_In_ LPWSTR _In_ DWORD _In_ DWORD _In_ DWORD dwFlags
Definition: netsh.h:141
#define BOOL
Definition: nt_native.h:43
#define LOCALE_SYSTEM_DEFAULT
#define LOWORD(l)
Definition: pedump.c:82
short WCHAR
Definition: pedump.c:58
long LONG
Definition: pedump.c:60
const WCHAR * str
#define WARN_(ch,...)
Definition: debug.h:157
#define memset(x, y, z)
Definition: compat.h:39
#define towlower(c)
Definition: wctype.h:97
#define TRACE(s)
Definition: solgame.cpp:4
Definition: wincrypt.h:341
LPWSTR pwszRfc822Name
Definition: wincrypt.h:345
LPWSTR pwszURL
Definition: wincrypt.h:348
DWORD dwAltNameChoice
Definition: wincrypt.h:342
CRYPT_DATA_BLOB IPAddress
Definition: wincrypt.h:349
CERT_NAME_BLOB DirectoryName
Definition: wincrypt.h:347
PCERT_ALT_NAME_ENTRY rgAltEntry
Definition: wincrypt.h:366
PCERT_SIMPLE_CHAIN * rgpChain
Definition: wincrypt.h:1053
DWORD cLowerQualityChainContext
Definition: wincrypt.h:1054
CERT_TRUST_STATUS TrustStatus
Definition: wincrypt.h:1051
PCCERT_CHAIN_CONTEXT * rgpLowerQualityChainContext
Definition: wincrypt.h:1055
PCCERT_CONTEXT pCertContext
Definition: wincrypt.h:1028
CERT_TRUST_STATUS TrustStatus
Definition: wincrypt.h:1029
HCERTSTORE hRestrictedRoot
Definition: wincrypt.h:3786
CERT_USAGE_MATCH RequestedUsage
Definition: chain.c:2625
CERT_USAGE_MATCH RequestedUsage
Definition: wincrypt.h:1183
DWORD dwCertEncodingType
Definition: wincrypt.h:488
HCERTSTORE hCertStore
Definition: wincrypt.h:492
PCERT_INFO pCertInfo
Definition: wincrypt.h:491
CRYPT_OBJID_BLOB Value
Definition: wincrypt.h:241
CERT_ALT_NAME_ENTRY Base
Definition: wincrypt.h:584
PCERT_EXTENSION rgExtension
Definition: wincrypt.h:261
CERT_NAME_BLOB Issuer
Definition: wincrypt.h:253
CERT_PUBLIC_KEY_INFO SubjectPublicKeyInfo
Definition: wincrypt.h:257
CRYPT_ALGORITHM_IDENTIFIER SignatureAlgorithm
Definition: wincrypt.h:252
DWORD cExtension
Definition: wincrypt.h:260
PCERT_GENERAL_SUBTREE rgPermittedSubtree
Definition: wincrypt.h:592
PCERT_GENERAL_SUBTREE rgExcludedSubtree
Definition: wincrypt.h:594
PCERT_RDN rgRDN
Definition: wincrypt.h:277
CERT_POLICY_INFO * rgPolicyInfo
Definition: wincrypt.h:409
CERT_POLICY_QUALIFIER_INFO * rgPolicyQualifier
Definition: wincrypt.h:404
LPSTR pszPolicyIdentifier
Definition: wincrypt.h:402
DWORD cPolicyQualifier
Definition: wincrypt.h:403
CRYPT_BIT_BLOB PublicKey
Definition: wincrypt.h:235
CERT_RDN_VALUE_BLOB Value
Definition: wincrypt.h:267
LPFILETIME pftTimeToUse
Definition: wincrypt.h:920
HCERTSTORE hCrlStore
Definition: wincrypt.h:919
PCCERT_CONTEXT pIssuerCert
Definition: wincrypt.h:916
HCERTSTORE * rgCertStore
Definition: wincrypt.h:918
CERT_TRUST_STATUS TrustStatus
Definition: wincrypt.h:1038
PCERT_CHAIN_ELEMENT * rgpElement
Definition: wincrypt.h:1040
CERT_ENHKEY_USAGE Usage
Definition: wincrypt.h:1161
BYTE * pbData
Definition: wincrypt.h:112
BYTE * pbData
Definition: wincrypt.h:206
LPWSTR * rgwszUrl
Definition: wincrypt.h:1738
DWORD cUsageIdentifier
Definition: wincrypt.h:831
LPSTR * rgpszUsageIdentifier
Definition: wincrypt.h:832
DWORD MaximumCachedCertificates
Definition: chain.c:50
DWORD dwUrlRetrievalTimeout
Definition: chain.c:49
HCERTSTORE hRoot
Definition: chain.c:46
DWORD CycleDetectionModulus
Definition: chain.c:51
HCERTSTORE hWorld
Definition: chain.c:47
CERT_CHAIN_CONTEXT context
Definition: chain.c:259
HCERTSTORE world
Definition: chain.c:260
Definition: cookie.c:202
Definition: image.c:134
Definition: _hash_fun.h:40
Definition: match.c:28
Definition: name.c:39
Definition: ps.c:97
struct sock * chain
Definition: tcpcore.h:1
const char * LPCSTR
Definition: typedefs.h:52
const uint16_t * LPCWSTR
Definition: typedefs.h:57
unsigned char * LPBYTE
Definition: typedefs.h:53
uint16_t * LPWSTR
Definition: typedefs.h:56
char * server_name
Definition: widl.c:128
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
struct _CERT_CHAIN_ELEMENT CERT_CHAIN_ELEMENT
#define CERT_FIND_CERT_ID
Definition: wincrypt.h:3054
#define CERT_CHAIN_POLICY_MICROSOFT_ROOT
Definition: wincrypt.h:1080
#define X509_AUTHORITY_KEY_ID2
Definition: wincrypt.h:3550
#define szOID_AUTHORITY_KEY_IDENTIFIER
Definition: wincrypt.h:3331
#define CERT_ID_ISSUER_SERIAL_NUMBER
Definition: wincrypt.h:3838
#define CONTEXT_OID_CERTIFICATE
Definition: wincrypt.h:1876
#define USAGE_MATCH_TYPE_AND
Definition: wincrypt.h:1156
struct _CERT_SIMPLE_CHAIN CERT_SIMPLE_CHAIN
#define CERT_KEY_ENCIPHERMENT_KEY_USAGE
Definition: wincrypt.h:315
#define CERT_CHAIN_POLICY_BASE
Definition: wincrypt.h:1074
#define CRYPT_DECODE_NOCOPY_FLAG
Definition: wincrypt.h:3608
#define CERT_KEY_IDENTIFIER_PROP_ID
Definition: wincrypt.h:2853
#define NETSCAPE_SSL_CA_CERT_TYPE
Definition: wincrypt.h:3512
#define CERT_CHAIN_RETURN_LOWER_QUALITY_CONTEXTS
Definition: wincrypt.h:1177
#define X509_NAME
Definition: wincrypt.h:3524
#define CERT_NON_REPUDIATION_KEY_USAGE
Definition: wincrypt.h:314
const CERT_CHAIN_CONTEXT * PCCERT_CHAIN_CONTEXT
Definition: wincrypt.h:1047
#define URL_OID_CERTIFICATE_ISSUER
Definition: wincrypt.h:1748
#define CERT_TRUST_IS_REVOKED
Definition: wincrypt.h:984
#define X509_UNICODE_NAME
Definition: wincrypt.h:3537
#define CERT_TRUST_INVALID_POLICY_CONSTRAINTS
Definition: wincrypt.h:991
#define CERT_NAME_SIMPLE_DISPLAY_TYPE
Definition: wincrypt.h:3658
#define CERT_STORE_PROV_COLLECTION
Definition: wincrypt.h:2465
#define CERT_V3
Definition: wincrypt.h:2805
#define HCCE_CURRENT_USER
Definition: wincrypt.h:3773
#define CERT_TRUST_REVOCATION_STATUS_UNKNOWN
Definition: wincrypt.h:988
#define CERT_CHAIN_REVOCATION_CHECK_CHAIN
Definition: wincrypt.h:1170
#define CERT_ALT_NAME_URL
Definition: wincrypt.h:360
#define NETSCAPE_SSL_SERVER_AUTH_CERT_TYPE
Definition: wincrypt.h:3509
#define CERT_TRUST_HAS_NOT_SUPPORTED_CRITICAL_EXT
Definition: wincrypt.h:1001
#define CERT_CHAIN_POLICY_BASIC_CONSTRAINTS
Definition: wincrypt.h:1078
#define szOID_BASIC_CONSTRAINTS2
Definition: wincrypt.h:3345
#define CERT_ALT_NAME_DIRECTORY_NAME
Definition: wincrypt.h:358
#define CERT_TRUST_IS_CYCLIC
Definition: wincrypt.h:989
#define NETSCAPE_SIGN_CERT_TYPE
Definition: wincrypt.h:3511
#define CERT_CHAIN_REVOCATION_CHECK_END_CERT
Definition: wincrypt.h:1169
#define CERT_ID_KEY_IDENTIFIER
Definition: wincrypt.h:3839
#define CERT_ALT_NAME_IP_ADDRESS
Definition: wincrypt.h:361
#define szOID_NAME_CONSTRAINTS
Definition: wincrypt.h:3351
#define CERT_TRUST_HAS_VALID_NAME_CONSTRAINTS
Definition: wincrypt.h:1015
#define CERT_STORE_CREATE_NEW_FLAG
Definition: wincrypt.h:2633
#define NETSCAPE_SIGN_CA_CERT_TYPE
Definition: wincrypt.h:3514
#define CERT_CHAIN_CACHE_ONLY_URL_RETRIEVAL
Definition: wincrypt.h:3778
#define CERT_TRUST_INVALID_EXTENSION
Definition: wincrypt.h:990
#define szOID_ISSUER_ALT_NAME2
Definition: wincrypt.h:3344
#define CERT_TRUST_INVALID_BASIC_CONSTRAINTS
Definition: wincrypt.h:992
#define CERT_ALT_NAME_RFC822_NAME
Definition: wincrypt.h:355
#define CERT_ALT_NAME_OTHER_NAME
Definition: wincrypt.h:354
#define CERT_TRUST_HAS_EXACT_MATCH_ISSUER
Definition: wincrypt.h:1008
#define CERT_CRL_SIGN_KEY_USAGE
Definition: wincrypt.h:320
#define HCCE_LOCAL_MACHINE
Definition: wincrypt.h:3774
#define CERT_CASE_INSENSITIVE_IS_RDN_ATTRS_FLAG
Definition: wincrypt.h:2954
#define CRYPT_VERIFY_CERT_SIGN_ISSUER_CERT
Definition: wincrypt.h:3632
#define CERT_DIGITAL_SIGNATURE_KEY_USAGE
Definition: wincrypt.h:313
#define CERT_V1
Definition: wincrypt.h:2803
#define szOID_KEY_USAGE
Definition: wincrypt.h:3341
#define CERT_TRUST_IS_NOT_TIME_NESTED
Definition: wincrypt.h:983
#define CRYPT_VERIFY_CERT_SIGN_SUBJECT_CERT
Definition: wincrypt.h:3627
#define X509_ASN_ENCODING
Definition: wincrypt.h:2501
#define szOID_ANY_CERT_POLICY
Definition: wincrypt.h:3354
#define szOID_BASIC_CONSTRAINTS
Definition: wincrypt.h:3339
#define CERT_CHAIN_POLICY_AUTHENTICODE
Definition: wincrypt.h:1075
#define CRYPT_AIA_RETRIEVAL
Definition: wincrypt.h:1894
#define CERT_TRUST_IS_SELF_SIGNED
Definition: wincrypt.h:1011
#define CERT_CHAIN_REVOCATION_ACCUMULATIVE_TIMEOUT
Definition: wincrypt.h:1174
#define CRYPT_DECODE_ALLOC_FLAG
Definition: wincrypt.h:3612
#define CERT_STORE_PROV_MEMORY
Definition: wincrypt.h:2455
#define CERT_TRUST_IS_OFFLINE_REVOCATION
Definition: wincrypt.h:998
#define CERT_VERIFY_CACHE_ONLY_BASED_REVOCATION
Definition: wincrypt.h:932
#define CERT_TRUST_HAS_KEY_MATCH_ISSUER
Definition: wincrypt.h:1009
#define X509_AUTHORITY_KEY_ID
Definition: wincrypt.h:3526
#define CERT_ENCIPHER_ONLY_KEY_USAGE
Definition: wincrypt.h:321
#define CERT_SIMPLE_NAME_STR
Definition: wincrypt.h:3642
#define MICROSOFT_ROOT_CERT_CHAIN_POLICY_CHECK_APPLICATION_ROOT_FLAG
Definition: wincrypt.h:1113
#define CERT_TRUST_HAS_NOT_PERMITTED_NAME_CONSTRAINT
Definition: wincrypt.h:996
#define szOID_RSA_emailAddr
Definition: wincrypt.h:3188
#define NETSCAPE_SSL_CLIENT_AUTH_CERT_TYPE
Definition: wincrypt.h:3508
#define X509_CERT_POLICIES
Definition: wincrypt.h:3533
#define CERT_CA_SUBJECT_FLAG
Definition: wincrypt.h:387
#define AUTHTYPE_SERVER
Definition: wincrypt.h:1148
#define szOID_NETSCAPE_CERT_TYPE
Definition: wincrypt.h:3496
#define CERT_DECIPHER_ONLY_KEY_USAGE
Definition: wincrypt.h:323
#define CERT_CHAIN_POLICY_ALLOW_UNKNOWN_CA_FLAG
Definition: wincrypt.h:1092
#define NETSCAPE_SMIME_CERT_TYPE
Definition: wincrypt.h:3510
struct _CERT_CHAIN_CONTEXT CERT_CHAIN_CONTEXT
Definition: wincrypt.h:1046
#define CERT_CHAIN_POLICY_IGNORE_WRONG_USAGE_FLAG
Definition: wincrypt.h:1093
#define szOID_SUBJECT_ALT_NAME
Definition: wincrypt.h:3336
#define szOID_CERT_POLICIES
Definition: wincrypt.h:3353
#define CERT_SYSTEM_STORE_LOCAL_MACHINE
Definition: wincrypt.h:2530
#define CERT_CHAIN_POLICY_SSL
Definition: wincrypt.h:1077
#define CERT_ALT_NAME_DNS_NAME
Definition: wincrypt.h:356
#define X509_BITS
Definition: wincrypt.h:3544
#define szOID_ENHANCED_KEY_USAGE
Definition: wincrypt.h:3358
#define CERT_STORE_ADD_NEW
Definition: wincrypt.h:2651
#define CERT_TRUST_INVALID_NAME_CONSTRAINTS
Definition: wincrypt.h:993
#define szOID_SUBJECT_ALT_NAME2
Definition: wincrypt.h:3343
#define CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT
Definition: wincrypt.h:1171
#define CERT_HASH_PROP_ID
Definition: wincrypt.h:2835
#define CERT_VERIFY_REV_ACCUMULATIVE_TIMEOUT_FLAG
Definition: wincrypt.h:933
#define CERT_CHAIN_POLICY_IGNORE_NOT_SUPPORTED_CRITICAL_EXT_FLAG
Definition: wincrypt.h:1109
#define CERT_NAME_ISSUER_FLAG
Definition: wincrypt.h:3664
#define CERT_CONTEXT_REVOCATION_TYPE
Definition: wincrypt.h:930
#define CERT_TRUST_HAS_NAME_MATCH_ISSUER
Definition: wincrypt.h:1010
#define CERT_STORE_PROV_SYSTEM_W
Definition: wincrypt.h:2463
#define CERT_FIND_SUBJECT_NAME
Definition: wincrypt.h:3025
#define CERT_FIND_SHA1_HASH
Definition: wincrypt.h:3012
#define CERT_TRUST_HAS_EXCLUDED_NAME_CONSTRAINT
Definition: wincrypt.h:997
#define CRYPT_OID_VERIFY_CERTIFICATE_CHAIN_POLICY_FUNC
Definition: wincrypt.h:2675
#define CERT_TRUST_IS_PARTIAL_CHAIN
Definition: wincrypt.h:1003
#define CERT_CHAIN_REVOCATION_CHECK_CACHE_ONLY
Definition: wincrypt.h:1172
#define CERT_KEY_AGREEMENT_KEY_USAGE
Definition: wincrypt.h:317
#define CERT_SYSTEM_STORE_CURRENT_USER
Definition: wincrypt.h:2528
#define X509_ALTERNATE_NAME
Definition: wincrypt.h:3529
#define szOID_AUTHORITY_KEY_IDENTIFIER2
Definition: wincrypt.h:3356
#define szOID_COMMON_NAME
Definition: wincrypt.h:3290
#define PKCS_7_ASN_ENCODING
Definition: wincrypt.h:2503
#define NETSCAPE_SMIME_CA_CERT_TYPE
Definition: wincrypt.h:3513
#define X509_NAME_CONSTRAINTS
Definition: wincrypt.h:3577
#define CERT_TRUST_IS_NOT_VALID_FOR_USAGE
Definition: wincrypt.h:986
#define CERT_KEY_CERT_SIGN_KEY_USAGE
Definition: wincrypt.h:318
#define CERT_TRUST_IS_NOT_SIGNATURE_VALID
Definition: wincrypt.h:985
#define szOID_DOMAIN_COMPONENT
Definition: wincrypt.h:3361
#define CERT_DATA_ENCIPHERMENT_KEY_USAGE
Definition: wincrypt.h:316
#define CERT_TRUST_HAS_NOT_SUPPORTED_NAME_CONSTRAINT
Definition: wincrypt.h:994
struct _CERT_CHAIN_CONTEXT * PCERT_CHAIN_CONTEXT
Definition: wincrypt.h:1046
#define CERT_VERIFY_REV_CHAIN_FLAG
Definition: wincrypt.h:931
struct _CERT_BASIC_CONSTRAINTS2_INFO CERT_BASIC_CONSTRAINTS2_INFO
#define CERT_CHAIN_POLICY_IGNORE_NOT_TIME_VALID_FLAG
Definition: wincrypt.h:1082
#define CERT_ALT_NAME_REGISTERED_ID
Definition: wincrypt.h:362
#define X509_ENHANCED_KEY_USAGE
Definition: wincrypt.h:3555
#define CRYPT_CACHE_ONLY_RETRIEVAL
Definition: wincrypt.h:1883
#define CERT_TRUST_IS_UNTRUSTED_ROOT
Definition: wincrypt.h:987
#define CERT_TRUST_IS_NOT_TIME_VALID
Definition: wincrypt.h:982
#define szOID_ISSUER_ALT_NAME
Definition: wincrypt.h:3337
#define CERT_V2
Definition: wincrypt.h:2804
#define WINAPI
Definition: msvc.h:6
#define CRYPT_E_REVOKED
Definition: winerror.h:4433
#define CERT_E_REVOCATION_FAILURE
Definition: winerror.h:4644
#define CERT_E_CHAINING
Definition: winerror.h:4640
#define CERT_E_UNTRUSTEDROOT
Definition: winerror.h:4639
#define CERT_E_UNTRUSTEDTESTROOT
Definition: winerror.h:4643
#define CERT_E_REVOKED
Definition: winerror.h:4642
#define CRYPT_E_NO_REVOCATION_DLL
Definition: winerror.h:4434
#define CRYPT_E_NOT_IN_REVOCATION_DATABASE
Definition: winerror.h:4437
#define CERT_E_WRONG_USAGE
Definition: winerror.h:4646
#define TRUST_E_CERT_SIGNATURE
Definition: winerror.h:4588
#define CERT_E_CRITICAL
Definition: winerror.h:4635
#define TRUST_E_BASIC_CONSTRAINTS
Definition: winerror.h:4592
#define CRYPT_E_NO_REVOCATION_CHECK
Definition: winerror.h:4435
#define CERT_E_CN_NO_MATCH
Definition: winerror.h:4645
#define CRYPT_E_REVOCATION_OFFLINE
Definition: winerror.h:4436
#define CERT_E_EXPIRED
Definition: winerror.h:4631
#define ERROR_INVALID_DATA
Definition: winerror.h:238
#define SECURITY_FLAG_IGNORE_CERT_DATE_INVALID
Definition: winhttp.h:344
#define SECURITY_FLAG_IGNORE_UNKNOWN_CA
Definition: winhttp.h:343
#define SECURITY_FLAG_IGNORE_CERT_CN_INVALID
Definition: winhttp.h:345
#define SECURITY_FLAG_IGNORE_WRONG_USAGE
Definition: wininet.h:831
#define SECURITY_FLAG_IGNORE_REVOCATION
Definition: wininet.h:829
#define LOCALE_SSHORTDATE
Definition: winnls.h:70
unsigned char BYTE
Definition: xxhash.c:193