openssl/
provider.rs

1use crate::error::ErrorStack;
2use crate::lib_ctx::LibCtxRef;
3use crate::{cvt, cvt_p};
4use foreign_types::{ForeignType, ForeignTypeRef};
5use openssl_macros::corresponds;
6use std::ffi::CString;
7use std::ptr;
8
9foreign_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]
19unsafe fn ossl_provider_free(p: *mut ffi::OSSL_PROVIDER) {
20    ffi::OSSL_PROVIDER_unload(p);
21}
22
23impl 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)]
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)]
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)]
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}