public X509ContentType GetCertContentType(byte[] rawData)
        {
            ContentType contentType;

            unsafe
            {
                fixed (byte* pRawData = rawData)
                {
                    CRYPTOAPI_BLOB certBlob = new CRYPTOAPI_BLOB(rawData.Length, pRawData);
                    if (!Interop.crypt32.CryptQueryObject(
                        CertQueryObjectType.CERT_QUERY_OBJECT_BLOB,
                        &certBlob,
                        ExpectedContentTypeFlags.CERT_QUERY_CONTENT_FLAG_ALL,
                        ExpectedFormatTypeFlags.CERT_QUERY_FORMAT_FLAG_ALL,
                        0,
                        IntPtr.Zero,
                        out contentType,
                        IntPtr.Zero,
                        IntPtr.Zero,
                        IntPtr.Zero,
                        IntPtr.Zero))
                    {
                        throw new CryptographicException(Marshal.GetLastWin32Error());
                    }
                }
            }

            return MapContentType(contentType);
        }
Beispiel #2
0
 public unsafe void FindByThumbprint(byte[] thumbPrint)
 {
     fixed (byte* pThumbPrint = thumbPrint)
     {
         CRYPTOAPI_BLOB blob = new CRYPTOAPI_BLOB(thumbPrint.Length, pThumbPrint);
         FindCore(CertFindType.CERT_FIND_HASH, &blob);
     }
 }
Beispiel #3
0
        private static StorePal FromBlobOrFile(byte[] rawData, string fileName, string password, X509KeyStorageFlags keyStorageFlags)
        {
            bool fromFile = fileName != null;

            unsafe
            {
                fixed (byte* pRawData = rawData)
                {
                    fixed (char* pFileName = fileName)
                    {
                        CRYPTOAPI_BLOB blob = new CRYPTOAPI_BLOB(fromFile ? 0 : rawData.Length, pRawData);
                        bool persistKeySet = (0 != (keyStorageFlags & X509KeyStorageFlags.PersistKeySet));
                        PfxCertStoreFlags certStoreFlags = MapKeyStorageFlags(keyStorageFlags);

                        void* pvObject = fromFile ? (void*)pFileName : (void*)&blob;

                        ContentType contentType;
                        SafeCertStoreHandle certStore;
                        if (!Interop.crypt32.CryptQueryObject(
                            fromFile ? CertQueryObjectType.CERT_QUERY_OBJECT_FILE : CertQueryObjectType.CERT_QUERY_OBJECT_BLOB,
                            pvObject,
                            StoreExpectedContentFlags,
                            ExpectedFormatTypeFlags.CERT_QUERY_FORMAT_FLAG_ALL,
                            0,
                            IntPtr.Zero,
                            out contentType,
                            IntPtr.Zero,
                            out certStore,
                            IntPtr.Zero,
                            IntPtr.Zero
                            ))
                        {
                            throw Marshal.GetLastWin32Error().ToCryptographicException();
                        }

                        if (contentType == ContentType.CERT_QUERY_CONTENT_PFX)
                        {
                            certStore.Dispose();

                            if (fromFile)
                            {
                                rawData = File.ReadAllBytes(fileName);
                            }
                            fixed (byte* pRawData2 = rawData)
                            {
                                CRYPTOAPI_BLOB blob2 = new CRYPTOAPI_BLOB(rawData.Length, pRawData2);
                                certStore = Interop.crypt32.PFXImportCertStore(ref blob2, password, certStoreFlags);
                                if (certStore == null || certStore.IsInvalid)
                                    throw Marshal.GetLastWin32Error().ToCryptographicException();
                            }

                            if (!persistKeySet)
                            {
                                //
                                // If the user did not want us to persist private keys, then we should loop through all
                                // the certificates in the collection and set our custom CERT_DELETE_KEYSET_PROP_ID property
                                // so the key container will be deleted when the cert contexts will go away.
                                //
                                SafeCertContextHandle pCertContext = null;
                                while (Interop.crypt32.CertEnumCertificatesInStore(certStore, ref pCertContext))
                                {
                                    CRYPTOAPI_BLOB nullBlob = new CRYPTOAPI_BLOB(0, null);
                                    if (!Interop.crypt32.CertSetCertificateContextProperty(pCertContext, CertContextPropId.CERT_DELETE_KEYSET_PROP_ID, CertSetPropertyFlags.CERT_SET_PROPERTY_INHIBIT_PERSIST_FLAG, &nullBlob))
                                        throw Marshal.GetLastWin32Error().ToCryptographicException();
                                }
                            }
                        }

                        return new StorePal(certStore);
                    }
                }
            }
        }
