summaryrefslogtreecommitdiff
path: root/common/ccd_config.c
diff options
context:
space:
mode:
Diffstat (limited to 'common/ccd_config.c')
-rw-r--r--common/ccd_config.c94
1 files changed, 74 insertions, 20 deletions
diff --git a/common/ccd_config.c b/common/ccd_config.c
index 73f6bb0246..6d19d972d2 100644
--- a/common/ccd_config.c
+++ b/common/ccd_config.c
@@ -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,