[BTLS]: Add managed BTLS sources.
authorMartin Baulig <martin.baulig@xamarin.com>
Fri, 30 Sep 2016 11:47:22 +0000 (13:47 +0200)
committerMartin Baulig <martin.baulig@xamarin.com>
Fri, 30 Sep 2016 12:07:26 +0000 (14:07 +0200)
* external/boringssl: unmanaged code from Google (added earlier).

* mono/btls: unmanaged BTLS lives here (added earlier).

* System/Mono.Btls: managed BTLS lives here.

* Mono.Btls.Interface: The purpose of this assembly is to allow test suites
  such as xamarin/web-tests to test parts of the BTLS APIs without making
  System.dll's internals visible.  It is not a stable and maintained API.

73 files changed:
mcs/class/Makefile
mcs/class/Mono.Btls.Interface/Makefile [new file with mode: 0644]
mcs/class/Mono.Btls.Interface/Mono.Btls.Interface.dll.sources [new file with mode: 0644]
mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsObject.cs [new file with mode: 0644]
mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsProvider.cs [new file with mode: 0644]
mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsX509.cs [new file with mode: 0644]
mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsX509Chain.cs [new file with mode: 0644]
mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsX509Error.cs [new file with mode: 0644]
mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsX509Format.cs [new file with mode: 0644]
mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsX509Lookup.cs [new file with mode: 0644]
mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsX509Name.cs [new file with mode: 0644]
mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsX509Purpose.cs [new file with mode: 0644]
mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsX509Store.cs [new file with mode: 0644]
mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsX509StoreCtx.cs [new file with mode: 0644]
mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsX509StoreManager.cs [new file with mode: 0644]
mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsX509StoreType.cs [new file with mode: 0644]
mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsX509TrustKind.cs [new file with mode: 0644]
mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsX509VerifyFlags.cs [new file with mode: 0644]
mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsX509VerifyParam.cs [new file with mode: 0644]
mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/VersionInfo.cs [new file with mode: 0644]
mcs/class/Mono.Btls.Interface/Properties/AssemblyInfo.cs [new file with mode: 0644]
mcs/class/Mono.Btls.Interface/README.md [new file with mode: 0644]
mcs/class/System/Assembly/AssemblyInfo.cs
mcs/class/System/Mono.Btls/MonoBtlsBio.cs [new file with mode: 0644]
mcs/class/System/Mono.Btls/MonoBtlsContext.cs [new file with mode: 0644]
mcs/class/System/Mono.Btls/MonoBtlsError.cs [new file with mode: 0644]
mcs/class/System/Mono.Btls/MonoBtlsException.cs [new file with mode: 0644]
mcs/class/System/Mono.Btls/MonoBtlsKey.cs [new file with mode: 0644]
mcs/class/System/Mono.Btls/MonoBtlsObject.cs [new file with mode: 0644]
mcs/class/System/Mono.Btls/MonoBtlsPkcs12.cs [new file with mode: 0644]
mcs/class/System/Mono.Btls/MonoBtlsProvider.cs [new file with mode: 0644]
mcs/class/System/Mono.Btls/MonoBtlsSsl.cs [new file with mode: 0644]
mcs/class/System/Mono.Btls/MonoBtlsSslCtx.cs [new file with mode: 0644]
mcs/class/System/Mono.Btls/MonoBtlsSslError.cs [new file with mode: 0644]
mcs/class/System/Mono.Btls/MonoBtlsStream.cs [new file with mode: 0644]
mcs/class/System/Mono.Btls/MonoBtlsUtils.cs [new file with mode: 0644]
mcs/class/System/Mono.Btls/MonoBtlsX509.cs [new file with mode: 0644]
mcs/class/System/Mono.Btls/MonoBtlsX509Chain.cs [new file with mode: 0644]
mcs/class/System/Mono.Btls/MonoBtlsX509Crl.cs [new file with mode: 0644]
mcs/class/System/Mono.Btls/MonoBtlsX509Error.cs [new file with mode: 0644]
mcs/class/System/Mono.Btls/MonoBtlsX509Exception.cs [new file with mode: 0644]
mcs/class/System/Mono.Btls/MonoBtlsX509FileType.cs [new file with mode: 0644]
mcs/class/System/Mono.Btls/MonoBtlsX509Format.cs [new file with mode: 0644]
mcs/class/System/Mono.Btls/MonoBtlsX509Lookup.cs [new file with mode: 0644]
mcs/class/System/Mono.Btls/MonoBtlsX509LookupAndroid.cs [new file with mode: 0644]
mcs/class/System/Mono.Btls/MonoBtlsX509LookupMono.cs [new file with mode: 0644]
mcs/class/System/Mono.Btls/MonoBtlsX509LookupMonoCollection.cs [new file with mode: 0644]
mcs/class/System/Mono.Btls/MonoBtlsX509LookupType.cs [new file with mode: 0644]
mcs/class/System/Mono.Btls/MonoBtlsX509Name.cs [new file with mode: 0644]
mcs/class/System/Mono.Btls/MonoBtlsX509NameEntryType.cs [new file with mode: 0644]
mcs/class/System/Mono.Btls/MonoBtlsX509NameList.cs [new file with mode: 0644]
mcs/class/System/Mono.Btls/MonoBtlsX509Purpose.cs [new file with mode: 0644]
mcs/class/System/Mono.Btls/MonoBtlsX509Revoked.cs [new file with mode: 0644]
mcs/class/System/Mono.Btls/MonoBtlsX509Store.cs [new file with mode: 0644]
mcs/class/System/Mono.Btls/MonoBtlsX509StoreCtx.cs [new file with mode: 0644]
mcs/class/System/Mono.Btls/MonoBtlsX509StoreManager.cs [new file with mode: 0644]
mcs/class/System/Mono.Btls/MonoBtlsX509StoreType.cs [new file with mode: 0644]
mcs/class/System/Mono.Btls/MonoBtlsX509TrustKind.cs [new file with mode: 0644]
mcs/class/System/Mono.Btls/MonoBtlsX509VerifyFlags.cs [new file with mode: 0644]
mcs/class/System/Mono.Btls/MonoBtlsX509VerifyParam.cs [new file with mode: 0644]
mcs/class/System/Mono.Btls/X509CertificateImplBtls.cs [new file with mode: 0644]
mcs/class/System/Mono.Btls/X509ChainImplBtls.cs [new file with mode: 0644]
mcs/class/System/Mono.Net.Security/MonoTlsProviderFactory.Droid.cs
mcs/class/System/Mono.Net.Security/MonoTlsProviderFactory.cs
mcs/class/System/System.Security.Cryptography.X509Certificates/X509Helper2.cs
mcs/class/System/System.dll.sources
mcs/class/System/mobile_System.dll.sources
mcs/class/System/monodroid_System.dll.sources
mcs/tools/Makefile
mcs/tools/btls/AssemblyInfo.cs [new file with mode: 0644]
mcs/tools/btls/Makefile [new file with mode: 0644]
mcs/tools/btls/btls-cert-sync.cs [new file with mode: 0644]
mcs/tools/btls/btls-cert-sync.exe.sources [new file with mode: 0644]

index e9c0a1621512da713432a917ee93e659d16bd5d0..ef78dfed837c40257ea4ed70221e4c2f310cff80 100644 (file)
@@ -141,6 +141,7 @@ xammac_4_5_dirs := \
        System.Data.Linq                \
        System.Net.Http \
        System.Net.Http.WebRequest \
+       Mono.Btls.Interface \
        System.Runtime.InteropServices.RuntimeInformation \
        System.Reflection.Context       \
        System.Net.Http.WinHttpHandler  \
@@ -236,6 +237,7 @@ net_4_x_dirs := \
 net_4_x_parallel_dirs := \
        PEAPI                           \
        I18N                            \
+       Mono.Btls.Interface             \
        Mono.Http                       \
        Mono.Cairo                      \
        Mono.Cecil                      \
