openpgp-card: allow additional status in factory reset

The opcard-rs implementation may return StatusBytes::ExecutionErrorNonVolatileMemoryUnchanged in some circumstances.

Also see https://gitlab.com/openpgp-card/openpgp-card/-/issues/70

Fixes #70
This commit is contained in:
Heiko Schaefer 2023-09-02 16:46:56 +02:00
parent 82662e6d46
commit 4d5d9e7ee1
No known key found for this signature in database
GPG key ID: 4A849A1904CCBD7D
2 changed files with 25 additions and 16 deletions

View file

@ -73,6 +73,9 @@ pub enum StatusBytes {
#[error("Password not checked, {0} allowed retries")] #[error("Password not checked, {0} allowed retries")]
PasswordNotChecked(u8), PasswordNotChecked(u8),
#[error("Execution error with non-volatile memory unchanged")]
ExecutionErrorNonVolatileMemoryUnchanged,
#[error("Triggering by the card {0}")] #[error("Triggering by the card {0}")]
TriggeringByCard(u8), TriggeringByCard(u8),
@ -145,6 +148,7 @@ impl From<(u8, u8)> for StatusBytes {
(0x62, 0x85) => StatusBytes::TerminationState, (0x62, 0x85) => StatusBytes::TerminationState,
(0x63, 0xC0..=0xCF) => StatusBytes::PasswordNotChecked(status.1 & 0xf), (0x63, 0xC0..=0xCF) => StatusBytes::PasswordNotChecked(status.1 & 0xf),
(0x64, 0x00) => StatusBytes::ExecutionErrorNonVolatileMemoryUnchanged,
(0x64, 0x02..=0x80) => StatusBytes::TriggeringByCard(status.1), (0x64, 0x02..=0x80) => StatusBytes::TriggeringByCard(status.1),
(0x65, 0x01) => StatusBytes::MemoryFailure, (0x65, 0x01) => StatusBytes::MemoryFailure,
(0x66, 0x00) => StatusBytes::SecurityRelatedIssues, (0x66, 0x00) => StatusBytes::SecurityRelatedIssues,

View file

@ -661,15 +661,18 @@ impl<'a> Transaction<'a> {
log::info!("OpenPgpTransaction: factory_reset"); log::info!("OpenPgpTransaction: factory_reset");
// send 4 bad requests to verify pw1 // send 4 bad requests to verify pw1
// [apdu 00 20 00 81 08 40 40 40 40 40 40 40 40]
for _ in 0..4 { for _ in 0..4 {
log::info!(" verify_pw1_81"); let resp = self.verify_pw1_sign(&[0x40; 8]);
let verify = commands::verify_pw1_81([0x40; 8].to_vec());
let resp = self.send_command(verify, false)?; if !(matches!(
if !(resp.status() == StatusBytes::SecurityStatusNotSatisfied resp,
|| resp.status() == StatusBytes::AuthenticationMethodBlocked Err(Error::CardStatus(StatusBytes::SecurityStatusNotSatisfied))
|| matches!(resp.status(), StatusBytes::PasswordNotChecked(_))) | Err(Error::CardStatus(StatusBytes::AuthenticationMethodBlocked))
{ | Err(Error::CardStatus(
StatusBytes::ExecutionErrorNonVolatileMemoryUnchanged
))
| Err(Error::CardStatus(StatusBytes::PasswordNotChecked(_)))
)) {
return Err(Error::InternalError( return Err(Error::InternalError(
"Unexpected status for reset, at pw1.".into(), "Unexpected status for reset, at pw1.".into(),
)); ));
@ -677,16 +680,18 @@ impl<'a> Transaction<'a> {
} }
// send 4 bad requests to verify pw3 // send 4 bad requests to verify pw3
// [apdu 00 20 00 83 08 40 40 40 40 40 40 40 40]
for _ in 0..4 { for _ in 0..4 {
log::info!(" verify_pw3"); let resp = self.verify_pw3(&[0x40; 8]);
let verify = commands::verify_pw3([0x40; 8].to_vec());
let resp = self.send_command(verify, false)?;
if !(resp.status() == StatusBytes::SecurityStatusNotSatisfied if !(matches!(
|| resp.status() == StatusBytes::AuthenticationMethodBlocked resp,
|| matches!(resp.status(), StatusBytes::PasswordNotChecked(_))) Err(Error::CardStatus(StatusBytes::SecurityStatusNotSatisfied))
{ | Err(Error::CardStatus(StatusBytes::AuthenticationMethodBlocked))
| Err(Error::CardStatus(
StatusBytes::ExecutionErrorNonVolatileMemoryUnchanged
))
| Err(Error::CardStatus(StatusBytes::PasswordNotChecked(_)))
)) {
return Err(Error::InternalError( return Err(Error::InternalError(
"Unexpected status for reset, at pw3.".into(), "Unexpected status for reset, at pw3.".into(),
)); ));