summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRandall Spangler <rspangler@chromium.org>2018-05-18 17:04:59 -0700
committerchrome-bot <chrome-bot@chromium.org>2018-05-25 20:31:56 -0700
commitb3218b9533b607dd53fec13671e3d91b50c0122a (patch)
tree7f34a5cba4328fe9dbe9d013d829f62baa89c8cd
parent13776ebef9af8fc954d16ed922666ea3446df7c5 (diff)
downloadchrome-ec-b3218b9533b607dd53fec13671e3d91b50c0122a.tar.gz
ccd_config: Ccd vendor command takes params struct
This is needed so ccd_open() can see p->flags, for a subsequent change. No change to existing command behavior or binary size. BUG=b:79983505 BRANCH=cr50 TEST=gsctool -I still works Change-Id: I614d8c410e8bc55a5045e253469b2ec222078684 Signed-off-by: Randall Spangler <rspangler@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/1072500 Reviewed-by: Vadim Bendebury <vbendeb@chromium.org>
-rw-r--r--common/ccd_config.c212
-rw-r--r--common/extension.c5
2 files changed, 95 insertions, 122 deletions
diff --git a/common/ccd_config.c b/common/ccd_config.c
index 78fc822d9f..677eb025ca 100644
--- a/common/ccd_config.c
+++ b/common/ccd_config.c
@@ -16,7 +16,6 @@
#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"
@@ -56,6 +55,8 @@ enum ccd_unlock_restrict {
*/
struct ccd_vendor_cmd_header {
struct tpm_cmd_header tpm_header;
+
+ /* On input, the subcommand. On output, may contain EC return code */
uint8_t ccd_subcommand;
} __packed;
@@ -783,7 +784,7 @@ static int do_ccd_password(char *password)
* 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
+ * set, cleared, or entered to open/unlock). If argc value 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,
@@ -791,39 +792,33 @@ static int do_ccd_password(char *password)
*
* Message header is always the same, the payload is the password, if
* supplied.
+ *
+ * Expected output is nothing on success, or a single byte EC return code.
*/
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;
+ uint8_t buf[sizeof(struct ccd_vendor_cmd_header) +
+ CCD_MAX_PASSWORD_SIZE];
+ struct ccd_vendor_cmd_header *vch = (struct ccd_vendor_cmd_header *)buf;
+ size_t password_size = 0;
uint32_t return_code;
if (argc > 1) {
password_size = strlen(password);
-
- if (password_size > CCD_MAX_PASSWORD_SIZE)
+ if (password_size > CCD_MAX_PASSWORD_SIZE)
return EC_ERROR_PARAM1;
- } else {
- password_size = 0;
}
- 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. */
vch->tpm_header.tag = htobe16(0x8001); /* TPM_ST_NO_SESSIONS */
- vch->tpm_header.size = htobe32(command_size);
+ vch->tpm_header.size = htobe32(sizeof(*vch) + password_size);
vch->tpm_header.command_code = htobe32(TPM_CC_VENDOR_BIT_MASK);
vch->tpm_header.subcommand_code = htobe16(VENDOR_CC_CCD);
vch->ccd_subcommand = subcmd;
memcpy(vch + 1, password, password_size);
- tpm_alt_extension(&vch->tpm_header, command_size);
+ tpm_alt_extension(&vch->tpm_header, sizeof(buf));
/*
* Return status in the command code field now, in case of error,
@@ -832,26 +827,20 @@ static int ccd_command_wrapper(int argc, char *password,
return_code = be32toh(vch->tpm_header.command_code);
if ((return_code != EC_SUCCESS) &&
(return_code != VENDOR_RC_IN_PROGRESS)) {
- rv = vch->ccd_subcommand;
- } else {
- rv = EC_SUCCESS;
+ return vch->ccd_subcommand;
}
-
- shared_mem_release(vch);
- return rv;
+ return EC_SUCCESS;
}
-static enum vendor_cmd_rc ccd_open(void *buf,
- size_t input_size,
- size_t *response_size)
+static enum vendor_cmd_rc ccd_open(struct vendor_cmd_params *p)
{
int is_long = 1;
int need_pp = 1;
int rv;
- char *buffer = buf;
+ char *buffer = p->buffer;
if (force_disabled) {
- *response_size = 1;
+ p->out_size = 1;
buffer[0] = EC_ERROR_ACCESS_DENIED;
return VENDOR_RC_NOT_ALLOWED;
}
@@ -861,15 +850,15 @@ static enum vendor_cmd_rc ccd_open(void *buf,
/* FWMP blocks open even if a password is set */
if (!board_fwmp_allows_unlock()) {
- *response_size = 1;
+ p->out_size = 1;
buffer[0] = EC_ERROR_ACCESS_DENIED;
return VENDOR_RC_NOT_ALLOWED;
}
/* If a password is set, check it */
if (raw_has_password()) {
- if (!input_size) {
- *response_size = 1;
+ if (!p->in_size) {
+ p->out_size = 1;
buffer[0] = EC_ERROR_PARAM_COUNT;
return VENDOR_RC_PASSWORD_REQUIRED;
}
@@ -878,10 +867,10 @@ static enum vendor_cmd_rc ccd_open(void *buf,
* We know there is plenty of room in the TPM buffer this is
* stored in.
*/
- buffer[input_size] = '\0';
+ buffer[p->in_size] = '\0';
rv = raw_check_password(buffer);
if (rv) {
- *response_size = 1;
+ p->out_size = 1;
buffer[0] = rv;
return VENDOR_RC_INTERNAL_ERROR;
}
@@ -890,7 +879,7 @@ static enum vendor_cmd_rc ccd_open(void *buf,
/* Fail and abort if already checking physical presence */
if (physical_detect_busy()) {
physical_detect_abort();
- *response_size = 1;
+ p->out_size = 1;
buffer[0] = EC_ERROR_BUSY;
return VENDOR_RC_INTERNAL_ERROR;
}
@@ -912,7 +901,7 @@ static enum vendor_cmd_rc ccd_open(void *buf,
ccprintf("Starting CCD open...\n");
rv = physical_detect_start(is_long, ccd_open_done_async);
if (rv != EC_SUCCESS) {
- *response_size = 1;
+ p->out_size = 1;
buffer[0] = rv;
return VENDOR_RC_INTERNAL_ERROR;
}
@@ -925,16 +914,14 @@ static enum vendor_cmd_rc ccd_open(void *buf,
return VENDOR_RC_SUCCESS;
}
-static enum vendor_cmd_rc ccd_unlock(void *buf,
- size_t input_size,
- size_t *response_size)
+static enum vendor_cmd_rc ccd_unlock(struct vendor_cmd_params *p)
{
int need_pp = 1;
int rv;
- char *buffer = buf;
+ char *buffer = p->buffer;
if (force_disabled) {
- *response_size = 1;
+ p->out_size = 1;
buffer[0] = EC_ERROR_ACCESS_DENIED;
return VENDOR_RC_NOT_ALLOWED;
}
@@ -950,14 +937,14 @@ static enum vendor_cmd_rc ccd_unlock(void *buf,
/* Only allowed if password is already set, and not blocked by FWMP */
if (!raw_has_password() || !board_fwmp_allows_unlock()) {
- *response_size = 1;
+ p->out_size = 1;
buffer[0] = EC_ERROR_ACCESS_DENIED;
return VENDOR_RC_NOT_ALLOWED;
}
/* Make sure password was specified */
- if (!input_size) {
- *response_size = 1;
+ if (!p->in_size) {
+ p->out_size = 1;
buffer[0] = EC_ERROR_PARAM_COUNT;
return VENDOR_RC_PASSWORD_REQUIRED;
}
@@ -966,10 +953,10 @@ static enum vendor_cmd_rc ccd_unlock(void *buf,
* Check the password. We know there is plenty of room in the TPM
* buffer this is stored in.
*/
- buffer[input_size] = '\0';
+ buffer[p->in_size] = '\0';
rv = raw_check_password(buffer);
if (rv) {
- *response_size = 1;
+ p->out_size = 1;
buffer[0] = rv;
return VENDOR_RC_INTERNAL_ERROR;
}
@@ -977,7 +964,7 @@ static enum vendor_cmd_rc ccd_unlock(void *buf,
/* Fail and abort if already checking physical presence */
if (physical_detect_busy()) {
physical_detect_abort();
- *response_size = 1;
+ p->out_size = 1;
buffer[0] = EC_ERROR_BUSY;
return VENDOR_RC_INTERNAL_ERROR;
}
@@ -997,7 +984,7 @@ static enum vendor_cmd_rc ccd_unlock(void *buf,
ccprintf("Starting CCD unlock...\n");
rv = physical_detect_start(0, ccd_unlock_done);
if (rv != EC_SUCCESS) {
- *response_size = 1;
+ p->out_size = 1;
buffer[0] = rv;
return VENDOR_RC_INTERNAL_ERROR;
}
@@ -1010,9 +997,7 @@ static enum vendor_cmd_rc ccd_unlock(void *buf,
return VENDOR_RC_SUCCESS;
}
-static enum vendor_cmd_rc ccd_lock(void *unused0,
- size_t unused1,
- size_t *response_size)
+static enum vendor_cmd_rc ccd_lock(struct vendor_cmd_params *p)
{
/* Lock always works */
ccprintf("CCD locked.\n");
@@ -1295,43 +1280,39 @@ DECLARE_VENDOR_COMMAND(VENDOR_CC_MANAGE_CCD_PWD, manage_ccd_password);
* The payload of the command is a text string to use to set or clear the
* password.
*/
-static enum vendor_cmd_rc ccd_password(void *buf,
- size_t input_size,
- size_t *response_size)
+static enum vendor_cmd_rc ccd_password(struct vendor_cmd_params *p)
{
int rv = EC_SUCCESS;
char password[CCD_MAX_PASSWORD_SIZE + 1];
- char *response = buf;
+ char *response = p->buffer;
if (password_state != PASSWORD_ALLOWED_STATE) {
- *response_size = 1;
+ p->out_size = 1;
*response = EC_ERROR_ACCESS_DENIED;
return VENDOR_RC_NOT_ALLOWED;
}
- if (!input_size || (input_size >= sizeof(password))) {
+ if (!p->in_size || (p->in_size >= sizeof(password))) {
rv = EC_ERROR_PARAM1;
} else {
- memcpy(password, buf, input_size);
- password[input_size] = '\0';
+ memcpy(password, p->buffer, p->in_size);
+ password[p->in_size] = '\0';
rv = do_ccd_password(password);
- always_memset(password, 0, input_size);
+ always_memset(password, 0, p->in_size);
}
if (rv != EC_SUCCESS) {
*response = rv;
- *response_size = 1;
+ p->out_size = 1;
return VENDOR_RC_INTERNAL_ERROR;
}
return VENDOR_RC_SUCCESS;
}
-static enum vendor_cmd_rc ccd_pp_poll(void *buf,
- size_t input_size,
- size_t *response_size)
+static enum vendor_cmd_rc ccd_pp_poll(struct vendor_cmd_params *p)
{
- char *buffer = buf;
+ char *buffer = p->buffer;
if ((ccd_state == CCD_STATE_OPENED) ||
(ccd_state == CCD_STATE_UNLOCKED)) {
@@ -1349,48 +1330,38 @@ static enum vendor_cmd_rc ccd_pp_poll(void *buf,
break;
}
}
- *response_size = 1;
+ p->out_size = 1;
return VENDOR_RC_SUCCESS;
}
-static enum vendor_cmd_rc ccd_pp_poll_unlock(void *buf,
- size_t input_size,
- size_t *response_size)
+static enum vendor_cmd_rc ccd_pp_poll_unlock(struct vendor_cmd_params *p)
{
- char *buffer;
+ char *buffer = p->buffer;
if ((ccd_state != CCD_STATE_OPENED) &&
(ccd_state != CCD_STATE_UNLOCKED))
- return ccd_pp_poll(buf, input_size, response_size);
-
+ return ccd_pp_poll(p);
- buffer = buf;
- *response_size = 1;
+ p->out_size = 1;
buffer[0] = CCD_PP_DONE;
return VENDOR_RC_SUCCESS;
}
-static enum vendor_cmd_rc ccd_pp_poll_open(void *buf,
- size_t input_size,
- size_t *response_size)
+static enum vendor_cmd_rc ccd_pp_poll_open(struct vendor_cmd_params *p)
{
- char *buffer;
+ char *buffer = p->buffer;
if (ccd_state != CCD_STATE_OPENED)
- return ccd_pp_poll(buf, input_size, response_size);
-
+ return ccd_pp_poll(p);
- buffer = buf;
- *response_size = 1;
+ p->out_size = 1;
buffer[0] = CCD_PP_DONE;
return VENDOR_RC_SUCCESS;
}
-static enum vendor_cmd_rc ccd_get_info(void *buf,
- size_t input_size,
- size_t *response_size)
+static enum vendor_cmd_rc ccd_get_info(struct vendor_cmd_params *p)
{
int i;
struct ccd_info_response response = {};
@@ -1418,8 +1389,8 @@ static enum vendor_cmd_rc ccd_get_info(void *buf,
htobe32(response.ccd_caps_defaults[i]);
}
- *response_size = sizeof(response);
- memcpy(buf, &response, sizeof(response));
+ p->out_size = sizeof(response);
+ memcpy(p->buffer, &response, sizeof(response));
return VENDOR_RC_SUCCESS;
}
@@ -1428,21 +1399,30 @@ static enum vendor_cmd_rc ccd_get_info(void *buf,
* 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)
+static enum vendor_cmd_rc ccd_vendor(struct vendor_cmd_params *p)
{
- enum vendor_cmd_rc (*handler)(void *x, size_t y, size_t *t) = NULL;
- char *buffer;
+ enum vendor_cmd_rc (*handler)(struct vendor_cmd_params *p);
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.
+ * The command buffer 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;
+ char *buffer = p->buffer;
+
+ /*
+ * Make sure the buffer is large enough to accommodate any CCD
+ * subcommand response (plus one byte, since the response is shifted),
+ * so we can skip size checks in the processing functions.
+ */
+ if (p->out_size < sizeof(struct ccd_info_response) + 1) {
+ p->out_size = 0;
+ return VENDOR_RC_RESPONSE_TOO_BIG;
+ }
+
+ /* Now we can assume no output data unless proven otherwise */
+ p->out_size = 0;
/* Pick what to do based on subcommand. */
switch (buffer[0]) {
@@ -1476,34 +1456,26 @@ static enum vendor_cmd_rc ccd_vendor(enum vendor_cmd_cc code,
default:
CPRINTS("%s:%d - unknown subcommand\n", __func__, __LINE__);
- break;
+ return VENDOR_RC_NO_SUCH_SUBCOMMAND;
}
- if (handler) {
- /*
- * Let's be optimistic: 0 usually means success.
- *
- * We know the buffer is large enough to accommodate any CCD
- * subcommand response, so there is no size checks in the
- * processing functions.
- */
- *response_size = 0;
-
- 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;
- }
+ /* Shift buffer past the subcommand when calling the handler */
+ p->buffer = buffer + 1;
+ p->in_size--;
+ rc = handler(p);
+ p->buffer = buffer;
+ p->in_size++;
+ /*
+ * Move response up for the master to see it in the right
+ * place in the response buffer. We have to do this because the
+ * first byte of the buffer on input was the subcommand, so we
+ * passed buffer + 1 in the handler call above.
+ */
+ memmove(buffer, buffer + 1, p->out_size);
return rc;
}
-DECLARE_VENDOR_COMMAND(VENDOR_CC_CCD, ccd_vendor);
+DECLARE_VENDOR_COMMAND_P(VENDOR_CC_CCD, ccd_vendor);
static enum vendor_cmd_rc ccd_disable_rma(enum vendor_cmd_cc code,
void *buf,
@@ -1557,7 +1529,7 @@ static enum vendor_cmd_rc ccd_disable_rma(enum vendor_cmd_cc code,
}
- ccd_lock(NULL, 0, NULL);
+ ccd_lock(NULL);
/*
* We do it here to make sure that the device comes out of RMA
diff --git a/common/extension.c b/common/extension.c
index fecb61ec9e..eaded0244f 100644
--- a/common/extension.c
+++ b/common/extension.c
@@ -18,8 +18,9 @@ uint32_t extension_route_command(struct vendor_cmd_params *p)
const char *why_ignore = "not found";
#ifdef DEBUG_EXTENSION
- CPRINTS("%s(%d,%s)", __func__, command_code,
- flags & VENDOR_CMD_FROM_USB ? "USB" : "AP");
+ CPRINTS("%s(%d,%s) is=%d os=%d", __func__, p->code,
+ p->flags & VENDOR_CMD_FROM_USB ? "USB" : "AP",
+ p->in_size, p->out_size);
#endif
/* Filter commands from USB */