diff --git a/openpgp-card-sequoia/src/lib.rs b/openpgp-card-sequoia/src/lib.rs index 52a93ca..9e6f31e 100644 --- a/openpgp-card-sequoia/src/lib.rs +++ b/openpgp-card-sequoia/src/lib.rs @@ -35,7 +35,7 @@ use openpgp_card::algorithm::{Algo, AlgoInfo, Curve}; use openpgp_card::card_do::{ ApplicationId, ApplicationRelatedData, Cardholder, ExtendedCap, ExtendedLengthInfo, Features, Fingerprint, Historical, KeySet, PWStatus, - Sex, + SecuritySupportTemplate, Sex, }; use openpgp_card::crypto_data::{ CardUploadableKey, Cryptogram, EccKey, EccType, Hash, PrivateKeyMaterial, @@ -684,7 +684,9 @@ impl CardBase { } // --- security support template (7a) --- - pub fn get_security_support_template(&mut self) -> Result> { + pub fn get_security_support_template( + &mut self, + ) -> Result { self.card_app.get_security_support_template() } diff --git a/openpgp-card/src/card_app.rs b/openpgp-card/src/card_app.rs index 22e9aab..ddce952 100644 --- a/openpgp-card/src/card_app.rs +++ b/openpgp-card/src/card_app.rs @@ -10,7 +10,9 @@ use anyhow::{anyhow, Result}; use crate::algorithm::{Algo, AlgoInfo, AlgoSimple, RsaAttrs}; use crate::apdu::{commands, response::Response}; -use crate::card_do::{ApplicationRelatedData, Cardholder, Sex}; +use crate::card_do::{ + ApplicationRelatedData, Cardholder, SecuritySupportTemplate, Sex, +}; use crate::crypto_data::{ CardUploadableKey, Cryptogram, EccType, Hash, PublicKeyMaterial, }; @@ -159,14 +161,30 @@ impl CardApp { } // --- security support template (7a) --- - // FIXME: parse data into a proper data structure - pub fn get_security_support_template(&mut self) -> Result> { + pub fn get_security_support_template( + &mut self, + ) -> Result { let sst = commands::get_security_support_template(); let resp = apdu::send_command(&mut self.card_client, sst, true)?; resp.check_ok()?; let tlv = Tlv::try_from(resp.data()?)?; - Ok(tlv.serialize()) + let res = tlv + .find(&Tag::from([0x93])) + .ok_or(anyhow!("Couldn't get SecuritySupportTemplate DO"))?; + + if let TlvEntry::S(data) = res { + let mut data = data.to_vec(); + assert_eq!(data.len(), 3); + + data.insert(0, 0); // prepend a zero + let data: [u8; 4] = data.try_into().unwrap(); + + let dsc: u32 = u32::from_be_bytes(data); + Ok(SecuritySupportTemplate { dsc }) + } else { + Err(anyhow!("Failed to process SecuritySupportTemplate")) + } } // DO "Algorithm Information" (0xFA) diff --git a/openpgp-card/src/card_do/mod.rs b/openpgp-card/src/card_do/mod.rs index 582e35c..9003108 100644 --- a/openpgp-card/src/card_do/mod.rs +++ b/openpgp-card/src/card_do/mod.rs @@ -168,6 +168,19 @@ impl ApplicationRelatedData { } } +#[derive(Debug)] +pub struct SecuritySupportTemplate { + // Digital signature counter [3 bytes] + // (counts usage of Compute Digital Signature command) + pub(crate) dsc: u32, +} + +impl SecuritySupportTemplate { + pub fn get_signature_count(&self) -> u32 { + self.dsc + } +} + /// An OpenPGP key generation Time #[derive(Clone, Eq, PartialEq, Debug)] pub struct KeyGeneration(u32);