From fb3c135906cab203cfd11b3cb4a502ef8530987a Mon Sep 17 00:00:00 2001 From: Nathaniel McCallum Date: Mon, 9 Jul 2018 08:47:14 +0200 Subject: [PATCH] Add support for TPM 2.0 --- Makefile.am | 5 ++ configure.ac | 11 +++ doc/clevis-encrypt-tpm2.1 | 142 +++++++++++++++++++++++++++++++ doc/clevis-encrypt-tpm2.1.md | 108 +++++++++++++++++++++++ doc/clevis.1 | 40 ++++++++- src/Makefile.am | 6 ++ src/clevis-decrypt-tpm2 | 126 +++++++++++++++++++++++++++ src/clevis-encrypt-tpm2 | 156 ++++++++++++++++++++++++++++++++++ src/dracut/module-setup.sh.in | 23 +++++ 9 files changed, 615 insertions(+), 2 deletions(-) create mode 100644 doc/clevis-encrypt-tpm2.1 create mode 100644 doc/clevis-encrypt-tpm2.1.md create mode 100755 src/clevis-decrypt-tpm2 create mode 100755 src/clevis-encrypt-tpm2 diff --git a/Makefile.am b/Makefile.am index 141642a..75f9745 100644 --- a/Makefile.am +++ b/Makefile.am @@ -14,3 +14,8 @@ dist_man1_MANS = \ doc/clevis-luks-bind.1 \ doc/clevis-decrypt.1 \ doc/clevis.1 + +if HAVE_TPM2_TOOLS + dist_man1_MANS += \ + doc/clevis-encrypt-tpm2.1 +endif diff --git a/configure.ac b/configure.ac index f9ed01a..313f64e 100644 --- a/configure.ac +++ b/configure.ac @@ -54,6 +54,17 @@ fi AC_SUBST(SD_ACTIVATE) +for ac_prog in createprimary pcrlist createpolicy create load unseal; do + unset TPM2_TOOLS + unset ac_cv_prog_TPM2_TOOLS + AC_CHECK_PROG([TPM2_TOOLS], [tpm2_$ac_prog], [yes]) + test -z "$TPM2_TOOLS" && break +done + +test -n "$TPM2_TOOLS" || AC_MSG_WARN([tpm2_$ac_prog not found, tpm2 pin won't be installed]) + +AM_CONDITIONAL([HAVE_TPM2_TOOLS], [test -n "$TPM2_TOOLS"]) + AC_ARG_ENABLE([user], AS_HELP_STRING([--enable-user=USER], [Set unprivileged user (default: root)]), diff --git a/doc/clevis-encrypt-tpm2.1 b/doc/clevis-encrypt-tpm2.1 new file mode 100644 index 0000000..096ad23 --- /dev/null +++ b/doc/clevis-encrypt-tpm2.1 @@ -0,0 +1,142 @@ +.\" Automatically generated by Pandoc 1.19.1 +.\" +.TH "CLEVIS\-ENCRYPT\-TPM2" "1" "November 2017" "" "" +.hy +.SH NAME +.PP +clevis\-encrypt\-tpm2 \-\- Encrypts using a TPM2.0 chip binding policy +.SH SYNOPSIS +.PP +\f[C]clevis\ encrypt\ tpm2\f[] CONFIG < PT > JWE +.SH OVERVIEW +.PP +The \f[C]clevis\ encrypt\ tpm2\f[] command encrypts using a Trusted +Platform Module 2.0 (TPM2) chip. +Its only argument is the JSON configuration object. +.PP +When using the tpm2 pin, we create a new, cryptographically\-strong, +random key. +This key is encrypted using the TPM2 chip. +Then at decryption time, the key is decrypted again using the TPM2 chip. +.IP +.nf +\f[C] +$\ clevis\ encrypt\ tpm2\ \[aq]{}\[aq]\ <\ PT\ >\ JWE +\f[] +.fi +.PP +The pin has reasonable defaults for its configuration, but a different +hierarchy, hash, and key algorithms can be chosen if the defaults used +are not suitable: +.IP +.nf +\f[C] +$\ clevis\ encrypt\ tpm2\ \[aq]{"hash":"sha1","key":"rsa"}\[aq]\ <\ PT\ >\ JWE +\f[] +.fi +.PP +To decrypt the data, simply provide the ciphertext (JWE): +.IP +.nf +\f[C] +$\ clevis\ decrypt\ <\ JWE\ >\ PT +\f[] +.fi +.PP +Note that like other pins no configuration is used for decryption, this +is due clevis storing the public and private keys to unseal the TPM2 +encrypted object in the JWE so clevis can fetch that information from +there. +.PP +The pin also supports sealing data to a Platform Configuration Registers +(PCR) state. +That way the data can only be unsealed if the PCRs hashes values match +the policy used when sealing. +.PP +For example, to seal the data to the PCR with index 0 and 1 for the SHA1 +bank: +.IP +.nf +\f[C] +$\ clevis\ encrypt\ tpm2\ \[aq]{"pcr_bank":"sha1","pcr_ids":"0,1"}\[aq]\ <\ PT\ >\ JWE +\f[] +.fi +.PP +The PCR digest values are looked up from the current hash values for the +PCRs, but a digest can also be provided if the data needs to be sealed +with values different to the current ones, by passing the binary hash +encoded in base64: +.IP +.nf +\f[C] +$\ clevis\ encrypt\ tpm2\ \[aq]{"pcr_ids":"0","pcr_digest":"xy7J5svCtqlfM03d1lE5gdoA8MI"}\[aq]\ <\ PT\ >\ JWE +\f[] +.fi +.SH Threat model +.PP +The Clevis security model relies in the fact that an attacker will not +be able to access both the encrypted data and the decryption key. +.PP +For most Clevis pins, the decryption key is not locally stored, so the +decryption policy is only satisfied if the decryption key can be +remotely accessed. +It could for example be stored in a remote server or in a hardware +authentication device that has to be plugged into the machine. +.PP +The tpm2 pin is different in this regard, since a key is wrapped by a +TPM2 chip that is always present in the machine. +This does not mean that there are not use cases for this pin, but it is +important to understand the fact that an attacker that has access to +both the encrypted data and the local TPM2 chip will be able to decrypt +the data. +.SH CONFIG +.PP +This command uses the following configuration properties: +.IP \[bu] 2 +\f[C]hash\f[] (string) : Hash algorithm used in the computation of the +object name (default: sha256) +.PP +It must be one of the following: +.IP \[bu] 2 +\f[C]sha1\f[] +.IP \[bu] 2 +\f[C]sha256\f[] +.IP \[bu] 2 +\f[C]sha384\f[] +.IP \[bu] 2 +\f[C]sha512\f[] +.IP \[bu] 2 +\f[C]sm3_256\f[] +.IP \[bu] 2 +\f[C]key\f[] (string) : Algorithm type for the generated key (default: +ecc) +.PP +It must be one of the following: +.IP \[bu] 2 +\f[C]rsa\f[] +.IP \[bu] 2 +\f[C]keyedhash\f[] +.IP \[bu] 2 +\f[C]ecc\f[] +.IP \[bu] 2 +\f[C]symcipher\f[] +.IP \[bu] 2 +\f[C]pcr_bank\f[] (string) : PCR algorithm bank to use for policy +(default: sha1) +.PP +It must be one of the following: +.IP \[bu] 2 +\f[C]sha1\f[] +.IP \[bu] 2 +\f[C]sha256\f[] +.IP \[bu] 2 +\f[C]pcr_ids\f[] (string) : Comma separated list of PCR used for policy. +If not present, no policy is used +.IP \[bu] 2 +\f[C]pcr_digest\f[] (string) : Binary PCR hashes encoded in base64. +If not present, the hash values are looked up +.SH SEE ALSO +.PP +\f[C]clevis\-decrypt\f[](1) +.SH AUTHORS +Javier Martinez Canillas . diff --git a/doc/clevis-encrypt-tpm2.1.md b/doc/clevis-encrypt-tpm2.1.md new file mode 100644 index 0000000..f533d67 --- /dev/null +++ b/doc/clevis-encrypt-tpm2.1.md @@ -0,0 +1,108 @@ +% CLEVIS-ENCRYPT-TPM2(1) +% Javier Martinez Canillas +% November 2017 + +# NAME + +clevis-encrypt-tpm2 -- Encrypts using a TPM2.0 chip binding policy + +# SYNOPSIS + +`clevis encrypt tpm2` CONFIG < PT > JWE + +# OVERVIEW + +The `clevis encrypt tpm2` command encrypts using a Trusted Platform Module 2.0 +(TPM2) chip. Its only argument is the JSON configuration object. + +When using the tpm2 pin, we create a new, cryptographically-strong, random key. +This key is encrypted using the TPM2 chip. +Then at decryption time, the key is decrypted again using the TPM2 chip. + + $ clevis encrypt tpm2 '{}' < PT > JWE + +The pin has reasonable defaults for its configuration, but a different hierarchy, +hash, and key algorithms can be chosen if the defaults used are not suitable: + + $ clevis encrypt tpm2 '{"hash":"sha1","key":"rsa"}' < PT > JWE + +To decrypt the data, simply provide the ciphertext (JWE): + + $ clevis decrypt < JWE > PT + +Note that like other pins no configuration is used for decryption, this is due +clevis storing the public and private keys to unseal the TPM2 encrypted object +in the JWE so clevis can fetch that information from there. + +The pin also supports sealing data to a Platform Configuration Registers (PCR) +state. That way the data can only be unsealed if the PCRs hashes values match +the policy used when sealing. + +For example, to seal the data to the PCR with index 0 and 1 for the SHA1 bank: + + $ clevis encrypt tpm2 '{"pcr_bank":"sha1","pcr_ids":"0,1"}' < PT > JWE + +The PCR digest values are looked up from the current hash values for the PCRs, +but a digest can also be provided if the data needs to be sealed with values +different to the current ones, by passing the binary hash encoded in base64: + + $ clevis encrypt tpm2 '{"pcr_ids":"0","pcr_digest":"xy7J5svCtqlfM03d1lE5gdoA8MI"}' < PT > JWE + +# Threat model + +The Clevis security model relies in the fact that an attacker will not be able to +access both the encrypted data and the decryption key. + +For most Clevis pins, the decryption key is not locally stored, so the decryption +policy is only satisfied if the decryption key can be remotely accessed. It could +for example be stored in a remote server or in a hardware authentication device +that has to be plugged into the machine. + +The tpm2 pin is different in this regard, since a key is wrapped by a TPM2 chip +that is always present in the machine. This does not mean that there are not use +cases for this pin, but it is important to understand the fact that an attacker +that has access to both the encrypted data and the local TPM2 chip will be able +to decrypt the data. + +# CONFIG + +This command uses the following configuration properties: + +* `hash` (string) : + Hash algorithm used in the computation of the object name (default: sha256) + + It must be one of the following: + + * `sha1` + * `sha256` + * `sha384` + * `sha512` + * `sm3_256` + +* `key` (string) : + Algorithm type for the generated key (default: ecc) + + It must be one of the following: + + * `rsa` + * `keyedhash` + * `ecc` + * `symcipher` + +* `pcr_bank` (string) : + PCR algorithm bank to use for policy (default: sha1) + + It must be one of the following: + + * `sha1` + * `sha256` + +* `pcr_ids` (string) : + Comma separated list of PCR used for policy. If not present, no policy is used + +* `pcr_digest` (string) : + Binary PCR hashes encoded in base64. If not present, the hash values are looked up + +# SEE ALSO + +`clevis-decrypt`(1) diff --git a/doc/clevis.1 b/doc/clevis.1 index 3d4a10d..0937533 100644 --- a/doc/clevis.1 +++ b/doc/clevis.1 @@ -80,6 +80,42 @@ $\ clevis\ decrypt\ <\ JWE\ >\ PT .fi .PP For more information, see \f[C]clevis\-encrypt\-tang\f[](1). +.SH TPM2 BINDING +.PP +Clevis provides support to encrypt a key in a Trusted Platform Module +2.0 (TPM2) chip. +The cryptographically\-strong, random key used for encryption is +encrypted using the TPM2 chip, and then at decryption time is decrypted +using the TPM2 to allow clevis to decrypt the secret stored in the JWE. +.PP +Encrypting data using the tpm2 pin works the same than the pins +mentioned above: +.IP +.nf +\f[C] +$\ clevis\ encrypt\ tpm2\ \[aq]{}\[aq]\ <\ PT\ >\ JWE +\f[] +.fi +.PP +The pin has reasonable defaults for its configuration, but a different +hierarchy, hash, and key algorithms can be chosen if the defaults used +are not suitable. +.PP +Decryption also works similar to other pins, only the JWE needs to be +provided: +.IP +.nf +\f[C] +$\ clevis\ decrypt\ <\ JWE\ >\ PT +\f[] +.fi +.PP +Note that like other pins no configuration is used for decryption, this +is due clevis storing the public and private keys to unseal the TPM2 +encrypted object in the JWE so clevis can fetch that information from +there. +.PP +For more information see \f[C]clevis\-encrypt\-tpm2\f[](1). .SH SHAMIR\[aq]S SECRET SHARING .PP Clevis provides a way to mix pins together to create sophisticated @@ -151,7 +187,7 @@ For more information, see \f[C]clevis\-luks\-bind\f[](1). .SH SEE ALSO .PP \f[C]clevis\-encrypt\-http\f[](1), \f[C]clevis\-encrypt\-tang\f[](1), -\f[C]clevis\-encrypt\-sss\f[](1), \f[C]clevis\-luks\-bind\f[](1), -\f[C]clevis\-decrypt\f[](1) +\f[C]clevis\-encrypt\-tpm2\f[](1), \f[C]clevis\-encrypt\-sss\f[](1), +\f[C]clevis\-luks\-bind\f[](1), \f[C]clevis\-decrypt\f[](1) .SH AUTHORS Nathaniel McCallum . diff --git a/src/Makefile.am b/src/Makefile.am index 244874b..8562502 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -25,6 +25,12 @@ dist_bin_SCRIPTS = \ clevis-decrypt \ clevis +if HAVE_TPM2_TOOLS + dist_bin_SCRIPTS += \ + clevis-encrypt-tpm2 \ + clevis-decrypt-tpm2 +endif + clevis_encrypt_sss_SOURCES = clevis-encrypt-sss.c sss.c sss.h clevis_decrypt_sss_SOURCES = clevis-decrypt-sss.c sss.c sss.h clevis_encrypt_sss_LDADD = @jose_LIBS@ @libcrypto_LIBS@ diff --git a/src/clevis-decrypt-tpm2 b/src/clevis-decrypt-tpm2 new file mode 100755 index 0000000..f3871d8 --- /dev/null +++ b/src/clevis-decrypt-tpm2 @@ -0,0 +1,126 @@ +#!/bin/bash -e +# vim: set tabstop=8 shiftwidth=4 softtabstop=4 expandtab smarttab colorcolumn=80: +# +# Copyright (c) 2017 Red Hat, Inc. +# Author: Javier Martinez Canillas +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + +# The owner hierarchy is the one that should be used by the Operating System. +auth="o" + +function on_exit() { + if ! rm -r $TMP; then + echo "Delete temporary files failed!" >&2 + exit 1 + fi +} + +[ $# -eq 1 -a "$1" == "--summary" ] && exit 1 + +if [ -t 0 ]; then + echo >&2 + echo "Usage: clevis decrypt tpm2 < JWE > PLAINTEXT" >&2 + echo >&2 + exit 1 +fi + +export TPM2TOOLS_TCTI_NAME=device +export TPM2TOOLS_DEVICE_FILE=`ls /dev/tpmrm? 2>/dev/null` + +if [ -z "${TPM2TOOLS_DEVICE_FILE[0]}" ]; then + echo "A TPM2 device with the in-kernel resource manager is needed!" >&2 + exit 1 +fi + +if ! [[ -r "${TPM2TOOLS_DEVICE_FILE[0]}" && -w "${TPM2TOOLS_DEVICE_FILE[0]}" ]]; then + echo "The ${TPM2TOOLS_DEVICE_FILE[0]} device must be readable and writable!" >&2 + exit 1 +fi + +read -d . hdr + +if ! jhd=`jose b64 dec -i- <<< "$hdr"`; then + echo "Error decoding JWE protected header!" >&2 + exit 1 +fi + +if [ `jose fmt -j- -Og clevis -g pin -u- <<< "$jhd"` != "tpm2" ]; then + echo "JWE pin mismatch!" >&2 + exit 1 +fi + +if ! hash=`jose fmt -j- -Og clevis -g tpm2 -g hash -Su- <<< "$jhd"`; then + echo "JWE missing required 'hash' header parameter!" >&2 + exit 1 +fi + +if ! key=`jose fmt -j- -Og clevis -g tpm2 -g key -Su- <<< "$jhd"`; then + echo "JWE missing required 'key' header parameter!" >&2 + exit 1 +fi + +if ! jwk_pub=`jose fmt -j- -Og clevis -g tpm2 -g jwk_pub -Su- <<< "$jhd"`; then + echo "JWE missing required 'key' header parameter!" >&2 + exit 1 +fi + +if ! jwk_priv=`jose fmt -j- -Og clevis -g tpm2 -g jwk_priv -Su- <<< "$jhd"`; then + echo "JWE missing required 'key' header parameter!" >&2 + exit 1 +fi + +if ! TMP=`mktemp -d`; then + echo "Creating a temporary dir for TPM files failed!" >&2 + exit 1 +fi + +trap 'on_exit' EXIT + +pcr_ids=`jose fmt -j- -Og clevis -g tpm2 -g pcr_ids -Su- <<< "$jhd"` || true + +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" +fi + +if ! `jose b64 dec -i- -O $TMP/jwk.pub <<< "$jwk_pub"`; then + echo "Decoding jwk.pub from Base64 failed!" >&2 + exit 1 +fi + +if ! `jose b64 dec -i- -O $TMP/jwk.priv <<< "$jwk_priv"`; then + echo "Decoding jwk.priv from Base64 failed!" >&2 + exit 1 +fi + +if ! tpm2_createprimary -Q -H "$auth" -g "$hash" -G "$key" \ + -C $TMP/primary.context 2>/dev/null; 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 + echo "Loading jwk to TPM2 failed!" >&2 + exit 1 +fi + +if ! jwk=`tpm2_unseal -c $TMP/load.context $policy_options 2>/dev/null`; then + echo "Unsealing jwk from TPM failed!" >&2 + exit 1 +fi + +jose jwe dec -k- -i- < <(echo -n "$jwk$hdr."; cat) diff --git a/src/clevis-encrypt-tpm2 b/src/clevis-encrypt-tpm2 new file mode 100755 index 0000000..b99aa97 --- /dev/null +++ b/src/clevis-encrypt-tpm2 @@ -0,0 +1,156 @@ +#!/bin/bash -e +# vim: set tabstop=8 shiftwidth=4 softtabstop=4 expandtab smarttab colorcolumn=80: +# +# Copyright (c) 2017 Red Hat, Inc. +# Author: Javier Martinez Canillas +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + +SUMMARY="Encrypts using a TPM2.0 chip binding policy" +# The owner hierarchy is the one that should be used by the Operating System. +auth="o" +# Algorithm type must be keyedhash for object with user provided sensitive data. +alg_create_key="keyedhash" +# Attributes for the created TPM2 object with the JWK as sensitive data. +obj_attr="fixedtpm|fixedparent|sensitivedataorigin|noda|adminwithpolicy" + +function on_exit() { + if ! rm -rf $TMP; then + echo "Delete temporary files failed!" >&2 + exit 1 + fi +} + +if [ "$1" == "--summary" ]; then + echo "$SUMMARY" + exit 0 +fi + +if [ -t 0 ]; then + echo >&2 + echo "Usage: clevis encrypt tpm2 CONFIG < PLAINTEXT > JWE" >&2 + echo >&2 + echo $SUMMARY >&2 + echo >&2 + echo "This command uses the following configuration properties:" >&2 + echo >&2 + echo " hash: Hash algorithm used in the computation of the object name (default: sha256)" >&2 + echo >&2 + echo " key: Algorithm type for the generated key (default: ecc)" >&2 + echo >&2 + echo " pcr_bank: PCR algorithm bank to use for policy (default: sha1)" >&2 + echo >&2 + echo " pcr_ids: PCR list used for policy. If not present, no policy is used" >&2 + echo >&2 + echo " pcr_digest: Binary PCR hashes encoded in base64. If not present, the hash values are looked up" >&2 + echo >&2 + exit 1 +fi + +export TPM2TOOLS_TCTI_NAME=device +export TPM2TOOLS_DEVICE_FILE=`ls /dev/tpmrm? 2>/dev/null` + +if [ -z "${TPM2TOOLS_DEVICE_FILE[0]}" ]; then + echo "A TPM2 device with the in-kernel resource manager is needed!" >&2 + exit 1 +fi + +if ! [[ -r "${TPM2TOOLS_DEVICE_FILE[0]}" && -w "${TPM2TOOLS_DEVICE_FILE[0]}" ]]; then + echo "The ${TPM2TOOLS_DEVICE_FILE[0]} device must be readable and writable!" >&2 + exit 1 +fi + +if ! cfg=`jose fmt -j "$1" -Oo- 2>/dev/null`; then + echo "Configuration is malformed!" >&2 + exit 1 +fi + +hash=`jose fmt -j- -Og hash -u- <<< "$cfg"` || hash="sha256" + +key=`jose fmt -j- -Og key -u- <<< "$cfg"` || key="ecc" + +pcr_bank=`jose fmt -j- -Og pcr_hash -u- <<< "$cfg"` || pcr_bank="sha1" + +pcr_ids=`jose fmt -j- -Og pcr_ids -u- <<< "$cfg"` || true + +pcr_digest=`jose fmt -j- -Og pcr_digest -u- <<< "$cfg"` || true + +if ! jwk=`jose jwk gen -i '{"alg":"A256GCM"}'`; then + echo "Generating a jwk failed!" >&2 + exit 1 +fi + +if ! TMP=`mktemp -d`; then + echo "Creating a temporary dir for TPM files failed!" >&2 + exit 1 +fi + +trap 'on_exit' EXIT + +if ! tpm2_createprimary -Q -H "$auth" -g "$hash" -G "$key" -C $TMP/primary.context; then + echo "Creating TPM2 primary key failed!" >&2 + exit 1 +fi + +if [ -n "$pcr_ids" ]; then + if [ -z "$pcr_digest" ]; then + if ! tpm2_pcrlist -Q -L "$pcr_bank":"$pcr_ids" -o $TMP/pcr.digest; then + echo "Creating PCR hashes file failed!" >&2 + exit 1 + fi + else + if ! jose b64 dec -i- -O "$TMP"/pcr.digest <<< "$pcr_digest"; then + echo "Error decoding PCR digest!" >&2 + exit 1 + fi + fi + + if ! tpm2_createpolicy -Q -P -L "$pcr_bank":"$pcr_ids" -F $TMP/pcr.digest -f $TMP/pcr.policy; then + echo "create policy fail, please check the environment or parameters!" + exit 1 + fi + + policy_options="-L $TMP/pcr.policy" +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 + echo "Creating TPM2 object for jwk failed!" >&2 + exit 1 +fi + +if ! jwk_pub=`jose b64 enc -I $TMP/jwk.pub`; then + echo "Encoding jwk.pub in Base64 failed!" >&2 + exit 1 +fi + +if ! jwk_priv=`jose b64 enc -I $TMP/jwk.priv`; then + echo "Encoding jwk.priv in Base64 failed!" >&2 + exit 1 +fi + +jwe='{"protected":{"clevis":{"pin":"tpm2","tpm2":{}}}}' +jwe=`jose fmt -j "$jwe" -g protected -g clevis -g tpm2 -q "$hash" -s hash -UUUUo-` +jwe=`jose fmt -j "$jwe" -g protected -g clevis -g tpm2 -q "$key" -s key -UUUUo-` + +if [ -n "$pcr_ids" ]; then + jwe=`jose fmt -j "$jwe" -g protected -g clevis -g tpm2 -q "$pcr_bank" -s pcr_bank -UUUUo-` + jwe=`jose fmt -j "$jwe" -g protected -g clevis -g tpm2 -q "$pcr_ids" -s pcr_ids -UUUUo-` +fi + +jwe=`jose fmt -j "$jwe" -g protected -g clevis -g tpm2 -q "$jwk_pub" -s jwk_pub -UUUUo-` +jwe=`jose fmt -j "$jwe" -g protected -g clevis -g tpm2 -q "$jwk_priv" -s jwk_priv -UUUUo-` + +jose jwe enc -i- -k- -I- -c < <(echo -n "$jwe$jwk"; cat) diff --git a/src/dracut/module-setup.sh.in b/src/dracut/module-setup.sh.in index 5087d56..119762e 100755 --- a/src/dracut/module-setup.sh.in +++ b/src/dracut/module-setup.sh.in @@ -28,6 +28,8 @@ cmdline() { } install() { + local ret=0 + cmdline > "${initdir}/etc/cmdline.d/99clevis.conf" inst_hook initqueue/online 60 "$moddir/clevis-hook.sh" @@ -41,10 +43,31 @@ install() { clevis-decrypt \ luksmeta \ clevis \ + mktemp \ curl \ jose \ nc + for cmd in clevis-decrypt-tpm2 \ + tpm2_createprimary \ + tpm2_unseal \ + tpm2_load; do + + if ! find_binary "$cmd" &>/dev/null; then + ((ret++)) + fi + done + + if (($ret == 0)); then + inst_multiple clevis-decrypt-tpm2 \ + tpm2_createprimary \ + tpm2_unseal \ + tpm2_load + fi + dracut_need_initqueue } +installkernel() { + hostonly='' instmods =drivers/char/tpm +} -- 2.17.1