Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
93 changes: 90 additions & 3 deletions hal/blocking/src/ecdsa.rs
Original file line number Diff line number Diff line change
Expand Up @@ -348,7 +348,7 @@ pub trait PrivateKey<C: Curve>: Zeroize {
/// - `Ok(())`: The private key is valid
/// - `Err(ErrorKind::WeakKey)`: The key is zero, equal to curve order, or otherwise weak
/// - `Err(ErrorKind::InvalidKeyFormat)`: The key format is invalid
fn validate(&self) -> Result<(), ErrorKind>;
fn validate(&self, curve: &C) -> Result<(), ErrorKind>;
}

/// A trait representing an abstract elliptic curve with associated types for cryptographic operations.
Expand Down Expand Up @@ -579,18 +579,21 @@ pub trait SerializableSignature<C: Curve>: Signature<C> + IntoBytes + FromBytes
/// Trait for ECDSA key generation over a specific elliptic curve.
///
/// This trait enables generation of cryptographically secure ECDSA key pairs
/// using a cryptographic random number generator.
/// using a cryptographic random number generator. Keys can be generated either
/// as standalone objects or stored directly in a key vault for enhanced security.
///
/// # Security Requirements
///
/// - Must use a cryptographically secure random number generator
/// - Generated keys must be uniformly distributed over the valid scalar range
/// - Private keys must be properly zeroized after use
/// - Key vault storage should be preferred for hardware-backed security
///
/// # Example
///
/// ```rust,ignore
/// use openprot_hal_blocking::ecdsa::{EcdsaKeyGen, Curve, ErrorKind};
/// use openprot_hal_blocking::ecdsa::{EcdsaKeyGen, Curve, generate_and_store_keypair};
/// use openprot_hal_blocking::key_vault::{KeyLifecycle, KeyStore};
/// use rand_core::{RngCore, CryptoRng};
///
/// struct MyKeyGenerator;
Expand All @@ -608,6 +611,20 @@ pub trait SerializableSignature<C: Curve>: Signature<C> + IntoBytes + FromBytes
/// unimplemented!()
/// }
/// }
///
/// // Usage example with standalone function:
/// let mut key_gen = MyKeyGenerator;
/// let mut vault = MyKeyVault::new();
/// let mut rng = MyRng::new();
///
/// let public_key = generate_and_store_keypair(
/// &mut key_gen,
/// &mut vault,
/// KeyId::new(42),
/// KeyUsage::SIGNING,
/// KeyMetadata::default(),
/// &mut rng
/// )?;
/// ```
pub trait EcdsaKeyGen<C: Curve>: ErrorType {
/// The type representing the private key for the curve.
Expand All @@ -630,6 +647,76 @@ pub trait EcdsaKeyGen<C: Curve>: ErrorType {
R: rand_core::RngCore + rand_core::CryptoRng;
}

/// Generates an ECDSA key pair and stores the private key in a key vault.
///
/// This function provides integrated key generation and secure storage, ensuring
/// that private keys are immediately stored in a secure vault rather than
/// being exposed in memory. Only the public key is returned to the caller.
///
/// # Parameters
/// - `key_gen`: The key generator implementation
/// - `vault`: The key vault for secure private key storage
/// - `key_id`: Unique identifier for the key in the vault
/// - `usage`: Usage permissions for the stored key
/// - `metadata`: Additional metadata to store with the key
/// - `rng`: A cryptographically secure random number generator
///
/// # Returns
/// The generated public key (private key is securely stored in vault)
///
/// # Security Benefits
/// - Private key is never exposed to caller
/// - Immediate secure storage reduces attack surface
/// - Usage permissions are set atomically with storage
/// - Vault locking mechanisms can be applied immediately
///
/// # Example
/// ```rust,ignore
/// use openprot_hal_blocking::ecdsa::{generate_and_store_keypair, P256};
/// use openprot_hal_blocking::key_vault::{KeyLifecycle, KeyStore};
///
/// let mut key_gen = MyKeyGenerator::new();
/// let mut vault = MyKeyVault::new();
/// let mut rng = MyRng::new();
///
/// let public_key = generate_and_store_keypair::<P256, _, _, _>(
/// &mut key_gen,
/// &mut vault,
/// KeyId::new(42),
/// KeyUsage::SIGNING,
/// KeyMetadata::default(),
/// &mut rng
/// )?;
/// ```
pub fn generate_and_store_keypair<C, G, V, R>(
key_gen: &mut G,
vault: &mut V,
key_id: <V as crate::key_vault::KeyStore>::KeyId,
usage: <V as crate::key_vault::KeyStore>::KeyUsage,
metadata: <V as crate::key_vault::KeyLifecycle>::KeyMetadata,
rng: &mut R,
) -> Result<G::PublicKey, G::Error>
where
C: Curve,
G: EcdsaKeyGen<C>,
R: rand_core::RngCore + rand_core::CryptoRng,
V: crate::key_vault::KeyLifecycle<KeyData = G::PrivateKey> + crate::key_vault::KeyStore,
<V as crate::key_vault::KeyLifecycle>::KeyId: From<<V as crate::key_vault::KeyStore>::KeyId>,
G::Error: From<V::Error>,
{
// Generate key pair
let (private_key, public_key) = key_gen.generate_keypair(rng)?;

// Store private key in vault with metadata
let lifecycle_key_id = <V as crate::key_vault::KeyLifecycle>::KeyId::from(key_id);
vault
.store_key(lifecycle_key_id, private_key, metadata)
.map_err(G::Error::from)?;
vault.set_key_usage(key_id, usage).map_err(G::Error::from)?;

Ok(public_key)
}

/// Trait for ECDSA signing using a digest algorithm.
///
/// This trait provides ECDSA signature generation from message digests.
Expand Down
209 changes: 209 additions & 0 deletions hal/blocking/src/key_vault.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,209 @@
// Licensed under the Apache-2.0 license

/// Error kind for key management operations.
///
/// This represents a common set of key management operation errors that can occur across
/// different implementations. The enum is `#[non_exhaustive]` to allow for future
/// additions without breaking API compatibility.
///
/// Implementations are free to define more specific or additional error types.
/// However, by providing a mapping to these common errors through the [`Error::kind`]
/// method, generic code can still react to them appropriately.
#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
#[non_exhaustive]
pub enum ErrorKind {
/// The operation is busy and cannot be completed
///
/// This indicates that the hardware or implementation is currently
/// busy with another operation. The caller should retry later.
Busy,

/// The specified key was not found
///
/// Returned when attempting to access a key that does not exist
/// in the storage backend.
KeyNotFound,

/// Access to the key was denied
///
/// This could indicate insufficient permissions, key usage policy
/// violations, or other access control restrictions.
AccessDenied,

/// Invalid key usage specification
///
/// Returned when the specified key usage constraints are invalid
/// or incompatible with the key or storage backend.
InvalidUsage,

/// Hardware fault or failure
///
/// Indicates a hardware-level error in secure storage elements,
/// HSMs, or other hardware-backed key storage.
HardwareFault,

/// Other implementation-specific error
///
/// Catch-all for errors that don't fit other categories.
Other,
}

impl core::fmt::Display for ErrorKind {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self {
Self::Busy => write!(f, "key storage hardware is busy"),
Self::KeyNotFound => write!(f, "specified key was not found"),
Self::AccessDenied => write!(f, "access to key was denied"),
Self::InvalidUsage => write!(f, "invalid key usage specification"),
Self::HardwareFault => write!(f, "hardware fault during key operation"),
Self::Other => write!(f, "key management operation failed"),
}
}
}
/// Common interface for key management errors.
///
/// This trait provides a standardized way to categorize and handle errors
/// from different key management implementations.
pub trait Error: core::fmt::Debug {
/// Convert error to a generic error kind
///
/// By using this method, errors freely defined by HAL implementations
/// can be converted to a set of generic errors upon which generic
/// code can act.
fn kind(&self) -> ErrorKind;
}

