Last active
October 12, 2023 06:22
-
-
Save THS-on/c24764c306d11c3da9469d94bb9a48bb to your computer and use it in GitHub Desktop.
Example on how to protect a key using pcr policy using TSS rust bindings
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use std::str::FromStr; | |
pub use tss_esapi::Error; | |
use tss_esapi::{ | |
attributes::ObjectAttributesBuilder, | |
handles::PcrHandle, | |
interface_types::{ | |
algorithm::{PublicAlgorithm, SymmetricMode}, | |
ecc::EccCurve, | |
key_bits::AesKeyBits, | |
resource_handles::Hierarchy, | |
session_handles::AuthSession, | |
}, | |
structures::{ | |
CreateKeyResult, CreatePrimaryKeyResult, Digest, DigestValues, EccPoint, EccScheme, | |
HashScheme, KeyDerivationFunctionScheme, MaxBuffer, PcrSelectionListBuilder, PublicBuilder, | |
PublicEccParametersBuilder, SignatureScheme, SymmetricDefinitionObject, | |
}, | |
tcti_ldr::DeviceConfig, | |
}; | |
use tss_esapi::{ | |
constants::SessionType, | |
interface_types::algorithm::HashingAlgorithm, | |
structures::{PcrSlot, SymmetricDefinition}, | |
Context, TctiNameConf, | |
}; | |
fn create_primary(context: &mut Context) -> Result<CreatePrimaryKeyResult, Error> { | |
let ecc_params = PublicEccParametersBuilder::new() | |
.with_ecc_scheme(EccScheme::Null) | |
.with_curve(EccCurve::NistP256) | |
.with_is_decryption_key(true) | |
.with_restricted(true) | |
.with_symmetric(SymmetricDefinitionObject::Aes { | |
key_bits: AesKeyBits::Aes128, | |
mode: SymmetricMode::Cfb, | |
}) | |
.with_key_derivation_function_scheme(KeyDerivationFunctionScheme::Null) | |
.build()?; | |
let primary_object_attributes = ObjectAttributesBuilder::new() | |
.with_fixed_tpm(true) | |
.with_fixed_parent(true) | |
.with_sensitive_data_origin(true) | |
.with_user_with_auth(true) | |
.with_restricted(true) | |
.with_decrypt(true) | |
.build()?; | |
let primary_public = PublicBuilder::new() | |
.with_public_algorithm(PublicAlgorithm::Ecc) | |
.with_name_hashing_algorithm(HashingAlgorithm::Sha256) | |
.with_object_attributes(primary_object_attributes) | |
.with_ecc_parameters(ecc_params) | |
.with_ecc_unique_identifier(EccPoint::default()) | |
.build()?; | |
context.execute_with_nullauth_session(|ctx| { | |
ctx.create_primary( | |
Hierarchy::Endorsement, | |
primary_public.clone(), | |
None, | |
None, | |
None, | |
None, | |
) | |
}) | |
} | |
fn create_policy(context: &mut Context) -> Result<AuthSession, Error> { | |
let session = context | |
.start_auth_session( | |
None, | |
None, | |
None, | |
SessionType::Policy, | |
SymmetricDefinition::AES_128_CFB, | |
HashingAlgorithm::Sha256, | |
)? | |
.unwrap(); | |
let pcr_selection_list = PcrSelectionListBuilder::new() | |
.with_selection(HashingAlgorithm::Sha256, vec![PcrSlot::Slot7].as_slice()) | |
.build()?; | |
let (_update_counter, pcr_sel, pcr_data) = | |
context.execute_without_session(|ctx| ctx.pcr_read(pcr_selection_list))?; | |
let concatenated_pcr_values = pcr_data | |
.value() | |
.iter() | |
.map(|x| x.value()) | |
.collect::<Vec<&[u8]>>() | |
.concat(); | |
let concatenated_pcr_values = MaxBuffer::try_from(concatenated_pcr_values)?; | |
let (hashed_data, _ticket) = context.execute_without_session(|ctx| { | |
ctx.hash( | |
concatenated_pcr_values, | |
HashingAlgorithm::Sha256, | |
Hierarchy::Endorsement, | |
) | |
})?; | |
context.policy_pcr(session.try_into()?, hashed_data.clone(), pcr_sel.clone())?; | |
Ok(session) | |
} | |
fn create_key_with_policy( | |
context: &mut Context, | |
policy: Digest, | |
primary: &CreatePrimaryKeyResult, | |
) -> Result<CreateKeyResult, Error> { | |
let ecc_params = PublicEccParametersBuilder::new() | |
.with_ecc_scheme(EccScheme::Null) | |
.with_curve(EccCurve::NistP256) | |
.with_restricted(true) | |
.with_symmetric(SymmetricDefinitionObject::Null) | |
.with_key_derivation_function_scheme(KeyDerivationFunctionScheme::Null) | |
.build()?; | |
let key_object_attributes = ObjectAttributesBuilder::new() | |
.with_fixed_tpm(true) | |
.with_fixed_parent(true) | |
.with_sensitive_data_origin(true) | |
.with_decrypt(true) | |
.with_sign_encrypt(true) | |
.build()?; | |
let key_public = PublicBuilder::new() | |
.with_public_algorithm(PublicAlgorithm::Ecc) | |
.with_name_hashing_algorithm(HashingAlgorithm::Sha256) | |
.with_object_attributes(key_object_attributes) | |
.with_ecc_parameters(ecc_params) | |
.with_ecc_unique_identifier(EccPoint::default()) | |
.with_auth_policy(policy) | |
.build()?; | |
context.execute_with_nullauth_session(|ctx| { | |
ctx.create(primary.key_handle, key_public, None, None, None, None) | |
}) | |
} | |
fn extend_pcr7(context: &mut Context) -> Result<(), Error> { | |
let mut digests = DigestValues::new(); | |
let data = MaxBuffer::try_from(vec![0])?; | |
let (digest, _) = context.execute_without_session(|ctx| { | |
ctx.hash(data, HashingAlgorithm::Sha256, Hierarchy::Endorsement) | |
})?; | |
digests.set(HashingAlgorithm::Sha256, digest); | |
context.execute_with_nullauth_session(|ctx| ctx.pcr_extend(PcrHandle::Pcr7, digests)) | |
} | |
fn run() -> Result<(), Error> { | |
let device = TctiNameConf::Device(DeviceConfig::from_str("/dev/tpmrm0")?); | |
let mut context = Context::new(device)?; | |
let primary = create_primary(&mut context)?; | |
println!("Created primary key"); | |
let session = create_policy(&mut context)?; | |
let session_digest = context.policy_get_digest(session.try_into()?)?; | |
println!("Created session digest for policy"); | |
let key: CreateKeyResult = create_key_with_policy(&mut context, session_digest, &primary)?; | |
println!("Created Key"); | |
let key_handle = context.execute_with_nullauth_session(|ctx| { | |
ctx.load(primary.key_handle, key.out_private, key.out_public) | |
})?; | |
println!("Loaded key"); | |
// Create digest to sign | |
let data = MaxBuffer::try_from(vec![0])?; | |
let (digest, ticket) = context.execute_without_session(|ctx| { | |
ctx.hash(data, HashingAlgorithm::Sha256, Hierarchy::Endorsement) | |
})?; | |
println!("Hashed data"); | |
// Create fresh session | |
let session = create_policy(&mut context)?; | |
// Uncomment to check if the policy actually works | |
//extend_pcr7(&mut context)?; | |
let signature = context.execute_with_session(Some(session), |ctx| { | |
ctx.sign( | |
key_handle, | |
digest, | |
SignatureScheme::EcDsa { | |
hash_scheme: HashScheme::new(HashingAlgorithm::Sha256), | |
}, | |
ticket, | |
) | |
})?; | |
println!("Generated signature"); | |
println!("Signature {:?}", signature); | |
Ok(()) | |
} | |
fn main() { | |
let res = run(); | |
match res { | |
Ok(_) => {} | |
Err(e) => { | |
println!("{}\n\n", e); | |
Err::<(), tss_esapi::Error>(e).unwrap(); | |
} | |
}; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment