diff options
author | Vadim Bendebury <vbendeb@chromium.org> | 2017-10-26 15:59:27 -0700 |
---|---|---|
committer | ChromeOS Commit Bot <chromeos-commit-bot@chromium.org> | 2017-11-13 18:58:34 +0000 |
commit | 634a251c739a986650cd6dfc4fd18819d4bc506d (patch) | |
tree | 73cb9436326b546e59df02b6e6f1db54d293faa6 | |
parent | 754117ac43f1767b73230ab3e438f94371c54b6f (diff) | |
download | chrome-ec-634a251c739a986650cd6dfc4fd18819d4bc506d.tar.gz |
ccd: pass 'ccd password' execution through tpm task context
It is necessary to be able to set password both from the Cr50 console
and through a vendor command.
This patch moves all password management logic to the TPM task context
using the alternative vendor command path.
BRANCH=cr50
BUG=b:62537474
TEST=verified that using Cr50 console CCD password still can be set
and cleared as before.
Change-Id: I0574caf931e3717567fdb270e406643eac47764b
Signed-off-by: Vadim Bendebury <vbendeb@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/740914
Reviewed-by: Randall Spangler <rspangler@chromium.org>
(cherry picked from commit 734fe2d40bbd3f8068a0bfae7d3d10b53d97019c)
Reviewed-on: https://chromium-review.googlesource.com/766073
-rw-r--r-- | common/ccd_config.c | 105 | ||||
-rw-r--r-- | include/tpm_vendor_cmds.h | 1 |
2 files changed, 99 insertions, 7 deletions
diff --git a/common/ccd_config.c b/common/ccd_config.c index f6038f4f1d..5adbe36282 100644 --- a/common/ccd_config.c +++ b/common/ccd_config.c @@ -5,18 +5,24 @@ * Case Closed Debug configuration */ -#include "ccd_config.h" #include "common.h" +#include "byteorder.h" +#include "ccd_config.h" #include "console.h" #include "cryptoc/sha256.h" +#include "cryptoc/util.h" #include "dcrypto.h" +#include "extension.h" #include "hooks.h" #include "nvmem_vars.h" #include "physical_presence.h" +#include "shared_mem.h" #include "system.h" #include "system_chip.h" #include "task.h" #include "timer.h" +#include "tpm_registers.h" +#include "tpm_vendor_cmds.h" #include "trng.h" #define CPRINTS(format, args...) cprints(CC_CCD, format, ## args) @@ -62,6 +68,9 @@ enum ccd_capability_state { #define CCD_PASSWORD_SALT_SIZE 4 #define CCD_PASSWORD_DIGEST_SIZE 16 +/* Way longer than practical. */ +#define CCD_MAX_PASSWORD_SIZE 40 + struct ccd_config { /* Version (CCD_CONFIG_VERSION) */ uint8_t version; @@ -757,25 +766,69 @@ static int command_ccd_set(int argc, char **argv) return ccd_set_cap(cap, new); } -static int command_ccd_password(int argc, char **argv) +static int do_ccd_password(char *password) { /* Only works if unlocked or opened */ if (ccd_state == CCD_STATE_LOCKED) return EC_ERROR_ACCESS_DENIED; - if (argc < 2) - return EC_ERROR_PARAM_COUNT; - /* If password was set from Opened, can't change if just Unlocked */ if (raw_has_password() && ccd_state == CCD_STATE_UNLOCKED && !ccd_get_flag(CCD_FLAG_PASSWORD_SET_WHEN_UNLOCKED)) return EC_ERROR_ACCESS_DENIED; - if (!strcasecmp(argv[1], "clear")) + if (!strcasecmp(password, "clear")) return ccd_reset_password(); /* Set new password */ - return ccd_set_password(argv[1]); + return ccd_set_password(password); +} + +static int command_ccd_password(int argc, char **argv) +{ + struct tpm_cmd_header *tpmh; + int rv; + size_t password_size; + size_t command_size; + + if (argc < 2) + return EC_ERROR_PARAM_COUNT; + + password_size = strlen(argv[1]); + + if (password_size > CCD_MAX_PASSWORD_SIZE) { + ccprintf("Password can not be longer than %d characters\n", + CCD_MAX_PASSWORD_SIZE); + return EC_ERROR_PARAM1; + } + + command_size = sizeof(struct tpm_cmd_header) + password_size; + rv = shared_mem_acquire(command_size, (char **)&tpmh); + 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); + + /* + * 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]); + rv = EC_ERROR_UNKNOWN; + } else { + rv = EC_SUCCESS; + } + + shared_mem_release(tpmh); + return EC_SUCCESS; } static int command_ccd_open(int argc, char **argv) @@ -1062,3 +1115,41 @@ static int command_ccd(int argc, char **argv) DECLARE_SAFE_CONSOLE_COMMAND(ccd, command_ccd, "[help | ...]", "Configure case-closed debugging"); + +/* + * Handle the VENDOR_CC_CCD_PASSWORD command. + * + * 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. + */ +static enum vendor_cmd_rc ccd_password(enum vendor_cmd_cc code, + void *buf, + size_t input_size, + size_t *response_size) +{ + int rv = EC_SUCCESS; + char password[CCD_MAX_PASSWORD_SIZE + 1]; + + if (!input_size || (input_size >= sizeof(password))) { + rv = EC_ERROR_PARAM1; + } else { + memcpy(password, buf, input_size); + password[input_size] = '\0'; + } + + if (rv == EC_SUCCESS) { + rv = do_ccd_password(password); + always_memset(password, 0, input_size); + } + + if (rv != EC_SUCCESS) { + ((uint8_t *)buf)[0] = (uint8_t)rv; + *response_size = 1; + return VENDOR_RC_INTERNAL_ERROR; + } + + *response_size = 0; + return VENDOR_RC_SUCCESS; +} +DECLARE_VENDOR_COMMAND(VENDOR_CC_CCD_PASSWORD, ccd_password); diff --git a/include/tpm_vendor_cmds.h b/include/tpm_vendor_cmds.h index 1166884b7e..93961e793d 100644 --- a/include/tpm_vendor_cmds.h +++ b/include/tpm_vendor_cmds.h @@ -44,6 +44,7 @@ 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, LAST_VENDOR_COMMAND = 65535, }; |