security/tpm: Move tpm TSS and TSPI layer to security section

* Move code from src/lib and src/include into src/security/tpm
* Split TPM TSS 1.2 and 2.0
* Fix header includes
* Add a new directory structure with kconfig and makefile includes

Change-Id: Id15a9aa6bd367560318dfcfd450bf5626ea0ec2b
Signed-off-by: Philipp Deppenwiese <zaolin@das-labor.org>
Reviewed-on: https://review.coreboot.org/22103
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Stefan Reinauer <stefan.reinauer@coreboot.org>
This commit is contained in:
Philipp Deppenwiese
2017-10-18 17:13:07 +02:00
committed by Stefan Reinauer
parent 4fef7818ec
commit 64e2d19082
51 changed files with 126 additions and 107 deletions

View File

@@ -53,16 +53,6 @@ verstage-$(CONFIG_COLLECT_TIMESTAMPS) += timestamp.c
verstage-y += boot_device.c
verstage-$(CONFIG_CONSOLE_CBMEM) += cbmem_console.c
verstage-$(CONFIG_TPM) += tlcl.c
verstage-$(CONFIG_TPM2) += tpm2_marshaling.c
verstage-$(CONFIG_TPM2) += tpm2_tlcl.c
ifeq ($(CONFIG_VBOOT_SEPARATE_VERSTAGE),y)
romstage-$(CONFIG_TPM) += tlcl.c
romstage-$(CONFIG_TPM2) += tpm2_marshaling.c
romstage-$(CONFIG_TPM2) += tpm2_tlcl.c
endif # CONFIG_VBOOT_SEPARATE_VERSTAGE
verstage-$(CONFIG_GENERIC_UDELAY) += timer.c
verstage-$(CONFIG_GENERIC_GPIO_LIB) += gpio.c
@@ -144,8 +134,6 @@ ramstage-$(CONFIG_GENERIC_GPIO_LIB) += gpio.c
ramstage-$(CONFIG_GENERIC_UDELAY) += timer.c
ramstage-y += b64_decode.c
ramstage-$(CONFIG_ACPI_NHLT) += nhlt.c
ramstage-$(CONFIG_TPM2) += tpm2_marshaling.c
ramstage-$(CONFIG_TPM2) += tpm2_tlcl.c
romstage-y += cbmem_common.c
romstage-y += imd_cbmem.c

View File

@@ -1,353 +0,0 @@
/* Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
/* A lightweight TPM command library.
*
* The general idea is that TPM commands are array of bytes whose
* fields are mostly compile-time constant. The goal is to build much
* of the commands at compile time (or build time) and change some of
* the fields at run time as needed. The code in
* utility/tlcl_generator.c builds structures containing the commands,
* as well as the offsets of the fields that need to be set at run
* time.
*/
#include <arch/early_variables.h>
#include <assert.h>
#include <string.h>
#include <tpm_lite/tlcl.h>
#include <tpm.h>
#include <vb2_api.h>
#include "tlcl_internal.h"
#include "tlcl_structures.h"
#ifdef FOR_TEST
#include <stdio.h>
#define VBDEBUG(format, args...) printf(format, ## args)
#else
#include <console/console.h>
#define VBDEBUG(format, args...) printk(BIOS_DEBUG, format, ## args)
#endif
static int tpm_send_receive(const uint8_t *request,
uint32_t request_length,
uint8_t *response,
uint32_t *response_length)
{
size_t len = *response_length;
if (tis_sendrecv(request, request_length, response, &len))
return VB2_ERROR_UNKNOWN;
/* check 64->32bit overflow and (re)check response buffer overflow */
if (len > *response_length)
return VB2_ERROR_UNKNOWN;
*response_length = len;
return VB2_SUCCESS;
}
/* Sets the size field of a TPM command. */
static inline void set_tpm_command_size(uint8_t *buffer, uint32_t size)
{
to_tpm_uint32(buffer + sizeof(uint16_t), size);
}
/* Gets the size field of a TPM command. */
__attribute__((unused))
static inline int tpm_command_size(const uint8_t *buffer)
{
uint32_t size;
from_tpm_uint32(buffer + sizeof(uint16_t), &size);
return (int) size;
}
/* Gets the code field of a TPM command. */
static inline int tpm_command_code(const uint8_t *buffer)
{
uint32_t code;
from_tpm_uint32(buffer + sizeof(uint16_t) + sizeof(uint32_t), &code);
return code;
}
/* Gets the return code field of a TPM result. */
static inline int tpm_return_code(const uint8_t *buffer)
{
return tpm_command_code(buffer);
}
/* Like TlclSendReceive below, but do not retry if NEEDS_SELFTEST or
* DOING_SELFTEST errors are returned.
*/
static uint32_t tlcl_send_receive_no_retry(const uint8_t *request,
uint8_t *response, int max_length)
{
uint32_t response_length = max_length;
uint32_t result;
result = tpm_send_receive(request, tpm_command_size(request),
response, &response_length);
if (result != 0) {
/* Communication with TPM failed, so response is garbage */
VBDEBUG("TPM: command 0x%x send/receive failed: 0x%x\n",
tpm_command_code(request), result);
return result;
}
/* Otherwise, use the result code from the response */
result = tpm_return_code(response);
/* TODO: add paranoia about returned response_length vs. max_length
* (and possibly expected length from the response header). See
* crosbug.com/17017 */
VBDEBUG("TPM: command 0x%x returned 0x%x\n",
tpm_command_code(request), result);
return result;
}
/* Sends a TPM command and gets a response. Returns 0 if success or the TPM
* error code if error. Waits for the self test to complete if needed. */
uint32_t tlcl_send_receive(const uint8_t *request, uint8_t *response,
int max_length)
{
uint32_t result = tlcl_send_receive_no_retry(request, response,
max_length);
/* If the command fails because the self test has not completed, try it
* again after attempting to ensure that the self test has completed. */
if (result == TPM_E_NEEDS_SELFTEST || result == TPM_E_DOING_SELFTEST) {
result = tlcl_continue_self_test();
if (result != TPM_SUCCESS)
return result;
#if defined(TPM_BLOCKING_CONTINUESELFTEST) || defined(VB_RECOVERY_MODE)
/* Retry only once */
result = tlcl_send_receive_no_retry(request, response,
max_length);
#else
/* This needs serious testing. The TPM specification says: "iii.
* The caller MUST wait for the actions of TPM_ContinueSelfTest
* to complete before reissuing the command C1." But, if
* ContinueSelfTest is non-blocking, how do we know that the
* actions have completed other than trying again? */
do {
result = tlcl_send_receive_no_retry(request, response,
max_length);
} while (result == TPM_E_DOING_SELFTEST);
#endif
}
return result;
}
/* Sends a command and returns the error code. */
static uint32_t send(const uint8_t *command)
{
uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE];
return tlcl_send_receive(command, response, sizeof(response));
}
/* Exported functions. */
static uint8_t tlcl_init_done CAR_GLOBAL;
uint32_t tlcl_lib_init(void)
{
uint8_t done = car_get_var(tlcl_init_done);
if (done)
return VB2_SUCCESS;
if (tis_init())
return VB2_ERROR_UNKNOWN;
if (tis_open())
return VB2_ERROR_UNKNOWN;
car_set_var(tlcl_init_done, 1);
return VB2_SUCCESS;
}
uint32_t tlcl_startup(void)
{
VBDEBUG("TPM: Startup\n");
return send(tpm_startup_cmd.buffer);
}
uint32_t tlcl_resume(void)
{
VBDEBUG("TPM: Resume\n");
return send(tpm_resume_cmd.buffer);
}
uint32_t tlcl_self_test_full(void)
{
VBDEBUG("TPM: Self test full\n");
return send(tpm_selftestfull_cmd.buffer);
}
uint32_t tlcl_continue_self_test(void)
{
uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE];
VBDEBUG("TPM: Continue self test\n");
/* Call the No Retry version of SendReceive to avoid recursion. */
return tlcl_send_receive_no_retry(tpm_continueselftest_cmd.buffer,
response, sizeof(response));
}
uint32_t tlcl_define_space(uint32_t index, uint32_t perm, uint32_t size)
{
struct s_tpm_nv_definespace_cmd cmd;
VBDEBUG("TPM: TlclDefineSpace(0x%x, 0x%x, %d)\n", index, perm, size);
memcpy(&cmd, &tpm_nv_definespace_cmd, sizeof(cmd));
to_tpm_uint32(cmd.buffer + tpm_nv_definespace_cmd.index, index);
to_tpm_uint32(cmd.buffer + tpm_nv_definespace_cmd.perm, perm);
to_tpm_uint32(cmd.buffer + tpm_nv_definespace_cmd.size, size);
return send(cmd.buffer);
}
uint32_t tlcl_write(uint32_t index, const void *data, uint32_t length)
{
struct s_tpm_nv_write_cmd cmd;
uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE];
const int total_length =
kTpmRequestHeaderLength + kWriteInfoLength + length;
VBDEBUG("TPM: tlcl_write(0x%x, %d)\n", index, length);
memcpy(&cmd, &tpm_nv_write_cmd, sizeof(cmd));
assert(total_length <= TPM_LARGE_ENOUGH_COMMAND_SIZE);
set_tpm_command_size(cmd.buffer, total_length);
to_tpm_uint32(cmd.buffer + tpm_nv_write_cmd.index, index);
to_tpm_uint32(cmd.buffer + tpm_nv_write_cmd.length, length);
memcpy(cmd.buffer + tpm_nv_write_cmd.data, data, length);
return tlcl_send_receive(cmd.buffer, response, sizeof(response));
}
uint32_t tlcl_read(uint32_t index, void *data, uint32_t length)
{
struct s_tpm_nv_read_cmd cmd;
uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE];
uint32_t result_length;
uint32_t result;
VBDEBUG("TPM: tlcl_read(0x%x, %d)\n", index, length);
memcpy(&cmd, &tpm_nv_read_cmd, sizeof(cmd));
to_tpm_uint32(cmd.buffer + tpm_nv_read_cmd.index, index);
to_tpm_uint32(cmd.buffer + tpm_nv_read_cmd.length, length);
result = tlcl_send_receive(cmd.buffer, response, sizeof(response));
if (result == TPM_SUCCESS && length > 0) {
uint8_t *nv_read_cursor = response + kTpmResponseHeaderLength;
from_tpm_uint32(nv_read_cursor, &result_length);
nv_read_cursor += sizeof(uint32_t);
memcpy(data, nv_read_cursor, result_length);
}
return result;
}
uint32_t tlcl_assert_physical_presence(void)
{
VBDEBUG("TPM: Asserting physical presence\n");
return send(tpm_ppassert_cmd.buffer);
}
uint32_t tlcl_physical_presence_cmd_enable(void)
{
VBDEBUG("TPM: Enable the physical presence command\n");
return send(tpm_ppenable_cmd.buffer);
}
uint32_t tlcl_finalize_physical_presence(void)
{
VBDEBUG("TPM: Enable PP cmd, disable HW pp, and set lifetime lock\n");
return send(tpm_finalizepp_cmd.buffer);
}
uint32_t tlcl_set_nv_locked(void)
{
VBDEBUG("TPM: Set NV locked\n");
return tlcl_define_space(TPM_NV_INDEX_LOCK, 0, 0);
}
uint32_t tlcl_force_clear(void)
{
VBDEBUG("TPM: Force clear\n");
return send(tpm_forceclear_cmd.buffer);
}
uint32_t tlcl_set_enable(void)
{
VBDEBUG("TPM: Enabling TPM\n");
return send(tpm_physicalenable_cmd.buffer);
}
uint32_t tlcl_set_deactivated(uint8_t flag)
{
struct s_tpm_physicalsetdeactivated_cmd cmd;
VBDEBUG("TPM: SetDeactivated(%d)\n", flag);
memcpy(&cmd, &tpm_physicalsetdeactivated_cmd, sizeof(cmd));
*(cmd.buffer + cmd.deactivated) = flag;
return send(cmd.buffer);
}
uint32_t tlcl_get_permanent_flags(TPM_PERMANENT_FLAGS *pflags)
{
uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE];
uint32_t size;
uint32_t result = tlcl_send_receive(tpm_getflags_cmd.buffer, response,
sizeof(response));
if (result != TPM_SUCCESS)
return result;
from_tpm_uint32(response + kTpmResponseHeaderLength, &size);
assert(size == sizeof(TPM_PERMANENT_FLAGS));
memcpy(pflags, response + kTpmResponseHeaderLength + sizeof(size),
sizeof(TPM_PERMANENT_FLAGS));
return result;
}
uint32_t tlcl_get_flags(uint8_t *disable, uint8_t *deactivated,
uint8_t *nvlocked)
{
TPM_PERMANENT_FLAGS pflags;
uint32_t result = tlcl_get_permanent_flags(&pflags);
if (result == TPM_SUCCESS) {
if (disable)
*disable = pflags.disable;
if (deactivated)
*deactivated = pflags.deactivated;
if (nvlocked)
*nvlocked = pflags.nvLocked;
VBDEBUG("TPM: flags disable=%d, deactivated=%d, nvlocked=%d\n",
pflags.disable, pflags.deactivated, pflags.nvLocked);
}
return result;
}
uint32_t tlcl_set_global_lock(void)
{
uint32_t x;
VBDEBUG("TPM: Set global lock\n");
return tlcl_write(TPM_NV_INDEX0, (uint8_t *) &x, 0);
}
uint32_t tlcl_extend(int pcr_num, const uint8_t *in_digest,
uint8_t *out_digest)
{
struct s_tpm_extend_cmd cmd;
uint8_t response[kTpmResponseHeaderLength + kPcrDigestLength];
uint32_t result;
memcpy(&cmd, &tpm_extend_cmd, sizeof(cmd));
to_tpm_uint32(cmd.buffer + tpm_extend_cmd.pcrNum, pcr_num);
memcpy(cmd.buffer + cmd.inDigest, in_digest, kPcrDigestLength);
result = tlcl_send_receive(cmd.buffer, response, sizeof(response));
if (result != TPM_SUCCESS)
return result;
if (out_digest)
memcpy(out_digest, response + kTpmResponseHeaderLength,
kPcrDigestLength);
return result;
}

