From 27d3610293330b74b292474b0269a5f65228cac2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sosth=C3=A8ne=20Gu=C3=A9don?= Date: Tue, 3 Jan 2023 14:24:31 +0100 Subject: [PATCH 1/6] Fix gpg not detecting the card when the state is corrupted Fix https://github.com/Nitrokey/opcard-rs/issues/102 --- src/command/data.rs | 143 ++++++++++++++++++++++++++++++++------------ 1 file changed, 104 insertions(+), 39 deletions(-) diff --git a/src/command/data.rs b/src/command/data.rs index 42e64ec..a20d2f6 100644 --- a/src/command/data.rs +++ b/src/command/data.rs @@ -348,29 +348,29 @@ impl GetDataObject { match self { Self::HistoricalBytes => historical_bytes(context)?, Self::ApplicationIdentifier => context.reply.expand(&context.options.aid())?, - Self::PwStatusBytes => pw_status_bytes(context.load_state()?)?, + Self::PwStatusBytes => pw_status_bytes(context)?, Self::ExtendedLengthInformation => context.reply.expand(&EXTENDED_LENGTH_INFO)?, Self::ExtendedCapabilities => context.reply.expand(&EXTENDED_CAPABILITIES)?, Self::GeneralFeatureManagement => context .reply .expand(&general_feature_management(context.options))?, - Self::AlgorithmAttributesSignature => alg_attr_sign(context.load_state()?)?, - Self::AlgorithmAttributesDecryption => alg_attr_dec(context.load_state()?)?, - Self::AlgorithmAttributesAuthentication => alg_attr_aut(context.load_state()?)?, + Self::AlgorithmAttributesSignature => alg_attr_sign(context)?, + Self::AlgorithmAttributesDecryption => alg_attr_dec(context)?, + Self::AlgorithmAttributesAuthentication => alg_attr_aut(context)?, Self::AlgorithmInformation => algo_info(context)?, - Self::Fingerprints => fingerprints(context.load_state()?)?, - Self::CAFingerprints => ca_fingerprints(context.load_state()?)?, - Self::KeyGenerationDates => keygen_dates(context.load_state()?)?, - Self::KeyInformation => key_info(context.load_state()?)?, - Self::UifCds => uif(context.load_state()?, KeyType::Sign)?, - Self::UifDec => uif(context.load_state()?, KeyType::Dec)?, - Self::UifAut => uif(context.load_state()?, KeyType::Aut)?, - Self::CardHolderName => cardholder_name(context.load_state()?)?, - Self::CardHolderSex => cardholder_sex(context.load_state()?)?, - Self::LanguagePreferences => language_preferences(context.load_state()?)?, + Self::Fingerprints => fingerprints(context)?, + Self::CAFingerprints => ca_fingerprints(context)?, + Self::KeyGenerationDates => keygen_dates(context)?, + Self::KeyInformation => key_info(context)?, + Self::UifCds => uif(context, KeyType::Sign)?, + Self::UifDec => uif(context, KeyType::Dec)?, + Self::UifAut => uif(context, KeyType::Aut)?, + Self::CardHolderName => cardholder_name(context)?, + Self::CardHolderSex => cardholder_sex(context)?, + Self::LanguagePreferences => language_preferences(context)?, Self::Url => get_arbitrary_do(context, ArbitraryDO::Url)?, Self::LoginData => get_arbitrary_do(context, ArbitraryDO::LoginData)?, - Self::DigitalSignatureCounter => signature_counter(context.load_state()?)?, + Self::DigitalSignatureCounter => signature_counter(context)?, Self::KdfDo => get_arbitrary_do(context, ArbitraryDO::KdfDo)?, Self::PrivateUse1 => get_arbitrary_do(context, ArbitraryDO::PrivateUse1)?, Self::PrivateUse2 => get_arbitrary_do(context, ArbitraryDO::PrivateUse2)?, @@ -555,18 +555,32 @@ fn cardholder_cert( } fn pw_status_bytes( - mut ctx: LoadedContext<'_, R, T>, + mut ctx: Context<'_, R, T>, ) -> Result<(), Status> { - let status = PasswordStatus { - pw1_valid_multiple: ctx.state.internal.pw1_valid_multiple(), - max_length_pw1: MAX_PIN_LENGTH as u8, - max_length_rc: MAX_PIN_LENGTH as u8, - max_length_pw3: MAX_PIN_LENGTH as u8, - error_counter_pw1: ctx.state.internal.remaining_tries(Password::Pw1), - // TODO when implementing RESET RETRY COUNTER - error_counter_rc: 3, - error_counter_pw3: ctx.state.internal.remaining_tries(Password::Pw3), + let status = if let Ok(ctx) = ctx.load_state() { + PasswordStatus { + pw1_valid_multiple: ctx.state.internal.pw1_valid_multiple(), + max_length_pw1: MAX_PIN_LENGTH as u8, + max_length_rc: MAX_PIN_LENGTH as u8, + max_length_pw3: MAX_PIN_LENGTH as u8, + error_counter_pw1: ctx.state.internal.remaining_tries(Password::Pw1), + // TODO when implementing RESET RETRY COUNTER + error_counter_rc: 3, + error_counter_pw3: ctx.state.internal.remaining_tries(Password::Pw3), + } + } else { + // If the state doesn't load, return placeholder so that gpg presents the option to factory reset + PasswordStatus { + pw1_valid_multiple: false, + max_length_pw1: MAX_PIN_LENGTH as u8, + max_length_rc: MAX_PIN_LENGTH as u8, + max_length_pw3: MAX_PIN_LENGTH as u8, + error_counter_pw1: 3, + error_counter_rc: 3, + error_counter_pw3: 3, + } }; + let status: [u8; 7] = status.into(); ctx.reply.expand(&status) } @@ -594,46 +608,72 @@ fn algo_info(mut ctx: Context<'_, R, T>) -> } fn alg_attr_sign( - mut ctx: LoadedContext<'_, R, T>, + mut ctx: Context<'_, R, T>, ) -> Result<(), Status> { + let Ok(mut ctx) = ctx.load_state() else { + // If the state doesn't load, return placeholder so that gpg presents the option to factory reset + return ctx.reply.expand(SignatureAlgorithm::default().attributes()); + }; + ctx.reply .expand(ctx.state.internal.sign_alg().attributes())?; Ok(()) } fn alg_attr_dec( - mut ctx: LoadedContext<'_, R, T>, + mut ctx: Context<'_, R, T>, ) -> Result<(), Status> { + let Ok(mut ctx) = ctx.load_state() else { + // If the state doesn't load, return placeholder so that gpg presents the option to factory reset + return ctx.reply.expand(DecryptionAlgorithm::default().attributes()); + }; + ctx.reply .expand(ctx.state.internal.dec_alg().attributes())?; Ok(()) } fn alg_attr_aut( - mut ctx: LoadedContext<'_, R, T>, + mut ctx: Context<'_, R, T>, ) -> Result<(), Status> { + let Ok(mut ctx) = ctx.load_state() else { + // If the state doesn't load, return placeholder so that gpg presents the option to factory reset + return ctx.reply.expand(AuthenticationAlgorithm::default().attributes()); + }; ctx.reply .expand(ctx.state.internal.aut_alg().attributes())?; Ok(()) } fn fingerprints( - mut ctx: LoadedContext<'_, R, T>, + mut ctx: Context<'_, R, T>, ) -> Result<(), Status> { + let Ok(mut ctx) = ctx.load_state() else { + // If the state doesn't load, return placeholder so that gpg presents the option to factory reset + return ctx.reply.expand(&[0;60]); + }; ctx.reply.expand(&ctx.state.internal.fingerprints().0)?; Ok(()) } fn ca_fingerprints( - mut ctx: LoadedContext<'_, R, T>, + mut ctx: Context<'_, R, T>, ) -> Result<(), Status> { + let Ok(mut ctx) = ctx.load_state() else { + // If the state doesn't load, return placeholder so that gpg presents the option to factory reset + return ctx.reply.expand(&[0;60]); + }; ctx.reply.expand(&ctx.state.internal.ca_fingerprints().0)?; Ok(()) } fn keygen_dates( - mut ctx: LoadedContext<'_, R, T>, + mut ctx: Context<'_, R, T>, ) -> Result<(), Status> { + let Ok(mut ctx) = ctx.load_state() else { + // If the state doesn't load, return placeholder so that gpg presents the option to factory reset + return ctx.reply.expand(&[0;12]); + }; ctx.reply.expand(&ctx.state.internal.keygen_dates().0)?; Ok(()) } @@ -646,9 +686,11 @@ fn key_info_byte(data: Option) -> u8 { } } -fn key_info( - mut ctx: LoadedContext<'_, R, T>, -) -> Result<(), Status> { +fn key_info(mut ctx: Context<'_, R, T>) -> Result<(), Status> { + let Ok(mut ctx) = ctx.load_state() else { + // If the state doesn't load, return placeholder so that gpg presents the option to factory reset + return ctx.reply.expand(&hex!("010002000300")); + }; // Key-Ref. : Sig = 1, Dec = 2, Aut = 3 (see §7.2.18) ctx.reply.expand(&[ 0x01, @@ -666,9 +708,14 @@ fn key_info( } fn uif( - mut ctx: LoadedContext<'_, R, T>, + mut ctx: Context<'_, R, T>, key: KeyType, ) -> Result<(), Status> { + let Ok(mut ctx) = ctx.load_state() else { + // If the state doesn't load, return placeholder so that gpg presents the option to factory reset + return ctx.reply.expand(&[Uif::Disabled as u8, general_feature_management_byte(ctx.options)]); + }; + if !ctx.options.button_available { warn!("GET DAT for uif without a button available"); return Err(Status::FunctionNotSupported); @@ -680,28 +727,46 @@ fn uif( } fn cardholder_name( - mut ctx: LoadedContext<'_, R, T>, + mut ctx: Context<'_, R, T>, ) -> Result<(), Status> { + let Ok(mut ctx) = ctx.load_state() else { + // If the state doesn't load, return placeholder so that gpg presents the option to factory reset + return ctx.reply.expand(b"Card state corrupted. Factory reset recommended"); + }; ctx.reply.expand(ctx.state.internal.cardholder_name()) } fn cardholder_sex( - mut ctx: LoadedContext<'_, R, T>, + mut ctx: Context<'_, R, T>, ) -> Result<(), Status> { + let Ok(mut ctx) = ctx.load_state() else { + // If the state doesn't load, return placeholder so that gpg presents the option to factory reset + return ctx.reply + .expand(&[Sex::NotKnown as u8]) + }; ctx.reply .expand(&[ctx.state.internal.cardholder_sex() as u8]) } fn language_preferences( - mut ctx: LoadedContext<'_, R, T>, + mut ctx: Context<'_, R, T>, ) -> Result<(), Status> { + let Ok(mut ctx) = ctx.load_state() else { + // If the state doesn't load, return placeholder so that gpg presents the option to factory reset + return ctx.reply.expand(b""); + }; ctx.reply.expand(ctx.state.internal.language_preferences()) } fn signature_counter( - mut ctx: LoadedContext<'_, R, T>, + mut ctx: Context<'_, R, T>, ) -> Result<(), Status> { // Counter is only on 3 bytes + let Ok(mut ctx) = ctx.load_state() else { + // If the state doesn't load, return placeholder so that gpg presents the option to factory reset + return ctx.reply.expand(&0u32.to_be_bytes()[1..]); + }; + let resp = &ctx.state.internal.sign_count().to_be_bytes()[1..]; ctx.reply.expand(resp) } From a7bb1e933fa1eb8541ee4f173d7e14e35f8ce612 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sosth=C3=A8ne=20Gu=C3=A9don?= Date: Tue, 3 Jan 2023 14:26:26 +0100 Subject: [PATCH 2/6] Fix clippy warnings --- src/tlv.rs | 2 +- tests/command-response.rs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/tlv.rs b/src/tlv.rs index 372216c..4d94519 100644 --- a/src/tlv.rs +++ b/src/tlv.rs @@ -69,7 +69,7 @@ pub fn take_len(data: &[u8]) -> Option<(usize, &[u8])> { let l2 = *data.get(1)?; let l3 = *data.get(2)?; let len = u16::from_be_bytes([l2, l3]) as usize; - Some((len as usize, &data[3..])) + Some((len, &data[3..])) } } diff --git a/tests/command-response.rs b/tests/command-response.rs index 6a8fcdb..0d0ef98 100644 --- a/tests/command-response.rs +++ b/tests/command-response.rs @@ -294,7 +294,7 @@ impl Default for OutputMatcher { fn parse_hex(data: &str) -> Vec { let tmp: String = data.split_whitespace().collect(); - hex::decode(&tmp).unwrap() + hex::decode(tmp).unwrap() } impl OutputMatcher { @@ -417,7 +417,7 @@ impl IoCmd { println!("Command: {:x?}", input); let mut rep: heapless::Vec = heapless::Vec::new(); let cmd: iso7816::Command<1024> = iso7816::Command::try_from(input).unwrap_or_else(|err| { - panic!("Bad command: {err:?}, for command: {}", hex::encode(&input)) + panic!("Bad command: {err:?}, for command: {}", hex::encode(input)) }); let status: Status = card .handle(&cmd, &mut rep) From c20b6318532abfbaa7c704b1f5f4fd34795724e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sosth=C3=A8ne=20Gu=C3=A9don?= Date: Tue, 3 Jan 2023 14:56:32 +0100 Subject: [PATCH 3/6] Fix MSRV --- src/command/data.rs | 170 +++++++++++++++++++++++--------------------- 1 file changed, 87 insertions(+), 83 deletions(-) diff --git a/src/command/data.rs b/src/command/data.rs index a20d2f6..e0768fd 100644 --- a/src/command/data.rs +++ b/src/command/data.rs @@ -610,72 +610,69 @@ fn algo_info(mut ctx: Context<'_, R, T>) -> fn alg_attr_sign( mut ctx: Context<'_, R, T>, ) -> Result<(), Status> { - let Ok(mut ctx) = ctx.load_state() else { + if let Ok(mut ctx) = ctx.load_state() { + ctx.reply.expand(ctx.state.internal.sign_alg().attributes()) + } else { // If the state doesn't load, return placeholder so that gpg presents the option to factory reset - return ctx.reply.expand(SignatureAlgorithm::default().attributes()); - }; - - ctx.reply - .expand(ctx.state.internal.sign_alg().attributes())?; - Ok(()) + ctx.reply.expand(SignatureAlgorithm::default().attributes()) + } } fn alg_attr_dec( mut ctx: Context<'_, R, T>, ) -> Result<(), Status> { - let Ok(mut ctx) = ctx.load_state() else { + if let Ok(mut ctx) = ctx.load_state() { + ctx.reply.expand(ctx.state.internal.dec_alg().attributes()) + } else { // If the state doesn't load, return placeholder so that gpg presents the option to factory reset - return ctx.reply.expand(DecryptionAlgorithm::default().attributes()); - }; - - ctx.reply - .expand(ctx.state.internal.dec_alg().attributes())?; - Ok(()) + ctx.reply + .expand(DecryptionAlgorithm::default().attributes()) + } } fn alg_attr_aut( mut ctx: Context<'_, R, T>, ) -> Result<(), Status> { - let Ok(mut ctx) = ctx.load_state() else { + if let Ok(mut ctx) = ctx.load_state() { + ctx.reply.expand(ctx.state.internal.aut_alg().attributes()) + } else { // If the state doesn't load, return placeholder so that gpg presents the option to factory reset - return ctx.reply.expand(AuthenticationAlgorithm::default().attributes()); - }; - ctx.reply - .expand(ctx.state.internal.aut_alg().attributes())?; - Ok(()) + ctx.reply + .expand(AuthenticationAlgorithm::default().attributes()) + } } fn fingerprints( mut ctx: Context<'_, R, T>, ) -> Result<(), Status> { - let Ok(mut ctx) = ctx.load_state() else { + if let Ok(mut ctx) = ctx.load_state() { + ctx.reply.expand(&ctx.state.internal.fingerprints().0) + } else { // If the state doesn't load, return placeholder so that gpg presents the option to factory reset - return ctx.reply.expand(&[0;60]); - }; - ctx.reply.expand(&ctx.state.internal.fingerprints().0)?; - Ok(()) + ctx.reply.expand(&[0; 60]) + } } fn ca_fingerprints( mut ctx: Context<'_, R, T>, ) -> Result<(), Status> { - let Ok(mut ctx) = ctx.load_state() else { + if let Ok(mut ctx) = ctx.load_state() { + ctx.reply.expand(&ctx.state.internal.ca_fingerprints().0) + } else { // If the state doesn't load, return placeholder so that gpg presents the option to factory reset - return ctx.reply.expand(&[0;60]); - }; - ctx.reply.expand(&ctx.state.internal.ca_fingerprints().0)?; - Ok(()) + ctx.reply.expand(&[0; 60]) + } } fn keygen_dates( mut ctx: Context<'_, R, T>, ) -> Result<(), Status> { - let Ok(mut ctx) = ctx.load_state() else { + if let Ok(mut ctx) = ctx.load_state() { + ctx.reply.expand(&ctx.state.internal.keygen_dates().0) + } else { // If the state doesn't load, return placeholder so that gpg presents the option to factory reset - return ctx.reply.expand(&[0;12]); - }; - ctx.reply.expand(&ctx.state.internal.keygen_dates().0)?; - Ok(()) + ctx.reply.expand(&[0; 12]) + } } fn key_info_byte(data: Option) -> u8 { @@ -687,88 +684,95 @@ fn key_info_byte(data: Option) -> u8 { } fn key_info(mut ctx: Context<'_, R, T>) -> Result<(), Status> { - let Ok(mut ctx) = ctx.load_state() else { + if let Ok(mut ctx) = ctx.load_state() { + // Key-Ref. : Sig = 1, Dec = 2, Aut = 3 (see §7.2.18) + ctx.reply.expand(&[ + 0x01, + key_info_byte(ctx.state.internal.key_origin(KeyType::Sign)), + ])?; + ctx.reply.expand(&[ + 0x02, + key_info_byte(ctx.state.internal.key_origin(KeyType::Dec)), + ])?; + ctx.reply.expand(&[ + 0x03, + key_info_byte(ctx.state.internal.key_origin(KeyType::Aut)), + ])?; + Ok(()) + } else { // If the state doesn't load, return placeholder so that gpg presents the option to factory reset - return ctx.reply.expand(&hex!("010002000300")); - }; - // Key-Ref. : Sig = 1, Dec = 2, Aut = 3 (see §7.2.18) - ctx.reply.expand(&[ - 0x01, - key_info_byte(ctx.state.internal.key_origin(KeyType::Sign)), - ])?; - ctx.reply.expand(&[ - 0x02, - key_info_byte(ctx.state.internal.key_origin(KeyType::Dec)), - ])?; - ctx.reply.expand(&[ - 0x03, - key_info_byte(ctx.state.internal.key_origin(KeyType::Aut)), - ])?; - Ok(()) + ctx.reply.expand(&hex!("010002000300")) + } } fn uif( mut ctx: Context<'_, R, T>, key: KeyType, ) -> Result<(), Status> { - let Ok(mut ctx) = ctx.load_state() else { - // If the state doesn't load, return placeholder so that gpg presents the option to factory reset - return ctx.reply.expand(&[Uif::Disabled as u8, general_feature_management_byte(ctx.options)]); - }; + if let Ok(mut ctx) = ctx.load_state() { + if !ctx.options.button_available { + warn!("GET DAT for uif without a button available"); + return Err(Status::FunctionNotSupported); + } - if !ctx.options.button_available { - warn!("GET DAT for uif without a button available"); - return Err(Status::FunctionNotSupported); + let state_byte = ctx.state.internal.uif(key).as_byte(); + let button_byte = general_feature_management_byte(ctx.options); + ctx.reply.expand(&[state_byte, button_byte]) + } else { + // If the state doesn't load, return placeholder so that gpg presents the option to factory reset + ctx.reply.expand(&[ + Uif::Disabled as u8, + general_feature_management_byte(ctx.options), + ]) } - - let state_byte = ctx.state.internal.uif(key).as_byte(); - let button_byte = general_feature_management_byte(ctx.options); - ctx.reply.expand(&[state_byte, button_byte]) } fn cardholder_name( mut ctx: Context<'_, R, T>, ) -> Result<(), Status> { - let Ok(mut ctx) = ctx.load_state() else { + if let Ok(mut ctx) = ctx.load_state() { + ctx.reply.expand(ctx.state.internal.cardholder_name()) + } else { // If the state doesn't load, return placeholder so that gpg presents the option to factory reset - return ctx.reply.expand(b"Card state corrupted. Factory reset recommended"); - }; - ctx.reply.expand(ctx.state.internal.cardholder_name()) + ctx.reply + .expand(b"Card state corrupted. Factory reset recommended") + } } fn cardholder_sex( mut ctx: Context<'_, R, T>, ) -> Result<(), Status> { - let Ok(mut ctx) = ctx.load_state() else { + if let Ok(mut ctx) = ctx.load_state() { + ctx.reply + .expand(&[ctx.state.internal.cardholder_sex() as u8]) + } else { // If the state doesn't load, return placeholder so that gpg presents the option to factory reset - return ctx.reply - .expand(&[Sex::NotKnown as u8]) - }; - ctx.reply - .expand(&[ctx.state.internal.cardholder_sex() as u8]) + ctx.reply.expand(&[Sex::NotKnown as u8]) + } } fn language_preferences( mut ctx: Context<'_, R, T>, ) -> Result<(), Status> { - let Ok(mut ctx) = ctx.load_state() else { + if let Ok(mut ctx) = ctx.load_state() { + ctx.reply.expand(ctx.state.internal.language_preferences()) + } else { // If the state doesn't load, return placeholder so that gpg presents the option to factory reset - return ctx.reply.expand(b""); - }; - ctx.reply.expand(ctx.state.internal.language_preferences()) + ctx.reply.expand(b"") + } } fn signature_counter( mut ctx: Context<'_, R, T>, ) -> Result<(), Status> { // Counter is only on 3 bytes - let Ok(mut ctx) = ctx.load_state() else { + if let Ok(mut ctx) = ctx.load_state() { + let resp = &ctx.state.internal.sign_count().to_be_bytes()[1..]; + ctx.reply.expand(resp) + } else { // If the state doesn't load, return placeholder so that gpg presents the option to factory reset - return ctx.reply.expand(&0u32.to_be_bytes()[1..]); - }; - - let resp = &ctx.state.internal.sign_count().to_be_bytes()[1..]; - ctx.reply.expand(resp) + ctx.reply.expand(&0u32.to_be_bytes()[1..]) + } } fn get_arbitrary_do( From b669df8e21ee5295d29fc798b35dfb7c26d25c66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sosth=C3=A8ne=20Gu=C3=A9don?= Date: Tue, 3 Jan 2023 15:25:54 +0100 Subject: [PATCH 4/6] Fix reset code counter --- src/command/data.rs | 3 +-- src/state.rs | 1 - 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/command/data.rs b/src/command/data.rs index e0768fd..4a95436 100644 --- a/src/command/data.rs +++ b/src/command/data.rs @@ -564,8 +564,7 @@ fn pw_status_bytes( max_length_rc: MAX_PIN_LENGTH as u8, max_length_pw3: MAX_PIN_LENGTH as u8, error_counter_pw1: ctx.state.internal.remaining_tries(Password::Pw1), - // TODO when implementing RESET RETRY COUNTER - error_counter_rc: 3, + error_counter_rc: ctx.state.internal.remaining_tries(Password::ResetCode), error_counter_pw3: ctx.state.internal.remaining_tries(Password::Pw3), } } else { diff --git a/src/state.rs b/src/state.rs index e025f71..4a6ee3e 100644 --- a/src/state.rs +++ b/src/state.rs @@ -1,5 +1,4 @@ // Copyright (C) 2022 Nitrokey GmbH -// let algo = ctx.state.internal. // SPDX-License-Identifier: LGPL-3.0-only use core::mem::swap; From 590601e57ba876d9d28d0864746b1188c24a2e20 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sosth=C3=A8ne=20Gu=C3=A9don?= Date: Wed, 1 Feb 2023 10:58:59 +0100 Subject: [PATCH 5/6] Remove recommandation to factory reset --- src/command/data.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/command/data.rs b/src/command/data.rs index 4a95436..248cc88 100644 --- a/src/command/data.rs +++ b/src/command/data.rs @@ -733,8 +733,7 @@ fn cardholder_name( ctx.reply.expand(ctx.state.internal.cardholder_name()) } else { // If the state doesn't load, return placeholder so that gpg presents the option to factory reset - ctx.reply - .expand(b"Card state corrupted. Factory reset recommended") + ctx.reply.expand(b"Card state corrupted.") } } From c51db89915032db74293de48cfa94dcb6d602135 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sosth=C3=A8ne=20Gu=C3=A9don?= Date: Wed, 1 Feb 2023 11:02:20 +0100 Subject: [PATCH 6/6] Fix clippy warnings --- tests/command-response.rs | 6 +++--- tests/gpg-status.rs | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/command-response.rs b/tests/command-response.rs index 0d0ef98..f858fa1 100644 --- a/tests/command-response.rs +++ b/tests/command-response.rs @@ -414,7 +414,7 @@ impl IoCmd { expected_status: Status, card: &mut opcard::Card, ) { - println!("Command: {:x?}", input); + println!("Command: {input:x?}"); let mut rep: heapless::Vec = heapless::Vec::new(); let cmd: iso7816::Command<1024> = iso7816::Command::try_from(input).unwrap_or_else(|err| { panic!("Bad command: {err:?}, for command: {}", hex::encode(input)) @@ -428,10 +428,10 @@ impl IoCmd { println!("Output: {:?}\nStatus: {status:?}", hex::encode(&rep)); if !output.validate(&rep) { - panic!("Bad output. Expected {:?}", output); + panic!("Bad output. Expected {output:?}"); } if status != expected_status { - panic!("Bad status. Expected {:?}", expected_status); + panic!("Bad status. Expected {expected_status:?}"); } } diff --git a/tests/gpg-status.rs b/tests/gpg-status.rs index 2eafd14..7b78c80 100644 --- a/tests/gpg-status.rs +++ b/tests/gpg-status.rs @@ -47,7 +47,7 @@ fn gpg_card_status() { let stdout = String::from_utf8_lossy(&output.stdout); println!("=== stdout ==="); - println!("{}", stdout); + println!("{stdout}"); println!("=== end stdout ==="); println!();