Merge remote-tracking branch 'upstream/master'
[mono.git] / mcs / class / System / System.Security.Cryptography / AsnEncodedData.cs
1 //
2 // AsnEncodedData.cs - System.Security.Cryptography.AsnEncodedData
3 //
4 // Author:
5 //      Sebastien Pouliot  <sebastien@ximian.com>
6 //
7 // (C) 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 #if SECURITY_DEP
31
32 extern alias MonoSecurity;
33
34 using System.Security.Cryptography.X509Certificates;
35 using System.Text;
36
37 using MonoSecurity::Mono.Security;
38 using MonoSecurity::Mono.Security.Cryptography;
39
40 namespace System.Security.Cryptography {
41
42         internal enum AsnDecodeStatus {
43                 NotDecoded = -1,
44                 Ok = 0,
45                 BadAsn = 1,
46                 BadTag = 2,
47                 BadLength = 3,
48                 InformationNotAvailable = 4
49         }
50
51         public class AsnEncodedData {
52
53                 internal Oid _oid;
54                 internal byte[] _raw;
55
56                 // constructors
57
58                 protected AsnEncodedData ()
59                 {
60                 }
61         
62                 public AsnEncodedData (string oid, byte[] rawData)
63                 {
64                         _oid = new Oid (oid);
65                         RawData = rawData;
66                 }
67
68                 public AsnEncodedData (Oid oid, byte[] rawData)
69                 {
70                         Oid = oid;
71                         RawData = rawData;
72
73                         // yes, here oid == null is legal (by design), 
74                         // but no, it would not be legal for an oid string
75                         // see MSDN FDBK11479
76                 }
77
78                 public AsnEncodedData (AsnEncodedData asnEncodedData)
79                 {
80                         if (asnEncodedData == null)
81                                 throw new ArgumentNullException ("asnEncodedData");
82
83                         if (asnEncodedData._oid != null)
84                                 Oid = new Oid (asnEncodedData._oid);
85                         RawData = asnEncodedData._raw;
86                 }
87
88                 public AsnEncodedData (byte[] rawData)
89                 {
90                         RawData = rawData;
91                 }
92
93                 // properties
94
95                 public Oid Oid {
96                         get { return _oid; }
97                         set {
98                                 if (value == null)
99                                         _oid = null;
100                                 else
101                                         _oid = new Oid (value);
102                         }
103                 }
104
105                 public byte[] RawData { 
106                         get { return _raw; }
107                         set {
108                                 if (value == null)
109                                         throw new ArgumentNullException ("RawData");
110                                 _raw = (byte[])value.Clone ();
111                         }
112                 }
113
114                 // methods
115
116                 public virtual void CopyFrom (AsnEncodedData asnEncodedData)
117                 {
118                         if (asnEncodedData == null)
119                                 throw new ArgumentNullException ("asnEncodedData");
120
121                         if (asnEncodedData._oid == null)
122                                 Oid = null;
123                         else
124                                 Oid = new Oid (asnEncodedData._oid);
125
126                         RawData = asnEncodedData._raw;
127                 }
128
129                 public virtual string Format (bool multiLine) 
130                 {
131                         if (_raw == null)
132                                 return String.Empty;
133
134                         if (_oid == null)
135                                 return Default (multiLine);
136
137                         return ToString (multiLine);
138                 }
139
140                 // internal decoding/formatting methods
141
142                 internal virtual string ToString (bool multiLine)
143                 {
144                         switch (_oid.Value) {
145                         // fx supported objects
146                         case X509BasicConstraintsExtension.oid:
147                                 return BasicConstraintsExtension (multiLine);
148                         case X509EnhancedKeyUsageExtension.oid:
149                                 return EnhancedKeyUsageExtension (multiLine);
150                         case X509KeyUsageExtension.oid:
151                                 return KeyUsageExtension (multiLine);
152                         case X509SubjectKeyIdentifierExtension.oid:
153                                 return SubjectKeyIdentifierExtension (multiLine);
154                         // other known objects (i.e. supported structure) - 
155                         // but without any corresponding framework class
156                         case Oid.oidSubjectAltName:
157                                 return SubjectAltName (multiLine);
158                         case Oid.oidNetscapeCertType:
159                                 return NetscapeCertType (multiLine);
160                         default:
161                                 return Default (multiLine);
162                         }
163                 }
164
165                 internal string Default (bool multiLine)
166                 {
167                         StringBuilder sb = new StringBuilder ();
168                         for (int i=0; i < _raw.Length; i++) {
169                                 sb.Append (_raw [i].ToString ("x2"));
170                                 if (i != _raw.Length - 1)
171                                         sb.Append (" ");
172                         }
173                         return sb.ToString ();
174                 }
175
176                 // Indirectly (undocumented but) supported extensions
177
178                 internal string BasicConstraintsExtension (bool multiLine)
179                 {
180                         try {
181                                 X509BasicConstraintsExtension bc = new X509BasicConstraintsExtension  (this, false);
182                                 return bc.ToString (multiLine);
183                         }
184                         catch {
185                                 return String.Empty;
186                         }
187                 }
188
189                 internal string EnhancedKeyUsageExtension (bool multiLine)
190                 {
191                         try {
192                                 X509EnhancedKeyUsageExtension eku = new X509EnhancedKeyUsageExtension  (this, false);
193                                 return eku.ToString (multiLine);
194                         }
195                         catch {
196                                 return String.Empty;
197                         }
198                 }
199
200                 internal string KeyUsageExtension (bool multiLine)
201                 {
202                         try {
203                                 X509KeyUsageExtension ku = new X509KeyUsageExtension  (this, false);
204                                 return ku.ToString (multiLine);
205                         }
206                         catch {
207                                 return String.Empty;
208                         }
209                 }
210
211                 internal string SubjectKeyIdentifierExtension (bool multiLine)
212                 {
213                         try {
214                                 X509SubjectKeyIdentifierExtension ski = new X509SubjectKeyIdentifierExtension  (this, false);
215                                 return ski.ToString (multiLine);
216                         }
217                         catch {
218                                 return String.Empty;
219                         }
220                 }
221
222                 // Indirectly (undocumented but) supported extensions
223
224                 internal string SubjectAltName (bool multiLine)
225                 {
226                         if (_raw.Length < 5)
227                                 return "Information Not Available";
228
229                         try {
230                                 ASN1 ex = new ASN1 (_raw);
231                                 StringBuilder sb = new StringBuilder ();
232                                 for (int i=0; i < ex.Count; i++) {
233                                         ASN1 el = ex [i];
234
235                                         string type = null;
236                                         string name = null;
237
238                                         switch (el.Tag) {
239                                         case 0x81:
240                                                 type = "RFC822 Name=";
241                                                 name = Encoding.ASCII.GetString (el.Value);
242                                                 break;
243                                         case 0x82:
244                                                 type = "DNS Name=";
245                                                 name = Encoding.ASCII.GetString (el.Value);
246                                                 break;
247                                         default:
248                                                 type = String.Format ("Unknown ({0})=", el.Tag);
249                                                 name = CryptoConvert.ToHex (el.Value);
250                                                 break;
251                                         }
252
253                                         sb.Append (type);
254                                         sb.Append (name);
255                                         if (multiLine) {
256                                                 sb.Append (Environment.NewLine);
257                                         } else if (i < ex.Count - 1) {
258                                                 sb.Append (", ");
259                                         }
260                                 }
261                                 return sb.ToString ();
262                         }
263                         catch {
264                                 return String.Empty;
265                         }
266                 }
267
268                 internal string NetscapeCertType (bool multiLine)
269                 {
270                         // 4 byte long, BITSTRING (0x03), Value length of 2
271                         if ((_raw.Length < 4) || (_raw [0] != 0x03) || (_raw [1] != 0x02))
272                                 return "Information Not Available";
273                         // first value byte is the number of unused bits
274                         int value = (_raw [3] >> _raw [2]) << _raw [2];
275
276                         StringBuilder sb = new StringBuilder ();
277
278                         if ((value & 0x80) == 0x80) {
279                                 sb.Append ("SSL Client Authentication");
280                         }
281                         if ((value & 0x40) == 0x40) {
282                                 if (sb.Length > 0)
283                                         sb.Append (", ");
284                                 sb.Append ("SSL Server Authentication");
285                         }
286                         if ((value & 0x20) == 0x20) {
287                                 if (sb.Length > 0)
288                                         sb.Append (", ");
289                                 sb.Append ("SMIME");
290                         }
291                         if ((value & 0x10) == 0x10) {
292                                 if (sb.Length > 0)
293                                         sb.Append (", ");
294                                 sb.Append ("Signature"); // a.k.a. Object Signing / Code Signing
295                         }
296                         if ((value & 0x08) == 0x08) {
297                                 if (sb.Length > 0)
298                                         sb.Append (", ");
299                                 sb.Append ("Unknown cert type");
300                         }
301                         if ((value & 0x04) == 0x04) {
302                                 if (sb.Length > 0)
303                                         sb.Append (", ");
304                                 sb.Append ("SSL CA");   // CA == Certificate Authority
305                         }
306                         if ((value & 0x02) == 0x02) {
307                                 if (sb.Length > 0)
308                                         sb.Append (", ");
309                                 sb.Append ("SMIME CA");
310                         }
311                         if ((value & 0x01) == 0x01) {
312                                 if (sb.Length > 0)
313                                         sb.Append (", ");
314                                 sb.Append ("Signature CA");
315                         }
316                         sb.AppendFormat (" ({0})", value.ToString ("x2"));
317                         return sb.ToString ();
318                 }
319         }
320 }
321
322 #endif