Add functionality for cli tools.

This commit is contained in:
Heiko Schaefer 2021-10-28 00:04:50 +02:00
parent 1d4f058858
commit aa7528ec9a
4 changed files with 81 additions and 9 deletions

View file

@ -454,7 +454,7 @@ pub fn test_pw_status(
ca.verify_pw3("12345678")?;
pws.set_pw1_cds_multi(true);
pws.set_pw1_cds_valid_once(false);
pws.set_pw1_pin_block(true);
ca.set_pw_status_bytes(&pws, false)?;

View file

@ -18,7 +18,7 @@ use openpgp::parse::{
};
use openpgp::policy::Policy;
use openpgp::serialize::stream::{Message, Signer};
use openpgp::Cert;
use openpgp::{Cert, Fingerprint};
use sequoia_openpgp as openpgp;
use openpgp_card::KeyType;
@ -60,6 +60,36 @@ pub fn get_subkey<'a>(
}
}
/// Retrieve a (sub)key from a Cert, with a specified fingerprint.
pub fn get_subkey_by_fingerprint<'a>(
cert: &'a Cert,
policy: &'a dyn Policy,
fingerprint: &str,
) -> Result<Option<ValidErasedKeyAmalgamation<'a, SecretParts>>> {
let fp = Fingerprint::from_hex(fingerprint)?;
// Find usable (sub)key with Fingerprint fp.
let mut vkas: Vec<_> = cert
.keys()
.with_policy(policy, None)
.secret()
.alive()
.revoked(false)
.filter(|vka| vka.fingerprint() == fp)
.collect();
if vkas.is_empty() {
Ok(None)
} else if vkas.len() == 1 {
Ok(Some(vkas.pop().unwrap()))
} else {
Err(anyhow::anyhow!(
"Unexpected number of suitable (sub)key found: {}",
vkas.len()
))
}
}
/// Produce an armored signature from `input` and a Signer `s`.
pub fn sign_helper<S>(s: S, input: &mut dyn io::Read) -> Result<String>
where

View file

@ -4,8 +4,10 @@
//! OpenPGP card data objects (DO)
use anyhow::{anyhow, Result};
use chrono::{DateTime, Utc};
use std::convert::TryFrom;
use std::convert::TryInto;
use std::time::{Duration, UNIX_EPOCH};
use crate::{algorithm::Algo, tlv::Tlv, Error, KeySet, KeyType};
@ -193,6 +195,13 @@ impl KeyGenerationTime {
pub fn get(&self) -> u32 {
self.0
}
pub fn formatted(&self) -> String {
let d = UNIX_EPOCH + Duration::from_secs(self.get() as u64);
let datetime = DateTime::<Utc>::from(d);
datetime.format("%Y-%m-%d %H:%M:%S").to_string()
}
}
/// 4.2.1 Application Identifier (AID)
@ -312,7 +321,7 @@ impl From<u8> for Sex {
/// PW status Bytes (see spec page 23)
#[derive(Debug, PartialEq)]
pub struct PWStatusBytes {
pub(crate) pw1_cds_multi: bool,
pub(crate) pw1_cds_valid_once: bool,
pub(crate) pw1_pin_block: bool,
pub(crate) pw1_len: u8,
pub(crate) rc_len: u8,
@ -324,8 +333,8 @@ pub struct PWStatusBytes {
}
impl PWStatusBytes {
pub fn set_pw1_cds_multi(&mut self, val: bool) {
self.pw1_cds_multi = val;
pub fn set_pw1_cds_valid_once(&mut self, val: bool) {
self.pw1_cds_valid_once = val;
}
pub fn set_pw1_pin_block(&mut self, val: bool) {
self.pw1_pin_block = val;
@ -333,12 +342,45 @@ impl PWStatusBytes {
pub fn set_pw3_pin_block(&mut self, val: bool) {
self.pw3_pin_block = val;
}
pub fn get_pw1_cds_valid_once(&self) -> bool {
self.pw1_cds_valid_once
}
pub fn get_err_count_pw1(&self) -> u8 {
self.err_count_pw1
}
pub fn get_err_count_rst(&self) -> u8 {
self.err_count_rst
}
pub fn get_err_count_pw3(&self) -> u8 {
self.err_count_pw3
}
}
/// Fingerprint (see spec pg. 23)
#[derive(Clone, Eq, PartialEq)]
pub struct Fingerprint([u8; 20]);
impl Fingerprint {
pub fn to_spaced_hex(&self) -> String {
let mut fp = String::new();
for i in 0..20 {
fp.push_str(&format!("{:02X}", self.0[i]));
if i < 19 && (i % 2 == 1) {
fp.push(' ');
}
if i == 9 {
fp.push(' ');
}
}
fp
}
}
/// Helper fn for nom parsing
pub(crate) fn complete<O>(
result: nom::IResult<&[u8], O>,

View file

@ -18,7 +18,7 @@ impl PWStatusBytes {
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 });
data.push(if self.pw1_cds_valid_once { 0 } else { 1 });
if long {
let mut b2 = self.pw1_len;
@ -45,7 +45,7 @@ impl TryFrom<&[u8]> for PWStatusBytes {
fn try_from(input: &[u8]) -> Result<Self, Self::Error> {
if input.len() == 7 {
let pw1_cds_multi = input[0] == 0x01;
let pw1_cds_valid_once = input[0] == 0x00;
let pw1_pin_block = input[1] & 0x80 != 0;
let pw1_len = input[1] & 0x7f;
let rc_len = input[2];
@ -56,7 +56,7 @@ impl TryFrom<&[u8]> for PWStatusBytes {
let err_count_pw3 = input[6];
Ok(Self {
pw1_cds_multi,
pw1_cds_valid_once,
pw1_pin_block,
pw1_len,
rc_len,
@ -90,7 +90,7 @@ mod test {
assert_eq!(
pws,
PWStatusBytes {
pw1_cds_multi: false,
pw1_cds_valid_once: true,
pw1_pin_block: false,
pw1_len: 0x40,
rc_len: 0x40,