summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVadim Bendebury <vbendeb@chromium.org>2017-10-26 15:59:27 -0700
committerChromeOS Commit Bot <chromeos-commit-bot@chromium.org>2017-11-13 18:58:34 +0000
commit634a251c739a986650cd6dfc4fd18819d4bc506d (patch)
tree73cb9436326b546e59df02b6e6f1db54d293faa6
parent754117ac43f1767b73230ab3e438f94371c54b6f (diff)
downloadchrome-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.c105
-rw-r--r--include/tpm_vendor_cmds.h1
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,
};