use base64::{Engine as _, engine::general_purpose};
use clap::ValueEnum;
use cosmian_kmip::kmip_2_1::kmip_types::{CryptographicAlgorithm, RecommendedCurve};
use strum::EnumString;
use crate::error::UtilsError;
#[derive(Default, Debug, Clone, Copy, EnumString, ValueEnum)]
#[strum(serialize_all = "kebab-case")]
pub enum Curve {
#[default]
NistP256,
NistP384,
NistP521,
#[cfg(feature = "non-fips")]
X25519,
#[cfg(feature = "non-fips")]
Ed25519,
#[cfg(feature = "non-fips")]
X448,
#[cfg(feature = "non-fips")]
Ed448,
#[cfg(feature = "non-fips")]
Secp256k1,
#[cfg(feature = "non-fips")]
Secp224k1,
}
impl From<Curve> for RecommendedCurve {
fn from(curve: Curve) -> Self {
match curve {
Curve::NistP256 => Self::P256,
Curve::NistP384 => Self::P384,
Curve::NistP521 => Self::P521,
#[cfg(feature = "non-fips")]
Curve::X25519 => Self::CURVE25519,
#[cfg(feature = "non-fips")]
Curve::Ed25519 => Self::CURVEED25519,
#[cfg(feature = "non-fips")]
Curve::X448 => Self::CURVE448,
#[cfg(feature = "non-fips")]
Curve::Ed448 => Self::CURVEED448,
#[cfg(feature = "non-fips")]
Curve::Secp256k1 => Self::SECP256K1,
#[cfg(feature = "non-fips")]
Curve::Secp224k1 => Self::SECP224K1,
}
}
}
#[derive(Debug, Clone, Copy, Default, EnumString, ValueEnum)]
pub enum SymmetricAlgorithm {
#[cfg(feature = "non-fips")]
Chacha20,
#[default]
Aes,
Sha3,
Shake,
}
#[derive(Debug, Clone, Copy, Default, EnumString, ValueEnum)]
pub enum SecretDataType {
Password,
#[default]
Seed,
}
pub fn prepare_sym_key_elements(
number_of_bits: Option<usize>,
wrap_key_b64: &Option<String>,
algorithm: SymmetricAlgorithm,
) -> Result<(usize, Option<Vec<u8>>, CryptographicAlgorithm), UtilsError> {
let mut key_bytes = None;
let number_of_bits = if let Some(key_b64) = &wrap_key_b64 {
let bytes = general_purpose::STANDARD.decode(key_b64)?;
let number_of_bits = bytes.len() * 8;
key_bytes = Some(bytes);
number_of_bits
} else {
number_of_bits.unwrap_or(256)
};
let algorithm = match algorithm {
SymmetricAlgorithm::Aes => CryptographicAlgorithm::AES,
#[cfg(feature = "non-fips")]
SymmetricAlgorithm::Chacha20 => CryptographicAlgorithm::ChaCha20,
SymmetricAlgorithm::Sha3 => match number_of_bits {
224 => CryptographicAlgorithm::SHA3224,
256 => CryptographicAlgorithm::SHA3256,
384 => CryptographicAlgorithm::SHA3384,
512 => CryptographicAlgorithm::SHA3512,
_ => {
return Err(UtilsError::Default(format!(
"invalid number of bits for sha3 {number_of_bits}"
)));
}
},
SymmetricAlgorithm::Shake => match number_of_bits {
128 => CryptographicAlgorithm::SHAKE128,
256 => CryptographicAlgorithm::SHAKE256,
_ => {
return Err(UtilsError::Default(format!(
"invalid number of bits for shake {number_of_bits}"
)));
}
},
};
Ok((number_of_bits, key_bytes, algorithm))
}