Rebase on tss-esapi 4.0.10-alpha and tpm2-policy 0.3.0

Signed-off-by: Patrick Uiterwijk <patrick@puiterwijk.org>
This commit is contained in:
Patrick Uiterwijk 2020-12-03 13:49:41 +00:00
parent 14d91c28d1
commit ec1770cdb5
4 changed files with 61 additions and 104 deletions

View file

@ -10,10 +10,10 @@ license = "EUPL-1.2"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies] [dependencies]
tss-esapi = "4.0.6-alpha.1" tss-esapi = "4.0.10-alpha.1"
serde = "1.0" serde = "1.0"
biscuit = "0.5.0-beta2" biscuit = "0.5.0-beta2"
serde_json = "1.0" serde_json = "1.0"
base64 = "0.12.1" base64 = "0.12.1"
atty = "0.2.14" atty = "0.2.14"
tpm2-policy = "0.2.0" tpm2-policy = "0.3.0"

View file

@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
use std::convert::TryFrom; use std::convert::{TryFrom, TryInto};
use std::error::Error; use std::error::Error;
use std::fmt; use std::fmt;
@ -39,7 +39,7 @@ mod utils;
use cli::TPM2Config; use cli::TPM2Config;
use tss_esapi::algorithm::structures::SensitiveData; use tss_esapi::structures::{PcrSelectionListBuilder, SensitiveData};
#[derive(Debug)] #[derive(Debug)]
enum PinError { enum PinError {
@ -161,7 +161,7 @@ fn perform_encrypt(cfg: TPM2Config, input: &str) -> Result<(), PinError> {
_ => "tpm2plus", _ => "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 = ctx.get_random(32)?;
let key_bytes: &[u8] = key_bytes.value(); 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 public = tpm_objects::create_tpm2b_public_sealed_object(policy_digest)?;
let jwk_str = SensitiveData::try_from(jwk_str.as_bytes().to_vec())?; let jwk_str = SensitiveData::try_from(jwk_str.as_bytes().to_vec())?;
let (jwk_priv, jwk_pub) = let jwk_result = ctx.execute_with_nullauth_session(|ctx| {
ctx.create_key(key_handle, &public, None, Some(&jwk_str), None, &[])?; 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<ClevisHeader> = biscuit::jwe::Header { let hdr: biscuit::jwe::Header<ClevisHeader> = biscuit::jwe::Header {
registered: biscuit::jwe::RegisteredHeader { registered: biscuit::jwe::RegisteredHeader {
@ -350,12 +358,12 @@ fn perform_decrypt(input: &str) -> Result<(), PinError> {
let mut ctx = utils::get_tpm2_ctx()?; let mut ctx = utils::get_tpm2_ctx()?;
let key_handle = utils::get_tpm2_primary_key(&mut ctx, &key_public)?; 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 =
let key = ctx.load(key_handle, jwkpriv, jwkpub)?; 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 = &unsealed.value();
let unsealed = std::str::from_utf8(unsealed)?; let unsealed = std::str::from_utf8(unsealed)?;
let jwk: biscuit::jwk::JWK<biscuit::Empty> = serde_json::from_str(unsealed)?; let jwk: biscuit::jwk::JWK<biscuit::Empty> = serde_json::from_str(unsealed)?;

View file

@ -1,11 +1,12 @@
use std::env;
use std::fs; use std::fs;
use std::str::FromStr; use std::str::FromStr;
use tss_esapi::constants::algorithm::HashingAlgorithm; use tss_esapi::{
use tss_esapi::constants::tss as tss_constants; constants::algorithm::HashingAlgorithm, handles::KeyHandle,
use tss_esapi::tss2_esys::{ESYS_TR, ESYS_TR_NONE, ESYS_TR_RH_OWNER}; interface_types::resource_handles::Hierarchy, structures::PcrSelectionListBuilder, Context,
use tss_esapi::Context; Tcti,
use tss_esapi::Tcti; };
use serde::Deserialize; use serde::Deserialize;
@ -77,87 +78,35 @@ where
} }
pub(crate) fn get_tpm2_ctx() -> Result<tss_esapi::Context, tss_esapi::Error> { pub(crate) fn get_tpm2_ctx() -> Result<tss_esapi::Context, tss_esapi::Error> {
let tcti_path = if std::path::Path::new("/dev/tpmrm0").exists() { let tcti_path = match env::var("TCTI") {
"device:/dev/tpmrm0" Ok(val) => val,
} else { Err(_) => {
"device:/dev/tpm0" 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) } unsafe { Context::new(tcti) }
} }
pub(crate) fn perform_with_other_sessions<T, E, F>(
ctx: &mut Context,
sestype: tss_esapi::tss2_esys::TPM2_SE,
f: F,
) -> Result<T, E>
where
F: Fn(&mut Context) -> Result<T, E>,
E: From<tss_esapi::Error> + From<PinError>,
{
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( pub(crate) fn get_tpm2_primary_key(
ctx: &mut Context, ctx: &mut Context,
pub_template: &tss_esapi::tss2_esys::TPM2B_PUBLIC, pub_template: &tss_esapi::tss2_esys::TPM2B_PUBLIC,
) -> Result<ESYS_TR, PinError> { ) -> Result<KeyHandle, PinError> {
perform_with_other_sessions(ctx, tss_constants::TPM2_SE_HMAC, |ctx| { ctx.execute_with_nullauth_session(|ctx| {
ctx.create_primary_key(ESYS_TR_RH_OWNER, pub_template, None, None, None, &[]) ctx.create_primary_key(
.map_err(|e| e.into()) Hierarchy::Owner,
}) pub_template,
} None,
None,
pub(crate) fn create_and_set_tpm2_session( None,
ctx: &mut tss_esapi::Context, PcrSelectionListBuilder::new().build(),
session_type: tss_esapi::tss2_esys::TPM2_SE, )
) -> Result<ESYS_TR, PinError> { .map(|r| r.key_handle)
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<tss_esapi::tss2_esys::TPMT_SYM_DEF, PinError> {
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,
},
}) })
.map_err(|e| e.into())
} }

View file

@ -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) 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 # This tests we can handle the extra argument (either empty string or -y) from Clevis v15
# https://github.com/latchset/clevis/commit/36fae7c2dbf030d6c74abaed945db7bf3c25d054 # 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, 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 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 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 (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 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 (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" | ./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 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 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" | ./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 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 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" | ./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 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 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) # Negative test (PCR change)
token=$(echo Failed | ./target/debug/clevis-pin-tpm2 encrypt '{"pcr_ids":[23]}') token=$(echo Failed | ./target/debug/clevis-pin-tpm2 encrypt '{"pcr_ids":[23]}')