1dd6b2fdac1eb597268b956eab7e90a719bf3cd1
[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 using Mono.Btls;
41 #endif
42
43 using System.IO;
44 using System.Text;
45
46 namespace System.Security.Cryptography.X509Certificates
47 {
48         internal static class X509Helper2
49         {
50                 internal static long GetSubjectNameHash (X509Certificate certificate)
51                 {
52                         return GetSubjectNameHash (certificate.Impl);
53                 }
54
55                 internal static long GetSubjectNameHash (X509CertificateImpl impl)
56                 {
57 #if SECURITY_DEP
58                         using (var x509 = GetNativeInstance (impl))
59                                 return GetSubjectNameHash (x509);
60 #else
61                         throw new NotSupportedException ();
62 #endif
63                 }
64
65                 internal static void ExportAsPEM (X509Certificate certificate, Stream stream, bool includeHumanReadableForm)
66                 {
67                         ExportAsPEM (certificate.Impl, stream, includeHumanReadableForm);
68                 }
69
70                 internal static void ExportAsPEM (X509CertificateImpl impl, Stream stream, bool includeHumanReadableForm)
71                 {
72 #if SECURITY_DEP
73                         using (var x509 = GetNativeInstance (impl))
74                                 ExportAsPEM (x509, stream, includeHumanReadableForm);
75 #else
76                         throw new NotSupportedException ();
77 #endif
78                 }
79
80 #if SECURITY_DEP
81                 internal static void Initialize ()
82                 {
83                         X509Helper.InstallNativeHelper (new MyNativeHelper ());
84                 }
85
86                 internal static void ThrowIfContextInvalid (X509CertificateImpl impl)
87                 {
88                         X509Helper.ThrowIfContextInvalid (impl);
89                 }
90
91                 static MonoBtlsX509 GetNativeInstance (X509CertificateImpl impl)
92                 {
93                         ThrowIfContextInvalid (impl);
94                         var btlsImpl = impl as X509CertificateImplBtls;
95                         if (btlsImpl != null)
96                                 return btlsImpl.X509.Copy ();
97                         else
98                                 return MonoBtlsX509.LoadFromData (impl.GetRawCertData (), MonoBtlsX509Format.DER);
99                 }
100
101                 internal static long GetSubjectNameHash (MonoBtlsX509 x509)
102                 {
103                         using (var subject = x509.GetSubjectName ())
104                                 return subject.GetHash ();
105                 }
106
107                 internal static void ExportAsPEM (MonoBtlsX509 x509, Stream stream, bool includeHumanReadableForm)
108                 {
109                         using (var bio = MonoBtlsBio.CreateMonoStream (stream)) {
110                                 x509.ExportAsPEM (bio, includeHumanReadableForm);
111                         }
112                 }
113
114                 internal static X509Certificate2Impl Import (byte[] rawData, string password, X509KeyStorageFlags keyStorageFlags)
115                 {
116                         var provider = MonoTlsProviderFactory.GetProvider ();
117                         if (provider.HasNativeCertificates) {
118                                 var impl = provider.GetNativeCertificate (rawData, password, keyStorageFlags);
119                                 return impl;
120                         } else {
121                                 var impl = new X509Certificate2ImplMono ();
122                                 impl.Import (rawData, password, keyStorageFlags);
123                                 return impl;
124                         }
125                 }
126
127                 internal static X509Certificate2Impl Import (X509Certificate cert)
128                 {
129                         var provider = MonoTlsProviderFactory.GetProvider ();
130                         if (provider.HasNativeCertificates) {
131                                 var impl = provider.GetNativeCertificate (cert);
132                                 return impl;
133                         }
134                         var impl2 = cert.Impl as X509Certificate2Impl;
135                         if (impl2 != null)
136                                 return (X509Certificate2Impl)impl2.Clone ();
137                         return Import (cert.GetRawCertData (), null, X509KeyStorageFlags.DefaultKeySet);
138                 }
139
140                 internal static X509ChainImpl CreateChainImpl (bool useMachineContext)
141                 {
142                         return new X509ChainImplMono (useMachineContext);
143                 }
144
145                 public static bool IsValid (X509ChainImpl impl)
146                 {
147                         return impl != null && impl.IsValid;
148                 }
149
150                 internal static void ThrowIfContextInvalid (X509ChainImpl impl)
151                 {
152                         if (!IsValid (impl))
153                                 throw GetInvalidChainContextException ();
154                 }
155
156                 internal static Exception GetInvalidChainContextException ()
157                 {
158                         return new CryptographicException (Locale.GetText ("Chain instance is empty."));
159                 }
160
161                 class MyNativeHelper : INativeCertificateHelper
162                 {
163                         public X509CertificateImpl Import (
164                                 byte[] data, string password, X509KeyStorageFlags flags)
165                         {
166                                 return X509Helper2.Import (data, password, flags);
167                         }
168
169                         public X509CertificateImpl Import (X509Certificate cert)
170                         {
171                                 return X509Helper2.Import (cert);
172                         }
173                 }
174 #endif
175         }
176 }