2 // MonoBtlsX509Store.cs
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 a copy
10 // of this software and associated documentation files (the "Software"), to deal
11 // in the Software without restriction, including without limitation the rights
12 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 // copies of the Software, and to permit persons to whom the Software is
14 // furnished to do so, subject to the following conditions:
16 // The above copyright notice and this permission notice shall be included in
17 // all copies or substantial portions of the Software.
19 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
26 #if SECURITY_DEP && MONO_FEATURE_BTLS
27 #if MONO_SECURITY_ALIAS
28 extern alias MonoSecurity;
32 using System.Collections.Generic;
33 using System.Runtime.InteropServices;
34 using System.Runtime.CompilerServices;
35 using System.Security.Cryptography.X509Certificates;
37 #if MONO_SECURITY_ALIAS
38 using MonoSecurity::Mono.Security.Interface;
40 using Mono.Security.Interface;
45 class MonoBtlsX509Store : MonoBtlsObject
47 internal class BoringX509StoreHandle : MonoBtlsHandle
49 public BoringX509StoreHandle (IntPtr handle)
54 protected override bool ReleaseHandle ()
56 mono_btls_x509_store_free (handle);
61 new internal BoringX509StoreHandle Handle {
62 get { return (BoringX509StoreHandle)base.Handle; }
65 [DllImport (BTLS_DYLIB)]
66 extern static IntPtr mono_btls_x509_store_new ();
68 [DllImport (BTLS_DYLIB)]
69 extern static IntPtr mono_btls_x509_store_from_ctx (IntPtr ctx);
71 [DllImport (BTLS_DYLIB)]
72 extern static IntPtr mono_btls_x509_store_from_ssl_ctx (IntPtr handle);
74 [DllImport (BTLS_DYLIB)]
75 extern static int mono_btls_x509_store_load_locations (IntPtr handle, IntPtr file, IntPtr path);
77 [DllImport (BTLS_DYLIB)]
78 extern static int mono_btls_x509_store_set_default_paths (IntPtr handle);
80 [DllImport (BTLS_DYLIB)]
81 extern static int mono_btls_x509_store_add_cert (IntPtr handle, IntPtr x509);
83 [DllImport (BTLS_DYLIB)]
84 extern static int mono_btls_x509_store_get_count (IntPtr handle);
86 [DllImport (BTLS_DYLIB)]
87 extern static void mono_btls_x509_store_free (IntPtr handle);
89 Dictionary<IntPtr,MonoBtlsX509Lookup> lookupHash;
91 public void LoadLocations (string file, string path)
93 IntPtr filePtr = IntPtr.Zero;
94 IntPtr pathPtr = IntPtr.Zero;
97 filePtr = Marshal.StringToHGlobalAnsi (file);
99 pathPtr = Marshal.StringToHGlobalAnsi (path);
100 var ret = mono_btls_x509_store_load_locations (
101 Handle.DangerousGetHandle (), filePtr, pathPtr);
104 if (filePtr != IntPtr.Zero)
105 Marshal.FreeHGlobal (filePtr);
106 if (pathPtr != IntPtr.Zero)
107 Marshal.FreeHGlobal (pathPtr);
111 public void SetDefaultPaths ()
113 var ret = mono_btls_x509_store_set_default_paths (Handle.DangerousGetHandle ());
117 static BoringX509StoreHandle Create_internal ()
119 var handle = mono_btls_x509_store_new ();
120 if (handle == IntPtr.Zero)
121 throw new MonoBtlsException ();
122 return new BoringX509StoreHandle (handle);
125 static BoringX509StoreHandle Create_internal (IntPtr store_ctx)
127 var handle = mono_btls_x509_store_from_ssl_ctx (store_ctx);
128 if (handle == IntPtr.Zero)
129 throw new MonoBtlsException ();
130 return new BoringX509StoreHandle (handle);
133 static BoringX509StoreHandle Create_internal (MonoBtlsSslCtx.BoringSslCtxHandle ctx)
135 var handle = mono_btls_x509_store_from_ssl_ctx (ctx.DangerousGetHandle ());
136 if (handle == IntPtr.Zero)
137 throw new MonoBtlsException ();
138 return new BoringX509StoreHandle (handle);
141 internal MonoBtlsX509Store ()
142 : base (Create_internal ())
146 internal MonoBtlsX509Store (IntPtr store_ctx)
147 : base (Create_internal (store_ctx))
151 internal MonoBtlsX509Store (MonoBtlsSslCtx.BoringSslCtxHandle ctx)
152 : base (Create_internal (ctx))
156 public void AddCertificate (MonoBtlsX509 x509)
158 var ret = mono_btls_x509_store_add_cert (
159 Handle.DangerousGetHandle (),
160 x509.Handle.DangerousGetHandle ());
164 public int GetCount ()
166 return mono_btls_x509_store_get_count (Handle.DangerousGetHandle ());
169 internal void AddTrustedRoots ()
171 MonoBtlsProvider.SetupCertificateStore (this, MonoTlsSettings.DefaultSettings, false);
174 public MonoBtlsX509Lookup AddLookup (MonoBtlsX509LookupType type)
176 if (lookupHash == null)
177 lookupHash = new Dictionary<IntPtr,MonoBtlsX509Lookup> ();
180 * X509_STORE_add_lookup() returns the same 'X509_LOOKUP *' for each
181 * unique 'X509_LOOKUP_METHOD *' (which is supposed to be a static struct)
182 * and we want to use the same managed object for each unique 'X509_LOOKUP *'.
184 var lookup = new MonoBtlsX509Lookup (this, type);
185 var nativeLookup = lookup.GetNativeLookup ();
186 if (lookupHash.ContainsKey (nativeLookup)) {
188 lookup = lookupHash [nativeLookup];
190 lookupHash.Add (nativeLookup, lookup);
196 public void AddDirectoryLookup (string dir, MonoBtlsX509FileType type)
198 var lookup = AddLookup (MonoBtlsX509LookupType.HASH_DIR);
199 lookup.AddDirectory (dir, type);
202 public void AddFileLookup (string file, MonoBtlsX509FileType type)
204 var lookup = AddLookup (MonoBtlsX509LookupType.FILE);
205 lookup.LoadFile (file, type);
208 public void AddCollection (X509CertificateCollection collection, MonoBtlsX509TrustKind trust)
210 var monoLookup = new MonoBtlsX509LookupMonoCollection (collection, trust);
211 var lookup = new MonoBtlsX509Lookup (this, MonoBtlsX509LookupType.MONO);
212 lookup.AddMono (monoLookup);
216 public void AddAndroidLookup ()
218 var androidLookup = new MonoBtlsX509LookupAndroid ();
219 var lookup = new MonoBtlsX509Lookup (this, MonoBtlsX509LookupType.MONO);
220 lookup.AddMono (androidLookup);
224 protected override void Close ()
227 if (lookupHash != null) {
228 foreach (var lookup in lookupHash.Values)