in src/Tasks/ManifestUtil/mansign2.cs [289:472]
private void VerifyLicenseNew(CmiManifestVerifyFlags verifyFlags, bool oldFormat)
{
XmlNamespaceManager nsm = new XmlNamespaceManager(_manifestDom.NameTable);
nsm.AddNamespace("asm", AssemblyNamespaceUri);
nsm.AddNamespace("asm2", AssemblyV2NamespaceUri);
nsm.AddNamespace("ds", SignedXml.XmlDsigNamespaceUrl);
nsm.AddNamespace("msrel", MSRelNamespaceUri);
nsm.AddNamespace("r", LicenseNamespaceUri);
nsm.AddNamespace("as", AuthenticodeNamespaceUri);
// We are done if no license.
XmlElement licenseNode = _manifestDom.SelectSingleNode("asm:assembly/ds:Signature/ds:KeyInfo/msrel:RelData/r:license", nsm) as XmlElement;
if (licenseNode == null)
{
return;
}
// Make sure this license is for this manifest.
VerifyAssemblyIdentity(nsm);
// Found a license, so instantiate signer info property.
_authenticodeSignerInfo = new CmiAuthenticodeSignerInfo(Win32.TRUST_E_FAIL);
// Find the license's signature
XmlElement signatureNode = licenseNode.SelectSingleNode("//r:issuer/ds:Signature", nsm) as XmlElement;
if (signatureNode == null)
{
throw new CryptographicException(Win32.TRUST_E_NOSIGNATURE);
}
// Make sure it is indeed an Authenticode signature, and it is an enveloped signature.
// Then make sure the transforms are valid.
VerifySignatureForm(signatureNode, "AuthenticodeSignature", nsm);
// Now read the enveloped license signature.
XmlDocument licenseDom = new XmlDocument();
licenseDom.LoadXml(licenseNode.OuterXml);
signatureNode = licenseDom.SelectSingleNode("//r:issuer/ds:Signature", nsm) as XmlElement;
ManifestSignedXml2 signedXml = new ManifestSignedXml2(licenseDom);
signedXml.LoadXml(signatureNode);
if (_useSha256)
{
signedXml.SignedInfo.SignatureMethod = Sha256SignatureMethodUri;
}
// Check the signature
if (!signedXml.CheckSignature())
{
_authenticodeSignerInfo = null;
throw new CryptographicException(Win32.TRUST_E_CERT_SIGNATURE);
}
X509Certificate2 signingCertificate = GetSigningCertificate(signedXml, nsm);
// First make sure certificate is not explicitly disallowed.
X509Store store = new X509Store(StoreName.Disallowed, StoreLocation.CurrentUser);
store.Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly);
X509Certificate2Collection storedCertificates = null;
try
{
storedCertificates = (X509Certificate2Collection)store.Certificates;
if (storedCertificates == null)
{
_authenticodeSignerInfo.ErrorCode = Win32.TRUST_E_FAIL;
throw new CryptographicException(Win32.TRUST_E_FAIL);
}
if (storedCertificates.Contains(signingCertificate))
{
_authenticodeSignerInfo.ErrorCode = Win32.TRUST_E_EXPLICIT_DISTRUST;
throw new CryptographicException(Win32.TRUST_E_EXPLICIT_DISTRUST);
}
}
finally
{
store.Close();
}
// prepare information for the TrustManager to display
string hash;
string description;
string url;
if (!GetManifestInformation(licenseNode, nsm, out hash, out description, out url))
{
_authenticodeSignerInfo.ErrorCode = Win32.TRUST_E_SUBJECT_FORM_UNKNOWN;
throw new CryptographicException(Win32.TRUST_E_SUBJECT_FORM_UNKNOWN);
}
_authenticodeSignerInfo.Hash = hash;
_authenticodeSignerInfo.Description = description;
_authenticodeSignerInfo.DescriptionUrl = url;
// read the timestamp from the manifest
DateTime verificationTime;
bool isTimestamped = VerifySignatureTimestamp(signatureNode, nsm, out verificationTime);
bool isLifetimeSigning = false;
if (isTimestamped)
{
isLifetimeSigning = ((verifyFlags & CmiManifestVerifyFlags.LifetimeSigning) == CmiManifestVerifyFlags.LifetimeSigning);
if (!isLifetimeSigning)
{
isLifetimeSigning = GetLifetimeSigning(signingCertificate);
}
}
// Retrieve the Authenticode policy settings from registry.
uint policies = GetAuthenticodePolicies();
X509Chain chain = new X509Chain(); // use the current user profile
chain.ChainPolicy.RevocationFlag = X509RevocationFlag.ExcludeRoot;
chain.ChainPolicy.RevocationMode = X509RevocationMode.Online;
if ((CmiManifestVerifyFlags.RevocationCheckEndCertOnly & verifyFlags) == CmiManifestVerifyFlags.RevocationCheckEndCertOnly)
{
chain.ChainPolicy.RevocationFlag = X509RevocationFlag.EndCertificateOnly;
}
else if ((CmiManifestVerifyFlags.RevocationCheckEntireChain & verifyFlags) == CmiManifestVerifyFlags.RevocationCheckEntireChain)
{
chain.ChainPolicy.RevocationFlag = X509RevocationFlag.EntireChain;
}
else if (((CmiManifestVerifyFlags.RevocationNoCheck & verifyFlags) == CmiManifestVerifyFlags.RevocationNoCheck) ||
((Win32.WTPF_IGNOREREVOKATION & policies) == Win32.WTPF_IGNOREREVOKATION))
{
chain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck;
}
chain.ChainPolicy.VerificationTime = verificationTime; // local time
if (isTimestamped && isLifetimeSigning)
{
chain.ChainPolicy.ApplicationPolicy.Add(new Oid(Win32.szOID_KP_LIFETIME_SIGNING));
}
chain.ChainPolicy.UrlRetrievalTimeout = new TimeSpan(0, 1, 0);
chain.ChainPolicy.VerificationFlags = X509VerificationFlags.NoFlag; // don't ignore anything
bool chainIsValid = chain.Build(signingCertificate);
if (!chainIsValid)
{
#if DEBUG
X509ChainStatus[] statuses = chain.ChainStatus;
foreach (X509ChainStatus status in statuses)
{
System.Diagnostics.Debug.WriteLine("flag = " + status.Status + " " + status.StatusInformation);
}
#endif
AuthenticodeSignerInfo.ErrorCode = Win32.TRUST_E_SUBJECT_NOT_TRUSTED;
throw new CryptographicException(Win32.TRUST_E_SUBJECT_NOT_TRUSTED);
}
// package information for the trust manager
_authenticodeSignerInfo.SignerChain = chain;
store = new X509Store(StoreName.TrustedPublisher, StoreLocation.CurrentUser);
store.Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly);
try
{
storedCertificates = (X509Certificate2Collection)store.Certificates;
if (storedCertificates == null)
{
_authenticodeSignerInfo.ErrorCode = Win32.TRUST_E_FAIL;
throw new CryptographicException(Win32.TRUST_E_FAIL);
}
if (!storedCertificates.Contains(signingCertificate))
{
AuthenticodeSignerInfo.ErrorCode = Win32.TRUST_E_SUBJECT_NOT_TRUSTED;
throw new CryptographicException(Win32.TRUST_E_SUBJECT_NOT_TRUSTED);
}
}
finally
{
store.Close();
}
// Verify Certificate publisher name
XmlElement subjectNode = licenseNode.SelectSingleNode("r:grant/as:AuthenticodePublisher/as:X509SubjectName", nsm) as XmlElement;
if (subjectNode == null || String.Compare(signingCertificate.Subject, subjectNode.InnerText, StringComparison.Ordinal) != 0)
{
AuthenticodeSignerInfo.ErrorCode = Win32.TRUST_E_CERT_SIGNATURE;
throw new CryptographicException(Win32.TRUST_E_CERT_SIGNATURE);
}
if (!oldFormat)
// Make sure we have the intended Authenticode signer.
VerifyPublisherIdentity(nsm);
}