Beispiel #1
0
        [System.Security.SecurityCritical]  // auto-generated
        private byte[] ExportHelper(X509ContentType contentType, object password)
        {
            switch (contentType)
            {
            case X509ContentType.Cert:
                break;

#if FEATURE_CORECLR
            case (X509ContentType)0x02 /* X509ContentType.SerializedCert */:
            case (X509ContentType)0x03 /* X509ContentType.Pkcs12 */:
                throw new CryptographicException(Environment.GetResourceString("Cryptography_X509_InvalidContentType"),
                                                 new NotSupportedException());
#else // FEATURE_CORECLR
            case X509ContentType.SerializedCert:
                break;

#if !FEATURE_PAL
            case X509ContentType.Pkcs12:
                KeyContainerPermission kp = new KeyContainerPermission(KeyContainerPermissionFlags.Open | KeyContainerPermissionFlags.Export);
                kp.Demand();
                break;
#endif // !FEATURE_PAL
#endif // FEATURE_CORECLR else
            default:
                throw new CryptographicException(Environment.GetResourceString("Cryptography_X509_InvalidContentType"));
            }

#if !FEATURE_CORECLR
            IntPtr szPassword     = IntPtr.Zero;
            byte[] encodedRawData = null;
            SafeCertStoreHandle safeCertStoreHandle = X509Utils.ExportCertToMemoryStore(this);

            RuntimeHelpers.PrepareConstrainedRegions();
            try {
                szPassword     = X509Utils.PasswordToHGlobalUni(password);
                encodedRawData = X509Utils._ExportCertificatesToBlob(safeCertStoreHandle, contentType, szPassword);
            }
            finally {
                if (szPassword != IntPtr.Zero)
                {
                    Marshal.ZeroFreeGlobalAllocUnicode(szPassword);
                }
                safeCertStoreHandle.Dispose();
            }
            if (encodedRawData == null)
            {
                throw new CryptographicException(Environment.GetResourceString("Cryptography_X509_ExportFailed"));
            }
            return(encodedRawData);
#else // !FEATURE_CORECLR
            return(RawData);
#endif // !FEATURE_CORECLR
        }
Beispiel #2
0
        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);
        }
        /// <summary>
        /// Note: this factory method creates the store using links to the original certificates rather than copies. This means that any changes to certificate properties
        /// in the store changes the original.
        /// </summary>
        internal static partial IExportPal LinkFromCertificateCollection(X509Certificate2Collection certificates)
        {
            // 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 certStore = Interop.crypt32.CertOpenStore(
                CertStoreProvider.CERT_STORE_PROV_MEMORY,
                Interop.Crypt32.CertEncodingType.All,
                IntPtr.Zero,
                Interop.Crypt32.CertStoreFlags.CERT_STORE_ENUM_ARCHIVED_FLAG | Interop.Crypt32.CertStoreFlags.CERT_STORE_CREATE_NEW_FLAG,
                null);

            try
            {
                if (certStore.IsInvalid)
                {
                    throw Marshal.GetHRForLastWin32Error().ToCryptographicException();
                }

                //
                // 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.
                //

                for (int i = 0; i < certificates.Count; i++)
                {
                    using (SafeCertContextHandle certContext = ((CertificatePal)certificates[i].Pal !).GetCertContext())
                    {
                        if (!Interop.Crypt32.CertAddCertificateLinkToStore(certStore, certContext, Interop.Crypt32.CertStoreAddDisposition.CERT_STORE_ADD_ALWAYS, IntPtr.Zero))
                        {
                            throw Marshal.GetLastPInvokeError().ToCryptographicException();
                        }
                    }
                }

                return(new StorePal(certStore));
            }
            catch
            {
                certStore.Dispose();
                throw;
            }
        }
Beispiel #4
0
        internal static partial IStorePal FromHandle(IntPtr storeHandle)
        {
            if (storeHandle == IntPtr.Zero)
            {
                throw new ArgumentNullException(nameof(storeHandle));
            }

            SafeCertStoreHandle certStoreHandle = Interop.Crypt32.CertDuplicateStore(storeHandle);

            if (certStoreHandle == null || certStoreHandle.IsInvalid)
            {
                certStoreHandle?.Dispose();
                throw new CryptographicException(SR.Cryptography_InvalidStoreHandle, nameof(storeHandle));
            }

            var pal = new StorePal(certStoreHandle);

            return(pal);
        }
