use super::{symmetric_key::SymmetricKey, KeyToSource};
use anyhow::Result;
use infinitree::crypto::yubikey::{
yubico_manager::{config::*, *},
YubikeyCR,
};
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct YubikeyCRKey {
#[serde(flatten)]
pub credentials: SymmetricKey,
#[serde(flatten)]
pub config: YubikeyCRConfig,
}
impl KeyToSource for YubikeyCRKey {
type Target = YubikeyCR;
fn to_keysource(self, stash: &str) -> Result<Self::Target> {
let mut yk = Yubico::new();
let device = yk.find_yubikey()?;
let mut ykconfig = Config::default()
.set_product_id(device.product_id)
.set_vendor_id(device.vendor_id);
if let Some(slot) = self.config.slot {
ykconfig = ykconfig.set_slot(match slot {
YubikeyCRSlot::Slot1 => Slot::Slot1,
YubikeyCRSlot::Slot2 => Slot::Slot2,
});
}
if let Some(key) = self.config.key {
ykconfig = ykconfig.set_command(match key {
YubikeyCRHmac::Hmac1 => Command::ChallengeHmac1,
YubikeyCRHmac::Hmac2 => Command::ChallengeHmac2,
});
}
let (user, pw) = self.credentials.interactive_credentials(stash)?;
Ok(YubikeyCR::with_credentials(user, pw, ykconfig)?)
}
}
#[derive(clap::Args, Default, Clone, Debug, Deserialize, Serialize)]
pub struct YubikeyCRConfig {
#[serde(default)]
#[clap(value_enum)]
pub slot: Option<YubikeyCRSlot>,
#[serde(default)]
#[clap(value_enum)]
pub key: Option<YubikeyCRHmac>,
}
#[derive(clap::ValueEnum, Clone, Debug, Deserialize, Serialize)]
pub enum YubikeyCRSlot {
#[serde(rename = "slot1")]
Slot1,
#[serde(rename = "slot2")]
Slot2,
}
#[derive(clap::ValueEnum, Clone, Debug, Deserialize, Serialize)]
pub enum YubikeyCRHmac {
#[serde(rename = "hmac1")]
Hmac1,
#[serde(rename = "hmac2")]
Hmac2,
}