Implement TryFrom (instead of offering that functionality without implementing the trait)

This commit is contained in:
Heiko Schaefer 2021-09-02 18:00:55 +02:00
parent b560d4eb5a
commit c7751ff4ce
5 changed files with 83 additions and 60 deletions

View file

@ -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<Fingerprint> = (&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<KeyGenerationTime> =
(&kg.serialize()[..]).try_into()?;
log::debug!("Key generation: {:x?}", kg);

View file

@ -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<Self> {
impl TryFrom<&[u8]> for ExtendedLengthInfo {
type Error = anyhow::Error;
fn try_from(input: &[u8]) -> Result<Self, Self::Error> {
let eli = complete(parse(input))?;
Ok(Self {

View file

@ -83,14 +83,21 @@ fn fingerprints(input: &[u8]) -> nom::IResult<&[u8], KeySet<Fingerprint>> {
)
}
/// Parse three fingerprints from the card into a KeySet of Fingerprints
pub(crate) fn to_keyset(input: &[u8]) -> Result<KeySet<Fingerprint>, Error> {
log::trace!("Fingerprint from input: {:x?}, len {}", input, input.len());
impl TryFrom<&[u8]> for KeySet<Fingerprint> {
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<Self, Self::Error> {
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)
}
}

View file

@ -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<KeyGenerationTime> for DateTime<Utc> {
fn from(kg: KeyGenerationTime) -> Self {
@ -53,22 +54,26 @@ fn key_generation_set(
)))(input)
}
pub fn from(input: &[u8]) -> Result<KeySet<KeyGenerationTime>, 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<KeyGenerationTime> {
type Error = Error;
log::trace!(
"Key generation times from input: {:x?}, len {}",
input,
input.len()
);
fn try_from(input: &[u8]) -> Result<Self, Self::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).
// 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)
}
}

View file

@ -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<Self, Error> {
/// 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<u8> {
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<Self, Self::Error> {
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<u8> {
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
}
}