Beispiel #4
0
        public byte[] Export(X509ContentType contentType, string password)
        {
            switch (contentType)
            {
                case X509ContentType.Cert:
                    {
                        SafeCertContextHandle pCertContext = null;
                        if (!Interop.crypt32.CertEnumCertificatesInStore(_certStore, ref pCertContext))
                            return null;
                        try
                        {
                            unsafe
                            {
                                byte[] rawData = new byte[pCertContext.CertContext->cbCertEncoded];
                                Marshal.Copy((IntPtr)(pCertContext.CertContext->pbCertEncoded), rawData, 0, rawData.Length);
                                GC.KeepAlive(pCertContext);
                                return rawData;
                            }
                        }
                        finally
                        {
                            pCertContext.Dispose();
                        }
                    }

                case X509ContentType.SerializedCert:
                    {
                        SafeCertContextHandle pCertContext = null;
                        if (!Interop.crypt32.CertEnumCertificatesInStore(_certStore, ref pCertContext))
                            return null;

                        try
                        {
                            int cbEncoded = 0;
                            if (!Interop.crypt32.CertSerializeCertificateStoreElement(pCertContext, 0, null, ref cbEncoded))
                                throw Marshal.GetHRForLastWin32Error().ToCryptographicException();;

                            byte[] pbEncoded = new byte[cbEncoded];
                            if (!Interop.crypt32.CertSerializeCertificateStoreElement(pCertContext, 0, pbEncoded, ref cbEncoded))
                                throw Marshal.GetHRForLastWin32Error().ToCryptographicException();;

                            return pbEncoded;
                        }
                        finally
                        {
                            pCertContext.Dispose();
                        }
                    }

                case X509ContentType.Pkcs12:
                    {
                        unsafe
                        {
                            CRYPTOAPI_BLOB dataBlob = new CRYPTOAPI_BLOB(0, (byte*)null);

                            if (!Interop.crypt32.PFXExportCertStore(_certStore, ref dataBlob, password, PFXExportFlags.EXPORT_PRIVATE_KEYS | PFXExportFlags.REPORT_NOT_ABLE_TO_EXPORT_PRIVATE_KEY))
                                throw Marshal.GetHRForLastWin32Error().ToCryptographicException();;

                            byte[] pbEncoded = new byte[dataBlob.cbData];
                            fixed (byte* ppbEncoded = pbEncoded)
                            {
                                dataBlob.pbData = ppbEncoded;
                                if (!Interop.crypt32.PFXExportCertStore(_certStore, ref dataBlob, password, PFXExportFlags.EXPORT_PRIVATE_KEYS | PFXExportFlags.REPORT_NOT_ABLE_TO_EXPORT_PRIVATE_KEY))
                                    throw Marshal.GetHRForLastWin32Error().ToCryptographicException();;
                            }

                            return pbEncoded;
                        }
                    }

                case X509ContentType.SerializedStore:
                    return SaveToMemoryStore(CertStoreSaveAs.CERT_STORE_SAVE_AS_STORE);

                case X509ContentType.Pkcs7:
                    return SaveToMemoryStore(CertStoreSaveAs.CERT_STORE_SAVE_AS_PKCS7);

                default:
                    throw new CryptographicException(SR.Cryptography_X509_InvalidContentType);
            }
        }
