use alloc::{string::String, vec::Vec};
use der::ErrorKind;
use der::asn1::Utf8StringRef;
use der::{
DecodeValue, EncodeValue, Enumerated, FixedTag, Header, Length, Reader, Sequence, Tag, Writer,
asn1::OctetString,
};
use x509_cert::attr::Attribute;
macro_rules! impl_str_enum {
(
$(#[$attr:meta])* $vis: vis enum $name: ident {
$( $(#[$attr_item: meta])* $item: ident => $value: expr,)*
}
)=> {
$(#[$attr])*
$vis enum $name {
$( $(#[$attr_item])* $item, )*
}
impl AsRef<str> for $name {
fn as_ref(&self) -> &str {
match self {
$( Self::$item => $value, )*
}
}
}
impl<'d> DecodeValue<'d> for $name {
type Error = der::Error;
fn decode_value<R: Reader<'d>>(reader: &mut R, header: Header) -> der::Result<Self> {
let value = Utf8StringRef::decode_value(reader, header)?;
match value.as_ref() {
$( $value => Ok(Self::$item), )*
_ => Err(der::Error::new(
ErrorKind::Value { tag: Self::TAG },
reader.position(),
)),
}
}
}
impl EncodeValue for $name {
fn value_len(&self) -> der::Result<Length> {
Utf8StringRef::new(self.as_ref())?.value_len()
}
fn encode_value(&self, encoder: &mut impl Writer) -> der::Result<()> {
Utf8StringRef::new(self.as_ref())?.encode_value(encoder)
}
}
impl FixedTag for $name {
const TAG: Tag = String::TAG;
}
};
}
#[derive(Sequence, PartialEq, Eq)]
#[allow(missing_docs)]
pub struct SymmetricKeyPackage {
#[asn1(default = "Default::default")]
pub version: KeyPkgVersion,
#[asn1(context_specific = "0", tag_mode = "IMPLICIT", optional = "true")]
pub s_key_pkg_attrs: Option<Vec<Attribute>>,
pub s_keys: SymmetricKeys,
}
pub type SymmetricKeys = Vec<OneSymmetricKey>;
#[derive(Sequence, PartialEq, Eq)]
#[allow(missing_docs)]
pub struct OneSymmetricKey {
#[asn1(optional = "true")]
pub s_key_attrs: Option<Vec<Attribute>>,
#[asn1(optional = "true")]
pub s_key: Option<OctetString>,
}
#[derive(Default, Clone, Debug, Copy, PartialEq, Eq, PartialOrd, Ord, Enumerated)]
#[asn1(type = "INTEGER")]
#[repr(u8)]
#[allow(missing_docs)]
pub enum KeyPkgVersion {
#[default]
V1 = 1,
}
#[derive(Sequence, PartialEq, Eq)]
#[allow(missing_docs)]
pub struct FriendlyName {
pub friendly_name: String,
#[asn1(optional = "true")]
pub friendly_name_lang_tag: Option<String>,
}
#[derive(Sequence, PartialEq, Eq)]
#[allow(missing_docs)]
pub struct PSKCAlgorithmParameters {
pub suite: String,
pub challenge_format: ChallengeFormat,
pub response_format: ResponseFormat,
}
#[derive(Sequence, PartialEq, Eq)]
#[allow(missing_docs)]
pub struct ChallengeFormat {
pub encoding: Encoding,
#[asn1(default = "Default::default")]
pub check_digit: bool,
pub min: der::asn1::Int,
pub max: der::asn1::Int,
}
impl_str_enum!(
#[derive(Copy, Clone, PartialEq, Eq)]
pub enum Encoding {
Decimal => "DECIMAL",
Hexadecimal => "HEXADECIMAL",
Alphanumeric => "ALPHANUMERIC",
Base64 => "BASE64",
Binary => "BINARY",
}
);
#[derive(Sequence, PartialEq, Eq)]
#[allow(missing_docs)]
pub struct ResponseFormat {
pub encoding: Encoding,
pub length: u32,
#[asn1(default = "Default::default")]
pub check_digit: bool,
}
#[derive(Sequence, PartialEq, Eq)]
#[allow(missing_docs)]
pub struct ValueMac {
pub mac_algorithm: String,
pub mac: String,
}
pub type PSKCKeyUsages = Vec<PSKCKeyUsage>;
impl_str_enum!(
#[derive(Copy, Clone, PartialEq, Eq)]
pub enum PSKCKeyUsage {
Otp => "Otp",
Cr => "CR",
Encrypt => "Encrypt",
Integrity => "Integrity",
Verify => "Verify",
Unlock => "Unlock",
Decrypt => "Decrypt",
KeyWrap => "KeyWrap",
Unwrap => "Unwrap",
Derive => "Derive",
Generate => "Generate",
}
);
#[derive(Sequence, PartialEq, Eq)]
#[allow(missing_docs)]
pub struct PINPolicy {
#[asn1(context_specific = "0", tag_mode = "IMPLICIT", optional = "true")]
pub pin_key_id: Option<String>,
#[asn1(context_specific = "1", tag_mode = "IMPLICIT")]
pub pin_usage_mode: PINUsageMode,
#[asn1(context_specific = "2", tag_mode = "IMPLICIT", optional = "true")]
pub max_failed_attempts: Option<u32>,
#[asn1(context_specific = "3", tag_mode = "IMPLICIT", optional = "true")]
pub min_length: Option<u32>,
#[asn1(context_specific = "4", tag_mode = "IMPLICIT", optional = "true")]
pub max_length: Option<u32>,
#[asn1(context_specific = "5", tag_mode = "IMPLICIT", optional = "true")]
pub pin_encoding: Option<Encoding>,
}
impl_str_enum!(
#[derive(Copy, Clone, PartialEq, Eq)]
pub enum PINUsageMode {
Local => "Local",
Prepend => "Prepend",
Append => "Append",
Algorithmic => "Algorithmic",
}
);