Skip to main content

kipuka_hsm/
lib.rs

1//! PKCS#11 HSM abstraction with ML-DSA and ML-KEM support.
2//!
3//! This crate provides a high-level interface to PKCS#11 Hardware Security Modules (HSMs)
4//! with full support for:
5//!
6//! - **Classical algorithms**: RSA (2048/3072/4096), ECDSA (P-256/P-384/P-521)
7//! - **Post-quantum algorithms**: ML-DSA (FIPS 204), ML-KEM (FIPS 203)
8//! - **Key wrapping**: AES Key Wrap (RFC 3394), RSAES-OAEP
9//! - **NIAP CA PP compliance**: FCS_CKM.1 key generation requirements
10//!
11//! # Supported Providers
12//!
13//! - Entrust nShield
14//! - Utimaco CryptoServer
15//! - Kryoptic (software token)
16//! - Thales Luna Cloud HSM (CSP)
17//! - Thales Luna Tactical (TCT)
18//!
19//! # Post-Quantum Cryptography
20//!
21//! PQC mechanisms (ML-DSA, ML-KEM) are vendor-specific until PKCS#11 v3.2 standardization.
22//! Each provider configuration includes vendor-specific mechanism IDs via `PqcMechanismIds`.
23//!
24//! When HSM does not support PQC, the library can fall back to software implementations
25//! using `synta-certificate`.
26//!
27//! # Architecture
28//!
29//! ```text
30//! ┌─────────────────────────────────────────────────────────┐
31//! │                     Application Layer                    │
32//! │                  (kipuka EST server)                     │
33//! └─────────────────────────────────────────────────────────┘
34//!                           │
35//!                           ▼
36//! ┌─────────────────────────────────────────────────────────┐
37//! │                    kipuka-hsm crate                      │
38//! │  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐  │
39//! │  │  HsmKeyPair  │  │  HsmSigner   │  │   HsmSlot    │  │
40//! │  └──────────────┘  └──────────────┘  └──────────────┘  │
41//! │            │              │                  │           │
42//! │            └──────────────┴──────────────────┘           │
43//! │                           │                              │
44//! │                  ┌────────▼────────┐                     │
45//! │                  │ Pkcs11Context   │                     │
46//! │                  └────────┬────────┘                     │
47//! └───────────────────────────┼──────────────────────────────┘
48//!                             │
49//!                             ▼
50//! ┌─────────────────────────────────────────────────────────┐
51//! │                     cryptoki crate                       │
52//! │              (Rust PKCS#11 bindings)                     │
53//! └─────────────────────────────────────────────────────────┘
54//!                             │
55//!                             ▼
56//! ┌─────────────────────────────────────────────────────────┐
57//! │            Vendor PKCS#11 Library (.so/.dll)             │
58//! │   (Entrust, Utimaco, Kryoptic, Thales CSP/TCT)          │
59//! └─────────────────────────────────────────────────────────┘
60//!                             │
61//!                             ▼
62//! ┌─────────────────────────────────────────────────────────┐
63//! │              Hardware Security Module                    │
64//! │           (Physical HSM or software token)               │
65//! └─────────────────────────────────────────────────────────┘
66//! ```
67//!
68//! # Example Usage
69//!
70//! ```rust,no_run
71//! use kipuka_hsm::{
72//!     HsmSlot, HsmKeyPair, KeyAlgorithm, EcdsaCurve,
73//!     Pkcs11Context, sign_ecdsa,
74//!     providers::HsmProvider,
75//!     key::PqcMechanismIds,
76//! };
77//!
78//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
79//! // Initialize PKCS#11 library
80//! let provider = HsmProvider::Kryoptic;
81//! let config = provider.config();
82//! let context = Pkcs11Context::new(&config.library_path)?;
83//!
84//! // Find HSM slot
85//! let slot = HsmSlot::find_first_slot(&context)?;
86//!
87//! // Generate ECDSA P-256 key pair
88//! let pqc_mechanisms = PqcMechanismIds::default();
89//! let key = HsmKeyPair::generate(
90//!     &slot,
91//!     KeyAlgorithm::Ecdsa(EcdsaCurve::P256),
92//!     "my-signing-key",
93//!     &[0x01, 0x02, 0x03], // CKA_ID
94//!     &config,
95//!     &pqc_mechanisms,
96//! )?;
97//!
98//! // Sign a message digest
99//! let digest = [0u8; 32]; // SHA-256 digest
100//! let signature = sign_ecdsa(&key, &digest)?;
101//! # Ok(())
102//! # }
103//! ```
104//!
105//! # ML-DSA Example
106//!
107//! ```rust,no_run
108//! use kipuka_hsm::{
109//!     HsmSlot, HsmKeyPair, KeyAlgorithm, MlDsaLevel,
110//!     Pkcs11Context, sign_ml_dsa,
111//!     providers::HsmProvider,
112//!     key::PqcMechanismIds,
113//! };
114//!
115//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
116//! let provider = HsmProvider::Kryoptic;
117//! let config = provider.config();
118//! let context = Pkcs11Context::new(&config.library_path)?;
119//! let slot = HsmSlot::find_first_slot(&context)?;
120//!
121//! // Configure vendor-specific PQC mechanism IDs
122//! let pqc_mechanisms = PqcMechanismIds {
123//!     ml_dsa_keygen: Some(0x8000_0001),
124//!     ml_dsa_65: Some(0x8000_0003),
125//!     ..Default::default()
126//! };
127//!
128//! // Generate ML-DSA-65 key pair
129//! let key = HsmKeyPair::generate(
130//!     &slot,
131//!     KeyAlgorithm::MlDsa(MlDsaLevel::L3),
132//!     "ml-dsa-signing-key",
133//!     &[0x04, 0x05, 0x06],
134//!     &config,
135//!     &pqc_mechanisms,
136//! )?;
137//!
138//! // Sign a message (ML-DSA hashes internally)
139//! let message = b"Hello, post-quantum world!";
140//! let signature = sign_ml_dsa(&key, message, MlDsaLevel::L3, &pqc_mechanisms)?;
141//! # Ok(())
142//! # }
143//! ```
144
145// Core modules
146pub mod error;
147pub mod key;
148pub mod pkcs11;
149pub mod sign;
150pub mod slot;
151
152// Provider registry
153pub mod providers;
154
155// Re-exports for convenience
156pub use error::{HsmError, HsmResult};
157pub use key::{EcdsaCurve, HsmKeyPair, KeyAlgorithm, MlDsaLevel, MlKemLevel, PqcMechanismIds};
158pub use pkcs11::Pkcs11Context;
159pub use providers::HsmProvider;
160pub use sign::{
161    DefaultHsmSigner, HsmSigner, RsaHashAlgorithm, SoftwarePqcFallback, sign_ecdsa, sign_ml_dsa,
162    sign_rsa_pkcs1, sign_rsa_pss,
163};
164pub use slot::HsmSlot;
165
166/// High-level HSM context wrapping PKCS#11 initialization and provider config.
167///
168/// Used by `AppState` to hold the HSM connection for the server lifetime.
169pub struct HsmContext {
170    pub context: Pkcs11Context,
171    pub provider: HsmProvider,
172}
173
174impl HsmContext {
175    pub fn new(context: Pkcs11Context, provider: HsmProvider) -> Self {
176        Self { context, provider }
177    }
178
179    pub fn placeholder() -> Self {
180        Self {
181            context: Pkcs11Context::placeholder(),
182            provider: HsmProvider::Kryoptic,
183        }
184    }
185}
186
187#[cfg(test)]
188mod tests {
189    use super::*;
190
191    #[test]
192    fn test_module_structure() {
193        // Smoke test to ensure all modules compile and link
194        let _provider = HsmProvider::Kryoptic;
195        let _config = _provider.config();
196        assert!(!_config.library_path.is_empty());
197    }
198
199    #[test]
200    fn test_pqc_mechanism_ids() {
201        let ids = PqcMechanismIds::default();
202        assert!(ids.ml_dsa_keygen.is_some());
203        assert!(ids.ml_kem_keygen.is_some());
204    }
205
206    #[test]
207    fn test_key_algorithms() {
208        let rsa = KeyAlgorithm::Rsa(2048);
209        let ecdsa = KeyAlgorithm::Ecdsa(EcdsaCurve::P256);
210        let ml_dsa = KeyAlgorithm::MlDsa(MlDsaLevel::L3);
211        let ml_kem = KeyAlgorithm::MlKem(MlKemLevel::L3);
212
213        // Just verify they construct
214        assert!(matches!(rsa, KeyAlgorithm::Rsa(2048)));
215        assert!(matches!(ecdsa, KeyAlgorithm::Ecdsa(_)));
216        assert!(matches!(ml_dsa, KeyAlgorithm::MlDsa(_)));
217        assert!(matches!(ml_kem, KeyAlgorithm::MlKem(_)));
218    }
219}