Compare commits
	
		
			No commits in common. "f11bd91d752b2dff762598eea6a33bf45ac19c99" and "f830d0f5ab3358ad13b3ca53afde1baad82996de" have entirely different histories.
		
	
	
		
			f11bd91d75
			...
			f830d0f5ab
		
	
		
					 3 changed files with 10 additions and 180 deletions
				
			
		|  | @ -1,147 +0,0 @@ | ||||||
| #!/bin/sh |  | ||||||
| 
 |  | ||||||
| # Exit immediately if a command exits with a non-zero status |  | ||||||
| set -e |  | ||||||
| 
 |  | ||||||
| # Summary of the script's functionality |  | ||||||
| summary="Decrypts a JWE using a TPM2.0 chip." |  | ||||||
| 
 |  | ||||||
| # TPM2.0 owner hierarchy to be used by the Operating System |  | ||||||
| auth="o" |  | ||||||
| 
 |  | ||||||
| # Display summary if requested |  | ||||||
| if [ "$1" = "--summary" ]; then |  | ||||||
|     echo "$summary" |  | ||||||
|     exit 0 |  | ||||||
| fi |  | ||||||
| 
 |  | ||||||
| # Display usage information if input is from a terminal |  | ||||||
| if [ -t 0 ]; then |  | ||||||
|     exec >&2 |  | ||||||
|     echo |  | ||||||
|     echo "Usage: \"zlevis-decrypt < file.jwe\"" |  | ||||||
|     echo "Usage ZFS: \"zfs list -Ho tpm:jwe <pool> | zlevis-decrypt\"" |  | ||||||
|     echo |  | ||||||
|     echo "$summary" |  | ||||||
|     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}') |  | ||||||
| 
 |  | ||||||
| # Check if the tpm2-tools version is supported |  | ||||||
| if [ -z "$tpm2tools_version" ] || [ "$tpm2tools_version" -lt 4 ] || [ "$tpm2tools_version" -gt 5 ]; then |  | ||||||
|     echo "The tpm2 pin requires a tpm2-tools version between 4 and 5" |  | ||||||
|     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 |  | ||||||
| 
 |  | ||||||
| # Decode the JWE protected header |  | ||||||
| if ! jhd="$(jose b64 dec -i- < <(echo "$hdr"))"; 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 clevis -g pin -u- < "$tmp"/jhd)" != "tpm2" ]; then |  | ||||||
|     echo "JWE pin mismatch" >&2 |  | ||||||
|     exit 1 |  | ||||||
| fi |  | ||||||
| 
 |  | ||||||
| # Extract required parameters from the JWE header |  | ||||||
| if ! hash="$(jose fmt -j- -Og clevis -g tpm2 -g hash -Su- < "$tmp"/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- < "$tmp"/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- < "$tmp"/jhd)"; 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 clevis -g tpm2 -g jwk_priv -Su- < "$tmp"/jhd)"; 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 clevis -g tpm2 -g pcr_ids -Su- < "$tmp"/jhd)" || true |  | ||||||
| pcr_spec="" |  | ||||||
| if [ -n "$pcr_ids" ]; then |  | ||||||
|     pcr_bank="$(jose fmt -j- -Og clevis -g tpm2 -g pcr_bank -Su- < "$tmp"/jhd)" |  | ||||||
|     pcr_spec="$pcr_bank:$pcr_ids" |  | ||||||
| fi |  | ||||||
| 
 |  | ||||||
| # Decode the public and private keys from Base64 |  | ||||||
| if ! jose b64 dec -i- -O "$tmp"/jwk.pub < "$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 |  | ||||||
|     echo "Decoding jwk.priv from Base64 failed" >&2 |  | ||||||
|     exit 1 |  | ||||||
| fi |  | ||||||
| 
 |  | ||||||
