use std::{ os::raw::c_char, ffi::CStr, }; use tss_esapi::constants::response_code::Tss2ResponseCode; use tss_esapi_sys::TSS2_RC; #[link(name = "tss2-rc")] extern { fn Tss2_RC_Decode(rc: TSS2_RC) -> *const c_char; } trait HasResponseCode { fn response_code(&self) -> TSS2_RC; } fn tss2_rc_decode(err: E) -> &'static str { let c_str = unsafe { let ptr = Tss2_RC_Decode(err.response_code()); CStr::from_ptr(ptr) }; // We're relying on Tss2_RC_Decode to return valid C strings. c_str.to_str().unwrap() } impl HasResponseCode for Tss2ResponseCode { fn response_code(&self) -> TSS2_RC { match self { Tss2ResponseCode::Success => 0, Tss2ResponseCode::FormatZero(code) => code.0, Tss2ResponseCode::FormatOne(code) => code.0, } } } trait Tss2Expect { /// Provides an enhanced error message for types which contain TSS2 response codes. fn tss2_expect(self, err_msg: &str) -> T; } impl Tss2Expect for tss_esapi::Result { fn tss2_expect(self, err_msg: &str) -> T { match self { tss_esapi::Result::Ok(val) => val, tss_esapi::Result::Err(err) => { match err { tss_esapi::Error::WrapperError(err) => panic!("{}: {}", err_msg, err), tss_esapi::Error::Tss2Error(err) => { let rc = err.response_code(); let text = tss2_rc_decode(err); panic!("{}, response code: {}, response text: {}", err_msg, rc, text); } } }, } } } #[cfg(test)] mod test { use super::*; use tss_esapi::{ Context, constants::{ session_type::{SessionType}, }, tcti_ldr::{TabrmdConfig}, interface_types::{ resource_handles::{Hierarchy}, algorithm::{HashingAlgorithm}, ecc::{EccCurve}, }, structures::{ Digest, EccPoint, EccScheme, KeyDerivationFunctionScheme, HashScheme, Public, PublicEccParameters, SymmetricDefinition, SymmetricDefinitionObject, }, attributes::{ object::{ObjectAttributes}, }, }; #[test] fn create_context() { let config = TabrmdConfig::default(); let mut context = Context::new_with_tabrmd(config).unwrap(); context.self_test(true).unwrap(); } #[test] fn create_primary_key() { let config = TabrmdConfig::default(); let mut context = Context::new_with_tabrmd(config) .expect("Failed to connect to tabrmd. Ensure that tpm2-abrmd is running"); let public = { let object_attributes = ObjectAttributes::builder() .with_fixed_tpm(true) .with_fixed_parent(true) .with_sensitive_data_origin(true) .with_user_with_auth(true) .with_decrypt(false) .with_sign_encrypt(true) .with_restricted(false) .build() .expect("ObjectAttributesBuilder failed"); let name_hashing_algorithm = HashingAlgorithm::Sha256; let empty = [0u8; 0]; let auth_policy = Digest::try_from(empty.as_slice()).unwrap(); let parameters = PublicEccParameters::new( SymmetricDefinitionObject::Null, EccScheme::EcDsa(HashScheme::new(HashingAlgorithm::Sha256)), EccCurve::NistP256, KeyDerivationFunctionScheme::Null ); Public::Ecc { object_attributes, name_hashing_algorithm, auth_policy, parameters, unique: EccPoint::default(), } }; let session = context.start_auth_session( None, None, None, SessionType::Hmac, SymmetricDefinition::AES_256_CFB, HashingAlgorithm::Sha256, ) .expect("Failed to create session") .expect("Received invalid handle"); context.execute_with_session(Some(session), |ctx| { let primary = ctx.create_primary( Hierarchy::Null, public, None, None, None, None, ) .tss2_expect("create_primary failed") .key_handle; ctx.flush_context(primary.into()).expect("flush_context failed"); }); } }