tpm: disociate TPMv1.x specific and generic code
authorMiquel Raynal <miquel.raynal@bootlin.com>
Tue, 15 May 2018 09:57:06 +0000 (11:57 +0200)
committerTom Rini <trini@konsulko.com>
Sat, 26 May 2018 00:12:55 +0000 (20:12 -0400)
There are no changes in this commit but a new organization of the code
as follow.

* cmd/ directory:
        > move existing code from cmd/tpm.c in cmd/tpm-common.c
> move specific code in cmd/tpm-v1.c
> create a specific header file with generic definitions for
  commands only called cmd/tpm-user-utils.h

* lib/ directory:
        > move existing code from lib/tpm.c in lib/tpm-common.c
> move specific code in lib/tpm-v1.c
> create a specific header file with generic definitions for
  the library itself called lib/tpm-utils.h

* include/ directory:
        > move existing code from include/tpm.h in include/tpm-common.h
> move specific code in include/tpm-v1.h

Code designated as 'common' is compiled if TPM are used. Code designated
as 'specific' is compiled only if the right specification has been
selected.

All files include tpm-common.h.
Files in cmd/ include tpm-user-utils.h.
Files in lib/ include tpm-utils.h.
Depending on the specification, files may include either (not both)
tpm-v1.h or tpm-v2.h.

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
Reviewed-by: Tom Rini <trini@konsulko.com>
[trini: Fix a few more cases of tpm.h -> tpm-v1.h, some Kconfig logic]
Signed-off-by: Tom Rini <trini@konsulko.com>
26 files changed:
board/gdsys/a38x/controlcenterdc.c
board/gdsys/a38x/hre.c
board/gdsys/a38x/keyprogram.c
board/gdsys/p1022/controlcenterd-id.c
cmd/Makefile
cmd/tpm-common.c [new file with mode: 0644]
cmd/tpm-user-utils.h [new file with mode: 0644]
cmd/tpm-v1.c [new file with mode: 0644]
cmd/tpm.c [deleted file]
cmd/tpm_test.c
drivers/tpm/Kconfig
drivers/tpm/tpm-uclass.c
drivers/tpm/tpm_atmel_twi.c
drivers/tpm/tpm_tis_infineon.c
drivers/tpm/tpm_tis_lpc.c
drivers/tpm/tpm_tis_sandbox.c
drivers/tpm/tpm_tis_st33zp24_i2c.c
drivers/tpm/tpm_tis_st33zp24_spi.c
include/tpm-common.h [new file with mode: 0644]
include/tpm-v1.h [new file with mode: 0644]
include/tpm.h [deleted file]
lib/Makefile
lib/tpm-common.c [new file with mode: 0644]
lib/tpm-utils.h [new file with mode: 0644]
lib/tpm-v1.c [new file with mode: 0644]
lib/tpm.c [deleted file]

index 320bc100c9dafba0f9db4267117e6a25e90f363d..824a08f12af83ca64b8e44dafa99488725a50c10 100644 (file)
@@ -7,7 +7,7 @@
 #include <common.h>
 #include <dm.h>
 #include <miiphy.h>
-#include <tpm.h>
+#include <tpm-v1.h>
 #include <asm/io.h>
 #include <asm/arch/cpu.h>
 #include <asm-generic/gpio.h>
index 961316cab7849f7e30613d7120afa2a3c93dd6e7..34c4df71b259aaad44c049f2789c0353792a4f27 100644 (file)
@@ -9,7 +9,7 @@
 #include <fs.h>
 #include <i2c.h>
 #include <mmc.h>
-#include <tpm.h>
+#include <tpm-v1.h>
 #include <u-boot/sha1.h>
 #include <asm/byteorder.h>
 #include <asm/unaligned.h>
index f6a2747fb25ec9855711d6260775a409f4dc98ec..1fb5306b50f6f402842cc502bf354748dd56e5dc 100644 (file)
@@ -5,7 +5,7 @@
  */
 
 #include <common.h>
-#include <tpm.h>
+#include <tpm-v1.h>
 #include <malloc.h>
 #include <linux/ctype.h>
 #include <asm/unaligned.h>
index 87edf92f43a8144757e579dd6368bb57995103fb..7e082dff0527865213c2a70e0560c495a500ef32 100644 (file)
@@ -15,7 +15,7 @@
 #include <fs.h>
 #include <i2c.h>
 #include <mmc.h>
-#include <tpm.h>
+#include <tpm-v1.h>
 #include <u-boot/sha1.h>
 #include <asm/byteorder.h>
 #include <asm/unaligned.h>
index ca6ead8e8e8a6341c0d6eee0a03ad97d4f5d9211..6164f6e611f8dff6096c64736a86e7db24a698e8 100644 (file)
@@ -120,7 +120,8 @@ 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_V1) += 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_CROS_EC) += cros_ec.o
 obj-$(CONFIG_CMD_TSI148) += tsi148.o
