[corlib] Fixes security tests failures
[mono.git] / mcs / class / System.Security / System.Security.Cryptography.Xml / EncryptedXml.cs
index 27a132880a09e8b2f9d3421b70cd79d2741aaf48..6dde9199a2ad36d5c5f9d8620f7444ff22760df2 100644 (file)
@@ -27,7 +27,6 @@
 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 //
 
-#if NET_2_0
 
 using System.Collections;
 using System.IO;
@@ -141,7 +140,18 @@ namespace System.Security.Cryptography.Xml {
 
                public byte[] DecryptData (EncryptedData encryptedData, SymmetricAlgorithm symAlg)
                {
-                       return Transform (encryptedData.CipherData.CipherValue, symAlg.CreateDecryptor (), 0);
+                       if (encryptedData == null)
+                               throw new ArgumentNullException ("encryptedData");
+                       if (symAlg == null)
+                               throw new ArgumentNullException ("symAlg");
+
+                       PaddingMode bak = symAlg.Padding;
+                       try {
+                               symAlg.Padding = Padding;
+                               return Transform (encryptedData.CipherData.CipherValue, symAlg.CreateDecryptor (), symAlg.BlockSize / 8, true);
+                       } finally {
+                               symAlg.Padding = bak;
+                       }
                }
 
                public void DecryptDocument ()
@@ -157,6 +167,9 @@ namespace System.Security.Cryptography.Xml {
 
                public virtual byte[] DecryptEncryptedKey (EncryptedKey encryptedKey)
                {
+                       if (encryptedKey == null)
+                               throw new ArgumentNullException ("encryptedKey");
+
                        object keyAlg = null;
                        foreach (KeyInfoClause innerClause in encryptedKey.KeyInfo) {
                                if (innerClause is KeyInfoName) {
@@ -175,6 +188,11 @@ namespace System.Security.Cryptography.Xml {
 
                public static byte[] DecryptKey (byte[] keyData, SymmetricAlgorithm symAlg)
                {
+                       if (keyData == null)
+                               throw new ArgumentNullException ("keyData");
+                       if (symAlg == null)
+                               throw new ArgumentNullException ("symAlg");
+
                        if (symAlg is TripleDES)
                                return SymmetricKeyWrap.TripleDESKeyWrapDecrypt (symAlg.Key, keyData);
                        if (symAlg is Rijndael)
@@ -237,6 +255,22 @@ namespace System.Security.Cryptography.Xml {
                }
 
                public byte[] EncryptData (byte[] plainText, SymmetricAlgorithm symAlg)
+               {
+                       if (plainText == null)
+                               throw new ArgumentNullException ("plainText");
+                       if (symAlg == null)
+                               throw new ArgumentNullException ("symAlg");
+
+                       PaddingMode bak = symAlg.Padding;
+                       try {
+                               symAlg.Padding = Padding;
+                               return EncryptDataCore (plainText, symAlg);
+                       } finally {
+                               symAlg.Padding = bak;
+                       }
+               }
+
+               byte[] EncryptDataCore (byte[] plainText, SymmetricAlgorithm symAlg)
                {
                        // Write the symmetric algorithm IV and ciphertext together.
                        // We use a memory stream to accomplish this.
@@ -257,6 +291,9 @@ namespace System.Security.Cryptography.Xml {
 
                public byte[] EncryptData (XmlElement inputElement, SymmetricAlgorithm symAlg, bool content)
                {
+                       if (inputElement == null)
+                               throw new ArgumentNullException ("inputElement");
+
                        if (content)
                                return EncryptData (Encoding.GetBytes (inputElement.InnerXml), symAlg);
                        else
@@ -265,6 +302,11 @@ namespace System.Security.Cryptography.Xml {
 
                public static byte[] EncryptKey (byte[] keyData, SymmetricAlgorithm symAlg)
                {
+                       if (keyData == null)
+                               throw new ArgumentNullException ("keyData");
+                       if (symAlg == null)
+                               throw new ArgumentNullException ("symAlg");
+
                        if (symAlg is TripleDES)
                                return SymmetricKeyWrap.TripleDESKeyWrapEncrypt (symAlg.Key, keyData);
                        if (symAlg is Rijndael)
@@ -312,7 +354,7 @@ namespace System.Security.Cryptography.Xml {
                                symAlg = SymmetricAlgorithm.Create ("TripleDES");
                                break;
                        default:
-                               throw new ArgumentException ("symAlgUri");
+                               throw new CryptographicException ("symAlgUri");
                        }
 
                        return symAlg;
@@ -362,6 +404,9 @@ namespace System.Security.Cryptography.Xml {
 
                public virtual byte[] GetDecryptionIV (EncryptedData encryptedData, string symAlgUri)
                {
+                       if (encryptedData == null)
+                               throw new ArgumentNullException ("encryptedData");
+
                        SymmetricAlgorithm symAlg = GetAlgorithm (symAlgUri);
                        byte[] iv = new Byte [symAlg.BlockSize / 8];
                        Buffer.BlockCopy (encryptedData.CipherData.CipherValue, 0, iv, 0, iv.Length);
@@ -370,6 +415,11 @@ namespace System.Security.Cryptography.Xml {
 
                public virtual SymmetricAlgorithm GetDecryptionKey (EncryptedData encryptedData, string symAlgUri)
                {
+                       if (encryptedData == null)
+                               throw new ArgumentNullException ("encryptedData");
+                       if (symAlgUri == null)
+                               return null;
+
                        SymmetricAlgorithm symAlg = GetAlgorithm (symAlgUri);
                        symAlg.IV = GetDecryptionIV (encryptedData, encryptedData.EncryptionMethod.KeyAlgorithm);
                        KeyInfo keyInfo = encryptedData.KeyInfo;
@@ -384,6 +434,9 @@ namespace System.Security.Cryptography.Xml {
 
                public virtual XmlElement GetIdElement (XmlDocument document, string idValue)
                {
+                       if ((document == null) || (idValue == null))
+                               return null;
+
                         // this works only if there's a DTD or XSD available to define the ID
                        XmlElement xel = document.GetElementById (idValue);
                        if (xel == null) {
@@ -395,6 +448,11 @@ namespace System.Security.Cryptography.Xml {
 
                public void ReplaceData (XmlElement inputElement, byte[] decryptedData)
                {
+                       if (inputElement == null)
+                               throw new ArgumentNullException ("inputElement");
+                       if (decryptedData == null)
+                               throw new ArgumentNullException ("decryptedData");
+
                        XmlDocument ownerDocument = inputElement.OwnerDocument;
                        XmlTextReader reader = new XmlTextReader (new StringReader (Encoding.GetString (decryptedData, 0, decryptedData.Length)));
                        reader.MoveToContent ();
@@ -404,24 +462,38 @@ namespace System.Security.Cryptography.Xml {
 
                public static void ReplaceElement (XmlElement inputElement, EncryptedData encryptedData, bool content)
                {
+                       if (inputElement == null)
+                               throw new ArgumentNullException ("inputElement");
+                       if (encryptedData == null)
+                               throw new ArgumentNullException ("encryptedData");
+
                        XmlDocument ownerDocument = inputElement.OwnerDocument;
                        inputElement.ParentNode.ReplaceChild (encryptedData.GetXml (ownerDocument), inputElement);
                }
 
                private byte[] Transform (byte[] data, ICryptoTransform transform)
                {
-                       return Transform (data, transform, 0);
+                       return Transform (data, transform, 0, false);
                }
 
-               private byte[] Transform (byte[] data, ICryptoTransform transform, int startIndex)
+               private byte[] Transform (byte[] data, ICryptoTransform transform, int blockOctetCount, bool trimPadding)
                {
                        MemoryStream output = new MemoryStream ();
                        CryptoStream crypto = new CryptoStream (output, transform, CryptoStreamMode.Write);
-                       crypto.Write (data, startIndex, data.Length - startIndex);
+                       crypto.Write (data, 0, data.Length);
 
                        crypto.FlushFinalBlock ();
 
-                       byte[] result = output.ToArray ();
+                       // strip padding (see xmlenc spec 5.2)
+                       int trimSize = 0;
+                       if (trimPadding)
+                               trimSize = output.GetBuffer () [output.Length - 1];
+                       // It should not happen, but somehow .NET allows such cipher 
+                       // data as if there were no padding.
+                       if (trimSize > blockOctetCount)
+                               trimSize = 0;
+                       byte[] result = new byte [output.Length - blockOctetCount - trimSize];
+                       Array.Copy (output.GetBuffer (), blockOctetCount, result, 0, result.Length);
 
                        crypto.Close ();
                        output.Close ();
@@ -433,4 +505,3 @@ namespace System.Security.Cryptography.Xml {
        }
 }
 
-#endif