diff options
Diffstat (limited to 'cmd')
-rw-r--r-- | cmd/Kconfig | 40 | ||||
-rw-r--r-- | cmd/Makefile | 5 | ||||
-rw-r--r-- | cmd/bootcount.c | 61 | ||||
-rw-r--r-- | cmd/mmc.c | 6 | ||||
-rw-r--r-- | cmd/pmic.c | 31 | ||||
-rw-r--r-- | cmd/tpm-common.c | 288 | ||||
-rw-r--r-- | cmd/tpm-user-utils.h | 24 | ||||
-rw-r--r-- | cmd/tpm-v1.c (renamed from cmd/tpm.c) | 488 | ||||
-rw-r--r-- | cmd/tpm-v2.c | 389 | ||||
-rw-r--r-- | cmd/tpm_test.c | 2 |
10 files changed, 926 insertions, 408 deletions
diff --git a/cmd/Kconfig b/cmd/Kconfig index 38406fcfda..1a1ca60237 100644 --- a/cmd/Kconfig +++ b/cmd/Kconfig @@ -228,7 +228,7 @@ config CMD_BOOTEFI config CMD_BOOTEFI_HELLO_COMPILE bool "Compile a standard EFI hello world binary for testing" - depends on CMD_BOOTEFI && (ARM || X86) + depends on CMD_BOOTEFI && (ARM || X86 || RISCV) default y help This compiles a standard EFI hello world application with U-Boot so @@ -816,6 +816,13 @@ config CMD_MMC help MMC memory mapped support. +config CMD_MMC_RPMB + bool "Enable support for RPMB in the mmc command" + depends on CMD_MMC + help + Enable the commands for reading, writing and programming the + key for the Replay Protection Memory Block partition in eMMC. + config CMD_NAND bool "nand" default y if NAND_SUNXI @@ -1222,6 +1229,13 @@ config CMD_BMP the image into RAM, then using this command to look at it or display it. +config CMD_BOOTCOUNT + bool "bootcount" + depends on BOOTCOUNT_LIMIT + help + Enable the bootcount command, which allows interrogation and + reset of the bootcounter. + config CMD_BSP bool "Enable board-specific commands" help @@ -1477,25 +1491,37 @@ config HASH_VERIFY help Add -v option to verify data against a hash. +config CMD_TPM_V1 + bool + +config CMD_TPM_V2 + bool + config CMD_TPM bool "Enable the 'tpm' command" - depends on TPM + depends on TPM_V1 || TPM_V2 + select CMD_TPM_V1 if TPM_V1 + select CMD_TPM_V2 if TPM_V2 help This provides a means to talk to a TPM from the command line. A wide range of commands if provided - see 'tpm help' for details. The command requires a suitable TPM on your board and the correct driver must be enabled. +if CMD_TPM + config CMD_TPM_TEST bool "Enable the 'tpm test' command" - depends on CMD_TPM + depends on TPM_V1 help - This provides a a series of tests to confirm that the TPM is working - correctly. The tests cover initialisation, non-volatile RAM, extend, - global lock and checking that timing is within expectations. The - tests pass correctly on Infineon TPMs but may need to be adjusted + This provides a a series of tests to confirm that the TPMv1.x is + working correctly. The tests cover initialisation, non-volatile RAM, + extend, global lock and checking that timing is within expectations. + The tests pass correctly on Infineon TPMs but may need to be adjusted for other devices. +endif + endmenu menu "Firmware commands" diff --git a/cmd/Makefile b/cmd/Makefile index 0d7322ee0a..e0088df33b 100644 --- a/cmd/Makefile +++ b/cmd/Makefile @@ -22,6 +22,7 @@ obj-$(CONFIG_CMD_BEDBUG) += bedbug.o obj-$(CONFIG_CMD_BINOP) += binop.o obj-$(CONFIG_CMD_BLOCK_CACHE) += blkcache.o obj-$(CONFIG_CMD_BMP) += bmp.o +obj-$(CONFIG_CMD_BOOTCOUNT) += bootcount.o obj-$(CONFIG_CMD_BOOTEFI) += bootefi.o obj-$(CONFIG_CMD_BOOTMENU) += bootmenu.o obj-$(CONFIG_CMD_BOOTSTAGE) += bootstage.o @@ -119,8 +120,10 @@ obj-$(CONFIG_CMD_TERMINAL) += terminal.o obj-$(CONFIG_CMD_TIME) += time.o obj-$(CONFIG_CMD_TRACE) += trace.o obj-$(CONFIG_HUSH_PARSER) += test.o -obj-$(CONFIG_CMD_TPM) += tpm.o +obj-$(CONFIG_CMD_TPM) += tpm-common.o +obj-$(CONFIG_CMD_TPM_V1) += tpm-v1.o obj-$(CONFIG_CMD_TPM_TEST) += tpm_test.o +obj-$(CONFIG_CMD_TPM_V2) += tpm-v2.o obj-$(CONFIG_CMD_CROS_EC) += cros_ec.o obj-$(CONFIG_CMD_TSI148) += tsi148.o obj-$(CONFIG_CMD_UBI) += ubi.o diff --git a/cmd/bootcount.c b/cmd/bootcount.c new file mode 100644 index 0000000000..c358418ebe --- /dev/null +++ b/cmd/bootcount.c @@ -0,0 +1,61 @@ +// SPDX-License-Identifier: GPL-2.0+ + +#include <common.h> +#include <command.h> +#include <bootcount.h> + +static int do_bootcount_print(cmd_tbl_t *cmdtp, int flag, int argc, + char * const argv[]) +{ + printf("%lu\n", bootcount_load()); + return CMD_RET_SUCCESS; +} + +static int do_bootcount_reset(cmd_tbl_t *cmdtp, int flag, int argc, + char * const argv[]) +{ + /* + * note that we're explicitly not resetting the environment + * variable, so you still have the old bootcounter available + */ + bootcount_store(0); + return CMD_RET_SUCCESS; +} + +static cmd_tbl_t bootcount_sub[] = { + U_BOOT_CMD_MKENT(print, 1, 1, do_bootcount_print, "", ""), + U_BOOT_CMD_MKENT(reset, 1, 1, do_bootcount_reset, "", ""), +}; + +static int do_bootcount(cmd_tbl_t *cmdtp, int flag, int argc, + char * const argv[]) +{ + cmd_tbl_t *cp; + + if (argc < 2) + return CMD_RET_USAGE; + + /* drop initial "bootcount" arg */ + argc--; + argv++; + + cp = find_cmd_tbl(argv[0], bootcount_sub, ARRAY_SIZE(bootcount_sub)); + if (cp) + return cp->cmd(cmdtp, flag, argc, argv); + + return CMD_RET_USAGE; +} + +#if CONFIG_IS_ENABLED(SYS_LONGHELP) +static char bootcount_help_text[] = + "print - print current bootcounter\n" + "reset - reset the bootcounter" + ; +#endif + +U_BOOT_CMD(bootcount, 2, 1, do_bootcount, + "bootcount", +#if CONFIG_IS_ENABLED(SYS_LONGHELP) + bootcount_help_text +#endif +); @@ -128,7 +128,7 @@ static int do_mmcinfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) return CMD_RET_SUCCESS; } -#ifdef CONFIG_SUPPORT_EMMC_RPMB +#if CONFIG_IS_ENABLED(CMD_MMC_RPMB) static int confirm_key_prog(void) { puts("Warning: Programming authentication key can be done only once !\n" @@ -886,7 +886,7 @@ static cmd_tbl_t cmd_mmc[] = { U_BOOT_CMD_MKENT(partconf, 5, 0, do_mmc_partconf, "", ""), U_BOOT_CMD_MKENT(rst-function, 3, 0, do_mmc_rst_func, "", ""), #endif -#ifdef CONFIG_SUPPORT_EMMC_RPMB +#if CONFIG_IS_ENABLED(CMD_MMC_RPMB) U_BOOT_CMD_MKENT(rpmb, CONFIG_SYS_MAXARGS, 1, do_mmcrpmb, "", ""), #endif U_BOOT_CMD_MKENT(setdsr, 2, 0, do_mmc_setdsr, "", ""), @@ -953,7 +953,7 @@ U_BOOT_CMD( " - Change the RST_n_FUNCTION field of the specified device\n" " WARNING: This is a write-once field and 0 / 1 / 2 are the only valid values.\n" #endif -#ifdef CONFIG_SUPPORT_EMMC_RPMB +#if CONFIG_IS_ENABLED(CMD_MMC_RPMB) "mmc rpmb read addr blk# cnt [address of auth-key] - block size is 256 bytes\n" "mmc rpmb write addr blk# cnt <address of auth-key> - block size is 256 bytes\n" "mmc rpmb key <address of auth-key> - program the RPMB authentication key.\n" diff --git a/cmd/pmic.c b/cmd/pmic.c index f4b4a3f588..e46d813a70 100644 --- a/cmd/pmic.c +++ b/cmd/pmic.c @@ -75,8 +75,9 @@ static int do_list(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) static int do_dump(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { + struct uc_pmic_priv *priv; struct udevice *dev; - uint8_t value; + char fmt[16]; uint reg; int ret; @@ -86,12 +87,15 @@ static int do_dump(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) } dev = currdev; - + priv = dev_get_uclass_priv(dev); printf("Dump pmic: %s registers\n", dev->name); + sprintf(fmt, "%%%d.%dx ", priv->trans_len * 2, + priv->trans_len * 2); + for (reg = 0; reg < pmic_reg_count(dev); reg++) { - ret = pmic_read(dev, reg, &value, 1); - if (ret) { + ret = pmic_reg_read(dev, reg); + if (ret < 0) { printf("Can't read register: %d\n", reg); return failure(ret); } @@ -99,7 +103,7 @@ static int do_dump(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) if (!(reg % 16)) printf("\n0x%02x: ", reg); - printf("%2.2x ", value); + printf(fmt, ret); } printf("\n"); @@ -108,9 +112,10 @@ static int do_dump(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) static int do_read(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { + struct uc_pmic_priv *priv; struct udevice *dev; int regs, ret; - uint8_t value; + char fmt[24]; uint reg; if (!currdev) { @@ -119,6 +124,7 @@ static int do_read(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) } dev = currdev; + priv = dev_get_uclass_priv(dev); if (argc != 2) return CMD_RET_USAGE; @@ -130,13 +136,15 @@ static int do_read(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) return failure(-EFAULT); } - ret = pmic_read(dev, reg, &value, 1); - if (ret) { + ret = pmic_reg_read(dev, reg); + if (ret < 0) { printf("Can't read PMIC register: %d!\n", reg); return failure(ret); } - printf("0x%02x: 0x%2.2x\n", reg, value); + sprintf(fmt, "0x%%02x: 0x%%%d.%dx\n", priv->trans_len * 2, + priv->trans_len * 2); + printf(fmt, reg, ret); return CMD_RET_SUCCESS; } @@ -144,9 +152,8 @@ static int do_read(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) static int do_write(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { struct udevice *dev; + uint reg, value; int regs, ret; - uint8_t value; - uint reg; if (!currdev) { printf("First, set the PMIC device!\n"); @@ -167,7 +174,7 @@ static int do_write(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) value = simple_strtoul(argv[2], NULL, 0); - ret = pmic_write(dev, reg, &value, 1); + ret = pmic_reg_write(dev, reg, value); if (ret) { printf("Can't write PMIC register: %d!\n", reg); return failure(ret); diff --git a/cmd/tpm-common.c b/cmd/tpm-common.c new file mode 100644 index 0000000000..6cf9fcc9ac --- /dev/null +++ b/cmd/tpm-common.c @@ -0,0 +1,288 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2013 The Chromium OS Authors. + */ + +#include <common.h> +#include <command.h> +#include <dm.h> +#include <asm/unaligned.h> +#include <linux/string.h> +#include <tpm-common.h> +#include "tpm-user-utils.h" + +/** + * Print a byte string in hexdecimal format, 16-bytes per line. + * + * @param data byte string to be printed + * @param count number of bytes to be printed + */ +void print_byte_string(u8 *data, size_t count) +{ + int i, print_newline = 0; + + for (i = 0; i < count; i++) { + printf(" %02x", data[i]); + print_newline = (i % 16 == 15); + if (print_newline) + putc('\n'); + } + /* Avoid duplicated newline at the end */ + if (!print_newline) + putc('\n'); +} + +/** + * Convert a text string of hexdecimal values into a byte string. + * + * @param bytes text string of hexdecimal values with no space + * between them + * @param data output buffer for byte string. The caller has to make + * sure it is large enough for storing the output. If + * NULL is passed, a large enough buffer will be allocated, + * and the caller must free it. + * @param count_ptr output variable for the length of byte string + * @return pointer to output buffer + */ +void *parse_byte_string(char *bytes, u8 *data, size_t *count_ptr) +{ + char byte[3]; + size_t count, length; + int i; + + if (!bytes) + return NULL; + length = strlen(bytes); + count = length / 2; + + if (!data) + data = malloc(count); + if (!data) + return NULL; + + byte[2] = '\0'; + for (i = 0; i < length; i += 2) { + byte[0] = bytes[i]; + byte[1] = bytes[i + 1]; + data[i / 2] = (u8)simple_strtoul(byte, NULL, 16); + } + + if (count_ptr) + *count_ptr = count; + + return data; +} + +/** + * report_return_code() - Report any error and return failure or success + * + * @param return_code TPM command return code + * @return value of enum command_ret_t + */ +int report_return_code(int return_code) +{ + if (return_code) { + printf("Error: %d\n", return_code); + return CMD_RET_FAILURE; + } else { + return CMD_RET_SUCCESS; + } +} + +/** + * Return number of values defined by a type string. + * + * @param type_str type string + * @return number of values of type string + */ +int type_string_get_num_values(const char *type_str) +{ + return strlen(type_str); +} + +/** + * Return total size of values defined by a type string. + * + * @param type_str type string + * @return total size of values of type string, or 0 if type string + * contains illegal type character. + */ +size_t type_string_get_space_size(const char *type_str) +{ + size_t size; + + for (size = 0; *type_str; type_str++) { + switch (*type_str) { + case 'b': + size += 1; + break; + case 'w': + size += 2; + break; + case 'd': + size += 4; + break; + default: + return 0; + } + } + + return size; +} + +/** + * Allocate a buffer large enough to hold values defined by a type + * string. The caller has to free the buffer. + * + * @param type_str type string + * @param count pointer for storing size of buffer + * @return pointer to buffer or NULL on error + */ +void *type_string_alloc(const char *type_str, u32 *count) +{ + void *data; + size_t size; + + size = type_string_get_space_size(type_str); + if (!size) + return NULL; + data = malloc(size); + if (data) + *count = size; + + return data; +} + +/** + * Pack values defined by a type string into a buffer. The buffer must have + * large enough space. + * + * @param type_str type string + * @param values text strings of values to be packed + * @param data output buffer of values + * @return 0 on success, non-0 on error + */ +int type_string_pack(const char *type_str, char * const values[], + u8 *data) +{ + size_t offset; + u32 value; + + for (offset = 0; *type_str; type_str++, values++) { + value = simple_strtoul(values[0], NULL, 0); + switch (*type_str) { + case 'b': + data[offset] = value; + offset += 1; + break; + case 'w': + put_unaligned_be16(value, data + offset); + offset += 2; + break; + case 'd': + put_unaligned_be32(value, data + offset); + offset += 4; + break; + default: + return -1; + } + } + + return 0; +} + +/** + * Read values defined by a type string from a buffer, and write these values + * to environment variables. + * + * @param type_str type string + * @param data input buffer of values + * @param vars names of environment variables + * @return 0 on success, non-0 on error + */ +int type_string_write_vars(const char *type_str, u8 *data, + char * const vars[]) +{ + size_t offset; + u32 value; + + for (offset = 0; *type_str; type_str++, vars++) { + switch (*type_str) { + case 'b': + value = data[offset]; + offset += 1; + break; + case 'w': + value = get_unaligned_be16(data + offset); + offset += 2; + break; + case 'd': + value = get_unaligned_be32(data + offset); + offset += 4; + break; + default: + return -1; + } + if (env_set_ulong(*vars, value)) + return -1; + } + + return 0; +} + +int get_tpm(struct udevice **devp) +{ + int rc; + + rc = uclass_first_device_err(UCLASS_TPM, devp); + if (rc) { + printf("Could not find TPM (ret=%d)\n", rc); + return CMD_RET_FAILURE; + } + + return 0; +} + +int do_tpm_info(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) +{ + struct udevice *dev; + char buf[80]; + int rc; + + rc = get_tpm(&dev); + if (rc) + return rc; + rc = tpm_get_desc(dev, buf, sizeof(buf)); + if (rc < 0) { + printf("Couldn't get TPM info (%d)\n", rc); + return CMD_RET_FAILURE; + } + printf("%s\n", buf); + + return 0; +} + +int do_tpm_init(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + if (argc != 1) + return CMD_RET_USAGE; + + return report_return_code(tpm_init()); +} + +int do_tpm(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + cmd_tbl_t *tpm_commands, *cmd; + unsigned int size; + + if (argc < 2) + return CMD_RET_USAGE; + + tpm_commands = get_tpm_commands(&size); + + cmd = find_cmd_tbl(argv[1], tpm_commands, size); + if (!cmd) + return CMD_RET_USAGE; + + return cmd->cmd(cmdtp, flag, argc - 1, argv + 1); +} diff --git a/cmd/tpm-user-utils.h b/cmd/tpm-user-utils.h new file mode 100644 index 0000000000..8ce9861784 --- /dev/null +++ b/cmd/tpm-user-utils.h @@ -0,0 +1,24 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (c) 2013 The Chromium OS Authors. + * Coypright (c) 2013 Guntermann & Drunck GmbH + */ + +#ifndef __TPM_USER_UTILS_H +#define __TPM_USER_UTILS_H + +void print_byte_string(u8 *data, size_t count); +void *parse_byte_string(char *bytes, u8 *data, size_t *count_ptr); +int report_return_code(int return_code); +int type_string_get_num_values(const char *type_str); +size_t type_string_get_space_size(const char *type_str); +void *type_string_alloc(const char *type_str, u32 *count); +int type_string_pack(const char *type_str, char * const values[], u8 *data); +int type_string_write_vars(const char *type_str, u8 *data, char * const vars[]); +int get_tpm(struct udevice **devp); + +int do_tpm_init(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]); +int do_tpm_info(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]); +int do_tpm(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]); + +#endif /* __TPM_USER_UTILS_H */ diff --git a/cmd/tpm.c b/cmd/tpm-v1.c index c173bcfe42..0874c4d7ba 100644 --- a/cmd/tpm.c +++ b/cmd/tpm-v1.c @@ -4,241 +4,14 @@ */ #include <common.h> -#include <command.h> -#include <dm.h> #include <malloc.h> -#include <tpm.h> #include <asm/unaligned.h> -#include <linux/string.h> +#include <tpm-common.h> +#include <tpm-v1.h> +#include "tpm-user-utils.h" -/* Useful constants */ -enum { - DIGEST_LENGTH = 20, - /* max lengths, valid for RSA keys <= 2048 bits */ - TPM_PUBKEY_MAX_LENGTH = 288, -}; - -/** - * Print a byte string in hexdecimal format, 16-bytes per line. - * - * @param data byte string to be printed - * @param count number of bytes to be printed - */ -static void print_byte_string(uint8_t *data, size_t count) -{ - int i, print_newline = 0; - - for (i = 0; i < count; i++) { - printf(" %02x", data[i]); - print_newline = (i % 16 == 15); - if (print_newline) - putc('\n'); - } - /* Avoid duplicated newline at the end */ - if (!print_newline) - putc('\n'); -} - -/** - * Convert a text string of hexdecimal values into a byte string. - * - * @param bytes text string of hexdecimal values with no space - * between them - * @param data output buffer for byte string. The caller has to make - * sure it is large enough for storing the output. If - * NULL is passed, a large enough buffer will be allocated, - * and the caller must free it. - * @param count_ptr output variable for the length of byte string - * @return pointer to output buffer - */ -static void *parse_byte_string(char *bytes, uint8_t *data, size_t *count_ptr) -{ - char byte[3]; - size_t count, length; - int i; - - if (!bytes) - return NULL; - length = strlen(bytes); - count = length / 2; - - if (!data) - data = malloc(count); - if (!data) - return NULL; - - byte[2] = '\0'; - for (i = 0; i < length; i += 2) { - byte[0] = bytes[i]; - byte[1] = bytes[i + 1]; - data[i / 2] = (uint8_t)simple_strtoul(byte, NULL, 16); - } - - if (count_ptr) - *count_ptr = count; - - return data; -} - -/** - * report_return_code() - Report any error and return failure or success - * - * @param return_code TPM command return code - * @return value of enum command_ret_t - */ -static int report_return_code(int return_code) -{ - if (return_code) { - printf("Error: %d\n", return_code); - return CMD_RET_FAILURE; - } else { - return CMD_RET_SUCCESS; - } -} - -/** - * Return number of values defined by a type string. - * - * @param type_str type string - * @return number of values of type string - */ -static int type_string_get_num_values(const char *type_str) -{ - return strlen(type_str); -} - -/** - * Return total size of values defined by a type string. - * - * @param type_str type string - * @return total size of values of type string, or 0 if type string - * contains illegal type character. - */ -static size_t type_string_get_space_size(const char *type_str) -{ - size_t size; - - for (size = 0; *type_str; type_str++) { - switch (*type_str) { - case 'b': - size += 1; - break; - case 'w': - size += 2; - break; - case 'd': - size += 4; - break; - default: - return 0; - } - } - - return size; -} - -/** - * Allocate a buffer large enough to hold values defined by a type - * string. The caller has to free the buffer. - * - * @param type_str type string - * @param count pointer for storing size of buffer - * @return pointer to buffer or NULL on error - */ -static void *type_string_alloc(const char *type_str, uint32_t *count) -{ - void *data; - size_t size; - - size = type_string_get_space_size(type_str); - if (!size) - return NULL; - data = malloc(size); - if (data) - *count = size; - - return data; -} - -/** - * Pack values defined by a type string into a buffer. The buffer must have - * large enough space. - * - * @param type_str type string - * @param values text strings of values to be packed - * @param data output buffer of values - * @return 0 on success, non-0 on error - */ -static int type_string_pack(const char *type_str, char * const values[], - uint8_t *data) -{ - size_t offset; - uint32_t value; - - for (offset = 0; *type_str; type_str++, values++) { - value = simple_strtoul(values[0], NULL, 0); - switch (*type_str) { - case 'b': - data[offset] = value; - offset += 1; - break; - case 'w': - put_unaligned_be16(value, data + offset); - offset += 2; - break; - case 'd': - put_unaligned_be32(value, data + offset); - offset += 4; - break; - default: - return -1; - } - } - - return 0; -} - -/** - * Read values defined by a type string from a buffer, and write these values - * to environment variables. - * - * @param type_str type string - * @param data input buffer of values - * @param vars names of environment variables - * @return 0 on success, non-0 on error - */ -static int type_string_write_vars(const char *type_str, uint8_t *data, - char * const vars[]) -{ - size_t offset; - uint32_t value; - - for (offset = 0; *type_str; type_str++, vars++) { - switch (*type_str) { - case 'b': - value = data[offset]; - offset += 1; - break; - case 'w': - value = get_unaligned_be16(data + offset); - offset += 2; - break; - case 'd': - value = get_unaligned_be32(data + offset); - offset += 4; - break; - default: - return -1; - } - if (env_set_ulong(*vars, value)) - return -1; - } - - return 0; -} - -static int do_tpm_startup(cmd_tbl_t *cmdtp, int flag, - int argc, char * const argv[]) +static int do_tpm_startup(cmd_tbl_t *cmdtp, int flag, int argc, + char * const argv[]) { enum tpm_startup_type mode; @@ -258,10 +31,10 @@ static int do_tpm_startup(cmd_tbl_t *cmdtp, int flag, return report_return_code(tpm_startup(mode)); } -static int do_tpm_nv_define_space(cmd_tbl_t *cmdtp, int flag, - int argc, char * const argv[]) +static int do_tpm_nv_define_space(cmd_tbl_t *cmdtp, int flag, int argc, + char * const argv[]) { - uint32_t index, perm, size; + u32 index, perm, size; if (argc != 4) return CMD_RET_USAGE; @@ -272,10 +45,10 @@ static int do_tpm_nv_define_space(cmd_tbl_t *cmdtp, int flag, return report_return_code(tpm_nv_define_space(index, perm, size)); } -static int do_tpm_nv_read_value(cmd_tbl_t *cmdtp, int flag, - int argc, char * const argv[]) +static int do_tpm_nv_read_value(cmd_tbl_t *cmdtp, int flag, int argc, + char * const argv[]) { - uint32_t index, count, rc; + u32 index, count, rc; void *data; if (argc != 4) @@ -293,10 +66,10 @@ static int do_tpm_nv_read_value(cmd_tbl_t *cmdtp, int flag, return report_return_code(rc); } -static int do_tpm_nv_write_value(cmd_tbl_t *cmdtp, int flag, - int argc, char * const argv[]) +static int do_tpm_nv_write_value(cmd_tbl_t *cmdtp, int flag, int argc, + char * const argv[]) { - uint32_t index, rc; + u32 index, rc; size_t count; void *data; @@ -315,11 +88,11 @@ static int do_tpm_nv_write_value(cmd_tbl_t *cmdtp, int flag, return report_return_code(rc); } -static int do_tpm_extend(cmd_tbl_t *cmdtp, int flag, - int argc, char * const argv[]) +static int do_tpm_extend(cmd_tbl_t *cmdtp, int flag, int argc, + char * const argv[]) { - uint32_t index, rc; - uint8_t in_digest[20], out_digest[20]; + u32 index, rc; + u8 in_digest[20], out_digest[20]; if (argc != 3) return CMD_RET_USAGE; @@ -338,10 +111,10 @@ static int do_tpm_extend(cmd_tbl_t *cmdtp, int flag, return report_return_code(rc); } -static int do_tpm_pcr_read(cmd_tbl_t *cmdtp, int flag, - int argc, char * const argv[]) +static int do_tpm_pcr_read(cmd_tbl_t *cmdtp, int flag, int argc, + char * const argv[]) { - uint32_t index, count, rc; + u32 index, count, rc; void *data; if (argc != 4) @@ -359,22 +132,22 @@ static int do_tpm_pcr_read(cmd_tbl_t *cmdtp, int flag, return report_return_code(rc); } -static int do_tpm_tsc_physical_presence(cmd_tbl_t *cmdtp, int flag, - int argc, char * const argv[]) +static int do_tpm_tsc_physical_presence(cmd_tbl_t *cmdtp, int flag, int argc, + char * const argv[]) { - uint16_t presence; + u16 presence; if (argc != 2) return CMD_RET_USAGE; - presence = (uint16_t)simple_strtoul(argv[1], NULL, 0); + presence = (u16)simple_strtoul(argv[1], NULL, 0); return report_return_code(tpm_tsc_physical_presence(presence)); } -static int do_tpm_read_pubek(cmd_tbl_t *cmdtp, int flag, - int argc, char * const argv[]) +static int do_tpm_read_pubek(cmd_tbl_t *cmdtp, int flag, int argc, + char * const argv[]) { - uint32_t count, rc; + u32 count, rc; void *data; if (argc != 3) @@ -391,22 +164,22 @@ static int do_tpm_read_pubek(cmd_tbl_t *cmdtp, int flag, return report_return_code(rc); } -static int do_tpm_physical_set_deactivated(cmd_tbl_t *cmdtp, int flag, - int argc, char * const argv[]) +static int do_tpm_physical_set_deactivated(cmd_tbl_t *cmdtp, int flag, int argc, + char * const argv[]) { - uint8_t state; + u8 state; if (argc != 2) return CMD_RET_USAGE; - state = (uint8_t)simple_strtoul(argv[1], NULL, 0); + state = (u8)simple_strtoul(argv[1], NULL, 0); return report_return_code(tpm_physical_set_deactivated(state)); } -static int do_tpm_get_capability(cmd_tbl_t *cmdtp, int flag, - int argc, char * const argv[]) +static int do_tpm_get_capability(cmd_tbl_t *cmdtp, int flag, int argc, + char * const argv[]) { - uint32_t cap_area, sub_cap, rc; + u32 cap_area, sub_cap, rc; void *cap; size_t count; @@ -426,63 +199,14 @@ static int do_tpm_get_capability(cmd_tbl_t *cmdtp, int flag, return report_return_code(rc); } -#define TPM_COMMAND_NO_ARG(cmd) \ -static int do_##cmd(cmd_tbl_t *cmdtp, int flag, \ - int argc, char * const argv[]) \ -{ \ - if (argc != 1) \ - return CMD_RET_USAGE; \ - 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) -TPM_COMMAND_NO_ARG(tpm_physical_enable) -TPM_COMMAND_NO_ARG(tpm_physical_disable) - -static int get_tpm(struct udevice **devp) -{ - int rc; - - rc = uclass_first_device_err(UCLASS_TPM, devp); - if (rc) { - printf("Could not find TPM (ret=%d)\n", rc); - return CMD_RET_FAILURE; - } - - return 0; -} - -static int do_tpm_info(cmd_tbl_t *cmdtp, int flag, int argc, - char *const argv[]) -{ - struct udevice *dev; - char buf[80]; - int rc; - - rc = get_tpm(&dev); - if (rc) - return rc; - rc = tpm_get_desc(dev, buf, sizeof(buf)); - if (rc < 0) { - printf("Couldn't get TPM info (%d)\n", rc); - return CMD_RET_FAILURE; - } - printf("%s\n", buf); - - return 0; -} - -static int do_tpm_raw_transfer(cmd_tbl_t *cmdtp, int flag, - int argc, char * const argv[]) +static int do_tpm_raw_transfer(cmd_tbl_t *cmdtp, int flag, int argc, + char * const argv[]) { struct udevice *dev; void *command; - uint8_t response[1024]; + u8 response[1024]; size_t count, response_length = sizeof(response); - uint32_t rc; + u32 rc; command = parse_byte_string(argv[1], NULL, &count); if (!command) { @@ -504,10 +228,10 @@ static int do_tpm_raw_transfer(cmd_tbl_t *cmdtp, int flag, return report_return_code(rc); } -static int do_tpm_nv_define(cmd_tbl_t *cmdtp, int flag, - int argc, char * const argv[]) +static int do_tpm_nv_define(cmd_tbl_t *cmdtp, int flag, int argc, + char * const argv[]) { - uint32_t index, perm, size; + u32 index, perm, size; if (argc != 4) return CMD_RET_USAGE; @@ -522,10 +246,10 @@ static int do_tpm_nv_define(cmd_tbl_t *cmdtp, int flag, return report_return_code(tpm_nv_define_space(index, perm, size)); } -static int do_tpm_nv_read(cmd_tbl_t *cmdtp, int flag, - int argc, char * const argv[]) +static int do_tpm_nv_read(cmd_tbl_t *cmdtp, int flag, int argc, + char * const argv[]) { - uint32_t index, count, err; + u32 index, count, err; void *data; if (argc < 3) @@ -551,10 +275,10 @@ static int do_tpm_nv_read(cmd_tbl_t *cmdtp, int flag, return report_return_code(err); } -static int do_tpm_nv_write(cmd_tbl_t *cmdtp, int flag, - int argc, char * const argv[]) +static int do_tpm_nv_write(cmd_tbl_t *cmdtp, int flag, int argc, + char * const argv[]) { - uint32_t index, count, err; + u32 index, count, err; void *data; if (argc < 3) @@ -581,10 +305,10 @@ static int do_tpm_nv_write(cmd_tbl_t *cmdtp, int flag, #ifdef CONFIG_TPM_AUTH_SESSIONS -static int do_tpm_oiap(cmd_tbl_t *cmdtp, int flag, - int argc, char * const argv[]) +static int do_tpm_oiap(cmd_tbl_t *cmdtp, int flag, int argc, + char * const argv[]) { - uint32_t auth_handle, err; + u32 auth_handle, err; err = tpm_oiap(&auth_handle); @@ -595,10 +319,10 @@ static int do_tpm_oiap(cmd_tbl_t *cmdtp, int flag, static int do_tpm_load_key_by_sha1(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { - uint32_t parent_handle = 0; - uint32_t key_len, key_handle, err; - uint8_t usage_auth[DIGEST_LENGTH]; - uint8_t parent_hash[DIGEST_LENGTH]; + u32 parent_handle = 0; + u32 key_len, key_handle, err; + u8 usage_auth[DIGEST_LENGTH]; + u8 parent_hash[DIGEST_LENGTH]; void *key; if (argc < 5) @@ -630,11 +354,11 @@ static int do_tpm_load_key_by_sha1(cmd_tbl_t *cmdtp, int flag, int argc, char * } #endif /* CONFIG_TPM_LOAD_KEY_BY_SHA1 */ -static int do_tpm_load_key2_oiap(cmd_tbl_t *cmdtp, int flag, - int argc, char * const argv[]) +static int do_tpm_load_key2_oiap(cmd_tbl_t *cmdtp, int flag, int argc, + char * const argv[]) { - uint32_t parent_handle, key_len, key_handle, err; - uint8_t usage_auth[DIGEST_LENGTH]; + u32 parent_handle, key_len, key_handle, err; + u8 usage_auth[DIGEST_LENGTH]; void *key; if (argc < 5) @@ -648,19 +372,19 @@ static int do_tpm_load_key2_oiap(cmd_tbl_t *cmdtp, int flag, parse_byte_string(argv[4], usage_auth, NULL); err = tpm_load_key2_oiap(parent_handle, key, key_len, usage_auth, - &key_handle); + &key_handle); if (!err) printf("Key handle is 0x%x\n", key_handle); return report_return_code(err); } -static int do_tpm_get_pub_key_oiap(cmd_tbl_t *cmdtp, int flag, - int argc, char * const argv[]) +static int do_tpm_get_pub_key_oiap(cmd_tbl_t *cmdtp, int flag, int argc, + char * const argv[]) { - uint32_t key_handle, err; - uint8_t usage_auth[DIGEST_LENGTH]; - uint8_t pub_key_buffer[TPM_PUBKEY_MAX_LENGTH]; + u32 key_handle, err; + u8 usage_auth[DIGEST_LENGTH]; + u8 pub_key_buffer[TPM_PUBKEY_MAX_LENGTH]; size_t pub_key_len = sizeof(pub_key_buffer); if (argc < 3) @@ -671,8 +395,8 @@ static int do_tpm_get_pub_key_oiap(cmd_tbl_t *cmdtp, int flag, return CMD_RET_FAILURE; parse_byte_string(argv[2], usage_auth, NULL); - err = tpm_get_pub_key_oiap(key_handle, usage_auth, - pub_key_buffer, &pub_key_len); + err = tpm_get_pub_key_oiap(key_handle, usage_auth, pub_key_buffer, + &pub_key_len); if (!err) { printf("dump of received pub key structure:\n"); print_byte_string(pub_key_buffer, pub_key_len); @@ -720,9 +444,9 @@ static int do_tpm_flush(cmd_tbl_t *cmdtp, int flag, int argc, } if (!strcasecmp(argv[2], "all")) { - uint16_t res_count; - uint8_t buf[288]; - uint8_t *ptr; + u16 res_count; + u8 buf[288]; + u8 *ptr; int err; uint i; @@ -738,7 +462,7 @@ static int do_tpm_flush(cmd_tbl_t *cmdtp, int flag, int argc, for (i = 0; i < res_count; ++i, ptr += 4) tpm_flush_specific(get_unaligned_be32(ptr), type); } else { - uint32_t handle = simple_strtoul(argv[2], NULL, 0); + u32 handle = simple_strtoul(argv[2], NULL, 0); if (!handle) { printf("Illegal resource handle %s\n", argv[2]); @@ -756,9 +480,9 @@ static int do_tpm_list(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { int type = 0; - uint16_t res_count; - uint8_t buf[288]; - uint8_t *ptr; + u16 res_count; + u8 buf[288]; + u8 *ptr; int err; uint i; @@ -813,51 +537,53 @@ static int do_tpm_list(cmd_tbl_t *cmdtp, int flag, int argc, } #endif /* CONFIG_TPM_LIST_RESOURCES */ -#define MAKE_TPM_CMD_ENTRY(cmd) \ - U_BOOT_CMD_MKENT(cmd, 0, 1, do_tpm_ ## cmd, "", "") +TPM_COMMAND_NO_ARG(tpm_self_test_full) +TPM_COMMAND_NO_ARG(tpm_continue_self_test) +TPM_COMMAND_NO_ARG(tpm_force_clear) +TPM_COMMAND_NO_ARG(tpm_physical_enable) +TPM_COMMAND_NO_ARG(tpm_physical_disable) -static cmd_tbl_t tpm_commands[] = { +static cmd_tbl_t tpm1_commands[] = { U_BOOT_CMD_MKENT(info, 0, 1, do_tpm_info, "", ""), - U_BOOT_CMD_MKENT(init, 0, 1, - do_tpm_init, "", ""), + U_BOOT_CMD_MKENT(init, 0, 1, do_tpm_init, "", ""), U_BOOT_CMD_MKENT(startup, 0, 1, - do_tpm_startup, "", ""), + do_tpm_startup, "", ""), U_BOOT_CMD_MKENT(self_test_full, 0, 1, - do_tpm_self_test_full, "", ""), + do_tpm_self_test_full, "", ""), U_BOOT_CMD_MKENT(continue_self_test, 0, 1, - do_tpm_continue_self_test, "", ""), + do_tpm_continue_self_test, "", ""), U_BOOT_CMD_MKENT(force_clear, 0, 1, - do_tpm_force_clear, "", ""), + do_tpm_force_clear, "", ""), U_BOOT_CMD_MKENT(physical_enable, 0, 1, - do_tpm_physical_enable, "", ""), + do_tpm_physical_enable, "", ""), U_BOOT_CMD_MKENT(physical_disable, 0, 1, - do_tpm_physical_disable, "", ""), + do_tpm_physical_disable, "", ""), U_BOOT_CMD_MKENT(nv_define_space, 0, 1, - do_tpm_nv_define_space, "", ""), + do_tpm_nv_define_space, "", ""), U_BOOT_CMD_MKENT(nv_read_value, 0, 1, - do_tpm_nv_read_value, "", ""), + do_tpm_nv_read_value, "", ""), U_BOOT_CMD_MKENT(nv_write_value, 0, 1, - do_tpm_nv_write_value, "", ""), + do_tpm_nv_write_value, "", ""), U_BOOT_CMD_MKENT(extend, 0, 1, - do_tpm_extend, "", ""), + do_tpm_extend, "", ""), U_BOOT_CMD_MKENT(pcr_read, 0, 1, - do_tpm_pcr_read, "", ""), + do_tpm_pcr_read, "", ""), U_BOOT_CMD_MKENT(tsc_physical_presence, 0, 1, - do_tpm_tsc_physical_presence, "", ""), + do_tpm_tsc_physical_presence, "", ""), U_BOOT_CMD_MKENT(read_pubek, 0, 1, - do_tpm_read_pubek, "", ""), + do_tpm_read_pubek, "", ""), U_BOOT_CMD_MKENT(physical_set_deactivated, 0, 1, - do_tpm_physical_set_deactivated, "", ""), + do_tpm_physical_set_deactivated, "", ""), U_BOOT_CMD_MKENT(get_capability, 0, 1, - do_tpm_get_capability, "", ""), + do_tpm_get_capability, "", ""), U_BOOT_CMD_MKENT(raw_transfer, 0, 1, - do_tpm_raw_transfer, "", ""), + do_tpm_raw_transfer, "", ""), U_BOOT_CMD_MKENT(nv_define, 0, 1, - do_tpm_nv_define, "", ""), + do_tpm_nv_define, "", ""), U_BOOT_CMD_MKENT(nv_read, 0, 1, - do_tpm_nv_read, "", ""), + do_tpm_nv_read, "", ""), U_BOOT_CMD_MKENT(nv_write, 0, 1, - do_tpm_nv_write, "", ""), + do_tpm_nv_write, "", ""), #ifdef CONFIG_TPM_AUTH_SESSIONS U_BOOT_CMD_MKENT(oiap, 0, 1, do_tpm_oiap, "", ""), @@ -882,21 +608,15 @@ static cmd_tbl_t tpm_commands[] = { #endif /* CONFIG_TPM_LIST_RESOURCES */ }; -static int do_tpm(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +cmd_tbl_t *get_tpm_commands(unsigned int *size) { - cmd_tbl_t *tpm_cmd; - - if (argc < 2) - return CMD_RET_USAGE; - tpm_cmd = find_cmd_tbl(argv[1], tpm_commands, ARRAY_SIZE(tpm_commands)); - if (!tpm_cmd) - return CMD_RET_USAGE; + *size = ARRAY_SIZE(tpm1_commands); - return tpm_cmd->cmd(cmdtp, flag, argc - 1, argv + 1); + return tpm1_commands; } U_BOOT_CMD(tpm, CONFIG_SYS_MAXARGS, 1, do_tpm, -"Issue a TPM command", +"Issue a TPMv1.x command", "cmd args...\n" " - Issue TPM command <cmd> with arguments <args...>.\n" "Admin Startup and State Commands:\n" diff --git a/cmd/tpm-v2.c b/cmd/tpm-v2.c new file mode 100644 index 0000000000..38add4f462 --- /dev/null +++ b/cmd/tpm-v2.c @@ -0,0 +1,389 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2018 Bootlin + * Author: Miquel Raynal <miquel.raynal@bootlin.com> + */ + +#include <common.h> +#include <dm.h> +#include <log.h> +#include <mapmem.h> +#include <tpm-common.h> +#include <tpm-v2.h> +#include "tpm-user-utils.h" + +static int do_tpm2_startup(cmd_tbl_t *cmdtp, int flag, int argc, + char * const argv[]) +{ + enum tpm2_startup_types mode; + + if (argc != 2) + return CMD_RET_USAGE; + + if (!strcasecmp("TPM2_SU_CLEAR", argv[1])) { + mode = TPM2_SU_CLEAR; + } else if (!strcasecmp("TPM2_SU_STATE", argv[1])) { + mode = TPM2_SU_STATE; + } else { + printf("Couldn't recognize mode string: %s\n", argv[1]); + return CMD_RET_FAILURE; + } + + return report_return_code(tpm2_startup(mode)); +} + +static int do_tpm2_self_test(cmd_tbl_t *cmdtp, int flag, int argc, + char * const argv[]) +{ + enum tpm2_yes_no full_test; + + if (argc != 2) + return CMD_RET_USAGE; + + if (!strcasecmp("full", argv[1])) { + full_test = TPMI_YES; + } else if (!strcasecmp("continue", argv[1])) { + full_test = TPMI_NO; + } else { + printf("Couldn't recognize test mode: %s\n", argv[1]); + return CMD_RET_FAILURE; + } + + return report_return_code(tpm2_self_test(full_test)); +} + +static int do_tpm2_clear(cmd_tbl_t *cmdtp, int flag, int argc, + char * const argv[]) +{ + u32 handle = 0; + const char *pw = (argc < 3) ? NULL : argv[2]; + const ssize_t pw_sz = pw ? strlen(pw) : 0; + + if (argc < 2 || argc > 3) + return CMD_RET_USAGE; + + if (pw_sz > TPM2_DIGEST_LEN) + return -EINVAL; + + if (!strcasecmp("TPM2_RH_LOCKOUT", argv[1])) + handle = TPM2_RH_LOCKOUT; + else if (!strcasecmp("TPM2_RH_PLATFORM", argv[1])) + handle = TPM2_RH_PLATFORM; + else + return CMD_RET_USAGE; + + return report_return_code(tpm2_clear(handle, pw, pw_sz)); +} + +static int do_tpm2_pcr_extend(cmd_tbl_t *cmdtp, int flag, int argc, + char * const argv[]) +{ + struct udevice *dev; + struct tpm_chip_priv *priv; + u32 index = simple_strtoul(argv[1], NULL, 0); + void *digest = map_sysmem(simple_strtoul(argv[2], NULL, 0), 0); + int ret; + u32 rc; + + if (argc != 3) + return CMD_RET_USAGE; + + ret = uclass_first_device_err(UCLASS_TPM, &dev); + if (ret) + return ret; + + priv = dev_get_uclass_priv(dev); + if (!priv) + return -EINVAL; + + if (index >= priv->pcr_count) + return -EINVAL; + + rc = tpm2_pcr_extend(index, digest); + + unmap_sysmem(digest); + + return report_return_code(rc); +} + +static int do_tpm_pcr_read(cmd_tbl_t *cmdtp, int flag, int argc, + char * const argv[]) +{ + struct udevice *dev; + struct tpm_chip_priv *priv; + u32 index, rc; + unsigned int updates; + void *data; + int ret; + + if (argc != 3) + return CMD_RET_USAGE; + + ret = uclass_first_device_err(UCLASS_TPM, &dev); + if (ret) + return ret; + + priv = dev_get_uclass_priv(dev); + if (!priv) + return -EINVAL; + + index = simple_strtoul(argv[1], NULL, 0); + if (index >= priv->pcr_count) + return -EINVAL; + + data = map_sysmem(simple_strtoul(argv[2], NULL, 0), 0); + + rc = tpm2_pcr_read(index, priv->pcr_select_min, data, &updates); + if (!rc) { + printf("PCR #%u content (%d known updates):\n", index, updates); + print_byte_string(data, TPM2_DIGEST_LEN); + } + + unmap_sysmem(data); + + return report_return_code(rc); +} + +static int do_tpm_get_capability(cmd_tbl_t *cmdtp, int flag, int argc, + char * const argv[]) +{ + u32 capability, property, rc; + u8 *data; + size_t count; + int i, j; + + if (argc != 5) + return CMD_RET_USAGE; + + capability = simple_strtoul(argv[1], NULL, 0); + property = simple_strtoul(argv[2], NULL, 0); + data = map_sysmem(simple_strtoul(argv[3], NULL, 0), 0); + count = simple_strtoul(argv[4], NULL, 0); + + rc = tpm2_get_capability(capability, property, data, count); + if (rc) + goto unmap_data; + + printf("Capabilities read from TPM:\n"); + for (i = 0; i < count; i++) { + printf("Property 0x"); + for (j = 0; j < 4; j++) + printf("%02x", data[(i * 8) + j]); + printf(": 0x"); + for (j = 4; j < 8; j++) + printf("%02x", data[(i * 8) + j]); + printf("\n"); + } + +unmap_data: + unmap_sysmem(data); + + return report_return_code(rc); +} + +static int do_tpm_dam_reset(cmd_tbl_t *cmdtp, int flag, int argc, + char *const argv[]) +{ + const char *pw = (argc < 2) ? NULL : argv[1]; + const ssize_t pw_sz = pw ? strlen(pw) : 0; + + if (argc > 2) + return CMD_RET_USAGE; + + if (pw_sz > TPM2_DIGEST_LEN) + return -EINVAL; + + return report_return_code(tpm2_dam_reset(pw, pw_sz)); +} + +static int do_tpm_dam_parameters(cmd_tbl_t *cmdtp, int flag, int argc, + char *const argv[]) +{ + const char *pw = (argc < 5) ? NULL : argv[4]; + const ssize_t pw_sz = pw ? strlen(pw) : 0; + /* + * No Dictionary Attack Mitigation (DAM) means: + * maxtries = 0xFFFFFFFF, recovery_time = 1, lockout_recovery = 0 + */ + unsigned long int max_tries; + unsigned long int recovery_time; + unsigned long int lockout_recovery; + + if (argc < 4 || argc > 5) + return CMD_RET_USAGE; + + if (pw_sz > TPM2_DIGEST_LEN) + return -EINVAL; + + if (strict_strtoul(argv[1], 0, &max_tries)) + return CMD_RET_USAGE; + + if (strict_strtoul(argv[2], 0, &recovery_time)) + return CMD_RET_USAGE; + + if (strict_strtoul(argv[3], 0, &lockout_recovery)) + return CMD_RET_USAGE; + + log(LOGC_NONE, LOGL_INFO, "Changing dictionary attack parameters:\n"); + log(LOGC_NONE, LOGL_INFO, "- maxTries: %lu", max_tries); + log(LOGC_NONE, LOGL_INFO, "- recoveryTime: %lu\n", recovery_time); + log(LOGC_NONE, LOGL_INFO, "- lockoutRecovery: %lu\n", lockout_recovery); + + return report_return_code(tpm2_dam_parameters(pw, pw_sz, max_tries, + recovery_time, + lockout_recovery)); +} + +static int do_tpm_change_auth(cmd_tbl_t *cmdtp, int flag, int argc, + char *const argv[]) +{ + u32 handle; + const char *newpw = argv[2]; + const char *oldpw = (argc == 3) ? NULL : argv[3]; + const ssize_t newpw_sz = strlen(newpw); + const ssize_t oldpw_sz = oldpw ? strlen(oldpw) : 0; + + if (argc < 3 || argc > 4) + return CMD_RET_USAGE; + + if (newpw_sz > TPM2_DIGEST_LEN || oldpw_sz > TPM2_DIGEST_LEN) + return -EINVAL; + + if (!strcasecmp("TPM2_RH_LOCKOUT", argv[1])) + handle = TPM2_RH_LOCKOUT; + else if (!strcasecmp("TPM2_RH_ENDORSEMENT", argv[1])) + handle = TPM2_RH_ENDORSEMENT; + else if (!strcasecmp("TPM2_RH_OWNER", argv[1])) + handle = TPM2_RH_OWNER; + else if (!strcasecmp("TPM2_RH_PLATFORM", argv[1])) + handle = TPM2_RH_PLATFORM; + else + return CMD_RET_USAGE; + + return report_return_code(tpm2_change_auth(handle, newpw, newpw_sz, + oldpw, oldpw_sz)); +} + +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_LEN) + 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_LEN) + 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 cmd_tbl_t tpm2_commands[] = { + U_BOOT_CMD_MKENT(info, 0, 1, do_tpm_info, "", ""), + U_BOOT_CMD_MKENT(init, 0, 1, do_tpm_init, "", ""), + U_BOOT_CMD_MKENT(startup, 0, 1, do_tpm2_startup, "", ""), + U_BOOT_CMD_MKENT(self_test, 0, 1, do_tpm2_self_test, "", ""), + U_BOOT_CMD_MKENT(clear, 0, 1, do_tpm2_clear, "", ""), + U_BOOT_CMD_MKENT(pcr_extend, 0, 1, do_tpm2_pcr_extend, "", ""), + U_BOOT_CMD_MKENT(pcr_read, 0, 1, do_tpm_pcr_read, "", ""), + U_BOOT_CMD_MKENT(get_capability, 0, 1, do_tpm_get_capability, "", ""), + U_BOOT_CMD_MKENT(dam_reset, 0, 1, do_tpm_dam_reset, "", ""), + U_BOOT_CMD_MKENT(dam_parameters, 0, 1, do_tpm_dam_parameters, "", ""), + U_BOOT_CMD_MKENT(change_auth, 0, 1, do_tpm_change_auth, "", ""), + U_BOOT_CMD_MKENT(pcr_setauthpolicy, 0, 1, + do_tpm_pcr_setauthpolicy, "", ""), + U_BOOT_CMD_MKENT(pcr_setauthvalue, 0, 1, + do_tpm_pcr_setauthvalue, "", ""), +}; + +cmd_tbl_t *get_tpm_commands(unsigned int *size) +{ + *size = ARRAY_SIZE(tpm2_commands); + + return tpm2_commands; +} + +U_BOOT_CMD(tpm, CONFIG_SYS_MAXARGS, 1, do_tpm, "Issue a TPMv2.x command", +"<command> [<arguments>]\n" +"\n" +"info\n" +" Show information about the TPM.\n" +"init\n" +" Initialize the software stack. Always the first command to issue.\n" +"startup <mode>\n" +" Issue a TPM2_Startup command.\n" +" <mode> is one of:\n" +" * TPM2_SU_CLEAR (reset state)\n" +" * TPM2_SU_STATE (preserved state)\n" +"self_test <type>\n" +" Test the TPM capabilities.\n" +" <type> is one of:\n" +" * full (perform all tests)\n" +" * continue (only check untested tests)\n" +"clear <hierarchy>\n" +" Issue a TPM2_Clear command.\n" +" <hierarchy> is one of:\n" +" * TPM2_RH_LOCKOUT\n" +" * TPM2_RH_PLATFORM\n" +"pcr_extend <pcr> <digest_addr>\n" +" Extend PCR #<pcr> with digest at <digest_addr>.\n" +" <pcr>: index of the PCR\n" +" <digest_addr>: address of a 32-byte SHA256 digest\n" +"pcr_read <pcr> <digest_addr>\n" +" Read PCR #<pcr> to memory address <digest_addr>.\n" +" <pcr>: index of the PCR\n" +" <digest_addr>: address to store the a 32-byte SHA256 digest\n" +"get_capability <capability> <property> <addr> <count>\n" +" Read and display <count> entries indexed by <capability>/<property>.\n" +" Values are 4 bytes long and are written at <addr>.\n" +" <capability>: capability\n" +" <property>: property\n" +" <addr>: address to store <count> entries of 4 bytes\n" +" <count>: number of entries to retrieve\n" +"dam_reset [<password>]\n" +" If the TPM is not in a LOCKOUT state, reset the internal error counter.\n" +" <password>: optional password\n" +"dam_parameters <max_tries> <recovery_time> <lockout_recovery> [<password>]\n" +" If the TPM is not in a LOCKOUT state, set the DAM parameters\n" +" <maxTries>: maximum number of failures before lockout,\n" +" 0 means always locking\n" +" <recoveryTime>: time before decrement of the error counter,\n" +" 0 means no lockout\n" +" <lockoutRecovery>: time of a lockout (before the next try),\n" +" 0 means a reboot is needed\n" +" <password>: optional password of the LOCKOUT hierarchy\n" +"change_auth <hierarchy> <new_pw> [<old_pw>]\n" +" <hierarchy>: the hierarchy\n" +" <new_pw>: new password for <hierarchy>\n" +" <old_pw>: optional previous password of <hierarchy>\n" +"pcr_setauthpolicy|pcr_setauthvalue <pcr> <key> [<password>]\n" +" Change the <key> to access PCR #<pcr>.\n" +" hierarchy and may be empty.\n" +" /!\\WARNING: untested function, use at your own risks !\n" +" <pcr>: index of the PCR\n" +" <key>: secret to protect the access of PCR #<pcr>\n" +" <password>: optional password of the PLATFORM hierarchy\n" +); diff --git a/cmd/tpm_test.c b/cmd/tpm_test.c index 2e7d133a47..35f3c96e3d 100644 --- a/cmd/tpm_test.c +++ b/cmd/tpm_test.c @@ -6,7 +6,7 @@ #include <common.h> #include <command.h> #include <environment.h> -#include <tpm.h> +#include <tpm-v1.h> /* Prints error and returns on failure */ #define TPM_CHECK(tpm_command) do { \ |