From 0f8f0c543c1f19b10b3bf46ca606db4903e3b708 Mon Sep 17 00:00:00 2001 From: Martin Baulig Date: Fri, 30 Sep 2016 13:47:22 +0200 Subject: [PATCH] [BTLS]: Add managed BTLS sources. * 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. --- mcs/class/Makefile | 2 + mcs/class/Mono.Btls.Interface/Makefile | 12 + .../Mono.Btls.Interface.dll.sources | 22 + .../Mono.Btls.Interface/BtlsObject.cs | 73 +++ .../Mono.Btls.Interface/BtlsProvider.cs | 106 ++++ .../Mono.Btls.Interface/BtlsX509.cs | 132 +++++ .../Mono.Btls.Interface/BtlsX509Chain.cs | 58 +++ .../Mono.Btls.Interface/BtlsX509Error.cs | 110 +++++ .../Mono.Btls.Interface/BtlsX509Format.cs | 37 ++ .../Mono.Btls.Interface/BtlsX509Lookup.cs | 72 +++ .../Mono.Btls.Interface/BtlsX509Name.cs | 62 +++ .../Mono.Btls.Interface/BtlsX509Purpose.cs | 43 ++ .../Mono.Btls.Interface/BtlsX509Store.cs | 91 ++++ .../Mono.Btls.Interface/BtlsX509StoreCtx.cs | 71 +++ .../BtlsX509StoreManager.cs | 44 ++ .../Mono.Btls.Interface/BtlsX509StoreType.cs | 43 ++ .../Mono.Btls.Interface/BtlsX509TrustKind.cs | 42 ++ .../BtlsX509VerifyFlags.cs | 38 ++ .../BtlsX509VerifyParam.cs | 91 ++++ .../Mono.Btls.Interface/VersionInfo.cs | 34 ++ .../Properties/AssemblyInfo.cs | 47 ++ mcs/class/Mono.Btls.Interface/README.md | 9 + mcs/class/System/Assembly/AssemblyInfo.cs | 2 + mcs/class/System/Mono.Btls/MonoBtlsBio.cs | 449 +++++++++++++++++ mcs/class/System/Mono.Btls/MonoBtlsContext.cs | 455 +++++++++++++++++ mcs/class/System/Mono.Btls/MonoBtlsError.cs | 83 ++++ .../System/Mono.Btls/MonoBtlsException.cs | 53 ++ mcs/class/System/Mono.Btls/MonoBtlsKey.cs | 106 ++++ mcs/class/System/Mono.Btls/MonoBtlsObject.cs | 143 ++++++ mcs/class/System/Mono.Btls/MonoBtlsPkcs12.cs | 144 ++++++ .../System/Mono.Btls/MonoBtlsProvider.cs | 268 ++++++++++ mcs/class/System/Mono.Btls/MonoBtlsSsl.cs | 409 +++++++++++++++ mcs/class/System/Mono.Btls/MonoBtlsSslCtx.cs | 260 ++++++++++ .../System/Mono.Btls/MonoBtlsSslError.cs | 47 ++ mcs/class/System/Mono.Btls/MonoBtlsStream.cs | 65 +++ mcs/class/System/Mono.Btls/MonoBtlsUtils.cs | 186 +++++++ mcs/class/System/Mono.Btls/MonoBtlsX509.cs | 465 ++++++++++++++++++ .../System/Mono.Btls/MonoBtlsX509Chain.cs | 122 +++++ mcs/class/System/Mono.Btls/MonoBtlsX509Crl.cs | 188 +++++++ .../System/Mono.Btls/MonoBtlsX509Error.cs | 111 +++++ .../System/Mono.Btls/MonoBtlsX509Exception.cs | 56 +++ .../System/Mono.Btls/MonoBtlsX509FileType.cs | 37 ++ .../System/Mono.Btls/MonoBtlsX509Format.cs | 36 ++ .../System/Mono.Btls/MonoBtlsX509Lookup.cs | 217 ++++++++ .../Mono.Btls/MonoBtlsX509LookupAndroid.cs | 43 ++ .../Mono.Btls/MonoBtlsX509LookupMono.cs | 128 +++++ .../MonoBtlsX509LookupMonoCollection.cs | 102 ++++ .../Mono.Btls/MonoBtlsX509LookupType.cs | 39 ++ .../System/Mono.Btls/MonoBtlsX509Name.cs | 216 ++++++++ .../Mono.Btls/MonoBtlsX509NameEntryType.cs | 51 ++ .../System/Mono.Btls/MonoBtlsX509NameList.cs | 121 +++++ .../System/Mono.Btls/MonoBtlsX509Purpose.cs | 43 ++ .../System/Mono.Btls/MonoBtlsX509Revoked.cs | 120 +++++ .../System/Mono.Btls/MonoBtlsX509Store.cs | 230 +++++++++ .../System/Mono.Btls/MonoBtlsX509StoreCtx.cs | 252 ++++++++++ .../Mono.Btls/MonoBtlsX509StoreManager.cs | 120 +++++ .../System/Mono.Btls/MonoBtlsX509StoreType.cs | 40 ++ .../System/Mono.Btls/MonoBtlsX509TrustKind.cs | 42 ++ .../Mono.Btls/MonoBtlsX509VerifyFlags.cs | 39 ++ .../Mono.Btls/MonoBtlsX509VerifyParam.cs | 277 +++++++++++ .../Mono.Btls/X509CertificateImplBtls.cs | 390 +++++++++++++++ .../System/Mono.Btls/X509ChainImplBtls.cs | 176 +++++++ .../MonoTlsProviderFactory.Droid.cs | 6 - .../MonoTlsProviderFactory.cs | 2 - .../X509Helper2.cs | 8 +- mcs/class/System/System.dll.sources | 39 ++ mcs/class/System/mobile_System.dll.sources | 39 ++ mcs/class/System/monodroid_System.dll.sources | 1 + mcs/tools/Makefile | 3 +- mcs/tools/btls/AssemblyInfo.cs | 26 + mcs/tools/btls/Makefile | 9 + mcs/tools/btls/btls-cert-sync.cs | 61 +++ mcs/tools/btls/btls-cert-sync.exe.sources | 4 + 73 files changed, 7753 insertions(+), 15 deletions(-) create mode 100644 mcs/class/Mono.Btls.Interface/Makefile create mode 100644 mcs/class/Mono.Btls.Interface/Mono.Btls.Interface.dll.sources create mode 100644 mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsObject.cs create mode 100644 mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsProvider.cs create mode 100644 mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsX509.cs create mode 100644 mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsX509Chain.cs create mode 100644 mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsX509Error.cs create mode 100644 mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsX509Format.cs create mode 100644 mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsX509Lookup.cs create mode 100644 mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsX509Name.cs create mode 100644 mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsX509Purpose.cs create mode 100644 mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsX509Store.cs create mode 100644 mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsX509StoreCtx.cs create mode 100644 mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsX509StoreManager.cs create mode 100644 mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsX509StoreType.cs create mode 100644 mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsX509TrustKind.cs create mode 100644 mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsX509VerifyFlags.cs create mode 100644 mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsX509VerifyParam.cs create mode 100644 mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/VersionInfo.cs create mode 100644 mcs/class/Mono.Btls.Interface/Properties/AssemblyInfo.cs create mode 100644 mcs/class/Mono.Btls.Interface/README.md create mode 100644 mcs/class/System/Mono.Btls/MonoBtlsBio.cs create mode 100644 mcs/class/System/Mono.Btls/MonoBtlsContext.cs create mode 100644 mcs/class/System/Mono.Btls/MonoBtlsError.cs create mode 100644 mcs/class/System/Mono.Btls/MonoBtlsException.cs create mode 100644 mcs/class/System/Mono.Btls/MonoBtlsKey.cs create mode 100644 mcs/class/System/Mono.Btls/MonoBtlsObject.cs create mode 100644 mcs/class/System/Mono.Btls/MonoBtlsPkcs12.cs create mode 100644 mcs/class/System/Mono.Btls/MonoBtlsProvider.cs create mode 100644 mcs/class/System/Mono.Btls/MonoBtlsSsl.cs create mode 100644 mcs/class/System/Mono.Btls/MonoBtlsSslCtx.cs create mode 100644 mcs/class/System/Mono.Btls/MonoBtlsSslError.cs create mode 100644 mcs/class/System/Mono.Btls/MonoBtlsStream.cs create mode 100644 mcs/class/System/Mono.Btls/MonoBtlsUtils.cs create mode 100644 mcs/class/System/Mono.Btls/MonoBtlsX509.cs create mode 100644 mcs/class/System/Mono.Btls/MonoBtlsX509Chain.cs create mode 100644 mcs/class/System/Mono.Btls/MonoBtlsX509Crl.cs create mode 100644 mcs/class/System/Mono.Btls/MonoBtlsX509Error.cs create mode 100644 mcs/class/System/Mono.Btls/MonoBtlsX509Exception.cs create mode 100644 mcs/class/System/Mono.Btls/MonoBtlsX509FileType.cs create mode 100644 mcs/class/System/Mono.Btls/MonoBtlsX509Format.cs create mode 100644 mcs/class/System/Mono.Btls/MonoBtlsX509Lookup.cs create mode 100644 mcs/class/System/Mono.Btls/MonoBtlsX509LookupAndroid.cs create mode 100644 mcs/class/System/Mono.Btls/MonoBtlsX509LookupMono.cs create mode 100644 mcs/class/System/Mono.Btls/MonoBtlsX509LookupMonoCollection.cs create mode 100644 mcs/class/System/Mono.Btls/MonoBtlsX509LookupType.cs create mode 100644 mcs/class/System/Mono.Btls/MonoBtlsX509Name.cs create mode 100644 mcs/class/System/Mono.Btls/MonoBtlsX509NameEntryType.cs create mode 100644 mcs/class/System/Mono.Btls/MonoBtlsX509NameList.cs create mode 100644 mcs/class/System/Mono.Btls/MonoBtlsX509Purpose.cs create mode 100644 mcs/class/System/Mono.Btls/MonoBtlsX509Revoked.cs create mode 100644 mcs/class/System/Mono.Btls/MonoBtlsX509Store.cs create mode 100644 mcs/class/System/Mono.Btls/MonoBtlsX509StoreCtx.cs create mode 100644 mcs/class/System/Mono.Btls/MonoBtlsX509StoreManager.cs create mode 100644 mcs/class/System/Mono.Btls/MonoBtlsX509StoreType.cs create mode 100644 mcs/class/System/Mono.Btls/MonoBtlsX509TrustKind.cs create mode 100644 mcs/class/System/Mono.Btls/MonoBtlsX509VerifyFlags.cs create mode 100644 mcs/class/System/Mono.Btls/MonoBtlsX509VerifyParam.cs create mode 100644 mcs/class/System/Mono.Btls/X509CertificateImplBtls.cs create mode 100644 mcs/class/System/Mono.Btls/X509ChainImplBtls.cs create mode 100644 mcs/tools/btls/AssemblyInfo.cs create mode 100644 mcs/tools/btls/Makefile create mode 100644 mcs/tools/btls/btls-cert-sync.cs create mode 100644 mcs/tools/btls/btls-cert-sync.exe.sources diff --git a/mcs/class/Makefile b/mcs/class/Makefile index e9c0a162151..ef78dfed837 100644 --- a/mcs/class/Makefile +++ b/mcs/class/Makefile @@ -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 index 00000000000..ea7e128a3f0 --- /dev/null +++ b/mcs/class/Mono.Btls.Interface/Makefile @@ -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 index 00000000000..710e06d35b9 --- /dev/null +++ b/mcs/class/Mono.Btls.Interface/Mono.Btls.Interface.dll.sources @@ -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 index 00000000000..b2e607c1773 --- /dev/null +++ b/mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsObject.cs @@ -0,0 +1,73 @@ +// +// BtlsObject.cs +// +// Author: +// Martin Baulig +// +// 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 index 00000000000..6a8d8106253 --- /dev/null +++ b/mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsProvider.cs @@ -0,0 +1,106 @@ +// +// BtlsProvider.cs +// +// Author: +// Martin Baulig +// +// 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 index 00000000000..abcdafbf006 --- /dev/null +++ b/mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsX509.cs @@ -0,0 +1,132 @@ +// +// BtlsX509.cs +// +// Author: +// Martin Baulig +// +// 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 index 00000000000..38e9ec5814e --- /dev/null +++ b/mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsX509Chain.cs @@ -0,0 +1,58 @@ +// +// BtlsX509Chain.cs +// +// Author: +// Martin Baulig +// +// 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 index 00000000000..089b4f23e09 --- /dev/null +++ b/mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsX509Error.cs @@ -0,0 +1,110 @@ +// +// BtlsX509Error.cs +// +// Author: +// Martin Baulig +// +// 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 index 00000000000..6ff63cec120 --- /dev/null +++ b/mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsX509Format.cs @@ -0,0 +1,37 @@ +// +// BtlsX509Format.cs +// +// Author: +// Martin Baulig +// +// 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 index 00000000000..836088fdd5b --- /dev/null +++ b/mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsX509Lookup.cs @@ -0,0 +1,72 @@ +// +// BtlsX509Lookup.cs +// +// Author: +// Martin Baulig +// +// 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 index 00000000000..69ca5a9e201 --- /dev/null +++ b/mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsX509Name.cs @@ -0,0 +1,62 @@ +// +// BtlsX509Name.cs +// +// Author: +// Martin Baulig +// +// 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 index 00000000000..ac906dfe85c --- /dev/null +++ b/mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsX509Purpose.cs @@ -0,0 +1,43 @@ +// +// BtlsX509Purpose.cs +// +// Author: +// Martin Baulig +// +// 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 index 00000000000..7b8f03fc7a6 --- /dev/null +++ b/mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsX509Store.cs @@ -0,0 +1,91 @@ +// +// BtlsX509Store.cs +// +// Author: +// Martin Baulig +// +// 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 index 00000000000..97d4a066f66 --- /dev/null +++ b/mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsX509StoreCtx.cs @@ -0,0 +1,71 @@ +// +// BtlsX509StoreCtx.cs +// +// Author: +// Martin Baulig +// +// 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 index 00000000000..1989ff44f27 --- /dev/null +++ b/mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsX509StoreManager.cs @@ -0,0 +1,44 @@ +// +// BtlsX509StoreManager.cs +// +// Author: +// Martin Baulig +// +// 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 index 00000000000..acdfb98d4c9 --- /dev/null +++ b/mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsX509StoreType.cs @@ -0,0 +1,43 @@ +// +// BtlsX509StoreType.cs +// +// Author: +// Martin Baulig +// +// 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 index 00000000000..9338ec61dbf --- /dev/null +++ b/mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsX509TrustKind.cs @@ -0,0 +1,42 @@ +// +// BtlsX509TrustKind.cs +// +// Author: +// Martin Baulig +// +// 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 index 00000000000..02640c82a17 --- /dev/null +++ b/mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsX509VerifyFlags.cs @@ -0,0 +1,38 @@ +// +// BtlsX509VerifyFlags.cs +// +// Author: +// Martin Baulig +// +// 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 index 00000000000..8d4e5eba5e3 --- /dev/null +++ b/mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/BtlsX509VerifyParam.cs @@ -0,0 +1,91 @@ +// +// BtlsX509VerifyParam.cs +// +// Author: +// Martin Baulig +// +// 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 index 00000000000..726c4ba88b3 --- /dev/null +++ b/mcs/class/Mono.Btls.Interface/Mono.Btls.Interface/VersionInfo.cs @@ -0,0 +1,34 @@ +// +// VersionInfo.cs +// +// Author: +// Martin Baulig +// +// 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 index 00000000000..5ff0bcb3b95 --- /dev/null +++ b/mcs/class/Mono.Btls.Interface/Properties/AssemblyInfo.cs @@ -0,0 +1,47 @@ +// +// AssemblyInfo.cs +// +// Author: +// Martin Baulig +// +// 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 index 00000000000..81e169c8b2b --- /dev/null +++ b/mcs/class/Mono.Btls.Interface/README.md @@ -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. + diff --git a/mcs/class/System/Assembly/AssemblyInfo.cs b/mcs/class/System/Assembly/AssemblyInfo.cs index a80606ef668..6ed83d7c1e0 100644 --- a/mcs/class/System/Assembly/AssemblyInfo.cs +++ b/mcs/class/System/Assembly/AssemblyInfo.cs @@ -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 index 00000000000..1fbe47117d1 --- /dev/null +++ b/mcs/class/System/Mono.Btls/MonoBtlsBio.cs @@ -0,0 +1,449 @@ +// +// MonoBtlsBio.cs +// +// Author: +// Martin Baulig +// +// 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 index 00000000000..f40107b674b --- /dev/null +++ b/mcs/class/System/Mono.Btls/MonoBtlsContext.cs @@ -0,0 +1,455 @@ +// +// MonoBtlsContext.cs +// +// Author: +// Martin Baulig +// +// 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 (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 index 00000000000..2645a926bc3 --- /dev/null +++ b/mcs/class/System/Mono.Btls/MonoBtlsError.cs @@ -0,0 +1,83 @@ +// +// MonoBtlsError.cs +// +// Author: +// Martin Baulig +// +// 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 index 00000000000..bf6b163f95f --- /dev/null +++ b/mcs/class/System/Mono.Btls/MonoBtlsException.cs @@ -0,0 +1,53 @@ +// +// MonoBtlsException.cs +// +// Author: +// Martin Baulig +// +// 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 index 00000000000..d7c802df359 --- /dev/null +++ b/mcs/class/System/Mono.Btls/MonoBtlsKey.cs @@ -0,0 +1,106 @@ +// +// MonoBtlsKey.cs +// +// Author: +// Martin Baulig +// +// 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 index 00000000000..8f3054318fe --- /dev/null +++ b/mcs/class/System/Mono.Btls/MonoBtlsObject.cs @@ -0,0 +1,143 @@ +// +// MonoBtlsObject.cs +// +// Author: +// Martin Baulig +// +// 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 index 00000000000..93ea13747aa --- /dev/null +++ b/mcs/class/System/Mono.Btls/MonoBtlsPkcs12.cs @@ -0,0 +1,144 @@ +// +// MonoBtlsPkcs12.cs +// +// Author: +// Martin Baulig +// +// 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 index 00000000000..fd3f2bee792 --- /dev/null +++ b/mcs/class/System/Mono.Btls/MonoBtlsProvider.cs @@ -0,0 +1,268 @@ +// +// MonoBtlsProvider.cs +// +// Author: +// Martin Baulig +// +// 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 index 00000000000..a9b5d87e935 --- /dev/null +++ b/mcs/class/System/Mono.Btls/MonoBtlsSsl.cs @@ -0,0 +1,409 @@ +// +// MonoBtlsSsl.cs +// +// Author: +// Martin Baulig +// +// 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 index 00000000000..517b158b8e0 --- /dev/null +++ b/mcs/class/System/Mono.Btls/MonoBtlsSslCtx.cs @@ -0,0 +1,260 @@ +// +// MonoBtlsSslCtx.cs +// +// Author: +// Martin Baulig +// +// 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 index 00000000000..38f6f4fb0e7 --- /dev/null +++ b/mcs/class/System/Mono.Btls/MonoBtlsSslError.cs @@ -0,0 +1,47 @@ +// +// MonoBtlsSslError.cs +// +// Author: +// Martin Baulig +// +// 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 index 00000000000..d2f32e98c65 --- /dev/null +++ b/mcs/class/System/Mono.Btls/MonoBtlsStream.cs @@ -0,0 +1,65 @@ +// +// MonoBtlsStream.cs +// +// Author: +// Martin Baulig +// +// 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 index 00000000000..c3dae84fd6f --- /dev/null +++ b/mcs/class/System/Mono.Btls/MonoBtlsUtils.cs @@ -0,0 +1,186 @@ +// +// MonoBtlsUtils.cs +// +// Author: +// Martin Baulig +// +// 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 index 00000000000..4d451b9b073 --- /dev/null +++ b/mcs/class/System/Mono.Btls/MonoBtlsX509.cs @@ -0,0 +1,465 @@ +// +// MonoBtlsX509.cs +// +// Author: +// Martin Baulig +// +// 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 index 00000000000..6926ae7e65b --- /dev/null +++ b/mcs/class/System/Mono.Btls/MonoBtlsX509Chain.cs @@ -0,0 +1,122 @@ +// +// MonoBtlsX509Chain.cs +// +// Author: +// Martin Baulig +// +// 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 index 00000000000..9b8a64f67b9 --- /dev/null +++ b/mcs/class/System/Mono.Btls/MonoBtlsX509Crl.cs @@ -0,0 +1,188 @@ +// +// MonoBtlsX509Crl.cs +// +// Author: +// Martin Baulig +// +// 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 index 00000000000..50196bfd49d --- /dev/null +++ b/mcs/class/System/Mono.Btls/MonoBtlsX509Error.cs @@ -0,0 +1,111 @@ +// +// MonoBtlsX509Error.cs +// +// Author: +// Martin Baulig +// +// 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 index 00000000000..588e7a7f692 --- /dev/null +++ b/mcs/class/System/Mono.Btls/MonoBtlsX509Exception.cs @@ -0,0 +1,56 @@ +// +// MonoBtlsX509Exception.cs +// +// Author: +// Martin Baulig +// +// 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 index 00000000000..67d26e6c357 --- /dev/null +++ b/mcs/class/System/Mono.Btls/MonoBtlsX509FileType.cs @@ -0,0 +1,37 @@ +// +// MonoBtlsX509FileType.cs +// +// Author: +// Martin Baulig +// +// 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 index 00000000000..551da69c4bf --- /dev/null +++ b/mcs/class/System/Mono.Btls/MonoBtlsX509Format.cs @@ -0,0 +1,36 @@ +// +// MonoBtlsX509Format.cs +// +// Author: +// Martin Baulig +// +// 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 index 00000000000..3e8fb299768 --- /dev/null +++ b/mcs/class/System/Mono.Btls/MonoBtlsX509Lookup.cs @@ -0,0 +1,217 @@ +// +// MonoBtlsX509Lookup.cs +// +// Author: +// Martin Baulig +// +// 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 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 (); + 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 index 00000000000..45f365ce3ee --- /dev/null +++ b/mcs/class/System/Mono.Btls/MonoBtlsX509LookupAndroid.cs @@ -0,0 +1,43 @@ +// +// MonoBtlsX509LookupAndroid.cs +// +// Author: +// Martin Baulig +// +// 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 index 00000000000..9dbecea3e84 --- /dev/null +++ b/mcs/class/System/Mono.Btls/MonoBtlsX509LookupMono.cs @@ -0,0 +1,128 @@ +// +// MonoBtlsX509LookupMono.cs +// +// Author: +// Martin Baulig +// +// 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 index 00000000000..8a854f6303a --- /dev/null +++ b/mcs/class/System/Mono.Btls/MonoBtlsX509LookupMonoCollection.cs @@ -0,0 +1,102 @@ +// +// MonoBtlsX509LookupMonoCollection.cs +// +// Author: +// Martin Baulig +// +// 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 index 00000000000..2cbdf7cb718 --- /dev/null +++ b/mcs/class/System/Mono.Btls/MonoBtlsX509LookupType.cs @@ -0,0 +1,39 @@ +// +// MonoBtlsX509LookupCollection.cs +// +// Author: +// Martin Baulig +// +// 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 index 00000000000..9b3b7230340 --- /dev/null +++ b/mcs/class/System/Mono.Btls/MonoBtlsX509Name.cs @@ -0,0 +1,216 @@ +// +// MonoBtlsX509Name.cs +// +// Author: +// Martin Baulig +// +// 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 index 00000000000..781d6917c9d --- /dev/null +++ b/mcs/class/System/Mono.Btls/MonoBtlsX509NameEntryType.cs @@ -0,0 +1,51 @@ +// +// MonoBtlsX509NameEntryType.cs +// +// Author: +// Martin Baulig +// +// 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 index 00000000000..cccc005f8d9 --- /dev/null +++ b/mcs/class/System/Mono.Btls/MonoBtlsX509NameList.cs @@ -0,0 +1,121 @@ +// +// MonoBtlsX509NameList.cs +// +// Author: +// Martin Baulig +// +// 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 index 00000000000..d80957c301b --- /dev/null +++ b/mcs/class/System/Mono.Btls/MonoBtlsX509Purpose.cs @@ -0,0 +1,43 @@ +// +// MonoBtlsX509Purpose.cs +// +// Author: +// Martin Baulig +// +// 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 index 00000000000..00aafa209fb --- /dev/null +++ b/mcs/class/System/Mono.Btls/MonoBtlsX509Revoked.cs @@ -0,0 +1,120 @@ +// +// MonoBtlsX509Revoked.cs +// +// Author: +// Martin Baulig +// +// 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 index 00000000000..2e03715ce34 --- /dev/null +++ b/mcs/class/System/Mono.Btls/MonoBtlsX509Store.cs @@ -0,0 +1,230 @@ +// +// MonoBtlsX509Store.cs +// +// Author: +// Martin Baulig +// +// 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 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 (); + + /* + * 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 index 00000000000..affb9883a02 --- /dev/null +++ b/mcs/class/System/Mono.Btls/MonoBtlsX509StoreCtx.cs @@ -0,0 +1,252 @@ +// +// MonoBtlsX509StoreCtx.cs +// +// Author: +// Martin Baulig +// +// 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 index 00000000000..13c92a29ef0 --- /dev/null +++ b/mcs/class/System/Mono.Btls/MonoBtlsX509StoreManager.cs @@ -0,0 +1,120 @@ +// +// MonoBtlsX509StoreManager.cs +// +// Author: +// Martin Baulig +// +// 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 index 00000000000..22cc0726cd7 --- /dev/null +++ b/mcs/class/System/Mono.Btls/MonoBtlsX509StoreType.cs @@ -0,0 +1,40 @@ +// +// MonoBtlsX509StoreType.cs +// +// Author: +// Martin Baulig +// +// 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 index 00000000000..e207683711b --- /dev/null +++ b/mcs/class/System/Mono.Btls/MonoBtlsX509TrustKind.cs @@ -0,0 +1,42 @@ +// +// MonoBtlsX509TrustKind.cs +// +// Author: +// Martin Baulig +// +// 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 index 00000000000..628633bcfd1 --- /dev/null +++ b/mcs/class/System/Mono.Btls/MonoBtlsX509VerifyFlags.cs @@ -0,0 +1,39 @@ +// +// MonoBtlsX509VerifyFlags.cs +// +// Author: +// Martin Baulig +// +// 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 index 00000000000..59c210b253e --- /dev/null +++ b/mcs/class/System/Mono.Btls/MonoBtlsX509VerifyParam.cs @@ -0,0 +1,277 @@ +// +// MonoBtlsX509VerifyParam.cs +// +// Author: +// Martin Baulig +// +// 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 index 00000000000..022eb11f9f2 --- /dev/null +++ b/mcs/class/System/Mono.Btls/X509CertificateImplBtls.cs @@ -0,0 +1,390 @@ +// +// X509CertificateImplBtls.cs +// +// Author: +// Martin Baulig +// +// 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 index 00000000000..81fe569645b --- /dev/null +++ b/mcs/class/System/Mono.Btls/X509ChainImplBtls.cs @@ -0,0 +1,176 @@ +// +// X509ChainImplBtls.cs +// +// Author: +// Martin Baulig +// +// 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 diff --git a/mcs/class/System/Mono.Net.Security/MonoTlsProviderFactory.Droid.cs b/mcs/class/System/Mono.Net.Security/MonoTlsProviderFactory.Droid.cs index 7ba425257f5..6849b160bf3 100644 --- a/mcs/class/System/Mono.Net.Security/MonoTlsProviderFactory.Droid.cs +++ b/mcs/class/System/Mono.Net.Security/MonoTlsProviderFactory.Droid.cs @@ -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)); } diff --git a/mcs/class/System/Mono.Net.Security/MonoTlsProviderFactory.cs b/mcs/class/System/Mono.Net.Security/MonoTlsProviderFactory.cs index 34d64334c15..059ef82a177 100644 --- a/mcs/class/System/Mono.Net.Security/MonoTlsProviderFactory.cs +++ b/mcs/class/System/Mono.Net.Security/MonoTlsProviderFactory.cs @@ -156,10 +156,8 @@ namespace Mono.Net.Security return; providerRegistration = new Dictionary (); providerRegistration.Add ("legacy", "Mono.Net.Security.LegacyTlsProvider"); -#if HAVE_BTLS if (Mono.Btls.MonoBtlsProvider.IsSupported ()) providerRegistration.Add ("btls", "Mono.Btls.MonoBtlsProvider"); -#endif X509Helper2.Initialize (); } } diff --git a/mcs/class/System/System.Security.Cryptography.X509Certificates/X509Helper2.cs b/mcs/class/System/System.Security.Cryptography.X509Certificates/X509Helper2.cs index 92709e04fa8..1dd6b2fdac1 100644 --- a/mcs/class/System/System.Security.Cryptography.X509Certificates/X509Helper2.cs +++ b/mcs/class/System/System.Security.Cryptography.X509Certificates/X509Helper2.cs @@ -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) { diff --git a/mcs/class/System/System.dll.sources b/mcs/class/System/System.dll.sources index 0e6fc9187a9..eca011f5bae 100644 --- a/mcs/class/System/System.dll.sources +++ b/mcs/class/System/System.dll.sources @@ -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 diff --git a/mcs/class/System/mobile_System.dll.sources b/mcs/class/System/mobile_System.dll.sources index b971e3d0358..8eb0ae99dc1 100644 --- a/mcs/class/System/mobile_System.dll.sources +++ b/mcs/class/System/mobile_System.dll.sources @@ -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 diff --git a/mcs/class/System/monodroid_System.dll.sources b/mcs/class/System/monodroid_System.dll.sources index 686004bd3b1..c2950c536ca 100644 --- a/mcs/class/System/monodroid_System.dll.sources +++ b/mcs/class/System/monodroid_System.dll.sources @@ -1,3 +1,4 @@ #include mobile_System.dll.sources System/AndroidPlatform.cs Mono.Net.Security/MonoTlsProviderFactory.Droid.cs +Mono.Btls/MonoBtlsX509LookupAndroid.cs diff --git a/mcs/tools/Makefile b/mcs/tools/Makefile index 693318cbea7..af120d403ed 100644 --- a/mcs/tools/Makefile +++ b/mcs/tools/Makefile @@ -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 index 00000000000..06f8d61c8d2 --- /dev/null +++ b/mcs/tools/btls/AssemblyInfo.cs @@ -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 index 00000000000..b871a0f5e14 --- /dev/null +++ b/mcs/tools/btls/Makefile @@ -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 index 00000000000..0ef071ffefa --- /dev/null +++ b/mcs/tools/btls/btls-cert-sync.cs @@ -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 index 00000000000..706d78f894b --- /dev/null +++ b/mcs/tools/btls/btls-cert-sync.exe.sources @@ -0,0 +1,4 @@ +../../build/common/SR.cs +../../build/common/Consts.cs +AssemblyInfo.cs +btls-cert-sync.cs -- 2.25.1