1#![allow(clippy::doc_markdown)]
6
7use crate::{
8 auth::Auth,
9 command::{
10 Algorithm, Cache, Certificate, CommandError, Convert, Create, CreatePrimary, Delete, Evict,
11 Load, Memory, PcrEvent, Policy, ResetLock, ReturnCode, Unseal,
12 },
13 job::Job,
14};
15use clap::{builder::styling::Styles, Parser, Subcommand};
16use std::path::PathBuf;
17use strum::{Display, EnumString};
18use tpm2_protocol::data::TpmRh;
19
20const STYLES: Styles = Styles::styled()
21 .header(clap::builder::styling::Style::new().bold())
22 .usage(clap::builder::styling::Style::new().bold())
23 .literal(clap::builder::styling::Style::new())
24 .placeholder(clap::builder::styling::Style::new());
25
26pub trait SubCommand {
28 fn run(&self, job: &mut Job) -> Result<(), CommandError>;
34
35 #[must_use]
37 fn is_local(&self) -> bool {
38 false
39 }
40}
41
42#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Display, EnumString)]
43#[strum(serialize_all = "kebab-case")]
44pub enum LogFormat {
45 #[default]
46 Plain,
47 Pretty,
48}
49
50#[derive(Parser, Debug)]
52#[command(version, about, styles = STYLES)]
53pub struct TopLevel {
54 #[arg(short = 'd', long, default_value = "/dev/tpmrm0")]
56 pub device: PathBuf,
57
58 #[arg(long, default_value_t = LogFormat::default(), value_parser = clap::value_parser!(LogFormat))]
60 pub log_format: LogFormat,
61
62 #[arg(short = 'A', long = "auth", global = true, value_delimiter = ',')]
64 pub auth: Vec<Auth>,
65
66 #[command(subcommand)]
67 pub command: Command,
68}
69
70#[derive(Subcommand, Debug)]
71pub enum Command {
72 Algorithm(Algorithm),
73 Cache(Cache),
74 Certificate(Certificate),
75 Convert(Convert),
76 Create(Create),
77 CreatePrimary(CreatePrimary),
78 Delete(Delete),
79 Evict(Evict),
80 Load(Load),
81 Memory(Memory),
82 PcrEvent(PcrEvent),
83 Policy(Policy),
84 ReturnCode(ReturnCode),
85 ResetLock(ResetLock),
86 Unseal(Unseal),
87}
88
89impl Command {
90 fn as_subcommand(&self) -> &dyn SubCommand {
91 match self {
92 Self::Algorithm(cmd) => cmd,
93 Self::Cache(cmd) => cmd,
94 Self::Certificate(cmd) => cmd,
95 Self::Convert(cmd) => cmd,
96 Self::Create(cmd) => cmd,
97 Self::CreatePrimary(cmd) => cmd,
98 Self::Delete(cmd) => cmd,
99 Self::Evict(cmd) => cmd,
100 Self::Load(cmd) => cmd,
101 Self::Memory(cmd) => cmd,
102 Self::PcrEvent(cmd) => cmd,
103 Self::Policy(cmd) => cmd,
104 Self::ReturnCode(cmd) => cmd,
105 Self::ResetLock(cmd) => cmd,
106 Self::Unseal(cmd) => cmd,
107 }
108 }
109}
110
111impl SubCommand for Command {
112 fn run(&self, job: &mut Job) -> Result<(), CommandError> {
113 self.as_subcommand().run(job)
114 }
115
116 fn is_local(&self) -> bool {
117 self.as_subcommand().is_local()
118 }
119}
120
121#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Display, EnumString)]
122#[strum(serialize_all = "kebab-case")]
123pub enum Hierarchy {
124 #[default]
125 Owner,
126 Platform,
127 Endorsement,
128}
129
130impl From<Hierarchy> for TpmRh {
131 fn from(h: Hierarchy) -> Self {
132 match h {
133 Hierarchy::Owner => TpmRh::Owner,
134 Hierarchy::Platform => TpmRh::Platform,
135 Hierarchy::Endorsement => TpmRh::Endorsement,
136 }
137 }
138}