View File

@@ -1,65 +0,0 @@
/* Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef TPM_LITE_TLCL_INTERNAL_H_
#define TPM_LITE_TLCL_INTERNAL_H_
/*
* These numbers derive from adding the sizes of command fields as shown in the
* TPM commands manual.
*/
#define kTpmRequestHeaderLength 10
#define kTpmResponseHeaderLength 10
#define kTpmReadInfoLength 12
#define kEncAuthLength 20
#define kPcrDigestLength 20
/*
* Conversion functions. to_tpm_TYPE puts a value of type TYPE into a TPM
* command buffer. from_tpm_TYPE gets a value of type TYPE from a TPM command
* buffer into a variable.
*/
__attribute__((unused))
static inline void to_tpm_uint32(uint8_t *buffer, uint32_t x)
{
buffer[0] = (uint8_t)(x >> 24);
buffer[1] = (uint8_t)((x >> 16) & 0xff);
buffer[2] = (uint8_t)((x >> 8) & 0xff);
buffer[3] = (uint8_t)(x & 0xff);
}
/*
* See comment for above function.
*/
__attribute__((unused))
static inline void from_tpm_uint32(const uint8_t *buffer, uint32_t *x)
{
*x = ((buffer[0] << 24) |
(buffer[1] << 16) |
(buffer[2] << 8) |
buffer[3]);
}
/*
* See comment for above function.
*/
__attribute__((unused))
static inline void to_tpm_uint16(uint8_t *buffer, uint16_t x)
{
buffer[0] = (uint8_t)(x >> 8);
buffer[1] = (uint8_t)(x & 0xff);
}
/*
* See comment for above function.
*/
__attribute__((unused))
static inline void from_tpm_uint16(const uint8_t *buffer, uint16_t *x)
{
*x = (buffer[0] << 8) | buffer[1];
}
#endif /* TPM_LITE_TLCL_INTERNAL_H_ */

View File

@@ -1,164 +0,0 @@
/* This file is automatically generated */
const struct s_tpm_extend_cmd{
uint8_t buffer[34];
uint16_t pcrNum;
uint16_t inDigest;
} tpm_extend_cmd = {{0x0, 0xc1, 0x0, 0x0, 0x0, 0x22, 0x0, 0x0, 0x0, 0x14, },
10, 14, };
const struct s_tpm_get_random_cmd{
uint8_t buffer[14];
uint16_t bytesRequested;
} tpm_get_random_cmd = {{0x0, 0xc1, 0x0, 0x0, 0x0, 0xe, 0x0, 0x0, 0x0, 0x46, },
10, };
const struct s_tpm_getownership_cmd{
uint8_t buffer[22];
} tpm_getownership_cmd = {
{0x0, 0xc1, 0x0, 0x0, 0x0, 0x16, 0x0, 0x0, 0x0, 0x65,
0x0, 0x0, 0x0, 0x5, 0x0, 0x0, 0x0, 0x4, 0x0, 0x0, 0x1, 0x11, },
};
const struct s_tpm_getpermissions_cmd{
uint8_t buffer[22];
uint16_t index;
} tpm_getpermissions_cmd = {
{0x0, 0xc1, 0x0, 0x0, 0x0, 0x16, 0x0, 0x0, 0x0, 0x65,
0x0, 0x0, 0x0, 0x11, 0x0, 0x0, 0x0, 0x4, },
18, };
const struct s_tpm_getstclearflags_cmd{
uint8_t buffer[22];
} tpm_getstclearflags_cmd = {
{0x0, 0xc1, 0x0, 0x0, 0x0, 0x16, 0x0, 0x0, 0x0, 0x65,
0x0, 0x0, 0x0, 0x4, 0x0, 0x0, 0x0, 0x4, 0x0, 0x0, 0x1, 0x9, },
};
const struct s_tpm_getflags_cmd{
uint8_t buffer[22];
} tpm_getflags_cmd = {
{0x0, 0xc1, 0x0, 0x0, 0x0, 0x16, 0x0, 0x0, 0x0, 0x65,
0x0, 0x0, 0x0, 0x4, 0x0, 0x0, 0x0, 0x4, 0x0, 0x0, 0x1, 0x8, },
};
const struct s_tpm_physicalsetdeactivated_cmd{
uint8_t buffer[11];
uint16_t deactivated;
} tpm_physicalsetdeactivated_cmd = {
{0x0, 0xc1, 0x0, 0x0, 0x0, 0xb, 0x0, 0x0, 0x0, 0x72, },
10, };
const struct s_tpm_physicalenable_cmd{
uint8_t buffer[10];
} tpm_physicalenable_cmd = {
{0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x6f, },
};
const struct s_tpm_physicaldisable_cmd{
uint8_t buffer[10];
} tpm_physicaldisable_cmd = {
{0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x70, },
};
const struct s_tpm_forceclear_cmd{
uint8_t buffer[10];
} tpm_forceclear_cmd = {{0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x5d, },
};
const struct s_tpm_readpubek_cmd{
uint8_t buffer[30];
} tpm_readpubek_cmd = {{0x0, 0xc1, 0x0, 0x0, 0x0, 0x1e, 0x0, 0x0, 0x0, 0x7c, },
};
const struct s_tpm_continueselftest_cmd{
uint8_t buffer[10];
} tpm_continueselftest_cmd = {
{0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x53, },
};
const struct s_tpm_selftestfull_cmd{
uint8_t buffer[10];
} tpm_selftestfull_cmd = {
{0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x50, },
};
const struct s_tpm_resume_cmd{
uint8_t buffer[12];
} tpm_resume_cmd = {
{0x0, 0xc1, 0x0, 0x0, 0x0, 0xc, 0x0, 0x0, 0x0, 0x99, 0x0, 0x2, },
};
const struct s_tpm_savestate_cmd{
uint8_t buffer[10];
} tpm_savestate_cmd = {{0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x98, },
};
const struct s_tpm_startup_cmd{
uint8_t buffer[12];
} tpm_startup_cmd = {
{0x0, 0xc1, 0x0, 0x0, 0x0, 0xc, 0x0, 0x0, 0x0, 0x99, 0x0, 0x1, },
};
const struct s_tpm_finalizepp_cmd{
uint8_t buffer[12];
} tpm_finalizepp_cmd = {
{0x0, 0xc1, 0x0, 0x0, 0x0, 0xc, 0x40, 0x0, 0x0, 0xa, 0x2, 0xa0, },
};
const struct s_tpm_pplock_cmd{
uint8_t buffer[12];
} tpm_pplock_cmd = {
{0x0, 0xc1, 0x0, 0x0, 0x0, 0xc, 0x40, 0x0, 0x0, 0xa, 0x0, 0x4, },
};
const struct s_tpm_ppenable_cmd{
uint8_t buffer[12];
} tpm_ppenable_cmd = {
{0x0, 0xc1, 0x0, 0x0, 0x0, 0xc, 0x40, 0x0, 0x0, 0xa, 0x0, 0x20, },
};
const struct s_tpm_ppassert_cmd{
uint8_t buffer[12];
} tpm_ppassert_cmd = {
{0x0, 0xc1, 0x0, 0x0, 0x0, 0xc, 0x40, 0x0, 0x0, 0xa, 0x0, 0x8, },
};
const struct s_tpm_pcr_read_cmd{
uint8_t buffer[14];
uint16_t pcrNum;
} tpm_pcr_read_cmd = {{0x0, 0xc1, 0x0, 0x0, 0x0, 0xe, 0x0, 0x0, 0x0, 0x15, },
10, };
const struct s_tpm_nv_read_cmd{
uint8_t buffer[22];
uint16_t index;
uint16_t length;
} tpm_nv_read_cmd = {{0x0, 0xc1, 0x0, 0x0, 0x0, 0x16, 0x0, 0x0, 0x0, 0xcf, },
10, 18, };
const struct s_tpm_nv_write_cmd{
uint8_t buffer[256];
uint16_t index;
uint16_t length;
uint16_t data;
} tpm_nv_write_cmd = {{0x0, 0xc1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xcd, },
10, 18, 22, };
const struct s_tpm_nv_definespace_cmd{
uint8_t buffer[101];
uint16_t index;
uint16_t perm;
uint16_t size;
} tpm_nv_definespace_cmd = {
{0x0, 0xc1, 0x0, 0x0, 0x0, 0x65, 0x0, 0x0, 0x0, 0xcc,
0x0, 0x18, 0, 0, 0, 0, 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,
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, 0x0, 0x17,
},
12, 70, 77,
};
const int kWriteInfoLength = 12;
const int kNvDataPublicPermissionsOffset = 60;

