diff --git a/src/cmd_pgpcardadmin.rs b/src/cmd_pgpcardadmin.rs new file mode 100644 index 0000000..4456515 --- /dev/null +++ b/src/cmd_pgpcardadmin.rs @@ -0,0 +1,25 @@ +use clap::{App, Arg, ArgMatches, SubCommand}; +use rust_util::util_clap::{Command, CommandError}; + +pub struct CommandImpl; + +impl Command for CommandImpl { + fn name(&self) -> &str { "pgp-card-admin" } + + fn subcommand<'a>(&self) -> App<'a, 'a> { + SubCommand::with_name(self.name()).about("OpenPGP Card Admin subcommand") + .arg(Arg::with_name("pin").short("p").long("pin").takes_value(true).default_value("12345678").help("OpenPGP card admin pin")) + } + + fn run(&self, _arg_matches: &ArgMatches, sub_arg_matches: &ArgMatches) -> CommandError { + let pin = opt_value_result!(sub_arg_matches.value_of("pin"), "Pass must be assigned"); + if pin.len() < 8 { return simple_error!("Admin pin length:{}, must >= 8!", pin.len()); } + + let _card_admin = crate::pgpcardutil::get_card_admin(pin)?; + + information!("Admin pin verify success!"); + // card_admin.get_aid() + + Ok(None) + } +} diff --git a/src/cmd_pgpcarddecrypt.rs b/src/cmd_pgpcarddecrypt.rs index 435aeb0..a89b995 100644 --- a/src/cmd_pgpcarddecrypt.rs +++ b/src/cmd_pgpcarddecrypt.rs @@ -11,7 +11,7 @@ impl Command for CommandImpl { fn subcommand<'a>(&self) -> App<'a, 'a> { SubCommand::with_name(self.name()).about("OpenPGP Card Decrypt subcommand") - .arg(Arg::with_name("pass").short("p").long("pass").takes_value(true).default_value("123456").help("OpenPGP card password")) + .arg(Arg::with_name("pin").short("p").long("pin").takes_value(true).default_value("123456").help("OpenPGP card user pin")) .arg(Arg::with_name("cipher").short("c").long("cipher").takes_value(true).help("Cipher text HEX")) .arg(Arg::with_name("cipher-base64").short("b").long("cipher-base64").takes_value(true).help("Cipher text base64")) .arg(Arg::with_name("json").long("json").help("JSON output")) @@ -19,12 +19,11 @@ impl Command for CommandImpl { fn run(&self, _arg_matches: &ArgMatches, sub_arg_matches: &ArgMatches) -> CommandError { let json_output = sub_arg_matches.is_present("json"); - if json_output { - rust_util::util_msg::set_logger_std_out(false); - } - let pass_opt = sub_arg_matches.value_of("pass"); - let pass = opt_value_result!(pass_opt, "Pass must be assigned"); - if pass.len() < 6 { return simple_error!("Pass length:{}, must >= 6!", pass.len()); } + if json_output { rust_util::util_msg::set_logger_std_out(false); } + + let pin = opt_value_result!(sub_arg_matches.value_of("pin"), "User pin must be assigned"); + if pin.len() < 6 { return simple_error!("User pin length:{}, must >= 6!", pin.len()); } + let cipher = sub_arg_matches.value_of("cipher"); let cipher_base64 = sub_arg_matches.value_of("cipher-base64"); @@ -36,7 +35,7 @@ impl Command for CommandImpl { return simple_error!("cipher or cipher-base64 must assign one"); }; - let user = crate::pgpcardutil::get_card_user_sw1_82(pass)?; + let user = crate::pgpcardutil::get_card_user_sw1_82(pin)?; let text = user.decrypt(DecryptMe::RSA(&cipher_bytes))?; success!("Clear text HEX: {}", hex::encode(&text)); success!("Clear text base64: {}", base64::encode(&text)); diff --git a/src/cmd_pgpcardlist.rs b/src/cmd_pgpcardlist.rs index ea01abf..ecce4a1 100644 --- a/src/cmd_pgpcardlist.rs +++ b/src/cmd_pgpcardlist.rs @@ -71,12 +71,12 @@ impl Command for CommandImpl { println!("{}", serde_json::to_string_pretty(&json).unwrap()); } - if let Ok(pass) = std::env::var("PASS") { + if let Ok(pin) = std::env::var("PASS") { if let Ok(list) = OpenPGPCard::list_cards() { // pw1_81 for signature // openssl dgst -sha256 -verify aa -signature sig LICENSE for card in list { - match card.verify_pw1_81(&pass) { + match card.verify_pw1_81(&pin) { Result::Ok(user) => { let h = hex::decode("8f25018489d6fe0dec34a352314c38dc146247b7de65735790f4398a92afa84b").unwrap(); let mut hh = [0_u8; 0x20]; @@ -95,7 +95,7 @@ impl Command for CommandImpl { // pw1_82 for encryption // PKCSv1.5 for card in list { - match card.verify_pw1_82(&pass) { + match card.verify_pw1_82(&pin) { Result::Ok(user) => { let e = hex::decode("705d2af390174706c42de8361c4cb7a4684e06216305d6da70cab9248fa1abb9fac2b4c004187a53b9ed2b7f8ab75b20a54a12e6be672a742504b38d07b192f1f815285b6605b06a1a86d97f14ffcf41a9b3463ff3d8b2afe63e53aeb43048fef358639e5589fab8000d0805fe9145b5457cb5f7f91243b25181d1c7853b384a3bba45143a5ceeb2612463e51fbce52154e20726e6cf58f0317ebdf92613a10aec2b34224b0ffd1333c475cab473cf66aa895700e6681d20d12ddc897e0731226d4dc6bc9bd2e4aca02dba49175a35e45f9f3b56973a0381c777dac73a7eb8a04bfde45d3c19f44f740a193439da6829bf4beba90529c3017bddbd64aacbad92d3632260d5b6a7b5565fd852f17cff031fbdc2700d6acc2dedaaad307aaf7bb2de8f2b02faf84d94fa046e4ce487480918a54ca4672e1388deae8881436f454e65263a4984003495031126b4488ab27c6f4555f16bdd0fe2b9132443bbf49aa9c19864c4b1b917914e9c070a0327e52cf3b536e218a56ec97e12979e5981977e008eb9180d02da322c1a019fa535d77b67912039bc699b291d950714367d1c4a4a41edc86b1ab99d101da75a61c762fee28f8a004fb7656800623ac95d88c1978f18a1d286916cdab9c9f0f91d500cffdc8cb2853011a352bfa5f1fcd4a59720004153fb644afef083909c6a537ebc24255c1284ecf665a8cb7212672051e8b4").unwrap(); println!(":::: {}", e.len()); diff --git a/src/cmd_pgpcardsign.rs b/src/cmd_pgpcardsign.rs index c5f9654..645b3eb 100644 --- a/src/cmd_pgpcardsign.rs +++ b/src/cmd_pgpcardsign.rs @@ -12,7 +12,7 @@ impl Command for CommandImpl { fn subcommand<'a>(&self) -> App<'a, 'a> { SubCommand::with_name(self.name()).about("OpenPGP Card Sign subcommand") - .arg(Arg::with_name("pass").short("p").long("pass").takes_value(true).default_value("123456").help("OpenPGP card password")) + .arg(Arg::with_name("pin").short("p").long("pin").takes_value(true).default_value("123456").help("OpenPGP card user pin")) .arg(Arg::with_name("sha256").short("2").long("sha256").takes_value(true).help("Digest SHA256 HEX")) .arg(Arg::with_name("sha384").short("3").long("sha384").takes_value(true).help("Digest SHA384 HEX")) .arg(Arg::with_name("sha512").short("5").long("sha512").takes_value(true).help("Digest SHA512 HEX")) @@ -24,11 +24,10 @@ impl Command for CommandImpl { if json_output { rust_util::util_msg::set_logger_std_out(false); } - let pass = sub_arg_matches.value_of("pass"); - let pass = match pass { - Some(p) => p, - None => return simple_error!("Pass must be assigned"), - }; + let pin_opt = sub_arg_matches.value_of("pin"); + let pin = opt_value_result!(pin_opt, "User pin must be assigned"); + if pin.len() < 6 { return simple_error!("User pin length:{}, must >= 6!", pin.len()); } + let sha256 = sub_arg_matches.value_of("sha256"); let sha384 = sub_arg_matches.value_of("sha384"); let sha512 = sub_arg_matches.value_of("sha512"); @@ -39,7 +38,7 @@ impl Command for CommandImpl { let mut json = BTreeMap::new(); if let Some(sha256) = sha256 { - let user = crate::pgpcardutil::get_card_user_sw1_81(pass)?; + let user = crate::pgpcardutil::get_card_user_sw1_81(pin)?; let sha256_hex = opt_result!(hex::decode(sha256.trim()), "Decode sha256 failed: {}"); let sha256_hex = copy_sha256(&sha256_hex)?; let sig = user.signature_for_hash(Hash::SHA256(sha256_hex))?; @@ -53,7 +52,7 @@ impl Command for CommandImpl { } } if let Some(sha384) = sha384 { - let user = crate::pgpcardutil::get_card_user_sw1_81(pass)?; + let user = crate::pgpcardutil::get_card_user_sw1_81(pin)?; let sha384_hex = opt_result!(hex::decode(sha384.trim()), "Decode sha384 failed: {}"); let sha384_hex = copy_sha384(&sha384_hex)?; let sig = user.signature_for_hash(Hash::SHA384(sha384_hex))?; @@ -67,7 +66,7 @@ impl Command for CommandImpl { } } if let Some(sha512) = sha512 { - let user = crate::pgpcardutil::get_card_user_sw1_81(pass)?; + let user = crate::pgpcardutil::get_card_user_sw1_81(pin)?; let sha512_hex = opt_result!(hex::decode(sha512.trim()), "Decode sha512 failed: {}"); let sha512_hex = copy_sha512(&sha512_hex)?; let sig = user.signature_for_hash(Hash::SHA512(sha512_hex))?; diff --git a/src/cmd_pivsign.rs b/src/cmd_pivsign.rs index 2587b54..ddb2de7 100644 --- a/src/cmd_pivsign.rs +++ b/src/cmd_pivsign.rs @@ -12,7 +12,7 @@ impl Command for CommandImpl { fn subcommand<'a>(&self) -> App<'a, 'a> { SubCommand::with_name(self.name()).about("PIV Sign subcommand") - .arg(Arg::with_name("pass").short("p").long("pass").takes_value(true).default_value("123456").help("OpenPGP card password")) + .arg(Arg::with_name("pin").short("p").long("pin").takes_value(true).default_value("123456").help("OpenPGP card user pin")) .arg(Arg::with_name("json").long("json").help("JSON output")) } @@ -22,11 +22,10 @@ impl Command for CommandImpl { rust_util::util_msg::set_logger_std_out(false); } warning!("This feature is not complete"); - let pass_opt = sub_arg_matches.value_of("pass"); - let pass = opt_value_result!(pass_opt, "Pass must be assigned"); + let pin = opt_value_result!(sub_arg_matches.value_of("pin"), "User pin must be assigned"); let mut yk = opt_result!(YubiKey::open(), "YubiKey not found: {}"); - opt_result!(yk.verify_pin(pass.as_bytes()), "YubiKey verify pin failed: {}"); + opt_result!(yk.verify_pin(pin.as_bytes()), "YubiKey verify pin failed: {}"); let raw_in = [1_u8; 256]; let sign_result = yubikey::piv::sign_data(&mut yk, &raw_in, AlgorithmId::Rsa2048, SlotId::Signature); let sign = opt_result!(sign_result, "Sign data failed: {}"); diff --git a/src/main.rs b/src/main.rs index 1350d65..16018d9 100644 --- a/src/main.rs +++ b/src/main.rs @@ -10,6 +10,7 @@ mod cmd_u2fregister; mod cmd_u2fsign; mod cmd_pgp; mod pgpcardutil; +mod cmd_pgpcardadmin; mod cmd_pgpcardlist; mod cmd_pgpcardsign; mod cmd_pgpcarddecrypt; @@ -41,6 +42,7 @@ fn inner_main() -> CommandError { Box::new(cmd_chall::CommandImpl), Box::new(cmd_challconfig::CommandImpl), Box::new(cmd_pgp::CommandImpl), + Box::new(cmd_pgpcardadmin::CommandImpl), Box::new(cmd_pgpcardlist::CommandImpl), Box::new(cmd_pgpcardsign::CommandImpl), Box::new(cmd_pgpcarddecrypt::CommandImpl), diff --git a/src/pgpcardutil.rs b/src/pgpcardutil.rs index 2784ff3..99e2a1a 100644 --- a/src/pgpcardutil.rs +++ b/src/pgpcardutil.rs @@ -1,37 +1,43 @@ -use openpgp_card::{OpenPGPCard, OpenPGPCardUser}; +use openpgp_card::{OpenPGPCard, OpenPGPCardAdmin, OpenPGPCardUser}; use rust_util::XResult; -pub fn get_card_user_sw1_81(pass: &str) -> XResult { - match OpenPGPCard::list_cards() { - Ok(list) => { - // pw1_81 for signature - // openssl dgst -sha256 -verify aa -signature sig LICENSE - if list.is_empty() { - return simple_error!("Cannot find any card"); - } - match list.into_iter().next().unwrap().verify_pw1_81(pass) { - Result::Ok(user) => Ok(user), - Result::Err(_) => simple_error!("Verify pw1_81 OpenPGP card failed"), - } - } - Err(e) => simple_error!("Read OpenPGP card failed: {}", e), +pub fn get_card_user_sw1_81(pin: &str) -> XResult { + // pw1_81 for signature + // openssl dgst -sha256 -verify aa -signature sig LICENSE + get_card_user(|open_pgp_card: OpenPGPCard| open_pgp_card.verify_pw1_81(pin), "pw1_81") +} + +pub fn get_card_user_sw1_82(pin: &str) -> XResult { + // pw1_82 for decrypt + // PKCSv1.5 + get_card_user(|open_pgp_card: OpenPGPCard| open_pgp_card.verify_pw1_82(pin), "pw1_82") +} + +pub fn get_card_admin(pin: &str) -> XResult { + let card = get_card()?; + match card.verify_pw3(pin) { + Result::Ok(admin) => Ok(admin), + Result::Err(_) => simple_error!("Verify pw3 OpenPGP card failed"), } } -pub fn get_card_user_sw1_82(pass: &str) -> XResult { - match OpenPGPCard::list_cards() { - Ok(list) => { - // pw1_82 for decrypt - // PKCSv1.5 - if list.is_empty() { - return simple_error!("Cannot find any card"); - } - match list.into_iter().next().unwrap().verify_pw1_82(pass) { - Result::Ok(user) => Ok(user), - Result::Err(_) => simple_error!("Verify pw1_82 OpenPGP card failed"), - } - } - Err(e) => simple_error!("Read OpenPGP card failed: {}", e), +fn get_card_user(process_fn: impl Fn(OpenPGPCard) -> Result, tag: &str) -> XResult { + let card = get_card()?; + match process_fn(card) { + Result::Ok(user) => Ok(user), + Result::Err(_) => simple_error!("Verify {} OpenPGP card failed", tag), } } +fn get_card() -> XResult { + let card_list = opt_result!(OpenPGPCard::list_cards(), + "Read OpenPGP card list failed: {}"); + if card_list.is_empty() { + return simple_error!("Cannot find any card"); + } + if card_list.len() > 0 { + warning!("Find {} OpenPGP cards, will use first card", card_list.len()); + } + Ok(opt_value_result!(card_list.into_iter().next(), "Get first card failed")) +} +