#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum UserVerificationPolicy {
Required,
#[default]
Preferred,
Discouraged,
}
impl UserVerificationPolicy {
#[must_use]
pub fn as_str(self) -> &'static str {
match self {
UserVerificationPolicy::Required => "required",
UserVerificationPolicy::Preferred => "preferred",
UserVerificationPolicy::Discouraged => "discouraged",
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum ResidentKeyPolicy {
Required,
#[default]
Preferred,
Discouraged,
}
impl ResidentKeyPolicy {
#[must_use]
pub fn as_str(self) -> &'static str {
match self {
ResidentKeyPolicy::Required => "required",
ResidentKeyPolicy::Preferred => "preferred",
ResidentKeyPolicy::Discouraged => "discouraged",
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum AttestationConveyance {
#[default]
None,
Indirect,
Direct,
Enterprise,
}
impl AttestationConveyance {
#[must_use]
pub fn as_str(self) -> &'static str {
match self {
AttestationConveyance::None => "none",
AttestationConveyance::Indirect => "indirect",
AttestationConveyance::Direct => "direct",
AttestationConveyance::Enterprise => "enterprise",
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum BackupPolicy {
#[default]
Allow,
RequireDeviceBound,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct CredentialPolicy {
pub user_verification: UserVerificationPolicy,
pub backup: BackupPolicy,
pub allowed_algorithms: Vec<i32>,
}
impl Default for CredentialPolicy {
fn default() -> Self {
Self {
user_verification: UserVerificationPolicy::Preferred,
backup: BackupPolicy::Allow,
allowed_algorithms: Vec::new(),
}
}
}
impl CredentialPolicy {
#[must_use]
pub fn strict() -> Self {
Self {
user_verification: UserVerificationPolicy::Required,
backup: BackupPolicy::RequireDeviceBound,
allowed_algorithms: vec![crate::crypto::COSE_ALG_ES256],
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn wire_strings_roundtrip() {
assert_eq!(UserVerificationPolicy::Required.as_str(), "required");
assert_eq!(UserVerificationPolicy::Preferred.as_str(), "preferred");
assert_eq!(UserVerificationPolicy::Discouraged.as_str(), "discouraged");
assert_eq!(ResidentKeyPolicy::Required.as_str(), "required");
assert_eq!(ResidentKeyPolicy::Preferred.as_str(), "preferred");
assert_eq!(ResidentKeyPolicy::Discouraged.as_str(), "discouraged");
assert_eq!(AttestationConveyance::None.as_str(), "none");
assert_eq!(AttestationConveyance::Indirect.as_str(), "indirect");
assert_eq!(AttestationConveyance::Direct.as_str(), "direct");
assert_eq!(AttestationConveyance::Enterprise.as_str(), "enterprise");
}
#[test]
fn default_policy_is_permissive() {
let policy = CredentialPolicy::default();
assert_eq!(policy.user_verification, UserVerificationPolicy::Preferred);
assert_eq!(policy.backup, BackupPolicy::Allow);
assert!(policy.allowed_algorithms.is_empty());
}
#[test]
fn strict_policy_tightens_everything() {
let policy = CredentialPolicy::strict();
assert_eq!(policy.user_verification, UserVerificationPolicy::Required);
assert_eq!(policy.backup, BackupPolicy::RequireDeviceBound);
assert_eq!(
policy.allowed_algorithms,
vec![crate::crypto::COSE_ALG_ES256]
);
}
}