Important: |
---|
This is retired content. This content is outdated and is no longer being maintained. It is provided as a courtesy for individuals who are still using these technologies. This content may contain URLs that were valid when originally published, but now link to sites or pages that no longer exist. |
This function builds a certificate chain context starting from an end certificate and going back, if possible, to a trusted root certificate. This is the primary API used to verify a certificate against a root store.
Syntax
BOOL WINAPI CertGetCertificateChain( HCERTCHAINENGINE hChainEngine, PCCERT_CONTEXT pCertContext, LPFILETIME pTime, HCERTSTORE hAdditionalStore, PCERT_CHAIN_PARA pChainPara, DWORD dwFlags, LPVOID pvReserved, PCCERT_CHAIN_CONTEXT* ppChainContext ); |
Parameters
- hChainEngine
-
[in] Optional. Handle to the chain engine, which includes name space and cache, to be used. If the value of this parameter is NULL, the default chain engine, HHCE_CURRENT_USER, is used. This parameter can be set to HCCE_LOCAL_MACHINE.
- pCertContext
-
[in] Pointer to the CERT_CONTEXTstructure of the end certificate, the certificate for which a chain is being built. This certificate context will be the element with zero index in the first simple chain.
- pTime
-
[in] Optional. Pointer to a FILETIME variable indicating the time for which the chain is to be validated. Note that the time does not affect root store checking. The current system time is used if NULL is passed to this parameter. Trust in a particular certificate being a trusted root is based on the current state of the root store and not the state of the root store at a time passed in by this parameter.
- hAdditionalStore
-
[in] Handle to any additional store to search for supporting certificates. This parameter can be NULL if no additional store is to be searched.
- pChainPara
-
[in] Pointer to a CERT_CHAIN_PARAstructure that includes chain-building parameters.
- dwFlags
-
[in] Flag values indicating special processing. The CERT_CHAIN_CACHE_END_CERT flag can be used. When this flag is set, the end certificate is cached, which might speed up the chain-building process. By default, the end certificate is not cached and it would need to be verified each time a chain is built for it.
- pvReserved
-
[in] Reserved parameter that must be set to NULL.
- ppChainContext
-
[in] Pointer to a pointer to the chain context created.
Return Value
If the function succeeds, the return value is nonzero, or TRUE.
If the function fails, the return value is zero, or FALSE. For extended error information, call the GetLastErrorfunction.
Remarks
When an application requests a certificate chain, the structure returned is in the form of a CERT_CHAIN_CONTEXTstructure. This context contains an array of CERT_SIMPLE_CHAINstructures where each simple chain goes from an end certificate to a self-signed certificate. Because Windows Embedded CE does not support certificate trust lists, there is only one CERT_SIMPLE_CHAIN in the array. Each simple chain contains the chain of certificates, summary trust information about the chain, and trust information about each certificate element in the chain.
The desktop operating system supports the following dwFlagsflags that Windows Embedded CE does not support:
CERT_CHAIN_REVOCATION_CHECK_END_CERT
CERT_CHAIN_REVOCATION_CHECK_CHAIN
CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT
CERT_CHAIN_REVOCATION_CHECK_CACHE_ONLY.
Example Code
This example code demonstrates the use of CertGetCertificateChainto verify a certificate. In addition, it also shows how to verify that the DNS name in the certificate matches the name of the server that is being connected to.
Copy Code | |
---|---|
#include <wincrypt.h> DWORD VerifyServerCertificate( PCCERT_CONTEXT pCertContextServer, PWSTR pwszServerName) { PCCERT_CHAIN_CONTEXT pChainContext = NULL; CERT_CHAIN_PARA ChainPara; PCERT_SIMPLE_CHAIN pSimpleChain; PCCERT_CONTEXT pRootCert; WCHAR* pwszName = NULL; DWORD dwErr = NO_ERROR; DWORD cchName; DWORD dwTrustErrorMask = ~(CERT_TRUST_IS_NOT_TIME_NESTED|CERT_TRUST_REVOCATION_STATUS_UNKNOWN); ZeroMemory(&ChainPara, sizeof(ChainPara)); ChainPara.cbSize = sizeof(ChainPara); if(!CertGetCertificateChain( NULL, pCertContextServer, NULL, pCertContextServer->hCertStore, &ChainPara, 0, NULL, &pChainContext)) { dwErr = GetLastError(); EapTlsTrace(TEXT("CertGetCertificateChain failed and returned 0x%x"), dwErr); pChainContext = NULL; goto LDone; } pSimpleChain = pChainContext->rgpChain[0]; dwTrustErrorMask &= pSimpleChain->TrustStatus.dwErrorStatus; if (dwTrustErrorMask) { if (dwTrustErrorMask & (CERT_TRUST_IS_PARTIAL_CHAIN | CERT_TRUST_IS_UNTRUSTED_ROOT)) dwErr = SEC_E_UNTRUSTED_ROOT; else if (dwTrustErrorMask & (CERT_TRUST_IS_NOT_TIME_VALID)) dwErr = SEC_E_CERT_EXPIRED; else dwErr = SEC_E_CERT_UNKNOWN; goto LDone; } // Compare the DNS name in the certificate with the server. dwErr = SEC_E_CERT_UNKNOWN; // Could be a better error. // Get the DNS name from the certificate. pwszName = NULL; cchName = CertGetNameStringW(pCertContextServer, CERT_NAME_DNS_TYPE, 0, NULL, NULL, 0); if (cchName > 1) { pwszName = LocalAlloc(0, sizeof(WCHAR)*cchName); if (pwszName) { cchName = CertGetNameStringW(pCertContextServer, CERT_NAME_DNS_TYPE, 0, NULL, pwszName, cchName); if (cchName > 1 && wcsicmp(pwszServerName, pwszName) == 0) dwErr = ERROR_SUCCESS; } } LDone: if (pChainContext) { CertFreeCertificateChain(pChainContext); } LocalFree(pwszName); return(dwErr); } |
Requirements
Header | wincrypt.h |
Library | crypt32.lib |
Windows Embedded CE | Windows CE 3.0 and later |
Windows Mobile | Windows Mobile Version 5.0 and later |