[BTLS]: Certificate cleanups and fixes. (#3706)
authorMartin Baulig <martin.baulig@xamarin.com>
Wed, 5 Oct 2016 11:05:24 +0000 (13:05 +0200)
committerMartin Baulig <martin.baulig@xamarin.com>
Wed, 5 Oct 2016 11:07:21 +0000 (13:07 +0200)
* [BTLS]: Allow fallback to MX.X509Certificate in X509CertificateImplBtls.

* [BTLS]: Fix X509Certificate2.MonoCertificate.

* X509Certificate2Impl.FallbackImpl: make abstract.

* X509Helper2.GetMonoCertificate(): new internal helper method.

* X509Certificate2.MonoCertificate: use X509Helper2.GetMonoCertificate().
  This is only used by X509ChainImplMono; we should investigate whether we
  could implement the missing APIs in BTLS.

* [BTLS]: Fully implement X509CertificateImplBtls.Import() and use correct semantics.

.NET's X509Certificate2.Import() uses several implicit fallbacks which we previously
did not handle in BTLS.

* you may provide a (unused) password when importing an unencrypted PKCS#8.

* when using null as password, it will attempt to use string.Empty if importing
  without password fails.

* [BTLS]: Implement X509CertificateImplBtls.PrivateKey.

* [BTLS]: Implement X509CertificateImplBtls.Export().

* [BTLS]: Implement X509CertificateImplBtls.Verify().

* [BTLS]: Fix X500DistinguishedName quoting.

* MonoBtlsUtils: don't quote special chars in UTF-16 strings.

* X500DistinguishedName: don't decode raw data when passed in a name.

* [ci] Test System.dll with both the legacy and btls TLS provider

* [ci] Only run the additional btls System.dll test run on OSX for now

Otherwise we might run it on platforms where btls isn't supported yet and get errors.

(cherry picked from commit 9638ee9ece023eb96f314de64624bf37ce4b7faf)

14 files changed:
mcs/class/System/Mono.Btls/MonoBtlsContext.cs
mcs/class/System/Mono.Btls/MonoBtlsKey.cs
mcs/class/System/Mono.Btls/MonoBtlsPkcs12.cs
mcs/class/System/Mono.Btls/MonoBtlsProvider.cs
mcs/class/System/Mono.Btls/MonoBtlsUtils.cs
mcs/class/System/Mono.Btls/MonoBtlsX509Name.cs
mcs/class/System/Mono.Btls/X509CertificateImplBtls.cs
mcs/class/System/System.Security.Cryptography.X509Certificates/X500DistinguishedName.cs
mcs/class/System/System.Security.Cryptography.X509Certificates/X509Certificate2.cs
mcs/class/System/System.Security.Cryptography.X509Certificates/X509Certificate2Impl.cs
mcs/class/System/System.Security.Cryptography.X509Certificates/X509Certificate2ImplMono.cs
mcs/class/System/System.Security.Cryptography.X509Certificates/X509Helper2.cs
mono/btls/btls-x509-name.c
mono/btls/btls-x509-name.h

index daacffa14e4065fd0e7418b5c6989e6c5460a3d9..c06688dc86eee8fdd083e5f42ce1c9c06bce3472 100644 (file)
@@ -212,17 +212,7 @@ namespace Mono.Btls
 
                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
+                       MonoBtlsProvider.SetupCertificateStore (ctx.CertificateStore);
 
                        if (Settings != null && Settings.TrustAnchors != null) {
                                var trust = IsServer ? MonoBtlsX509TrustKind.TRUST_CLIENT : MonoBtlsX509TrustKind.TRUST_SERVER;
index e3e3defe7ff3f2a41da4d6896ac4368114b67564..81280b54ece80f8580681a88adee175a04727daa 100644 (file)
@@ -86,6 +86,12 @@ namespace Mono.Btls
                        return buffer;
                }
 
+               public bool IsRsa {
+                       get {
+                               return mono_btls_key_is_rsa (Handle.DangerousGetHandle ()) != 0;
+                       }
+               }
+
                public MonoBtlsKey Copy ()
                {
                        CheckThrow ();
index 93ea13747aa3fa017e5d657eac5c8d65d133c7f2..a7d42a190b441406430c5635015b200217dd2c35 100644 (file)
@@ -113,7 +113,8 @@ namespace Mono.Btls
                        var passptr = IntPtr.Zero;
                        fixed (void* ptr = buffer)
                        try {
-                               passptr = Marshal.StringToHGlobalAnsi (password ?? string.Empty);
+                               if (password != null)
+                                       passptr = Marshal.StringToHGlobalAnsi (password);
                                var ret = mono_btls_pkcs12_import (
                                        Handle.DangerousGetHandle (), ptr,
                                        buffer.Length, passptr);
index fd3f2bee79203c7fe68c0a3539c3e1eea3d5fbed..1a5185a514ffb160568da3599098c5958833a5e6 100644 (file)
@@ -99,7 +99,7 @@ namespace Mono.Btls
                internal override X509Certificate2Impl GetNativeCertificate (
                        byte[] data, string password, X509KeyStorageFlags flags)
                {
-                       var impl = new X509CertificateImplBtls (true);
+                       var impl = new X509CertificateImplBtls (false);
                        impl.Import (data, password, flags);
                        return impl;
                }
@@ -154,8 +154,7 @@ namespace Mono.Btls
                        using (var nativeChain = MonoBtlsProvider.GetNativeChain (certificates))
                        using (var param = GetVerifyParam (targetHost, serverMode))
                        using (var storeCtx = new MonoBtlsX509StoreCtx ()) {
-                               store.LoadLocations (null, GetSystemStoreLocation ());
-                               store.SetDefaultPaths ();
+                               SetupCertificateStore (store);
 
                                storeCtx.Initialize (store, nativeChain);
 
@@ -177,6 +176,23 @@ namespace Mono.Btls
                        }
                }
 
+               internal static bool ValidateCertificate (MonoBtlsX509Chain chain, MonoBtlsX509VerifyParam param)
+               {
+                       using (var store = new MonoBtlsX509Store ())
+                       using (var storeCtx = new MonoBtlsX509StoreCtx ()) {
+                               SetupCertificateStore (store);
+
+                               storeCtx.Initialize (store, chain);
+
+                               if (param != null)
+                                       storeCtx.SetVerifyParam (param);
+
+                               var ret = storeCtx.Verify ();
+
+                               return ret == 1;
+                       }
+               }
+
                void CheckValidationResult (
                        ICertificateValidator validator, string targetHost, bool serverMode,
                        X509CertificateCollection certificates, bool wantsChain,
@@ -189,6 +205,21 @@ namespace Mono.Btls
                        }
                }
 
+               internal static void SetupCertificateStore (MonoBtlsX509Store store)
+               {
+#if MONODROID
+                       store.SetDefaultPaths ();
+                       store.AddAndroidLookup ();
+#else
+                       var userPath = MonoBtlsX509StoreManager.GetStorePath (MonoBtlsX509StoreType.UserTrustedRoots);
+                       if (Directory.Exists (userPath))
+                               store.AddDirectoryLookup (userPath, MonoBtlsX509FileType.PEM);
+                       var machinePath = MonoBtlsX509StoreManager.GetStorePath (MonoBtlsX509StoreType.MachineTrustedRoots);
+                       if (Directory.Exists (machinePath))
+                               store.AddDirectoryLookup (machinePath, MonoBtlsX509FileType.PEM);
+#endif
+               }
+
                public static string GetSystemStoreLocation ()
                {
 #if ANDROID
index c3dae84fd6f013ba85d6ac55088186d12d9d40cc..63dba5d698778162568e0b5695a18151fa7a9765 100644 (file)
@@ -55,7 +55,8 @@ namespace Mono.Btls
                                if (Compare (oidValue, emailOid))
                                        type = MonoBtlsX509NameEntryType.Email;
                        }
-                       var text = name.GetEntryValue (index);
+                       int tag;
+                       var text = name.GetEntryValue (index, out tag);
                        if (text == null)
                                return false;
                        var oid = name.GetEntryOid (index);
@@ -121,7 +122,7 @@ namespace Mono.Btls
 
                        // 16bits or 8bits string ? TODO not complete (+special chars!)
                        char[] specials = { ',', '+', '"', '\\', '<', '>', ';' };
-                       if (quotes) {
+                       if (quotes && tag != 0x1E) {
                                if ((text.IndexOfAny (specials, 0, text.Length) > 0) ||
                                    text.StartsWith (" ") || (text.EndsWith (" ")))
                                        text = "\"" + text + "\"";
index 9b3b7230340bc36c26cc02f56d134dcccf00f623..80a322caaf3f6882df62c1005af52248341afcd6 100644 (file)
@@ -80,7 +80,7 @@ namespace Mono.Btls
                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);
+               extern static int mono_btls_x509_name_get_entry_value (IntPtr name, int index, out int tag, out IntPtr str);
 
                [MethodImpl (MethodImplOptions.InternalCall)]
                extern unsafe static IntPtr mono_btls_x509_name_from_data (void* data, int len, int use_canon_enc);
@@ -185,13 +185,13 @@ namespace Mono.Btls
                        return bytes;
                }
 
-               public unsafe string GetEntryValue (int index)
+               public unsafe string GetEntryValue (int index, out int tag)
                {
                        if (index >= GetEntryCount ())
                                throw new ArgumentOutOfRangeException ();
                        IntPtr data;
                        var ret = mono_btls_x509_name_get_entry_value (
-                               Handle.DangerousGetHandle (), index, out data);
+                               Handle.DangerousGetHandle (), index, out tag, out data);
                        if (ret <= 0)
                                return null;
                        try {
index 022eb11f9f288d46c7bb8dfdfc560160ccf80401..ef077b80e9fedeea766e756fb2895e99c4786ff4 100644 (file)
 // 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
+
+#if MONO_SECURITY_ALIAS
+using MX = MonoSecurity::Mono.Security.X509;
+#else
+using MX = Mono.Security.X509;
+#endif
+
 using System;
 using System.Text;
+using System.Collections;
 using System.Security;
 using System.Security.Cryptography;
 using System.Security.Cryptography.X509Certificates;
-using MX = Mono.Security.X509;
+using Mono.Security.Cryptography;
 
 namespace Mono.Btls
 {
@@ -115,12 +126,12 @@ namespace Mono.Btls
                        return true;
                }
 
-               protected override byte [] GetCertHash (bool lazy)
+               protected override byte[] GetCertHash (bool lazy)
                {
                        return X509.GetCertHash ();
                }
 
-               public override byte [] GetRawCertData ()
+               public override byte[] GetRawCertData ()
                {
                        return X509.GetRawData (MonoBtlsX509Format.DER);
                }
@@ -169,7 +180,7 @@ namespace Mono.Btls
                        return PublicKey.EncodedParameters.RawData;
                }
 
-               public override byte [] Export (X509ContentType contentType, byte [] password)
+               public override byte[] Export (X509ContentType contentType, byte[] password)
                {
                        ThrowIfContextInvalid ();
 
@@ -232,10 +243,10 @@ namespace Mono.Btls
                                throw new InvalidOperationException ();
                        if (fallback != null)
                                return;
-                       fallback = X509Helper2.Import (GetRawCertData (), null, X509KeyStorageFlags.DefaultKeySet);
+                       fallback = X509Helper2.Import (GetRawCertData (), null, X509KeyStorageFlags.DefaultKeySet, true);
                }
 
-               internal X509Certificate2Impl FallbackImpl {
+               internal override X509Certificate2Impl FallbackImpl {
                        get {
                                MustFallback ();
                                return fallback;
@@ -259,7 +270,7 @@ namespace Mono.Btls
                }
 
                public override bool HasPrivateKey {
-                       get { return FallbackImpl.HasPrivateKey; }
+                       get { return privateKey != null; }
                }
 
                public override X500DistinguishedName IssuerName {
@@ -278,7 +289,12 @@ namespace Mono.Btls
                }
 
                public override AsymmetricAlgorithm PrivateKey {
-                       get { return FallbackImpl.PrivateKey; }
+                       get {
+                               if (privateKey == null || !privateKey.IsRsa)
+                                       return null;
+                               var bytes = privateKey.GetBytes (true);
+                               return PKCS8.PrivateKeyInfo.DecodeRSA (bytes);
+                       }
                        set { FallbackImpl.PrivateKey = value; }
                }
 
@@ -325,19 +341,62 @@ namespace Mono.Btls
                        return FallbackImpl.GetNameInfo (nameType, forIssuer);
                }
 
-               public override void Import (byte [] data, string password, X509KeyStorageFlags keyStorageFlags)
+               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;
+                               try {
+                                       Import (data);
+                               } catch (Exception e) {
+                                       try {
+                                                ImportPkcs12 (data, null);
+                                       } catch {
+                                               string msg = Locale.GetText ("Unable to decode certificate.");
+                                               // inner exception is the original (not second) exception
+                                               throw new CryptographicException (msg, e);
+                                       }
+                               }
+                       } else {
+                               // try PKCS#12
+                               try {
+                                       ImportPkcs12 (data, password);
+                               } catch (Exception e) {
+                                       try {
+                                               // it's possible to supply a (unrequired/unusued) password
+                                               // fix bug #79028
+                                               Import (data);
+                                       } catch {
+                                               string msg = Locale.GetText ("Unable to decode certificate.");
+                                               // inner exception is the original (not second) exception
+                                               throw new CryptographicException (msg, e);
+                                       }
+                               }
                        }
+               }
+
+               void Import (byte[] data)
+               {
+                       // 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);
+               }
 
