// Bridge API — thin wrappers that delegate to ccc_rust providers. // // No cryptographic logic here; only type conversions and registry lookups. use ccc_crypto_core::{KemProvider, ProviderRegistry}; use ccc_crypto_wolfssl::WolfSslProvider; use crate::api::dto::*; /// Trace-level bridge logging. Visible only when `RUST_LOG=trace` (or /// equivalent) is set; compiled out in release builds when the `log` crate's /// `release_max_level_off` feature is enabled. macro_rules! dbg_bridge { ($($arg:tt)*) => { log::trace!("[ccc-bridge] {}", format!($($arg)*)); }; } // ── Helpers ────────────────────────────────────────────────────────────────── /// Default provider name used when the caller doesn't specify one. const DEFAULT_PROVIDER: &str = "wolfssl"; /// Get the default provider from the registry or return an error. fn default_provider( ) -> Result, CccCryptoError> { ProviderRegistry::global() .get(DEFAULT_PROVIDER) .ok_or_else(|| { CccCryptoError::InternalError(format!( "provider '{DEFAULT_PROVIDER}' not registered — call ccc_init() first" )) }) } /// A lazily-initialised KemProvider instance. /// /// `KemProvider` is not part of the `CryptoProvider` supertrait, so we keep /// a standalone `WolfSslProvider` for KEM operations. fn kem_provider() -> &'static WolfSslProvider { use std::sync::OnceLock; static KEM: OnceLock = OnceLock::new(); KEM.get_or_init(WolfSslProvider::new) } // ── Init ───────────────────────────────────────────────────────────────────── /// Initialise the CCC cryptographic subsystem. /// /// Registers the wolfSSL provider in the global registry. /// Safe to call multiple times (idempotent). pub fn ccc_init() { dbg_bridge!("ccc_init: enter"); flutter_rust_bridge::setup_default_user_utils(); if !ProviderRegistry::global().contains(DEFAULT_PROVIDER) { ccc_crypto_wolfssl::init(); } dbg_bridge!("ccc_init: exit"); } // ── Provider info ──────────────────────────────────────────────────────────── /// List all registered provider names. #[flutter_rust_bridge::frb(sync)] pub fn ccc_list_providers() -> Vec { dbg_bridge!("ccc_list_providers"); ProviderRegistry::global().list() } /// Return the capabilities of the default provider. pub fn ccc_capabilities() -> Result { dbg_bridge!("ccc_capabilities"); let provider = default_provider()?; Ok(CccCapabilities::from(provider.capabilities())) } // ── AEAD ───────────────────────────────────────────────────────────────────── /// Encrypt with an AEAD algorithm. /// /// Returns ciphertext‖tag. pub fn ccc_aead_encrypt( algorithm: CccAeadAlgorithm, key: Vec, nonce: Vec, plaintext: Vec, aad: Vec, ) -> Result, CccCryptoError> { dbg_bridge!("ccc_aead_encrypt: pt_len={}", plaintext.len()); let provider = default_provider()?; Ok(provider.encrypt_aead(algorithm.to_core(), &key, &nonce, &plaintext, &aad)?) } /// Decrypt with an AEAD algorithm. /// /// Expects ciphertext‖tag as `ciphertext`. pub fn ccc_aead_decrypt( algorithm: CccAeadAlgorithm, key: Vec, nonce: Vec, ciphertext: Vec, aad: Vec, ) -> Result, CccCryptoError> { dbg_bridge!("ccc_aead_decrypt: ct_len={}", ciphertext.len()); let provider = default_provider()?; Ok(provider.decrypt_aead(algorithm.to_core(), &key, &nonce, &ciphertext, &aad)?) } // ── KDF ────────────────────────────────────────────────────────────────────── /// Derive key material using a KDF. pub fn ccc_kdf_derive( algorithm: CccKdfAlgorithm, ikm: Vec, salt: Vec, info: Vec, length: u32, ) -> Result, CccCryptoError> { dbg_bridge!("ccc_kdf_derive: length={}", length); let provider = default_provider()?; let derived = provider.derive_key( algorithm.to_core(), &ikm, &salt, &info, length as usize, )?; // Move out of Zeroizing wrapper — FRB will copy to Dart. Ok(derived.to_vec()) } // ── MAC ────────────────────────────────────────────────────────────────────── /// Compute a MAC tag. pub fn ccc_mac_compute( algorithm: CccMacAlgorithm, key: Vec, data: Vec, ) -> Result, CccCryptoError> { dbg_bridge!("ccc_mac_compute: data_len={}", data.len()); let provider = default_provider()?; Ok(provider.compute_mac(algorithm.to_core(), &key, &data)?) } /// Verify a MAC tag. Returns `true` if valid. pub fn ccc_mac_verify( algorithm: CccMacAlgorithm, key: Vec, data: Vec, mac: Vec, ) -> Result { dbg_bridge!("ccc_mac_verify: data_len={}", data.len()); let provider = default_provider()?; Ok(provider.verify_mac(algorithm.to_core(), &key, &data, &mac)?) } // ── Hash ───────────────────────────────────────────────────────────────────── /// Compute a cryptographic hash. pub fn ccc_hash( algorithm: CccHashAlgorithm, data: Vec, ) -> Result, CccCryptoError> { dbg_bridge!("ccc_hash: data_len={}", data.len()); let provider = default_provider()?; Ok(provider.hash(algorithm.to_core(), &data)?) } // ── KEM ────────────────────────────────────────────────────────────────────── /// Generate a KEM key pair. pub fn ccc_kem_generate_keypair( algorithm: CccKemAlgorithm, ) -> Result { dbg_bridge!("ccc_kem_generate_keypair"); let kp = kem_provider().generate_keypair(algorithm.to_core())?; Ok(CccKemKeyPair::from(kp)) } /// KEM encapsulation — produce ciphertext + shared secret from a public key. pub fn ccc_kem_encapsulate( algorithm: CccKemAlgorithm, public_key: Vec, ) -> Result { dbg_bridge!("ccc_kem_encapsulate"); let result = kem_provider().encapsulate(algorithm.to_core(), &public_key)?; Ok(CccKemEncapResult::from(result)) } /// KEM decapsulation — recover shared secret from ciphertext + private key. pub fn ccc_kem_decapsulate( algorithm: CccKemAlgorithm, private_key: Vec, ciphertext: Vec, ) -> Result, CccCryptoError> { dbg_bridge!("ccc_kem_decapsulate"); let ss = kem_provider().decapsulate(algorithm.to_core(), &private_key, &ciphertext)?; Ok(ss.to_vec()) } // ── Self-test ──────────────────────────────────────────────────────────────── /// Run the provider self-test and return a structured report. pub fn ccc_self_test() -> Result { dbg_bridge!("ccc_self_test"); let provider = default_provider()?; Ok(CccSelfTestReport::from(provider.self_test())) }