Add get_key_generation_times()

This commit is contained in:
Heiko Schaefer 2021-07-16 16:39:02 +02:00
commit 1c15e61fb4
3 changed files with 93 additions and 3 deletions

View file

@ -20,7 +20,8 @@ use crate::parse::{
algo_attrs::Algo, algo_info::AlgoInfo, application_id::ApplicationId, algo_attrs::Algo, algo_info::AlgoInfo, application_id::ApplicationId,
cardholder::CardHolder, extended_cap::ExtendedCap, cardholder::CardHolder, extended_cap::ExtendedCap,
extended_length_info::ExtendedLengthInfo, fingerprint, extended_length_info::ExtendedLengthInfo, fingerprint,
historical::Historical, pw_status::PWStatus, KeySet, historical::Historical, key_generation_times,
key_generation_times::KeyGeneration, pw_status::PWStatus, KeySet,
}; };
use crate::tlv::{tag::Tag, Tlv, TlvEntry}; use crate::tlv::{tag::Tag, Tlv, TlvEntry};
use crate::{ use crate::{
@ -191,8 +192,20 @@ impl CardApp {
unimplemented!() unimplemented!()
} }
pub fn get_key_generation_times() { pub fn get_key_generation_times(
unimplemented!() ard: &Tlv,
) -> Result<KeySet<KeyGeneration>, OpenpgpCardError> {
let kg = ard.find(&Tag::from([0xCD]));
if let Some(kg) = kg {
let kg = key_generation_times::from(&kg.serialize())?;
log::debug!("Key generation: {:x?}", kg);
Ok(kg)
} else {
Err(anyhow!("Failed to get key generation times.").into())
}
} }
pub fn get_key_information() { pub fn get_key_information() {

View file

@ -0,0 +1,76 @@
// SPDX-FileCopyrightText: 2021 Heiko Schaefer <heiko@schaefer.name>
// SPDX-License-Identifier: MIT OR Apache-2.0
use anyhow::anyhow;
use nom::{
bytes::complete as bytes, combinator, number::complete as number, sequence,
};
use std::fmt;
use crate::errors::OpenpgpCardError;
use crate::parse::KeySet;
use chrono::{DateTime, NaiveDateTime, Utc};
#[derive(Clone, Eq, PartialEq, Debug)]
pub struct KeyGeneration(u32);
impl From<KeyGeneration> for DateTime<Utc> {
fn from(kg: KeyGeneration) -> Self {
let naive_datetime = NaiveDateTime::from_timestamp(kg.0 as i64, 0);
DateTime::from_utc(naive_datetime, Utc)
}
}
impl From<&KeyGeneration> for u32 {
fn from(kg: &KeyGeneration) -> Self {
kg.0
}
}
impl From<u32> for KeyGeneration {
fn from(data: u32) -> Self {
Self(data)
}
}
fn gen_time(input: &[u8]) -> nom::IResult<&[u8], u32> {
(number::be_u32)(input)
}
fn key_generation(input: &[u8]) -> nom::IResult<&[u8], Option<KeyGeneration>> {
combinator::map(gen_time, |kg| match kg {
0 => None,
kg => Some(KeyGeneration(kg)),
})(input)
}
fn key_generation_set(
input: &[u8],
) -> nom::IResult<&[u8], KeySet<KeyGeneration>> {
combinator::into(sequence::tuple((
key_generation,
key_generation,
key_generation,
)))(input)
}
pub fn from(input: &[u8]) -> Result<KeySet<KeyGeneration>, OpenpgpCardError> {
// 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).
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(OpenpgpCardError::InternalError)
}

View file

@ -12,6 +12,7 @@ pub mod extended_cap;
pub mod extended_length_info; pub mod extended_length_info;
pub mod fingerprint; pub mod fingerprint;
pub mod historical; pub mod historical;
pub mod key_generation_times;
pub mod pw_status; pub mod pw_status;
use anyhow::{anyhow, Error}; use anyhow::{anyhow, Error};