[PATCH] implement policy_pcr commands to lock NV-indexes behind a PCR
Ilias Apalodimas
ilias.apalodimas at linaro.org
Wed Mar 27 15:47:00 CET 2024
Hi Niek,
On Thu, 7 Mar 2024 at 07:59, niek.nooijens at omron.com
<niek.nooijens at omron.com> wrote:
>
> Hi Illias
>
> I updated all the comments.
> I did note that the format in tpm-v2.h of the function description wasn't up to standard even for code I didn't create, so I fixed that as well.
> It's also pushed to my github:https://github.com/nieknooijens/u-boot/tree/tpm_policy_patch
Thanks, I'll have a look within the week. That being said, please try
to read the guidelines and send the patch properly using git-send
email if a new version is required, along with
- the version number in the topic
- a short description of the changes between revisions
I am receiving enough patches and it's pretty easy for me to lose
track without those
Thanks
/Ilias
>
> Here's the update:
>
> =======================START PATCH=========================
> From c0e213d45925da819d7ce41e02072ea740e44014 Mon Sep 17 00:00:00 2001
> From: Niek Nooijens <niek.nooijens at omron.com>
> Date: Tue, 20 Feb 2024 13:42:57 +0900
> Subject: [PATCH] [TPM] implement commands to lock NV-indexes behind a PCR
> policy
>
> Added commands are:
> - start auth session
> - flush context
> - policyPCR
> - getPolicyDigest
>
> Signed-off-by: Niek Nooijens <niek.nooijens at omron.com>
> ---
> cmd/tpm-v2.c | 247 +++++++++++++++++++++++++-
> include/tpm-common.h | 2 +
> include/tpm-v2.h | 375 +++++++++++++++++++++++----------------
> lib/tpm-v2.c | 413 ++++++++++++++++++++++++++++++++++---------
> lib/tpm_api.c | 4 +-
> 5 files changed, 806 insertions(+), 235 deletions(-)
>
> diff --git a/cmd/tpm-v2.c b/cmd/tpm-v2.c
> index 7e479b9dfe..5ba82602c2 100644
> --- a/cmd/tpm-v2.c
> +++ b/cmd/tpm-v2.c
> @@ -136,15 +136,12 @@ static int do_tpm_pcr_read(struct cmd_tbl *cmdtp, int flag, int argc,
>
> if (argc != 3)
> return CMD_RET_USAGE;
> -
> ret = get_tpm(&dev);
> if (ret)
> return ret;
> -
> priv = dev_get_uclass_priv(dev);
> if (!priv)
> return -EINVAL;
> -
> index = simple_strtoul(argv[1], NULL, 0);
> if (index >= priv->pcr_count)
> return -EINVAL;
> @@ -356,6 +353,207 @@ static int do_tpm_pcr_setauthvalue(struct cmd_tbl *cmdtp, int flag,
> key, key_sz));
> }
>
> +static int do_tpm_nv_define(struct cmd_tbl *cmdtp, int flag,
> + int argc, char *const argv[])
> +{
> + struct udevice *dev;
> + struct tpm_chip_priv *priv;
> + u32 nv_addr, nv_size, rc;
> + void *policy_addr = NULL;
> + size_t policy_size = 0;
> + int ret;
> +
> + u32 nv_attributes = TPMA_NV_PLATFORMCREATE | TPMA_NV_OWNERWRITE |\
> + TPMA_NV_OWNERREAD | TPMA_NV_PPWRITE | TPMA_NV_PPREAD;
> +
> + if (argc < 3 && argc > 7)
> + return CMD_RET_USAGE;
> +
> + ret = get_tpm(&dev);
> + if (ret)
> + return ret;
> +
> + priv = dev_get_uclass_priv(dev);
> + if (!priv)
> + return -EINVAL;
> +
> + nv_addr = simple_strtoul(argv[1], NULL, 0);
> + nv_size = simple_strtoul(argv[2], NULL, 0);
> + if (argc > 3)
> + nv_attributes = simple_strtoul(argv[3], NULL, 0);
> + if (argc > 4) {
> + policy_addr = map_sysmem(simple_strtoul(argv[4], NULL, 0), 0);
> + //POLICYREAD and POLICYWRITE are obligated when providing policy, so just force it
> + nv_attributes |= (TPMA_NV_POLICYREAD | TPMA_NV_POLICYWRITE);
> + if (argc < 5)
> + return CMD_RET_USAGE;
> + policy_size = simple_strtoul(argv[5], NULL, 0);
> + }
> +
> + rc = tpm2_nv_define_space(dev, nv_addr, nv_size, nv_attributes, policy_addr, policy_size);
> + if (rc)
> + printf("ERROR: nv_define #%u returns: 0x%x\n", nv_addr, rc);
> +
> + unmap_sysmem(policy_addr);
> +
> + return report_return_code(rc);
> +}
> +
> +static int do_tpm_nv_undefine(struct cmd_tbl *cmdtp, int flag,
> + int argc, char *const argv[])
> +{
> + struct udevice *dev;
> + u32 nv_addr, ret, rc;
> +
> + ret = get_tpm(&dev);
> + if (ret)
> + return ret;
> + if (argc != 2)
> + return CMD_RET_USAGE;
> +
> + nv_addr = simple_strtoul(argv[1], NULL, 0);
> + rc = tpm2_nv_undefine_space(dev, nv_addr);
> +
> + return report_return_code(rc);
> +}
> +
> +static int do_tpm_nv_read_value(struct cmd_tbl *cmdtp, int flag,
> + int argc, char *const argv[])
> +{
> + struct udevice *dev;
> + u32 nv_addr, nv_size, rc;
> + void *session_addr = NULL;
> + int ret;
> + void *out_data;
> +
> + ret = get_tpm(&dev);
> + if (ret)
> + return ret;
> + if (argc < 4)
> + return CMD_RET_USAGE;
> +
> + nv_addr = simple_strtoul(argv[1], NULL, 0);
> + nv_size = simple_strtoul(argv[2], NULL, 0);
> + out_data = map_sysmem(simple_strtoul(argv[3], NULL, 0), 0);
> + if (argc == 5)
> + session_addr = map_sysmem(simple_strtoul(argv[4], NULL, 0), 0);
> + //if session handle is NULL, Password authorization is used
> + rc = tpm2_nv_read_value(dev, nv_addr, out_data, nv_size, session_addr);
> +
> + if (rc)
> + printf("ERROR: nv_read #%u returns: #%u\n", nv_addr, rc);
> +
> + unmap_sysmem(out_data);
> + return report_return_code(rc);
> +}
> +
> +static int do_tpm_nv_write_value(struct cmd_tbl *cmdtp, int flag,
> + int argc, char *const argv[])
> +{
> + struct udevice *dev;
> + u32 nv_addr, nv_size, rc;
> + void *session_addr = NULL, *data_to_write = NULL;
> + int ret;
> +
> + ret = get_tpm(&dev);
> + if (ret)
> + return ret;
> + if (argc < 4)
> + return CMD_RET_USAGE;
> +
> + nv_addr = simple_strtoul(argv[1], NULL, 0); //tpm_addr
> + nv_size = simple_strtoul(argv[2], NULL, 0); //size
> + data_to_write = map_sysmem(simple_strtoul(argv[3], NULL, 0), 0);
> +
> + if (argc == 5)
> + session_addr = map_sysmem(simple_strtoul(argv[4], NULL, 0), 0);
> +
> + rc = tpm2_nv_write_value(dev, nv_addr, data_to_write, nv_size, session_addr);
> + if (rc)
> + printf("ERROR: nv_write #%u returns: #%u\n", nv_addr, rc);
> +
> + unmap_sysmem(session_addr);
> + unmap_sysmem(data_to_write);
> + return report_return_code(rc);
> +}
> +
> +static int do_start_auth_session(struct cmd_tbl *cmdtp, int flag,
> +int argc, char *const argv[])
> +{
> + struct udevice *dev;
> + u32 rc;
> + u8 session_type = TPM_SE_POLICY;
> + int ret;
> + void *data_to_write;
> +
> + ret = get_tpm(&dev);
> + if (argc < 2)
> + return CMD_RET_USAGE;
> +
> + data_to_write = map_sysmem(simple_strtoul(argv[1], NULL, 0), 0);
> + if (argc > 2)
> + session_type = simple_strtoul(argv[2], NULL, 0);
> +
> + rc = tpm2_start_auth_session(dev, data_to_write, session_type);
> + if (rc)
> + printf("ERROR: start_auth_session returns: #%u\n", rc);
> +
> + unmap_sysmem(data_to_write);
> + return report_return_code(rc);
> +}
> +
> +static int do_flush_context(struct cmd_tbl *cmdtp, int flag,
> + int argc, char *const argv[])
> +{
> + struct udevice *dev;
> + u32 rc;
> + int ret;
> + void *data_to_read;
> +
> + ret = get_tpm(&dev);
> +
> + if (argc < 2)
> + return CMD_RET_USAGE;
> +
> + data_to_read = map_sysmem(simple_strtoul(argv[1], NULL, 0), 0);
> + u32 session_handle = *((u32 *)data_to_read);
> +
> + rc = tpm2_flush_context(dev, session_handle);
> +
> + if (rc)
> + printf("ERROR: flush_context returns: #%u\n", rc);
> +
> + unmap_sysmem(data_to_read);
> + return report_return_code(rc);
> +}
> +
> +static int do_policy_pcr(struct cmd_tbl *cmdtp, int flag,
> + int argc, char *const argv[])
> +{
> + struct udevice *dev;
> + u32 rc, pcr, session_handle;
> + int ret;
> + void *data_to_read, *out_digest;
> +
> + ret = get_tpm(&dev);
> +
> + if (argc != 4)
> + return CMD_RET_USAGE;
> +
> + data_to_read = map_sysmem(simple_strtoul(argv[1], NULL, 0), 0);
> + session_handle = *((u32 *)data_to_read);
> + pcr = simple_strtoul(argv[2], NULL, 0);
> + out_digest = map_sysmem(simple_strtoul(argv[3], NULL, 0), 0);
> + rc = tpm2_set_policy_pcr(dev, session_handle, pcr, out_digest);
> +
> + if (rc)
> + printf("ERROR: policy_pcr returns: #%u\n", rc);
> +
> + unmap_sysmem(data_to_read);
> + unmap_sysmem(out_digest);
> + return report_return_code(rc);
> +}
> +
> static struct cmd_tbl tpm2_commands[] = {
> U_BOOT_CMD_MKENT(device, 0, 1, do_tpm_device, "", ""),
> U_BOOT_CMD_MKENT(info, 0, 1, do_tpm_info, "", ""),
> @@ -375,6 +573,13 @@ static struct cmd_tbl tpm2_commands[] = {
> do_tpm_pcr_setauthpolicy, "", ""),
> U_BOOT_CMD_MKENT(pcr_setauthvalue, 0, 1,
> do_tpm_pcr_setauthvalue, "", ""),
> + U_BOOT_CMD_MKENT(nv_define, 0, 1, do_tpm_nv_define, "", ""),
> + U_BOOT_CMD_MKENT(nv_undefine, 0, 1, do_tpm_nv_undefine, "", ""),
> + U_BOOT_CMD_MKENT(nv_read, 0, 1, do_tpm_nv_read_value, "", ""),
> + U_BOOT_CMD_MKENT(nv_write, 0, 1, do_tpm_nv_write_value, "", ""),
> + U_BOOT_CMD_MKENT(start_auth_session, 0, 1, do_start_auth_session, "", ""),
> + U_BOOT_CMD_MKENT(flush_context, 0, 1, do_flush_context, "", ""),
> + U_BOOT_CMD_MKENT(policy_pcr, 0, 1, do_policy_pcr, "", ""),
> };
>
> struct cmd_tbl *get_tpm2_commands(unsigned int *size)
> @@ -453,4 +658,40 @@ U_BOOT_CMD(tpm2, CONFIG_SYS_MAXARGS, 1, do_tpm, "Issue a TPMv2.x command",
> " <pcr>: index of the PCR\n"
> " <key>: secret to protect the access of PCR #<pcr>\n"
> " <password>: optional password of the PLATFORM hierarchy\n"
> +"\n"
> +"nv_define <tpm_addr> <size> [<attributes> <policy_digest_addr> <policy_size>]\n"
> +" Define new nv index in the TPM at <tpm_addr> with size <size>\n"
> +" <tpm_addr>: the internal address used within the TPM for the NV-index\n"
> +" <attributes>: is described in tpm-v2.h enum tpm_index_attrs. Note; Always use TPMA_NV_PLATFORMCREATE!\n"
> +" will default to: TPMA_NV_PLATFORMCREATE|TPMA_NV_OWNERWRITE|TPMA_NV_OWNERREAD|TPMA_NV_PPWRITE|TPMA_NV_PPREAD\n"
> +" <policy_digest_addr>: address to a policy digest. (e.g. a PCR value)\n"
> +" <policy_size>: size of the digest in bytes\n"
> +"nv_undefine <tpm_addr>\n"
> +" delete nv index\n"
> +"nv_read <tpm_addr> <size> <data_addr> [<session_handle_addr>]\n"
> +" Read data stored in TPM nv_memory at <tpm_addr> with size <size>\n"
> +" <tpm_addr>: the internal address used within the TPM for the NV-index\n"
> +" <size>: datasize in bytes\n"
> +" <data_addr>: memory address where to store the data read from the TPM\n"
> +" <session_handle_addr>: addr where the session handle is stored\n"
> +"nv_write <tpm_addr> <size> <data_addr> [<session_handle_addr>]\n"
> +" Write data to the TPM's nv_memory at <tpm_addr> with size <size>\n"
> +" <tpm_addr>: the internal address used within the TPM for the NV-index\n"
> +" <size>: datasize in bytes\n"
> +" <data_addr>: memory address of the data to be written to the TPM's NV-index\n"
> +" <session_handle_addr>: addr where the session handle is stored\n"
> +"start_auth_session <session_handle_addr> [<session_type>]\n"
> +" Start an authorization session and store it's handle at <session_handle_addr>\n"
> +" <session_handle_addr>: addr where to store the handle data (4 bytes)\n"
> +" <session_type>: type of session: 0x00 for HMAC, 0x01 for policy, 0x03 for trial\n"
> +" will default to 0x01 (TPM_SE_POLICY) if not provided\n"
> +" to create a policy, use TPM_SE_TRIAL (0x03), to authenticate TPM_SE_POLICY (0x01)\n"
> +"flush_context <session_handle_addr>\n"
> +" flush/terminate a session which's handle is stored at <session_handle_addr>\n"
> +" <session_handle_addr>: addr where the session handle is stored\n"
> +"policy_pcr <session_handle_addr> <pcr> <digest_addr>\n"
> +" create a policy to authorize using a PCR\n"
> +" <session_handle_addr>: addr where the session handle is stored\n"
> +" <pcr>: index of the PCR\n"
> +" <digest_addr>: addr where to store the policy digest (for nv_define/nv_read/write)\n"
> );
> diff --git a/include/tpm-common.h b/include/tpm-common.h
> index 1ba81386ce..5620454da7 100644
> --- a/include/tpm-common.h
> +++ b/include/tpm-common.h
> @@ -69,6 +69,8 @@ struct tpm_chip_priv {
> uint pcr_count;
> uint pcr_select_min;
> bool plat_hier_disabled;
> + u16 nonce_sz;
> + u8 nonce[32]; //NONCE_TPM_SIZE;
> };
>
> /**
> diff --git a/include/tpm-v2.h b/include/tpm-v2.h
> index 33dd103767..cf75495526 100644
> --- a/include/tpm-v2.h
> +++ b/include/tpm-v2.h
> @@ -301,7 +301,8 @@ enum tpm2_startup_types {
> */
> enum tpm2_handles {
> TPM2_RH_OWNER = 0x40000001,
> - TPM2_RS_PW = 0x40000009,
> + TPM2_RH_NULL = 0x40000007,
> + TPM2_RS_PW = 0x40000009,
> TPM2_RH_LOCKOUT = 0x4000000A,
> TPM2_RH_ENDORSEMENT = 0x4000000B,
> TPM2_RH_PLATFORM = 0x4000000C,
> @@ -325,24 +326,30 @@ enum tpm2_handles {
> * @TPM2_CC_PCR_SETAUTHVAL: TPM2_PCR_SetAuthValue().
> */
> enum tpm2_command_codes {
> - TPM2_CC_STARTUP = 0x0144,
> - TPM2_CC_SELF_TEST = 0x0143,
> - TPM2_CC_HIER_CONTROL = 0x0121,
> - TPM2_CC_CLEAR = 0x0126,
> - TPM2_CC_CLEARCONTROL = 0x0127,
> - TPM2_CC_HIERCHANGEAUTH = 0x0129,
> - TPM2_CC_NV_DEFINE_SPACE = 0x012a,
> - TPM2_CC_PCR_SETAUTHPOL = 0x012C,
> - TPM2_CC_NV_WRITE = 0x0137,
> - TPM2_CC_NV_WRITELOCK = 0x0138,
> - TPM2_CC_DAM_RESET = 0x0139,
> - TPM2_CC_DAM_PARAMETERS = 0x013A,
> - TPM2_CC_NV_READ = 0x014E,
> - TPM2_CC_GET_CAPABILITY = 0x017A,
> - TPM2_CC_GET_RANDOM = 0x017B,
> - TPM2_CC_PCR_READ = 0x017E,
> - TPM2_CC_PCR_EXTEND = 0x0182,
> - TPM2_CC_PCR_SETAUTHVAL = 0x0183,
> + TPM2_CC_STARTUP = 0x0144,
> + TPM2_CC_SELF_TEST = 0x0143,
> + TPM2_CC_HIER_CONTROL = 0x0121,
> + TPM2_CC_CLEAR = 0x0126,
> + TPM2_CC_CLEARCONTROL = 0x0127,
> + TPM2_CC_HIERCHANGEAUTH = 0x0129,
> + TPM2_CC_NV_DEFINE_SPACE = 0x012a,
> + TPM2_CC_NV_UNDEFINE_SPACE = 0x0122,
> + TPM2_CC_PCR_SETAUTHPOL = 0x012C,
> + TPM2_CC_CREATE_PRIMARY = 0x0131,
> + TPM2_CC_NV_WRITE = 0x0137,
> + TPM2_CC_NV_WRITELOCK = 0x0138,
> + TPM2_CC_DAM_RESET = 0x0139,
> + TPM2_CC_DAM_PARAMETERS = 0x013A,
> + TPM2_CC_NV_READ = 0x014E,
> + TPM2_CC_FLUSH_CONTEXT = 0x0165,
> + TPM2_CC_START_AUTH_SESSION = 0x0176,
> + TPM2_CC_GET_CAPABILITY = 0x017A,
> + TPM2_CC_GET_RANDOM = 0x017B,
> + TPM2_CC_PCR_READ = 0x017E,
> + TPM2_CC_POLICY_PCR = 0x017F,
> + TPM2_CC_PCR_EXTEND = 0x0182,
> + TPM2_CC_PCR_SETAUTHVAL = 0x0183,
> + TPM2_CC_POLICY_GET_DIGEST = 0x0189,
> };
>
> /**
> @@ -384,6 +391,16 @@ enum tpm2_algorithms {
> TPM2_ALG_SHA512 = 0x0D,
> TPM2_ALG_NULL = 0x10,
> TPM2_ALG_SM3_256 = 0x12,
> + TPM2_ALG_ECC = 0x23,
> +};
> +
> +/**
> + * TPM2 session types.
> + */
> +enum tpm2_se {
> + TPM_SE_HMAC = 0x00,
> + TPM_SE_POLICY = 0x01,
> + TPM_SE_TRIAL = 0x03,
> };
>
> extern const enum tpm2_algorithms tpm2_supported_algorithms[4];
> @@ -503,10 +520,10 @@ struct tcg2_event_log {
> /**
> * Create a list of digests of the supported PCR banks for a given input data
> *
> - * @dev TPM device
> - * @input Data
> - * @length Length of the data to calculate the digest
> - * @digest_list List of digests to fill in
> + * @dev: TPM device
> + * @input: Data
> + * @length: Length of the data to calculate the digest
> + * @digest_list: List of digests to fill in
> *
> * Return: zero on success, negative errno otherwise
> */
> @@ -516,7 +533,7 @@ int tcg2_create_digest(struct udevice *dev, const u8 *input, u32 length,
> /**
> * Get the event size of the specified digests
> *
> - * @digest_list List of digests for the event
> + * @digest_list: List of digests for the event
> *
> * Return: Size in bytes of the event
> */
> @@ -525,8 +542,8 @@ u32 tcg2_event_get_size(struct tpml_digest_values *digest_list);
> /**
> * tcg2_get_active_pcr_banks
> *
> - * @dev TPM device
> - * @active_pcr_banks Bitmask of PCR algorithms supported
> + * @dev: TPM device
> + * @active_pcr_banks: Bitmask of PCR algorithms supported
> *
> * Return: zero on success, negative errno otherwise
> */
> @@ -535,12 +552,12 @@ int tcg2_get_active_pcr_banks(struct udevice *dev, u32 *active_pcr_banks);
> /**
> * tcg2_log_append - Append an event to an event log
> *
> - * @pcr_index Index of the PCR
> - * @event_type Type of event
> - * @digest_list List of digests to add
> - * @size Size of event
> - * @event Event data
> - * @log Log buffer to append the event to
> + * @pcr_index: Index of the PCR
> + * @event_type: Type of event
> + * @digest_list: List of digests to add
> + * @size: Size of event
> + * @event: Event data
> + * @log: Log buffer to append the event to
> */
> void tcg2_log_append(u32 pcr_index, u32 event_type,
> struct tpml_digest_values *digest_list, u32 size,
> @@ -549,9 +566,9 @@ void tcg2_log_append(u32 pcr_index, u32 event_type,
> /**
> * Extend the PCR with specified digests
> *
> - * @dev TPM device
> - * @pcr_index Index of the PCR
> - * @digest_list List of digests to extend
> + * @dev: TPM device
> + * @pcr_index: Index of the PCR
> + * @digest_list: List of digests to extend
> *
> * Return: zero on success, negative errno otherwise
> */
> @@ -561,9 +578,9 @@ int tcg2_pcr_extend(struct udevice *dev, u32 pcr_index,
> /**
> * Read the PCR into a list of digests
> *
> - * @dev TPM device
> - * @pcr_index Index of the PCR
> - * @digest_list List of digests to extend
> + * @dev: TPM device
> + * @pcr_index: Index of the PCR
> + * @digest_list: List of digests to extend
> *
> * Return: zero on success, negative errno otherwise
> */
> @@ -573,14 +590,14 @@ int tcg2_pcr_read(struct udevice *dev, u32 pcr_index,
> /**
> * Measure data into the TPM PCRs and the platform event log.
> *
> - * @dev TPM device
> - * @log Platform event log
> - * @pcr_index Index of the PCR
> - * @size Size of the data or 0 for event only
> - * @data Pointer to the data or NULL for event only
> - * @event_type Event log type
> - * @event_size Size of the event
> - * @event Pointer to the event
> + * @dev: TPM device
> + * @log: Platform event log
> + * @pcr_index: Index of the PCR
> + * @size: Size of the data or 0 for event only
> + * @data: Pointer to the data or NULL for event only
> + * @event_type: Event log type
> + * @event_size: Size of the event
> + * @event: Pointer to the event
> *
> * Return: zero on success, negative errno otherwise
> */
> @@ -598,13 +615,13 @@ int tcg2_measure_data(struct udevice *dev, struct tcg2_event_log *elog,
> * and the PCRs are not extended, the log is "replayed" to extend the PCRs.
> * If no log is discovered, create the log header.
> *
> - * @dev TPM device
> - * @elog Platform event log. The log pointer and log_size
> + * @dev: TPM device
> + * @elog: Platform event log. The log pointer and log_size
> * members must be initialized to either 0 or to a valid
> * memory region, in which case any existing log
> * discovered will be copied to the specified memory
> * region.
> - * @ignore_existing_log Boolean to indicate whether or not to ignore an
> + * @ignore_existing_log: Boolean to indicate whether or not to ignore an
> * existing platform log in memory
> *
> * Return: zero on success, negative errno otherwise
> @@ -615,13 +632,13 @@ int tcg2_log_prepare_buffer(struct udevice *dev, struct tcg2_event_log *elog,
> /**
> * Begin measurements.
> *
> - * @dev TPM device
> - * @elog Platform event log. The log pointer and log_size
> + * @dev: TPM device
> + * @elog: Platform event log. The log pointer and log_size
> * members must be initialized to either 0 or to a valid
> * memory region, in which case any existing log
> * discovered will be copied to the specified memory
> * region.
> - * @ignore_existing_log Boolean to indicate whether or not to ignore an
> + * @ignore_existing_log: Boolean to indicate whether or not to ignore an
> * existing platform log in memory
> *
> * Return: zero on success, negative errno otherwise
> @@ -632,9 +649,9 @@ int tcg2_measurement_init(struct udevice **dev, struct tcg2_event_log *elog,
> /**
> * Stop measurements and record separator events.
> *
> - * @dev TPM device
> - * @elog Platform event log
> - * @error Boolean to indicate whether an error ocurred or not
> + * @dev: TPM device
> + * @elog: Platform event log
> + * @error: Boolean to indicate whether an error ocurred or not
> */
> void tcg2_measurement_term(struct udevice *dev, struct tcg2_event_log *elog,
> bool error);
> @@ -642,9 +659,9 @@ void tcg2_measurement_term(struct udevice *dev, struct tcg2_event_log *elog,
> /**
> * Get the platform event log address and size.
> *
> - * @dev TPM device
> - * @addr Address of the log
> - * @size Size of the log
> + * @dev: TPM device
> + * @addr: Address of the log
> + * @size: Size of the log
> *
> * Return: zero on success, negative errno otherwise
> */
> @@ -653,7 +670,7 @@ int tcg2_platform_get_log(struct udevice *dev, void **addr, u32 *size);
> /**
> * Get the first TPM2 device found.
> *
> - * @dev TPM device
> + * @dev: TPM device
> *
> * Return: zero on success, negative errno otherwise
> */
> @@ -662,16 +679,16 @@ int tcg2_platform_get_tpm2(struct udevice **dev);
> /**
> * Platform-specific function for handling TPM startup errors
> *
> - * @dev TPM device
> - * @rc The TPM response code
> + * @dev: TPM device
> + * @rc: The TPM response code
> */
> void tcg2_platform_startup_error(struct udevice *dev, int rc);
>
> /**
> * Issue a TPM2_Startup command.
> *
> - * @dev TPM device
> - * @mode TPM startup mode
> + * @dev: TPM device
> + * @mode: TPM startup mode
> *
> * Return: code of the operation
> */
> @@ -680,8 +697,8 @@ u32 tpm2_startup(struct udevice *dev, enum tpm2_startup_types mode);
> /**
> * Issue a TPM2_SelfTest command.
> *
> - * @dev TPM device
> - * @full_test Asking to perform all tests or only the untested ones
> + * @dev: TPM device
> + * @full_test: Asking to perform all tests or only the untested ones
> *
> * Return: code of the operation
> */
> @@ -690,41 +707,99 @@ u32 tpm2_self_test(struct udevice *dev, enum tpm2_yes_no full_test);
> /**
> * Issue a TPM2_Clear command.
> *
> - * @dev TPM device
> - * @handle Handle
> - * @pw Password
> - * @pw_sz Length of the password
> + * @dev: TPM device
> + * @handle: Handle
> + * @pw: Password
> + * @pw_sz: Length of the password
> *
> * Return: code of the operation
> */
> u32 tpm2_clear(struct udevice *dev, u32 handle, const char *pw,
> const ssize_t pw_sz);
>
> +/**
> + * Issue a TPM2_StartAuthSession command. (chaining commands together which need authorization)
> + *
> + * @dev: TPM device
> + * @session_handle: Pointer to memory where to store the session handle.
> + * @session_type: tpm2_se value to indicate session type (usually TPM_SE_POLICY)
> + *
> + * Return: code of the operation
> + */
> +u32 tpm2_start_auth_session(struct udevice *dev, u32 *session_handle, u8 session_type);
> +/**
> + * Issue a TPM2_FlushContext command. (for ending the authorization session)
> + *
> + * @dev: TPM device
> + * @session_handle: Authorization session to be terminated.
> + *
> + * Return: code of the operation
> + */
> +u32 tpm2_flush_context(struct udevice *dev, u32 session_handle);
> +
> +/**
> + * Issue a TPM2_PolicyPCR command. (for authenticating using a PCR value)
> + *
> + * @dev: TPM device
> + * @session_handle: policy session handle started with start_auth_session.
> + * @index: Index of the PCR
> + *
> + * @note: For now only 1 PCR selection is supported,
> + * since the value of one PCR can be extended with the value of another.
> + * This achieves the same effect as selecting multiple PCR's
> + * @out_digest: addr where to write the digest
> + *
> + * Return: code of the operation
> + */
> +u32 tpm2_set_policy_pcr(struct udevice *dev, u32 session_handle, u32 index, void *out_digest);
> +
> +/**
> + * Issue a TPM2_getPolicyDigest command.
> + *
> + * @dev: TPM device
> + * @session_handle: policy session handle started with start_auth_session.
> + * @out_digest: addr where to write the digest (size is 0x20 for SHA256)
> + * Return: code of the operation
> + */
> +u32 tpm2_get_policy_digest(struct udevice *dev, u32 session_handle, void *out_digest);
> +
> /**
> * Issue a TPM_NV_DefineSpace command
> *
> * This allows a space to be defined with given attributes and policy
> *
> - * @dev TPM device
> - * @space_index index of the area
> - * @space_size size of area in bytes
> - * @nv_attributes TPM_NV_ATTRIBUTES of the area
> - * @nv_policy policy to use
> - * @nv_policy_size size of the policy
> - * Return: return code of the operation
> + * @dev: TPM device
> + * @space_index: index of the area
> + * @space_size: size of area in bytes
> + * @nv_attributes: TPM_NV_ATTRIBUTES of the area
> + * @session_handle: handle to a session. can be TPM2_RS_PW
> + * @nv_policy: policy to use
> + * @nv_policy_size: size of the policy
> + * Return: return code of the operation
> */
> u32 tpm2_nv_define_space(struct udevice *dev, u32 space_index,
> size_t space_size, u32 nv_attributes,
> const u8 *nv_policy, size_t nv_policy_size);
>
> +/**
> + * Issue a TPM_NV_UnDefineSpace command
> + *
> + * This allows a space to be removed. Needed because TPM_clear doesn't clear platform entries
> + *
> + * @dev: TPM device
> + * @space_index: index of the area
> + * Return: return code of the operation
> + */
> +u32 tpm2_nv_undefine_space(struct udevice *dev, u32 space_index);
> +
> /**
> * Issue a TPM2_PCR_Extend command.
> *
> - * @dev TPM device
> - * @index Index of the PCR
> - * @algorithm Algorithm used, defined in 'enum tpm2_algorithms'
> - * @digest Value representing the event to be recorded
> - * @digest_len len of the hash
> + * @dev: TPM device
> + * @index: Index of the PCR
> + * @algorithm: Algorithm used, defined in 'enum tpm2_algorithms'
> + * @digest: Value representing the event to be recorded
> + * @digest_len: len of the hash
> *
> * Return: code of the operation
> */
> @@ -734,36 +809,38 @@ u32 tpm2_pcr_extend(struct udevice *dev, u32 index, u32 algorithm,
> /**
> * Read data from the secure storage
> *
> - * @dev TPM device
> - * @index Index of data to read
> - * @data Place to put data
> - * @count Number of bytes of data
> - * Return: code of the operation
> + * @dev: TPM device
> + * @index: Index of data to read
> + * @data: Place to put data
> + * @count: Number of bytes of data
> + * @session_handle: handle of a running authorization session. if NULL->password authorization
> + * Return: code of the operation
> */
> -u32 tpm2_nv_read_value(struct udevice *dev, u32 index, void *data, u32 count);
> +u32 tpm2_nv_read_value(struct udevice *dev, u32 index, void *data, u32 count, u32 *session_handle);
>
> /**
> * Write data to the secure storage
> *
> - * @dev TPM device
> - * @index Index of data to write
> - * @data Data to write
> - * @count Number of bytes of data
> - * Return: code of the operation
> + * @dev: TPM device
> + * @index: Index of data to write
> + * @data: Data to write
> + * @count: Number of bytes of data
> + * @session_handle: handle of a running authorization session. if NULL->password authorization
> + * Return: code of the operation
> */
> u32 tpm2_nv_write_value(struct udevice *dev, u32 index, const void *data,
> - u32 count);
> + u32 count, u32 *session_handle);
>
> /**
> * Issue a TPM2_PCR_Read command.
> *
> - * @dev TPM device
> - * @idx Index of the PCR
> - * @idx_min_sz Minimum size in bytes of the pcrSelect array
> - * @algorithm Algorithm used, defined in 'enum tpm2_algorithms'
> - * @data Output buffer for contents of the named PCR
> - * @digest_len len of the data
> - * @updates Optional out parameter: number of updates for this PCR
> + * @dev: TPM device
> + * @idx: Index of the PCR
> + * @idx_min_sz: Minimum size in bytes of the pcrSelect array
> + * @algorithm: Algorithm used, defined in 'enum tpm2_algorithms'
> + * @data: Output buffer for contents of the named PCR
> + * @digest_len: len of the data
> + * @updates: Optional out parameter: number of updates for this PCR
> *
> * Return: code of the operation
> */
> @@ -775,13 +852,13 @@ u32 tpm2_pcr_read(struct udevice *dev, u32 idx, unsigned int idx_min_sz,
> * Issue a TPM2_GetCapability command. This implementation is limited
> * to query property index that is 4-byte wide.
> *
> - * @dev TPM device
> - * @capability Partition of capabilities
> - * @property Further definition of capability, limited to be 4 bytes wide
> - * @buf Output buffer for capability information
> - * @prop_count Size of output buffer
> + * @dev: TPM device
> + * @capability: Partition of capabilities
> + * @property: Further definition of capability, limited to be 4 bytes wide
> + * @buf: Output buffer for capability information
> + * @prop_count: Size of output buffer
> *
> - * Return: code of the operation
> + * Return: code of the operation
> */
> u32 tpm2_get_capability(struct udevice *dev, u32 capability, u32 property,
> void *buf, size_t prop_count);
> @@ -802,9 +879,9 @@ int tpm2_get_pcr_info(struct udevice *dev, u32 *supported_pcr, u32 *active_pcr,
> /**
> * Issue a TPM2_DictionaryAttackLockReset command.
> *
> - * @dev TPM device
> - * @pw Password
> - * @pw_sz Length of the password
> + * @dev: TPM device
> + * @pw: Password
> + * @pw_sz: Length of the password
> *
> * Return: code of the operation
> */
> @@ -813,12 +890,12 @@ u32 tpm2_dam_reset(struct udevice *dev, const char *pw, const ssize_t pw_sz);
> /**
> * Issue a TPM2_DictionaryAttackParameters command.
> *
> - * @dev TPM device
> - * @pw Password
> - * @pw_sz Length of the password
> - * @max_tries Count of authorizations before lockout
> - * @recovery_time Time before decrementation of the failure count
> - * @lockout_recovery Time to wait after a lockout
> + * @dev: TPM device
> + * @pw: Password
> + * @pw_sz: Length of the password
> + * @max_tries: Count of authorizations before lockout
> + * @recovery_time: Time before decrementation of the failure count
> + * @lockout_recovery: Time to wait after a lockout
> *
> * Return: code of the operation
> */
> @@ -830,12 +907,12 @@ u32 tpm2_dam_parameters(struct udevice *dev, const char *pw,
> /**
> * Issue a TPM2_HierarchyChangeAuth command.
> *
> - * @dev TPM device
> - * @handle Handle
> - * @newpw New password
> - * @newpw_sz Length of the new password
> - * @oldpw Old password
> - * @oldpw_sz Length of the old password
> + * @dev: TPM device
> + * @handle: Handle
> + * @newpw: New password
> + * @newpw_sz: Length of the new password
> + * @oldpw: Old password
> + * @oldpw_sz: Length of the old password
> *
> * Return: code of the operation
> */
> @@ -846,11 +923,11 @@ int tpm2_change_auth(struct udevice *dev, u32 handle, const char *newpw,
> /**
> * Issue a TPM_PCR_SetAuthPolicy command.
> *
> - * @dev TPM device
> - * @pw Platform password
> - * @pw_sz Length of the password
> - * @index Index of the PCR
> - * @digest New key to access the PCR
> + * @dev: TPM device
> + * @pw: Platform password
> + * @pw_sz: Length of the password
> + * @index: Index of the PCR
> + * @digest: New key to access the PCR
> *
> * Return: code of the operation
> */
> @@ -860,12 +937,12 @@ u32 tpm2_pcr_setauthpolicy(struct udevice *dev, const char *pw,
> /**
> * Issue a TPM_PCR_SetAuthValue command.
> *
> - * @dev TPM device
> - * @pw Platform password
> - * @pw_sz Length of the password
> - * @index Index of the PCR
> - * @digest New key to access the PCR
> - * @key_sz Length of the new key
> + * @dev: TPM device
> + * @pw: Platform password
> + * @pw_sz: Length of the password
> + * @index: Index of the PCR
> + * @digest: New key to access the PCR
> + * @key_sz: Length of the new key
> *
> * Return: code of the operation
> */
> @@ -876,9 +953,9 @@ u32 tpm2_pcr_setauthvalue(struct udevice *dev, const char *pw,
> /**
> * Issue a TPM2_GetRandom command.
> *
> - * @dev TPM device
> - * @param data output buffer for the random bytes
> - * @param count size of output buffer
> + * @dev: TPM device
> + * @data: output buffer for the random bytes
> + * @count: size of output buffer
> *
> * Return: return code of the operation
> */
> @@ -889,8 +966,8 @@ u32 tpm2_get_random(struct udevice *dev, void *data, u32 count);
> *
> * Once locked the data cannot be written until after a reboot
> *
> - * @dev TPM device
> - * @index Index of data to lock
> + * @dev: TPM device
> + * @index: Index of data to lock
> * Return: code of the operation
> */
> u32 tpm2_write_lock(struct udevice *dev, u32 index);
> @@ -901,7 +978,7 @@ u32 tpm2_write_lock(struct udevice *dev, u32 index);
> * This can be called to close off access to the firmware data in the data,
> * before calling the kernel.
> *
> - * @dev TPM device
> + * @dev: TPM device
> * Return: code of the operation
> */
> u32 tpm2_disable_platform_hierarchy(struct udevice *dev);
> @@ -909,7 +986,7 @@ u32 tpm2_disable_platform_hierarchy(struct udevice *dev);
> /**
> * submit user specified data to the TPM and get response
> *
> - * @dev TPM device
> + * @dev: TPM device
> * @sendbuf: Buffer of the data to send
> * @recvbuf: Buffer to save the response to
> * @recv_size: Pointer to the size of the response buffer
> @@ -930,7 +1007,7 @@ u32 tpm2_submit_command(struct udevice *dev, const u8 *sendbuf,
> * Return: result of the operation
> */
> u32 tpm2_report_state(struct udevice *dev, uint vendor_cmd, uint vendor_subcmd,
> - u8 *recvbuf, size_t *recv_size);
> + u8 *recvbuf, size_t *recv_size);
>
> /**
> * tpm2_enable_nvcommits() - Tell TPM to commit NV data immediately
> @@ -941,7 +1018,7 @@ u32 tpm2_report_state(struct udevice *dev, uint vendor_cmd, uint vendor_subcmd,
> * This vendor command is used to indicate that non-volatile data should be
> * written to its store immediately.
> *
> - * @dev TPM device
> + * @dev: TPM device
> * @vendor_cmd: Vendor command number to send
> * @vendor_subcmd: Vendor sub-command number to send
> * Return: result of the operation
> @@ -951,16 +1028,16 @@ u32 tpm2_enable_nvcommits(struct udevice *dev, uint vendor_cmd,
>
> /**
> * tpm2_auto_start() - start up the TPM and perform selftests.
> - * If a testable function has not been tested and is
> - * requested the TPM2 will return TPM_RC_NEEDS_TEST.
> + * If a testable function has not been tested and is
> + * requested the TPM2 will return TPM_RC_NEEDS_TEST.
> *
> - * @param dev TPM device
> + * @dev: TPM device
> * Return: TPM2_RC_TESTING, if TPM2 self-test is in progress.
> - * TPM2_RC_SUCCESS, if testing of all functions is complete without
> - * functional failures.
> - * TPM2_RC_FAILURE, if any test failed.
> - * TPM2_RC_INITIALIZE, if the TPM has not gone through the Startup
> - * sequence
> + * TPM2_RC_SUCCESS, if testing of all functions is complete without
> + * functional failures.
> + * TPM2_RC_FAILURE, if any test failed.
> + * TPM2_RC_INITIALIZE, if the TPM has not gone through the Startup
> + * sequence
>
> */
> u32 tpm2_auto_start(struct udevice *dev);
> diff --git a/lib/tpm-v2.c b/lib/tpm-v2.c
> index 68eaaa639f..5856b5de03 100644
> --- a/lib/tpm-v2.c
> +++ b/lib/tpm-v2.c
> @@ -786,19 +786,188 @@ u32 tpm2_clear(struct udevice *dev, u32 handle, const char *pw,
> return tpm_sendrecv_command(dev, command_v2, NULL, NULL);
> }
>
> +u32 tpm2_start_auth_session(struct udevice *dev, u32 *session_handle, u8 session_type)
> +{
> + const u16 nonce_size = TPM2_SHA256_DIGEST_SIZE;
> + const int handles_len = sizeof(u32) * 2;
> + uint offset = TPM2_HDR_LEN + handles_len + sizeof(nonce_size);
> + struct tpm_chip_priv *priv;
> + int ret;
> +
> + priv = dev_get_uclass_priv(dev);
> + if (!priv)
> + return TPM_LIB_ERROR;
> +
> + u8 command_v2[COMMAND_BUFFER_SIZE] = {
> + /* header 10 bytes */
> + tpm_u16(TPM2_ST_NO_SESSIONS), /* TAG */
> + tpm_u32(offset + nonce_size + 7),/* Length */
> + tpm_u32(TPM2_CC_START_AUTH_SESSION),/* Command code */
> +
> + /* handles 8 bytes */
> + tpm_u32(TPM2_RH_NULL), /* TPMI_DH_OBJECT+ */
> + tpm_u32(TPM2_RH_NULL), /* TPMI_DH_ENTITY+ */
> +
> + /* NONCE 32 bytes -> use pack_byte_string() */
> + tpm_u16(nonce_size),
> + /* message 7 bytes -> use pack_byte_string() */
> + //tpm_u16(0), // salt size
> + //session_type, // session type
> + //tpm_u16(TPM2_ALG_NULL), // symmetric key algorythm
> + //tpm_u16(TPM2_ALG_SHA256), // auth hash
> + };
> +
> + u8 Nonce[nonce_size]; //nonce is a random number you use once. (Number ONCE)
> +
> + memset(&Nonce, 2, nonce_size); //should use TPM_get_random() to randomize
> +
> + ret = pack_byte_string(command_v2, sizeof(command_v2), "swbww",
> + offset, Nonce, nonce_size,
> + offset + nonce_size, 0, //salt size
> + offset + nonce_size + 2, session_type,
> + offset + nonce_size + 3, TPM2_ALG_NULL,
> + offset + nonce_size + 5, TPM2_ALG_SHA256);
> +
> + if (ret)
> + return TPM_LIB_ERROR;
> +
> + size_t response_len = COMMAND_BUFFER_SIZE;
> + u8 response[COMMAND_BUFFER_SIZE];
> + u16 tag;
> + u32 size, code;
> +
> + ret = tpm_sendrecv_command(dev, command_v2, response, &response_len);
> +
> + if (ret)
> + return log_msg_ret("read", ret);
> +
> + if (unpack_byte_string(response, response_len, "wdddws",
> + 0, &tag, 2, &size, 6, &code, //header
> + 10, session_handle, //TPMI_SH_AUTH_SESSION
> + 14, &priv->nonce_sz,
> + 16, priv->nonce, TPM2_SHA256_DIGEST_SIZE)) //HACK: we asked for SHA256, so that's what we'll get.
> + return TPM_LIB_ERROR;
> + return ret;
> +}
> +
> +u32 tpm2_flush_context(struct udevice *dev, u32 session_handle)
> +{
> + u8 command_v2[COMMAND_BUFFER_SIZE] = {
> + /* header 10 bytes */
> + tpm_u16(TPM2_ST_NO_SESSIONS), /* TAG */
> + tpm_u32(TPM2_HDR_LEN + sizeof(u32)),/* Length */
> + tpm_u32(TPM2_CC_FLUSH_CONTEXT),/* Command code */
> +
> + /* session handle 4 bytes */
> + tpm_u32(session_handle), /* TPMI_DH_CONTEXT+ */
> + };
> + return tpm_sendrecv_command(dev, command_v2, NULL, NULL);
> +}
> +
> +u32 tpm2_set_policy_pcr(struct udevice *dev, u32 session_handle, u32 index, void *out_digest)
> +{
> + const int offset = TPM2_HDR_LEN + 6;
> + const int message_len = offset + TPM2_SHA256_DIGEST_SIZE + 10;
> + int ret;
> + u8 pcr_sel_bit = BIT(index % 8);
> + struct tpm_chip_priv *priv;
> + struct tpml_digest_values digest_list;
> +
> + digest_list.count = 1;
> + digest_list.digests->hash_alg = TPM2_ALG_SHA256;
> + tcg2_pcr_read(dev, index, &digest_list);
> +
> + u8 pcr_sha_output[TPM2_SHA256_DIGEST_SIZE];
> + sha256_context ctx_256;
> +
> + sha256_starts(&ctx_256);
> + sha256_update(&ctx_256, digest_list.digests[0].digest.sha256, TPM2_SHA256_DIGEST_SIZE);
> + sha256_finish(&ctx_256, pcr_sha_output);
> +
> + priv = dev_get_uclass_priv(dev);
> + if (!priv)
> + return TPM_LIB_ERROR;
> +
> + u8 idx_array_sz = max(priv->pcr_select_min, DIV_ROUND_UP(index, 8));
> +
> + u8 command_v2[COMMAND_BUFFER_SIZE] = {
> + /* header 10 bytes */
> + tpm_u16(TPM2_ST_NO_SESSIONS), /* TAG -> TPM2_ST_SESSIONS only for audit or decrypt*/
> + tpm_u32(message_len),/* Length */
> + tpm_u32(TPM2_CC_POLICY_PCR),/* Command code */
> + /* session handle 4 bytes */
> + tpm_u32(session_handle), /* TPMI_SH_POLICY */
> + /* PCR Digest - 32 bytes */
> + tpm_u16(TPM2_SHA256_DIGEST_SIZE) /*hash size*/
> + /* digest - 32-bytes */
> + /* PCR selection */
> + //tpm_u32(1), /* Number of selections */
> + //tpm_u16(TPM_ALG_SHA256), /* Algorithm */
> + //idx_array_sz, /* Array size for selection */
> + /* bitmap(idx) Selected PCR bitmap */
> + };
> +
> + if (pack_byte_string(command_v2, COMMAND_BUFFER_SIZE, "sdwbbw",
> + offset, pcr_sha_output, TPM2_SHA256_DIGEST_SIZE,
> + offset + TPM2_SHA256_DIGEST_SIZE, 1, /* Number of selections */
> + offset + TPM2_SHA256_DIGEST_SIZE + 4, TPM2_ALG_SHA256, /* Algorithm */
> + offset + TPM2_SHA256_DIGEST_SIZE + 6, idx_array_sz, /* size of select */
> + offset + TPM2_SHA256_DIGEST_SIZE + 7, pcr_sel_bit,/* Selected PCR bitmap */
> + offset + TPM2_SHA256_DIGEST_SIZE + 8, 0)) /*padding */
> + return TPM_LIB_ERROR;
> +
> + ret = tpm_sendrecv_command(dev, command_v2, NULL, NULL);
> + if (ret)
> + return ret;
> + return tpm2_get_policy_digest(dev, session_handle, out_digest);
> +}
> +
> +u32 tpm2_get_policy_digest(struct udevice *dev, u32 session_handle, void *out_digest)
> +{
> + const int message_len = TPM2_HDR_LEN + sizeof(u32);
> +
> + u8 command_v2[COMMAND_BUFFER_SIZE] = {
> + /* header 10 bytes */
> + tpm_u16(TPM2_ST_NO_SESSIONS), /* TAG -> SESSIONS only for audit or decrypt */
> + tpm_u32(message_len),/* Length */
> + tpm_u32(TPM2_CC_POLICY_GET_DIGEST),/* Command code */
> + /* session handle 4 bytes */
> + tpm_u32(session_handle), /* TPMI_SH_POLICY */
> + };
> +
> + size_t response_len = COMMAND_BUFFER_SIZE;
> + u8 response[COMMAND_BUFFER_SIZE];
> + int ret;
> + u16 tag;
> + u32 size, code;
> +
> + ret = tpm_sendrecv_command(dev, command_v2, response, &response_len);
> + if (ret)
> + return log_msg_ret("read", ret);
> +
> + if (unpack_byte_string(response, response_len, "wdds",
> + 0, &tag, 2, &size, 6, &code,
> + 12, out_digest, TPM2_SHA256_DIGEST_SIZE)) //digest_size
> + return TPM_LIB_ERROR;
> +
> + return ret;
> +}
> +
> u32 tpm2_nv_define_space(struct udevice *dev, u32 space_index,
> - size_t space_size, u32 nv_attributes,
> - const u8 *nv_policy, size_t nv_policy_size)
> + size_t space_size, u32 nv_attributes,
> + const u8 *nv_policy, size_t nv_policy_size)
> {
> /*
> * Calculate the offset of the nv_policy piece by adding each of the
> * chunks below.
> */
> const int platform_len = sizeof(u32);
> - const int session_hdr_len = 13;
> + const int session_hdr_len = 15;
> const int message_len = 14;
> - uint offset = TPM2_HDR_LEN + platform_len + session_hdr_len +
> - message_len;
> + int ret;
> + uint offset = TPM2_HDR_LEN + platform_len + session_hdr_len + message_len;
> + u8 attrs = 0;
> +
> u8 command_v2[COMMAND_BUFFER_SIZE] = {
> /* header 10 bytes */
> tpm_u16(TPM2_ST_SESSIONS), /* TAG */
> @@ -806,43 +975,72 @@ u32 tpm2_nv_define_space(struct udevice *dev, u32 space_index,
> tpm_u32(TPM2_CC_NV_DEFINE_SPACE),/* Command code */
>
> /* handles 4 bytes */
> - tpm_u32(TPM2_RH_PLATFORM), /* Primary platform seed */
> + tpm_u32(TPM2_RH_PLATFORM), /* platform seed, requires TPMA_NV_PLATFORMCREATE */
>
> - /* session header 13 bytes */
> +
> + /* session header 15 bytes */
> + /*null auth session*/
> tpm_u32(9), /* Header size */
> - tpm_u32(TPM2_RS_PW), /* Password authorisation */
> + tpm_u32(TPM2_RS_PW), /* auth handle if active, otherwise TPM2_RS_PW*/
> tpm_u16(0), /* nonce_size */
> - 0, /* session_attrs */
> + attrs, /* session_attrs */
> + tpm_u16(0), /* HMAC size */
> + /*end auth area*/
> tpm_u16(0), /* auth_size */
> -
> /* message 14 bytes + policy */
> tpm_u16(message_len + nv_policy_size), /* size */
> tpm_u32(space_index),
> tpm_u16(TPM2_ALG_SHA256),
> - tpm_u32(nv_attributes),
> + tpm_u32(nv_attributes | TPMA_NV_PLATFORMCREATE),
> tpm_u16(nv_policy_size),
> /*
> * nv_policy
> * space_size
> */
> };
> - int ret;
> -
> /*
> * Fill the command structure starting from the first buffer:
> - * - the password (if any)
> + * - the password (if any)
> */
> ret = pack_byte_string(command_v2, sizeof(command_v2), "sw",
> - offset, nv_policy, nv_policy_size,
> - offset + nv_policy_size, space_size);
> + offset, nv_policy, nv_policy_size,
> + offset + nv_policy_size, space_size);
> if (ret)
> return TPM_LIB_ERROR;
> + return tpm_sendrecv_command(dev, command_v2, NULL, NULL);
> +}
> +
> +u32 tpm2_nv_undefine_space(struct udevice *dev, u32 space_index)
> +{
> + const int platform_len = sizeof(u32);
> + const int session_hdr_len = 13;
> + const int message_len = 4;
> + u8 command_v2[COMMAND_BUFFER_SIZE] = {
> + /* header 10 bytes */
> + tpm_u16(TPM2_ST_SESSIONS), /* TAG */
> + tpm_u32(TPM2_HDR_LEN + platform_len + session_hdr_len +
> + message_len),/* Length - header + provision + index + auth area*/
> + tpm_u32(TPM2_CC_NV_UNDEFINE_SPACE),/* Command code */
> +
> + /* handles 4 bytes */
> + tpm_u32(TPM2_RH_PLATFORM), /* Primary platform seed */
> + /* nv_index */
> + tpm_u32(space_index),
> +
> + /*null auth session*/
> + tpm_u32(9), /* Header size */
> + tpm_u32(TPM2_RS_PW), /* Password authorisation*/
> + tpm_u16(0), /* nonce_size */
> + 0, /* session_attrs */
> + tpm_u16(0), /* HMAC size */
> + /*end auth area*/
>
> + };
> return tpm_sendrecv_command(dev, command_v2, NULL, NULL);
> }
>
> u32 tpm2_pcr_extend(struct udevice *dev, u32 index, u32 algorithm,
> - const u8 *digest, u32 digest_len)
> + const u8 *digest, u32 digest_len)
> {
> /* Length of the message header, up to start of digest */
> uint offset = 33;
> @@ -865,7 +1063,7 @@ u32 tpm2_pcr_extend(struct udevice *dev, u32 index, u32 algorithm,
>
> /* hashes */
> tpm_u32(1), /* Count (number of hashes) */
> - tpm_u16(algorithm), /* Algorithm of the hash */
> + tpm_u16(algorithm), /* Algorithm of the hash */
> /* STRING(digest) Digest */
> };
> int ret;
> @@ -874,66 +1072,111 @@ u32 tpm2_pcr_extend(struct udevice *dev, u32 index, u32 algorithm,
> return -EINVAL;
> /*
> * Fill the command structure starting from the first buffer:
> - * - the digest
> + * - the digest
> */
> ret = pack_byte_string(command_v2, sizeof(command_v2), "s",
> - offset, digest, digest_len);
> + offset, digest, digest_len);
> if (ret)
> return TPM_LIB_ERROR;
>
> return tpm_sendrecv_command(dev, command_v2, NULL, NULL);
> }
>
> -u32 tpm2_nv_read_value(struct udevice *dev, u32 index, void *data, u32 count)
> +u32 tpm2_nv_read_value(struct udevice *dev, u32 index, void *data, u32 count, u32 *session_handle)
> {
> - u8 command_v2[COMMAND_BUFFER_SIZE] = {
> - /* header 10 bytes */
> - tpm_u16(TPM2_ST_SESSIONS), /* TAG */
> - tpm_u32(10 + 8 + 4 + 9 + 4), /* Length */
> - tpm_u32(TPM2_CC_NV_READ), /* Command code */
> + static const int handles_len = 8, auth_handle_hdr_len = 10;
> + u32 offset = TPM2_HDR_LEN + handles_len + auth_handle_hdr_len;
> + struct tpm_chip_priv *priv;
> + int ret;
> + u16 tag;
> + u32 size, code;
>
> - /* handles 8 bytes */
> - tpm_u32(TPM2_RH_PLATFORM), /* Primary platform seed */
> - tpm_u32(HR_NV_INDEX + index), /* Password authorisation */
> + priv = dev_get_uclass_priv(dev);
>
> - /* AUTH_SESSION */
> - tpm_u32(9), /* Authorization size */
> - tpm_u32(TPM2_RS_PW), /* Session handle */
> - tpm_u16(0), /* Size of <nonce> */
> - /* <nonce> (if any) */
> - 0, /* Attributes: Cont/Excl/Rst */
> - tpm_u16(0), /* Size of <hmac/password> */
> - /* <hmac/password> (if any) */
> + if (!priv)
> + return TPM_LIB_ERROR;
> +
> + u32 nonce_size = priv->nonce_sz;
> + u32 authorization = TPM2_RS_PW;
>
> - tpm_u16(count), /* Number of bytes */
> - tpm_u16(0), /* Offset */
> + priv->nonce[nonce_size - 1]++; //increase nonce.
> + if (session_handle)
> + authorization = *session_handle;
> + else
> + nonce_size = 0; //cannot use nonce when using password authorization
> +
> + u8 command_v2[COMMAND_BUFFER_SIZE] = {
> + /* header 10 bytes */
> + tpm_u16(TPM2_ST_SESSIONS), /* TAG */
> + tpm_u32(offset + nonce_size + 7), /* Length */
> + tpm_u32(TPM2_CC_NV_READ), /* Command code */
> +
> + /* handles 8 bytes */
> + tpm_u32(index), /* Primary platform seed */
> + tpm_u32(index), /*nv index*/
> +
> + /* AUTH_SESSION */
> + tpm_u32(9 + nonce_size), /* Authorization size */
> + /*auth handle - 9 bytes */
> + tpm_u32(authorization),
> + tpm_u16(nonce_size), /* Size of <nonce> */
> + /* <nonce> (if any) */
> + /* Attributes: Cont/Excl/Rst */
> + /* Size of <hmac/password> */
> + /* <hmac/password> (if any) */
> + /* end auth handle */
> + /* Number of bytes */
> + /* Offset */
> };
> +
> size_t response_len = COMMAND_BUFFER_SIZE;
> u8 response[COMMAND_BUFFER_SIZE];
> - int ret;
> - u16 tag;
> - u32 size, code;
> +
> + ret = pack_byte_string(command_v2, sizeof(command_v2), "sbwww",
> + offset, priv->nonce, nonce_size,
> + offset + nonce_size, 0,
> + offset + nonce_size + 1, 0,
> + offset + nonce_size + 3, count,
> + offset + nonce_size + 5, 0);
> +
> + if (ret)
> + return TPM_LIB_ERROR;
>
> ret = tpm_sendrecv_command(dev, command_v2, response, &response_len);
> if (ret)
> return log_msg_ret("read", ret);
> +
> if (unpack_byte_string(response, response_len, "wdds",
> - 0, &tag, 2, &size, 6, &code,
> - 16, data, count))
> + 0, &tag, 2, &size, 6, &code,
> + 16, data, count))
> return TPM_LIB_ERROR;
>
> return 0;
> }
>
> u32 tpm2_nv_write_value(struct udevice *dev, u32 index, const void *data,
> - u32 count)
> + u32 count, u32 *session_handle)
> {
> + int ret;
> + u32 authorization = TPM2_RS_PW;
> struct tpm_chip_priv *priv = dev_get_uclass_priv(dev);
> - uint offset = 10 + 8 + 4 + 9 + 2;
> - uint len = offset + count + 2;
> - /* Use empty password auth if platform hierarchy is disabled */
> - u32 auth = priv->plat_hier_disabled ? HR_NV_INDEX + index :
> - TPM2_RH_PLATFORM;
> +
> + if (!priv)
> + return TPM_LIB_ERROR;
> +
> + u32 nonce_size = priv->nonce_sz;
> +
> + priv->nonce[nonce_size - 1]++;
> +
> + if (session_handle)
> + authorization = *session_handle;
> + else
> + nonce_size = 0; //cannot use nonce when using password authorization
> +
> + static const int handles_len = 8, auth_handle_hdr_len = 10, nv_info_sz = 7;
> + u32 offset = TPM2_HDR_LEN + handles_len + auth_handle_hdr_len;
> + uint len = offset + nonce_size + count + nv_info_sz;
> +
> u8 command_v2[COMMAND_BUFFER_SIZE] = {
> /* header 10 bytes */
> tpm_u16(TPM2_ST_SESSIONS), /* TAG */
> @@ -941,27 +1184,34 @@ u32 tpm2_nv_write_value(struct udevice *dev, u32 index, const void *data,
> tpm_u32(TPM2_CC_NV_WRITE), /* Command code */
>
> /* handles 8 bytes */
> - tpm_u32(auth), /* Primary platform seed */
> - tpm_u32(HR_NV_INDEX + index), /* Password authorisation */
> + tpm_u32(index), /* Primary platform seed */
> + tpm_u32(index), /*nv index*/
>
> /* AUTH_SESSION */
> - tpm_u32(9), /* Authorization size */
> - tpm_u32(TPM2_RS_PW), /* Session handle */
> - tpm_u16(0), /* Size of <nonce> */
> - /* <nonce> (if any) */
> - 0, /* Attributes: Cont/Excl/Rst */
> - tpm_u16(0), /* Size of <hmac/password> */
> - /* <hmac/password> (if any) */
> -
> - tpm_u16(count),
> + tpm_u32(9 + nonce_size), /* Authorization size */
> + /*auth handle - 9 bytes */
> + tpm_u32(authorization),
> + tpm_u16(nonce_size), /* Size of <nonce> */
> + /* <nonce> (if any) */
> + /* Attributes: Cont/Excl/Rst */
> + /* Size of <hmac/password> */
> + /* <hmac/password> (if any) */
> + /* end auth handle */
> + /* size of buffer - 2 bytes*/
> + /* data (buffer)*/
> + /* offset -> the octet offset into the NV Area*/
> };
> size_t response_len = COMMAND_BUFFER_SIZE;
> u8 response[COMMAND_BUFFER_SIZE];
> - int ret;
>
> - ret = pack_byte_string(command_v2, sizeof(command_v2), "sw",
> - offset, data, count,
> - offset + count, 0);
> + ret = pack_byte_string(command_v2, sizeof(command_v2), "sbwwsw",
> + offset, priv->nonce, nonce_size,
> + offset + nonce_size, 0, //attrs
> + offset + nonce_size + 1, 0, //hmac sz
> + offset + nonce_size + 3, count,
> + offset + nonce_size + 5, data, count,
> + offset + nonce_size + count, 0);
> +
> if (ret)
> return TPM_LIB_ERROR;
>
> @@ -972,6 +1222,8 @@ u32 tpm2_pcr_read(struct udevice *dev, u32 idx, unsigned int idx_min_sz,
> u16 algorithm, void *data, u32 digest_len,
> unsigned int *updates)
> {
> + int ret;
> +
> u8 idx_array_sz = max(idx_min_sz, DIV_ROUND_UP(idx, 8));
> u8 command_v2[COMMAND_BUFFER_SIZE] = {
> tpm_u16(TPM2_ST_NO_SESSIONS), /* TAG */
> @@ -982,17 +1234,16 @@ u32 tpm2_pcr_read(struct udevice *dev, u32 idx, unsigned int idx_min_sz,
> tpm_u32(1), /* Number of selections */
> tpm_u16(algorithm), /* Algorithm of the hash */
> idx_array_sz, /* Array size for selection */
> - /* bitmap(idx) Selected PCR bitmap */
> + /* Selected PCR bitmap */
> };
> size_t response_len = COMMAND_BUFFER_SIZE;
> u8 response[COMMAND_BUFFER_SIZE];
> unsigned int pcr_sel_idx = idx / 8;
> u8 pcr_sel_bit = BIT(idx % 8);
> unsigned int counter = 0;
> - int ret;
>
> if (pack_byte_string(command_v2, COMMAND_BUFFER_SIZE, "b",
> - 17 + pcr_sel_idx, pcr_sel_bit))
> + 17 + pcr_sel_idx, pcr_sel_bit))
> return TPM_LIB_ERROR;
>
> ret = tpm_sendrecv_command(dev, command_v2, response, &response_len);
> @@ -1003,9 +1254,9 @@ u32 tpm2_pcr_read(struct udevice *dev, u32 idx, unsigned int idx_min_sz,
> return TPM_LIB_ERROR;
>
> if (unpack_byte_string(response, response_len, "ds",
> - 10, &counter,
> - response_len - digest_len, data,
> - digest_len))
> + 10, &counter,
> + response_len - digest_len, data,
> + digest_len))
> return TPM_LIB_ERROR;
>
> if (updates)
> @@ -1088,7 +1339,7 @@ static bool tpm2_is_active_pcr(struct tpms_pcr_selection *selection)
> }
>
> int tpm2_get_pcr_info(struct udevice *dev, u32 *supported_pcr, u32 *active_pcr,
> - u32 *pcr_banks)
> + u32 *pcr_banks)
> {
> u8 response[(sizeof(struct tpms_capability_data) -
> offsetof(struct tpms_capability_data, data))];
> @@ -1111,7 +1362,7 @@ int tpm2_get_pcr_info(struct udevice *dev, u32 *supported_pcr, u32 *active_pcr,
> * instead of TPM2_NUM_PCR_BANKS
> */
> if (pcrs.count > ARRAY_SIZE(tpm2_supported_algorithms) ||
> - pcrs.count < 1) {
> + pcrs.count < 1) {
> printf("%s: too many pcrs: %u\n", __func__, pcrs.count);
> return -EMSGSIZE;
> }
> @@ -1135,10 +1386,10 @@ int tpm2_get_pcr_info(struct udevice *dev, u32 *supported_pcr, u32 *active_pcr,
> i * ((num_pcr + 7) / 8);
> u32 size_select_offset =
> hash_offset + offsetof(struct tpms_pcr_selection,
> - size_of_select);
> + size_of_select);
> u32 pcr_select_offset =
> hash_offset + offsetof(struct tpms_pcr_selection,
> - pcr_select);
> + pcr_select);
>
> pcrs.selection[i].hash =
> get_unaligned_be16(response + hash_offset);
> @@ -1146,12 +1397,12 @@ int tpm2_get_pcr_info(struct udevice *dev, u32 *supported_pcr, u32 *active_pcr,
> __get_unaligned_be(response + size_select_offset);
> if (pcrs.selection[i].size_of_select > TPM2_PCR_SELECT_MAX) {
> printf("%s: pcrs selection too large: %u\n", __func__,
> - pcrs.selection[i].size_of_select);
> + pcrs.selection[i].size_of_select);
> return -ENOBUFS;
> }
> /* copy the array of pcr_select */
> memcpy(pcrs.selection[i].pcr_select, response + pcr_select_offset,
> - pcrs.selection[i].size_of_select);
> + pcrs.selection[i].size_of_select);
> }
>
> for (i = 0; i < pcrs.count; i++) {
> @@ -1163,7 +1414,7 @@ int tpm2_get_pcr_info(struct udevice *dev, u32 *supported_pcr, u32 *active_pcr,
> *active_pcr |= hash_mask;
> } else {
> printf("%s: unknown algorithm %x\n", __func__,
> - pcrs.selection[i].hash);
> + pcrs.selection[i].hash);
> }
> }
>
> @@ -1196,10 +1447,10 @@ u32 tpm2_dam_reset(struct udevice *dev, const char *pw, const ssize_t pw_sz)
>
> /*
> * Fill the command structure starting from the first buffer:
> - * - the password (if any)
> + * - the password (if any)
> */
> ret = pack_byte_string(command_v2, sizeof(command_v2), "s",
> - offset, pw, pw_sz);
> + offset, pw, pw_sz);
> offset += pw_sz;
> if (ret)
> return TPM_LIB_ERROR;
> @@ -1511,7 +1762,7 @@ u32 tpm2_submit_command(struct udevice *dev, const u8 *sendbuf,
> }
>
> u32 tpm2_report_state(struct udevice *dev, uint vendor_cmd, uint vendor_subcmd,
> - u8 *recvbuf, size_t *recv_size)
> + u8 *recvbuf, size_t *recv_size)
> {
> u8 command_v2[COMMAND_BUFFER_SIZE] = {
> /* header 10 bytes */
> diff --git a/lib/tpm_api.c b/lib/tpm_api.c
> index 39a5121e30..5875e7b085 100644
> --- a/lib/tpm_api.c
> +++ b/lib/tpm_api.c
> @@ -128,7 +128,7 @@ u32 tpm_nv_read_value(struct udevice *dev, u32 index, void *data, u32 count)
> if (tpm_is_v1(dev))
> return tpm1_nv_read_value(dev, index, data, count);
> else if (tpm_is_v2(dev))
> - return tpm2_nv_read_value(dev, index, data, count);
> + return tpm2_nv_read_value(dev, index, data, count, NULL);
> else
> return -ENOSYS;
> }
> @@ -139,7 +139,7 @@ u32 tpm_nv_write_value(struct udevice *dev, u32 index, const void *data,
> if (tpm_is_v1(dev))
> return tpm1_nv_write_value(dev, index, data, count);
> else if (tpm_is_v2(dev))
> - return tpm2_nv_write_value(dev, index, data, count);
> + return tpm2_nv_write_value(dev, index, data, count, NULL);
> else
> return -ENOSYS;
> }
> --
> 2.34.1
> ===========================END PATCH=======================
> ________________________________
> 差出人: Ilias Apalodimas <ilias.apalodimas at linaro.org>
> 送信日時: 2024年3月5日 19:47
> 宛先: Niek Nooijens / OC-IAB PBD-C DEVEL 1-1 <niek.nooijens at omron.com>
> CC: u-boot at lists.denx.de <u-boot at lists.denx.de>
> 件名: Re: [PATCH] implement policy_pcr commands to lock NV-indexes behind a PCR
>
> [ilias.apalodimas at linaro.org からのメールを受け取る頻度は高くありません。これが問題である可能性の理由については、https://aka.ms/LearnAboutSenderIdentification をご覧ください。]
>
> On Tue, 20 Feb 2024 at 07:59, niek.nooijens at omron.com
> <niek.nooijens at omron.com> wrote:
> >
> > Hi there
> >
> > After the NV-memory read/write code I'm here again for another patch.
> > This time I implemented code to allow an NV-index to be locked behind a PCR value.
> > This can be used together with the new measured-boot code allowing you to store encryption keys inside the TPM and locking them behind PCR's.
> > To do that you:
> >
> > set the PCR's to some value
> > start an auth session
> > create a policy_pcr
> > get that policy's digest
> > use NV_define together with the policy digest.
> > use nv_write together with the session handle in which the policy_digest was generated.
> >
> > After another PCR extend, the NV index will be locked and cannot be read.
> > At next boot, when the PCR's are in the correct state again, you can read the NV_index by authenticating with a PCR value.
> > To do that you:
> >
> > set the PCR's to the correct value
> > start an auth session
> > create a policy_pcr
> > nv_read whilst providing the session handle in which the policy was created.
> >
> >
> > It might not be perfect yet, but at least it vastly extends the TPM capabilities of uboot.
> > I generated the patch against latest github master.
> > Feedback is welcome.
> >
> > Niek
> >
> > =================START PATCH========================
> > From 8d3ea3130794d9db51d95056eb42044a2c5d9f4f Mon Sep 17 00:00:00 2001
> > From: Niek Nooijens <niek.nooijens at omron.com>
> > Date: Tue, 20 Feb 2024 13:42:57 +0900
> > Subject: [PATCH] implement policy_pcr commands to lock NV-indexes behind a PCR
> > policy
> >
> > Signed-off-by: Niek Nooijens <niek.nooijens at omron.com>
> > ---
> > cmd/tpm-v2.c | 258 +++++++++++++++++++++++++++++++
> > include/tpm-common.h | 2 +
> > include/tpm-v2.h | 126 ++++++++++++---
> > lib/tpm-v2.c | 355 +++++++++++++++++++++++++++++++++++++------
> > lib/tpm_api.c | 4 +-
> > 5 files changed, 669 insertions(+), 76 deletions(-)
> >
> > diff --git a/cmd/tpm-v2.c b/cmd/tpm-v2.c
> > index 7e479b9dfe..6b6f4629ea 100644
> > --- a/cmd/tpm-v2.c
> > +++ b/cmd/tpm-v2.c
> > @@ -356,6 +356,222 @@ static int do_tpm_pcr_setauthvalue(struct cmd_tbl *cmdtp, int flag,
> > key, key_sz));
> > }
> >
> > +static int do_tpm_nv_define(struct cmd_tbl *cmdtp, int flag,
> > + int argc, char *const argv[])
> > +{
> > + struct udevice *dev;
> > + struct tpm_chip_priv *priv;
> > + u32 nv_addr, nv_size, rc;
> > + void *policy_addr = NULL;
> > + size_t policy_size = 0;
> > + int ret;
> > +
> > + u32 nv_attributes = TPMA_NV_PLATFORMCREATE | TPMA_NV_OWNERWRITE | TPMA_NV_OWNERREAD | TPMA_NV_PPWRITE | TPMA_NV_PPREAD;
>
> You need to break this at 80 chars
> u32 nv_attributes = TPMA_NV_PLATFORMCREATE | TPMA_NV_OWNERWRITE | \
> ...etc
>
> > +
> > + if (argc < 3 && argc > 7)
> > + return CMD_RET_USAGE;
> > +
> > + ret = get_tpm(&dev);
> > + if (ret)
> > + return ret;
> > +
> > + priv = dev_get_uclass_priv(dev);
> > + if (!priv)
> > + return -EINVAL;
> > +
> > + nv_addr = simple_strtoul(argv[1], NULL, 0);
> > +
> > + nv_size = simple_strtoul(argv[2], NULL, 0);
> > +
> > + if (argc > 3)
> > + nv_attributes = simple_strtoul(argv[3], NULL, 0);
> > +
> > + if (argc > 4) {
> > + policy_addr = map_sysmem(simple_strtoul(argv[4], NULL, 0), 0);
> > + nv_attributes |= (TPMA_NV_POLICYREAD | TPMA_NV_POLICYWRITE); //obligated, might as well force it
>
> I am not sure I understand the comment
>
> > + if (argc < 5)
> > + return CMD_RET_USAGE;
> > + policy_size = simple_strtoul(argv[5], NULL, 0);
> > + }
> > +
> > + rc = tpm2_nv_define_space(dev, nv_addr, nv_size, nv_attributes, policy_addr, policy_size);
> > +
>
> You don't need an empty line here
>
> > + if (rc)
> > + printf("ERROR: nv_define #%u returns: 0x%x\n", nv_addr, rc);
> > +
> > + if (policy_addr)
> > + unmap_sysmem(policy_addr);
>
> Later down the code, you unconditionally call unmap_sysmem even for
> NULL. I don't think we need the check here either
>
> > +
> > + return report_return_code(rc);
> > +}
> > +
> > +static int do_tpm_nv_undefine(struct cmd_tbl *cmdtp, int flag,
> > + int argc, char *const argv[])
> > +{
> > + struct udevice *dev;
> > + u32 nv_addr, ret, rc;
> > +
> > + ret = get_tpm(&dev);
> > + if (ret)
> > + return ret;
> > +
> > + if (argc != 2)
> > + return CMD_RET_USAGE;
> > +
> > + nv_addr = simple_strtoul(argv[1], NULL, 0);
> > + rc = tpm2_nv_undefine_space(dev, nv_addr);
> > +
> > + return report_return_code(rc);
> > +}
> > +
> > +static int do_tpm_nv_read_value(struct cmd_tbl *cmdtp, int flag,
> > + int argc, char *const argv[])
> > +{
> > + struct udevice *dev;
> > + u32 nv_addr, nv_size, rc;
> > + void *session_addr = NULL;
> > + int ret;
> > + void *out_data;
> > +
> > + ret = get_tpm(&dev);
> > + if (ret)
> > + return ret;
> > +
> > + if (argc < 4)
> > + return CMD_RET_USAGE;
> > +
> > + nv_addr = simple_strtoul(argv[1], NULL, 0);
> > +
> > + nv_size = simple_strtoul(argv[2], NULL, 0);
> > +
> > + out_data = map_sysmem(simple_strtoul(argv[3], NULL, 0), 0);
> > +
>
> Get rid of the empty lines before if() statements in the entire patch please.
>
> > + if (argc == 5)
> > + session_addr = map_sysmem(simple_strtoul(argv[4], NULL, 0), 0);
> > +
> > + rc = tpm2_nv_read_value(dev, nv_addr, out_data, nv_size, session_addr);
>
> What happens if session_addr is NULL?
>
> > +
> > + if (rc)
> > + printf("ERROR: nv_read #%u returns: #%u\n", nv_addr, rc);
> > +
> > + unmap_sysmem(out_data);
> > + return report_return_code(rc);
> > +}
> > +
> > +static int do_tpm_nv_write_value(struct cmd_tbl *cmdtp, int flag,
> > + int argc, char *const argv[]) //TODO: session handle from auth session!
>
> Please explain that TODO in more detail
>
> > +{
> > + struct udevice *dev;
> > + u32 nv_addr, nv_size, rc;
> > + void *session_addr = NULL;
> > + int ret;
> > +
> > + ret = get_tpm(&dev);
> > + if (ret)
> > + return ret;
> > +
> > + if (argc < 4)
> > + return CMD_RET_USAGE;
> > +
> > + nv_addr = simple_strtoul(argv[1], NULL, 0); //tpm_addr
> > +
> > + nv_size = simple_strtoul(argv[2], NULL, 0); //size
> > +
> > + void *data_to_write = map_sysmem(simple_strtoul(argv[3], NULL, 0), 0);
> > +
> > + if (argc == 5)
> > + session_addr = map_sysmem(simple_strtoul(argv[4], NULL, 0), 0);
> > +
> > + rc = tpm2_nv_write_value(dev, nv_addr, data_to_write, nv_size, session_addr);
> > +
> > + if (rc)
> > + printf("ERROR: nv_write #%u returns: #%u\n", nv_addr, rc);
> > +
> > + unmap_sysmem(session_addr);
> > + unmap_sysmem(data_to_write);
> > + return report_return_code(rc);
> > +}
> > +
> > +static int do_start_auth_session(struct cmd_tbl *cmdtp, int flag,
> > + int argc, char *const argv[])
> > +{
> > + struct udevice *dev;
> > + u32 rc;
> > + u8 session_type = TPM_SE_POLICY;
> > + int ret;
> > +
> > + ret = get_tpm(&dev);
> > +
> > + if (argc < 2)
> > + return CMD_RET_USAGE;
> > +
> > + void *data_to_write = map_sysmem(simple_strtoul(argv[1], NULL, 0), 0);
> > +
> > + if (argc > 2)
> > + session_type = simple_strtoul(argv[2], NULL, 0);
> > +
> > + rc = tpm2_start_auth_session(dev, data_to_write, session_type);
> > +
> > + if (rc)
> > + printf("ERROR: start_auth_session returns: #%u\n", rc);
> > +
> > + unmap_sysmem(data_to_write);
> > + return report_return_code(rc);
> > +}
> > +
> > +static int do_flush_context(struct cmd_tbl *cmdtp, int flag,
> > + int argc, char *const argv[])
> > +{
> > + struct udevice *dev;
> > + u32 rc;
> > + int ret;
> > +
> > + ret = get_tpm(&dev);
> > +
> > + if (argc < 2)
> > + return CMD_RET_USAGE;
> > +
> > + void *data_to_read = map_sysmem(simple_strtoul(argv[1], NULL, 0), 0);
> > + u32 session_handle = *((u32 *)data_to_read);
> > +
> > + rc = tpm2_flush_context(dev, session_handle);
> > +
> > + if (rc)
> > + printf("ERROR: flush_context returns: #%u\n", rc);
> > +
> > + unmap_sysmem(data_to_read);
> > + return report_return_code(rc);
> > +}
> > +
> > +static int do_policy_pcr(struct cmd_tbl *cmdtp, int flag,
> > + int argc, char *const argv[])
> > +{
> > + struct udevice *dev;
> > + u32 rc, pcr;
> > + int ret;
> > +
> > + ret = get_tpm(&dev);
> > +
> > + if (argc != 4)
> > + return CMD_RET_USAGE;
> > +
> > + void *data_to_read = map_sysmem(simple_strtoul(argv[1], NULL, 0), 0);
> > + u32 session_handle = *((u32 *)data_to_read);
> > +
> > + pcr = simple_strtoul(argv[2], NULL, 0);
> > +
> > + void *out_digest = map_sysmem(simple_strtoul(argv[3], NULL, 0), 0);
> > +
> > + rc = tpm2_set_policy_pcr(dev, session_handle, pcr, out_digest);
> > +
> > + if (rc)
> > + printf("ERROR: policy_pcr returns: #%u\n", rc);
> > +
> > + unmap_sysmem(data_to_read);
> > + unmap_sysmem(out_digest);
> > + return report_return_code(rc);
> > +}
> > +
> > static struct cmd_tbl tpm2_commands[] = {
> > U_BOOT_CMD_MKENT(device, 0, 1, do_tpm_device, "", ""),
> > U_BOOT_CMD_MKENT(info, 0, 1, do_tpm_info, "", ""),
> > @@ -375,6 +591,13 @@ static struct cmd_tbl tpm2_commands[] = {
> > do_tpm_pcr_setauthpolicy, "", ""),
> > U_BOOT_CMD_MKENT(pcr_setauthvalue, 0, 1,
> > do_tpm_pcr_setauthvalue, "", ""),
> > + U_BOOT_CMD_MKENT(nv_define, 0, 1, do_tpm_nv_define, "", ""),
> > + U_BOOT_CMD_MKENT(nv_undefine, 0, 1, do_tpm_nv_undefine, "", ""),
> > + U_BOOT_CMD_MKENT(nv_read, 0, 1, do_tpm_nv_read_value, "", ""),
> > + U_BOOT_CMD_MKENT(nv_write, 0, 1, do_tpm_nv_write_value, "", ""),
> > + U_BOOT_CMD_MKENT(start_auth_session, 0, 1, do_start_auth_session, "", ""),
> > + U_BOOT_CMD_MKENT(flush_context, 0, 1, do_flush_context, "", ""),
> > + U_BOOT_CMD_MKENT(policy_pcr, 0, 1, do_policy_pcr, "", ""),
> > };
> >
> > struct cmd_tbl *get_tpm2_commands(unsigned int *size)
> > @@ -453,4 +676,40 @@ U_BOOT_CMD(tpm2, CONFIG_SYS_MAXARGS, 1, do_tpm, "Issue a TPMv2.x command",
> > " <pcr>: index of the PCR\n"
> > " <key>: secret to protect the access of PCR #<pcr>\n"
> > " <password>: optional password of the PLATFORM hierarchy\n"
> > +"\n"
> > +"nv_define <tpm_addr> <size> [<attributes> <policy_digest_addr> <policy_size>]\n"
> > +" Define new nv index in the TPM at <tpm_addr> with size <size>\n"
> > +" <tpm_addr>: the internal address used within the TPM for the NV-index\n"
> > +" <attributes>: is described in tpm-v2.h enum tpm_index_attrs. Note; Always use TPMA_NV_PLATFORMCREATE!\n"
> > +" will default to: TPMA_NV_PLATFORMCREATE|TPMA_NV_OWNERWRITE|TPMA_NV_OWNERREAD|TPMA_NV_PPWRITE|TPMA_NV_PPREAD\n"
> > +" <policy_digest_addr>: address to a policy digest. (e.g. a PCR value)\n"
> > +" <policy_size>: size of the digest in bytes\n"
> > +"nv_undefine <tpm_addr>\n"
> > +" delete nv index\n"
> > +"nv_read <tpm_addr> <size> <data_addr> [<session_handle_addr>]\n"
> > +" Read data stored in TPM nv_memory at <tpm_addr> with size <size>\n"
> > +" <tpm_addr>: the internal address used within the TPM for the NV-index\n"
> > +" <size>: datasize in bytes\n"
> > +" <data_addr>: memory address where to store the data read from the TPM\n"
> > +" <session_handle_addr>: addr where the session handle is stored\n"
> > +"nv_write <tpm_addr> <size> <data_addr> [<session_handle_addr>]\n"
> > +" Write data to the TPM's nv_memory at <tpm_addr> with size <size>\n"
> > +" <tpm_addr>: the internal address used within the TPM for the NV-index\n"
> > +" <size>: datasize in bytes\n"
> > +" <data_addr>: memory address of the data to be written to the TPM's NV-index\n"
> > +" <session_handle_addr>: addr where the session handle is stored\n"
> > +"start_auth_session <session_handle_addr> [<session_type>]\n"
> > +" Start an authorization session and store it's handle at <session_handle_addr>\n"
> > +" <session_handle_addr>: addr where to store the handle data (4 bytes)\n"
> > +" <session_type>: type of session: 0x00 for HMAC, 0x01 for policy, 0x03 for trial\n"
> > +" will default to 0x01 (TPM_SE_POLICY) if not provided\n"
> > +" to create a policy, use TPM_SE_TRIAL (0x03), to authenticate TPM_SE_POLICY (0x01)\n"
> > +"flush_context <session_handle_addr>\n"
> > +" flush/terminate a session which's handle is stored at <session_handle_addr>\n"
> > +" <session_handle_addr>: addr where the session handle is stored\n"
> > +"policy_pcr <session_handle_addr> <pcr> <digest_addr>\n"
> > +" create a policy to authorize using a PCR\n"
> > +" <session_handle_addr>: addr where the session handle is stored\n"
> > +" <pcr>: index of the PCR\n"
> > +" <digest_addr>: addr where to store the policy digest (for nv_define/nv_read/write)\n"
> > );
> > diff --git a/include/tpm-common.h b/include/tpm-common.h
> > index 1ba81386ce..5620454da7 100644
> > --- a/include/tpm-common.h
> > +++ b/include/tpm-common.h
> > @@ -69,6 +69,8 @@ struct tpm_chip_priv {
> > uint pcr_count;
> > uint pcr_select_min;
> > bool plat_hier_disabled;
> > + u16 nonce_sz;
> > + u8 nonce[32]; //NONCE_TPM_SIZE;
>
> Add this on a define on the header file and use it, instead of adding a comment
>
>
> > };
> >
> > /**
> > diff --git a/include/tpm-v2.h b/include/tpm-v2.h
> > index 33dd103767..5b60883777 100644
> > --- a/include/tpm-v2.h
> > +++ b/include/tpm-v2.h
> > @@ -301,7 +301,8 @@ enum tpm2_startup_types {
> > */
> > enum tpm2_handles {
> > TPM2_RH_OWNER = 0x40000001,
> > - TPM2_RS_PW = 0x40000009,
> > + TPM2_RH_NULL = 0x40000007,
> > + TPM2_RS_PW = 0x40000009,
> > TPM2_RH_LOCKOUT = 0x4000000A,
> > TPM2_RH_ENDORSEMENT = 0x4000000B,
> > TPM2_RH_PLATFORM = 0x4000000C,
> > @@ -325,24 +326,30 @@ enum tpm2_handles {
> > * @TPM2_CC_PCR_SETAUTHVAL: TPM2_PCR_SetAuthValue().
> > */
> > enum tpm2_command_codes {
> > - TPM2_CC_STARTUP = 0x0144,
> > - TPM2_CC_SELF_TEST = 0x0143,
> > - TPM2_CC_HIER_CONTROL = 0x0121,
> > - TPM2_CC_CLEAR = 0x0126,
> > - TPM2_CC_CLEARCONTROL = 0x0127,
> > - TPM2_CC_HIERCHANGEAUTH = 0x0129,
> > - TPM2_CC_NV_DEFINE_SPACE = 0x012a,
> > - TPM2_CC_PCR_SETAUTHPOL = 0x012C,
> > - TPM2_CC_NV_WRITE = 0x0137,
> > - TPM2_CC_NV_WRITELOCK = 0x0138,
> > - TPM2_CC_DAM_RESET = 0x0139,
> > - TPM2_CC_DAM_PARAMETERS = 0x013A,
> > - TPM2_CC_NV_READ = 0x014E,
> > - TPM2_CC_GET_CAPABILITY = 0x017A,
> > - TPM2_CC_GET_RANDOM = 0x017B,
> > - TPM2_CC_PCR_READ = 0x017E,
> > - TPM2_CC_PCR_EXTEND = 0x0182,
> > - TPM2_CC_PCR_SETAUTHVAL = 0x0183,
> > + TPM2_CC_STARTUP = 0x0144,
> > + TPM2_CC_SELF_TEST = 0x0143,
> > + TPM2_CC_HIER_CONTROL = 0x0121,
> > + TPM2_CC_CLEAR = 0x0126,
>
> Some of the values you added include an extra tab, can you indent all
> of these properly?
>
> > + TPM2_CC_CLEARCONTROL = 0x0127,
> > + TPM2_CC_HIERCHANGEAUTH = 0x0129,
> > + TPM2_CC_NV_DEFINE_SPACE = 0x012a,
> > + TPM2_CC_NV_UNDEFINE_SPACE = 0x0122,
> > + TPM2_CC_PCR_SETAUTHPOL = 0x012C,
> > + TPM2_CC_CREATE_PRIMARY = 0x0131,
> > + TPM2_CC_NV_WRITE = 0x0137,
> > + TPM2_CC_NV_WRITELOCK = 0x0138,
> > + TPM2_CC_DAM_RESET = 0x0139,
> > + TPM2_CC_DAM_PARAMETERS = 0x013A,
> > + TPM2_CC_NV_READ = 0x014E,
> > + TPM2_CC_FLUSH_CONTEXT = 0x0165,
> > + TPM2_CC_START_AUTH_SESSION = 0x0176,
> > + TPM2_CC_GET_CAPABILITY = 0x017A,
> > + TPM2_CC_GET_RANDOM = 0x017B,
> > + TPM2_CC_PCR_READ = 0x017E,
> > + TPM2_CC_POLICY_PCR = 0x017F,
> > + TPM2_CC_PCR_EXTEND = 0x0182,
> > + TPM2_CC_PCR_SETAUTHVAL = 0x0183,
> > + TPM2_CC_POLICY_GET_DIGEST = 0x0189,
> > };
> >
> > /**
> > @@ -384,6 +391,16 @@ enum tpm2_algorithms {
> > TPM2_ALG_SHA512 = 0x0D,
> > TPM2_ALG_NULL = 0x10,
> > TPM2_ALG_SM3_256 = 0x12,
> > + TPM2_ALG_ECC = 0x23,
> > +};
> > +
> > +/**
> > + * TPM2 session types.
> > + */
> > +enum tpm2_se {
> > + TPM_SE_HMAC = 0x00,
> > + TPM_SE_POLICY = 0x01,
> > + TPM_SE_TRIAL = 0x03,
> > };
> >
> > extern const enum tpm2_algorithms tpm2_supported_algorithms[4];
> > @@ -700,6 +717,51 @@ u32 tpm2_self_test(struct udevice *dev, enum tpm2_yes_no full_test);
> > u32 tpm2_clear(struct udevice *dev, u32 handle, const char *pw,
> > const ssize_t pw_sz);
> >
> > +/**
> > + * Issue a TPM2_StartAuthSession command. (chaining several commands together that need authorization)
> > + *
> > + * @dev TPM device
> > + * @session_handle Pointer to memory where to store the session handle.
> > + * @session_type tpm2_se value to indicate session type (usually TPM_SE_POLICY)
> > + *
> > + * Return: code of the operation
> > + */
> > +u32 tpm2_start_auth_session(struct udevice *dev, u32 *session_handle, u8 session_type);
> > +/**
> > + * Issue a TPM2_FlushContext command. (for ending the authorization session)
> > + *
> > + * @dev TPM device
> > + * @session_handle Authorization session to be terminated.
> > + *
> > + * Return: code of the operation
> > + */
> > +u32 tpm2_flush_context(struct udevice *dev, u32 session_handle);
> > +
> > +/**
> > + * Issue a TPM2_PolicyPCR command. (for authenticating using a PCR value)
> > + *
> > + * @dev TPM device
> > + * @session_handle policy session handle started with start_auth_session.
> > + * @index Index of the PCR
> > + *
> > + * @note For now only 1 PCR selection is supported,
> > + * since the value of one PCR can be extended with the value of another.
> > + * This achieves the same effect as selecting multiple PCR's
> > + * @out_digest addr where to write the digest
>
> The comments should be like this
> @dev: TPM device
> @session_handle: ....
> etc
> Please fix them on all functions
>
> > + * Return: code of the operation
> > + */
> > +u32 tpm2_set_policy_pcr(struct udevice *dev, u32 session_handle, u32 index, void *out_digest);
> > +
> > +/**
> > + * Issue a TPM2_getPolicyDigest command.
> > + *
> > + * @dev TPM device
> > + * @session_handle policy session handle started with start_auth_session.
> > + * @out_digest addr where to write the digest (size is always 0x20 / TPM2_SHA256_DIGEST_SIZE)
> > + * Return: code of the operation
> > + */
> > +u32 tpm2_get_policy_digest(struct udevice *dev, u32 session_handle, void *out_digest);
> > +
> > /**
> > * Issue a TPM_NV_DefineSpace command
> > *
> > @@ -709,6 +771,7 @@ u32 tpm2_clear(struct udevice *dev, u32 handle, const char *pw,
> > * @space_index index of the area
> > * @space_size size of area in bytes
> > * @nv_attributes TPM_NV_ATTRIBUTES of the area
> > + * @session_handle handle to a session. can be TPM2_RS_PW
> > * @nv_policy policy to use
> > * @nv_policy_size size of the policy
> > * Return: return code of the operation
> > @@ -717,6 +780,17 @@ u32 tpm2_nv_define_space(struct udevice *dev, u32 space_index,
> > size_t space_size, u32 nv_attributes,
> > const u8 *nv_policy, size_t nv_policy_size);
> >
> > +/**
> > + * Issue a TPM_NV_UnDefineSpace command
> > + *
> > + * This allows a space to be removed. Needed because TPM_clear doesn't clear platform entries
> > + *
> > + * @dev TPM device
> > + * @space_index index of the area
> > + * Return: return code of the operation
> > + */
> > +u32 tpm2_nv_undefine_space(struct udevice *dev, u32 space_index);
> > +
> > /**
> > * Issue a TPM2_PCR_Extend command.
> > *
> > @@ -734,13 +808,14 @@ u32 tpm2_pcr_extend(struct udevice *dev, u32 index, u32 algorithm,
> > /**
> > * Read data from the secure storage
> > *
> > - * @dev TPM device
> > - * @index Index of data to read
> > - * @data Place to put data
> > - * @count Number of bytes of data
> > + * @dev TPM device
> > + * @index Index of data to read
> > + * @data Place to put data
> > + * @count Number of bytes of data
> > + * @session_handle handle of a running authorization session. if NULL->password authorization
> > * Return: code of the operation
> > */
> > -u32 tpm2_nv_read_value(struct udevice *dev, u32 index, void *data, u32 count);
> > +u32 tpm2_nv_read_value(struct udevice *dev, u32 index, void *data, u32 count, u32 *session_handle);
> >
> > /**
> > * Write data to the secure storage
> > @@ -749,10 +824,11 @@ u32 tpm2_nv_read_value(struct udevice *dev, u32 index, void *data, u32 count);
> > * @index Index of data to write
> > * @data Data to write
> > * @count Number of bytes of data
> > + * @session_handle handle of a running authorization session. if NULL->password authorization
> > * Return: code of the operation
> > */
> > u32 tpm2_nv_write_value(struct udevice *dev, u32 index, const void *data,
> > - u32 count);
> > + u32 count, u32 *session_handle);
> >
> > /**
> > * Issue a TPM2_PCR_Read command.
> > diff --git a/lib/tpm-v2.c b/lib/tpm-v2.c
> > index 68eaaa639f..3d5e4e8343 100644
> > --- a/lib/tpm-v2.c
> > +++ b/lib/tpm-v2.c
> > @@ -786,19 +787,192 @@ u32 tpm2_clear(struct udevice *dev, u32 handle, const char *pw,
> > return tpm_sendrecv_command(dev, command_v2, NULL, NULL);
> > }
> >
> > +u32 tpm2_start_auth_session(struct udevice *dev, u32 *session_handle, u8 session_type)
> > +{
> > + const u16 nonce_size = TPM2_SHA256_DIGEST_SIZE;
> > + const int handles_len = sizeof(u32) * 2;
> > + uint offset = TPM2_HDR_LEN + handles_len + 2;
> > + struct tpm_chip_priv *priv;
> > +
> > + priv = dev_get_uclass_priv(dev);
> > + if (!priv)
> > + return TPM_LIB_ERROR;
> > +
> > + u8 command_v2[COMMAND_BUFFER_SIZE] = {
> > + /* header 10 bytes */
> > + tpm_u16(TPM2_ST_NO_SESSIONS), /* TAG */
> > + tpm_u32(offset + nonce_size + 7),/* Length */
> > + tpm_u32(TPM2_CC_START_AUTH_SESSION),/* Command code */
> > +
> > + /* handles 8 bytes */
> > + tpm_u32(TPM2_RH_NULL), /* TPMI_DH_OBJECT+ */
> > + tpm_u32(TPM2_RH_NULL), /* TPMI_DH_ENTITY+ */
> > +
> > + /* NONCE 32 bytes -> use pack_byte_string() */
> > + tpm_u16(nonce_size),
> > + /* message 7 bytes -> use pack_byte_string() */
> > + //tpm_u16(0), // salt size
> > + //session_type, // session type
> > + //tpm_u16(TPM2_ALG_NULL), // symmetric key algorythm
> > + //tpm_u16(TPM2_ALG_SHA256), // auth hash
> > + };
> > + u8 Nonce[nonce_size]; //nonce is a random number you use once. (Number ONCE)
> > +
> > + memset(&Nonce, 2, nonce_size); //should use TPM_get_random() to randomize
> > + int ret;
> > +
> > + ret = pack_byte_string(command_v2, sizeof(command_v2), "swbww",
> > + offset, Nonce, nonce_size,
> > + offset + nonce_size, 0, //salt size
> > + offset + nonce_size + 2, session_type,
> > + offset + nonce_size + 3, TPM2_ALG_NULL,
> > + offset + nonce_size + 5, TPM2_ALG_SHA256);
> > +
> > + if (ret)
> > + return TPM_LIB_ERROR;
> > +
> > + size_t response_len = COMMAND_BUFFER_SIZE;
> > + u8 response[COMMAND_BUFFER_SIZE];
> > + u16 tag;
> > + u32 size, code;
> > +
> > + ret = tpm_sendrecv_command(dev, command_v2, response, &response_len);
> > +
> > + if (ret)
> > + return log_msg_ret("read", ret);
> > +
> > + if (unpack_byte_string(response, response_len, "wdddws",
> > + 0, &tag, 2, &size, 6, &code, //header
> > + 10, session_handle, //TPMI_SH_AUTH_SESSION
> > + 14, &priv->nonce_sz,
> > + 16, priv->nonce, TPM2_SHA256_DIGEST_SIZE)) //HACK: we asked for a SHA256, so that's what we'll get. if ret == 0 at least
> > + return TPM_LIB_ERROR;
> > +
> > + return ret;
> > +}
> > +
> > +u32 tpm2_flush_context(struct udevice *dev, u32 session_handle)
> > +{
> > + u8 command_v2[COMMAND_BUFFER_SIZE] = {
> > + /* header 10 bytes */
> > + tpm_u16(TPM2_ST_NO_SESSIONS), /* TAG */
> > + tpm_u32(TPM2_HDR_LEN + sizeof(u32)),/* Length */
> > + tpm_u32(TPM2_CC_FLUSH_CONTEXT),/* Command code */
> > +
> > + /* session handle 4 bytes */
> > + tpm_u32(session_handle), /* TPMI_DH_CONTEXT+ */
> > + };
> > + return tpm_sendrecv_command(dev, command_v2, NULL, NULL);
> > +}
> > +
> > +u32 tpm2_set_policy_pcr(struct udevice *dev, u32 session_handle, u32 index, void *out_digest)
> > +{
> > + const int offset = TPM2_HDR_LEN + 6;
> > + const int message_len = offset + TPM2_SHA256_DIGEST_SIZE + 10;
> > +
> > + u8 pcr_sel_bit = BIT(index % 8);
> > + struct tpm_chip_priv *priv;
> > + struct tpml_digest_values digest_list;
> > +
> > + digest_list.count = 1;
> > + digest_list.digests->hash_alg = TPM2_ALG_SHA256;
> > + tcg2_pcr_read(dev, index, &digest_list);
> > +
> > + u8 pcr_sha_output[TPM2_SHA256_DIGEST_SIZE];
> > + sha256_context ctx_256;
> > +
> > + sha256_starts(&ctx_256);
> > + sha256_update(&ctx_256, digest_list.digests[0].digest.sha256, TPM2_SHA256_DIGEST_SIZE);
> > + sha256_finish(&ctx_256, pcr_sha_output);
> > +
> > + priv = dev_get_uclass_priv(dev);
> > + if (!priv)
> > + return TPM_LIB_ERROR;
> > +
> > + u8 idx_array_sz = max(priv->pcr_select_min, DIV_ROUND_UP(index, 8));
> > +
> > + u8 command_v2[COMMAND_BUFFER_SIZE] = {
> > + /* header 10 bytes */
> > + tpm_u16(TPM2_ST_NO_SESSIONS), /* TAG -> TPM2_ST_SESSIONS only for audit or decrypt*/
> > + tpm_u32(message_len),/* Length */
> > + tpm_u32(TPM2_CC_POLICY_PCR),/* Command code */
> > + /* session handle 4 bytes */
> > + tpm_u32(session_handle), /* TPMI_SH_POLICY */
> > + /* PCR Digest - 32 bytes */
> > + tpm_u16(TPM2_SHA256_DIGEST_SIZE) /*hash size*/
> > + /* digest - 32-bytes */
> > + /* PCR selection */
> > + //tpm_u32(1), /* Number of selections */
> > + //tpm_u16(TPM_ALG_SHA256), /* Algorithm of the hash */
> > + //idx_array_sz, /* Array size for selection */
> > + /* bitmap(idx) Selected PCR bitmap */
> > + };
> > +
> > + if (pack_byte_string(command_v2, COMMAND_BUFFER_SIZE, "sdwbbw",
> > + offset, pcr_sha_output, TPM2_SHA256_DIGEST_SIZE,
> > + offset + TPM2_SHA256_DIGEST_SIZE, 1, /* Number of selections */
> > + offset + TPM2_SHA256_DIGEST_SIZE + 4, TPM2_ALG_SHA256, /* Algorithm of the hash */
> > + offset + TPM2_SHA256_DIGEST_SIZE + 6, idx_array_sz, /* Array size for selection */
> > + offset + TPM2_SHA256_DIGEST_SIZE + 7, pcr_sel_bit,/* Selected PCR bitmap */
> > + offset + TPM2_SHA256_DIGEST_SIZE + 8, 0)) /*padding */
> > + return TPM_LIB_ERROR;
> > +
> > + int ret = tpm_sendrecv_command(dev, command_v2, NULL, NULL);
> > +
> > + if (ret)
> > + return ret;
> > +
> > + return tpm2_get_policy_digest(dev, session_handle, out_digest);
> > +}
> > +
> > +u32 tpm2_get_policy_digest(struct udevice *dev, u32 session_handle, void *out_digest)
> > +{
> > + const int message_len = TPM2_HDR_LEN + sizeof(u32);
> > +
> > + u8 command_v2[COMMAND_BUFFER_SIZE] = {
> > + /* header 10 bytes */
> > + tpm_u16(TPM2_ST_NO_SESSIONS), /* TAG -> only audit or decrypt session uses TPM2_ST_SESSIONS */
> > + tpm_u32(message_len),/* Length */
> > + tpm_u32(TPM2_CC_POLICY_GET_DIGEST),/* Command code */
> > + /* session handle 4 bytes */
> > + tpm_u32(session_handle), /* TPMI_SH_POLICY */
> > + };
> > +
> > + size_t response_len = COMMAND_BUFFER_SIZE;
> > + u8 response[COMMAND_BUFFER_SIZE];
> > + int ret;
> > + u16 tag;
> > + u32 size, code;
> > +
> > + ret = tpm_sendrecv_command(dev, command_v2, response, &response_len);
> > + if (ret)
> > + return log_msg_ret("read", ret);
> > +
> > + if (unpack_byte_string(response, response_len, "wdds",
> > + 0, &tag, 2, &size, 6, &code,
> > + 12, out_digest, TPM2_SHA256_DIGEST_SIZE)) //digest_size
> > + return TPM_LIB_ERROR;
> > +
> > + return ret;
> > +}
> > +
> > u32 tpm2_nv_define_space(struct udevice *dev, u32 space_index,
> > - size_t space_size, u32 nv_attributes,
> > - const u8 *nv_policy, size_t nv_policy_size)
> > + size_t space_size, u32 nv_attributes,
> > + const u8 *nv_policy, size_t nv_policy_size)
> > {
> > /*
> > * Calculate the offset of the nv_policy piece by adding each of the
> > * chunks below.
> > */
> > const int platform_len = sizeof(u32);
> > - const int session_hdr_len = 13;
> > + const int session_hdr_len = 15;
> > const int message_len = 14;
> > - uint offset = TPM2_HDR_LEN + platform_len + session_hdr_len +
> > - message_len;
> > + uint offset = TPM2_HDR_LEN + platform_len + session_hdr_len + message_len;
> > + u8 attrs = 0;
> > +
> > + //if(session_handle != TPM2_RS_PW)
> > + //attrs = 1; //continue_session (bit 1)
>
> Why is this commented out?
>
> > +
> > u8 command_v2[COMMAND_BUFFER_SIZE] = {
> > /* header 10 bytes */
> > tpm_u16(TPM2_ST_SESSIONS), /* TAG */
> > @@ -806,20 +979,24 @@ u32 tpm2_nv_define_space(struct udevice *dev, u32 space_index,
> > tpm_u32(TPM2_CC_NV_DEFINE_SPACE),/* Command code */
> >
> > /* handles 4 bytes */
> > - tpm_u32(TPM2_RH_PLATFORM), /* Primary platform seed */
> > + tpm_u32(TPM2_RH_PLATFORM), /* Primary platform seed, requires TPMA_NV_PLATFORMCREATE*/
> > +
> >
> > - /* session header 13 bytes */
> > + /* session header 15 bytes */
> > + /*null auth session*/
> > tpm_u32(9), /* Header size */
> > - tpm_u32(TPM2_RS_PW), /* Password authorisation */
> > + tpm_u32(TPM2_RS_PW),/* auth session handle if it's active, otherwise TPM2_RS_PW*/
> > tpm_u16(0), /* nonce_size */
> > - 0, /* session_attrs */
> > + attrs, /* session_attrs */
> > + tpm_u16(0), /* HMAC size */
> > + /*end auth area*/
> > tpm_u16(0), /* auth_size */
> >
> > /* message 14 bytes + policy */
> > tpm_u16(message_len + nv_policy_size), /* size */
> > tpm_u32(space_index),
> > tpm_u16(TPM2_ALG_SHA256),
> > - tpm_u32(nv_attributes),
> > + tpm_u32(nv_attributes | TPMA_NV_PLATFORMCREATE),
> > tpm_u16(nv_policy_size),
> > /*
> > * nv_policy
> > @@ -841,6 +1018,35 @@ u32 tpm2_nv_define_space(struct udevice *dev, u32 space_index,
> > return tpm_sendrecv_command(dev, command_v2, NULL, NULL);
> > }
> >
> > +u32 tpm2_nv_undefine_space(struct udevice *dev, u32 space_index)
> > +{
> > + const int platform_len = sizeof(u32);
> > + const int session_hdr_len = 13;
> > + const int message_len = 4;
> > + u8 command_v2[COMMAND_BUFFER_SIZE] = {
> > + /* header 10 bytes */
> > + tpm_u16(TPM2_ST_SESSIONS), /* TAG */
> > + tpm_u32(TPM2_HDR_LEN + platform_len + session_hdr_len +
> > + message_len),/* Length - header + provision + index + auth area*/
> > + tpm_u32(TPM2_CC_NV_UNDEFINE_SPACE),/* Command code */
> > +
> > + /* handles 4 bytes */
> > + tpm_u32(TPM2_RH_PLATFORM), /* Primary platform seed */
> > + /* nv_index */
> > + tpm_u32(space_index),
> > +
> > + /*null auth session*/
> > + tpm_u32(9), /* Header size */
> > + tpm_u32(TPM2_RS_PW), /* Password authorisation*/
> > + tpm_u16(0), /* nonce_size */
> > + 0, /* session_attrs */
> > + tpm_u16(0), /* HMAC size */
> > + /*end auth area*/
> > +
> > + };
> > + return tpm_sendrecv_command(dev, command_v2, NULL, NULL);
> > +}
> > +
> > u32 tpm2_pcr_extend(struct udevice *dev, u32 index, u32 algorithm,
> > const u8 *digest, u32 digest_len)
> > {
> > @@ -884,56 +1091,101 @@ u32 tpm2_pcr_extend(struct udevice *dev, u32 index, u32 algorithm,
> > return tpm_sendrecv_command(dev, command_v2, NULL, NULL);
> > }
> >
> > -u32 tpm2_nv_read_value(struct udevice *dev, u32 index, void *data, u32 count)
> > +u32 tpm2_nv_read_value(struct udevice *dev, u32 index, void *data, u32 count, u32 *session_handle)
> > {
> > - u8 command_v2[COMMAND_BUFFER_SIZE] = {
> > - /* header 10 bytes */
> > - tpm_u16(TPM2_ST_SESSIONS), /* TAG */
> > - tpm_u32(10 + 8 + 4 + 9 + 4), /* Length */
> > - tpm_u32(TPM2_CC_NV_READ), /* Command code */
> > + u32 offset = TPM2_HDR_LEN + 8 + 4 + 6;
> > + struct tpm_chip_priv *priv;
> >
> > - /* handles 8 bytes */
> > - tpm_u32(TPM2_RH_PLATFORM), /* Primary platform seed */
> > - tpm_u32(HR_NV_INDEX + index), /* Password authorisation */
> > + priv = dev_get_uclass_priv(dev);
> >
> > - /* AUTH_SESSION */
> > - tpm_u32(9), /* Authorization size */
> > - tpm_u32(TPM2_RS_PW), /* Session handle */
> > - tpm_u16(0), /* Size of <nonce> */
> > - /* <nonce> (if any) */
> > - 0, /* Attributes: Cont/Excl/Rst */
> > - tpm_u16(0), /* Size of <hmac/password> */
> > - /* <hmac/password> (if any) */
> > + if (!priv)
> > + return TPM_LIB_ERROR;
> > +
> > + u32 nonce_size = priv->nonce_sz;
> > +
> > + priv->nonce[nonce_size - 1]++; //increase nonce.
> > +
> > + u32 authorization = TPM2_RS_PW;
> >
> > - tpm_u16(count), /* Number of bytes */
> > - tpm_u16(0), /* Offset */
> > + if (session_handle)
> > + authorization = *session_handle;
> > + else
> > + nonce_size = 0; //cannot use nonce when using password authorization
> > +
> > + u8 command_v2[COMMAND_BUFFER_SIZE] = {
> > + /* header 10 bytes */
> > + tpm_u16(TPM2_ST_SESSIONS), /* TAG */
> > + tpm_u32(offset + nonce_size + 7), /* Length */
> > + tpm_u32(TPM2_CC_NV_READ), /* Command code */
> > +
> > + /* handles 8 bytes */
> > + tpm_u32(index), /* Primary platform seed */
> > + tpm_u32(index), /*nv index*/
> > +
> > + /* AUTH_SESSION */
> > + tpm_u32(9 + nonce_size), /* Authorization size - 4 bytes*/
> > + /*auth handle - 9 bytes */
> > + tpm_u32(authorization),
> > + tpm_u16(nonce_size), /* Size of <nonce> */
> > + /* <nonce> (if any) */
> > + //0, /* Attributes: Cont/Excl/Rst */
> > + //tpm_u16(0), /* Size of <hmac/password> */
> > + /* <hmac/password> (if any) */
> > + /*end auth handle */
> > + //tpm_u16(count), /* Number of bytes */
> > + //tpm_u16(0), /* Offset */
>
> I am not sure keeping the values commented out helps in readability.
> > };
> > +
> > size_t response_len = COMMAND_BUFFER_SIZE;
> > u8 response[COMMAND_BUFFER_SIZE];
> > int ret;
> > u16 tag;
> > u32 size, code;
>
> Those should be defined on top. IIRC we don't allow declarations here.
>
> >
> > + ret = pack_byte_string(command_v2, sizeof(command_v2), "sbwww",
> > + offset, priv->nonce, nonce_size,
> > + offset + nonce_size, 0,
> > + offset + nonce_size + 1, 0,
> > + offset + nonce_size + 3, count,
> > + offset + nonce_size + 5, 0);
> > +
> > + if (ret)
> > + return TPM_LIB_ERROR;
> > +
> > ret = tpm_sendrecv_command(dev, command_v2, response, &response_len);
> > if (ret)
> > return log_msg_ret("read", ret);
> > +
> > if (unpack_byte_string(response, response_len, "wdds",
> > - 0, &tag, 2, &size, 6, &code,
> > - 16, data, count))
> > + 0, &tag, 2, &size, 6, &code,
> > + 16, data, count))
> > return TPM_LIB_ERROR;
> >
> > return 0;
> > }
> >
> > u32 tpm2_nv_write_value(struct udevice *dev, u32 index, const void *data,
> > - u32 count)
> > + u32 count, u32 *session_handle)
> > {
> > struct tpm_chip_priv *priv = dev_get_uclass_priv(dev);
> > - uint offset = 10 + 8 + 4 + 9 + 2;
> > - uint len = offset + count + 2;
> > - /* Use empty password auth if platform hierarchy is disabled */
> > - u32 auth = priv->plat_hier_disabled ? HR_NV_INDEX + index :
> > - TPM2_RH_PLATFORM;
> > +
> > + if (!priv)
> > + return TPM_LIB_ERROR;
> > +
> > + u32 nonce_size = priv->nonce_sz;
> > +
> > + priv->nonce[nonce_size - 1]++;
> > +
> > + u32 authorization = TPM2_RS_PW;
> > +
> > + if (session_handle)
> > + authorization = *session_handle;
> > + else
> > + nonce_size = 0; //cannot use nonce when using password authorization
> > +
> > + uint offset = TPM2_HDR_LEN + 8 + 4 + 6;
> > + uint len = offset + nonce_size + count + 7;
>
> This isn't a problem of your patch directly, but since you are
> changing that, can we get rid of the magic values (e.g 8,4, 7 etc) and
> either add a comment or a define that explains it?
>
> > +
> > u8 command_v2[COMMAND_BUFFER_SIZE] = {
> > /* header 10 bytes */
> > tpm_u16(TPM2_ST_SESSIONS), /* TAG */
> > @@ -941,27 +1192,35 @@ u32 tpm2_nv_write_value(struct udevice *dev, u32 index, const void *data,
> > tpm_u32(TPM2_CC_NV_WRITE), /* Command code */
> >
> > /* handles 8 bytes */
> > - tpm_u32(auth), /* Primary platform seed */
> > - tpm_u32(HR_NV_INDEX + index), /* Password authorisation */
> > + tpm_u32(index), /* Primary platform seed */
> > + tpm_u32(index), /*nv index*/
> >
> > /* AUTH_SESSION */
> > - tpm_u32(9), /* Authorization size */
> > - tpm_u32(TPM2_RS_PW), /* Session handle */
> > - tpm_u16(0), /* Size of <nonce> */
> > + tpm_u32(9 + nonce_size), /* Authorization size - 4 bytes */
> > + /*auth handle - 9 bytes */
> > + tpm_u32(authorization),
> > + tpm_u16(nonce_size), /* Size of <nonce> */
> > /* <nonce> (if any) */
> > - 0, /* Attributes: Cont/Excl/Rst */
> > - tpm_u16(0), /* Size of <hmac/password> */
> > + //0, /* Attributes: Cont/Excl/Rst */
> > + //tpm_u16(0), /* Size of <hmac/password> */
> > /* <hmac/password> (if any) */
> > -
> > - tpm_u16(count),
> > + /*end auth handle */
> > + //tpm_u16(count),/*size of buffer - 2 bytes*/
> > + /*data (buffer)*/
> > + /*offset -> the octet offset into the NV Area*/
> > };
> > size_t response_len = COMMAND_BUFFER_SIZE;
> > u8 response[COMMAND_BUFFER_SIZE];
> > int ret;
> >
> > - ret = pack_byte_string(command_v2, sizeof(command_v2), "sw",
> > - offset, data, count,
> > - offset + count, 0);
> > + ret = pack_byte_string(command_v2, sizeof(command_v2), "sbwwsw",
> > + offset, priv->nonce, nonce_size,
> > + offset + nonce_size, 0, //attrs
> > + offset + nonce_size + 1, 0, //hmac sz
> > + offset + nonce_size + 3, count,
> > + offset + nonce_size + 5, data, count,
> > + offset + nonce_size + count, 0);
> > +
> > if (ret)
> > return TPM_LIB_ERROR;
> >
> > diff --git a/lib/tpm_api.c b/lib/tpm_api.c
> > index 39a5121e30..5875e7b085 100644
> > --- a/lib/tpm_api.c
> > +++ b/lib/tpm_api.c
> > @@ -128,7 +128,7 @@ u32 tpm_nv_read_value(struct udevice *dev, u32 index, void *data, u32 count)
> > if (tpm_is_v1(dev))
> > return tpm1_nv_read_value(dev, index, data, count);
> > else if (tpm_is_v2(dev))
> > - return tpm2_nv_read_value(dev, index, data, count);
> > + return tpm2_nv_read_value(dev, index, data, count, NULL);
> > else
> > return -ENOSYS;
> > }
> > @@ -139,7 +139,7 @@ u32 tpm_nv_write_value(struct udevice *dev, u32 index, const void *data,
> > if (tpm_is_v1(dev))
> > return tpm1_nv_write_value(dev, index, data, count);
> > else if (tpm_is_v2(dev))
> > - return tpm2_nv_write_value(dev, index, data, count);
> > + return tpm2_nv_write_value(dev, index, data, count, NULL);
> > else
> > return -ENOSYS;
> > }
> > --
> > 2.34.1
> > ==========================END PATCH=======================
>
>
> Thanks
> /Ilias
More information about the U-Boot
mailing list