Minimize the output data: assert data that is always expected - only return Status bytes that diverge between cards.

Added a test that sets and checks name, lang, sex, url data.
This commit is contained in:
Heiko Schaefer 2021-07-14 00:06:30 +02:00
parent 6c7ce6228c
commit 499e128b4e

View file

@ -1,13 +1,12 @@
// SPDX-FileCopyrightText: 2021 Heiko Schaefer <heiko@schaefer.name> // SPDX-FileCopyrightText: 2021 Heiko Schaefer <heiko@schaefer.name>
// SPDX-License-Identifier: MIT OR Apache-2.0 // SPDX-License-Identifier: MIT OR Apache-2.0
use anyhow::{anyhow, Result}; use anyhow::Result;
use std::env; use std::collections::HashMap;
use openpgp_card::apdu::PcscClient; use openpgp_card::apdu::PcscClient;
use openpgp_card::card_app::CardApp; use openpgp_card::card_app::CardApp;
use openpgp_card::CardClientBox; use openpgp_card::{CardClientBox, Sex};
use std::collections::HashMap;
#[derive(Debug)] #[derive(Debug)]
enum TestResult { enum TestResult {
@ -17,43 +16,91 @@ enum TestResult {
type TestOutput = Vec<TestResult>; type TestOutput = Vec<TestResult>;
/// outputs: /// Sets name, lang, sex, url; then reads the fields from the card and
/// - verify pw3 + pin -> Status /// compares the values with the expected values.
///
/// Returns an empty TestOutput, throws errors for unexpected Status codes
/// and for unequal field values.
fn test_set_user_data(ca: &mut CardApp) -> Result<TestOutput> {
let res = ca.verify_pw3("12345678")?;
res.check_ok()?;
// name
let res = ca.set_name("Bar<<Foo")?;
res.check_ok()?;
// lang
let res = ca.set_lang("deen")?;
res.check_ok()?;
// sex
let res = ca.set_sex(Sex::Female)?;
res.check_ok()?;
// url
let res = ca.set_url("https://duckduckgo.com/")?;
res.check_ok()?;
// read all the fields back again, expect equal data
let ch = ca.get_cardholder_related_data()?;
assert_eq!(ch.name, Some("Bar<<Foo".to_string()));
assert_eq!(ch.lang, Some(vec![['d', 'e'], ['e', 'n']]));
assert_eq!(ch.sex, Some(Sex::Female));
let url = ca.get_url()?;
assert_eq!(url, "https://duckduckgo.com/".to_string());
Ok(vec![])
}
/// Outputs:
/// - verify pw3 (check) -> Status /// - verify pw3 (check) -> Status
/// - set name -> Status
/// - get name -> Text(name)
/// - verify pw1 + pin -> Status
/// - verify pw1 (check) -> Status /// - verify pw1 (check) -> Status
/// - set name -> Status
/// - get name -> Text(name)
fn test_verify(ca: &mut CardApp) -> Result<TestOutput> { fn test_verify(ca: &mut CardApp) -> Result<TestOutput> {
// Steps:
//
// - try to set name without verify, assert result is not ok
// - verify pw3 + pin -> Status
// - verify pw3 (check) -> Status
// - set name -> Status
// - get name -> Text(name)
// - verify pw1 + pin -> Status
// - verify pw1 (check) -> Status
// - set name -> Status
// - get name -> Text(name)
let mut out = vec![]; let mut out = vec![];
// try to set name without verify, assert result is not ok!
let res = ca.set_name("Notverified<<Hello")?;
assert_eq!(res.status(), [0x69, 0x82]); // "Security status not satisfied"
let res = ca.verify_pw3("12345678")?; let res = ca.verify_pw3("12345678")?;
out.push(TestResult::Status(res.status())); res.check_ok()?;
let check = ca.check_pw3()?; let check = ca.check_pw3()?;
// don't "check_ok()" - yubikey5 returns an error code!
out.push(TestResult::Status(check.status())); out.push(TestResult::Status(check.status()));
let res = ca.set_name("Admin<<Hello")?; let res = ca.set_name("Admin<<Hello")?;
out.push(TestResult::Status(res.status()));
res.check_ok()?; res.check_ok()?;
let cardholder = ca.get_cardholder_related_data()?; let cardholder = ca.get_cardholder_related_data()?;
out.push(TestResult::Text(cardholder.name.unwrap())); assert_eq!(cardholder.name, Some("Admin<<Hello".to_string()));
let res = ca.verify_pw1("123456")?; let res = ca.verify_pw1("123456")?;
out.push(TestResult::Status(res.status())); res.check_ok()?;
let check = ca.check_pw3()?; let check = ca.check_pw3()?;
// don't "check_ok()" - yubikey5 returns an error code
out.push(TestResult::Status(check.status())); out.push(TestResult::Status(check.status()));
let res = ca.set_name("There<<Hello")?; let res = ca.set_name("There<<Hello")?;
out.push(TestResult::Status(res.status()));
res.check_ok()?; res.check_ok()?;
let cardholder = ca.get_cardholder_related_data()?; let cardholder = ca.get_cardholder_related_data()?;
out.push(TestResult::Text(cardholder.name.unwrap())); assert_eq!(cardholder.name, Some("There<<Hello".to_string()));
Ok(out) Ok(out)
} }
@ -88,10 +135,6 @@ fn run_test(
} }
fn main() -> Result<()> { fn main() -> Result<()> {
// Ident of the OpenPGP Card that will be used for tests.
let test_card_ident =
env::var("TEST_CARD_IDENT").expect("TEST_CARD_IDENT is not set");
// list of card idents to runs the tests on // list of card idents to runs the tests on
let cards = vec![ let cards = vec![
"0006:16019180", // Yubikey 5 "0006:16019180", // Yubikey 5
@ -100,6 +143,7 @@ fn main() -> Result<()> {
]; ];
let _verify_res = run_test(&cards, test_verify)?; let _verify_res = run_test(&cards, test_verify)?;
let _userdata_res = run_test(&cards, test_set_user_data)?;
Ok(()) Ok(())
} }