2005-01-31 Zoltan Varga <vargaz@freemail.hu>
[mono.git] / mcs / class / System.Security / 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 NET_2_0
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                         Oid = new Oid (asnEncodedData._oid);
82                         RawData = asnEncodedData._raw;
83                 }
84
85                 public AsnEncodedData (byte[] rawData)
86                 {
87                         RawData = rawData;
88                 }
89
90                 // properties
91
92                 public Oid Oid {
93                         get { return _oid; }
94                         set {
95                                 if (value == null)
96                                         _oid = null;
97                                 else
98                                         _oid = new Oid (value);
99                         }
100                 }
101
102                 public byte[] RawData { 
103                         get { return _raw; }
104                         set {
105                                 if (value == null)
106                                         throw new ArgumentNullException ("RawData");
107                                 _raw = (byte[])value.Clone ();
108                         }
109                 }
110
111                 // methods
112
113                 public virtual void CopyFrom (AsnEncodedData asnEncodedData)
114                 {
115                         if (asnEncodedData == null)
116                                 throw new ArgumentNullException ("asnEncodedData");
117
118                         Oid = new Oid (asnEncodedData._oid);
119                         RawData = asnEncodedData._raw;
120                 }
121
122                 public virtual string Format (bool multiLine) 
123                 {
124                         if (_raw == null)
125                                 return String.Empty;
126
127                         if (_oid == null)
128                                 return Default (multiLine);
129
130                         return ToString (multiLine);
131                 }
132
133                 // internal decoding/formatting methods
134
135                 internal virtual string ToString (bool multiLine)
136                 {
137                         switch (_oid.Value) {
138                         // fx supported objects
139                         case X509BasicConstraintsExtension.oid:
140                                 return BasicConstraintsExtension (multiLine);
141                         case X509EnhancedKeyUsageExtension.oid:
142                                 return EnhancedKeyUsageExtension (multiLine);
143                         case X509KeyUsageExtension.oid:
144                                 return KeyUsageExtension (multiLine);
145                         case X509SubjectKeyIdentifierExtension.oid:
146                                 return SubjectKeyIdentifierExtension (multiLine);
147                         // other known objects (i.e. supported structure) - 
148                         // but without any corresponding framework class
149                         case Oid.oidSubjectAltName:
150                                 return SubjectAltName (multiLine);
151                         case Oid.oidNetscapeCertType:
152                                 return NetscapeCertType (multiLine);
153                         default:
154                                 return Default (multiLine);
155                         }
156                 }
157
158                 internal string Default (bool multiLine)
159                 {
160                         StringBuilder sb = new StringBuilder ();
161                         for (int i=0; i < _raw.Length; i++) {
162                                 sb.Append (_raw [i].ToString ("x2"));
163                                 if (i != _raw.Length - 1)
164                                         sb.Append (" ");
165                         }
166                         return sb.ToString ();
167                 }
168
169                 // Indirectly (undocumented but) supported extensions
170
171                 internal string BasicConstraintsExtension (bool multiLine)
172                 {
173                         try {
174                                 X509BasicConstraintsExtension bc = new X509BasicConstraintsExtension  (this, false);
175                                 return bc.ToString (multiLine);
176                         }
177                         catch {
178                                 return String.Empty;
179                         }
180                 }
181
182                 internal string EnhancedKeyUsageExtension (bool multiLine)
183                 {
184                         try {
185                                 X509EnhancedKeyUsageExtension eku = new X509EnhancedKeyUsageExtension  (this, false);
186                                 return eku.ToString (multiLine);
187                         }
188                         catch {
189                                 return String.Empty;
190                         }
191                 }
192
193                 internal string KeyUsageExtension (bool multiLine)
194                 {
195                         try {
196                                 X509KeyUsageExtension ku = new X509KeyUsageExtension  (this, false);
197                                 return ku.ToString (multiLine);
198                         }
199                         catch {
200                                 return String.Empty;
201                         }
202                 }
203
204                 internal string SubjectKeyIdentifierExtension (bool multiLine)
205                 {
206                         try {
207                                 X509SubjectKeyIdentifierExtension ski = new X509SubjectKeyIdentifierExtension  (this, false);
208                                 return ski.ToString (multiLine);
209                         }
210                         catch {
211                                 return String.Empty;
212                         }
213                 }
214
215                 // Indirectly (undocumented but) supported extensions
216
217                 internal string SubjectAltName (bool multiLine)
218                 {
219                         if (_raw.Length < 5)
220                                 return "Information Not Available";
221
222                         try {
223                                 ASN1 ex = new ASN1 (_raw);
224                                 StringBuilder sb = new StringBuilder ();
225                                 for (int i=0; i < ex.Count; i++) {
226                                         ASN1 el = ex [i];
227
228                                         string type = null;
229                                         string name = null;
230
231                                         switch (el.Tag) {
232                                         case 0x81:
233                                                 type = "RFC822 Name=";
234                                                 name = Encoding.ASCII.GetString (el.Value);
235                                                 break;
236                                         case 0x82:
237                                                 type = "DNS Name=";
238                                                 name = Encoding.ASCII.GetString (el.Value);
239                                                 break;
240                                         default:
241                                                 type = String.Format ("Unknown ({0})=", el.Tag);
242                                                 name = CryptoConvert.ToHex (el.Value);
243                                                 break;
244                                         }
245
246                                         sb.Append (type);
247                                         sb.Append (name);
248                                         if (multiLine) {
249                                                 sb.Append (Environment.NewLine);
250                                         } else if (i < ex.Count - 1) {
251                                                 sb.Append (", ");
252                                         }
253                                 }
254                                 return sb.ToString ();
255                         }
256                         catch {
257                                 return String.Empty;
258                         }
259                 }
260
261                 internal string NetscapeCertType (bool multiLine)
262                 {
263                         // 4 byte long, BITSTRING (0x03), Value length of 2
264                         if ((_raw.Length < 4) || (_raw [0] != 0x03) || (_raw [1] != 0x02))
265                                 return "Information Not Available";
266                         // first value byte is the number of unused bits
267                         int value = (_raw [3] >> _raw [2]) << _raw [2];
268
269                         StringBuilder sb = new StringBuilder ();
270
271                         bool first = false;
272                         if ((value & 0x80) == 0x80) {
273                                 sb.Append ("SSL Client Authentication");
274                         }
275                         if ((value & 0x40) == 0x40) {
276                                 if (sb.Length > 0)
277                                         sb.Append (", ");
278                                 sb.Append ("SSL Server Authentication");
279                         }
280                         if ((value & 0x20) == 0x20) {
281                                 if (sb.Length > 0)
282                                         sb.Append (", ");
283                                 sb.Append ("SMIME");
284                         }
285                         if ((value & 0x10) == 0x10) {
286                                 if (sb.Length > 0)
287                                         sb.Append (", ");
288                                 sb.Append ("Signature"); // a.k.a. Object Signing / Code Signing
289                         }
290                         if ((value & 0x08) == 0x08) {
291                                 if (sb.Length > 0)
292                                         sb.Append (", ");
293                                 sb.Append ("Unknown cert type");
294                         }
295                         if ((value & 0x04) == 0x04) {
296                                 if (sb.Length > 0)
297                                         sb.Append (", ");
298                                 sb.Append ("SSL CA");   // CA == Certificate Authority
299                         }
300                         if ((value & 0x02) == 0x02) {
301                                 if (sb.Length > 0)
302                                         sb.Append (", ");
303                                 sb.Append ("SMIME CA");
304                         }
305                         if ((value & 0x01) == 0x01) {
306                                 if (sb.Length > 0)
307                                         sb.Append (", ");
308                                 sb.Append ("Signature CA");
309                         }
310                         sb.AppendFormat (" ({0})", value.ToString ("x2"));
311                         return sb.ToString ();
312                 }
313         }
314 }
315
316 #endif