Add functionality for cli tools.
This commit is contained in:
parent
1d4f058858
commit
aa7528ec9a
4 changed files with 81 additions and 9 deletions
|
@ -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)?;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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>,
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in a new issue