use std::str::FromStr; use ssh_encoding::{Decode, Label, LabelError}; use x509_parser::{nom::Finish, prelude::*}; #[non_exhaustive] #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub enum Version { V00, V01, } impl AsRef for Version { fn as_ref(&self) -> &str { match self { Self::V00 => "ssh-sk-attest-v00", Self::V01 => "ssh-sk-attest-v01", } } } impl FromStr for Version { type Err = LabelError; fn from_str(s: &str) -> Result { match s { "ssh-sk-attest-v00" => Ok(Self::V00), "ssh-sk-attest-v01" => Ok(Self::V01), _ => Err(LabelError::new(s.into())), } } } impl Label for Version {} #[non_exhaustive] pub struct SshAttestationInfo { pub version: Version, pub attestation_cert: Vec, pub enroll_sig: Vec, pub auth_data: Option>, } impl SshAttestationInfo { pub fn decode_cert(&self) -> Result, X509Error> { X509Certificate::from_der(&self.attestation_cert) .finish() .map(|(_, cert)| cert) } } impl Decode for SshAttestationInfo { type Error = ssh_encoding::Error; fn decode(reader: &mut impl ssh_encoding::Reader) -> core::result::Result { let version = Version::decode(reader)?; let attestation_cert = Vec::decode(reader)?; let enroll_sig = Vec::decode(reader)?; let auth_data = match version { Version::V00 => None, Version::V01 => Some(Vec::decode(reader)?), }; Ok(Self { version, attestation_cert, enroll_sig, auth_data, }) } }