External token id parameter

This change introduces new parameter "-e", that
allows specifying an existing token ID to avoid
having to provide an existing passphrase and
use an already configured LUKS2 token ID to read it

Signed-off-by: Sergio Arroutbi <sarroutb@redhat.com>
This commit is contained in:
Sergio Arroutbi 2022-12-09 11:40:09 +01:00
parent 2efddf72e8
commit 594feccd06
3 changed files with 361 additions and 0 deletions

View File

@ -0,0 +1,357 @@
--- clevis-18.ori/src/luks/clevis-luks-bind 2021-04-15 13:00:19.965065700 +0200
+++ clevis-18.new/src/luks/clevis-luks-bind 2022-12-01 12:16:36.564185792 +0100
@@ -25,7 +25,7 @@
usage() {
exec >&2
echo
- echo "Usage: clevis luks bind [-y] [-f] [-s SLT] [-k KEY] [-t TOKEN_ID] -d DEV PIN CFG"
+ echo "Usage: clevis luks bind [-y] [-f] [-s SLT] [-k KEY] [-t TOKEN_ID] [-e EXISTING_TOKEN_ID] -d DEV PIN CFG"
echo
echo "$SUMMARY":
echo
@@ -42,6 +42,8 @@
echo " -k KEY Non-interactively read LUKS password from KEY file"
echo " -k - Non-interactively read LUKS password from standard input"
echo
+ echo " -e E_TKN_ID Existing LUKS token ID for existing passphrase; only available for LUKS2"
+ echo
exit 2
}
@@ -52,13 +54,14 @@
FRC=
YES=
-while getopts ":hfyd:s:k:t:" o; do
+while getopts ":hfyd:s:k:t:e:" o; do
case "$o" in
f) FRC='-f';;
d) DEV="$OPTARG";;
s) SLT="$OPTARG";;
k) KEY="$OPTARG";;
t) TOKEN_ID="$OPTARG";;
+ e) EXISTING_TOKEN_ID="$OPTARG";;
y) FRC='-f'
YES='-y';;
*) usage;;
@@ -99,11 +102,20 @@
exit 1
fi
+if [ -n "${EXISTING_TOKEN_ID}" ] && ! clevis_luks_luks2_existing_token_id_supported; then
+ echo "Existing token ID not supported in this cryptsetup version" >&2
+ exit 1
+fi
+
# Get the existing passphrase/keyfile.
existing_key=
keyfile=
case "${KEY}" in
-"") IFS= read -r -s -p "Enter existing LUKS password: " existing_key; echo >&2;;
+ "")
+ if [ -z "${EXISTING_TOKEN_ID}" ] ; then
+ IFS= read -r -s -p "Enter existing LUKS password: " existing_key; echo >&2
+ fi
+ ;;
-) IFS= read -r -s -p "" existing_key ||:
if [ "${luks_type}" = "luks1" ] && ! luksmeta test -d "${DEV}" \
&& [ -z "${FRC}" ]; then
@@ -119,6 +131,13 @@
;;
esac
+# Check if existing token id for keyring read is provided
+# If so, keyfile is not allowed
+if [ -n "${EXISTING_TOKEN_ID}" ] && [ -n "${keyfile}" ] ; then
+ echo "Cannot specify kernel keyring description together with key file" >&2
+ exit 1
+fi
+
# If necessary, initialize the LUKS volume.
if [ "${luks_type}" = "luks1" ] && ! luksmeta test -d "${DEV}"; then
luksmeta init -d "${DEV}" ${FRC}
@@ -127,7 +146,7 @@
if ! clevis_luks_do_bind "${DEV}" "${SLT}" "${TOKEN_ID}" \
"${PIN}" "${CFG}" \
"${YES}" "" \
- "${existing_key}" "${keyfile}"; then
+ "${existing_key}" "${keyfile}" "${EXISTING_TOKEN_ID}"; then
echo "Error adding new binding to ${DEV}" >&2
exit 1
fi
--- clevis-18.ori/src/luks/clevis-luks-bind.1.adoc 2021-04-15 13:00:19.965065700 +0200
+++ clevis-18.new/src/luks/clevis-luks-bind.1.adoc 2022-12-01 12:17:23.877527175 +0100
@@ -9,7 +9,7 @@
== SYNOPSIS
-*clevis luks bind* [-f] [-y] -d DEV [-t TKN_ID] [-s SLT] [-k KEY] PIN CFG
+*clevis luks bind* [-f] [-y] -d DEV [-t TKN_ID] [-s SLT] [-k KEY] [-e EXISTING_TOKEN_ID] PIN CFG
== OVERVIEW
@@ -54,6 +54,12 @@
* *-k* - :
Non-interactively read LUKS password from standard input
+* *-e* _E_TKN_ID_ :
+ LUKS token ID for existing passphrase; only available for LUKS2.
+ This parameter allows providing a configured token ID in LUKS2
+ containing the existing passphrase for this device, so that
+ existing passphrase is not prompted by clevis
+
== CAVEATS
This command does not change the LUKS master key. This implies that if you
--- clevis-18.ori/src/luks/clevis-luks-common-functions.in 2021-04-15 13:00:19.965065700 +0200
+++ clevis-18.new/src/luks/clevis-luks-common-functions.in 2022-12-01 12:22:36.600783564 +0100
@@ -292,9 +292,10 @@
local KEY="${2:-}"
local KEYFILE="${3:-}"
local SLT="${4:-}"
+ local EXISTING_TOKEN_ID="${5:-}"
[ -z "${DEV}" ] && return 1
- [ -z "${KEYFILE}" ] && [ -z "${KEY}" ] && return 1
+ [ -z "${EXISTING_TOKEN_ID}" ] && [ -z "${KEYFILE}" ] && [ -z "${KEY}" ] && return 1
local extra_args
extra_args="$([ -n "${SLT}" ] && printf -- '--key-slot %s' "${SLT}")"
@@ -303,6 +304,11 @@
${extra_args}
return
fi
+ if [ -n "${EXISTING_TOKEN_ID}" ]; then
+ cryptsetup open --test-passphrase "${DEV}" --token-id "${EXISTING_TOKEN_ID}" \
+ ${extra_args}
+ return
+ fi
printf '%s' "${KEY}" | cryptsetup open --test-passphrase "${DEV}" \
${extra_args}
@@ -734,10 +740,11 @@
local NEWKEY="${3}"
local KEY="${4}"
local KEYFILE="${5:-}"
+ local EXISTING_TOKEN_ID="${6:-}"
[ -z "${DEV}" ] && return 1
[ -z "${NEWKEY}" ] && return 1
- [ -z "${KEY}" ] && [ -z "${KEYFILE}" ] && return 1
+ [ -z "${EXISTING_TOKEN_ID}" ] && [ -z "${KEY}" ] && [ -z "${KEYFILE}" ] && return 1
local extra_args='' input
input="$(printf '%s\n%s' "${KEY}" "${NEWKEY}")"
@@ -745,6 +752,10 @@
extra_args="$(printf -- '--key-file %s' "${KEYFILE}")"
input="$(printf '%s' "${NEWKEY}")"
fi
+ if [ -n "${EXISTING_TOKEN_ID}" ]; then
+ extra_args="$(printf -- '--token-id %s' "${EXISTING_TOKEN_ID}")"
+ input="$(printf '%s' "${NEWKEY}")"
+ fi
printf '%s' "${input}" | cryptsetup luksAddKey --batch-mode \
--key-slot "${SLT}" \
@@ -759,6 +770,7 @@
local NEWKEY="${3}"
local KEY="${4}"
local KEYFILE="${5:-}"
+ local EXISTING_TOKEN_ID="${6:-}"
[ -z "${DEV}" ] && return 1
[ -z "${NEWKEY}" ] && return 1
@@ -768,7 +780,7 @@
local in_place
clevis_luks_check_valid_key_or_keyfile "${DEV}" \
"${KEY}" "${KEYFILE}" \
- "${SLT}" 2>/dev/null \
+ "${SLT}" "${EXISTING_TOKEN_ID}" 2>/dev/null \
&& in_place=true
local input extra_args=
@@ -777,6 +789,10 @@
extra_args="$(printf -- '--key-file %s' "${KEYFILE}")"
input="$(printf '%s' "${NEWKEY}")"
fi
+ if [ -n "${EXISTING_TOKEN_ID}" ]; then
+ extra_args="$(printf -- '--token-id %s' "${EXISTING_TOKEN_ID}")"
+ input="$(printf '%s' "${NEWKEY}")"
+ fi
if [ -n "${in_place}" ]; then
printf '%s' "${input}" | cryptsetup luksChangeKey "${DEV}" \
@@ -803,6 +819,7 @@
local KEY="${4}"
local KEYFILE="${5:-}"
local OVERWRITE="${6:-}"
+ local EXISTING_TOKEN_ID="${7:-}"
[ -z "${DEV}" ] && return 1
[ -z "${SLT}" ] && return 1
@@ -820,13 +837,13 @@
[ -n "${OVERWRITE}" ] || return 1
clevis_luks_update_key "${DEV}" "${SLT}" \
- "${NEWKEY}" "${KEY}" "${KEYFILE}"
+ "${NEWKEY}" "${KEY}" "${KEYFILE}" "${EXISTING_TOKEN_ID}"
return
fi
# Add a new key.
clevis_luks_add_key "${DEV}" "${SLT}" \
- "${NEWKEY}" "${KEY}" "${KEYFILE}"
+ "${NEWKEY}" "${KEY}" "${KEYFILE}" "${EXISTING_TOKEN_ID}"
}
# clevis_luks_generate_key() generates a new key for use with clevis.
@@ -927,6 +944,8 @@
if ! clevis_luks_check_valid_key_or_keyfile "${DEV}" \
"${KEY}" \
"${KEYFILE}" \
+ "" \
+ "${EXISTING_TOKEN_ID}" \
&& ! KEY="$(clevis_luks_get_existing_key "${DEV}" \
"Enter existing LUKS password: " \
"recover")"; then
@@ -971,7 +990,7 @@
if ! clevis_luks_save_key_to_slot "${DEV}" "${SLT}" \
"${newkey}" "${KEY}" "${KEYFILE}" \
- "${OVERWRITE}"; then
+ "${OVERWRITE}" "${EXISTING_TOKEN_ID}"; then
echo "Unable to save/update key slot; operation cancelled" >&2
clevis_luks_restore_dev "${CLEVIS_TMP_DIR}" || :
rm -rf "${CLEVIS_TMP_DIR}"
@@ -992,12 +1011,19 @@
}
# clevis_luks_luks2_supported() indicates whether we support LUKS2 devices.
-# Suppor is determined at build time.
+# Support is determined at build time.
function clevis_luks_luks2_supported() {
# We require cryptsetup >= 2.0.4 to fully support LUKSv2.
return @OLD_CRYPTSETUP@
}
+# clevis_luks_luks2_existing_token_id_supported() indicates whether
+# cryptsetup allows token id for passphrase providing
+function clevis_luks_luks2_existing_token_id_supported() {
+ # We require cryptsetup >= 2.6.0 to fully support LUKSv2 addkey/open by token ID
+ return @OLD_CRYPTSETUP_EXISTING_TOKEN_ID@
+}
+
# clevis_luks_type() returns the LUKS type of a device, e.g. "luks1".
clevis_luks_type() {
local DEV="${1}"
--- clevis-18.ori/src/luks/meson.build 2021-04-15 13:00:19.965065700 +0200
+++ clevis-18.new/src/luks/meson.build 2022-12-01 12:23:01.159960762 +0100
@@ -14,6 +14,15 @@
endif
endif
+libcryptsetup_ext_token_id = dependency('libcryptsetup', version: '>=2.6.0', required: false)
+if libcryptsetup_ext_token_id.found()
+ luksmeta_data.set('OLD_CRYPTSETUP_EXISTING_TOKEN_ID', '0')
+ message('cryptsetup version supports existing token id')
+else
+ luksmeta_data.set('OLD_CRYPTSETUP_EXISTING_TOKEN_ID', '1')
+ warning('cryptsetup version does not support existing token id')
+endif
+
clevis_luks_common_functions = configure_file(
input: 'clevis-luks-common-functions.in',
output: 'clevis-luks-common-functions',
--- clevis-18.ori/src/luks/tests/bind-luks2-ext-token 1970-01-01 01:00:00.000000000 +0100
+++ clevis-18.new/src/luks/tests/bind-luks2-ext-token 2022-12-01 12:23:34.784203368 +0100
@@ -0,0 +1,74 @@
+#!/bin/bash -ex
+# vim: set tabstop=8 shiftwidth=4 softtabstop=4 expandtab smarttab colorcolumn=80:
+#
+# Copyright (c) 2022 Red Hat, Inc.
+# Author: Sergio Arroutbi <sarroutb@redhat.com>
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+
+TEST=$(basename "${0}")
+. tests-common-functions
+
+on_exit() {
+ [ -d "${TMP}" ] && rm -rf "${TMP}"
+}
+
+create_existing_token_id_from_keyring() {
+ local DEV="${1}"
+ local KEYDESC="${2}"
+ local TOKEN_ID="${3}"
+ local PASS="${4}"
+ if [[ -z "${DEV}" ]] || [[ -z "${KEYDESC}" ]] || [[ -z "${TOKEN_ID}" ]]; then
+ return 1
+ fi
+ KEYRING_ID=$(keyctl add user "${KEYDESC}" "${PASS}" @s)
+ keyctl print "${KEYRING_ID}" 2>/dev/null 1>/dev/null
+ cryptsetup token add --token-id "${TOKEN_ID}" --key-description "${KEYDESC}" "${DEV}"
+}
+
+if ! luks2_supported; then
+ skip_test "${TEST}: LUKS2 is not supported."
+fi
+
+if ! luks2_existing_token_id_supported; then
+ skip_test "${TEST}: Existing token ID not supported"
+fi
+
+trap 'on_exit' EXIT
+trap 'exit' ERR
+
+TMP="$(mktemp -d)"
+
+ADV="${TMP}/adv.jws"
+tang_create_adv "${TMP}" "${ADV}"
+CFG="$(printf '{"url":"foobar","adv":"%s"}' "$ADV")"
+
+EXISTING_TOKEN_ID=5
+KEYDESC="testkey"
+PASS="123exttokenid_"
+DEV="${TMP}/luks2-device-ext-token"
+new_device "luks2" "${DEV}" "${PASS}"
+
+create_existing_token_id_from_keyring "${DEV}" "${KEYDESC}" "${EXISTING_TOKEN_ID}" "${PASS}"
+
+if ! clevis luks bind -y -d "${DEV}" -e "${EXISTING_TOKEN_ID}" tang "${CFG}"; then
+ error "${TEST}: Binding expected to succeed with existing token id:${EXISTING_TOKEN_ID}" >&2
+fi
+
+KEYFILE="${TMP}/keyfile.txt"
+touch "${KEYFILE}"
+if clevis luks bind -y -d "${DEV}" -e "${EXISTING_TOKEN_ID}" -k "${KEYFILE}" tang "${CFG}"; then
+ error "${TEST}: Using existing token id and keyfile should dump an error" >&2
+fi
\ No newline at end of file
--- clevis-18.ori/src/luks/tests/tests-common-functions.in 2021-04-15 13:00:19.967066500 +0200
+++ clevis-18.new/src/luks/tests/tests-common-functions.in 2022-12-01 12:25:06.386864313 +0100
@@ -36,6 +36,12 @@
return @OLD_CRYPTSETUP@
}
+# We require cryptsetup >= 2.6.0 to fully support LUKSv2 addkey/open by token ID
+# Support is determined at build time.
+luks2_existing_token_id_supported() {
+ return @OLD_CRYPTSETUP_EXISTING_TOKEN_ID@
+}
+
# Creates a new LUKS1 or LUKS2 device to be used.
new_device() {
local LUKS="${1}"

View File

@ -1,3 +1,6 @@
* Thu Dec 1 2022 Sergio Arroutbi <sarroutb@redhat.com> - 18-11
- Add external token id parameter for existing passphrase
* Fri Aug 05 2022 Luca BRUNO <lucab@lucabruno.net> - 18-10
- Simplify sysusers.d fragment by using default 'nologin' shell

View File

@ -11,6 +11,7 @@ Source1: clevis.sysusers
Patch0001: 0001-sss-use-BN_set_word-x-0-instead-of-BN_zero.patch
Patch0002: 0002-systemd-account-for-unlocking-failures-in-clevis-luk.patch
Patch0003: 0003-feat-rename-the-test-pin-to-null-pin.patch
Patch0004: 0004-clevis-external-token-id.patch
BuildRequires: git-core
BuildRequires: gcc