Implement --generate command

Includes logic to help users manage their keys:

- If the key is using a default PIN, we require the user to change it.
- We set the PUK equal to the PIN so the user doesn't need to remember
  them separately.
- We migrate the default management key to a new PIN-protected key.
This commit is contained in:
Jack Grigg
2021-01-03 19:47:10 +00:00
parent eedf9fa997
commit 850f96cd2c
7 changed files with 341 additions and 4 deletions
+33
View File
@@ -5,14 +5,20 @@ use yubikey_piv::{key::RetiredSlotId, Serial};
use crate::USABLE_SLOTS;
pub enum Error {
CustomManagementKey,
InvalidPinLength,
InvalidPinPolicy(String),
InvalidSlot(u8),
InvalidTouchPolicy(String),
Io(io::Error),
MultipleCommands,
MultipleIdentities,
MultipleYubiKeys,
NoEmptySlots(Serial),
NoIdentities,
NoMatchingSerial(Serial),
SlotHasNoIdentity(RetiredSlotId),
SlotIsNotEmpty(RetiredSlotId),
TimedOut,
YubiKey(yubikey_piv::Error),
}
@@ -34,11 +40,25 @@ impl From<yubikey_piv::error::Error> for Error {
impl fmt::Debug for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Error::CustomManagementKey => {
writeln!(f, "Custom unprotected management keys are not supported.")?
}
Error::InvalidPinLength => writeln!(f, "The PIN needs to be 1-8 characters.")?,
Error::InvalidPinPolicy(s) => writeln!(
f,
"Invalid PIN policy '{}' (expected [always, once, never]).",
s
)?,
Error::InvalidSlot(slot) => writeln!(
f,
"Invalid slot '{}' (expected number between 1 and 20).",
slot
)?,
Error::InvalidTouchPolicy(s) => writeln!(
f,
"Invalid touch policy '{}' (expected [always, cached, never]).",
s
)?,
Error::Io(e) => writeln!(f, "Failed to set up YubiKey: {}", e)?,
Error::MultipleCommands => writeln!(
f,
@@ -52,6 +72,9 @@ impl fmt::Debug for Error {
f,
"Multiple YubiKeys are plugged in. Use --serial to select a single YubiKey."
)?,
Error::NoEmptySlots(serial) => {
writeln!(f, "YubiKey with serial {} has no empty slots.", serial)?
}
Error::NoIdentities => {
writeln!(f, "This YubiKey does not contain any age identities.")?
}
@@ -63,6 +86,11 @@ impl fmt::Debug for Error {
"Slot {} does not contain an age identity or compatible key.",
USABLE_SLOTS.iter().position(|s| s == slot).unwrap() + 1
)?,
Error::SlotIsNotEmpty(slot) => writeln!(
f,
"Slot {} is not empty. Use --force to overwrite the slot.",
USABLE_SLOTS.iter().position(|s| s == slot).unwrap() + 1
)?,
Error::TimedOut => {
writeln!(f, "Timed out while waiting for a YubiKey to be inserted.")?
}
@@ -70,6 +98,11 @@ impl fmt::Debug for Error {
yubikey_piv::error::Error::NotFound => {
writeln!(f, "Please insert the YubiKey you want to set up")?
}
yubikey_piv::error::Error::WrongPin { tries } => writeln!(
f,
"Invalid PIN ({} tries remaining before it is blocked)",
tries
)?,
e => {
writeln!(f, "Error while communicating with YubiKey: {}", e)?;
use std::error::Error;