From patchwork Thu Mar 8 15:40:21 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Miquel Raynal X-Patchwork-Id: 883198 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 3zxw0T07XGz9shc for ; Fri, 9 Mar 2018 02:48:40 +1100 (AEDT) Received: by lists.denx.de (Postfix, from userid 105) id B6959C21FAB; Thu, 8 Mar 2018 15:45:43 +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 879D6C21EE4; Thu, 8 Mar 2018 15:41:20 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id 51DE4C21F5E; Thu, 8 Mar 2018 15:40:56 +0000 (UTC) Received: from mail.bootlin.com (mail.bootlin.com [62.4.15.54]) by lists.denx.de (Postfix) with ESMTP id A5798C21FD8 for ; Thu, 8 Mar 2018 15:40:49 +0000 (UTC) Received: by mail.bootlin.com (Postfix, from userid 110) id 160E820792; Thu, 8 Mar 2018 16:40:48 +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 412FF20890; Thu, 8 Mar 2018 16:40:29 +0100 (CET) From: Miquel Raynal To: u-boot@lists.denx.de Date: Thu, 8 Mar 2018 16:40:21 +0100 Message-Id: <20180308154021.25255-19-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 18/18] tpm: add PCR authentication commands support 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" Add support for the TPM2_PCR_SetAuthPolicy and TPM2_PCR_SetAuthValue commands. Change the command file and the help accordingly. Note: These commands could not be tested because the TPMs available do not support them, however they could be useful for someone else. The user is warned by the command help. Signed-off-by: Miquel Raynal --- cmd/tpm.c | 49 +++++++++++++++++++++++++++ include/tpm.h | 29 ++++++++++++++++ lib/tpm.c | 106 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 184 insertions(+) diff --git a/cmd/tpm.c b/cmd/tpm.c index 3c486c313b..c97babea84 100644 --- a/cmd/tpm.c +++ b/cmd/tpm.c @@ -349,6 +349,43 @@ static int do_tpm_pcr_event(cmd_tbl_t *cmdtp, int flag, return report_return_code(rc); } +static int do_tpm_pcr_setauthpolicy(cmd_tbl_t *cmdtp, int flag, + int argc, char * const argv[]) +{ + u32 index = simple_strtoul(argv[1], NULL, 0); + char *key = argv[2]; + const char *pw = (argc < 4) ? NULL : argv[3]; + const ssize_t pw_sz = pw ? strlen(pw) : 0; + + if (strlen(key) != TPM2_DIGEST_LENGTH) + return -EINVAL; + + if (argc < 3 || argc > 4) + return CMD_RET_USAGE; + + return report_return_code(tpm2_pcr_setauthpolicy(pw, pw_sz, index, + key)); +} + +static int do_tpm_pcr_setauthvalue(cmd_tbl_t *cmdtp, int flag, + int argc, char * const argv[]) +{ + u32 index = simple_strtoul(argv[1], NULL, 0); + char *key = argv[2]; + const ssize_t key_sz = strlen(key); + const char *pw = (argc < 4) ? NULL : argv[3]; + const ssize_t pw_sz = pw ? strlen(pw) : 0; + + if (strlen(key) != TPM2_DIGEST_LENGTH) + return -EINVAL; + + if (argc < 3 || argc > 4) + return CMD_RET_USAGE; + + return report_return_code(tpm2_pcr_setauthvalue(pw, pw_sz, index, + key, key_sz)); +} + static int do_tpm_pcr_extend(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { @@ -1003,6 +1040,10 @@ static cmd_tbl_t tpm_commands[] = { do_tpm_nv_write_value, "", ""), U_BOOT_CMD_MKENT(pcr_event, 0, 1, do_tpm_pcr_event, "", ""), + U_BOOT_CMD_MKENT(pcr_setauthpolicy, 0, 1, + do_tpm_pcr_setauthpolicy, "", ""), + U_BOOT_CMD_MKENT(pcr_setauthvalue, 0, 1, + do_tpm_pcr_setauthvalue, "", ""), U_BOOT_CMD_MKENT(pcr_extend, 0, 1, do_tpm_pcr_extend, "", ""), U_BOOT_CMD_MKENT(pcr_read, 0, 1, @@ -1150,6 +1191,14 @@ U_BOOT_CMD(tpm, CONFIG_SYS_MAXARGS, 1, do_tpm, " - Read bytes of the public endorsement key to memory\n" " address \n" "Integrity Collection and Reporting Commands:\n" +" pcr_setauthpolicy \n" +" - Change the to access PCR. is for the platform\n" +" hierarchy and may be empty.\n" +" /!\\WARNING: untested function, use at your own risks !\n" +" pcr_setauthvalue \n" +" - Change the to access PCR. is for the platform\n" +" hierarchy and may be empty.\n" +" /!\\WARNING: untested function, use at your own risks !\n" " pcr_event \n" " - Add a new measurement to a PCR. Update PCR with\n" " . It must be a 20 byte digest for TPMv1 or a SHA256\n" diff --git a/include/tpm.h b/include/tpm.h index cc63f06634..93ec521e74 100644 --- a/include/tpm.h +++ b/include/tpm.h @@ -61,11 +61,13 @@ enum tpm2_command_codes { TPM2_CC_CLEAR = 0x0126, TPM2_CC_CLEARCONTROL = 0x0127, TPM2_CC_HIERCHANGEAUTH = 0x0129, + TPM2_CC_PCR_SETAUTHPOL = 0x012C, TPM2_CC_DAM_RESET = 0x0139, TPM2_CC_DAM_PARAMETERS = 0x013A, TPM2_CC_GET_CAPABILITY = 0x017A, TPM2_CC_PCR_READ = 0x017E, TPM2_CC_PCR_EXTEND = 0x0182, + TPM2_CC_PCR_SETAUTHVAL = 0x0183, }; enum tpm2_return_codes { @@ -559,6 +561,33 @@ uint32_t tpm_nv_write_value(uint32_t index, const void *data, uint32_t length); */ int tpm_pcr_event(u32 index, const void *in_digest, void *out_digest); +/** + * Issue a TPM_PCR_SetAuthPolicy command. + * + * @param pw Platform password + * @param pw_sz Length of the password + * @param index Index of the PCR + * @param digest New key to access the PCR + * + * @return return code of the operation + */ +int tpm2_pcr_setauthpolicy(const char *pw, const ssize_t pw_sz, u32 index, + const char *key); + +/** + * Issue a TPM_PCR_SetAuthValue command. + * + * @param pw Platform password + * @param pw_sz Length of the password + * @param index Index of the PCR + * @param digest New key to access the PCR + * @param key_sz Length of the new key + * + * @return return code of the operation + */ +int tpm2_pcr_setauthvalue(const char *pw, const ssize_t pw_sz, u32 index, + const char *key, const ssize_t key_sz); + /** * Issue a TPM_PCR_Extend command. * diff --git a/lib/tpm.c b/lib/tpm.c index f09b9ce9eb..542449a4ea 100644 --- a/lib/tpm.c +++ b/lib/tpm.c @@ -527,6 +527,112 @@ int tpm_pcr_event(u32 index, const void *in_digest, void *out_digest) return 0; } +int tpm2_pcr_setauthpolicy(const char *pw, const ssize_t pw_sz, u32 index, + const char *key) +{ + u8 command_v2[COMMAND_BUFFER_SIZE] = { + STRINGIFY16(TPM2_ST_SESSIONS), /* TAG */ + STRINGIFY32(35 + pw_sz + TPM2_DIGEST_LENGTH), /* Command size */ + STRINGIFY32(TPM2_CC_PCR_SETAUTHPOL), /* Command code */ + + /* HANDLE */ + STRINGIFY32(TPM2_RH_PLATFORM), /* TPM resource handle */ + + /* AUTH_SESSION */ + STRINGIFY32(9 + pw_sz), /* Authorization size */ + STRINGIFY32(TPM2_RS_PW), /* session handle */ + STRINGIFY16(0), /* Size of */ + /* (if any) */ + 0, /* Attributes: Cont/Excl/Rst */ + STRINGIFY16(pw_sz) /* Size of */ + /* STRING(pw) (if any) */ + + /* TPM2B_AUTH (TPM2B_DIGEST) */ + /* STRINGIFY16(TPM2_DIGEST_LENGTH) Digest size length */ + /* STRING(key) Digest buffer (PCR key) */ + + /* TPMI_ALG_HASH */ + /* STRINGIFY16(TPM2_ALG_SHA256) Algorithm of the hash */ + + /* TPMI_DH_PCR */ + /* STRINGIFY32(index), PCR Index */ + }; + unsigned int offset = 27; + int ret; + + if (!is_tpmv2) + return TPM_LIB_ERROR; + + /* + * Fill the command structure starting from the first buffer: + * - the password (if any) + * - the PCR key length + * - the PCR key + * - the hash algorithm + * - the PCR index + */ + ret = pack_byte_string(command_v2, sizeof(command_v2), "swswd", + offset, pw, pw_sz, + offset + pw_sz, TPM2_DIGEST_LENGTH, + offset + pw_sz + 2, key, TPM2_DIGEST_LENGTH, + offset + pw_sz + 2 + TPM2_DIGEST_LENGTH, + TPM2_ALG_SHA256, + offset + pw_sz + 4 + TPM2_DIGEST_LENGTH, index); + offset += pw_sz + 2 + TPM2_DIGEST_LENGTH + 2 + 4; + if (ret) + return TPM_LIB_ERROR; + + return tpm_sendrecv_command(command_v2, NULL, NULL); +} + +int tpm2_pcr_setauthvalue(const char *pw, const ssize_t pw_sz, u32 index, + const char *key, const ssize_t key_sz) +{ + u8 command_v2[COMMAND_BUFFER_SIZE] = { + STRINGIFY16(TPM2_ST_SESSIONS), /* TAG */ + STRINGIFY32(33 + pw_sz + TPM2_DIGEST_LENGTH), /* Command size */ + STRINGIFY32(TPM2_CC_PCR_SETAUTHVAL), /* Command code */ + + /* HANDLE */ + STRINGIFY32(index), /* Handle (PCR Index) */ + + /* AUTH_SESSION */ + STRINGIFY32(9 + pw_sz), /* Authorization size */ + STRINGIFY32(TPM2_RS_PW), /* session handle */ + STRINGIFY16(0), /* Size of */ + /* (if any) */ + 0, /* Attributes: Cont/Excl/Rst */ + STRINGIFY16(pw_sz), /* Size of */ + /* STRING(pw) (if any) */ + + /* TPM2B_DIGEST */ + /* STRINGIFY16(key_sz) Key length */ + /* STRING(key) Key */ + }; + unsigned int offset = 27; + int ret; + + if (!is_tpmv2) + return TPM_LIB_ERROR; + + /* + * Fill the command structure starting from the first buffer: + * - the password (if any) + * - the number of digests, 1 in our case + * - the algorithm, sha256 in our case + * - the digest (64 bytes) + */ + ret = pack_byte_string(command_v2, sizeof(command_v2), "sws", + offset, pw, pw_sz, + offset + pw_sz, key_sz, + offset + pw_sz + 2, key, key_sz); + offset += pw_sz + 2 + key_sz; + if (ret) + return TPM_LIB_ERROR; + + return tpm_sendrecv_command(command_v2, NULL, NULL); +} + int tpm2_pcr_extend(u32 index, const uint8_t *digest) { u8 command_v2[COMMAND_BUFFER_SIZE] = {