tauri_plugin_secure_element/
lib.rs

1use tauri::{
2    plugin::{Builder, TauriPlugin},
3    Manager, Runtime,
4};
5
6pub use models::*;
7
8#[cfg(desktop)]
9mod desktop;
10#[cfg(mobile)]
11mod mobile;
12
13mod commands;
14mod error;
15mod models;
16mod validation;
17
18pub use error::{Error, Result};
19
20#[cfg(desktop)]
21use desktop::SecureElement;
22#[cfg(mobile)]
23use mobile::SecureElement;
24
25// Provide a stub SecureElement for when neither desktop nor mobile is configured
26// This allows the code to compile during cargo package
27#[cfg(not(any(desktop, mobile)))]
28mod stub {
29    use crate::models::*;
30    use crate::Result;
31    use tauri::{AppHandle, Runtime};
32
33    pub struct SecureElement<R: Runtime>(AppHandle<R>);
34
35    impl<R: Runtime> SecureElement<R> {
36        pub fn new(_app: AppHandle<R>) -> Self {
37            Self(_app)
38        }
39
40        pub fn ping(&self, payload: PingRequest) -> Result<PingResponse> {
41            Ok(PingResponse {
42                value: payload.value,
43            })
44        }
45
46        pub fn generate_secure_key(
47            &self,
48            _payload: GenerateSecureKeyRequest,
49        ) -> Result<GenerateSecureKeyResponse> {
50            Err(crate::Error::Io(std::io::Error::new(
51                std::io::ErrorKind::Unsupported,
52                "Secure element not available - compilation stub",
53            )))
54        }
55
56        pub fn list_keys(&self, _payload: ListKeysRequest) -> Result<ListKeysResponse> {
57            Err(crate::Error::Io(std::io::Error::new(
58                std::io::ErrorKind::Unsupported,
59                "Secure element not available - compilation stub",
60            )))
61        }
62
63        pub fn sign_with_key(&self, _payload: SignWithKeyRequest) -> Result<SignWithKeyResponse> {
64            Err(crate::Error::Io(std::io::Error::new(
65                std::io::ErrorKind::Unsupported,
66                "Secure element not available - compilation stub",
67            )))
68        }
69
70        pub fn delete_key(&self, _payload: DeleteKeyRequest) -> Result<DeleteKeyResponse> {
71            Err(crate::Error::Io(std::io::Error::new(
72                std::io::ErrorKind::Unsupported,
73                "Secure element not available - compilation stub",
74            )))
75        }
76
77        pub fn check_secure_element_support(&self) -> Result<CheckSecureElementSupportResponse> {
78            Err(crate::Error::Io(std::io::Error::new(
79                std::io::ErrorKind::Unsupported,
80                "Secure element not available - compilation stub",
81            )))
82        }
83    }
84}
85
86#[cfg(not(any(desktop, mobile)))]
87use stub::SecureElement;
88
89/// Extensions to [`tauri::App`], [`tauri::AppHandle`] and [`tauri::Window`] to access the secure-element APIs.
90pub trait SecureElementExt<R: Runtime> {
91    fn secure_element(&self) -> &SecureElement<R>;
92}
93
94#[cfg(any(desktop, mobile))]
95impl<R: Runtime, T: Manager<R>> crate::SecureElementExt<R> for T {
96    fn secure_element(&self) -> &SecureElement<R> {
97        self.state::<SecureElement<R>>().inner()
98    }
99}
100
101#[cfg(not(any(desktop, mobile)))]
102impl<R: Runtime, T: Manager<R>> crate::SecureElementExt<R> for T {
103    fn secure_element(&self) -> &SecureElement<R> {
104        // This should never be called during actual use, only for compilation
105        panic!("SecureElement is not available - this is a compilation stub")
106    }
107}
108
109/// Initializes the plugin.
110pub fn init<R: Runtime>() -> TauriPlugin<R> {
111    Builder::new("secure-element")
112        .invoke_handler(tauri::generate_handler![
113            commands::ping,
114            commands::generate_secure_key,
115            commands::list_keys,
116            commands::sign_with_key,
117            commands::delete_key,
118            commands::check_secure_element_support
119        ])
120        .setup(|app, api| {
121            #[cfg(mobile)]
122            {
123                let secure_element = mobile::init(app, api)?;
124                app.manage(secure_element);
125            }
126            #[cfg(desktop)]
127            {
128                let secure_element = desktop::init(app, api)?;
129                app.manage(secure_element);
130            }
131            #[cfg(not(any(desktop, mobile)))]
132            {
133                // Stub for compilation during cargo package
134                let _ = api;
135                let secure_element = SecureElement::new(app.clone());
136                app.manage(secure_element);
137            }
138            Ok(())
139        })
140        .build()
141}