[U-Boot] [PATCH 05/18] tpm: prepare support for TPMv2 commands
Miquel Raynal
miquel.raynal at bootlin.com
Thu Mar 8 15:40:08 UTC 2018
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.raynal at 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
More information about the U-Boot
mailing list