diff --git a/0015-support-sha256-algorithm.patch b/0015-support-sha256-algorithm.patch new file mode 100644 index 0000000..086517f --- /dev/null +++ b/0015-support-sha256-algorithm.patch @@ -0,0 +1,219 @@ +--- clevis-15.ori/src/pins/tang/clevis-decrypt-tang 2023-05-23 11:29:59.717465656 +0200 ++++ clevis-15/src/pins/tang/clevis-decrypt-tang 2023-05-23 11:49:02.950511503 +0200 +@@ -50,12 +50,30 @@ + exit 1 + fi + +-if ! srv="$(jose fmt -j- -Og clevis -g tang -g adv -Oo- <<< "$jhd" \ +- | jose jwk thp -i- -f "$kid")"; then ++if ! keys="$(jose fmt -j- -Og clevis -g tang -g adv -Oo- <<< "${jhd}")"; then + echo "JWE missing required 'clevis.tang.adv' header parameter!" >&2 + exit 1 + fi + ++# Check if the thumbprint we have in `kid' is in the advertised keys. ++CLEVIS_DEFAULT_THP_ALG=S1 # SHA-1 ++CLEVIS_ALTERNATIVE_THP_ALGS=S256 # SHA-256 ++ ++if ! srv="$(jose jwk thp -i- -f "${kid}" -a "${CLEVIS_DEFAULT_THP_ALG}" \ ++ <<< "${keys}")"; then ++ # `kid' thumprint not in the advertised keys, but it's possible it was ++ # generated using a different algorithm than the default one. ++ # Let us try the alternative supported algorithms to make sure `kid' ++ # really is not part of the advertised keys. ++ for alg in ${CLEVIS_ALTERNATIVE_THP_ALGS}; do ++ srv="$(jose jwk thp -i- -f "$kid" -a "${alg}" <<< "${keys}")" && break ++ done ++ if [ -z "${srv}" ]; then ++ echo "JWE header validation of 'clevis.tang.adv' failed: key thumbprint does not match" >&2 ++ exit 1 ++ fi ++fi ++ + if ! url="$(jose fmt -j- -Og clevis -g tang -g url -Su- <<< "$jhd")"; then + echo "JWE missing required 'clevis.tang.url' header parameter!" >&2 + exit 1 +--- clevis-15.ori/src/pins/tang/clevis-encrypt-tang 2020-10-28 19:55:47.673228700 +0100 ++++ clevis-15/src/pins/tang/clevis-encrypt-tang 2023-05-23 15:15:18.440099403 +0200 +@@ -64,6 +64,9 @@ + exit 1 + fi + ++CLEVIS_DEFAULT_THP_ALG=S1 # SHA-1 ++CLEVIS_ALTERNATIVE_THP_ALGS=S256 # SHA-256 ++ + trust= + [ -n "${2}" ] && [ "${2}" == "-y" ] && trust=yes + +@@ -111,15 +114,24 @@ + if [ -z "$thp" ]; then + echo "The advertisement contains the following signing keys:" >&2 + echo >&2 +- jose jwk thp -i- <<< "$ver" >&2 ++ jose jwk thp -i- -a "${CLEVIS_DEFAULT_THP_ALG}" <<< "$ver" >&2 + echo >&2 + read -r -p "Do you wish to trust these keys? [ynYN] " ans < /dev/tty + [[ "$ans" =~ ^[yY]$ ]] || exit 1 +- + elif [ "$thp" != "any" ] && \ +- ! jose jwk thp -i- -f "$thp" -o /dev/null <<< "$ver"; then +- echo "Trusted JWK '$thp' did not sign the advertisement!" >&2 +- exit 1 ++ ! jose jwk thp -i- -f "${thp}" -o /dev/null -a "${CLEVIS_DEFAULT_THP_ALG}" \ ++ <<< "$ver"; then ++ # Thumbprint of trusted JWK did not match the signature. Let's check ++ # alternative thumbprints generated with clevis supported hash ++ # algorithms to be sure. ++ for alg in ${CLEVIS_ALTERNATIVE_THP_ALGS}; do ++ srv="$(jose jwk thp -i- -f "${thp}" -a "${alg}" <<< "${ver}")" \ ++ && break ++ done ++ if [ -z "${srv}" ]; then ++ echo "Trusted JWK '$thp' did not sign the advertisement!" >&2 ++ exit 1 ++ fi + fi + fi + +@@ -138,7 +150,7 @@ + + jwk="$(jose fmt -j- -Od key_ops -o- <<< "$jwk")" + jwk="$(jose fmt -j- -Od alg -o- <<< "$jwk")" +-kid="$(jose jwk thp -i- <<< "$jwk")" ++kid="$(jose jwk thp -i- -a "${CLEVIS_DEFAULT_THP_ALG}" <<< "$jwk")" + jwe='{"protected":{"alg":"ECDH-ES","enc":"A256GCM","clevis":{"pin":"tang","tang":{}}}}' + jwe="$(jose fmt -j "$jwe" -g protected -q "$kid" -s kid -UUo-)" + jwe="$(jose fmt -j "$jwe" -g protected -g clevis -g tang -q "$url" -s url -UUUUo-)" +--- clevis-15.ori/src/luks/tests/meson.build 2023-05-23 11:29:59.594464890 +0200 ++++ clevis-15/src/luks/tests/meson.build 2023-05-23 12:00:10.811482757 +0200 +@@ -113,6 +113,7 @@ + test('report-sss-luks2', find_program('report-sss-luks2'), env: env, timeout: 120) + test('edit-tang-luks2', find_program('edit-tang-luks2'), env: env, timeout: 210) + test('pass-tang-luks2', find_program('pass-tang-luks2'), env: env, timeout: 60) ++ test('default-thp-alg', find_program('default-thp-alg'), env: env) + endif + + test('backup-restore-luks2', find_program('backup-restore-luks2'), env: env, timeout: 120) +--- clevis-15.ori/src/luks/tests/default-thp-alg 1970-01-01 01:00:00.000000000 +0100 ++++ clevis-15/src/luks/tests/default-thp-alg 2023-05-23 16:09:21.920385994 +0200 +@@ -0,0 +1,120 @@ ++#!/bin/bash ++set -exo pipefail ++# vim: set ts=8 shiftwidth=4 softtabstop=4 expandtab smarttab colorcolumn=80: ++# ++# Copyright (c) 2020 Red Hat, Inc. ++# Author: Sergio Correia ++# ++# 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 . ++ ++ ++. tests-common-functions ++ ++TEST=$(basename "${0}") ++ ++on_exit() { ++ exit_status=$? ++ tang_stop "${TMP}" ++ [ -d "${TMP}" ] && rm -rf "${TMP}" ++ exit "${exit_status}" ++} ++ ++trap 'on_exit' EXIT ++ ++TMP="$(mktemp -d)" ++ ++port=$(get_random_port) ++tang_run "${TMP}" "${port}" ++ ++url="http://localhost:${port}" ++data="just a sample text" ++ ++adv="${TMP}/adv" ++# Get the advertisement and extract the keys. ++tang_get_adv "${port}" "${adv}" ++ ++jwks="$(jose fmt --json="${adv}" --get payload --b64load --output=-)" ++enc="$(printf '%s' "${jwks}" | jose jwk use --input=- --required \ ++ --use deriveKey --output=-)" ++ ++jose fmt --json="${enc}" --get keys --array \ ++ || enc="$(printf '{"keys": [%s]}' "${enc}")" ++ ++jwk="$(jose fmt --json="${enc}" --get keys --array --foreach=- \ ++ | jose fmt --json=- --delete key_ops --delete alg --output=-)" ++ ++jwe_t='{"protected":{"alg":"ECDH-ES","enc":"A256GCM","clevis":{"pin":"tang","tang":{}}}}' ++jwe_t="$(jose fmt --json="${jwe_t}" --get protected --get clevis --get tang --quote "${url}" --set url -UUUUo-)" ++jwe_t="$(printf '%s' "${jwks}" | jose fmt --json="${jwe_t}" --get protected --get clevis --get tang --json=- --set adv -UUUUo-)" ++ ++# We currently support SHA-1 (legacy) and SHA-256. ++CLEVIS_SUPPORTED_THP_ALGS="S1 S256" ++# Now we will use every hash algorithm supported by jose to create a thumbprint ++# for `kid', then we do the encoding and verify clevis decrypt can decode it ++# correctly. ++for alg in ${CLEVIS_SUPPORTED_THP_ALGS}; do ++ kid="$(printf '%s' "${jwk}" | jose jwk thp -a "${alg}" --input=-)" ++ jwe="$(jose fmt --json="${jwe_t}" --get protected --quote "${kid}" -s kid -UUo-)" ++ ++ encoded=$(printf '%s%s' "${jwk}" "${data}" \ ++ | jose jwe enc --input="${jwe}" --key=- --detached=- --compact) ++ ++ if ! decoded="$(printf '%s' "${encoded}" | clevis decrypt)"; then ++ tang_error "${TEST}: decoding is expected to work (alg = ${alg})" ++ fi ++ ++ if [ "${decoded}" != "${data}" ]; then ++ tang_error "${TEST}: tang decrypt should have succeeded decoded[${decoded}] data[${data}] (alg = ${alg})" ++ fi ++done ++ ++# Now let's test encryption providing the thp in the configuration. ++data="just another test" ++for alg in ${CLEVIS_SUPPORTED_THP_ALGS}; do ++ thp="$(jose fmt --json="${adv}" -g payload -y -o- \ ++ | jose jwk use -i- -r -u verify -o- \ ++ | jose jwk thp -i- -a "${alg}")" ++ cfg="$(printf '{"url":"%s", "thp":"%s"}' "${url}" "${thp}")" ++ if ! encoded=$(printf '%s' "${data}" | clevis encrypt tang "${cfg}"); then ++ tang_error "${TEST}: tang encryption should have succeeded when providing the thp (${thp}) with any supported algorithm (${alg})" ++ fi ++ ++ if ! decoded="$(printf '%s' "${encoded}" | clevis decrypt)"; then ++ tang_error "${TEST}: decoding is expected to work (thp alg = ${alg})" ++ fi ++ ++ if [ "${decoded}" != "${data}" ]; then ++ tang_error "${TEST}: tang decrypt should have succeeded decoded[${decoded}] data[${data}] (alg = ${alg})" ++ fi ++done ++ ++# Let's also try some unsupported thp hash algorithms. ++UNSUPPORTED="S224 S384 S512" # SHA-224, SHA-384, SHA-512. ++for alg in ${UNSUPPORTED}; do ++ thp="$(jose fmt --json="${adv}" -g payload -y -o- \ ++ | jose jwk use -i- -r -u verify -o- \ ++ | jose jwk thp -i- -a "${alg}")" ++ cfg="$(printf '{"url":"%s", "thp":"%s"}' "${url}" "${thp}")" ++ if echo foo | clevis encrypt tang "${cfg}" >/dev/null; then ++ tang_error "${TEST}: tang encryption should have failed when providing the thp (${thp}) with an unsupported algorithm (${alg})" ++ fi ++done ++ ++# Now let's try some bad values for thp. ++for thp in "" "foo" "invalid"; do ++ cfg="$(printf '{"url":"%s", "thp":"%s"}' "${url}" "${thp}")" ++ if echo foo | clevis encrypt tang "${cfg}" >/dev/null; then ++ tang_error "${TEST}: tang encryption expected to fail when providing a bad thp" ++ fi ++done diff --git a/clevis.spec b/clevis.spec index 592ac6e..9f85e1e 100644 --- a/clevis.spec +++ b/clevis.spec @@ -2,7 +2,7 @@ Name: clevis Version: 15 -Release: 14%{?dist} +Release: 15%{?dist} Summary: Automated decryption framework License: GPLv3+ @@ -23,6 +23,7 @@ Patch0011: 0011-Improve-boot-performance-by-removing-key-check.patch Patch0012: 0012-ignore-empty-and-comment-lines-in-crypttab.patch Patch0013: 0013-luks-define-max-entropy-bits-for-pwmake.patch Patch0014: 0014-luks-edit-remove-unnecessary-redirection.patch +Patch0015: 0015-support-sha256-algorithm.patch BuildRequires: git BuildRequires: gcc @@ -203,6 +204,10 @@ systemctl preset %{name}-luks-askpass.path >/dev/null 2>&1 || : %attr(4755, root, root) %{_libexecdir}/%{name}-luks-udisks2 %changelog +* Tue May 23 2023 Sergio Arroutbi - 15-15 +- Include SHA-256 thumbprints clevis support + Resolves: rhbz#2209058 + * Mon Jan 16 2023 Sergio Arroutbi - 15-14 - luks-edit: remove unnecessary 2>/dev/null Resolves: rhbz#2159739