
Hi Niek,
On Thu, 7 Mar 2024 at 07:59, niek.nooijens@omron.com niek.nooijens@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@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@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
* 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.
- @elog: Platform event log. The log pointer and log_size
- @ignore_existing_log Boolean to indicate whether or not to ignore an
* existing platform log in memory
- @ignore_existing_log: Boolean to indicate whether or not to ignore an
- 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
* 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.
- @elog: Platform event log. The log pointer and log_size
- @ignore_existing_log Boolean to indicate whether or not to ignore an
* existing platform log in memory
- @ignore_existing_log: Boolean to indicate whether or not to ignore an
- 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@linaro.org 送信日時: 2024年3月5日 19:47 宛先: Niek Nooijens / OC-IAB PBD-C DEVEL 1-1 niek.nooijens@omron.com CC: u-boot@lists.denx.de u-boot@lists.denx.de 件名: Re: [PATCH] implement policy_pcr commands to lock NV-indexes behind a PCR
[ilias.apalodimas@linaro.org からのメールを受け取る頻度は高くありません。これが問題である可能性の理由については、https://aka.ms/LearnAboutSenderIdentification をご覧ください。]
On Tue, 20 Feb 2024 at 07:59, niek.nooijens@omron.com niek.nooijens@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@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@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