View File

@@ -1,559 +0,0 @@
/*
* Copyright 2016 The Chromium OS Authors. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include <arch/early_variables.h>
#include <commonlib/iobuf.h>
#include <console/console.h>
#include <stdlib.h>
#include <string.h>
#include "tpm2_marshaling.h"
static uint16_t tpm_tag CAR_GLOBAL; /* Depends on the command type. */
#define unmarshal_TPM_CAP(a, b) ibuf_read_be32(a, b)
#define unmarshal_TPM_CC(a, b) ibuf_read_be32(a, b)
#define unmarshal_TPM_PT(a, b) ibuf_read_be32(a, b)
#define unmarshal_TPM_HANDLE(a, b) ibuf_read_be32(a, b)
#define marshal_TPM_HANDLE(a, b) obuf_write_be32(a, b)
#define marshal_TPMI_ALG_HASH(a, b) obuf_write_be16(a, b)
static int marshal_startup(struct obuf *ob, struct tpm2_startup *cmd_body)
{
return obuf_write_be16(ob, cmd_body->startup_type);
}
static int marshal_get_capability(struct obuf *ob,
struct tpm2_get_capability *cmd_body)
{
int rc = 0;
rc |= obuf_write_be32(ob, cmd_body->capability);
rc |= obuf_write_be32(ob, cmd_body->property);
rc |= obuf_write_be32(ob, cmd_body->propertyCount);
return rc;
}
static int marshal_TPM2B(struct obuf *ob, TPM2B *data)
{
int rc = 0;
rc |= obuf_write_be16(ob, data->size);
rc |= obuf_write(ob, data->buffer, data->size);
return rc;
}
static int marshal_TPMA_NV(struct obuf *ob, TPMA_NV *nv)
{
uint32_t v;
memcpy(&v, nv, sizeof(v));
return obuf_write_be32(ob, v);
}
static int marshal_TPMS_NV_PUBLIC(struct obuf *ob, TPMS_NV_PUBLIC *nvpub)
{
int rc = 0;
rc |= marshal_TPM_HANDLE(ob, nvpub->nvIndex);
rc |= marshal_TPMI_ALG_HASH(ob, nvpub->nameAlg);
rc |= marshal_TPMA_NV(ob, &nvpub->attributes);
rc |= marshal_TPM2B(ob, &nvpub->authPolicy.b);
rc |= obuf_write_be16(ob, nvpub->dataSize);
return rc;
}
static int marshal_TPMT_HA(struct obuf *ob, TPMT_HA *tpmtha)
{
int rc = 0;
rc |= marshal_TPMI_ALG_HASH(ob, tpmtha->hashAlg);
rc |= obuf_write(ob, tpmtha->digest.sha256,
sizeof(tpmtha->digest.sha256));
return rc;
}
static int marshal_TPML_DIGEST_VALUES(struct obuf *ob,
TPML_DIGEST_VALUES *dvalues)
{
int i;
int rc = 0;
rc |= obuf_write_be32(ob, dvalues->count);
for (i = 0; i < dvalues->count; i++)
rc |= marshal_TPMT_HA(ob, &dvalues->digests[i]);
return rc;
}
static int marshal_session_header(struct obuf *ob,
struct tpm2_session_header *session_header)
{
int rc = 0;
struct obuf ob_sz;
size_t prev_written;
/* Snapshot current location to place size of header. */
if (obuf_splice_current(ob, &ob_sz, sizeof(uint32_t)) < 0)
return -1;
/* Write a size placeholder. */
rc |= obuf_write_be32(ob, 0);
/* Keep track of session header data size by tracking num written. */
prev_written = obuf_nr_written(ob);
rc |= obuf_write_be32(ob, session_header->session_handle);
rc |= obuf_write_be16(ob, session_header->nonce_size);
rc |= obuf_write(ob, session_header->nonce, session_header->nonce_size);
rc |= obuf_write_be8(ob, session_header->session_attrs);
rc |= obuf_write_be16(ob, session_header->auth_size);
rc |= obuf_write(ob, session_header->auth, session_header->auth_size);
/* Fill back in proper size of session header. */
rc |= obuf_write_be32(&ob_sz, obuf_nr_written(ob) - prev_written);
return rc;
}
/*
* Common session header can include one or two handles and an empty
* session_header structure.
*/
static int marshal_common_session_header(struct obuf *ob,
const uint32_t *handles,
size_t handle_count)
{
size_t i;
struct tpm2_session_header session_header;
int rc = 0;
car_set_var(tpm_tag, TPM_ST_SESSIONS);
for (i = 0; i < handle_count; i++)
rc |= marshal_TPM_HANDLE(ob, handles[i]);
memset(&session_header, 0, sizeof(session_header));
session_header.session_handle = TPM_RS_PW;
rc |= marshal_session_header(ob, &session_header);
return rc;
}
static int marshal_nv_define_space(struct obuf *ob,
struct tpm2_nv_define_space_cmd *nvd_in)
{
const uint32_t handle[] = { TPM_RH_PLATFORM };
struct obuf ob_sz;
size_t prev_written;
int rc = 0;
rc |= marshal_common_session_header(ob, handle, ARRAY_SIZE(handle));
rc |= marshal_TPM2B(ob, &nvd_in->auth.b);
/* Snapshot current location to place size field. */
if (obuf_splice_current(ob, &ob_sz, sizeof(uint16_t)) < 0)
return -1;
/* Put placeholder for size */
rc |= obuf_write_be16(ob, 0);
/* Keep track of nv define space data size by tracking num written. */
prev_written = obuf_nr_written(ob);
rc |= marshal_TPMS_NV_PUBLIC(ob, &nvd_in->publicInfo);
rc |= obuf_write_be16(&ob_sz, obuf_nr_written(ob) - prev_written);
return rc;
}
static int marshal_nv_write(struct obuf *ob,
struct tpm2_nv_write_cmd *command_body)
{
int rc = 0;
uint32_t handles[] = { TPM_RH_PLATFORM, command_body->nvIndex };
rc |= marshal_common_session_header(ob, handles, ARRAY_SIZE(handles));
rc |= marshal_TPM2B(ob, &command_body->data.b);
rc |= obuf_write_be16(ob, command_body->offset);
return rc;
}
static int marshal_nv_write_lock(struct obuf *ob,
struct tpm2_nv_write_lock_cmd *command_body)
{
uint32_t handles[] = { TPM_RH_PLATFORM, command_body->nvIndex };
return marshal_common_session_header(ob, handles, ARRAY_SIZE(handles));
}
static int marshal_pcr_extend(struct obuf *ob,
struct tpm2_pcr_extend_cmd *command_body)
{
int rc = 0;
uint32_t handles[] = { command_body->pcrHandle };
rc |= marshal_common_session_header(ob, handles, ARRAY_SIZE(handles));
rc |= marshal_TPML_DIGEST_VALUES(ob, &command_body->digests);
return rc;
}
static int marshal_nv_read(struct obuf *ob,
struct tpm2_nv_read_cmd *command_body)
{
int rc = 0;
uint32_t handles[] = { TPM_RH_PLATFORM, command_body->nvIndex };
rc |= marshal_common_session_header(ob, handles, ARRAY_SIZE(handles));
rc |= obuf_write_be16(ob, command_body->size);
rc |= obuf_write_be16(ob, command_body->offset);
return rc;
}
/* TPM2_Clear command does not require paramaters. */
static int marshal_clear(struct obuf *ob)
{
const uint32_t handle[] = { TPM_RH_PLATFORM };
return marshal_common_session_header(ob, handle, ARRAY_SIZE(handle));
}
static int marshal_selftest(struct obuf *ob,
struct tpm2_self_test *command_body)
{
return obuf_write_be8(ob, command_body->yes_no);
}
static int marshal_hierarchy_control(struct obuf *ob,
struct tpm2_hierarchy_control_cmd *command_body)
{
int rc = 0;
struct tpm2_session_header session_header;
car_set_var(tpm_tag, TPM_ST_SESSIONS);
rc |= marshal_TPM_HANDLE(ob, TPM_RH_PLATFORM);
memset(&session_header, 0, sizeof(session_header));
session_header.session_handle = TPM_RS_PW;
rc |= marshal_session_header(ob, &session_header);
rc |= marshal_TPM_HANDLE(ob, command_body->enable);
rc |= obuf_write_be8(ob, command_body->state);
return rc;
}
static int marshal_cr50_vendor_command(struct obuf *ob, void *command_body)
{
int rc = 0;
uint16_t *sub_command = command_body;
switch (*sub_command) {
case TPM2_CR50_SUB_CMD_NVMEM_ENABLE_COMMITS:
rc |= obuf_write_be16(ob, *sub_command);
break;
case TPM2_CR50_SUB_CMD_TURN_UPDATE_ON:
rc |= obuf_write_be16(ob, sub_command[0]);
rc |= obuf_write_be16(ob, sub_command[1]);
break;
default:
/* Unsupported subcommand. */
printk(BIOS_WARNING, "Unsupported cr50 subcommand: 0x%04x\n",
*sub_command);
rc = -1;
break;
}
return rc;
}
int tpm_marshal_command(TPM_CC command, void *tpm_command_body, struct obuf *ob)
{
struct obuf ob_hdr;
const size_t hdr_sz = sizeof(uint16_t) + 2 * sizeof(uint32_t);
int rc = 0;
car_set_var(tpm_tag, TPM_ST_NO_SESSIONS);
if (obuf_splice_current(ob, &ob_hdr, hdr_sz) < 0)
return -1;
/* Write TPM command header with placeholder field values. */
rc |= obuf_write_be16(ob, 0);
rc |= obuf_write_be32(ob, 0);
rc |= obuf_write_be32(ob, command);
if (rc != 0)
return rc;
switch (command) {
case TPM2_Startup:
rc |= marshal_startup(ob, tpm_command_body);
break;
case TPM2_GetCapability:
rc |= marshal_get_capability(ob, tpm_command_body);
break;
case TPM2_NV_Read:
rc |= marshal_nv_read(ob, tpm_command_body);
break;
case TPM2_NV_DefineSpace:
rc |= marshal_nv_define_space(ob, tpm_command_body);
break;
case TPM2_NV_Write:
rc |= marshal_nv_write(ob, tpm_command_body);
break;
case TPM2_NV_WriteLock:
rc |= marshal_nv_write_lock(ob, tpm_command_body);
break;
case TPM2_SelfTest:
rc |= marshal_selftest(ob, tpm_command_body);
break;
case TPM2_Hierarchy_Control:
rc |= marshal_hierarchy_control(ob, tpm_command_body);
break;
case TPM2_Clear:
rc |= marshal_clear(ob);
break;
case TPM2_PCR_Extend:
rc |= marshal_pcr_extend(ob, tpm_command_body);
break;
case TPM2_CR50_VENDOR_COMMAND:
rc |= marshal_cr50_vendor_command(ob, tpm_command_body);
break;
default:
printk(BIOS_INFO, "%s:%d:Request to marshal unsupported command %#x\n",
__FILE__, __LINE__, command);
rc = -1;
}
if (rc != 0)
return rc;
/* Fix up the command header with known values. */
rc |= obuf_write_be16(&ob_hdr, car_get_var(tpm_tag));
rc |= obuf_write_be32(&ob_hdr, obuf_nr_written(ob));
return rc;
}
static int unmarshal_get_capability(struct ibuf *ib,
struct get_cap_response *gcr)
{
int i;
int rc = 0;
rc |= ibuf_read_be8(ib, &gcr->more_data);
rc |= unmarshal_TPM_CAP(ib, &gcr->cd.capability);
if (rc != 0)
return rc;
switch (gcr->cd.capability) {
case TPM_CAP_TPM_PROPERTIES:
if (ibuf_read_be32(ib, &gcr->cd.data.tpmProperties.count))
return -1;
if (gcr->cd.data.tpmProperties.count > ARRAY_SIZE
(gcr->cd.data.tpmProperties.tpmProperty)) {
printk(BIOS_INFO, "%s:%s:%d - %d - too many properties\n",
__FILE__, __func__, __LINE__,
gcr->cd.data.tpmProperties.count);
return -1;
}
for (i = 0; i < gcr->cd.data.tpmProperties.count; i++) {
TPMS_TAGGED_PROPERTY *pp;
pp = gcr->cd.data.tpmProperties.tpmProperty + i;
rc |= unmarshal_TPM_PT(ib, &pp->property);
rc |= ibuf_read_be32(ib, &pp->value);
}
break;
default:
printk(BIOS_ERR,
"%s:%d - unable to unmarshal capability response",
__func__, __LINE__);
printk(BIOS_ERR, " for %d\n", gcr->cd.capability);
rc = -1;
break;
}
return rc;
}
static int unmarshal_TPM2B_MAX_NV_BUFFER(struct ibuf *ib,
TPM2B_MAX_NV_BUFFER *nv_buffer)
{
if (ibuf_read_be16(ib, &nv_buffer->t.size))
return -1;
nv_buffer->t.buffer = ibuf_oob_drain(ib, nv_buffer->t.size);
if (nv_buffer->t.buffer == NULL) {
printk(BIOS_ERR, "%s:%d - "
"size mismatch: expected %d, remaining %zd\n",
__func__, __LINE__, nv_buffer->t.size,
ibuf_remaining(ib));
return -1;
}
return 0;
}
static int unmarshal_nv_read(struct ibuf *ib, struct nv_read_response *nvr)
{
/* Total size of the parameter field. */
if (ibuf_read_be32(ib, &nvr->params_size))
return -1;
if (unmarshal_TPM2B_MAX_NV_BUFFER(ib, &nvr->buffer))
return -1;
if (nvr->params_size !=
(nvr->buffer.t.size + sizeof(nvr->buffer.t.size))) {
printk(BIOS_ERR,
"%s:%d - parameter/buffer %d/%d size mismatch",
__func__, __LINE__, nvr->params_size,
nvr->buffer.t.size);
return -1;
}
/*
* Let's ignore the authorisation section. It should be 5 bytes total,
* just confirm that this is the case and report any discrepancy.
*/
if (ibuf_remaining(ib) != 5)
printk(BIOS_ERR,
"%s:%d - unexpected authorisation seciton size %zd\n",
__func__, __LINE__, ibuf_remaining(ib));
ibuf_oob_drain(ib, ibuf_remaining(ib));
return 0;
}
static int unmarshal_vendor_command(struct ibuf *ib,
struct vendor_command_response *vcr)
{
if (ibuf_read_be16(ib, &vcr->vc_subcommand))
return -1;
switch (vcr->vc_subcommand) {
case TPM2_CR50_SUB_CMD_NVMEM_ENABLE_COMMITS:
break;
case TPM2_CR50_SUB_CMD_TURN_UPDATE_ON:
return ibuf_read_be8(ib, &vcr->num_restored_headers);
break;
default:
printk(BIOS_ERR,
"%s:%d - unsupported vendor command %#04x!\n",
__func__, __LINE__, vcr->vc_subcommand);
return -1;
}
return 0;
}
struct tpm2_response *tpm_unmarshal_response(TPM_CC command, struct ibuf *ib)
{
static struct tpm2_response tpm2_static_resp CAR_GLOBAL;
struct tpm2_response *tpm2_resp = car_get_var_ptr(&tpm2_static_resp);
int rc = 0;
rc |= ibuf_read_be16(ib, &tpm2_resp->hdr.tpm_tag);
rc |= ibuf_read_be32(ib, &tpm2_resp->hdr.tpm_size);
rc |= unmarshal_TPM_CC(ib, &tpm2_resp->hdr.tpm_code);
if (rc != 0)
return NULL;
if (ibuf_remaining(ib) == 0) {
if (tpm2_resp->hdr.tpm_size != ibuf_nr_read(ib))
printk(BIOS_ERR,
"%s: size mismatch in response to command %#x\n",
__func__, command);
return tpm2_resp;
}
switch (command) {
case TPM2_Startup:
break;
case TPM2_GetCapability:
rc |= unmarshal_get_capability(ib, &tpm2_resp->gc);
break;
case TPM2_NV_Read:
rc |= unmarshal_nv_read(ib, &tpm2_resp->nvr);
break;
case TPM2_Hierarchy_Control:
case TPM2_Clear:
case TPM2_NV_DefineSpace:
case TPM2_NV_Write:
case TPM2_NV_WriteLock:
case TPM2_PCR_Extend:
/* Session data included in response can be safely ignored. */
ibuf_oob_drain(ib, ibuf_remaining(ib));
break;
case TPM2_CR50_VENDOR_COMMAND:
rc |= unmarshal_vendor_command(ib, &tpm2_resp->vcr);
break;
default:
{
size_t i;
size_t sz_left;
const uint8_t *data;
printk(BIOS_INFO, "%s:%d:"
"Request to unmarshal unexpected command %#x,"
" code %#x",
__func__, __LINE__, command,
tpm2_resp->hdr.tpm_code);
sz_left = ibuf_remaining(ib);
data = ibuf_oob_drain(ib, sz_left);
for (i = 0; i < sz_left; i++) {
if (!(i % 16))
printk(BIOS_INFO, "\n");
printk(BIOS_INFO, "%2.2x ", data[i]);
}
}
printk(BIOS_INFO, "\n");
return NULL;
}
if (ibuf_remaining(ib)) {
printk(BIOS_INFO,
"%s:%d got %d bytes back in response to %#x,"
" failed to parse (%zd)\n",
__func__, __LINE__, tpm2_resp->hdr.tpm_size,
command, ibuf_remaining(ib));
return NULL;
}
/* The entire message have been parsed. */
return tpm2_resp;
}

