Ejemplo n.º 1
0
        public void Decode(byte[] encodedMessage)
        {
            if (encodedMessage == null)
            {
                throw new ArgumentNullException("encodedMessage");
            }

            if (m_safeCryptMsgHandle != null && !m_safeCryptMsgHandle.IsInvalid)
            {
                m_safeCryptMsgHandle.Dispose();
            }

            m_safeCryptMsgHandle = OpenToDecode(encodedMessage, this.ContentInfo, this.Detached);
            if (!this.Detached)
            {
                Oid    contentType = PkcsUtils.GetContentType(m_safeCryptMsgHandle);
                byte[] content     = PkcsUtils.GetContent(m_safeCryptMsgHandle);
                m_contentInfo = new ContentInfo(contentType, content);
            }
        }
Ejemplo n.º 2
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();
                }
            }
        }
        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 deleteKeyContainer             = false;

            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 = Interop.CPError.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);

                        // 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 |
                            // begin: gost
                            X509KeyStorageFlags.CspNoPersistKeySet;
                        // end gost

                        deleteKeyContainer = ((keyStorageFlags & DeleteUnless) == 0);
                    }

                    CertificatePal pal = new CertificatePal(pCertContext, deleteKeyContainer);

                    pCertContext = null;
                    return(pal);
                }
            }
            finally
            {
                if (hCertStore != null)
                {
                    hCertStore.Dispose();
                }
                if (hCryptMsg != null)
                {
                    hCryptMsg.Dispose();
                }
                if (pCertContext != null)
                {
                    pCertContext.Dispose();
                }
            }
        }
Ejemplo n.º 4
0
        public static Oid GetContentType(byte[] encodedMessage)
        {
            if (encodedMessage == null)
            {
                throw new ArgumentNullException("encodedMessage");
            }

            SafeCryptMsgHandle safeCryptMsgHandle = CAPI.CAPISafe.CryptMsgOpenToDecode(
                CAPI.X509_ASN_ENCODING | CAPI.PKCS_7_ASN_ENCODING,
                0,
                0,
                IntPtr.Zero,
                IntPtr.Zero,
                IntPtr.Zero);

            if (safeCryptMsgHandle == null || safeCryptMsgHandle.IsInvalid)
            {
                throw new CryptographicException(Marshal.GetLastWin32Error());
            }

            if (!CAPI.CAPISafe.CryptMsgUpdate(safeCryptMsgHandle, encodedMessage, (uint)encodedMessage.Length, true))
            {
                throw new CryptographicException(Marshal.GetLastWin32Error());
            }

            Oid contentType;

            switch (PkcsUtils.GetMessageType(safeCryptMsgHandle))
            {
            case CAPI.CMSG_DATA:
                contentType = Oid.FromOidValue(CAPI.szOID_RSA_data, OidGroup.ExtensionOrAttribute);
                break;

            case CAPI.CMSG_SIGNED:
                contentType = Oid.FromOidValue(CAPI.szOID_RSA_signedData, OidGroup.ExtensionOrAttribute);
                break;

            case CAPI.CMSG_ENVELOPED:
                contentType = Oid.FromOidValue(CAPI.szOID_RSA_envelopedData, OidGroup.ExtensionOrAttribute);
                break;

            case CAPI.CMSG_SIGNED_AND_ENVELOPED:
                contentType = Oid.FromOidValue(CAPI.szOID_RSA_signEnvData, OidGroup.ExtensionOrAttribute);
                break;

            case CAPI.CMSG_HASHED:
                contentType = Oid.FromOidValue(CAPI.szOID_RSA_hashedData, OidGroup.ExtensionOrAttribute);
                break;

            case CAPI.CMSG_ENCRYPTED:
                contentType = Oid.FromOidValue(CAPI.szOID_RSA_encryptedData, OidGroup.ExtensionOrAttribute);
                break;

            default:
                throw new CryptographicException(CAPI.CRYPT_E_INVALID_MSG_TYPE);
            }

            safeCryptMsgHandle.Dispose();

            return(contentType);
        }
