From 51a61fb41ce2bdc6240c9426eb4ada48f0ab42a8 Mon Sep 17 00:00:00 2001 From: Mahavir Jain Date: Thu, 9 Feb 2023 10:40:06 +0530 Subject: [PATCH 1/3] gen_esp32part: allow secure boot v2 based app partition size 4K aligned For Secure Boot v2 case, unsigned image is first padded to next 64K aligned boundary and then a signature block of 4K gets appended. Thus an app partition whose size is 4K aligned should be allowed here. For Secure Boot v1 case, app partition size must be 64K aligned as the signature block lies at the very end of 64K boundary. Relevant: 57b601ab7f6254e98b29d6f48124055b59f57d15 --- components/partition_table/CMakeLists.txt | 6 ++- components/partition_table/gen_esp32part.py | 41 +++++++++++++++------ 2 files changed, 35 insertions(+), 12 deletions(-) diff --git a/components/partition_table/CMakeLists.txt b/components/partition_table/CMakeLists.txt index 385d2a5d96..5431cddf74 100644 --- a/components/partition_table/CMakeLists.txt +++ b/components/partition_table/CMakeLists.txt @@ -25,7 +25,11 @@ if(CONFIG_ESPTOOLPY_FLASHSIZE) endif() if(CONFIG_SECURE_BOOT AND NOT CONFIG_SECURE_BOOT_ALLOW_SHORT_APP_PARTITION) - set(partition_secure_opt --secure) + if(CONFIG_SECURE_BOOT_V2_ENABLED) + set(partition_secure_opt --secure v2) + else() + set(partition_secure_opt --secure v1) + endif() else() set(partition_secure_opt "") endif() diff --git a/components/partition_table/gen_esp32part.py b/components/partition_table/gen_esp32part.py index ba6ba6c5da..8660c9d654 100755 --- a/components/partition_table/gen_esp32part.py +++ b/components/partition_table/gen_esp32part.py @@ -28,6 +28,10 @@ PARTITION_TABLE_SIZE = 0x1000 # Size of partition table MIN_PARTITION_SUBTYPE_APP_OTA = 0x10 NUM_PARTITION_SUBTYPE_APP_OTA = 16 +SECURE_NONE = None +SECURE_V1 = 'v1' +SECURE_V2 = 'v2' + __version__ = '1.2' APP_TYPE = 0x00 @@ -91,13 +95,26 @@ ALIGNMENT = { STRICT_DATA_ALIGNMENT = 0x1000 -def get_alignment_for_type(ptype): +def get_alignment_offset_for_type(ptype): return ALIGNMENT.get(ptype, ALIGNMENT[DATA_TYPE]) +def get_alignment_size_for_type(ptype): + if ptype == APP_TYPE and secure == SECURE_V1: + # For secure boot v1 case, app partition must be 64K aligned + # signature block (68 bytes) lies at the very end of 64K block + return 0x10000 + if ptype == APP_TYPE and secure == SECURE_V2: + # For secure boot v2 case, app partition must be 4K aligned + # signature block (4K) is kept after padding the unsigned image to 64K boundary + return 0x1000 + # No specific size alignement requirement as such + return 0x1 + + quiet = False md5sum = True -secure = False +secure = SECURE_NONE offset_part_table = 0 @@ -164,7 +181,7 @@ class PartitionTable(list): raise InputError('CSV Error: Partitions overlap. Partition at line %d sets offset 0x%x. Previous partition ends 0x%x' % (e.line_no, e.offset, last_end)) if e.offset is None: - pad_to = get_alignment_for_type(e.type) + pad_to = get_alignment_offset_for_type(e.type) if last_end % pad_to != 0: last_end += pad_to - (last_end % pad_to) e.offset = last_end @@ -397,18 +414,20 @@ class PartitionDefinition(object): raise ValidationError(self, 'Subtype field is not set') if self.offset is None: raise ValidationError(self, 'Offset field is not set') - align = get_alignment_for_type(self.type) - if self.offset % align: - raise ValidationError(self, 'Offset 0x%x is not aligned to 0x%x' % (self.offset, align)) + if self.size is None: + raise ValidationError(self, 'Size field is not set') + offset_align = get_alignment_offset_for_type(self.type) + if self.offset % offset_align: + raise ValidationError(self, 'Offset 0x%x is not aligned to 0x%x' % (self.offset, offset_align)) # The alignment requirement for non-app partition is 4 bytes, but it should be 4 kB. # Print a warning for now, make it an error in IDF 5.0 (IDF-3742). if self.type != APP_TYPE and self.offset % STRICT_DATA_ALIGNMENT: critical('WARNING: Partition %s not aligned to 0x%x.' 'This is deprecated and will be considered an error in the future release.' % (self.name, STRICT_DATA_ALIGNMENT)) - if self.size % align and secure and self.type == APP_TYPE: - raise ValidationError(self, 'Size 0x%x is not aligned to 0x%x' % (self.size, align)) - if self.size is None: - raise ValidationError(self, 'Size field is not set') + if self.type == APP_TYPE and secure is not SECURE_NONE: + size_align = get_alignment_size_for_type(self.type) + if self.size % size_align: + raise ValidationError(self, 'Size 0x%x is not aligned to 0x%x' % (self.size, size_align)) if self.name in TYPES and TYPES.get(self.name, '') != self.type: critical("WARNING: Partition has name '%s' which is a partition type, but does not match this partition's " @@ -513,7 +532,7 @@ def main(): 'enabled by default and this flag does nothing.', action='store_true') parser.add_argument('--quiet', '-q', help="Don't print non-critical status messages to stderr", action='store_true') parser.add_argument('--offset', '-o', help='Set offset partition table', default='0x8000') - parser.add_argument('--secure', help='Require app partitions to be suitable for secure boot', action='store_true') + parser.add_argument('--secure', help='Require app partitions to be suitable for secure boot', nargs='?', const=SECURE_V1, choices=[SECURE_V1, SECURE_V2]) parser.add_argument('input', help='Path to CSV or binary file to parse.', type=argparse.FileType('rb')) parser.add_argument('output', help='Path to output converted binary or CSV file. Will use stdout if omitted.', nargs='?', default='-') From 5002ccd9c36b33d17e704a5e89cb140a0bc45bc9 Mon Sep 17 00:00:00 2001 From: Mahavir Jain Date: Mon, 6 Feb 2023 09:06:32 +0530 Subject: [PATCH 2/3] partition_table: add tests for checking secure boot part size --- .../gen_esp32part_tests.py | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/components/partition_table/test_gen_esp32part_host/gen_esp32part_tests.py b/components/partition_table/test_gen_esp32part_host/gen_esp32part_tests.py index 7ba1878151..47ea9f4a67 100755 --- a/components/partition_table/test_gen_esp32part_host/gen_esp32part_tests.py +++ b/components/partition_table/test_gen_esp32part_host/gen_esp32part_tests.py @@ -389,6 +389,38 @@ class CommandLineTests(Py23TestCase): class VerificationTests(Py23TestCase): + def _run_genesp32(self, csvcontents, args): + csvpath = tempfile.mktemp() + with open(csvpath, 'w') as f: + f.write(csvcontents) + try: + output = subprocess.check_output([sys.executable, '../gen_esp32part.py', csvpath] + args, stderr=subprocess.STDOUT) + return output.strip() + except subprocess.CalledProcessError as e: + return e.output.strip() + finally: + os.remove(csvpath) + + def test_check_secure_app_size(self): + sample_csv = """ +ota_0, app, ota_0, , 0x101000 +ota_1, app, ota_1, , 0x100800 + """ + + def rge(args): + return self._run_genesp32(sample_csv, args) + + # Valid test that would pass with the above partition table + partfile = tempfile.mktemp() + self.assertEqual(rge([partfile]), b'Parsing CSV input...\nVerifying table...') + os.remove(partfile) + # Failure case 1, incorrect ota_0 partition size + self.assertEqual(rge(['-q', '--secure', 'v1']), + b'Partition ota_0 invalid: Size 0x101000 is not aligned to 0x10000') + # Failure case 2, incorrect ota_1 partition size + self.assertEqual(rge(['-q', '--secure', 'v2']), + b'Partition ota_1 invalid: Size 0x100800 is not aligned to 0x1000') + def test_bad_alignment(self): csv = """ # Name,Type, SubType,Offset,Size From 379d9034ebd13d3395ae55d63a4fbf548fc7ebd6 Mon Sep 17 00:00:00 2001 From: Mahavir Jain Date: Sun, 12 Feb 2023 21:29:39 +0530 Subject: [PATCH 3/3] partition_table: fix make build for new "--secure [v1/v2]" argument --- components/partition_table/Makefile.projbuild | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/components/partition_table/Makefile.projbuild b/components/partition_table/Makefile.projbuild index 7b85adaa0f..3241052f53 100644 --- a/components/partition_table/Makefile.projbuild +++ b/components/partition_table/Makefile.projbuild @@ -21,7 +21,11 @@ endif PARTITION_SECURE_OPT := ifdef CONFIG_SECURE_BOOT ifndef CONFIG_SECURE_BOOT_ALLOW_SHORT_APP_PARTITION -PARTITION_SECURE_OPT += --secure +ifdef CONFIG_SECURE_BOOT_V2_ENABLED +PARTITION_SECURE_OPT += --secure v2 +else +PARTITION_SECURE_OPT += --secure v1 +endif endif endif