cli/command/
mod.rs

1// SPDX-License-Identifier: GPL-3.0-or-later
2// Copyright (c) 2024-2025 Jarkko Sakkinen
3// Copyright (c) 2025 Opinsys Oy
4
5#![allow(clippy::doc_markdown)]
6
7pub mod algorithm;
8pub mod certificate;
9pub mod convert;
10pub mod create;
11pub mod create_primary;
12pub mod delete;
13pub mod key;
14pub mod load;
15pub mod memory;
16pub mod pcr_event;
17pub mod policy;
18pub mod reset_lock;
19pub mod return_code;
20pub mod save;
21pub mod seal;
22pub mod session;
23pub mod start_session;
24pub mod unseal;
25
26pub use algorithm::*;
27pub use certificate::*;
28pub use convert::*;
29pub use create::*;
30pub use create_primary::*;
31pub use delete::*;
32pub use key::*;
33pub use load::*;
34pub use memory::*;
35pub use pcr_event::*;
36pub use policy::*;
37pub use reset_lock::*;
38pub use return_code::*;
39pub use save::*;
40pub use seal::*;
41pub use session::*;
42pub use start_session::*;
43pub use unseal::*;
44
45use crate::{
46    context::ContextError,
47    crypto::CryptoError,
48    device::DeviceError,
49    key::{AlgInfo, KeyError},
50    pcr::PcrError,
51    policy::PolicyError,
52    session::SessionError,
53    uri::UriError,
54};
55use std::{
56    fmt,
57    io::{IsTerminal, Write},
58    num::TryFromIntError,
59};
60use tabled::{
61    settings::{object::Rows, Disable, Format, Modify, Style},
62    Table, Tabled,
63};
64use thiserror::Error;
65use tpm2_protocol::{data::TpmCc, TpmErrorKind};
66
67/// Creates, styles, and prints a table from a vector of `Tabled` items.
68///
69/// # Errors
70///
71/// Returns an I/O error if writing to the writer fails.
72pub fn print_table<T>(
73    writer: &mut dyn Write,
74    items: Vec<T>,
75    plain: bool,
76) -> Result<(), std::io::Error>
77where
78    T: Tabled,
79{
80    if !items.is_empty() {
81        let mut table = Table::new(items);
82
83        if plain {
84            table.with(Style::empty()).with(Disable::row(Rows::first()));
85        } else {
86            table.with(Style::blank());
87            if std::io::stdout().is_terminal() {
88                table.with(
89                    Modify::new(Rows::first())
90                        .with(Format::content(|s: &str| format!("\x1b[1m{s}\x1b[0m"))),
91                );
92            }
93        }
94        writeln!(writer, "{table}")?;
95    }
96    Ok(())
97}
98
99/// Returns an error if the provided algorithm is `KeyedHash`.
100///
101/// # Errors
102///
103/// Returns `CommandError::UnsupportedKeyAlgorithm` if the algorithm is keyedhash.
104pub fn deny_keyedhash(algorithm: &crate::key::Alg) -> Result<(), CommandError> {
105    if algorithm.params == AlgInfo::KeyedHash {
106        Err(CommandError::UnsupportedKeyAlgorithm(algorithm.clone()))
107    } else {
108        Ok(())
109    }
110}
111
112#[derive(Debug, Error)]
113pub enum CommandError {
114    #[error("capability not found: {0}")]
115    CapabilityMissing(tpm2_protocol::data::TpmCap),
116    #[error("context: {0}")]
117    Context(#[from] ContextError),
118    #[error("crypto: {0}")]
119    Crypto(#[from] CryptoError),
120    #[error("device: {0}")]
121    Device(#[from] DeviceError),
122    #[error("dictionary attack lockout is active")]
123    DictionaryAttackLocked,
124    #[error("format: {0}")]
125    Fmt(#[from] fmt::Error),
126    #[error("invalid input: {0}")]
127    InvalidInput(String),
128    #[error("invalid output: {0}")]
129    InvalidOutput(String),
130    #[error("I/O: {0}")]
131    Io(#[from] std::io::Error),
132    #[error("key error: {0}")]
133    Key(#[from] KeyError),
134    #[error("parent missing")]
135    ParentMissing,
136    #[error("pcr: {0}")]
137    Pcr(#[from] PcrError),
138    #[error("policy: {0}")]
139    Policy(#[from] PolicyError),
140    #[error("response mismatch: {0}")]
141    ResponseMismatch(TpmCc),
142    #[error("session: {0}")]
143    Session(#[from] SessionError),
144    #[error("unsupported key algorithm: '{0}'")]
145    UnsupportedKeyAlgorithm(crate::key::Alg),
146    #[error("unsupported session: {0}")]
147    UnsupportedSession(String),
148    #[error("uri: {0}")]
149    Uri(#[from] UriError),
150}
151
152impl From<TpmErrorKind> for CommandError {
153    fn from(err: TpmErrorKind) -> Self {
154        Self::Device(err.into())
155    }
156}
157
158impl From<TryFromIntError> for CommandError {
159    fn from(err: TryFromIntError) -> Self {
160        Self::Device(err.into())
161    }
162}