Files
age-plugin-yubikey/src/native.rs
T
2026-04-07 23:44:03 +01:00

60 lines
1.6 KiB
Rust

use std::marker::PhantomData;
use std::rc::Rc;
use std::sync::RwLock;
use hkdf::Hkdf;
use sha2::Sha256;
use crate::key::Connection;
pub(crate) mod p256tag;
/// Derives a tag for the tagged age recipient formats.
fn stanza_tag(ikm: &[u8], salt: &str) -> [u8; 4] {
let (tag, _) = Hkdf::<Sha256>::extract(Some(salt.as_bytes()), ikm);
tag[..4].try_into().expect("correct length")
}
/// Pretend that a YubiKey connection is a KEM private key.
struct YubiKeyKemPrivateKey<'a, Kem> {
conn: Rc<RwLock<&'a mut Connection>>,
_kem: PhantomData<Kem>,
}
impl<'a, Kem> YubiKeyKemPrivateKey<'a, Kem> {
fn new(conn: &'a mut Connection) -> Self {
Self {
conn: Rc::new(RwLock::new(conn)),
_kem: PhantomData::default(),
}
}
}
impl<'a, Kem> Clone for YubiKeyKemPrivateKey<'a, Kem> {
fn clone(&self) -> Self {
Self {
conn: self.conn.clone(),
_kem: PhantomData::default(),
}
}
}
impl<'a, Kem> PartialEq for YubiKeyKemPrivateKey<'a, Kem> {
fn eq(&self, other: &Self) -> bool {
self.conn.read().unwrap().stub() == other.conn.read().unwrap().stub()
}
}
impl<'a, Kem> Eq for YubiKeyKemPrivateKey<'a, Kem> {}
impl<'a, Kem: hpke::Kem> hpke::Serializable for YubiKeyKemPrivateKey<'a, Kem> {
type OutputSize = <Kem::PrivateKey as hpke::Serializable>::OutputSize;
fn write_exact(&self, _: &mut [u8]) {
unreachable!("Never called")
}
}
impl<'a, Kem: hpke::Kem> hpke::Deserializable for YubiKeyKemPrivateKey<'a, Kem> {
fn from_bytes(_: &[u8]) -> Result<Self, hpke::HpkeError> {
unreachable!("Never called")
}
}