From 62f237f859bac23d4e972509789df33e2a6a2602 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Sun, 9 Apr 2023 06:48:57 +0000 Subject: [PATCH] Provide a better error message when management key authentication fails We now indicate to the user that AES management key algorithms are not yet supported, and tell them how to change their management key to use TDES. Closes str4d/age-plugin-yubikey#135. --- i18n/en-US/age_plugin_yubikey.ftl | 6 +++- src/error.rs | 25 +++++++++++++-- src/key.rs | 51 +++++++++++++++++-------------- 3 files changed, 55 insertions(+), 27 deletions(-) diff --git a/i18n/en-US/age_plugin_yubikey.ftl b/i18n/en-US/age_plugin_yubikey.ftl index 9129c7a..42e115d 100644 --- a/i18n/en-US/age_plugin_yubikey.ftl +++ b/i18n/en-US/age_plugin_yubikey.ftl @@ -187,8 +187,12 @@ plugin-err-pin-required = A PIN is required for {-yubikey} with serial {$yub ## Errors +err-mgmt-key-auth = Failed to authenticate with the PIN-protected management key. +rec-mgmt-key-auth = + Check whether your management key is using the TDES algorithm. + AES is not supported yet: {$aes_url} err-custom-mgmt-key = Custom unprotected non-TDES management keys are not supported. -rec-custom-mgmt-key = +rec-change-mgmt-key = You can use the {-yubikey} Manager CLI to change to a protected management key: {" "}{$cmd} diff --git a/src/error.rs b/src/error.rs index 3a48a0b..1674ffa 100644 --- a/src/error.rs +++ b/src/error.rs @@ -21,6 +21,7 @@ pub enum Error { InvalidSlot(u8), InvalidTouchPolicy(String), Io(io::Error), + ManagementKeyAuth, MultipleCommands, MultipleYubiKeys, NoEmptySlots(Serial), @@ -50,12 +51,19 @@ impl From for Error { // manually to provide the error output we want. impl fmt::Debug for Error { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + const CHANGE_MGMT_KEY_CMD: &str = + "ykman piv access change-management-key -a TDES --protect"; + const CHANGE_MGMT_KEY_URL: &str = "https://developers.yubico.com/yubikey-manager/"; + match self { Error::CustomManagementKey => { wlnfl!(f, "err-custom-mgmt-key")?; - let cmd = "ykman piv access change-management-key --protect"; - let url = "https://developers.yubico.com/yubikey-manager/"; - wlnfl!(f, "rec-custom-mgmt-key", cmd = cmd, url = url)?; + wlnfl!( + f, + "rec-change-mgmt-key", + cmd = CHANGE_MGMT_KEY_CMD, + url = CHANGE_MGMT_KEY_URL + )?; } Error::InvalidFlagCommand(flag, command) => wlnfl!( f, @@ -78,6 +86,17 @@ impl fmt::Debug for Error { expected = "always, cached, never", )?, Error::Io(e) => wlnfl!(f, "err-io", err = e.to_string())?, + Error::ManagementKeyAuth => { + let aes_url = "https://github.com/str4d/age-plugin-yubikey/issues/92"; + wlnfl!(f, "err-mgmt-key-auth")?; + wlnfl!(f, "rec-mgmt-key-auth", aes_url = aes_url)?; + wlnfl!( + f, + "rec-change-mgmt-key", + cmd = CHANGE_MGMT_KEY_CMD, + url = CHANGE_MGMT_KEY_URL + )?; + } Error::MultipleCommands => wlnfl!(f, "err-multiple-commands")?, Error::MultipleYubiKeys => wlnfl!(f, "err-multiple-yubikeys")?, Error::NoEmptySlots(serial) => { diff --git a/src/key.rs b/src/key.rs index b942c21..d86a0ad 100644 --- a/src/key.rs +++ b/src/key.rs @@ -354,30 +354,35 @@ pub(crate) fn manage(yubikey: &mut YubiKey) -> Result<(), Error> { yubikey.change_pin(pin.as_bytes(), new_pin.as_bytes())?; } - if let Ok(mgm_key) = MgmKey::get_protected(yubikey) { - yubikey.authenticate(mgm_key)?; - } else { - // Try to authenticate with the default management key. - yubikey - .authenticate(MgmKey::default()) - .map_err(|_| Error::CustomManagementKey)?; + match MgmKey::get_protected(yubikey) { + Ok(mgm_key) => yubikey.authenticate(mgm_key).map_err(|e| match e { + yubikey::Error::AuthenticationError => Error::ManagementKeyAuth, + _ => e.into(), + })?, + Err(yubikey::Error::AuthenticationError) => Err(Error::ManagementKeyAuth)?, + _ => { + // Try to authenticate with the default management key. + yubikey + .authenticate(MgmKey::default()) + .map_err(|_| Error::CustomManagementKey)?; - // Migrate to a PIN-protected management key. - let mgm_key = MgmKey::generate(); - eprintln!(); - eprintln!("{}", fl!("mgr-changing-mgmt-key")); - eprint!("... "); - mgm_key.set_protected(yubikey).map_err(|e| { - eprintln!( - "{}", - fl!( - "mgr-changing-mgmt-key-error", - management_key = hex::encode(mgm_key.as_ref()), - ) - ); - e - })?; - eprintln!("{}", fl!("mgr-changing-mgmt-key-success")); + // Migrate to a PIN-protected management key. + let mgm_key = MgmKey::generate(); + eprintln!(); + eprintln!("{}", fl!("mgr-changing-mgmt-key")); + eprint!("... "); + mgm_key.set_protected(yubikey).map_err(|e| { + eprintln!( + "{}", + fl!( + "mgr-changing-mgmt-key-error", + management_key = hex::encode(mgm_key.as_ref()), + ) + ); + e + })?; + eprintln!("{}", fl!("mgr-changing-mgmt-key-success")); + } } Ok(())