From 7d4425dc1b96f4a0efeb4383c6a32ab664d7e3cc Mon Sep 17 00:00:00 2001 From: Jonas Witschel 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