/// Trait for associating a type with a key management error type.
///
/// This trait is used throughout the key management module to associate operations
/// with their specific error types while maintaining type safety.
pub trait ErrorType {
/// Error type.
type Error: Error;
}

/// Configuration and setup operations for key vaults
///
/// This trait provides methods for configuring key vault implementations
/// with runtime parameters and checking their configuration state.
pub trait KeyVaultSetup: ErrorType {
/// Configuration type for the key vault
///
/// This type contains all the runtime parameters needed to configure
/// the key vault implementation.
type KeyVaultConfig;

/// Configure the key vault with runtime parameters
///
/// This method applies the provided configuration to the key vault,
/// setting up any necessary resources, security policies, or hardware
/// initialization required for operation.
///
/// # Parameters
///
/// - `config`: Configuration parameters specific to this key vault implementation
///
/// # Errors
///
/// - `ErrorKind::InvalidUsage`: Invalid configuration parameters
/// - `ErrorKind::HardwareFault`: Hardware initialization failed
/// - `ErrorKind::AccessDenied`: Insufficient permissions for configuration
/// - `ErrorKind::Busy`: Key vault is currently busy and cannot be reconfigured
fn configure(&mut self, config: Self::KeyVaultConfig) -> Result<(), Self::Error>;

/// Check if the key vault is properly configured
///
/// Returns `true` if the key vault has been successfully configured
/// and is ready for key operations, `false` otherwise.
///
/// # Note
///
/// This method is infallible as it only checks internal state.
/// It does not perform any hardware operations that could fail.
fn is_configured(&self) -> bool;
}

