public void Dispose() { SafeCertContextHandle certContext = _certContext; _certContext = null !; if (certContext != null && !certContext.IsInvalid) { certContext.Dispose(); } }
internal static partial ICertificatePal FromHandle(IntPtr handle) { if (handle == IntPtr.Zero) { throw new ArgumentException(SR.Arg_InvalidHandle, nameof(handle)); } SafeCertContextHandle safeCertContextHandle = Interop.Crypt32.CertDuplicateCertificateContext(handle); if (safeCertContextHandle.IsInvalid) { Exception e = ErrorCode.HRESULT_INVALID_HANDLE.ToCryptographicException(); safeCertContextHandle.Dispose(); throw e; } int cbData = 0; bool deleteKeyContainer = Interop.Crypt32.CertGetCertificateContextProperty(safeCertContextHandle, Interop.Crypt32.CertContextPropId.CERT_CLR_DELETE_KEY_PROP_ID, out Interop.Crypt32.DATA_BLOB _, ref cbData); return(new CertificatePal(safeCertContextHandle, deleteKeyContainer)); }
#pragma warning restore 618 public virtual void Reset() { m_subjectName = null; m_issuerName = null; m_serialNumber = null; m_publicKeyParameters = null; m_publicKeyValue = null; m_publicKeyOid = null; m_rawData = null; m_thumbprint = null; m_notBefore = DateTime.MinValue; m_notAfter = DateTime.MinValue; if (!m_safeCertContext.IsInvalid) { // Free the current certificate handle if (!m_certContextCloned) { m_safeCertContext.Dispose(); } m_safeCertContext = SafeCertContextHandle.InvalidHandle; } m_certContextCloned = false; }
private static SafeCertContextHandle FilterPFXStore( ReadOnlySpan <byte> rawData, SafePasswordHandle password, Interop.Crypt32.PfxCertStoreFlags pfxCertStoreFlags) { SafeCertStoreHandle hStore; unsafe { fixed(byte *pbRawData = rawData) { Interop.Crypt32.DATA_BLOB certBlob = new Interop.Crypt32.DATA_BLOB(new IntPtr(pbRawData), (uint)rawData.Length); hStore = Interop.Crypt32.PFXImportCertStore(ref certBlob, password, pfxCertStoreFlags); if (hStore.IsInvalid) { throw Marshal.GetHRForLastWin32Error().ToCryptographicException(); } } } try { // Find the first cert with private key. If none, then simply take the very first cert. Along the way, delete the keycontainers // of any cert we don't accept. SafeCertContextHandle pCertContext = SafeCertContextHandle.InvalidHandle; SafeCertContextHandle?pEnumContext = null; while (Interop.crypt32.CertEnumCertificatesInStore(hStore, ref pEnumContext)) { if (pEnumContext.ContainsPrivateKey) { if ((!pCertContext.IsInvalid) && pCertContext.ContainsPrivateKey) { // We already found our chosen one. Free up this one's key and move on. // If this one has a persisted private key, clean up the key file. // If it was an ephemeral private key no action is required. if (pEnumContext.HasPersistedPrivateKey) { SafeCertContextHandleWithKeyContainerDeletion.DeleteKeyContainer(pEnumContext); } } else { // Found our first cert that has a private key. Set it up as our chosen one but keep iterating // as we need to free up the keys of any remaining certs. pCertContext.Dispose(); pCertContext = pEnumContext.Duplicate(); } } else { if (pCertContext.IsInvalid) { // Doesn't have a private key but hang on to it anyway in case we don't find any certs with a private key. pCertContext = pEnumContext.Duplicate(); } } } if (pCertContext.IsInvalid) { throw new CryptographicException(SR.Cryptography_Pfx_NoCertificates); } return(pCertContext); } finally { hStore.Dispose(); } }
private static ICertificatePal FromBlobOrFile(ReadOnlySpan <byte> rawData, string?fileName, SafePasswordHandle password, X509KeyStorageFlags keyStorageFlags) { Debug.Assert(!rawData.IsEmpty || fileName != null); Debug.Assert(password != null); bool loadFromFile = (fileName != null); Interop.Crypt32.PfxCertStoreFlags pfxCertStoreFlags = MapKeyStorageFlags(keyStorageFlags); bool deleteKeyContainer = false; Interop.Crypt32.CertEncodingType msgAndCertEncodingType; Interop.Crypt32.ContentType contentType; Interop.Crypt32.FormatType formatType; SafeCertStoreHandle? hCertStore = null; SafeCryptMsgHandle? hCryptMsg = null; SafeCertContextHandle?pCertContext = null; try { unsafe { fixed(byte *pRawData = rawData) { fixed(char *pFileName = fileName) { Interop.Crypt32.DATA_BLOB certBlob = new Interop.Crypt32.DATA_BLOB(new IntPtr(pRawData), (uint)(loadFromFile ? 0 : rawData.Length)); Interop.Crypt32.CertQueryObjectType objectType = loadFromFile ? Interop.Crypt32.CertQueryObjectType.CERT_QUERY_OBJECT_FILE : Interop.Crypt32.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 == Interop.Crypt32.ContentType.CERT_QUERY_CONTENT_PKCS7_SIGNED || contentType == Interop.Crypt32.ContentType.CERT_QUERY_CONTENT_PKCS7_SIGNED_EMBED) { pCertContext?.Dispose(); pCertContext = GetSignerInPKCS7Store(hCertStore, hCryptMsg); } else if (contentType == Interop.Crypt32.ContentType.CERT_QUERY_CONTENT_PFX) { if (loadFromFile) { rawData = File.ReadAllBytes(fileName !); } pCertContext?.Dispose(); pCertContext = FilterPFXStore(rawData, password, pfxCertStoreFlags); // If PersistKeySet is set we don't delete the key, so that it persists. // If EphemeralKeySet is set we don't delete the key, because there's no file, so it's a wasteful call. const X509KeyStorageFlags DeleteUnless = X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.EphemeralKeySet; deleteKeyContainer = ((keyStorageFlags & DeleteUnless) == 0); } CertificatePal pal = new CertificatePal(pCertContext, deleteKeyContainer); pCertContext = null; return(pal); } } finally { hCertStore?.Dispose(); hCryptMsg?.Dispose(); pCertContext?.Dispose(); } }
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); }