#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>
#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>
*/
#include <common.h>
-#include <tpm.h>
+#include <tpm-v1.h>
#include <malloc.h>
#include <linux/ctype.h>
#include <asm/unaligned.h>
#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>
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
--- /dev/null
+// 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);
+}
--- /dev/null
+/* 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 */
--- /dev/null
+// 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"
+);
+++ /dev/null
-// 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"
-);
#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 { \
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
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
#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)
#include <common.h>
#include <dm.h>
-#include <tpm.h>
+#include <tpm-v1.h>
#include <i2c.h>
#include <asm/unaligned.h>
#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>
#include <common.h>
#include <dm.h>
#include <mapmem.h>
-#include <tpm.h>
+#include <tpm-v1.h>
#include <asm/io.h>
#define PREFIX "lpc_tpm: "
#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>
#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>
#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>
--- /dev/null
+/* 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 */
--- /dev/null
+/* 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 */
+++ /dev/null
-/* 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 */
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
--- /dev/null
+// 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);
+}
--- /dev/null
+/* 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 */
--- /dev/null
+// 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;
+}
+++ /dev/null
-// 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;
-}