Skip to content

Commit

Permalink
Implement a pin to store the key in a single file
Browse files Browse the repository at this point in the history
This is a very simple pin, and possibly rather for educational
purposes: Store the jwk at a given place in the file system.
  • Loading branch information
Christoph Biedl committed Jan 28, 2023
1 parent 6f1f138 commit b44e13e
Show file tree
Hide file tree
Showing 8 changed files with 307 additions and 0 deletions.
59 changes: 59 additions & 0 deletions src/pins/file/clevis-decrypt-file
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
#!/bin/bash

set -eu

# Copyright (c) 2020 Christoph Biedl
# Author: Christoph Biedl <[email protected]>
#
# 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 <https://www.gnu.org/licenses/>.
#

[ $# -eq 1 ] && [ "${1:-}" = "--summary" ] && exit 2

if [ -t 0 ] ; then
echo >&2
echo 'Usage: clevis decrypt file < JWE > PLAINTEXT' >&2
echo >&2
exit 1
fi

read -d . hdr64
if ! hdr="$(jose fmt --quote="$hdr64" --string --b64load --object --output=-)" ; then
echo 'JWE header corrupt' >&2
exit 1
fi

if [ "$(jose fmt --json="$hdr" --get clevis --get pin --unquote=-)" != 'file' ] ; then
echo 'JWE pin mismatch!' >&2
exit 1
fi

if ! name="$(jose fmt --json="$hdr" --get clevis --get file --get name --unquote=-)" ; then
echo 'JWE missing 'clevis.file.name' header parameter!' >&2
exit 1
fi

if [ ! -f "$name" ] ; then
echo "Key file $name not found" >&2
exit 1
fi

jwk="$(cat "$name")"

if ! jose fmt --json="$jwk" --object --output=/dev/null 2>/dev/null ; then
echo "Key file $name is malformed" >&2
exit 1
fi

( printf '%s' "$jwk$hdr64." ; cat ) | exec jose jwe dec --key=- --input=-
65 changes: 65 additions & 0 deletions src/pins/file/clevis-encrypt-file
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
#!/bin/sh

set -eu

# Copyright (c) 2020 Christoph Biedl
# Author: Christoph Biedl <[email protected]>
#
# 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 <https://www.gnu.org/licenses/>.
#

SUMMARY='Encrypts using a jwk stored in a file policy'

if [ "${1:-}" = '--summary' ] ; then
echo "$SUMMARY"
exit 0
fi

if [ -t 0 ] ; then
exec >&2
echo
echo 'Usage: clevis encrypt file CONFIG < PLAINTEXT > JWE'
echo
echo "$SUMMARY"
echo
echo 'his command uses the following configuration properties:'
echo
echo ' name: <string> The file that holds the encryption key (REQUIRED)'
echo
exit 2
fi

if ! cfg="$(jose fmt --json="$1" --object --output=- 2>/dev/null)" ; then
echo 'Configuration is malformed!' >&2
exit 1
fi

if ! name="$(jose fmt --json="$cfg" --object --get name --unquote=-)" ; then
echo 'Missing the required name property!' >&2
exit 1
fi

if [ -e "$name" ] ; then
echo "File $name already exists" >&2
exit 1
fi

jwk="$(jose jwk gen --input='{"alg":"A256GCM"}')"

( umask 0377 ; echo "$jwk" >"$name" )

jwe='{"protected":{"clevis":{"pin":"file","file":{}}}}'
jwe="$(jose fmt --json="$jwe" --get protected --get clevis --get file --quote "$name" --set name -UUUU --output=-)"

( printf '%s' "$jwe$jwk" ; cat ) | exec jose jwe enc --input=- --key=- --detached=- --compact
44 changes: 44 additions & 0 deletions src/pins/file/clevis-encrypt-file.1.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
CLEVIS-ENCRYPT-FILE(1)
======================
:doctype: manpage


== NAME

clevis-encrypt-file - Encrypts using a file policy

== SYNOPSIS

*clevis encrypt file* CONFIG < PT > JWE

== OVERVIEW

The *clevis encrypt file* command encrypts using a file policy.
Its only argument is the JSON configuration object.

Encrypting data using the file pin works like this:

$ clevis encrypt file '{"name":"/path/to/file"}' < PT > JWE

The given file must not exist yet.

To decrypt the data, just pass it to the *clevis decrypt* command:

$ clevis decrypt < JWE > PT

== CONFIG

This command uses the following configuration properties:

* *name* (string) :
The name to the file where the jwk is stored (REQUIRED)

== BUGS

Requires that directories for that file already exist.

Rather for educational purposes.

== SEE ALSO

link:clevis-decrypt.1.adoc[*clevis-decrypt*(1)]
27 changes: 27 additions & 0 deletions src/pins/file/dracut.module-setup.sh.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#!/bin/sh
#
# Copyright (c) 2020 Christoph Biedl
# Author: Christoph Biedl <[email protected]>
#
# 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/>.
#

depends() {
echo clevis
return 0
}

install() {
inst clevis-decrypt-file
}
35 changes: 35 additions & 0 deletions src/pins/file/initramfs.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#!/bin/sh
#
# Copyright (c) 2020 Christoph Biedl
# Author: Christoph Biedl <[email protected]>
#
# 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/>.
#

case $1 in
prereqs)
exit 0
;;
esac

