use crate::error::WSError;
use crate::signature::PublicKey;
use std::fmt;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum SigningAlgorithm {
Ed25519,
EcdsaP256,
EcdsaP384,
}
impl fmt::Display for SigningAlgorithm {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
SigningAlgorithm::Ed25519 => write!(f, "ed25519"),
SigningAlgorithm::EcdsaP256 => write!(f, "ecdsa-p256"),
SigningAlgorithm::EcdsaP384 => write!(f, "ecdsa-p384"),
}
}
}
pub trait HardwareSigner: Send + Sync {
fn sign(&self, data: &[u8]) -> Result<Vec<u8>, HardwareError>;
fn public_key(&self) -> Result<Vec<u8>, HardwareError>;
fn algorithm(&self) -> SigningAlgorithm;
fn key_id(&self) -> Option<String> {
None
}
fn security_level(&self) -> SecurityLevel {
SecurityLevel::Software
}
}
pub trait HardwareVerifier: Send + Sync {
fn verify(&self, data: &[u8], signature: &[u8], public_key: &[u8]) -> Result<(), HardwareError>;
fn supported_algorithms(&self) -> Vec<SigningAlgorithm>;
fn supports_algorithm(&self, algorithm: SigningAlgorithm) -> bool {
self.supported_algorithms().contains(&algorithm)
}
}
#[derive(Debug, Clone)]
pub enum HardwareError {
NotAvailable(String),
KeyNotFound(String),
SigningFailed(String),
VerificationFailed(String),
UnsupportedAlgorithm(SigningAlgorithm),
CommunicationError(String),
AccessDenied(String),
}
impl fmt::Display for HardwareError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
HardwareError::NotAvailable(msg) => write!(f, "Hardware not available: {}", msg),
HardwareError::KeyNotFound(msg) => write!(f, "Key not found: {}", msg),
HardwareError::SigningFailed(msg) => write!(f, "Signing failed: {}", msg),
HardwareError::VerificationFailed(msg) => write!(f, "Verification failed: {}", msg),
HardwareError::UnsupportedAlgorithm(alg) => {
write!(f, "Algorithm not supported: {}", alg)
}
HardwareError::CommunicationError(msg) => write!(f, "Communication error: {}", msg),
HardwareError::AccessDenied(msg) => write!(f, "Access denied: {}", msg),
}
}
}
impl std::error::Error for HardwareError {}
pub struct SoftwareEd25519Signer {
secret_key: ed25519_compact::SecretKey,
key_id: Option<String>,
}
impl SoftwareEd25519Signer {
pub fn from_secret_key(secret_key: ed25519_compact::SecretKey, key_id: Option<String>) -> Self {
Self { secret_key, key_id }
}
pub fn generate(key_id: Option<String>) -> Self {
let key_pair = ed25519_compact::KeyPair::generate();
Self {
secret_key: key_pair.sk,
key_id,
}
}
}
impl HardwareSigner for SoftwareEd25519Signer {
fn sign(&self, data: &[u8]) -> Result<Vec<u8>, HardwareError> {
let signature = self.secret_key.sign(data, None);
Ok(signature.as_ref().to_vec())
}
fn public_key(&self) -> Result<Vec<u8>, HardwareError> {
Ok(self.secret_key.public_key().as_ref().to_vec())
}
fn algorithm(&self) -> SigningAlgorithm {
SigningAlgorithm::Ed25519
}
fn key_id(&self) -> Option<String> {
self.key_id.clone()
}
fn security_level(&self) -> SecurityLevel {
SecurityLevel::Software
}
}
pub struct SoftwareEd25519Verifier;
impl SoftwareEd25519Verifier {
pub fn new() -> Self {
Self
}
}
impl Default for SoftwareEd25519Verifier {
fn default() -> Self {
Self::new()
}
}
impl HardwareVerifier for SoftwareEd25519Verifier {
fn verify(&self, data: &[u8], signature: &[u8], public_key: &[u8]) -> Result<(), HardwareError> {
if signature.len() != 64 {
return Err(HardwareError::VerificationFailed(
"Invalid signature length (expected 64 bytes)".to_string(),
));
}
if public_key.len() != 32 {
return Err(HardwareError::VerificationFailed(
"Invalid public key length (expected 32 bytes)".to_string(),
));
}
let sig = ed25519_compact::Signature::from_slice(signature).map_err(|e| {
HardwareError::VerificationFailed(format!("Invalid signature format: {:?}", e))
})?;
let pk = ed25519_compact::PublicKey::from_slice(public_key).map_err(|e| {
HardwareError::VerificationFailed(format!("Invalid public key format: {:?}", e))
})?;
pk.verify(data, &sig)
.map_err(|_| HardwareError::VerificationFailed("Signature verification failed".to_string()))
}
fn supported_algorithms(&self) -> Vec<SigningAlgorithm> {
vec![SigningAlgorithm::Ed25519]
}
}
#[cfg(feature = "software-keys")]
pub mod software;
#[cfg(feature = "keyring-storage")]
pub mod keyring_storage;
#[cfg(all(feature = "tpm2", target_os = "linux"))]
pub mod tpm2;
#[cfg(feature = "secure-element")]
pub mod secure_element;
#[cfg(feature = "trustzone")]
pub mod trustzone;
#[cfg(feature = "sgx")]
pub mod sgx;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct KeyHandle(u64);
impl KeyHandle {
pub fn from_raw(value: u64) -> Self {
KeyHandle(value)
}
pub fn as_raw(&self) -> u64 {
self.0
}
}
#[derive(Debug, Clone)]
pub struct Attestation {
pub attestation_type: AttestationType,
pub data: Vec<u8>,
pub signature: Option<Vec<u8>>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum AttestationType {
None,
Tpm2Quote,
SgxReport,
TrustZoneAttestation,
SecureElementCert,
}
pub trait SecureKeyProvider: Send + Sync {
fn name(&self) -> &str;
fn security_level(&self) -> SecurityLevel;
fn health_check(&self) -> Result<(), WSError>;
fn generate_key(&self) -> Result<KeyHandle, WSError>;
fn load_key(&self, key_id: &str) -> Result<KeyHandle, WSError>;
fn sign(&self, handle: KeyHandle, data: &[u8]) -> Result<Vec<u8>, WSError>;
fn get_public_key(&self, handle: KeyHandle) -> Result<PublicKey, WSError>;
fn attestation(&self, handle: KeyHandle) -> Result<Option<Attestation>, WSError> {
let _ = handle; Ok(None) }
fn delete_key(&self, handle: KeyHandle) -> Result<(), WSError>;
fn list_keys(&self) -> Result<Vec<KeyHandle>, WSError>;
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub enum SecurityLevel {
Software = 0,
HardwareBasic = 1,
HardwareBacked = 2,
HardwareCertified = 3,
}
impl fmt::Display for SecurityLevel {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
SecurityLevel::Software => write!(f, "Software (Development Only)"),
SecurityLevel::HardwareBasic => write!(f, "Hardware-Assisted"),
SecurityLevel::HardwareBacked => write!(f, "Hardware-Backed (Production)"),
SecurityLevel::HardwareCertified => write!(f, "Hardware-Certified (High Security)"),
}
}
}
pub fn detect_platform() -> Result<Box<dyn SecureKeyProvider>, WSError> {
#[cfg(all(feature = "tpm2", target_os = "linux"))]
{
if let Ok(provider) = tpm2::Tpm2Provider::new() {
log::info!("Detected TPM 2.0 hardware");
return Ok(Box::new(provider));
}
}
#[cfg(feature = "secure-element")]
{
for bus_path in &["/dev/i2c-1", "/dev/i2c-0", "/dev/i2c-2"] {
if let Ok(provider) = secure_element::SecureElementProvider::auto_detect(bus_path) {
log::info!("Detected secure element hardware on {}", bus_path);
return Ok(Box::new(provider));
}
}
}
#[cfg(feature = "trustzone")]
{
if let Ok(provider) = trustzone::TrustZoneProvider::new() {
log::info!("Detected ARM TrustZone");
return Ok(Box::new(provider));
}
}
#[cfg(feature = "software-keys")]
{
log::warn!("No hardware security detected, using software keys (DEVELOPMENT ONLY)");
Ok(Box::new(software::SoftwareProvider::new()))
}
#[cfg(not(feature = "software-keys"))]
{
Err(WSError::HardwareError(
"No hardware security modules available".to_string(),
))
}
}
pub fn list_available_providers() -> Vec<(String, Box<dyn SecureKeyProvider>)> {
let mut providers = Vec::new();
#[cfg(feature = "secure-element")]
{
for bus_path in &["/dev/i2c-1", "/dev/i2c-0", "/dev/i2c-2"] {
if let Ok(provider) = secure_element::SecureElementProvider::auto_detect(bus_path) {
providers.push((
format!("Secure Element ({})", bus_path),
Box::new(provider) as Box<dyn SecureKeyProvider>,
));
break; }
}
}
#[cfg(feature = "trustzone")]
{
if let Ok(provider) = trustzone::TrustZoneProvider::new() {
providers.push((
"TrustZone".to_string(),
Box::new(provider) as Box<dyn SecureKeyProvider>,
));
}
}
#[cfg(feature = "software-keys")]
{
providers.push((
"Software (Development)".to_string(),
Box::new(software::SoftwareProvider::new()) as Box<dyn SecureKeyProvider>,
));
}
providers
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_software_ed25519_signer() {
let signer = SoftwareEd25519Signer::generate(Some("test-key".to_string()));
let data = b"test data to sign";
let signature = signer.sign(data).expect("signing should succeed");
assert_eq!(signature.len(), 64, "Ed25519 signature should be 64 bytes");
let public_key = signer.public_key().expect("public key should be available");
assert_eq!(public_key.len(), 32, "Ed25519 public key should be 32 bytes");
assert_eq!(signer.key_id(), Some("test-key".to_string()));
assert_eq!(signer.algorithm(), SigningAlgorithm::Ed25519);
assert_eq!(signer.security_level(), SecurityLevel::Software);
}
#[test]
fn test_software_ed25519_verifier() {
let verifier = SoftwareEd25519Verifier::new();
let signer = SoftwareEd25519Signer::generate(None);
let data = b"test data for verification";
let signature = signer.sign(data).unwrap();
let public_key = signer.public_key().unwrap();
assert!(verifier.verify(data, &signature, &public_key).is_ok());
assert!(verifier.verify(b"wrong data", &signature, &public_key).is_err());
let mut bad_sig = signature.clone();
bad_sig[0] ^= 0xff;
assert!(verifier.verify(data, &bad_sig, &public_key).is_err());
let algorithms = verifier.supported_algorithms();
assert!(algorithms.contains(&SigningAlgorithm::Ed25519));
assert!(verifier.supports_algorithm(SigningAlgorithm::Ed25519));
assert!(!verifier.supports_algorithm(SigningAlgorithm::EcdsaP256));
}
#[test]
fn test_signing_algorithm_display() {
assert_eq!(SigningAlgorithm::Ed25519.to_string(), "ed25519");
assert_eq!(SigningAlgorithm::EcdsaP256.to_string(), "ecdsa-p256");
assert_eq!(SigningAlgorithm::EcdsaP384.to_string(), "ecdsa-p384");
}
#[test]
fn test_hardware_error_display() {
let err = HardwareError::NotAvailable("TPM not found".to_string());
assert!(err.to_string().contains("Hardware not available"));
assert!(err.to_string().contains("TPM not found"));
let err = HardwareError::VerificationFailed("bad signature".to_string());
assert!(err.to_string().contains("Verification failed"));
let err = HardwareError::UnsupportedAlgorithm(SigningAlgorithm::EcdsaP384);
assert!(err.to_string().contains("ecdsa-p384"));
}
#[test]
fn test_key_handle_creation() {
let handle = KeyHandle::from_raw(42);
assert_eq!(handle.as_raw(), 42);
}
#[test]
fn test_key_handle_equality() {
let handle1 = KeyHandle::from_raw(42);
let handle2 = KeyHandle::from_raw(42);
let handle3 = KeyHandle::from_raw(43);
assert_eq!(handle1, handle2);
assert_ne!(handle1, handle3);
}
#[test]
fn test_security_level_ordering() {
assert!(SecurityLevel::Software < SecurityLevel::HardwareBasic);
assert!(SecurityLevel::HardwareBasic < SecurityLevel::HardwareBacked);
assert!(SecurityLevel::HardwareBacked < SecurityLevel::HardwareCertified);
}
#[test]
fn test_security_level_display() {
assert_eq!(
SecurityLevel::Software.to_string(),
"Software (Development Only)"
);
assert_eq!(
SecurityLevel::HardwareCertified.to_string(),
"Hardware-Certified (High Security)"
);
}
#[test]
fn test_detect_platform() {
let result = detect_platform();
assert!(result.is_ok());
let provider = result.unwrap();
println!("Detected platform: {}", provider.name());
println!("Security level: {}", provider.security_level());
}
#[test]
fn test_list_available_providers() {
let providers = list_available_providers();
assert!(!providers.is_empty(), "Should have at least one provider");
for (name, provider) in providers {
println!(
"Available provider: {} ({})",
name,
provider.security_level()
);
}
}
}