Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions tss-esapi/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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 = "*"
env_logger = "0.11.5"
serde_json = "^1.0.108"
sha2 = { version = "0.10.8", features = ["oid"] }
Expand Down
21 changes: 17 additions & 4 deletions tss-esapi/build.rs
Original file line number Diff line number Diff line change
@@ -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)");
Expand All @@ -13,22 +14,34 @@ fn main() {

// If documentation for Docs.rs is being built then the version is set
// to the minimum supported tpm2-tss version.
let tss_version = if std::env::var("DOCS_RS").is_ok() {
let mut tss_version = if std::env::var("DOCS_RS").is_ok() {
TPM2_TSS_MINIMUM_VERSION
} else {
let tss_version_string = std::env::var("DEP_TSS2_ESYS_VERSION")
.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")
};

// nuke any prerelease info, which probably is just a git repo/dirty flag
// like: 4.0.1-67-gb7bad346
tss_version.pre = Prerelease::EMPTY;
//eprintln!("tss version: {} / {:?}", tss_version_string, tss_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();
Expand Down
71 changes: 48 additions & 23 deletions tss-esapi/examples/certify.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -124,6 +126,8 @@ use tss_esapi::{
};

use std::convert::{TryFrom, TryInto};
use std::env;
use std::process::exit;

fn main() {
env_logger::init();
Expand All @@ -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::<i32>().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.
Expand All @@ -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();
Expand Down
25 changes: 19 additions & 6 deletions tss-esapi/src/abstraction/ek.rs
Original file line number Diff line number Diff line change
@@ -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,
Expand All @@ -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
Expand All @@ -38,28 +40,34 @@ 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.
///
/// Source: TCG EK Credential Profile for TPM Family 2.0; Level 0 Version 2.3 Revision 2
/// Appendix B.3.3 and B.3.4
///
/// for an example of IntoKeyCusomization usage,
/// see test_create_custom_ak() in tests/integration_tests/abstraction_tests/ak_tests.rs
///
pub fn create_ek_public_from_default_template<IKC: IntoKeyCustomization>(
alg: AsymmetricAlgorithmSelection,
key_customization: IKC,
Expand Down Expand Up @@ -112,6 +120,7 @@ pub fn create_ek_public_from_default_template<IKC: IntoKeyCustomization>(
_ => return Err(Error::local_error(WrapperErrorKind::UnsupportedParam)),
};


PublicBuilder::new()
.with_public_algorithm(PublicAlgorithm::Rsa)
.with_name_hashing_algorithm(hash_alg)
Expand Down Expand Up @@ -139,10 +148,10 @@ pub fn create_ek_public_from_default_template<IKC: IntoKeyCustomization>(
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,
Expand Down Expand Up @@ -179,7 +188,11 @@ pub fn create_ek_public_from_default_template<IKC: IntoKeyCustomization>(
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 {
Expand Down
2 changes: 2 additions & 0 deletions tss-esapi/src/abstraction/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ use crate::{
};

/// KeyCustomizaion allows to adjust how a key is going to be created
/// for an example of IntoKeyCusomization usage,
/// see test_create_custom_ak() in tests/integration_tests/abstraction_tests/ak_tests.rs
pub trait KeyCustomization {
/// Alter the attributes used on key creation
fn attributes(&self, attributes_builder: ObjectAttributesBuilder) -> ObjectAttributesBuilder {
Expand Down
4 changes: 2 additions & 2 deletions tss-esapi/src/abstraction/nv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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},
Expand Down Expand Up @@ -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<usize> {
Ok(ctx
.get_tpm_property(PropertyTag::NvBufferMax)?
.get_tpm_property(PropertyTag::PrimitivePropertyTag(PrimitivePropertyTag::NvBufferMax))?
.map(usize::try_from)
.transpose()
.map_err(|_| {
Expand Down
2 changes: 1 addition & 1 deletion tss-esapi/src/constants/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
};
Expand Down
25 changes: 17 additions & 8 deletions tss-esapi/src/constants/property_tag.rs
Original file line number Diff line number Diff line change
@@ -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,
Expand Down Expand Up @@ -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<PropertyTag> 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<TPM2_PT> for PropertyTag {
type Error = Error;
fn try_from(tpm_pt: TPM2_PT) -> Result<PropertyTag> {
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)) },
}
}
}
1 change: 1 addition & 0 deletions tss-esapi/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
missing_copy_implementations,
rustdoc::broken_intra_doc_links,
)]
#![feature(stmt_expr_attributes)]

//! # TSS 2.0 Rust Wrapper over Enhanced System API
//! This crate exposes the functionality of the TCG Software Stack Enhanced System API to
Expand Down
10 changes: 5 additions & 5 deletions tss-esapi/src/utils/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
//! type name. Unions are converted to Rust `enum`s by dropping the `TPMU` qualifier and appending
//! `Union`.
use crate::attributes::ObjectAttributesBuilder;
use crate::constants::PropertyTag;
use crate::constants::{PropertyTag,PrimitivePropertyTag};
use crate::interface_types::{
algorithm::{HashingAlgorithm, PublicAlgorithm},
ecc::EccCurve,
Expand Down Expand Up @@ -248,10 +248,10 @@ fn tpm_int_to_string(num: u32) -> String {
pub fn get_tpm_vendor(context: &mut Context) -> Result<String> {
// Retrieve the TPM property values
Ok([
PropertyTag::VendorString1,
PropertyTag::VendorString2,
PropertyTag::VendorString3,
PropertyTag::VendorString4,
PropertyTag::PrimitivePropertyTag(PrimitivePropertyTag::VendorString1),
PropertyTag::PrimitivePropertyTag(PrimitivePropertyTag::VendorString2),
PropertyTag::PrimitivePropertyTag(PrimitivePropertyTag::VendorString3),
PropertyTag::PrimitivePropertyTag(PrimitivePropertyTag::VendorString4),
]
.iter()
// Retrieve property values
Expand Down
Loading