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