92709e04fa8a77a2c599fd7b7121d55e6a86b45b
[mono.git] / mcs / class / System / System.Security.Cryptography.X509Certificates / X509Helper2.cs
1 //
2 // X509Helper2.cs
3 //
4 // Authors:
5 //      Martin Baulig  <martin.baulig@xamarin.com>
6 //
7 // Copyright (C) 2016 Xamarin, Inc. (http://www.xamarin.com)
8 //
9 // Permission is hereby granted, free of charge, to any person obtaining
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:
16 // 
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
19 // 
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.
27 //
28
29 #if SECURITY_DEP
30 #if MONO_SECURITY_ALIAS
31 extern alias MonoSecurity;
32 #endif
33
34 #if MONO_SECURITY_ALIAS
35 using MonoSecurity::Mono.Security.Interface;
36 #else
37 using Mono.Security.Interface;
38 #endif
39
40 #if HAVE_BTLS
41 using Mono.Btls;
42 #endif
43 #endif
44
45 using System.IO;
46 using System.Text;
47
48 namespace System.Security.Cryptography.X509Certificates
49 {
50         internal static class X509Helper2
51         {
52                 internal static long GetSubjectNameHash (X509Certificate certificate)
53                 {
54                         return GetSubjectNameHash (certificate.Impl);
55                 }
56
57                 internal static long GetSubjectNameHash (X509CertificateImpl impl)
58                 {
59 #if SECURITY_DEP && HAVE_BTLS
60                         using (var x509 = GetNativeInstance (impl))
61                                 return GetSubjectNameHash (x509);
62 #else
63                         throw new NotSupportedException ();
64 #endif
65                 }
66
67                 internal static void ExportAsPEM (X509Certificate certificate, Stream stream, bool includeHumanReadableForm)
68                 {
69                         ExportAsPEM (certificate.Impl, stream, includeHumanReadableForm);
70                 }
71
72                 internal static void ExportAsPEM (X509CertificateImpl impl, Stream stream, bool includeHumanReadableForm)
73                 {
74 #if SECURITY_DEP && HAVE_BTLS
75                         using (var x509 = GetNativeInstance (impl))
76                                 ExportAsPEM (x509, stream, includeHumanReadableForm);
77 #else
78                         throw new NotSupportedException ();
79 #endif
80                 }
81
82 #if SECURITY_DEP
83                 internal static void Initialize ()
84                 {
85                         X509Helper.InstallNativeHelper (new MyNativeHelper ());
86                 }
87
88                 internal static void ThrowIfContextInvalid (X509CertificateImpl impl)
89                 {
90                         X509Helper.ThrowIfContextInvalid (impl);
91                 }
92
93 #if HAVE_BTLS
94                 static MonoBtlsX509 GetNativeInstance (X509CertificateImpl impl)
95                 {
96                         ThrowIfContextInvalid (impl);
97                         var btlsImpl = impl as X509CertificateImplBtls;
98                         if (btlsImpl != null)
99                                 return btlsImpl.X509.Copy ();
100                         else
101                                 return MonoBtlsX509.LoadFromData (impl.GetRawCertData (), MonoBtlsX509Format.DER);
102                 }
103
104                 internal static long GetSubjectNameHash (MonoBtlsX509 x509)
105                 {
106                         using (var subject = x509.GetSubjectName ())
107                                 return subject.GetHash ();
108                 }
109
110                 internal static void ExportAsPEM (MonoBtlsX509 x509, Stream stream, bool includeHumanReadableForm)
111                 {
112                         using (var bio = MonoBtlsBio.CreateMonoStream (stream)) {
113                                 x509.ExportAsPEM (bio, includeHumanReadableForm);
114                         }
115                 }
116 #endif
117
118                 internal static X509Certificate2Impl Import (byte[] rawData, string password, X509KeyStorageFlags keyStorageFlags)
119                 {
120                         var provider = MonoTlsProviderFactory.GetProvider ();
121                         if (provider.HasNativeCertificates) {
122                                 var impl = provider.GetNativeCertificate (rawData, password, keyStorageFlags);
123                                 return impl;
124                         } else {
125                                 var impl = new X509Certificate2ImplMono ();
126                                 impl.Import (rawData, password, keyStorageFlags);
127                                 return impl;
128                         }
129                 }
130
131                 internal static X509Certificate2Impl Import (X509Certificate cert)
132                 {
133                         var provider = MonoTlsProviderFactory.GetProvider ();
134                         if (provider.HasNativeCertificates) {
135                                 var impl = provider.GetNativeCertificate (cert);
136                                 return impl;
137                         }
138                         var impl2 = cert.Impl as X509Certificate2Impl;
139                         if (impl2 != null)
140                                 return (X509Certificate2Impl)impl2.Clone ();
141                         return Import (cert.GetRawCertData (), null, X509KeyStorageFlags.DefaultKeySet);
142                 }
143
144                 internal static X509ChainImpl CreateChainImpl (bool useMachineContext)
145                 {
146                         return new X509ChainImplMono (useMachineContext);
147                 }
148
149                 public static bool IsValid (X509ChainImpl impl)
150                 {
151                         return impl != null && impl.IsValid;
152                 }
153
154                 internal static void ThrowIfContextInvalid (X509ChainImpl impl)
155                 {
156                         if (!IsValid (impl))
157                                 throw GetInvalidChainContextException ();
158                 }
159
160                 internal static Exception GetInvalidChainContextException ()
161                 {
162                         return new CryptographicException (Locale.GetText ("Chain instance is empty."));
163                 }
164
165                 class MyNativeHelper : INativeCertificateHelper
166                 {
167                         public X509CertificateImpl Import (
168                                 byte[] data, string password, X509KeyStorageFlags flags)
169                         {
170                                 return X509Helper2.Import (data, password, flags);
171                         }
172
173                         public X509CertificateImpl Import (X509Certificate cert)
174                         {
175                                 return X509Helper2.Import (cert);
176                         }
177                 }
178 #endif
179         }
180 }