diff options
Diffstat (limited to 'common/ccd_config.c')
-rw-r--r-- | common/ccd_config.c | 94 |
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, |