Blob Blame History Raw
From 7d4425dc1b96f4a0efeb4383c6a32ab664d7e3cc Mon Sep 17 00:00:00 2001
From: Jonas Witschel <diabonas@gmx.de>
Date: Fri, 6 Sep 2019 15:27:14 +0200
Subject: [PATCH] pins/tpm2: add support for tpm2-tools 4.X

tpm2-tools renamed tpm2_pcrlist to tpm2_pcrread and changed a lot of
option names. Only the new unified environment variable TPM2TOOLS_TCTI
is supported, TPM2TOOLS_TCTI_NAME and TPM2TOOLS_DEVICE_FILE are no
longer recognised. Determine the tpm2-tools version from the output of
$(tpm2_createprimary -v) and switch accordingly.
---
 src/luks/systemd/dracut/module-setup.sh.in |  6 ++-
 src/pins/tpm2/clevis-decrypt-tpm2          | 40 ++++++++++++++----
 src/pins/tpm2/clevis-encrypt-tpm2          | 48 ++++++++++++++++++----
 src/pins/tpm2/meson.build                  |  5 ++-
 4 files changed, 77 insertions(+), 22 deletions(-)

diff --git a/src/luks/systemd/dracut/module-setup.sh.in b/src/luks/systemd/dracut/module-setup.sh.in
index 2dcdb68549d..89cc42cd226 100755
--- a/src/luks/systemd/dracut/module-setup.sh.in
+++ b/src/luks/systemd/dracut/module-setup.sh.in
@@ -19,7 +19,8 @@
 #
 
 check() {
-    require_binaries clevis-decrypt-tpm2 tpm2_createprimary tpm2_pcrlist tpm2_unseal tpm2_load || return 1
+    require_binaries clevis-decrypt-tpm2 tpm2_createprimary tpm2_unseal tpm2_load || return 1
+    require_any_binary tpm2_pcrread tpm2_pcrlist || return 1
     return 0
 }
 
@@ -53,7 +54,8 @@ install() {
         jose \
         nc
 
-    inst_multiple clevis-decrypt-tpm2 tpm2_createprimary tpm2_pcrlist tpm2_unseal tpm2_load
+    inst_multiple clevis-decrypt-tpm2 tpm2_createprimary tpm2_unseal tpm2_load
+    inst_multiple -o tpm2_pcrread tpm2_pcrlist
     inst_libdir_file "libtss2-tcti-device.so*"
     dracut_need_initqueue
 }
diff --git a/src/pins/tpm2/clevis-decrypt-tpm2 b/src/pins/tpm2/clevis-decrypt-tpm2
index 4fc1c5858e3..e603e9a7275 100755
--- a/src/pins/tpm2/clevis-decrypt-tpm2
+++ b/src/pins/tpm2/clevis-decrypt-tpm2
@@ -37,16 +37,22 @@ if [ -t 0 ]; then
     exit 1
 fi
 
-TPM2TOOLS_INFO=`tpm2_pcrlist -v`
+TPM2TOOLS_INFO="$(tpm2_createprimary -v)"
 
-if [[ $TPM2TOOLS_INFO != *version=\"3.* ]]; then
-    echo "The tpm2 pin requires tpm2-tools version 3" >&2
+match='version="(.)\.'
+[[ $TPM2TOOLS_INFO =~ $match ]] && TPM2TOOLS_VERSION="${BASH_REMATCH[1]}"
+if [[ $TPM2TOOLS_VERSION != 3 ]] && [[ $TPM2TOOLS_VERSION != 4 ]]; then
+    echo "The tpm2 pin requires tpm2-tools version 3 or 4" >&2
     exit 1
 fi
 
+# Old environment variables for tpm2-tools 3.0
 export TPM2TOOLS_TCTI_NAME=device
 export TPM2TOOLS_DEVICE_FILE=`ls /dev/tpmrm? 2>/dev/null`
 
+# New environment variable for tpm2-tools >= 3.1
+export TPM2TOOLS_TCTI="$TPM2TOOLS_TCTI_NAME:${TPM2TOOLS_DEVICE_FILE[0]}"
+
 if [ -z "${TPM2TOOLS_DEVICE_FILE[0]}" ]; then
     echo "A TPM2 device with the in-kernel resource manager is needed!" >&2
     exit 1
@@ -98,9 +104,10 @@ trap 'on_exit' EXIT
 
 pcr_ids=`jose fmt -j- -Og clevis -g tpm2 -g pcr_ids -Su- <<< "$jhd"` || true
 
+pcr_spec=''
 if [ -n "$pcr_ids" ]; then
     pcr_bank=`jose fmt -j- -Og clevis -g tpm2 -g pcr_bank -Su- <<< "$jhd"`
-    policy_options="-L $pcr_bank:$pcr_ids"
+    pcr_spec="$pcr_bank:$pcr_ids"
 fi
 
 if ! `jose b64 dec -i- -O $TMP/jwk.pub <<< "$jwk_pub"`; then
@@ -113,19 +120,34 @@ if ! `jose b64 dec -i- -O $TMP/jwk.priv <<< "$jwk_priv"`; then
     exit 1
 fi
 
-if ! tpm2_createprimary -Q -H "$auth" -g "$hash" -G "$key" \
-     -C $TMP/primary.context 2>/dev/null; then
+case "$TPM2TOOLS_VERSION" in
+    3) tpm2_createprimary -Q -H "$auth" -g "$hash" -G "$key" -C "$TMP"/primary.context || fail=$?;;
+    4) tpm2_createprimary -Q -C "$auth" -g "$hash" -G "$key" -c "$TMP"/primary.context || fail=$?;;
+    *) fail=1;;
+esac
+if [ -n "$fail" ]; then
     echo "Creating TPM2 primary key failed!" >&2
     exit 1
 fi
 
