diff --git a/Makefile.am b/Makefile.am index 79dfd191a..5a4fdda90 100644 --- a/Makefile.am +++ b/Makefile.am @@ -203,7 +203,8 @@ tpm2_tools = \ tools/tpm2_ecdhzgen.c \ tools/tpm2_zgen2phase.c \ tools/tpm2_sessionconfig.c \ - tools/tpm2_getpolicydigest.c + tools/tpm2_getpolicydigest.c \ + tools/tpm2_pcrsetauthvalue.c # Create the symlinks for each tool to the tpm2 and optional tss2 bundled executables install-exec-hook: diff --git a/lib/tpm2.c b/lib/tpm2.c index fb1f0e9a9..2e2ea39bf 100644 --- a/lib/tpm2.c +++ b/lib/tpm2.c @@ -5842,6 +5842,28 @@ tool_rc tpm2_zgen2phase(ESYS_CONTEXT *esys_context, return tool_rc_success; } +tool_rc tpm2_pcr_setauthvalue(ESYS_CONTEXT *esys_context, + tpm2_loaded_object *pcrindex_auth_obj, const TPM2B_AUTH *pcrindex_newauth) { + + ESYS_TR shandle1 = ESYS_TR_NONE; + tool_rc rc = tpm2_auth_util_get_shandle(esys_context, + pcrindex_auth_obj->tr_handle, pcrindex_auth_obj->session, &shandle1); + if (rc != tool_rc_success) { + LOG_ERR("Failed to get shandle"); + return rc; + } + + TSS2_RC rval = Esys_PCR_SetAuthValue(esys_context, + pcrindex_auth_obj->tr_handle, shandle1, ESYS_TR_NONE, ESYS_TR_NONE, + pcrindex_newauth); + if (rval != TPM2_RC_SUCCESS) { + LOG_PERR(Esys_PCR_SetAuthValue, rval); + return tool_rc_from_tpm(rval); + } + + return rc; +} + tool_rc tpm2_getsapicontext(ESYS_CONTEXT *esys_context, TSS2_SYS_CONTEXT **sys_context) { diff --git a/lib/tpm2.h b/lib/tpm2.h index 52a89564f..ed0c8c604 100644 --- a/lib/tpm2.h +++ b/lib/tpm2.h @@ -552,6 +552,9 @@ tool_rc tpm2_zgen2phase(ESYS_CONTEXT *esys_context, TPM2B_ECC_POINT *Q2, TPM2B_ECC_POINT **Z1, TPM2B_ECC_POINT **Z2, TPMI_ECC_KEY_EXCHANGE keyexchange_scheme, UINT16 commit_counter); +tool_rc tpm2_pcr_setauthvalue(ESYS_CONTEXT *esys_context, + tpm2_loaded_object *pcrindex_auth_obj, const TPM2B_AUTH *pcrindex_newauth); + tool_rc tpm2_getsapicontext(ESYS_CONTEXT *esys_context, TSS2_SYS_CONTEXT **sys_context); diff --git a/lib/tpm2_util.c b/lib/tpm2_util.c index 5026848f6..afefbfc9b 100644 --- a/lib/tpm2_util.c +++ b/lib/tpm2_util.c @@ -614,6 +614,77 @@ ESYS_TR tpm2_tpmi_hierarchy_to_esys_tr(TPMI_RH_PROVISION inh) { return ESYS_TR_NONE; } +ESYS_TR tpm2_sys_pcrhandle_to_esys_tr(TPMI_DH_PCR sys_pcrhandle) { + + switch (sys_pcrhandle) { + case 0: + return ESYS_TR_PCR0; + case 1: + return ESYS_TR_PCR1; + case 2: + return ESYS_TR_PCR2; + case 3: + return ESYS_TR_PCR3; + case 4: + return ESYS_TR_PCR4; + case 5: + return ESYS_TR_PCR5; + case 6: + return ESYS_TR_PCR6; + case 7: + return ESYS_TR_PCR7; + case 8: + return ESYS_TR_PCR8; + case 9: + return ESYS_TR_PCR9; + case 10: + return ESYS_TR_PCR10; + case 11: + return ESYS_TR_PCR11; + case 12: + return ESYS_TR_PCR12; + case 13: + return ESYS_TR_PCR13; + case 14: + return ESYS_TR_PCR14; + case 15: + return ESYS_TR_PCR15; + case 16: + return ESYS_TR_PCR16; + case 17: + return ESYS_TR_PCR17; + case 18: + return ESYS_TR_PCR18; + case 19: + return ESYS_TR_PCR19; + case 20: + return ESYS_TR_PCR20; + case 21: + return ESYS_TR_PCR21; + case 22: + return ESYS_TR_PCR22; + case 23: + return ESYS_TR_PCR23; + case 24: + return ESYS_TR_PCR24; + case 25: + return ESYS_TR_PCR25; + case 26: + return ESYS_TR_PCR26; + case 27: + return ESYS_TR_PCR27; + case 28: + return ESYS_TR_PCR28; + case 29: + return ESYS_TR_PCR29; + case 30: + return ESYS_TR_PCR30; + case 31: + return ESYS_TR_PCR31; + } + return ESYS_TR_NONE; +} + tool_rc tpm2_util_sys_handle_to_esys_handle(ESYS_CONTEXT *context, TPM2_HANDLE sys_handle, ESYS_TR *esys_handle) { @@ -623,6 +694,12 @@ tool_rc tpm2_util_sys_handle_to_esys_handle(ESYS_CONTEXT *context, return tool_rc_success; } + h = tpm2_sys_pcrhandle_to_esys_tr(sys_handle); + if (h != ESYS_TR_NONE) { + *esys_handle = h; + return tool_rc_success; + } + return tpm2_from_tpm_public(context, sys_handle, ESYS_TR_NONE, ESYS_TR_NONE, ESYS_TR_NONE, esys_handle); } diff --git a/man/tpm2_pcrsetauthvalue.1.md b/man/tpm2_pcrsetauthvalue.1.md new file mode 100644 index 000000000..987b1c919 --- /dev/null +++ b/man/tpm2_pcrsetauthvalue.1.md @@ -0,0 +1,56 @@ +% tpm2_pcrsetauthvalue(1) tpm2-tools | General Commands Manual + +# NAME + +**tpm2_pcrsetauthvalue**(1) - Add or change the authvalue of a PCR handle which +is in the authorization set. + +# SYNOPSIS + +**tpm2_pcrsetauthvalue** [*OPTIONS*] [*ARGUMENT*] + +# DESCRIPTION + +**tpm2_pcrsetauthvalue**(1) - Add or change the authvalue of a PCR handle which +is in the authorization set. Only those PCR handles which are in the +authorization set can be specified. To retrieve which specific PCR handles in a +given TPM implementation are in the authorization set, run **tpm2_getcap** with +option **pcrhandles-with-auth**. + +# OPTIONS + + * **-P**, **\--auth**=_AUTH_: + + Specifies the existing authorization value for the PCR handle. + + * **\-p**, **\--newauth**=_AUTH_: + + Specifies the new authorization value to be set for the PCR handle. + + * **ARGUMENT** the command line argument specifies the PCR handle. + +## References + +[context object format](common/ctxobj.md) details the methods for specifying +_OBJECT_. + +[authorization formatting](common/authorizations.md) details the methods for +specifying _AUTH_. + +[common options](common/options.md) collection of common options that provide +information many users may expect. + +[common tcti options](common/tcti.md) collection of options used to configure +the various known TCTI modules. + +# EXAMPLES + +## Change authvalue of the PCR handle 20 + +```bash +tpm2_pcrsetauthvalue -p newauthvalue 0x00000014 +``` + +[returns](common/returns.md) + +[footer](common/footer.md) diff --git a/tools/tpm2_pcrsetauthvalue.c b/tools/tpm2_pcrsetauthvalue.c new file mode 100644 index 000000000..970b3f6d6 --- /dev/null +++ b/tools/tpm2_pcrsetauthvalue.c @@ -0,0 +1,242 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +#include +#include +#include + +#include "files.h" +#include "log.h" +#include "tpm2.h" +#include "tpm2_auth_util.h" +#include "tpm2_options.h" +#include "tpm2_tool.h" + +typedef struct tpm_pcr_setauthvalue_ctx tpm_pcr_setauthvalue_ctx; +#define MAX_SESSIONS 3 +#define MAX_AUX_SESSIONS 2 +struct tpm_pcr_setauthvalue_ctx { + /* + * Inputs + */ + struct { + const char *ctx_path; + const char *auth_str; + tpm2_loaded_object object; + } pcrindex_auth; + + char *pcrindex_auth_str; + TPM2B_AUTH pcrindex_newauth; + + /* + * Outputs + */ + + /* + * Parameter hashes + */ + + /* + * Aux sessions + */ +}; + +static tpm_pcr_setauthvalue_ctx ctx = { 0 }; + +static tool_rc pcr_set_authvalue(ESYS_CONTEXT *ectx) { + + tool_rc rc = tpm2_pcr_setauthvalue(ectx, &ctx.pcrindex_auth.object, + &ctx.pcrindex_newauth); + if (rc != tool_rc_success) { + LOG_ERR("Failed to set pcr authvalue"); + } + + return rc; +} + +static tool_rc process_output(ESYS_CONTEXT *ectx) { + + UNUSED(ectx); + + /* + * 1. Outputs that do not require TPM2_CC_ dispatch + */ + + /* + * 2. Outputs generated after TPM2_CC_ dispatch + */ + + return tool_rc_success; +} + +static tool_rc process_inputs(ESYS_CONTEXT *ectx) { + + /* + * 1. Object and auth initializations + */ + + /* + * 1.a Add the new-auth values to be set for the object. + */ + tpm2_session *tmp; + tool_rc rc = tpm2_auth_util_from_optarg(NULL, ctx.pcrindex_auth_str, &tmp, true); + if (rc != tool_rc_success) { + LOG_ERR("Error: cannot parse the pcrindex authvalue to be set"); + return rc; + } + const TPM2B_AUTH *auth = tpm2_session_get_auth_value(tmp); + ctx.pcrindex_newauth = *auth; + tpm2_session_close(&tmp); + + /* + * 1.b Add object names and their auth sessions + */ + rc = tpm2_util_object_load_auth(ectx, ctx.pcrindex_auth.ctx_path, + ctx.pcrindex_auth.auth_str, &ctx.pcrindex_auth.object, true, + TPM2_HANDLE_FLAGS_PCR); + if (rc != tool_rc_success) { + LOG_ERR("Invalid PCR Index or authorization."); + return tool_rc_option_error; + } + + /* + * 2. Restore auxiliary sessions + */ + + /* + * 3. Command specific initializations dependent on loaded objects + */ + + /* + * 4. Configuration for calculating the pHash + */ + + /* 4.a Determine pHash length and alg */ + + /* + * 4.b Determine if TPM2_CC_ is to be dispatched + * is_tcti_none [N] + * !rphash && !cphash [Y] + * !rphash && cphash [N] + * rphash && !cphash [Y] + * rphash && cphash [Y] + */ + + return rc; +} + +static tool_rc check_options(tpm2_option_flags flags) { + + UNUSED(flags); + + if (!ctx.pcrindex_auth.ctx_path) { + LOG_ERR("PCR Index must be specified as argument."); + return tool_rc_option_error; + } + + if (!ctx.pcrindex_auth_str) { + LOG_ERR("Authvalue to be set for PCR index must be specified."); + return tool_rc_option_error; + } + + return tool_rc_success; +} + +static bool on_option(char key, char *value) { + + switch (key) { + case 'P': + ctx.pcrindex_auth.auth_str = value; + break; + case 'p': + ctx.pcrindex_auth_str = value; + break; + } + + return true; +} + +static bool on_arg(int argc, char **argv) { + + UNUSED(argc); + + if (!argv) { + LOG_ERR("PCR Index must be specified"); + return false; + } + + ctx.pcrindex_auth.ctx_path = argv[0]; + + return true; +} + +static bool tpm2_tool_onstart(tpm2_options **opts) { + + const struct option topts[] = { + { "auth", required_argument, NULL, 'P' }, + { "newauth", required_argument, NULL, 'p' }, + }; + + *opts = tpm2_options_new("P:p:", ARRAY_LEN(topts), topts, on_option, + on_arg, 0); + + return *opts != NULL; +} + +static tool_rc tpm2_tool_onrun(ESYS_CONTEXT *ectx, tpm2_option_flags flags) { + + UNUSED(flags); + + /* + * 1. Process options + */ + tool_rc rc = check_options(flags); + if (rc != tool_rc_success) { + return rc; + } + + /* + * 2. Process inputs + */ + rc = process_inputs(ectx); + if (rc != tool_rc_success) { + return rc; + } + + /* + * 3. TPM2_CC_ call + */ + rc = pcr_set_authvalue(ectx); + if (rc != tool_rc_success) { + return rc; + } + /* + * 4. Process outputs + */ + return process_output(ectx); +} + +static tool_rc tpm2_tool_onstop(ESYS_CONTEXT *ectx) { + + UNUSED(ectx); + /* + * 1. Free objects + */ + + /* + * 2. Close authorization sessions + */ + tool_rc rc = tool_rc_success; + tool_rc tmp_rc = tpm2_session_close(&ctx.pcrindex_auth.object.session); + if (tmp_rc != tool_rc_success) { + rc = tmp_rc; + } + + /* + * 3. Close auxiliary sessions + */ + + return rc; +} + +// Register this tool with tpm2_tool.c +TPM2_TOOL_REGISTER("pcrsetauthvalue", tpm2_tool_onstart, tpm2_tool_onrun, + tpm2_tool_onstop, NULL)