summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--common/ccd_config.c208
-rw-r--r--common/tpm_registers.c7
-rw-r--r--include/tpm_registers.h6
3 files changed, 150 insertions, 71 deletions
diff --git a/common/ccd_config.c b/common/ccd_config.c
index 4b58b84434..cf6871150f 100644
--- a/common/ccd_config.c
+++ b/common/ccd_config.c
@@ -571,13 +571,14 @@ static void ccd_open_done(void)
{
if (!ccd_is_cap_enabled(CCD_CAP_OPEN_WITHOUT_TPM_WIPE)) {
/* Can't open unless wipe succeeds */
- if (board_wipe_tpm() != EC_SUCCESS) {
+ if (tpm_sync_reset(1) != EC_SUCCESS) {
CPRINTS("CCD open TPM wipe failed");
return;
}
}
- if (!ccd_is_cap_enabled(CCD_CAP_UNLOCK_WITHOUT_AP_REBOOT))
+ if (!ccd_is_cap_enabled(CCD_CAP_UNLOCK_WITHOUT_AP_REBOOT) ||
+ !ccd_is_cap_enabled(CCD_CAP_OPEN_WITHOUT_TPM_WIPE))
board_reboot_ap();
CPRINTS("CCD opened");
@@ -805,21 +806,37 @@ static int do_ccd_password(char *password)
}
/*
- * Prepare a message containing a TPM vendor command, have the TPM task
- * process the message and report the result to the caller.
+ * Common wrapper for CCD commands which are passed through the TPM task
+ * context.
+ *
+ * All commands could have a single parameter, which is the password (to be
+ * set, cleared, or entered to open/unlock). If argc calue exceeds 1, the
+ * pointer to password is set, it is checked not to exceed maximum size.
+ *
+ * If the check succeeds, prepare a message containing a TPM vendor command,
+ * have the TPM task process the message and report the result to the caller.
*
- * Message header is always the same, the caller supplies the subcommand code
- * and payload, if any.
+ * Message header is always the same, the payload is the password, if
+ * supplied.
*/
-static int send_vendor_command(enum ccd_vendor_subcommands subcmd,
- void *payload, size_t size)
+static int ccd_command_wrapper(int argc, char *password,
+ enum ccd_vendor_subcommands subcmd)
{
int rv;
struct ccd_vendor_cmd_header *vch;
size_t command_size;
+ size_t password_size;
+
+ if (argc > 1) {
+ password_size = strlen(password);
+ if (password_size > CCD_MAX_PASSWORD_SIZE)
+ return EC_ERROR_PARAM1;
+ } else {
+ password_size = 0;
+ }
- command_size = sizeof(*vch) + size;
+ command_size = sizeof(*vch) + password_size;
rv = shared_mem_acquire(command_size, (char **)&vch);
if (rv != EC_SUCCESS)
return rv;
@@ -831,7 +848,7 @@ static int send_vendor_command(enum ccd_vendor_subcommands subcmd,
vch->tpm_header.subcommand_code = htobe16(VENDOR_CC_CCD);
vch->ccd_subcommand = subcmd;
- memcpy(vch + 1, payload, size);
+ memcpy(vch + 1, password, password_size);
tpm_alt_extension(&vch->tpm_header, command_size);
/*
@@ -846,54 +863,57 @@ static int send_vendor_command(enum ccd_vendor_subcommands subcmd,
}
shared_mem_release(vch);
- return EC_SUCCESS;
-}
-
-static int command_ccd_password(int argc, char **argv)
-{
- size_t password_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;
- }
-
- return send_vendor_command(CCDV_PASSWORD, argv[1], password_size);
+ return rv;
}
-static int command_ccd_open(int argc, char **argv)
+static enum vendor_cmd_rc ccd_open(void *buf,
+ size_t input_size,
+ size_t *response_size)
{
int is_long = 1;
int need_pp = 1;
int rv;
+ char *buffer = buf;
- if (force_disabled)
- return EC_ERROR_ACCESS_DENIED;
+ if (force_disabled) {
+ *response_size = 1;
+ buffer[0] = EC_ERROR_ACCESS_DENIED;
+ return VENDOR_RC_NOT_ALLOWED;
+ }
if (ccd_state == CCD_STATE_OPENED)
- return EC_SUCCESS;
+ return VENDOR_RC_SUCCESS;
if (raw_has_password()) {
- if (argc < 2)
- return EC_ERROR_PARAM_COUNT;
+ if (!input_size) {
+ *response_size = 1;
+ buffer[0] = EC_ERROR_PARAM_COUNT;
+ return VENDOR_RC_INTERNAL_ERROR;
+ }
- rv = raw_check_password(argv[1]);
- if (rv)
- return rv;
+ /*
+ * We know there is plenty of room in the TPM buffer this is
+ * stored in.
+ */
+ buffer[input_size] = '\0';
+ rv = raw_check_password(buffer);
+ if (rv) {
+ *response_size = 1;
+ buffer[0] = rv;
+ return VENDOR_RC_INTERNAL_ERROR;
+ }
} else if (!board_fwmp_allows_unlock()) {
- return EC_ERROR_ACCESS_DENIED;
+ *response_size = 1;
+ buffer[0] = EC_ERROR_ACCESS_DENIED;
+ return VENDOR_RC_NOT_ALLOWED;
}
/* Fail and abort if already checking physical presence */
if (physical_detect_busy()) {
physical_detect_abort();
- return EC_ERROR_BUSY;
+ *response_size = 1;
+ buffer[0] = EC_ERROR_BUSY;
+ return VENDOR_RC_INTERNAL_ERROR;
}
/* Reduce physical presence if enabled via config */
@@ -911,41 +931,65 @@ static int command_ccd_open(int argc, char **argv)
if (need_pp) {
/* Start physical presence detect */
ccprintf("Starting CCD open...\n");
- return physical_detect_start(is_long, ccd_open_done);
+ rv = physical_detect_start(is_long, ccd_open_done);
+ if (rv != EC_SUCCESS) {
+ *response_size = 1;
+ buffer[0] = rv;
+ return VENDOR_RC_INTERNAL_ERROR;
+ }
} else {
/* No physical presence required; go straight to done */
ccd_open_done();
- return EC_SUCCESS;
}
+
+ return VENDOR_RC_SUCCESS;
}
-static int command_ccd_unlock(int argc, char **argv)
+static enum vendor_cmd_rc ccd_unlock(void *buf,
+ size_t input_size,
+ size_t *response_size)
{
int need_pp = 1;
int rv;
+ char *buffer = buf;
- if (force_disabled)
- return EC_ERROR_ACCESS_DENIED;
+ if (force_disabled) {
+ *response_size = 1;
+ buffer[0] = EC_ERROR_ACCESS_DENIED;
+ return VENDOR_RC_NOT_ALLOWED;
+ }
if (ccd_state == CCD_STATE_UNLOCKED)
- return EC_SUCCESS;
+ return VENDOR_RC_SUCCESS;
/* Can go from opened to unlocked with no delay or password */
if (ccd_state == CCD_STATE_OPENED) {
ccd_unlock_done();
- return EC_SUCCESS;
+ return VENDOR_RC_SUCCESS;
}
if (raw_has_password()) {
- if (argc < 2)
- return EC_ERROR_PARAM_COUNT;
+ if (!input_size) {
+ *response_size = 1;
+ buffer[0] = EC_ERROR_PARAM_COUNT;
+ return VENDOR_RC_INTERNAL_ERROR;
+ }
- rv = raw_check_password(argv[1]);
- if (rv)
- return rv;
+ /*
+ * We know there is plenty of room in the TPM buffer this is
+ * stored in.
+ */
+ buffer[input_size] = '\0';
+ rv = raw_check_password(buffer);
+ if (rv) {
+ *response_size = 1;
+ buffer[0] = rv;
+ return VENDOR_RC_INTERNAL_ERROR;
+ }
} else if (!board_fwmp_allows_unlock()) {
- /* Unlock disabled by FWMP */
- return EC_ERROR_ACCESS_DENIED;
+ *response_size = 1;
+ buffer[0] = EC_ERROR_ACCESS_DENIED;
+ return VENDOR_RC_NOT_ALLOWED;
} else {
/*
* When unlock is requested via the console, physical presence
@@ -970,7 +1014,9 @@ static int command_ccd_unlock(int argc, char **argv)
/* Fail and abort if already checking physical presence */
if (physical_detect_busy()) {
physical_detect_abort();
- return EC_ERROR_BUSY;
+ *response_size = 1;
+ buffer[0] = EC_ERROR_BUSY;
+ return VENDOR_RC_INTERNAL_ERROR;
}
/* Bypass physical presence check if configured to do so */
@@ -986,22 +1032,31 @@ static int command_ccd_unlock(int argc, char **argv)
if (need_pp) {
/* Start physical presence detect */
ccprintf("Starting CCD unlock...\n");
- return physical_detect_start(0, ccd_unlock_done);
+ rv = physical_detect_start(0, ccd_unlock_done);
+ if (rv != EC_SUCCESS) {
+ *response_size = 1;
+ buffer[0] = rv;
+ return VENDOR_RC_INTERNAL_ERROR;
+ }
} else {
/* Unlock immediately */
ccd_unlock_done();
- return EC_SUCCESS;
}
+ return VENDOR_RC_SUCCESS;
}
-static int command_ccd_lock(void)
+static enum vendor_cmd_rc ccd_lock(void *unused0,
+ size_t unused1,
+ size_t *response_size)
{
/* Lock always works */
ccprintf("CCD locked.\n");
ccd_set_state(CCD_STATE_LOCKED);
- return EC_SUCCESS;
+ return VENDOR_RC_SUCCESS;
}
+
+
/* NOTE: Testlab command is console-only; no TPM vendor command for this */
static int command_ccd_testlab(int argc, char **argv)
{
@@ -1121,17 +1176,20 @@ static int command_ccd(int argc, char **argv)
/* Commands to set state */
if (!strcasecmp(argv[1], "lock"))
- return command_ccd_lock();
+ return ccd_command_wrapper(0, NULL, CCDV_LOCK);
if (!strcasecmp(argv[1], "unlock"))
- return command_ccd_unlock(argc - 1, argv + 1);
+ return ccd_command_wrapper(argc - 1, argv[2], CCDV_UNLOCK);
if (!strcasecmp(argv[1], "open"))
- return command_ccd_open(argc - 1, argv + 1);
+ return ccd_command_wrapper(argc - 1, argv[2], CCDV_OPEN);
/* Commands to configure capabilities */
if (!strcasecmp(argv[1], "set"))
return command_ccd_set(argc - 1, argv + 1);
- if (!strcasecmp(argv[1], "password"))
- return command_ccd_password(argc - 1, argv + 1);
+ if (!strcasecmp(argv[1], "password")) {
+ if (argc != 3)
+ return EC_ERROR_PARAM_COUNT;
+ return ccd_command_wrapper(argc - 1, argv[2], CCDV_PASSWORD);
+ }
if (!strcasecmp(argv[1], "reset"))
return command_ccd_reset(argc - 1, argv + 1);
@@ -1285,7 +1343,6 @@ static enum vendor_cmd_rc ccd_password(void *buf,
return VENDOR_RC_INTERNAL_ERROR;
}
- *response_size = 0;
return VENDOR_RC_SUCCESS;
}
@@ -1315,12 +1372,26 @@ static enum vendor_cmd_rc ccd_vendor(enum vendor_cmd_cc code,
handler = ccd_password;
break;
+ case CCDV_OPEN:
+ handler = ccd_open;
+ break;
+
+ case CCDV_UNLOCK:
+ handler = ccd_unlock;
+ break;
+
+ case CCDV_LOCK:
+ handler = ccd_lock;
+ break;
+
default:
CPRINTS("%s:%d - unknown subcommand\n", __func__, __LINE__);
break;
}
if (handler) {
+ *response_size = 0; /* Let's be optimistic: 0 means success. */
+
rc = handler(buf + 1, input_size - 1, response_size);
/*
@@ -1387,12 +1458,7 @@ static enum vendor_cmd_rc ccd_disable_rma(enum vendor_cmd_cc code,
}
- rv = command_ccd_lock();
- if (rv != EC_SUCCESS) {
- error_line = __LINE__;
- break;
- }
-
+ ccd_lock(NULL, 0, NULL);
*response_size = 0;
return VENDOR_RC_SUCCESS;
} while (0);
diff --git a/common/tpm_registers.c b/common/tpm_registers.c
index 8c39270a7d..a6d726a2e9 100644
--- a/common/tpm_registers.c
+++ b/common/tpm_registers.c
@@ -879,6 +879,13 @@ static void tpm_reset_now(int wipe_first)
if_start();
}
+int tpm_sync_reset(int wipe_first)
+{
+ tpm_reset_now(wipe_first);
+
+ return wipe_result;
+}
+
void tpm_task(void)
{
uint32_t evt;
diff --git a/include/tpm_registers.h b/include/tpm_registers.h
index 5da9ab6c2f..b82a355170 100644
--- a/include/tpm_registers.h
+++ b/include/tpm_registers.h
@@ -55,6 +55,12 @@ int tpm_reset_request(int wait_until_done, int wipe_nvmem_first);
void tpm_reinstate_nvmem_commits(void);
/*
+ * To be called by functions running on the TPM task context. Returns
+ * EC_SUCCESS on successful reset.
+ */
+int tpm_sync_reset(int wipe_first);
+
+/*
* This structure describes the header of all commands and responses sent and
* received over TPM FIFO.
*