Hi dan This might be because I used the checkpatch.pl script. Here's one without it.
Niek =========================START PATCH ======================= From de056f510156a2fa1b4b439e1fa1f44516aa8add Mon Sep 17 00:00:00 2001 From: Niek Nooijens <niek.nooij...@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.nooij...@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,221 @@ 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); + nv_attributes |= (TPMA_NV_POLICYREAD | TPMA_NV_POLICYWRITE); //obligated, might as well force it + 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); + + if (policy_addr) + 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); + + 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[]) //TODO: session handle from auth session! +{ + 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 +590,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 +675,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..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, + 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 + * 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 +786,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) + 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 +1090,99 @@ 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 */ }; + 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) { 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 != NULL) + 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; + u8 command_v2[COMMAND_BUFFER_SIZE] = { /* header 10 bytes */ tpm_u16(TPM2_ST_SESSIONS), /* TAG */ @@ -941,27 +1190,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============================ ________________________________ 差出人: Dan Carpenter <dan.carpen...@linaro.org> 送信日時: 2024年2月21日 02:56 宛先: Niek Nooijens / OC-IAB PBD-C DEVEL 1-1 <niek.nooij...@omron.com> CC: Ilias Apalodimas <ilias.apalodi...@linaro.org>; u-boot@lists.denx.de <u-boot@lists.denx.de> 件名: Re: [PATCH] implement policy_pcr commands to lock NV-indexes behind a PCR [dan.carpen...@linaro.org からのメールを受け取る頻度は高くありません。これが問題である可能性の理由については、https://aka.ms/LearnAboutSenderIdentification をご覧ください。] I'm kind of new to u-boot and I'm not really able to review this code as well as I should. But also I can't apply the patch. It seems white space damaged? The kernel has a good document on how to do this. I'm pretty sure u-boot does as well but I'm new. https://jpn01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fwww.kernel.org%2Fdoc%2FDocumentation%2Fprocess%2Femail-clients.rst&data=05%7C02%7Cniek.nooijens%40omron.com%7Cfff2a571b0f64e4cee7308dc323d3de9%7C0ecff5a94bef4a7b96eca96579b4ac37%7C0%7C0%7C638440485810051997%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C0%7C%7C%7C&sdata=dU5lPn1UMeoLauNg2lVkRsopKimQ5qwJda11ZRm%2FJhQ%3D&reserved=0<https://www.kernel.org/doc/Documentation/process/email-clients.rst> Please run your patch through the scripts/checkpatch.pl script. Stuff like this triggers a warning: > +static int do_tpm_nv_write_value(struct cmd_tbl *cmdtp, int flag, > + int argc, char *const argv[]) //TODO: session handle > from auth session! > +{ > + 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; WARNING: suspect code indent for conditional statements (0, 0) #250: FILE: cmd/tpm-v2.c:437: + if (ret) + return ret; WARNING: suspect code indent for conditional statements (0, 0) #253: FILE: cmd/tpm-v2.c:440: + if (argc < 4) + return CMD_RET_USAGE; Also the subject should have a subsystem prefix and the information from the email should be moved into the commit message. Currently the commit message is empty. > 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, Changing TPM2_RS_PW is an unrelated whitespace change. Do that as a separate patch. But I don't get it at all because the TPM2_RS_PW enum has always been indented correctly as far as I can see. So it's a puzzle. I mean there are a lot of TODOs and I understand that you just wanted a high level review but I kept getting distracted and lost and I couldn't apply the patch so it was just really hard to figure out what was going on. :( regards, dan carpenter