From c7751ff4cee658fe0e718564e811d76cf9bf2b9c Mon Sep 17 00:00:00 2001 From: Heiko Schaefer Date: Thu, 2 Sep 2021 18:00:55 +0200 Subject: [PATCH] Implement TryFrom (instead of offering that functionality without implementing the trait) --- openpgp-card/src/card_do.rs | 9 +-- .../src/card_do/extended_length_info.rs | 7 +- openpgp-card/src/card_do/fingerprint.rs | 25 ++++--- .../src/card_do/key_generation_times.rs | 37 ++++++----- openpgp-card/src/card_do/pw_status.rs | 65 ++++++++++--------- 5 files changed, 83 insertions(+), 60 deletions(-) diff --git a/openpgp-card/src/card_do.rs b/openpgp-card/src/card_do.rs index cc6db38..8e861a7 100644 --- a/openpgp-card/src/card_do.rs +++ b/openpgp-card/src/card_do.rs @@ -69,7 +69,7 @@ impl ApplicationRelatedData { if let Some(eli) = eli { // The card has returned extended length information - Ok(Some(ExtendedLengthInfo::from(&eli.serialize()[..])?)) + Ok(Some((&eli.serialize()[..]).try_into()?)) } else { // The card didn't return this (optional) DO. That is ok. Ok(None) @@ -117,7 +117,7 @@ impl ApplicationRelatedData { let psb = self.0.find(&[0xc4].into()); if let Some(psb) = psb { - let pws = PWStatus::try_from(&psb.serialize())?; + let pws = (&psb.serialize()[..]).try_into()?; log::debug!("PW Status: {:x?}", pws); @@ -134,7 +134,7 @@ impl ApplicationRelatedData { let fp = self.0.find(&[0xc5].into()); if let Some(fp) = fp { - let fp = fingerprint::to_keyset(&fp.serialize())?; + let fp: KeySet = (&fp.serialize()[..]).try_into()?; log::debug!("Fp: {:x?}", fp); @@ -151,7 +151,8 @@ impl ApplicationRelatedData { let kg = self.0.find(&[0xcd].into()); if let Some(kg) = kg { - let kg = key_generation_times::from(&kg.serialize())?; + let kg: KeySet = + (&kg.serialize()[..]).try_into()?; log::debug!("Key generation: {:x?}", kg); diff --git a/openpgp-card/src/card_do/extended_length_info.rs b/openpgp-card/src/card_do/extended_length_info.rs index cd70478..72ad0ed 100644 --- a/openpgp-card/src/card_do/extended_length_info.rs +++ b/openpgp-card/src/card_do/extended_length_info.rs @@ -7,6 +7,7 @@ use anyhow::Result; use nom::{bytes::complete::tag, number::complete as number, sequence}; use crate::card_do::{complete, ExtendedLengthInfo}; +use std::convert::TryFrom; fn parse(input: &[u8]) -> nom::IResult<&[u8], (u16, u16)> { let (input, (_, cmd, _, resp)) = @@ -28,8 +29,12 @@ impl ExtendedLengthInfo { pub fn max_response_bytes(&self) -> u16 { self.max_response_bytes } +} - pub fn from(input: &[u8]) -> Result { +impl TryFrom<&[u8]> for ExtendedLengthInfo { + type Error = anyhow::Error; + + fn try_from(input: &[u8]) -> Result { let eli = complete(parse(input))?; Ok(Self { diff --git a/openpgp-card/src/card_do/fingerprint.rs b/openpgp-card/src/card_do/fingerprint.rs index a010c82..52a44db 100644 --- a/openpgp-card/src/card_do/fingerprint.rs +++ b/openpgp-card/src/card_do/fingerprint.rs @@ -83,14 +83,21 @@ fn fingerprints(input: &[u8]) -> nom::IResult<&[u8], KeySet> { ) } -/// Parse three fingerprints from the card into a KeySet of Fingerprints -pub(crate) fn to_keyset(input: &[u8]) -> Result, Error> { - log::trace!("Fingerprint from input: {:x?}, len {}", input, input.len()); +impl TryFrom<&[u8]> for KeySet { + type Error = Error; - // The input may be longer than 3 fingerprint, don't fail if it hasn't - // been completely consumed. - self::fingerprints(input) - .map(|res| res.1) - .map_err(|err| anyhow!("Parsing failed: {:?}", err)) - .map_err(Error::InternalError) + fn try_from(input: &[u8]) -> Result { + log::trace!( + "Fingerprint from input: {:x?}, len {}", + input, + input.len() + ); + + // The input may be longer than 3 fingerprint, don't fail if it hasn't + // been completely consumed. + self::fingerprints(input) + .map(|res| res.1) + .map_err(|err| anyhow!("Parsing failed: {:?}", err)) + .map_err(Error::InternalError) + } } diff --git a/openpgp-card/src/card_do/key_generation_times.rs b/openpgp-card/src/card_do/key_generation_times.rs index 68e7c7a..ec63784 100644 --- a/openpgp-card/src/card_do/key_generation_times.rs +++ b/openpgp-card/src/card_do/key_generation_times.rs @@ -9,6 +9,7 @@ use nom::{combinator, number::complete as number, sequence}; use crate::card_do::{KeyGenerationTime, KeySet}; use crate::Error; +use std::convert::TryFrom; impl From for DateTime { fn from(kg: KeyGenerationTime) -> Self { @@ -53,22 +54,26 @@ fn key_generation_set( )))(input) } -pub fn from(input: &[u8]) -> Result, Error> { - // List of generation dates/times of key pairs, binary. - // 4 bytes, Big Endian each for Sig, Dec and Aut. Each - // value shall be seconds since Jan 1, 1970. Default - // value is 00000000 (not specified). +impl TryFrom<&[u8]> for KeySet { + type Error = Error; - log::trace!( - "Key generation times from input: {:x?}, len {}", - input, - input.len() - ); + fn try_from(input: &[u8]) -> Result { + // List of generation dates/times of key pairs, binary. + // 4 bytes, Big Endian each for Sig, Dec and Aut. Each + // value shall be seconds since Jan 1, 1970. Default + // value is 00000000 (not specified). - // The input may be longer than 3 key generation times, don't fail if it - // hasn't been completely consumed. - self::key_generation_set(input) - .map(|res| res.1) - .map_err(|err| anyhow!("Parsing failed: {:?}", err)) - .map_err(Error::InternalError) + log::trace!( + "Key generation times from input: {:x?}, len {}", + input, + input.len() + ); + + // The input may be longer than 3 key generation times, don't fail if it + // hasn't been completely consumed. + self::key_generation_set(input) + .map(|res| res.1) + .map_err(|err| anyhow!("Parsing failed: {:?}", err)) + .map_err(Error::InternalError) + } } diff --git a/openpgp-card/src/card_do/pw_status.rs b/openpgp-card/src/card_do/pw_status.rs index 0d3e97b..a6b84e6 100644 --- a/openpgp-card/src/card_do/pw_status.rs +++ b/openpgp-card/src/card_do/pw_status.rs @@ -7,9 +7,43 @@ use anyhow::anyhow; use crate::card_do::PWStatus; use crate::Error; +use std::convert::TryFrom; impl PWStatus { - pub fn try_from(input: &[u8]) -> Result { + /// PUT DO for PW Status Bytes accepts either 1 or 4 bytes of data. + /// This method generates the 1 byte version for 'long==false' and the + /// 4 bytes version for 'long==true'. + /// + /// (See OpenPGP card spec, pg. 28) + pub(crate) fn serialize_for_put(&self, long: bool) -> Vec { + let mut data = vec![]; + + data.push(if !self.pw1_cds_multi { 0 } else { 1 }); + + if long { + let mut b2 = self.pw1_len; + if self.pw1_pin_block { + b2 |= 0x80; + } + data.push(b2); + + data.push(self.rc_len); + + let mut b4 = self.pw3_len; + if self.pw3_pin_block { + b4 |= 0x80; + } + data.push(b4); + } + + data + } +} + +impl TryFrom<&[u8]> for PWStatus { + type Error = Error; + + fn try_from(input: &[u8]) -> Result { if input.len() == 7 { let pw1_cds_multi = input[0] == 0x01; let pw1_pin_block = input[1] & 0x80 != 0; @@ -39,33 +73,4 @@ impl PWStatus { ))) } } - - /// PUT DO for PW Status Bytes accepts either 1 or 4 bytes of data. - /// This method generates the 1 byte version for 'long==false' and the - /// 4 bytes version for 'long==true'. - /// - /// (See OpenPGP card spec, pg. 28) - pub fn serialize_for_put(&self, long: bool) -> Vec { - let mut data = vec![]; - - data.push(if !self.pw1_cds_multi { 0 } else { 1 }); - - if long { - let mut b2 = self.pw1_len; - if self.pw1_pin_block { - b2 |= 0x80; - } - data.push(b2); - - data.push(self.rc_len); - - let mut b4 = self.pw3_len; - if self.pw3_pin_block { - b4 |= 0x80; - } - data.push(b4); - } - - data - } }