diff --git a/tools/src/bin/opgpcard/cli.rs b/tools/src/bin/opgpcard/cli.rs index 7ed6696..8328fd5 100644 --- a/tools/src/bin/opgpcard/cli.rs +++ b/tools/src/bin/opgpcard/cli.rs @@ -75,17 +75,7 @@ pub enum Command { }, /// Decrypt data using a card - Decrypt { - #[clap(name = "card ident", short = 'c', long = "card")] - ident: String, - - #[clap(name = "User PIN file", short = 'p', long = "user-pin")] - user_pin: Option, - - /// Input file (stdin if unset) - #[clap(name = "input")] - input: Option, - }, + Decrypt(commands::decrypt::DecryptCommand), /// Sign data using a card Sign { diff --git a/tools/src/bin/opgpcard/commands/decrypt.rs b/tools/src/bin/opgpcard/commands/decrypt.rs new file mode 100644 index 0000000..34c7d56 --- /dev/null +++ b/tools/src/bin/opgpcard/commands/decrypt.rs @@ -0,0 +1,56 @@ +// SPDX-FileCopyrightText: 2021-2022 Heiko Schaefer +// SPDX-FileCopyrightText: 2022 Nora Widdecke +// SPDX-License-Identifier: MIT OR Apache-2.0 + +use anyhow::{anyhow, Result}; +use clap::Parser; + +use std::path::PathBuf; + +use sequoia_openpgp::{ + parse::{stream::DecryptorBuilder, Parse}, + policy::StandardPolicy, +}; + +use openpgp_card_sequoia::card::Card; + +use crate::util; + +#[derive(Parser, Debug)] +pub struct DecryptCommand { + #[clap(name = "card ident", short = 'c', long = "card")] + ident: String, + + #[clap(name = "User PIN file", short = 'p', long = "user-pin")] + pin_file: Option, + + /// Input file (stdin if unset) + #[clap(name = "input")] + input: Option, +} + +pub fn decrypt(command: DecryptCommand) -> Result<(), Box> { + let p = StandardPolicy::new(); + + let input = util::open_or_stdin(command.input.as_deref())?; + + let backend = util::open_card(&command.ident)?; + let mut card = Card::new(backend); + let mut open = card.transaction()?; + + if open.fingerprints()?.decryption().is_none() { + return Err(anyhow!("Can't decrypt: this card has no key in the decryption slot.").into()); + } + + let user_pin = util::get_pin(&mut open, command.pin_file, crate::ENTER_USER_PIN); + + let mut user = util::verify_to_user(&mut open, user_pin.as_deref())?; + let d = user.decryptor(&|| println!("Touch confirmation needed for decryption"))?; + + let db = DecryptorBuilder::from_reader(input)?; + let mut decryptor = db.with_policy(&p, None, d)?; + + std::io::copy(&mut decryptor, &mut std::io::stdout())?; + + Ok(()) +} diff --git a/tools/src/bin/opgpcard/commands/mod.rs b/tools/src/bin/opgpcard/commands/mod.rs index 590a30a..7746aec 100644 --- a/tools/src/bin/opgpcard/commands/mod.rs +++ b/tools/src/bin/opgpcard/commands/mod.rs @@ -2,6 +2,7 @@ // SPDX-FileCopyrightText: 2022 Nora Widdecke // SPDX-License-Identifier: MIT OR Apache-2.0 +pub mod decrypt; pub mod info; pub mod pubkey; pub mod ssh; diff --git a/tools/src/bin/opgpcard/main.rs b/tools/src/bin/opgpcard/main.rs index 5e8e848..4087f98 100644 --- a/tools/src/bin/opgpcard/main.rs +++ b/tools/src/bin/opgpcard/main.rs @@ -10,7 +10,7 @@ use std::path::{Path, PathBuf}; use sequoia_openpgp::cert::prelude::ValidErasedKeyAmalgamation; use sequoia_openpgp::packet::key::{SecretParts, UnspecifiedRole}; use sequoia_openpgp::packet::Key; -use sequoia_openpgp::parse::{stream::DecryptorBuilder, Parse}; +use sequoia_openpgp::parse::Parse; use sequoia_openpgp::policy::{Policy, StandardPolicy}; use sequoia_openpgp::serialize::stream::{Armorer, Message, Signer}; use sequoia_openpgp::serialize::SerializeInto; @@ -64,12 +64,8 @@ fn main() -> Result<(), Box> { cli::Command::SetIdentity { ident, id } => { set_identity(&ident, id)?; } - cli::Command::Decrypt { - ident, - user_pin, - input, - } => { - decrypt(&ident, user_pin, input.as_deref())?; + cli::Command::Decrypt(cmd) => { + commands::decrypt::decrypt(cmd)?; } cli::Command::Sign { ident, @@ -595,36 +591,6 @@ fn pick_card_for_reading(ident: Option) -> Result, - input: Option<&Path>, -) -> Result<(), Box> { - let p = StandardPolicy::new(); - - let input = util::open_or_stdin(input)?; - - let backend = util::open_card(ident)?; - let mut card = Card::new(backend); - let mut open = card.transaction()?; - - if open.fingerprints()?.decryption().is_none() { - return Err(anyhow!("Can't decrypt: this card has no key in the decryption slot.").into()); - } - - let user_pin = util::get_pin(&mut open, pin_file, ENTER_USER_PIN); - - let mut user = util::verify_to_user(&mut open, user_pin.as_deref())?; - let d = user.decryptor(&|| println!("Touch confirmation needed for decryption"))?; - - let db = DecryptorBuilder::from_reader(input)?; - let mut decryptor = db.with_policy(&p, None, d)?; - - std::io::copy(&mut decryptor, &mut std::io::stdout())?; - - Ok(()) -} - fn sign_detached( ident: &str, pin_file: Option,