* roottypes.cs: Rename from tree.cs.
[mono.git] / mcs / class / Microsoft.Web.Services / Microsoft.Web.Services.Security / EncryptedKey.cs
index 40fcb93c6f5749bb320486cfe0ec9c7fb5bafe86..b300151aacfce625899addb1d25acbac119dfc01 100644 (file)
@@ -6,39 +6,46 @@
 //
 // (C) 2002, 2003 Motus Technologies Inc. (http://www.motus.com)
 //
-// Licensed under MIT X11 (see LICENSE) with this specific addition:
-//
-// \93This source code may incorporate intellectual property owned by Microsoft 
-// Corporation. Our provision of this source code does not include any licenses
-// or any other rights to you under any Microsoft intellectual property. If you
-// would like a license from Microsoft (e.g. rebrand, redistribute), you need 
-// to contact Microsoft directly.\94 
-//
 
 using System;
+using System.Security.Cryptography;
 using System.Security.Cryptography.Xml;
 using System.Xml;
+#if !WSE1
 using Microsoft.Web.Services.Xml;
+#endif
 
 namespace Microsoft.Web.Services.Security {
 
        public class EncryptedKey : IXmlElement {
 
-               private AsymmetricEncryptionKey aek;
-               private KeyInfo ki;
+               private DecryptionKey dk;
+               private EncryptionKey ek;
                private ReferenceList list;
+               private string keyex;
+               private string session;
+               private SymmetricEncryptionKey key;
+               private byte[] decdata;
 
-               internal EncryptedKey () 
+               internal EncryptedKey ()
                {
                        list = new ReferenceList ();
+                       keyex = XmlEncryption.AlgorithmURI.RSA15;
+                       session = XmlEncryption.AlgorithmURI.TripleDES;
                }
 
+#if WSE1
                public EncryptedKey (AsymmetricEncryptionKey key) : this ()
+#else
+               [Obsolete ("since WSE2 TP")]
+               public EncryptedKey (EncryptionKey key) : this ()
+#endif
                {
                        if (key == null)
                                throw new ArgumentNullException ("key");
-                       aek = key;
-                       ki = new KeyInfo ();
+                       if ((key.KeyInfo == null) || (key.KeyInfo.Count < 1))
+                               throw new ArgumentException ("no KeyInfo");
+                       ek = key;
                }
 
                public EncryptedKey (XmlElement element) : this ()
@@ -47,35 +54,183 @@ namespace Microsoft.Web.Services.Security {
                }
 
                public string EncryptionMethod {
-                       get { return null; }
+                       get { return keyex; }
                }
 
                public KeyInfo KeyInfo {
-                       get { return ki; }
+                       get { return ek.KeyInfo; }
                }
 
                public ReferenceList ReferenceList {
                        get { return list; }
                }
 
+               public string SessionAlgorithmURI { 
+                       get { return session; }
+                       set { 
+                               switch (value) {
+                                       case null:
+                                               throw new ArgumentNullException ("value");
+                                       case XmlEncryption.AlgorithmURI.AES128:
+                                       case XmlEncryption.AlgorithmURI.AES192:
+                                       case XmlEncryption.AlgorithmURI.AES256:
+                                       case XmlEncryption.AlgorithmURI.TripleDES:
+                                               if (session != value)
+                                                       key = null;
+                                               session = value;
+                                               break;
+                                       default:
+                                               throw new SecurityFault ("unsupported algorithm", null);
+                               }
+                       }
+               }
+
+               // note: no default key size is assumed because they could change in the future
+               private SymmetricAlgorithm GetSymmetricAlgorithm (string algorithmURI) 
+               {
+                       SymmetricAlgorithm sa = null;
+                       switch (algorithmURI) {
+                                       // Reference: http://www.w3.org/2001/04/xmlenc#aes128-cbc [REQUIRED]
+                               case XmlEncryption.AlgorithmURI.AES128:
+                                       sa = Rijndael.Create ();
+                                       sa.KeySize = 128;
+                                       break;
+                                       // Reference: http://www.w3.org/2001/04/xmlenc#aes192-cbc [OPTIONAL]
+                               case XmlEncryption.AlgorithmURI.AES192:
+                                       sa = Rijndael.Create ();
+                                       sa.KeySize = 192;
+                                       break;
+                                       // Reference: http://www.w3.org/2001/04/xmlenc#aes256-cbc [REQUIRED]
+                               case XmlEncryption.AlgorithmURI.AES256:
+                                       sa = Rijndael.Create ();
+                                       sa.KeySize = 256;
+                                       break;
+                                       // Reference: http://www.w3.org/2001/04/xmlenc#tripledes-cbc [REQUIRED]
+                               case XmlEncryption.AlgorithmURI.TripleDES:
+                                       sa = TripleDES.Create ();
+                                       sa.KeySize = 192;
+                                       break;
+                               default:
+                                       return null;
+                       }
+                       // for decryption we must use the decrypted key (from the keyexchange)
+                       if ((sa != null) && (decdata != null))
+                               sa.Key = decdata;
+                       return sa;
+               }
+
+               internal SymmetricEncryptionKey Key {
+                       get {
+                               if (key == null) {
+                                       key = new SymmetricEncryptionKey (GetSymmetricAlgorithm (session));
+                               }
+                               return key;
+                       }
+               }
+
+               [MonoTODO("incomplete")]
                public XmlElement GetXml (XmlDocument document) 
                {
                        if (document == null)
                                throw new ArgumentNullException ("document");
-                       return ki.GetXml ();
+
+                       XmlAttribute ema = document.CreateAttribute (XmlEncryption.AttributeNames.Algorithm);
+                       ema.InnerText = keyex;
+                       XmlElement em = document.CreateElement (XmlEncryption.Prefix, XmlEncryption.ElementNames.EncryptionMethod, XmlEncryption.NamespaceURI);
+                       em.Attributes.Append (ema);
+
+                       XmlElement ki = KeyInfo.GetXml ();
+
+                       AsymmetricKeyExchangeFormatter fmt = null;
+                       AsymmetricEncryptionKey aek = (ek as AsymmetricEncryptionKey);
+                       switch (keyex) {
+                               case XmlEncryption.AlgorithmURI.RSA15:
+                                       fmt = new RSAPKCS1KeyExchangeFormatter (aek.Algorithm);
+                                       break;
+                               case XmlEncryption.AlgorithmURI.RSAOAEP:
+                                       fmt = new RSAOAEPKeyExchangeFormatter (aek.Algorithm);
+                                       // TODO: parameters
+                                       break;
+                               default:
+                                       throw new SecurityFault ("unknown key exchange algorithm", null);
+                       }
+                       byte[] enckey = fmt.CreateKeyExchange (Key.Algorithm.Key);
+
+                       XmlElement cv = document.CreateElement (XmlEncryption.Prefix, XmlEncryption.ElementNames.CipherValue, XmlEncryption.NamespaceURI);
+                       cv.InnerText = Convert.ToBase64String (enckey);
+                       XmlElement cd = document.CreateElement (XmlEncryption.Prefix, XmlEncryption.ElementNames.CipherData, XmlEncryption.NamespaceURI);
+                       cd.AppendChild (cv);
+
+                       XmlElement rl = list.GetXml (document);
+
+                       XmlAttribute ekt = document.CreateAttribute (XmlEncryption.AttributeNames.Type);
+                       ekt.InnerText = XmlEncryption.TypeURI.EncryptedKey;
+                       XmlElement result = document.CreateElement (XmlEncryption.Prefix, XmlEncryption.ElementNames.EncryptedKey, XmlEncryption.NamespaceURI);
+                       result.Attributes.Append (ekt);
+                       result.AppendChild (em);
+                       result.AppendChild (document.ImportNode (ki, true));
+                       result.AppendChild (cd);
+                       result.AppendChild (rl);
+                       return result;
                }
 
+               [MonoTODO("incomplete")]
                public void LoadXml (XmlElement element) 
                {
-                       if ((element.LocalName != "") || (element.NamespaceURI != ""))
+                       if (element == null)
+                               throw new ArgumentNullException ("element");
+                       if ((element.LocalName != XmlEncryption.ElementNames.EncryptedKey) || (element.NamespaceURI != XmlEncryption.NamespaceURI))
                                throw new System.ArgumentException ("invalid LocalName or NamespaceURI");
-                       ki = new KeyInfo ();
-                       try {
-                               ki.LoadXml (element);
+
+                       XmlNodeList xnl = element.GetElementsByTagName (XmlEncryption.ElementNames.EncryptionMethod, XmlEncryption.NamespaceURI);
+                       if ((xnl != null) && (xnl.Count > 0)) {
+                               XmlAttribute ema = xnl [0].Attributes [XmlEncryption.AttributeNames.Algorithm];
+                               if (ema != null)
+                                       keyex = ema.InnerText;
                        }
-                       catch {
-                               throw new ArgumentException ("element has no KeyInfo");
+
+                       xnl = element.GetElementsByTagName (XmlSignature.ElementNames.KeyInfo, XmlSignature.NamespaceURI);
+                       if ((xnl != null) && (xnl.Count > 0)) {
+                               KeyInfo ki = new KeyInfo ();
+                               ki.LoadXml ((XmlElement) xnl [0]);
+#if WSE1
+                               DecryptionKeyProvider dkp = new DecryptionKeyProvider ();
+                               dk = dkp.GetDecryptionKey (keyex, ki);
+#else
+                               // TODO
+#endif
+                       }
+
+                       byte[] encdata = null;
+                       xnl = element.GetElementsByTagName (XmlEncryption.ElementNames.CipherData, XmlEncryption.NamespaceURI);
+                       if ((xnl != null) && (xnl.Count > 0)) {
+                               XmlElement cd = (XmlElement) xnl [0];
+                               foreach (XmlNode xn in cd.ChildNodes) {
+                                       if ((xn.LocalName == XmlEncryption.ElementNames.CipherValue) && (xn.NamespaceURI == XmlEncryption.NamespaceURI)) {
+                                               encdata = Convert.FromBase64String (xn.InnerText);
+                                       }
+                               }
+                       }
+
+                       xnl = element.GetElementsByTagName (XmlEncryption.ElementNames.ReferenceList, XmlEncryption.NamespaceURI);
+                       if ((xnl != null) && (xnl.Count > 0)) {
+                               list.LoadXml ((XmlElement) xnl [0]);
+                       }
+
+                       AsymmetricDecryptionKey adk = (dk as AsymmetricDecryptionKey);
+                       if ((adk != null) && (encdata != null)) {
+                               AsymmetricKeyExchangeDeformatter def = null;
+                               switch (keyex) {
+                                       case XmlEncryption.AlgorithmURI.RSA15:
+                                               def = new RSAPKCS1KeyExchangeDeformatter (adk.Algorithm);
+                                               decdata = def.DecryptKeyExchange (encdata);
+                                               break;
+                                       case XmlEncryption.AlgorithmURI.RSAOAEP:
+                                               // TODO
+                                               break;
+                               }
                        }
+                       // TODO
                }
        }
 }