Blame SOURCES/0005-Add-the-option-to-extract-luks-passphrase-used-for-b.patch

3700a9
From e3641a7193adac1cea525c093f39679c2cfa22c9 Mon Sep 17 00:00:00 2001
ef20f4
From: Sergio Correia <scorreia@redhat.com>
3700a9
Date: Wed, 13 May 2020 23:53:38 -0300
3700a9
Subject: [PATCH 5/8] Add the option to extract luks passphrase used for
3700a9
 binding
ef20f4
ef20f4
Usage:
ef20f4
ef20f4
clevis luks pass -d /dev/sda1 -s 1
ef20f4
<passphrase here>
ef20f4
---
ef20f4
 src/luks/clevis-luks-pass        | 69 +++++++++++++++++++++++++++++
ef20f4
 src/luks/clevis-luks-pass.1.adoc | 43 ++++++++++++++++++
ef20f4
 src/luks/meson.build             |  3 ++
ef20f4
 src/luks/tests/meson.build       | 11 +++++
ef20f4
 src/luks/tests/pass-tang-luks1   | 75 ++++++++++++++++++++++++++++++++
ef20f4
 src/luks/tests/pass-tang-luks2   | 75 ++++++++++++++++++++++++++++++++
ef20f4
 6 files changed, 276 insertions(+)
ef20f4
 create mode 100755 src/luks/clevis-luks-pass
ef20f4
 create mode 100644 src/luks/clevis-luks-pass.1.adoc
ef20f4
 create mode 100755 src/luks/tests/pass-tang-luks1
ef20f4
 create mode 100755 src/luks/tests/pass-tang-luks2
