Example #1
0
 internal static extern bool CertGetCertificateChain(
     [In] SafeChainEngineHandle hChainEngine,
     [In] SafeCertContextHandle pCertContext,
     [In] ref FILETIME pTime,
     [In] SafeCertStoreHandle hAdditionalStore,
     [In] ref CERT_CHAIN_PARA pChainPara,
     [In] uint dwFlags,
     [In] IntPtr pvReserved,
     [In, Out] ref SafeX509ChainHandle ppChainContext);
Example #2
0
        /// <summary>
        /// Builds and validates a certificate chain, similar to <see cref="X509Chain.Build" />.
        /// </summary>
        /// <param name="certificate">The certificate to validate.</param>
        /// <param name="chainPolicy">The chain policy to apply.</param>
        /// <param name="chain">The resulting chain, whose <see cref="X509Chain.ChainStatus"/> and <see cref="X509Chain.ChainElements"/> properties are populated.</param>
        /// <returns>Whether the certificate is valid accoring to the given <paramref name="chainPolicy"/></returns>
        /// <exception cref="System.Security.Cryptography.CryptographicException">
        /// When any of the underlying Windows CryptoAPI calls fail.
        /// </exception>
        public unsafe bool BuildChain(X509Certificate2 certificate, X509ChainPolicy chainPolicy, out X509Chain chain)
        {
            SafeX509ChainHandle ppChainContext = SafeX509ChainHandle.InvalidHandle;

            SafeCertStoreHandle hCertStore = SafeCertStoreHandle.InvalidHandle;

            if (chainPolicy.ExtraStore != null && chainPolicy.ExtraStore.Count > 0)
            {
                hCertStore = ExportToMemoryStore(chainPolicy.ExtraStore);
            }

            NativeMethods.CERT_CHAIN_PARA chainPara = new NativeMethods.CERT_CHAIN_PARA();

            // Initialize the structure size.
            chainPara.cbSize = (uint)Marshal.SizeOf(chainPara);

            SafeLocalAllocHandle applicationPolicyHandle = SafeLocalAllocHandle.InvalidHandle;
            SafeLocalAllocHandle certificatePolicyHandle = SafeLocalAllocHandle.InvalidHandle;

            try
            {
                // Application policy
                if (chainPolicy.ApplicationPolicy != null && chainPolicy.ApplicationPolicy.Count > 0)
                {
                    chainPara.RequestedUsage.dwType = NativeMethods.USAGE_MATCH_TYPE_AND;
                    chainPara.RequestedUsage.Usage.cUsageIdentifier = (uint)chainPolicy.ApplicationPolicy.Count;
                    applicationPolicyHandle = CopyOidsToUnmanagedMemory(chainPolicy.ApplicationPolicy);
                    chainPara.RequestedUsage.Usage.rgpszUsageIdentifier = applicationPolicyHandle.DangerousGetHandle();
                }

                // Certificate policy
                if (chainPolicy.CertificatePolicy != null && chainPolicy.CertificatePolicy.Count > 0)
                {
                    chainPara.RequestedIssuancePolicy.dwType = NativeMethods.USAGE_MATCH_TYPE_AND;
                    chainPara.RequestedIssuancePolicy.Usage.cUsageIdentifier = (uint)chainPolicy.CertificatePolicy.Count;
                    certificatePolicyHandle = CopyOidsToUnmanagedMemory(chainPolicy.CertificatePolicy);
                    chainPara.RequestedIssuancePolicy.Usage.rgpszUsageIdentifier = certificatePolicyHandle.DangerousGetHandle();
                }

                chainPara.dwUrlRetrievalTimeout = (uint)Math.Floor(chainPolicy.UrlRetrievalTimeout.TotalMilliseconds);

                FILETIME ft = new FILETIME();
                *(long *)&ft = chainPolicy.VerificationTime.ToFileTime();

                uint flags = MapRevocationFlags(chainPolicy.RevocationMode, chainPolicy.RevocationFlag);

                using (SafeCertContextHandle certContextHandle = NativeMethods.CertDuplicateCertificateContext(certificate.Handle))
                {
                    // Build the chain.
                    if (!NativeMethods.CertGetCertificateChain(hChainEngine: this.safeChainEngineHandle,
                                                               pCertContext: certContextHandle,
                                                               pTime: ref ft,
                                                               hAdditionalStore: hCertStore,
                                                               pChainPara: ref chainPara,
                                                               dwFlags: flags,
                                                               pvReserved: IntPtr.Zero,
                                                               ppChainContext: ref ppChainContext))
                    {
                        throw new CryptographicException(Marshal.GetHRForLastWin32Error());
                    }

                    chain = new X509Chain(ppChainContext.DangerousGetHandle())
                    {
                        ChainPolicy = chainPolicy
                    };

                    // Verify the chain using the specified policy.
                    NativeMethods.CERT_CHAIN_POLICY_PARA   policyPara   = new NativeMethods.CERT_CHAIN_POLICY_PARA(Marshal.SizeOf(typeof(NativeMethods.CERT_CHAIN_POLICY_PARA)));
                    NativeMethods.CERT_CHAIN_POLICY_STATUS policyStatus = new NativeMethods.CERT_CHAIN_POLICY_STATUS(Marshal.SizeOf(typeof(NativeMethods.CERT_CHAIN_POLICY_STATUS)));

                    policyPara.dwFlags = (uint)chainPolicy.VerificationFlags;

                    if (!NativeMethods.CertVerifyCertificateChainPolicy(
                            pszPolicyOID: new IntPtr(NativeMethods.CERT_CHAIN_POLICY_BASE),
                            pChainContext: ppChainContext,
                            pPolicyPara: ref policyPara,
                            pPolicyStatus: ref policyStatus))
                    {
                        throw new CryptographicException(Marshal.GetLastWin32Error());
                    }

                    NativeMethods.SetLastError(policyStatus.dwError);
                    return(policyStatus.dwError == 0);
                }
            }
            finally
            {
                applicationPolicyHandle.Dispose();
                certificatePolicyHandle.Dispose();
            }
        }
Example #3
0
 internal static extern bool CertVerifyCertificateChainPolicy(
     [In] IntPtr pszPolicyOID,
     [In] SafeX509ChainHandle pChainContext,
     [In] ref CERT_CHAIN_POLICY_PARA pPolicyPara,
     [In, Out] ref CERT_CHAIN_POLICY_STATUS pPolicyStatus);