diff --git a/src/security/vboot/antirollback.h b/src/security/vboot/antirollback.h index a208c04610..2297762d36 100644 --- a/src/security/vboot/antirollback.h +++ b/src/security/vboot/antirollback.h @@ -28,6 +28,7 @@ enum vb2_pcr_digest; /* 0x100d: Hash of MRC_CACHE training data for non-recovery boot */ #define MRC_RW_HASH_NV_INDEX 0x100d #define HASH_NV_SIZE VB2_SHA256_DIGEST_SIZE +#define ENT_ROLLBACK_COUNTER_INDEX 0x100e /* Zero-Touch Enrollment related spaces */ #define ZTE_BOARD_ID_NV_INDEX 0x3fff00 #define ZTE_RMA_SN_BITS_INDEX 0x3fff01 diff --git a/src/security/vboot/secdata_tpm.c b/src/security/vboot/secdata_tpm.c index 0bc4f839fe..47efe2dd00 100644 --- a/src/security/vboot/secdata_tpm.c +++ b/src/security/vboot/secdata_tpm.c @@ -116,6 +116,17 @@ static const TPMA_NV rw_space_attributes = { .TPMA_NV_WRITE_STCLEAR = 1, }; +const static TPMA_NV rw_counter_attributes = { + .TPMA_NV_AUTHWRITE = 1, + .TPMA_NV_AUTHREAD = 1, + .TPMA_NV_PPREAD = 1, + .TPMA_NV_PPWRITE = 1, + .TPMA_NV_PLATFORMCREATE = 1, + .TPMA_NV_COUNTER = 1, + .TPMA_NV_NO_DA = 1, + .TPMA_NV_WRITE_STCLEAR = 1, +}; + static const TPMA_NV fwmp_attr = { .TPMA_NV_PLATFORMCREATE = 1, .TPMA_NV_OWNERWRITE = 1, @@ -330,6 +341,15 @@ static uint32_t setup_zte_spaces(void) return rv; } +static uint32_t enterprise_rollback_create_counter(void) +{ + /* + * No need to increment the counter to initialize, this can be done later. + */ + return tlcl_define_space(ENT_ROLLBACK_COUNTER_INDEX, /*size=*/8, + rw_counter_attributes, NULL, 0); +} + static uint32_t _factory_initialize_tpm(struct vb2_context *ctx) { RETURN_ON_FAILURE(tlcl_force_clear()); @@ -363,6 +383,14 @@ static uint32_t _factory_initialize_tpm(struct vb2_context *ctx) CONFIG(MAINBOARD_HAS_I2C_TPM_CR50)))) RETURN_ON_FAILURE(setup_zte_spaces()); + /* + * On TPM 2.0, create a counter that survives TPM clear. This allows to + * securely lock data during enterprise rollback by binding to this + * counter's value. + */ + if (CONFIG(CHROMEOS)) + RETURN_ON_FAILURE(enterprise_rollback_create_counter()); + RETURN_ON_FAILURE(setup_firmware_space(ctx)); return TPM_SUCCESS;