use super::{Key, KeyLifecycleManager, KeyManagerLifecycleExt, KeyManagerOperations, KeyState};
use crate::audit::AuditLogger;
use crate::error::{CryptoError, Result};
use crate::fips::{is_fips_enabled, validator::FipsAlgorithmValidator, FipsContext};
use crate::random::SecureRandom;
use crate::types::Algorithm;
use chrono::{DateTime, Utc};
use std::collections::HashMap;
use std::sync::{Arc, RwLock};
use crate::key::openssl_rsa::{convert_rsa_der_to_pkcs8, generate_openssl_rsa_private_key};
use ring::rand::SystemRandom;
use ring::signature::{EcdsaKeyPair, Ed25519KeyPair};
pub struct KeyManager {
keys: Arc<RwLock<HashMap<String, Key>>>,
key_aliases: Arc<RwLock<HashMap<String, String>>>, lifecycle_manager: Option<Arc<KeyLifecycleManager>>,
rng: SecureRandom,
fips_context: Option<Arc<FipsContext>>,
}
impl KeyManager {
pub fn new() -> Result<Self> {
Ok(Self {
keys: Arc::new(RwLock::new(HashMap::new())),
key_aliases: Arc::new(RwLock::new(HashMap::new())),
lifecycle_manager: None,
rng: SecureRandom::new()?,
fips_context: None,
})
}
pub fn enable_lifecycle_management(&mut self, lifecycle_manager: Arc<KeyLifecycleManager>) {
self.lifecycle_manager = Some(lifecycle_manager);
}
pub fn set_fips_context(&mut self, fips_context: Arc<FipsContext>) {
self.fips_context = Some(fips_context);
}
fn generate_signature_key(&self, algorithm: Algorithm) -> Result<Vec<u8>> {
match algorithm {
Algorithm::Ed25519 => {
let rng = SystemRandom::new();
let pkcs8_bytes = Ed25519KeyPair::generate_pkcs8(&rng).map_err(|e| {
CryptoError::KeyError(format!("Failed to generate Ed25519 PKCS#8 key: {}", e))
})?;
Ok(pkcs8_bytes.as_ref().to_vec())
}
Algorithm::ECDSAP256 | Algorithm::ECDSAP384 => {
let rng = SystemRandom::new();
let signing_alg = match algorithm {
Algorithm::ECDSAP256 => &ring::signature::ECDSA_P256_SHA256_FIXED_SIGNING,
Algorithm::ECDSAP384 => &ring::signature::ECDSA_P384_SHA384_FIXED_SIGNING,
_ => {
return Err(CryptoError::UnsupportedAlgorithm(format!(
"Unsupported ECDSA algorithm: {:?}",
algorithm
)))
}
};
let pkcs8_bytes = EcdsaKeyPair::generate_pkcs8(signing_alg, &rng).map_err(|e| {
CryptoError::KeyError(format!("Failed to generate ECDSA PKCS#8 key: {}", e))
})?;
Ok(pkcs8_bytes.as_ref().to_vec())
}
Algorithm::RSA2048 | Algorithm::RSA3072 | Algorithm::RSA4096 => {
let key_size = match algorithm {
Algorithm::RSA2048 => 2048,
Algorithm::RSA3072 => 3072,
Algorithm::RSA4096 => 4096,
_ => 2048,
};
let der_bytes = generate_openssl_rsa_private_key(key_size)?;
let pkcs8_bytes = convert_rsa_der_to_pkcs8(&der_bytes)?;
Ok(pkcs8_bytes)
}
_ => {
let size = algorithm.key_size();
let mut key_data = vec![0u8; size];
self.rng.fill(&mut key_data)?;
Ok(key_data)
}
}
}
pub fn generate_key(&self, algorithm: Algorithm) -> Result<String> {
if is_fips_enabled() {
FipsAlgorithmValidator::validate_fips_compliance(&algorithm)?;
}
let key_data = self.generate_signature_key(algorithm)?;
let mut key = Key::new(algorithm, key_data)?;
key.activate(None)?;
let id = key.id().to_string();
AuditLogger::log("KEY_GENERATE", Some(algorithm), Some(&id), Ok(()));
{
let mut store = self
.keys
.write()
.map_err(|_| CryptoError::MemoryProtectionFailed("Lock poisoned".into()))?;
store.insert(id.clone(), key);
}
Ok(id)
}
pub fn generate_key_with_alias(&self, algorithm: Algorithm, alias: &str) -> Result<String> {
let key_id = self.generate_key(algorithm)?;
let mut aliases = self
.key_aliases
.write()
.map_err(|_| CryptoError::MemoryProtectionFailed("Lock poisoned".into()))?;
aliases.insert(alias.to_string(), key_id.clone());
Ok(key_id)
}
pub fn generate_key_with_id(&self, algorithm: Algorithm, key_id: &str) -> Result<String> {
self.generate_key_with_id_internal(algorithm, key_id)
}
fn generate_key_with_id_internal(&self, algorithm: Algorithm, key_id: &str) -> Result<String> {
let key_data = self.generate_signature_key(algorithm)?;
let mut key = Key::new_with_id(algorithm, key_data, key_id)?;
key.activate(None)?;
{
let mut store = self
.keys
.write()
.map_err(|_| CryptoError::MemoryProtectionFailed("Lock poisoned".into()))?;
store.insert(key_id.to_string(), key);
}
Ok(key_id.to_string())
}
pub fn resolve_alias(&self, alias: &str) -> Result<String> {
let aliases = self
.key_aliases
.read()
.map_err(|_| CryptoError::MemoryProtectionFailed("Lock poisoned".into()))?;
aliases
.get(alias)
.cloned()
.ok_or_else(|| CryptoError::KeyNotFound(alias.to_string()))
}
pub fn get_key(&self, id_or_alias: &str) -> Result<Key> {
let key_id = self
.resolve_alias(id_or_alias)
.unwrap_or_else(|_| id_or_alias.to_string());
let store = self
.keys
.read()
.map_err(|_| CryptoError::MemoryProtectionFailed("Lock poisoned".into()))?;
let key = store
.get(&key_id)
.ok_or_else(|| CryptoError::KeyNotFound(key_id.clone()))?;
if key.state() == KeyState::Destroyed {
return Err(CryptoError::KeyNotFound("Key is destroyed".into()));
}
Ok(key.clone())
}
pub(crate) fn with_key<F, T>(&self, id_or_alias: &str, f: F) -> Result<T>
where
F: FnOnce(&Key) -> Result<T>,
{
let key_id = self
.resolve_alias(id_or_alias)
.unwrap_or_else(|_| id_or_alias.to_string());
let store = self
.keys
.read()
.map_err(|_| CryptoError::MemoryProtectionFailed("Lock poisoned".into()))?;
let key = store
.get(&key_id)
.ok_or_else(|| CryptoError::KeyNotFound("Key not found".into()))?;
if key.state() == KeyState::Destroyed {
return Err(CryptoError::KeyNotFound("Key is destroyed".into()));
}
f(key)
}
fn with_key_mut<F, T>(&self, id_or_alias: &str, f: F) -> Result<T>
where
F: FnOnce(&mut Key) -> Result<T>,
{
let key_id = self
.resolve_alias(id_or_alias)
.unwrap_or_else(|_| id_or_alias.to_string());
let mut store = self
.keys
.write()
.map_err(|_| CryptoError::MemoryProtectionFailed("Lock poisoned".into()))?;
let key = store
.get_mut(&key_id)
.ok_or_else(|| CryptoError::KeyNotFound("Key not found".into()))?;
if key.state() == KeyState::Destroyed {
return Err(CryptoError::KeyNotFound("Key is destroyed".into()));
}
f(key)
}
pub fn activate_key(&self, id_or_alias: &str) -> Result<()> {
self.with_key_mut(id_or_alias, |key| key.activate(None))
}
pub fn suspend_key(&self, id_or_alias: &str) -> Result<()> {
self.with_key_mut(id_or_alias, |key| key.suspend())
}
pub fn resume_key(&self, id_or_alias: &str) -> Result<()> {
self.with_key_mut(id_or_alias, |key| key.resume())
}
pub fn set_key_expiration(&self, id_or_alias: &str, expires_at: DateTime<Utc>) -> Result<()> {
self.with_key_mut(id_or_alias, |key| {
key.set_expires_at(expires_at);
Ok(())
})
}
pub fn destroy_key(&self, id_or_alias: &str) -> Result<()> {
let key_id = self
.resolve_alias(id_or_alias)
.unwrap_or_else(|_| id_or_alias.to_string());
let mut store = self
.keys
.write()
.map_err(|_| CryptoError::MemoryProtectionFailed("Lock poisoned".into()))?;
if let Some(mut key) = store.remove(&key_id) {
key.destroy()?;
let mut aliases = self
.key_aliases
.write()
.map_err(|_| CryptoError::MemoryProtectionFailed("Lock poisoned".into()))?;
aliases.retain(|_, v| v != &key_id);
Ok(())
} else {
Err(CryptoError::KeyNotFound(key_id))
}
}
pub fn get_key_status(&self, id_or_alias: &str) -> Result<String> {
let key_id = self
.resolve_alias(id_or_alias)
.unwrap_or_else(|_| id_or_alias.to_string());
let store = self
.keys
.read()
.map_err(|_| CryptoError::MemoryProtectionFailed("Lock poisoned".into()))?;
let key = store
.get(&key_id)
.ok_or_else(|| CryptoError::KeyNotFound(key_id.clone()))?;
Ok(key.get_lifecycle_status())
}
pub fn list_keys(&self) -> Result<Vec<String>> {
let store = self
.keys
.read()
.map_err(|_| CryptoError::MemoryProtectionFailed("Lock poisoned".into()))?;
Ok(store.keys().cloned().collect())
}
pub fn list_aliases(&self) -> Result<Vec<String>> {
let aliases = self
.key_aliases
.read()
.map_err(|_| CryptoError::MemoryProtectionFailed("Lock poisoned".into()))?;
Ok(aliases.keys().cloned().collect())
}
pub fn get_key_stats(&self) -> Result<HashMap<String, String>> {
let store = self
.keys
.read()
.map_err(|_| CryptoError::MemoryProtectionFailed("Lock poisoned".into()))?;
let mut stats = HashMap::new();
let total_keys = store.len();
let active_keys = store
.values()
.filter(|k| k.state() == KeyState::Active)
.count();
let suspended_keys = store
.values()
.filter(|k| k.state() == KeyState::Suspended)
.count();
let destroyed_keys = store
.values()
.filter(|k| k.state() == KeyState::Destroyed)
.count();
stats.insert("total_keys".to_string(), total_keys.to_string());
stats.insert("active_keys".to_string(), active_keys.to_string());
stats.insert("suspended_keys".to_string(), suspended_keys.to_string());
stats.insert("destroyed_keys".to_string(), destroyed_keys.to_string());
Ok(stats)
}
pub fn set_key_max_usage(&self, id_or_alias: &str, max_usage: Option<usize>) -> Result<()> {
let key_id = self
.resolve_alias(id_or_alias)
.unwrap_or_else(|_| id_or_alias.to_string());
let mut store = self
.keys
.write()
.map_err(|_| CryptoError::MemoryProtectionFailed("Lock poisoned".into()))?;
let key = store
.get_mut(&key_id)
.ok_or_else(|| CryptoError::KeyNotFound(key_id.clone()))?;
key.set_max_usage(max_usage);
Ok(())
}
}
impl KeyManagerLifecycleExt for KeyManager {
fn generate_key_with_lifecycle(
&self,
algorithm: Algorithm,
lifecycle_manager: &KeyLifecycleManager,
) -> Result<String> {
lifecycle_manager.create_key_version(self, algorithm)
}
fn rotate_key(
&self,
key_id: &str,
algorithm: Algorithm,
lifecycle_manager: &KeyLifecycleManager,
) -> Result<String> {
lifecycle_manager.rotate_key(self, key_id, algorithm)
}
fn get_key_lifecycle_status(
&self,
key_id: &str,
lifecycle_manager: &KeyLifecycleManager,
) -> Result<String> {
lifecycle_manager
.get_rotation_warning(key_id)
.map(|warning| warning.unwrap_or_else(|| "No rotation warning".to_string()))
}
}
impl KeyManagerOperations for KeyManager {
fn generate_key_operation(&self, algorithm: Algorithm) -> Result<String> {
self.generate_key(algorithm)
}
fn get_key_operation(&self, key_id: &str) -> Result<Key> {
self.get_key(key_id)
}
fn destroy_key_operation(&self, key_id: &str) -> Result<()> {
self.destroy_key(key_id)
}
fn list_keys_operation(&self) -> Result<Vec<String>> {
self.list_keys()
}
}
#[allow(dead_code)]
pub struct TenantKeyManager {
tenant_id: String,
key_manager: KeyManager,
}
#[allow(dead_code)]
impl TenantKeyManager {
#[allow(dead_code)]
pub fn new(tenant_id: &str) -> Result<Self> {
Ok(Self {
tenant_id: tenant_id.to_string(),
key_manager: KeyManager::new()?,
})
}
pub fn tenant_id(&self) -> &str {
&self.tenant_id
}
fn normalize_key_id(&self, key_id: &str, operation: &str) -> Result<String> {
if key_id.contains(':') {
let parts: Vec<&str> = key_id.split(':').collect();
if parts[0] != self.tenant_id {
AuditLogger::log_unauthorized_access(
operation,
None,
Some(key_id),
Some(&self.tenant_id),
&format!(
"Tenant {} attempted to access key from tenant {}",
self.tenant_id, parts[0]
),
);
return Err(crate::error::CryptoError::KeyNotFound(
"Key not found in tenant".into(),
));
}
Ok(key_id.to_string())
} else {
Ok(format!("{}:{}", self.tenant_id, key_id))
}
}
pub fn generate_key(&self, algorithm: Algorithm) -> Result<String> {
let tenant_key_id = format!("{}:{}", self.tenant_id, uuid::Uuid::new_v4());
AuditLogger::log_with_tenant(
"KEY_GENERATE",
Some(algorithm),
Some(&tenant_key_id),
Some(&self.tenant_id),
Ok(()),
"authorized",
);
let size = algorithm.key_size();
let mut key_data = vec![0u8; size];
self.key_manager.rng.fill(&mut key_data)?;
let mut key = super::Key::new_with_id(algorithm, key_data, &tenant_key_id)?;
key.activate(Some(&self.tenant_id))?;
{
let mut store = self
.key_manager
.keys
.write()
.map_err(|_| CryptoError::MemoryProtectionFailed("Lock poisoned".into()))?;
store.insert(tenant_key_id.to_string(), key);
}
Ok(tenant_key_id.to_string())
}
pub fn generate_key_with_alias(&self, algorithm: Algorithm, alias: &str) -> Result<String> {
let key_id = self.generate_key(algorithm)?;
let tenant_alias = format!("{}:{}", self.tenant_id, alias);
let mut aliases = self
.key_manager
.key_aliases
.write()
.map_err(|_| CryptoError::MemoryProtectionFailed("Lock poisoned".into()))?;
aliases.insert(tenant_alias, key_id.clone());
Ok(key_id)
}
pub fn get_key(&self, key_id: &str) -> Result<super::Key> {
let tenant_key_id = self.normalize_key_id(key_id, "KEY_ACCESS")?;
let result = self.key_manager.get_key(&tenant_key_id);
match &result {
Ok(_) => {
AuditLogger::log_with_tenant(
"KEY_ACCESS",
None,
Some(key_id),
Some(&self.tenant_id),
Ok(()),
"authorized",
);
}
Err(e) => {
AuditLogger::log_with_tenant(
"KEY_ACCESS",
None,
Some(key_id),
Some(&self.tenant_id),
Err(CryptoError::KeyError(e.to_string())),
"authorized",
);
}
}
result
}
pub fn list_keys(&self) -> Result<Vec<String>> {
let all_keys = self.key_manager.list_keys()?;
let prefix = format!("{}:", self.tenant_id);
let tenant_keys: Vec<String> = all_keys
.into_iter()
.filter(|key_id| key_id.starts_with(&prefix))
.map(|key_id| key_id.strip_prefix(&prefix).unwrap_or(&key_id).to_string())
.collect();
AuditLogger::log_with_tenant(
"KEY_LIST",
None,
None,
Some(&self.tenant_id),
Ok(()),
"authorized",
);
Ok(tenant_keys)
}
pub fn activate_key(&self, key_id: &str) -> Result<()> {
let tenant_key_id = self.normalize_key_id(key_id, "KEY_ACTIVATE")?;
let result = self.key_manager.activate_key(&tenant_key_id);
match &result {
Ok(_) => {
AuditLogger::log_with_tenant(
"KEY_ACTIVATE",
None,
Some(key_id),
Some(&self.tenant_id),
Ok(()),
"authorized",
);
}
Err(e) => {
AuditLogger::log_with_tenant(
"KEY_ACTIVATE",
None,
Some(key_id),
Some(&self.tenant_id),
Err(CryptoError::KeyError(e.to_string())),
"authorized",
);
}
}
result
}
pub fn suspend_key(&self, key_id: &str) -> Result<()> {
let tenant_key_id = self.normalize_key_id(key_id, "KEY_SUSPEND")?;
let result = self.key_manager.suspend_key(&tenant_key_id);
match &result {
Ok(_) => {
AuditLogger::log_with_tenant(
"KEY_SUSPEND",
None,
Some(key_id),
Some(&self.tenant_id),
Ok(()),
"authorized",
);
}
Err(e) => {
AuditLogger::log_with_tenant(
"KEY_SUSPEND",
None,
Some(key_id),
Some(&self.tenant_id),
Err(CryptoError::KeyError(e.to_string())),
"authorized",
);
}
}
result
}
pub fn destroy_key(&self, key_id: &str) -> Result<()> {
let tenant_key_id = self.normalize_key_id(key_id, "KEY_DESTROY")?;
let result = self.key_manager.destroy_key(&tenant_key_id);
match &result {
Ok(_) => {
AuditLogger::log_with_tenant(
"KEY_DESTROY",
None,
Some(key_id),
Some(&self.tenant_id),
Ok(()),
"authorized",
);
}
Err(e) => {
AuditLogger::log_with_tenant(
"KEY_DESTROY",
None,
Some(key_id),
Some(&self.tenant_id),
Err(CryptoError::KeyError(e.to_string())),
"authorized",
);
}
}
result
}
pub fn set_key_max_usage(&self, key_id: &str, max_usage: Option<usize>) -> Result<()> {
let tenant_key_id = self.normalize_key_id(key_id, "KEY_MAX_USAGE_SET")?;
let result = self
.key_manager
.set_key_max_usage(&tenant_key_id, max_usage);
match &result {
Ok(_) => {
AuditLogger::log_with_tenant(
"KEY_MAX_USAGE_SET",
None,
Some(key_id),
Some(&self.tenant_id),
Ok(()),
"authorized",
);
}
Err(e) => {
AuditLogger::log_with_tenant(
"KEY_MAX_USAGE_SET",
None,
Some(key_id),
Some(&self.tenant_id),
Err(CryptoError::KeyError(e.to_string())),
"authorized",
);
}
}
result
}
}
impl KeyManagerOperations for TenantKeyManager {
fn generate_key_operation(&self, algorithm: Algorithm) -> Result<String> {
self.generate_key(algorithm)
}
fn get_key_operation(&self, key_id: &str) -> Result<Key> {
self.get_key(key_id)
}
fn destroy_key_operation(&self, key_id: &str) -> Result<()> {
self.destroy_key(key_id)
}
fn list_keys_operation(&self) -> Result<Vec<String>> {
self.list_keys()
}
}