diff --git a/tss-esapi/Cargo.toml b/tss-esapi/Cargo.toml
index fa8e9fed6..7524cd29d 100644
--- a/tss-esapi/Cargo.toml
+++ b/tss-esapi/Cargo.toml
@@ -64,8 +64,10 @@ strum = { version = "0.26.3", optional = true }
strum_macros = { version = "0.26.4", optional = true }
paste = "1.0.14"
getrandom = "0.2.11"
+env = "*"
[dev-dependencies]
+serial_test = { version = "*", features = ["file_locks"] }
env_logger = "0.11.5"
serde_json = "^1.0.108"
sha2 = { version = "0.10.8", features = ["oid"] }
diff --git a/tss-esapi/README.md b/tss-esapi/README.md
index 3ee4a12be..4089937a1 100644
--- a/tss-esapi/README.md
+++ b/tss-esapi/README.md
@@ -1,4 +1,4 @@
-# TPM2 Software Stack Rust Wrapper
+# TPM2 Software Stack Rust Wrapper
@@ -6,12 +6,12 @@
-This is the high-level, Rust idiomatic wrapper crate that exposes an interface
+This is the high-level, Rust idiomatic wrapper crate that exposes an interface
to [TSS](https://github.com/tpm2-software/tpm2-tss).
This crate depends on the [`tss-esapi-sys`](../tss-esapi-sys/) crate for its
FFI interface. By default, pre-generated bindings are used. If you'd like the
-bindings to be generated at build time, please enable either the
+bindings to be generated at build time, please enable either the
`generate-bindings` feature - the FFI bindings will then be generated at build
time using the headers identified on the system.
@@ -31,7 +31,7 @@ The crate currently offers the following features:
* `abstraction` (enabled by default) - provides a set of abstracted primitives
on top of the basic Rust-native ESAPI API provided by the crate. This feature
can be turned off to reduce the number of dependencies built.
-* `serde` - enable serde `Serialize`/`Deserialize` traits for types.
+* `serde` - enable serde `Serialize`/`Deserialize` traits for types.
* `rustcrypto-full` (disabled by default) - provides conversion from all
supported elliptic curves, rsa or hashes.
Support for individual hash, rsa or curves can be pulled individually.
@@ -45,4 +45,11 @@ The crate currently offers the following features:
For more information on cross-compiling the `tss-esapi` crate, please see the README of the `tss-esapi-sys` crate.
+## Building against libtss2
+
+The [TSS](https://github.com/tpm2-software/tpm2-tss) library can be installed from Debian, RPM, or other packaging manager.
+It will install a pkg-config definition to indicate how to compile and link against the library.
+When it is installed via source, and/or if it has been edited (such as to debug things), then the version number will be marked with the git commit (and dirty flag). The resulting version string is unfortunately not compatible with the semver parser/comparing mechanism, and it can be rejected.
+Setting the environment variable TPM2\_TSS\_VERSION\_IGNORE\]_PRERELEASE to a non-empty string will cause the build system to ignore this pre-release information.
+
*Copyright 2021 Contributors to the Parsec project.*
diff --git a/tss-esapi/build.rs b/tss-esapi/build.rs
index 39c3a0a18..ef3f3305c 100644
--- a/tss-esapi/build.rs
+++ b/tss-esapi/build.rs
@@ -1,8 +1,9 @@
// Copyright 2021 Contributors to the Parsec project.
// SPDX-License-Identifier: Apache-2.0
-use semver::{Version, VersionReq};
+use semver::{Version, VersionReq, Prerelease};
const TPM2_TSS_MINIMUM_VERSION: Version = Version::new(4, 1, 3);
+const TPM2_TSS_VERSION_IGNORE_PRERELEASE: &str = "TPM2_TSS_VERSION_IGNORE_PRERELEASE";
fn main() {
println!("cargo:rustc-check-cfg=cfg(hierarchy_is_esys_tr)");
@@ -20,15 +21,22 @@ fn main() {
.expect("Failed to parse ENV variable DEP_TSS2_ESYS_VERSION as string");
Version::parse(&tss_version_string)
- .expect("Failed to parse the DEP_TSS2_ESYS_VERSION variable as a semver version")
+ .map(|mut v| {
+ if std::env::var(TPM2_TSS_VERSION_IGNORE_PRERELEASE).is_ok() {
+ v.pre = Prerelease::EMPTY;
+ }
+ v
+ })
+ .expect("Failed to parse the DEP_TSS2_ESYS_VERSION variable {tss_version_string} as a semver version")
};
let supported_tss_version =
VersionReq::parse("<5.0.0, >=2.3.3").expect("Failed to parse supported TSS version");
+ //eprintln!("tss version: {} / {:?}", supported_tss_version, tss_version);
assert!(
supported_tss_version.matches(&tss_version),
- "Unsupported TSS version {tss_version}"
+ "Unsupported TSS version {tss_version}, maybe try {TPM2_TSS_VERSION_IGNORE_PRERELEASE}=true"
);
let hierarchy_is_esys_tr_req = VersionReq::parse(">=3.0.0").unwrap();
diff --git a/tss-esapi/examples/certify.rs b/tss-esapi/examples/certify.rs
index 2c6f7a0b4..229d60a32 100644
--- a/tss-esapi/examples/certify.rs
+++ b/tss-esapi/examples/certify.rs
@@ -111,10 +111,12 @@ use tss_esapi::{
interface_types::{
algorithm::{HashingAlgorithm, PublicAlgorithm, SignatureSchemeAlgorithm},
ecc::EccCurve,
+ key_bits::RsaKeyBits,
reserved_handles::Hierarchy,
session_handles::PolicySession,
},
structures::{
+ //RsaScheme, RsaExponent,
Data, Digest, EccPoint, EccScheme, HashScheme, MaxBuffer, PublicBuilder,
PublicEccParametersBuilder, SignatureScheme, SymmetricCipherParameters,
SymmetricDefinition, SymmetricDefinitionObject,
@@ -124,6 +126,8 @@ use tss_esapi::{
};
use std::convert::{TryFrom, TryInto};
+use std::env;
+use std::process::exit;
fn main() {
env_logger::init();
@@ -137,13 +141,26 @@ fn main() {
TctiNameConf::from_environment_variable()
.expect("Failed to get TCTI / TPM2TOOLS_TCTI from environment. Try `export TCTI=device:/dev/tpmrm0`"),
)
- .expect("Failed to create Context");
+ .expect("Failed to create Context");
let mut context_2 = Context::new(
TctiNameConf::from_environment_variable()
.expect("Failed to get TCTI / TPM2TOOLS_TCTI from environment. Try `export TCTI=device:/dev/tpmrm0`"),
)
- .expect("Failed to create Context");
+ .expect("Failed to create Context");
+
+ let mut args = env::args();
+ let _ = args.next(); // eat argv[0], cmd-name.
+
+ let selection = {
+ if let Some(arg1) = args.next() {
+ arg1.parse::().unwrap()
+ } else {
+ 0 // default if no arguments.
+ }
+ };
+
+ println!("Selecting method {}", selection);
// First we need the endorsement key. This is bound to the manufacturer of the TPM
// and will serve as proof that the TPM is trustworthy.
@@ -154,29 +171,37 @@ fn main() {
// Remember, the Hash alg in many cases has to match the key type, especially
// with ecdsa.
- // == RSA
- // let ek_alg = AsymmetricAlgorithmSelection::Rsa(RsaKeyBits::Rsa2048);
- // let hash_alg = HashingAlgorithm::Sha256;
- // let sign_alg = SignatureSchemeAlgorithm::RsaPss;
- // let sig_scheme = SignatureScheme::RsaPss {
- // scheme: HashScheme::new(hash_alg),
- // };
-
- // == ECDSA P384
- let ek_alg = AsymmetricAlgorithmSelection::Ecc(EccCurve::NistP384);
- let hash_alg = HashingAlgorithm::Sha384;
- let sign_alg = SignatureSchemeAlgorithm::EcDsa;
- let sig_scheme = SignatureScheme::EcDsa {
- scheme: HashScheme::new(hash_alg),
+ let (ek_alg, hash_alg, sign_alg, sig_scheme) = match selection {
+ 0 => {
+ // == RSA
+ let hash_alg = HashingAlgorithm::Sha256;
+ (AsymmetricAlgorithmSelection::Rsa(RsaKeyBits::Rsa2048),// ek_alg
+ hash_alg, // hash_alg
+ SignatureSchemeAlgorithm::RsaPss, // sign_alg
+ SignatureScheme::RsaPss { scheme: HashScheme::new(hash_alg) }) // sig_scheme
+ },
+ 1 => {
+ // == ECDSA P384
+ let hash_alg = HashingAlgorithm::Sha256;
+ (AsymmetricAlgorithmSelection::Ecc(EccCurve::NistP384),
+ hash_alg,
+ SignatureSchemeAlgorithm::EcDsa,
+ SignatureScheme::EcDsa { scheme: HashScheme::new(hash_alg) })
+ },
+ 2 => {
+ // == ECDSA P256
+ let hash_alg = HashingAlgorithm::Sha256;
+ (AsymmetricAlgorithmSelection::Ecc(EccCurve::NistP256),
+ hash_alg,
+ SignatureSchemeAlgorithm::EcDsa,
+ SignatureScheme::EcDsa { scheme: HashScheme::new(hash_alg) })
+ },
+ _ => {
+ println!("Select 0 - RSA, 1 - P384, 2 - P256");
+ exit(1);
+ }
};
- // == ECDSA P256
- // let ek_alg = AsymmetricAlgorithmSelection::Ecc(EccCurve::NistP256);
- // let hash_alg = HashingAlgorithm::Sha256;
- // let sign_alg = SignatureSchemeAlgorithm::EcDsa;
- // let sig_scheme = SignatureScheme::EcDsa {
- // scheme: HashScheme::new(hash_alg),
- // };
// If you wish to see the EK cert, you can fetch it's X509 DER here.
let ek_pubcert = retrieve_ek_pubcert(&mut context_1, ek_alg).unwrap();
diff --git a/tss-esapi/src/abstraction/ek.rs b/tss-esapi/src/abstraction/ek.rs
index dcba25ad2..9f1ae7c98 100644
--- a/tss-esapi/src/abstraction/ek.rs
+++ b/tss-esapi/src/abstraction/ek.rs
@@ -1,6 +1,7 @@
// Copyright 2020 Contributors to the Parsec project.
// SPDX-License-Identifier: Apache-2.0
+#[allow(unused_imports)]
use crate::{
abstraction::{nv, AsymmetricAlgorithmSelection, IntoKeyCustomization, KeyCustomization},
attributes::ObjectAttributesBuilder,
@@ -12,12 +13,13 @@ use crate::{
reserved_handles::{Hierarchy, NvAuth},
},
structures::{
- EccParameter, EccPoint, EccScheme, KeyDerivationFunctionScheme, Public, PublicBuilder,
+ Digest, EccParameter, EccPoint, EccScheme, KeyDerivationFunctionScheme, Public, PublicBuilder,
PublicEccParametersBuilder, PublicKeyRsa, PublicRsaParametersBuilder, RsaExponent,
RsaScheme, SymmetricDefinitionObject,
},
Context, Error, Result, WrapperErrorKind,
};
+#[allow(unused_imports)]
use std::convert::TryFrom;
// Source: TCG EK Credential Profile for TPM Family 2.0; Level 0 Version 2.3 Revision 2
// Section 2.2.1.4 (Low Range) for Windows compatibility
@@ -38,22 +40,24 @@ const AUTHPOLICY_A_SHA256: [u8; 32] = [
0x83, 0x71, 0x97, 0x67, 0x44, 0x84, 0xb3, 0xf8, 0x1a, 0x90, 0xcc, 0x8d, 0x46, 0xa5, 0xd7, 0x24,
0xfd, 0x52, 0xd7, 0x6e, 0x06, 0x52, 0x0b, 0x64, 0xf2, 0xa1, 0xda, 0x1b, 0x33, 0x14, 0x69, 0xaa,
];
+#[allow(unused)]
const AUTHPOLICY_B_SHA384: [u8; 48] = [
0xb2, 0x6e, 0x7d, 0x28, 0xd1, 0x1a, 0x50, 0xbc, 0x53, 0xd8, 0x82, 0xbc, 0xf5, 0xfd, 0x3a, 0x1a,
0x07, 0x41, 0x48, 0xbb, 0x35, 0xd3, 0xb4, 0xe4, 0xcb, 0x1c, 0x0a, 0xd9, 0xbd, 0xe4, 0x19, 0xca,
0xcb, 0x47, 0xba, 0x09, 0x69, 0x96, 0x46, 0x15, 0x0f, 0x9f, 0xc0, 0x00, 0xf3, 0xf8, 0x0e, 0x12,
];
+#[allow(unused)]
const AUTHPOLICY_B_SHA512: [u8; 64] = [
0xb8, 0x22, 0x1c, 0xa6, 0x9e, 0x85, 0x50, 0xa4, 0x91, 0x4d, 0xe3, 0xfa, 0xa6, 0xa1, 0x8c, 0x07,
0x2c, 0xc0, 0x12, 0x08, 0x07, 0x3a, 0x92, 0x8d, 0x5d, 0x66, 0xd5, 0x9e, 0xf7, 0x9e, 0x49, 0xa4,
0x29, 0xc4, 0x1a, 0x6b, 0x26, 0x95, 0x71, 0xd5, 0x7e, 0xdb, 0x25, 0xfb, 0xdb, 0x18, 0x38, 0x42,
0x56, 0x08, 0xb4, 0x13, 0xcd, 0x61, 0x6a, 0x5f, 0x6d, 0xb5, 0xb6, 0x07, 0x1a, 0xf9, 0x9b, 0xea,
];
+#[allow(unused)]
const AUTHPOLICY_B_SM3_256: [u8; 32] = [
0x16, 0x78, 0x60, 0xa3, 0x5f, 0x2c, 0x5c, 0x35, 0x67, 0xf9, 0xc9, 0x27, 0xac, 0x56, 0xc0, 0x32,
0xf3, 0xb3, 0xa6, 0x46, 0x2f, 0x8d, 0x03, 0x79, 0x98, 0xe7, 0xa1, 0x0f, 0x77, 0xfa, 0x45, 0x4a,
];
-
/// Get the [`Public`] representing a default Endorsement Key
///
/// **Note**: This only works for key algorithms specified in TCG EK Credential Profile for TPM Family 2.0.
@@ -103,8 +107,8 @@ pub fn create_ek_public_from_default_template(
PublicKeyRsa::new_empty_with_size(RsaKeyBits::Rsa2048),
),
RsaKeyBits::Rsa3072 | RsaKeyBits::Rsa4096 => (
- HashingAlgorithm::Sha384,
- AUTHPOLICY_B_SHA384.into(),
+ HashingAlgorithm::Sha256,
+ AUTHPOLICY_A_SHA256.into(),
SymmetricDefinitionObject::AES_256_CFB,
PublicKeyRsa::new_empty(),
),
@@ -112,6 +116,7 @@ pub fn create_ek_public_from_default_template(
_ => return Err(Error::local_error(WrapperErrorKind::UnsupportedParam)),
};
+
PublicBuilder::new()
.with_public_algorithm(PublicAlgorithm::Rsa)
.with_name_hashing_algorithm(hash_alg)
@@ -139,10 +144,10 @@ pub fn create_ek_public_from_default_template(
32,
),
EccCurve::NistP384 => (
- HashingAlgorithm::Sha384,
- AUTHPOLICY_B_SHA384.into(),
+ HashingAlgorithm::Sha256,
+ AUTHPOLICY_A_SHA256.into(),
SymmetricDefinitionObject::AES_256_CFB,
- 0,
+ 48,
),
EccCurve::NistP521 => (
HashingAlgorithm::Sha512,
@@ -179,7 +184,11 @@ pub fn create_ek_public_from_default_template(
EccParameter::try_from(vec![0u8; xy_size])?,
EccParameter::try_from(vec![0u8; xy_size])?,
))
- }
+ },
+
+ // Other algos are not supported in the spec, so return a error
+ //_ => return Err(Error::local_error(WrapperErrorKind::UnsupportedParam)),
+
};
let key_builder = if let Some(ref k) = key_customization {
diff --git a/tss-esapi/src/abstraction/no_tpm/quote.rs b/tss-esapi/src/abstraction/no_tpm/quote.rs
index 25e9719ea..8d85dfb65 100644
--- a/tss-esapi/src/abstraction/no_tpm/quote.rs
+++ b/tss-esapi/src/abstraction/no_tpm/quote.rs
@@ -222,6 +222,8 @@ fn checkquote_pcr_digests(
/// # },
/// # TctiNameConf,
/// # };
+/// # #[serial_test::file_serial]
+/// # fn main() {
/// # let mut context =
/// # Context::new(
/// # TctiNameConf::from_environment_variable().expect("Failed to get TCTI"),
@@ -293,6 +295,7 @@ fn checkquote_pcr_digests(
/// &qualifying_data
/// )
/// .unwrap();
+/// # }
/// ```
pub fn checkquote(
attest: &Attest,
diff --git a/tss-esapi/src/abstraction/nv.rs b/tss-esapi/src/abstraction/nv.rs
index 01562e688..40f7d46f8 100644
--- a/tss-esapi/src/abstraction/nv.rs
+++ b/tss-esapi/src/abstraction/nv.rs
@@ -7,7 +7,7 @@ use std::{
};
use crate::{
- constants::{tss::*, CapabilityType, PropertyTag},
+ constants::{tss::*, CapabilityType, PropertyTag, PrimitivePropertyTag},
handles::{AuthHandle, NvIndexHandle, NvIndexTpmHandle, TpmHandle},
interface_types::reserved_handles::NvAuth,
structures::{CapabilityData, MaxNvBuffer, Name, NvPublic},
@@ -154,7 +154,7 @@ impl NvOpenOptions {
/// Get the maximum buffer size for an NV space.
pub fn max_nv_buffer_size(ctx: &mut Context) -> Result {
Ok(ctx
- .get_tpm_property(PropertyTag::NvBufferMax)?
+ .get_tpm_property(PropertyTag::PrimitivePropertyTag(PrimitivePropertyTag::NvBufferMax))?
.map(usize::try_from)
.transpose()
.map_err(|_| {
diff --git a/tss-esapi/src/abstraction/pcr.rs b/tss-esapi/src/abstraction/pcr.rs
index 97e856a36..5f8706596 100644
--- a/tss-esapi/src/abstraction/pcr.rs
+++ b/tss-esapi/src/abstraction/pcr.rs
@@ -15,6 +15,8 @@ pub use data::PcrData;
///
/// ```rust
/// # use tss_esapi::{Context, TctiNameConf};
+/// # #[serial_test::file_serial]
+/// # fn main() {
/// # // Create context
/// # let mut context =
/// # Context::new(
@@ -57,6 +59,7 @@ pub use data::PcrData;
/// .expect("Failed to build PcrSelectionList");
/// let _pcr_data = tss_esapi::abstraction::pcr::read_all(&mut context, pcr_selection_list)
/// .expect("pcr::read_all failed");
+/// # }
/// ```
pub fn read_all(
context: &mut Context,
diff --git a/tss-esapi/src/constants/mod.rs b/tss-esapi/src/constants/mod.rs
index f1ada1a78..299fb7096 100644
--- a/tss-esapi/src/constants/mod.rs
+++ b/tss-esapi/src/constants/mod.rs
@@ -64,7 +64,7 @@ pub use command_code::CommandCode;
pub use ecc::EccCurveIdentifier;
pub use nv_index_type::NvIndexType;
pub use pcr_property_tag::PcrPropertyTag;
-pub use property_tag::PropertyTag;
+pub use property_tag::{PropertyTag,PrimitivePropertyTag};
pub use return_code::{
BaseError, ReturnCodeLayer, TpmFormatOneError, TpmFormatZeroError, TpmFormatZeroWarning,
};
diff --git a/tss-esapi/src/constants/property_tag.rs b/tss-esapi/src/constants/property_tag.rs
index ec8eca1da..1321b9afa 100644
--- a/tss-esapi/src/constants/property_tag.rs
+++ b/tss-esapi/src/constants/property_tag.rs
@@ -1,14 +1,13 @@
// Copyright 2020 Contributors to the Parsec project.
// SPDX-License-Identifier: Apache-2.0
-use crate::{constants::tss::*, tss2_esys::TPM2_PT, Error, Result, WrapperErrorKind};
-use log::error;
+use crate::{constants::tss::*, tss2_esys::TPM2_PT, Error, Result};
use num_derive::{FromPrimitive, ToPrimitive};
use num_traits::{FromPrimitive, ToPrimitive};
use std::convert::TryFrom;
#[derive(FromPrimitive, ToPrimitive, Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[repr(u32)]
-pub enum PropertyTag {
+pub enum PrimitivePropertyTag {
None = TPM2_PT_NONE,
// Fixed
FamilyIndicator = TPM2_PT_FAMILY_INDICATOR,
@@ -81,19 +80,29 @@ pub enum PropertyTag {
AuditCounter1 = TPM2_PT_AUDIT_COUNTER_1,
}
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
+pub enum PropertyTag {
+ PrimitivePropertyTag(PrimitivePropertyTag),
+ Other(u32),
+}
+
+
impl From for TPM2_PT {
fn from(property_tag: PropertyTag) -> TPM2_PT {
// The values are well defined so this cannot fail.
- property_tag.to_u32().unwrap()
+ match property_tag {
+ PropertyTag::PrimitivePropertyTag(base) => { base.to_u32().unwrap() },
+ PropertyTag::Other(value) => { value },
+ }
}
}
impl TryFrom for PropertyTag {
type Error = Error;
fn try_from(tpm_pt: TPM2_PT) -> Result {
- PropertyTag::from_u32(tpm_pt).ok_or_else(|| {
- error!("value = {} did not match any PropertyTag.", tpm_pt);
- Error::local_error(WrapperErrorKind::InvalidParam)
- })
+ match PrimitivePropertyTag::from_u32(tpm_pt) {
+ Some(x) => { Ok(PropertyTag::PrimitivePropertyTag(x)) },
+ None => { Ok(PropertyTag::Other(tpm_pt)) },
+ }
}
}
diff --git a/tss-esapi/src/context.rs b/tss-esapi/src/context.rs
index adb26e999..238480250 100644
--- a/tss-esapi/src/context.rs
+++ b/tss-esapi/src/context.rs
@@ -149,6 +149,8 @@ impl Context {
/// # interface_types::algorithm::HashingAlgorithm,
/// # structures::SymmetricDefinition,
/// # };
+ /// # #[serial_test::file_serial]
+ /// # fn main() {
/// # // Create context
/// # let mut context =
/// # Context::new(
@@ -175,6 +177,7 @@ impl Context {
/// # assert_eq!(auth_session, session_1);
/// # assert_eq!(None, session_2);
/// # assert_eq!(None, session_3);
+ /// # }
/// ```
pub fn set_sessions(
&mut self,
@@ -197,6 +200,8 @@ impl Context {
/// ```rust
/// # use tss_esapi::{Context, tcti_ldr::TctiNameConf, interface_types::session_handles::AuthSession};
/// # // Create context
+ /// # #[serial_test::file_serial]
+ /// # fn main() {
/// # let mut context =
/// # Context::new(
/// # TctiNameConf::from_environment_variable().expect("Failed to get TCTI"),
@@ -210,6 +215,7 @@ impl Context {
/// # assert_eq!(None, session_1);
/// # assert_eq!(None, session_2);
/// # assert_eq!(None, session_3);
+ /// # }
/// ```
pub fn clear_sessions(&mut self) {
self.sessions = (None, None, None)
@@ -221,6 +227,8 @@ impl Context {
///
/// ```rust
/// # use tss_esapi::{Context, tcti_ldr::TctiNameConf, interface_types::session_handles::AuthSession};
+ /// # #[serial_test::file_serial]
+ /// # fn main() {
/// # // Create context
/// # let mut context =
/// # Context::new(
@@ -234,6 +242,7 @@ impl Context {
/// assert_eq!(Some(AuthSession::Password), session_1);
/// assert_eq!(None, session_2);
/// assert_eq!(None, session_3);
+ /// # }
/// ```
pub fn sessions(
&self,
@@ -356,17 +365,20 @@ impl Context {
/// # Example
///
/// ```rust
- /// # use tss_esapi::{Context, tcti_ldr::TctiNameConf, constants::PropertyTag};
+ /// # use tss_esapi::{Context, tcti_ldr::TctiNameConf, constants::{PropertyTag,PrimitivePropertyTag}};
/// # use std::str::FromStr;
+ /// # #[serial_test::file_serial]
+ /// # fn main() {
/// # // Create context
/// # let mut context =
/// # Context::new(
/// # TctiNameConf::from_environment_variable().expect("Failed to get TCTI"),
/// # ).expect("Failed to create Context");
/// let rev = context
- /// .get_tpm_property(PropertyTag::Revision)
+ /// .get_tpm_property(PropertyTag::PrimitivePropertyTag(PrimitivePropertyTag::Revision))
/// .expect("Wrong value from TPM")
/// .expect("Value is not supported");
+ /// # }
/// ```
pub fn get_tpm_property(&mut self, property: PropertyTag) -> Result