From 03127b4e4658df5ae528706235161c7e9501d5c6 Mon Sep 17 00:00:00 2001 From: Luc Date: Mon, 10 Feb 2025 15:36:04 +0100 Subject: [PATCH] src/zlevis-decrypt: update w.r.t. issue #1 --- src/zlevis-decrypt | 67 ++++++++++++++++++++++------------------------ 1 file changed, 32 insertions(+), 35 deletions(-) diff --git a/src/zlevis-decrypt b/src/zlevis-decrypt index c218fbd..9fcc270 100755 --- a/src/zlevis-decrypt +++ b/src/zlevis-decrypt @@ -25,15 +25,6 @@ if [ -t 0 ]; then exit 2 fi -# Function to clean up temporary files on exit -on_exit() { - if [ ! -d "$tmp" ] || ! rm -rf "$tmp"; then - echo "Delete temporary files failed" >&2 - echo "You need to clean up: $tmp" >&2 - exit 1 - fi -} - # Get the version of tpm2-tools tpm2tools_version=$(tpm2_createprimary -v | awk -F'version="' '{print $2}' | awk -F'.' '{print $1}') @@ -43,73 +34,69 @@ if [ -z "$tpm2tools_version" ] || [ "$tpm2tools_version" -lt 4 ] || [ "$tpm2tool exit 1 fi -# Create a temporary directory for TPM files -if ! tmp="$(mktemp -d)"; then - echo "Creating a temporary dir for TPM files failed" >&2 - exit 1 -fi - -# Set up cleanup on exit -trap 'on_exit' EXIT - # Read the JWE protected header read -r -d . hdr -echo "$hdr" > "$tmp"/hdr # Decode the JWE protected header -if ! jhd="$(jose b64 dec -i- < "$tmp"/hdr)"; then +if ! jhd="$(printf "%s" "$hdr" | jose b64 dec -i-)"; then echo "Error decoding JWE protected header" >&2 exit 1 fi -echo "$jhd" > "$tmp"/jhd # Validate the JWE pin type -if [ "$(jose fmt -j- -Og zlevis -g pin -u- < "$tmp"/jhd)" != "tpm2" ]; then +if [ "$(printf "%s" "$jhd" | jose fmt -j- -Og zlevis -g pin -u-)" != "tpm2" ]; then echo "JWE pin mismatch" >&2 exit 1 fi # Extract required parameters from the JWE header -if ! hash="$(jose fmt -j- -Og zlevis -g tpm2 -g hash -Su- < "$tmp"/jhd)"; then +if ! hash="$(printf "%s" "$jhd" | jose fmt -j- -Og zlevis -g tpm2 -g hash -Su-)"; then echo "JWE missing required 'hash' header parameter!" >&2 exit 1 fi -if ! key="$(jose fmt -j- -Og zlevis -g tpm2 -g key -Su- < "$tmp"/jhd)"; then +if ! key="$(printf "%s" "$jhd" | jose fmt -j- -Og zlevis -g tpm2 -g key -Su-)"; then echo "JWE missing required 'key' header parameter!" >&2 exit 1 fi -if ! jwk_pub="$(jose fmt -j- -Og zlevis -g tpm2 -g jwk_pub -Su- < "$tmp"/jhd)"; then +if ! jwk_pub="$(printf "%s" "$jhd" | jose fmt -j- -Og zlevis -g tpm2 -g jwk_pub -Su-)"; then echo "JWE missing required 'jwk_pub' header parameter!" >&2 exit 1 fi -echo "$jwk_pub" > "$tmp"/jwk_pub -if ! jwk_priv="$(jose fmt -j- -Og zlevis -g tpm2 -g jwk_priv -Su- < "$tmp"/jhd)"; then +if ! jwk_priv="$(printf "%s" "$jhd" | jose fmt -j- -Og zlevis -g tpm2 -g jwk_priv -Su-)"; then echo "JWE missing required 'jwk_priv' header parameter!" >&2 exit 1 fi -echo "$jwk_priv" > "$tmp"/jwk_priv # Handle optional PCR parameters -pcr_ids="$(jose fmt -j- -Og zlevis -g tpm2 -g pcr_ids -Su- < "$tmp"/jhd)" || true +pcr_ids="$(printf "%s" "$jhd" | jose fmt -j- -Og zlevis -g tpm2 -g pcr_ids -Su-)" || true pcr_spec="" if [ -n "$pcr_ids" ]; then - pcr_bank="$(jose fmt -j- -Og zlevis -g tpm2 -g pcr_bank -Su- < "$tmp"/jhd)" + pcr_bank="$(printf "%s" "$jhd" | jose fmt -j- -Og zlevis -g tpm2 -g pcr_bank -Su-)" pcr_spec="$pcr_bank:$pcr_ids" fi +# Define and trap tmp jwk_pub and jwk_priv +tmp_jwk_pub = "/tmp/jwk_pub.$" +tmp_jwk_priv = "/tmp/jwk_priv.$" +trap 'rm -f "$tmp_jwk_pub" "$tmp_jwk_priv"' EXIT + # Decode the public and private keys from Base64 -if ! jose b64 dec -i- -O "$tmp"/jwk.pub < "$tmp"/jwk_pub; then +if ! printf "%s" "$jwk_pub" | jose b64 dec -i- -O "$tmp_jwk_pub"; then echo "Decoding jwk.pub from Base64 failed" >&2 exit 1 fi -if ! jose b64 dec -i- -O "$tmp"/jwk.priv < "$tmp"/jwk_priv; then +if ! printf "%s" "$jwk_priv" | jose b64 dec -i- -O "$tmp_jwk_priv"; then echo "Decoding jwk.priv from Base64 failed" >&2 exit 1 fi +# Define and trap primary_context +tmp_primary_context = "/tmp/primary_context.$" +trap 'rm -f "$tmp_jwk_pub" "$tmp_jwk_priv" "$tmp_primary_context"' EXIT + # Create the primary key in the TPM case "$tpm2tools_version" in - 4|5) tpm2_createprimary -Q -C "$auth" -g "$hash" -G "$key" -c "$tmp"/primary.context || fail=$?;; + 4|5) tpm2_createprimary -Q -C "$auth" -g "$hash" -G "$key" -c "$tmp_primary_context" || fail=$?;; *) fail=1;; esac if [ -n "$fail" ]; then @@ -118,9 +105,13 @@ if [ -n "$fail" ]; then fi tpm2_flushcontext -t +# Define and trap load_context +tmp_load_context = "/tmp/load_context.$" +trap 'rm -f "$tmp_jwk_pub" "$tmp_jwk_priv" "$tmp_primary_context" "$tmp_load_context"' EXIT + # Load the JWK into the TPM case "$tpm2tools_version" in - 4|5) tpm2_load -Q -C "$tmp"/primary.context -u "$tmp"/jwk.pub -r "$tmp"/jwk.priv -c "$tmp"/load.context || fail=$?;; + 4|5) tpm2_load -Q -C "$tmp_primary_context" -u "$tmp_jwk_pub" -r "$tmp_jwk_priv" -c "$tmp_load_context" || fail=$?;; *) fail=1;; esac if [ -n "$fail" ]; then @@ -129,9 +120,12 @@ if [ -n "$fail" ]; then fi tpm2_flushcontext -t +# Remove tmp_jwk_pub, tmp_jwk_priv and tmp_primary_context +rm -f "$tmp_jwk_pub" "$tmp_jwk_priv" "$tmp_primary_context" + # Unseal the JWK from the TPM case "$tpm2tools_version" in - 4|5) jwk="$(tpm2_unseal -c "$tmp/load.context" ${pcr_spec:+-p pcr:$pcr_spec})" || fail=$?;; + 4|5) jwk="$(tpm2_unseal -c "$tmp_load_context" ${pcr_spec:+-p pcr:$pcr_spec})" || fail=$?;; *) fail=1;; esac if [ -n "$fail" ]; then @@ -140,6 +134,9 @@ if [ -n "$fail" ]; then fi tpm2_flushcontext -t +# Remove tmp_load_context +rm -f "$tmp_load_context" + # Output the decrypted JWK along with the original header (echo "$jwk$hdr."; /bin/cat) | jose jwe dec -k- -i-