-if ! tpm2_load -Q -c $TMP/primary.context -u $TMP/jwk.pub -r $TMP/jwk.priv \
-     -C $TMP/load.context 2>/dev/null; then
+case "$TPM2TOOLS_VERSION" in
+    3) tpm2_load -Q -c "$TMP"/primary.context -u "$TMP"/jwk.pub -r "$TMP"/jwk.priv \
+                 -C "$TMP"/load.context || fail=$?;;
+    4) 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
     echo "Loading jwk to TPM2 failed!" >&2
     exit 1
 fi
 
-if ! jwk=`tpm2_unseal -c $TMP/load.context $policy_options 2>/dev/null`; then
+case "$TPM2TOOLS_VERSION" in
+    3) jwk="$(tpm2_unseal -c "$TMP"/load.context ${pcr_spec:+-L $pcr_spec})" || fail=$?;;
+    4) jwk="$(tpm2_unseal -c "$TMP"/load.context ${pcr_spec:+-p pcr:$pcr_spec})" || fail=$?;;
+    *) fail=1;;
+esac
+if [ -n "$fail" ]; then
     echo "Unsealing jwk from TPM failed!" >&2
     exit 1
 fi
diff --git a/src/pins/tpm2/clevis-encrypt-tpm2 b/src/pins/tpm2/clevis-encrypt-tpm2
index a7f333269bc..90321963d1e 100755
--- a/src/pins/tpm2/clevis-encrypt-tpm2
+++ b/src/pins/tpm2/clevis-encrypt-tpm2
@@ -59,16 +59,22 @@ if [ -t 0 ]; then
     exit 1
 fi
 
-TPM2TOOLS_INFO=`tpm2_pcrlist -v`
+TPM2TOOLS_INFO="$(tpm2_createprimary -v)"
 
-if [[ $TPM2TOOLS_INFO != *version=\"3.* ]]; then
-    echo "The tpm2 pin requires tpm2-tools version 3" >&2
+match='version="(.)\.'
+[[ $TPM2TOOLS_INFO =~ $match ]] && TPM2TOOLS_VERSION="${BASH_REMATCH[1]}"
+if [[ $TPM2TOOLS_VERSION != 3 ]] && [[ $TPM2TOOLS_VERSION != 4 ]]; then
+    echo "The tpm2 pin requires tpm2-tools version 3 or 4" >&2
     exit 1
 fi
 
+# Old environment variables for tpm2-tools 3.0
 export TPM2TOOLS_TCTI_NAME=device
 export TPM2TOOLS_DEVICE_FILE=`ls /dev/tpmrm? 2>/dev/null`
 
+# New environment variable for tpm2-tools >= 3.1
+export TPM2TOOLS_TCTI="$TPM2TOOLS_TCTI_NAME:${TPM2TOOLS_DEVICE_FILE[0]}"
+
 if [ -z "${TPM2TOOLS_DEVICE_FILE[0]}" ]; then
     echo "A TPM2 device with the in-kernel resource manager is needed!" >&2
     exit 1
@@ -106,14 +112,25 @@ fi
 
 trap 'on_exit' EXIT
 
-if ! tpm2_createprimary -Q -H "$auth" -g "$hash" -G "$key" -C $TMP/primary.context; then
+case "$TPM2TOOLS_VERSION" in
+    3) tpm2_createprimary -Q -H "$auth" -g "$hash" -G "$key" -C "$TMP"/primary.context || fail=$?;;
+    4) tpm2_createprimary -Q -C "$auth" -g "$hash" -G "$key" -c "$TMP"/primary.context || fail=$?;;
+    *) fail=1;;
+esac
+if [ -n "$fail" ]; then
     echo "Creating TPM2 primary key failed!" >&2
     exit 1
 fi
 
