update readme (#21797)
[mono-project.git] / mcs / class / System / Mono.Btls / MonoBtlsX509.cs
blob109034c0c4979abec23cb747a6448b1d303d722d
1 //
2 // MonoBtlsX509.cs
3 //
4 // Author:
5 // Martin Baulig <martin.baulig@xamarin.com>
6 //
7 // Copyright (c) 2016 Xamarin Inc. (http://www.xamarin.com)
8 //
9 // Permission is hereby granted, free of charge, to any person obtaining a copy
10 // of this software and associated documentation files (the "Software"), to deal
11 // in the Software without restriction, including without limitation the rights
12 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 // copies of the Software, and to permit persons to whom the Software is
14 // furnished to do so, subject to the following conditions:
16 // The above copyright notice and this permission notice shall be included in
17 // all copies or substantial portions of the Software.
19 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 // THE SOFTWARE.
26 #if SECURITY_DEP && MONO_FEATURE_BTLS
27 using System;
28 using System.IO;
29 using System.Text;
30 using System.Threading;
31 using System.Runtime.CompilerServices;
32 using System.Runtime.InteropServices;
33 using System.Security.Cryptography.X509Certificates;
34 using System.Security.Cryptography;
36 namespace Mono.Btls
38 class MonoBtlsX509 : MonoBtlsObject
40 internal class BoringX509Handle : MonoBtlsHandle
42 public BoringX509Handle (IntPtr handle)
43 : base (handle, true)
47 protected override bool ReleaseHandle ()
49 if (handle != IntPtr.Zero)
50 mono_btls_x509_free (handle);
51 return true;
54 public IntPtr StealHandle ()
56 var retval = Interlocked.Exchange (ref handle, IntPtr.Zero);
57 return retval;
61 new internal BoringX509Handle Handle {
62 get { return (BoringX509Handle)base.Handle; }
65 internal MonoBtlsX509 (BoringX509Handle handle)
66 : base (handle)
70 [DllImport (BTLS_DYLIB)]
71 extern static IntPtr mono_btls_x509_up_ref (IntPtr handle);
73 [DllImport (BTLS_DYLIB)]
74 extern static IntPtr mono_btls_x509_from_data (IntPtr data, int len, MonoBtlsX509Format format);
76 [DllImport (BTLS_DYLIB)]
77 extern static IntPtr mono_btls_x509_get_subject_name (IntPtr handle);
79 [DllImport (BTLS_DYLIB)]
80 extern static IntPtr mono_btls_x509_get_issuer_name (IntPtr handle);
82 [DllImport (BTLS_DYLIB)]
83 extern static int mono_btls_x509_get_subject_name_string (IntPtr handle, IntPtr buffer, int size);
85 [DllImport (BTLS_DYLIB)]
86 extern static int mono_btls_x509_get_issuer_name_string (IntPtr handle, IntPtr buffer, int size);
88 [DllImport (BTLS_DYLIB)]
89 extern static int mono_btls_x509_get_raw_data (IntPtr handle, IntPtr bio, MonoBtlsX509Format format);
91 [DllImport (BTLS_DYLIB)]
92 extern static int mono_btls_x509_cmp (IntPtr a, IntPtr b);
94 [DllImport (BTLS_DYLIB)]
95 extern static int mono_btls_x509_get_hash (IntPtr handle, out IntPtr data);
97 [DllImport (BTLS_DYLIB)]
98 extern static long mono_btls_x509_get_not_before (IntPtr handle);
100 [DllImport (BTLS_DYLIB)]
101 extern static long mono_btls_x509_get_not_after (IntPtr handle);
103 [DllImport (BTLS_DYLIB)]
104 extern static int mono_btls_x509_get_public_key (IntPtr handle, IntPtr bio);
106 [DllImport (BTLS_DYLIB)]
107 extern static int mono_btls_x509_get_serial_number (IntPtr handle, IntPtr data, int size, int mono_style);
109 [DllImport (BTLS_DYLIB)]
110 extern static int mono_btls_x509_get_version (IntPtr handle);
112 [DllImport (BTLS_DYLIB)]
113 extern static int mono_btls_x509_get_signature_algorithm (IntPtr handle, IntPtr buffer, int size);
115 [DllImport (BTLS_DYLIB)]
116 extern static int mono_btls_x509_get_public_key_asn1 (IntPtr handle, IntPtr oid, int oid_size, out IntPtr data, out int size);
118 [DllImport (BTLS_DYLIB)]
119 extern static int mono_btls_x509_get_public_key_parameters (IntPtr handle, IntPtr oid, int oid_size, out IntPtr data, out int size);
121 [DllImport (BTLS_DYLIB)]
122 extern static IntPtr mono_btls_x509_get_pubkey (IntPtr handle);
124 [DllImport (BTLS_DYLIB)]
125 extern static int mono_btls_x509_get_subject_key_identifier (IntPtr handle, out IntPtr data, out int size);
127 [DllImport (BTLS_DYLIB)]
128 extern static int mono_btls_x509_print (IntPtr handle, IntPtr bio);
130 [DllImport (BTLS_DYLIB)]
131 extern static void mono_btls_x509_free (IntPtr handle);
133 [DllImport (BTLS_DYLIB)]
134 extern static IntPtr mono_btls_x509_dup (IntPtr handle);
136 [DllImport (BTLS_DYLIB)]
137 extern static int mono_btls_x509_add_trust_object (IntPtr handle, MonoBtlsX509Purpose purpose);
139 [DllImport (BTLS_DYLIB)]
140 extern static int mono_btls_x509_add_reject_object (IntPtr handle, MonoBtlsX509Purpose purpose);
142 [DllImport (BTLS_DYLIB)]
143 extern static int mono_btls_x509_add_explicit_trust (IntPtr handle, MonoBtlsX509TrustKind kind);
145 internal MonoBtlsX509 Copy ()
147 var copy = mono_btls_x509_up_ref (Handle.DangerousGetHandle ());
148 CheckError (copy != IntPtr.Zero);
149 return new MonoBtlsX509 (new BoringX509Handle (copy));
152 // This will actually duplicate the underlying 'X509 *' object instead of
153 // simply increasing the reference count.
154 internal MonoBtlsX509 Duplicate ()
156 var copy = mono_btls_x509_dup (Handle.DangerousGetHandle ());
157 CheckError (copy != IntPtr.Zero);
158 return new MonoBtlsX509 (new BoringX509Handle (copy));
161 public static MonoBtlsX509 LoadFromData (byte[] buffer, MonoBtlsX509Format format)
163 var data = Marshal.AllocHGlobal (buffer.Length);
164 if (data == IntPtr.Zero)
165 throw new OutOfMemoryException ();
167 try {
168 Marshal.Copy (buffer, 0, data, buffer.Length);
169 var x509 = mono_btls_x509_from_data (data, buffer.Length, format);
170 if (x509 == IntPtr.Zero)
171 throw new MonoBtlsException ("Failed to read certificate from data.");
173 return new MonoBtlsX509 (new BoringX509Handle (x509));
174 } finally {
175 Marshal.FreeHGlobal (data);
179 public MonoBtlsX509Name GetSubjectName ()
181 var handle = mono_btls_x509_get_subject_name (Handle.DangerousGetHandle ());
182 CheckError (handle != IntPtr.Zero);
183 return new MonoBtlsX509Name (new MonoBtlsX509Name.BoringX509NameHandle (handle, false));
186 public string GetSubjectNameString ()
188 const int size = 4096;
189 var data = Marshal.AllocHGlobal (size);
190 try {
191 var ret = mono_btls_x509_get_subject_name_string (
192 Handle.DangerousGetHandle (), data, size);
193 CheckError (ret);
194 return Marshal.PtrToStringAnsi (data);
195 } finally {
196 Marshal.FreeHGlobal (data);
200 public long GetSubjectNameHash ()
202 CheckThrow ();
203 using (var subject = GetSubjectName ())
204 return subject.GetHash ();
207 public MonoBtlsX509Name GetIssuerName ()
209 var handle = mono_btls_x509_get_issuer_name (Handle.DangerousGetHandle ());
210 CheckError (handle != IntPtr.Zero);
211 return new MonoBtlsX509Name (new MonoBtlsX509Name.BoringX509NameHandle (handle, false));
214 public string GetIssuerNameString ()
216 const int size = 4096;
217 var data = Marshal.AllocHGlobal (size);
218 try {
219 var ret = mono_btls_x509_get_issuer_name_string (
220 Handle.DangerousGetHandle (), data, size);
221 CheckError (ret);
222 return Marshal.PtrToStringAnsi (data);
223 } finally {
224 Marshal.FreeHGlobal (data);
228 public byte[] GetRawData (MonoBtlsX509Format format)
230 using (var bio = new MonoBtlsBioMemory ()) {
231 var ret = mono_btls_x509_get_raw_data (
232 Handle.DangerousGetHandle (),
233 bio.Handle.DangerousGetHandle (),
234 format);
235 CheckError (ret);
236 return bio.GetData ();
240 public void GetRawData (MonoBtlsBio bio, MonoBtlsX509Format format)
242 CheckThrow ();
243 var ret = mono_btls_x509_get_raw_data (
244 Handle.DangerousGetHandle (),
245 bio.Handle.DangerousGetHandle (),
246 format);
247 CheckError (ret);
250 public static int Compare (MonoBtlsX509 a, MonoBtlsX509 b)
252 return mono_btls_x509_cmp (
253 a.Handle.DangerousGetHandle (),
254 b.Handle.DangerousGetHandle ());
257 public byte[] GetCertHash ()
259 IntPtr data;
260 var ret = mono_btls_x509_get_hash (Handle.DangerousGetHandle (), out data);
261 CheckError (ret > 0);
262 var buffer = new byte [ret];
263 Marshal.Copy (data, buffer, 0, ret);
264 return buffer;
267 public DateTime GetNotBefore ()
269 var ticks = mono_btls_x509_get_not_before (Handle.DangerousGetHandle ());
270 return new DateTime (1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddSeconds (ticks);
273 public DateTime GetNotAfter ()
275 var ticks = mono_btls_x509_get_not_after (Handle.DangerousGetHandle ());
276 return new DateTime (1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddSeconds (ticks);
279 public byte[] GetPublicKeyData ()
281 using (var bio = new MonoBtlsBioMemory ()) {
282 var ret = mono_btls_x509_get_public_key (
283 Handle.DangerousGetHandle (),
284 bio.Handle.DangerousGetHandle ());
285 CheckError (ret > 0);
286 return bio.GetData ();
290 public byte[] GetSerialNumber (bool mono_style)
292 int size = 256;
293 IntPtr data = Marshal.AllocHGlobal (size);
294 try {
295 var ret = mono_btls_x509_get_serial_number (
296 Handle.DangerousGetHandle (), data,
297 size, mono_style ? 1 : 0);
298 CheckError (ret > 0);
299 var buffer = new byte [ret];
300 Marshal.Copy (data, buffer, 0, ret);
301 return buffer;
302 } finally {
303 if (data != IntPtr.Zero)
304 Marshal.FreeHGlobal (data);
308 public int GetVersion ()
310 return mono_btls_x509_get_version (Handle.DangerousGetHandle ());
313 public string GetSignatureAlgorithm ()
315 int size = 256;
316 IntPtr data = Marshal.AllocHGlobal (size);
317 try {
318 var ret = mono_btls_x509_get_signature_algorithm (
319 Handle.DangerousGetHandle (), data, size);
320 CheckError (ret > 0);
321 return Marshal.PtrToStringAnsi (data);
322 } finally {
323 Marshal.FreeHGlobal (data);
327 public AsnEncodedData GetPublicKeyAsn1 ()
329 int size;
330 IntPtr data;
332 int oidSize = 256;
333 var oidData = Marshal.AllocHGlobal (256);
334 string oid;
336 try {
337 var ret = mono_btls_x509_get_public_key_asn1 (
338 Handle.DangerousGetHandle (), oidData, oidSize,
339 out data, out size);
340 CheckError (ret);
341 oid = Marshal.PtrToStringAnsi (oidData);
342 } finally {
343 Marshal.FreeHGlobal (oidData);
346 try {
347 var buffer = new byte[size];
348 Marshal.Copy (data, buffer, 0, size);
349 return new AsnEncodedData (oid.ToString (), buffer);
350 } finally {
351 if (data != IntPtr.Zero)
352 FreeDataPtr (data);
356 public AsnEncodedData GetPublicKeyParameters ()
358 int size;
359 IntPtr data;
361 int oidSize = 256;
362 var oidData = Marshal.AllocHGlobal (256);
363 string oid;
365 try {
366 var ret = mono_btls_x509_get_public_key_parameters (
367 Handle.DangerousGetHandle (), oidData, oidSize,
368 out data, out size);
369 CheckError (ret);
370 oid = Marshal.PtrToStringAnsi (oidData);
371 } finally {
372 Marshal.FreeHGlobal (oidData);
375 try {
376 var buffer = new byte[size];
377 Marshal.Copy (data, buffer, 0, size);
378 return new AsnEncodedData (oid.ToString (), buffer);
379 } finally {
380 if (data != IntPtr.Zero)
381 FreeDataPtr (data);
385 public byte[] GetSubjectKeyIdentifier ()
387 int size;
388 IntPtr data = IntPtr.Zero;
390 try {
391 var ret = mono_btls_x509_get_subject_key_identifier (
392 Handle.DangerousGetHandle (), out data, out size);
393 CheckError (ret);
394 var buffer = new byte[size];
395 Marshal.Copy (data, buffer, 0, size);
396 return buffer;
397 } finally {
398 if (data != IntPtr.Zero)
399 FreeDataPtr (data);
403 public MonoBtlsKey GetPublicKey ()
405 var handle = mono_btls_x509_get_pubkey (Handle.DangerousGetHandle ());
406 CheckError (handle != IntPtr.Zero);
407 return new MonoBtlsKey (new MonoBtlsKey.BoringKeyHandle (handle));
410 public void Print (MonoBtlsBio bio)
412 var ret = mono_btls_x509_print (
413 Handle.DangerousGetHandle (),
414 bio.Handle.DangerousGetHandle ());
415 CheckError (ret);
418 public void ExportAsPEM (MonoBtlsBio bio, bool includeHumanReadableForm)
420 GetRawData (bio, MonoBtlsX509Format.PEM);
422 if (!includeHumanReadableForm)
423 return;
425 Print (bio);
427 var hash = GetCertHash ();
428 var output = new StringBuilder ();
429 output.Append ("SHA1 Fingerprint=");
430 for (int i = 0; i < hash.Length; i++) {
431 if (i > 0)
432 output.Append (":");
433 output.AppendFormat ("{0:X2}", hash [i]);
435 output.AppendLine ();
436 var outputData = Encoding.ASCII.GetBytes (output.ToString ());
437 bio.Write (outputData, 0, outputData.Length);
440 public void AddTrustObject (MonoBtlsX509Purpose purpose)
442 CheckThrow ();
443 var ret = mono_btls_x509_add_trust_object (
444 Handle.DangerousGetHandle (), purpose);
445 CheckError (ret);
448 public void AddRejectObject (MonoBtlsX509Purpose purpose)
450 CheckThrow ();
451 var ret = mono_btls_x509_add_reject_object (
452 Handle.DangerousGetHandle (), purpose);
453 CheckError (ret);
456 public void AddExplicitTrust (MonoBtlsX509TrustKind kind)
458 CheckThrow ();
459 var ret = mono_btls_x509_add_explicit_trust (
460 Handle.DangerousGetHandle (), kind);
461 CheckError (ret);
465 #endif