Implement TryFrom (instead of offering that functionality without implementing the trait)
This commit is contained in:
parent
b560d4eb5a
commit
c7751ff4ce
5 changed files with 83 additions and 60 deletions
|
@ -69,7 +69,7 @@ impl ApplicationRelatedData {
|
||||||
|
|
||||||
if let Some(eli) = eli {
|
if let Some(eli) = eli {
|
||||||
// The card has returned extended length information
|
// The card has returned extended length information
|
||||||
Ok(Some(ExtendedLengthInfo::from(&eli.serialize()[..])?))
|
Ok(Some((&eli.serialize()[..]).try_into()?))
|
||||||
} else {
|
} else {
|
||||||
// The card didn't return this (optional) DO. That is ok.
|
// The card didn't return this (optional) DO. That is ok.
|
||||||
Ok(None)
|
Ok(None)
|
||||||
|
@ -117,7 +117,7 @@ impl ApplicationRelatedData {
|
||||||
let psb = self.0.find(&[0xc4].into());
|
let psb = self.0.find(&[0xc4].into());
|
||||||
|
|
||||||
if let Some(psb) = psb {
|
if let Some(psb) = psb {
|
||||||
let pws = PWStatus::try_from(&psb.serialize())?;
|
let pws = (&psb.serialize()[..]).try_into()?;
|
||||||
|
|
||||||
log::debug!("PW Status: {:x?}", pws);
|
log::debug!("PW Status: {:x?}", pws);
|
||||||
|
|
||||||
|
@ -134,7 +134,7 @@ impl ApplicationRelatedData {
|
||||||
let fp = self.0.find(&[0xc5].into());
|
let fp = self.0.find(&[0xc5].into());
|
||||||
|
|
||||||
if let Some(fp) = fp {
|
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);
|
log::debug!("Fp: {:x?}", fp);
|
||||||
|
|
||||||
|
@ -151,7 +151,8 @@ impl ApplicationRelatedData {
|
||||||
let kg = self.0.find(&[0xcd].into());
|
let kg = self.0.find(&[0xcd].into());
|
||||||
|
|
||||||
if let Some(kg) = kg {
|
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);
|
log::debug!("Key generation: {:x?}", kg);
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@ use anyhow::Result;
|
||||||
use nom::{bytes::complete::tag, number::complete as number, sequence};
|
use nom::{bytes::complete::tag, number::complete as number, sequence};
|
||||||
|
|
||||||
use crate::card_do::{complete, ExtendedLengthInfo};
|
use crate::card_do::{complete, ExtendedLengthInfo};
|
||||||
|
use std::convert::TryFrom;
|
||||||
|
|
||||||
fn parse(input: &[u8]) -> nom::IResult<&[u8], (u16, u16)> {
|
fn parse(input: &[u8]) -> nom::IResult<&[u8], (u16, u16)> {
|
||||||
let (input, (_, cmd, _, resp)) =
|
let (input, (_, cmd, _, resp)) =
|
||||||
|
@ -28,8 +29,12 @@ impl ExtendedLengthInfo {
|
||||||
pub fn max_response_bytes(&self) -> u16 {
|
pub fn max_response_bytes(&self) -> u16 {
|
||||||
self.max_response_bytes
|
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))?;
|
let eli = complete(parse(input))?;
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
|
|
|
@ -83,14 +83,21 @@ fn fingerprints(input: &[u8]) -> nom::IResult<&[u8], KeySet<Fingerprint>> {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse three fingerprints from the card into a KeySet of Fingerprints
|
impl TryFrom<&[u8]> for KeySet<Fingerprint> {
|
||||||
pub(crate) fn to_keyset(input: &[u8]) -> Result<KeySet<Fingerprint>, Error> {
|
type Error = 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
|
fn try_from(input: &[u8]) -> Result<Self, Self::Error> {
|
||||||
// been completely consumed.
|
log::trace!(
|
||||||
self::fingerprints(input)
|
"Fingerprint from input: {:x?}, len {}",
|
||||||
.map(|res| res.1)
|
input,
|
||||||
.map_err(|err| anyhow!("Parsing failed: {:?}", err))
|
input.len()
|
||||||
.map_err(Error::InternalError)
|
);
|
||||||
|
|
||||||
|
// 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)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@ use nom::{combinator, number::complete as number, sequence};
|
||||||
|
|
||||||
use crate::card_do::{KeyGenerationTime, KeySet};
|
use crate::card_do::{KeyGenerationTime, KeySet};
|
||||||
use crate::Error;
|
use crate::Error;
|
||||||
|
use std::convert::TryFrom;
|
||||||
|
|
||||||
impl From<KeyGenerationTime> for DateTime<Utc> {
|
impl From<KeyGenerationTime> for DateTime<Utc> {
|
||||||
fn from(kg: KeyGenerationTime) -> Self {
|
fn from(kg: KeyGenerationTime) -> Self {
|
||||||
|
@ -53,22 +54,26 @@ fn key_generation_set(
|
||||||
)))(input)
|
)))(input)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from(input: &[u8]) -> Result<KeySet<KeyGenerationTime>, Error> {
|
impl TryFrom<&[u8]> for KeySet<KeyGenerationTime> {
|
||||||
// List of generation dates/times of key pairs, binary.
|
type Error = Error;
|
||||||
// 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).
|
|
||||||
|
|
||||||
log::trace!(
|
fn try_from(input: &[u8]) -> Result<Self, Self::Error> {
|
||||||
"Key generation times from input: {:x?}, len {}",
|
// List of generation dates/times of key pairs, binary.
|
||||||
input,
|
// 4 bytes, Big Endian each for Sig, Dec and Aut. Each
|
||||||
input.len()
|
// 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
|
log::trace!(
|
||||||
// hasn't been completely consumed.
|
"Key generation times from input: {:x?}, len {}",
|
||||||
self::key_generation_set(input)
|
input,
|
||||||
.map(|res| res.1)
|
input.len()
|
||||||
.map_err(|err| anyhow!("Parsing failed: {:?}", err))
|
);
|
||||||
.map_err(Error::InternalError)
|
|
||||||
|
// 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)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,9 +7,43 @@ use anyhow::anyhow;
|
||||||
|
|
||||||
use crate::card_do::PWStatus;
|
use crate::card_do::PWStatus;
|
||||||
use crate::Error;
|
use crate::Error;
|
||||||
|
use std::convert::TryFrom;
|
||||||
|
|
||||||
impl PWStatus {
|
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 {
|
if input.len() == 7 {
|
||||||
let pw1_cds_multi = input[0] == 0x01;
|
let pw1_cds_multi = input[0] == 0x01;
|
||||||
let pw1_pin_block = input[1] & 0x80 != 0;
|
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
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue