~nabijaczleweli/tzpfms

92f6927a08787fed5dfb04efe18b49df1048607b — наб a month ago 1d03292
Migrate some meaty zfs funxions out
M src/bin/zfs-tpm1x-change-key.cpp => src/bin/zfs-tpm1x-change-key.cpp +3 -52
@@ 40,40 40,7 @@ int main(int argc, char ** argv) {
		    REQUIRE_KEY_LOADED(dataset);


		    // TSS_RESULT Tspi_Context_Create(TSS_HCONTEXT* phContext);
		    // TSS_RESULT Tspi_Context_Connect(TSS_HCONTEXT hLocalContext, UNICODE* wszDestination);
		    // TSS_RESULT Tspi_Context_GetTpmObject(TSS_HCONTEXT hContext, TSS_HTPM* phTPM);
		    //
		    // TSS_RESULT Tspi_TPM_GetRandom(TSS_HTPM hTPM, UINT32 size, BYTE** random);
		    //
		    //
		    // TSS_RESULT Tspi_Context_LoadKeyByUUID(TSS_HCONTEXT hContext, TSS_FLAG persistentStorageType,
		    //                                       TSS_UUID     uuidData, TSS_HKEY* phKey);
		    //
		    //
		    // TSS_RESULT Tspi_Context_CreateObject(TSS_HCONTEXT hContext,  TSS_FLAG     objectType,
		    //                                      TSS_FLAG     initFlags, TSS_HOBJECT* phObject);
		    // TSS_RESULT Tspi_Key_CreateKey(TSS_HKEY hKey, TSS_HKEY hWrappingKey, TSS_HPCRS hPcrComposite);
		    //
		    //
		    // TSS_RESULT Tspi_Data_Seal(TSS_HENCDATA hEncData,     TSS_HKEY hEncKey,
		    //                           UINT32       ulDataLength, BYTE*    rgbDataToSeal,
		    //                           TSS_HPCRS    hPcrComposite);
		    //
		    //
		    // TSS_RESULT Tspi_Policy_SetSecret(TSS_HPOLICY hPolicy,        TSS_FLAG secretMode,
		    //                                  UINT32      ulSecretLength, BYTE*    rgbSecret);
		    //
		    // TSS_RESULT Tspi_Policy_AssignToObject(TSS_HPOLICY hPolicy, TSS_HOBJECT hObject);
		    //
		    // TSS_RESULT Tspi_Context_FreeMemory(TSS_HCONTEXT hContext, BYTE* rgbMemory);
		    // TSS_RESULT Tspi_Context_Close(TSS_HCONTEXT hLocalContext);
		    //
		    //
		    // TSS_RESULT Tspi_GetAttribData(TSS_HOBJECT hObject, TSS_FLAG attribFlag,
		    //                               TSS_FLAG    subFlag, UINT32*  pulAttribDataSize,
		    //                               BYTE**      prgbAttribData);

		    /// Mostly based on See tpm_sealdata(1) from tpm-tools.

		    // All memory lives as long as this does
		    TSS_HCONTEXT ctx{};


@@ 230,29 197,13 @@ int main(int argc, char ** argv) {
			    *cur++ = ':';
			    for(auto i = 0u; i < sealed_object_blob_len; ++i, cur += 2)
				    sprintf(cur, "%02X", sealed_object_blob[i]);
				  *cur++ = '\0';
			    *cur++ = '\0';
		    }
		    fprintf(stderr, "%s\n", handle);
		    TRY_MAIN(set_key_props(dataset, THIS_BACKEND, handle));

		    /// zfs_crypto_rewrap() with "prompt" reads from stdin, but not if it's a TTY;
		    /// this user-proofs the set-up, and means we don't have to touch the filesysten:
		    /// instead, get an FD, write the raw key data there, dup() it onto stdin,
		    /// let libzfs read it, then restore stdin

		    int key_fd;
		    TRY_MAIN(filled_fd(key_fd, wrap_key, WRAPPING_KEY_LEN));
		    quickscope_wrapper key_fd_deleter{[=] { close(key_fd); }};


		    TRY_MAIN(with_stdin_at(key_fd, [&] {
			    if(zfs_crypto_rewrap(dataset, TRY_PTR("get rewrap args", rewrap_args()), B_FALSE))
				    return __LINE__;  // Error printed by libzfs
			    else
				    printf("Key for %s changed\n", zfs_get_name(dataset));

			    return 0;
		    }));
		    TRY_MAIN(change_key(dataset, wrap_key));

		    // ok = true;
		    // return 0;

M src/bin/zfs-tpm2-change-key.cpp => src/bin/zfs-tpm2-change-key.cpp +1 -18
@@ 89,24 89,7 @@ int main(int argc, char ** argv) {
				    TRY_MAIN(set_key_props(dataset, THIS_BACKEND, persistent_handle_s));
			    }

			    /// zfs_crypto_rewrap() with "prompt" reads from stdin, but not if it's a TTY;
			    /// this user-proofs the set-up, and means we don't have to touch the filesysten:
			    /// instead, get an FD, write the raw key data there, dup() it onto stdin,
			    /// let libzfs read it, then restore stdin

			    int key_fd;
			    TRY_MAIN(filled_fd(key_fd, wrap_key, WRAPPING_KEY_LEN));
			    quickscope_wrapper key_fd_deleter{[=] { close(key_fd); }};


			    TRY_MAIN(with_stdin_at(key_fd, [&] {
				    if(zfs_crypto_rewrap(dataset, TRY_PTR("get rewrap args", rewrap_args()), B_FALSE))
					    return __LINE__;  // Error printed by libzfs
				    else
					    printf("Key for %s changed\n", zfs_get_name(dataset));

				    return 0;
			    }));
			    TRY_MAIN(change_key(dataset, wrap_key));

			    ok = true;
			    return 0;

M src/bin/zfs-tpm2-clear-key.cpp => src/bin/zfs-tpm2-clear-key.cpp +5 -1
@@ 19,8 19,12 @@ int main(int argc, char ** argv) {
	    [&](auto dataset) {
		    REQUIRE_KEY_LOADED(dataset);

		    char * persistent_handle_s{};
		    TRY_MAIN(parse_key_props(dataset, THIS_BACKEND, persistent_handle_s));

		    TPMI_DH_PERSISTENT persistent_handle{};
		    TRY_MAIN(parse_key_props(dataset, THIS_BACKEND, persistent_handle));
		    TRY_MAIN(tpm2_parse_handle(zfs_get_name(dataset), persistent_handle_s, persistent_handle));


		    if(zfs_crypto_rewrap(dataset, TRY_PTR("get clear rewrap args", clear_rewrap_args()), B_FALSE))
			    return __LINE__;  // Error printed by libzfs

M src/bin/zfs-tpm2-load-key.cpp => src/bin/zfs-tpm2-load-key.cpp +7 -17
@@ 17,12 17,15 @@


int main(int argc, char ** argv) {
	auto noop = B_FALSE;
	auto noop = false;
	return do_main(
	    argc, argv, "n", "[-n]", [&](auto) { noop = B_TRUE; },
	    argc, argv, "n", "[-n]", [&](auto) { noop = true; },
	    [&](auto dataset) {
		    char * handle_s{};
		    TRY_MAIN(parse_key_props(dataset, THIS_BACKEND, handle_s));

		    TPMI_DH_PERSISTENT handle{};
		    TRY_MAIN(parse_key_props(dataset, THIS_BACKEND, handle));
		    TRY_MAIN(tpm2_parse_handle(zfs_get_name(dataset), handle_s, handle));


		    uint8_t wrap_key[WRAPPING_KEY_LEN];


@@ 32,20 35,7 @@ int main(int argc, char ** argv) {
		    }));


		    int key_fd;
		    TRY_MAIN(filled_fd(key_fd, (void *)wrap_key, sizeof(wrap_key)));
		    quickscope_wrapper key_fd_deleter{[=] { close(key_fd); }};


		    TRY_MAIN(with_stdin_at(key_fd, [&] {
			    if(zfs_crypto_load_key(dataset, noop, nullptr))
				    return __LINE__;  // Error printed by libzfs
			    else
				    printf("Key for %s %s\n", zfs_get_name(dataset), noop ? "OK" : "loaded");

			    return 0;
		    }));

		    TRY_MAIN(load_key(dataset, wrap_key, noop));
		    return 0;
	    });
}

M src/tpm2.cpp => src/tpm2.cpp +16 -4
@@ 3,6 3,7 @@

#include "tpm2.hpp"
#include "main.hpp"
#include "parse.hpp"

#include <algorithm>
#include <time.h>


@@ 24,6 25,16 @@ TPM2B_DATA tpm2_creation_metadata(const char * dataset_name) {
}


int tpm2_parse_handle(const char * dataset_name, const char * handle_s, TPMI_DH_PERSISTENT & handle) {
	if(parse_int(handle_s, handle)) {
		fprintf(stderr, "Dataset %s's handle %s not valid.\n", dataset_name, handle_s);
		return __LINE__;
	}

	return 0;
}


int tpm2_generate_rand(ESYS_CONTEXT * tpm2_ctx, void * into, size_t length) {
	TPM2B_DIGEST * rand{};
	TRY_TPM2("get random data from TPM", Esys_GetRandom(tpm2_ctx, ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE, length, &rand));


@@ 42,7 53,7 @@ int tpm2_generate_rand(ESYS_CONTEXT * tpm2_ctx, void * into, size_t length) {
static int tpm2_find_unused_persistent_non_platform(ESYS_CONTEXT * tpm2_ctx, TPMI_DH_PERSISTENT & persistent_handle) {
	TPMS_CAPABILITY_DATA * cap;  // TODO: check for more data?
	TRY_TPM2("Read used persistent TPM handles", Esys_GetCapability(tpm2_ctx, ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE, TPM2_CAP_HANDLES, TPM2_PERSISTENT_FIRST,
	                                                    TPM2_MAX_CAP_HANDLES, nullptr, &cap));
	                                                                TPM2_MAX_CAP_HANDLES, nullptr, &cap));
	quickscope_wrapper cap_deleter{[=] { Esys_Free(cap); }};

	persistent_handle = 0;


@@ 94,8 105,9 @@ 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_TPM2("create primary encryption key", 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));
		TRY_TPM2("create primary encryption key",
		         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));
		quickscope_wrapper creation_ticket_deleter{[=] { Esys_Free(creation_ticket); }};
		quickscope_wrapper creation_hash_deleter{[=] { Esys_Free(creation_hash); }};
		quickscope_wrapper creation_data_deleter{[=] { Esys_Free(creation_data); }};


@@ 141,7 153,7 @@ int tpm2_seal(ESYS_CONTEXT * tpm2_ctx, ESYS_TR tpm2_session, TPMI_DH_PERSISTENT 
		TPM2B_DIGEST * creation_hash{};
		TPMT_TK_CREATION * creation_ticket{};
		TRY_TPM2("create key seal", Esys_Create(tpm2_ctx, primary_handle, tpm2_session, ESYS_TR_NONE, ESYS_TR_NONE, &secret_sens, &pub, &metadata, &pcrs,
		                                      &sealant_private, &sealant_public, &creation_data, &creation_hash, &creation_ticket));
		                                        &sealant_private, &sealant_public, &creation_data, &creation_hash, &creation_ticket));
		quickscope_wrapper creation_ticket_deleter{[=] { Esys_Free(creation_ticket); }};
		quickscope_wrapper creation_hash_deleter{[=] { Esys_Free(creation_hash); }};
		quickscope_wrapper creation_data_deleter{[=] { Esys_Free(creation_data); }};

M src/tpm2.hpp => src/tpm2.hpp +3 -0
@@ 46,6 46,9 @@ int with_tpm2_session(F && func) {

extern TPM2B_DATA tpm2_creation_metadata(const char * dataset_name);

/// Parse a persistent handle name as stored in a ZFS property
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);

M src/zfs.cpp => src/zfs.cpp +4 -10
@@ 4,7 4,6 @@
#include "zfs.hpp"
#include "common.hpp"
#include "main.hpp"
#include "parse.hpp"

#include <libzfs.h>



@@ 102,8 101,8 @@ int clear_key_props(zfs_handle_t * from) {
}


int parse_key_props(zfs_handle_t * in, const char * our_backend, uint32_t & handle) {
	char *backend{}, *handle_s{};
int parse_key_props(zfs_handle_t * in, const char * our_backend, char *& handle) {
	char *backend{};
	TRY_MAIN(lookup_userprop(in, PROPNAME_BACKEND, backend));

	if(!backend) {


@@ 115,16 114,11 @@ int parse_key_props(zfs_handle_t * in, const char * our_backend, uint32_t & hand
		return __LINE__;
	}

	TRY_MAIN(lookup_userprop(in, PROPNAME_KEY, handle_s));
	if(!handle_s) {
	TRY_MAIN(lookup_userprop(in, PROPNAME_KEY, handle));
	if(!handle) {
		fprintf(stderr, "Dataset %s missing key data.\n", zfs_get_name(in));
		return __LINE__;
	}

	if(parse_int(handle_s, handle)) {
		fprintf(stderr, "Dataset %s's handle %s not valid.\n", zfs_get_name(in), handle_s);
		return __LINE__;
	}

	return 0;
}

M src/zfs.hpp => src/zfs.hpp +12 -1
@@ 42,4 42,15 @@ extern int set_key_props(zfs_handle_t * on, const char * backend, const char * h
extern int clear_key_props(zfs_handle_t * from);

/// Read in decoding props from the dataset
extern int parse_key_props(zfs_handle_t * in, const char * our_backend, uint32_t & handle);
extern int parse_key_props(zfs_handle_t * in, const char * our_backend, char *& handle);


/// Rewrap key on on to wrap_key.
///
/// wrap_key must be WRAPPING_KEY_LEN long.
extern int change_key(zfs_handle_t * on, const uint8_t * wrap_key);

/// (Try to) load key wrap_key for for_d.
///
/// wrap_key must be WRAPPING_KEY_LEN long.
extern int load_key(zfs_handle_t * for_d, const uint8_t * wrap_key, bool noop);

A src/zfs_meat.cpp => src/zfs_meat.cpp +49 -0
@@ 0,0 1,49 @@
/* SPDX-License-Identifier: MIT */


#include "fd.hpp"
#include "main.hpp"
#include "zfs.hpp"

#include <libzfs.h>
// #include <sys/zio_crypt.h>
#define WRAPPING_KEY_LEN 32


template <class F>
static int with_stdin_at_buffer(const void * buf, size_t buf_len, F && func) {
	int key_fd;
	TRY_MAIN(filled_fd(key_fd, buf, buf_len));
	quickscope_wrapper key_fd_deleter{[=] { close(key_fd); }};

	return with_stdin_at(key_fd, func);
}


int change_key(zfs_handle_t * on, const uint8_t * wrap_key) {
	/// zfs_crypto_rewrap() with "prompt" reads from stdin, but not if it's a TTY;
	/// this user-proofs the set-up, and means we don't have to touch the filesysten:
	/// instead, get an FD, write the raw key data there, dup() it onto stdin,
	/// let libzfs read it, then restore stdin

	return with_stdin_at_buffer(wrap_key, WRAPPING_KEY_LEN, [&] {
		if(zfs_crypto_rewrap(on, TRY_PTR("get rewrap args", rewrap_args()), B_FALSE))
			return __LINE__;  // Error printed by libzfs
		else
			printf("Key for %s changed\n", zfs_get_name(on));

		return 0;
	});
}


int load_key(zfs_handle_t * for_d, const uint8_t * wrap_key, bool noop) {
	return with_stdin_at_buffer(wrap_key, WRAPPING_KEY_LEN, [&] {
		if(zfs_crypto_load_key(for_d, noop ? B_TRUE : B_FALSE, nullptr))
			return __LINE__;  // Error printed by libzfs
		else
			printf("Key for %s %s\n", zfs_get_name(for_d), noop ? "OK" : "loaded");

		return 0;
	});
}