summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVadim Bendebury <vbendeb@chromium.org>2017-10-19 18:53:41 -0700
committerChromeOS Commit Bot <chromeos-commit-bot@chromium.org>2017-10-24 23:30:58 +0000
commit3ce7b41860de0a38ba0f2d561409b5181d87508f (patch)
tree7651299942d45d246a99096e6f8809fc6e289995
parent3f3923c376e75e760aed9a444e96b240f9721a7b (diff)
downloadchrome-ec-3ce7b41860de0a38ba0f2d561409b5181d87508f.tar.gz
rma: process proper auth code
When RMA process has been initialized and the user entered the expected authentication code value, the Cr50 needs to wipe out TPM memory, open and unlock CCD and reboot the device. This patch adds a function to accomplish that. User response is validated on the TPM task context, and TPM reset request also requires TPM task processing. To decouple response processing from the following reset, the response processing is handled by a hook task callback, delayed for 1s to make sure that user receives the response. After TPM has successfully reset the CCD is reinitialized with RMA 'opened' and the device is rebooted. Just in case something goes wrong with the unlock and the hook is not invoked, add a 10s deferred function to take the EC out of reset so that the device still can reboot. BRANCH=none BUG=b:67007905 TEST=on a Bob device: - on the Cr50 console enter 'ccd lock', verify that ccd is locked (by examining output of the 'ccd' command) - at the bash prompt enter gsctool -r -s -t, copy the authentication code from the Cr50 console and pass it to gsctool. - observe the device reset TPM wiping out its memory, enable CCD and reboot. Change-Id: I6fafb5e642cb2b6f2040507a7f1989607fd31316 Signed-off-by: Vadim Bendebury <vbendeb@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/729983 Reviewed-by: Randall Spangler <rspangler@chromium.org> Reviewed-by: Mary Ruthven <mruthven@chromium.org> (cherry picked from commit aeb0c8e4b90e6f5b9a2aaba776e4ed3db675e073) Reviewed-on: https://chromium-review.googlesource.com/736812
-rw-r--r--common/ccd_config.c23
-rw-r--r--common/rma_auth.c76
-rw-r--r--include/ccd_config.h20
3 files changed, 97 insertions, 22 deletions
diff --git a/common/ccd_config.c b/common/ccd_config.c
index 30993ce417..f6038f4f1d 100644
--- a/common/ccd_config.c
+++ b/common/ccd_config.c
@@ -93,21 +93,6 @@ struct ccd_capability_info {
enum ccd_capability_state default_state;
};
-/* Flags for ccd_reset_config() */
-enum ccd_reset_config_flags {
- /* Also reset test lab flag */
- CCD_RESET_TEST_LAB = (1 << 0),
-
- /* Only reset Always/UnlessLocked settings */
- CCD_RESET_UNLOCKED_ONLY = (1 << 1),
-
- /* Use RMA/factory defaults */
- CCD_RESET_RMA = (1 << 2)
-};
-
-/* Forward declarations of static functions */
-static int ccd_reset_config(unsigned flags);
-
/* Nvmem variable name for CCD config */
static const uint8_t k_ccd_config = NVMEM_VAR_CCD_CONFIG;
@@ -454,13 +439,7 @@ static int ccd_set_cap(enum ccd_capability cap, enum ccd_capability_state state)
return ccd_save_config();
}
-/**
- * Reset CCD config to defaults.
- *
- * @param flags Reset flags (see enum ccd_reset_config_flags)
- * @return EC_SUCCESS, or non-zero if error.
- */
-static int ccd_reset_config(unsigned flags)
+int ccd_reset_config(unsigned int flags)
{
int old_lab = ccd_get_flag(CCD_FLAG_TEST_LAB);
diff --git a/common/rma_auth.c b/common/rma_auth.c
index 926dfb1328..2bb5550e9d 100644
--- a/common/rma_auth.c
+++ b/common/rma_auth.c
@@ -8,10 +8,12 @@
#include "common.h"
#include "base32.h"
#include "byteorder.h"
+#include "ccd_config.h"
#include "chip/g/board_id.h"
#include "console.h"
#include "curve25519.h"
#include "extension.h"
+#include "hooks.h"
#include "rma_auth.h"
#include "shared_mem.h"
#include "system.h"
@@ -225,6 +227,78 @@ static enum vendor_cmd_rc get_challenge(uint8_t *buf, size_t *buf_size)
return VENDOR_RC_SUCCESS;
}
+static uint8_t ccd_hook_active;
+
+static void ccd_config_changed(void)
+{
+ if (!ccd_hook_active)
+ return;
+
+ CPRINTF("%s: CCD change saved, rebooting\n", __func__);
+ cflush();
+ system_reset(SYSTEM_RESET_HARD);
+}
+DECLARE_HOOK(HOOK_CCD_CHANGE, ccd_config_changed, HOOK_PRIO_LAST);
+
+static void rma_reset_failed(void)
+{
+ ccd_hook_active = 0;
+ CPRINTF("%s: CCD RMA reset failed\n");
+ deassert_ec_rst();
+}
+DECLARE_DEFERRED(rma_reset_failed);
+
+/* The below time constants are way longer than should be required in practice:
+ *
+ * Time it takes to finish processing TPM command which provided valid RMA
+ * authentication code.
+ */
+#define TPM_PROCESSING_TIME (1 * SECOND)
+
+/*
+ * Time it takse TPM reset function to wipe out the NVMEM and reboot the
+ * device.
+ */
+#define TPM_RESET_TIME (10 * SECOND)
+
+/* Total time deep sleep should not be allowed. */
+#define DISABLE_SLEEP_TIME (TPM_PROCESSING_TIME + TPM_RESET_TIME)
+
+static void enter_rma_mode(void)
+{
+ int rv;
+
+ CPRINTF("%s: resetting TPM\n", __func__);
+
+ /*
+ * Let's make sure the rest of the system is out of the way while TPM
+ * is being wiped out.
+ */
+ assert_ec_rst();
+
+ if (tpm_reset_request(1, 1) != EC_SUCCESS) {
+ CPRINTF("%s: TPM reset attempt failed\n", __func__);
+ deassert_ec_rst();
+ return;
+ }
+
+ tpm_reinstate_nvmem_commits();
+
+ CPRINTF("%s: TPM reset succeeded, RMA resetting CCD\n", __func__);
+
+ ccd_hook_active = 1;
+ rv = ccd_reset_config(CCD_RESET_RMA);
+ if (rv != EC_SUCCESS)
+ rma_reset_failed();
+
+ /*
+ * Make sure we never end up with the EC held in reset, no matter what
+ * prevents the proper RMA flow from succeeding.
+ */
+ hook_call_deferred(&rma_reset_failed_data, TPM_RESET_TIME);
+}
+DECLARE_DEFERRED(enter_rma_mode);
+
/*
* Compare response sent by the operator with the pre-compiled auth code.
* Return error code or success depending on the comparison results.
@@ -249,6 +323,8 @@ static enum vendor_cmd_rc process_response(uint8_t *buf,
if (rv == EC_SUCCESS) {
CPRINTF("%s: success!\n", __func__);
*response_size = 0;
+ delay_sleep_by(DISABLE_SLEEP_TIME);
+ hook_call_deferred(&enter_rma_mode_data, TPM_PROCESSING_TIME);
return VENDOR_RC_SUCCESS;
}
diff --git a/include/ccd_config.h b/include/ccd_config.h
index 333f4552b7..075cb53502 100644
--- a/include/ccd_config.h
+++ b/include/ccd_config.h
@@ -156,4 +156,24 @@ enum ccd_state ccd_get_state(void);
*/
void ccd_disable(void);
+/* Flags for ccd_reset_config() */
+enum ccd_reset_config_flags {
+ /* Also reset test lab flag */
+ CCD_RESET_TEST_LAB = (1 << 0),
+
+ /* Only reset Always/UnlessLocked settings */
+ CCD_RESET_UNLOCKED_ONLY = (1 << 1),
+
+ /* Use RMA/factory defaults */
+ CCD_RESET_RMA = (1 << 2)
+};
+
+/**
+ * Reset CCD config to the desired state.
+ *
+ * @param flags Reset flags (see enum ccd_reset_config_flags)
+ * @return EC_SUCCESS, or non-zero if error.
+ */
+int ccd_reset_config(unsigned int flags);
+
#endif /* __CROS_EC_CCD_CONFIG_H */