cli/command/
reset_lock.rs1use super::{CommandError, ContextError, DeviceError};
6use crate::{
7 cli::{get_auth, SubCommand},
8 context::ContextCache,
9 device::{self, Auth, Device},
10};
11use argh::FromArgs;
12use std::{cell::RefCell, rc::Rc};
13use tpm2_protocol::{
14 data::{TpmCc, TpmRcBase, TpmRh, TpmSe},
15 message::TpmDictionaryAttackLockResetCommand,
16};
17
18#[derive(FromArgs, Debug)]
20#[argh(subcommand, name = "reset-lock")]
21pub struct ResetLock {
22 #[argh(option, arg_name = "auth", short = 'a')]
25 pub auth: Option<String>,
26
27 #[argh(option, arg_name = "auth", short = 'm', long = "hmac-auth")]
30 pub hmac_auth: Option<String>,
31}
32
33impl SubCommand for ResetLock {
34 fn run(
35 &self,
36 device: Option<Rc<RefCell<Device>>>,
37 context: &mut ContextCache,
38 _plain: bool,
39 ) -> Result<(), CommandError> {
40 let auth = match (self.auth.as_ref(), self.hmac_auth.as_ref()) {
41 (Some(_), Some(_)) => {
42 return Err(CommandError::InvalidInput(
43 "Cannot use --auth and --hmac-auth at the same time".to_string(),
44 ));
45 }
46 (Some(auth_str), None) => get_auth(
47 Some(auth_str),
48 "TPM2SH_AUTH",
49 &context.session_map,
50 &[TpmSe::Policy],
51 )?,
52 (None, Some(hmac_auth_str)) => get_auth(
53 Some(hmac_auth_str),
54 "TPM2SH_HMAC_AUTH",
55 &context.session_map,
56 &[TpmSe::Hmac],
57 )?,
58 (None, None) => {
59 let auth = get_auth(None, "TPM2SH_AUTH", &context.session_map, &[TpmSe::Policy])?;
60 if matches!(&auth, Auth::Password(p) if p.is_empty()) {
61 get_auth(
62 None,
63 "TPM2SH_HMAC_AUTH",
64 &context.session_map,
65 &[TpmSe::Hmac],
66 )?
67 } else {
68 auth
69 }
70 }
71 };
72 device::with_device(device, |device| {
73 let command = TpmDictionaryAttackLockResetCommand {
74 lock_handle: (TpmRh::Lockout as u32).into(),
75 };
76 let handles = [TpmRh::Lockout as u32];
77 let auths = &[auth];
78
79 let (resp, _) = match context.execute(device, &command, &handles, auths) {
80 Ok(result) => result,
81 Err(ContextError::Device(DeviceError::TpmRc(rc)))
82 if rc.base() == TpmRcBase::Lockout =>
83 {
84 return Err(CommandError::DictionaryAttackLocked);
85 }
86 Err(e) => return Err(e.into()),
87 };
88
89 resp.DictionaryAttackLockReset()
90 .map_err(|_| CommandError::ResponseMismatch(TpmCc::DictionaryAttackLockReset))?;
91
92 writeln!(context.writer, "done")?;
93
94 Ok(())
95 })
96 }
97}