From d1f854f2f0de3b36af369c40572116a0731d849c Mon Sep 17 00:00:00 2001 From: Heiko Schaefer Date: Sat, 3 Jul 2021 21:23:17 +0200 Subject: [PATCH] Implement get_pw_status_bytes() --- openpgp-card-sequoia/src/main.rs | 3 ++ openpgp-card/src/lib.rs | 18 ++++++++-- openpgp-card/src/parse/mod.rs | 1 + openpgp-card/src/parse/pw_status.rs | 51 +++++++++++++++++++++++++++++ 4 files changed, 70 insertions(+), 3 deletions(-) create mode 100644 openpgp-card/src/parse/pw_status.rs diff --git a/openpgp-card-sequoia/src/main.rs b/openpgp-card-sequoia/src/main.rs index db91bc0..b6a5c94 100644 --- a/openpgp-card-sequoia/src/main.rs +++ b/openpgp-card-sequoia/src/main.rs @@ -48,6 +48,9 @@ fn main() -> Result<(), Box> { let ext = oc.get_extended_capabilities()?; println!("extended_capabilities {:#x?}", ext); + let pws = oc.get_pw_status_bytes()?; + println!("PW Status Bytes {:#x?}", pws); + // cardholder let ch = oc.get_cardholder_related_data()?; diff --git a/openpgp-card/src/lib.rs b/openpgp-card/src/lib.rs index 175c4fe..3925420 100644 --- a/openpgp-card/src/lib.rs +++ b/openpgp-card/src/lib.rs @@ -11,7 +11,7 @@ use parse::{ algo_attrs::Algo, algo_info::AlgoInfo, application_id::ApplicationId, cardholder::CardHolder, extended_cap::ExtendedCap, extended_cap::Features, extended_length_info::ExtendedLengthInfo, fingerprint, - historical::Historical, KeySet, + historical::Historical, pw_status::PWStatus, KeySet, }; use tlv::Tlv; @@ -384,8 +384,20 @@ impl CardBase { } } - pub fn get_pw_status_bytes() { - unimplemented!() + /// PW status Bytes + pub fn get_pw_status_bytes(&self) -> Result { + // get from cached "application related data" + let psb = self.ard.find(&Tag::from([0xc4])); + + if let Some(psb) = psb { + let pws = PWStatus::try_from(&psb.serialize())?; + + log::debug!("PW Status: {:x?}", pws); + + Ok(pws) + } else { + Err(anyhow!("Failed to get PW status Bytes.").into()) + } } pub fn get_fingerprints( diff --git a/openpgp-card/src/parse/mod.rs b/openpgp-card/src/parse/mod.rs index 6f5f66c..2da0124 100644 --- a/openpgp-card/src/parse/mod.rs +++ b/openpgp-card/src/parse/mod.rs @@ -12,6 +12,7 @@ pub mod extended_cap; pub mod extended_length_info; pub mod fingerprint; pub mod historical; +pub mod pw_status; use anyhow::{anyhow, Error}; diff --git a/openpgp-card/src/parse/pw_status.rs b/openpgp-card/src/parse/pw_status.rs new file mode 100644 index 0000000..8260fc5 --- /dev/null +++ b/openpgp-card/src/parse/pw_status.rs @@ -0,0 +1,51 @@ +// SPDX-FileCopyrightText: 2021 Heiko Schaefer +// SPDX-License-Identifier: MIT OR Apache-2.0 + +use crate::errors::OpenpgpCardError; +use anyhow::anyhow; + +#[derive(Debug)] +pub struct PWStatus { + pub(crate) pw1_cds_multi: bool, + pub(crate) pw1_derived: bool, + pub(crate) pw1_len: u8, + pub(crate) rc_len: u8, + pub(crate) pw3_derived: bool, + pub(crate) pw3_len: u8, + pub(crate) err_count_pw1: u8, + pub(crate) err_count_rst: u8, + pub(crate) err_count_pw3: u8, +} + +impl PWStatus { + pub fn try_from(input: &[u8]) -> Result { + if input.len() == 7 { + let pw1_cds_multi = input[0] == 0x01; + let pw1_derived = input[1] & 0x80 != 0; + let pw1_len = input[1] & 0x7f; + let rc_len = input[2]; + let pw3_derived = input[3] & 0x80 != 0; + let pw3_len = input[3] & 0x7f; + let err_count_pw1 = input[4]; + let err_count_rst = input[5]; + let err_count_pw3 = input[6]; + + Ok(Self { + pw1_cds_multi, + pw1_derived, + pw1_len, + rc_len, + pw3_derived, + pw3_len, + err_count_pw1, + err_count_rst, + err_count_pw3, + }) + } else { + Err(OpenpgpCardError::InternalError(anyhow!( + "Unexpected length of PW Status Bytes: {}", + input.len() + ))) + } + } +}