Skip to main content

kipuka_hsm/providers/
thales_tct.rs

1//! Thales Luna Tactical (TCT) HSM provider.
2//!
3//! The Luna TCT (Tactical) is a ruggedized, battery-backed HSM designed for
4//! mobile, field, and disconnected environments with tamper-responsive security.
5//!
6//! # Platform-specific Library Paths
7//!
8//! Luna TCT uses the same PKCS#11 library as Luna CSP:
9//! - Linux: `/usr/safenet/lunaclient/lib/libCryptoki2_64.so`
10//! - Windows: `C:\Program Files\SafeNet\LunaClient\cryptoki.dll`
11//!
12//! # Tactical/Ruggedized Features
13//!
14//! - **Battery-backed RAM**: Keys persist through power loss
15//! - **Tamper detection**: Physical intrusion triggers key zeroization
16//! - **Environmental hardening**: Extended temperature, shock, vibration tolerance
17//! - **Portable form factor**: Designed for field deployment
18//!
19//! # Disconnected/Air-Gapped Environments
20//!
21//! Luna TCT is specifically designed for disconnected EST use cases per
22//! RHELBU-3536 R7-Disconnected:
23//!
24//! - **No network dependency**: All cryptographic operations local to HSM
25//! - **Offline key generation**: CA and EST server keys generated on-device
26//! - **Manual key transport**: Physical custody for key backup/recovery
27//! - **Audit trail**: Local logging of all key operations
28//!
29//! For disconnected deployments:
30//! 1. Generate CA and EST server keys on TCT in secure facility
31//! 2. Configure EST server with PKCS#11 URI pointing to TCT keys
32//! 3. Deploy TCT with EST server to disconnected environment
33//! 4. All certificate issuance happens locally without network connectivity
34//!
35//! # Storage Constraints
36//!
37//! Luna TCT has more conservative limits than cloud HSMs:
38//! - Limited slot count (typically 1-4 partitions)
39//! - Smaller key storage capacity (hundreds vs thousands of keys)
40//! - Battery lifetime considerations for long-term deployments
41//!
42//! # Mechanism Support
43//!
44//! Luna TCT provides the same cryptographic mechanisms as Luna CSP:
45//! - Full RSA and ECDSA support
46//! - AES Key Wrap (CKM_AES_KEY_WRAP, CKM_AES_KEY_WRAP_PAD)
47//! - RSAES-OAEP for key wrapping
48
49use crate::HsmProvider;
50use crate::providers::HsmProviderConfig;
51use cryptoki::mechanism::MechanismType;
52
53/// Default PKCS#11 library path for Luna TCT.
54///
55/// Same library as Luna CSP; behavior differs based on connected HSM model.
56pub fn default_library_path() -> &'static str {
57    #[cfg(target_os = "linux")]
58    return "/usr/safenet/lunaclient/lib/libCryptoki2_64.so";
59
60    #[cfg(target_os = "windows")]
61    return "C:\\Program Files\\SafeNet\\LunaClient\\cryptoki.dll";
62
63    #[cfg(not(any(target_os = "linux", target_os = "windows")))]
64    return "/usr/safenet/lunaclient/lib/libCryptoki2_64.so";
65}
66
67/// Mechanisms supported by Luna TCT.
68///
69/// Same mechanism set as Luna CSP.
70pub fn supported_mechanisms() -> Vec<MechanismType> {
71    vec![
72        // RSA
73        MechanismType::RSA_PKCS,
74        MechanismType::RSA_PKCS_KEY_PAIR_GEN,
75        MechanismType::SHA256_RSA_PKCS,
76        MechanismType::SHA384_RSA_PKCS,
77        MechanismType::SHA512_RSA_PKCS,
78        MechanismType::RSA_PKCS_PSS,
79        MechanismType::SHA256_RSA_PKCS_PSS,
80        MechanismType::SHA384_RSA_PKCS_PSS,
81        MechanismType::SHA512_RSA_PKCS_PSS,
82        MechanismType::RSA_PKCS_OAEP,
83        // ECDSA
84        MechanismType::ECDSA,
85        MechanismType::ECDSA_SHA256,
86        MechanismType::ECDSA_SHA384,
87        MechanismType::ECDSA_SHA512,
88        MechanismType::ECC_KEY_PAIR_GEN,
89        // AES
90        MechanismType::AES_KEY_GEN,
91        MechanismType::AES_ECB,
92        MechanismType::AES_CBC,
93        MechanismType::AES_GCM,
94        MechanismType::AES_KEY_WRAP,
95        MechanismType::AES_KEY_WRAP_PAD,
96        // Hashing
97        MechanismType::SHA256,
98        MechanismType::SHA384,
99        MechanismType::SHA512,
100    ]
101}
102
103/// Get the default provider configuration for Thales Luna TCT.
104pub fn provider_config() -> HsmProviderConfig {
105    HsmProviderConfig {
106        provider: HsmProvider::ThalesTct,
107        library_path: default_library_path().to_string(),
108        supported_mechanisms: supported_mechanisms(),
109        notes: vec![
110            "Ruggedized, battery-backed HSM for tactical/field deployment".to_string(),
111            "Tamper-responsive with physical intrusion detection".to_string(),
112            "Designed for disconnected/air-gapped environments (RHELBU-3536 R7-Disconnected)"
113                .to_string(),
114            "Limited slot count and key storage vs cloud HSMs".to_string(),
115            "Same PKCS#11 mechanisms as Luna CSP".to_string(),
116            "CKM_AES_KEY_WRAP and CKM_AES_KEY_WRAP_PAD fully supported".to_string(),
117            "RSAES-OAEP fully supported".to_string(),
118            "Offline key generation and certificate issuance without network dependency"
119                .to_string(),
120            "Manual key transport via physical custody for backup/recovery".to_string(),
121        ],
122    }
123}
124
125#[cfg(test)]
126mod tests {
127    use super::*;
128
129    #[test]
130    fn test_library_path_not_empty() {
131        assert!(!default_library_path().is_empty());
132    }
133
134    #[test]
135    fn test_mechanisms_same_as_csp() {
136        // TCT and CSP use same PKCS#11 library and mechanism set
137        let mechanisms = supported_mechanisms();
138        assert!(mechanisms.contains(&MechanismType::RSA_PKCS));
139        assert!(mechanisms.contains(&MechanismType::ECDSA));
140        assert!(mechanisms.contains(&MechanismType::AES_KEY_WRAP));
141    }
142
143    #[test]
144    fn test_config_has_tactical_notes() {
145        let config = provider_config();
146        assert!(
147            config
148                .notes
149                .iter()
150                .any(|n| n.contains("tactical") || n.contains("Tactical"))
151        );
152        assert!(
153            config
154                .notes
155                .iter()
156                .any(|n| n.contains("disconnected") || n.contains("air-gapped"))
157        );
158        assert!(config.notes.iter().any(|n| n.contains("battery")));
159    }
160}