Later choice between v1 and v2 compliant functions will be handled by a
global value in lib/tpm.c that will be accessible through set/get
accessors from lib/cmd.c.

This global value is set during the initialization phase if the TPM2
handle is given to the init command.

Signed-off-by: Miquel Raynal <miquel.ray...@bootlin.com>
---
 cmd/tpm.c     | 37 +++++++++++++++++++++-----
 include/tpm.h | 20 ++++++++++++++
 lib/tpm.c     | 83 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
 3 files changed, 131 insertions(+), 9 deletions(-)

diff --git a/cmd/tpm.c b/cmd/tpm.c
index f456396d75..1d32028b64 100644
--- a/cmd/tpm.c
+++ b/cmd/tpm.c
@@ -89,12 +89,16 @@ static void *parse_byte_string(char *bytes, uint8_t *data, 
size_t *count_ptr)
  */
 static int report_return_code(int return_code)
 {
-       if (return_code) {
-               printf("Error: %d\n", return_code);
-               return CMD_RET_FAILURE;
-       } else {
+       if (!return_code)
                return CMD_RET_SUCCESS;
-       }
+
+       if (return_code == -EOPNOTSUPP)
+               printf("TPMv%d error: unavailable command with this spec\n",
+                      tpm_get_specification());
+       else
+               printf("TPM error: %d\n", return_code);
+
+       return CMD_RET_FAILURE;
 }
 
 /**
@@ -427,6 +431,24 @@ static int do_tpm_get_capability(cmd_tbl_t *cmdtp, int 
flag,
        return report_return_code(rc);
 }
 
+static int do_tpm_init(cmd_tbl_t *cmdtp, int flag,
+                      int argc, char * const argv[])
+{
+       if (argc > 2)
+               return CMD_RET_USAGE;
+
+       if (argc == 2) {
+               if (!strcasecmp("TPM1", argv[1]))
+                       tpm_set_specification(1);
+               else if (!strcasecmp("TPM2", argv[1]))
+                       tpm_set_specification(2);
+               else
+                       return CMD_RET_USAGE;
+       }
+
+       return report_return_code(tpm_init());
+}
+
 #define TPM_COMMAND_NO_ARG(cmd)                                \
 static int do_##cmd(cmd_tbl_t *cmdtp, int flag,                \
                int argc, char * const argv[])          \
@@ -436,7 +458,6 @@ static int do_##cmd(cmd_tbl_t *cmdtp, int flag,             
\
        return report_return_code(cmd());               \
 }
 
-TPM_COMMAND_NO_ARG(tpm_init)
 TPM_COMMAND_NO_ARG(tpm_self_test_full)
 TPM_COMMAND_NO_ARG(tpm_continue_self_test)
 TPM_COMMAND_NO_ARG(tpm_force_clear)
@@ -902,8 +923,10 @@ U_BOOT_CMD(tpm, CONFIG_SYS_MAXARGS, 1, do_tpm,
 "    - Issue TPM command <cmd> with arguments <args...>.\n"
 "Admin Startup and State Commands:\n"
 "  info - Show information about the TPM\n"
-"  init\n"
+"  init [<type>]\n"
 "    - Put TPM into a state where it waits for 'startup' command.\n"
+"      <type> is one of TPM1 (default) or TPM2. This choice impacts the way\n"
+"      other functions will behave.\n"
 "  startup mode\n"
 "    - Issue TPM_Starup command.  <mode> is one of TPM_ST_CLEAR,\n"
 "      TPM_ST_STATE, and TPM_ST_DEACTIVATED.\n"
diff --git a/include/tpm.h b/include/tpm.h
index 760d94865c..0ec3428ea4 100644
--- a/include/tpm.h
+++ b/include/tpm.h
@@ -30,6 +30,11 @@ enum tpm_startup_type {
        TPM_ST_DEACTIVATED      = 0x0003,
 };
 
+enum tpm2_startup_types {
+       TPM2_SU_CLEAR   = 0x0000,
+       TPM2_SU_STATE   = 0x0001,
+};
+
 enum tpm_physical_presence {
        TPM_PHYSICAL_PRESENCE_HW_DISABLE        = 0x0200,
        TPM_PHYSICAL_PRESENCE_CMD_DISABLE       = 0x0100,
@@ -417,6 +422,21 @@ int tpm_xfer(struct udevice *dev, const uint8_t *sendbuf, 
size_t send_size,
  */
 int tpm_init(void);
 