View File

@@ -1,46 +0,0 @@
/*
* Copyright 2016 The Chromium OS Authors. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef __SRC_LIB_TPM2_MARSHALING_H
#define __SRC_LIB_TPM2_MARSHALING_H
#include <commonlib/iobuf.h>
#include "tpm2_tlcl_structures.h"
/* The below functions are used to serialize/deserialize TPM2 commands. */
/**
* tpm_marshal_command
*
* Given a structure containing a TPM2 command, serialize the structure for
* sending it to the TPM.
*
* @command: code of the TPM2 command to marshal
* @tpm_command_body: a pointer to the command specific structure
* @ob: output buffer where command is marshaled to
*
* Returns 0 on success or -1 on error.
*
*/
int tpm_marshal_command(TPM_CC command, void *tpm_command_body,
struct obuf *ob);
/**
* tpm_unmarshal_response
*
* Given a buffer received from the TPM in response to a certain command,
* deserialize the buffer into the expeced response structure.
*
* struct tpm2_response is a union of all possible responses.
*
* @command: code of the TPM2 command for which a response is unmarshaled
* @ib: input buffer containing the serialized response.
*
* Returns a pointer to the deserialized response or NULL in case of
* unmarshaling problems.
*/
struct tpm2_response *tpm_unmarshal_response(TPM_CC command, struct ibuf *ib);
#endif // __SRC_LIB_TPM2_MARSHALING_H

View File

