[runtime] Remove handler block trampoline code
[mono.git] / mcs / class / System.Security / System.Security.Cryptography.Xml / Reference.cs
1 //
2 // Reference.cs - Reference implementation for XML Signature
3 //
4 // Author:
5 //      Sebastien Pouliot <sebastien@ximian.com>
6 //
7 // (C) 2002, 2003 Motus Technologies Inc. (http://www.motus.com)
8 // Copyright (C) 2004-2005 Novell, Inc (http://www.novell.com)
9 //
10 // Permission is hereby granted, free of charge, to any person obtaining
11 // a copy of this software and associated documentation files (the
12 // "Software"), to deal in the Software without restriction, including
13 // without limitation the rights to use, copy, modify, merge, publish,
14 // distribute, sublicense, and/or sell copies of the Software, and to
15 // permit persons to whom the Software is furnished to do so, subject to
16 // the following conditions:
17 // 
18 // The above copyright notice and this permission notice shall be
19 // included in all copies or substantial portions of the Software.
20 // 
21 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
25 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 //
29
30 using System.IO;
31 using System.Runtime.InteropServices;
32 using System.Xml;
33
34 namespace System.Security.Cryptography.Xml { 
35
36         // http://www.w3.org/TR/2002/REC-xmldsig-core-20020212/Overview.html#sec-Reference
37         public class Reference {
38
39                 private TransformChain chain;
40                 private string digestMethod;
41                 private byte[] digestValue;
42                 private string id;
43                 private string uri;
44                 private string type;
45                 private Stream stream;
46                 private XmlElement element;
47
48                 public Reference () 
49                 {
50                         chain = new TransformChain ();
51                         digestMethod = XmlSignature.NamespaceURI + "sha1";
52                 }
53
54                 [MonoTODO ("There is no description about how it is used.")]
55                 public Reference (Stream stream) : this () 
56                 {
57                         this.stream = stream;
58                 }
59
60                 public Reference (string uri) : this ()
61                 {
62                         this.uri = uri;
63                 }
64
65                 // default to SHA1
66                 public string DigestMethod {
67                         get { return digestMethod; }
68                         set {
69                                 element = null;
70                                 digestMethod = value;
71                         }
72                 }
73
74                 public byte[] DigestValue {
75                         get { return digestValue; }
76                         set {
77                                 element = null;
78                                 digestValue = value;
79                         }
80                 }
81
82                 public string Id {
83                         get { return id; }
84                         set {
85                                 element = null;
86                                 id = value;
87                         }
88                 }
89
90                 public TransformChain TransformChain {
91                         get { return chain; }
92                         [ComVisible (false)]
93                         set { chain = value; }
94                 }
95
96                 public string Type {
97                         get { return type; }
98                         set {
99                                 element = null;
100                                 type = value;
101                         }
102                 }
103
104                 public string Uri {
105                         get { return uri; }
106                         set {
107                                 element = null;
108                                 uri = value;
109                         }
110                 }
111
112                 public void AddTransform (Transform transform) 
113                 {
114                         chain.Add (transform);
115                 }
116
117                 public XmlElement GetXml () 
118                 {
119                         if (element != null)
120                                 return element;
121
122                         if (digestMethod == null)
123                                 throw new CryptographicException ("DigestMethod");
124                         if (digestValue == null)
125                                 throw new NullReferenceException ("DigestValue");
126
127                         XmlDocument document = new XmlDocument ();
128                         XmlElement xel = document.CreateElement (XmlSignature.ElementNames.Reference, XmlSignature.NamespaceURI);
129                         if (id != null)
130                                 xel.SetAttribute (XmlSignature.AttributeNames.Id, id);
131                         if (uri != null)
132                                 xel.SetAttribute (XmlSignature.AttributeNames.URI, uri);
133                         if (type != null)
134                                 xel.SetAttribute (XmlSignature.AttributeNames.Type, type);
135
136                         if (chain.Count > 0) {
137                                 XmlElement ts = document.CreateElement (XmlSignature.ElementNames.Transforms, XmlSignature.NamespaceURI);
138                                 foreach (Transform t in chain) {
139                                         XmlNode xn = t.GetXml ();
140                                         XmlNode newNode = document.ImportNode (xn, true);
141                                         ts.AppendChild (newNode);
142                                 }
143                                 xel.AppendChild (ts);
144                         }
145
146                         XmlElement dm = document.CreateElement (XmlSignature.ElementNames.DigestMethod, XmlSignature.NamespaceURI);
147                         dm.SetAttribute (XmlSignature.AttributeNames.Algorithm, digestMethod);
148                         xel.AppendChild (dm);
149
150                         XmlElement dv = document.CreateElement (XmlSignature.ElementNames.DigestValue, XmlSignature.NamespaceURI);
151                         dv.InnerText = Convert.ToBase64String (digestValue);
152                         xel.AppendChild (dv);
153
154                         return xel;
155                 }
156
157                 // note: we do NOT return null -on purpose- if attribute isn't found
158                 private string GetAttribute (XmlElement xel, string attribute) 
159                 {
160                         XmlAttribute xa = xel.Attributes [attribute];
161                         return ((xa != null) ? xa.InnerText : null);
162                 }
163
164                 public void LoadXml (XmlElement value) 
165                 {
166                         if (value == null)
167                                 throw new ArgumentNullException ("value");
168
169                         if ((value.LocalName != XmlSignature.ElementNames.Reference) || (value.NamespaceURI != XmlSignature.NamespaceURI))
170                                 throw new CryptographicException ();
171
172                         id = GetAttribute (value, XmlSignature.AttributeNames.Id);
173                         uri = GetAttribute (value, XmlSignature.AttributeNames.URI);
174                         type = GetAttribute (value, XmlSignature.AttributeNames.Type);
175                         // Note: order is important for validations
176                         XmlNodeList xnl = value.GetElementsByTagName (XmlSignature.ElementNames.Transform, XmlSignature.NamespaceURI);
177                         if ((xnl != null) && (xnl.Count > 0)) {
178                                 Transform t = null;
179                                 foreach (XmlNode xn in xnl) {
180                                         string a = GetAttribute ((XmlElement)xn, XmlSignature.AttributeNames.Algorithm);
181 /*      This code is useful for debugging in VS.NET because using CryptoConfig
182         (from MS mscorlib) would throw InvalidCastException because it's 
183         Transform would come from MS System.Security.dll not Mono's.
184                                         switch (a) {
185                                                 case "http://www.w3.org/2000/09/xmldsig#base64":
186                                                         t = new XmlDsigBase64Transform ();
187                                                         break;
188                                                 case "http://www.w3.org/TR/2001/REC-xml-c14n-20010315":
189                                                         t = new XmlDsigC14NTransform ();
190                                                         break;
191                                                 case "http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments":
192                                                         t = new XmlDsigC14NWithCommentsTransform ();
193                                                         break;
194                                                 case "http://www.w3.org/2000/09/xmldsig#enveloped-signature":
195                                                         t = new XmlDsigEnvelopedSignatureTransform ();
196                                                         break;
197                                                 case "http://www.w3.org/TR/1999/REC-xpath-19991116":
198                                                         t = new XmlDsigXPathTransform ();
199                                                         break;
200                                                 case "http://www.w3.org/TR/1999/REC-xslt-19991116":
201                                                         t = new XmlDsigXsltTransform ();
202                                                         break;
203                                                 case "http://www.w3.org/2002/07/decrypt#XML":
204                                                         t = new XmlDecryptionTransform ();
205                                                         break;
206                                                 default:
207                                                         throw new NotSupportedException ();
208                                         }
209 */
210                                         t = (Transform) CryptoConfig.CreateFromName (a);
211                                         if (t == null)
212                                                 throw new CryptographicException ("Unknown transform {0}.", a);
213
214                                         if (xn.ChildNodes.Count > 0) {
215                                                 t.LoadInnerXml (xn.ChildNodes);
216                                         }
217                                         AddTransform (t);
218                                 }
219                         }
220                         // get DigestMethod
221                         DigestMethod = XmlSignature.GetAttributeFromElement (value, XmlSignature.AttributeNames.Algorithm, XmlSignature.ElementNames.DigestMethod);
222                         // get DigestValue
223                         XmlElement dig = XmlSignature.GetChildElement (value, XmlSignature.ElementNames.DigestValue, XmlSignature.NamespaceURI);
224                         if (dig != null)
225                                 DigestValue = Convert.FromBase64String (dig.InnerText);
226                         element = value;
227                 }
228         }
229 }