diff --git a/src/apdu.rs b/src/apdu.rs index 954e9f34..67b69c6c 100644 --- a/src/apdu.rs +++ b/src/apdu.rs @@ -210,6 +210,9 @@ pub enum Ins { /// YubiHSM Auth // Put credential PutCredential, + /// YubiHSM Auth // Delete credential + DeleteCredential, + /// Other/unrecognized instruction codes Other(u8), } @@ -237,6 +240,7 @@ impl Ins { Ins::GetMetadata => 0xf7, // Yubihsm auth Ins::PutCredential => 0x01, + Ins::DeleteCredential => 0x02, Ins::Calculate => 0x03, Ins::GetHostChallenge => 0x04, Ins::ListCredentials => 0x05, @@ -249,6 +253,7 @@ impl From for Ins { fn from(code: u8) -> Self { match code { 0x01 => Ins::PutCredential, + 0x02 => Ins::DeleteCredential, 0x03 => Ins::Calculate, 0x04 => Ins::GetHostChallenge, 0x05 => Ins::ListCredentials, diff --git a/src/hsmauth.rs b/src/hsmauth.rs index 89881e39..9ac41de9 100644 --- a/src/hsmauth.rs +++ b/src/hsmauth.rs @@ -149,6 +149,15 @@ impl HsmAuth { ) } + /// Delete credential + pub fn delete_credential(&mut self, mgmkey: Option, label: Label) -> Result<()> { + Transaction::new(&mut self.client.card)?.delete_credential( + self.client.version, + mgmkey.unwrap_or(MgmKey::default()), + label, + ) + } + /// Retun the inner `YubiKey` pub fn into_inner(mut self) -> Result { Transaction::new(&mut self.client.card)?.select_piv_application()?; diff --git a/src/transaction.rs b/src/transaction.rs index d2550cb1..f0b77f7f 100644 --- a/src/transaction.rs +++ b/src/transaction.rs @@ -708,4 +708,51 @@ impl<'tx> Transaction<'tx> { Ok(()) } + + /// Delete a credential to YubiHSM Auth applet + pub fn delete_credential( + &mut self, + version: Version, + mgmkey: hsmauth::MgmKey, + label: Label, + ) -> Result<()> { + // YubiHSM was introduced by firmware 5.4.3 + // https://docs.yubico.com/yesdk/users-manual/application-yubihsm-auth/yubihsm-auth-overview.html + if version + < (Version { + major: 5, + minor: 4, + patch: 3, + }) + { + return Err(Error::NotSupported); + } + + let mut data = [0u8; CB_BUF_MAX]; + let mut len = data.len(); + let mut data_remaining = &mut data[..]; + + let offset = Tlv::write(data_remaining, TAG_MGMKEY, &mgmkey.0)?; + data_remaining = &mut data_remaining[offset..]; + + let offset = Tlv::write(data_remaining, TAG_LABEL, &label.0)?; + data_remaining = &mut data_remaining[offset..]; + + len -= data_remaining.len(); + + let response = Apdu::new(Ins::DeleteCredential) + .params(0x00, 0x00) + .data(&data[..len]) + .transmit(self, 2)?; + + if !response.is_success() { + error!( + "Unable to delete credential: {:04x}", + response.status_words().code() + ); + return Err(Error::GenericError); + } + + Ok(()) + } }