diff --git a/mcs/class/Mono.Btls.Interface/Makefile b/mcs/class/Mono.Btls.Interface/Makefile
new file mode 100644 (file)
index 0000000..ea7e128
--- /dev/null
@@ -0,0 +1,12 @@
+thisdir = class/Mono.Btls.Interface
+SUBDIRS = 
+include ../../build/rules.make
+
+LIBRARY = Mono.Btls.Interface.dll
+LIB_REFS = System Mono.Security
+LIB_MCS_FLAGS = -unsafe -nowarn:1030 -keyfile:../mono.pub -delaysign -d:SECURITY_DEP
+
+include ../../build/library.make
+
+$(the_lib): ../Mono.Security/Makefile
+
diff --git a/mcs/class/Mono.Btls.Interface/Mono.Btls.Interface.dll.sources b/mcs/class/Mono.Btls.Interface/Mono.Btls.Interface.dll.sources
new file mode 100644 (file)
index 0000000..710e06d
--- /dev/null
@@ -0,0 +1,22 @@
+./Properties/AssemblyInfo.cs
+../../build/common/Consts.cs
+../../build/common/Locale.cs
+../../build/common/MonoTODOAttribute.cs
+
+Mono.Btls.Interface/BtlsObject.cs
+Mono.Btls.Interface/BtlsProvider.cs
+Mono.Btls.Interface/BtlsX509.cs
+Mono.Btls.Interface/BtlsX509Chain.cs
+Mono.Btls.Interface/BtlsX509Error.cs
+Mono.Btls.Interface/BtlsX509Format.cs
+Mono.Btls.Interface/BtlsX509Lookup.cs
+Mono.Btls.Interface/BtlsX509Name.cs
+Mono.Btls.Interface/BtlsX509Purpose.cs
+Mono.Btls.Interface/BtlsX509Store.cs
+Mono.Btls.Interface/BtlsX509StoreCtx.cs
+Mono.Btls.Interface/BtlsX509StoreManager.cs
+Mono.Btls.Interface/BtlsX509StoreType.cs
+Mono.Btls.Interface/BtlsX509TrustKind.cs
+Mono.Btls.Interface/BtlsX509VerifyFlags.cs
+Mono.Btls.Interface/BtlsX509VerifyParam.cs
+Mono.Btls.Interface/VersionInfo.cs
diff --git a/mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsObject.cs b/mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsObject.cs
new file mode 100644 (file)
index 0000000..b2e607c
--- /dev/null
@@ -0,0 +1,73 @@
+//
+// BtlsObject.cs
+//
+// Author:
+//       Martin Baulig <martin.baulig@xamarin.com>
+//
+// Copyright (c) 2016 Xamarin Inc. (http://www.xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+using System;
+
+namespace Mono.Btls.Interface
+{
+       public abstract class BtlsObject : IDisposable
+       {
+               MonoBtlsObject instance;
+
+               internal MonoBtlsObject Instance {
+                       get {
+                               if (!IsValid)
+                                       throw new ObjectDisposedException (GetType ().Name);
+                               return instance;
+                       }
+               }
+
+               internal BtlsObject (MonoBtlsObject instance)
+               {
+                       this.instance = instance;
+               }
+
+               public bool IsValid {
+                       get { return instance != null && instance.IsValid; }
+               }
+
+               protected void Dispose (bool disposing)
+               {
+                       if (disposing) {
+                               if (instance != null) {
+                                       instance.Dispose ();
+                                       instance = null;
+                               }
+                       }
+               }
+
+               public void Dispose ()
+               {
+                       Dispose (true);
+                       GC.SuppressFinalize (this);
+               }
+
+               ~BtlsObject ()
+               {
+                       Dispose (false);
+               }
+       }
+}
+
diff --git a/mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsProvider.cs b/mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsProvider.cs
new file mode 100644 (file)
index 0000000..6a8d810
--- /dev/null
@@ -0,0 +1,106 @@
+//
+// BtlsProvider.cs
+//
+// Author:
+//       Martin Baulig <martin.baulig@xamarin.com>
+//
+// Copyright (c) 2016 Xamarin Inc. (http://www.xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+using System;
+using Mono.Security.Interface;
+using System.Security.Cryptography.X509Certificates;
+
+namespace Mono.Btls.Interface
+{
+       public static class BtlsProvider
+       {
+               public static bool IsSupported ()
+               {
+                       return MonoBtlsProvider.IsSupported ();
+               }
+
+               public static MonoTlsProvider GetProvider ()
+               {
+                       return new MonoBtlsProvider ();
+               }
+
+               public static BtlsX509 CreateNative (byte[] data, BtlsX509Format format)
+               {
+                       var x509 = MonoBtlsX509.LoadFromData (data, (MonoBtlsX509Format)format);
+                       return new BtlsX509 (x509);
+               }
+
+               public static X509Certificate CreateCertificate (byte[] data, BtlsX509Format format, bool disallowFallback = false)
+               {
+                       return MonoBtlsProvider.CreateCertificate (data, (MonoBtlsX509Format)format, disallowFallback);
+               }
+
+               public static X509Certificate2 CreateCertificate2 (byte[] data, BtlsX509Format format, bool disallowFallback = false)
+               {
+                       return MonoBtlsProvider.CreateCertificate2 (data, (MonoBtlsX509Format)format, disallowFallback);
+               }
+
+               public static X509Certificate2 CreateCertificate2 (byte[] data, string password, bool disallowFallback = false)
+               {
+                       return MonoBtlsProvider.CreateCertificate2 (data, password, disallowFallback);
+               }
+
+               public static BtlsX509Chain CreateNativeChain ()
+               {
+                       return new BtlsX509Chain (new MonoBtlsX509Chain ());
+               }
+
+               public static BtlsX509Store CreateNativeStore ()
+               {
+                       return new BtlsX509Store (new MonoBtlsX509Store ());
+               }
+
+               public static BtlsX509StoreCtx CreateNativeStoreCtx ()
+               {
+                       return new BtlsX509StoreCtx (new MonoBtlsX509StoreCtx ());
+               }
+
+               public static X509Chain CreateChain ()
+               {
+                       return MonoBtlsProvider.CreateChain ();
+               }
+
+               public static string GetSystemStoreLocation ()
+               {
+                       return MonoBtlsProvider.GetSystemStoreLocation ();
+               }
+
+               public static BtlsX509VerifyParam GetVerifyParam_SslClient ()
+               {
+                       return new BtlsX509VerifyParam (MonoBtlsX509VerifyParam.GetSslClient ());
+               }
+
+               public static BtlsX509VerifyParam GetVerifyParam_SslServer ()
+               {
+                       return new BtlsX509VerifyParam (MonoBtlsX509VerifyParam.GetSslServer ());
+               }
+
+               public static X509Chain GetManagedChain (BtlsX509Chain chain)
+               {
+                       return MonoBtlsProvider.GetManagedChain (chain.Instance);
+               }
+       }
+}
+
diff --git a/mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsX509.cs b/mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsX509.cs
new file mode 100644 (file)
index 0000000..abcdafb
--- /dev/null
@@ -0,0 +1,132 @@
+//
+// BtlsX509.cs
+//
+// Author:
+//       Martin Baulig <martin.baulig@xamarin.com>
+//
+// Copyright (c) 2016 Xamarin Inc. (http://www.xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+using System;
+using System.IO;
+using System.Security.Cryptography;
+
+namespace Mono.Btls.Interface
+{
+       public class BtlsX509 : BtlsObject
+       {
+               new internal MonoBtlsX509 Instance {
+                       get { return (MonoBtlsX509)base.Instance; }
+               }
+
+               internal BtlsX509 (MonoBtlsX509 x509)
+                       : base (x509)
+               {
+               }
+
+               public BtlsX509Name GetSubjectName ()
+               {
+                       return new BtlsX509Name (Instance.GetSubjectName ());
+               }
+
+               public BtlsX509Name GetIssuerName ()
+               {
+                       return new BtlsX509Name (Instance.GetIssuerName ());
+               }
+
+               public string GetSubjectNameString ()
+               {
+                       return Instance.GetSubjectNameString ();
+               }
+
+               public string GetIssuerNameString ()
+               {
+                       return Instance.GetIssuerNameString ();
+               }
+
+               public byte[] GetRawData (BtlsX509Format format)
+               {
+                       return Instance.GetRawData ((MonoBtlsX509Format)format);
+               }
+
+               public byte[] GetCertHash ()
+               {
+                       return Instance.GetCertHash ();
+               }
+
+               public DateTime GetNotBefore ()
+               {
+                       return Instance.GetNotBefore ();
+               }
+
+               public DateTime GetNotAfter ()
+               {
+                       return Instance.GetNotAfter ();
+               }
+
+               public byte[] GetPublicKeyData ()
+               {
+                       return Instance.GetPublicKeyData ();
+               }
+
+               public byte[] GetSerialNumber (bool mono_style)
+               {
+                       return Instance.GetSerialNumber (mono_style);
+               }
+
+               public int GetVersion ()
+               {
+                       return Instance.GetVersion ();
+               }
+
+               public Oid GetSignatureAlgorithm ()
+               {
+                       return Instance.GetSignatureAlgorithm ();
+               }
+
+               public AsnEncodedData GetPublicKeyAsn1 ()
+               {
+                       return Instance.GetPublicKeyAsn1 ();
+               }
+
+               public AsnEncodedData GetPublicKeyParameters ()
+               {
+                       return Instance.GetPublicKeyParameters (); 
+               }
+
+               public long GetSubjectNameHash ()
+               {
+                       using (var name = GetSubjectName ())
+                               return name.GetHash ();
+               }
+
+               public void Print (Stream stream)
+               {
+                       using (var bio = MonoBtlsBio.CreateMonoStream (stream))
+                               Instance.Print (bio);
+               }
+
+               public void ExportAsPEM (Stream stream, bool includeHumanReadableForm)
+               {
+                       using (var bio = MonoBtlsBio.CreateMonoStream (stream))
+                               Instance.ExportAsPEM (bio, includeHumanReadableForm);
+               }
+       }
+}
+
diff --git a/mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsX509Chain.cs b/mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsX509Chain.cs
new file mode 100644 (file)
index 0000000..38e9ec5
--- /dev/null
@@ -0,0 +1,58 @@
+//
+// BtlsX509Chain.cs
+//
+// Author:
+//       Martin Baulig <martin.baulig@xamarin.com>
+//
+// Copyright (c) 2016 Xamarin Inc. (http://www.xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+using System;
+
+namespace Mono.Btls.Interface
+{
+       public class BtlsX509Chain : BtlsObject
+       {
+               new internal MonoBtlsX509Chain Instance {
+                       get { return (MonoBtlsX509Chain)base.Instance; }
+               }
+
+               internal BtlsX509Chain (MonoBtlsX509Chain chain)
+                       : base (chain)
+               {
+               }
+
+               public int Count {
+                       get { return Instance.Count; }
+               }
+
+               public BtlsX509 this[int index] {
+                       get {
+                               var x509 = Instance.GetCertificate (index);
+                               return new BtlsX509 (x509.Copy ());
+                       }
+               }
+
+               public void Add (BtlsX509 x509)
+               {
+                       Instance.AddCertificate (x509.Instance);
+               }
+       }
+}
+
diff --git a/mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsX509Error.cs b/mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsX509Error.cs
new file mode 100644 (file)
index 0000000..089b4f2
--- /dev/null
@@ -0,0 +1,110 @@
+//
+// BtlsX509Error.cs
+//
+// Author:
+//       Martin Baulig <martin.baulig@xamarin.com>
+//
+// Copyright (c) 2016 Xamarin Inc. (http://www.xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+using System;
+namespace Mono.Btls.Interface
+{
+       // Keep in sync with NativeBoringX509Error
+       public enum BtlsX509Error
+       {
+               OK = 0,
+               /* illegal error (for uninitialized values, to avoid X509_V_OK): 1 */
+
+               UNABLE_TO_GET_ISSUER_CERT = 2,
+               UNABLE_TO_GET_CRL = 3,
+               UNABLE_TO_DECRYPT_CERT_SIGNATURE = 4,
+               UNABLE_TO_DECRYPT_CRL_SIGNATURE = 5,
+               UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY = 6,
+               CERT_SIGNATURE_FAILURE = 7,
+               CRL_SIGNATURE_FAILURE = 8,
+               CERT_NOT_YET_VALID = 9,
+               CERT_HAS_EXPIRED = 10,
+               CRL_NOT_YET_VALID = 11,
+               CRL_HAS_EXPIRED = 12,
+               ERROR_IN_CERT_NOT_BEFORE_FIELD = 13,
+               ERROR_IN_CERT_NOT_AFTER_FIELD = 14,
+               ERROR_IN_CRL_LAST_UPDATE_FIELD = 15,
+               ERROR_IN_CRL_NEXT_UPDATE_FIELD = 16,
+               OUT_OF_MEM = 17,
+               DEPTH_ZERO_SELF_SIGNED_CERT = 18,
+               SELF_SIGNED_CERT_IN_CHAIN = 19,
+               UNABLE_TO_GET_ISSUER_CERT_LOCALLY = 20,
+               UNABLE_TO_VERIFY_LEAF_SIGNATURE = 21,
+               CERT_CHAIN_TOO_LONG = 22,
+               CERT_REVOKED = 23,
+               INVALID_CA = 24,
+               PATH_LENGTH_EXCEEDED = 25,
+               INVALID_PURPOSE = 26,
+               CERT_UNTRUSTED = 27,
+               CERT_REJECTED = 28,
+               /* These are 'informational' when looking for issuer cert */
+               SUBJECT_ISSUER_MISMATCH = 29,
+               AKID_SKID_MISMATCH = 30,
+               AKID_ISSUER_SERIAL_MISMATCH = 31,
+               KEYUSAGE_NO_CERTSIGN = 32,
+
+               UNABLE_TO_GET_CRL_ISSUER = 33,
+               UNHANDLED_CRITICAL_EXTENSION = 34,
+               KEYUSAGE_NO_CRL_SIGN = 35,
+               UNHANDLED_CRITICAL_CRL_EXTENSION = 36,
+               INVALID_NON_CA = 37,
+               PROXY_PATH_LENGTH_EXCEEDED = 38,
+               KEYUSAGE_NO_DIGITAL_SIGNATURE = 39,
+               PROXY_CERTIFICATES_NOT_ALLOWED = 40,
+
+               INVALID_EXTENSION = 41,
+               INVALID_POLICY_EXTENSION = 42,
+               NO_EXPLICIT_POLICY = 43,
+               DIFFERENT_CRL_SCOPE = 44,
+               UNSUPPORTED_EXTENSION_FEATURE = 45,
+
+               UNNESTED_RESOURCE = 46,
+
+               PERMITTED_VIOLATION = 47,
+               EXCLUDED_VIOLATION = 48,
+               SUBTREE_MINMAX = 49,
+               UNSUPPORTED_CONSTRAINT_TYPE = 51,
+               UNSUPPORTED_CONSTRAINT_SYNTAX = 52,
+               UNSUPPORTED_NAME_SYNTAX = 53,
+               CRL_PATH_VALIDATION_ERROR = 54,
+
+               /* Suite B mode algorithm violation */
+               SUITE_B_INVALID_VERSION = 56,
+               SUITE_B_INVALID_ALGORITHM = 57,
+               SUITE_B_INVALID_CURVE = 58,
+               SUITE_B_INVALID_SIGNATURE_ALGORITHM = 59,
+               SUITE_B_LOS_NOT_ALLOWED = 60,
+               SUITE_B_CANNOT_SIGN_P_384_WITH_P_256 = 61,
+
+               /* Host, email and IP check errors */
+               HOSTNAME_MISMATCH = 62,
+               EMAIL_MISMATCH = 63,
+               IP_ADDRESS_MISMATCH = 64,
+
+               /* The application is not happy */
+               APPLICATION_VERIFICATION = 50
+       }
+}
+
diff --git a/mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsX509Format.cs b/mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsX509Format.cs
new file mode 100644 (file)
index 0000000..6ff63ce
--- /dev/null
@@ -0,0 +1,37 @@
+//
+// BtlsX509Format.cs
+//
+// Author:
+//       Martin Baulig <martin.baulig@xamarin.com>
+//
+// Copyright (c) 2016 Xamarin Inc. (http://www.xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+using System;
+
+namespace Mono.Btls.Interface
+{
+       // Keep in sync with NativeBoringX509Format
+       public enum BtlsX509Format
+       {
+               DER = 1,
+               PEM = 2
+       }
+}
+
diff --git a/mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsX509Lookup.cs b/mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsX509Lookup.cs
new file mode 100644 (file)
index 0000000..836088f
--- /dev/null
@@ -0,0 +1,72 @@
+//
+// BtlsX509Lookup.cs
+//
+// Author:
+//       Martin Baulig <martin.baulig@xamarin.com>
+//
+// Copyright (c) 2016 Xamarin Inc. (http://www.xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+using System;
+using System.IO;
+using System.Security.Cryptography;
+
+namespace Mono.Btls.Interface
+{
+       public class BtlsX509Lookup : BtlsObject
+       {
+               new internal MonoBtlsX509Lookup Instance {
+                       get { return (MonoBtlsX509Lookup)base.Instance; }
+               }
+
+               internal BtlsX509Lookup (MonoBtlsX509Lookup lookup)
+                       : base (lookup)
+               {
+               }
+
+               public void Initialize ()
+               {
+                       Instance.Initialize ();
+               }
+
+               public void Shutdown ()
+               {
+                       Instance.Shutdown ();
+               }
+
+               public BtlsX509 LookupBySubject (BtlsX509Name name)
+               {
+                       var x509 = Instance.LookupBySubject (name.Instance);
+                       if (x509 == null)
+                               return null;
+
+                       return new BtlsX509 (x509);
+               }
+
+               public void LoadFile (string file, BtlsX509Format type)
+               {
+                       Instance.LoadFile (file, (MonoBtlsX509FileType)type);
+               }
+
+               public void AddDirectory (string dir, BtlsX509Format type)
+               {
+                       Instance.AddDirectory (dir, (MonoBtlsX509FileType)type);
+               }
+       }
+}
diff --git a/mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsX509Name.cs b/mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsX509Name.cs
new file mode 100644 (file)
index 0000000..69ca5a9
--- /dev/null
@@ -0,0 +1,62 @@
+//
+// BtlsX509Name.cs
+//
+// Author:
+//       Martin Baulig <martin.baulig@xamarin.com>
+//
+// Copyright (c) 2016 Xamarin Inc. (http://www.xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+using System;
+
+namespace Mono.Btls.Interface
+{
+       public class BtlsX509Name : BtlsObject
+       {
+               new internal MonoBtlsX509Name Instance {
+                       get { return (MonoBtlsX509Name)base.Instance; }
+               }
+
+               internal BtlsX509Name (MonoBtlsX509Name name)
+                       : base (name)
+               {
+               }
+
+               public string GetString ()
+               {
+                       return Instance.GetString ();
+               }
+
+               public byte[] GetRawData (bool use_canon_enc)
+               {
+                       return Instance.GetRawData (use_canon_enc);
+               }
+
+               public long GetHash ()
+               {
+                       return Instance.GetHash ();
+               }
+
+               public long GetHashOld ()
+               {
+                       return Instance.GetHashOld ();
+               }
+       }
+}
+
diff --git a/mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsX509Purpose.cs b/mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsX509Purpose.cs
new file mode 100644 (file)
index 0000000..ac906df
--- /dev/null
@@ -0,0 +1,43 @@
+//
+// BtlsX509Purpose.cs
+//
+// Author:
+//       Martin Baulig <martin.baulig@xamarin.com>
+//
+// Copyright (c) 2016 Xamarin Inc. (http://www.xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+using System;
+namespace Mono.Btls.Interface
+{
+       // Keep in sync with NativeBoringX509Purpose
+       public enum BtlsX509Purpose
+       {
+               SSL_CLIENT = 1,
+               SSL_SERVER = 2,
+               NS_SSL_SERVER = 3,
+               SMIME_SIGN = 4,
+               SMIME_ENCRYPT = 5,
+               CRL_SIGN = 6,
+               ANY = 7,
+               OCSP_HELPER = 8,
+               TIMESTAMP_SIGN = 9,
+       }
+}
+
diff --git a/mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsX509Store.cs b/mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsX509Store.cs
new file mode 100644 (file)
index 0000000..7b8f03f
--- /dev/null
@@ -0,0 +1,91 @@
+//
+// BtlsX509Store.cs
+//
+// Author:
+//       Martin Baulig <martin.baulig@xamarin.com>
+//
+// Copyright (c) 2016 Xamarin Inc. (http://www.xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+using System;
+using System.Security.Cryptography.X509Certificates;
+
+namespace Mono.Btls.Interface
+{
+       public class BtlsX509Store : BtlsObject
+       {
+               new internal MonoBtlsX509Store Instance {
+                       get { return (MonoBtlsX509Store)base.Instance; }
+               }
+
+               internal BtlsX509Store (MonoBtlsX509Store store)
+                       : base (store)
+               {
+               }
+
+               public void LoadLocations (string file, string path)
+               {
+                       Instance.LoadLocations (file, path);
+               }
+
+               public void AddTrustedRoots ()
+               {
+                       Instance.AddTrustedRoots ();
+               }
+
+               public void AddCertificate (BtlsX509 x509)
+               {
+                       Instance.AddCertificate (x509.Instance);
+               }
+
+               public int GetCount ()
+               {
+                       return Instance.GetCount ();
+               }
+
+               public void AddLookup (X509CertificateCollection certificates, BtlsX509TrustKind trust)
+               {
+                       Instance.AddCollection (certificates, (MonoBtlsX509TrustKind)trust);
+               }
+
+               static MonoBtlsX509FileType GetFileType (BtlsX509Format format)
+               {
+                       switch (format) {
+                       case BtlsX509Format.DER:
+                               return MonoBtlsX509FileType.ASN1;
+                       case BtlsX509Format.PEM:
+                               return MonoBtlsX509FileType.PEM;
+                       default:
+                               throw new NotSupportedException ();
+                       }
+               }
+
+               public void AddDirectoryLookup (string dir, BtlsX509Format format)
+               {
+                       Instance.AddDirectoryLookup (dir, GetFileType (format));
+               }
+
+               public void AddFileLookup (string file, BtlsX509Format format)
+               {
+                       Instance.AddFileLookup (file, GetFileType (format));
+               }
+
+       }
+}
+
diff --git a/mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsX509StoreCtx.cs b/mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsX509StoreCtx.cs
new file mode 100644 (file)
index 0000000..97d4a06
--- /dev/null
@@ -0,0 +1,71 @@
+//
+// BtlsX509StoreCtx.cs
+//
+// Author:
+//       Martin Baulig <martin.baulig@xamarin.com>
+//
+// Copyright (c) 2016 Xamarin Inc. (http://www.xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+using System;
+namespace Mono.Btls.Interface
+{
+       public class BtlsX509StoreCtx : BtlsObject
+       {
+               new internal MonoBtlsX509StoreCtx Instance {
+                       get { return (MonoBtlsX509StoreCtx)base.Instance; }
+               }
+
+               internal BtlsX509StoreCtx (MonoBtlsX509StoreCtx ctx)
+                       : base (ctx)
+               {
+               }
+
+               public void Initialize (BtlsX509Store store, BtlsX509Chain chain)
+               {
+                       Instance.Initialize (store.Instance, chain.Instance);
+               }
+
+               public void SetVerifyParam (BtlsX509VerifyParam param)
+               {
+                       Instance.SetVerifyParam (param.Instance);
+               }
+
+               public int Verify ()
+               {
+                       return Instance.Verify ();
+               }
+
+               public BtlsX509Error GetError ()
+               {
+                       return (BtlsX509Error)Instance.GetError ();
+               }
+
+               public Exception GetException ()
+               {
+                       return Instance.GetException ();
+               }
+
+               public BtlsX509Chain GetChain ()
+               {
+                       return new BtlsX509Chain (Instance.GetChain ());
+               }
+       }
+}
+
diff --git a/mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsX509StoreManager.cs b/mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsX509StoreManager.cs
new file mode 100644 (file)
index 0000000..1989ff4
--- /dev/null
@@ -0,0 +1,44 @@
+//
+// BtlsX509StoreManager.cs
+//
+// Author:
+//       Martin Baulig <martin.baulig@xamarin.com>
+//
+// Copyright (c) 2016 Xamarin Inc. (http://www.xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+using System;
+using System.IO;
+using System.Security.Cryptography;
+
+namespace Mono.Btls.Interface
+{
+       public static class BtlsX509StoreManager
+       {
+               public static bool HasStore (BtlsX509StoreType type)
+               {
+                       return MonoBtlsX509StoreManager.HasStore ((MonoBtlsX509StoreType)type);
+               }
+
+               public static string GetStorePath (BtlsX509StoreType type)
+               {
+                       return MonoBtlsX509StoreManager.GetStorePath ((MonoBtlsX509StoreType)type);
+               }
+       }
+}
diff --git a/mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsX509StoreType.cs b/mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsX509StoreType.cs
new file mode 100644 (file)
index 0000000..acdfb98
--- /dev/null
@@ -0,0 +1,43 @@
+//
+// BtlsX509StoreType.cs
+//
+// Author:
+//       Martin Baulig <martin.baulig@xamarin.com>
+//
+// Copyright (c) 2016 Xamarin Inc. (http://www.xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+using System;
+using System.IO;
+using System.Security.Cryptography;
+
+namespace Mono.Btls.Interface
+{
+       // Keep in sync with MonoBtlsX509StoreType
+       public enum BtlsX509StoreType
+       {
+               Custom,
+               MachineTrustedRoots,
+               MachineIntermediateCA,
+               MachineUntrusted,
+               UserTrustedRoots,
+               UserIntermediateCA,
+               UserUntrusted
+       }
+}
diff --git a/mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsX509TrustKind.cs b/mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsX509TrustKind.cs
new file mode 100644 (file)
index 0000000..9338ec6
--- /dev/null
@@ -0,0 +1,42 @@
+//
+// BtlsX509TrustKind.cs
+//
+// Author:
+//       Martin Baulig <martin.baulig@xamarin.com>
+//
+// Copyright (c) 2016 Xamarin Inc. (http://www.xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+using System;
+namespace Mono.Btls.Interface
+{
+       // Keep in sync with MonoBtlsX509TrustKind
+       [Flags]
+       public enum BtlsX509TrustKind
+       {
+               DEFAULT         = 0,
+               TRUST_CLIENT    = 1,
+               TRUST_SERVER    = 2,
+               TRUST_ALL       = 4,
+               REJECT_CLIENT   = 32,
+               REJECT_SERVER   = 64,
+               REJECT_ALL      = 128
+       }
+}
+
diff --git a/mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsX509VerifyFlags.cs b/mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsX509VerifyFlags.cs
new file mode 100644 (file)
index 0000000..02640c8
--- /dev/null
@@ -0,0 +1,38 @@
+//
+// BtlsX509VerifyFlags.cs
+//
+// Author:
+//       Martin Baulig <martin.baulig@xamarin.com>
+//
+// Copyright (c) 2016 Xamarin Inc. (http://www.xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+using System;
+namespace Mono.Btls.Interface
+{
+       // Keep in sync with NativeBoringX509VerifyFlags
+       public enum BtlsX509VerifyFlags
+       {
+               DEFAULT = 0,
+               CRL_CHECK = 1,
+               CRL_CHECK_ALL = 2,
+               X509_STRIC = 4
+       }
+}
+
diff --git a/mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsX509VerifyParam.cs b/mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsX509VerifyParam.cs
new file mode 100644 (file)
index 0000000..8d4e5eb
--- /dev/null
@@ -0,0 +1,91 @@
+//
+// BtlsX509VerifyParam.cs
+//
+// Author:
+//       Martin Baulig <martin.baulig@xamarin.com>
+//
+// Copyright (c) 2016 Xamarin Inc. (http://www.xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+using System;
+namespace Mono.Btls.Interface
+{
+       public class BtlsX509VerifyParam : BtlsObject
+       {
+               new internal MonoBtlsX509VerifyParam Instance {
+                       get { return (MonoBtlsX509VerifyParam)base.Instance; }
+               }
+
+               internal BtlsX509VerifyParam (MonoBtlsX509VerifyParam param)
+                       : base (param)
+               {
+               }
+
+               public BtlsX509VerifyParam Copy ()
+               {
+                       return new BtlsX509VerifyParam (Instance.Copy ());
+               }
+
+               public void SetName (string name)
+               {
+                       Instance.SetName (name);
+               }
+
+               public void SetHost (string name)
+               {
+                       Instance.SetHost (name);
+               }
+
+               public void AddHost (string name)
+               {
+                       Instance.AddHost (name);
+               }
+
+               public BtlsX509VerifyFlags GetFlags ()
+               {
+                       return (BtlsX509VerifyFlags)Instance.GetFlags ();
+               }
+
+               public void SetFlags (BtlsX509VerifyFlags flags)
+               {
+                       Instance.SetFlags ((ulong)flags);
+               }
+
+               public void SetPurpose (BtlsX509Purpose purpose)
+               {
+                       Instance.SetPurpose ((MonoBtlsX509Purpose)purpose);
+               }
+
+               public int GetDepth ()
+               {
+                       return Instance.GetDepth ();
+               }
+
+               public void SetDepth (int depth)
+               {
+                       Instance.SetDepth (depth);
+               }
+
+               public void SetTime (DateTime time)
+               {
+                       Instance.SetTime (time);
+               }
+       }
+}
+
diff --git a/mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/VersionInfo.cs b/mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/VersionInfo.cs
new file mode 100644 (file)
index 0000000..726c4ba
--- /dev/null
@@ -0,0 +1,34 @@
+//
+// VersionInfo.cs
+//
+// Author:
+//       Martin Baulig <martin.baulig@xamarin.com>
+//
+// Copyright (c) 2016 Xamarin Inc. (http://www.xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+using System;
+namespace Mono.Btls.Interface
+{
+       public static class VersionInfo
+       {
+               public const string Version = "1.0.0";
+       }
+}
+
diff --git a/mcs/class/Mono.Btls.Interface/Properties/AssemblyInfo.cs b/mcs/class/Mono.Btls.Interface/Properties/AssemblyInfo.cs
new file mode 100644 (file)
index 0000000..5ff0bcb
--- /dev/null
@@ -0,0 +1,47 @@
+//
+// AssemblyInfo.cs
+//
+// Author:
+//       Martin Baulig <martin.baulig@xamarin.com>
+//
+// Copyright (c) 2016 Xamarin Inc. (http://www.xamarin.com)
+
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+using System;
+using System.Reflection;
+using System.Resources;
+using System.Security;
+using System.Security.Permissions;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about the system assembly
+
+[assembly: AssemblyVersion (Consts.FxVersion)]
+
+[assembly: AssemblyCompany ("MONO development team")]
+[assembly: AssemblyCopyright ("(c) 2016 Xamarin")]
+[assembly: AssemblyDescription ("Mono.Btls.Interface")]
+[assembly: AssemblyProduct ("MONO CLI")]
+[assembly: AssemblyTitle ("Mono.Btls.Interface")]
+[assembly: CLSCompliant (true)]
+[assembly: ComVisible (false)]
+[assembly: NeutralResourcesLanguage ("en-US")]
+
diff --git a/mcs/class/Mono.Btls.Interface/README.md b/mcs/class/Mono.Btls.Interface/README.md
new file mode 100644 (file)
index 0000000..81e169c
--- /dev/null
@@ -0,0 +1,9 @@
+Mono.Btls.Interface
+===================
+
+The purpose of this assembly is to allow test suites such as xamarin/web-tests
+(https://github.com/xamarin/web-tests/tree/stable) to test parts of BTLS without
+making System.dll internals visible.
+
+It should not be considered a stable and maintained API for third parties.
+
index a80606ef6681ab5fb206f56beb846e816f5bc309..6ed83d7c1e03020ffe63c8d68f4d129ec468b6bd 100644 (file)
@@ -74,5 +74,7 @@ using System.Runtime.InteropServices;
        [assembly: StringFreezing]
        [assembly: DefaultDependency (LoadHint.Always)]
 
+       [assembly: InternalsVisibleTo ("btls-cert-sync, PublicKey=002400000480000094000000060200000024000052534131000400000100010079159977d2d03a8e6bea7a2e74e8d1afcc93e8851974952bb480a12c9134474d04062447c37e0e68c080536fcf3c3fbe2ff9c979ce998475e506e8ce82dd5b0f350dc10e93bf2eeecf874b24770c5081dbea7447fddafa277b22de47d6ffea449674a4f9fccf84d15069089380284dbdd35f46cdff12a1bd78e4ef0065d016df")]
+       [assembly: InternalsVisibleTo ("Mono.Btls.Interface, PublicKey=002400000480000094000000060200000024000052534131000400000100010079159977d2d03a8e6bea7a2e74e8d1afcc93e8851974952bb480a12c9134474d04062447c37e0e68c080536fcf3c3fbe2ff9c979ce998475e506e8ce82dd5b0f350dc10e93bf2eeecf874b24770c5081dbea7447fddafa277b22de47d6ffea449674a4f9fccf84d15069089380284dbdd35f46cdff12a1bd78e4ef0065d016df")]
        [assembly: InternalsVisibleTo ("Mono.Security, PublicKey=002400000480000094000000060200000024000052534131000400000100010079159977d2d03a8e6bea7a2e74e8d1afcc93e8851974952bb480a12c9134474d04062447c37e0e68c080536fcf3c3fbe2ff9c979ce998475e506e8ce82dd5b0f350dc10e93bf2eeecf874b24770c5081dbea7447fddafa277b22de47d6ffea449674a4f9fccf84d15069089380284dbdd35f46cdff12a1bd78e4ef0065d016df")]
 
diff --git a/mcs/class/System/Mono.Btls/MonoBtlsBio.cs b/mcs/class/System/Mono.Btls/MonoBtlsBio.cs
new file mode 100644 (file)
index 0000000..1fbe471
--- /dev/null
@@ -0,0 +1,449 @@
+//
+// MonoBtlsBio.cs
+//
+// Author:
+//       Martin Baulig <martin.baulig@xamarin.com>
+//
+// Copyright (c) 2016 Xamarin Inc. (http://www.xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+#if SECURITY_DEP
+using System;
+using System.IO;
+using System.Text;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+#if MONOTOUCH
+using MonoTouch;
+#endif
+
+namespace Mono.Btls
+{
+       class MonoBtlsBio : MonoBtlsObject
+       {
+               internal MonoBtlsBio (BoringBioHandle handle)
+                       : base (handle)
+               {
+               }
+
+               new protected internal BoringBioHandle Handle {
+                       get { return (BoringBioHandle)base.Handle; }
+               }
+
+               protected internal class BoringBioHandle : MonoBtlsHandle
+               {
+                       public BoringBioHandle (IntPtr handle)
+                               : base (handle, true)
+                       {
+                       }
+
+                       protected override bool ReleaseHandle ()
+                       {
+                               if (handle != IntPtr.Zero) {
+                                       mono_btls_bio_free (handle);
+                                       handle = IntPtr.Zero;
+                               }
+                               return true;
+                       }
+
+               }
+
+               public static MonoBtlsBio CreateMonoStream (Stream stream)
+               {
+                       return MonoBtlsBioMono.CreateStream (stream, false);
+               }
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static int mono_btls_bio_read (IntPtr bio, IntPtr data, int len);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static int mono_btls_bio_write (IntPtr bio, IntPtr data, int len);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static int mono_btls_bio_flush (IntPtr bio);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static int mono_btls_bio_indent (IntPtr bio, uint indent, uint max_indent);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static int mono_btls_bio_hexdump (IntPtr bio, IntPtr data, int len, uint indent);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static void mono_btls_bio_print_errors (IntPtr bio);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static void mono_btls_bio_free (IntPtr handle);
+
+               public int Read (byte[] buffer, int offset, int size)
+               {
+                       CheckThrow ();
+                       var data = Marshal.AllocHGlobal (size);
+                       if (data == IntPtr.Zero)
+                               throw new OutOfMemoryException ();
+
+                       bool release = false;
+                       try {
+                               Handle.DangerousAddRef (ref release);
+                               var ret = mono_btls_bio_read (Handle.DangerousGetHandle (), data, size);
+                               if (ret > 0)
+                                       Marshal.Copy (data, buffer,offset, ret);
+                               return ret;
+                       } finally {
+                               if (release)
+                                       Handle.DangerousRelease ();
+                               Marshal.FreeHGlobal (data);
+                       }
+               }
+
+               public int Write (byte[] buffer, int offset, int size)
+               {
+                       CheckThrow ();
+                       var data = Marshal.AllocHGlobal (size);
+                       if (data == IntPtr.Zero)
+                               throw new OutOfMemoryException ();
+
+                       bool release = false;
+                       try {
+                               Handle.DangerousAddRef (ref release);
+                               Marshal.Copy (buffer, offset, data, size);
+                               return mono_btls_bio_write (Handle.DangerousGetHandle (), data, size);
+                       } finally {
+                               if (release)
+                                       Handle.DangerousRelease ();
+                               Marshal.FreeHGlobal (data);
+                       }
+               }
+
+               public int Flush ()
+               {
+                       CheckThrow ();
+                       bool release = false;
+                       try {
+                               Handle.DangerousAddRef (ref release);
+                               return mono_btls_bio_flush (Handle.DangerousGetHandle ());
+                       } finally {
+                               if (release)
+                                       Handle.DangerousRelease ();
+                       }
+               }
+
+               public int Indent (uint indent, uint max_indent)
+               {
+                       CheckThrow ();
+                       bool release = false;
+                       try {
+                               Handle.DangerousAddRef (ref release);
+                               return mono_btls_bio_indent (Handle.DangerousGetHandle (), indent, max_indent);
+                       } finally {
+                               if (release)
+                                       Handle.DangerousRelease ();
+                       }
+               }
+
+               public int HexDump (byte[] buffer, uint indent)
+               {
+                       CheckThrow ();
+                       var data = Marshal.AllocHGlobal (buffer.Length);
+                       if (data == IntPtr.Zero)
+                               throw new OutOfMemoryException ();
+
+                       bool release = false;
+                       try {
+                               Handle.DangerousAddRef (ref release);
+                               Marshal.Copy (buffer, 0, data, buffer.Length);
+                               return mono_btls_bio_hexdump (Handle.DangerousGetHandle (), data, buffer.Length, indent);
+                       } finally {
+                               if (release)
+                                       Handle.DangerousRelease ();
+                               Marshal.FreeHGlobal (data);
+                       }
+               }
+
+               public void PrintErrors ()
+               {
+                       CheckThrow ();
+                       bool release = false;
+                       try {
+                               Handle.DangerousAddRef (ref release);
+                               mono_btls_bio_print_errors (Handle.DangerousGetHandle ());
+                       } finally {
+                               if (release)
+                                       Handle.DangerousRelease ();
+                       }
+               }
+       }
+
+       class MonoBtlsBioMemory : MonoBtlsBio
+       {
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static IntPtr mono_btls_bio_mem_new ();
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static int mono_btls_bio_mem_get_data (IntPtr handle, out IntPtr data);
+
+               public MonoBtlsBioMemory ()
+                       : base (new BoringBioHandle (mono_btls_bio_mem_new ()))
+               {
+               }
+
+               public byte[] GetData ()
+               {
+                       IntPtr data;
+                       bool release = false;
+                       try {
+                               Handle.DangerousAddRef (ref release);
+                               var size = mono_btls_bio_mem_get_data (Handle.DangerousGetHandle (), out data);
+                               CheckError (size > 0);
+                               var buffer = new byte[size];
+                               Marshal.Copy (data, buffer, 0, size);
+                               return buffer;
+                       } finally {
+                               if (release)
+                                       Handle.DangerousRelease ();
+                       }
+               }
+       }
+
+       interface IMonoBtlsBioMono
+       {
+               int Read (byte[] buffer, int offset, int size, out bool wantMore);
+
+               bool Write (byte[] buffer, int offset, int size);
+
+               void Flush ();
+
+               void Close ();
+       }
+
+       class MonoBtlsBioMono : MonoBtlsBio
+       {
+               GCHandle handle;
+               IntPtr instance;
+               BioReadFunc readFunc;
+               BioWriteFunc writeFunc;
+               BioControlFunc controlFunc;
+               IntPtr readFuncPtr;
+               IntPtr writeFuncPtr;
+               IntPtr controlFuncPtr;
+               IMonoBtlsBioMono backend;
+
+               public MonoBtlsBioMono (IMonoBtlsBioMono backend)
+                       : base (new BoringBioHandle (mono_btls_bio_mono_new ()))
+               {
+                       this.backend = backend;
+                       handle = GCHandle.Alloc (this);
+                       instance = GCHandle.ToIntPtr (handle);
+                       readFunc = OnRead;
+                       writeFunc = OnWrite;
+                       controlFunc = Control;
+                       readFuncPtr = Marshal.GetFunctionPointerForDelegate (readFunc);
+                       writeFuncPtr = Marshal.GetFunctionPointerForDelegate (writeFunc);
+                       controlFuncPtr = Marshal.GetFunctionPointerForDelegate (controlFunc);
+                       mono_btls_bio_mono_initialize (Handle.DangerousGetHandle (), instance, readFuncPtr, writeFuncPtr, controlFuncPtr);
+               }
+
+               public static MonoBtlsBioMono CreateStream (Stream stream, bool ownsStream)
+               {
+                       return new MonoBtlsBioMono (new StreamBackend (stream, ownsStream));
+               }
+
+               public static MonoBtlsBioMono CreateString (StringWriter writer)
+               {
+                       return new MonoBtlsBioMono (new StringBackend (writer));
+               }
+
+               enum ControlCommand
+               {
+                       Flush = 1
+               }
+
+               delegate int BioReadFunc (IntPtr bio, IntPtr data, int dataLength, out int wantMore);
+               delegate int BioWriteFunc (IntPtr bio, IntPtr data, int dataLength);
+               delegate long BioControlFunc (IntPtr bio, ControlCommand command, long arg);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static IntPtr mono_btls_bio_mono_new ();
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static void mono_btls_bio_mono_initialize (IntPtr handle, IntPtr instance, IntPtr readFunc, IntPtr writeFunc, IntPtr controlFunc);
+
+               long Control (ControlCommand command, long arg)
+               {
+                       switch (command) {
+                       case ControlCommand.Flush:
+                               backend.Flush ();
+                               return 1;
+
+                       default:
+                               throw new NotImplementedException ();
+                       }
+               }
+
+               int OnRead (IntPtr data, int dataLength, out int wantMore)
+               {
+                       bool wantMoreBool;
+                       var buffer = new byte[dataLength];
+                       var ret = backend.Read (buffer, 0, dataLength, out wantMoreBool);
+                       wantMore = wantMoreBool ? 1 : 0;
+                       if (ret <= 0)
+                               return ret;
+                       Marshal.Copy (buffer, 0, data, ret);
+                       return ret;
+               }
+
+#if MONOTOUCH
+               [MonoPInvokeCallback (typeof (BioReadFunc))]
+#endif
+               static int OnRead (IntPtr instance, IntPtr data, int dataLength, out int wantMore)
+               {
+                       var c = (MonoBtlsBioMono)GCHandle.FromIntPtr (instance).Target;
+                       try {
+                               return c.OnRead (data, dataLength, out wantMore);
+                       } catch (Exception ex) {
+                               c.SetException (ex);
+                               wantMore = 0;
+                               return -1;
+                       }
+               }
+
+               int OnWrite (IntPtr data, int dataLength)
+               {
+                       var buffer = new byte[dataLength];
+                       Marshal.Copy (data, buffer, 0, dataLength);
+                       var ok = backend.Write (buffer, 0, dataLength);
+                       return ok ? dataLength : -1;
+               }
+
+#if MONOTOUCH
+               [MonoPInvokeCallback (typeof (BioWriteFunc))]
+#endif
+               static int OnWrite (IntPtr instance, IntPtr data, int dataLength)
+               {
+                       var c = (MonoBtlsBioMono)GCHandle.FromIntPtr (instance).Target;
+                       try {
+                               return c.OnWrite (data, dataLength);
+                       } catch (Exception ex) {
+                               c.SetException (ex);
+                               return -1;
+                       }
+               }
+
+#if MONOTOUCH
+               [MonoPInvokeCallback (typeof (BioControlFunc))]
+#endif
+               static long Control (IntPtr instance, ControlCommand command, long arg)
+               {
+                       var c = (MonoBtlsBioMono)GCHandle.FromIntPtr (instance).Target;
+                       try {
+                               return c.Control (command, arg);
+                       } catch (Exception ex) {
+                               c.SetException (ex);
+                               return -1;
+                       }
+               }
+
+               protected override void Close ()
+               {
+                       try {
+                               if (backend != null) {
+                                       backend.Close ();
+                                       backend = null;
+                               }
+                               if (handle.IsAllocated)
+                                       handle.Free ();
+                       } finally {
+                               base.Close ();
+                       }
+               }
+
+               class StreamBackend : IMonoBtlsBioMono
+               {
+                       Stream stream;
+                       bool ownsStream;
+
+                       public Stream InnerStream {
+                               get { return stream; }
+                       }
+
+                       public StreamBackend (Stream stream, bool ownsStream)
+                       {
+                               this.stream = stream;
+                               this.ownsStream = ownsStream;
+                       }
+
+                       public int Read (byte[] buffer, int offset, int size, out bool wantMore)
+                       {
+                               wantMore = false;
+                               return stream.Read (buffer, offset, size);
+                       }
+
+                       public bool Write (byte[] buffer, int offset, int size)
+                       {
+                               stream.Write (buffer, offset, size);
+                               return true;
+                       }
+
+                       public void Flush ()
+                       {
+                               stream.Flush ();
+                       }
+
+                       public void Close ()
+                       {
+                               if (ownsStream && stream != null)
+                                       stream.Dispose ();
+                               stream = null;
+                       }
+               }
+
+               class StringBackend : IMonoBtlsBioMono
+               {
+                       StringWriter writer;
+                       Encoding encoding = new UTF8Encoding ();
+
+                       public StringBackend (StringWriter writer)
+                       {
+                               this.writer = writer;
+                       }
+
+                       public int Read (byte[] buffer, int offset, int size, out bool wantMore)
+                       {
+                               wantMore = false;
+                               return -1;
+                       }
+
+                       public bool Write (byte[] buffer, int offset, int size)
+                       {
+                               var text = encoding.GetString (buffer, offset, size);
+                               writer.Write (text);
+                               return true;
+                       }
+
+                       public void Flush ()
+                       {
+                       }
+
+                       public void Close ()
+                       {
+                       }
+               }
+       }
+}
+#endif
diff --git a/mcs/class/System/Mono.Btls/MonoBtlsContext.cs b/mcs/class/System/Mono.Btls/MonoBtlsContext.cs
new file mode 100644 (file)
index 0000000..f40107b
--- /dev/null
@@ -0,0 +1,455 @@
+//
+// MonoBtlsContext.cs
+//
+// Author:
+//       Martin Baulig <martin.baulig@xamarin.com>
+//
+// Copyright (c) 2016 Xamarin Inc. (http://www.xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+#if SECURITY_DEP
+#if MONO_SECURITY_ALIAS
+extern alias MonoSecurity;
+#endif
+
+using System;
+using System.IO;
+using System.Threading;
+using System.Threading.Tasks;
+using System.Security.Cryptography.X509Certificates;
+using System.Security.Authentication;
+using System.Runtime.InteropServices;
+
+#if MONO_SECURITY_ALIAS
+using MonoSecurity::Mono.Security.Interface;
+#else
+using Mono.Security.Interface;
+#endif
+
+using MNS = Mono.Net.Security;
+
+namespace Mono.Btls
+{
+       class MonoBtlsContext : MNS.MobileTlsContext, IMonoBtlsBioMono
+       {
+               X509Certificate remoteCertificate;
+               X509Certificate clientCertificate;
+               X509CertificateImplBtls nativeServerCertificate;
+               X509CertificateImplBtls nativeClientCertificate;
+               MonoBtlsSslCtx ctx;
+               MonoBtlsSsl ssl;
+               MonoBtlsBio bio;
+               MonoBtlsBio errbio;
+
+               MonoTlsConnectionInfo connectionInfo;
+               bool certificateValidated;
+               bool isAuthenticated;
+               bool connected;
+
+               public MonoBtlsContext (
+                       MNS.MobileAuthenticatedStream parent,
+                       bool serverMode, string targetHost,
+                       SslProtocols enabledProtocols, X509Certificate serverCertificate,
+                       X509CertificateCollection clientCertificates, bool askForClientCert)
+                       : base (parent, serverMode, targetHost, enabledProtocols,
+                               serverCertificate, clientCertificates, askForClientCert)
+               {
+                       if (serverMode)
+                               nativeServerCertificate = GetPrivateCertificate (serverCertificate);
+               }
+
+               static X509CertificateImplBtls GetPrivateCertificate (X509Certificate certificate)
+               {
+                       var impl = certificate.Impl as X509CertificateImplBtls;
+                       if (impl != null)
+                               return (X509CertificateImplBtls)impl.Clone ();
+
+                       var password = Guid.NewGuid ().ToString ();
+                       var buffer = certificate.Export (X509ContentType.Pfx, password);
+
+                       impl = new X509CertificateImplBtls ();
+                       impl.Import (buffer, password, X509KeyStorageFlags.DefaultKeySet);
+                       return impl;
+               }
+
+               new public MonoBtlsProvider Provider {
+                       get { return (MonoBtlsProvider)base.Provider; }
+               }
+
+               int VerifyCallback (MonoBtlsX509StoreCtx storeCtx)
+               {
+                       using (var chainImpl = new X509ChainImplBtls (storeCtx))
+                       using (var managedChain = new X509Chain (chainImpl)) {
+                               var leaf = managedChain.ChainElements[0].Certificate;
+                               var result = ValidateCertificate (leaf, managedChain);
+                               certificateValidated = true;
+                               return result ? 1 : 0;
+                       }
+               }
+
+               int SelectCallback ()
+               {
+                       Debug ("SELECT CALLBACK!");
+
+                       GetPeerCertificate ();
+                       if (remoteCertificate == null)
+                               throw new TlsException (AlertDescription.InternalError, "Cannot request client certificate before receiving one from the server.");
+
+                       var clientCert = SelectClientCertificate (remoteCertificate, null);
+                       Debug ("SELECT CALLBACK #1: {0}", clientCert);
+                       if (clientCert == null)
+                               return 1;
+
+                       nativeClientCertificate = GetPrivateCertificate (clientCert);
+                       Debug ("SELECT CALLBACK #2: {0}", nativeClientCertificate);
+                       clientCertificate = new X509Certificate (nativeClientCertificate);
+                       SetPrivateCertificate (nativeClientCertificate);
+                       return 1;
+               }
+
+               public override void StartHandshake ()
+               {
+                       InitializeConnection ();
+
+                       ssl = new MonoBtlsSsl (ctx);
+
+                       bio = new MonoBtlsBioMono (this);
+                       ssl.SetBio (bio);
+
+                       if (IsServer) {
+                               SetPrivateCertificate (nativeServerCertificate);
+                       }
+               }
+
+               void SetPrivateCertificate (X509CertificateImplBtls privateCert)
+               {
+                       Debug ("SetPrivateCertificate: {0}", privateCert);
+                       ssl.SetCertificate (privateCert.X509);
+                       ssl.SetPrivateKey (privateCert.NativePrivateKey);
+                       var intermediate = privateCert.IntermediateCertificates;
+                       if (intermediate == null)
+                               return;
+                       for (int i = 0; i < intermediate.Count; i++) {
+                               var impl = (X509CertificateImplBtls)intermediate [i];
+                               Debug ("SetPrivateCertificate - add intermediate: {0}", impl);
+                               ssl.AddIntermediateCertificate (impl.X509);
+                       }
+               }
+
+               Exception GetException (MonoBtlsSslError status)
+               {
+                       var error = MonoBtlsError.GetError ();
+                       if (error == null)
+                               return new MonoBtlsException (status);
+
+                       var text = MonoBtlsError.GetErrorString (error);
+                       return new MonoBtlsException ("{0} {1}", status, text);
+               }
+
+               public override bool ProcessHandshake ()
+               {
+                       var done = false;
+                       while (!done) {
+                               Debug ("ProcessHandshake");
+                               MonoBtlsError.ClearError ();
+                               var status = DoProcessHandshake ();
+                               Debug ("ProcessHandshake #1: {0}", status);
+
+                               switch (status) {
+                               case MonoBtlsSslError.None:
+                                       if (connected)
+                                               done = true;
+                                       else
+                                               connected = true;
+                                       break;
+                               case MonoBtlsSslError.WantRead:
+                               case MonoBtlsSslError.WantWrite:
+                                       return false;
+                               default:
+                                       throw GetException (status);
+                               }
+                       }
+
+                       ssl.PrintErrors ();
+
+                       return true;
+               }
+
+               MonoBtlsSslError DoProcessHandshake ()
+               {
+                       if (connected)
+                               return ssl.Handshake ();
+                       else if (IsServer)
+                               return ssl.Accept ();
+                       else
+                               return ssl.Connect ();
+               }
+
+               public override void FinishHandshake ()
+               {
+                       InitializeSession ();
+
+                       isAuthenticated = true;
+               }
+
+               void SetupCertificateStore ()
+               {
+#if MONODROID
+                       ctx.CertificateStore.SetDefaultPaths ();
+                       ctx.CertificateStore.AddAndroidLookup ();
+#else
+                       var userPath = MonoBtlsX509StoreManager.GetStorePath (MonoBtlsX509StoreType.UserTrustedRoots);
+                       if (Directory.Exists (userPath))
+                               ctx.CertificateStore.AddDirectoryLookup (userPath, MonoBtlsX509FileType.PEM);
+                       var machinePath = MonoBtlsX509StoreManager.GetStorePath (MonoBtlsX509StoreType.MachineTrustedRoots);
+                       if (Directory.Exists (machinePath))
+                               ctx.CertificateStore.AddDirectoryLookup (machinePath, MonoBtlsX509FileType.PEM);
+#endif
+
+                       if (Settings != null && Settings.TrustAnchors != null) {
+                               var trust = IsServer ? MonoBtlsX509TrustKind.TRUST_CLIENT : MonoBtlsX509TrustKind.TRUST_SERVER;
+                               ctx.CertificateStore.AddCollection (Settings.TrustAnchors, trust);
+                       }
+               }
+
+               void InitializeConnection ()
+               {
+                       ctx = new MonoBtlsSslCtx ();
+
+#if MARTIN_DEBUG
+                       errbio = MonoBtlsBio.CreateMonoStream (Console.OpenStandardError ());
+                       ctx.SetDebugBio (errbio);
+#endif
+
+                       SetupCertificateStore ();
+
+                       if (!IsServer || AskForClientCertificate)
+                               ctx.SetVerifyCallback (VerifyCallback, false);
+                       if (!IsServer)
+                               ctx.SetSelectCallback (SelectCallback);
+
+                       ctx.SetVerifyParam (MonoBtlsProvider.GetVerifyParam (TargetHost, IsServer));
+
+                       TlsProtocolCode minProtocol, maxProtocol;
+                       GetProtocolVersions (out minProtocol, out maxProtocol);
+
+                       ctx.SetMinVersion ((int)minProtocol);
+                       ctx.SetMaxVersion ((int)maxProtocol);
+
+                       if (Settings != null && Settings.EnabledCiphers != null) {
+                               var ciphers = new short [Settings.EnabledCiphers.Length];
+                               for (int i = 0; i < ciphers.Length; i++)
+                                       ciphers [i] = (short)Settings.EnabledCiphers [i];
+                               ctx.SetCiphers (ciphers, true);
+                       }
+               }
+
+               void GetPeerCertificate ()
+               {
+                       if (remoteCertificate != null)
+                               return;
+                       using (var remoteCert = ssl.GetPeerCertificate ()) {
+                               if (remoteCert != null)
+                                       remoteCertificate = MonoBtlsProvider.CreateCertificate (remoteCert);
+                       }
+               }
+
+               void InitializeSession ()
+               {
+                       GetPeerCertificate ();
+
+                       if (IsServer && AskForClientCertificate && !certificateValidated) {
+                               if (!ValidateCertificate (null, null))
+                                       throw new TlsException (AlertDescription.CertificateUnknown);
+                       }
+
+                       var cipher = (CipherSuiteCode)ssl.GetCipher ();
+                       var protocol = (TlsProtocolCode)ssl.GetVersion ();
+                       Debug ("GET CONNECTION INFO: {0:x}:{0} {1:x}:{1} {2}", cipher, protocol, (TlsProtocolCode)protocol);
+
+                       connectionInfo = new MonoTlsConnectionInfo {
+                               CipherSuiteCode = cipher,
+                               ProtocolVersion = GetProtocol (protocol)
+                       };
+               }
+
+               static TlsProtocols GetProtocol (TlsProtocolCode protocol)
+               {
+                       switch (protocol) {
+                       case TlsProtocolCode.Tls10:
+                               return TlsProtocols.Tls10;
+                       case TlsProtocolCode.Tls11:
+                               return TlsProtocols.Tls11;
+                       case TlsProtocolCode.Tls12:
+                               return TlsProtocols.Tls12;
+                       default:
+                               throw new NotSupportedException ();
+                       }
+               }
+
+               public override void Flush ()
+               {
+                       throw new NotImplementedException ();
+               }
+
+               public override int Read (byte[] buffer, int offset, int size, out bool wantMore)
+               {
+                       Debug ("Read: {0} {1} {2}", buffer.Length, offset, size);
+
+                       var data = Marshal.AllocHGlobal (size);
+                       if (data == IntPtr.Zero)
+                               throw new OutOfMemoryException ();
+
+                       try {
+                               MonoBtlsError.ClearError ();
+                               var status = ssl.Read (data, ref size);
+                               Debug ("Read done: {0} {1}", status, size);
+
+                               if (status == MonoBtlsSslError.WantRead) {
+                                       wantMore = true;
+                                       return 0;
+                               } else if (status != MonoBtlsSslError.None) {
+                                       throw GetException (status);
+                               }
+
+                               if (size > 0)
+                                       Marshal.Copy (data, buffer, offset, size);
+
+                               wantMore = false;
+                               return size;
+                       } finally {
+                               Marshal.FreeHGlobal (data);
+                       }
+               }
+
+               public override int Write (byte[] buffer, int offset, int size, out bool wantMore)
+               {
+                       Debug ("Write: {0} {1} {2}", buffer.Length, offset, size);
+
+                       var data = Marshal.AllocHGlobal (size);
+                       if (data == IntPtr.Zero)
+                               throw new OutOfMemoryException ();
+
+                       try {
+                               MonoBtlsError.ClearError ();
+                               Marshal.Copy (buffer, offset, data, size);
+                               var status = ssl.Write (data, ref size);
+                               Debug ("Write done: {0} {1}", status, size);
+
+                               if (status == MonoBtlsSslError.WantWrite) {
+                                       wantMore = true;
+                                       return 0;
+                               } else if (status != MonoBtlsSslError.None) {
+                                       throw GetException (status);
+                               }
+
+                               wantMore = false;
+                               return size;
+                       } finally {
+                               Marshal.FreeHGlobal (data);
+                       }
+               }
+
+               public override void Close ()
+               {
+                       Debug ("Close!");
+                       ssl.Dispose ();
+               }
+
+               void Dispose<T> (ref T disposable)
+                       where T : class, IDisposable
+               {
+                       try {
+                               if (disposable != null)
+                                       disposable.Dispose ();
+                       } catch {
+                               ;
+                       } finally {
+                               disposable = null;
+                       }
+               }
+
+               protected override void Dispose (bool disposing)
+               {
+                       try {
+                               if (disposing) {
+                                       Dispose (ref remoteCertificate);
+                                       Dispose (ref nativeServerCertificate);
+                                       Dispose (ref nativeClientCertificate);
+                                       Dispose (ref clientCertificate);
+                                       Dispose (ref ctx);
+                                       Dispose (ref ssl);
+                                       Dispose (ref bio);
+                                       Dispose (ref errbio);
+                               }
+                       } finally {
+                               base.Dispose (disposing);
+                       }
+               }
+
+               int IMonoBtlsBioMono.Read (byte[] buffer, int offset, int size, out bool wantMore)
+               {
+                       Debug ("InternalRead: {0} {1}", offset, size);
+                       var ret = Parent.InternalRead (buffer, offset, size, out wantMore);
+                       Debug ("InternalReadDone: {0} {1}", ret, wantMore);
+                       return ret;
+               }
+
+               bool IMonoBtlsBioMono.Write (byte[] buffer, int offset, int size)
+               {
+                       Debug ("InternalWrite: {0} {1}", offset, size);
+                       var ret = Parent.InternalWrite (buffer, offset, size);
+                       Debug ("InternalWrite done: {0}", ret);
+                       return ret;
+               }
+
+               void IMonoBtlsBioMono.Flush ()
+               {
+                       ;
+               }
+
+               void IMonoBtlsBioMono.Close ()
+               {
+                       ;
+               }
+
+               public override bool HasContext {
+                       get { return ssl != null && ssl.IsValid; }
+               }
+               public override bool IsAuthenticated {
+                       get { return isAuthenticated; }
+               }
+               public override MonoTlsConnectionInfo ConnectionInfo {
+                       get { return connectionInfo; }
+               }
+               internal override bool IsRemoteCertificateAvailable {
+                       get { return remoteCertificate != null; }
+               }
+               internal override X509Certificate LocalClientCertificate {
+                       get { return clientCertificate; }
+               }
+               public override X509Certificate RemoteCertificate {
+                       get { return remoteCertificate; }
+               }
+               public override TlsProtocols NegotiatedProtocol {
+                       get { return connectionInfo.ProtocolVersion; }
+               }
+       }
+}
+#endif
diff --git a/mcs/class/System/Mono.Btls/MonoBtlsError.cs b/mcs/class/System/Mono.Btls/MonoBtlsError.cs
new file mode 100644 (file)
index 0000000..2645a92
--- /dev/null
@@ -0,0 +1,83 @@
+//
+// MonoBtlsError.cs
+//
+// Author:
+//       Martin Baulig <martin.baulig@xamarin.com>
+//
+// Copyright (c) 2015 Xamarin Inc. (http://www.xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+// #if SECURITY_DEP
+using System;
+using System.IO;
+using System.Text;
+using System.Runtime.InteropServices;
+using System.Runtime.CompilerServices;
+
+#if MONOTOUCH
+using MonoTouch;
+#endif
+
+namespace Mono.Btls
+{
+       static class MonoBtlsError
+       {
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static int mono_btls_error_peek_error ();
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static int mono_btls_error_get_error ();
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static void mono_btls_error_clear_error ();
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static void mono_btls_error_get_error_string_n (int error, IntPtr buf, int len);
+
+               public static int PeekError ()
+               {
+                       return mono_btls_error_peek_error ();
+               }
+
+               public static int GetError ()
+               {
+                       return mono_btls_error_get_error ();
+               }
+
+               public static void ClearError ()
+               {
+                       mono_btls_error_clear_error ();
+               }
+
+               public static string GetErrorString (int error)
+               {
+                       var size = 1024;
+                       var buffer = Marshal.AllocHGlobal (size);
+                       if (buffer == IntPtr.Zero)
+                               throw new OutOfMemoryException ();
+                       try {
+                               mono_btls_error_get_error_string_n (error, buffer, size);
+                               return Marshal.PtrToStringAnsi (buffer);
+                       } finally {
+                               Marshal.FreeHGlobal (buffer);
+                       }
+               }
+       }
+}
+// #endif
diff --git a/mcs/class/System/Mono.Btls/MonoBtlsException.cs b/mcs/class/System/Mono.Btls/MonoBtlsException.cs
new file mode 100644 (file)
index 0000000..bf6b163
--- /dev/null
@@ -0,0 +1,53 @@
+//
+// MonoBtlsException.cs
+//
+// Author:
+//       Martin Baulig <martin.baulig@xamarin.com>
+//
+// Copyright (c) 2016 Xamarin Inc. (http://www.xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+#if SECURITY_DEP
+using System;
+
+namespace Mono.Btls
+{
+       class MonoBtlsException : Exception
+       {
+               public MonoBtlsException ()
+               {
+               }
+
+               public MonoBtlsException (MonoBtlsSslError error)
+                       : base (error.ToString ())
+               {
+               }
+
+               public MonoBtlsException (string message)
+                       : base (message)
+               {
+               }
+
+               public MonoBtlsException (string format, params object[] args)
+                       : base (string.Format (format, args))
+               {
+               }
+       }
+}
+#endif
diff --git a/mcs/class/System/Mono.Btls/MonoBtlsKey.cs b/mcs/class/System/Mono.Btls/MonoBtlsKey.cs
new file mode 100644 (file)
index 0000000..d7c802d
--- /dev/null
@@ -0,0 +1,106 @@
+//
+// MonoBtlsKey.cs
+//
+// Author:
+//       Martin Baulig <martin.baulig@xamarin.com>
+//
+// Copyright (c) 2016 Xamarin Inc. (http://www.xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+#if SECURITY_DEP
+using System;
+using System.IO;
+using System.Text;
+using System.Runtime.InteropServices;
+using System.Runtime.CompilerServices;
+
+namespace Mono.Btls
+{
+       class MonoBtlsKey : MonoBtlsObject
+       {
+               internal class BoringKeyHandle : MonoBtlsHandle
+               {
+                       internal BoringKeyHandle (IntPtr handle)
+                               : base (handle, true)
+                       {
+                       }
+
+                       protected override bool ReleaseHandle ()
+                       {
+                               mono_btls_key_free (handle);
+                               return true;
+                       }
+               }
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static void mono_btls_key_free (IntPtr handle);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static IntPtr mono_btls_key_up_ref (IntPtr handle);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static int mono_btls_key_get_bytes (IntPtr handle, out IntPtr data, out int size, int include_private_bits);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static int mono_btls_key_get_bits (IntPtr handle);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static int mono_btls_key_is_rsa (IntPtr handle);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static int mono_btls_key_test (IntPtr handle);
+
+               new internal BoringKeyHandle Handle {
+                       get { return (BoringKeyHandle)base.Handle; }
+               }
+
+               internal MonoBtlsKey (BoringKeyHandle handle)
+                       : base (handle)
+               {
+               }
+
+               public byte[] GetBytes (bool include_private_bits)
+               {
+                       int size;
+                       IntPtr data;
+
+                       var ret = mono_btls_key_get_bytes (Handle.DangerousGetHandle (), out data, out size, include_private_bits ? 1 : 0);
+                       CheckError (ret);
+
+                       var buffer = new byte [size];
+                       Marshal.Copy (data, buffer, 0, size);
+                       FreeDataPtr (data);
+                       return buffer;
+               }
+
+               public void Test ()
+               {
+                       mono_btls_key_test (Handle.DangerousGetHandle ());
+               }
+
+               public MonoBtlsKey Copy ()
+               {
+                       CheckThrow ();
+                       var copy = mono_btls_key_up_ref (Handle.DangerousGetHandle ());
+                       CheckError (copy != IntPtr.Zero);
+                       return new MonoBtlsKey (new BoringKeyHandle (copy));
+               }
+       }
+}
+#endif
diff --git a/mcs/class/System/Mono.Btls/MonoBtlsObject.cs b/mcs/class/System/Mono.Btls/MonoBtlsObject.cs
new file mode 100644 (file)
index 0000000..8f30543
--- /dev/null
@@ -0,0 +1,143 @@
+//
+// MonoBtlsObject.cs
+//
+// Author:
+//       Martin Baulig <martin.baulig@xamarin.com>
+//
+// Copyright (c) 2016 Xamarin Inc. (http://www.xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+#if SECURITY_DEP
+using System;
+using System.Threading;
+using System.Runtime.InteropServices;
+using System.Runtime.CompilerServices;
+
+namespace Mono.Btls
+{
+       abstract class MonoBtlsObject : IDisposable
+       {
+               internal MonoBtlsObject (MonoBtlsHandle handle)
+               {
+                       this.handle = handle;
+               }
+
+               protected internal abstract class MonoBtlsHandle : SafeHandle
+               {
+                       internal MonoBtlsHandle ()
+                               : base (IntPtr.Zero, true)
+                       {
+                       }
+
+                       internal MonoBtlsHandle (IntPtr handle, bool ownsHandle)
+                               : base (handle, ownsHandle)
+                       {
+                       }
+
+                       public override bool IsInvalid {
+                               get { return handle == IntPtr.Zero; }
+                       }
+               }
+
+               internal MonoBtlsHandle Handle {
+                       get {
+                               CheckThrow ();
+                               return handle;
+                       }
+               }
+
+               public bool IsValid {
+                       get { return handle != null && !handle.IsInvalid; }
+               }
+
+               MonoBtlsHandle handle;
+               Exception lastError;
+
+               protected void CheckThrow ()
+               {
+                       if (lastError != null)
+                               throw lastError;
+                       if (handle == null || handle.IsInvalid)
+                               throw new ObjectDisposedException ("MonoBtlsSsl");
+               }
+
+               protected Exception SetException (Exception ex)
+               {
+                       if (lastError == null)
+                               lastError = ex;
+                       return ex;
+               }
+
+               protected void CheckError (bool ok, [CallerMemberName] string callerName = null)
+               {
+                       if (!ok) {
+                               if (callerName != null)
+                                       throw new MonoBtlsException ("{0}.{1} failed.", GetType ().Name, callerName);
+                               else
+                                       throw new MonoBtlsException ();
+                       }
+
+               }
+
+               protected void CheckError (int ret, [CallerMemberName] string callerName = null)
+               {
+                       CheckError (ret == 1, callerName);
+               }
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static void mono_btls_free (IntPtr data);
+
+               protected void FreeDataPtr (IntPtr data)
+               {
+                       mono_btls_free (data);
+               }
+
+               protected virtual void Close ()
+               {
+               }
+
+               protected void Dispose (bool disposing)
+               {
+                       if (disposing) {
+                               try {
+                                       if (handle != null) {
+                                               Close ();
+                                               handle.Dispose ();
+                                               handle = null;
+                                       }
+                               } finally {
+                                       var disposedExc = new ObjectDisposedException (GetType ().Name);
+                                       Interlocked.CompareExchange (ref lastError, disposedExc, null);
+                               }
+                       }
+               }
+
+               public void Dispose ()
+               {
+                       Dispose (true);
+                       GC.SuppressFinalize (this);
+               }
+
+               ~MonoBtlsObject ()
+               {
+                       Dispose (false);
+               }
+       }
+}
+#endif
diff --git a/mcs/class/System/Mono.Btls/MonoBtlsPkcs12.cs b/mcs/class/System/Mono.Btls/MonoBtlsPkcs12.cs
new file mode 100644 (file)
index 0000000..93ea137
--- /dev/null
@@ -0,0 +1,144 @@
+//
+// MonoBtlsPkcs12.cs
+//
+// Author:
+//       Martin Baulig <martin.baulig@xamarin.com>
+//
+// Copyright (c) 2015 Xamarin Inc. (http://www.xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+#if SECURITY_DEP
+using System;
+using System.IO;
+using System.Security.Cryptography.X509Certificates;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+namespace Mono.Btls
+{
+       class MonoBtlsPkcs12 : MonoBtlsObject
+       {
+               internal class BoringPkcs12Handle : MonoBtlsHandle
+               {
+                       public BoringPkcs12Handle (IntPtr handle)
+                               : base (handle, true)
+                       {
+                       }
+
+                       protected override bool ReleaseHandle ()
+                       {
+                               mono_btls_pkcs12_free (handle);
+                               return true;
+                       }
+               }
+
+               new internal BoringPkcs12Handle Handle {
+                       get { return (BoringPkcs12Handle)base.Handle; }
+               }
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static void mono_btls_pkcs12_free (IntPtr handle);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static IntPtr mono_btls_pkcs12_new ();
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static int mono_btls_pkcs12_get_count (IntPtr handle);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static IntPtr mono_btls_pkcs12_get_cert (IntPtr Handle, int index);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static int mono_btls_pkcs12_add_cert (IntPtr chain, IntPtr x509);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern unsafe static int mono_btls_pkcs12_import (IntPtr chain, void* data, int len, IntPtr password);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static int mono_btls_pkcs12_has_private_key (IntPtr pkcs12);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static IntPtr mono_btls_pkcs12_get_private_key (IntPtr pkcs12);
+
+               internal MonoBtlsPkcs12 ()
+                       : base (new BoringPkcs12Handle (mono_btls_pkcs12_new ()))
+               {
+               }
+
+               internal MonoBtlsPkcs12 (BoringPkcs12Handle handle)
+                       : base (handle)
+               {
+               }
+
+               MonoBtlsKey privateKey;
+
+               public int Count {
+                       get { return mono_btls_pkcs12_get_count (Handle.DangerousGetHandle ()); }
+               }
+
+               public MonoBtlsX509 GetCertificate (int index)
+               {
+                       if (index >= Count)
+                               throw new IndexOutOfRangeException ();
+                       var handle = mono_btls_pkcs12_get_cert (Handle.DangerousGetHandle (), index);
+                       CheckError (handle != IntPtr.Zero);
+                       return new MonoBtlsX509 (new MonoBtlsX509.BoringX509Handle (handle));
+               }
+
+               public void AddCertificate (MonoBtlsX509 x509)
+               {
+                       mono_btls_pkcs12_add_cert (
+                               Handle.DangerousGetHandle (),
+                               x509.Handle.DangerousGetHandle ());
+               }
+
+               public unsafe void Import (byte[] buffer, string password)
+               {
+                       var passptr = IntPtr.Zero;
+                       fixed (void* ptr = buffer)
+                       try {
+                               passptr = Marshal.StringToHGlobalAnsi (password ?? string.Empty);
+                               var ret = mono_btls_pkcs12_import (
+                                       Handle.DangerousGetHandle (), ptr,
+                                       buffer.Length, passptr);
+                               CheckError (ret);
+                       } finally {
+                               if (passptr != IntPtr.Zero)
+                                       Marshal.FreeHGlobal (passptr);
+                       }
+               }
+
+               public bool HasPrivateKey {
+                       get { return mono_btls_pkcs12_has_private_key (Handle.DangerousGetHandle ()) != 0; }
+               }
+
+               public MonoBtlsKey GetPrivateKey ()
+               {
+                       if (!HasPrivateKey)
+                               throw new InvalidOperationException ();
+                       if (privateKey == null) {
+                               var handle = mono_btls_pkcs12_get_private_key (Handle.DangerousGetHandle ());
+                               CheckError (handle != IntPtr.Zero);
+                               privateKey = new MonoBtlsKey (new MonoBtlsKey.BoringKeyHandle (handle));
+                       }
+                       return privateKey;
+               }
+       }
+}
+#endif
diff --git a/mcs/class/System/Mono.Btls/MonoBtlsProvider.cs b/mcs/class/System/Mono.Btls/MonoBtlsProvider.cs
new file mode 100644 (file)
index 0000000..fd3f2be
--- /dev/null
@@ -0,0 +1,268 @@
+//
+// MonoBtlsProvider.cs
+//
+// Author:
+//       Martin Baulig <martin.baulig@xamarin.com>
+//
+// Copyright (c) 2016 Xamarin Inc. (http://www.xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+#if SECURITY_DEP
+#if MONO_SECURITY_ALIAS
+extern alias MonoSecurity;
+#endif
+
+using System;
+using System.IO;
+using System.Threading;
+using System.Threading.Tasks;
+using System.Runtime.CompilerServices;
+using System.Security.Cryptography.X509Certificates;
+using System.Security.Authentication;
+
+#if MONO_SECURITY_ALIAS
+using MonoSecurity::Mono.Security.Interface;
+using MX = MonoSecurity::Mono.Security.X509;
+#else
+using Mono.Security.Interface;
+using MX = Mono.Security.X509;
+#endif
+
+using MNS = Mono.Net.Security;
+
+namespace Mono.Btls
+{
+       class MonoBtlsProvider : MonoTlsProvider
+       {
+               static readonly Guid id = new Guid ("432d18c9-9348-4b90-bfbf-9f2a10e1f15b");
+
+               public override Guid ID {
+                       get { return id; }
+               }
+               public override string Name {
+                       get { return "btls"; }
+               }
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               public extern static bool IsSupported ();
+
+               internal MonoBtlsProvider ()
+               {
+                       if (!IsSupported ())
+                               throw new NotSupportedException ("BTLS is not supported in this runtime.");
+               }
+
+               public override bool SupportsSslStream {
+                       get { return true; }
+               }
+
+               public override bool SupportsMonoExtensions {
+                       get { return true; }
+               }
+
+               public override bool SupportsConnectionInfo {
+                       get { return true; }
+               }
+
+               public override SslProtocols SupportedProtocols {
+                       get { return SslProtocols.Tls12 | SslProtocols.Tls11 | SslProtocols.Tls; }
+               }
+
+               public override IMonoSslStream CreateSslStream (
+                       Stream innerStream, bool leaveInnerStreamOpen,
+                       MonoTlsSettings settings = null)
+               {
+                       return new MonoBtlsStream (
+                               innerStream, leaveInnerStreamOpen, settings, this);
+               }
+
+               internal override bool HasNativeCertificates {
+                       get { return true; }
+               }
+
+               internal override X509Certificate2Impl GetNativeCertificate (
+                       byte[] data, string password, X509KeyStorageFlags flags)
+               {
+                       var impl = new X509CertificateImplBtls (true);
+                       impl.Import (data, password, flags);
+                       return impl;
+               }
+
+               internal override X509Certificate2Impl GetNativeCertificate (
+                       X509Certificate certificate)
+               {
+                       var impl = certificate.Impl as X509CertificateImplBtls;
+                       if (impl != null)
+                               return (X509Certificate2Impl)impl.Clone ();
+
+                       var data = certificate.GetRawCertData ();
+                       return new X509CertificateImplBtls (data, MonoBtlsX509Format.DER, false);
+               }
+
+               internal static MonoBtlsX509VerifyParam GetVerifyParam (string targetHost, bool serverMode)
+               {
+                       MonoBtlsX509VerifyParam param;
+                       if (serverMode)
+                               param = MonoBtlsX509VerifyParam.GetSslClient ();
+                       else
+                               param = MonoBtlsX509VerifyParam.GetSslServer ();
+
+                       if (string.IsNullOrEmpty (targetHost))
+                               return param;
+
+                       try {
+                               var copy = param.Copy ();
+                               copy.SetHost (targetHost);
+                               return copy;
+                       } finally {
+                               param.Dispose ();
+                       }
+               }
+
+               internal override bool ValidateCertificate (
+                       ICertificateValidator2 validator, string targetHost, bool serverMode,
+                       X509CertificateCollection certificates, bool wantsChain, ref X509Chain chain,
+                       ref MonoSslPolicyErrors errors, ref int status11)
+               {
+                       if (chain != null) {
+                               var chainImpl = (X509ChainImplBtls)chain.Impl;
+                               var success = chainImpl.StoreCtx.VerifyResult == 1;
+                               CheckValidationResult (
+                                       validator, targetHost, serverMode, certificates,
+                                       wantsChain, chain, chainImpl.StoreCtx,
+                                       success, ref errors, ref status11);
+                               return success;
+                       }
+
+                       using (var store = new MonoBtlsX509Store ())
+                       using (var nativeChain = MonoBtlsProvider.GetNativeChain (certificates))
+                       using (var param = GetVerifyParam (targetHost, serverMode))
+                       using (var storeCtx = new MonoBtlsX509StoreCtx ()) {
+                               store.LoadLocations (null, GetSystemStoreLocation ());
+                               store.SetDefaultPaths ();
+
+                               storeCtx.Initialize (store, nativeChain);
+
+                               storeCtx.SetVerifyParam (param);
+
+                               var ret = storeCtx.Verify ();
+
+                               var success = ret == 1;
+
+                               if (wantsChain && chain == null) {
+                                       chain = GetManagedChain (nativeChain);
+                               }
+
+                               CheckValidationResult (
+                                       validator, targetHost, serverMode, certificates,
+                                       wantsChain, null, storeCtx,
+                                       success, ref errors, ref status11);
+                               return success;
+                       }
+               }
+
+               void CheckValidationResult (
+                       ICertificateValidator validator, string targetHost, bool serverMode,
+                       X509CertificateCollection certificates, bool wantsChain,
+                       X509Chain chain, MonoBtlsX509StoreCtx storeCtx,
+                       bool success, ref MonoSslPolicyErrors errors, ref int status11)
+               {
+                       if (!success) {
+                               errors = MonoSslPolicyErrors.RemoteCertificateChainErrors;
+                               status11 = unchecked((int)0x800B010B);
+                       }
+               }
+
+               public static string GetSystemStoreLocation ()
+               {
+#if ANDROID
+                       return "/system/etc/security/cacerts";
+#else
+                       var appData = Environment.GetFolderPath (Environment.SpecialFolder.ApplicationData);
+                       var path = Path.Combine (appData, ".mono", "certs", "NewTrust");
+                       return path;
+#endif
+               }
+
+               public static X509Certificate CreateCertificate (byte[] data, MonoBtlsX509Format format, bool disallowFallback = false)
+               {
+                       using (var impl = new X509CertificateImplBtls (data, format, disallowFallback)) {
+                               return new X509Certificate (impl);
+                       }
+               }
+
+               public static X509Certificate2 CreateCertificate2 (byte[] data, MonoBtlsX509Format format, bool disallowFallback = false)
+               {
+                       using (var impl = new X509CertificateImplBtls (data, format, disallowFallback)) {
+                               return new X509Certificate2 (impl);
+                       }
+               }
+
+               public static X509Certificate2 CreateCertificate2 (byte[] data, string password, bool disallowFallback = false)
+               {
+                       using (var impl = new X509CertificateImplBtls (disallowFallback)) {
+                               impl.Import (data, password, X509KeyStorageFlags.DefaultKeySet);
+                               return new X509Certificate2 (impl);
+                       }
+               }
+
+               public static X509Certificate CreateCertificate (MonoBtlsX509 x509)
+               {
+                       using (var impl = new X509CertificateImplBtls (x509, true))
+                               return new X509Certificate (impl);
+               }
+
+               public static X509Chain CreateChain ()
+               {
+                       using (var impl = new X509ChainImplBtls ())
+                               return new X509Chain (impl);
+               }
+
+               public static X509Chain GetManagedChain (MonoBtlsX509Chain chain)
+               {
+                       var impl = new X509ChainImplBtls (chain);
+                       return new X509Chain (impl);
+               }
+
+               public static MonoBtlsX509 GetBtlsCertificate (X509Certificate certificate)
+               {
+                       var impl = certificate.Impl as X509CertificateImplBtls;
+                       if (impl != null)
+                               return impl.X509.Copy ();
+
+                       return MonoBtlsX509.LoadFromData (certificate.GetRawCertData (), MonoBtlsX509Format.DER);
+               }
+
+               public static MonoBtlsX509Chain GetNativeChain (X509CertificateCollection certificates)
+               {
+                       var chain = new MonoBtlsX509Chain ();
+                       try {
+                               foreach (var cert in certificates) {
+                                       using (var x509 = GetBtlsCertificate (cert))
+                                               chain.AddCertificate (x509);
+                               }
+                               return chain;
+                       } catch {
+                               chain.Dispose ();
+                               throw;
+                       }
+               }
+       }
+}
+#endif
diff --git a/mcs/class/System/Mono.Btls/MonoBtlsSsl.cs b/mcs/class/System/Mono.Btls/MonoBtlsSsl.cs
new file mode 100644 (file)
index 0000000..a9b5d87
--- /dev/null
@@ -0,0 +1,409 @@
+//
+// MonoBtlsSsl.cs
+//
+// Author:
+//       Martin Baulig <martin.baulig@xamarin.com>
+//
+// Copyright (c) 2015 Xamarin Inc. (http://www.xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+#if SECURITY_DEP
+using System;
+using System.IO;
+using System.Text;
+using System.Runtime.InteropServices;
+using System.Runtime.CompilerServices;
+
+#if MONOTOUCH
+using MonoTouch;
+#endif
+
+namespace Mono.Btls
+{
+       delegate int MonoBtlsVerifyCallback (MonoBtlsX509StoreCtx ctx);
+       delegate int MonoBtlsSelectCallback ();
+
+       class MonoBtlsSsl : MonoBtlsObject
+       {
+               internal class BoringSslHandle : MonoBtlsHandle
+               {
+                       public BoringSslHandle (IntPtr handle)
+                               : base (handle, true)
+                       {
+                       }
+
+                       protected override bool ReleaseHandle ()
+                       {
+                               mono_btls_ssl_destroy (handle);
+                               return true;
+                       }
+               }
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static void mono_btls_ssl_destroy (IntPtr handle);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static IntPtr mono_btls_ssl_new (IntPtr handle);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static int mono_btls_ssl_use_certificate (IntPtr handle, IntPtr x509);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static int mono_btls_ssl_use_private_key (IntPtr handle, IntPtr key);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static int mono_btls_ssl_add_chain_certificate (IntPtr handle, IntPtr x509);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static int mono_btls_ssl_accept (IntPtr handle);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static int mono_btls_ssl_connect (IntPtr handle);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static int mono_btls_ssl_handshake (IntPtr handle);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static void mono_btls_ssl_close (IntPtr handle);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static void mono_btls_ssl_set_bio (IntPtr handle, IntPtr bio);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static int mono_btls_ssl_read (IntPtr handle, IntPtr data, int len);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static int mono_btls_ssl_write (IntPtr handle, IntPtr data, int len);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static int mono_btls_ssl_get_error (IntPtr handle, int ret_code);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static void mono_btls_ssl_test (IntPtr handle);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static int mono_btls_ssl_get_version (IntPtr handle);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static void mono_btls_ssl_set_min_version (IntPtr handle, int version);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static void mono_btls_ssl_set_max_version (IntPtr handle, int version);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static int mono_btls_ssl_get_cipher (IntPtr handle);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static int mono_btls_ssl_get_ciphers (IntPtr handle, out IntPtr data);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static IntPtr mono_btls_ssl_get_peer_certificate (IntPtr handle);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static int mono_btls_ssl_set_cipher_list (IntPtr handle, IntPtr str);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static void mono_btls_ssl_print_errors_cb (IntPtr func, IntPtr ctx);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static int mono_btls_ssl_set_verify_param (IntPtr handle, IntPtr param);
+
+               static BoringSslHandle Create_internal (MonoBtlsSslCtx ctx)
+               {
+                       var handle = mono_btls_ssl_new (ctx.Handle.DangerousGetHandle ());
+                       if (handle == IntPtr.Zero)
+                               throw new MonoBtlsException ();
+                       return new BoringSslHandle (handle);
+               }
+
+               PrintErrorsCallbackFunc printErrorsFunc;
+               IntPtr printErrorsFuncPtr;
+
+               public MonoBtlsSsl (MonoBtlsSslCtx ctx)
+                       : base (Create_internal (ctx))
+               {
+                       printErrorsFunc = PrintErrorsCallback;
+                       printErrorsFuncPtr = Marshal.GetFunctionPointerForDelegate (printErrorsFunc);
+               }
+
+               new internal BoringSslHandle Handle {
+                       get { return (BoringSslHandle)base.Handle; }
+               }
+
+               public void SetBio (MonoBtlsBio bio)
+               {
+                       CheckThrow ();
+                       mono_btls_ssl_set_bio (
+                               Handle.DangerousGetHandle (),
+                               bio.Handle.DangerousGetHandle ());
+               }
+
+               Exception ThrowError ([CallerMemberName] string callerName = null)
+               {
+                       string errors;
+                       try {
+                               if (callerName == null)
+                                       callerName = GetType ().Name;
+                               errors = GetErrors ();
+                       } catch {
+                               errors = null;
+                       }
+
+                       if (errors != null) {
+                               Console.Error.WriteLine ("ERROR: {0} failed: {1}", callerName, errors);
+                               throw new MonoBtlsException ("{0} failed: {1}.", callerName, errors);
+                       } else {
+                               Console.Error.WriteLine ("ERROR: {0} failed.", callerName);
+                               throw new MonoBtlsException ("{0} failed.", callerName);
+                       }
+               }
+
+               MonoBtlsSslError GetError (int ret_code)
+               {
+                       CheckThrow ();
+                       var error = mono_btls_ssl_get_error (
+                               Handle.DangerousGetHandle (), ret_code);
+                       return (MonoBtlsSslError)error;
+               }
+
+               public void SetCertificate (MonoBtlsX509 x509)
+               {
+                       CheckThrow ();
+
+                       var ret = mono_btls_ssl_use_certificate (
+                               Handle.DangerousGetHandle (),
+                               x509.Handle.DangerousGetHandle ());
+                       if (ret <= 0)
+                               throw ThrowError ();
+               }
+
+               public void SetPrivateKey (MonoBtlsKey key)
+               {
+                       CheckThrow ();
+
+                       var ret = mono_btls_ssl_use_private_key (
+                               Handle.DangerousGetHandle (),
+                               key.Handle.DangerousGetHandle ());
+                       if (ret <= 0)
+                               throw ThrowError ();
+               }
+
+               public void AddIntermediateCertificate (MonoBtlsX509 x509)
+               {
+                       CheckThrow ();
+
+                       var ret = mono_btls_ssl_add_chain_certificate (
+                               Handle.DangerousGetHandle (),
+                               x509.Handle.DangerousGetHandle ());
+                       if (ret <= 0)
+                               throw ThrowError ();
+               }
+
+               public MonoBtlsSslError Accept ()
+               {
+                       CheckThrow ();
+
+                       var ret = mono_btls_ssl_accept (Handle.DangerousGetHandle ());
+
+                       var error = GetError (ret);
+                       return error;
+               }
+
+               public MonoBtlsSslError Connect ()
+               {
+                       CheckThrow ();
+
+                       var ret = mono_btls_ssl_connect (Handle.DangerousGetHandle ());
+
+                       var error = GetError (ret);
+                       return error;
+               }
+
+               public MonoBtlsSslError Handshake ()
+               {
+                       CheckThrow ();
+
+                       var ret = mono_btls_ssl_handshake (Handle.DangerousGetHandle ());
+
+                       var error = GetError (ret);
+                       return error;
+               }
+
+               delegate int PrintErrorsCallbackFunc (IntPtr str, IntPtr len, IntPtr ctx);
+
+#if MONOTOUCH
+               [MonoPInvokeCallback (typeof (PrintErrorsCallbackFunc))]
+#endif
+               static int PrintErrorsCallback (IntPtr str, IntPtr len, IntPtr ctx)
+               {
+                       var sb = (StringBuilder)GCHandle.FromIntPtr (ctx).Target;
+                       try {
+                               var text = Marshal.PtrToStringAnsi (str, (int)len);
+                               sb.Append (text);
+                               return 1;
+                       } catch {
+                               return 0;
+                       }
+               }
+
+               public string GetErrors ()
+               {
+                       var text = new StringBuilder ();
+                       var handle = GCHandle.Alloc (text);
+
+                       try {
+                               mono_btls_ssl_print_errors_cb (printErrorsFuncPtr, GCHandle.ToIntPtr (handle));
+                               return text.ToString ();
+                       } finally {
+                               if (handle.IsAllocated)
+                                       handle.Free ();
+                       }
+               }
+
+               public void PrintErrors ()
+               {
+                       var errors = GetErrors ();
+                       if (string.IsNullOrEmpty (errors))
+                               return;
+                       Console.Error.WriteLine (errors);
+               }
+
+               public MonoBtlsSslError Read (IntPtr data, ref int dataSize)
+               {
+                       CheckThrow ();
+                       var ret = mono_btls_ssl_read (
+                               Handle.DangerousGetHandle (), data, dataSize);
+
+                       if (ret >= 0) {
+                               dataSize = ret;
+                               return MonoBtlsSslError.None;
+                       }
+
+                       var error = mono_btls_ssl_get_error (
+                               Handle.DangerousGetHandle (), ret);
+                       dataSize = 0;
+                       return (MonoBtlsSslError)error;
+               }
+
+               public MonoBtlsSslError Write (IntPtr data, ref int dataSize)
+               {
+                       CheckThrow ();
+                       var ret = mono_btls_ssl_write (
+                               Handle.DangerousGetHandle (), data, dataSize);
+
+                       if (ret >= 0) {
+                               dataSize = ret;
+                               return MonoBtlsSslError.None;
+                       }
+
+                       var error = mono_btls_ssl_get_error (
+                               Handle.DangerousGetHandle (), ret);
+                       dataSize = 0;
+                       return (MonoBtlsSslError)error;
+               }
+
+               public int GetVersion ()
+               {
+                       CheckThrow ();
+                       return mono_btls_ssl_get_version (Handle.DangerousGetHandle ());
+               }
+
+               public void SetMinVersion (int version)
+               {
+                       CheckThrow ();
+                       mono_btls_ssl_set_min_version (Handle.DangerousGetHandle (), version);
+               }
+
+               public void SetMaxVersion (int version)
+               {
+                       CheckThrow ();
+                       mono_btls_ssl_set_max_version (Handle.DangerousGetHandle (), version);
+               }
+
+               public int GetCipher ()
+               {
+                       CheckThrow ();
+                       var cipher = mono_btls_ssl_get_cipher (Handle.DangerousGetHandle ());
+                       CheckError (cipher > 0);
+                       return cipher;
+               }
+
+               public short[] GetCiphers ()
+               {
+                       CheckThrow ();
+                       IntPtr data;
+                       var count = mono_btls_ssl_get_ciphers (
+                               Handle.DangerousGetHandle (), out data);
+                       CheckError (count > 0);
+                       try {
+                               short[] ciphers = new short[count];
+                               Marshal.Copy (data, ciphers, 0, count);
+                               return ciphers;
+                       } finally {
+                               FreeDataPtr (data);
+                       }
+               }
+
+               public void SetCipherList (string str)
+               {
+                       CheckThrow ();
+                       IntPtr strPtr = IntPtr.Zero;
+                       try {
+                               strPtr = Marshal.StringToHGlobalAnsi (str);
+                               var ret = mono_btls_ssl_set_cipher_list (
+                                       Handle.DangerousGetHandle (), strPtr);
+                               CheckError (ret);
+                       } finally {
+                               if (strPtr != IntPtr.Zero)
+                                       Marshal.FreeHGlobal (strPtr);
+                       }
+               }
+
+               public MonoBtlsX509 GetPeerCertificate ()
+               {
+                       CheckThrow ();
+                       var x509 = mono_btls_ssl_get_peer_certificate (
+                               Handle.DangerousGetHandle ());
+                       if (x509 == IntPtr.Zero)
+                               return null;
+                       return new MonoBtlsX509 (new MonoBtlsX509.BoringX509Handle (x509));
+               }
+
+               public void SetVerifyParam (MonoBtlsX509VerifyParam param)
+               {
+                       CheckThrow ();
+                       var ret = mono_btls_ssl_set_verify_param (
+                               Handle.DangerousGetHandle (),
+                               param.Handle.DangerousGetHandle ());
+                       CheckError (ret);
+               }
+
+               public void Test ()
+               {
+                       CheckThrow ();
+                       mono_btls_ssl_test (Handle.DangerousGetHandle ());
+               }
+
+               protected override void Close ()
+               {
+                       mono_btls_ssl_close (Handle.DangerousGetHandle ());
+               }
+       }
+}
+#endif
diff --git a/mcs/class/System/Mono.Btls/MonoBtlsSslCtx.cs b/mcs/class/System/Mono.Btls/MonoBtlsSslCtx.cs
new file mode 100644 (file)
index 0000000..517b158
--- /dev/null
@@ -0,0 +1,260 @@
+//
+// MonoBtlsSslCtx.cs
+//
+// Author:
+//       Martin Baulig <martin.baulig@xamarin.com>
+//
+// Copyright (c) 2016 Xamarin Inc. (http://www.xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+#if SECURITY_DEP
+using System;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+#if MONOTOUCH
+using MonoTouch;
+#endif
+
+namespace Mono.Btls
+{
+       class MonoBtlsSslCtx : MonoBtlsObject
+       {
+               internal class BoringSslCtxHandle : MonoBtlsHandle
+               {
+                       public BoringSslCtxHandle (IntPtr handle)
+                               : base (handle, true)
+                       {
+                       }
+
+                       protected override bool ReleaseHandle ()
+                       {
+                               mono_btls_ssl_ctx_free (handle);
+                               return true;
+                       }
+               }
+
+               new internal BoringSslCtxHandle Handle {
+                       get { return (BoringSslCtxHandle)base.Handle; }
+               }
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static IntPtr mono_btls_ssl_ctx_new ();
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static int mono_btls_ssl_ctx_free (IntPtr handle);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static IntPtr mono_btls_ssl_ctx_up_ref (IntPtr handle);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static void mono_btls_ssl_ctx_initialize (IntPtr handle, IntPtr instance);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static void mono_btls_ssl_ctx_set_debug_bio (IntPtr handle, IntPtr bio);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static void mono_btls_ssl_ctx_set_cert_verify_callback (IntPtr handle, IntPtr func, int cert_required);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static void mono_btls_ssl_ctx_set_cert_select_callback (IntPtr handle, IntPtr func);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static void mono_btls_ssl_ctx_set_min_version (IntPtr handle, int version);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static void mono_btls_ssl_ctx_set_max_version (IntPtr handle, int version);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static int mono_btls_ssl_ctx_is_cipher_supported (IntPtr handle, short value);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static int mono_btls_ssl_ctx_set_ciphers (IntPtr handle, int count, IntPtr data, int allow_unsupported);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static int mono_btls_ssl_ctx_set_verify_param (IntPtr handle, IntPtr param);
+
+               delegate int NativeVerifyFunc (IntPtr instance, int preverify_ok, IntPtr ctx);
+               delegate int NativeSelectFunc (IntPtr instance);
+
+               NativeVerifyFunc verifyFunc;
+               NativeSelectFunc selectFunc;
+               IntPtr verifyFuncPtr;
+               IntPtr selectFuncPtr;
+               MonoBtlsVerifyCallback verifyCallback;
+               MonoBtlsSelectCallback selectCallback;
+               MonoBtlsX509Store store;
+               GCHandle instance;
+               IntPtr instancePtr;
+
+               public MonoBtlsSslCtx ()
+                       : this (new BoringSslCtxHandle (mono_btls_ssl_ctx_new ()))
+               {
+               }
+
+               internal MonoBtlsSslCtx (BoringSslCtxHandle handle)
+                       : base (handle)
+               {
+                       instance = GCHandle.Alloc (this);
+                       instancePtr = GCHandle.ToIntPtr (instance);
+                       mono_btls_ssl_ctx_initialize (
+                               handle.DangerousGetHandle (), instancePtr);
+
+                       verifyFunc = NativeVerifyCallback;
+                       selectFunc = NativeSelectCallback;
+                       verifyFuncPtr = Marshal.GetFunctionPointerForDelegate (verifyFunc);
+                       selectFuncPtr = Marshal.GetFunctionPointerForDelegate (selectFunc);
+
+                       store = new MonoBtlsX509Store (Handle);
+               }
+
+               internal MonoBtlsSslCtx Copy ()
+               {
+                       var copy = mono_btls_ssl_ctx_up_ref (Handle.DangerousGetHandle ());
+                       return new MonoBtlsSslCtx (new BoringSslCtxHandle (copy));
+               }
+
+               public MonoBtlsX509Store CertificateStore {
+                       get { return store; }
+               }
+
+               int VerifyCallback (bool preverify_ok, MonoBtlsX509StoreCtx ctx)
+               {
+                       if (verifyCallback != null)
+                               return verifyCallback (ctx);
+                       return 0;
+               }
+
+#if MONOTOUCH
+               [MonoPInvokeCallback (typeof (NativeVerifyFunc))]
+#endif
+               static int NativeVerifyCallback (IntPtr instance, int preverify_ok, IntPtr store_ctx)
+               {
+                       var c = (MonoBtlsSslCtx)GCHandle.FromIntPtr (instance).Target;
+                       using (var ctx = new MonoBtlsX509StoreCtx (preverify_ok, store_ctx)) {
+                               try {
+                                       return c.VerifyCallback (preverify_ok != 0, ctx);
+                               } catch (Exception ex) {
+                                       c.SetException (ex);
+                               }
+                       }
+                       return 0;
+               }
+
+               int SelectCallback ()
+               {
+                       if (selectCallback != null)
+                               return selectCallback ();
+                       return 1;
+               }
+
+#if MONOTOUCH
+               [MonoPInvokeCallback (typeof (NativeSelectFunc))]
+#endif
+               static int NativeSelectCallback (IntPtr instance)
+               {
+                       var c = (MonoBtlsSslCtx)GCHandle.FromIntPtr (instance).Target;
+                       try {
+                               return c.SelectCallback ();
+                       } catch (Exception ex) {
+                               c.SetException (ex);
+                               return 0;
+                       }
+               }
+
+               public void SetDebugBio (MonoBtlsBio bio)
+               {
+                       CheckThrow ();
+                       mono_btls_ssl_ctx_set_debug_bio (Handle.DangerousGetHandle (), bio.Handle.DangerousGetHandle ());
+               }
+
+               public void SetVerifyCallback (MonoBtlsVerifyCallback callback, bool client_cert_required)
+               {
+                       CheckThrow ();
+
+                       verifyCallback = callback;
+                       mono_btls_ssl_ctx_set_cert_verify_callback (
+                               Handle.DangerousGetHandle (), verifyFuncPtr,
+                               client_cert_required ? 1 : 0);
+               }
+
+               public void SetSelectCallback (MonoBtlsSelectCallback callback)
+               {
+                       CheckThrow ();
+
+                       selectCallback = callback;
+                       mono_btls_ssl_ctx_set_cert_select_callback (
+                               Handle.DangerousGetHandle (), selectFuncPtr);
+               }
+
+               public void SetMinVersion (int version)
+               {
+                       CheckThrow ();
+                       mono_btls_ssl_ctx_set_min_version (Handle.DangerousGetHandle (), version);
+               }
+
+               public void SetMaxVersion (int version)
+               {
+                       CheckThrow ();
+                       mono_btls_ssl_ctx_set_max_version (Handle.DangerousGetHandle (), version);
+               }
+
+               public bool IsCipherSupported (short value)
+               {
+                       CheckThrow ();
+                       return mono_btls_ssl_ctx_is_cipher_supported (Handle.DangerousGetHandle (), value) != 0;
+               }
+
+               public void SetCiphers (short[] ciphers, bool allow_unsupported)
+               {
+                       CheckThrow ();
+                       var data = Marshal.AllocHGlobal (ciphers.Length * 2);
+                       try {
+                               Marshal.Copy (ciphers, 0, data, ciphers.Length);
+                               var ret = mono_btls_ssl_ctx_set_ciphers (
+                                       Handle.DangerousGetHandle (),
+                                       ciphers.Length, data, allow_unsupported ? 1 : 0);
+                               CheckError (ret > 0);
+                       } finally {
+                               Marshal.FreeHGlobal (data);
+                       }
+               }
+
+               public void SetVerifyParam (MonoBtlsX509VerifyParam param)
+               {
+                       CheckThrow ();
+                       var ret = mono_btls_ssl_ctx_set_verify_param (
+                               Handle.DangerousGetHandle (),
+                               param.Handle.DangerousGetHandle ());
+                       CheckError (ret);
+               }
+
+               protected override void Close ()
+               {
+                       if (store != null) {
+                               store.Dispose ();
+                               store = null;
+                       }
+                       if (instance.IsAllocated)
+                               instance.Free ();
+                       base.Close ();
+               }
+       }
+}
+#endif
diff --git a/mcs/class/System/Mono.Btls/MonoBtlsSslError.cs b/mcs/class/System/Mono.Btls/MonoBtlsSslError.cs
new file mode 100644 (file)
index 0000000..38f6f4f
--- /dev/null
@@ -0,0 +1,47 @@
+//
+// MonoBtlsSslError.cs
+//
+// Author:
+//       Martin Baulig <martin.baulig@xamarin.com>
+//
+// Copyright (c) 2015 Xamarin Inc. (http://www.xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+#if SECURITY_DEP
+namespace Mono.Btls
+{
+       // keep in sync with boringssl/include/ssl.h
+       enum MonoBtlsSslError
+       {
+               None = 0,
+               Ssl = 1,
+               WantRead = 2,
+               WantWrite = 3,
+               WantX509Lookup = 4,
+               Syscall = 5,
+               ZeroReturn = 6,
+               WantConnect = 7,
+               WantAccept = 8,
+               WantChannelIdLookup = 9,
+               PendingSession = 11,
+               PendingCertificate = 12,
+               WantPrivateKeyOperation = 13
+       }
+}
+#endif
diff --git a/mcs/class/System/Mono.Btls/MonoBtlsStream.cs b/mcs/class/System/Mono.Btls/MonoBtlsStream.cs
new file mode 100644 (file)
index 0000000..d2f32e9
--- /dev/null
@@ -0,0 +1,65 @@
+//
+// MonoBtlsStream.cs
+//
+// Author:
+//       Martin Baulig <martin.baulig@xamarin.com>
+//
+// Copyright (c) 2016 Xamarin Inc. (http://www.xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+#if SECURITY_DEP
+#if MONO_SECURITY_ALIAS
+extern alias MonoSecurity;
+#endif
+
+using System;
+using System.IO;
+using System.Security.Authentication;
+using System.Security.Cryptography.X509Certificates;
+
+#if MONO_SECURITY_ALIAS
+using MonoSecurity::Mono.Security.Interface;
+#else
+using Mono.Security.Interface;
+#endif
+
+using MNS = Mono.Net.Security;
+
+namespace Mono.Btls
+{
+       class MonoBtlsStream : MNS.MobileAuthenticatedStream
+       {
+               public MonoBtlsStream (Stream innerStream, bool leaveInnerStreamOpen, MonoTlsSettings settings, MonoTlsProvider provider)
+                       : base (innerStream, leaveInnerStreamOpen, settings, provider)
+               {
+               }
+
+               protected override MNS.MobileTlsContext CreateContext (
+                       MNS.MobileAuthenticatedStream parent, bool serverMode, string targetHost,
+                       SslProtocols enabledProtocols, X509Certificate serverCertificate,
+                       X509CertificateCollection clientCertificates, bool askForClientCert)
+               {
+                       return new MonoBtlsContext (
+                               parent, serverMode, targetHost,
+                               enabledProtocols, serverCertificate,
+                               clientCertificates, askForClientCert);
+               }
+       }
+}
+#endif
diff --git a/mcs/class/System/Mono.Btls/MonoBtlsUtils.cs b/mcs/class/System/Mono.Btls/MonoBtlsUtils.cs
new file mode 100644 (file)
index 0000000..c3dae84
--- /dev/null
@@ -0,0 +1,186 @@
+//
+// MonoBtlsUtils.cs
+//
+// Author:
+//       Martin Baulig <martin.baulig@xamarin.com>
+//
+// Copyright (c) 2016 Xamarin Inc. (http://www.xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+#if SECURITY_DEP
+using System;
+using System.Text;
+using System.Security.Cryptography.X509Certificates;
+
+namespace Mono.Btls
+{
+       static class MonoBtlsUtils
+       {
+               static byte[] emailOid = { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01 };
+
+               public static bool Compare (byte[] a, byte[] b)
+               {
+                       if (a.Length != b.Length)
+                               return false;
+                       for (int i = 0; i < a.Length; i++) {
+                               if (a[i] != b[i])
+                                       return false;
+                       }
+                       return true;
+               }
+
+               static bool AppendEntry (StringBuilder sb, MonoBtlsX509Name name, int index, string separator, bool quotes)
+               {
+                       var type = name.GetEntryType (index);
+                       if (type < 0)
+                               return false;
+                       else if (type == 0) {
+                               var oidValue = name.GetEntryOidData (index);
+                               if (Compare (oidValue, emailOid))
+                                       type = MonoBtlsX509NameEntryType.Email;
+                       }
+                       var text = name.GetEntryValue (index);
+                       if (text == null)
+                               return false;
+                       var oid = name.GetEntryOid (index);
+                       if (oid == null)
+                               return false;
+
+                       if (sb.Length > 0)
+                               sb.Append (separator);
+
+                       switch (type) {
+                       case MonoBtlsX509NameEntryType.CountryName:
+                               sb.Append ("C=");
+                               break;
+                       case MonoBtlsX509NameEntryType.OrganizationName:
+                               sb.Append ("O=");
+                               break;
+                       case MonoBtlsX509NameEntryType.OrganizationalUnitName:
+                               sb.Append ("OU=");
+                               break;
+                       case MonoBtlsX509NameEntryType.CommonName:
+                               sb.Append ("CN=");
+                               break;
+                       case MonoBtlsX509NameEntryType.LocalityName:
+                               sb.Append ("L=");
+                               break;
+                       case MonoBtlsX509NameEntryType.StateOrProvinceName:
+                               sb.Append ("S=");       // NOTE: RFC2253 uses ST=
+                               break;
+                       case MonoBtlsX509NameEntryType.StreetAddress:
+                               sb.Append ("STREET=");
+                               break;
+                       case MonoBtlsX509NameEntryType.DomainComponent:
+                               sb.Append ("DC=");
+                               break;
+                       case MonoBtlsX509NameEntryType.UserId:
+                               sb.Append ("UID=");
+                               break;
+                       case MonoBtlsX509NameEntryType.Email:
+                               sb.Append ("E=");       // NOTE: Not part of RFC2253
+                               break;
+                       case MonoBtlsX509NameEntryType.DnQualifier:
+                               sb.Append ("dnQualifier=");
+                               break;
+                       case MonoBtlsX509NameEntryType.Title:
+                               sb.Append ("T=");
+                               break;
+                       case MonoBtlsX509NameEntryType.Surname:
+                               sb.Append ("SN=");
+                               break;
+                       case MonoBtlsX509NameEntryType.GivenName:
+                               sb.Append ("G=");
+                               break;
+                       case MonoBtlsX509NameEntryType.Initial:
+                               sb.Append ("I=");
+                               break;
+                       default:
+                               // unknown OID
+                               sb.Append ("OID.");     // NOTE: Not present as RFC2253
+                               sb.Append (oid);
+                               sb.Append ("=");
+                               break;
+                       }
+
+                       // 16bits or 8bits string ? TODO not complete (+special chars!)
+                       char[] specials = { ',', '+', '"', '\\', '<', '>', ';' };
+                       if (quotes) {
+                               if ((text.IndexOfAny (specials, 0, text.Length) > 0) ||
+                                   text.StartsWith (" ") || (text.EndsWith (" ")))
+                                       text = "\"" + text + "\"";
+                       }
+
+                       sb.Append (text);
+                       return true;
+               }
+
+               const X500DistinguishedNameFlags AllFlags = X500DistinguishedNameFlags.Reversed |
+                       X500DistinguishedNameFlags.UseSemicolons | X500DistinguishedNameFlags.DoNotUsePlusSign |
+                       X500DistinguishedNameFlags.DoNotUseQuotes | X500DistinguishedNameFlags.UseCommas |
+                       X500DistinguishedNameFlags.UseNewLines | X500DistinguishedNameFlags.UseUTF8Encoding |
+                       X500DistinguishedNameFlags.UseT61Encoding | X500DistinguishedNameFlags.ForceUTF8Encoding;
+
+               static string GetSeparator (X500DistinguishedNameFlags flag)
+               {
+                       if ((flag & X500DistinguishedNameFlags.UseSemicolons) != 0)
+                               return "; ";
+                       if ((flag & X500DistinguishedNameFlags.UseCommas) != 0)
+                               return ", ";
+                       if ((flag & X500DistinguishedNameFlags.UseNewLines) != 0)
+                               return Environment.NewLine;
+                       return ", "; //default
+               }
+
+               public static string FormatName (MonoBtlsX509Name name, X500DistinguishedNameFlags flag)
+               {
+                       if ((flag != 0) && ((flag & AllFlags) == 0))
+                               throw new ArgumentException ("flag");
+
+                       if (name.GetEntryCount () == 0)
+                               return String.Empty;
+
+                       // Mono.Security reversed isn't the same as fx 2.0 (which is the reverse of 1.x)
+                       bool reversed = ((flag & X500DistinguishedNameFlags.Reversed) != 0);
+                       bool quotes = ((flag & X500DistinguishedNameFlags.DoNotUseQuotes) == 0);
+                       string separator = GetSeparator (flag);
+
+                       return FormatName (name, reversed, separator, quotes);
+               }
+
+               public static string FormatName (MonoBtlsX509Name name, bool reversed, string separator, bool quotes)
+               {
+                       var count = name.GetEntryCount ();
+                       StringBuilder sb = new StringBuilder ();
+
+                       if (reversed) {
+                               for (int i = count - 1; i >= 0; i--) {
+                                       AppendEntry (sb, name, i, separator, quotes);
+                               }
+                       } else {
+                               for (int i = 0; i < count; i++) {
+                                       AppendEntry (sb, name, i, separator, quotes);
+                               }
+                       }
+
+                       return sb.ToString ();
+               }
+       }
+}
+#endif
diff --git a/mcs/class/System/Mono.Btls/MonoBtlsX509.cs b/mcs/class/System/Mono.Btls/MonoBtlsX509.cs
new file mode 100644 (file)
index 0000000..4d451b9
--- /dev/null
@@ -0,0 +1,465 @@
+//
+// MonoBtlsX509.cs
+//
+// Author:
+//       Martin Baulig <martin.baulig@xamarin.com>
+//
+// Copyright (c) 2016 Xamarin Inc. (http://www.xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+#if SECURITY_DEP
+using System;
+using System.IO;
+using System.Text;
+using System.Threading;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Security.Cryptography.X509Certificates;
+using System.Security.Cryptography;
+
+namespace Mono.Btls
+{
+       class MonoBtlsX509 : MonoBtlsObject
+       {
+               internal class BoringX509Handle : MonoBtlsHandle
+               {
+                       public BoringX509Handle (IntPtr handle)
+                               : base (handle, true)
+                       {
+                       }
+
+                       protected override bool ReleaseHandle ()
+                       {
+                               if (handle != IntPtr.Zero)
+                                       mono_btls_x509_free (handle);
+                               return true;
+                       }
+
+                       public IntPtr StealHandle ()
+                       {
+                               var retval = Interlocked.Exchange (ref handle, IntPtr.Zero);
+                               return retval;
+                       }
+               }
+
+               new internal BoringX509Handle Handle {
+                       get { return (BoringX509Handle)base.Handle; }
+               }
+
+               internal MonoBtlsX509 (BoringX509Handle handle) 
+                       : base (handle)
+               {
+               }
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static IntPtr mono_btls_x509_up_ref (IntPtr handle);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static IntPtr mono_btls_x509_from_data (IntPtr data, int len, MonoBtlsX509Format format);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static IntPtr mono_btls_x509_get_subject_name (IntPtr handle);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static IntPtr mono_btls_x509_get_issuer_name (IntPtr handle);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static int mono_btls_x509_get_subject_name_string (IntPtr handle, IntPtr buffer, int size);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static int mono_btls_x509_get_issuer_name_string (IntPtr handle, IntPtr buffer, int size);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static int mono_btls_x509_get_raw_data (IntPtr handle, IntPtr bio, MonoBtlsX509Format format);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static int mono_btls_x509_cmp (IntPtr a, IntPtr b);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static int mono_btls_x509_get_hash (IntPtr handle, out IntPtr data);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static long mono_btls_x509_get_not_before (IntPtr handle);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static long mono_btls_x509_get_not_after (IntPtr handle);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static int mono_btls_x509_get_public_key (IntPtr handle, IntPtr bio);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static int mono_btls_x509_get_serial_number (IntPtr handle, IntPtr data, int size, int mono_style);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static int mono_btls_x509_get_version (IntPtr handle);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static int mono_btls_x509_get_signature_algorithm (IntPtr handle, IntPtr buffer, int size);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static int mono_btls_x509_get_public_key_asn1 (IntPtr handle, IntPtr oid, int oid_size, out IntPtr data, out int size);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static int mono_btls_x509_get_public_key_parameters (IntPtr handle, IntPtr oid, int oid_size, out IntPtr data, out int size);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static IntPtr mono_btls_x509_get_pubkey (IntPtr handle);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static int mono_btls_x509_get_subject_key_identifier (IntPtr handle, out IntPtr data, out int size);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static int mono_btls_x509_print (IntPtr handle, IntPtr bio);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static void mono_btls_x509_free (IntPtr handle);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static IntPtr mono_btls_x509_dup (IntPtr handle);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static int mono_btls_x509_add_trust_object (IntPtr handle, MonoBtlsX509Purpose purpose);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static int mono_btls_x509_add_reject_object (IntPtr handle, MonoBtlsX509Purpose purpose);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static int mono_btls_x509_add_explicit_trust (IntPtr handle, MonoBtlsX509TrustKind kind);
+
+               internal MonoBtlsX509 Copy ()
+               {
+                       var copy = mono_btls_x509_up_ref (Handle.DangerousGetHandle ());
+                       CheckError (copy != IntPtr.Zero);
+                       return new MonoBtlsX509 (new BoringX509Handle (copy));
+               }
+
+               // This will actually duplicate the underlying 'X509 *' object instead of
+               // simply increasing the reference count.
+               internal MonoBtlsX509 Duplicate ()
+               {
+                       var copy = mono_btls_x509_dup (Handle.DangerousGetHandle ());
+                       CheckError (copy != IntPtr.Zero);
+                       return new MonoBtlsX509 (new BoringX509Handle (copy));
+               }
+
+               public static MonoBtlsX509 LoadFromData (byte[] buffer, MonoBtlsX509Format format)
+               {
+                       var data = Marshal.AllocHGlobal (buffer.Length);
+                       if (data == IntPtr.Zero)
+                               throw new OutOfMemoryException ();
+
+                       try {
+                               Marshal.Copy (buffer, 0, data, buffer.Length);
+                               var x509 = mono_btls_x509_from_data (data, buffer.Length, format);
+                               if (x509 == IntPtr.Zero)
+                                       throw new MonoBtlsException ("Failed to read certificate from data.");
+
+                               return new MonoBtlsX509 (new BoringX509Handle (x509));
+                       } finally {
+                               Marshal.FreeHGlobal (data);
+                       }
+               }
+
+               public MonoBtlsX509Name GetSubjectName ()
+               {
+                       var handle = mono_btls_x509_get_subject_name (Handle.DangerousGetHandle ());
+                       CheckError (handle != IntPtr.Zero);
+                       return new MonoBtlsX509Name (new MonoBtlsX509Name.BoringX509NameHandle (handle, false));
+               }
+
+               public string GetSubjectNameString ()
+               {
+                       const int size = 4096;
+                       var data = Marshal.AllocHGlobal (size);
+                       try {
+                               var ret = mono_btls_x509_get_subject_name_string (
+                                       Handle.DangerousGetHandle (), data, size);
+                               CheckError (ret);
+                               return Marshal.PtrToStringAnsi (data);
+                       } finally {
+                               Marshal.FreeHGlobal (data);
+                       }
+               }
+
+               public long GetSubjectNameHash ()
+               {
+                       CheckThrow ();
+                       using (var subject = GetSubjectName ())
+                               return subject.GetHash ();
+               }
+
+               public MonoBtlsX509Name GetIssuerName ()
+               {
+                       var handle = mono_btls_x509_get_issuer_name (Handle.DangerousGetHandle ());
+                       CheckError (handle != IntPtr.Zero);
+                       return new MonoBtlsX509Name (new MonoBtlsX509Name.BoringX509NameHandle (handle, false));
+               }
+
+               public string GetIssuerNameString ()
+               {
+                       const int size = 4096;
+                       var data = Marshal.AllocHGlobal (size);
+                       try {
+                               var ret = mono_btls_x509_get_issuer_name_string (
+                                       Handle.DangerousGetHandle (), data, size);
+                               CheckError (ret);
+                               return Marshal.PtrToStringAnsi (data);
+                       } finally {
+                               Marshal.FreeHGlobal (data);
+                       }
+               }
+
+               public byte[] GetRawData (MonoBtlsX509Format format)
+               {
+                       using (var bio = new MonoBtlsBioMemory ()) {
+                               var ret = mono_btls_x509_get_raw_data (
+                                       Handle.DangerousGetHandle (),
+                                       bio.Handle.DangerousGetHandle (),
+                                       format);
+                               CheckError (ret);
+                               return bio.GetData ();
+                       }
+               }
+
+               public void GetRawData (MonoBtlsBio bio, MonoBtlsX509Format format)
+               {
+                       CheckThrow ();
+                       var ret = mono_btls_x509_get_raw_data (
+                               Handle.DangerousGetHandle (),
+                               bio.Handle.DangerousGetHandle (),
+                               format);
+                       CheckError (ret);
+               }
+
+               public static int Compare (MonoBtlsX509 a, MonoBtlsX509 b)
+               {
+                       return mono_btls_x509_cmp (
+                               a.Handle.DangerousGetHandle (),
+                               b.Handle.DangerousGetHandle ());
+               }
+
+               public byte[] GetCertHash ()
+               {
+                       IntPtr data;
+                       var ret = mono_btls_x509_get_hash (Handle.DangerousGetHandle (), out data);
+                       CheckError (ret > 0);
+                       var buffer = new byte [ret];
+                       Marshal.Copy (data, buffer, 0, ret);
+                       return buffer;
+               }
+
+               public DateTime GetNotBefore ()
+               {
+                       var ticks = mono_btls_x509_get_not_before (Handle.DangerousGetHandle ());
+                       return new DateTime (1970, 1, 1).AddSeconds (ticks);
+               }
+
+               public DateTime GetNotAfter ()
+               {
+                       var ticks = mono_btls_x509_get_not_after (Handle.DangerousGetHandle ());
+                       return new DateTime (1970, 1, 1).AddSeconds (ticks);
+               }
+
+               public byte[] GetPublicKeyData ()
+               {
+                       using (var bio = new MonoBtlsBioMemory ()) {
+                               var ret = mono_btls_x509_get_public_key (
+                                       Handle.DangerousGetHandle (),
+                                       bio.Handle.DangerousGetHandle ());
+                               CheckError (ret > 0);
+                               return bio.GetData ();
+                       }
+               }
+
+               public byte[] GetSerialNumber (bool mono_style)
+               {
+                       int size = 256;
+                       IntPtr data = Marshal.AllocHGlobal (size);
+                       try {
+                               var ret = mono_btls_x509_get_serial_number (
+                                       Handle.DangerousGetHandle (), data,
+                                       size, mono_style ? 1 : 0);
+                               CheckError (ret > 0);
+                               var buffer = new byte [ret];
+                               Marshal.Copy (data, buffer, 0, ret);
+                               return buffer;
+                       } finally {
+                               if (data != IntPtr.Zero)
+                                       Marshal.FreeHGlobal (data);
+                       }
+               }
+
+               public int GetVersion ()
+               {
+                       return mono_btls_x509_get_version (Handle.DangerousGetHandle ());
+               }
+
+               public Oid GetSignatureAlgorithm ()
+               {
+                       int size = 256;
+                       IntPtr data = Marshal.AllocHGlobal (size);
+                       try {
+                               var ret = mono_btls_x509_get_signature_algorithm (
+                                       Handle.DangerousGetHandle (), data, size);
+                               CheckError (ret > 0);
+                               return new Oid (Marshal.PtrToStringAnsi (data));
+                       } finally {
+                               Marshal.FreeHGlobal (data);
+                       }
+               }
+
+               public AsnEncodedData GetPublicKeyAsn1 ()
+               {
+                       int size;
+                       IntPtr data;
+
+                       int oidSize = 256;
+                       var oidData = Marshal.AllocHGlobal (256);
+                       string oid;
+
+                       try {
+                               var ret = mono_btls_x509_get_public_key_asn1 (
+                                       Handle.DangerousGetHandle (), oidData, oidSize,
+                                       out data, out size);
+                               CheckError (ret);
+                               oid = Marshal.PtrToStringAnsi (oidData);
+                       } finally {
+                               Marshal.FreeHGlobal (oidData);
+                       }
+
+                       try {
+                               var buffer = new byte[size];
+                               Marshal.Copy (data, buffer, 0, size);
+                               return new AsnEncodedData (oid.ToString (), buffer);
+                       } finally {
+                               if (data != IntPtr.Zero)
+                                       FreeDataPtr (data);
+                       }
+               }
+
+               public AsnEncodedData GetPublicKeyParameters ()
+               {
+                       int size;
+                       IntPtr data;
+
+                       int oidSize = 256;
+                       var oidData = Marshal.AllocHGlobal (256);
+                       string oid;
+
+                       try {
+                               var ret = mono_btls_x509_get_public_key_parameters (
+                                       Handle.DangerousGetHandle (), oidData, oidSize,
+                                       out data, out size);
+                               CheckError (ret);
+                               oid = Marshal.PtrToStringAnsi (oidData);
+                       } finally {
+                               Marshal.FreeHGlobal (oidData);
+                       }
+
+                       try {
+                               var buffer = new byte[size];
+                               Marshal.Copy (data, buffer, 0, size);
+                               return new AsnEncodedData (oid.ToString (), buffer);
+                       } finally {
+                               if (data != IntPtr.Zero)
+                                       FreeDataPtr (data);
+                       }
+               }
+
+               public byte[] GetSubjectKeyIdentifier ()
+               {
+                       int size;
+                       IntPtr data = IntPtr.Zero;
+
+                       try {
+                               var ret = mono_btls_x509_get_subject_key_identifier (
+                                       Handle.DangerousGetHandle (), out data, out size);
+                               CheckError (ret);
+                               var buffer = new byte[size];
+                               Marshal.Copy (data, buffer, 0, size);
+                               return buffer;
+                       } finally {
+                               if (data != IntPtr.Zero)
+                                       FreeDataPtr (data);
+                       }
+               }
+
+               public MonoBtlsKey GetPublicKey ()
+               {
+                       var handle = mono_btls_x509_get_pubkey (Handle.DangerousGetHandle ());
+                       CheckError (handle != IntPtr.Zero);
+                       return new MonoBtlsKey (new MonoBtlsKey.BoringKeyHandle (handle));
+               }
+
+               public void Print (MonoBtlsBio bio)
+               {
+                       var ret = mono_btls_x509_print (
+                               Handle.DangerousGetHandle (),
+                               bio.Handle.DangerousGetHandle ());
+                       CheckError (ret);
+               }
+
+               public void ExportAsPEM (MonoBtlsBio bio, bool includeHumanReadableForm)
+               {
+                       GetRawData (bio, MonoBtlsX509Format.PEM);
+
+                       if (!includeHumanReadableForm)
+                               return;
+
+                       Print (bio);
+
+                       var hash = GetCertHash ();
+                       var output = new StringBuilder ();
+                       output.Append ("SHA1 Fingerprint=");
+                       for (int i = 0; i < hash.Length; i++) {
+                               if (i > 0)
+                                       output.Append (":");
+                               output.AppendFormat ("{0:X2}", hash [i]);
+                       }
+                       output.AppendLine ();
+                       var outputData = Encoding.ASCII.GetBytes (output.ToString ());
+                       bio.Write (outputData, 0, outputData.Length);
+               }
+
+               public void AddTrustObject (MonoBtlsX509Purpose purpose)
+               {
+                       CheckThrow ();
+                       var ret = mono_btls_x509_add_trust_object (
+                               Handle.DangerousGetHandle (), purpose);
+                       CheckError (ret);
+               }
+
+               public void AddRejectObject (MonoBtlsX509Purpose purpose)
+               {
+                       CheckThrow ();
+                       var ret = mono_btls_x509_add_reject_object (
+                               Handle.DangerousGetHandle (), purpose);
+                       CheckError (ret);
+               }
+
+               public void AddExplicitTrust (MonoBtlsX509TrustKind kind)
+               {
+                       CheckThrow ();
+                       var ret = mono_btls_x509_add_explicit_trust (
+                               Handle.DangerousGetHandle (), kind);
+                       CheckError (ret);
+               }
+       }
+}
+#endif
diff --git a/mcs/class/System/Mono.Btls/MonoBtlsX509Chain.cs b/mcs/class/System/Mono.Btls/MonoBtlsX509Chain.cs
new file mode 100644 (file)
index 0000000..6926ae7
--- /dev/null
@@ -0,0 +1,122 @@
+//
+// MonoBtlsX509Chain.cs
+//
+// Author:
+//       Martin Baulig <martin.baulig@xamarin.com>
+//
+// Copyright (c) 2016 Xamarin Inc. (http://www.xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+#if SECURITY_DEP
+using System;
+using System.IO;
+using System.Security.Cryptography.X509Certificates;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+namespace Mono.Btls
+{
+       class MonoBtlsX509Chain : MonoBtlsObject
+       {
+               internal class BoringX509ChainHandle : MonoBtlsHandle
+               {
+                       public BoringX509ChainHandle (IntPtr handle)
+                               : base (handle, true)
+                       {
+                       }
+
+                       protected override bool ReleaseHandle ()
+                       {
+                               mono_btls_x509_chain_free (handle);
+                               return true;
+                       }
+               }
+
+               new internal BoringX509ChainHandle Handle {
+                       get { return (BoringX509ChainHandle)base.Handle; }
+               }
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static IntPtr mono_btls_x509_chain_new ();
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static int mono_btls_x509_chain_get_count (IntPtr handle);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static IntPtr mono_btls_x509_chain_get_cert (IntPtr Handle, int index);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static int mono_btls_x509_chain_add_cert (IntPtr chain, IntPtr x509);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static IntPtr mono_btls_x509_chain_up_ref (IntPtr handle);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static void mono_btls_x509_chain_free (IntPtr handle);
+
+               public MonoBtlsX509Chain ()
+                       : base (new BoringX509ChainHandle (mono_btls_x509_chain_new ()))
+               {
+               }
+
+               internal MonoBtlsX509Chain (BoringX509ChainHandle handle)
+                       : base (handle)
+               {
+               }
+
+               public int Count {
+                       get { return mono_btls_x509_chain_get_count (Handle.DangerousGetHandle ()); }
+               }
+
+               public MonoBtlsX509 GetCertificate (int index)
+               {
+                       if (index >= Count)
+                               throw new IndexOutOfRangeException ();
+                       var handle = mono_btls_x509_chain_get_cert (
+                               Handle.DangerousGetHandle (), index);
+                       CheckError (handle != IntPtr.Zero);
+                       return new MonoBtlsX509 (new MonoBtlsX509.BoringX509Handle (handle));
+               }
+
+               public void Dump ()
+               {
+                       Console.Error.WriteLine ("CHAIN: {0:x} {1}", Handle, Count);
+                       for (int i = 0; i < Count; i++) {
+                               using (var cert = GetCertificate (i)) {
+                                       Console.Error.WriteLine ("  CERT #{0}: {1}", i, cert.GetSubjectNameString ());
+                               }
+                       }
+               }
+
+               public void AddCertificate (MonoBtlsX509 x509)
+               {
+                       mono_btls_x509_chain_add_cert (
+                               Handle.DangerousGetHandle (),
+                               x509.Handle.DangerousGetHandle ());
+               }
+
+               internal MonoBtlsX509Chain Copy ()
+               {
+                       var copy = mono_btls_x509_chain_up_ref (Handle.DangerousGetHandle ());
+                       CheckError (copy != IntPtr.Zero);
+                       return new MonoBtlsX509Chain (new BoringX509ChainHandle (copy));
+               }
+       }
+}
+#endif
diff --git a/mcs/class/System/Mono.Btls/MonoBtlsX509Crl.cs b/mcs/class/System/Mono.Btls/MonoBtlsX509Crl.cs
new file mode 100644 (file)
index 0000000..9b8a64f
--- /dev/null
@@ -0,0 +1,188 @@
+//
+// MonoBtlsX509Crl.cs
+//
+// Author:
+//       Martin Baulig <martin.baulig@xamarin.com>
+//
+// Copyright (c) 2016 Xamarin Inc. (http://www.xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+#if SECURITY_DEP
+using System;
+using System.IO;
+using System.Text;
+using System.Threading;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Security.Cryptography.X509Certificates;
+using System.Security.Cryptography;
+
+namespace Mono.Btls
+{
+       class MonoBtlsX509Crl : MonoBtlsObject
+       {
+               internal class BoringX509CrlHandle : MonoBtlsHandle
+               {
+                       public BoringX509CrlHandle (IntPtr handle)
+                               : base (handle, true)
+                       {
+                       }
+
+                       protected override bool ReleaseHandle ()
+                       {
+                               if (handle != IntPtr.Zero)
+                                       mono_btls_x509_crl_free (handle);
+                               return true;
+                       }
+
+                       public IntPtr StealHandle ()
+                       {
+                               var retval = Interlocked.Exchange (ref handle, IntPtr.Zero);
+                               return retval;
+                       }
+               }
+
+               new internal BoringX509CrlHandle Handle {
+                       get { return (BoringX509CrlHandle)base.Handle; }
+               }
+
+               internal MonoBtlsX509Crl (BoringX509CrlHandle handle) 
+                       : base (handle)
+               {
+               }
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static IntPtr mono_btls_x509_crl_ref (IntPtr handle);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static void mono_btls_x509_crl_test (IntPtr handle);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static IntPtr mono_btls_x509_crl_from_data (IntPtr data, int len, MonoBtlsX509Format format);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static IntPtr mono_btls_x509_crl_get_by_cert (IntPtr handle, IntPtr x509);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               unsafe extern static IntPtr mono_btls_x509_crl_get_by_serial (IntPtr handle, void *serial, int len);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static int mono_btls_x509_crl_get_revoked_count (IntPtr handle);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static IntPtr mono_btls_x509_crl_get_revoked (IntPtr handle, int index);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static long mono_btls_x509_crl_get_last_update (IntPtr handle);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static long mono_btls_x509_crl_get_next_update (IntPtr handle);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static long mono_btls_x509_crl_get_version (IntPtr handle);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static IntPtr mono_btls_x509_crl_get_issuer (IntPtr handle);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static void mono_btls_x509_crl_free (IntPtr handle);
+
+               public static MonoBtlsX509Crl LoadFromData (byte[] buffer, MonoBtlsX509Format format)
+               {
+                       var data = Marshal.AllocHGlobal (buffer.Length);
+                       if (data == IntPtr.Zero)
+                               throw new OutOfMemoryException ();
+
+                       try {
+                               Marshal.Copy (buffer, 0, data, buffer.Length);
+                               var crl = mono_btls_x509_crl_from_data (data, buffer.Length, format);
+                               if (crl == IntPtr.Zero)
+                                       throw new MonoBtlsException ("Failed to read CRL from data.");
+
+                               return new MonoBtlsX509Crl (new BoringX509CrlHandle (crl));
+                       } finally {
+                               Marshal.FreeHGlobal (data);
+                       }
+               }
+
+               public MonoBtlsX509Revoked GetByCert (MonoBtlsX509 x509)
+               {
+                       var revoked = mono_btls_x509_crl_get_by_cert (
+                               Handle.DangerousGetHandle (),
+                               x509.Handle.DangerousGetHandle ());
+                       if (revoked == IntPtr.Zero)
+                               return null;
+                       return new MonoBtlsX509Revoked (new MonoBtlsX509Revoked.BoringX509RevokedHandle (revoked));
+               }
+
+               public unsafe MonoBtlsX509Revoked GetBySerial (byte[] serial)
+               {
+                       fixed (void *ptr = serial)
+                       {
+                               var revoked = mono_btls_x509_crl_get_by_serial (
+                                       Handle.DangerousGetHandle (), ptr, serial.Length);
+                               if (revoked == IntPtr.Zero)
+                                       return null;
+                               return new MonoBtlsX509Revoked (new MonoBtlsX509Revoked.BoringX509RevokedHandle (revoked));
+                       }
+               }
+
+               public int GetRevokedCount ()
+               {
+                       return mono_btls_x509_crl_get_revoked_count (Handle.DangerousGetHandle ());
+               }
+
+               public MonoBtlsX509Revoked GetRevoked (int index)
+               {
+                       if (index >= GetRevokedCount ())
+                               throw new ArgumentOutOfRangeException ();
+
+                       var revoked = mono_btls_x509_crl_get_revoked (
+                               Handle.DangerousGetHandle (), index);
+                       if (revoked == IntPtr.Zero)
+                               return null;
+                       return new MonoBtlsX509Revoked (new MonoBtlsX509Revoked.BoringX509RevokedHandle (revoked));
+               }
+
+               public DateTime GetLastUpdate ()
+               {
+                       var ticks = mono_btls_x509_crl_get_last_update (Handle.DangerousGetHandle ());
+                       return new DateTime (1970, 1, 1).AddSeconds (ticks);
+               }
+
+               public DateTime GetNextUpdate ()
+               {
+                       var ticks = mono_btls_x509_crl_get_next_update (Handle.DangerousGetHandle ());
+                       return new DateTime (1970, 1, 1).AddSeconds (ticks);
+               }
+
+               public long GetVersion ()
+               {
+                       return mono_btls_x509_crl_get_version (Handle.DangerousGetHandle ());
+               }
+
+               public MonoBtlsX509Name GetIssuerName ()
+               {
+                       var handle = mono_btls_x509_crl_get_issuer (Handle.DangerousGetHandle ());
+                       CheckError (handle != IntPtr.Zero);
+                       return new MonoBtlsX509Name (new MonoBtlsX509Name.BoringX509NameHandle (handle, false));
+               }
+       }
+}
+#endif
diff --git a/mcs/class/System/Mono.Btls/MonoBtlsX509Error.cs b/mcs/class/System/Mono.Btls/MonoBtlsX509Error.cs
new file mode 100644 (file)
index 0000000..50196bf
--- /dev/null
@@ -0,0 +1,111 @@
+//
+// MonoBtlsX509Error.cs
+//
+// Author:
+//       Martin Baulig <martin.baulig@xamarin.com>
+//
+// Copyright (c) 2016 Xamarin Inc. (http://www.xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+#if SECURITY_DEP
+using System;
+namespace Mono.Btls
+{
+       // Keep in sync with x509_vfy.h
+       enum MonoBtlsX509Error
+       {
+               OK = 0,
+               /* illegal error (for uninitialized values, to avoid X509_V_OK): 1 */
+
+               UNABLE_TO_GET_ISSUER_CERT = 2,
+               UNABLE_TO_GET_CRL = 3,
+               UNABLE_TO_DECRYPT_CERT_SIGNATURE = 4,
+               UNABLE_TO_DECRYPT_CRL_SIGNATURE = 5,
+               UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY = 6,
+               CERT_SIGNATURE_FAILURE = 7,
+               CRL_SIGNATURE_FAILURE = 8,
+               CERT_NOT_YET_VALID = 9,
+               CERT_HAS_EXPIRED = 10,
+               CRL_NOT_YET_VALID = 11,
+               CRL_HAS_EXPIRED = 12,
+               ERROR_IN_CERT_NOT_BEFORE_FIELD = 13,
+               ERROR_IN_CERT_NOT_AFTER_FIELD = 14,
+               ERROR_IN_CRL_LAST_UPDATE_FIELD = 15,
+               ERROR_IN_CRL_NEXT_UPDATE_FIELD = 16,
+               OUT_OF_MEM = 17,
+               DEPTH_ZERO_SELF_SIGNED_CERT = 18,
+               SELF_SIGNED_CERT_IN_CHAIN = 19,
+               UNABLE_TO_GET_ISSUER_CERT_LOCALLY = 20,
+               UNABLE_TO_VERIFY_LEAF_SIGNATURE = 21,
+               CERT_CHAIN_TOO_LONG = 22,
+               CERT_REVOKED = 23,
+               INVALID_CA = 24,
+               PATH_LENGTH_EXCEEDED = 25,
+               INVALID_PURPOSE = 26,
+               CERT_UNTRUSTED = 27,
+               CERT_REJECTED = 28,
+               /* These are 'informational' when looking for issuer cert */
+               SUBJECT_ISSUER_MISMATCH = 29,
+               AKID_SKID_MISMATCH = 30,
+               AKID_ISSUER_SERIAL_MISMATCH = 31,
+               KEYUSAGE_NO_CERTSIGN = 32,
+
+               UNABLE_TO_GET_CRL_ISSUER = 33,
+               UNHANDLED_CRITICAL_EXTENSION = 34,
+               KEYUSAGE_NO_CRL_SIGN = 35,
+               UNHANDLED_CRITICAL_CRL_EXTENSION = 36,
+               INVALID_NON_CA = 37,
+               PROXY_PATH_LENGTH_EXCEEDED = 38,
+               KEYUSAGE_NO_DIGITAL_SIGNATURE = 39,
+               PROXY_CERTIFICATES_NOT_ALLOWED = 40,
+
+               INVALID_EXTENSION = 41,
+               INVALID_POLICY_EXTENSION = 42,
+               NO_EXPLICIT_POLICY = 43,
+               DIFFERENT_CRL_SCOPE = 44,
+               UNSUPPORTED_EXTENSION_FEATURE = 45,
+
+               UNNESTED_RESOURCE = 46,
+
+               PERMITTED_VIOLATION = 47,
+               EXCLUDED_VIOLATION = 48,
+               SUBTREE_MINMAX = 49,
+               UNSUPPORTED_CONSTRAINT_TYPE = 51,
+               UNSUPPORTED_CONSTRAINT_SYNTAX = 52,
+               UNSUPPORTED_NAME_SYNTAX = 53,
+               CRL_PATH_VALIDATION_ERROR = 54,
+
+               /* Suite B mode algorithm violation */
+               SUITE_B_INVALID_VERSION = 56,
+               SUITE_B_INVALID_ALGORITHM = 57,
+               SUITE_B_INVALID_CURVE = 58,
+               SUITE_B_INVALID_SIGNATURE_ALGORITHM = 59,
+               SUITE_B_LOS_NOT_ALLOWED = 60,
+               SUITE_B_CANNOT_SIGN_P_384_WITH_P_256 = 61,
+
+               /* Host, email and IP check errors */
+               HOSTNAME_MISMATCH = 62,
+               EMAIL_MISMATCH = 63,
+               IP_ADDRESS_MISMATCH = 64,
+
+               /* The application is not happy */
+               APPLICATION_VERIFICATION = 50
+       }
+}
+#endif
diff --git a/mcs/class/System/Mono.Btls/MonoBtlsX509Exception.cs b/mcs/class/System/Mono.Btls/MonoBtlsX509Exception.cs
new file mode 100644 (file)
index 0000000..588e7a7
--- /dev/null
@@ -0,0 +1,56 @@
+//
+// MonoBtlsX509Exception.cs
+//
+// Author:
+//       Martin Baulig <martin.baulig@xamarin.com>
+//
+// Copyright (c) 2016 Xamarin Inc. (http://www.xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+#if SECURITY_DEP
+using System;
+
+namespace Mono.Btls
+{
+       class MonoBtlsX509Exception : Exception
+       {
+               public MonoBtlsX509Error ErrorCode {
+                       get;
+                       private set;
+               }
+
+               public string ErrorMessage {
+                       get;
+                       private set;
+               }
+
+               public MonoBtlsX509Exception (MonoBtlsX509Error code, string message)
+                       : base (message)
+               {
+                       ErrorCode = code;
+                       ErrorMessage = message;
+               }
+
+               public override string ToString ()
+               {
+                       return string.Format ("[MonoBtlsX509Exception: ErrorCode={0}, ErrorMessage={1}]", ErrorCode, ErrorMessage);
+               }
+       }
+}
+#endif
diff --git a/mcs/class/System/Mono.Btls/MonoBtlsX509FileType.cs b/mcs/class/System/Mono.Btls/MonoBtlsX509FileType.cs
new file mode 100644 (file)
index 0000000..67d26e6
--- /dev/null
@@ -0,0 +1,37 @@
+//
+// MonoBtlsX509FileType.cs
+//
+// Author:
+//       Martin Baulig <martin.baulig@xamarin.com>
+//
+// Copyright (c) 2016 Xamarin Inc. (http://www.xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+#if SECURITY_DEP
+using System;
+namespace Mono.Btls
+{
+       enum MonoBtlsX509FileType
+       {
+               PEM = 1,
+               ASN1 = 2,
+               DEFAULT = 3
+       }
+}
+#endif
diff --git a/mcs/class/System/Mono.Btls/MonoBtlsX509Format.cs b/mcs/class/System/Mono.Btls/MonoBtlsX509Format.cs
new file mode 100644 (file)
index 0000000..551da69
--- /dev/null
@@ -0,0 +1,36 @@
+//
+// MonoBtlsX509Format.cs
+//
+// Author:
+//       Martin Baulig <martin.baulig@xamarin.com>
+//
+// Copyright (c) 2016 Xamarin Inc. (http://www.xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+#if SECURITY_DEP
+using System;
+namespace Mono.Btls
+{
+       enum MonoBtlsX509Format
+       {
+               DER = 1,
+               PEM = 2
+       }
+}
+#endif
diff --git a/mcs/class/System/Mono.Btls/MonoBtlsX509Lookup.cs b/mcs/class/System/Mono.Btls/MonoBtlsX509Lookup.cs
new file mode 100644 (file)
index 0000000..3e8fb29
--- /dev/null
@@ -0,0 +1,217 @@
+//
+// MonoBtlsX509Lookup.cs
+//
+// Author:
+//       Martin Baulig <martin.baulig@xamarin.com>
+//
+// Copyright (c) 2016 Xamarin Inc. (http://www.xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+#if SECURITY_DEP
+using System;
+using System.IO;
+using System.Runtime.InteropServices;
+using System.Runtime.CompilerServices;
+using System.Collections.Generic;
+
+namespace Mono.Btls
+{
+       class MonoBtlsX509Lookup : MonoBtlsObject
+       {
+               internal class BoringX509LookupHandle : MonoBtlsHandle
+               {
+                       public BoringX509LookupHandle (IntPtr handle)
+                               : base (handle, true)
+                       {
+                       }
+
+                       protected override bool ReleaseHandle ()
+                       {
+                               mono_btls_x509_lookup_free (handle);
+                               return true;
+                       }
+               }
+
+               new internal BoringX509LookupHandle Handle {
+                       get { return (BoringX509LookupHandle)base.Handle; }
+               }
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static IntPtr mono_btls_x509_lookup_new (IntPtr store, MonoBtlsX509LookupType type);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static int mono_btls_x509_lookup_load_file (IntPtr handle, IntPtr file, MonoBtlsX509FileType type);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static int mono_btls_x509_lookup_add_dir (IntPtr handle, IntPtr dir, MonoBtlsX509FileType type);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static int mono_btls_x509_lookup_add_mono (IntPtr handle, IntPtr monoLookup);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static void mono_btls_x509_lookup_method_mono_init (
+                       IntPtr handle, IntPtr instance, IntPtr by_subject_func);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static int mono_btls_x509_lookup_init (IntPtr handle);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static int mono_btls_x509_lookup_shutdown (IntPtr handle);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static IntPtr mono_btls_x509_lookup_by_subject (IntPtr handle, IntPtr name);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static IntPtr mono_btls_x509_lookup_by_fingerprint (IntPtr handle, IntPtr bytes, int len);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static void mono_btls_x509_lookup_free (IntPtr handle);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static IntPtr mono_btls_x509_lookup_peek_lookup (IntPtr handle);
+
+               MonoBtlsX509LookupType type;
+               List<MonoBtlsX509LookupMono> monoLookups;
+
+#if FIXME
+               // Do we need this?
+               internal MonoBtlsX509Lookup (BoringX509LookupHandle handle)
+                       : base (handle)
+               {
+               }
+#endif
+
+               static BoringX509LookupHandle Create_internal (MonoBtlsX509Store store, MonoBtlsX509LookupType type)
+               {
+                       var handle = mono_btls_x509_lookup_new (
+                               store.Handle.DangerousGetHandle (), type);
+                       if (handle == IntPtr.Zero)
+                               throw new MonoBtlsException ();
+                       return new BoringX509LookupHandle (handle);
+               }
+
+               internal MonoBtlsX509Lookup (MonoBtlsX509Store store, MonoBtlsX509LookupType type)
+                       : base (Create_internal (store, type))
+               {
+                       this.type = type;
+               }
+
+               internal IntPtr GetNativeLookup ()
+               {
+                       return mono_btls_x509_lookup_peek_lookup (Handle.DangerousGetHandle ());
+               }
+
+               public void LoadFile (string file, MonoBtlsX509FileType type)
+               {
+                       IntPtr filePtr = IntPtr.Zero;
+                       try {
+                               if (file != null)
+                                       filePtr = Marshal.StringToHGlobalAnsi (file);
+                               var ret = mono_btls_x509_lookup_load_file (
+                                       Handle.DangerousGetHandle (), filePtr, type);
+                               CheckError (ret);
+                       } finally {
+                               if (filePtr != IntPtr.Zero)
+                                       Marshal.FreeHGlobal (filePtr);
+                       }
+               }
+
+               public void AddDirectory (string dir, MonoBtlsX509FileType type)
+               {
+                       IntPtr dirPtr = IntPtr.Zero;
+                       try {
+                               if (dir != null)
+                                       dirPtr = Marshal.StringToHGlobalAnsi (dir);
+                               var ret = mono_btls_x509_lookup_add_dir (
+                                       Handle.DangerousGetHandle (), dirPtr, type);
+                               CheckError (ret);
+                       } finally {
+                               if (dirPtr != IntPtr.Zero)
+                                       Marshal.FreeHGlobal (dirPtr);
+                       }
+               }
+
+               // Takes ownership of the 'monoLookup'.
+               internal void AddMono (MonoBtlsX509LookupMono monoLookup)
+               {
+                       if (type != MonoBtlsX509LookupType.MONO)
+                               throw new NotSupportedException ();
+                       var ret = mono_btls_x509_lookup_add_mono (
+                               Handle.DangerousGetHandle (), monoLookup.Handle.DangerousGetHandle ());
+                       CheckError (ret);
+
+                       if (monoLookups == null)
+                               monoLookups = new List<MonoBtlsX509LookupMono> ();
+                       monoLookups.Add (monoLookup);
+               }
+
+               public void Initialize ()
+               {
+                       var ret = mono_btls_x509_lookup_init (Handle.DangerousGetHandle ());
+                       CheckError (ret);
+               }
+
+               public void Shutdown ()
+               {
+                       var ret = mono_btls_x509_lookup_shutdown (Handle.DangerousGetHandle ());
+                       CheckError (ret);
+               }
+
+               public MonoBtlsX509 LookupBySubject (MonoBtlsX509Name name)
+               {
+                       var handle = mono_btls_x509_lookup_by_subject (
+                               Handle.DangerousGetHandle (),
+                               name.Handle.DangerousGetHandle ());
+                       if (handle == IntPtr.Zero)
+                               return null;
+                       return new MonoBtlsX509 (new MonoBtlsX509.BoringX509Handle (handle));
+               }
+
+               public MonoBtlsX509 LookupByFingerPrint (byte[] fingerprint)
+               {
+                       var bytes = Marshal.AllocHGlobal (fingerprint.Length);
+                       try {
+                               Marshal.Copy (fingerprint, 0, bytes, fingerprint.Length);
+                               var handle = mono_btls_x509_lookup_by_fingerprint (
+                                       Handle.DangerousGetHandle (),
+                                       bytes, fingerprint.Length);
+                               if (handle == IntPtr.Zero)
+                                       return null;
+                               return new MonoBtlsX509 (new MonoBtlsX509.BoringX509Handle (handle));
+                       } finally {
+                               if (bytes != IntPtr.Zero)
+                                       Marshal.FreeHGlobal (bytes);
+                       }
+               }
+
+               protected override void Close ()
+               {
+                       try {
+                               if (monoLookups != null) {
+                                       foreach (var monoLookup in monoLookups)
+                                               monoLookup.Dispose ();
+                               monoLookups = null;
+                               }
+                       } finally {
+                               base.Close ();
+                       }
+               }
+       }
+}
+#endif
diff --git a/mcs/class/System/Mono.Btls/MonoBtlsX509LookupAndroid.cs b/mcs/class/System/Mono.Btls/MonoBtlsX509LookupAndroid.cs
new file mode 100644 (file)
index 0000000..45f365c
--- /dev/null
@@ -0,0 +1,43 @@
+//
+// MonoBtlsX509LookupAndroid.cs
+//
+// Author:
+//       Martin Baulig <martin.baulig@xamarin.com>
+//
+// Copyright (c) 2016 Xamarin Inc. (http://www.xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+#if SECURITY_DEP && MONODROID
+using System;
+using System.IO;
+using System.Runtime.InteropServices;
+using System.Runtime.CompilerServices;
+using System.Security.Cryptography.X509Certificates;
+
+namespace Mono.Btls
+{
+       internal class MonoBtlsX509LookupAndroid : MonoBtlsX509LookupMono
+       {
+               protected override MonoBtlsX509 OnGetBySubject (MonoBtlsX509Name name)
+               {
+                       return AndroidPlatform.CertStoreLookup (name);
+               }
+       }
+}
+#endif
diff --git a/mcs/class/System/Mono.Btls/MonoBtlsX509LookupMono.cs b/mcs/class/System/Mono.Btls/MonoBtlsX509LookupMono.cs
new file mode 100644 (file)
index 0000000..9dbecea
--- /dev/null
@@ -0,0 +1,128 @@
+//
+// MonoBtlsX509LookupMono.cs
+//
+// Author:
+//       Martin Baulig <martin.baulig@xamarin.com>
+//
+// Copyright (c) 2016 Xamarin Inc. (http://www.xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+#if SECURITY_DEP
+using System;
+using System.IO;
+using System.Runtime.InteropServices;
+using System.Runtime.CompilerServices;
+
+namespace Mono.Btls
+{
+       abstract class MonoBtlsX509LookupMono : MonoBtlsObject
+       {
+               internal class BoringX509LookupMonoHandle : MonoBtlsHandle
+               {
+                       public BoringX509LookupMonoHandle (IntPtr handle)
+                               : base (handle, true)
+                       {
+                       }
+
+                       protected override bool ReleaseHandle ()
+                       {
+                               mono_btls_x509_lookup_mono_free (handle);
+                               return true;
+                       }
+               }
+
+               new internal BoringX509LookupMonoHandle Handle {
+                       get { return (BoringX509LookupMonoHandle)base.Handle; }
+               }
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static IntPtr mono_btls_x509_lookup_mono_new ();
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static void mono_btls_x509_lookup_mono_init (
+                       IntPtr handle, IntPtr instance, IntPtr by_subject_func);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static int mono_btls_x509_lookup_mono_free (IntPtr handle);
+
+               delegate int BySubjectFunc (IntPtr instance, IntPtr name, out IntPtr x509_ptr);
+
+               GCHandle gch;
+               IntPtr instance;
+               BySubjectFunc bySubjectFunc;
+               IntPtr bySubjectFuncPtr;
+
+               internal MonoBtlsX509LookupMono ()
+                       : base (new BoringX509LookupMonoHandle (mono_btls_x509_lookup_mono_new ()))
+               {
+                       gch = GCHandle.Alloc (this);
+                       instance = GCHandle.ToIntPtr (gch);
+                       bySubjectFunc = OnGetBySubject;
+                       bySubjectFuncPtr = Marshal.GetFunctionPointerForDelegate (bySubjectFunc);
+                       mono_btls_x509_lookup_mono_init (Handle.DangerousGetHandle (), instance, bySubjectFuncPtr);
+               }
+
+               protected abstract MonoBtlsX509 OnGetBySubject (MonoBtlsX509Name name);
+
+#if MONOTOUCH
+               [MonoPInvokeCallback (typeof (BySubjectFunc))]
+#endif
+               static int OnGetBySubject (IntPtr instance, IntPtr name_ptr, out IntPtr x509_ptr)
+               {
+                       try {
+                               MonoBtlsX509LookupMono obj;
+                               MonoBtlsX509Name.BoringX509NameHandle name_handle = null;
+                               try {
+                                       obj = (MonoBtlsX509LookupMono)GCHandle.FromIntPtr (instance).Target;
+                                       name_handle = new MonoBtlsX509Name.BoringX509NameHandle (name_ptr, false);
+                                       MonoBtlsX509Name name_obj = new MonoBtlsX509Name (name_handle);
+                                       var x509 = obj.OnGetBySubject (name_obj);
+                                       if (x509 != null) {
+                                               x509_ptr = x509.Handle.StealHandle ();
+                                               return 1;
+                                       } else {
+                                               x509_ptr = IntPtr.Zero;
+                                               return 0;
+                                       }
+                               } finally {
+                                       if (name_handle != null)
+                                               name_handle.Dispose ();
+                               }
+                       } catch (Exception ex) {
+                               Console.WriteLine ("LOOKUP METHOD - GET BY SUBJECT EX: {0}", ex);
+                               x509_ptr = IntPtr.Zero;
+                               return 0;
+                       }
+               }
+
+               protected override void Close ()
+               {
+                       try {
+                               if (gch.IsAllocated)
+                                       gch.Free ();
+                       } finally {
+                               instance = IntPtr.Zero;
+                               bySubjectFunc = null;
+                               bySubjectFuncPtr = IntPtr.Zero;
+                               base.Close ();
+                       }
+               }
+       }
+}
+#endif
diff --git a/mcs/class/System/Mono.Btls/MonoBtlsX509LookupMonoCollection.cs b/mcs/class/System/Mono.Btls/MonoBtlsX509LookupMonoCollection.cs
new file mode 100644 (file)
index 0000000..8a854f6
--- /dev/null
@@ -0,0 +1,102 @@
+//
+// MonoBtlsX509LookupMonoCollection.cs
+//
+// Author:
+//       Martin Baulig <martin.baulig@xamarin.com>
+//
+// Copyright (c) 2016 Xamarin Inc. (http://www.xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+#if SECURITY_DEP
+using System;
+using System.IO;
+using System.Runtime.InteropServices;
+using System.Runtime.CompilerServices;
+using System.Security.Cryptography.X509Certificates;
+
+#if MONOTOUCH
+using MonoTouch;
+#endif
+
+namespace Mono.Btls
+{
+       internal class MonoBtlsX509LookupMonoCollection : MonoBtlsX509LookupMono
+       {
+               long[] hashes;
+               MonoBtlsX509[] certificates;
+               X509CertificateCollection collection;
+               MonoBtlsX509TrustKind trust;
+
+               internal MonoBtlsX509LookupMonoCollection (X509CertificateCollection collection, MonoBtlsX509TrustKind trust)
+               {
+                       this.collection = collection;
+                       this.trust = trust;
+               }
+
+               void Initialize ()
+               {
+                       if (certificates != null)
+                               return;
+
+                       hashes = new long [collection.Count];
+                       certificates = new MonoBtlsX509 [collection.Count];
+                       for (int i = 0; i < collection.Count; i++) {
+                               // Create new 'X509 *' instance since we need to modify it to add the
+                               // trust settings.
+                               var data = collection [i].GetRawCertData ();
+                               certificates [i] = MonoBtlsX509.LoadFromData (data, MonoBtlsX509Format.DER);
+                               certificates [i].AddExplicitTrust (trust);
+                               hashes [i] = certificates [i].GetSubjectNameHash ();
+                       }
+               }
+
+               protected override MonoBtlsX509 OnGetBySubject (MonoBtlsX509Name name)
+               {
+                       Console.WriteLine ("COLLECTION LOOKUP: {0:x} - {1}", name.GetHash (), name.GetString ());
+                       Initialize ();
+
+                       var hash = name.GetHash ();
+                       for (int i = 0; i < certificates.Length; i++) {
+                               if (hashes [i] == hash)
+                                       return certificates [i];
+                       }
+
+                       return null;
+               }
+
+               protected override void Close ()
+               {
+                       try {
+                               if (certificates != null) {
+                                       for (int i = 0; i < certificates.Length; i++) {
+                                               if (certificates [i] != null) {
+                                                       certificates [i].Dispose ();
+                                                       certificates [i] = null;
+                                               }
+                                       }
+                                       certificates = null;
+                                       hashes = null;
+                               }
+                       } finally {
+                               base.Close ();
+                       }
+               }
+       }
+}
+#endif
diff --git a/mcs/class/System/Mono.Btls/MonoBtlsX509LookupType.cs b/mcs/class/System/Mono.Btls/MonoBtlsX509LookupType.cs
new file mode 100644 (file)
index 0000000..2cbdf7c
--- /dev/null
@@ -0,0 +1,39 @@
+//
+// MonoBtlsX509LookupCollection.cs
+//
+// Author:
+//       Martin Baulig <martin.baulig@xamarin.com>
+//
+// Copyright (c) 2016 Xamarin Inc. (http://www.xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+#if SECURITY_DEP
+using System;
+
+namespace Mono.Btls
+{
+       enum MonoBtlsX509LookupType
+       {
+               UNKNOWN = 0,
+               FILE,
+               HASH_DIR,
+               MONO
+       }
+}
+#endif
diff --git a/mcs/class/System/Mono.Btls/MonoBtlsX509Name.cs b/mcs/class/System/Mono.Btls/MonoBtlsX509Name.cs
new file mode 100644 (file)
index 0000000..9b3b723
--- /dev/null
@@ -0,0 +1,216 @@
+//
+// MonoBtlsX509Name.cs
+//
+// Author:
+//       Martin Baulig <martin.baulig@xamarin.com>
+//
+// Copyright (c) 2016 Xamarin Inc. (http://www.xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+#if SECURITY_DEP
+using System;
+using System.IO;
+using System.Text;
+using System.Runtime.InteropServices;
+using System.Runtime.CompilerServices;
+
+namespace Mono.Btls
+{
+       class MonoBtlsX509Name : MonoBtlsObject
+       {
+               internal class BoringX509NameHandle : MonoBtlsHandle
+               {
+                       bool dontFree;
+
+                       internal BoringX509NameHandle (IntPtr handle, bool ownsHandle)
+                               : base (handle, ownsHandle)
+                       {
+                               this.dontFree = !ownsHandle;
+                       }
+
+                       protected override bool ReleaseHandle ()
+                       {
+                               if (!dontFree)
+                                       mono_btls_x509_name_free (handle);
+                               return true;
+                       }
+               }
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static int mono_btls_x509_name_print_bio (IntPtr handle, IntPtr bio);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static int mono_btls_x509_name_print_string (IntPtr handle, IntPtr buffer, int size);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static int mono_btls_x509_name_get_raw_data (IntPtr handle, out IntPtr buffer, int use_canon_enc);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static long mono_btls_x509_name_hash (IntPtr handle);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static long mono_btls_x509_name_hash_old (IntPtr handle);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static int mono_btls_x509_name_get_entry_count (IntPtr handle);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static MonoBtlsX509NameEntryType mono_btls_x509_name_get_entry_type (IntPtr name, int index);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static int mono_btls_x509_name_get_entry_oid (IntPtr name, int index, IntPtr buffer, int size);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static int mono_btls_x509_name_get_entry_oid_data (IntPtr name, int index, out IntPtr data);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static int mono_btls_x509_name_get_entry_value (IntPtr name, int index, out IntPtr str);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern unsafe static IntPtr mono_btls_x509_name_from_data (void* data, int len, int use_canon_enc);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static void mono_btls_x509_name_free (IntPtr handle);
+
+               new internal BoringX509NameHandle Handle {
+                       get { return (BoringX509NameHandle)base.Handle; }
+               }
+
+               internal MonoBtlsX509Name (BoringX509NameHandle handle)
+                       : base (handle)
+               {
+               }
+
+               public string GetString ()
+               {
+                       const int size = 4096;
+                       var data = Marshal.AllocHGlobal (size);
+                       try {
+                               var ret = mono_btls_x509_name_print_string (
+                                       Handle.DangerousGetHandle (), data, size);
+                               CheckError (ret);
+                               return Marshal.PtrToStringAnsi (data);
+                       } finally {
+                               Marshal.FreeHGlobal (data);
+                       }
+               }
+
+               public void PrintBio (MonoBtlsBio bio)
+               {
+                       var ret = mono_btls_x509_name_print_bio (
+                               Handle.DangerousGetHandle (),
+                               bio.Handle.DangerousGetHandle ());
+                       CheckError (ret);
+               }
+
+               public byte[] GetRawData (bool use_canon_enc)
+               {
+                       IntPtr data;
+                       var ret = mono_btls_x509_name_get_raw_data (
+                               Handle.DangerousGetHandle (),
+                               out data, use_canon_enc ? 1 : 0);
+                       CheckError (ret > 0);
+                       var buffer = new byte [ret];
+                       Marshal.Copy (data, buffer, 0, ret);
+                       FreeDataPtr (data);
+                       return buffer;
+               }
+
+               public long GetHash ()
+               {
+                       return mono_btls_x509_name_hash (Handle.DangerousGetHandle ());
+               }
+
+               public long GetHashOld ()
+               {
+                       return mono_btls_x509_name_hash_old (Handle.DangerousGetHandle ());
+               }
+
+               public int GetEntryCount ()
+               {
+                       return mono_btls_x509_name_get_entry_count (Handle.DangerousGetHandle ());
+               }
+
+               public MonoBtlsX509NameEntryType GetEntryType (int index)
+               {
+                       if (index >= GetEntryCount ())
+                               throw new ArgumentOutOfRangeException ();
+                       return mono_btls_x509_name_get_entry_type (
+                               Handle.DangerousGetHandle (), index);
+               }
+
+               public string GetEntryOid (int index)
+               {
+                       if (index >= GetEntryCount ())
+                               throw new ArgumentOutOfRangeException ();
+
+                       const int size = 4096;
+                       var data = Marshal.AllocHGlobal (size);
+                       try {
+                               var ret = mono_btls_x509_name_get_entry_oid (
+                                       Handle.DangerousGetHandle (),
+                                       index, data, size);
+                               CheckError (ret > 0);
+                               return Marshal.PtrToStringAnsi (data);
+                       } finally {
+                               Marshal.FreeHGlobal (data);
+                       }
+               }
+
+               public byte[] GetEntryOidData (int index)
+               {
+                       IntPtr data;
+                       var ret = mono_btls_x509_name_get_entry_oid_data (
+                               Handle.DangerousGetHandle (), index, out data);
+                       CheckError (ret > 0);
+
+                       var bytes = new byte[ret];
+                       Marshal.Copy (data, bytes, 0, ret);
+                       return bytes;
+               }
+
+               public unsafe string GetEntryValue (int index)
+               {
+                       if (index >= GetEntryCount ())
+                               throw new ArgumentOutOfRangeException ();
+                       IntPtr data;
+                       var ret = mono_btls_x509_name_get_entry_value (
+                               Handle.DangerousGetHandle (), index, out data);
+                       if (ret <= 0)
+                               return null;
+                       try {
+                               return new UTF8Encoding ().GetString ((byte*)data, ret);
+                       } finally {
+                               if (data != IntPtr.Zero)
+                                       FreeDataPtr (data);
+                       }
+               }
+
+               public static unsafe MonoBtlsX509Name CreateFromData (byte[] data, bool use_canon_enc)
+               {
+                       fixed (void *ptr = data) {
+                               var handle = mono_btls_x509_name_from_data (ptr, data.Length, use_canon_enc ? 1 : 0);
+                               if (handle == IntPtr.Zero)
+                                       throw new MonoBtlsException ("mono_btls_x509_name_from_data() failed.");
+                               return new MonoBtlsX509Name (new BoringX509NameHandle (handle, false));
+                       }
+               }
+       }
+}
+#endif
diff --git a/mcs/class/System/Mono.Btls/MonoBtlsX509NameEntryType.cs b/mcs/class/System/Mono.Btls/MonoBtlsX509NameEntryType.cs
new file mode 100644 (file)
index 0000000..781d691
--- /dev/null
@@ -0,0 +1,51 @@
+//
+// MonoBtlsX509NameEntryType.cs
+//
+// Author:
+//       Martin Baulig <martin.baulig@xamarin.com>
+//
+// Copyright (c) 2016 Xamarin Inc. (http://www.xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+#if SECURITY_DEP
+using System;
+namespace Mono.Btls
+{
+       enum MonoBtlsX509NameEntryType : int
+       {
+               Unknown = 0,
+               CountryName,
+               OrganizationName,
+               OrganizationalUnitName,
+               CommonName,
+               LocalityName,
+               StateOrProvinceName,
+               StreetAddress,
+               SerialNumber,
+               DomainComponent,
+               UserId,
+               Email,
+               DnQualifier,
+               Title,
+               Surname,
+               GivenName,
+               Initial
+       }
+}
+#endif
diff --git a/mcs/class/System/Mono.Btls/MonoBtlsX509NameList.cs b/mcs/class/System/Mono.Btls/MonoBtlsX509NameList.cs
new file mode 100644 (file)
index 0000000..cccc005
--- /dev/null
@@ -0,0 +1,121 @@
+//
+// MonoBtlsX509NameList.cs
+//
+// Author:
+//       Martin Baulig <martin.baulig@xamarin.com>
+//
+// Copyright (c) 2016 Xamarin Inc. (http://www.xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+#if SECURITY_DEP
+using System;
+using System.IO;
+using System.Text;
+using System.Runtime.InteropServices;
+using System.Runtime.CompilerServices;
+
+namespace Mono.Btls
+{
+       class MonoBtlsX509NameList : MonoBtlsObject
+       {
+               internal class BoringX509NameListHandle : MonoBtlsHandle
+               {
+                       bool dontFree;
+
+                       internal BoringX509NameListHandle (IntPtr handle, bool ownsHandle)
+                               : base (handle, ownsHandle)
+                       {
+                               this.dontFree = !ownsHandle;
+                       }
+
+                       protected override bool ReleaseHandle ()
+                       {
+                               if (!dontFree)
+                                       mono_btls_x509_name_list_free (handle);
+                               return true;
+                       }
+               }
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static IntPtr mono_btls_x509_name_list_new ();
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static int mono_btls_x509_name_list_get_count (IntPtr handle);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static int mono_btls_x509_name_list_add (IntPtr handle, IntPtr name);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static IntPtr mono_btls_x509_name_list_get_item (IntPtr handle, int index);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static void mono_btls_x509_name_list_free (IntPtr handle);
+
+               new internal BoringX509NameListHandle Handle {
+                       get { return (BoringX509NameListHandle)base.Handle; }
+               }
+
+               internal MonoBtlsX509NameList (BoringX509NameListHandle handle)
+                       : base (handle)
+               {
+               }
+
+               internal MonoBtlsX509NameList ()
+                       : this (Create_internal ())
+               {
+               }
+
+               static BoringX509NameListHandle Create_internal ()
+               {
+                       var handle = mono_btls_x509_name_list_new ();
+                       if (handle == IntPtr.Zero)
+                               throw new MonoBtlsException ();
+                       return new BoringX509NameListHandle (handle, true);
+               }
+
+               public int GetCount ()
+               {
+                       CheckThrow ();
+                       return mono_btls_x509_name_list_get_count (
+                               Handle.DangerousGetHandle ());
+               }
+
+               public MonoBtlsX509Name GetItem (int index)
+               {
+                       CheckThrow ();
+                       if (index < 0 || index >= GetCount ())
+                               throw new ArgumentOutOfRangeException ();
+                       var ptr = mono_btls_x509_name_list_get_item (
+                               Handle.DangerousGetHandle (), index);
+                       if (ptr == IntPtr.Zero)
+                               return null;
+                       return new MonoBtlsX509Name (
+                               new MonoBtlsX509Name.BoringX509NameHandle (ptr, true));
+               }
+
+               public void Add (MonoBtlsX509Name name)
+               {
+                       CheckThrow ();
+                       mono_btls_x509_name_list_add (
+                               Handle.DangerousGetHandle (),
+                               name.Handle.DangerousGetHandle ());
+               }
+       }
+}
+#endif
diff --git a/mcs/class/System/Mono.Btls/MonoBtlsX509Purpose.cs b/mcs/class/System/Mono.Btls/MonoBtlsX509Purpose.cs
new file mode 100644 (file)
index 0000000..d80957c
--- /dev/null
@@ -0,0 +1,43 @@
+//
+// MonoBtlsX509Purpose.cs
+//
+// Author:
+//       Martin Baulig <martin.baulig@xamarin.com>
+//
+// Copyright (c) 2016 Xamarin Inc. (http://www.xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+#if SECURITY_DEP
+using System;
+namespace Mono.Btls
+{
+       enum MonoBtlsX509Purpose
+       {
+               SSL_CLIENT = 1,
+               SSL_SERVER = 2,
+               NS_SSL_SERVER = 3,
+               SMIME_SIGN = 4,
+               SMIME_ENCRYPT = 5,
+               CRL_SIGN = 6,
+               ANY = 7,
+               OCSP_HELPER = 8,
+               TIMESTAMP_SIGN = 9,
+       }
+}
+#endif
diff --git a/mcs/class/System/Mono.Btls/MonoBtlsX509Revoked.cs b/mcs/class/System/Mono.Btls/MonoBtlsX509Revoked.cs
new file mode 100644 (file)
index 0000000..00aafa2
--- /dev/null
@@ -0,0 +1,120 @@
+//
+// MonoBtlsX509Revoked.cs
+//
+// Author:
+//       Martin Baulig <martin.baulig@xamarin.com>
+//
+// Copyright (c) 2016 Xamarin Inc. (http://www.xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+#if SECURITY_DEP
+using System;
+using System.IO;
+using System.Text;
+using System.Threading;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Security.Cryptography.X509Certificates;
+using System.Security.Cryptography;
+
+namespace Mono.Btls
+{
+       class MonoBtlsX509Revoked : MonoBtlsObject
+       {
+               internal class BoringX509RevokedHandle : MonoBtlsHandle
+               {
+                       public BoringX509RevokedHandle (IntPtr handle)
+                               : base (handle, true)
+                       {
+                       }
+
+                       protected override bool ReleaseHandle ()
+                       {
+                               if (handle != IntPtr.Zero)
+                                       mono_btls_x509_revoked_free (handle);
+                               return true;
+                       }
+
+                       public IntPtr StealHandle ()
+                       {
+                               var retval = Interlocked.Exchange (ref handle, IntPtr.Zero);
+                               return retval;
+                       }
+               }
+
+               new internal BoringX509RevokedHandle Handle {
+                       get { return (BoringX509RevokedHandle)base.Handle; }
+               }
+
+               internal MonoBtlsX509Revoked (BoringX509RevokedHandle handle)
+                       : base (handle)
+               {
+               }
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static int mono_btls_x509_revoked_get_serial_number (IntPtr handle, IntPtr data, int size);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static long mono_btls_x509_revoked_get_revocation_date (IntPtr handle);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static int mono_btls_x509_revoked_get_reason (IntPtr handle);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static int mono_btls_x509_revoked_get_sequence (IntPtr handle);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static void mono_btls_x509_revoked_free (IntPtr handle);
+
+               public byte[] GetSerialNumber ()
+               {
+                       int size = 256;
+                       IntPtr data = Marshal.AllocHGlobal (size);
+                       try {
+                               var ret = mono_btls_x509_revoked_get_serial_number (
+                                       Handle.DangerousGetHandle (), data, size);
+                               CheckError (ret > 0);
+                               var buffer = new byte[ret];
+                               Marshal.Copy (data, buffer, 0, ret);
+                               return buffer;
+                       } finally {
+                               if (data != IntPtr.Zero)
+                                       Marshal.FreeHGlobal (data);
+                       }
+               }
+
+               public DateTime GetRevocationDate ()
+               {
+                       var ticks = mono_btls_x509_revoked_get_revocation_date (
+                               Handle.DangerousGetHandle ());
+                       return new DateTime (1970, 1, 1).AddSeconds (ticks);
+               }
+
+               public int GetReason ()
+               {
+                       return mono_btls_x509_revoked_get_reason (Handle.DangerousGetHandle ());
+               }
+
+               public int GetSequence ()
+               {
+                       return mono_btls_x509_revoked_get_sequence (Handle.DangerousGetHandle ());
+               }
+       }
+}
+#endif
diff --git a/mcs/class/System/Mono.Btls/MonoBtlsX509Store.cs b/mcs/class/System/Mono.Btls/MonoBtlsX509Store.cs
new file mode 100644 (file)
index 0000000..2e03715
--- /dev/null
@@ -0,0 +1,230 @@
+//
+// MonoBtlsX509Store.cs
+//
+// Author:
+//       Martin Baulig <martin.baulig@xamarin.com>
+//
+// Copyright (c) 2016 Xamarin Inc. (http://www.xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+#if SECURITY_DEP
+using System;
+using System.IO;
+using System.Collections.Generic;
+using System.Runtime.InteropServices;
+using System.Runtime.CompilerServices;
+using System.Security.Cryptography.X509Certificates;
+
+namespace Mono.Btls
+{
+       class MonoBtlsX509Store : MonoBtlsObject
+       {
+               internal class BoringX509StoreHandle : MonoBtlsHandle
+               {
+                       public BoringX509StoreHandle (IntPtr handle)
+                               : base (handle, true)
+                       {
+                       }
+
+                       protected override bool ReleaseHandle ()
+                       {
+                               mono_btls_x509_store_free (handle);
+                               return true;
+                       }
+               }
+
+               new internal BoringX509StoreHandle Handle {
+                       get { return (BoringX509StoreHandle)base.Handle; }
+               }
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static IntPtr mono_btls_x509_store_new ();
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static IntPtr mono_btls_x509_store_from_ctx (IntPtr ctx);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static IntPtr mono_btls_x509_store_from_ssl_ctx (IntPtr handle);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static int mono_btls_x509_store_load_locations (IntPtr handle, IntPtr file, IntPtr path);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static int mono_btls_x509_store_set_default_paths (IntPtr handle);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static int mono_btls_x509_store_add_cert (IntPtr handle, IntPtr x509);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static int mono_btls_x509_store_get_count (IntPtr handle);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static void mono_btls_x509_store_free (IntPtr handle);
+
+               Dictionary<IntPtr,MonoBtlsX509Lookup> lookupHash;
+
+               public void LoadLocations (string file, string path)
+               {
+                       IntPtr filePtr = IntPtr.Zero;
+                       IntPtr pathPtr = IntPtr.Zero;
+                       try {
+                               if (file != null)
+                                       filePtr = Marshal.StringToHGlobalAnsi (file);
+                               if (path != null)
+                                       pathPtr = Marshal.StringToHGlobalAnsi (path);
+                               var ret = mono_btls_x509_store_load_locations (
+                                       Handle.DangerousGetHandle (), filePtr, pathPtr);
+                               CheckError (ret);
+                       } finally {
+                               if (filePtr != IntPtr.Zero)
+                                       Marshal.FreeHGlobal (filePtr);
+                               if (pathPtr != IntPtr.Zero)
+                                       Marshal.FreeHGlobal (pathPtr);
+                       }
+               }
+
+               public void SetDefaultPaths ()
+               {
+                       var ret = mono_btls_x509_store_set_default_paths (Handle.DangerousGetHandle ());
+                       CheckError (ret);
+               }
+
+               static BoringX509StoreHandle Create_internal ()
+               {
+                       var handle = mono_btls_x509_store_new ();
+                       if (handle == IntPtr.Zero)
+                               throw new MonoBtlsException ();
+                       return new BoringX509StoreHandle (handle);
+               }
+
+               static BoringX509StoreHandle Create_internal (IntPtr store_ctx)
+               {
+                       var handle = mono_btls_x509_store_from_ssl_ctx (store_ctx);
+                       if (handle == IntPtr.Zero)
+                               throw new MonoBtlsException ();
+                       return new BoringX509StoreHandle (handle);
+               }
+
+               static BoringX509StoreHandle Create_internal (MonoBtlsSslCtx.BoringSslCtxHandle ctx)
+               {
+                       var handle = mono_btls_x509_store_from_ssl_ctx (ctx.DangerousGetHandle ());
+                       if (handle == IntPtr.Zero)
+                               throw new MonoBtlsException ();
+                       return new BoringX509StoreHandle (handle);
+               }
+
+               internal MonoBtlsX509Store ()
+                       : base (Create_internal ())
+               {
+               }
+
+               internal MonoBtlsX509Store (IntPtr store_ctx)
+                       : base (Create_internal (store_ctx))
+               {
+               }
+
+               internal MonoBtlsX509Store (MonoBtlsSslCtx.BoringSslCtxHandle ctx)
+                       : base (Create_internal (ctx))
+               {
+               }
+
+               public void AddCertificate (MonoBtlsX509 x509)
+               {
+                       var ret = mono_btls_x509_store_add_cert (
+                               Handle.DangerousGetHandle (),
+                               x509.Handle.DangerousGetHandle ());
+                       CheckError (ret);
+               }
+
+               public int GetCount ()
+               {
+                       return mono_btls_x509_store_get_count (Handle.DangerousGetHandle ());
+               }
+
+               internal void AddTrustedRoots ()
+               {
+                       var systemRoot = MonoBtlsProvider.GetSystemStoreLocation ();
+                       LoadLocations (null, systemRoot);
+               }
+
+               public MonoBtlsX509Lookup AddLookup (MonoBtlsX509LookupType type)
+               {
+                       if (lookupHash == null)
+                               lookupHash = new Dictionary<IntPtr,MonoBtlsX509Lookup> ();
+
+                       /*
+                        * X509_STORE_add_lookup() returns the same 'X509_LOOKUP *' for each
+                        * unique 'X509_LOOKUP_METHOD *' (which is supposed to be a static struct)
+                        * and we want to use the same managed object for each unique 'X509_LOOKUP *'.
+                       */
+                       var lookup = new MonoBtlsX509Lookup (this, type);
+                       var nativeLookup = lookup.GetNativeLookup ();
+                       if (lookupHash.ContainsKey (nativeLookup)) {
+                               lookup.Dispose ();
+                               lookup = lookupHash [nativeLookup];
+                       } else {
+                               lookupHash.Add (nativeLookup, lookup);
+                       }
+
+                       return lookup;
+               }
+
+               public void AddDirectoryLookup (string dir, MonoBtlsX509FileType type)
+               {
+                       var lookup = AddLookup (MonoBtlsX509LookupType.HASH_DIR);
+                       lookup.AddDirectory (dir, type);
+               }
+
+               public void AddFileLookup (string file, MonoBtlsX509FileType type)
+               {
+                       var lookup = AddLookup (MonoBtlsX509LookupType.FILE);
+                       lookup.LoadFile (file, type);
+               }
+
+               public void AddCollection (X509CertificateCollection collection, MonoBtlsX509TrustKind trust)
+               {
+                       var monoLookup = new MonoBtlsX509LookupMonoCollection (collection, trust);
+                       var lookup = new MonoBtlsX509Lookup (this, MonoBtlsX509LookupType.MONO);
+                       lookup.AddMono (monoLookup);
+               }
+
+#if MONODROID
+               public void AddAndroidLookup ()
+               {
+                       var androidLookup = new MonoBtlsX509LookupAndroid ();
+                       var lookup = new MonoBtlsX509Lookup (this, MonoBtlsX509LookupType.MONO);
+                       lookup.AddMono (androidLookup);
+               }
+#endif
+
+               protected override void Close ()
+               {
+                       try {
+                               if (lookupHash != null) {
+                                       foreach (var lookup in lookupHash.Values)
+                                               lookup.Dispose ();
+                                       lookupHash = null;
+                               }
+                       } finally {
+                               base.Close ();
+                       }
+               }
+       }
+}
+#endif
diff --git a/mcs/class/System/Mono.Btls/MonoBtlsX509StoreCtx.cs b/mcs/class/System/Mono.Btls/MonoBtlsX509StoreCtx.cs
new file mode 100644 (file)
index 0000000..affb988
--- /dev/null
@@ -0,0 +1,252 @@
+//
+// MonoBtlsX509StoreCtx.cs
+//
+// Author:
+//       Martin Baulig <martin.baulig@xamarin.com>
+//
+// Copyright (c) 2016 Xamarin Inc. (http://www.xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+#if SECURITY_DEP
+using System;
+using System.IO;
+using System.Runtime.InteropServices;
+using System.Runtime.CompilerServices;
+
+namespace Mono.Btls
+{
+       class MonoBtlsX509StoreCtx : MonoBtlsObject
+       {
+               internal class BoringX509StoreCtxHandle : MonoBtlsHandle
+               {
+                       bool dontFree;
+
+                       internal BoringX509StoreCtxHandle (IntPtr handle, bool ownsHandle = true)
+                               : base (handle, ownsHandle)
+                       {
+                               dontFree = !ownsHandle;
+                       }
+
+                       #if FIXME
+                       internal BoringX509StoreCtxHandle (IntPtr handle)
+                               : base ()
+                       {
+                               base.handle = handle;
+                               this.dontFree = true;
+                       }
+                       #endif
+
+                       protected override bool ReleaseHandle ()
+                       {
+                               if (!dontFree)
+                                       mono_btls_x509_store_ctx_free (handle);
+                               return true;
+                       }
+               }
+
+               int? verifyResult;
+
+               new internal BoringX509StoreCtxHandle Handle {
+                       get { return (BoringX509StoreCtxHandle)base.Handle; }
+               }
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static IntPtr mono_btls_x509_store_ctx_new ();
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static IntPtr mono_btls_x509_store_ctx_from_ptr (IntPtr ctx);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static MonoBtlsX509Error mono_btls_x509_store_ctx_get_error (IntPtr handle, out IntPtr error_string);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static int mono_btls_x509_store_ctx_get_error_depth (IntPtr handle);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static IntPtr mono_btls_x509_store_ctx_get_chain (IntPtr handle);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static int mono_btls_x509_store_ctx_init (IntPtr handle, IntPtr store, IntPtr chain);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static int mono_btls_x509_store_ctx_set_param (IntPtr handle, IntPtr param);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static void mono_btls_x509_store_ctx_test (IntPtr handle);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static int mono_btls_x509_store_ctx_verify_cert (IntPtr handle);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static IntPtr mono_btls_x509_store_ctx_get_by_subject (IntPtr handle, IntPtr name);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static IntPtr mono_btls_x509_store_ctx_get_current_cert (IntPtr handle);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static IntPtr mono_btls_x509_store_ctx_get_current_issuer (IntPtr handle);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static IntPtr mono_btls_x509_store_ctx_get_verify_param (IntPtr handle);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static IntPtr mono_btls_x509_store_ctx_get_untrusted (IntPtr handle);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static IntPtr mono_btls_x509_store_ctx_up_ref (IntPtr handle);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static void mono_btls_x509_store_ctx_free (IntPtr handle);
+
+               internal MonoBtlsX509StoreCtx ()
+                       : base (new BoringX509StoreCtxHandle (mono_btls_x509_store_ctx_new ()))
+               {
+               }
+
+               static BoringX509StoreCtxHandle Create_internal (IntPtr store_ctx)
+               {
+                       var handle = mono_btls_x509_store_ctx_from_ptr (store_ctx);
+                       if (handle == IntPtr.Zero)
+                               throw new MonoBtlsException ();
+                       return new BoringX509StoreCtxHandle (handle);
+               }
+
+               internal MonoBtlsX509StoreCtx (int preverify_ok, IntPtr store_ctx)
+                       : base (Create_internal (store_ctx))
+               {
+                       verifyResult = preverify_ok;
+               }
+
+               internal MonoBtlsX509StoreCtx (BoringX509StoreCtxHandle ptr, int? verifyResult)
+                       : base (ptr)
+               {
+                       this.verifyResult = verifyResult;
+               }
+
+               public MonoBtlsX509Error GetError ()
+               {
+                       IntPtr error_string_ptr;
+                       return mono_btls_x509_store_ctx_get_error (Handle.DangerousGetHandle (), out error_string_ptr);
+               }
+
+               public MonoBtlsX509Exception GetException ()
+               {
+                       IntPtr error_string_ptr;
+                       var error = mono_btls_x509_store_ctx_get_error (Handle.DangerousGetHandle (), out error_string_ptr);
+                       if (error == 0)
+                               return null;
+                       if (error_string_ptr != IntPtr.Zero) {
+                               var error_string = Marshal.PtrToStringAnsi (error_string_ptr);
+                               return new MonoBtlsX509Exception (error, error_string);
+                       }
+                       return new MonoBtlsX509Exception (error, "Unknown verify error.");
+               }
+
+               public MonoBtlsX509Chain GetChain ()
+               {
+                       var chain = mono_btls_x509_store_ctx_get_chain (Handle.DangerousGetHandle ());
+                       CheckError (chain != IntPtr.Zero);
+                       return new MonoBtlsX509Chain (new MonoBtlsX509Chain.BoringX509ChainHandle (chain));
+               }
+
+               public MonoBtlsX509Chain GetUntrusted ()
+               {
+                       var chain = mono_btls_x509_store_ctx_get_untrusted (Handle.DangerousGetHandle ());
+                       CheckError (chain != IntPtr.Zero);
+                       return new MonoBtlsX509Chain (new MonoBtlsX509Chain.BoringX509ChainHandle (chain));
+               }
+
+               public void Test ()
+               {
+                       mono_btls_x509_store_ctx_test (Handle.DangerousGetHandle ());
+               }
+
+               public void Initialize (MonoBtlsX509Store store, MonoBtlsX509Chain chain)
+               {
+                       var ret = mono_btls_x509_store_ctx_init (
+                               Handle.DangerousGetHandle (),
+                               store.Handle.DangerousGetHandle (),
+                               chain.Handle.DangerousGetHandle ());
+                       CheckError (ret);
+               }
+
+               public void SetVerifyParam (MonoBtlsX509VerifyParam param)
+               {
+                       var ret = mono_btls_x509_store_ctx_set_param (
+                               Handle.DangerousGetHandle (),
+                               param.Handle.DangerousGetHandle ());
+                       CheckError (ret);
+               }
+
+               public int VerifyResult {
+                       get {
+                               if (verifyResult == null)
+                                       throw new InvalidOperationException ();
+                               return verifyResult.Value;
+                       }
+               }
+
+               public int Verify ()
+               {
+                       verifyResult = mono_btls_x509_store_ctx_verify_cert (Handle.DangerousGetHandle ());
+                       return verifyResult.Value;
+               }
+
+               public MonoBtlsX509 LookupBySubject (MonoBtlsX509Name name)
+               {
+                       var handle = mono_btls_x509_store_ctx_get_by_subject (
+                               Handle.DangerousGetHandle (), name.Handle.DangerousGetHandle ());
+                       if (handle == IntPtr.Zero)
+                               return null;
+                       return new MonoBtlsX509 (new MonoBtlsX509.BoringX509Handle (handle));
+               }
+
+               public MonoBtlsX509 GetCurrentCertificate ()
+               {
+                       var x509 = mono_btls_x509_store_ctx_get_current_cert (Handle.DangerousGetHandle ());
+                       if (x509 == IntPtr.Zero)
+                               return null;
+                       return new MonoBtlsX509 (new MonoBtlsX509.BoringX509Handle (x509));
+               }
+
+               public MonoBtlsX509 GetCurrentIssuer ()
+               {
+                       var x509 = mono_btls_x509_store_ctx_get_current_issuer (Handle.DangerousGetHandle ());
+                       if (x509 == IntPtr.Zero)
+                               return null;
+                       return new MonoBtlsX509 (new MonoBtlsX509.BoringX509Handle (x509));
+               }
+
+               public MonoBtlsX509VerifyParam GetVerifyParam ()
+               {
+                       var param = mono_btls_x509_store_ctx_get_verify_param (Handle.DangerousGetHandle ());
+                       if (param == IntPtr.Zero)
+                               return null;
+                       return new MonoBtlsX509VerifyParam (new MonoBtlsX509VerifyParam.BoringX509VerifyParamHandle (param));
+               }
+
+               public MonoBtlsX509StoreCtx Copy ()
+               {
+                       var copy = mono_btls_x509_store_ctx_up_ref (Handle.DangerousGetHandle ());
+                       CheckError (copy != IntPtr.Zero);
+                       return new MonoBtlsX509StoreCtx (new BoringX509StoreCtxHandle (copy), verifyResult);
+               }
+       }
+}
+#endif
diff --git a/mcs/class/System/Mono.Btls/MonoBtlsX509StoreManager.cs b/mcs/class/System/Mono.Btls/MonoBtlsX509StoreManager.cs
new file mode 100644 (file)
index 0000000..13c92a2
--- /dev/null
@@ -0,0 +1,120 @@
+//
+// MonoBtlsX509StoreManager.cs
+//
+// Author:
+//       Martin Baulig <martin.baulig@xamarin.com>
+//
+// Copyright (c) 2016 Xamarin Inc. (http://www.xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+#if SECURITY_DEP
+#if MONO_SECURITY_ALIAS
+extern alias MonoSecurity;
+#endif
+
+using System;
+using System.IO;
+using System.Security.Cryptography.X509Certificates;
+
+#if MONO_SECURITY_ALIAS
+using MonoSecurity::Mono.Security.Interface;
+using MX = MonoSecurity::Mono.Security.X509;
+#else
+using Mono.Security.Interface;
+using MX = Mono.Security.X509;
+#endif
+
+namespace Mono.Btls
+{
+       static class MonoBtlsX509StoreManager
+       {
+               static bool initialized;
+               static string machineTrustedRootPath;
+               static string machineIntermediateCAPath;
+               static string machineUntrustedPath;
+               static string userTrustedRootPath;
+               static string userIntermediateCAPath;
+               static string userUntrustedPath;
+
+               static void Initialize ()
+               {
+                       if (initialized)
+                               return;
+
+                       try {
+                               DoInitialize ();
+                       } catch (Exception ex) {
+                               Console.Error.WriteLine ("MonoBtlsX509StoreManager.Initialize() threw exception: {0}", ex);
+                       } finally {
+                               initialized = true;
+                       }
+               }
+
+               static void DoInitialize ()
+               {
+#if !ANDROID
+                       var userPath = MX.X509StoreManager.NewCurrentUserPath;
+                       userTrustedRootPath = Path.Combine (userPath, MX.X509Stores.Names.TrustedRoot);
+                       userIntermediateCAPath = Path.Combine (userPath, MX.X509Stores.Names.IntermediateCA);
+                       userUntrustedPath = Path.Combine (userPath, MX.X509Stores.Names.Untrusted);
+
+                       var machinePath = MX.X509StoreManager.NewLocalMachinePath;
+                       machineTrustedRootPath = Path.Combine (userPath, MX.X509Stores.Names.TrustedRoot);
+                       machineIntermediateCAPath = Path.Combine (userPath, MX.X509Stores.Names.IntermediateCA);
+                       machineUntrustedPath = Path.Combine (userPath, MX.X509Stores.Names.Untrusted);
+#endif
+               }
+
+               public static bool HasStore (MonoBtlsX509StoreType type)
+               {
+#if ANDROID
+                       return false;
+#else
+                       var path = GetStorePath (type);
+                       return path != null && Directory.Exists (path);
+#endif
+               }
+
+               public static string GetStorePath (MonoBtlsX509StoreType type)
+               {
+#if ANDROID
+                       throw new NotSupportedException ();
+#else
+                       Initialize ();
+                       switch (type) {
+                       case MonoBtlsX509StoreType.MachineTrustedRoots:
+                               return machineTrustedRootPath;
+                       case MonoBtlsX509StoreType.MachineIntermediateCA:
+                               return machineIntermediateCAPath;
+                       case MonoBtlsX509StoreType.MachineUntrusted:
+                               return machineUntrustedPath;
+                       case MonoBtlsX509StoreType.UserTrustedRoots:
+                               return userTrustedRootPath;
+                       case MonoBtlsX509StoreType.UserIntermediateCA:
+                               return userIntermediateCAPath;
+                       case MonoBtlsX509StoreType.UserUntrusted:
+                               return userUntrustedPath;
+                       default:
+                               throw new NotSupportedException ();
+                       }
+#endif
+               }
+       }
+}
+#endif
diff --git a/mcs/class/System/Mono.Btls/MonoBtlsX509StoreType.cs b/mcs/class/System/Mono.Btls/MonoBtlsX509StoreType.cs
new file mode 100644 (file)
index 0000000..22cc072
--- /dev/null
@@ -0,0 +1,40 @@
+//
+// MonoBtlsX509StoreType.cs
+//
+// Author:
+//       Martin Baulig <martin.baulig@xamarin.com>
+//
+// Copyright (c) 2016 Xamarin Inc. (http://www.xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+#if SECURITY_DEP
+namespace Mono.Btls
+{
+       enum MonoBtlsX509StoreType
+       {
+               Custom,
+               MachineTrustedRoots,
+               MachineIntermediateCA,
+               MachineUntrusted,
+               UserTrustedRoots,
+               UserIntermediateCA,
+               UserUntrusted
+       }
+}
+#endif
diff --git a/mcs/class/System/Mono.Btls/MonoBtlsX509TrustKind.cs b/mcs/class/System/Mono.Btls/MonoBtlsX509TrustKind.cs
new file mode 100644 (file)
index 0000000..e207683
--- /dev/null
@@ -0,0 +1,42 @@
+//
+// MonoBtlsX509TrustKind.cs
+//
+// Author:
+//       Martin Baulig <martin.baulig@xamarin.com>
+//
+// Copyright (c) 2016 Xamarin Inc. (http://www.xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+#if SECURITY_DEP
+using System;
+namespace Mono.Btls
+{
+       [Flags]
+       enum MonoBtlsX509TrustKind
+       {
+               DEFAULT         = 0,
+               TRUST_CLIENT    = 1,
+               TRUST_SERVER    = 2,
+               TRUST_ALL       = 4,
+               REJECT_CLIENT   = 32,
+               REJECT_SERVER   = 64,
+               REJECT_ALL      = 128
+       }
+}
+#endif
diff --git a/mcs/class/System/Mono.Btls/MonoBtlsX509VerifyFlags.cs b/mcs/class/System/Mono.Btls/MonoBtlsX509VerifyFlags.cs
new file mode 100644 (file)
index 0000000..628633b
--- /dev/null
@@ -0,0 +1,39 @@
+//
+// MonoBtlsX509VerifyFlags.cs
+//
+// Author:
+//       Martin Baulig <martin.baulig@xamarin.com>
+//
+// Copyright (c) 2016 Xamarin Inc. (http://www.xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+#if SECURITY_DEP
+using System;
+namespace Mono.Btls
+{
+       [Flags]
+       enum MonoBtlsX509VerifyFlags
+       {
+               DEFAULT         = 0,
+               CRL_CHECK       = 1,
+               CRL_CHECK_ALL   = 2,
+               X509_STRIC      = 4
+       }
+}
+#endif
diff --git a/mcs/class/System/Mono.Btls/MonoBtlsX509VerifyParam.cs b/mcs/class/System/Mono.Btls/MonoBtlsX509VerifyParam.cs
new file mode 100644 (file)
index 0000000..59c210b
--- /dev/null
@@ -0,0 +1,277 @@
+//
+// MonoBtlsX509VerifyParam.cs
+//
+// Author:
+//       Martin Baulig <martin.baulig@xamarin.com>
+//
+// Copyright (c) 2016 Xamarin Inc. (http://www.xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+#if SECURITY_DEP
+using System;
+using System.IO;
+using System.Runtime.InteropServices;
+using System.Runtime.CompilerServices;
+
+namespace Mono.Btls
+{
+       class MonoBtlsX509VerifyParam : MonoBtlsObject
+       {
+               internal class BoringX509VerifyParamHandle : MonoBtlsHandle
+               {
+                       public BoringX509VerifyParamHandle (IntPtr handle)
+                               : base (handle, true)
+                       {
+                       }
+
+                       protected override bool ReleaseHandle ()
+                       {
+                               mono_btls_x509_verify_param_free (handle);
+                               return true;
+                       }
+               }
+
+               new internal BoringX509VerifyParamHandle Handle {
+                       get { return (BoringX509VerifyParamHandle)base.Handle; }
+               }
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static IntPtr mono_btls_x509_verify_param_new ();
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static IntPtr mono_btls_x509_verify_param_copy (IntPtr handle);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static IntPtr mono_btls_x509_verify_param_lookup (IntPtr name);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static int mono_btls_x509_verify_param_can_modify (IntPtr param);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static int mono_btls_x509_verify_param_set_name (IntPtr handle, IntPtr name);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static int mono_btls_x509_verify_param_set_host (IntPtr handle, IntPtr name, int namelen);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static int mono_btls_x509_verify_param_add_host (IntPtr handle, IntPtr name, int namelen);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static ulong mono_btls_x509_verify_param_get_flags (IntPtr handle);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static int mono_btls_x509_verify_param_set_flags (IntPtr handle, ulong flags);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static MonoBtlsX509VerifyFlags mono_btls_x509_verify_param_get_mono_flags (IntPtr handle);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static int mono_btls_x509_verify_param_set_mono_flags (IntPtr handle, MonoBtlsX509VerifyFlags flags);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static int mono_btls_x509_verify_param_set_purpose (IntPtr handle, MonoBtlsX509Purpose purpose);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static int mono_btls_x509_verify_param_get_depth (IntPtr handle);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static int mono_btls_x509_verify_param_set_depth (IntPtr handle, int depth);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static int mono_btls_x509_verify_param_set_time (IntPtr handle, long time);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static IntPtr mono_btls_x509_verify_param_get_peername (IntPtr handle);
+
+               [MethodImpl (MethodImplOptions.InternalCall)]
+               extern static void mono_btls_x509_verify_param_free (IntPtr handle);
+
+               internal MonoBtlsX509VerifyParam ()
+                       : base (new BoringX509VerifyParamHandle (mono_btls_x509_verify_param_new ()))
+               {
+               }
+
+               internal MonoBtlsX509VerifyParam (BoringX509VerifyParamHandle handle)
+                       : base (handle)
+               {
+               }
+
+               public MonoBtlsX509VerifyParam Copy ()
+               {
+                       var copy = mono_btls_x509_verify_param_copy (Handle.DangerousGetHandle ());
+                       CheckError (copy != IntPtr.Zero);
+                       return new MonoBtlsX509VerifyParam (new BoringX509VerifyParamHandle (copy));
+               }
+
+               public static MonoBtlsX509VerifyParam GetSslClient ()
+               {
+                       return Lookup ("ssl_client", true);
+               }
+
+               public static MonoBtlsX509VerifyParam GetSslServer ()
+               {
+                       return Lookup ("ssl_server", true);
+               }
+
+               public static MonoBtlsX509VerifyParam Lookup (string name, bool fail = false)
+               {
+                       IntPtr namePtr = IntPtr.Zero;
+                       IntPtr handle = IntPtr.Zero;
+
+                       try {
+                               namePtr = Marshal.StringToHGlobalAnsi (name);
+                               handle = mono_btls_x509_verify_param_lookup (namePtr);
+                               if (handle == IntPtr.Zero) {
+                                       if (!fail)
+                                               return null;
+                                       throw new MonoBtlsException ("X509_VERIFY_PARAM_lookup() could not find '{0}'.", name);
+                               }
+
+                               return new MonoBtlsX509VerifyParam (new BoringX509VerifyParamHandle (handle));
+                       } finally {
+                               if (namePtr != IntPtr.Zero)
+                                       Marshal.FreeHGlobal (namePtr);
+                       }
+               }
+
+               public bool CanModify {
+                       get {
+                               return mono_btls_x509_verify_param_can_modify (Handle.DangerousGetHandle ()) != 0;
+                       }
+               }
+
+               void WantToModify ()
+               {
+                       if (!CanModify)
+                               throw new MonoBtlsException ("Attempting to modify read-only MonoBtlsX509VerifyParam instance.");
+               }
+
+               public void SetName (string name)
+               {
+                       WantToModify ();
+                       IntPtr namePtr = IntPtr.Zero;
+                       try {
+                               namePtr = Marshal.StringToHGlobalAnsi (name);
+                               var ret = mono_btls_x509_verify_param_set_name (
+                                       Handle.DangerousGetHandle (), namePtr);
+                               CheckError (ret);
+                       } finally {
+                               if (namePtr != IntPtr.Zero)
+                                       Marshal.FreeHGlobal (namePtr);
+                       }
+               }
+
+               public void SetHost (string name)
+               {
+                       WantToModify ();
+                       IntPtr namePtr = IntPtr.Zero;
+                       try {
+                               namePtr = Marshal.StringToHGlobalAnsi (name);
+                               var ret = mono_btls_x509_verify_param_set_host (
+                                       Handle.DangerousGetHandle (), namePtr, name.Length);
+                               CheckError (ret);
+                       } finally {
+                               if (namePtr != IntPtr.Zero)
+                                       Marshal.FreeHGlobal (namePtr);
+                       }
+               }
+
+               public void AddHost (string name)
+               {
+                       WantToModify ();
+                       IntPtr namePtr = IntPtr.Zero;
+                       try {
+                               namePtr = Marshal.StringToHGlobalAnsi (name);
+                               var ret = mono_btls_x509_verify_param_add_host (
+                                       Handle.DangerousGetHandle (), namePtr, name.Length);
+                               CheckError (ret);
+                       } finally {
+                               if (namePtr != IntPtr.Zero)
+                                       Marshal.FreeHGlobal (namePtr);
+                       }
+               }
+
+               public ulong GetFlags ()
+               {
+                       return mono_btls_x509_verify_param_get_flags (Handle.DangerousGetHandle ());
+               }
+
+               public void SetFlags (ulong flags)
+               {
+                       WantToModify ();
+                       var ret = mono_btls_x509_verify_param_set_flags (
+                               Handle.DangerousGetHandle (), flags);
+                       CheckError (ret);
+               }
+
+               public MonoBtlsX509VerifyFlags GetMonoFlags ()
+               {
+                       return mono_btls_x509_verify_param_get_mono_flags (
+                               Handle.DangerousGetHandle ());
+               }
+
+               public void SetMonoFlags (MonoBtlsX509VerifyFlags flags)
+               {
+                       WantToModify ();
+                       var ret = mono_btls_x509_verify_param_set_mono_flags (
+                               Handle.DangerousGetHandle (), flags);
+                       CheckError (ret);
+               }
+
+               public void SetPurpose (MonoBtlsX509Purpose purpose)
+               {
+                       WantToModify ();
+                       var ret = mono_btls_x509_verify_param_set_purpose (
+                               Handle.DangerousGetHandle (), purpose);
+                       CheckError (ret);
+               }
+
+               public int GetDepth ()
+               {
+                       return mono_btls_x509_verify_param_get_depth (Handle.DangerousGetHandle ());
+               }
+
+               public void SetDepth (int depth)
+               {
+                       WantToModify ();
+                       var ret = mono_btls_x509_verify_param_set_depth (
+                               Handle.DangerousGetHandle (), depth);
+                       CheckError (ret);
+               }
+
+               public void SetTime (DateTime time)
+               {
+                       WantToModify ();
+                       var epoch = new DateTime (1970, 1, 1);
+                       var ticks = (long)time.Subtract (epoch).TotalSeconds;
+                       var ret = mono_btls_x509_verify_param_set_time (
+                               Handle.DangerousGetHandle (), ticks);
+                       CheckError (ret);
+               }
+
+               public string GetPeerName ()
+               {
+                       var peer = mono_btls_x509_verify_param_get_peername (Handle.DangerousGetHandle ());
+                       if (peer == IntPtr.Zero)
+                               return null;
+                       return Marshal.PtrToStringAnsi (peer);
+               }
+       }
+}
+#endif
diff --git a/mcs/class/System/Mono.Btls/X509CertificateImplBtls.cs b/mcs/class/System/Mono.Btls/X509CertificateImplBtls.cs
new file mode 100644 (file)
index 0000000..022eb11
--- /dev/null
@@ -0,0 +1,390 @@
+//
+// X509CertificateImplBtls.cs
+//
+// Author:
+//       Martin Baulig <martin.baulig@xamarin.com>
+//
+// Copyright (c) 2016 Xamarin Inc. (http://www.xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+#if SECURITY_DEP
+using System;
+using System.Text;
+using System.Security;
+using System.Security.Cryptography;
+using System.Security.Cryptography.X509Certificates;
+using MX = Mono.Security.X509;
+
+namespace Mono.Btls
+{
+       class X509CertificateImplBtls : X509Certificate2Impl
+       {
+               MonoBtlsX509 x509;
+               MonoBtlsKey privateKey;
+               X500DistinguishedName subjectName;
+               X500DistinguishedName issuerName;
+               X509CertificateImplCollection intermediateCerts;
+               PublicKey publicKey;
+               bool archived;
+               bool disallowFallback;
+
+               internal X509CertificateImplBtls (bool disallowFallback = false)
+               {
+                       this.disallowFallback = disallowFallback;
+               }
+
+               internal X509CertificateImplBtls (MonoBtlsX509 x509, bool disallowFallback = false)
+               {
+                       this.disallowFallback = disallowFallback;
+                       this.x509 = x509.Copy ();
+               }
+
+               X509CertificateImplBtls (X509CertificateImplBtls other)
+               {
+                       disallowFallback = other.disallowFallback;
+                       x509 = other.x509 != null ? other.x509.Copy () : null;
+                       privateKey = other.privateKey != null ? other.privateKey.Copy () : null;
+                       if (other.intermediateCerts != null)
+                               intermediateCerts = other.intermediateCerts.Clone ();
+               }
+
+               internal X509CertificateImplBtls (byte[] data, MonoBtlsX509Format format, bool disallowFallback = false)
+               {
+                       this.disallowFallback = disallowFallback;
+                       x509 = MonoBtlsX509.LoadFromData (data, format);
+               }
+
+               public override bool IsValid {
+                       get { return x509 != null && x509.IsValid; }
+               }
+
+               public override IntPtr Handle {
+                       get { return x509.Handle.DangerousGetHandle (); }
+               }
+
+               public override IntPtr GetNativeAppleCertificate ()
+               {
+                       return IntPtr.Zero;
+               }
+
+               internal MonoBtlsX509 X509 {
+                       get {
+                               ThrowIfContextInvalid ();
+                               return x509;
+                       }
+               }
+
+               internal MonoBtlsKey NativePrivateKey {
+                       get {
+                               ThrowIfContextInvalid ();
+                               return privateKey;
+                       }
+               }
+
+               public override X509CertificateImpl Clone ()
+               {
+                       ThrowIfContextInvalid ();
+                       return new X509CertificateImplBtls (this);
+               }
+
+               public override bool Equals (X509CertificateImpl other, out bool result)
+               {
+                       var otherBoringImpl = other as X509CertificateImplBtls;
+                       if (otherBoringImpl == null) {
+                               result = false;
+                               return false;
+                       }
+
+                       result = MonoBtlsX509.Compare (X509, otherBoringImpl.X509) == 0;
+                       return true;
+               }
+
+               protected override byte [] GetCertHash (bool lazy)
+               {
+                       return X509.GetCertHash ();
+               }
+
+               public override byte [] GetRawCertData ()
+               {
+                       return X509.GetRawData (MonoBtlsX509Format.DER);
+               }
+
+               public override string GetSubjectName (bool legacyV1Mode)
+               {
+                       if (legacyV1Mode)
+                               return SubjectName.Decode (X500DistinguishedNameFlags.None);
+                       return SubjectName.Name;
+               }
+
+               public override string GetIssuerName (bool legacyV1Mode)
+               {
+                       if (legacyV1Mode)
+                               return IssuerName.Decode (X500DistinguishedNameFlags.None);
+                       return IssuerName.Name;
+               }
+
+               public override DateTime GetValidFrom ()
+               {
+                       return X509.GetNotBefore ().ToLocalTime ();
+               }
+
+               public override DateTime GetValidUntil ()
+               {
+                       return X509.GetNotAfter ().ToLocalTime ();
+               }
+
+               public override byte[] GetPublicKey ()
+               {
+                       return X509.GetPublicKeyData ();
+               }
+
+               public override byte[] GetSerialNumber ()
+               {
+                       return X509.GetSerialNumber (true);
+               }
+
+               public override string GetKeyAlgorithm ()
+               {
+                       return PublicKey.Oid.Value;
+               }
+
+               public override byte[] GetKeyAlgorithmParameters ()
+               {
+                       return PublicKey.EncodedParameters.RawData;
+               }
+
+               public override byte [] Export (X509ContentType contentType, byte [] password)
+               {
+                       ThrowIfContextInvalid ();
+
+                       switch (contentType) {
+                       case X509ContentType.Cert:
+                               return GetRawCertData ();
+                       case X509ContentType.Pfx: // this includes Pkcs12
+                               // TODO
+                               throw new NotSupportedException ();
+                       case X509ContentType.SerializedCert:
+                               // TODO
+                               throw new NotSupportedException ();
+                       default:
+                               string msg = Locale.GetText ("This certificate format '{0}' cannot be exported.", contentType);
+                               throw new CryptographicException (msg);
+                       }
+               }
+
+               internal override X509CertificateImplCollection IntermediateCertificates {
+                       get { return intermediateCerts; }
+               }
+
+               public override string ToString (bool full)
+               {
+                       ThrowIfContextInvalid ();
+
+                       if (!full) {
+                               var summary = GetSubjectName (false);
+                               return string.Format ("[X509Certificate: {0}]", summary);
+                       }
+
+                       string nl = Environment.NewLine;
+                       StringBuilder sb = new StringBuilder ();
+                       sb.AppendFormat ("[Subject]{0}  {1}{0}{0}", nl, GetSubjectName (false));
+
+                       sb.AppendFormat ("[Issuer]{0}  {1}{0}{0}", nl, GetIssuerName (false));
+                       sb.AppendFormat ("[Not Before]{0}  {1}{0}{0}", nl, GetValidFrom ().ToLocalTime ());
+                       sb.AppendFormat ("[Not After]{0}  {1}{0}{0}", nl, GetValidUntil ().ToLocalTime ());
+                       sb.AppendFormat ("[Thumbprint]{0}  {1}{0}", nl, X509Helper.ToHexString (GetCertHash ()));
+
+                       sb.Append (nl);
+                       return sb.ToString ();
+               }
+
+               protected override void Dispose (bool disposing)
+               {
+                       if (x509 != null) {
+                               x509.Dispose ();
+                               x509 = null;
+                       }
+               }
+
+#region X509Certificate2Impl
+
+               X509Certificate2Impl fallback;
+
+               void MustFallback ()
+               {
+                       if (disallowFallback)
+                               throw new InvalidOperationException ();
+                       if (fallback != null)
+                               return;
+                       fallback = X509Helper2.Import (GetRawCertData (), null, X509KeyStorageFlags.DefaultKeySet);
+               }
+
+               internal X509Certificate2Impl FallbackImpl {
+                       get {
+                               MustFallback ();
+                               return fallback;
+                       }
+               }
+
+               [MonoTODO]
+               public override bool Archived {
+                       get {
+                               ThrowIfContextInvalid ();
+                               return archived;
+                       }
+                       set {
+                               ThrowIfContextInvalid ();
+                               archived = value;
+                       }
+               }
+
+               public override X509ExtensionCollection Extensions {
+                       get { return FallbackImpl.Extensions; }
+               }
+
+               public override bool HasPrivateKey {
+                       get { return FallbackImpl.HasPrivateKey; }
+               }
+
+               public override X500DistinguishedName IssuerName {
+                       get {
+                               ThrowIfContextInvalid ();
+                               if (issuerName == null) {
+                                       using (var xname = x509.GetIssuerName ()) {
+                                               var encoding = xname.GetRawData (false);
+                                               var canonEncoding = xname.GetRawData (true);
+                                               var name = MonoBtlsUtils.FormatName (xname, true, ", ", true);
+                                               issuerName = new X500DistinguishedName (encoding, canonEncoding, name);
+                                       }
+                               }
+                               return issuerName;
+                       }
+               }
+
+               public override AsymmetricAlgorithm PrivateKey {
+                       get { return FallbackImpl.PrivateKey; }
+                       set { FallbackImpl.PrivateKey = value; }
+               }
+
+               public override PublicKey PublicKey {
+                       get {
+                               ThrowIfContextInvalid ();
+                               if (publicKey == null) {
+                                       var keyAsn = X509.GetPublicKeyAsn1 ();
+                                       var keyParamAsn = X509.GetPublicKeyParameters ();
+                                       publicKey = new PublicKey (keyAsn.Oid, keyParamAsn, keyAsn);
+                               }
+                               return publicKey;
+                       }
+               }
+
+               public override Oid SignatureAlgorithm {
+                       get {
+                               ThrowIfContextInvalid ();
+                               return X509.GetSignatureAlgorithm ();
+                       }
+               }
+
+               public override X500DistinguishedName SubjectName {
+                       get {
+                               ThrowIfContextInvalid ();
+                               if (subjectName == null) {
+                                       using (var xname = x509.GetSubjectName ()) {
+                                               var encoding = xname.GetRawData (false);
+                                               var canonEncoding = xname.GetRawData (true);
+                                               var name = MonoBtlsUtils.FormatName (xname, true, ", ", true);
+                                               subjectName = new X500DistinguishedName (encoding, canonEncoding, name);
+                                       }
+                               }
+                               return subjectName;
+                       }
+               }
+
+               public override int Version {
+                       get { return X509.GetVersion (); }
+               }
+
+               public override string GetNameInfo (X509NameType nameType, bool forIssuer)
+               {
+                       return FallbackImpl.GetNameInfo (nameType, forIssuer);
+               }
+
+               public override void Import (byte [] data, string password, X509KeyStorageFlags keyStorageFlags)
+               {
+                       if (password == null) {
+                               // Does it look like PEM?
+                               if ((data.Length > 0) && (data [0] != 0x30))
+                                       x509 = MonoBtlsX509.LoadFromData (data, MonoBtlsX509Format.PEM);
+                               else
+                                       x509 = MonoBtlsX509.LoadFromData (data, MonoBtlsX509Format.DER);
+                               return;
+                       }
+
+                       using (var pkcs12 = new MonoBtlsPkcs12 ()) {
+                               pkcs12.Import (data, password);
+                               x509 = pkcs12.GetCertificate (0);
+                               if (pkcs12.HasPrivateKey)
+                                       privateKey = pkcs12.GetPrivateKey ();
+                               if (pkcs12.Count > 1) {
+                                       intermediateCerts = new X509CertificateImplCollection ();
+                                       for (int i = 0; i < pkcs12.Count; i++) {
+                                               using (var ic = pkcs12.GetCertificate (i)) {
+                                                       if (MonoBtlsX509.Compare (ic, x509) == 0)
+                                                               continue;
+                                                       var impl = new X509CertificateImplBtls (ic, true);
+                                                       intermediateCerts.Add (impl, true);
+                                               }
+                                       }
+                               }
+                       }
+               }
+
+               public override byte [] Export (X509ContentType contentType, string password)
+               {
+                       return FallbackImpl.Export (contentType, password);
+               }
+
+               public override bool Verify (X509Certificate2 thisCertificate)
+               {
+                       return FallbackImpl.Verify (thisCertificate);
+               }
+
+               public override void Reset ()
+               {
+                       if (x509 != null) {
+                               x509.Dispose ();
+                               x509 = null;
+                       }
+                       if (privateKey != null) {
+                               privateKey = null;
+                               privateKey = null;
+                       }
+                       subjectName = null;
+                       issuerName = null;
+                       archived = false;
+                       publicKey = null;
+                       intermediateCerts = null;
+                       if (fallback != null)
+                               fallback.Reset ();
+               }
+
+#endregion
+       }
+}
+#endif
diff --git a/mcs/class/System/Mono.Btls/X509ChainImplBtls.cs b/mcs/class/System/Mono.Btls/X509ChainImplBtls.cs
new file mode 100644 (file)
index 0000000..81fe569
--- /dev/null
@@ -0,0 +1,176 @@
+//
+// X509ChainImplBtls.cs
+//
+// Author:
+//       Martin Baulig <martin.baulig@xamarin.com>
+//
+// Copyright (c) 2016 Xamarin Inc. (http://www.xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+#if SECURITY_DEP
+using System;
+using System.Text;
+using System.Security;
+using System.Security.Cryptography;
+using System.Security.Cryptography.X509Certificates;
+using MX = Mono.Security.X509;
+
+namespace Mono.Btls
+{
+       class X509ChainImplBtls : X509ChainImpl
+       {
+               MonoBtlsX509StoreCtx storeCtx;
+               MonoBtlsX509Chain chain;
+               MonoBtlsX509Chain untrustedChain;
+               X509ChainElementCollection elements;
+               X509Certificate2Collection untrusted;
+               X509Certificate2[] certificates;
+               X509ChainPolicy policy;
+
+               internal X509ChainImplBtls (MonoBtlsX509Chain chain)
+               {
+                       this.chain = chain.Copy ();
+                       policy = new X509ChainPolicy ();
+               }
+
+               internal X509ChainImplBtls (MonoBtlsX509StoreCtx storeCtx)
+               {
+                       this.storeCtx = storeCtx.Copy ();
+                       this.chain = storeCtx.GetChain ();
+
+                       policy = new X509ChainPolicy ();
+                       using (var test = (IDisposable)null) {
+                               ;
+                       }
+
+                       untrustedChain = storeCtx.GetUntrusted ();
+
+                       if (untrustedChain != null) {
+                               untrusted = new X509Certificate2Collection ();
+                               policy.ExtraStore = untrusted;
+                               for (int i = 0; i < untrustedChain.Count; i++) {
+                                       using (var cert = untrustedChain.GetCertificate (i))
+                                       using (var impl = new X509CertificateImplBtls (cert))
+                                               untrusted.Add (new X509Certificate2 (impl));
+                               }
+                       }
+                       storeCtx.Test ();
+               }
+
+               internal X509ChainImplBtls ()
+               {
+                       chain = new MonoBtlsX509Chain ();
+                       elements = new X509ChainElementCollection ();
+                       policy = new X509ChainPolicy ();
+               }
+
+               public override bool IsValid {
+                       get { return chain != null && chain.IsValid; }
+               }
+
+               public override IntPtr Handle {
+                       get { return chain.Handle.DangerousGetHandle (); }
+               }
+
+               internal MonoBtlsX509Chain Chain {
+                       get {
+                               ThrowIfContextInvalid ();
+                               return chain;
+                       }
+               }
+
+               internal MonoBtlsX509StoreCtx StoreCtx {
+                       get {
+                               ThrowIfContextInvalid ();
+                               return storeCtx;
+                       }
+               }
+
+               public override X509ChainElementCollection ChainElements {
+                       get {
+                               ThrowIfContextInvalid ();
+                               if (elements != null)
+                                       return elements;
+
+                               elements = new X509ChainElementCollection ();
+                               certificates = new X509Certificate2 [chain.Count];
+
+                               for (int i = 0; i < certificates.Length; i++) {
+                                       var cert = chain.GetCertificate (i);
+                                       var impl = new X509CertificateImplBtls (cert);
+                                       certificates [i] = new X509Certificate2 (impl);
+                                       elements.Add (certificates [i]);
+                               }
+
+                               return elements;
+                       }
+               }
+
+               public override X509ChainPolicy ChainPolicy {
+                       get { return policy; }
+                       set { policy = value; }
+               }
+
+               public override X509ChainStatus[] ChainStatus {
+                       get { throw new NotImplementedException (); }
+               }
+
+               public override bool Build (X509Certificate2 certificate)
+               {
+                       return false;
+               }
+
+               public override void Reset ()
+               {
+                       if (certificates != null) {
+                               foreach (var certificate in certificates)
+                                       certificate.Dispose ();
+                               certificates = null;
+                       }
+                       if (elements != null) {
+                               elements.Clear ();
+                               elements = null;
+                       }
+               }
+
+               protected override void Dispose (bool disposing)
+               {
+                       if (disposing) {
+                               if (chain != null) {
+                                       chain.Dispose ();
+                                       chain = null;
+                               }
+                               if (storeCtx != null) {
+                                       storeCtx.Dispose ();
+                                       storeCtx = null;
+                               }
+                               if (untrustedChain != null) {
+                                       untrustedChain.Dispose ();
+                                       untrustedChain = null;
+                               }
+                               if (untrusted != null) {
+                                       foreach (var cert in untrusted)
+                                               cert.Dispose ();
+                               }
+                       }
+                       base.Dispose (disposing);
+               }
+       }
+}
+#endif
index 7ba425257f592e7432baac6850c980b0a5d22f94..6849b160bf35017241bdf78e4e6290bbf24748a8 100644 (file)
@@ -2,9 +2,7 @@
 #if SECURITY_DEP
 using System;
 using MSI = Mono.Security.Interface;
-#if HAVE_BTLS
 using Mono.Btls;
-#endif
 
 namespace Mono.Net.Security
 {
@@ -20,13 +18,9 @@ namespace Mono.Net.Security
                        case "legacy":
                                return new LegacyTlsProvider ();
                        case "btls":
-#if HAVE_BTLS
                                if (!MonoBtlsProvider.IsSupported ())
                                        throw new NotSupportedException ("BTLS in not supported!");
                                return new MonoBtlsProvider ();
-#else
-                               throw new NotSupportedException ("BTLS in not supported!");
-#endif
                        default:
                                throw new NotSupportedException (string.Format ("Invalid TLS Provider: `{0}'.", provider));
                        }
index 34d64334c1583e1ebe40d52830aabf5c1e07c8c4..059ef82a1770ed9927ab5a1b0fe4f8e5504808a3 100644 (file)
@@ -156,10 +156,8 @@ namespace Mono.Net.Security
                                        return;
                                providerRegistration = new Dictionary<string,string> ();
                                providerRegistration.Add ("legacy", "Mono.Net.Security.LegacyTlsProvider");
-#if HAVE_BTLS
                                if (Mono.Btls.MonoBtlsProvider.IsSupported ())
                                        providerRegistration.Add ("btls", "Mono.Btls.MonoBtlsProvider");
-#endif
                                X509Helper2.Initialize ();
                        }
                }
