diff --git a/Cargo.toml b/Cargo.toml index 755c855e..2b1656b4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -56,6 +56,7 @@ virtual = ["std", "vpicc"] rsa2048 = ["trussed/rsa2048"] rsa4096 = ["rsa2048", "trussed/rsa4096"] rsa4096-gen = ["rsa4096"] +dangerous-test-real-card = [] # used for delog log-all = [] diff --git a/Makefile b/Makefile index 8d681364..7640ca42 100644 --- a/Makefile +++ b/Makefile @@ -2,6 +2,9 @@ # SPDX-License-Identifier: CC0-1.0 export RUST_LOG ?= info,cargo_tarpaulin=off +export OPCARD_DANGEROUS_TEST_CARD_VENDOR ?= 0000 +export OPCARD_DANGEROUS_TEST_CARD_SERIAL ?= 000000 +export OPCARD_DANGEROUS_TEST_CARD_NAME ?= test card FUZZ_JOBS?=$(shell nproc) FUZZ_DURATION?="0" @@ -26,6 +29,11 @@ fix: test: cargo test --features virtual,rsa2048,rsa4096-gen gpg_crypto,sequoia_gen_key cargo test --features virtual,rsa2048,rsa4096 + + +.PHONY: test +dangerous-real-card-test: + cargo test --features rsa4096,dangerous-test-real-card .PHONY: fuzz fuzz: fuzz-corpus diff --git a/tests/crypto-gpg-import.rs b/tests/crypto-gpg-import.rs index 2f9b7221..1d54d809 100644 --- a/tests/crypto-gpg-import.rs +++ b/tests/crypto-gpg-import.rs @@ -1,14 +1,18 @@ // Copyright (C) 2022 Nitrokey GmbH // SPDX-License-Identifier: LGPL-3.0-only +#![cfg(any(feature = "virtual", feature = "dangerous-test-real-card"))] -#![cfg(feature = "virtual")] mod virt; use rand::Rng; use test_log::test; +use virt::gnupg_test; use virt::GpgCommand::*; -use virt::{gnupg_test, with_vsc}; + +#[cfg(feature = "virtual")] +#[allow(unused)] +use virt::with_vsc; const DEFAULT_PW3: &str = "12345678"; const DEFAULT_PW1: &str = "123456"; @@ -23,1146 +27,1201 @@ impl<'s> Drop for FileDropper<'s> { } fn gpg_255() { - with_vsc(|| { - let file_number: u32 = rand::rngs::OsRng.gen(); - let tmp = format!("/tmp/opcard-tests-{file_number}.gpg"); - let encrypted_file = &tmp; - let tmp = format!("/tmp/opcard-tests-{file_number}-sig.gpg"); - let sign_file = &tmp; - let tmp = format!("/tmp/opcard-tests-{file_number}.toml"); - let decrypted_file = &tmp; - let _dropper = FileDropper { - temp_file_name: encrypted_file, - }; - let _dropper = FileDropper { - temp_file_name: sign_file, - }; - let _dropper = FileDropper { - temp_file_name: decrypted_file, - }; - - let tmp = format!("test name{file_number}"); - let temp_name = &tmp; - - let tmp = format!("test{file_number}@email.com"); - let temp_email = &tmp; - - let custom_match = format!( - r"uid:u::::\d{{10}}::[0-9A-F]{{40}}::{temp_name} \(no comment\) <{temp_email}>::::::::::0:" - ); - - let custom_match2 = format!( - r"uid:u::::::::{temp_name} \(no comment\) <{temp_email}>:::.*,mdc,no-ks-modify:1,p::" - ); - - gnupg_test( - &["9", "1", "0", temp_name, temp_email, "no comment", "", ""], - &[ - vec![ - r"\[GNUPG:\] GET_LINE keygen.algo", - r"\[GNUPG:\] GET_LINE keygen.curve", - r"\[GNUPG:\] GET_LINE keygen.valid", - r"\[GNUPG:\] GET_LINE keygen.name", - r"\[GNUPG:\] GET_LINE keygen.email", - r"\[GNUPG:\] GET_LINE keygen.comment", - ], - virt::gpg_inquire_pin(), - virt::gpg_inquire_pin(), - vec![ - r"pub:u:\d*:22:[0-9A-F]{16}:[0-9A-F]{10}:::u:::scESC:::\+::ed25519:::0:", - r"fpr:::::::::[0-9A-F]{40}:", - r"grp:::::::::[0-9A-F]{40}:", - &custom_match, - r"sub:u:\d*:18:[0-9A-F]{16}:[0-9A-F]{10}::::::e:::\+::cv25519::", - r"fpr:::::::::[0-9A-F]{40}:", - r"grp:::::::::[0-9A-F]{40}:", - r"\[GNUPG:\] KEY_CREATED B [A-F0-9]{40}", - ], - ] - .into_iter() - .flatten() - .collect::>(), - &[ - r"gpg: revocation certificate stored as '.*\.rev'", - r"gpg: checking the trustdb", - r"gpg: marginals needed: \d completes needed: \d trust model: pgp", - r"gpg: depth:[ 0-9]*valid:[ 0-9]*signed:[ 0-9]*trust: \d*-, \d*q, \d*n, \d*m, \d*f, \d*u", + let file_number: u32 = rand::rngs::OsRng.gen(); + let tmp = format!("/tmp/opcard-tests-{file_number}.gpg"); + let encrypted_file = &tmp; + let tmp = format!("/tmp/opcard-tests-{file_number}-sig.gpg"); + let sign_file = &tmp; + let tmp = format!("/tmp/opcard-tests-{file_number}.toml"); + let decrypted_file = &tmp; + let _dropper = FileDropper { + temp_file_name: encrypted_file, + }; + let _dropper = FileDropper { + temp_file_name: sign_file, + }; + let _dropper = FileDropper { + temp_file_name: decrypted_file, + }; + + let tmp = format!("test name{file_number}"); + let temp_name = &tmp; + + let tmp = format!("test{file_number}@email.com"); + let temp_email = &tmp; + + let custom_match = format!( + r"uid:u::::\d{{10}}::[0-9A-F]{{40}}::{temp_name} \(no comment\) <{temp_email}>::::::::::0:" + ); + + let custom_match2 = format!( + r"uid:u::::::::{temp_name} \(no comment\) <{temp_email}>:::.*,mdc,no-ks-modify:1,p::" + ); + + gnupg_test( + &[], + &[ + vec![r"\[GNUPG:\] CARDCTRL \d D276000124010304[A-Z0-9]*"], + virt::gpg_status(virt::KeyType::RsaNone, 0), + ] + .into_iter() + .flatten() + .collect::>(), + &[], + CardStatus, + ); + + gnupg_test( + &["9", "1", "0", temp_name, temp_email, "no comment", "", ""], + &[ + vec![ + r"\[GNUPG:\] GET_LINE keygen.algo", + r"\[GNUPG:\] GET_LINE keygen.curve", + r"\[GNUPG:\] GET_LINE keygen.valid", + r"\[GNUPG:\] GET_LINE keygen.name", + r"\[GNUPG:\] GET_LINE keygen.email", + r"\[GNUPG:\] GET_LINE keygen.comment", + ], + virt::gpg_inquire_pin(), + virt::gpg_inquire_pin(), + vec![ + r"pub:u:\d*:22:[0-9A-F]{16}:[0-9A-F]{10}:::u:::scESC:::\+::ed25519:::0:", + r"fpr:::::::::[0-9A-F]{40}:", + r"grp:::::::::[0-9A-F]{40}:", + &custom_match, + r"sub:u:\d*:18:[0-9A-F]{16}:[0-9A-F]{10}::::::e:::\+::cv25519::", + r"fpr:::::::::[0-9A-F]{40}:", + r"grp:::::::::[0-9A-F]{40}:", + r"\[GNUPG:\] KEY_CREATED B [A-F0-9]{40}", + ], + ] + .into_iter() + .flatten() + .collect::>(), + &[ + r"gpg: revocation certificate stored as '.*\.rev'", + r"gpg: checking the trustdb", + r"gpg: marginals needed: \d completes needed: \d trust model: pgp", + r"gpg: depth:[ 0-9]*valid:[ 0-9]*signed:[ 0-9]*trust: \d*-, \d*q, \d*n, \d*m, \d*f, \d*u", + ], + Generate, + ); + + println!("================ FINISHED GENERATING 25519 KEYS ================"); + + gnupg_test( + &["key *", "keytocard", "2", DEFAULT_PW3, DEFAULT_PW3, "save"], + &[ + vec![ + r"sec:u:\d*:22:[0-9A-F]{16}:[0-9A-F]{10}:0::u:::sc", + r"fpr:::::::::[0-9A-F]{40}:", + r"ssb:u:\d*:18:[0-9A-F]{16}:[0-9A-F]{10}:0:::::e", + r"fpr:::::::::[0-9A-F]{40}:", + &custom_match2, + r"\[GNUPG:\] GET_LINE keyedit.prompt", + r"sec:u:\d*:22:[0-9A-F]{16}:[0-9A-F]{10}:0::u:::sc", + r"fpr:::::::::[0-9A-F]{40}:", + r"ssb:u:\d*:18:[0-9A-F]{16}:[0-9A-F]{10}:0:::::e", + r"fpr:::::::::[0-9A-F]{40}:", + &custom_match2, + r"\[GNUPG:\] GET_LINE keyedit.prompt", + r"\[GNUPG:\] CARDCTRL 3 D276000124010304[A-F0-9]*", + r"\[GNUPG:\] GET_LINE cardedit.genkeys.storekeytype", ], - Generate, - ); - - println!("================ FINISHED GENERATING 25519 KEYS ================"); - - gnupg_test( - &["key *", "keytocard", "2", DEFAULT_PW3, DEFAULT_PW3, "save"], - &[ - vec![ - r"sec:u:\d*:22:[0-9A-F]{16}:[0-9A-F]{10}:0::u:::sc", - r"fpr:::::::::[0-9A-F]{40}:", - r"ssb:u:\d*:18:[0-9A-F]{16}:[0-9A-F]{10}:0:::::e", - r"fpr:::::::::[0-9A-F]{40}:", - &custom_match2, - r"\[GNUPG:\] GET_LINE keyedit.prompt", - r"sec:u:\d*:22:[0-9A-F]{16}:[0-9A-F]{10}:0::u:::sc", - r"fpr:::::::::[0-9A-F]{40}:", - r"ssb:u:\d*:18:[0-9A-F]{16}:[0-9A-F]{10}:0:::::e", - r"fpr:::::::::[0-9A-F]{40}:", - &custom_match2, - r"\[GNUPG:\] GET_LINE keyedit.prompt", - r"\[GNUPG:\] CARDCTRL 3 D2760001240103040000000000000000", - r"\[GNUPG:\] GET_LINE cardedit.genkeys.storekeytype", - ], - virt::gpg_inquire_pin(), - virt::gpg_inquire_pin(), - vec![ - r"sec:u:\d*:22:[0-9A-F]{16}:[0-9A-F]{10}:0::u:::sc", - r"fpr:::::::::[0-9A-F]{40}:", - r"ssb:u:\d*:18:[0-9A-F]{16}:[0-9A-F]{10}:0:::::e", - r"fpr:::::::::[0-9A-F]{40}:", - &custom_match2, - r"\[GNUPG:\] GET_LINE keyedit.prompt", - ], - ] - .into_iter() - .flatten() - .collect::>(), - &[], - EditKey { o: temp_email }, - ); - - println!("================ FINISHED IMPORTING DECRYPTION KEY ================"); - - gnupg_test( - &["keytocard", "y", "1", DEFAULT_PW3, "save"], - &[ - vec![ - r"sec:u:\d*:22:[0-9A-F]{16}:[0-9A-F]{10}:0::u:::sc", - r"fpr:::::::::[0-9A-F]{40}:", - r"ssb:u:\d*:18:[0-9A-F]{16}:[0-9A-F]{10}:0:::::e", - r"fpr:::::::::[0-9A-F]{40}:", - &custom_match2, - r"\[GNUPG:\] GET_LINE keyedit.prompt", - r"\[GNUPG:\] GET_BOOL keyedit.keytocard.use_primary", - r"\[GNUPG:\] CARDCTRL 3 D2760001240103040000000000000000", - r"\[GNUPG:\] GET_LINE cardedit.genkeys.storekeytype", - ], - virt::gpg_inquire_pin(), - vec![ - r"sec:u:\d*:22:[0-9A-F]{16}:[0-9A-F]{10}:0::u:::sc", - r"fpr:::::::::[0-9A-F]{40}:", - r"ssb:u:\d*:18:[0-9A-F]{16}:[0-9A-F]{10}:0:::::e", - r"fpr:::::::::[0-9A-F]{40}:", - &custom_match2, - r"\[GNUPG:\] GET_LINE keyedit.prompt", - ], - ] - .into_iter() - .flatten() - .collect::>(), - &[], - EditKey { o: temp_email }, - ); - - println!("================ FINISHED IMPORTING 25519 KEYS ================"); - - gnupg_test( - &[], - &[ - r"\[GNUPG:\] BEGIN_ENCRYPTION \d \d", - r"\[GNUPG:\] END_ENCRYPTION", + virt::gpg_inquire_pin(), + virt::gpg_inquire_pin(), + vec![ + r"sec:u:\d*:22:[0-9A-F]{16}:[0-9A-F]{10}:0::u:::sc", + r"fpr:::::::::[0-9A-F]{40}:", + r"ssb:u:\d*:18:[0-9A-F]{16}:[0-9A-F]{10}:0:::::e", + r"fpr:::::::::[0-9A-F]{40}:", + &custom_match2, + r"\[GNUPG:\] GET_LINE keyedit.prompt", ], - &[], - Encrypt { - i: "Cargo.toml", - o: encrypted_file, - r: temp_email, - }, - ); - - println!("================ FINISHED ENCRYPTION ================"); - - let custom1 = format!( - r"\[GNUPG:\] USERID_HINT [a-fA-F0-9]{{16}} {temp_name} \(no comment\) <{temp_email}>" - ); - let custom2 = format!(r"{temp_name} \(no comment\) <{temp_email}>"); - gnupg_test( - &[DEFAULT_PW1], - &[ - vec![ - r"\[GNUPG:\] ENC_TO [a-fA-F0-9]{16} \d* \d*", - &custom1, - r"\[GNUPG:\] NEED_PASSPHRASE [a-fA-F0-9]{16} [a-fA-F0-9]{16} 18 0", - ], - virt::gpg_inquire_pin(), - vec![ - r"\[GNUPG:\] DECRYPTION_KEY [a-fA-F0-9]{40} [a-fA-F0-9]{40} u", - r"\[GNUPG:\] BEGIN_DECRYPTION", - r"\[GNUPG:\] DECRYPTION_INFO \d \d \d", - r"\[GNUPG:\] PLAINTEXT \d* \d* Cargo.toml", - r"\[GNUPG:\] PLAINTEXT_LENGTH \d*", - r"\[GNUPG:\] DECRYPTION_OKAY", - r"\[GNUPG:\] GOODMDC", - r"\[GNUPG:\] END_DECRYPTION", - ], - ] - .into_iter() - .flatten() - .collect::>(), - &[ - r"gpg: encrypted with \d*-bit ECDH key, ID [a-fA-F0-9]{16}, created \d{4}-\d\d-\d\d", - &custom2, + ] + .into_iter() + .flatten() + .collect::>(), + &[], + EditKey { o: temp_email }, + ); + + println!("================ FINISHED IMPORTING DECRYPTION KEY ================"); + + gnupg_test( + &["keytocard", "y", "1", DEFAULT_PW3, "save"], + &[ + vec![ + r"sec:u:\d*:22:[0-9A-F]{16}:[0-9A-F]{10}:0::u:::sc", + r"fpr:::::::::[0-9A-F]{40}:", + r"ssb:u:\d*:18:[0-9A-F]{16}:[0-9A-F]{10}:0:::::e", + r"fpr:::::::::[0-9A-F]{40}:", + &custom_match2, + r"\[GNUPG:\] GET_LINE keyedit.prompt", + r"\[GNUPG:\] GET_BOOL keyedit.keytocard.use_primary", + r"\[GNUPG:\] CARDCTRL 3 D276000124010304[A-F0-9]*", + r"\[GNUPG:\] GET_LINE cardedit.genkeys.storekeytype", ], - Decrypt { - i: encrypted_file, - o: decrypted_file, - }, - ); - - println!("================ FINISHED DECRYPTION ================"); - - gnupg_test( - &[DEFAULT_PW1], - &[ - vec![ - r"\[GNUPG:\] CARDCTRL 3 D2760001240103040000000000000000", - r"\[GNUPG:\] BEGIN_SIGNING H\d*", - &custom1, - r"\[GNUPG:\] NEED_PASSPHRASE [a-fA-F0-9]{16} [a-fA-F0-9]{16} 22 0", - ], - virt::gpg_inquire_pin(), - vec![r"\[GNUPG:\] SIG_CREATED S 22 8 00 [a-fA-F0-9]{10} [a-fA-F0-9]{40}"], - ] - .into_iter() - .flatten() - .collect::>(), - &[r#"gpg: using "test\d*@email.com" as default secret key for signing"#], - Sign { - i: "Cargo.toml", - o: sign_file, - s: temp_email, - }, - ); - - println!("================ FINISHED SIGNATURE ================"); - - gnupg_test( - &[], - &[ - r"\[GNUPG:\] NEWSIG test\d*@email.com", - r"\[GNUPG:\] SIG_ID [^ ]* \d{4}-\d\d-\d\d [a-fA-F0-9]{10}", - r"\[GNUPG:\] GOODSIG [a-fA-F0-9]{16} test name\d* \(no comment\) ", - r"\[GNUPG:\] VALIDSIG [a-fA-F0-9]{40} \d{4}-\d\d-\d\d [a-fA-F0-9]{10} \d \d \d 22 8 00 [a-fA-F0-9]{40}", - r"\[GNUPG:\] TRUST_ULTIMATE 0 pgp", + virt::gpg_inquire_pin(), + vec![ + r"sec:u:\d*:22:[0-9A-F]{16}:[0-9A-F]{10}:0::u:::sc", + r"fpr:::::::::[0-9A-F]{40}:", + r"ssb:u:\d*:18:[0-9A-F]{16}:[0-9A-F]{10}:0:::::e", + r"fpr:::::::::[0-9A-F]{40}:", + &custom_match2, + r"\[GNUPG:\] GET_LINE keyedit.prompt", ], - &[ - r"gpg: Signature made .*", - r"gpg: using EDDSA key [a-fA-F0-9]{40}", - r#"gpg: issuer "test\d*@email.com""#, - r#"pg: Good signature from "test name\d* \(no comment\) "#, + ] + .into_iter() + .flatten() + .collect::>(), + &[], + EditKey { o: temp_email }, + ); + + println!("================ FINISHED IMPORTING 25519 KEYS ================"); + + gnupg_test( + &[], + &[ + r"\[GNUPG:\] BEGIN_ENCRYPTION \d \d", + r"\[GNUPG:\] END_ENCRYPTION", + ], + &[], + Encrypt { + i: "Cargo.toml", + o: encrypted_file, + r: temp_email, + }, + ); + + println!("================ FINISHED ENCRYPTION ================"); + + let custom1 = format!( + r"\[GNUPG:\] USERID_HINT [a-fA-F0-9]{{16}} {temp_name} \(no comment\) <{temp_email}>" + ); + let custom2 = format!(r"{temp_name} \(no comment\) <{temp_email}>"); + gnupg_test( + &[DEFAULT_PW1], + &[ + vec![ + r"\[GNUPG:\] ENC_TO [a-fA-F0-9]{16} \d* \d*", + &custom1, + r"\[GNUPG:\] NEED_PASSPHRASE [a-fA-F0-9]{16} [a-fA-F0-9]{16} 18 0", ], - Verify { i: sign_file }, - ); - - gnupg_test( - &[ - "admin", - "factory-reset", - "y", - "yes", - "verify", - DEFAULT_PW1, - "quit", + virt::gpg_inquire_pin(), + vec![ + r"\[GNUPG:\] DECRYPTION_KEY [a-fA-F0-9]{40} [a-fA-F0-9]{40} u", + r"\[GNUPG:\] BEGIN_DECRYPTION", + r"\[GNUPG:\] DECRYPTION_INFO \d \d \d", + r"\[GNUPG:\] PLAINTEXT \d* \d* Cargo.toml", + r"\[GNUPG:\] PLAINTEXT_LENGTH \d*", + r"\[GNUPG:\] DECRYPTION_OKAY", + r"\[GNUPG:\] GOODMDC", + r"\[GNUPG:\] END_DECRYPTION", ], - &[ - vec![r"\[GNUPG:\] CARDCTRL \d D2760001240103040000000000000000"], - virt::gpg_status(virt::KeyType::Cv25519NoAut, 1), - vec![ - r"\[GNUPG:\] GET_LINE cardedit.prompt", - r"\[GNUPG:\] GET_LINE cardedit.prompt", - r"\[GNUPG:\] GET_BOOL cardedit.factory-reset.proceed", - r"\[GNUPG:\] GET_LINE cardedit.factory-reset.really", - r"\[GNUPG:\] GET_LINE cardedit.prompt", - ], - virt::gpg_inquire_pin(), - virt::gpg_status(virt::KeyType::RsaNone, 0), - vec![r"\[GNUPG:\] GET_LINE cardedit.prompt"], - ] - .into_iter() - .flatten() - .collect::>(), - &[ - r"gpg: OpenPGP card no. [0-9A-F]{32} detected", - r"gpg: Note: This command destroys all keys stored on the card!", + ] + .into_iter() + .flatten() + .collect::>(), + &[ + r"gpg: encrypted with \d*-bit ECDH key, ID [a-fA-F0-9]{16}, created \d{4}-\d\d-\d\d", + &custom2, + ], + Decrypt { + i: encrypted_file, + o: decrypted_file, + }, + ); + + println!("================ FINISHED DECRYPTION ================"); + + gnupg_test( + &[DEFAULT_PW1], + &[ + vec![ + r"\[GNUPG:\] CARDCTRL 3 D276000124010304[A-F0-9]*", + r"\[GNUPG:\] BEGIN_SIGNING H\d*", + &custom1, + r"\[GNUPG:\] NEED_PASSPHRASE [a-fA-F0-9]{16} [a-fA-F0-9]{16} 22 0", ], - EditCard, - ); - }); + virt::gpg_inquire_pin(), + vec![r"\[GNUPG:\] SIG_CREATED S 22 8 00 [a-fA-F0-9]{10} [a-fA-F0-9]{40}"], + ] + .into_iter() + .flatten() + .collect::>(), + &[r#"gpg: using "test\d*@email.com" as default secret key for signing"#], + Sign { + i: "Cargo.toml", + o: sign_file, + s: temp_email, + }, + ); + + println!("================ FINISHED SIGNATURE ================"); + + gnupg_test( + &[], + &[ + r"\[GNUPG:\] NEWSIG test\d*@email.com", + r"\[GNUPG:\] SIG_ID [^ ]* \d{4}-\d\d-\d\d [a-fA-F0-9]{10}", + r"\[GNUPG:\] GOODSIG [a-fA-F0-9]{16} test name\d* \(no comment\) ", + r"\[GNUPG:\] VALIDSIG [a-fA-F0-9]{40} \d{4}-\d\d-\d\d [a-fA-F0-9]{10} \d \d \d 22 8 00 [a-fA-F0-9]{40}", + r"\[GNUPG:\] TRUST_ULTIMATE 0 pgp", + ], + &[ + r"gpg: Signature made .*", + r"gpg: using EDDSA key [a-fA-F0-9]{40}", + r#"gpg: issuer "test\d*@email.com""#, + r#"pg: Good signature from "test name\d* \(no comment\) "#, + ], + Verify { i: sign_file }, + ); + + gnupg_test( + &[ + "admin", + "factory-reset", + "y", + "yes", + "verify", + DEFAULT_PW1, + "quit", + ], + &[ + vec![r"\[GNUPG:\] CARDCTRL \d D276000124010304[A-F0-9]*"], + virt::gpg_status(virt::KeyType::Cv25519NoAut, 1), + vec![ + r"\[GNUPG:\] GET_LINE cardedit.prompt", + r"\[GNUPG:\] GET_LINE cardedit.prompt", + r"\[GNUPG:\] GET_BOOL cardedit.factory-reset.proceed", + r"\[GNUPG:\] GET_LINE cardedit.factory-reset.really", + r"\[GNUPG:\] GET_LINE cardedit.prompt", + ], + virt::gpg_inquire_pin(), + virt::gpg_status(virt::KeyType::RsaNone, 0), + vec![r"\[GNUPG:\] GET_LINE cardedit.prompt"], + ] + .into_iter() + .flatten() + .collect::>(), + &[ + r"gpg: OpenPGP card no. [0-9A-F]{32} detected", + r"gpg: Note: This command destroys all keys stored on the card!", + ], + EditCard, + ); } fn gpg_p256() { - with_vsc(|| { - let file_number: u32 = rand::rngs::OsRng.gen(); - let tmp = format!("/tmp/opcard-tests-{file_number}.gpg"); - let encrypted_file = &tmp; - let tmp = format!("/tmp/opcard-tests-{file_number}-sig.gpg"); - let sign_file = &tmp; - let tmp = format!("/tmp/opcard-tests-{file_number}.toml"); - let decrypted_file = &tmp; - let _dropper = FileDropper { - temp_file_name: encrypted_file, - }; - let _dropper = FileDropper { - temp_file_name: sign_file, - }; - let _dropper = FileDropper { - temp_file_name: decrypted_file, - }; - - let tmp = format!("test name{file_number}"); - let temp_name = &tmp; - - let tmp = format!("test{file_number}@email.com"); - let temp_email = &tmp; - - let custom_match = format!( - r"uid:u::::\d{{10}}::[0-9A-F]{{40}}::{temp_name} \(no comment\) <{temp_email}>::::::::::0:" - ); - - let custom_match2 = format!( - r"uid:u::::::::{temp_name} \(no comment\) <{temp_email}>:::.*,mdc,no-ks-modify:1,p::" - ); - - gnupg_test( - &["9", "3", "0", temp_name, temp_email, "no comment", "", ""], - &[ - vec![ - r"\[GNUPG:\] GET_LINE keygen.algo", - r"\[GNUPG:\] GET_LINE keygen.curve", - r"\[GNUPG:\] GET_LINE keygen.valid", - r"\[GNUPG:\] GET_LINE keygen.name", - r"\[GNUPG:\] GET_LINE keygen.email", - r"\[GNUPG:\] GET_LINE keygen.comment", - ], - virt::gpg_inquire_pin(), - virt::gpg_inquire_pin(), - vec![ - r"pub:u:\d*:19:[0-9A-F]{16}:[0-9A-F]{10}:::u:::scESC:::\+::nistp256:::0:", - r"fpr:::::::::[0-9A-F]{40}:", - r"grp:::::::::[0-9A-F]{40}:", - &custom_match, - r"sub:u:\d*:18:[0-9A-F]{16}:[0-9A-F]{10}::::::e:::\+::nistp256::", - r"fpr:::::::::[0-9A-F]{40}:", - r"grp:::::::::[0-9A-F]{40}:", - r"\[GNUPG:\] KEY_CREATED B [A-F0-9]{40}", - ], - ] - .into_iter() - .flatten() - .collect::>(), - &[ - r"gpg: revocation certificate stored as '.*\.rev'", - r"gpg: checking the trustdb", - r"gpg: marginals needed: \d completes needed: \d trust model: pgp", - r"gpg: depth:[ 0-9]*valid:[ 0-9]*signed:[ 0-9]*trust: \d*-, \d*q, \d*n, \d*m, \d*f, \d*u", + let file_number: u32 = rand::rngs::OsRng.gen(); + let tmp = format!("/tmp/opcard-tests-{file_number}.gpg"); + let encrypted_file = &tmp; + let tmp = format!("/tmp/opcard-tests-{file_number}-sig.gpg"); + let sign_file = &tmp; + let tmp = format!("/tmp/opcard-tests-{file_number}.toml"); + let decrypted_file = &tmp; + let _dropper = FileDropper { + temp_file_name: encrypted_file, + }; + let _dropper = FileDropper { + temp_file_name: sign_file, + }; + let _dropper = FileDropper { + temp_file_name: decrypted_file, + }; + + let tmp = format!("test name{file_number}"); + let temp_name = &tmp; + + let tmp = format!("test{file_number}@email.com"); + let temp_email = &tmp; + + let custom_match = format!( + r"uid:u::::\d{{10}}::[0-9A-F]{{40}}::{temp_name} \(no comment\) <{temp_email}>::::::::::0:" + ); + + let custom_match2 = format!( + r"uid:u::::::::{temp_name} \(no comment\) <{temp_email}>:::.*,mdc,no-ks-modify:1,p::" + ); + + gnupg_test( + &[], + &[ + vec![r"\[GNUPG:\] CARDCTRL \d D276000124010304[A-Z0-9]*"], + virt::gpg_status(virt::KeyType::RsaNone, 0), + ] + .into_iter() + .flatten() + .collect::>(), + &[], + CardStatus, + ); + + gnupg_test( + &["9", "3", "0", temp_name, temp_email, "no comment", "", ""], + &[ + vec![ + r"\[GNUPG:\] GET_LINE keygen.algo", + r"\[GNUPG:\] GET_LINE keygen.curve", + r"\[GNUPG:\] GET_LINE keygen.valid", + r"\[GNUPG:\] GET_LINE keygen.name", + r"\[GNUPG:\] GET_LINE keygen.email", + r"\[GNUPG:\] GET_LINE keygen.comment", + ], + virt::gpg_inquire_pin(), + virt::gpg_inquire_pin(), + vec![ + r"pub:u:\d*:19:[0-9A-F]{16}:[0-9A-F]{10}:::u:::scESC:::\+::nistp256:::0:", + r"fpr:::::::::[0-9A-F]{40}:", + r"grp:::::::::[0-9A-F]{40}:", + &custom_match, + r"sub:u:\d*:18:[0-9A-F]{16}:[0-9A-F]{10}::::::e:::\+::nistp256::", + r"fpr:::::::::[0-9A-F]{40}:", + r"grp:::::::::[0-9A-F]{40}:", + r"\[GNUPG:\] KEY_CREATED B [A-F0-9]{40}", ], - Generate, - ); - - println!("================ FINISHED GENERATING P256 KEYS ================"); - - gnupg_test( - &["key *", "keytocard", "2", DEFAULT_PW3, DEFAULT_PW3, "save"], - &[ - vec![ - r"sec:u:\d*:19:[0-9A-F]{16}:[0-9A-F]{10}:0::u:::sc", - r"fpr:::::::::[0-9A-F]{40}:", - r"ssb:u:\d*:18:[0-9A-F]{16}:[0-9A-F]{10}:0:::::e", - r"fpr:::::::::[0-9A-F]{40}:", - &custom_match2, - r"\[GNUPG:\] GET_LINE keyedit.prompt", - r"sec:u:\d*:19:[0-9A-F]{16}:[0-9A-F]{10}:0::u:::sc", - r"fpr:::::::::[0-9A-F]{40}:", - r"ssb:u:\d*:18:[0-9A-F]{16}:[0-9A-F]{10}:0:::::e", - r"fpr:::::::::[0-9A-F]{40}:", - &custom_match2, - r"\[GNUPG:\] GET_LINE keyedit.prompt", - r"\[GNUPG:\] CARDCTRL 3 D2760001240103040000000000000000", - r"\[GNUPG:\] GET_LINE cardedit.genkeys.storekeytype", - ], - virt::gpg_inquire_pin(), - virt::gpg_inquire_pin(), - vec![ - r"sec:u:\d*:19:[0-9A-F]{16}:[0-9A-F]{10}:0::u:::sc", - r"fpr:::::::::[0-9A-F]{40}:", - r"ssb:u:\d*:18:[0-9A-F]{16}:[0-9A-F]{10}:0:::::e", - r"fpr:::::::::[0-9A-F]{40}:", - &custom_match2, - r"\[GNUPG:\] GET_LINE keyedit.prompt", - ], - ] - .into_iter() - .flatten() - .collect::>(), - &[], - EditKey { o: temp_email }, - ); - - println!("================ FINISHED IMPORTING DECRYPTION KEY ================"); - - gnupg_test( - &["keytocard", "y", "1", DEFAULT_PW3, "save"], - &[ - vec![ - r"sec:u:\d*:19:[0-9A-F]{16}:[0-9A-F]{10}:0::u:::sc", - r"fpr:::::::::[0-9A-F]{40}:", - r"ssb:u:\d*:18:[0-9A-F]{16}:[0-9A-F]{10}:0:::::e", - r"fpr:::::::::[0-9A-F]{40}:", - &custom_match2, - r"\[GNUPG:\] GET_LINE keyedit.prompt", - r"\[GNUPG:\] GET_BOOL keyedit.keytocard.use_primary", - r"\[GNUPG:\] CARDCTRL 3 D2760001240103040000000000000000", - r"\[GNUPG:\] GET_LINE cardedit.genkeys.storekeytype", - ], - virt::gpg_inquire_pin(), - vec![ - r"sec:u:\d*:19:[0-9A-F]{16}:[0-9A-F]{10}:0::u:::sc", - r"fpr:::::::::[0-9A-F]{40}:", - r"ssb:u:\d*:18:[0-9A-F]{16}:[0-9A-F]{10}:0:::::e", - r"fpr:::::::::[0-9A-F]{40}:", - &custom_match2, - r"\[GNUPG:\] GET_LINE keyedit.prompt", - ], - ] - .into_iter() - .flatten() - .collect::>(), - &[], - EditKey { o: temp_email }, - ); - - println!("================ FINISHED IMPORTING P256 KEYS ================"); - - gnupg_test( - &[], - &[ - r"\[GNUPG:\] BEGIN_ENCRYPTION \d \d", - r"\[GNUPG:\] END_ENCRYPTION", + ] + .into_iter() + .flatten() + .collect::>(), + &[ + r"gpg: revocation certificate stored as '.*\.rev'", + r"gpg: checking the trustdb", + r"gpg: marginals needed: \d completes needed: \d trust model: pgp", + r"gpg: depth:[ 0-9]*valid:[ 0-9]*signed:[ 0-9]*trust: \d*-, \d*q, \d*n, \d*m, \d*f, \d*u", + ], + Generate, + ); + + println!("================ FINISHED GENERATING P256 KEYS ================"); + + gnupg_test( + &["key *", "keytocard", "2", DEFAULT_PW3, DEFAULT_PW3, "save"], + &[ + vec![ + r"sec:u:\d*:19:[0-9A-F]{16}:[0-9A-F]{10}:0::u:::sc", + r"fpr:::::::::[0-9A-F]{40}:", + r"ssb:u:\d*:18:[0-9A-F]{16}:[0-9A-F]{10}:0:::::e", + r"fpr:::::::::[0-9A-F]{40}:", + &custom_match2, + r"\[GNUPG:\] GET_LINE keyedit.prompt", + r"sec:u:\d*:19:[0-9A-F]{16}:[0-9A-F]{10}:0::u:::sc", + r"fpr:::::::::[0-9A-F]{40}:", + r"ssb:u:\d*:18:[0-9A-F]{16}:[0-9A-F]{10}:0:::::e", + r"fpr:::::::::[0-9A-F]{40}:", + &custom_match2, + r"\[GNUPG:\] GET_LINE keyedit.prompt", + r"\[GNUPG:\] CARDCTRL 3 D276000124010304[A-F0-9]*", + r"\[GNUPG:\] GET_LINE cardedit.genkeys.storekeytype", ], - &[], - Encrypt { - i: "Cargo.toml", - o: encrypted_file, - r: temp_email, - }, - ); - - println!("================ FINISHED ENCRYPTION ================"); - - let custom1 = format!( - r"\[GNUPG:\] USERID_HINT [a-fA-F0-9]{{16}} {temp_name} \(no comment\) <{temp_email}>" - ); - let custom2 = format!(r"{temp_name} \(no comment\) <{temp_email}>"); - - gnupg_test( - &[DEFAULT_PW1], - &[ - vec![ - r"\[GNUPG:\] ENC_TO [a-fA-F0-9]{16} \d* \d*", - &custom1, - r"\[GNUPG:\] NEED_PASSPHRASE [a-fA-F0-9]{16} [a-fA-F0-9]{16} 18 0", - ], - virt::gpg_inquire_pin(), - vec![ - r"\[GNUPG:\] DECRYPTION_KEY [a-fA-F0-9]{40} [a-fA-F0-9]{40} u", - r"\[GNUPG:\] BEGIN_DECRYPTION", - r"\[GNUPG:\] DECRYPTION_INFO \d \d \d", - r"\[GNUPG:\] PLAINTEXT \d* \d* Cargo.toml", - r"\[GNUPG:\] PLAINTEXT_LENGTH \d*", - r"\[GNUPG:\] DECRYPTION_OKAY", - r"\[GNUPG:\] GOODMDC", - r"\[GNUPG:\] END_DECRYPTION", - ], - ] - .into_iter() - .flatten() - .collect::>(), - &[ - r"gpg: encrypted with \d*-bit ECDH key, ID [a-fA-F0-9]{16}, created \d{4}-\d\d-\d\d", - &custom2, + virt::gpg_inquire_pin(), + virt::gpg_inquire_pin(), + vec![ + r"sec:u:\d*:19:[0-9A-F]{16}:[0-9A-F]{10}:0::u:::sc", + r"fpr:::::::::[0-9A-F]{40}:", + r"ssb:u:\d*:18:[0-9A-F]{16}:[0-9A-F]{10}:0:::::e", + r"fpr:::::::::[0-9A-F]{40}:", + &custom_match2, + r"\[GNUPG:\] GET_LINE keyedit.prompt", ], - Decrypt { - i: encrypted_file, - o: decrypted_file, - }, - ); - - println!("================ FINISHED DECRYPTION ================"); - - gnupg_test( - &[DEFAULT_PW1], - &[ - vec![ - r"\[GNUPG:\] CARDCTRL 3 D2760001240103040000000000000000", - r"\[GNUPG:\] BEGIN_SIGNING H\d*", - &custom1, - r"\[GNUPG:\] NEED_PASSPHRASE [a-fA-F0-9]{16} [a-fA-F0-9]{16} 19 0", - ], - virt::gpg_inquire_pin(), - vec![r"\[GNUPG:\] SIG_CREATED S 19 8 00 [a-fA-F0-9]{10} [a-fA-F0-9]{40}"], - ] - .into_iter() - .flatten() - .collect::>(), - &[r#"gpg: using "test\d*@email.com" as default secret key for signing"#], - Sign { - i: "Cargo.toml", - o: sign_file, - s: temp_email, - }, - ); - - println!("================ FINISHED SIGNATURE ================"); - - gnupg_test( - &[], - &[ - r"\[GNUPG:\] NEWSIG test\d*@email.com", - r"\[GNUPG:\] SIG_ID [^ ]* \d{4}-\d\d-\d\d [a-fA-F0-9]{10}", - r"\[GNUPG:\] GOODSIG [a-fA-F0-9]{16} test name\d* \(no comment\) ", - r"\[GNUPG:\] VALIDSIG [a-fA-F0-9]{40} \d{4}-\d\d-\d\d [a-fA-F0-9]{10} \d \d \d 19 8 00 [a-fA-F0-9]{40}", - r"\[GNUPG:\] TRUST_ULTIMATE 0 pgp", + ] + .into_iter() + .flatten() + .collect::>(), + &[], + EditKey { o: temp_email }, + ); + + println!("================ FINISHED IMPORTING DECRYPTION KEY ================"); + + gnupg_test( + &["keytocard", "y", "1", DEFAULT_PW3, "save"], + &[ + vec![ + r"sec:u:\d*:19:[0-9A-F]{16}:[0-9A-F]{10}:0::u:::sc", + r"fpr:::::::::[0-9A-F]{40}:", + r"ssb:u:\d*:18:[0-9A-F]{16}:[0-9A-F]{10}:0:::::e", + r"fpr:::::::::[0-9A-F]{40}:", + &custom_match2, + r"\[GNUPG:\] GET_LINE keyedit.prompt", + r"\[GNUPG:\] GET_BOOL keyedit.keytocard.use_primary", + r"\[GNUPG:\] CARDCTRL 3 D276000124010304[A-F0-9]*", + r"\[GNUPG:\] GET_LINE cardedit.genkeys.storekeytype", ], - &[ - r"gpg: Signature made .*", - r"gpg: using ECDSA key [a-fA-F0-9]{40}", - r#"gpg: issuer "test\d*@email.com""#, - r#"pg: Good signature from "test name\d* \(no comment\) "#, + virt::gpg_inquire_pin(), + vec![ + r"sec:u:\d*:19:[0-9A-F]{16}:[0-9A-F]{10}:0::u:::sc", + r"fpr:::::::::[0-9A-F]{40}:", + r"ssb:u:\d*:18:[0-9A-F]{16}:[0-9A-F]{10}:0:::::e", + r"fpr:::::::::[0-9A-F]{40}:", + &custom_match2, + r"\[GNUPG:\] GET_LINE keyedit.prompt", ], - Verify { i: sign_file }, - ); - - gnupg_test( - &[ - "admin", - "factory-reset", - "y", - "yes", - "verify", - DEFAULT_PW1, - "quit", + ] + .into_iter() + .flatten() + .collect::>(), + &[], + EditKey { o: temp_email }, + ); + + println!("================ FINISHED IMPORTING P256 KEYS ================"); + + gnupg_test( + &[], + &[ + r"\[GNUPG:\] BEGIN_ENCRYPTION \d \d", + r"\[GNUPG:\] END_ENCRYPTION", + ], + &[], + Encrypt { + i: "Cargo.toml", + o: encrypted_file, + r: temp_email, + }, + ); + + println!("================ FINISHED ENCRYPTION ================"); + + let custom1 = format!( + r"\[GNUPG:\] USERID_HINT [a-fA-F0-9]{{16}} {temp_name} \(no comment\) <{temp_email}>" + ); + let custom2 = format!(r"{temp_name} \(no comment\) <{temp_email}>"); + + gnupg_test( + &[DEFAULT_PW1], + &[ + vec![ + r"\[GNUPG:\] ENC_TO [a-fA-F0-9]{16} \d* \d*", + &custom1, + r"\[GNUPG:\] NEED_PASSPHRASE [a-fA-F0-9]{16} [a-fA-F0-9]{16} 18 0", ], - &[ - vec![r"\[GNUPG:\] CARDCTRL \d D2760001240103040000000000000000"], - virt::gpg_status(virt::KeyType::P256NoAut, 1), - vec![ - r"\[GNUPG:\] GET_LINE cardedit.prompt", - r"\[GNUPG:\] GET_LINE cardedit.prompt", - r"\[GNUPG:\] GET_BOOL cardedit.factory-reset.proceed", - r"\[GNUPG:\] GET_LINE cardedit.factory-reset.really", - r"\[GNUPG:\] GET_LINE cardedit.prompt", - ], - virt::gpg_inquire_pin(), - virt::gpg_status(virt::KeyType::RsaNone, 0), - vec![r"\[GNUPG:\] GET_LINE cardedit.prompt"], - ] - .into_iter() - .flatten() - .collect::>(), - &[ - r"gpg: OpenPGP card no. [0-9A-F]{32} detected", - r"gpg: Note: This command destroys all keys stored on the card!", + virt::gpg_inquire_pin(), + vec![ + r"\[GNUPG:\] DECRYPTION_KEY [a-fA-F0-9]{40} [a-fA-F0-9]{40} u", + r"\[GNUPG:\] BEGIN_DECRYPTION", + r"\[GNUPG:\] DECRYPTION_INFO \d \d \d", + r"\[GNUPG:\] PLAINTEXT \d* \d* Cargo.toml", + r"\[GNUPG:\] PLAINTEXT_LENGTH \d*", + r"\[GNUPG:\] DECRYPTION_OKAY", + r"\[GNUPG:\] GOODMDC", + r"\[GNUPG:\] END_DECRYPTION", ], - EditCard, - ); - }); + ] + .into_iter() + .flatten() + .collect::>(), + &[ + r"gpg: encrypted with \d*-bit ECDH key, ID [a-fA-F0-9]{16}, created \d{4}-\d\d-\d\d", + &custom2, + ], + Decrypt { + i: encrypted_file, + o: decrypted_file, + }, + ); + + println!("================ FINISHED DECRYPTION ================"); + + gnupg_test( + &[DEFAULT_PW1], + &[ + vec![ + r"\[GNUPG:\] CARDCTRL 3 D276000124010304[A-F0-9]*", + r"\[GNUPG:\] BEGIN_SIGNING H\d*", + &custom1, + r"\[GNUPG:\] NEED_PASSPHRASE [a-fA-F0-9]{16} [a-fA-F0-9]{16} 19 0", + ], + virt::gpg_inquire_pin(), + vec![r"\[GNUPG:\] SIG_CREATED S 19 8 00 [a-fA-F0-9]{10} [a-fA-F0-9]{40}"], + ] + .into_iter() + .flatten() + .collect::>(), + &[r#"gpg: using "test\d*@email.com" as default secret key for signing"#], + Sign { + i: "Cargo.toml", + o: sign_file, + s: temp_email, + }, + ); + + println!("================ FINISHED SIGNATURE ================"); + + gnupg_test( + &[], + &[ + r"\[GNUPG:\] NEWSIG test\d*@email.com", + r"\[GNUPG:\] SIG_ID [^ ]* \d{4}-\d\d-\d\d [a-fA-F0-9]{10}", + r"\[GNUPG:\] GOODSIG [a-fA-F0-9]{16} test name\d* \(no comment\) ", + r"\[GNUPG:\] VALIDSIG [a-fA-F0-9]{40} \d{4}-\d\d-\d\d [a-fA-F0-9]{10} \d \d \d 19 8 00 [a-fA-F0-9]{40}", + r"\[GNUPG:\] TRUST_ULTIMATE 0 pgp", + ], + &[ + r"gpg: Signature made .*", + r"gpg: using ECDSA key [a-fA-F0-9]{40}", + r#"gpg: issuer "test\d*@email.com""#, + r#"pg: Good signature from "test name\d* \(no comment\) "#, + ], + Verify { i: sign_file }, + ); + + gnupg_test( + &[ + "admin", + "factory-reset", + "y", + "yes", + "verify", + DEFAULT_PW1, + "quit", + ], + &[ + vec![r"\[GNUPG:\] CARDCTRL \d D276000124010304[A-F0-9]*"], + virt::gpg_status(virt::KeyType::P256NoAut, 1), + vec![ + r"\[GNUPG:\] GET_LINE cardedit.prompt", + r"\[GNUPG:\] GET_LINE cardedit.prompt", + r"\[GNUPG:\] GET_BOOL cardedit.factory-reset.proceed", + r"\[GNUPG:\] GET_LINE cardedit.factory-reset.really", + r"\[GNUPG:\] GET_LINE cardedit.prompt", + ], + virt::gpg_inquire_pin(), + virt::gpg_status(virt::KeyType::RsaNone, 0), + vec![r"\[GNUPG:\] GET_LINE cardedit.prompt"], + ] + .into_iter() + .flatten() + .collect::>(), + &[ + r"gpg: OpenPGP card no. [0-9A-F]{32} detected", + r"gpg: Note: This command destroys all keys stored on the card!", + ], + EditCard, + ); } #[cfg(feature = "rsa2048")] fn gpg_rsa_2048() { - with_vsc(|| { - let file_number: u32 = rand::rngs::OsRng.gen(); - let tmp = format!("/tmp/opcard-tests-{file_number}.gpg"); - let encrypted_file = &tmp; - let tmp = format!("/tmp/opcard-tests-{file_number}-sig.gpg"); - let sign_file = &tmp; - let tmp = format!("/tmp/opcard-tests-{file_number}.toml"); - let decrypted_file = &tmp; - let _dropper = FileDropper { - temp_file_name: encrypted_file, - }; - let _dropper = FileDropper { - temp_file_name: sign_file, - }; - let _dropper = FileDropper { - temp_file_name: decrypted_file, - }; - - let tmp = format!("test name{file_number}"); - let temp_name = &tmp; - - let tmp = format!("test{file_number}@email.com"); - let temp_email = &tmp; - - let custom_match = format!( - r"uid:u::::\d{{10}}::[0-9A-F]{{40}}::{temp_name} \(no comment\) <{temp_email}>::::::::::0:" - ); - - let custom_match2 = format!( - r"uid:u::::::::{temp_name} \(no comment\) <{temp_email}>:::.*,mdc,no-ks-modify:1,p::" - ); - - gnupg_test( - &[ - "1", - "2048", - "2048", - "0", - temp_name, - temp_email, - "no comment", - "", - "", + let file_number: u32 = rand::rngs::OsRng.gen(); + let tmp = format!("/tmp/opcard-tests-{file_number}.gpg"); + let encrypted_file = &tmp; + let tmp = format!("/tmp/opcard-tests-{file_number}-sig.gpg"); + let sign_file = &tmp; + let tmp = format!("/tmp/opcard-tests-{file_number}.toml"); + let decrypted_file = &tmp; + let _dropper = FileDropper { + temp_file_name: encrypted_file, + }; + let _dropper = FileDropper { + temp_file_name: sign_file, + }; + let _dropper = FileDropper { + temp_file_name: decrypted_file, + }; + + let tmp = format!("test name{file_number}"); + let temp_name = &tmp; + + let tmp = format!("test{file_number}@email.com"); + let temp_email = &tmp; + + let custom_match = format!( + r"uid:u::::\d{{10}}::[0-9A-F]{{40}}::{temp_name} \(no comment\) <{temp_email}>::::::::::0:" + ); + + let custom_match2 = format!( + r"uid:u::::::::{temp_name} \(no comment\) <{temp_email}>:::.*,mdc,no-ks-modify:1,p::" + ); + + gnupg_test( + &[], + &[ + vec![r"\[GNUPG:\] CARDCTRL \d D276000124010304[A-Z0-9]*"], + virt::gpg_status(virt::KeyType::RsaNone, 0), + ] + .into_iter() + .flatten() + .collect::>(), + &[], + CardStatus, + ); + + gnupg_test( + &[ + "1", + "2048", + "2048", + "0", + temp_name, + temp_email, + "no comment", + "", + "", + ], + &[ + vec![ + r"\[GNUPG:\] GET_LINE keygen.algo", + r"\[GNUPG:\] GET_LINE keygen.size", + r"\[GNUPG:\] GET_LINE keygen.size", + r"\[GNUPG:\] GET_LINE keygen.valid", + r"\[GNUPG:\] GET_LINE keygen.name", + r"\[GNUPG:\] GET_LINE keygen.email", + r"\[GNUPG:\] GET_LINE keygen.comment", + ], + virt::gpg_inquire_pin(), + virt::gpg_inquire_pin(), + vec![ + r"pub:u:\d*:1:[0-9A-F]{16}:[0-9A-F]{10}:::u:::scESC:::\+:::23::0:", + r"fpr:::::::::[0-9A-F]{40}:", + r"grp:::::::::[0-9A-F]{40}:", + &custom_match, + r"sub:u:\d*:1:[0-9A-F]{16}:[0-9A-F]{10}::::::e:::\+:::23:", + r"fpr:::::::::[0-9A-F]{40}:", + r"grp:::::::::[0-9A-F]{40}:", + r"\[GNUPG:\] KEY_CREATED B [A-F0-9]{40}", ], - &[ - vec![ - r"\[GNUPG:\] GET_LINE keygen.algo", - r"\[GNUPG:\] GET_LINE keygen.size", - r"\[GNUPG:\] GET_LINE keygen.size", - r"\[GNUPG:\] GET_LINE keygen.valid", - r"\[GNUPG:\] GET_LINE keygen.name", - r"\[GNUPG:\] GET_LINE keygen.email", - r"\[GNUPG:\] GET_LINE keygen.comment", - ], - virt::gpg_inquire_pin(), - virt::gpg_inquire_pin(), - vec![ - r"pub:u:\d*:1:[0-9A-F]{16}:[0-9A-F]{10}:::u:::scESC:::\+:::23::0:", - r"fpr:::::::::[0-9A-F]{40}:", - r"grp:::::::::[0-9A-F]{40}:", - &custom_match, - r"sub:u:\d*:1:[0-9A-F]{16}:[0-9A-F]{10}::::::e:::\+:::23:", - r"fpr:::::::::[0-9A-F]{40}:", - r"grp:::::::::[0-9A-F]{40}:", - r"\[GNUPG:\] KEY_CREATED B [A-F0-9]{40}", - ], - ] - .into_iter() - .flatten() - .collect::>(), - &[ - r"gpg: revocation certificate stored as '.*\.rev'", - r"gpg: checking the trustdb", - r"gpg: marginals needed: \d completes needed: \d trust model: pgp", - r"gpg: depth:[ 0-9]*valid:[ 0-9]*signed:[ 0-9]*trust: \d*-, \d*q, \d*n, \d*m, \d*f, \d*u", + ] + .into_iter() + .flatten() + .collect::>(), + &[ + r"gpg: revocation certificate stored as '.*\.rev'", + r"gpg: checking the trustdb", + r"gpg: marginals needed: \d completes needed: \d trust model: pgp", + r"gpg: depth:[ 0-9]*valid:[ 0-9]*signed:[ 0-9]*trust: \d*-, \d*q, \d*n, \d*m, \d*f, \d*u", + ], + Generate, + ); + + println!("================ FINISHED GENERATING Rsa2048 KEYS ================"); + + gnupg_test( + &["key *", "keytocard", "2", DEFAULT_PW3, "save"], + &[ + vec![ + r"sec:u:\d*:1:[0-9A-F]{16}:[0-9A-F]{10}:0::u:::sc", + r"fpr:::::::::[0-9A-F]{40}:", + r"ssb:u:\d*:1:[0-9A-F]{16}:[0-9A-F]{10}:0:::::e", + r"fpr:::::::::[0-9A-F]{40}:", + &custom_match2, + r"\[GNUPG:\] GET_LINE keyedit.prompt", + r"sec:u:\d*:1:[0-9A-F]{16}:[0-9A-F]{10}:0::u:::sc", + r"fpr:::::::::[0-9A-F]{40}:", + r"ssb:u:\d*:1:[0-9A-F]{16}:[0-9A-F]{10}:0:::::e", + r"fpr:::::::::[0-9A-F]{40}:", + &custom_match2, + r"\[GNUPG:\] GET_LINE keyedit.prompt", + r"\[GNUPG:\] CARDCTRL 3 D276000124010304[A-F0-9]*", + r"\[GNUPG:\] GET_LINE cardedit.genkeys.storekeytype", ], - Generate, - ); - - println!("================ FINISHED GENERATING Rsa2048 KEYS ================"); - - gnupg_test( - &["key *", "keytocard", "2", DEFAULT_PW3, "save"], - &[ - vec![ - r"sec:u:\d*:1:[0-9A-F]{16}:[0-9A-F]{10}:0::u:::sc", - r"fpr:::::::::[0-9A-F]{40}:", - r"ssb:u:\d*:1:[0-9A-F]{16}:[0-9A-F]{10}:0:::::e", - r"fpr:::::::::[0-9A-F]{40}:", - &custom_match2, - r"\[GNUPG:\] GET_LINE keyedit.prompt", - r"sec:u:\d*:1:[0-9A-F]{16}:[0-9A-F]{10}:0::u:::sc", - r"fpr:::::::::[0-9A-F]{40}:", - r"ssb:u:\d*:1:[0-9A-F]{16}:[0-9A-F]{10}:0:::::e", - r"fpr:::::::::[0-9A-F]{40}:", - &custom_match2, - r"\[GNUPG:\] GET_LINE keyedit.prompt", - r"\[GNUPG:\] CARDCTRL 3 D2760001240103040000000000000000", - r"\[GNUPG:\] GET_LINE cardedit.genkeys.storekeytype", - ], - virt::gpg_inquire_pin(), - // virt::gpg_inquire_pin(), - vec![ - r"sec:u:\d*:1:[0-9A-F]{16}:[0-9A-F]{10}:0::u:::sc", - r"fpr:::::::::[0-9A-F]{40}:", - r"ssb:u:\d*:1:[0-9A-F]{16}:[0-9A-F]{10}:0:::::e", - r"fpr:::::::::[0-9A-F]{40}:", - &custom_match2, - r"\[GNUPG:\] GET_LINE keyedit.prompt", - ], - ] - .into_iter() - .flatten() - .collect::>(), - &[], - EditKey { o: temp_email }, - ); - - println!("================ FINISHED IMPORTING DECRYPTION KEY ================"); - - gnupg_test( - &["keytocard", "y", "1", DEFAULT_PW3, "save"], - &[ - vec![ - r"sec:u:\d*:1:[0-9A-F]{16}:[0-9A-F]{10}:0::u:::sc", - r"fpr:::::::::[0-9A-F]{40}:", - r"ssb:u:\d*:1:[0-9A-F]{16}:[0-9A-F]{10}:0:::::e", - r"fpr:::::::::[0-9A-F]{40}:", - &custom_match2, - r"\[GNUPG:\] GET_LINE keyedit.prompt", - r"\[GNUPG:\] GET_BOOL keyedit.keytocard.use_primary", - r"\[GNUPG:\] CARDCTRL 3 D2760001240103040000000000000000", - r"\[GNUPG:\] GET_LINE cardedit.genkeys.storekeytype", - ], - vec![ - r"sec:u:\d*:1:[0-9A-F]{16}:[0-9A-F]{10}:0::u:::sc", - r"fpr:::::::::[0-9A-F]{40}:", - r"ssb:u:\d*:1:[0-9A-F]{16}:[0-9A-F]{10}:0:::::e", - r"fpr:::::::::[0-9A-F]{40}:", - &custom_match2, - r"\[GNUPG:\] GET_LINE keyedit.prompt", - r"\[GNUPG:\] GET_LINE keyedit.prompt", - ], - ] - .into_iter() - .flatten() - .collect::>(), - &[], - EditKey { o: temp_email }, - ); - - println!("================ FINISHED IMPORTING Rsa2048 KEYS ================"); - - gnupg_test( - &[], - &[ - r"\[GNUPG:\] BEGIN_ENCRYPTION \d \d", - r"\[GNUPG:\] END_ENCRYPTION", + virt::gpg_inquire_pin(), + // virt::gpg_inquire_pin(), + vec![ + r"sec:u:\d*:1:[0-9A-F]{16}:[0-9A-F]{10}:0::u:::sc", + r"fpr:::::::::[0-9A-F]{40}:", + r"ssb:u:\d*:1:[0-9A-F]{16}:[0-9A-F]{10}:0:::::e", + r"fpr:::::::::[0-9A-F]{40}:", + &custom_match2, + r"\[GNUPG:\] GET_LINE keyedit.prompt", ], - &[], - Encrypt { - i: "Cargo.toml", - o: encrypted_file, - r: temp_email, - }, - ); - - println!("================ FINISHED ENCRYPTION ================"); - - let custom1 = format!( - r"\[GNUPG:\] USERID_HINT [a-fA-F0-9]{{16}} {temp_name} \(no comment\) <{temp_email}>" - ); - let custom2 = format!(r"{temp_name} \(no comment\) <{temp_email}>"); - - gnupg_test( - &[DEFAULT_PW1], - &[ - vec![ - r"\[GNUPG:\] ENC_TO [a-fA-F0-9]{16} \d* \d*", - &custom1, - r"\[GNUPG:\] NEED_PASSPHRASE [a-fA-F0-9]{16} [a-fA-F0-9]{16} 1 0", - ], - virt::gpg_inquire_pin(), - vec![ - r"\[GNUPG:\] DECRYPTION_KEY [a-fA-F0-9]{40} [a-fA-F0-9]{40} u", - r"\[GNUPG:\] BEGIN_DECRYPTION", - r"\[GNUPG:\] DECRYPTION_INFO \d \d \d", - r"\[GNUPG:\] PLAINTEXT \d* \d* Cargo.toml", - r"\[GNUPG:\] PLAINTEXT_LENGTH \d*", - r"\[GNUPG:\] DECRYPTION_OKAY", - r"\[GNUPG:\] GOODMDC", - r"\[GNUPG:\] END_DECRYPTION", - ], - ] - .into_iter() - .flatten() - .collect::>(), - &[ - r"gpg: encrypted with \d*-bit RSA key, ID [a-fA-F0-9]{16}, created \d{4}-\d\d-\d\d", - &custom2, + ] + .into_iter() + .flatten() + .collect::>(), + &[], + EditKey { o: temp_email }, + ); + + println!("================ FINISHED IMPORTING DECRYPTION KEY ================"); + + gnupg_test( + &["keytocard", "y", "1", DEFAULT_PW3, "save"], + &[ + vec![ + r"sec:u:\d*:1:[0-9A-F]{16}:[0-9A-F]{10}:0::u:::sc", + r"fpr:::::::::[0-9A-F]{40}:", + r"ssb:u:\d*:1:[0-9A-F]{16}:[0-9A-F]{10}:0:::::e", + r"fpr:::::::::[0-9A-F]{40}:", + &custom_match2, + r"\[GNUPG:\] GET_LINE keyedit.prompt", + r"\[GNUPG:\] GET_BOOL keyedit.keytocard.use_primary", + r"\[GNUPG:\] CARDCTRL 3 D276000124010304[A-F0-9]*", + r"\[GNUPG:\] GET_LINE cardedit.genkeys.storekeytype", ], - Decrypt { - i: encrypted_file, - o: decrypted_file, - }, - ); - - println!("================ FINISHED DECRYPTION ================"); - - gnupg_test( - &[DEFAULT_PW1], - &[ - vec![ - r"\[GNUPG:\] CARDCTRL 3 D2760001240103040000000000000000", - r"\[GNUPG:\] BEGIN_SIGNING H\d*", - &custom1, - r"\[GNUPG:\] NEED_PASSPHRASE [a-fA-F0-9]{16} [a-fA-F0-9]{16} 1 0", - ], - virt::gpg_inquire_pin(), - vec![r"\[GNUPG:\] SIG_CREATED S 1 \d* 00 [a-fA-F0-9]{10} [a-fA-F0-9]{40}"], - ] - .into_iter() - .flatten() - .collect::>(), - &[r#"gpg: using "test\d*@email.com" as default secret key for signing"#], - Sign { - i: "Cargo.toml", - o: sign_file, - s: temp_email, - }, - ); - - println!("================ FINISHED SIGNATURE ================"); - - gnupg_test( - &[], - &[ - r"\[GNUPG:\] NEWSIG test\d*@email.com", - r"\[GNUPG:\] SIG_ID [^ ]* \d{4}-\d\d-\d\d [a-fA-F0-9]{10}", - r"\[GNUPG:\] GOODSIG [a-fA-F0-9]{16} test name\d* \(no comment\) ", - r"\[GNUPG:\] VALIDSIG [a-fA-F0-9]{40} \d{4}-\d\d-\d\d [a-fA-F0-9]{10} \d \d \d 1 \d* 00 [a-fA-F0-9]{40}", - r"\[GNUPG:\] TRUST_ULTIMATE 0 pgp", + vec![ + r"sec:u:\d*:1:[0-9A-F]{16}:[0-9A-F]{10}:0::u:::sc", + r"fpr:::::::::[0-9A-F]{40}:", + r"ssb:u:\d*:1:[0-9A-F]{16}:[0-9A-F]{10}:0:::::e", + r"fpr:::::::::[0-9A-F]{40}:", + &custom_match2, + r"\[GNUPG:\] GET_LINE keyedit.prompt", + r"\[GNUPG:\] GET_LINE keyedit.prompt", ], - &[ - r"gpg: Signature made .*", - r"gpg: using RSA key [a-fA-F0-9]{40}", - r#"gpg: issuer "test\d*@email.com""#, - r#"pg: Good signature from "test name\d* \(no comment\) "#, + ] + .into_iter() + .flatten() + .collect::>(), + &[], + EditKey { o: temp_email }, + ); + + println!("================ FINISHED IMPORTING Rsa2048 KEYS ================"); + + gnupg_test( + &[], + &[ + r"\[GNUPG:\] BEGIN_ENCRYPTION \d \d", + r"\[GNUPG:\] END_ENCRYPTION", + ], + &[], + Encrypt { + i: "Cargo.toml", + o: encrypted_file, + r: temp_email, + }, + ); + + println!("================ FINISHED ENCRYPTION ================"); + + let custom1 = format!( + r"\[GNUPG:\] USERID_HINT [a-fA-F0-9]{{16}} {temp_name} \(no comment\) <{temp_email}>" + ); + let custom2 = format!(r"{temp_name} \(no comment\) <{temp_email}>"); + + gnupg_test( + &[DEFAULT_PW1], + &[ + vec![ + r"\[GNUPG:\] ENC_TO [a-fA-F0-9]{16} \d* \d*", + &custom1, + r"\[GNUPG:\] NEED_PASSPHRASE [a-fA-F0-9]{16} [a-fA-F0-9]{16} 1 0", ], - Verify { i: sign_file }, - ); - - gnupg_test( - &[ - "admin", - "factory-reset", - "y", - "yes", - "verify", - DEFAULT_PW1, - "quit", + virt::gpg_inquire_pin(), + vec![ + r"\[GNUPG:\] DECRYPTION_KEY [a-fA-F0-9]{40} [a-fA-F0-9]{40} u", + r"\[GNUPG:\] BEGIN_DECRYPTION", + r"\[GNUPG:\] DECRYPTION_INFO \d \d \d", + r"\[GNUPG:\] PLAINTEXT \d* \d* Cargo.toml", + r"\[GNUPG:\] PLAINTEXT_LENGTH \d*", + r"\[GNUPG:\] DECRYPTION_OKAY", + r"\[GNUPG:\] GOODMDC", + r"\[GNUPG:\] END_DECRYPTION", ], - &[ - vec![r"\[GNUPG:\] CARDCTRL \d D2760001240103040000000000000000"], - virt::gpg_status(virt::KeyType::RsaNoAut, 1), - vec![ - r"\[GNUPG:\] GET_LINE cardedit.prompt", - r"\[GNUPG:\] GET_LINE cardedit.prompt", - r"\[GNUPG:\] GET_BOOL cardedit.factory-reset.proceed", - r"\[GNUPG:\] GET_LINE cardedit.factory-reset.really", - r"\[GNUPG:\] GET_LINE cardedit.prompt", - ], - virt::gpg_inquire_pin(), - virt::gpg_status(virt::KeyType::RsaNone, 0), - vec![r"\[GNUPG:\] GET_LINE cardedit.prompt"], - ] - .into_iter() - .flatten() - .collect::>(), - &[ - r"gpg: OpenPGP card no. [0-9A-F]{32} detected", - r"gpg: Note: This command destroys all keys stored on the card!", + ] + .into_iter() + .flatten() + .collect::>(), + &[ + r"gpg: encrypted with \d*-bit RSA key, ID [a-fA-F0-9]{16}, created \d{4}-\d\d-\d\d", + &custom2, + ], + Decrypt { + i: encrypted_file, + o: decrypted_file, + }, + ); + + println!("================ FINISHED DECRYPTION ================"); + + gnupg_test( + &[DEFAULT_PW1], + &[ + vec![ + r"\[GNUPG:\] CARDCTRL 3 D276000124010304[A-F0-9]*", + r"\[GNUPG:\] BEGIN_SIGNING H\d*", + &custom1, + r"\[GNUPG:\] NEED_PASSPHRASE [a-fA-F0-9]{16} [a-fA-F0-9]{16} 1 0", ], - EditCard, - ); - }); + virt::gpg_inquire_pin(), + vec![r"\[GNUPG:\] SIG_CREATED S 1 \d* 00 [a-fA-F0-9]{10} [a-fA-F0-9]{40}"], + ] + .into_iter() + .flatten() + .collect::>(), + &[r#"gpg: using "test\d*@email.com" as default secret key for signing"#], + Sign { + i: "Cargo.toml", + o: sign_file, + s: temp_email, + }, + ); + + println!("================ FINISHED SIGNATURE ================"); + + gnupg_test( + &[], + &[ + r"\[GNUPG:\] NEWSIG test\d*@email.com", + r"\[GNUPG:\] SIG_ID [^ ]* \d{4}-\d\d-\d\d [a-fA-F0-9]{10}", + r"\[GNUPG:\] GOODSIG [a-fA-F0-9]{16} test name\d* \(no comment\) ", + r"\[GNUPG:\] VALIDSIG [a-fA-F0-9]{40} \d{4}-\d\d-\d\d [a-fA-F0-9]{10} \d \d \d 1 \d* 00 [a-fA-F0-9]{40}", + r"\[GNUPG:\] TRUST_ULTIMATE 0 pgp", + ], + &[ + r"gpg: Signature made .*", + r"gpg: using RSA key [a-fA-F0-9]{40}", + r#"gpg: issuer "test\d*@email.com""#, + r#"pg: Good signature from "test name\d* \(no comment\) "#, + ], + Verify { i: sign_file }, + ); + + gnupg_test( + &[ + "admin", + "factory-reset", + "y", + "yes", + "verify", + DEFAULT_PW1, + "quit", + ], + &[ + vec![r"\[GNUPG:\] CARDCTRL \d D276000124010304[A-F0-9]*"], + virt::gpg_status(virt::KeyType::RsaNoAut, 1), + vec![ + r"\[GNUPG:\] GET_LINE cardedit.prompt", + r"\[GNUPG:\] GET_LINE cardedit.prompt", + r"\[GNUPG:\] GET_BOOL cardedit.factory-reset.proceed", + r"\[GNUPG:\] GET_LINE cardedit.factory-reset.really", + r"\[GNUPG:\] GET_LINE cardedit.prompt", + ], + virt::gpg_inquire_pin(), + virt::gpg_status(virt::KeyType::RsaNone, 0), + vec![r"\[GNUPG:\] GET_LINE cardedit.prompt"], + ] + .into_iter() + .flatten() + .collect::>(), + &[ + r"gpg: OpenPGP card no. [0-9A-F]{32} detected", + r"gpg: Note: This command destroys all keys stored on the card!", + ], + EditCard, + ); } #[cfg(feature = "rsa4096")] fn gpg_rsa_4096() { - with_vsc(|| { - let file_number: u32 = rand::rngs::OsRng.gen(); - let tmp = format!("/tmp/opcard-tests-{file_number}.gpg"); - let encrypted_file = &tmp; - let tmp = format!("/tmp/opcard-tests-{file_number}-sig.gpg"); - let sign_file = &tmp; - let tmp = format!("/tmp/opcard-tests-{file_number}.toml"); - let decrypted_file = &tmp; - let _dropper = FileDropper { - temp_file_name: encrypted_file, - }; - let _dropper = FileDropper { - temp_file_name: sign_file, - }; - let _dropper = FileDropper { - temp_file_name: decrypted_file, - }; - - let tmp = format!("test name{file_number}"); - let temp_name = &tmp; - - let tmp = format!("test{file_number}@email.com"); - let temp_email = &tmp; - - let custom_match = format!( - r"uid:u::::\d{{10}}::[0-9A-F]{{40}}::{temp_name} \(no comment\) <{temp_email}>::::::::::0:" - ); - - let custom_match2 = format!( - r"uid:u::::::::{temp_name} \(no comment\) <{temp_email}>:::.*,mdc,no-ks-modify:1,p::" - ); - - gnupg_test( - &[ - "1", - "4096", - "4096", - "0", - temp_name, - temp_email, - "no comment", - "", - "", + let file_number: u32 = rand::rngs::OsRng.gen(); + let tmp = format!("/tmp/opcard-tests-{file_number}.gpg"); + let encrypted_file = &tmp; + let tmp = format!("/tmp/opcard-tests-{file_number}-sig.gpg"); + let sign_file = &tmp; + let tmp = format!("/tmp/opcard-tests-{file_number}.toml"); + let decrypted_file = &tmp; + let _dropper = FileDropper { + temp_file_name: encrypted_file, + }; + let _dropper = FileDropper { + temp_file_name: sign_file, + }; + let _dropper = FileDropper { + temp_file_name: decrypted_file, + }; + + let tmp = format!("test name{file_number}"); + let temp_name = &tmp; + + let tmp = format!("test{file_number}@email.com"); + let temp_email = &tmp; + + let custom_match = format!( + r"uid:u::::\d{{10}}::[0-9A-F]{{40}}::{temp_name} \(no comment\) <{temp_email}>::::::::::0:" + ); + + let custom_match2 = format!( + r"uid:u::::::::{temp_name} \(no comment\) <{temp_email}>:::.*,mdc,no-ks-modify:1,p::" + ); + + gnupg_test( + &[], + &[ + vec![r"\[GNUPG:\] CARDCTRL \d D276000124010304[A-Z0-9]*"], + virt::gpg_status(virt::KeyType::RsaNone, 0), + ] + .into_iter() + .flatten() + .collect::>(), + &[], + CardStatus, + ); + + gnupg_test( + &[ + "1", + "4096", + "4096", + "0", + temp_name, + temp_email, + "no comment", + "", + "", + ], + &[ + vec![ + r"\[GNUPG:\] GET_LINE keygen.algo", + r"\[GNUPG:\] GET_LINE keygen.size", + r"\[GNUPG:\] GET_LINE keygen.size", + r"\[GNUPG:\] GET_LINE keygen.valid", + r"\[GNUPG:\] GET_LINE keygen.name", + r"\[GNUPG:\] GET_LINE keygen.email", + r"\[GNUPG:\] GET_LINE keygen.comment", + ], + virt::gpg_inquire_pin(), + virt::gpg_inquire_pin(), + vec![ + r"pub:u:\d*:1:[0-9A-F]{16}:[0-9A-F]{10}:::u:::scESC:::\+:::23::0:", + r"fpr:::::::::[0-9A-F]{40}:", + r"grp:::::::::[0-9A-F]{40}:", + &custom_match, + r"sub:u:\d*:1:[0-9A-F]{16}:[0-9A-F]{10}::::::e:::\+:::23:", + r"fpr:::::::::[0-9A-F]{40}:", + r"grp:::::::::[0-9A-F]{40}:", + r"\[GNUPG:\] KEY_CREATED B [A-F0-9]{40}", ], - &[ - vec![ - r"\[GNUPG:\] GET_LINE keygen.algo", - r"\[GNUPG:\] GET_LINE keygen.size", - r"\[GNUPG:\] GET_LINE keygen.size", - r"\[GNUPG:\] GET_LINE keygen.valid", - r"\[GNUPG:\] GET_LINE keygen.name", - r"\[GNUPG:\] GET_LINE keygen.email", - r"\[GNUPG:\] GET_LINE keygen.comment", - ], - virt::gpg_inquire_pin(), - virt::gpg_inquire_pin(), - vec![ - r"pub:u:\d*:1:[0-9A-F]{16}:[0-9A-F]{10}:::u:::scESC:::\+:::23::0:", - r"fpr:::::::::[0-9A-F]{40}:", - r"grp:::::::::[0-9A-F]{40}:", - &custom_match, - r"sub:u:\d*:1:[0-9A-F]{16}:[0-9A-F]{10}::::::e:::\+:::23:", - r"fpr:::::::::[0-9A-F]{40}:", - r"grp:::::::::[0-9A-F]{40}:", - r"\[GNUPG:\] KEY_CREATED B [A-F0-9]{40}", - ], - ] - .into_iter() - .flatten() - .collect::>(), - &[ - r"gpg: revocation certificate stored as '.*\.rev'", - r"gpg: checking the trustdb", - r"gpg: marginals needed: \d completes needed: \d trust model: pgp", - r"gpg: depth:[ 0-9]*valid:[ 0-9]*signed:[ 0-9]*trust: \d*-, \d*q, \d*n, \d*m, \d*f, \d*u", + ] + .into_iter() + .flatten() + .collect::>(), + &[ + r"gpg: revocation certificate stored as '.*\.rev'", + r"gpg: checking the trustdb", + r"gpg: marginals needed: \d completes needed: \d trust model: pgp", + r"gpg: depth:[ 0-9]*valid:[ 0-9]*signed:[ 0-9]*trust: \d*-, \d*q, \d*n, \d*m, \d*f, \d*u", + ], + Generate, + ); + + println!("================ FINISHED GENERATING Rsa4096 KEYS ================"); + + gnupg_test( + &["key *", "keytocard", "2", DEFAULT_PW3, DEFAULT_PW3, "save"], + &[ + vec![ + r"sec:u:\d*:1:[0-9A-F]{16}:[0-9A-F]{10}:0::u:::sc", + r"fpr:::::::::[0-9A-F]{40}:", + r"ssb:u:\d*:1:[0-9A-F]{16}:[0-9A-F]{10}:0:::::e", + r"fpr:::::::::[0-9A-F]{40}:", + &custom_match2, + r"\[GNUPG:\] GET_LINE keyedit.prompt", + r"sec:u:\d*:1:[0-9A-F]{16}:[0-9A-F]{10}:0::u:::sc", + r"fpr:::::::::[0-9A-F]{40}:", + r"ssb:u:\d*:1:[0-9A-F]{16}:[0-9A-F]{10}:0:::::e", + r"fpr:::::::::[0-9A-F]{40}:", + &custom_match2, + r"\[GNUPG:\] GET_LINE keyedit.prompt", + r"\[GNUPG:\] CARDCTRL 3 D276000124010304[A-F0-9]*", + r"\[GNUPG:\] GET_LINE cardedit.genkeys.storekeytype", ], - Generate, - ); - - println!("================ FINISHED GENERATING Rsa4096 KEYS ================"); - - gnupg_test( - &["key *", "keytocard", "2", DEFAULT_PW3, DEFAULT_PW3, "save"], - &[ - vec![ - r"sec:u:\d*:1:[0-9A-F]{16}:[0-9A-F]{10}:0::u:::sc", - r"fpr:::::::::[0-9A-F]{40}:", - r"ssb:u:\d*:1:[0-9A-F]{16}:[0-9A-F]{10}:0:::::e", - r"fpr:::::::::[0-9A-F]{40}:", - &custom_match2, - r"\[GNUPG:\] GET_LINE keyedit.prompt", - r"sec:u:\d*:1:[0-9A-F]{16}:[0-9A-F]{10}:0::u:::sc", - r"fpr:::::::::[0-9A-F]{40}:", - r"ssb:u:\d*:1:[0-9A-F]{16}:[0-9A-F]{10}:0:::::e", - r"fpr:::::::::[0-9A-F]{40}:", - &custom_match2, - r"\[GNUPG:\] GET_LINE keyedit.prompt", - r"\[GNUPG:\] CARDCTRL 3 D2760001240103040000000000000000", - r"\[GNUPG:\] GET_LINE cardedit.genkeys.storekeytype", - ], - virt::gpg_inquire_pin(), - virt::gpg_inquire_pin(), - vec![ - r"sec:u:\d*:1:[0-9A-F]{16}:[0-9A-F]{10}:0::u:::sc", - r"fpr:::::::::[0-9A-F]{40}:", - r"ssb:u:\d*:1:[0-9A-F]{16}:[0-9A-F]{10}:0:::::e", - r"fpr:::::::::[0-9A-F]{40}:", - &custom_match2, - r"\[GNUPG:\] GET_LINE keyedit.prompt", - ], - ] - .into_iter() - .flatten() - .collect::>(), - &[], - EditKey { o: temp_email }, - ); - - println!("================ FINISHED IMPORTING DECRYPTION KEY ================"); - - gnupg_test( - &["keytocard", "y", "1", DEFAULT_PW3, "save"], - &[ - vec![ - r"sec:u:\d*:1:[0-9A-F]{16}:[0-9A-F]{10}:0::u:::sc", - r"fpr:::::::::[0-9A-F]{40}:", - r"ssb:u:\d*:1:[0-9A-F]{16}:[0-9A-F]{10}:0:::::e", - r"fpr:::::::::[0-9A-F]{40}:", - &custom_match2, - r"\[GNUPG:\] GET_LINE keyedit.prompt", - r"\[GNUPG:\] GET_BOOL keyedit.keytocard.use_primary", - r"\[GNUPG:\] CARDCTRL 3 D2760001240103040000000000000000", - r"\[GNUPG:\] GET_LINE cardedit.genkeys.storekeytype", - ], - virt::gpg_inquire_pin(), - vec![ - r"sec:u:\d*:1:[0-9A-F]{16}:[0-9A-F]{10}:0::u:::sc", - r"fpr:::::::::[0-9A-F]{40}:", - r"ssb:u:\d*:1:[0-9A-F]{16}:[0-9A-F]{10}:0:::::e", - r"fpr:::::::::[0-9A-F]{40}:", - &custom_match2, - r"\[GNUPG:\] GET_LINE keyedit.prompt", - ], - ] - .into_iter() - .flatten() - .collect::>(), - &[], - EditKey { o: temp_email }, - ); - - println!("================ FINISHED IMPORTING Rsa4096 KEYS ================"); - - gnupg_test( - &[], - &[ - r"\[GNUPG:\] BEGIN_ENCRYPTION \d \d", - r"\[GNUPG:\] END_ENCRYPTION", + virt::gpg_inquire_pin(), + virt::gpg_inquire_pin(), + vec![ + r"sec:u:\d*:1:[0-9A-F]{16}:[0-9A-F]{10}:0::u:::sc", + r"fpr:::::::::[0-9A-F]{40}:", + r"ssb:u:\d*:1:[0-9A-F]{16}:[0-9A-F]{10}:0:::::e", + r"fpr:::::::::[0-9A-F]{40}:", + &custom_match2, + r"\[GNUPG:\] GET_LINE keyedit.prompt", ], - &[], - Encrypt { - i: "Cargo.toml", - o: encrypted_file, - r: temp_email, - }, - ); - - println!("================ FINISHED ENCRYPTION ================"); - - let custom1 = format!( - r"\[GNUPG:\] USERID_HINT [a-fA-F0-9]{{16}} {temp_name} \(no comment\) <{temp_email}>" - ); - let custom2 = format!(r"{temp_name} \(no comment\) <{temp_email}>"); - - gnupg_test( - &[DEFAULT_PW1], - &[ - vec![ - r"\[GNUPG:\] ENC_TO [a-fA-F0-9]{16} \d* \d*", - &custom1, - r"\[GNUPG:\] NEED_PASSPHRASE [a-fA-F0-9]{16} [a-fA-F0-9]{16} 1 0", - ], - virt::gpg_inquire_pin(), - vec![ - r"\[GNUPG:\] DECRYPTION_KEY [a-fA-F0-9]{40} [a-fA-F0-9]{40} u", - r"\[GNUPG:\] BEGIN_DECRYPTION", - r"\[GNUPG:\] DECRYPTION_INFO \d \d \d", - r"\[GNUPG:\] PLAINTEXT \d* \d* Cargo.toml", - r"\[GNUPG:\] PLAINTEXT_LENGTH \d*", - r"\[GNUPG:\] DECRYPTION_OKAY", - r"\[GNUPG:\] GOODMDC", - r"\[GNUPG:\] END_DECRYPTION", - ], - ] - .into_iter() - .flatten() - .collect::>(), - &[ - r"gpg: encrypted with \d*-bit RSA key, ID [a-fA-F0-9]{16}, created \d{4}-\d\d-\d\d", - &custom2, + ] + .into_iter() + .flatten() + .collect::>(), + &[], + EditKey { o: temp_email }, + ); + + println!("================ FINISHED IMPORTING DECRYPTION KEY ================"); + + gnupg_test( + &["keytocard", "y", "1", DEFAULT_PW3, "save"], + &[ + vec![ + r"sec:u:\d*:1:[0-9A-F]{16}:[0-9A-F]{10}:0::u:::sc", + r"fpr:::::::::[0-9A-F]{40}:", + r"ssb:u:\d*:1:[0-9A-F]{16}:[0-9A-F]{10}:0:::::e", + r"fpr:::::::::[0-9A-F]{40}:", + &custom_match2, + r"\[GNUPG:\] GET_LINE keyedit.prompt", + r"\[GNUPG:\] GET_BOOL keyedit.keytocard.use_primary", + r"\[GNUPG:\] CARDCTRL 3 D276000124010304[A-F0-9]*", + r"\[GNUPG:\] GET_LINE cardedit.genkeys.storekeytype", ], - Decrypt { - i: encrypted_file, - o: decrypted_file, - }, - ); - - println!("================ FINISHED DECRYPTION ================"); - - gnupg_test( - &[DEFAULT_PW1], - &[ - vec![ - r"\[GNUPG:\] CARDCTRL 3 D2760001240103040000000000000000", - r"\[GNUPG:\] BEGIN_SIGNING H\d*", - &custom1, - r"\[GNUPG:\] NEED_PASSPHRASE [a-fA-F0-9]{16} [a-fA-F0-9]{16} 1 0", - ], - virt::gpg_inquire_pin(), - vec![r"\[GNUPG:\] SIG_CREATED S 1 \d* 00 [a-fA-F0-9]{10} [a-fA-F0-9]{40}"], - ] - .into_iter() - .flatten() - .collect::>(), - &[r#"gpg: using "test\d*@email.com" as default secret key for signing"#], - Sign { - i: "Cargo.toml", - o: sign_file, - s: temp_email, - }, - ); - - println!("================ FINISHED SIGNATURE ================"); - - gnupg_test( - &[], - &[ - r"\[GNUPG:\] NEWSIG test\d*@email.com", - r"\[GNUPG:\] SIG_ID [^ ]* \d{4}-\d\d-\d\d [a-fA-F0-9]{10}", - r"\[GNUPG:\] GOODSIG [a-fA-F0-9]{16} test name\d* \(no comment\) ", - r"\[GNUPG:\] VALIDSIG [a-fA-F0-9]{40} \d{4}-\d\d-\d\d [a-fA-F0-9]{10} \d \d \d 1 \d* 00 [a-fA-F0-9]{40}", - r"\[GNUPG:\] TRUST_ULTIMATE 0 pgp", + virt::gpg_inquire_pin(), + vec![ + r"sec:u:\d*:1:[0-9A-F]{16}:[0-9A-F]{10}:0::u:::sc", + r"fpr:::::::::[0-9A-F]{40}:", + r"ssb:u:\d*:1:[0-9A-F]{16}:[0-9A-F]{10}:0:::::e", + r"fpr:::::::::[0-9A-F]{40}:", + &custom_match2, + r"\[GNUPG:\] GET_LINE keyedit.prompt", ], - &[ - r"gpg: Signature made .*", - r"gpg: using RSA key [a-fA-F0-9]{40}", - r#"gpg: issuer "test\d*@email.com""#, - r#"pg: Good signature from "test name\d* \(no comment\) "#, + ] + .into_iter() + .flatten() + .collect::>(), + &[], + EditKey { o: temp_email }, + ); + + println!("================ FINISHED IMPORTING Rsa4096 KEYS ================"); + + gnupg_test( + &[], + &[ + r"\[GNUPG:\] BEGIN_ENCRYPTION \d \d", + r"\[GNUPG:\] END_ENCRYPTION", + ], + &[], + Encrypt { + i: "Cargo.toml", + o: encrypted_file, + r: temp_email, + }, + ); + + println!("================ FINISHED ENCRYPTION ================"); + + let custom1 = format!( + r"\[GNUPG:\] USERID_HINT [a-fA-F0-9]{{16}} {temp_name} \(no comment\) <{temp_email}>" + ); + let custom2 = format!(r"{temp_name} \(no comment\) <{temp_email}>"); + + gnupg_test( + &[DEFAULT_PW1], + &[ + vec![ + r"\[GNUPG:\] ENC_TO [a-fA-F0-9]{16} \d* \d*", + &custom1, + r"\[GNUPG:\] NEED_PASSPHRASE [a-fA-F0-9]{16} [a-fA-F0-9]{16} 1 0", ], - Verify { i: sign_file }, - ); - - gnupg_test( - &[ - "admin", - "factory-reset", - "y", - "yes", - "verify", - DEFAULT_PW1, - "quit", + virt::gpg_inquire_pin(), + vec![ + r"\[GNUPG:\] DECRYPTION_KEY [a-fA-F0-9]{40} [a-fA-F0-9]{40} u", + r"\[GNUPG:\] BEGIN_DECRYPTION", + r"\[GNUPG:\] DECRYPTION_INFO \d \d \d", + r"\[GNUPG:\] PLAINTEXT \d* \d* Cargo.toml", + r"\[GNUPG:\] PLAINTEXT_LENGTH \d*", + r"\[GNUPG:\] DECRYPTION_OKAY", + r"\[GNUPG:\] GOODMDC", + r"\[GNUPG:\] END_DECRYPTION", ], - &[ - vec![r"\[GNUPG:\] CARDCTRL \d D2760001240103040000000000000000"], - virt::gpg_status(virt::KeyType::Rsa4096NoAut, 1), - vec![ - r"\[GNUPG:\] GET_LINE cardedit.prompt", - r"\[GNUPG:\] GET_LINE cardedit.prompt", - r"\[GNUPG:\] GET_BOOL cardedit.factory-reset.proceed", - r"\[GNUPG:\] GET_LINE cardedit.factory-reset.really", - r"\[GNUPG:\] GET_LINE cardedit.prompt", - ], - virt::gpg_inquire_pin(), - virt::gpg_status(virt::KeyType::RsaNone, 0), - vec![r"\[GNUPG:\] GET_LINE cardedit.prompt"], - ] - .into_iter() - .flatten() - .collect::>(), - &[ - r"gpg: OpenPGP card no. [0-9A-F]{32} detected", - r"gpg: Note: This command destroys all keys stored on the card!", + ] + .into_iter() + .flatten() + .collect::>(), + &[ + r"gpg: encrypted with \d*-bit RSA key, ID [a-fA-F0-9]{16}, created \d{4}-\d\d-\d\d", + &custom2, + ], + Decrypt { + i: encrypted_file, + o: decrypted_file, + }, + ); + + println!("================ FINISHED DECRYPTION ================"); + + gnupg_test( + &[DEFAULT_PW1], + &[ + vec![ + r"\[GNUPG:\] CARDCTRL 3 D276000124010304[A-F0-9]*", + r"\[GNUPG:\] BEGIN_SIGNING H\d*", + &custom1, + r"\[GNUPG:\] NEED_PASSPHRASE [a-fA-F0-9]{16} [a-fA-F0-9]{16} 1 0", ], - EditCard, - ); - }); + virt::gpg_inquire_pin(), + vec![r"\[GNUPG:\] SIG_CREATED S 1 \d* 00 [a-fA-F0-9]{10} [a-fA-F0-9]{40}"], + ] + .into_iter() + .flatten() + .collect::>(), + &[r#"gpg: using "test\d*@email.com" as default secret key for signing"#], + Sign { + i: "Cargo.toml", + o: sign_file, + s: temp_email, + }, + ); + + println!("================ FINISHED SIGNATURE ================"); + + gnupg_test( + &[], + &[ + r"\[GNUPG:\] NEWSIG test\d*@email.com", + r"\[GNUPG:\] SIG_ID [^ ]* \d{4}-\d\d-\d\d [a-fA-F0-9]{10}", + r"\[GNUPG:\] GOODSIG [a-fA-F0-9]{16} test name\d* \(no comment\) ", + r"\[GNUPG:\] VALIDSIG [a-fA-F0-9]{40} \d{4}-\d\d-\d\d [a-fA-F0-9]{10} \d \d \d 1 \d* 00 [a-fA-F0-9]{40}", + r"\[GNUPG:\] TRUST_ULTIMATE 0 pgp", + ], + &[ + r"gpg: Signature made .*", + r"gpg: using RSA key [a-fA-F0-9]{40}", + r#"gpg: issuer "test\d*@email.com""#, + r#"pg: Good signature from "test name\d* \(no comment\) "#, + ], + Verify { i: sign_file }, + ); + + gnupg_test( + &[ + "admin", + "factory-reset", + "y", + "yes", + "verify", + DEFAULT_PW1, + "quit", + ], + &[ + vec![r"\[GNUPG:\] CARDCTRL \d D276000124010304[A-F0-9]*"], + virt::gpg_status(virt::KeyType::Rsa4096NoAut, 1), + vec![ + r"\[GNUPG:\] GET_LINE cardedit.prompt", + r"\[GNUPG:\] GET_LINE cardedit.prompt", + r"\[GNUPG:\] GET_BOOL cardedit.factory-reset.proceed", + r"\[GNUPG:\] GET_LINE cardedit.factory-reset.really", + r"\[GNUPG:\] GET_LINE cardedit.prompt", + ], + virt::gpg_inquire_pin(), + virt::gpg_status(virt::KeyType::RsaNone, 0), + vec![r"\[GNUPG:\] GET_LINE cardedit.prompt"], + ] + .into_iter() + .flatten() + .collect::>(), + &[ + r"gpg: OpenPGP card no. [0-9A-F]{32} detected", + r"gpg: Note: This command destroys all keys stored on the card!", + ], + EditCard, + ); } +#[cfg(all(feature = "virtual", not(feature = "dangerous-test-real-card")))] #[test] -fn gpg_crypto_import() { - #[cfg(feature = "rsa2048")] - gpg_rsa_2048(); +fn gpg_crypto() { #[cfg(feature = "rsa2048")] - gpg_rsa_4096(); + with_vsc(gpg_rsa_2048); + #[cfg(feature = "rsa4096")] + with_vsc(gpg_rsa_4096); + with_vsc(gpg_255); + with_vsc(gpg_p256); +} +#[cfg(feature = "dangerous-test-real-card")] +#[test] +fn gpg_crypto() { gpg_255(); gpg_p256(); + #[cfg(feature = "rsa2048")] + gpg_rsa_2048(); + #[cfg(feature = "rsa4096")] + gpg_rsa_4096(); } diff --git a/tests/crypto-gpg.rs b/tests/crypto-gpg.rs index abcfe1ef..748a3811 100644 --- a/tests/crypto-gpg.rs +++ b/tests/crypto-gpg.rs @@ -1,7 +1,7 @@ // Copyright (C) 2022 Nitrokey GmbH // SPDX-License-Identifier: LGPL-3.0-only +#![cfg(any(feature = "virtual", feature = "dangerous-test-real-card"))] -#![cfg(feature = "virtual")] mod virt; use std::iter; @@ -9,8 +9,12 @@ use std::iter; use rand::Rng; use test_log::test; +use virt::gnupg_test; use virt::GpgCommand::*; -use virt::{gnupg_test, with_vsc}; + +#[cfg(feature = "virtual")] +#[allow(unused)] +use virt::with_vsc; fn attr_ec_ask() -> Vec<&'static str> { iter::repeat( @@ -54,35 +58,47 @@ impl<'s> Drop for FileDropper<'s> { } fn gpg_255() { - with_vsc(|| { - let file_number: u32 = rand::rngs::OsRng.gen(); - let tmp = format!("/tmp/opcard-tests-{file_number}.gpg"); - let encrypted_file = &tmp; - let tmp = format!("/tmp/opcard-tests-{file_number}-sig.gpg"); - let sign_file = &tmp; - let tmp = format!("/tmp/opcard-tests-{file_number}.toml"); - let decrypted_file = &tmp; - let _dropper = FileDropper { - temp_file_name: encrypted_file, - }; - let _dropper = FileDropper { - temp_file_name: sign_file, - }; - let _dropper = FileDropper { - temp_file_name: decrypted_file, - }; - - let tmp = format!("test name{file_number}"); - let temp_name = &tmp; - - let tmp = format!("test{file_number}@email.com"); - let temp_email = &tmp; - - let custom_match = format!( - r"uid:u::::\d{{10}}::[0-9A-F]{{40}}::{temp_name} \(no comment\) <{temp_email}>::::::::::0:" - ); + let file_number: u32 = rand::rngs::OsRng.gen(); + let tmp = format!("/tmp/opcard-tests-{file_number}.gpg"); + let encrypted_file = &tmp; + let tmp = format!("/tmp/opcard-tests-{file_number}-sig.gpg"); + let sign_file = &tmp; + let tmp = format!("/tmp/opcard-tests-{file_number}.toml"); + let decrypted_file = &tmp; + let _dropper = FileDropper { + temp_file_name: encrypted_file, + }; + let _dropper = FileDropper { + temp_file_name: sign_file, + }; + let _dropper = FileDropper { + temp_file_name: decrypted_file, + }; + + let tmp = format!("test name{file_number}"); + let temp_name = &tmp; + + let tmp = format!("test{file_number}@email.com"); + let temp_email = &tmp; + + let custom_match = format!( + r"uid:u::::\d{{10}}::[0-9A-F]{{40}}::{temp_name} \(no comment\) <{temp_email}>::::::::::0:" + ); + + gnupg_test( + &[], + &[ + vec![r"\[GNUPG:\] CARDCTRL \d D276000124010304[A-Z0-9]*"], + virt::gpg_status(virt::KeyType::RsaNone, 0), + ] + .into_iter() + .flatten() + .collect::>(), + &[], + CardStatus, + ); - gnupg_test( + gnupg_test( &[ "admin", "key-attr", @@ -107,7 +123,7 @@ fn gpg_255() { "quit", ], &[ - vec![r"\[GNUPG:\] CARDCTRL \d D2760001240103040000000000000000"], + vec![r"\[GNUPG:\] CARDCTRL \d D276000124010304[A-Z0-9]*"], virt::gpg_status(virt::KeyType::RsaNone,0), vec![ r"\[GNUPG:\] GET_LINE cardedit.prompt", @@ -130,14 +146,14 @@ fn gpg_255() { ], virt::gpg_inquire_pin(), vec![ - r"pub:u:\d*:22:[0-9A-F]{16}:[0-9A-F]{10}:::u:::scESCA:::D2760001240103040000000000000000::ed25519:::0:", + r"pub:u:\d*:22:[0-9A-F]{16}:[0-9A-F]{10}:::u:::scESCA:::D276000124010304[A-Z0-9]*::ed25519:::0:", r"fpr:::::::::[0-9A-F]{40}:", r"grp:::::::::[0-9A-F]{40}:", &custom_match, - r"sub:u:\d*:22:[0-9A-F]{16}:[0-9A-F]{10}::::::a:::D2760001240103040000000000000000::ed25519::", + r"sub:u:\d*:22:[0-9A-F]{16}:[0-9A-F]{10}::::::a:::D276000124010304[A-Z0-9]*::ed25519::", r"fpr:::::::::[0-9A-F]{40}:", r"grp:::::::::[0-9A-F]{40}:", - r"sub:u:\d*:18:[0-9A-F]{16}:[0-9A-F]{10}::::::e:::D2760001240103040000000000000000::cv25519::", + r"sub:u:\d*:18:[0-9A-F]{16}:[0-9A-F]{10}::::::e:::D276000124010304[A-Z0-9]*::cv25519::", r"fpr:::::::::[0-9A-F]{40}:", r"grp:::::::::[0-9A-F]{40}:", r"\[GNUPG:\] KEY_CREATED B [0-9A-F]{40}", @@ -153,171 +169,182 @@ fn gpg_255() { EditCard, ); - println!("================ FINISHED GENERATING 25519 KEYS ================"); + println!("================ FINISHED GENERATING 25519 KEYS ================"); - gnupg_test( - &[], - &[ - r"\[GNUPG:\] BEGIN_ENCRYPTION \d \d", - r"\[GNUPG:\] END_ENCRYPTION", - ], - &[], - Encrypt { - i: "Cargo.toml", - o: encrypted_file, - r: temp_email, - }, - ); + gnupg_test( + &[], + &[ + r"\[GNUPG:\] BEGIN_ENCRYPTION \d \d", + r"\[GNUPG:\] END_ENCRYPTION", + ], + &[], + Encrypt { + i: "Cargo.toml", + o: encrypted_file, + r: temp_email, + }, + ); - println!("================ FINISHED ENCRYPTION ================"); + println!("================ FINISHED ENCRYPTION ================"); - let custom1 = format!( - r"\[GNUPG:\] USERID_HINT [a-fA-F0-9]{{16}} {temp_name} \(no comment\) <{temp_email}>" - ); - let custom2 = format!(r"{temp_name} \(no comment\) <{temp_email}>"); - gnupg_test( - &[DEFAULT_PW1], - &[ - vec![ - r"\[GNUPG:\] ENC_TO [a-fA-F0-9]{16} \d* \d*", - &custom1, - r"\[GNUPG:\] NEED_PASSPHRASE [a-fA-F0-9]{16} [a-fA-F0-9]{16} 18 0", - ], - virt::gpg_inquire_pin(), - vec![ - r"\[GNUPG:\] DECRYPTION_KEY [a-fA-F0-9]{40} [a-fA-F0-9]{40} u", - r"\[GNUPG:\] BEGIN_DECRYPTION", - r"\[GNUPG:\] DECRYPTION_INFO \d \d \d", - r"\[GNUPG:\] PLAINTEXT \d* \d* Cargo.toml", - r"\[GNUPG:\] PLAINTEXT_LENGTH \d*", - r"\[GNUPG:\] DECRYPTION_OKAY", - r"\[GNUPG:\] GOODMDC", - r"\[GNUPG:\] END_DECRYPTION", - ], - ] - .into_iter() - .flatten() - .collect::>(), - &[ - r"gpg: encrypted with \d*-bit ECDH key, ID [a-fA-F0-9]{16}, created \d{4}-\d\d-\d\d", - &custom2, + let custom1 = format!( + r"\[GNUPG:\] USERID_HINT [a-fA-F0-9]{{16}} {temp_name} \(no comment\) <{temp_email}>" + ); + let custom2 = format!(r"{temp_name} \(no comment\) <{temp_email}>"); + gnupg_test( + &[DEFAULT_PW1], + &[ + vec![ + r"\[GNUPG:\] ENC_TO [a-fA-F0-9]{16} \d* \d*", + &custom1, + r"\[GNUPG:\] NEED_PASSPHRASE [a-fA-F0-9]{16} [a-fA-F0-9]{16} 18 0", ], - Decrypt { - i: encrypted_file, - o: decrypted_file, - }, - ); + virt::gpg_inquire_pin(), + vec![ + r"\[GNUPG:\] DECRYPTION_KEY [a-fA-F0-9]{40} [a-fA-F0-9]{40} u", + r"\[GNUPG:\] BEGIN_DECRYPTION", + r"\[GNUPG:\] DECRYPTION_INFO \d \d \d", + r"\[GNUPG:\] PLAINTEXT \d* \d* Cargo.toml", + r"\[GNUPG:\] PLAINTEXT_LENGTH \d*", + r"\[GNUPG:\] DECRYPTION_OKAY", + r"\[GNUPG:\] GOODMDC", + r"\[GNUPG:\] END_DECRYPTION", + ], + ] + .into_iter() + .flatten() + .collect::>(), + &[ + r"gpg: encrypted with \d*-bit ECDH key, ID [a-fA-F0-9]{16}, created \d{4}-\d\d-\d\d", + &custom2, + ], + Decrypt { + i: encrypted_file, + o: decrypted_file, + }, + ); - println!("================ FINISHED DECRYPTION ================"); + println!("================ FINISHED DECRYPTION ================"); - gnupg_test( - &[DEFAULT_PW1], - &[ - vec![ - r"\[GNUPG:\] CARDCTRL 3 D2760001240103040000000000000000", - r"\[GNUPG:\] BEGIN_SIGNING H\d*", - &custom1, - r"\[GNUPG:\] NEED_PASSPHRASE [a-fA-F0-9]{16} [a-fA-F0-9]{16} 22 0", - ], - virt::gpg_inquire_pin(), - vec![r"\[GNUPG:\] SIG_CREATED S 22 8 00 [a-fA-F0-9]{10} [a-fA-F0-9]{40}"], - ] - .into_iter() - .flatten() - .collect::>(), - &[r#"gpg: using "test\d*@email.com" as default secret key for signing"#], - Sign { - i: "Cargo.toml", - o: sign_file, - s: temp_email, - }, - ); + gnupg_test( + &[DEFAULT_PW1], + &[ + vec![ + r"\[GNUPG:\] CARDCTRL 3 D276000124010304[A-Z0-9]*", + r"\[GNUPG:\] BEGIN_SIGNING H\d*", + &custom1, + r"\[GNUPG:\] NEED_PASSPHRASE [a-fA-F0-9]{16} [a-fA-F0-9]{16} 22 0", + ], + virt::gpg_inquire_pin(), + vec![r"\[GNUPG:\] SIG_CREATED S 22 8 00 [a-fA-F0-9]{10} [a-fA-F0-9]{40}"], + ] + .into_iter() + .flatten() + .collect::>(), + &[r#"gpg: using "test\d*@email.com" as default secret key for signing"#], + Sign { + i: "Cargo.toml", + o: sign_file, + s: temp_email, + }, + ); - println!("================ FINISHED SIGNATURE ================"); + println!("================ FINISHED SIGNATURE ================"); - gnupg_test( - &[], - &[ - r"\[GNUPG:\] NEWSIG test\d*@email.com", - r"\[GNUPG:\] SIG_ID [^ ]* \d{4}-\d\d-\d\d [a-fA-F0-9]{10}", - r"\[GNUPG:\] GOODSIG [a-fA-F0-9]{16} test name\d* \(no comment\) ", - r"\[GNUPG:\] VALIDSIG [a-fA-F0-9]{40} \d{4}-\d\d-\d\d [a-fA-F0-9]{10} \d \d \d 22 8 00 [a-fA-F0-9]{40}", - r"\[GNUPG:\] TRUST_ULTIMATE 0 pgp", - ], - &[ - r"gpg: Signature made .*", - r"gpg: using EDDSA key [a-fA-F0-9]{40}", - r#"gpg: issuer "test\d*@email.com""#, - r#"pg: Good signature from "test name\d* \(no comment\) "#, - ], - Verify { i: sign_file }, - ); - gnupg_test( - &[ - "admin", - "factory-reset", - "y", - "yes", - "verify", - DEFAULT_PW1, - "quit", + gnupg_test( + &[], + &[ + r"\[GNUPG:\] NEWSIG test\d*@email.com", + r"\[GNUPG:\] SIG_ID [^ ]* \d{4}-\d\d-\d\d [a-fA-F0-9]{10}", + r"\[GNUPG:\] GOODSIG [a-fA-F0-9]{16} test name\d* \(no comment\) ", + r"\[GNUPG:\] VALIDSIG [a-fA-F0-9]{40} \d{4}-\d\d-\d\d [a-fA-F0-9]{10} \d \d \d 22 8 00 [a-fA-F0-9]{40}", + r"\[GNUPG:\] TRUST_ULTIMATE 0 pgp", + ], + &[ + r"gpg: Signature made .*", + r"gpg: using EDDSA key [a-fA-F0-9]{40}", + r#"gpg: issuer "test\d*@email.com""#, + r#"pg: Good signature from "test name\d* \(no comment\) "#, + ], + Verify { i: sign_file }, + ); + gnupg_test( + &[ + "admin", + "factory-reset", + "y", + "yes", + "verify", + DEFAULT_PW1, + "quit", + ], + &[ + vec![r"\[GNUPG:\] CARDCTRL \d D276000124010304[A-Z0-9]*"], + virt::gpg_status(virt::KeyType::Cv25519, 5), + vec![ + r"\[GNUPG:\] GET_LINE cardedit.prompt", + r"\[GNUPG:\] GET_LINE cardedit.prompt", + r"\[GNUPG:\] GET_BOOL cardedit.factory-reset.proceed", + r"\[GNUPG:\] GET_LINE cardedit.factory-reset.really", + r"\[GNUPG:\] GET_LINE cardedit.prompt", ], - &[ - vec![r"\[GNUPG:\] CARDCTRL \d D2760001240103040000000000000000"], - virt::gpg_status(virt::KeyType::Cv25519, 5), - vec![ - r"\[GNUPG:\] GET_LINE cardedit.prompt", - r"\[GNUPG:\] GET_LINE cardedit.prompt", - r"\[GNUPG:\] GET_BOOL cardedit.factory-reset.proceed", - r"\[GNUPG:\] GET_LINE cardedit.factory-reset.really", - r"\[GNUPG:\] GET_LINE cardedit.prompt", - ], - virt::gpg_inquire_pin(), - virt::gpg_status(virt::KeyType::RsaNone, 0), - vec![r"\[GNUPG:\] GET_LINE cardedit.prompt"], - ] - .into_iter() - .flatten() - .collect::>(), - &[ - r"gpg: OpenPGP card no. [0-9A-F]{32} detected", - r"gpg: Note: This command destroys all keys stored on the card!", - ], - EditCard, - ); - }); + virt::gpg_inquire_pin(), + virt::gpg_status(virt::KeyType::RsaNone, 0), + vec![r"\[GNUPG:\] GET_LINE cardedit.prompt"], + ] + .into_iter() + .flatten() + .collect::>(), + &[ + r"gpg: OpenPGP card no. [0-9A-F]{32} detected", + r"gpg: Note: This command destroys all keys stored on the card!", + ], + EditCard, + ); } fn gpg_p256() { - with_vsc(|| { - let file_number: u32 = rand::rngs::OsRng.gen(); - let tmp = format!("/tmp/opcard-tests-{file_number}.gpg"); - let encrypted_file = &tmp; - let tmp = format!("/tmp/opcard-tests-{file_number}-sig.gpg"); - let sign_file = &tmp; - let tmp = format!("/tmp/opcard-tests-{file_number}.toml"); - let decrypted_file = &tmp; - let _dropper = FileDropper { - temp_file_name: encrypted_file, - }; - let _dropper = FileDropper { - temp_file_name: sign_file, - }; - let _dropper = FileDropper { - temp_file_name: decrypted_file, - }; - - let tmp = format!("test name{file_number}"); - let temp_name = &tmp; - - let tmp = format!("test{file_number}@email.com"); - let temp_email = &tmp; - - let custom_match = format!( - r"uid:u::::\d{{10}}::[0-9A-F]{{40}}::{temp_name} \(no comment\) <{temp_email}>::::::::::0:" - ); + let file_number: u32 = rand::rngs::OsRng.gen(); + let tmp = format!("/tmp/opcard-tests-{file_number}.gpg"); + let encrypted_file = &tmp; + let tmp = format!("/tmp/opcard-tests-{file_number}-sig.gpg"); + let sign_file = &tmp; + let tmp = format!("/tmp/opcard-tests-{file_number}.toml"); + let decrypted_file = &tmp; + let _dropper = FileDropper { + temp_file_name: encrypted_file, + }; + let _dropper = FileDropper { + temp_file_name: sign_file, + }; + let _dropper = FileDropper { + temp_file_name: decrypted_file, + }; + + let tmp = format!("test name{file_number}"); + let temp_name = &tmp; - gnupg_test( + let tmp = format!("test{file_number}@email.com"); + let temp_email = &tmp; + + let custom_match = format!( + r"uid:u::::\d{{10}}::[0-9A-F]{{40}}::{temp_name} \(no comment\) <{temp_email}>::::::::::0:" + ); + + gnupg_test( + &[], + &[ + vec![r"\[GNUPG:\] CARDCTRL \d D276000124010304[A-Z0-9]*"], + virt::gpg_status(virt::KeyType::RsaNone, 0), + ] + .into_iter() + .flatten() + .collect::>(), + &[], + CardStatus, + ); + + gnupg_test( &[ "admin", "key-attr", @@ -342,7 +369,7 @@ fn gpg_p256() { "quit", ], &[ - vec![r"\[GNUPG:\] CARDCTRL \d D2760001240103040000000000000000"], + vec![r"\[GNUPG:\] CARDCTRL \d D276000124010304[A-Z0-9]*"], virt::gpg_status(virt::KeyType::RsaNone,0), vec![ r"\[GNUPG:\] GET_LINE cardedit.prompt", @@ -365,14 +392,14 @@ fn gpg_p256() { ], virt::gpg_inquire_pin(), vec![ - r"pub:u:\d*:19:[0-9A-F]{16}:[0-9A-F]{10}:::u:::scESCA:::D2760001240103040000000000000000::nistp256:::0:", + r"pub:u:\d*:19:[0-9A-F]{16}:[0-9A-F]{10}:::u:::scESCA:::D276000124010304[A-Z0-9]*::nistp256:::0:", r"fpr:::::::::[0-9A-F]{40}:", r"grp:::::::::[0-9A-F]{40}:", &custom_match, - r"sub:u:\d*:19:[0-9A-F]{16}:[0-9A-F]{10}::::::a:::D2760001240103040000000000000000::nistp256::", + r"sub:u:\d*:19:[0-9A-F]{16}:[0-9A-F]{10}::::::a:::D276000124010304[A-Z0-9]*::nistp256::", r"fpr:::::::::[0-9A-F]{40}:", r"grp:::::::::[0-9A-F]{40}:", - r"sub:u:\d*:18:[0-9A-F]{16}:[0-9A-F]{10}::::::e:::D2760001240103040000000000000000::nistp256::", + r"sub:u:\d*:18:[0-9A-F]{16}:[0-9A-F]{10}::::::e:::D276000124010304[A-Z0-9]*::nistp256::", r"fpr:::::::::[0-9A-F]{40}:", r"grp:::::::::[0-9A-F]{40}:", r"\[GNUPG:\] KEY_CREATED B [0-9A-F]{40}", @@ -388,174 +415,185 @@ fn gpg_p256() { EditCard, ); - println!("================ FINISHED GENERATING P256 KEYS ================"); + println!("================ FINISHED GENERATING P256 KEYS ================"); - gnupg_test( - &[], - &[ - r"\[GNUPG:\] BEGIN_ENCRYPTION \d \d", - r"\[GNUPG:\] END_ENCRYPTION", - ], - &[], - Encrypt { - i: "Cargo.toml", - o: encrypted_file, - r: temp_email, - }, - ); + gnupg_test( + &[], + &[ + r"\[GNUPG:\] BEGIN_ENCRYPTION \d \d", + r"\[GNUPG:\] END_ENCRYPTION", + ], + &[], + Encrypt { + i: "Cargo.toml", + o: encrypted_file, + r: temp_email, + }, + ); - println!("================ FINISHED ENCRYPTION ================"); + println!("================ FINISHED ENCRYPTION ================"); - let custom1 = format!( - r"\[GNUPG:\] USERID_HINT [a-fA-F0-9]{{16}} {temp_name} \(no comment\) <{temp_email}>" - ); - let custom2 = format!(r"{temp_name} \(no comment\) <{temp_email}>"); + let custom1 = format!( + r"\[GNUPG:\] USERID_HINT [a-fA-F0-9]{{16}} {temp_name} \(no comment\) <{temp_email}>" + ); + let custom2 = format!(r"{temp_name} \(no comment\) <{temp_email}>"); - gnupg_test( - &[DEFAULT_PW1], - &[ - vec![ - r"\[GNUPG:\] ENC_TO [a-fA-F0-9]{16} \d* \d*", - &custom1, - r"\[GNUPG:\] NEED_PASSPHRASE [a-fA-F0-9]{16} [a-fA-F0-9]{16} 18 0", - ], - virt::gpg_inquire_pin(), - vec![ - r"\[GNUPG:\] DECRYPTION_KEY [a-fA-F0-9]{40} [a-fA-F0-9]{40} u", - r"\[GNUPG:\] BEGIN_DECRYPTION", - r"\[GNUPG:\] DECRYPTION_INFO \d \d \d", - r"\[GNUPG:\] PLAINTEXT \d* \d* Cargo.toml", - r"\[GNUPG:\] PLAINTEXT_LENGTH \d*", - r"\[GNUPG:\] DECRYPTION_OKAY", - r"\[GNUPG:\] GOODMDC", - r"\[GNUPG:\] END_DECRYPTION", - ], - ] - .into_iter() - .flatten() - .collect::>(), - &[ - r"gpg: encrypted with \d*-bit ECDH key, ID [a-fA-F0-9]{16}, created \d{4}-\d\d-\d\d", - &custom2, + gnupg_test( + &[DEFAULT_PW1], + &[ + vec![ + r"\[GNUPG:\] ENC_TO [a-fA-F0-9]{16} \d* \d*", + &custom1, + r"\[GNUPG:\] NEED_PASSPHRASE [a-fA-F0-9]{16} [a-fA-F0-9]{16} 18 0", ], - Decrypt { - i: encrypted_file, - o: decrypted_file, - }, - ); + virt::gpg_inquire_pin(), + vec![ + r"\[GNUPG:\] DECRYPTION_KEY [a-fA-F0-9]{40} [a-fA-F0-9]{40} u", + r"\[GNUPG:\] BEGIN_DECRYPTION", + r"\[GNUPG:\] DECRYPTION_INFO \d \d \d", + r"\[GNUPG:\] PLAINTEXT \d* \d* Cargo.toml", + r"\[GNUPG:\] PLAINTEXT_LENGTH \d*", + r"\[GNUPG:\] DECRYPTION_OKAY", + r"\[GNUPG:\] GOODMDC", + r"\[GNUPG:\] END_DECRYPTION", + ], + ] + .into_iter() + .flatten() + .collect::>(), + &[ + r"gpg: encrypted with \d*-bit ECDH key, ID [a-fA-F0-9]{16}, created \d{4}-\d\d-\d\d", + &custom2, + ], + Decrypt { + i: encrypted_file, + o: decrypted_file, + }, + ); - println!("================ FINISHED DECRYPTION ================"); + println!("================ FINISHED DECRYPTION ================"); - gnupg_test( - &[DEFAULT_PW1], - &[ - vec![ - r"\[GNUPG:\] CARDCTRL 3 D2760001240103040000000000000000", - r"\[GNUPG:\] BEGIN_SIGNING H\d*", - &custom1, - r"\[GNUPG:\] NEED_PASSPHRASE [a-fA-F0-9]{16} [a-fA-F0-9]{16} 19 0", - ], - virt::gpg_inquire_pin(), - vec![r"\[GNUPG:\] SIG_CREATED S 19 8 00 [a-fA-F0-9]{10} [a-fA-F0-9]{40}"], - ] - .into_iter() - .flatten() - .collect::>(), - &[r#"gpg: using "test\d*@email.com" as default secret key for signing"#], - Sign { - i: "Cargo.toml", - o: sign_file, - s: temp_email, - }, - ); + gnupg_test( + &[DEFAULT_PW1], + &[ + vec![ + r"\[GNUPG:\] CARDCTRL 3 D276000124010304[A-Z0-9]*", + r"\[GNUPG:\] BEGIN_SIGNING H\d*", + &custom1, + r"\[GNUPG:\] NEED_PASSPHRASE [a-fA-F0-9]{16} [a-fA-F0-9]{16} 19 0", + ], + virt::gpg_inquire_pin(), + vec![r"\[GNUPG:\] SIG_CREATED S 19 8 00 [a-fA-F0-9]{10} [a-fA-F0-9]{40}"], + ] + .into_iter() + .flatten() + .collect::>(), + &[r#"gpg: using "test\d*@email.com" as default secret key for signing"#], + Sign { + i: "Cargo.toml", + o: sign_file, + s: temp_email, + }, + ); - println!("================ FINISHED SIGNATURE ================"); + println!("================ FINISHED SIGNATURE ================"); - gnupg_test( - &[], - &[ - r"\[GNUPG:\] NEWSIG test\d*@email.com", - r"\[GNUPG:\] SIG_ID [^ ]* \d{4}-\d\d-\d\d [a-fA-F0-9]{10}", - r"\[GNUPG:\] GOODSIG [a-fA-F0-9]{16} test name\d* \(no comment\) ", - r"\[GNUPG:\] VALIDSIG [a-fA-F0-9]{40} \d{4}-\d\d-\d\d [a-fA-F0-9]{10} \d \d \d 19 8 00 [a-fA-F0-9]{40}", - r"\[GNUPG:\] TRUST_ULTIMATE 0 pgp", - ], - &[ - r"gpg: Signature made .*", - r"gpg: using ECDSA key [a-fA-F0-9]{40}", - r#"gpg: issuer "test\d*@email.com""#, - r#"pg: Good signature from "test name\d* \(no comment\) "#, - ], - Verify { i: sign_file }, - ); + gnupg_test( + &[], + &[ + r"\[GNUPG:\] NEWSIG test\d*@email.com", + r"\[GNUPG:\] SIG_ID [^ ]* \d{4}-\d\d-\d\d [a-fA-F0-9]{10}", + r"\[GNUPG:\] GOODSIG [a-fA-F0-9]{16} test name\d* \(no comment\) ", + r"\[GNUPG:\] VALIDSIG [a-fA-F0-9]{40} \d{4}-\d\d-\d\d [a-fA-F0-9]{10} \d \d \d 19 8 00 [a-fA-F0-9]{40}", + r"\[GNUPG:\] TRUST_ULTIMATE 0 pgp", + ], + &[ + r"gpg: Signature made .*", + r"gpg: using ECDSA key [a-fA-F0-9]{40}", + r#"gpg: issuer "test\d*@email.com""#, + r#"pg: Good signature from "test name\d* \(no comment\) "#, + ], + Verify { i: sign_file }, + ); - gnupg_test( - &[ - "admin", - "factory-reset", - "y", - "yes", - "verify", - DEFAULT_PW1, - "quit", + gnupg_test( + &[ + "admin", + "factory-reset", + "y", + "yes", + "verify", + DEFAULT_PW1, + "quit", + ], + &[ + vec![r"\[GNUPG:\] CARDCTRL \d D276000124010304[A-Z0-9]*"], + virt::gpg_status(virt::KeyType::P256, 5), + vec![ + r"\[GNUPG:\] GET_LINE cardedit.prompt", + r"\[GNUPG:\] GET_LINE cardedit.prompt", + r"\[GNUPG:\] GET_BOOL cardedit.factory-reset.proceed", + r"\[GNUPG:\] GET_LINE cardedit.factory-reset.really", + r"\[GNUPG:\] GET_LINE cardedit.prompt", ], - &[ - vec![r"\[GNUPG:\] CARDCTRL \d D2760001240103040000000000000000"], - virt::gpg_status(virt::KeyType::P256, 5), - vec![ - r"\[GNUPG:\] GET_LINE cardedit.prompt", - r"\[GNUPG:\] GET_LINE cardedit.prompt", - r"\[GNUPG:\] GET_BOOL cardedit.factory-reset.proceed", - r"\[GNUPG:\] GET_LINE cardedit.factory-reset.really", - r"\[GNUPG:\] GET_LINE cardedit.prompt", - ], - virt::gpg_inquire_pin(), - virt::gpg_status(virt::KeyType::RsaNone, 0), - vec![r"\[GNUPG:\] GET_LINE cardedit.prompt"], - ] - .into_iter() - .flatten() - .collect::>(), - &[ - r"gpg: OpenPGP card no. [0-9A-F]{32} detected", - r"gpg: Note: This command destroys all keys stored on the card!", - ], - EditCard, - ); - }); + virt::gpg_inquire_pin(), + virt::gpg_status(virt::KeyType::RsaNone, 0), + vec![r"\[GNUPG:\] GET_LINE cardedit.prompt"], + ] + .into_iter() + .flatten() + .collect::>(), + &[ + r"gpg: OpenPGP card no. [0-9A-F]{32} detected", + r"gpg: Note: This command destroys all keys stored on the card!", + ], + EditCard, + ); } #[cfg(feature = "rsa2048")] fn gpg_rsa_2048() { - with_vsc(|| { - let file_number: u32 = rand::rngs::OsRng.gen(); - let tmp = format!("/tmp/opcard-tests-{file_number}.gpg"); - let encrypted_file = &tmp; - let tmp = format!("/tmp/opcard-tests-{file_number}-sig.gpg"); - let sign_file = &tmp; - let tmp = format!("/tmp/opcard-tests-{file_number}.toml"); - let decrypted_file = &tmp; - let _dropper = FileDropper { - temp_file_name: encrypted_file, - }; - let _dropper = FileDropper { - temp_file_name: sign_file, - }; - let _dropper = FileDropper { - temp_file_name: decrypted_file, - }; - - let tmp = format!("test name{file_number}"); - let temp_name = &tmp; - - let tmp = format!("test{file_number}@email.com"); - let temp_email = &tmp; - - let custom_match = format!( - r"uid:u::::\d{{10}}::[0-9A-F]{{40}}::{temp_name} \(no comment\) <{temp_email}>::::::::::0:" - ); + let file_number: u32 = rand::rngs::OsRng.gen(); + let tmp = format!("/tmp/opcard-tests-{file_number}.gpg"); + let encrypted_file = &tmp; + let tmp = format!("/tmp/opcard-tests-{file_number}-sig.gpg"); + let sign_file = &tmp; + let tmp = format!("/tmp/opcard-tests-{file_number}.toml"); + let decrypted_file = &tmp; + let _dropper = FileDropper { + temp_file_name: encrypted_file, + }; + let _dropper = FileDropper { + temp_file_name: sign_file, + }; + let _dropper = FileDropper { + temp_file_name: decrypted_file, + }; + + let tmp = format!("test name{file_number}"); + let temp_name = &tmp; - gnupg_test( + let tmp = format!("test{file_number}@email.com"); + let temp_email = &tmp; + + let custom_match = format!( + r"uid:u::::\d{{10}}::[0-9A-F]{{40}}::{temp_name} \(no comment\) <{temp_email}>::::::::::0:" + ); + + gnupg_test( + &[], + &[ + vec![r"\[GNUPG:\] CARDCTRL \d D276000124010304[A-Z0-9]*"], + virt::gpg_status(virt::KeyType::RsaNone, 0), + ] + .into_iter() + .flatten() + .collect::>(), + &[], + CardStatus, + ); + + gnupg_test( &[ "admin", "generate", @@ -570,7 +608,7 @@ fn gpg_rsa_2048() { "quit", ], &[ - vec![r"\[GNUPG:\] CARDCTRL \d D2760001240103040000000000000000"], + vec![r"\[GNUPG:\] CARDCTRL \d D276000124010304[A-Z0-9]*"], virt::gpg_status(virt::KeyType::RsaNone,0), vec![ r"\[GNUPG:\] GET_LINE cardedit.prompt", @@ -589,14 +627,14 @@ fn gpg_rsa_2048() { ], virt::gpg_inquire_pin(), vec![ - r"pub:u:\d*:1:[0-9A-F]{16}:[0-9A-F]{10}:::u:::scESCA:::D2760001240103040000000000000000:::23::0:", + r"pub:u:\d*:1:[0-9A-F]{16}:[0-9A-F]{10}:::u:::scESCA:::D276000124010304[A-Z0-9]*:::23::0:", r"fpr:::::::::[0-9A-F]{40}:", r"grp:::::::::[0-9A-F]{40}:", &custom_match, - r"sub:u:\d*:1:[0-9A-F]{16}:[0-9A-F]{10}::::::a:::D2760001240103040000000000000000:::23:", + r"sub:u:\d*:1:[0-9A-F]{16}:[0-9A-F]{10}::::::a:::D276000124010304[A-Z0-9]*:::23:", r"fpr:::::::::[0-9A-F]{40}:", r"grp:::::::::[0-9A-F]{40}:", - r"sub:u:\d*:1:[0-9A-F]{16}:[0-9A-F]{10}::::::e:::D2760001240103040000000000000000:::23:", + r"sub:u:\d*:1:[0-9A-F]{16}:[0-9A-F]{10}::::::e:::D276000124010304[A-Z0-9]*:::23:", r"fpr:::::::::[0-9A-F]{40}:", r"grp:::::::::[0-9A-F]{40}:", r"\[GNUPG:\] KEY_CREATED B [0-9A-F]{40}", @@ -612,172 +650,183 @@ fn gpg_rsa_2048() { EditCard, ); - println!("================ FINISHED GENERATING 25519 KEYS ================"); + println!("================ FINISHED GENERATING 25519 KEYS ================"); - gnupg_test( - &[], - &[ - r"\[GNUPG:\] BEGIN_ENCRYPTION \d \d", - r"\[GNUPG:\] END_ENCRYPTION", - ], - &[], - Encrypt { - i: "Cargo.toml", - o: encrypted_file, - r: temp_email, - }, - ); + gnupg_test( + &[], + &[ + r"\[GNUPG:\] BEGIN_ENCRYPTION \d \d", + r"\[GNUPG:\] END_ENCRYPTION", + ], + &[], + Encrypt { + i: "Cargo.toml", + o: encrypted_file, + r: temp_email, + }, + ); - println!("================ FINISHED ENCRYPTION ================"); + println!("================ FINISHED ENCRYPTION ================"); - let custom1 = format!( - r"\[GNUPG:\] USERID_HINT [a-fA-F0-9]{{16}} {temp_name} \(no comment\) <{temp_email}>" - ); - let custom2 = format!(r"{temp_name} \(no comment\) <{temp_email}>"); - gnupg_test( - &[DEFAULT_PW1], - &[ - vec![ - r"\[GNUPG:\] ENC_TO [a-fA-F0-9]{16} \d* \d*", - &custom1, - r"\[GNUPG:\] NEED_PASSPHRASE [a-fA-F0-9]{16} [a-fA-F0-9]{16} 1 0", - ], - virt::gpg_inquire_pin(), - vec![ - r"\[GNUPG:\] DECRYPTION_KEY [a-fA-F0-9]{40} [a-fA-F0-9]{40} u", - r"\[GNUPG:\] BEGIN_DECRYPTION", - r"\[GNUPG:\] DECRYPTION_INFO \d \d \d", - r"\[GNUPG:\] PLAINTEXT \d* \d* Cargo.toml", - r"\[GNUPG:\] PLAINTEXT_LENGTH \d*", - r"\[GNUPG:\] DECRYPTION_OKAY", - r"\[GNUPG:\] GOODMDC", - r"\[GNUPG:\] END_DECRYPTION", - ], - ] - .into_iter() - .flatten() - .collect::>(), - &[ - r"gpg: encrypted with \d*-bit RSA key, ID [a-fA-F0-9]{16}, created \d{4}-\d\d-\d\d", - &custom2, + let custom1 = format!( + r"\[GNUPG:\] USERID_HINT [a-fA-F0-9]{{16}} {temp_name} \(no comment\) <{temp_email}>" + ); + let custom2 = format!(r"{temp_name} \(no comment\) <{temp_email}>"); + gnupg_test( + &[DEFAULT_PW1], + &[ + vec![ + r"\[GNUPG:\] ENC_TO [a-fA-F0-9]{16} \d* \d*", + &custom1, + r"\[GNUPG:\] NEED_PASSPHRASE [a-fA-F0-9]{16} [a-fA-F0-9]{16} 1 0", ], - Decrypt { - i: encrypted_file, - o: decrypted_file, - }, - ); + virt::gpg_inquire_pin(), + vec![ + r"\[GNUPG:\] DECRYPTION_KEY [a-fA-F0-9]{40} [a-fA-F0-9]{40} u", + r"\[GNUPG:\] BEGIN_DECRYPTION", + r"\[GNUPG:\] DECRYPTION_INFO \d \d \d", + r"\[GNUPG:\] PLAINTEXT \d* \d* Cargo.toml", + r"\[GNUPG:\] PLAINTEXT_LENGTH \d*", + r"\[GNUPG:\] DECRYPTION_OKAY", + r"\[GNUPG:\] GOODMDC", + r"\[GNUPG:\] END_DECRYPTION", + ], + ] + .into_iter() + .flatten() + .collect::>(), + &[ + r"gpg: encrypted with \d*-bit RSA key, ID [a-fA-F0-9]{16}, created \d{4}-\d\d-\d\d", + &custom2, + ], + Decrypt { + i: encrypted_file, + o: decrypted_file, + }, + ); - println!("================ FINISHED DECRYPTION ================"); + println!("================ FINISHED DECRYPTION ================"); - gnupg_test( - &[DEFAULT_PW1], - &[ - vec![ - r"\[GNUPG:\] CARDCTRL 3 D2760001240103040000000000000000", - r"\[GNUPG:\] BEGIN_SIGNING H\d*", - &custom1, - r"\[GNUPG:\] NEED_PASSPHRASE [a-fA-F0-9]{16} [a-fA-F0-9]{16} 1 0", - ], - virt::gpg_inquire_pin(), - vec![r"\[GNUPG:\] SIG_CREATED S 1 \d* 00 [a-fA-F0-9]{10} [a-fA-F0-9]{40}"], - ] - .into_iter() - .flatten() - .collect::>(), - &[r#"gpg: using "test\d*@email.com" as default secret key for signing"#], - Sign { - i: "Cargo.toml", - o: sign_file, - s: temp_email, - }, - ); + gnupg_test( + &[DEFAULT_PW1], + &[ + vec![ + r"\[GNUPG:\] CARDCTRL 3 D276000124010304[A-Z0-9]*", + r"\[GNUPG:\] BEGIN_SIGNING H\d*", + &custom1, + r"\[GNUPG:\] NEED_PASSPHRASE [a-fA-F0-9]{16} [a-fA-F0-9]{16} 1 0", + ], + virt::gpg_inquire_pin(), + vec![r"\[GNUPG:\] SIG_CREATED S 1 \d* 00 [a-fA-F0-9]{10} [a-fA-F0-9]{40}"], + ] + .into_iter() + .flatten() + .collect::>(), + &[r#"gpg: using "test\d*@email.com" as default secret key for signing"#], + Sign { + i: "Cargo.toml", + o: sign_file, + s: temp_email, + }, + ); - println!("================ FINISHED SIGNATURE ================"); + println!("================ FINISHED SIGNATURE ================"); - gnupg_test( - &[], - &[ - r"\[GNUPG:\] NEWSIG test\d*@email.com", - r"\[GNUPG:\] SIG_ID [^ ]* \d{4}-\d\d-\d\d [a-fA-F0-9]{10}", - r"\[GNUPG:\] GOODSIG [a-fA-F0-9]{16} test name\d* \(no comment\) ", - r"\[GNUPG:\] VALIDSIG [a-fA-F0-9]{40} \d{4}-\d\d-\d\d [a-fA-F0-9]{10} \d \d \d 1 \d* 00 [a-fA-F0-9]{40}", - r"\[GNUPG:\] TRUST_ULTIMATE 0 pgp", - ], - &[ - r"gpg: Signature made .*", - r"gpg: using RSA key [a-fA-F0-9]{40}", - r#"gpg: issuer "test\d*@email.com""#, - r#"pg: Good signature from "test name\d* \(no comment\) "#, + gnupg_test( + &[], + &[ + r"\[GNUPG:\] NEWSIG test\d*@email.com", + r"\[GNUPG:\] SIG_ID [^ ]* \d{4}-\d\d-\d\d [a-fA-F0-9]{10}", + r"\[GNUPG:\] GOODSIG [a-fA-F0-9]{16} test name\d* \(no comment\) ", + r"\[GNUPG:\] VALIDSIG [a-fA-F0-9]{40} \d{4}-\d\d-\d\d [a-fA-F0-9]{10} \d \d \d 1 \d* 00 [a-fA-F0-9]{40}", + r"\[GNUPG:\] TRUST_ULTIMATE 0 pgp", + ], + &[ + r"gpg: Signature made .*", + r"gpg: using RSA key [a-fA-F0-9]{40}", + r#"gpg: issuer "test\d*@email.com""#, + r#"pg: Good signature from "test name\d* \(no comment\) "#, + ], + Verify { i: sign_file }, + ); + gnupg_test( + &[ + "admin", + "factory-reset", + "y", + "yes", + "verify", + DEFAULT_PW1, + "quit", + ], + &[ + vec![r"\[GNUPG:\] CARDCTRL \d D276000124010304[A-Z0-9]*"], + virt::gpg_status(virt::KeyType::Rsa, 5), + vec![ + r"\[GNUPG:\] GET_LINE cardedit.prompt", + r"\[GNUPG:\] GET_LINE cardedit.prompt", + r"\[GNUPG:\] GET_BOOL cardedit.factory-reset.proceed", + r"\[GNUPG:\] GET_LINE cardedit.factory-reset.really", + r"\[GNUPG:\] GET_LINE cardedit.prompt", ], - Verify { i: sign_file }, - ); - gnupg_test( - &[ - "admin", - "factory-reset", - "y", - "yes", - "verify", - DEFAULT_PW1, - "quit", - ], - &[ - vec![r"\[GNUPG:\] CARDCTRL \d D2760001240103040000000000000000"], - virt::gpg_status(virt::KeyType::Rsa, 5), - vec![ - r"\[GNUPG:\] GET_LINE cardedit.prompt", - r"\[GNUPG:\] GET_LINE cardedit.prompt", - r"\[GNUPG:\] GET_BOOL cardedit.factory-reset.proceed", - r"\[GNUPG:\] GET_LINE cardedit.factory-reset.really", - r"\[GNUPG:\] GET_LINE cardedit.prompt", - ], - virt::gpg_inquire_pin(), - virt::gpg_status(virt::KeyType::RsaNone, 0), - vec![r"\[GNUPG:\] GET_LINE cardedit.prompt"], - ] - .into_iter() - .flatten() - .collect::>(), - &[ - r"gpg: OpenPGP card no. [0-9A-F]{32} detected", - r"gpg: Note: This command destroys all keys stored on the card!", - ], - EditCard, - ); - }); + virt::gpg_inquire_pin(), + virt::gpg_status(virt::KeyType::RsaNone, 0), + vec![r"\[GNUPG:\] GET_LINE cardedit.prompt"], + ] + .into_iter() + .flatten() + .collect::>(), + &[ + r"gpg: OpenPGP card no. [0-9A-F]{32} detected", + r"gpg: Note: This command destroys all keys stored on the card!", + ], + EditCard, + ); } #[cfg(feature = "rsa4096-gen")] fn gpg_rsa_4096() { - with_vsc(|| { - let file_number: u32 = rand::rngs::OsRng.gen(); - let tmp = format!("/tmp/opcard-tests-{file_number}.gpg"); - let encrypted_file = &tmp; - let tmp = format!("/tmp/opcard-tests-{file_number}-sig.gpg"); - let sign_file = &tmp; - let tmp = format!("/tmp/opcard-tests-{file_number}.toml"); - let decrypted_file = &tmp; - let _dropper = FileDropper { - temp_file_name: encrypted_file, - }; - let _dropper = FileDropper { - temp_file_name: sign_file, - }; - let _dropper = FileDropper { - temp_file_name: decrypted_file, - }; - - let tmp = format!("test name{file_number}"); - let temp_name = &tmp; - - let tmp = format!("test{file_number}@email.com"); - let temp_email = &tmp; - - let custom_match = format!( - r"uid:u::::\d{{10}}::[0-9A-F]{{40}}::{temp_name} \(no comment\) <{temp_email}>::::::::::0:" - ); + let file_number: u32 = rand::rngs::OsRng.gen(); + let tmp = format!("/tmp/opcard-tests-{file_number}.gpg"); + let encrypted_file = &tmp; + let tmp = format!("/tmp/opcard-tests-{file_number}-sig.gpg"); + let sign_file = &tmp; + let tmp = format!("/tmp/opcard-tests-{file_number}.toml"); + let decrypted_file = &tmp; + let _dropper = FileDropper { + temp_file_name: encrypted_file, + }; + let _dropper = FileDropper { + temp_file_name: sign_file, + }; + let _dropper = FileDropper { + temp_file_name: decrypted_file, + }; + + let tmp = format!("test name{file_number}"); + let temp_name = &tmp; - gnupg_test( + let tmp = format!("test{file_number}@email.com"); + let temp_email = &tmp; + + let custom_match = format!( + r"uid:u::::\d{{10}}::[0-9A-F]{{40}}::{temp_name} \(no comment\) <{temp_email}>::::::::::0:" + ); + + gnupg_test( + &[], + &[ + vec![r"\[GNUPG:\] CARDCTRL \d D276000124010304[A-Z0-9]*"], + virt::gpg_status(virt::KeyType::RsaNone, 0), + ] + .into_iter() + .flatten() + .collect::>(), + &[], + CardStatus, + ); + + gnupg_test( &[ "admin", "key-attr", @@ -802,7 +851,7 @@ fn gpg_rsa_4096() { "quit", ], &[ - vec![r"\[GNUPG:\] CARDCTRL \d D2760001240103040000000000000000"], + vec![r"\[GNUPG:\] CARDCTRL \d D276000124010304[A-Z0-9]*"], virt::gpg_status(virt::KeyType::RsaNone,0), vec![ r"\[GNUPG:\] GET_LINE cardedit.prompt", @@ -825,14 +874,14 @@ fn gpg_rsa_4096() { ], virt::gpg_inquire_pin(), vec![ - r"pub:u:\d*:1:[0-9A-F]{16}:[0-9A-F]{10}:::u:::scESCA:::D2760001240103040000000000000000:::23::0:", + r"pub:u:\d*:1:[0-9A-F]{16}:[0-9A-F]{10}:::u:::scESCA:::D276000124010304[A-Z0-9]*:::23::0:", r"fpr:::::::::[0-9A-F]{40}:", r"grp:::::::::[0-9A-F]{40}:", &custom_match, - r"sub:u:\d*:1:[0-9A-F]{16}:[0-9A-F]{10}::::::a:::D2760001240103040000000000000000:::23:", + r"sub:u:\d*:1:[0-9A-F]{16}:[0-9A-F]{10}::::::a:::D276000124010304[A-Z0-9]*:::23:", r"fpr:::::::::[0-9A-F]{40}:", r"grp:::::::::[0-9A-F]{40}:", - r"sub:u:\d*:1:[0-9A-F]{16}:[0-9A-F]{10}::::::e:::D2760001240103040000000000000000:::23:", + r"sub:u:\d*:1:[0-9A-F]{16}:[0-9A-F]{10}::::::e:::D276000124010304[A-Z0-9]*:::23:", r"fpr:::::::::[0-9A-F]{40}:", r"grp:::::::::[0-9A-F]{40}:", r"\[GNUPG:\] KEY_CREATED B [0-9A-F]{40}", @@ -848,147 +897,158 @@ fn gpg_rsa_4096() { EditCard, ); - println!("================ FINISHED GENERATING 25519 KEYS ================"); + println!("================ FINISHED GENERATING 25519 KEYS ================"); - gnupg_test( - &[], - &[ - r"\[GNUPG:\] BEGIN_ENCRYPTION \d \d", - r"\[GNUPG:\] END_ENCRYPTION", - ], - &[], - Encrypt { - i: "Cargo.toml", - o: encrypted_file, - r: temp_email, - }, - ); + gnupg_test( + &[], + &[ + r"\[GNUPG:\] BEGIN_ENCRYPTION \d \d", + r"\[GNUPG:\] END_ENCRYPTION", + ], + &[], + Encrypt { + i: "Cargo.toml", + o: encrypted_file, + r: temp_email, + }, + ); - println!("================ FINISHED ENCRYPTION ================"); + println!("================ FINISHED ENCRYPTION ================"); - let custom1 = format!( - r"\[GNUPG:\] USERID_HINT [a-fA-F0-9]{{16}} {temp_name} \(no comment\) <{temp_email}>" - ); - let custom2 = format!(r"{temp_name} \(no comment\) <{temp_email}>"); - gnupg_test( - &[DEFAULT_PW1], - &[ - vec![ - r"\[GNUPG:\] ENC_TO [a-fA-F0-9]{16} \d* \d*", - &custom1, - r"\[GNUPG:\] NEED_PASSPHRASE [a-fA-F0-9]{16} [a-fA-F0-9]{16} 1 0", - ], - virt::gpg_inquire_pin(), - vec![ - r"\[GNUPG:\] DECRYPTION_KEY [a-fA-F0-9]{40} [a-fA-F0-9]{40} u", - r"\[GNUPG:\] BEGIN_DECRYPTION", - r"\[GNUPG:\] DECRYPTION_INFO \d \d \d", - r"\[GNUPG:\] PLAINTEXT \d* \d* Cargo.toml", - r"\[GNUPG:\] PLAINTEXT_LENGTH \d*", - r"\[GNUPG:\] DECRYPTION_OKAY", - r"\[GNUPG:\] GOODMDC", - r"\[GNUPG:\] END_DECRYPTION", - ], - ] - .into_iter() - .flatten() - .collect::>(), - &[ - r"gpg: encrypted with \d*-bit RSA key, ID [a-fA-F0-9]{16}, created \d{4}-\d\d-\d\d", - &custom2, + let custom1 = format!( + r"\[GNUPG:\] USERID_HINT [a-fA-F0-9]{{16}} {temp_name} \(no comment\) <{temp_email}>" + ); + let custom2 = format!(r"{temp_name} \(no comment\) <{temp_email}>"); + gnupg_test( + &[DEFAULT_PW1], + &[ + vec![ + r"\[GNUPG:\] ENC_TO [a-fA-F0-9]{16} \d* \d*", + &custom1, + r"\[GNUPG:\] NEED_PASSPHRASE [a-fA-F0-9]{16} [a-fA-F0-9]{16} 1 0", ], - Decrypt { - i: encrypted_file, - o: decrypted_file, - }, - ); + virt::gpg_inquire_pin(), + vec![ + r"\[GNUPG:\] DECRYPTION_KEY [a-fA-F0-9]{40} [a-fA-F0-9]{40} u", + r"\[GNUPG:\] BEGIN_DECRYPTION", + r"\[GNUPG:\] DECRYPTION_INFO \d \d \d", + r"\[GNUPG:\] PLAINTEXT \d* \d* Cargo.toml", + r"\[GNUPG:\] PLAINTEXT_LENGTH \d*", + r"\[GNUPG:\] DECRYPTION_OKAY", + r"\[GNUPG:\] GOODMDC", + r"\[GNUPG:\] END_DECRYPTION", + ], + ] + .into_iter() + .flatten() + .collect::>(), + &[ + r"gpg: encrypted with \d*-bit RSA key, ID [a-fA-F0-9]{16}, created \d{4}-\d\d-\d\d", + &custom2, + ], + Decrypt { + i: encrypted_file, + o: decrypted_file, + }, + ); - println!("================ FINISHED DECRYPTION ================"); + println!("================ FINISHED DECRYPTION ================"); - gnupg_test( - &[DEFAULT_PW1], - &[ - vec![ - r"\[GNUPG:\] CARDCTRL 3 D2760001240103040000000000000000", - r"\[GNUPG:\] BEGIN_SIGNING H\d*", - &custom1, - r"\[GNUPG:\] NEED_PASSPHRASE [a-fA-F0-9]{16} [a-fA-F0-9]{16} 1 0", - ], - virt::gpg_inquire_pin(), - vec![r"\[GNUPG:\] SIG_CREATED S 1 \d* 00 [a-fA-F0-9]{10} [a-fA-F0-9]{40}"], - ] - .into_iter() - .flatten() - .collect::>(), - &[r#"gpg: using "test\d*@email.com" as default secret key for signing"#], - Sign { - i: "Cargo.toml", - o: sign_file, - s: temp_email, - }, - ); + gnupg_test( + &[DEFAULT_PW1], + &[ + vec![ + r"\[GNUPG:\] CARDCTRL 3 D276000124010304[A-Z0-9]*", + r"\[GNUPG:\] BEGIN_SIGNING H\d*", + &custom1, + r"\[GNUPG:\] NEED_PASSPHRASE [a-fA-F0-9]{16} [a-fA-F0-9]{16} 1 0", + ], + virt::gpg_inquire_pin(), + vec![r"\[GNUPG:\] SIG_CREATED S 1 \d* 00 [a-fA-F0-9]{10} [a-fA-F0-9]{40}"], + ] + .into_iter() + .flatten() + .collect::>(), + &[r#"gpg: using "test\d*@email.com" as default secret key for signing"#], + Sign { + i: "Cargo.toml", + o: sign_file, + s: temp_email, + }, + ); - println!("================ FINISHED SIGNATURE ================"); + println!("================ FINISHED SIGNATURE ================"); - gnupg_test( - &[], - &[ - r"\[GNUPG:\] NEWSIG test\d*@email.com", - r"\[GNUPG:\] SIG_ID [^ ]* \d{4}-\d\d-\d\d [a-fA-F0-9]{10}", - r"\[GNUPG:\] GOODSIG [a-fA-F0-9]{16} test name\d* \(no comment\) ", - r"\[GNUPG:\] VALIDSIG [a-fA-F0-9]{40} \d{4}-\d\d-\d\d [a-fA-F0-9]{10} \d \d \d 1 \d* 00 [a-fA-F0-9]{40}", - r"\[GNUPG:\] TRUST_ULTIMATE 0 pgp", - ], - &[ - r"gpg: Signature made .*", - r"gpg: using RSA key [a-fA-F0-9]{40}", - r#"gpg: issuer "test\d*@email.com""#, - r#"pg: Good signature from "test name\d* \(no comment\) "#, - ], - Verify { i: sign_file }, - ); - gnupg_test( - &[ - "admin", - "factory-reset", - "y", - "yes", - "verify", - DEFAULT_PW1, - "quit", - ], - &[ - vec![r"\[GNUPG:\] CARDCTRL \d D2760001240103040000000000000000"], - virt::gpg_status(virt::KeyType::Rsa4096, 5), - vec![ - r"\[GNUPG:\] GET_LINE cardedit.prompt", - r"\[GNUPG:\] GET_LINE cardedit.prompt", - r"\[GNUPG:\] GET_BOOL cardedit.factory-reset.proceed", - r"\[GNUPG:\] GET_LINE cardedit.factory-reset.really", - r"\[GNUPG:\] GET_LINE cardedit.prompt", - ], - virt::gpg_inquire_pin(), - virt::gpg_status(virt::KeyType::RsaNone, 0), - vec![r"\[GNUPG:\] GET_LINE cardedit.prompt"], - ] - .into_iter() - .flatten() - .collect::>(), - &[ - r"gpg: OpenPGP card no. [0-9A-F]{32} detected", - r"gpg: Note: This command destroys all keys stored on the card!", + gnupg_test( + &[], + &[ + r"\[GNUPG:\] NEWSIG test\d*@email.com", + r"\[GNUPG:\] SIG_ID [^ ]* \d{4}-\d\d-\d\d [a-fA-F0-9]{10}", + r"\[GNUPG:\] GOODSIG [a-fA-F0-9]{16} test name\d* \(no comment\) ", + r"\[GNUPG:\] VALIDSIG [a-fA-F0-9]{40} \d{4}-\d\d-\d\d [a-fA-F0-9]{10} \d \d \d 1 \d* 00 [a-fA-F0-9]{40}", + r"\[GNUPG:\] TRUST_ULTIMATE 0 pgp", + ], + &[ + r"gpg: Signature made .*", + r"gpg: using RSA key [a-fA-F0-9]{40}", + r#"gpg: issuer "test\d*@email.com""#, + r#"pg: Good signature from "test name\d* \(no comment\) "#, + ], + Verify { i: sign_file }, + ); + gnupg_test( + &[ + "admin", + "factory-reset", + "y", + "yes", + "verify", + DEFAULT_PW1, + "quit", + ], + &[ + vec![r"\[GNUPG:\] CARDCTRL \d D276000124010304[A-Z0-9]*"], + virt::gpg_status(virt::KeyType::Rsa4096, 5), + vec![ + r"\[GNUPG:\] GET_LINE cardedit.prompt", + r"\[GNUPG:\] GET_LINE cardedit.prompt", + r"\[GNUPG:\] GET_BOOL cardedit.factory-reset.proceed", + r"\[GNUPG:\] GET_LINE cardedit.factory-reset.really", + r"\[GNUPG:\] GET_LINE cardedit.prompt", ], - EditCard, - ); - }); + virt::gpg_inquire_pin(), + virt::gpg_status(virt::KeyType::RsaNone, 0), + vec![r"\[GNUPG:\] GET_LINE cardedit.prompt"], + ] + .into_iter() + .flatten() + .collect::>(), + &[ + r"gpg: OpenPGP card no. [0-9A-F]{32} detected", + r"gpg: Note: This command destroys all keys stored on the card!", + ], + EditCard, + ); } +#[cfg(all(feature = "virtual", not(feature = "dangerous-test-real-card")))] #[test] fn gpg_crypto() { + with_vsc(gpg_255); + with_vsc(gpg_p256); #[cfg(feature = "rsa2048")] - gpg_rsa_2048(); + with_vsc(gpg_rsa_2048); #[cfg(feature = "rsa4096-gen")] - gpg_rsa_4096(); + with_vsc(gpg_rsa_4096); +} + +#[cfg(feature = "dangerous-test-real-card")] +#[test] +fn gpg_crypto() { gpg_255(); gpg_p256(); + #[cfg(feature = "rsa2048")] + gpg_rsa_2048(); + #[cfg(feature = "rsa4096-gen")] + gpg_rsa_4096(); } diff --git a/tests/crypto-sequoia.rs b/tests/crypto-sequoia.rs index 7d85e488..4ea088da 100644 --- a/tests/crypto-sequoia.rs +++ b/tests/crypto-sequoia.rs @@ -1,6 +1,6 @@ // Copyright (C) 2022 Nitrokey GmbH // SPDX-License-Identifier: LGPL-3.0-only -#![cfg(feature = "virtual")] +#![cfg(any(feature = "virtual", feature = "dangerous-test-real-card"))] mod card; mod virt; @@ -16,265 +16,294 @@ use sequoia_openpgp::types::HashAlgorithm; use test_log::test; -#[test] -fn sequoia_gen_key() { - #[cfg(feature = "rsa2048")] - virt::with_vsc(|| { - let mut cards = PcscBackend::cards(None).unwrap(); - let mut pgp = OpenPgp::new(cards.pop().unwrap()); - let mut open = Open::new(pgp.transaction().unwrap()).unwrap(); - open.verify_admin(b"12345678").unwrap(); - let mut admin = open.admin_card().unwrap(); - - let (material, gendate) = admin - .generate_key_simple(KeyType::Decryption, Some(AlgoSimple::RSA2k)) +#[cfg(all(feature = "virtual", not(feature = "dangerous-test-real-card")))] +const IDENT: &str = "0000:00000000"; +#[cfg(feature = "dangerous-test-real-card")] +const IDENT: &str = concat!( + env!("OPCARD_DANGEROUS_TEST_CARD_VENDOR"), + ":", + env!("OPCARD_DANGEROUS_TEST_CARD_SERIAL") +); + +#[cfg(feature = "rsa2048")] +fn rsa2048() { + let card = PcscBackend::open_by_ident(IDENT, None).unwrap(); + let mut pgp = OpenPgp::new(card); + let mut open = Open::new(pgp.transaction().unwrap()).unwrap(); + open.verify_admin(b"12345678").unwrap(); + let mut admin = open.admin_card().unwrap(); + + let (material, gendate) = admin + .generate_key_simple(KeyType::Decryption, Some(AlgoSimple::RSA2k)) + .unwrap(); + let dec_pubk = + public_key_material_to_key(&material, KeyType::Decryption, &gendate, None, None).unwrap(); + + let (material, gendate) = admin + .generate_key_simple(KeyType::Authentication, Some(AlgoSimple::RSA2k)) + .unwrap(); + let aut_pubk = + public_key_material_to_key(&material, KeyType::Authentication, &gendate, None, None) .unwrap(); - let dec_pubk = - public_key_material_to_key(&material, KeyType::Decryption, &gendate, None, None) - .unwrap(); - let (material, gendate) = admin - .generate_key_simple(KeyType::Authentication, Some(AlgoSimple::RSA2k)) - .unwrap(); - let aut_pubk = - public_key_material_to_key(&material, KeyType::Authentication, &gendate, None, None) - .unwrap(); + let (material, gendate) = admin + .generate_key_simple(KeyType::Signing, Some(AlgoSimple::RSA2k)) + .unwrap(); + let pubk = + public_key_material_to_key(&material, KeyType::Signing, &gendate, None, None).unwrap(); + + open.verify_user_for_signing(b"123456").unwrap(); + let mut sign_card = open.signing_card().unwrap(); + let mut signer = sign_card.signer_from_public(pubk.clone(), &|| {}); + let data = [1; 32]; + let signature = signer.sign(HashAlgorithm::SHA256, &data).unwrap(); + assert!(pubk + .verify(&signature, HashAlgorithm::SHA256, &data) + .is_ok()); + + open.verify_user(b"123456").unwrap(); + let mut user_card = open.user_card().unwrap(); + let mut authenticator = user_card.authenticator_from_public(aut_pubk.clone(), &|| {}); + let data = [2; 32]; + let signature = authenticator.sign(HashAlgorithm::SHA256, &data).unwrap(); + assert!(aut_pubk + .verify(&signature, HashAlgorithm::SHA256, &data) + .is_ok()); + + let mut session = SessionKey::new(19); + session[0] = 7; + let ciphertext = dec_pubk.encrypt(&session).unwrap(); + let mut decryptor = user_card.decryptor_from_public(dec_pubk, &|| {}); + assert_eq!(session, decryptor.decrypt(&ciphertext, None).unwrap()); +} - let (material, gendate) = admin - .generate_key_simple(KeyType::Signing, Some(AlgoSimple::RSA2k)) +#[cfg(feature = "rsa4096-gen")] +fn rsa4096() { + let card = PcscBackend::open_by_ident(IDENT, None).unwrap(); + let mut pgp = OpenPgp::new(card); + let mut open = Open::new(pgp.transaction().unwrap()).unwrap(); + open.verify_admin(b"12345678").unwrap(); + let mut admin = open.admin_card().unwrap(); + + let (material, gendate) = admin + .generate_key_simple(KeyType::Decryption, Some(AlgoSimple::RSA4k)) + .unwrap(); + let dec_pubk = + public_key_material_to_key(&material, KeyType::Decryption, &gendate, None, None).unwrap(); + + let (material, gendate) = admin + .generate_key_simple(KeyType::Authentication, Some(AlgoSimple::RSA4k)) + .unwrap(); + let aut_pubk = + public_key_material_to_key(&material, KeyType::Authentication, &gendate, None, None) .unwrap(); - let pubk = - public_key_material_to_key(&material, KeyType::Signing, &gendate, None, None).unwrap(); - - open.verify_user_for_signing(b"123456").unwrap(); - let mut sign_card = open.signing_card().unwrap(); - let mut signer = sign_card.signer_from_public(pubk.clone(), &|| {}); - let data = [1; 32]; - let signature = signer.sign(HashAlgorithm::SHA256, &data).unwrap(); - assert!(pubk - .verify(&signature, HashAlgorithm::SHA256, &data) - .is_ok()); - - open.verify_user(b"123456").unwrap(); - let mut user_card = open.user_card().unwrap(); - let mut authenticator = user_card.authenticator_from_public(aut_pubk.clone(), &|| {}); - let data = [2; 32]; - let signature = authenticator.sign(HashAlgorithm::SHA256, &data).unwrap(); - assert!(aut_pubk - .verify(&signature, HashAlgorithm::SHA256, &data) - .is_ok()); - - let mut session = SessionKey::new(19); - session[0] = 7; - let ciphertext = dec_pubk.encrypt(&session).unwrap(); - let mut decryptor = user_card.decryptor_from_public(dec_pubk, &|| {}); - assert_eq!(session, decryptor.decrypt(&ciphertext, None).unwrap()); - }); - #[cfg(feature = "rsa4096-gen")] - virt::with_vsc(|| { - let mut cards = PcscBackend::cards(None).unwrap(); - let mut pgp = OpenPgp::new(cards.pop().unwrap()); - let mut open = Open::new(pgp.transaction().unwrap()).unwrap(); - open.verify_admin(b"12345678").unwrap(); - let mut admin = open.admin_card().unwrap(); - - let (material, gendate) = admin - .generate_key_simple(KeyType::Decryption, Some(AlgoSimple::RSA4k)) - .unwrap(); - let dec_pubk = - public_key_material_to_key(&material, KeyType::Decryption, &gendate, None, None) - .unwrap(); + let (material, gendate) = admin + .generate_key_simple(KeyType::Signing, Some(AlgoSimple::RSA4k)) + .unwrap(); + let pubk = + public_key_material_to_key(&material, KeyType::Signing, &gendate, None, None).unwrap(); + + open.verify_user_for_signing(b"123456").unwrap(); + let mut sign_card = open.signing_card().unwrap(); + let mut signer = sign_card.signer_from_public(pubk.clone(), &|| {}); + let data = [1; 64]; + let signature = signer.sign(HashAlgorithm::SHA512, &data).unwrap(); + assert!(pubk + .verify(&signature, HashAlgorithm::SHA512, &data) + .is_ok()); + open.verify_user(b"123456").unwrap(); + let mut user_card = open.user_card().unwrap(); + let mut authenticator = user_card.authenticator_from_public(aut_pubk.clone(), &|| {}); + let data = [2; 64]; + let signature = authenticator.sign(HashAlgorithm::SHA512, &data).unwrap(); + assert!(aut_pubk + .verify(&signature, HashAlgorithm::SHA512, &data) + .is_ok()); + + let mut session = SessionKey::new(19); + session[0] = 7; + let ciphertext = dec_pubk.encrypt(&session).unwrap(); + let mut decryptor = user_card.decryptor_from_public(dec_pubk, &|| {}); + assert_eq!(session, decryptor.decrypt(&ciphertext, None).unwrap()); +} - let (material, gendate) = admin - .generate_key_simple(KeyType::Authentication, Some(AlgoSimple::RSA4k)) +fn p256() { + let card = PcscBackend::open_by_ident(IDENT, None).unwrap(); + let mut pgp = OpenPgp::new(card); + let mut open = Open::new(pgp.transaction().unwrap()).unwrap(); + open.verify_admin(b"12345678").unwrap(); + let mut admin = open.admin_card().unwrap(); + let (material, gendate) = admin + .generate_key_simple(KeyType::Decryption, Some(AlgoSimple::NIST256)) + .unwrap(); + let dec_pubk = + public_key_material_to_key(&material, KeyType::Decryption, &gendate, None, None).unwrap(); + let dec_pubk_aut = + public_key_material_to_key(&material, KeyType::Authentication, &gendate, None, None) .unwrap(); - let aut_pubk = - public_key_material_to_key(&material, KeyType::Authentication, &gendate, None, None) - .unwrap(); - let (material, gendate) = admin - .generate_key_simple(KeyType::Signing, Some(AlgoSimple::RSA4k)) - .unwrap(); - let pubk = - public_key_material_to_key(&material, KeyType::Signing, &gendate, None, None).unwrap(); - - open.verify_user_for_signing(b"123456").unwrap(); - let mut sign_card = open.signing_card().unwrap(); - let mut signer = sign_card.signer_from_public(pubk.clone(), &|| {}); - let data = [1; 64]; - let signature = signer.sign(HashAlgorithm::SHA512, &data).unwrap(); - assert!(pubk - .verify(&signature, HashAlgorithm::SHA512, &data) - .is_ok()); - open.verify_user(b"123456").unwrap(); - let mut user_card = open.user_card().unwrap(); - let mut authenticator = user_card.authenticator_from_public(aut_pubk.clone(), &|| {}); - let data = [2; 64]; - let signature = authenticator.sign(HashAlgorithm::SHA512, &data).unwrap(); - assert!(aut_pubk - .verify(&signature, HashAlgorithm::SHA512, &data) - .is_ok()); - - let mut session = SessionKey::new(19); - session[0] = 7; - let ciphertext = dec_pubk.encrypt(&session).unwrap(); - let mut decryptor = user_card.decryptor_from_public(dec_pubk, &|| {}); - assert_eq!(session, decryptor.decrypt(&ciphertext, None).unwrap()); - }); - - virt::with_vsc(|| { - let mut cards = PcscBackend::cards(None).unwrap(); - let mut pgp = OpenPgp::new(cards.pop().unwrap()); - let mut open = Open::new(pgp.transaction().unwrap()).unwrap(); - open.verify_admin(b"12345678").unwrap(); - let mut admin = open.admin_card().unwrap(); - let (material, gendate) = admin - .generate_key_simple(KeyType::Decryption, Some(AlgoSimple::NIST256)) - .unwrap(); - let dec_pubk = - public_key_material_to_key(&material, KeyType::Decryption, &gendate, None, None) - .unwrap(); - let dec_pubk_aut = - public_key_material_to_key(&material, KeyType::Authentication, &gendate, None, None) - .unwrap(); - - let (material, gendate) = admin - .generate_key_simple(KeyType::Authentication, Some(AlgoSimple::NIST256)) - .unwrap(); - let aut_pubk = - public_key_material_to_key(&material, KeyType::Authentication, &gendate, None, None) - .unwrap(); - let aut_pubk_dec = - public_key_material_to_key(&material, KeyType::Decryption, &gendate, None, None) - .unwrap(); - - let (material, gendate) = admin - .generate_key_simple(KeyType::Signing, Some(AlgoSimple::NIST256)) - .unwrap(); - let sign_pubk = - public_key_material_to_key(&material, KeyType::Signing, &gendate, None, None).unwrap(); - - open.verify_user_for_signing(b"123456").unwrap(); - let mut sign_card = open.signing_card().unwrap(); - let mut signer = sign_card.signer_from_public(sign_pubk.clone(), &|| {}); - let data = [1; 32]; - let signature = signer.sign(HashAlgorithm::SHA256, &data).unwrap(); - assert!(sign_pubk - .verify(&signature, HashAlgorithm::SHA256, &data) - .is_ok()); - - open.verify_user(b"123456").unwrap(); - let mut user_card = open.user_card().unwrap(); - let mut authenticator = user_card.authenticator_from_public(aut_pubk.clone(), &|| {}); - let data = [2; 32]; - let signature = authenticator.sign(HashAlgorithm::SHA256, &data).unwrap(); - assert!(dec_pubk_aut - .verify(&signature, HashAlgorithm::SHA256, &data) - .is_err()); - assert!(aut_pubk - .verify(&signature, HashAlgorithm::SHA256, &data) - .is_ok()); - - let mut session = SessionKey::new(19); - session[0] = 7; - let ciphertext = dec_pubk.encrypt(&session).unwrap(); - let mut decryptor = user_card.decryptor_from_public(dec_pubk, &|| {}); - assert_eq!(session, decryptor.decrypt(&ciphertext, Some(32)).unwrap()); - - open.manage_security_environment(KeyType::Authentication, KeyType::Decryption) - .unwrap(); - let mut user_card = open.user_card().unwrap(); - let mut authenticator = user_card.authenticator_from_public(aut_pubk.clone(), &|| {}); - let data = [3; 32]; - let signature = authenticator.sign(HashAlgorithm::SHA256, &data).unwrap(); - assert!(aut_pubk - .verify(&signature, HashAlgorithm::SHA256, &data) - .is_err()); - dec_pubk_aut - .verify(&signature, HashAlgorithm::SHA256, &data) + let (material, gendate) = admin + .generate_key_simple(KeyType::Authentication, Some(AlgoSimple::NIST256)) + .unwrap(); + let aut_pubk = + public_key_material_to_key(&material, KeyType::Authentication, &gendate, None, None) .unwrap(); + let aut_pubk_dec = + public_key_material_to_key(&material, KeyType::Decryption, &gendate, None, None).unwrap(); + + let (material, gendate) = admin + .generate_key_simple(KeyType::Signing, Some(AlgoSimple::NIST256)) + .unwrap(); + let sign_pubk = + public_key_material_to_key(&material, KeyType::Signing, &gendate, None, None).unwrap(); + + open.verify_user_for_signing(b"123456").unwrap(); + let mut sign_card = open.signing_card().unwrap(); + let mut signer = sign_card.signer_from_public(sign_pubk.clone(), &|| {}); + let data = [1; 32]; + let signature = signer.sign(HashAlgorithm::SHA256, &data).unwrap(); + assert!(sign_pubk + .verify(&signature, HashAlgorithm::SHA256, &data) + .is_ok()); + + open.verify_user(b"123456").unwrap(); + let mut user_card = open.user_card().unwrap(); + let mut authenticator = user_card.authenticator_from_public(aut_pubk.clone(), &|| {}); + let data = [2; 32]; + let signature = authenticator.sign(HashAlgorithm::SHA256, &data).unwrap(); + assert!(dec_pubk_aut + .verify(&signature, HashAlgorithm::SHA256, &data) + .is_err()); + assert!(aut_pubk + .verify(&signature, HashAlgorithm::SHA256, &data) + .is_ok()); + + let mut session = SessionKey::new(19); + session[0] = 7; + let ciphertext = dec_pubk.encrypt(&session).unwrap(); + let mut decryptor = user_card.decryptor_from_public(dec_pubk, &|| {}); + assert_eq!(session, decryptor.decrypt(&ciphertext, Some(32)).unwrap()); + + open.manage_security_environment(KeyType::Authentication, KeyType::Decryption) + .unwrap(); + let mut user_card = open.user_card().unwrap(); + let mut authenticator = user_card.authenticator_from_public(aut_pubk.clone(), &|| {}); + let data = [3; 32]; + let signature = authenticator.sign(HashAlgorithm::SHA256, &data).unwrap(); + assert!(aut_pubk + .verify(&signature, HashAlgorithm::SHA256, &data) + .is_err()); + dec_pubk_aut + .verify(&signature, HashAlgorithm::SHA256, &data) + .unwrap(); + + open.manage_security_environment(KeyType::Decryption, KeyType::Authentication) + .unwrap(); + let mut user_card = open.user_card().unwrap(); + let mut session = SessionKey::new(19); + session[0] = 7; + let ciphertext = aut_pubk_dec.encrypt(&session).unwrap(); + let mut decryptor = user_card.decryptor_from_public(aut_pubk_dec, &|| {}); + assert_eq!(session, decryptor.decrypt(&ciphertext, Some(32)).unwrap()); +} - open.manage_security_environment(KeyType::Decryption, KeyType::Authentication) +fn curve25519() { + let card = PcscBackend::open_by_ident(IDENT, None).unwrap(); + let mut pgp = OpenPgp::new(card); + let mut open = Open::new(pgp.transaction().unwrap()).unwrap(); + open.verify_admin(b"12345678").unwrap(); + let mut admin = open.admin_card().unwrap(); + + let (material, gendate) = admin + .generate_key_simple(KeyType::Decryption, Some(AlgoSimple::Curve25519)) + .unwrap(); + let dec_pubk = + public_key_material_to_key(&material, KeyType::Decryption, &gendate, None, None).unwrap(); + + let (material, gendate) = admin + .generate_key_simple(KeyType::Authentication, Some(AlgoSimple::Curve25519)) + .unwrap(); + let aut_pubk = + public_key_material_to_key(&material, KeyType::Authentication, &gendate, None, None) .unwrap(); - let mut user_card = open.user_card().unwrap(); - let mut session = SessionKey::new(19); - session[0] = 7; - let ciphertext = aut_pubk_dec.encrypt(&session).unwrap(); - let mut decryptor = user_card.decryptor_from_public(aut_pubk_dec, &|| {}); - assert_eq!(session, decryptor.decrypt(&ciphertext, Some(32)).unwrap()); - }); - - virt::with_vsc(|| { - let mut cards = PcscBackend::cards(None).unwrap(); - let mut pgp = OpenPgp::new(cards.pop().unwrap()); - let mut open = Open::new(pgp.transaction().unwrap()).unwrap(); - open.verify_admin(b"12345678").unwrap(); - let mut admin = open.admin_card().unwrap(); - - let (material, gendate) = admin - .generate_key_simple(KeyType::Decryption, Some(AlgoSimple::Curve25519)) - .unwrap(); - let dec_pubk = - public_key_material_to_key(&material, KeyType::Decryption, &gendate, None, None) - .unwrap(); - let (material, gendate) = admin - .generate_key_simple(KeyType::Authentication, Some(AlgoSimple::Curve25519)) - .unwrap(); - let aut_pubk = - public_key_material_to_key(&material, KeyType::Authentication, &gendate, None, None) - .unwrap(); + let (material, gendate) = admin + .generate_key_simple(KeyType::Signing, Some(AlgoSimple::Curve25519)) + .unwrap(); + let pubk = + public_key_material_to_key(&material, KeyType::Signing, &gendate, None, None).unwrap(); + + open.verify_user_for_signing(b"123456").unwrap(); + let mut sign_card = open.signing_card().unwrap(); + let mut signer = sign_card.signer_from_public(pubk.clone(), &|| {}); + let data = [1; 32]; + let signature = signer.sign(HashAlgorithm::SHA256, &data).unwrap(); + assert!(pubk + .verify(&signature, HashAlgorithm::SHA256, &data) + .is_ok()); + + open.verify_user(b"123456").unwrap(); + let mut user_card = open.user_card().unwrap(); + let mut authenticator = user_card.authenticator_from_public(aut_pubk.clone(), &|| {}); + let data = [2; 32]; + let signature = authenticator.sign(HashAlgorithm::SHA256, &data).unwrap(); + assert!(aut_pubk + .verify(&signature, HashAlgorithm::SHA256, &data) + .is_ok()); + + let mut session = SessionKey::new(19); + session[0] = 7; + let ciphertext = dec_pubk.encrypt(&session).unwrap(); + let mut decryptor = user_card.decryptor_from_public(dec_pubk.clone(), &|| {}); + assert_eq!(session, decryptor.decrypt(&ciphertext, None).unwrap()); + + open.manage_security_environment(KeyType::Authentication, KeyType::Decryption) + .unwrap(); + let mut user_card = open.user_card().unwrap(); + let mut authenticator = user_card.authenticator_from_public(aut_pubk, &|| {}); + let data = [3; 32]; + // Signature with X25519 key should fail + let _ = authenticator + .sign(HashAlgorithm::SHA256, &data) + .unwrap_err(); + + open.manage_security_environment(KeyType::Decryption, KeyType::Authentication) + .unwrap(); + let mut user_card = open.user_card().unwrap(); + let mut session = SessionKey::new(19); + session[0] = 7; + let ciphertext = dec_pubk.encrypt(&session).unwrap(); + let mut decryptor = user_card.decryptor_from_public(dec_pubk, &|| {}); + + // X25519 with and EdDSA key should fail + decryptor.decrypt(&ciphertext, None).unwrap_err(); +} - let (material, gendate) = admin - .generate_key_simple(KeyType::Signing, Some(AlgoSimple::Curve25519)) - .unwrap(); - let pubk = - public_key_material_to_key(&material, KeyType::Signing, &gendate, None, None).unwrap(); - - open.verify_user_for_signing(b"123456").unwrap(); - let mut sign_card = open.signing_card().unwrap(); - let mut signer = sign_card.signer_from_public(pubk.clone(), &|| {}); - let data = [1; 32]; - let signature = signer.sign(HashAlgorithm::SHA256, &data).unwrap(); - assert!(pubk - .verify(&signature, HashAlgorithm::SHA256, &data) - .is_ok()); - - open.verify_user(b"123456").unwrap(); - let mut user_card = open.user_card().unwrap(); - let mut authenticator = user_card.authenticator_from_public(aut_pubk.clone(), &|| {}); - let data = [2; 32]; - let signature = authenticator.sign(HashAlgorithm::SHA256, &data).unwrap(); - assert!(aut_pubk - .verify(&signature, HashAlgorithm::SHA256, &data) - .is_ok()); - - let mut session = SessionKey::new(19); - session[0] = 7; - let ciphertext = dec_pubk.encrypt(&session).unwrap(); - let mut decryptor = user_card.decryptor_from_public(dec_pubk.clone(), &|| {}); - assert_eq!(session, decryptor.decrypt(&ciphertext, None).unwrap()); - - open.manage_security_environment(KeyType::Authentication, KeyType::Decryption) - .unwrap(); - let mut user_card = open.user_card().unwrap(); - let mut authenticator = user_card.authenticator_from_public(aut_pubk, &|| {}); - let data = [3; 32]; - // Signature with X25519 key should fail - let _ = authenticator - .sign(HashAlgorithm::SHA256, &data) - .unwrap_err(); - - open.manage_security_environment(KeyType::Decryption, KeyType::Authentication) - .unwrap(); - let mut user_card = open.user_card().unwrap(); - let mut session = SessionKey::new(19); - session[0] = 7; - let ciphertext = dec_pubk.encrypt(&session).unwrap(); - let mut decryptor = user_card.decryptor_from_public(dec_pubk, &|| {}); - - // X25519 with and EdDSA key should fail - decryptor.decrypt(&ciphertext, None).unwrap_err(); - }); +#[cfg(all(feature = "virtual", not(feature = "dangerous-test-real-card")))] +#[test] +fn sequoia_gen_key() { + #[cfg(feature = "rsa2048")] + virt::with_vsc(rsa2048); + + #[cfg(feature = "rsa4096-gen")] + virt::with_vsc(rsa4096); + + virt::with_vsc(p256); + + virt::with_vsc(curve25519); +} + +#[cfg(feature = "dangerous-test-real-card")] +#[test] +fn sequoia_gen_key() { + #[cfg(feature = "rsa2048")] + rsa2048(); + + #[cfg(feature = "rsa4096-gen")] + rsa4096(); + + p256(); + + curve25519(); } diff --git a/tests/gpg-status.rs b/tests/gpg-status.rs index 2eafd145..1fa90210 100644 --- a/tests/gpg-status.rs +++ b/tests/gpg-status.rs @@ -15,7 +15,7 @@ fn gpg_card_status() { let status_regex = Regex::new( "\ Reader ...........: Virtual PCD \\d\\d \\d\\d\n\ - Application ID ...: D2760001240103040000000000000000\n\ + Application ID ...: D276000124010304[A-Z0-9]*\n\ Application type .: OpenPGP\n\ Version ..........: 3.4\n\ Manufacturer .....: test card\n\ diff --git a/tests/virt/mod.rs b/tests/virt/mod.rs index 4fe8a579..64e72290 100644 --- a/tests/virt/mod.rs +++ b/tests/virt/mod.rs @@ -1,18 +1,20 @@ // Copyright (C) 2022 Nitrokey GmbH // SPDX-License-Identifier: LGPL-3.0-only - -#![cfg(feature = "virtual")] +#![cfg(any(feature = "virtual", feature = "dangerous-test-real-card"))] use std::{ io::{BufRead, BufReader, Write}, mem::drop, process::{Command, Stdio}, - sync::mpsc, - thread::{self, sleep}, - time::Duration, + thread, }; +#[cfg(feature = "virtual")] +use std::{sync::mpsc, thread::sleep, time::Duration}; + use regex::{Regex, RegexSet}; + +#[cfg(feature = "virtual")] use stoppable_thread::spawn; const STDOUT_FILTER: &[&str] = &[ @@ -34,6 +36,8 @@ const STDERR_FILTER: &[&str] = &[ r"There is NO WARRANTY, to the extent permitted by law.", ]; +#[cfg(feature = "virtual")] +#[allow(unused)] pub fn with_vsc R, R>(f: F) -> R { let mut vpicc = vpicc::connect().expect("failed to connect to vpcd"); @@ -163,12 +167,36 @@ pub fn gpg_status(key: KeyType, sign_count: usize) -> Vec<&'static str> { }; let fprtimes = r"fprtime:\d*:\d*:\d*:"; + #[cfg(feature = "virtual")] + let (reader, serial, vendor) = ( + r"Reader:Virtual PCD \d\d \d\d:AID:D276000124010304[A-Z0-9]*:openpgp-card", + r"vendor:0000:test card:", + r"serial:00000000:", + ); + #[cfg(feature = "dangerous-test-real-card")] + let (reader, serial, vendor) = ( + concat!( + r"Reader:", + env!("OPCARD_DANGEROUS_TEST_CARD_VENDOR"), + ":", + env!("OPCARD_DANGEROUS_TEST_CARD_SERIAL"), + ":X:0:AID:D276000124010304[A-Z0-9]*:openpgp-card" + ), + concat!( + r"vendor:", + env!("OPCARD_DANGEROUS_TEST_CARD_VENDOR"), + ":", + env!("OPCARD_DANGEROUS_TEST_CARD_NAME"), + ":" + ), + concat!(r"serial:", env!("OPCARD_DANGEROUS_TEST_CARD_SERIAL"), ":"), + ); [ - r"Reader:Virtual PCD \d\d \d\d:AID:D2760001240103040000000000000000:openpgp-card", + reader, r"version:0304", - r"vendor:0000:test card", - r"serial:00000000", + r"vendor:[a-zA-Z0-9]{4}:.*:", + r"serial:[a-zA-Z0-9]*:", r"name:::", r"lang::", r"sex:u:", @@ -202,6 +230,7 @@ pub fn gpg_inquire_pin() -> Vec<&'static str> { #[allow(unused)] pub enum GpgCommand<'a> { EditCard, + CardStatus, Encrypt { r: &'a str, i: &'a str, o: &'a str }, Decrypt { i: &'a str, o: &'a str }, Sign { i: &'a str, s: &'a str, o: &'a str }, @@ -228,6 +257,7 @@ impl GpgCommand<'_> { .stdin(Stdio::piped()); match self { GpgCommand::EditCard => cmd.arg("--edit-card"), + GpgCommand::CardStatus => cmd.arg("--card-status"), GpgCommand::Encrypt { i, o, r } => { cmd.args(["--encrypt", "--output", o, "--recipient", r, i]) }