sandbox: tpm: Support nvdata in TPM2
Add support for this feature in the TPM2 emulator, to support Chromium OS vboot. Signed-off-by: Simon Glass <sjg@chromium.org>
This commit is contained in:
@@ -11,6 +11,7 @@
|
|||||||
#include <asm/unaligned.h>
|
#include <asm/unaligned.h>
|
||||||
#include <linux/bitops.h>
|
#include <linux/bitops.h>
|
||||||
#include <u-boot/crc.h>
|
#include <u-boot/crc.h>
|
||||||
|
#include "sandbox_common.h"
|
||||||
|
|
||||||
/* Hierarchies */
|
/* Hierarchies */
|
||||||
enum tpm2_hierarchy {
|
enum tpm2_hierarchy {
|
||||||
@@ -73,6 +74,7 @@ struct sandbox_tpm2 {
|
|||||||
u32 properties[TPM2_PROPERTY_NB];
|
u32 properties[TPM2_PROPERTY_NB];
|
||||||
u8 pcr[SANDBOX_TPM_PCR_NB][TPM2_DIGEST_LEN];
|
u8 pcr[SANDBOX_TPM_PCR_NB][TPM2_DIGEST_LEN];
|
||||||
u32 pcr_extensions[SANDBOX_TPM_PCR_NB];
|
u32 pcr_extensions[SANDBOX_TPM_PCR_NB];
|
||||||
|
struct nvdata_state nvdata[NV_SEQ_COUNT];
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct sandbox_tpm2 s_state, *g_state;
|
static struct sandbox_tpm2 s_state, *g_state;
|
||||||
@@ -109,6 +111,10 @@ static int sandbox_tpm2_check_session(struct udevice *dev, u32 command, u16 tag,
|
|||||||
case TPM2_CC_DAM_RESET:
|
case TPM2_CC_DAM_RESET:
|
||||||
case TPM2_CC_DAM_PARAMETERS:
|
case TPM2_CC_DAM_PARAMETERS:
|
||||||
case TPM2_CC_PCR_EXTEND:
|
case TPM2_CC_PCR_EXTEND:
|
||||||
|
case TPM2_CC_NV_READ:
|
||||||
|
case TPM2_CC_NV_WRITE:
|
||||||
|
case TPM2_CC_NV_WRITELOCK:
|
||||||
|
case TPM2_CC_NV_DEFINE_SPACE:
|
||||||
if (tag != TPM2_ST_SESSIONS) {
|
if (tag != TPM2_ST_SESSIONS) {
|
||||||
printf("Session required for command 0x%x\n", command);
|
printf("Session required for command 0x%x\n", command);
|
||||||
return TPM2_RC_AUTH_CONTEXT;
|
return TPM2_RC_AUTH_CONTEXT;
|
||||||
@@ -137,6 +143,10 @@ static int sandbox_tpm2_check_session(struct udevice *dev, u32 command, u16 tag,
|
|||||||
break;
|
break;
|
||||||
case TPM2_RH_PLATFORM:
|
case TPM2_RH_PLATFORM:
|
||||||
*hierarchy = TPM2_HIERARCHY_PLATFORM;
|
*hierarchy = TPM2_HIERARCHY_PLATFORM;
|
||||||
|
if (command == TPM2_CC_NV_READ ||
|
||||||
|
command == TPM2_CC_NV_WRITE ||
|
||||||
|
command == TPM2_CC_NV_WRITELOCK)
|
||||||
|
*auth += sizeof(u32);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
printf("Wrong handle 0x%x\n", handle);
|
printf("Wrong handle 0x%x\n", handle);
|
||||||
@@ -573,6 +583,64 @@ static int sandbox_tpm2_xfer(struct udevice *dev, const u8 *sendbuf,
|
|||||||
sandbox_tpm2_fill_buf(recv, recv_len, tag, rc);
|
sandbox_tpm2_fill_buf(recv, recv_len, tag, rc);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case TPM2_CC_NV_READ: {
|
||||||
|
int index, seq;
|
||||||
|
|
||||||
|
index = get_unaligned_be32(sendbuf + TPM2_HDR_LEN + 4);
|
||||||
|
length = get_unaligned_be16(sent);
|
||||||
|
/* ignore offset */
|
||||||
|
seq = sb_tpm_index_to_seq(index);
|
||||||
|
if (seq < 0)
|
||||||
|
return log_msg_ret("index", -EINVAL);
|
||||||
|
printf("tpm: nvread index=%#02x, len=%#02x, seq=%#02x\n", index,
|
||||||
|
length, seq);
|
||||||
|
*recv_len = TPM2_HDR_LEN + 6 + length;
|
||||||
|
memset(recvbuf, '\0', *recv_len);
|
||||||
|
put_unaligned_be32(length, recvbuf + 2);
|
||||||
|
sb_tpm_read_data(tpm->nvdata, seq, recvbuf,
|
||||||
|
TPM2_HDR_LEN + 4 + 2, length);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TPM2_CC_NV_WRITE: {
|
||||||
|
int index, seq;
|
||||||
|
|
||||||
|
index = get_unaligned_be32(sendbuf + TPM2_HDR_LEN + 4);
|
||||||
|
length = get_unaligned_be16(sent);
|
||||||
|
sent += sizeof(u16);
|
||||||
|
|
||||||
|
/* ignore offset */
|
||||||
|
seq = sb_tpm_index_to_seq(index);
|
||||||
|
if (seq < 0)
|
||||||
|
return log_msg_ret("index", -EINVAL);
|
||||||
|
printf("tpm: nvwrite index=%#02x, len=%#02x, seq=%#02x\n", index,
|
||||||
|
length, seq);
|
||||||
|
memcpy(&tpm->nvdata[seq].data, sent, length);
|
||||||
|
tpm->nvdata[seq].present = true;
|
||||||
|
*recv_len = TPM2_HDR_LEN + 2;
|
||||||
|
memset(recvbuf, '\0', *recv_len);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TPM2_CC_NV_DEFINE_SPACE: {
|
||||||
|
int policy_size, index, seq;
|
||||||
|
|
||||||
|
policy_size = get_unaligned_be16(sent + 12);
|
||||||
|
index = get_unaligned_be32(sent + 2);
|
||||||
|
sent += 14 + policy_size;
|
||||||
|
length = get_unaligned_be16(sent);
|
||||||
|
seq = sb_tpm_index_to_seq(index);
|
||||||
|
if (seq < 0)
|
||||||
|
return -EINVAL;
|
||||||
|
printf("tpm: define_space index=%x, len=%x, seq=%x, policy_size=%x\n",
|
||||||
|
index, length, seq, policy_size);
|
||||||
|
sb_tpm_define_data(tpm->nvdata, seq, length);
|
||||||
|
*recv_len = 12;
|
||||||
|
memset(recvbuf, '\0', *recv_len);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TPM2_CC_NV_WRITELOCK:
|
||||||
|
*recv_len = 12;
|
||||||
|
memset(recvbuf, '\0', *recv_len);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
printf("TPM2 command %02x unknown in Sandbox\n", command);
|
printf("TPM2 command %02x unknown in Sandbox\n", command);
|
||||||
rc = TPM2_RC_COMMAND_CODE;
|
rc = TPM2_RC_COMMAND_CODE;
|
||||||
|
|||||||
@@ -32,6 +32,8 @@ struct udevice;
|
|||||||
#define TPM2_MAX_TPM_PROPERTIES ((TPM2_MAX_CAP_BUFFER - sizeof(u32) /* TPM2_CAP */ - \
|
#define TPM2_MAX_TPM_PROPERTIES ((TPM2_MAX_CAP_BUFFER - sizeof(u32) /* TPM2_CAP */ - \
|
||||||
sizeof(u32)) / sizeof(struct tpms_tagged_property))
|
sizeof(u32)) / sizeof(struct tpms_tagged_property))
|
||||||
|
|
||||||
|
#define TPM2_HDR_LEN 10
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We deviate from this draft of the specification by increasing the value of
|
* We deviate from this draft of the specification by increasing the value of
|
||||||
* TPM2_NUM_PCR_BANKS from 3 to 16 to ensure compatibility with TPM2
|
* TPM2_NUM_PCR_BANKS from 3 to 16 to ensure compatibility with TPM2
|
||||||
|
|||||||
Reference in New Issue
Block a user