1use crate::{
6 command::CommandError,
7 context::ContextCache,
8 key::{Alg, KeyError, TpmKey},
9 uri::Uri,
10};
11use std::io::{self, Read};
12use tpm2_protocol::{
13 constant::TPM_MAX_COMMAND_SIZE, data::TpmRc, TpmBuild, TpmErrorKind, TpmHandle, TpmWriter,
14};
15
16pub fn from_str_to_handle(input: &str) -> Result<TpmHandle, String> {
23 let input = match input.strip_prefix("0x") {
24 Some(input) => input,
25 None => input,
26 };
27 u32::from_str_radix(input, 16)
28 .map(TpmHandle)
29 .map_err(|e| e.to_string())
30}
31
32pub fn from_tpm_object_to_vec<T: TpmBuild>(obj: &T) -> Result<Vec<u8>, TpmErrorKind> {
38 let mut buf = vec![0u8; TPM_MAX_COMMAND_SIZE];
39 let len = {
40 let mut writer = TpmWriter::new(&mut buf);
41 obj.build(&mut writer)?;
42 writer.len()
43 };
44 buf.truncate(len);
45 Ok(buf)
46}
47
48pub fn from_input_to_bytes(input: Option<&Uri>) -> io::Result<Vec<u8>> {
54 let mut input_bytes = Vec::new();
55 match input {
56 Some(Uri::Path(path)) => {
57 input_bytes = std::fs::read(path)?;
58 }
59 None => {
60 io::stdin().read_to_end(&mut input_bytes)?;
61 }
62 Some(uri) => {
63 return Err(io::Error::new(
64 io::ErrorKind::InvalidInput,
65 format!("input must be a file path, but got '{uri}'"),
66 ));
67 }
68 }
69 Ok(input_bytes)
70}
71
72pub fn from_tpm_key_to_output(
81 context: &mut ContextCache,
82 tpm_key: &TpmKey,
83 output: Option<&Uri>,
84) -> Result<(), CommandError> {
85 if let Some(output_uri) = output {
86 if !matches!(output_uri, Uri::Path(_)) {
87 return Err(CommandError::InvalidOutput(format!(
88 "output must be a file path, but got '{output_uri}'"
89 )));
90 }
91 context.write_key_data(Some(output_uri), tpm_key)?;
92 } else {
93 context.write_key_data(None, tpm_key)?;
94 }
95 Ok(())
96}
97
98pub fn from_str_to_tpm_rc(s: &str) -> Result<TpmRc, String> {
104 let s_no_prefix = s.strip_prefix("0x").unwrap_or(s);
105 let raw_rc = u32::from_str_radix(s_no_prefix, 16)
106 .map_err(|e| format!("Failed to parse hex u32: {e}"))?;
107 TpmRc::try_from(raw_rc).map_err(|e| format!("Invalid TPM RC value '{s}': {e}"))
108}
109
110pub fn from_str_to_alg(s: &str) -> Result<Alg, String> {
116 Alg::new_keyedhash(s).map_err(|e: KeyError| e.to_string())
117}