use crate::error::{CryptoError, Result};
use crate::types::Algorithm;
#[derive(Clone)]
pub struct FipsAlgorithmValidator;
impl FipsAlgorithmValidator {
const APPROVED_ALGORITHMS: &'static [Algorithm] = &[
Algorithm::AES128GCM,
Algorithm::AES192GCM,
Algorithm::AES256GCM,
Algorithm::ECDSAP256,
Algorithm::ECDSAP384,
Algorithm::ECDSAP521,
Algorithm::RSA2048,
Algorithm::RSA3072,
Algorithm::RSA4096,
Algorithm::SHA256,
Algorithm::SHA384,
Algorithm::SHA512,
Algorithm::SHA3_256,
Algorithm::SHA3_384,
Algorithm::SHA3_512,
Algorithm::HKDF,
Algorithm::PBKDF2,
];
#[allow(dead_code)]
const NON_APPROVED_ALGORITHMS: &'static [Algorithm] = &[
Algorithm::SM2,
Algorithm::SM3,
Algorithm::SM4GCM,
Algorithm::Sm3Kdf,
Algorithm::Ed25519,
Algorithm::Argon2id,
];
pub fn is_algorithm_approved(algorithm: &Algorithm) -> bool {
Self::APPROVED_ALGORITHMS.contains(algorithm)
}
#[allow(dead_code)]
pub fn is_algorithm_non_approved(algorithm: &Algorithm) -> bool {
Self::NON_APPROVED_ALGORITHMS.contains(algorithm)
}
pub fn validate_fips_compliance(algorithm: &Algorithm) -> Result<()> {
if !Self::is_algorithm_approved(algorithm) {
return Err(CryptoError::FipsError(format!(
"算法 {:?} 不符合 FIPS 140-3 要求。批准的算法: {:?}",
algorithm,
Self::get_approved_algorithms()
)));
}
Ok(())
}
pub fn get_approved_algorithms() -> Vec<Algorithm> {
Self::APPROVED_ALGORITHMS.to_vec()
}
#[allow(dead_code)]
pub fn get_non_approved_algorithms() -> Vec<Algorithm> {
Self::NON_APPROVED_ALGORITHMS.to_vec()
}
#[allow(dead_code)]
pub fn get_all_supported_algorithms() -> Vec<Algorithm> {
let mut all_algorithms = Self::APPROVED_ALGORITHMS.to_vec();
all_algorithms.extend(Self::NON_APPROVED_ALGORITHMS);
all_algorithms
}
pub fn validate_key_size(algorithm: &Algorithm, key_size: usize) -> Result<()> {
match algorithm {
Algorithm::AES128GCM if key_size != 16 => {
return Err(CryptoError::FipsError(format!(
"AES-128 requires 16 byte key, got {}",
key_size
)));
}
Algorithm::AES192GCM if key_size != 24 => {
return Err(CryptoError::FipsError(format!(
"AES-192 requires 24 byte key, got {}",
key_size
)));
}
Algorithm::AES256GCM if key_size != 32 => {
return Err(CryptoError::FipsError(format!(
"AES-256 requires 32 byte key, got {}",
key_size
)));
}
Algorithm::RSA2048 if key_size < 256 => {
return Err(CryptoError::FipsError(format!(
"RSA-2048 requires at least 256 byte key, got {}",
key_size
)));
}
Algorithm::RSA3072 if key_size < 384 => {
return Err(CryptoError::FipsError(format!(
"RSA-3072 requires at least 384 byte key, got {}",
key_size
)));
}
Algorithm::RSA4096 if key_size < 512 => {
return Err(CryptoError::FipsError(format!(
"RSA-4096 requires at least 512 byte key, got {}",
key_size
)));
}
Algorithm::ECDSAP256 if key_size < 32 => {
return Err(CryptoError::FipsError(format!(
"ECDSA P-256 requires at least 32 byte key, got {}",
key_size
)));
}
Algorithm::ECDSAP384 if key_size < 48 => {
return Err(CryptoError::FipsError(format!(
"ECDSA P-384 requires at least 48 byte key, got {}",
key_size
)));
}
Algorithm::ECDSAP521 if key_size < 66 => {
return Err(CryptoError::FipsError(format!(
"ECDSA P-521 requires at least 66 byte key, got {}",
key_size
)));
}
_ => {} }
Ok(())
}
#[allow(dead_code)]
pub fn get_algorithm_fips_status(algorithm: &Algorithm) -> &'static str {
if Self::is_algorithm_approved(algorithm) {
"FIPS 140-3 Approved"
} else if Self::is_algorithm_non_approved(algorithm) {
"Non-FIPS Approved"
} else {
"Unknown"
}
}
#[allow(dead_code)]
pub fn validate_algorithms_fips_compliance(algorithms: &[Algorithm]) -> Result<()> {
let mut non_approved = Vec::with_capacity(algorithms.len());
for algorithm in algorithms {
if !Self::is_algorithm_approved(algorithm) {
non_approved.push(*algorithm);
}
}
if !non_approved.is_empty() {
return Err(CryptoError::FipsError(format!(
"The following algorithms are not FIPS 140-3 approved: {:?}",
non_approved
)));
}
Ok(())
}
}