use std::fmt;
use clap::ValueEnum;
use cosmian_kmip::{
kmip_0::kmip_types::CryptographicUsageMask,
kmip_2_1::{
kmip_attributes::Attributes,
kmip_objects::ObjectType,
kmip_operations::CreateKeyPair,
kmip_types::{
CryptographicAlgorithm, CryptographicDomainParameters, CryptographicParameters,
KeyFormatType, RecommendedCurve, VendorAttribute, VendorAttributeValue,
},
},
time_normalize,
};
use crate::{cover_crypt_utils::VENDOR_ATTR_COVER_CRYPT_ACCESS_STRUCTURE, error::UtilsError};
#[derive(ValueEnum, Debug, Clone, Copy, PartialEq, Eq)]
pub enum KemAlgorithm {
#[clap(name = "ml-kem-512")]
MlKem512,
#[clap(name = "ml-kem-768")]
MlKem768,
#[clap(name = "p256")]
P256,
#[clap(name = "curve25519")]
Curve25519,
#[clap(name = "ml-kem-512-p256")]
MlKem512P256,
#[clap(name = "ml-kem-768-p256")]
MlKem768P256,
#[clap(name = "ml-kem-512-curve25519")]
MlKem512Curve25519,
#[clap(name = "ml-kem-768-curve25519")]
MlKem768Curve25519,
#[clap(name = "cover-crypt")]
CoverCrypt,
}
impl fmt::Display for KemAlgorithm {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::MlKem512 => write!(f, "ML-KEM-512"),
Self::MlKem768 => write!(f, "ML-KEM-768"),
Self::P256 => write!(f, "P-256"),
Self::Curve25519 => write!(f, "Curve25519"),
Self::MlKem512P256 => write!(f, "ML-KEM-512/P-256"),
Self::MlKem768P256 => write!(f, "ML-KEM-768/P-256"),
Self::MlKem512Curve25519 => write!(f, "ML-KEM-512/Curve25519"),
Self::MlKem768Curve25519 => write!(f, "ML-KEM-768/Curve25519"),
Self::CoverCrypt => write!(f, "CoverCrypt"),
}
}
}
pub fn build_create_configurable_kem_keypair_request<T: IntoIterator<Item = impl AsRef<str>>>(
vendor_id: &str,
access_structure: Option<&str>,
tags: T,
kem_algorithm: KemAlgorithm,
sensitive: bool,
wrapping_key_id: Option<&String>,
) -> Result<CreateKeyPair, UtilsError> {
let (cryptographic_domain_parameters, cryptographic_parameters) = match kem_algorithm {
KemAlgorithm::MlKem512 => Ok((
None,
Some(CryptographicParameters {
cryptographic_algorithm: Some(CryptographicAlgorithm::MLKEM_512),
..Default::default()
}),
)),
KemAlgorithm::MlKem768 => Ok((
None,
Some(CryptographicParameters {
cryptographic_algorithm: Some(CryptographicAlgorithm::MLKEM_768),
..Default::default()
}),
)),
KemAlgorithm::P256 => Ok((
Some(CryptographicDomainParameters {
qlength: Some(256),
recommended_curve: Some(RecommendedCurve::P256),
}),
None,
)),
KemAlgorithm::Curve25519 => Ok((
Some(CryptographicDomainParameters {
qlength: Some(256),
recommended_curve: Some(RecommendedCurve::CURVE25519),
}),
None,
)),
KemAlgorithm::MlKem512P256 => Ok((
Some(CryptographicDomainParameters {
qlength: Some(256),
recommended_curve: Some(RecommendedCurve::P256),
}),
Some(CryptographicParameters {
cryptographic_algorithm: Some(CryptographicAlgorithm::MLKEM_512),
..Default::default()
}),
)),
KemAlgorithm::MlKem768P256 => Ok((
Some(CryptographicDomainParameters {
qlength: Some(256),
recommended_curve: Some(RecommendedCurve::P256),
}),
Some(CryptographicParameters {
cryptographic_algorithm: Some(CryptographicAlgorithm::MLKEM_768),
..Default::default()
}),
)),
KemAlgorithm::MlKem512Curve25519 => Ok((
Some(CryptographicDomainParameters {
qlength: Some(256),
recommended_curve: Some(RecommendedCurve::CURVE25519),
}),
Some(CryptographicParameters {
cryptographic_algorithm: Some(CryptographicAlgorithm::MLKEM_512),
..Default::default()
}),
)),
KemAlgorithm::MlKem768Curve25519 => Ok((
Some(CryptographicDomainParameters {
qlength: Some(256),
recommended_curve: Some(RecommendedCurve::CURVE25519),
}),
Some(CryptographicParameters {
cryptographic_algorithm: Some(CryptographicAlgorithm::MLKEM_768),
..Default::default()
}),
)),
KemAlgorithm::CoverCrypt => {
if access_structure.is_none() {
Err(UtilsError::Default(
"access structure must be given to generate a CoverCrypt key-pair".to_owned(),
))
} else {
Ok((
None,
Some(CryptographicParameters {
cryptographic_algorithm: Some(CryptographicAlgorithm::CoverCrypt),
..Default::default()
}),
))
}
}
}?;
let vendor_attributes = access_structure.map(|access_structure| {
vec![VendorAttribute {
vendor_identification: vendor_id.to_owned(),
attribute_name: VENDOR_ATTR_COVER_CRYPT_ACCESS_STRUCTURE.to_owned(),
attribute_value: VendorAttributeValue::ByteString(access_structure.as_bytes().to_vec()),
}]
});
let mut attributes = Attributes {
object_type: Some(ObjectType::PrivateKey),
cryptographic_algorithm: Some(CryptographicAlgorithm::ConfigurableKEM),
key_format_type: Some(KeyFormatType::ConfigurableKEMSecretKey),
vendor_attributes,
cryptographic_usage_mask: Some(CryptographicUsageMask::Unrestricted),
sensitive: sensitive.then_some(true),
cryptographic_domain_parameters,
cryptographic_parameters,
activation_date: Some(time_normalize().map_err(|e| UtilsError::Default(e.to_string()))?),
..Attributes::default()
};
attributes.set_tags(vendor_id, tags)?;
if let Some(wrap_key_id) = wrapping_key_id {
attributes.set_wrapping_key_id(vendor_id, wrap_key_id);
}
let request = CreateKeyPair {
common_attributes: Some(attributes),
..CreateKeyPair::default()
};
Ok(request)
}