+/**
+ * Assign a value to the global is_nfcv2 boolean to discriminate in the lib
+ * between the available specifications.
+ *
+ * @version: 1 or 2, depending on the supported specification
+ */
+int tpm_set_specification(int version);
+
+/**
+ * Return the current value of the specification.
+ *
+ * @return: 1 or 2, depending on the supported specification
+ */
+int tpm_get_specification(void);
+
 /**
  * Issue a TPM_Startup command.
  *
diff --git a/lib/tpm.c b/lib/tpm.c
index 99556b1cf6..38b76b4961 100644
--- a/lib/tpm.c
+++ b/lib/tpm.c
@@ -15,6 +15,9 @@
 /* Internal error of TPM command library */
 #define TPM_LIB_ERROR  ((uint32_t)~0u)
 
+/* Global boolean to discriminate TPMv2.x from TPMv1.x functions */
+static bool is_tpmv2;
+
 /* Useful constants */
 enum {
        COMMAND_BUFFER_SIZE             = 256,
@@ -262,6 +265,26 @@ static uint32_t tpm_sendrecv_command(const void *command,
        return tpm_return_code(response);
 }
 
+int tpm_set_specification(int version)
+{
+       if (version == 1) {
+               debug("TPM complies to the v1.x specification\n");
+               is_tpmv2 = false;
+       } else if (version == 2) {
+               debug("TPM complies to the v2.x specification\n");
+               is_tpmv2 = true;
+       } else {
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+int tpm_get_specification(void)
+{
+       return is_tpmv2 ? 2 : 1;
+}
+
 int tpm_init(void)
 {
        int err;
@@ -338,6 +361,9 @@ uint32_t tpm_nv_define_space(uint32_t index, uint32_t perm, 
uint32_t size)
        const size_t size_offset = 77;
        uint8_t buf[COMMAND_BUFFER_SIZE];
 
+       if (is_tpmv2)
+               return -EOPNOTSUPP;
+
        if (pack_byte_string(buf, sizeof(buf), "sddd",
                                0, command, sizeof(command),
                                index_offset, index,
@@ -362,6 +388,9 @@ uint32_t tpm_nv_read_value(uint32_t index, void *data, 
uint32_t count)
        uint32_t data_size;
        uint32_t err;
 
+       if (is_tpmv2)
+               return -EOPNOTSUPP;
+
        if (pack_byte_string(buf, sizeof(buf), "sdd",
                                0, command, sizeof(command),
                                index_offset, index,
@@ -398,6 +427,9 @@ uint32_t tpm_nv_write_value(uint32_t index, const void 
*data, uint32_t length)
        size_t response_length = sizeof(response);
        uint32_t err;
 
+       if (is_tpmv2)
+               return -EOPNOTSUPP;
+
        if (pack_byte_string(buf, sizeof(buf), "sddds",
                                0, command, sizeof(command),
                                command_size_offset, total_length,
@@ -425,6 +457,9 @@ uint32_t tpm_extend(uint32_t index, const void *in_digest, 
void *out_digest)
        size_t response_length = sizeof(response);
        uint32_t err;
 
+       if (is_tpmv2)
+               return -EOPNOTSUPP;
+
        if (pack_byte_string(buf, sizeof(buf), "sds",
                                0, command, sizeof(command),
                                index_offset, index,
@@ -454,8 +489,8 @@ uint32_t tpm_pcr_read(uint32_t index, void *data, size_t 
count)
        size_t response_length = sizeof(response);
        uint32_t err;
 
-       if (count < PCR_DIGEST_LENGTH)
-               return TPM_LIB_ERROR;
+       if (is_tpmv2)
+               return -EOPNOTSUPP;
 
        if (pack_byte_string(buf, sizeof(buf), "sd",
                                0, command, sizeof(command),
@@ -479,6 +514,9 @@ uint32_t tpm_tsc_physical_presence(uint16_t presence)
        const size_t presence_offset = 10;
        uint8_t buf[COMMAND_BUFFER_SIZE];
 
+       if (is_tpmv2)
+               return -EOPNOTSUPP;
+
        if (pack_byte_string(buf, sizeof(buf), "sw",
                                0, command, sizeof(command),
                                presence_offset, presence))
@@ -500,6 +538,9 @@ uint32_t tpm_read_pubek(void *data, size_t count)
        uint32_t data_size;
        uint32_t err;
 
+       if (is_tpmv2)
+               return -EOPNOTSUPP;
+
        err = tpm_sendrecv_command(command, response, &response_length);
        if (err)
                return err;
@@ -533,6 +574,9 @@ uint32_t tpm_physical_enable(void)
                0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x6f,
        };
 
+       if (is_tpmv2)
+               return -EOPNOTSUPP;
+
        return tpm_sendrecv_command(command, NULL, NULL);
 }
 
@@ -542,6 +586,9 @@ uint32_t tpm_physical_disable(void)
                0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x70,
        };
 
+       if (is_tpmv2)
+               return -EOPNOTSUPP;
+
        return tpm_sendrecv_command(command, NULL, NULL);
 }
 
@@ -553,6 +600,9 @@ uint32_t tpm_physical_set_deactivated(uint8_t state)
        const size_t state_offset = 10;
        uint8_t buf[COMMAND_BUFFER_SIZE];
 
+       if (is_tpmv2)
+               return -EOPNOTSUPP;
+
        if (pack_byte_string(buf, sizeof(buf), "sb",
                                0, command, sizeof(command),
                                state_offset, state))
@@ -618,6 +668,9 @@ uint32_t tpm_get_permanent_flags(struct tpm_permanent_flags 
*pflags)
        uint32_t err;
        uint32_t data_size;
 
+       if (is_tpmv2)
+               return -EOPNOTSUPP;
+
        err = tpm_sendrecv_command(command, response, &response_length);
        if (err)
                return err;
@@ -648,6 +701,9 @@ uint32_t tpm_get_permissions(uint32_t index, uint32_t *perm)
        size_t response_length = sizeof(response);
        uint32_t err;
 
+       if (is_tpmv2)
+               return -EOPNOTSUPP;
+
        if (pack_byte_string(buf, sizeof(buf), "d", 0, command, sizeof(command),
                             index_offset, index))
                return TPM_LIB_ERROR;
@@ -677,6 +733,9 @@ uint32_t tpm_flush_specific(uint32_t key_handle, uint32_t 
resource_type)
        size_t response_length = sizeof(response);
        uint32_t err;
 
+       if (is_tpmv2)
+               return -EOPNOTSUPP;
+
        if (pack_byte_string(buf, sizeof(buf), "sdd",
                             0, command, sizeof(command),
                             key_handle_offset, key_handle,
@@ -835,6 +894,9 @@ uint32_t tpm_terminate_auth_session(uint32_t auth_handle)
        const size_t req_handle_offset = TPM_REQUEST_HEADER_LENGTH;
        uint8_t request[COMMAND_BUFFER_SIZE];
 
+       if (is_tpmv2)
+               return -EOPNOTSUPP;
+
        if (pack_byte_string(request, sizeof(request), "sd",
                             0, command, sizeof(command),
                             req_handle_offset, auth_handle))
@@ -848,8 +910,13 @@ uint32_t tpm_terminate_auth_session(uint32_t auth_handle)
 uint32_t tpm_end_oiap(void)
 {
        uint32_t err = TPM_SUCCESS;
+
        if (oiap_session.valid)
                err = tpm_terminate_auth_session(oiap_session.handle);
+
+       if (is_tpmv2)
+               return -EOPNOTSUPP;
+
        return err;
 }
 
@@ -866,6 +933,9 @@ uint32_t tpm_oiap(uint32_t *auth_handle)
        size_t response_length = sizeof(response);
        uint32_t err;
 
+       if (is_tpmv2)
+               return -EOPNOTSUPP;
+
        if (oiap_session.valid)
                tpm_terminate_auth_session(oiap_session.handle);
 
@@ -904,6 +974,9 @@ uint32_t tpm_load_key2_oiap(uint32_t parent_handle,
        size_t response_length = sizeof(response);
        uint32_t err;
 
+       if (is_tpmv2)
+               return -EOPNOTSUPP;
+
        if (!oiap_session.valid) {
                err = tpm_oiap(NULL);
                if (err)
@@ -967,6 +1040,9 @@ uint32_t tpm_get_pub_key_oiap(uint32_t key_handle, const 
void *usage_auth,
        size_t response_length = sizeof(response);
        uint32_t err;
 
+       if (is_tpmv2)
+               return -EOPNOTSUPP;
+
        if (!oiap_session.valid) {
                err = tpm_oiap(NULL);
                if (err)
@@ -1025,6 +1101,9 @@ uint32_t tpm_find_key_sha1(const uint8_t auth[20], const 
uint8_t
        size_t buf_len;
        unsigned int i;
 
+       if (is_tpmv2)
+               return -EOPNOTSUPP;
+
        /* fetch list of already loaded keys in the TPM */
        err = tpm_get_capability(TPM_CAP_HANDLE, TPM_RT_KEY, buf, sizeof(buf));
        if (err)
-- 
2.14.1

_______________________________________________
U-Boot mailing list
U-Boot@lists.denx.de
https://lists.denx.de/listinfo/u-boot

Reply via email to