1 use crate::error::ErrorStack;
2 use crate::lib_ctx::LibCtxRef;
3 use crate::{cvt, cvt_p};
4 use foreign_types::{ForeignType, ForeignTypeRef};
5 use openssl_macros::corresponds;
6 use std::ffi::CString;
7 use std::ptr;
8 
9 foreign_type_and_impl_send_sync! {
10     type CType = ffi::OSSL_PROVIDER;
11     fn drop = ossl_provider_free;
12 
13     pub struct Provider;
14     /// A reference to a [`Provider`].
15     pub struct ProviderRef;
16 }
17 
18 #[inline]
ossl_provider_free(p: *mut ffi::OSSL_PROVIDER)19 unsafe fn ossl_provider_free(p: *mut ffi::OSSL_PROVIDER) {
20     ffi::OSSL_PROVIDER_unload(p);
21 }
22 
23 impl Provider {
24     /// Loads a new provider into the specified library context, disabling the fallback providers.
25     ///
26     /// If `ctx` is `None`, the provider will be loaded in to the default library context.
27     #[corresponds(OSSL_provider_load)]
load(ctx: Option<&LibCtxRef>, name: &str) -> Result<Self, ErrorStack>28     pub fn load(ctx: Option<&LibCtxRef>, name: &str) -> Result<Self, ErrorStack> {
29         let name = CString::new(name).unwrap();
30         unsafe {
31             let p = cvt_p(ffi::OSSL_PROVIDER_load(
32                 ctx.map_or(ptr::null_mut(), ForeignTypeRef::as_ptr),
33                 name.as_ptr(),
34             ))?;
35 
36             Ok(Provider::from_ptr(p))
37         }
38     }
39 
40     /// Loads a new provider into the specified library context, disabling the fallback providers if `retain_fallbacks`
41     /// is `false` and the load succeeds.
42     ///
43     /// If `ctx` is `None`, the provider will be loaded into the default library context.
44     #[corresponds(OSSL_provider_try_load)]
try_load( ctx: Option<&LibCtxRef>, name: &str, retain_fallbacks: bool, ) -> Result<Self, ErrorStack>45     pub fn try_load(
46         ctx: Option<&LibCtxRef>,
47         name: &str,
48         retain_fallbacks: bool,
49     ) -> Result<Self, ErrorStack> {
50         let name = CString::new(name).unwrap();
51         unsafe {
52             let p = cvt_p(ffi::OSSL_PROVIDER_try_load(
53                 ctx.map_or(ptr::null_mut(), ForeignTypeRef::as_ptr),
54                 name.as_ptr(),
55                 retain_fallbacks as _,
56             ))?;
57 
58             // OSSL_PROVIDER_try_load seems to leave errors on the stack, even
59             // when it succeeds.
60             let _ = ErrorStack::get();
61 
62             Ok(Provider::from_ptr(p))
63         }
64     }
65 
66     /// Specifies the default search path that is to be used for looking for providers in the specified library context.
67     /// If left unspecified, an environment variable and a fall back default value will be used instead
68     ///
69     /// If `ctx` is `None`, the provider will be loaded into the default library context.
70     #[corresponds(OSSL_PROVIDER_set_default_search_path)]
set_default_search_path(ctx: Option<&LibCtxRef>, path: &str) -> Result<(), ErrorStack>71     pub fn set_default_search_path(ctx: Option<&LibCtxRef>, path: &str) -> Result<(), ErrorStack> {
72         let path = CString::new(path).unwrap();
73         unsafe {
74             cvt(ffi::OSSL_PROVIDER_set_default_search_path(
75                 ctx.map_or(ptr::null_mut(), ForeignTypeRef::as_ptr),
76                 path.as_ptr(),
77             ))
78             .map(|_| ())
79         }
80     }
81 }
82