diff --git a/openpgp-card/src/apdu/commands.rs b/openpgp-card/src/apdu/commands.rs index 0ee3d2f..5d662b7 100644 --- a/openpgp-card/src/apdu/commands.rs +++ b/openpgp-card/src/apdu/commands.rs @@ -139,18 +139,35 @@ pub(crate) fn put_cardholder_certificate(data: Vec) -> Command { put_data(&[0x7F, 0x21], data) } -/// Change PW1 (user pin). -/// This can be used to reset the counter and set a pin. -pub(crate) fn change_pw1(pin: Vec) -> Command { - Command::new(0x00, 0x2C, 0x02, 0x81, pin) +/// "RESET RETRY COUNTER" (PW1, user pin) +/// Reset the counter of PW1 and set a new pin. +pub(crate) fn reset_retry_counter_pw1( + resetting_code: Option>, + new_pin: Vec, +) -> Command { + if let Some(resetting_code) = resetting_code { + // Present the Resetting Code (DO D3) in the command data (P1 = 00) + + // Data field: Resetting Code + New PW + let mut data = resetting_code; + data.extend(new_pin); + + Command::new(0x00, 0x2C, 0x00, 0x81, data) + } else { + // Use after correct verification of PW3 (P1 = 02) + // (Usage of secure messaging is equivalent to PW3) + Command::new(0x00, 0x2C, 0x02, 0x81, new_pin) + } } -/// Change PW3 (admin pin) -pub(crate) fn change_pw3(oldpin: Vec, newpin: Vec) -> Command { - let mut fullpin = oldpin; - fullpin.extend(newpin.iter()); +/// "CHANGE REFERENCE DATA" - change PW1 (user pin) +pub(crate) fn change_pw1(data: Vec) -> Command { + Command::new(0x00, 0x24, 0x00, 0x81, data) +} - Command::new(0x00, 0x24, 0x00, 0x83, fullpin) +/// "CHANGE REFERENCE DATA" - change PW3 (admin pin) +pub(crate) fn change_pw3(data: Vec) -> Command { + Command::new(0x00, 0x24, 0x00, 0x83, data) } /// 7.2.10 PSO: COMPUTE DIGITAL SIGNATURE diff --git a/openpgp-card/src/card_app.rs b/openpgp-card/src/card_app.rs index 6553adc..63d4363 100644 --- a/openpgp-card/src/card_app.rs +++ b/openpgp-card/src/card_app.rs @@ -359,6 +359,54 @@ impl CardApp { apdu::send_command(&mut self.card_client, verify, false)?.try_into() } + /// Change the value of PW1 (user password). + /// + /// The current value of PW1 must be presented in `old` for authorization. + pub fn change_pw1( + &mut self, + old: &str, + new: &str, + ) -> Result { + let mut data = vec![]; + data.extend(old.as_bytes()); + data.extend(new.as_bytes()); + + let change = commands::change_pw1(data); + apdu::send_command(&mut self.card_client, change, false)?.try_into() + } + + /// Change the value of PW3 (admin password). + /// + /// The current value of PW3 must be presented in `old` for authorization. + pub fn change_pw3( + &mut self, + old: &str, + new: &str, + ) -> Result { + let mut data = vec![]; + data.extend(old.as_bytes()); + data.extend(new.as_bytes()); + + let change = commands::change_pw3(data); + apdu::send_command(&mut self.card_client, change, false)?.try_into() + } + + /// Reset the error counter for PW1 (user password) and set a new value + /// for PW1. + /// + /// For authorization, either: + /// - PW3 must have been verified previously, + /// - secure messaging must be currently used, + /// - the resetting_code must be presented. + pub fn reset_retry_counter_pw1( + &mut self, + new_pw1: Vec, + resetting_code: Option>, + ) -> Result { + let reset = commands::reset_retry_counter_pw1(resetting_code, new_pw1); + apdu::send_command(&mut self.card_client, reset, false)?.try_into() + } + // --- decrypt --- /// Decrypt the ciphertext in `dm`, on the card. @@ -581,6 +629,16 @@ impl CardApp { apdu::send_command(&mut self.card_client, cmd, false)?.try_into() } + /// Set resetting code + /// (4.3.4 Resetting Code) + pub fn set_resetting_code( + &mut self, + resetting_code: Vec, + ) -> Result { + let cmd = commands::put_data(&[0xd3], resetting_code); + apdu::send_command(&mut self.card_client, cmd, false)?.try_into() + } + /// Import an existing private key to the card. /// (This implicitly sets the algorithm info, fingerprint and timestamp) pub fn key_import(