/// Core key vault operations
pub trait KeyStore: ErrorType {
/// Type representing a key identifier
type KeyId: Copy + Clone + PartialEq + Eq;
/// Type representing key usage permissions
type KeyUsage: Copy + Clone + PartialEq + Eq;

/// Erase a specific key
fn erase_key(&mut self, id: Self::KeyId) -> Result<(), Self::Error>;

/// Erase all keys that are not locked
fn erase_all_keys(&mut self) -> Result<(), Self::Error>;

/// Check if a key exists and is valid
fn key_exists(&self, id: Self::KeyId) -> Result<bool, Self::Error>;

/// Get the usage permissions for a key
fn get_key_usage(&self, id: Self::KeyId) -> Result<Self::KeyUsage, Self::Error>;

/// Set the usage permissions for a key
fn set_key_usage(&mut self, id: Self::KeyId, usage: Self::KeyUsage) -> Result<(), Self::Error>;
}

/// Key locking mechanisms for security
pub trait KeyLocking: ErrorType {
/// Type representing a key identifier
type KeyId: Copy + Clone + PartialEq + Eq;

/// Check if key has write lock
fn is_write_locked(&self, id: Self::KeyId) -> Result<bool, Self::Error>;

/// Set write lock on key
fn set_write_lock(&mut self, id: Self::KeyId) -> Result<(), Self::Error>;

/// Clear write lock on key
fn clear_write_lock(&mut self, id: Self::KeyId) -> Result<(), Self::Error>;

/// Check if key has use lock
fn is_use_locked(&self, id: Self::KeyId) -> Result<bool, Self::Error>;

/// Set use lock on key
fn set_use_lock(&mut self, id: Self::KeyId) -> Result<(), Self::Error>;

/// Clear use lock on key
fn clear_use_lock(&mut self, id: Self::KeyId) -> Result<(), Self::Error>;
}

/// Key lifecycle management
/// Complete key lifecycle from creation to retrieval
pub trait KeyLifecycle: ErrorType {
/// Type representing a key identifier
type KeyId: Copy + Clone + PartialEq + Eq;

/// Type representing key data
type KeyData;

/// Type representing key metadata
type KeyMetadata;

/// Store a key with metadata
fn store_key(
&mut self,
id: Self::KeyId,
data: Self::KeyData,
metadata: Self::KeyMetadata,
) -> Result<(), Self::Error>;

/// Retrieve key data (if permitted)
fn retrieve_key(&self, id: Self::KeyId) -> Result<Self::KeyData, Self::Error>;

/// Get key metadata
fn get_key_metadata(&self, id: Self::KeyId) -> Result<Self::KeyMetadata, Self::Error>;

/// Update key metadata
fn update_key_metadata(
&mut self,
id: Self::KeyId,
metadata: Self::KeyMetadata,
) -> Result<(), Self::Error>;
}

/// Blanket trait implementation for types that implement key vsault setup, core operations, and locking
pub trait KeyVault: KeyVaultSetup + KeyStore + KeyLocking {}
impl<T> KeyVault for T where T: KeyVaultSetup + KeyStore + KeyLocking {}
3 changes: 3 additions & 0 deletions hal/blocking/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ pub mod mac;
/// Reset and clocking traits for OpenPRoT HAL
pub mod system_control;

/// Key management traits
pub mod key_vault;

// Re-export embedded-hal 1.0 traits
pub use embedded_hal::delay::DelayNs;
pub use embedded_hal::digital::{InputPin, OutputPin, StatefulOutputPin};
Expand Down
Loading
Loading