index 92709e04fa8a77a2c599fd7b7121d55e6a86b45b..1dd6b2fdac1eb597268b956eab7e90a719bf3cd1 100644 (file)
@@ -37,10 +37,8 @@ using MonoSecurity::Mono.Security.Interface;
 using Mono.Security.Interface;
 #endif
 
-#if HAVE_BTLS
 using Mono.Btls;
 #endif
-#endif
 
 using System.IO;
 using System.Text;
@@ -56,7 +54,7 @@ namespace System.Security.Cryptography.X509Certificates
 
                internal static long GetSubjectNameHash (X509CertificateImpl impl)
                {
-#if SECURITY_DEP && HAVE_BTLS
+#if SECURITY_DEP
                        using (var x509 = GetNativeInstance (impl))
                                return GetSubjectNameHash (x509);
 #else
@@ -71,7 +69,7 @@ namespace System.Security.Cryptography.X509Certificates
 
                internal static void ExportAsPEM (X509CertificateImpl impl, Stream stream, bool includeHumanReadableForm)
                {
-#if SECURITY_DEP && HAVE_BTLS
+#if SECURITY_DEP
                        using (var x509 = GetNativeInstance (impl))
                                ExportAsPEM (x509, stream, includeHumanReadableForm);
 #else
@@ -90,7 +88,6 @@ namespace System.Security.Cryptography.X509Certificates
                        X509Helper.ThrowIfContextInvalid (impl);
                }
 
-#if HAVE_BTLS
                static MonoBtlsX509 GetNativeInstance (X509CertificateImpl impl)
                {
                        ThrowIfContextInvalid (impl);
@@ -113,7 +110,6 @@ namespace System.Security.Cryptography.X509Certificates
                                x509.ExportAsPEM (bio, includeHumanReadableForm);
                        }
                }