+               void ImportPkcs12 (byte[] data, string password)
+               {
                        using (var pkcs12 = new MonoBtlsPkcs12 ()) {
-                               pkcs12.Import (data, password);
+                               if (string.IsNullOrEmpty (password)) {
+                                       try {
+                                               // Support both unencrypted PKCS#12..
+                                               pkcs12.Import (data, null);
+                                       } catch {
+                                               // ..and PKCS#12 encrypted with an empty password
+                                               pkcs12.Import (data, string.Empty);
+                                       }
+                               } else {
+                                       pkcs12.Import (data, password);
+                               }
+
                                x509 = pkcs12.GetCertificate (0);
                                if (pkcs12.HasPrivateKey)
                                        privateKey = pkcs12.GetPrivateKey ();
@@ -355,14 +414,60 @@ namespace Mono.Btls
                        }
                }
 
-               public override byte [] Export (X509ContentType contentType, string password)
+               public override byte[] Export (X509ContentType contentType, string password)
                {
-                       return FallbackImpl.Export (contentType, password);
+                       ThrowIfContextInvalid ();
+
+                       switch (contentType) {
+                       case X509ContentType.Cert:
+                               return GetRawCertData ();
+                       case X509ContentType.Pfx: // this includes Pkcs12
+                               return ExportPkcs12 (password);
+                       case X509ContentType.SerializedCert:
+                               // TODO
+                               throw new NotSupportedException ();
+                       default:
+                               string msg = Locale.GetText ("This certificate format '{0}' cannot be exported.", contentType);
+                               throw new CryptographicException (msg);
+                       }
+               }
+
+               byte[] ExportPkcs12 (string password)
+               {
+                       var pfx = new MX.PKCS12 ();
+                       try {
+                               var attrs = new Hashtable ();
+                               var localKeyId = new ArrayList ();
+                               localKeyId.Add (new byte[] { 1, 0, 0, 0 });
+                               attrs.Add (MX.PKCS9.localKeyId, localKeyId);
+                               if (password != null)
+                                       pfx.Password = password;
+                               pfx.AddCertificate (new MX.X509Certificate (GetRawCertData ()), attrs);
+                               if (IntermediateCertificates != null) {
+                                       for (int i = 0; i < IntermediateCertificates.Count; i++)
+                                               pfx.AddCertificate (new MX.X509Certificate (IntermediateCertificates [i].GetRawCertData ()));
+                               }
+                               var privateKey = PrivateKey;
+                               if (privateKey != null)
+                                       pfx.AddPkcs8ShroudedKeyBag (privateKey, attrs);
+                               return pfx.GetBytes ();
+                       } finally {
+                               pfx.Password = null;
+                       }
                }
 
                public override bool Verify (X509Certificate2 thisCertificate)
                {
-                       return FallbackImpl.Verify (thisCertificate);
+                       using (var chain = new MonoBtlsX509Chain ()) {
+                               chain.AddCertificate (x509.Copy ());
+                               if (intermediateCerts != null) {
+                                       for (int i = 0; i < intermediateCerts.Count; i++) {
+                                               var intermediate = (X509CertificateImplBtls)intermediateCerts [i];
+                                               chain.AddCertificate (intermediate.x509.Copy ());
+                                       }
+                               }
+                               return MonoBtlsProvider.ValidateCertificate (chain, null);
+                       }
                }
 
                public override void Reset ()
