use crate::error::WSError;
use crate::platform::{Attestation, KeyHandle, SecureKeyProvider, SecurityLevel};
use crate::signature::PublicKey;
#[cfg(feature = "se050")]
pub mod se050;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct KeySlot(pub u8);
impl KeySlot {
pub const MAX: u8 = 15;
pub fn validate(&self) -> Result<(), WSError> {
if self.0 > Self::MAX {
return Err(WSError::InvalidArgument);
}
Ok(())
}
}
#[derive(Debug, Clone)]
pub struct SlotConfig {
pub slot: KeySlot,
pub locked: bool,
pub requires_auth: bool,
pub usage: KeyUsage,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum KeyUsage {
Signing,
KeyAgreement,
General,
}
pub trait I2cBus: Send + Sync {
fn write(&mut self, address: u8, data: &[u8]) -> Result<(), WSError>;
fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), WSError>;
fn write_read(
&mut self,
address: u8,
write_data: &[u8],
read_buffer: &mut [u8],
) -> Result<(), WSError>;
}
pub struct SecureElementProvider {
inner: Box<dyn SecureKeyProvider>,
chip_type: ChipType,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ChipType {
Atecc608,
Se050,
OptigaTrustM,
}
impl SecureElementProvider {
pub fn auto_detect(_bus_path: &str) -> Result<Self, WSError> {
Err(WSError::HardwareError(
"Secure element support not yet implemented. See platform/secure_element/ for planned features.".to_string(),
))
}
pub fn chip_type(&self) -> ChipType {
self.chip_type
}
}
impl SecureKeyProvider for SecureElementProvider {
fn name(&self) -> &str {
self.inner.name()
}
fn security_level(&self) -> SecurityLevel {
self.inner.security_level()
}
fn health_check(&self) -> Result<(), WSError> {
self.inner.health_check()
}
fn generate_key(&self) -> Result<KeyHandle, WSError> {
self.inner.generate_key()
}
fn load_key(&self, key_id: &str) -> Result<KeyHandle, WSError> {
self.inner.load_key(key_id)
}
fn sign(&self, handle: KeyHandle, data: &[u8]) -> Result<Vec<u8>, WSError> {
self.inner.sign(handle, data)
}
fn get_public_key(&self, handle: KeyHandle) -> Result<PublicKey, WSError> {
self.inner.get_public_key(handle)
}
fn attestation(&self, handle: KeyHandle) -> Result<Option<Attestation>, WSError> {
self.inner.attestation(handle)
}
fn delete_key(&self, handle: KeyHandle) -> Result<(), WSError> {
self.inner.delete_key(handle)
}
fn list_keys(&self) -> Result<Vec<KeyHandle>, WSError> {
self.inner.list_keys()
}
}
#[cfg(test)]
pub struct MockI2cBus {
responses: std::collections::HashMap<Vec<u8>, Vec<u8>>,
}
#[cfg(test)]
impl MockI2cBus {
pub fn new() -> Self {
MockI2cBus {
responses: std::collections::HashMap::new(),
}
}
pub fn add_response(&mut self, command: Vec<u8>, response: Vec<u8>) {
self.responses.insert(command, response);
}
}
#[cfg(test)]
impl I2cBus for MockI2cBus {
fn write(&mut self, _address: u8, _data: &[u8]) -> Result<(), WSError> {
Ok(())
}
fn read(&mut self, _address: u8, buffer: &mut [u8]) -> Result<(), WSError> {
buffer.fill(0);
Ok(())
}
fn write_read(
&mut self,
_address: u8,
write_data: &[u8],
read_buffer: &mut [u8],
) -> Result<(), WSError> {
if let Some(response) = self.responses.get(write_data) {
let copy_len = response.len().min(read_buffer.len());
read_buffer[..copy_len].copy_from_slice(&response[..copy_len]);
Ok(())
} else {
read_buffer.fill(0);
Ok(())
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_key_slot_validation() {
assert!(KeySlot(0).validate().is_ok());
assert!(KeySlot(15).validate().is_ok());
assert!(KeySlot(16).validate().is_err()); assert!(KeySlot(255).validate().is_err());
}
#[test]
fn test_key_slot_max() {
assert_eq!(KeySlot::MAX, 15);
}
#[test]
fn test_slot_config_creation() {
let config = SlotConfig {
slot: KeySlot(0),
locked: true,
requires_auth: false,
usage: KeyUsage::Signing,
};
assert_eq!(config.slot.0, 0);
assert!(config.locked);
assert!(!config.requires_auth);
assert_eq!(config.usage, KeyUsage::Signing);
}
#[test]
fn test_mock_i2c_bus() {
let mut bus = MockI2cBus::new();
let command = vec![0x01, 0x02, 0x03];
let response = vec![0x04, 0x05, 0x06];
bus.add_response(command.clone(), response.clone());
let mut read_buffer = vec![0u8; 3];
assert!(bus.write_read(0x60, &command, &mut read_buffer).is_ok());
assert_eq!(read_buffer, response);
}
#[test]
fn test_chip_type_equality() {
assert_eq!(ChipType::Atecc608, ChipType::Atecc608);
assert_ne!(ChipType::Atecc608, ChipType::Se050);
}
#[test]
fn test_key_usage() {
let signing = KeyUsage::Signing;
let agreement = KeyUsage::KeyAgreement;
let general = KeyUsage::General;
assert_eq!(signing, KeyUsage::Signing);
assert_ne!(signing, agreement);
assert_ne!(agreement, general);
}
}