import clevis-11-9.el8

This commit is contained in:
CentOS Sources 2020-04-28 05:34:20 -04:00 committed by Andrew Lukoshko
parent 0157707ddb
commit 1aa8576cd2
10 changed files with 4038 additions and 7 deletions

View File

@ -0,0 +1,858 @@
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

View File

@ -0,0 +1,57 @@
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

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,364 @@
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

View File

@ -0,0 +1,77 @@
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

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,42 @@
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

View File

@ -0,0 +1,60 @@
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

View File

@ -0,0 +1,237 @@
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

View File

@ -2,17 +2,26 @@
Name: clevis Name: clevis
Version: 11 Version: 11
Release: 2%{?dist} Release: 9%{?dist}
Summary: Automated decryption framework Summary: Automated decryption framework
License: GPLv3+ License: GPLv3+
URL: https://github.com/latchset/%{name} URL: https://github.com/latchset/%{name}
Source0: https://github.com/latchset/%{name}/releases/download/v%{version}/%{name}-%{version}.tar.xz Source0: https://github.com/latchset/%{name}/releases/download/v%{version}/%{name}-%{version}.tar.xz
Patch0: Delete-remaining-references-to-the-removed-http-pin.patch Patch01: Delete-remaining-references-to-the-removed-http-pin.patch
Patch1: Install-cryptsetup-and-tpm2_pcrlist-in-the-initramfs.patch Patch02: Install-cryptsetup-and-tpm2_pcrlist-in-the-initramfs.patch
Patch2: Add-device-TCTI-library-to-the-initramfs.patch Patch03: Add-device-TCTI-library-to-the-initramfs.patch
Patch3: Check-key-derivation-key-is-available.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
BuildRequires: gcc BuildRequires: gcc
BuildRequires: meson BuildRequires: meson
@ -33,6 +42,11 @@ BuildRequires: systemd
BuildRequires: dracut BuildRequires: dracut
BuildRequires: tang >= 6 BuildRequires: tang >= 6
BuildRequires: curl BuildRequires: curl
BuildRequires: luksmeta
BuildRequires: cracklib-dicts
Buildrequires: jq
BuildRequires: diffutils
BuildRequires: expect
Requires: tpm2-tools >= 3.0.0 Requires: tpm2-tools >= 3.0.0
Requires: coreutils Requires: coreutils
@ -121,6 +135,15 @@ getent passwd %{name} >/dev/null || \
-c "Clevis Decryption Framework unprivileged user" %{name} -c "Clevis Decryption Framework unprivileged user" %{name}
exit 0 exit 0
%pre systemd
if [ $1 -ge 0 ]; then
# clevis-systemd < 11-8 shipped with clevis-luks-askpass.path unit.
# Make sure it's gone.
[ -e /usr/lib/systemd/system/clevis-luks-askpass.path ] && \
systemctl disable clevis-luks-askpass.path
fi
exit 0
%files %files
%license COPYING %license COPYING
%{_datadir}/bash-completion/ %{_datadir}/bash-completion/
@ -143,14 +166,27 @@ exit 0
%{_mandir}/man1/%{name}-luks-unlock.1* %{_mandir}/man1/%{name}-luks-unlock.1*
%{_mandir}/man1/%{name}-luks-unbind.1* %{_mandir}/man1/%{name}-luks-unbind.1*
%{_mandir}/man1/%{name}-luks-bind.1* %{_mandir}/man1/%{name}-luks-bind.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.*
%{_bindir}/%{name}-luks-unlock %{_bindir}/%{name}-luks-unlock
%{_bindir}/%{name}-luks-unbind %{_bindir}/%{name}-luks-unbind
%{_bindir}/%{name}-luks-bind %{_bindir}/%{name}-luks-bind
%{_bindir}/%{name}-luks-common-functions
%{_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
%files systemd %files systemd
%{_libexecdir}/%{name}-luks-askpass %{_libexecdir}/%{name}-luks-askpass
%{_unitdir}/%{name}-luks-askpass.path %{_unitdir}/%{name}-luks-askpass@.path
%{_unitdir}/%{name}-luks-askpass.service %{_unitdir}/%{name}-luks-askpass@.service
%files dracut %files dracut
%{_prefix}/lib/dracut/modules.d/60%{name} %{_prefix}/lib/dracut/modules.d/60%{name}
@ -160,6 +196,35 @@ exit 0
%attr(4755, root, root) %{_libexecdir}/%{name}-luks-udisks2 %attr(4755, root, root) %{_libexecdir}/%{name}-luks-udisks2
%changelog %changelog
* Wed Feb 02 2020 Sergio Correia <scorreia@redhat.com> - 11-9
- Improve clevis luks regen not to unbind+bind in every case
Resolves: rhbz#1795675
* Mon Jan 13 2020 Sergio Correia <scorreia@redhat.com> - 11-8
- Use one clevis-luks-askpass per device
Resolves: rhbz#1784524
* Sat Nov 30 2019 Sergio Correia <scorreia@redhat.com> - 11-7
- Add rd.neednet=1 to cmdline only if there are devices bound to tang
Resolves: rhbz#1762028
* Sat Nov 30 2019 Sergio Correia <scorreia@redhat.com> - 11-6
- Add option to extract luks passphrase used for binding
Resolves: rhbz#1436780
* Thu Nov 28 2019 Sergio Correia <scorreia@redhat.com> - 11-5
- Add support for listing existing PBD policies in place
Resolves: rhbz#1766526
* Fri Oct 18 2019 Sergio Correia <scorreia@redhat.com> - 11-4
- Improve error message when bind is given an invalid PIN
Resolves: rhbz#1543380
* Wed Oct 16 2019 Sergio Correia <scorreia@redhat.com> - 11-3
- Add clevis luks report and regen
Resolves: rhbz#1564566
Resolves: rhbz#1564559
* Fri Jan 04 2019 Daniel Kopecek <dkopecek@redhat.com> - 11-2 * Fri Jan 04 2019 Daniel Kopecek <dkopecek@redhat.com> - 11-2
- Check that key derivation key is available - Check that key derivation key is available
- Delete remaining references to the removed http pin - Delete remaining references to the removed http pin