ccd: prepare for handling crucial CCD commands through TPM task context

We want CCD commands lock, open, password, and unlock (at least to
start with) to be available over both CLI and through crosh (i.e.
coming over /dev/tpm0).

Let's allocate a TPM vendor command for handling all CCD subcommands,
and move to this new framework the 'ccd password' command, which
already is available over vendor command.

BRANCH=cr50
BUG=b:62537474
TEST=verified that 'ccd password' still works both over Suzy-Q CLI and
     using gsctool on the target.

Change-Id: I2d06230b762f47af7e580b188a587bc5678ca169
Signed-off-by: Vadim Bendebury <vbendeb@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/853280
Reviewed-by: Randall Spangler <rspangler@chromium.org>
(cherry picked from commit 877e5909b4)
Reviewed-on: https://chromium-review.googlesource.com/896754
This commit is contained in:
Vadim Bendebury 2018-01-05 16:16:07 -08:00 committed by ChromeOS Commit Bot
parent ad8d5cb82a
commit e2fc92801d
4 changed files with 96 additions and 25 deletions

View File

@ -64,6 +64,15 @@ enum ccd_capability_state {
CCD_CAP_STATE_COUNT
};
/*
* CCD command header; including the subcommand code used to demultiplex
* various CCD commands over the same TPM vendor command.
*/
struct ccd_vendor_cmd_header {
struct tpm_cmd_header tpm_header;
uint8_t ccd_subcommand;
} __packed;
/* Size of password salt and digest in bytes */
#define CCD_PASSWORD_SALT_SIZE 4
#define CCD_PASSWORD_DIGEST_SIZE 16
@ -796,7 +805,7 @@ static int do_ccd_password(char *password)
static int command_ccd_password(int argc, char **argv)
{
struct tpm_cmd_header *tpmh;
struct ccd_vendor_cmd_header *vch;
int rv;
size_t password_size;
size_t command_size;
@ -812,32 +821,33 @@ static int command_ccd_password(int argc, char **argv)
return EC_ERROR_PARAM1;
}
command_size = sizeof(struct tpm_cmd_header) + password_size;
rv = shared_mem_acquire(command_size, (char **)&tpmh);
command_size = sizeof(*vch) + password_size;
rv = shared_mem_acquire(command_size, (char **)&vch);
if (rv != EC_SUCCESS)
return rv;
/* Build the extension command to set/clear CCD password. */
tpmh->tag = htobe16(0x8001); /* TPM_ST_NO_SESSIONS */
tpmh->size = htobe32(command_size);
tpmh->command_code = htobe32(TPM_CC_VENDOR_BIT_MASK);
tpmh->subcommand_code = htobe16(VENDOR_CC_CCD_PASSWORD);
memcpy(tpmh + 1, argv[1], password_size);
tpm_alt_extension(tpmh, command_size);
vch->tpm_header.tag = htobe16(0x8001); /* TPM_ST_NO_SESSIONS */
vch->tpm_header.size = htobe32(command_size);
vch->tpm_header.command_code = htobe32(TPM_CC_VENDOR_BIT_MASK);
vch->tpm_header.subcommand_code = htobe16(VENDOR_CC_CCD);
vch->ccd_subcommand = CCDV_PASSWORD;
memcpy(vch + 1, argv[1], password_size);
tpm_alt_extension(&vch->tpm_header, command_size);
/*
* Return status in the command code field now, in case of error,
* error code is the first byte after the header.
*/
if (tpmh->command_code) {
ccprintf("Password setting error %d\n",
((uint8_t *)(tpmh + 1))[0]);
if (vch->tpm_header.command_code) {
ccprintf("Password setting error %d\n", vch->ccd_subcommand);
rv = EC_ERROR_UNKNOWN;
} else {
rv = EC_SUCCESS;
}
shared_mem_release(tpmh);
shared_mem_release(vch);
return EC_SUCCESS;
}
@ -1225,14 +1235,12 @@ static enum vendor_cmd_rc manage_ccd_password(enum vendor_cmd_cc code,
DECLARE_VENDOR_COMMAND(VENDOR_CC_MANAGE_CCD_PWD, manage_ccd_password);
/*
* Handle the VENDOR_CC_CCD_PASSWORD command.
* Handle the CCVD_PASSWORD subcommand.
*
* The payload of the command is a text string to use to set the password. The
* text string set to 'clear' has a special effect though, it clears the
* password instead of setting it.
* The payload of the command is a text string to use to set or clear the
* password.
*/
static enum vendor_cmd_rc ccd_password(enum vendor_cmd_cc code,
void *buf,
static enum vendor_cmd_rc ccd_password(void *buf,
size_t input_size,
size_t *response_size)
{
@ -1264,8 +1272,54 @@ static enum vendor_cmd_rc ccd_password(enum vendor_cmd_cc code,
*response_size = 0;
return VENDOR_RC_SUCCESS;
}
DECLARE_VENDOR_COMMAND(VENDOR_CC_CCD_PASSWORD, ccd_password);
/*
* Common TPM Vendor command handler used to demultiplex various CCD commands
* which need to be available both throuh CLI and over /dev/tpm0.
*/
static enum vendor_cmd_rc ccd_vendor(enum vendor_cmd_cc code,
void *buf,
size_t input_size,
size_t *response_size)
{
enum vendor_cmd_rc (*handler)(void *x, size_t y, size_t *t);
char *buffer;
enum vendor_cmd_rc rc;
/*
* buf points to the next byte after tpm header, i.e. to the CCD
* subcommand. Cache the pointer to make it easier to access and
* manipulate.
*/
buffer = buf;
/* Pick what to do based on subcommand. */
switch (buffer[0]) {
case CCDV_PASSWORD:
handler = ccd_password;
break;
default:
CPRINTS("%s:%d - unknown subcommand\n", __func__, __LINE__);
break;
}
if (handler) {
rc = handler(buf + 1, input_size - 1, response_size);
/*
* Move response up for the master to see it in the right
* place in the response buffer.
*/
memmove(buf, buf + 1, *response_size);
} else {
rc = VENDOR_RC_NO_SUCH_SUBCOMMAND;
*response_size = 0;
}
return rc;
}
DECLARE_VENDOR_COMMAND(VENDOR_CC_CCD, ccd_vendor);
static enum vendor_cmd_rc ccd_disable_rma(enum vendor_cmd_cc code,
void *buf,

View File

@ -27,6 +27,7 @@
#include "config.h"
#include "ccd_config.h"
#include "compile_time_macros.h"
#include "misc_util.h"
#include "signed_header.h"
@ -1582,12 +1583,13 @@ static void process_password(struct transfer_descriptor *td)
}
/*
* Ok, we have a password, let's drop the newline in the end and send
* it down.
* Ok, we have a password, let's move it in the buffer to overwrite
* the newline and free a byte to prepend the subcommand code.
*/
password[--len] = '\0';
memmove(password + 1, password, len - 1);
password[0] = CCDV_PASSWORD;
response_size = sizeof(response);
rv = send_vendor_command(td, VENDOR_CC_CCD_PASSWORD,
rv = send_vendor_command(td, VENDOR_CC_CCD,
password, len,
&response, &response_size);
free(password);

View File

@ -98,6 +98,17 @@ enum ccd_capability {
CCD_CAP_COUNT
};
/*
* Subcommand code, used to pass different CCD commands using the same TPM
* vendor command.
*/
enum ccd_vendor_subcommands {
CCDV_PASSWORD = 0,
CCDV_OPEN = 1,
CCDV_UNLOCK = 2,
CCDV_LOCK = 3,
};
/**
* Initialize CCD configuration at boot.
*

View File

@ -44,9 +44,12 @@ enum vendor_cmd_cc {
VENDOR_CC_POP_LOG_ENTRY = 28,
VENDOR_CC_GET_REC_BTN = 29,
VENDOR_CC_RMA_CHALLENGE_RESPONSE = 30,
VENDOR_CC_CCD_PASSWORD = 31,
/* A gap left for the no longer supported CCD password command. */
VENDOR_CC_DISABLE_RMA = 32,
VENDOR_CC_MANAGE_CCD_PWD = 33,
VENDOR_CC_CCD = 34,
LAST_VENDOR_COMMAND = 65535,
};
@ -69,6 +72,7 @@ enum vendor_cmd_rc {
VENDOR_RC_RESPONSE_TOO_BIG = 5,
VENDOR_RC_INTERNAL_ERROR = 6,
VENDOR_RC_NOT_ALLOWED = 7,
VENDOR_RC_NO_SUCH_SUBCOMMAND = 8,
/* Only 7 bits available; max is 127 */
VENDOR_RC_NO_SUCH_COMMAND = 127,
};