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
[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"

View file

@ -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<ClevisHeader> = 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<biscuit::Empty> = serde_json::from_str(unsealed)?;

View file

@ -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<tss_esapi::Context, tss_esapi::Error> {
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<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(
ctx: &mut Context,
pub_template: &tss_esapi::tss2_esys::TPM2B_PUBLIC,
) -> Result<ESYS_TR, PinError> {
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<ESYS_TR, PinError> {
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,
},
) -> Result<KeyHandle, PinError> {
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())
}

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)
# 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]}')