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); } }
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(); } } }
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); }
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); }
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; } }