cli/command/
unseal.rs

1// SPDX-License-Identifier: GPL-3-0-or-later
2// Copyright (c) 2025 Opinsys Oy
3
4use crate::{
5    cli::SubCommand, command::CommandError, device::with_device, handle::Handle, job::Job,
6};
7use clap::Args;
8use std::io::IsTerminal;
9use tpm2_protocol::{data::TpmCc, message::TpmUnsealCommand};
10
11/// Retrieves data from a sealed data object.
12#[derive(Args, Debug)]
13#[command(about = "Retrieves data from a sealed data object.")]
14pub struct Unseal {
15    /// Input: 'tpm:<persistent handle>' or 'vtpm:<transient handle>'
16    pub input: Handle,
17
18    /// Force hex output when redirecting to a file or pipe
19    #[arg(long)]
20    pub hex: bool,
21}
22
23impl SubCommand for Unseal {
24    fn run(&self, job: &mut Job) -> Result<(), CommandError> {
25        with_device(job.device.clone(), |device| {
26            let item_handle = job.load_context(device, &self.input)?;
27            let auths = vec![job.auth_list.first().cloned().unwrap_or_default()];
28
29            let unseal_cmd = TpmUnsealCommand {
30                item_handle: item_handle.0.into(),
31            };
32            let unseal_handles = [item_handle.0];
33
34            let (resp, _) = job.execute(device, &unseal_cmd, &unseal_handles, &auths)?;
35
36            let out_data = resp
37                .Unseal()
38                .map_err(|_| CommandError::ResponseMismatch(TpmCc::Unseal))?
39                .out_data;
40
41            if self.hex || std::io::stdout().is_terminal() {
42                writeln!(job.writer, "{}", hex::encode(out_data.as_ref()))?;
43            } else {
44                job.writer.write_all(out_data.as_ref())?;
45            }
46            Ok(())
47        })
48    }
49}