@@ -1,438 +0,0 @@
/*
* Copyright 2016 The Chromium OS Authors. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include <antirollback.h>
#include <arch/early_variables.h>
#include <console/console.h>
#include <endian.h>
#include <lib/tpm2_tlcl_structures.h>
#include <string.h>
#include <tpm.h>
#include <vb2_api.h>
#include "tpm2_marshaling.h"
/*
* This file provides interface between firmware and TPM2 device. The TPM1.2
* API was copied as is and relevant functions modified to comply with the
* TPM2 specification.
*/
static void *tpm_process_command(TPM_CC command, void *command_body)
{
struct obuf ob;
struct ibuf ib;
size_t out_size;
size_t in_size;
const uint8_t *sendb;
/* Command/response buffer. */
static uint8_t cr_buffer[TPM_BUFFER_SIZE] CAR_GLOBAL;
uint8_t *cr_buffer_ptr = car_get_var_ptr(cr_buffer);
obuf_init(&ob, cr_buffer_ptr, sizeof(cr_buffer));
if (tpm_marshal_command(command, command_body, &ob) < 0) {
printk(BIOS_ERR, "command %#x\n", command);
return NULL;
}
sendb = obuf_contents(&ob, &out_size);
in_size = sizeof(cr_buffer);
if (tis_sendrecv(sendb, out_size, cr_buffer_ptr, &in_size)) {
printk(BIOS_ERR, "tpm transaction failed\n");
return NULL;
}
ibuf_init(&ib, cr_buffer_ptr, in_size);
return tpm_unmarshal_response(command, &ib);
}
uint32_t tlcl_get_permanent_flags(TPM_PERMANENT_FLAGS *pflags)
{
printk(BIOS_INFO, "%s:%s:%d\n", __FILE__, __func__, __LINE__);
return TPM_SUCCESS;
}
static uint32_t tlcl_send_startup(TPM_SU type)
{
struct tpm2_startup startup;
struct tpm2_response *response;
startup.startup_type = type;
response = tpm_process_command(TPM2_Startup, &startup);
if (response && response->hdr.tpm_code &&
(response->hdr.tpm_code != TPM_RC_INITIALIZE)) {
printk(BIOS_INFO, "%s: Startup return code is %x\n",
__func__, response->hdr.tpm_code);
return TPM_E_IOERROR;
}
return TPM_SUCCESS;
}
uint32_t tlcl_resume(void)
{
return tlcl_send_startup(TPM_SU_STATE);
}
uint32_t tlcl_assert_physical_presence(void)
{
/*
* Nothing to do on TPM2 for this, use platform hierarchy availability
* instead.
*/
return TPM_SUCCESS;
}
/*
* The caller will provide the digest in a 32 byte buffer, let's consider it a
* sha256 digest.
*/
uint32_t tlcl_extend(int pcr_num, const uint8_t *in_digest,
uint8_t *out_digest)
{
struct tpm2_pcr_extend_cmd pcr_ext_cmd;
struct tpm2_response *response;
pcr_ext_cmd.pcrHandle = HR_PCR + pcr_num;
pcr_ext_cmd.digests.count = 1;
pcr_ext_cmd.digests.digests[0].hashAlg = TPM_ALG_SHA256;
memcpy(pcr_ext_cmd.digests.digests[0].digest.sha256, in_digest,
sizeof(pcr_ext_cmd.digests.digests[0].digest.sha256));
response = tpm_process_command(TPM2_PCR_Extend, &pcr_ext_cmd);
printk(BIOS_INFO, "%s: response is %x\n",
__func__, response ? response->hdr.tpm_code : -1);
if (!response || response->hdr.tpm_code)
return TPM_E_IOERROR;
return TPM_SUCCESS;
}
uint32_t tlcl_finalize_physical_presence(void)
{
/* Nothing needs to be done with tpm2. */
printk(BIOS_INFO, "%s:%s:%d\n", __FILE__, __func__, __LINE__);
return TPM_SUCCESS;
}
uint32_t tlcl_force_clear(void)
{
struct tpm2_response *response;
response = tpm_process_command(TPM2_Clear, NULL);
printk(BIOS_INFO, "%s: response is %x\n",
__func__, response ? response->hdr.tpm_code : -1);
if (!response || response->hdr.tpm_code)
return TPM_E_IOERROR;
return TPM_SUCCESS;
}
uint32_t tlcl_get_flags(uint8_t *disable, uint8_t *deactivated,
uint8_t *nvlocked)
{
/*
* TPM2 does not map directly into these flags TPM1.2 based firmware
* expects to be able to retrieve.
*
* In any case, if any of these conditions are present, the following
* firmware flow would be interrupted and will have a chance to report
* an error. Let's just hardcode an "All OK" response for now.
*/
if (disable)
*disable = 0;
if (nvlocked)
*nvlocked = 1;
if (deactivated)
*deactivated = 0;
return TPM_SUCCESS;
}
static uint8_t tlcl_init_done CAR_GLOBAL;
/* This function is called directly by vboot, uses vboot return types. */
uint32_t tlcl_lib_init(void)
{
uint8_t done = car_get_var(tlcl_init_done);
if (done)
return VB2_SUCCESS;
if (tis_init())
return VB2_ERROR_UNKNOWN;
if (tis_open())
return VB2_ERROR_UNKNOWN;
car_set_var(tlcl_init_done, 1);
return VB2_SUCCESS;
}
uint32_t tlcl_physical_presence_cmd_enable(void)
{
printk(BIOS_INFO, "%s:%s:%d\n", __FILE__, __func__, __LINE__);
return TPM_SUCCESS;
}
uint32_t tlcl_read(uint32_t index, void *data, uint32_t length)
{
struct tpm2_nv_read_cmd nv_readc;
struct tpm2_response *response;
memset(&nv_readc, 0, sizeof(nv_readc));
nv_readc.nvIndex = HR_NV_INDEX + index;
nv_readc.size = length;
response = tpm_process_command(TPM2_NV_Read, &nv_readc);
/* Need to map tpm error codes into internal values. */
if (!response)
return TPM_E_READ_FAILURE;
printk(BIOS_INFO, "%s:%d index %#x return code %x\n",
__FILE__, __LINE__, index, response->hdr.tpm_code);
switch (response->hdr.tpm_code) {
case 0:
break;
/* Uninitialized, returned if the space hasn't been written. */
case TPM_RC_NV_UNINITIALIZED:
/*
* Bad index, cr50 specific value, returned if the space
* hasn't been defined.
*/
case TPM_RC_CR50_NV_UNDEFINED:
return TPM_E_BADINDEX;
default:
return TPM_E_READ_FAILURE;
}
if (length > response->nvr.buffer.t.size)
return TPM_E_RESPONSE_TOO_LARGE;
if (length < response->nvr.buffer.t.size)
return TPM_E_READ_EMPTY;
memcpy(data, response->nvr.buffer.t.buffer, length);
return TPM_SUCCESS;
}
uint32_t tlcl_self_test_full(void)
{
struct tpm2_self_test st;
struct tpm2_response *response;
st.yes_no = 1;
response = tpm_process_command(TPM2_SelfTest, &st);
printk(BIOS_INFO, "%s: response is %x\n",
__func__, response ? response->hdr.tpm_code : -1);
return TPM_SUCCESS;
}
uint32_t tlcl_set_deactivated(uint8_t flag)
{
printk(BIOS_INFO, "%s:%s:%d\n", __FILE__, __func__, __LINE__);
return TPM_SUCCESS;
}
uint32_t tlcl_set_enable(void)
{
printk(BIOS_INFO, "%s:%s:%d\n", __FILE__, __func__, __LINE__);
return TPM_SUCCESS;
}
uint32_t tlcl_lock_nv_write(uint32_t index)
{
struct tpm2_response *response;
/* TPM Wll reject attempts to write at non-defined index. */
struct tpm2_nv_write_lock_cmd nv_wl = {
.nvIndex = HR_NV_INDEX + index,
};
response = tpm_process_command(TPM2_NV_WriteLock, &nv_wl);
printk(BIOS_INFO, "%s: response is %x\n",
__func__, response ? response->hdr.tpm_code : -1);
if (!response || response->hdr.tpm_code)
return TPM_E_IOERROR;
return TPM_SUCCESS;
}
uint32_t tlcl_startup(void)
{
return tlcl_send_startup(TPM_SU_CLEAR);
}
uint32_t tlcl_write(uint32_t index, const void *data, uint32_t length)
{
struct tpm2_nv_write_cmd nv_writec;
struct tpm2_response *response;
memset(&nv_writec, 0, sizeof(nv_writec));
nv_writec.nvIndex = HR_NV_INDEX + index;
nv_writec.data.t.size = length;
nv_writec.data.t.buffer = data;
response = tpm_process_command(TPM2_NV_Write, &nv_writec);
printk(BIOS_INFO, "%s: response is %x\n",
__func__, response ? response->hdr.tpm_code : -1);
/* Need to map tpm error codes into internal values. */
if (!response || response->hdr.tpm_code)
return TPM_E_WRITE_FAILURE;
return TPM_SUCCESS;
}
uint32_t tlcl_define_space(uint32_t space_index, size_t space_size)
{
struct tpm2_nv_define_space_cmd nvds_cmd;
struct tpm2_response *response;
/*
* Different sets of NVRAM space attributes apply to the "ro" spaces,
* i.e. those which should not be possible to delete or modify once
* the RO exits, and the rest of the NVRAM spaces.
*/
const TPMA_NV ro_space_attributes = {
.TPMA_NV_PPWRITE = 1,
.TPMA_NV_AUTHREAD = 1,
.TPMA_NV_PPREAD = 1,
.TPMA_NV_PLATFORMCREATE = 1,
.TPMA_NV_WRITE_STCLEAR = 1,
.TPMA_NV_POLICY_DELETE = 1,
};
const TPMA_NV default_space_attributes = {
.TPMA_NV_PPWRITE = 1,
.TPMA_NV_AUTHREAD = 1,
.TPMA_NV_PPREAD = 1,
.TPMA_NV_PLATFORMCREATE = 1,
};
/* Prepare the define space command structure. */
memset(&nvds_cmd, 0, sizeof(nvds_cmd));
nvds_cmd.publicInfo.dataSize = space_size;
nvds_cmd.publicInfo.nvIndex = HR_NV_INDEX + space_index;
nvds_cmd.publicInfo.nameAlg = TPM_ALG_SHA256;
/* RO only NV spaces should be impossible to destroy. */
if ((space_index == FIRMWARE_NV_INDEX) ||
(space_index == REC_HASH_NV_INDEX)) {
/*
* This policy digest was obtained using TPM2_PolicyPCR
* selecting only PCR_0 with a value of all zeros.
*/
const uint8_t pcr0_unchanged_policy[] = {
0x09, 0x93, 0x3C, 0xCE, 0xEB, 0xB4, 0x41, 0x11,
0x18, 0x81, 0x1D, 0xD4, 0x47, 0x78, 0x80, 0x08,
0x88, 0x86, 0x62, 0x2D, 0xD7, 0x79, 0x94, 0x46,
0x62, 0x26, 0x68, 0x8E, 0xEE, 0xE6, 0x6A, 0xA1
};
nvds_cmd.publicInfo.attributes = ro_space_attributes;
/*
* Use policy digest based on default pcr0 value. This makes
* sure that the space can not be deleted as soon as PCR0
* value has been extended from default.
*/
nvds_cmd.publicInfo.authPolicy.t.buffer = pcr0_unchanged_policy;
nvds_cmd.publicInfo.authPolicy.t.size =
sizeof(pcr0_unchanged_policy);
} else {
nvds_cmd.publicInfo.attributes = default_space_attributes;
}
response = tpm_process_command(TPM2_NV_DefineSpace, &nvds_cmd);
printk(BIOS_INFO, "%s: response is %x\n",
__func__, response ? response->hdr.tpm_code : -1);
if (!response)
return TPM_E_NO_DEVICE;
/* Map TPM2 retrun codes into common vboot represenation. */
switch (response->hdr.tpm_code) {
case TPM2_RC_SUCCESS:
return TPM_SUCCESS;
case TPM2_RC_NV_DEFINED:
return TPM_E_NV_DEFINED;
default:
return TPM_E_INTERNAL_INCONSISTENCY;
}
}
uint32_t tlcl_disable_platform_hierarchy(void)
{
struct tpm2_response *response;
struct tpm2_hierarchy_control_cmd hc = {
.enable = TPM_RH_PLATFORM,
.state = 0,
};
response = tpm_process_command(TPM2_Hierarchy_Control, &hc);
if (!response || response->hdr.tpm_code)
return TPM_E_INTERNAL_INCONSISTENCY;
return TPM_SUCCESS;
}
uint32_t tlcl_cr50_enable_nvcommits(void)
{
uint16_t sub_command = TPM2_CR50_SUB_CMD_NVMEM_ENABLE_COMMITS;
struct tpm2_response *response;
printk(BIOS_INFO, "Enabling cr50 nvmem commmits\n");
response = tpm_process_command(TPM2_CR50_VENDOR_COMMAND, &sub_command);
if (response == NULL || (response && response->hdr.tpm_code)) {
if (response)
printk(BIOS_INFO, "%s: failed %x\n", __func__,
response->hdr.tpm_code);
else
printk(BIOS_INFO, "%s: failed\n", __func__);
return TPM_E_IOERROR;
}
return TPM_SUCCESS;
}
uint32_t tlcl_cr50_enable_update(uint16_t timeout_ms,
uint8_t *num_restored_headers)
{
struct tpm2_response *response;
uint16_t command_body[] = {
TPM2_CR50_SUB_CMD_TURN_UPDATE_ON, timeout_ms
};
printk(BIOS_INFO, "Checking cr50 for pending updates\n");
response = tpm_process_command(TPM2_CR50_VENDOR_COMMAND, command_body);
if (!response || response->hdr.tpm_code)
return TPM_E_INTERNAL_INCONSISTENCY;
*num_restored_headers = response->vcr.num_restored_headers;
return TPM_SUCCESS;
}

