mirror of
https://github.com/Telecominfraproject/OpenCellular.git
synced 2025-12-29 10:00:51 +00:00
cr50: read fwmp and act on it when controlling console restrictions
It needs to be possible to prevent unlocking of CCD on enterprise enrolled devices, in particular to prevent users from moving into dev mode. A bit in the FWMP structure flags field was allocated for the purposes of preventing console unlock in those cases. This patch adds code to read the FWMP structure from the TPM NVMEM, verify it and determine if it should be possible to unlock the console. The restriction is not honored by Cr50 DBG images. The FWMP value is read only once per TPM reset, this means each time the admin console changes the relevant flag bit, the Chrome OS device has to be rebooted to pick up the new flag value. BRANCH=cr50 BUG=b:35587387,b:35587053 TEST=verified that FWMP is properly read and acted upon. Change-Id: I17e15ea2b2293a0c096858fba3ccc389452caede Reviewed-on: https://chromium-review.googlesource.com/457824 Commit-Ready: Vadim Bendebury <vbendeb@chromium.org> Tested-by: Vadim Bendebury <vbendeb@chromium.org> Reviewed-by: Mary Ruthven <mruthven@chromium.org>
This commit is contained in:
committed by
chrome-bot
parent
bff0a80934
commit
fb5a05ab22
@@ -41,6 +41,8 @@
|
||||
#define CONFIG_WP_ALWAYS
|
||||
#define CONFIG_CMD_FLASH
|
||||
|
||||
#define CONFIG_CRC8
|
||||
|
||||
/* We're using TOP_A for partition 0, TOP_B for partition 1 */
|
||||
#define CONFIG_FLASH_NVMEM
|
||||
/* Offset to start of NvMem area from base of flash */
|
||||
|
||||
@@ -49,6 +49,7 @@ board-y += tpm2/stubs.o
|
||||
board-y += tpm2/tpm_state.o
|
||||
board-y += tpm2/trng.o
|
||||
board-y += tpm2/upgrade.o
|
||||
board-y += tpm_nvmem_read.o
|
||||
board-y += wp.o
|
||||
|
||||
# Build and link with an external library
|
||||
|
||||
103
board/cr50/wp.c
103
board/cr50/wp.c
@@ -5,6 +5,7 @@
|
||||
|
||||
#include "common.h"
|
||||
#include "console.h"
|
||||
#include "crc8.h"
|
||||
#include "extension.h"
|
||||
#include "gpio.h"
|
||||
#include "hooks.h"
|
||||
@@ -16,6 +17,7 @@
|
||||
#include "system_chip.h"
|
||||
#include "task.h"
|
||||
#include "timer.h"
|
||||
#include "tpm_nvmem_read.h"
|
||||
#include "tpm_registers.h"
|
||||
#include "util.h"
|
||||
|
||||
@@ -252,9 +254,84 @@ static void init_console_lock_and_wp(void)
|
||||
/* This must run after initializing the NVMem partitions. */
|
||||
DECLARE_HOOK(HOOK_INIT, init_console_lock_and_wp, HOOK_PRIO_DEFAULT+1);
|
||||
|
||||
/*
|
||||
* These definitions and the structure layout were manually copied from
|
||||
* src/platform/vboot_reference/firmware/lib/include/rollback_index.h. at
|
||||
* git sha c7282f6.
|
||||
*/
|
||||
#define FWMP_NV_INDEX 0x100a
|
||||
#define FWMP_HASH_SIZE 32
|
||||
#define FWMP_DEV_DISABLE_CCD_UNLOCK (1 << 6)
|
||||
|
||||
/* Firmware management parameters */
|
||||
struct RollbackSpaceFwmp {
|
||||
/* CRC-8 of fields following struct_size */
|
||||
uint8_t crc;
|
||||
/* Structure size in bytes */
|
||||
uint8_t struct_size;
|
||||
/* Structure version */
|
||||
uint8_t struct_version;
|
||||
/* Reserved; ignored by current reader */
|
||||
uint8_t reserved0;
|
||||
/* Flags; see enum fwmp_flags */
|
||||
uint32_t flags;
|
||||
/* Hash of developer kernel key */
|
||||
uint8_t dev_key_hash[FWMP_HASH_SIZE];
|
||||
} __packed;
|
||||
|
||||
static int lock_enforced(const struct RollbackSpaceFwmp *fwmp)
|
||||
{
|
||||
uint8_t crc;
|
||||
|
||||
/* Let's verify that the FWMP structure makes sense. */
|
||||
if (fwmp->struct_size != sizeof(*fwmp)) {
|
||||
CPRINTS("%s: fwmp size mismatch (%d)\n", __func__,
|
||||
fwmp->struct_size);
|
||||
return 1;
|
||||
}
|
||||
|
||||
crc = crc8(&fwmp->struct_version, sizeof(struct RollbackSpaceFwmp) -
|
||||
offsetof(struct RollbackSpaceFwmp, struct_version));
|
||||
if (fwmp->crc != crc) {
|
||||
CPRINTS("%s: fwmp crc mismatch\n", __func__);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return !!(fwmp->flags & FWMP_DEV_DISABLE_CCD_UNLOCK);
|
||||
}
|
||||
|
||||
static int fwmp_allows_unlock;
|
||||
void read_fwmp(void)
|
||||
{
|
||||
/* Let's see if FWMP disables console activation. */
|
||||
struct RollbackSpaceFwmp fwmp;
|
||||
|
||||
switch (read_tpm_nvmem(FWMP_NV_INDEX,
|
||||
sizeof(struct RollbackSpaceFwmp), &fwmp)) {
|
||||
default:
|
||||
/* Something is messed up, let's not allow console unlock. */
|
||||
fwmp_allows_unlock = 0;
|
||||
break;
|
||||
|
||||
case tpm_read_not_found:
|
||||
fwmp_allows_unlock = 1;
|
||||
break;
|
||||
|
||||
case tpm_read_success:
|
||||
fwmp_allows_unlock = !lock_enforced(&fwmp);
|
||||
break;
|
||||
}
|
||||
|
||||
CPRINTS("Console unlock %sallowed", fwmp_allows_unlock ? "" : "not ");
|
||||
}
|
||||
|
||||
int console_is_restricted(void)
|
||||
{
|
||||
#ifndef CR50_DEV
|
||||
return fwmp_allows_unlock ? console_restricted_state : 1;
|
||||
#else
|
||||
return console_restricted_state;
|
||||
#endif
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
@@ -410,32 +487,32 @@ static const char warning[] = "\n\t!!! WARNING !!!\n\n"
|
||||
|
||||
static int command_lock(int argc, char **argv)
|
||||
{
|
||||
int enabled;
|
||||
int enable;
|
||||
int i;
|
||||
|
||||
#ifndef CR50_DEV
|
||||
/* Don't allow the console to be unlocked at all for prod images. */
|
||||
ASSERT(console_is_restricted() == 1);
|
||||
if (argc > 1)
|
||||
return EC_ERROR_ACCESS_DENIED;
|
||||
|
||||
goto out;
|
||||
#endif /* !defined(CR50_DEV) */
|
||||
|
||||
if (argc > 1) {
|
||||
if (!parse_bool(argv[1], &enabled))
|
||||
if (!parse_bool(argv[1], &enable))
|
||||
return EC_ERROR_PARAM1;
|
||||
|
||||
/* Changing nothing does nothing */
|
||||
if (enabled == console_is_restricted())
|
||||
if (enable == console_is_restricted())
|
||||
goto out;
|
||||
|
||||
/* Locking the console is always allowed */
|
||||
if (enabled) {
|
||||
if (enable) {
|
||||
lock_the_console();
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!fwmp_allows_unlock) {
|
||||
#ifdef CR50_DEV
|
||||
ccprintf("Ignoring FWMP unlock setting\n");
|
||||
#else
|
||||
ccprintf("Managed device console can't be unlocked\n");
|
||||
goto out;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Don't count down if we know it's likely to fail */
|
||||
if (unlock_in_progress) {
|
||||
ccprintf("An unlock process is already in progress\n");
|
||||
|
||||
@@ -3,6 +3,9 @@
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#ifndef __EC_BOARD_CR50_WP_H
|
||||
#define __EC_BOARD_CR50_WP_H
|
||||
|
||||
#include "common.h"
|
||||
|
||||
/**
|
||||
@@ -11,3 +14,11 @@
|
||||
* @param asserted: 0 to disable write protect, otherwise enable write protect.
|
||||
*/
|
||||
void set_wp_state(int asserted);
|
||||
|
||||
/**
|
||||
* Read the FWMP value from TPM NVMEM and set the console restriction
|
||||
* appropriately.
|
||||
*/
|
||||
void read_fwmp(void);
|
||||
|
||||
#endif /* ! __EC_BOARD_CR50_WP_H */
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include "tpm_registers.h"
|
||||
#include "util.h"
|
||||
#include "watchdog.h"
|
||||
#include "wp.h"
|
||||
|
||||
/* TPM2 library includes. */
|
||||
#include "ExecCommand_fp.h"
|
||||
@@ -864,6 +865,10 @@ void tpm_task(void)
|
||||
*/
|
||||
if (command_code == TPM2_PCR_Read)
|
||||
system_process_retry_counter();
|
||||
|
||||
else if (command_code == TPM2_Startup)
|
||||
read_fwmp();
|
||||
|
||||
#ifdef CONFIG_EXTENSION_COMMAND
|
||||
if (!IS_CUSTOM_CODE(command_code))
|
||||
#endif
|
||||
|
||||
@@ -69,5 +69,6 @@ struct tpm_cmd_header {
|
||||
* crosbug.com/p/55667 for detals.
|
||||
*/
|
||||
#define TPM2_PCR_Read 0x0000017e
|
||||
#define TPM2_Startup 0x00000144
|
||||
|
||||
#endif /* __CROS_EC_TPM_REGISTERS_H */
|
||||
|
||||
Reference in New Issue
Block a user