Attention is currently required from: Michał Żygowski.

Filip Lewiński would like Michał Żygowski to review this change.

View Change

security/tpm: Add TPM2 NV_ReadPublic command support

Change-Id: I3c032b4f88d445372beebbe354f458a061a63bb9
Signed-off-by: Michał Żygowski <michal.zygowski@3mdeb.com>
---
M src/security/tpm/tss.h
M src/security/tpm/tss/tcg-2.0/tss.c
M src/security/tpm/tss/tcg-2.0/tss_marshaling.c
M src/security/tpm/tss/tcg-2.0/tss_structures.h
4 files changed, 173 insertions(+), 1 deletion(-)

git pull ssh://review.coreboot.org:29418/coreboot refs/changes/37/82037/1
diff --git a/src/security/tpm/tss.h b/src/security/tpm/tss.h
index c9aec08..8833402 100644
--- a/src/security/tpm/tss.h
+++ b/src/security/tpm/tss.h
@@ -27,6 +27,39 @@
*
* Other operations are defined in tss1.h and tss2.h.
*/
+uint32_t tlcl_define_space(uint32_t space_index, size_t space_size,
+ const TPMA_NV nv_attributes,
+ const uint8_t *nv_policy, size_t nv_policy_size);
+
+/**
+ * Read the public data of NV index. [index] is the index for the space,
+ * [nvrp_resp] is hte NV index output data. The TPM error code is returned.
+ */
+uint32_t tlcl_nv_read_public(uint32_t space_index,
+ struct nv_read_public_response *nvrp_resp);
+/*
+ * Issue TPM2_GetCapability command
+ */
+uint32_t tlcl_get_capability(TPM_CAP capability, uint32_t property,
+ uint32_t property_count,
+ TPMS_CAPABILITY_DATA *capability_data);
+
+/* Issue TPM2_NV_SetBits command */
+uint32_t tlcl_set_bits(uint32_t index, uint64_t bits);
+
+/*
+ * Makes tpm_process_command available for on top implementations of
+ * custom tpm standards like cr50
+ */
+void *tpm_process_command(TPM_CC command, void *command_body);
+
+/* Return digest size of hash algorithm */
+uint16_t tlcl_get_hash_size_from_algo(TPMI_ALG_HASH hash_algo);
+
+#endif
+
+/*****************************************************************************/
+/* Generic Functions implemented in tlcl.c */

/**
* Call this first. Returns 0 if success, nonzero if error.
diff --git a/src/security/tpm/tss/tcg-2.0/tss.c b/src/security/tpm/tss/tcg-2.0/tss.c
index 282845e..576ad53 100644
--- a/src/security/tpm/tss/tcg-2.0/tss.c
+++ b/src/security/tpm/tss/tcg-2.0/tss.c
@@ -391,7 +391,36 @@
}
}

-uint16_t tlcl2_get_hash_size_from_algo(TPMI_ALG_HASH hash_algo)
+uint32_t tlcl_nv_read_public(uint32_t space_index,
+ struct nv_read_public_response *nvrp_resp)
+{
+ struct tpm2_nv_read_public_cmd nvrp_cmd;
+ struct tpm2_response *response;
+
+ /* Prepare the define space command structure. */
+ memset(&nvrp_cmd, 0, sizeof(nvrp_cmd));
+
+ nvrp_cmd.nvIndex = HR_NV_INDEX + space_index;
+
+ response = tpm_process_command(TPM2_NV_ReadPublic, &nvrp_cmd);
+ printk(BIOS_INFO, "%s: response is %x\n", __func__,
+ response ? response->hdr.tpm_code : -1);
+
+ if (!response)
+ return TPM_E_NO_DEVICE;
+
+ /* Map TPM2 return codes into common vboot representation. */
+ switch (response->hdr.tpm_code) {
+ case TPM2_RC_SUCCESS:
+ memcpy(nvrp_resp, &response->nvrp, sizeof(*nvrp_resp));
+ return TPM_SUCCESS;
+ default:
+ return TPM_E_INTERNAL_INCONSISTENCY;
+ }
+}
+
+uint16_t tlcl_get_hash_size_from_algo(TPMI_ALG_HASH hash_algo)
+
{
uint16_t value;

diff --git a/src/security/tpm/tss/tcg-2.0/tss_marshaling.c b/src/security/tpm/tss/tcg-2.0/tss_marshaling.c
index 3039a8b..5bf293e 100644
--- a/src/security/tpm/tss/tcg-2.0/tss_marshaling.c
+++ b/src/security/tpm/tss/tcg-2.0/tss_marshaling.c
@@ -197,6 +197,13 @@
return rc;
}

+static int marshal_nv_read_public(struct obuf *ob,
+ const struct tpm2_nv_read_public_cmd *nvrp_in)
+{
+ return obuf_write_be32(ob, nvrp_in->nvIndex);
+}
+
+
static int marshal_nv_setbits(struct obuf *ob,
const struct tpm2_nv_setbits_cmd *command_body)
{
@@ -401,6 +408,10 @@
rc |= marshal_nv_define_space(ob, tpm_command_body);
break;

+ case TPM2_NV_ReadPublic:
+ rc |= marshal_nv_read_public(ob, tpm_command_body);
+ break;
+
case TPM2_NV_SetBits:
rc |= marshal_nv_setbits(ob, tpm_command_body);
break;
@@ -563,6 +574,80 @@
return 0;
}