ef20f4
ef20f4
diff --git a/src/luks/clevis-luks-pass b/src/luks/clevis-luks-pass
ef20f4
new file mode 100755
ef20f4
index 0000000..1ce8c4c
ef20f4
--- /dev/null
ef20f4
+++ b/src/luks/clevis-luks-pass
ef20f4
@@ -0,0 +1,69 @@
ef20f4
+#!/bin/bash -e
ef20f4
+# vim: set tabstop=8 shiftwidth=4 softtabstop=4 expandtab smarttab colorcolumn=80:
ef20f4
+#
ef20f4
+# Copyright (c) 2019 Red Hat, Inc.
ef20f4
+# Author: Sergio Correia <scorreia@redhat.com> - LUKS2 support.
ef20f4
+#
ef20f4
+# This program is free software: you can redistribute it and/or modify
ef20f4
+# it under the terms of the GNU General Public License as published by
ef20f4
+# the Free Software Foundation, either version 3 of the License, or
ef20f4
+# (at your option) any later version.
ef20f4
+#
ef20f4
+# This program is distributed in the hope that it will be useful,
ef20f4
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
ef20f4
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
ef20f4
+# GNU General Public License for more details.
ef20f4
+#
ef20f4
+# You should have received a copy of the GNU General Public License
ef20f4
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
ef20f4
+#
ef20f4
+
ef20f4
+. clevis-luks-common-functions
ef20f4
+
ef20f4
+SUMMARY="Returns the LUKS passphrase used for binding a particular slot."
ef20f4
+
ef20f4
+function usage() {
ef20f4
+    echo >&2
ef20f4
+    echo "Usage: clevis luks pass -d DEV -s SLT" >&2
ef20f4
+    echo >&2
ef20f4
+    echo "$SUMMARY": >&2
ef20f4
+    echo >&2
ef20f4
+    echo "  -d DEV  The LUKS device to extract the LUKS passphrase used for binding" >&2
ef20f4
+    echo >&2
ef20f4
+    echo "  -s SLOT The slot number to extract the LUKS passphrase" >&2
ef20f4
+    echo >&2
ef20f4
+    exit 1
ef20f4
+}
ef20f4
+
ef20f4
+if [ ${#} -eq 1 ] && [ "${1}" = "--summary" ]; then
ef20f4
+    echo "${SUMMARY}"
ef20f4
+    exit 0
ef20f4
+fi
ef20f4
+
ef20f4
+while getopts ":d:s:" o; do
ef20f4
+    case "$o" in
ef20f4
+    d) DEV=${OPTARG};;
ef20f4
+    s) SLT=${OPTARG};;
ef20f4
+    *) usage;;
ef20f4
+    esac
ef20f4
+done
ef20f4
+
ef20f4
+if [ -z "${DEV}" ]; then
ef20f4
+    echo "Did not specify a device!" >&2
ef20f4
+    usage
ef20f4
+fi
ef20f4
+
ef20f4
+if [ -z "${SLT}" ]; then
ef20f4
+    echo "Did not specify a slot!" >&2
ef20f4
+    usage
ef20f4
+fi
ef20f4
+
ef20f4
+if ! jwe=$(clevis_luks_read_slot "${DEV}" "${SLT}" 2>/dev/null); then
ef20f4
+    echo "It was not possible to read slot ${SLT} from ${DEV}!" >&2
ef20f4
+    exit 1
ef20f4
+fi
ef20f4
+
ef20f4
+if ! clevis decrypt < <(echo -n "${jwe}"); then
ef20f4
+    echo "It was not possible to decrypt the passphrase associated to slot ${SLT} in {DEV}!" >&2
ef20f4
+    exit 1
ef20f4
+fi
ef20f4
diff --git a/src/luks/clevis-luks-pass.1.adoc b/src/luks/clevis-luks-pass.1.adoc
ef20f4
new file mode 100644
ef20f4
index 0000000..fa9526a
ef20f4
--- /dev/null
ef20f4
+++ b/src/luks/clevis-luks-pass.1.adoc
ef20f4
@@ -0,0 +1,43 @@
ef20f4
+CLEVIS-LUKS-PASS(1)
ef20f4
+===================
ef20f4
+:doctype: manpage
ef20f4
+
ef20f4
+
ef20f4
+== NAME
ef20f4
+
ef20f4
+clevis-luks-pass - Extracts the passphrase used for binding a particular slot in a LUKS device
ef20f4
+
ef20f4
+== SYNOPSIS
ef20f4
+
ef20f4
+*clevis luks pass* -d DEV -s SLT
ef20f4
+
ef20f4
+== OVERVIEW
ef20f4
+
ef20f4
+The *clevis luks pass* command extracts the passphrase used for binding a particular slot in a LUKS device.
ef20f4
+For example:
ef20f4
+
ef20f4
+    clevis luks pass -d /dev/sda1 -s 1
ef20f4
+
ef20f4
+== OPTIONS
ef20f4
+
ef20f4
+* *-d* _DEV_ :
ef20f4
+  The LUKS device on which to extract a passphrase from
ef20f4
+
ef20f4
+* *-s* _SLT_ :
ef20f4
+  The slot to use for extracting the passphrase
ef20f4
+
ef20f4
+== EXAMPLE
ef20f4
+
ef20f4
+    clevis luks pass -d /dev/sda1 -s 1
ef20f4
+    <passphrase here>
ef20f4
+
ef20f4
+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
ef20f4
+file together with cryptsetup. For instance:
ef20f4
+
ef20f4
+    clevis luks pass -d /dev/sda1 -s 1 > slot1-passphrase
ef20f4
+
ef20f4
+And the file slot1-passphrase will contain the passphrase associated with slot #1 in /dev/sda1.
ef20f4
+
ef20f4
+== SEE ALSO
ef20f4
+
ef20f4
+link:clevis-luks-unlock.1.adoc[*clevis-luks-unlock*(1)],
ef20f4
diff --git a/src/luks/meson.build b/src/luks/meson.build
3700a9
index 0d24f8d..fda2ca8 100644
ef20f4
--- a/src/luks/meson.build
ef20f4
+++ b/src/luks/meson.build
3700a9
@@ -41,6 +41,9 @@ if libcryptsetup.found() and luksmeta.found() and pwmake.found()
ef20f4
 
3700a9
   bins += join_paths(meson.current_source_dir(), 'clevis-luks-unlock')
3700a9
   mans += join_paths(meson.current_source_dir(), 'clevis-luks-unlock.1')
3700a9
+
ef20f4
+  bins += join_paths(meson.current_source_dir(), 'clevis-luks-pass')
ef20f4
+  mans += join_paths(meson.current_source_dir(), 'clevis-luks-pass.1')
3700a9
 else
3700a9
   warning('Will not install LUKS support due to missing dependencies!')
3700a9
 endif
ef20f4
diff --git a/src/luks/tests/meson.build b/src/luks/tests/meson.build
3700a9
index 9a16b42..4757c4b 100644
ef20f4
--- a/src/luks/tests/meson.build
ef20f4
+++ b/src/luks/tests/meson.build
ef20f4
@@ -1,3 +1,9 @@
ef20f4
+actv = find_program(
ef20f4
+  'systemd-socket-activate',
ef20f4
+  'systemd-activate',
ef20f4
+  required: false
ef20f4
+)
ef20f4
+
ef20f4
 # We use jq for comparing the pin config in the clevis luks list tests.
ef20f4
 jq = find_program('jq', required: false)
ef20f4
 
3700a9
@@ -45,8 +51,11 @@ env.prepend('PATH',
ef20f4
   join_paths(meson.build_root(), 'src', 'pins', 'sss'),
ef20f4
   join_paths(meson.build_root(), 'src', 'pins', 'tang'),
ef20f4
   join_paths(meson.build_root(), 'src', 'pins', 'tpm2'),
ef20f4
+  libexecdir,
ef20f4
+  '/usr/libexec',
ef20f4
   separator: ':'
ef20f4
 )
