From 89a12052931ef360ef7e0842550c6681ada2917c Mon Sep 17 00:00:00 2001 From: zugzwang Date: Fri, 23 Sep 2022 08:27:29 +0200 Subject: [PATCH] Unlock P12 with --pkcs12-passphrase (#70) * Unlock P12 with --pkcs12-passphrase * Bump openpgp-dsm crate version to 1.0.3 --- Cargo.lock | 2 +- openpgp-dsm/Cargo.toml | 2 +- openpgp-dsm/src/lib.rs | 13 +++++++------ sq/src/commands/key.rs | 4 ++++ sq/src/sq-usage.rs | 22 ++++++++++++++++++++++ sq/src/sq.rs | 4 ++++ sq/src/sq_cli.rs | 28 ++++++++++++++++++++++++++++ 7 files changed, 67 insertions(+), 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9a752aca..66c18dea 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2070,7 +2070,7 @@ checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" [[package]] name = "openpgp-dsm" -version = "1.0.2" +version = "1.0.3" dependencies = [ "anyhow", "bindgen", diff --git a/openpgp-dsm/Cargo.toml b/openpgp-dsm/Cargo.toml index d7f559d0..5c7620d3 100644 --- a/openpgp-dsm/Cargo.toml +++ b/openpgp-dsm/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "openpgp-dsm" -version = "1.0.2" +version = "1.0.3" authors = ["zugzwang "] edition = "2018" diff --git a/openpgp-dsm/src/lib.rs b/openpgp-dsm/src/lib.rs index b639bde5..b113da22 100644 --- a/openpgp-dsm/src/lib.rs +++ b/openpgp-dsm/src/lib.rs @@ -110,9 +110,10 @@ pub enum Auth { impl Auth { pub fn from_options_or_env( - cli_api_key: Option<&str>, + cli_api_key: Option<&str>, cli_client_cert: Option<&str>, - cli_app_uuid: Option<&str>, + cli_app_uuid: Option<&str>, + cli_p12_pass: Option<&str>, ) -> Result { // Try API key let api_key = match (cli_api_key, env::var(ENV_API_KEY).ok()) { @@ -169,7 +170,7 @@ impl Auth { Ok(Auth::ApiKey(api_key)) }, (None, Some((client_cert, app_uuid))) => { - let p12_id = try_unlock_p12(client_cert)?; + let p12_id = try_unlock_p12(client_cert, cli_p12_pass)?; let uuid = Uuid::parse_str(&app_uuid) .context("bad app UUID")?; @@ -1847,15 +1848,15 @@ fn api_curve_from_sequoia_curve(curve: SequoiaCurve) -> Result { } } -fn try_unlock_p12(cert_file: String) -> Result { +fn try_unlock_p12(cert_file: String, passphrase: Option<&str>) -> Result { let mut cert_stream = File::open(cert_file.clone()) .context(format!("opening {}", cert_file))?; let mut cert = Vec::new(); cert_stream.read_to_end(&mut cert) .context(format!("reading {}", cert_file))?; - // Try to unlock certificate without password first + // Try to unlock certificate with passed password, if any let mut first = true; - if let Ok(id) = Identity::from_pkcs12(&cert, "") { + if let Ok(id) = Identity::from_pkcs12(&cert, passphrase.unwrap_or("")) { return Ok(id) } else { // Try to unlock with env var passphrase diff --git a/sq/src/commands/key.rs b/sq/src/commands/key.rs index cdabb370..ceb9eb02 100644 --- a/sq/src/commands/key.rs +++ b/sq/src/commands/key.rs @@ -81,6 +81,7 @@ fn generate(config: Config, m: &ArgMatches) -> Result<()> { m.value_of("api-key"), m.value_of("client-cert"), m.value_of("app-uuid"), + m.value_of("pkcs12-passphrase"), )?; println!("Generating keys inside inside Fortanix DSM. This might take a while..."); dsm::generate_key( @@ -334,6 +335,7 @@ fn extract_cert(config: Config, m: &ArgMatches) -> Result<()> { m.value_of("api-key"), m.value_of("client-cert"), m.value_of("app-uuid"), + m.value_of("pkcs12-passphrase"), )?; let dsm_auth = dsm::Credentials::new(dsm_secret)?; dsm::extract_cert(key_name, dsm_auth)? @@ -357,6 +359,7 @@ fn dsm_import(config: Config, m: &ArgMatches) -> Result<()> { m.value_of("api-key"), m.value_of("client-cert"), m.value_of("app-uuid"), + m.value_of("pkcs12-passphrase"), )?; let dsm_auth = dsm::Credentials::new(dsm_secret)?; let input = open_or_stdin(m.value_of("input"))?; @@ -376,6 +379,7 @@ fn extract_dsm(config: Config, m: &ArgMatches) -> Result<()> { m.value_of("api-key"), m.value_of("client-cert"), m.value_of("app-uuid"), + m.value_of("pkcs12-passphrase"), )?; let dsm_auth = dsm::Credentials::new(dsm_secret)?; let key = match m.value_of("dsm-key") { diff --git a/sq/src/sq-usage.rs b/sq/src/sq-usage.rs index eb7f4ffe..5f497b9f 100644 --- a/sq/src/sq-usage.rs +++ b/sq/src/sq-usage.rs @@ -104,6 +104,9 @@ //! -o, --output //! Writes to FILE or stdout if omitted //! +//! --pkcs12-passphrase +//! Passphrase for unlocking the PKCS12 identity file (cert-based +//! authentication) //! --private-key-store //! Provides parameters for private key store //! @@ -193,6 +196,9 @@ //! -o, --output //! Writes to FILE or stdout if omitted //! +//! --pkcs12-passphrase +//! Passphrase for unlocking the PKCS12 identity file (cert-based +//! authentication) //! --private-key-store //! Provides parameters for private key store //! @@ -283,6 +289,9 @@ //! -o, --output //! Writes to FILE or stdout if omitted //! +//! --pkcs12-passphrase +//! Passphrase for unlocking the PKCS12 identity file (cert-based +//! authentication) //! --private-key-store //! Provides parameters for private key store //! @@ -480,6 +489,9 @@ //! -e, --export //! Writes the key to OUTFILE //! +//! --pkcs12-passphrase +//! Passphrase for unlocking the PKCS12 identity file (cert-based +//! authentication) //! --rev-cert //! Writes the revocation certificate to FILE. mandatory if OUTFILE is //! "-". [default: .rev] @@ -592,6 +604,9 @@ //! -o, --output //! Writes to FILE or stdout if omitted //! +//! --pkcs12-passphrase +//! Passphrase for unlocking the PKCS12 identity file (cert-based +//! authentication) //! //! ARGS: //! @@ -644,6 +659,10 @@ //! //! -o, --output //! Writes to FILE or stdout if omitted +//! +//! --pkcs12-passphrase +//! Passphrase for unlocking the PKCS12 identity file (cert-based +//! authentication) //! ``` //! //! ### Subcommand key dsm-import @@ -684,6 +703,9 @@ //! --input //! Reads from FILE or stdin if omitted //! +//! --pkcs12-passphrase +//! Passphrase for unlocking the PKCS12 identity file (cert-based +//! authentication) //! //! EXAMPLES: //! diff --git a/sq/src/sq.rs b/sq/src/sq.rs index 94cabbd9..2ad674ee 100644 --- a/sq/src/sq.rs +++ b/sq/src/sq.rs @@ -441,6 +441,7 @@ fn main() -> Result<()> { m.value_of("api-key"), m.value_of("client-cert"), m.value_of("app-uuid"), + m.value_of("pkcs12-passphrase"), )?; let dsm_auth = Credentials::new(dsm_secret)?; secrets.push(PreSecret::Dsm(dsm_auth, name.to_string())); @@ -488,6 +489,7 @@ fn main() -> Result<()> { m.value_of("api-key"), m.value_of("client-cert"), m.value_of("app-uuid"), + m.value_of("pkcs12-passphrase"), )?; let dsm_auth = Credentials::new(dsm_secret)?; additional_secrets @@ -554,6 +556,7 @@ fn main() -> Result<()> { m.value_of("api-key"), m.value_of("client-cert"), m.value_of("app-uuid"), + m.value_of("pkcs12-passphrase"), )?; let dsm_auth = Credentials::new(dsm_secret)?; secrets.push(secrets::PreSecret::Dsm(dsm_auth, name.to_string())); @@ -702,6 +705,7 @@ fn main() -> Result<()> { m.value_of("api-key"), m.value_of("client-cert"), m.value_of("app-uuid"), + m.value_of("pkcs12-passphrase"), )?; let dsm_auth = Credentials::new(dsm_secret)?; secrets.push(PreSecret::Dsm(dsm_auth, name.to_string())); diff --git a/sq/src/sq_cli.rs b/sq/src/sq_cli.rs index fd3ff1df..93291f94 100644 --- a/sq/src/sq_cli.rs +++ b/sq/src/sq_cli.rs @@ -149,6 +149,10 @@ $ sq decrypt ciphertext.pgp .long("app-uuid").value_name("APP-UUID") .help("Authenticates to Fortanix DSM with the given App \ (cert-based authentication)")) + .arg(Arg::with_name("pkcs12-passphrase") + .long("pkcs12-passphrase").value_name("PKCS12-PASSPHRASE") + .help("Passphrase for unlocking the PKCS12 identity file \ + (cert-based authentication)")) .arg(Arg::with_name("dsm-key") .long("dsm-key").value_name("DSM-KEY-NAME") .help("Decrypts with secrets stored inside the \ @@ -210,6 +214,10 @@ $ sq encrypt --symmetric message.txt .long("app-uuid").value_name("APP-UUID") .help("Authenticates to Fortanix DSM with the given App \ (cert-based authentication)")) + .arg(Arg::with_name("pkcs12-passphrase") + .long("pkcs12-passphrase").value_name("PKCS12-PASSPHRASE") + .help("Passphrase for unlocking the PKCS12 identity file \ + (cert-based authentication)")) .arg(Arg::with_name("signer-dsm-key") .long("signer-dsm-key").value_name("DSM-KEY-NAME") .help("Signs the message with a key stored in Fortanix \ @@ -334,6 +342,10 @@ $ sq sign --detached --signer-key juliet.pgp message.txt .long("app-uuid").value_name("APP-UUID") .help("Authenticates to Fortanix DSM with the given App \ (cert-based authentication)")) + .arg(Arg::with_name("pkcs12-passphrase") + .long("pkcs12-passphrase").value_name("PKCS12-PASSPHRASE") + .help("Passphrase for unlocking the PKCS12 identity file \ + (cert-based authentication)")) .arg(Arg::with_name("dsm-key") .long("dsm-key").value_name("DSM-KEY-NAME") .help("Signs the message with the Fortanix DSM key")) @@ -605,6 +617,10 @@ $ sq key generate --userid \"\" --userid \"Juliet Capulet\" .long("app-uuid").value_name("APP-UUID") .help("Authenticates to Fortanix DSM with the given App \ (cert-based authentication)")) + .arg(Arg::with_name("pkcs12-passphrase") + .long("pkcs12-passphrase").value_name("PKCS12-PASSPHRASE") + .help("Passphrase for unlocking the PKCS12 identity file \ + (cert-based authentication)")) .arg(Arg::with_name("dsm-exportable") .long("dsm-exportable") .help("(DANGER) Configure the key to be exportable from DSM")) @@ -759,6 +775,10 @@ $ sq key extract-cert --output juliet.cert.pgp juliet.key.pgp .long("app-uuid").value_name("APP-UUID") .help("Authenticates to Fortanix DSM with the given App \ (cert-based authentication)")) + .arg(Arg::with_name("pkcs12-passphrase") + .long("pkcs12-passphrase").value_name("PKCS12-PASSPHRASE") + .help("Passphrase for unlocking the PKCS12 identity file \ + (cert-based authentication)")) .arg(Arg::with_name("dsm-key") .long("dsm-key").value_name("DSM-KEY-NAME") .help("Extracts the certificate from Fortanix \ @@ -785,6 +805,10 @@ command exfiltrates secrets from DSM and outputs a Key. .long("app-uuid").value_name("APP-UUID") .help("Authenticates to Fortanix DSM with the given App \ (cert-based authentication)")) + .arg(Arg::with_name("pkcs12-passphrase") + .long("pkcs12-passphrase").value_name("PKCS12-PASSPHRASE") + .help("Passphrase for unlocking the PKCS12 identity file \ + (cert-based authentication)")) .arg(Arg::with_name("dsm-key") .long("dsm-key").value_name("DSM-KEY-NAME") .required(true) @@ -822,6 +846,10 @@ $ sq-dsm key dsm-import --dsm-key=\"Imported by sq-dsm\" < my_priv_key.asc .long("app-uuid").value_name("APP-UUID") .help("Authenticates to Fortanix DSM with the given App \ (cert-based authentication)")) + .arg(Arg::with_name("pkcs12-passphrase") + .long("pkcs12-passphrase").value_name("PKCS12-PASSPHRASE") + .help("Passphrase for unlocking the PKCS12 identity file \ + (cert-based authentication)")) .arg(Arg::with_name("dsm-key") .long("dsm-key").value_name("DSM-KEY-NAME") .required(true)