tzpfms/src/bin/zfs-tpm1x-load-key.cpp

82 lines
3.3 KiB
C++

/* SPDX-License-Identifier: MIT */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "../fd.hpp"
#include "../main.hpp"
#include "../tpm1x.hpp"
#include "../zfs.hpp"
#define THIS_BACKEND "TPM1.X"
int main(int argc, char ** argv) {
auto noop = false;
return do_main(
argc, argv, "n", "[-n]", [&](auto) { noop = true; },
[&](auto dataset) {
/// Vaguely based on tpmUnsealFile(3) from src:tpm-tools.
char * handle_s{};
TRY_MAIN(parse_key_props(dataset, THIS_BACKEND, handle_s));
tpm1x_handle handle{};
TRY_MAIN(tpm1x_parse_handle(zfs_get_name(dataset), handle_s, handle));
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?)", "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); }};
TSS_HPOLICY parent_key_policy{};
TRY_TPM1X("create sealant key policy", Tspi_Context_CreateObject(ctx, TSS_OBJECT_TYPE_POLICY, TSS_POLICY_USAGE, &parent_key_policy));
TRY_TPM1X("assign policy to sealant key", Tspi_Policy_AssignToObject(parent_key_policy, parent_key));
quickscope_wrapper parent_key_policy_deleter{[&] {
Tspi_Policy_FlushSecret(parent_key_policy);
Tspi_Context_CloseObject(ctx, parent_key_policy);
}};
TRY_TPM1X("assign default sealant key secret",
Tspi_Policy_SetSecret(parent_key_policy, TSS_SECRET_MODE_SHA1, sizeof(parent_key_secret), (BYTE *)parent_key_secret));
TSS_HOBJECT sealed_object{};
TSS_HPOLICY sealed_object_policy{};
TRY_MAIN(tpm1x_prep_sealed_object(ctx, sealed_object, sealed_object_policy));
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 + 512 + 1];
// %s=dataset name, then TPM1.x. noun for "Enter passphrase for" prompt
snprintf(what_for, sizeof(what_for), gettext("%s %s wrapping key"), zfs_get_name(dataset), THIS_BACKEND);
uint8_t * loaded_wrap_key{};
uint32_t loaded_wrap_key_len{};
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)) {
// 0A1234... follows
fprintf(stderr, gettext("Wrong sealed data length (%u != %zu): "), loaded_wrap_key_len, sizeof(wrap_key));
for(auto i = 0u; i < loaded_wrap_key_len; ++i)
fprintf(stderr, "%02hhX", loaded_wrap_key[i]);
fprintf(stderr, "\n");
return __LINE__;
}
memcpy(wrap_key, loaded_wrap_key, sizeof(wrap_key));
return 0;
}));
TRY_MAIN(load_key(dataset, wrap_key, noop));
return 0;
});
}