From c6d1b1a3128d29a2d13799cf869602d1afb02d57 Mon Sep 17 00:00:00 2001 From: Sergio Correia Date: Wed, 4 Dec 2019 18:11:00 -0300 Subject: [PATCH] Backport upstream tests and fixes Commits backported: * Add tests for LUKS binding and unbinding - https://github.com/latchset/clevis/pull/134/commits/f5d42cb3ba02ff8fcf39cc6c2751d2cd444f5a74 * Rework the logic for reading the existing key - https://github.com/latchset/clevis/pull/141/commits/834eda9db62992fc235ecef41461502fd4084f6e * fix for different output from 'luksAddKey' command w/cryptsetup v2.0.2 ( - https://github.com/latchset/clevis/commit/62bd6de0b8c36a238809546273ff08c3f3766564 * pins/tang: check that key derivation key is available - https://github.com/latchset/clevis/pull/119/commits/c231352729223b08ade04e4e46c775bb934c9959 --- src/luks/clevis-luks-bind | 53 ++++++++--- src/luks/meson.build | 5 +- .../tests/bind-key-file-non-interactive-luks1 | 59 ++++++++++++ src/luks/tests/bind-luks1 | 57 ++++++++++++ src/luks/tests/bind-luks2 | 48 ++++++++++ .../bind-pass-with-newline-keyfile-luks1 | 70 ++++++++++++++ src/luks/tests/bind-pass-with-newline-luks1 | 67 +++++++++++++ src/luks/tests/bind-wrong-pass-luks1 | 56 +++++++++++ src/luks/tests/bind-wrong-pass-luks2 | 47 ++++++++++ src/luks/tests/meson.build | 27 ++++++ src/luks/tests/tests-common-functions | 93 +++++++++++++++++++ src/luks/tests/unbind-luks1 | 74 +++++++++++++++ src/luks/tests/unbind-luks2 | 51 ++++++++++ src/luks/tests/unbind-unbound-slot-luks1 | 40 ++++++++ src/luks/tests/unbind-unbound-slot-luks2 | 41 ++++++++ src/pins/tang/clevis-encrypt-tang | 6 +- 16 files changed, 780 insertions(+), 14 deletions(-) create mode 100755 src/luks/tests/bind-key-file-non-interactive-luks1 create mode 100755 src/luks/tests/bind-luks1 create mode 100755 src/luks/tests/bind-luks2 create mode 100755 src/luks/tests/bind-pass-with-newline-keyfile-luks1 create mode 100755 src/luks/tests/bind-pass-with-newline-luks1 create mode 100755 src/luks/tests/bind-wrong-pass-luks1 create mode 100755 src/luks/tests/bind-wrong-pass-luks2 create mode 100644 src/luks/tests/meson.build create mode 100755 src/luks/tests/tests-common-functions create mode 100755 src/luks/tests/unbind-luks1 create mode 100755 src/luks/tests/unbind-luks2 create mode 100755 src/luks/tests/unbind-unbound-slot-luks1 create mode 100755 src/luks/tests/unbind-unbound-slot-luks2 diff --git a/src/luks/clevis-luks-bind b/src/luks/clevis-luks-bind index 7aae2ea..6edfccd 100755 --- a/src/luks/clevis-luks-bind +++ b/src/luks/clevis-luks-bind @@ -107,26 +107,55 @@ if cryptsetup isLuks --type luks1 "$DEV" && ! luksmeta test -d "$DEV"; then luksmeta init -d "$DEV" $FRC fi -# Get the old key +# Get the existing key. case "$KEY" in -"") read -s -p "Enter existing LUKS password: " old; echo;; - -) old=`/bin/cat`;; - *) old=`/bin/cat "$KEY"`;; +"") read -r -s -p "Enter existing LUKS password: " existing_key; echo;; + -) existing_key="$(/bin/cat)";; + *) ! IFS= read -rd '' existing_key < "$KEY";; esac -# Add the new key + +#Add the new key if [ -n "$SLT" ]; then - if ! echo -e "$old\n$key" | cryptsetup luksAddKey --key-slot $SLT $DEV; then - echo "Error while adding new key to LUKS header!" >&2 - exit 1 + cryptsetup luksAddKey --key-slot "$SLT" --key-file \ + <(echo -n "$existing_key") "$DEV" +else + if cryptsetup isLuks --type luks2 "${DEV}"; then + readarray -t usedSlotsBeforeAddKey < <(cryptsetup luksDump "${DEV}" \ + | sed -rn 's|^\s+([0-9]+): luks2$|\1|p') + else + readarray -t usedSlotsBeforeAddKey < <(cryptsetup luksDump "${DEV}" \ + | sed -rn 's|^Key Slot ([0-7]): ENABLED$|\1|p') fi -elif ! SLT=`echo -e "$old\n$key" \ - | cryptsetup luksAddKey -v $DEV \ - | sed -rn 's|^Key slot ([0-9]+) created\.$|\1|p'`; then + cryptsetup luksAddKey --key-file <(echo -n "${existing_key}") "$DEV" +fi < <(echo -n "${key}") +if [ $? -ne 0 ]; then echo "Error while adding new key to LUKS header!" >&2 exit 1 fi +#Determine slot used by new key if a desired slot was not specified +if [ -z "$SLT" ]; then + if cryptsetup isLuks --type luks2 "${DEV}"; then + readarray -t usedSlotsAfterAddKey < <(cryptsetup luksDump "${DEV}" \ + | sed -rn 's|^\s+([0-9]+): luks2$|\1|p') + else + readarray -t usedSlotsAfterAddKey < <(cryptsetup luksDump "${DEV}" \ + | sed -rn 's|^Key Slot ([0-7]): ENABLED$|\1|p') + fi + for i in "${usedSlotsAfterAddKey[@]}"; do + if [[ ! " ${usedSlotsBeforeAddKey[@]} " =~ " ${i} " ]]; then + SLT=$i + break + fi + done +fi + +if [ -z "$SLT" ]; then + echo "Error while adding new key to LUKS header! Key slot is undefined." >&2 + exit 1 +fi + if cryptsetup isLuks --type luks1 "$DEV"; then if ! echo -n $jwe | luksmeta save -d "$DEV" -u "$UUID" -s $SLT 2>/dev/null; then echo "Error while saving Clevis metadata in LUKSMeta!" >&2 @@ -142,4 +171,4 @@ else cryptsetup luksRemoveKey "$DEV" <<<"$key" exit 1 fi -fi \ No newline at end of file +fi diff --git a/src/luks/meson.build b/src/luks/meson.build index 1f64ab0..2935c3f 100644 --- a/src/luks/meson.build +++ b/src/luks/meson.build @@ -18,4 +18,7 @@ if libcryptsetup.found() and luksmeta.found() and pwmake.found() mans += join_paths(meson.current_source_dir(), 'clevis-luks-unlockers.7') else warning('Will not install LUKS support due to missing dependencies!') -endif \ No newline at end of file +endif + +# Tests. +subdir('tests') diff --git a/src/luks/tests/bind-key-file-non-interactive-luks1 b/src/luks/tests/bind-key-file-non-interactive-luks1 new file mode 100755 index 0000000..f5b5d03 --- /dev/null +++ b/src/luks/tests/bind-key-file-non-interactive-luks1 @@ -0,0 +1,59 @@ +#!/bin/bash -ex +# vim: set tabstop=8 shiftwidth=4 softtabstop=4 expandtab smarttab colorcolumn=80: +# +# Copyright (c) 2019 Red Hat, Inc. +# Author: Sergio Correia +# +# 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="${0}" +. tests-common-functions + +on_exit() { + [ -d "${TMP}" ] && rm -rf "${TMP}" +} + +trap 'on_exit' EXIT +trap 'exit' ERR + +TMP="$(mktemp -d)" + +ADV="${TMP}/adv.jws" +create_tang_adv "${ADV}" +CFG="$(printf '{"url":"foobar","adv":"%s"}' "$ADV")" +UUID="cb6e8904-81ff-40da-a84a-07ab9ab5715e" +KEYFILE="${TMP}/key" +PASS=$(openssl rand -hex 8) +echo -n "${PASS}" > "${KEYFILE}" + +# LUKS1. +DEV="${TMP}/luks1-device" +new_device_keyfile "luks1" "${DEV}" "${KEYFILE}" +if ! clevis luks bind -f -k "${KEYFILE}" -d "${DEV}" tang "${CFG}"; then + error "${TEST}: Binding is expected to succeed when given a correct (${KEYFILE})." >&2 +fi + +SLT=1 +if ! read -r _ state uuid < <(luksmeta show -d "${DEV}" | grep "^${SLT} *"); then + error "${TEST}: Error reading LUKSmeta info for slot ${SLT} of ${DEV}." >&2 +fi + +if [ "${state}" != "active" ]; then + error "${TEST}: state (${state}) is expected to be 'active'." >&2 +fi + +if [ "${uuid}" != "${UUID}" ]; then + error "${TEST}: UUID ($uuid) is expected to be '${UUID}'." >&2 +fi diff --git a/src/luks/tests/bind-luks1 b/src/luks/tests/bind-luks1 new file mode 100755 index 0000000..281a328 --- /dev/null +++ b/src/luks/tests/bind-luks1 @@ -0,0 +1,57 @@ +#!/bin/bash -ex +# vim: set tabstop=8 shiftwidth=4 softtabstop=4 expandtab smarttab colorcolumn=80: +# +# Copyright (c) 2019 Red Hat, Inc. +# Author: Sergio Correia +# +# 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}" +} + +trap 'on_exit' EXIT +trap 'exit' ERR + +TMP="$(mktemp -d)" + +ADV="${TMP}/adv.jws" +create_tang_adv "${ADV}" +CFG="$(printf '{"url":"foobar","adv":"%s"}' "$ADV")" + +# LUKS1. +DEV="${TMP}/luks1-device" +UUID="cb6e8904-81ff-40da-a84a-07ab9ab5715e" +new_device "luks1" "${DEV}" + +if ! clevis luks bind -f -d "${DEV}" tang "${CFG}" <<< "${DEFAULT_PASS}"; then + error "${TEST}: Binding is expected to succeed when given a correct (${DEFAULT_PASS}) password." >&2 +fi + +SLT=1 +if ! read -r _ state uuid < <(luksmeta show -d "${DEV}" | grep "^${SLT} *"); then + error "${TEST}: Error reading LUKSmeta info for slot ${SLT} of ${DEV}." >&2 +fi + +if [ "${state}" != "active" ]; then + error "${TEST}: state (${state}) is expected to be 'active'." >&2 +fi + +if [ "${uuid}" != "${UUID}" ]; then + error "${TEST}: UUID ($uuid) is expected to be '${UUID}'." >&2 +fi diff --git a/src/luks/tests/bind-luks2 b/src/luks/tests/bind-luks2 new file mode 100755 index 0000000..11f988c --- /dev/null +++ b/src/luks/tests/bind-luks2 @@ -0,0 +1,48 @@ +#!/bin/bash -ex +# vim: set tabstop=8 shiftwidth=4 softtabstop=4 expandtab smarttab colorcolumn=80: +# +# Copyright (c) 2019 Red Hat, Inc. +# Author: Sergio Correia +# +# 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}" +} + +trap 'on_exit' EXIT +trap 'exit' ERR + +if ! luks2_supported; then + error "{TEST}: LUKS2 is not supported." +fi + +TMP="$(mktemp -d)" + +ADV="${TMP}/adv.jws" +create_tang_adv "${ADV}" +CFG="$(printf '{"url":"foobar","adv":"%s"}' "$ADV")" + +# LUKS2. + +DEV="${TMP}/luks2-device" +new_device "luks2" "${DEV}" + +if ! clevis luks bind -d "${DEV}" tang "${CFG}" <<< "${DEFAULT_PASS}"; then + error "${TEST}: Binding is expected to succeed when given a correct (${DEFAULT_PASS}) password." >&2 +fi diff --git a/src/luks/tests/bind-pass-with-newline-keyfile-luks1 b/src/luks/tests/bind-pass-with-newline-keyfile-luks1 new file mode 100755 index 0000000..bce584e --- /dev/null +++ b/src/luks/tests/bind-pass-with-newline-keyfile-luks1 @@ -0,0 +1,70 @@ +#!/bin/bash -ex +# vim: set tabstop=8 shiftwidth=4 softtabstop=4 expandtab smarttab colorcolumn=80: +# +# Copyright (c) 2019 Red Hat, Inc. +# Author: Sergio Correia +# +# 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="${0}" +. tests-common-functions + +on_exit() { + [ -d "${TMP}" ] && rm -rf "${TMP}" +} + +trap 'on_exit' EXIT +trap 'exit' ERR + +TMP="$(mktemp -d)" + +ADV="${TMP}/adv.jws" +create_tang_adv "${ADV}" +CFG="$(printf '{"url":"foobar","adv":"%s"}' "$ADV")" + +# LUKS1. +DEV="${TMP}/luks1-device" +UUID="cb6e8904-81ff-40da-a84a-07ab9ab5715e" + +# Using newlines and special chars in the passphrase. +PASS="foo + +bar + +\\\&#@@&@*!)( + +$$$ +" + +KEYFILE="${TMP}/key" +echo -n "${PASS}" > "${KEYFILE}" + +new_device_keyfile "luks1" "${DEV}" "${KEYFILE}" +if ! clevis luks bind -f -k "${KEYFILE}" -d "${DEV}" tang "${CFG}"; then + error "${TEST}: Binding is expected to succeed when given a correct (${KEYFILE}) password." >&2 +fi + +SLT=1 +if ! read -r _ state uuid < <(luksmeta show -d "${DEV}" | grep "^${SLT} *"); then + error "${TEST}: Error reading LUKSmeta info for slot ${SLT} of ${DEV}." >&2 +fi + +if [ "${state}" != "active" ]; then + error "${TEST}: state (${state}) is expected to be 'active'." >&2 +fi + +if [ "${uuid}" != "${UUID}" ]; then + error "${TEST}: UUID ($uuid) is expected to be '${UUID}'." >&2 +fi diff --git a/src/luks/tests/bind-pass-with-newline-luks1 b/src/luks/tests/bind-pass-with-newline-luks1 new file mode 100755 index 0000000..89de082 --- /dev/null +++ b/src/luks/tests/bind-pass-with-newline-luks1 @@ -0,0 +1,67 @@ +#!/bin/bash -ex +# vim: set tabstop=8 shiftwidth=4 softtabstop=4 expandtab smarttab colorcolumn=80: +# +# Copyright (c) 2019 Red Hat, Inc. +# Author: Sergio Correia +# +# 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="${0}" +. tests-common-functions + +on_exit() { + [ -d "${TMP}" ] && rm -rf "${TMP}" +} + +trap 'on_exit' EXIT +trap 'exit' ERR + +TMP="$(mktemp -d)" + +ADV="${TMP}/adv.jws" +create_tang_adv "${ADV}" +CFG="$(printf '{"url":"foobar","adv":"%s"}' "$ADV")" + +# LUKS1. +DEV="${TMP}/luks1-device" +UUID="cb6e8904-81ff-40da-a84a-07ab9ab5715e" + +# Using newlines and special chars in the passphrase. +PASS="foo + +bar + +\\\&#@@&@*!)( + +$$$ +" +new_device "luks1" "${DEV}" "${PASS}" + +if ! clevis luks bind -f -d "${DEV}" tang "${CFG}" <<< "${PASS}"; then + error "${TEST}: Binding is expected to succeed when given a correct (${PASS}) password." >&2 +fi + +SLT=1 +if ! read -r _ state uuid < <(luksmeta show -d "${DEV}" | grep "^${SLT} *"); then + error "${TEST}: Error reading LUKSmeta info for slot ${SLT} of ${DEV}." >&2 +fi + +if [ "${state}" != "active" ]; then + error "${TEST}: state (${state}) is expected to be 'active'." >&2 +fi + +if [ "${uuid}" != "${UUID}" ]; then + error "${TEST}: UUID ($uuid) is expected to be '${UUID}'." >&2 +fi diff --git a/src/luks/tests/bind-wrong-pass-luks1 b/src/luks/tests/bind-wrong-pass-luks1 new file mode 100755 index 0000000..a15945e --- /dev/null +++ b/src/luks/tests/bind-wrong-pass-luks1 @@ -0,0 +1,56 @@ +#!/bin/bash -ex +# vim: set tabstop=8 shiftwidth=4 softtabstop=4 expandtab smarttab colorcolumn=80: +# +# Copyright (c) 2019 Red Hat, Inc. +# Author: Sergio Correia +# +# 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}" +} + +trap 'on_exit' EXIT +trap 'exit' ERR + +TMP="$(mktemp -d)" + +ADV="${TMP}/adv.jws" +create_tang_adv "${ADV}" +CFG="$(printf '{"url":"foobar","adv":"%s"}' "$ADV")" + +# LUKS1. +DEV="${TMP}/luks1-device" +new_device "luks1" "${DEV}" + +if clevis luks bind -f -d "${DEV}" tang "${CFG}" <<< "wrong-passphrase"; then + error "${TEST}: Binding is expected to fail when given a wrong password." >&2 +fi + +SLT=1 +if ! read -r _ state uuid < <(luksmeta show -d "${DEV}" | grep "^${SLT} *"); then + error "${TEST}: Error reading LUKSmeta info for slot ${SLT} of ${DEV}." >&2 +fi + +if [ "${state}" != "inactive" ]; then + error "${TEST}: state (${state}) is expected to be 'inactive'." >&2 +fi + +if [ "${uuid}" != "empty" ]; then + error "${TEST}: UUID ($uuid) is expected to be 'empty'." >&2 +fi diff --git a/src/luks/tests/bind-wrong-pass-luks2 b/src/luks/tests/bind-wrong-pass-luks2 new file mode 100755 index 0000000..cbbb095 --- /dev/null +++ b/src/luks/tests/bind-wrong-pass-luks2 @@ -0,0 +1,47 @@ +#!/bin/bash -ex +# vim: set tabstop=8 shiftwidth=4 softtabstop=4 expandtab smarttab colorcolumn=80: +# +# Copyright (c) 2019 Red Hat, Inc. +# Author: Sergio Correia +# +# 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}" +} + +trap 'on_exit' EXIT +trap 'exit' ERR + +if ! luks2_supported; then + error "{TEST}: LUKS2 is not supported." +fi + +TMP="$(mktemp -d)" + +ADV="${TMP}/adv.jws" +create_tang_adv "${ADV}" +CFG="$(printf '{"url":"foobar","adv":"%s"}' "$ADV")" + +# LUKS2. +DEV="${TMP}/luks2-device" +new_device "luks2" "${DEV}" + +if clevis luks bind -d "${DEV}" tang "${CFG}" <<< "wrong-passphrase"; then + error "${TEST}: Binding is expected to fail when given a wrong password." >&2 +fi diff --git a/src/luks/tests/meson.build b/src/luks/tests/meson.build new file mode 100644 index 0000000..85b8a99 --- /dev/null +++ b/src/luks/tests/meson.build @@ -0,0 +1,27 @@ +env = environment() +env.prepend('PATH', + join_paths(meson.source_root(), 'src'), + join_paths(meson.source_root(), 'src', 'luks'), + join_paths(meson.source_root(), 'src', 'pins', 'tang'), + join_paths(meson.source_root(), 'src', 'pins', 'tpm2'), + meson.current_source_dir(), + meson.current_build_dir(), + join_paths(meson.build_root(), 'src'), + join_paths(meson.build_root(), 'src', 'luks'), + separator: ':' +) + +test('bind-wrong-pass-luks1', find_program('bind-wrong-pass-luks1'), env: env) +test('bind-luks1', find_program('bind-luks1'), env: env) +test('unbind-unbound-slot-luks1', find_program('unbind-unbound-slot-luks1'), env: env) +test('unbind-luks1', find_program('unbind-luks1'), env: env) +test('bind-key-file-non-interactive', find_program('bind-key-file-non-interactive-luks1'), env: env) +test('bind-pass-with-newline', find_program('bind-pass-with-newline-luks1'), env: env) +test('bind-pass-with-newline-keyfile', find_program('bind-pass-with-newline-keyfile-luks1'), env: env) + +# LUKS2 tests go here. +# Binding LUKS2 takes longer, so timeout is increased for a few tests. +test('bind-wrong-pass-luks2', find_program('bind-wrong-pass-luks2'), env: env) +test('bind-luks2', find_program('bind-luks2'), env: env, timeout: 60) +test('unbind-unbound-slot-luks2', find_program('unbind-unbound-slot-luks2'), env: env) +test('unbind-luks2', find_program('unbind-luks2'), env: env, timeout: 60) diff --git a/src/luks/tests/tests-common-functions b/src/luks/tests/tests-common-functions new file mode 100755 index 0000000..4befaa9 --- /dev/null +++ b/src/luks/tests/tests-common-functions @@ -0,0 +1,93 @@ +#!/bin/bash -ex +# vim: set tabstop=8 shiftwidth=4 softtabstop=4 expandtab smarttab colorcolumn=80: +# +# Copyright (c) 2019 Red Hat, Inc. +# Author: Sergio Correia +# +# 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 . +# + +error() { + echo "${1}" >&2 + exit 1 +} + +# We require cryptsetup >= 2.0.4 to fully support LUKSv2. +# Support is determined at build time. +luks2_supported() { + return 0 +} + +# Creates a tang adv to be used in the test. +create_tang_adv() { + local adv="${1}" + local SIG="${TMP}/sig.jwk" + jose jwk gen -i '{"alg":"ES512"}' > "${SIG}" + + local EXC="${TMP}/exc.jwk" + jose jwk gen -i '{"alg":"ECMR"}' > "${EXC}" + + local TEMPLATE='{"protected":{"cty":"jwk-set+json"}}' + jose jwk pub -s -i "${SIG}" -i "${EXC}" \ + | 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 PASS="${3}" + + # Using a default password, if none has been provided. + if [ -z "${PASS}" ]; then + PASS="${DEFAULT_PASS}" + fi + + local DEV_CACHED="${TMP}/${LUKS}.cached" + + # Let's reuse an existing device, if there is one. + if [ -f "${DEV_CACHED}" ]; then + echo "Reusing cached ${LUKS} device..." + cp -f "${DEV_CACHED}" "${DEV}" + return 0 + fi + + fallocate -l16M "${DEV}" + local extra_options= + if [ "${LUKS}" = "luks2" ]; then + extra_options="--pbkdf pbkdf2" + fi + if ! cryptsetup luksFormat --type "${LUKS}" --batch-mode --force-password "${DEV}" <<< "${PASS}"; then + cryptsetup luksFormat --type "${LUKS}" --batch-mode --force-password "${DEV}" --debug 2>&1 <<< "${PASS}" + fi + # Caching the just-formatted device for possible reuse. + cp -f "${DEV}" "${DEV_CACHED}" +} + +# Creates a new LUKS1 or LUKS2 device to be used, using a keyfile. +new_device_keyfile() { + local LUKS="${1}" + local DEV="${2}" + local KEYFILE="${3}" + + if [[ -z "${KEYFILE}" ]] || [[ ! -f "${KEYFILE}" ]]; then + error "Invalid keyfile (${KEYFILE})." + fi + + fallocate -l16M "${DEV}" + cryptsetup luksFormat --type "${LUKS}" --batch-mode "${DEV}" "${KEYFILE}" +} + +export DEFAULT_PASS='just-some-test-password-here' diff --git a/src/luks/tests/unbind-luks1 b/src/luks/tests/unbind-luks1 new file mode 100755 index 0000000..56cf8c0 --- /dev/null +++ b/src/luks/tests/unbind-luks1 @@ -0,0 +1,74 @@ +#!/bin/bash -ex +# vim: set tabstop=8 shiftwidth=4 softtabstop=4 expandtab smarttab colorcolumn=80: +# +# Copyright (c) 2019 Red Hat, Inc. +# Author: Sergio Correia +# +# 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}" +} + +trap 'on_exit' EXIT +trap 'exit' ERR + +TMP="$(mktemp -d)" +ADV="${TMP}/adv.jws" +create_tang_adv "${ADV}" +CFG="$(printf '{"url":"foobar","adv":"%s"}' "$ADV")" + +# LUKS1. +DEV="${TMP}/luks1-device" +UUID="cb6e8904-81ff-40da-a84a-07ab9ab5715e" +new_device "luks1" "${DEV}" + +# Bind, initially. +if ! clevis luks bind -f -d "${DEV}" tang "${CFG}" <<< "${DEFAULT_PASS}"; then + error "${TEST}: Binding is expected to succeed when given a correct (${DEFAULT_PASS}) password." >&2 +fi + +SLT=1 +if ! read -r _ state uuid < <(luksmeta show -d "${DEV}" | grep "^${SLT} *"); then + error "${TEST}: Error reading LUKSmeta info for slot ${SLT} of ${DEV}." >&2 +fi + +if [ "${state}" != "active" ]; then + error "${TEST}: state (${state}) is expected to be 'active'." >&2 +fi + +if [ "${uuid}" != "${UUID}" ]; then + error "${TEST}: UUID ($uuid) is expected to be '${UUID}'." >&2 +fi + +# Now unbind. +if ! clevis luks unbind -f -d "${DEV}" -s "${SLT}"; then + error "${TEST}: Unbind is expected to succeed for device ${DEV} and slot ${SLT}" >&2 +fi + +if ! read -r _ state uuid < <(luksmeta show -d "${DEV}" | grep "^${SLT} *"); then + error "${TEST}: Error reading LUKSmeta info for slot ${SLT} of ${DEV}." >&2 +fi + +if [ "${state}" != "inactive" ]; then + error "${TEST}: state (${state}) is expected to be 'inactive'." >&2 +fi + +if [ "${uuid}" != "empty" ]; then + error "${TEST}: UUID ($uuid) is expected to be 'empty'." >&2 +fi diff --git a/src/luks/tests/unbind-luks2 b/src/luks/tests/unbind-luks2 new file mode 100755 index 0000000..82871be --- /dev/null +++ b/src/luks/tests/unbind-luks2 @@ -0,0 +1,51 @@ +#!/bin/bash -ex +# vim: set tabstop=8 shiftwidth=4 softtabstop=4 expandtab smarttab colorcolumn=80: +# +# Copyright (c) 2019 Red Hat, Inc. +# Author: Sergio Correia +# +# 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}" +} + +trap 'on_exit' EXIT +trap 'exit' ERR + +if ! luks2_supported; then + error "{TEST}: LUKS2 is not supported." +fi + +TMP="$(mktemp -d)" +ADV="${TMP}/adv.jws" +create_tang_adv "${ADV}" +CFG="$(printf '{"url":"foobar","adv":"%s"}' "$ADV")" + +# LUKS2. +DEV="${TMP}/luks2-device" +new_device "luks2" "${DEV}" +# Binding. +if ! clevis luks bind -d "${DEV}" tang "${CFG}" <<< "${DEFAULT_PASS}"; then + error "${TEST}: Binding is expected to succeed." >&2 +fi + +SLT=1 +if ! clevis luks unbind -f -d "${DEV}" -s "${SLT}"; then + error "${TEST}: Unbind is expected to succeed for device ${DEV} and slot ${SLT}" >&2 +fi diff --git a/src/luks/tests/unbind-unbound-slot-luks1 b/src/luks/tests/unbind-unbound-slot-luks1 new file mode 100755 index 0000000..e562a36 --- /dev/null +++ b/src/luks/tests/unbind-unbound-slot-luks1 @@ -0,0 +1,40 @@ +#!/bin/bash -ex +# vim: set tabstop=8 shiftwidth=4 softtabstop=4 expandtab smarttab colorcolumn=80: +# +# Copyright (c) 2019 Red Hat, Inc. +# Author: Sergio Correia +# +# 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}" +} + +trap 'on_exit' EXIT +trap 'exit' ERR + +TMP="$(mktemp -d)" + +# LUKS1. +DEV="${TMP}/luks1-device" +new_device "luks1" "${DEV}" + +SLT=2 +if clevis luks unbind -d "${DEV}" -s "${SLT}"; then + error "${TEST}: Unbind is expected to fail for device ${DEV} and slot ${SLT}" >&2 +fi diff --git a/src/luks/tests/unbind-unbound-slot-luks2 b/src/luks/tests/unbind-unbound-slot-luks2 new file mode 100755 index 0000000..6a2aca5 --- /dev/null +++ b/src/luks/tests/unbind-unbound-slot-luks2 @@ -0,0 +1,41 @@ +#!/bin/bash -ex +# vim: set tabstop=8 shiftwidth=4 softtabstop=4 expandtab smarttab colorcolumn=80: +# +# Copyright (c) 2019 Red Hat, Inc. +# Author: Sergio Correia +# +# 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}" +} + +trap 'on_exit' EXIT +trap 'exit' ERR + +if ! luks2_supported; then + error "{TEST}: LUKS2 is not supported." +fi + +TMP="$(mktemp -d)" + +DEV="${TMP}/luks2-device" +new_device "luks2" "${DEV}" +if clevis luks unbind -d "${DEV}" -s "${SLT}"; then + error "${TEST}: Unbind is expected to fail for device ${DEV} and slot ${SLT}" >&2 +fi diff --git a/src/pins/tang/clevis-encrypt-tang b/src/pins/tang/clevis-encrypt-tang index e65a7d1..5461b45 100755 --- a/src/pins/tang/clevis-encrypt-tang +++ b/src/pins/tang/clevis-encrypt-tang @@ -114,7 +114,11 @@ elif [ "$thp" != "any" ] && \ fi ### Perform encryption -enc=`jose jwk use -i- -r -u deriveKey -o- <<< "$jwks"` +if ! enc="$(jose jwk use -i- -r -u deriveKey -o- <<< "$jwks")"; then + echo "Key derivation key not available!" >&2 + exit 1 +fi + jose fmt -j "$enc" -Og keys -A || enc="{\"keys\":[$enc]}" for jwk in `jose fmt -j- -Og keys -Af- <<< "$enc"`; do -- 2.23.0