From d23a46b42fb0f5b580797289e05ed7cb350f00e6 Mon Sep 17 00:00:00 2001 From: Tyson Jones Date: Thu, 11 Jun 2026 11:22:41 -0600 Subject: [PATCH 1/5] handle parsing protected tlv region --- src/smpclient/mcuboot.py | 41 +++++++++++++----- .../fixtures/tf-m-9a4cb1a28/tfm_s_signed.bin | Bin 0 -> 524288 bytes tests/test_mcuboot_tools.py | 23 +++++++++- 3 files changed, 53 insertions(+), 11 deletions(-) create mode 100644 tests/fixtures/tf-m-9a4cb1a28/tfm_s_signed.bin diff --git a/src/smpclient/mcuboot.py b/src/smpclient/mcuboot.py index 4e81acc..8a5ca31 100644 --- a/src/smpclient/mcuboot.py +++ b/src/smpclient/mcuboot.py @@ -237,9 +237,9 @@ class ImageTLVInfo: def __post_init__(self) -> None: """Do initial validation of the header.""" - if self.magic != IMAGE_TLV_INFO_MAGIC: + if self.magic not in (IMAGE_TLV_INFO_MAGIC, IMAGE_TLV_PROT_INFO_MAGIC): raise MCUBootImageError( - f"TLV info magic is {hex(self.magic)}, expected {hex(IMAGE_TLV_INFO_MAGIC)}" + f"TLV info magic is {hex(self.magic)}, expected {hex(IMAGE_TLV_INFO_MAGIC)} or {hex(IMAGE_TLV_PROT_INFO_MAGIC)}" ) @staticmethod @@ -266,7 +266,6 @@ def load_from(file: BytesIO | BufferedReader) -> 'ImageTLV': """Load an `ImageTLV` from a file.""" return ImageTLV(*IMAGE_TLV_STRUCT.unpack_from(file.read(IMAGE_TLV_STRUCT.size))) - @dataclass(frozen=True) class ImageTLVValue: header: ImageTLV @@ -292,6 +291,8 @@ class ImageInfo: header: ImageHeader tlv_info: ImageTLVInfo tlvs: list[ImageTLVValue] + protected_tlv_info: ImageTLVInfo | None = None + protected_tlvs: list[ImageTLVValue] = Field(default_factory=lambda: []) file: str | None = None def get_tlv(self, tlv: ImageTLVType) -> ImageTLVValue: @@ -301,6 +302,16 @@ def get_tlv(self, tlv: ImageTLVType) -> ImageTLVValue: else: raise TLVNotFound(f"{tlv} not found in image.") + @staticmethod + def parse_tlvs(f: BytesIO, tlvs_end_offset: int) -> list[ImageTLVValue]: + """Parse TLVs from the current position in the file up to the given byte offset.""" + tlvs: list[ImageTLVValue] = [] + while f.tell() < tlvs_end_offset: + tlv_header = ImageTLV.load_from(f) + tlvs.append(ImageTLVValue(header=tlv_header, value=f.read(tlv_header.len))) + + return tlvs + @staticmethod def load_file(path: str) -> 'ImageInfo': """Load MCUBoot `ImageInfo` from the file at `path`. @@ -325,18 +336,22 @@ def load_file(path: str) -> 'ImageInfo': tlv_offset = image_header.hdr_size + image_header.img_size f.seek(tlv_offset) # move to the start of the TLV area - tlv_info = ImageTLVInfo.load_from(f) - tlvs: list[ImageTLVValue] = [] - while f.tell() < tlv_offset + tlv_info.tlv_tot: - tlv_header = ImageTLV.load_from(f) - tlvs.append(ImageTLVValue(header=tlv_header, value=f.read(tlv_header.len))) + # The mcuboot design doc says that optional protected TLV entries come before regular TLV entries + protected_tlvs = [] + protected_tlv_info = None + if image_header.protect_tlv_size > 0: + protected_tlv_info = ImageTLVInfo.load_from(f) + protected_tlvs = ImageInfo.parse_tlvs(f, tlv_offset + protected_tlv_info.tlv_tot) - return ImageInfo(file=path, header=image_header, tlv_info=tlv_info, tlvs=tlvs) + tlv_info = ImageTLVInfo.load_from(f) + tlvs = ImageInfo.parse_tlvs(f, tlv_offset + (protected_tlv_info.tlv_tot if protected_tlv_info else 0) + tlv_info.tlv_tot) + + return ImageInfo(file=path, header=image_header, tlv_info=tlv_info, tlvs=tlvs, protected_tlv_info=protected_tlv_info, protected_tlvs=protected_tlvs) @cached_property def _map_tlv_type_to_value(self) -> dict[int, ImageTLVValue]: - return {tlv.header.type: tlv for tlv in self.tlvs} + return {tlv.header.type: tlv for tlv in (*self.tlvs, *self.protected_tlvs)} def __str__(self) -> str: rep = ( @@ -348,6 +363,12 @@ def __str__(self) -> str: for tlv in self.tlvs: rep += f" {str(tlv)}\n" + if self.protected_tlv_info: + rep += f"{self.protected_tlv_info}\n" + + for tlv in self.protected_tlvs: + rep += f" {str(tlv)}\n" + return rep diff --git a/tests/fixtures/tf-m-9a4cb1a28/tfm_s_signed.bin b/tests/fixtures/tf-m-9a4cb1a28/tfm_s_signed.bin new file mode 100644 index 0000000000000000000000000000000000000000..5fe4c1fc97702688ea498a1d16451672f89f1e02 GIT binary patch literal 524288 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 z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ gfB*pk1m0fY=wIIT None: image_info = ImageInfo.load_file(str(image.PATH)) @@ -230,3 +229,25 @@ def test_tlv_value_str_unknown() -> None: tlv_header = ImageTLV(type=0x99, len=4) tlv_value = ImageTLVValue(header=tlv_header, value=b"\xde\xad\xbe\xef") assert str(tlv_value) == "0x99=deadbeef" + +def test_protected_tlv_parsing() -> None: + """Test that protected TLVs are parsed correctly when present.""" + + # tfm_s_signed.bin generated via https://docs.zephyrproject.org/latest/samples/tfm_integration/tfm_ipc/README.html#tfm_ipc + image_info = ImageInfo.load_file(str(Path("tests", "fixtures", "tf-m-9a4cb1a28", "tfm_s_signed.bin"))) + + assert image_info.protected_tlv_info is not None + assert len(image_info.protected_tlvs) == 3 + assert len(image_info.tlvs) == 3 + + # imgtool should put these three regular TLVs in the image + image_info.get_tlv(IMAGE_TLV.SHA256) + image_info.get_tlv(IMAGE_TLV.KEYHASH) + image_info.get_tlv(IMAGE_TLV.ECDSA_SIG) + + # and these three protected TLVs + image_info.get_tlv(IMAGE_TLV.SEC_CNT) + image_info.get_tlv(IMAGE_TLV.BOOT_RECORD) + image_info.get_tlv(IMAGE_TLV.DEPENDENCY) + + From 9d990409cbb59fc94364a51fa6f6e05529cefc55 Mon Sep 17 00:00:00 2001 From: Tyson Jones Date: Thu, 11 Jun 2026 11:33:39 -0600 Subject: [PATCH 2/5] fixed linter error --- tests/test_mcuboot_tools.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/test_mcuboot_tools.py b/tests/test_mcuboot_tools.py index a6b1151..40f2162 100644 --- a/tests/test_mcuboot_tools.py +++ b/tests/test_mcuboot_tools.py @@ -232,7 +232,6 @@ def test_tlv_value_str_unknown() -> None: def test_protected_tlv_parsing() -> None: """Test that protected TLVs are parsed correctly when present.""" - # tfm_s_signed.bin generated via https://docs.zephyrproject.org/latest/samples/tfm_integration/tfm_ipc/README.html#tfm_ipc image_info = ImageInfo.load_file(str(Path("tests", "fixtures", "tf-m-9a4cb1a28", "tfm_s_signed.bin"))) From ec448a2f6dfcadb7434d5e88b3b5f9c85da12ff5 Mon Sep 17 00:00:00 2001 From: Tyson Jones Date: Thu, 11 Jun 2026 12:03:12 -0600 Subject: [PATCH 3/5] validation, formatting, made TLV parse function pure --- src/smpclient/mcuboot.py | 39 ++++++++++++++++++++++++++++--------- tests/test_mcuboot_tools.py | 8 +++++--- 2 files changed, 35 insertions(+), 12 deletions(-) diff --git a/src/smpclient/mcuboot.py b/src/smpclient/mcuboot.py index 8a5ca31..a95aa54 100644 --- a/src/smpclient/mcuboot.py +++ b/src/smpclient/mcuboot.py @@ -235,6 +235,8 @@ class ImageTLVInfo: tlv_tot: int """size of TLV area (including tlv_info header)""" + REGION_SIZE = IMAGE_TLV_INFO_STRUCT.size + def __post_init__(self) -> None: """Do initial validation of the header.""" if self.magic not in (IMAGE_TLV_INFO_MAGIC, IMAGE_TLV_PROT_INFO_MAGIC): @@ -266,6 +268,7 @@ def load_from(file: BytesIO | BufferedReader) -> 'ImageTLV': """Load an `ImageTLV` from a file.""" return ImageTLV(*IMAGE_TLV_STRUCT.unpack_from(file.read(IMAGE_TLV_STRUCT.size))) + @dataclass(frozen=True) class ImageTLVValue: header: ImageTLV @@ -303,10 +306,11 @@ def get_tlv(self, tlv: ImageTLVType) -> ImageTLVValue: raise TLVNotFound(f"{tlv} not found in image.") @staticmethod - def parse_tlvs(f: BytesIO, tlvs_end_offset: int) -> list[ImageTLVValue]: - """Parse TLVs from the current position in the file up to the given byte offset.""" + def parse_tlvs(region: bytes) -> list[ImageTLVValue]: + """Parse TLVs from a byte sequence.""" tlvs: list[ImageTLVValue] = [] - while f.tell() < tlvs_end_offset: + f = BytesIO(region) + while f.tell() < len(region): tlv_header = ImageTLV.load_from(f) tlvs.append(ImageTLVValue(header=tlv_header, value=f.read(tlv_header.len))) @@ -338,16 +342,33 @@ def load_file(path: str) -> 'ImageInfo': f.seek(tlv_offset) # move to the start of the TLV area # The mcuboot design doc says that optional protected TLV entries come before regular TLV entries - protected_tlvs = [] - protected_tlv_info = None + protected_tlvs: list[ImageTLVValue] = [] + protected_tlv_info: ImageTLVInfo | None = None if image_header.protect_tlv_size > 0: protected_tlv_info = ImageTLVInfo.load_from(f) - protected_tlvs = ImageInfo.parse_tlvs(f, tlv_offset + protected_tlv_info.tlv_tot) + if protected_tlv_info.magic != IMAGE_TLV_PROT_INFO_MAGIC: + raise MCUBootImageError( + f"Protected TLV info magic is {hex(protected_tlv_info.magic)}, expected {hex(IMAGE_TLV_PROT_INFO_MAGIC)}" + ) + protected_tlvs = ImageInfo.parse_tlvs( + f.read(protected_tlv_info.tlv_tot - ImageTLVInfo.REGION_SIZE) + ) tlv_info = ImageTLVInfo.load_from(f) - tlvs = ImageInfo.parse_tlvs(f, tlv_offset + (protected_tlv_info.tlv_tot if protected_tlv_info else 0) + tlv_info.tlv_tot) - - return ImageInfo(file=path, header=image_header, tlv_info=tlv_info, tlvs=tlvs, protected_tlv_info=protected_tlv_info, protected_tlvs=protected_tlvs) + if tlv_info.magic != IMAGE_TLV_INFO_MAGIC: + raise MCUBootImageError( + f"TLV info magic is {hex(tlv_info.magic)}, expected {hex(IMAGE_TLV_INFO_MAGIC)}" + ) + tlvs = ImageInfo.parse_tlvs(f.read(tlv_info.tlv_tot - ImageTLVInfo.REGION_SIZE)) + + return ImageInfo( + file=path, + header=image_header, + tlv_info=tlv_info, + tlvs=tlvs, + protected_tlv_info=protected_tlv_info, + protected_tlvs=protected_tlvs, + ) @cached_property def _map_tlv_type_to_value(self) -> dict[int, ImageTLVValue]: diff --git a/tests/test_mcuboot_tools.py b/tests/test_mcuboot_tools.py index 40f2162..0d1fecc 100644 --- a/tests/test_mcuboot_tools.py +++ b/tests/test_mcuboot_tools.py @@ -45,6 +45,7 @@ class SIGNED_HEX(_HELLO_WORLD_SIGNED_BASE): "46d0c082b77b48a70af315db284beaf4cedae49a51f1aa935df934a2e14a6762773c43c926809cf0bd83b2e944c06d2666617083cdc7afbd358070e207759a6100997602e63313c2d3dcd68f7d8c04ab381751f3d96e7908076fee25b157c9d5922ddd2007c1a2f9104d1196dc7d702ee64b27db710f043d80c3e371e84682c0de402b7e3447a34900c71da3ba3bc7681c7cd28273b6e6f7c99bd731bd289d1710e0fbeb4619556ab0e4f343b09c394993e745acc450ef58589148d9daf8a63214d66ad09186503dd07a9c110f6c5cad2f3075838806c42c78c431454c947186e09f969f9564f1ba30771dc9df76985b2dbc47a7fe2bd2c2436b8c890b8e0de8" # noqa ) + @pytest.mark.parametrize("image", [SIGNED_BIN, SIGNED_HEX]) def test_ImageInfo(image: _ImageFileFixture) -> None: image_info = ImageInfo.load_file(str(image.PATH)) @@ -230,10 +231,13 @@ def test_tlv_value_str_unknown() -> None: tlv_value = ImageTLVValue(header=tlv_header, value=b"\xde\xad\xbe\xef") assert str(tlv_value) == "0x99=deadbeef" + def test_protected_tlv_parsing() -> None: """Test that protected TLVs are parsed correctly when present.""" # tfm_s_signed.bin generated via https://docs.zephyrproject.org/latest/samples/tfm_integration/tfm_ipc/README.html#tfm_ipc - image_info = ImageInfo.load_file(str(Path("tests", "fixtures", "tf-m-9a4cb1a28", "tfm_s_signed.bin"))) + image_info = ImageInfo.load_file( + str(Path("tests", "fixtures", "tf-m-9a4cb1a28", "tfm_s_signed.bin")) + ) assert image_info.protected_tlv_info is not None assert len(image_info.protected_tlvs) == 3 @@ -248,5 +252,3 @@ def test_protected_tlv_parsing() -> None: image_info.get_tlv(IMAGE_TLV.SEC_CNT) image_info.get_tlv(IMAGE_TLV.BOOT_RECORD) image_info.get_tlv(IMAGE_TLV.DEPENDENCY) - - From ccf2053c2c1726f2d08caaa3851f89bbe8a07951 Mon Sep 17 00:00:00 2001 From: Tyson Jones Date: Thu, 11 Jun 2026 12:21:36 -0600 Subject: [PATCH 4/5] improved validation per copilot --- src/smpclient/mcuboot.py | 42 ++++++++++++++++++++++++---------------- 1 file changed, 25 insertions(+), 17 deletions(-) diff --git a/src/smpclient/mcuboot.py b/src/smpclient/mcuboot.py index a95aa54..16da649 100644 --- a/src/smpclient/mcuboot.py +++ b/src/smpclient/mcuboot.py @@ -237,22 +237,32 @@ class ImageTLVInfo: REGION_SIZE = IMAGE_TLV_INFO_STRUCT.size - def __post_init__(self) -> None: - """Do initial validation of the header.""" - if self.magic not in (IMAGE_TLV_INFO_MAGIC, IMAGE_TLV_PROT_INFO_MAGIC): + @staticmethod + def loads(data: bytes, protected=False) -> 'ImageTLVInfo': + """Load an `ImageTLVInfo` from bytes.""" + info = ImageTLVInfo(*IMAGE_TLV_INFO_STRUCT.unpack(data)) + + if protected and info.magic != IMAGE_TLV_PROT_INFO_MAGIC: raise MCUBootImageError( - f"TLV info magic is {hex(self.magic)}, expected {hex(IMAGE_TLV_INFO_MAGIC)} or {hex(IMAGE_TLV_PROT_INFO_MAGIC)}" + f"Expected protected TLV info magic {hex(IMAGE_TLV_PROT_INFO_MAGIC)}, got {hex(info.magic)}" ) - @staticmethod - def loads(data: bytes) -> 'ImageTLVInfo': - """Load an `ImageTLVInfo` from bytes.""" - return ImageTLVInfo(*IMAGE_TLV_INFO_STRUCT.unpack(data)) + if not protected and info.magic != IMAGE_TLV_INFO_MAGIC: + raise MCUBootImageError( + f"Expected TLV info magic {hex(IMAGE_TLV_INFO_MAGIC)}, got {hex(info.magic)}" + ) + + if info.tlv_tot < ImageTLVInfo.REGION_SIZE: + raise MCUBootImageError( + f"TLV total size must be at least {ImageTLVInfo.REGION_SIZE}, got {info.tlv_tot}" + ) + + return info @staticmethod - def load_from(file: BytesIO | BufferedReader) -> 'ImageTLVInfo': + def load_from(file: BytesIO | BufferedReader, protected=False) -> 'ImageTLVInfo': """Load an `ImageTLVInfo` from a file.""" - return ImageTLVInfo.loads(file.read(IMAGE_TLV_INFO_STRUCT.size)) + return ImageTLVInfo.loads(file.read(IMAGE_TLV_INFO_STRUCT.size), protected=protected) @dataclass(frozen=True) @@ -345,20 +355,18 @@ def load_file(path: str) -> 'ImageInfo': protected_tlvs: list[ImageTLVValue] = [] protected_tlv_info: ImageTLVInfo | None = None if image_header.protect_tlv_size > 0: - protected_tlv_info = ImageTLVInfo.load_from(f) - if protected_tlv_info.magic != IMAGE_TLV_PROT_INFO_MAGIC: + protected_tlv_info = ImageTLVInfo.load_from(f, protected=True) + + if protected_tlv_info.tlv_tot != image_header.protect_tlv_size: raise MCUBootImageError( - f"Protected TLV info magic is {hex(protected_tlv_info.magic)}, expected {hex(IMAGE_TLV_PROT_INFO_MAGIC)}" + f"Protected TLV info total size {protected_tlv_info.tlv_tot} does not match header value {image_header.protect_tlv_size}" ) + protected_tlvs = ImageInfo.parse_tlvs( f.read(protected_tlv_info.tlv_tot - ImageTLVInfo.REGION_SIZE) ) tlv_info = ImageTLVInfo.load_from(f) - if tlv_info.magic != IMAGE_TLV_INFO_MAGIC: - raise MCUBootImageError( - f"TLV info magic is {hex(tlv_info.magic)}, expected {hex(IMAGE_TLV_INFO_MAGIC)}" - ) tlvs = ImageInfo.parse_tlvs(f.read(tlv_info.tlv_tot - ImageTLVInfo.REGION_SIZE)) return ImageInfo( From cdb659a6c357c3e73bec4672a7495d2f6a36bf09 Mon Sep 17 00:00:00 2001 From: Tyson Jones Date: Thu, 11 Jun 2026 12:23:39 -0600 Subject: [PATCH 5/5] missing function parameter type annotation --- src/smpclient/mcuboot.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/smpclient/mcuboot.py b/src/smpclient/mcuboot.py index 16da649..1e9f20b 100644 --- a/src/smpclient/mcuboot.py +++ b/src/smpclient/mcuboot.py @@ -238,7 +238,7 @@ class ImageTLVInfo: REGION_SIZE = IMAGE_TLV_INFO_STRUCT.size @staticmethod - def loads(data: bytes, protected=False) -> 'ImageTLVInfo': + def loads(data: bytes, protected: bool = False) -> 'ImageTLVInfo': """Load an `ImageTLVInfo` from bytes.""" info = ImageTLVInfo(*IMAGE_TLV_INFO_STRUCT.unpack(data)) @@ -260,7 +260,7 @@ def loads(data: bytes, protected=False) -> 'ImageTLVInfo': return info @staticmethod - def load_from(file: BytesIO | BufferedReader, protected=False) -> 'ImageTLVInfo': + def load_from(file: BytesIO | BufferedReader, protected: bool = False) -> 'ImageTLVInfo': """Load an `ImageTLVInfo` from a file.""" return ImageTLVInfo.loads(file.read(IMAGE_TLV_INFO_STRUCT.size), protected=protected)