diff --git a/tss-esapi/src/context.rs b/tss-esapi/src/context.rs index dd4577b4..9d10c1dc 100644 --- a/tss-esapi/src/context.rs +++ b/tss-esapi/src/context.rs @@ -3,7 +3,7 @@ mod handle_manager; use crate::{ attributes::SessionAttributesBuilder, - constants::{CapabilityType, PropertyTag, SessionType}, + constants::{CapabilityType, PropertyTag, SessionType, StartupType}, handles::{ObjectHandle, SessionHandle}, interface_types::{algorithm::HashingAlgorithm, session_handles::AuthSession}, structures::{CapabilityData, SymmetricDefinition}, @@ -91,6 +91,9 @@ impl Context { pub fn new(tcti_name_conf: TctiNameConf) -> Result { let mut esys_context = null_mut(); + // Some TCTI backend will not automatically send a clear and we need to send a clear + // manually before being to operate. + let needs_clear_startup = matches!(tcti_name_conf, TctiNameConf::LibTpms { .. }); let mut _tcti_context = TctiContext::initialize(tcti_name_conf)?; ReturnCode::ensure_success( @@ -107,13 +110,19 @@ impl Context { )?; let esys_context = unsafe { Some(Malloced::from_raw(esys_context)) }; - Ok(Context { + let mut context = Context { esys_context, sessions: (None, None, None), _tcti_context, handle_manager: HandleManager::new(), cached_tpm_properties: HashMap::new(), - }) + }; + + if needs_clear_startup { + context.startup(StartupType::Clear)?; + } + + Ok(context) } /// Create a new ESYS context based on the TAB Resource Manager Daemon. diff --git a/tss-esapi/src/tcti_ldr.rs b/tss-esapi/src/tcti_ldr.rs index f564baf8..9b4a0fa2 100644 --- a/tss-esapi/src/tcti_ldr.rs +++ b/tss-esapi/src/tcti_ldr.rs @@ -21,6 +21,7 @@ const DEVICE: &str = "device"; const MSSIM: &str = "mssim"; const SWTPM: &str = "swtpm"; const TABRMD: &str = "tabrmd"; +const LIBTPMS: &str = "libtpms"; /// TCTI Context created via a TCTI Loader Library. /// Wrapper around the TSS2_TCTI_CONTEXT structure. @@ -139,6 +140,10 @@ pub enum TctiNameConf { /// /// For more information about configuration, see [this page](https://www.mankier.com/3/Tss2_Tcti_Mssim_Init) Swtpm(TpmSimulatorConfig), + /// Connect to a TPM (simulator) available as a library + /// + /// This allows for an optional state file + LibTpms { state: Option }, /// Connect to a TPM through an Access Broker/Resource Manager daemon /// /// For more information about configuration, see [this page](https://www.mankier.com/3/Tss2_Tcti_Tabrmd_Init) @@ -174,6 +179,7 @@ impl TryFrom for CString { TctiNameConf::Mssim(..) => MSSIM, TctiNameConf::Swtpm(..) => SWTPM, TctiNameConf::Tabrmd(..) => TABRMD, + TctiNameConf::LibTpms { .. } => LIBTPMS, }; let tcti_conf = match tcti { @@ -204,6 +210,9 @@ impl TryFrom for CString { TctiNameConf::Tabrmd(config) => { format!("bus_name={},bus_type={}", config.bus_name, config.bus_type) } + TctiNameConf::LibTpms { state } => { + state.map(|s| s.display().to_string()).unwrap_or_default() + } }; if tcti_conf.is_empty() { @@ -247,6 +256,15 @@ impl FromStr for TctiNameConf { )?)); } + let libtpms_pattern = Regex::new(r"^libtpms(:(.*))?$").unwrap(); //should not fail + if let Some(captures) = libtpms_pattern.captures(config_str) { + return Ok(TctiNameConf::LibTpms { + state: captures + .get(2) + .and_then(|s| PathBuf::from_str(s.as_str()).ok()), + }); + } + Err(Error::WrapperError(WrapperErrorKind::InvalidParam)) } } @@ -327,6 +345,17 @@ fn validate_from_str_tcti() { let tcti = TctiNameConf::from_str("tabrmd").unwrap(); assert_eq!(tcti, TctiNameConf::Tabrmd(Default::default())); + + let tcti = TctiNameConf::from_str("libtpms:/try/this/path").unwrap(); + assert_eq!( + tcti, + TctiNameConf::LibTpms { + state: Some(PathBuf::from("/try/this/path")) + } + ); + + let tcti = TctiNameConf::from_str("libtpms").unwrap(); + assert_eq!(tcti, TctiNameConf::LibTpms { state: None }); } /// Configuration for a Device TCTI context