use cosmian_kmip::time_normalize;
use cosmian_kms_client::{
cosmian_kmip::{
kmip_0::kmip_types::CryptographicUsageMask,
kmip_2_1::{
kmip_attributes::Attributes,
kmip_objects::ObjectType,
kmip_operations::{Register, RegisterResponse},
kmip_types::{CryptographicAlgorithm, ProtectionStorageMasks},
requests::create_symmetric_key_kmip_object,
},
},
kmip_2_1::extra::tagging::VENDOR_ID_COSMIAN,
};
use cosmian_logger::log_init;
use test_kms_server::start_default_test_kms_server;
use crate::error::result::KmsCliResult;
#[tokio::test]
async fn test_register_success_preactive() -> KmsCliResult<()> {
log_init(None);
let ctx = start_default_test_kms_server().await;
let client = ctx.get_owner_client();
let key_bytes = vec![0_u8; 32];
let attributes = Attributes {
cryptographic_algorithm: Some(CryptographicAlgorithm::AES),
cryptographic_length: Some(256),
cryptographic_usage_mask: Some(
CryptographicUsageMask::Encrypt | CryptographicUsageMask::Decrypt,
),
object_type: Some(ObjectType::SymmetricKey),
..Default::default()
};
let object = create_symmetric_key_kmip_object(VENDOR_ID_COSMIAN, &key_bytes, &attributes)?;
let register_request = Register {
object_type: ObjectType::SymmetricKey,
object,
attributes,
protection_storage_masks: None,
};
let response: RegisterResponse = client.register(register_request).await?;
assert!(!response.unique_identifier.to_string().is_empty());
Ok(())
}
#[tokio::test]
async fn test_register_success_active() -> KmsCliResult<()> {
log_init(None);
let ctx = start_default_test_kms_server().await;
let client = ctx.get_owner_client();
let key_bytes = vec![0_u8; 32];
let past_date = time_normalize()? - time::Duration::hours(1);
let attributes = Attributes {
cryptographic_algorithm: Some(CryptographicAlgorithm::AES),
cryptographic_length: Some(256),
cryptographic_usage_mask: Some(
CryptographicUsageMask::Encrypt | CryptographicUsageMask::Decrypt,
),
object_type: Some(ObjectType::SymmetricKey),
initial_date: Some(past_date),
..Default::default()
};
let object = create_symmetric_key_kmip_object(VENDOR_ID_COSMIAN, &key_bytes, &attributes)?;
let register_request = Register {
object_type: ObjectType::SymmetricKey,
object,
attributes,
protection_storage_masks: None,
};
let response: RegisterResponse = client.register(register_request).await?;
assert!(!response.unique_identifier.to_string().is_empty());
Ok(())
}
#[tokio::test]
async fn test_register_invalid_object_type() -> KmsCliResult<()> {
log_init(None);
let ctx = start_default_test_kms_server().await;
let client = ctx.get_owner_client();
let key_bytes = vec![0_u8; 32];
let attributes = Attributes {
cryptographic_algorithm: Some(CryptographicAlgorithm::AES),
cryptographic_length: Some(256),
cryptographic_usage_mask: Some(
CryptographicUsageMask::Encrypt | CryptographicUsageMask::Decrypt,
),
object_type: Some(ObjectType::SymmetricKey),
..Default::default()
};
let object = create_symmetric_key_kmip_object(VENDOR_ID_COSMIAN, &key_bytes, &attributes)?;
let register_request = Register {
object_type: ObjectType::PrivateKey, object,
attributes,
protection_storage_masks: None,
};
let result = client.register(register_request).await;
assert!(result.is_err());
let err = result.unwrap_err();
let err_msg = err.to_string();
assert!(
err_msg.contains("object type") || err_msg.contains("Inconsistent"),
"Expected 'Invalid Object Type' error, got: {err_msg}"
);
Ok(())
}
#[tokio::test]
async fn test_register_feature_not_supported() -> KmsCliResult<()> {
log_init(None);
let ctx = start_default_test_kms_server().await;
let client = ctx.get_owner_client();
let key_bytes = vec![0_u8; 32];
let attributes = Attributes {
cryptographic_algorithm: Some(CryptographicAlgorithm::AES),
cryptographic_length: Some(256),
cryptographic_usage_mask: Some(
CryptographicUsageMask::Encrypt | CryptographicUsageMask::Decrypt,
),
object_type: Some(ObjectType::SymmetricKey),
..Default::default()
};
let object = create_symmetric_key_kmip_object(VENDOR_ID_COSMIAN, &key_bytes, &attributes)?;
let register_request = Register {
object_type: ObjectType::SymmetricKey,
object,
attributes,
protection_storage_masks: Some(ProtectionStorageMasks::Software),
};
let result = client.register(register_request).await;
assert!(result.is_err());
let err = result.unwrap_err();
let err_msg = err.to_string();
assert!(
err_msg.contains("not yet support")
|| err_msg.contains("placeholder")
|| err_msg.contains("Feature"),
"Expected 'Feature Not Supported' error, got: {err_msg}"
);
Ok(())
}
#[tokio::test]
async fn test_register_invalid_attribute() -> KmsCliResult<()> {
log_init(None);
let ctx = start_default_test_kms_server().await;
let client = ctx.get_owner_client();
let invalid_key_bytes = vec![0_u8; 15];
let attributes = Attributes {
cryptographic_algorithm: Some(CryptographicAlgorithm::AES),
cryptographic_length: Some(120), cryptographic_usage_mask: Some(
CryptographicUsageMask::Encrypt | CryptographicUsageMask::Decrypt,
),
object_type: Some(ObjectType::SymmetricKey),
..Default::default()
};
let object_result =
create_symmetric_key_kmip_object(VENDOR_ID_COSMIAN, &invalid_key_bytes, &attributes);
if let Ok(object) = object_result {
let register_request = Register {
object_type: ObjectType::SymmetricKey,
object,
attributes,
protection_storage_masks: None,
};
let result = client.register(register_request).await;
if let Err(err) = result {
let err_msg = err.to_string();
assert!(
err_msg.contains("Invalid")
|| err_msg.contains("invalid")
|| err_msg.contains("size"),
"Expected 'Invalid Attribute' error, got: {err_msg}"
);
}
}
Ok(())
}
#[tokio::test]
async fn test_register_state_determination() -> KmsCliResult<()> {
log_init(None);
let ctx = start_default_test_kms_server().await;
let client = ctx.get_owner_client();
let key_bytes1 = vec![0_u8; 32];
let attributes1 = Attributes {
cryptographic_algorithm: Some(CryptographicAlgorithm::AES),
cryptographic_length: Some(256),
cryptographic_usage_mask: Some(
CryptographicUsageMask::Encrypt | CryptographicUsageMask::Decrypt,
),
object_type: Some(ObjectType::SymmetricKey),
..Default::default()
};
let object1 = create_symmetric_key_kmip_object(VENDOR_ID_COSMIAN, &key_bytes1, &attributes1)?;
let register_request1 = Register {
object_type: ObjectType::SymmetricKey,
object: object1,
attributes: attributes1,
protection_storage_masks: None,
};
let response1: RegisterResponse = client.register(register_request1).await?;
let key_id1 = response1.unique_identifier.to_string();
assert!(!key_id1.is_empty());
let key_bytes2 = vec![0_u8; 32];
let past_date = time_normalize()? - time::Duration::hours(1);
let attributes2 = Attributes {
cryptographic_algorithm: Some(CryptographicAlgorithm::AES),
cryptographic_length: Some(256),
cryptographic_usage_mask: Some(
CryptographicUsageMask::Encrypt | CryptographicUsageMask::Decrypt,
),
object_type: Some(ObjectType::SymmetricKey),
initial_date: Some(past_date),
..Default::default()
};
let object2 = create_symmetric_key_kmip_object(VENDOR_ID_COSMIAN, &key_bytes2, &attributes2)?;
let register_request2 = Register {
object_type: ObjectType::SymmetricKey,
object: object2,
attributes: attributes2,
protection_storage_masks: None,
};
let response2: RegisterResponse = client.register(register_request2).await?;
let key_id2 = response2.unique_identifier.to_string();
assert!(!key_id2.is_empty());
Ok(())
}