diff --git a/.clevis.metadata b/.clevis.metadata
index 4602876..2d0caa9 100644
--- a/.clevis.metadata
+++ b/.clevis.metadata
@@ -1 +1 @@
-086374814a4d71db8625d27a1719e03244a7cff0 SOURCES/clevis-11.tar.xz
+83aebcbe5792b43bf281b442f379cea08d7c43b0 SOURCES/clevis-13.tar.xz
diff --git a/.gitignore b/.gitignore
index f017bbb..a769e5f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1 @@
-SOURCES/clevis-11.tar.xz
+SOURCES/clevis-13.tar.xz
diff --git a/SOURCES/0001-Adjust-pin-tang-test-to-account-for-newer-tang-witho.patch b/SOURCES/0001-Adjust-pin-tang-test-to-account-for-newer-tang-witho.patch
new file mode 100644
index 0000000..8455003
--- /dev/null
+++ b/SOURCES/0001-Adjust-pin-tang-test-to-account-for-newer-tang-witho.patch
@@ -0,0 +1,84 @@
+From 27a27befed2257c2156ed8b94d679951b9b1a4d5 Mon Sep 17 00:00:00 2001
+From: Sergio Correia <scorreia@redhat.com>
+Date: Wed, 13 May 2020 23:51:04 -0300
+Subject: [PATCH 1/8] Adjust pin-tang test to account for newer tang without
+ tangd-update
+
+---
+ src/luks/tests/unbind-unbound-slot-luks2 |  1 +
+ src/pins/tang/meson.build                |  8 +-------
+ src/pins/tang/pin-tang                   | 11 ++++++++---
+ 3 files changed, 10 insertions(+), 10 deletions(-)
+
+diff --git a/src/luks/tests/unbind-unbound-slot-luks2 b/src/luks/tests/unbind-unbound-slot-luks2
+index 6a2aca5..6d814ad 100755
+--- a/src/luks/tests/unbind-unbound-slot-luks2
++++ b/src/luks/tests/unbind-unbound-slot-luks2
+@@ -36,6 +36,7 @@ TMP="$(mktemp -d)"
+ 
+ DEV="${TMP}/luks2-device"
+ new_device "luks2" "${DEV}"
++SLT=2
+ if clevis luks unbind -d "${DEV}" -s "${SLT}"; then
+     error "${TEST}: Unbind is expected to fail for device ${DEV} and slot ${SLT}" >&2
+ fi
+diff --git a/src/pins/tang/meson.build b/src/pins/tang/meson.build
+index 74a3442..9b9a3db 100644
+--- a/src/pins/tang/meson.build
++++ b/src/pins/tang/meson.build
+@@ -9,12 +9,6 @@ kgen = find_program(
+   '/usr/lib/x86_64-linux-gnu/tangd-keygen',
+   required: false
+ )
+-updt = find_program(
+-  join_paths(libexecdir, 'tangd-update'),
+-  '/usr/libexec/tangd-update',
+-  '/usr/lib/x86_64-linux-gnu/tangd-update',
+-  required: false
+-)
+ tang = find_program(
+   join_paths(libexecdir, 'tangd'),
+   '/usr/libexec/tangd',
+@@ -28,7 +22,7 @@ if curl.found()
+   bins += join_paths(meson.current_source_dir(), 'clevis-encrypt-tang')
+   mans += join_paths(meson.current_source_dir(), 'clevis-encrypt-tang.1')
+ 
+-  if actv.found() and kgen.found() and updt.found() and tang.found()
++  if actv.found() and kgen.found() and tang.found()
+     env = environment()
+     env.set('SD_ACTIVATE', actv.path())
+     env.append('PATH',
+diff --git a/src/pins/tang/pin-tang b/src/pins/tang/pin-tang
+index 1720d3d..8190f3d 100755
+--- a/src/pins/tang/pin-tang
++++ b/src/pins/tang/pin-tang
+@@ -31,18 +31,23 @@ mkdir -p "$TMP"/db
+ mkdir -p "$TMP"/cache
+ 
+ # Generate the server keys
++KEYS="$TMP"/db
+ tangd-keygen "$TMP"/db sig exc
+-tangd-update "$TMP"/db "$TMP"/cache
++if which tangd-update; then
++    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 "$TMP"/cache &
++$SD_ACTIVATE --inetd -l 127.0.0.1:$port -a tangd "$KEYS" &
+ PID=$!
+ sleep 0.25
+ 
+ thp="$(jose jwk thp -i "$TMP/db/sig.jwk")"
+-adv="$TMP/cache/default.jws"
+ url="http://localhost:${port}"
++adv="$TMP/adv"
++curl "$url/adv" -o $adv
+ 
+ cfg="$(printf '{"url":"%s","adv":"%s"}' "$url" "$adv")"
+ enc="$(echo -n "hi" | clevis encrypt tang "$cfg")"
+-- 
+2.18.4
+
diff --git a/SOURCES/0002-Fix-clevis-luks-unlock-and-add-related-tests.patch b/SOURCES/0002-Fix-clevis-luks-unlock-and-add-related-tests.patch
new file mode 100644
index 0000000..0f4b835
--- /dev/null
+++ b/SOURCES/0002-Fix-clevis-luks-unlock-and-add-related-tests.patch
@@ -0,0 +1,732 @@
+From e5f6d87d5c71f3faf0c0dbe38534fd3eab30f43e Mon Sep 17 00:00:00 2001
+From: Sergio Correia <scorreia@redhat.com>
+Date: Wed, 13 May 2020 23:51:04 -0300
+Subject: [PATCH 2/8] Fix clevis luks unlock and add related tests
+
+---
+ src/luks/clevis-luks-common-functions    |  35 ++++++
+ src/luks/clevis-luks-unlock              |  68 ++++++++++++
+ src/luks/clevis-luks-unlock.in           | 130 ----------------------
+ src/luks/meson.build                     |  10 +-
+ src/luks/tests/meson.build               |  40 +++++++
+ src/luks/tests/tests-common-functions.in | 134 +++++++++++++++++++++--
+ src/luks/tests/unlock-tang-luks1         |  83 ++++++++++++++
+ src/luks/tests/unlock-tang-luks2         |  83 ++++++++++++++
+ 8 files changed, 439 insertions(+), 144 deletions(-)
+ create mode 100755 src/luks/clevis-luks-unlock
+ delete mode 100755 src/luks/clevis-luks-unlock.in
+ create mode 100755 src/luks/tests/unlock-tang-luks1
+ create mode 100755 src/luks/tests/unlock-tang-luks2
+
+diff --git a/src/luks/clevis-luks-common-functions b/src/luks/clevis-luks-common-functions
+index e27c444..d04fdb5 100644
+--- a/src/luks/clevis-luks-common-functions
++++ b/src/luks/clevis-luks-common-functions
+@@ -281,3 +281,38 @@ clevis_luks_read_pins_from_slot() {
+     fi
+     printf "%s: %s\n" "${SLOT}" "${cfg}"
+ }
++
++# clevis_luks_unlock_device() does the unlock of the device passed as
++# parameter and returns the decoded passphrase.
++clevis_luks_unlock_device() {
++    local DEV="${1}"
++    [ -z "${DEV}" ] && return 1
++
++    local used_slots
++    if ! used_slots=$(clevis_luks_used_slots "${DEV}") \
++                      || [ -z "${used_slots}" ]; then
++        return 1
++    fi
++
++    local slt jwe passphrase
++    for slt in ${used_slots}; do
++        if ! jwe="$(clevis_luks_read_slot "${DEV}" "${slt}" 2>/dev/null)" \
++                   || [ -z "${jwe}" ]; then
++            continue
++        fi
++
++        if ! passphrase="$(clevis decrypt < <(echo -n "${jwe}"))" \
++                           || [ -z "${passphrase}" ]; then
++            continue
++        fi
++
++        if ! cryptsetup luksOpen --test-passphrase "${DEV}" \
++             --key-file <(echo -n "${passphrase}"); then
++            continue
++        fi
++        echo -n "${passphrase}"
++        return 0
++    done
++
++    return 1
++}
+diff --git a/src/luks/clevis-luks-unlock b/src/luks/clevis-luks-unlock
+new file mode 100755
+index 0000000..580fde8
+--- /dev/null
++++ b/src/luks/clevis-luks-unlock
+@@ -0,0 +1,68 @@
++#!/bin/bash -e
++# vim: set tabstop=8 shiftwidth=4 softtabstop=4 expandtab smarttab colorcolumn=80:
++#
++# Copyright (c) 2016 Red Hat, Inc.
++# Author: Nathaniel McCallum <npmccallum@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/>.
++#
++. clevis-luks-common-functions
++
++SUMMARY="Unlocks a LUKS volume"
++
++function usage() {
++    exec >&2
++    echo
++    echo "Usage: clevis luks unlock -d DEV [-n NAME]"
++    echo
++    echo "$SUMMARY":
++    echo
++    echo "  -d DEV  The LUKS device on which to perform unlocking"
++    echo
++    echo "  -n NAME The name of the unlocked device node"
++    echo
++    exit 2
++}
++
++if [ $# -eq 1 ] && [ "$1" == "--summary" ]; then
++    echo "$SUMMARY"
++    exit 0
++fi
++
++while getopts ":d:n:" o; do
++    case "$o" in
++    d) DEV="$OPTARG";;
++    n) NAME="$OPTARG";;
++    *) usage;;
++    esac
++done
++
++if [ -z "$DEV" ]; then
++    echo "Did not specify a device!" >&2
++    usage
++fi
++
++if ! cryptsetup isLuks "$DEV"; then
++    echo "$DEV is not a LUKS device!" >&2
++    exit 1
++fi
++
++NAME="${NAME:-luks-"$(cryptsetup luksUUID "$DEV")"}"
++
++if ! pt=$(clevis_luks_unlock_device "${DEV}"); then
++    echo "${DEV} could not be opened." >&2
++    exit 1
++fi
++
++cryptsetup open -d- "${DEV}" "${NAME}" < <(echo -n "${pt}")
+diff --git a/src/luks/clevis-luks-unlock.in b/src/luks/clevis-luks-unlock.in
+deleted file mode 100755
+index aa3134b..0000000
+--- a/src/luks/clevis-luks-unlock.in
++++ /dev/null
+@@ -1,130 +0,0 @@
+-#!/bin/bash -e
+-# vim: set tabstop=8 shiftwidth=4 softtabstop=4 expandtab smarttab colorcolumn=80:
+-#
+-# Copyright (c) 2016 Red Hat, Inc.
+-# Author: Nathaniel McCallum <npmccallum@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/>.
+-#
+-
+-SUMMARY="Unlocks a LUKS volume"
+-UUID=cb6e8904-81ff-40da-a84a-07ab9ab5715e
+-
+-# We require cryptsetup >= 2.0.4 to fully support LUKSv2.
+-# Support is determined at build time.
+-function luks2_supported() {
+-    return @OLD_CRYPTSETUP@
+-}
+-
+-function usage() {
+-    exec >&2
+-    echo
+-    echo "Usage: clevis luks unlock -d DEV [-n NAME]"
+-    echo
+-    echo "$SUMMARY":
+-    echo
+-    echo "  -d DEV  The LUKS device on which to perform unlocking"
+-    echo
+-    echo "  -n NAME The name of the unlocked device node"
+-    echo
+-    exit 2
+-}
+-
+-if [ $# -eq 1 ] && [ "$1" == "--summary" ]; then
+-    echo "$SUMMARY"
+-    exit 0
+-fi
+-
+-while getopts ":d:n:" o; do
+-    case "$o" in
+-    d) DEV="$OPTARG";;
+-    n) NAME="$OPTARG";;
+-    *) usage;;
+-    esac
+-done
+-
+-if [ -z "$DEV" ]; then
+-    echo "Did not specify a device!" >&2
+-    usage
+-fi
+-
+-if ! cryptsetup isLuks "$DEV"; then
+-    echo "$DEV is not a LUKS device!" >&2
+-    exit 1
+-fi
+-
+-if luks2_supported; then
+-    if cryptsetup isLuks --type luks1 "$DEV"; then
+-        luks_type="luks1"
+-    elif cryptsetup isLuks --type luks2 "$DEV";then
+-        luks_type="luks2"
+-    else
+-        echo "$DEV is not a supported LUKS device!" >&2
+-        exit 1
+-    fi
+-else
+-    luks_type="luks1"
+-fi
+-NAME="${NAME:-luks-"$(cryptsetup luksUUID "$DEV")"}"
+-
+-luks1_decrypt() {
+-    luksmeta load "$@" \
+-        | clevis decrypt
+-
+-    local rc
+-    for rc in "${PIPESTATUS[@]}"; do
+-        [ $rc -eq 0 ] || return $rc
+-    done
+-    return 0
+-}
+-
+-luks2_decrypt() {
+-    # jose jwe fmt -c outputs extra \n, so clean it up
+-    cryptsetup token export "$@" \
+-        | jose fmt -j- -Og jwe -o- \
+-        | jose jwe fmt -i- -c \
+-        | tr -d '\n' \
+-        | clevis decrypt
+-
+-    local rc
+-    for rc in "${PIPESTATUS[@]}"; do
+-        [ $rc -eq 0 ] || return $rc
+-    done
+-    return 0
+-}
+-
+-if [ "$luks_type" == "luks1" ]; then
+-    while read -r slot state uuid; do
+-        [ "$state" == "active" ] || continue
+-        [ "$uuid" == "$UUID" ] || continue
+-
+-        pt="$(luks1_decrypt -d $DEV -s $slot -u $UUID)" \
+-            || continue
+-        exec cryptsetup open -d- "$DEV" "$NAME" < <(
+-            echo -n "$pt"
+-        )
+-    done < <(luksmeta show -d "$DEV")
+-
+-elif [ "$luks_type" == "luks2" ]; then
+-    while read -r id; do
+-        pt="$(luks2_decrypt --token-id "$id" "$DEV")" \
+-            || continue
+-        exec cryptsetup open -d- "$DEV" "$NAME" < <(
+-            echo -n "$pt"
+-        )
+-    done < <(cryptsetup luksDump "$DEV" | sed -rn 's|^\s+([0-9]+): clevis|\1|p')
+-fi
+-
+-echo "$DEV could not be opened." >&2
+-exit 1
+diff --git a/src/luks/meson.build b/src/luks/meson.build
+index bbba63f..0d24f8d 100644
+--- a/src/luks/meson.build
++++ b/src/luks/meson.build
+@@ -21,9 +21,7 @@ clevis_luks_bind = configure_file(input: 'clevis-luks-bind.in',
+ clevis_luks_unbind = configure_file(input: 'clevis-luks-unbind.in',
+                output: 'clevis-luks-unbind',
+                configuration: luksmeta_data)
+-clevis_luks_unlock = configure_file(input: 'clevis-luks-unlock.in',
+-               output: 'clevis-luks-unlock',
+-               configuration: luksmeta_data)
++
+ if libcryptsetup.found() and luksmeta.found() and pwmake.found()
+   subdir('systemd')
+   subdir('udisks2')
+@@ -31,18 +29,18 @@ if libcryptsetup.found() and luksmeta.found() and pwmake.found()
+   bins += clevis_luks_unbind
+   mans += join_paths(meson.current_source_dir(), 'clevis-luks-unbind.1')
+ 
+-  bins += clevis_luks_unlock
+-  mans += join_paths(meson.current_source_dir(), 'clevis-luks-unlock.1')
+-
+   bins += clevis_luks_bind
+   mans += join_paths(meson.current_source_dir(), 'clevis-luks-bind.1')
+ 
+   mans += join_paths(meson.current_source_dir(), 'clevis-luks-unlockers.7')
+ 
+   bins += join_paths(meson.current_source_dir(), 'clevis-luks-common-functions')
++
+   bins += join_paths(meson.current_source_dir(), 'clevis-luks-list')
+   mans += join_paths(meson.current_source_dir(), 'clevis-luks-list.1')
+ 
++  bins += join_paths(meson.current_source_dir(), 'clevis-luks-unlock')
++  mans += join_paths(meson.current_source_dir(), 'clevis-luks-unlock.1')
+ else
+   warning('Will not install LUKS support due to missing dependencies!')
+ endif
+diff --git a/src/luks/tests/meson.build b/src/luks/tests/meson.build
+index 2e0fb92..9a16b42 100644
+--- a/src/luks/tests/meson.build
++++ b/src/luks/tests/meson.build
+@@ -1,6 +1,30 @@
+ # 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,
+@@ -24,6 +48,14 @@ env.prepend('PATH',
+   separator: ':'
+ )
+ 
++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)
+@@ -42,6 +74,10 @@ 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
++
+ # 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.
+@@ -56,4 +92,8 @@ if luksmeta_data.get('OLD_CRYPTSETUP') == '0'
+     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
+ endif
+diff --git a/src/luks/tests/tests-common-functions.in b/src/luks/tests/tests-common-functions.in
+index 90420d1..7b3fdad 100755
+--- a/src/luks/tests/tests-common-functions.in
++++ b/src/luks/tests/tests-common-functions.in
+@@ -56,7 +56,7 @@ new_device() {
+ 
+     # Some builders fail if the cryptsetup steps are not ran as root, so let's
+     # skip the test now if not running as root.
+-    if [ $(id -u) != 0 ]; then
++    if [ "$(id -u)" != 0 ]; then
+         skip_test "WARNING: You must be root to run this test; test skipped."
+     fi
+ 
+@@ -74,9 +74,9 @@ new_device() {
+         return 0
+     fi
+ 
+-    fallocate -l16M "${DEV}"
+-    local extra_options='--pbkdf pbkdf2 --pbkdf-force-iterations 1000'
+-    cryptsetup luksFormat --type "${LUKS}" ${extra_options} --batch-mode \
++    fallocate -l64M "${DEV}"
++    cryptsetup luksFormat --type "${LUKS}" --pbkdf pbkdf2 \
++        --pbkdf-force-iterations 1000 --batch-mode \
+         --force-password "${DEV}" <<< "${PASS}"
+     # Caching the just-formatted device for possible reuse.
+     cp -f "${DEV}" "${DEV_CACHED}"
+@@ -90,7 +90,7 @@ new_device_keyfile() {
+ 
+     # Some builders fail if the cryptsetup steps are not ran as root, so let's
+     # skip the test now if not running as root.
+-    if [ $(id -u) != 0 ]; then
++    if [ "$(id -u)" != 0 ]; then
+         skip_test "WARNING: You must be root to run this test; test skipped."
+     fi
+ 
+@@ -98,9 +98,9 @@ new_device_keyfile() {
+         error "Invalid keyfile (${KEYFILE})."
+     fi
+ 
+-    fallocate -l16M "${DEV}"
+-    local extra_options='--pbkdf pbkdf2 --pbkdf-force-iterations 1000'
+-    cryptsetup luksFormat --type "${LUKS}"  ${extra_options} --batch-mode \
++    fallocate -l64M "${DEV}"
++    cryptsetup luksFormat --type "${LUKS}" --pbkdf pbkdf2 \
++        --pbkdf-force-iterations 1000 --batch-mode \
+         "${DEV}" "${KEYFILE}"
+ }
+ 
+@@ -112,4 +112,122 @@ pin_cfg_equal() {
+          <(jq -S . < <(echo -n "${cfg2}"))
+ }
+ 
++# Get a random port to be used with a test tang server.
++get_random_port() {
++    shuf -i 1024-65535 -n 1
++}
++
++# Removes tang rotated keys from the test server.
++tang_remove_rotated_keys() {
++    local basedir="${1}"
++
++    if [ -z "${basedir}" ]; then
++        echo "Please pass a valid base directory for tang"
++        return 1
++    fi
++
++    local db="${basedir}/db"
++    mkdir -p "${db}"
++
++    pushd "${db}"
++        find . -name ".*.jwk" -exec rm -f {} \;
++    popd
++}
++
++# Creates new keys for the test tang server.
++tang_new_keys() {
++    local basedir="${1}"
++    local rotate="${2}"
++
++    if [ -z "${basedir}" ]; then
++        echo "Please pass a valid base directory for tang"
++        return 1
++    fi
++
++    [ -z "${TANGD_KEYGEN}" ] && skip_test "WARNING: TANGD_KEYGEN is not defined."
++
++    local db="${basedir}/db"
++    mkdir -p "${db}"
++
++    if [ -n "${rotate}" ]; then
++        pushd "${db}"
++            local k
++            k=$(find . -name "*.jwk" | wc -l)
++            if [ "${k}" -gt 0 ]; then
++                for k in *.jwk; do
++                    mv -f -- "${k}" ".${k}"
++                done
++            fi
++        popd
++    fi
++
++    "${TANGD_KEYGEN}" "${db}"
++
++    return 0
++}
++
++# Start a test tang server.
++tang_run() {
++    local basedir="${1}"
++    local port="${2}"
++
++    if [ -z "${basedir}" ]; then
++        echo "Please pass a valid base directory for tang" >&2
++        return 1
++    fi
++
++    if [ -z "${port}" ]; then
++        echo "Please pass a valid port for tang" >&2
++        return 1
++    fi
++
++    if ! tang_new_keys "${basedir}"; then
++        echo "Error creating new keys for tang server" >&2
++        return 1
++    fi
++
++    local KEYS="${basedir}/db"
++
++    local inetd='--inetd'
++    [ "${SD_ACTIVATE##*/}" = "systemd-activate" ] && inetd=
++
++    local pid pidfile
++    pidfile="${basedir}/tang.pid"
++
++    "${SD_ACTIVATE}" ${inetd} -l "${TANG_HOST}":"${port}" \
++            -a "${TANGD}" "${KEYS}" &
++    pid=$!
++    echo "${pid}" > "${pidfile}"
++}
++
++# Stop tang server.
++tang_stop() {
++    local basedir="${1}"
++    local pidfile="${basedir}/tang.pid"
++    [ -f "${pidfile}" ] || return 0
++
++    local pid
++    pid=$(<"${pidfile}")
++    kill "${pid}"
++}
++
++# Wait for the tang server to be operational.
++tang_wait_until_ready() {
++   local port="${1}"
++   while ! curl --output /dev/null --silent --fail \
++                http://"${TANG_HOST}":"${port}"/adv; do
++       sleep 0.1
++       echo -n . >&2
++   done
++}
++
++# Get tang advertisement.
++tang_get_adv() {
++    local port="${1}"
++    local adv="${2}"
++
++    curl -o "${adv}" http://"${TANG_HOST}":"${port}"/adv
++}
++
++export TANG_HOST=127.0.0.1
+ export DEFAULT_PASS='just-some-test-password-here'
+diff --git a/src/luks/tests/unlock-tang-luks1 b/src/luks/tests/unlock-tang-luks1
+new file mode 100755
+index 0000000..841ba01
+--- /dev/null
++++ b/src/luks/tests/unlock-tang-luks1
+@@ -0,0 +1,83 @@
++#!/bin/bash -ex
++# vim: set ts=8 shiftwidth=4 softtabstop=4 expandtab smarttab colorcolumn=80:
++#
++# Copyright (c) 2020 Red Hat, Inc.
++# Author: Sergio Correia <scorreia@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}" ] && return 0
++    tang_stop "${TMP}"
++    rm -rf "${TMP}"
++}
++
++trap 'on_exit' EXIT
++trap 'on_exit' ERR
++
++TMP="$(mktemp -d)"
++
++port=$(get_random_port)
++tang_run "${TMP}" "${port}" &
++tang_wait_until_ready "${port}"
++
++url="http://${TANG_HOST}:${port}"
++adv="${TMP}/adv"
++tang_get_adv "${port}" "${adv}"
++
++cfg=$(printf '{"url":"%s","adv":"%s"}' "$url" "$adv")
++
++# LUKS1.
++DEV="${TMP}/luks1-device"
++new_device "luks1" "${DEV}"
++
++if ! clevis luks bind -f -d "${DEV}" tang "${cfg}" <<< "${DEFAULT_PASS}"; then
++    error "${TEST}: Bind should have succeeded."
++fi
++
++if ! clevis_luks_unlock_device "${DEV}"; then
++    error "${TEST}: we were unable to unlock ${DEV}."
++fi
++
++# Let's rotate the tang keys and add another binding with the new key.
++tang_new_keys "${TMP}" "rotate-keys"
++
++# Unlock should still work now.
++if ! clevis_luks_unlock_device "${DEV}"; then
++    error "${TEST}: we should still be able to unlock ${DEV}"
++fi
++
++# Now let's remove the rotated keys.
++tang_remove_rotated_keys "${TMP}"
++
++# Unlock should not work anymore.
++if clevis_luks_unlock_device "${DEV}"; then
++    error "${TEST}: we should not be able to unlock ${DEV}"
++fi
++
++# Now let's add another binding with the new keys.
++tang_get_adv "${port}" "${adv}" # Updating the advertisement.
++if ! clevis luks bind -f -d "${DEV}" tang "${cfg}" <<< "${DEFAULT_PASS}"; then
++    error "${TEST}: Bind should have succeeded."
++fi
++
++# Unlock should work again, using the new keys.
++if ! clevis_luks_unlock_device "${DEV}"; then
++    error "${TEST}: we should be able to unlock ${DEV} with the new keys"
++fi
+diff --git a/src/luks/tests/unlock-tang-luks2 b/src/luks/tests/unlock-tang-luks2
+new file mode 100755
+index 0000000..81822fb
+--- /dev/null
++++ b/src/luks/tests/unlock-tang-luks2
+@@ -0,0 +1,83 @@
++#!/bin/bash -ex
++# vim: set ts=8 shiftwidth=4 softtabstop=4 expandtab smarttab colorcolumn=80:
++#
++# Copyright (c) 2020 Red Hat, Inc.
++# Author: Sergio Correia <scorreia@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}" ] && return 0
++    tang_stop "${TMP}"
++    rm -rf "${TMP}"
++}
++
++trap 'on_exit' EXIT
++trap 'on_exit' ERR
++
++TMP="$(mktemp -d)"
++
++port=$(get_random_port)
++tang_run "${TMP}" "${port}" &
++tang_wait_until_ready "${port}"
++
++url="http://${TANG_HOST}:${port}"
++adv="${TMP}/adv"
++tang_get_adv "${port}" "${adv}"
++
++cfg=$(printf '{"url":"%s","adv":"%s"}' "$url" "$adv")
++
++# LUKS2.
++DEV="${TMP}/luks2-device"
++new_device "luks2" "${DEV}"
++
++if ! clevis luks bind -f -d "${DEV}" tang "${cfg}" <<< "${DEFAULT_PASS}"; then
++    error "${TEST}: Bind should have succeeded."
++fi
++
++if ! clevis_luks_unlock_device "${DEV}"; then
++    error "${TEST}: we were unable to unlock ${DEV}."
++fi
++
++# Let's rotate the tang keys and add another binding with the new key.
++tang_new_keys "${TMP}" "rotate-keys"
++
++# Unlock should still work now.
++if ! clevis_luks_unlock_device "${DEV}"; then
++    error "${TEST}: we should still be able to unlock ${DEV}"
++fi
++
++# Now let's remove the rotated keys.
++tang_remove_rotated_keys "${TMP}"
++
++# Unlock should not work anymore.
++if clevis_luks_unlock_device "${DEV}"; then
++    error "${TEST}: we should not be able to unlock ${DEV}"
++fi
++
++# Now let's add another binding with the new keys.
++tang_get_adv "${port}" "${adv}" # Updating the advertisement.
++if ! clevis luks bind -f -d "${DEV}" tang "${cfg}" <<< "${DEFAULT_PASS}"; then
++    error "${TEST}: Bind should have succeeded."
++fi
++
++# Unlock should work again, using the new keys.
++if ! clevis_luks_unlock_device "${DEV}"; then
++    error "${TEST}: we should be able to unlock ${DEV} with the new keys"
++fi
+-- 
+2.18.4
+
diff --git a/SOURCES/0003-Improve-error-message-when-bind-is-given-an-invalid-.patch b/SOURCES/0003-Improve-error-message-when-bind-is-given-an-invalid-.patch
new file mode 100644
index 0000000..73f3470
--- /dev/null
+++ b/SOURCES/0003-Improve-error-message-when-bind-is-given-an-invalid-.patch
@@ -0,0 +1,57 @@
+From d393fbc256e22cc8019d18214e4d140d58f3302a Mon Sep 17 00:00:00 2001
+From: Sergio Correia <scorreia@redhat.com>
+Date: Wed, 13 May 2020 23:51:04 -0300
+Subject: [PATCH 3/8] Improve error message when bind is given an invalid PIN
+
+---
+ src/luks/clevis-luks-bind.in          | 6 ++++++
+ src/luks/clevis-luks-common-functions | 9 +++++++++
+ 2 files changed, 15 insertions(+)
+
+diff --git a/src/luks/clevis-luks-bind.in b/src/luks/clevis-luks-bind.in
+index a5d3c5f..89a5e22 100755
+--- a/src/luks/clevis-luks-bind.in
++++ b/src/luks/clevis-luks-bind.in
+@@ -19,6 +19,8 @@
+ # along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ #
+ 
++. clevis-luks-common-functions
++
+ SUMMARY="Binds a LUKS device using the specified policy"
+ UUID=cb6e8904-81ff-40da-a84a-07ab9ab5715e
+ 
+@@ -76,6 +78,10 @@ fi
+ if ! PIN="${@:$((OPTIND++)):1}" || [ -z "$PIN" ]; then
+     echo "Did not specify a pin!" >&2
+     usage
++elif ! EXE=$(findexe clevis-encrypt-"${PIN}") \
++             || [ -z "${EXE}" ]; then
++    echo "'$PIN' is not a valid pin!" >&2
++    usage
+ fi
+ 
+ if ! CFG="${@:$((OPTIND++)):1}" || [ -z "$CFG" ]; then
+diff --git a/src/luks/clevis-luks-common-functions b/src/luks/clevis-luks-common-functions
+index d04fdb5..36f0bfd 100644
+--- a/src/luks/clevis-luks-common-functions
++++ b/src/luks/clevis-luks-common-functions
+@@ -108,6 +108,15 @@ clevis_luks_read_slot() {
+     echo "${DATA_CODED}"
+ }
+ 
++# findexe() finds an executable.
++findexe() {
++    while read -r -d: path; do
++        [ -f "${path}/${1}" ] && [ -x "${path}/${1}" ] && \
++          echo "${path}/${1}" && return 0
++    done <<< "${PATH}:"
++    return 1
++}
++
+ # clevis_luks_used_slots() will return the list of used slots for a given LUKS
+ # device.
+ clevis_luks_used_slots() {
+-- 
+2.18.4
+
diff --git a/SOURCES/0004-Add-rd.neednet-1-to-cmdline-only-if-there-are-device.patch b/SOURCES/0004-Add-rd.neednet-1-to-cmdline-only-if-there-are-device.patch
new file mode 100644
index 0000000..0f0af18
--- /dev/null
+++ b/SOURCES/0004-Add-rd.neednet-1-to-cmdline-only-if-there-are-device.patch
@@ -0,0 +1,53 @@
+From fc0cc6f159857e463aacababdc0735b0972d103c Mon Sep 17 00:00:00 2001
+From: Sergio Correia <scorreia@redhat.com>
+Date: Wed, 13 May 2020 23:51:04 -0300
+Subject: [PATCH 4/8] Add rd.neednet=1 to cmdline only if there are devices
+ bound to tang
+
+---
+ .../dracut/clevis-pin-tang/module-setup.sh.in | 21 +++++++++++++++++--
+ 1 file changed, 19 insertions(+), 2 deletions(-)
+
+diff --git a/src/luks/systemd/dracut/clevis-pin-tang/module-setup.sh.in b/src/luks/systemd/dracut/clevis-pin-tang/module-setup.sh.in
+index 1bb2ead..a4984dc 100755
+--- a/src/luks/systemd/dracut/clevis-pin-tang/module-setup.sh.in
++++ b/src/luks/systemd/dracut/clevis-pin-tang/module-setup.sh.in
+@@ -18,8 +18,23 @@
+ # along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ #
+ 
++has_devices_bound_to_tang() {
++    local dev
++    for dev in $(lsblk -p -n -s -r \
++                 | awk '$6 == "crypt" { getline; print $1 }' | sort -u); do
++       if clevis luks list -d "${dev}" 2>/dev/null | grep -q tang; then
++           return 0
++       fi
++    done
++    return 1
++}
++
+ depends() {
+-    echo clevis network
++    local deps="clevis"
++    if has_devices_bound_to_tang; then
++         deps=$(printf "%s network" "${deps}")
++    fi
++    echo "${deps}"
+     return 0
+ }
+ 
+@@ -28,7 +43,9 @@ cmdline() {
+ }
+ 
+ install() {
+-    cmdline > "${initdir}/etc/cmdline.d/99clevis-pin-tang.conf"
++    if has_devices_bound_to_tang; then
++        cmdline > "${initdir}/etc/cmdline.d/99clevis-pin-tang.conf"
++    fi
+ 
+     inst_multiple \
+ 	clevis-decrypt-tang \
+-- 
+2.18.4
+
diff --git a/SOURCES/0005-Add-the-option-to-extract-luks-passphrase-used-for-b.patch b/SOURCES/0005-Add-the-option-to-extract-luks-passphrase-used-for-b.patch
new file mode 100644
index 0000000..b3ed25b
--- /dev/null
+++ b/SOURCES/0005-Add-the-option-to-extract-luks-passphrase-used-for-b.patch
@@ -0,0 +1,366 @@
+From e3641a7193adac1cea525c093f39679c2cfa22c9 Mon Sep 17 00:00:00 2001
+From: Sergio Correia <scorreia@redhat.com>
+Date: Wed, 13 May 2020 23:53:38 -0300
+Subject: [PATCH 5/8] Add the option to extract luks passphrase used for
+ binding
+
+Usage:
+
+clevis luks pass -d /dev/sda1 -s 1
+<passphrase here>
+---
+ src/luks/clevis-luks-pass        | 69 +++++++++++++++++++++++++++++
+ src/luks/clevis-luks-pass.1.adoc | 43 ++++++++++++++++++
+ src/luks/meson.build             |  3 ++
+ src/luks/tests/meson.build       | 11 +++++
+ src/luks/tests/pass-tang-luks1   | 75 ++++++++++++++++++++++++++++++++
+ src/luks/tests/pass-tang-luks2   | 75 ++++++++++++++++++++++++++++++++
+ 6 files changed, 276 insertions(+)
+ create mode 100755 src/luks/clevis-luks-pass
+ create mode 100644 src/luks/clevis-luks-pass.1.adoc
+ create mode 100755 src/luks/tests/pass-tang-luks1
+ create mode 100755 src/luks/tests/pass-tang-luks2
+
+diff --git a/src/luks/clevis-luks-pass b/src/luks/clevis-luks-pass
+new file mode 100755
+index 0000000..1ce8c4c
+--- /dev/null
++++ b/src/luks/clevis-luks-pass
+@@ -0,0 +1,69 @@
++#!/bin/bash -e
++# vim: set tabstop=8 shiftwidth=4 softtabstop=4 expandtab smarttab colorcolumn=80:
++#
++# Copyright (c) 2019 Red Hat, Inc.
++# Author: Sergio Correia <scorreia@redhat.com> - LUKS2 support.
++#
++# 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/>.
++#
++
++. clevis-luks-common-functions
++
++SUMMARY="Returns the LUKS passphrase used for binding a particular slot."
++
++function usage() {
++    echo >&2
++    echo "Usage: clevis luks pass -d DEV -s SLT" >&2
++    echo >&2
++    echo "$SUMMARY": >&2
++    echo >&2
++    echo "  -d DEV  The LUKS device to extract the LUKS passphrase used for binding" >&2
++    echo >&2
++    echo "  -s SLOT The slot number to extract the LUKS passphrase" >&2
++    echo >&2
++    exit 1
++}
++
++if [ ${#} -eq 1 ] && [ "${1}" = "--summary" ]; then
++    echo "${SUMMARY}"
++    exit 0
++fi
++
++while getopts ":d:s:" o; do
++    case "$o" in
++    d) DEV=${OPTARG};;
++    s) SLT=${OPTARG};;
++    *) usage;;
++    esac
++done
++
++if [ -z "${DEV}" ]; then
++    echo "Did not specify a device!" >&2
++    usage
++fi
++
++if [ -z "${SLT}" ]; then
++    echo "Did not specify a slot!" >&2
++    usage
++fi
++
++if ! jwe=$(clevis_luks_read_slot "${DEV}" "${SLT}" 2>/dev/null); then
++    echo "It was not possible to read slot ${SLT} from ${DEV}!" >&2
++    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
++    exit 1
++fi
+diff --git a/src/luks/clevis-luks-pass.1.adoc b/src/luks/clevis-luks-pass.1.adoc
+new file mode 100644
+index 0000000..fa9526a
+--- /dev/null
++++ b/src/luks/clevis-luks-pass.1.adoc
+@@ -0,0 +1,43 @@
++CLEVIS-LUKS-PASS(1)
++===================
++:doctype: manpage
++
++
++== NAME
++
++clevis-luks-pass - Extracts the passphrase used for binding a particular slot in a LUKS device
++
++== SYNOPSIS
++
++*clevis luks pass* -d DEV -s SLT
++
++== OVERVIEW
++
++The *clevis luks pass* command extracts the passphrase used for binding a particular slot in a LUKS device.
++For example:
++
++    clevis luks pass -d /dev/sda1 -s 1
++
++== OPTIONS
++
++* *-d* _DEV_ :
++  The LUKS device on which to extract a passphrase from
++
++* *-s* _SLT_ :
++  The slot to use for extracting the passphrase
++
++== EXAMPLE
++
++    clevis luks pass -d /dev/sda1 -s 1
++    <passphrase here>
++
++Note that the output of *clevis luks pass* might be non-printable, in which case it would be better to redirect its output to a file and use it as a key
++file together with cryptsetup. For instance:
++
++    clevis luks pass -d /dev/sda1 -s 1 > slot1-passphrase
++
++And the file slot1-passphrase will contain the passphrase associated with slot #1 in /dev/sda1.
++
++== SEE ALSO
++
++link:clevis-luks-unlock.1.adoc[*clevis-luks-unlock*(1)],
+diff --git a/src/luks/meson.build b/src/luks/meson.build
+index 0d24f8d..fda2ca8 100644
+--- a/src/luks/meson.build
++++ b/src/luks/meson.build
+@@ -41,6 +41,9 @@ if libcryptsetup.found() and luksmeta.found() and pwmake.found()
+ 
+   bins += join_paths(meson.current_source_dir(), 'clevis-luks-unlock')
+   mans += join_paths(meson.current_source_dir(), 'clevis-luks-unlock.1')
++
++  bins += join_paths(meson.current_source_dir(), 'clevis-luks-pass')
++  mans += join_paths(meson.current_source_dir(), 'clevis-luks-pass.1')
+ else
+   warning('Will not install LUKS support due to missing dependencies!')
+ endif
+diff --git a/src/luks/tests/meson.build b/src/luks/tests/meson.build
+index 9a16b42..4757c4b 100644
+--- a/src/luks/tests/meson.build
++++ b/src/luks/tests/meson.build
+@@ -1,3 +1,9 @@
++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)
+ 
+@@ -45,8 +51,11 @@ env.prepend('PATH',
+   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()
+@@ -77,6 +86,7 @@ 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.
+@@ -96,4 +106,5 @@ if luksmeta_data.get('OLD_CRYPTSETUP') == '0'
+   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/pass-tang-luks1 b/src/luks/tests/pass-tang-luks1
+new file mode 100755
+index 0000000..05cdb3e
+--- /dev/null
++++ b/src/luks/tests/pass-tang-luks1
+@@ -0,0 +1,75 @@
++#!/bin/bash -x
++# vim: set tabstop=8 shiftwidth=4 softtabstop=4 expandtab smarttab colorcolumn=80:
++#
++# Copyright (c) 2019 Red Hat, Inc.
++# Author: Sergio Correia <scorreia@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="${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}"
++
++if ! clevis luks bind -f -d "${DEV}" tang "${cfg}" <<< "${DEFAULT_PASS}"; then
++    error "${TEST}: Bind should have succeeded."
++fi
++
++#Now let's test the passphrase.
++SLT=1
++PASS=$(clevis luks pass -d "${DEV}" -s "${SLT}")
++echo $PASS >&2
++if ! cryptsetup luksOpen --test-passphrase ""${DEV} \
++        --key-file <(clevis luks pass -d "${DEV}" -s "${SLT}"); then
++    error "Passphrase obtained from clevis luks pass failed."
++fi
++
++kill -9 "${PID}"
++! wait "${PID}"
++unset PID
+diff --git a/src/luks/tests/pass-tang-luks2 b/src/luks/tests/pass-tang-luks2
+new file mode 100755
+index 0000000..9123aa0
+--- /dev/null
++++ b/src/luks/tests/pass-tang-luks2
+@@ -0,0 +1,75 @@
++#!/bin/bash -x
++# vim: set tabstop=8 shiftwidth=4 softtabstop=4 expandtab smarttab colorcolumn=80:
++#
++# Copyright (c) 2019 Red Hat, Inc.
++# Author: Sergio Correia <scorreia@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="${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}"
++
++if ! clevis luks bind -f -d "${DEV}" tang "${cfg}" <<< "${DEFAULT_PASS}"; then
++    error "${TEST}: Bind should have succeeded."
++fi
++
++#Now let's test the passphrase.
++SLT=1
++PASS=$(clevis luks pass -d "${DEV}" -s "${SLT}")
++echo $PASS >&2
++if ! cryptsetup luksOpen --test-passphrase ""${DEV} \
++        --key-file <(clevis luks pass -d "${DEV}" -s "${SLT}"); then
++    error "Passphrase obtained from clevis luks pass failed."
++fi
++
++kill -9 "${PID}"
++! wait "${PID}"
++unset PID
+-- 
+2.18.4
+
diff --git a/SOURCES/0006-Add-clevis-luks-regen-command.patch b/SOURCES/0006-Add-clevis-luks-regen-command.patch
new file mode 100644
index 0000000..bce58e3
--- /dev/null
+++ b/SOURCES/0006-Add-clevis-luks-regen-command.patch
@@ -0,0 +1,1387 @@
+From 158bdeda3ca961b0e615c8adfc58b61e1a1ba5c7 Mon Sep 17 00:00:00 2001
+From: Sergio Correia <scorreia@redhat.com>
+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 <rsroka@redhat.com>
++# Author: Sergio Correia <scorreia@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/>.
++#
++
++. 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 <scorreia@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="${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 <scorreia@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="${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 <scorreia@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="${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 <scorreia@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="${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 <scorreia@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="${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 <scorreia@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="${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
+
diff --git a/SOURCES/0007-Add-clevis-luks-report.patch b/SOURCES/0007-Add-clevis-luks-report.patch
new file mode 100644
index 0000000..962e700
--- /dev/null
+++ b/SOURCES/0007-Add-clevis-luks-report.patch
@@ -0,0 +1,464 @@
+From a85f50f789d69d9ca0a4096a64ac912f5967f97f Mon Sep 17 00:00:00 2001
+From: Sergio Correia <scorreia@redhat.com>
+Date: Sun, 10 May 2020 15:32:50 -0300
+Subject: [PATCH 7/8] Add clevis luks report
+
+---
+ src/luks/clevis-luks-report         | 95 +++++++++++++++++++++++++++++
+ src/luks/clevis-luks-report-compare | 71 +++++++++++++++++++++
+ src/luks/clevis-luks-report-decode  | 59 ++++++++++++++++++
+ src/luks/clevis-luks-report-sss     | 53 ++++++++++++++++
+ src/luks/clevis-luks-report-tang    | 67 ++++++++++++++++++++
+ src/luks/clevis-luks-report.1.adoc  | 41 +++++++++++++
+ src/luks/meson.build                |  7 +++
+ 7 files changed, 393 insertions(+)
+ create mode 100755 src/luks/clevis-luks-report
+ create mode 100755 src/luks/clevis-luks-report-compare
+ create mode 100755 src/luks/clevis-luks-report-decode
+ create mode 100755 src/luks/clevis-luks-report-sss
+ create mode 100755 src/luks/clevis-luks-report-tang
+ create mode 100644 src/luks/clevis-luks-report.1.adoc
+
+diff --git a/src/luks/clevis-luks-report b/src/luks/clevis-luks-report
+new file mode 100755
+index 0000000..f047256
+--- /dev/null
++++ b/src/luks/clevis-luks-report
+@@ -0,0 +1,95 @@
++#!/usr/bin/bash -e
++# vim: set tabstop=8 shiftwidth=4 softtabstop=4 expandtab smarttab colorcolumn=80:
++#
++# Copyright (c) 2018 Red Hat, Inc.
++# Author: Radovan Sroka <rsroka@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/>.
++#
++
++. clevis-luks-common-functions
++
++SUMMARY="Report any key rotation on the server side"
++
++if [ "$1" == "--summary" ]; then
++    echo "$SUMMARY"
++    exit 0
++fi
++
++function usage_and_exit () {
++    echo >&2
++    echo "Usage: clevis luks report [-qr] -d DEV -s SLOT" >&2
++    echo >&2
++    echo -e "  -q\t Quiet mode" >&2
++    echo -e "  -r\t Regenerate luks metadata with \"clevis luks regen -d DEV -s SLOT\"" >&2
++    echo >&2
++    echo "$SUMMARY" >&2
++    echo >&2
++    exit "$1"
++}
++
++while getopts "hd:s:rq" o; do
++    case "$o" in
++    d) DEV="$OPTARG";;
++    h) usage_and_exit 0;;
++    r) ROPT="regen";;
++    s) SLT="$OPTARG";;
++    q) QOPT="quiet";;
++    *) usage_and_exit 1;;
++    esac
++done
++
++### get luks metadata
++
++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 ! DATA_CODED=$(clevis_luks_read_slot "${DEV}" "${SLT}"); then
++    # Error message was already displayed by clevis_luks_read_slot(),
++    # at this point.
++    exit 1
++fi
++
++EXE="$(findexe clevis-luks-report-decode)"
++RESULT="$($EXE "${DATA_CODED}")"
++
++if [ -n "$RESULT" ]; then
++    echo "$RESULT"
++    echo "Report detected that some keys were rotated."
++    if [ -z "$QOPT" ]; then
++        if [ -z "$ROPT" ]; then
++            read -r -p "Do you want to regenerate luks metadata with \"clevis luks regen -d $DEV -s $SLT\"? [ynYN] " ans < /dev/tty
++            [[ "$ans" =~ ^[yY]$ ]] && ROPT="regen"
++        fi
++    fi
++else
++    exit 0
++fi
++
++if [ "$ROPT" = "regen" ]; then
++    EXE="$(findexe clevis-luks-regen)"
++    exec "$EXE" -d "$DEV" -s "$SLT"
++else
++    if [ -n "${RESULT}" ]; then
++        # Keys were rotated.
++        exit 1
++    fi
++fi
+diff --git a/src/luks/clevis-luks-report-compare b/src/luks/clevis-luks-report-compare
+new file mode 100755
+index 0000000..2ba5132
+--- /dev/null
++++ b/src/luks/clevis-luks-report-compare
+@@ -0,0 +1,71 @@
++#!/usr/bin/bash -e
++# vim: set tabstop=8 shiftwidth=4 softtabstop=4 expandtab smarttab colorcolumn=80:
++#
++# Copyright (c) 2018 Red Hat, Inc.
++# Author: Radovan Sroka <rsroka@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/>.
++#
++
++SUMMARY="Compare two sets of keys"
++
++if [ "$1" == "--summary" ]; then
++    echo "$SUMMARY"
++    exit 1
++fi
++
++if [ -z "$1" ]; then
++    echo "$0 missing the first argument!"
++    exit 1
++fi
++
++if [ -z "$2" ]; then
++    echo "$0 missing the second argument!"
++    exit 1
++fi
++
++ADV_KEYS="$1" # keys from advertisement
++LUKS_KEYS="$2" # keys from luks metadata
++
++### iterate over adv keys and make thumbprints
++CNT=0
++declare -a ADV_KEYS_ARRAY
++while res="$(jose fmt -j- -g keys -g"$CNT" -o- <<< "$ADV_KEYS")"; do
++    thp="$(echo "$res" | jose jwk thp -i-)"
++    ADV_KEYS_ARRAY["$CNT"]="$thp"
++    CNT=$(( CNT + 1 ))
++done
++
++CNT=0
++while key="$(jose fmt -j- -g keys -g"$CNT" -o- <<< "$LUKS_KEYS")"; do
++    thp="$(echo "$key" | jose jwk thp -i-)"
++
++    FOUND=0
++    for k in "${ADV_KEYS_ARRAY[@]}"
++    do
++        if [ "$k" = "$thp" ]; then
++            FOUND=1
++            break
++        fi
++    done
++
++    if [ "$FOUND" -eq "0" ]; then
++        echo "Key \"$thp\" is not in the advertisement and was probably rotated!"
++        echo "$key"
++        echo
++    fi
++    CNT=$(( CNT + 1 ))
++done
++
++exit 0
+diff --git a/src/luks/clevis-luks-report-decode b/src/luks/clevis-luks-report-decode
+new file mode 100755
+index 0000000..f39d1e9
+--- /dev/null
++++ b/src/luks/clevis-luks-report-decode
+@@ -0,0 +1,59 @@
++#!/usr/bin/bash -e
++# vim: set tabstop=8 shiftwidth=4 softtabstop=4 expandtab smarttab colorcolumn=80:
++#
++# Copyright (c) 2018 Red Hat, Inc.
++# Author: Radovan Sroka <rsroka@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/>.
++#
++
++. clevis-luks-common-functions
++
++SUMMARY="Decode luks header"
++
++if [ "$1" == "--summary" ]; then
++    echo "$SUMMARY"
++    exit 1
++fi
++
++if [ -z "$1" ]; then
++    echo "$0 missing the first argument!"
++    exit 1
++fi
++
++DATA_CODED="$1"
++
++if DATA_CODED="$(jose jwe fmt -i- <<< "$DATA_CODED")"; then
++    DATA_CODED="$(jose fmt -j- -g protected -u- <<< "$DATA_CODED")"
++    DATA_DECODED="$(jose b64 dec -i- <<< "$DATA_CODED")"
++else
++    echo "Error decoding JWE protected header!" >&2
++    exit 1
++fi
++
++### get pin and url
++
++if ! PIN="$(jose fmt -j- -g clevis -g pin -u- <<< "$DATA_DECODED")" || [ -z "$PIN" ]; then
++    echo "Pin wasn't found in luks metadata!" >&2
++    exit 1
++fi
++
++if ! CONTENT="$(jose fmt -j- -g clevis -g "$PIN" -o- <<< "$DATA_DECODED")" || [ -z "$CONTENT" ]; then
++    echo "Content wasn't found!" >&2
++    exit 1
++fi
++
++EXE="$(findexe clevis-luks-report-"$PIN")"
++
++exec "$EXE" "$CONTENT"
+diff --git a/src/luks/clevis-luks-report-sss b/src/luks/clevis-luks-report-sss
+new file mode 100755
+index 0000000..1dba4c1
+--- /dev/null
++++ b/src/luks/clevis-luks-report-sss
+@@ -0,0 +1,53 @@
++#!/bin/bash -e
++# vim: set tabstop=8 shiftwidth=4 softtabstop=4 expandtab smarttab colorcolumn=80:
++#
++# Copyright (c) 2018 Red Hat, Inc.
++# Author: Radovan Sroka <rsroka@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/>.
++#
++
++. clevis-luks-common-functions
++
++SUMMARY="SSS report plugin"
++
++if [ "$1" == "--summary" ]; then
++    echo "$SUMMARY"
++    exit 1
++fi
++
++if [ -z "$1" ]; then
++    echo "$0 missing the first argument!" >&2
++    exit 1
++fi
++
++CONTENT="$1" # sss content
++
++CNT=0
++while DATA_CODED="$(jose fmt -j- -g jwe -g"$CNT" -u- <<< "$CONTENT")"; do
++    if [ -z "$DATA_CODED" ]; then
++        CNT=$(( CNT + 1 ))
++        continue # in some cases it can be empty string
++    fi
++
++    EXE="$(findexe clevis-luks-report-decode)"
++    if ! $EXE "$DATA_CODED"; then
++        echo "Failed" >&2
++        exit 1
++    fi
++
++    CNT=$(( CNT + 1 ))
++done
++
++exit 0
+diff --git a/src/luks/clevis-luks-report-tang b/src/luks/clevis-luks-report-tang
+new file mode 100755
+index 0000000..07f2a72
+--- /dev/null
++++ b/src/luks/clevis-luks-report-tang
+@@ -0,0 +1,67 @@
++#!/usr/bin/bash -e
++# vim: set tabstop=8 shiftwidth=4 softtabstop=4 expandtab smarttab colorcolumn=80:
++#
++# Copyright (c) 2018 Red Hat, Inc.
++# Author: Radovan Sroka <rsroka@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/>.
++#
++
++. clevis-luks-common-functions
++
++SUMMARY="Tang report plugin"
++
++if [ "$1" == "--summary" ]; then
++    echo "$SUMMARY"
++    exit 1
++fi
++
++if [ -z "$1" ]; then
++    echo "$0 missing the first argument!"
++    exit 1
++fi
++
++CONTENT="$1"
++
++### Get the advertisement
++if ! URL="$(jose fmt -j- -g url -u- <<< "$CONTENT")" || [ -z "$URL" ]; then
++    echo "URL was not found!" >&2
++    exit 1
++fi
++
++if ! jws="$(curl -sfg "$URL/adv")"; then
++    echo "Unable to fetch advertisement: $URL/adv!" >&2
++    exit 1
++fi
++
++if ! TANG_KEYS="$(jose fmt -j- -Og payload -SyOg keys -AUo- <<< "$jws")"; then
++    echo "Advertisement is malformed!" >&2
++    exit 1
++fi
++
++### Check advertisement validity
++ver="$(jose jwk use -i- -r -u verify -o- <<< "$TANG_KEYS")"
++if ! jose jws ver -i "$jws" -k- -a <<< "$ver"; then
++    echo "Advertisement is missing signatures!" >&2
++    exit 1
++fi
++
++if ! LUKS_KEYS="$(jose fmt -j- -g adv -o- <<< "$CONTENT")" || [ -z "$LUKS_KEYS" ]; then
++    echo "LUKS keys from LUKS metadata were not found!" >&2
++    exit 1
++fi
++
++EXE="$(findexe clevis-luks-report-compare)"
++
++exec "$EXE" "$TANG_KEYS" "$LUKS_KEYS"
+diff --git a/src/luks/clevis-luks-report.1.adoc b/src/luks/clevis-luks-report.1.adoc
+new file mode 100644
+index 0000000..cf42afe
+--- /dev/null
++++ b/src/luks/clevis-luks-report.1.adoc
+@@ -0,0 +1,41 @@
++CLEVIS-LUKS-REPORT(1)
++=====================
++:doctype: manpage
++
++
++== NAME
++
++clevis-luks-report - Reports whether a pin bound to a LUKS1 or LUKS2 volume has been rotated
++
++== SYNOPSIS
++
++*clevis luks report* -d DEV -s SLT
++
++== OVERVIEW
++
++The *clevis luks report* command checks a given slot of a LUKS device and reports whether the pin bound to it
++-- if any -- has been rotated.
++
++== OPTIONS
++
++* *-d* _DEV_ :
++  The bound LUKS device
++
++* *-s* _SLT_ :
++  The slot or key slot number for the pin to be verified
++
++* *-q* :
++  Quiet mode. If used, we will not prompt whether to regenerate data with *clevis luks regen*
++
++* *-r* :
++  Regenerates LUKS metadata with *clevis luks regen -d DEV -s SLOT*
++
++== EXAMPLE
++
++    Check whether the pin bound to slot 1 in /dev/sda1 has been rotated:
++
++    # clevis luks report -d /dev/sda1 -s 1
++
++== SEE ALSO
++
++link:clevis-luks-regen.1.adoc[*clevis-luks-regen*(1)]
+diff --git a/src/luks/meson.build b/src/luks/meson.build
+index f21388d..ee588c3 100644
+--- a/src/luks/meson.build
++++ b/src/luks/meson.build
+@@ -47,6 +47,13 @@ if libcryptsetup.found() and luksmeta.found() and pwmake.found()
+ 
+   bins += join_paths(meson.current_source_dir(), 'clevis-luks-regen')
+   mans += join_paths(meson.current_source_dir(), 'clevis-luks-regen.1')
++
++  bins += join_paths(meson.current_source_dir(), 'clevis-luks-report')
++  bins += join_paths(meson.current_source_dir(), 'clevis-luks-report-compare')
++  bins += join_paths(meson.current_source_dir(), 'clevis-luks-report-decode')
++  bins += join_paths(meson.current_source_dir(), 'clevis-luks-report-sss')
++  bins += join_paths(meson.current_source_dir(), 'clevis-luks-report-tang')
++  mans += join_paths(meson.current_source_dir(), 'clevis-luks-report.1')
+ else
+   warning('Will not install LUKS support due to missing dependencies!')
+ endif
+-- 
+2.18.4
+
diff --git a/SOURCES/0008-Use-one-clevis-luks-askpass-per-device.patch b/SOURCES/0008-Use-one-clevis-luks-askpass-per-device.patch
new file mode 100644
index 0000000..b9f0532
--- /dev/null
+++ b/SOURCES/0008-Use-one-clevis-luks-askpass-per-device.patch
@@ -0,0 +1,339 @@
+From 3250784e99016d9f920892dbb1438b9e76fb210b Mon Sep 17 00:00:00 2001
+From: Sergio Correia <scorreia@redhat.com>
+Date: Sun, 10 May 2020 15:57:23 -0300
+Subject: [PATCH 8/8] Use one clevis-luks-askpass per device
+
+This should improve the reliability of the boot unlocking, especially
+when unlocking multiple devices upon boot.
+
+It also greatly simplifies the configuration, as there is no need to
+enable any systemd units manually nor add _netdev to either fstab or
+crypttab.
+---
+ src/luks/clevis-luks-common-functions         |  8 ++
+ src/luks/clevis-luks-unlockers.7.adoc         | 16 +---
+ src/luks/systemd/clevis-luks-askpass          | 81 ++++++-------------
+ src/luks/systemd/clevis-luks-askpass.path     | 10 ---
+ .../systemd/clevis-luks-askpass.service.in    |  8 --
+ src/luks/systemd/clevis-luks-askpass@.path    | 12 +++
+ .../systemd/clevis-luks-askpass@.service.in   |  8 ++
+ .../systemd/dracut/clevis/module-setup.sh.in  | 23 ++++++
+ src/luks/systemd/meson.build                  |  6 +-
+ 9 files changed, 80 insertions(+), 92 deletions(-)
+ delete mode 100644 src/luks/systemd/clevis-luks-askpass.path
+ delete mode 100644 src/luks/systemd/clevis-luks-askpass.service.in
+ create mode 100644 src/luks/systemd/clevis-luks-askpass@.path
+ create mode 100644 src/luks/systemd/clevis-luks-askpass@.service.in
+
+diff --git a/src/luks/clevis-luks-common-functions b/src/luks/clevis-luks-common-functions
+index 5b515ad..c9d712a 100644
+--- a/src/luks/clevis-luks-common-functions
++++ b/src/luks/clevis-luks-common-functions
+@@ -555,3 +555,11 @@ clevis_luks_restore_dev() {
+     fi
+     return 0
+ }
++
++# clevis_is_luks_device_by_uuid_open() checks whether the LUKS device with
++# given UUID is open.
++clevis_is_luks_device_by_uuid_open() {
++    local LUKS_UUID="${1}"
++    [ -z "${LUKS_UUID}" ] && return 1
++    test -b /dev/disk/by-id/dm-uuid-*"${LUKS_UUID//-/}"*
++}
+diff --git a/src/luks/clevis-luks-unlockers.7.adoc b/src/luks/clevis-luks-unlockers.7.adoc
+index 161b73a..e8d47ba 100644
+--- a/src/luks/clevis-luks-unlockers.7.adoc
++++ b/src/luks/clevis-luks-unlockers.7.adoc
+@@ -26,7 +26,7 @@ You can unlock a LUKS volume manually using the following command:
+ 
+ For more information, see link:clevis-luks-unlock.1.adoc[*clevis-luks-unlock*(1)].
+ 
+-== EARLY BOOT UNLOCKING
++== BOOT UNLOCKING
+ 
+ If Clevis integration does not already ship in your initramfs, you may need to
+ rebuild your initramfs with this command:
+@@ -34,23 +34,13 @@ rebuild your initramfs with this command:
+     $ sudo dracut -f
+ 
+ Once Clevis is integrated into your initramfs, a simple reboot should unlock
+-your root volume. Note, however, that early boot integration only works for the
+-root volume. Non-root volumes should use the late boot unlocker.
++your clevis-bound volumes. Root volumes will be unlocked in early-boot, while the
++remaining volumes will be unlocked after dracut switch-root.
+ 
+ Dracut will bring up your network using DHCP by default. If you need to specify
+ additional network parameters, such as static IP configuration, please consult
+ the dracut documentation.
+ 
+-== LATE BOOT UNLOCKING
+-
+-You can enable late boot unlocking by executing the following command:
+-
+-    $ sudo systemctl enable clevis-luks-askpass.path
+-
+-After a reboot, Clevis will attempt to unlock all *_netdev* devices listed in
+-*/etc/crypttab* when systemd prompts for their passwords. This implies that
+-systemd support for *_netdev* is required.
+-
+ == DESKTOP UNLOCKING
+ 
+ When the udisks2 unlocker is installed, your GNOME desktop session should
+diff --git a/src/luks/systemd/clevis-luks-askpass b/src/luks/systemd/clevis-luks-askpass
+index 9fea6aa..20294e5 100755
+--- a/src/luks/systemd/clevis-luks-askpass
++++ b/src/luks/systemd/clevis-luks-askpass
+@@ -19,96 +19,61 @@
+ # along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ #
+ 
+-UUID=cb6e8904-81ff-40da-a84a-07ab9ab5715e
++. clevis-luks-common-functions
+ 
+ shopt -s nullglob
+ 
+ path=/run/systemd/ask-password
+-while getopts ":lp:" o; do
++while getopts ":lp:u:" o; do
+     case "$o" in
+     l) loop=true;;
+     p) path="$OPTARG";;
++    u) device_uuid=$OPTARG;;
++    *) ;;
+     esac
+ done
+ 
+-luks1_decrypt() {
+-    luksmeta load "$@" \
+-        | clevis decrypt
+-
+-    local rc
+-    for rc in "${PIPESTATUS[@]}"; do
+-        [ $rc -eq 0 ] || return $rc
+-    done
+-    return 0
+-}
+-
+-luks2_jwe() {
+-    # jose jwe fmt -c outputs extra \n, so clean it up
+-    cryptsetup token export "$@" \
+-        | jose fmt -j- -Og jwe -o- \
+-        | jose jwe fmt -i- -c \
+-        | tr -d '\n'
+-
+-    local rc
+-    for rc in "${PIPESTATUS[@]}"; do
+-        [ $rc -eq 0 ] || return $rc
+-    done
+-    return 0
+-}
+-
+ while true; do
+     todo=0
+ 
+     for question in "$path"/ask.*; do
+-        metadata=false
+         unlocked=false
+         d=
+         s=
+ 
+-        while read line; do
++        while read -r line; do
+             case "$line" in
+                 Id=cryptsetup:*) d="${line##Id=cryptsetup:}";;
+                 Socket=*) s="${line##Socket=}";;
+             esac
+         done < "$question"
+ 
+-        [ "$d" ] && [ "$s" ] || continue
++        [ -b "${d}" ] || continue
++        [ -S "${s}" ] || continue
+ 
+-        if cryptsetup isLuks --type luks1 "$d"; then
+-            # If the device is not initialized, sliently skip it.
+-            luksmeta test -d "$d" || continue
+-
+-            while read -r slot state uuid; do
+-                [ "$state" == "active" ] || continue
+-                [ "$uuid" == "$UUID" ] || continue
+-                metadata=true
+-
+-                if pt="$(luks1_decrypt -d "$d" -s "$slot" -u "$UUID")"; then
+-                    echo -n "+$pt" | ncat -U -u --send-only "$s"
+-                    unlocked=true
+-                    break
+-                fi
+-            done < <(luksmeta show -d "$d")
+-        elif cryptsetup isLuks --type luks2 "$d"; then
+-            while read -r id; do
+-                jwe="$(luks2_jwe --token-id "$id" "$d")" \
+-                    || continue
+-                metadata=true
++        if [ -n "${device_uuid}" ]; then
++            uuid="$(cryptsetup luksUUID "${d}")"
++            [ "${uuid}" != "${device_uuid}" ] && todo=1 && continue
++        fi
+ 
+-                if pt="$(echo -n "$jwe" | clevis decrypt)"; then
+-                    echo -n "+$pt" | ncat -U -u --send-only "$s"
+-                    unlocked=true
+-                    break
+-                fi
+-            done < <(cryptsetup luksDump "$d" | sed -rn 's|^\s+([0-9]+): clevis|\1|p')
++        if pt="$(clevis_luks_unlock_device "${d}")"; then
++            echo -n "+$pt" | ncat -U -u --send-only "$s"
++            unlocked=true
+         fi
+ 
+-        [ "$metadata" == true ] || continue
++        [ -n "${device_uuid}" ] && [ "${unlocked}" == true ] && break
+         [ "$unlocked" == true ] && continue
+         ((todo++))
+     done
+ 
+-    if [ $todo -eq 0 ] || [ "$loop" != true ]; then
++    if [ -n "${device_uuid}" ]; then
++        [ ! -b /dev/disk/by-uuid/"${device_uuid}" ] && break
++        if clevis_is_luks_device_by_uuid_open "${device_uuid}"; then
++            break
++        fi
++    fi
++
++    if [ "$todo" -eq 0 ] || [ "$loop" != true ]; then
+         break;
+     fi
+ 
+diff --git a/src/luks/systemd/clevis-luks-askpass.path b/src/luks/systemd/clevis-luks-askpass.path
+deleted file mode 100644
+index a4d01ba..0000000
+--- a/src/luks/systemd/clevis-luks-askpass.path
++++ /dev/null
+@@ -1,10 +0,0 @@
+-[Unit]
+-Description=Clevis systemd-ask-password Watcher
+-Before=remote-fs-pre.target
+-Wants=remote-fs-pre.target
+-
+-[Path]
+-PathChanged=/run/systemd/ask-password
+-
+-[Install]
+-WantedBy=remote-fs.target
+diff --git a/src/luks/systemd/clevis-luks-askpass.service.in b/src/luks/systemd/clevis-luks-askpass.service.in
+deleted file mode 100644
+index 2c6bbed..0000000
+--- a/src/luks/systemd/clevis-luks-askpass.service.in
++++ /dev/null
+@@ -1,8 +0,0 @@
+-[Unit]
+-Description=Clevis LUKS systemd-ask-password Responder
+-Requires=network-online.target
+-After=network-online.target
+-
+-[Service]
+-Type=oneshot
+-ExecStart=@libexecdir@/clevis-luks-askpass -l
+diff --git a/src/luks/systemd/clevis-luks-askpass@.path b/src/luks/systemd/clevis-luks-askpass@.path
+new file mode 100644
+index 0000000..3f23665
+--- /dev/null
++++ b/src/luks/systemd/clevis-luks-askpass@.path
+@@ -0,0 +1,12 @@
++[Unit]
++Description=Clevis systemd-ask-password Watcher for %i
++DefaultDependencies=no
++Conflicts=shutdown.target
++Before=basic.target shutdown.target
++
++[Path]
++DirectoryNotEmpty=/run/systemd/ask-password
++MakeDirectory=yes
++
++[Install]
++WantedBy=basic.target
+diff --git a/src/luks/systemd/clevis-luks-askpass@.service.in b/src/luks/systemd/clevis-luks-askpass@.service.in
+new file mode 100644
+index 0000000..4165ec5
+--- /dev/null
++++ b/src/luks/systemd/clevis-luks-askpass@.service.in
+@@ -0,0 +1,8 @@
++[Unit]
++Description=Clevis LUKS systemd-ask-password Responder for luks-%i
++DefaultDependencies=no
++Conflicts=shutdown.target
++Before=shutdown.target
++
++[Service]
++ExecStart=@libexecdir@/clevis-luks-askpass -u %i
+diff --git a/src/luks/systemd/dracut/clevis/module-setup.sh.in b/src/luks/systemd/dracut/clevis/module-setup.sh.in
+index abc79b3..1a0d6f7 100755
+--- a/src/luks/systemd/dracut/clevis/module-setup.sh.in
++++ b/src/luks/systemd/dracut/clevis/module-setup.sh.in
+@@ -23,6 +23,24 @@ depends() {
+     return 255
+ }
+ 
++configure_passwd_watchers() {
++    if ! command -v systemctl >/dev/null; then
++        return 1
++    fi
++
++    find /etc/systemd/system/ -name "clevis-luks-askpass*" -exec rm -f {} \;
++
++    local uuid
++    for dev in $(lsblk -p -n -s -r \
++                 | awk '$6 == "crypt" { getline; print $1 }' | sort -u); do
++        uuid=$(cryptsetup luksUUID "${dev}")
++
++        if clevis luks list -d "${dev}" >/dev/null 2>/dev/null; then
++            systemctl enable "clevis-luks-askpass@${uuid}.path" 2>/dev/null
++        fi
++    done
++}
++
+ install() {
+     inst_hook initqueue/online 60 "$moddir/clevis-hook.sh"
+     inst_hook initqueue/settled 60 "$moddir/clevis-hook.sh"
+@@ -30,6 +48,10 @@ install() {
+     inst_multiple \
+ 	/etc/services \
+         @libexecdir@/clevis-luks-askpass \
++        clevis-luks-common-functions \
++        head \
++        grep \
++        sed \
+         clevis-decrypt \
+         cryptsetup \
+         luksmeta \
+@@ -38,5 +60,6 @@ install() {
+         jose \
+         ncat
+ 
++    configure_passwd_watchers
+     dracut_need_initqueue
+ }
+diff --git a/src/luks/systemd/meson.build b/src/luks/systemd/meson.build
+index 369e7f7..334e84c 100644
+--- a/src/luks/systemd/meson.build
++++ b/src/luks/systemd/meson.build
+@@ -6,13 +6,13 @@ if systemd.found()
+   unitdir = systemd.get_pkgconfig_variable('systemdsystemunitdir')
+ 
+   configure_file(
+-    input: 'clevis-luks-askpass.service.in',
+-    output: 'clevis-luks-askpass.service',
++    input: 'clevis-luks-askpass@.service.in',
++    output: 'clevis-luks-askpass@.service',
+     install_dir: unitdir,
+     configuration: data,
+   )
+ 
+-  install_data('clevis-luks-askpass.path', install_dir: unitdir)
++  install_data('clevis-luks-askpass@.path', install_dir: unitdir)
+   install_data('clevis-luks-askpass', install_dir: libexecdir)
+ else
+   warning('Will not install systemd support due to missing dependencies!')
+-- 
+2.18.4
+
diff --git a/SOURCES/0009-Introduce-y-assume-yes-argument-to-clevis-luks-bind.patch b/SOURCES/0009-Introduce-y-assume-yes-argument-to-clevis-luks-bind.patch
new file mode 100644
index 0000000..0e54343
--- /dev/null
+++ b/SOURCES/0009-Introduce-y-assume-yes-argument-to-clevis-luks-bind.patch
@@ -0,0 +1,555 @@
+From 7b1639b2194a8bfbb0daedf1cbdfc4ebef5f6b31 Mon Sep 17 00:00:00 2001
+From: Sergio Correia <scorreia@redhat.com>
+Date: Mon, 18 May 2020 08:36:17 -0300
+Subject: [PATCH] Introduce -y (assume yes) argument to clevis luks bind
+
+In order to simplify automated operations with e.g. ansible,
+it would be helpful to have a way to automate the creation of
+bindings with clevis.
+
+In simple scenarios, it's possible to download the advertisement
+from a tang server and pass it in the binding configuration, to
+do the binding offline, in the following way:
+
+curl -sfg http://tang.server/adv -o adv.jws
+
+clevis luks bind -d /dev/sda2 tang '{"url":"http://tang.server", "adv":"adv.jws}'
+
+However, for more complex scenarios using multiple servers with
+the sss pin, it becomes a lot more complicated to do the same
+thing and do the binding in an automated fashion. An alternative
+would be to use expect (tcl), but it can also be complicated.
+
+In this commit we introduce -y as a parameter to clevis luks bind,
+meanining _assume yes_. Essentially, this would make it so that
+the user would not have to manually trust tang key(s) by typing
+y/yes.
+
+Security-wise, it would be similar to downloading the advertisement
+manually and passing it to tang as the "adv" configuration option,
+something already supported.
+
+We already have a -f parameter, so we picked something different,
+not to change existing behavior and possibly break existing scripts.
+---
+ src/luks/clevis-luks-bind.1.adoc         |  7 +-
+ src/luks/clevis-luks-bind.in             | 11 +++-
+ src/luks/clevis-luks-regen               |  4 +-
+ src/luks/tests/assume-yes-luks1          | 81 ++++++++++++++++++++++++
+ src/luks/tests/assume-yes-luks2          | 81 ++++++++++++++++++++++++
+ src/luks/tests/meson.build               |  2 +
+ src/pins/sss/clevis-encrypt-sss.1.adoc   | 14 +++-
+ src/pins/sss/clevis-encrypt-sss.c        | 30 ++++++---
+ src/pins/tang/clevis-encrypt-tang        | 35 ++++++----
+ src/pins/tang/clevis-encrypt-tang.1.adoc | 11 +++-
+ 10 files changed, 246 insertions(+), 30 deletions(-)
+ create mode 100755 src/luks/tests/assume-yes-luks1
+ create mode 100755 src/luks/tests/assume-yes-luks2
+
+diff --git a/src/luks/clevis-luks-bind.1.adoc b/src/luks/clevis-luks-bind.1.adoc
+index 336c0f4..438e517 100644
+--- a/src/luks/clevis-luks-bind.1.adoc
++++ b/src/luks/clevis-luks-bind.1.adoc
+@@ -9,7 +9,7 @@ clevis-luks-bind - Bind a LUKS device using the specified policy
+ 
+ == SYNOPSIS
+ 
+-*clevis luks bind* [-f] -d DEV [-s SLT] [-k KEY] PIN CFG
++*clevis luks bind* [-f] [-y] -d DEV [-s SLT] [-k KEY] PIN CFG
+ 
+ == OVERVIEW
+ 
+@@ -34,6 +34,11 @@ Clevis LUKS unlockers. See link:clevis-luks-unlockers.7.adoc[*clevis-luks-unlock
+ * *-f* :
+   Do not prompt for LUKSMeta initialization
+ 
++* *-y* :
++  Automatically answer yes for all questions. When using _tang_, it
++  causes the advertisement trust check to be skipped, which can be
++  useful in automated deployments
++
+ * *-d* _DEV_ :
+   The LUKS device on which to perform binding
+ 
+diff --git a/src/luks/clevis-luks-bind.in b/src/luks/clevis-luks-bind.in
+index 89a5e22..8b8b5ee 100755
+--- a/src/luks/clevis-luks-bind.in
++++ b/src/luks/clevis-luks-bind.in
+@@ -33,12 +33,14 @@ function luks2_supported() {
+ function usage() {
+     exec >&2
+     echo
+-    echo "Usage: clevis luks bind [-f] [-s SLT] [-k KEY] -d DEV PIN CFG"
++    echo "Usage: clevis luks bind [-f] [-y] [-s SLT] [-k KEY] -d DEV PIN CFG"
+     echo
+     echo "$SUMMARY":
+     echo
+     echo "  -f      Do not prompt for LUKSMeta initialization"
+     echo
++    echo "  -y      Automatically answer yes for all questions"
++    echo
+     echo "  -d DEV  The LUKS device on which to perform binding"
+     echo
+     echo "  -s SLT  The LUKS slot to use"
+@@ -55,12 +57,15 @@ if [ $# -eq 1 ] && [ "$1" == "--summary" ]; then
+ fi
+ 
+ FRC=()
+-while getopts ":hfd:s:k:" o; do
++YES=()
++while getopts ":fyd:s:k:" o; do
+     case "$o" in
+     f) FRC+=(-f);;
+     d) DEV="$OPTARG";;
+     s) SLT="$OPTARG";;
+     k) KEY="$OPTARG";;
++    y) FRC+=(-f)
++       YES+=(-y);;
+     *) usage;;
+     esac
+ done
+@@ -139,7 +144,7 @@ cryptsetup luksDump "$DEV" \
+ )")"
+ 
+ # Encrypt the new key
+-jwe="$(echo -n "$key" | clevis encrypt "$PIN" "$CFG")"
++jwe="$(echo -n "$key" | clevis encrypt "$PIN" "$CFG" "${YES}")"
+ 
+ # If necessary, initialize the LUKS volume
+ if [ "$luks_type" == "luks1" ] && ! luksmeta test -d "$DEV"; then
+diff --git a/src/luks/clevis-luks-regen b/src/luks/clevis-luks-regen
+index 44fd673..6071d85 100755
+--- a/src/luks/clevis-luks-regen
++++ b/src/luks/clevis-luks-regen
+@@ -110,7 +110,7 @@ if ! new_passphrase=$(generate_key "${DEV}"); then
+ fi
+ 
+ # Reencrypt the new password.
+-if ! jwe=$(clevis encrypt "${PIN}" "${CFG}" <<< "${new_passphrase}"); then
++if ! jwe="$(clevis encrypt "${PIN}" "${CFG}" <<< "${new_passphrase}")"; then
+     echo "Error using pin '${PIN}' with config '${CFG}'" >&2
+     exit 1
+ fi
+@@ -176,7 +176,7 @@ 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
++        <<< "$(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
+diff --git a/src/luks/tests/assume-yes-luks1 b/src/luks/tests/assume-yes-luks1
+new file mode 100755
+index 0000000..ad9dea4
+--- /dev/null
++++ b/src/luks/tests/assume-yes-luks1
+@@ -0,0 +1,81 @@
++#!/bin/bash -ex
++# vim: set ts=8 shiftwidth=4 softtabstop=4 expandtab smarttab colorcolumn=80:
++#
++# Copyright (c) 2020 Red Hat, Inc.
++# Author: Sergio Correia <scorreia@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)"
++
++port=$(get_random_port)
++tang_run "${TMP}" "${port}" &
++tang_wait_until_ready "${port}"
++
++url="http://${TANG_HOST}:${port}"
++
++cfg=$(printf '{"url":"%s"}' "$url")
++
++# LUKS1.
++DEV="${TMP}/luks1-device"
++new_device "luks1" "${DEV}"
++
++if ! clevis luks bind -y -d "${DEV}" tang "${cfg}" <<< "${DEFAULT_PASS}"; then
++    error "${TEST}: Bind should have succeeded."
++fi
++
++if ! clevis_luks_unlock_device "${DEV}"; then
++    error "${TEST}: we were unable to unlock ${DEV}."
++fi
++
++# Let's use a second tang server to test the sss pin.
++TMP2="$(mktemp -d)"
++
++port2=$(get_random_port)
++tang_run "${TMP2}" "${port2}" &
++tang_wait_until_ready "${port2}"
++
++url2="http://${TANG_HOST}:${port2}"
++
++cfg2=$(printf '{"t":1,"pins":{"tang":[{"url":"%s"},{"url":"%s"}]}}' \
++       "${url1}" "${url2}")
++
++# LUKS1.
++new_device "luks1" "${DEV}"
++# Now let's test the sss pin with the two test tang servers we deployed.
++if ! clevis luks bind -y -d "${DEV}" sss "${cfg2}" <<< "${DEFAULT_PASS}"; then
++    error "${TEST}: Bind should have succeeded."
++fi
++
++# Unlock should still work now.
++if ! clevis_luks_unlock_device "${DEV}"; then
++    error "${TEST}: we should still be able to unlock ${DEV}"
++fi
+diff --git a/src/luks/tests/assume-yes-luks2 b/src/luks/tests/assume-yes-luks2
+new file mode 100755
+index 0000000..5c0edc3
+--- /dev/null
++++ b/src/luks/tests/assume-yes-luks2
+@@ -0,0 +1,81 @@
++#!/bin/bash -ex
++# vim: set ts=8 shiftwidth=4 softtabstop=4 expandtab smarttab colorcolumn=80:
++#
++# Copyright (c) 2020 Red Hat, Inc.
++# Author: Sergio Correia <scorreia@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)"
++
++port=$(get_random_port)
++tang_run "${TMP}" "${port}" &
++tang_wait_until_ready "${port}"
++
++url="http://${TANG_HOST}:${port}"
++
++cfg=$(printf '{"url":"%s"}' "$url")
++
++# LUKS2.
++DEV="${TMP}/luks2-device"
++new_device "luks2" "${DEV}"
++
++if ! clevis luks bind -y -d "${DEV}" tang "${cfg}" <<< "${DEFAULT_PASS}"; then
++    error "${TEST}: Bind should have succeeded."
++fi
++
++if ! clevis_luks_unlock_device "${DEV}"; then
++    error "${TEST}: we were unable to unlock ${DEV}."
++fi
++
++# Let's use a second tang server to test the sss pin.
++TMP2="$(mktemp -d)"
++
++port2=$(get_random_port)
++tang_run "${TMP2}" "${port2}" &
++tang_wait_until_ready "${port2}"
++
++url2="http://${TANG_HOST}:${port2}"
++
++cfg2=$(printf '{"t":1,"pins":{"tang":[{"url":"%s"},{"url":"%s"}]}}' \
++       "${url1}" "${url2}")
++
++# LUKS2.
++new_device "luks2" "${DEV}"
++# Now let's test the sss pin with the two test tang servers we deployed.
++if ! clevis luks bind -y -d "${DEV}" sss "${cfg2}" <<< "${DEFAULT_PASS}"; then
++    error "${TEST}: Bind should have succeeded."
++fi
++
++# Unlock should still work now.
++if ! clevis_luks_unlock_device "${DEV}"; then
++    error "${TEST}: we should still be able to unlock ${DEV}"
++fi
+diff --git a/src/luks/tests/meson.build b/src/luks/tests/meson.build
+index dbef9bf..4795488 100644
+--- a/src/luks/tests/meson.build
++++ b/src/luks/tests/meson.build
+@@ -85,6 +85,7 @@ endif
+ 
+ if has_tang
+   test('unlock-tang-luks1', find_program('unlock-tang-luks1'), env: env, timeout: 90)
++  test('assume-yes-luks1', find_program('assume-yes-luks1'), env: env)
+ endif
+ test('pass-tang-luks1', find_program('pass-tang-luks1'), env: env)
+ test('backup-restore-luks1', find_program('backup-restore-luks1'), env: env)
+@@ -108,6 +109,7 @@ if luksmeta_data.get('OLD_CRYPTSETUP') == '0'
+ 
+   if has_tang
+     test('unlock-tang-luks2', find_program('unlock-tang-luks2'), env: env, timeout: 120)
++    test('assume-yes-luks2', find_program('assume-yes-luks2'), env: env, timeout: 60)
+   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)
+diff --git a/src/pins/sss/clevis-encrypt-sss.1.adoc b/src/pins/sss/clevis-encrypt-sss.1.adoc
+index 7144e7e..7152144 100644
+--- a/src/pins/sss/clevis-encrypt-sss.1.adoc
++++ b/src/pins/sss/clevis-encrypt-sss.1.adoc
+@@ -5,11 +5,11 @@ CLEVIS-ENCRYPT-SSS(1)
+ 
+ == NAME
+ 
+-clevis-encrypt-sss - Encrypts using a Shamir's Secret Sharing policy 
++clevis-encrypt-sss - Encrypts using a Shamir's Secret Sharing policy
+ 
+ == SYNOPSIS
+ 
+-*clevis encrypt sss* CONFIG < PT > JWE
++*clevis encrypt sss* CONFIG [-y] < PT > JWE
+ 
+ == OVERVIEW
+ 
+@@ -52,6 +52,16 @@ The format of the *pins* property is as follows:
+ When the list version of the format is used, multiple pins of that type will
+ receive key fragments.
+ 
++== OPTIONS
++
++* *-y* :
++  Automatically answer yes for all questions. For the _tang_ pin, it will
++  skip the advertisement trust check, which can be useful in automated
++  deployments:
++
++    $ cfg='{"t":1,"pins":{"tang":[{"url":...},{"url":...}]}}'
++    $ clevis encrypt sss "$cfg" -y < PT > JWE
++
+ == SEE ALSO
+ 
+ link:clevis-encrypt-tang.1.adoc[*clevis-encrypt-tang*(1)],
+diff --git a/src/pins/sss/clevis-encrypt-sss.c b/src/pins/sss/clevis-encrypt-sss.c
+index d6f2c2c..531e918 100644
+--- a/src/pins/sss/clevis-encrypt-sss.c
++++ b/src/pins/sss/clevis-encrypt-sss.c
+@@ -86,9 +86,9 @@ npins(json_t *pins)
+ }
+ 
+ static json_t *
+-encrypt_frag(json_t *sss, const char *pin, const json_t *cfg)
++encrypt_frag(json_t *sss, const char *pin, const json_t *cfg, int assume_yes)
+ {
+-    char *args[] = { "clevis", "encrypt", (char *) pin, NULL, NULL };
++    char *args[] = { "clevis", "encrypt", (char *) pin, NULL, NULL, NULL };
+     json_auto_t *jwe = json_string("");
+     str_auto_t *str = NULL;
+     uint8_t *pnt = NULL;
+@@ -100,6 +100,10 @@ encrypt_frag(json_t *sss, const char *pin, const json_t *cfg)
+     if (!str)
+         return NULL;
+ 
++    if (assume_yes) {
++        args[4] = "-y";
++    }
++
+     pnt = sss_point(sss, &pntl);
+     if (!pnt)
+         return NULL;
+@@ -137,7 +141,7 @@ encrypt_frag(json_t *sss, const char *pin, const json_t *cfg)
+ }
+ 
+ static json_t *
+-encrypt_frags(json_int_t t, json_t *pins)
++encrypt_frags(json_int_t t, json_t *pins, int assume_yes)
+ {
+     const char *pname = NULL;
+     json_auto_t *sss = NULL;
+@@ -172,7 +176,7 @@ encrypt_frags(json_int_t t, json_t *pins)
+         json_array_foreach(pcfgs, i, pcfg) {
+             json_auto_t *jwe = NULL;
+ 
+-            jwe = encrypt_frag(sss, pname, pcfg);
++            jwe = encrypt_frag(sss, pname, pcfg, assume_yes);
+             if (!jwe)
+                 return NULL;
+ 
+@@ -201,14 +205,24 @@ main(int argc, char *argv[])
+     const char *iv = NULL;
+     json_t *pins = NULL;
+     json_int_t t = 1;
++    int assume_yes = 0;
+ 
+     if (argc == 2 && strcmp(argv[1], "--summary") == 0) {
+         fprintf(stdout, "%s\n", SUMMARY);
+         return EXIT_SUCCESS;
+     }
+ 
+-    if (isatty(STDIN_FILENO) || argc != 2)
+-        goto usage;
++    if (isatty(STDIN_FILENO) || argc != 2) {
++        if (argc != 3) {
++            goto usage;
++        }
++
++        if (strcmp(argv[2], "-y") == 0) {
++            assume_yes = 1;
++        } else if (strlen(argv[2]) > 0) {
++            goto usage;
++        }
++    }
+ 
+     /* Parse configuration. */
+     cfg = json_loads(argv[1], 0, NULL);
+@@ -228,7 +242,7 @@ main(int argc, char *argv[])
+         return EXIT_FAILURE;
+     }
+ 
+-    sss = encrypt_frags(t, pins);
++    sss = encrypt_frags(t, pins, assume_yes);
+     if (!sss)
+         return EXIT_FAILURE;
+ 
+@@ -287,7 +301,7 @@ main(int argc, char *argv[])
+ 
+ usage:
+     fprintf(stderr, "\n");
+-    fprintf(stderr, "Usage: clevis encrypt sss CONFIG < PLAINTEXT > JWE\n");
++    fprintf(stderr, "Usage: clevis encrypt sss CONFIG [-y] < PLAINTEXT > JWE\n");
+     fprintf(stderr, "\n");
+     fprintf(stderr, "%s\n", SUMMARY);
+     fprintf(stderr, "\n");
+diff --git a/src/pins/tang/clevis-encrypt-tang b/src/pins/tang/clevis-encrypt-tang
+index 378b25d..4a43f1f 100755
+--- a/src/pins/tang/clevis-encrypt-tang
++++ b/src/pins/tang/clevis-encrypt-tang
+@@ -28,10 +28,14 @@ fi
+ if [ -t 0 ]; then
+     exec >&2
+     echo
+-    echo "Usage: clevis encrypt tang CONFIG < PLAINTEXT > JWE"
++    echo "Usage: clevis encrypt tang CONFIG [-y] < PLAINTEXT > JWE"
+     echo
+     echo "$SUMMARY"
+     echo
++    echo "  -y              Use this option for skipping the advertisement"
++    echo "                  trust check. This can be useful in automated"
++    echo "                  deployments"
++    echo
+     echo "This command uses the following configuration properties:"
+     echo
+     echo "  url: <string>   The base URL of the Tang server (REQUIRED)"
+@@ -60,6 +64,9 @@ if ! cfg="$(jose fmt -j- -Oo- <<< "$1" 2>/dev/null)"; then
+     exit 1
+ fi
+ 
++trust=
++[ -n "${2}" ] && [ "${2}" == "-y" ] && trust=yes
++
+ if ! url="$(jose fmt -j- -Og url -u- <<< "$cfg")"; then
+     echo "Missing the required 'url' property!" >&2
+     exit 1
+@@ -100,18 +107,20 @@ if ! jose jws ver -i "$jws" -k- -a <<< "$ver"; then
+ fi
+ 
+ ### Check advertisement trust
+-if [ -z "$thp" ]; then
+-    echo "The advertisement contains the following signing keys:" >&2
+-    echo >&2
+-    jose jwk thp -i- <<< "$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
++if [ -z "${trust}" ]; then
++    if [ -z "$thp" ]; then
++        echo "The advertisement contains the following signing keys:" >&2
++        echo >&2
++        jose jwk thp -i- <<< "$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
++    fi
+ fi
+ 
+ ### Perform encryption
+diff --git a/src/pins/tang/clevis-encrypt-tang.1.adoc b/src/pins/tang/clevis-encrypt-tang.1.adoc
+index 276575f..c34d109 100644
+--- a/src/pins/tang/clevis-encrypt-tang.1.adoc
++++ b/src/pins/tang/clevis-encrypt-tang.1.adoc
+@@ -9,7 +9,7 @@ clevis-encrypt-tang - Encrypts using a Tang binding server policy
+ 
+ == SYNOPSIS
+ 
+-*clevis encrypt tang* CONFIG < PT > JWE
++*clevis encrypt tang* CONFIG [-y] < PT > JWE
+ 
+ == OVERVIEW
+ 
+@@ -76,6 +76,15 @@ This command uses the following configuration properties:
+ * *adv* (object) :
+   A trusted advertisement (raw JSON)
+ 
++== OPTIONS
++
++* *-y* :
++  Automatically answer yes for all questions. Use this option for skipping
++  the advertisement trust check. This can be useful in automated deployments:
++
++    $ clevis encrypt tang '{"url":...}' -y < PT > JWE
++
++
+ == SEE ALSO
+ 
+ link:clevis-decrypt.1.adoc[*clevis-decrypt*(1)]
+-- 
+2.18.4
+
diff --git a/SOURCES/0010-Add-clevis-luks-edit-command.patch b/SOURCES/0010-Add-clevis-luks-edit-command.patch
new file mode 100644
index 0000000..f41161f
--- /dev/null
+++ b/SOURCES/0010-Add-clevis-luks-edit-command.patch
@@ -0,0 +1,1036 @@
+From 46dc5904a9a6b0f1dcdb2511cc3f09671ef54b2a Mon Sep 17 00:00:00 2001
+From: Sergio Correia <scorreia@redhat.com>
+Date: Wed, 20 May 2020 21:09:15 -0300
+Subject: [PATCH] Add clevis luks edit command
+
+---
+ src/luks/clevis-luks-common-functions    |  65 ++++--
+ src/luks/clevis-luks-edit                | 242 +++++++++++++++++++++++
+ src/luks/clevis-luks-edit.1.adoc         |  69 +++++++
+ src/luks/clevis-luks-regen               | 125 ++----------
+ src/luks/meson.build                     |   3 +
+ src/luks/tests/edit-tang-luks1           | 106 ++++++++++
+ src/luks/tests/edit-tang-luks2           | 106 ++++++++++
+ src/luks/tests/meson.build               |  28 ++-
+ src/luks/tests/regen-inplace-luks1       |   2 +-
+ src/luks/tests/regen-inplace-luks2       |   2 +-
+ src/luks/tests/regen-not-inplace-luks1   |   2 +-
+ src/luks/tests/regen-not-inplace-luks2   |   2 +-
+ src/luks/tests/tests-common-functions.in |  26 ---
+ src/luks/tests/unlock-tang-luks1         |   7 +-
+ src/luks/tests/unlock-tang-luks2         |   8 +-
+ 15 files changed, 606 insertions(+), 187 deletions(-)
+ create mode 100755 src/luks/clevis-luks-edit
+ create mode 100644 src/luks/clevis-luks-edit.1.adoc
+ create mode 100755 src/luks/tests/edit-tang-luks1
+ create mode 100755 src/luks/tests/edit-tang-luks2
+
+diff --git a/src/luks/clevis-luks-common-functions b/src/luks/clevis-luks-common-functions
+index c9d712a..f3a875c 100644
+--- a/src/luks/clevis-luks-common-functions
++++ b/src/luks/clevis-luks-common-functions
+@@ -141,11 +141,7 @@ clevis_luks_decode_jwe() {
+     local jwe="${1}"
+ 
+     local coded
+-    if ! coded=$(jose jwe fmt -i- <<< "${jwe}"); then
+-        return 1
+-    fi
+-
+-    coded=$(jose fmt -j- -g protected -u- <<< "${coded}" | tr -d '"')
++    read -r -d . coded <<< "${jwe}"
+     jose b64 dec -i- <<< "${coded}"
+ }
+ 
+@@ -291,6 +287,46 @@ clevis_luks_read_pins_from_slot() {
+     printf "%s: %s\n" "${SLOT}" "${cfg}"
+ }
+ 
++# clevis_luks_is_key_valid() checks whether the given key is valid to unlock
++# the given device.
++clevis_luks_is_key_valid() {
++    local DEV="${1}"
++    local KEY="${2}"
++
++    if ! cryptsetup open --test-passphrase "${DEV}" \
++                         --key-file <(echo -n "${KEY}") 2>/dev/null; then
++        return 1
++    fi
++    return 0
++}
++
++# clevis_luks_unlock_device_by_slot() does the unlock of the device and slot
++# passed as parameters and returns the decoded passphrase.
++clevis_luks_unlock_device_by_slot() {
++    local DEV="${1}"
++    local SLT="${2}"
++
++    [ -z "${DEV}" ] && return 1
++    [ -z "${SLT}" ] && return 1
++
++    local jwe passphrase
++    if ! jwe="$(clevis_luks_read_slot "${DEV}" "${SLT}" 2>/dev/null)" \
++                || [ -z "${jwe}" ]; then
++        return 1
++    fi
++
++    if ! passphrase="$(clevis decrypt < <(echo -n "${jwe}") 2>/dev/null)" \
++                       || [ -z "${passphrase}" ]; then
++        return 1
++    fi
++
++    if ! clevis_luks_is_key_valid "${DEV}" "${passphrase}"; then
++        return 1
++    fi
++    echo -n "${passphrase}"
++    return 0
++}
++
+ # clevis_luks_unlock_device() does the unlock of the device passed as
+ # parameter and returns the decoded passphrase.
+ clevis_luks_unlock_device() {
+@@ -303,26 +339,15 @@ clevis_luks_unlock_device() {
+         return 1
+     fi
+ 
+-    local slt jwe passphrase
++    local slt pt
+     for slt in ${used_slots}; do
+-        if ! jwe="$(clevis_luks_read_slot "${DEV}" "${slt}" 2>/dev/null)" \
+-                   || [ -z "${jwe}" ]; then
+-            continue
+-        fi
+-
+-        if ! passphrase="$(clevis decrypt < <(echo -n "${jwe}"))" \
+-                           || [ -z "${passphrase}" ]; then
++        if ! pt=$(clevis_luks_unlock_device_by_slot "${DEV}" "${slt}") \
++                  || [ -z "${pt}" ]; then
+             continue
+         fi
+-
+-        if ! cryptsetup luksOpen --test-passphrase "${DEV}" \
+-             --key-file <(echo -n "${passphrase}"); then
+-            continue
+-        fi
+-        echo -n "${passphrase}"
++        echo -n "${pt}"
+         return 0
+     done
+-
+     return 1
+ }
+ 
+diff --git a/src/luks/clevis-luks-edit b/src/luks/clevis-luks-edit
+new file mode 100755
+index 0000000..fc95f75
+--- /dev/null
++++ b/src/luks/clevis-luks-edit
+@@ -0,0 +1,242 @@
++#!/bin/bash -e
++# vim: set ts=8 shiftwidth=4 softtabstop=4 expandtab smarttab colorcolumn=80:
++#
++# Copyright (c) 2020 Red Hat, Inc.
++# Author: Sergio Correia <scorreia@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/>.
++#
++
++. clevis-luks-common-functions
++
++SUMMARY="Edit a binding from a clevis-bound slot in a LUKS device"
++
++usage() {
++    echo >&2
++    echo "Usage: clevis luks edit [-f] -d DEV -s SLT [-c CONFIG]" >&2
++    echo >&2
++    echo "$SUMMARY": >&2
++    echo >&2
++    echo "  -d DEV     The LUKS device to edit clevis-bound pins" >&2
++    echo >&2
++    echo "  -s SLOT    The slot to use when editing the clevis binding" >&2
++    echo >&2
++    echo "  -f         Proceed with the edit operation even if the configuration is the same" >&2
++    echo >&2
++    echo "  -c CONFIG  The updated config to use" >&2
++    echo >&2
++    exit 1
++}
++
++on_exit() {
++    [ -d "$TMP" ] && rm -rf "${TMP}"
++}
++
++validate_cfg() {
++    local json="${1}"
++    jose fmt -j- -O <<< "${json}" 2>/dev/null
++}
++
++edit_cfg() {
++    local cfg_file="${1}"
++    local editor="${EDITOR:-vi}"
++
++    "${editor}" "${cfg_file}" || true
++    if ! validate_cfg "$(<"${cfg_file}")"; then
++        local ans=
++        while true; do
++            read -r -p \
++              "Malformed configuration. Would you like to edit again? [ynYN] " \
++             ans < /dev/tty
++
++            [[ "${ans}" =~ ^[nN]$ ]] && return 1
++            [[ "${ans}" =~ ^[yY]$ ]] && break
++        done
++        edit_cfg "${cfg_file}"
++    fi
++    return 0
++}
++
++if [ "${#}" -eq 1 ] && [ "${1}" = "--summary" ]; then
++    echo "${SUMMARY}"
++    exit 0
++fi
++
++CFG=
++FRC=
++while getopts ":fd:s:c:" o; do
++    case "$o" in
++    d) DEV=${OPTARG};;
++    s) SLT=${OPTARG};;
++    c) CFG=${OPTARG};;
++    f) FRC=-f;;
++    *) usage;;
++    esac
++done
++
++if [ -z "${DEV}" ]; then
++    echo "Did not specify a device!" >&2
++    usage
++fi
++
++if [ -z "${SLT}" ]; then
++    echo "Did not specify a slot!" >&2
++    usage
++fi
++
++if ! binding="$(clevis luks list -d "${DEV}" -s "${SLT}" 2>/dev/null)" \
++                || [ -z "${binding}" ]; then
++    echo "Error retrieving current configuration from ${DEV}:${SLT}" >&2
++    exit 1
++fi
++
++read -r _ pin cfg <<< "${binding}"
++# Remove single quotes.
++cfg=${cfg//\'}
++if ! pretty_cfg="$(jq . <<< "${cfg}")" || [ -z "${pretty_cfg}" ]; then
++    echo "Error reading the configuration from ${DEV}:${SLT}" >&2
++    exit 1
++fi
++
++if ! TMP="$(mktemp -d)" || [ -z "${TMP}" ]; then
++    echo "Creating a temporary dir for editing binding failed" >&2
++    exit 1
++fi
++
++trap 'on_exit' EXIT
++trap 'on_exit' ERR
++
++if [ -z "${CFG}" ]; then
++   CFG_FILE="${TMP}/cfg"
++    echo "${pretty_cfg}" > "${CFG_FILE}"
++    if ! edit_cfg "${CFG_FILE}"; then
++        exit 1
++    fi
++
++    if ! new_cfg="$(jq . -S < "${CFG_FILE}")" || [ -z "${new_cfg}" ]; then
++        echo "Error reading the updated config for ${DEV}:${SLT}" >&2
++        exit 1
++    fi
++else
++    if ! validate_cfg "${CFG}"; then
++        echo "Invalid configuration given as parameter with -c" >&2
++        exit 1
++    fi
++    new_cfg="$(jq . -S <<< "${CFG}")"
++fi
++
++if [ "${new_cfg}" = "$(jq -S . <<< "${pretty_cfg}")" ] && [ -z "${FRC}" ]; then
++    echo "No changes detected; exiting" >&2
++    exit 1
++fi
++
++if ! jcfg="$(jose fmt -j- -Oo- <<< "${new_cfg}" 2>/dev/null)" \
++             || [ -z "${jcfg}" ]; then
++    echo "Error preparing the configuration for the binding update" >&2
++    exit 1
++fi
++
++if [ -z "${CFG}" ]; then
++    printf "Pin: %s\nNew config:\n%s\n" "${pin}" "${new_cfg}"
++    while true; do
++        read -r -p \
++          "Would you like to proceed with the updated configuration? [ynYN] " \
++         ans < /dev/tty
++        [[ "${ans}" =~ ^[nN]$ ]] && exit 0
++        [[ "${ans}" =~ ^[yY]$ ]] && break
++    done
++fi
++
++echo "Updating binding..."
++
++# Create new key.
++if ! new_pass=$(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}" "${jcfg}" -y <<< "${new_pass}")"; then
++    echo "Error using pin '${pin}' with config '${jcfg}'" >&2
++    exit 1
++fi
++
++# 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
++
++# Get passphrase.
++if ! pt="$(clevis_luks_unlock_device "${DEV}")" \
++           || [ -z "${pt}" ]; then
++    # Unable to retrieve a passphrase from the bindings, so let's query
++    # the user.
++    read -r -s -p "Enter existing LUKS password: " pt; echo
++    # Check if the key is valid.
++    if ! clevis_luks_is_key_valid "${DEV}" "${pt}"; then
++        echo "The key provided is not valid for ${DEV}" >&2
++        exit 1
++    fi
++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}" \
++        <<< "${pt}"; then
++    in_place=true
++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_pass}") <<< "${pt}"; then
++        echo "Error updating LUKS passphrase in ${DEV}:${SLT}" >&2
++        clevis_luks_restore_dev "${DEV}" "${TMP}"
++        exit 1
++    fi
++else
++    if ! cryptsetup luksKillSlot --batch-mode "${DEV}" "${SLT}"; then
++        echo "Error wiping slot ${SLT} from ${DEV}" >&2
++        clevis_luks_restore_dev "${DEV}" "${TMP}"
++        exit 1
++    fi
++
++    if ! echo -n "${new_pass}" \
++            | cryptsetup luksAddKey --key-slot "${SLT}" \
++                         --key-file <(echo -n "${pt}") "${DEV}"; then
++        echo "Error updating LUKS passphrase in ${DEV}:${SLT}." >&2
++        clevis_luks_restore_dev "${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
++    clevis_luks_restore_dev "${DEV}" "${TMP}"
++    exit 1
++fi
++
++# Make sure we can unlock the device with this keyslot.
++if ! clevis_luks_unlock_device_by_slot "${DEV}" "${SLT}" >/dev/null \
++                                       2>/dev/null; then
++    echo "Invalid configuration detected. Reverting changes." >&2
++    clevis_luks_restore_dev "${DEV}" "${TMP}"
++    exit 1
++fi
++
++echo "Binding edited successfully."
+diff --git a/src/luks/clevis-luks-edit.1.adoc b/src/luks/clevis-luks-edit.1.adoc
+new file mode 100644
+index 0000000..454de89
+--- /dev/null
++++ b/src/luks/clevis-luks-edit.1.adoc
+@@ -0,0 +1,69 @@
++CLEVIS-LUKS-EDIT(1)
++===================
++:doctype: manpage
++
++
++== NAME
++
++clevis-luks-edit - Edit a binding from a clevis-bound slot in a LUKS device
++
++== SYNOPSIS
++
++*clevis luks edit* -d DEV -s SLT [-c CONFIG]
++
++== OVERVIEW
++
++The *clevis luks edit* command edits clevis bindings from a LUKS device.
++For example:
++
++    clevis luks edit -d /dev/sda1 -s 1
++
++== OPTIONS
++
++* *-d* _DEV_ :
++  The LUKS device to edit clevis-bound pins
++
++* *-s* _SLT_ :
++  The slot to use when editing the clevis binding
++
++* *-f* :
++  Proceed with the edit operation even if the config is the same as the current one
++
++* *-c* _CONFIG_ :
++  The updated config to use
++
++
++== EXAMPLES
++
++    clevis luks list -d /dev/sda1
++    1: tang '{"url":"addr"}'
++
++As we can see in the example above, */dev/sda1* has one slots bound, in this case, to a _tang_ pin.
++
++We can edit this binding by issuing the following command:
++
++    clevis luks edit -d /dev/sda1 -s 1
++
++This will open a text editor -- the one set in the $EDITOR environment variable, or _vi_, as a fallback -- with the current
++configuration of this binding to be edited. In this case, we should have the following:
++
++    {
++        "url": "addr"
++    }
++
++Once at the editor, we can edit the pin configuration. For _tang_, we could edit the _url_, for instance. After completing the change,
++save the file and exit. The updated configuration will be validated for JSON, and if there are no errors, you will be shown the
++updated configuration and prompted whether to proceed.
++
++By proceeding, the binding will be updated. There may be required to provide a valid LUKS passphrase for the device.
++
++In the second example, we will update the same device and slot, but we will be providing the updated configuration as well:
++
++    clevis luks edit -d /dev/sda1 -s 1 -c '{"url":"new-addr-here"}'
++
++In this case, the binding update will be done in non-interactive mode, however it also may be required to provide a valud LUKS
++passphrase for the device.
++
++== SEE ALSO
++
++link:clevis-luks-list.1.adoc[*clevis-luks-list*(1)],
+diff --git a/src/luks/clevis-luks-regen b/src/luks/clevis-luks-regen
+index 6071d85..8f32e08 100755
+--- a/src/luks/clevis-luks-regen
++++ b/src/luks/clevis-luks-regen
+@@ -41,15 +41,7 @@ function usage_and_exit () {
+     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
++while getopts ":hd:s:" o; do
+     case "$o" in
+     d) DEV="$OPTARG";;
+     h) usage_and_exit 0;;
+@@ -68,117 +60,22 @@ if [ -z "$SLT" ]; then
+     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
++if ! binding="$(clevis luks list -d "${DEV}" -s "${SLT}" 2>/dev/null)" \
++                || [ -z "${binding}" ]; then
++    echo "Error retrieving current configuration from ${DEV}:${SLT}" >&2
+     exit 1
+ fi
+ 
+-PIN=$(echo "${pin_cfg}" | awk '{ print $2 }')
+-CFG=$(echo "${pin_cfg}" | awk '{ print $3 }' | tr -d "'")
++read -r _ pin cfg <<< "${binding}"
+ 
+ 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
++echo "PIN: ${pin}"
++echo "CONFIG: ${cfg}"
+ 
+-# 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}"
++# Remove single quotes.
++cfg=${cfg//\'}
++if ! clevis luks edit -f -d "${DEV}" -s "${SLT}" -c "${cfg}" >/dev/null; then
++    echo "Error rotating keys in ${DEV}:${SLT}" >&2
+     exit 1
+ fi
+ 
+diff --git a/src/luks/meson.build b/src/luks/meson.build
+index ee588c3..ba02bd9 100644
+--- a/src/luks/meson.build
++++ b/src/luks/meson.build
+@@ -54,6 +54,9 @@ if libcryptsetup.found() and luksmeta.found() and pwmake.found()
+   bins += join_paths(meson.current_source_dir(), 'clevis-luks-report-sss')
+   bins += join_paths(meson.current_source_dir(), 'clevis-luks-report-tang')
+   mans += join_paths(meson.current_source_dir(), 'clevis-luks-report.1')
++
++  bins += join_paths(meson.current_source_dir(), 'clevis-luks-edit')
++  mans += join_paths(meson.current_source_dir(), 'clevis-luks-edit.1')
+ else
+   warning('Will not install LUKS support due to missing dependencies!')
+ endif
+diff --git a/src/luks/tests/edit-tang-luks1 b/src/luks/tests/edit-tang-luks1
+new file mode 100755
+index 0000000..3d42d68
+--- /dev/null
++++ b/src/luks/tests/edit-tang-luks1
+@@ -0,0 +1,106 @@
++#!/bin/bash -ex
++# vim: set ts=8 shiftwidth=4 softtabstop=4 expandtab smarttab colorcolumn=80:
++#
++# Copyright (c) 2020 Red Hat, Inc.
++# Author: Sergio Correia <scorreia@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)"
++
++port=$(get_random_port)
++tang_run "${TMP}" "${port}" &
++tang_wait_until_ready "${port}"
++
++url="http://${TANG_HOST}:${port}"
++
++cfg=$(printf '{"url":"%s"}' "${url}")
++
++# LUKS1.
++DEV="${TMP}/luks1-device"
++new_device "luks1" "${DEV}"
++
++if ! clevis luks bind -y -d "${DEV}" tang "${cfg}" <<< "${DEFAULT_PASS}"; then
++    error "${TEST}: Bind should have succeeded."
++fi
++
++# Now let's try to change the config but using the same one we already have.
++if clevis luks edit -d "${DEV}" -s 1 -c "${cfg}"; then
++    error "${TEST}: edit should not have succeeded because the config is the same."
++fi
++
++# And now, just a broken config.
++new_cfg=$(printf '{"url&:"%s"}' "${url}")
++if clevis luks edit -d "${DEV}" -s 1 -c "${new_cfg}"; then
++    error "${TEST}: edit should have failed because of invalid JSON"
++fi
++
++# Now let's have another tang instance running and change the config to use
++# the new one.
++port2=$(get_random_port)
++TMP2="$(mktemp -d)"
++tang_run "${TMP2}" "${port2}" &
++tang_wait_until_ready "${port2}"
++new_url="http://${TANG_HOST}:${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
++
++# And now let's use sss and start with a single tang server, then add a second
++# one.
++new_device "luks1" "${DEV}"
++cfg=$(printf '{"t":1,"pins":{"tang":[{"url":"%s"}]}}' "${url}")
++if ! clevis luks bind -y -d "${DEV}" sss "${cfg}" <<< "${DEFAULT_PASS}"; then
++    error "${TEST}: Bind should have succeeded."
++fi
++new_cfg=$(printf '{"t":1,"pins":{"tang":[{"url":"%s"},{"url":"%s"}]}}' \
++          "${url}" "${new_url}")
++
++if ! clevis luks edit -d "${DEV}" -s 1 -c "${new_cfg}"; then
++    error "${TEST}: edit should have succeeded and added a new tang server"
++fi
++
++# Now let's change the threshold to 2.
++new_cfg=$(printf '{"t":2,"pins":{"tang":[{"url":"%s"},{"url":"%s"}]}}' \
++          "${url}" "${new_url}")
++
++if ! clevis luks edit -d "${DEV}" -s 1 -c "${new_cfg}"; then
++    error "${TEST}: edit should have succeeded and added a new tang server"
++fi
++
++# And finally, let's try a broken config, with a wrong threshold.
++new_cfg=$(printf '{"t":3,"pins":{"tang":[{"url":"%s"},{"url":"%s"}]}}' \
++          "${url}" "${new_url}")
++if clevis luks edit -d "${DEV}" -s 1 -c "${new_cfg}"; then
++    error "${TEST}: edit should have failed because threshold > number of servers"
++fi
+diff --git a/src/luks/tests/edit-tang-luks2 b/src/luks/tests/edit-tang-luks2
+new file mode 100755
+index 0000000..9000053
+--- /dev/null
++++ b/src/luks/tests/edit-tang-luks2
+@@ -0,0 +1,106 @@
++#!/bin/bash -ex
++# vim: set ts=8 shiftwidth=4 softtabstop=4 expandtab smarttab colorcolumn=80:
++#
++# Copyright (c) 2020 Red Hat, Inc.
++# Author: Sergio Correia <scorreia@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)"
++
++port=$(get_random_port)
++tang_run "${TMP}" "${port}" &
++tang_wait_until_ready "${port}"
++
++url="http://${TANG_HOST}:${port}"
++
++cfg=$(printf '{"url":"%s"}' "${url}")
++
++# LUKS2.
++DEV="${TMP}/luks2-device"
++new_device "luks2" "${DEV}"
++
++if ! clevis luks bind -y -d "${DEV}" tang "${cfg}" <<< "${DEFAULT_PASS}"; then
++    error "${TEST}: Bind should have succeeded."
++fi
++
++# Now let's try to change the config but using the same one we already have.
++if clevis luks edit -d "${DEV}" -s 1 -c "${cfg}"; then
++    error "${TEST}: edit should not have succeeded because the config is the same."
++fi
++
++# And now, just a broken config.
++new_cfg=$(printf '{"url&:"%s"}' "${url}")
++if clevis luks edit -d "${DEV}" -s 1 -c "${new_cfg}"; then
++    error "${TEST}: edit should have failed because of invalid JSON"
++fi
++
++# Now let's have another tang instance running and change the config to use
++# the new one.
++port2=$(get_random_port)
++TMP2="$(mktemp -d)"
++tang_run "${TMP2}" "${port2}" &
++tang_wait_until_ready "${port2}"
++new_url="http://${TANG_HOST}:${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
++
++# And now let's use sss and start with a single tang server, then add a second
++# one.
++new_device "luks2" "${DEV}"
++cfg=$(printf '{"t":1,"pins":{"tang":[{"url":"%s"}]}}' "${url}")
++if ! clevis luks bind -y -d "${DEV}" sss "${cfg}" <<< "${DEFAULT_PASS}"; then
++    error "${TEST}: Bind should have succeeded."
++fi
++new_cfg=$(printf '{"t":1,"pins":{"tang":[{"url":"%s"},{"url":"%s"}]}}' \
++          "${url}" "${new_url}")
++
++if ! clevis luks edit -d "${DEV}" -s 1 -c "${new_cfg}"; then
++    error "${TEST}: edit should have succeeded and added a new tang server"
++fi
++
++# Now let's change the threshold to 2.
++new_cfg=$(printf '{"t":2,"pins":{"tang":[{"url":"%s"},{"url":"%s"}]}}' \
++          "${url}" "${new_url}")
++
++if ! clevis luks edit -d "${DEV}" -s 1 -c "${new_cfg}"; then
++    error "${TEST}: edit should have succeeded and added a new tang server"
++fi
++
++# And finally, let's try a broken config, with a wrong threshold.
++new_cfg=$(printf '{"t":3,"pins":{"tang":[{"url":"%s"},{"url":"%s"}]}}' \
++          "${url}" "${new_url}")
++if clevis luks edit -d "${DEV}" -s 1 -c "${new_cfg}"; then
++    error "${TEST}: edit should have failed because threshold > number of servers"
++fi
+diff --git a/src/luks/tests/meson.build b/src/luks/tests/meson.build
+index 4795488..67fa597 100644
+--- a/src/luks/tests/meson.build
++++ b/src/luks/tests/meson.build
+@@ -4,8 +4,9 @@ actv = find_program(
+   required: false
+ )
+ 
+-# We use jq for comparing the pin config in the clevis luks list tests.
+-jq = find_program('jq', required: false)
++# We use jq for comparing the pin config in the clevis luks list tests
++# and also in clevis luks edit.
++jq = find_program('jq', required: true)
+ 
+ # we use systemd-socket-activate for running test tang servers.
+ actv = find_program(
+@@ -74,19 +75,16 @@ test('bind-pass-with-newline', find_program('bind-pass-with-newline-luks1'), 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
++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)
+ 
+ if has_tang
+   test('unlock-tang-luks1', find_program('unlock-tang-luks1'), env: env, timeout: 90)
+   test('assume-yes-luks1', find_program('assume-yes-luks1'), env: env)
++  test('edit-tang-luks1', find_program('edit-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)
+@@ -100,16 +98,14 @@ if luksmeta_data.get('OLD_CRYPTSETUP') == '0'
+   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
++  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)
+ 
+   if has_tang
+     test('unlock-tang-luks2', find_program('unlock-tang-luks2'), env: env, timeout: 120)
+     test('assume-yes-luks2', find_program('assume-yes-luks2'), env: env, timeout: 60)
++    test('edit-tang-luks2', find_program('edit-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)
+diff --git a/src/luks/tests/regen-inplace-luks1 b/src/luks/tests/regen-inplace-luks1
+index 3a42ced..32072c4 100755
+--- a/src/luks/tests/regen-inplace-luks1
++++ b/src/luks/tests/regen-inplace-luks1
+@@ -76,7 +76,7 @@ fi
+ old_key=$(clevis luks pass -d "${DEV}" -s "${SLT}")
+ 
+ # Now let's try regen.
+-if ! clevis_regen "${DEV}" "${SLT}" "${DEFAULT_PASS}"; then
++if ! clevis luks regen -d "${DEV}" -s "${SLT}"; then
+     error "${TEST}: clevis luks regen failed"
+ fi
+ 
+diff --git a/src/luks/tests/regen-inplace-luks2 b/src/luks/tests/regen-inplace-luks2
+index 1cb7a29..d1bc182 100755
+--- a/src/luks/tests/regen-inplace-luks2
++++ b/src/luks/tests/regen-inplace-luks2
+@@ -77,7 +77,7 @@ fi
+ old_key=$(clevis luks pass -d "${DEV}" -s "${SLT}")
+ 
+ # Now let's try regen.
+-if ! clevis_regen "${DEV}" "${SLT}" "${DEFAULT_PASS}"; then
++if ! clevis luks regen -d "${DEV}" -s "${SLT}"; then
+     error "${TEST}: clevis luks regen failed"
+ fi
+ 
+diff --git a/src/luks/tests/regen-not-inplace-luks1 b/src/luks/tests/regen-not-inplace-luks1
+index 1b65ca7..fba61dc 100755
+--- a/src/luks/tests/regen-not-inplace-luks1
++++ b/src/luks/tests/regen-not-inplace-luks1
+@@ -79,7 +79,7 @@ if [ "${enabled}" -ne 2 ]; then
+ fi
+ 
+ # Now let's try regen.
+-if ! clevis_regen "${DEV}" "${SLT}" "${DEFAULT_PASS}"; then
++if ! clevis luks regen -d "${DEV}" -s "${SLT}" <<< "${DEFAULT_PASS}"; then
+     error "${TEST}: clevis luks regen failed"
+ fi
+ 
+diff --git a/src/luks/tests/regen-not-inplace-luks2 b/src/luks/tests/regen-not-inplace-luks2
+index dc91449..6e3b012 100755
+--- a/src/luks/tests/regen-not-inplace-luks2
++++ b/src/luks/tests/regen-not-inplace-luks2
+@@ -80,7 +80,7 @@ if [ "${enabled}" -ne 2 ]; then
+ fi
+ 
+ # Now let's try regen.
+-if ! clevis_regen "${DEV}" "${SLT}" "${DEFAULT_PASS}"; then
++if ! clevis luks regen -d "${DEV}" -s "${SLT}" <<< "${DEFAULT_PASS}"; then
+     error "${TEST}: clevis luks regen failed"
+ fi
+ 
+diff --git a/src/luks/tests/tests-common-functions.in b/src/luks/tests/tests-common-functions.in
+index 6101f28..7b3fdad 100755
+--- a/src/luks/tests/tests-common-functions.in
++++ b/src/luks/tests/tests-common-functions.in
+@@ -229,31 +229,5 @@ 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'
+diff --git a/src/luks/tests/unlock-tang-luks1 b/src/luks/tests/unlock-tang-luks1
+index 841ba01..6ede47b 100755
+--- a/src/luks/tests/unlock-tang-luks1
++++ b/src/luks/tests/unlock-tang-luks1
+@@ -31,6 +31,10 @@ on_exit() {
+ trap 'on_exit' EXIT
+ trap 'on_exit' ERR
+ 
++# LUKS1.
++DEV="${TMP}/luks1-device"
++new_device "luks1" "${DEV}"
++
+ TMP="$(mktemp -d)"
+ 
+ port=$(get_random_port)
+@@ -43,9 +47,6 @@ tang_get_adv "${port}" "${adv}"
+ 
+ cfg=$(printf '{"url":"%s","adv":"%s"}' "$url" "$adv")
+ 
+-# LUKS1.
+-DEV="${TMP}/luks1-device"
+-new_device "luks1" "${DEV}"
+ 
+ if ! clevis luks bind -f -d "${DEV}" tang "${cfg}" <<< "${DEFAULT_PASS}"; then
+     error "${TEST}: Bind should have succeeded."
+diff --git a/src/luks/tests/unlock-tang-luks2 b/src/luks/tests/unlock-tang-luks2
+index 81822fb..b32c5aa 100755
+--- a/src/luks/tests/unlock-tang-luks2
++++ b/src/luks/tests/unlock-tang-luks2
+@@ -31,6 +31,10 @@ on_exit() {
+ trap 'on_exit' EXIT
+ trap 'on_exit' ERR
+ 
++# LUKS2.
++DEV="${TMP}/luks2-device"
++new_device "luks2" "${DEV}"
++
+ TMP="$(mktemp -d)"
+ 
+ port=$(get_random_port)
+@@ -43,10 +47,6 @@ tang_get_adv "${port}" "${adv}"
+ 
+ cfg=$(printf '{"url":"%s","adv":"%s"}' "$url" "$adv")
+ 
+-# LUKS2.
+-DEV="${TMP}/luks2-device"
+-new_device "luks2" "${DEV}"
+-
+ if ! clevis luks bind -f -d "${DEV}" tang "${cfg}" <<< "${DEFAULT_PASS}"; then
+     error "${TEST}: Bind should have succeeded."
+ fi
+-- 
+2.18.4
+
diff --git a/SOURCES/Add-clevis-luks-report-regen.patch b/SOURCES/Add-clevis-luks-report-regen.patch
deleted file mode 100644
index 274e651..0000000
--- a/SOURCES/Add-clevis-luks-report-regen.patch
+++ /dev/null
@@ -1,858 +0,0 @@
-From 70d3da5ce8d68e8ff258122592670eb70da0c839 Mon Sep 17 00:00:00 2001
-From: Sergio Correia <scorreia@redhat.com>
-Date: Wed, 16 Oct 2019 09:14:58 -0300
-Subject: [PATCH 2/2] Add clevis luks report/regen
-
----
- src/luks/clevis-luks-common-functions | 143 ++++++++++++++++++++
- src/luks/clevis-luks-regen            | 186 ++++++++++++++++++++++++++
- src/luks/clevis-luks-regen.1.adoc     |  36 +++++
- src/luks/clevis-luks-report           |  95 +++++++++++++
- src/luks/clevis-luks-report-compare   |  71 ++++++++++
- src/luks/clevis-luks-report-decode    |  59 ++++++++
- src/luks/clevis-luks-report-sss       |  53 ++++++++
- src/luks/clevis-luks-report-tang      |  67 ++++++++++
- src/luks/clevis-luks-report.1.adoc    |  41 ++++++
- src/luks/meson.build                  |  12 ++
- 10 files changed, 763 insertions(+)
- create mode 100644 src/luks/clevis-luks-common-functions
- create mode 100755 src/luks/clevis-luks-regen
- create mode 100644 src/luks/clevis-luks-regen.1.adoc
- create mode 100755 src/luks/clevis-luks-report
- create mode 100755 src/luks/clevis-luks-report-compare
- create mode 100755 src/luks/clevis-luks-report-decode
- create mode 100755 src/luks/clevis-luks-report-sss
- create mode 100755 src/luks/clevis-luks-report-tang
- create mode 100644 src/luks/clevis-luks-report.1.adoc
-
-diff --git a/src/luks/clevis-luks-common-functions b/src/luks/clevis-luks-common-functions
-new file mode 100644
-index 0000000..d676253
---- /dev/null
-+++ b/src/luks/clevis-luks-common-functions
-@@ -0,0 +1,143 @@
-+#!/bin/bash -e
-+# vim: set tabstop=8 shiftwidth=4 softtabstop=4 expandtab smarttab colorcolumn=80:
-+#
-+# Copyright (c) 2019 Red Hat, Inc.
-+# Author: Sergio Correia <scorreia@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/>.
-+#
-+
-+# valid_slot() will check whether a given slot is possibly valid, i.e., if it
-+# is a numeric value within the specified range.
-+valid_slot() {
-+    local SLT="${1}"
-+    local MAX_SLOTS="${2}"
-+    case "${SLT}" in
-+        ''|*[!0-9]*)
-+            return 1
-+            ;;
-+        *)
-+            # We got an integer, now let's make sure it is within the
-+            # supported range.
-+            if [ "${SLT}" -ge "${MAX_SLOTS}" ]; then
-+                return 1
-+            fi
-+            ;;
-+    esac
-+}
-+
-+# clevis_luks_read_slot() will read a particular slot of a given device, which
-+# should be either LUKS1 or LUKS2. Returns 1 in case of failure; 0 in case of
-+# success.
-+clevis_luks_read_slot() {
-+    local DEV="${1}"
-+    local SLT="${2}"
-+
-+    if [ -z "${DEV}" ] || [ -z "${SLT}" ]; then
-+        echo "Need both a device and a slot as arguments." >&2
-+        return 1
-+    fi
-+
-+    local DATA_CODED=''
-+    local MAX_LUKS1_SLOTS=8
-+    local MAX_LUKS2_SLOTS=32
-+    if cryptsetup isLuks --type luks1 "${DEV}"; then
-+        if ! valid_slot "${SLT}" "${MAX_LUKS1_SLOTS}"; then
-+            echo "Please, provide a valid key slot number; 0-7 for LUKS1" >&2
-+            return 1
-+        fi
-+
-+        if ! luksmeta test -d "${DEV}"; then
-+            echo "The ${DEV} device is not valid!" >&2
-+            return 1
-+        fi
-+
-+        local uuid
-+        # Pattern from luksmeta: active slot uuid.
-+        read -r _ _ uuid <<< "$(luksmeta show -d "${DEV}" | grep "^${SLT} *")"
-+
-+        if [ "${uuid}" = "empty" ]; then
-+           echo "The LUKSMeta slot ${SLT} on device ${DEV} is already empty." >&2
-+           return 1
-+        fi
-+
-+        if ! DATA_CODED="$(luksmeta load -d "${DEV}" -s "${SLT}")"; then
-+            echo "Cannot load data from ${DEV} slot:${SLT}!" >&2
-+            return 1
-+        fi
-+    elif cryptsetup isLuks --type luks2 "${DEV}"; then
-+        if ! valid_slot "${SLT}" "${MAX_LUKS2_SLOTS}"; then
-+            echo "Please, provide a valid key slot number; 0-31 for LUKS2" >&2
-+            return 1
-+        fi
-+
-+        local token_id
-+        token_id=$(cryptsetup luksDump "${DEV}" \
-+                    | grep -E -B1 "^\s+Keyslot:\s+${SLT}$" \
-+                    | head -n 1 | sed -rn 's|^\s+([0-9]+): clevis|\1|p')
-+        if [ -z "${token_id}" ]; then
-+            echo "Cannot load data from ${DEV} slot:${SLT}. No token found!" >&2
-+            return 1
-+        fi
-+
-+        local token
-+        token=$(cryptsetup token export --token-id "${token_id}" "${DEV}")
-+        DATA_CODED=$(jose fmt -j- -Og jwe -o- <<< "${token}" \
-+                     | jose jwe fmt -i- -c)
-+
-+        if [ -z "${DATA_CODED}" ]; then
-+            echo "Cannot load data from ${DEV} slot:${SLT}!" >&2
-+            return 1
-+        fi
-+    else
-+        echo "${DEV} is not a supported LUKS device!" >&2
-+        return 1
-+    fi
-+    echo "${DATA_CODED}"
-+}
-+
-+# 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}"
-+}
-+
-+findexe() {
-+    while read -r -d: path; do
-+        [ -f "${path}/${1}" ] && [ -x "${path}/${1}" ] && \
-+          echo "${path}/${1}" && return 0
-+    done <<< "${PATH}:"
-+    return 1
-+}
-+
-diff --git a/src/luks/clevis-luks-regen b/src/luks/clevis-luks-regen
-new file mode 100755
-index 0000000..9535ba3
---- /dev/null
-+++ b/src/luks/clevis-luks-regen
-@@ -0,0 +1,186 @@
-+#!/usr/bin/env bash
-+# vim: set tabstop=8 shiftwidth=4 softtabstop=4 expandtab smarttab colorcolumn=80:
-+#
-+# Copyright (c) 2018 Red Hat, Inc.
-+# Author: Radovan Sroka <rsroka@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/>.
-+#
-+
-+. clevis-luks-common-functions
-+
-+SUMMARY="Regenerate LUKS metadata"
-+
-+if [ "$1" == "--summary" ]; then
-+    echo "$SUMMARY"
-+    exit 0
-+fi
-+
-+function usage_and_exit () {
-+    echo >&2
-+    echo "Usage: clevis luks regen -d DEV -s SLOT" >&2
-+    echo >&2
-+    echo "$SUMMARY" >&2
-+    echo >&2
-+    exit "$1"
-+}
-+
-+if [ "$#" -ne "4" ]; then
-+    usage_and_exit 1
-+fi
-+
-+while getopts "hd:s:" o; do
-+    case "$o" in
-+    d) DEV="$OPTARG";;
-+    h) usage_and_exit 0;;
-+    s) SLT="$OPTARG";;
-+    *) usage_and_exit 1;;
-+    esac
-+done
-+
-+function decode_luks_header () {
-+    if DATA_CODED="$(jose jwe fmt -i- <<< "$1")"; then
-+        DATA_CODED="$(jose fmt -j- -g protected -u- <<< "$DATA_CODED")"
-+        DATA_DECODED="$(jose b64 dec -i- <<< "$DATA_CODED")"
-+    else
-+        echo "Error decoding JWE protected header!" >&2
-+        exit 1
-+    fi
-+
-+    echo "$DATA_DECODED"
-+}
-+
-+function generate_cfg () {
-+    echo -n "{"
-+    DATA="$(decode_luks_header "$1")"
-+
-+    if ! P="$(jose fmt -j- -g clevis -g pin -u- <<< "$DATA")" || [ -z "$P" ]; then
-+        echo "Pin wasn't found in LUKS metadata!" >&2
-+        exit 1
-+    fi
-+
-+    if ! CONTENT="$(jose fmt -j- -g clevis -g "$P" -o- <<< "$DATA")" || [ -z "$CONTENT" ]; then
-+        echo "Content was not found!" >&2
-+    fi
-+
-+    # echo -n "\"$P\": ["
-+
-+    if [ "$P" = "tang" ] || [ "$P" = "http" ]; then
-+        URL="$(jose fmt -j- -g url -u- <<< "$CONTENT")"
-+        echo -n "\"url\":\"$URL\""
-+    elif [ "$P" = "sss" ]; then
-+        THRESHOLD="$(jose fmt -j- -g t -o- <<< "$CONTENT")"
-+        if [ -n "$THRESHOLD" ]; then
-+            echo -n "\"t\":$THRESHOLD,"
-+        fi
-+
-+        echo -n "\"pins\":{"
-+
-+        CNT=0
-+        PREV=""
-+        while ITEM="$(jose fmt -j- -g jwe -g"$CNT" -u- <<< "$CONTENT")"; do
-+            if [ -z "$ITEM" ]; then
-+                CNT=$(( CNT + 1 ))
-+                continue # in some cases it can be empty string
-+            fi
-+
-+            DD="$(decode_luks_header "$ITEM")"
-+
-+            if ! PP="$(jose fmt -j- -g clevis -g pin -u- <<< "$DD")" || [ -z "$PP" ]; then
-+                echo "Pin wasn't found in LUKS metadata!" >&2
-+                exit 1
-+            fi
-+
-+            if [ "$CNT" -eq 0 ]; then
-+                PREV="$PP"
-+                echo -n "\"$PP\":["
-+                echo -n "$(generate_cfg "$ITEM")"
-+            else
-+                if ! [ "$PREV" = "$PP" ]; then
-+                    echo -n "],\"$PP\":["
-+                    echo -n "$(generate_cfg "$ITEM")"
-+                else
-+                    echo -n ",$(generate_cfg "$ITEM")"
-+                fi
-+            fi
-+
-+            PREV="$PP"
-+            CNT=$(( CNT + 1 ))
-+        done
-+
-+        echo -n "]}"
-+
-+    else
-+        echo "Unknown pin $P!" >&2
-+        exit 1
-+    fi
-+
-+    echo -n "}"
-+}
-+
-+### get luks metadata
-+
-+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 ! OLD_LUKS_CODED="$(clevis_luks_read_slot "$DEV" "$SLT")"; then
-+    echo "Error reading metadata from LUKS device!" >&2
-+    exit 1
-+fi
-+
-+### ----------------------------------------------------------------------
-+
-+DECODED="$(decode_luks_header "$OLD_LUKS_CODED")"
-+
-+if ! PIN="$(jose fmt -j- -g clevis -g pin -u- <<< "$DECODED")" || [ -z "$PIN" ]; then
-+    echo "Pin wasn't found in LUKS metadata!" >&2
-+    exit 1
-+fi
-+
-+CFG="$(generate_cfg "$OLD_LUKS_CODED")"
-+
-+### ----------------------------------------------------------------------
-+
-+echo "Regenerating with:"
-+echo "PIN: $PIN"
-+echo "CONFIG: $CFG"
-+
-+trap 'echo "Ignoring CONTROL-C!"' INT TERM
-+
-+# Get the existing key.
-+read -r -s -p "Enter existing LUKS password: " existing_key; echo
-+
-+# Check if the key is valid.
-+if ! cryptsetup luksOpen --test-passphrase "${DEV}" <<< "${existing_key}"; then
-+    exit 1
-+fi
-+
-+if ! clevis luks unbind -d "${DEV}" -s "${SLT}" -f; then
-+    echo "Error during unbind of rotated key from slot:$SLT in $DEV" >&2
-+    exit 1
-+fi
-+
-+if ! clevis luks bind -d "${DEV}" -s "${SLT}" "${PIN}" "${CFG}" -k - <<< "${existing_key}"; then
-+    echo "Error during bind of new key from slot:$SLT in $DEV" >&2
-+    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..3cd6b7c
---- /dev/null
-+++ b/src/luks/clevis-luks-regen.1.adoc
-@@ -0,0 +1,36 @@
-+CLEVIS-LUKS-REGEN(1)
-+=====================
-+:doctype: manpage
-+
-+
-+== NAME
-+
-+clevis-luks-regen - Regenerates LUKS metadata
-+
-+== SYNOPSIS
-+
-+*clevis luks regen* -d DEV -s SLT
-+
-+== OVERVIEW
-+
-+The *clevis luks regen* command regenerates the LUKS metadata for a given slot in a LUKS device. It effectively
-+performs an operation equivalent to *clevis luks unbind* and *clevis luks bind* for rebinding said slot and device.
-+
-+== 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
-+
-+    Regenerate the binding of slot 1 from /dev/sda1:
-+
-+    # clevis luks regen -d /dev/sda1 -s 1
-+
-+== SEE ALSO
-+
-+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/clevis-luks-report b/src/luks/clevis-luks-report
-new file mode 100755
-index 0000000..f047256
---- /dev/null
-+++ b/src/luks/clevis-luks-report
-@@ -0,0 +1,95 @@
-+#!/usr/bin/bash -e
-+# vim: set tabstop=8 shiftwidth=4 softtabstop=4 expandtab smarttab colorcolumn=80:
-+#
-+# Copyright (c) 2018 Red Hat, Inc.
-+# Author: Radovan Sroka <rsroka@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/>.
-+#
-+
-+. clevis-luks-common-functions
-+
-+SUMMARY="Report any key rotation on the server side"
-+
-+if [ "$1" == "--summary" ]; then
-+    echo "$SUMMARY"
-+    exit 0
-+fi
-+
-+function usage_and_exit () {
-+    echo >&2
-+    echo "Usage: clevis luks report [-qr] -d DEV -s SLOT" >&2
-+    echo >&2
-+    echo -e "  -q\t Quiet mode" >&2
-+    echo -e "  -r\t Regenerate luks metadata with \"clevis luks regen -d DEV -s SLOT\"" >&2
-+    echo >&2
-+    echo "$SUMMARY" >&2
-+    echo >&2
-+    exit "$1"
-+}
-+
-+while getopts "hd:s:rq" o; do
-+    case "$o" in
-+    d) DEV="$OPTARG";;
-+    h) usage_and_exit 0;;
-+    r) ROPT="regen";;
-+    s) SLT="$OPTARG";;
-+    q) QOPT="quiet";;
-+    *) usage_and_exit 1;;
-+    esac
-+done
-+
-+### get luks metadata
-+
-+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 ! DATA_CODED=$(clevis_luks_read_slot "${DEV}" "${SLT}"); then
-+    # Error message was already displayed by clevis_luks_read_slot(),
-+    # at this point.
-+    exit 1
-+fi
-+
-+EXE="$(findexe clevis-luks-report-decode)"
-+RESULT="$($EXE "${DATA_CODED}")"
-+
-+if [ -n "$RESULT" ]; then
-+    echo "$RESULT"
-+    echo "Report detected that some keys were rotated."
-+    if [ -z "$QOPT" ]; then
-+        if [ -z "$ROPT" ]; then
-+            read -r -p "Do you want to regenerate luks metadata with \"clevis luks regen -d $DEV -s $SLT\"? [ynYN] " ans < /dev/tty
-+            [[ "$ans" =~ ^[yY]$ ]] && ROPT="regen"
-+        fi
-+    fi
-+else
-+    exit 0
-+fi
-+
-+if [ "$ROPT" = "regen" ]; then
-+    EXE="$(findexe clevis-luks-regen)"
-+    exec "$EXE" -d "$DEV" -s "$SLT"
-+else
-+    if [ -n "${RESULT}" ]; then
-+        # Keys were rotated.
-+        exit 1
-+    fi
-+fi
-diff --git a/src/luks/clevis-luks-report-compare b/src/luks/clevis-luks-report-compare
-new file mode 100755
-index 0000000..2ba5132
---- /dev/null
-+++ b/src/luks/clevis-luks-report-compare
-@@ -0,0 +1,71 @@
-+#!/usr/bin/bash -e
-+# vim: set tabstop=8 shiftwidth=4 softtabstop=4 expandtab smarttab colorcolumn=80:
-+#
-+# Copyright (c) 2018 Red Hat, Inc.
-+# Author: Radovan Sroka <rsroka@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/>.
-+#
-+
-+SUMMARY="Compare two sets of keys"
-+
-+if [ "$1" == "--summary" ]; then
-+    echo "$SUMMARY"
-+    exit 1
-+fi
-+
-+if [ -z "$1" ]; then
-+    echo "$0 missing the first argument!"
-+    exit 1
-+fi
-+
-+if [ -z "$2" ]; then
-+    echo "$0 missing the second argument!"
-+    exit 1
-+fi
-+
-+ADV_KEYS="$1" # keys from advertisement
-+LUKS_KEYS="$2" # keys from luks metadata
-+
-+### iterate over adv keys and make thumbprints
-+CNT=0
-+declare -a ADV_KEYS_ARRAY
-+while res="$(jose fmt -j- -g keys -g"$CNT" -o- <<< "$ADV_KEYS")"; do
-+    thp="$(echo "$res" | jose jwk thp -i-)"
-+    ADV_KEYS_ARRAY["$CNT"]="$thp"
-+    CNT=$(( CNT + 1 ))
-+done
-+
-+CNT=0
-+while key="$(jose fmt -j- -g keys -g"$CNT" -o- <<< "$LUKS_KEYS")"; do
-+    thp="$(echo "$key" | jose jwk thp -i-)"
-+
-+    FOUND=0
-+    for k in "${ADV_KEYS_ARRAY[@]}"
-+    do
-+        if [ "$k" = "$thp" ]; then
-+            FOUND=1
-+            break
-+        fi
-+    done
-+
-+    if [ "$FOUND" -eq "0" ]; then
-+        echo "Key \"$thp\" is not in the advertisement and was probably rotated!"
-+        echo "$key"
-+        echo
-+    fi
-+    CNT=$(( CNT + 1 ))
-+done
-+
-+exit 0
-diff --git a/src/luks/clevis-luks-report-decode b/src/luks/clevis-luks-report-decode
-new file mode 100755
-index 0000000..f39d1e9
---- /dev/null
-+++ b/src/luks/clevis-luks-report-decode
-@@ -0,0 +1,59 @@
-+#!/usr/bin/bash -e
-+# vim: set tabstop=8 shiftwidth=4 softtabstop=4 expandtab smarttab colorcolumn=80:
-+#
-+# Copyright (c) 2018 Red Hat, Inc.
-+# Author: Radovan Sroka <rsroka@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/>.
-+#
-+
-+. clevis-luks-common-functions
-+
-+SUMMARY="Decode luks header"
-+
-+if [ "$1" == "--summary" ]; then
-+    echo "$SUMMARY"
-+    exit 1
-+fi
-+
-+if [ -z "$1" ]; then
-+    echo "$0 missing the first argument!"
-+    exit 1
-+fi
-+
-+DATA_CODED="$1"
-+
-+if DATA_CODED="$(jose jwe fmt -i- <<< "$DATA_CODED")"; then
-+    DATA_CODED="$(jose fmt -j- -g protected -u- <<< "$DATA_CODED")"
-+    DATA_DECODED="$(jose b64 dec -i- <<< "$DATA_CODED")"
-+else
-+    echo "Error decoding JWE protected header!" >&2
-+    exit 1
-+fi
-+
-+### get pin and url
-+
-+if ! PIN="$(jose fmt -j- -g clevis -g pin -u- <<< "$DATA_DECODED")" || [ -z "$PIN" ]; then
-+    echo "Pin wasn't found in luks metadata!" >&2
-+    exit 1
-+fi
-+
-+if ! CONTENT="$(jose fmt -j- -g clevis -g "$PIN" -o- <<< "$DATA_DECODED")" || [ -z "$CONTENT" ]; then
-+    echo "Content wasn't found!" >&2
-+    exit 1
-+fi
-+
-+EXE="$(findexe clevis-luks-report-"$PIN")"
-+
-+exec "$EXE" "$CONTENT"
-diff --git a/src/luks/clevis-luks-report-sss b/src/luks/clevis-luks-report-sss
-new file mode 100755
-index 0000000..1dba4c1
---- /dev/null
-+++ b/src/luks/clevis-luks-report-sss
-@@ -0,0 +1,53 @@
-+#!/bin/bash -e
-+# vim: set tabstop=8 shiftwidth=4 softtabstop=4 expandtab smarttab colorcolumn=80:
-+#
-+# Copyright (c) 2018 Red Hat, Inc.
-+# Author: Radovan Sroka <rsroka@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/>.
-+#
-+
-+. clevis-luks-common-functions
-+
-+SUMMARY="SSS report plugin"
-+
-+if [ "$1" == "--summary" ]; then
-+    echo "$SUMMARY"
-+    exit 1
-+fi
-+
-+if [ -z "$1" ]; then
-+    echo "$0 missing the first argument!" >&2
-+    exit 1
-+fi
-+
-+CONTENT="$1" # sss content
-+
-+CNT=0
-+while DATA_CODED="$(jose fmt -j- -g jwe -g"$CNT" -u- <<< "$CONTENT")"; do
-+    if [ -z "$DATA_CODED" ]; then
-+        CNT=$(( CNT + 1 ))
-+        continue # in some cases it can be empty string
-+    fi
-+
-+    EXE="$(findexe clevis-luks-report-decode)"
-+    if ! $EXE "$DATA_CODED"; then
-+        echo "Failed" >&2
-+        exit 1
-+    fi
-+
-+    CNT=$(( CNT + 1 ))
-+done
-+
-+exit 0
-diff --git a/src/luks/clevis-luks-report-tang b/src/luks/clevis-luks-report-tang
-new file mode 100755
-index 0000000..07f2a72
---- /dev/null
-+++ b/src/luks/clevis-luks-report-tang
-@@ -0,0 +1,67 @@
-+#!/usr/bin/bash -e
-+# vim: set tabstop=8 shiftwidth=4 softtabstop=4 expandtab smarttab colorcolumn=80:
-+#
-+# Copyright (c) 2018 Red Hat, Inc.
-+# Author: Radovan Sroka <rsroka@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/>.
-+#
-+
-+. clevis-luks-common-functions
-+
-+SUMMARY="Tang report plugin"
-+
-+if [ "$1" == "--summary" ]; then
-+    echo "$SUMMARY"
-+    exit 1
-+fi
-+
-+if [ -z "$1" ]; then
-+    echo "$0 missing the first argument!"
-+    exit 1
-+fi
-+
-+CONTENT="$1"
-+
-+### Get the advertisement
-+if ! URL="$(jose fmt -j- -g url -u- <<< "$CONTENT")" || [ -z "$URL" ]; then
-+    echo "URL was not found!" >&2
-+    exit 1
-+fi
-+
-+if ! jws="$(curl -sfg "$URL/adv")"; then
-+    echo "Unable to fetch advertisement: $URL/adv!" >&2
-+    exit 1
-+fi
-+
-+if ! TANG_KEYS="$(jose fmt -j- -Og payload -SyOg keys -AUo- <<< "$jws")"; then
-+    echo "Advertisement is malformed!" >&2
-+    exit 1
-+fi
-+
-+### Check advertisement validity
-+ver="$(jose jwk use -i- -r -u verify -o- <<< "$TANG_KEYS")"
-+if ! jose jws ver -i "$jws" -k- -a <<< "$ver"; then
-+    echo "Advertisement is missing signatures!" >&2
-+    exit 1
-+fi
-+
-+if ! LUKS_KEYS="$(jose fmt -j- -g adv -o- <<< "$CONTENT")" || [ -z "$LUKS_KEYS" ]; then
-+    echo "LUKS keys from LUKS metadata were not found!" >&2
-+    exit 1
-+fi
-+
-+EXE="$(findexe clevis-luks-report-compare)"
-+
-+exec "$EXE" "$TANG_KEYS" "$LUKS_KEYS"
-diff --git a/src/luks/clevis-luks-report.1.adoc b/src/luks/clevis-luks-report.1.adoc
-new file mode 100644
-index 0000000..cf42afe
---- /dev/null
-+++ b/src/luks/clevis-luks-report.1.adoc
-@@ -0,0 +1,41 @@
-+CLEVIS-LUKS-REPORT(1)
-+=====================
-+:doctype: manpage
-+
-+
-+== NAME
-+
-+clevis-luks-report - Reports whether a pin bound to a LUKS1 or LUKS2 volume has been rotated
-+
-+== SYNOPSIS
-+
-+*clevis luks report* -d DEV -s SLT
-+
-+== OVERVIEW
-+
-+The *clevis luks report* command checks a given slot of a LUKS device and reports whether the pin bound to it
-+-- if any -- has been rotated.
-+
-+== OPTIONS
-+
-+* *-d* _DEV_ :
-+  The bound LUKS device
-+
-+* *-s* _SLT_ :
-+  The slot or key slot number for the pin to be verified
-+
-+* *-q* :
-+  Quiet mode. If used, we will not prompt whether to regenerate data with *clevis luks regen*
-+
-+* *-r* :
-+  Regenerates LUKS metadata with *clevis luks regen -d DEV -s SLOT*
-+
-+== EXAMPLE
-+
-+    Check whether the pin bound to slot 1 in /dev/sda1 has been rotated:
-+
-+    # clevis luks report -d /dev/sda1 -s 1
-+
-+== SEE ALSO
-+
-+link:clevis-luks-regen.1.adoc[*clevis-luks-regen*(1)]
-diff --git a/src/luks/meson.build b/src/luks/meson.build
-index 1f64ab0..7c045c4 100644
---- a/src/luks/meson.build
-+++ b/src/luks/meson.build
-@@ -15,6 +15,18 @@ if libcryptsetup.found() and luksmeta.found() and pwmake.found()
-   bins += join_paths(meson.current_source_dir(), 'clevis-luks-bind')
-   mans += join_paths(meson.current_source_dir(), 'clevis-luks-bind.1')
- 
-+  bins += join_paths(meson.current_source_dir(), 'clevis-luks-common-functions')
-+
-+  bins += join_paths(meson.current_source_dir(), 'clevis-luks-regen')
-+  mans += join_paths(meson.current_source_dir(), 'clevis-luks-regen.1')
-+
-+  bins += join_paths(meson.current_source_dir(), 'clevis-luks-report')
-+  bins += join_paths(meson.current_source_dir(), 'clevis-luks-report-compare')
-+  bins += join_paths(meson.current_source_dir(), 'clevis-luks-report-decode')
-+  bins += join_paths(meson.current_source_dir(), 'clevis-luks-report-sss')
-+  bins += join_paths(meson.current_source_dir(), 'clevis-luks-report-tang')
-+  mans += join_paths(meson.current_source_dir(), 'clevis-luks-report.1')
-+
-   mans += join_paths(meson.current_source_dir(), 'clevis-luks-unlockers.7')
- else
-   warning('Will not install LUKS support due to missing dependencies!')
--- 
-2.21.0
-
diff --git a/SOURCES/Add-device-TCTI-library-to-the-initramfs.patch b/SOURCES/Add-device-TCTI-library-to-the-initramfs.patch
deleted file mode 100644
index 6757e60..0000000
--- a/SOURCES/Add-device-TCTI-library-to-the-initramfs.patch
+++ /dev/null
@@ -1,34 +0,0 @@
-From 6826e5d31d6323eac5137404f0194bf2183b561c Mon Sep 17 00:00:00 2001
-From: Javier Martinez Canillas <javierm@redhat.com>
-Date: Wed, 7 Nov 2018 16:48:47 +0100
-Subject: [PATCH 3/3] Add device TCTI library to the initramfs
-
-The tpm2-tools don't dynamically link against the TCTI libraries anymore,
-but instead dlopen() the correct library depending on the TCTI used.
-
-So dracut isn't able anymore to figure out automatically using ldd what
-libraries are needed by the tpm2-tools. Since clevis uses the device TCTI
-to access the TPM directly, add the libtss2-tcti-device.so to the initrd.
-
-Suggested-by: Federico Chiacchiaretta <federico.chia@gmail.com>
-
-Fixes: ##74
----
- src/luks/systemd/dracut/module-setup.sh.in | 1 +
- 1 file changed, 1 insertion(+)
-
-diff --git a/src/luks/systemd/dracut/module-setup.sh.in b/src/luks/systemd/dracut/module-setup.sh.in
-index 41e7d6c9b002..990bf4aeed56 100755
---- a/src/luks/systemd/dracut/module-setup.sh.in
-+++ b/src/luks/systemd/dracut/module-setup.sh.in
-@@ -65,6 +65,7 @@ install() {
- 	    tpm2_pcrlist \
- 	    tpm2_unseal \
- 	    tpm2_load
-+	inst_libdir_file "libtss2-tcti-device.so*"
-     fi
- 
-     dracut_need_initqueue
--- 
-2.19.1
-
diff --git a/SOURCES/Add-rd.neednet-1-to-cmdline-only-if-there-are-device.patch b/SOURCES/Add-rd.neednet-1-to-cmdline-only-if-there-are-device.patch
deleted file mode 100644
index a73b797..0000000
--- a/SOURCES/Add-rd.neednet-1-to-cmdline-only-if-there-are-device.patch
+++ /dev/null
@@ -1,57 +0,0 @@
-From 25009adea66d3bf9b73f128273de28e532b03281 Mon Sep 17 00:00:00 2001
-From: Sergio Correia <scorreia@redhat.com>
-Date: Sat, 30 Nov 2019 18:23:09 -0500
-Subject: [PATCH] Add rd.neednet=1 to cmdline only if there are devices bound
- to tang
-
----
- src/luks/systemd/dracut/module-setup.sh.in | 24 ++++++++++++++++++----
- 1 file changed, 20 insertions(+), 4 deletions(-)
-
-diff --git a/src/luks/systemd/dracut/module-setup.sh.in b/src/luks/systemd/dracut/module-setup.sh.in
-index 990bf4a..841f7a8 100755
---- a/src/luks/systemd/dracut/module-setup.sh.in
-+++ b/src/luks/systemd/dracut/module-setup.sh.in
-@@ -18,19 +18,35 @@
- # along with this program.  If not, see <http://www.gnu.org/licenses/>.
- #
- 
-+is_bound_to_tang() {
-+    local dev
-+    for dev in $(lsblk -p -n -s -r \
-+                 | awk '$6 == "crypt" { getline; print $1 }' | sort -u); do
-+       if clevis luks list -d "${dev}" 2>/dev/null | grep -q tang; then
-+           return 0
-+       fi
-+    done
-+    return 1
-+}
-+
- depends() {
--    echo crypt systemd network
--    return 0
-+    local depends="crypt systemd"
-+    if is_bound_to_tang; then
-+        depends=$(printf "%s network" "${depends}")
-+    fi
-+    echo "${depends}"
- }
- 
--cmdline() {
-+tang_cmdline() {
-     echo "rd.neednet=1"
- }
- 
- install() {
-     local ret=0
- 
--    cmdline > "${initdir}/etc/cmdline.d/99clevis.conf"
-+    if is_bound_to_tang; then
-+        tang_cmdline > "${initdir}/etc/cmdline.d/99clevis.conf"
-+    fi
- 
-     inst_hook initqueue/online 60 "$moddir/clevis-hook.sh"
-     inst_hook initqueue/settled 60 "$moddir/clevis-hook.sh"
--- 
-2.18.1
-
diff --git a/SOURCES/Add-support-for-listing-existing-PBD-policies-in-pla.patch b/SOURCES/Add-support-for-listing-existing-PBD-policies-in-pla.patch
deleted file mode 100644
index 4f6c2bf..0000000
--- a/SOURCES/Add-support-for-listing-existing-PBD-policies-in-pla.patch
+++ /dev/null
@@ -1,1009 +0,0 @@
-From a128130755bcd893ccf1d70b52c13fbaf29613c9 Mon Sep 17 00:00:00 2001
-From: Sergio Correia <scorreia@redhat.com>
-Date: Sat, 30 Nov 2019 14:26:59 -0500
-Subject: [PATCH] Add clevis luks list command
-
-Usage:
-clevis luks list -d DEV [-s SLT]
-
-Examples:
-
-clevis luks list -d device
-1: sss '{"t":1,"pins":{"tang":[{"url":"addr1"},{"url":"addr2"}],"tpm2":[{"hash":"sha256","key":"ecc"}],"sss":{"t":1,"pins":{"tang":[{"url":"addr3"}]}}}}'
-2: tang '{"url":"addr"}'
-3: tpm2 '{"hash":"sha256","key":"ecc","pcr_bank":"sha1","pcr_ids":"7"}'
-
-clevis luks list -d device -s 3
-3: tpm2 '{"hash":"sha256","key":"ecc","pcr_bank":"sha1","pcr_ids":"7"}'
----
- src/luks/clevis-luks-common-functions | 173 ++++++++++++++++++++++++++
- src/luks/clevis-luks-list             |  77 ++++++++++++
- src/luks/clevis-luks-list.1.adoc      |  58 +++++++++
- src/luks/meson.build                  |   8 +-
- src/luks/tests/list-recursive-luks1   |  85 +++++++++++++
- src/luks/tests/list-recursive-luks2   |  85 +++++++++++++
- src/luks/tests/list-sss-tang-luks1    |  77 ++++++++++++
- src/luks/tests/list-sss-tang-luks2    |  77 ++++++++++++
- src/luks/tests/list-tang-luks1        |  64 ++++++++++
- src/luks/tests/list-tang-luks2        |  64 ++++++++++
- src/luks/tests/meson.build            |  36 ++++++
- src/luks/tests/tests-common-functions |  76 +++++++++++
- 12 files changed, 879 insertions(+), 1 deletion(-)
- create mode 100755 src/luks/clevis-luks-list
- create mode 100644 src/luks/clevis-luks-list.1.adoc
- create mode 100755 src/luks/tests/list-recursive-luks1
- create mode 100755 src/luks/tests/list-recursive-luks2
- create mode 100755 src/luks/tests/list-sss-tang-luks1
- create mode 100755 src/luks/tests/list-sss-tang-luks2
- create mode 100755 src/luks/tests/list-tang-luks1
- create mode 100755 src/luks/tests/list-tang-luks2
- create mode 100644 src/luks/tests/meson.build
- create mode 100644 src/luks/tests/tests-common-functions
-
-diff --git a/src/luks/clevis-luks-common-functions b/src/luks/clevis-luks-common-functions
-index d676253..9ba1812 100644
---- a/src/luks/clevis-luks-common-functions
-+++ b/src/luks/clevis-luks-common-functions
-@@ -141,3 +141,176 @@ findexe() {
-     return 1
- }
- 
-+# clevis_luks_used_slots() will return the list of used slots for a given LUKS
-+# device.
-+clevis_luks_used_slots() {
-+    local DEV="${1}"
-+
-+    local slots
-+    if cryptsetup isLuks --type luks1 "${DEV}"; then
-+        readarray -t slots < <(cryptsetup luksDump "${DEV}" \
-+            | sed -rn 's|^Key Slot ([0-7]): ENABLED$|\1|p')
-+    elif cryptsetup isLuks --type luks2 "${DEV}"; then
-+        readarray -t slots < <(cryptsetup luksDump "${DEV}" \
-+            | sed -rn 's|^\s+([0-9]+): luks2$|\1|p')
-+    else
-+        echo "${DEV} is not a supported LUKS device!" >&2
-+        return 1
-+    fi
-+    echo "${slots[@]}"
-+}
-+
-+# clevis_luks_decode_jwe() will decode a given JWE.
-+clevis_luks_decode_jwe() {
-+    local jwe="${1}"
-+
-+    local coded
-+    if ! coded=$(jose jwe fmt -i- <<< "${jwe}"); then
-+        return 1
-+    fi
-+
-+    coded=$(jose fmt -j- -g protected -u- <<< "${coded}" | tr -d '"')
-+    jose b64 dec -i- <<< "${coded}"
-+}
-+
-+# clevis_luks_print_pin_config() will print the config of a given pin; i.e.
-+# for tang it will display the associated url address, and for tpm2, the
-+# properties in place, like the hash, for instance.
-+clevis_luks_print_pin_config() {
-+    local P="${1}"
-+    local decoded="${2}"
-+
-+    local content
-+    if ! content="$(jose fmt -j- -g clevis -g "${P}" -o- <<< "${decoded}")" \
-+                    || [[ -z "${content}" ]]; then
-+        return 1
-+    fi
-+
-+    local pin=
-+    case "${P}" in
-+    tang)
-+        local url
-+        url="$(jose fmt -j- -g url -u- <<< "${content}")"
-+        pin=$(printf '{"url":"%s"}' "${url}")
-+        printf "tang '%s'" "${pin}"
-+        ;;
-+    tpm2)
-+        # Valid properties for tpm2 pin are the following:
-+        # hash, key, pcr_bank, pcr_ids, pcr_digest.
-+        local key
-+        local value
-+        for key in 'hash' 'key' 'pcr_bank' 'pcr_ids' 'pcr_digest'; do
-+            if value=$(jose fmt -j- -g "${key}" -u- <<< "${content}"); then
-+                pin=$(printf '%s,"%s":"%s"' "${pin}" "${key}" "${value}")
-+            fi
-+        done
-+        # Remove possible leading comma.
-+        pin=${pin/#,/}
-+        printf "tpm2 '{%s}'" "${pin}"
-+        ;;
-+    sss)
-+        local threshold
-+        threshold=$(jose fmt -j- -Og t -o- <<< "${content}")
-+        clevis_luks_process_sss_pin "${content}" "${threshold}"
-+        ;;
-+    *)
-+        printf "unknown pin '%s'" "${P}"
-+        ;;
-+    esac
-+}
-+
-+# clevis_luks_decode_pin_config() will receive a JWE and extract a pin config
-+# from it.
-+clevis_luks_decode_pin_config() {
-+    local jwe="${1}"
-+
-+    local decoded
-+    if ! decoded=$(clevis_luks_decode_jwe "${jwe}"); then
-+        return 1
-+    fi
-+
-+    local P
-+    if ! P=$(jose fmt -j- -Og clevis -g pin -u- <<< "${decoded}"); then
-+        return 1
-+    fi
-+
-+    clevis_luks_print_pin_config "${P}" "${decoded}"
-+}
-+
-+# clevis_luks_join_sss_cfg() will receive a list of configurations for a given
-+# pin and returns it as list, in the format PIN [cfg1, cfg2, ..., cfgN].
-+clevis_luks_join_sss_cfg() {
-+    local pin="${1}"
-+    local cfg="${2}"
-+    cfg=$(echo "${cfg}" | tr -d "'" | sed -e 's/^,//')
-+    printf '"%s":[%s]' "${pin}" "${cfg}"
-+}
-+
-+# clevis_luks_process_sss_pin() will receive a JWE with information on the sss
-+# pin config, and also its associated threshold, and will extract the info.
-+clevis_luks_process_sss_pin() {
-+    local jwe="${1}"
-+    local threshold="${2}"
-+
-+    local sss_tang
-+    local sss_tpm2
-+    local sss
-+    local pin_cfg
-+    local pin
-+    local cfg
-+
-+    local coded
-+    for coded in $(jose fmt -j- -Og jwe -Af- <<< "${jwe}"| tr -d '"'); do
-+        if ! pin_cfg="$(clevis_luks_decode_pin_config "${coded}")"; then
-+            continue
-+        fi
-+        read -r pin cfg <<< "${pin_cfg}"
-+        case "${pin}" in
-+        tang)
-+            sss_tang="${sss_tang},${cfg}"
-+            ;;
-+        tpm2)
-+            sss_tpm2="${sss_tpm2},${cfg}"
-+            ;;
-+        sss)
-+            sss=$(echo "${cfg}" | tr -d "'")
-+            ;;
-+        esac
-+    done
-+
-+    cfg=
-+    if [[ -n "${sss_tang}" ]]; then
-+        cfg=$(clevis_luks_join_sss_cfg "tang" "${sss_tang}")
-+    fi
-+
-+    if [[ -n "${sss_tpm2}" ]]; then
-+        cfg="${cfg},"$(clevis_luks_join_sss_cfg "tpm2" "${sss_tpm2}")
-+    fi
-+
-+    if [[ -n "${sss}" ]]; then
-+        cfg=$(printf '%s,"sss":%s' "${cfg}" "${sss}")
-+    fi
-+
-+    # Remove possible leading comma.
-+    cfg=${cfg/#,/}
-+    pin=$(printf '{"t":%d,"pins":{%s}}' "${threshold}" "${cfg}")
-+    printf "sss '%s'" "${pin}"
-+}
-+
-+# clevis_luks_read_pins_from_slot() will receive a given device and slot and
-+# will then output its associated policy configuration.
-+clevis_luks_read_pins_from_slot() {
-+    local DEV="${1}"
-+    local SLOT="${2}"
-+
-+    local jwe
-+    if ! jwe=$(clevis_luks_read_slot "${DEV}" "${SLOT}" 2>/dev/null); then
-+        return 1
-+    fi
-+
-+    local cfg
-+    if ! cfg="$(clevis_luks_decode_pin_config "${jwe}")"; then
-+        return 1
-+    fi
-+    printf "%s: %s\n" "${SLOT}" "${cfg}"
-+}
-diff --git a/src/luks/clevis-luks-list b/src/luks/clevis-luks-list
-new file mode 100755
-index 0000000..58678c4
---- /dev/null
-+++ b/src/luks/clevis-luks-list
-@@ -0,0 +1,77 @@
-+#!/bin/bash -e
-+# vim: set tabstop=8 shiftwidth=4 softtabstop=4 expandtab smarttab colorcolumn=80:
-+#
-+# Copyright (c) 2017-2019 Red Hat, Inc.
-+# Author: Javier Martinez Canillas <javierm@redhat.com>
-+# Author: Sergio Correia <scorreia@redhat.com> - LUKS2 support.
-+#
-+# 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/>.
-+#
-+
-+. clevis-luks-common-functions
-+
-+SUMMARY="Lists pins bound to a LUKSv1 or LUKSv2 device"
-+
-+function usage() {
-+    echo >&2
-+    echo "Usage: clevis luks list -d DEV [-s SLT]" >&2
-+    echo >&2
-+    echo "$SUMMARY": >&2
-+    echo >&2
-+    echo "  -d DEV  The LUKS device to list bound pins" >&2
-+    echo >&2
-+    echo "  -s SLOT The slot number to list" >&2
-+    echo >&2
-+    exit 1
-+}
-+
-+if [ ${#} -eq 1 ] && [ "${1}" = "--summary" ]; then
-+    echo "${SUMMARY}"
-+    exit 0
-+fi
-+
-+while getopts ":d:s:" o; do
-+    case "$o" in
-+    d) DEV=${OPTARG};;
-+    s) SLT=${OPTARG};;
-+    *) usage;;
-+    esac
-+done
-+
-+if [ -z "${DEV}" ]; then
-+    echo "Did not specify a device!" >&2
-+    usage
-+fi
-+
-+if cryptsetup isLuks --type luks1 "${DEV}"; then
-+    if ! luksmeta test -d "${DEV}" 2>/dev/null; then
-+        echo "The ${DEV} device is not valid!" >&2
-+        exit 1
-+    fi
-+fi
-+
-+if [ -n "${SLT}" ]; then
-+    clevis_luks_read_pins_from_slot "${DEV}" "${SLT}"
-+else
-+    if ! slots=$(clevis_luks_used_slots "${DEV}"); then
-+        echo "No used slots detected for device ${DEV}!" >&2
-+        exit 1
-+    fi
-+
-+    for s in ${slots}; do
-+        if ! clevis_luks_read_pins_from_slot "${DEV}" "${s}"; then
-+            continue
-+        fi
-+    done
-+fi
-diff --git a/src/luks/clevis-luks-list.1.adoc b/src/luks/clevis-luks-list.1.adoc
-new file mode 100644
-index 0000000..2e84f05
---- /dev/null
-+++ b/src/luks/clevis-luks-list.1.adoc
-@@ -0,0 +1,58 @@
-+CLEVIS-LUKS-LIST(1)
-+===================
-+:doctype: manpage
-+
-+
-+== NAME
-+
-+clevis-luks-list - Lists pins bound to a LUKS device
-+
-+== SYNOPSIS
-+
-+*clevis luks list* -d DEV [-s SLT]
-+
-+== OVERVIEW
-+
-+The *clevis luks list* command list the pins bound to LUKS device.
-+For example:
-+
-+    clevis luks list -d /dev/sda1
-+
-+== OPTIONS
-+
-+* *-d* _DEV_ :
-+  The LUKS device on which to list bound pins
-+
-+* *-s* _SLT_ :
-+  The slot to use for listing the pin from
-+
-+== EXAMPLES
-+
-+    clevis luks list -d /dev/sda1
-+    1: sss '{"t":1,"pins":{"tang":[{"url":"addr1"},{"url":"addr2"}],"tpm2":[{"hash":"sha256","key":"ecc"}],"sss":{"t":1,"pins":{"tang":[{"url":"addr3"}]}}}}'
-+    2: tang '{"url":"addr"}'
-+    3: tpm2 '{"hash":"sha256","key":"ecc","pcr_bank":"sha1","pcr_ids":"7"}'
-+
-+As we can see in the example above, */dev/sda1* has three slots bound each with a different pin.
-+- Slot #1 is bound with the _sss_ pin, and uses also tang and tpm2 pins in its policy.
-+- Slot #2 is bound using the _tang_ pin
-+- Slot #3 is bound with the _tpm2_ pin
-+
-+Note that the output of *clevis luks list* can be used with the *clevis luks bind* command, such as:
-+
-+    clevis luks bind -d /dev/sda1 tpm2 '{"hash":"sha256","key":"ecc","pcr_bank":"sha1","pcr_ids":"7"}'
-+
-+And we will bind another slot with a policy similar to the one we have in slot #3.
-+Also note that if you are interested in a particular slot, you can pass the _-s SLT_ argument to *clevis luks list*:
-+
-+  clevis luks list -d /dev/sda1 -s 2
-+  2: tang '{"url":"addr"}'
-+
-+In the above example, we listed only the pin bound to slot #2.
-+
-+== SEE ALSO
-+
-+link:clevis-luks-bind.1.adoc[*clevis-luks-bind*(1)],
-+link:clevis-encrypt-tang.1.adoc[*clevis-encrypt-tang*(1)],
-+link:clevis-encrypt-tpm2.1.adoc[*clevis-encrypt-tpm2*(1)],
-+link:clevis-encrypt-sss.1.adoc[*clevis-encrypt-sss*(1)],
-diff --git a/src/luks/meson.build b/src/luks/meson.build
-index 7c045c4..51d82fb 100644
---- a/src/luks/meson.build
-+++ b/src/luks/meson.build
-@@ -20,6 +20,9 @@ if libcryptsetup.found() and luksmeta.found() and pwmake.found()
-   bins += join_paths(meson.current_source_dir(), 'clevis-luks-regen')
-   mans += join_paths(meson.current_source_dir(), 'clevis-luks-regen.1')
- 
-+  bins += join_paths(meson.current_source_dir(), 'clevis-luks-list')
-+  mans += join_paths(meson.current_source_dir(), 'clevis-luks-list.1')
-+
-   bins += join_paths(meson.current_source_dir(), 'clevis-luks-report')
-   bins += join_paths(meson.current_source_dir(), 'clevis-luks-report-compare')
-   bins += join_paths(meson.current_source_dir(), 'clevis-luks-report-decode')
-@@ -30,4 +33,7 @@ if libcryptsetup.found() and luksmeta.found() and pwmake.found()
-   mans += join_paths(meson.current_source_dir(), 'clevis-luks-unlockers.7')
- else
-   warning('Will not install LUKS support due to missing dependencies!')
--endif
-\ No newline at end of file
-+endif
-+
-+# Tests.
-+subdir('tests')
-diff --git a/src/luks/tests/list-recursive-luks1 b/src/luks/tests/list-recursive-luks1
-new file mode 100755
-index 0000000..d9eaa3a
---- /dev/null
-+++ b/src/luks/tests/list-recursive-luks1
-@@ -0,0 +1,85 @@
-+#!/bin/bash -ex
-+# vim: set tabstop=8 shiftwidth=4 softtabstop=4 expandtab smarttab colorcolumn=80:
-+#
-+# Copyright (c) 2019 Red Hat, Inc.
-+# Author: Sergio Correia <scorreia@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
-+
-+on_exit() {
-+    [ -d "${TMP}" ] && rm -rf "${TMP}"
-+}
-+
-+trap 'on_exit' EXIT
-+trap 'exit' ERR
-+
-+TMP="$(mktemp -d)"
-+
-+ADV="${TMP}/adv.jws"
-+create_tang_adv "${ADV}"
-+PIN="sss"
-+CFG=$(printf '
-+{
-+  "t": 1,
-+  "pins": {
-+    "sss": {
-+      "t": 1,
-+      "pins": {
-+        "sss": {
-+          "t": 1,
-+          "pins": {
-+            "tang": [
-+              {
-+                "url": "ADDR","adv": "%s"
-+              }
-+            ]
-+          }
-+        }
-+      }
-+    }
-+  }
-+}
-+' "${ADV}")
-+
-+# LUKS1.
-+DEV="${TMP}/luks1-device"
-+UUID="cb6e8904-81ff-40da-a84a-07ab9ab5715e"
-+new_device "luks1" "${DEV}"
-+
-+if ! clevis luks bind -f -d "${DEV}" "${PIN}" "${CFG}" <<< "${DEFAULT_PASS}"; then
-+    error "${TEST}: Binding is expected to succeed when given a correct (${DEFAULT_PASS}) password."
-+fi
-+
-+SLT=1
-+if ! read -r slot pin cfg < <(clevis luks list -d "${DEV}" -s "${SLT}"); then
-+    error "${TEST}: clevis luks list is expected to succeed for device(${DEV}) and slot (${SLT})"
-+fi
-+
-+if [[ "${slot}" != "${SLT}:" ]]; then
-+    error "${TEST}: slot (${slot}) is expected to be ${SLT}"
-+fi
-+
-+if [[ "${pin}" != "${PIN}" ]]; then
-+    error "${TEST}: pin (${pin}) is expected to be '${PIN}'"
-+fi
-+
-+to_remove_from_cfg=$(printf ',"adv": "%s"' "${ADV}")
-+cfg_for_cmp=${cfg//"${to_remove_from_cfg}"/}
-+if ! pin_cfg_equal "${cfg}" "${cfg_for_cmp}"; then
-+    error "${TEST}: config obtained from clevis luks list (${cfg}) is expected to match the one used to bind the test (${cfg_for_cmp})"
-+fi
-diff --git a/src/luks/tests/list-recursive-luks2 b/src/luks/tests/list-recursive-luks2
-new file mode 100755
-index 0000000..80a8278
---- /dev/null
-+++ b/src/luks/tests/list-recursive-luks2
-@@ -0,0 +1,85 @@
-+#!/bin/bash -ex
-+# vim: set tabstop=8 shiftwidth=4 softtabstop=4 expandtab smarttab colorcolumn=80:
-+#
-+# Copyright (c) 2019 Red Hat, Inc.
-+# Author: Sergio Correia <scorreia@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
-+
-+on_exit() {
-+    [ -d "${TMP}" ] && rm -rf "${TMP}"
-+}
-+
-+trap 'on_exit' EXIT
-+trap 'exit' ERR
-+
-+TMP="$(mktemp -d)"
-+
-+ADV="${TMP}/adv.jws"
-+create_tang_adv "${ADV}"
-+PIN="sss"
-+CFG=$(printf '
-+{
-+  "t": 1,
-+  "pins": {
-+    "sss": {
-+      "t": 1,
-+      "pins": {
-+        "sss": {
-+          "t": 1,
-+          "pins": {
-+            "tang": [
-+              {
-+                "url": "ADDR","adv": "%s"
-+              }
-+            ]
-+          }
-+        }
-+      }
-+    }
-+  }
-+}
-+' "${ADV}")
-+
-+# LUKS2.
-+DEV="${TMP}/luks1-device"
-+UUID="cb6e8904-81ff-40da-a84a-07ab9ab5715e"
-+new_device "luks2" "${DEV}"
-+
-+if ! clevis luks bind -f -d "${DEV}" "${PIN}" "${CFG}" <<< "${DEFAULT_PASS}"; then
-+    error "${TEST}: Binding is expected to succeed when given a correct (${DEFAULT_PASS}) password."
-+fi
-+
-+SLT=1
-+if ! read -r slot pin cfg < <(clevis luks list -d "${DEV}" -s "${SLT}"); then
-+    error "${TEST}: clevis luks list is expected to succeed for device(${DEV}) and slot (${SLT})"
-+fi
-+
-+if [[ "${slot}" != "${SLT}:" ]]; then
-+    error "${TEST}: slot (${slot}) is expected to be ${SLT}"
-+fi
-+
-+if [[ "${pin}" != "${PIN}" ]]; then
-+    error "${TEST}: pin (${pin}) is expected to be '${PIN}'"
-+fi
-+
-+to_remove_from_cfg=$(printf ',"adv": "%s"' "${ADV}")
-+cfg_for_cmp=${cfg//"${to_remove_from_cfg}"/}
-+if ! pin_cfg_equal "${cfg}" "${cfg_for_cmp}"; then
-+    error "${TEST}: config obtained from clevis luks list (${cfg}) is expected to match the one used to bind the test (${cfg_for_cmp})"
-+fi
-diff --git a/src/luks/tests/list-sss-tang-luks1 b/src/luks/tests/list-sss-tang-luks1
-new file mode 100755
-index 0000000..086fa35
---- /dev/null
-+++ b/src/luks/tests/list-sss-tang-luks1
-@@ -0,0 +1,77 @@
-+#!/bin/bash -ex
-+# vim: set tabstop=8 shiftwidth=4 softtabstop=4 expandtab smarttab colorcolumn=80:
-+#
-+# Copyright (c) 2019 Red Hat, Inc.
-+# Author: Sergio Correia <scorreia@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
-+
-+on_exit() {
-+    [ -d "${TMP}" ] && rm -rf "${TMP}"
-+}
-+
-+trap 'on_exit' EXIT
-+trap 'exit' ERR
-+
-+TMP="$(mktemp -d)"
-+
-+ADV="${TMP}/adv.jws"
-+create_tang_adv "${ADV}"
-+PIN="sss"
-+CFG=$(printf '
-+{
-+   "t": 2,
-+   "pins": {
-+     "tang": [
-+       {"url":"ADDR1","adv":"%s"},
-+       {"url":"ADDR2","adv":"%s"},
-+       {"url":"ADDR3","adv":"%s"},
-+       {"url":"ADDR4","adv":"%s"},
-+       {"url":"ADDR5","adv":"%s"}
-+     ]
-+   }
-+}
-+' "${ADV}" "${ADV}" "${ADV}" "${ADV}" "${ADV}")
-+
-+# LUKS1.
-+DEV="${TMP}/luks1-device"
-+UUID="cb6e8904-81ff-40da-a84a-07ab9ab5715e"
-+new_device "luks1" "${DEV}"
-+
-+if ! clevis luks bind -f -d "${DEV}" ${PIN} "${CFG}" <<< "${DEFAULT_PASS}"; then
-+    error "${TEST}: Binding is expected to succeed when given a correct (${DEFAULT_PASS}) password."
-+fi
-+
-+SLT=1
-+if ! read -r slot pin cfg < <(clevis luks list -d "${DEV}" -s "${SLT}"); then
-+    error "${TEST}: clevis luks list is expected to succeed for device(${DEV}) and slot (${SLT})"
-+fi
-+
-+if [[ "${slot}" != "${SLT}:" ]]; then
-+    error "${TEST}: slot (${slot}) is expected to be ${SLT}"
-+fi
-+
-+if [[ "${pin}" != "${PIN}" ]]; then
-+    error "${TEST}: pin (${pin}) is expected to be '${PIN}'"
-+fi
-+
-+to_remove_from_cfg=$(printf ',"adv": "%s"' "${ADV}")
-+cfg_for_cmp=${cfg//"${to_remove_from_cfg}"/}
-+if ! pin_cfg_equal "${cfg}" "${cfg_for_cmp}"; then
-+    error "${TEST}: config obtained from clevis luks list (${cfg}) is expected to match the one used to bind the test (${cfg_for_cmp})"
-+fi
-diff --git a/src/luks/tests/list-sss-tang-luks2 b/src/luks/tests/list-sss-tang-luks2
-new file mode 100755
-index 0000000..ea4cfbb
---- /dev/null
-+++ b/src/luks/tests/list-sss-tang-luks2
-@@ -0,0 +1,77 @@
-+#!/bin/bash -ex
-+# vim: set tabstop=8 shiftwidth=4 softtabstop=4 expandtab smarttab colorcolumn=80:
-+#
-+# Copyright (c) 2019 Red Hat, Inc.
-+# Author: Sergio Correia <scorreia@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
-+
-+on_exit() {
-+    [ -d "${TMP}" ] && rm -rf "${TMP}"
-+}
-+
-+trap 'on_exit' EXIT
-+trap 'exit' ERR
-+
-+TMP="$(mktemp -d)"
-+
-+ADV="${TMP}/adv.jws"
-+create_tang_adv "${ADV}"
-+PIN="sss"
-+CFG=$(printf '
-+{
-+   "t": 2,
-+   "pins": {
-+     "tang": [
-+       {"url":"ADDR1","adv":"%s"},
-+       {"url":"ADDR2","adv":"%s"},
-+       {"url":"ADDR3","adv":"%s"},
-+       {"url":"ADDR4","adv":"%s"},
-+       {"url":"ADDR5","adv":"%s"}
-+     ]
-+   }
-+}
-+' "${ADV}" "${ADV}" "${ADV}" "${ADV}" "${ADV}")
-+
-+# LUKS2.
-+DEV="${TMP}/luks1-device"
-+UUID="cb6e8904-81ff-40da-a84a-07ab9ab5715e"
-+new_device "luks2" "${DEV}"
-+
-+if ! clevis luks bind -f -d "${DEV}" ${PIN} "${CFG}" <<< "${DEFAULT_PASS}"; then
-+    error "${TEST}: Binding is expected to succeed when given a correct (${DEFAULT_PASS}) password."
-+fi
-+
-+SLT=1
-+if ! read -r slot pin cfg < <(clevis luks list -d "${DEV}" -s "${SLT}"); then
-+    error "${TEST}: clevis luks list is expected to succeed for device(${DEV}) and slot (${SLT})"
-+fi
-+
-+if [[ "${slot}" != "${SLT}:" ]]; then
-+    error "${TEST}: slot (${slot}) is expected to be ${SLT}"
-+fi
-+
-+if [[ "${pin}" != "${PIN}" ]]; then
-+    error "${TEST}: pin (${pin}) is expected to be '${PIN}'"
-+fi
-+
-+to_remove_from_cfg=$(printf ',"adv": "%s"' "${ADV}")
-+cfg_for_cmp=${cfg//"${to_remove_from_cfg}"/}
-+if ! pin_cfg_equal "${cfg}" "${cfg_for_cmp}"; then
-+    error "${TEST}: config obtained from clevis luks list (${cfg}) is expected to match the one used to bind the test (${cfg_for_cmp})"
-+fi
-diff --git a/src/luks/tests/list-tang-luks1 b/src/luks/tests/list-tang-luks1
-new file mode 100755
-index 0000000..c526693
---- /dev/null
-+++ b/src/luks/tests/list-tang-luks1
-@@ -0,0 +1,64 @@
-+#!/bin/bash -ex
-+# vim: set tabstop=8 shiftwidth=4 softtabstop=4 expandtab smarttab colorcolumn=80:
-+#
-+# Copyright (c) 2019 Red Hat, Inc.
-+# Author: Sergio Correia <scorreia@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
-+
-+on_exit() {
-+    [ -d "${TMP}" ] && rm -rf "${TMP}"
-+}
-+
-+trap 'on_exit' EXIT
-+trap 'exit' ERR
-+
-+TMP="$(mktemp -d)"
-+
-+ADV="${TMP}/adv.jws"
-+create_tang_adv "${ADV}"
-+PIN="tang"
-+CFG=$(printf '{"url": "ADDR","adv": "%s"}' "${ADV}")
-+
-+# LUKS1.
-+DEV="${TMP}/luks1-device"
-+UUID="cb6e8904-81ff-40da-a84a-07ab9ab5715e"
-+new_device "luks1" "${DEV}"
-+
-+if ! clevis luks bind -f -d "${DEV}" "${PIN}" "${CFG}" <<< "${DEFAULT_PASS}"; then
-+    error "${TEST}: Binding is expected to succeed when given a correct (${DEFAULT_PASS}) password."
-+fi
-+
-+SLT=1
-+if ! read -r slot pin cfg < <(clevis luks list -d "${DEV}" -s "${SLT}"); then
-+    error "${TEST}: clevis luks list is expected to succeed for device(${DEV}) and slot (${SLT})"
-+fi
-+
-+if [[ "${slot}" != "${SLT}:" ]]; then
-+    error "${TEST}: slot (${slot}) is expected to be ${SLT}"
-+fi
-+
-+if [[ "${pin}" != "${PIN}" ]]; then
-+    error "${TEST}: pin (${pin}) is expected to be '${PIN}'"
-+fi
-+
-+to_remove_from_cfg=$(printf ',"adv": "%s"' "${ADV}")
-+cfg_for_cmp=${cfg//"${to_remove_from_cfg}"/}
-+if ! pin_cfg_equal "${cfg}" "${cfg_for_cmp}"; then
-+    error "${TEST}: config obtained from clevis luks list (${cfg}) is expected to match the one used to bind the test (${cfg_for_cmp})"
-+fi
-diff --git a/src/luks/tests/list-tang-luks2 b/src/luks/tests/list-tang-luks2
-new file mode 100755
-index 0000000..d4d4849
---- /dev/null
-+++ b/src/luks/tests/list-tang-luks2
-@@ -0,0 +1,64 @@
-+#!/bin/bash -ex
-+# vim: set tabstop=8 shiftwidth=4 softtabstop=4 expandtab smarttab colorcolumn=80:
-+#
-+# Copyright (c) 2019 Red Hat, Inc.
-+# Author: Sergio Correia <scorreia@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
-+
-+on_exit() {
-+    [ -d "${TMP}" ] && rm -rf "${TMP}"
-+}
-+
-+trap 'on_exit' EXIT
-+trap 'exit' ERR
-+
-+TMP="$(mktemp -d)"
-+
-+ADV="${TMP}/adv.jws"
-+create_tang_adv "${ADV}"
-+PIN="tang"
-+CFG=$(printf '{"url": "ADDR","adv": "%s"}' "${ADV}")
-+
-+# LUKS2.
-+DEV="${TMP}/luks1-device"
-+UUID="cb6e8904-81ff-40da-a84a-07ab9ab5715e"
-+new_device "luks2" "${DEV}"
-+
-+if ! clevis luks bind -f -d "${DEV}" "${PIN}" "${CFG}" <<< "${DEFAULT_PASS}"; then
-+    error "${TEST}: Binding is expected to succeed when given a correct (${DEFAULT_PASS}) password."
-+fi
-+
-+SLT=1
-+if ! read -r slot pin cfg < <(clevis luks list -d "${DEV}" -s "${SLT}"); then
-+    error "${TEST}: clevis luks list is expected to succeed for device(${DEV}) and slot (${SLT})"
-+fi
-+
-+if [[ "${slot}" != "${SLT}:" ]]; then
-+    error "${TEST}: slot (${slot}) is expected to be ${SLT}"
-+fi
-+
-+if [[ "${pin}" != "${PIN}" ]]; then
-+    error "${TEST}: pin (${pin}) is expected to be '${PIN}'"
-+fi
-+
-+to_remove_from_cfg=$(printf ',"adv": "%s"' "${ADV}")
-+cfg_for_cmp=${cfg//"${to_remove_from_cfg}"/}
-+if ! pin_cfg_equal "${cfg}" "${cfg_for_cmp}"; then
-+    error "${TEST}: config obtained from clevis luks list (${cfg}) is expected to match the one used to bind the test (${cfg_for_cmp})"
-+fi
-diff --git a/src/luks/tests/meson.build b/src/luks/tests/meson.build
-new file mode 100644
-index 0000000..6513eaa
---- /dev/null
-+++ b/src/luks/tests/meson.build
-@@ -0,0 +1,36 @@
-+# We use jq for comparing the pin config in the clevis luks list tests.
-+jq = find_program('jq', required: 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'),
-+  separator: ':'
-+)
-+
-+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
-+
-+# 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 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
-diff --git a/src/luks/tests/tests-common-functions b/src/luks/tests/tests-common-functions
-new file mode 100644
-index 0000000..b65a84a
---- /dev/null
-+++ b/src/luks/tests/tests-common-functions
-@@ -0,0 +1,76 @@
-+#!/bin/bash -ex
-+# vim: set tabstop=8 shiftwidth=4 softtabstop=4 expandtab smarttab colorcolumn=80:
-+#
-+# Copyright (c) 2019 Red Hat, Inc.
-+# Author: Sergio Correia <scorreia@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/>.
-+#
-+
-+# We require cryptsetup >= 2.0.4 to fully support LUKSv2.
-+# Support is determined at build time.
-+luks2_supported() {
-+    # In RHEL8 we support LUKS2.
-+    return 0
-+}
-+
-+# Creates a tang adv to be used in the test.
-+create_tang_adv() {
-+    local adv="${1}"
-+    local SIG="${TMP}/sig.jwk"
-+    jose jwk gen -i '{"alg":"ES512"}' > "${SIG}"
-+
-+    local EXC="${TMP}/exc.jwk"
-+    jose jwk gen -i '{"alg":"ECMR"}' > "${EXC}"
-+
-+    local TEMPLATE='{"protected":{"cty":"jwk-set+json"}}'
-+    jose jwk pub -s -i "${SIG}" -i "${EXC}" \
-+        | jose jws sig -I- -s "${TEMPLATE}" -k "${SIG}" -o "${adv}"
-+}
-+
-+
-+# Creates a new LUKS1 or LUKS2 device to be used.
-+new_device() {
-+    local LUKS="${1}"
-+    local DEV="${2}"
-+
-+    local DEV_CACHED="${TMP}/${LUKS}.cached"
-+
-+    # Let's reuse an existing device, if there is one.
-+    if [ -f "${DEV_CACHED}" ]; then
-+        echo "Reusing cached ${LUKS} device..."
-+        cp -f "${DEV_CACHED}" "${DEV}"
-+        return 0
-+    fi
-+
-+    fallocate -l16M "${DEV}"
-+    cryptsetup luksFormat --type "${LUKS}" --batch-mode --force-password "${DEV}" <<< "${DEFAULT_PASS}"
-+    # Caching the just-formatted device for possible reuse.
-+    cp -f "${DEV}" "${DEV_CACHED}"
-+}
-+
-+error() {
-+    echo "${1}" >&2
-+    exit 1
-+}
-+
-+pin_cfg_equal() {
-+    local cfg1="${1}"
-+    local cfg2="${1}"
-+
-+    diff <(jq -S . < <(echo -n "${cfg1}")) \
-+         <(jq -S . < <(echo -n "${cfg2}"))
-+}
-+
-+export DEFAULT_PASS='just-some-test-password-here'
--- 
-2.18.1
-
diff --git a/SOURCES/Add-the-option-to-extract-luks-passphrase-used-for-b.patch b/SOURCES/Add-the-option-to-extract-luks-passphrase-used-for-b.patch
deleted file mode 100644
index 4f2465d..0000000
--- a/SOURCES/Add-the-option-to-extract-luks-passphrase-used-for-b.patch
+++ /dev/null
@@ -1,364 +0,0 @@
-From 69556d143544a72f84e9daf25924e3ae5132ce1a Mon Sep 17 00:00:00 2001
-From: Sergio Correia <scorreia@redhat.com>
-Date: Sat, 30 Nov 2019 14:58:43 -0500
-Subject: [PATCH] Add the option to extract luks passphrase used for binding
-
-Usage:
-
-clevis luks pass -d /dev/sda1 -s 1
-<passphrase here>
----
- src/luks/clevis-luks-pass        | 69 +++++++++++++++++++++++++++++
- src/luks/clevis-luks-pass.1.adoc | 43 ++++++++++++++++++
- src/luks/meson.build             |  3 ++
- src/luks/tests/meson.build       | 11 +++++
- src/luks/tests/pass-tang-luks1   | 75 ++++++++++++++++++++++++++++++++
- src/luks/tests/pass-tang-luks2   | 75 ++++++++++++++++++++++++++++++++
- 6 files changed, 276 insertions(+)
- create mode 100755 src/luks/clevis-luks-pass
- create mode 100644 src/luks/clevis-luks-pass.1.adoc
- create mode 100755 src/luks/tests/pass-tang-luks1
- create mode 100755 src/luks/tests/pass-tang-luks2
-
-diff --git a/src/luks/clevis-luks-pass b/src/luks/clevis-luks-pass
-new file mode 100755
-index 0000000..1ce8c4c
---- /dev/null
-+++ b/src/luks/clevis-luks-pass
-@@ -0,0 +1,69 @@
-+#!/bin/bash -e
-+# vim: set tabstop=8 shiftwidth=4 softtabstop=4 expandtab smarttab colorcolumn=80:
-+#
-+# Copyright (c) 2019 Red Hat, Inc.
-+# Author: Sergio Correia <scorreia@redhat.com> - LUKS2 support.
-+#
-+# 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/>.
-+#
-+
-+. clevis-luks-common-functions
-+
-+SUMMARY="Returns the LUKS passphrase used for binding a particular slot."
-+
-+function usage() {
-+    echo >&2
-+    echo "Usage: clevis luks pass -d DEV -s SLT" >&2
-+    echo >&2
-+    echo "$SUMMARY": >&2
-+    echo >&2
-+    echo "  -d DEV  The LUKS device to extract the LUKS passphrase used for binding" >&2
-+    echo >&2
-+    echo "  -s SLOT The slot number to extract the LUKS passphrase" >&2
-+    echo >&2
-+    exit 1
-+}
-+
-+if [ ${#} -eq 1 ] && [ "${1}" = "--summary" ]; then
-+    echo "${SUMMARY}"
-+    exit 0
-+fi
-+
-+while getopts ":d:s:" o; do
-+    case "$o" in
-+    d) DEV=${OPTARG};;
-+    s) SLT=${OPTARG};;
-+    *) usage;;
-+    esac
-+done
-+
-+if [ -z "${DEV}" ]; then
-+    echo "Did not specify a device!" >&2
-+    usage
-+fi
-+
-+if [ -z "${SLT}" ]; then
-+    echo "Did not specify a slot!" >&2
-+    usage
-+fi
-+
-+if ! jwe=$(clevis_luks_read_slot "${DEV}" "${SLT}" 2>/dev/null); then
-+    echo "It was not possible to read slot ${SLT} from ${DEV}!" >&2
-+    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
-+    exit 1
-+fi
-diff --git a/src/luks/clevis-luks-pass.1.adoc b/src/luks/clevis-luks-pass.1.adoc
-new file mode 100644
-index 0000000..fa9526a
---- /dev/null
-+++ b/src/luks/clevis-luks-pass.1.adoc
-@@ -0,0 +1,43 @@
-+CLEVIS-LUKS-PASS(1)
-+===================
-+:doctype: manpage
-+
-+
-+== NAME
-+
-+clevis-luks-pass - Extracts the passphrase used for binding a particular slot in a LUKS device
-+
-+== SYNOPSIS
-+
-+*clevis luks pass* -d DEV -s SLT
-+
-+== OVERVIEW
-+
-+The *clevis luks pass* command extracts the passphrase used for binding a particular slot in a LUKS device.
-+For example:
-+
-+    clevis luks pass -d /dev/sda1 -s 1
-+
-+== OPTIONS
-+
-+* *-d* _DEV_ :
-+  The LUKS device on which to extract a passphrase from
-+
-+* *-s* _SLT_ :
-+  The slot to use for extracting the passphrase
-+
-+== EXAMPLE
-+
-+    clevis luks pass -d /dev/sda1 -s 1
-+    <passphrase here>
-+
-+Note that the output of *clevis luks pass* might be non-printable, in which case it would be better to redirect its output to a file and use it as a key
-+file together with cryptsetup. For instance:
-+
-+    clevis luks pass -d /dev/sda1 -s 1 > slot1-passphrase
-+
-+And the file slot1-passphrase will contain the passphrase associated with slot #1 in /dev/sda1.
-+
-+== SEE ALSO
-+
-+link:clevis-luks-unlock.1.adoc[*clevis-luks-unlock*(1)],
-diff --git a/src/luks/meson.build b/src/luks/meson.build
-index 51d82fb..b2dd724 100644
---- a/src/luks/meson.build
-+++ b/src/luks/meson.build
-@@ -23,6 +23,9 @@ if libcryptsetup.found() and luksmeta.found() and pwmake.found()
-   bins += join_paths(meson.current_source_dir(), 'clevis-luks-list')
-   mans += join_paths(meson.current_source_dir(), 'clevis-luks-list.1')
- 
-+  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-report')
-   bins += join_paths(meson.current_source_dir(), 'clevis-luks-report-compare')
-   bins += join_paths(meson.current_source_dir(), 'clevis-luks-report-decode')
-diff --git a/src/luks/tests/meson.build b/src/luks/tests/meson.build
-index 6513eaa..248d2ea 100644
---- a/src/luks/tests/meson.build
-+++ b/src/luks/tests/meson.build
-@@ -1,3 +1,9 @@
-+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)
- 
-@@ -15,8 +21,11 @@ env.prepend('PATH',
-   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())
- 
- if jq.found()
-   test('list-recursive-luks1', find_program('list-recursive-luks1'), env: env)
-@@ -25,6 +34,7 @@ if jq.found()
- else
-   warning('Will not run "clevis luks list" tests due to missing jq dependency')
- 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.
-@@ -34,3 +44,4 @@ if jq.found()
-   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
-+test('pass-tang-luks2', find_program('pass-tang-luks2'), env: env, timeout: 60)
-diff --git a/src/luks/tests/pass-tang-luks1 b/src/luks/tests/pass-tang-luks1
-new file mode 100755
-index 0000000..05cdb3e
---- /dev/null
-+++ b/src/luks/tests/pass-tang-luks1
-@@ -0,0 +1,75 @@
-+#!/bin/bash -x
-+# vim: set tabstop=8 shiftwidth=4 softtabstop=4 expandtab smarttab colorcolumn=80:
-+#
-+# Copyright (c) 2019 Red Hat, Inc.
-+# Author: Sergio Correia <scorreia@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="${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}"
-+
-+if ! clevis luks bind -f -d "${DEV}" tang "${cfg}" <<< "${DEFAULT_PASS}"; then
-+    error "${TEST}: Bind should have succeeded."
-+fi
-+
-+#Now let's test the passphrase.
-+SLT=1
-+PASS=$(clevis luks pass -d "${DEV}" -s "${SLT}")
-+echo $PASS >&2
-+if ! cryptsetup luksOpen --test-passphrase ""${DEV} \
-+        --key-file <(clevis luks pass -d "${DEV}" -s "${SLT}"); then
-+    error "Passphrase obtained from clevis luks pass failed."
-+fi
-+
-+kill -9 "${PID}"
-+! wait "${PID}"
-+unset PID
-diff --git a/src/luks/tests/pass-tang-luks2 b/src/luks/tests/pass-tang-luks2
-new file mode 100755
-index 0000000..9123aa0
---- /dev/null
-+++ b/src/luks/tests/pass-tang-luks2
-@@ -0,0 +1,75 @@
-+#!/bin/bash -x
-+# vim: set tabstop=8 shiftwidth=4 softtabstop=4 expandtab smarttab colorcolumn=80:
-+#
-+# Copyright (c) 2019 Red Hat, Inc.
-+# Author: Sergio Correia <scorreia@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="${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}"
-+
-+if ! clevis luks bind -f -d "${DEV}" tang "${cfg}" <<< "${DEFAULT_PASS}"; then
-+    error "${TEST}: Bind should have succeeded."
-+fi
-+
-+#Now let's test the passphrase.
-+SLT=1
-+PASS=$(clevis luks pass -d "${DEV}" -s "${SLT}")
-+echo $PASS >&2
-+if ! cryptsetup luksOpen --test-passphrase ""${DEV} \
-+        --key-file <(clevis luks pass -d "${DEV}" -s "${SLT}"); then
-+    error "Passphrase obtained from clevis luks pass failed."
-+fi
-+
-+kill -9 "${PID}"
-+! wait "${PID}"
-+unset PID
--- 
-2.18.1
-
diff --git a/SOURCES/Adjust-pin-tang-test-to-account-for-newer-tang-witho.patch b/SOURCES/Adjust-pin-tang-test-to-account-for-newer-tang-witho.patch
deleted file mode 100644
index 20e6137..0000000
--- a/SOURCES/Adjust-pin-tang-test-to-account-for-newer-tang-witho.patch
+++ /dev/null
@@ -1,77 +0,0 @@
-From 53ecfcf6d934206e3daef4ed3515a0d6f098e276 Mon Sep 17 00:00:00 2001
-From: Sergio Correia <scorreia@redhat.com>
-Date: Wed, 16 Oct 2019 11:40:33 -0300
-Subject: [PATCH 1/2] Adjust pin-tang test to account for newer tang without
- tangd-update
-
----
- src/pins/tang/meson.build |  9 ++-------
- src/pins/tang/pin-tang    | 11 ++++++++---
- 2 files changed, 10 insertions(+), 10 deletions(-)
-
-diff --git a/src/pins/tang/meson.build b/src/pins/tang/meson.build
-index 110d72d..061a79f 100644
---- a/src/pins/tang/meson.build
-+++ b/src/pins/tang/meson.build
-@@ -8,11 +8,6 @@ kgen = find_program(
-   '/usr/libexec/tangd-keygen',
-   required: false
- )
--updt = find_program(
--  join_paths(libexecdir, 'tangd-update'),
--  '/usr/libexec/tangd-update',
--  required: false
--)
- tang = find_program(
-   join_paths(libexecdir, 'tangd'),
-   '/usr/libexec/tangd',
-@@ -25,7 +20,7 @@ if curl.found()
-   bins += join_paths(meson.current_source_dir(), 'clevis-encrypt-tang')
-   mans += join_paths(meson.current_source_dir(), 'clevis-encrypt-tang.1')
- 
--  if actv.found() and kgen.found() and updt.found() and tang.found()
-+  if actv.found() and kgen.found() and tang.found()
-     env = environment()
-     env.set('SD_ACTIVATE', actv.path())
-     env.append('PATH',
-@@ -42,4 +37,4 @@ if curl.found()
-   endif
- else
-   warning('Will not install tang pin due to missing dependencies!')
--endif
-\ No newline at end of file
-+endif
-diff --git a/src/pins/tang/pin-tang b/src/pins/tang/pin-tang
-index f420818..9dcc2da 100755
---- a/src/pins/tang/pin-tang
-+++ b/src/pins/tang/pin-tang
-@@ -31,18 +31,23 @@ mkdir -p $TMP/db
- mkdir -p $TMP/cache
- 
- # Generate the server keys
-+KEYS=$TMP/db
- tangd-keygen $TMP/db sig exc
--tangd-update $TMP/db $TMP/cache
-+if which tangd-update; then
-+    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 $TMP/cache &
-+$SD_ACTIVATE --inetd -l 127.0.0.1:$port -a tangd $KEYS &
- export PID=$!
- sleep 0.25
- 
- thp=`jose jwk thp -i "$TMP/db/sig.jwk"`
--adv="$TMP/cache/default.jws"
- url="http://localhost:${port}"
-+adv="$TMP/adv"
-+curl "$url/adv" -o $adv
- 
- cfg=`printf '{"url":"%s","adv":"%s"}' "$url" "$adv"`
- enc=`echo -n "hi" | clevis encrypt tang "$cfg"`
--- 
-2.21.0
-
diff --git a/SOURCES/Check-key-derivation-key-is-available.patch b/SOURCES/Check-key-derivation-key-is-available.patch
deleted file mode 100644
index bc1be6f..0000000
--- a/SOURCES/Check-key-derivation-key-is-available.patch
+++ /dev/null
@@ -1,30 +0,0 @@
-From 8b707e8bfcbfd073579ee553b982b4784490f5ea Mon Sep 17 00:00:00 2001
-From: Daniel Kopecek <dkopecek@redhat.com>
-Date: Wed, 5 Dec 2018 13:18:59 +0100
-Subject: [PATCH] clevis-encrypt-tang: check key derivation key is available
- before encryption
-
----
- src/pins/tang/clevis-encrypt-tang | 6 +++++-
- 1 file changed, 5 insertions(+), 1 deletion(-)
-
-diff --git a/src/pins/tang/clevis-encrypt-tang b/src/pins/tang/clevis-encrypt-tang
-index e65a7d1..7fc55ca 100755
---- a/src/pins/tang/clevis-encrypt-tang
-+++ b/src/pins/tang/clevis-encrypt-tang
-@@ -114,7 +114,11 @@ elif [ "$thp" != "any" ] && \
- fi
- 
- ### Perform encryption
--enc=`jose jwk use -i- -r -u deriveKey -o- <<< "$jwks"`
-+if ! enc=`jose jwk use -i- -r -u deriveKey -o- <<< "$jwks"`; then
-+    echo "Key derivation key not available!" >&2
-+    exit 1
-+fi
-+
- jose fmt -j "$enc" -Og keys -A || enc="{\"keys\":[$enc]}"
- 
- for jwk in `jose fmt -j- -Og keys -Af- <<< "$enc"`; do
--- 
-2.13.6
-
diff --git a/SOURCES/Delete-remaining-references-to-the-removed-http-pin.patch b/SOURCES/Delete-remaining-references-to-the-removed-http-pin.patch
deleted file mode 100644
index 36f1361..0000000
--- a/SOURCES/Delete-remaining-references-to-the-removed-http-pin.patch
+++ /dev/null
@@ -1,132 +0,0 @@
-From 1e344dbf6a60fcd2c60a4b8512be455e112d8398 Mon Sep 17 00:00:00 2001
-From: Javier Martinez Canillas <javierm@redhat.com>
-Date: Wed, 7 Nov 2018 14:53:08 +0100
-Subject: [PATCH 1/3] Delete remaining references to the removed http pin
-
-Commit 800d73185d7f ("Remove HTTP pin") removed the clevis http pin, but
-there are still references of it in the docs and also the dracut module.
-
-This was causing dracut to fail building the initramfs due the following:
-
-dracut-install: ERROR: installing 'clevis-decrypt-http'
-
-Suggested-by: Dominick Grift <dac.override@gmail.com>
-
-Fixes: #73
----
- README.md                                  | 21 ---------------------
- src/clevis.1.adoc                          | 21 ---------------------
- src/luks/clevis-luks-bind.1.adoc           |  1 -
- src/luks/systemd/dracut/module-setup.sh.in |  1 -
- src/pins/sss/clevis-encrypt-sss.1.adoc     |  1 -
- 5 files changed, 45 deletions(-)
-
-diff --git a/README.md b/README.md
-index ce8def12ec96..d57339aca5d9 100644
---- a/README.md
-+++ b/README.md
-@@ -58,27 +58,6 @@ advertisement is stored, or the JSON contents of the advertisment itself. When
- the advertisment is specified manually like this, Clevis presumes that the
- advertisement is trusted.
- 
--#### PIN: HTTP
--
--Clevis also ships a pin for performing escrow using HTTP. Please note that,
--at this time, this pin does not provide HTTPS support and is suitable only
--for use over local sockets. This provides integration with services like
--[Custodia](http://github.com/latchset/custodia).
--
--For example:
--
--```bash
--$ echo hi | clevis encrypt http '{"url": "http://server.local/key"}' > hi.jwe
--```
--
--The HTTP pin generate a new (cryptographically-strong random) key and performs
--encryption using it. It then performs a PUT request to the URL specified. It is
--understood that the server will securely store this key for later retrieval.
--During decryption, the pin will perform a GET request to retrieve the key and
--perform decryption.
--
--Patches to provide support for HTTPS and authentication are welcome.
--
- #### PIN: TPM2
- 
- Clevis provides support to encrypt a key in a Trusted Platform Module 2.0 (TPM2)
-diff --git a/src/clevis.1.adoc b/src/clevis.1.adoc
-index 756aba57a4c8..dea0a696f5f7 100644
---- a/src/clevis.1.adoc
-+++ b/src/clevis.1.adoc
-@@ -21,26 +21,6 @@ take a policy as its first argument and plaintext on standard input and to
- encrypt the data so that it can be automatically decrypted if the policy is
- met. Lets walk through an example.
- 
--== HTTP ESCROW
--
--When using the HTTP pin, we create a new, cryptographically-strong, random key.
--This key is stored in a remote HTTP escrow server (using a simple PUT or POST).
--Then at decryption time, we attempt to fetch the key back again in order to
--decrypt our data. So, for our configuration we need to pass the URL to the key
--location:
--
--    $ clevis encrypt http '{"url":"https://escrow.srv/1234"}' < PT > JWE
--
--To decrypt the data, simply provide the ciphertext (JWE):
--
--    $ clevis decrypt < JWE > PLAINTEXT
--
--Notice that we did not pass any configuration during decryption. The decrypt
--command extracted the URL (and possibly other configuration) from the JWE
--object, fetched the encryption key from the escrow and performed decryption.
--
--For more information, see link:clevis-encrypt-http.1.adoc[*clevis-encrypt-http*(1)].
--
- == TANG BINDING
- 
- Clevis provides support for the Tang network binding server. Tang provides
-@@ -136,7 +116,6 @@ For more information, see link:clevis-luks-bind.1.adoc[*clevis-luks-bind*(1)].
- 
- == SEE ALSO
- 
--link:clevis-encrypt-http.1.adoc[*clevis-encrypt-http*(1)],
- link:clevis-encrypt-tang.1.adoc[*clevis-encrypt-tang*(1)],
- link:clevis-encrypt-tpm2.1.adoc[*clevis-encrypt-tpm2*(1)],
- link:clevis-encrypt-sss.1.adoc[*clevis-encrypt-sss*(1)],
-diff --git a/src/luks/clevis-luks-bind.1.adoc b/src/luks/clevis-luks-bind.1.adoc
-index 9f3a880cfb0c..0d649e3ec28b 100644
---- a/src/luks/clevis-luks-bind.1.adoc
-+++ b/src/luks/clevis-luks-bind.1.adoc
-@@ -61,7 +61,6 @@ The images cannot be shared without also sharing a master key.
- == SEE ALSO
- 
- link:clevis-luks-unlockers.7.adoc[*clevis-luks-unlockers*(7)],
--link:clevis-encrypt-http.1.adoc[*clevis-encrypt-http*(1)],
- link:clevis-encrypt-tang.1.adoc[*clevis-encrypt-tang*(1)],
- link:clevis-encrypt-sss.1.adoc[*clevis-encrypt-sss*(1)],
- link:clevis-decrypt.1.adoc[*clevis-decrypt*(1)]
-diff --git a/src/luks/systemd/dracut/module-setup.sh.in b/src/luks/systemd/dracut/module-setup.sh.in
-index 119762e38326..48aea5b3f29a 100755
---- a/src/luks/systemd/dracut/module-setup.sh.in
-+++ b/src/luks/systemd/dracut/module-setup.sh.in
-@@ -36,7 +36,6 @@ install() {
-     inst_hook initqueue/settled 60 "$moddir/clevis-hook.sh"
- 
-     inst_multiple /etc/services \
--        clevis-decrypt-http \
-         clevis-decrypt-tang \
-         clevis-decrypt-sss \
-         @libexecdir@/clevis-luks-askpass \
-diff --git a/src/pins/sss/clevis-encrypt-sss.1.adoc b/src/pins/sss/clevis-encrypt-sss.1.adoc
-index d46498db328c..7144e7e9ea96 100644
---- a/src/pins/sss/clevis-encrypt-sss.1.adoc
-+++ b/src/pins/sss/clevis-encrypt-sss.1.adoc
-@@ -54,6 +54,5 @@ receive key fragments.
- 
- == SEE ALSO
- 
--link:clevis-encrypt-http.1.adoc[*clevis-encrypt-http*(1)],
- link:clevis-encrypt-tang.1.adoc[*clevis-encrypt-tang*(1)],
- link:clevis-decrypt.1.adoc[*clevis-decrypt*(1)]
--- 
-2.19.1
-
diff --git a/SOURCES/Improve-clevis-luks-regen-no-unbind-in-every-case.patch b/SOURCES/Improve-clevis-luks-regen-no-unbind-in-every-case.patch
deleted file mode 100644
index b905ada..0000000
--- a/SOURCES/Improve-clevis-luks-regen-no-unbind-in-every-case.patch
+++ /dev/null
@@ -1,1262 +0,0 @@
-From 5536f15b9235cb6ae1b79a5ad1d96a8ea97b3113 Mon Sep 17 00:00:00 2001
-From: Sergio Correia <scorreia@redhat.com>
-Date: Wed, 29 Jan 2020 06:29:32 -0500
-Subject: [PATCH] Improve clevis luks regen; no unbind in every case
-
-When updating the metadata -- likely due to a tang key rotation --,
-clevis will not do unbind + bind in every case.
-
-Now we have 2 cases to be handled:
-1) we have the key for the slot being rotated; in this case, the
-   rotation happens in-place
-
-2) we don't have the key for the slot being rotated; in this case,
-   we have to re-add the keyslot with updated info.
-
-Added also mechanisms for backup + restore of the LUKS header/slots,
-so that we can revert back to the original state if clevis luks regen
-fails.
----
- src/luks/clevis-luks-common-functions  | 202 ++++++++++++++++++++++
- src/luks/clevis-luks-pass              |   5 +-
- src/luks/clevis-luks-regen             | 223 ++++++++++++-------------
- src/luks/tests/backup-restore-luks1    | 114 +++++++++++++
- src/luks/tests/backup-restore-luks2    | 115 +++++++++++++
- src/luks/tests/meson.build             |   7 +
- 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  |  27 ++-
- 11 files changed, 966 insertions(+), 115 deletions(-)
- create mode 100755 src/luks/tests/backup-restore-luks1
- create mode 100755 src/luks/tests/backup-restore-luks2
- 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 9ba1812..2a1af26 100644
---- a/src/luks/clevis-luks-common-functions
-+++ b/src/luks/clevis-luks-common-functions
-@@ -314,3 +314,205 @@ clevis_luks_read_pins_from_slot() {
-     fi
-     printf "%s: %s\n" "${SLOT}" "${cfg}"
- }
-+
-+# 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="${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="${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
-index 9535ba3..44fd673 100755
---- a/src/luks/clevis-luks-regen
-+++ b/src/luks/clevis-luks-regen
-@@ -1,8 +1,9 @@
--#!/usr/bin/env bash
-+#!/usr/bin/bash
- # vim: set tabstop=8 shiftwidth=4 softtabstop=4 expandtab smarttab colorcolumn=80:
- #
- # Copyright (c) 2018 Red Hat, Inc.
- # Author: Radovan Sroka <rsroka@redhat.com>
-+# Author: Sergio Correia <scorreia@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
-@@ -28,19 +29,27 @@ if [ "$1" == "--summary" ]; then
- fi
- 
- function usage_and_exit () {
--    echo >&2
--    echo "Usage: clevis luks regen -d DEV -s SLOT" >&2
--    echo >&2
--    echo "$SUMMARY" >&2
--    echo >&2
--    exit "$1"
-+    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}"
- }
- 
--if [ "$#" -ne "4" ]; then
--    usage_and_exit 1
--fi
-+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 "hd:s:" o; do
-+while getopts ":hfd:s:" o; do
-     case "$o" in
-     d) DEV="$OPTARG";;
-     h) usage_and_exit 0;;
-@@ -49,88 +58,6 @@ while getopts "hd:s:" o; do
-     esac
- done
- 
--function decode_luks_header () {
--    if DATA_CODED="$(jose jwe fmt -i- <<< "$1")"; then
--        DATA_CODED="$(jose fmt -j- -g protected -u- <<< "$DATA_CODED")"
--        DATA_DECODED="$(jose b64 dec -i- <<< "$DATA_CODED")"
--    else
--        echo "Error decoding JWE protected header!" >&2
--        exit 1
--    fi
--
--    echo "$DATA_DECODED"
--}
--
--function generate_cfg () {
--    echo -n "{"
--    DATA="$(decode_luks_header "$1")"
--
--    if ! P="$(jose fmt -j- -g clevis -g pin -u- <<< "$DATA")" || [ -z "$P" ]; then
--        echo "Pin wasn't found in LUKS metadata!" >&2
--        exit 1
--    fi
--
--    if ! CONTENT="$(jose fmt -j- -g clevis -g "$P" -o- <<< "$DATA")" || [ -z "$CONTENT" ]; then
--        echo "Content was not found!" >&2
--    fi
--
--    # echo -n "\"$P\": ["
--
--    if [ "$P" = "tang" ] || [ "$P" = "http" ]; then
--        URL="$(jose fmt -j- -g url -u- <<< "$CONTENT")"
--        echo -n "\"url\":\"$URL\""
--    elif [ "$P" = "sss" ]; then
--        THRESHOLD="$(jose fmt -j- -g t -o- <<< "$CONTENT")"
--        if [ -n "$THRESHOLD" ]; then
--            echo -n "\"t\":$THRESHOLD,"
--        fi
--
--        echo -n "\"pins\":{"
--
--        CNT=0
--        PREV=""
--        while ITEM="$(jose fmt -j- -g jwe -g"$CNT" -u- <<< "$CONTENT")"; do
--            if [ -z "$ITEM" ]; then
--                CNT=$(( CNT + 1 ))
--                continue # in some cases it can be empty string
--            fi
--
--            DD="$(decode_luks_header "$ITEM")"
--
--            if ! PP="$(jose fmt -j- -g clevis -g pin -u- <<< "$DD")" || [ -z "$PP" ]; then
--                echo "Pin wasn't found in LUKS metadata!" >&2
--                exit 1
--            fi
--
--            if [ "$CNT" -eq 0 ]; then
--                PREV="$PP"
--                echo -n "\"$PP\":["
--                echo -n "$(generate_cfg "$ITEM")"
--            else
--                if ! [ "$PREV" = "$PP" ]; then
--                    echo -n "],\"$PP\":["
--                    echo -n "$(generate_cfg "$ITEM")"
--                else
--                    echo -n ",$(generate_cfg "$ITEM")"
--                fi
--            fi
--
--            PREV="$PP"
--            CNT=$(( CNT + 1 ))
--        done
--
--        echo -n "]}"
--
--    else
--        echo "Unknown pin $P!" >&2
--        exit 1
--    fi
--
--    echo -n "}"
--}
--
--### get luks metadata
--
- if [ -z "$DEV" ]; then
-     echo "Did not specify a device!" >&2
-     exit 1
-@@ -141,23 +68,14 @@ if [ -z "$SLT" ]; then
-     exit 1
- fi
- 
--if ! OLD_LUKS_CODED="$(clevis_luks_read_slot "$DEV" "$SLT")"; then
--    echo "Error reading metadata from LUKS device!" >&2
--    exit 1
--fi
--
- ### ----------------------------------------------------------------------
--
--DECODED="$(decode_luks_header "$OLD_LUKS_CODED")"
--
--if ! PIN="$(jose fmt -j- -g clevis -g pin -u- <<< "$DECODED")" || [ -z "$PIN" ]; then
--    echo "Pin wasn't found in LUKS metadata!" >&2
-+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
- 
--CFG="$(generate_cfg "$OLD_LUKS_CODED")"
--
--### ----------------------------------------------------------------------
-+PIN=$(echo "${pin_cfg}" | awk '{ print $2 }')
-+CFG=$(echo "${pin_cfg}" | awk '{ print $3 }' | tr -d "'")
- 
- echo "Regenerating with:"
- echo "PIN: $PIN"
-@@ -166,20 +84,101 @@ echo "CONFIG: $CFG"
- trap 'echo "Ignoring CONTROL-C!"' INT TERM
- 
- # Get the existing key.
--read -r -s -p "Enter existing LUKS password: " existing_key; echo
-+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 luksOpen --test-passphrase "${DEV}" <<< "${existing_key}"; then
-+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
- 
--if ! clevis luks unbind -d "${DEV}" -s "${SLT}" -f; then
--    echo "Error during unbind of rotated key from slot:$SLT in $DEV" >&2
-+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
- 
--if ! clevis luks bind -d "${DEV}" -s "${SLT}" "${PIN}" "${CFG}" -k - <<< "${existing_key}"; then
--    echo "Error during bind of new key from slot:$SLT in $DEV" >&2
-+# 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
- 
-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 <scorreia@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="${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 <scorreia@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="${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 248d2ea..4e0a6cb 100644
---- a/src/luks/tests/meson.build
-+++ b/src/luks/tests/meson.build
-@@ -35,6 +35,9 @@ else
-   warning('Will not run "clevis luks list" tests due to missing jq dependency')
- 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.
-@@ -45,3 +48,7 @@ if jq.found()
-   test('list-sss-tang-luks2', find_program('list-sss-tang-luks2'), env: env, timeout: 60)
- 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)
-+
-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 <scorreia@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="${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 <scorreia@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="${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 <scorreia@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="${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 <scorreia@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="${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 b/src/luks/tests/tests-common-functions
-index 7758876..1139f09 100644
---- a/src/luks/tests/tests-common-functions
-+++ b/src/luks/tests/tests-common-functions
-@@ -63,7 +63,7 @@ new_device() {
-         return 0
-     fi
- 
--    fallocate -l16M "${DEV}"
-+    fallocate -l64M "${DEV}"
-     local extra_options='--pbkdf pbkdf2 --pbkdf-force-iterations 1000'
-     cryptsetup luksFormat --type "${LUKS}" ${extra_options} --batch-mode --force-password "${DEV}" <<< "${DEFAULT_PASS}"
-     # Caching the just-formatted device for possible reuse.
-@@ -83,4 +83,29 @@ pin_cfg_equal() {
-          <(jq -S . < <(echo -n "${cfg2}"))
- }
- 
-+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 DEFAULT_PASS='just-some-test-password-here'
--- 
-2.18.2
-
diff --git a/SOURCES/Improve-error-message-when-bind-is-given-an-invalid-.patch b/SOURCES/Improve-error-message-when-bind-is-given-an-invalid-.patch
deleted file mode 100644
index e0c2af0..0000000
--- a/SOURCES/Improve-error-message-when-bind-is-given-an-invalid-.patch
+++ /dev/null
@@ -1,42 +0,0 @@
-From 02f17448e379c92745f8203f47e5de0725b1c1b6 Mon Sep 17 00:00:00 2001
-From: Sergio Correia <scorreia@redhat.com>
-Date: Fri, 18 Oct 2019 09:04:22 -0300
-Subject: [PATCH] Improve error message when bind is given an invalid PIN
-
----
- src/luks/clevis-luks-bind | 7 ++++++-
- 1 file changed, 6 insertions(+), 1 deletion(-)
-
-diff --git a/src/luks/clevis-luks-bind b/src/luks/clevis-luks-bind
-index 7aae2ea..1b5caf2 100755
---- a/src/luks/clevis-luks-bind
-+++ b/src/luks/clevis-luks-bind
-@@ -19,6 +19,8 @@
- # along with this program.  If not, see <http://www.gnu.org/licenses/>.
- #
- 
-+. clevis-luks-common-functions
-+
- SUMMARY="Binds a LUKS device using the specified policy"
- UUID=cb6e8904-81ff-40da-a84a-07ab9ab5715e
- 
-@@ -68,6 +70,9 @@ fi
- if ! PIN=${@:$((OPTIND++)):1} || [ -z "$PIN" ]; then
-     echo "Did not specify a pin!" >&2
-     usage
-+elif ! EXE=$(findexe clevis-encrypt-"${PIN}"); then
-+    echo "'$PIN' is not a valid pin!" >&2
-+    usage
- fi
- 
- if ! CFG=${@:$((OPTIND++)):1} || [ -z "$CFG" ]; then
-@@ -142,4 +147,4 @@ else
-         cryptsetup luksRemoveKey "$DEV" <<<"$key"
-         exit 1
-     fi
--fi
-\ No newline at end of file
-+fi
--- 
-2.21.0
-
diff --git a/SOURCES/Improve-tests-speed.patch b/SOURCES/Improve-tests-speed.patch
deleted file mode 100644
index 3993614..0000000
--- a/SOURCES/Improve-tests-speed.patch
+++ /dev/null
@@ -1,60 +0,0 @@
-From 874ee402645f9c3c40eaf5882a9cb92bc88b1a8f Mon Sep 17 00:00:00 2001
-From: Sergio Correia <scorreia@redhat.com>
-Date: Sun, 22 Dec 2019 16:46:19 -0500
-Subject: [PATCH] Improve tests speed Also run tests only as root, if they
- involve cryptsetup
-
----
- src/luks/tests/tests-common-functions | 16 +++++++++++++---
- 1 file changed, 13 insertions(+), 3 deletions(-)
-
-diff --git a/src/luks/tests/tests-common-functions b/src/luks/tests/tests-common-functions
-index b65a84a..7758876 100644
---- a/src/luks/tests/tests-common-functions
-+++ b/src/luks/tests/tests-common-functions
-@@ -25,6 +25,11 @@ luks2_supported() {
-     return 0
- }
- 
-+skip_test() {
-+    echo "${1}" >&2
-+    exit 77
-+}
-+
- # Creates a tang adv to be used in the test.
- create_tang_adv() {
-     local adv="${1}"
-@@ -39,14 +44,18 @@ create_tang_adv() {
-         | jose jws sig -I- -s "${TEMPLATE}" -k "${SIG}" -o "${adv}"
- }
- 
--
- # Creates a new LUKS1 or LUKS2 device to be used.
- new_device() {
-     local LUKS="${1}"
-     local DEV="${2}"
--
-     local DEV_CACHED="${TMP}/${LUKS}.cached"
- 
-+    # Some builders fail if the cryptsetup steps are not ran as root, so let's
-+    # skip the test now if not running as root.
-+    if [ $(id -u) != 0 ]; then
-+        skip_test "WARNING: You must be root to run this test; test skipped."
-+    fi
-+
-     # Let's reuse an existing device, if there is one.
-     if [ -f "${DEV_CACHED}" ]; then
-         echo "Reusing cached ${LUKS} device..."
-@@ -55,7 +64,8 @@ new_device() {
-     fi
- 
-     fallocate -l16M "${DEV}"
--    cryptsetup luksFormat --type "${LUKS}" --batch-mode --force-password "${DEV}" <<< "${DEFAULT_PASS}"
-+    local extra_options='--pbkdf pbkdf2 --pbkdf-force-iterations 1000'
-+    cryptsetup luksFormat --type "${LUKS}" ${extra_options} --batch-mode --force-password "${DEV}" <<< "${DEFAULT_PASS}"
-     # Caching the just-formatted device for possible reuse.
-     cp -f "${DEV}" "${DEV_CACHED}"
- }
--- 
-2.18.1
-
diff --git a/SOURCES/Install-cryptsetup-and-tpm2_pcrlist-in-the-initramfs.patch b/SOURCES/Install-cryptsetup-and-tpm2_pcrlist-in-the-initramfs.patch
deleted file mode 100644
index 28082b7..0000000
--- a/SOURCES/Install-cryptsetup-and-tpm2_pcrlist-in-the-initramfs.patch
+++ /dev/null
@@ -1,49 +0,0 @@
-From 34658590e45ab85f6008379d9433406a5c7fd914 Mon Sep 17 00:00:00 2001
-From: Javier Martinez Canillas <javierm@redhat.com>
-Date: Wed, 7 Nov 2018 15:12:17 +0100
-Subject: [PATCH 2/3] Install cryptsetup and tpm2_pcrlist in the initramfs
-
-The cryptsetup and tpm2_pcrlist are missing in the initramfs, this makes
-automatic LUKS unlocking fail with the following errors:
-
-dracut-initqueue[382]: /usr/libexec/clevis-luks-askpass: line 52: cryptsetup: command not found
-dracut-initqueue[382]: /usr/bin/clevis-decrypt-tpm2: line 40: tpm2_pcrlist: command not found
-
-Suggested-by: Federico Chiacchiaretta <federico.chia@gmail.com>
-
-Fixes: #74
----
- src/luks/systemd/dracut/module-setup.sh.in | 3 +++
- 1 file changed, 3 insertions(+)
-
-diff --git a/src/luks/systemd/dracut/module-setup.sh.in b/src/luks/systemd/dracut/module-setup.sh.in
-index 48aea5b3f29a..41e7d6c9b002 100755
---- a/src/luks/systemd/dracut/module-setup.sh.in
-+++ b/src/luks/systemd/dracut/module-setup.sh.in
-@@ -40,6 +40,7 @@ install() {
-         clevis-decrypt-sss \
-         @libexecdir@/clevis-luks-askpass \
-         clevis-decrypt \
-+        cryptsetup \
-         luksmeta \
-         clevis \
-         mktemp \
-@@ -49,6 +50,7 @@ install() {
- 
-     for cmd in clevis-decrypt-tpm2 \
- 	tpm2_createprimary \
-+	tpm2_pcrlist \
- 	tpm2_unseal \
- 	tpm2_load; do
- 
-@@ -60,6 +62,7 @@ install() {
-     if (($ret == 0)); then
- 	inst_multiple clevis-decrypt-tpm2 \
- 	    tpm2_createprimary \
-+	    tpm2_pcrlist \
- 	    tpm2_unseal \
- 	    tpm2_load
-     fi
--- 
-2.19.1
-
diff --git a/SOURCES/Use-one-clevis-luks-askpass-per-device.patch b/SOURCES/Use-one-clevis-luks-askpass-per-device.patch
deleted file mode 100644
index 87c657b..0000000
--- a/SOURCES/Use-one-clevis-luks-askpass-per-device.patch
+++ /dev/null
@@ -1,237 +0,0 @@
-From 523f1361c759d5af0952b0137d4dbd51be1e7b3d Mon Sep 17 00:00:00 2001
-From: Sergio Correia <scorreia@redhat.com>
-Date: Sun, 22 Dec 2019 17:01:09 -0500
-Subject: [PATCH] Use one clevis-luks-askpass per device
-
-This should improve the reliability of the boot unlocking, especially
-when unlocking multiple devices upon boot.
-
-It also greatly simplifies the configuration, as three is no need to
-enable any systemd units manually nor add _netdev to either fstab or
-crypttab.
----
- src/luks/clevis-luks-unlockers.7.adoc         | 16 +++----------
- src/luks/systemd/clevis-luks-askpass          |  7 +++++-
- src/luks/systemd/clevis-luks-askpass.path     | 10 --------
- .../systemd/clevis-luks-askpass.service.in    |  8 -------
- src/luks/systemd/clevis-luks-askpass@.path    | 12 ++++++++++
- .../systemd/clevis-luks-askpass@.service.in   |  9 +++++++
- src/luks/systemd/dracut/module-setup.sh.in    | 24 +++++++++++++++++++
- src/luks/systemd/meson.build                  |  8 +++----
- 8 files changed, 58 insertions(+), 36 deletions(-)
- delete mode 100644 src/luks/systemd/clevis-luks-askpass.path
- delete mode 100644 src/luks/systemd/clevis-luks-askpass.service.in
- create mode 100644 src/luks/systemd/clevis-luks-askpass@.path
- create mode 100644 src/luks/systemd/clevis-luks-askpass@.service.in
-
-diff --git a/src/luks/clevis-luks-unlockers.7.adoc b/src/luks/clevis-luks-unlockers.7.adoc
-index 161b73a..e8d47ba 100644
---- a/src/luks/clevis-luks-unlockers.7.adoc
-+++ b/src/luks/clevis-luks-unlockers.7.adoc
-@@ -26,7 +26,7 @@ You can unlock a LUKS volume manually using the following command:
- 
- For more information, see link:clevis-luks-unlock.1.adoc[*clevis-luks-unlock*(1)].
- 
--== EARLY BOOT UNLOCKING
-+== BOOT UNLOCKING
- 
- If Clevis integration does not already ship in your initramfs, you may need to
- rebuild your initramfs with this command:
-@@ -34,23 +34,13 @@ rebuild your initramfs with this command:
-     $ sudo dracut -f
- 
- Once Clevis is integrated into your initramfs, a simple reboot should unlock
--your root volume. Note, however, that early boot integration only works for the
--root volume. Non-root volumes should use the late boot unlocker.
-+your clevis-bound volumes. Root volumes will be unlocked in early-boot, while the
-+remaining volumes will be unlocked after dracut switch-root.
- 
- Dracut will bring up your network using DHCP by default. If you need to specify
- additional network parameters, such as static IP configuration, please consult
- the dracut documentation.
- 
--== LATE BOOT UNLOCKING
--
--You can enable late boot unlocking by executing the following command:
--
--    $ sudo systemctl enable clevis-luks-askpass.path
--
--After a reboot, Clevis will attempt to unlock all *_netdev* devices listed in
--*/etc/crypttab* when systemd prompts for their passwords. This implies that
--systemd support for *_netdev* is required.
--
- == DESKTOP UNLOCKING
- 
- When the udisks2 unlocker is installed, your GNOME desktop session should
-diff --git a/src/luks/systemd/clevis-luks-askpass b/src/luks/systemd/clevis-luks-askpass
-index b01d93a..feebb1a 100755
---- a/src/luks/systemd/clevis-luks-askpass
-+++ b/src/luks/systemd/clevis-luks-askpass
-@@ -24,15 +24,17 @@ UUID=cb6e8904-81ff-40da-a84a-07ab9ab5715e
- shopt -s nullglob
- 
- path=/run/systemd/ask-password
--while getopts ":lp:" o; do
-+while getopts ":lpu:" o; do
-     case "$o" in
-     l) loop=true;;
-     p) path=$OPTARG;;
-+    u) device_uuid=$OPTARG;;
-     esac
- done
- 
- while true; do
-     todo=0
-+    [ -n "${device_uuid}" ] && todo=1 && loop=true
- 
-     for question in $path/ask.*; do
-         metadata=false
-@@ -48,6 +50,8 @@ while true; do
-         done < "$question"
- 
-         [ -z "$d" -o -z "$s" ] && continue
-+        [[ -n "${device_uuid}" ]] && [[ "${d}" != *"${device_uuid}"* ]] \
-+            && continue
- 
-         if cryptsetup isLuks --type luks1 "$d"; then
-             # If the device is not initialized, sliently skip it.
-@@ -79,6 +83,7 @@ while true; do
-             done
-         fi
- 
-+        [ -n "${device_uuid}" ] && [ "${unlocked}" == true ] && todo=0 && break
-         [ $metadata == true ] || continue
-         [ $unlocked == true ] && continue
-         todo=$((todo + 1))
-diff --git a/src/luks/systemd/clevis-luks-askpass.path b/src/luks/systemd/clevis-luks-askpass.path
-deleted file mode 100644
-index a4d01ba..0000000
---- a/src/luks/systemd/clevis-luks-askpass.path
-+++ /dev/null
-@@ -1,10 +0,0 @@
--[Unit]
--Description=Clevis systemd-ask-password Watcher
--Before=remote-fs-pre.target
--Wants=remote-fs-pre.target
--
--[Path]
--PathChanged=/run/systemd/ask-password
--
--[Install]
--WantedBy=remote-fs.target
-diff --git a/src/luks/systemd/clevis-luks-askpass.service.in b/src/luks/systemd/clevis-luks-askpass.service.in
-deleted file mode 100644
-index 2c6bbed..0000000
---- a/src/luks/systemd/clevis-luks-askpass.service.in
-+++ /dev/null
-@@ -1,8 +0,0 @@
--[Unit]
--Description=Clevis LUKS systemd-ask-password Responder
--Requires=network-online.target
--After=network-online.target
--
--[Service]
--Type=oneshot
--ExecStart=@libexecdir@/clevis-luks-askpass -l
-diff --git a/src/luks/systemd/clevis-luks-askpass@.path b/src/luks/systemd/clevis-luks-askpass@.path
-new file mode 100644
-index 0000000..3f23665
---- /dev/null
-+++ b/src/luks/systemd/clevis-luks-askpass@.path
-@@ -0,0 +1,12 @@
-+[Unit]
-+Description=Clevis systemd-ask-password Watcher for %i
-+DefaultDependencies=no
-+Conflicts=shutdown.target
-+Before=basic.target shutdown.target
-+
-+[Path]
-+DirectoryNotEmpty=/run/systemd/ask-password
-+MakeDirectory=yes
-+
-+[Install]
-+WantedBy=basic.target
-diff --git a/src/luks/systemd/clevis-luks-askpass@.service.in b/src/luks/systemd/clevis-luks-askpass@.service.in
-new file mode 100644
-index 0000000..cd26eb2
---- /dev/null
-+++ b/src/luks/systemd/clevis-luks-askpass@.service.in
-@@ -0,0 +1,9 @@
-+[Unit]
-+Description=Clevis LUKS systemd-ask-password Responder for luks-%i
-+DefaultDependencies=no
-+Conflicts=shutdown.target
-+Before=shutdown.target
-+
-+[Service]
-+Type=oneshot
-+ExecStart=@libexecdir@/clevis-luks-askpass -u %i
-diff --git a/src/luks/systemd/dracut/module-setup.sh.in b/src/luks/systemd/dracut/module-setup.sh.in
-index 841f7a8..1877715 100755
---- a/src/luks/systemd/dracut/module-setup.sh.in
-+++ b/src/luks/systemd/dracut/module-setup.sh.in
-@@ -29,6 +29,29 @@ is_bound_to_tang() {
-     return 1
- }
- 
-+configure_passwd_watchers() {
-+    if ! command -v systemctl >/dev/null; then
-+        return 1
-+    fi
-+
-+    local proc_cmdline
-+    proc_cmdline=$(</proc/cmdline)
-+
-+    local luks_uuid
-+    local cfg
-+    for dev in $(lsblk -p -n -s -r \
-+                 | awk '$6 == "crypt" { getline; print $1 }' | sort -u); do
-+        luks_uuid=$(cryptsetup luksUUID "${dev}")
-+        [[ "${proc_cmdline}" == *"rd.luks.uuid=luks-${luks_uuid}"* ]] && continue
-+
-+        if cfg=$(clevis luks list -d "${dev}" 2>/dev/null); then
-+            local action=enable
-+            [ -z "${cfg}" ] && action=disable
-+            systemctl "${action}" "clevis-luks-askpass@${luks_uuid}.path" 2>/dev/null
-+        fi
-+    done
-+}
-+
- depends() {
-     local depends="crypt systemd"
-     if is_bound_to_tang; then
-@@ -84,6 +107,7 @@ install() {
- 	inst_libdir_file "libtss2-tcti-device.so*"
-     fi
- 
-+    configure_passwd_watchers
-     dracut_need_initqueue
- }
- 
-diff --git a/src/luks/systemd/meson.build b/src/luks/systemd/meson.build
-index 108e9d8..334e84c 100644
---- a/src/luks/systemd/meson.build
-+++ b/src/luks/systemd/meson.build
-@@ -6,14 +6,14 @@ if systemd.found()
-   unitdir = systemd.get_pkgconfig_variable('systemdsystemunitdir')
- 
-   configure_file(
--    input: 'clevis-luks-askpass.service.in',
--    output: 'clevis-luks-askpass.service',
-+    input: 'clevis-luks-askpass@.service.in',
-+    output: 'clevis-luks-askpass@.service',
-     install_dir: unitdir,
-     configuration: data,
-   )
- 
--  install_data('clevis-luks-askpass.path', install_dir: unitdir)
-+  install_data('clevis-luks-askpass@.path', install_dir: unitdir)
-   install_data('clevis-luks-askpass', install_dir: libexecdir)
- else
-   warning('Will not install systemd support due to missing dependencies!')
--endif
-\ No newline at end of file
-+endif
--- 
-2.18.1
-
diff --git a/SPECS/clevis.spec b/SPECS/clevis.spec
index 02a259b..63a02e4 100644
--- a/SPECS/clevis.spec
+++ b/SPECS/clevis.spec
@@ -1,27 +1,24 @@
 %global _hardened_build 1
 
 Name:           clevis
-Version:        11
-Release:        9%{?dist}
+Version:        13
+Release:        3%{?dist}
 Summary:        Automated decryption framework
 
 License:        GPLv3+
 URL:            https://github.com/latchset/%{name}
 Source0:        https://github.com/latchset/%{name}/releases/download/v%{version}/%{name}-%{version}.tar.xz
 
-Patch01: Delete-remaining-references-to-the-removed-http-pin.patch
-Patch02: Install-cryptsetup-and-tpm2_pcrlist-in-the-initramfs.patch
-Patch03: Add-device-TCTI-library-to-the-initramfs.patch
-Patch04: Check-key-derivation-key-is-available.patch
-Patch05: Adjust-pin-tang-test-to-account-for-newer-tang-witho.patch
-Patch06: Add-clevis-luks-report-regen.patch
-Patch07: Improve-error-message-when-bind-is-given-an-invalid-.patch
-Patch08: Add-support-for-listing-existing-PBD-policies-in-pla.patch
-Patch09: Add-the-option-to-extract-luks-passphrase-used-for-b.patch
-Patch10: Add-rd.neednet-1-to-cmdline-only-if-there-are-device.patch
-Patch11: Improve-tests-speed.patch
-Patch12: Use-one-clevis-luks-askpass-per-device.patch
-Patch13: Improve-clevis-luks-regen-no-unbind-in-every-case.patch
+Patch0001: 0001-Adjust-pin-tang-test-to-account-for-newer-tang-witho.patch
+Patch0002: 0002-Fix-clevis-luks-unlock-and-add-related-tests.patch
+Patch0003: 0003-Improve-error-message-when-bind-is-given-an-invalid-.patch
+Patch0004: 0004-Add-rd.neednet-1-to-cmdline-only-if-there-are-device.patch
+Patch0005: 0005-Add-the-option-to-extract-luks-passphrase-used-for-b.patch
+Patch0006: 0006-Add-clevis-luks-regen-command.patch
+Patch0007: 0007-Add-clevis-luks-report.patch
+Patch0008: 0008-Use-one-clevis-luks-askpass-per-device.patch
+Patch0009: 0009-Introduce-y-assume-yes-argument-to-clevis-luks-bind.patch
+Patch0010: 0010-Add-clevis-luks-edit-command.patch
 
 BuildRequires:  gcc
 BuildRequires:  meson
@@ -47,11 +44,14 @@ BuildRequires:  cracklib-dicts
 Buildrequires:  jq
 BuildRequires:  diffutils
 BuildRequires:  expect
+BuildRequires:  openssl
 
+Requires:       cracklib-dicts
 Requires:       tpm2-tools >= 3.0.0
 Requires:       coreutils
 Requires:       jose >= 8
 Requires:       curl
+Requires:       jq
 Requires(pre):  shadow-utils
 
 %description
@@ -62,17 +62,17 @@ occur automatically.
 The clevis package provides basic encryption/decryption policy support.
 Users can use this directly; but most commonly, it will be used as a
 building block for other packages. For example, see the clevis-luks
-and clevis-dracut packages for automatic root volume unlocking of LUKSv1
+and clevis-dracut packages for automatic root volume unlocking of LUKS
 volumes during early boot.
 
 %package luks
-Summary:        LUKSv1 integration for clevis
+Summary:        LUKS integration for clevis
 Requires:       %{name}%{?_isa} = %{version}-%{release}
 Requires:       cryptsetup
 Requires:       luksmeta >= 8
 
 %description luks
-LUKSv1 integration for clevis. This package allows you to bind a LUKSv1
+LUKS integration for clevis. This package allows you to bind a LUKS
 volume to a clevis unlocking policy. For automated unlocking, an unlocker
 will also be required. See, for example, clevis-dracut and clevis-udisks2.
 
@@ -95,7 +95,7 @@ Requires:       systemd%{?_isa} >= 236
 Requires:       nc
 
 %description systemd
-Automatically unlocks LUKSv1 _netdev block devices from /etc/crypttab.
+Automatically unlocks clevis-bound LUKS block devices during boot.
 
 %package dracut
 Summary:        Dracut integration for clevis
@@ -103,18 +103,18 @@ Requires:       %{name}-systemd%{?_isa} = %{version}-%{release}
 Requires:       dracut-network
 
 %description dracut
-Automatically unlocks LUKSv1 block devices in early boot.
+Automatically unlocks LUKS block devices in early boot.
 
 %package udisks2
 Summary:        UDisks2/Storaged integration for clevis
 Requires:       %{name}-luks%{?_isa} = %{version}-%{release}
 
 %description udisks2
-Automatically unlocks LUKSv1 block devices in desktop environments that
+Automatically unlocks LUKS block devices in desktop environments that
 use UDisks2 or storaged (like GNOME).
 
 %prep
-%autosetup -p1
+%autosetup -S git
 
 %build
 %meson -Duser=clevis -Dgroup=clevis
@@ -166,22 +166,24 @@ exit 0
 %{_mandir}/man1/%{name}-luks-unlock.1*
 %{_mandir}/man1/%{name}-luks-unbind.1*
 %{_mandir}/man1/%{name}-luks-bind.1*
+%{_mandir}/man1/%{name}-luks-list.1*
+%{_mandir}/man1/%{name}-luks-pass.1*
 %{_mandir}/man1/%{name}-luks-regen.1*
 %{_mandir}/man1/%{name}-luks-report.1*
-%{_mandir}/man1/%{name}-luks-list.1*
-%{_mandir}/man1/%{name}-luks-pass.1.*
+%{_mandir}/man1/%{name}-luks-edit.1*
 %{_bindir}/%{name}-luks-unlock
 %{_bindir}/%{name}-luks-unbind
 %{_bindir}/%{name}-luks-bind
 %{_bindir}/%{name}-luks-common-functions
+%{_bindir}/%{name}-luks-list
+%{_bindir}/%{name}-luks-pass
 %{_bindir}/%{name}-luks-regen
 %{_bindir}/%{name}-luks-report
 %{_bindir}/%{name}-luks-report-compare
 %{_bindir}/%{name}-luks-report-decode
 %{_bindir}/%{name}-luks-report-sss
 %{_bindir}/%{name}-luks-report-tang
-%{_bindir}/%{name}-luks-list
-%{_bindir}/%{name}-luks-pass
+%{_bindir}/%{name}-luks-edit
 
 %files systemd
 %{_libexecdir}/%{name}-luks-askpass
@@ -190,13 +192,33 @@ exit 0
 
 %files dracut
 %{_prefix}/lib/dracut/modules.d/60%{name}
+%{_prefix}/lib/dracut/modules.d/60%{name}-pin-sss
+%{_prefix}/lib/dracut/modules.d/60%{name}-pin-tang
+%{_prefix}/lib/dracut/modules.d/60%{name}-pin-tpm2
 
 %files udisks2
 %{_sysconfdir}/xdg/autostart/%{name}-luks-udisks2.desktop
 %attr(4755, root, root) %{_libexecdir}/%{name}-luks-udisks2
 
 %changelog
-* Wed Feb 02 2020 Sergio Correia <scorreia@redhat.com> - 11-9
+* Wed May 20 2020 Sergio Correia <scorreia@redhat.com> - 13-3
+- Add clevis luks edit command
+  Resolves: rhbz#1436735
+
+* Mon May 18 2020 Sergio Correia <scorreia@redhat.com> - 13-2
+- Introduce -y (assume yes) argument to clevis luks bind
+  Resolves: rhbz#1819767
+
+* Sun May 10 2020 Sergio Correia <scorreia@redhat.com> - 13-1
+- Update to new upstream release, v13
+  Resolves: rhbz#1827225
+  Resolves: rhbz#1827665
+  Resolves: rhbz#1801556
+  Resolves: rhbz#1784448
+  Resolves: rhbz#1826917
+  Resolves: rhbz#1812014
+
+* Sun Feb 02 2020 Sergio Correia <scorreia@redhat.com> - 11-9
 - Improve clevis luks regen not to unbind+bind in every case
   Resolves: rhbz#1795675