check the config's CRC32 checksum while reading
This commit is contained in:
parent
51445163a8
commit
39fa558741
@ -1,5 +1,6 @@
|
|||||||
"""Interact with the protobuf config from a picotool flash dump of a GP2040-CE board."""
|
"""Interact with the protobuf config from a picotool flash dump of a GP2040-CE board."""
|
||||||
import argparse
|
import argparse
|
||||||
|
import binascii
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from google.protobuf.json_format import MessageToJson
|
from google.protobuf.json_format import MessageToJson
|
||||||
@ -21,6 +22,10 @@ FOOTER_MAGIC = b'\x65\xe3\xf1\xd2'
|
|||||||
#################
|
#################
|
||||||
|
|
||||||
|
|
||||||
|
class ConfigCrcError(ValueError):
|
||||||
|
"""Exception raised when the CRC checksum in the footer doesn't match the actual content's."""
|
||||||
|
|
||||||
|
|
||||||
class ConfigLengthError(ValueError):
|
class ConfigLengthError(ValueError):
|
||||||
"""Exception raised when a length sanity check fails."""
|
"""Exception raised when a length sanity check fails."""
|
||||||
|
|
||||||
@ -52,7 +57,7 @@ def get_config_footer(content: bytes) -> tuple[int, int, str]:
|
|||||||
Args:
|
Args:
|
||||||
content: bytes from a GP2040-CE board's storage section
|
content: bytes from a GP2040-CE board's storage section
|
||||||
Returns:
|
Returns:
|
||||||
the discovered config size, config CRC, and magic from the config footer
|
the discovered config size, config CRC checksum, and magic from the config footer
|
||||||
Raises:
|
Raises:
|
||||||
ConfigLengthError, ConfigMagicError: if the provided bytes are not a config footer
|
ConfigLengthError, ConfigMagicError: if the provided bytes are not a config footer
|
||||||
"""
|
"""
|
||||||
@ -70,10 +75,15 @@ def get_config_footer(content: bytes) -> tuple[int, int, str]:
|
|||||||
config_crc = int.from_bytes(reversed(footer[4:8]), 'big')
|
config_crc = int.from_bytes(reversed(footer[4:8]), 'big')
|
||||||
config_magic = f'0x{footer[8:12].hex()}'
|
config_magic = f'0x{footer[8:12].hex()}'
|
||||||
|
|
||||||
# one last sanity check
|
# more sanity checks
|
||||||
if len(content) < config_size + FOOTER_SIZE:
|
if len(content) < config_size + FOOTER_SIZE:
|
||||||
raise ConfigLengthError("provided content is not large enough according to the config footer!")
|
raise ConfigLengthError("provided content is not large enough according to the config footer!")
|
||||||
|
|
||||||
|
content_crc = binascii.crc32(content[-(config_size + 12):-12])
|
||||||
|
if config_crc != content_crc:
|
||||||
|
raise ConfigCrcError(f"provided content CRC checksum {content_crc} does not match footer's expected CRC "
|
||||||
|
f"checksum {config_crc}!")
|
||||||
|
|
||||||
logger.debug("detected footer (size:%s, crc:%s, magic:%s", config_size, config_crc, config_magic)
|
logger.debug("detected footer (size:%s, crc:%s, magic:%s", config_size, config_crc, config_magic)
|
||||||
return config_size, config_crc, config_magic
|
return config_size, config_crc, config_magic
|
||||||
|
|
||||||
|
@ -56,6 +56,14 @@ def test_config_footer_bad_magic(storage_dump):
|
|||||||
_, _, _ = storage.get_config_footer(unmagical)
|
_, _, _ = storage.get_config_footer(unmagical)
|
||||||
|
|
||||||
|
|
||||||
|
def test_config_footer_bad_crc(storage_dump):
|
||||||
|
"""Test that a config footer isn't detected if the CRC checksums don't match."""
|
||||||
|
corrupt = bytearray(storage_dump)
|
||||||
|
corrupt[-50:-40] = bytearray(0*10)
|
||||||
|
with pytest.raises(storage.ConfigCrcError):
|
||||||
|
_, _, _ = storage.get_config_footer(corrupt)
|
||||||
|
|
||||||
|
|
||||||
def test_config_fails_without_pb2s(storage_dump):
|
def test_config_fails_without_pb2s(storage_dump):
|
||||||
"""Test that we need the config_pb2 to exist/be compiled for reading the config to work."""
|
"""Test that we need the config_pb2 to exist/be compiled for reading the config to work."""
|
||||||
with pytest.raises(ModuleNotFoundError):
|
with pytest.raises(ModuleNotFoundError):
|
||||||
|
Loading…
x
Reference in New Issue
Block a user