tpm2_lite: implement TlclGetPermissions

Implement TlclGetPermissions, which sends a TPM2_NV_ReadPublic command
and returns the attributes of the NV Index (TPM2 Spec, Part 3, Section 31.6).

BUG=chrome-os-partner:58873
BUG=chrome-os-partner:55210
BRANCH=none
TEST=Run "tpmc def" with various permissions to define new indexes,
     verify that "tpmc getp" returns matching permissions for them.

Change-Id: I2ad7163332ae8793cd717875645f19baef513b26
Reviewed-on: https://chromium-review.googlesource.com/409618
Commit-Ready: Vadim Bendebury <vbendeb@chromium.org>
Tested-by: Andrey Pronin <apronin@chromium.org>
Reviewed-by: Vadim Bendebury <vbendeb@chromium.org>
This commit is contained in:
Andrey Pronin
2016-11-09 20:19:32 -08:00
committed by chrome-bot
parent d28b4e1444
commit 1afcfc1366
3 changed files with 122 additions and 3 deletions

View File

@@ -27,6 +27,7 @@
#define TPM2_Shutdown ((TPM_CC)0x00000145)
#define TPM2_NV_Read ((TPM_CC)0x0000014E)
#define TPM2_NV_ReadLock ((TPM_CC)0x0000014F)
#define TPM2_NV_ReadPublic ((TPM_CC)0x00000169)
#define TPM2_GetCapability ((TPM_CC)0x0000017A)
/* TCG Spec defined, verify for TPM2.
@@ -106,7 +107,7 @@ typedef uint32_t TPMA_NV;
typedef struct {
uint16_t size;
uint8_t *buffer;
} TPM2B, TPM2B_DIGEST, TPM2B_AUTH;
} TPM2B, TPM2B_DIGEST, TPM2B_AUTH, TPM2B_NAME;
typedef union {
struct {
@@ -168,6 +169,10 @@ struct tpm2_nv_write_lock_cmd {
TPMI_RH_NV_INDEX nvIndex;
};
struct tpm2_nv_read_public_cmd {
TPMI_RH_NV_INDEX nvIndex;
};
struct tpm2_hierarchy_control_cmd {
TPMI_RH_ENABLES enable;
TPMI_YES_NO state;
@@ -230,12 +235,18 @@ struct get_capability_response {
TPMS_CAPABILITY_DATA capability_data;
} __attribute__((packed));
struct nv_read_public_response {
TPMS_NV_PUBLIC nvPublic;
TPM2B_NAME nvName;
} __attribute__((packed));
struct tpm2_response {
struct tpm_header hdr;
union {
struct nv_read_response nvr;
struct tpm2_session_header def_space;
struct get_capability_response cap;
struct nv_read_public_response nv_read_public;
};
};

View File

@@ -101,6 +101,9 @@ static uint32_t unmarshal_u32(void **buffer, int *buffer_space)
return value;
}
#define unmarshal_TPM_HANDLE(a, b) unmarshal_u32(a, b)
#define unmarshal_ALG_ID(a, b) unmarshal_u16(a, b)
static void unmarshal_TPM2B_MAX_NV_BUFFER(void **buffer,
int *size,
TPM2B_MAX_NV_BUFFER *nv_buffer)
@@ -156,6 +159,69 @@ static void unmarshal_nv_read(void **buffer, int *size,
unmarshal_authorization_section(buffer, size, "NV_Read");
}
static void unmarshal_TPM2B(void **buffer,
int *size,
TPM2B *tpm2b)
{
tpm2b->size = unmarshal_u16(buffer, size);
if (tpm2b->size > *size) {
VBDEBUG(("%s:%d - "
"size mismatch: expected %d, remaining %d\n",
__func__, __LINE__, tpm2b->size, *size));
*size = -1;
return;
}
tpm2b->buffer = *buffer;
*buffer = ((uint8_t *)(*buffer)) + tpm2b->size;
*size -= tpm2b->size;
}
static void unmarshal_TPMS_NV_PUBLIC(void **buffer,
int *size,
TPMS_NV_PUBLIC *pub)
{
int tpm2b_size = unmarshal_u16(buffer, size);
if (tpm2b_size > *size) {
VBDEBUG(("%s:%d - "
"size mismatch: expected %d, remaining %d\n",
__func__, __LINE__, tpm2b_size, *size));
*size = -1;
return;
}
*size -= tpm2b_size;
pub->nvIndex = unmarshal_TPM_HANDLE(buffer, &tpm2b_size);
pub->nameAlg = unmarshal_ALG_ID(buffer, &tpm2b_size);
pub->attributes = unmarshal_u32(buffer, &tpm2b_size);
unmarshal_TPM2B(buffer, &tpm2b_size, &pub->authPolicy);
pub->dataSize = unmarshal_u16(buffer, &tpm2b_size);
if (tpm2b_size != 0) {
VBDEBUG(("%s:%d - "
"TPMS_NV_PUBLIC size doesn't match the size field\n",
__func__, __LINE__));
*size = -1;
return;
}
}
static void unmarshal_nv_read_public(void **buffer, int *size,
struct nv_read_public_response *nv_pub)
{
unmarshal_TPMS_NV_PUBLIC(buffer, size, &nv_pub->nvPublic);
unmarshal_TPM2B(buffer, size, &nv_pub->nvName);
if (*size > 0) {
VBDEBUG(("%s:%d - "
"extra %d bytes after nvName\n",
__func__, __LINE__, *size));
*size = -1;
return;
}
}
static void unmarshal_TPML_TAGGED_TPM_PROPERTY(void **buffer, int *size,
TPML_TAGGED_TPM_PROPERTY *prop)
{
@@ -499,6 +565,15 @@ static void marshal_nv_write_lock(void **buffer,
marshal_session_header(buffer, &session_header, buffer_space);
}
static void marshal_nv_read_public(void **buffer,
struct tpm2_nv_read_public_cmd *command_body,
int *buffer_space)
{
tpm_tag = TPM_ST_NO_SESSIONS;
marshal_TPM_HANDLE(buffer, command_body->nvIndex, buffer_space);
}
static void marshal_hierarchy_control(void **buffer,
struct tpm2_hierarchy_control_cmd
*command_body,
@@ -600,6 +675,10 @@ int tpm_marshal_command(TPM_CC command, void *tpm_command_body,
marshal_nv_write_lock(&cmd_body, tpm_command_body, &body_size);
break;
case TPM2_NV_ReadPublic:
marshal_nv_read_public(&cmd_body, tpm_command_body, &body_size);
break;
case TPM2_Hierarchy_Control:
marshal_hierarchy_control(&cmd_body,
tpm_command_body, &body_size);
@@ -672,6 +751,11 @@ struct tpm2_response *tpm_unmarshal_response(TPM_CC command,
&tpm2_resp.nvr);
break;
case TPM2_NV_ReadPublic:
unmarshal_nv_read_public(&response_body, &cr_size,
&tpm2_resp.nv_read_public);
break;
case TPM2_GetCapability:
unmarshal_get_capability(&response_body, &cr_size,
&tpm2_resp.cap);

View File

@@ -244,13 +244,37 @@ uint32_t TlclExtend(int pcr_num, const uint8_t *in_digest, uint8_t *out_digest)
return TPM_SUCCESS;
}
static uint32_t tlcl_nv_read_public(uint32_t index,
struct nv_read_public_response **presp)
{
struct tpm2_response *response;
struct tpm2_nv_read_public_cmd read_pub;
memset(&read_pub, 0, sizeof(read_pub));
read_pub.nvIndex = HR_NV_INDEX + index;
response = tpm_process_command(TPM2_NV_ReadPublic, &read_pub);
if (!response || response->hdr.tpm_code)
return TPM_E_IOERROR;
*presp = &response->nv_read_public;
return TPM_SUCCESS;
}
/**
* Get the permission bits for the NVRAM space with |index|.
*/
uint32_t TlclGetPermissions(uint32_t index, uint32_t *permissions)
{
*permissions = 0;
VBDEBUG(("%s called, NOT YET IMPLEMENTED\n", __func__));
uint32_t rv;
struct nv_read_public_response *resp;
rv = tlcl_nv_read_public(index, &resp);
if (rv != TPM_SUCCESS)
return rv;
*permissions = resp->nvPublic.attributes;
return TPM_SUCCESS;
}