-#endif
 
                internal static X509Certificate2Impl Import (byte[] rawData, string password, X509KeyStorageFlags keyStorageFlags)
                {
index 0e6fc9187a98e2c237a73f44de1789c8bcd8e722..eca011f5bae7492477124fe6e7ff515c19d7c35a 100644 (file)
@@ -538,6 +538,45 @@ System.Windows.Input/ICommand.cs
 
 System/IOSelector.cs
 
+Mono.Btls/MonoBtlsBio.cs
+Mono.Btls/MonoBtlsContext.cs
+Mono.Btls/MonoBtlsError.cs
+Mono.Btls/MonoBtlsException.cs
+Mono.Btls/MonoBtlsKey.cs
+Mono.Btls/MonoBtlsObject.cs
+Mono.Btls/MonoBtlsPkcs12.cs
+Mono.Btls/MonoBtlsProvider.cs
+Mono.Btls/MonoBtlsSsl.cs
+Mono.Btls/MonoBtlsSslCtx.cs
+Mono.Btls/MonoBtlsSslError.cs
+Mono.Btls/MonoBtlsStream.cs
+Mono.Btls/MonoBtlsUtils.cs
+Mono.Btls/MonoBtlsX509.cs
+Mono.Btls/MonoBtlsX509Chain.cs
+Mono.Btls/MonoBtlsX509Crl.cs
+Mono.Btls/MonoBtlsX509Error.cs
+Mono.Btls/MonoBtlsX509Exception.cs
+Mono.Btls/MonoBtlsX509FileType.cs
+Mono.Btls/MonoBtlsX509Format.cs
+Mono.Btls/MonoBtlsX509Lookup.cs
+Mono.Btls/MonoBtlsX509LookupMono.cs
+Mono.Btls/MonoBtlsX509LookupMonoCollection.cs
+Mono.Btls/MonoBtlsX509LookupType.cs
+Mono.Btls/MonoBtlsX509Name.cs
+Mono.Btls/MonoBtlsX509NameList.cs
+Mono.Btls/MonoBtlsX509NameEntryType.cs
+Mono.Btls/MonoBtlsX509Purpose.cs
+Mono.Btls/MonoBtlsX509Revoked.cs
+Mono.Btls/MonoBtlsX509Store.cs
+Mono.Btls/MonoBtlsX509StoreCtx.cs
+Mono.Btls/MonoBtlsX509StoreManager.cs
+Mono.Btls/MonoBtlsX509StoreType.cs
+Mono.Btls/MonoBtlsX509TrustKind.cs
+Mono.Btls/MonoBtlsX509VerifyFlags.cs
+Mono.Btls/MonoBtlsX509VerifyParam.cs
+Mono.Btls/X509CertificateImplBtls.cs
+Mono.Btls/X509ChainImplBtls.cs
+
 Mono.Net.Security/AsyncProtocolRequest.cs
 Mono.Net.Security/CallbackHelpers.cs
 Mono.Net.Security/ChainValidationHelper.cs
index b971e3d0358f4ba1e8c549cc9544c6501675231d..8eb0ae99dc15857a48aee48b7ea09ff939e209fd 100644 (file)
@@ -302,6 +302,45 @@ Mono.Net.Security/MonoTlsStream.cs
 Mono.Net.Security/NoReflectionHelper.cs
 Mono.Net.Security/SystemCertificateValidator.cs
 
+Mono.Btls/MonoBtlsBio.cs
+Mono.Btls/MonoBtlsContext.cs
+Mono.Btls/MonoBtlsError.cs
+Mono.Btls/MonoBtlsException.cs
+Mono.Btls/MonoBtlsKey.cs
+Mono.Btls/MonoBtlsObject.cs
+Mono.Btls/MonoBtlsPkcs12.cs
+Mono.Btls/MonoBtlsProvider.cs
+Mono.Btls/MonoBtlsSsl.cs
+Mono.Btls/MonoBtlsSslCtx.cs
+Mono.Btls/MonoBtlsSslError.cs
+Mono.Btls/MonoBtlsStream.cs
+Mono.Btls/MonoBtlsUtils.cs
+Mono.Btls/MonoBtlsX509.cs
+Mono.Btls/MonoBtlsX509Chain.cs
+Mono.Btls/MonoBtlsX509Crl.cs
+Mono.Btls/MonoBtlsX509Error.cs
+Mono.Btls/MonoBtlsX509Exception.cs
+Mono.Btls/MonoBtlsX509FileType.cs
+Mono.Btls/MonoBtlsX509Format.cs
+Mono.Btls/MonoBtlsX509Lookup.cs
+Mono.Btls/MonoBtlsX509LookupMonoCollection.cs
+Mono.Btls/MonoBtlsX509LookupMono.cs
+Mono.Btls/MonoBtlsX509LookupType.cs
+Mono.Btls/MonoBtlsX509Name.cs
+Mono.Btls/MonoBtlsX509NameList.cs
+Mono.Btls/MonoBtlsX509NameEntryType.cs
+Mono.Btls/MonoBtlsX509Purpose.cs
+Mono.Btls/MonoBtlsX509Revoked.cs
+Mono.Btls/MonoBtlsX509Store.cs
+Mono.Btls/MonoBtlsX509StoreCtx.cs
+Mono.Btls/MonoBtlsX509StoreManager.cs
+Mono.Btls/MonoBtlsX509StoreType.cs
+Mono.Btls/MonoBtlsX509TrustKind.cs
+Mono.Btls/MonoBtlsX509VerifyFlags.cs
+Mono.Btls/MonoBtlsX509VerifyParam.cs
+Mono.Btls/X509CertificateImplBtls.cs
+Mono.Btls/X509ChainImplBtls.cs
+
 ReferenceSources/AutoWebProxyScriptEngine.cs
 ReferenceSources/AssertWrapper.cs
 ReferenceSources/CAPI.cs
index 686004bd3b16c16676290b8c5bec21daaa5b0827..c2950c536caf33f5d6f337df9463118118f248e8 100644 (file)
@@ -1,3 +1,4 @@
 #include mobile_System.dll.sources
 System/AndroidPlatform.cs
 Mono.Net.Security/MonoTlsProviderFactory.Droid.cs
+Mono.Btls/MonoBtlsX509LookupAndroid.cs
index 693318cbea7e07fdb27df8413379a15d159e7ac0..af120d403ed56646c67d8ad8299c5779f5a6cb12 100644 (file)
@@ -47,7 +47,8 @@ net_4_5_dirs := \
        mdbrebase       \
        ikdasm          \
        mono-symbolicate        \
-       linker-analyzer
+       linker-analyzer \
+       btls
 
 build_SUBDIRS = gacutil security culevel cil-stringreplacer commoncryptogenerator
 net_4_5_SUBDIRS = gacutil
diff --git a/mcs/tools/btls/AssemblyInfo.cs b/mcs/tools/btls/AssemblyInfo.cs
new file mode 100644 (file)
index 0000000..06f8d61
--- /dev/null
@@ -0,0 +1,26 @@
+using System;
+using System.Diagnostics;
+using System.Reflection;
+using System.Resources;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+[assembly: AssemblyTitle ("btls-cert-sync")]
+[assembly: AssemblyDescription ("btls-cert-sync")]
+[assembly: AssemblyDefaultAlias ("btls-cert-sync")]
+
+[assembly: AssemblyCompany (Consts.MonoCompany)]
+[assembly: AssemblyProduct (Consts.MonoProduct)]
+[assembly: AssemblyCopyright (Consts.MonoCopyright)]
+[assembly: AssemblyVersion (Consts.FxVersion)]
+[assembly: AssemblyFileVersion (Consts.FxFileVersion)]
+[assembly: SatelliteContractVersion (Consts.FxVersion)]
+[assembly: AssemblyInformationalVersion (Consts.FxFileVersion)]
+
+[assembly: CLSCompliant (true)]
+[assembly: NeutralResourcesLanguage ("en-US")]
+
+[assembly: ComVisible (false)]
+
+[assembly: AssemblyDelaySign (true)]
+[assembly: AssemblyKeyFile ("../../class/mono.pub")]
diff --git a/mcs/tools/btls/Makefile b/mcs/tools/btls/Makefile
new file mode 100644 (file)
index 0000000..b871a0f
--- /dev/null
@@ -0,0 +1,9 @@
+thisdir = tools/btls
+SUBDIRS = 
+include ../../build/rules.make
+
+LOCAL_MCS_FLAGS =
+LIB_REFS = System Mono.Security Mono.Btls.Interface
+PROGRAM = btls-cert-sync.exe
+
+include ../../build/executable.make
diff --git a/mcs/tools/btls/btls-cert-sync.cs b/mcs/tools/btls/btls-cert-sync.cs
new file mode 100644 (file)
index 0000000..0ef071f
--- /dev/null
@@ -0,0 +1,61 @@
+using System;
+using System.IO;
+using System.Text;
+using System.Security.Cryptography.X509Certificates;
+using Mono.Btls;
+
+namespace Mono.Btls
+{
+       static class BtlsCertSync
+       {
+               static void Main (string[] args)
+               {
+                       if (!MonoBtlsProvider.IsSupported ()) {
+                               Console.Error.WriteLine ("BTLS is not supported in this runtime!");
+                               Environment.Exit (255);
+                       }
+
+                       var configPath = Environment.GetFolderPath (Environment.SpecialFolder.ApplicationData);
+                       configPath = Path.Combine (configPath, ".mono");
+
+                       var oldStorePath = Path.Combine (configPath, "certs", "Trust");
+                       var newStorePath = MonoBtlsX509StoreManager.GetStorePath (MonoBtlsX509StoreType.UserTrustedRoots);
+
+                       if (!Directory.Exists (oldStorePath)) {
+                               Console.WriteLine ("Old trust store {0} does not exist.");
+                               Environment.Exit (255);
+                       }
+
+                       if (Directory.Exists (newStorePath))
+                               Directory.Delete (newStorePath, true);
+                       Directory.CreateDirectory (newStorePath);
+
+                       var oldfiles = Directory.GetFiles (oldStorePath, "*.cer");
+                       Console.WriteLine ("Found {0} files in the old store.", oldfiles.Length);
+
+                       foreach (var file in oldfiles) {
+                               Console.WriteLine ("Converting {0}.", file);
+                               var data = File.ReadAllBytes (file);
+                               using (var x509 = MonoBtlsX509.LoadFromData (data, MonoBtlsX509Format.DER)) {
+                                       ConvertToNewFormat (newStorePath, x509);
+                               }
+                       }
+               }
+
+               static void ConvertToNewFormat (string root, MonoBtlsX509 x509)
+               {
+                       long hash = x509.GetSubjectNameHash ();
+
+                       string newName;
+                       int index = 0;
+                       do {
+                               newName = Path.Combine (root, string.Format ("{0:x8}.{1}", hash, index++));
+                       } while (File.Exists (newName));
+                       Console.WriteLine ("  new name: {0}", newName);
+
+                       using (var stream = new FileStream (newName, FileMode.Create))
+                       using (var bio = MonoBtlsBio.CreateMonoStream (stream))
+                                x509.ExportAsPEM (bio, true);
+               }
+       }
+}
diff --git a/mcs/tools/btls/btls-cert-sync.exe.sources b/mcs/tools/btls/btls-cert-sync.exe.sources
new file mode 100644 (file)
index 0000000..706d78f
--- /dev/null
@@ -0,0 +1,4 @@
+../../build/common/SR.cs
+../../build/common/Consts.cs
+AssemblyInfo.cs
+btls-cert-sync.cs