Ejemplo n.º 5
0
        private unsafe void Sign(CmsSigner signer, bool silent)
        {
            SafeCryptMsgHandle safeCryptMsgHandle = null;

            CAPI.CMSG_SIGNED_ENCODE_INFO signedEncodeInfo = new CAPI.CMSG_SIGNED_ENCODE_INFO(Marshal.SizeOf(typeof(CAPI.CMSG_SIGNED_ENCODE_INFO)));
            SafeCryptProvHandle          safeCryptProvHandle;

            CAPI.CMSG_SIGNER_ENCODE_INFO signerEncodeInfo = PkcsUtils.CreateSignerEncodeInfo(signer, silent, out safeCryptProvHandle);

            byte[] encodedMessage = null;
            try {
                SafeLocalAllocHandle pSignerEncodeInfo = CAPI.LocalAlloc(CAPI.LMEM_FIXED, new IntPtr(Marshal.SizeOf(typeof(CAPI.CMSG_SIGNER_ENCODE_INFO))));

                try {
                    Marshal.StructureToPtr(signerEncodeInfo, pSignerEncodeInfo.DangerousGetHandle(), false);
                    X509Certificate2Collection bagOfCerts         = PkcsUtils.CreateBagOfCertificates(signer);
                    SafeLocalAllocHandle       pEncodedBagOfCerts = PkcsUtils.CreateEncodedCertBlob(bagOfCerts);

                    signedEncodeInfo.cSigners     = 1;
                    signedEncodeInfo.rgSigners    = pSignerEncodeInfo.DangerousGetHandle();
                    signedEncodeInfo.cCertEncoded = (uint)bagOfCerts.Count;
                    if (bagOfCerts.Count > 0)
                    {
                        signedEncodeInfo.rgCertEncoded = pEncodedBagOfCerts.DangerousGetHandle();
                    }

                    // Because of the way CAPI treats inner content OID, we should pass NULL
                    // for data type, otherwise detached will not work.
                    if (String.Compare(this.ContentInfo.ContentType.Value, CAPI.szOID_RSA_data, StringComparison.OrdinalIgnoreCase) == 0)
                    {
                        safeCryptMsgHandle = CAPI.CryptMsgOpenToEncode(CAPI.X509_ASN_ENCODING | CAPI.PKCS_7_ASN_ENCODING,
                                                                       Detached ? CAPI.CMSG_DETACHED_FLAG : 0,
                                                                       CAPI.CMSG_SIGNED,
                                                                       new IntPtr(&signedEncodeInfo),
                                                                       IntPtr.Zero,
                                                                       IntPtr.Zero);
                    }
                    else
                    {
                        safeCryptMsgHandle = CAPI.CryptMsgOpenToEncode(CAPI.X509_ASN_ENCODING | CAPI.PKCS_7_ASN_ENCODING,
                                                                       Detached ? CAPI.CMSG_DETACHED_FLAG : 0,
                                                                       CAPI.CMSG_SIGNED,
                                                                       new IntPtr(&signedEncodeInfo),
                                                                       this.ContentInfo.ContentType.Value,
                                                                       IntPtr.Zero);
                    }

                    if (safeCryptMsgHandle == null || safeCryptMsgHandle.IsInvalid)
                    {
                        throw new CryptographicException(Marshal.GetLastWin32Error());
                    }


                    if (this.ContentInfo.Content.Length > 0)
                    {
                        if (!CAPI.CAPISafe.CryptMsgUpdate(safeCryptMsgHandle, this.ContentInfo.pContent, (uint)this.ContentInfo.Content.Length, true))
                        {
                            throw new CryptographicException(Marshal.GetLastWin32Error());
                        }
                    }

                    // Retrieve encoded message.
                    encodedMessage = PkcsUtils.GetContent(safeCryptMsgHandle);
                    safeCryptMsgHandle.Dispose();

                    pEncodedBagOfCerts.Dispose();
                }
                finally {
                    Marshal.DestroyStructure(pSignerEncodeInfo.DangerousGetHandle(), typeof(CAPI.CMSG_SIGNER_ENCODE_INFO));
                    pSignerEncodeInfo.Dispose();
                }
            }
            finally {
                // Don't forget to free all the resource still held inside signerEncodeInfo.
                signerEncodeInfo.Dispose();
                safeCryptProvHandle.Dispose();
            }

            // Re-open to decode.
            safeCryptMsgHandle = OpenToDecode(encodedMessage, this.ContentInfo, this.Detached);
            if (m_safeCryptMsgHandle != null && !m_safeCryptMsgHandle.IsInvalid)
            {
                m_safeCryptMsgHandle.Dispose();
            }
            m_safeCryptMsgHandle = safeCryptMsgHandle;
            GC.KeepAlive(signer);
        }
