diff options
-rw-r--r-- | board/cr50/factory_mode.c | 42 | ||||
-rw-r--r-- | common/ccd_config.c | 5 | ||||
-rw-r--r-- | include/ccd_config.h | 9 | ||||
-rw-r--r-- | include/tpm_vendor_cmds.h | 8 |
4 files changed, 64 insertions, 0 deletions
diff --git a/board/cr50/factory_mode.c b/board/cr50/factory_mode.c index c8a5dd2cdd..22d028d4ee 100644 --- a/board/cr50/factory_mode.c +++ b/board/cr50/factory_mode.c @@ -5,6 +5,8 @@ #include "board_id.h" #include "console.h" +#include "ccd_config.h" +#include "extension.h" #include "system.h" #define CPRINTS(format, args...) cprints(CC_CCD, format, ## args) @@ -75,3 +77,43 @@ int board_is_first_factory_boot(void) return (!(system_get_reset_flags() & RESET_FLAG_HIBERNATE) && inactive_image_is_guc_image() && board_id_is_erased()); } + +/* + * Vendor command for ccd factory reset. + * + * This vendor command can be used to enable ccd and disable write protect with + * a factory reset. A factory reset is automatically done during the first + * factory boot, but this vendor command can be used to do a factory reset at + * any time. Before calling factory reset, cr50 will make sure it is safe to do + * so. Cr50 checks batt_is_present to make sure the user has physical access to + * the device. Cr50 also checks ccd isn't disabled by the FWMP or ccd password. + * + * checks: + * - batt_is_present - Factory reset can only be done if HW write protect is + * removed. + * - FWMP disables ccd - If FWMP has disabled ccd, then we can't bypass it with + * a factory reset. + * - CCD password is set - If there is a password, someone will have to use that + * to open ccd and enable ccd manually. A factory reset cannot be + * used to get around the password. + */ +static enum vendor_cmd_rc vc_factory_reset(enum vendor_cmd_cc code, + void *buf, + size_t input_size, + size_t *response_size) +{ + *response_size = 0; + + if (input_size) + return VENDOR_RC_BOGUS_ARGS; + + if (board_battery_is_present() || !board_fwmp_allows_unlock() || + ccd_has_password()) + return VENDOR_RC_NOT_ALLOWED; + + CPRINTF("factory reset\n"); + enable_ccd_factory_mode(); + + return VENDOR_RC_SUCCESS; +} +DECLARE_VENDOR_COMMAND(VENDOR_CC_RESET_FACTORY, vc_factory_reset); diff --git a/common/ccd_config.c b/common/ccd_config.c index c356d0a04e..a3d419356c 100644 --- a/common/ccd_config.c +++ b/common/ccd_config.c @@ -581,6 +581,11 @@ static void ccd_testlab_toggle(void) /******************************************************************************/ /* External interface */ +int ccd_has_password(void) +{ + return raw_has_password(); +} + void ccd_config_init(enum ccd_state state) { /* Set initial state, after making sure it's a valid one */ diff --git a/include/ccd_config.h b/include/ccd_config.h index 7153449883..240feb5240 100644 --- a/include/ccd_config.h +++ b/include/ccd_config.h @@ -276,6 +276,15 @@ int ccd_reset_config(unsigned int flags); void ccd_tpm_reset_callback(void); /** + * Return True if the ccd password is set. It is possible that a pending ccd + * change would set or clear the password, but we don't think this is a big + * issue or risk for now. + * + * @return 1 if password is set, 0 if it's not + */ +int ccd_has_password(void); + +/** * Enter CCD factory mode. This will clear the TPM and do a hard reboot after * updating the ccd config. */ diff --git a/include/tpm_vendor_cmds.h b/include/tpm_vendor_cmds.h index 58bb669d4a..b6b32c3ef7 100644 --- a/include/tpm_vendor_cmds.h +++ b/include/tpm_vendor_cmds.h @@ -55,6 +55,14 @@ enum vendor_cmd_cc { VENDOR_CC_GET_ALERTS_DATA = 35, VENDOR_CC_SPI_HASH = 36, VENDOR_CC_PINWEAVER = 37, + /* + * Check the factory reset settings. If they're all set correctly, do a + * factory reset to enable ccd factory mode. All capabilities will be + * set to Always and write protect will be permanently disabled. This + * mode can't be reset unless VENDOR_CC_DISABLE_FACTORY is called or + * the 'ccd reset' console command is run. + */ + VENDOR_CC_RESET_FACTORY = 38, LAST_VENDOR_COMMAND = 65535, }; |