--- 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 +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + +TEST=$(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}"