Ejemplo n.º 6
0
        internal static DecryptorPalWindows Decode(
            ReadOnlySpan <byte> encodedMessage,
            out int version,
            out ContentInfo contentInfo,
            out AlgorithmIdentifier contentEncryptionAlgorithm,
            out X509Certificate2Collection originatorCerts,
            out CryptographicAttributeObjectCollection unprotectedAttributes
            )
        {
            SafeCryptMsgHandle?hCryptMsg = null;

            try
            {
                hCryptMsg = Interop.Crypt32.CryptMsgOpenToDecode(MsgEncodingType.All, 0, 0, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero);
                if (hCryptMsg == null || hCryptMsg.IsInvalid)
                {
                    throw Marshal.GetLastWin32Error().ToCryptographicException();
                }

                if (!Interop.Crypt32.CryptMsgUpdate(
                        hCryptMsg,
                        ref MemoryMarshal.GetReference(encodedMessage),
                        encodedMessage.Length,
                        fFinal: true))
                {
                    throw Marshal.GetLastWin32Error().ToCryptographicException();
                }

                CryptMsgType cryptMsgType = hCryptMsg.GetMessageType();
                if (cryptMsgType != CryptMsgType.CMSG_ENVELOPED)
                {
                    throw ErrorCode.CRYPT_E_INVALID_MSG_TYPE.ToCryptographicException();
                }

                version = hCryptMsg.GetVersion();

                contentInfo = hCryptMsg.GetContentInfo();

                AlgorithmIdentifierAsn contentEncryptionAlgorithmAsn;
                using (SafeHandle sh = hCryptMsg.GetMsgParamAsMemory(CryptMsgParamType.CMSG_ENVELOPE_ALGORITHM_PARAM))
                {
                    unsafe
                    {
                        CRYPT_ALGORITHM_IDENTIFIER *pCryptAlgorithmIdentifier = (CRYPT_ALGORITHM_IDENTIFIER *)(sh.DangerousGetHandle());
                        contentEncryptionAlgorithm = (*pCryptAlgorithmIdentifier).ToAlgorithmIdentifier();
                        contentEncryptionAlgorithmAsn.Algorithm  = contentEncryptionAlgorithm.Oid.Value !;
                        contentEncryptionAlgorithmAsn.Parameters = (*pCryptAlgorithmIdentifier).Parameters.ToByteArray();
                    }
                }

                originatorCerts       = hCryptMsg.GetOriginatorCerts();
                unprotectedAttributes = hCryptMsg.GetUnprotectedAttributes();

                RecipientInfoCollection recipientInfos = CreateRecipientInfos(hCryptMsg);
                return(new DecryptorPalWindows(hCryptMsg, recipientInfos, contentEncryptionAlgorithmAsn));
            }
            catch
            {
                hCryptMsg?.Dispose();
                throw;
            }
        }