| # 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=$?;; |  | ||||||
|     *) fail=1;; |  | ||||||
| esac |  | ||||||
| if [ -n "$fail" ]; then |  | ||||||
|     echo "Creating TPM2 primary key failed" >&2 |  | ||||||
|     exit 1 |  | ||||||
| fi |  | ||||||
| tpm2_flushcontext -t |  | ||||||
| 
 |  | ||||||
| # 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=$?;; |  | ||||||
|     *) fail=1;; |  | ||||||
| esac |  | ||||||
| if [ -n "$fail" ]; then |  | ||||||
|     echo "Loading jwk to TPM2 failed" >&2 |  | ||||||
|     exit 1 |  | ||||||
| fi |  | ||||||
| tpm2_flushcontext -t |  | ||||||
| 
 |  | ||||||
| # 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=$?;; |  | ||||||
|     *) fail=1;; |  | ||||||
| esac |  | ||||||
| if [ -n "$fail" ]; then |  | ||||||
|     echo "Unsealing jwk from TPM failed" >&2 |  | ||||||
|     exit 1 |  | ||||||
| fi |  | ||||||
| tpm2_flushcontext -t |  | ||||||
| 
 |  | ||||||
| # Output the decrypted JWK along with the original header |  | ||||||
| (echo "$jwk$hdr."; /bin/cat) | jose jwe dec -k- -i- |  | ||||||
| 
 |  | ||||||
| # Exit with the status of the last command |  | ||||||
| exit $? |  | ||||||
|  | @ -9,6 +9,12 @@ summary="Encrypts using a TPM2.0 chip binding policy." | ||||||
| # TPM2.0 owner hierarchy to be used by the Operating System | # TPM2.0 owner hierarchy to be used by the Operating System | ||||||
| auth="o" | auth="o" | ||||||
| 
 | 
 | ||||||
|  | # Algorithm type for the TPM2 object with user-provided sensitive data | ||||||
|  | alg_create_key="keyedhash" | ||||||
|  | 
 | ||||||
|  | # Policy options for the TPM2 object | ||||||
|  | policy_options="" | ||||||
|  | 
 | ||||||
| # Attributes for the created TPM2 object with the JWK as sensitive data | # Attributes for the created TPM2 object with the JWK as sensitive data | ||||||
| obj_attr="fixedtpm|fixedparent|noda|adminwithpolicy" | obj_attr="fixedtpm|fixedparent|noda|adminwithpolicy" | ||||||
| 
 | 
 | ||||||
|  | @ -21,11 +27,7 @@ fi | ||||||
| # Display usage information if input is from a terminal | # Display usage information if input is from a terminal | ||||||
| if [ -t 0 ]; then | if [ -t 0 ]; then | ||||||
|     exec >&2 |     exec >&2 | ||||||
|     echo |     echo "Usage: zlevis-encrypt '{\"property\":\"value\"}' < tank.key > tank.jwe" | ||||||
|     echo "Usage: \"zlevis-encrypt '{\"property\":\"value\"}' < file.key > file.jwe\"" |  | ||||||
|     echo |  | ||||||
|     echo "Usage ZFS: \"zfs set tpm:jwe=\$(zlevis-encrypt '{\"property\":\"value\"}' < tank.key) <pool>\"" |  | ||||||
|     echo |  | ||||||
|     echo |     echo | ||||||
|     echo "$summary" |     echo "$summary" | ||||||
|     echo |     echo | ||||||
|  | @ -51,7 +53,7 @@ validate_pcrs() { | ||||||
|     _pcrs_r="" |     _pcrs_r="" | ||||||
|     case "${_tpm2_tools_v}" in |     case "${_tpm2_tools_v}" in | ||||||
|     4|5) _pcrs_r=$(tpm2_pcrread "${_pcr_bank}":"${_pcrs}" | grep -v "  ${_pcr_bank}")  || _fail=$?;; |     4|5) _pcrs_r=$(tpm2_pcrread "${_pcr_bank}":"${_pcrs}" | grep -v "  ${_pcr_bank}")  || _fail=$?;; | ||||||
|     *) _fail=1;; |     *) _fail=1 | ||||||
|     esac |     esac | ||||||
| 
 | 
 | ||||||
