diff --git a/Cargo.lock b/Cargo.lock index ed599b5..26a4d57 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -508,7 +508,7 @@ dependencies = [ [[package]] name = "card-cli" -version = "1.12.9" +version = "1.12.10" dependencies = [ "aes-gcm-stream", "authenticator 0.3.1", diff --git a/Cargo.toml b/Cargo.toml index 09a6cb6..dd57420 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "card-cli" -version = "1.12.9" +version = "1.12.10" authors = ["Hatter Jiang "] edition = "2018" diff --git a/src/cmd_external_public_key.rs b/src/cmd_external_public_key.rs index d8bfc03..93e0109 100644 --- a/src/cmd_external_public_key.rs +++ b/src/cmd_external_public_key.rs @@ -72,7 +72,7 @@ fn fetch_public_key(parameter: &str, serial_opt: &Option<&str>) -> XResult { if key.algorithm.is_ecc() { - let private_key = cmd_hmac_decrypt::try_hmac_decrypt(&key.hmac_enc_private_key)?; + let private_key = cmd_hmac_decrypt::try_decrypt(&key.hmac_enc_private_key)?; let p256_public_key = ecdsautil::parse_p256_private_key_to_public_key(&private_key).ok(); let p384_public_key = ecdsautil::parse_p384_private_key_to_public_key(&private_key).ok(); let p521_public_key = ecdsautil::parse_p521_private_key_to_public_key(&private_key).ok(); @@ -89,7 +89,7 @@ fn fetch_public_key(parameter: &str, serial_opt: &Option<&str>) -> XResult XResult> { } KeyUri::YubikeyHmacEncSoftKey(key) => { if key.algorithm.is_ecc() { - let private_key = cmd_hmac_decrypt::try_hmac_decrypt(&key.hmac_enc_private_key)?; + let private_key = cmd_hmac_decrypt::try_decrypt(&key.hmac_enc_private_key)?; let (jwt_algorithm, private_key_d) = parse_ecdsa_private_key(&private_key)?; let raw_in = digest_by_jwt_algorithm(jwt_algorithm, &message_bytes)?; @@ -110,7 +110,7 @@ fn sign(sub_arg_matches: &ArgMatches) -> XResult> { Ok(signed_data) } else if key.algorithm.is_rsa() { use rsa::pkcs8::DecodePrivateKey; - let private_key = cmd_hmac_decrypt::try_hmac_decrypt(&key.hmac_enc_private_key)?; + let private_key = cmd_hmac_decrypt::try_decrypt(&key.hmac_enc_private_key)?; let private_key_der = base64_decode(&private_key)?; let rsa_private_key = RsaPrivateKey::from_pkcs8_der(&private_key_der)?; diff --git a/src/cmd_hmac_decrypt.rs b/src/cmd_hmac_decrypt.rs index d2182d3..c778ef2 100644 --- a/src/cmd_hmac_decrypt.rs +++ b/src/cmd_hmac_decrypt.rs @@ -32,7 +32,11 @@ impl Command for CommandImpl { let ciphertext = sub_arg_matches.value_of("ciphertext").unwrap(); let auto_pbe = sub_arg_matches.is_present("auto-pbe"); - let text = hmac_decrypt(ciphertext, auto_pbe)?; + let text = if pbeutil::is_simple_pbe_encrypted(ciphertext) { + pbeutil::simple_pbe_decrypt_with_prompt_to_string(&ciphertext)? + } else { + hmac_decrypt(ciphertext, auto_pbe)? + }; if json_output { let mut json = BTreeMap::<&'_ str, String>::new(); @@ -47,9 +51,11 @@ impl Command for CommandImpl { } } -pub fn try_hmac_decrypt(ciphertext: &str) -> XResult { +pub fn try_decrypt(ciphertext: &str) -> XResult { if is_hmac_encrypted(ciphertext) { hmac_decrypt(ciphertext, true) + } else if pbeutil::is_simple_pbe_encrypted(ciphertext) { + pbeutil::simple_pbe_decrypt_with_prompt_to_string(&ciphertext) } else { Ok(ciphertext.to_string()) } @@ -58,7 +64,7 @@ pub fn try_hmac_decrypt(ciphertext: &str) -> XResult { pub fn hmac_decrypt(ciphertext: &str, auto_pbe: bool) -> XResult { let text = hmac_decrypt_to_string(ciphertext)?; if auto_pbe && pbeutil::is_simple_pbe_encrypted(&text) { - Ok(pbeutil::simple_pbe_decrypt_with_prompt_to_string(&text)?) + pbeutil::simple_pbe_decrypt_with_prompt_to_string(&text) } else { Ok(text) } diff --git a/src/cmd_hmac_encrypt.rs b/src/cmd_hmac_encrypt.rs index c4555b2..e520626 100644 --- a/src/cmd_hmac_encrypt.rs +++ b/src/cmd_hmac_encrypt.rs @@ -31,22 +31,24 @@ impl Command for CommandImpl { let json_output = cmdutil::check_json_output(sub_arg_matches); let text = sub_arg_matches.value_of("plaintext").unwrap().to_string(); - let hmac_encrypt_ciphertext = hmac_encrypt(&text, &mut None, sub_arg_matches)?; + let ciphertext = do_encrypt(&text, &mut None, sub_arg_matches)?; + let ciphertext = hmacutil::hmac_encrypt_from_string(&ciphertext)?; if json_output { let mut json = BTreeMap::<&'_ str, String>::new(); - json.insert("ciphertext", hmac_encrypt_ciphertext); + json.insert("ciphertext", ciphertext); util::print_pretty_json(&json); } else { - success!("HMAC encrypt ciphertext: {}", hmac_encrypt_ciphertext); + success!("HMAC encrypt ciphertext: {}", ciphertext); } Ok(None) } } -pub fn hmac_encrypt(text: &str, password_opt: &mut Option, sub_arg_matches: &ArgMatches) -> XResult { +pub fn do_encrypt(text: &str, password_opt: &mut Option, sub_arg_matches: &ArgMatches) -> XResult { + let with_hmac_encrypt = sub_arg_matches.is_present("with-hmac-encrypt"); let with_pbe_encrypt = sub_arg_matches.is_present("with-pbe-encrypt"); let text = if with_pbe_encrypt { let double_pin_check = sub_arg_matches.is_present("double-pin-check"); @@ -56,5 +58,9 @@ pub fn hmac_encrypt(text: &str, password_opt: &mut Option, sub_arg_match } else { text.to_string() }; - Ok(hmacutil::hmac_encrypt_from_string(&text)?) + if with_hmac_encrypt { + Ok(hmacutil::hmac_encrypt_from_string(&text)?) + } else { + Ok(text) + } } diff --git a/src/cmd_keypair_generate.rs b/src/cmd_keypair_generate.rs index 08b7b98..9a1ab91 100644 --- a/src/cmd_keypair_generate.rs +++ b/src/cmd_keypair_generate.rs @@ -2,7 +2,7 @@ use crate::ecdsautil::EcdsaAlgorithm; use crate::keychain::{KeychainKey, KeychainKeyValue}; use crate::keyutil::{KeyAlgorithmId, KeyUri, YubikeyHmacEncSoftKey}; use crate::util::base64_encode; -use crate::{cmd_hmac_encrypt, cmdutil, ecdsautil, rsautil, util, yubikeyutil}; +use crate::{cmd_hmac_encrypt, cmdutil, ecdsautil, hmacutil, pbeutil, rsautil, util, yubikeyutil}; use clap::{App, Arg, ArgMatches, SubCommand}; use rust_util::util_clap::{Command, CommandError}; use std::collections::BTreeMap; @@ -35,7 +35,6 @@ impl Command for CommandImpl { fn run(&self, _arg_matches: &ArgMatches, sub_arg_matches: &ArgMatches) -> CommandError { let json_output = cmdutil::check_json_output(sub_arg_matches); - let with_hmac_encrypt = sub_arg_matches.is_present("with-hmac-encrypt"); let key_type = sub_arg_matches.value_of("type").unwrap().to_lowercase(); let keychain_name = sub_arg_matches.value_of("keychain-name"); @@ -71,14 +70,10 @@ impl Command for CommandImpl { }; let mut password_opt = None; - let (pkcs8_base64, secret_key_pem) = if with_hmac_encrypt { - ( - cmd_hmac_encrypt::hmac_encrypt(&pkcs8_base64, &mut password_opt, sub_arg_matches)?, - cmd_hmac_encrypt::hmac_encrypt(&secret_key_pem, &mut password_opt, sub_arg_matches)?, - ) - } else { - (pkcs8_base64, secret_key_pem) - }; + let (pkcs8_base64, secret_key_pem) = ( + cmd_hmac_encrypt::do_encrypt(&pkcs8_base64, &mut password_opt, sub_arg_matches)?, + cmd_hmac_encrypt::do_encrypt(&secret_key_pem, &mut password_opt, sub_arg_matches)?, + ); let public_key_base64 = base64_encode(&public_key_der); let keychain_key_uri = if let Some(keychain_name) = keychain_name { @@ -114,7 +109,8 @@ impl Command for CommandImpl { "rsa4096" => Some(KeyAlgorithmId::Rsa4096), _ => None, }; - if let (true, Some(algorithm_id)) = (with_hmac_encrypt, algorithm_id) { + let with_encrypt = hmacutil::is_hmac_encrypted(&pkcs8_base64) || pbeutil::is_simple_pbe_encrypted(&pkcs8_base64); + if let (true, Some(algorithm_id)) = (with_encrypt, algorithm_id) { let yk = yubikeyutil::open_yubikey()?; let yubikey_hmac_enc_soft_key = YubikeyHmacEncSoftKey { key_name: format!("yubikey{}-{}", yk.version().major, yk.serial().0), diff --git a/src/cmd_se_ecdh.rs b/src/cmd_se_ecdh.rs index d17c523..15e60ee 100644 --- a/src/cmd_se_ecdh.rs +++ b/src/cmd_se_ecdh.rs @@ -35,7 +35,7 @@ impl Command for CommandImpl { let key = sub_arg_matches.value_of("key").unwrap(); let epk = sub_arg_matches.value_of("epk").unwrap(); - let key = cmd_hmac_decrypt::try_hmac_decrypt(key)?; + let key = cmd_hmac_decrypt::try_decrypt(key)?; let key_uri = parse_key_uri(&key)?; let se_key_uri = key_uri.as_secure_enclave_key()?; debugging!("Secure enclave key URI: {:?}", se_key_uri); diff --git a/src/cmd_se_ecsign.rs b/src/cmd_se_ecsign.rs index ea83eff..106e564 100644 --- a/src/cmd_se_ecsign.rs +++ b/src/cmd_se_ecsign.rs @@ -45,7 +45,7 @@ impl Command for CommandImpl { Some(input) => input.as_bytes().to_vec(), }; - let key = cmd_hmac_decrypt::try_hmac_decrypt(key)?; + let key = cmd_hmac_decrypt::try_decrypt(key)?; let key_uri = parse_key_uri(&key)?; let se_key_uri = key_uri.as_secure_enclave_key()?; debugging!("Secure enclave key URI: {:?}", se_key_uri); diff --git a/src/cmd_se_generate.rs b/src/cmd_se_generate.rs index 2bfdc7d..fabd1cb 100644 --- a/src/cmd_se_generate.rs +++ b/src/cmd_se_generate.rs @@ -6,7 +6,7 @@ use p256::PublicKey; use rust_util::util_clap::{Command, CommandError}; use spki::DecodePublicKey; use std::collections::BTreeMap; -use crate::cmd_hmac_encrypt::hmac_encrypt; +use crate::cmd_hmac_encrypt; pub struct CommandImpl; @@ -67,12 +67,7 @@ impl Command for CommandImpl { private_key, ); - let with_hmac_encrypt = sub_arg_matches.is_present("with-hmac-encrypt"); - let key_uri = if with_hmac_encrypt { - hmac_encrypt(&key_uri, &mut None, sub_arg_matches)? - } else { - key_uri - }; + let key_uri = cmd_hmac_encrypt::do_encrypt(&key_uri, &mut None, sub_arg_matches)?; print_se_key(json_output, &public_key_point, &public_key_der, &key_uri); Ok(None) diff --git a/src/cmd_se_recover.rs b/src/cmd_se_recover.rs index 0dafeb3..888ba55 100644 --- a/src/cmd_se_recover.rs +++ b/src/cmd_se_recover.rs @@ -23,7 +23,7 @@ impl Command for CommandImpl { seutil::check_se_supported()?; let key = sub_arg_matches.value_of("key").unwrap(); - let key = cmd_hmac_decrypt::try_hmac_decrypt(key)?; + let key = cmd_hmac_decrypt::try_decrypt(key)?; let key_uri = parse_key_uri(&key)?; let se_key_uri = key_uri.as_secure_enclave_key()?; debugging!("Secure enclave key URI: {:?}", se_key_uri); diff --git a/src/cmd_sign_jwt_se.rs b/src/cmd_sign_jwt_se.rs index 074bf6f..4e6815b 100644 --- a/src/cmd_sign_jwt_se.rs +++ b/src/cmd_sign_jwt_se.rs @@ -34,7 +34,7 @@ impl Command for CommandImpl { sub_arg_matches.value_of("key"), "Private key PKCS#8 DER base64 encoded or PEM" ); - let private_key = cmd_hmac_decrypt::try_hmac_decrypt(private_key)?; + let private_key = cmd_hmac_decrypt::try_decrypt(private_key)?; let key_uri = parse_key_uri(&private_key)?; let se_key_uri = key_uri.as_secure_enclave_key()?; debugging!("Secure enclave key URI: {:?}", se_key_uri); diff --git a/src/cmd_sign_jwt_soft.rs b/src/cmd_sign_jwt_soft.rs index 86f194b..9a726e4 100644 --- a/src/cmd_sign_jwt_soft.rs +++ b/src/cmd_sign_jwt_soft.rs @@ -33,7 +33,7 @@ impl Command for CommandImpl { "Private key PKCS#8 DER base64 encoded or PEM" ); - let private_key = cmd_hmac_decrypt::try_hmac_decrypt(private_key)?; + let private_key = cmd_hmac_decrypt::try_decrypt(private_key)?; let private_key = if keychain::is_keychain_key_uri(&private_key) { debugging!("Private key keychain key URI: {}", &private_key);