From 0cf16ed2a254f732136f79920d9aed1f85317ad8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=BD=D0=B0=D0=B1?= Date: Sat, 17 Oct 2020 23:36:53 +0200 Subject: [PATCH] Add zfs-tpm-clear-key --- README.md | 2 +- configMakefile | 4 ++-- src/bin/zfs-tpm-clear-key.cpp | 29 +++++++++++++++++++++++++++++ src/bin/zfs-tpm2-change-key.cpp | 5 +---- src/bin/zfs-tpm2-load-key.cpp | 1 - src/zfs.cpp | 29 +++++++++++++++++++++++++++++ src/zfs.hpp | 15 +++++++++++++++ 7 files changed, 77 insertions(+), 8 deletions(-) create mode 100644 src/bin/zfs-tpm-clear-key.cpp diff --git a/README.md b/README.md index bfb4bf4..fdc2f9c 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ Plus it's a pretty good annoyed sigh onomatopoeia. ### Building You'll need `pkg-config`, `libzfslinux-dev`, `libtss2-dev`, and `make` should hopefully Just Work™ if you have a C++17-capable compiler. -The output binaries are trimmed of extraneous dependencies, so they're all just libc + libzfs and friends + TPM back-end. +The output binaries are trimmed of extraneous dependencies, so they're all just libc + libzfs and friends + TPM back-end, if any. ### Installation diff --git a/configMakefile b/configMakefile index 7d1abe1..5aaeda9 100644 --- a/configMakefile +++ b/configMakefile @@ -56,8 +56,8 @@ LDD ?= ldd AWK ?= awk RONN ?= ronn OBJ := .o -CXXAR := -g -O3 -std=c++17 -fno-exceptions -Wall -Wextra $(CXXSPECIFIC) -pipe $(INCCXXAR) $(PIC) -STRIP ?= @echo strip +CXXAR := -O3 -std=c++17 -fno-exceptions -Wall -Wextra $(CXXSPECIFIC) -pipe $(INCCXXAR) $(PIC) +STRIP ?= strip STRIPAR := --strip-all --remove-section=.comment --remove-section=.note OUTDIR := out/ diff --git a/src/bin/zfs-tpm-clear-key.cpp b/src/bin/zfs-tpm-clear-key.cpp new file mode 100644 index 0000000..9b23197 --- /dev/null +++ b/src/bin/zfs-tpm-clear-key.cpp @@ -0,0 +1,29 @@ +/* SPDX-License-Identifier: MIT */ + + +#include + +#include + +#include "../main.hpp" +#include "../zfs.hpp" + + +int main(int argc, char ** argv) { + return do_main( + argc, argv, "", [&](auto) {}, + [&](auto dataset) { + REQUIRE_KEY_LOADED(dataset); + + if(zfs_crypto_rewrap(dataset, TRY_PTR("get clear rewrap args", clear_rewrap_args()), B_FALSE)) + return __LINE__; // Error printed by libzfs + + if(clear_key_props(dataset)) { + fprintf(stderr, "You might need to run \"zfs inherit %s %s\" and \"zfs inherit %s %s\"!\n", PROPNAME_BACKEND, zfs_get_name(dataset), PROPNAME_KEY, + zfs_get_name(dataset)); + return __LINE__; + } + + return 0; + }); +} diff --git a/src/bin/zfs-tpm2-change-key.cpp b/src/bin/zfs-tpm2-change-key.cpp index fc8e5ea..e69fa4f 100644 --- a/src/bin/zfs-tpm2-change-key.cpp +++ b/src/bin/zfs-tpm2-change-key.cpp @@ -46,10 +46,7 @@ int main(int argc, char ** argv) { return do_main( argc, argv, "b:", [&](auto) { backup = optarg; }, [&](auto dataset) { - if(zfs_prop_get_int(dataset, ZFS_PROP_KEYSTATUS) == ZFS_KEYSTATUS_UNAVAILABLE) { - fprintf(stderr, "Key change error: Key must be loaded.\n"); // mimic libzfs error output - return __LINE__; - } + REQUIRE_KEY_LOADED(dataset); // https://software.intel.com/content/www/us/en/develop/articles/code-sample-protecting-secret-data-and-keys-using-intel-platform-trust-technology.html diff --git a/src/bin/zfs-tpm2-load-key.cpp b/src/bin/zfs-tpm2-load-key.cpp index 022f755..dfcd547 100644 --- a/src/bin/zfs-tpm2-load-key.cpp +++ b/src/bin/zfs-tpm2-load-key.cpp @@ -24,7 +24,6 @@ int main(int argc, char ** argv) { [&](auto dataset) { char *backend{}, *handle_s{}; TRY_MAIN(lookup_userprop(zfs_get_user_props(dataset), PROPNAME_BACKEND, backend)); - fprintf(stderr, "backend=%s\n", backend); if(!backend) { fprintf(stderr, "Dataset %s not encrypted with tzpfms!\n", zfs_get_name(dataset)); diff --git a/src/zfs.cpp b/src/zfs.cpp index 02bfa21..4fa9858 100644 --- a/src/zfs.cpp +++ b/src/zfs.cpp @@ -30,6 +30,27 @@ nvlist_t * rewrap_args() { } +static nvlist_t * crrargs{}; +static quickscope_wrapper crrargs_deleter{[] { nvlist_free(crrargs); }}; +nvlist_t * clear_rewrap_args() { + if(!crrargs) + if(auto err = + [&] { + TRY_NVL("allocate rewrap nvlist", nvlist_alloc(&crrargs, NV_UNIQUE_NAME, 0)); + TRY_NVL("add keyformat to rewrap nvlist", nvlist_add_string(crrargs, zfs_prop_to_name(ZFS_PROP_KEYFORMAT), "passphrase")); + TRY_NVL("add keylocation to rewrap nvlist", nvlist_add_string(crrargs, zfs_prop_to_name(ZFS_PROP_KEYLOCATION), "prompt")); + return 0; + }(); + err && crrargs) { + nvlist_free(crrargs); + crrargs = nullptr; + errno = err; + } + + return crrargs; +} + + #define TRY_LOOKUP(what, ...) \ ({ \ const auto _try_retl = (__VA_ARGS__); \ @@ -38,6 +59,7 @@ nvlist_t * rewrap_args() { TRY_NVL(what, _try_retl); \ }) +// TODO: how does this interact with nested datasets? int lookup_userprop(nvlist_t * from, const char * name, char *& out) { // xyz.nabijaczleweli:tzpfms.key: // value: '76B0286BEB3FAF57536C47D9A2BAD38157FD522A75A59E72867BBFD6AF167395' @@ -69,3 +91,10 @@ int set_key_props(zfs_handle_t * on, const char * backend, uint32_t handle) { return 0; } + + +int clear_key_props(zfs_handle_t * from) { + TRY("delete tzpfms.backend", zfs_prop_inherit(from, PROPNAME_BACKEND, B_FALSE)); + TRY("delete tzpfms.key", zfs_prop_inherit(from, PROPNAME_KEY, B_FALSE)); + return 0; +} diff --git a/src/zfs.hpp b/src/zfs.hpp index dc6f504..8324569 100644 --- a/src/zfs.hpp +++ b/src/zfs.hpp @@ -18,8 +18,20 @@ #define PROPNAME_KEY "xyz.nabijaczleweli:tzpfms.key" +/// Mimic libzfs error output +#define REQUIRE_KEY_LOADED(dataset) \ + do { \ + if(zfs_prop_get_int(dataset, ZFS_PROP_KEYSTATUS) == ZFS_KEYSTATUS_UNAVAILABLE) { \ + fprintf(stderr, "Key change error: Key must be loaded.\n"); \ + return __LINE__; \ + } \ + } while(0) + + /// Static nvlist with {keyformat=raw, keylocation=prompt} extern nvlist_t * rewrap_args(); +/// Static nvlist with {keyformat=passphrase, keylocation=prompt} +extern nvlist_t * clear_rewrap_args(); /// Extract user property name from ZFS property list from to out. /// @@ -28,3 +40,6 @@ extern int lookup_userprop(nvlist_t * from, const char * name, char *& out); /// Set required decoding props on the dataset extern int set_key_props(zfs_handle_t * on, const char * backend, uint32_t handle); + +/// Remove decoding props from the dataset +extern int clear_key_props(zfs_handle_t * from);