Beispiel #5
0
        private byte[] SaveToMemoryStore(CertStoreSaveAs dwSaveAs)
        {
            unsafe
            {
                CRYPTOAPI_BLOB blob = new CRYPTOAPI_BLOB(0, null);
                if (!Interop.crypt32.CertSaveStore(_certStore, CertEncodingType.All, dwSaveAs, CertStoreSaveTo.CERT_STORE_SAVE_TO_MEMORY, ref blob, 0))
                    throw Marshal.GetLastWin32Error().ToCryptographicException();

                byte[] exportedData = new byte[blob.cbData];
                fixed (byte* pExportedData = exportedData)
                {
                    blob.pbData = pExportedData;
                    if (!Interop.crypt32.CertSaveStore(_certStore, CertEncodingType.All, dwSaveAs, CertStoreSaveTo.CERT_STORE_SAVE_TO_MEMORY, ref blob, 0))
                        throw Marshal.GetLastWin32Error().ToCryptographicException();
                }
                return exportedData;
            }
        }
Beispiel #6
0
        private static ICertificatePal FromBlobOrFile(byte[] rawData, string fileName, string password, X509KeyStorageFlags keyStorageFlags)
        {
            Debug.Assert(rawData != null || fileName != 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();
            }
        }
Beispiel #7
0
        private static SafeCertContextHandle FilterPFXStore(byte[] rawData, string password, PfxCertStoreFlags pfxCertStoreFlags)
        {
            SafeCertStoreHandle hStore;
            unsafe
            {
                fixed (byte* pbRawData = rawData)
                {
                    CRYPTOAPI_BLOB certBlob = new CRYPTOAPI_BLOB(rawData.Length, pbRawData);
                    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.
                            SafeCertContextHandleWithKeyContainerDeletion.DeleteKeyContainer(pEnumContext);
                        }
                        else
                        {
                            // Found our first cert that has a private key. Set him 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)
                            pCertContext = pEnumContext.Duplicate(); // Doesn't have a private key but hang on to it anyway in case we don't find any certs with a private key.
                    }
                }

                if (pCertContext.IsInvalid)
                {
                    // For compat, setting "hr" to ERROR_INVALID_PARAMETER even though ERROR_INVALID_PARAMETER is not actually an HRESULT.
                    throw ErrorCode.ERROR_INVALID_PARAMETER.ToCryptographicException();
                }

                return pCertContext;
            }
            finally
            {
                hStore.Dispose();
            }
        }
 public byte[] EncodeX509SubjectKeyIdentifierExtension(byte[] subjectKeyIdentifier)
 {
     unsafe
     {
         fixed (byte* pSubkectKeyIdentifier = subjectKeyIdentifier)
         {
             CRYPTOAPI_BLOB blob = new CRYPTOAPI_BLOB(subjectKeyIdentifier.Length, pSubkectKeyIdentifier);
             return Interop.crypt32.EncodeObject(Oids.SubjectKeyIdentifier, &blob);
         }
     }
 }
Beispiel #9
0
 public static extern bool CertSaveStore(SafeCertStoreHandle hCertStore, CertEncodingType dwMsgAndCertEncodingType, CertStoreSaveAs dwSaveAs, CertStoreSaveTo dwSaveTo, ref CRYPTOAPI_BLOB pvSaveToPara, int dwFlags);
Beispiel #10
0
 public static extern bool CertGetCertificateContextProperty(SafeCertContextHandle pCertContext, CertContextPropId dwPropId, [Out] out CRYPTOAPI_BLOB pvData, [In, Out] ref int pcbData);
Beispiel #11
0
 public static extern bool CertSaveStore(SafeCertStoreHandle hCertStore, CertEncodingType dwMsgAndCertEncodingType, CertStoreSaveAs dwSaveAs, CertStoreSaveTo dwSaveTo, ref CRYPTOAPI_BLOB pvSaveToPara, int dwFlags);
Beispiel #12
0
 public static extern int CertNameToStr(CertEncodingType dwCertEncodingType, [In] ref CRYPTOAPI_BLOB pName, CertNameStrTypeAndFlags dwStrType, StringBuilder psz, int csz);
Beispiel #13
0
 public static extern bool PFXExportCertStore(SafeCertStoreHandle hStore, [In, Out] ref CRYPTOAPI_BLOB pPFX, String szPassword, PFXExportFlags dwFlags);
Beispiel #14
0
 public static extern SafeCertStoreHandle PFXImportCertStore([In] ref CRYPTOAPI_BLOB pPFX, String szPassword, PfxCertStoreFlags dwFlags);