+static int unmarshal_TPM2B_NV_PUBLIC(struct ibuf *ib, TPM2B_NV_PUBLIC *nv_public)
+{
+ int rc = 0;
+
+ rc |= ibuf_read_be16(ib, &nv_public->t.size);
+ rc |= ibuf_read_be32(ib, &nv_public->t.nvPublic.nvIndex);
+ rc |= ibuf_read_be16(ib, &nv_public->t.nvPublic.nameAlg);
+ rc |= ibuf_read_be32(ib, (uint32_t *)&nv_public->t.nvPublic.attributes);
+ rc |= ibuf_read_be16(ib, &nv_public->t.nvPublic.authPolicy.t.size);
+
+ nv_public->t.nvPublic.authPolicy.t.buffer =
+ ibuf_oob_drain(ib, nv_public->t.nvPublic.authPolicy.t.size);
+
+ rc |= ibuf_read_be16(ib, &nv_public->t.nvPublic.dataSize);
+
+ return rc;
+}
+
+static int unmarshal_TPM2B_NAME(struct ibuf *ib, TPM2B_NAME *name)
+{
+ int rc = 0;
+ size_t digest_size;
+
+ rc |= ibuf_read_be16(ib, &name->size);
+
+ if (name->size == 0)
+ return rc;
+
+ /* If size is 4 it is a handle, otherwise it should be a digest */
+ if (name->size == 4) {
+ rc |= ibuf_read_be32(ib, &name->name.handle);
+ return rc;
+ }
+
+ rc |= ibuf_read_be16(ib, &name->name.digest.hashAlg);
+
+ switch(name->name.digest.hashAlg) {
+ case TPM_ALG_SHA1:
+ digest_size = SHA1_DIGEST_SIZE;
+ break;
+ case TPM_ALG_SHA256:
+ digest_size = SHA256_DIGEST_SIZE;
+ break;
+ case TPM_ALG_SHA384:
+ digest_size = SHA384_DIGEST_SIZE;
+ break;
+ case TPM_ALG_SHA512:
+ digest_size = SHA512_DIGEST_SIZE;
+ break;
+ case TPM_ALG_SM3_256:
+ digest_size = SM3_256_DIGEST_SIZE;
+ break;
+ default:
+ printk(BIOS_WARNING, "%s: Unknown hash algorithm (%02x)\n",
+ __func__, name->name.digest.hashAlg);
+ return 1;
+ }
+
+ memcpy(&name->name.digest.digest, ibuf_oob_drain(ib, digest_size), digest_size);
+
+ return rc;
+}
+
+
+static int unmarshal_nv_read_public(struct ibuf *ib, struct nv_read_public_response *nvrp)
+{
+ int rc = 0;
+
+ rc |= unmarshal_TPM2B_NV_PUBLIC(ib, &nvrp->nvPublic);
+ rc |= unmarshal_TPM2B_NAME(ib, &nvrp->nvName);
+
+ return rc;
+}
+
static int unmarshal_vendor_command(struct ibuf *ib,
struct vendor_command_response *vcr)
{
@@ -635,6 +720,10 @@
rc |= unmarshal_nv_read(ib, &tpm2_static_resp.nvr);
break;

+ case TPM2_NV_ReadPublic:
+ rc |= unmarshal_nv_read_public(ib, &tpm2_static_resp.nvrp);
+ break;
+
case TPM2_Hierarchy_Control:
case TPM2_Clear:
case TPM2_ClearControl:
diff --git a/src/security/tpm/tss/tcg-2.0/tss_structures.h b/src/security/tpm/tss/tcg-2.0/tss_structures.h
index f2682b1..5893ffd 100644
--- a/src/security/tpm/tss/tcg-2.0/tss_structures.h
+++ b/src/security/tpm/tss/tcg-2.0/tss_structures.h
@@ -88,6 +88,7 @@
#define TPM2_Startup ((TPM_CC)0x00000144)
#define TPM2_Shutdown ((TPM_CC)0x00000145)
#define TPM2_NV_Read ((TPM_CC)0x0000014E)
+#define TPM2_NV_ReadPublic ((TPM_CC)0x00000169)
#define TPM2_GetCapability ((TPM_CC)0x0000017A)
#define TPM2_PCR_Extend ((TPM_CC)0x00000182)
/* TPM2 specifies vendor commands need to have this bit set. Vendor command
@@ -345,6 +346,21 @@
TPM2B_MAX_NV_BUFFER buffer;
};

+typedef union {
+ TPMT_HA digest;
+ TPM_HANDLE handle;
+} TPMU_NAME;
+
+typedef struct {
+ uint16_t size;
+ TPMU_NAME name;
+} TPM2B_NAME;
+
+struct nv_read_public_response {
+ TPM2B_NV_PUBLIC nvPublic;
+ TPM2B_NAME nvName;
+};
+
struct vendor_command_response {
uint16_t vc_subcommand;
union {
@@ -391,6 +407,7 @@
union {
struct get_cap_response gc;
struct nv_read_response nvr;
+ struct nv_read_public_response nvrp;
struct tpm2_session_header def_space;
struct vendor_command_response vcr;
};
@@ -401,6 +418,10 @@
TPMS_NV_PUBLIC publicInfo;
};

+struct tpm2_nv_read_public_cmd {
+ TPMI_RH_NV_INDEX nvIndex;
+};
+
struct tpm2_nv_write_cmd {
TPMI_RH_NV_INDEX nvIndex;
TPM2B_MAX_NV_BUFFER data;

To view, visit change 82037. To unsubscribe, or for help writing mail filters, visit settings.

Gerrit-Project: coreboot
Gerrit-Branch: main
Gerrit-Change-Id: I3c032b4f88d445372beebbe354f458a061a63bb9
Gerrit-Change-Number: 82037
Gerrit-PatchSet: 1
Gerrit-Owner: Filip Lewiński <filip.lewinski@3mdeb.com>
Gerrit-Reviewer: Michał Żygowski <michal.zygowski@3mdeb.com>
Gerrit-Attention: Michał Żygowski <michal.zygowski@3mdeb.com>
Gerrit-MessageType: newchange