View File

@@ -1,372 +0,0 @@
/*
* Copyright 2016 The Chromium OS Authors. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef __SRC_LIB_TPM2_TLCL_STRUCTURES_H
#define __SRC_LIB_TPM2_TLCL_STRUCTURES_H
/*
* This file includes a subset of definitions of TPM protocol version 2.x
* constants and structures needed for functions used in coreboot.
*/
#include <stdint.h>
#include <compiler.h>
#include <tpm_lite/tlcl.h>
#include <types.h>
/* This should be plenty for what firmware needs. */
#define TPM_BUFFER_SIZE 256
/* Basic TPM2 types. */
typedef uint16_t TPM_SU;
typedef uint16_t TPM_ALG_ID;
typedef uint32_t TPM_CC;
typedef uint32_t TPM_HANDLE;
typedef uint32_t TPM_RC;
typedef uint8_t TPMI_YES_NO;
typedef TPM_ALG_ID TPMI_ALG_HASH;
typedef TPM_HANDLE TPMI_DH_PCR;
typedef TPM_HANDLE TPMI_RH_NV_INDEX;
typedef TPM_HANDLE TPMI_RH_ENABLES;
typedef TPM_HANDLE TPMI_SH_AUTH_SESSION;
typedef TPM_HANDLE TPM_RH;
/* Some hardcoded algorithm values. */
#define TPM_ALG_HMAC ((TPM_ALG_ID)0x0005)
#define TPM_ALG_NULL ((TPM_ALG_ID)0x0010)
#define TPM_ALG_SHA1 ((TPM_ALG_ID)0x0004)
#define TPM_ALG_SHA256 ((TPM_ALG_ID)0x000b)
#define SHA256_DIGEST_SIZE 32
/* Some hardcoded hierarchies. */
#define TPM_RH_NULL 0x40000007
#define TPM_RS_PW 0x40000009
#define TPM_RH_PLATFORM 0x4000000C
typedef struct {
uint16_t size;
uint8_t *buffer;
} TPM2B;
/* Relevant TPM Command's structures. */
/* Common command/response header. */
struct tpm_header {
uint16_t tpm_tag;
uint32_t tpm_size;
TPM_CC tpm_code;
} __packed;
/* TPM command codes. */
#define TPM2_Hierarchy_Control ((TPM_CC)0x00000121)
#define TPM2_Clear ((TPM_CC)0x00000126)
#define TPM2_NV_DefineSpace ((TPM_CC)0x0000012A)
#define TPM2_NV_Write ((TPM_CC)0x00000137)
#define TPM2_NV_WriteLock ((TPM_CC)0x00000138)
#define TPM2_SelfTest ((TPM_CC)0x00000143)
#define TPM2_Startup ((TPM_CC)0x00000144)
#define TPM2_NV_Read ((TPM_CC)0x0000014E)
#define TPM2_GetCapability ((TPM_CC)0x0000017A)
#define TPM2_PCR_Extend ((TPM_CC)0x00000182)
/* TPM2 specifies vendor commands need to have this bit set. Vendor command
space is defined by the lower 16 bits. */
#define TPM_CC_VENDOR_BIT_MASK 0x20000000
/* FIXME: below is not enough to differentiate between vendors commands
of numerous devices. However, the current tpm2 APIs aren't very amenable
to extending generically because the marshaling code is assuming all
knowledge of all commands. */
#define TPM2_CR50_VENDOR_COMMAND ((TPM_CC)(TPM_CC_VENDOR_BIT_MASK | 0))
#define TPM2_CR50_SUB_CMD_NVMEM_ENABLE_COMMITS (21)
#define TPM2_CR50_SUB_CMD_TURN_UPDATE_ON (24)
/* Startup values. */
#define TPM_SU_CLEAR 0
#define TPM_SU_STATE 1
#define TPM_HT_PCR 0x00
#define TPM_HT_NV_INDEX 0x01
#define TPM_HT_HMAC_SESSION 0x02
#define TPM_HT_POLICY_SESSION 0x03
#define HR_SHIFT 24
#define HR_PCR (TPM_HT_PCR << HR_SHIFT)
#define HR_HMAC_SESSION (TPM_HT_HMAC_SESSION << HR_SHIFT)
#define HR_POLICY_SESSION (TPM_HT_POLICY_SESSION << HR_SHIFT)
#define HR_TRANSIENT (TPM_HT_TRANSIENT << HR_SHIFT)
#define HR_PERSISTENT (TPM_HT_PERSISTENT << HR_SHIFT)
#define HR_NV_INDEX (TPM_HT_NV_INDEX << HR_SHIFT)
#define HR_PERMANENT (TPM_HT_PERMANENT << HR_SHIFT)
#define PCR_FIRST (HR_PCR + 0)
#define PCR_LAST (PCR_FIRST + IMPLEMENTATION_PCR-1)
#define HMAC_SESSION_FIRST (HR_HMAC_SESSION + 0)
#define HMAC_SESSION_LAST (HMAC_SESSION_FIRST+MAX_ACTIVE_SESSIONS-1)
#define LOADED_SESSION_FIRST HMAC_SESSION_FIRST
#define LOADED_SESSION_LAST HMAC_SESSION_LAST
#define POLICY_SESSION_FIRST (HR_POLICY_SESSION + 0)
#define POLICY_SESSION_LAST (POLICY_SESSION_FIRST + MAX_ACTIVE_SESSIONS-1)
#define TRANSIENT_FIRST (HR_TRANSIENT + 0)
#define ACTIVE_SESSION_FIRST POLICY_SESSION_FIRST
#define ACTIVE_SESSION_LAST POLICY_SESSION_LAST
#define TRANSIENT_LAST (TRANSIENT_FIRST+MAX_LOADED_OBJECTS-1)
#define PERSISTENT_FIRST (HR_PERSISTENT + 0)
#define PERSISTENT_LAST (PERSISTENT_FIRST + 0x00FFFFFF)
#define PLATFORM_PERSISTENT (PERSISTENT_FIRST + 0x00800000)
#define NV_INDEX_FIRST (HR_NV_INDEX + 0)
#define NV_INDEX_LAST (NV_INDEX_FIRST + 0x00FFFFFF)
#define PERMANENT_FIRST TPM_RH_FIRST
#define PERMANENT_LAST TPM_RH_LAST
/* Tpm2 command tags. */
#define TPM_ST_NO_SESSIONS 0x8001
#define TPM_ST_SESSIONS 0x8002
/* Values copied from tpm2/tpm_types.h */
#define RC_VER1 0x100
#define TPM_RC_INITIALIZE ((TPM_RC)(RC_VER1 + 0x000))
#define TPM_RC_NV_UNINITIALIZED ((TPM_RC)(RC_VER1 + 0x04A))
/*
* Cr50 returns this code when an attempt is made to read an NV location which
* has not yet been defined. This is an aggregation of various return code
* extensions which may or may not match if a different TPM2 device is
* used.
*/
#define TPM_RC_CR50_NV_UNDEFINED 0x28b
/* TPM command structures. */
struct tpm2_startup {
TPM_SU startup_type;
};
/* Various TPM capability types to use when querying the device. */
typedef uint32_t TPM_CAP;
#define TPM_CAP_TPM_PROPERTIES ((TPM_CAP)0x00000006)
typedef TPM_HANDLE TPMI_RH_NV_AUTH;
typedef TPM_HANDLE TPMI_RH_NV_INDEX;
/* TPM Property capability constants. */
typedef uint32_t TPM_PT;
#define PT_GROUP 0x00000100
#define PT_VAR (PT_GROUP * 2)
#define TPM_PT_PERMANENT ((TPM_PT)(PT_VAR + 0))
/* Structures of payloads of various TPM2 commands. */
struct tpm2_get_capability {
TPM_CAP capability;
uint32_t property;
uint32_t propertyCount;
};
/* get_capability response when PT_PERMANENT is requested. */
typedef struct {
uint32_t ownerAuthSet : 1;
uint32_t endorsementAuthSet : 1;
uint32_t lockoutAuthSet : 1;
uint32_t reserved3_7 : 5;
uint32_t disableClear : 1;
uint32_t inLockout : 1;
uint32_t tpmGeneratedEPS : 1;
uint32_t reserved11_31 : 21;
} TPMA_PERMANENT;
typedef struct {
uint32_t TPMA_NV_PPWRITE : 1;
uint32_t TPMA_NV_OWNERWRITE : 1;
uint32_t TPMA_NV_AUTHWRITE : 1;
uint32_t TPMA_NV_POLICYWRITE : 1;
uint32_t TPMA_NV_COUNTER : 1;
uint32_t TPMA_NV_BITS : 1;
uint32_t TPMA_NV_EXTEND : 1;
uint32_t reserved7_9 : 3;
uint32_t TPMA_NV_POLICY_DELETE : 1;
uint32_t TPMA_NV_WRITELOCKED : 1;
uint32_t TPMA_NV_WRITEALL : 1;
uint32_t TPMA_NV_WRITEDEFINE : 1;
uint32_t TPMA_NV_WRITE_STCLEAR : 1;
uint32_t TPMA_NV_GLOBALLOCK : 1;
uint32_t TPMA_NV_PPREAD : 1;
uint32_t TPMA_NV_OWNERREAD : 1;
uint32_t TPMA_NV_AUTHREAD : 1;
uint32_t TPMA_NV_POLICYREAD : 1;
uint32_t reserved20_24 : 5;
uint32_t TPMA_NV_NO_DA : 1;
uint32_t TPMA_NV_ORDERLY : 1;
uint32_t TPMA_NV_CLEAR_STCLEAR : 1;
uint32_t TPMA_NV_READLOCKED : 1;
uint32_t TPMA_NV_WRITTEN : 1;
uint32_t TPMA_NV_PLATFORMCREATE : 1;
uint32_t TPMA_NV_READ_STCLEAR : 1;
} TPMA_NV;
typedef union {
struct {
uint16_t size;
const uint8_t *buffer;
} t;
TPM2B b;
} TPM2B_DIGEST;
typedef TPM2B_DIGEST TPM2B_AUTH;
typedef TPM2B_DIGEST TPM2B_NONCE;
typedef struct {
TPM_PT property;
uint32_t value;
} TPMS_TAGGED_PROPERTY;
#define MAX_CAP_DATA (TPM_BUFFER_SIZE - sizeof(struct tpm_header) - \
sizeof(TPMI_YES_NO) - sizeof(TPM_CAP) - sizeof(uint32_t))
#define MAX_TPM_PROPERTIES (MAX_CAP_DATA/sizeof(TPMS_TAGGED_PROPERTY))
/* Somewhat arbitrary, leave enough room for command wrappers. */
#define MAX_NV_BUFFER_SIZE (TPM_BUFFER_SIZE - sizeof(struct tpm_header) - 50)
typedef struct {
uint32_t count;
TPMS_TAGGED_PROPERTY tpmProperty[MAX_TPM_PROPERTIES];
} TPML_TAGGED_TPM_PROPERTY;
typedef union {
TPML_TAGGED_TPM_PROPERTY tpmProperties;
} TPMU_CAPABILITIES;
typedef struct {
TPM_CAP capability;
TPMU_CAPABILITIES data;
} TPMS_CAPABILITY_DATA;
struct get_cap_response {
TPMI_YES_NO more_data;
TPMS_CAPABILITY_DATA cd;
};
typedef struct {
TPMI_RH_NV_INDEX nvIndex;
TPMI_ALG_HASH nameAlg;
TPMA_NV attributes;
TPM2B_DIGEST authPolicy;
uint16_t dataSize;
} TPMS_NV_PUBLIC;
typedef union {
struct {
uint16_t size;
TPMS_NV_PUBLIC nvPublic;
} t;
TPM2B b;
} TPM2B_NV_PUBLIC;
typedef union {
struct {
uint16_t size;
const uint8_t *buffer;
} t;
TPM2B b;
} TPM2B_MAX_NV_BUFFER;
/*
* This is a union, but as of now we support just one digest - sha256, so
* there is just one element.
*/
typedef union {
uint8_t sha256[SHA256_DIGEST_SIZE];
} TPMU_HA;
typedef struct {
TPMI_ALG_HASH hashAlg;
TPMU_HA digest;
} TPMT_HA;
typedef struct {
uint32_t count;
TPMT_HA digests[1]; /* Limit max number of hashes to 1. */
} TPML_DIGEST_VALUES;
struct nv_read_response {
uint32_t params_size;
TPM2B_MAX_NV_BUFFER buffer;
};
struct vendor_command_response {
uint16_t vc_subcommand;
union {
uint8_t num_restored_headers;
};
};
struct tpm2_session_attrs {
uint8_t continueSession : 1;
uint8_t auditExclusive : 1;
uint8_t auditReset : 1;
uint8_t reserved3_4 : 2;
uint8_t decrypt : 1;
uint8_t encrypt : 1;
uint8_t audit : 1;
};
/*
* TPM session header for commands requiring session information. Also
* included in the responses to those commands.
*/
struct tpm2_session_header {
uint32_t session_handle;
uint16_t nonce_size;
uint8_t *nonce;
union {
struct tpm2_session_attrs session_attr_bits;
uint8_t session_attrs;
} __packed;
uint16_t auth_size;
uint8_t *auth;
};
struct tpm2_response {
struct tpm_header hdr;
union {
struct get_cap_response gc;
struct nv_read_response nvr;
struct tpm2_session_header def_space;
struct vendor_command_response vcr;
};
};
struct tpm2_nv_define_space_cmd {
TPM2B_AUTH auth;
TPMS_NV_PUBLIC publicInfo;
};
struct tpm2_nv_write_cmd {
TPMI_RH_NV_INDEX nvIndex;
TPM2B_MAX_NV_BUFFER data;
uint16_t offset;
};
struct tpm2_self_test {
TPMI_YES_NO yes_no;
};
struct tpm2_nv_read_cmd {
TPMI_RH_NV_INDEX nvIndex;
uint16_t size;
uint16_t offset;
};
struct tpm2_nv_write_lock_cmd {
TPMI_RH_NV_INDEX nvIndex;
};
struct tpm2_pcr_extend_cmd {
TPMI_DH_PCR pcrHandle;
TPML_DIGEST_VALUES digests;
};
struct tpm2_hierarchy_control_cmd {
TPMI_RH_ENABLES enable;
TPMI_YES_NO state;
};
#endif // __SRC_LIB_TPM2_TLCL_STRUCTURES_H

