Particularly when using secure boot with signed TLVs, it may be required to issue and sign TLVs for specific units. As typically all units of a board are compiled to validate TLVs against the same key, a "binding" mechanism is needed if interchange of TLVs across those units must be prevented. This mapping binds against the UID of the SoC, rendering a signed TLV with such a field invalid for all but the one unit.
When generating TLVs that use this mapping, the exact case-sensitive string representation of the SoC UID must be taken into account. Add the special mapping tlv_bind_soc_uid that aborts TLV parsing if the supplied string does not match the SoC UID number. Include this mapping in barebox_tlv_v1_mappings with tag 0x0024 to make it available in testing and in other setups using the generic tlv parsers. Set up tlv_register_default as a late initcall so that it's loaded after the SoC UID was initialized. Signed-off-by: Jonas Rebmann <[email protected]> --- Changes in v2: - Switch to using barebox_get_soc_uid and rename and reword everything accordingly (serial number -> soc uid) - Init tlv_register_default as late_initcall instead of device_initcall - Link to v1: https://lore.barebox.org/barebox/[email protected] --- common/tlv/barebox.c | 18 +++++++++++++++++- include/tlv/tlv.h | 1 + 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/common/tlv/barebox.c b/common/tlv/barebox.c index 24de3eeaaa..fdba9fa2a5 100644 --- a/common/tlv/barebox.c +++ b/common/tlv/barebox.c @@ -1,8 +1,12 @@ // SPDX-License-Identifier: GPL-2.0-only +#include "barebox-info.h" #include <common.h> #include <net.h> #include <tlv/tlv.h> +#include <param.h> +#include <string.h> + int tlv_handle_serial(struct tlv_device *dev, struct tlv_mapping *map, u16 len, const u8 *val) { @@ -16,6 +20,16 @@ int tlv_handle_serial(struct tlv_device *dev, struct tlv_mapping *map, u16 len, return 0; } +int tlv_bind_soc_uid(struct tlv_device *dev, struct tlv_mapping *map, u16 len, const u8 *val) +{ + char *tlv_serial = basprintf("%.*s", len, val); + + if (streq_ptr(tlv_serial, barebox_get_soc_uid())) + return __tlv_format_str(dev, map, len, val) ? 0 : -ENOMEM; + + return -EACCES; +} + int tlv_handle_eth_address(struct tlv_device *dev, struct tlv_mapping *map, u16 len, const u8 *val) { int i; @@ -169,6 +183,8 @@ struct tlv_mapping barebox_tlv_v1_mappings[] = { { 0x0011, tlv_handle_eth_address, "ethernet-address" }, /* A sequence of multiple Ethernet addresses */ { 0x0012, tlv_handle_eth_address_seq, "ethernet-address" }, + /* Reject TLVs if device serial number string does not match CPU serial */ + { 0x0024, tlv_bind_soc_uid, "bound-soc_uid"}, { /* sentintel */ }, }; @@ -212,4 +228,4 @@ static int tlv_register_default(void) } return 0; } -device_initcall(tlv_register_default); +late_initcall(tlv_register_default); diff --git a/include/tlv/tlv.h b/include/tlv/tlv.h index 536f61646c..54e3afed45 100644 --- a/include/tlv/tlv.h +++ b/include/tlv/tlv.h @@ -37,6 +37,7 @@ extern int tlv_format_hex(struct tlv_device *dev, struct tlv_mapping *map, u16 l extern int tlv_format_mac(struct tlv_device *dev, struct tlv_mapping *map, u16 len, const u8 *val); extern int tlv_format_blob(struct tlv_device *dev, struct tlv_mapping *map, u16 len, const u8 *val); extern int tlv_handle_serial(struct tlv_device *dev, struct tlv_mapping *map, u16 len, const u8 *val); +extern int tlv_bind_soc_uid(struct tlv_device *dev, struct tlv_mapping *map, u16 len, const u8 *val); extern int tlv_handle_eth_address(struct tlv_device *dev, struct tlv_mapping *map, u16 len, const u8 *val); extern int tlv_handle_eth_address_seq(struct tlv_device *dev, struct tlv_mapping *map, u16 len, const u8 *val); --- base-commit: bafc52d7dc93accb213271e3e5c267c4335d8cb2 change-id: 20251112-tlv_bind_serial-b8b24a6fd4a0 Best regards, -- Jonas Rebmann <[email protected]>
