/// <summary> /// A less error-prone wrapper for CertEnumCertificatesInStore(). /// /// To begin the enumeration, set pCertContext to null. Each iteration replaces pCertContext with /// the next certificate in the iteration. The final call sets pCertContext to an invalid SafeCertStoreHandle /// and returns "false" to indicate the end of the store has been reached. /// </summary> public static bool CertEnumCertificatesInStore(SafeCertStoreHandle hCertStore, ref SafeCertContextHandle pCertContext) { unsafe { CERT_CONTEXT* pPrevCertContext = pCertContext == null ? null : pCertContext.Disconnect(); pCertContext = CertEnumCertificatesInStore(hCertStore, pPrevCertContext); return !pCertContext.IsInvalid; } }
public static unsafe extern bool CryptQueryObject( CertQueryObjectType dwObjectType, void* pvObject, ExpectedContentTypeFlags dwExpectedContentTypeFlags, ExpectedFormatTypeFlags dwExpectedFormatTypeFlags, int dwFlags, // reserved - always pass 0 IntPtr pdwMsgAndCertEncodingType, out ContentType pdwContentType, IntPtr pdwFormatType, out SafeCertStoreHandle phCertStore, IntPtr phMsg, IntPtr ppvContext );
private unsafe static byte[] ExportCertificatesToBlob(SafeCertStoreHandle safeCertStoreHandle, X509ContentType contentType, string password) { SafeCertContextHandle safeCertContextHandle = SafeCertContextHandle.InvalidHandle; uint dwSaveAs = CAPI.CERT_STORE_SAVE_AS_PKCS7; byte[] pbBlob = null; CAPI.CRYPTOAPI_BLOB DataBlob = new CAPI.CRYPTOAPI_BLOB(); SafeLocalAllocHandle pbEncoded = SafeLocalAllocHandle.InvalidHandle; switch(contentType) { case X509ContentType.Cert: safeCertContextHandle = CAPI.CertEnumCertificatesInStore(safeCertStoreHandle, safeCertContextHandle); if (safeCertContextHandle != null && !safeCertContextHandle.IsInvalid) { CAPI.CERT_CONTEXT pCertContext = *((CAPI.CERT_CONTEXT*) safeCertContextHandle.DangerousGetHandle()); pbBlob = new byte[pCertContext.cbCertEncoded]; Marshal.Copy(pCertContext.pbCertEncoded, pbBlob, 0, pbBlob.Length); } break; case X509ContentType.SerializedCert: safeCertContextHandle = CAPI.CertEnumCertificatesInStore(safeCertStoreHandle, safeCertContextHandle); uint cbEncoded = 0; if (safeCertContextHandle != null && !safeCertContextHandle.IsInvalid) { if (!CAPI.CertSerializeCertificateStoreElement(safeCertContextHandle, 0, pbEncoded, new IntPtr(&cbEncoded))) throw new CryptographicException(Marshal.GetLastWin32Error()); pbEncoded = CAPI.LocalAlloc(CAPI.LMEM_FIXED, new IntPtr(cbEncoded)); if (!CAPI.CertSerializeCertificateStoreElement(safeCertContextHandle, 0, pbEncoded, new IntPtr(&cbEncoded))) throw new CryptographicException(Marshal.GetLastWin32Error()); pbBlob = new byte[cbEncoded]; Marshal.Copy(pbEncoded.DangerousGetHandle(), pbBlob, 0, pbBlob.Length); } break; case X509ContentType.Pkcs12: if (!CAPI.PFXExportCertStore(safeCertStoreHandle, new IntPtr(&DataBlob), password, CAPI.EXPORT_PRIVATE_KEYS | CAPI.REPORT_NOT_ABLE_TO_EXPORT_PRIVATE_KEY)) throw new CryptographicException(Marshal.GetLastWin32Error()); pbEncoded = CAPI.LocalAlloc(CAPI.LMEM_FIXED, new IntPtr(DataBlob.cbData)); DataBlob.pbData = pbEncoded.DangerousGetHandle(); if (!CAPI.PFXExportCertStore(safeCertStoreHandle, new IntPtr(&DataBlob), password, CAPI.EXPORT_PRIVATE_KEYS | CAPI.REPORT_NOT_ABLE_TO_EXPORT_PRIVATE_KEY)) throw new CryptographicException(Marshal.GetLastWin32Error()); pbBlob = new byte[DataBlob.cbData]; Marshal.Copy(DataBlob.pbData, pbBlob, 0, pbBlob.Length); break; case X509ContentType.SerializedStore: // falling through case X509ContentType.Pkcs7: if (contentType == X509ContentType.SerializedStore) dwSaveAs = CAPI.CERT_STORE_SAVE_AS_STORE; // determine the required length if (!CAPI.CertSaveStore(safeCertStoreHandle, CAPI.X509_ASN_ENCODING | CAPI.PKCS_7_ASN_ENCODING, dwSaveAs, CAPI.CERT_STORE_SAVE_TO_MEMORY, new IntPtr(&DataBlob), 0)) throw new CryptographicException(Marshal.GetLastWin32Error()); pbEncoded = CAPI.LocalAlloc(CAPI.LMEM_FIXED, new IntPtr(DataBlob.cbData)); DataBlob.pbData = pbEncoded.DangerousGetHandle(); // now save the store to a memory blob if (!CAPI.CertSaveStore(safeCertStoreHandle, CAPI.X509_ASN_ENCODING | CAPI.PKCS_7_ASN_ENCODING, dwSaveAs, CAPI.CERT_STORE_SAVE_TO_MEMORY, new IntPtr(&DataBlob), 0)) throw new CryptographicException(Marshal.GetLastWin32Error()); pbBlob = new byte[DataBlob.cbData]; Marshal.Copy(DataBlob.pbData, pbBlob, 0, pbBlob.Length); break; default: throw new CryptographicException(SR.GetString(SR.Cryptography_X509_InvalidContentType)); } pbEncoded.Dispose(); safeCertContextHandle.Dispose(); return pbBlob; }
private static void FindByCert(SafeCertStoreHandle safeSourceStoreHandle, uint dwFindType, IntPtr pvFindPara, bool validOnly, FindProcDelegate pfnCertCallback1, FindProcDelegate pfnCertCallback2, object pvCallbackData1, object pvCallbackData2, SafeCertStoreHandle safeTargetStoreHandle) { int hr = CAPI.S_OK; SafeCertContextHandle pEnumContext = SafeCertContextHandle.InvalidHandle; pEnumContext = CAPI.CertFindCertificateInStore(safeSourceStoreHandle, CAPI.X509_ASN_ENCODING | CAPI.PKCS_7_ASN_ENCODING, 0, dwFindType, pvFindPara, pEnumContext); while (pEnumContext != null && !pEnumContext.IsInvalid) { if (pfnCertCallback1 != null) { hr = pfnCertCallback1(pEnumContext, pvCallbackData1); if (hr == CAPI.S_FALSE) { if (pfnCertCallback2 != null) hr = pfnCertCallback2(pEnumContext, pvCallbackData2); if (hr == CAPI.S_FALSE) // skip this certificate goto skip; } if (hr != CAPI.S_OK) break; } if (validOnly) { hr = X509Utils.VerifyCertificate(pEnumContext, null, null, X509RevocationMode.NoCheck, X509RevocationFlag.ExcludeRoot, DateTime.Now, new TimeSpan(0, 0, 0), // default null, new IntPtr(CAPI.CERT_CHAIN_POLICY_BASE), IntPtr.Zero); if (hr == CAPI.S_FALSE) // skip this certificate goto skip; if (hr != CAPI.S_OK) break; } // // We use CertAddCertificateLinkToStore to keep a link to the original store, so any property changes get // applied to the original store. This has a limit of 99 links per cert context however. // if (!CAPI.CertAddCertificateLinkToStore(safeTargetStoreHandle, pEnumContext, CAPI.CERT_STORE_ADD_ALWAYS, SafeCertContextHandle.InvalidHandle)) { hr = Marshal.GetHRForLastWin32Error(); break; } skip: // CertFindCertificateInStore always releases the context regardless of success // or failure so we don't need to manually release it GC.SuppressFinalize(pEnumContext); pEnumContext = CAPI.CertFindCertificateInStore(safeSourceStoreHandle, CAPI.X509_ASN_ENCODING | CAPI.PKCS_7_ASN_ENCODING, 0, dwFindType, pvFindPara, pEnumContext); } if (pEnumContext != null && !pEnumContext.IsInvalid) pEnumContext.Dispose(); if (hr != CAPI.S_FALSE && hr != CAPI.S_OK) throw new CryptographicException(hr); }
private static ICertificatePal FromBlobOrFile(byte[] rawData, string fileName, SafePasswordHandle password, X509KeyStorageFlags keyStorageFlags) { Debug.Assert(rawData != null || fileName != null); Debug.Assert(password != null); bool loadFromFile = (fileName != null); PfxCertStoreFlags pfxCertStoreFlags = MapKeyStorageFlags(keyStorageFlags); bool persistKeySet = (0 != (keyStorageFlags & X509KeyStorageFlags.PersistKeySet)); CertEncodingType msgAndCertEncodingType; ContentType contentType; FormatType formatType; SafeCertStoreHandle hCertStore = null; SafeCryptMsgHandle hCryptMsg = null; SafeCertContextHandle pCertContext = null; try { unsafe { fixed(byte *pRawData = rawData) { fixed(char *pFileName = fileName) { CRYPTOAPI_BLOB certBlob = new CRYPTOAPI_BLOB(loadFromFile ? 0 : rawData.Length, pRawData); CertQueryObjectType objectType = loadFromFile ? CertQueryObjectType.CERT_QUERY_OBJECT_FILE : CertQueryObjectType.CERT_QUERY_OBJECT_BLOB; void *pvObject = loadFromFile ? (void *)pFileName : (void *)&certBlob; bool success = Interop.crypt32.CryptQueryObject( objectType, pvObject, X509ExpectedContentTypeFlags, X509ExpectedFormatTypeFlags, 0, out msgAndCertEncodingType, out contentType, out formatType, out hCertStore, out hCryptMsg, out pCertContext ); if (!success) { int hr = Marshal.GetHRForLastWin32Error(); throw hr.ToCryptographicException(); } } } if (contentType == ContentType.CERT_QUERY_CONTENT_PKCS7_SIGNED || contentType == ContentType.CERT_QUERY_CONTENT_PKCS7_SIGNED_EMBED) { pCertContext = GetSignerInPKCS7Store(hCertStore, hCryptMsg); } else if (contentType == ContentType.CERT_QUERY_CONTENT_PFX) { if (loadFromFile) { rawData = File.ReadAllBytes(fileName); } pCertContext = FilterPFXStore(rawData, password, pfxCertStoreFlags); } CertificatePal pal = new CertificatePal(pCertContext, deleteKeyContainer: !persistKeySet); pCertContext = null; return(pal); } } finally { if (hCertStore != null) { hCertStore.Dispose(); } if (hCryptMsg != null) { hCryptMsg.Dispose(); } if (pCertContext != null) { pCertContext.Dispose(); } } }
public void Dispose() { SafeCertStoreHandle certStore = _certStore; _certStore = null; if (certStore != null) certStore.Dispose(); }
public static extern bool CertAddCertificateContextToStore(SafeCertStoreHandle hCertStore, SafeCertContextHandle pCertContext, CertStoreAddDisposition dwAddDisposition, IntPtr ppStoreContext);
internal static extern void _AddCertificateToStore(SafeCertStoreHandle safeCertStoreHandle, SafeCertContextHandle safeCertContext);
static SafeCertStoreHandle ExportToMemoryStore(X509Certificate2Collection collection, IntPtr pCertContext) { CAPI.CERT_CONTEXT certContext = (CAPI.CERT_CONTEXT)Marshal.PtrToStructure(pCertContext, typeof(CAPI.CERT_CONTEXT)); // No extra store nor intermediate certificates if ((collection == null || collection.Count <= 0) && certContext.hCertStore == IntPtr.Zero) { return(SafeCertStoreHandle.InvalidHandle); } // we always want to use CERT_STORE_ENUM_ARCHIVED_FLAG since we want to preserve the collection in this operation. // By default, Archived certificates will not be included. SafeCertStoreHandle certStoreHandle = CAPI.CertOpenStore( new IntPtr(CAPI.CERT_STORE_PROV_MEMORY), CAPI.X509_ASN_ENCODING | CAPI.PKCS_7_ASN_ENCODING, IntPtr.Zero, CAPI.CERT_STORE_ENUM_ARCHIVED_FLAG | CAPI.CERT_STORE_CREATE_NEW_FLAG, null); if (certStoreHandle == null || certStoreHandle.IsInvalid) { int error = Marshal.GetLastWin32Error(); throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CryptographicException(error)); } // // We use CertAddCertificateLinkToStore to keep a link to the original store, so any property changes get // applied to the original store. This has a limit of 99 links per cert context however. // // Add extra store if (collection != null && collection.Count > 0) { foreach (X509Certificate2 x509 in collection) { if (!CAPI.CertAddCertificateLinkToStore(certStoreHandle, x509.Handle, CAPI.CERT_STORE_ADD_ALWAYS, SafeCertContextHandle.InvalidHandle)) { int error = Marshal.GetLastWin32Error(); throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CryptographicException(error)); } } } // Add intermediates // The hCertStore needs to be acquired from an X509Certificate2 object // constructed using a fresh cert context handle. If we simply refer to the hCertStore // property of the certContext local variable directly, there is a risk that we are accessing // a closed store. This is because if the X509Certificate2(rawdata) constructor closes the store handle (hCertStore). // There is no way to know which constructor was used at this point. // using (SafeCertContextHandle safeCertContext = CAPI.CertCreateCertificateContext(certContext.dwCertEncodingType, certContext.pbCertEncoded, certContext.cbCertEncoded)) { // // Create an X509Certificate2 using the new cert context that dup's the provided certificate. // X509Certificate2 intermediatesCert = new X509Certificate2(safeCertContext.DangerousGetHandle()); // // Dereference the handle to this intermediate cert and use it to access the handle // of this certificate's cert store. Then, call CAPI.CertAddCertificateLinkToStore // on each cert in this store by wrapping this cert store handle with an X509Store // object. // CAPI.CERT_CONTEXT intermediatesCertContext = (CAPI.CERT_CONTEXT)Marshal.PtrToStructure(intermediatesCert.Handle, typeof(CAPI.CERT_CONTEXT)); if (intermediatesCertContext.hCertStore != IntPtr.Zero) { X509Certificate2Collection intermediates = null; X509Store store = new X509Store(intermediatesCertContext.hCertStore); try { intermediates = store.Certificates; foreach (X509Certificate2 x509 in intermediates) { if (!CAPI.CertAddCertificateLinkToStore(certStoreHandle, x509.Handle, CAPI.CERT_STORE_ADD_ALWAYS, SafeCertContextHandle.InvalidHandle)) { int error = Marshal.GetLastWin32Error(); throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CryptographicException(error)); } } } finally { SecurityUtils.ResetAllCertificates(intermediates); store.Close(); } } } return(certStoreHandle); }
/// <summary> /// A less error-prone wrapper for CertEnumCertificatesInStore(). /// /// To begin the enumeration, set pCertContext to null. Each iteration replaces pCertContext with /// the next certificate in the iteration. The final call sets pCertContext to an invalid SafeCertStoreHandle /// and returns "false" to indicate the the end of the store has been reached. /// </summary> public static unsafe bool CertFindCertificateInStore(SafeCertStoreHandle hCertStore, CertFindType dwFindType, void* pvFindPara, ref SafeCertContextHandle pCertContext) { CERT_CONTEXT* pPrevCertContext = pCertContext == null ? null : pCertContext.Disconnect(); pCertContext = CertFindCertificateInStore(hCertStore, CertEncodingType.All, CertFindFlags.None, dwFindType, pvFindPara, pPrevCertContext); return !pCertContext.IsInvalid; }
internal static extern IntPtr CertEnumCertificatesInStore(SafeCertStoreHandle hCertStore, IntPtr pPrevCertContext);
static unsafe void BuildChain(IntPtr hChainEngine, IntPtr pCertContext, X509Certificate2Collection extraStore, OidCollection applicationPolicy, OidCollection certificatePolicy, X509RevocationMode revocationMode, X509RevocationFlag revocationFlag, DateTime verificationTime, TimeSpan timeout, out SafeCertChainHandle ppChainContext) { SafeCertStoreHandle hCertStore = ExportToMemoryStore(extraStore, pCertContext); CAPI.CERT_CHAIN_PARA ChainPara = new CAPI.CERT_CHAIN_PARA(); ChainPara.cbSize = (uint)Marshal.SizeOf(typeof(CAPI.CERT_CHAIN_PARA)); // Application policy SafeHGlobalHandle applicationPolicyHandle = SafeHGlobalHandle.InvalidHandle; SafeHGlobalHandle certificatePolicyHandle = SafeHGlobalHandle.InvalidHandle; try { if (applicationPolicy != null && applicationPolicy.Count > 0) { ChainPara.RequestedUsage.dwType = CAPI.USAGE_MATCH_TYPE_AND; ChainPara.RequestedUsage.Usage.cUsageIdentifier = (uint)applicationPolicy.Count; applicationPolicyHandle = 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 = CopyOidsToUnmanagedMemory(certificatePolicy); ChainPara.RequestedIssuancePolicy.Usage.rgpszUsageIdentifier = certificatePolicyHandle.DangerousGetHandle(); } ChainPara.dwUrlRetrievalTimeout = (uint)timeout.Milliseconds; FILETIME ft = new FILETIME(); *((long *)&ft) = verificationTime.ToFileTime(); uint flags = MapRevocationFlags(revocationMode, revocationFlag); // Build the chain. if (!CAPI.CertGetCertificateChain(hChainEngine, pCertContext, ref ft, hCertStore, ref ChainPara, flags, IntPtr.Zero, out ppChainContext)) { int error = Marshal.GetLastWin32Error(); throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CryptographicException(error)); } } finally { if (applicationPolicyHandle != null) { applicationPolicyHandle.Dispose(); } if (certificatePolicyHandle != null) { certificatePolicyHandle.Dispose(); } hCertStore.Close(); } }
/// <summary> /// A less error-prone wrapper for CertEnumCertificatesInStore(). /// /// To begin the enumeration, set pCertContext to null. Each iteration replaces pCertContext with /// the next certificate in the iteration. The final call sets pCertContext to an invalid SafeCertStoreHandle /// and returns "false" to indicate the end of the store has been reached. /// </summary> public static unsafe bool CertFindCertificateInStore(SafeCertStoreHandle hCertStore, Interop.Crypt32.CertFindType dwFindType, void *pvFindPara, [NotNull] ref SafeCertContextHandle?pCertContext) { Interop.Crypt32.CERT_CONTEXT *pPrevCertContext = pCertContext == null ? null : pCertContext.Disconnect(); pCertContext = Interop.Crypt32.CertFindCertificateInStore(hCertStore, Interop.Crypt32.CertEncodingType.All, Interop.Crypt32.CertFindFlags.None, dwFindType, pvFindPara, pPrevCertContext); return(!pCertContext.IsInvalid); }
public void Open(OpenFlags openFlags) { DiagnosticUtility.DebugAssert(this.certStoreHandle.IsInvalid, ""); uint dwOpenFlags = MapX509StoreFlags(this.storeLocation, openFlags); SafeCertStoreHandle certStoreHandle = CAPI.CertOpenStore(new IntPtr(CAPI.CERT_STORE_PROV_SYSTEM), CAPI.X509_ASN_ENCODING | CAPI.PKCS_7_ASN_ENCODING, IntPtr.Zero, dwOpenFlags, this.storeName); if (certStoreHandle == null || certStoreHandle.IsInvalid) { int error = Marshal.GetLastWin32Error(); throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CryptographicException(error)); } this.certStoreHandle = certStoreHandle; }
private StorePal(SafeCertStoreHandle certStore) { _certStore = certStore; }
internal static extern void _OpenX509Store(uint storeType, uint flags, string storeName, ref SafeCertStoreHandle safeCertStoreHandle);
private static extern unsafe SafeCertContextHandle CertEnumCertificatesInStore(SafeCertStoreHandle hCertStore, CERT_CONTEXT *pPrevCertContext);
private static extern unsafe bool CertGetCertificateChain(IntPtr hChainEngine, SafeCertContextHandle pCertContext, FILETIME* pTime, SafeCertStoreHandle hStore, [In] ref CERT_CHAIN_PARA pChainPara, CertChainFlags dwFlags, IntPtr pvReserved, out SafeX509ChainHandle ppChainContext);
public static extern bool PFXExportCertStore(SafeCertStoreHandle hStore, [In, Out] ref CRYPTOAPI_BLOB pPFX, string szPassword, PFXExportFlags dwFlags);
public static extern bool CertControlStore(SafeCertStoreHandle hCertStore, CertControlStoreFlags dwFlags, CertControlStoreType dwControlType, IntPtr pvCtrlPara);
public static unsafe bool CertGetCertificateChain(ChainEngine hChainEngine, SafeCertContextHandle pCertContext, FILETIME *pTime, SafeCertStoreHandle hStore, [In] ref CERT_CHAIN_PARA pChainPara, CertChainFlags dwFlags, IntPtr pvReserved, out SafeX509ChainHandle ppChainContext) { return(CertGetCertificateChain((IntPtr)hChainEngine, pCertContext, pTime, hStore, ref pChainPara, dwFlags, pvReserved, out ppChainContext)); }
internal static X509Certificate2Collection GetCertificates(SafeCertStoreHandle safeCertStoreHandle) { X509Certificate2Collection collection = new X509Certificate2Collection(); IntPtr pEnumContext = CAPI.CertEnumCertificatesInStore(safeCertStoreHandle, IntPtr.Zero); while (pEnumContext != IntPtr.Zero) { X509Certificate2 certificate = new X509Certificate2(pEnumContext); collection.Add(certificate); pEnumContext = CAPI.CertEnumCertificatesInStore(safeCertStoreHandle, pEnumContext); } return collection; }
public static extern bool CertSaveStore(SafeCertStoreHandle hCertStore, CertEncodingType dwMsgAndCertEncodingType, CertStoreSaveAs dwSaveAs, CertStoreSaveTo dwSaveTo, ref CRYPTOAPI_BLOB pvSaveToPara, int dwFlags);
internal StorePal(SafeCertStoreHandle certStore) { _certStore = certStore; }
public X509Store (IntPtr storeHandle) { if (storeHandle == IntPtr.Zero) throw new ArgumentNullException("storeHandle"); m_safeCertStoreHandle = CAPI.CertDuplicateStore(storeHandle); if (m_safeCertStoreHandle == null || m_safeCertStoreHandle.IsInvalid) throw new CryptographicException(SR.GetString(SR.Cryptography_InvalidStoreHandle), "storeHandle"); }
internal static partial bool PFXExportCertStore(SafeCertStoreHandle hStore, ref DATA_BLOB pPFX, SafePasswordHandle szPassword, PFXExportFlags dwFlags);
public void Open(OpenFlags flags) { if (m_location != StoreLocation.CurrentUser && m_location != StoreLocation.LocalMachine) throw new ArgumentException(String.Format(CultureInfo.CurrentCulture, SR.GetString(SR.Arg_EnumIllegalVal), "m_location")); uint storeFlags = X509Utils.MapX509StoreFlags(m_location, flags); if (!m_safeCertStoreHandle.IsInvalid) // Free the current store handle m_safeCertStoreHandle.Dispose(); m_safeCertStoreHandle = CAPI.CertOpenStore(new IntPtr(CAPI.CERT_STORE_PROV_SYSTEM), CAPI.X509_ASN_ENCODING | CAPI.PKCS_7_ASN_ENCODING, IntPtr.Zero, storeFlags, m_storeName); if (m_safeCertStoreHandle == null || m_safeCertStoreHandle.IsInvalid) throw new CryptographicException(Marshal.GetLastWin32Error()); // // We want the store to auto-resync when requesting a snapshot so that // updates to the store will be taken into account. // CAPI.CertControlStore(m_safeCertStoreHandle, 0, CAPI.CERT_STORE_CTRL_AUTO_RESYNC, IntPtr.Zero); }
private static unsafe SafeCertStoreHandle SelectFromStore (SafeCertStoreHandle safeSourceStoreHandle, string title, string message, X509SelectionFlag selectionFlags, IntPtr hwndParent) { int dwErrorCode = CAPI.ERROR_SUCCESS; // First, create a memory store SafeCertStoreHandle safeCertStoreHandle = CAPI.CertOpenStore((IntPtr) CAPI.CERT_STORE_PROV_MEMORY, CAPI.X509_ASN_ENCODING | CAPI.PKCS_7_ASN_ENCODING, IntPtr.Zero, 0, null); if (safeCertStoreHandle == null || safeCertStoreHandle.IsInvalid) throw new CryptographicException(Marshal.GetLastWin32Error()); CAPI.CRYPTUI_SELECTCERTIFICATE_STRUCTW csc = new CAPI.CRYPTUI_SELECTCERTIFICATE_STRUCTW(); // Older versions of CRYPTUI do not check the size correctly, // so always force it to the oldest version of the structure. csc.dwSize = (uint) Marshal.OffsetOf(typeof(CAPI.CRYPTUI_SELECTCERTIFICATE_STRUCTW), "hSelectedCertStore"); 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 = CAPI.CryptUIDlgSelectCertificateW(csc); if (safeCertContextHandle != null && !safeCertContextHandle.IsInvalid) { // Single select, so add it to our hCertStore SafeCertContextHandle ppStoreContext = SafeCertContextHandle.InvalidHandle; if (!CAPI.CertAddCertificateContextToStore(safeCertStoreHandle, safeCertContextHandle, CAPI.CERT_STORE_ADD_NEWER_INHERIT_PROPERTIES, ppStoreContext)) dwErrorCode = Marshal.GetLastWin32Error(); } if (dwErrorCode != CAPI.ERROR_SUCCESS) throw new CryptographicException(Marshal.GetLastWin32Error()); return safeCertStoreHandle; }
private unsafe static SafeCertStoreHandle FindCertInStore(SafeCertStoreHandle safeSourceStoreHandle, X509FindType findType, Object findValue, bool validOnly) { if (findValue == null) throw new ArgumentNullException("findValue"); IntPtr pvFindPara = IntPtr.Zero; object pvCallbackData1 = null; object pvCallbackData2 = null; FindProcDelegate pfnCertCallback1 = null; FindProcDelegate pfnCertCallback2 = null; uint dwFindType = CAPI.CERT_FIND_ANY; string subject, issuer; CAPI.CRYPTOAPI_BLOB HashBlob = new CAPI.CRYPTOAPI_BLOB(); SafeLocalAllocHandle pb = SafeLocalAllocHandle.InvalidHandle; _FILETIME ft = new _FILETIME(); string oidValue = null; switch(findType) { case X509FindType.FindByThumbprint: if (findValue.GetType() != typeof(string)) throw new CryptographicException(SR.GetString(SR.Cryptography_X509_InvalidFindValue)); byte[] hex = X509Utils.DecodeHexString((string) findValue); pb = X509Utils.ByteToPtr(hex); HashBlob.pbData = pb.DangerousGetHandle(); HashBlob.cbData = (uint) hex.Length; dwFindType = CAPI.CERT_FIND_HASH; pvFindPara = new IntPtr(&HashBlob); break; case X509FindType.FindBySubjectName: if (findValue.GetType() != typeof(string)) throw new CryptographicException(SR.GetString(SR.Cryptography_X509_InvalidFindValue)); subject = (string) findValue; dwFindType = CAPI.CERT_FIND_SUBJECT_STR; pb = X509Utils.StringToUniPtr(subject); pvFindPara = pb.DangerousGetHandle(); break; case X509FindType.FindBySubjectDistinguishedName: if (findValue.GetType() != typeof(string)) throw new CryptographicException(SR.GetString(SR.Cryptography_X509_InvalidFindValue)); subject = (string) findValue; pfnCertCallback1 = new FindProcDelegate(FindSubjectDistinguishedNameCallback); pvCallbackData1 = subject; break; case X509FindType.FindByIssuerName: if (findValue.GetType() != typeof(string)) throw new CryptographicException(SR.GetString(SR.Cryptography_X509_InvalidFindValue)); issuer = (string) findValue; dwFindType = CAPI.CERT_FIND_ISSUER_STR; pb = X509Utils.StringToUniPtr(issuer); pvFindPara = pb.DangerousGetHandle(); break; case X509FindType.FindByIssuerDistinguishedName: if (findValue.GetType() != typeof(string)) throw new CryptographicException(SR.GetString(SR.Cryptography_X509_InvalidFindValue)); issuer = (string) findValue; pfnCertCallback1 = new FindProcDelegate(FindIssuerDistinguishedNameCallback); pvCallbackData1 = issuer; break; case X509FindType.FindBySerialNumber: if (findValue.GetType() != typeof(string)) throw new CryptographicException(SR.GetString(SR.Cryptography_X509_InvalidFindValue)); pfnCertCallback1 = new FindProcDelegate(FindSerialNumberCallback); pfnCertCallback2 = new FindProcDelegate(FindSerialNumberCallback); BigInt h = new BigInt(); h.FromHexadecimal((string) findValue); pvCallbackData1 = (byte[]) h.ToByteArray(); h.FromDecimal((string) findValue); pvCallbackData2 = (byte[]) h.ToByteArray(); break; case X509FindType.FindByTimeValid: if (findValue.GetType() != typeof(DateTime)) throw new CryptographicException(SR.GetString(SR.Cryptography_X509_InvalidFindValue)); *((long*) &ft) = ((DateTime) findValue).ToFileTime(); pfnCertCallback1 = new FindProcDelegate(FindTimeValidCallback); pvCallbackData1 = ft; break; case X509FindType.FindByTimeNotYetValid: if (findValue.GetType() != typeof(DateTime)) throw new CryptographicException(SR.GetString(SR.Cryptography_X509_InvalidFindValue)); *((long*) &ft) = ((DateTime) findValue).ToFileTime(); pfnCertCallback1 = new FindProcDelegate(FindTimeNotBeforeCallback); pvCallbackData1 = ft; break; case X509FindType.FindByTimeExpired: if (findValue.GetType() != typeof(DateTime)) throw new CryptographicException(SR.GetString(SR.Cryptography_X509_InvalidFindValue)); *((long*) &ft) = ((DateTime) findValue).ToFileTime(); pfnCertCallback1 = new FindProcDelegate(FindTimeNotAfterCallback); pvCallbackData1 = ft; break; case X509FindType.FindByTemplateName: if (findValue.GetType() != typeof(string)) throw new CryptographicException(SR.GetString(SR.Cryptography_X509_InvalidFindValue)); pvCallbackData1 = (string) findValue; pfnCertCallback1 = new FindProcDelegate(FindTemplateNameCallback); break; case X509FindType.FindByApplicationPolicy: if (findValue.GetType() != typeof(string)) throw new CryptographicException(SR.GetString(SR.Cryptography_X509_InvalidFindValue)); // If we were passed the friendly name, retrieve the value string. oidValue = X509Utils.FindOidInfoWithFallback(CAPI.CRYPT_OID_INFO_NAME_KEY, (string) findValue, OidGroup.Policy); if (oidValue == null) { oidValue = (string) findValue; X509Utils.ValidateOidValue(oidValue); } pvCallbackData1 = oidValue; pfnCertCallback1 = new FindProcDelegate(FindApplicationPolicyCallback); break; case X509FindType.FindByCertificatePolicy: if (findValue.GetType() != typeof(string)) throw new CryptographicException(SR.GetString(SR.Cryptography_X509_InvalidFindValue)); // If we were passed the friendly name, retrieve the value string. oidValue = X509Utils.FindOidInfoWithFallback(CAPI.CRYPT_OID_INFO_NAME_KEY, (string)findValue, OidGroup.Policy); if (oidValue == null) { oidValue = (string) findValue; X509Utils.ValidateOidValue(oidValue); } pvCallbackData1 = oidValue; pfnCertCallback1 = new FindProcDelegate(FindCertificatePolicyCallback); break; case X509FindType.FindByExtension: if (findValue.GetType() != typeof(string)) throw new CryptographicException(SR.GetString(SR.Cryptography_X509_InvalidFindValue)); // If we were passed the friendly name, retrieve the value string. oidValue = X509Utils.FindOidInfoWithFallback(CAPI.CRYPT_OID_INFO_NAME_KEY, (string)findValue, OidGroup.ExtensionOrAttribute); if (oidValue == null) { oidValue = (string) findValue; X509Utils.ValidateOidValue(oidValue); } pvCallbackData1 = oidValue; pfnCertCallback1 = new FindProcDelegate(FindExtensionCallback); break; case X509FindType.FindByKeyUsage: // The findValue object can be either a friendly name, a X509KeyUsageFlags enum or an integer. if (findValue.GetType() == typeof(string)) { CAPI.KEY_USAGE_STRUCT[] KeyUsages = new CAPI.KEY_USAGE_STRUCT[] { new CAPI.KEY_USAGE_STRUCT("DigitalSignature", CAPI.CERT_DIGITAL_SIGNATURE_KEY_USAGE), new CAPI.KEY_USAGE_STRUCT("NonRepudiation", CAPI.CERT_NON_REPUDIATION_KEY_USAGE), new CAPI.KEY_USAGE_STRUCT("KeyEncipherment", CAPI.CERT_KEY_ENCIPHERMENT_KEY_USAGE), new CAPI.KEY_USAGE_STRUCT("DataEncipherment", CAPI.CERT_DATA_ENCIPHERMENT_KEY_USAGE), new CAPI.KEY_USAGE_STRUCT("KeyAgreement", CAPI.CERT_KEY_AGREEMENT_KEY_USAGE), new CAPI.KEY_USAGE_STRUCT("KeyCertSign", CAPI.CERT_KEY_CERT_SIGN_KEY_USAGE), new CAPI.KEY_USAGE_STRUCT("CrlSign", CAPI.CERT_CRL_SIGN_KEY_USAGE), new CAPI.KEY_USAGE_STRUCT("EncipherOnly", CAPI.CERT_ENCIPHER_ONLY_KEY_USAGE), new CAPI.KEY_USAGE_STRUCT("DecipherOnly", CAPI.CERT_DECIPHER_ONLY_KEY_USAGE) }; for (uint index = 0; index < KeyUsages.Length; index++) { if (String.Compare(KeyUsages[index].pwszKeyUsage, (string) findValue, StringComparison.OrdinalIgnoreCase) == 0) { pvCallbackData1 = KeyUsages[index].dwKeyUsageBit; break; } } if (pvCallbackData1 == null) throw new CryptographicException(SR.GetString(SR.Cryptography_X509_InvalidFindType)); } else if (findValue.GetType() == typeof(X509KeyUsageFlags)) { pvCallbackData1 = findValue; } else if (findValue.GetType() == typeof(uint) || findValue.GetType() == typeof(int)) { // We got the actual DWORD pvCallbackData1 = findValue; } else throw new CryptographicException(SR.GetString(SR.Cryptography_X509_InvalidFindType)); pfnCertCallback1 = new FindProcDelegate(FindKeyUsageCallback); break; case X509FindType.FindBySubjectKeyIdentifier: if (findValue.GetType() != typeof(string)) throw new CryptographicException(SR.GetString(SR.Cryptography_X509_InvalidFindValue)); pvCallbackData1 = (byte[]) X509Utils.DecodeHexString((string) findValue); pfnCertCallback1 = new FindProcDelegate(FindSubjectKeyIdentifierCallback); break; default: throw new CryptographicException(SR.GetString(SR.Cryptography_X509_InvalidFindType)); } // First, create a memory store SafeCertStoreHandle safeTargetStoreHandle = CAPI.CertOpenStore(new IntPtr(CAPI.CERT_STORE_PROV_MEMORY), CAPI.X509_ASN_ENCODING | CAPI.PKCS_7_ASN_ENCODING, IntPtr.Zero, CAPI.CERT_STORE_ENUM_ARCHIVED_FLAG | CAPI.CERT_STORE_CREATE_NEW_FLAG, null); if (safeTargetStoreHandle == null || safeTargetStoreHandle.IsInvalid) throw new CryptographicException(Marshal.GetLastWin32Error()); // FindByCert will throw an exception in case of failures. FindByCert(safeSourceStoreHandle, dwFindType, pvFindPara, validOnly, pfnCertCallback1, pfnCertCallback2, pvCallbackData1, pvCallbackData2, safeTargetStoreHandle); pb.Dispose(); return safeTargetStoreHandle; }
public static extern bool PFXExportCertStore(SafeCertStoreHandle hStore, [In, Out] ref CRYPTOAPI_BLOB pPFX, String szPassword, PFXExportFlags dwFlags);
// // private static methods // private static void RemoveCertificateFromStore(SafeCertStoreHandle safeCertStoreHandle, SafeCertContextHandle safeCertContext) { if (safeCertContext == null || safeCertContext.IsInvalid) return; if (safeCertStoreHandle == null || safeCertStoreHandle.IsInvalid || safeCertStoreHandle.IsClosed) throw new CryptographicException(SR.GetString(SR.Cryptography_X509_StoreNotOpen)); // Find the certificate in the store. SafeCertContextHandle safeCertContext2 = CAPI.CertFindCertificateInStore(safeCertStoreHandle, CAPI.X509_ASN_ENCODING | CAPI.PKCS_7_ASN_ENCODING, 0, CAPI.CERT_FIND_EXISTING, safeCertContext.DangerousGetHandle(), SafeCertContextHandle.InvalidHandle); // The certificate is not present in the store, simply return. if (safeCertContext2 == null || safeCertContext2.IsInvalid) return; // CertDeleteCertificateFromStore always releases the context regardless of success // or failure so we don't need to manually release it GC.SuppressFinalize(safeCertContext2); // Remove from the store. if (!CAPI.CertDeleteCertificateFromStore(safeCertContext2)) throw new CryptographicException(Marshal.GetLastWin32Error()); }
internal static extern byte[] _ExportCertificatesToBlob(SafeCertStoreHandle safeCertStoreHandle, X509ContentType contentType, IntPtr password);
private static extern unsafe SafeCertContextHandle CertEnumCertificatesInStore(SafeCertStoreHandle hCertStore, CERT_CONTEXT* pPrevCertContext);
internal static X509Certificate2Collection GetCertificates(SafeCertStoreHandle safeCertStoreHandle) { X509Certificate2Collection certificate2Collection = new X509Certificate2Collection(); for (IntPtr index = CAPI.CertEnumCertificatesInStore(safeCertStoreHandle, IntPtr.Zero); index != IntPtr.Zero; index = CAPI.CertEnumCertificatesInStore(safeCertStoreHandle, index)) { X509Certificate2 certificate = new X509Certificate2(index); certificate2Collection.Add(certificate); } return certificate2Collection; }
public static unsafe bool CertGetCertificateChain(ChainEngine hChainEngine, SafeCertContextHandle pCertContext, FILETIME* pTime, SafeCertStoreHandle hStore, [In] ref CERT_CHAIN_PARA pChainPara, CertChainFlags dwFlags, IntPtr pvReserved, out SafeX509ChainHandle ppChainContext) { return CertGetCertificateChain((IntPtr)hChainEngine, pCertContext, pTime, hStore, ref pChainPara, dwFlags, pvReserved, out ppChainContext); }
private static unsafe partial CERT_CONTEXT *CertEnumCertificatesInStore(SafeCertStoreHandle hCertStore, CERT_CONTEXT *pPrevCertContext);
public static unsafe partial bool CertGetCertificateChain(IntPtr hChainEngine, SafeCertContextHandle pCertContext, FILETIME *pTime, SafeCertStoreHandle hStore, ref CERT_CHAIN_PARA pChainPara, CertChainFlags dwFlags, IntPtr pvReserved, out SafeX509ChainHandle ppChainContext);
private static unsafe extern SafeCertContextHandle CertFindCertificateInStore(SafeCertStoreHandle hCertStore, CertEncodingType dwCertEncodingType, CertFindFlags dwFindFlags, CertFindType dwFindType, void* pvFindPara, CERT_CONTEXT* pPrevCertContext);
public static partial bool CertSaveStore(SafeCertStoreHandle hCertStore, CertEncodingType dwMsgAndCertEncodingType, CertStoreSaveAs dwSaveAs, CertStoreSaveTo dwSaveTo, ref DATA_BLOB pvSaveToPara, int dwFlags);
private static unsafe partial SafeCertContextHandle CertFindCertificateInStore(SafeCertStoreHandle hCertStore, CertEncodingType dwCertEncodingType, CertFindFlags dwFindFlags, CertFindType dwFindType, void *pvFindPara, CERT_CONTEXT *pPrevCertContext);
public static partial bool CertControlStore(SafeCertStoreHandle hCertStore, CertControlStoreFlags dwFlags, CertControlStoreType dwControlType, IntPtr pvCtrlPara);
public static partial bool CertAddCertificateLinkToStore(SafeCertStoreHandle hCertStore, SafeCertContextHandle pCertContext, CertStoreAddDisposition dwAddDisposition, IntPtr ppStoreContext);
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 bool CertAddCertificateLinkToStore(SafeCertStoreHandle hCertStore, SafeCertContextHandle pCertContext, uint dwAddDisposition, [In, Out] SafeCertContextHandle ppStoreContext);