Attention is currently required from: Aaron Durbin. Aseda Aboagye has uploaded this change for review. ( https://review.coreboot.org/c/coreboot/+/55242 )
Change subject: security/vboot: Add support for ZTE spaces ......................................................................
security/vboot: Add support for ZTE spaces
This commit adds support for the Chrome OS Zero-Touch Enrollment related spaces. For TPM 2.0 devices which don't use Cr50, coreboot will define the Attested Device ID, Board ID, and RMA counter spaces.
BUG=b:184676425 BRANCH=None TEST=Build and flash lalala, verify that the ZTE spaces are created successfully.
Signed-off-by: Aseda Aboagye aaboagye@google.com Change-Id: I97e3ae7e18fc9ee9a02afadbbafeb226b41af0eb --- M src/security/vboot/antirollback.h M src/security/vboot/secdata_tpm.c 2 files changed, 124 insertions(+), 15 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/42/55242/1
diff --git a/src/security/vboot/antirollback.h b/src/security/vboot/antirollback.h index fcfa7a2..a208c04 100644 --- a/src/security/vboot/antirollback.h +++ b/src/security/vboot/antirollback.h @@ -28,6 +28,10 @@ /* 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 +/* Zero-Touch Enrollment related spaces */ +#define ZTE_BOARD_ID_NV_INDEX 0x3fff00 +#define ZTE_RMA_SN_BITS_INDEX 0x3fff01 +#define ZTE_RMA_BYTES_COUNTER_INDEX 0x3fff04
/* Structure definitions for TPM spaces */
diff --git a/src/security/vboot/secdata_tpm.c b/src/security/vboot/secdata_tpm.c index dd36796..1cc1888 100644 --- a/src/security/vboot/secdata_tpm.c +++ b/src/security/vboot/secdata_tpm.c @@ -117,6 +117,29 @@ .TPMA_NV_PPWRITE = 1, };
+/* Attributes for spaces that enable zero-touch enrollment (ZTE) */ +static const TPMA_NV zte_attr = { + .TPMA_NV_PLATFORMCREATE = 1, + .TPMA_NV_WRITEDEFINE = 1, + .TPMA_NV_AUTHWRITE = 1, + .TPMA_NV_AUTHREAD = 1, + .TPMA_NV_PPWRITE =1, + .TPMA_NV_PPREAD = 1, + .TPMA_NV_NO_DA = 1, + .TPMA_NV_POLICY_DELETE = 1, +}; + +static const TPMA_NV zte_rma_bytes_attr = { + .TPMA_NV_PLATFORMCREATE = 1, + .TPMA_NV_BITS = 1, + .TPMA_NV_AUTHWRITE = 1, + .TPMA_NV_AUTHREAD = 1, + .TPMA_NV_PPWRITE =1, + .TPMA_NV_PPREAD = 1, + .TPMA_NV_NO_DA = 1, + .TPMA_NV_POLICY_DELETE = 1, +}; + /* * This policy digest was obtained using TPM2_PolicyOR on 3 digests * corresponding to a sequence of @@ -154,6 +177,30 @@ 0x50, 0xEF, 0x96, 0x98, 0x0A, 0x2B, 0x96, 0x6E, 0xA9, 0x09, 0x04, 0x4A, 0x01, 0xB8, 0x5F, 0xA5, 0x4A, 0x96, 0xFC, 0x59, 0x84};
+static uint32_t define_space(const char *name, uint32_t index, uint32_t length, + const TPMA_NV nv_attributes, + const uint8_t *nv_policy, size_t nv_policy_size) +{ + uint32_t rv; + + rv = tlcl_define_space(index, length, nv_attributes, nv_policy, + nv_policy_size); + if (rv == TPM_E_NV_DEFINED) { + /* + * Continue with writing: it may be defined, but not written + * to. In that case a subsequent tlcl_read() would still return + * TPM_E_BADINDEX on TPM 2.0. The cases when some non-firmware + * space is defined while the firmware space is not there + * should be rare (interru pted initialization), so no big harm + * in writing once again even if it was written already. + */ + VBDEBUG("%s: %s space already exists\n", __func__, name); + rv = TPM_SUCCESS; + } + + return rv; +} + /* Nothing special in the TPM2 path yet. */ static uint32_t safe_write(uint32_t index, const void *data, uint32_t length) { @@ -166,21 +213,8 @@ { uint32_t rv;
- rv = tlcl_define_space(index, length, nv_attributes, nv_policy, - nv_policy_size); - if (rv == TPM_E_NV_DEFINED) { - /* - * Continue with writing: it may be defined, but not written - * to. In that case a subsequent tlcl_read() would still return - * TPM_E_BADINDEX on TPM 2.0. The cases when some non-firmware - * space is defined while the firmware space is not there - * should be rare (interrupted initialization), so no big harm - * in writing once again even if it was written already. - */ - VBDEBUG("%s: %s space already exists\n", __func__, name); - rv = TPM_SUCCESS; - } - + rv = define_space(name, index, length, nv_attributes, nv_policy, + nv_policy_size); if (rv != TPM_SUCCESS) return rv;
@@ -225,6 +259,69 @@ } }
+/** + * Setup the Zero-Touch Enrollment(ZTE) related spaces. + * + * These spaces are not used by firmware, but we do need to initialize them. + */ +static uint32_t setup_zte_spaces(void) +{ + uint32_t rv; + uint64_t rma_bytes_counter_default = 0; + uint8_t rma_sn_bits_default[16]; + uint8_t board_id_default[12]; + + /* Initialize defaults: Board ID and RMA+SN Bits must be intialized to + all 0xFFs. */ + for (int i = 0; i < ARRAY_SIZE(rma_sn_bits_default); i++) + rma_sn_bits_default[i] = 0xFF; + + for (int i = 0; i < ARRAY_SIZE(board_id_default); i++) + board_id_default[i] = 0xFF; + + /* Setup RMA + SN Bits */ + rv = setup_space("RMA + SN Bits", ZTE_RMA_SN_BITS_INDEX, + rma_sn_bits_default, sizeof(rma_sn_bits_default), + zte_attr, + pcr0_allowed_policy, sizeof(pcr0_allowed_policy)); + if (rv != TPM_SUCCESS) { + VBDEBUG("%s: Failed to setup RMA + SN Bits space\n", __func__); + return rv; + } + + /* Setup Board ID */ + rv = setup_space("Board ID", ZTE_BOARD_ID_NV_INDEX, + board_id_default, sizeof(board_id_default), + zte_attr, + pcr0_allowed_policy, sizeof(pcr0_allowed_policy)); + if (rv != TPM_SUCCESS) { + VBDEBUG("%s: Failed to setup Board ID space\n", __func__); + return rv; + } + + /* Setup RMA Bytes counter */ + rv = define_space("RMA Bytes Counter", ZTE_RMA_BYTES_COUNTER_INDEX, + sizeof(rma_bytes_counter_default), + zte_rma_bytes_attr, + pcr0_allowed_policy, sizeof(pcr0_allowed_policy)); + if (rv != TPM_SUCCESS) { + VBDEBUG("%s: Failed to define RMA Bytes space\n", __func__); + return rv; + } + + /* + * Since the RMA counter has the BITS attribute, we need to call + * TPM2_NV_SetBits() in order to initialize it. + */ + rv = tlcl_set_bits(ZTE_RMA_BYTES_COUNTER_INDEX, 0); + if (rv != TPM_SUCCESS) { + VBDEBUG("%s: Failed to init RMA Bytes space\n", __func__); + return rv; + } + + return rv; +} + static uint32_t _factory_initialize_tpm(struct vb2_context *ctx) { RETURN_ON_FAILURE(tlcl_force_clear()); @@ -250,6 +347,14 @@ /* Define and write firmware management parameters space. */ RETURN_ON_FAILURE(setup_fwmp_space(ctx));
+ /* + * Define and write zero-touch enrollment (ZTE) spaces. For Cr50 devices, + * these are setup elsewhere via TPM vendor commands. + */ + if (!(CONFIG(MAINBOARD_HAS_SPI_TPM_CR50) || + CONFIG(MAINBOARD_HAS_I2C_TPM_CR50))) + RETURN_ON_FAILURE(setup_zte_spaces()); + RETURN_ON_FAILURE(setup_firmware_space(ctx));
return TPM_SUCCESS;