From patchwork Thu Mar 8 15:40:08 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Miquel Raynal X-Patchwork-Id: 883192 X-Patchwork-Delegate: sjg@chromium.org Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.denx.de (client-ip=81.169.180.215; helo=lists.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=bootlin.com Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 3zxvx251FLz9shc for ; Fri, 9 Mar 2018 02:45:42 +1100 (AEDT) Received: by lists.denx.de (Postfix, from userid 105) id 233D1C21C2C; Thu, 8 Mar 2018 15:43:16 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on lists.denx.de X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=RCVD_IN_DNSWL_BLOCKED autolearn=unavailable autolearn_force=no version=3.4.0 Received: from lists.denx.de (localhost [IPv6:::1]) by lists.denx.de (Postfix) with ESMTP id D3C5DC21FB2; Thu, 8 Mar 2018 15:40:48 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id C3128C21C2C; Thu, 8 Mar 2018 15:40:41 +0000 (UTC) Received: from mail.bootlin.com (mail.bootlin.com [62.4.15.54]) by lists.denx.de (Postfix) with ESMTP id D8609C21EC8 for ; Thu, 8 Mar 2018 15:40:39 +0000 (UTC) Received: by mail.bootlin.com (Postfix, from userid 110) id 3D11020721; Thu, 8 Mar 2018 16:40:38 +0100 (CET) Received: from localhost.localdomain (LStLambert-657-1-97-87.w90-63.abo.wanadoo.fr [90.63.216.87]) by mail.bootlin.com (Postfix) with ESMTPSA id A9E1B207A5; Thu, 8 Mar 2018 16:40:27 +0100 (CET) From: Miquel Raynal To: u-boot@lists.denx.de Date: Thu, 8 Mar 2018 16:40:08 +0100 Message-Id: <20180308154021.25255-6-miquel.raynal@bootlin.com> X-Mailer: git-send-email 2.14.1 In-Reply-To: <20180308154021.25255-1-miquel.raynal@bootlin.com> References: <20180308154021.25255-1-miquel.raynal@bootlin.com> Subject: [U-Boot] [PATCH 05/18] tpm: prepare support for TPMv2 commands X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.18 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" 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 --- 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 with arguments .\n" "Admin Startup and State Commands:\n" " info - Show information about the TPM\n" -" init\n" +" init []\n" " - Put TPM into a state where it waits for 'startup' command.\n" +" 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. 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)