5 // Martin Baulig <martin.baulig@xamarin.com>
7 // Copyright (C) 2016 Xamarin, Inc. (http://www.xamarin.com)
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 #if MONO_SECURITY_ALIAS
31 extern alias MonoSecurity;
34 #if MONO_SECURITY_ALIAS
35 using MonoSecurity::Mono.Security.Interface;
36 using MX = MonoSecurity::Mono.Security.X509;
39 using Mono.Security.Interface;
41 using MX = Mono.Security.X509;
52 namespace System.Security.Cryptography.X509Certificates
54 internal static class X509Helper2
56 internal static long GetSubjectNameHash (X509Certificate certificate)
58 return GetSubjectNameHash (certificate.Impl);
61 internal static long GetSubjectNameHash (X509CertificateImpl impl)
64 using (var x509 = GetNativeInstance (impl))
65 return GetSubjectNameHash (x509);
67 throw new NotSupportedException ();
71 internal static void ExportAsPEM (X509Certificate certificate, Stream stream, bool includeHumanReadableForm)
73 ExportAsPEM (certificate.Impl, stream, includeHumanReadableForm);
76 internal static void ExportAsPEM (X509CertificateImpl impl, Stream stream, bool includeHumanReadableForm)
79 using (var x509 = GetNativeInstance (impl))
80 ExportAsPEM (x509, stream, includeHumanReadableForm);
82 throw new NotSupportedException ();
87 internal static void Initialize ()
89 X509Helper.InstallNativeHelper (new MyNativeHelper ());
92 internal static void ThrowIfContextInvalid (X509CertificateImpl impl)
94 X509Helper.ThrowIfContextInvalid (impl);
97 #if !MONO_FEATURE_BTLS
98 static X509Certificate GetNativeInstance (X509CertificateImpl impl)
100 throw new PlatformNotSupportedException ();
103 static MonoBtlsX509 GetNativeInstance (X509CertificateImpl impl)
105 ThrowIfContextInvalid (impl);
106 var btlsImpl = impl as X509CertificateImplBtls;
107 if (btlsImpl != null)
108 return btlsImpl.X509.Copy ();
110 return MonoBtlsX509.LoadFromData (impl.GetRawCertData (), MonoBtlsX509Format.DER);
113 internal static long GetSubjectNameHash (MonoBtlsX509 x509)
115 using (var subject = x509.GetSubjectName ())
116 return subject.GetHash ();
119 internal static void ExportAsPEM (MonoBtlsX509 x509, Stream stream, bool includeHumanReadableForm)
121 using (var bio = MonoBtlsBio.CreateMonoStream (stream)) {
122 x509.ExportAsPEM (bio, includeHumanReadableForm);
125 #endif // !MONO_FEATURE_BTLS
127 internal static X509Certificate2Impl Import (byte[] rawData, string password, X509KeyStorageFlags keyStorageFlags, bool disableProvider = false)
129 #if MONO_FEATURE_BTLS
130 if (!disableProvider) {
131 var provider = MonoTlsProviderFactory.GetProvider ();
132 if (provider.HasNativeCertificates) {
133 var impl = provider.GetNativeCertificate (rawData, password, keyStorageFlags);
137 #endif // MONO_FEATURE_BTLS
138 var impl2 = new X509Certificate2ImplMono ();
139 impl2.Import (rawData, password, keyStorageFlags);
143 internal static X509Certificate2Impl Import (X509Certificate cert, bool disableProvider = false)
145 #if MONO_FEATURE_BTLS
146 if (!disableProvider) {
147 var provider = MonoTlsProviderFactory.GetProvider ();
148 if (provider.HasNativeCertificates) {
149 var impl = provider.GetNativeCertificate (cert);
153 #endif // MONO_FEATURE_BTLS
154 var impl2 = cert.Impl as X509Certificate2Impl;
156 return (X509Certificate2Impl)impl2.Clone ();
157 return Import (cert.GetRawCertData (), null, X509KeyStorageFlags.DefaultKeySet);
161 * This is used by X509ChainImplMono
163 * Some of the missing APIs such as X509v3 extensions can be added to the native
164 * BTLS implementation.
166 * We should also consider replacing X509ChainImplMono with a new X509ChainImplBtls
169 [MonoTODO ("Investigate replacement; see comments in source.")]
170 internal static MX.X509Certificate GetMonoCertificate (X509Certificate2 certificate)
172 var impl2 = certificate.Impl as X509Certificate2Impl;
174 impl2 = Import (certificate, true);
175 var fallbackImpl = impl2.FallbackImpl as X509Certificate2ImplMono;
176 if (fallbackImpl == null)
177 throw new NotSupportedException ();
178 return fallbackImpl.MonoCertificate;
181 internal static X509ChainImpl CreateChainImpl (bool useMachineContext)
183 return new X509ChainImplMono (useMachineContext);
186 public static bool IsValid (X509ChainImpl impl)
188 return impl != null && impl.IsValid;
191 internal static void ThrowIfContextInvalid (X509ChainImpl impl)
194 throw GetInvalidChainContextException ();
197 internal static Exception GetInvalidChainContextException ()
199 return new CryptographicException (Locale.GetText ("Chain instance is empty."));
202 class MyNativeHelper : INativeCertificateHelper
204 public X509CertificateImpl Import (
205 byte[] data, string password, X509KeyStorageFlags flags)
207 return X509Helper2.Import (data, password, flags);
210 public X509CertificateImpl Import (X509Certificate cert)
212 return X509Helper2.Import (cert);