blob: 290b925e0b537e309db870925f9c1964e5439d84 [file] [log] [blame]
// Licensed under the Apache-2.0 license
// SPDX-License-Identifier: Apache-2.0
//! # ECDSA Digital Signature Operations
//!
//! This module provides a comprehensive, type-safe abstraction for Elliptic Curve Digital
//! Signature Algorithm (ECDSA) operations. The design follows security best practices and
//! provides a generic interface that can work with any elliptic curve.
//!
//! ## Features
//!
//! - **Type Safety**: Generic over curve types to prevent cross-curve contamination
//! - **Security First**: Mandatory cryptographic RNG, proper key validation, secure memory clearing
//! - **No-std Compatible**: Works in embedded environments without standard library
//! - **Comprehensive Error Handling**: Detailed error types for proper debugging and security
//! - **Optional Serialization**: Flexible serialization support for software keys, with hardware key compatibility
//!
//! ## Architecture
//!
//! The module follows a trait-based design with the following key components:
//!
//! ```text
//! Curve (Abstract EC Parameters)
//! ├── DigestType: DigestAlgorithm
//! └── Scalar: IntoBytes + FromBytes
//!
//! Key Management
//! ├── PrivateKey<C>: Zeroize + Validation
//! ├── SerializablePrivateKey<C>: PrivateKey<C> + Serialization (optional)
//! ├── PublicKey<C>: Coordinate Access + Validation
//! └── SerializablePublicKey<C>: PublicKey<C> + Serialization (optional)
//!
//! Signatures
//! ├── Signature<C>: Component Access + Validation
//! └── SerializableSignature<C>: Signature<C> + Serialization (optional)
//!
//! Operations
//! ├── EcdsaKeyGen<C>: Key pair generation
//! ├── EcdsaSign<C>: Digital signing with RNG
//! └── EcdsaVerify<C>: Signature verification
//!
//! Error Handling
//! ├── Error: Debug → ErrorKind mapping
//! ├── ErrorType: Associated error types
//! └── ErrorKind: Common error classifications
//!
//! Key Storage Patterns
//! ├── Software Keys: Implement SerializablePrivateKey for persistence
//! ├── Hardware Keys: Implement only PrivateKey for HSM/secure enclave
//! └── Hybrid Systems: Mix both patterns as needed
//! ```
//!
//! ## Usage Example
//!
//! ```rust,no_run
//! # use openprot_hal_blocking::ecdsa::*;
//! # use rand_core::{RngCore, CryptoRng};
//! #
//! # fn example() -> Result<(), Box<dyn std::error::Error>> {
//! // This example shows both software and hardware key patterns
//!
//! // SOFTWARE KEYS (with optional serialization):
//! // let mut key_generator = SoftwareKeyGen::new();
//! // let mut rng = YourCryptoRng::new();
//! // let (private_key, public_key) = key_generator.generate_keypair(&mut rng)?;
//!
//! // Software keys can be serialized:
//! // let private_bytes = private_key.as_bytes(); // SerializablePrivateKey
//! // let public_bytes = public_key.as_bytes(); // SerializablePublicKey
//!
//! // HARDWARE KEYS (no serialization):
//! // let mut hsm_generator = HsmKeyGen::new();
//! // let (hsm_private, hsm_public) = hsm_generator.generate_keypair(&mut rng)?;
//!
//! // Hardware keys cannot be serialized (no IntoBytes/FromBytes bounds)
//! // but can still be used for cryptographic operations:
//! // hsm_private.validate()?; // PrivateKey trait method
//!
//! // Both key types work the same for crypto operations:
//! // let mut signer = YourSignerImpl::new();
//! // let message_digest = your_hash_function(message);
//! // let signature = signer.sign(&private_key, &message_digest, &mut rng)?;
//! // let signature_hsm = signer.sign(&hsm_private, &message_digest, &mut rng)?;
//!
//! # Ok(())
//! # }
//! ```
//!
//! ## Security Considerations
//!
//! - **Always validate inputs**: Use the `validate()` methods on keys and signatures
//! - **Use cryptographic RNG**: Only `CryptoRng + RngCore` is accepted for signing
//! - **Clear sensitive data**: Private keys implement `Zeroize` for secure memory clearing
//! - **Hardware key support**: Private keys can be non-serializable for HSM/secure enclave use
//! - **Constant-time operations**: Implementers should use constant-time algorithms where possible
//! - **Side-channel protection**: Be aware of timing attacks in verification operations
use crate::digest::DigestAlgorithm;
use core::fmt::Debug;
use zerocopy::Immutable;
use zerocopy::{FromBytes, IntoBytes};
use zeroize::Zeroize;
/// Trait for converting implementation-specific ECDSA errors into generic error kinds.
///
/// This trait allows HAL implementations to define their own detailed error types
/// while still providing a common interface for generic code to handle errors.
///
/// # Example
///
/// ```rust
/// # use openprot_hal_blocking::ecdsa::{Error, ErrorKind};
/// #[derive(Debug)]
/// enum MyEcdsaError {
/// HardwareFault,
/// InvalidParameters,
/// Timeout,
/// }
///
/// impl Error for MyEcdsaError {
/// fn kind(&self) -> ErrorKind {
/// match self {
/// MyEcdsaError::HardwareFault => ErrorKind::Other,
/// MyEcdsaError::InvalidParameters => ErrorKind::InvalidKeyFormat,
/// MyEcdsaError::Timeout => ErrorKind::Busy,
/// }
/// }
/// }
/// ```
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;
}
impl Error for core::convert::Infallible {
fn kind(&self) -> ErrorKind {
match *self {}
}
}
/// Trait for associating a type with an ECDSA error type.
///
/// This trait is used throughout the ECDSA module to associate operations
/// with their specific error types while maintaining type safety.
///
/// # Example
///
/// ```rust
/// # use openprot_hal_blocking::ecdsa::{ErrorType, Error, ErrorKind};
/// # #[derive(Debug)]
/// # enum MyError { Failed }
/// # impl Error for MyError {
/// # fn kind(&self) -> ErrorKind { ErrorKind::Other }
/// # }
/// struct MyEcdsaDevice;
///
/// impl ErrorType for MyEcdsaDevice {
/// type Error = MyError;
/// }
/// ```
pub trait ErrorType {
/// Error type.
type Error: Error;
}
/// Error kind for ECDSA operations.
///
/// This represents a common set of ECDSA 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.
///
/// # Security Note
///
/// Error types should not leak sensitive information. For example, avoid
/// distinguishing between "key not found" and "wrong key" errors, as this
/// could provide timing attack vectors.
///
/// # Examples
///
/// ```rust
/// # use openprot_hal_blocking::ecdsa::ErrorKind;
/// # let error_kind = ErrorKind::Busy;
/// match error_kind {
/// ErrorKind::InvalidSignature => {
/// // Handle signature verification failure
/// eprintln!("Signature verification failed");
/// }
/// ErrorKind::WeakKey => {
/// // Handle weak key detection
/// eprintln!("Weak key detected - regenerate keypair");
/// }
/// ErrorKind::Busy => {
/// // Handle resource busy - retry later
/// eprintln!("ECDSA hardware is busy, retry later");
/// }
/// _ => {
/// // Handle other errors
/// eprintln!("ECDSA operation failed: {:?}", error_kind);
/// }
/// }
/// ```
#[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 signature is invalid
///
/// Returned when signature verification fails. This could indicate:
/// - The signature was corrupted during transmission
/// - The signature was created with a different key
/// - The message was modified after signing
/// - The signature components (r, s) are invalid
InvalidSignature,
/// Key generation failed
///
/// Indicates that the key generation process could not complete successfully.
/// This might be due to insufficient entropy, hardware failures, or other
/// random number generation issues.
KeyGenError,
/// Signing operation failed
///
/// The signing process encountered an error. This is distinct from key
/// generation errors and typically indicates issues during the actual
/// signing computation.
SigningError,
/// Invalid key format or encoding
///
/// The provided key data could not be parsed or is in an unsupported format.
/// This includes issues with:
/// - Incorrect key length
/// - Invalid encoding (DER, PEM, etc.)
/// - Malformed key structure
InvalidKeyFormat,
/// Point is not on the curve
///
/// The provided coordinates do not represent a valid point on the specified
/// elliptic curve. This is a critical security check that prevents attacks
/// using invalid curve points.
InvalidPoint,
/// Unsupported curve or algorithm
///
/// The requested elliptic curve or algorithm parameters are not supported
/// by this implementation. Common reasons include:
/// - Curve not implemented in hardware
/// - Disabled curve due to security concerns
/// - Incompatible curve parameters
UnsupportedCurve,
/// Weak key detected (e.g., zero key, key equal to curve order)
///
/// The key fails cryptographic strength requirements. This includes:
/// - Zero private keys
/// - Private keys equal to the curve order
/// - Public keys at the identity point
/// - Other mathematically weak keys
WeakKey,
/// Other unspecified error
///
/// A catch-all for errors that don't fit into the specific categories above.
/// Implementations should prefer specific error types when possible.
Other,
}
/// Trait for ECC private keys associated with a specific curve.
///
/// Private keys must implement secure memory clearing through the [`Zeroize`] trait
/// to ensure cryptographic material is properly destroyed when no longer needed.
///
/// # Security Requirements
///
/// Implementations must:
/// - Validate keys are within the valid scalar range (1 < key < curve_order)
/// - Implement constant-time operations where possible
/// - Clear sensitive data from memory using [`Zeroize`]
/// - Hardware keys may store only handles/references, not actual key material
///
/// # Hardware Key Considerations
///
/// For hardware-based keys (HSMs, TPMs, secure enclaves):
/// - The `Zeroize` implementation may clear key handles/references
/// - Actual key material remains securely stored in hardware
/// - Consider calling hardware APIs to invalidate keys during zeroization
/// - Some implementations may use no-op zeroization if hardware manages lifecycle
///
/// # Example
///
/// ```rust,ignore
/// use openprot_hal_blocking::ecdsa::{PrivateKey, SerializablePrivateKey, Curve, ErrorKind};
/// use zeroize::Zeroize;
/// use zerocopy::{IntoBytes, FromBytes};
///
/// // Software private key (can be serialized)
/// #[derive(IntoBytes, FromBytes)]
/// struct SoftwarePrivateKey([u8; 32]);
///
/// impl<C: Curve> PrivateKey<C> for SoftwarePrivateKey {
/// fn validate(&self) -> Result<(), ErrorKind> {
/// // Check if key is zero or equal to curve order
/// if self.0.iter().all(|&b| b == 0) {
/// return Err(ErrorKind::WeakKey);
/// }
/// Ok(())
/// }
/// }
///
/// // Implement optional serialization
/// impl<C: Curve> SerializablePrivateKey<C> for SoftwarePrivateKey {}
///
/// // Hardware private key (cannot be serialized)
/// struct HardwarePrivateKey {
/// key_handle: u32, // Handle to key in HSM
/// }
///
/// impl<C: Curve> PrivateKey<C> for HardwarePrivateKey {
/// fn validate(&self) -> Result<(), ErrorKind> {
/// // Validate key exists in hardware
/// // (implementation would call into HSM API)
/// Ok(())
/// }
/// }
///
/// // No SerializablePrivateKey implementation for hardware keys
/// ```
pub trait PrivateKey<C: Curve>: Zeroize {
/// Validate that this private key is valid for the curve.
///
/// This method should verify that the private key is within the valid
/// range for the curve (typically 1 < key < curve_order).
///
/// # Returns
/// - `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, curve: &C) -> Result<(), ErrorKind>;
}
/// A trait representing an abstract elliptic curve with associated types for cryptographic operations.
///
/// This trait defines the fundamental components required for elliptic curve cryptography,
/// including the digest algorithm for hashing operations and the scalar field element type
/// for curve arithmetic.
///
/// # Associated Types
///
/// - [`DigestType`]: The hash function used for message digests in signing operations
/// - [`Scalar`]: The field element type representing curve coordinates and private keys
///
/// # Example
///
/// ```rust,ignore
/// use openprot_hal_blocking::ecdsa::{Curve, DigestAlgorithm};
/// use openprot_hal_blocking::digest::Sha256;
///
/// struct P256;
///
/// impl Curve for P256 {
/// type DigestType = Sha256;
/// type Scalar = [u8; 32];
/// }
/// ```
///
/// [`DigestType`]: Curve::DigestType
/// [`Scalar`]: Curve::Scalar
pub trait Curve {
/// The digest algorithm used by this elliptic curve for cryptographic operations.
type DigestType: DigestAlgorithm;
/// The scalar field element type used in elliptic curve operations.
type Scalar: IntoBytes + FromBytes;
}
/// Trait for ECDSA signatures associated with a specific curve.
///
/// This trait provides access to signature components and validation methods
/// for ECDSA signatures over elliptic curves.
///
/// # Security Considerations
///
/// - Signature components (r, s) must be in the range [1, curve_order)
/// - Zero values for r or s make the signature invalid
/// - Implementations should validate signatures before use
///
/// # Example
///
/// ```rust,ignore
/// use openprot_hal_blocking::ecdsa::{Signature, Curve, ErrorKind};
///
/// struct MySignature {
/// r: [u8; 32],
/// s: [u8; 32],
/// }
///
/// impl<C: Curve> Signature<C> for MySignature {
/// fn from_coordinates(r: C::Scalar, s: C::Scalar) -> Result<Self, ErrorKind> {
/// // Validate that r and s are in valid range [1, curve_order)
/// if r.iter().all(|&b| b == 0) || s.iter().all(|&b| b == 0) {
/// return Err(ErrorKind::InvalidSignature);
/// }
/// Ok(Self { r, s })
/// }
///
/// fn coordinates(&self, r_out: &mut C::Scalar, s_out: &mut C::Scalar) {
/// // Zero-allocation coordinate access for embedded environments
/// *r_out = self.r;
/// *s_out = self.s;
/// }
/// }
/// ```
pub trait Signature<C: Curve> {
/// Create a new signature from r and s components with validation.
///
/// This method validates that both r and s are within the valid range
/// for the curve (typically 1 ≤ r,s < curve_order).
///
/// # Parameters
/// - `r`: The r component of the signature
/// - `s`: The s component of the signature
///
/// # Returns
/// - `Ok(Self)`: Valid signature
/// - `Err(ErrorKind::InvalidSignature)`: If r or s are invalid (zero or ≥ curve order)
fn from_coordinates(r: C::Scalar, s: C::Scalar) -> Result<Self, ErrorKind>
where
Self: Sized;
/// Write coordinates to output buffers (zero-allocation for embedded).
///
/// This method provides zero-allocation coordinate access for embedded
/// environments. Implementations can extract coordinates directly into
/// the provided buffers without temporary allocation.
fn coordinates(&self, x_out: &mut C::Scalar, y_out: &mut C::Scalar);
}
/// A trait representing a public key associated with a specific elliptic curve.
/// Trait for ECC public keys associated with a specific curve.
///
/// Public keys represent points on elliptic curves and are used for signature verification.
/// This trait provides coordinate access and validation methods to ensure keys represent
/// valid curve points.
///
/// # Security Considerations
///
/// - Points must lie on the specified elliptic curve
/// - The identity element (point at infinity) is typically invalid for cryptographic use
/// - Always validate public keys before using them for verification
///
/// # Example
///
/// ```rust,ignore
/// use openprot_hal_blocking::ecdsa::{PublicKey, Curve, ErrorKind};
///
/// struct MyPublicKey {
/// x: [u8; 32],
/// y: [u8; 32],
/// }
///
/// impl<C: Curve> PublicKey<C> for MyPublicKey {
/// fn coordinates(&self, x_out: &mut C::Scalar, y_out: &mut C::Scalar) {
/// // Zero-allocation coordinate access
/// *x_out = self.x;
/// *y_out = self.y;
/// }
///
/// fn from_coordinates(x: C::Scalar, y: C::Scalar) -> Result<Self, ErrorKind> {
/// // Validate point is on curve during construction
/// // (validation logic would go here)
/// Ok(Self { x, y })
/// }
/// }
/// ```
pub trait PublicKey<C: Curve> {
/// Write coordinates to output buffers (zero-allocation for embedded).
///
/// This method provides zero-allocation coordinate access for embedded
/// environments. Implementations can extract coordinates directly into
/// the provided buffers without temporary allocation.
fn coordinates(&self, x_out: &mut C::Scalar, y_out: &mut C::Scalar);
/// Create a new public key from x and y coordinates with validation.
///
/// This method validates that the point (x, y) lies on the specified curve
/// and is cryptographically valid. Validation is performed during construction
/// to ensure all created public keys are valid.
///
/// # Parameters
/// - `x`: The x coordinate of the point
/// - `y`: The y coordinate of the point
///
/// # Returns
/// - `Ok(Self)`: Valid public key if the point is on the curve
/// - `Err(ErrorKind::InvalidPoint)`: If the point is not on the curve
/// - `Err(ErrorKind::WeakKey)`: If the point is the identity element
fn from_coordinates(x: C::Scalar, y: C::Scalar) -> Result<Self, ErrorKind>
where
Self: Sized;
}
/// Optional serialization support for private keys.
///
/// This trait provides serialization capabilities for private keys that support it,
/// such as software-based keys. Hardware-based keys (HSMs, secure enclaves, etc.)
/// do not need to implement this trait.
///
/// # Security Note
///
/// Implementing this trait exposes private key material as bytes. Only implement
/// this for software keys where serialization is appropriate and secure.
///
/// # Example
///
/// ```rust,ignore
/// use openprot_hal_blocking::ecdsa::{PrivateKey, SerializablePrivateKey, Curve};
/// use zerocopy::{IntoBytes, FromBytes};
///
/// #[derive(IntoBytes, FromBytes)]
/// struct SoftwarePrivateKey([u8; 32]);
///
/// impl<C: Curve> PrivateKey<C> for SoftwarePrivateKey { /* ... */ }
/// impl<C: Curve> SerializablePrivateKey<C> for SoftwarePrivateKey {}
/// ```
pub trait SerializablePrivateKey<C: Curve>: PrivateKey<C> + IntoBytes + FromBytes {}
/// Optional serialization support for public keys.
///
/// This trait provides serialization capabilities for public keys that support it.
/// Most public key implementations should implement this since public keys are
/// not sensitive and often need to be transmitted or stored.
///
/// # Example
///
/// ```rust,ignore
/// use openprot_hal_blocking::ecdsa::{PublicKey, SerializablePublicKey, Curve};
/// use zerocopy::{IntoBytes, FromBytes};
///
/// #[derive(IntoBytes, FromBytes)]
/// struct MyPublicKey { /* ... */ }
///
/// impl<C: Curve> PublicKey<C> for MyPublicKey { /* ... */ }
/// impl<C: Curve> SerializablePublicKey<C> for MyPublicKey {}
/// ```
pub trait SerializablePublicKey<C: Curve>: PublicKey<C> + IntoBytes + FromBytes {}
/// Optional serialization support for signatures.
///
/// This trait provides serialization capabilities for signatures that support it.
/// Most signature implementations should implement this since signatures need
/// to be transmitted and verified.
///
/// # Example
///
/// ```rust,ignore
/// use openprot_hal_blocking::ecdsa::{Signature, SerializableSignature, Curve};
/// use zerocopy::{IntoBytes, FromBytes};
///
/// #[derive(IntoBytes, FromBytes)]
/// struct MySignature { /* ... */ }
///
/// impl<C: Curve> Signature<C> for MySignature { /* ... */ }
/// impl<C: Curve> SerializableSignature<C> for MySignature {}
/// ```
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. 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, generate_and_store_keypair};
/// use openprot_hal_blocking::key_vault::{KeyLifecycle, KeyStore};
/// use rand_core::{RngCore, CryptoRng};
///
/// struct MyKeyGenerator;
///
/// impl<C: Curve> EcdsaKeyGen<C> for MyKeyGenerator {
/// type PrivateKey = MyPrivateKey;
/// type PublicKey = MyPublicKey;
///
/// fn generate_keypair<R>(&mut self, rng: &mut R)
/// -> Result<(Self::PrivateKey, Self::PublicKey), Self::Error>
/// where
/// R: RngCore + CryptoRng,
/// {
/// // Generate cryptographically secure key pair
/// 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.
type PrivateKey: PrivateKey<C>;
/// The type representing the public key for the curve.
type PublicKey: PublicKey<C>;
/// Generates an ECDSA key pair.
///
/// # Parameters
/// - `rng`: A cryptographically secure random number generator.
///
/// # Returns
/// A tuple containing the generated private key and public key.
fn generate_keypair<R>(
&mut self,
rng: &mut R,
) -> Result<(Self::PrivateKey, Self::PublicKey), Self::Error>
where
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.
/// The digest should be produced by a cryptographically secure hash function
/// that matches the curve's security level.
///
/// # Security Considerations
///
/// - Use cryptographically secure random number generators for nonce generation
/// - Ensure digest length matches the curve's security level
/// - Private keys must be validated before use
///
/// # Example
///
/// ```rust,ignore
/// use openprot_hal_blocking::ecdsa::{EcdsaSign, Curve, PrivateKey};
/// use rand_core::{RngCore, CryptoRng};
///
/// struct MySigner;
///
/// impl<C: Curve> EcdsaSign<C> for MySigner {
/// type PrivateKey = MyPrivateKey;
/// type Signature = MySignature;
///
/// fn sign<R>(&mut self, key: &Self::PrivateKey, digest: &[u8], rng: &mut R)
/// -> Result<Self::Signature, Self::Error>
/// where
/// R: RngCore + CryptoRng,
/// {
/// // Generate ECDSA signature
/// unimplemented!()
/// }
/// }
/// ```
pub trait EcdsaSign<C: Curve>: ErrorType {
/// The type representing the private key for the curve.
type PrivateKey: PrivateKey<C>;
/// The type representing the signature for the curve.
type Signature: Signature<C>;
/// Signs a digest produced by a compatible hash function.
///
/// # Parameters
/// - `private_key`: The private key used for signing.
/// - `digest`: The digest output from a hash function.
/// - `rng`: A cryptographically secure random number generator.
fn sign<R>(
&mut self,
private_key: &Self::PrivateKey,
digest: <<C as Curve>::DigestType as DigestAlgorithm>::Digest,
rng: &mut R,
) -> Result<Self::Signature, Self::Error>
where
R: rand_core::RngCore + rand_core::CryptoRng;
}
/// Trait for ECDSA signature verification using a digest algorithm.
///
/// This trait provides ECDSA signature verification against message digests
/// using public keys. Verification should be performed in constant time
/// where possible to prevent timing attacks.
///
/// # Security Considerations
///
/// - Always validate public keys before verification
/// - Validate signature components are within valid ranges
/// - Use constant-time comparison operations when possible
///
/// # Example
///
/// ```rust,ignore
/// use openprot_hal_blocking::ecdsa::{EcdsaVerify, Curve, PublicKey};
///
/// struct MyVerifier;
///
/// impl<C: Curve> EcdsaVerify<C> for MyVerifier {
/// type PublicKey = MyPublicKey;
/// type Signature = MySignature;
///
/// fn verify(&mut self, key: &Self::PublicKey, digest: &[u8], signature: &Self::Signature)
/// -> Result<(), Self::Error>
/// {
/// // Verify ECDSA signature
/// unimplemented!()
/// }
/// }
/// ```
pub trait EcdsaVerify<C: Curve>: ErrorType {
/// The type representing the public key for the curve.
type PublicKey: PublicKey<C>;
/// The type representing the signature for the curve.
type Signature: Signature<C>;
/// Verifies a signature against a digest.
///
/// # Parameters
/// - `public_key`: The public key used for verification.
/// - `digest`: The digest output from a hash function.
/// - `signature`: The signature to verify.
fn verify(
&mut self,
public_key: &Self::PublicKey,
digest: <<C as Curve>::DigestType as DigestAlgorithm>::Digest,
signature: &Self::Signature,
) -> Result<(), Self::Error>;
}
/// secp256k1 elliptic curve marker type.
///
/// This zero-sized type represents the secp256k1 elliptic curve, widely used in
/// Bitcoin and other cryptocurrencies. It provides ~128-bit security level.
///
/// ## Parameters
/// - **Field Size**: 256 bits
/// - **Security Level**: ~128 bits
/// - **Standard**: SEC 2
/// - **Common Uses**: Bitcoin, Ethereum, cryptocurrency applications
///
/// ## Example
/// ```rust,ignore
/// use openprot_hal_blocking::ecdsa::Secp256k1;
///
/// // Type-safe key generation for secp256k1
/// let key_gen = MyKeyGenerator;
/// let (private_key, public_key) = key_gen.generate_keypair(Secp256k1)?;
/// ```
#[derive(Clone, Copy, Debug)]
pub struct Secp256k1;
impl Curve for Secp256k1 {
type DigestType = crate::digest::Sha2_256;
type Scalar = [u8; 32];
}
/// NIST P-256 elliptic curve marker type.
///
/// This zero-sized type represents the NIST P-256 elliptic curve (secp256r1).
/// This is the most widely used elliptic curve for ECDSA, providing ~128-bit security.
///
/// ## Parameters
/// - **Field Size**: 256 bits
/// - **Security Level**: ~128 bits
/// - **Standard**: FIPS 186-4, RFC 5480
/// - **Common Uses**: TLS certificates, JWT signing, general-purpose cryptography
///
/// ## Example
/// ```rust,ignore
/// use openprot_hal_blocking::ecdsa::P256;
///
/// // Type-safe key generation for P-256
/// let key_gen = MyKeyGenerator;
/// let (private_key, public_key) = key_gen.generate_keypair(P256)?;
/// ```
#[derive(Clone, Copy, Debug)]
pub struct P256;
impl Curve for P256 {
type DigestType = crate::digest::Sha2_256;
type Scalar = [u8; 32];
}
/// NIST P-384 elliptic curve marker type.
///
/// This zero-sized type represents the NIST P-384 elliptic curve (secp384r1).
/// Provides higher security level than P-256 with ~192-bit security.
///
/// ## Parameters
/// - **Field Size**: 384 bits
/// - **Security Level**: ~192 bits
/// - **Standard**: FIPS 186-4, RFC 5480
/// - **Common Uses**: High-security applications, government systems
///
/// ## Example
/// ```rust,ignore
/// use openprot_hal_blocking::ecdsa::P384;
///
/// // Type-safe key generation for P-384
/// let key_gen = MyKeyGenerator;
/// let (private_key, public_key) = key_gen.generate_keypair(P384)?;
/// ```
#[derive(Clone, Copy, Debug)]
pub struct P384;
impl Curve for P384 {
type DigestType = crate::digest::Sha2_384;
type Scalar = [u8; 48];
}
/// A serializable public key for the P384 elliptic curve.
///
/// This implementation provides both coordinate access and serialization
/// capabilities for P384 public keys, supporting the standard 96-byte
/// uncompressed format (48 bytes each for x and y coordinates).
#[derive(Clone, Debug, IntoBytes, FromBytes, Immutable)]
#[repr(C)]
pub struct P384PublicKey {
/// X coordinate (48 bytes for P384)
x: [u8; 48],
/// Y coordinate (48 bytes for P384)
y: [u8; 48],
}
impl P384PublicKey {
/// Create a new P384 public key from raw coordinates
pub fn new(x: [u8; 48], y: [u8; 48]) -> Self {
Self { x, y }
}
}
impl PublicKey<P384> for P384PublicKey {
fn coordinates(
&self,
x_out: &mut <P384 as Curve>::Scalar,
y_out: &mut <P384 as Curve>::Scalar,
) {
// P384::Scalar is [u8; 48], so we can copy directly
*x_out = self.x;
*y_out = self.y;
}
fn from_coordinates(
x: <P384 as Curve>::Scalar,
y: <P384 as Curve>::Scalar,
) -> Result<Self, ErrorKind> {
Ok(Self::new(x, y))
}
}
impl SerializablePublicKey<P384> for P384PublicKey {}
/// A serializable signature for the P384 elliptic curve.
///
/// This implementation provides both signature validation and serialization
/// capabilities for P384 ECDSA signatures, supporting the standard 96-byte
/// format (48 bytes each for r and s components).
#[derive(Clone, Debug, IntoBytes, FromBytes, Immutable)]
#[repr(C)]
pub struct P384Signature {
/// R component (48 bytes for P384)
r: [u8; 48],
/// S component (48 bytes for P384)
s: [u8; 48],
}
impl P384Signature {
/// Create a new P384 signature from r and s components
pub fn new(r: [u8; 48], s: [u8; 48]) -> Self {
Self { r, s }
}
}
impl Signature<P384> for P384Signature {
fn from_coordinates(
r: <P384 as Curve>::Scalar,
s: <P384 as Curve>::Scalar,
) -> Result<Self, ErrorKind> {
// TODO: Add proper signature validation here
// For now, we accept any r,s values but in a real implementation
// we should validate that 1 ≤ r,s < curve_order
Ok(Self::new(r, s))
}
fn coordinates(
&self,
r_out: &mut <P384 as Curve>::Scalar,
s_out: &mut <P384 as Curve>::Scalar,
) {
// P384::Scalar is [u8; 48], so we can copy directly
*r_out = self.r;
*s_out = self.s;
}
}
impl SerializableSignature<P384> for P384Signature {}
/// NIST P-521 elliptic curve marker type.
///
/// This zero-sized type represents the NIST P-521 elliptic curve (secp521r1).
/// Provides maximum security among NIST curves with ~256-bit security.
///
/// ## Parameters
/// - **Field Size**: 521 bits
/// - **Security Level**: ~256 bits
/// - **Standard**: FIPS 186-4, RFC 5480
/// - **Common Uses**: Maximum security applications, long-term archival
///
/// ## Example
/// ```rust,ignore
/// use openprot_hal_blocking::ecdsa::P521;
///
/// // Type-safe key generation for P-521
/// let key_gen = MyKeyGenerator;
/// let (private_key, public_key) = key_gen.generate_keypair(P521)?;
/// ```
#[derive(Clone, Copy, Debug)]
pub struct P521;
impl Curve for P521 {
type DigestType = crate::digest::Sha2_512;
type Scalar = [u8; 66];
}
/// Brainpool P256r1 elliptic curve marker type.
///
/// This zero-sized type represents the Brainpool P256r1 elliptic curve.
/// Brainpool curves are alternative curves to NIST curves with potentially better properties.
///
/// ## Parameters
/// - **Field Size**: 256 bits
/// - **Security Level**: ~128 bits
/// - **Standard**: RFC 5639
/// - **Common Uses**: Alternative to NIST curves, European standards
///
/// ## Example
/// ```rust,ignore
/// use openprot_hal_blocking::ecdsa::BrainpoolP256r1;
///
/// // Type-safe key generation for Brainpool P256r1
/// let key_gen = MyKeyGenerator;
/// let (private_key, public_key) = key_gen.generate_keypair(BrainpoolP256r1)?;
/// ```
#[derive(Clone, Copy, Debug)]
pub struct BrainpoolP256r1;
impl Curve for BrainpoolP256r1 {
type DigestType = crate::digest::Sha2_256;
type Scalar = [u8; 32];
}
/// Brainpool P384r1 elliptic curve marker type.
///
/// This zero-sized type represents the Brainpool P384r1 elliptic curve.
/// Provides higher security level than P256r1 with 192-bit security.
///
/// ## Parameters
/// - **Field Size**: 384 bits
/// - **Security Level**: ~192 bits
/// - **Standard**: RFC 5639
/// - **Common Uses**: High-security applications, European standards
///
/// ## Example
/// ```rust,ignore
/// use openprot_hal_blocking::ecdsa::BrainpoolP384r1;
///
/// // Type-safe key generation for Brainpool P384r1
/// let key_gen = MyKeyGenerator;
/// let (private_key, public_key) = key_gen.generate_keypair(BrainpoolP384r1)?;
/// ```
#[derive(Clone, Copy, Debug)]
pub struct BrainpoolP384r1;
impl Curve for BrainpoolP384r1 {
type DigestType = crate::digest::Sha2_384;
type Scalar = [u8; 48];
}
/// Brainpool P512r1 elliptic curve marker type.
///
/// This zero-sized type represents the Brainpool P512r1 elliptic curve.
/// Provides maximum security among Brainpool curves with ~256-bit security.
///
/// ## Parameters
/// - **Field Size**: 512 bits
/// - **Security Level**: ~256 bits
/// - **Standard**: RFC 5639
/// - **Common Uses**: Maximum security applications, European standards
///
/// ## Example
/// ```rust,ignore
/// use openprot_hal_blocking::ecdsa::BrainpoolP512r1;
///
/// // Type-safe key generation for Brainpool P512r1
/// let key_gen = MyKeyGenerator;
/// let (private_key, public_key) = key_gen.generate_keypair(BrainpoolP512r1)?;
/// ```
#[derive(Clone, Copy, Debug)]
pub struct BrainpoolP512r1;
impl Curve for BrainpoolP512r1 {
type DigestType = crate::digest::Sha2_512;
type Scalar = [u8; 64];
}