diff --git a/cmd/tpm-common.c b/cmd/tpm-common.c
new file mode 100644 (file)
index 0000000..6cf9fcc
--- /dev/null
@@ -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 (file)
index 0000000..8ce9861
--- /dev/null
@@ -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-v1.c b/cmd/tpm-v1.c
new file mode 100644 (file)
index 0000000..0874c4d
--- /dev/null
@@ -0,0 +1,723 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2013 The Chromium OS Authors.
+ */
+
+#include <common.h>
+#include <malloc.h>
+#include <asm/unaligned.h>
+#include <tpm-common.h>
+#include <tpm-v1.h>
+#include "tpm-user-utils.h"
+
+static int do_tpm_startup(cmd_tbl_t *cmdtp, int flag, int argc,
+                         char * const argv[])
+{
+       enum tpm_startup_type mode;
+
+       if (argc != 2)
+               return CMD_RET_USAGE;
+       if (!strcasecmp("TPM_ST_CLEAR", argv[1])) {
+               mode = TPM_ST_CLEAR;
+       } else if (!strcasecmp("TPM_ST_STATE", argv[1])) {
+               mode = TPM_ST_STATE;
+       } else if (!strcasecmp("TPM_ST_DEACTIVATED", argv[1])) {
+               mode = TPM_ST_DEACTIVATED;
+       } else {
+               printf("Couldn't recognize mode string: %s\n", argv[1]);
+               return CMD_RET_FAILURE;
+       }
+
+       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[])
+{
+       u32 index, perm, size;
+
+       if (argc != 4)
+               return CMD_RET_USAGE;
+       index = simple_strtoul(argv[1], NULL, 0);
+       perm = simple_strtoul(argv[2], NULL, 0);
+       size = simple_strtoul(argv[3], NULL, 0);
+
+       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[])
+{
+       u32 index, count, rc;
+       void *data;
+
+       if (argc != 4)
+               return CMD_RET_USAGE;
+       index = simple_strtoul(argv[1], NULL, 0);
+       data = (void *)simple_strtoul(argv[2], NULL, 0);
+       count = simple_strtoul(argv[3], NULL, 0);
+
+       rc = tpm_nv_read_value(index, data, count);
+       if (!rc) {
+               puts("area content:\n");
+               print_byte_string(data, count);
+       }
+
+       return report_return_code(rc);
+}
+
+static int do_tpm_nv_write_value(cmd_tbl_t *cmdtp, int flag, int argc,
+                                char * const argv[])
+{
+       u32 index, rc;
+       size_t count;
+       void *data;
+
+       if (argc != 3)
+               return CMD_RET_USAGE;
+       index = simple_strtoul(argv[1], NULL, 0);
+       data = parse_byte_string(argv[2], NULL, &count);
+       if (!data) {
+               printf("Couldn't parse byte string %s\n", argv[2]);
+               return CMD_RET_FAILURE;
+       }
+
+       rc = tpm_nv_write_value(index, data, count);
+       free(data);
+
+       return report_return_code(rc);
+}
+
+static int do_tpm_extend(cmd_tbl_t *cmdtp, int flag, int argc,
+                        char * const argv[])
+{
+       u32 index, rc;
+       u8 in_digest[20], out_digest[20];
+
+       if (argc != 3)
+               return CMD_RET_USAGE;
+       index = simple_strtoul(argv[1], NULL, 0);
+       if (!parse_byte_string(argv[2], in_digest, NULL)) {
+               printf("Couldn't parse byte string %s\n", argv[2]);
+               return CMD_RET_FAILURE;
+       }
+
+       rc = tpm_extend(index, in_digest, out_digest);
+       if (!rc) {
+               puts("PCR value after execution of the command:\n");
+               print_byte_string(out_digest, sizeof(out_digest));
+       }
+
+       return report_return_code(rc);
+}
+
+static int do_tpm_pcr_read(cmd_tbl_t *cmdtp, int flag, int argc,
+                          char * const argv[])
+{
+       u32 index, count, rc;
+       void *data;
+
+       if (argc != 4)
+               return CMD_RET_USAGE;
+       index = simple_strtoul(argv[1], NULL, 0);
+       data = (void *)simple_strtoul(argv[2], NULL, 0);
+       count = simple_strtoul(argv[3], NULL, 0);
+
+       rc = tpm_pcr_read(index, data, count);
+       if (!rc) {
+               puts("Named PCR content:\n");
+               print_byte_string(data, count);
+       }
+
+       return report_return_code(rc);
+}
+
+static int do_tpm_tsc_physical_presence(cmd_tbl_t *cmdtp, int flag, int argc,
+                                       char * const argv[])
+{
+       u16 presence;
+
+       if (argc != 2)
+               return CMD_RET_USAGE;
+       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[])
+{
+       u32 count, rc;
+       void *data;
+
+       if (argc != 3)
+               return CMD_RET_USAGE;
+       data = (void *)simple_strtoul(argv[1], NULL, 0);
+       count = simple_strtoul(argv[2], NULL, 0);
+
+       rc = tpm_read_pubek(data, count);
+       if (!rc) {
+               puts("pubek value:\n");
+               print_byte_string(data, count);
+       }
+
+       return report_return_code(rc);
+}
+
+static int do_tpm_physical_set_deactivated(cmd_tbl_t *cmdtp, int flag, int argc,
+                                          char * const argv[])
+{
+       u8 state;
+
+       if (argc != 2)
+               return CMD_RET_USAGE;
+       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[])
+{
+       u32 cap_area, sub_cap, rc;
+       void *cap;
+       size_t count;
+
+       if (argc != 5)
+               return CMD_RET_USAGE;
+       cap_area = simple_strtoul(argv[1], NULL, 0);
+       sub_cap = simple_strtoul(argv[2], NULL, 0);
+       cap = (void *)simple_strtoul(argv[3], NULL, 0);
+       count = simple_strtoul(argv[4], NULL, 0);
+
+       rc = tpm_get_capability(cap_area, sub_cap, cap, count);
+       if (!rc) {
+               puts("capability information:\n");
+               print_byte_string(cap, count);
+       }
+
+       return report_return_code(rc);
+}
+
+static int do_tpm_raw_transfer(cmd_tbl_t *cmdtp, int flag, int argc,
+                              char * const argv[])
+{
+       struct udevice *dev;
+       void *command;
+       u8 response[1024];
+       size_t count, response_length = sizeof(response);
+       u32 rc;
+
+       command = parse_byte_string(argv[1], NULL, &count);
+       if (!command) {
+               printf("Couldn't parse byte string %s\n", argv[1]);
+               return CMD_RET_FAILURE;
+       }
+
+       rc = get_tpm(&dev);
+       if (rc)
+               return rc;
+
+       rc = tpm_xfer(dev, command, count, response, &response_length);
+       free(command);
+       if (!rc) {
+               puts("tpm response:\n");
+               print_byte_string(response, response_length);
+       }
+
+       return report_return_code(rc);
+}
+
+static int do_tpm_nv_define(cmd_tbl_t *cmdtp, int flag, int argc,
+                           char * const argv[])
+{
+       u32 index, perm, size;
+
+       if (argc != 4)
+               return CMD_RET_USAGE;
+       size = type_string_get_space_size(argv[1]);
+       if (!size) {
+               printf("Couldn't parse arguments\n");
+               return CMD_RET_USAGE;
+       }
+       index = simple_strtoul(argv[2], NULL, 0);
+       perm = simple_strtoul(argv[3], NULL, 0);
+
+       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[])
+{
+       u32 index, count, err;
+       void *data;
+
+       if (argc < 3)
+               return CMD_RET_USAGE;
+       if (argc != 3 + type_string_get_num_values(argv[1]))
+               return CMD_RET_USAGE;
+       index = simple_strtoul(argv[2], NULL, 0);
+       data = type_string_alloc(argv[1], &count);
+       if (!data) {
+               printf("Couldn't parse arguments\n");
+               return CMD_RET_USAGE;
+       }
+
+       err = tpm_nv_read_value(index, data, count);
+       if (!err) {
+               if (type_string_write_vars(argv[1], data, argv + 3)) {
+                       printf("Couldn't write to variables\n");
+                       err = ~0;
+               }
+       }
+       free(data);
+
+       return report_return_code(err);
+}
+
+static int do_tpm_nv_write(cmd_tbl_t *cmdtp, int flag, int argc,
+                          char * const argv[])
+{
+       u32 index, count, err;
+       void *data;
+
+       if (argc < 3)
+               return CMD_RET_USAGE;
+       if (argc != 3 + type_string_get_num_values(argv[1]))
+               return CMD_RET_USAGE;
+       index = simple_strtoul(argv[2], NULL, 0);
+       data = type_string_alloc(argv[1], &count);
+       if (!data) {
+               printf("Couldn't parse arguments\n");
+               return CMD_RET_USAGE;
+       }
+       if (type_string_pack(argv[1], argv + 3, data)) {
+               printf("Couldn't parse arguments\n");
+               free(data);
+               return CMD_RET_USAGE;
+       }
+
+       err = tpm_nv_write_value(index, data, count);
+       free(data);
+
+       return report_return_code(err);
+}
+
+#ifdef CONFIG_TPM_AUTH_SESSIONS
+
+static int do_tpm_oiap(cmd_tbl_t *cmdtp, int flag, int argc,
+                      char * const argv[])
+{
+       u32 auth_handle, err;
+
+       err = tpm_oiap(&auth_handle);
+
+       return report_return_code(err);
+}
+
+#ifdef CONFIG_TPM_LOAD_KEY_BY_SHA1
+static int do_tpm_load_key_by_sha1(cmd_tbl_t *cmdtp, int flag, int argc, char *
+                                  const argv[])
+{
+       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)
+               return CMD_RET_USAGE;
+
+       parse_byte_string(argv[1], parent_hash, NULL);
+       key = (void *)simple_strtoul(argv[2], NULL, 0);
+       key_len = simple_strtoul(argv[3], NULL, 0);
+       if (strlen(argv[4]) != 2 * DIGEST_LENGTH)
+               return CMD_RET_FAILURE;
+       parse_byte_string(argv[4], usage_auth, NULL);
+
+       err = tpm_find_key_sha1(usage_auth, parent_hash, &parent_handle);
+       if (err) {
+               printf("Could not find matching parent key (err = %d)\n", err);
+               return CMD_RET_FAILURE;
+       }
+
+       printf("Found parent key %08x\n", parent_handle);
+
+       err = tpm_load_key2_oiap(parent_handle, key, key_len, usage_auth,
+                                &key_handle);
+       if (!err) {
+               printf("Key handle is 0x%x\n", key_handle);
+               env_set_hex("key_handle", key_handle);
+       }
+
+       return report_return_code(err);
+}
+#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[])
+{
+       u32 parent_handle, key_len, key_handle, err;
+       u8 usage_auth[DIGEST_LENGTH];
+       void *key;
+
+       if (argc < 5)
+               return CMD_RET_USAGE;
+
+       parent_handle = simple_strtoul(argv[1], NULL, 0);
+       key = (void *)simple_strtoul(argv[2], NULL, 0);
+       key_len = simple_strtoul(argv[3], NULL, 0);
+       if (strlen(argv[4]) != 2 * DIGEST_LENGTH)
+               return CMD_RET_FAILURE;
+       parse_byte_string(argv[4], usage_auth, NULL);
+
+       err = tpm_load_key2_oiap(parent_handle, key, key_len, usage_auth,
+                                &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[])
+{
+       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)
+               return CMD_RET_USAGE;
+
+       key_handle = simple_strtoul(argv[1], NULL, 0);
+       if (strlen(argv[2]) != 2 * DIGEST_LENGTH)
+               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);
+       if (!err) {
+               printf("dump of received pub key structure:\n");
+               print_byte_string(pub_key_buffer, pub_key_len);
+       }
+       return report_return_code(err);
+}
+
+TPM_COMMAND_NO_ARG(tpm_end_oiap)
+
+#endif /* CONFIG_TPM_AUTH_SESSIONS */
+
+#ifdef CONFIG_TPM_FLUSH_RESOURCES
+static int do_tpm_flush(cmd_tbl_t *cmdtp, int flag, int argc,
+                       char * const argv[])
+{
+       int type = 0;
+
+       if (argc != 3)
+               return CMD_RET_USAGE;
+
+       if (!strcasecmp(argv[1], "key"))
+               type = TPM_RT_KEY;
+       else if (!strcasecmp(argv[1], "auth"))
+               type = TPM_RT_AUTH;
+       else if (!strcasecmp(argv[1], "hash"))
+               type = TPM_RT_HASH;
+       else if (!strcasecmp(argv[1], "trans"))
+               type = TPM_RT_TRANS;
+       else if (!strcasecmp(argv[1], "context"))
+               type = TPM_RT_CONTEXT;
+       else if (!strcasecmp(argv[1], "counter"))
+               type = TPM_RT_COUNTER;
+       else if (!strcasecmp(argv[1], "delegate"))
+               type = TPM_RT_DELEGATE;
+       else if (!strcasecmp(argv[1], "daa_tpm"))
+               type = TPM_RT_DAA_TPM;
+       else if (!strcasecmp(argv[1], "daa_v0"))
+               type = TPM_RT_DAA_V0;
+       else if (!strcasecmp(argv[1], "daa_v1"))
+               type = TPM_RT_DAA_V1;
+
+       if (!type) {
+               printf("Resource type %s unknown.\n", argv[1]);
+               return -1;
+       }
+
+       if (!strcasecmp(argv[2], "all")) {
+               u16 res_count;
+               u8 buf[288];
+               u8 *ptr;
+               int err;
+               uint i;
+
+               /* fetch list of already loaded resources in the TPM */
+               err = tpm_get_capability(TPM_CAP_HANDLE, type, buf,
+                                        sizeof(buf));
+               if (err) {
+                       printf("tpm_get_capability returned error %d.\n", err);
+                       return -1;
+               }
+               res_count = get_unaligned_be16(buf);
+               ptr = buf + 2;
+               for (i = 0; i < res_count; ++i, ptr += 4)
+                       tpm_flush_specific(get_unaligned_be32(ptr), type);
+       } else {
+               u32 handle = simple_strtoul(argv[2], NULL, 0);
+
+               if (!handle) {
+                       printf("Illegal resource handle %s\n", argv[2]);
+                       return -1;
+               }
+               tpm_flush_specific(cpu_to_be32(handle), type);
+       }
+
+       return 0;
+}
+#endif /* CONFIG_TPM_FLUSH_RESOURCES */
+
+#ifdef CONFIG_TPM_LIST_RESOURCES
+static int do_tpm_list(cmd_tbl_t *cmdtp, int flag, int argc,
+                      char * const argv[])
+{
+       int type = 0;
+       u16 res_count;
+       u8 buf[288];
+       u8 *ptr;
+       int err;
+       uint i;
+
+       if (argc != 2)
+               return CMD_RET_USAGE;
+
+       if (!strcasecmp(argv[1], "key"))
+               type = TPM_RT_KEY;
+       else if (!strcasecmp(argv[1], "auth"))
+               type = TPM_RT_AUTH;
+       else if (!strcasecmp(argv[1], "hash"))
+               type = TPM_RT_HASH;
+       else if (!strcasecmp(argv[1], "trans"))
+               type = TPM_RT_TRANS;
+       else if (!strcasecmp(argv[1], "context"))
+               type = TPM_RT_CONTEXT;
+       else if (!strcasecmp(argv[1], "counter"))
+               type = TPM_RT_COUNTER;
+       else if (!strcasecmp(argv[1], "delegate"))
+               type = TPM_RT_DELEGATE;
+       else if (!strcasecmp(argv[1], "daa_tpm"))
+               type = TPM_RT_DAA_TPM;
+       else if (!strcasecmp(argv[1], "daa_v0"))
+               type = TPM_RT_DAA_V0;
+       else if (!strcasecmp(argv[1], "daa_v1"))
+               type = TPM_RT_DAA_V1;
+
+       if (!type) {
+               printf("Resource type %s unknown.\n", argv[1]);
+               return -1;
+       }
+
+       /* fetch list of already loaded resources in the TPM */
+       err = tpm_get_capability(TPM_CAP_HANDLE, type, buf,
+                                sizeof(buf));
+       if (err) {
+               printf("tpm_get_capability returned error %d.\n", err);
+               return -1;
+       }
+       res_count = get_unaligned_be16(buf);
+       ptr = buf + 2;
+
+       printf("Resources of type %s (%02x):\n", argv[1], type);
+       if (!res_count) {
+               puts("None\n");
+       } else {
+               for (i = 0; i < res_count; ++i, ptr += 4)
+                       printf("Index %d: %08x\n", i, get_unaligned_be32(ptr));
+       }
+
+       return 0;
+}
+#endif /* CONFIG_TPM_LIST_RESOURCES */
+
+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 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(startup, 0, 1,
+                        do_tpm_startup, "", ""),
+       U_BOOT_CMD_MKENT(self_test_full, 0, 1,
+                        do_tpm_self_test_full, "", ""),
+       U_BOOT_CMD_MKENT(continue_self_test, 0, 1,
+                        do_tpm_continue_self_test, "", ""),
+       U_BOOT_CMD_MKENT(force_clear, 0, 1,
+                        do_tpm_force_clear, "", ""),
+       U_BOOT_CMD_MKENT(physical_enable, 0, 1,
+                        do_tpm_physical_enable, "", ""),
+       U_BOOT_CMD_MKENT(physical_disable, 0, 1,
+                        do_tpm_physical_disable, "", ""),
+       U_BOOT_CMD_MKENT(nv_define_space, 0, 1,
+                        do_tpm_nv_define_space, "", ""),
+       U_BOOT_CMD_MKENT(nv_read_value, 0, 1,
+                        do_tpm_nv_read_value, "", ""),
+       U_BOOT_CMD_MKENT(nv_write_value, 0, 1,
+                        do_tpm_nv_write_value, "", ""),
+       U_BOOT_CMD_MKENT(extend, 0, 1,
+                        do_tpm_extend, "", ""),
+       U_BOOT_CMD_MKENT(pcr_read, 0, 1,
+                        do_tpm_pcr_read, "", ""),
+       U_BOOT_CMD_MKENT(tsc_physical_presence, 0, 1,
+                        do_tpm_tsc_physical_presence, "", ""),
+       U_BOOT_CMD_MKENT(read_pubek, 0, 1,
+                        do_tpm_read_pubek, "", ""),
+       U_BOOT_CMD_MKENT(physical_set_deactivated, 0, 1,
+                        do_tpm_physical_set_deactivated, "", ""),
+       U_BOOT_CMD_MKENT(get_capability, 0, 1,
+                        do_tpm_get_capability, "", ""),
+       U_BOOT_CMD_MKENT(raw_transfer, 0, 1,
+                        do_tpm_raw_transfer, "", ""),
+       U_BOOT_CMD_MKENT(nv_define, 0, 1,
+                        do_tpm_nv_define, "", ""),
+       U_BOOT_CMD_MKENT(nv_read, 0, 1,
+                        do_tpm_nv_read, "", ""),
+       U_BOOT_CMD_MKENT(nv_write, 0, 1,
+                        do_tpm_nv_write, "", ""),
+#ifdef CONFIG_TPM_AUTH_SESSIONS
+       U_BOOT_CMD_MKENT(oiap, 0, 1,
+                        do_tpm_oiap, "", ""),
+       U_BOOT_CMD_MKENT(end_oiap, 0, 1,
+                        do_tpm_end_oiap, "", ""),
+       U_BOOT_CMD_MKENT(load_key2_oiap, 0, 1,
+                        do_tpm_load_key2_oiap, "", ""),
+#ifdef CONFIG_TPM_LOAD_KEY_BY_SHA1
+       U_BOOT_CMD_MKENT(load_key_by_sha1, 0, 1,
+                        do_tpm_load_key_by_sha1, "", ""),
+#endif /* CONFIG_TPM_LOAD_KEY_BY_SHA1 */
+       U_BOOT_CMD_MKENT(get_pub_key_oiap, 0, 1,
+                        do_tpm_get_pub_key_oiap, "", ""),
+#endif /* CONFIG_TPM_AUTH_SESSIONS */
+#ifdef CONFIG_TPM_FLUSH_RESOURCES
+       U_BOOT_CMD_MKENT(flush, 0, 1,
+                        do_tpm_flush, "", ""),
+#endif /* CONFIG_TPM_FLUSH_RESOURCES */
+#ifdef CONFIG_TPM_LIST_RESOURCES
+       U_BOOT_CMD_MKENT(list, 0, 1,
+                        do_tpm_list, "", ""),
+#endif /* CONFIG_TPM_LIST_RESOURCES */
+};
+
+cmd_tbl_t *get_tpm_commands(unsigned int *size)
+{
+       *size = ARRAY_SIZE(tpm1_commands);
+
+       return tpm1_commands;
+}
+
+U_BOOT_CMD(tpm, CONFIG_SYS_MAXARGS, 1, do_tpm,
+"Issue a TPMv1.x command",
+"cmd args...\n"
+"    - Issue TPM command <cmd> with arguments <args...>.\n"
+"Admin Startup and State Commands:\n"
+"  info - Show information about the TPM\n"
+"  init\n"
+"    - Put TPM into a state where it waits for 'startup' command.\n"
+"  startup mode\n"
+"    - Issue TPM_Starup command.  <mode> is one of TPM_ST_CLEAR,\n"
+"      TPM_ST_STATE, and TPM_ST_DEACTIVATED.\n"
+"Admin Testing Commands:\n"
+"  self_test_full\n"
+"    - Test all of the TPM capabilities.\n"
+"  continue_self_test\n"
+"    - Inform TPM that it should complete the self-test.\n"
+"Admin Opt-in Commands:\n"
+"  physical_enable\n"
+"    - Set the PERMANENT disable flag to FALSE using physical presence as\n"
+"      authorization.\n"
+"  physical_disable\n"
+"    - Set the PERMANENT disable flag to TRUE using physical presence as\n"
+"      authorization.\n"
+"  physical_set_deactivated 0|1\n"
+"    - Set deactivated flag.\n"
+"Admin Ownership Commands:\n"
+"  force_clear\n"
+"    - Issue TPM_ForceClear command.\n"
+"  tsc_physical_presence flags\n"
+"    - Set TPM device's Physical Presence flags to <flags>.\n"
+"The Capability Commands:\n"
+"  get_capability cap_area sub_cap addr count\n"
+"    - Read <count> bytes of TPM capability indexed by <cap_area> and\n"
+"      <sub_cap> to memory address <addr>.\n"
+#if defined(CONFIG_TPM_FLUSH_RESOURCES) || defined(CONFIG_TPM_LIST_RESOURCES)
+"Resource management functions\n"
+#endif
+#ifdef CONFIG_TPM_FLUSH_RESOURCES
+"  flush resource_type id\n"
+"    - flushes a resource of type <resource_type> (may be one of key, auth,\n"
+"      hash, trans, context, counter, delegate, daa_tpm, daa_v0, daa_v1),\n"
+"      and id <id> from the TPM. Use an <id> of \"all\" to flush all\n"
+"      resources of that type.\n"
+#endif /* CONFIG_TPM_FLUSH_RESOURCES */
+#ifdef CONFIG_TPM_LIST_RESOURCES
+"  list resource_type\n"
+"    - lists resources of type <resource_type> (may be one of key, auth,\n"
+"      hash, trans, context, counter, delegate, daa_tpm, daa_v0, daa_v1),\n"
+"      contained in the TPM.\n"
+#endif /* CONFIG_TPM_LIST_RESOURCES */
+#ifdef CONFIG_TPM_AUTH_SESSIONS
+"Storage functions\n"
+"  loadkey2_oiap parent_handle key_addr key_len usage_auth\n"
+"    - loads a key data from memory address <key_addr>, <key_len> bytes\n"
+"      into TPM using the parent key <parent_handle> with authorization\n"
+"      <usage_auth> (20 bytes hex string).\n"
+#ifdef CONFIG_TPM_LOAD_KEY_BY_SHA1
+"  load_key_by_sha1 parent_hash key_addr key_len usage_auth\n"
+"    - loads a key data from memory address <key_addr>, <key_len> bytes\n"
+"      into TPM using the parent hash <parent_hash> (20 bytes hex string)\n"
+"      with authorization <usage_auth> (20 bytes hex string).\n"
+#endif /* CONFIG_TPM_LOAD_KEY_BY_SHA1 */
+"  get_pub_key_oiap key_handle usage_auth\n"
+"    - get the public key portion of a loaded key <key_handle> using\n"
+"      authorization <usage auth> (20 bytes hex string)\n"
+#endif /* CONFIG_TPM_AUTH_SESSIONS */
+"Endorsement Key Handling Commands:\n"
+"  read_pubek addr count\n"
+"    - Read <count> bytes of the public endorsement key to memory\n"
+"      address <addr>\n"
+"Integrity Collection and Reporting Commands:\n"
+"  extend index digest_hex_string\n"
+"    - Add a new measurement to a PCR.  Update PCR <index> with the 20-bytes\n"
+"      <digest_hex_string>\n"
+"  pcr_read index addr count\n"
+"    - Read <count> bytes from PCR <index> to memory address <addr>.\n"
+#ifdef CONFIG_TPM_AUTH_SESSIONS
+"Authorization Sessions\n"
+"  oiap\n"
+"    - setup an OIAP session\n"
+"  end_oiap\n"
+"    - terminates an active OIAP session\n"
+#endif /* CONFIG_TPM_AUTH_SESSIONS */
+"Non-volatile Storage Commands:\n"
+"  nv_define_space index permission size\n"
+"    - Establish a space at index <index> with <permission> of <size> bytes.\n"
+"  nv_read_value index addr count\n"
+"    - Read <count> bytes from space <index> to memory address <addr>.\n"
+"  nv_write_value index addr count\n"
+"    - Write <count> bytes from memory address <addr> to space <index>.\n"
+"Miscellaneous helper functions:\n"
+"  raw_transfer byte_string\n"
+"    - Send a byte string <byte_string> to TPM and print the response.\n"
+" Non-volatile storage helper functions:\n"
+"    These helper functions treat a non-volatile space as a non-padded\n"
+"    sequence of integer values.  These integer values are defined by a type\n"
+"    string, which is a text string of 'bwd' characters: 'b' means a 8-bit\n"
+"    value, 'w' 16-bit value, 'd' 32-bit value.  All helper functions take\n"
+"    a type string as their first argument.\n"
+"  nv_define type_string index perm\n"
+"    - Define a space <index> with permission <perm>.\n"
+"  nv_read types_string index vars...\n"
+"    - Read from space <index> to environment variables <vars...>.\n"
+"  nv_write types_string index values...\n"
+"    - Write to space <index> from values <values...>.\n"
+);
diff --git a/cmd/tpm.c b/cmd/tpm.c
deleted file mode 100644 (file)
index e0cd841..0000000
--- a/cmd/tpm.c
+++ /dev/null
@@ -1,1001 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Copyright (c) 2013 The Chromium OS Authors.
- */
-
-#include <common.h>
-#include <command.h>
-#include <dm.h>
-#include <malloc.h>
-#include <tpm.h>
-#include <asm/unaligned.h>
-#include <linux/string.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(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
- */
-static 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
- */
-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, 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
- */
-static 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
- */
-static 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;
-}
-
-static int do_tpm_startup(cmd_tbl_t *cmdtp, int flag, int argc,
-                         char * const argv[])
-{
-       enum tpm_startup_type mode;
-
-       if (argc != 2)
-               return CMD_RET_USAGE;
-       if (!strcasecmp("TPM_ST_CLEAR", argv[1])) {
-               mode = TPM_ST_CLEAR;
-       } else if (!strcasecmp("TPM_ST_STATE", argv[1])) {
-               mode = TPM_ST_STATE;
-       } else if (!strcasecmp("TPM_ST_DEACTIVATED", argv[1])) {
-               mode = TPM_ST_DEACTIVATED;
-       } else {
-               printf("Couldn't recognize mode string: %s\n", argv[1]);
-               return CMD_RET_FAILURE;
-       }
-
-       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[])
-{
-       u32 index, perm, size;
-
-       if (argc != 4)
-               return CMD_RET_USAGE;
-       index = simple_strtoul(argv[1], NULL, 0);
-       perm = simple_strtoul(argv[2], NULL, 0);
-       size = simple_strtoul(argv[3], NULL, 0);
-
-       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[])
-{
-       u32 index, count, rc;
-       void *data;
-
-       if (argc != 4)
-               return CMD_RET_USAGE;
-       index = simple_strtoul(argv[1], NULL, 0);
-       data = (void *)simple_strtoul(argv[2], NULL, 0);
-       count = simple_strtoul(argv[3], NULL, 0);
-
-       rc = tpm_nv_read_value(index, data, count);
-       if (!rc) {
-               puts("area content:\n");
-               print_byte_string(data, count);
-       }
-
-       return report_return_code(rc);
-}
-
-static int do_tpm_nv_write_value(cmd_tbl_t *cmdtp, int flag, int argc,
-                                char * const argv[])
-{
-       u32 index, rc;
-       size_t count;
-       void *data;
-
-       if (argc != 3)
-               return CMD_RET_USAGE;
-       index = simple_strtoul(argv[1], NULL, 0);
-       data = parse_byte_string(argv[2], NULL, &count);
-       if (!data) {
-               printf("Couldn't parse byte string %s\n", argv[2]);
-               return CMD_RET_FAILURE;
-       }
-
-       rc = tpm_nv_write_value(index, data, count);
-       free(data);
-
-       return report_return_code(rc);
-}
-
-static int do_tpm_extend(cmd_tbl_t *cmdtp, int flag, int argc,
-                        char * const argv[])
-{
-       u32 index, rc;
-       u8 in_digest[20], out_digest[20];
-
-       if (argc != 3)
-               return CMD_RET_USAGE;
-       index = simple_strtoul(argv[1], NULL, 0);
-       if (!parse_byte_string(argv[2], in_digest, NULL)) {
-               printf("Couldn't parse byte string %s\n", argv[2]);
-               return CMD_RET_FAILURE;
-       }
-
-       rc = tpm_extend(index, in_digest, out_digest);
-       if (!rc) {
-               puts("PCR value after execution of the command:\n");
-               print_byte_string(out_digest, sizeof(out_digest));
-       }
-
-       return report_return_code(rc);
-}
-
-static int do_tpm_pcr_read(cmd_tbl_t *cmdtp, int flag, int argc,
-                          char * const argv[])
-{
-       u32 index, count, rc;
-       void *data;
-
-       if (argc != 4)
-               return CMD_RET_USAGE;
-       index = simple_strtoul(argv[1], NULL, 0);
-       data = (void *)simple_strtoul(argv[2], NULL, 0);
-       count = simple_strtoul(argv[3], NULL, 0);
-
-       rc = tpm_pcr_read(index, data, count);
-       if (!rc) {
-               puts("Named PCR content:\n");
-               print_byte_string(data, count);
-       }
-
-       return report_return_code(rc);
-}
-
-static int do_tpm_tsc_physical_presence(cmd_tbl_t *cmdtp, int flag, int argc,
-                                       char * const argv[])
-{
-       u16 presence;
-
-       if (argc != 2)
-               return CMD_RET_USAGE;
-       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[])
-{
-       u32 count, rc;
-       void *data;
-
-       if (argc != 3)
-               return CMD_RET_USAGE;
-       data = (void *)simple_strtoul(argv[1], NULL, 0);
-       count = simple_strtoul(argv[2], NULL, 0);
-
-       rc = tpm_read_pubek(data, count);
-       if (!rc) {
-               puts("pubek value:\n");
-               print_byte_string(data, count);
-       }
-
-       return report_return_code(rc);
-}
-
-static int do_tpm_physical_set_deactivated(cmd_tbl_t *cmdtp, int flag, int argc,
-                                          char * const argv[])
-{
-       u8 state;
-
-       if (argc != 2)
-               return CMD_RET_USAGE;
-       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[])
-{
-       u32 cap_area, sub_cap, rc;
-       void *cap;
-       size_t count;
-
-       if (argc != 5)
-               return CMD_RET_USAGE;
-       cap_area = simple_strtoul(argv[1], NULL, 0);
-       sub_cap = simple_strtoul(argv[2], NULL, 0);
-       cap = (void *)simple_strtoul(argv[3], NULL, 0);
-       count = simple_strtoul(argv[4], NULL, 0);
-
-       rc = tpm_get_capability(cap_area, sub_cap, cap, count);
-       if (!rc) {
-               puts("capability information:\n");
-               print_byte_string(cap, count);
-       }
-
-       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[])
-{
-       struct udevice *dev;
-       void *command;
-       u8 response[1024];
-       size_t count, response_length = sizeof(response);
-       u32 rc;
-
-       command = parse_byte_string(argv[1], NULL, &count);
-       if (!command) {
-               printf("Couldn't parse byte string %s\n", argv[1]);
-               return CMD_RET_FAILURE;
-       }
-
-       rc = get_tpm(&dev);
-       if (rc)
-               return rc;
-
-       rc = tpm_xfer(dev, command, count, response, &response_length);
-       free(command);
-       if (!rc) {
-               puts("tpm response:\n");
-               print_byte_string(response, response_length);
-       }
-
-       return report_return_code(rc);
-}
-
-static int do_tpm_nv_define(cmd_tbl_t *cmdtp, int flag, int argc,
-                           char * const argv[])
-{
-       u32 index, perm, size;
-
-       if (argc != 4)
-               return CMD_RET_USAGE;
-       size = type_string_get_space_size(argv[1]);
-       if (!size) {
-               printf("Couldn't parse arguments\n");
-               return CMD_RET_USAGE;
-       }
-       index = simple_strtoul(argv[2], NULL, 0);
-       perm = simple_strtoul(argv[3], NULL, 0);
-
-       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[])
-{
-       u32 index, count, err;
-       void *data;
-
-       if (argc < 3)
-               return CMD_RET_USAGE;
-       if (argc != 3 + type_string_get_num_values(argv[1]))
-               return CMD_RET_USAGE;
-       index = simple_strtoul(argv[2], NULL, 0);
-       data = type_string_alloc(argv[1], &count);
-       if (!data) {
-               printf("Couldn't parse arguments\n");
-               return CMD_RET_USAGE;
-       }
-
-       err = tpm_nv_read_value(index, data, count);
-       if (!err) {
-               if (type_string_write_vars(argv[1], data, argv + 3)) {
-                       printf("Couldn't write to variables\n");
-                       err = ~0;
-               }
-       }
-       free(data);
-
-       return report_return_code(err);
-}
-
-static int do_tpm_nv_write(cmd_tbl_t *cmdtp, int flag, int argc,
-                          char * const argv[])
-{
-       u32 index, count, err;
-       void *data;
-
-       if (argc < 3)
-               return CMD_RET_USAGE;
-       if (argc != 3 + type_string_get_num_values(argv[1]))
-               return CMD_RET_USAGE;
-       index = simple_strtoul(argv[2], NULL, 0);
-       data = type_string_alloc(argv[1], &count);
-       if (!data) {
-               printf("Couldn't parse arguments\n");
-               return CMD_RET_USAGE;
-       }
-       if (type_string_pack(argv[1], argv + 3, data)) {
-               printf("Couldn't parse arguments\n");
-               free(data);
-               return CMD_RET_USAGE;
-       }
-
-       err = tpm_nv_write_value(index, data, count);
-       free(data);
-
-       return report_return_code(err);
-}
-
-#ifdef CONFIG_TPM_AUTH_SESSIONS
-
-static int do_tpm_oiap(cmd_tbl_t *cmdtp, int flag, int argc,
-                      char * const argv[])
-{
-       u32 auth_handle, err;
-
-       err = tpm_oiap(&auth_handle);
-
-       return report_return_code(err);
-}
-
-#ifdef CONFIG_TPM_LOAD_KEY_BY_SHA1
-static int do_tpm_load_key_by_sha1(cmd_tbl_t *cmdtp, int flag, int argc, char *
-                                  const argv[])
-{
-       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)
-               return CMD_RET_USAGE;
-
-       parse_byte_string(argv[1], parent_hash, NULL);
-       key = (void *)simple_strtoul(argv[2], NULL, 0);
-       key_len = simple_strtoul(argv[3], NULL, 0);
-       if (strlen(argv[4]) != 2 * DIGEST_LENGTH)
-               return CMD_RET_FAILURE;
-       parse_byte_string(argv[4], usage_auth, NULL);
-
-       err = tpm_find_key_sha1(usage_auth, parent_hash, &parent_handle);
-       if (err) {
-               printf("Could not find matching parent key (err = %d)\n", err);
-               return CMD_RET_FAILURE;
-       }
-
-       printf("Found parent key %08x\n", parent_handle);
-
-       err = tpm_load_key2_oiap(parent_handle, key, key_len, usage_auth,
-                                &key_handle);
-       if (!err) {
-               printf("Key handle is 0x%x\n", key_handle);
-               env_set_hex("key_handle", key_handle);
-       }
-
-       return report_return_code(err);
-}
-#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[])
-{
-       u32 parent_handle, key_len, key_handle, err;
-       u8 usage_auth[DIGEST_LENGTH];
-       void *key;
-
-       if (argc < 5)
-               return CMD_RET_USAGE;
-
-       parent_handle = simple_strtoul(argv[1], NULL, 0);
-       key = (void *)simple_strtoul(argv[2], NULL, 0);
-       key_len = simple_strtoul(argv[3], NULL, 0);
-       if (strlen(argv[4]) != 2 * DIGEST_LENGTH)
-               return CMD_RET_FAILURE;
-       parse_byte_string(argv[4], usage_auth, NULL);
-
-       err = tpm_load_key2_oiap(parent_handle, key, key_len, usage_auth,
-                                &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[])
-{
-       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)
-               return CMD_RET_USAGE;
-
-       key_handle = simple_strtoul(argv[1], NULL, 0);
-       if (strlen(argv[2]) != 2 * DIGEST_LENGTH)
-               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);
-       if (!err) {
-               printf("dump of received pub key structure:\n");
-               print_byte_string(pub_key_buffer, pub_key_len);
-       }
-       return report_return_code(err);
-}
-
-TPM_COMMAND_NO_ARG(tpm_end_oiap)
-
-#endif /* CONFIG_TPM_AUTH_SESSIONS */
-
-#ifdef CONFIG_TPM_FLUSH_RESOURCES
-static int do_tpm_flush(cmd_tbl_t *cmdtp, int flag, int argc,
-                       char * const argv[])
-{
-       int type = 0;
-
-       if (argc != 3)
-               return CMD_RET_USAGE;
-
-       if (!strcasecmp(argv[1], "key"))
-               type = TPM_RT_KEY;
-       else if (!strcasecmp(argv[1], "auth"))
-               type = TPM_RT_AUTH;
-       else if (!strcasecmp(argv[1], "hash"))
-               type = TPM_RT_HASH;
-       else if (!strcasecmp(argv[1], "trans"))
-               type = TPM_RT_TRANS;
-       else if (!strcasecmp(argv[1], "context"))
-               type = TPM_RT_CONTEXT;
-       else if (!strcasecmp(argv[1], "counter"))
-               type = TPM_RT_COUNTER;
-       else if (!strcasecmp(argv[1], "delegate"))
-               type = TPM_RT_DELEGATE;
-       else if (!strcasecmp(argv[1], "daa_tpm"))
-               type = TPM_RT_DAA_TPM;
-       else if (!strcasecmp(argv[1], "daa_v0"))
-               type = TPM_RT_DAA_V0;
-       else if (!strcasecmp(argv[1], "daa_v1"))
-               type = TPM_RT_DAA_V1;
-
-       if (!type) {
-               printf("Resource type %s unknown.\n", argv[1]);
-               return -1;
-       }
-
-       if (!strcasecmp(argv[2], "all")) {
-               u16 res_count;
-               u8 buf[288];
-               u8 *ptr;
-               int err;
-               uint i;
-
-               /* fetch list of already loaded resources in the TPM */
-               err = tpm_get_capability(TPM_CAP_HANDLE, type, buf,
-                                        sizeof(buf));
-               if (err) {
-                       printf("tpm_get_capability returned error %d.\n", err);
-                       return -1;
-               }
-               res_count = get_unaligned_be16(buf);
-               ptr = buf + 2;
-               for (i = 0; i < res_count; ++i, ptr += 4)
-                       tpm_flush_specific(get_unaligned_be32(ptr), type);
-       } else {
-               u32 handle = simple_strtoul(argv[2], NULL, 0);
-
-               if (!handle) {
-                       printf("Illegal resource handle %s\n", argv[2]);
-                       return -1;
-               }
-               tpm_flush_specific(cpu_to_be32(handle), type);
-       }
-
-       return 0;
-}
-#endif /* CONFIG_TPM_FLUSH_RESOURCES */
-
-#ifdef CONFIG_TPM_LIST_RESOURCES
-static int do_tpm_list(cmd_tbl_t *cmdtp, int flag, int argc,
-                      char * const argv[])
-{
-       int type = 0;
-       u16 res_count;
-       u8 buf[288];
-       u8 *ptr;
-       int err;
-       uint i;
-
-       if (argc != 2)
-               return CMD_RET_USAGE;
-
-       if (!strcasecmp(argv[1], "key"))
-               type = TPM_RT_KEY;
-       else if (!strcasecmp(argv[1], "auth"))
-               type = TPM_RT_AUTH;
-       else if (!strcasecmp(argv[1], "hash"))
-               type = TPM_RT_HASH;
-       else if (!strcasecmp(argv[1], "trans"))
-               type = TPM_RT_TRANS;
-       else if (!strcasecmp(argv[1], "context"))
-               type = TPM_RT_CONTEXT;
-       else if (!strcasecmp(argv[1], "counter"))
-               type = TPM_RT_COUNTER;
-       else if (!strcasecmp(argv[1], "delegate"))
-               type = TPM_RT_DELEGATE;
-       else if (!strcasecmp(argv[1], "daa_tpm"))
-               type = TPM_RT_DAA_TPM;
-       else if (!strcasecmp(argv[1], "daa_v0"))
-               type = TPM_RT_DAA_V0;
-       else if (!strcasecmp(argv[1], "daa_v1"))
-               type = TPM_RT_DAA_V1;
-
-       if (!type) {
-               printf("Resource type %s unknown.\n", argv[1]);
-               return -1;
-       }
-
-       /* fetch list of already loaded resources in the TPM */
-       err = tpm_get_capability(TPM_CAP_HANDLE, type, buf,
-                                sizeof(buf));
-       if (err) {
-               printf("tpm_get_capability returned error %d.\n", err);
-               return -1;
-       }
-       res_count = get_unaligned_be16(buf);
-       ptr = buf + 2;
-
-       printf("Resources of type %s (%02x):\n", argv[1], type);
-       if (!res_count) {
-               puts("None\n");
-       } else {
-               for (i = 0; i < res_count; ++i, ptr += 4)
-                       printf("Index %d: %08x\n", i, get_unaligned_be32(ptr));
-       }
-
-       return 0;
-}
-#endif /* CONFIG_TPM_LIST_RESOURCES */
-
-#define MAKE_TPM_CMD_ENTRY(cmd) \
-       U_BOOT_CMD_MKENT(cmd, 0, 1, do_tpm_ ## cmd, "", "")
-
-static cmd_tbl_t tpm_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_tpm_startup, "", ""),
-       U_BOOT_CMD_MKENT(self_test_full, 0, 1,
-                        do_tpm_self_test_full, "", ""),
-       U_BOOT_CMD_MKENT(continue_self_test, 0, 1,
-                        do_tpm_continue_self_test, "", ""),
-       U_BOOT_CMD_MKENT(force_clear, 0, 1,
-                        do_tpm_force_clear, "", ""),
-       U_BOOT_CMD_MKENT(physical_enable, 0, 1,
-                        do_tpm_physical_enable, "", ""),
-       U_BOOT_CMD_MKENT(physical_disable, 0, 1,
-                        do_tpm_physical_disable, "", ""),
-       U_BOOT_CMD_MKENT(nv_define_space, 0, 1,
-                        do_tpm_nv_define_space, "", ""),
-       U_BOOT_CMD_MKENT(nv_read_value, 0, 1,
-                        do_tpm_nv_read_value, "", ""),
-       U_BOOT_CMD_MKENT(nv_write_value, 0, 1,
-                        do_tpm_nv_write_value, "", ""),
-       U_BOOT_CMD_MKENT(extend, 0, 1,
-                        do_tpm_extend, "", ""),
-       U_BOOT_CMD_MKENT(pcr_read, 0, 1,
-                        do_tpm_pcr_read, "", ""),
-       U_BOOT_CMD_MKENT(tsc_physical_presence, 0, 1,
-                        do_tpm_tsc_physical_presence, "", ""),
-       U_BOOT_CMD_MKENT(read_pubek, 0, 1,
-                        do_tpm_read_pubek, "", ""),
-       U_BOOT_CMD_MKENT(physical_set_deactivated, 0, 1,
-                        do_tpm_physical_set_deactivated, "", ""),
-       U_BOOT_CMD_MKENT(get_capability, 0, 1,
-                        do_tpm_get_capability, "", ""),
-       U_BOOT_CMD_MKENT(raw_transfer, 0, 1,
-                        do_tpm_raw_transfer, "", ""),
-       U_BOOT_CMD_MKENT(nv_define, 0, 1,
-                        do_tpm_nv_define, "", ""),
-       U_BOOT_CMD_MKENT(nv_read, 0, 1,
-                        do_tpm_nv_read, "", ""),
-       U_BOOT_CMD_MKENT(nv_write, 0, 1,
-                        do_tpm_nv_write, "", ""),
-#ifdef CONFIG_TPM_AUTH_SESSIONS
-       U_BOOT_CMD_MKENT(oiap, 0, 1,
-                        do_tpm_oiap, "", ""),
-       U_BOOT_CMD_MKENT(end_oiap, 0, 1,
-                        do_tpm_end_oiap, "", ""),
-       U_BOOT_CMD_MKENT(load_key2_oiap, 0, 1,
-                        do_tpm_load_key2_oiap, "", ""),
-#ifdef CONFIG_TPM_LOAD_KEY_BY_SHA1
-       U_BOOT_CMD_MKENT(load_key_by_sha1, 0, 1,
-                        do_tpm_load_key_by_sha1, "", ""),
-#endif /* CONFIG_TPM_LOAD_KEY_BY_SHA1 */
-       U_BOOT_CMD_MKENT(get_pub_key_oiap, 0, 1,
-                        do_tpm_get_pub_key_oiap, "", ""),
-#endif /* CONFIG_TPM_AUTH_SESSIONS */
-#ifdef CONFIG_TPM_FLUSH_RESOURCES
-       U_BOOT_CMD_MKENT(flush, 0, 1,
-                        do_tpm_flush, "", ""),
-#endif /* CONFIG_TPM_FLUSH_RESOURCES */
-#ifdef CONFIG_TPM_LIST_RESOURCES
-       U_BOOT_CMD_MKENT(list, 0, 1,
-                        do_tpm_list, "", ""),
-#endif /* CONFIG_TPM_LIST_RESOURCES */
-};
-
-static int do_tpm(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
-{
-       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;
-
-       return tpm_cmd->cmd(cmdtp, flag, argc - 1, argv + 1);
-}
-
-U_BOOT_CMD(tpm, CONFIG_SYS_MAXARGS, 1, do_tpm,
-"Issue a TPM command",
-"cmd args...\n"
-"    - Issue TPM command <cmd> with arguments <args...>.\n"
-"Admin Startup and State Commands:\n"
-"  info - Show information about the TPM\n"
-"  init\n"
-"    - Put TPM into a state where it waits for 'startup' command.\n"
-"  startup mode\n"
-"    - Issue TPM_Starup command.  <mode> is one of TPM_ST_CLEAR,\n"
-"      TPM_ST_STATE, and TPM_ST_DEACTIVATED.\n"
-"Admin Testing Commands:\n"
-"  self_test_full\n"
-"    - Test all of the TPM capabilities.\n"
-"  continue_self_test\n"
-"    - Inform TPM that it should complete the self-test.\n"
-"Admin Opt-in Commands:\n"
-"  physical_enable\n"
-"    - Set the PERMANENT disable flag to FALSE using physical presence as\n"
-"      authorization.\n"
-"  physical_disable\n"
-"    - Set the PERMANENT disable flag to TRUE using physical presence as\n"
-"      authorization.\n"
-"  physical_set_deactivated 0|1\n"
-"    - Set deactivated flag.\n"
-"Admin Ownership Commands:\n"
-"  force_clear\n"
-"    - Issue TPM_ForceClear command.\n"
-"  tsc_physical_presence flags\n"
-"    - Set TPM device's Physical Presence flags to <flags>.\n"
-"The Capability Commands:\n"
-"  get_capability cap_area sub_cap addr count\n"
-"    - Read <count> bytes of TPM capability indexed by <cap_area> and\n"
-"      <sub_cap> to memory address <addr>.\n"
-#if defined(CONFIG_TPM_FLUSH_RESOURCES) || defined(CONFIG_TPM_LIST_RESOURCES)
-"Resource management functions\n"
-#endif
-#ifdef CONFIG_TPM_FLUSH_RESOURCES
-"  flush resource_type id\n"
-"    - flushes a resource of type <resource_type> (may be one of key, auth,\n"
-"      hash, trans, context, counter, delegate, daa_tpm, daa_v0, daa_v1),\n"
-"      and id <id> from the TPM. Use an <id> of \"all\" to flush all\n"
-"      resources of that type.\n"
-#endif /* CONFIG_TPM_FLUSH_RESOURCES */
-#ifdef CONFIG_TPM_LIST_RESOURCES
-"  list resource_type\n"
-"    - lists resources of type <resource_type> (may be one of key, auth,\n"
-"      hash, trans, context, counter, delegate, daa_tpm, daa_v0, daa_v1),\n"
-"      contained in the TPM.\n"
-#endif /* CONFIG_TPM_LIST_RESOURCES */
-#ifdef CONFIG_TPM_AUTH_SESSIONS
-"Storage functions\n"
-"  loadkey2_oiap parent_handle key_addr key_len usage_auth\n"
-"    - loads a key data from memory address <key_addr>, <key_len> bytes\n"
-"      into TPM using the parent key <parent_handle> with authorization\n"
-"      <usage_auth> (20 bytes hex string).\n"
-#ifdef CONFIG_TPM_LOAD_KEY_BY_SHA1
-"  load_key_by_sha1 parent_hash key_addr key_len usage_auth\n"
-"    - loads a key data from memory address <key_addr>, <key_len> bytes\n"
-"      into TPM using the parent hash <parent_hash> (20 bytes hex string)\n"
-"      with authorization <usage_auth> (20 bytes hex string).\n"
-#endif /* CONFIG_TPM_LOAD_KEY_BY_SHA1 */
-"  get_pub_key_oiap key_handle usage_auth\n"
-"    - get the public key portion of a loaded key <key_handle> using\n"
-"      authorization <usage auth> (20 bytes hex string)\n"
-#endif /* CONFIG_TPM_AUTH_SESSIONS */
-"Endorsement Key Handling Commands:\n"
-"  read_pubek addr count\n"
-"    - Read <count> bytes of the public endorsement key to memory\n"
-"      address <addr>\n"
-"Integrity Collection and Reporting Commands:\n"
-"  extend index digest_hex_string\n"
-"    - Add a new measurement to a PCR.  Update PCR <index> with the 20-bytes\n"
-"      <digest_hex_string>\n"
-"  pcr_read index addr count\n"
-"    - Read <count> bytes from PCR <index> to memory address <addr>.\n"
-#ifdef CONFIG_TPM_AUTH_SESSIONS
-"Authorization Sessions\n"
-"  oiap\n"
-"    - setup an OIAP session\n"
-"  end_oiap\n"
-"    - terminates an active OIAP session\n"
-#endif /* CONFIG_TPM_AUTH_SESSIONS */
-"Non-volatile Storage Commands:\n"
-"  nv_define_space index permission size\n"
-"    - Establish a space at index <index> with <permission> of <size> bytes.\n"
-"  nv_read_value index addr count\n"
-"    - Read <count> bytes from space <index> to memory address <addr>.\n"
-"  nv_write_value index addr count\n"
-"    - Write <count> bytes from memory address <addr> to space <index>.\n"
-"Miscellaneous helper functions:\n"
-"  raw_transfer byte_string\n"
-"    - Send a byte string <byte_string> to TPM and print the response.\n"
-" Non-volatile storage helper functions:\n"
-"    These helper functions treat a non-volatile space as a non-padded\n"
-"    sequence of integer values.  These integer values are defined by a type\n"
-"    string, which is a text string of 'bwd' characters: 'b' means a 8-bit\n"
-"    value, 'w' 16-bit value, 'd' 32-bit value.  All helper functions take\n"
-"    a type string as their first argument.\n"
-"  nv_define type_string index perm\n"
-"    - Define a space <index> with permission <perm>.\n"
-"  nv_read types_string index vars...\n"
-"    - Read from space <index> to environment variables <vars...>.\n"
-"  nv_write types_string index values...\n"
-"    - Write to space <index> from values <values...>.\n"
-);
index 2e7d133a47e75ac805d184884f44252334be1d82..35f3c96e3de7c38d4034433cf213ea4903cca116 100644 (file)
@@ -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 { \
index 53c34612df0aa692279f2cb9982e3a084c13db45..bc11f61e91f63fa207e0df01560346e172fbac1a 100644 (file)
@@ -46,7 +46,7 @@ config TPM_TIS_INFINEON
 
 config TPM_TIS_I2C_BURST_LIMITATION
        bool "Enable I2C burst length limitation"
-       depends on TPM_V1 && TPM_TIS_INFINEON
+       depends on TPM_TIS_INFINEON
        help
          Some broken TPMs have a limitation on the number of bytes they can
          receive in one message. Enable this option to allow you to set this
@@ -62,6 +62,7 @@ config TPM_TIS_I2C_BURST_LIMITATION_LEN
 config TPM_TIS_LPC
        bool "Enable support for Infineon SLB9635/45 TPMs on LPC"
        depends on TPM_V1 && X86
+       select TPM_DRIVER_SELECTED
        help
          This driver supports Infineon TPM devices connected on the LPC bus.
          The usual tpm operations and the 'tpm' command can be used to talk
index e71545235cff29e1b1ea1930d6d8190395cc1efe..9488b091a2e823cd53680dbd1573c9859b3dc072 100644 (file)
@@ -6,8 +6,10 @@
 
 #include <common.h>
 #include <dm.h>
-#include <tpm.h>
 #include <linux/unaligned/be_byteshift.h>
+#if defined(CONFIG_TPM_V1)
+#include <tpm-v1.h>
+#endif
 #include "tpm_internal.h"
 
 int tpm_open(struct udevice *dev)
index 8547580c244803c50a79ad1892d67c988018736c..2079ea913e4428d88e03a962c00e5a667aecbba5 100644 (file)
@@ -7,7 +7,7 @@
 
 #include <common.h>
 #include <dm.h>
-#include <tpm.h>
+#include <tpm-v1.h>
 #include <i2c.h>
 #include <asm/unaligned.h>
 
index 9b2a0250e19eb64dfafe8beb159da6e9cbd6188a..b5fe43ee50f7f68b95bb4b32232b919382000589 100644 (file)
@@ -23,7 +23,7 @@
 #include <dm.h>
 #include <fdtdec.h>
 #include <i2c.h>
-#include <tpm.h>
+#include <tpm-v1.h>
 #include <linux/errno.h>
 #include <linux/compiler.h>
 #include <linux/types.h>
index 572926382ef271b486bf74a2c4e740f012e29430..7664bb1a6057996b4d2a8c0d726fce1b370045c4 100644 (file)
@@ -15,7 +15,7 @@
 #include <common.h>
 #include <dm.h>
 #include <mapmem.h>
-#include <tpm.h>
+#include <tpm-v1.h>
 #include <asm/io.h>
 
 #define PREFIX "lpc_tpm: "
index 44157542a1f4c5390f253f4d8d37cf5ea02af377..8816d55759fdf7bba66537bbf9efe2434afe6a49 100644 (file)
@@ -5,7 +5,7 @@
 
 #include <common.h>
 #include <dm.h>
-#include <tpm.h>
+#include <tpm-v1.h>
 #include <asm/state.h>
 #include <asm/unaligned.h>
 #include <linux/crc8.h>
index 9cf302caffd0e67df63ea396edb15b367ae74338..0d380375eb33c6b108b6c1ba78499da463766599 100644 (file)
@@ -16,7 +16,7 @@
 #include <dm.h>
 #include <fdtdec.h>
 #include <i2c.h>
-#include <tpm.h>
+#include <tpm-v1.h>
 #include <errno.h>
 #include <linux/types.h>
 #include <asm/unaligned.h>
index d5fde11a83d497e0c1769225925edd67667c3f1f..f6087e7633822aad580eb33612bd0334fc17dc65 100644 (file)
@@ -16,7 +16,7 @@
 #include <dm.h>
 #include <fdtdec.h>
 #include <spi.h>
-#include <tpm.h>
+#include <tpm-v1.h>
 #include <errno.h>
 #include <linux/types.h>
 #include <asm/unaligned.h>
diff --git a/include/tpm-common.h b/include/tpm-common.h
new file mode 100644 (file)
index 0000000..1ca5d28
--- /dev/null
@@ -0,0 +1,210 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (c) 2013 The Chromium OS Authors.
+ * Coypright (c) 2013 Guntermann & Drunck GmbH
+ */
+
+#ifndef __TPM_COMMON_H
+#define __TPM_COMMON_H
+
+enum tpm_duration {
+       TPM_SHORT = 0,
+       TPM_MEDIUM = 1,
+       TPM_LONG = 2,
+       TPM_UNDEFINED,
+
+       TPM_DURATION_COUNT,
+};
+
+/*
+ * Here is a partial implementation of TPM commands.  Please consult TCG Main
+ * Specification for definitions of TPM commands.
+ */
+
+#define TPM_HEADER_SIZE                10
+
+/* Max buffer size supported by our tpm */
+#define TPM_DEV_BUFSIZE                1260
+
+/**
+ * struct tpm_chip_priv - Information about a TPM, stored by the uclass
+ *
+ * These values must be set up by the device's probe() method before
+ * communcation is attempted. If the device has an xfer() method, this is
+ * not needed. There is no need to set up @buf.
+ *
+ * @duration_ms:       Length of each duration type in milliseconds
+ * @retry_time_ms:     Time to wait before retrying receive
+ */
+struct tpm_chip_priv {
+       uint duration_ms[TPM_DURATION_COUNT];
+       uint retry_time_ms;
+       u8 buf[TPM_DEV_BUFSIZE + sizeof(u8)];  /* Max buffer size + addr */
+};
+
+/**
+ * struct tpm_ops - low-level TPM operations
+ *
+ * These are designed to avoid loops and delays in the driver itself. These
+ * should be handled in the uclass.
+ *
+ * In gneral you should implement everything except xfer(). Where you need
+ * complete control of the transfer, then xfer() can be provided and will
+ * override the other methods.
+ *
+ * This interface is for low-level TPM access. It does not understand the
+ * concept of localities or the various TPM messages. That interface is
+ * defined in the functions later on in this file, but they all translate
+ * to bytes which are sent and received.
+ */
+struct tpm_ops {
+       /**
+        * open() - Request access to locality 0 for the caller
+        *
+        * After all commands have been completed the caller should call
+        * close().
+        *
+        * @dev:        Device to close
+        * @return 0 ok OK, -ve on error
+        */
+       int (*open)(struct udevice *dev);
+
+       /**
+        * close() - Close the current session
+        *
+        * Releasing the locked locality. Returns 0 on success, -ve 1 on
+        * failure (in case lock removal did not succeed).
+        *
+        * @dev:        Device to close
+        * @return 0 ok OK, -ve on error
+        */
+       int (*close)(struct udevice *dev);
+
+       /**
+        * get_desc() - Get a text description of the TPM
+        *
+        * @dev:        Device to check
+        * @buf:        Buffer to put the string
+        * @size:       Maximum size of buffer
+        * @return length of string, or -ENOSPC it no space
+        */
+       int (*get_desc)(struct udevice *dev, char *buf, int size);
+
+       /**
+        * send() - send data to the TPM
+        *
+        * @dev:        Device to talk to
+        * @sendbuf:    Buffer of the data to send
+        * @send_size:  Size of the data to send
+        *
+        * Returns 0 on success or -ve on failure.
+        */
+       int (*send)(struct udevice *dev, const u8 *sendbuf, size_t send_size);
+
+       /**
+        * recv() - receive a response from the TPM
+        *
+        * @dev:        Device to talk to
+        * @recvbuf:    Buffer to save the response to
+        * @max_size:   Maximum number of bytes to receive
+        *
+        * Returns number of bytes received on success, -EAGAIN if the TPM
+        * response is not ready, -EINTR if cancelled, or other -ve value on
+        * failure.
+        */
+       int (*recv)(struct udevice *dev, u8 *recvbuf, size_t max_size);
+
+       /**
+        * cleanup() - clean up after an operation in progress
+        *
+        * This is called if receiving times out. The TPM may need to abort
+        * the current transaction if it did not complete, and make itself
+        * ready for another.
+        *
+        * @dev:        Device to talk to
+        */
+       int (*cleanup)(struct udevice *dev);
+
+       /**
+        * xfer() - send data to the TPM and get response
+        *
+        * This method is optional. If it exists it is used in preference
+        * to send(), recv() and cleanup(). It should handle all aspects of
+        * TPM communication for a single transfer.
+        *
+        * @dev:        Device to talk to
+        * @sendbuf:    Buffer of the data to send
+        * @send_size:  Size of the data to send
+        * @recvbuf:    Buffer to save the response to
+        * @recv_size:  Pointer to the size of the response buffer
+        *
+        * Returns 0 on success (and places the number of response bytes at
+        * recv_size) or -ve on failure.
+        */
+       int (*xfer)(struct udevice *dev, const u8 *sendbuf, size_t send_size,
+                   u8 *recvbuf, size_t *recv_size);
+};
+
+#define tpm_get_ops(dev)        ((struct tpm_ops *)device_get_ops(dev))
+
+#define MAKE_TPM_CMD_ENTRY(cmd) \
+       U_BOOT_CMD_MKENT(cmd, 0, 1, do_tpm_ ## cmd, "", "")
+
+#define TPM_COMMAND_NO_ARG(cmd)                                \
+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_get_desc() - Get a text description of the TPM
+ *
+ * @dev:       Device to check
+ * @buf:       Buffer to put the string
+ * @size:      Maximum size of buffer
+ * @return length of string, or -ENOSPC it no space
+ */
+int tpm_get_desc(struct udevice *dev, char *buf, int size);
+
+/**
+ * tpm_xfer() - send data to the TPM and get response
+ *
+ * This first uses the device's send() method to send the bytes. Then it calls
+ * recv() to get the reply. If recv() returns -EAGAIN then it will delay a
+ * short time and then call recv() again.
+ *
+ * Regardless of whether recv() completes successfully, it will then call
+ * cleanup() to finish the transaction.
+ *
+ * Note that the outgoing data is inspected to determine command type
+ * (ordinal) and a timeout is used for that command type.
+ *
+ * @sendbuf - buffer of the data to send
+ * @send_size size of the data to send
+ * @recvbuf - memory to save the response to
+ * @recv_len - pointer to the size of the response buffer
+ *
+ * Returns 0 on success (and places the number of response bytes at
+ * recv_len) or -ve on failure.
+ */
+int tpm_xfer(struct udevice *dev, const u8 *sendbuf, size_t send_size,
+            u8 *recvbuf, size_t *recv_size);
+
+/**
+ * Initialize TPM device.  It must be called before any TPM commands.
+ *
+ * @return 0 on success, non-0 on error.
+ */
+int tpm_init(void);
+
+/**
+ * Retrieve the array containing all the commands.
+ *
+ * @return a cmd_tbl_t array.
+ */
+cmd_tbl_t *get_tpm_commands(unsigned int *size);
+
+#endif /* __TPM_COMMON_H */
diff --git a/include/tpm-v1.h b/include/tpm-v1.h
new file mode 100644 (file)
index 0000000..6b4941e
--- /dev/null
@@ -0,0 +1,480 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (c) 2013 The Chromium OS Authors.
+ * Coypright (c) 2013 Guntermann & Drunck GmbH
+ */
+
+#ifndef __TPM_V1_H
+#define __TPM_V1_H
+
+#include <tpm-common.h>
+
+/* Useful constants */
+enum {
+       TPM_REQUEST_HEADER_LENGTH       = 10,
+       TPM_RESPONSE_HEADER_LENGTH      = 10,
+       PCR_DIGEST_LENGTH               = 20,
+       DIGEST_LENGTH                   = 20,
+       TPM_REQUEST_AUTH_LENGTH         = 45,
+       TPM_RESPONSE_AUTH_LENGTH        = 41,
+       /* some max lengths, valid for RSA keys <= 2048 bits */
+       TPM_KEY12_MAX_LENGTH            = 618,
+       TPM_PUBKEY_MAX_LENGTH           = 288,
+};
+
+enum tpm_startup_type {
+       TPM_ST_CLEAR            = 0x0001,
+       TPM_ST_STATE            = 0x0002,
+       TPM_ST_DEACTIVATED      = 0x0003,
+};
+
+enum tpm_physical_presence {
+       TPM_PHYSICAL_PRESENCE_HW_DISABLE        = 0x0200,
+       TPM_PHYSICAL_PRESENCE_CMD_DISABLE       = 0x0100,
+       TPM_PHYSICAL_PRESENCE_LIFETIME_LOCK     = 0x0080,
+       TPM_PHYSICAL_PRESENCE_HW_ENABLE         = 0x0040,
+       TPM_PHYSICAL_PRESENCE_CMD_ENABLE        = 0x0020,
+       TPM_PHYSICAL_PRESENCE_NOTPRESENT        = 0x0010,
+       TPM_PHYSICAL_PRESENCE_PRESENT           = 0x0008,
+       TPM_PHYSICAL_PRESENCE_LOCK              = 0x0004,
+};
+
+enum tpm_nv_index {
+       TPM_NV_INDEX_LOCK       = 0xffffffff,
+       TPM_NV_INDEX_0          = 0x00000000,
+       TPM_NV_INDEX_DIR        = 0x10000001,
+};
+
+enum tpm_resource_type {
+       TPM_RT_KEY      = 0x00000001,
+       TPM_RT_AUTH     = 0x00000002,
+       TPM_RT_HASH     = 0x00000003,
+       TPM_RT_TRANS    = 0x00000004,
+       TPM_RT_CONTEXT  = 0x00000005,
+       TPM_RT_COUNTER  = 0x00000006,
+       TPM_RT_DELEGATE = 0x00000007,
+       TPM_RT_DAA_TPM  = 0x00000008,
+       TPM_RT_DAA_V0   = 0x00000009,
+       TPM_RT_DAA_V1   = 0x0000000A,
+};
+
+enum tpm_capability_areas {
+       TPM_CAP_ORD             = 0x00000001,
+       TPM_CAP_ALG             = 0x00000002,
+       TPM_CAP_PID             = 0x00000003,
+       TPM_CAP_FLAG            = 0x00000004,
+       TPM_CAP_PROPERTY        = 0x00000005,
+       TPM_CAP_VERSION         = 0x00000006,
+       TPM_CAP_KEY_HANDLE      = 0x00000007,
+       TPM_CAP_CHECK_LOADED    = 0x00000008,
+       TPM_CAP_SYM_MODE        = 0x00000009,
+       TPM_CAP_KEY_STATUS      = 0x0000000C,
+       TPM_CAP_NV_LIST         = 0x0000000D,
+       TPM_CAP_MFR             = 0x00000010,
+       TPM_CAP_NV_INDEX        = 0x00000011,
+       TPM_CAP_TRANS_ALG       = 0x00000012,
+       TPM_CAP_HANDLE          = 0x00000014,
+       TPM_CAP_TRANS_ES        = 0x00000015,
+       TPM_CAP_AUTH_ENCRYPT    = 0x00000017,
+       TPM_CAP_SELECT_SIZE     = 0x00000018,
+       TPM_CAP_DA_LOGIC        = 0x00000019,
+       TPM_CAP_VERSION_VAL     = 0x0000001A,
+};
+
+#define TPM_NV_PER_GLOBALLOCK          BIT(15)
+#define TPM_NV_PER_PPREAD              BIT(16)
+#define TPM_NV_PER_PPWRITE             BIT(0)
+#define TPM_NV_PER_READ_STCLEAR                BIT(31)
+#define TPM_NV_PER_WRITE_STCLEAR       BIT(14)
+#define TPM_NV_PER_WRITEDEFINE         BIT(13)
+#define TPM_NV_PER_WRITEALL            BIT(12)
+
+enum {
+       TPM_PUBEK_SIZE                  = 256,
+};
+
+/**
+ * TPM return codes as defined in the TCG Main specification
+ * (TPM Main Part 2 Structures; Specification version 1.2)
+ */
+enum tpm_return_code {
+       TPM_BASE        = 0x00000000,
+       TPM_NON_FATAL   = 0x00000800,
+       TPM_SUCCESS     = TPM_BASE,
+       /* TPM-defined fatal error codes */
+       TPM_AUTHFAIL                    = TPM_BASE +  1,
+       TPM_BADINDEX                    = TPM_BASE +  2,
+       TPM_BAD_PARAMETER               = TPM_BASE +  3,
+       TPM_AUDITFAILURE                = TPM_BASE +  4,
+       TPM_CLEAR_DISABLED              = TPM_BASE +  5,
+       TPM_DEACTIVATED                 = TPM_BASE +  6,
+       TPM_DISABLED                    = TPM_BASE +  7,
+       TPM_DISABLED_CMD                = TPM_BASE +  8,
+       TPM_FAIL                        = TPM_BASE +  9,
+       TPM_BAD_ORDINAL                 = TPM_BASE + 10,
+       TPM_INSTALL_DISABLED            = TPM_BASE + 11,
+       TPM_INVALID_KEYHANDLE           = TPM_BASE + 12,
+       TPM_KEYNOTFOUND                 = TPM_BASE + 13,
+       TPM_INAPPROPRIATE_ENC           = TPM_BASE + 14,
+       TPM_MIGRATE_FAIL                = TPM_BASE + 15,
+       TPM_INVALID_PCR_INFO            = TPM_BASE + 16,
+       TPM_NOSPACE                     = TPM_BASE + 17,
+       TPM_NOSRK                       = TPM_BASE + 18,
+       TPM_NOTSEALED_BLOB              = TPM_BASE + 19,
+       TPM_OWNER_SET                   = TPM_BASE + 20,
+       TPM_RESOURCES                   = TPM_BASE + 21,
+       TPM_SHORTRANDOM                 = TPM_BASE + 22,
+       TPM_SIZE                        = TPM_BASE + 23,
+       TPM_WRONGPCRVAL                 = TPM_BASE + 24,
+       TPM_BAD_PARAM_SIZE              = TPM_BASE + 25,
+       TPM_SHA_THREAD                  = TPM_BASE + 26,
+       TPM_SHA_ERROR                   = TPM_BASE + 27,
+       TPM_FAILEDSELFTEST              = TPM_BASE + 28,
+       TPM_AUTH2FAIL                   = TPM_BASE + 29,
+       TPM_BADTAG                      = TPM_BASE + 30,
+       TPM_IOERROR                     = TPM_BASE + 31,
+       TPM_ENCRYPT_ERROR               = TPM_BASE + 32,
+       TPM_DECRYPT_ERROR               = TPM_BASE + 33,
+       TPM_INVALID_AUTHHANDLE          = TPM_BASE + 34,
+       TPM_NO_ENDORSEMENT              = TPM_BASE + 35,
+       TPM_INVALID_KEYUSAGE            = TPM_BASE + 36,
+       TPM_WRONG_ENTITYTYPE            = TPM_BASE + 37,
+       TPM_INVALID_POSTINIT            = TPM_BASE + 38,
+       TPM_INAPPROPRIATE_SIG           = TPM_BASE + 39,
+       TPM_BAD_KEY_PROPERTY            = TPM_BASE + 40,
+       TPM_BAD_MIGRATION               = TPM_BASE + 41,
+       TPM_BAD_SCHEME                  = TPM_BASE + 42,
+       TPM_BAD_DATASIZE                = TPM_BASE + 43,
+       TPM_BAD_MODE                    = TPM_BASE + 44,
+       TPM_BAD_PRESENCE                = TPM_BASE + 45,
+       TPM_BAD_VERSION                 = TPM_BASE + 46,
+       TPM_NO_WRAP_TRANSPORT           = TPM_BASE + 47,
+       TPM_AUDITFAIL_UNSUCCESSFUL      = TPM_BASE + 48,
+       TPM_AUDITFAIL_SUCCESSFUL        = TPM_BASE + 49,
+       TPM_NOTRESETABLE                = TPM_BASE + 50,
+       TPM_NOTLOCAL                    = TPM_BASE + 51,
+       TPM_BAD_TYPE                    = TPM_BASE + 52,
+       TPM_INVALID_RESOURCE            = TPM_BASE + 53,
+       TPM_NOTFIPS                     = TPM_BASE + 54,
+       TPM_INVALID_FAMILY              = TPM_BASE + 55,
+       TPM_NO_NV_PERMISSION            = TPM_BASE + 56,
+       TPM_REQUIRES_SIGN               = TPM_BASE + 57,
+       TPM_KEY_NOTSUPPORTED            = TPM_BASE + 58,
+       TPM_AUTH_CONFLICT               = TPM_BASE + 59,
+       TPM_AREA_LOCKED                 = TPM_BASE + 60,
+       TPM_BAD_LOCALITY                = TPM_BASE + 61,
+       TPM_READ_ONLY                   = TPM_BASE + 62,
+       TPM_PER_NOWRITE                 = TPM_BASE + 63,
+       TPM_FAMILY_COUNT                = TPM_BASE + 64,
+       TPM_WRITE_LOCKED                = TPM_BASE + 65,
+       TPM_BAD_ATTRIBUTES              = TPM_BASE + 66,
+       TPM_INVALID_STRUCTURE           = TPM_BASE + 67,
+       TPM_KEY_OWNER_CONTROL           = TPM_BASE + 68,
+       TPM_BAD_COUNTER                 = TPM_BASE + 69,
+       TPM_NOT_FULLWRITE               = TPM_BASE + 70,
+       TPM_CONTEXT_GAP                 = TPM_BASE + 71,
+       TPM_MAXNVWRITES                 = TPM_BASE + 72,
+       TPM_NOOPERATOR                  = TPM_BASE + 73,
+       TPM_RESOURCEMISSING             = TPM_BASE + 74,
+       TPM_DELEGATE_LOCK               = TPM_BASE + 75,
+       TPM_DELEGATE_FAMILY             = TPM_BASE + 76,
+       TPM_DELEGATE_ADMIN              = TPM_BASE + 77,
+       TPM_TRANSPORT_NOTEXCLUSIVE      = TPM_BASE + 78,
+       TPM_OWNER_CONTROL               = TPM_BASE + 79,
+       TPM_DAA_RESOURCES               = TPM_BASE + 80,
+       TPM_DAA_INPUT_DATA0             = TPM_BASE + 81,
+       TPM_DAA_INPUT_DATA1             = TPM_BASE + 82,
+       TPM_DAA_ISSUER_SETTINGS         = TPM_BASE + 83,
+       TPM_DAA_TPM_SETTINGS            = TPM_BASE + 84,
+       TPM_DAA_STAGE                   = TPM_BASE + 85,
+       TPM_DAA_ISSUER_VALIDITY         = TPM_BASE + 86,
+       TPM_DAA_WRONG_W                 = TPM_BASE + 87,
+       TPM_BAD_HANDLE                  = TPM_BASE + 88,
+       TPM_BAD_DELEGATE                = TPM_BASE + 89,
+       TPM_BADCONTEXT                  = TPM_BASE + 90,
+       TPM_TOOMANYCONTEXTS             = TPM_BASE + 91,
+       TPM_MA_TICKET_SIGNATURE         = TPM_BASE + 92,
+       TPM_MA_DESTINATION              = TPM_BASE + 93,
+       TPM_MA_SOURCE                   = TPM_BASE + 94,
+       TPM_MA_AUTHORITY                = TPM_BASE + 95,
+       TPM_PERMANENTEK                 = TPM_BASE + 97,
+       TPM_BAD_SIGNATURE               = TPM_BASE + 98,
+       TPM_NOCONTEXTSPACE              = TPM_BASE + 99,
+       /* TPM-defined non-fatal errors */
+       TPM_RETRY               = TPM_BASE + TPM_NON_FATAL,
+       TPM_NEEDS_SELFTEST      = TPM_BASE + TPM_NON_FATAL + 1,
+       TPM_DOING_SELFTEST      = TPM_BASE + TPM_NON_FATAL + 2,
+       TPM_DEFEND_LOCK_RUNNING = TPM_BASE + TPM_NON_FATAL + 3,
+};
+
+struct tpm_permanent_flags {
+       __be16  tag;
+       u8      disable;
+       u8      ownership;
+       u8      deactivated;
+       u8      read_pubek;
+       u8      disable_owner_clear;
+       u8      allow_maintenance;
+       u8      physical_presence_lifetime_lock;
+       u8      physical_presence_hw_enable;
+       u8      physical_presence_cmd_enable;
+       u8      cekp_used;
+       u8      tpm_post;
+       u8      tpm_post_lock;
+       u8      fips;
+       u8      operator;
+       u8      enable_revoke_ek;
+       u8      nv_locked;
+       u8      read_srk_pub;
+       u8      tpm_established;
+       u8      maintenance_done;
+       u8      disable_full_da_logic_info;
+} __packed;
+
+/**
+ * Issue a TPM_Startup command.
+ *
+ * @param mode         TPM startup mode
+ * @return return code of the operation
+ */
+u32 tpm_startup(enum tpm_startup_type mode);
+
+/**
+ * Issue a TPM_SelfTestFull command.
+ *
+ * @return return code of the operation
+ */
+u32 tpm_self_test_full(void);
+
+/**
+ * Issue a TPM_ContinueSelfTest command.
+ *
+ * @return return code of the operation
+ */
+u32 tpm_continue_self_test(void);
+
+/**
+ * Issue a TPM_NV_DefineSpace command.  The implementation is limited
+ * to specify TPM_NV_ATTRIBUTES and size of the area.  The area index
+ * could be one of the special value listed in enum tpm_nv_index.
+ *
+ * @param index                index of the area
+ * @param perm         TPM_NV_ATTRIBUTES of the area
+ * @param size         size of the area
+ * @return return code of the operation
+ */
+u32 tpm_nv_define_space(u32 index, u32 perm, u32 size);
+
+/**
+ * Issue a TPM_NV_ReadValue command.  This implementation is limited
+ * to read the area from offset 0.  The area index could be one of
+ * the special value listed in enum tpm_nv_index.
+ *
+ * @param index                index of the area
+ * @param data         output buffer of the area contents
+ * @param count                size of output buffer
+ * @return return code of the operation
+ */
+u32 tpm_nv_read_value(u32 index, void *data, u32 count);
+
+/**
+ * Issue a TPM_NV_WriteValue command.  This implementation is limited
+ * to write the area from offset 0.  The area index could be one of
+ * the special value listed in enum tpm_nv_index.
+ *
+ * @param index                index of the area
+ * @param data         input buffer to be wrote to the area
+ * @param length       length of data bytes of input buffer
+ * @return return code of the operation
+ */
+u32 tpm_nv_write_value(u32 index, const void *data, u32 length);
+
+/**
+ * Issue a TPM_Extend command.
+ *
+ * @param index                index of the PCR
+ * @param in_digest    160-bit value representing the event to be
+ *                     recorded
+ * @param out_digest   160-bit PCR value after execution of the
+ *                     command
+ * @return return code of the operation
+ */
+u32 tpm_extend(u32 index, const void *in_digest, void *out_digest);
+
+/**
+ * Issue a TPM_PCRRead command.
+ *
+ * @param index                index of the PCR
+ * @param data         output buffer for contents of the named PCR
+ * @param count                size of output buffer
+ * @return return code of the operation
+ */
+u32 tpm_pcr_read(u32 index, void *data, size_t count);
+
+/**
+ * Issue a TSC_PhysicalPresence command.  TPM physical presence flag
+ * is bit-wise OR'ed of flags listed in enum tpm_physical_presence.
+ *
+ * @param presence     TPM physical presence flag
+ * @return return code of the operation
+ */
+u32 tpm_tsc_physical_presence(u16 presence);
+
+/**
+ * Issue a TPM_ReadPubek command.
+ *
+ * @param data         output buffer for the public endorsement key
+ * @param count                size of output buffer
+ * @return return code of the operation
+ */
+u32 tpm_read_pubek(void *data, size_t count);
+
+/**
+ * Issue a TPM_ForceClear command.
+ *
+ * @return return code of the operation
+ */
+u32 tpm_force_clear(void);
+
+/**
+ * Issue a TPM_PhysicalEnable command.
+ *
+ * @return return code of the operation
+ */
+u32 tpm_physical_enable(void);
+
+/**
+ * Issue a TPM_PhysicalDisable command.
+ *
+ * @return return code of the operation
+ */
+u32 tpm_physical_disable(void);
+
+/**
+ * Issue a TPM_PhysicalSetDeactivated command.
+ *
+ * @param state                boolean state of the deactivated flag
+ * @return return code of the operation
+ */
+u32 tpm_physical_set_deactivated(u8 state);
+
+/**
+ * Issue a TPM_GetCapability command.  This implementation is limited
+ * to query sub_cap index that is 4-byte wide.
+ *
+ * @param cap_area     partition of capabilities
+ * @param sub_cap      further definition of capability, which is
+ *                     limited to be 4-byte wide
+ * @param cap          output buffer for capability information
+ * @param count                size of output buffer
+ * @return return code of the operation
+ */
+u32 tpm_get_capability(u32 cap_area, u32 sub_cap, void *cap, size_t count);
+
+/**
+ * Issue a TPM_FlushSpecific command for a AUTH resource.
+ *
+ * @param auth_handle  handle of the auth session
+ * @return return code of the operation
+ */
+u32 tpm_terminate_auth_session(u32 auth_handle);
+
+/**
+ * Issue a TPM_OIAP command to setup an object independent authorization
+ * session.
+ * Information about the session is stored internally.
+ * If there was already an OIAP session active it is terminated and a new
+ * session is set up.
+ *
+ * @param auth_handle  pointer to the (new) auth handle or NULL.
+ * @return return code of the operation
+ */
+u32 tpm_oiap(u32 *auth_handle);
+
+/**
+ * Ends an active OIAP session.
+ *
+ * @return return code of the operation
+ */
+u32 tpm_end_oiap(void);
+
+/**
+ * Issue a TPM_LoadKey2 (Auth1) command using an OIAP session for authenticating
+ * the usage of the parent key.
+ *
+ * @param parent_handle        handle of the parent key.
+ * @param key          pointer to the key structure (TPM_KEY or TPM_KEY12).
+ * @param key_length   size of the key structure
+ * @param parent_key_usage_auth        usage auth for the parent key
+ * @param key_handle   pointer to the key handle
+ * @return return code of the operation
+ */
+u32 tpm_load_key2_oiap(u32 parent_handle, const void *key, size_t key_length,
+                      const void *parent_key_usage_auth, u32 *key_handle);
+
+/**
+ * Issue a TPM_GetPubKey (Auth1) command using an OIAP session for
+ * authenticating the usage of the key.
+ *
+ * @param key_handle   handle of the key
+ * @param usage_auth   usage auth for the key
+ * @param pubkey       pointer to the pub key buffer; may be NULL if the pubkey
+ *                     should not be stored.
+ * @param pubkey_len   pointer to the pub key buffer len. On entry: the size of
+ *                     the provided pubkey buffer. On successful exit: the size
+ *                     of the stored TPM_PUBKEY structure (iff pubkey != NULL).
+ * @return return code of the operation
+ */
+u32 tpm_get_pub_key_oiap(u32 key_handle, const void *usage_auth, void *pubkey,
+                        size_t *pubkey_len);
+
+/**
+ * Get the TPM permanent flags value
+ *
+ * @param pflags       Place to put permanent flags
+ * @return return code of the operation
+ */
+u32 tpm_get_permanent_flags(struct tpm_permanent_flags *pflags);
+
+/**
+ * Get the TPM permissions
+ *
+ * @param perm         Returns permissions value
+ * @return return code of the operation
+ */
+u32 tpm_get_permissions(u32 index, u32 *perm);
+
+/**
+ * Flush a resource with a given handle and type from the TPM
+ *
+ * @param key_handle           handle of the resource
+ * @param resource_type                type of the resource
+ * @return return code of the operation
+ */
+u32 tpm_flush_specific(u32 key_handle, u32 resource_type);
+
+#ifdef CONFIG_TPM_LOAD_KEY_BY_SHA1
+/**
+ * Search for a key by usage AuthData and the hash of the parent's pub key.
+ *
+ * @param auth         Usage auth of the key to search for
+ * @param pubkey_digest        SHA1 hash of the pub key structure of the key
+ * @param[out] handle  The handle of the key (Non-null iff found)
+ * @return 0 if key was found in TPM; != 0 if not.
+ */
+u32 tpm_find_key_sha1(const u8 auth[20], const u8 pubkey_digest[20],
+                     u32 *handle);
+#endif /* CONFIG_TPM_LOAD_KEY_BY_SHA1 */
+
+/**
+ * Read random bytes from the TPM RNG. The implementation deals with the fact
+ * that the TPM may legally return fewer bytes than requested by retrying
+ * until @p count bytes have been received.
+ *
+ * @param data         output buffer for the random bytes
+ * @param count                size of output buffer
+ * @return return code of the operation
+ */
+u32 tpm_get_random(void *data, u32 count);
+
+#endif /* __TPM_V1_H */
diff --git a/include/tpm.h b/include/tpm.h
deleted file mode 100644 (file)
index 23d925e..0000000
+++ /dev/null
@@ -1,664 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-/*
- * Copyright (c) 2013 The Chromium OS Authors.
- * Coypright (c) 2013 Guntermann & Drunck GmbH
- */
-
-#ifndef __TPM_H
-#define __TPM_H
-
-/*
- * Here is a partial implementation of TPM commands.  Please consult TCG Main
- * Specification for definitions of TPM commands.
- */
-
-#define TPM_HEADER_SIZE                10
-
-enum tpm_duration {
-       TPM_SHORT = 0,
-       TPM_MEDIUM = 1,
-       TPM_LONG = 2,
-       TPM_UNDEFINED,
-
-       TPM_DURATION_COUNT,
-};
-
-enum tpm_startup_type {
-       TPM_ST_CLEAR            = 0x0001,
-       TPM_ST_STATE            = 0x0002,
-       TPM_ST_DEACTIVATED      = 0x0003,
-};
-
-enum tpm_physical_presence {
-       TPM_PHYSICAL_PRESENCE_HW_DISABLE        = 0x0200,
-       TPM_PHYSICAL_PRESENCE_CMD_DISABLE       = 0x0100,
-       TPM_PHYSICAL_PRESENCE_LIFETIME_LOCK     = 0x0080,
-       TPM_PHYSICAL_PRESENCE_HW_ENABLE         = 0x0040,
-       TPM_PHYSICAL_PRESENCE_CMD_ENABLE        = 0x0020,
-       TPM_PHYSICAL_PRESENCE_NOTPRESENT        = 0x0010,
-       TPM_PHYSICAL_PRESENCE_PRESENT           = 0x0008,
-       TPM_PHYSICAL_PRESENCE_LOCK              = 0x0004,
-};
-
-enum tpm_nv_index {
-       TPM_NV_INDEX_LOCK       = 0xffffffff,
-       TPM_NV_INDEX_0          = 0x00000000,
-       TPM_NV_INDEX_DIR        = 0x10000001,
-};
-
-enum tpm_resource_type {
-       TPM_RT_KEY      = 0x00000001,
-       TPM_RT_AUTH     = 0x00000002,
-       TPM_RT_HASH     = 0x00000003,
-       TPM_RT_TRANS    = 0x00000004,
-       TPM_RT_CONTEXT  = 0x00000005,
-       TPM_RT_COUNTER  = 0x00000006,
-       TPM_RT_DELEGATE = 0x00000007,
-       TPM_RT_DAA_TPM  = 0x00000008,
-       TPM_RT_DAA_V0   = 0x00000009,
-       TPM_RT_DAA_V1   = 0x0000000A,
-};
-
-enum tpm_capability_areas {
-       TPM_CAP_ORD             = 0x00000001,
-       TPM_CAP_ALG             = 0x00000002,
-       TPM_CAP_PID             = 0x00000003,
-       TPM_CAP_FLAG            = 0x00000004,
-       TPM_CAP_PROPERTY        = 0x00000005,
-       TPM_CAP_VERSION         = 0x00000006,
-       TPM_CAP_KEY_HANDLE      = 0x00000007,
-       TPM_CAP_CHECK_LOADED    = 0x00000008,
-       TPM_CAP_SYM_MODE        = 0x00000009,
-       TPM_CAP_KEY_STATUS      = 0x0000000C,
-       TPM_CAP_NV_LIST         = 0x0000000D,
-       TPM_CAP_MFR             = 0x00000010,
-       TPM_CAP_NV_INDEX        = 0x00000011,
-       TPM_CAP_TRANS_ALG       = 0x00000012,
-       TPM_CAP_HANDLE          = 0x00000014,
-       TPM_CAP_TRANS_ES        = 0x00000015,
-       TPM_CAP_AUTH_ENCRYPT    = 0x00000017,
-       TPM_CAP_SELECT_SIZE     = 0x00000018,
-       TPM_CAP_DA_LOGIC        = 0x00000019,
-       TPM_CAP_VERSION_VAL     = 0x0000001A,
-};
-
-#define TPM_NV_PER_GLOBALLOCK          BIT(15)
-#define TPM_NV_PER_PPREAD              BIT(16)
-#define TPM_NV_PER_PPWRITE             BIT(0)
-#define TPM_NV_PER_READ_STCLEAR                BIT(31)
-#define TPM_NV_PER_WRITE_STCLEAR       BIT(14)
-#define TPM_NV_PER_WRITEDEFINE         BIT(13)
-#define TPM_NV_PER_WRITEALL            BIT(12)
-
-enum {
-       TPM_PUBEK_SIZE                  = 256,
-};
-
-/**
- * TPM return codes as defined in the TCG Main specification
- * (TPM Main Part 2 Structures; Specification version 1.2)
- */
-enum tpm_return_code {
-       TPM_BASE        = 0x00000000,
-       TPM_NON_FATAL   = 0x00000800,
-       TPM_SUCCESS     = TPM_BASE,
-       /* TPM-defined fatal error codes */
-       TPM_AUTHFAIL                    = TPM_BASE +  1,
-       TPM_BADINDEX                    = TPM_BASE +  2,
-       TPM_BAD_PARAMETER               = TPM_BASE +  3,
-       TPM_AUDITFAILURE                = TPM_BASE +  4,
-       TPM_CLEAR_DISABLED              = TPM_BASE +  5,
-       TPM_DEACTIVATED                 = TPM_BASE +  6,
-       TPM_DISABLED                    = TPM_BASE +  7,
-       TPM_DISABLED_CMD                = TPM_BASE +  8,
-       TPM_FAIL                        = TPM_BASE +  9,
-       TPM_BAD_ORDINAL                 = TPM_BASE + 10,
-       TPM_INSTALL_DISABLED            = TPM_BASE + 11,
-       TPM_INVALID_KEYHANDLE           = TPM_BASE + 12,
-       TPM_KEYNOTFOUND                 = TPM_BASE + 13,
-       TPM_INAPPROPRIATE_ENC           = TPM_BASE + 14,
-       TPM_MIGRATE_FAIL                = TPM_BASE + 15,
-       TPM_INVALID_PCR_INFO            = TPM_BASE + 16,
-       TPM_NOSPACE                     = TPM_BASE + 17,
-       TPM_NOSRK                       = TPM_BASE + 18,
-       TPM_NOTSEALED_BLOB              = TPM_BASE + 19,
-       TPM_OWNER_SET                   = TPM_BASE + 20,
-       TPM_RESOURCES                   = TPM_BASE + 21,
-       TPM_SHORTRANDOM                 = TPM_BASE + 22,
-       TPM_SIZE                        = TPM_BASE + 23,
-       TPM_WRONGPCRVAL                 = TPM_BASE + 24,
-       TPM_BAD_PARAM_SIZE              = TPM_BASE + 25,
-       TPM_SHA_THREAD                  = TPM_BASE + 26,
-       TPM_SHA_ERROR                   = TPM_BASE + 27,
-       TPM_FAILEDSELFTEST              = TPM_BASE + 28,
-       TPM_AUTH2FAIL                   = TPM_BASE + 29,
-       TPM_BADTAG                      = TPM_BASE + 30,
-       TPM_IOERROR                     = TPM_BASE + 31,
-       TPM_ENCRYPT_ERROR               = TPM_BASE + 32,
-       TPM_DECRYPT_ERROR               = TPM_BASE + 33,
-       TPM_INVALID_AUTHHANDLE          = TPM_BASE + 34,
-       TPM_NO_ENDORSEMENT              = TPM_BASE + 35,
-       TPM_INVALID_KEYUSAGE            = TPM_BASE + 36,
-       TPM_WRONG_ENTITYTYPE            = TPM_BASE + 37,
-       TPM_INVALID_POSTINIT            = TPM_BASE + 38,
-       TPM_INAPPROPRIATE_SIG           = TPM_BASE + 39,
-       TPM_BAD_KEY_PROPERTY            = TPM_BASE + 40,
-       TPM_BAD_MIGRATION               = TPM_BASE + 41,
-       TPM_BAD_SCHEME                  = TPM_BASE + 42,
-       TPM_BAD_DATASIZE                = TPM_BASE + 43,
-       TPM_BAD_MODE                    = TPM_BASE + 44,
-       TPM_BAD_PRESENCE                = TPM_BASE + 45,
-       TPM_BAD_VERSION                 = TPM_BASE + 46,
-       TPM_NO_WRAP_TRANSPORT           = TPM_BASE + 47,
-       TPM_AUDITFAIL_UNSUCCESSFUL      = TPM_BASE + 48,
-       TPM_AUDITFAIL_SUCCESSFUL        = TPM_BASE + 49,
-       TPM_NOTRESETABLE                = TPM_BASE + 50,
-       TPM_NOTLOCAL                    = TPM_BASE + 51,
-       TPM_BAD_TYPE                    = TPM_BASE + 52,
-       TPM_INVALID_RESOURCE            = TPM_BASE + 53,
-       TPM_NOTFIPS                     = TPM_BASE + 54,
-       TPM_INVALID_FAMILY              = TPM_BASE + 55,
-       TPM_NO_NV_PERMISSION            = TPM_BASE + 56,
-       TPM_REQUIRES_SIGN               = TPM_BASE + 57,
-       TPM_KEY_NOTSUPPORTED            = TPM_BASE + 58,
-       TPM_AUTH_CONFLICT               = TPM_BASE + 59,
-       TPM_AREA_LOCKED                 = TPM_BASE + 60,
-       TPM_BAD_LOCALITY                = TPM_BASE + 61,
-       TPM_READ_ONLY                   = TPM_BASE + 62,
-       TPM_PER_NOWRITE                 = TPM_BASE + 63,
-       TPM_FAMILY_COUNT                = TPM_BASE + 64,
-       TPM_WRITE_LOCKED                = TPM_BASE + 65,
-       TPM_BAD_ATTRIBUTES              = TPM_BASE + 66,
-       TPM_INVALID_STRUCTURE           = TPM_BASE + 67,
-       TPM_KEY_OWNER_CONTROL           = TPM_BASE + 68,
-       TPM_BAD_COUNTER                 = TPM_BASE + 69,
-       TPM_NOT_FULLWRITE               = TPM_BASE + 70,
-       TPM_CONTEXT_GAP                 = TPM_BASE + 71,
-       TPM_MAXNVWRITES                 = TPM_BASE + 72,
-       TPM_NOOPERATOR                  = TPM_BASE + 73,
-       TPM_RESOURCEMISSING             = TPM_BASE + 74,
-       TPM_DELEGATE_LOCK               = TPM_BASE + 75,
-       TPM_DELEGATE_FAMILY             = TPM_BASE + 76,
-       TPM_DELEGATE_ADMIN              = TPM_BASE + 77,
-       TPM_TRANSPORT_NOTEXCLUSIVE      = TPM_BASE + 78,
-       TPM_OWNER_CONTROL               = TPM_BASE + 79,
-       TPM_DAA_RESOURCES               = TPM_BASE + 80,
-       TPM_DAA_INPUT_DATA0             = TPM_BASE + 81,
-       TPM_DAA_INPUT_DATA1             = TPM_BASE + 82,
-       TPM_DAA_ISSUER_SETTINGS         = TPM_BASE + 83,
-       TPM_DAA_TPM_SETTINGS            = TPM_BASE + 84,
-       TPM_DAA_STAGE                   = TPM_BASE + 85,
-       TPM_DAA_ISSUER_VALIDITY         = TPM_BASE + 86,
-       TPM_DAA_WRONG_W                 = TPM_BASE + 87,
-       TPM_BAD_HANDLE                  = TPM_BASE + 88,
-       TPM_BAD_DELEGATE                = TPM_BASE + 89,
-       TPM_BADCONTEXT                  = TPM_BASE + 90,
-       TPM_TOOMANYCONTEXTS             = TPM_BASE + 91,
-       TPM_MA_TICKET_SIGNATURE         = TPM_BASE + 92,
-       TPM_MA_DESTINATION              = TPM_BASE + 93,
-       TPM_MA_SOURCE                   = TPM_BASE + 94,
-       TPM_MA_AUTHORITY                = TPM_BASE + 95,
-       TPM_PERMANENTEK                 = TPM_BASE + 97,
-       TPM_BAD_SIGNATURE               = TPM_BASE + 98,
-       TPM_NOCONTEXTSPACE              = TPM_BASE + 99,
-       /* TPM-defined non-fatal errors */
-       TPM_RETRY               = TPM_BASE + TPM_NON_FATAL,
-       TPM_NEEDS_SELFTEST      = TPM_BASE + TPM_NON_FATAL + 1,
-       TPM_DOING_SELFTEST      = TPM_BASE + TPM_NON_FATAL + 2,
-       TPM_DEFEND_LOCK_RUNNING = TPM_BASE + TPM_NON_FATAL + 3,
-};
-
-struct tpm_permanent_flags {
-       __be16  tag;
-       u8      disable;
-       u8      ownership;
-       u8      deactivated;
-       u8      read_pubek;
-       u8      disable_owner_clear;
-       u8      allow_maintenance;
-       u8      physical_presence_lifetime_lock;
-       u8      physical_presence_hw_enable;
-       u8      physical_presence_cmd_enable;
-       u8      cekp_used;
-       u8      tpm_post;
-       u8      tpm_post_lock;
-       u8      fips;
-       u8      operator;
-       u8      enable_revoke_ek;
-       u8      nv_locked;
-       u8      read_srk_pub;
-       u8      tpm_established;
-       u8      maintenance_done;
-       u8      disable_full_da_logic_info;
-} __packed;
-
-/* Max buffer size supported by our tpm */
-#define TPM_DEV_BUFSIZE                1260
-
-/**
- * struct tpm_chip_priv - Information about a TPM, stored by the uclass
- *
- * These values must be set up by the device's probe() method before
- * communcation is attempted. If the device has an xfer() method, this is
- * not needed. There is no need to set up @buf.
- *
- * @duration_ms:       Length of each duration type in milliseconds
- * @retry_time_ms:     Time to wait before retrying receive
- */
-struct tpm_chip_priv {
-       uint duration_ms[TPM_DURATION_COUNT];
-       uint retry_time_ms;
-       u8 buf[TPM_DEV_BUFSIZE + sizeof(u8)];  /* Max buffer size + addr */
-};
-
-/**
- * struct tpm_ops - low-level TPM operations
- *
- * These are designed to avoid loops and delays in the driver itself. These
- * should be handled in the uclass.
- *
- * In gneral you should implement everything except xfer(). Where you need
- * complete control of the transfer, then xfer() can be provided and will
- * override the other methods.
- *
- * This interface is for low-level TPM access. It does not understand the
- * concept of localities or the various TPM messages. That interface is
- * defined in the functions later on in this file, but they all translate
- * to bytes which are sent and received.
- */
-struct tpm_ops {
-       /**
-        * open() - Request access to locality 0 for the caller
-        *
-        * After all commands have been completed the caller should call
-        * close().
-        *
-        * @dev:        Device to close
-        * @return 0 ok OK, -ve on error
-        */
-       int (*open)(struct udevice *dev);
-
-       /**
-        * close() - Close the current session
-        *
-        * Releasing the locked locality. Returns 0 on success, -ve 1 on
-        * failure (in case lock removal did not succeed).
-        *
-        * @dev:        Device to close
-        * @return 0 ok OK, -ve on error
-        */
-       int (*close)(struct udevice *dev);
-
-       /**
-        * get_desc() - Get a text description of the TPM
-        *
-        * @dev:        Device to check
-        * @buf:        Buffer to put the string
-        * @size:       Maximum size of buffer
-        * @return length of string, or -ENOSPC it no space
-        */
-       int (*get_desc)(struct udevice *dev, char *buf, int size);
-
-       /**
-        * send() - send data to the TPM
-        *
-        * @dev:        Device to talk to
-        * @sendbuf:    Buffer of the data to send
-        * @send_size:  Size of the data to send
-        *
-        * Returns 0 on success or -ve on failure.
-        */
-       int (*send)(struct udevice *dev, const u8 *sendbuf, size_t send_size);
-
-       /**
-        * recv() - receive a response from the TPM
-        *
-        * @dev:        Device to talk to
-        * @recvbuf:    Buffer to save the response to
-        * @max_size:   Maximum number of bytes to receive
-        *
-        * Returns number of bytes received on success, -EAGAIN if the TPM
-        * response is not ready, -EINTR if cancelled, or other -ve value on
-        * failure.
-        */
-       int (*recv)(struct udevice *dev, u8 *recvbuf, size_t max_size);
-
-       /**
-        * cleanup() - clean up after an operation in progress
-        *
-        * This is called if receiving times out. The TPM may need to abort
-        * the current transaction if it did not complete, and make itself
-        * ready for another.
-        *
-        * @dev:        Device to talk to
-        */
-       int (*cleanup)(struct udevice *dev);
-
-       /**
-        * xfer() - send data to the TPM and get response
-        *
-        * This method is optional. If it exists it is used in preference
-        * to send(), recv() and cleanup(). It should handle all aspects of
-        * TPM communication for a single transfer.
-        *
-        * @dev:        Device to talk to
-        * @sendbuf:    Buffer of the data to send
-        * @send_size:  Size of the data to send
-        * @recvbuf:    Buffer to save the response to
-        * @recv_size:  Pointer to the size of the response buffer
-        *
-        * Returns 0 on success (and places the number of response bytes at
-        * recv_size) or -ve on failure.
-        */
-       int (*xfer)(struct udevice *dev, const u8 *sendbuf, size_t send_size,
-                   u8 *recvbuf, size_t *recv_size);
-};
-
-#define tpm_get_ops(dev)        ((struct tpm_ops *)device_get_ops(dev))
-
-/**
- * tpm_open() - Request access to locality 0 for the caller
- *
- * After all commands have been completed the caller is supposed to
- * call tpm_close().
- *
- * Returns 0 on success, -ve on failure.
- */
-int tpm_open(struct udevice *dev);
-
-/**
- * tpm_close() - Close the current session
- *
- * Releasing the locked locality. Returns 0 on success, -ve 1 on
- * failure (in case lock removal did not succeed).
- */
-int tpm_close(struct udevice *dev);
-
-/**
- * tpm_get_desc() - Get a text description of the TPM
- *
- * @dev:       Device to check
- * @buf:       Buffer to put the string
- * @size:      Maximum size of buffer
- * @return length of string, or -ENOSPC it no space
- */
-int tpm_get_desc(struct udevice *dev, char *buf, int size);
-
-/**
- * tpm_xfer() - send data to the TPM and get response
- *
- * This first uses the device's send() method to send the bytes. Then it calls
- * recv() to get the reply. If recv() returns -EAGAIN then it will delay a
- * short time and then call recv() again.
- *
- * Regardless of whether recv() completes successfully, it will then call
- * cleanup() to finish the transaction.
- *
- * Note that the outgoing data is inspected to determine command type
- * (ordinal) and a timeout is used for that command type.
- *
- * @sendbuf - buffer of the data to send
- * @send_size size of the data to send
- * @recvbuf - memory to save the response to
- * @recv_len - pointer to the size of the response buffer
- *
- * Returns 0 on success (and places the number of response bytes at
- * recv_len) or -ve on failure.
- */
-int tpm_xfer(struct udevice *dev, const u8 *sendbuf, size_t send_size,
-            u8 *recvbuf, size_t *recv_size);
-
-/**
- * Initialize TPM device.  It must be called before any TPM commands.
- *
- * @return 0 on success, non-0 on error.
- */
-int tpm_init(void);
-
-/**
- * Issue a TPM_Startup command.
- *
- * @param mode         TPM startup mode
- * @return return code of the operation
- */
-u32 tpm_startup(enum tpm_startup_type mode);
-
-/**
- * Issue a TPM_SelfTestFull command.
- *
- * @return return code of the operation
- */
-u32 tpm_self_test_full(void);
-
-/**
- * Issue a TPM_ContinueSelfTest command.
- *
- * @return return code of the operation
- */
-u32 tpm_continue_self_test(void);
-
-/**
- * Issue a TPM_NV_DefineSpace command.  The implementation is limited
- * to specify TPM_NV_ATTRIBUTES and size of the area.  The area index
- * could be one of the special value listed in enum tpm_nv_index.
- *
- * @param index                index of the area
- * @param perm         TPM_NV_ATTRIBUTES of the area
- * @param size         size of the area
- * @return return code of the operation
- */
-u32 tpm_nv_define_space(u32 index, u32 perm, u32 size);
-
-/**
- * Issue a TPM_NV_ReadValue command.  This implementation is limited
- * to read the area from offset 0.  The area index could be one of
- * the special value listed in enum tpm_nv_index.
- *
- * @param index                index of the area
- * @param data         output buffer of the area contents
- * @param count                size of output buffer
- * @return return code of the operation
- */
-u32 tpm_nv_read_value(u32 index, void *data, u32 count);
-
-/**
- * Issue a TPM_NV_WriteValue command.  This implementation is limited
- * to write the area from offset 0.  The area index could be one of
- * the special value listed in enum tpm_nv_index.
- *
- * @param index                index of the area
- * @param data         input buffer to be wrote to the area
- * @param length       length of data bytes of input buffer
- * @return return code of the operation
- */
-u32 tpm_nv_write_value(u32 index, const void *data, u32 length);
-
-/**
- * Issue a TPM_Extend command.
- *
- * @param index                index of the PCR
- * @param in_digest    160-bit value representing the event to be
- *                     recorded
- * @param out_digest   160-bit PCR value after execution of the
- *                     command
- * @return return code of the operation
- */
-u32 tpm_extend(u32 index, const void *in_digest, void *out_digest);
-
-/**
- * Issue a TPM_PCRRead command.
- *
- * @param index                index of the PCR
- * @param data         output buffer for contents of the named PCR
- * @param count                size of output buffer
- * @return return code of the operation
- */
-u32 tpm_pcr_read(u32 index, void *data, size_t count);
-
-/**
- * Issue a TSC_PhysicalPresence command.  TPM physical presence flag
- * is bit-wise OR'ed of flags listed in enum tpm_physical_presence.
- *
- * @param presence     TPM physical presence flag
- * @return return code of the operation
- */
-u32 tpm_tsc_physical_presence(u16 presence);
-
-/**
- * Issue a TPM_ReadPubek command.
- *
- * @param data         output buffer for the public endorsement key
- * @param count                size of output buffer
- * @return return code of the operation
- */
-u32 tpm_read_pubek(void *data, size_t count);
-
-/**
- * Issue a TPM_ForceClear command.
- *
- * @return return code of the operation
- */
-u32 tpm_force_clear(void);
-
-/**
- * Issue a TPM_PhysicalEnable command.
- *
- * @return return code of the operation
- */
-u32 tpm_physical_enable(void);
-
-/**
- * Issue a TPM_PhysicalDisable command.
- *
- * @return return code of the operation
- */
-u32 tpm_physical_disable(void);
-
-/**
- * Issue a TPM_PhysicalSetDeactivated command.
- *
- * @param state                boolean state of the deactivated flag
- * @return return code of the operation
- */
-u32 tpm_physical_set_deactivated(u8 state);
-
-/**
- * Issue a TPM_GetCapability command.  This implementation is limited
- * to query sub_cap index that is 4-byte wide.
- *
- * @param cap_area     partition of capabilities
- * @param sub_cap      further definition of capability, which is
- *                     limited to be 4-byte wide
- * @param cap          output buffer for capability information
- * @param count                size of output buffer
- * @return return code of the operation
- */
-u32 tpm_get_capability(u32 cap_area, u32 sub_cap, void *cap, size_t count);
-
-/**
- * Issue a TPM_FlushSpecific command for a AUTH resource.
- *
- * @param auth_handle  handle of the auth session
- * @return return code of the operation
- */
-u32 tpm_terminate_auth_session(u32 auth_handle);
-
-/**
- * Issue a TPM_OIAP command to setup an object independent authorization
- * session.
- * Information about the session is stored internally.
- * If there was already an OIAP session active it is terminated and a new
- * session is set up.
- *
- * @param auth_handle  pointer to the (new) auth handle or NULL.
- * @return return code of the operation
- */
-u32 tpm_oiap(u32 *auth_handle);
-
-/**
- * Ends an active OIAP session.
- *
- * @return return code of the operation
- */
-u32 tpm_end_oiap(void);
-
-/**
- * Issue a TPM_LoadKey2 (Auth1) command using an OIAP session for authenticating
- * the usage of the parent key.
- *
- * @param parent_handle        handle of the parent key.
- * @param key          pointer to the key structure (TPM_KEY or TPM_KEY12).
- * @param key_length   size of the key structure
- * @param parent_key_usage_auth        usage auth for the parent key
- * @param key_handle   pointer to the key handle
- * @return return code of the operation
- */
-u32 tpm_load_key2_oiap(u32 parent_handle, const void *key, size_t key_length,
-                      const void *parent_key_usage_auth, u32 *key_handle);
-
-/**
- * Issue a TPM_GetPubKey (Auth1) command using an OIAP session for
- * authenticating the usage of the key.
- *
- * @param key_handle   handle of the key
- * @param usage_auth   usage auth for the key
- * @param pubkey       pointer to the pub key buffer; may be NULL if the pubkey
- *                     should not be stored.
- * @param pubkey_len   pointer to the pub key buffer len. On entry: the size of
- *                     the provided pubkey buffer. On successful exit: the size
- *                     of the stored TPM_PUBKEY structure (iff pubkey != NULL).
- * @return return code of the operation
- */
-u32 tpm_get_pub_key_oiap(u32 key_handle, const void *usage_auth, void *pubkey,
-                        size_t *pubkey_len);
-
-/**
- * Get the TPM permanent flags value
- *
- * @param pflags       Place to put permanent flags
- * @return return code of the operation
- */
-u32 tpm_get_permanent_flags(struct tpm_permanent_flags *pflags);
-
-/**
- * Get the TPM permissions
- *
- * @param perm         Returns permissions value
- * @return return code of the operation
- */
-u32 tpm_get_permissions(u32 index, u32 *perm);
-
-/**
- * Flush a resource with a given handle and type from the TPM
- *
- * @param key_handle           handle of the resource
- * @param resource_type                type of the resource
- * @return return code of the operation
- */
-u32 tpm_flush_specific(u32 key_handle, u32 resource_type);
-
-#ifdef CONFIG_TPM_LOAD_KEY_BY_SHA1
-/**
- * Search for a key by usage AuthData and the hash of the parent's pub key.
- *
- * @param auth         Usage auth of the key to search for
- * @param pubkey_digest        SHA1 hash of the pub key structure of the key
- * @param[out] handle  The handle of the key (Non-null iff found)
- * @return 0 if key was found in TPM; != 0 if not.
- */
-u32 tpm_find_key_sha1(const u8 auth[20], const u8 pubkey_digest[20],
-                     u32 *handle);
-#endif /* CONFIG_TPM_LOAD_KEY_BY_SHA1 */
-
-/**
- * Read random bytes from the TPM RNG. The implementation deals with the fact
- * that the TPM may legally return fewer bytes than requested by retrying
- * until @p count bytes have been received.
- *
- * @param data         output buffer for the random bytes
- * @param count                size of output buffer
- * @return return code of the operation
- */
-u32 tpm_get_random(void *data, u32 count);
-
-#endif /* __TPM_H */
index 2a56b3b1c60dc9df8b2230be57d40a6fe08dbc81..72504e7654a89917fafbdd0e80e95f5541831924 100644 (file)
@@ -39,7 +39,8 @@ obj-$(CONFIG_PHYSMEM) += physmem.o
 obj-y += qsort.o
 obj-y += rc4.o
 obj-$(CONFIG_SUPPORT_EMMC_RPMB) += sha256.o
-obj-$(CONFIG_TPM_V1) += tpm.o
+obj-$(CONFIG_TPM) += tpm-common.o
+obj-$(CONFIG_TPM_V1) += tpm-v1.o
 obj-$(CONFIG_RBTREE)   += rbtree.o
 obj-$(CONFIG_BITREVERSE) += bitrev.o
 obj-y += list_sort.o
diff --git a/lib/tpm-common.c b/lib/tpm-common.c
new file mode 100644 (file)
index 0000000..4c2b939
--- /dev/null
@@ -0,0 +1,188 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2013 The Chromium OS Authors.
+ * Coypright (c) 2013 Guntermann & Drunck GmbH
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <asm/unaligned.h>
+#include <tpm-common.h>
+#include "tpm-utils.h"
+
+int pack_byte_string(u8 *str, size_t size, const char *format, ...)
+{
+       va_list args;
+       size_t offset = 0, length = 0;
+       u8 *data = NULL;
+       u32 value = 0;
+
+       va_start(args, format);
+       for (; *format; format++) {
+               switch (*format) {
+               case 'b':
+                       offset = va_arg(args, size_t);
+                       value = va_arg(args, int);
+                       length = 1;
+                       break;
+               case 'w':
+                       offset = va_arg(args, size_t);
+                       value = va_arg(args, int);
+                       length = 2;
+                       break;
+               case 'd':
+                       offset = va_arg(args, size_t);
+                       value = va_arg(args, u32);
+                       length = 4;
+                       break;
+               case 's':
+                       offset = va_arg(args, size_t);
+                       data = va_arg(args, u8 *);
+                       length = va_arg(args, u32);
+                       break;
+               default:
+                       debug("Couldn't recognize format string\n");
+                       va_end(args);
+                       return -1;
+               }
+
+               if (offset + length > size) {
+                       va_end(args);
+                       return -1;
+               }
+
+               switch (*format) {
+               case 'b':
+                       str[offset] = value;
+                       break;
+               case 'w':
+                       put_unaligned_be16(value, str + offset);
+                       break;
+               case 'd':
+                       put_unaligned_be32(value, str + offset);
+                       break;
+               case 's':
+                       memcpy(str + offset, data, length);
+                       break;
+               }
+       }
+       va_end(args);
+
+       return 0;
+}
+
+int unpack_byte_string(const u8 *str, size_t size, const char *format, ...)
+{
+       va_list args;
+       size_t offset = 0, length = 0;
+       u8 *ptr8 = NULL;
+       u16 *ptr16 = NULL;
+       u32 *ptr32 = NULL;
+
+       va_start(args, format);
+       for (; *format; format++) {
+               switch (*format) {
+               case 'b':
+                       offset = va_arg(args, size_t);
+                       ptr8 = va_arg(args, u8 *);
+                       length = 1;
+                       break;
+               case 'w':
+                       offset = va_arg(args, size_t);
+                       ptr16 = va_arg(args, u16 *);
+                       length = 2;
+                       break;
+               case 'd':
+                       offset = va_arg(args, size_t);
+                       ptr32 = va_arg(args, u32 *);
+                       length = 4;
+                       break;
+               case 's':
+                       offset = va_arg(args, size_t);
+                       ptr8 = va_arg(args, u8 *);
+                       length = va_arg(args, u32);
+                       break;
+               default:
+                       va_end(args);
+                       debug("Couldn't recognize format string\n");
+                       return -1;
+               }
+
+               if (offset + length > size) {
+                       va_end(args);
+                       return -1;
+               }
+
+               switch (*format) {
+               case 'b':
+                       *ptr8 = str[offset];
+                       break;
+               case 'w':
+                       *ptr16 = get_unaligned_be16(str + offset);
+                       break;
+               case 'd':
+                       *ptr32 = get_unaligned_be32(str + offset);
+                       break;
+               case 's':
+                       memcpy(ptr8, str + offset, length);
+                       break;
+               }
+       }
+       va_end(args);
+
+       return 0;
+}
+
+u32 tpm_command_size(const void *command)
+{
+       const size_t command_size_offset = 2;
+
+       return get_unaligned_be32(command + command_size_offset);
+}
+
+u32 tpm_return_code(const void *response)
+{
+       const size_t return_code_offset = 6;
+
+       return get_unaligned_be32(response + return_code_offset);
+}
+
+u32 tpm_sendrecv_command(const void *command, void *response, size_t *size_ptr)
+{
+       struct udevice *dev;
+       int err, ret;
+       u8 response_buffer[COMMAND_BUFFER_SIZE];
+       size_t response_length;
+
+       if (response) {
+               response_length = *size_ptr;
+       } else {
+               response = response_buffer;
+               response_length = sizeof(response_buffer);
+       }
+
+       ret = uclass_first_device_err(UCLASS_TPM, &dev);
+       if (ret)
+               return ret;
+       err = tpm_xfer(dev, command, tpm_command_size(command),
+                      response, &response_length);
+
+       if (err < 0)
+               return TPM_LIB_ERROR;
+       if (size_ptr)
+               *size_ptr = response_length;
+
+       return tpm_return_code(response);
+}
+
+int tpm_init(void)
+{
+       struct udevice *dev;
+       int err;
+
+       err = uclass_first_device_err(UCLASS_TPM, &dev);
+       if (err)
+               return err;
+
+       return tpm_open(dev);
+}
diff --git a/lib/tpm-utils.h b/lib/tpm-utils.h
new file mode 100644 (file)
index 0000000..bc98d1e
--- /dev/null
@@ -0,0 +1,95 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (c) 2013 The Chromium OS Authors.
+ * Coypright (c) 2013 Guntermann & Drunck GmbH
+ */
+
+#ifndef __TPM_UTILS_H
+#define __TPM_UTILS_H
+
+#define COMMAND_BUFFER_SIZE 256
+
+/* Internal error of TPM command library */
+#define TPM_LIB_ERROR ((u32)~0u)
+
+/**
+ * tpm_open() - Request access to locality 0 for the caller
+ *
+ * After all commands have been completed the caller is supposed to
+ * call tpm_close().
+ *
+ * Returns 0 on success, -ve on failure.
+ */
+int tpm_open(struct udevice *dev);
+
+/**
+ * tpm_close() - Close the current session
+ *
+ * Releasing the locked locality. Returns 0 on success, -ve 1 on
+ * failure (in case lock removal did not succeed).
+ */
+int tpm_close(struct udevice *dev);
+
+/**
+ * Pack data into a byte string.  The data types are specified in
+ * the format string: 'b' means unsigned byte, 'w' unsigned word,
+ * 'd' unsigned double word, and 's' byte string.  The data are a
+ * series of offsets and values (for type byte string there are also
+ * lengths).  The data values are packed into the byte string
+ * sequentially, and so a latter value could over-write a former
+ * value.
+ *
+ * @param str          output string
+ * @param size         size of output string
+ * @param format       format string
+ * @param ...          data points
+ * @return 0 on success, non-0 on error
+ */
+int pack_byte_string(u8 *str, size_t size, const char *format, ...);
+
+/**
+ * Unpack data from a byte string.  The data types are specified in
+ * the format string: 'b' means unsigned byte, 'w' unsigned word,
+ * 'd' unsigned double word, and 's' byte string.  The data are a
+ * series of offsets and pointers (for type byte string there are also
+ * lengths).
+ *
+ * @param str          output string
+ * @param size         size of output string
+ * @param format       format string
+ * @param ...          data points
+ * @return 0 on success, non-0 on error
+ */
+int unpack_byte_string(const u8 *str, size_t size, const char *format, ...);
+
+/**
+ * Get TPM command size.
+ *
+ * @param command      byte string of TPM command
+ * @return command size of the TPM command
+ */
+u32 tpm_command_size(const void *command);
+
+/**
+ * Get TPM response return code, which is one of TPM_RESULT values.
+ *
+ * @param response     byte string of TPM response
+ * @return return code of the TPM response
+ */
+u32 tpm_return_code(const void *response);
+
+/**
+ * Send a TPM command and return response's return code, and optionally
+ * return response to caller.
+ *
+ * @param command      byte string of TPM command
+ * @param response     output buffer for TPM response, or NULL if the
+ *                     caller does not care about it
+ * @param size_ptr     output buffer size (input parameter) and TPM
+ *                     response length (output parameter); this parameter
+ *                     is a bidirectional
+ * @return return code of the TPM response
+ */
+u32 tpm_sendrecv_command(const void *command, void *response, size_t *size_ptr);
+
+#endif /* __TPM_UTILS_H */
diff --git a/lib/tpm-v1.c b/lib/tpm-v1.c
new file mode 100644 (file)
index 0000000..7aecb24
--- /dev/null
@@ -0,0 +1,852 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2013 The Chromium OS Authors.
+ * Coypright (c) 2013 Guntermann & Drunck GmbH
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <asm/unaligned.h>
+#include <u-boot/sha1.h>
+#include <tpm-common.h>
+#include <tpm-v1.h>
+#include "tpm-utils.h"
+
+#ifdef CONFIG_TPM_AUTH_SESSIONS
+
+#ifndef CONFIG_SHA1
+#error "TPM_AUTH_SESSIONS require SHA1 to be configured, too"
+#endif /* !CONFIG_SHA1 */
+
+struct session_data {
+       int             valid;
+       u32     handle;
+       u8              nonce_even[DIGEST_LENGTH];
+       u8              nonce_odd[DIGEST_LENGTH];
+};
+
+static struct session_data oiap_session = {0, };
+
+#endif /* CONFIG_TPM_AUTH_SESSIONS */
+
+u32 tpm_startup(enum tpm_startup_type mode)
+{
+       const u8 command[12] = {
+               0x0, 0xc1, 0x0, 0x0, 0x0, 0xc, 0x0, 0x0, 0x0, 0x99, 0x0, 0x0,
+       };
+       const size_t mode_offset = 10;
+       u8 buf[COMMAND_BUFFER_SIZE];
+
+       if (pack_byte_string(buf, sizeof(buf), "sw",
+                            0, command, sizeof(command),
+                            mode_offset, mode))
+               return TPM_LIB_ERROR;
+
+       return tpm_sendrecv_command(buf, NULL, NULL);
+}
+
+u32 tpm_self_test_full(void)
+{
+       const u8 command[10] = {
+               0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x50,
+       };
+       return tpm_sendrecv_command(command, NULL, NULL);
+}
+
+u32 tpm_continue_self_test(void)
+{
+       const u8 command[10] = {
+               0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x53,
+       };
+       return tpm_sendrecv_command(command, NULL, NULL);
+}
+
+u32 tpm_nv_define_space(u32 index, u32 perm, u32 size)
+{
+       const u8 command[101] = {
+               0x0, 0xc1,              /* TPM_TAG */
+               0x0, 0x0, 0x0, 0x65,    /* parameter size */
+               0x0, 0x0, 0x0, 0xcc,    /* TPM_COMMAND_CODE */
+               /* TPM_NV_DATA_PUBLIC->... */
+               0x0, 0x18,              /* ...->TPM_STRUCTURE_TAG */
+               0, 0, 0, 0,             /* ...->TPM_NV_INDEX */
+               /* TPM_NV_DATA_PUBLIC->TPM_PCR_INFO_SHORT */
+               0x0, 0x3,
+               0, 0, 0,
+               0x1f,
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+               /* TPM_NV_DATA_PUBLIC->TPM_PCR_INFO_SHORT */
+               0x0, 0x3,
+               0, 0, 0,
+               0x1f,
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+               /* TPM_NV_ATTRIBUTES->... */
+               0x0, 0x17,              /* ...->TPM_STRUCTURE_TAG */
+               0, 0, 0, 0,             /* ...->attributes */
+               /* End of TPM_NV_ATTRIBUTES */
+               0,                      /* bReadSTClear */
+               0,                      /* bWriteSTClear */
+               0,                      /* bWriteDefine */
+               0, 0, 0, 0,             /* size */
+       };
+       const size_t index_offset = 12;
+       const size_t perm_offset = 70;
+       const size_t size_offset = 77;
+       u8 buf[COMMAND_BUFFER_SIZE];
+
+       if (pack_byte_string(buf, sizeof(buf), "sddd",
+                            0, command, sizeof(command),
+                            index_offset, index,
+                            perm_offset, perm,
+                            size_offset, size))
+               return TPM_LIB_ERROR;
+
+       return tpm_sendrecv_command(buf, NULL, NULL);
+}
+
+u32 tpm_nv_read_value(u32 index, void *data, u32 count)
+{
+       const u8 command[22] = {
+               0x0, 0xc1, 0x0, 0x0, 0x0, 0x16, 0x0, 0x0, 0x0, 0xcf,
+       };
+       const size_t index_offset = 10;
+       const size_t length_offset = 18;
+       const size_t data_size_offset = 10;
+       const size_t data_offset = 14;
+       u8 buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
+       size_t response_length = sizeof(response);
+       u32 data_size;
+       u32 err;
+
+       if (pack_byte_string(buf, sizeof(buf), "sdd",
+                            0, command, sizeof(command),
+                            index_offset, index,
+                            length_offset, count))
+               return TPM_LIB_ERROR;
+       err = tpm_sendrecv_command(buf, response, &response_length);
+       if (err)
+               return err;
+       if (unpack_byte_string(response, response_length, "d",
+                              data_size_offset, &data_size))
+               return TPM_LIB_ERROR;
+       if (data_size > count)
+               return TPM_LIB_ERROR;
+       if (unpack_byte_string(response, response_length, "s",
+                              data_offset, data, data_size))
+               return TPM_LIB_ERROR;
+
+       return 0;
+}
+
+u32 tpm_nv_write_value(u32 index, const void *data, u32 length)
+{
+       const u8 command[256] = {
+               0x0, 0xc1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xcd,
+       };
+       const size_t command_size_offset = 2;
+       const size_t index_offset = 10;
+       const size_t length_offset = 18;
+       const size_t data_offset = 22;
+       const size_t write_info_size = 12;
+       const u32 total_length =
+               TPM_REQUEST_HEADER_LENGTH + write_info_size + length;
+       u8 buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
+       size_t response_length = sizeof(response);
+       u32 err;
+
+       if (pack_byte_string(buf, sizeof(buf), "sddds",
+                            0, command, sizeof(command),
+                            command_size_offset, total_length,
+                            index_offset, index,
+                            length_offset, length,
+                            data_offset, data, length))
+               return TPM_LIB_ERROR;
+       err = tpm_sendrecv_command(buf, response, &response_length);
+       if (err)
+               return err;
+
+       return 0;
+}
+
+u32 tpm_extend(u32 index, const void *in_digest, void *out_digest)
+{
+       const u8 command[34] = {
+               0x0, 0xc1, 0x0, 0x0, 0x0, 0x22, 0x0, 0x0, 0x0, 0x14,
+       };
+       const size_t index_offset = 10;
+       const size_t in_digest_offset = 14;
+       const size_t out_digest_offset = 10;
+       u8 buf[COMMAND_BUFFER_SIZE];
+       u8 response[TPM_RESPONSE_HEADER_LENGTH + PCR_DIGEST_LENGTH];
+       size_t response_length = sizeof(response);
+       u32 err;
+
+       if (pack_byte_string(buf, sizeof(buf), "sds",
+                            0, command, sizeof(command),
+                            index_offset, index,
+                            in_digest_offset, in_digest,
+                            PCR_DIGEST_LENGTH))
+               return TPM_LIB_ERROR;
+       err = tpm_sendrecv_command(buf, response, &response_length);
+       if (err)
+               return err;
+
+       if (unpack_byte_string(response, response_length, "s",
+                              out_digest_offset, out_digest,
+                              PCR_DIGEST_LENGTH))
+               return TPM_LIB_ERROR;
+
+       return 0;
+}
+
+u32 tpm_pcr_read(u32 index, void *data, size_t count)
+{
+       const u8 command[14] = {
+               0x0, 0xc1, 0x0, 0x0, 0x0, 0xe, 0x0, 0x0, 0x0, 0x15,
+       };
+       const size_t index_offset = 10;
+       const size_t out_digest_offset = 10;
+       u8 buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
+       size_t response_length = sizeof(response);
+       u32 err;
+
+       if (count < PCR_DIGEST_LENGTH)
+               return TPM_LIB_ERROR;
+
+       if (pack_byte_string(buf, sizeof(buf), "sd",
+                            0, command, sizeof(command),
+                            index_offset, index))
+               return TPM_LIB_ERROR;
+       err = tpm_sendrecv_command(buf, response, &response_length);
+       if (err)
+               return err;
+       if (unpack_byte_string(response, response_length, "s",
+                              out_digest_offset, data, PCR_DIGEST_LENGTH))
+               return TPM_LIB_ERROR;
+
+       return 0;
+}
+
+u32 tpm_tsc_physical_presence(u16 presence)
+{
+       const u8 command[12] = {
+               0x0, 0xc1, 0x0, 0x0, 0x0, 0xc, 0x40, 0x0, 0x0, 0xa, 0x0, 0x0,
+       };
+       const size_t presence_offset = 10;
+       u8 buf[COMMAND_BUFFER_SIZE];
+
+       if (pack_byte_string(buf, sizeof(buf), "sw",
+                            0, command, sizeof(command),
+                            presence_offset, presence))
+               return TPM_LIB_ERROR;
+
+       return tpm_sendrecv_command(buf, NULL, NULL);
+}
+
+u32 tpm_read_pubek(void *data, size_t count)
+{
+       const u8 command[30] = {
+               0x0, 0xc1, 0x0, 0x0, 0x0, 0x1e, 0x0, 0x0, 0x0, 0x7c,
+       };
+       const size_t response_size_offset = 2;
+       const size_t data_offset = 10;
+       const size_t header_and_checksum_size = TPM_RESPONSE_HEADER_LENGTH + 20;
+       u8 response[COMMAND_BUFFER_SIZE + TPM_PUBEK_SIZE];
+       size_t response_length = sizeof(response);
+       u32 data_size;
+       u32 err;
+
+       err = tpm_sendrecv_command(command, response, &response_length);
+       if (err)
+               return err;
+       if (unpack_byte_string(response, response_length, "d",
+                              response_size_offset, &data_size))
+               return TPM_LIB_ERROR;
+       if (data_size < header_and_checksum_size)
+               return TPM_LIB_ERROR;
+       data_size -= header_and_checksum_size;
+       if (data_size > count)
+               return TPM_LIB_ERROR;
+       if (unpack_byte_string(response, response_length, "s",
+                              data_offset, data, data_size))
+               return TPM_LIB_ERROR;
+
+       return 0;
+}
+
+u32 tpm_force_clear(void)
+{
+       const u8 command[10] = {
+               0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x5d,
+       };
+
+       return tpm_sendrecv_command(command, NULL, NULL);
+}
+
+u32 tpm_physical_enable(void)
+{
+       const u8 command[10] = {
+               0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x6f,
+       };
+
+       return tpm_sendrecv_command(command, NULL, NULL);
+}
+
+u32 tpm_physical_disable(void)
+{
+       const u8 command[10] = {
+               0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x70,
+       };
+
+       return tpm_sendrecv_command(command, NULL, NULL);
+}
+
+u32 tpm_physical_set_deactivated(u8 state)
+{
+       const u8 command[11] = {
+               0x0, 0xc1, 0x0, 0x0, 0x0, 0xb, 0x0, 0x0, 0x0, 0x72,
+       };
+       const size_t state_offset = 10;
+       u8 buf[COMMAND_BUFFER_SIZE];
+
+       if (pack_byte_string(buf, sizeof(buf), "sb",
+                            0, command, sizeof(command),
+                            state_offset, state))
+               return TPM_LIB_ERROR;
+
+       return tpm_sendrecv_command(buf, NULL, NULL);
+}
+
+u32 tpm_get_capability(u32 cap_area, u32 sub_cap, void *cap, size_t count)
+{
+       const u8 command[22] = {
+               0x0, 0xc1,              /* TPM_TAG */
+               0x0, 0x0, 0x0, 0x16,    /* parameter size */
+               0x0, 0x0, 0x0, 0x65,    /* TPM_COMMAND_CODE */
+               0x0, 0x0, 0x0, 0x0,     /* TPM_CAPABILITY_AREA */
+               0x0, 0x0, 0x0, 0x4,     /* subcap size */
+               0x0, 0x0, 0x0, 0x0,     /* subcap value */
+       };
+       const size_t cap_area_offset = 10;
+       const size_t sub_cap_offset = 18;
+       const size_t cap_offset = 14;
+       const size_t cap_size_offset = 10;
+       u8 buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
+       size_t response_length = sizeof(response);
+       u32 cap_size;
+       u32 err;
+
+       if (pack_byte_string(buf, sizeof(buf), "sdd",
+                            0, command, sizeof(command),
+                            cap_area_offset, cap_area,
+                            sub_cap_offset, sub_cap))
+               return TPM_LIB_ERROR;
+       err = tpm_sendrecv_command(buf, response, &response_length);
+       if (err)
+               return err;
+       if (unpack_byte_string(response, response_length, "d",
+                              cap_size_offset, &cap_size))
+               return TPM_LIB_ERROR;
+       if (cap_size > response_length || cap_size > count)
+               return TPM_LIB_ERROR;
+       if (unpack_byte_string(response, response_length, "s",
+                              cap_offset, cap, cap_size))
+               return TPM_LIB_ERROR;
+
+       return 0;
+}
+
+u32 tpm_get_permanent_flags(struct tpm_permanent_flags *pflags)
+{
+       const u8 command[22] = {
+               0x0, 0xc1,              /* TPM_TAG */
+               0x0, 0x0, 0x0, 0x16,    /* parameter size */
+               0x0, 0x0, 0x0, 0x65,    /* TPM_COMMAND_CODE */
+               0x0, 0x0, 0x0, 0x4,     /* TPM_CAP_FLAG_PERM */
+               0x0, 0x0, 0x0, 0x4,     /* subcap size */
+               0x0, 0x0, 0x1, 0x8,     /* subcap value */
+       };
+       const size_t data_size_offset = TPM_HEADER_SIZE;
+       const size_t data_offset = TPM_HEADER_SIZE + sizeof(u32);
+       u8 response[COMMAND_BUFFER_SIZE];
+       size_t response_length = sizeof(response);
+       u32 err;
+       u32 data_size;
+
+       err = tpm_sendrecv_command(command, response, &response_length);
+       if (err)
+               return err;
+       if (unpack_byte_string(response, response_length, "d",
+                              data_size_offset, &data_size))
+               return TPM_LIB_ERROR;
+       if (data_size < sizeof(*pflags))
+               return TPM_LIB_ERROR;
+       if (unpack_byte_string(response, response_length, "s",
+                              data_offset, pflags, sizeof(*pflags)))
+               return TPM_LIB_ERROR;
+
+       return 0;
+}
+
+u32 tpm_get_permissions(u32 index, u32 *perm)
+{
+       const u8 command[22] = {
+               0x0, 0xc1,              /* TPM_TAG */
+               0x0, 0x0, 0x0, 0x16,    /* parameter size */
+               0x0, 0x0, 0x0, 0x65,    /* TPM_COMMAND_CODE */
+               0x0, 0x0, 0x0, 0x11,
+               0x0, 0x0, 0x0, 0x4,
+       };
+       const size_t index_offset = 18;
+       const size_t perm_offset = 60;
+       u8 buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
+       size_t response_length = sizeof(response);
+       u32 err;
+
+       if (pack_byte_string(buf, sizeof(buf), "d", 0, command, sizeof(command),
+                            index_offset, index))
+               return TPM_LIB_ERROR;
+       err = tpm_sendrecv_command(buf, response, &response_length);
+       if (err)
+               return err;
+       if (unpack_byte_string(response, response_length, "d",
+                              perm_offset, perm))
+               return TPM_LIB_ERROR;
+
+       return 0;
+}
+
+#ifdef CONFIG_TPM_FLUSH_RESOURCES
+u32 tpm_flush_specific(u32 key_handle, u32 resource_type)
+{
+       const u8 command[18] = {
+               0x00, 0xc1,             /* TPM_TAG */
+               0x00, 0x00, 0x00, 0x12, /* parameter size */
+               0x00, 0x00, 0x00, 0xba, /* TPM_COMMAND_CODE */
+               0x00, 0x00, 0x00, 0x00, /* key handle */
+               0x00, 0x00, 0x00, 0x00, /* resource type */
+       };
+       const size_t key_handle_offset = 10;
+       const size_t resource_type_offset = 14;
+       u8 buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
+       size_t response_length = sizeof(response);
+       u32 err;
+
+       if (pack_byte_string(buf, sizeof(buf), "sdd",
+                            0, command, sizeof(command),
+                            key_handle_offset, key_handle,
+                            resource_type_offset, resource_type))
+               return TPM_LIB_ERROR;
+
+       err = tpm_sendrecv_command(buf, response, &response_length);
+       if (err)
+               return err;
+       return 0;
+}
+#endif /* CONFIG_TPM_FLUSH_RESOURCES */
+
+#ifdef CONFIG_TPM_AUTH_SESSIONS
+
+/**
+ * Fill an authentication block in a request.
+ * This func can create the first as well as the second auth block (for
+ * double authorized commands).
+ *
+ * @param request      pointer to the request (w/ uninitialised auth data)
+ * @param request_len0 length of the request without auth data
+ * @param handles_len  length of the handles area in request
+ * @param auth_session pointer to the (valid) auth session to be used
+ * @param request_auth pointer to the auth block of the request to be filled
+ * @param auth         authentication data (HMAC key)
+ */
+static u32 create_request_auth(const void *request, size_t request_len0,
+                              size_t handles_len,
+                              struct session_data *auth_session,
+                              void *request_auth, const void *auth)
+{
+       u8 hmac_data[DIGEST_LENGTH * 3 + 1];
+       sha1_context hash_ctx;
+       const size_t command_code_offset = 6;
+       const size_t auth_nonce_odd_offset = 4;
+       const size_t auth_continue_offset = 24;
+       const size_t auth_auth_offset = 25;
+
+       if (!auth_session || !auth_session->valid)
+               return TPM_LIB_ERROR;
+
+       sha1_starts(&hash_ctx);
+       sha1_update(&hash_ctx, request + command_code_offset, 4);
+       if (request_len0 > TPM_REQUEST_HEADER_LENGTH + handles_len)
+               sha1_update(&hash_ctx,
+                           request + TPM_REQUEST_HEADER_LENGTH + handles_len,
+                           request_len0 - TPM_REQUEST_HEADER_LENGTH
+                           - handles_len);
+       sha1_finish(&hash_ctx, hmac_data);
+
+       sha1_starts(&hash_ctx);
+       sha1_update(&hash_ctx, auth_session->nonce_odd, DIGEST_LENGTH);
+       sha1_update(&hash_ctx, hmac_data, sizeof(hmac_data));
+       sha1_finish(&hash_ctx, auth_session->nonce_odd);
+
+       if (pack_byte_string(request_auth, TPM_REQUEST_AUTH_LENGTH, "dsb",
+                            0, auth_session->handle,
+                            auth_nonce_odd_offset, auth_session->nonce_odd,
+                            DIGEST_LENGTH,
+                            auth_continue_offset, 1))
+               return TPM_LIB_ERROR;
+       if (pack_byte_string(hmac_data, sizeof(hmac_data), "ss",
+                            DIGEST_LENGTH,
+                            auth_session->nonce_even,
+                            DIGEST_LENGTH,
+                            2 * DIGEST_LENGTH,
+                            request_auth + auth_nonce_odd_offset,
+                            DIGEST_LENGTH + 1))
+               return TPM_LIB_ERROR;
+       sha1_hmac(auth, DIGEST_LENGTH, hmac_data, sizeof(hmac_data),
+                 request_auth + auth_auth_offset);
+
+       return TPM_SUCCESS;
+}
+
+/**
+ * Verify an authentication block in a response.
+ * Since this func updates the nonce_even in the session data it has to be
+ * called when receiving a succesfull AUTH response.
+ * This func can verify the first as well as the second auth block (for
+ * double authorized commands).
+ *
+ * @param command_code command code of the request
+ * @param response     pointer to the request (w/ uninitialised auth data)
+ * @param handles_len  length of the handles area in response
+ * @param auth_session pointer to the (valid) auth session to be used
+ * @param response_auth        pointer to the auth block of the response to be verified
+ * @param auth         authentication data (HMAC key)
+ */
+static u32 verify_response_auth(u32 command_code, const void *response,
+                               size_t response_len0, size_t handles_len,
+                               struct session_data *auth_session,
+                               const void *response_auth, const void *auth)
+{
+       u8 hmac_data[DIGEST_LENGTH * 3 + 1];
+       u8 computed_auth[DIGEST_LENGTH];
+       sha1_context hash_ctx;
+       const size_t return_code_offset = 6;
+       const size_t auth_continue_offset = 20;
+       const size_t auth_auth_offset = 21;
+       u8 auth_continue;
+
+       if (!auth_session || !auth_session->valid)
+               return TPM_AUTHFAIL;
+       if (pack_byte_string(hmac_data, sizeof(hmac_data), "d",
+                            0, command_code))
+               return TPM_LIB_ERROR;
+       if (response_len0 < TPM_RESPONSE_HEADER_LENGTH)
+               return TPM_LIB_ERROR;
+
+       sha1_starts(&hash_ctx);
+       sha1_update(&hash_ctx, response + return_code_offset, 4);
+       sha1_update(&hash_ctx, hmac_data, 4);
+       if (response_len0 > TPM_RESPONSE_HEADER_LENGTH + handles_len)
+               sha1_update(&hash_ctx,
+                           response + TPM_RESPONSE_HEADER_LENGTH + handles_len,
+                           response_len0 - TPM_RESPONSE_HEADER_LENGTH
+                           - handles_len);
+       sha1_finish(&hash_ctx, hmac_data);
+
+       memcpy(auth_session->nonce_even, response_auth, DIGEST_LENGTH);
+       auth_continue = ((u8 *)response_auth)[auth_continue_offset];
+       if (pack_byte_string(hmac_data, sizeof(hmac_data), "ssb",
+                            DIGEST_LENGTH,
+                            response_auth,
+                            DIGEST_LENGTH,
+                            2 * DIGEST_LENGTH,
+                            auth_session->nonce_odd,
+                            DIGEST_LENGTH,
+                            3 * DIGEST_LENGTH,
+                            auth_continue))
+               return TPM_LIB_ERROR;
+
+       sha1_hmac(auth, DIGEST_LENGTH, hmac_data, sizeof(hmac_data),
+                 computed_auth);
+
+       if (memcmp(computed_auth, response_auth + auth_auth_offset,
+                  DIGEST_LENGTH))
+               return TPM_AUTHFAIL;
+
+       return TPM_SUCCESS;
+}
+
+u32 tpm_terminate_auth_session(u32 auth_handle)
+{
+       const u8 command[18] = {
+               0x00, 0xc1,             /* TPM_TAG */
+               0x00, 0x00, 0x00, 0x00, /* parameter size */
+               0x00, 0x00, 0x00, 0xba, /* TPM_COMMAND_CODE */
+               0x00, 0x00, 0x00, 0x00, /* TPM_HANDLE */
+               0x00, 0x00, 0x00, 0x02, /* TPM_RESOURCE_TYPE */
+       };
+       const size_t req_handle_offset = TPM_REQUEST_HEADER_LENGTH;
+       u8 request[COMMAND_BUFFER_SIZE];
+
+       if (pack_byte_string(request, sizeof(request), "sd",
+                            0, command, sizeof(command),
+                            req_handle_offset, auth_handle))
+               return TPM_LIB_ERROR;
+       if (oiap_session.valid && oiap_session.handle == auth_handle)
+               oiap_session.valid = 0;
+
+       return tpm_sendrecv_command(request, NULL, NULL);
+}
+
+u32 tpm_end_oiap(void)
+{
+       u32 err = TPM_SUCCESS;
+
+       if (oiap_session.valid)
+               err = tpm_terminate_auth_session(oiap_session.handle);
+       return err;
+}
+
+u32 tpm_oiap(u32 *auth_handle)
+{
+       const u8 command[10] = {
+               0x00, 0xc1,             /* TPM_TAG */
+               0x00, 0x00, 0x00, 0x0a, /* parameter size */
+               0x00, 0x00, 0x00, 0x0a, /* TPM_COMMAND_CODE */
+       };
+       const size_t res_auth_handle_offset = TPM_RESPONSE_HEADER_LENGTH;
+       const size_t res_nonce_even_offset = TPM_RESPONSE_HEADER_LENGTH + 4;
+       u8 response[COMMAND_BUFFER_SIZE];
+       size_t response_length = sizeof(response);
+       u32 err;
+
+       if (oiap_session.valid)
+               tpm_terminate_auth_session(oiap_session.handle);
+
+       err = tpm_sendrecv_command(command, response, &response_length);
+       if (err)
+               return err;
+       if (unpack_byte_string(response, response_length, "ds",
+                              res_auth_handle_offset, &oiap_session.handle,
+                              res_nonce_even_offset, &oiap_session.nonce_even,
+                              (u32)DIGEST_LENGTH))
+               return TPM_LIB_ERROR;
+       oiap_session.valid = 1;
+       if (auth_handle)
+               *auth_handle = oiap_session.handle;
+       return 0;
+}
+
+u32 tpm_load_key2_oiap(u32 parent_handle, const void *key, size_t key_length,
+                      const void *parent_key_usage_auth, u32 *key_handle)
+{
+       const u8 command[14] = {
+               0x00, 0xc2,             /* TPM_TAG */
+               0x00, 0x00, 0x00, 0x00, /* parameter size */
+               0x00, 0x00, 0x00, 0x41, /* TPM_COMMAND_CODE */
+               0x00, 0x00, 0x00, 0x00, /* parent handle */
+       };
+       const size_t req_size_offset = 2;
+       const size_t req_parent_handle_offset = TPM_REQUEST_HEADER_LENGTH;
+       const size_t req_key_offset = TPM_REQUEST_HEADER_LENGTH + 4;
+       const size_t res_handle_offset = TPM_RESPONSE_HEADER_LENGTH;
+       u8 request[sizeof(command) + TPM_KEY12_MAX_LENGTH +
+                  TPM_REQUEST_AUTH_LENGTH];
+       u8 response[COMMAND_BUFFER_SIZE];
+       size_t response_length = sizeof(response);
+       u32 err;
+
+       if (!oiap_session.valid) {
+               err = tpm_oiap(NULL);
+               if (err)
+                       return err;
+       }
+       if (pack_byte_string(request, sizeof(request), "sdds",
+                            0, command, sizeof(command),
+                            req_size_offset,
+                            sizeof(command) + key_length
+                            + TPM_REQUEST_AUTH_LENGTH,
+                            req_parent_handle_offset, parent_handle,
+                            req_key_offset, key, key_length
+               ))
+               return TPM_LIB_ERROR;
+
+       err = create_request_auth(request, sizeof(command) + key_length, 4,
+                                 &oiap_session,
+                                 request + sizeof(command) + key_length,
+                                 parent_key_usage_auth);
+       if (err)
+               return err;
+       err = tpm_sendrecv_command(request, response, &response_length);
+       if (err) {
+               if (err == TPM_AUTHFAIL)
+                       oiap_session.valid = 0;
+               return err;
+       }
+
+       err = verify_response_auth(0x00000041, response,
+                                  response_length - TPM_RESPONSE_AUTH_LENGTH,
+                                  4, &oiap_session,
+                                  response + response_length -
+                                  TPM_RESPONSE_AUTH_LENGTH,
+                                  parent_key_usage_auth);
+       if (err)
+               return err;
+
+       if (key_handle) {
+               if (unpack_byte_string(response, response_length, "d",
+                                      res_handle_offset, key_handle))
+                       return TPM_LIB_ERROR;
+       }
+
+       return 0;
+}
+
+u32 tpm_get_pub_key_oiap(u32 key_handle, const void *usage_auth, void *pubkey,
+                        size_t *pubkey_len)
+{
+       const u8 command[14] = {
+               0x00, 0xc2,             /* TPM_TAG */
+               0x00, 0x00, 0x00, 0x00, /* parameter size */
+               0x00, 0x00, 0x00, 0x21, /* TPM_COMMAND_CODE */
+               0x00, 0x00, 0x00, 0x00, /* key handle */
+       };
+       const size_t req_size_offset = 2;
+       const size_t req_key_handle_offset = TPM_REQUEST_HEADER_LENGTH;
+       const size_t res_pubkey_offset = TPM_RESPONSE_HEADER_LENGTH;
+       u8 request[sizeof(command) + TPM_REQUEST_AUTH_LENGTH];
+       u8 response[TPM_RESPONSE_HEADER_LENGTH + TPM_PUBKEY_MAX_LENGTH +
+                   TPM_RESPONSE_AUTH_LENGTH];
+       size_t response_length = sizeof(response);
+       u32 err;
+
+       if (!oiap_session.valid) {
+               err = tpm_oiap(NULL);
+               if (err)
+                       return err;
+       }
+       if (pack_byte_string(request, sizeof(request), "sdd",
+                            0, command, sizeof(command),
+                            req_size_offset,
+                            (u32)(sizeof(command)
+                            + TPM_REQUEST_AUTH_LENGTH),
+                            req_key_handle_offset, key_handle
+               ))
+               return TPM_LIB_ERROR;
+       err = create_request_auth(request, sizeof(command), 4, &oiap_session,
+                                 request + sizeof(command), usage_auth);
+       if (err)
+               return err;
+       err = tpm_sendrecv_command(request, response, &response_length);
+       if (err) {
+               if (err == TPM_AUTHFAIL)
+                       oiap_session.valid = 0;
+               return err;
+       }
+       err = verify_response_auth(0x00000021, response,
+                                  response_length - TPM_RESPONSE_AUTH_LENGTH,
+                                  0, &oiap_session,
+                                  response + response_length -
+                                  TPM_RESPONSE_AUTH_LENGTH,
+                                  usage_auth);
+       if (err)
+               return err;
+
+       if (pubkey) {
+               if ((response_length - TPM_RESPONSE_HEADER_LENGTH
+                    - TPM_RESPONSE_AUTH_LENGTH) > *pubkey_len)
+                       return TPM_LIB_ERROR;
+               *pubkey_len = response_length - TPM_RESPONSE_HEADER_LENGTH
+                       - TPM_RESPONSE_AUTH_LENGTH;
+               memcpy(pubkey, response + res_pubkey_offset,
+                      response_length - TPM_RESPONSE_HEADER_LENGTH
+                      - TPM_RESPONSE_AUTH_LENGTH);
+       }
+
+       return 0;
+}
+
+#ifdef CONFIG_TPM_LOAD_KEY_BY_SHA1
+u32 tpm_find_key_sha1(const u8 auth[20], const u8 pubkey_digest[20],
+                     u32 *handle)
+{
+       u16 key_count;
+       u32 key_handles[10];
+       u8 buf[288];
+       u8 *ptr;
+       u32 err;
+       u8 digest[20];
+       size_t buf_len;
+       unsigned int i;
+
+       /* fetch list of already loaded keys in the TPM */
+       err = tpm_get_capability(TPM_CAP_HANDLE, TPM_RT_KEY, buf, sizeof(buf));
+       if (err)
+               return -1;
+       key_count = get_unaligned_be16(buf);
+       ptr = buf + 2;
+       for (i = 0; i < key_count; ++i, ptr += 4)
+               key_handles[i] = get_unaligned_be32(ptr);
+
+       /* now search a(/ the) key which we can access with the given auth */
+       for (i = 0; i < key_count; ++i) {
+               buf_len = sizeof(buf);
+               err = tpm_get_pub_key_oiap(key_handles[i], auth, buf, &buf_len);
+               if (err && err != TPM_AUTHFAIL)
+                       return -1;
+               if (err)
+                       continue;
+               sha1_csum(buf, buf_len, digest);
+               if (!memcmp(digest, pubkey_digest, 20)) {
+                       *handle = key_handles[i];
+                       return 0;
+               }
+       }
+       return 1;
+}
+#endif /* CONFIG_TPM_LOAD_KEY_BY_SHA1 */
+
+#endif /* CONFIG_TPM_AUTH_SESSIONS */
+
+u32 tpm_get_random(void *data, u32 count)
+{
+       const u8 command[14] = {
+               0x0, 0xc1,              /* TPM_TAG */
+               0x0, 0x0, 0x0, 0xe,     /* parameter size */
+               0x0, 0x0, 0x0, 0x46,    /* TPM_COMMAND_CODE */
+       };
+       const size_t length_offset = 10;
+       const size_t data_size_offset = 10;
+       const size_t data_offset = 14;
+       u8 buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
+       size_t response_length = sizeof(response);
+       u32 data_size;
+       u8 *out = data;
+
+       while (count > 0) {
+               u32 this_bytes = min((size_t)count,
+                                    sizeof(response) - data_offset);
+               u32 err;
+
+               if (pack_byte_string(buf, sizeof(buf), "sd",
+                                    0, command, sizeof(command),
+                                    length_offset, this_bytes))
+                       return TPM_LIB_ERROR;
+               err = tpm_sendrecv_command(buf, response, &response_length);
+               if (err)
+                       return err;
+               if (unpack_byte_string(response, response_length, "d",
+                                      data_size_offset, &data_size))
+                       return TPM_LIB_ERROR;
+               if (data_size > count)
+                       return TPM_LIB_ERROR;
+               if (unpack_byte_string(response, response_length, "s",
+                                      data_offset, out, data_size))
+                       return TPM_LIB_ERROR;
+
+               count -= data_size;
+               out += data_size;
+       }
+
+       return 0;
+}
diff --git a/lib/tpm.c b/lib/tpm.c
deleted file mode 100644 (file)
index 899528e..0000000
--- a/lib/tpm.c
+++ /dev/null
@@ -1,1096 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Copyright (c) 2013 The Chromium OS Authors.
- * Coypright (c) 2013 Guntermann & Drunck GmbH
- */
-
-#include <common.h>
-#include <dm.h>
-#include <tpm.h>
-#include <asm/unaligned.h>
-#include <u-boot/sha1.h>
-
-/* Internal error of TPM command library */
-#define TPM_LIB_ERROR  ((u32)~0u)
-
-/* Useful constants */
-enum {
-       COMMAND_BUFFER_SIZE             = 256,
-       TPM_REQUEST_HEADER_LENGTH       = 10,
-       TPM_RESPONSE_HEADER_LENGTH      = 10,
-       PCR_DIGEST_LENGTH               = 20,
-       DIGEST_LENGTH                   = 20,
-       TPM_REQUEST_AUTH_LENGTH         = 45,
-       TPM_RESPONSE_AUTH_LENGTH        = 41,
-       /* some max lengths, valid for RSA keys <= 2048 bits */
-       TPM_KEY12_MAX_LENGTH            = 618,
-       TPM_PUBKEY_MAX_LENGTH           = 288,
-};
-
-#ifdef CONFIG_TPM_AUTH_SESSIONS
-
-#ifndef CONFIG_SHA1
-#error "TPM_AUTH_SESSIONS require SHA1 to be configured, too"
-#endif /* !CONFIG_SHA1 */
-
-struct session_data {
-       int             valid;
-       u32     handle;
-       u8              nonce_even[DIGEST_LENGTH];
-       u8              nonce_odd[DIGEST_LENGTH];
-};
-
-static struct session_data oiap_session = {0, };
-
-#endif /* CONFIG_TPM_AUTH_SESSIONS */
-
-/**
- * Pack data into a byte string.  The data types are specified in
- * the format string: 'b' means unsigned byte, 'w' unsigned word,
- * 'd' unsigned double word, and 's' byte string.  The data are a
- * series of offsets and values (for type byte string there are also
- * lengths).  The data values are packed into the byte string
- * sequentially, and so a latter value could over-write a former
- * value.
- *
- * @param str          output string
- * @param size         size of output string
- * @param format       format string
- * @param ...          data points
- * @return 0 on success, non-0 on error
- */
-int pack_byte_string(u8 *str, size_t size, const char *format, ...)
-{
-       va_list args;
-       size_t offset = 0, length = 0;
-       u8 *data = NULL;
-       u32 value = 0;
-
-       va_start(args, format);
-       for (; *format; format++) {
-               switch (*format) {
-               case 'b':
-                       offset = va_arg(args, size_t);
-                       value = va_arg(args, int);
-                       length = 1;
-                       break;
-               case 'w':
-                       offset = va_arg(args, size_t);
-                       value = va_arg(args, int);
-                       length = 2;
-                       break;
-               case 'd':
-                       offset = va_arg(args, size_t);
-                       value = va_arg(args, u32);
-                       length = 4;
-                       break;
-               case 's':
-                       offset = va_arg(args, size_t);
-                       data = va_arg(args, u8 *);
-                       length = va_arg(args, u32);
-                       break;
-               default:
-                       debug("Couldn't recognize format string\n");
-                       va_end(args);
-                       return -1;
-               }
-
-               if (offset + length > size) {
-                       va_end(args);
-                       return -1;
-               }
-
-               switch (*format) {
-               case 'b':
-                       str[offset] = value;
-                       break;
-               case 'w':
-                       put_unaligned_be16(value, str + offset);
-                       break;
-               case 'd':
-                       put_unaligned_be32(value, str + offset);
-                       break;
-               case 's':
-                       memcpy(str + offset, data, length);
-                       break;
-               }
-       }
-       va_end(args);
-
-       return 0;
-}
-
-/**
- * Unpack data from a byte string.  The data types are specified in
- * the format string: 'b' means unsigned byte, 'w' unsigned word,
- * 'd' unsigned double word, and 's' byte string.  The data are a
- * series of offsets and pointers (for type byte string there are also
- * lengths).
- *
- * @param str          output string
- * @param size         size of output string
- * @param format       format string
- * @param ...          data points
- * @return 0 on success, non-0 on error
- */
-int unpack_byte_string(const u8 *str, size_t size, const char *format, ...)
-{
-       va_list args;
-       size_t offset = 0, length = 0;
-       u8 *ptr8 = NULL;
-       u16 *ptr16 = NULL;
-       u32 *ptr32 = NULL;
-
-       va_start(args, format);
-       for (; *format; format++) {
-               switch (*format) {
-               case 'b':
-                       offset = va_arg(args, size_t);
-                       ptr8 = va_arg(args, u8 *);
-                       length = 1;
-                       break;
-               case 'w':
-                       offset = va_arg(args, size_t);
-                       ptr16 = va_arg(args, u16 *);
-                       length = 2;
-                       break;
-               case 'd':
-                       offset = va_arg(args, size_t);
-                       ptr32 = va_arg(args, u32 *);
-                       length = 4;
-                       break;
-               case 's':
-                       offset = va_arg(args, size_t);
-                       ptr8 = va_arg(args, u8 *);
-                       length = va_arg(args, u32);
-                       break;
-               default:
-                       va_end(args);
-                       debug("Couldn't recognize format string\n");
-                       return -1;
-               }
-
-               if (offset + length > size) {
-                       va_end(args);
-                       return -1;
-               }
-
-               switch (*format) {
-               case 'b':
-                       *ptr8 = str[offset];
-                       break;
-               case 'w':
-                       *ptr16 = get_unaligned_be16(str + offset);
-                       break;
-               case 'd':
-                       *ptr32 = get_unaligned_be32(str + offset);
-                       break;
-               case 's':
-                       memcpy(ptr8, str + offset, length);
-                       break;
-               }
-       }
-       va_end(args);
-
-       return 0;
-}
-
-/**
- * Get TPM command size.
- *
- * @param command      byte string of TPM command
- * @return command size of the TPM command
- */
-static u32 tpm_command_size(const void *command)
-{
-       const size_t command_size_offset = 2;
-
-       return get_unaligned_be32(command + command_size_offset);
-}
-
-/**
- * Get TPM response return code, which is one of TPM_RESULT values.
- *
- * @param response     byte string of TPM response
- * @return return code of the TPM response
- */
-static u32 tpm_return_code(const void *response)
-{
-       const size_t return_code_offset = 6;
-
-       return get_unaligned_be32(response + return_code_offset);
-}
-
-/**
- * Send a TPM command and return response's return code, and optionally
- * return response to caller.
- *
- * @param command      byte string of TPM command
- * @param response     output buffer for TPM response, or NULL if the
- *                     caller does not care about it
- * @param size_ptr     output buffer size (input parameter) and TPM
- *                     response length (output parameter); this parameter
- *                     is a bidirectional
- * @return return code of the TPM response
- */
-static u32 tpm_sendrecv_command(const void *command, void *response,
-                               size_t *size_ptr)
-{
-       struct udevice *dev;
-       int err, ret;
-       u8 response_buffer[COMMAND_BUFFER_SIZE];
-       size_t response_length;
-
-       if (response) {
-               response_length = *size_ptr;
-       } else {
-               response = response_buffer;
-               response_length = sizeof(response_buffer);
-       }
-
-       ret = uclass_first_device_err(UCLASS_TPM, &dev);
-       if (ret)
-               return ret;
-       err = tpm_xfer(dev, command, tpm_command_size(command),
-                      response, &response_length);
-
-       if (err < 0)
-               return TPM_LIB_ERROR;
-       if (size_ptr)
-               *size_ptr = response_length;
-
-       return tpm_return_code(response);
-}
-
-int tpm_init(void)
-{
-       int err;
-       struct udevice *dev;
-
-       err = uclass_first_device_err(UCLASS_TPM, &dev);
-       if (err)
-               return err;
-       return tpm_open(dev);
-}
-
-u32 tpm_startup(enum tpm_startup_type mode)
-{
-       const u8 command[12] = {
-               0x0, 0xc1, 0x0, 0x0, 0x0, 0xc, 0x0, 0x0, 0x0, 0x99, 0x0, 0x0,
-       };
-       const size_t mode_offset = 10;
-       u8 buf[COMMAND_BUFFER_SIZE];
-
-       if (pack_byte_string(buf, sizeof(buf), "sw",
-                            0, command, sizeof(command),
-                            mode_offset, mode))
-               return TPM_LIB_ERROR;
-
-       return tpm_sendrecv_command(buf, NULL, NULL);
-}
-
-u32 tpm_self_test_full(void)
-{
-       const u8 command[10] = {
-               0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x50,
-       };
-       return tpm_sendrecv_command(command, NULL, NULL);
-}
-
-u32 tpm_continue_self_test(void)
-{
-       const u8 command[10] = {
-               0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x53,
-       };
-       return tpm_sendrecv_command(command, NULL, NULL);
-}
-
-u32 tpm_nv_define_space(u32 index, u32 perm, u32 size)
-{
-       const u8 command[101] = {
-               0x0, 0xc1,              /* TPM_TAG */
-               0x0, 0x0, 0x0, 0x65,    /* parameter size */
-               0x0, 0x0, 0x0, 0xcc,    /* TPM_COMMAND_CODE */
-               /* TPM_NV_DATA_PUBLIC->... */
-               0x0, 0x18,              /* ...->TPM_STRUCTURE_TAG */
-               0, 0, 0, 0,             /* ...->TPM_NV_INDEX */
-               /* TPM_NV_DATA_PUBLIC->TPM_PCR_INFO_SHORT */
-               0x0, 0x3,
-               0, 0, 0,
-               0x1f,
-               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-               /* TPM_NV_DATA_PUBLIC->TPM_PCR_INFO_SHORT */
-               0x0, 0x3,
-               0, 0, 0,
-               0x1f,
-               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-               /* TPM_NV_ATTRIBUTES->... */
-               0x0, 0x17,              /* ...->TPM_STRUCTURE_TAG */
-               0, 0, 0, 0,             /* ...->attributes */
-               /* End of TPM_NV_ATTRIBUTES */
-               0,                      /* bReadSTClear */
-               0,                      /* bWriteSTClear */
-               0,                      /* bWriteDefine */
-               0, 0, 0, 0,             /* size */
-       };
-       const size_t index_offset = 12;
-       const size_t perm_offset = 70;
-       const size_t size_offset = 77;
-       u8 buf[COMMAND_BUFFER_SIZE];
-
-       if (pack_byte_string(buf, sizeof(buf), "sddd",
-                            0, command, sizeof(command),
-                            index_offset, index,
-                            perm_offset, perm,
-                            size_offset, size))
-               return TPM_LIB_ERROR;
-
-       return tpm_sendrecv_command(buf, NULL, NULL);
-}
-
-u32 tpm_nv_read_value(u32 index, void *data, u32 count)
-{
-       const u8 command[22] = {
-               0x0, 0xc1, 0x0, 0x0, 0x0, 0x16, 0x0, 0x0, 0x0, 0xcf,
-       };
-       const size_t index_offset = 10;
-       const size_t length_offset = 18;
-       const size_t data_size_offset = 10;
-       const size_t data_offset = 14;
-       u8 buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
-       size_t response_length = sizeof(response);
-       u32 data_size;
-       u32 err;
-
-       if (pack_byte_string(buf, sizeof(buf), "sdd",
-                            0, command, sizeof(command),
-                            index_offset, index,
-                            length_offset, count))
-               return TPM_LIB_ERROR;
-       err = tpm_sendrecv_command(buf, response, &response_length);
-       if (err)
-               return err;
-       if (unpack_byte_string(response, response_length, "d",
-                              data_size_offset, &data_size))
-               return TPM_LIB_ERROR;
-       if (data_size > count)
-               return TPM_LIB_ERROR;
-       if (unpack_byte_string(response, response_length, "s",
-                              data_offset, data, data_size))
-               return TPM_LIB_ERROR;
-
-       return 0;
-}
-
-u32 tpm_nv_write_value(u32 index, const void *data, u32 length)
-{
-       const u8 command[256] = {
-               0x0, 0xc1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xcd,
-       };
-       const size_t command_size_offset = 2;
-       const size_t index_offset = 10;
-       const size_t length_offset = 18;
-       const size_t data_offset = 22;
-       const size_t write_info_size = 12;
-       const u32 total_length =
-               TPM_REQUEST_HEADER_LENGTH + write_info_size + length;
-       u8 buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
-       size_t response_length = sizeof(response);
-       u32 err;
-
-       if (pack_byte_string(buf, sizeof(buf), "sddds",
-                            0, command, sizeof(command),
-                            command_size_offset, total_length,
-                            index_offset, index,
-                            length_offset, length,
-                            data_offset, data, length))
-               return TPM_LIB_ERROR;
-       err = tpm_sendrecv_command(buf, response, &response_length);
-       if (err)
-               return err;
-
-       return 0;
-}
-
-u32 tpm_extend(u32 index, const void *in_digest, void *out_digest)
-{
-       const u8 command[34] = {
-               0x0, 0xc1, 0x0, 0x0, 0x0, 0x22, 0x0, 0x0, 0x0, 0x14,
-       };
-       const size_t index_offset = 10;
-       const size_t in_digest_offset = 14;
-       const size_t out_digest_offset = 10;
-       u8 buf[COMMAND_BUFFER_SIZE];
-       u8 response[TPM_RESPONSE_HEADER_LENGTH + PCR_DIGEST_LENGTH];
-       size_t response_length = sizeof(response);
-       u32 err;
-
-       if (pack_byte_string(buf, sizeof(buf), "sds",
-                            0, command, sizeof(command),
-                            index_offset, index,
-                            in_digest_offset, in_digest,
-                            PCR_DIGEST_LENGTH))
-               return TPM_LIB_ERROR;
-       err = tpm_sendrecv_command(buf, response, &response_length);
-       if (err)
-               return err;
-
-       if (unpack_byte_string(response, response_length, "s",
-                              out_digest_offset, out_digest,
-                              PCR_DIGEST_LENGTH))
-               return TPM_LIB_ERROR;
-
-       return 0;
-}
-
-u32 tpm_pcr_read(u32 index, void *data, size_t count)
-{
-       const u8 command[14] = {
-               0x0, 0xc1, 0x0, 0x0, 0x0, 0xe, 0x0, 0x0, 0x0, 0x15,
-       };
-       const size_t index_offset = 10;
-       const size_t out_digest_offset = 10;
-       u8 buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
-       size_t response_length = sizeof(response);
-       u32 err;
-
-       if (count < PCR_DIGEST_LENGTH)
-               return TPM_LIB_ERROR;
-
-       if (pack_byte_string(buf, sizeof(buf), "sd",
-                            0, command, sizeof(command),
-                            index_offset, index))
-               return TPM_LIB_ERROR;
-       err = tpm_sendrecv_command(buf, response, &response_length);
-       if (err)
-               return err;
-       if (unpack_byte_string(response, response_length, "s",
-                              out_digest_offset, data, PCR_DIGEST_LENGTH))
-               return TPM_LIB_ERROR;
-
-       return 0;
-}
-
-u32 tpm_tsc_physical_presence(u16 presence)
-{
-       const u8 command[12] = {
-               0x0, 0xc1, 0x0, 0x0, 0x0, 0xc, 0x40, 0x0, 0x0, 0xa, 0x0, 0x0,
-       };
-       const size_t presence_offset = 10;
-       u8 buf[COMMAND_BUFFER_SIZE];
-
-       if (pack_byte_string(buf, sizeof(buf), "sw",
-                            0, command, sizeof(command),
-                            presence_offset, presence))
-               return TPM_LIB_ERROR;
-
-       return tpm_sendrecv_command(buf, NULL, NULL);
-}
-
-u32 tpm_read_pubek(void *data, size_t count)
-{
-       const u8 command[30] = {
-               0x0, 0xc1, 0x0, 0x0, 0x0, 0x1e, 0x0, 0x0, 0x0, 0x7c,
-       };
-       const size_t response_size_offset = 2;
-       const size_t data_offset = 10;
-       const size_t header_and_checksum_size = TPM_RESPONSE_HEADER_LENGTH + 20;
-       u8 response[COMMAND_BUFFER_SIZE + TPM_PUBEK_SIZE];
-       size_t response_length = sizeof(response);
-       u32 data_size;
-       u32 err;
-
-       err = tpm_sendrecv_command(command, response, &response_length);
-       if (err)
-               return err;
-       if (unpack_byte_string(response, response_length, "d",
-                              response_size_offset, &data_size))
-               return TPM_LIB_ERROR;
-       if (data_size < header_and_checksum_size)
-               return TPM_LIB_ERROR;
-       data_size -= header_and_checksum_size;
-       if (data_size > count)
-               return TPM_LIB_ERROR;
-       if (unpack_byte_string(response, response_length, "s",
-                              data_offset, data, data_size))
-               return TPM_LIB_ERROR;
-
-       return 0;
-}
-
-u32 tpm_force_clear(void)
-{
-       const u8 command[10] = {
-               0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x5d,
-       };
-
-       return tpm_sendrecv_command(command, NULL, NULL);
-}
-
-u32 tpm_physical_enable(void)
-{
-       const u8 command[10] = {
-               0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x6f,
-       };
-
-       return tpm_sendrecv_command(command, NULL, NULL);
-}
-
-u32 tpm_physical_disable(void)
-{
-       const u8 command[10] = {
-               0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x70,
-       };
-
-       return tpm_sendrecv_command(command, NULL, NULL);
-}
-
-u32 tpm_physical_set_deactivated(u8 state)
-{
-       const u8 command[11] = {
-               0x0, 0xc1, 0x0, 0x0, 0x0, 0xb, 0x0, 0x0, 0x0, 0x72,
-       };
-       const size_t state_offset = 10;
-       u8 buf[COMMAND_BUFFER_SIZE];
-
-       if (pack_byte_string(buf, sizeof(buf), "sb",
-                            0, command, sizeof(command),
-                            state_offset, state))
-               return TPM_LIB_ERROR;
-
-       return tpm_sendrecv_command(buf, NULL, NULL);
-}
-
-u32 tpm_get_capability(u32 cap_area, u32 sub_cap, void *cap, size_t count)
-{
-       const u8 command[22] = {
-               0x0, 0xc1,              /* TPM_TAG */
-               0x0, 0x0, 0x0, 0x16,    /* parameter size */
-               0x0, 0x0, 0x0, 0x65,    /* TPM_COMMAND_CODE */
-               0x0, 0x0, 0x0, 0x0,     /* TPM_CAPABILITY_AREA */
-               0x0, 0x0, 0x0, 0x4,     /* subcap size */
-               0x0, 0x0, 0x0, 0x0,     /* subcap value */
-       };
-       const size_t cap_area_offset = 10;
-       const size_t sub_cap_offset = 18;
-       const size_t cap_offset = 14;
-       const size_t cap_size_offset = 10;
-       u8 buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
-       size_t response_length = sizeof(response);
-       u32 cap_size;
-       u32 err;
-
-       if (pack_byte_string(buf, sizeof(buf), "sdd",
-                            0, command, sizeof(command),
-                            cap_area_offset, cap_area,
-                            sub_cap_offset, sub_cap))
-               return TPM_LIB_ERROR;
-       err = tpm_sendrecv_command(buf, response, &response_length);
-       if (err)
-               return err;
-       if (unpack_byte_string(response, response_length, "d",
-                              cap_size_offset, &cap_size))
-               return TPM_LIB_ERROR;
-       if (cap_size > response_length || cap_size > count)
-               return TPM_LIB_ERROR;
-       if (unpack_byte_string(response, response_length, "s",
-                              cap_offset, cap, cap_size))
-               return TPM_LIB_ERROR;
-
-       return 0;
-}
-
-u32 tpm_get_permanent_flags(struct tpm_permanent_flags *pflags)
-{
-       const u8 command[22] = {
-               0x0, 0xc1,              /* TPM_TAG */
-               0x0, 0x0, 0x0, 0x16,    /* parameter size */
-               0x0, 0x0, 0x0, 0x65,    /* TPM_COMMAND_CODE */
-               0x0, 0x0, 0x0, 0x4,     /* TPM_CAP_FLAG_PERM */
-               0x0, 0x0, 0x0, 0x4,     /* subcap size */
-               0x0, 0x0, 0x1, 0x8,     /* subcap value */
-       };
-       const size_t data_size_offset = TPM_HEADER_SIZE;
-       const size_t data_offset = TPM_HEADER_SIZE + sizeof(u32);
-       u8 response[COMMAND_BUFFER_SIZE];
-       size_t response_length = sizeof(response);
-       u32 err;
-       u32 data_size;
-
-       err = tpm_sendrecv_command(command, response, &response_length);
-       if (err)
-               return err;
-       if (unpack_byte_string(response, response_length, "d",
-                              data_size_offset, &data_size))
-               return TPM_LIB_ERROR;
-       if (data_size < sizeof(*pflags))
-               return TPM_LIB_ERROR;
-       if (unpack_byte_string(response, response_length, "s",
-                              data_offset, pflags, sizeof(*pflags)))
-               return TPM_LIB_ERROR;
-
-       return 0;
-}
-
-u32 tpm_get_permissions(u32 index, u32 *perm)
-{
-       const u8 command[22] = {
-               0x0, 0xc1,              /* TPM_TAG */
-               0x0, 0x0, 0x0, 0x16,    /* parameter size */
-               0x0, 0x0, 0x0, 0x65,    /* TPM_COMMAND_CODE */
-               0x0, 0x0, 0x0, 0x11,
-               0x0, 0x0, 0x0, 0x4,
-       };
-       const size_t index_offset = 18;
-       const size_t perm_offset = 60;
-       u8 buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
-       size_t response_length = sizeof(response);
-       u32 err;
-
-       if (pack_byte_string(buf, sizeof(buf), "d", 0, command, sizeof(command),
-                            index_offset, index))
-               return TPM_LIB_ERROR;
-       err = tpm_sendrecv_command(buf, response, &response_length);
-       if (err)
-               return err;
-       if (unpack_byte_string(response, response_length, "d",
-                              perm_offset, perm))
-               return TPM_LIB_ERROR;
-
-       return 0;
-}
-
-#ifdef CONFIG_TPM_FLUSH_RESOURCES
-u32 tpm_flush_specific(u32 key_handle, u32 resource_type)
-{
-       const u8 command[18] = {
-               0x00, 0xc1,             /* TPM_TAG */
-               0x00, 0x00, 0x00, 0x12, /* parameter size */
-               0x00, 0x00, 0x00, 0xba, /* TPM_COMMAND_CODE */
-               0x00, 0x00, 0x00, 0x00, /* key handle */
-               0x00, 0x00, 0x00, 0x00, /* resource type */
-       };
-       const size_t key_handle_offset = 10;
-       const size_t resource_type_offset = 14;
-       u8 buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
-       size_t response_length = sizeof(response);
-       u32 err;
-
-       if (pack_byte_string(buf, sizeof(buf), "sdd",
-                            0, command, sizeof(command),
-                            key_handle_offset, key_handle,
-                            resource_type_offset, resource_type))
-               return TPM_LIB_ERROR;
-
-       err = tpm_sendrecv_command(buf, response, &response_length);
-       if (err)
-               return err;
-       return 0;
-}
-#endif /* CONFIG_TPM_FLUSH_RESOURCES */
-
-#ifdef CONFIG_TPM_AUTH_SESSIONS
-
-/**
- * Fill an authentication block in a request.
- * This func can create the first as well as the second auth block (for
- * double authorized commands).
- *
- * @param request      pointer to the request (w/ uninitialised auth data)
- * @param request_len0 length of the request without auth data
- * @param handles_len  length of the handles area in request
- * @param auth_session pointer to the (valid) auth session to be used
- * @param request_auth pointer to the auth block of the request to be filled
- * @param auth         authentication data (HMAC key)
- */
-static u32 create_request_auth(const void *request, size_t request_len0,
-                              size_t handles_len,
-                              struct session_data *auth_session,
-                              void *request_auth, const void *auth)
-{
-       u8 hmac_data[DIGEST_LENGTH * 3 + 1];
-       sha1_context hash_ctx;
-       const size_t command_code_offset = 6;
-       const size_t auth_nonce_odd_offset = 4;
-       const size_t auth_continue_offset = 24;
-       const size_t auth_auth_offset = 25;
-
-       if (!auth_session || !auth_session->valid)
-               return TPM_LIB_ERROR;
-
-       sha1_starts(&hash_ctx);
-       sha1_update(&hash_ctx, request + command_code_offset, 4);
-       if (request_len0 > TPM_REQUEST_HEADER_LENGTH + handles_len)
-               sha1_update(&hash_ctx,
-                           request + TPM_REQUEST_HEADER_LENGTH + handles_len,
-                           request_len0 - TPM_REQUEST_HEADER_LENGTH
-                           - handles_len);
-       sha1_finish(&hash_ctx, hmac_data);
-
-       sha1_starts(&hash_ctx);
-       sha1_update(&hash_ctx, auth_session->nonce_odd, DIGEST_LENGTH);
-       sha1_update(&hash_ctx, hmac_data, sizeof(hmac_data));
-       sha1_finish(&hash_ctx, auth_session->nonce_odd);
-
-       if (pack_byte_string(request_auth, TPM_REQUEST_AUTH_LENGTH, "dsb",
-                            0, auth_session->handle,
-                            auth_nonce_odd_offset, auth_session->nonce_odd,
-                            DIGEST_LENGTH,
-                            auth_continue_offset, 1))
-               return TPM_LIB_ERROR;
-       if (pack_byte_string(hmac_data, sizeof(hmac_data), "ss",
-                            DIGEST_LENGTH,
-                            auth_session->nonce_even,
-                            DIGEST_LENGTH,
-                            2 * DIGEST_LENGTH,
-                            request_auth + auth_nonce_odd_offset,
-                            DIGEST_LENGTH + 1))
-               return TPM_LIB_ERROR;
-       sha1_hmac(auth, DIGEST_LENGTH, hmac_data, sizeof(hmac_data),
-                 request_auth + auth_auth_offset);
-
-       return TPM_SUCCESS;
-}
-
-/**
- * Verify an authentication block in a response.
- * Since this func updates the nonce_even in the session data it has to be
- * called when receiving a succesfull AUTH response.
- * This func can verify the first as well as the second auth block (for
- * double authorized commands).
- *
- * @param command_code command code of the request
- * @param response     pointer to the request (w/ uninitialised auth data)
- * @param handles_len  length of the handles area in response
- * @param auth_session pointer to the (valid) auth session to be used
- * @param response_auth        pointer to the auth block of the response to be verified
- * @param auth         authentication data (HMAC key)
- */
-static u32 verify_response_auth(u32 command_code, const void *response,
-                               size_t response_len0, size_t handles_len,
-                               struct session_data *auth_session,
-                               const void *response_auth, const void *auth)
-{
-       u8 hmac_data[DIGEST_LENGTH * 3 + 1];
-       u8 computed_auth[DIGEST_LENGTH];
-       sha1_context hash_ctx;
-       const size_t return_code_offset = 6;
-       const size_t auth_continue_offset = 20;
-       const size_t auth_auth_offset = 21;
-       u8 auth_continue;
-
-       if (!auth_session || !auth_session->valid)
-               return TPM_AUTHFAIL;
-       if (pack_byte_string(hmac_data, sizeof(hmac_data), "d",
-                            0, command_code))
-               return TPM_LIB_ERROR;
-       if (response_len0 < TPM_RESPONSE_HEADER_LENGTH)
-               return TPM_LIB_ERROR;
-
-       sha1_starts(&hash_ctx);
-       sha1_update(&hash_ctx, response + return_code_offset, 4);
-       sha1_update(&hash_ctx, hmac_data, 4);
-       if (response_len0 > TPM_RESPONSE_HEADER_LENGTH + handles_len)
-               sha1_update(&hash_ctx,
-                           response + TPM_RESPONSE_HEADER_LENGTH + handles_len,
-                           response_len0 - TPM_RESPONSE_HEADER_LENGTH
-                           - handles_len);
-       sha1_finish(&hash_ctx, hmac_data);
-
-       memcpy(auth_session->nonce_even, response_auth, DIGEST_LENGTH);
-       auth_continue = ((u8 *)response_auth)[auth_continue_offset];
-       if (pack_byte_string(hmac_data, sizeof(hmac_data), "ssb",
-                            DIGEST_LENGTH,
-                            response_auth,
-                            DIGEST_LENGTH,
-                            2 * DIGEST_LENGTH,
-                            auth_session->nonce_odd,
-                            DIGEST_LENGTH,
-                            3 * DIGEST_LENGTH,
-                            auth_continue))
-               return TPM_LIB_ERROR;
-
-       sha1_hmac(auth, DIGEST_LENGTH, hmac_data, sizeof(hmac_data),
-                 computed_auth);
-
-       if (memcmp(computed_auth, response_auth + auth_auth_offset,
-                  DIGEST_LENGTH))
-               return TPM_AUTHFAIL;
-
-       return TPM_SUCCESS;
-}
-
-u32 tpm_terminate_auth_session(u32 auth_handle)
-{
-       const u8 command[18] = {
-               0x00, 0xc1,             /* TPM_TAG */
-               0x00, 0x00, 0x00, 0x00, /* parameter size */
-               0x00, 0x00, 0x00, 0xba, /* TPM_COMMAND_CODE */
-               0x00, 0x00, 0x00, 0x00, /* TPM_HANDLE */
-               0x00, 0x00, 0x00, 0x02, /* TPM_RESOURCE_TYPE */
-       };
-       const size_t req_handle_offset = TPM_REQUEST_HEADER_LENGTH;
-       u8 request[COMMAND_BUFFER_SIZE];
-
-       if (pack_byte_string(request, sizeof(request), "sd",
-                            0, command, sizeof(command),
-                            req_handle_offset, auth_handle))
-               return TPM_LIB_ERROR;
-       if (oiap_session.valid && oiap_session.handle == auth_handle)
-               oiap_session.valid = 0;
-
-       return tpm_sendrecv_command(request, NULL, NULL);
-}
-
-u32 tpm_end_oiap(void)
-{
-       u32 err = TPM_SUCCESS;
-
-       if (oiap_session.valid)
-               err = tpm_terminate_auth_session(oiap_session.handle);
-       return err;
-}
-
-u32 tpm_oiap(u32 *auth_handle)
-{
-       const u8 command[10] = {
-               0x00, 0xc1,             /* TPM_TAG */
-               0x00, 0x00, 0x00, 0x0a, /* parameter size */
-               0x00, 0x00, 0x00, 0x0a, /* TPM_COMMAND_CODE */
-       };
-       const size_t res_auth_handle_offset = TPM_RESPONSE_HEADER_LENGTH;
-       const size_t res_nonce_even_offset = TPM_RESPONSE_HEADER_LENGTH + 4;
-       u8 response[COMMAND_BUFFER_SIZE];
-       size_t response_length = sizeof(response);
-       u32 err;
-
-       if (oiap_session.valid)
-               tpm_terminate_auth_session(oiap_session.handle);
-
-       err = tpm_sendrecv_command(command, response, &response_length);
-       if (err)
-               return err;
-       if (unpack_byte_string(response, response_length, "ds",
-                              res_auth_handle_offset, &oiap_session.handle,
-                              res_nonce_even_offset, &oiap_session.nonce_even,
-                              (u32)DIGEST_LENGTH))
-               return TPM_LIB_ERROR;
-       oiap_session.valid = 1;
-       if (auth_handle)
-               *auth_handle = oiap_session.handle;
-       return 0;
-}
-
-u32 tpm_load_key2_oiap(u32 parent_handle, const void *key, size_t key_length,
-                      const void *parent_key_usage_auth, u32 *key_handle)
-{
-       const u8 command[14] = {
-               0x00, 0xc2,             /* TPM_TAG */
-               0x00, 0x00, 0x00, 0x00, /* parameter size */
-               0x00, 0x00, 0x00, 0x41, /* TPM_COMMAND_CODE */
-               0x00, 0x00, 0x00, 0x00, /* parent handle */
-       };
-       const size_t req_size_offset = 2;
-       const size_t req_parent_handle_offset = TPM_REQUEST_HEADER_LENGTH;
-       const size_t req_key_offset = TPM_REQUEST_HEADER_LENGTH + 4;
-       const size_t res_handle_offset = TPM_RESPONSE_HEADER_LENGTH;
-       u8 request[sizeof(command) + TPM_KEY12_MAX_LENGTH +
-                  TPM_REQUEST_AUTH_LENGTH];
-       u8 response[COMMAND_BUFFER_SIZE];
-       size_t response_length = sizeof(response);
-       u32 err;
-
-       if (!oiap_session.valid) {
-               err = tpm_oiap(NULL);
-               if (err)
-                       return err;
-       }
-       if (pack_byte_string(request, sizeof(request), "sdds",
-                            0, command, sizeof(command),
-                            req_size_offset,
-                            sizeof(command) + key_length
-                            + TPM_REQUEST_AUTH_LENGTH,
-                            req_parent_handle_offset, parent_handle,
-                            req_key_offset, key, key_length
-               ))
-               return TPM_LIB_ERROR;
-
-       err = create_request_auth(request, sizeof(command) + key_length, 4,
-                                 &oiap_session,
-                                 request + sizeof(command) + key_length,
-                                 parent_key_usage_auth);
-       if (err)
-               return err;
-       err = tpm_sendrecv_command(request, response, &response_length);
-       if (err) {
-               if (err == TPM_AUTHFAIL)
-                       oiap_session.valid = 0;
-               return err;
-       }
-
-       err = verify_response_auth(0x00000041, response,
-                                  response_length - TPM_RESPONSE_AUTH_LENGTH,
-                                  4, &oiap_session,
-                                  response + response_length -
-                                  TPM_RESPONSE_AUTH_LENGTH,
-                                  parent_key_usage_auth);
-       if (err)
-               return err;
-
-       if (key_handle) {
-               if (unpack_byte_string(response, response_length, "d",
-                                      res_handle_offset, key_handle))
-                       return TPM_LIB_ERROR;
-       }
-
-       return 0;
-}
-
-u32 tpm_get_pub_key_oiap(u32 key_handle, const void *usage_auth, void *pubkey,
-                        size_t *pubkey_len)
-{
-       const u8 command[14] = {
-               0x00, 0xc2,             /* TPM_TAG */
-               0x00, 0x00, 0x00, 0x00, /* parameter size */
-               0x00, 0x00, 0x00, 0x21, /* TPM_COMMAND_CODE */
-               0x00, 0x00, 0x00, 0x00, /* key handle */
-       };
-       const size_t req_size_offset = 2;
-       const size_t req_key_handle_offset = TPM_REQUEST_HEADER_LENGTH;
-       const size_t res_pubkey_offset = TPM_RESPONSE_HEADER_LENGTH;
-       u8 request[sizeof(command) + TPM_REQUEST_AUTH_LENGTH];
-       u8 response[TPM_RESPONSE_HEADER_LENGTH + TPM_PUBKEY_MAX_LENGTH +
-                   TPM_RESPONSE_AUTH_LENGTH];
-       size_t response_length = sizeof(response);
-       u32 err;
-
-       if (!oiap_session.valid) {
-               err = tpm_oiap(NULL);
-               if (err)
-                       return err;
-       }
-       if (pack_byte_string(request, sizeof(request), "sdd",
-                            0, command, sizeof(command),
-                            req_size_offset,
-                            (u32)(sizeof(command)
-                            + TPM_REQUEST_AUTH_LENGTH),
-                            req_key_handle_offset, key_handle
-               ))
-               return TPM_LIB_ERROR;
-       err = create_request_auth(request, sizeof(command), 4, &oiap_session,
-                                 request + sizeof(command), usage_auth);
-       if (err)
-               return err;
-       err = tpm_sendrecv_command(request, response, &response_length);
-       if (err) {
-               if (err == TPM_AUTHFAIL)
-                       oiap_session.valid = 0;
-               return err;
-       }
-       err = verify_response_auth(0x00000021, response,
-                                  response_length - TPM_RESPONSE_AUTH_LENGTH,
-                                  0, &oiap_session,
-                                  response + response_length -
-                                  TPM_RESPONSE_AUTH_LENGTH,
-                                  usage_auth);
-       if (err)
-               return err;
-
-       if (pubkey) {
-               if ((response_length - TPM_RESPONSE_HEADER_LENGTH
-                    - TPM_RESPONSE_AUTH_LENGTH) > *pubkey_len)
-                       return TPM_LIB_ERROR;
-               *pubkey_len = response_length - TPM_RESPONSE_HEADER_LENGTH
-                       - TPM_RESPONSE_AUTH_LENGTH;
-               memcpy(pubkey, response + res_pubkey_offset,
-                      response_length - TPM_RESPONSE_HEADER_LENGTH
-                      - TPM_RESPONSE_AUTH_LENGTH);
-       }
-
-       return 0;
-}
-
-#ifdef CONFIG_TPM_LOAD_KEY_BY_SHA1
-u32 tpm_find_key_sha1(const u8 auth[20], const u8 pubkey_digest[20],
-                     u32 *handle)
-{
-       u16 key_count;
-       u32 key_handles[10];
-       u8 buf[288];
-       u8 *ptr;
-       u32 err;
-       u8 digest[20];
-       size_t buf_len;
-       unsigned int i;
-
-       /* fetch list of already loaded keys in the TPM */
-       err = tpm_get_capability(TPM_CAP_HANDLE, TPM_RT_KEY, buf, sizeof(buf));
-       if (err)
-               return -1;
-       key_count = get_unaligned_be16(buf);
-       ptr = buf + 2;
-       for (i = 0; i < key_count; ++i, ptr += 4)
-               key_handles[i] = get_unaligned_be32(ptr);
-
-       /* now search a(/ the) key which we can access with the given auth */
-       for (i = 0; i < key_count; ++i) {
-               buf_len = sizeof(buf);
-               err = tpm_get_pub_key_oiap(key_handles[i], auth, buf, &buf_len);
-               if (err && err != TPM_AUTHFAIL)
-                       return -1;
-               if (err)
-                       continue;
-               sha1_csum(buf, buf_len, digest);
-               if (!memcmp(digest, pubkey_digest, 20)) {
-                       *handle = key_handles[i];
-                       return 0;
-               }
-       }
-       return 1;
-}
-#endif /* CONFIG_TPM_LOAD_KEY_BY_SHA1 */
-
-#endif /* CONFIG_TPM_AUTH_SESSIONS */
-
-u32 tpm_get_random(void *data, u32 count)
-{
-       const u8 command[14] = {
-               0x0, 0xc1,              /* TPM_TAG */
-               0x0, 0x0, 0x0, 0xe,     /* parameter size */
-               0x0, 0x0, 0x0, 0x46,    /* TPM_COMMAND_CODE */
-       };
-       const size_t length_offset = 10;
-       const size_t data_size_offset = 10;
-       const size_t data_offset = 14;
-       u8 buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
-       size_t response_length = sizeof(response);
-       u32 data_size;
-       u8 *out = data;
-
-       while (count > 0) {
-               u32 this_bytes = min((size_t)count,
-                                    sizeof(response) - data_offset);
-               u32 err;
-
-               if (pack_byte_string(buf, sizeof(buf), "sd",
-                                    0, command, sizeof(command),
-                                    length_offset, this_bytes))
-                       return TPM_LIB_ERROR;
-               err = tpm_sendrecv_command(buf, response, &response_length);
-               if (err)
-                       return err;
-               if (unpack_byte_string(response, response_length, "d",
-                                      data_size_offset, &data_size))
-                       return TPM_LIB_ERROR;
-               if (data_size > count)
-                       return TPM_LIB_ERROR;
-               if (unpack_byte_string(response, response_length, "s",
-                                      data_offset, out, data_size))
-                       return TPM_LIB_ERROR;
-
-               count -= data_size;
-               out += data_size;
-       }
-
-       return 0;
-}