|     # Check for errors in PCR validation |     # Check for errors in PCR validation | ||||||
|  | @ -74,12 +76,13 @@ on_exit() { | ||||||
| tpm2tools_version=$(tpm2_createprimary -v | awk -F'version="' '{print $2}' | awk -F'.' '{print $1}') | tpm2tools_version=$(tpm2_createprimary -v | awk -F'version="' '{print $2}' | awk -F'.' '{print $1}') | ||||||
| 
 | 
 | ||||||
| # Check if the tpm2-tools version is supported | # Check if the tpm2-tools version is supported | ||||||
| if [ -z "$tpm2tools_version" ] || [ "$tpm2tools_version" -lt 4 ] || [ "$tpm2tools_version" -gt 5 ]; then | if [ -z "$tpm2tools_version" ] || [ $tpm2tools_version -lt 4 ] || [ $tpm2tools_version -gt 5 ]; then | ||||||
|     echo "The tpm2 pin requires a tpm2-tools version between 4 and 5" |     echo "The tpm2 pin requires a tpm2-tools version between 4 and 5" | ||||||
|     exit 1 |     exit 1 | ||||||
| fi | fi | ||||||
| 
 | 
 | ||||||
| # Create a temporary directory for TPM files | # Create a temporary directory for TPM files | ||||||
|  | mkdir -p "${tmpdir:-/tmp}" | ||||||
| if ! tmp="$(mktemp -d)"; then | if ! tmp="$(mktemp -d)"; then | ||||||
|     echo "Creating a temporary dir for TPM files failed" >&2 |     echo "Creating a temporary dir for TPM files failed" >&2 | ||||||
|     exit 1 |     exit 1 | ||||||
|  | @ -159,7 +162,6 @@ fi | ||||||
| tpm2_flushcontext -t | tpm2_flushcontext -t | ||||||
| 
 | 
 | ||||||
| # Handle PCRs and policy creation if PCR IDs are provided | # Handle PCRs and policy creation if PCR IDs are provided | ||||||
| policy_options="" |  | ||||||
| if [ -n "$pcr_ids" ]; then | if [ -n "$pcr_ids" ]; then | ||||||
|     if [ -z "$pcr_digest" ]; then |     if [ -z "$pcr_digest" ]; then | ||||||
|         case "$tpm2tools_version" in |         case "$tpm2tools_version" in | ||||||
|  |  | ||||||
|  | @ -1,25 +0,0 @@ | ||||||
| #!/bin/sh |  | ||||||
| 
 |  | ||||||
| # Exit immediately if a command exits with a non-zero status |  | ||||||
| set -e |  | ||||||
| 
 |  | ||||||
| # Check if zlevis-decrypt is present |  | ||||||
| command -v zlevis-decrypt > /dev/null || exit 1 |  | ||||||
| 
 |  | ||||||
| # Read ZFS dataset information. |  | ||||||
| zfs list -Ho name,encryption,keystatus,encryptionroot,tpm:jwe | while IFS=$'\t' read -r ds enc keystatus encroot jwe; do |  | ||||||
| 	# Check if the dataset is the encryption root. |  | ||||||
|     if [ "$ds" = "$encroot" ] && [ "$enc" != "off" ] && [ "$jwe" != "-" ]; then |  | ||||||
|         if [ "$keystatus" = "available" ]; then |  | ||||||
|             echo "Pool $ds already unlocked" |  | ||||||
|         else |  | ||||||
|             echo "Loading key for $ds" |  | ||||||
|             if echo -n "$jwe" | zlevis-decrypt | zfs load-key -L prompt "$ds"; then |  | ||||||
|                 echo "Unlocked $ds" |  | ||||||
|             else |  | ||||||
|                 echo "FAILED TO UNLOCK $ds" >&2 |  | ||||||
| 				exit 1 |  | ||||||
|             fi |  | ||||||
|         fi |  | ||||||
|     fi |  | ||||||
| done |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue