use super::{
BufferOwner, DestructionPolicy, ExportPolicy, OutputMaterial, RetentionPolicy,
SecretSensitivity, ZeroizationPolicy,
};
use crypto_core::RngOutputKind;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[non_exhaustive]
pub enum SecretMaterialOperation {
AeadSeal,
AeadOpen,
ConstantTimeCompare,
Hash,
MacAuthenticate,
MacVerify,
KeyDerivation,
KeyWrap,
KeyUnwrap,
SignatureKeyGeneration,
SignatureKeyDerivation,
SignatureSign,
SignatureVerify,
KeyAgreementKeyGeneration,
KeyAgreementKeyDerivation,
KeyAgreementSharedSecret,
KemKeyGeneration,
KemKeyDerivation,
KemEncapsulate,
KemDecapsulate,
HpkeKeyGeneration,
HpkeKeyDerivation,
HpkeSenderSetup,
HpkeReceiverSetup,
HpkeSeal,
HpkeOpen,
HpkeExport,
RandomFill,
RandomNonce,
RandomSalt,
PublicKeyEncoding,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[non_exhaustive]
pub struct MaterialPolicy {
pub owner: BufferOwner,
pub sensitivity: SecretSensitivity,
pub retention: RetentionPolicy,
pub zeroization: ZeroizationPolicy,
pub export: ExportPolicy,
pub destruction: DestructionPolicy,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[non_exhaustive]
pub struct OperationSecretMaterialPolicy {
pub input: MaterialPolicy,
pub output: MaterialPolicy,
pub request_wire: MaterialPolicy,
pub response_wire: MaterialPolicy,
pub output_material: OutputMaterial,
}
#[must_use]
pub const fn operation_secret_material_policy(
operation: SecretMaterialOperation,
) -> OperationSecretMaterialPolicy {
match operation {
SecretMaterialOperation::AeadSeal | SecretMaterialOperation::KeyWrap => {
secret_input_sensitive_output(OutputMaterial::SensitivePublic)
}
SecretMaterialOperation::AeadOpen
| SecretMaterialOperation::KeyUnwrap
| SecretMaterialOperation::KeyDerivation
| SecretMaterialOperation::KeyAgreementSharedSecret
| SecretMaterialOperation::KemDecapsulate
| SecretMaterialOperation::HpkeOpen
| SecretMaterialOperation::HpkeExport => secret_output(OutputMaterial::Secret),
SecretMaterialOperation::RandomFill => caller_owned_secret_output(),
SecretMaterialOperation::RandomNonce => public_operation(),
SecretMaterialOperation::RandomSalt => {
public_input_sensitive_output(OutputMaterial::SensitivePublic)
}
SecretMaterialOperation::SignatureKeyGeneration
| SecretMaterialOperation::KeyAgreementKeyGeneration
| SecretMaterialOperation::KemKeyGeneration
| SecretMaterialOperation::KemEncapsulate
| SecretMaterialOperation::HpkeKeyGeneration => {
public_input_secret_output(OutputMaterial::Mixed)
}
SecretMaterialOperation::SignatureKeyDerivation
| SecretMaterialOperation::KeyAgreementKeyDerivation
| SecretMaterialOperation::KemKeyDerivation
| SecretMaterialOperation::HpkeKeyDerivation => secret_output(OutputMaterial::Mixed),
SecretMaterialOperation::HpkeSenderSetup | SecretMaterialOperation::HpkeReceiverSetup => {
secret_input_non_exportable_output(OutputMaterial::Mixed)
}
SecretMaterialOperation::HpkeSeal => {
secret_input_sensitive_output(OutputMaterial::SensitivePublic)
}
SecretMaterialOperation::Hash
| SecretMaterialOperation::ConstantTimeCompare
| SecretMaterialOperation::MacAuthenticate
| SecretMaterialOperation::MacVerify
| SecretMaterialOperation::SignatureSign => {
secret_input_public_output(OutputMaterial::Public)
}
SecretMaterialOperation::SignatureVerify | SecretMaterialOperation::PublicKeyEncoding => {
public_operation()
}
}
}
#[must_use]
pub const fn random_fill_secret_material_policy(
kind: RngOutputKind,
) -> OperationSecretMaterialPolicy {
match kind {
RngOutputKind::AeadNonce12 => caller_owned_public_output(),
RngOutputKind::Argon2Salt16 | RngOutputKind::Argon2Salt32 => {
caller_owned_sensitive_output()
}
RngOutputKind::Generic
| RngOutputKind::Aes256GcmKey
| RngOutputKind::MlKem1024Seed
| RngOutputKind::MlDsa87Seed
| RngOutputKind::Ed25519Seed
| RngOutputKind::SlhDsaSha2_128sSeed => caller_owned_secret_output(),
_ => caller_owned_secret_output(),
}
}
#[inline]
pub(crate) const fn bind_operation_policy(
operation: SecretMaterialOperation,
) -> OperationSecretMaterialPolicy {
operation_secret_material_policy(operation)
}
#[inline]
#[cfg(feature = "csprng")]
pub(crate) const fn bind_random_fill_policy(kind: RngOutputKind) -> OperationSecretMaterialPolicy {
random_fill_secret_material_policy(kind)
}
const fn secret_input_public_output(
output_material: OutputMaterial,
) -> OperationSecretMaterialPolicy {
operation_policy(
borrowed_secret(),
public_result(),
secret_wire(),
public_wire(),
output_material,
)
}
const fn secret_input_sensitive_output(
output_material: OutputMaterial,
) -> OperationSecretMaterialPolicy {
operation_policy(
borrowed_secret(),
sensitive_result(),
secret_wire(),
sensitive_wire(),
output_material,
)
}
const fn secret_output(output_material: OutputMaterial) -> OperationSecretMaterialPolicy {
operation_policy(
borrowed_secret(),
owned_secret(),
secret_wire(),
secret_wire(),
output_material,
)
}
const fn secret_input_non_exportable_output(
output_material: OutputMaterial,
) -> OperationSecretMaterialPolicy {
operation_policy(
borrowed_secret(),
MaterialPolicy {
owner: BufferOwner::OperationLayer,
sensitivity: SecretSensitivity::Secret,
retention: RetentionPolicy::ResultLifetime,
zeroization: ZeroizationPolicy::OwnerZeroizesOnDrop,
export: ExportPolicy::NonExportable,
destruction: DestructionPolicy::ZeroizeOnDrop,
},
public_wire(),
public_wire(),
output_material,
)
}
const fn public_input_secret_output(
output_material: OutputMaterial,
) -> OperationSecretMaterialPolicy {
operation_policy(
borrowed_public(),
owned_secret(),
public_wire(),
secret_wire(),
output_material,
)
}
const fn public_input_sensitive_output(
output_material: OutputMaterial,
) -> OperationSecretMaterialPolicy {
operation_policy(
borrowed_public(),
sensitive_result(),
public_wire(),
sensitive_wire(),
output_material,
)
}
const fn caller_owned_secret_output() -> OperationSecretMaterialPolicy {
operation_policy(
borrowed_public(),
MaterialPolicy {
owner: BufferOwner::Caller,
sensitivity: SecretSensitivity::Secret,
retention: RetentionPolicy::ResultLifetime,
zeroization: ZeroizationPolicy::CallerRetainsResponsibility,
export: ExportPolicy::SecretOwnerRequired,
destruction: DestructionPolicy::CallerControlled,
},
public_wire(),
secret_wire(),
OutputMaterial::Secret,
)
}
const fn caller_owned_sensitive_output() -> OperationSecretMaterialPolicy {
operation_policy(
borrowed_public(),
MaterialPolicy {
owner: BufferOwner::Caller,
sensitivity: SecretSensitivity::Sensitive,
retention: RetentionPolicy::ResultLifetime,
zeroization: ZeroizationPolicy::OwnerZeroizesOnDrop,
export: ExportPolicy::Public,
destruction: DestructionPolicy::ZeroizeOnDrop,
},
public_wire(),
sensitive_wire(),
OutputMaterial::SensitivePublic,
)
}
const fn caller_owned_public_output() -> OperationSecretMaterialPolicy {
operation_policy(
borrowed_public(),
MaterialPolicy {
owner: BufferOwner::Caller,
sensitivity: SecretSensitivity::Public,
retention: RetentionPolicy::ResultLifetime,
zeroization: ZeroizationPolicy::NotRequired,
export: ExportPolicy::Public,
destruction: DestructionPolicy::NoneRequired,
},
public_wire(),
public_wire(),
OutputMaterial::Public,
)
}
const fn public_operation() -> OperationSecretMaterialPolicy {
operation_policy(
borrowed_public(),
public_result(),
public_wire(),
public_wire(),
OutputMaterial::Public,
)
}
const fn operation_policy(
input: MaterialPolicy,
output: MaterialPolicy,
request_wire: MaterialPolicy,
response_wire: MaterialPolicy,
output_material: OutputMaterial,
) -> OperationSecretMaterialPolicy {
OperationSecretMaterialPolicy {
input,
output,
request_wire,
response_wire,
output_material,
}
}
const fn borrowed_secret() -> MaterialPolicy {
MaterialPolicy {
owner: BufferOwner::Caller,
sensitivity: SecretSensitivity::Secret,
retention: RetentionPolicy::BorrowedForCall,
zeroization: ZeroizationPolicy::CallerRetainsResponsibility,
export: ExportPolicy::SecretOwnerRequired,
destruction: DestructionPolicy::CallerControlled,
}
}
const fn borrowed_public() -> MaterialPolicy {
MaterialPolicy {
owner: BufferOwner::Caller,
sensitivity: SecretSensitivity::Public,
retention: RetentionPolicy::BorrowedForCall,
zeroization: ZeroizationPolicy::NotRequired,
export: ExportPolicy::Public,
destruction: DestructionPolicy::NoneRequired,
}
}
const fn owned_secret() -> MaterialPolicy {
MaterialPolicy {
owner: BufferOwner::OperationLayer,
sensitivity: SecretSensitivity::Secret,
retention: RetentionPolicy::ResultLifetime,
zeroization: ZeroizationPolicy::OwnerZeroizesOnDrop,
export: ExportPolicy::SecretOwnerRequired,
destruction: DestructionPolicy::ZeroizeOnDrop,
}
}
const fn public_result() -> MaterialPolicy {
MaterialPolicy {
owner: BufferOwner::OperationLayer,
sensitivity: SecretSensitivity::Public,
retention: RetentionPolicy::ResultLifetime,
zeroization: ZeroizationPolicy::NotRequired,
export: ExportPolicy::Public,
destruction: DestructionPolicy::NoneRequired,
}
}
const fn sensitive_result() -> MaterialPolicy {
MaterialPolicy {
owner: BufferOwner::OperationLayer,
sensitivity: SecretSensitivity::Sensitive,
retention: RetentionPolicy::ResultLifetime,
zeroization: ZeroizationPolicy::NotRequired,
export: ExportPolicy::Public,
destruction: DestructionPolicy::NoneRequired,
}
}
const fn secret_wire() -> MaterialPolicy {
MaterialPolicy {
owner: BufferOwner::OperationContract,
sensitivity: SecretSensitivity::Secret,
retention: RetentionPolicy::OperationTemporary,
zeroization: ZeroizationPolicy::OwnerZeroizesOnDrop,
export: ExportPolicy::SecretOwnerRequired,
destruction: DestructionPolicy::ZeroizeOnDrop,
}
}
const fn public_wire() -> MaterialPolicy {
MaterialPolicy {
owner: BufferOwner::OperationContract,
sensitivity: SecretSensitivity::Public,
retention: RetentionPolicy::OperationTemporary,
zeroization: ZeroizationPolicy::NotRequired,
export: ExportPolicy::Public,
destruction: DestructionPolicy::NoneRequired,
}
}
const fn sensitive_wire() -> MaterialPolicy {
MaterialPolicy {
owner: BufferOwner::OperationContract,
sensitivity: SecretSensitivity::Sensitive,
retention: RetentionPolicy::OperationTemporary,
zeroization: ZeroizationPolicy::NotRequired,
export: ExportPolicy::Public,
destruction: DestructionPolicy::NoneRequired,
}
}