Merge pull request #498 from Unroll-Me/master
[mono.git] / mcs / class / corlib / System.Security.Cryptography / RSA.cs
index 1dd947f8e8883d4f6e53218638acf4749affe996..1a575931845239bfd6082d76cbeb07ac6556b2bf 100644 (file)
 // System.Security.Cryptography.RSA.cs
 //
 // Authors:
-//   Dan Lewis (dihlewis@yahoo.co.uk)
-//   Sebastien Pouliot (spouliot@motus.com)
+//     Dan Lewis (dihlewis@yahoo.co.uk)
+//     Sebastien Pouliot (sebastien@ximian.com)
 //
 // (C) 2002
-// Portions (C) 2002 Motus Technologies Inc. (http://www.motus.com)
+// Portions (C) 2002, 2003 Motus Technologies Inc. (http://www.motus.com)
+// Copyright (C) 2004-2006,2008 Novell, Inc (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+// 
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+// 
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 //
 
-using System;
+using System.Globalization;
+using System.Runtime.InteropServices;
 using System.Text;
 
-namespace System.Security.Cryptography 
-{
-       internal class RSAHandler : MiniParser.IHandler {
-
-               private RSAParameters rsa;
-               private bool unknown;
-               private byte[] temp;
-
-               public RSAHandler () 
-               {
-                       rsa = new RSAParameters();
-               }
-
-               public RSAParameters GetParams () {
-                       return rsa;
-               }
-
-               public void OnStartParsing (MiniParser parser) {}
-
-               public void OnStartElement (string name, MiniParser.IAttrList attrs) {}
-
-               public void OnEndElement (string name) {
-                       switch (name) {
-                               case "P":
-                                       rsa.P = temp;
-                                       break;
-                               case "Q":
-                                       rsa.Q = temp;
-                                       break;
-                               case "D":
-                                       rsa.D = temp;
-                                       break;
-                               case "DP":
-                                       rsa.DP = temp;
-                                       break;
-                               case "DQ":
-                                       rsa.DQ = temp;
-                                       break;
-                               case "Exponent":
-                                       rsa.Exponent = temp;
-                                       break;
-                               case "InverseQ":
-                                       rsa.InverseQ = temp;
-                                       break;
-                               case "Modulus":
-                                       rsa.Modulus = temp;
-                                       break;
-                               default:
-                                       // unknown tag in parameters
-                                       break;
-                       }
-               }
+using Mono.Xml;
 
-               public void OnChars (string ch) 
-               {
-                       temp = Convert.FromBase64String (ch);
-               }
+namespace System.Security.Cryptography {
 
-               public void OnEndParsing (MiniParser parser) {}
-       }
+       [ComVisible (true)]
+       public abstract class RSA : AsymmetricAlgorithm {
 
-       public abstract class RSA : AsymmetricAlgorithm 
-       {
                public static new RSA Create () 
                {
+#if FULL_AOT_RUNTIME
+                       return new System.Security.Cryptography.RSACryptoServiceProvider ();
+#else
                        return Create ("System.Security.Cryptography.RSA");
+#endif
                }
 
                public static new RSA Create (string algName)
                {
                        return (RSA) CryptoConfig.CreateFromName (algName);
                }
-       
-               public RSA () { }
+
+               protected RSA ()
+               {
+               }
 
                public abstract byte[] EncryptValue (byte[] rgb);
+
                public abstract byte[] DecryptValue (byte[] rgb);
 
-               public abstract RSAParameters ExportParameters (bool include);
+               public abstract RSAParameters ExportParameters (bool includePrivateParameters);
+
                public abstract void ImportParameters (RSAParameters parameters);
 
-               protected void ZeroizePrivateKey (RSAParameters parameters)
+               internal void ZeroizePrivateKey (RSAParameters parameters)
                {
                        if (parameters.P != null)
-                               Array.Clear(parameters.P, 0, parameters.P.Length);
+                               Array.Clear (parameters.P, 0, parameters.P.Length);
                        if (parameters.Q != null)
-                               Array.Clear(parameters.Q, 0, parameters.Q.Length);
+                               Array.Clear (parameters.Q, 0, parameters.Q.Length);
                        if (parameters.DP != null)
-                               Array.Clear(parameters.DP, 0, parameters.DP.Length);
+                               Array.Clear (parameters.DP, 0, parameters.DP.Length);
                        if (parameters.DQ != null)
-                               Array.Clear(parameters.DQ, 0, parameters.DQ.Length);
+                               Array.Clear (parameters.DQ, 0, parameters.DQ.Length);
                        if (parameters.InverseQ != null)
-                               Array.Clear(parameters.InverseQ, 0, parameters.InverseQ.Length);
+                               Array.Clear (parameters.InverseQ, 0, parameters.InverseQ.Length);
                        if (parameters.D != null)
-                               Array.Clear(parameters.D, 0, parameters.D.Length);
+                               Array.Clear (parameters.D, 0, parameters.D.Length);
                }
 
                public override void FromXmlString (string xmlString) 
                {
                        if (xmlString == null)
-                               throw new ArgumentNullException ();
+                               throw new ArgumentNullException ("xmlString");
 
                        RSAParameters rsaParams = new RSAParameters ();
                        try {
-                               MiniParser parser = new MiniParser ();
-                               AsymmetricParameters reader = new AsymmetricParameters (xmlString);
-                               RSAHandler handler = new RSAHandler ();
-                               parser.Parse(reader, handler);
-                               ImportParameters (handler.GetParams ());
+                               rsaParams.P = GetNamedParam (xmlString, "P");
+                               rsaParams.Q = GetNamedParam (xmlString, "Q");
+                               rsaParams.D = GetNamedParam (xmlString, "D");
+                               rsaParams.DP = GetNamedParam (xmlString, "DP");
+                               rsaParams.DQ = GetNamedParam (xmlString, "DQ");
+                               rsaParams.InverseQ = GetNamedParam (xmlString, "InverseQ");
+                               rsaParams.Exponent = GetNamedParam (xmlString, "Exponent");
+                               rsaParams.Modulus = GetNamedParam (xmlString, "Modulus");
+                               ImportParameters (rsaParams);
                        }
-                       catch {
+                       catch (Exception e) {
                                ZeroizePrivateKey (rsaParams);
-                               throw new CryptographicException ();
+                               throw new CryptographicException (
+                                       Locale.GetText ("Couldn't decode XML"), e);
                        }
                        finally {
                                ZeroizePrivateKey (rsaParams);
@@ -146,8 +124,20 @@ namespace System.Security.Cryptography
                                sb.Append (Convert.ToBase64String (rsaParams.Exponent));
                                sb.Append ("</Exponent>");
 
-                               if (includePrivateParameters)
-                               {
+                               if (includePrivateParameters) {
+                                       // we want an ArgumentNullException is only the D is missing, but a
+                                       // CryptographicException if other parameters (CRT) are missings
+                                       if (rsaParams.D == null) {
+                                               string msg = Locale.GetText ("Missing D parameter for the private key.");
+                                               throw new ArgumentNullException (msg);
+                                       } else if ((rsaParams.P == null) || (rsaParams.Q == null) || (rsaParams.DP == null) ||
+                                               (rsaParams.DQ == null) || (rsaParams.InverseQ == null)) {
+                                               // note: we can import a private key, using FromXmlString,
+                                               // without the CRT parameters but we export it using ToXmlString!
+                                               string msg = Locale.GetText ("Missing some CRT parameters for the private key.");
+                                               throw new CryptographicException (msg);
+                                       }
+
                                        sb.Append ("<P>");
                                        sb.Append (Convert.ToBase64String (rsaParams.P));
                                        sb.Append ("</P>");