Blame SOURCES/0010-existing-luks2-token-id.patch

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