. @initramfstoolsdir@/hook-functions

die() {
code="$1"
msg="$2"
echo " (ERROR): $msg" >&2
exit "$code"
}

copy_exec @bindir@/clevis-decrypt-file || die 1 "@bindir@/clevis-decrypt-file not found"
46 changes: 46 additions & 0 deletions src/pins/file/meson.build
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@

dracut = dependency('dracut', required: false)
initramfs_tools = find_program('update-initramfs', required: false)

bins += join_paths(meson.current_source_dir(), 'clevis-decrypt-file')
bins += join_paths(meson.current_source_dir(), 'clevis-encrypt-file')
mans += join_paths(meson.current_source_dir(), 'clevis-encrypt-file.1')

env = environment()
env.append('PATH',
join_paths(meson.source_root(), 'src'),
meson.current_source_dir(),
'/usr/libexec',
libexecdir,
separator: ':'
)

test('pin-file', find_program('./pin-file'), env: env)

if dracut.found()
dracutdir = dracut.get_pkgconfig_variable('dracutmodulesdir') + '/60' + meson.project_name() + '-pin-file'
configure_file(
input: 'dracut.module-setup.sh.in',
output: 'module-setup.sh',
install_dir: dracutdir,
configuration: data,
)
else
warning('Will not install dracut module clevis-pin-file due to missing dependencies!')
endif

if initramfs_tools.found()
initramfstools_dir = '/usr/share/initramfs-tools'
initramfs_hooks_dir = '/usr/share/initramfs-tools/hooks'
initramfs_data = configuration_data()
initramfs_data.merge_from(data)
initramfs_data.set('initramfstoolsdir', initramfstools_dir)
configure_file(
input: 'initramfs.in',
output: 'clevis-pin-file',
install_dir: initramfs_hooks_dir,
configuration: initramfs_data,
)
else
warning('Will not install initramfs module clevis-pin-file due to missing dependencies!')
endif
30 changes: 30 additions & 0 deletions src/pins/file/pin-file
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#!/bin/sh

set -e

# Copyright (c) 2020 Christoph Biedl
# Author: Christoph Biedl <[email protected]>
#
# 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/>.
#

TMP="$(mktemp -d)"
# shellcheck disable=SC2064 # Expanding TMP right now is intended
trap "rm -rf \"$TMP\"" EXIT

cfg="$(printf '{"name":"%s"}' "$TMP/key")"
inp='hi'
enc="$(printf '%s' "$inp" | clevis encrypt file "$cfg")"
dec="$(printf '%s' "$enc" | clevis decrypt)"
test "$dec" = "$inp"
1 change: 1 addition & 0 deletions src/pins/meson.build
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
subdir('file')
subdir('sss')
subdir('tang')
subdir('tpm2')

0 comments on commit b44e13e

Please sign in to comment.