-
Notifications
You must be signed in to change notification settings - Fork 106
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This should ease writing new pins a lot, for newcomers and for experienced authors as well.
- Loading branch information
Christoph Biedl
committed
May 23, 2020
1 parent
0bb86d3
commit 6f1f138
Showing
8 changed files
with
530 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
|
||
# Writing your own pin | ||
|
||
The files here should give you an introduction into writing your own pin. | ||
|
||
## Overall workflow | ||
|
||
The `encrypt` script reads a plain text from stdin, encrypts it using | ||
`jose jwe enc` which writes the result to stdout, together with some | ||
information how to re-create the plain text later. The encryption key | ||
itself *must* *not* be included here. | ||
|
||
The encryption key is provided or created by the pin and stashed away | ||
in some way. That is the core logic of a pin. | ||
|
||
A configuration in the JSON format is provided as the first parameter, | ||
it controls the pin's operation. | ||
|
||
The `decrypt` script reads the encrypted information from stdin, | ||
decrypts it using `ose jwe dec` which again writes the result to | ||
stdout. The information provided by `encrypt` above is available, this | ||
must be sufficient to restore the encryption key. | ||
|
||
## How to use this template | ||
|
||
Copy all the files here (except for this one) into a new subdirectory | ||
of `src/pins/`, named as your pin. | ||
|
||
Replace @pin@ with the name of your pin everywhere, including file names. | ||
|
||
The `clevis-{en,de}crypt-@pin@` scripts require the most attention. | ||
|
||
Have a man page in `clevis-encrypt-@[email protected]`. | ||
|
||
Adjust `meson.build`. | ||
|
||
Provide a test in `pin-@pin@`. | ||
|
||
Adjust dracut configuration in `dracut.module-setup.sh.in`. | ||
|
||
Adjust initramfs configuration in `initramfs.in`. | ||
|
||
Optionally add something to `clevis-luks-list`. | ||
|
||
Finally, add your pin in `../meson.build`. | ||
|
||
## Comments | ||
|
||
An extra form of comments is used to explain concepts. They all should | ||
be removed before sending out patches/merge requests. | ||
|
||
#%# some generic information | ||
#!# things worth to know, gotchas | ||
#?# some bits that require more understanding | ||
|
||
## Nameing your pin and configuration variables | ||
|
||
The pin name should be short and reflect the purpose. To avoid trouble | ||
or extra work, the name should start with a letter, followed by letters, | ||
digits, or underscore. | ||
|
||
Parameter names for the pin configuration should follow the same | ||
syntax. These templates assume they can be used as a shell variable. | ||
|
||
## Templates variables | ||
|
||
The templates use `@...@` to mark places that can semi-automatically | ||
be adjusted to your needs. Variables are | ||
|
||
* `@pin@`: The name of this pin, see above | ||
* `@PIN@`: The name of this pin, uppercase | ||
* `@year@`: Current year | ||
* `@name@`: Your name | ||
* `@email@`: Your e-mail address | ||
* `@mand1@`: The name of a mandatory parameter | ||
* `@mand2@`: The name of another mandatory parameter | ||
* `@opt1@`: The name of an optional parameter | ||
* `@param1@`: The name of a parameter needed for decryption | ||
* `@param2@`: Another name | ||
|
||
If you have more parameters, extend accordingly | ||
|
||
Any `@@` requires attention in wording. | ||
|
||
Make sure you've replaced *all* occurances of template variables. | ||
Else the build will probably fail. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
#%# Creating an decrypting pin | ||
#%# | ||
#%# Read README.md and clevis-encrypt-@pin@ first, this file aims to | ||
#%# to avoid information duplication. | ||
#%# Unfortunately, this one uses a bashism (read -d) that is not at | ||
#%# all easy to eliminate. | ||
#!/bin/bash | ||
|
||
set -eu | ||
|
||
# Copyright (c) @year@ @name@ | ||
# Author: @name@ <@email@> | ||
# | ||
# 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/>. | ||
# | ||
|
||
#%# This program takes no options - everything needed to know will be | ||
#%# read from stdin. | ||
[ $# -eq 1 ] && [ "${1:-}" = "--summary" ] && exit 2 | ||
|
||
if [ -t 0 ] ; then | ||
echo >&2 | ||
echo 'Usage: clevis decrypt @pin@ < JWE > PLAINTEXT' >&2 | ||
echo >&2 | ||
exit 1 | ||
fi | ||
|
||
#%# The input is concatenated using the dot. Read the first element | ||
#%# but leave everything else in the buffer. Only read -d can to that. | ||
read -d . hdr64 | ||
#%# The header is base64-encoded. Decode now and also verify this is valid JSON | ||
if ! hdr="$(jose fmt --quote="$hdr64" --string --b64load --object --output=-)" ; then | ||
echo 'JWE header corrupt' >&2 | ||
exit 1 | ||
fi | ||
|
||
#%# Input validation: The pin must exist by name. | ||
if [ "$(jose fmt --json="$hdr" --get clevis --get pin --unquote=-)" != '@pin@' ] ; then | ||
echo 'JWE pin mismatch!' >&2 | ||
exit 1 | ||
fi | ||
|
||
#%# Load the parameters into shell variables. | ||
if ! @param1@="$(jose fmt --json="$hdr" --get clevis --get @pin@ --get @param1@ --unquote=-)" ; then | ||
echo 'JWE missing 'clevis.@pin@.@param1@' header parameter!' >&2 | ||
exit 1 | ||
fi | ||
if ! @param2@="$(jose fmt --json="$hdr" --get clevis --get @pin@ --get @param2@ --unquote=-)" ; then | ||
echo 'JWE missing 'clevis.@pin@.@param2@' header parameter!' >&2 | ||
exit 1 | ||
fi | ||
|
||
#%# Possibly some pre-checks on your parameters are needed. | ||
|
||
#%# Now everything is set up for your pin's business logic | ||
#%# | ||
#%# Your job: Somehow bring the key into `jwk`. | ||
jwk="$(load_jwk)" | ||
|
||
#%# Finally, forward everything to `jose jwe dec` which does the | ||
#%# decryption job. | ||
( printf '%s' "$jwk$hdr64." ; cat ) | exec jose jwe dec --key=- --input=- |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,140 @@ | ||
#%# Creating an encrypting pin | ||
#%# | ||
#%# Read README.md first. | ||
#%# | ||
#%# The shell interpreter. For portability, it should have as little | ||
#%# requirements as possibly. Especially the decrypt should be executable | ||
#%# in busybox' ash as well | ||
#!/bin/sh | ||
|
||
#%# Some hardening. Safeguard against coding errors. | ||
set -eu | ||
|
||
#%# Legal stuff. Put your name etc. here. | ||
#%# Of course you're not bound to GPL-3+ but it will certainly ease | ||
#%# inclusion in upstream clevis if you use that. | ||
# Copyright (c) @year@ @name@ | ||
# Author: @name@ <@email@> | ||
# | ||
# 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/>. | ||
# | ||
|
||
#%# A one-line summary. Will be used in the help messages below. | ||
SUMMARY='Encrypts using a @pin@ @@ policy' | ||
|
||
#%# Some option parsing, very simple. | ||
#%# Don't touch, it's hardcoded in the `clevis` program. | ||
if [ "${1:-}" = '--summary' ] ; then | ||
echo "$SUMMARY" | ||
exit 0 | ||
fi | ||
|
||
#%# Regular operation assumes output goes to a file. If not, print | ||
#%# some usage information and bail out. | ||
if [ -t 0 ] ; then | ||
#!# Since this script runs in a pipe, *all* operational messages | ||
#!# must go to stderr. | ||
exec >&2 | ||
echo | ||
#%# Don't be confused: This script is called from `clevis`, so | ||
#%# the usage text has spaces, not dashes. | ||
#%# Also, the configuration is in $1, see below. | ||
echo 'Usage: clevis encrypt @pin@ CONFIG < PLAINTEXT > JWE' | ||
echo | ||
echo "$SUMMARY" | ||
echo | ||
echo 'This command uses the following configuration properties:' | ||
echo | ||
#%# For the sake of users: Give a good explanation of your pin's | ||
#%# parameters. | ||
#%# Mandatory parameters should contain the string "REQUIRED" | ||
echo ' @mand1@: <string> One parameter @@ (REQUIRED)' | ||
echo | ||
echo ' @mand2@: <string> Another parameter @@ (REQUIRED)' | ||
echo | ||
#%# Optional parameters should mention the default value. | ||
echo ' @opt1@: <string> An optional parameter @@ (default: @@)' | ||
echo | ||
#%# Pure visual: Make sure the short descriptions are aligned to the | ||
#%# same column. | ||
exit 2 | ||
fi | ||
|
||
#%# The CONFIG parameter in $1 has to be valid JSON | ||
if ! cfg="$(jose fmt --json="${1:-}" --object --output=- 2>/dev/null)" ; then | ||
echo 'Configuration is malformed!' >&2 | ||
exit 1 | ||
fi | ||
|
||
#%# Load the values from the configuration into shell variables. | ||
#%# Re-using the name is certainly a good idea | ||
#%# | ||
#%# For mandatory parameters it's like that: | ||
if ! @mand1@="$(jose fmt --json="$cfg" --object --get @mand1@ --unquote=-)" ; then | ||
echo 'Missing the required @mand1@ property!' >&2 | ||
exit 1 | ||
fi | ||
if ! @mand2@="$(jose fmt --json="$cfg" --object --get @mand2@ --unquote=-)" ; then | ||
echo 'Missing the required @mand2@ property!' >&2 | ||
exit 1 | ||
fi | ||
|
||
#%# For optional parameters, use: | ||
@opt1@="$(jose fmt --json="$cfg" --object --get @opt1@ --unquote=-)" || @opt1@='@@' | ||
|
||
#%# Possibly validate parameters. If a check can be done at *en*crypt | ||
#%# time, it should be done now. | ||
|
||
#%# Now everything is set up for your pin's business logic. | ||
#%# | ||
#%# Your jobs, in no particular order: | ||
#%# | ||
#%# 1. Have the key in `jwk`: | ||
#%# If you want to create a new key: | ||
jwk="$(jose jwk gen --input='{"alg":"A256GCM"}')" | ||
#%# Feel free to use different algorithms for `"alg"`, | ||
#%# jose-jwk-gen(1) and jose-alg(1) have more on all this. | ||
#%# | ||
#%# Or, if you want to use an existing key, just load it into `jwk` | ||
#%# from wherever you got it from: | ||
jwk="$(somehow_get_the_key)" | ||
#%# Remember the result must be a valid jwk object. | ||
|
||
#%# 2. Store the key somewhere. That's your logic. | ||
store_the_jwk "$jwk" | ||
#%# It is a good idea to store the entire `$jwk`. If you want to | ||
#%# extract the actual key, use | ||
#%# jose fmt --json="$jwk" --object --get k --unquote=- | ||
#%# ... but you're probably wrong if you want to do that. | ||
|
||
#%# 3. Assemble all the information you will need to re-create | ||
#%# the key later in `jwe`: | ||
#%# | ||
#%# First create a skeleton that declares the pin, and creates a store. | ||
jwe='{"protected":{"clevis":{"pin":"@pin@","@pin@":{}}}}' | ||
#%# Then populate that store. Possibly you'll just have to pass | ||
#%# the parameters. Leave out those you will not need for decryption. | ||
#%# NB: The long form of the `-U` parameter of `jose fmt` is "--unwind" | ||
jwe="$(jose fmt --json="$jwe" --get protected --get clevis --get @pin@ --quote "$@mand1@" --set @mand1@ -UUUU --output=-)" | ||
jwe="$(jose fmt --json="$jwe" --get protected --get clevis --get @pin@ --quote "$@opt1@" --set @opt1@ -UUUU --output=-)" | ||
|
||
#%# Almost there! | ||
#%# Forward everything to `jose jwe enc` which does the encryption job - | ||
#%# including reading the plaintext from stdin which gets replicated | ||
#%# using `cat`. | ||
( printf '%s' "$jwe$jwk" ; cat ) | exec jose jwe enc --input=- --key=- --detached=- --compact | ||
#%# Anything that follows is executed only if jose failed. | ||
#%# | ||
#!# When using mktemp or the like, cleaning up has to be done | ||
#!# manually. See clevis-{en,de}crypt-tpm2 for an example. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
#%# Align the equal signs after substitution | ||
CLEVIS-ENCRYPT-@PIN@(1) | ||
======================= | ||
:doctype: manpage | ||
|
||
|
||
== NAME | ||
|
||
clevis-encrypt-@pin@ - Encrypts using a @@ policy | ||
|
||
== SYNOPSIS | ||
|
||
*clevis encrypt @pin@* CONFIG < PT > JWE | ||
|
||
== OVERVIEW | ||
|
||
The *clevis encrypt @pin@* command encrypts using a @@ policy. | ||
Its only argument is the JSON configuration object. | ||
|
||
#%# And so on ... | ||
|
||
Encrypting data using the @pin@ pin works like this: | ||
|
||
$ clevis encrypt @pin@ '{"@mand1@":"@@","@mand2":"@@"}' < PT > JWE | ||
|
||
To decrypt the data, just pass it to the *clevis decrypt* command: | ||
|
||
$ clevis decrypt < JWE > PT | ||
|
||
== CONFIG | ||
|
||
This command uses the following configuration properties: | ||
|
||
#%# Keep this in sync with the short help in clevis-encrypt-@pin@ | ||
|
||
* *@mand1@* (string) : | ||
@@ (REQUIRED) | ||
|
||
* *@mand2@* (string) : | ||
@@ (REQUIRED) | ||
|
||
* *@opt1@* (string) : | ||
@@ (default: @@) | ||
|
||
== BUGS | ||
|
||
#%# List any flaws and gotchas here. | ||
|
||
== SEE ALSO | ||
|
||
link:clevis-decrypt.1.adoc[*clevis-decrypt*(1)] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
#!/bin/sh | ||
# | ||
# Copyright (c) @year@ @name@ | ||
# Author: @name@ <@email@> | ||
# | ||
# 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-@pin@ | ||
} |
Oops, something went wrong.