ef20f4
+env.set('SD_ACTIVATE', actv.path())
ef20f4
 
3700a9
 has_tang = false
3700a9
 if actv.found() and kgen.found() and tang.found()
3700a9
@@ -77,6 +86,7 @@ endif
3700a9
 if has_tang
3700a9
   test('unlock-tang-luks1', find_program('unlock-tang-luks1'), env: env, timeout: 90)
ef20f4
 endif
ef20f4
+test('pass-tang-luks1', find_program('pass-tang-luks1'), env: env)
ef20f4
 
ef20f4
 # LUKS2 tests go here, and they get included if we get support for it, based
ef20f4
 # on the cryptsetup version.
3700a9
@@ -96,4 +106,5 @@ if luksmeta_data.get('OLD_CRYPTSETUP') == '0'
3700a9
   if has_tang
3700a9
     test('unlock-tang-luks2', find_program('unlock-tang-luks2'), env: env, timeout: 120)
3700a9
   endif
3700a9
+  test('pass-tang-luks2', find_program('pass-tang-luks2'), env: env, timeout: 60)
ef20f4
 endif
ef20f4
diff --git a/src/luks/tests/pass-tang-luks1 b/src/luks/tests/pass-tang-luks1
ef20f4
new file mode 100755
ef20f4
index 0000000..05cdb3e
ef20f4
--- /dev/null
ef20f4
+++ b/src/luks/tests/pass-tang-luks1
ef20f4
@@ -0,0 +1,75 @@
ef20f4
+#!/bin/bash -x
ef20f4
+# vim: set tabstop=8 shiftwidth=4 softtabstop=4 expandtab smarttab colorcolumn=80:
ef20f4
+#
ef20f4
+# Copyright (c) 2019 Red Hat, Inc.
ef20f4
+# Author: Sergio Correia <scorreia@redhat.com>
ef20f4
+#
ef20f4
+# This program is free software: you can redistribute it and/or modify
ef20f4
+# it under the terms of the GNU General Public License as published by
ef20f4
+# the Free Software Foundation, either version 3 of the License, or
ef20f4
+# (at your option) any later version.
ef20f4
+#
ef20f4
+# This program is distributed in the hope that it will be useful,
ef20f4
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
ef20f4
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
ef20f4
+# GNU General Public License for more details.
ef20f4
+#
ef20f4
+# You should have received a copy of the GNU General Public License
ef20f4
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
ef20f4
+#
ef20f4
+
ef20f4
+TEST="${0}"
ef20f4
+. tests-common-functions
ef20f4
+
ef20f4
+function on_exit() {
ef20f4
+    if [ "$PID" ]; then kill $PID; wait $PID || true; fi
ef20f4
+    [ -d "$TMP" ] && rm -rf $TMP
ef20f4
+}
ef20f4
+
ef20f4
+trap 'on_exit' EXIT
ef20f4
+trap 'exit' ERR
ef20f4
+
ef20f4
+export TMP=$(mktemp -d)
ef20f4
+mkdir -p "${TMP}/db"
ef20f4
+
ef20f4
+# Generate the server keys
ef20f4
+KEYS="$TMP/db"
ef20f4
+tangd-keygen $TMP/db sig exc
ef20f4
+if which tangd-update; then
ef20f4
+    mkdir -p "${TMP}/cache"
ef20f4
+    tangd-update "${TMP}/db" "${TMP}/cache"
ef20f4
+    KEYS="${TMP}/cache"
ef20f4
+fi
ef20f4
+
ef20f4
+# Start the server.
ef20f4
+port=$(shuf -i 1024-65536 -n 1)
ef20f4
+"${SD_ACTIVATE}" --inetd -l 127.0.0.1:"${port}" -a tangd "${KEYS}" &
ef20f4
+export PID=$!
ef20f4
+sleep 0.25
ef20f4
+
ef20f4
+url="http://localhost:${port}"
ef20f4
+adv="${TMP}/adv"
ef20f4
+curl "${url}/adv" -o "${adv}"
ef20f4
+
ef20f4
+cfg=$(printf '{"url":"%s","adv":"%s"}' "$url" "$adv")
ef20f4
+
ef20f4
+# LUKS1.
ef20f4
+DEV="${TMP}/luks1-device"
ef20f4
+new_device "luks1" "${DEV}"
ef20f4
+
ef20f4
+if ! clevis luks bind -f -d "${DEV}" tang "${cfg}" <<< "${DEFAULT_PASS}"; then
ef20f4
+    error "${TEST}: Bind should have succeeded."
ef20f4
+fi
ef20f4
+
ef20f4
+#Now let's test the passphrase.
ef20f4
+SLT=1
ef20f4
+PASS=$(clevis luks pass -d "${DEV}" -s "${SLT}")
ef20f4
+echo $PASS >&2
ef20f4
+if ! cryptsetup luksOpen --test-passphrase ""${DEV} \
ef20f4
+        --key-file <(clevis luks pass -d "${DEV}" -s "${SLT}"); then
ef20f4
+    error "Passphrase obtained from clevis luks pass failed."
ef20f4
+fi
ef20f4
+
ef20f4
+kill -9 "${PID}"
ef20f4
+! wait "${PID}"
ef20f4
+unset PID
ef20f4
diff --git a/src/luks/tests/pass-tang-luks2 b/src/luks/tests/pass-tang-luks2
ef20f4
new file mode 100755
ef20f4
index 0000000..9123aa0
ef20f4
--- /dev/null
ef20f4
+++ b/src/luks/tests/pass-tang-luks2
ef20f4
@@ -0,0 +1,75 @@
ef20f4
+#!/bin/bash -x
ef20f4
+# vim: set tabstop=8 shiftwidth=4 softtabstop=4 expandtab smarttab colorcolumn=80:
ef20f4
+#
ef20f4
+# Copyright (c) 2019 Red Hat, Inc.
ef20f4
+# Author: Sergio Correia <scorreia@redhat.com>
ef20f4
+#
ef20f4
+# This program is free software: you can redistribute it and/or modify
ef20f4
+# it under the terms of the GNU General Public License as published by
ef20f4
+# the Free Software Foundation, either version 3 of the License, or
ef20f4
+# (at your option) any later version.
ef20f4
+#
ef20f4
+# This program is distributed in the hope that it will be useful,
ef20f4
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
ef20f4
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
ef20f4
+# GNU General Public License for more details.
ef20f4
+#
ef20f4
+# You should have received a copy of the GNU General Public License
ef20f4
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
ef20f4
+#
ef20f4
+
ef20f4
+TEST="${0}"
ef20f4
+. tests-common-functions
ef20f4
+
ef20f4
+function on_exit() {
ef20f4
+    if [ "$PID" ]; then kill $PID; wait $PID || true; fi
ef20f4
+    [ -d "$TMP" ] && rm -rf $TMP
ef20f4
+}
ef20f4
+
ef20f4
+trap 'on_exit' EXIT
ef20f4
+trap 'exit' ERR
ef20f4
+
ef20f4
+export TMP=$(mktemp -d)
ef20f4
+mkdir -p "${TMP}/db"
ef20f4
+
ef20f4
+# Generate the server keys
ef20f4
+KEYS="$TMP/db"
ef20f4
+tangd-keygen $TMP/db sig exc
ef20f4
+if which tangd-update; then
ef20f4
+    mkdir -p "${TMP}/cache"
ef20f4
+    tangd-update "${TMP}/db" "${TMP}/cache"
ef20f4
+    KEYS="${TMP}/cache"
ef20f4
+fi
ef20f4
+
ef20f4
+# Start the server.
ef20f4
+port=$(shuf -i 1024-65536 -n 1)
ef20f4
+"${SD_ACTIVATE}" --inetd -l 127.0.0.1:"${port}" -a tangd "${KEYS}" &
ef20f4
+export PID=$!
ef20f4
+sleep 0.25
ef20f4
+
ef20f4
+url="http://localhost:${port}"
ef20f4
+adv="${TMP}/adv"
ef20f4
+curl "${url}/adv" -o "${adv}"
ef20f4
+
ef20f4
+cfg=$(printf '{"url":"%s","adv":"%s"}' "$url" "$adv")
ef20f4
+
ef20f4
+# LUKS2.
ef20f4
+DEV="${TMP}/luks2-device"
ef20f4
+new_device "luks2" "${DEV}"
ef20f4
+
ef20f4
+if ! clevis luks bind -f -d "${DEV}" tang "${cfg}" <<< "${DEFAULT_PASS}"; then
ef20f4
+    error "${TEST}: Bind should have succeeded."
ef20f4
+fi
ef20f4
+
ef20f4
+#Now let's test the passphrase.
ef20f4
+SLT=1
ef20f4
+PASS=$(clevis luks pass -d "${DEV}" -s "${SLT}")
ef20f4
+echo $PASS >&2
ef20f4
+if ! cryptsetup luksOpen --test-passphrase ""${DEV} \
ef20f4
+        --key-file <(clevis luks pass -d "${DEV}" -s "${SLT}"); then
ef20f4
+    error "Passphrase obtained from clevis luks pass failed."
ef20f4
+fi
ef20f4
+
ef20f4
+kill -9 "${PID}"
ef20f4
+! wait "${PID}"
ef20f4
+unset PID
ef20f4
-- 
3700a9
2.18.4
ef20f4