feat: works with errors

This commit is contained in:
2024-08-15 23:19:05 +08:00
parent 5d410e76b2
commit e31190d4e5
7 changed files with 207 additions and 137 deletions

View File

@@ -16,25 +16,24 @@ use std::sync::{Arc, Mutex};
use tracing::instrument;
use x509_cert::der::Encode;
use x509_parser::nom::Parser;
use yubikey::piv::AlgorithmId;
use yubikey::YubiKey;
use native_pkcs11_traits::{Backend, KeySearchOptions};
use crate::piv::slot::SlotObject;
use crate::piv::util::get_algorithm_id_by_certificate;
use native_pkcs11_traits::Certificate as P11Certificate;
use native_pkcs11_traits::KeyAlgorithm as P11KeyAlgorithm;
use native_pkcs11_traits::KeySearchOptions as P11KeySearchOptions;
use native_pkcs11_traits::PrivateKey as P11PrivateKey;
use native_pkcs11_traits::PublicKey as P11PublicKey;
use native_pkcs11_traits::Result as P11Result;
use crate::certificate::YubikeyPivCertificate;
use crate::piv::util::get_algorithm_id_by_certificate;
use native_pkcs11_traits::{Backend, KeyAlgorithm, KeySearchOptions};
#[derive(Debug, Default)]
pub struct YubikeyPivBackend {
cached_pin: Mutex<Option<String>>,
yubikey: Mutex<Option<YubiKey>>,
slot_objects: Mutex<Option<Vec<SlotObject>>>,
}
impl YubikeyPivBackend {
@@ -77,6 +76,53 @@ impl YubikeyPivBackend {
}
Ok(cached_pin.as_deref().unwrap().to_string())
}
fn init_slot_objects(&self) -> P11Result<()> {
let mut slot_objects_opt = self.slot_objects.lock().unwrap();
if slot_objects_opt.is_some() {
return Ok(());
}
let mut slot_objects = vec![];
self.run_with_yubikey(false, |yk| {
let keys = yk.piv_keys()?;
for key in keys {
let slot_id = key.slot().to_string();
let certificate_der = key.certificate().cert.to_der()?;
let public_key_der = key.certificate().cert.tbs_certificate.subject_public_key_info.to_der()?;
let algorithm_id = get_algorithm_id_by_certificate(key.certificate())?;
let algorithm = match algorithm_id {
AlgorithmId::Rsa1024 | AlgorithmId::Rsa2048 => KeyAlgorithm::Rsa,
AlgorithmId::EccP256 | AlgorithmId::EccP384 => KeyAlgorithm::Ecc,
};
// println!(">>> {} {:?} {}", &slot_id, algorithm_id, &key.certificate().cert.tbs_certificate.subject); // TODO remove
let slot_object = SlotObject::new(
algorithm,
slot_id,
certificate_der,
public_key_der,
);
slot_objects.push(slot_object);
}
Ok(())
})?;
*slot_objects_opt = Some(slot_objects);
Ok(())
}
fn for_each_slot_objects<F>(&self, mut callback: F) -> P11Result<()>
where
F: FnMut(&SlotObject) -> P11Result<()>,
{
let slot_objects = &self.slot_objects.lock().unwrap();
for slot_objects in slot_objects.iter() {
for slot_object in slot_objects {
callback(slot_object)?;
}
}
Ok(())
}
}
impl Backend for YubikeyPivBackend {
@@ -88,25 +134,11 @@ impl Backend for YubikeyPivBackend {
fn find_all_certificates(
&self,
) -> P11Result<Vec<Box<dyn P11Certificate>>> {
println!("[find_all_certificates]");
let mut certs = vec![];
self.run_with_yubikey(false, |yk| {
let keys = yk.piv_keys()?;
for key in keys {
let certificate_der = key.certificate().cert.to_der()?;
let public_key_der = key.certificate().cert.tbs_certificate.subject_public_key_info.to_der()?;
let algorithm_id = get_algorithm_id_by_certificate(key.certificate())?;
println!(">>> {:?} {}", algorithm_id, &key.certificate().cert.tbs_certificate.subject);
if algorithm_id == AlgorithmId::EccP256 || algorithm_id == AlgorithmId::EccP384 {
let cert: Box<dyn P11Certificate> = Box::new(YubikeyPivCertificate::new(
key.slot().to_string(),
key.slot().to_string(),
certificate_der,
public_key_der,
)?);
certs.push(cert);
}
}
// println!("[find_all_certificates]");
self.init_slot_objects()?;
let mut certs: Vec<Box<dyn P11Certificate>> = vec![];
self.for_each_slot_objects(|slot_object| {
certs.push(slot_object.to_certificate()?);
Ok(())
})?;
Ok(certs)
@@ -118,16 +150,26 @@ impl Backend for YubikeyPivBackend {
query: P11KeySearchOptions,
) -> P11Result<Option<Arc<dyn P11PrivateKey>>> {
println!("[find_private_key]");
match query {
KeySearchOptions::Label(label) => {
println!(">>> find private key >>>: {}", label);
self.init_slot_objects()?;
let mut private_key: Option<Arc<dyn P11PrivateKey>> = None;
self.for_each_slot_objects(|slot_object| {
if private_key.is_none() {
match &query {
KeySearchOptions::Label(label) => {
if &slot_object.label == label {
private_key = Some(Arc::from(slot_object.to_private_key()?));
}
}
KeySearchOptions::PublicKeyHash(public_key_hash) => {
if hex::encode(&slot_object.public_key_hash) == hex::encode(public_key_hash) {
private_key = Some(Arc::from(slot_object.to_private_key()?));
}
}
}
}
KeySearchOptions::PublicKeyHash(public_key_hash) => {
println!(">>> find private key >>>: {:?}", public_key_hash);
}
}
// TODO ...
Ok(None)
Ok(())
})?;
Ok(private_key)
}
#[instrument]
@@ -136,35 +178,52 @@ impl Backend for YubikeyPivBackend {
query: P11KeySearchOptions,
) -> P11Result<Option<Box<dyn P11PublicKey>>> {
println!("[find_public_key]");
match query {
KeySearchOptions::Label(label) => {
println!(">>> find public key >>>: {}", label);
self.init_slot_objects()?;
let mut public_key: Option<Box<dyn P11PublicKey>> = None;
self.for_each_slot_objects(|slot_object| {
if public_key.is_none() {
match &query {
KeySearchOptions::Label(label) => {
if &slot_object.label == label {
public_key = Some(slot_object.to_public_key()?);
}
}
KeySearchOptions::PublicKeyHash(public_key_hash) => {
if hex::encode(&slot_object.public_key_hash) == hex::encode(public_key_hash) {
public_key = Some(slot_object.to_public_key()?);
}
}
}
}
KeySearchOptions::PublicKeyHash(public_key_hash) => {
println!(">>> find public key >>>: {:?}", public_key_hash);
}
}
// TODO ...
Ok(None)
Ok(())
})?;
Ok(public_key)
}
fn find_all_private_keys(
&self,
) -> P11Result<Vec<Arc<dyn P11PrivateKey>>> {
println!("[find_all_private_keys]");
// TODO ...
Ok(vec![])
self.init_slot_objects()?;
let mut private_keys: Vec<Arc<dyn P11PrivateKey>> = vec![];
self.for_each_slot_objects(|slot_object| {
private_keys.push(Arc::from(slot_object.to_private_key()?));
Ok(())
})?;
Ok(private_keys)
}
fn find_all_public_keys(
&self,
) -> P11Result<Vec<Arc<dyn P11PublicKey>>> {
println!("[find_all_public_keys]");
// self.find_all_certificates().map(|c|{
// c.as_mut().map(|c| )
// })
// TODO ...
Ok(vec![])
self.init_slot_objects()?;
let mut public_keys: Vec<Arc<dyn P11PublicKey>> = vec![];
self.for_each_slot_objects(|slot_object| {
public_keys.push(Arc::from(slot_object.to_public_key()?));
Ok(())
})?;
Ok(public_keys)
}
#[instrument]