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