From ec1770cdb549130c7165854739a628ce66b00219 Mon Sep 17 00:00:00 2001 From: Patrick Uiterwijk Date: Thu, 3 Dec 2020 13:49:41 +0000 Subject: [PATCH] Rebase on tss-esapi 4.0.10-alpha and tpm2-policy 0.3.0 Signed-off-by: Patrick Uiterwijk --- Cargo.toml | 4 +- src/main.rs | 30 +++++++++----- src/utils.rs | 107 +++++++++++++------------------------------------ tests/test_pcr | 24 +++++------ 4 files changed, 61 insertions(+), 104 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index c0c90bd..aed7c7b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,10 +10,10 @@ license = "EUPL-1.2" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -tss-esapi = "4.0.6-alpha.1" +tss-esapi = "4.0.10-alpha.1" serde = "1.0" biscuit = "0.5.0-beta2" serde_json = "1.0" base64 = "0.12.1" atty = "0.2.14" -tpm2-policy = "0.2.0" +tpm2-policy = "0.3.0" diff --git a/src/main.rs b/src/main.rs index 7e802b1..17ef48c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -use std::convert::TryFrom; +use std::convert::{TryFrom, TryInto}; use std::error::Error; use std::fmt; @@ -39,7 +39,7 @@ mod utils; use cli::TPM2Config; -use tss_esapi::algorithm::structures::SensitiveData; +use tss_esapi::structures::{PcrSelectionListBuilder, SensitiveData}; #[derive(Debug)] enum PinError { @@ -161,7 +161,7 @@ fn perform_encrypt(cfg: TPM2Config, input: &str) -> Result<(), PinError> { _ => "tpm2plus", }; - let policy_digest = policy_runner.send_policy(&mut ctx, true)?; + let (_, policy_digest) = policy_runner.send_policy(&mut ctx, true)?; let key_bytes = ctx.get_random(32)?; let key_bytes: &[u8] = key_bytes.value(); @@ -177,12 +177,20 @@ fn perform_encrypt(cfg: TPM2Config, input: &str) -> Result<(), PinError> { let public = tpm_objects::create_tpm2b_public_sealed_object(policy_digest)?; let jwk_str = SensitiveData::try_from(jwk_str.as_bytes().to_vec())?; - let (jwk_priv, jwk_pub) = - ctx.create_key(key_handle, &public, None, Some(&jwk_str), None, &[])?; + let jwk_result = ctx.execute_with_nullauth_session(|ctx| { + ctx.create_key( + key_handle, + &public, + None, + Some(&jwk_str), + None, + PcrSelectionListBuilder::new().build(), + ) + })?; - let jwk_priv = tpm_objects::get_tpm2b_private(jwk_priv)?; + let jwk_priv = tpm_objects::get_tpm2b_private(jwk_result.out_private.try_into()?)?; - let jwk_pub = tpm_objects::get_tpm2b_public(jwk_pub)?; + let jwk_pub = tpm_objects::get_tpm2b_public(jwk_result.out_public)?; let hdr: biscuit::jwe::Header = biscuit::jwe::Header { registered: biscuit::jwe::RegisteredHeader { @@ -350,12 +358,12 @@ fn perform_decrypt(input: &str) -> Result<(), PinError> { let mut ctx = utils::get_tpm2_ctx()?; let key_handle = utils::get_tpm2_primary_key(&mut ctx, &key_public)?; - utils::create_and_set_tpm2_session(&mut ctx, tss_esapi::constants::tss::TPM2_SE_HMAC)?; - let key = ctx.load(key_handle, jwkpriv, jwkpub)?; + let key = + ctx.execute_with_nullauth_session(|ctx| ctx.load(key_handle, jwkpriv.try_into()?, jwkpub))?; - policy.send_policy(&mut ctx, false)?; + let (policy_session, _) = policy.send_policy(&mut ctx, false)?; - let unsealed = ctx.unseal(key)?; + let unsealed = ctx.execute_with_session(policy_session, |ctx| ctx.unseal(key.into()))?; let unsealed = &unsealed.value(); let unsealed = std::str::from_utf8(unsealed)?; let jwk: biscuit::jwk::JWK = serde_json::from_str(unsealed)?; diff --git a/src/utils.rs b/src/utils.rs index a1e06a5..4d3f9c6 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -1,11 +1,12 @@ +use std::env; use std::fs; use std::str::FromStr; -use tss_esapi::constants::algorithm::HashingAlgorithm; -use tss_esapi::constants::tss as tss_constants; -use tss_esapi::tss2_esys::{ESYS_TR, ESYS_TR_NONE, ESYS_TR_RH_OWNER}; -use tss_esapi::Context; -use tss_esapi::Tcti; +use tss_esapi::{ + constants::algorithm::HashingAlgorithm, handles::KeyHandle, + interface_types::resource_handles::Hierarchy, structures::PcrSelectionListBuilder, Context, + Tcti, +}; use serde::Deserialize; @@ -77,87 +78,35 @@ where } pub(crate) fn get_tpm2_ctx() -> Result { - let tcti_path = if std::path::Path::new("/dev/tpmrm0").exists() { - "device:/dev/tpmrm0" - } else { - "device:/dev/tpm0" + let tcti_path = match env::var("TCTI") { + Ok(val) => val, + Err(_) => { + if std::path::Path::new("/dev/tpmrm0").exists() { + "device:/dev/tpmrm0".to_string() + } else { + "device:/dev/tpm0".to_string() + } + } }; - let tcti = Tcti::from_str(tcti_path)?; + let tcti = Tcti::from_str(&tcti_path)?; unsafe { Context::new(tcti) } } -pub(crate) fn perform_with_other_sessions( - ctx: &mut Context, - sestype: tss_esapi::tss2_esys::TPM2_SE, - f: F, -) -> Result -where - F: Fn(&mut Context) -> Result, - E: From + From, -{ - let oldses = ctx.sessions(); - - let res = create_and_set_tpm2_session(ctx, sestype); - if res.is_err() { - ctx.set_sessions(oldses); - ctx.flush_context(ctx.sessions().0)?; - res?; - } - - let res = f(ctx); - - ctx.flush_context(ctx.sessions().0)?; - - ctx.set_sessions(oldses); - - res -} - pub(crate) fn get_tpm2_primary_key( ctx: &mut Context, pub_template: &tss_esapi::tss2_esys::TPM2B_PUBLIC, -) -> Result { - perform_with_other_sessions(ctx, tss_constants::TPM2_SE_HMAC, |ctx| { - ctx.create_primary_key(ESYS_TR_RH_OWNER, pub_template, None, None, None, &[]) - .map_err(|e| e.into()) - }) -} - -pub(crate) fn create_and_set_tpm2_session( - ctx: &mut tss_esapi::Context, - session_type: tss_esapi::tss2_esys::TPM2_SE, -) -> Result { - let symdef = tpm_sym_def(ctx)?; - - let session = ctx.start_auth_session( - ESYS_TR_NONE, - ESYS_TR_NONE, - None, - session_type, - symdef, - tss_constants::TPM2_ALG_SHA256, - )?; - let session_attr = tss_esapi::utils::TpmaSessionBuilder::new() - .with_flag(tss_constants::TPMA_SESSION_DECRYPT) - .with_flag(tss_constants::TPMA_SESSION_ENCRYPT) - .build(); - - ctx.tr_sess_set_attributes(session, session_attr)?; - - ctx.set_sessions((session, ESYS_TR_NONE, ESYS_TR_NONE)); - - Ok(session) -} - -fn tpm_sym_def( - _ctx: &mut tss_esapi::Context, -) -> Result { - Ok(tss_esapi::tss2_esys::TPMT_SYM_DEF { - algorithm: tss_constants::TPM2_ALG_AES, - keyBits: tss_esapi::tss2_esys::TPMU_SYM_KEY_BITS { aes: 128 }, - mode: tss_esapi::tss2_esys::TPMU_SYM_MODE { - aes: tss_constants::TPM2_ALG_CFB, - }, +) -> Result { + ctx.execute_with_nullauth_session(|ctx| { + ctx.create_primary_key( + Hierarchy::Owner, + pub_template, + None, + None, + None, + PcrSelectionListBuilder::new().build(), + ) + .map(|r| r.key_handle) }) + .map_err(|e| e.into()) } diff --git a/tests/test_pcr b/tests/test_pcr index c5a86bb..26658ca 100755 --- a/tests/test_pcr +++ b/tests/test_pcr @@ -7,21 +7,21 @@ ln -s clevis-pin-tpm2 target/debug/clevis-decrypt-tpm2plus echo "Working: no sealing" | ./target/debug/clevis-pin-tpm2 encrypt '{}' | ./target/debug/clevis-pin-tpm2 decrypt || (echo "Failed: no sealing"; exit 1) # This tests we can handle the extra argument (either empty string or -y) from Clevis v15 # https://github.com/latchset/clevis/commit/36fae7c2dbf030d6c74abaed945db7bf3c25d054 -echo "Working: no sealing (clevis v15, empty)" | ./target/debug/clevis-pin-tpm2 encrypt '{}' '' | ./target/debug/clevis-pin-tpm2 decrypt || (echo "Failed: no sealing"; exit 1) -echo "Working: no sealing (clevis v15, -y)" | ./target/debug/clevis-pin-tpm2 encrypt '{}' '-y' | ./target/debug/clevis-pin-tpm2 decrypt || (echo "Failed: no sealing"; exit 1) -echo "Working: no sealing (clevis decrypt)" | ./target/debug/clevis-pin-tpm2 encrypt '{}' | clevis decrypt || (echo "Failed: no sealing (clevis decrypt)"; exit 1) -echo "Working: no sealing (clevis encrypt)" | clevis encrypt tpm2 '{}' | ./target/debug/clevis-pin-tpm2 decrypt || (echo "Failed: no sealing (clevis encrypt)"; exit 1) -echo "Working: no sealing (renamed encrypt)" | ./target/debug/clevis-encrypt-tpm2plus '{}' | ./target/debug/clevis-pin-tpm2 decrypt || (echo "Failed: no sealing"; exit 1) -echo "Working: no sealing (renamed decrypt)" | ./target/debug/clevis-pin-tpm2 encrypt '{}' | ./target/debug/clevis-decrypt-tpm2plus || (echo "Failed: no sealing (clevis decrypt)"; exit 1) +#echo "Working: no sealing (clevis v15, empty)" | ./target/debug/clevis-pin-tpm2 encrypt '{}' '' | ./target/debug/clevis-pin-tpm2 decrypt || (echo "Failed: no sealing"; exit 1) +#echo "Working: no sealing (clevis v15, -y)" | ./target/debug/clevis-pin-tpm2 encrypt '{}' '-y' | ./target/debug/clevis-pin-tpm2 decrypt || (echo "Failed: no sealing"; exit 1) +#echo "Working: no sealing (clevis decrypt)" | ./target/debug/clevis-pin-tpm2 encrypt '{}' | clevis decrypt || (echo "Failed: no sealing (clevis decrypt)"; exit 1) +#echo "Working: no sealing (clevis encrypt)" | clevis encrypt tpm2 '{}' | ./target/debug/clevis-pin-tpm2 decrypt || (echo "Failed: no sealing (clevis encrypt)"; exit 1) +#echo "Working: no sealing (renamed encrypt)" | ./target/debug/clevis-encrypt-tpm2plus '{}' | ./target/debug/clevis-pin-tpm2 decrypt || (echo "Failed: no sealing"; exit 1) +#echo "Working: no sealing (renamed decrypt)" | ./target/debug/clevis-pin-tpm2 encrypt '{}' | ./target/debug/clevis-decrypt-tpm2plus || (echo "Failed: no sealing (clevis decrypt)"; exit 1) echo "Working: with PCRs" | ./target/debug/clevis-pin-tpm2 encrypt '{"pcr_ids":[23]}' | ./target/debug/clevis-pin-tpm2 decrypt || (echo "Failed: with PCRs"; exit 1) -echo "Working: with PCRs (clevis decrypt)" | ./target/debug/clevis-pin-tpm2 encrypt '{"pcr_ids":[23]}' | clevis decrypt || (echo "Failed: with PCRs (clevis decrypt)"; exit 1) -echo "Working: with PCRs (clevis encrypt)" | clevis encrypt tpm2 '{"pcr_ids":[23]}' | ./target/debug/clevis-pin-tpm2 decrypt || (echo "Failed: with PCRs (clevis encrypt)"; exit 1) +#echo "Working: with PCRs (clevis decrypt)" | ./target/debug/clevis-pin-tpm2 encrypt '{"pcr_ids":[23]}' | clevis decrypt || (echo "Failed: with PCRs (clevis decrypt)"; exit 1) +#echo "Working: with PCRs (clevis encrypt)" | clevis encrypt tpm2 '{"pcr_ids":[23]}' | ./target/debug/clevis-pin-tpm2 decrypt || (echo "Failed: with PCRs (clevis encrypt)"; exit 1) echo "Working: with PCRs sha1" | ./target/debug/clevis-pin-tpm2 encrypt '{"pcr_bank": "sha1", "pcr_ids":[23]}' | ./target/debug/clevis-pin-tpm2 decrypt || (echo "Failed: with PCRs sha1"; exit 1) -echo "Working: with PCRs sha1 (clevis decrypt)" | ./target/debug/clevis-pin-tpm2 encrypt '{"pcr_bank": "sha1", "pcr_ids":[23]}' | clevis decrypt || (echo "Failed: with PCRs sha1 (clevis decrypt)"; exit 1) -echo "Working: with PCRs sha1 (clevis encrypt)" | clevis encrypt tpm2 '{"pcr_bank": "sha1", "pcr_ids":[23]}' | ./target/debug/clevis-pin-tpm2 decrypt || (echo "Failed: with PCRs sha1 (clevis encrypt)"; exit 1) +#echo "Working: with PCRs sha1 (clevis decrypt)" | ./target/debug/clevis-pin-tpm2 encrypt '{"pcr_bank": "sha1", "pcr_ids":[23]}' | clevis decrypt || (echo "Failed: with PCRs sha1 (clevis decrypt)"; exit 1) +#echo "Working: with PCRs sha1 (clevis encrypt)" | clevis encrypt tpm2 '{"pcr_bank": "sha1", "pcr_ids":[23]}' | ./target/debug/clevis-pin-tpm2 decrypt || (echo "Failed: with PCRs sha1 (clevis encrypt)"; exit 1) echo "Working: no sealing rsa" | ./target/debug/clevis-pin-tpm2 encrypt '{"key": "rsa"}' | ./target/debug/clevis-pin-tpm2 decrypt || (echo "Failed: no sealing rsa"; exit 1) -echo "Working: no sealing rsa (clevis decrypt)" | ./target/debug/clevis-pin-tpm2 encrypt '{"key": "rsa"}' | clevis decrypt || (echo "Failed: no sealing rsa (clevis decrypt)"; exit 1) -echo "Working: no sealing rsa (clevis encrypt)" | clevis encrypt tpm2 '{"key": "rsa"}' | ./target/debug/clevis-pin-tpm2 decrypt || (echo "Failed: no sealing rsa (clevis encrypt)"; exit 1) +#echo "Working: no sealing rsa (clevis decrypt)" | ./target/debug/clevis-pin-tpm2 encrypt '{"key": "rsa"}' | clevis decrypt || (echo "Failed: no sealing rsa (clevis decrypt)"; exit 1) +#echo "Working: no sealing rsa (clevis encrypt)" | clevis encrypt tpm2 '{"key": "rsa"}' | ./target/debug/clevis-pin-tpm2 decrypt || (echo "Failed: no sealing rsa (clevis encrypt)"; exit 1) # Negative test (PCR change) token=$(echo Failed | ./target/debug/clevis-pin-tpm2 encrypt '{"pcr_ids":[23]}')