Add $TZPFMS_PASSPHRASE_HELPER. Always include the TPM back-end and/or dataset name in password what-fors

This commit is contained in:
наб 2021-11-15 18:36:52 +01:00
parent 74ec450e16
commit 9c8ee8d68c
No known key found for this signature in database
GPG Key ID: BCFD0B018D2658F1
19 changed files with 182 additions and 49 deletions

View File

@ -122,3 +122,4 @@ To all who support further development on Patreon, in particular:
* ThePhD
* Embark Studios
* Jasper Bekkers

View File

@ -34,7 +34,6 @@ _install_tpm1x() {
check() {
command -v zfs-tpm-list > /dev/null || return 1
# shellcheck disable=SC2154
if [ -n "$hostonly" ]; then
_get_backend || return

View File

@ -4,28 +4,26 @@
#define WITH_PROMPTABLE_TTY(REDIREXIONS)
# This sucks a lot of ass, since we don't know the questions or the amount thereof beforehand
# (0-2 (owner hierarchy/ownership + sealed object, both optional) best-case and 0-6 worst-case (both entered wrong twice)).
# Plymouth doesn't allow us to actually check what the splash status was, and ioctl(KDGETMODE) isn't reliable;
# ideally, we'd only clear the screen if we were making the switch, but not if the user was already switched to the log output.
# Instead, clear if there's a "quiet", leave alone otherwise, and always restore;
# cmdline option "plymouth.ignore-show-splash" can be used to disable splashes altogether, if desired.
with_promptable_tty() {
if plymouth --ping 2>/dev/null; then
plymouth hide-splash
# shellcheck disable=SC2217
[ "${quiet:-n}" = "y" ] && printf '\033c' REDIREXIONS
"$@" REDIREXIONS; ret="$?"
plymouth show-splash
# shellcheck disable=SC2016
TZPFMS_PASSPHRASE_HELPER='exec plymouth ask-for-password --prompt="$1: "' "$@" 2>/run/tzpfms-err; ret="$?"
[ -s /run/tzpfms-err ] && plymouth display-message --text="$(cat /run/tzpfms-err)"
elif [ -e /run/systemd/system ] && command -v systemd-ask-password > /dev/null; then # --no-tty matches zfs and actually works
# shellcheck disable=SC2016
TZPFMS_PASSPHRASE_HELPER='exec systemd-ask-password --no-tty --id="tzpfms:$2" "$1: "' "$@" 2>/run/tzpfms-err; ret="$?"
else
# Mimic /scripts/zfs#decrypt_fs(): setting "printk" temporarily to "7" will allow prompt even if kernel option "quiet"
read -r printk _ < /proc/sys/kernel/printk
[ "$printk" = "7" ] || echo 7 > /proc/sys/kernel/printk
"$@" REDIREXIONS; ret="$?"
TZPFMS_PASSPHRASE_HELPER="${TZPFMS_PASSPHRASE_HELPER:-}" "$@" REDIREXIONS; ret="$?" # allow overriding in cmdline, but always set to raze default
[ "$printk" = "7" ] || echo "$printk" > /proc/sys/kernel/printk
fi
[ -s /run/tzpfms-err ] && cat /run/tzpfms-err >&2
[ -s /run/tzpfms-err ] && [ "$ret" -ne 0 ] && sed 's;^;'"$1"': ;' /run/tzpfms-err >> /dev/kmsg
rm -f /run/tzpfms-err
return "$ret"
}
#endefine

View File

@ -7,6 +7,8 @@ To all who support further development, in particular:
ThePhD
.It
Embark Studios
.It
Jasper Bekkers
.El
.
.Sh REPORTING BUGS

26
man/passphrase.h Normal file
View File

@ -0,0 +1,26 @@
.\" SPDX-License-Identifier: MIT
.
.Sh ENVIRONMENT VARIABLES
.Bl -tag -compact -width "TZPFMS"
.It Ev TZPFMS_PASSPHRASE_HELPER
If set and nonempty, will be run as
.Dl Pa /bin/ Ns Nm sh Fl c Li \&"$TZPFMS_PASSPHRASE_HELPER" \&"$TZPFMS_PASSPHRASE_HELPER" Qo Ar prepared prompt Qc Qo Ar target Qc Qo Oo Li new Oc Qc Qo Oo Li again Oc Qc
to provide a passphrase, instead of reading from the standard input.
.Pp
The standard output stream of the helper is tied to an anonymous file and used in its entirety as the passphrase, except for a trailing new-line, if any.
The second argument contains either the dataset name or the element of the TPM hierarchy.
The third argument is
.Li new
if this is for a new passphrase, and the fourth is
.Li again
if it's the second prompt for that passphrase.
The first argument already contains all of this information, as a pre-formatted noun phrase.
.Pp
If the helper doesn't exist
.Pq the shell exits with Sy 127 ,
a diagnostic is issued and the normal prompt is used as fall-back.
If it fails for any other reason, the prompting is aborted.
.Pp
An example value would be:
.No ' Ns Nm systemd-ask-password Fl -id Ns Li = Ns Qo Li tzpfms:\& Ns Ar $2 Qc Qo Ar $1 Ns Li ": " Qc Ns ' .
.El

View File

@ -101,6 +101,8 @@ In case of a catastrophic event, the key can be loaded by running
.Dl Nm zfs Cm load-key Ar dataset Li < Ar backup-file
.El
.
#include "passphrase.h"
.
#include "backend-tpm1x.h"
.
#include "common.h"

View File

@ -39,6 +39,8 @@ Equivalent to
option.
.El
.
#include "passphrase.h"
.
#include "backend-tpm1x.h"
.
#include "common.h"

View File

@ -98,6 +98,8 @@ In case of a catastrophic event, the key can be loaded by running
.Dl Nm zfs Cm load-key Ar dataset Li < Ar backup-file
.El
.
#include "passphrase.h"
.
#include "backend-tpm2.h"
.
#include "common.h"

View File

@ -36,6 +36,8 @@ See
.Xr zfs-tpm2-change-key 8
for a detailed description.
.
#include "passphrase.h"
.
#include "backend-tpm2.h"
.
#include "common.h"

View File

@ -38,6 +38,8 @@ Equivalent to
option.
.El
.
#include "passphrase.h"
.
#include "backend-tpm1x.h"
.
#include "common.h"

View File

@ -60,9 +60,12 @@ int main(int argc, char ** argv) {
}};
{
char what_for[ZFS_MAX_DATASET_NAME_LEN + 40 + 1];
snprintf(what_for, sizeof(what_for), "%s TPM1.X wrapping key (or empty for none)", zfs_get_name(dataset));
uint8_t * parent_key_passphrase{};
size_t parent_key_passphrase_len{};
TRY_MAIN(read_new_passphrase("wrapping key (or empty for none)", parent_key_passphrase, parent_key_passphrase_len));
TRY_MAIN(read_new_passphrase(what_for, parent_key_passphrase, parent_key_passphrase_len));
quickscope_wrapper parent_key_passphrase_deleter{[&] { free(parent_key_passphrase); }};
if(parent_key_passphrase_len)

View File

@ -36,7 +36,7 @@ int main(int argc, char ** argv) {
uint8_t wrap_key[WRAPPING_KEY_LEN]{};
TRY_MAIN(with_tpm1x_session([&](auto ctx, auto srk, auto srk_policy) {
TSS_HOBJECT parent_key{};
TRY_MAIN(try_policy_or_passphrase("load sealant key from blob (did you take ownership?)", "SRK", srk_policy, [&] {
TRY_MAIN(try_policy_or_passphrase("load sealant key from blob (did you take ownership?)", "TPM1.X SRK", srk_policy, [&] {
return Tspi_Context_LoadKeyByBlob(ctx, srk, handle.parent_key_blob_len, handle.parent_key_blob, &parent_key);
}));
quickscope_wrapper parent_key_deleter{[&] { Tspi_Key_UnloadKey(parent_key); }};
@ -59,10 +59,12 @@ int main(int argc, char ** argv) {
TRY_TPM1X("load sealed object from blob", Tspi_SetAttribData(sealed_object, TSS_TSPATTRIB_ENCDATA_BLOB, TSS_TSPATTRIB_ENCDATABLOB_BLOB,
handle.sealed_object_blob_len, handle.sealed_object_blob));
char what_for[ZFS_MAX_DATASET_NAME_LEN + 20 + 1];
snprintf(what_for, sizeof(what_for), "%s TPM1.X wrapping key", zfs_get_name(dataset));
uint8_t * loaded_wrap_key{};
uint32_t loaded_wrap_key_len{};
TRY_MAIN(try_policy_or_passphrase("unseal wrapping key", "wrapping key", parent_key_policy,
TRY_MAIN(try_policy_or_passphrase("unseal wrapping key", what_for, parent_key_policy,
[&] { return Tspi_Data_Unseal(sealed_object, parent_key, &loaded_wrap_key_len, &loaded_wrap_key); }));
if(loaded_wrap_key_len != sizeof(wrap_key)) {
fprintf(stderr, "Wrong sealed data length (%" PRIu32 " != %zu): ", loaded_wrap_key_len, sizeof(wrap_key));

View File

@ -59,7 +59,8 @@ int main(int argc, char ** argv) {
if(backup)
TRY_MAIN(write_exact(backup, wrap_key, sizeof(wrap_key), 0400));
TRY_MAIN(tpm2_seal(tpm2_ctx, tpm2_session, persistent_handle, tpm2_creation_metadata(zfs_get_name(dataset)), wrap_key, sizeof(wrap_key)));
TRY_MAIN(tpm2_seal(zfs_get_name(dataset), tpm2_ctx, tpm2_session, persistent_handle, tpm2_creation_metadata(zfs_get_name(dataset)), wrap_key,
sizeof(wrap_key)));
bool ok = false; // Try to free the persistent handle if we're unsuccessful in actually using it later on
quickscope_wrapper persistent_clearer{[&] {
if(!ok && tpm2_free_persistent(tpm2_ctx, tpm2_session, persistent_handle))

View File

@ -30,7 +30,7 @@ int main(int argc, char ** argv) {
uint8_t wrap_key[WRAPPING_KEY_LEN];
TRY_MAIN(with_tpm2_session([&](auto tpm2_ctx, auto tpm2_session) {
TRY_MAIN(tpm2_unseal(tpm2_ctx, tpm2_session, handle, wrap_key, sizeof(wrap_key)));
TRY_MAIN(tpm2_unseal(zfs_get_name(dataset), tpm2_ctx, tpm2_session, handle, wrap_key, sizeof(wrap_key)));
return 0;
}));

View File

@ -6,8 +6,10 @@
#include "main.hpp"
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <termios.h>
#include <unistd.h>
@ -18,7 +20,7 @@
int filled_fd(int & fd, const void * with, size_t with_len) {
int pipes[2];
TRY("create buffer pipe", pipe(pipes));
TRY("create buffer pipe", pipe2(pipes, O_CLOEXEC));
quickscope_wrapper pipes_w_deleter{[=] { close(pipes[1]); }};
fd = pipes[0];
@ -34,7 +36,7 @@ int filled_fd(int & fd, const void * with, size_t with_len) {
int read_exact(const char * path, void * data, size_t len) {
auto infd = TRY("open input file", open(path, O_RDONLY));
auto infd = TRY("open input file", open(path, O_RDONLY | O_CLOEXEC));
quickscope_wrapper infd_deleter{[=] { close(infd); }};
while(len)
@ -49,8 +51,8 @@ int read_exact(const char * path, void * data, size_t len) {
int write_exact(const char * path, const void * data, size_t len, mode_t mode) {
auto outfd = TRY("create output file", open(path, O_WRONLY | O_CREAT | O_EXCL, mode));
quickscope_wrapper infd_deleter{[=] { close(outfd); }};
auto outfd = TRY("create output file", open(path, O_WRONLY | O_CREAT | O_EXCL | O_CLOEXEC, mode));
quickscope_wrapper outfd_deleter{[=] { close(outfd); }};
while(len) {
const auto rd = TRY("write to output file", write(outfd, data, len));
@ -62,6 +64,76 @@ int write_exact(const char * path, const void * data, size_t len, mode_t mode) {
}
#define TRY_HELPER(what, ...) TRY_GENERIC(what, , == -1, errno, -1, strerror, __VA_ARGS__)
/// TRY_MAIN rules, plus -1 for ENOENT
static int get_key_material_helper(const char * helper, const char * whom, bool again, bool newkey, uint8_t *& buf, size_t & len_out) {
#if __linux__ || __FreeBSD__
auto outfd = TRY_HELPER("create helper output", memfd_create(whom, MFD_CLOEXEC));
#else
int outfd;
char fname[8 + 10 + 1 + 20 + 1]; // 4294967296, 18446744073709551616
auto pid = getpid();
for(uint64_t i = 0; i < UINT64_MAX; ++i) {
snprintf(fname, sizeof(fname), "/tzpfms:%" PRIu32 ":%" PRIu64 "", static_cast<uint32_t>(pid), i);
if((outfd = shm_open(fname, O_RDWR | O_CREAT | O_EXCL | O_CLOEXEC, 0000)) != -1 || errno != EEXIST)
break;
}
TRY_HELPER("create helper output", outfd);
shm_unlink(fname);
#endif
quickscope_wrapper outfd_deleter{[=] { close(outfd); }};
switch(auto pid = TRY_HELPER("create child", fork())) {
case 0: // child
dup2(outfd, 1);
char * msg;
if(asprintf(&msg, "%sassphrase for %s%s", newkey ? "New p" : "P", whom, again ? " (again)" : "") == -1)
msg = const_cast<char *>(whom);
execl("/bin/sh", "sh", "-c", helper, helper, msg, whom, newkey ? "new" : "", again ? "again" : "", nullptr);
fprintf(stderr, "exec(/bin/sh): %s\n", strerror(errno));
_exit(127);
break;
default: // parent
int err, ret;
while((ret = waitpid(pid, &err, 0)) == -1 && errno == EINTR)
;
TRY("wait for helper", ret);
if(WIFEXITED(err)) {
switch(WEXITSTATUS(err)) {
case 0:
struct stat sb;
fstat(outfd, &sb);
if(auto out = mmap(nullptr, sb.st_size, PROT_READ, MAP_PRIVATE | MAP_POPULATE, outfd, 0); out != MAP_FAILED) {
quickscope_wrapper out_deleter{[=] { munmap(out, sb.st_size); }};
buf = static_cast<uint8_t *>(malloc(sb.st_size)); // TODO:if failed
len_out = sb.st_size;
memcpy(buf, out, sb.st_size);
// Trim ending newline, if any
if(buf[len_out - 1] == '\n')
buf[--len_out] = '\0';
return 0;
} else
; // error
case 127: // enoent, error already written by shell or child
return -1;
default:
fprintf(stderr, "Helper '%s' failed with %d.\n", helper, WEXITSTATUS(err));
return __LINE__;
}
} else {
fprintf(stderr, "Helper '%s' died to signal %d: %s.\n", helper, WTERMSIG(err), strsignal(WTERMSIG(err)));
return __LINE__;
}
}
}
/// Adapted from src:zfs's lib/libzfs/libzfs_crypto.c#get_key_material_raw()
static int get_key_material_raw(const char * whom, bool again, bool newkey, uint8_t *& buf, size_t & len_out) {
static int caught_interrupt;
@ -79,7 +151,10 @@ static int get_key_material_raw(const char * whom, bool again, bool newkey, uint
sigemptyset(&act.sa_mask);
caught_interrupt = 0;
act.sa_handler = [](auto sig) { caught_interrupt = sig; };
act.sa_handler = [](auto sig) {
caught_interrupt = sig;
fputs("^C\n", stderr);
};
sigaction(SIGINT, &act, &osigint);
act.sa_handler = SIG_IGN;
@ -105,7 +180,7 @@ static int get_key_material_raw(const char * whom, bool again, bool newkey, uint
// If we caught a signal, re-throw it now
if(caught_interrupt != 0)
kill(getpid(), caught_interrupt);
raise(caught_interrupt);
// Print the newline that was not echoed
putchar('\n');
@ -128,10 +203,8 @@ static int get_key_material_raw(const char * whom, bool again, bool newkey, uint
break;
default:
// Trim ending newline, if any
if(buf[bytes - 1] == '\n') {
buf[bytes - 1] = '\0';
--bytes;
}
if(buf[bytes - 1] == '\n')
buf[--bytes] = '\0';
break;
}
@ -139,8 +212,20 @@ static int get_key_material_raw(const char * whom, bool again, bool newkey, uint
return 0;
}
static int get_key_material_dispatch(const char * whom, bool again, bool newkey, uint8_t *& buf, size_t & len_out) {
static const char * helper = getenv("TZPFMS_PASSPHRASE_HELPER");
if(helper && *helper) {
if(auto err = get_key_material_helper(helper, whom, again, newkey, buf, len_out); err != -1)
return err;
else
helper = nullptr;
}
return get_key_material_raw(whom, again, newkey, buf, len_out);
}
int read_known_passphrase(const char * whom, uint8_t *& buf, size_t & len_out, size_t max_len) {
TRY_MAIN(get_key_material_raw(whom, false, false, buf, len_out));
TRY_MAIN(get_key_material_dispatch(whom, false, false, buf, len_out));
if(len_out <= max_len)
return 0;
@ -154,7 +239,7 @@ int read_known_passphrase(const char * whom, uint8_t *& buf, size_t & len_out, s
int read_new_passphrase(const char * whom, uint8_t *& buf, size_t & len_out, size_t max_len) {
uint8_t * first_passphrase{};
size_t first_passphrase_len{};
TRY_MAIN(get_key_material_raw(whom, false, true, first_passphrase, first_passphrase_len));
TRY_MAIN(get_key_material_dispatch(whom, false, true, first_passphrase, first_passphrase_len));
quickscope_wrapper first_passphrase_deleter{[&] { free(first_passphrase); }};
if(first_passphrase_len != 0 && first_passphrase_len < MIN_PASSPHRASE_LEN)
@ -164,7 +249,7 @@ int read_new_passphrase(const char * whom, uint8_t *& buf, size_t & len_out, siz
uint8_t * second_passphrase{};
size_t second_passphrase_len{};
TRY_MAIN(get_key_material_raw(whom, true, true, second_passphrase, second_passphrase_len));
TRY_MAIN(get_key_material_dispatch(whom, true, true, second_passphrase, second_passphrase_len));
quickscope_wrapper second_passphrase_deleter{[&] { free(second_passphrase); }};
if(second_passphrase_len != first_passphrase_len || memcmp(first_passphrase, second_passphrase, first_passphrase_len))

View File

@ -37,5 +37,5 @@ extern int write_exact(const char * path, const void * data, size_t len, mode_t
/// Prompt for passphrase for whom the user knows, up to max_len bytes
extern int read_known_passphrase(const char * whom, uint8_t *& buf, size_t & len_out, size_t max_len = SIZE_MAX);
/// Prompt twive for passphrase for whom the user is setting
/// Prompt twice for passphrase for whom the user is setting
extern int read_new_passphrase(const char * whom, uint8_t *& buf, size_t & len_out, size_t max_len = SIZE_MAX);

View File

@ -45,8 +45,8 @@ TPM2B_DATA tpm2_creation_metadata(const char * dataset_name) {
const auto now = time(nullptr);
const auto now_tm = localtime(&now);
metadata.size = snprintf((char *)metadata.buffer, sizeof(metadata.buffer), "%s %d-%02d-%02dT%02d:%02d:%02d %s", dataset_name, //
now_tm->tm_year + 1900, now_tm->tm_mon + 1, now_tm->tm_mday, now_tm->tm_hour, now_tm->tm_min, now_tm->tm_sec, //
TZPFMS_VERSION) +
now_tm->tm_year + 1900, now_tm->tm_mon + 1, now_tm->tm_mday, now_tm->tm_hour, now_tm->tm_min, now_tm->tm_sec, //
TZPFMS_VERSION) +
1;
metadata.size = metadata.size > sizeof(metadata.buffer) ? sizeof(metadata.buffer) : metadata.size;
@ -102,8 +102,8 @@ static int tpm2_find_unused_persistent_non_platform(ESYS_CONTEXT * tpm2_ctx, TPM
return 0;
}
int tpm2_seal(ESYS_CONTEXT * tpm2_ctx, ESYS_TR tpm2_session, TPMI_DH_PERSISTENT & persistent_handle, const TPM2B_DATA & metadata, void * data,
size_t data_len) {
int tpm2_seal(const char * dataset, ESYS_CONTEXT * tpm2_ctx, ESYS_TR tpm2_session, TPMI_DH_PERSISTENT & persistent_handle, const TPM2B_DATA & metadata,
void * data, size_t data_len) {
ESYS_TR primary_handle = ESYS_TR_NONE;
quickscope_wrapper primary_handle_deleter{[&] { Esys_FlushContext(tpm2_ctx, primary_handle); }};
@ -129,7 +129,7 @@ int tpm2_seal(ESYS_CONTEXT * tpm2_ctx, ESYS_TR tpm2_session, TPMI_DH_PERSISTENT
TPM2B_CREATION_DATA * creation_data{};
TPM2B_DIGEST * creation_hash{};
TPMT_TK_CREATION * creation_ticket{};
TRY_MAIN(try_or_passphrase("create primary encryption key", "owner hierarchy", tpm2_ctx, TPM2_RC_BAD_AUTH, ESYS_TR_RH_OWNER, [&] {
TRY_MAIN(try_or_passphrase("create primary encryption key", "TPM2 owner hierarchy", tpm2_ctx, TPM2_RC_BAD_AUTH, ESYS_TR_RH_OWNER, [&] {
return Esys_CreatePrimary(tpm2_ctx, ESYS_TR_RH_OWNER, tpm2_session, ESYS_TR_NONE, ESYS_TR_NONE, &primary_sens, &pub, &metadata, &pcrs, &primary_handle,
&public_ret, &creation_data, &creation_hash, &creation_ticket);
}));
@ -166,9 +166,13 @@ int tpm2_seal(ESYS_CONTEXT * tpm2_ctx, ESYS_TR tpm2_session, TPMI_DH_PERSISTENT
memcpy(secret_sens.sensitive.data.buffer, data, secret_sens.sensitive.data.size);
{
char what_for[ZFS_MAX_DATASET_NAME_LEN + 38 + 1];
snprintf(what_for, sizeof(what_for), "%s TPM2 wrapping key (or empty for none)", dataset);
uint8_t * passphrase{};
size_t passphrase_len{};
TRY_MAIN(read_new_passphrase("wrapping key (or empty for none)", passphrase, passphrase_len, sizeof(TPM2B_SENSITIVE_CREATE::sensitive.userAuth.buffer)));
TRY_MAIN(read_new_passphrase("%s TPM2 wrapping key (or empty for none)", passphrase, passphrase_len,
sizeof(TPM2B_SENSITIVE_CREATE::sensitive.userAuth.buffer)));
quickscope_wrapper passphrase_deleter{[&] { free(passphrase); }};
secret_sens.sensitive.userAuth.size = passphrase_len;
@ -214,14 +218,17 @@ int tpm2_seal(ESYS_CONTEXT * tpm2_ctx, ESYS_TR tpm2_session, TPMI_DH_PERSISTENT
return 0;
}
int tpm2_unseal(ESYS_CONTEXT * tpm2_ctx, ESYS_TR tpm2_session, TPMI_DH_PERSISTENT persistent_handle, void * data, size_t data_len) {
int tpm2_unseal(const char * dataset, ESYS_CONTEXT * tpm2_ctx, ESYS_TR tpm2_session, TPMI_DH_PERSISTENT persistent_handle, void * data, size_t data_len) {
char what_for[ZFS_MAX_DATASET_NAME_LEN + 18 + 1];
snprintf(what_for, sizeof(what_for), "%s TPM2 wrapping key", dataset);
// Entirely fake and not flushable (tpm:parameter(1):value is out of range or is not correct for the context)
ESYS_TR pandle;
TRY_TPM2("convert persistent handle to object", Esys_TR_FromTPMPublic(tpm2_ctx, persistent_handle, ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE, &pandle));
TPM2B_SENSITIVE_DATA * unsealed{};
quickscope_wrapper unsealed_deleter{[=] { Esys_Free(unsealed); }};
TRY_MAIN(try_or_passphrase("unseal wrapping key", "wrapping key", tpm2_ctx, TPM2_RC_AUTH_FAIL, pandle,
TRY_MAIN(try_or_passphrase("unseal wrapping key", what_for, tpm2_ctx, TPM2_RC_AUTH_FAIL, pandle,
[&] { return Esys_Unseal(tpm2_ctx, pandle, tpm2_session, ESYS_TR_NONE, ESYS_TR_NONE, &unsealed); }));
if(unsealed->size != data_len)
@ -236,7 +243,7 @@ int tpm2_free_persistent(ESYS_CONTEXT * tpm2_ctx, ESYS_TR tpm2_session, TPMI_DH_
TRY_TPM2("convert persistent handle to object", Esys_TR_FromTPMPublic(tpm2_ctx, persistent_handle, ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE, &pandle));
ESYS_TR new_handle;
TRY_MAIN(try_or_passphrase("unpersist object", "owner hierarchy", tpm2_ctx, TPM2_RC_BAD_AUTH, ESYS_TR_RH_OWNER,
TRY_MAIN(try_or_passphrase("unpersist object", "TPM2 owner hierarchy", tpm2_ctx, TPM2_RC_BAD_AUTH, ESYS_TR_RH_OWNER,
[&] { return Esys_EvictControl(tpm2_ctx, ESYS_TR_RH_OWNER, pandle, tpm2_session, ESYS_TR_NONE, ESYS_TR_NONE, 0, &new_handle); }));
return 0;

View File

@ -48,7 +48,7 @@ extern TPM2B_DATA tpm2_creation_metadata(const char * dataset_name);
extern int tpm2_parse_handle(const char * dataset_name, const char * handle_s, TPMI_DH_PERSISTENT & handle);
extern int tpm2_generate_rand(ESYS_CONTEXT * tpm2_ctx, void * into, size_t length);
extern int tpm2_seal(ESYS_CONTEXT * tpm2_ctx, ESYS_TR tpm2_session, TPMI_DH_PERSISTENT & persistent_handle, const TPM2B_DATA & metadata, void * data,
size_t data_len);
extern int tpm2_unseal(ESYS_CONTEXT * tpm2_ctx, ESYS_TR tpm2_session, TPMI_DH_PERSISTENT persistent_handle, void * data, size_t data_len);
extern int tpm2_seal(const char * dataset, ESYS_CONTEXT * tpm2_ctx, ESYS_TR tpm2_session, TPMI_DH_PERSISTENT & persistent_handle, const TPM2B_DATA & metadata,
void * data, size_t data_len);
extern int tpm2_unseal(const char * dataset, ESYS_CONTEXT * tpm2_ctx, ESYS_TR tpm2_session, TPMI_DH_PERSISTENT persistent_handle, void * data, size_t data_len);
extern int tpm2_free_persistent(ESYS_CONTEXT * tpm2_ctx, ESYS_TR tpm2_session, TPMI_DH_PERSISTENT persistent_handle);

View File

@ -20,11 +20,10 @@
/// Mimic libzfs error output
#define REQUIRE_KEY_LOADED(dataset) \
do { \
if(zfs_prop_get_int(dataset, ZFS_PROP_KEYSTATUS) == ZFS_KEYSTATUS_UNAVAILABLE) { \
return fprintf(stderr, "Key change error: Key must be loaded.\n"), __LINE__; \
} \
#define REQUIRE_KEY_LOADED(dataset) \
do { \
if(zfs_prop_get_int(dataset, ZFS_PROP_KEYSTATUS) == ZFS_KEYSTATUS_UNAVAILABLE) \
return fprintf(stderr, "Key change error: Key must be loaded.\n"), __LINE__; \
} while(0)