In corlib/System.Runtime.InteropServices:
[mono.git] / mcs / class / corlib / System.Security.Cryptography.X509Certificates / X509Certificate20.cs
1 //
2 // X509Certificate20.cs: Partial class to handle new 2.0-only stuff
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-2006 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.Runtime.InteropServices;
33 using System.Security.Permissions;
34 using System.Text;
35
36 using Mono.Security;
37 using Mono.Security.X509;
38
39 using System.Runtime.Serialization;
40
41 namespace System.Security.Cryptography.X509Certificates {
42
43         [ComVisible (true)]
44         [MonoTODO ("X509ContentType.SerializedCert isn't supported (anywhere in the class)")]
45         public partial class X509Certificate : IDeserializationCallback, ISerializable {
46
47                 private string issuer_name;
48                 private string subject_name;
49
50
51                 public X509Certificate ()
52                 {
53                         // this allows an empty certificate to exists
54                 }
55
56                 public X509Certificate (byte[] rawData, string password)
57                 {
58                         Import (rawData, password, X509KeyStorageFlags.DefaultKeySet);
59                 }
60
61                 [MonoTODO ("SecureString support is incomplete")]
62                 public X509Certificate (byte[] rawData, SecureString password)
63                 {
64                         Import (rawData, password, X509KeyStorageFlags.DefaultKeySet);
65                 }
66
67                 public X509Certificate (byte[] rawData, string password, X509KeyStorageFlags keyStorageFlags)
68                 {
69                         Import (rawData, password, keyStorageFlags);
70                 }
71
72                 [MonoTODO ("SecureString support is incomplete")]
73                 public X509Certificate (byte[] rawData, SecureString password, X509KeyStorageFlags keyStorageFlags)
74                 {
75                         Import (rawData, password, keyStorageFlags);
76                 }
77
78                 public X509Certificate (string fileName)
79                 {
80                         Import (fileName, (string)null, X509KeyStorageFlags.DefaultKeySet);
81                 }
82
83                 public X509Certificate (string fileName, string password)
84                 {
85                         Import (fileName, password, X509KeyStorageFlags.DefaultKeySet);
86                 }
87
88                 [MonoTODO ("SecureString support is incomplete")]
89                 public X509Certificate (string fileName, SecureString password)
90                 {
91                         Import (fileName, password, X509KeyStorageFlags.DefaultKeySet);
92                 }
93
94                 public X509Certificate (string fileName, string password, X509KeyStorageFlags keyStorageFlags)
95                 {
96                         Import (fileName, password, keyStorageFlags);
97                 }
98
99                 [MonoTODO ("SecureString support is incomplete")]
100                 public X509Certificate (string fileName, SecureString password, X509KeyStorageFlags keyStorageFlags)
101                 {
102                         Import (fileName, password, keyStorageFlags);
103                 }
104
105                 public X509Certificate (SerializationInfo info, StreamingContext context)
106                 {
107                         byte[] raw = (byte[]) info.GetValue ("RawData", typeof (byte[]));
108                         Import (raw, (string)null, X509KeyStorageFlags.DefaultKeySet);
109                 }
110
111
112                 public string Issuer {
113                         get {
114                                 if (x509 == null)
115                                         throw new CryptographicException (Locale.GetText ("Certificate instance is empty."));
116
117                                 if (issuer_name == null)
118                                         issuer_name = X501.ToString (x509.GetIssuerName (), true, ", ", true);
119                                 return issuer_name;
120                         }
121                 }
122
123                 public string Subject {
124                         get {
125                                 if (x509 == null)
126                                         throw new CryptographicException (Locale.GetText ("Certificate instance is empty."));
127
128                                 if (subject_name == null)
129                                         subject_name = X501.ToString (x509.GetSubjectName (), true, ", ", true);
130                                 return subject_name;
131                         }
132                 }
133
134                 [ComVisible (false)]
135                 public IntPtr Handle {
136                         get { return IntPtr.Zero; }
137                 }
138
139
140                 [ComVisible (false)]
141                 public override bool Equals (object obj) 
142                 {
143                         X509Certificate x = (obj as X509Certificate);
144                         if (x != null)
145                                 return this.Equals (x);
146                         return false;
147                 }
148
149                 [MonoTODO ("X509ContentType.Pfx/Pkcs12 and SerializedCert are not supported")]
150                 [ComVisible (false)]
151                 public virtual byte[] Export (X509ContentType contentType)
152                 {
153                         return Export (contentType, (byte[])null);
154                 }
155
156                 [MonoTODO ("X509ContentType.Pfx/Pkcs12 and SerializedCert are not supported")]
157                 [ComVisible (false)]
158                 public virtual byte[] Export (X509ContentType contentType, string password)
159                 {
160                         byte[] pwd = (password == null) ? null : Encoding.UTF8.GetBytes (password);
161                         return Export (contentType, pwd);
162                 }
163
164                 [MonoTODO ("X509ContentType.Pfx/Pkcs12 and SerializedCert are not supported. SecureString support is incomplete.")]
165                 public virtual byte[] Export (X509ContentType contentType, SecureString password)
166                 {
167                         byte[] pwd = (password == null) ? null : password.GetBuffer ();
168                         return Export (contentType, pwd);
169                 }
170
171                 internal byte[] Export (X509ContentType contentType, byte[] password)
172                 {
173                         if (x509 == null)
174                                 throw new CryptographicException (Locale.GetText ("Certificate instance is empty."));
175
176                         try {
177                                 switch (contentType) {
178                                 case X509ContentType.Cert:
179                                         return x509.RawData;
180                                 case X509ContentType.Pfx: // this includes Pkcs12
181                                         // TODO
182                                         throw new NotSupportedException ();
183                                 case X509ContentType.SerializedCert:
184                                         // TODO
185                                         throw new NotSupportedException ();
186                                 default:
187                                         string msg = Locale.GetText ("This certificate format '{0}' cannot be exported.", contentType);
188                                         throw new CryptographicException (msg);
189                                 }
190                         }
191                         finally {
192                                 // protect password
193                                 if (password != null)
194                                         Array.Clear (password, 0, password.Length);
195                         }
196                 }
197
198                 void IDeserializationCallback.OnDeserialization (object sender)
199                 {
200                 }
201
202                 [ComVisible (false)]
203                 public virtual void Import (byte[] rawData)
204                 {
205                         Import (rawData, (string)null, X509KeyStorageFlags.DefaultKeySet);
206                 }
207
208                 [MonoTODO ("missing KeyStorageFlags support")]
209                 [ComVisible (false)]
210                 public virtual void Import (byte[] rawData, string password, X509KeyStorageFlags keyStorageFlags)
211                 {
212                         Reset ();
213                         if (password == null) {
214                                 try {
215                                         x509 = new Mono.Security.X509.X509Certificate (rawData);
216                                 }
217                                 catch (Exception e) {
218                                         try {
219                                                 PKCS12 pfx = new PKCS12 (rawData);
220                                                 if (pfx.Certificates.Count > 0)
221                                                         x509 = pfx.Certificates [0];
222                                                 else
223                                                         x509 = null;
224                                         }
225                                         catch {
226                                                 string msg = Locale.GetText ("Unable to decode certificate.");
227                                                 // inner exception is the original (not second) exception
228                                                 throw new CryptographicException (msg, e);
229                                         }
230                                 }
231                         } else {
232                                 // try PKCS#12
233                                 try {
234                                         PKCS12 pfx = new PKCS12 (rawData, password);
235                                         if (pfx.Certificates.Count > 0) {
236                                                 x509 = pfx.Certificates [0];
237                                         } else {
238                                                 x509 = null;
239                                         }
240                                 }
241                                 catch {
242                                         // it's possible to supply a (unrequired/unusued) password
243                                         // fix bug #79028
244                                         x509 = new Mono.Security.X509.X509Certificate (rawData);
245                                 }
246                         }
247                 }
248
249                 [MonoTODO ("SecureString support is incomplete")]
250                 public virtual void Import (byte[] rawData, SecureString password, X509KeyStorageFlags keyStorageFlags)
251                 {
252                         Import (rawData, (string)null, keyStorageFlags);
253                 }
254
255                 [ComVisible (false)]
256                 public virtual void Import (string fileName)
257                 {
258                         byte[] rawData = Load (fileName);
259                         Import (rawData, (string)null, X509KeyStorageFlags.DefaultKeySet);
260                 }
261
262                 [MonoTODO ("missing KeyStorageFlags support")]
263                 [ComVisible (false)]
264                 public virtual void Import (string fileName, string password, X509KeyStorageFlags keyStorageFlags)
265                 {
266                         byte[] rawData = Load (fileName);
267                         Import (rawData, password, keyStorageFlags);
268                 }
269
270                 [MonoTODO ("SecureString support is incomplete, missing KeyStorageFlags support")]
271                 public virtual void Import (string fileName, SecureString password, X509KeyStorageFlags keyStorageFlags)
272                 {
273                         byte[] rawData = Load (fileName);
274                         Import (rawData, (string)null, keyStorageFlags);
275                 }
276
277                 void ISerializable.GetObjectData (SerializationInfo info, StreamingContext context)
278                 {
279                         // will throw a NRE if info is null (just like MS implementation)
280                         info.AddValue ("RawData", x509.RawData);
281                 }
282
283                 [ComVisible (false)]
284                 public virtual void Reset ()
285                 {
286                         x509 = null;
287                         issuer_name = null;
288                         subject_name = null;
289                         hideDates = false;
290                         cachedCertificateHash = null;
291                 }
292         }
293 }
294
295 #endif