private X509Chain BuildSignatureChain(X509Native.AXL_AUTHENTICODE_SIGNER_INFO signer, XmlElement licenseNode, X509RevocationFlag revocationFlag, X509RevocationMode revocationMode) { Debug.Assert(licenseNode != null, "licenseNode != null"); X509Chain signatureChain = null; if (signer.pChainContext != IntPtr.Zero) { signatureChain = new X509Chain(signer.pChainContext); } else if (signer.dwError == (int)SignatureVerificationResult.UntrustedRootCertificate) { // CertVerifyAuthenticodeLicense will not return the certificate chain for self signed certificates // so we'll need to extract the certificate from the signature ourselves. XmlElement x509Data = licenseNode.SelectSingleNode("r:issuer/ds:Signature/ds:KeyInfo/ds:X509Data", m_namespaceManager) as XmlElement; if (x509Data != null) { XmlNodeList certificateNodes = x509Data.SelectNodes("ds:X509Certificate", m_namespaceManager); // A manifest could have many X509Certificate nodes in its X509Data, which may include the // signing certificate, links on the chain to a root, or certificates not used at all in // the chain. Since we don't know which certificate actually did the signing, we only // process the chain if we have a single certificate. if (certificateNodes.Count == 1 && certificateNodes[0] is XmlElement) { byte[] rawCertificate = Convert.FromBase64String(certificateNodes[0].InnerText.Trim()); X509Certificate2 signingCertificate = new X509Certificate2(rawCertificate); signatureChain = new X509Chain(); signatureChain.ChainPolicy.RevocationFlag = revocationFlag; signatureChain.ChainPolicy.RevocationMode = revocationMode; signatureChain.Build(signingCertificate); } } } return(signatureChain); }
private X509Chain BuildSignatureChain(X509Native.AXL_AUTHENTICODE_SIGNER_INFO signer, XmlElement licenseNode, X509RevocationFlag revocationFlag, X509RevocationMode revocationMode) { X509Chain chain = null; if (signer.dwError == -2146762487) { XmlElement element = licenseNode.SelectSingleNode("r:issuer/ds:Signature/ds:KeyInfo/ds:X509Data", this.m_namespaceManager) as XmlElement; if (element != null) { X509Certificate2 certificate = new X509Certificate2(Convert.FromBase64String(element.InnerText.Trim())); chain = new X509Chain { ChainPolicy = { RevocationFlag = revocationFlag, RevocationMode = revocationMode } }; chain.Build(certificate); } return(chain); } if (signer.pChainContext != IntPtr.Zero) { chain = new X509Chain(signer.pChainContext); } return(chain); }
private AuthenticodeSignatureInformation VerifyAuthenticodeSignature(XmlElement signatureNode, X509RevocationFlag revocationFlag, X509RevocationMode revocationMode) { Debug.Assert(signatureNode != null, "signatureNode != null"); // See if there is an Authenticode signature on the manifest XmlElement licenseNode = signatureNode.SelectSingleNode("ds:KeyInfo/msrel:RelData/r:license", m_namespaceManager) as XmlElement; if (licenseNode == null) { return(null); } // Make sure that the signature is for this manifest SignatureVerificationResult identityVerification = VerifyAuthenticodeSignatureIdentity(licenseNode); if (identityVerification != SignatureVerificationResult.Valid) { return(new AuthenticodeSignatureInformation(identityVerification)); } SignatureVerificationResult hashVerification = VerifyAuthenticodeExpectedHash(licenseNode); if (hashVerification != SignatureVerificationResult.Valid) { return(new AuthenticodeSignatureInformation(hashVerification)); } // Verify the signature, extracting information about it AuthenticodeSignatureInformation authenticodeSignature = null; X509Native.AXL_AUTHENTICODE_SIGNER_INFO signer = new X509Native.AXL_AUTHENTICODE_SIGNER_INFO(); signer.cbSize = Marshal.SizeOf(typeof(X509Native.AXL_AUTHENTICODE_SIGNER_INFO)); X509Native.AXL_AUTHENTICODE_TIMESTAMPER_INFO timestamper = new X509Native.AXL_AUTHENTICODE_TIMESTAMPER_INFO(); timestamper.cbsize = Marshal.SizeOf(typeof(X509Native.AXL_AUTHENTICODE_TIMESTAMPER_INFO)); RuntimeHelpers.PrepareConstrainedRegions(); try { byte[] licenseXml = Encoding.UTF8.GetBytes(licenseNode.OuterXml); X509Native.AxlVerificationFlags verificationFlags = MapRevocationFlags(revocationFlag, revocationMode); unsafe { fixed(byte *pLicenseXml = licenseXml) { // Safe since we're verifying the size of this buffer is correct CapiNative.CRYPTOAPI_BLOB xmlBlob = new CapiNative.CRYPTOAPI_BLOB(); xmlBlob.cbData = licenseXml.Length; xmlBlob.pbData = new IntPtr(pLicenseXml); int hrVerify = X509Native.UnsafeNativeMethods.CertVerifyAuthenticodeLicense(ref xmlBlob, verificationFlags, ref signer, ref timestamper); if (hrVerify == (int)SignatureVerificationResult.MissingSignature) { return(new AuthenticodeSignatureInformation(SignatureVerificationResult.MissingSignature)); } } } X509Chain signatureChain = BuildSignatureChain(signer, licenseNode, revocationFlag, revocationMode); TimestampInformation timestamp = GetTimestampInformation(timestamper, licenseNode); authenticodeSignature = new AuthenticodeSignatureInformation(signer, signatureChain, timestamp); } finally { X509Native.UnsafeNativeMethods.CertFreeAuthenticodeSignerInfo(ref signer); X509Native.UnsafeNativeMethods.CertFreeAuthenticodeTimestamperInfo(ref timestamper); } // Verify the signing certificate matches the expected publisher Debug.Assert(authenticodeSignature != null, "authenticodeSignature != null"); if (authenticodeSignature.SigningCertificate == null) { return(new AuthenticodeSignatureInformation(authenticodeSignature.VerificationResult)); } SignatureVerificationResult publisherMatch = VerifyAuthenticodePublisher(authenticodeSignature.SigningCertificate); if (publisherMatch != SignatureVerificationResult.Valid) { return(new AuthenticodeSignatureInformation(publisherMatch)); } return(authenticodeSignature); }
private unsafe AuthenticodeSignatureInformation VerifyAuthenticodeSignature(XmlElement signatureNode, X509RevocationFlag revocationFlag, X509RevocationMode revocationMode) { XmlElement licenseNode = signatureNode.SelectSingleNode("ds:KeyInfo/msrel:RelData/r:license", this.m_namespaceManager) as XmlElement; if (licenseNode == null) { return(null); } SignatureVerificationResult error = this.VerifyAuthenticodeSignatureIdentity(licenseNode); if (error != SignatureVerificationResult.Valid) { return(new AuthenticodeSignatureInformation(error)); } SignatureVerificationResult result2 = this.VerifyAuthenticodeExpectedHash(licenseNode); if (result2 != SignatureVerificationResult.Valid) { return(new AuthenticodeSignatureInformation(result2)); } AuthenticodeSignatureInformation information = null; X509Native.AXL_AUTHENTICODE_SIGNER_INFO pSignerInfo = new X509Native.AXL_AUTHENTICODE_SIGNER_INFO { cbSize = Marshal.SizeOf(typeof(X509Native.AXL_AUTHENTICODE_SIGNER_INFO)) }; X509Native.AXL_AUTHENTICODE_TIMESTAMPER_INFO pTimestamperInfo = new X509Native.AXL_AUTHENTICODE_TIMESTAMPER_INFO { cbsize = Marshal.SizeOf(typeof(X509Native.AXL_AUTHENTICODE_TIMESTAMPER_INFO)) }; RuntimeHelpers.PrepareConstrainedRegions(); try { byte[] bytes = Encoding.UTF8.GetBytes(licenseNode.OuterXml); X509Native.AxlVerificationFlags dwFlags = MapRevocationFlags(revocationFlag, revocationMode); try { fixed(byte *numRef = bytes) { CapiNative.CRYPTOAPI_BLOB pLicenseBlob = new CapiNative.CRYPTOAPI_BLOB { cbData = bytes.Length, pbData = new IntPtr((void *)numRef) }; if (X509Native.UnsafeNativeMethods.CertVerifyAuthenticodeLicense(ref pLicenseBlob, dwFlags, ref pSignerInfo, ref pTimestamperInfo) == -2146762496) { return(new AuthenticodeSignatureInformation(SignatureVerificationResult.MissingSignature)); } } } finally { numRef = null; } X509Chain signatureChain = this.BuildSignatureChain(pSignerInfo, licenseNode, revocationFlag, revocationMode); TimestampInformation timestampInformation = this.GetTimestampInformation(pTimestamperInfo, licenseNode); information = new AuthenticodeSignatureInformation(pSignerInfo, signatureChain, timestampInformation); } finally { X509Native.UnsafeNativeMethods.CertFreeAuthenticodeSignerInfo(ref pSignerInfo); X509Native.UnsafeNativeMethods.CertFreeAuthenticodeTimestamperInfo(ref pTimestamperInfo); } if (information.SigningCertificate == null) { return(new AuthenticodeSignatureInformation(information.VerificationResult)); } SignatureVerificationResult result3 = this.VerifyAuthenticodePublisher(information.SigningCertificate); if (result3 != SignatureVerificationResult.Valid) { return(new AuthenticodeSignatureInformation(result3)); } return(information); }