+policy_options=()
 if [ -n "$pcr_ids" ]; then
     if [ -z "$pcr_digest" ]; then
-        if ! tpm2_pcrlist -Q -L "$pcr_bank":"$pcr_ids" -o $TMP/pcr.digest; then
+        case "$TPM2TOOLS_VERSION" in
+            3) tpm2_pcrlist -Q -L "$pcr_bank":"$pcr_ids" -o "$TMP"/pcr.digest || fail=$?;;
+            4) tpm2_pcrread -Q "$pcr_bank":"$pcr_ids" -o "$TMP"/pcr.digest || fail=$?;;
+            *) fail=1;;
+        esac
+        if [ -n "$fail" ]; then
             echo "Creating PCR hashes file failed!" >&2
             exit 1
         fi
@@ -124,18 +141,31 @@ if [ -n "$pcr_ids" ]; then
         fi
     fi
 
-    if ! tpm2_createpolicy -Q -P -L "$pcr_bank":"$pcr_ids" -F $TMP/pcr.digest -f $TMP/pcr.policy; then
+    case "$TPM2TOOLS_VERSION" in
+        3) tpm2_createpolicy -Q -g "$hash" -P -L "$pcr_bank":"$pcr_ids" \
+                             -F "$TMP"/pcr.digest -f "$TMP"/pcr.policy || fail=$?;;
+        4) tpm2_createpolicy -Q -g "$hash" --policy-pcr -l "$pcr_bank":"$pcr_ids" \
+                             -f "$TMP"/pcr.digest -L "$TMP"/pcr.policy || fail=$?;;
+        *) fail=1;;
+    esac
+    if [ -n "$fail" ]; then
         echo "create policy fail, please check the environment or parameters!"
         exit 1
     fi
 
-    policy_options="-L $TMP/pcr.policy"
+    policy_options+=(-L "$TMP/pcr.policy")
 else
     obj_attr="$obj_attr|userwithauth"
 fi
 
-if ! tpm2_create -Q -g "$hash" -G "$alg_create_key" -c $TMP/primary.context -u $TMP/jwk.pub \
-     -r $TMP/jwk.priv -A "$obj_attr" $policy_options -I- <<< "$jwk"; then
+case "$TPM2TOOLS_VERSION" in
+    3) tpm2_create -Q -g "$hash" -G "$alg_create_key" -c "$TMP"/primary.context -u "$TMP"/jwk.pub \
+                   -r "$TMP"/jwk.priv -A "$obj_attr" "${policy_options[@]}" -I- <<< "$jwk" || fail=$?;;
+    4) tpm2_create -Q -g "$hash" -C "$TMP"/primary.context -u "$TMP"/jwk.pub \
+                   -r "$TMP"/jwk.priv -a "$obj_attr" "${policy_options[@]}" -i- <<< "$jwk" || fail=$?;;
+    *) fail=1;;
+esac
+if [ -n "$fail" ]; then
     echo "Creating TPM2 object for jwk failed!" >&2
     exit 1
 fi
diff --git a/src/pins/tpm2/meson.build b/src/pins/tpm2/meson.build
index 8121ec49cb3..4041a9a16d4 100644
--- a/src/pins/tpm2/meson.build
+++ b/src/pins/tpm2/meson.build
@@ -1,8 +1,9 @@
-cmds = ['createprimary', 'pcrlist', 'createpolicy', 'create', 'load', 'unseal']
+cmds = ['tpm2_createprimary', ['tpm2_pcrread', 'tpm2_pcrlist'],
+        'tpm2_createpolicy', 'tpm2_create', 'tpm2_load', 'tpm2_unseal']
 
 all = true
 foreach cmd : cmds
-  all = all and find_program('tpm2_' + cmd, required: false).found()
+  all = all and find_program(cmd, required: false).found()
 endforeach
 
 if all
-- 
2.21.0