in src/Tasks/ManifestUtil/mansign.cs [280:445]
internal void Verify(CmiManifestVerifyFlags verifyFlags)
{
// Reset signer infos.
_strongNameSignerInfo = null;
_authenticodeSignerInfo = null;
XmlNamespaceManager nsm = new XmlNamespaceManager(_manifestDom.NameTable);
nsm.AddNamespace("ds", SignedXml.XmlDsigNamespaceUrl);
XmlElement signatureNode = _manifestDom.SelectSingleNode("//ds:Signature", nsm) as XmlElement;
if (signatureNode == null)
{
throw new CryptographicException(Win32.TRUST_E_NOSIGNATURE);
}
// Make sure it is indeed SN signature, and it is an enveloped signature.
string snIdName = "Id";
if (!signatureNode.HasAttribute(snIdName))
{
snIdName = "id";
if (!signatureNode.HasAttribute(snIdName))
{
snIdName = "ID";
if (!signatureNode.HasAttribute(snIdName))
{
throw new CryptographicException(Win32.TRUST_E_SUBJECT_FORM_UNKNOWN);
}
}
}
string snIdValue = signatureNode.GetAttribute(snIdName);
if (snIdValue == null ||
String.Compare(snIdValue, "StrongNameSignature", StringComparison.Ordinal) != 0)
{
throw new CryptographicException(Win32.TRUST_E_SUBJECT_FORM_UNKNOWN);
}
// Make sure it is indeed an enveloped signature.
bool oldFormat = false;
bool validFormat = false;
XmlNodeList referenceNodes = signatureNode.SelectNodes("ds:SignedInfo/ds:Reference", nsm);
foreach (XmlNode referenceNode in referenceNodes)
{
XmlElement reference = referenceNode as XmlElement;
if (reference != null && reference.HasAttribute("URI"))
{
string uriValue = reference.GetAttribute("URI");
if (uriValue != null)
{
// We expect URI="" (empty URI value which means to hash the entire document).
if (uriValue.Length == 0)
{
XmlNode transformsNode = reference.SelectSingleNode("ds:Transforms", nsm);
if (transformsNode == null)
{
throw new CryptographicException(Win32.TRUST_E_SUBJECT_FORM_UNKNOWN);
}
// Make sure the transforms are what we expected.
XmlNodeList transforms = transformsNode.SelectNodes("ds:Transform", nsm);
if (transforms.Count < 2)
{
// We expect at least:
// <Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
// <Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" />
throw new CryptographicException(Win32.TRUST_E_SUBJECT_FORM_UNKNOWN);
}
bool c14 = false;
bool enveloped = false;
for (int i = 0; i < transforms.Count; i++)
{
XmlElement transform = transforms[i] as XmlElement;
string algorithm = transform.GetAttribute("Algorithm");
if (algorithm == null)
{
break;
}
else if (String.Compare(algorithm, SignedXml.XmlDsigExcC14NTransformUrl, StringComparison.Ordinal) != 0)
{
c14 = true;
if (enveloped)
{
validFormat = true;
break;
}
}
else if (String.Compare(algorithm, SignedXml.XmlDsigEnvelopedSignatureTransformUrl, StringComparison.Ordinal) != 0)
{
enveloped = true;
if (c14)
{
validFormat = true;
break;
}
}
}
}
else if (String.Compare(uriValue, "#StrongNameKeyInfo", StringComparison.Ordinal) == 0)
{
oldFormat = true;
XmlNode transformsNode = referenceNode.SelectSingleNode("ds:Transforms", nsm);
if (transformsNode == null)
{
throw new CryptographicException(Win32.TRUST_E_SUBJECT_FORM_UNKNOWN);
}
// Make sure the transforms are what we expected.
XmlNodeList transforms = transformsNode.SelectNodes("ds:Transform", nsm);
if (transforms.Count < 1)
{
// We expect at least:
// <Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
throw new CryptographicException(Win32.TRUST_E_SUBJECT_FORM_UNKNOWN);
}
for (int i = 0; i < transforms.Count; i++)
{
XmlElement transform = transforms[i] as XmlElement;
string algorithm = transform.GetAttribute("Algorithm");
if (algorithm == null)
{
break;
}
else if (String.Compare(algorithm, SignedXml.XmlDsigExcC14NTransformUrl, StringComparison.Ordinal) != 0)
{
validFormat = true;
break;
}
}
}
}
}
}
if (!validFormat)
{
throw new CryptographicException(Win32.TRUST_E_SUBJECT_FORM_UNKNOWN);
}
// It is the DSig we want, now make sure the public key matches the token.
string publicKeyToken = VerifyPublicKeyToken();
// OK. We found the SN signature with matching public key token, so
// instantiate the SN signer info property.
_strongNameSignerInfo = new CmiStrongNameSignerInfo(Win32.TRUST_E_FAIL, publicKeyToken);
// Now verify the SN signature, and Authenticode license if available.
ManifestSignedXml signedXml = new ManifestSignedXml(_manifestDom, true);
signedXml.LoadXml(signatureNode);
AsymmetricAlgorithm key = null;
bool dsigValid = signedXml.CheckSignatureReturningKey(out key);
_strongNameSignerInfo.PublicKey = key;
if (!dsigValid)
{
_strongNameSignerInfo.ErrorCode = Win32.TRUST_E_BAD_DIGEST;
throw new CryptographicException(Win32.TRUST_E_BAD_DIGEST);
}
// Verify license as well if requested.
if ((verifyFlags & CmiManifestVerifyFlags.StrongNameOnly) != CmiManifestVerifyFlags.StrongNameOnly)
{
VerifyLicense(verifyFlags, oldFormat);
}
}