From e746cca0d4064c781c6e5ef54bb0bf536ee94a9e Mon Sep 17 00:00:00 2001 From: Ralf Anton Beier Date: Mon, 12 Jan 2026 06:51:56 +0100 Subject: [PATCH 1/2] chore: bump version to 0.5.0 New features in this release: - SLSA-aware policy engine for supply chain verification - Example policies (development, production, slsa-l3) - Loom integration documentation - Trusted publishing workflow for crates.io - Security fix for OOM vulnerability in certificate chain parsing --- Cargo.toml | 2 +- src/cli/Cargo.toml | 2 +- src/component/Cargo.toml | 2 +- src/lib/Cargo.toml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index bc363be..6f2e785 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,7 +11,7 @@ exclude = [ ] [workspace.package] -version = "0.4.1" +version = "0.5.0" edition = "2024" authors = ["Frank Denis "] license = "MIT" diff --git a/src/cli/Cargo.toml b/src/cli/Cargo.toml index cbe5b7a..cb5ea9f 100644 --- a/src/cli/Cargo.toml +++ b/src/cli/Cargo.toml @@ -28,5 +28,5 @@ regex = "1.12.2" # HTTP client for keyless signing ureq = { version = "3.1.2" } wasi = { version = "0.14.7" } -wsc = { version = "0.4.1", path = "../lib" } +wsc = { version = "0.5.0", path = "../lib" } serde_json = "1.0" diff --git a/src/component/Cargo.toml b/src/component/Cargo.toml index d697632..526a3f8 100644 --- a/src/component/Cargo.toml +++ b/src/component/Cargo.toml @@ -12,7 +12,7 @@ crate-type = ["cdylib"] [dependencies] # Core signing library -wsc = { version = "0.4.0", path = "../lib" } +wsc = { version = "0.5.0", path = "../lib" } # WIT bindings generation wit-bindgen = { version = "0.47.0", default-features = false, features = ["realloc"] } diff --git a/src/lib/Cargo.toml b/src/lib/Cargo.toml index 1d57721..c34725b 100644 --- a/src/lib/Cargo.toml +++ b/src/lib/Cargo.toml @@ -13,7 +13,7 @@ categories = ["cryptography", "wasm"] [dependencies] # Re-export attestation types from minimal crate -wsc-attestation = { version = "0.4.1", path = "../attestation" } +wsc-attestation = { version = "0.5.0", path = "../attestation" } anyhow = "1.0.100" ct-codecs = "1.1.6" ed25519-compact = { version = "2.1.1", features = ["pem"] } From b1c01a88b67cb6a7db8752432d78693390cd1ba2 Mon Sep 17 00:00:00 2001 From: Ralf Anton Beier Date: Fri, 16 Jan 2026 15:10:16 +0100 Subject: [PATCH 2/2] chore: remove incomplete ATECC608 implementation The ATECC608 secure element code was half-implemented with critical issues: - Used P-256 ECDSA but main codebase uses Ed25519 (incompatible) - sign() returned mock data (all zeros) - get_public_key() always returned an error Removed: - src/lib/src/platform/secure_element/atecc608.rs (563 lines) - atecc608 feature flag Kept: - Well-designed SecureKeyProvider trait hierarchy - I2C bus abstraction traits - KeySlot and SlotConfig types - Placeholder stubs for future hardware support (SE050, TPM2, etc.) The platform module now clearly documents what's working (software keys) vs what's planned (hardware backends). --- Cargo.lock | 8 +- src/lib/Cargo.toml | 17 +- .../src/platform/secure_element/atecc608.rs | 563 ------------------ src/lib/src/platform/secure_element/mod.rs | 65 +- 4 files changed, 27 insertions(+), 626 deletions(-) delete mode 100644 src/lib/src/platform/secure_element/atecc608.rs diff --git a/Cargo.lock b/Cargo.lock index 2ca772a..18a0a4f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1953,7 +1953,7 @@ checksum = "a374235c3c0dff10537040b437073d09f1e38f13216b5f3cbc809c6226814e5c" [[package]] name = "wsc" -version = "0.4.1" +version = "0.5.0" dependencies = [ "anyhow", "base64", @@ -1995,7 +1995,7 @@ dependencies = [ [[package]] name = "wsc-attestation" -version = "0.4.1" +version = "0.5.0" dependencies = [ "chrono", "ct-codecs", @@ -2010,7 +2010,7 @@ dependencies = [ [[package]] name = "wsc-cli" -version = "0.4.1" +version = "0.5.0" dependencies = [ "clap", "env_logger", @@ -2023,7 +2023,7 @@ dependencies = [ [[package]] name = "wsc-component" -version = "0.4.1" +version = "0.5.0" dependencies = [ "wit-bindgen 0.47.0", "wsc", diff --git a/src/lib/Cargo.toml b/src/lib/Cargo.toml index c34725b..77633ad 100644 --- a/src/lib/Cargo.toml +++ b/src/lib/Cargo.toml @@ -68,12 +68,11 @@ wat = "1.221" default = ["software-keys"] # Software-based key storage (always available, for development/testing) software-keys = [] -# Hardware security backends (embedded/production) -tpm2 = [] # TPM 2.0 support - will add tpm2-tss dependency -secure-element = [] # Generic secure element support -atecc608 = ["secure-element"] # Microchip ATECC608 (I2C) -se050 = ["secure-element"] # NXP SE050 EdgeLock (I2C/SPI) -trustzone = [] # ARM TrustZone / OP-TEE support -sgx = [] # Intel SGX support -# Alternative serialization formats (future feature) -cbor = [] # CBOR serialization support +# Hardware security backends (planned - traits available, implementations pending) +tpm2 = [] # TPM 2.0 support (planned) +secure-element = [] # Generic secure element support (planned) +se050 = ["secure-element"] # NXP SE050 EdgeLock (planned) +trustzone = [] # ARM TrustZone / OP-TEE support (planned) +sgx = [] # Intel SGX support (planned) +# Alternative serialization formats (planned) +cbor = [] # CBOR serialization support (planned) diff --git a/src/lib/src/platform/secure_element/atecc608.rs b/src/lib/src/platform/secure_element/atecc608.rs deleted file mode 100644 index 94dad81..0000000 --- a/src/lib/src/platform/secure_element/atecc608.rs +++ /dev/null @@ -1,563 +0,0 @@ -/// Microchip ATECC608 Secure Element Provider -/// -/// The ATECC608 is a cryptographic co-processor with hardware-based key storage -/// and cryptographic operations. It's widely used in IoT devices due to its -/// low cost and power consumption. -/// -/// # Features -/// -/// - **ECC P-256** (NIST secp256r1) signing and key agreement -/// - **16 key slots** with configurable policies -/// - **Hardware RNG** for key generation -/// - **Secure key storage** (keys never readable by host) -/// - **I2C interface** (100-400 kHz) -/// - **Low power** (<150 µA active, <150 nA sleep) -/// -/// # Security -/// -/// - FIPS 140-2 Level 1 certified (optional Level 2) -/// - Keys generated in hardware, never exposed -/// - Anti-tampering features -/// - Locked configuration (write-once) -/// -/// # Pin Configuration -/// -/// ```text -/// ATECC608: -/// Pin 1 (NC): No connect -/// Pin 2 (NC): No connect -/// Pin 3 (NC): No connect -/// Pin 4 (GND): Ground -/// Pin 5 (SDA): I2C Data -/// Pin 6 (SCL): I2C Clock -/// Pin 7 (NC): No connect -/// Pin 8 (VCC): Power (2.0-5.5V) -/// ``` -/// -/// # I2C Address -/// -/// Default: 0x60 (can be configured to 0xC0) -/// -/// # Example -/// -/// ```ignore -/// use wsc::platform::secure_element::atecc608::Atecc608Provider; -/// use wsc::platform::SecureKeyProvider; -/// -/// // Initialize on /dev/i2c-1, address 0x60 -/// let se = Atecc608Provider::new("/dev/i2c-1", 0x60)?; -/// -/// // Generate key in slot 0 (permanently locked) -/// let handle = se.generate_in_slot(KeySlot(0), true)?; -/// -/// // Sign data (happens in secure element) -/// let signature = se.sign(handle, b"data to sign")?; -/// ``` -use super::{I2cBus, KeySlot, KeyUsage, SlotConfig}; -use crate::error::WSError; -use crate::platform::{Attestation, AttestationType, KeyHandle, SecureKeyProvider, SecurityLevel}; -use crate::signature::PublicKey; - -/// ATECC608 command opcodes -#[repr(u8)] -#[derive(Debug, Clone, Copy)] -enum Command { - /// Generate private key - GenKey = 0x40, - /// Sign data with private key - Sign = 0x41, - /// Get public key - Info = 0x30, - /// Read data zone - Read = 0x02, - /// Get random number - Random = 0x1B, - /// Nonce (required before some operations) - Nonce = 0x16, -} - -/// ATECC608 provider implementation -pub struct Atecc608Provider { - /// I2C bus interface - bus: Box, - /// I2C device address - address: u8, - /// Slot allocation tracking - used_slots: [bool; 16], -} - -impl Atecc608Provider { - /// Create a new ATECC608 provider - /// - /// # Arguments - /// - /// * `bus_path` - Path to I2C bus device (e.g., "/dev/i2c-1") - /// * `address` - I2C address of device (usually 0x60) - /// - /// # Returns - /// - /// Initialized provider, or error if device not accessible - /// - /// # Platform Support - /// - /// - **Linux**: Requires i2c-dev kernel module - /// - **Embedded**: Platform-specific I2C HAL - /// - **Testing**: Mock I2C bus - pub fn new(_bus_path: &str, _address: u8) -> Result { - // In a real implementation, we'd open the I2C bus: - // let bus = LinuxI2cBus::open(bus_path)?; - - // For now, return error indicating feature needs hardware - #[cfg(not(test))] - { - return Err(WSError::HardwareError( - "ATECC608 support requires hardware I2C implementation. \ - Enable 'atecc608' feature and provide I2C bus." - .to_string(), - )); - } - - #[cfg(test)] - { - use super::MockI2cBus; - let bus = Box::new(MockI2cBus::new()) as Box; - - Ok(Atecc608Provider { - bus, - address: _address, - used_slots: [false; 16], - }) - } - } - - /// Create provider with custom I2C bus implementation - /// - /// This allows using platform-specific I2C drivers or mocks for testing. - pub fn with_bus(bus: Box, address: u8) -> Self { - Atecc608Provider { - bus, - address, - used_slots: [false; 16], - } - } - - /// Wake up the device from sleep mode - /// - /// ATECC608 requires a wake sequence before communication: - /// 1. SDA held low for >60µs (wake pulse) - /// 2. Device responds with wake token - fn wake(&mut self) -> Result<(), WSError> { - // Wake sequence: write 0x00 to trigger wake - self.bus.write(0x00, &[])?; - - // Wait for wake response (should be 0x04 0x11 0x33 0x43) - let mut response = [0u8; 4]; - self.bus.read(self.address, &mut response)?; - - // Verify wake token - if response != [0x04, 0x11, 0x33, 0x43] { - // In test mode, accept zeros - #[cfg(test)] - { - return Ok(()); - } - #[cfg(not(test))] - { - return Err(WSError::HardwareError( - "Invalid wake response from ATECC608".to_string(), - )); - } - } - - Ok(()) - } - - /// Calculate CRC16 checksum for ATECC608 protocol - /// - /// The ATECC608 uses CRC-16/XMODEM (poly=0x1021, init=0x0000) - fn calculate_crc16(data: &[u8]) -> u16 { - let mut crc: u16 = 0x0000; - - for &byte in data { - crc ^= (byte as u16) << 8; - for _ in 0..8 { - if crc & 0x8000 != 0 { - crc = (crc << 1) ^ 0x1021; - } else { - crc <<= 1; - } - } - } - - crc - } - - /// Send command to device - fn send_command( - &mut self, - opcode: Command, - param1: u8, - param2: u16, - data: &[u8], - ) -> Result, WSError> { - // Wake device - self.wake()?; - - // Build command packet - let mut packet = Vec::new(); - packet.push(0x03); // Command flag - packet.push(7 + data.len() as u8); // Length - packet.push(opcode as u8); - packet.push(param1); - packet.push((param2 & 0xFF) as u8); - packet.push((param2 >> 8) as u8); - packet.extend_from_slice(data); - - // Calculate and append CRC - let crc = Self::calculate_crc16(&packet[1..]); - packet.push((crc & 0xFF) as u8); - packet.push((crc >> 8) as u8); - - // Send command - self.bus.write(self.address, &packet)?; - - // Wait for execution (timing depends on command) - // In real implementation: std::thread::sleep(Duration::from_millis(execution_time)) - - // Read response - let mut response = vec![0u8; 128]; // Max response size - self.bus.read(self.address, &mut response)?; - - // Parse response length - let length = response[0] as usize; - if length < 4 { - return Err(WSError::HardwareError( - "Invalid response length from ATECC608".to_string(), - )); - } - - // Verify CRC - #[cfg(not(test))] - { - let data_crc = Self::calculate_crc16(&response[0..length - 2]); - let received_crc = u16::from_le_bytes([response[length - 2], response[length - 1]]); - if data_crc != received_crc { - return Err(WSError::HardwareError( - "CRC mismatch in ATECC608 response".to_string(), - )); - } - } - - // Return data (excluding length and CRC) - Ok(response[1..length - 2].to_vec()) - } - - /// Find next available key slot - fn find_free_slot(&self) -> Result { - for (i, &used) in self.used_slots.iter().enumerate() { - if !used { - return Ok(KeySlot(i as u8)); - } - } - Err(WSError::NoSpace) - } - - /// Generate key in specific slot - /// - /// # Arguments - /// - /// * `slot` - Key slot number (0-15) - /// * `lock` - If true, key is permanently locked (never extractable) - pub fn generate_in_slot(&mut self, slot: KeySlot, lock: bool) -> Result { - slot.validate()?; - - // Mode: 0x04 = create new key, locked if requested - let mode = if lock { 0x04 } else { 0x00 }; - - // Send GenKey command - let _response = self.send_command(Command::GenKey, mode, slot.0 as u16, &[])?; - - // Mark slot as used - self.used_slots[slot.0 as usize] = true; - - // Encode slot in handle (upper 8 bits = slot, lower 56 bits = 0) - Ok(KeyHandle::from_raw((slot.0 as u64) << 56)) - } - - /// Extract slot number from key handle - fn handle_to_slot(&self, handle: KeyHandle) -> Result { - let slot_num = (handle.as_raw() >> 56) as u8; - let slot = KeySlot(slot_num); - slot.validate()?; - Ok(slot) - } - - /// Get slot configuration - pub fn get_slot_config(&mut self, slot: KeySlot) -> Result { - slot.validate()?; - - // Read configuration zone (would need actual implementation) - // For now, return default config - Ok(SlotConfig { - slot, - locked: true, // Assume locked in production - requires_auth: false, - usage: KeyUsage::Signing, - }) - } -} - -impl SecureKeyProvider for Atecc608Provider { - fn name(&self) -> &str { - "ATECC608 Secure Element" - } - - fn security_level(&self) -> SecurityLevel { - // ATECC608 is hardware-backed with FIPS 140-2 certification - SecurityLevel::HardwareCertified - } - - fn health_check(&self) -> Result<(), WSError> { - // Try to wake device and read device info - // In real implementation: - // - Wake device - // - Send Info command - // - Verify response - - #[cfg(test)] - { - Ok(()) // Always healthy in test mode - } - - #[cfg(not(test))] - { - // Would implement actual health check - Ok(()) - } - } - - fn generate_key(&self) -> Result { - // Cast to mut (in real impl, would use interior mutability) - // This is a design compromise - should use RefCell or Mutex - Err(WSError::InternalError( - "Use generate_in_slot() for ATECC608 to specify key slot".to_string(), - )) - } - - fn load_key(&self, key_id: &str) -> Result { - // Parse slot number from key_id (e.g., "slot:0") - if let Some(slot_str) = key_id.strip_prefix("slot:") { - if let Ok(slot_num) = slot_str.parse::() { - let slot = KeySlot(slot_num); - slot.validate()?; - - // Encode slot in handle - return Ok(KeyHandle::from_raw((slot_num as u64) << 56)); - } - } - - Err(WSError::KeyNotFound(format!( - "Invalid key ID format. Use 'slot:N' where N is 0-15. Got: '{}'", - key_id - ))) - } - - fn sign(&self, handle: KeyHandle, data: &[u8]) -> Result, WSError> { - let _slot = self.handle_to_slot(handle)?; - - // ATECC608 signs SHA-256 hashes - // Data should be pre-hashed to 32 bytes - if data.len() != 32 { - return Err(WSError::InvalidArgument); - } - - // Mode: 0x80 = external signature (data provided) - // In real implementation: - // let response = self.send_command(Command::Sign, 0x80, _slot.0 as u16, data)?; - - // For now, return mock signature (64 bytes for P-256) - #[cfg(test)] - { - Ok(vec![0u8; 64]) - } - - #[cfg(not(test))] - { - // Would send actual Sign command - Ok(vec![0u8; 64]) - } - } - - fn get_public_key(&self, handle: KeyHandle) -> Result { - let _slot = self.handle_to_slot(handle)?; - - // Send GenKey command with mode 0x00 (get public key) - // In real implementation: - // let response = self.send_command(Command::GenKey, 0x00, _slot.0 as u16, &[])?; - - // Response would be 64 bytes (X and Y coordinates of P-256 point) - // Would need to convert from P-256 to Ed25519 for our PublicKey type - // OR extend PublicKey to support P-256 - - Err(WSError::InternalError( - "ATECC608 uses ECDSA P-256, conversion to Ed25519 PublicKey needed".to_string(), - )) - } - - fn attestation(&self, handle: KeyHandle) -> Result, WSError> { - let _slot = self.handle_to_slot(handle)?; - - // ATECC608 supports attestation via device certificate - // Would read device certificate from slot 10 (default) - - Ok(Some(Attestation { - attestation_type: AttestationType::SecureElementCert, - data: vec![], // Would contain device certificate - signature: None, - })) - } - - fn delete_key(&self, handle: KeyHandle) -> Result<(), WSError> { - let slot = self.handle_to_slot(handle)?; - - // ATECC608 doesn't support key deletion once locked - // Can only overwrite if slot is not locked - - Err(WSError::HardwareError(format!( - "ATECC608 slot {} cannot be deleted if locked", - slot.0 - ))) - } - - fn list_keys(&self) -> Result, WSError> { - // Return handles for all used slots - let mut handles = Vec::new(); - for (i, &used) in self.used_slots.iter().enumerate() { - if used { - handles.push(KeyHandle::from_raw((i as u64) << 56)); - } - } - Ok(handles) - } -} - -#[cfg(test)] -mod tests { - use super::super::MockI2cBus; - use super::*; - - fn create_test_provider() -> Atecc608Provider { - Atecc608Provider::new("/dev/i2c-1", 0x60).unwrap() - } - - #[test] - fn test_provider_creation() { - let provider = create_test_provider(); - assert_eq!(provider.name(), "ATECC608 Secure Element"); - assert_eq!(provider.security_level(), SecurityLevel::HardwareCertified); - } - - #[test] - fn test_health_check() { - let provider = create_test_provider(); - assert!(provider.health_check().is_ok()); - } - - #[test] - fn test_crc16_calculation() { - // Test vector from ATECC608 datasheet - let data = [0x07, 0x02, 0x00, 0x00, 0x00]; - let crc = Atecc608Provider::calculate_crc16(&data); - - // Verify it produces a CRC (exact value depends on test vector) - assert_ne!(crc, 0); - } - - #[test] - fn test_slot_validation() { - let provider = create_test_provider(); - - // Valid slots - assert!(provider.handle_to_slot(KeyHandle::from_raw(0)).is_ok()); - assert!( - provider - .handle_to_slot(KeyHandle::from_raw(15u64 << 56)) - .is_ok() - ); - - // Invalid slots - assert!( - provider - .handle_to_slot(KeyHandle::from_raw(16u64 << 56)) - .is_err() - ); - } - - #[test] - fn test_load_key_by_slot() { - let provider = create_test_provider(); - - // Valid slot ID - let result = provider.load_key("slot:0"); - assert!(result.is_ok()); - - let handle = result.unwrap(); - let slot = provider.handle_to_slot(handle).unwrap(); - assert_eq!(slot.0, 0); - - // Invalid formats - assert!(provider.load_key("invalid").is_err()); - assert!(provider.load_key("slot:99").is_err()); - } - - #[test] - fn test_list_keys_empty() { - let provider = create_test_provider(); - let keys = provider.list_keys().unwrap(); - assert_eq!(keys.len(), 0); - } - - #[test] - fn test_attestation_supported() { - let provider = create_test_provider(); - let handle = KeyHandle::from_raw(0); // Slot 0 - - let attestation = provider.attestation(handle).unwrap(); - assert!(attestation.is_some()); - - let att = attestation.unwrap(); - assert_eq!(att.attestation_type, AttestationType::SecureElementCert); - } - - #[test] - fn test_sign_requires_32_bytes() { - let provider = create_test_provider(); - let handle = KeyHandle::from_raw(0); // Slot 0 - - // Valid 32-byte hash - let hash = [0u8; 32]; - let result = provider.sign(handle, &hash); - assert!(result.is_ok()); - - // Invalid length - let invalid = [0u8; 16]; - let result = provider.sign(handle, &invalid); - assert!(result.is_err()); - } - - #[test] - fn test_custom_bus() { - let mock_bus = Box::new(MockI2cBus::new()) as Box; - let provider = Atecc608Provider::with_bus(mock_bus, 0x60); - - assert_eq!(provider.address, 0x60); - assert_eq!(provider.used_slots.len(), 16); - } - - #[test] - fn test_command_enum() { - assert_eq!(Command::GenKey as u8, 0x40); - assert_eq!(Command::Sign as u8, 0x41); - assert_eq!(Command::Info as u8, 0x30); - } -} diff --git a/src/lib/src/platform/secure_element/mod.rs b/src/lib/src/platform/secure_element/mod.rs index 7ba8060..d3e99b3 100644 --- a/src/lib/src/platform/secure_element/mod.rs +++ b/src/lib/src/platform/secure_element/mod.rs @@ -1,9 +1,8 @@ /// Secure Element integration for embedded systems /// -/// This module provides support for hardware secure elements commonly used in -/// IoT and embedded systems: +/// This module provides traits and types for hardware secure elements commonly +/// used in IoT and embedded systems. Actual implementations are planned for: /// -/// - **ATECC608**: Microchip CryptoAuthentication (I2C, cost-effective) /// - **SE050**: NXP EdgeLock (I2C/SPI, advanced features) /// - **OPTIGA**: Infineon Trust M (I2C, automotive-grade) /// @@ -21,7 +20,6 @@ /// Most secure elements use I2C or SPI protocols: /// - **I2C**: Most common, 100-400 kHz /// - **SPI**: Higher speed, less common -/// - **UART**: Rare, legacy devices /// /// # Architecture /// @@ -43,30 +41,15 @@ /// - Keys can be locked (write-once, read-never) /// - Slot can require authentication /// -/// # Example +/// # Status /// -/// ```ignore -/// use wsc::platform::secure_element::{Atecc608Provider, KeySlot}; -/// -/// // Initialize secure element on I2C bus 1, address 0x60 -/// let se = Atecc608Provider::new("/dev/i2c-1", 0x60)?; -/// -/// // Generate key in slot 0 (locked, never extractable) -/// let handle = se.generate_in_slot(KeySlot(0), true)?; -/// -/// // Sign data (operation happens IN secure element) -/// let signature = se.sign(handle, data)?; -/// -/// // Public key can be exported -/// let public_key = se.get_public_key(handle)?; -/// ``` +/// This module provides the trait infrastructure for secure element support. +/// Concrete implementations require platform-specific I2C/SPI drivers and +/// are planned for future releases. use crate::error::WSError; use crate::platform::{Attestation, KeyHandle, SecureKeyProvider, SecurityLevel}; use crate::signature::PublicKey; -#[cfg(feature = "atecc608")] -pub mod atecc608; - #[cfg(feature = "se050")] pub mod se050; @@ -167,36 +150,18 @@ impl SecureElementProvider { /// # Returns /// /// Detected secure element provider, or error if none found + /// + /// # Status + /// + /// This function is a placeholder. Secure element support requires + /// platform-specific I2C drivers and is planned for future releases. pub fn auto_detect(_bus_path: &str) -> Result { - // Try common addresses in order of likelihood - // ATECC608: 0x60 (most common in IoT) - // SE050: 0x48 (NXP default) - // OPTIGA: 0x30 (Infineon default) - - #[cfg(feature = "atecc608")] - { - // Try ATECC608 first (most common) - if let Ok(provider) = atecc608::Atecc608Provider::new(_bus_path, 0x60) { - return Ok(SecureElementProvider { - inner: Box::new(provider), - chip_type: ChipType::Atecc608, - }); - } - } - - // TODO(se050): Add SE050 detection when implemented - // #[cfg(feature = "se050")] - // { - // if let Ok(provider) = se050::Se050Provider::new(_bus_path, 0x48) { - // return Ok(SecureElementProvider { - // inner: Box::new(provider), - // chip_type: ChipType::Se050, - // }); - // } - // } + // Secure element implementations planned: + // - SE050: 0x48 (NXP default) + // - OPTIGA: 0x30 (Infineon default) Err(WSError::HardwareError( - "No secure element detected on I2C bus".to_string(), + "Secure element support not yet implemented. See platform/secure_element/ for planned features.".to_string(), )) }