From 8f968b9e79c5721d78cc88e46fe57457fe9d490d Mon Sep 17 00:00:00 2001 From: Ian Hays Date: Wed, 25 Apr 2018 15:22:17 +0000 Subject: [PATCH] Merged PR 117476: [2.1-MSRC] Misc SignedXML fixes --- .../Cryptography/Xml/CipherReference.cs | 3 +- .../Cryptography/Xml/CryptoHelpers.cs | 32 +++- .../Xml/DSASignatureDescription.cs | 4 +- .../Cryptography/Xml/EncryptedReference.cs | 6 +- .../Security/Cryptography/Xml/EncryptedXml.cs | 44 ++++- .../Security/Cryptography/Xml/KeyInfo.cs | 9 +- .../Xml/RSAPKCS1SignatureDescription.cs | 4 +- .../Security/Cryptography/Xml/Reference.cs | 54 +++++- .../Security/Cryptography/Xml/Signature.cs | 32 +++- .../Security/Cryptography/Xml/SignedInfo.cs | 32 +++- .../Security/Cryptography/Xml/SignedXml.cs | 6 +- .../Cryptography/Xml/SignedXmlDebugLog.cs | 12 +- .../Cryptography/Xml/TransformChain.cs | 2 +- .../System/Security/Cryptography/Xml/Utils.cs | 26 +++ .../Xml/XmlDecryptionTransform.cs | 25 ++- .../Cryptography/Xml/XmlDsigC14NTransform.cs | 6 +- .../Xml/XmlDsigEnvelopedSignatureTransform.cs | 6 +- .../Xml/XmlDsigExcC14NTransform.cs | 21 ++- .../Cryptography/Xml/XmlDsigXPathTransform.cs | 41 +++-- .../Cryptography/Xml/XmlLicenseTransform.cs | 6 +- .../tests/KeyInfo_ArbitraryElements.cs | 33 ++++ .../tests/Reference_ArbitraryElements.cs | 156 ++++++++++++++++++ .../tests/Signature_ArbitraryElements.cs | 153 +++++++++++++++++ .../tests/SignedInfo_ArbitraryElements.cs | 81 +++++++++ .../tests/SignedXml_Helpers.cs | 34 ++++ .../tests/SignedXml_Limits.cs | 41 +++++ .../SignedXml_SignatureMethodAlgorithm.cs | 38 +++++ ...tem.Security.Cryptography.Xml.Tests.csproj | 9 +- .../tests/XmlDecryptionTransformTest.cs | 2 +- 29 files changed, 846 insertions(+), 72 deletions(-) create mode 100644 src/System.Security.Cryptography.Xml/tests/KeyInfo_ArbitraryElements.cs create mode 100644 src/System.Security.Cryptography.Xml/tests/Reference_ArbitraryElements.cs create mode 100644 src/System.Security.Cryptography.Xml/tests/Signature_ArbitraryElements.cs create mode 100644 src/System.Security.Cryptography.Xml/tests/SignedInfo_ArbitraryElements.cs create mode 100644 src/System.Security.Cryptography.Xml/tests/SignedXml_Helpers.cs create mode 100644 src/System.Security.Cryptography.Xml/tests/SignedXml_Limits.cs create mode 100644 src/System.Security.Cryptography.Xml/tests/SignedXml_SignatureMethodAlgorithm.cs diff --git a/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/CipherReference.cs b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/CipherReference.cs index 079a5d09f75f..5dd3dd296810 100644 --- a/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/CipherReference.cs +++ b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/CipherReference.cs @@ -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); diff --git a/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/CryptoHelpers.cs b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/CryptoHelpers.cs index a857475d3e40..d73702fdac7d 100644 --- a/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/CryptoHelpers.cs +++ b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/CryptoHelpers.cs @@ -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) { @@ -73,7 +79,23 @@ public static object CreateFromName(string name) return TripleDES.Create(); } - return CryptoConfig.CreateFromName(name); + return null; + } + + public static T CreateFromName(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; + } } } } diff --git a/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/DSASignatureDescription.cs b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/DSASignatureDescription.cs index 4c74f878f473..ca0ff8d3e8ad 100644 --- a/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/DSASignatureDescription.cs +++ b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/DSASignatureDescription.cs @@ -20,7 +20,7 @@ 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; @@ -28,7 +28,7 @@ public sealed override AsymmetricSignatureDeformatter CreateDeformatter(Asymmetr 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; diff --git a/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/EncryptedReference.cs b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/EncryptedReference.cs index 4c8b5fddc54f..0c92ff1c7982 100644 --- a/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/EncryptedReference.cs +++ b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/EncryptedReference.cs @@ -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); diff --git a/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/EncryptedXml.cs b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/EncryptedXml.cs index 19202e33b2a3..574799c281e6 100644 --- a/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/EncryptedXml.cs +++ b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/EncryptedXml.cs @@ -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 @@ -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(symmetricAlgorithmUri); + if (symAlg == null) + { + throw new CryptographicException(SR.Cryptography_Xml_MissingAlgorithm); + } symAlg.Key = key; return symAlg; } @@ -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); @@ -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); } @@ -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(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); } diff --git a/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/KeyInfo.cs b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/KeyInfo.cs index 50ca8a58039f..d69b0ef8643e 100644 --- a/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/KeyInfo.cs +++ b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/KeyInfo.cs @@ -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) @@ -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) { @@ -94,7 +100,8 @@ public void LoadXml(XmlElement value) } } } - KeyInfoClause keyInfoClause = (KeyInfoClause)CryptoHelpers.CreateFromName(kicString); + + KeyInfoClause keyInfoClause = CryptoHelpers.CreateFromName(kicString); // if we don't know what kind of KeyInfoClause we're looking at, use a generic KeyInfoNode: if (keyInfoClause == null) keyInfoClause = new KeyInfoNode(); diff --git a/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/RSAPKCS1SignatureDescription.cs b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/RSAPKCS1SignatureDescription.cs index 2fc6a3d81005..ab37fbd98e4b 100644 --- a/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/RSAPKCS1SignatureDescription.cs +++ b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/RSAPKCS1SignatureDescription.cs @@ -16,7 +16,7 @@ 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; @@ -24,7 +24,7 @@ public sealed override AsymmetricSignatureDeformatter CreateDeformatter(Asymmetr 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; diff --git a/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/Reference.cs b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/Reference.cs index a34d3d492c6c..b608cf077af3 100644 --- a/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/Reference.cs +++ b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/Reference.cs @@ -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(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); @@ -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; @@ -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(_digestMethod); if (_hashAlgorithm == null) throw new CryptographicException(SR.Cryptography_Xml_CreateHashAlgorithmFailed); diff --git a/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/Signature.cs b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/Signature.cs index e023d983f566..d755de9e7365 100644 --- a/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/Signature.cs +++ b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/Signature.cs @@ -148,37 +148,53 @@ public void LoadXml(XmlElement value) // Id attribute -- optional _id = Utils.GetAttribute(signatureElement, "Id", SignedXml.XmlDsigNamespaceUrl); + if (!Utils.VerifyAttributes(signatureElement, "Id")) + throw new CryptographicException(SR.Cryptography_Xml_InvalidElement, "Signature"); XmlNamespaceManager nsm = new XmlNamespaceManager(value.OwnerDocument.NameTable); nsm.AddNamespace("ds", SignedXml.XmlDsigNamespaceUrl); + int expectedChildNodes = 0; // SignedInfo - XmlElement signedInfoElement = signatureElement.SelectSingleNode("ds:SignedInfo", nsm) as XmlElement; - if (signedInfoElement == null) + XmlNodeList signedInfoNodes = signatureElement.SelectNodes("ds:SignedInfo", nsm); + if (signedInfoNodes == null || signedInfoNodes.Count == 0 || signedInfoNodes.Count > 1) throw new CryptographicException(SR.Cryptography_Xml_InvalidElement, "SignedInfo"); + XmlElement signedInfoElement = signedInfoNodes[0] as XmlElement; + expectedChildNodes += signedInfoNodes.Count; SignedInfo = new SignedInfo(); SignedInfo.LoadXml(signedInfoElement); // SignatureValue - XmlElement signatureValueElement = signatureElement.SelectSingleNode("ds:SignatureValue", nsm) as XmlElement; - if (signatureValueElement == null) - throw new CryptographicException(SR.Cryptography_Xml_InvalidElement, "SignedInfo/SignatureValue"); + XmlNodeList signatureValueNodes = signatureElement.SelectNodes("ds:SignatureValue", nsm); + if (signatureValueNodes == null || signatureValueNodes.Count == 0 || signatureValueNodes.Count > 1) + throw new CryptographicException(SR.Cryptography_Xml_InvalidElement, "SignatureValue"); + XmlElement signatureValueElement = signatureValueNodes[0] as XmlElement; + expectedChildNodes += signatureValueNodes.Count; _signatureValue = Convert.FromBase64String(Utils.DiscardWhiteSpaces(signatureValueElement.InnerText)); _signatureValueId = Utils.GetAttribute(signatureValueElement, "Id", SignedXml.XmlDsigNamespaceUrl); + if (!Utils.VerifyAttributes(signatureValueElement, "Id")) + throw new CryptographicException(SR.Cryptography_Xml_InvalidElement, "SignatureValue"); + // KeyInfo - optional single element XmlNodeList keyInfoNodes = signatureElement.SelectNodes("ds:KeyInfo", nsm); _keyInfo = new KeyInfo(); if (keyInfoNodes != null) { + if (keyInfoNodes.Count > 1) + { + throw new CryptographicException(SR.Cryptography_Xml_InvalidElement, "KeyInfo"); + } foreach (XmlNode node in keyInfoNodes) { XmlElement keyInfoElement = node as XmlElement; if (keyInfoElement != null) _keyInfo.LoadXml(keyInfoElement); } + expectedChildNodes += keyInfoNodes.Count; } + // Object - zero or more elements allowed XmlNodeList objectNodes = signatureElement.SelectNodes("ds:Object", nsm); _embeddedObjects.Clear(); if (objectNodes != null) @@ -193,6 +209,7 @@ public void LoadXml(XmlElement value) _embeddedObjects.Add(dataObj); } } + expectedChildNodes += objectNodes.Count; } // Select all elements that have Id attributes @@ -204,6 +221,11 @@ public void LoadXml(XmlElement value) _referencedItems.Add(node); } } + // Verify that there aren't any extra nodes that aren't allowed + if (signatureElement.SelectNodes("*").Count != expectedChildNodes) + { + throw new CryptographicException(SR.Cryptography_Xml_InvalidElement, "Signature"); + } } public void AddObject(DataObject dataObject) diff --git a/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/SignedInfo.cs b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/SignedInfo.cs index 30408790d4d1..f87416ec5a31 100644 --- a/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/SignedInfo.cs +++ b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/SignedInfo.cs @@ -98,7 +98,7 @@ public Transform CanonicalizationMethodObject { if (_canonicalizationMethodTransform == null) { - _canonicalizationMethodTransform = CryptoHelpers.CreateFromName(CanonicalizationMethod) as Transform; + _canonicalizationMethodTransform = CryptoHelpers.CreateFromName(CanonicalizationMethod); if (_canonicalizationMethodTransform == null) throw new CryptographicException(string.Format(CultureInfo.CurrentCulture, SR.Cryptography_Xml_CreateTransformFailed, CanonicalizationMethod)); _canonicalizationMethodTransform.SignedXml = SignedXml; @@ -213,24 +213,35 @@ public void LoadXml(XmlElement value) XmlNamespaceManager nsm = new XmlNamespaceManager(value.OwnerDocument.NameTable); nsm.AddNamespace("ds", SignedXml.XmlDsigNamespaceUrl); + int expectedChildNodes = 0; // Id attribute -- optional _id = Utils.GetAttribute(signedInfoElement, "Id", SignedXml.XmlDsigNamespaceUrl); + if (!Utils.VerifyAttributes(signedInfoElement, "Id")) + throw new CryptographicException(SR.Cryptography_Xml_InvalidElement, "SignedInfo"); // CanonicalizationMethod -- must be present - XmlElement canonicalizationMethodElement = signedInfoElement.SelectSingleNode("ds:CanonicalizationMethod", nsm) as XmlElement; - if (canonicalizationMethodElement == null) + XmlNodeList canonicalizationMethodNodes = signedInfoElement.SelectNodes("ds:CanonicalizationMethod", nsm); + if (canonicalizationMethodNodes == null || canonicalizationMethodNodes.Count == 0 || canonicalizationMethodNodes.Count > 1) throw new CryptographicException(SR.Cryptography_Xml_InvalidElement, "SignedInfo/CanonicalizationMethod"); + XmlElement canonicalizationMethodElement = canonicalizationMethodNodes.Item(0) as XmlElement; + expectedChildNodes += canonicalizationMethodNodes.Count; _canonicalizationMethod = Utils.GetAttribute(canonicalizationMethodElement, "Algorithm", SignedXml.XmlDsigNamespaceUrl); + if (_canonicalizationMethod == null || !Utils.VerifyAttributes(canonicalizationMethodElement, "Algorithm")) + throw new CryptographicException(SR.Cryptography_Xml_InvalidElement, "SignedInfo/CanonicalizationMethod"); _canonicalizationMethodTransform = null; if (canonicalizationMethodElement.ChildNodes.Count > 0) CanonicalizationMethodObject.LoadInnerXml(canonicalizationMethodElement.ChildNodes); // SignatureMethod -- must be present - XmlElement signatureMethodElement = signedInfoElement.SelectSingleNode("ds:SignatureMethod", nsm) as XmlElement; - if (signatureMethodElement == null) + XmlNodeList signatureMethodNodes = signedInfoElement.SelectNodes("ds:SignatureMethod", nsm); + if (signatureMethodNodes == null || signatureMethodNodes.Count == 0 || signatureMethodNodes.Count > 1) throw new CryptographicException(SR.Cryptography_Xml_InvalidElement, "SignedInfo/SignatureMethod"); + XmlElement signatureMethodElement = signatureMethodNodes.Item(0) as XmlElement; + expectedChildNodes += signatureMethodNodes.Count; _signatureMethod = Utils.GetAttribute(signatureMethodElement, "Algorithm", SignedXml.XmlDsigNamespaceUrl); + if (_signatureMethod == null || !Utils.VerifyAttributes(signatureMethodElement, "Algorithm")) + throw new CryptographicException(SR.Cryptography_Xml_InvalidElement, "SignedInfo/SignatureMethod"); // Now get the output length if we are using a MAC algorithm XmlElement signatureLengthElement = signatureMethodElement.SelectSingleNode("ds:HMACOutputLength", nsm) as XmlElement; @@ -240,9 +251,14 @@ public void LoadXml(XmlElement value) // flush out any reference that was there _references.Clear(); + // Reference - 0 or more XmlNodeList referenceNodes = signedInfoElement.SelectNodes("ds:Reference", nsm); if (referenceNodes != null) { + if (referenceNodes.Count > Utils.MaxReferencesPerSignedInfo) + { + throw new CryptographicException(SR.Cryptography_Xml_InvalidElement, "SignedInfo/Reference"); + } foreach (XmlNode node in referenceNodes) { XmlElement referenceElement = node as XmlElement; @@ -250,6 +266,12 @@ public void LoadXml(XmlElement value) AddReference(reference); reference.LoadXml(referenceElement); } + expectedChildNodes += referenceNodes.Count; + // Verify that there aren't any extra nodes that aren't allowed + if (signedInfoElement.SelectNodes("*").Count != expectedChildNodes) + { + throw new CryptographicException(SR.Cryptography_Xml_InvalidElement, "SignedInfo"); + } } // Save away the cached value diff --git a/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/SignedXml.cs b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/SignedXml.cs index dfe3774358f7..b90f3fdd2f17 100644 --- a/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/SignedXml.cs +++ b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/SignedXml.cs @@ -410,7 +410,7 @@ public void ComputeSignature() } // See if there is a signature description class defined in the Config file - SignatureDescription signatureDescription = CryptoHelpers.CreateFromName(SignedInfo.SignatureMethod) as SignatureDescription; + SignatureDescription signatureDescription = CryptoHelpers.CreateFromName(SignedInfo.SignatureMethod); if (signatureDescription == null) throw new CryptographicException(SR.Cryptography_Xml_SignatureDescriptionNotCreated); HashAlgorithm hashAlg = signatureDescription.CreateDigest(); @@ -653,7 +653,7 @@ private bool DoesSignatureUseTruncatedHmac() } // See if we're signed witn an HMAC algorithm - HMAC hmac = CryptoHelpers.CreateFromName(SignatureMethod) as HMAC; + HMAC hmac = CryptoHelpers.CreateFromName(SignatureMethod); if (hmac == null) { // We aren't signed with an HMAC algorithm, so we cannot have a truncated HMAC @@ -1017,7 +1017,7 @@ private bool CheckSignedInfo(AsymmetricAlgorithm key) SignedXmlDebugLog.LogBeginCheckSignedInfo(this, m_signature.SignedInfo); - SignatureDescription signatureDescription = CryptoHelpers.CreateFromName(SignatureMethod) as SignatureDescription; + SignatureDescription signatureDescription = CryptoHelpers.CreateFromName(SignatureMethod); if (signatureDescription == null) throw new CryptographicException(SR.Cryptography_Xml_SignatureDescriptionNotCreated); diff --git a/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/SignedXmlDebugLog.cs b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/SignedXmlDebugLog.cs index 299b8804ded9..ae678857a64e 100644 --- a/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/SignedXmlDebugLog.cs +++ b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/SignedXmlDebugLog.cs @@ -698,6 +698,8 @@ internal static void LogSigningReference(SignedXml signedXml, Reference referenc if (VerboseLoggingEnabled) { + HashAlgorithm hashAlgorithm = CryptoHelpers.CreateFromName(reference.DigestMethod); + string hashAlgorithmName = hashAlgorithm == null ? "null" : hashAlgorithm.GetType().Name; string logMessage = string.Format(CultureInfo.InvariantCulture, SR.Log_SigningReference, GetObjectId(reference), @@ -705,7 +707,7 @@ internal static void LogSigningReference(SignedXml signedXml, Reference referenc reference.Id, reference.Type, reference.DigestMethod, - CryptoHelpers.CreateFromName(reference.DigestMethod).GetType().Name); + hashAlgorithmName); WriteLine(signedXml, TraceEventType.Verbose, @@ -831,11 +833,13 @@ internal static void LogVerifyReferenceHash(SignedXml signedXml, if (VerboseLoggingEnabled) { + HashAlgorithm hashAlgorithm = CryptoHelpers.CreateFromName(reference.DigestMethod); + string hashAlgorithmName = hashAlgorithm == null ? "null" : hashAlgorithm.GetType().Name; string logMessage = string.Format(CultureInfo.InvariantCulture, SR.Log_ReferenceHash, GetObjectId(reference), reference.DigestMethod, - CryptoHelpers.CreateFromName(reference.DigestMethod).GetType().Name, + hashAlgorithmName, FormatBytes(actualHash), FormatBytes(expectedHash)); @@ -1043,11 +1047,13 @@ internal static void LogSignedXmlRecursionLimit(SignedXml signedXml, if (InformationLoggingEnabled) { + HashAlgorithm hashAlgorithm = CryptoHelpers.CreateFromName(reference.DigestMethod); + string hashAlgorithmName = hashAlgorithm == null ? "null" : hashAlgorithm.GetType().Name; string logMessage = string.Format(CultureInfo.InvariantCulture, SR.Log_SignedXmlRecursionLimit, GetObjectId(reference), reference.DigestMethod, - CryptoHelpers.CreateFromName(reference.DigestMethod).GetType().Name); + hashAlgorithmName); WriteLine(signedXml, TraceEventType.Information, diff --git a/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/TransformChain.cs b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/TransformChain.cs index 7c2530da778f..3242910a3ef0 100644 --- a/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/TransformChain.cs +++ b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/TransformChain.cs @@ -200,7 +200,7 @@ internal void LoadXml(XmlElement value) { XmlElement transformElement = (XmlElement)transformNodes.Item(i); string algorithm = Utils.GetAttribute(transformElement, "Algorithm", SignedXml.XmlDsigNamespaceUrl); - Transform transform = CryptoHelpers.CreateFromName(algorithm) as Transform; + Transform transform = CryptoHelpers.CreateFromName(algorithm); if (transform == null) throw new CryptographicException(SR.Cryptography_Xml_UnknownTransform); // let the transform read the children of the transformElement for data diff --git a/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/Utils.cs b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/Utils.cs index 0ec93ebdbe98..4f0608c7085f 100644 --- a/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/Utils.cs +++ b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/Utils.cs @@ -81,6 +81,29 @@ internal static bool HasAttribute(XmlElement element, string localName, string n return element.HasAttribute(localName) || element.HasAttribute(localName, namespaceURI); } + internal static bool VerifyAttributes(XmlElement element, string expectedAttrName) + { + return VerifyAttributes(element, expectedAttrName == null ? null : new string[] { expectedAttrName }); + } + + internal static bool VerifyAttributes(XmlElement element, string[] expectedAttrNames) + { + foreach (XmlAttribute attr in element.Attributes) + { + // There are a few Xml Special Attributes that are always allowed on any node. Make sure we allow those here. + bool attrIsAllowed = attr.Name == "xmlns" || attr.Name.StartsWith("xmlns:") || attr.Name == "xml:space" || attr.Name == "xml:lang" || attr.Name == "xml:base"; + int expectedInd = 0; + while (!attrIsAllowed && expectedAttrNames != null && expectedInd < expectedAttrNames.Length) + { + attrIsAllowed = attr.Name == expectedAttrNames[expectedInd]; + expectedInd++; + } + if (!attrIsAllowed) + return false; + } + return true; + } + internal static bool IsNamespaceNode(XmlNode n) { return n.NodeType == XmlNodeType.Attribute && (n.Prefix.Equals("xmlns") || (n.Prefix.Length == 0 && n.LocalName.Equals("xmlns"))); @@ -774,5 +797,8 @@ internal static AsymmetricAlgorithm GetAnyPublicKey(X509Certificate2 certificate { return (AsymmetricAlgorithm)certificate.GetRSAPublicKey(); } + + internal const int MaxTransformsPerReference = 10; + internal const int MaxReferencesPerSignedInfo = 100; } } diff --git a/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/XmlDecryptionTransform.cs b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/XmlDecryptionTransform.cs index 7e6fb6a3f3b1..d721fb6fead1 100644 --- a/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/XmlDecryptionTransform.cs +++ b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/XmlDecryptionTransform.cs @@ -98,14 +98,25 @@ public override void LoadInnerXml(XmlNodeList nodeList) foreach (XmlNode node in nodeList) { XmlElement elem = node as XmlElement; - if (elem != null && elem.LocalName == "Except" && elem.NamespaceURI == XmlDecryptionTransformNamespaceUrl) + if (elem != null) { - // the Uri is required - string uri = Utils.GetAttribute(elem, "URI", XmlDecryptionTransformNamespaceUrl); - if (uri == null || uri.Length == 0 || uri[0] != '#') - throw new CryptographicException(SR.Cryptography_Xml_UriRequired); - string idref = Utils.ExtractIdFromLocalUri(uri); - ExceptUris.Add(idref); + if (elem.LocalName == "Except" && elem.NamespaceURI == XmlDecryptionTransformNamespaceUrl) + { + // the Uri is required + string uri = Utils.GetAttribute(elem, "URI", XmlDecryptionTransformNamespaceUrl); + if (uri == null || uri.Length == 0 || uri[0] != '#') + throw new CryptographicException(SR.Cryptography_Xml_UriRequired); + if (!Utils.VerifyAttributes(elem, "URI")) + { + throw new CryptographicException(SR.Cryptography_Xml_UnknownTransform); + } + string idref = Utils.ExtractIdFromLocalUri(uri); + ExceptUris.Add(idref); + } + else + { + throw new CryptographicException(SR.Cryptography_Xml_UnknownTransform); + } } } } diff --git a/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/XmlDsigC14NTransform.cs b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/XmlDsigC14NTransform.cs index 0a67878804cd..b03d8424f121 100644 --- a/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/XmlDsigC14NTransform.cs +++ b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/XmlDsigC14NTransform.cs @@ -42,7 +42,11 @@ public override Type[] OutputTypes get { return _outputTypes; } } - public override void LoadInnerXml(XmlNodeList nodeList) { } + public override void LoadInnerXml(XmlNodeList nodeList) + { + if (nodeList != null && nodeList.Count > 0) + throw new CryptographicException(SR.Cryptography_Xml_UnknownTransform); + } protected override XmlNodeList GetInnerXml() { diff --git a/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/XmlDsigEnvelopedSignatureTransform.cs b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/XmlDsigEnvelopedSignatureTransform.cs index 15dae41c9ced..d1d98ed33145 100644 --- a/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/XmlDsigEnvelopedSignatureTransform.cs +++ b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/XmlDsigEnvelopedSignatureTransform.cs @@ -52,7 +52,11 @@ public override Type[] OutputTypes } // An enveloped signature has no inner XML elements - public override void LoadInnerXml(XmlNodeList nodeList) { } + public override void LoadInnerXml(XmlNodeList nodeList) + { + if (nodeList != null && nodeList.Count > 0) + throw new CryptographicException(SR.Cryptography_Xml_UnknownTransform); + } // An enveloped signature has no inner XML elements protected override XmlNodeList GetInnerXml() diff --git a/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/XmlDsigExcC14NTransform.cs b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/XmlDsigExcC14NTransform.cs index f861c5ff3190..44373ee12aae 100644 --- a/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/XmlDsigExcC14NTransform.cs +++ b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/XmlDsigExcC14NTransform.cs @@ -58,12 +58,23 @@ public override void LoadInnerXml(XmlNodeList nodeList) foreach (XmlNode n in nodeList) { XmlElement e = n as XmlElement; - if (e != null && e.LocalName.Equals("InclusiveNamespaces") && - e.NamespaceURI.Equals(SignedXml.XmlDsigExcC14NTransformUrl) && - Utils.HasAttribute(e, "PrefixList", SignedXml.XmlDsigNamespaceUrl)) + if (e != null) { - InclusiveNamespacesPrefixList = Utils.GetAttribute(e, "PrefixList", SignedXml.XmlDsigNamespaceUrl); - return; + if (e.LocalName.Equals("InclusiveNamespaces") + && e.NamespaceURI.Equals(SignedXml.XmlDsigExcC14NTransformUrl) && + Utils.HasAttribute(e, "PrefixList", SignedXml.XmlDsigNamespaceUrl)) + { + if (!Utils.VerifyAttributes(e, "PrefixList")) + { + throw new CryptographicException(SR.Cryptography_Xml_UnknownTransform); + } + this.InclusiveNamespacesPrefixList = Utils.GetAttribute(e, "PrefixList", SignedXml.XmlDsigNamespaceUrl); + return; + } + else + { + throw new CryptographicException(SR.Cryptography_Xml_UnknownTransform); + } } } } diff --git a/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/XmlDsigXPathTransform.cs b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/XmlDsigXPathTransform.cs index 07c02d7c68c6..48812b908f33 100644 --- a/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/XmlDsigXPathTransform.cs +++ b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/XmlDsigXPathTransform.cs @@ -50,28 +50,39 @@ public override void LoadInnerXml(XmlNodeList nodeList) string prefix = null; string namespaceURI = null; XmlElement elem = node as XmlElement; - if ((elem != null) && (elem.LocalName == "XPath")) + if (elem != null) { - _xpathexpr = elem.InnerXml.Trim(null); - XmlNodeReader nr = new XmlNodeReader(elem); - XmlNameTable nt = nr.NameTable; - _nsm = new XmlNamespaceManager(nt); - // Look for a namespace in the attributes - foreach (XmlAttribute attrib in elem.Attributes) + if (elem.LocalName == "XPath") { - if (attrib.Prefix == "xmlns") + _xpathexpr = elem.InnerXml.Trim(null); + XmlNodeReader nr = new XmlNodeReader(elem); + XmlNameTable nt = nr.NameTable; + _nsm = new XmlNamespaceManager(nt); + if (!Utils.VerifyAttributes(elem, (string)null)) { - prefix = attrib.LocalName; - namespaceURI = attrib.Value; - if (prefix == null) + throw new CryptographicException(SR.Cryptography_Xml_UnknownTransform); + } + // Look for a namespace in the attributes + foreach (XmlAttribute attrib in elem.Attributes) + { + if (attrib.Prefix == "xmlns") { - prefix = elem.Prefix; - namespaceURI = elem.NamespaceURI; + prefix = attrib.LocalName; + namespaceURI = attrib.Value; + if (prefix == null) + { + prefix = elem.Prefix; + namespaceURI = elem.NamespaceURI; + } + _nsm.AddNamespace(prefix, namespaceURI); } - _nsm.AddNamespace(prefix, namespaceURI); } + break; + } + else + { + throw new CryptographicException(SR.Cryptography_Xml_UnknownTransform); } - break; } } diff --git a/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/XmlLicenseTransform.cs b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/XmlLicenseTransform.cs index bb1f49201b51..0c45f2627b60 100644 --- a/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/XmlLicenseTransform.cs +++ b/src/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/XmlLicenseTransform.cs @@ -132,7 +132,11 @@ public override object GetOutput(Type type) } // License transform has no inner XML elements - public override void LoadInnerXml(XmlNodeList nodeList) { } + public override void LoadInnerXml(XmlNodeList nodeList) + { + if (nodeList != null && nodeList.Count > 0) + throw new CryptographicException(SR.Cryptography_Xml_UnknownTransform); + } public override void LoadInput(object obj) { diff --git a/src/System.Security.Cryptography.Xml/tests/KeyInfo_ArbitraryElements.cs b/src/System.Security.Cryptography.Xml/tests/KeyInfo_ArbitraryElements.cs new file mode 100644 index 000000000000..a05b09eb0e59 --- /dev/null +++ b/src/System.Security.Cryptography.Xml/tests/KeyInfo_ArbitraryElements.cs @@ -0,0 +1,33 @@ +// Licensed to the .NET Foundation under one or more agreements. +// See the LICENSE file in the project root for more information. + +using System.Xml; +using Xunit; + +namespace System.Security.Cryptography.Xml.Tests +{ + public class KeyInfo_ArbitraryElements + { + [Fact] + public static void ExtraData() + { + string arbitraryData = @"lol"; + string xml = $@"XZVZLYkc1BAx+YtaqeYlxanb2cGI=Kx8xs0of766gimu5girTqiTR5xoiWjN4XMx8uzDDhG70bIqpSzlhh6IA3iI54R5mpqCCPWrJJp85ps4jpQk8RGHe4KMejstbY6YXCfs7LtRPzkNzcoZB3vDbr3ijUSrbMk+0wTaZeyeYs8Z6cOicDIVN6bN6yC/Se5fbzTTCSmg={arbitraryData}ww2w+NbXwY/GRBZfFcXqrAM2X+P1NQoU+QEvgLO1izMTB8kvx1i/bodBvHTrKMwAMGEO4kVATA1f1Vf5/lVnbqiCLMJPVRZU6rWKjOGD28T/VRaIGywTV+mC0HvMbe4DlEd3dBwJZLIMUNvOPsj5Ua+l9IS4EoszFNAg6F5Lsyk=AQAB"; + Assert.True(Helpers.VerifyCryptoExceptionOnLoad(xml, false)); + } + + [Fact] + public static void ExtraAttributes() + { + string xml = $@"XZVZLYkc1BAx+YtaqeYlxanb2cGI=Kx8xs0of766gimu5girTqiTR5xoiWjN4XMx8uzDDhG70bIqpSzlhh6IA3iI54R5mpqCCPWrJJp85ps4jpQk8RGHe4KMejstbY6YXCfs7LtRPzkNzcoZB3vDbr3ijUSrbMk+0wTaZeyeYs8Z6cOicDIVN6bN6yC/Se5fbzTTCSmg=ww2w+NbXwY/GRBZfFcXqrAM2X+P1NQoU+QEvgLO1izMTB8kvx1i/bodBvHTrKMwAMGEO4kVATA1f1Vf5/lVnbqiCLMJPVRZU6rWKjOGD28T/VRaIGywTV+mC0HvMbe4DlEd3dBwJZLIMUNvOPsj5Ua+l9IS4EoszFNAg6F5Lsyk=AQAB"; + Assert.False(Helpers.VerifyCryptoExceptionOnLoad(xml, true)); + } + + [Fact] + public static void KeyValue_ExtraAttributes() + { + string xml = $@"XZVZLYkc1BAx+YtaqeYlxanb2cGI=Kx8xs0of766gimu5girTqiTR5xoiWjN4XMx8uzDDhG70bIqpSzlhh6IA3iI54R5mpqCCPWrJJp85ps4jpQk8RGHe4KMejstbY6YXCfs7LtRPzkNzcoZB3vDbr3ijUSrbMk+0wTaZeyeYs8Z6cOicDIVN6bN6yC/Se5fbzTTCSmg=ww2w+NbXwY/GRBZfFcXqrAM2X+P1NQoU+QEvgLO1izMTB8kvx1i/bodBvHTrKMwAMGEO4kVATA1f1Vf5/lVnbqiCLMJPVRZU6rWKjOGD28T/VRaIGywTV+mC0HvMbe4DlEd3dBwJZLIMUNvOPsj5Ua+l9IS4EoszFNAg6F5Lsyk=AQAB"; + Assert.False(Helpers.VerifyCryptoExceptionOnLoad(xml, true)); + } + } +} diff --git a/src/System.Security.Cryptography.Xml/tests/Reference_ArbitraryElements.cs b/src/System.Security.Cryptography.Xml/tests/Reference_ArbitraryElements.cs new file mode 100644 index 000000000000..8a1f86daef8c --- /dev/null +++ b/src/System.Security.Cryptography.Xml/tests/Reference_ArbitraryElements.cs @@ -0,0 +1,156 @@ +// Licensed to the .NET Foundation under one or more agreements. +// See the LICENSE file in the project root for more information. + +using System.Xml; +using Xunit; + +namespace System.Security.Cryptography.Xml.Tests +{ + public class Reference_ArbitraryElements + { + [Fact] + public static void ExtraData() + { + string arbitraryData = @"lol"; + string xml = $@"X{arbitraryData}ZVZLYkc1BAx+YtaqeYlxanb2cGI=Kx8xs0of766gimu5girTqiTR5xoiWjN4XMx8uzDDhG70bIqpSzlhh6IA3iI54R5mpqCCPWrJJp85ps4jpQk8RGHe4KMejstbY6YXCfs7LtRPzkNzcoZB3vDbr3ijUSrbMk+0wTaZeyeYs8Z6cOicDIVN6bN6yC/Se5fbzTTCSmg=ww2w+NbXwY/GRBZfFcXqrAM2X+P1NQoU+QEvgLO1izMTB8kvx1i/bodBvHTrKMwAMGEO4kVATA1f1Vf5/lVnbqiCLMJPVRZU6rWKjOGD28T/VRaIGywTV+mC0HvMbe4DlEd3dBwJZLIMUNvOPsj5Ua+l9IS4EoszFNAg6F5Lsyk=AQAB"; + Assert.False(Helpers.VerifyCryptoExceptionOnLoad(xml, true)); + } + + [Fact] + public static void OutOfOrder() + { + string xml = $@"XZVZLYkc1BAx+YtaqeYlxanb2cGI=Kx8xs0of766gimu5girTqiTR5xoiWjN4XMx8uzDDhG70bIqpSzlhh6IA3iI54R5mpqCCPWrJJp85ps4jpQk8RGHe4KMejstbY6YXCfs7LtRPzkNzcoZB3vDbr3ijUSrbMk+0wTaZeyeYs8Z6cOicDIVN6bN6yC/Se5fbzTTCSmg=ww2w+NbXwY/GRBZfFcXqrAM2X+P1NQoU+QEvgLO1izMTB8kvx1i/bodBvHTrKMwAMGEO4kVATA1f1Vf5/lVnbqiCLMJPVRZU6rWKjOGD28T/VRaIGywTV+mC0HvMbe4DlEd3dBwJZLIMUNvOPsj5Ua+l9IS4EoszFNAg6F5Lsyk=AQAB"; + Assert.False(Helpers.VerifyCryptoExceptionOnLoad(xml, false)); + } + + [Fact] + public static void DuplicateTransforms() + { + string arbitraryData = @"lol"; + string xml = $@"X{arbitraryData}ZVZLYkc1BAx+YtaqeYlxanb2cGI=Kx8xs0of766gimu5girTqiTR5xoiWjN4XMx8uzDDhG70bIqpSzlhh6IA3iI54R5mpqCCPWrJJp85ps4jpQk8RGHe4KMejstbY6YXCfs7LtRPzkNzcoZB3vDbr3ijUSrbMk+0wTaZeyeYs8Z6cOicDIVN6bN6yC/Se5fbzTTCSmg=ww2w+NbXwY/GRBZfFcXqrAM2X+P1NQoU+QEvgLO1izMTB8kvx1i/bodBvHTrKMwAMGEO4kVATA1f1Vf5/lVnbqiCLMJPVRZU6rWKjOGD28T/VRaIGywTV+mC0HvMbe4DlEd3dBwJZLIMUNvOPsj5Ua+l9IS4EoszFNAg6F5Lsyk=AQAB"; + Assert.False(Helpers.VerifyCryptoExceptionOnLoad(xml, true)); + } + + [Fact] + public static void Transforms_ExtraData() + { + string arbitraryData = @"lol"; + string xml = $@"X{arbitraryData}ZVZLYkc1BAx+YtaqeYlxanb2cGI=Kx8xs0of766gimu5girTqiTR5xoiWjN4XMx8uzDDhG70bIqpSzlhh6IA3iI54R5mpqCCPWrJJp85ps4jpQk8RGHe4KMejstbY6YXCfs7LtRPzkNzcoZB3vDbr3ijUSrbMk+0wTaZeyeYs8Z6cOicDIVN6bN6yC/Se5fbzTTCSmg=ww2w+NbXwY/GRBZfFcXqrAM2X+P1NQoU+QEvgLO1izMTB8kvx1i/bodBvHTrKMwAMGEO4kVATA1f1Vf5/lVnbqiCLMJPVRZU6rWKjOGD28T/VRaIGywTV+mC0HvMbe4DlEd3dBwJZLIMUNvOPsj5Ua+l9IS4EoszFNAg6F5Lsyk=AQAB"; + Assert.False(Helpers.VerifyCryptoExceptionOnLoad(xml, true)); + } + + [Fact] + public static void Transforms_ExtraData_CData_Text() + { + string arbitraryData = @"text"; + + string xml = $@" +X{arbitraryData}ZVZLYkc1BAx+YtaqeYlxanb2cGI=Kx8xs0of766gimu5girTqiTR5xoiWjN4XMx8uzDDhG70bIqpSzlhh6IA3iI54R5mpqCCPWrJJp85ps4jpQk8RGHe4KMejstbY6YXCfs7LtRPzkNzcoZB3vDbr3ijUSrbMk+0wTaZeyeYs8Z6cOicDIVN6bN6yC/Se5fbzTTCSmg=ww2w+NbXwY/GRBZfFcXqrAM2X+P1NQoU+QEvgLO1izMTB8kvx1i/bodBvHTrKMwAMGEO4kVATA1f1Vf5/lVnbqiCLMJPVRZU6rWKjOGD28T/VRaIGywTV+mC0HvMbe4DlEd3dBwJZLIMUNvOPsj5Ua+l9IS4EoszFNAg6F5Lsyk=AQAB"; + + Assert.False(Helpers.VerifyCryptoExceptionOnLoad(xml, false)); + } + + [Fact] + public static void Transforms_ExtraData_XmlNotation() + { + string xml = $@" +XZVZLYkc1BAx+YtaqeYlxanb2cGI=Kx8xs0of766gimu5girTqiTR5xoiWjN4XMx8uzDDhG70bIqpSzlhh6IA3iI54R5mpqCCPWrJJp85ps4jpQk8RGHe4KMejstbY6YXCfs7LtRPzkNzcoZB3vDbr3ijUSrbMk+0wTaZeyeYs8Z6cOicDIVN6bN6yC/Se5fbzTTCSmg=ww2w+NbXwY/GRBZfFcXqrAM2X+P1NQoU+QEvgLO1izMTB8kvx1i/bodBvHTrKMwAMGEO4kVATA1f1Vf5/lVnbqiCLMJPVRZU6rWKjOGD28T/VRaIGywTV+mC0HvMbe4DlEd3dBwJZLIMUNvOPsj5Ua+l9IS4EoszFNAg6F5Lsyk=AQAB"; + + Assert.False(Helpers.VerifyCryptoExceptionOnLoad(xml, true)); + } + + [Fact] + public static void Transforms_ExtraData_XmlProcessingInstruction() + { + string xml = $@" +XZVZLYkc1BAx+YtaqeYlxanb2cGI=Kx8xs0of766gimu5girTqiTR5xoiWjN4XMx8uzDDhG70bIqpSzlhh6IA3iI54R5mpqCCPWrJJp85ps4jpQk8RGHe4KMejstbY6YXCfs7LtRPzkNzcoZB3vDbr3ijUSrbMk+0wTaZeyeYs8Z6cOicDIVN6bN6yC/Se5fbzTTCSmg=ww2w+NbXwY/GRBZfFcXqrAM2X+P1NQoU+QEvgLO1izMTB8kvx1i/bodBvHTrKMwAMGEO4kVATA1f1Vf5/lVnbqiCLMJPVRZU6rWKjOGD28T/VRaIGywTV+mC0HvMbe4DlEd3dBwJZLIMUNvOPsj5Ua+l9IS4EoszFNAg6F5Lsyk=AQAB"; + + Assert.False(Helpers.VerifyCryptoExceptionOnLoad(xml, false)); + } + + [Fact] + public static void Transforms_ExtraAttributes() + { + string xml = $@"XZVZLYkc1BAx+YtaqeYlxanb2cGI=Kx8xs0of766gimu5girTqiTR5xoiWjN4XMx8uzDDhG70bIqpSzlhh6IA3iI54R5mpqCCPWrJJp85ps4jpQk8RGHe4KMejstbY6YXCfs7LtRPzkNzcoZB3vDbr3ijUSrbMk+0wTaZeyeYs8Z6cOicDIVN6bN6yC/Se5fbzTTCSmg=ww2w+NbXwY/GRBZfFcXqrAM2X+P1NQoU+QEvgLO1izMTB8kvx1i/bodBvHTrKMwAMGEO4kVATA1f1Vf5/lVnbqiCLMJPVRZU6rWKjOGD28T/VRaIGywTV+mC0HvMbe4DlEd3dBwJZLIMUNvOPsj5Ua+l9IS4EoszFNAg6F5Lsyk=AQAB"; + Assert.False(Helpers.VerifyCryptoExceptionOnLoad(xml, true)); + } + + [Fact] + public static void DuplicateDigestMethod() + { + string arbitraryData = @"lol"; + + string xml = $@"X{arbitraryData}{arbitraryData}ZVZLYkc1BAx+YtaqeYlxanb2cGI=Kx8xs0of766gimu5girTqiTR5xoiWjN4XMx8uzDDhG70bIqpSzlhh6IA3iI54R5mpqCCPWrJJp85ps4jpQk8RGHe4KMejstbY6YXCfs7LtRPzkNzcoZB3vDbr3ijUSrbMk+0wTaZeyeYs8Z6cOicDIVN6bN6yC/Se5fbzTTCSmg=ww2w+NbXwY/GRBZfFcXqrAM2X+P1NQoU+QEvgLO1izMTB8kvx1i/bodBvHTrKMwAMGEO4kVATA1f1Vf5/lVnbqiCLMJPVRZU6rWKjOGD28T/VRaIGywTV+mC0HvMbe4DlEd3dBwJZLIMUNvOPsj5Ua+l9IS4EoszFNAg6F5Lsyk=AQAB"; + Assert.False(Helpers.VerifyCryptoExceptionOnLoad(xml, true)); + } + + [Fact] + public static void DuplicateDigestValue() + { + string arbitraryData = @"lol"; + string xml = $@"X{arbitraryData}ZVZLYkc1BAx+YtaqeYlxanb2cGI={arbitraryData}Kx8xs0of766gimu5girTqiTR5xoiWjN4XMx8uzDDhG70bIqpSzlhh6IA3iI54R5mpqCCPWrJJp85ps4jpQk8RGHe4KMejstbY6YXCfs7LtRPzkNzcoZB3vDbr3ijUSrbMk+0wTaZeyeYs8Z6cOicDIVN6bN6yC/Se5fbzTTCSmg=ww2w+NbXwY/GRBZfFcXqrAM2X+P1NQoU+QEvgLO1izMTB8kvx1i/bodBvHTrKMwAMGEO4kVATA1f1Vf5/lVnbqiCLMJPVRZU6rWKjOGD28T/VRaIGywTV+mC0HvMbe4DlEd3dBwJZLIMUNvOPsj5Ua+l9IS4EoszFNAg6F5Lsyk=AQAB"; + Assert.False(Helpers.VerifyCryptoExceptionOnLoad(xml, true)); + } + + [Fact] + public static void ExtraAttributes() + { + foreach (string includeID in new string[] { "", $@" Id=""""" }) + foreach (string includeURI in new string[] { "", $@" URI=""""" }) + foreach (string includeType in new string[] { "", $@" Type=""""" }) + foreach (string includeExtra in new string[] { "", $@" extraattr=""cat""" }) + { + string xml = $@"XZVZLYkc1BAx+YtaqeYlxanb2cGI=Kx8xs0of766gimu5girTqiTR5xoiWjN4XMx8uzDDhG70bIqpSzlhh6IA3iI54R5mpqCCPWrJJp85ps4jpQk8RGHe4KMejstbY6YXCfs7LtRPzkNzcoZB3vDbr3ijUSrbMk+0wTaZeyeYs8Z6cOicDIVN6bN6yC/Se5fbzTTCSmg=ww2w+NbXwY/GRBZfFcXqrAM2X+P1NQoU+QEvgLO1izMTB8kvx1i/bodBvHTrKMwAMGEO4kVATA1f1Vf5/lVnbqiCLMJPVRZU6rWKjOGD28T/VRaIGywTV+mC0HvMbe4DlEd3dBwJZLIMUNvOPsj5Ua+l9IS4EoszFNAg6F5Lsyk=AQAB"; + Assert.Equal((includeExtra == "" && includeID == "" && includeURI != "" && includeType == ""), Helpers.VerifyCryptoExceptionOnLoad(xml, includeExtra != "")); + } + } + + [Fact] + public static void DuplicateLegalAttributes() + { + foreach (string includeID in new string[] { "", $@" Id=""""", $@" Id="""" Id=""""" }) + foreach (string includeURI in new string[] { "", $@" URI=""""", $@" URI="""" URI=""""" }) + foreach (string includeType in new string[] { "", $@" Type=""""", $@" Type="""" Type=""""" }) + { + string xml = $@"XZVZLYkc1BAx+YtaqeYlxanb2cGI=Kx8xs0of766gimu5girTqiTR5xoiWjN4XMx8uzDDhG70bIqpSzlhh6IA3iI54R5mpqCCPWrJJp85ps4jpQk8RGHe4KMejstbY6YXCfs7LtRPzkNzcoZB3vDbr3ijUSrbMk+0wTaZeyeYs8Z6cOicDIVN6bN6yC/Se5fbzTTCSmg=ww2w+NbXwY/GRBZfFcXqrAM2X+P1NQoU+QEvgLO1izMTB8kvx1i/bodBvHTrKMwAMGEO4kVATA1f1Vf5/lVnbqiCLMJPVRZU6rWKjOGD28T/VRaIGywTV+mC0HvMbe4DlEd3dBwJZLIMUNvOPsj5Ua+l9IS4EoszFNAg6F5Lsyk=AQAB"; + bool throwsXmlException = includeID.LastIndexOf("I") != includeID.IndexOf("I") || includeURI.LastIndexOf("U") != includeURI.IndexOf("U") || includeType.LastIndexOf("T") != includeType.IndexOf("T"); + if (throwsXmlException) + Assert.Throws(() => Helpers.VerifyCryptoExceptionOnLoad(xml, false)); + else + Assert.Equal(includeID == "" && includeURI != "" && includeType == "", Helpers.VerifyCryptoExceptionOnLoad(xml, false)); + } + } + + [Fact] + public static void MissingAttribute_Transform() + { + string arbitraryData = @"lol"; + string xml = $@"XZVZLYkc1BAx+YtaqeYlxanb2cGI={arbitraryData}Kx8xs0of766gimu5girTqiTR5xoiWjN4XMx8uzDDhG70bIqpSzlhh6IA3iI54R5mpqCCPWrJJp85ps4jpQk8RGHe4KMejstbY6YXCfs7LtRPzkNzcoZB3vDbr3ijUSrbMk+0wTaZeyeYs8Z6cOicDIVN6bN6yC/Se5fbzTTCSmg=ww2w+NbXwY/GRBZfFcXqrAM2X+P1NQoU+QEvgLO1izMTB8kvx1i/bodBvHTrKMwAMGEO4kVATA1f1Vf5/lVnbqiCLMJPVRZU6rWKjOGD28T/VRaIGywTV+mC0HvMbe4DlEd3dBwJZLIMUNvOPsj5Ua+l9IS4EoszFNAg6F5Lsyk=AQAB"; + Helpers.VerifyCryptoExceptionOnLoad(xml, true); + } + + [Fact] + public static void ExtraAttribute_Transform() + { + string arbitraryData = @"lol"; + string xml = $@"XZVZLYkc1BAx+YtaqeYlxanb2cGI={arbitraryData}Kx8xs0of766gimu5girTqiTR5xoiWjN4XMx8uzDDhG70bIqpSzlhh6IA3iI54R5mpqCCPWrJJp85ps4jpQk8RGHe4KMejstbY6YXCfs7LtRPzkNzcoZB3vDbr3ijUSrbMk+0wTaZeyeYs8Z6cOicDIVN6bN6yC/Se5fbzTTCSmg=ww2w+NbXwY/GRBZfFcXqrAM2X+P1NQoU+QEvgLO1izMTB8kvx1i/bodBvHTrKMwAMGEO4kVATA1f1Vf5/lVnbqiCLMJPVRZU6rWKjOGD28T/VRaIGywTV+mC0HvMbe4DlEd3dBwJZLIMUNvOPsj5Ua+l9IS4EoszFNAg6F5Lsyk=AQAB"; + Helpers.VerifyCryptoExceptionOnLoad(xml, true); + } + + [Fact] + public static void MissingAttribute_DigestMethod() + { + string arbitraryData = @"lol"; + string xml = $@"XZVZLYkc1BAx+YtaqeYlxanb2cGI={arbitraryData}Kx8xs0of766gimu5girTqiTR5xoiWjN4XMx8uzDDhG70bIqpSzlhh6IA3iI54R5mpqCCPWrJJp85ps4jpQk8RGHe4KMejstbY6YXCfs7LtRPzkNzcoZB3vDbr3ijUSrbMk+0wTaZeyeYs8Z6cOicDIVN6bN6yC/Se5fbzTTCSmg=ww2w+NbXwY/GRBZfFcXqrAM2X+P1NQoU+QEvgLO1izMTB8kvx1i/bodBvHTrKMwAMGEO4kVATA1f1Vf5/lVnbqiCLMJPVRZU6rWKjOGD28T/VRaIGywTV+mC0HvMbe4DlEd3dBwJZLIMUNvOPsj5Ua+l9IS4EoszFNAg6F5Lsyk=AQAB"; + Helpers.VerifyCryptoExceptionOnLoad(xml, true); + } + + [Fact] + public static void ExtraAttribute_DigestMethod() + { + string arbitraryData = @"lol"; + string xml = $@"XZVZLYkc1BAx+YtaqeYlxanb2cGI={arbitraryData}Kx8xs0of766gimu5girTqiTR5xoiWjN4XMx8uzDDhG70bIqpSzlhh6IA3iI54R5mpqCCPWrJJp85ps4jpQk8RGHe4KMejstbY6YXCfs7LtRPzkNzcoZB3vDbr3ijUSrbMk+0wTaZeyeYs8Z6cOicDIVN6bN6yC/Se5fbzTTCSmg=ww2w+NbXwY/GRBZfFcXqrAM2X+P1NQoU+QEvgLO1izMTB8kvx1i/bodBvHTrKMwAMGEO4kVATA1f1Vf5/lVnbqiCLMJPVRZU6rWKjOGD28T/VRaIGywTV+mC0HvMbe4DlEd3dBwJZLIMUNvOPsj5Ua+l9IS4EoszFNAg6F5Lsyk=AQAB"; + Helpers.VerifyCryptoExceptionOnLoad(xml, true); + } + } +} diff --git a/src/System.Security.Cryptography.Xml/tests/Signature_ArbitraryElements.cs b/src/System.Security.Cryptography.Xml/tests/Signature_ArbitraryElements.cs new file mode 100644 index 000000000000..e45ef911d625 --- /dev/null +++ b/src/System.Security.Cryptography.Xml/tests/Signature_ArbitraryElements.cs @@ -0,0 +1,153 @@ +// Licensed to the .NET Foundation under one or more agreements. +// See the LICENSE file in the project root for more information. + +using System.Xml; +using Xunit; + +namespace System.Security.Cryptography.Xml.Tests +{ + public class Signature_ArbitraryElements + { + [Fact] + public static void CorrectAttributes() + { + string xml = $@"XZVZLYkc1BAx+YtaqeYlxanb2cGI=Kx8xs0of766gimu5girTqiTR5xoiWjN4XMx8uzDDhG70bIqpSzlhh6IA3iI54R5mpqCCPWrJJp85ps4jpQk8RGHe4KMejstbY6YXCfs7LtRPzkNzcoZB3vDbr3ijUSrbMk+0wTaZeyeYs8Z6cOicDIVN6bN6yC/Se5fbzTTCSmg=ww2w+NbXwY/GRBZfFcXqrAM2X+P1NQoU+QEvgLO1izMTB8kvx1i/bodBvHTrKMwAMGEO4kVATA1f1Vf5/lVnbqiCLMJPVRZU6rWKjOGD28T/VRaIGywTV+mC0HvMbe4DlEd3dBwJZLIMUNvOPsj5Ua+l9IS4EoszFNAg6F5Lsyk=AQAB"; + Assert.False(Helpers.VerifyCryptoExceptionOnLoad(xml, false)); + } + + [Fact] + public static void DoubleSameAttribute_ID() + { + string xml = $@"XZVZLYkc1BAx+YtaqeYlxanb2cGI=Kx8xs0of766gimu5girTqiTR5xoiWjN4XMx8uzDDhG70bIqpSzlhh6IA3iI54R5mpqCCPWrJJp85ps4jpQk8RGHe4KMejstbY6YXCfs7LtRPzkNzcoZB3vDbr3ijUSrbMk+0wTaZeyeYs8Z6cOicDIVN6bN6yC/Se5fbzTTCSmg=ww2w+NbXwY/GRBZfFcXqrAM2X+P1NQoU+QEvgLO1izMTB8kvx1i/bodBvHTrKMwAMGEO4kVATA1f1Vf5/lVnbqiCLMJPVRZU6rWKjOGD28T/VRaIGywTV+mC0HvMbe4DlEd3dBwJZLIMUNvOPsj5Ua+l9IS4EoszFNAg6F5Lsyk=AQAB"; + Assert.Throws(() => Helpers.VerifyCryptoExceptionOnLoad(xml, true)); + } + + [Fact] + public static void DifferentSignatureXMLNS() + { + string xml = $@"XZVZLYkc1BAx+YtaqeYlxanb2cGI=Kx8xs0of766gimu5girTqiTR5xoiWjN4XMx8uzDDhG70bIqpSzlhh6IA3iI54R5mpqCCPWrJJp85ps4jpQk8RGHe4KMejstbY6YXCfs7LtRPzkNzcoZB3vDbr3ijUSrbMk+0wTaZeyeYs8Z6cOicDIVN6bN6yC/Se5fbzTTCSmg=ww2w+NbXwY/GRBZfFcXqrAM2X+P1NQoU+QEvgLO1izMTB8kvx1i/bodBvHTrKMwAMGEO4kVATA1f1Vf5/lVnbqiCLMJPVRZU6rWKjOGD28T/VRaIGywTV+mC0HvMbe4DlEd3dBwJZLIMUNvOPsj5Ua+l9IS4EoszFNAg6F5Lsyk=AQAB"; + Assert.False(Helpers.VerifyCryptoExceptionOnLoad(xml, true)); + } + + [Fact] + public static void ExtraAttributes() + { + string xml = $@"XZVZLYkc1BAx+YtaqeYlxanb2cGI=Kx8xs0of766gimu5girTqiTR5xoiWjN4XMx8uzDDhG70bIqpSzlhh6IA3iI54R5mpqCCPWrJJp85ps4jpQk8RGHe4KMejstbY6YXCfs7LtRPzkNzcoZB3vDbr3ijUSrbMk+0wTaZeyeYs8Z6cOicDIVN6bN6yC/Se5fbzTTCSmg=ww2w+NbXwY/GRBZfFcXqrAM2X+P1NQoU+QEvgLO1izMTB8kvx1i/bodBvHTrKMwAMGEO4kVATA1f1Vf5/lVnbqiCLMJPVRZU6rWKjOGD28T/VRaIGywTV+mC0HvMbe4DlEd3dBwJZLIMUNvOPsj5Ua+l9IS4EoszFNAg6F5Lsyk=AQAB"; + Assert.False(Helpers.VerifyCryptoExceptionOnLoad(xml, true)); + } + + [Fact] + public static void ExtraAttributes_WeirdXMLNS() + { + string xml = $@"XZVZLYkc1BAx+YtaqeYlxanb2cGI=Kx8xs0of766gimu5girTqiTR5xoiWjN4XMx8uzDDhG70bIqpSzlhh6IA3iI54R5mpqCCPWrJJp85ps4jpQk8RGHe4KMejstbY6YXCfs7LtRPzkNzcoZB3vDbr3ijUSrbMk+0wTaZeyeYs8Z6cOicDIVN6bN6yC/Se5fbzTTCSmg=ww2w+NbXwY/GRBZfFcXqrAM2X+P1NQoU+QEvgLO1izMTB8kvx1i/bodBvHTrKMwAMGEO4kVATA1f1Vf5/lVnbqiCLMJPVRZU6rWKjOGD28T/VRaIGywTV+mC0HvMbe4DlEd3dBwJZLIMUNvOPsj5Ua+l9IS4EoszFNAg6F5Lsyk=AQAB"; + Assert.True(Helpers.VerifyCryptoExceptionOnLoad(xml, false)); + } + + [Fact] + public static void ExtraAttributes_Preserve() + { + string xml = $@" +XZVZLYkc1BAx+YtaqeYlxanb2cGI=Kx8xs0of766gimu5girTqiTR5xoiWjN4XMx8uzDDhG70bIqpSzlhh6IA3iI54R5mpqCCPWrJJp85ps4jpQk8RGHe4KMejstbY6YXCfs7LtRPzkNzcoZB3vDbr3ijUSrbMk+0wTaZeyeYs8Z6cOicDIVN6bN6yC/Se5fbzTTCSmg=ww2w+NbXwY/GRBZfFcXqrAM2X+P1NQoU+QEvgLO1izMTB8kvx1i/bodBvHTrKMwAMGEO4kVATA1f1Vf5/lVnbqiCLMJPVRZU6rWKjOGD28T/VRaIGywTV+mC0HvMbe4DlEd3dBwJZLIMUNvOPsj5Ua+l9IS4EoszFNAg6F5Lsyk=AQAB"; + + Assert.True(Helpers.VerifyCryptoExceptionOnLoad(xml, false)); + } + + [Fact] + public static void ExtraAttributes_Preserve_PlusExtraData() + { + string xml = $@" +X i ss u eZVZLYkc1BAx+YtaqeYlxanb2cGI=Kx8xs0of766gimu5girTqiTR5xoiWjN4XMx8uzDDhG70bIqpSzlhh6IA3iI54R5mpqCCPWrJJp85ps4jpQk8RGHe4KMejstbY6YXCfs7LtRPzkNzcoZB3vDbr3ijUSrbMk+0wTaZeyeYs8Z6cOicDIVN6bN6yC/Se5fbzTTCSmg=ww2w+NbXwY/GRBZfFcXqrAM2X+P1NQoU+QEvgLO1izMTB8kvx1i/bodBvHTrKMwAMGEO4kVATA1f1Vf5/lVnbqiCLMJPVRZU6rWKjOGD28T/VRaIGywTV+mC0HvMbe4DlEd3dBwJZLIMUNvOPsj5Ua+l9IS4EoszFNAg6F5Lsyk=AQAB"; + + Assert.False(Helpers.VerifyCryptoExceptionOnLoad(xml, true)); + } + + [Fact] + public static void ExtraAttributes_Lang() + { + string xml = $@" + XZVZLYkc1BAx+YtaqeYlxanb2cGI=Kx8xs0of766gimu5girTqiTR5xoiWjN4XMx8uzDDhG70bIqpSzlhh6IA3iI54R5mpqCCPWrJJp85ps4jpQk8RGHe4KMejstbY6YXCfs7LtRPzkNzcoZB3vDbr3ijUSrbMk+0wTaZeyeYs8Z6cOicDIVN6bN6yC/Se5fbzTTCSmg=ww2w+NbXwY/GRBZfFcXqrAM2X+P1NQoU+QEvgLO1izMTB8kvx1i/bodBvHTrKMwAMGEO4kVATA1f1Vf5/lVnbqiCLMJPVRZU6rWKjOGD28T/VRaIGywTV+mC0HvMbe4DlEd3dBwJZLIMUNvOPsj5Ua+l9IS4EoszFNAg6F5Lsyk=AQAB"; + + Assert.True(Helpers.VerifyCryptoExceptionOnLoad(xml, false)); + } + + [Fact] + public static void ExtraAttributes_Base() + { + string xml = $@" + XZVZLYkc1BAx+YtaqeYlxanb2cGI=Kx8xs0of766gimu5girTqiTR5xoiWjN4XMx8uzDDhG70bIqpSzlhh6IA3iI54R5mpqCCPWrJJp85ps4jpQk8RGHe4KMejstbY6YXCfs7LtRPzkNzcoZB3vDbr3ijUSrbMk+0wTaZeyeYs8Z6cOicDIVN6bN6yC/Se5fbzTTCSmg=ww2w+NbXwY/GRBZfFcXqrAM2X+P1NQoU+QEvgLO1izMTB8kvx1i/bodBvHTrKMwAMGEO4kVATA1f1Vf5/lVnbqiCLMJPVRZU6rWKjOGD28T/VRaIGywTV+mC0HvMbe4DlEd3dBwJZLIMUNvOPsj5Ua+l9IS4EoszFNAg6F5Lsyk=AQAB"; + + Assert.True(Helpers.VerifyCryptoExceptionOnLoad(xml, false)); + } + + [Fact] + public static void ExtraAttributes_DigestValueWhenMissingDigestValue() + { + string xml = $@"XKx8xs0of766gimu5girTqiTR5xoiWjN4XMx8uzDDhG70bIqpSzlhh6IA3iI54R5mpqCCPWrJJp85ps4jpQk8RGHe4KMejstbY6YXCfs7LtRPzkNzcoZB3vDbr3ijUSrbMk+0wTaZeyeYs8Z6cOicDIVN6bN6yC/Se5fbzTTCSmg=ww2w+NbXwY/GRBZfFcXqrAM2X+P1NQoU+QEvgLO1izMTB8kvx1i/bodBvHTrKMwAMGEO4kVATA1f1Vf5/lVnbqiCLMJPVRZU6rWKjOGD28T/VRaIGywTV+mC0HvMbe4DlEd3dBwJZLIMUNvOPsj5Ua+l9IS4EoszFNAg6F5Lsyk=AQAB"; + Assert.False(Helpers.VerifyCryptoExceptionOnLoad(xml, true)); + } + + [Fact] + public static void ExtraAttributes_ExtraFirst() + { + string xml = $@"XZVZLYkc1BAx+YtaqeYlxanb2cGI=Kx8xs0of766gimu5girTqiTR5xoiWjN4XMx8uzDDhG70bIqpSzlhh6IA3iI54R5mpqCCPWrJJp85ps4jpQk8RGHe4KMejstbY6YXCfs7LtRPzkNzcoZB3vDbr3ijUSrbMk+0wTaZeyeYs8Z6cOicDIVN6bN6yC/Se5fbzTTCSmg=ww2w+NbXwY/GRBZfFcXqrAM2X+P1NQoU+QEvgLO1izMTB8kvx1i/bodBvHTrKMwAMGEO4kVATA1f1Vf5/lVnbqiCLMJPVRZU6rWKjOGD28T/VRaIGywTV+mC0HvMbe4DlEd3dBwJZLIMUNvOPsj5Ua+l9IS4EoszFNAg6F5Lsyk=AQAB"; + Assert.False(Helpers.VerifyCryptoExceptionOnLoad(xml, true)); + } + + [Fact] + public static void ExtraAttributes_SignatureValue() + { + string xml = $@"XZVZLYkc1BAx+YtaqeYlxanb2cGI=Kx8xs0of766gimu5girTqiTR5xoiWjN4XMx8uzDDhG70bIqpSzlhh6IA3iI54R5mpqCCPWrJJp85ps4jpQk8RGHe4KMejstbY6YXCfs7LtRPzkNzcoZB3vDbr3ijUSrbMk+0wTaZeyeYs8Z6cOicDIVN6bN6yC/Se5fbzTTCSmg=ww2w+NbXwY/GRBZfFcXqrAM2X+P1NQoU+QEvgLO1izMTB8kvx1i/bodBvHTrKMwAMGEO4kVATA1f1Vf5/lVnbqiCLMJPVRZU6rWKjOGD28T/VRaIGywTV+mC0HvMbe4DlEd3dBwJZLIMUNvOPsj5Ua+l9IS4EoszFNAg6F5Lsyk=AQAB"; + Assert.False(Helpers.VerifyCryptoExceptionOnLoad(xml, true)); + } + + [Theory] + [InlineData(@"lol", false, true)] // Element + [InlineData(@"", true, false)] //CData_CDataSection + [InlineData(@"", true, false)] //CData_Comment + [InlineData(@" ", true, false)] //CData_Whitespace + [InlineData(@"this", true, false)] //CData_Text + [InlineData(@"&", true, false)] //EntityReference + [InlineData(@"", true, false)] //EntityReference + [InlineData(@"", true, false)] //EntityReference + + public static void ExtraData(string arbitraryData, bool checkSignatureSucceeds, bool loadThrows) + { + string xml = $@" + X{arbitraryData}ZVZLYkc1BAx+YtaqeYlxanb2cGI=Kx8xs0of766gimu5girTqiTR5xoiWjN4XMx8uzDDhG70bIqpSzlhh6IA3iI54R5mpqCCPWrJJp85ps4jpQk8RGHe4KMejstbY6YXCfs7LtRPzkNzcoZB3vDbr3ijUSrbMk+0wTaZeyeYs8Z6cOicDIVN6bN6yC/Se5fbzTTCSmg=ww2w+NbXwY/GRBZfFcXqrAM2X+P1NQoU+QEvgLO1izMTB8kvx1i/bodBvHTrKMwAMGEO4kVATA1f1Vf5/lVnbqiCLMJPVRZU6rWKjOGD28T/VRaIGywTV+mC0HvMbe4DlEd3dBwJZLIMUNvOPsj5Ua+l9IS4EoszFNAg6F5Lsyk=AQAB"; + + Assert.Equal(checkSignatureSucceeds, Helpers.VerifyCryptoExceptionOnLoad(xml, loadThrows)); + } + + [Fact] + public static void OutOfOrder() + { + string xml = $@"XKx8xs0of766gimu5girTqiTR5xoiWjN4XMx8uzDDhG70bIqpSzlhh6IA3iI54R5mpqCCPWrJJp85ps4jpQk8RGHe4KMejstbY6YXCfs7LtRPzkNzcoZB3vDbr3ijUSrbMk+0wTaZeyeYs8Z6cOicDIVN6bN6yC/Se5fbzTTCSmg=ZVZLYkc1BAx+YtaqeYlxanb2cGI=ww2w+NbXwY/GRBZfFcXqrAM2X+P1NQoU+QEvgLO1izMTB8kvx1i/bodBvHTrKMwAMGEO4kVATA1f1Vf5/lVnbqiCLMJPVRZU6rWKjOGD28T/VRaIGywTV+mC0HvMbe4DlEd3dBwJZLIMUNvOPsj5Ua+l9IS4EoszFNAg6F5Lsyk=AQAB"; + Assert.True(Helpers.VerifyCryptoExceptionOnLoad(xml, false)); + } + + [Fact] + public static void DuplicateSignedInfo() + { + string arbitraryData = @"lol"; + + string xml = $@"XZVZLYkc1BAx+YtaqeYlxanb2cGI={arbitraryData}Kx8xs0of766gimu5girTqiTR5xoiWjN4XMx8uzDDhG70bIqpSzlhh6IA3iI54R5mpqCCPWrJJp85ps4jpQk8RGHe4KMejstbY6YXCfs7LtRPzkNzcoZB3vDbr3ijUSrbMk+0wTaZeyeYs8Z6cOicDIVN6bN6yC/Se5fbzTTCSmg=ww2w+NbXwY/GRBZfFcXqrAM2X+P1NQoU+QEvgLO1izMTB8kvx1i/bodBvHTrKMwAMGEO4kVATA1f1Vf5/lVnbqiCLMJPVRZU6rWKjOGD28T/VRaIGywTV+mC0HvMbe4DlEd3dBwJZLIMUNvOPsj5Ua+l9IS4EoszFNAg6F5Lsyk=AQAB"; + Assert.False(Helpers.VerifyCryptoExceptionOnLoad(xml, true)); + } + + [Fact] + public static void DuplicateSignatureValue() + { + string arbitraryData = @"lol"; + string xml = $@"XZVZLYkc1BAx+YtaqeYlxanb2cGI=Kx8xs0of766gimu5girTqiTR5xoiWjN4XMx8uzDDhG70bIqpSzlhh6IA3iI54R5mpqCCPWrJJp85ps4jpQk8RGHe4KMejstbY6YXCfs7LtRPzkNzcoZB3vDbr3ijUSrbMk+0wTaZeyeYs8Z6cOicDIVN6bN6yC/Se5fbzTTCSmg={arbitraryData}ww2w+NbXwY/GRBZfFcXqrAM2X+P1NQoU+QEvgLO1izMTB8kvx1i/bodBvHTrKMwAMGEO4kVATA1f1Vf5/lVnbqiCLMJPVRZU6rWKjOGD28T/VRaIGywTV+mC0HvMbe4DlEd3dBwJZLIMUNvOPsj5Ua+l9IS4EoszFNAg6F5Lsyk=AQAB"; + Assert.False(Helpers.VerifyCryptoExceptionOnLoad(xml, true)); + } + + [Fact] + public static void DuplicateKeyInfo() + { + string arbitraryData = @"lol"; + string xml = $@"XZVZLYkc1BAx+YtaqeYlxanb2cGI=Kx8xs0of766gimu5girTqiTR5xoiWjN4XMx8uzDDhG70bIqpSzlhh6IA3iI54R5mpqCCPWrJJp85ps4jpQk8RGHe4KMejstbY6YXCfs7LtRPzkNzcoZB3vDbr3ijUSrbMk+0wTaZeyeYs8Z6cOicDIVN6bN6yC/Se5fbzTTCSmg=ww2w+NbXwY/GRBZfFcXqrAM2X+P1NQoU+QEvgLO1izMTB8kvx1i/bodBvHTrKMwAMGEO4kVATA1f1Vf5/lVnbqiCLMJPVRZU6rWKjOGD28T/VRaIGywTV+mC0HvMbe4DlEd3dBwJZLIMUNvOPsj5Ua+l9IS4EoszFNAg6F5Lsyk=AQAB{arbitraryData}ww2w+NbXwY/GRBZfFcXqrAM2X+P1NQoU+QEvgLO1izMTB8kvx1i/bodBvHTrKMwAMGEO4kVATA1f1Vf5/lVnbqiCLMJPVRZU6rWKjOGD28T/VRaIGywTV+mC0HvMbe4DlEd3dBwJZLIMUNvOPsj5Ua+l9IS4EoszFNAg6F5Lsyk=AQAB"; + Assert.False(Helpers.VerifyCryptoExceptionOnLoad(xml, true)); + } + } +} diff --git a/src/System.Security.Cryptography.Xml/tests/SignedInfo_ArbitraryElements.cs b/src/System.Security.Cryptography.Xml/tests/SignedInfo_ArbitraryElements.cs new file mode 100644 index 000000000000..9c6b03b078cb --- /dev/null +++ b/src/System.Security.Cryptography.Xml/tests/SignedInfo_ArbitraryElements.cs @@ -0,0 +1,81 @@ +// Licensed to the .NET Foundation under one or more agreements. +// See the LICENSE file in the project root for more information. + +using System.Xml; +using Xunit; + +namespace System.Security.Cryptography.Xml.Tests +{ + public class SignedInfo_ArbitraryElements + { + [Fact] + public static void ExtraData() + { + string arbitraryData = @"lol"; + + string xml = $@"X{arbitraryData}ZVZLYkc1BAx+YtaqeYlxanb2cGI=Kx8xs0of766gimu5girTqiTR5xoiWjN4XMx8uzDDhG70bIqpSzlhh6IA3iI54R5mpqCCPWrJJp85ps4jpQk8RGHe4KMejstbY6YXCfs7LtRPzkNzcoZB3vDbr3ijUSrbMk+0wTaZeyeYs8Z6cOicDIVN6bN6yC/Se5fbzTTCSmg=ww2w+NbXwY/GRBZfFcXqrAM2X+P1NQoU+QEvgLO1izMTB8kvx1i/bodBvHTrKMwAMGEO4kVATA1f1Vf5/lVnbqiCLMJPVRZU6rWKjOGD28T/VRaIGywTV+mC0HvMbe4DlEd3dBwJZLIMUNvOPsj5Ua+l9IS4EoszFNAg6F5Lsyk=AQAB"; + Assert.False(Helpers.VerifyCryptoExceptionOnLoad(xml, true)); + } + + [Fact] + public static void OutOfOrder() + { + string xml = $@"XZVZLYkc1BAx+YtaqeYlxanb2cGI=Kx8xs0of766gimu5girTqiTR5xoiWjN4XMx8uzDDhG70bIqpSzlhh6IA3iI54R5mpqCCPWrJJp85ps4jpQk8RGHe4KMejstbY6YXCfs7LtRPzkNzcoZB3vDbr3ijUSrbMk+0wTaZeyeYs8Z6cOicDIVN6bN6yC/Se5fbzTTCSmg=ww2w+NbXwY/GRBZfFcXqrAM2X+P1NQoU+QEvgLO1izMTB8kvx1i/bodBvHTrKMwAMGEO4kVATA1f1Vf5/lVnbqiCLMJPVRZU6rWKjOGD28T/VRaIGywTV+mC0HvMbe4DlEd3dBwJZLIMUNvOPsj5Ua+l9IS4EoszFNAg6F5Lsyk=AQAB"; + Assert.False(Helpers.VerifyCryptoExceptionOnLoad(xml, false)); + } + + [Fact] + public static void DuplicateCanonicalizationMethod() + { + string arbitraryData = @"lol"; + + string xml = $@"X{arbitraryData}ZVZLYkc1BAx+YtaqeYlxanb2cGI=Kx8xs0of766gimu5girTqiTR5xoiWjN4XMx8uzDDhG70bIqpSzlhh6IA3iI54R5mpqCCPWrJJp85ps4jpQk8RGHe4KMejstbY6YXCfs7LtRPzkNzcoZB3vDbr3ijUSrbMk+0wTaZeyeYs8Z6cOicDIVN6bN6yC/Se5fbzTTCSmg=ww2w+NbXwY/GRBZfFcXqrAM2X+P1NQoU+QEvgLO1izMTB8kvx1i/bodBvHTrKMwAMGEO4kVATA1f1Vf5/lVnbqiCLMJPVRZU6rWKjOGD28T/VRaIGywTV+mC0HvMbe4DlEd3dBwJZLIMUNvOPsj5Ua+l9IS4EoszFNAg6F5Lsyk=AQAB"; + Assert.False(Helpers.VerifyCryptoExceptionOnLoad(xml, true)); + } + + [Fact] + public static void DuplicateSignatureMethod() + { + string arbitraryData = @"lol"; + + string xml = $@"X{arbitraryData}ZVZLYkc1BAx+YtaqeYlxanb2cGI=Kx8xs0of766gimu5girTqiTR5xoiWjN4XMx8uzDDhG70bIqpSzlhh6IA3iI54R5mpqCCPWrJJp85ps4jpQk8RGHe4KMejstbY6YXCfs7LtRPzkNzcoZB3vDbr3ijUSrbMk+0wTaZeyeYs8Z6cOicDIVN6bN6yC/Se5fbzTTCSmg=ww2w+NbXwY/GRBZfFcXqrAM2X+P1NQoU+QEvgLO1izMTB8kvx1i/bodBvHTrKMwAMGEO4kVATA1f1Vf5/lVnbqiCLMJPVRZU6rWKjOGD28T/VRaIGywTV+mC0HvMbe4DlEd3dBwJZLIMUNvOPsj5Ua+l9IS4EoszFNAg6F5Lsyk=AQAB"; + Assert.False(Helpers.VerifyCryptoExceptionOnLoad(xml, true)); + } + + [Fact] + public static void ExtraAttributes() + { + string xml = $@"XZVZLYkc1BAx+YtaqeYlxanb2cGI=Kx8xs0of766gimu5girTqiTR5xoiWjN4XMx8uzDDhG70bIqpSzlhh6IA3iI54R5mpqCCPWrJJp85ps4jpQk8RGHe4KMejstbY6YXCfs7LtRPzkNzcoZB3vDbr3ijUSrbMk+0wTaZeyeYs8Z6cOicDIVN6bN6yC/Se5fbzTTCSmg=ww2w+NbXwY/GRBZfFcXqrAM2X+P1NQoU+QEvgLO1izMTB8kvx1i/bodBvHTrKMwAMGEO4kVATA1f1Vf5/lVnbqiCLMJPVRZU6rWKjOGD28T/VRaIGywTV+mC0HvMbe4DlEd3dBwJZLIMUNvOPsj5Ua+l9IS4EoszFNAg6F5Lsyk=AQAB"; + Assert.False(Helpers.VerifyCryptoExceptionOnLoad(xml, true)); + } + + [Fact] + public static void ExtraAttributes_CanonicalizationMethod() + { + string xml = $@"XZVZLYkc1BAx+YtaqeYlxanb2cGI=Kx8xs0of766gimu5girTqiTR5xoiWjN4XMx8uzDDhG70bIqpSzlhh6IA3iI54R5mpqCCPWrJJp85ps4jpQk8RGHe4KMejstbY6YXCfs7LtRPzkNzcoZB3vDbr3ijUSrbMk+0wTaZeyeYs8Z6cOicDIVN6bN6yC/Se5fbzTTCSmg=ww2w+NbXwY/GRBZfFcXqrAM2X+P1NQoU+QEvgLO1izMTB8kvx1i/bodBvHTrKMwAMGEO4kVATA1f1Vf5/lVnbqiCLMJPVRZU6rWKjOGD28T/VRaIGywTV+mC0HvMbe4DlEd3dBwJZLIMUNvOPsj5Ua+l9IS4EoszFNAg6F5Lsyk=AQAB"; + Assert.False(Helpers.VerifyCryptoExceptionOnLoad(xml, true)); + } + + [Fact] + public static void MissingAttributes_CanonicalizationMethod() + { + string xml = $@"XZVZLYkc1BAx+YtaqeYlxanb2cGI=Kx8xs0of766gimu5girTqiTR5xoiWjN4XMx8uzDDhG70bIqpSzlhh6IA3iI54R5mpqCCPWrJJp85ps4jpQk8RGHe4KMejstbY6YXCfs7LtRPzkNzcoZB3vDbr3ijUSrbMk+0wTaZeyeYs8Z6cOicDIVN6bN6yC/Se5fbzTTCSmg=ww2w+NbXwY/GRBZfFcXqrAM2X+P1NQoU+QEvgLO1izMTB8kvx1i/bodBvHTrKMwAMGEO4kVATA1f1Vf5/lVnbqiCLMJPVRZU6rWKjOGD28T/VRaIGywTV+mC0HvMbe4DlEd3dBwJZLIMUNvOPsj5Ua+l9IS4EoszFNAg6F5Lsyk=AQAB"; + Assert.False(Helpers.VerifyCryptoExceptionOnLoad(xml, true)); + } + + [Fact] + public static void ExtraAttributes_SignatureMethod() + { + string xml = $@"XZVZLYkc1BAx+YtaqeYlxanb2cGI=Kx8xs0of766gimu5girTqiTR5xoiWjN4XMx8uzDDhG70bIqpSzlhh6IA3iI54R5mpqCCPWrJJp85ps4jpQk8RGHe4KMejstbY6YXCfs7LtRPzkNzcoZB3vDbr3ijUSrbMk+0wTaZeyeYs8Z6cOicDIVN6bN6yC/Se5fbzTTCSmg=ww2w+NbXwY/GRBZfFcXqrAM2X+P1NQoU+QEvgLO1izMTB8kvx1i/bodBvHTrKMwAMGEO4kVATA1f1Vf5/lVnbqiCLMJPVRZU6rWKjOGD28T/VRaIGywTV+mC0HvMbe4DlEd3dBwJZLIMUNvOPsj5Ua+l9IS4EoszFNAg6F5Lsyk=AQAB"; + Assert.False(Helpers.VerifyCryptoExceptionOnLoad(xml, true)); + } + + [Fact] + public static void MissingAttributes_SignatureMethod() + { + string xml = $@"XZVZLYkc1BAx+YtaqeYlxanb2cGI=Kx8xs0of766gimu5girTqiTR5xoiWjN4XMx8uzDDhG70bIqpSzlhh6IA3iI54R5mpqCCPWrJJp85ps4jpQk8RGHe4KMejstbY6YXCfs7LtRPzkNzcoZB3vDbr3ijUSrbMk+0wTaZeyeYs8Z6cOicDIVN6bN6yC/Se5fbzTTCSmg=ww2w+NbXwY/GRBZfFcXqrAM2X+P1NQoU+QEvgLO1izMTB8kvx1i/bodBvHTrKMwAMGEO4kVATA1f1Vf5/lVnbqiCLMJPVRZU6rWKjOGD28T/VRaIGywTV+mC0HvMbe4DlEd3dBwJZLIMUNvOPsj5Ua+l9IS4EoszFNAg6F5Lsyk=AQAB"; + Assert.False(Helpers.VerifyCryptoExceptionOnLoad(xml, true)); + + } + } +} diff --git a/src/System.Security.Cryptography.Xml/tests/SignedXml_Helpers.cs b/src/System.Security.Cryptography.Xml/tests/SignedXml_Helpers.cs new file mode 100644 index 000000000000..2ca013195987 --- /dev/null +++ b/src/System.Security.Cryptography.Xml/tests/SignedXml_Helpers.cs @@ -0,0 +1,34 @@ +// Licensed to the .NET Foundation under one or more agreements. +// See the LICENSE file in the project root for more information. + +using System.Xml; +using System.Security.Cryptography.X509Certificates; +using Xunit; + +namespace System.Security.Cryptography.Xml.Tests +{ + public static class Helpers + { + public static bool VerifyCryptoExceptionOnLoad(string xml, bool loadXmlThrows) + { + var xmlDoc = new XmlDocument(); + xmlDoc.PreserveWhitespace = true; + xmlDoc.LoadXml(xml); + + var signatureNode = (XmlElement)xmlDoc.GetElementsByTagName("Signature", SignedXml.XmlDsigNamespaceUrl)[0]; + + SignedXml signedXml = new SignedXml(xmlDoc); + if (loadXmlThrows) + Assert.Throws(() => signedXml.LoadXml(signatureNode)); + else + signedXml.LoadXml(signatureNode); + + if (!loadXmlThrows) + { + bool checkSigResult = signedXml.CheckSignature(); + return checkSigResult; + } + return false; + } + } +} diff --git a/src/System.Security.Cryptography.Xml/tests/SignedXml_Limits.cs b/src/System.Security.Cryptography.Xml/tests/SignedXml_Limits.cs new file mode 100644 index 000000000000..4f20978f5b7d --- /dev/null +++ b/src/System.Security.Cryptography.Xml/tests/SignedXml_Limits.cs @@ -0,0 +1,41 @@ +// Licensed to the .NET Foundation under one or more agreements. +// See the LICENSE file in the project root for more information. + +using System.Xml; +using Xunit; + +namespace System.Security.Cryptography.Xml.Tests +{ + public class SignedXml_Limits + { + private const int MaxTransformsPerReference = 10; + private const int MaxReferencesPerSignedInfo = 100; + + [Theory] + [InlineData(1, 1, false)] + [InlineData(MaxTransformsPerReference, 1, false)] + [InlineData(MaxTransformsPerReference + 1, 1, true)] + [InlineData(1, MaxReferencesPerSignedInfo, false)] + [InlineData(1, MaxReferencesPerSignedInfo + 1, true)] + [InlineData(MaxTransformsPerReference, MaxReferencesPerSignedInfo, false)] + [InlineData(MaxTransformsPerReference, MaxReferencesPerSignedInfo + 1, true)] + [InlineData(MaxTransformsPerReference + 1, MaxReferencesPerSignedInfo, true)] + [InlineData(MaxTransformsPerReference + 1, MaxReferencesPerSignedInfo + 1, true)] + public static void TestReferenceLimits(int numTransformsPerReference, int numReferencesPerSignedInfo, bool loadXmlThrows) + { + string xml = $@" +X"; + for (int i = 0; i < numReferencesPerSignedInfo; i++) + { + xml += $@""; + for (int j = 0; j < numTransformsPerReference; j++) + { + xml += $@""; + } + xml += $@"ZVZLYkc1BAx+YtaqeYlxanb2cGI="; + } + xml += $@"Kx8xs0of766gimu5girTqiTR5xoiWjN4XMx8uzDDhG70bIqpSzlhh6IA3iI54R5mpqCCPWrJJp85ps4jpQk8RGHe4KMejstbY6YXCfs7LtRPzkNzcoZB3vDbr3ijUSrbMk+0wTaZeyeYs8Z6cOicDIVN6bN6yC/Se5fbzTTCSmg=ww2w+NbXwY/GRBZfFcXqrAM2X+P1NQoU+QEvgLO1izMTB8kvx1i/bodBvHTrKMwAMGEO4kVATA1f1Vf5/lVnbqiCLMJPVRZU6rWKjOGD28T/VRaIGywTV+mC0HvMbe4DlEd3dBwJZLIMUNvOPsj5Ua+l9IS4EoszFNAg6F5Lsyk=AQAB"; + Helpers.VerifyCryptoExceptionOnLoad(xml, loadXmlThrows); + } + } +} diff --git a/src/System.Security.Cryptography.Xml/tests/SignedXml_SignatureMethodAlgorithm.cs b/src/System.Security.Cryptography.Xml/tests/SignedXml_SignatureMethodAlgorithm.cs new file mode 100644 index 000000000000..71af4cda6ebe --- /dev/null +++ b/src/System.Security.Cryptography.Xml/tests/SignedXml_SignatureMethodAlgorithm.cs @@ -0,0 +1,38 @@ +// Licensed to the .NET Foundation under one or more agreements. +// See the LICENSE file in the project root for more information. + +using System.Xml; +using Xunit; + +namespace System.Security.Cryptography.Xml.Tests +{ + public class SignedXml_SignatureMethodAlgorithm + { + [Fact] + public static void TestDummySignatureAlgorithm() + { + string objectToConstruct = typeof(DummyClass).AssemblyQualifiedName; + string xml = $@" + XZVZLYkc1BAx+YtaqeYlxanb2cGI=Kx8xs0of766gimu5girTqiTR5xoiWjN4XMx8uzDDhG70bIqpSzlhh6IA3iI54R5mpqCCPWrJJp85ps4jpQk8RGHe4KMejstbY6YXCfs7LtRPzkNzcoZB3vDbr3ijUSrbMk+0wTaZeyeYs8Z6cOicDIVN6bN6yC/Se5fbzTTCSmg=ww2w+NbXwY/GRBZfFcXqrAM2X+P1NQoU+QEvgLO1izMTB8kvx1i/bodBvHTrKMwAMGEO4kVATA1f1Vf5/lVnbqiCLMJPVRZU6rWKjOGD28T/VRaIGywTV+mC0HvMbe4DlEd3dBwJZLIMUNvOPsj5Ua+l9IS4EoszFNAg6F5Lsyk=AQAB"; + + var xmlDoc = new XmlDocument(); + xmlDoc.PreserveWhitespace = true; + xmlDoc.LoadXml(xml); + + var signatureNode = (XmlElement)xmlDoc.GetElementsByTagName("Signature", SignedXml.XmlDsigNamespaceUrl)[0]; + + SignedXml signedXml = new SignedXml(xmlDoc); + signedXml.LoadXml(signatureNode); + Assert.Throws(() => signedXml.CheckSignature()); + } + + public class DummyClass + { + public DummyClass() + { + Assert.False(true); + } + } + } +} + diff --git a/src/System.Security.Cryptography.Xml/tests/System.Security.Cryptography.Xml.Tests.csproj b/src/System.Security.Cryptography.Xml/tests/System.Security.Cryptography.Xml.Tests.csproj index 3cb9cf6d35d2..df30f0c72c5b 100644 --- a/src/System.Security.Cryptography.Xml/tests/System.Security.Cryptography.Xml.Tests.csproj +++ b/src/System.Security.Cryptography.Xml/tests/System.Security.Cryptography.Xml.Tests.csproj @@ -21,12 +21,15 @@ + + + @@ -35,10 +38,14 @@ + + + + @@ -67,4 +74,4 @@ - + \ No newline at end of file diff --git a/src/System.Security.Cryptography.Xml/tests/XmlDecryptionTransformTest.cs b/src/System.Security.Cryptography.Xml/tests/XmlDecryptionTransformTest.cs index 5b2051e3a646..70d86a8ceafa 100644 --- a/src/System.Security.Cryptography.Xml/tests/XmlDecryptionTransformTest.cs +++ b/src/System.Security.Cryptography.Xml/tests/XmlDecryptionTransformTest.cs @@ -110,7 +110,7 @@ public void LoadInnerXml_XmlNoExcept() XmlDocument doc = new XmlDocument(); doc.LoadXml(""); - transform.LoadInnerXml(doc.ChildNodes); + Assert.Throws(() => transform.LoadInnerXml(doc.ChildNodes)); Assert.Null(transform.UnprotectedGetInnerXml()); }