internal static unsafe SafeLocalAllocHandle CreateEncodedCertBlob(X509Certificate2Collection certificates) { SafeLocalAllocHandle localAllocHandle = SafeLocalAllocHandle.InvalidHandle; if (certificates.Count > 0) { localAllocHandle = CAPI.LocalAlloc(0U, new IntPtr(certificates.Count * Marshal.SizeOf(typeof(CAPI.CRYPTOAPI_BLOB)))); CAPI.CRYPTOAPI_BLOB *cryptoapiBlobPtr = (CAPI.CRYPTOAPI_BLOB *)(void *) localAllocHandle.DangerousGetHandle(); foreach (X509Certificate2 certificate in certificates) { CAPI.CERT_CONTEXT certContext = *(CAPI.CERT_CONTEXT *)(void *) X509Utils.GetCertContext(certificate).DangerousGetHandle(); cryptoapiBlobPtr->cbData = certContext.cbCertEncoded; cryptoapiBlobPtr->pbData = certContext.pbCertEncoded; ++cryptoapiBlobPtr; } } return(localAllocHandle); }
internal unsafe X509ExtensionCollection(SafeCertContextHandle safeCertContextHandle) { using (SafeCertContextHandle certContext = CAPI.CertDuplicateCertificateContext(safeCertContextHandle)) { CAPI.CERT_CONTEXT pCertContext = *((CAPI.CERT_CONTEXT *)certContext.DangerousGetHandle()); CAPI.CERT_INFO pCertInfo = (CAPI.CERT_INFO)Marshal.PtrToStructure(pCertContext.pCertInfo, typeof(CAPI.CERT_INFO)); uint cExtensions = pCertInfo.cExtension; IntPtr rgExtensions = pCertInfo.rgExtension; for (uint index = 0; index < cExtensions; index++) { X509Extension extension = new X509Extension(new IntPtr((long)rgExtensions + (index * Marshal.SizeOf(typeof(CAPI.CERT_EXTENSION))))); X509Extension customExtension = CryptoConfig.CreateFromName(extension.Oid.Value) as X509Extension; if (customExtension != null) { customExtension.CopyFrom(extension); extension = customExtension; } Add(extension); } } }
internal static unsafe uint AddCertsToMessage(SafeCryptMsgHandle safeCryptMsgHandle, X509Certificate2Collection bagOfCerts, X509Certificate2Collection chainOfCerts) { uint num = 0U; foreach (X509Certificate2 certificate in chainOfCerts) { if (bagOfCerts.Find(X509FindType.FindByThumbprint, (object)certificate.Thumbprint, false).Count == 0) { CAPI.CERT_CONTEXT certContext = *(CAPI.CERT_CONTEXT *)(void *) X509Utils.GetCertContext(certificate).DangerousGetHandle(); if (!CAPI.CryptMsgControl(safeCryptMsgHandle, 0U, 10U, new IntPtr((long)&new CAPI.CRYPTOAPI_BLOB() { cbData = certContext.cbCertEncoded, pbData = certContext.pbCertEncoded }))) { throw new CryptographicException(Marshal.GetLastWin32Error()); } ++num; } } return(num); }
private unsafe void Verify(X509Certificate2Collection extraStore, X509Certificate2 certificate, bool verifySignatureOnly) { checked { // We need to find out if DSS parameters inheritance is necessary. If so, we need to // first build the chain to cause CAPI to inherit and set the parameters in the // CERT_PUBKEY_ALG_PARA_PROP_ID extended property. Once we have the parameters in // the property, we then need to retrieve a copy and point to it in the CERT_INFO // structure. SafeLocalAllocHandle pbParameters = SafeLocalAllocHandle.InvalidHandle; CAPI.CERT_CONTEXT pCertContext = (CAPI.CERT_CONTEXT)Marshal.PtrToStructure(X509Utils.GetCertContext(certificate).DangerousGetHandle(), typeof(CAPI.CERT_CONTEXT)); // Point to SubjectPublicKeyInfo field inside the CERT_INFO structure. IntPtr pSubjectPublicKeyInfo = new IntPtr((long)pCertContext.pCertInfo + (long)Marshal.OffsetOf(typeof(CAPI.CERT_INFO), "SubjectPublicKeyInfo")); // Point to Algorithm field inside the SubjectPublicKeyInfo field. IntPtr pAlgorithm = new IntPtr((long)pSubjectPublicKeyInfo + (long)Marshal.OffsetOf(typeof(CAPI.CERT_PUBLIC_KEY_INFO), "Algorithm")); // Point to Parameters field inside the Algorithm field. IntPtr pParameters = new IntPtr((long)pAlgorithm + (long)Marshal.OffsetOf(typeof(CAPI.CRYPT_ALGORITHM_IDENTIFIER), "Parameters")); // Retrieve the pszObjId pointer. IntPtr pObjId = Marshal.ReadIntPtr(pAlgorithm); // Translate the OID to AlgId value. CAPI.CRYPT_OID_INFO pOIDInfo = CAPI.CryptFindOIDInfo(CAPI.CRYPT_OID_INFO_OID_KEY, pObjId, CAPI.CRYPT_PUBKEY_ALG_OID_GROUP_ID); // Is this DSS? if (pOIDInfo.Algid == CAPI.CALG_DSS_SIGN) { bool inheritParameters = false; // This is DSS, so inherit the parameters if necessary. IntPtr pcbData = new IntPtr((long)pParameters + (long)Marshal.OffsetOf(typeof(CAPI.CRYPTOAPI_BLOB), "cbData")); IntPtr ppbData = new IntPtr((long)pParameters + (long)Marshal.OffsetOf(typeof(CAPI.CRYPTOAPI_BLOB), "pbData")); if (Marshal.ReadInt32(pcbData) == 0) { inheritParameters = true; } else { // Need to inherit if NULL pbData or *pbData is 0x05 (NULL ASN tag). if (Marshal.ReadIntPtr(ppbData) == IntPtr.Zero) { inheritParameters = true; } else { IntPtr pbData = Marshal.ReadIntPtr(ppbData); if ((uint)Marshal.ReadInt32(pbData) == CAPI.ASN_TAG_NULL) { inheritParameters = true; } } } // Do we need to copy inherited DSS parameters? if (inheritParameters) { // Build the chain to force CAPI to propagate the parameters to // CERT_PUBKEY_ALG_PARA_PROP_ID extended property. SafeCertChainHandle pChainContext = SafeCertChainHandle.InvalidHandle; X509Utils.BuildChain(new IntPtr(CAPI.HCCE_CURRENT_USER), X509Utils.GetCertContext(certificate), null, null, null, X509RevocationMode.NoCheck, X509RevocationFlag.ExcludeRoot, DateTime.Now, new TimeSpan(0, 0, 0), // default ref pChainContext); pChainContext.Dispose(); // The parameter is inherited in the extended property, but not copied // to CERT_INFO, so we need to do it ourselves. uint cbParameters = 0; if (!CAPI.CAPISafe.CertGetCertificateContextProperty(X509Utils.GetCertContext(certificate), CAPI.CERT_PUBKEY_ALG_PARA_PROP_ID, pbParameters, ref cbParameters)) { throw new CryptographicException(Marshal.GetLastWin32Error()); } if (cbParameters > 0) { pbParameters = CAPI.LocalAlloc(CAPI.LPTR, new IntPtr(cbParameters)); if (!CAPI.CAPISafe.CertGetCertificateContextProperty(X509Utils.GetCertContext(certificate), CAPI.CERT_PUBKEY_ALG_PARA_PROP_ID, pbParameters, ref cbParameters)) { throw new CryptographicException(Marshal.GetLastWin32Error()); } Marshal.WriteInt32(pcbData, (int)cbParameters); Marshal.WriteIntPtr(ppbData, pbParameters.DangerousGetHandle()); } } } // Is this counter signer? if (m_parentSignerInfo == null) { // Just plain signer. if (!CAPI.CryptMsgControl(m_signedCms.GetCryptMsgHandle(), 0, CAPI.CMSG_CTRL_VERIFY_SIGNATURE, pCertContext.pCertInfo)) { throw new CryptographicException(Marshal.GetLastWin32Error()); } } else { // Counter signer, so need to first find parent signer's index. int index = -1; int lastWin32Error = 0; // Since we allow the same signer to sign more than once, // we must than try all signatures of the same signer. while (true) { try { // Find index of parent signer. index = PkcsUtils.GetSignerIndex(m_signedCms.GetCryptMsgHandle(), m_parentSignerInfo, index + 1); } catch (CryptographicException) { // Did we ever find a signature of the same signer? if (lastWin32Error == 0) { // No. So we just re-throw, which is most likely CAPI.CRYPT_E_SIGNER_NOT_FOUND. throw; } else { // Yes. Throw previous error, which is most likely CAPI.NTE_BAD_SIGNATURE. throw new CryptographicException(lastWin32Error); } } // Now get the parent encoded singer info. uint cbParentEncodedSignerInfo = 0; SafeLocalAllocHandle pbParentEncodedSignerInfo = SafeLocalAllocHandle.InvalidHandle; PkcsUtils.GetParam(m_signedCms.GetCryptMsgHandle(), CAPI.CMSG_ENCODED_SIGNER, (uint)index, out pbParentEncodedSignerInfo, out cbParentEncodedSignerInfo); // Try next signer if we can't get parent of this signer. if (cbParentEncodedSignerInfo == 0) { lastWin32Error = CAPI.CRYPT_E_NO_SIGNER; continue; } fixed(byte *pbEncodedSignerInfo = m_encodedSignerInfo) { if (!CAPI.CAPISafe.CryptMsgVerifyCountersignatureEncoded(IntPtr.Zero, CAPI.X509_ASN_ENCODING | CAPI.PKCS_7_ASN_ENCODING, pbParentEncodedSignerInfo.DangerousGetHandle(), cbParentEncodedSignerInfo, new IntPtr(pbEncodedSignerInfo), (uint)m_encodedSignerInfo.Length, pCertContext.pCertInfo)) { // Cache the error, and try next signer. lastWin32Error = Marshal.GetLastWin32Error(); continue; } } // Keep alive. pbParentEncodedSignerInfo.Dispose(); // The signature is successfully verified. break; } } // Verfiy the cert if requested. if (!verifySignatureOnly) { int hr = VerifyCertificate(certificate, extraStore); if (hr != CAPI.S_OK) { throw new CryptographicException(hr); } } // Keep alive. pbParameters.Dispose(); } }
private unsafe void Verify(X509Certificate2Collection extraStore, X509Certificate2 certificate, bool verifySignatureOnly) { SafeLocalAllocHandle pvData1 = SafeLocalAllocHandle.InvalidHandle; CAPI.CERT_CONTEXT certContext = (CAPI.CERT_CONTEXT)Marshal.PtrToStructure(X509Utils.GetCertContext(certificate).DangerousGetHandle(), typeof(CAPI.CERT_CONTEXT)); IntPtr ptr1 = new IntPtr((long)new IntPtr((long)certContext.pCertInfo + (long)Marshal.OffsetOf(typeof(CAPI.CERT_INFO), "SubjectPublicKeyInfo")) + (long)Marshal.OffsetOf(typeof(CAPI.CERT_PUBLIC_KEY_INFO), "Algorithm")); IntPtr num1 = new IntPtr((long)ptr1 + (long)Marshal.OffsetOf(typeof(CAPI.CRYPT_ALGORITHM_IDENTIFIER), "Parameters")); if ((int)CAPI.CryptFindOIDInfo(1U, Marshal.ReadIntPtr(ptr1), 3U).Algid == 8704) { bool flag = false; IntPtr ptr2 = new IntPtr((long)num1 + (long)Marshal.OffsetOf(typeof(CAPI.CRYPTOAPI_BLOB), "cbData")); IntPtr ptr3 = new IntPtr((long)num1 + (long)Marshal.OffsetOf(typeof(CAPI.CRYPTOAPI_BLOB), "pbData")); if (Marshal.ReadInt32(ptr2) == 0) { flag = true; } else if (Marshal.ReadIntPtr(ptr3) == IntPtr.Zero) { flag = true; } else if (Marshal.ReadInt32(Marshal.ReadIntPtr(ptr3)) == 5) { flag = true; } if (flag) { SafeCertChainHandle invalidHandle = SafeCertChainHandle.InvalidHandle; X509Utils.BuildChain(new IntPtr(0L), X509Utils.GetCertContext(certificate), (X509Certificate2Collection)null, (OidCollection)null, (OidCollection)null, X509RevocationMode.NoCheck, X509RevocationFlag.ExcludeRoot, DateTime.Now, new TimeSpan(0, 0, 0), ref invalidHandle); invalidHandle.Dispose(); uint pcbData = 0U; if (!CAPI.CAPISafe.CertGetCertificateContextProperty(X509Utils.GetCertContext(certificate), 22U, pvData1, out pcbData)) { throw new CryptographicException(Marshal.GetLastWin32Error()); } if (pcbData > 0U) { pvData1 = CAPI.LocalAlloc(64U, new IntPtr((long)pcbData)); if (!CAPI.CAPISafe.CertGetCertificateContextProperty(X509Utils.GetCertContext(certificate), 22U, pvData1, out pcbData)) { throw new CryptographicException(Marshal.GetLastWin32Error()); } Marshal.WriteInt32(ptr2, (int)pcbData); Marshal.WriteIntPtr(ptr3, pvData1.DangerousGetHandle()); } } } if (this.m_parentSignerInfo == null) { if (!CAPI.CryptMsgControl(this.m_signedCms.GetCryptMsgHandle(), 0U, 1U, certContext.pCertInfo)) { throw new CryptographicException(Marshal.GetLastWin32Error()); } } else { int num2 = -1; int hr = 0; SafeLocalAllocHandle pvData2; while (true) { try { num2 = PkcsUtils.GetSignerIndex(this.m_signedCms.GetCryptMsgHandle(), this.m_parentSignerInfo, num2 + 1); } catch (CryptographicException ex) { if (hr != 0) { throw new CryptographicException(hr); } throw; } uint cbData = 0U; pvData2 = SafeLocalAllocHandle.InvalidHandle; PkcsUtils.GetParam(this.m_signedCms.GetCryptMsgHandle(), 28U, (uint)num2, out pvData2, out cbData); if ((int)cbData == 0) { hr = -2146885618; } else { fixed(byte *numPtr = this.m_encodedSignerInfo) { if (!CAPI.CAPISafe.CryptMsgVerifyCountersignatureEncoded(IntPtr.Zero, 65537U, pvData2.DangerousGetHandle(), cbData, new IntPtr((void *)numPtr), (uint)this.m_encodedSignerInfo.Length, certContext.pCertInfo)) { hr = Marshal.GetLastWin32Error(); } else { break; } } } } // ISSUE: fixed variable is out of scope // ISSUE: __unpin statement __unpin(numPtr); pvData2.Dispose(); } if (!verifySignatureOnly) { int hr = SignerInfo.VerifyCertificate(certificate, extraStore); if (hr != 0) { throw new CryptographicException(hr); } } pvData1.Dispose(); }
static SafeCertStoreHandle ExportToMemoryStore(X509Certificate2Collection collection, IntPtr pCertContext) { CAPI.CERT_CONTEXT certContext = (CAPI.CERT_CONTEXT)Marshal.PtrToStructure(pCertContext, typeof(CAPI.CERT_CONTEXT)); // No extra store nor intermediate certificates if ((collection == null || collection.Count <= 0) && certContext.hCertStore == IntPtr.Zero) { return(SafeCertStoreHandle.InvalidHandle); } // 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 certStoreHandle = CAPI.CertOpenStore( new IntPtr(CAPI.CERT_STORE_PROV_MEMORY), CAPI.X509_ASN_ENCODING | CAPI.PKCS_7_ASN_ENCODING, IntPtr.Zero, CAPI.CERT_STORE_ENUM_ARCHIVED_FLAG | CAPI.CERT_STORE_CREATE_NEW_FLAG, null); if (certStoreHandle == null || certStoreHandle.IsInvalid) { int error = Marshal.GetLastWin32Error(); throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CryptographicException(error)); } // // 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. // // Add extra store if (collection != null && collection.Count > 0) { foreach (X509Certificate2 x509 in collection) { if (!CAPI.CertAddCertificateLinkToStore(certStoreHandle, x509.Handle, CAPI.CERT_STORE_ADD_ALWAYS, SafeCertContextHandle.InvalidHandle)) { int error = Marshal.GetLastWin32Error(); throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CryptographicException(error)); } } } // Add intermediates // The hCertStore needs to be acquired from an X509Certificate2 object // constructed using a fresh cert context handle. If we simply refer to the hCertStore // property of the certContext local variable directly, there is a risk that we are accessing // a closed store. This is because if the X509Certificate2(rawdata) constructor closes the store handle (hCertStore). // There is no way to know which constructor was used at this point. // using (SafeCertContextHandle safeCertContext = CAPI.CertCreateCertificateContext(certContext.dwCertEncodingType, certContext.pbCertEncoded, certContext.cbCertEncoded)) { // // Create an X509Certificate2 using the new cert context that dup's the provided certificate. // X509Certificate2 intermediatesCert = new X509Certificate2(safeCertContext.DangerousGetHandle()); // // Dereference the handle to this intermediate cert and use it to access the handle // of this certificate's cert store. Then, call CAPI.CertAddCertificateLinkToStore // on each cert in this store by wrapping this cert store handle with an X509Store // object. // CAPI.CERT_CONTEXT intermediatesCertContext = (CAPI.CERT_CONTEXT)Marshal.PtrToStructure(intermediatesCert.Handle, typeof(CAPI.CERT_CONTEXT)); if (intermediatesCertContext.hCertStore != IntPtr.Zero) { X509Certificate2Collection intermediates = null; X509Store store = new X509Store(intermediatesCertContext.hCertStore); try { intermediates = store.Certificates; foreach (X509Certificate2 x509 in intermediates) { if (!CAPI.CertAddCertificateLinkToStore(certStoreHandle, x509.Handle, CAPI.CERT_STORE_ADD_ALWAYS, SafeCertContextHandle.InvalidHandle)) { int error = Marshal.GetLastWin32Error(); throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CryptographicException(error)); } } } finally { SecurityUtils.ResetAllCertificates(intermediates); store.Close(); } } } return(certStoreHandle); }
internal static unsafe CAPI.CMSG_SIGNER_ENCODE_INFO CreateSignerEncodeInfo(CmsSigner signer, bool silent) { CAPI.CMSG_SIGNER_ENCODE_INFO signerEncodeInfo = new CAPI.CMSG_SIGNER_ENCODE_INFO(Marshal.SizeOf(typeof(CAPI.CMSG_SIGNER_ENCODE_INFO))); SafeCryptProvHandle invalidHandle1 = SafeCryptProvHandle.InvalidHandle; uint pdwKeySpec = 0U; bool pfCallerFreeProv = false; signerEncodeInfo.HashAlgorithm.pszObjId = signer.DigestAlgorithm.Value; if (string.Compare(signer.Certificate.PublicKey.Oid.Value, "1.2.840.10040.4.1", StringComparison.Ordinal) == 0) { signerEncodeInfo.HashEncryptionAlgorithm.pszObjId = "1.2.840.10040.4.3"; } signerEncodeInfo.cAuthAttr = (uint)signer.SignedAttributes.Count; signerEncodeInfo.rgAuthAttr = PkcsUtils.CreateCryptAttributes(signer.SignedAttributes); signerEncodeInfo.cUnauthAttr = (uint)signer.UnsignedAttributes.Count; signerEncodeInfo.rgUnauthAttr = PkcsUtils.CreateCryptAttributes(signer.UnsignedAttributes); if (signer.SignerIdentifierType == SubjectIdentifierType.NoSignature) { signerEncodeInfo.HashEncryptionAlgorithm.pszObjId = "1.3.6.1.5.5.7.6.2"; signerEncodeInfo.pCertInfo = IntPtr.Zero; signerEncodeInfo.dwKeySpec = pdwKeySpec; if (!CAPI.CryptAcquireContext(out invalidHandle1, (string)null, (string)null, 1U, 4026531840U)) { throw new CryptographicException(Marshal.GetLastWin32Error()); } signerEncodeInfo.hCryptProv = invalidHandle1.DangerousGetHandle(); GC.SuppressFinalize((object)invalidHandle1); signerEncodeInfo.SignerId.dwIdChoice = 1U; X500DistinguishedName distinguishedName = new X500DistinguishedName("CN=Dummy Signer"); distinguishedName.Oid = new Oid("1.3.6.1.4.1.311.21.9"); signerEncodeInfo.SignerId.Value.IssuerSerialNumber.Issuer.cbData = (uint)distinguishedName.RawData.Length; SafeLocalAllocHandle localAllocHandle1 = CAPI.LocalAlloc(64U, new IntPtr((long)signerEncodeInfo.SignerId.Value.IssuerSerialNumber.Issuer.cbData)); Marshal.Copy(distinguishedName.RawData, 0, localAllocHandle1.DangerousGetHandle(), distinguishedName.RawData.Length); signerEncodeInfo.SignerId.Value.IssuerSerialNumber.Issuer.pbData = localAllocHandle1.DangerousGetHandle(); GC.SuppressFinalize((object)localAllocHandle1); signerEncodeInfo.SignerId.Value.IssuerSerialNumber.SerialNumber.cbData = 1U; SafeLocalAllocHandle localAllocHandle2 = CAPI.LocalAlloc(64U, new IntPtr((long)signerEncodeInfo.SignerId.Value.IssuerSerialNumber.SerialNumber.cbData)); *(sbyte *)(void *)localAllocHandle2.DangerousGetHandle() = (sbyte)0; signerEncodeInfo.SignerId.Value.IssuerSerialNumber.SerialNumber.pbData = localAllocHandle2.DangerousGetHandle(); GC.SuppressFinalize((object)localAllocHandle2); return(signerEncodeInfo); } else { System.Security.Cryptography.SafeCertContextHandle certContext1 = X509Utils.GetCertContext(signer.Certificate); if (!CAPI.CAPISafe.CryptAcquireCertificatePrivateKey(certContext1, silent ? 70U : 6U, IntPtr.Zero, out invalidHandle1, out pdwKeySpec, out pfCallerFreeProv)) { throw new CryptographicException(Marshal.GetLastWin32Error()); } signerEncodeInfo.dwKeySpec = pdwKeySpec; signerEncodeInfo.hCryptProv = invalidHandle1.DangerousGetHandle(); GC.SuppressFinalize((object)invalidHandle1); CAPI.CERT_CONTEXT certContext2 = *(CAPI.CERT_CONTEXT *)(void *) certContext1.DangerousGetHandle(); signerEncodeInfo.pCertInfo = certContext2.pCertInfo; if (signer.SignerIdentifierType == SubjectIdentifierType.SubjectKeyIdentifier) { uint pcbData = 0U; SafeLocalAllocHandle invalidHandle2 = SafeLocalAllocHandle.InvalidHandle; if (!CAPI.CAPISafe.CertGetCertificateContextProperty(certContext1, 20U, invalidHandle2, out pcbData)) { throw new CryptographicException(Marshal.GetLastWin32Error()); } if (pcbData > 0U) { SafeLocalAllocHandle pvData = CAPI.LocalAlloc(64U, new IntPtr((long)pcbData)); if (!CAPI.CAPISafe.CertGetCertificateContextProperty(certContext1, 20U, pvData, out pcbData)) { throw new CryptographicException(Marshal.GetLastWin32Error()); } signerEncodeInfo.SignerId.dwIdChoice = 2U; signerEncodeInfo.SignerId.Value.KeyId.cbData = pcbData; signerEncodeInfo.SignerId.Value.KeyId.pbData = pvData.DangerousGetHandle(); GC.SuppressFinalize((object)pvData); } } return(signerEncodeInfo); } }