index 795f0d04b21acfabb51a09db288cfa3ccfecd274..068c63067cb354376335b7d0cf566a34c2b84449 100644 (file)
@@ -124,7 +124,6 @@ namespace System.Security.Cryptography.X509Certificates {
                }
 
                internal X500DistinguishedName (byte[] encoded, byte[] canonEncoding, string name)
-                       : this (encoded)
                {
                        this.canonEncoding = canonEncoding;
                        this.name = name;
index bd69c786b89b80f947a56046fa9d7eb45411e291..ef10413f59722853150a79935cca076d7e1fbcae 100644 (file)
@@ -399,13 +399,10 @@ namespace System.Security.Cryptography.X509Certificates {
                // internal stuff because X509Certificate2 isn't complete enough
                // (maybe X509Certificate3 will be better?)
 
-               [Obsolete ("KILL")]
+               [MonoTODO ("See comment in X509Helper2.GetMonoCertificate().")]
                internal MX.X509Certificate MonoCertificate {
                        get {
-                               var monoImpl = Impl as X509Certificate2ImplMono;
-                               if (monoImpl == null)
-                                       throw new NotSupportedException ();
-                               return monoImpl.MonoCertificate;
+                               return X509Helper2.GetMonoCertificate (this);
                        }
                }
 
index 234d0907f2dbcaedf74a722b331e2083aaebf8af..38797d55fcee583b75ca47f09158b8dea078a3dd 100644 (file)
@@ -71,6 +71,10 @@ namespace System.Security.Cryptography.X509Certificates
                        get;
                }
 
+               internal abstract X509Certificate2Impl FallbackImpl {
+                       get;
+               }
+
                public abstract string GetNameInfo (X509NameType nameType, bool forIssuer);
 
                public abstract void Import (byte[] rawData, string password, X509KeyStorageFlags keyStorageFlags);
index cdc14c49eb13e2d2479c961ce8e9a4a4243ce484..a16d6e069068d2bb5f5538059259f6ba7cd5240b 100644 (file)
@@ -483,6 +483,7 @@ namespace System.Security.Cryptography.X509Certificates
                [MonoTODO ("missing KeyStorageFlags support")]
                public override void Import (byte[] rawData, string password, X509KeyStorageFlags keyStorageFlags)
                {
+                       Reset ();
                        MX.X509Certificate cert = null;
                        if (password == null) {
                                try {
@@ -718,6 +719,10 @@ namespace System.Security.Cryptography.X509Certificates
                internal MX.X509Certificate MonoCertificate {
                        get { return _cert; }
                }
+
+               internal override X509Certificate2Impl FallbackImpl {
+                       get { return this; }
+               }
        }
 }
 
index 337dcaf9ed2dfa175757a106f15ec849a087f06e..9bbe99f86314cd4eb7e1eafbb667171e3133e079 100644 (file)
@@ -33,10 +33,12 @@ extern alias MonoSecurity;
 
 #if MONO_SECURITY_ALIAS
 using MonoSecurity::Mono.Security.Interface;
+using MX = MonoSecurity::Mono.Security.X509;
 #else
 #if !FEATURE_NO_BSD_SOCKETS
 using Mono.Security.Interface;
 #endif
+using MX = Mono.Security.X509;
 #endif
 
 #if !FEATURE_NO_BSD_SOCKETS
@@ -122,13 +124,15 @@ namespace System.Security.Cryptography.X509Certificates
                }
 #endif // !FEATURE_NO_BSD_SOCKETS
 
-               internal static X509Certificate2Impl Import (byte[] rawData, string password, X509KeyStorageFlags keyStorageFlags)
+               internal static X509Certificate2Impl Import (byte[] rawData, string password, X509KeyStorageFlags keyStorageFlags, bool disableProvider = false)
                {
 #if !FEATURE_NO_BSD_SOCKETS
-                       var provider = MonoTlsProviderFactory.GetProvider ();
-                       if (provider.HasNativeCertificates) {
-                               var impl = provider.GetNativeCertificate (rawData, password, keyStorageFlags);
-                               return impl;
+                       if (!disableProvider) {
+                               var provider = MonoTlsProviderFactory.GetProvider ();
+                               if (provider.HasNativeCertificates) {
+                                       var impl = provider.GetNativeCertificate (rawData, password, keyStorageFlags);
+                                       return impl;
+                               }
                        }
 #endif // FEATURE_NO_BSD_SOCKETS
                        var impl2 = new X509Certificate2ImplMono ();
@@ -136,13 +140,15 @@ namespace System.Security.Cryptography.X509Certificates
                        return impl2;
                }
 
-               internal static X509Certificate2Impl Import (X509Certificate cert)
+               internal static X509Certificate2Impl Import (X509Certificate cert, bool disableProvider = false)
                {
 #if !FEATURE_NO_BSD_SOCKETS
-                       var provider = MonoTlsProviderFactory.GetProvider ();
-                       if (provider.HasNativeCertificates) {
-                               var impl = provider.GetNativeCertificate (cert);
-                               return impl;
+                       if (!disableProvider) {
+                               var provider = MonoTlsProviderFactory.GetProvider ();
+                               if (provider.HasNativeCertificates) {
+                                       var impl = provider.GetNativeCertificate (cert);
+                                       return impl;
+                               }
                        }
 #endif // FEATURE_NO_BSD_SOCKETS
                        var impl2 = cert.Impl as X509Certificate2Impl;
@@ -151,6 +157,27 @@ namespace System.Security.Cryptography.X509Certificates
                        return Import (cert.GetRawCertData (), null, X509KeyStorageFlags.DefaultKeySet);
                }
 
+               /*
+                * This is used by X509ChainImplMono
+                * 
+                * Some of the missing APIs such as X509v3 extensions can be added to the native
+                * BTLS implementation.
+                * 
+                * We should also consider replacing X509ChainImplMono with a new X509ChainImplBtls
+                * at some point.
+                */
+               [MonoTODO ("Investigate replacement; see comments in source.")]
+               internal static MX.X509Certificate GetMonoCertificate (X509Certificate2 certificate)
+               {
+                       var impl2 = certificate.Impl as X509Certificate2Impl;
+                       if (impl2 == null)
+                               impl2 = Import (certificate, true);
+                       var fallbackImpl = impl2.FallbackImpl as X509Certificate2ImplMono;
+                       if (fallbackImpl == null)
+                               throw new NotSupportedException ();
+                       return fallbackImpl.MonoCertificate;
+               }
+
                internal static X509ChainImpl CreateChainImpl (bool useMachineContext)
                {
                        return new X509ChainImplMono (useMachineContext);
index d76d885e6a5d1324f55f38bb858f020ce7ada336..7a40f75b53bd2b8a720d51886a72fb146323afb8 100644 (file)
@@ -272,12 +272,13 @@ mono_btls_x509_name_get_entry_oid_data (MonoBtlsX509Name *name, int index, const
 }
 
 int
-mono_btls_x509_name_get_entry_value (MonoBtlsX509Name *name, int index, unsigned char **str)
+mono_btls_x509_name_get_entry_value (MonoBtlsX509Name *name, int index, int *tag, unsigned char **str)
 {
        X509_NAME_ENTRY *entry;
        ASN1_STRING *data;
 
        *str = NULL;
+       *tag = 0;
 
        if (index >= X509_NAME_entry_count (name->name))
                return 0;
@@ -290,5 +291,6 @@ mono_btls_x509_name_get_entry_value (MonoBtlsX509Name *name, int index, unsigned
        if (!data)
                return 0;
 
+       *tag = data->type;
        return ASN1_STRING_to_UTF8 (str, data);
 }
index 20c6a68656319dc5e4613466ac034c1bc385ba54..604de2bb5e6627a682debcd033b3c4bb23420cd3 100644 (file)
@@ -75,6 +75,6 @@ int
 mono_btls_x509_name_get_entry_oid_data (MonoBtlsX509Name *name, int index, const void **data);
 
 int
-mono_btls_x509_name_get_entry_value (MonoBtlsX509Name *name, int index, unsigned char **str);
+mono_btls_x509_name_get_entry_value (MonoBtlsX509Name *name, int index, int *tag, unsigned char **str);
 
 #endif /* __btls__btls_x509_name__ */