Skip to content
This repository has been archived by the owner on Jan 23, 2023. It is now read-only.
/ corefx Public archive

Commit

Permalink
Merged PR 117476: [2.1-MSRC] Misc SignedXML fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
Ian Hays committed Apr 25, 2018
1 parent 35e4886 commit 8f968b9
Show file tree
Hide file tree
Showing 29 changed files with 846 additions and 72 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,8 @@ public override void LoadXml(XmlElement value)
throw new ArgumentNullException(nameof(value));

ReferenceType = value.LocalName;
Uri = Utils.GetAttribute(value, "URI", EncryptedXml.XmlEncNamespaceUrl);
string uri = Utils.GetAttribute(value, "URI", EncryptedXml.XmlEncNamespaceUrl);
Uri = uri ?? throw new CryptographicException(SR.Cryptography_Xml_UriRequired);

// Transforms
XmlNamespaceManager nsm = new XmlNamespaceManager(value.OwnerDocument.NameTable);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,21 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System.Diagnostics.CodeAnalysis;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace System.Security.Cryptography.Xml
{
internal static class CryptoHelpers
{
[SuppressMessage("Microsoft.Security", "CA5350", Justification = "SHA1 needed for compat.")]
[SuppressMessage("Microsoft.Security", "CA5351", Justification = "HMACMD5 needed for compat.")]
public static object CreateFromName(string name)
private static readonly char[] _invalidChars = new char[] { ',', '`', '[', '*', '&' };

[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA5350", Justification = "SHA1 needed for compat.")]
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA5351", Justification = "HMACMD5 needed for compat.")]
public static object CreateFromKnownName(string name)
{
switch (name)
{
Expand Down Expand Up @@ -73,7 +79,23 @@ public static object CreateFromName(string name)
return TripleDES.Create();
}

return CryptoConfig.CreateFromName(name);
return null;
}

public static T CreateFromName<T>(string name) where T : class
{
if (name == null || name.IndexOfAny(_invalidChars) >= 0)
{
return null;
}
try
{
return (CreateFromKnownName(name) ?? CryptoConfig.CreateFromName(name)) as T;
}
catch (Exception)
{
return null;
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,15 @@ public DSASignatureDescription()

public sealed override AsymmetricSignatureDeformatter CreateDeformatter(AsymmetricAlgorithm key)
{
var item = (AsymmetricSignatureDeformatter)CryptoHelpers.CreateFromName(DeformatterAlgorithm);
var item = (AsymmetricSignatureDeformatter)CryptoConfig.CreateFromName(DeformatterAlgorithm);
item.SetKey(key);
item.SetHashAlgorithm(HashAlgorithm);
return item;
}

public sealed override AsymmetricSignatureFormatter CreateFormatter(AsymmetricAlgorithm key)
{
var item = (AsymmetricSignatureFormatter)CryptoHelpers.CreateFromName(FormatterAlgorithm);
var item = (AsymmetricSignatureFormatter)CryptoConfig.CreateFromName(FormatterAlgorithm);
item.SetKey(key);
item.SetHashAlgorithm(HashAlgorithm);
return item;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,11 @@ public virtual void LoadXml(XmlElement value)
throw new ArgumentNullException(nameof(value));

ReferenceType = value.LocalName;
Uri = Utils.GetAttribute(value, "URI", EncryptedXml.XmlEncNamespaceUrl);

string uri = Utils.GetAttribute(value, "URI", EncryptedXml.XmlEncNamespaceUrl);
if (uri == null)
throw new ArgumentNullException(SR.Cryptography_Xml_UriRequired);
Uri = uri;

// Transforms
XmlNamespaceManager nsm = new XmlNamespaceManager(value.OwnerDocument.NameTable);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -197,21 +197,38 @@ private byte[] GetCipherValue(CipherData cipherData)
if (cipherData.CipherReference.CipherValue != null)
return cipherData.CipherReference.CipherValue;
Stream decInputStream = null;
if (cipherData.CipherReference.Uri == null)
{
throw new CryptographicException(SR.Cryptography_Xml_UriNotSupported);
}
// See if the CipherReference is a local URI
if (cipherData.CipherReference.Uri.Length == 0)
{
// self referenced Uri
string baseUri = (_document == null ? null : _document.BaseURI);
TransformChain tc = cipherData.CipherReference.TransformChain;
if (tc == null)
{
throw new CryptographicException(SR.Cryptography_Xml_UriNotSupported);
}
decInputStream = tc.TransformToOctetStream(_document, _xmlResolver, baseUri);
}
else if (cipherData.CipherReference.Uri[0] == '#')
{
string idref = Utils.ExtractIdFromLocalUri(cipherData.CipherReference.Uri);
// Serialize
inputStream = new MemoryStream(_encoding.GetBytes(GetIdElement(_document, idref).OuterXml));
XmlElement idElem = GetIdElement(_document, idref);
if (idElem == null || idElem.OuterXml == null)
{
throw new CryptographicException(SR.Cryptography_Xml_UriNotSupported);
}
inputStream = new MemoryStream(_encoding.GetBytes(idElem.OuterXml));
string baseUri = (_document == null ? null : _document.BaseURI);
TransformChain tc = cipherData.CipherReference.TransformChain;
if (tc == null)
{
throw new CryptographicException(SR.Cryptography_Xml_UriNotSupported);
}
decInputStream = tc.TransformToOctetStream(inputStream, _xmlResolver, baseUri);
}
else
Expand Down Expand Up @@ -361,7 +378,11 @@ public virtual SymmetricAlgorithm GetDecryptionKey(EncryptedData encryptedData,
if (key == null)
throw new CryptographicException(SR.Cryptography_Xml_MissingDecryptionKey);

SymmetricAlgorithm symAlg = (SymmetricAlgorithm)CryptoHelpers.CreateFromName(symmetricAlgorithmUri);
SymmetricAlgorithm symAlg = CryptoHelpers.CreateFromName<SymmetricAlgorithm>(symmetricAlgorithmUri);
if (symAlg == null)
{
throw new CryptographicException(SR.Cryptography_Xml_MissingAlgorithm);
}
symAlg.Key = key;
return symAlg;
}
Expand Down Expand Up @@ -394,6 +415,10 @@ public virtual byte[] DecryptEncryptedKey(EncryptedKey encryptedKey)
object kek = _keyNameMapping[keyName];
if (kek != null)
{
if (encryptedKey.CipherData == null || encryptedKey.CipherData.CipherValue == null)
{
throw new CryptographicException(SR.Cryptography_Xml_MissingAlgorithm);
}
// kek is either a SymmetricAlgorithm or an RSA key, otherwise, we wouldn't be able to insert it in the hash table
if (kek is SymmetricAlgorithm)
return EncryptedXml.DecryptKey(encryptedKey.CipherData.CipherValue, (SymmetricAlgorithm)kek);
Expand All @@ -414,6 +439,10 @@ public virtual byte[] DecryptEncryptedKey(EncryptedKey encryptedKey)
{
if (privateKey != null)
{
if (encryptedKey.CipherData == null || encryptedKey.CipherData.CipherValue == null)
{
throw new CryptographicException(SR.Cryptography_Xml_MissingAlgorithm);
}
fOAEP = (encryptedKey.EncryptionMethod != null && encryptedKey.EncryptionMethod.KeyAlgorithm == EncryptedXml.XmlEncRSAOAEPUrl);
return EncryptedXml.DecryptKey(encryptedKey.CipherData.CipherValue, privateKey, fOAEP);
}
Expand Down Expand Up @@ -456,7 +485,16 @@ public virtual byte[] DecryptEncryptedKey(EncryptedKey encryptedKey)
if (encryptionKey != null)
{
// this is a symmetric algorithm for sure
SymmetricAlgorithm symAlg = (SymmetricAlgorithm)CryptoHelpers.CreateFromName(encryptedKey.EncryptionMethod.KeyAlgorithm);
SymmetricAlgorithm symAlg = CryptoHelpers.CreateFromName<SymmetricAlgorithm>(encryptedKey.EncryptionMethod.KeyAlgorithm);
if (symAlg == null)
{
throw new CryptographicException(SR.Cryptography_Xml_MissingAlgorithm);
}
symAlg.Key = encryptionKey;
if (encryptedKey.CipherData == null || encryptedKey.CipherData.CipherValue == null)
{
throw new CryptographicException(SR.Cryptography_Xml_MissingAlgorithm);
}
symAlg.Key = encryptionKey;
return EncryptedXml.DecryptKey(encryptedKey.CipherData.CipherValue, symAlg);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ public void LoadXml(XmlElement value)

XmlElement keyInfoElement = value;
_id = Utils.GetAttribute(keyInfoElement, "Id", SignedXml.XmlDsigNamespaceUrl);
if (!Utils.VerifyAttributes(keyInfoElement, "Id"))
throw new CryptographicException(SR.Cryptography_Xml_InvalidElement, "KeyInfo");

XmlNode child = keyInfoElement.FirstChild;
while (child != null)
Expand All @@ -83,6 +85,10 @@ public void LoadXml(XmlElement value)
// Special-case handling for KeyValue -- we have to go one level deeper
if (kicString == "http://www.w3.org/2000/09/xmldsig# KeyValue")
{
if (!Utils.VerifyAttributes(elem, (string[])null))
{
throw new CryptographicException(SR.Cryptography_Xml_InvalidElement, "KeyInfo/KeyValue");
}
XmlNodeList nodeList2 = elem.ChildNodes;
foreach (XmlNode node2 in nodeList2)
{
Expand All @@ -94,7 +100,8 @@ public void LoadXml(XmlElement value)
}
}
}
KeyInfoClause keyInfoClause = (KeyInfoClause)CryptoHelpers.CreateFromName(kicString);

KeyInfoClause keyInfoClause = CryptoHelpers.CreateFromName<KeyInfoClause>(kicString);
// if we don't know what kind of KeyInfoClause we're looking at, use a generic KeyInfoNode:
if (keyInfoClause == null)
keyInfoClause = new KeyInfoNode();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,15 @@ public RSAPKCS1SignatureDescription(string hashAlgorithmName)

public sealed override AsymmetricSignatureDeformatter CreateDeformatter(AsymmetricAlgorithm key)
{
var item = (AsymmetricSignatureDeformatter)CryptoHelpers.CreateFromName(DeformatterAlgorithm);
var item = (AsymmetricSignatureDeformatter)CryptoConfig.CreateFromName(DeformatterAlgorithm);
item.SetKey(key);
item.SetHashAlgorithm(DigestAlgorithm);
return item;
}

public sealed override AsymmetricSignatureFormatter CreateFormatter(AsymmetricAlgorithm key)
{
var item = (AsymmetricSignatureFormatter)CryptoHelpers.CreateFromName(FormatterAlgorithm);
var item = (AsymmetricSignatureFormatter)CryptoConfig.CreateFromName(FormatterAlgorithm);
item.SetKey(key);
item.SetHashAlgorithm(DigestAlgorithm);
return item;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -219,25 +219,52 @@ public void LoadXml(XmlElement value)
_id = Utils.GetAttribute(value, "Id", SignedXml.XmlDsigNamespaceUrl);
_uri = Utils.GetAttribute(value, "URI", SignedXml.XmlDsigNamespaceUrl);
_type = Utils.GetAttribute(value, "Type", SignedXml.XmlDsigNamespaceUrl);
if (!Utils.VerifyAttributes(value, new string[] { "Id", "URI", "Type" }))
throw new CryptographicException(SR.Cryptography_Xml_InvalidElement, "Reference");

XmlNamespaceManager nsm = new XmlNamespaceManager(value.OwnerDocument.NameTable);
nsm.AddNamespace("ds", SignedXml.XmlDsigNamespaceUrl);

// Transforms
bool hasTransforms = false;
TransformChain = new TransformChain();
XmlElement transformsElement = value.SelectSingleNode("ds:Transforms", nsm) as XmlElement;
if (transformsElement != null)
XmlNodeList transformsNodes = value.SelectNodes("ds:Transforms", nsm);
if (transformsNodes != null && transformsNodes.Count != 0)
{
if (transformsNodes.Count > 1)
{
throw new CryptographicException(SR.Cryptography_Xml_InvalidElement, "Reference/Transforms");
}
hasTransforms = true;
XmlElement transformsElement = transformsNodes[0] as XmlElement;
if (!Utils.VerifyAttributes(transformsElement, (string[])null))
{
throw new CryptographicException(SR.Cryptography_Xml_InvalidElement, "Reference/Transforms");
}
XmlNodeList transformNodes = transformsElement.SelectNodes("ds:Transform", nsm);
if (transformNodes != null)
{
if (transformNodes.Count != transformsElement.SelectNodes("*").Count)
{
throw new CryptographicException(SR.Cryptography_Xml_InvalidElement, "Reference/Transforms");
}
if (transformNodes.Count > Utils.MaxTransformsPerReference)
{
throw new CryptographicException(SR.Cryptography_Xml_InvalidElement, "Reference/Transforms");
}
foreach (XmlNode transformNode in transformNodes)
{
XmlElement transformElement = transformNode as XmlElement;
string algorithm = Utils.GetAttribute(transformElement, "Algorithm", SignedXml.XmlDsigNamespaceUrl);
Transform transform = CryptoHelpers.CreateFromName(algorithm) as Transform;
if (algorithm == null || !Utils.VerifyAttributes(transformElement, "Algorithm"))
{
throw new CryptographicException(SR.Cryptography_Xml_UnknownTransform);
}
Transform transform = CryptoHelpers.CreateFromName<Transform>(algorithm);
if (transform == null)
{
throw new CryptographicException(SR.Cryptography_Xml_UnknownTransform);
}
AddTransform(transform);
// let the transform read the children of the transformElement for data
transform.LoadInnerXml(transformElement.ChildNodes);
Expand Down Expand Up @@ -267,16 +294,27 @@ public void LoadXml(XmlElement value)
}

// DigestMethod
XmlElement digestMethodElement = value.SelectSingleNode("ds:DigestMethod", nsm) as XmlElement;
if (digestMethodElement == null)
XmlNodeList digestMethodNodes = value.SelectNodes("ds:DigestMethod", nsm);
if (digestMethodNodes == null || digestMethodNodes.Count == 0 || digestMethodNodes.Count > 1)
throw new CryptographicException(SR.Cryptography_Xml_InvalidElement, "Reference/DigestMethod");
XmlElement digestMethodElement = digestMethodNodes[0] as XmlElement;
_digestMethod = Utils.GetAttribute(digestMethodElement, "Algorithm", SignedXml.XmlDsigNamespaceUrl);
if (_digestMethod == null || !Utils.VerifyAttributes(digestMethodElement, "Algorithm"))
throw new CryptographicException(SR.Cryptography_Xml_InvalidElement, "Reference/DigestMethod");


// DigestValue
XmlElement digestValueElement = value.SelectSingleNode("ds:DigestValue", nsm) as XmlElement;
if (digestValueElement == null)
XmlNodeList digestValueNodes = value.SelectNodes("ds:DigestValue", nsm);
if (digestValueNodes == null || digestValueNodes.Count == 0 || digestValueNodes.Count > 1)
throw new CryptographicException(SR.Cryptography_Xml_InvalidElement, "Reference/DigestValue");
XmlElement digestValueElement = digestValueNodes[0] as XmlElement;
_digestValue = Convert.FromBase64String(Utils.DiscardWhiteSpaces(digestValueElement.InnerText));
if (!Utils.VerifyAttributes(digestValueElement, (string[])null))
throw new CryptographicException(SR.Cryptography_Xml_InvalidElement, "Reference/DigestValue");
// Verify that there aren't any extra nodes that aren't allowed
int expectedChildNodeCount = hasTransforms ? 3 : 2;
if (value.SelectNodes("*").Count != expectedChildNodeCount)
throw new CryptographicException(SR.Cryptography_Xml_InvalidElement, "Reference");

// cache the Xml
_cachedXml = value;
Expand Down Expand Up @@ -304,7 +342,7 @@ internal byte[] CalculateHashValue(XmlDocument document, CanonicalXmlNodeList re
{
// refList is a list of elements that might be targets of references
// Now's the time to create our hashing algorithm
_hashAlgorithm = CryptoHelpers.CreateFromName(_digestMethod) as HashAlgorithm;
_hashAlgorithm = CryptoHelpers.CreateFromName<HashAlgorithm>(_digestMethod);
if (_hashAlgorithm == null)
throw new CryptographicException(SR.Cryptography_Xml_CreateHashAlgorithmFailed);

Expand Down
Loading

0 comments on commit 8f968b9

Please sign in to comment.