Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 37 additions & 0 deletions src/luks/clevis-luks-common-functions.in
Original file line number Diff line number Diff line change
Expand Up @@ -795,6 +795,31 @@ clevis_luks_luksmeta_sync_fix() {
luksmeta wipe -f -d "${DEV}" -s "${first_free_slot}"
}

# clevis_luks_get_hash() returns the hash algorithm used by a LUKS device.
clevis_luks_get_hash() {
local DEV="${1}"
[ -z "${DEV}" ] && return 1

local luks_type hash
luks_type=$(clevis_luks_type "${DEV}") || return 1

case "${luks_type}" in
luks1) hash=$(cryptsetup luksDump "${DEV}" 2>/dev/null \
| awk '/^Hash spec:[ \t]+/{print $3; exit}');;
luks2) hash=$(cryptsetup luksDump "${DEV}" 2>/dev/null \
| awk '/^[[:space:]]+[0-9]+: luks/{in_slot=1}
in_slot && /Hash:/{print $2; exit}');;
*) return 1;;
esac

# Validate: only allow alphanumeric characters, hyphens and underscores.
case "${hash}" in
*[!a-zA-Z0-9_-]*|"") return 1;;
esac

printf '%s\n' "${hash}"
}

# clevis_luks_add_key() adds a new key to a key slot.
clevis_luks_add_key() {
local DEV="${1}"
Expand All @@ -819,6 +844,12 @@ clevis_luks_add_key() {
fi
local pbkdf_args="--pbkdf pbkdf2 --pbkdf-force-iterations 1000"

local hash
hash=$(clevis_luks_get_hash "${DEV}")
if [ -n "${hash}" ]; then
pbkdf_args="${pbkdf_args} --hash ${hash}"
fi

printf '%s' "${input}" | cryptsetup luksAddKey --force-password --batch-mode \
--key-slot "${SLT}" \
"${DEV}" \
Expand Down Expand Up @@ -859,6 +890,12 @@ clevis_luks_update_key() {

local pbkdf_args="--pbkdf pbkdf2 --pbkdf-force-iterations 1000"

local hash
hash=$(clevis_luks_get_hash "${DEV}")
if [ -n "${hash}" ]; then
pbkdf_args="${pbkdf_args} --hash ${hash}"
fi

if [ -n "${in_place}" ]; then
printf '%s' "${input}" | cryptsetup luksChangeKey "${DEV}" \
--key-slot "${SLT}" \
Expand Down
64 changes: 64 additions & 0 deletions src/luks/tests/bind-hash-luks1
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
#!/bin/bash -ex
#
# Copyright (c) 2026 Red Hat, Inc.
# Author: Sergio Arroutbi <sarroutb@redhat.com>
#
# 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 <http://www.gnu.org/licenses/>.
#

TEST=$(basename "${0}")
. tests-common-functions

. clevis-luks-common-functions

on_exit() {
[ -d "${TMP}" ] && rm -rf "${TMP}"
}

trap 'on_exit' EXIT
trap 'exit' ERR

TMP="$(mktemp -d)"

ADV="${TMP}/adv.jws"
tang_create_adv "${TMP}" "${ADV}"
CFG="$(printf '{"url":"foobar","adv":"%s"}' "$ADV")"

# LUKS1 with sha512.
DEV="${TMP}/luks1-device-sha512"
new_device_hash "luks1" "${DEV}" "sha512"

# Verify the device was created with sha512.
hash_before=$(cryptsetup luksDump "${DEV}" \
| sed -rn 's|^Hash spec:\s+(\S+)$|\1|p')
if [ "${hash_before}" != "sha512" ]; then
error "${TEST}: Device should have been formatted with sha512, got ${hash_before}."
fi

if ! clevis luks bind -f -d "${DEV}" tang "${CFG}" <<< "${DEFAULT_PASS}"; then
error "${TEST}: Binding is expected to succeed."
fi

# Verify the clevis slot also uses sha512.
hash_after=$(cryptsetup luksDump "${DEV}" \
| sed -rn 's|^Hash spec:\s+(\S+)$|\1|p')
if [ "${hash_after}" != "sha512" ]; then
error "${TEST}: After binding, hash should be sha512, got ${hash_after}."
fi

# Also check individual key slot hash via clevis_luks_get_hash.
hash_fn=$(clevis_luks_get_hash "${DEV}")
if [ "${hash_fn}" != "sha512" ]; then
error "${TEST}: clevis_luks_get_hash should return sha512, got ${hash_fn}."
fi
70 changes: 70 additions & 0 deletions src/luks/tests/bind-hash-luks2
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
#!/bin/bash -ex
#
# Copyright (c) 2026 Red Hat, Inc.
# Author: Sergio Arroutbi <sarroutb@redhat.com>
#
# 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 <http://www.gnu.org/licenses/>.
#

TEST=$(basename "${0}")
. tests-common-functions

. clevis-luks-common-functions

on_exit() {
[ -d "${TMP}" ] && rm -rf "${TMP}"
}

trap 'on_exit' EXIT
trap 'exit' ERR

TMP="$(mktemp -d)"

ADV="${TMP}/adv.jws"
tang_create_adv "${TMP}" "${ADV}"
CFG="$(printf '{"url":"foobar","adv":"%s"}' "$ADV")"

# LUKS2 with sha512.
DEV="${TMP}/luks2-device-sha512"
if ! luks2_supported; then
skip_test "LUKS2 is not supported."
fi

new_device_hash "luks2" "${DEV}" "sha512"

# Verify the device was created with sha512.
hash_before=$(cryptsetup luksDump "${DEV}" \
| sed -rn 's|^\s+Hash:\s+(\S+)$|\1|p' | head -1)
if [ "${hash_before}" != "sha512" ]; then
error "${TEST}: Device should have been formatted with sha512, got ${hash_before}."
fi

if ! clevis luks bind -f -d "${DEV}" tang "${CFG}" <<< "${DEFAULT_PASS}"; then
error "${TEST}: Binding is expected to succeed."
fi

# After binding, check that the new clevis slot also uses sha512.
# For LUKS2, we check the hash of the clevis key slot (slot 1).
# LUKS2 luksDump format lists slots as " 1: luks2", not "Key Slot 1".
hash_slot1=$(cryptsetup luksDump "${DEV}" \
| awk '/^[[:space:]]+1: luks/{found=1} found && /Hash:/{print $2; exit}')
if [ "${hash_slot1}" != "sha512" ]; then
error "${TEST}: Clevis slot hash should be sha512, got ${hash_slot1}."
fi

# Also check via clevis_luks_get_hash.
hash_fn=$(clevis_luks_get_hash "${DEV}")
if [ "${hash_fn}" != "sha512" ]; then
error "${TEST}: clevis_luks_get_hash should return sha512, got ${hash_fn}."
fi
95 changes: 95 additions & 0 deletions src/luks/tests/edit-hash-luks1
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
#!/bin/bash -ex
#
# Copyright (c) 2026 Red Hat, Inc.
# Author: Sergio Arroutbi <sarroutb@redhat.com>
#
# 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 <http://www.gnu.org/licenses/>.

TEST=$(basename "${0}")
. tests-common-functions

. clevis-luks-common-functions

on_exit() {
local d
for d in "${TMP}" "${TMP2}"; do
[ ! -d "${d}" ] && continue
tang_stop "${d}"
rm -rf "${d}"
done
}

trap 'on_exit' EXIT
trap 'on_exit' ERR

TMP="$(mktemp -d)"

tang_run "${TMP}"
port=$(tang_get_port "${TMP}")

url="http://localhost:${port}"

cfg=$(printf '{"url":"%s"}' "${url}")

# LUKS1 with sha512.
DEV="${TMP}/luks1-device-sha512"
new_device_hash "luks1" "${DEV}" "sha512"

# Verify the device was created with sha512.
hash_before=$(cryptsetup luksDump "${DEV}" \
| sed -rn 's|^Hash spec:\s+(\S+)$|\1|p')
if [ "${hash_before}" != "sha512" ]; then
error "${TEST}: Device should have been formatted with sha512, got ${hash_before}."
fi

if ! clevis luks bind -y -d "${DEV}" tang "${cfg}" <<< "${DEFAULT_PASS}"; then
error "${TEST}: Bind should have succeeded."
fi

# Verify hash is still sha512 after binding.
hash_after_bind=$(cryptsetup luksDump "${DEV}" \
| sed -rn 's|^Hash spec:\s+(\S+)$|\1|p')
if [ "${hash_after_bind}" != "sha512" ]; then
error "${TEST}: After binding, hash should be sha512, got ${hash_after_bind}."
fi

# Now let's have another tang instance running and change the config to use
# the new one.
TMP2="$(mktemp -d)"
tang_run "${TMP2}"
port2=$(tang_get_port "${TMP2}")
new_url="http://localhost:${port2}"
new_cfg=$(printf '{"url":"%s"}' "${new_url}")

if ! clevis luks edit -d "${DEV}" -s 1 -c "${new_cfg}"; then
error "${TEST}: edit should have succeeded."
fi

# Verify hash is still sha512 after edit.
hash_after_edit=$(cryptsetup luksDump "${DEV}" \
| sed -rn 's|^Hash spec:\s+(\S+)$|\1|p')
if [ "${hash_after_edit}" != "sha512" ]; then
error "${TEST}: After edit, hash should be sha512, got ${hash_after_edit}."
fi

# Also check via clevis_luks_get_hash.
hash_fn=$(clevis_luks_get_hash "${DEV}")
if [ "${hash_fn}" != "sha512" ]; then
error "${TEST}: clevis_luks_get_hash should return sha512, got ${hash_fn}."
fi

# Make sure we can still unlock the device.
if ! clevis_luks_unlock_device "${DEV}" >/dev/null; then
error "${TEST}: we should have been able to unlock the device"
fi
100 changes: 100 additions & 0 deletions src/luks/tests/edit-hash-luks2
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
#!/bin/bash -ex
#
# Copyright (c) 2026 Red Hat, Inc.
# Author: Sergio Arroutbi <sarroutb@redhat.com>
#
# 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 <http://www.gnu.org/licenses/>.

TEST=$(basename "${0}")
. tests-common-functions

. clevis-luks-common-functions

on_exit() {
local d
for d in "${TMP}" "${TMP2}"; do
[ ! -d "${d}" ] && continue
tang_stop "${d}"
rm -rf "${d}"
done
}

trap 'on_exit' EXIT
trap 'on_exit' ERR

TMP="$(mktemp -d)"

# LUKS2.
if ! luks2_supported; then
skip_test "LUKS2 is not supported."
fi

tang_run "${TMP}"
port=$(tang_get_port "${TMP}")

url="http://localhost:${port}"

cfg=$(printf '{"url":"%s"}' "${url}")

# LUKS2 with sha512.
DEV="${TMP}/luks2-device-sha512"
new_device_hash "luks2" "${DEV}" "sha512"

# Verify the device was created with sha512.
hash_before=$(cryptsetup luksDump "${DEV}" \
| sed -rn 's|^\s+Hash:\s+(\S+)$|\1|p' | head -1)
if [ "${hash_before}" != "sha512" ]; then
error "${TEST}: Device should have been formatted with sha512, got ${hash_before}."
fi

if ! clevis luks bind -y -d "${DEV}" tang "${cfg}" <<< "${DEFAULT_PASS}"; then
error "${TEST}: Bind should have succeeded."
fi

# Verify the clevis slot (slot 1) uses sha512 after binding.
hash_after_bind=$(cryptsetup luksDump "${DEV}" \
| awk '/^[[:space:]]+1: luks/{found=1} found && /Hash:/{print $2; exit}')
if [ "${hash_after_bind}" != "sha512" ]; then
error "${TEST}: After binding, clevis slot hash should be sha512, got ${hash_after_bind}."
fi

# Now let's have another tang instance running and change the config to use
# the new one.
TMP2="$(mktemp -d)"
tang_run "${TMP2}"
port2=$(tang_get_port "${TMP2}")
new_url="http://localhost:${port2}"
new_cfg=$(printf '{"url":"%s"}' "${new_url}")

if ! clevis luks edit -d "${DEV}" -s 1 -c "${new_cfg}"; then
error "${TEST}: edit should have succeeded."
fi

# Verify the clevis slot (slot 1) still uses sha512 after edit.
hash_after_edit=$(cryptsetup luksDump "${DEV}" \
| awk '/^[[:space:]]+1: luks/{found=1} found && /Hash:/{print $2; exit}')
if [ "${hash_after_edit}" != "sha512" ]; then
error "${TEST}: After edit, clevis slot hash should be sha512, got ${hash_after_edit}."
fi

# Also check via clevis_luks_get_hash.
hash_fn=$(clevis_luks_get_hash "${DEV}")
if [ "${hash_fn}" != "sha512" ]; then
error "${TEST}: clevis_luks_get_hash should return sha512, got ${hash_fn}."
fi

# Make sure we can still unlock the device.
if ! clevis_luks_unlock_device "${DEV}" >/dev/null; then
error "${TEST}: we should have been able to unlock the device"
fi
Loading