internal static extern void _OpenX509Store(uint storeType, uint flags, string storeName, ref SafeCertStoreHandle safeCertStoreHandle);
internal static extern void _AddCertificateToStore(SafeCertStoreHandle safeCertStoreHandle, SafeCertContextHandle safeCertContext);
internal static extern byte[] _ExportCertificatesToBlob(SafeCertStoreHandle safeCertStoreHandle, X509ContentType contentType, IntPtr password);
internal StorePal(SafeCertStoreHandle certStore) { _certStore = certStore; }
private static SafeCertContextHandle GetSignerInPKCS7Store(SafeCertStoreHandle hCertStore, SafeCryptMsgHandle hCryptMsg) { // make sure that there is at least one signer of the certificate store int dwSigners; int cbSigners = sizeof(int); if (!Interop.crypt32.CryptMsgGetParam(hCryptMsg, CryptMessageParameterType.CMSG_SIGNER_COUNT_PARAM, 0, out dwSigners, ref cbSigners)) throw Marshal.GetHRForLastWin32Error().ToCryptographicException();; if (dwSigners == 0) throw ErrorCode.CRYPT_E_SIGNER_NOT_FOUND.ToCryptographicException(); // get the first signer from the store, and use that as the loaded certificate int cbData = 0; if (!Interop.crypt32.CryptMsgGetParam(hCryptMsg, CryptMessageParameterType.CMSG_SIGNER_INFO_PARAM, 0, null, ref cbData)) throw Marshal.GetHRForLastWin32Error().ToCryptographicException();; byte[] cmsgSignerBytes = new byte[cbData]; if (!Interop.crypt32.CryptMsgGetParam(hCryptMsg, CryptMessageParameterType.CMSG_SIGNER_INFO_PARAM, 0, cmsgSignerBytes, ref cbData)) throw Marshal.GetHRForLastWin32Error().ToCryptographicException();; CERT_INFO certInfo = default(CERT_INFO); unsafe { fixed (byte* pCmsgSignerBytes = cmsgSignerBytes) { CMSG_SIGNER_INFO_Partial* pCmsgSignerInfo = (CMSG_SIGNER_INFO_Partial*)pCmsgSignerBytes; certInfo.Issuer.cbData = pCmsgSignerInfo->Issuer.cbData; certInfo.Issuer.pbData = pCmsgSignerInfo->Issuer.pbData; certInfo.SerialNumber.cbData = pCmsgSignerInfo->SerialNumber.cbData; certInfo.SerialNumber.pbData = pCmsgSignerInfo->SerialNumber.pbData; } SafeCertContextHandle pCertContext = null; if (!Interop.crypt32.CertFindCertificateInStore(hCertStore, CertFindType.CERT_FIND_SUBJECT_CERT, &certInfo, ref pCertContext)) throw Marshal.GetHRForLastWin32Error().ToCryptographicException();; return pCertContext; } }
internal static extern void _OpenX509Store(uint storeType, uint flags, string storeName, ref SafeCertStoreHandle safeCertStoreHandle);
protected override bool ReleaseHandle() { SafeCertStoreHandle._FreeCertStoreContext(this.handle); return(true); }
internal static extern void _AddCertificateToStore(SafeCertStoreHandle safeCertStoreHandle, SafeCertContextHandle safeCertContext);
internal static extern byte[] _ExportCertificatesToBlob(SafeCertStoreHandle safeCertStoreHandle, X509ContentType contentType, IntPtr password);
private static unsafe SafeCertStoreHandle SelectFromStore(SafeCertStoreHandle safeSourceStoreHandle, string?title, string?message, X509SelectionFlag selectionFlags, IntPtr hwndParent) { int dwErrorCode = ERROR_SUCCESS; SafeCertStoreHandle safeCertStoreHandle = Interop.Crypt32.CertOpenStore( (IntPtr)Interop.Crypt32.CERT_STORE_PROV_MEMORY, Interop.Crypt32.X509_ASN_ENCODING | Interop.Crypt32.PKCS_7_ASN_ENCODING, IntPtr.Zero, 0, IntPtr.Zero); if (safeCertStoreHandle == null || safeCertStoreHandle.IsInvalid) { Exception e = new CryptographicException(Marshal.GetLastWin32Error()); safeCertStoreHandle?.Dispose(); throw e; } Interop.CryptUI.CRYPTUI_SELECTCERTIFICATE_STRUCTW csc = default; // Older versions of CRYPTUI do not check the size correctly, // so always force it to the oldest version of the structure. #if NET7_0_OR_GREATER // Declare a local for Native to enable us to get the managed byte offset // without having a null check cause a failure. Interop.CryptUI.CRYPTUI_SELECTCERTIFICATE_STRUCTW.Marshaller.Native native; Unsafe.SkipInit(out native); csc.dwSize = (uint)Unsafe.ByteOffset(ref Unsafe.As <Interop.CryptUI.CRYPTUI_SELECTCERTIFICATE_STRUCTW.Marshaller.Native, byte>(ref native), ref Unsafe.As <IntPtr, byte>(ref native.hSelectedCertStore)); #else csc.dwSize = (uint)Marshal.OffsetOf(typeof(Interop.CryptUI.CRYPTUI_SELECTCERTIFICATE_STRUCTW), "hSelectedCertStore"); #endif csc.hwndParent = hwndParent; csc.dwFlags = (uint)selectionFlags; csc.szTitle = title; csc.dwDontUseColumn = 0; csc.szDisplayString = message; csc.pFilterCallback = IntPtr.Zero; csc.pDisplayCallback = IntPtr.Zero; csc.pvCallbackData = IntPtr.Zero; csc.cDisplayStores = 1; IntPtr hSourceCertStore = safeSourceStoreHandle.DangerousGetHandle(); csc.rghDisplayStores = new IntPtr(&hSourceCertStore); csc.cStores = 0; csc.rghStores = IntPtr.Zero; csc.cPropSheetPages = 0; csc.rgPropSheetPages = IntPtr.Zero; csc.hSelectedCertStore = safeCertStoreHandle.DangerousGetHandle(); SafeCertContextHandle safeCertContextHandle = Interop.CryptUI.CryptUIDlgSelectCertificateW(ref csc); if (safeCertContextHandle != null && !safeCertContextHandle.IsInvalid) { // Single select, so add it to our hCertStore SafeCertContextHandle ppStoreContext = SafeCertContextHandle.InvalidHandle; if (!Interop.Crypt32.CertAddCertificateLinkToStore(safeCertStoreHandle, safeCertContextHandle, Interop.Crypt32.CERT_STORE_ADD_ALWAYS, ppStoreContext)) { dwErrorCode = Marshal.GetLastWin32Error(); } } if (dwErrorCode != ERROR_SUCCESS) { safeCertContextHandle?.Dispose(); throw new CryptographicException(dwErrorCode); } return(safeCertStoreHandle); }
internal static unsafe int BuildChain(IntPtr hChainEngine, SafeCertContextHandle pCertContext, X509Certificate2Collection extraStore, OidCollection applicationPolicy, OidCollection certificatePolicy, X509RevocationMode revocationMode, X509RevocationFlag revocationFlag, DateTime verificationTime, TimeSpan timeout, ref SafeX509ChainHandle ppChainContext) { if (pCertContext == null || pCertContext.IsInvalid) { throw new ArgumentException(SR.GetString(SR.Cryptography_InvalidContextHandle), "pCertContext"); } SafeCertStoreHandle hCertStore = SafeCertStoreHandle.InvalidHandle; if (extraStore != null && extraStore.Count > 0) { hCertStore = X509Utils.ExportToMemoryStore(extraStore); } CAPI.CERT_CHAIN_PARA ChainPara = new CAPI.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 (applicationPolicy != null && applicationPolicy.Count > 0) { ChainPara.RequestedUsage.dwType = CAPI.USAGE_MATCH_TYPE_AND; ChainPara.RequestedUsage.Usage.cUsageIdentifier = (uint)applicationPolicy.Count; applicationPolicyHandle = X509Utils.CopyOidsToUnmanagedMemory(applicationPolicy); ChainPara.RequestedUsage.Usage.rgpszUsageIdentifier = applicationPolicyHandle.DangerousGetHandle(); } // Certificate policy if (certificatePolicy != null && certificatePolicy.Count > 0) { ChainPara.RequestedIssuancePolicy.dwType = CAPI.USAGE_MATCH_TYPE_AND; ChainPara.RequestedIssuancePolicy.Usage.cUsageIdentifier = (uint)certificatePolicy.Count; certificatePolicyHandle = X509Utils.CopyOidsToUnmanagedMemory(certificatePolicy); ChainPara.RequestedIssuancePolicy.Usage.rgpszUsageIdentifier = certificatePolicyHandle.DangerousGetHandle(); } ChainPara.dwUrlRetrievalTimeout = (uint)Math.Floor(timeout.TotalMilliseconds); _FILETIME ft = new _FILETIME(); *((long *)&ft) = verificationTime.ToFileTime(); uint flags = X509Utils.MapRevocationFlags(revocationMode, revocationFlag); // Build the chain. if (!CAPI.CertGetCertificateChain(hChainEngine, pCertContext, ref ft, hCertStore, ref ChainPara, flags, IntPtr.Zero, ref ppChainContext)) { return(Marshal.GetHRForLastWin32Error()); } } finally { applicationPolicyHandle.Dispose(); certificatePolicyHandle.Dispose(); } return(CAPI.S_OK); }
/// <summary> /// Does not throw on error. Returns null ChainPal instead. /// </summary> internal static partial IChainPal?BuildChain( bool useMachineContext, ICertificatePal cert, X509Certificate2Collection?extraStore, OidCollection?applicationPolicy, OidCollection?certificatePolicy, X509RevocationMode revocationMode, X509RevocationFlag revocationFlag, X509Certificate2Collection?customTrustStore, X509ChainTrustMode trustMode, DateTime verificationTime, TimeSpan timeout, bool disableAia) { CertificatePal certificatePal = (CertificatePal)cert; unsafe { using (SafeChainEngineHandle storeHandle = GetChainEngine(trustMode, customTrustStore, useMachineContext)) using (SafeCertStoreHandle extraStoreHandle = ConvertStoreToSafeHandle(extraStore)) { Interop.Crypt32.CERT_CHAIN_PARA chainPara = default; chainPara.cbSize = Marshal.SizeOf <Interop.Crypt32.CERT_CHAIN_PARA>(); int applicationPolicyCount; using (SafeHandle applicationPolicyOids = applicationPolicy !.ToLpstrArray(out applicationPolicyCount)) { if (!applicationPolicyOids.IsInvalid) { chainPara.RequestedUsage.dwType = Interop.Crypt32.CertUsageMatchType.USAGE_MATCH_TYPE_AND; chainPara.RequestedUsage.Usage.cUsageIdentifier = applicationPolicyCount; chainPara.RequestedUsage.Usage.rgpszUsageIdentifier = applicationPolicyOids.DangerousGetHandle(); } int certificatePolicyCount; using (SafeHandle certificatePolicyOids = certificatePolicy !.ToLpstrArray(out certificatePolicyCount)) { if (!certificatePolicyOids.IsInvalid) { chainPara.RequestedIssuancePolicy.dwType = Interop.Crypt32.CertUsageMatchType.USAGE_MATCH_TYPE_AND; chainPara.RequestedIssuancePolicy.Usage.cUsageIdentifier = certificatePolicyCount; chainPara.RequestedIssuancePolicy.Usage.rgpszUsageIdentifier = certificatePolicyOids.DangerousGetHandle(); } chainPara.dwUrlRetrievalTimeout = (int)Math.Floor(timeout.TotalMilliseconds); Interop.Crypt32.FILETIME ft = Interop.Crypt32.FILETIME.FromDateTime(verificationTime); Interop.Crypt32.CertChainFlags flags = MapRevocationFlags(revocationMode, revocationFlag, disableAia); SafeX509ChainHandle chain; using (SafeCertContextHandle certContext = certificatePal.GetCertContext()) { if (!Interop.Crypt32.CertGetCertificateChain(storeHandle.DangerousGetHandle(), certContext, &ft, extraStoreHandle, ref chainPara, flags, IntPtr.Zero, out chain)) { chain.Dispose(); return(null); } } return(new ChainPal(chain)); } } } } }
internal StorePal(SafeCertStoreHandle certStore) { _certStore = certStore; }
[System.Security.SecurityCritical] // auto-generated private static void OpenX509Store(uint storeType, uint flags, string storeName, SafeCertStoreHandle safeCertStoreHandle) { _OpenX509Store(storeType, flags, storeName, ref safeCertStoreHandle); if (!safeCertStoreHandle.IsInvalid) { GC.ReRegisterForFinalize(safeCertStoreHandle); } }