From 158bdeda3ca961b0e615c8adfc58b61e1a1ba5c7 Mon Sep 17 00:00:00 2001 From: Sergio Correia Date: Wed, 13 May 2020 23:55:41 -0300 Subject: [PATCH 6/8] Add clevis luks regen command The clevis luks regen command regenerates the LUKS binding for a given device/slot, using the same configuration of the existing binding. Example: clevis luks list -d /dev/sda1 1: tang '{"url":"http://tang.server"}' 2: tpm2 '{"hash":"sha256","key":"ecc"}' To rotate the binding in slot 1, we can use the following: clevis luks regen -d /dev/sda1 -s 1 The new binding will use the existing configuration, namely: '{"url":"http://tang.server"}', with the `tang' pin. --- src/luks/clevis-luks-common-functions | 230 +++++++++++++++++++++++ src/luks/clevis-luks-pass | 5 +- src/luks/clevis-luks-regen | 185 ++++++++++++++++++ src/luks/clevis-luks-regen.1.adoc | 48 +++++ src/luks/meson.build | 3 + src/luks/tests/backup-restore-luks1 | 114 +++++++++++ src/luks/tests/backup-restore-luks2 | 115 ++++++++++++ src/luks/tests/meson.build | 6 + src/luks/tests/meson.build.orig | 110 +++++++++++ src/luks/tests/regen-inplace-luks1 | 98 ++++++++++ src/luks/tests/regen-inplace-luks2 | 99 ++++++++++ src/luks/tests/regen-not-inplace-luks1 | 95 ++++++++++ src/luks/tests/regen-not-inplace-luks2 | 96 ++++++++++ src/luks/tests/tests-common-functions.in | 26 +++ 14 files changed, 1228 insertions(+), 2 deletions(-) create mode 100755 src/luks/clevis-luks-regen create mode 100644 src/luks/clevis-luks-regen.1.adoc create mode 100755 src/luks/tests/backup-restore-luks1 create mode 100755 src/luks/tests/backup-restore-luks2 create mode 100644 src/luks/tests/meson.build.orig create mode 100755 src/luks/tests/regen-inplace-luks1 create mode 100755 src/luks/tests/regen-inplace-luks2 create mode 100755 src/luks/tests/regen-not-inplace-luks1 create mode 100755 src/luks/tests/regen-not-inplace-luks2 diff --git a/src/luks/clevis-luks-common-functions b/src/luks/clevis-luks-common-functions index 36f0bfd..5b515ad 100644 --- a/src/luks/clevis-luks-common-functions +++ b/src/luks/clevis-luks-common-functions @@ -325,3 +325,233 @@ clevis_luks_unlock_device() { return 1 } + +# Generate a key with the same entropy as the LUKS master key of a given +# device. +generate_key() { + local DEV="${1}" + + if [ -z "${DEV}" ]; then + echo "Please, specify a device." >&2 + return 1 + fi + + local dump + local filter + dump=$(cryptsetup luksDump "${DEV}") + if cryptsetup isLuks --type luks1 "${DEV}"; then + filter=$(sed -rn 's|MK bits:[ \t]*([0-9]+)|\1|p' <<< "${dump}") + elif cryptsetup isLuks --type luks2 "${DEV}"; then + filter=$(sed -rn 's|^\s+Key:\s+([0-9]+) bits\s*$|\1|p' <<< "${dump}") + else + echo "${DEV} is not a supported LUKS device!" >&2 + return 1 + fi + local bits + bits=$(sort -n <<< "${filter}" | tail -n 1) + pwmake "${bits}" +} + +# clevis_luks1_save_slot() works with LUKS1 devices and it saves a given JWE +# to a specific device and slot. The last parameter indicates whether we +# should overwrite existing metadata. +clevis_luks1_save_slot() { + local DEV="${1}" + local SLOT="${2}" + local JWE="${3}" + local OVERWRITE="${4}" + + ! luksmeta test -d "${DEV}" && return 1 + + local UUID="cb6e8904-81ff-40da-a84a-07ab9ab5715e" + if luksmeta load -d "${DEV}" -s "${SLOT}" -u "${UUID}" >/dev/null 2>/dev/null; then + [ -z "${OVERWRITE}" ] && return 1 + if ! luksmeta wipe -f -d "${DEV}" -s "${SLOT}" -u "${UUID}"; then + echo "Error wiping slot ${SLOT} from ${DEV}" >&2 + return 1 + fi + fi + + if ! echo -n "${jwe}" | luksmeta save -d "${DEV}" -s "${SLOT}" -u "${UUID}"; then + echo "Error saving metadata to LUKSMeta slot ${SLOT} from ${DEV}" >&2 + return 1 + fi + return 0 +} + +# clevis_luks2_save_slot() works with LUKS2 devices and it saves a given JWE +# to a specific device and slot. The last parameter indicates whether we +# should overwrite existing metadata. +clevis_luks2_save_slot() { + local DEV="${1}" + local SLOT="${2}" + local JWE="${3}" + local OVERWRITE="${4}" + + local dump token + dump="$(cryptsetup luksDump "${DEV}")" + if ! token="$(grep -E -B1 "^\s+Keyslot:\s+${SLOT}$" <<< "${dump}" \ + | sed -rn 's|^\s+([0-9]+): clevis|\1|p')"; then + echo "Error trying to read token from LUKS2 device ${DEV}, slot ${SLOT}" >&2 + return 1 + fi + + if [ -n "${token}" ]; then + [ -z "${OVERWRITE}" ] && return 1 + if ! cryptsetup token remove --token-id "${token}" "${DEV}"; then + echo "Error while removing token ${token} from LUKS2 device ${DEV}" >&2 + return 1 + fi + fi + + local metadata + metadata=$(printf '{"type":"clevis","keyslots":["%s"],"jwe":%s}' \ + "${SLOT}" "$(jose jwe fmt -i- <<< "${JWE}")") + if ! cryptsetup token import "${DEV}" <<< "${metadata}"; then + echo "Error saving metadata to LUKS2 header in device ${DEV}" >&2 + return 1 + fi + return 0 +} + +# clevis_luks_save_slot() saves a given JWE to a LUKS device+slot. It can also +# overwrite existing metadata. +clevis_luks_save_slot() { + local DEV="${1}" + local SLOT="${2}" + local JWE="${3}" + local OVERWRITE="${4}" + + if cryptsetup isLuks --type luks1 "${DEV}"; then + ! clevis_luks1_save_slot "${DEV}" "${SLOT}" "${JWE}" "${OVERWRITE}" \ + && return 1 + elif cryptsetup isLuks --type luks2 "${DEV}"; then + ! clevis_luks2_save_slot "${DEV}" "${SLOT}" "${JWE}" "${OVERWRITE}" \ + && return 1 + else + return 1 + fi + return 0 +} + +# clevis_luks1_backup_dev() backups the LUKSMeta slots from a LUKS device, +# which can be restored with clevis_luks1_restore_dev(). +clevis_luks1_backup_dev() { + local DEV="${1}" + local TMP="${2}" + + [ -z "${DEV}" ] && return 1 + [ -z "${TMP}" ] && return 1 + + local slots slt uuid jwe fname + readarray -t slots < <(cryptsetup luksDump "${DEV}" \ + | sed -rn 's|^Key Slot ([0-7]): ENABLED$|\1|p') + + for slt in "${slots[@]}"; do + if ! uuid=$(luksmeta show -d "${DEV}" -s "${slt}") \ + || [ -z "${uuid}" ]; then + continue + fi + if ! jwe=$(luksmeta load -d "${DEV}" -s "${slt}") \ + || [ -z "${jwe}" ]; then + continue + fi + + fname=$(printf "slot_%s_%s" "${slt}" "${uuid}") + printf "%s" "${jwe}" > "${TMP}/${fname}" + done + return 0 +} + +# clevis_luks1_restore_dev() takes care of restoring the LUKSMeta slots from +# a LUKS device that was backup'ed by clevis_luks1_backup_dev(). +clevis_luks1_restore_dev() { + local DEV="${1}" + local TMP="${2}" + + [ -z "${DEV}" ] && return 1 + [ -z "${TMP}" ] && return 1 + + local slt uuid jwe fname + for fname in "${TMP}"/slot_*; do + [ -f "${fname}" ] || break + if ! slt=$(echo "${fname}" | cut -d '_' -f 2) \ + || [ -z "${slt}" ]; then + continue + fi + if ! uuid=$(echo "${fname}" | cut -d '_' -f 3) \ + || [ -z "${uuid}" ]; then + continue + fi + if ! jwe=$(< "${fname}") || [ -z "${jwe}" ]; then + continue + fi + if ! clevis_luks1_save_slot "${DEV}" "${slt}" \ + "${jwe}" "overwrite"; then + echo "Error restoring LUKSmeta slot ${slt} from ${DEV}" >&2 + return 1 + fi + done + return 0 +} + +# clevis_luks_backup_dev() backups a particular LUKS device, which can then +# be restored with clevis_luks_restore_dev(). +clevis_luks_backup_dev() { + local DEV="${1}" + local TMP="${2}" + + [ -z "${DEV}" ] && return 1 + [ -z "${TMP}" ] && return 1 + + local HDR + HDR="${TMP}/$(basename "${DEV}").header" + if ! cryptsetup luksHeaderBackup "${DEV}" --batch-mode \ + --header-backup-file "${HDR}"; then + echo "Error backing up LUKS header from ${DEV}" >&2 + return 1 + fi + + # If LUKS1, we need to manually back up (and later restore) the + # LUKSmeta slots. For LUKS2, simply saving the header also saves + # the associated tokens. + if cryptsetup isLuks --type luks1 "${DEV}"; then + if ! clevis_luks1_backup_dev "${DEV}" "${TMP}"; then + return 1 + fi + fi + return 0 +} + +# clevis_luks_restore_dev() restores a given device that was backup'ed by +# clevis_luks_backup_dev(). +clevis_luks_restore_dev() { + local DEV="${1}" + local TMP="${2}" + + [ -z "${DEV}" ] && return 1 + [ -z "${TMP}" ] && return 1 + + local HDR + HDR="${TMP}/$(basename "${DEV}").header" + if [ ! -e "${HDR}" ]; then + echo "LUKS header backup does not exist" >&2 + return 1 + fi + + if ! cryptsetup luksHeaderRestore "${DEV}" --batch-mode \ + --header-backup-file "${HDR}"; then + echo "Error restoring LUKS header from ${DEV}" >&2 + return 1 + fi + + # If LUKS1, we need to manually back up (and later restore) the + # LUKSmeta slots. For LUKS2, simply saving the header also saves + # the associated tokens. + if cryptsetup isLuks --type luks1 "${DEV}"; then + if ! clevis_luks1_restore_dev "${DEV}" "${TMP}"; then + return 1 + fi + fi + return 0 +} diff --git a/src/luks/clevis-luks-pass b/src/luks/clevis-luks-pass index 1ce8c4c..d31bc17 100755 --- a/src/luks/clevis-luks-pass +++ b/src/luks/clevis-luks-pass @@ -63,7 +63,8 @@ if ! jwe=$(clevis_luks_read_slot "${DEV}" "${SLT}" 2>/dev/null); then exit 1 fi -if ! clevis decrypt < <(echo -n "${jwe}"); then - echo "It was not possible to decrypt the passphrase associated to slot ${SLT} in {DEV}!" >&2 +if ! passphrase=$(clevis decrypt < <(echo -n "${jwe}") 2>/dev/null); then + echo "It was not possible to decrypt the passphrase associated to slot ${SLT} in ${DEV}!" >&2 exit 1 fi +echo -n "${passphrase}" diff --git a/src/luks/clevis-luks-regen b/src/luks/clevis-luks-regen new file mode 100755 index 0000000..44fd673 --- /dev/null +++ b/src/luks/clevis-luks-regen @@ -0,0 +1,185 @@ +#!/usr/bin/bash +# vim: set tabstop=8 shiftwidth=4 softtabstop=4 expandtab smarttab colorcolumn=80: +# +# Copyright (c) 2018 Red Hat, Inc. +# Author: Radovan Sroka +# 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 . +# + +. clevis-luks-common-functions + +SUMMARY="Regenerate LUKS metadata" + +if [ "$1" == "--summary" ]; then + echo "$SUMMARY" + exit 0 +fi + +function usage_and_exit () { + exec >&2 + echo "Usage: clevis luks regen -d DEV -s SLOT" + echo + echo "$SUMMARY" + echo + echo " -d DEV The LUKS device on which to perform rebinding" + echo + echo " -s SLT The LUKS slot to use" + echo + exit "${1}" +} + +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 +} + +while getopts ":hfd:s:" o; do + case "$o" in + d) DEV="$OPTARG";; + h) usage_and_exit 0;; + s) SLT="$OPTARG";; + *) usage_and_exit 1;; + esac +done + +if [ -z "$DEV" ]; then + echo "Did not specify a device!" >&2 + exit 1 +fi + +if [ -z "$SLT" ]; then + echo "Did not specify a slot!" >&2 + exit 1 +fi + +### ---------------------------------------------------------------------- +if ! pin_cfg=$(clevis luks list -d "${DEV}" -s "${SLT}" 2>/dev/null); then + echo "Error obtaining current configuration of device ${DEV}:${SLT}" >&2 + exit 1 +fi + +PIN=$(echo "${pin_cfg}" | awk '{ print $2 }') +CFG=$(echo "${pin_cfg}" | awk '{ print $3 }' | tr -d "'") + +echo "Regenerating with:" +echo "PIN: $PIN" +echo "CONFIG: $CFG" + +trap 'echo "Ignoring CONTROL-C!"' INT TERM + +# Get the existing key. +if ! existing_key=$(clevis luks pass -d "${DEV}" -s "${SLT}" 2>/dev/null); then + # We failed to obtain the passphrase for the slot -- perhaps + # it was rotated? --, so let's request user input. + read -r -s -p "Enter existing LUKS password: " existing_key; echo +fi + +# Check if the key is valid. +if ! cryptsetup open --test-passphrase "${DEV}" <<< "${existing_key}"; then + exit 1 +fi + +# Check if we can do the update in-place, i.e., if the key we got is the one +# for the slot we are interested in. +in_place= +if cryptsetup open --test-passphrase --key-slot "${SLT}" "${DEV}" \ + <<< "${existing_key}"; then + in_place=true +fi + +# Create new key. +if ! new_passphrase=$(generate_key "${DEV}"); then + echo "Error generating new key for device ${DEV}" >&2 + exit 1 +fi + +# Reencrypt the new password. +if ! jwe=$(clevis encrypt "${PIN}" "${CFG}" <<< "${new_passphrase}"); then + echo "Error using pin '${PIN}' with config '${CFG}'" >&2 + exit 1 +fi + +# Updating the metadata and the actual passphrase are destructive operations, +# hence we will do a backup of the LUKS header and restore it later in case +# we have issues performing these operations. +if ! TMP="$(mktemp -d)"; then + echo "Creating a temporary dir for device backup/restore failed!" >&2 + exit 1 +fi +trap 'on_exit' EXIT + +# Backup LUKS header. +if ! clevis_luks_backup_dev "${DEV}" "${TMP}"; then + echo "Error while trying to back up LUKS header from ${DEV}" >&2 + exit 1 +fi + +restore_device() { + local DEV="${1}" + local TMP="${2}" + + if ! clevis_luks_restore_dev "${DEV}" "${TMP}"; then + echo "Error while trying to restore LUKS header from ${DEV}." >&2 + else + echo "LUKS header restored successfully." >&2 + fi +} + +# Update the key slot with the new key. If we have the key for this slot, +# the change happens in-place. Otherwise, we kill the slot and re-add it. +if [ -n "${in_place}" ]; then + if ! cryptsetup luksChangeKey "${DEV}" --key-slot "${SLT}" \ + <(echo -n "${new_passphrase}") <<< "${existing_key}"; then + echo "Error updating LUKS passphrase in ${DEV}:${SLT}" >&2 + restore_device "${DEV}" "${TMP}" + exit 1 + fi +else + if ! cryptsetup luksKillSlot --batch-mode "${DEV}" "${SLT}"; then + echo "Error wiping slot ${SLT} from ${DEV}" >&2 + restore_device "${DEV}" "${TMP}" + exit 1 + fi + + if ! echo -n "${new_passphrase}" \ + | cryptsetup luksAddKey --key-slot "${SLT}" \ + --key-file <(echo -n "${existing_key}") "${DEV}"; then + echo "Error updating LUKS passphrase in ${DEV}:${SLT}." >&2 + restore_device "${DEV}" "${TMP}" + exit 1 + fi +fi + +# Update the metadata. +if ! clevis_luks_save_slot "${DEV}" "${SLT}" "${jwe}" "overwrite"; then + echo "Error updating metadata in ${DEV}:${SLT}" >&2 + restore_device "${DEV}" "${TMP}" + exit 1 +fi + +# Now make sure that we can unlock this device after the change. +# If we can't, undo the changes. +if ! cryptsetup open --test-passphrase --key-slot "${SLT}" "${DEV}" 2>/dev/null \ + <<< $(clevis luks pass -d "${DEV}" -s "${SLT}" 2>/dev/null); then + echo "Invalid configuration detected after rebinding. Reverting changes." + restore_device "${DEV}" "${TMP}" + exit 1 +fi + +echo "Keys were succesfully rotated." diff --git a/src/luks/clevis-luks-regen.1.adoc b/src/luks/clevis-luks-regen.1.adoc new file mode 100644 index 0000000..763fa1e --- /dev/null +++ b/src/luks/clevis-luks-regen.1.adoc @@ -0,0 +1,48 @@ +CLEVIS-LUKS-REGEN(1) +===================== +:doctype: manpage + + +== NAME + +clevis-luks-regen - Regenerates LUKS binding + +== SYNOPSIS + +*clevis luks regen* -d DEV -s SLT + +== OVERVIEW + +The *clevis luks regen* command regenerates the LUKS binding for a given slot in a LUKS device, using the same configuration of the +existing binding. Its operation can be compared to performing *clevis luks unbind* and *clevis luks bind* for rebinding said slot and device. +This is useful when rotating keys. + +== OPTIONS + +* *-d* _DEV_ : + The bound LUKS device + +* *-s* _SLT_ : + The slot or key slot number for rebinding. Note that it requires that such slot is currently bound by clevis. + +== EXAMPLE + + Let's start by using clevis luks list to see the current binding configuration in /dev/sda1: + + # clevis luks list -d /dev/sda1 + 1: tang '{"url":"http://tang.server"}' + 2: tpm2 '{"hash":"sha256","key":"ecc"}' + + We see that slot 1 in /dev/sda1 has a tang binding with the following configuration: + '{"url":"http://tang.server"}' + + Now let's do the rebinding of slot 1: + # clevis luks regen -d /dev/sda1 -s 1 + + After a successful operation, we will have the new binding using the same configuration that was already in place. + +== SEE ALSO + +link:clevis-luks-list.1.adoc[*clevis-luks-list*(1)] +link:clevis-luks-bind.1.adoc[*clevis-luks-bind*(1)] +link:clevis-luks-unbind.1.adoc[*clevis-luks-unbind*(1)] diff --git a/src/luks/meson.build b/src/luks/meson.build index fda2ca8..f21388d 100644 --- a/src/luks/meson.build +++ b/src/luks/meson.build @@ -44,6 +44,9 @@ if libcryptsetup.found() and luksmeta.found() and pwmake.found() bins += join_paths(meson.current_source_dir(), 'clevis-luks-pass') mans += join_paths(meson.current_source_dir(), 'clevis-luks-pass.1') + + bins += join_paths(meson.current_source_dir(), 'clevis-luks-regen') + mans += join_paths(meson.current_source_dir(), 'clevis-luks-regen.1') else warning('Will not install LUKS support due to missing dependencies!') endif diff --git a/src/luks/tests/backup-restore-luks1 b/src/luks/tests/backup-restore-luks1 new file mode 100755 index 0000000..733a4b6 --- /dev/null +++ b/src/luks/tests/backup-restore-luks1 @@ -0,0 +1,114 @@ +#!/bin/bash -x +# vim: set tabstop=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 . +# + +TEST="${0}" +. tests-common-functions +. clevis-luks-common-functions + +function on_exit() { + if [ "$PID" ]; then kill $PID; wait $PID || true; fi + [ -d "$TMP" ] && rm -rf $TMP +} + +trap 'on_exit' EXIT +trap 'exit' ERR + +export TMP=$(mktemp -d) +mkdir -p "${TMP}/db" + +# Generate the server keys +KEYS="$TMP/db" +tangd-keygen $TMP/db sig exc +if which tangd-update; then + mkdir -p "${TMP}/cache" + tangd-update "${TMP}/db" "${TMP}/cache" + KEYS="${TMP}/cache" +fi + +# Start the server. +port=$(shuf -i 1024-65536 -n 1) +"${SD_ACTIVATE}" --inetd -l 127.0.0.1:"${port}" -a tangd "${KEYS}" & +export PID=$! +sleep 0.25 + +url="http://localhost:${port}" +adv="${TMP}/adv" +curl "${url}/adv" -o "${adv}" + +cfg=$(printf '{"url":"%s","adv":"%s"}' "$url" "$adv") + +# LUKS1. +DEV="${TMP}/luks1-device" +new_device "luks1" "${DEV}" + +SLT=5 +if ! clevis luks bind -f -s "${SLT}" -d "${DEV}" tang "${cfg}" <<< "${DEFAULT_PASS}"; then + error "${TEST}: Bind should have succeeded." +fi + +ORIG_DEV="${TMP}/device.orig" +# Let's save it for comparison later. +cp -f "${DEV}" "${ORIG_DEV}" + +# Now let's backup and restore. +if ! clevis_luks_backup_dev "${DEV}" "${TMP}"; then + error "${TEST}: backup of ${DEV} failed." +fi + +# Now let's remove both the binding and the initial passphrase. +if ! clevis luks unbind -f -s "${SLT}" -d "${DEV}" <<< "${DEFAULT_PASS}"; then + error "${TEST}: unbind of slot ${SLT} in ${DEV} failed." +fi + +if ! cryptsetup luksRemoveKey --batch-mode "${DEV}" <<< "${DEFAULT_PASS}"; then + error "${TEST}: error removing the default password from ${DEV}." +fi + +# Making sure we have no slots enabled. +enabled=$(cryptsetup luksDump "${DEV}" | grep ENABLED | wc -l) +if [ "${enabled}" -ne 0 ]; then + error "${TEST}: we should not have any enabled (${enabled}) slots." +fi + +# Now we can restore it. +if ! clevis_luks_restore_dev "${DEV}" "${TMP}"; then + error "${TEST}: error restoring ${DEV}." +fi + +# And compare whether they are the same. +if ! cmp --silent "${ORIG_DEV}" "${DEV}"; then + error "${TEST}: the device differs from the original one after the restore." +fi + +# And making sure both the default passphrase and the binding work. +if ! cryptsetup open --test-passphrase "${DEV}" <<< "${DEFAULT_PASS}"; then + error "${TEST}: the default passphrase for ${DEV} did no work." +fi + +TEST_DEV="test-device-${RANDOM}" +if ! clevis luks unlock -d "${DEV}" -n "${TEST_DEV}"; then + error "${TEST}: we were unable to unlock ${DEV}." +fi + +cryptsetup close "${TEST_DEV}" + +kill -9 "${PID}" +! wait "${PID}" +unset PID diff --git a/src/luks/tests/backup-restore-luks2 b/src/luks/tests/backup-restore-luks2 new file mode 100755 index 0000000..a3b8608 --- /dev/null +++ b/src/luks/tests/backup-restore-luks2 @@ -0,0 +1,115 @@ +#!/bin/bash -x +# vim: set tabstop=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 . +# + +TEST="${0}" +. tests-common-functions +. clevis-luks-common-functions + +function on_exit() { + if [ "$PID" ]; then kill $PID; wait $PID || true; fi + [ -d "$TMP" ] && rm -rf $TMP +} + +trap 'on_exit' EXIT +trap 'exit' ERR + +export TMP=$(mktemp -d) +mkdir -p "${TMP}/db" + +# Generate the server keys +KEYS="$TMP/db" +tangd-keygen $TMP/db sig exc +if which tangd-update; then + mkdir -p "${TMP}/cache" + tangd-update "${TMP}/db" "${TMP}/cache" + KEYS="${TMP}/cache" +fi + +# Start the server. +port=$(shuf -i 1024-65536 -n 1) +"${SD_ACTIVATE}" --inetd -l 127.0.0.1:"${port}" -a tangd "${KEYS}" & +export PID=$! +sleep 0.25 + +url="http://localhost:${port}" +adv="${TMP}/adv" +curl "${url}/adv" -o "${adv}" + +cfg=$(printf '{"url":"%s","adv":"%s"}' "$url" "$adv") + +# LUKS2. +DEV="${TMP}/luks2-device" +new_device "luks2" "${DEV}" + +SLT=5 +if ! clevis luks bind -f -s "${SLT}" -d "${DEV}" tang "${cfg}" <<< "${DEFAULT_PASS}"; then + error "${TEST}: Bind should have succeeded." +fi + +ORIG_DEV="${TMP}/device.orig" +# Let's save it for comparison later. +cp -f "${DEV}" "${ORIG_DEV}" + +# Now let's backup and restore. +if ! clevis_luks_backup_dev "${DEV}" "${TMP}"; then + error "${TEST}: backup of ${DEV} failed." +fi + +# Now let's remove both the binding and the initial passphrase. +if ! clevis luks unbind -f -s "${SLT}" -d "${DEV}" <<< "${DEFAULT_PASS}"; then + error "${TEST}: unbind of slot ${SLT} in ${DEV} failed." +fi + +if ! cryptsetup luksRemoveKey --batch-mode "${DEV}" <<< "${DEFAULT_PASS}"; then + error "${TEST}: error removing the default password from ${DEV}." +fi + +# Making sure we have no slots enabled. +enabled=$(cryptsetup luksDump "${DEV}" \ + | sed -rn 's|^\s+([0-9]+): luks2$|\1|p' | wc -l) +if [ "${enabled}" -ne 0 ]; then + error "${TEST}: we should not have any enabled (${enabled}) slots." +fi + +# Now we can restore it. +if ! clevis_luks_restore_dev "${DEV}" "${TMP}"; then + error "${TEST}: error restoring ${DEV}." +fi + +# And compare whether they are the same. +if ! cmp --silent "${ORIG_DEV}" "${DEV}"; then + error "${TEST}: the device differs from the original one after the restore." +fi + +# And making sure both the default passphrase and the binding work. +if ! cryptsetup open --test-passphrase "${DEV}" <<< "${DEFAULT_PASS}"; then + error "${TEST}: the default passphrase for ${DEV} did no work." +fi + +TEST_DEV="test-device-${RANDOM}" +if ! clevis luks unlock -d "${DEV}" -n "${TEST_DEV}"; then + error "${TEST}: we were unable to unlock ${DEV}." +fi + +cryptsetup close "${TEST_DEV}" + +kill -9 "${PID}" +! wait "${PID}" +unset PID diff --git a/src/luks/tests/meson.build b/src/luks/tests/meson.build index 4757c4b..dbef9bf 100644 --- a/src/luks/tests/meson.build +++ b/src/luks/tests/meson.build @@ -87,6 +87,9 @@ if has_tang test('unlock-tang-luks1', find_program('unlock-tang-luks1'), env: env, timeout: 90) endif test('pass-tang-luks1', find_program('pass-tang-luks1'), env: env) +test('backup-restore-luks1', find_program('backup-restore-luks1'), env: env) +test('regen-inplace-luks1', find_program('regen-inplace-luks1'), env: env, timeout: 90) +test('regen-not-inplace-luks1', find_program('regen-not-inplace-luks1'), env: env, timeout: 90) # LUKS2 tests go here, and they get included if we get support for it, based # on the cryptsetup version. @@ -107,4 +110,7 @@ if luksmeta_data.get('OLD_CRYPTSETUP') == '0' test('unlock-tang-luks2', find_program('unlock-tang-luks2'), env: env, timeout: 120) endif test('pass-tang-luks2', find_program('pass-tang-luks2'), env: env, timeout: 60) + test('backup-restore-luks2', find_program('backup-restore-luks2'), env:env, timeout: 90) + test('regen-inplace-luks2', find_program('regen-inplace-luks2'), env: env, timeout: 90) + test('regen-not-inplace-luks2', find_program('regen-not-inplace-luks2'), env: env, timeout: 90) endif diff --git a/src/luks/tests/meson.build.orig b/src/luks/tests/meson.build.orig new file mode 100644 index 0000000..4757c4b --- /dev/null +++ b/src/luks/tests/meson.build.orig @@ -0,0 +1,110 @@ +actv = find_program( + 'systemd-socket-activate', + 'systemd-activate', + required: false +) + +# We use jq for comparing the pin config in the clevis luks list tests. +jq = find_program('jq', required: false) + +# we use systemd-socket-activate for running test tang servers. +actv = find_program( + 'systemd-socket-activate', + 'systemd-activate', + required: false +) + +kgen = find_program( + join_paths(libexecdir, 'tangd-keygen'), + join_paths(get_option('prefix'), get_option('libdir'), 'tangd-keygen'), + join_paths(get_option('prefix'), get_option('libexecdir'), 'tangd-keygen'), + join_paths('/', 'usr', get_option('libdir'), 'tangd-keygen'), + join_paths('/', 'usr', get_option('libexecdir'), 'tangd-keygen'), + required: false +) +tang = find_program( + join_paths(libexecdir, 'tangd'), + join_paths(get_option('prefix'), get_option('libdir'), 'tangd'), + join_paths(get_option('prefix'), get_option('libexecdir'), 'tangd'), + join_paths('/', 'usr', get_option('libdir'), 'tangd'), + join_paths('/', 'usr', get_option('libexecdir'), 'tangd'), + required: false +) + +common_functions = configure_file(input: 'tests-common-functions.in', + output: 'tests-common-functions', + configuration: luksmeta_data, + install: false +) + +env = environment() +env.prepend('PATH', + join_paths(meson.source_root(), 'src'), + join_paths(meson.source_root(), 'src', 'luks'), + join_paths(meson.source_root(), 'src', 'pins', 'sss'), + join_paths(meson.source_root(), 'src', 'pins', 'tang'), + join_paths(meson.source_root(), 'src', 'pins', 'tpm2'), + meson.current_source_dir(), + meson.current_build_dir(), + join_paths(meson.build_root(), 'src'), + join_paths(meson.build_root(), 'src', 'luks'), + join_paths(meson.build_root(), 'src', 'pins', 'sss'), + join_paths(meson.build_root(), 'src', 'pins', 'tang'), + join_paths(meson.build_root(), 'src', 'pins', 'tpm2'), + libexecdir, + '/usr/libexec', + separator: ':' +) +env.set('SD_ACTIVATE', actv.path()) + +has_tang = false +if actv.found() and kgen.found() and tang.found() + has_tang = true + env.set('SD_ACTIVATE', actv.path()) + env.set('TANGD_KEYGEN', kgen.path()) + env.set('TANGD', tang.path()) +endif + +test('bind-wrong-pass-luks1', find_program('bind-wrong-pass-luks1'), env: env) +test('bind-luks1', find_program('bind-luks1'), env: env) +test('unbind-unbound-slot-luks1', find_program('unbind-unbound-slot-luks1'), env: env) +test('unbind-luks1', find_program('unbind-luks1'), env: env) +test('bind-key-file-non-interactive', find_program('bind-key-file-non-interactive-luks1'), env: env) +test('bind-pass-with-newline', find_program('bind-pass-with-newline-luks1'), env: env) +test('bind-pass-with-newline-keyfile', find_program('bind-pass-with-newline-keyfile-luks1'), env: env) +# Bug #70. +test('bind-already-used-luksmeta-slot', find_program('bind-already-used-luksmeta-slot'), env: env, timeout: 60) + +if jq.found() + test('list-recursive-luks1', find_program('list-recursive-luks1'), env: env) + test('list-tang-luks1', find_program('list-tang-luks1'), env: env) + test('list-sss-tang-luks1', find_program('list-sss-tang-luks1'), env: env) +else + warning('Will not run "clevis luks list" tests due to missing jq dependency') +endif + +if has_tang + test('unlock-tang-luks1', find_program('unlock-tang-luks1'), env: env, timeout: 90) +endif +test('pass-tang-luks1', find_program('pass-tang-luks1'), env: env) + +# LUKS2 tests go here, and they get included if we get support for it, based +# on the cryptsetup version. +# Binding LUKS2 takes longer, so timeout is increased for a few tests. +if luksmeta_data.get('OLD_CRYPTSETUP') == '0' + test('bind-wrong-pass-luks2', find_program('bind-wrong-pass-luks2'), env: env) + test('bind-luks2', find_program('bind-luks2'), env: env, timeout: 60) + test('unbind-unbound-slot-luks2', find_program('unbind-unbound-slot-luks2'), env: env) + test('unbind-luks2', find_program('unbind-luks2'), env: env, timeout: 60) + + if jq.found() + test('list-recursive-luks2', find_program('list-recursive-luks2'), env: env, timeout: 60) + test('list-tang-luks2', find_program('list-tang-luks2'), env: env, timeout: 60) + test('list-sss-tang-luks2', find_program('list-sss-tang-luks2'), env: env, timeout: 60) + endif + + if has_tang + test('unlock-tang-luks2', find_program('unlock-tang-luks2'), env: env, timeout: 120) + endif + test('pass-tang-luks2', find_program('pass-tang-luks2'), env: env, timeout: 60) +endif diff --git a/src/luks/tests/regen-inplace-luks1 b/src/luks/tests/regen-inplace-luks1 new file mode 100755 index 0000000..3a42ced --- /dev/null +++ b/src/luks/tests/regen-inplace-luks1 @@ -0,0 +1,98 @@ +#!/bin/bash -x +# vim: set tabstop=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 . +# + +TEST="${0}" +. tests-common-functions + +function on_exit() { + if [ "$PID" ]; then kill $PID; wait $PID || true; fi + [ -d "$TMP" ] && rm -rf $TMP +} + +trap 'on_exit' EXIT +trap 'exit' ERR + +export TMP=$(mktemp -d) +mkdir -p "${TMP}/db" + +# Generate the server keys +KEYS="$TMP/db" +tangd-keygen $TMP/db sig exc +if which tangd-update; then + mkdir -p "${TMP}/cache" + tangd-update "${TMP}/db" "${TMP}/cache" + KEYS="${TMP}/cache" +fi + +# Start the server. +port=$(shuf -i 1024-65536 -n 1) +"${SD_ACTIVATE}" --inetd -l 127.0.0.1:"${port}" -a tangd "${KEYS}" & +export PID=$! +sleep 0.25 + +url="http://localhost:${port}" +adv="${TMP}/adv" +curl "${url}/adv" -o "${adv}" + +cfg=$(printf '{"url":"%s","adv":"%s"}' "$url" "$adv") + +# LUKS1. +DEV="${TMP}/luks1-device" +new_device "luks1" "${DEV}" + +SLT=1 +if ! clevis luks bind -f -s "${SLT}" -d "${DEV}" tang "${cfg}" <<< "${DEFAULT_PASS}"; then + error "${TEST}: Bind should have succeeded." +fi + +# Now let's remove the initial passphrase. +if ! cryptsetup luksRemoveKey --batch-mode "${DEV}" <<< "${DEFAULT_PASS}"; then + error "${TEST}: error removing the default password from ${DEV}." +fi + +# Making sure we have a single slot enabled. +enabled=$(cryptsetup luksDump "${DEV}" | grep ENABLED | wc -l) +if [ "${enabled}" -ne 1 ]; then + error "${TEST}: we should have only one slot enabled (${enabled})." +fi + +old_key=$(clevis luks pass -d "${DEV}" -s "${SLT}") + +# Now let's try regen. +if ! clevis_regen "${DEV}" "${SLT}" "${DEFAULT_PASS}"; then + error "${TEST}: clevis luks regen failed" +fi + +new_key=$(clevis luks pass -d "${DEV}" -s "${SLT}") + +if [ "${old_key}" = "${new_key}" ]; then + error "${TEST}: the passphrases should be different" +fi + +TEST_DEV="test-device-${RANDOM}" +if ! clevis luks unlock -d "${DEV}" -n "${TEST_DEV}"; then + error "${TEST}: we were unable to unlock ${DEV}." +fi + +cryptsetup close "${TEST_DEV}" + +kill -9 "${PID}" +! wait "${PID}" +unset PID diff --git a/src/luks/tests/regen-inplace-luks2 b/src/luks/tests/regen-inplace-luks2 new file mode 100755 index 0000000..1cb7a29 --- /dev/null +++ b/src/luks/tests/regen-inplace-luks2 @@ -0,0 +1,99 @@ +#!/bin/bash -x +# vim: set tabstop=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 . +# + +TEST="${0}" +. tests-common-functions + +function on_exit() { + if [ "$PID" ]; then kill $PID; wait $PID || true; fi + [ -d "$TMP" ] && rm -rf $TMP +} + +trap 'on_exit' EXIT +trap 'exit' ERR + +export TMP=$(mktemp -d) +mkdir -p "${TMP}/db" + +# Generate the server keys +KEYS="$TMP/db" +tangd-keygen $TMP/db sig exc +if which tangd-update; then + mkdir -p "${TMP}/cache" + tangd-update "${TMP}/db" "${TMP}/cache" + KEYS="${TMP}/cache" +fi + +# Start the server. +port=$(shuf -i 1024-65536 -n 1) +"${SD_ACTIVATE}" --inetd -l 127.0.0.1:"${port}" -a tangd "${KEYS}" & +export PID=$! +sleep 0.25 + +url="http://localhost:${port}" +adv="${TMP}/adv" +curl "${url}/adv" -o "${adv}" + +cfg=$(printf '{"url":"%s","adv":"%s"}' "$url" "$adv") + +# LUKS2. +DEV="${TMP}/luks2-device" +new_device "luks2" "${DEV}" + +SLT=1 +if ! clevis luks bind -f -s "${SLT}" -d "${DEV}" tang "${cfg}" <<< "${DEFAULT_PASS}"; then + error "${TEST}: Bind should have succeeded." +fi + +# Now let's remove the initial passphrase. +if ! cryptsetup luksRemoveKey --batch-mode "${DEV}" <<< "${DEFAULT_PASS}"; then + error "${TEST}: error removing the default password from ${DEV}." +fi + +# Making sure we have a single slot enabled. +enabled=$(cryptsetup luksDump "${DEV}" \ + | sed -rn 's|^\s+([0-9]+): luks2$|\1|p' | wc -l) +if [ "${enabled}" -ne 1 ]; then + error "${TEST}: we should have only one slot enabled (${enabled})." +fi + +old_key=$(clevis luks pass -d "${DEV}" -s "${SLT}") + +# Now let's try regen. +if ! clevis_regen "${DEV}" "${SLT}" "${DEFAULT_PASS}"; then + error "${TEST}: clevis luks regen failed" +fi + +new_key=$(clevis luks pass -d "${DEV}" -s "${SLT}") + +if [ "${old_key}" = "${new_key}" ]; then + error "${TEST}: the passphrases should be different" +fi + +TEST_DEV="test-device-${RANDOM}" +if ! clevis luks unlock -d "${DEV}" -n "${TEST_DEV}"; then + error "${TEST}: we were unable to unlock ${DEV}." +fi + +cryptsetup close "${TEST_DEV}" + +kill -9 "${PID}" +! wait "${PID}" +unset PID diff --git a/src/luks/tests/regen-not-inplace-luks1 b/src/luks/tests/regen-not-inplace-luks1 new file mode 100755 index 0000000..1b65ca7 --- /dev/null +++ b/src/luks/tests/regen-not-inplace-luks1 @@ -0,0 +1,95 @@ +#!/bin/bash -x +# vim: set tabstop=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 . +# + +TEST="${0}" +. tests-common-functions + +function on_exit() { + if [ "$PID" ]; then kill $PID; wait $PID || true; fi + [ -d "$TMP" ] && rm -rf $TMP +} + +trap 'on_exit' EXIT +trap 'exit' ERR + +export TMP=$(mktemp -d) +mkdir -p "${TMP}/db" + +# Generate the server keys +KEYS="$TMP/db" +tangd-keygen $TMP/db sig exc +if which tangd-update; then + mkdir -p "${TMP}/cache" + tangd-update "${TMP}/db" "${TMP}/cache" + KEYS="${TMP}/cache" +fi + +# Start the server. +port=$(shuf -i 1024-65536 -n 1) +"${SD_ACTIVATE}" --inetd -l 127.0.0.1:"${port}" -a tangd "${KEYS}" & +export PID=$! +sleep 0.25 + +url="http://localhost:${port}" +adv="${TMP}/adv" +curl "${url}/adv" -o "${adv}" + +cfg=$(printf '{"url":"%s","adv":"%s"}' "$url" "$adv") + +# LUKS1. +DEV="${TMP}/luks1-device" +new_device "luks1" "${DEV}" + +SLT=1 +if ! clevis luks bind -f -s "${SLT}" -d "${DEV}" tang "${cfg}" <<< "${DEFAULT_PASS}"; then + error "${TEST}: Bind should have succeeded." +fi + +# Now let's rotate the keys in the server and remove the old ones, so that we +# will be unable to unlock the volume using clevis and will have to provide +# manually a password for clevis luks regen. +rm -rf "${TMP}"/db/* +tangd-keygen $TMP/db sig exc +if which tangd-update; then + mkdir -p "${TMP}/cache" + tangd-update "${TMP}/db" "${TMP}/cache" +fi + +# Making sure we have two slots enabled. +enabled=$(cryptsetup luksDump "${DEV}" | grep ENABLED | wc -l) +if [ "${enabled}" -ne 2 ]; then + error "${TEST}: we should have two slots enabled (${enabled})." +fi + +# Now let's try regen. +if ! clevis_regen "${DEV}" "${SLT}" "${DEFAULT_PASS}"; then + error "${TEST}: clevis luks regen failed" +fi + +TEST_DEV="test-device-${RANDOM}" +if ! clevis luks unlock -d "${DEV}" -n "${TEST_DEV}"; then + error "${TEST}: we were unable to unlock ${DEV}." +fi + +cryptsetup close "${TEST_DEV}" + +kill -9 "${PID}" +! wait "${PID}" +unset PID diff --git a/src/luks/tests/regen-not-inplace-luks2 b/src/luks/tests/regen-not-inplace-luks2 new file mode 100755 index 0000000..dc91449 --- /dev/null +++ b/src/luks/tests/regen-not-inplace-luks2 @@ -0,0 +1,96 @@ +#!/bin/bash -x +# vim: set tabstop=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 . +# + +TEST="${0}" +. tests-common-functions + +function on_exit() { + if [ "$PID" ]; then kill $PID; wait $PID || true; fi + [ -d "$TMP" ] && rm -rf $TMP +} + +trap 'on_exit' EXIT +trap 'exit' ERR + +export TMP=$(mktemp -d) +mkdir -p "${TMP}/db" + +# Generate the server keys +KEYS="$TMP/db" +tangd-keygen $TMP/db sig exc +if which tangd-update; then + mkdir -p "${TMP}/cache" + tangd-update "${TMP}/db" "${TMP}/cache" + KEYS="${TMP}/cache" +fi + +# Start the server. +port=$(shuf -i 1024-65536 -n 1) +"${SD_ACTIVATE}" --inetd -l 127.0.0.1:"${port}" -a tangd "${KEYS}" & +export PID=$! +sleep 0.25 + +url="http://localhost:${port}" +adv="${TMP}/adv" +curl "${url}/adv" -o "${adv}" + +cfg=$(printf '{"url":"%s","adv":"%s"}' "$url" "$adv") + +# LUKS2. +DEV="${TMP}/luks2-device" +new_device "luks2" "${DEV}" + +SLT=1 +if ! clevis luks bind -f -s "${SLT}" -d "${DEV}" tang "${cfg}" <<< "${DEFAULT_PASS}"; then + error "${TEST}: Bind should have succeeded." +fi + +# Now let's rotate the keys in the server and remove the old ones, so that we +# will be unable to unlock the volume using clevis and will have to provide +# manually a password for clevis luks regen. +rm -rf "${TMP}"/db/* +tangd-keygen $TMP/db sig exc +if which tangd-update; then + mkdir -p "${TMP}/cache" + tangd-update "${TMP}/db" "${TMP}/cache" +fi + +# Making sure we have two slots enabled. +enabled=$(cryptsetup luksDump "${DEV}" \ + | sed -rn 's|^\s+([0-9]+): luks2$|\1|p' | wc -l) +if [ "${enabled}" -ne 2 ]; then + error "${TEST}: we should have two slots enabled (${enabled})." +fi + +# Now let's try regen. +if ! clevis_regen "${DEV}" "${SLT}" "${DEFAULT_PASS}"; then + error "${TEST}: clevis luks regen failed" +fi + +TEST_DEV="test-device-${RANDOM}" +if ! clevis luks unlock -d "${DEV}" -n "${TEST_DEV}"; then + error "${TEST}: we were unable to unlock ${DEV}." +fi + +cryptsetup close "${TEST_DEV}" + +kill -9 "${PID}" +! wait "${PID}" +unset PID diff --git a/src/luks/tests/tests-common-functions.in b/src/luks/tests/tests-common-functions.in index 7b3fdad..6101f28 100755 --- a/src/luks/tests/tests-common-functions.in +++ b/src/luks/tests/tests-common-functions.in @@ -229,5 +229,31 @@ tang_get_adv() { curl -o "${adv}" http://"${TANG_HOST}":"${port}"/adv } +# Regenerate binding. +clevis_regen() { + local DEV="${1}" + local SLT="${2}" + local PASS="${3}" + + expect -d << CLEVIS_REGEN + set timeout 120 + spawn sh -c "clevis luks regen -d $DEV -s $SLT" + expect { + "Enter existing LUKS password" { + send "$PASS\r" + exp_continue + } + "Do you wish to trust these keys" { + send "y\r" + exp_continue + } + expect eof + wait + } +CLEVIS_REGEN + ret=$? + return "${ret}" +} + export TANG_HOST=127.0.0.1 export DEFAULT_PASS='just-some-test-password-here' -- 2.18.4