View File

@@ -1,255 +0,0 @@
/* Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
/* TPM error codes.
*
* Copy-pasted and lightly edited from TCG TPM Main Part 2 TPM Structures
* Version 1.2 Level 2 Revision 103 26 October 2006 Draft.
*/
#ifndef TPM_ERROR_MESSAGES_H
#define TPM_ERROR_MESSAGES_H
#define TPM_E_BASE 0x0
#define TPM_E_NON_FATAL 0x800
typedef struct tpm_error_info {
const char *name;
uint32_t code;
const char *description;
} tpm_error_info;
tpm_error_info tpm_error_table[] = {
{"TPM_AUTHFAIL", TPM_E_BASE + 1,
"Authentication failed"},
{"TPM_BADINDEX", TPM_E_BASE + 2,
"The index to a PCR, DIR or other register is incorrect"},
{"TPM_BAD_PARAMETER", TPM_E_BASE + 3,
"One or more parameter is bad"},
{"TPM_AUDITFAILURE", TPM_E_BASE + 4,
"An operation completed successfully\n\
but the auditing of that operation failed"},
{"TPM_CLEAR_DISABLED", TPM_E_BASE + 5,
"The clear disable flag is set and all clear operations now require\n\
physical access"},
{"TPM_DEACTIVATED", TPM_E_BASE + 6,
"The TPM is deactivated"},
{"TPM_DISABLED", TPM_E_BASE + 7,
"The TPM is disabled"},
{"TPM_DISABLED_CMD", TPM_E_BASE + 8,
"The target command has been disabled"},
{"TPM_FAIL", TPM_E_BASE + 9,
"The operation failed"},
{"TPM_BAD_ORDINAL", TPM_E_BASE + 10,
"The ordinal was unknown or inconsistent"},
{"TPM_INSTALL_DISABLED", TPM_E_BASE + 11,
"The ability to install an owner is disabled"},
{"TPM_INVALID_KEYHANDLE", TPM_E_BASE + 12,
"The key handle can not be interpreted"},
{"TPM_KEYNOTFOUND", TPM_E_BASE + 13,
"The key handle points to an invalid key"},
{"TPM_INAPPROPRIATE_ENC", TPM_E_BASE + 14,
"Unacceptable encryption scheme"},
{"TPM_MIGRATEFAIL", TPM_E_BASE + 15,
"Migration authorization failed"},
{"TPM_INVALID_PCR_INFO", TPM_E_BASE + 16,
"PCR information could not be interpreted"},
{"TPM_NOSPACE", TPM_E_BASE + 17,
"No room to load key"},
{"TPM_NOSRK", TPM_E_BASE + 18,
"There is no SRK set"},
{"TPM_NOTSEALED_BLOB", TPM_E_BASE + 19,
"An encrypted blob is invalid or was not created by this TPM"},
{"TPM_OWNER_SET", TPM_E_BASE + 20,
"There is already an Owner"},
{"TPM_RESOURCES", TPM_E_BASE + 21,
"The TPM has insufficient internal resources to perform the requested \
action"},
{"TPM_SHORTRANDOM", TPM_E_BASE + 22,
"A random string was too short"},
{"TPM_SIZE", TPM_E_BASE + 23,
"The TPM does not have the space to perform the operation"},
{"TPM_WRONGPCRVAL", TPM_E_BASE + 24,
"The named PCR value does not match the current PCR value"},
{"TPM_BAD_PARAM_SIZE", TPM_E_BASE + 25,
"The paramSize argument to the command has the incorrect value"},
{"TPM_SHA_THREAD", TPM_E_BASE + 26,
"There is no existing SHA-1 thread"},
{"TPM_SHA_ERROR", TPM_E_BASE + 27,
"The calculation is unable to proceed because the existing SHA-1\n\
thread has already encountered an error"},
{"TPM_FAILEDSELFTEST", TPM_E_BASE + 28,
"Self-test has failed and the TPM has shutdown"},
{"TPM_AUTH2FAIL", TPM_E_BASE + 29,
"The authorization for the second key in a 2 key function\n\
failed authorization"},
{"TPM_BADTAG", TPM_E_BASE + 30,
"The tag value sent to for a command is invalid"},
{"TPM_IOERROR", TPM_E_BASE + 31,
"An IO error occurred transmitting information to the TPM"},
{"TPM_ENCRYPT_ERROR", TPM_E_BASE + 32,
"The encryption process had a problem"},
{"TPM_DECRYPT_ERROR", TPM_E_BASE + 33,
"The decryption process did not complete"},
{"TPM_INVALID_AUTHHANDLE", TPM_E_BASE + 34,
"An invalid handle was used"},
{"TPM_NO_ENDORSEMENT", TPM_E_BASE + 35,
"The TPM does not a EK installed"},
{"TPM_INVALID_KEYUSAGE", TPM_E_BASE + 36,
"The usage of a key is not allowed"},
{"TPM_WRONG_ENTITYTYPE", TPM_E_BASE + 37,
"The submitted entity type is not allowed"},
{"TPM_INVALID_POSTINIT", TPM_E_BASE + 38,
"The command was received in the wrong sequence relative to TPM_Init\n\
and a subsequent TPM_Startup"},
{"TPM_INAPPROPRIATE_SIG", TPM_E_BASE + 39,
"Signed data cannot include additional DER information"},
{"TPM_BAD_KEY_PROPERTY", TPM_E_BASE + 40,
"The key properties in TPM_KEY_PARMs are not supported by this TPM"},
{"TPM_BAD_MIGRATION", TPM_E_BASE + 41,
"The migration properties of this key are incorrect"},
{"TPM_BAD_SCHEME", TPM_E_BASE + 42,
"The signature or encryption scheme for this key is incorrect or not\n\
permitted in this situation"},
{"TPM_BAD_DATASIZE", TPM_E_BASE + 43,
"The size of the data (or blob) parameter is bad or inconsistent\n\
with the referenced key"},
{"TPM_BAD_MODE", TPM_E_BASE + 44,
"A mode parameter is bad, such as capArea or subCapArea for\n\
TPM_GetCapability, physicalPresence parameter for TPM_PhysicalPresence,\n\
or migrationType for, TPM_CreateMigrationBlob"},
{"TPM_BAD_PRESENCE", TPM_E_BASE + 45,
"Either the physicalPresence or physicalPresenceLock bits\n\
have the wrong value"},
{"TPM_BAD_VERSION", TPM_E_BASE + 46,
"The TPM cannot perform this version of the capability"},
{"TPM_NO_WRAP_TRANSPORT", TPM_E_BASE + 47,
"The TPM does not allow for wrapped transport sessions"},
{"TPM_AUDITFAIL_UNSUCCESSFUL", TPM_E_BASE + 48,
"TPM audit construction failed and the underlying command\n\
was returning a failure code also"},
{"TPM_AUDITFAIL_SUCCESSFUL", TPM_E_BASE + 49,
"TPM audit construction failed and the underlying command\n\
was returning success"},
{"TPM_NOTRESETABLE", TPM_E_BASE + 50,
"Attempt to reset a PCR register that does not have the resettable \
attribute"},
{"TPM_NOTLOCAL", TPM_E_BASE + 51,
"Attempt to reset a PCR register that requires locality\n\
and locality modifier not part of command transport"},
{"TPM_BAD_TYPE", TPM_E_BASE + 52,
"Make identity blob not properly typed"},
{"TPM_INVALID_RESOURCE", TPM_E_BASE + 53,
"When saving context identified resource type does not match actual \
resource"},
{"TPM_NOTFIPS", TPM_E_BASE + 54,
"The TPM is attempting to execute a command only available when in \
FIPS mode"},
{"TPM_INVALID_FAMILY", TPM_E_BASE + 55,
"The command is attempting to use an invalid family ID"},
{"TPM_NO_NV_PERMISSION", TPM_E_BASE + 56,
"The permission to manipulate the NV storage is not available"},
{"TPM_REQUIRES_SIGN", TPM_E_BASE + 57,
"The operation requires a signed command"},
{"TPM_KEY_NOTSUPPORTED", TPM_E_BASE + 58,
"Wrong operation to load an NV key"},
{"TPM_AUTH_CONFLICT", TPM_E_BASE + 59,
"NV_LoadKey blob requires both owner and blob authorization"},
{"TPM_AREA_LOCKED", TPM_E_BASE + 60,
"The NV area is locked and not writable"},
{"TPM_BAD_LOCALITY", TPM_E_BASE + 61,
"The locality is incorrect for the attempted operation"},
{"TPM_READ_ONLY", TPM_E_BASE + 62,
"The NV area is read only and can't be written to"},
{"TPM_PER_NOWRITE", TPM_E_BASE + 63,
"There is no protection on the write to the NV area"},
{"TPM_FAMILYCOUNT", TPM_E_BASE + 64,
"The family count value does not match"},
{"TPM_WRITE_LOCKED", TPM_E_BASE + 65,
"The NV area has already been written to"},
{"TPM_BAD_ATTRIBUTES", TPM_E_BASE + 66,
"The NV area attributes conflict"},
{"TPM_INVALID_STRUCTURE", TPM_E_BASE + 67,
"The structure tag and version are invalid or inconsistent"},
{"TPM_KEY_OWNER_CONTROL", TPM_E_BASE + 68,
"The key is under control of the TPM Owner and can only be evicted\n\
by the TPM Owner"},
{"TPM_BAD_COUNTER", TPM_E_BASE + 69,
"The counter handle is incorrect"},
{"TPM_NOT_FULLWRITE", TPM_E_BASE + 70,
"The write is not a complete write of the area"},
{"TPM_CONTEXT_GAP", TPM_E_BASE + 71,
"The gap between saved context counts is too large"},
{"TPM_MAXNVWRITES", TPM_E_BASE + 72,
"The maximum number of NV writes without an owner has been exceeded"},
{"TPM_NOOPERATOR", TPM_E_BASE + 73,
"No operator AuthData value is set"},
{"TPM_RESOURCEMISSING", TPM_E_BASE + 74,
"The resource pointed to by context is not loaded"},
{"TPM_DELEGATE_LOCK", TPM_E_BASE + 75,
"The delegate administration is locked"},
{"TPM_DELEGATE_FAMILY", TPM_E_BASE + 76,
"Attempt to manage a family other then the delegated family"},
{"TPM_DELEGATE_ADMIN", TPM_E_BASE + 77,
"Delegation table management not enabled"},
{"TPM_TRANSPORT_NOTEXCLUSIVE", TPM_E_BASE + 78,
"There was a command executed outside of an exclusive transport \
session"},
{"TPM_OWNER_CONTROL", TPM_E_BASE + 79,
"Attempt to context save a owner evict controlled key"},
{"TPM_DAA_RESOURCES", TPM_E_BASE + 80,
"The DAA command has no resources available to execute the command"},
{"TPM_DAA_INPUT_DATA0", TPM_E_BASE + 81,
"The consistency check on DAA parameter inputData0 has failed"},
{"TPM_DAA_INPUT_DATA1", TPM_E_BASE + 82,
"The consistency check on DAA parameter inputData1 has failed"},
{"TPM_DAA_ISSUER_SETTINGS", TPM_E_BASE + 83,
"The consistency check on DAA_issuerSettings has failed"},
{"TPM_DAA_TPM_SETTINGS", TPM_E_BASE + 84,
"The consistency check on DAA_tpmSpecific has failed"},
{"TPM_DAA_STAGE", TPM_E_BASE + 85,
"The atomic process indicated by the submitted DAA command is not\n\
the expected process"},
{"TPM_DAA_ISSUER_VALIDITY", TPM_E_BASE + 86,
"The issuer's validity check has detected an inconsistency"},
{"TPM_DAA_WRONG_W", TPM_E_BASE + 87,
"The consistency check on w has failed"},
{"TPM_BAD_HANDLE", TPM_E_BASE + 88,
"The handle is incorrect"},
{"TPM_BAD_DELEGATE", TPM_E_BASE + 89,
"Delegation is not correct"},
{"TPM_BADCONTEXT", TPM_E_BASE + 90,
"The context blob is invalid"},
{"TPM_TOOMANYCONTEXTS", TPM_E_BASE + 91,
"Too many contexts held by the TPM"},
{"TPM_MA_TICKET_SIGNATURE", TPM_E_BASE + 92,
"Migration authority signature validation failure"},
{"TPM_MA_DESTINATION", TPM_E_BASE + 93,
"Migration destination not authenticated"},
{"TPM_MA_SOURCE", TPM_E_BASE + 94,
"Migration source incorrect"},
{"TPM_MA_AUTHORITY", TPM_E_BASE + 95,
"Incorrect migration authority"},
{"TPM_PERMANENTEK", TPM_E_BASE + 97,
"Attempt to revoke the EK and the EK is not revocable"},
{"TPM_BAD_SIGNATURE", TPM_E_BASE + 98,
"Bad signature of CMK ticket"},
{"TPM_NOCONTEXTSPACE", TPM_E_BASE + 99,
"There is no room in the context list for additional contexts"},
{"TPM_RETRY", TPM_E_BASE + TPM_E_NON_FATAL,
"The TPM is too busy to respond to the command immediately, but\n\
the command could be resubmitted at a later time. The TPM MAY\n\
return TPM_RETRY for any command at any time"},
{"TPM_NEEDS_SELFTEST", TPM_E_BASE + TPM_E_NON_FATAL + 1,
"TPM_ContinueSelfTest has not been run"},
{"TPM_DOING_SELFTEST", TPM_E_BASE + TPM_E_NON_FATAL + 2,
"The TPM is currently executing the actions of TPM_ContinueSelfTest\n\
because the ordinal required resources that have not been tested"},
{"TPM_DEFEND_LOCK_RUNNING", TPM_E_BASE + TPM_E_NON_FATAL + 3,
"The TPM is defending against dictionary attacks and is in some\n\
time-out period"},
};
#endif /* TPM_ERROR_MESSAGES_H */