Beispiel #5
0
        private byte[] ExportHelper(X509ContentType contentType, object password)
        {
            switch (contentType)
            {
            case X509ContentType.Cert:
            case X509ContentType.SerializedCert:
                break;

            case X509ContentType.Pfx:
                new KeyContainerPermission(KeyContainerPermissionFlags.Export | KeyContainerPermissionFlags.Open).Demand();
                break;

            default:
                throw new CryptographicException(Environment.GetResourceString("Cryptography_X509_InvalidContentType"));
            }
            IntPtr zero = IntPtr.Zero;

            byte[] buffer = null;
            SafeCertStoreHandle safeCertStoreHandle = X509Utils.ExportCertToMemoryStore(this);

            RuntimeHelpers.PrepareConstrainedRegions();
            try
            {
                zero   = X509Utils.PasswordToHGlobalUni(password);
                buffer = X509Utils._ExportCertificatesToBlob(safeCertStoreHandle, contentType, zero);
            }
            finally
            {
                if (zero != IntPtr.Zero)
                {
                    Marshal.ZeroFreeGlobalAllocUnicode(zero);
                }
                safeCertStoreHandle.Dispose();
            }
            if (buffer == null)
            {
                throw new CryptographicException(Environment.GetResourceString("Cryptography_X509_ExportFailed"));
            }
            return(buffer);
        }
        internal static partial IStorePal FromSystemStore(string storeName, StoreLocation storeLocation, OpenFlags openFlags)
        {
            Interop.Crypt32.CertStoreFlags certStoreFlags = MapX509StoreFlags(storeLocation, openFlags);

            SafeCertStoreHandle certStore = Interop.crypt32.CertOpenStore(CertStoreProvider.CERT_STORE_PROV_SYSTEM_W, Interop.Crypt32.CertEncodingType.All, IntPtr.Zero, certStoreFlags, storeName);
            if (certStore.IsInvalid)
            {
                Exception e = Marshal.GetLastWin32Error().ToCryptographicException();
                certStore.Dispose();
                throw e;
            }

            //
            // We want the store to auto-resync when requesting a snapshot so that
            // updates to the store will be taken into account.
            //
            // For compat with desktop, ignoring any failures from this call. (It is pretty unlikely to fail, in any case.)
            //
            _ = Interop.Crypt32.CertControlStore(certStore, Interop.Crypt32.CertControlStoreFlags.None, Interop.Crypt32.CertControlStoreType.CERT_STORE_CTRL_AUTO_RESYNC, IntPtr.Zero);

            return new StorePal(certStore);
        }
Beispiel #7
0
        private byte[] ExportHelper(X509ContentType contentType, object password)
        {
            switch (contentType)
            {
            case X509ContentType.Cert:
            case X509ContentType.SerializedCert:
                IntPtr num      = IntPtr.Zero;
                byte[] numArray = (byte[])null;
                SafeCertStoreHandle memoryStore = X509Utils.ExportCertToMemoryStore(this);
                RuntimeHelpers.PrepareConstrainedRegions();
                try
                {
                    num      = X509Utils.PasswordToHGlobalUni(password);
                    numArray = X509Utils._ExportCertificatesToBlob(memoryStore, contentType, num);
                }
                finally
                {
                    if (num != IntPtr.Zero)
                    {
                        Marshal.ZeroFreeGlobalAllocUnicode(num);
                    }
                    memoryStore.Dispose();
                }
                if (numArray == null)
                {
                    throw new CryptographicException(Environment.GetResourceString("Cryptography_X509_ExportFailed"));
                }
                return(numArray);

            case X509ContentType.Pfx:
                new KeyContainerPermission(KeyContainerPermissionFlags.Open | KeyContainerPermissionFlags.Export).Demand();
                goto case X509ContentType.Cert;

            default:
                throw new CryptographicException(Environment.GetResourceString("Cryptography_X509_InvalidContentType"));
            }
        }
        internal static partial IExportPal FromCertificate(ICertificatePalCore cert)
        {
            CertificatePal certificatePal = (CertificatePal)cert;

            SafeCertStoreHandle certStore = Interop.crypt32.CertOpenStore(
                CertStoreProvider.CERT_STORE_PROV_MEMORY,
                Interop.Crypt32.CertEncodingType.All,
                IntPtr.Zero,
                Interop.Crypt32.CertStoreFlags.CERT_STORE_ENUM_ARCHIVED_FLAG | Interop.Crypt32.CertStoreFlags.CERT_STORE_CREATE_NEW_FLAG | Interop.Crypt32.CertStoreFlags.CERT_STORE_DEFER_CLOSE_UNTIL_LAST_FREE_FLAG,
                null);

            using (SafeCertContextHandle certContext = certificatePal.GetCertContext())
            {
                if (certStore.IsInvalid ||
                    !Interop.Crypt32.CertAddCertificateLinkToStore(certStore, certContext, Interop.Crypt32.CertStoreAddDisposition.CERT_STORE_ADD_ALWAYS, IntPtr.Zero))
                {
                    Exception e = Marshal.GetHRForLastWin32Error().ToCryptographicException();
                    certStore.Dispose();
                    throw e;
                }
            }

            return(new StorePal(certStore));
        }
        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();
            }
        }
Beispiel #10
0
        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);
        }