diff --git a/Cargo.lock b/Cargo.lock index 4bf73b73..3e288cb8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -594,6 +594,7 @@ dependencies = [ "ssh-key", "thiserror 1.0.69", "tsify-next", + "uniffi", "wasm-bindgen", ] @@ -609,6 +610,7 @@ dependencies = [ "bitwarden-fido", "bitwarden-generators", "bitwarden-send", + "bitwarden-ssh", "bitwarden-vault", "chrono", "env_logger", diff --git a/crates/bitwarden-ssh/Cargo.toml b/crates/bitwarden-ssh/Cargo.toml index e17f53e3..03ebf7cf 100644 --- a/crates/bitwarden-ssh/Cargo.toml +++ b/crates/bitwarden-ssh/Cargo.toml @@ -20,6 +20,7 @@ wasm = [ "dep:tsify-next", "dep:wasm-bindgen" ] # WASM support +uniffi = ["dep:uniffi"] # Uniffi bindings [dependencies] bitwarden-error = { workspace = true } @@ -36,6 +37,7 @@ ssh-key = { version = ">=0.6.7, <0.7", features = [ ], default-features = false } thiserror = { workspace = true } tsify-next = { workspace = true, optional = true } +uniffi = { workspace = true, optional = true } wasm-bindgen = { workspace = true, optional = true } [dev-dependencies] diff --git a/crates/bitwarden-ssh/src/generator.rs b/crates/bitwarden-ssh/src/generator.rs index 51b8f9f7..0cec1f41 100644 --- a/crates/bitwarden-ssh/src/generator.rs +++ b/crates/bitwarden-ssh/src/generator.rs @@ -7,6 +7,7 @@ use crate::{error, error::KeyGenerationError, SshKey}; #[derive(Serialize, Deserialize)] #[cfg_attr(feature = "wasm", derive(Tsify), tsify(into_wasm_abi, from_wasm_abi))] +#[cfg_attr(feature = "uniffi", derive(uniffi::Enum))] pub enum KeyAlgorithm { Ed25519, Rsa3072, diff --git a/crates/bitwarden-ssh/src/lib.rs b/crates/bitwarden-ssh/src/lib.rs index 1a972efe..459d1b41 100644 --- a/crates/bitwarden-ssh/src/lib.rs +++ b/crates/bitwarden-ssh/src/lib.rs @@ -9,8 +9,12 @@ use ssh_key::{HashAlg, PrivateKey}; #[cfg(feature = "wasm")] use tsify_next::Tsify; +#[cfg(feature = "uniffi")] +uniffi::setup_scaffolding!(); + #[derive(Serialize, Deserialize, Debug)] #[cfg_attr(feature = "wasm", derive(Tsify), tsify(into_wasm_abi, from_wasm_abi))] +#[cfg_attr(feature = "uniffi", derive(uniffi::Record))] pub struct SshKey { /// The private key in OpenSSH format pub private_key: String, diff --git a/crates/bitwarden-ssh/uniffi.toml b/crates/bitwarden-ssh/uniffi.toml new file mode 100644 index 00000000..202ae0a4 --- /dev/null +++ b/crates/bitwarden-ssh/uniffi.toml @@ -0,0 +1,9 @@ +[bindings.kotlin] +package_name = "com.bitwarden.ssh" +generate_immutable_records = true +android = true + +[bindings.swift] +ffi_module_name = "BitwardenSshFFI" +module_name = "BitwardenSsh" +generate_immutable_records = true diff --git a/crates/bitwarden-uniffi/Cargo.toml b/crates/bitwarden-uniffi/Cargo.toml index 1fb3a09a..87f04cd3 100644 --- a/crates/bitwarden-uniffi/Cargo.toml +++ b/crates/bitwarden-uniffi/Cargo.toml @@ -24,6 +24,7 @@ bitwarden-exporters = { workspace = true, features = ["uniffi"] } bitwarden-fido = { workspace = true, features = ["uniffi"] } bitwarden-generators = { workspace = true, features = ["uniffi"] } bitwarden-send = { workspace = true, features = ["uniffi"] } +bitwarden-ssh = { workspace = true, features = ["uniffi"] } bitwarden-vault = { workspace = true, features = ["uniffi"] } chrono = { workspace = true, features = ["std"] } env_logger = "0.11.1" diff --git a/crates/bitwarden-uniffi/src/error.rs b/crates/bitwarden-uniffi/src/error.rs index 89096e8b..076da70a 100644 --- a/crates/bitwarden-uniffi/src/error.rs +++ b/crates/bitwarden-uniffi/src/error.rs @@ -76,4 +76,9 @@ pub enum Error { DecryptFido2AutofillCredentials(#[from] bitwarden_fido::DecryptFido2AutofillCredentialsError), #[error(transparent)] Fido2Client(#[from] bitwarden_fido::Fido2ClientError), + + #[error(transparent)] + SshGeneration(#[from] bitwarden_ssh::error::KeyGenerationError), + #[error(transparent)] + SshImport(#[from] bitwarden_ssh::error::SshKeyImportError), } diff --git a/crates/bitwarden-uniffi/src/lib.rs b/crates/bitwarden-uniffi/src/lib.rs index 074d3992..fb7f22db 100644 --- a/crates/bitwarden-uniffi/src/lib.rs +++ b/crates/bitwarden-uniffi/src/lib.rs @@ -19,7 +19,7 @@ mod android_support; use crypto::CryptoClient; use error::Result; use platform::PlatformClient; -use tool::{ExporterClient, GeneratorClients, SendClient}; +use tool::{ExporterClient, GeneratorClients, SendClient, SshClient}; use vault::VaultClient; #[derive(uniffi::Object)] @@ -67,6 +67,11 @@ impl Client { Arc::new(SendClient(self)) } + /// SSH operations + pub fn ssh(self: Arc) -> Arc { + Arc::new(SshClient(self)) + } + /// Auth operations pub fn auth(self: Arc) -> Arc { Arc::new(AuthClient(self)) diff --git a/crates/bitwarden-uniffi/src/tool/mod.rs b/crates/bitwarden-uniffi/src/tool/mod.rs index c8f788b8..fd918ac4 100644 --- a/crates/bitwarden-uniffi/src/tool/mod.rs +++ b/crates/bitwarden-uniffi/src/tool/mod.rs @@ -15,6 +15,9 @@ use crate::{ mod sends; pub use sends::SendClient; +mod ssh; +pub use ssh::SshClient; + #[derive(uniffi::Object)] pub struct GeneratorClients(pub(crate) Arc); diff --git a/crates/bitwarden-uniffi/src/tool/ssh.rs b/crates/bitwarden-uniffi/src/tool/ssh.rs new file mode 100644 index 00000000..6e7cfe2c --- /dev/null +++ b/crates/bitwarden-uniffi/src/tool/ssh.rs @@ -0,0 +1,29 @@ +use std::sync::Arc; + +use crate::{ + error::{BitwardenError, Error}, + Client, Result, +}; + +#[derive(uniffi::Object)] +pub struct SshClient(pub Arc); + +#[uniffi::export] +impl SshClient { + pub fn generate_ssh_key( + &self, + key_algorithm: bitwarden_ssh::generator::KeyAlgorithm, + ) -> Result { + bitwarden_ssh::generator::generate_sshkey(key_algorithm) + .map_err(|e| BitwardenError::E(Error::SshGeneration(e))) + } + + pub fn import_ssh_key( + &self, + imported_key: String, + password: Option, + ) -> Result { + bitwarden_ssh::import::import_key(imported_key, password) + .map_err(|e| BitwardenError::E(Error::SshImport(e))) + } +}